00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "config.h"
00026 #include "system.h"
00027 #include "tree.h"
00028 #include "rtl.h"
00029 #include "regs.h"
00030 #include "hard-reg-set.h"
00031 #include "real.h"
00032 #include "insn-config.h"
00033 #include "conditions.h"
00034 #include "output.h"
00035 #include "insn-attr.h"
00036 #include "flags.h"
00037 #include "function.h"
00038 #include "expr.h"
00039 #include "optabs.h"
00040 #include "libfuncs.h"
00041 #include "recog.h"
00042 #include "toplev.h"
00043 #include "ggc.h"
00044 #include "tm_p.h"
00045 #include "debug.h"
00046 #include "target.h"
00047 #include "target-def.h"
00048
00049
00050
00051
00052
00053
00054 #define SKIP_CALLERS_UNIMP_P \
00055 (!TARGET_ARCH64 && current_function_returns_struct \
00056 && ! integer_zerop (DECL_SIZE (DECL_RESULT (current_function_decl))) \
00057 && (TREE_CODE (DECL_SIZE (DECL_RESULT (current_function_decl))) \
00058 == INTEGER_CST))
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 static int apparent_fsize;
00069 static int actual_fsize;
00070
00071
00072
00073 static int num_gfregs;
00074
00075
00076
00077 rtx sparc_compare_op0, sparc_compare_op1;
00078
00079
00080
00081 bool sparc_emitting_epilogue;
00082
00083 #ifdef LEAF_REGISTERS
00084
00085
00086
00087
00088 char leaf_reg_remap[] =
00089 { 0, 1, 2, 3, 4, 5, 6, 7,
00090 -1, -1, -1, -1, -1, -1, 14, -1,
00091 -1, -1, -1, -1, -1, -1, -1, -1,
00092 8, 9, 10, 11, 12, 13, -1, 15,
00093
00094 32, 33, 34, 35, 36, 37, 38, 39,
00095 40, 41, 42, 43, 44, 45, 46, 47,
00096 48, 49, 50, 51, 52, 53, 54, 55,
00097 56, 57, 58, 59, 60, 61, 62, 63,
00098 64, 65, 66, 67, 68, 69, 70, 71,
00099 72, 73, 74, 75, 76, 77, 78, 79,
00100 80, 81, 82, 83, 84, 85, 86, 87,
00101 88, 89, 90, 91, 92, 93, 94, 95,
00102 96, 97, 98, 99, 100};
00103
00104
00105
00106
00107 char sparc_leaf_regs[] =
00108 { 1, 1, 1, 1, 1, 1, 1, 1,
00109 0, 0, 0, 0, 0, 0, 1, 0,
00110 0, 0, 0, 0, 0, 0, 0, 0,
00111 1, 1, 1, 1, 1, 1, 0, 1,
00112 1, 1, 1, 1, 1, 1, 1, 1,
00113 1, 1, 1, 1, 1, 1, 1, 1,
00114 1, 1, 1, 1, 1, 1, 1, 1,
00115 1, 1, 1, 1, 1, 1, 1, 1,
00116 1, 1, 1, 1, 1, 1, 1, 1,
00117 1, 1, 1, 1, 1, 1, 1, 1,
00118 1, 1, 1, 1, 1, 1, 1, 1,
00119 1, 1, 1, 1, 1, 1, 1, 1,
00120 1, 1, 1, 1, 1};
00121
00122 #endif
00123
00124
00125
00126
00127
00128
00129 static const char *frame_base_name;
00130 static int frame_base_offset;
00131
00132 static void sparc_init_modes PARAMS ((void));
00133 static int save_regs PARAMS ((FILE *, int, int, const char *,
00134 int, int, int));
00135 static int restore_regs PARAMS ((FILE *, int, int, const char *, int, int));
00136 static void build_big_number PARAMS ((FILE *, int, const char *));
00137 static int function_arg_slotno PARAMS ((const CUMULATIVE_ARGS *,
00138 enum machine_mode, tree, int, int,
00139 int *, int *));
00140
00141 static int supersparc_adjust_cost PARAMS ((rtx, rtx, rtx, int));
00142 static int hypersparc_adjust_cost PARAMS ((rtx, rtx, rtx, int));
00143 static int ultrasparc_adjust_cost PARAMS ((rtx, rtx, rtx, int));
00144
00145 static void sparc_output_addr_vec PARAMS ((rtx));
00146 static void sparc_output_addr_diff_vec PARAMS ((rtx));
00147 static void sparc_output_deferred_case_vectors PARAMS ((void));
00148 static void sparc_add_gc_roots PARAMS ((void));
00149 static void mark_ultrasparc_pipeline_state PARAMS ((void *));
00150 static int check_return_regs PARAMS ((rtx));
00151 static int epilogue_renumber PARAMS ((rtx *, int));
00152 static bool sparc_assemble_integer PARAMS ((rtx, unsigned int, int));
00153 static int ultra_cmove_results_ready_p PARAMS ((rtx));
00154 static int ultra_fpmode_conflict_exists PARAMS ((enum machine_mode));
00155 static rtx *ultra_find_type PARAMS ((int, rtx *, int));
00156 static void ultra_build_types_avail PARAMS ((rtx *, int));
00157 static void ultra_flush_pipeline PARAMS ((void));
00158 static void ultra_rescan_pipeline_state PARAMS ((rtx *, int));
00159 static int set_extends PARAMS ((rtx));
00160 static void output_restore_regs PARAMS ((FILE *, int));
00161 static void sparc_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
00162 static void sparc_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
00163 static void sparc_flat_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
00164 static void sparc_flat_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
00165 static void sparc_nonflat_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT,
00166 int));
00167 static void sparc_nonflat_function_prologue PARAMS ((FILE *, HOST_WIDE_INT,
00168 int));
00169 #ifdef OBJECT_FORMAT_ELF
00170 static void sparc_elf_asm_named_section PARAMS ((const char *, unsigned int));
00171 #endif
00172 static void ultrasparc_sched_reorder PARAMS ((FILE *, int, rtx *, int));
00173 static int ultrasparc_variable_issue PARAMS ((rtx));
00174 static void ultrasparc_sched_init PARAMS ((void));
00175
00176 static int sparc_adjust_cost PARAMS ((rtx, rtx, rtx, int));
00177 static int sparc_issue_rate PARAMS ((void));
00178 static int sparc_variable_issue PARAMS ((FILE *, int, rtx, int));
00179 static void sparc_sched_init PARAMS ((FILE *, int, int));
00180 static int sparc_sched_reorder PARAMS ((FILE *, int, rtx *, int *, int));
00181
00182 static void emit_soft_tfmode_libcall PARAMS ((const char *, int, rtx *));
00183 static void emit_soft_tfmode_binop PARAMS ((enum rtx_code, rtx *));
00184 static void emit_soft_tfmode_unop PARAMS ((enum rtx_code, rtx *));
00185 static void emit_soft_tfmode_cvt PARAMS ((enum rtx_code, rtx *));
00186 static void emit_hard_tfmode_operation PARAMS ((enum rtx_code, rtx *));
00187
00188
00189
00190
00191 const char *sparc_cmodel_string;
00192
00193 enum cmodel sparc_cmodel;
00194
00195 char sparc_hard_reg_printed[8];
00196
00197 struct sparc_cpu_select sparc_select[] =
00198 {
00199
00200 { (char *)0, "default", 1, 1 },
00201 { (char *)0, "-mcpu=", 1, 1 },
00202 { (char *)0, "-mtune=", 1, 0 },
00203 { 0, 0, 0, 0 }
00204 };
00205
00206
00207 enum processor_type sparc_cpu;
00208
00209
00210
00211
00212
00213 #undef TARGET_ASM_ALIGNED_HI_OP
00214 #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
00215 #ifndef OBJECT_FORMAT_ELF
00216 #undef TARGET_ASM_ALIGNED_SI_OP
00217 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
00218 #endif
00219
00220 #undef TARGET_ASM_UNALIGNED_HI_OP
00221 #define TARGET_ASM_UNALIGNED_HI_OP "\t.uahalf\t"
00222 #undef TARGET_ASM_UNALIGNED_SI_OP
00223 #define TARGET_ASM_UNALIGNED_SI_OP "\t.uaword\t"
00224 #undef TARGET_ASM_UNALIGNED_DI_OP
00225 #define TARGET_ASM_UNALIGNED_DI_OP "\t.uaxword\t"
00226
00227
00228 #undef TARGET_ASM_INTEGER
00229 #define TARGET_ASM_INTEGER sparc_assemble_integer
00230
00231 #undef TARGET_ASM_FUNCTION_PROLOGUE
00232 #define TARGET_ASM_FUNCTION_PROLOGUE sparc_output_function_prologue
00233 #undef TARGET_ASM_FUNCTION_EPILOGUE
00234 #define TARGET_ASM_FUNCTION_EPILOGUE sparc_output_function_epilogue
00235
00236 #undef TARGET_SCHED_ADJUST_COST
00237 #define TARGET_SCHED_ADJUST_COST sparc_adjust_cost
00238 #undef TARGET_SCHED_ISSUE_RATE
00239 #define TARGET_SCHED_ISSUE_RATE sparc_issue_rate
00240 #undef TARGET_SCHED_VARIABLE_ISSUE
00241 #define TARGET_SCHED_VARIABLE_ISSUE sparc_variable_issue
00242 #undef TARGET_SCHED_INIT
00243 #define TARGET_SCHED_INIT sparc_sched_init
00244 #undef TARGET_SCHED_REORDER
00245 #define TARGET_SCHED_REORDER sparc_sched_reorder
00246
00247 struct gcc_target targetm = TARGET_INITIALIZER;
00248
00249
00250
00251
00252 void
00253 sparc_override_options ()
00254 {
00255 static struct code_model {
00256 const char *const name;
00257 const int value;
00258 } const cmodels[] = {
00259 { "32", CM_32 },
00260 { "medlow", CM_MEDLOW },
00261 { "medmid", CM_MEDMID },
00262 { "medany", CM_MEDANY },
00263 { "embmedany", CM_EMBMEDANY },
00264 { 0, 0 }
00265 };
00266 const struct code_model *cmodel;
00267
00268 static struct cpu_default {
00269 const int cpu;
00270 const char *const name;
00271 } const cpu_default[] = {
00272
00273 { TARGET_CPU_sparc, "cypress" },
00274 { TARGET_CPU_sparclet, "tsc701" },
00275 { TARGET_CPU_sparclite, "f930" },
00276 { TARGET_CPU_v8, "v8" },
00277 { TARGET_CPU_hypersparc, "hypersparc" },
00278 { TARGET_CPU_sparclite86x, "sparclite86x" },
00279 { TARGET_CPU_supersparc, "supersparc" },
00280 { TARGET_CPU_v9, "v9" },
00281 { TARGET_CPU_ultrasparc, "ultrasparc" },
00282 { 0, 0 }
00283 };
00284 const struct cpu_default *def;
00285
00286 static struct cpu_table {
00287 const char *const name;
00288 const enum processor_type processor;
00289 const int disable;
00290 const int enable;
00291 } const cpu_table[] = {
00292 { "v7", PROCESSOR_V7, MASK_ISA, 0 },
00293 { "cypress", PROCESSOR_CYPRESS, MASK_ISA, 0 },
00294 { "v8", PROCESSOR_V8, MASK_ISA, MASK_V8 },
00295
00296 { "supersparc", PROCESSOR_SUPERSPARC, MASK_ISA, MASK_V8 },
00297 { "sparclite", PROCESSOR_SPARCLITE, MASK_ISA, MASK_SPARCLITE },
00298
00299
00300 { "f930", PROCESSOR_F930, MASK_ISA|MASK_FPU, MASK_SPARCLITE },
00301 { "f934", PROCESSOR_F934, MASK_ISA, MASK_SPARCLITE|MASK_FPU },
00302 { "hypersparc", PROCESSOR_HYPERSPARC, MASK_ISA, MASK_V8|MASK_FPU },
00303 { "sparclite86x", PROCESSOR_SPARCLITE86X, MASK_ISA|MASK_FPU,
00304 MASK_SPARCLITE },
00305 { "sparclet", PROCESSOR_SPARCLET, MASK_ISA, MASK_SPARCLET },
00306
00307 { "tsc701", PROCESSOR_TSC701, MASK_ISA, MASK_SPARCLET },
00308 { "v9", PROCESSOR_V9, MASK_ISA, MASK_V9 },
00309
00310 { "ultrasparc", PROCESSOR_ULTRASPARC, MASK_ISA, MASK_V9
00311
00312
00313 |MASK_DEPRECATED_V8_INSNS},
00314 { 0, 0, 0, 0 }
00315 };
00316 const struct cpu_table *cpu;
00317 const struct sparc_cpu_select *sel;
00318 int fpu;
00319
00320 #ifndef SPARC_BI_ARCH
00321
00322 if (! TARGET_64BIT != DEFAULT_ARCH32_P)
00323 error ("%s is not supported by this configuration",
00324 DEFAULT_ARCH32_P ? "-m64" : "-m32");
00325 #endif
00326
00327
00328 if (TARGET_64BIT && ! TARGET_LONG_DOUBLE_128)
00329 {
00330 error ("-mlong-double-64 not allowed with -m64");
00331 target_flags |= MASK_LONG_DOUBLE_128;
00332 }
00333
00334
00335 sparc_cmodel = SPARC_DEFAULT_CMODEL;
00336
00337 #ifdef SPARC_BI_ARCH
00338 if (TARGET_ARCH32)
00339 sparc_cmodel = CM_32;
00340 #endif
00341
00342 if (sparc_cmodel_string != NULL)
00343 {
00344 if (TARGET_ARCH64)
00345 {
00346 for (cmodel = &cmodels[0]; cmodel->name; cmodel++)
00347 if (strcmp (sparc_cmodel_string, cmodel->name) == 0)
00348 break;
00349 if (cmodel->name == NULL)
00350 error ("bad value (%s) for -mcmodel= switch", sparc_cmodel_string);
00351 else
00352 sparc_cmodel = cmodel->value;
00353 }
00354 else
00355 error ("-mcmodel= is not supported on 32 bit systems");
00356 }
00357
00358 fpu = TARGET_FPU;
00359
00360
00361 for (def = &cpu_default[0]; def->name; ++def)
00362 if (def->cpu == TARGET_CPU_DEFAULT)
00363 break;
00364 if (! def->name)
00365 abort ();
00366 sparc_select[0].string = def->name;
00367
00368 for (sel = &sparc_select[0]; sel->name; ++sel)
00369 {
00370 if (sel->string)
00371 {
00372 for (cpu = &cpu_table[0]; cpu->name; ++cpu)
00373 if (! strcmp (sel->string, cpu->name))
00374 {
00375 if (sel->set_tune_p)
00376 sparc_cpu = cpu->processor;
00377
00378 if (sel->set_arch_p)
00379 {
00380 target_flags &= ~cpu->disable;
00381 target_flags |= cpu->enable;
00382 }
00383 break;
00384 }
00385
00386 if (! cpu->name)
00387 error ("bad value (%s) for %s switch", sel->string, sel->name);
00388 }
00389 }
00390
00391
00392
00393
00394 if (TARGET_FPU_SET)
00395 {
00396 target_flags = (target_flags & ~MASK_FPU) | fpu;
00397 target_flags &= ~MASK_FPU_SET;
00398 }
00399
00400
00401 if (! TARGET_FPU)
00402 target_flags &= ~MASK_VIS;
00403
00404
00405
00406
00407 if (TARGET_VIS || TARGET_ARCH64)
00408 {
00409 target_flags |= MASK_V9;
00410 target_flags &= ~(MASK_V8 | MASK_SPARCLET | MASK_SPARCLITE);
00411 }
00412
00413
00414 if (TARGET_V9 && TARGET_ARCH32)
00415 target_flags |= MASK_DEPRECATED_V8_INSNS;
00416
00417
00418 if (! TARGET_V9 || TARGET_ARCH64)
00419 target_flags &= ~MASK_V8PLUS;
00420
00421
00422 if (TARGET_ARCH32)
00423 target_flags &= ~MASK_STACK_BIAS;
00424
00425
00426 if (align_functions == 0 && sparc_cpu == PROCESSOR_ULTRASPARC)
00427 align_functions = 32;
00428
00429
00430 if (flag_pcc_struct_return == DEFAULT_PCC_STRUCT_RETURN)
00431 flag_pcc_struct_return = (TARGET_ARCH64 ? 0 : 1);
00432
00433
00434 if (!TARGET_ARCH64)
00435 targetm.asm_out.unaligned_op.di = NULL;
00436
00437
00438 sparc_init_modes ();
00439
00440
00441 sparc_add_gc_roots ();
00442 }
00443
00444
00445
00446
00447
00448
00449 int
00450 v9_regcmp_p (code)
00451 enum rtx_code code;
00452 {
00453 return (code == EQ || code == NE || code == GE || code == LT
00454 || code == LE || code == GT);
00455 }
00456
00457
00458
00459
00460
00461
00462
00463 int
00464 reg_or_0_operand (op, mode)
00465 rtx op;
00466 enum machine_mode mode;
00467 {
00468 if (register_operand (op, mode))
00469 return 1;
00470 if (op == const0_rtx)
00471 return 1;
00472 if (GET_MODE (op) == VOIDmode && GET_CODE (op) == CONST_DOUBLE
00473 && CONST_DOUBLE_HIGH (op) == 0
00474 && CONST_DOUBLE_LOW (op) == 0)
00475 return 1;
00476 if (fp_zero_operand (op, mode))
00477 return 1;
00478 return 0;
00479 }
00480
00481
00482
00483 int
00484 fp_zero_operand (op, mode)
00485 rtx op;
00486 enum machine_mode mode;
00487 {
00488 if (GET_MODE_CLASS (GET_MODE (op)) != MODE_FLOAT)
00489 return 0;
00490 return op == CONST0_RTX (mode);
00491 }
00492
00493
00494
00495 int
00496 fp_register_operand (op, mode)
00497 rtx op;
00498 enum machine_mode mode;
00499 {
00500 if (! register_operand (op, mode))
00501 return 0;
00502 if (GET_CODE (op) == SUBREG)
00503 op = SUBREG_REG (op);
00504 return GET_CODE (op) == REG && SPARC_FP_REG_P (REGNO (op));
00505 }
00506
00507
00508
00509
00510
00511 int
00512 fp_sethi_p (op)
00513 rtx op;
00514 {
00515 if (GET_CODE (op) == CONST_DOUBLE)
00516 {
00517 REAL_VALUE_TYPE r;
00518 long i;
00519
00520 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
00521 if (REAL_VALUES_EQUAL (r, dconst0) &&
00522 ! REAL_VALUE_MINUS_ZERO (r))
00523 return 0;
00524 REAL_VALUE_TO_TARGET_SINGLE (r, i);
00525 if (SPARC_SETHI_P (i))
00526 return 1;
00527 }
00528
00529 return 0;
00530 }
00531
00532
00533
00534
00535
00536 int
00537 fp_mov_p (op)
00538 rtx op;
00539 {
00540 if (GET_CODE (op) == CONST_DOUBLE)
00541 {
00542 REAL_VALUE_TYPE r;
00543 long i;
00544
00545 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
00546 if (REAL_VALUES_EQUAL (r, dconst0) &&
00547 ! REAL_VALUE_MINUS_ZERO (r))
00548 return 0;
00549 REAL_VALUE_TO_TARGET_SINGLE (r, i);
00550 if (SPARC_SIMM13_P (i))
00551 return 1;
00552 }
00553
00554 return 0;
00555 }
00556
00557
00558
00559
00560
00561 int
00562 fp_high_losum_p (op)
00563 rtx op;
00564 {
00565
00566
00567
00568 if (GET_CODE (op) == CONST_DOUBLE)
00569 {
00570 REAL_VALUE_TYPE r;
00571 long i;
00572
00573 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
00574 if (REAL_VALUES_EQUAL (r, dconst0) &&
00575 ! REAL_VALUE_MINUS_ZERO (r))
00576 return 0;
00577 REAL_VALUE_TO_TARGET_SINGLE (r, i);
00578 if (! SPARC_SETHI_P (i)
00579 && ! SPARC_SIMM13_P (i))
00580 return 1;
00581 }
00582
00583 return 0;
00584 }
00585
00586
00587
00588 int
00589 intreg_operand (op, mode)
00590 rtx op;
00591 enum machine_mode mode ATTRIBUTE_UNUSED;
00592 {
00593 return (register_operand (op, SImode)
00594 || (TARGET_ARCH64 && register_operand (op, DImode)));
00595 }
00596
00597
00598
00599 int
00600 fcc_reg_operand (op, mode)
00601 rtx op;
00602 enum machine_mode mode;
00603 {
00604
00605
00606 if (GET_CODE (op) != REG)
00607 return 0;
00608
00609 if (mode != VOIDmode && mode != GET_MODE (op))
00610 return 0;
00611 if (mode == VOIDmode
00612 && (GET_MODE (op) != CCFPmode && GET_MODE (op) != CCFPEmode))
00613 return 0;
00614
00615 #if 0
00616 if (reg_renumber == 0)
00617 return REGNO (op) >= FIRST_PSEUDO_REGISTER;
00618 return REGNO_OK_FOR_CCFP_P (REGNO (op));
00619 #else
00620 return (unsigned) REGNO (op) - SPARC_FIRST_V9_FCC_REG < 4;
00621 #endif
00622 }
00623
00624
00625
00626 int
00627 fcc0_reg_operand (op, mode)
00628 rtx op;
00629 enum machine_mode mode;
00630 {
00631
00632
00633 if (GET_CODE (op) != REG)
00634 return 0;
00635
00636 if (mode != VOIDmode && mode != GET_MODE (op))
00637 return 0;
00638 if (mode == VOIDmode
00639 && (GET_MODE (op) != CCFPmode && GET_MODE (op) != CCFPEmode))
00640 return 0;
00641
00642 return REGNO (op) == SPARC_FCC_REG;
00643 }
00644
00645
00646
00647 int
00648 icc_or_fcc_reg_operand (op, mode)
00649 rtx op;
00650 enum machine_mode mode;
00651 {
00652 if (GET_CODE (op) == REG && REGNO (op) == SPARC_ICC_REG)
00653 {
00654 if (mode != VOIDmode && mode != GET_MODE (op))
00655 return 0;
00656 if (mode == VOIDmode
00657 && GET_MODE (op) != CCmode && GET_MODE (op) != CCXmode)
00658 return 0;
00659 return 1;
00660 }
00661
00662 return fcc_reg_operand (op, mode);
00663 }
00664
00665
00666 int
00667 restore_operand (op, mode)
00668 rtx op;
00669 enum machine_mode mode;
00670 {
00671 return (GET_CODE (op) == REG && GET_MODE (op) == mode
00672 && (REGNO (op) < 8 || (REGNO (op) >= 24 && REGNO (op) < 32)));
00673 }
00674
00675
00676
00677
00678 int
00679 call_operand (op, mode)
00680 rtx op;
00681 enum machine_mode mode;
00682 {
00683 if (GET_CODE (op) != MEM)
00684 abort ();
00685 op = XEXP (op, 0);
00686 return (symbolic_operand (op, mode) || memory_address_p (Pmode, op));
00687 }
00688
00689 int
00690 call_operand_address (op, mode)
00691 rtx op;
00692 enum machine_mode mode;
00693 {
00694 return (symbolic_operand (op, mode) || memory_address_p (Pmode, op));
00695 }
00696
00697
00698
00699
00700 int
00701 symbolic_operand (op, mode)
00702 register rtx op;
00703 enum machine_mode mode;
00704 {
00705 enum machine_mode omode = GET_MODE (op);
00706
00707 if (omode != mode && omode != VOIDmode && mode != VOIDmode)
00708 return 0;
00709
00710 switch (GET_CODE (op))
00711 {
00712 case SYMBOL_REF:
00713 case LABEL_REF:
00714 return 1;
00715
00716 case CONST:
00717 op = XEXP (op, 0);
00718 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
00719 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
00720 && GET_CODE (XEXP (op, 1)) == CONST_INT);
00721
00722 default:
00723 return 0;
00724 }
00725 }
00726
00727
00728
00729
00730 int
00731 symbolic_memory_operand (op, mode)
00732 rtx op;
00733 enum machine_mode mode ATTRIBUTE_UNUSED;
00734 {
00735 if (GET_CODE (op) == SUBREG)
00736 op = SUBREG_REG (op);
00737 if (GET_CODE (op) != MEM)
00738 return 0;
00739 op = XEXP (op, 0);
00740 return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST
00741 || GET_CODE (op) == HIGH || GET_CODE (op) == LABEL_REF);
00742 }
00743
00744
00745
00746 int
00747 label_ref_operand (op, mode)
00748 rtx op;
00749 enum machine_mode mode;
00750 {
00751 if (GET_CODE (op) != LABEL_REF)
00752 return 0;
00753 if (GET_MODE (op) != mode)
00754 return 0;
00755 return 1;
00756 }
00757
00758
00759
00760
00761 int
00762 sp64_medium_pic_operand (op, mode)
00763 rtx op;
00764 enum machine_mode mode ATTRIBUTE_UNUSED;
00765 {
00766
00767
00768 if (GET_CODE (op) != CONST)
00769 return 0;
00770 op = XEXP (op, 0);
00771 if (GET_CODE (op) != MINUS)
00772 return 0;
00773 if (GET_CODE (XEXP (op, 0)) != SYMBOL_REF)
00774 return 0;
00775
00776 if (GET_CODE (XEXP (op, 1)) != CONST)
00777 return 0;
00778 if (GET_CODE (XEXP (XEXP (op, 1), 0)) != MINUS)
00779 return 0;
00780 return 1;
00781 }
00782
00783
00784
00785
00786
00787
00788 int
00789 data_segment_operand (op, mode)
00790 rtx op;
00791 enum machine_mode mode ATTRIBUTE_UNUSED;
00792 {
00793 switch (GET_CODE (op))
00794 {
00795 case SYMBOL_REF :
00796 return ! SYMBOL_REF_FLAG (op);
00797 case PLUS :
00798
00799
00800 case CONST :
00801 return data_segment_operand (XEXP (op, 0), VOIDmode);
00802 default :
00803 return 0;
00804 }
00805 }
00806
00807
00808
00809
00810 int
00811 text_segment_operand (op, mode)
00812 rtx op;
00813 enum machine_mode mode ATTRIBUTE_UNUSED;
00814 {
00815 switch (GET_CODE (op))
00816 {
00817 case LABEL_REF :
00818 return 1;
00819 case SYMBOL_REF :
00820 return SYMBOL_REF_FLAG (op);
00821 case PLUS :
00822
00823
00824 case CONST :
00825 return text_segment_operand (XEXP (op, 0), VOIDmode);
00826 default :
00827 return 0;
00828 }
00829 }
00830
00831
00832
00833
00834 int
00835 reg_or_nonsymb_mem_operand (op, mode)
00836 register rtx op;
00837 enum machine_mode mode;
00838 {
00839 if (register_operand (op, mode))
00840 return 1;
00841
00842 if (memory_operand (op, mode) && ! symbolic_memory_operand (op, mode))
00843 return 1;
00844
00845 return 0;
00846 }
00847
00848 int
00849 splittable_symbolic_memory_operand (op, mode)
00850 rtx op;
00851 enum machine_mode mode ATTRIBUTE_UNUSED;
00852 {
00853 if (GET_CODE (op) != MEM)
00854 return 0;
00855 if (! symbolic_operand (XEXP (op, 0), Pmode))
00856 return 0;
00857 return 1;
00858 }
00859
00860 int
00861 splittable_immediate_memory_operand (op, mode)
00862 rtx op;
00863 enum machine_mode mode ATTRIBUTE_UNUSED;
00864 {
00865 if (GET_CODE (op) != MEM)
00866 return 0;
00867 if (! immediate_operand (XEXP (op, 0), Pmode))
00868 return 0;
00869 return 1;
00870 }
00871
00872
00873
00874 int
00875 eq_or_neq (op, mode)
00876 rtx op;
00877 enum machine_mode mode ATTRIBUTE_UNUSED;
00878 {
00879 return (GET_CODE (op) == EQ || GET_CODE (op) == NE);
00880 }
00881
00882
00883
00884
00885 int
00886 normal_comp_operator (op, mode)
00887 rtx op;
00888 enum machine_mode mode ATTRIBUTE_UNUSED;
00889 {
00890 enum rtx_code code = GET_CODE (op);
00891
00892 if (GET_RTX_CLASS (code) != '<')
00893 return 0;
00894
00895 if (GET_MODE (XEXP (op, 0)) == CCFPmode
00896 || GET_MODE (XEXP (op, 0)) == CCFPEmode)
00897 return 1;
00898
00899 return (code != NE && code != EQ && code != GEU && code != LTU);
00900 }
00901
00902
00903
00904
00905 int
00906 noov_compare_op (op, mode)
00907 register rtx op;
00908 enum machine_mode mode ATTRIBUTE_UNUSED;
00909 {
00910 enum rtx_code code = GET_CODE (op);
00911
00912 if (GET_RTX_CLASS (code) != '<')
00913 return 0;
00914
00915 if (GET_MODE (XEXP (op, 0)) == CC_NOOVmode
00916 || GET_MODE (XEXP (op, 0)) == CCX_NOOVmode)
00917
00918 return (code == EQ || code == NE || code == GE || code == LT);
00919 return 1;
00920 }
00921
00922
00923
00924
00925 int
00926 noov_compare64_op (op, mode)
00927 register rtx op;
00928 enum machine_mode mode ATTRIBUTE_UNUSED;
00929 {
00930 enum rtx_code code = GET_CODE (op);
00931
00932 if (! TARGET_V9)
00933 return 0;
00934
00935 if (GET_RTX_CLASS (code) != '<')
00936 return 0;
00937
00938 if (GET_MODE (XEXP (op, 0)) == CCX_NOOVmode)
00939
00940 return (code == EQ || code == NE || code == GE || code == LT);
00941 return (GET_MODE (XEXP (op, 0)) == CCXmode);
00942 }
00943
00944
00945
00946
00947 int
00948 v9_regcmp_op (op, mode)
00949 register rtx op;
00950 enum machine_mode mode ATTRIBUTE_UNUSED;
00951 {
00952 enum rtx_code code = GET_CODE (op);
00953
00954 if (GET_RTX_CLASS (code) != '<')
00955 return 0;
00956
00957 return v9_regcmp_p (code);
00958 }
00959
00960
00961
00962 int
00963 extend_op (op, mode)
00964 rtx op;
00965 enum machine_mode mode ATTRIBUTE_UNUSED;
00966 {
00967 return GET_CODE (op) == SIGN_EXTEND || GET_CODE (op) == ZERO_EXTEND;
00968 }
00969
00970
00971
00972
00973
00974 int
00975 cc_arithop (op, mode)
00976 rtx op;
00977 enum machine_mode mode ATTRIBUTE_UNUSED;
00978 {
00979 if (GET_CODE (op) == AND
00980 || GET_CODE (op) == IOR
00981 || GET_CODE (op) == XOR)
00982 return 1;
00983
00984 return 0;
00985 }
00986
00987
00988
00989
00990 int
00991 cc_arithopn (op, mode)
00992 rtx op;
00993 enum machine_mode mode ATTRIBUTE_UNUSED;
00994 {
00995
00996
00997 return (GET_CODE (op) == AND
00998 || GET_CODE (op) == IOR);
00999 }
01000
01001
01002
01003
01004
01005 int
01006 arith_operand (op, mode)
01007 rtx op;
01008 enum machine_mode mode;
01009 {
01010 if (register_operand (op, mode))
01011 return 1;
01012 if (GET_CODE (op) != CONST_INT)
01013 return 0;
01014 return SMALL_INT32 (op);
01015 }
01016
01017
01018
01019 int
01020 arith_4096_operand (op, mode)
01021 rtx op;
01022 enum machine_mode mode ATTRIBUTE_UNUSED;
01023 {
01024 if (GET_CODE (op) != CONST_INT)
01025 return 0;
01026 else
01027 return INTVAL (op) == 4096;
01028 }
01029
01030
01031
01032 int
01033 arith_add_operand (op, mode)
01034 rtx op;
01035 enum machine_mode mode;
01036 {
01037 return arith_operand (op, mode) || arith_4096_operand (op, mode);
01038 }
01039
01040
01041
01042
01043 int
01044 const64_operand (op, mode)
01045 rtx op;
01046 enum machine_mode mode ATTRIBUTE_UNUSED;
01047 {
01048 return ((GET_CODE (op) == CONST_INT
01049 && SPARC_SIMM13_P (INTVAL (op)))
01050 #if HOST_BITS_PER_WIDE_INT != 64
01051 || (GET_CODE (op) == CONST_DOUBLE
01052 && SPARC_SIMM13_P (CONST_DOUBLE_LOW (op))
01053 && (CONST_DOUBLE_HIGH (op) ==
01054 ((CONST_DOUBLE_LOW (op) & 0x80000000) != 0 ?
01055 (HOST_WIDE_INT)-1 : 0)))
01056 #endif
01057 );
01058 }
01059
01060
01061 int
01062 const64_high_operand (op, mode)
01063 rtx op;
01064 enum machine_mode mode;
01065 {
01066 return ((GET_CODE (op) == CONST_INT
01067 && (INTVAL (op) & ~(HOST_WIDE_INT)0x3ff) != 0
01068 && SPARC_SETHI_P (INTVAL (op) & GET_MODE_MASK (mode))
01069 )
01070 || (GET_CODE (op) == CONST_DOUBLE
01071 && CONST_DOUBLE_HIGH (op) == 0
01072 && (CONST_DOUBLE_LOW (op) & ~(HOST_WIDE_INT)0x3ff) != 0
01073 && SPARC_SETHI_P (CONST_DOUBLE_LOW (op))));
01074 }
01075
01076
01077
01078
01079
01080 int
01081 arith11_operand (op, mode)
01082 rtx op;
01083 enum machine_mode mode;
01084 {
01085 return (register_operand (op, mode)
01086 || (GET_CODE (op) == CONST_INT && SPARC_SIMM11_P (INTVAL (op))));
01087 }
01088
01089
01090
01091
01092
01093 int
01094 arith10_operand (op, mode)
01095 rtx op;
01096 enum machine_mode mode;
01097 {
01098 return (register_operand (op, mode)
01099 || (GET_CODE (op) == CONST_INT && SPARC_SIMM10_P (INTVAL (op))));
01100 }
01101
01102
01103
01104
01105
01106
01107
01108
01109 int
01110 arith_double_operand (op, mode)
01111 rtx op;
01112 enum machine_mode mode;
01113 {
01114 return (register_operand (op, mode)
01115 || (GET_CODE (op) == CONST_INT && SMALL_INT (op))
01116 || (! TARGET_ARCH64
01117 && GET_CODE (op) == CONST_DOUBLE
01118 && (unsigned HOST_WIDE_INT) (CONST_DOUBLE_LOW (op) + 0x1000) < 0x2000
01119 && (unsigned HOST_WIDE_INT) (CONST_DOUBLE_HIGH (op) + 0x1000) < 0x2000)
01120 || (TARGET_ARCH64
01121 && GET_CODE (op) == CONST_DOUBLE
01122 && (unsigned HOST_WIDE_INT) (CONST_DOUBLE_LOW (op) + 0x1000) < 0x2000
01123 && ((CONST_DOUBLE_HIGH (op) == -1
01124 && (CONST_DOUBLE_LOW (op) & 0x1000) == 0x1000)
01125 || (CONST_DOUBLE_HIGH (op) == 0
01126 && (CONST_DOUBLE_LOW (op) & 0x1000) == 0))));
01127 }
01128
01129
01130
01131 int
01132 arith_double_4096_operand (op, mode)
01133 rtx op;
01134 enum machine_mode mode ATTRIBUTE_UNUSED;
01135 {
01136 return (TARGET_ARCH64 &&
01137 ((GET_CODE (op) == CONST_INT && INTVAL (op) == 4096) ||
01138 (GET_CODE (op) == CONST_DOUBLE &&
01139 CONST_DOUBLE_LOW (op) == 4096 &&
01140 CONST_DOUBLE_HIGH (op) == 0)));
01141 }
01142
01143
01144
01145 int
01146 arith_double_add_operand (op, mode)
01147 rtx op;
01148 enum machine_mode mode;
01149 {
01150 return arith_double_operand (op, mode) || arith_double_4096_operand (op, mode);
01151 }
01152
01153
01154
01155
01156
01157
01158 int
01159 arith11_double_operand (op, mode)
01160 rtx op;
01161 enum machine_mode mode;
01162 {
01163 return (register_operand (op, mode)
01164 || (GET_CODE (op) == CONST_DOUBLE
01165 && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
01166 && (unsigned HOST_WIDE_INT) (CONST_DOUBLE_LOW (op) + 0x400) < 0x800
01167 && ((CONST_DOUBLE_HIGH (op) == -1
01168 && (CONST_DOUBLE_LOW (op) & 0x400) == 0x400)
01169 || (CONST_DOUBLE_HIGH (op) == 0
01170 && (CONST_DOUBLE_LOW (op) & 0x400) == 0)))
01171 || (GET_CODE (op) == CONST_INT
01172 && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
01173 && (unsigned HOST_WIDE_INT) (INTVAL (op) + 0x400) < 0x800));
01174 }
01175
01176
01177
01178
01179
01180
01181 int
01182 arith10_double_operand (op, mode)
01183 rtx op;
01184 enum machine_mode mode;
01185 {
01186 return (register_operand (op, mode)
01187 || (GET_CODE (op) == CONST_DOUBLE
01188 && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
01189 && (unsigned) (CONST_DOUBLE_LOW (op) + 0x200) < 0x400
01190 && ((CONST_DOUBLE_HIGH (op) == -1
01191 && (CONST_DOUBLE_LOW (op) & 0x200) == 0x200)
01192 || (CONST_DOUBLE_HIGH (op) == 0
01193 && (CONST_DOUBLE_LOW (op) & 0x200) == 0)))
01194 || (GET_CODE (op) == CONST_INT
01195 && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
01196 && (unsigned HOST_WIDE_INT) (INTVAL (op) + 0x200) < 0x400));
01197 }
01198
01199
01200
01201
01202
01203 int
01204 small_int (op, mode)
01205 rtx op;
01206 enum machine_mode mode ATTRIBUTE_UNUSED;
01207 {
01208 return (GET_CODE (op) == CONST_INT && SMALL_INT (op));
01209 }
01210
01211 int
01212 small_int_or_double (op, mode)
01213 rtx op;
01214 enum machine_mode mode ATTRIBUTE_UNUSED;
01215 {
01216 return ((GET_CODE (op) == CONST_INT && SMALL_INT (op))
01217 || (GET_CODE (op) == CONST_DOUBLE
01218 && CONST_DOUBLE_HIGH (op) == 0
01219 && SPARC_SIMM13_P (CONST_DOUBLE_LOW (op))));
01220 }
01221
01222
01223
01224
01225
01226 int
01227 uns_small_int (op, mode)
01228 rtx op;
01229 enum machine_mode mode ATTRIBUTE_UNUSED;
01230 {
01231 #if HOST_BITS_PER_WIDE_INT > 32
01232
01233 return (GET_CODE (op) == CONST_INT
01234 && ((INTVAL (op) >= 0 && INTVAL (op) < 0x1000)
01235 || (INTVAL (op) >= 0xFFFFF000
01236 && INTVAL (op) <= 0xFFFFFFFF)));
01237 #else
01238 return ((GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 0x1000)
01239 || (GET_CODE (op) == CONST_DOUBLE
01240 && CONST_DOUBLE_HIGH (op) == 0
01241 && (unsigned) CONST_DOUBLE_LOW (op) - 0xFFFFF000 < 0x1000));
01242 #endif
01243 }
01244
01245 int
01246 uns_arith_operand (op, mode)
01247 rtx op;
01248 enum machine_mode mode;
01249 {
01250 return register_operand (op, mode) || uns_small_int (op, mode);
01251 }
01252
01253
01254 int
01255 clobbered_register (op, mode)
01256 rtx op;
01257 enum machine_mode mode ATTRIBUTE_UNUSED;
01258 {
01259 return (GET_CODE (op) == REG && call_used_regs[REGNO (op)]);
01260 }
01261
01262
01263
01264 int
01265 input_operand (op, mode)
01266 rtx op;
01267 enum machine_mode mode;
01268 {
01269
01270 if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
01271 return 0;
01272
01273
01274 if (GET_CODE (op) == CONST && GET_CODE (XEXP (op, 0)) == CONSTANT_P_RTX)
01275 return 1;
01276
01277
01278
01279 if (GET_MODE_CLASS (mode) == MODE_INT
01280 && ((GET_CODE (op) == CONST_INT
01281 && (SPARC_SETHI_P (INTVAL (op) & GET_MODE_MASK (mode))
01282 || SPARC_SIMM13_P (INTVAL (op))
01283 || (mode == DImode
01284 && ! TARGET_ARCH64)))
01285 || (TARGET_ARCH64
01286 && GET_CODE (op) == CONST_DOUBLE
01287 && ((CONST_DOUBLE_HIGH (op) == 0
01288 && SPARC_SETHI_P (CONST_DOUBLE_LOW (op)))
01289 ||
01290 #if HOST_BITS_PER_WIDE_INT == 64
01291 (CONST_DOUBLE_HIGH (op) == 0
01292 && SPARC_SIMM13_P (CONST_DOUBLE_LOW (op)))
01293 #else
01294 (SPARC_SIMM13_P (CONST_DOUBLE_LOW (op))
01295 && (((CONST_DOUBLE_LOW (op) & 0x80000000) == 0
01296 && CONST_DOUBLE_HIGH (op) == 0)
01297 || (CONST_DOUBLE_HIGH (op) == -1
01298 && CONST_DOUBLE_LOW (op) & 0x80000000) != 0))
01299 #endif
01300 ))))
01301 return 1;
01302
01303
01304
01305 if (! TARGET_ARCH64
01306 && mode == DImode
01307 && GET_CODE (op) == CONST_DOUBLE)
01308 return 1;
01309
01310 if (register_operand (op, mode))
01311 return 1;
01312
01313 if (GET_MODE_CLASS (mode) == MODE_FLOAT
01314 && GET_CODE (op) == CONST_DOUBLE)
01315 return 1;
01316
01317
01318
01319 if (GET_CODE (op) == SUBREG)
01320 op = SUBREG_REG (op);
01321
01322
01323 if (GET_CODE (op) == MEM)
01324 {
01325 rtx inside = XEXP (op, 0);
01326
01327 if (GET_CODE (inside) == LO_SUM)
01328 {
01329
01330
01331
01332 if (! TARGET_V9
01333 && GET_MODE (op) == TFmode)
01334 return 0;
01335
01336 return (register_operand (XEXP (inside, 0), Pmode)
01337 && CONSTANT_P (XEXP (inside, 1)));
01338 }
01339 return memory_address_p (mode, inside);
01340 }
01341
01342 return 0;
01343 }
01344
01345
01346
01347
01348 void
01349 sparc_emit_set_const32 (op0, op1)
01350 rtx op0;
01351 rtx op1;
01352 {
01353 enum machine_mode mode = GET_MODE (op0);
01354 rtx temp;
01355
01356 if (GET_CODE (op1) == CONST_INT)
01357 {
01358 HOST_WIDE_INT value = INTVAL (op1);
01359
01360 if (SPARC_SETHI_P (value & GET_MODE_MASK (mode))
01361 || SPARC_SIMM13_P (value))
01362 abort ();
01363 }
01364
01365
01366 if (reload_in_progress || reload_completed)
01367 temp = op0;
01368 else
01369 temp = gen_reg_rtx (mode);
01370
01371 if (GET_CODE (op1) == CONST_INT)
01372 {
01373
01374
01375
01376 if (TARGET_ARCH64
01377 && HOST_BITS_PER_WIDE_INT != 64
01378 && (INTVAL (op1) & 0x80000000) != 0)
01379 emit_insn (gen_rtx_SET
01380 (VOIDmode, temp,
01381 gen_rtx_CONST_DOUBLE (VOIDmode,
01382 INTVAL (op1) & ~(HOST_WIDE_INT)0x3ff,
01383 0)));
01384 else
01385 emit_insn (gen_rtx_SET (VOIDmode, temp,
01386 GEN_INT (INTVAL (op1)
01387 & ~(HOST_WIDE_INT)0x3ff)));
01388
01389 emit_insn (gen_rtx_SET (VOIDmode,
01390 op0,
01391 gen_rtx_IOR (mode, temp,
01392 GEN_INT (INTVAL (op1) & 0x3ff))));
01393 }
01394 else
01395 {
01396
01397 emit_insn (gen_rtx_SET (VOIDmode, temp,
01398 gen_rtx_HIGH (mode, op1)));
01399 emit_insn (gen_rtx_SET (VOIDmode,
01400 op0, gen_rtx_LO_SUM (mode, temp, op1)));
01401
01402 }
01403 }
01404
01405
01406
01407 void
01408 sparc_emit_set_symbolic_const64 (op0, op1, temp1)
01409 rtx op0;
01410 rtx op1;
01411 rtx temp1;
01412 {
01413 rtx ti_temp1 = 0;
01414
01415 if (temp1 && GET_MODE (temp1) == TImode)
01416 {
01417 ti_temp1 = temp1;
01418 temp1 = gen_rtx_REG (DImode, REGNO (temp1));
01419 }
01420
01421 switch (sparc_cmodel)
01422 {
01423 case CM_MEDLOW:
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434 emit_insn (gen_rtx_SET (VOIDmode, temp1, gen_rtx_HIGH (DImode, op1)));
01435 emit_insn (gen_rtx_SET (VOIDmode, op0, gen_rtx_LO_SUM (DImode, temp1, op1)));
01436 break;
01437
01438 case CM_MEDMID:
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451 emit_insn (gen_seth44 (op0, op1));
01452 emit_insn (gen_setm44 (op0, op0, op1));
01453 emit_insn (gen_rtx_SET (VOIDmode, temp1,
01454 gen_rtx_ASHIFT (DImode, op0, GEN_INT (12))));
01455 emit_insn (gen_setl44 (op0, temp1, op1));
01456 break;
01457
01458 case CM_MEDANY:
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477 if (rtx_equal_p (temp1, op0))
01478 {
01479 if (ti_temp1)
01480 temp1 = gen_rtx_REG (DImode, REGNO (temp1) + 1);
01481 else
01482 abort();
01483 }
01484
01485 emit_insn (gen_sethh (op0, op1));
01486 emit_insn (gen_setlm (temp1, op1));
01487 emit_insn (gen_sethm (op0, op0, op1));
01488 emit_insn (gen_rtx_SET (VOIDmode, op0,
01489 gen_rtx_ASHIFT (DImode, op0, GEN_INT (32))));
01490 emit_insn (gen_rtx_SET (VOIDmode, op0,
01491 gen_rtx_PLUS (DImode, op0, temp1)));
01492 emit_insn (gen_setlo (op0, op0, op1));
01493 break;
01494
01495 case CM_EMBMEDANY:
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513 if (data_segment_operand (op1, GET_MODE (op1)))
01514 {
01515 emit_insn (gen_embmedany_sethi (temp1, op1));
01516 emit_insn (gen_embmedany_brsum (op0, temp1));
01517 emit_insn (gen_embmedany_losum (op0, op0, op1));
01518 }
01519 else
01520 {
01521
01522
01523
01524 if (rtx_equal_p (temp1, op0))
01525 {
01526 if (ti_temp1)
01527 temp1 = gen_rtx_REG (DImode, REGNO (temp1) + 1);
01528 else
01529 abort();
01530 }
01531
01532 emit_insn (gen_embmedany_textuhi (op0, op1));
01533 emit_insn (gen_embmedany_texthi (temp1, op1));
01534 emit_insn (gen_embmedany_textulo (op0, op0, op1));
01535 emit_insn (gen_rtx_SET (VOIDmode, op0,
01536 gen_rtx_ASHIFT (DImode, op0, GEN_INT (32))));
01537 emit_insn (gen_rtx_SET (VOIDmode, op0,
01538 gen_rtx_PLUS (DImode, op0, temp1)));
01539 emit_insn (gen_embmedany_textlo (op0, op0, op1));
01540 }
01541 break;
01542
01543 default:
01544 abort();
01545 }
01546 }
01547
01548
01549
01550
01551 static void sparc_emit_set_safe_HIGH64 PARAMS ((rtx, HOST_WIDE_INT));
01552 static rtx gen_safe_SET64 PARAMS ((rtx, HOST_WIDE_INT));
01553 static rtx gen_safe_OR64 PARAMS ((rtx, HOST_WIDE_INT));
01554 static rtx gen_safe_XOR64 PARAMS ((rtx, HOST_WIDE_INT));
01555
01556 #if HOST_BITS_PER_WIDE_INT == 64
01557 #define GEN_HIGHINT64(__x) GEN_INT ((__x) & ~(HOST_WIDE_INT)0x3ff)
01558 #define GEN_INT64(__x) GEN_INT (__x)
01559 #else
01560 #define GEN_HIGHINT64(__x) \
01561 gen_rtx_CONST_DOUBLE (VOIDmode, (__x) & ~(HOST_WIDE_INT)0x3ff, 0)
01562 #define GEN_INT64(__x) \
01563 gen_rtx_CONST_DOUBLE (VOIDmode, (__x) & 0xffffffff, \
01564 ((__x) & 0x80000000 \
01565 ? -1 : 0))
01566 #endif
01567
01568
01569
01570
01571
01572
01573 static void
01574 sparc_emit_set_safe_HIGH64 (dest, val)
01575 rtx dest;
01576 HOST_WIDE_INT val;
01577 {
01578 emit_insn (gen_rtx_SET (VOIDmode, dest, GEN_HIGHINT64 (val)));
01579 }
01580
01581 static rtx
01582 gen_safe_SET64 (dest, val)
01583 rtx dest;
01584 HOST_WIDE_INT val;
01585 {
01586 return gen_rtx_SET (VOIDmode, dest, GEN_INT64 (val));
01587 }
01588
01589 static rtx
01590 gen_safe_OR64 (src, val)
01591 rtx src;
01592 HOST_WIDE_INT val;
01593 {
01594 return gen_rtx_IOR (DImode, src, GEN_INT64 (val));
01595 }
01596
01597 static rtx
01598 gen_safe_XOR64 (src, val)
01599 rtx src;
01600 HOST_WIDE_INT val;
01601 {
01602 return gen_rtx_XOR (DImode, src, GEN_INT64 (val));
01603 }
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613 static void sparc_emit_set_const64_quick1
01614 PARAMS ((rtx, rtx, unsigned HOST_WIDE_INT, int));
01615
01616 static void
01617 sparc_emit_set_const64_quick1 (op0, temp, low_bits, is_neg)
01618 rtx op0;
01619 rtx temp;
01620 unsigned HOST_WIDE_INT low_bits;
01621 int is_neg;
01622 {
01623 unsigned HOST_WIDE_INT high_bits;
01624
01625 if (is_neg)
01626 high_bits = (~low_bits) & 0xffffffff;
01627 else
01628 high_bits = low_bits;
01629
01630 sparc_emit_set_safe_HIGH64 (temp, high_bits);
01631 if (!is_neg)
01632 {
01633 emit_insn (gen_rtx_SET (VOIDmode, op0,
01634 gen_safe_OR64 (temp, (high_bits & 0x3ff))));
01635 }
01636 else
01637 {
01638
01639
01640
01641 if ((low_bits & 0x3ff) == 0x3ff)
01642 {
01643 emit_insn (gen_rtx_SET (VOIDmode, op0,
01644 gen_rtx_NOT (DImode, temp)));
01645 }
01646 else
01647 {
01648 emit_insn (gen_rtx_SET (VOIDmode, op0,
01649 gen_safe_XOR64 (temp,
01650 (-(HOST_WIDE_INT)0x400
01651 | (low_bits & 0x3ff)))));
01652 }
01653 }
01654 }
01655
01656 static void sparc_emit_set_const64_quick2
01657 PARAMS ((rtx, rtx, unsigned HOST_WIDE_INT,
01658 unsigned HOST_WIDE_INT, int));
01659
01660 static void
01661 sparc_emit_set_const64_quick2 (op0, temp, high_bits, low_immediate, shift_count)
01662 rtx op0;
01663 rtx temp;
01664 unsigned HOST_WIDE_INT high_bits;
01665 unsigned HOST_WIDE_INT low_immediate;
01666 int shift_count;
01667 {
01668 rtx temp2 = op0;
01669
01670 if ((high_bits & 0xfffffc00) != 0)
01671 {
01672 sparc_emit_set_safe_HIGH64 (temp, high_bits);
01673 if ((high_bits & ~0xfffffc00) != 0)
01674 emit_insn (gen_rtx_SET (VOIDmode, op0,
01675 gen_safe_OR64 (temp, (high_bits & 0x3ff))));
01676 else
01677 temp2 = temp;
01678 }
01679 else
01680 {
01681 emit_insn (gen_safe_SET64 (temp, high_bits));
01682 temp2 = temp;
01683 }
01684
01685
01686 emit_insn (gen_rtx_SET (VOIDmode, op0,
01687 gen_rtx_ASHIFT (DImode, temp2,
01688 GEN_INT (shift_count))));
01689
01690
01691
01692 if (low_immediate != 0)
01693 emit_insn (gen_rtx_SET (VOIDmode, op0,
01694 gen_safe_OR64 (op0, low_immediate)));
01695 }
01696
01697 static void sparc_emit_set_const64_longway
01698 PARAMS ((rtx, rtx, unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT));
01699
01700
01701
01702 static void
01703 sparc_emit_set_const64_longway (op0, temp, high_bits, low_bits)
01704 rtx op0;
01705 rtx temp;
01706 unsigned HOST_WIDE_INT high_bits;
01707 unsigned HOST_WIDE_INT low_bits;
01708 {
01709 rtx sub_temp;
01710
01711 if (reload_in_progress || reload_completed)
01712 sub_temp = op0;
01713 else
01714 sub_temp = gen_reg_rtx (DImode);
01715
01716 if ((high_bits & 0xfffffc00) != 0)
01717 {
01718 sparc_emit_set_safe_HIGH64 (temp, high_bits);
01719 if ((high_bits & ~0xfffffc00) != 0)
01720 emit_insn (gen_rtx_SET (VOIDmode,
01721 sub_temp,
01722 gen_safe_OR64 (temp, (high_bits & 0x3ff))));
01723 else
01724 sub_temp = temp;
01725 }
01726 else
01727 {
01728 emit_insn (gen_safe_SET64 (temp, high_bits));
01729 sub_temp = temp;
01730 }
01731
01732 if (!reload_in_progress && !reload_completed)
01733 {
01734 rtx temp2 = gen_reg_rtx (DImode);
01735 rtx temp3 = gen_reg_rtx (DImode);
01736 rtx temp4 = gen_reg_rtx (DImode);
01737
01738 emit_insn (gen_rtx_SET (VOIDmode, temp4,
01739 gen_rtx_ASHIFT (DImode, sub_temp,
01740 GEN_INT (32))));
01741
01742 sparc_emit_set_safe_HIGH64 (temp2, low_bits);
01743 if ((low_bits & ~0xfffffc00) != 0)
01744 {
01745 emit_insn (gen_rtx_SET (VOIDmode, temp3,
01746 gen_safe_OR64 (temp2, (low_bits & 0x3ff))));
01747 emit_insn (gen_rtx_SET (VOIDmode, op0,
01748 gen_rtx_PLUS (DImode, temp4, temp3)));
01749 }
01750 else
01751 {
01752 emit_insn (gen_rtx_SET (VOIDmode, op0,
01753 gen_rtx_PLUS (DImode, temp4, temp2)));
01754 }
01755 }
01756 else
01757 {
01758 rtx low1 = GEN_INT ((low_bits >> (32 - 12)) & 0xfff);
01759 rtx low2 = GEN_INT ((low_bits >> (32 - 12 - 12)) & 0xfff);
01760 rtx low3 = GEN_INT ((low_bits >> (32 - 12 - 12 - 8)) & 0x0ff);
01761 int to_shift = 12;
01762
01763
01764
01765
01766 if (low1 != const0_rtx)
01767 {
01768 emit_insn (gen_rtx_SET (VOIDmode, op0,
01769 gen_rtx_ASHIFT (DImode, sub_temp,
01770 GEN_INT (to_shift))));
01771 emit_insn (gen_rtx_SET (VOIDmode, op0,
01772 gen_rtx_IOR (DImode, op0, low1)));
01773 sub_temp = op0;
01774 to_shift = 12;
01775 }
01776 else
01777 {
01778 to_shift += 12;
01779 }
01780 if (low2 != const0_rtx)
01781 {
01782 emit_insn (gen_rtx_SET (VOIDmode, op0,
01783 gen_rtx_ASHIFT (DImode, sub_temp,
01784 GEN_INT (to_shift))));
01785 emit_insn (gen_rtx_SET (VOIDmode, op0,
01786 gen_rtx_IOR (DImode, op0, low2)));
01787 sub_temp = op0;
01788 to_shift = 8;
01789 }
01790 else
01791 {
01792 to_shift += 8;
01793 }
01794 emit_insn (gen_rtx_SET (VOIDmode, op0,
01795 gen_rtx_ASHIFT (DImode, sub_temp,
01796 GEN_INT (to_shift))));
01797 if (low3 != const0_rtx)
01798 emit_insn (gen_rtx_SET (VOIDmode, op0,
01799 gen_rtx_IOR (DImode, op0, low3)));
01800
01801 }
01802 }
01803
01804
01805 static void analyze_64bit_constant
01806 PARAMS ((unsigned HOST_WIDE_INT,
01807 unsigned HOST_WIDE_INT,
01808 int *, int *, int *));
01809
01810 static void
01811 analyze_64bit_constant (high_bits, low_bits, hbsp, lbsp, abbasp)
01812 unsigned HOST_WIDE_INT high_bits, low_bits;
01813 int *hbsp, *lbsp, *abbasp;
01814 {
01815 int lowest_bit_set, highest_bit_set, all_bits_between_are_set;
01816 int i;
01817
01818 lowest_bit_set = highest_bit_set = -1;
01819 i = 0;
01820 do
01821 {
01822 if ((lowest_bit_set == -1)
01823 && ((low_bits >> i) & 1))
01824 lowest_bit_set = i;
01825 if ((highest_bit_set == -1)
01826 && ((high_bits >> (32 - i - 1)) & 1))
01827 highest_bit_set = (64 - i - 1);
01828 }
01829 while (++i < 32
01830 && ((highest_bit_set == -1)
01831 || (lowest_bit_set == -1)));
01832 if (i == 32)
01833 {
01834 i = 0;
01835 do
01836 {
01837 if ((lowest_bit_set == -1)
01838 && ((high_bits >> i) & 1))
01839 lowest_bit_set = i + 32;
01840 if ((highest_bit_set == -1)
01841 && ((low_bits >> (32 - i - 1)) & 1))
01842 highest_bit_set = 32 - i - 1;
01843 }
01844 while (++i < 32
01845 && ((highest_bit_set == -1)
01846 || (lowest_bit_set == -1)));
01847 }
01848
01849
01850 if (lowest_bit_set == -1
01851 || highest_bit_set == -1)
01852 abort ();
01853 all_bits_between_are_set = 1;
01854 for (i = lowest_bit_set; i <= highest_bit_set; i++)
01855 {
01856 if (i < 32)
01857 {
01858 if ((low_bits & (1 << i)) != 0)
01859 continue;
01860 }
01861 else
01862 {
01863 if ((high_bits & (1 << (i - 32))) != 0)
01864 continue;
01865 }
01866 all_bits_between_are_set = 0;
01867 break;
01868 }
01869 *hbsp = highest_bit_set;
01870 *lbsp = lowest_bit_set;
01871 *abbasp = all_bits_between_are_set;
01872 }
01873
01874 static int const64_is_2insns
01875 PARAMS ((unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT));
01876
01877 static int
01878 const64_is_2insns (high_bits, low_bits)
01879 unsigned HOST_WIDE_INT high_bits, low_bits;
01880 {
01881 int highest_bit_set, lowest_bit_set, all_bits_between_are_set;
01882
01883 if (high_bits == 0
01884 || high_bits == 0xffffffff)
01885 return 1;
01886
01887 analyze_64bit_constant (high_bits, low_bits,
01888 &highest_bit_set, &lowest_bit_set,
01889 &all_bits_between_are_set);
01890
01891 if ((highest_bit_set == 63
01892 || lowest_bit_set == 0)
01893 && all_bits_between_are_set != 0)
01894 return 1;
01895
01896 if ((highest_bit_set - lowest_bit_set) < 21)
01897 return 1;
01898
01899 return 0;
01900 }
01901
01902 static unsigned HOST_WIDE_INT create_simple_focus_bits
01903 PARAMS ((unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT,
01904 int, int));
01905
01906 static unsigned HOST_WIDE_INT
01907 create_simple_focus_bits (high_bits, low_bits, lowest_bit_set, shift)
01908 unsigned HOST_WIDE_INT high_bits, low_bits;
01909 int lowest_bit_set, shift;
01910 {
01911 HOST_WIDE_INT hi, lo;
01912
01913 if (lowest_bit_set < 32)
01914 {
01915 lo = (low_bits >> lowest_bit_set) << shift;
01916 hi = ((high_bits << (32 - lowest_bit_set)) << shift);
01917 }
01918 else
01919 {
01920 lo = 0;
01921 hi = ((high_bits >> (lowest_bit_set - 32)) << shift);
01922 }
01923 if (hi & lo)
01924 abort ();
01925 return (hi | lo);
01926 }
01927
01928
01929
01930
01931
01932 void
01933 sparc_emit_set_const64 (op0, op1)
01934 rtx op0;
01935 rtx op1;
01936 {
01937 unsigned HOST_WIDE_INT high_bits, low_bits;
01938 int lowest_bit_set, highest_bit_set;
01939 int all_bits_between_are_set;
01940 rtx temp;
01941
01942
01943 if (! TARGET_ARCH64)
01944 abort ();
01945
01946 if (GET_CODE (op0) != SUBREG)
01947 {
01948 if (GET_CODE (op0) != REG
01949 || (REGNO (op0) >= SPARC_FIRST_FP_REG
01950 && REGNO (op0) <= SPARC_LAST_V9_FP_REG))
01951 abort ();
01952 }
01953
01954 if (reload_in_progress || reload_completed)
01955 temp = op0;
01956 else
01957 temp = gen_reg_rtx (DImode);
01958
01959 if (GET_CODE (op1) != CONST_DOUBLE
01960 && GET_CODE (op1) != CONST_INT)
01961 {
01962 sparc_emit_set_symbolic_const64 (op0, op1, temp);
01963 return;
01964 }
01965
01966 if (GET_CODE (op1) == CONST_DOUBLE)
01967 {
01968 #if HOST_BITS_PER_WIDE_INT == 64
01969 high_bits = (CONST_DOUBLE_LOW (op1) >> 32) & 0xffffffff;
01970 low_bits = CONST_DOUBLE_LOW (op1) & 0xffffffff;
01971 #else
01972 high_bits = CONST_DOUBLE_HIGH (op1);
01973 low_bits = CONST_DOUBLE_LOW (op1);
01974 #endif
01975 }
01976 else
01977 {
01978 #if HOST_BITS_PER_WIDE_INT == 64
01979 high_bits = ((INTVAL (op1) >> 32) & 0xffffffff);
01980 low_bits = (INTVAL (op1) & 0xffffffff);
01981 #else
01982 high_bits = ((INTVAL (op1) < 0) ?
01983 0xffffffff :
01984 0x00000000);
01985 low_bits = INTVAL (op1);
01986 #endif
01987 }
01988
01989
01990
01991
01992 analyze_64bit_constant (high_bits, low_bits,
01993 &highest_bit_set, &lowest_bit_set,
01994 &all_bits_between_are_set);
01995
01996
01997
01998
01999
02000
02001
02002
02003
02004
02005
02006
02007 if (((highest_bit_set == 63
02008 || lowest_bit_set == 0)
02009 && all_bits_between_are_set != 0)
02010 || ((highest_bit_set - lowest_bit_set) < 12))
02011 {
02012 HOST_WIDE_INT the_const = -1;
02013 int shift = lowest_bit_set;
02014
02015 if ((highest_bit_set != 63
02016 && lowest_bit_set != 0)
02017 || all_bits_between_are_set == 0)
02018 {
02019 the_const =
02020 create_simple_focus_bits (high_bits, low_bits,
02021 lowest_bit_set, 0);
02022 }
02023 else if (lowest_bit_set == 0)
02024 shift = -(63 - highest_bit_set);
02025
02026 if (! SPARC_SIMM13_P (the_const))
02027 abort ();
02028
02029 emit_insn (gen_safe_SET64 (temp, the_const));
02030 if (shift > 0)
02031 emit_insn (gen_rtx_SET (VOIDmode,
02032 op0,
02033 gen_rtx_ASHIFT (DImode,
02034 temp,
02035 GEN_INT (shift))));
02036 else if (shift < 0)
02037 emit_insn (gen_rtx_SET (VOIDmode,
02038 op0,
02039 gen_rtx_LSHIFTRT (DImode,
02040 temp,
02041 GEN_INT (-shift))));
02042 else
02043 abort ();
02044 return;
02045 }
02046
02047
02048
02049
02050
02051
02052
02053 if ((highest_bit_set - lowest_bit_set) < 21)
02054 {
02055 unsigned HOST_WIDE_INT focus_bits =
02056 create_simple_focus_bits (high_bits, low_bits,
02057 lowest_bit_set, 10);
02058
02059 if (! SPARC_SETHI_P (focus_bits))
02060 abort ();
02061
02062 sparc_emit_set_safe_HIGH64 (temp, focus_bits);
02063
02064
02065 if (lowest_bit_set < 10)
02066 emit_insn (gen_rtx_SET (VOIDmode,
02067 op0,
02068 gen_rtx_LSHIFTRT (DImode, temp,
02069 GEN_INT (10 - lowest_bit_set))));
02070 else if (lowest_bit_set > 10)
02071 emit_insn (gen_rtx_SET (VOIDmode,
02072 op0,
02073 gen_rtx_ASHIFT (DImode, temp,
02074 GEN_INT (lowest_bit_set - 10))));
02075 else
02076 abort ();
02077 return;
02078 }
02079
02080
02081
02082
02083
02084
02085 if (high_bits == 0
02086 || high_bits == 0xffffffff)
02087 {
02088 sparc_emit_set_const64_quick1 (op0, temp, low_bits,
02089 (high_bits == 0xffffffff));
02090 return;
02091 }
02092
02093
02094
02095
02096
02097
02098
02099 if (low_bits == 0)
02100 {
02101 sparc_emit_set_const64_quick2 (op0, temp, high_bits, 0, 32);
02102 return;
02103 }
02104
02105
02106
02107 if (const64_is_2insns ((~high_bits) & 0xffffffff,
02108 (~low_bits) & 0xfffffc00))
02109 {
02110
02111
02112 unsigned HOST_WIDE_INT trailing_bits = low_bits & 0x3ff;
02113
02114 if ((((~high_bits) & 0xffffffff) == 0
02115 && ((~low_bits) & 0x80000000) == 0)
02116 || (((~high_bits) & 0xffffffff) == 0xffffffff
02117 && ((~low_bits) & 0x80000000) != 0))
02118 {
02119 int fast_int = (~low_bits & 0xffffffff);
02120
02121 if ((SPARC_SETHI_P (fast_int)
02122 && (~high_bits & 0xffffffff) == 0)
02123 || SPARC_SIMM13_P (fast_int))
02124 emit_insn (gen_safe_SET64 (temp, fast_int));
02125 else
02126 sparc_emit_set_const64 (temp, GEN_INT64 (fast_int));
02127 }
02128 else
02129 {
02130 rtx negated_const;
02131 #if HOST_BITS_PER_WIDE_INT == 64
02132 negated_const = GEN_INT (((~low_bits) & 0xfffffc00) |
02133 (((HOST_WIDE_INT)((~high_bits) & 0xffffffff))<<32));
02134 #else
02135 negated_const = gen_rtx_CONST_DOUBLE (DImode,
02136 (~low_bits) & 0xfffffc00,
02137 (~high_bits) & 0xffffffff);
02138 #endif
02139 sparc_emit_set_const64 (temp, negated_const);
02140 }
02141
02142
02143
02144
02145 if (trailing_bits == 0x3ff)
02146 {
02147 emit_insn (gen_rtx_SET (VOIDmode, op0,
02148 gen_rtx_NOT (DImode, temp)));
02149 }
02150 else
02151 {
02152 emit_insn (gen_rtx_SET (VOIDmode,
02153 op0,
02154 gen_safe_XOR64 (temp,
02155 (-0x400 | trailing_bits))));
02156 }
02157 return;
02158 }
02159
02160
02161
02162
02163
02164
02165
02166
02167 if ((highest_bit_set - lowest_bit_set) < 32)
02168 {
02169 unsigned HOST_WIDE_INT focus_bits =
02170 create_simple_focus_bits (high_bits, low_bits,
02171 lowest_bit_set, 0);
02172
02173
02174 if (highest_bit_set < 32
02175 || lowest_bit_set >= 32)
02176 abort ();
02177
02178
02179
02180 sparc_emit_set_const64_quick2 (op0, temp,
02181 focus_bits, 0,
02182 lowest_bit_set);
02183 return;
02184 }
02185
02186
02187
02188
02189
02190
02191 if (SPARC_SIMM13_P(low_bits)
02192 && ((int)low_bits > 0))
02193 {
02194 sparc_emit_set_const64_quick2 (op0, temp, high_bits, low_bits, 32);
02195 return;
02196 }
02197
02198
02199 #if 0
02200 printf ("sparc_emit_set_const64: Hard constant [%08lx%08lx] neg[%08lx%08lx]\n",
02201 high_bits, low_bits, ~high_bits, ~low_bits);
02202 #endif
02203 sparc_emit_set_const64_longway (op0, temp, high_bits, low_bits);
02204 }
02205
02206
02207
02208
02209
02210
02211
02212 enum machine_mode
02213 select_cc_mode (op, x, y)
02214 enum rtx_code op;
02215 rtx x;
02216 rtx y ATTRIBUTE_UNUSED;
02217 {
02218 if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
02219 {
02220 switch (op)
02221 {
02222 case EQ:
02223 case NE:
02224 case UNORDERED:
02225 case ORDERED:
02226 case UNLT:
02227 case UNLE:
02228 case UNGT:
02229 case UNGE:
02230 case UNEQ:
02231 case LTGT:
02232 return CCFPmode;
02233
02234 case LT:
02235 case LE:
02236 case GT:
02237 case GE:
02238 return CCFPEmode;
02239
02240 default:
02241 abort ();
02242 }
02243 }
02244 else if (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS
02245 || GET_CODE (x) == NEG || GET_CODE (x) == ASHIFT)
02246 {
02247 if (TARGET_ARCH64 && GET_MODE (x) == DImode)
02248 return CCX_NOOVmode;
02249 else
02250 return CC_NOOVmode;
02251 }
02252 else
02253 {
02254 if (TARGET_ARCH64 && GET_MODE (x) == DImode)
02255 return CCXmode;
02256 else
02257 return CCmode;
02258 }
02259 }
02260
02261
02262
02263
02264 rtx
02265 gen_compare_reg (code, x, y)
02266 enum rtx_code code;
02267 rtx x, y;
02268 {
02269 enum machine_mode mode = SELECT_CC_MODE (code, x, y);
02270 rtx cc_reg;
02271
02272
02273
02274
02275
02276
02277
02278
02279
02280
02281
02282
02283
02284
02285
02286
02287
02288 if (TARGET_V9 && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
02289 #if 1
02290 {
02291 int reg;
02292
02293 static int next_fcc_reg = 0;
02294
02295 static rtx prev_args[4][2];
02296
02297
02298 for (reg = 0; reg < 4; reg++)
02299 if (prev_args[reg][0] == x && prev_args[reg][1] == y)
02300 break;
02301 if (reg == 4)
02302 {
02303 reg = next_fcc_reg;
02304 prev_args[reg][0] = x;
02305 prev_args[reg][1] = y;
02306 next_fcc_reg = (next_fcc_reg + 1) & 3;
02307 }
02308 cc_reg = gen_rtx_REG (mode, reg + SPARC_FIRST_V9_FCC_REG);
02309 }
02310 #else
02311 cc_reg = gen_reg_rtx (mode);
02312 #endif
02313 else if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
02314 cc_reg = gen_rtx_REG (mode, SPARC_FCC_REG);
02315 else
02316 cc_reg = gen_rtx_REG (mode, SPARC_ICC_REG);
02317
02318 emit_insn (gen_rtx_SET (VOIDmode, cc_reg,
02319 gen_rtx_COMPARE (mode, x, y)));
02320
02321 return cc_reg;
02322 }
02323
02324
02325
02326
02327
02328
02329
02330
02331
02332
02333
02334
02335
02336
02337
02338
02339
02340
02341
02342
02343
02344
02345
02346
02347 int
02348 gen_v9_scc (compare_code, operands)
02349 enum rtx_code compare_code;
02350 register rtx *operands;
02351 {
02352 rtx temp, op0, op1;
02353
02354 if (! TARGET_ARCH64
02355 && (GET_MODE (sparc_compare_op0) == DImode
02356 || GET_MODE (operands[0]) == DImode))
02357 return 0;
02358
02359 op0 = sparc_compare_op0;
02360 op1 = sparc_compare_op1;
02361
02362
02363 if (TARGET_ARCH64
02364 && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT
02365 && op1 == const0_rtx
02366 && v9_regcmp_p (compare_code))
02367 {
02368
02369
02370
02371 if (compare_code == NE
02372 && GET_MODE (operands[0]) == DImode
02373 && rtx_equal_p (op0, operands[0]))
02374 {
02375 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
02376 gen_rtx_IF_THEN_ELSE (DImode,
02377 gen_rtx_fmt_ee (compare_code, DImode,
02378 op0, const0_rtx),
02379 const1_rtx,
02380 operands[0])));
02381 return 1;
02382 }
02383
02384 if (reg_overlap_mentioned_p (operands[0], op0))
02385 {
02386
02387
02388 op0 = gen_reg_rtx (GET_MODE (sparc_compare_op0));
02389 emit_move_insn (op0, sparc_compare_op0);
02390 }
02391
02392 emit_insn (gen_rtx_SET (VOIDmode, operands[0], const0_rtx));
02393 if (GET_MODE (op0) != DImode)
02394 {
02395 temp = gen_reg_rtx (DImode);
02396 convert_move (temp, op0, 0);
02397 }
02398 else
02399 temp = op0;
02400 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
02401 gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
02402 gen_rtx_fmt_ee (compare_code, DImode,
02403 temp, const0_rtx),
02404 const1_rtx,
02405 operands[0])));
02406 return 1;
02407 }
02408 else
02409 {
02410 operands[1] = gen_compare_reg (compare_code, op0, op1);
02411
02412 switch (GET_MODE (operands[1]))
02413 {
02414 case CCmode :
02415 case CCXmode :
02416 case CCFPEmode :
02417 case CCFPmode :
02418 break;
02419 default :
02420 abort ();
02421 }
02422 emit_insn (gen_rtx_SET (VOIDmode, operands[0], const0_rtx));
02423 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
02424 gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
02425 gen_rtx_fmt_ee (compare_code,
02426 GET_MODE (operands[1]),
02427 operands[1], const0_rtx),
02428 const1_rtx, operands[0])));
02429 return 1;
02430 }
02431 }
02432
02433
02434
02435
02436
02437 void
02438 emit_v9_brxx_insn (code, op0, label)
02439 enum rtx_code code;
02440 rtx op0, label;
02441 {
02442 emit_jump_insn (gen_rtx_SET (VOIDmode,
02443 pc_rtx,
02444 gen_rtx_IF_THEN_ELSE (VOIDmode,
02445 gen_rtx_fmt_ee (code, GET_MODE (op0),
02446 op0, const0_rtx),
02447 gen_rtx_LABEL_REF (VOIDmode, label),
02448 pc_rtx)));
02449 }
02450
02451
02452
02453
02454
02455 rtx
02456 gen_df_reg (reg, low)
02457 rtx reg;
02458 int low;
02459 {
02460 int regno = REGNO (reg);
02461
02462 if ((WORDS_BIG_ENDIAN == 0) ^ (low != 0))
02463 regno += (TARGET_ARCH64 && regno < 32) ? 1 : 2;
02464 return gen_rtx_REG (DFmode, regno);
02465 }
02466
02467
02468
02469
02470
02471 static void
02472 emit_soft_tfmode_libcall (func_name, nargs, operands)
02473 const char *func_name;
02474 int nargs;
02475 rtx *operands;
02476 {
02477 rtx ret_slot = NULL, arg[3], func_sym;
02478 int i;
02479
02480
02481 if (nargs < 2 || nargs > 3)
02482 abort ();
02483
02484 for (i = 0; i < nargs; ++i)
02485 {
02486 rtx this_arg = operands[i];
02487 rtx this_slot;
02488
02489
02490 if (GET_MODE (this_arg) == TFmode)
02491 {
02492 int force_stack_temp;
02493
02494 force_stack_temp = 0;
02495 if (TARGET_BUGGY_QP_LIB && i == 0)
02496 force_stack_temp = 1;
02497
02498 if (GET_CODE (this_arg) == MEM
02499 && ! force_stack_temp)
02500 this_arg = XEXP (this_arg, 0);
02501 else if (CONSTANT_P (this_arg)
02502 && ! force_stack_temp)
02503 {
02504 this_slot = force_const_mem (TFmode, this_arg);
02505 this_arg = XEXP (this_slot, 0);
02506 }
02507 else
02508 {
02509 this_slot = assign_stack_temp (TFmode, GET_MODE_SIZE (TFmode), 0);
02510
02511
02512 if (i > 0)
02513 emit_move_insn (this_slot, this_arg);
02514 else
02515 ret_slot = this_slot;
02516
02517 this_arg = XEXP (this_slot, 0);
02518 }
02519 }
02520
02521 arg[i] = this_arg;
02522 }
02523
02524 func_sym = gen_rtx_SYMBOL_REF (Pmode, func_name);
02525
02526 if (GET_MODE (operands[0]) == TFmode)
02527 {
02528 if (nargs == 2)
02529 emit_library_call (func_sym, LCT_NORMAL, VOIDmode, 2,
02530 arg[0], GET_MODE (arg[0]),
02531 arg[1], GET_MODE (arg[1]));
02532 else
02533 emit_library_call (func_sym, LCT_NORMAL, VOIDmode, 3,
02534 arg[0], GET_MODE (arg[0]),
02535 arg[1], GET_MODE (arg[1]),
02536 arg[2], GET_MODE (arg[2]));
02537
02538 if (ret_slot)
02539 emit_move_insn (operands[0], ret_slot);
02540 }
02541 else
02542 {
02543 rtx ret;
02544
02545 if (nargs != 2)
02546 abort ();
02547
02548 ret = emit_library_call_value (func_sym, operands[0], LCT_NORMAL,
02549 GET_MODE (operands[0]), 1,
02550 arg[1], GET_MODE (arg[1]));
02551
02552 if (ret != operands[0])
02553 emit_move_insn (operands[0], ret);
02554 }
02555 }
02556
02557
02558
02559 static void
02560 emit_soft_tfmode_binop (code, operands)
02561 enum rtx_code code;
02562 rtx *operands;
02563 {
02564 const char *func;
02565
02566 switch (code)
02567 {
02568 case PLUS:
02569 func = "_Qp_add";
02570 break;
02571 case MINUS:
02572 func = "_Qp_sub";
02573 break;
02574 case MULT:
02575 func = "_Qp_mul";
02576 break;
02577 case DIV:
02578 func = "_Qp_div";
02579 break;
02580 default:
02581 abort ();
02582 }
02583
02584 emit_soft_tfmode_libcall (func, 3, operands);
02585 }
02586
02587 static void
02588 emit_soft_tfmode_unop (code, operands)
02589 enum rtx_code code;
02590 rtx *operands;
02591 {
02592 const char *func;
02593
02594 switch (code)
02595 {
02596 case SQRT:
02597 func = "_Qp_sqrt";
02598 break;
02599 default:
02600 abort ();
02601 }
02602
02603 emit_soft_tfmode_libcall (func, 2, operands);
02604 }
02605
02606 static void
02607 emit_soft_tfmode_cvt (code, operands)
02608 enum rtx_code code;
02609 rtx *operands;
02610 {
02611 const char *func;
02612
02613 switch (code)
02614 {
02615 case FLOAT_EXTEND:
02616 switch (GET_MODE (operands[1]))
02617 {
02618 case SFmode:
02619 func = "_Qp_stoq";
02620 break;
02621 case DFmode:
02622 func = "_Qp_dtoq";
02623 break;
02624 default:
02625 abort ();
02626 }
02627 break;
02628
02629 case FLOAT_TRUNCATE:
02630 switch (GET_MODE (operands[0]))
02631 {
02632 case SFmode:
02633 func = "_Qp_qtos";
02634 break;
02635 case DFmode:
02636 func = "_Qp_qtod";
02637 break;
02638 default:
02639 abort ();
02640 }
02641 break;
02642
02643 case FLOAT:
02644 switch (GET_MODE (operands[1]))
02645 {
02646 case SImode:
02647 func = "_Qp_itoq";
02648 break;
02649 case DImode:
02650 func = "_Qp_xtoq";
02651 break;
02652 default:
02653 abort ();
02654 }
02655 break;
02656
02657 case UNSIGNED_FLOAT:
02658 switch (GET_MODE (operands[1]))
02659 {
02660 case SImode:
02661 func = "_Qp_uitoq";
02662 break;
02663 case DImode:
02664 func = "_Qp_uxtoq";
02665 break;
02666 default:
02667 abort ();
02668 }
02669 break;
02670
02671 case FIX:
02672 switch (GET_MODE (operands[0]))
02673 {
02674 case SImode:
02675 func = "_Qp_qtoi";
02676 break;
02677 case DImode:
02678 func = "_Qp_qtox";
02679 break;
02680 default:
02681 abort ();
02682 }
02683 break;
02684
02685 case UNSIGNED_FIX:
02686 switch (GET_MODE (operands[0]))
02687 {
02688 case SImode:
02689 func = "_Qp_qtoui";
02690 break;
02691 case DImode:
02692 func = "_Qp_qtoux";
02693 break;
02694 default:
02695 abort ();
02696 }
02697 break;
02698
02699 default:
02700 abort ();
02701 }
02702
02703 emit_soft_tfmode_libcall (func, 2, operands);
02704 }
02705
02706
02707
02708
02709 static void
02710 emit_hard_tfmode_operation (code, operands)
02711 enum rtx_code code;
02712 rtx *operands;
02713 {
02714 rtx op, dest;
02715
02716 if (GET_RTX_CLASS (code) == '1')
02717 {
02718 operands[1] = force_reg (GET_MODE (operands[1]), operands[1]);
02719 op = gen_rtx_fmt_e (code, GET_MODE (operands[0]), operands[1]);
02720 }
02721 else
02722 {
02723 operands[1] = force_reg (GET_MODE (operands[1]), operands[1]);
02724 operands[2] = force_reg (GET_MODE (operands[2]), operands[2]);
02725 op = gen_rtx_fmt_ee (code, GET_MODE (operands[0]),
02726 operands[1], operands[2]);
02727 }
02728
02729 if (register_operand (operands[0], VOIDmode))
02730 dest = operands[0];
02731 else
02732 dest = gen_reg_rtx (GET_MODE (operands[0]));
02733
02734 emit_insn (gen_rtx_SET (VOIDmode, dest, op));
02735
02736 if (dest != operands[0])
02737 emit_move_insn (operands[0], dest);
02738 }
02739
02740 void
02741 emit_tfmode_binop (code, operands)
02742 enum rtx_code code;
02743 rtx *operands;
02744 {
02745 if (TARGET_HARD_QUAD)
02746 emit_hard_tfmode_operation (code, operands);
02747 else
02748 emit_soft_tfmode_binop (code, operands);
02749 }
02750
02751 void
02752 emit_tfmode_unop (code, operands)
02753 enum rtx_code code;
02754 rtx *operands;
02755 {
02756 if (TARGET_HARD_QUAD)
02757 emit_hard_tfmode_operation (code, operands);
02758 else
02759 emit_soft_tfmode_unop (code, operands);
02760 }
02761
02762 void
02763 emit_tfmode_cvt (code, operands)
02764 enum rtx_code code;
02765 rtx *operands;
02766 {
02767 if (TARGET_HARD_QUAD)
02768 emit_hard_tfmode_operation (code, operands);
02769 else
02770 emit_soft_tfmode_cvt (code, operands);
02771 }
02772
02773
02774
02775 int
02776 leaf_return_peephole_ok ()
02777 {
02778 return (actual_fsize == 0);
02779 }
02780
02781
02782
02783
02784 int
02785 empty_delay_slot (insn)
02786 rtx insn;
02787 {
02788 rtx seq;
02789
02790
02791 if (PREV_INSN (insn) == NULL)
02792 return 1;
02793
02794 seq = NEXT_INSN (PREV_INSN (insn));
02795 if (GET_CODE (PATTERN (seq)) == SEQUENCE)
02796 return 0;
02797
02798 return 1;
02799 }
02800
02801
02802
02803
02804 int
02805 eligible_for_epilogue_delay (trial, slot)
02806 rtx trial;
02807 int slot;
02808 {
02809 rtx pat, src;
02810
02811 if (slot >= 1)
02812 return 0;
02813
02814 if (GET_CODE (trial) != INSN || GET_CODE (PATTERN (trial)) != SET)
02815 return 0;
02816
02817 if (get_attr_length (trial) != 1)
02818 return 0;
02819
02820
02821
02822 if (num_gfregs)
02823 return 0;
02824
02825
02826
02827 if (current_function_calls_eh_return)
02828 return 0;
02829
02830
02831
02832
02833 if (current_function_uses_only_leaf_regs)
02834 {
02835 if (leaf_return_peephole_ok ())
02836 return ((get_attr_in_uncond_branch_delay (trial)
02837 == IN_BRANCH_DELAY_TRUE));
02838 return 0;
02839 }
02840
02841 pat = PATTERN (trial);
02842
02843
02844
02845 if (GET_CODE (SET_DEST (pat)) != REG
02846 || REGNO (SET_DEST (pat)) < 24)
02847 return 0;
02848
02849
02850
02851
02852 if (REGNO (SET_DEST (pat)) >= 32)
02853 {
02854 if (TARGET_V9 && ! epilogue_renumber (&pat, 1)
02855 && (get_attr_in_uncond_branch_delay (trial) == IN_BRANCH_DELAY_TRUE))
02856 return 1;
02857 return 0;
02858 }
02859
02860
02861
02862
02863 src = SET_SRC (pat);
02864
02865
02866 if (GET_MODE_CLASS (GET_MODE (src)) != MODE_FLOAT
02867 && arith_operand (src, GET_MODE (src)))
02868 {
02869 if (TARGET_ARCH64)
02870 return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (DImode);
02871 else
02872 return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (SImode);
02873 }
02874
02875
02876 else if (GET_MODE_CLASS (GET_MODE (src)) != MODE_FLOAT
02877 && arith_double_operand (src, GET_MODE (src)))
02878 return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (DImode);
02879
02880
02881 else if (! TARGET_FPU && restore_operand (SET_DEST (pat), SFmode)
02882 && register_operand (src, SFmode))
02883 return 1;
02884
02885
02886
02887 else if (TARGET_V9 && ! epilogue_renumber (&pat, 1)
02888 && (get_attr_in_uncond_branch_delay (trial) == IN_BRANCH_DELAY_TRUE))
02889 return 1;
02890
02891
02892 else if (GET_CODE (src) == PLUS
02893 && arith_operand (XEXP (src, 0), SImode)
02894 && arith_operand (XEXP (src, 1), SImode)
02895 && (register_operand (XEXP (src, 0), SImode)
02896 || register_operand (XEXP (src, 1), SImode)))
02897 return 1;
02898
02899
02900 else if (GET_CODE (src) == PLUS
02901 && arith_double_operand (XEXP (src, 0), DImode)
02902 && arith_double_operand (XEXP (src, 1), DImode)
02903 && (register_operand (XEXP (src, 0), DImode)
02904 || register_operand (XEXP (src, 1), DImode)))
02905 return 1;
02906
02907
02908
02909
02910 else if (GET_CODE (src) == LO_SUM
02911 && ! TARGET_CM_MEDMID
02912 && ((register_operand (XEXP (src, 0), SImode)
02913 && immediate_operand (XEXP (src, 1), SImode))
02914 || (TARGET_ARCH64
02915 && register_operand (XEXP (src, 0), DImode)
02916 && immediate_operand (XEXP (src, 1), DImode))))
02917 return 1;
02918
02919
02920 else if (GET_CODE (src) == ASHIFT
02921 && (register_operand (XEXP (src, 0), SImode)
02922 || register_operand (XEXP (src, 0), DImode))
02923 && XEXP (src, 1) == const1_rtx)
02924 return 1;
02925
02926 return 0;
02927 }
02928
02929
02930
02931
02932 int
02933 eligible_for_sibcall_delay (trial)
02934 rtx trial;
02935 {
02936 rtx pat, src;
02937
02938 if (GET_CODE (trial) != INSN || GET_CODE (PATTERN (trial)) != SET)
02939 return 0;
02940
02941 if (get_attr_length (trial) != 1)
02942 return 0;
02943
02944 pat = PATTERN (trial);
02945
02946 if (current_function_uses_only_leaf_regs)
02947 {
02948
02949
02950 if ((TARGET_ARCH64 && ! TARGET_CM_MEDLOW) || flag_pic)
02951 return 0;
02952
02953
02954 if (reg_mentioned_p (gen_rtx_REG (Pmode, 1), pat))
02955 return 0;
02956
02957 return 1;
02958 }
02959
02960
02961
02962 if (GET_CODE (SET_DEST (pat)) != REG
02963 || REGNO (SET_DEST (pat)) < 24
02964 || REGNO (SET_DEST (pat)) >= 32)
02965 return 0;
02966
02967
02968
02969 if (reg_mentioned_p (gen_rtx_REG (Pmode, 15), pat))
02970 return 0;
02971
02972 src = SET_SRC (pat);
02973
02974 if (GET_MODE_CLASS (GET_MODE (src)) != MODE_FLOAT
02975 && arith_operand (src, GET_MODE (src)))
02976 {
02977 if (TARGET_ARCH64)
02978 return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (DImode);
02979 else
02980 return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (SImode);
02981 }
02982
02983 else if (GET_MODE_CLASS (GET_MODE (src)) != MODE_FLOAT
02984 && arith_double_operand (src, GET_MODE (src)))
02985 return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (DImode);
02986
02987 else if (! TARGET_FPU && restore_operand (SET_DEST (pat), SFmode)
02988 && register_operand (src, SFmode))
02989 return 1;
02990
02991 else if (GET_CODE (src) == PLUS
02992 && arith_operand (XEXP (src, 0), SImode)
02993 && arith_operand (XEXP (src, 1), SImode)
02994 && (register_operand (XEXP (src, 0), SImode)
02995 || register_operand (XEXP (src, 1), SImode)))
02996 return 1;
02997
02998 else if (GET_CODE (src) == PLUS
02999 && arith_double_operand (XEXP (src, 0), DImode)
03000 && arith_double_operand (XEXP (src, 1), DImode)
03001 && (register_operand (XEXP (src, 0), DImode)
03002 || register_operand (XEXP (src, 1), DImode)))
03003 return 1;
03004
03005 else if (GET_CODE (src) == LO_SUM
03006 && ! TARGET_CM_MEDMID
03007 && ((register_operand (XEXP (src, 0), SImode)
03008 && immediate_operand (XEXP (src, 1), SImode))
03009 || (TARGET_ARCH64
03010 && register_operand (XEXP (src, 0), DImode)
03011 && immediate_operand (XEXP (src, 1), DImode))))
03012 return 1;
03013
03014 else if (GET_CODE (src) == ASHIFT
03015 && (register_operand (XEXP (src, 0), SImode)
03016 || register_operand (XEXP (src, 0), DImode))
03017 && XEXP (src, 1) == const1_rtx)
03018 return 1;
03019
03020 return 0;
03021 }
03022
03023 static int
03024 check_return_regs (x)
03025 rtx x;
03026 {
03027 switch (GET_CODE (x))
03028 {
03029 case REG:
03030 return IN_OR_GLOBAL_P (x);
03031
03032 case CONST_INT:
03033 case CONST_DOUBLE:
03034 case CONST:
03035 case SYMBOL_REF:
03036 case LABEL_REF:
03037 return 1;
03038
03039 case SET:
03040 case IOR:
03041 case AND:
03042 case XOR:
03043 case PLUS:
03044 case MINUS:
03045 if (check_return_regs (XEXP (x, 1)) == 0)
03046 return 0;
03047 case NOT:
03048 case NEG:
03049 case MEM:
03050 return check_return_regs (XEXP (x, 0));
03051
03052 default:
03053 return 0;
03054 }
03055
03056 }
03057
03058
03059 int
03060 eligible_for_return_delay (trial)
03061 rtx trial;
03062 {
03063 if (GET_CODE (PATTERN (trial)) != SET)
03064 return 0;
03065
03066 return check_return_regs (PATTERN (trial));
03067 }
03068
03069 int
03070 short_branch (uid1, uid2)
03071 int uid1, uid2;
03072 {
03073 int delta = INSN_ADDRESSES (uid1) - INSN_ADDRESSES (uid2);
03074
03075
03076 if (delta >= -1023 && delta <= 1022)
03077 return 1;
03078
03079 return 0;
03080 }
03081
03082
03083
03084
03085 int
03086 reg_unused_after (reg, insn)
03087 rtx reg;
03088 rtx insn;
03089 {
03090 enum rtx_code code, prev_code = UNKNOWN;
03091
03092 while ((insn = NEXT_INSN (insn)))
03093 {
03094 if (prev_code == CALL_INSN && call_used_regs[REGNO (reg)])
03095 return 1;
03096
03097 code = GET_CODE (insn);
03098 if (GET_CODE (insn) == CODE_LABEL)
03099 return 1;
03100
03101 if (GET_RTX_CLASS (code) == 'i')
03102 {
03103 rtx set = single_set (insn);
03104 int in_src = set && reg_overlap_mentioned_p (reg, SET_SRC (set));
03105 if (set && in_src)
03106 return 0;
03107 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
03108 return 1;
03109 if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
03110 return 0;
03111 }
03112 prev_code = code;
03113 }
03114 return 1;
03115 }
03116
03117
03118 static rtx global_offset_table;
03119
03120
03121 static rtx get_pc_symbol;
03122 static char get_pc_symbol_name[256];
03123
03124
03125
03126 int
03127 check_pic (i)
03128 int i;
03129 {
03130 switch (flag_pic)
03131 {
03132 case 1:
03133 if (GET_CODE (recog_data.operand[i]) == SYMBOL_REF
03134 || (GET_CODE (recog_data.operand[i]) == CONST
03135 && ! (GET_CODE (XEXP (recog_data.operand[i], 0)) == MINUS
03136 && (XEXP (XEXP (recog_data.operand[i], 0), 0)
03137 == global_offset_table)
03138 && (GET_CODE (XEXP (XEXP (recog_data.operand[i], 0), 1))
03139 == CONST))))
03140 abort ();
03141 case 2:
03142 default:
03143 return 1;
03144 }
03145 }
03146
03147
03148
03149
03150 int
03151 pic_address_needs_scratch (x)
03152 rtx x;
03153 {
03154
03155 if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS
03156 && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
03157 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
03158 && ! SMALL_INT (XEXP (XEXP (x, 0), 1)))
03159 return 1;
03160
03161 return 0;
03162 }
03163
03164
03165
03166
03167
03168
03169 rtx
03170 legitimize_pic_address (orig, mode, reg)
03171 rtx orig;
03172 enum machine_mode mode ATTRIBUTE_UNUSED;
03173 rtx reg;
03174 {
03175 if (GET_CODE (orig) == SYMBOL_REF)
03176 {
03177 rtx pic_ref, address;
03178 rtx insn;
03179
03180 if (reg == 0)
03181 {
03182 if (reload_in_progress || reload_completed)
03183 abort ();
03184 else
03185 reg = gen_reg_rtx (Pmode);
03186 }
03187
03188 if (flag_pic == 2)
03189 {
03190
03191
03192
03193 rtx temp_reg = ((reload_in_progress || reload_completed)
03194 ? reg : gen_reg_rtx (Pmode));
03195
03196
03197
03198
03199
03200 if (Pmode == SImode)
03201 {
03202 emit_insn (gen_movsi_high_pic (temp_reg, orig));
03203 emit_insn (gen_movsi_lo_sum_pic (temp_reg, temp_reg, orig));
03204 }
03205 else
03206 {
03207 emit_insn (gen_movdi_high_pic (temp_reg, orig));
03208 emit_insn (gen_movdi_lo_sum_pic (temp_reg, temp_reg, orig));
03209 }
03210 address = temp_reg;
03211 }
03212 else
03213 address = orig;
03214
03215 pic_ref = gen_rtx_MEM (Pmode,
03216 gen_rtx_PLUS (Pmode,
03217 pic_offset_table_rtx, address));
03218 current_function_uses_pic_offset_table = 1;
03219 RTX_UNCHANGING_P (pic_ref) = 1;
03220 insn = emit_move_insn (reg, pic_ref);
03221
03222
03223 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, orig,
03224 REG_NOTES (insn));
03225 return reg;
03226 }
03227 else if (GET_CODE (orig) == CONST)
03228 {
03229 rtx base, offset;
03230
03231 if (GET_CODE (XEXP (orig, 0)) == PLUS
03232 && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
03233 return orig;
03234
03235 if (reg == 0)
03236 {
03237 if (reload_in_progress || reload_completed)
03238 abort ();
03239 else
03240 reg = gen_reg_rtx (Pmode);
03241 }
03242
03243 if (GET_CODE (XEXP (orig, 0)) == PLUS)
03244 {
03245 base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
03246 offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
03247 base == reg ? 0 : reg);
03248 }
03249 else
03250 abort ();
03251
03252 if (GET_CODE (offset) == CONST_INT)
03253 {
03254 if (SMALL_INT (offset))
03255 return plus_constant (base, INTVAL (offset));
03256 else if (! reload_in_progress && ! reload_completed)
03257 offset = force_reg (Pmode, offset);
03258 else
03259
03260 abort ();
03261 }
03262 return gen_rtx_PLUS (Pmode, base, offset);
03263 }
03264 else if (GET_CODE (orig) == LABEL_REF)
03265
03266
03267
03268 current_function_uses_pic_offset_table = 1;
03269
03270 return orig;
03271 }
03272
03273
03274
03275 void
03276 load_pic_register ()
03277 {
03278
03279 int orig_flag_pic = flag_pic;
03280
03281 if (! flag_pic)
03282 abort ();
03283
03284
03285 if (get_pc_symbol_name[0] == 0)
03286 {
03287 int align;
03288
03289 ASM_GENERATE_INTERNAL_LABEL (get_pc_symbol_name, "LGETPC", 0);
03290 text_section ();
03291
03292 align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT);
03293 if (align > 0)
03294 ASM_OUTPUT_ALIGN (asm_out_file, align);
03295 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LGETPC", 0);
03296 fputs ("\tretl\n\tadd\t%o7, %l7, %l7\n", asm_out_file);
03297 }
03298
03299
03300
03301 global_offset_table = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
03302 get_pc_symbol = gen_rtx_SYMBOL_REF (Pmode, get_pc_symbol_name);
03303 flag_pic = 0;
03304
03305 emit_insn (gen_get_pc (pic_offset_table_rtx, global_offset_table,
03306 get_pc_symbol));
03307
03308 flag_pic = orig_flag_pic;
03309
03310
03311
03312
03313
03314 emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
03315 }
03316
03317
03318
03319
03320 int
03321 mem_min_alignment (mem, desired)
03322 rtx mem;
03323 int desired;
03324 {
03325 rtx addr, base, offset;
03326
03327
03328 if (GET_CODE (mem) != MEM)
03329 return 0;
03330
03331 addr = XEXP (mem, 0);
03332 base = offset = NULL_RTX;
03333 if (GET_CODE (addr) == PLUS)
03334 {
03335 if (GET_CODE (XEXP (addr, 0)) == REG)
03336 {
03337 base = XEXP (addr, 0);
03338
03339
03340
03341
03342
03343 if (GET_CODE (XEXP (addr, 1)) == CONST_INT)
03344 offset = XEXP (addr, 1);
03345 else
03346 offset = const0_rtx;
03347 }
03348 }
03349 else if (GET_CODE (addr) == REG)
03350 {
03351 base = addr;
03352 offset = const0_rtx;
03353 }
03354
03355 if (base != NULL_RTX)
03356 {
03357 int regno = REGNO (base);
03358
03359 if (regno != HARD_FRAME_POINTER_REGNUM && regno != STACK_POINTER_REGNUM)
03360 {
03361
03362
03363
03364
03365
03366 if (((cfun != 0
03367 && REGNO_POINTER_ALIGN (regno) >= desired * BITS_PER_UNIT)
03368 || (optimize && reload_completed))
03369 && (INTVAL (offset) & (desired - 1)) == 0)
03370 return 1;
03371 }
03372 else
03373 {
03374 if (((INTVAL (offset) - SPARC_STACK_BIAS) & (desired - 1)) == 0)
03375 return 1;
03376 }
03377 }
03378 else if (! TARGET_UNALIGNED_DOUBLES
03379 || CONSTANT_P (addr)
03380 || GET_CODE (addr) == LO_SUM)
03381 {
03382
03383
03384
03385 return 1;
03386 }
03387
03388
03389 return 0;
03390 }
03391
03392
03393
03394
03395
03396
03397
03398
03399
03400
03401
03402 enum sparc_mode_class {
03403 S_MODE, D_MODE, T_MODE, O_MODE,
03404 SF_MODE, DF_MODE, TF_MODE, OF_MODE,
03405 CC_MODE, CCFP_MODE
03406 };
03407
03408
03409 #define S_MODES ((1 << (int) S_MODE) | (1 << (int) SF_MODE))
03410
03411
03412 #define D_MODES (S_MODES | (1 << (int) D_MODE) | (1 << DF_MODE))
03413
03414
03415 #define T_MODES (D_MODES | (1 << (int) T_MODE) | (1 << (int) TF_MODE))
03416
03417
03418 #define O_MODES (T_MODES | (1 << (int) O_MODE) | (1 << (int) OF_MODE))
03419
03420
03421
03422
03423 #define SF_MODES (S_MODES)
03424
03425
03426 #define DF_MODES (S_MODES | D_MODES)
03427
03428
03429 #define DF_MODES_NO_S ((1 << (int) D_MODE) | (1 << (int) DF_MODE))
03430
03431
03432 #define TF_ONLY_MODES (1 << (int) TF_MODE)
03433
03434
03435 #define TF_MODES (DF_MODES | TF_ONLY_MODES)
03436
03437
03438 #define TF_MODES_NO_S (DF_MODES_NO_S | TF_ONLY_MODES)
03439
03440
03441 #define OF_ONLY_MODES (1 << (int) OF_MODE)
03442
03443
03444 #define OF_MODES (TF_MODES | OF_ONLY_MODES)
03445
03446 #define OF_MODES_NO_S (TF_MODES_NO_S | OF_ONLY_MODES)
03447
03448
03449 #define CC_MODES (1 << (int) CC_MODE)
03450 #define CCFP_MODES (1 << (int) CCFP_MODE)
03451
03452
03453
03454
03455
03456
03457
03458
03459 const int *hard_regno_mode_classes;
03460
03461 static const int hard_32bit_mode_classes[] = {
03462 S_MODES, S_MODES, T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES,
03463 T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, D_MODES, S_MODES,
03464 T_MODES, S_MODES, T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES,
03465 T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, D_MODES, S_MODES,
03466
03467 OF_MODES, SF_MODES, DF_MODES, SF_MODES, OF_MODES, SF_MODES, DF_MODES, SF_MODES,
03468 OF_MODES, SF_MODES, DF_MODES, SF_MODES, OF_MODES, SF_MODES, DF_MODES, SF_MODES,
03469 OF_MODES, SF_MODES, DF_MODES, SF_MODES, OF_MODES, SF_MODES, DF_MODES, SF_MODES,
03470 OF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES,
03471
03472
03473
03474 OF_MODES_NO_S, 0, DF_MODES_NO_S, 0, OF_MODES_NO_S, 0, DF_MODES_NO_S, 0,
03475 OF_MODES_NO_S, 0, DF_MODES_NO_S, 0, OF_MODES_NO_S, 0, DF_MODES_NO_S, 0,
03476 OF_MODES_NO_S, 0, DF_MODES_NO_S, 0, OF_MODES_NO_S, 0, DF_MODES_NO_S, 0,
03477 OF_MODES_NO_S, 0, DF_MODES_NO_S, 0, TF_MODES_NO_S, 0, DF_MODES_NO_S, 0,
03478
03479
03480 CCFP_MODES, CCFP_MODES, CCFP_MODES, CCFP_MODES,
03481
03482
03483 CC_MODES
03484 };
03485
03486 static const int hard_64bit_mode_classes[] = {
03487 D_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES,
03488 O_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES,
03489 T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES,
03490 O_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES,
03491
03492 OF_MODES, SF_MODES, DF_MODES, SF_MODES, OF_MODES, SF_MODES, DF_MODES, SF_MODES,
03493 OF_MODES, SF_MODES, DF_MODES, SF_MODES, OF_MODES, SF_MODES, DF_MODES, SF_MODES,
03494 OF_MODES, SF_MODES, DF_MODES, SF_MODES, OF_MODES, SF_MODES, DF_MODES, SF_MODES,
03495 OF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES,
03496
03497
03498
03499 OF_MODES_NO_S, 0, DF_MODES_NO_S, 0, OF_MODES_NO_S, 0, DF_MODES_NO_S, 0,
03500 OF_MODES_NO_S, 0, DF_MODES_NO_S, 0, OF_MODES_NO_S, 0, DF_MODES_NO_S, 0,
03501 OF_MODES_NO_S, 0, DF_MODES_NO_S, 0, OF_MODES_NO_S, 0, DF_MODES_NO_S, 0,
03502 OF_MODES_NO_S, 0, DF_MODES_NO_S, 0, TF_MODES_NO_S, 0, DF_MODES_NO_S, 0,
03503
03504
03505 CCFP_MODES, CCFP_MODES, CCFP_MODES, CCFP_MODES,
03506
03507
03508 CC_MODES
03509 };
03510
03511 int sparc_mode_class [NUM_MACHINE_MODES];
03512
03513 enum reg_class sparc_regno_reg_class[FIRST_PSEUDO_REGISTER];
03514
03515 static void
03516 sparc_init_modes ()
03517 {
03518 int i;
03519
03520 for (i = 0; i < NUM_MACHINE_MODES; i++)
03521 {
03522 switch (GET_MODE_CLASS (i))
03523 {
03524 case MODE_INT:
03525 case MODE_PARTIAL_INT:
03526 case MODE_COMPLEX_INT:
03527 if (GET_MODE_SIZE (i) <= 4)
03528 sparc_mode_class[i] = 1 << (int) S_MODE;
03529 else if (GET_MODE_SIZE (i) == 8)
03530 sparc_mode_class[i] = 1 << (int) D_MODE;
03531 else if (GET_MODE_SIZE (i) == 16)
03532 sparc_mode_class[i] = 1 << (int) T_MODE;
03533 else if (GET_MODE_SIZE (i) == 32)
03534 sparc_mode_class[i] = 1 << (int) O_MODE;
03535 else
03536 sparc_mode_class[i] = 0;
03537 break;
03538 case MODE_FLOAT:
03539 case MODE_COMPLEX_FLOAT:
03540 if (GET_MODE_SIZE (i) <= 4)
03541 sparc_mode_class[i] = 1 << (int) SF_MODE;
03542 else if (GET_MODE_SIZE (i) == 8)
03543 sparc_mode_class[i] = 1 << (int) DF_MODE;
03544 else if (GET_MODE_SIZE (i) == 16)
03545 sparc_mode_class[i] = 1 << (int) TF_MODE;
03546 else if (GET_MODE_SIZE (i) == 32)
03547 sparc_mode_class[i] = 1 << (int) OF_MODE;
03548 else
03549 sparc_mode_class[i] = 0;
03550 break;
03551 case MODE_CC:
03552 default:
03553
03554
03555 if (i == (int) CCFPmode || i == (int) CCFPEmode)
03556 sparc_mode_class[i] = 1 << (int) CCFP_MODE;
03557 else if (i == (int) CCmode || i == (int) CC_NOOVmode
03558 || i == (int) CCXmode || i == (int) CCX_NOOVmode)
03559 sparc_mode_class[i] = 1 << (int) CC_MODE;
03560 else
03561 sparc_mode_class[i] = 0;
03562 break;
03563 }
03564 }
03565
03566 if (TARGET_ARCH64)
03567 hard_regno_mode_classes = hard_64bit_mode_classes;
03568 else
03569 hard_regno_mode_classes = hard_32bit_mode_classes;
03570
03571
03572 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
03573 {
03574 if (i < 16 && TARGET_V8PLUS)
03575 sparc_regno_reg_class[i] = I64_REGS;
03576 else if (i < 32 || i == FRAME_POINTER_REGNUM)
03577 sparc_regno_reg_class[i] = GENERAL_REGS;
03578 else if (i < 64)
03579 sparc_regno_reg_class[i] = FP_REGS;
03580 else if (i < 96)
03581 sparc_regno_reg_class[i] = EXTRA_FP_REGS;
03582 else if (i < 100)
03583 sparc_regno_reg_class[i] = FPCC_REGS;
03584 else
03585 sparc_regno_reg_class[i] = NO_REGS;
03586 }
03587 }
03588
03589
03590
03591
03592
03593 static int
03594 save_regs (file, low, high, base, offset, n_regs, real_offset)
03595 FILE *file;
03596 int low, high;
03597 const char *base;
03598 int offset;
03599 int n_regs;
03600 int real_offset;
03601 {
03602 int i;
03603
03604 if (TARGET_ARCH64 && high <= 32)
03605 {
03606 for (i = low; i < high; i++)
03607 {
03608 if (regs_ever_live[i] && ! call_used_regs[i])
03609 {
03610 fprintf (file, "\tstx\t%s, [%s+%d]\n",
03611 reg_names[i], base, offset + 4 * n_regs);
03612 if (dwarf2out_do_frame ())
03613 dwarf2out_reg_save ("", i, real_offset + 4 * n_regs);
03614 n_regs += 2;
03615 }
03616 }
03617 }
03618 else
03619 {
03620 for (i = low; i < high; i += 2)
03621 {
03622 if (regs_ever_live[i] && ! call_used_regs[i])
03623 {
03624 if (regs_ever_live[i+1] && ! call_used_regs[i+1])
03625 {
03626 fprintf (file, "\tstd\t%s, [%s+%d]\n",
03627 reg_names[i], base, offset + 4 * n_regs);
03628 if (dwarf2out_do_frame ())
03629 {
03630 char *l = dwarf2out_cfi_label ();
03631 dwarf2out_reg_save (l, i, real_offset + 4 * n_regs);
03632 dwarf2out_reg_save (l, i+1, real_offset + 4 * n_regs + 4);
03633 }
03634 n_regs += 2;
03635 }
03636 else
03637 {
03638 fprintf (file, "\tst\t%s, [%s+%d]\n",
03639 reg_names[i], base, offset + 4 * n_regs);
03640 if (dwarf2out_do_frame ())
03641 dwarf2out_reg_save ("", i, real_offset + 4 * n_regs);
03642 n_regs += 2;
03643 }
03644 }
03645 else
03646 {
03647 if (regs_ever_live[i+1] && ! call_used_regs[i+1])
03648 {
03649 fprintf (file, "\tst\t%s, [%s+%d]\n",
03650 reg_names[i+1], base, offset + 4 * n_regs + 4);
03651 if (dwarf2out_do_frame ())
03652 dwarf2out_reg_save ("", i + 1, real_offset + 4 * n_regs + 4);
03653 n_regs += 2;
03654 }
03655 }
03656 }
03657 }
03658 return n_regs;
03659 }
03660
03661
03662
03663
03664
03665
03666 static int
03667 restore_regs (file, low, high, base, offset, n_regs)
03668 FILE *file;
03669 int low, high;
03670 const char *base;
03671 int offset;
03672 int n_regs;
03673 {
03674 int i;
03675
03676 if (TARGET_ARCH64 && high <= 32)
03677 {
03678 for (i = low; i < high; i++)
03679 {
03680 if (regs_ever_live[i] && ! call_used_regs[i])
03681 fprintf (file, "\tldx\t[%s+%d], %s\n",
03682 base, offset + 4 * n_regs, reg_names[i]),
03683 n_regs += 2;
03684 }
03685 }
03686 else
03687 {
03688 for (i = low; i < high; i += 2)
03689 {
03690 if (regs_ever_live[i] && ! call_used_regs[i])
03691 if (regs_ever_live[i+1] && ! call_used_regs[i+1])
03692 fprintf (file, "\tldd\t[%s+%d], %s\n",
03693 base, offset + 4 * n_regs, reg_names[i]),
03694 n_regs += 2;
03695 else
03696 fprintf (file, "\tld\t[%s+%d], %s\n",
03697 base, offset + 4 * n_regs, reg_names[i]),
03698 n_regs += 2;
03699 else if (regs_ever_live[i+1] && ! call_used_regs[i+1])
03700 fprintf (file, "\tld\t[%s+%d], %s\n",
03701 base, offset + 4 * n_regs + 4, reg_names[i+1]),
03702 n_regs += 2;
03703 }
03704 }
03705 return n_regs;
03706 }
03707
03708
03709
03710
03711 int
03712 compute_frame_size (size, leaf_function)
03713 int size;
03714 int leaf_function;
03715 {
03716 int n_regs = 0, i;
03717 int outgoing_args_size = (current_function_outgoing_args_size
03718 + REG_PARM_STACK_SPACE (current_function_decl));
03719
03720
03721
03722
03723 if (TARGET_ARCH64)
03724 {
03725 for (i = 0; i < 8; i++)
03726 if (regs_ever_live[i] && ! call_used_regs[i])
03727 n_regs += 2;
03728 }
03729 else
03730 {
03731 for (i = 0; i < 8; i += 2)
03732 if ((regs_ever_live[i] && ! call_used_regs[i])
03733 || (regs_ever_live[i+1] && ! call_used_regs[i+1]))
03734 n_regs += 2;
03735 }
03736
03737 for (i = 32; i < (TARGET_V9 ? 96 : 64); i += 2)
03738 if ((regs_ever_live[i] && ! call_used_regs[i])
03739 || (regs_ever_live[i+1] && ! call_used_regs[i+1]))
03740 n_regs += 2;
03741
03742
03743 num_gfregs = n_regs;
03744
03745 if (leaf_function && n_regs == 0
03746 && size == 0 && current_function_outgoing_args_size == 0)
03747 {
03748 actual_fsize = apparent_fsize = 0;
03749 }
03750 else
03751 {
03752
03753 apparent_fsize = (size - STARTING_FRAME_OFFSET + 7) & -8;
03754 apparent_fsize += n_regs * 4;
03755 actual_fsize = apparent_fsize + ((outgoing_args_size + 7) & -8);
03756 }
03757
03758
03759
03760
03761
03762 if (leaf_function == 0 || size > 0)
03763 actual_fsize += (16 * UNITS_PER_WORD) + (TARGET_ARCH64 ? 0 : 8);
03764
03765 return SPARC_STACK_ALIGN (actual_fsize);
03766 }
03767
03768
03769
03770
03771 static void
03772 build_big_number (file, num, reg)
03773 FILE *file;
03774 int num;
03775 const char *reg;
03776 {
03777 if (num >= 0 || ! TARGET_ARCH64)
03778 {
03779 fprintf (file, "\tsethi\t%%hi(%d), %s\n", num, reg);
03780 if ((num & 0x3ff) != 0)
03781 fprintf (file, "\tor\t%s, %%lo(%d), %s\n", reg, num, reg);
03782 }
03783 else
03784 {
03785
03786
03787
03788
03789
03790 int asize = num;
03791 int inv = ~asize;
03792 int low = -0x400 + (asize & 0x3FF);
03793
03794 fprintf (file, "\tsethi\t%%hi(%d), %s\n\txor\t%s, %d, %s\n",
03795 inv, reg, reg, low, reg);
03796 }
03797 }
03798
03799
03800 void
03801 sparc_output_scratch_registers (file)
03802 FILE *file ATTRIBUTE_UNUSED;
03803 {
03804 #ifdef HAVE_AS_REGISTER_PSEUDO_OP
03805 int i;
03806
03807 if (TARGET_ARCH32)
03808 return;
03809
03810
03811
03812 for (i = 2; i < 8; i++)
03813 {
03814 if (regs_ever_live [i]
03815 && ! sparc_hard_reg_printed [i])
03816 {
03817 sparc_hard_reg_printed [i] = 1;
03818 fprintf (file, "\t.register\t%%g%d, #scratch\n", i);
03819 }
03820 if (i == 3) i = 5;
03821 }
03822 #endif
03823 }
03824
03825
03826
03827
03828
03829
03830
03831
03832
03833
03834
03835
03836
03837
03838
03839
03840
03841 static void
03842 sparc_output_function_prologue (file, size)
03843 FILE *file;
03844 HOST_WIDE_INT size;
03845 {
03846 if (TARGET_FLAT)
03847 sparc_flat_function_prologue (file, size);
03848 else
03849 sparc_nonflat_function_prologue (file, size,
03850 current_function_uses_only_leaf_regs);
03851 }
03852
03853
03854
03855 static void
03856 sparc_nonflat_function_prologue (file, size, leaf_function)
03857 FILE *file;
03858 HOST_WIDE_INT size;
03859 int leaf_function;
03860 {
03861 sparc_output_scratch_registers (file);
03862
03863
03864
03865 actual_fsize = compute_frame_size (size, leaf_function);
03866
03867 if (leaf_function)
03868 {
03869 frame_base_name = "%sp";
03870 frame_base_offset = actual_fsize + SPARC_STACK_BIAS;
03871 }
03872 else
03873 {
03874 frame_base_name = "%fp";
03875 frame_base_offset = SPARC_STACK_BIAS;
03876 }
03877
03878
03879 fprintf (file, "\t%s#PROLOGUE# 0\n", ASM_COMMENT_START);
03880
03881 if (actual_fsize == 0)
03882 ;
03883 else if (! leaf_function)
03884 {
03885 if (actual_fsize <= 4096)
03886 fprintf (file, "\tsave\t%%sp, -%d, %%sp\n", actual_fsize);
03887 else if (actual_fsize <= 8192)
03888 {
03889 fprintf (file, "\tsave\t%%sp, -4096, %%sp\n");
03890 fprintf (file, "\tadd\t%%sp, -%d, %%sp\n", actual_fsize - 4096);
03891 }
03892 else
03893 {
03894 build_big_number (file, -actual_fsize, "%g1");
03895 fprintf (file, "\tsave\t%%sp, %%g1, %%sp\n");
03896 }
03897 }
03898 else
03899 {
03900 if (actual_fsize <= 4096)
03901 fprintf (file, "\tadd\t%%sp, -%d, %%sp\n", actual_fsize);
03902 else if (actual_fsize <= 8192)
03903 {
03904 fprintf (file, "\tadd\t%%sp, -4096, %%sp\n");
03905 fprintf (file, "\tadd\t%%sp, -%d, %%sp\n", actual_fsize - 4096);
03906 }
03907 else
03908 {
03909 build_big_number (file, -actual_fsize, "%g1");
03910 fprintf (file, "\tadd\t%%sp, %%g1, %%sp\n");
03911 }
03912 }
03913
03914 if (dwarf2out_do_frame () && actual_fsize)
03915 {
03916 char *label = dwarf2out_cfi_label ();
03917
03918
03919 dwarf2out_def_cfa (label, (leaf_function ? STACK_POINTER_REGNUM
03920 : HARD_FRAME_POINTER_REGNUM),
03921 frame_base_offset);
03922
03923 if (! leaf_function)
03924 {
03925
03926
03927
03928 dwarf2out_window_save (label);
03929
03930
03931 dwarf2out_return_reg (label, 31);
03932 }
03933 }
03934
03935
03936 if (! flag_pic)
03937 fprintf (file, "\t%s#PROLOGUE# 1\n", ASM_COMMENT_START);
03938
03939
03940 if (num_gfregs)
03941 {
03942 int offset, real_offset, n_regs;
03943 const char *base;
03944
03945 real_offset = -apparent_fsize;
03946 offset = -apparent_fsize + frame_base_offset;
03947 if (offset < -4096 || offset + num_gfregs * 4 > 4096)
03948 {
03949
03950
03951
03952
03953
03954
03955 build_big_number (file, offset, "%g1");
03956 fprintf (file, "\tadd\t%s, %%g1, %%g1\n", frame_base_name);
03957 base = "%g1";
03958 offset = 0;
03959 }
03960 else
03961 {
03962 base = frame_base_name;
03963 }
03964
03965 n_regs = save_regs (file, 0, 8, base, offset, 0, real_offset);
03966 save_regs (file, 32, TARGET_V9 ? 96 : 64, base, offset, n_regs,
03967 real_offset);
03968 }
03969 }
03970
03971
03972
03973 static void
03974 output_restore_regs (file, leaf_function)
03975 FILE *file;
03976 int leaf_function ATTRIBUTE_UNUSED;
03977 {
03978 int offset, n_regs;
03979 const char *base;
03980
03981 offset = -apparent_fsize + frame_base_offset;
03982 if (offset < -4096 || offset + num_gfregs * 4 > 4096 - 8 )
03983 {
03984 build_big_number (file, offset, "%g1");
03985 fprintf (file, "\tadd\t%s, %%g1, %%g1\n", frame_base_name);
03986 base = "%g1";
03987 offset = 0;
03988 }
03989 else
03990 {
03991 base = frame_base_name;
03992 }
03993
03994 n_regs = restore_regs (file, 0, 8, base, offset, 0);
03995 restore_regs (file, 32, TARGET_V9 ? 96 : 64, base, offset, n_regs);
03996 }
03997
03998
03999
04000
04001
04002
04003
04004
04005
04006 static void
04007 sparc_output_function_epilogue (file, size)
04008 FILE *file;
04009 HOST_WIDE_INT size;
04010 {
04011 if (TARGET_FLAT)
04012 sparc_flat_function_epilogue (file, size);
04013 else
04014 sparc_nonflat_function_epilogue (file, size,
04015 current_function_uses_only_leaf_regs);
04016 }
04017
04018
04019
04020 static void
04021 sparc_nonflat_function_epilogue (file, size, leaf_function)
04022 FILE *file;
04023 HOST_WIDE_INT size ATTRIBUTE_UNUSED;
04024 int leaf_function;
04025 {
04026 const char *ret;
04027
04028 if (current_function_epilogue_delay_list == 0)
04029 {
04030
04031
04032
04033
04034
04035
04036
04037
04038 rtx insn;
04039
04040 fputs("\tnop\n", file);
04041
04042 insn = get_last_insn ();
04043 if (GET_CODE (insn) == NOTE)
04044 insn = prev_nonnote_insn (insn);
04045 if (insn && GET_CODE (insn) == BARRIER)
04046 goto output_vectors;
04047 }
04048
04049 if (num_gfregs)
04050 output_restore_regs (file, leaf_function);
04051
04052
04053 if (leaf_function)
04054 ret = (SKIP_CALLERS_UNIMP_P ? "jmp\t%o7+12" : "retl");
04055 else
04056 ret = (SKIP_CALLERS_UNIMP_P ? "jmp\t%i7+12" : "ret");
04057
04058 if (! leaf_function)
04059 {
04060 if (current_function_calls_eh_return)
04061 {
04062 if (current_function_epilogue_delay_list)
04063 abort ();
04064 if (SKIP_CALLERS_UNIMP_P)
04065 abort ();
04066
04067 fputs ("\trestore\n\tretl\n\tadd\t%sp, %g1, %sp\n", file);
04068 }
04069
04070 else if (current_function_epilogue_delay_list)
04071 {
04072 rtx delay = PATTERN (XEXP (current_function_epilogue_delay_list, 0));
04073
04074 if (TARGET_V9 && ! epilogue_renumber (&delay, 1))
04075 {
04076 epilogue_renumber (&delay, 0);
04077 fputs (SKIP_CALLERS_UNIMP_P
04078 ? "\treturn\t%i7+12\n"
04079 : "\treturn\t%i7+8\n", file);
04080 final_scan_insn (XEXP (current_function_epilogue_delay_list, 0),
04081 file, 1, 0, 0);
04082 }
04083 else
04084 {
04085 rtx insn, src;
04086
04087 if (GET_CODE (delay) != SET)
04088 abort();
04089
04090 src = SET_SRC (delay);
04091 if (GET_CODE (src) == ASHIFT)
04092 {
04093 if (XEXP (src, 1) != const1_rtx)
04094 abort();
04095 SET_SRC (delay)
04096 = gen_rtx_PLUS (GET_MODE (src), XEXP (src, 0),
04097 XEXP (src, 0));
04098 }
04099
04100 insn = gen_rtx_PARALLEL (VOIDmode,
04101 gen_rtvec (2, delay,
04102 gen_rtx_RETURN (VOIDmode)));
04103 insn = emit_jump_insn (insn);
04104
04105 sparc_emitting_epilogue = true;
04106 final_scan_insn (insn, file, 1, 0, 1);
04107 sparc_emitting_epilogue = false;
04108 }
04109 }
04110 else if (TARGET_V9 && ! SKIP_CALLERS_UNIMP_P)
04111 fputs ("\treturn\t%i7+8\n\tnop\n", file);
04112 else
04113 fprintf (file, "\t%s\n\trestore\n", ret);
04114 }
04115
04116 else if (current_function_calls_eh_return)
04117 abort ();
04118 else if (current_function_epilogue_delay_list)
04119 {
04120
04121
04122
04123
04124 if (actual_fsize != 0)
04125 abort ();
04126 fprintf (file, "\t%s\n", ret);
04127 final_scan_insn (XEXP (current_function_epilogue_delay_list, 0),
04128 file, 1, 0, 1);
04129 }
04130
04131
04132 else if (actual_fsize == 0)
04133 fprintf (file, "\t%s\n\tnop\n", ret);
04134 else if (actual_fsize <= 4096)
04135 fprintf (file, "\t%s\n\tsub\t%%sp, -%d, %%sp\n", ret, actual_fsize);
04136 else if (actual_fsize <= 8192)
04137 fprintf (file, "\tsub\t%%sp, -4096, %%sp\n\t%s\n\tsub\t%%sp, -%d, %%sp\n",
04138 ret, actual_fsize - 4096);
04139 else if ((actual_fsize & 0x3ff) == 0)
04140 fprintf (file, "\tsethi\t%%hi(%d), %%g1\n\t%s\n\tadd\t%%sp, %%g1, %%sp\n",
04141 actual_fsize, ret);
04142 else
04143 fprintf (file, "\tsethi\t%%hi(%d), %%g1\n\tor\t%%g1, %%lo(%d), %%g1\n\t%s\n\tadd\t%%sp, %%g1, %%sp\n",
04144 actual_fsize, actual_fsize, ret);
04145
04146 output_vectors:
04147 sparc_output_deferred_case_vectors ();
04148 }
04149
04150
04151
04152 const char *
04153 output_sibcall (insn, call_operand)
04154 rtx insn, call_operand;
04155 {
04156 int leaf_regs = current_function_uses_only_leaf_regs;
04157 rtx operands[3];
04158 int delay_slot = dbr_sequence_length () > 0;
04159
04160 if (num_gfregs)
04161 {
04162
04163
04164
04165 if (delay_slot)
04166 {
04167 rtx delay = NEXT_INSN (insn);
04168
04169 if (! delay)
04170 abort ();
04171
04172 final_scan_insn (delay, asm_out_file, 1, 0, 1);
04173 PATTERN (delay) = gen_blockage ();
04174 INSN_CODE (delay) = -1;
04175 delay_slot = 0;
04176 }
04177 output_restore_regs (asm_out_file, leaf_regs);
04178 }
04179
04180 operands[0] = call_operand;
04181
04182 if (leaf_regs)
04183 {
04184 #ifdef HAVE_AS_RELAX_OPTION
04185
04186
04187
04188
04189 int spare_slot = 0;
04190 #else
04191 int spare_slot = ((TARGET_ARCH32 || TARGET_CM_MEDLOW) && ! flag_pic);
04192 #endif
04193 int size = 0;
04194
04195 if ((actual_fsize || ! spare_slot) && delay_slot)
04196 {
04197 rtx delay = NEXT_INSN (insn);
04198
04199 if (! delay)
04200 abort ();
04201
04202 final_scan_insn (delay, asm_out_file, 1, 0, 1);
04203 PATTERN (delay) = gen_blockage ();
04204 INSN_CODE (delay) = -1;
04205 delay_slot = 0;
04206 }
04207 if (actual_fsize)
04208 {
04209 if (actual_fsize <= 4096)
04210 size = actual_fsize;
04211 else if (actual_fsize <= 8192)
04212 {
04213 fputs ("\tsub\t%sp, -4096, %sp\n", asm_out_file);
04214 size = actual_fsize - 4096;
04215 }
04216 else if ((actual_fsize & 0x3ff) == 0)
04217 fprintf (asm_out_file,
04218 "\tsethi\t%%hi(%d), %%g1\n\tadd\t%%sp, %%g1, %%sp\n",
04219 actual_fsize);
04220 else
04221 {
04222 fprintf (asm_out_file,
04223 "\tsethi\t%%hi(%d), %%g1\n\tor\t%%g1, %%lo(%d), %%g1\n",
04224 actual_fsize, actual_fsize);
04225 fputs ("\tadd\t%%sp, %%g1, %%sp\n", asm_out_file);
04226 }
04227 }
04228 if (spare_slot)
04229 {
04230 output_asm_insn ("sethi\t%%hi(%a0), %%g1", operands);
04231 output_asm_insn ("jmpl\t%%g1 + %%lo(%a0), %%g0", operands);
04232 if (size)
04233 fprintf (asm_out_file, "\t sub\t%%sp, -%d, %%sp\n", size);
04234 else if (! delay_slot)
04235 fputs ("\t nop\n", asm_out_file);
04236 }
04237 else
04238 {
04239 if (size)
04240 fprintf (asm_out_file, "\tsub\t%%sp, -%d, %%sp\n", size);
04241
04242
04243 output_asm_insn ("or\t%%o7, %%g0, %%g1", operands);
04244 output_asm_insn ("call\t%a0, 0", operands);
04245 output_asm_insn (" or\t%%g1, %%g0, %%o7", operands);
04246 }
04247 return "";
04248 }
04249
04250 output_asm_insn ("call\t%a0, 0", operands);
04251 if (delay_slot)
04252 {
04253 rtx delay = NEXT_INSN (insn), pat;
04254
04255 if (! delay)
04256 abort ();
04257
04258 pat = PATTERN (delay);
04259 if (GET_CODE (pat) != SET)
04260 abort ();
04261
04262 operands[0] = SET_DEST (pat);
04263 pat = SET_SRC (pat);
04264 switch (GET_CODE (pat))
04265 {
04266 case PLUS:
04267 operands[1] = XEXP (pat, 0);
04268 operands[2] = XEXP (pat, 1);
04269 output_asm_insn (" restore %r1, %2, %Y0", operands);
04270 break;
04271 case LO_SUM:
04272 operands[1] = XEXP (pat, 0);
04273 operands[2] = XEXP (pat, 1);
04274 output_asm_insn (" restore %r1, %%lo(%a2), %Y0", operands);
04275 break;
04276 case ASHIFT:
04277 operands[1] = XEXP (pat, 0);
04278 output_asm_insn (" restore %r1, %r1, %Y0", operands);
04279 break;
04280 default:
04281 operands[1] = pat;
04282 output_asm_insn (" restore %%g0, %1, %Y0", operands);
04283 break;
04284 }
04285 PATTERN (delay) = gen_blockage ();
04286 INSN_CODE (delay) = -1;
04287 }
04288 else
04289 fputs ("\t restore\n", asm_out_file);
04290 return "";
04291 }
04292
04293
04294
04295
04296
04297
04298
04299
04300
04301
04302
04303
04304
04305
04306
04307
04308
04309
04310
04311
04312
04313
04314
04315
04316
04317
04318
04319
04320
04321
04322
04323
04324
04325
04326
04327
04328
04329
04330
04331
04332
04333
04334
04335
04336
04337
04338
04339
04340
04341
04342
04343
04344 #define SPARC_INT_ARG_MAX 6
04345
04346 #define SPARC_FP_ARG_MAX 16
04347
04348 #define ROUND_ADVANCE(SIZE) (((SIZE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
04349
04350
04351
04352
04353
04354
04355 void
04356 init_cumulative_args (cum, fntype, libname, indirect)
04357 CUMULATIVE_ARGS *cum;
04358 tree fntype;
04359 rtx libname ATTRIBUTE_UNUSED;
04360 int indirect ATTRIBUTE_UNUSED;
04361 {
04362 cum->words = 0;
04363 cum->prototype_p = fntype && TYPE_ARG_TYPES (fntype);
04364 cum->libcall_p = fntype == 0;
04365 }
04366
04367
04368
04369
04370
04371
04372
04373
04374
04375
04376
04377
04378
04379
04380
04381
04382 static int
04383 function_arg_slotno (cum, mode, type, named, incoming_p, pregno, ppadding)
04384 const CUMULATIVE_ARGS *cum;
04385 enum machine_mode mode;
04386 tree type;
04387 int named;
04388 int incoming_p;
04389 int *pregno;
04390 int *ppadding;
04391 {
04392 int regbase = (incoming_p
04393 ? SPARC_INCOMING_INT_ARG_FIRST
04394 : SPARC_OUTGOING_INT_ARG_FIRST);
04395 int slotno = cum->words;
04396 int regno;
04397
04398 *ppadding = 0;
04399
04400 if (type != 0 && TREE_ADDRESSABLE (type))
04401 return -1;
04402 if (TARGET_ARCH32
04403 && type != 0 && mode == BLKmode
04404 && TYPE_ALIGN (type) % PARM_BOUNDARY != 0)
04405 return -1;
04406
04407 switch (mode)
04408 {
04409 case VOIDmode :
04410
04411
04412 return -1;
04413
04414 case QImode : case CQImode :
04415 case HImode : case CHImode :
04416 case SImode : case CSImode :
04417 case DImode : case CDImode :
04418 case TImode : case CTImode :
04419 if (slotno >= SPARC_INT_ARG_MAX)
04420 return -1;
04421 regno = regbase + slotno;
04422 break;
04423
04424 case SFmode : case SCmode :
04425 case DFmode : case DCmode :
04426 case TFmode : case TCmode :
04427 if (TARGET_ARCH32)
04428 {
04429 if (slotno >= SPARC_INT_ARG_MAX)
04430 return -1;
04431 regno = regbase + slotno;
04432 }
04433 else
04434 {
04435 if ((mode == TFmode || mode == TCmode)
04436 && (slotno & 1) != 0)
04437 slotno++, *ppadding = 1;
04438 if (TARGET_FPU && named)
04439 {
04440 if (slotno >= SPARC_FP_ARG_MAX)
04441 return -1;
04442 regno = SPARC_FP_ARG_FIRST + slotno * 2;
04443 if (mode == SFmode)
04444 regno++;
04445 }
04446 else
04447 {
04448 if (slotno >= SPARC_INT_ARG_MAX)
04449 return -1;
04450 regno = regbase + slotno;
04451 }
04452 }
04453 break;
04454
04455 case BLKmode :
04456
04457 if (TARGET_ARCH64)
04458 {
04459 if (type && TYPE_ALIGN (type) == 128 && (slotno & 1) != 0)
04460 slotno++, *ppadding = 1;
04461 }
04462
04463 if (TARGET_ARCH32
04464 || (type && TREE_CODE (type) == UNION_TYPE))
04465 {
04466 if (slotno >= SPARC_INT_ARG_MAX)
04467 return -1;
04468 regno = regbase + slotno;
04469 }
04470 else
04471 {
04472 tree field;
04473 int intregs_p = 0, fpregs_p = 0;
04474
04475
04476
04477 int packed_p = 0;
04478
04479
04480 for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
04481 {
04482 if (TREE_CODE (field) == FIELD_DECL)
04483 {
04484 if (TREE_CODE (TREE_TYPE (field)) == REAL_TYPE
04485 && TARGET_FPU)
04486 fpregs_p = 1;
04487 else
04488 intregs_p = 1;
04489 if (DECL_PACKED (field))
04490 packed_p = 1;
04491 }
04492 }
04493 if (packed_p || !named)
04494 fpregs_p = 0, intregs_p = 1;
04495
04496
04497 if (fpregs_p && slotno >= SPARC_FP_ARG_MAX)
04498 return -1;
04499
04500
04501 if (!fpregs_p && intregs_p && slotno >= SPARC_INT_ARG_MAX)
04502 return -1;
04503
04504
04505
04506
04507 return slotno;
04508 }
04509 break;
04510
04511 default :
04512 abort ();
04513 }
04514
04515 *pregno = regno;
04516 return slotno;
04517 }
04518
04519
04520
04521 struct function_arg_record_value_parms
04522 {
04523 rtx ret;
04524 int slotno, named, regbase;
04525 unsigned int nregs;
04526 int intoffset;
04527 };
04528
04529 static void function_arg_record_value_3
04530 PARAMS ((HOST_WIDE_INT, struct function_arg_record_value_parms *));
04531 static void function_arg_record_value_2
04532 PARAMS ((tree, HOST_WIDE_INT,
04533 struct function_arg_record_value_parms *));
04534 static void function_arg_record_value_1
04535 PARAMS ((tree, HOST_WIDE_INT,
04536 struct function_arg_record_value_parms *));
04537 static rtx function_arg_record_value
04538 PARAMS ((tree, enum machine_mode, int, int, int));
04539
04540
04541
04542
04543 static void
04544 function_arg_record_value_1 (type, startbitpos, parms)
04545 tree type;
04546 HOST_WIDE_INT startbitpos;
04547 struct function_arg_record_value_parms *parms;
04548 {
04549 tree field;
04550
04551
04552
04553
04554 int packed_p = 0;
04555
04556
04557
04558
04559
04560 for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
04561 {
04562 if (TREE_CODE (field) == FIELD_DECL && DECL_PACKED (field))
04563 {
04564 packed_p = 1;
04565 break;
04566 }
04567 }
04568
04569
04570 for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
04571 {
04572 if (TREE_CODE (field) == FIELD_DECL)
04573 {
04574 HOST_WIDE_INT bitpos = startbitpos;
04575
04576 if (DECL_SIZE (field) != 0
04577 && host_integerp (bit_position (field), 1))
04578 bitpos += int_bit_position (field);
04579
04580
04581
04582 if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE)
04583 function_arg_record_value_1 (TREE_TYPE (field), bitpos, parms);
04584 else if ((TREE_CODE (TREE_TYPE (field)) == REAL_TYPE
04585 || (TREE_CODE (TREE_TYPE (field)) == COMPLEX_TYPE
04586 && (TREE_CODE (TREE_TYPE (TREE_TYPE (field)))
04587 == REAL_TYPE)))
04588 && TARGET_FPU
04589 && ! packed_p
04590 && parms->named)
04591 {
04592 if (parms->intoffset != -1)
04593 {
04594 int intslots, this_slotno;
04595
04596 intslots = (bitpos - parms->intoffset + BITS_PER_WORD - 1)
04597 / BITS_PER_WORD;
04598 this_slotno = parms->slotno + parms->intoffset
04599 / BITS_PER_WORD;
04600
04601 intslots = MIN (intslots, SPARC_INT_ARG_MAX - this_slotno);
04602 intslots = MAX (intslots, 0);
04603 parms->nregs += intslots;
04604 parms->intoffset = -1;
04605 }
04606
04607
04608
04609 parms->nregs += 1;
04610 if (TREE_CODE (TREE_TYPE (field)) == COMPLEX_TYPE)
04611 parms->nregs += 1;
04612 }
04613 else
04614 {
04615 if (parms->intoffset == -1)
04616 parms->intoffset = bitpos;
04617 }
04618 }
04619 }
04620 }
04621
04622
04623
04624
04625 static void
04626 function_arg_record_value_3 (bitpos, parms)
04627 HOST_WIDE_INT bitpos;
04628 struct function_arg_record_value_parms *parms;
04629 {
04630 enum machine_mode mode;
04631 unsigned int regno;
04632 unsigned int startbit, endbit;
04633 int this_slotno, intslots, intoffset;
04634 rtx reg;
04635
04636 if (parms->intoffset == -1)
04637 return;
04638
04639 intoffset = parms->intoffset;
04640 parms->intoffset = -1;
04641
04642 startbit = intoffset & -BITS_PER_WORD;
04643 endbit = (bitpos + BITS_PER_WORD - 1) & -BITS_PER_WORD;
04644 intslots = (endbit - startbit) / BITS_PER_WORD;
04645 this_slotno = parms->slotno + intoffset / BITS_PER_WORD;
04646
04647 intslots = MIN (intslots, SPARC_INT_ARG_MAX - this_slotno);
04648 if (intslots <= 0)
04649 return;
04650
04651
04652
04653
04654
04655
04656 if (intoffset % BITS_PER_WORD != 0)
04657 mode = mode_for_size (BITS_PER_WORD - intoffset % BITS_PER_WORD,
04658 MODE_INT, 0);
04659 else
04660 mode = word_mode;
04661
04662 intoffset /= BITS_PER_UNIT;
04663 do
04664 {
04665 regno = parms->regbase + this_slotno;
04666 reg = gen_rtx_REG (mode, regno);
04667 XVECEXP (parms->ret, 0, parms->nregs)
04668 = gen_rtx_EXPR_LIST (VOIDmode, reg, GEN_INT (intoffset));
04669
04670 this_slotno += 1;
04671 intoffset = (intoffset | (UNITS_PER_WORD-1)) + 1;
04672 parms->nregs += 1;
04673 intslots -= 1;
04674 }
04675 while (intslots > 0);
04676 }
04677
04678
04679
04680
04681
04682
04683 static void
04684 function_arg_record_value_2 (type, startbitpos, parms)
04685 tree type;
04686 HOST_WIDE_INT startbitpos;
04687 struct function_arg_record_value_parms *parms;
04688 {
04689 tree field;
04690 int packed_p = 0;
04691
04692 for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
04693 {
04694 if (TREE_CODE (field) == FIELD_DECL && DECL_PACKED (field))
04695 {
04696 packed_p = 1;
04697 break;
04698 }
04699 }
04700
04701 for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
04702 {
04703 if (TREE_CODE (field) == FIELD_DECL)
04704 {
04705 HOST_WIDE_INT bitpos = startbitpos;
04706
04707 if (DECL_SIZE (field) != 0
04708 && host_integerp (bit_position (field), 1))
04709 bitpos += int_bit_position (field);
04710
04711
04712
04713 if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE)
04714 function_arg_record_value_2 (TREE_TYPE (field), bitpos, parms);
04715 else if ((TREE_CODE (TREE_TYPE (field)) == REAL_TYPE
04716 || (TREE_CODE (TREE_TYPE (field)) == COMPLEX_TYPE
04717 && (TREE_CODE (TREE_TYPE (TREE_TYPE (field)))
04718 == REAL_TYPE)))
04719 && TARGET_FPU
04720 && ! packed_p
04721 && parms->named)
04722 {
04723 int this_slotno = parms->slotno + bitpos / BITS_PER_WORD;
04724 int regno;
04725 enum machine_mode mode = DECL_MODE (field);
04726 rtx reg;
04727
04728 function_arg_record_value_3 (bitpos, parms);
04729 regno = SPARC_FP_ARG_FIRST + this_slotno * 2
04730 + ((mode == SFmode || mode == SCmode)
04731 && (bitpos & 32) != 0);
04732 switch (mode)
04733 {
04734 case SCmode: mode = SFmode; break;
04735 case DCmode: mode = DFmode; break;
04736 case TCmode: mode = TFmode; break;
04737 default: break;
04738 }
04739 reg = gen_rtx_REG (mode, regno);
04740 XVECEXP (parms->ret, 0, parms->nregs)
04741 = gen_rtx_EXPR_LIST (VOIDmode, reg,
04742 GEN_INT (bitpos / BITS_PER_UNIT));
04743 parms->nregs += 1;
04744 if (TREE_CODE (TREE_TYPE (field)) == COMPLEX_TYPE)
04745 {
04746 regno += GET_MODE_SIZE (mode) / 4;
04747 reg = gen_rtx_REG (mode, regno);
04748 XVECEXP (parms->ret, 0, parms->nregs)
04749 = gen_rtx_EXPR_LIST (VOIDmode, reg,
04750 GEN_INT ((bitpos + GET_MODE_BITSIZE (mode))
04751 / BITS_PER_UNIT));
04752 parms->nregs += 1;
04753 }
04754 }
04755 else
04756 {
04757 if (parms->intoffset == -1)
04758 parms->intoffset = bitpos;
04759 }
04760 }
04761 }
04762 }
04763
04764
04765
04766
04767 static rtx
04768 function_arg_record_value (type, mode, slotno, named, regbase)
04769 tree type;
04770 enum machine_mode mode;
04771 int slotno, named, regbase;
04772 {
04773 HOST_WIDE_INT typesize = int_size_in_bytes (type);
04774 struct function_arg_record_value_parms parms;
04775 unsigned int nregs;
04776
04777 parms.ret = NULL_RTX;
04778 parms.slotno = slotno;
04779 parms.named = named;
04780 parms.regbase = regbase;
04781
04782
04783 parms.nregs = 0;
04784 parms.intoffset = 0;
04785 function_arg_record_value_1 (type, 0, &parms);
04786
04787 if (parms.intoffset != -1)
04788 {
04789 unsigned int startbit, endbit;
04790 int intslots, this_slotno;
04791
04792 startbit = parms.intoffset & -BITS_PER_WORD;
04793 endbit = (typesize*BITS_PER_UNIT + BITS_PER_WORD - 1) & -BITS_PER_WORD;
04794 intslots = (endbit - startbit) / BITS_PER_WORD;
04795 this_slotno = slotno + parms.intoffset / BITS_PER_WORD;
04796
04797 intslots = MIN (intslots, SPARC_INT_ARG_MAX - this_slotno);
04798 intslots = MAX (intslots, 0);
04799
04800 parms.nregs += intslots;
04801 }
04802 nregs = parms.nregs;
04803
04804
04805 if (nregs == 0)
04806 {
04807
04808 if (typesize <= 0)
04809 {
04810
04811
04812
04813
04814 return gen_rtx_REG (mode, regbase);
04815 }
04816 else
04817 {
04818
04819
04820 nregs = (typesize + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
04821 }
04822 if (nregs + slotno > SPARC_INT_ARG_MAX)
04823 nregs = SPARC_INT_ARG_MAX - slotno;
04824 }
04825 if (nregs == 0)
04826 abort ();
04827
04828 parms.ret = gen_rtx_PARALLEL (mode, rtvec_alloc (nregs));
04829
04830
04831 parms.nregs = 0;
04832 parms.intoffset = 0;
04833 function_arg_record_value_2 (type, 0, &parms);
04834 function_arg_record_value_3 (typesize * BITS_PER_UNIT, &parms);
04835
04836 if (parms.nregs != nregs)
04837 abort ();
04838
04839 return parms.ret;
04840 }
04841
04842
04843
04844
04845
04846
04847
04848
04849
04850
04851
04852
04853
04854
04855
04856
04857 rtx
04858 function_arg (cum, mode, type, named, incoming_p)
04859 const CUMULATIVE_ARGS *cum;
04860 enum machine_mode mode;
04861 tree type;
04862 int named;
04863 int incoming_p;
04864 {
04865 int regbase = (incoming_p
04866 ? SPARC_INCOMING_INT_ARG_FIRST
04867 : SPARC_OUTGOING_INT_ARG_FIRST);
04868 int slotno, regno, padding;
04869 rtx reg;
04870
04871 slotno = function_arg_slotno (cum, mode, type, named, incoming_p,
04872 ®no, &padding);
04873
04874 if (slotno == -1)
04875 return 0;
04876
04877 if (TARGET_ARCH32)
04878 {
04879 reg = gen_rtx_REG (mode, regno);
04880 return reg;
04881 }
04882
04883
04884
04885
04886
04887 if ((GET_MODE_CLASS (mode) == MODE_FLOAT
04888 || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
04889 && SPARC_FP_REG_P (regno))
04890 {
04891 reg = gen_rtx_REG (mode, regno);
04892 if (cum->prototype_p || cum->libcall_p)
04893 {
04894
04895
04896 #if 0
04897
04898
04899
04900
04901 if ((regno - SPARC_FP_ARG_FIRST) >= SPARC_INT_ARG_MAX * 2)
04902 return gen_rtx_PARALLEL (mode,
04903 gen_rtvec (2,
04904 gen_rtx_EXPR_LIST (VOIDmode,
04905 NULL_RTX, const0_rtx),
04906 gen_rtx_EXPR_LIST (VOIDmode,
04907 reg, const0_rtx)));
04908 else
04909 #else
04910
04911
04912
04913
04914
04915
04916
04917
04918
04919 #endif
04920 return reg;
04921 }
04922 else
04923 {
04924 rtx v0, v1;
04925
04926 if ((regno - SPARC_FP_ARG_FIRST) < SPARC_INT_ARG_MAX * 2)
04927 {
04928 int intreg;
04929
04930
04931
04932
04933 if (incoming_p)
04934 return reg;
04935
04936 intreg = (SPARC_OUTGOING_INT_ARG_FIRST
04937 + (regno - SPARC_FP_ARG_FIRST) / 2);
04938
04939 v0 = gen_rtx_EXPR_LIST (VOIDmode, reg, const0_rtx);
04940 v1 = gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_REG (mode, intreg),
04941 const0_rtx);
04942 return gen_rtx_PARALLEL (mode, gen_rtvec (2, v0, v1));
04943 }
04944 else
04945 {
04946 v0 = gen_rtx_EXPR_LIST (VOIDmode, NULL_RTX, const0_rtx);
04947 v1 = gen_rtx_EXPR_LIST (VOIDmode, reg, const0_rtx);
04948 return gen_rtx_PARALLEL (mode, gen_rtvec (2, v0, v1));
04949 }
04950 }
04951 }
04952 else if (type && TREE_CODE (type) == RECORD_TYPE)
04953 {
04954
04955
04956
04957 if (int_size_in_bytes (type) > 16)
04958 abort ();
04959
04960 return function_arg_record_value (type, mode, slotno, named, regbase);
04961 }
04962 else if (type && TREE_CODE (type) == UNION_TYPE)
04963 {
04964 enum machine_mode mode;
04965 int bytes = int_size_in_bytes (type);
04966
04967 if (bytes > 16)
04968 abort ();
04969
04970 mode = mode_for_size (bytes * BITS_PER_UNIT, MODE_INT, 0);
04971 reg = gen_rtx_REG (mode, regno);
04972 }
04973 else
04974 {
04975
04976 reg = gen_rtx_REG (mode, regno);
04977 }
04978
04979 return reg;
04980 }
04981
04982
04983
04984
04985
04986
04987
04988
04989
04990
04991
04992
04993 int
04994 function_arg_partial_nregs (cum, mode, type, named)
04995 const CUMULATIVE_ARGS *cum;
04996 enum machine_mode mode;
04997 tree type;
04998 int named;
04999 {
05000 int slotno, regno, padding;
05001
05002
05003 slotno = function_arg_slotno (cum, mode, type, named, 0, ®no, &padding);
05004
05005 if (slotno == -1)
05006 return 0;
05007
05008 if (TARGET_ARCH32)
05009 {
05010 if ((slotno + (mode == BLKmode
05011 ? ROUND_ADVANCE (int_size_in_bytes (type))
05012 : ROUND_ADVANCE (GET_MODE_SIZE (mode))))
05013 > NPARM_REGS (SImode))
05014 return NPARM_REGS (SImode) - slotno;
05015 return 0;
05016 }
05017 else
05018 {
05019 if (type && AGGREGATE_TYPE_P (type))
05020 {
05021 int size = int_size_in_bytes (type);
05022 int align = TYPE_ALIGN (type);
05023
05024 if (align == 16)
05025 slotno += slotno & 1;
05026 if (size > 8 && size <= 16
05027 && slotno == SPARC_INT_ARG_MAX - 1)
05028 return 1;
05029 }
05030 else if (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT
05031 || (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
05032 && ! TARGET_FPU))
05033 {
05034 if (GET_MODE_ALIGNMENT (mode) == 128)
05035 {
05036 slotno += slotno & 1;
05037 if (slotno == SPARC_INT_ARG_MAX - 2)
05038 return 1;
05039 }
05040 else
05041 {
05042 if (slotno == SPARC_INT_ARG_MAX - 1)
05043 return 1;
05044 }
05045 }
05046 else if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
05047 {
05048 if (GET_MODE_ALIGNMENT (mode) == 128)
05049 slotno += slotno & 1;
05050 if ((slotno + GET_MODE_SIZE (mode) / UNITS_PER_WORD)
05051 > SPARC_FP_ARG_MAX)
05052 return 1;
05053 }
05054 return 0;
05055 }
05056 }
05057
05058
05059
05060
05061
05062
05063
05064 int
05065 function_arg_pass_by_reference (cum, mode, type, named)
05066 const CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED;
05067 enum machine_mode mode;
05068 tree type;
05069 int named ATTRIBUTE_UNUSED;
05070 {
05071 if (TARGET_ARCH32)
05072 {
05073 return ((type && AGGREGATE_TYPE_P (type))
05074 || mode == TFmode || mode == TCmode);
05075 }
05076 else
05077 {
05078 return ((type && TREE_CODE (type) == ARRAY_TYPE)
05079
05080 || GET_MODE_SIZE (mode) > 16
05081 || (type
05082 && AGGREGATE_TYPE_P (type)
05083 && (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 16));
05084 }
05085 }
05086
05087
05088
05089
05090
05091
05092 void
05093 function_arg_advance (cum, mode, type, named)
05094 CUMULATIVE_ARGS *cum;
05095 enum machine_mode mode;
05096 tree type;
05097 int named;
05098 {
05099 int slotno, regno, padding;
05100
05101
05102 slotno = function_arg_slotno (cum, mode, type, named, 0, ®no, &padding);
05103
05104
05105 if (slotno != -1)
05106 cum->words += padding;
05107
05108 if (TARGET_ARCH32)
05109 {
05110 cum->words += (mode != BLKmode
05111 ? ROUND_ADVANCE (GET_MODE_SIZE (mode))
05112 : ROUND_ADVANCE (int_size_in_bytes (type)));
05113 }
05114 else
05115 {
05116 if (type && AGGREGATE_TYPE_P (type))
05117 {
05118 int size = int_size_in_bytes (type);
05119
05120 if (size <= 8)
05121 ++cum->words;
05122 else if (size <= 16)
05123 cum->words += 2;
05124 else
05125 ++cum->words;
05126 }
05127 else if (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT)
05128 {
05129 cum->words += 2;
05130 }
05131 else if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
05132 {
05133 cum->words += GET_MODE_SIZE (mode) / UNITS_PER_WORD;
05134 }
05135 else
05136 {
05137 cum->words += (mode != BLKmode
05138 ? ROUND_ADVANCE (GET_MODE_SIZE (mode))
05139 : ROUND_ADVANCE (int_size_in_bytes (type)));
05140 }
05141 }
05142 }
05143
05144
05145
05146
05147
05148 enum direction
05149 function_arg_padding (mode, type)
05150 enum machine_mode mode;
05151 tree type;
05152 {
05153 if (TARGET_ARCH64 && type != 0 && AGGREGATE_TYPE_P (type))
05154 return upward;
05155
05156
05157 return (! BYTES_BIG_ENDIAN
05158 ? upward
05159 : ((mode == BLKmode
05160 ? (type && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
05161 && int_size_in_bytes (type) < (PARM_BOUNDARY / BITS_PER_UNIT))
05162 : GET_MODE_BITSIZE (mode) < PARM_BOUNDARY)
05163 ? downward : upward));
05164 }
05165
05166
05167
05168
05169
05170 rtx
05171 function_value (type, mode, incoming_p)
05172 tree type;
05173 enum machine_mode mode;
05174 int incoming_p;
05175 {
05176 int regno;
05177 int regbase = (incoming_p
05178 ? SPARC_OUTGOING_INT_ARG_FIRST
05179 : SPARC_INCOMING_INT_ARG_FIRST);
05180
05181 if (TARGET_ARCH64 && type)
05182 {
05183 if (TREE_CODE (type) == RECORD_TYPE)
05184 {
05185
05186
05187
05188 if (int_size_in_bytes (type) > 32)
05189 abort ();
05190
05191 return function_arg_record_value (type, mode, 0, 1, regbase);
05192 }
05193 else if (AGGREGATE_TYPE_P (type))
05194 {
05195
05196
05197 HOST_WIDE_INT bytes = int_size_in_bytes (type);
05198
05199 if (bytes > 32)
05200 abort ();
05201
05202 mode = mode_for_size (bytes * BITS_PER_UNIT, MODE_INT, 0);
05203 }
05204 }
05205
05206 if (TARGET_ARCH64
05207 && GET_MODE_CLASS (mode) == MODE_INT
05208 && GET_MODE_SIZE (mode) < UNITS_PER_WORD
05209 && type && ! AGGREGATE_TYPE_P (type))
05210 mode = DImode;
05211
05212 if (incoming_p)
05213 regno = BASE_RETURN_VALUE_REG (mode);
05214 else
05215 regno = BASE_OUTGOING_VALUE_REG (mode);
05216
05217 return gen_rtx_REG (mode, regno);
05218 }
05219
05220
05221
05222
05223
05224 rtx
05225 sparc_builtin_saveregs ()
05226 {
05227 int first_reg = current_function_args_info.words;
05228 rtx address;
05229 int regno;
05230
05231 for (regno = first_reg; regno < NPARM_REGS (word_mode); regno++)
05232 emit_move_insn (gen_rtx_MEM (word_mode,
05233 gen_rtx_PLUS (Pmode,
05234 frame_pointer_rtx,
05235 GEN_INT (FIRST_PARM_OFFSET (0)
05236 + (UNITS_PER_WORD
05237 * regno)))),
05238 gen_rtx_REG (word_mode,
05239 BASE_INCOMING_ARG_REG (word_mode) + regno));
05240
05241 address = gen_rtx_PLUS (Pmode,
05242 frame_pointer_rtx,
05243 GEN_INT (FIRST_PARM_OFFSET (0)
05244 + UNITS_PER_WORD * first_reg));
05245
05246 return address;
05247 }
05248
05249
05250
05251 void
05252 sparc_va_start (stdarg_p, valist, nextarg)
05253 int stdarg_p ATTRIBUTE_UNUSED;
05254 tree valist;
05255 rtx nextarg;
05256 {
05257 nextarg = expand_builtin_saveregs ();
05258 std_expand_builtin_va_start (1, valist, nextarg);
05259 }
05260
05261
05262
05263 rtx
05264 sparc_va_arg (valist, type)
05265 tree valist, type;
05266 {
05267 HOST_WIDE_INT size, rsize, align;
05268 tree addr, incr;
05269 rtx addr_rtx;
05270 int indirect = 0;
05271
05272
05273 size = int_size_in_bytes (type);
05274 rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
05275 align = 0;
05276
05277 if (TARGET_ARCH64)
05278 {
05279 if (TYPE_ALIGN (type) >= 2 * (unsigned) BITS_PER_WORD)
05280 align = 2 * UNITS_PER_WORD;
05281
05282 if (AGGREGATE_TYPE_P (type))
05283 {
05284 if ((unsigned HOST_WIDE_INT) size > 16)
05285 {
05286 indirect = 1;
05287 size = rsize = UNITS_PER_WORD;
05288 }
05289
05290
05291 else if (size == 0)
05292 size = rsize = UNITS_PER_WORD;
05293 else
05294 size = rsize;
05295 }
05296 }
05297 else
05298 {
05299 if (AGGREGATE_TYPE_P (type)
05300 || TYPE_MODE (type) == TFmode
05301 || TYPE_MODE (type) == TCmode)
05302 {
05303 indirect = 1;
05304 size = rsize = UNITS_PER_WORD;
05305 }
05306 }
05307
05308 incr = valist;
05309 if (align)
05310 {
05311 incr = fold (build (PLUS_EXPR, ptr_type_node, incr,
05312 build_int_2 (align - 1, 0)));
05313 incr = fold (build (BIT_AND_EXPR, ptr_type_node, incr,
05314 build_int_2 (-align, -1)));
05315 }
05316
05317 addr = incr = save_expr (incr);
05318 if (BYTES_BIG_ENDIAN && size < rsize)
05319 {
05320 addr = fold (build (PLUS_EXPR, ptr_type_node, incr,
05321 build_int_2 (rsize - size, 0)));
05322 }
05323 incr = fold (build (PLUS_EXPR, ptr_type_node, incr,
05324 build_int_2 (rsize, 0)));
05325
05326 incr = build (MODIFY_EXPR, ptr_type_node, valist, incr);
05327 TREE_SIDE_EFFECTS (incr) = 1;
05328 expand_expr (incr, const0_rtx, VOIDmode, EXPAND_NORMAL);
05329
05330 addr_rtx = expand_expr (addr, NULL, Pmode, EXPAND_NORMAL);
05331
05332
05333
05334
05335
05336 if (align == 0
05337 && TYPE_ALIGN (type) > BITS_PER_WORD
05338 && !indirect)
05339 {
05340
05341
05342
05343
05344
05345 rtx tmp = assign_temp (type, 0, 1, 0);
05346 rtx dest_addr;
05347
05348 addr_rtx = force_reg (Pmode, addr_rtx);
05349 addr_rtx = gen_rtx_MEM (BLKmode, addr_rtx);
05350 set_mem_alias_set (addr_rtx, get_varargs_alias_set ());
05351 set_mem_align (addr_rtx, BITS_PER_WORD);
05352 tmp = shallow_copy_rtx (tmp);
05353 PUT_MODE (tmp, BLKmode);
05354 set_mem_alias_set (tmp, 0);
05355
05356 dest_addr = emit_block_move (tmp, addr_rtx, GEN_INT (rsize));
05357 if (dest_addr != NULL_RTX)
05358 addr_rtx = dest_addr;
05359 else
05360 addr_rtx = XCEXP (tmp, 0, MEM);
05361 }
05362
05363 if (indirect)
05364 {
05365 addr_rtx = force_reg (Pmode, addr_rtx);
05366 addr_rtx = gen_rtx_MEM (Pmode, addr_rtx);
05367 set_mem_alias_set (addr_rtx, get_varargs_alias_set ());
05368 }
05369
05370 return addr_rtx;
05371 }
05372
05373
05374
05375
05376
05377
05378
05379
05380
05381
05382
05383
05384
05385
05386 char *
05387 output_cbranch (op, dest, label, reversed, annul, noop, insn)
05388 rtx op, dest;
05389 int label;
05390 int reversed, annul, noop;
05391 rtx insn;
05392 {
05393 static char string[50];
05394 enum rtx_code code = GET_CODE (op);
05395 rtx cc_reg = XEXP (op, 0);
05396 enum machine_mode mode = GET_MODE (cc_reg);
05397 const char *labelno, *branch;
05398 int spaces = 8, far;
05399 char *p;
05400
05401
05402
05403
05404
05405
05406
05407
05408
05409
05410
05411
05412
05413
05414
05415
05416
05417
05418
05419
05420
05421
05422 far = get_attr_length (insn) >= 3;
05423 if (reversed ^ far)
05424 {
05425
05426
05427 if (mode == CCFPmode || mode == CCFPEmode)
05428 code = reverse_condition_maybe_unordered (code);
05429 else
05430 code = reverse_condition (code);
05431 }
05432
05433
05434 if (mode == CCFPmode || mode == CCFPEmode)
05435 {
05436 switch (code)
05437 {
05438 case NE:
05439 branch = "fbne";
05440 break;
05441 case EQ:
05442 branch = "fbe";
05443 break;
05444 case GE:
05445 branch = "fbge";
05446 break;
05447 case GT:
05448 branch = "fbg";
05449 break;
05450 case LE:
05451 branch = "fble";
05452 break;
05453 case LT:
05454 branch = "fbl";
05455 break;
05456 case UNORDERED:
05457 branch = "fbu";
05458 break;
05459 case ORDERED:
05460 branch = "fbo";
05461 break;
05462 case UNGT:
05463 branch = "fbug";
05464 break;
05465 case UNLT:
05466 branch = "fbul";
05467 break;
05468 case UNEQ:
05469 branch = "fbue";
05470 break;
05471 case UNGE:
05472 branch = "fbuge";
05473 break;
05474 case UNLE:
05475 branch = "fbule";
05476 break;
05477 case LTGT:
05478 branch = "fblg";
05479 break;
05480
05481 default:
05482 abort ();
05483 }
05484
05485
05486
05487
05488
05489
05490 string[0] = '\0';
05491 if (! TARGET_V9)
05492 strcpy (string, "nop\n\t");
05493 strcat (string, branch);
05494 }
05495 else
05496 {
05497 switch (code)
05498 {
05499 case NE:
05500 branch = "bne";
05501 break;
05502 case EQ:
05503 branch = "be";
05504 break;
05505 case GE:
05506 if (mode == CC_NOOVmode || mode == CCX_NOOVmode)
05507 branch = "bpos";
05508 else
05509 branch = "bge";
05510 break;
05511 case GT:
05512 branch = "bg";
05513 break;
05514 case LE:
05515 branch = "ble";
05516 break;
05517 case LT:
05518 if (mode == CC_NOOVmode || mode == CCX_NOOVmode)
05519 branch = "bneg";
05520 else
05521 branch = "bl";
05522 break;
05523 case GEU:
05524 branch = "bgeu";
05525 break;
05526 case GTU:
05527 branch = "bgu";
05528 break;
05529 case LEU:
05530 branch = "bleu";
05531 break;
05532 case LTU:
05533 branch = "blu";
05534 break;
05535
05536 default:
05537 abort ();
05538 }
05539 strcpy (string, branch);
05540 }
05541 spaces -= strlen (branch);
05542 p = strchr (string, '\0');
05543
05544
05545 if (annul && ! far)
05546 {
05547 strcpy (p, ",a");
05548 p += 2;
05549 spaces -= 2;
05550 }
05551
05552 if (! TARGET_V9)
05553 labelno = "";
05554 else
05555 {
05556 rtx note;
05557 int v8 = 0;
05558
05559 if (! far && insn && INSN_ADDRESSES_SET_P ())
05560 {
05561 int delta = (INSN_ADDRESSES (INSN_UID (dest))
05562 - INSN_ADDRESSES (INSN_UID (insn)));
05563
05564 if (delta < -260000 || delta >= 260000)
05565 v8 = 1;
05566 }
05567
05568 if (mode == CCFPmode || mode == CCFPEmode)
05569 {
05570 static char v9_fcc_labelno[] = "%%fccX, ";
05571
05572 v9_fcc_labelno[5] = REGNO (cc_reg) - SPARC_FIRST_V9_FCC_REG + '0';
05573 labelno = v9_fcc_labelno;
05574 if (v8)
05575 {
05576 if (REGNO (cc_reg) == SPARC_FCC_REG)
05577 labelno = "";
05578 else
05579 abort ();
05580 }
05581 }
05582 else if (mode == CCXmode || mode == CCX_NOOVmode)
05583 {
05584 labelno = "%%xcc, ";
05585 if (v8)
05586 abort ();
05587 }
05588 else
05589 {
05590 labelno = "%%icc, ";
05591 if (v8)
05592 labelno = "";
05593 }
05594
05595 if (*labelno && insn && (note = find_reg_note (insn, REG_BR_PROB, NULL_RTX)))
05596 {
05597 strcpy (p,
05598 ((INTVAL (XEXP (note, 0)) >= REG_BR_PROB_BASE / 2) ^ far)
05599 ? ",pt" : ",pn");
05600 p += 3;
05601 spaces -= 3;
05602 }
05603 }
05604 if (spaces > 0)
05605 *p++ = '\t';
05606 else
05607 *p++ = ' ';
05608 strcpy (p, labelno);
05609 p = strchr (p, '\0');
05610 if (far)
05611 {
05612 strcpy (p, ".+12\n\tnop\n\tb\t");
05613 if (annul || noop)
05614 p[3] = '6';
05615 p += 13;
05616 }
05617 *p++ = '%';
05618 *p++ = 'l';
05619
05620
05621 *p++ = label + '0';
05622 *p = '\0';
05623 if (noop)
05624 strcpy (p, "\n\tnop");
05625
05626 return string;
05627 }
05628
05629
05630
05631
05632
05633
05634 void
05635 sparc_emit_float_lib_cmp (x, y, comparison)
05636 rtx x, y;
05637 enum rtx_code comparison;
05638 {
05639 const char *qpfunc;
05640 rtx slot0, slot1, result, tem, tem2;
05641 enum machine_mode mode;
05642
05643 switch (comparison)
05644 {
05645 case EQ:
05646 qpfunc = (TARGET_ARCH64) ? "_Qp_feq" : "_Q_feq";
05647 break;
05648
05649 case NE:
05650 qpfunc = (TARGET_ARCH64) ? "_Qp_fne" : "_Q_fne";
05651 break;
05652
05653 case GT:
05654 qpfunc = (TARGET_ARCH64) ? "_Qp_fgt" : "_Q_fgt";
05655 break;
05656
05657 case GE:
05658 qpfunc = (TARGET_ARCH64) ? "_Qp_fge" : "_Q_fge";
05659 break;
05660
05661 case LT:
05662 qpfunc = (TARGET_ARCH64) ? "_Qp_flt" : "_Q_flt";
05663 break;
05664
05665 case LE:
05666 qpfunc = (TARGET_ARCH64) ? "_Qp_fle" : "_Q_fle";
05667 break;
05668
05669 case ORDERED:
05670 case UNORDERED:
05671 case UNGT:
05672 case UNLT:
05673 case UNEQ:
05674 case UNGE:
05675 case UNLE:
05676 case LTGT:
05677 qpfunc = (TARGET_ARCH64) ? "_Qp_cmp" : "_Q_cmp";
05678 break;
05679
05680 default:
05681 abort();
05682 break;
05683 }
05684
05685 if (TARGET_ARCH64)
05686 {
05687 if (GET_CODE (x) != MEM)
05688 {
05689 slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
05690 emit_insn (gen_rtx_SET (VOIDmode, slot0, x));
05691 }
05692 else
05693 slot0 = x;
05694
05695 if (GET_CODE (y) != MEM)
05696 {
05697 slot1 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
05698 emit_insn (gen_rtx_SET (VOIDmode, slot1, y));
05699 }
05700 else
05701 slot1 = y;
05702
05703 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, qpfunc), LCT_NORMAL,
05704 DImode, 2,
05705 XEXP (slot0, 0), Pmode,
05706 XEXP (slot1, 0), Pmode);
05707
05708 mode = DImode;
05709 }
05710 else
05711 {
05712 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, qpfunc), LCT_NORMAL,
05713 SImode, 2,
05714 x, TFmode, y, TFmode);
05715
05716 mode = SImode;
05717 }
05718
05719
05720
05721
05722
05723 result = gen_reg_rtx (mode);
05724 emit_move_insn (result, hard_libcall_value (mode));
05725
05726 switch (comparison)
05727 {
05728 default:
05729 emit_cmp_insn (result, const0_rtx, NE, NULL_RTX, mode, 0);
05730 break;
05731 case ORDERED:
05732 case UNORDERED:
05733 emit_cmp_insn (result, GEN_INT(3), comparison == UNORDERED ? EQ : NE,
05734 NULL_RTX, mode, 0);
05735 break;
05736 case UNGT:
05737 case UNGE:
05738 emit_cmp_insn (result, const1_rtx,
05739 comparison == UNGT ? GT : NE, NULL_RTX, mode, 0);
05740 break;
05741 case UNLE:
05742 emit_cmp_insn (result, const2_rtx, NE, NULL_RTX, mode, 0);
05743 break;
05744 case UNLT:
05745 tem = gen_reg_rtx (mode);
05746 if (TARGET_ARCH32)
05747 emit_insn (gen_andsi3 (tem, result, const1_rtx));
05748 else
05749 emit_insn (gen_anddi3 (tem, result, const1_rtx));
05750 emit_cmp_insn (tem, const0_rtx, NE, NULL_RTX, mode, 0);
05751 break;
05752 case UNEQ:
05753 case LTGT:
05754 tem = gen_reg_rtx (mode);
05755 if (TARGET_ARCH32)
05756 emit_insn (gen_addsi3 (tem, result, const1_rtx));
05757 else
05758 emit_insn (gen_adddi3 (tem, result, const1_rtx));
05759 tem2 = gen_reg_rtx (mode);
05760 if (TARGET_ARCH32)
05761 emit_insn (gen_andsi3 (tem2, tem, const2_rtx));
05762 else
05763 emit_insn (gen_anddi3 (tem2, tem, const2_rtx));
05764 emit_cmp_insn (tem2, const0_rtx, comparison == UNEQ ? EQ : NE,
05765 NULL_RTX, mode, 0);
05766 break;
05767 }
05768 }
05769
05770
05771
05772
05773 void
05774 sparc_emit_floatunsdi (operands)
05775 rtx operands[2];
05776 {
05777 rtx neglab, donelab, i0, i1, f0, in, out;
05778 enum machine_mode mode;
05779
05780 out = operands[0];
05781 in = force_reg (DImode, operands[1]);
05782 mode = GET_MODE (out);
05783 neglab = gen_label_rtx ();
05784 donelab = gen_label_rtx ();
05785 i0 = gen_reg_rtx (DImode);
05786 i1 = gen_reg_rtx (DImode);
05787 f0 = gen_reg_rtx (mode);
05788
05789 emit_cmp_and_jump_insns (in, const0_rtx, LT, const0_rtx, DImode, 0, neglab);
05790
05791 emit_insn (gen_rtx_SET (VOIDmode, out, gen_rtx_FLOAT (mode, in)));
05792 emit_jump_insn (gen_jump (donelab));
05793 emit_barrier ();
05794
05795 emit_label (neglab);
05796
05797 emit_insn (gen_lshrdi3 (i0, in, const1_rtx));
05798 emit_insn (gen_anddi3 (i1, in, const1_rtx));
05799 emit_insn (gen_iordi3 (i0, i0, i1));
05800 emit_insn (gen_rtx_SET (VOIDmode, f0, gen_rtx_FLOAT (mode, i0)));
05801 emit_insn (gen_rtx_SET (VOIDmode, out, gen_rtx_PLUS (mode, f0, f0)));
05802
05803 emit_label (donelab);
05804 }
05805
05806
05807
05808
05809
05810
05811
05812
05813
05814
05815
05816
05817 char *
05818 output_v9branch (op, dest, reg, label, reversed, annul, noop, insn)
05819 rtx op, dest;
05820 int reg, label;
05821 int reversed, annul, noop;
05822 rtx insn;
05823 {
05824 static char string[50];
05825 enum rtx_code code = GET_CODE (op);
05826 enum machine_mode mode = GET_MODE (XEXP (op, 0));
05827 rtx note;
05828 int far;
05829 char *p;
05830
05831
05832
05833
05834
05835
05836
05837
05838
05839
05840
05841
05842
05843
05844
05845
05846
05847
05848
05849
05850
05851
05852 far = get_attr_length (insn) >= 3;
05853
05854
05855 if (reversed ^ far)
05856 code = reverse_condition (code);
05857
05858
05859 if (mode != DImode)
05860 abort ();
05861
05862
05863
05864 switch (code)
05865 {
05866 case NE:
05867 strcpy (string, "brnz");
05868 break;
05869
05870 case EQ:
05871 strcpy (string, "brz");
05872 break;
05873
05874 case GE:
05875 strcpy (string, "brgez");
05876 break;
05877
05878 case LT:
05879 strcpy (string, "brlz");
05880 break;
05881
05882 case LE:
05883 strcpy (string, "brlez");
05884 break;
05885
05886 case GT:
05887 strcpy (string, "brgz");
05888 break;
05889
05890 default:
05891 abort ();
05892 }
05893
05894 p = strchr (string, '\0');
05895
05896
05897 if (annul && ! far)
05898 {
05899 strcpy (p, ",a");
05900 p += 2;
05901 }
05902
05903 if (insn && (note = find_reg_note (insn, REG_BR_PROB, NULL_RTX)))
05904 {
05905 strcpy (p,
05906 ((INTVAL (XEXP (note, 0)) >= REG_BR_PROB_BASE / 2) ^ far)
05907 ? ",pt" : ",pn");
05908 p += 3;
05909 }
05910
05911 *p = p < string + 8 ? '\t' : ' ';
05912 p++;
05913 *p++ = '%';
05914 *p++ = '0' + reg;
05915 *p++ = ',';
05916 *p++ = ' ';
05917 if (far)
05918 {
05919 int veryfar = 1, delta;
05920
05921 if (INSN_ADDRESSES_SET_P ())
05922 {
05923 delta = (INSN_ADDRESSES (INSN_UID (dest))
05924 - INSN_ADDRESSES (INSN_UID (insn)));
05925
05926 if (delta >= -260000 && delta < 260000)
05927 veryfar = 0;
05928 }
05929
05930 strcpy (p, ".+12\n\tnop\n\t");
05931 if (annul || noop)
05932 p[3] = '6';
05933 p += 11;
05934 if (veryfar)
05935 {
05936 strcpy (p, "b\t");
05937 p += 2;
05938 }
05939 else
05940 {
05941 strcpy (p, "ba,pt\t%%xcc, ");
05942 p += 13;
05943 }
05944 }
05945 *p++ = '%';
05946 *p++ = 'l';
05947 *p++ = '0' + label;
05948 *p = '\0';
05949
05950 if (noop)
05951 strcpy (p, "\n\tnop");
05952
05953 return string;
05954 }
05955
05956
05957
05958
05959
05960
05961 static int
05962 epilogue_renumber (where, test)
05963 register rtx *where;
05964 int test;
05965 {
05966 register const char *fmt;
05967 register int i;
05968 register enum rtx_code code;
05969
05970 if (*where == 0)
05971 return 0;
05972
05973 code = GET_CODE (*where);
05974
05975 switch (code)
05976 {
05977 case REG:
05978 if (REGNO (*where) >= 8 && REGNO (*where) < 24)
05979 return 1;
05980 if (! test && REGNO (*where) >= 24 && REGNO (*where) < 32)
05981 *where = gen_rtx (REG, GET_MODE (*where), OUTGOING_REGNO (REGNO(*where)));
05982 case SCRATCH:
05983 case CC0:
05984 case PC:
05985 case CONST_INT:
05986 case CONST_DOUBLE:
05987 return 0;
05988
05989
05990
05991
05992
05993
05994
05995
05996
05997
05998 case PLUS:
05999 if (GET_CODE (XEXP (*where, 0)) == REG
06000 && REGNO (XEXP (*where, 0)) == HARD_FRAME_POINTER_REGNUM
06001 && (GET_CODE (XEXP (*where, 1)) != CONST_INT
06002 || INTVAL (XEXP (*where, 1)) < SPARC_STACK_BIAS))
06003 return 1;
06004 break;
06005
06006 case MEM:
06007 if (SPARC_STACK_BIAS
06008 && GET_CODE (XEXP (*where, 0)) == REG
06009 && REGNO (XEXP (*where, 0)) == HARD_FRAME_POINTER_REGNUM)
06010 return 1;
06011 break;
06012
06013 default:
06014 break;
06015 }
06016
06017 fmt = GET_RTX_FORMAT (code);
06018
06019 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
06020 {
06021 if (fmt[i] == 'E')
06022 {
06023 register int j;
06024 for (j = XVECLEN (*where, i) - 1; j >= 0; j--)
06025 if (epilogue_renumber (&(XVECEXP (*where, i, j)), test))
06026 return 1;
06027 }
06028 else if (fmt[i] == 'e'
06029 && epilogue_renumber (&(XEXP (*where, i)), test))
06030 return 1;
06031 }
06032 return 0;
06033 }
06034
06035
06036
06037 static const int
06038 reg_leaf_alloc_order[] = REG_LEAF_ALLOC_ORDER;
06039
06040 static const int
06041 reg_nonleaf_alloc_order[] = REG_ALLOC_ORDER;
06042
06043 static const int *const reg_alloc_orders[] = {
06044 reg_leaf_alloc_order,
06045 reg_nonleaf_alloc_order};
06046
06047 void
06048 order_regs_for_local_alloc ()
06049 {
06050 static int last_order_nonleaf = 1;
06051
06052 if (regs_ever_live[15] != last_order_nonleaf)
06053 {
06054 last_order_nonleaf = !last_order_nonleaf;
06055 memcpy ((char *) reg_alloc_order,
06056 (const char *) reg_alloc_orders[last_order_nonleaf],
06057 FIRST_PSEUDO_REGISTER * sizeof (int));
06058 }
06059 }
06060
06061
06062
06063
06064 int
06065 sparc_splitdi_legitimate (reg, mem)
06066 rtx reg;
06067 rtx mem;
06068 {
06069
06070 if (! reload_completed)
06071 abort ();
06072
06073
06074 if (! offsettable_memref_p (mem))
06075 return 0;
06076
06077
06078
06079 if ((REGNO (reg) % 2) == 0
06080 && mem_min_alignment (mem, 8))
06081 return 0;
06082
06083
06084 return 1;
06085 }
06086
06087
06088
06089
06090
06091 int
06092 sparc_absnegfloat_split_legitimate (x, y)
06093 rtx x, y;
06094 {
06095 if (GET_CODE (x) != REG)
06096 return 0;
06097 if (GET_CODE (y) != REG)
06098 return 0;
06099 if (REGNO (x) == REGNO (y))
06100 return 0;
06101 return 1;
06102 }
06103
06104
06105
06106
06107
06108
06109 int
06110 registers_ok_for_ldd_peep (reg1, reg2)
06111 rtx reg1, reg2;
06112 {
06113
06114 if (GET_CODE (reg1) != REG || GET_CODE (reg2) != REG)
06115 return 0;
06116
06117 if (REGNO (reg1) % 2 != 0)
06118 return 0;
06119
06120
06121 if (TARGET_V9 && REGNO (reg1) < 32)
06122 return 0;
06123
06124 return (REGNO (reg1) == REGNO (reg2) - 1);
06125 }
06126
06127
06128
06129
06130
06131
06132
06133
06134
06135
06136
06137
06138
06139
06140
06141
06142
06143
06144
06145
06146
06147
06148
06149
06150
06151
06152
06153
06154
06155
06156
06157
06158 int
06159 mems_ok_for_ldd_peep (mem1, mem2, dependent_reg_rtx)
06160 rtx mem1, mem2, dependent_reg_rtx;
06161 {
06162 rtx addr1, addr2;
06163 unsigned int reg1;
06164 int offset1;
06165
06166
06167 if (MEM_VOLATILE_P (mem1) || MEM_VOLATILE_P (mem2))
06168 return 0;
06169
06170
06171 if (MEM_ALIGN (mem1) < 64)
06172 return 0;
06173
06174 addr1 = XEXP (mem1, 0);
06175 addr2 = XEXP (mem2, 0);
06176
06177
06178 if (GET_CODE (addr1) == PLUS)
06179 {
06180
06181 if (GET_CODE (XEXP (addr1, 0)) != REG)
06182 return 0;
06183 else
06184 {
06185 reg1 = REGNO (XEXP (addr1, 0));
06186
06187 if (GET_CODE (XEXP (addr1, 1)) != CONST_INT)
06188 return 0;
06189 offset1 = INTVAL (XEXP (addr1, 1));
06190 }
06191 }
06192 else if (GET_CODE (addr1) != REG)
06193 return 0;
06194 else
06195 {
06196 reg1 = REGNO (addr1);
06197
06198 offset1 = 0;
06199 }
06200
06201
06202 if (GET_CODE (addr2) != PLUS)
06203 return 0;
06204
06205 if (GET_CODE (XEXP (addr2, 0)) != REG
06206 || GET_CODE (XEXP (addr2, 1)) != CONST_INT)
06207 return 0;
06208
06209 if (reg1 != REGNO (XEXP (addr2, 0)))
06210 return 0;
06211
06212 if (dependent_reg_rtx != NULL_RTX && reg1 == REGNO (dependent_reg_rtx))
06213 return 0;
06214
06215
06216
06217 if (offset1 % 8 != 0)
06218 return 0;
06219
06220
06221 if (INTVAL (XEXP (addr2, 1)) != offset1 + 4)
06222 return 0;
06223
06224
06225
06226 return 1;
06227 }
06228
06229
06230
06231
06232
06233 int
06234 register_ok_for_ldd (reg)
06235 rtx reg;
06236 {
06237
06238 if (GET_CODE (reg) != REG)
06239 return 0;
06240
06241 if (REGNO (reg) < FIRST_PSEUDO_REGISTER)
06242 return (REGNO (reg) % 2 == 0);
06243 else
06244 return 1;
06245 }
06246
06247
06248
06249
06250
06251 void
06252 print_operand (file, x, code)
06253 FILE *file;
06254 rtx x;
06255 int code;
06256 {
06257 switch (code)
06258 {
06259 case '#':
06260
06261 if (dbr_sequence_length () == 0)
06262 fputs ("\n\t nop", file);
06263 return;
06264 case '*':
06265
06266
06267
06268
06269
06270
06271 if (dbr_sequence_length () == 0
06272 && (optimize && (int)sparc_cpu < PROCESSOR_V9))
06273 fputs (",a", file);
06274 return;
06275 case '(':
06276
06277
06278 if (dbr_sequence_length () == 0
06279 && ! (optimize && (int)sparc_cpu < PROCESSOR_V9))
06280 fputs ("\n\t nop", file);
06281 return;
06282 case '_':
06283
06284 fputs (EMBMEDANY_BASE_REG, file);
06285 return;
06286 case '@':
06287
06288
06289
06290 fprintf (file, "%s+%d", frame_base_name, frame_base_offset);
06291 return;
06292 case 'Y':
06293
06294 if (GET_CODE (x) == CONST_INT)
06295 break;
06296 else if (GET_CODE (x) != REG)
06297 output_operand_lossage ("invalid %%Y operand");
06298 else if (REGNO (x) < 8)
06299 fputs (reg_names[REGNO (x)], file);
06300 else if (REGNO (x) >= 24 && REGNO (x) < 32)
06301 fputs (reg_names[REGNO (x)-16], file);
06302 else
06303 output_operand_lossage ("invalid %%Y operand");
06304 return;
06305 case 'L':
06306
06307 if (WORDS_BIG_ENDIAN)
06308 fputs (reg_names[REGNO (x)+1], file);
06309 else
06310 fputs (reg_names[REGNO (x)], file);
06311 return;
06312 case 'H':
06313
06314 if (WORDS_BIG_ENDIAN)
06315 fputs (reg_names[REGNO (x)], file);
06316 else
06317 fputs (reg_names[REGNO (x)+1], file);
06318 return;
06319 case 'R':
06320
06321
06322 fputs (reg_names[REGNO (x)+1], file);
06323 return;
06324 case 'S':
06325
06326
06327 fputs (reg_names[REGNO (x)+2], file);
06328 return;
06329 case 'T':
06330
06331
06332 fputs (reg_names[REGNO (x)+3], file);
06333 return;
06334 case 'x':
06335
06336 if (REGNO (x) == SPARC_ICC_REG)
06337 {
06338
06339
06340 if (GET_MODE (x) == CCmode)
06341 fputs ("%icc", file);
06342 else if (GET_MODE (x) == CCXmode)
06343 fputs ("%xcc", file);
06344 else
06345 abort ();
06346 }
06347 else
06348
06349 fputs (reg_names[REGNO (x)], file);
06350 return;
06351 case 'm':
06352
06353 output_address (XEXP (x, 0));
06354 return;
06355 case 'r':
06356
06357
06358 if (x == const0_rtx
06359 || (GET_MODE (x) != VOIDmode && x == CONST0_RTX (GET_MODE (x))))
06360 {
06361 fputs ("%g0", file);
06362 return;
06363 }
06364 else
06365 break;
06366
06367 case 'A':
06368 switch (GET_CODE (x))
06369 {
06370 case IOR: fputs ("or", file); break;
06371 case AND: fputs ("and", file); break;
06372 case XOR: fputs ("xor", file); break;
06373 default: output_operand_lossage ("invalid %%A operand");
06374 }
06375 return;
06376
06377 case 'B':
06378 switch (GET_CODE (x))
06379 {
06380 case IOR: fputs ("orn", file); break;
06381 case AND: fputs ("andn", file); break;
06382 case XOR: fputs ("xnor", file); break;
06383 default: output_operand_lossage ("invalid %%B operand");
06384 }
06385 return;
06386
06387
06388 case 'c' :
06389 case 'C':
06390 {
06391 enum rtx_code rc = GET_CODE (x);
06392
06393 if (code == 'c')
06394 {
06395 enum machine_mode mode = GET_MODE (XEXP (x, 0));
06396 if (mode == CCFPmode || mode == CCFPEmode)
06397 rc = reverse_condition_maybe_unordered (GET_CODE (x));
06398 else
06399 rc = reverse_condition (GET_CODE (x));
06400 }
06401 switch (rc)
06402 {
06403 case NE: fputs ("ne", file); break;
06404 case EQ: fputs ("e", file); break;
06405 case GE: fputs ("ge", file); break;
06406 case GT: fputs ("g", file); break;
06407 case LE: fputs ("le", file); break;
06408 case LT: fputs ("l", file); break;
06409 case GEU: fputs ("geu", file); break;
06410 case GTU: fputs ("gu", file); break;
06411 case LEU: fputs ("leu", file); break;
06412 case LTU: fputs ("lu", file); break;
06413 case LTGT: fputs ("lg", file); break;
06414 case UNORDERED: fputs ("u", file); break;
06415 case ORDERED: fputs ("o", file); break;
06416 case UNLT: fputs ("ul", file); break;
06417 case UNLE: fputs ("ule", file); break;
06418 case UNGT: fputs ("ug", file); break;
06419 case UNGE: fputs ("uge", file); break;
06420 case UNEQ: fputs ("ue", file); break;
06421 default: output_operand_lossage (code == 'c'
06422 ? "invalid %%c operand"
06423 : "invalid %%C operand");
06424 }
06425 return;
06426 }
06427
06428
06429 case 'd':
06430 case 'D':
06431 {
06432 enum rtx_code rc = (code == 'd'
06433 ? reverse_condition (GET_CODE (x))
06434 : GET_CODE (x));
06435 switch (rc)
06436 {
06437 case NE: fputs ("ne", file); break;
06438 case EQ: fputs ("e", file); break;
06439 case GE: fputs ("gez", file); break;
06440 case LT: fputs ("lz", file); break;
06441 case LE: fputs ("lez", file); break;
06442 case GT: fputs ("gz", file); break;
06443 default: output_operand_lossage (code == 'd'
06444 ? "invalid %%d operand"
06445 : "invalid %%D operand");
06446 }
06447 return;
06448 }
06449
06450 case 'b':
06451 {
06452
06453 int i = trunc_int_for_mode (INTVAL (x), QImode);
06454 fprintf (file, "%d", i);
06455 return;
06456 }
06457
06458 case 'f':
06459
06460 if (GET_CODE (x) != MEM)
06461 output_operand_lossage ("invalid %%f operand");
06462 output_address (XEXP (x, 0));
06463 return;
06464
06465 case 0:
06466
06467 break;
06468
06469 default:
06470
06471 output_operand_lossage ("invalid operand output code");
06472 }
06473
06474 if (GET_CODE (x) == REG)
06475 fputs (reg_names[REGNO (x)], file);
06476 else if (GET_CODE (x) == MEM)
06477 {
06478 fputc ('[', file);
06479
06480 if (CONSTANT_P (XEXP (x, 0)))
06481 fputs ("%g0+", file);
06482 output_address (XEXP (x, 0));
06483 fputc (']', file);
06484 }
06485 else if (GET_CODE (x) == HIGH)
06486 {
06487 fputs ("%hi(", file);
06488 output_addr_const (file, XEXP (x, 0));
06489 fputc (')', file);
06490 }
06491 else if (GET_CODE (x) == LO_SUM)
06492 {
06493 print_operand (file, XEXP (x, 0), 0);
06494 if (TARGET_CM_MEDMID)
06495 fputs ("+%l44(", file);
06496 else
06497 fputs ("+%lo(", file);
06498 output_addr_const (file, XEXP (x, 1));
06499 fputc (')', file);
06500 }
06501 else if (GET_CODE (x) == CONST_DOUBLE
06502 && (GET_MODE (x) == VOIDmode
06503 || GET_MODE_CLASS (GET_MODE (x)) == MODE_INT))
06504 {
06505 if (CONST_DOUBLE_HIGH (x) == 0)
06506 fprintf (file, "%u", (unsigned int) CONST_DOUBLE_LOW (x));
06507 else if (CONST_DOUBLE_HIGH (x) == -1
06508 && CONST_DOUBLE_LOW (x) < 0)
06509 fprintf (file, "%d", (int) CONST_DOUBLE_LOW (x));
06510 else
06511 output_operand_lossage ("long long constant not a valid immediate operand");
06512 }
06513 else if (GET_CODE (x) == CONST_DOUBLE)
06514 output_operand_lossage ("floating point constant not a valid immediate operand");
06515 else { output_addr_const (file, x); }
06516 }
06517
06518
06519
06520
06521 static bool
06522 sparc_assemble_integer (x, size, aligned_p)
06523 rtx x;
06524 unsigned int size;
06525 int aligned_p;
06526 {
06527
06528
06529 if (aligned_p && size == 8
06530 && (GET_CODE (x) != CONST_INT && GET_CODE (x) != CONST_DOUBLE))
06531 {
06532 if (TARGET_V9)
06533 {
06534 assemble_integer_with_op ("\t.xword\t", x);
06535 return true;
06536 }
06537 else
06538 {
06539 assemble_aligned_integer (4, const0_rtx);
06540 assemble_aligned_integer (4, x);
06541 return true;
06542 }
06543 }
06544 return default_assemble_integer (x, size, aligned_p);
06545 }
06546
06547
06548
06549
06550
06551 #ifndef CHAR_TYPE_SIZE
06552 #define CHAR_TYPE_SIZE BITS_PER_UNIT
06553 #endif
06554
06555 #ifndef SHORT_TYPE_SIZE
06556 #define SHORT_TYPE_SIZE (BITS_PER_UNIT * 2)
06557 #endif
06558
06559 #ifndef INT_TYPE_SIZE
06560 #define INT_TYPE_SIZE BITS_PER_WORD
06561 #endif
06562
06563 #ifndef LONG_TYPE_SIZE
06564 #define LONG_TYPE_SIZE BITS_PER_WORD
06565 #endif
06566
06567 #ifndef LONG_LONG_TYPE_SIZE
06568 #define LONG_LONG_TYPE_SIZE (BITS_PER_WORD * 2)
06569 #endif
06570
06571 #ifndef FLOAT_TYPE_SIZE
06572 #define FLOAT_TYPE_SIZE BITS_PER_WORD
06573 #endif
06574
06575 #ifndef DOUBLE_TYPE_SIZE
06576 #define DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
06577 #endif
06578
06579 #ifndef LONG_DOUBLE_TYPE_SIZE
06580 #define LONG_DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
06581 #endif
06582
06583 unsigned long
06584 sparc_type_code (type)
06585 register tree type;
06586 {
06587 register unsigned long qualifiers = 0;
06588 register unsigned shift;
06589
06590
06591
06592
06593
06594
06595 for (shift = 6; shift < 30; shift += 2, type = TREE_TYPE (type))
06596 {
06597 switch (TREE_CODE (type))
06598 {
06599 case ERROR_MARK:
06600 return qualifiers;
06601
06602 case ARRAY_TYPE:
06603 qualifiers |= (3 << shift);
06604 break;
06605
06606 case FUNCTION_TYPE:
06607 case METHOD_TYPE:
06608 qualifiers |= (2 << shift);
06609 break;
06610
06611 case POINTER_TYPE:
06612 case REFERENCE_TYPE:
06613 case OFFSET_TYPE:
06614 qualifiers |= (1 << shift);
06615 break;
06616
06617 case RECORD_TYPE:
06618 return (qualifiers | 8);
06619
06620 case UNION_TYPE:
06621 case QUAL_UNION_TYPE:
06622 return (qualifiers | 9);
06623
06624 case ENUMERAL_TYPE:
06625 return (qualifiers | 10);
06626
06627 case VOID_TYPE:
06628 return (qualifiers | 16);
06629
06630 case INTEGER_TYPE:
06631
06632
06633 if (TREE_TYPE (type) != 0)
06634 break;
06635
06636
06637
06638
06639
06640
06641
06642
06643
06644
06645
06646
06647 if (TYPE_PRECISION (type) <= CHAR_TYPE_SIZE)
06648 return (qualifiers | (TREE_UNSIGNED (type) ? 12 : 2));
06649
06650 else if (TYPE_PRECISION (type) <= SHORT_TYPE_SIZE)
06651 return (qualifiers | (TREE_UNSIGNED (type) ? 13 : 3));
06652
06653 else if (TYPE_PRECISION (type) <= INT_TYPE_SIZE)
06654 return (qualifiers | (TREE_UNSIGNED (type) ? 14 : 4));
06655
06656 else
06657 return (qualifiers | (TREE_UNSIGNED (type) ? 15 : 5));
06658
06659 case REAL_TYPE:
06660
06661
06662 if (TREE_TYPE (type) != 0)
06663 break;
06664
06665
06666
06667
06668 if (TYPE_PRECISION (type) == FLOAT_TYPE_SIZE)
06669 return (qualifiers | 6);
06670
06671 else
06672 return (qualifiers | 7);
06673
06674 case COMPLEX_TYPE:
06675
06676
06677
06678 return (qualifiers | 7);
06679
06680 case CHAR_TYPE:
06681 case BOOLEAN_TYPE:
06682 case FILE_TYPE:
06683 case SET_TYPE:
06684 case LANG_TYPE:
06685 return qualifiers;
06686
06687 default:
06688 abort ();
06689 }
06690 }
06691
06692 return qualifiers;
06693 }
06694
06695
06696
06697
06698
06699
06700
06701
06702
06703
06704
06705
06706
06707
06708 void
06709 sparc_initialize_trampoline (tramp, fnaddr, cxt)
06710 rtx tramp, fnaddr, cxt;
06711 {
06712
06713
06714
06715
06716
06717
06718
06719
06720
06721
06722 #ifdef TRANSFER_FROM_TRAMPOLINE
06723 emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__enable_execute_stack"),
06724 LCT_NORMAL, VOIDmode, 1, tramp, Pmode);
06725 #endif
06726
06727 emit_move_insn
06728 (gen_rtx_MEM (SImode, plus_constant (tramp, 0)),
06729 expand_binop (SImode, ior_optab,
06730 expand_shift (RSHIFT_EXPR, SImode, fnaddr,
06731 size_int (10), 0, 1),
06732 GEN_INT (trunc_int_for_mode (0x03000000, SImode)),
06733 NULL_RTX, 1, OPTAB_DIRECT));
06734
06735 emit_move_insn
06736 (gen_rtx_MEM (SImode, plus_constant (tramp, 4)),
06737 expand_binop (SImode, ior_optab,
06738 expand_shift (RSHIFT_EXPR, SImode, cxt,
06739 size_int (10), 0, 1),
06740 GEN_INT (trunc_int_for_mode (0x05000000, SImode)),
06741 NULL_RTX, 1, OPTAB_DIRECT));
06742
06743 emit_move_insn
06744 (gen_rtx_MEM (SImode, plus_constant (tramp, 8)),
06745 expand_binop (SImode, ior_optab,
06746 expand_and (SImode, fnaddr, GEN_INT (0x3ff), NULL_RTX),
06747 GEN_INT (trunc_int_for_mode (0x81c06000, SImode)),
06748 NULL_RTX, 1, OPTAB_DIRECT));
06749
06750 emit_move_insn
06751 (gen_rtx_MEM (SImode, plus_constant (tramp, 12)),
06752 expand_binop (SImode, ior_optab,
06753 expand_and (SImode, cxt, GEN_INT (0x3ff), NULL_RTX),
06754 GEN_INT (trunc_int_for_mode (0x8410a000, SImode)),
06755 NULL_RTX, 1, OPTAB_DIRECT));
06756
06757
06758
06759 emit_insn (gen_flush (validize_mem (gen_rtx_MEM (SImode, tramp))));
06760 if (sparc_cpu != PROCESSOR_ULTRASPARC)
06761 emit_insn (gen_flush (validize_mem (gen_rtx_MEM (SImode,
06762 plus_constant (tramp, 8)))));
06763 }
06764
06765
06766
06767
06768
06769 void
06770 sparc64_initialize_trampoline (tramp, fnaddr, cxt)
06771 rtx tramp, fnaddr, cxt;
06772 {
06773 #ifdef TRANSFER_FROM_TRAMPOLINE
06774 emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__enable_execute_stack"),
06775 LCT_NORMAL, VOIDmode, 1, tramp, Pmode);
06776 #endif
06777
06778
06779
06780
06781
06782
06783
06784
06785
06786 emit_move_insn (gen_rtx_MEM (SImode, tramp),
06787 GEN_INT (trunc_int_for_mode (0x83414000, SImode)));
06788 emit_move_insn (gen_rtx_MEM (SImode, plus_constant (tramp, 4)),
06789 GEN_INT (trunc_int_for_mode (0xca586018, SImode)));
06790 emit_move_insn (gen_rtx_MEM (SImode, plus_constant (tramp, 8)),
06791 GEN_INT (trunc_int_for_mode (0x81c14000, SImode)));
06792 emit_move_insn (gen_rtx_MEM (SImode, plus_constant (tramp, 12)),
06793 GEN_INT (trunc_int_for_mode (0xca586010, SImode)));
06794 emit_move_insn (gen_rtx_MEM (DImode, plus_constant (tramp, 16)), cxt);
06795 emit_move_insn (gen_rtx_MEM (DImode, plus_constant (tramp, 24)), fnaddr);
06796 emit_insn (gen_flushdi (validize_mem (gen_rtx_MEM (DImode, tramp))));
06797
06798 if (sparc_cpu != PROCESSOR_ULTRASPARC)
06799 emit_insn (gen_flushdi (validize_mem (gen_rtx_MEM (DImode, plus_constant (tramp, 8)))));
06800 }
06801
06802
06803
06804
06805
06806
06807
06808
06809
06810
06811
06812
06813
06814
06815
06816
06817
06818
06819
06820
06821
06822
06823
06824
06825
06826
06827
06828
06829
06830
06831
06832
06833
06834
06835
06836
06837
06838
06839
06840
06841
06842
06843
06844
06845
06846
06847
06848
06849
06850
06851
06852
06853
06854
06855
06856
06857
06858
06859
06860
06861
06862
06863
06864
06865
06866 struct sparc_frame_info
06867 {
06868 unsigned long total_size;
06869 unsigned long var_size;
06870 unsigned long args_size;
06871 unsigned long extra_size;
06872 unsigned int gp_reg_size;
06873 unsigned int fp_reg_size;
06874 unsigned long gmask;
06875 unsigned long fmask;
06876 unsigned long reg_offset;
06877 int initialized;
06878 };
06879
06880
06881 struct sparc_frame_info current_frame_info;
06882
06883
06884 struct sparc_frame_info zero_frame_info;
06885
06886
06887
06888 #define RETURN_ADDR_REGNUM 15
06889 #define HARD_FRAME_POINTER_MASK (1 << (HARD_FRAME_POINTER_REGNUM))
06890 #define RETURN_ADDR_MASK (1 << (RETURN_ADDR_REGNUM))
06891
06892 #define MUST_SAVE_REGISTER(regno) \
06893 ((regs_ever_live[regno] && !call_used_regs[regno]) \
06894 || (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed) \
06895 || (regno == RETURN_ADDR_REGNUM && regs_ever_live[RETURN_ADDR_REGNUM]))
06896
06897
06898
06899
06900 unsigned long
06901 sparc_flat_compute_frame_size (size)
06902 int size;
06903 {
06904 int regno;
06905 unsigned long total_size;
06906 unsigned long var_size;
06907 unsigned long args_size;
06908 unsigned long extra_size;
06909 unsigned int gp_reg_size;
06910 unsigned int fp_reg_size;
06911 unsigned long gmask;
06912 unsigned long fmask;
06913 unsigned long reg_offset;
06914 int need_aligned_p;
06915
06916
06917
06918 extra_size = -STARTING_FRAME_OFFSET + FIRST_PARM_OFFSET(0);
06919 var_size = size;
06920 gp_reg_size = 0;
06921 fp_reg_size = 0;
06922 gmask = 0;
06923 fmask = 0;
06924 reg_offset = 0;
06925 need_aligned_p = 0;
06926
06927 args_size = 0;
06928 if (!leaf_function_p ())
06929 {
06930
06931 args_size = current_function_outgoing_args_size + 24;
06932 }
06933 total_size = var_size + args_size;
06934
06935
06936 for (regno = 1; regno <= 31; regno++)
06937 {
06938 if (MUST_SAVE_REGISTER (regno))
06939 {
06940
06941
06942 if ((regno & 0x1) == 0 && MUST_SAVE_REGISTER (regno+1))
06943 {
06944 if (gp_reg_size % 8 != 0)
06945 gp_reg_size += 4;
06946 gp_reg_size += 2 * UNITS_PER_WORD;
06947 gmask |= 3 << regno;
06948 regno++;
06949 need_aligned_p = 1;
06950 }
06951 else
06952 {
06953 gp_reg_size += UNITS_PER_WORD;
06954 gmask |= 1 << regno;
06955 }
06956 }
06957 }
06958
06959
06960 for (regno = 32; regno <= 63; regno++)
06961 {
06962 if (regs_ever_live[regno] && !call_used_regs[regno])
06963 {
06964 fp_reg_size += UNITS_PER_WORD;
06965 fmask |= 1 << (regno - 32);
06966 }
06967 }
06968
06969 if (gmask || fmask)
06970 {
06971 int n;
06972 reg_offset = FIRST_PARM_OFFSET(0) + args_size;
06973
06974 n = reg_offset % 8;
06975 if (need_aligned_p && n != 0)
06976 {
06977 total_size += 8 - n;
06978 reg_offset += 8 - n;
06979 }
06980 total_size += gp_reg_size + fp_reg_size;
06981 }
06982
06983
06984
06985
06986 if (total_size > 0)
06987 total_size += extra_size;
06988 else
06989 extra_size = 0;
06990
06991 total_size = SPARC_STACK_ALIGN (total_size);
06992
06993
06994 current_frame_info.total_size = total_size;
06995 current_frame_info.var_size = var_size;
06996 current_frame_info.args_size = args_size;
06997 current_frame_info.extra_size = extra_size;
06998 current_frame_info.gp_reg_size = gp_reg_size;
06999 current_frame_info.fp_reg_size = fp_reg_size;
07000 current_frame_info.gmask = gmask;
07001 current_frame_info.fmask = fmask;
07002 current_frame_info.reg_offset = reg_offset;
07003 current_frame_info.initialized = reload_completed;
07004
07005
07006 return total_size;
07007 }
07008
07009
07010
07011
07012
07013
07014
07015
07016
07017
07018
07019 void
07020 sparc_flat_save_restore (file, base_reg, offset, gmask, fmask, word_op,
07021 doubleword_op, base_offset)
07022 FILE *file;
07023 const char *base_reg;
07024 unsigned int offset;
07025 unsigned long gmask;
07026 unsigned long fmask;
07027 const char *word_op;
07028 const char *doubleword_op;
07029 unsigned long base_offset;
07030 {
07031 int regno;
07032
07033 if (gmask == 0 && fmask == 0)
07034 return;
07035
07036
07037
07038
07039
07040
07041 if (gmask)
07042 {
07043 for (regno = 1; regno <= 31; regno++)
07044 {
07045 if ((gmask & (1L << regno)) != 0)
07046 {
07047 if ((regno & 0x1) == 0 && ((gmask & (1L << (regno+1))) != 0))
07048 {
07049
07050
07051
07052
07053 if (offset % 8 != 0)
07054 offset += UNITS_PER_WORD;
07055
07056 if (word_op[0] == 's')
07057 {
07058 fprintf (file, "\t%s\t%s, [%s+%d]\n",
07059 doubleword_op, reg_names[regno],
07060 base_reg, offset);
07061 if (dwarf2out_do_frame ())
07062 {
07063 char *l = dwarf2out_cfi_label ();
07064 dwarf2out_reg_save (l, regno, offset + base_offset);
07065 dwarf2out_reg_save
07066 (l, regno+1, offset+base_offset + UNITS_PER_WORD);
07067 }
07068 }
07069 else
07070 fprintf (file, "\t%s\t[%s+%d], %s\n",
07071 doubleword_op, base_reg, offset,
07072 reg_names[regno]);
07073
07074 offset += 2 * UNITS_PER_WORD;
07075 regno++;
07076 }
07077 else
07078 {
07079 if (word_op[0] == 's')
07080 {
07081 fprintf (file, "\t%s\t%s, [%s+%d]\n",
07082 word_op, reg_names[regno],
07083 base_reg, offset);
07084 if (dwarf2out_do_frame ())
07085 dwarf2out_reg_save ("", regno, offset + base_offset);
07086 }
07087 else
07088 fprintf (file, "\t%s\t[%s+%d], %s\n",
07089 word_op, base_reg, offset, reg_names[regno]);
07090
07091 offset += UNITS_PER_WORD;
07092 }
07093 }
07094 }
07095 }
07096
07097 if (fmask)
07098 {
07099 for (regno = 32; regno <= 63; regno++)
07100 {
07101 if ((fmask & (1L << (regno - 32))) != 0)
07102 {
07103 if (word_op[0] == 's')
07104 {
07105 fprintf (file, "\t%s\t%s, [%s+%d]\n",
07106 word_op, reg_names[regno],
07107 base_reg, offset);
07108 if (dwarf2out_do_frame ())
07109 dwarf2out_reg_save ("", regno, offset + base_offset);
07110 }
07111 else
07112 fprintf (file, "\t%s\t[%s+%d], %s\n",
07113 word_op, base_reg, offset, reg_names[regno]);
07114
07115 offset += UNITS_PER_WORD;
07116 }
07117 }
07118 }
07119 }
07120
07121
07122
07123 static void
07124 sparc_flat_function_prologue (file, size)
07125 FILE *file;
07126 HOST_WIDE_INT size;
07127 {
07128 const char *sp_str = reg_names[STACK_POINTER_REGNUM];
07129 unsigned long gmask = current_frame_info.gmask;
07130
07131 sparc_output_scratch_registers (file);
07132
07133
07134 fprintf (file, "\t%s#PROLOGUE# 0\n", ASM_COMMENT_START);
07135 fprintf (file, "\t%s# vars= %ld, regs= %d/%d, args= %d, extra= %ld\n",
07136 ASM_COMMENT_START,
07137 current_frame_info.var_size,
07138 current_frame_info.gp_reg_size / 4,
07139 current_frame_info.fp_reg_size / 4,
07140 current_function_outgoing_args_size,
07141 current_frame_info.extra_size);
07142
07143 size = SPARC_STACK_ALIGN (size);
07144 size = (! current_frame_info.initialized
07145 ? sparc_flat_compute_frame_size (size)
07146 : current_frame_info.total_size);
07147
07148
07149 if (size == 0 && (gmask || current_frame_info.fmask))
07150 abort ();
07151
07152
07153
07154
07155
07156
07157
07158
07159
07160
07161
07162
07163
07164 if (size > 0)
07165 {
07166 unsigned int reg_offset = current_frame_info.reg_offset;
07167 const char *const fp_str = reg_names[HARD_FRAME_POINTER_REGNUM];
07168 static const char *const t1_str = "%g1";
07169
07170
07171
07172
07173
07174
07175
07176
07177
07178
07179
07180
07181
07182 if (reg_offset < 4096 - 64 * (unsigned) UNITS_PER_WORD)
07183 {
07184 if (size <= 4096)
07185 {
07186 fprintf (file, "\tadd\t%s, %d, %s\n",
07187 sp_str, (int) -size, sp_str);
07188 if (gmask & HARD_FRAME_POINTER_MASK)
07189 {
07190 fprintf (file, "\tst\t%s, [%s+%d]\n",
07191 fp_str, sp_str, reg_offset);
07192 fprintf (file, "\tsub\t%s, %d, %s\t%s# set up frame pointer\n",
07193 sp_str, (int) -size, fp_str, ASM_COMMENT_START);
07194 reg_offset += 4;
07195 }
07196 }
07197 else
07198 {
07199 fprintf (file, "\tset\t");
07200 fprintf (file, HOST_WIDE_INT_PRINT_DEC, size);
07201 fprintf (file, ", %s\n\tsub\t%s, %s, %s\n",
07202 t1_str, sp_str, t1_str, sp_str);
07203 if (gmask & HARD_FRAME_POINTER_MASK)
07204 {
07205 fprintf (file, "\tst\t%s, [%s+%d]\n",
07206 fp_str, sp_str, reg_offset);
07207 fprintf (file, "\tadd\t%s, %s, %s\t%s# set up frame pointer\n",
07208 sp_str, t1_str, fp_str, ASM_COMMENT_START);
07209 reg_offset += 4;
07210 }
07211 }
07212 if (dwarf2out_do_frame ())
07213 {
07214 char *l = dwarf2out_cfi_label ();
07215 if (gmask & HARD_FRAME_POINTER_MASK)
07216 {
07217 dwarf2out_reg_save (l, HARD_FRAME_POINTER_REGNUM,
07218 reg_offset - 4 - size);
07219 dwarf2out_def_cfa (l, HARD_FRAME_POINTER_REGNUM, 0);
07220 }
07221 else
07222 dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, size);
07223 }
07224 if (gmask & RETURN_ADDR_MASK)
07225 {
07226 fprintf (file, "\tst\t%s, [%s+%d]\n",
07227 reg_names[RETURN_ADDR_REGNUM], sp_str, reg_offset);
07228 if (dwarf2out_do_frame ())
07229 dwarf2out_return_save ("", reg_offset - size);
07230 reg_offset += 4;
07231 }
07232 sparc_flat_save_restore (file, sp_str, reg_offset,
07233 gmask & ~(HARD_FRAME_POINTER_MASK | RETURN_ADDR_MASK),
07234 current_frame_info.fmask,
07235 "st", "std", -size);
07236 }
07237 else
07238 {
07239
07240
07241
07242 unsigned HOST_WIDE_INT size1 = ((size - reg_offset + 64) + 15) & -16;
07243
07244 unsigned HOST_WIDE_INT offset = size1 - (size - reg_offset);
07245
07246 if (size1 <= 4096)
07247 {
07248 fprintf (file, "\tadd\t%s, %d, %s\n",
07249 sp_str, (int) -size1, sp_str);
07250 if (gmask & HARD_FRAME_POINTER_MASK)
07251 {
07252 fprintf (file, "\tst\t%s, [%s+%d]\n\tsub\t%s, %d, %s\t%s# set up frame pointer\n",
07253 fp_str, sp_str, (int) offset, sp_str, (int) -size1,
07254 fp_str, ASM_COMMENT_START);
07255 offset += 4;
07256 }
07257 }
07258 else
07259 {
07260 fprintf (file, "\tset\t");
07261 fprintf (file, HOST_WIDE_INT_PRINT_DEC, size1);
07262 fprintf (file, ", %s\n\tsub\t%s, %s, %s\n",
07263 t1_str, sp_str, t1_str, sp_str);
07264 if (gmask & HARD_FRAME_POINTER_MASK)
07265 {
07266 fprintf (file, "\tst\t%s, [%s+%d]\n\tadd\t%s, %s, %s\t%s# set up frame pointer\n",
07267 fp_str, sp_str, (int) offset, sp_str, t1_str,
07268 fp_str, ASM_COMMENT_START);
07269 offset += 4;
07270 }
07271 }
07272 if (dwarf2out_do_frame ())
07273 {
07274 char *l = dwarf2out_cfi_label ();
07275 if (gmask & HARD_FRAME_POINTER_MASK)
07276 {
07277 dwarf2out_reg_save (l, HARD_FRAME_POINTER_REGNUM,
07278 offset - 4 - size1);
07279 dwarf2out_def_cfa (l, HARD_FRAME_POINTER_REGNUM, 0);
07280 }
07281 else
07282 dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, size1);
07283 }
07284 if (gmask & RETURN_ADDR_MASK)
07285 {
07286 fprintf (file, "\tst\t%s, [%s+%d]\n",
07287 reg_names[RETURN_ADDR_REGNUM], sp_str, (int) offset);
07288 if (dwarf2out_do_frame ())
07289
07290
07291 dwarf2out_return_save ("", offset - size1);
07292 offset += 4;
07293 }
07294 sparc_flat_save_restore (file, sp_str, offset,
07295 gmask & ~(HARD_FRAME_POINTER_MASK | RETURN_ADDR_MASK),
07296 current_frame_info.fmask,
07297 "st", "std", -size1);
07298 fprintf (file, "\tset\t");
07299 fprintf (file, HOST_WIDE_INT_PRINT_DEC, size - size1);
07300 fprintf (file, ", %s\n\tsub\t%s, %s, %s\n",
07301 t1_str, sp_str, t1_str, sp_str);
07302 if (dwarf2out_do_frame ())
07303 if (! (gmask & HARD_FRAME_POINTER_MASK))
07304 dwarf2out_def_cfa ("", STACK_POINTER_REGNUM, size);
07305 }
07306 }
07307
07308 fprintf (file, "\t%s#PROLOGUE# 1\n", ASM_COMMENT_START);
07309 }
07310
07311
07312
07313
07314 static void
07315 sparc_flat_function_epilogue (file, size)
07316 FILE *file;
07317 HOST_WIDE_INT size;
07318 {
07319 rtx epilogue_delay = current_function_epilogue_delay_list;
07320 int noepilogue = FALSE;
07321
07322
07323 fprintf (file, "\t%s#EPILOGUE#\n", ASM_COMMENT_START);
07324
07325
07326
07327
07328
07329
07330 size = SPARC_STACK_ALIGN (size);
07331 size = (!current_frame_info.initialized
07332 ? sparc_flat_compute_frame_size (size)
07333 : current_frame_info.total_size);
07334
07335 if (size == 0 && epilogue_delay == 0)
07336 {
07337 rtx insn = get_last_insn ();
07338
07339
07340
07341 if (GET_CODE (insn) == NOTE)
07342 insn = prev_nonnote_insn (insn);
07343 if (insn && GET_CODE (insn) == BARRIER)
07344 noepilogue = TRUE;
07345 }
07346
07347 if (!noepilogue)
07348 {
07349 unsigned HOST_WIDE_INT reg_offset = current_frame_info.reg_offset;
07350 unsigned HOST_WIDE_INT size1;
07351 const char *const sp_str = reg_names[STACK_POINTER_REGNUM];
07352 const char *const fp_str = reg_names[HARD_FRAME_POINTER_REGNUM];
07353 static const char *const t1_str = "%g1";
07354
07355
07356
07357
07358
07359 if (size > 4095)
07360 {
07361 fprintf (file, "\tset\t");
07362 fprintf (file, HOST_WIDE_INT_PRINT_DEC, size);
07363 fprintf (file, ", %s\n", t1_str);
07364 }
07365
07366 if (frame_pointer_needed)
07367 {
07368 if (size > 4095)
07369 fprintf (file,"\tsub\t%s, %s, %s\t\t%s# sp not trusted here\n",
07370 fp_str, t1_str, sp_str, ASM_COMMENT_START);
07371 else
07372 fprintf (file,"\tsub\t%s, %d, %s\t\t%s# sp not trusted here\n",
07373 fp_str, (int) size, sp_str, ASM_COMMENT_START);
07374 }
07375
07376
07377 if (reg_offset < 4096 - 64 * (unsigned) UNITS_PER_WORD)
07378 {
07379 size1 = 0;
07380 }
07381 else
07382 {
07383
07384
07385
07386 size1 = ((reg_offset - 64 - 16) + 15) & -16;
07387
07388 reg_offset = size1 - reg_offset;
07389
07390 fprintf (file, "\tset\t");
07391 fprintf (file, HOST_WIDE_INT_PRINT_DEC, size1);
07392 fprintf (file, ", %s\n\tadd\t%s, %s, %s\n",
07393 t1_str, sp_str, t1_str, sp_str);
07394 }
07395
07396
07397
07398 if (current_frame_info.gmask & HARD_FRAME_POINTER_MASK)
07399 {
07400 fprintf (file, "\tld\t[%s+%d], %s\n",
07401 sp_str, (int) reg_offset, fp_str);
07402 reg_offset += 4;
07403 }
07404 if (current_frame_info.gmask & RETURN_ADDR_MASK)
07405 {
07406 fprintf (file, "\tld\t[%s+%d], %s\n",
07407 sp_str, (int) reg_offset, reg_names[RETURN_ADDR_REGNUM]);
07408 reg_offset += 4;
07409 }
07410
07411
07412 sparc_flat_save_restore (file, sp_str, reg_offset,
07413 current_frame_info.gmask & ~(HARD_FRAME_POINTER_MASK | RETURN_ADDR_MASK),
07414 current_frame_info.fmask,
07415 "ld", "ldd", 0);
07416
07417
07418
07419 if (size1 > 0)
07420 {
07421 size -= size1;
07422 if (size > 4095)
07423 {
07424 fprintf (file, "\tset\t");
07425 fprintf (file, HOST_WIDE_INT_PRINT_DEC, size);
07426 fprintf (file, ", %s\n", t1_str);
07427 }
07428 }
07429
07430 if (current_function_returns_struct)
07431 fprintf (file, "\tjmp\t%%o7+12\n");
07432 else
07433 fprintf (file, "\tretl\n");
07434
07435
07436
07437
07438
07439
07440 if (epilogue_delay)
07441 {
07442 if (size)
07443 abort ();
07444 final_scan_insn (XEXP (epilogue_delay, 0), file, 1, -2, 1);
07445 }
07446
07447 else if (size > 4095)
07448 fprintf (file, "\tadd\t%s, %s, %s\n", sp_str, t1_str, sp_str);
07449
07450 else if (size > 0)
07451 fprintf (file, "\tadd\t%s, %d, %s\n", sp_str, (int) size, sp_str);
07452
07453 else
07454 fprintf (file, "\tnop\n");
07455 }
07456
07457
07458 current_frame_info = zero_frame_info;
07459
07460 sparc_output_deferred_case_vectors ();
07461 }
07462
07463
07464
07465
07466
07467
07468 int
07469 sparc_flat_epilogue_delay_slots ()
07470 {
07471 if (!current_frame_info.initialized)
07472 (void) sparc_flat_compute_frame_size (get_frame_size ());
07473
07474 if (current_frame_info.total_size == 0)
07475 return 1;
07476
07477 return 0;
07478 }
07479
07480
07481
07482
07483
07484 int
07485 sparc_flat_eligible_for_epilogue_delay (trial, slot)
07486 rtx trial;
07487 int slot ATTRIBUTE_UNUSED;
07488 {
07489 rtx pat = PATTERN (trial);
07490
07491 if (get_attr_length (trial) != 1)
07492 return 0;
07493
07494 if (! reg_mentioned_p (stack_pointer_rtx, pat)
07495 && ! reg_mentioned_p (frame_pointer_rtx, pat))
07496 return 1;
07497
07498 return 0;
07499 }
07500
07501
07502
07503
07504 static int
07505 supersparc_adjust_cost (insn, link, dep_insn, cost)
07506 rtx insn;
07507 rtx link;
07508 rtx dep_insn;
07509 int cost;
07510 {
07511 enum attr_type insn_type;
07512
07513 if (! recog_memoized (insn))
07514 return 0;
07515
07516 insn_type = get_attr_type (insn);
07517
07518 if (REG_NOTE_KIND (link) == 0)
07519 {
07520
07521
07522
07523
07524
07525
07526
07527 if (insn_type == TYPE_LOAD || insn_type == TYPE_FPLOAD)
07528 return cost + 3;
07529
07530
07531 if (insn_type == TYPE_STORE || insn_type == TYPE_FPSTORE)
07532 {
07533 rtx pat = PATTERN(insn);
07534 rtx dep_pat = PATTERN (dep_insn);
07535
07536 if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET)
07537 return cost;
07538
07539
07540
07541
07542 if (rtx_equal_p (SET_DEST (dep_pat), SET_SRC (pat)))
07543 return cost;
07544
07545 return cost + 3;
07546 }
07547
07548
07549
07550 if (insn_type == TYPE_SHIFT)
07551 return cost + 3;
07552 }
07553 else
07554 {
07555
07556
07557
07558
07559
07560
07561
07562 if (insn_type == TYPE_IALU || insn_type == TYPE_SHIFT)
07563 return 0;
07564 }
07565
07566 return cost;
07567 }
07568
07569 static int
07570 hypersparc_adjust_cost (insn, link, dep_insn, cost)
07571 rtx insn;
07572 rtx link;
07573 rtx dep_insn;
07574 int cost;
07575 {
07576 enum attr_type insn_type, dep_type;
07577 rtx pat = PATTERN(insn);
07578 rtx dep_pat = PATTERN (dep_insn);
07579
07580 if (recog_memoized (insn) < 0 || recog_memoized (dep_insn) < 0)
07581 return cost;
07582
07583 insn_type = get_attr_type (insn);
07584 dep_type = get_attr_type (dep_insn);
07585
07586 switch (REG_NOTE_KIND (link))
07587 {
07588 case 0:
07589
07590
07591
07592 switch (insn_type)
07593 {
07594 case TYPE_STORE:
07595 case TYPE_FPSTORE:
07596
07597 if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET)
07598 return cost;
07599
07600 if (rtx_equal_p (SET_DEST (dep_pat), SET_SRC (pat)))
07601 return cost;
07602 return cost + 3;
07603
07604 case TYPE_LOAD:
07605 case TYPE_SLOAD:
07606 case TYPE_FPLOAD:
07607
07608
07609 if (dep_type == TYPE_STORE || dep_type == TYPE_FPSTORE)
07610 {
07611 if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET
07612 || GET_CODE (SET_DEST (dep_pat)) != MEM
07613 || GET_CODE (SET_SRC (pat)) != MEM
07614 || ! rtx_equal_p (XEXP (SET_DEST (dep_pat), 0),
07615 XEXP (SET_SRC (pat), 0)))
07616 return cost + 2;
07617
07618 return cost + 8;
07619 }
07620 break;
07621
07622 case TYPE_BRANCH:
07623
07624
07625 if (dep_type == TYPE_COMPARE)
07626 return 0;
07627
07628
07629 if (dep_type == TYPE_FPCMP)
07630 return cost - 1;
07631 break;
07632 default:
07633 break;
07634 }
07635 break;
07636
07637 case REG_DEP_ANTI:
07638
07639 if (insn_type == TYPE_IALU || insn_type == TYPE_SHIFT)
07640 return 0;
07641 break;
07642
07643 default:
07644 break;
07645 }
07646
07647 return cost;
07648 }
07649
07650 static int
07651 ultrasparc_adjust_cost (insn, link, dep_insn, cost)
07652 rtx insn;
07653 rtx link;
07654 rtx dep_insn;
07655 int cost;
07656 {
07657 enum attr_type insn_type, dep_type;
07658 rtx pat = PATTERN(insn);
07659 rtx dep_pat = PATTERN (dep_insn);
07660
07661 if (recog_memoized (insn) < 0 || recog_memoized (dep_insn) < 0)
07662 return cost;
07663
07664 insn_type = get_attr_type (insn);
07665 dep_type = get_attr_type (dep_insn);
07666
07667
07668
07669
07670 if (insn_type == TYPE_IMUL || insn_type == TYPE_IDIV)
07671 return 0;
07672
07673 #define SLOW_FP(dep_type) \
07674 (dep_type == TYPE_FPSQRTS || dep_type == TYPE_FPSQRTD || \
07675 dep_type == TYPE_FPDIVS || dep_type == TYPE_FPDIVD)
07676
07677 switch (REG_NOTE_KIND (link))
07678 {
07679 case 0:
07680
07681
07682
07683 if (dep_type == TYPE_CMOVE)
07684 {
07685
07686
07687 return cost + 1;
07688 }
07689
07690 switch (insn_type)
07691 {
07692
07693
07694 case TYPE_FPSTORE:
07695 if (! SLOW_FP (dep_type))
07696 return 0;
07697 return cost;
07698
07699 case TYPE_STORE:
07700 if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET)
07701 return cost;
07702
07703 if (rtx_equal_p (SET_DEST (dep_pat), SET_SRC (pat)))
07704
07705
07706
07707 return 0;
07708 return cost;
07709
07710 case TYPE_LOAD:
07711 case TYPE_SLOAD:
07712 case TYPE_FPLOAD:
07713
07714
07715
07716 if (dep_type == TYPE_STORE || dep_type == TYPE_FPSTORE)
07717 {
07718
07719
07720
07721
07722
07723
07724
07725 if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET
07726 || GET_CODE (SET_SRC (pat)) != MEM
07727 || GET_CODE (SET_DEST (dep_pat)) != MEM
07728 || ! rtx_equal_p (XEXP (SET_SRC (pat), 0),
07729 XEXP (SET_DEST (dep_pat), 0)))
07730 return cost + 2;
07731
07732 return cost + 8;
07733 }
07734 return cost;
07735
07736 case TYPE_BRANCH:
07737
07738
07739 if (dep_type == TYPE_COMPARE)
07740 return 0;
07741
07742
07743 if (dep_type == TYPE_FPCMP)
07744 return cost - 1;
07745 return cost;
07746
07747 case TYPE_FPCMOVE:
07748
07749
07750
07751
07752 if (dep_type == TYPE_IALU
07753 && cost < 2)
07754 return 2;
07755
07756
07757 case TYPE_CMOVE:
07758
07759
07760
07761
07762 if (dep_type == TYPE_LOAD || dep_type == TYPE_SLOAD)
07763 return cost + 3;
07764 return cost;
07765
07766 default:
07767 break;
07768 }
07769 break;
07770
07771 case REG_DEP_ANTI:
07772
07773 if (! SLOW_FP (dep_type))
07774 return 0;
07775 break;
07776
07777 case REG_DEP_OUTPUT:
07778
07779
07780 return cost + 1;
07781
07782 default:
07783 break;
07784 }
07785
07786
07787
07788
07789
07790
07791
07792
07793
07794
07795
07796 return cost;
07797
07798 #undef SLOW_FP
07799 }
07800
07801 static int
07802 sparc_adjust_cost(insn, link, dep, cost)
07803 rtx insn;
07804 rtx link;
07805 rtx dep;
07806 int cost;
07807 {
07808 switch (sparc_cpu)
07809 {
07810 case PROCESSOR_SUPERSPARC:
07811 cost = supersparc_adjust_cost (insn, link, dep, cost);
07812 break;
07813 case PROCESSOR_HYPERSPARC:
07814 case PROCESSOR_SPARCLITE86X:
07815 cost = hypersparc_adjust_cost (insn, link, dep, cost);
07816 break;
07817 case PROCESSOR_ULTRASPARC:
07818 cost = ultrasparc_adjust_cost (insn, link, dep, cost);
07819 break;
07820 default:
07821 break;
07822 }
07823 return cost;
07824 }
07825
07826
07827
07828
07829 #define TMASK(__x) ((unsigned)1 << ((int)(__x)))
07830 #define UMASK(__x) ((unsigned)1 << ((int)(__x)))
07831
07832 enum ultra_code { NONE=0,
07833 IEU0,
07834 IEU1,
07835 IEUN,
07836 LSU,
07837 CTI,
07838 FPM,
07839 FPA,
07840 SINGLE,
07841 NUM_ULTRA_CODES };
07842
07843 static enum ultra_code ultra_code_from_mask PARAMS ((int));
07844 static void ultra_schedule_insn PARAMS ((rtx *, rtx *, int, enum ultra_code));
07845
07846 static const char *const ultra_code_names[NUM_ULTRA_CODES] = {
07847 "NONE", "IEU0", "IEU1", "IEUN", "LSU", "CTI",
07848 "FPM", "FPA", "SINGLE" };
07849
07850 struct ultrasparc_pipeline_state {
07851
07852 rtx group[4];
07853
07854
07855 enum ultra_code codes[4];
07856
07857
07858
07859
07860 char commit[4];
07861
07862
07863 char group_size;
07864
07865
07866 char free_slot_mask;
07867
07868
07869
07870 char contents [NUM_ULTRA_CODES];
07871 char num_ieu_insns;
07872 };
07873
07874 #define ULTRA_NUM_HIST 8
07875 static struct ultrasparc_pipeline_state ultra_pipe_hist[ULTRA_NUM_HIST];
07876 static int ultra_cur_hist;
07877 static int ultra_cycles_elapsed;
07878
07879 #define ultra_pipe (ultra_pipe_hist[ultra_cur_hist])
07880
07881
07882 static enum ultra_code
07883 ultra_code_from_mask (type_mask)
07884 int type_mask;
07885 {
07886 if (type_mask & (TMASK (TYPE_SHIFT) | TMASK (TYPE_CMOVE)))
07887 return IEU0;
07888 else if (type_mask & (TMASK (TYPE_COMPARE) |
07889 TMASK (TYPE_CALL) |
07890 TMASK (TYPE_SIBCALL) |
07891 TMASK (TYPE_UNCOND_BRANCH)))
07892 return IEU1;
07893 else if (type_mask & TMASK (TYPE_IALU))
07894 return IEUN;
07895 else if (type_mask & (TMASK (TYPE_LOAD) | TMASK (TYPE_SLOAD) |
07896 TMASK (TYPE_STORE) | TMASK (TYPE_FPLOAD) |
07897 TMASK (TYPE_FPSTORE)))
07898 return LSU;
07899 else if (type_mask & (TMASK (TYPE_FPMUL) | TMASK (TYPE_FPDIVS) |
07900 TMASK (TYPE_FPDIVD) | TMASK (TYPE_FPSQRTS) |
07901 TMASK (TYPE_FPSQRTD)))
07902 return FPM;
07903 else if (type_mask & (TMASK (TYPE_FPMOVE) | TMASK (TYPE_FPCMOVE) |
07904 TMASK (TYPE_FP) | TMASK (TYPE_FPCMP)))
07905 return FPA;
07906 else if (type_mask & TMASK (TYPE_BRANCH))
07907 return CTI;
07908
07909 return SINGLE;
07910 }
07911
07912
07913
07914
07915 static int
07916 ultra_cmove_results_ready_p (insn)
07917 rtx insn;
07918 {
07919 struct ultrasparc_pipeline_state *up;
07920 int entry, slot;
07921
07922
07923
07924 entry = (ultra_cur_hist - 1) & (ULTRA_NUM_HIST - 1);
07925 up = &ultra_pipe_hist[entry];
07926 slot = 4;
07927 while (--slot >= 0)
07928 if (up->group[slot] == insn)
07929 return 0;
07930
07931 return 1;
07932 }
07933
07934
07935
07936
07937
07938 static int
07939 ultra_fpmode_conflict_exists (fpmode)
07940 enum machine_mode fpmode;
07941 {
07942 int hist_ent;
07943 int hist_lim;
07944
07945 hist_ent = (ultra_cur_hist - 1) & (ULTRA_NUM_HIST - 1);
07946 if (ultra_cycles_elapsed < 4)
07947 hist_lim = ultra_cycles_elapsed;
07948 else
07949 hist_lim = 4;
07950 while (hist_lim > 0)
07951 {
07952 struct ultrasparc_pipeline_state *up = &ultra_pipe_hist[hist_ent];
07953 int slot = 4;
07954
07955 while (--slot >= 0)
07956 {
07957 rtx insn = up->group[slot];
07958 enum machine_mode this_mode;
07959 rtx pat;
07960
07961 if (! insn
07962 || GET_CODE (insn) != INSN
07963 || (pat = PATTERN (insn)) == 0
07964 || GET_CODE (pat) != SET)
07965 continue;
07966
07967 this_mode = GET_MODE (SET_DEST (pat));
07968 if ((this_mode != SFmode
07969 && this_mode != DFmode)
07970 || this_mode == fpmode)
07971 continue;
07972
07973
07974
07975
07976 if (GET_CODE (SET_SRC (pat)) != ABS
07977 && GET_CODE (SET_SRC (pat)) != NEG
07978 && ((TMASK (get_attr_type (insn)) &
07979 (TMASK (TYPE_FPDIVS) | TMASK (TYPE_FPDIVD) |
07980 TMASK (TYPE_FPMOVE) | TMASK (TYPE_FPSQRTS) |
07981 TMASK (TYPE_FPSQRTD) |
07982 TMASK (TYPE_LOAD) | TMASK (TYPE_STORE))) == 0))
07983 return 1;
07984 }
07985 hist_lim--;
07986 hist_ent = (hist_ent - 1) & (ULTRA_NUM_HIST - 1);
07987 }
07988
07989
07990 return 0;
07991 }
07992
07993
07994
07995
07996
07997
07998
07999
08000 static int ultra_types_avail;
08001
08002 static rtx *
08003 ultra_find_type (type_mask, list, start)
08004 int type_mask;
08005 rtx *list;
08006 int start;
08007 {
08008 int i;
08009
08010
08011
08012 if ((type_mask & ultra_types_avail) == 0)
08013 return 0;
08014
08015 for (i = start; i >= 0; i--)
08016 {
08017 rtx insn = list[i];
08018
08019 if (recog_memoized (insn) >= 0
08020 && (TMASK(get_attr_type (insn)) & type_mask))
08021 {
08022 enum machine_mode fpmode = SFmode;
08023 rtx pat = 0;
08024 int slot;
08025 int check_depend = 0;
08026 int check_fpmode_conflict = 0;
08027
08028 if (GET_CODE (insn) == INSN
08029 && (pat = PATTERN(insn)) != 0
08030 && GET_CODE (pat) == SET
08031 && !(type_mask & (TMASK (TYPE_STORE) |
08032 TMASK (TYPE_FPSTORE))))
08033 {
08034 check_depend = 1;
08035 if (GET_MODE (SET_DEST (pat)) == SFmode
08036 || GET_MODE (SET_DEST (pat)) == DFmode)
08037 {
08038 fpmode = GET_MODE (SET_DEST (pat));
08039 check_fpmode_conflict = 1;
08040 }
08041 }
08042
08043 slot = 4;
08044 while(--slot >= 0)
08045 {
08046 rtx slot_insn = ultra_pipe.group[slot];
08047 rtx slot_pat;
08048
08049
08050
08051 if (slot_insn != 0
08052 && (slot_pat = PATTERN (slot_insn)) != 0
08053 && ((insn == slot_insn)
08054 || (check_depend == 1
08055 && GET_CODE (slot_insn) == INSN
08056 && GET_CODE (slot_pat) == SET
08057 && ((GET_CODE (SET_DEST (slot_pat)) == REG
08058 && GET_CODE (SET_SRC (pat)) == REG
08059 && REGNO (SET_DEST (slot_pat)) ==
08060 REGNO (SET_SRC (pat)))
08061 || (GET_CODE (SET_DEST (slot_pat)) == SUBREG
08062 && GET_CODE (SET_SRC (pat)) == SUBREG
08063 && REGNO (SUBREG_REG (SET_DEST (slot_pat))) ==
08064 REGNO (SUBREG_REG (SET_SRC (pat)))
08065 && SUBREG_BYTE (SET_DEST (slot_pat)) ==
08066 SUBREG_BYTE (SET_SRC (pat)))))
08067 || (check_fpmode_conflict == 1
08068 && GET_CODE (slot_insn) == INSN
08069 && GET_CODE (slot_pat) == SET
08070 && (GET_MODE (SET_DEST (slot_pat)) == SFmode
08071 || GET_MODE (SET_DEST (slot_pat)) == DFmode)
08072 && GET_MODE (SET_DEST (slot_pat)) != fpmode)))
08073 goto next;
08074 }
08075
08076
08077
08078 if (pat != 0
08079 && ultra_cycles_elapsed > 0)
08080 {
08081 rtx link;
08082
08083 for (link = LOG_LINKS (insn); link; link = XEXP (link, 1))
08084 {
08085 rtx link_insn = XEXP (link, 0);
08086 if (GET_CODE (link_insn) == INSN
08087 && recog_memoized (link_insn) >= 0
08088 && (TMASK (get_attr_type (link_insn)) &
08089 (TMASK (TYPE_CMOVE) | TMASK (TYPE_FPCMOVE)))
08090 && ! ultra_cmove_results_ready_p (link_insn))
08091 goto next;
08092 }
08093
08094 if (check_fpmode_conflict
08095 && ultra_fpmode_conflict_exists (fpmode))
08096 goto next;
08097 }
08098
08099 return &list[i];
08100 }
08101 next:
08102 ;
08103 }
08104 return 0;
08105 }
08106
08107 static void
08108 ultra_build_types_avail (ready, n_ready)
08109 rtx *ready;
08110 int n_ready;
08111 {
08112 int i = n_ready - 1;
08113
08114 ultra_types_avail = 0;
08115 while(i >= 0)
08116 {
08117 rtx insn = ready[i];
08118
08119 if (recog_memoized (insn) >= 0)
08120 ultra_types_avail |= TMASK (get_attr_type (insn));
08121
08122 i -= 1;
08123 }
08124 }
08125
08126
08127
08128
08129
08130 static void
08131 ultra_schedule_insn (ip, ready, this, type)
08132 rtx *ip;
08133 rtx *ready;
08134 int this;
08135 enum ultra_code type;
08136 {
08137 int pipe_slot;
08138 char mask = ultra_pipe.free_slot_mask;
08139 rtx temp;
08140
08141
08142 for (pipe_slot = 0; pipe_slot < 4; pipe_slot++)
08143 if ((mask & (1 << pipe_slot)) != 0)
08144 break;
08145 if (pipe_slot == 4)
08146 abort ();
08147
08148
08149 ultra_pipe.group[pipe_slot] = *ip;
08150 ultra_pipe.codes[pipe_slot] = type;
08151 ultra_pipe.contents[type] = 1;
08152 if (UMASK (type) &
08153 (UMASK (IEUN) | UMASK (IEU0) | UMASK (IEU1)))
08154 ultra_pipe.num_ieu_insns += 1;
08155
08156 ultra_pipe.free_slot_mask = (mask & ~(1 << pipe_slot));
08157 ultra_pipe.group_size += 1;
08158 ultra_pipe.commit[pipe_slot] = 0;
08159
08160
08161 temp = *ip;
08162 while (ip != &ready[this])
08163 {
08164 ip[0] = ip[1];
08165 ++ip;
08166 }
08167 *ip = temp;
08168 }
08169
08170
08171 static void
08172 ultra_flush_pipeline ()
08173 {
08174 ultra_cur_hist = (ultra_cur_hist + 1) & (ULTRA_NUM_HIST - 1);
08175 ultra_cycles_elapsed += 1;
08176 memset ((char *) &ultra_pipe, 0, sizeof ultra_pipe);
08177 ultra_pipe.free_slot_mask = 0xf;
08178 }
08179
08180
08181 static void
08182 ultrasparc_sched_init ()
08183 {
08184 memset ((char *) ultra_pipe_hist, 0, sizeof ultra_pipe_hist);
08185 ultra_cur_hist = 0;
08186 ultra_cycles_elapsed = 0;
08187 ultra_pipe.free_slot_mask = 0xf;
08188 }
08189
08190 static void
08191 sparc_sched_init (dump, sched_verbose, max_ready)
08192 FILE *dump ATTRIBUTE_UNUSED;
08193 int sched_verbose ATTRIBUTE_UNUSED;
08194 int max_ready ATTRIBUTE_UNUSED;
08195 {
08196 if (sparc_cpu == PROCESSOR_ULTRASPARC)
08197 ultrasparc_sched_init ();
08198 }
08199
08200
08201
08202
08203 static int
08204 ultrasparc_variable_issue (insn)
08205 rtx insn;
08206 {
08207 struct ultrasparc_pipeline_state *up = &ultra_pipe;
08208 int i, left_to_fire;
08209
08210 left_to_fire = 0;
08211 for (i = 0; i < 4; i++)
08212 {
08213 if (up->group[i] == 0)
08214 continue;
08215
08216 if (up->group[i] == insn)
08217 {
08218 up->commit[i] = 1;
08219 }
08220 else if (! up->commit[i])
08221 left_to_fire++;
08222 }
08223
08224 return left_to_fire;
08225 }
08226
08227 static int
08228 sparc_variable_issue (dump, sched_verbose, insn, cim)
08229 FILE *dump ATTRIBUTE_UNUSED;
08230 int sched_verbose ATTRIBUTE_UNUSED;
08231 rtx insn;
08232 int cim;
08233 {
08234 if (sparc_cpu == PROCESSOR_ULTRASPARC)
08235 return ultrasparc_variable_issue (insn);
08236 else
08237 return cim - 1;
08238 }
08239
08240
08241
08242
08243
08244 static void
08245 ultra_rescan_pipeline_state (ready, n_ready)
08246 rtx *ready;
08247 int n_ready;
08248 {
08249 struct ultrasparc_pipeline_state *up = &ultra_pipe;
08250 int i;
08251
08252 for (i = 0; i < 4; i++)
08253 {
08254 rtx insn = up->group[i];
08255 int j;
08256
08257 if (! insn)
08258 continue;
08259
08260
08261
08262
08263 if (up->commit[i] != 0)
08264 continue;
08265
08266 for (j = n_ready - 1; j >= 0; j--)
08267 if (ready[j] == insn)
08268 break;
08269
08270
08271 if (j < 0)
08272 {
08273 enum ultra_code ucode = up->codes[i];
08274
08275 up->group[i] = 0;
08276 up->codes[i] = NONE;
08277 up->contents[ucode] = 0;
08278 if (UMASK (ucode) &
08279 (UMASK (IEUN) | UMASK (IEU0) | UMASK (IEU1)))
08280 up->num_ieu_insns -= 1;
08281
08282 up->free_slot_mask |= (1 << i);
08283 up->group_size -= 1;
08284 up->commit[i] = 0;
08285 }
08286 }
08287 }
08288
08289 static void
08290 ultrasparc_sched_reorder (dump, sched_verbose, ready, n_ready)
08291 FILE *dump;
08292 int sched_verbose;
08293 rtx *ready;
08294 int n_ready;
08295 {
08296 struct ultrasparc_pipeline_state *up = &ultra_pipe;
08297 int i, this_insn;
08298
08299 if (sched_verbose)
08300 {
08301 int n;
08302
08303 fprintf (dump, "\n;;\tUltraSPARC Looking at [");
08304 for (n = n_ready - 1; n >= 0; n--)
08305 {
08306 rtx insn = ready[n];
08307 enum ultra_code ucode;
08308
08309 if (recog_memoized (insn) < 0)
08310 continue;
08311 ucode = ultra_code_from_mask (TMASK (get_attr_type (insn)));
08312 if (n != 0)
08313 fprintf (dump, "%s(%d) ",
08314 ultra_code_names[ucode],
08315 INSN_UID (insn));
08316 else
08317 fprintf (dump, "%s(%d)",
08318 ultra_code_names[ucode],
08319 INSN_UID (insn));
08320 }
08321 fprintf (dump, "]\n");
08322 }
08323
08324 this_insn = n_ready - 1;
08325
08326
08327 while ((this_insn >= 0)
08328 && recog_memoized (ready[this_insn]) < 0)
08329 this_insn--;
08330
08331 ultra_build_types_avail (ready, this_insn + 1);
08332
08333 while (this_insn >= 0) {
08334 int old_group_size = up->group_size;
08335
08336 if (up->group_size != 0)
08337 {
08338 int num_committed;
08339
08340 num_committed = (up->commit[0] + up->commit[1] +
08341 up->commit[2] + up->commit[3]);
08342
08343
08344
08345 if (num_committed == 0
08346 || num_committed == up->group_size)
08347 {
08348 ultra_flush_pipeline ();
08349 up = &ultra_pipe;
08350 old_group_size = 0;
08351 }
08352 else
08353 {
08354
08355
08356 ultra_rescan_pipeline_state (ready, n_ready);
08357
08358
08359
08360
08361 if (up->group_size != old_group_size)
08362 old_group_size = 0;
08363 }
08364 }
08365
08366 if (up->group_size == 0)
08367 {
08368
08369
08370 rtx *ip = ultra_find_type ((TMASK (TYPE_RETURN) | TMASK (TYPE_IDIV) |
08371 TMASK (TYPE_IMUL) | TMASK (TYPE_CMOVE) |
08372 TMASK (TYPE_MULTI) | TMASK (TYPE_MISC)),
08373 ready, this_insn);
08374 if (ip)
08375 {
08376 ultra_schedule_insn (ip, ready, this_insn, SINGLE);
08377 break;
08378 }
08379
08380
08381
08382 ip = ultra_find_type ((TMASK (TYPE_CALL) |
08383 TMASK (TYPE_SIBCALL) |
08384 TMASK (TYPE_CALL_NO_DELAY_SLOT) |
08385 TMASK (TYPE_UNCOND_BRANCH)),
08386 ready, this_insn);
08387 if (ip)
08388 {
08389 ultra_schedule_insn (ip, ready, this_insn, IEU1);
08390 this_insn--;
08391 }
08392 else if ((ip = ultra_find_type ((TMASK (TYPE_FPDIVS) |
08393 TMASK (TYPE_FPDIVD) |
08394 TMASK (TYPE_FPSQRTS) |
08395 TMASK (TYPE_FPSQRTD)),
08396 ready, this_insn)) != 0)
08397 {
08398 ultra_schedule_insn (ip, ready, this_insn, FPM);
08399 this_insn--;
08400 }
08401 }
08402
08403
08404
08405
08406 if ((up->free_slot_mask & 0x7) != 0
08407 && up->num_ieu_insns < 2
08408 && up->contents[IEU0] == 0
08409 && up->contents[IEUN] == 0)
08410 {
08411 rtx *ip = ultra_find_type (TMASK(TYPE_SHIFT), ready, this_insn);
08412 if (ip)
08413 {
08414 ultra_schedule_insn (ip, ready, this_insn, IEU0);
08415 this_insn--;
08416 }
08417 }
08418
08419
08420
08421 if ((up->free_slot_mask & 0x7) != 0
08422 && up->num_ieu_insns < 2)
08423 {
08424 rtx *ip = ultra_find_type ((TMASK (TYPE_IALU) |
08425 (up->contents[IEU1] == 0 ? TMASK (TYPE_COMPARE) : 0)),
08426 ready, this_insn);
08427 if (ip)
08428 {
08429 rtx insn = *ip;
08430
08431 ultra_schedule_insn (ip, ready, this_insn,
08432 (!up->contents[IEU1]
08433 && get_attr_type (insn) == TYPE_COMPARE)
08434 ? IEU1 : IEUN);
08435 this_insn--;
08436 }
08437 }
08438
08439
08440
08441 if ((up->free_slot_mask & 0x7) != 0
08442 && up->num_ieu_insns < 2)
08443 {
08444 rtx *ip;
08445 int tmask = TMASK (TYPE_IALU);
08446
08447 if (!up->contents[IEU1])
08448 tmask |= TMASK (TYPE_COMPARE);
08449 ip = ultra_find_type (tmask, ready, this_insn);
08450 if (ip)
08451 {
08452 rtx insn = *ip;
08453
08454 ultra_schedule_insn (ip, ready, this_insn,
08455 (!up->contents[IEU1]
08456 && get_attr_type (insn) == TYPE_COMPARE)
08457 ? IEU1 : IEUN);
08458 this_insn--;
08459 }
08460 }
08461
08462
08463
08464 if ((up->free_slot_mask & 0x7) != 0
08465 && up->contents[LSU] == 0)
08466 {
08467 rtx *ip = ultra_find_type ((TMASK (TYPE_LOAD) | TMASK (TYPE_SLOAD) |
08468 TMASK (TYPE_STORE) | TMASK (TYPE_FPLOAD) |
08469 TMASK (TYPE_FPSTORE)), ready, this_insn);
08470 if (ip)
08471 {
08472 ultra_schedule_insn (ip, ready, this_insn, LSU);
08473 this_insn--;
08474 }
08475 }
08476
08477
08478
08479
08480 if (up->free_slot_mask != 0
08481 && up->contents[FPM] == 0)
08482 {
08483 rtx *ip = ultra_find_type (TMASK (TYPE_FPMUL), ready, this_insn);
08484 if (ip)
08485 {
08486 ultra_schedule_insn (ip, ready, this_insn, FPM);
08487 this_insn--;
08488 }
08489 }
08490
08491
08492 if (up->free_slot_mask != 0
08493 && up->contents[FPA] == 0)
08494 {
08495 rtx *ip = ultra_find_type ((TMASK (TYPE_FPMOVE) | TMASK (TYPE_FPCMOVE) |
08496 TMASK (TYPE_FP) | TMASK (TYPE_FPCMP)),
08497 ready, this_insn);
08498 if (ip)
08499 {
08500 ultra_schedule_insn (ip, ready, this_insn, FPA);
08501 this_insn--;
08502 }
08503 }
08504
08505
08506 if (up->free_slot_mask != 0
08507 && up->contents[CTI] == 0)
08508 {
08509 rtx *ip = ultra_find_type (TMASK (TYPE_BRANCH), ready, this_insn);
08510
08511
08512
08513 if (ip && ((&ready[this_insn] - ip) < 2))
08514 {
08515 ultra_schedule_insn (ip, ready, this_insn, CTI);
08516 this_insn--;
08517 }
08518 }
08519
08520 up->group_size = 0;
08521 for (i = 0; i < 4; i++)
08522 if ((up->free_slot_mask & (1 << i)) == 0)
08523 up->group_size++;
08524
08525
08526 if (old_group_size != up->group_size)
08527 break;
08528
08529
08530
08531
08532
08533
08534 if (up->group_size == 0)
08535 {
08536 ultra_flush_pipeline ();
08537 up = &ultra_pipe;
08538 }
08539 else
08540 {
08541 memset ((char *) &ultra_pipe, 0, sizeof ultra_pipe);
08542 ultra_pipe.free_slot_mask = 0xf;
08543 }
08544 }
08545
08546 if (sched_verbose)
08547 {
08548 int n, gsize;
08549
08550 fprintf (dump, ";;\tUltraSPARC Launched [");
08551 gsize = up->group_size;
08552 for (n = 0; n < 4; n++)
08553 {
08554 rtx insn = up->group[n];
08555
08556 if (! insn)
08557 continue;
08558
08559 gsize -= 1;
08560 if (gsize != 0)
08561 fprintf (dump, "%s(%d) ",
08562 ultra_code_names[up->codes[n]],
08563 INSN_UID (insn));
08564 else
08565 fprintf (dump, "%s(%d)",
08566 ultra_code_names[up->codes[n]],
08567 INSN_UID (insn));
08568 }
08569 fprintf (dump, "]\n");
08570 }
08571 }
08572
08573 static int
08574 sparc_sched_reorder (dump, sched_verbose, ready, n_readyp, clock)
08575 FILE *dump;
08576 int sched_verbose;
08577 rtx *ready;
08578 int *n_readyp;
08579 int clock ATTRIBUTE_UNUSED;
08580 {
08581 if (sparc_cpu == PROCESSOR_ULTRASPARC)
08582 ultrasparc_sched_reorder (dump, sched_verbose, ready, *n_readyp);
08583 return sparc_issue_rate ();
08584 }
08585
08586 static int
08587 sparc_issue_rate ()
08588 {
08589 switch (sparc_cpu)
08590 {
08591 default:
08592 return 1;
08593 case PROCESSOR_V9:
08594
08595 return 2;
08596 case PROCESSOR_SUPERSPARC:
08597 return 3;
08598 case PROCESSOR_HYPERSPARC:
08599 case PROCESSOR_SPARCLITE86X:
08600 return 2;
08601 case PROCESSOR_ULTRASPARC:
08602 return 4;
08603 }
08604 }
08605
08606 static int
08607 set_extends (insn)
08608 rtx insn;
08609 {
08610 register rtx pat = PATTERN (insn);
08611
08612 switch (GET_CODE (SET_SRC (pat)))
08613 {
08614
08615 case MEM:
08616 case ZERO_EXTEND:
08617
08618 case HIGH:
08619
08620
08621 case LO_SUM:
08622
08623 case LT: case LTU:
08624 case GT: case GTU:
08625 case LE: case LEU:
08626 case GE: case GEU:
08627 case EQ:
08628 case NE:
08629 return 1;
08630 case AND:
08631 {
08632 rtx op0 = XEXP (SET_SRC (pat), 0);
08633 rtx op1 = XEXP (SET_SRC (pat), 1);
08634 if (GET_CODE (op1) == CONST_INT)
08635 return INTVAL (op1) >= 0;
08636 if (GET_CODE (op0) != REG)
08637 return 0;
08638 if (sparc_check_64 (op0, insn) == 1)
08639 return 1;
08640 return (GET_CODE (op1) == REG && sparc_check_64 (op1, insn) == 1);
08641 }
08642 case IOR:
08643 case XOR:
08644 {
08645 rtx op0 = XEXP (SET_SRC (pat), 0);
08646 rtx op1 = XEXP (SET_SRC (pat), 1);
08647 if (GET_CODE (op0) != REG || sparc_check_64 (op0, insn) <= 0)
08648 return 0;
08649 if (GET_CODE (op1) == CONST_INT)
08650 return INTVAL (op1) >= 0;
08651 return (GET_CODE (op1) == REG && sparc_check_64 (op1, insn) == 1);
08652 }
08653 case LSHIFTRT:
08654 return GET_MODE (SET_SRC (pat)) == SImode;
08655
08656 case CONST_DOUBLE:
08657 return ! (CONST_DOUBLE_LOW (SET_SRC (pat)) & 0x80000000);
08658 case CONST_INT:
08659 return ! (INTVAL (SET_SRC (pat)) & 0x80000000);
08660 case ASHIFTRT:
08661 case SIGN_EXTEND:
08662 return - (GET_MODE (SET_SRC (pat)) == SImode);
08663 case REG:
08664 return sparc_check_64 (SET_SRC (pat), insn);
08665 default:
08666 return 0;
08667 }
08668 }
08669
08670
08671 static rtx sparc_addr_diff_list;
08672 static rtx sparc_addr_list;
08673
08674 void
08675 sparc_defer_case_vector (lab, vec, diff)
08676 rtx lab, vec;
08677 int diff;
08678 {
08679 vec = gen_rtx_EXPR_LIST (VOIDmode, lab, vec);
08680 if (diff)
08681 sparc_addr_diff_list
08682 = gen_rtx_EXPR_LIST (VOIDmode, vec, sparc_addr_diff_list);
08683 else
08684 sparc_addr_list = gen_rtx_EXPR_LIST (VOIDmode, vec, sparc_addr_list);
08685 }
08686
08687 static void
08688 sparc_output_addr_vec (vec)
08689 rtx vec;
08690 {
08691 rtx lab = XEXP (vec, 0), body = XEXP (vec, 1);
08692 int idx, vlen = XVECLEN (body, 0);
08693
08694 #ifdef ASM_OUTPUT_ADDR_VEC_START
08695 ASM_OUTPUT_ADDR_VEC_START (asm_out_file);
08696 #endif
08697
08698 #ifdef ASM_OUTPUT_CASE_LABEL
08699 ASM_OUTPUT_CASE_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (lab),
08700 NEXT_INSN (lab));
08701 #else
08702 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (lab));
08703 #endif
08704
08705 for (idx = 0; idx < vlen; idx++)
08706 {
08707 ASM_OUTPUT_ADDR_VEC_ELT
08708 (asm_out_file, CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 0, idx), 0)));
08709 }
08710
08711 #ifdef ASM_OUTPUT_ADDR_VEC_END
08712 ASM_OUTPUT_ADDR_VEC_END (asm_out_file);
08713 #endif
08714 }
08715
08716 static void
08717 sparc_output_addr_diff_vec (vec)
08718 rtx vec;
08719 {
08720 rtx lab = XEXP (vec, 0), body = XEXP (vec, 1);
08721 rtx base = XEXP (XEXP (body, 0), 0);
08722 int idx, vlen = XVECLEN (body, 1);
08723
08724 #ifdef ASM_OUTPUT_ADDR_VEC_START
08725 ASM_OUTPUT_ADDR_VEC_START (asm_out_file);
08726 #endif
08727
08728 #ifdef ASM_OUTPUT_CASE_LABEL
08729 ASM_OUTPUT_CASE_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (lab),
08730 NEXT_INSN (lab));
08731 #else
08732 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (lab));
08733 #endif
08734
08735 for (idx = 0; idx < vlen; idx++)
08736 {
08737 ASM_OUTPUT_ADDR_DIFF_ELT
08738 (asm_out_file,
08739 body,
08740 CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 1, idx), 0)),
08741 CODE_LABEL_NUMBER (base));
08742 }
08743
08744 #ifdef ASM_OUTPUT_ADDR_VEC_END
08745 ASM_OUTPUT_ADDR_VEC_END (asm_out_file);
08746 #endif
08747 }
08748
08749 static void
08750 sparc_output_deferred_case_vectors ()
08751 {
08752 rtx t;
08753 int align;
08754
08755 if (sparc_addr_list == NULL_RTX
08756 && sparc_addr_diff_list == NULL_RTX)
08757 return;
08758
08759
08760 function_section (current_function_decl);
08761
08762 align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT);
08763 if (align > 0)
08764 ASM_OUTPUT_ALIGN (asm_out_file, align);
08765
08766 for (t = sparc_addr_list; t ; t = XEXP (t, 1))
08767 sparc_output_addr_vec (XEXP (t, 0));
08768 for (t = sparc_addr_diff_list; t ; t = XEXP (t, 1))
08769 sparc_output_addr_diff_vec (XEXP (t, 0));
08770
08771 sparc_addr_list = sparc_addr_diff_list = NULL_RTX;
08772 }
08773
08774
08775
08776
08777 int
08778 sparc_check_64 (x, insn)
08779 rtx x, insn;
08780 {
08781
08782
08783
08784
08785 int set_once = 0;
08786 rtx y = x;
08787
08788 if (GET_CODE (x) != REG)
08789 abort ();
08790
08791 if (GET_MODE (x) == DImode)
08792 y = gen_rtx_REG (SImode, REGNO (x) + WORDS_BIG_ENDIAN);
08793
08794 if (flag_expensive_optimizations
08795 && REG_N_SETS (REGNO (y)) == 1)
08796 set_once = 1;
08797
08798 if (insn == 0)
08799 {
08800 if (set_once)
08801 insn = get_last_insn_anywhere ();
08802 else
08803 return 0;
08804 }
08805
08806 while ((insn = PREV_INSN (insn)))
08807 {
08808 switch (GET_CODE (insn))
08809 {
08810 case JUMP_INSN:
08811 case NOTE:
08812 break;
08813 case CODE_LABEL:
08814 case CALL_INSN:
08815 default:
08816 if (! set_once)
08817 return 0;
08818 break;
08819 case INSN:
08820 {
08821 rtx pat = PATTERN (insn);
08822 if (GET_CODE (pat) != SET)
08823 return 0;
08824 if (rtx_equal_p (x, SET_DEST (pat)))
08825 return set_extends (insn);
08826 if (y && rtx_equal_p (y, SET_DEST (pat)))
08827 return set_extends (insn);
08828 if (reg_overlap_mentioned_p (SET_DEST (pat), y))
08829 return 0;
08830 }
08831 }
08832 }
08833 return 0;
08834 }
08835
08836 char *
08837 sparc_v8plus_shift (operands, insn, opcode)
08838 rtx *operands;
08839 rtx insn;
08840 const char *opcode;
08841 {
08842 static char asm_code[60];
08843
08844 if (GET_CODE (operands[3]) == SCRATCH)
08845 operands[3] = operands[0];
08846 if (GET_CODE (operands[1]) == CONST_INT)
08847 {
08848 output_asm_insn ("mov\t%1, %3", operands);
08849 }
08850 else
08851 {
08852 output_asm_insn ("sllx\t%H1, 32, %3", operands);
08853 if (sparc_check_64 (operands[1], insn) <= 0)
08854 output_asm_insn ("srl\t%L1, 0, %L1", operands);
08855 output_asm_insn ("or\t%L1, %3, %3", operands);
08856 }
08857
08858 strcpy(asm_code, opcode);
08859 if (which_alternative != 2)
08860 return strcat (asm_code, "\t%0, %2, %L0\n\tsrlx\t%L0, 32, %H0");
08861 else
08862 return strcat (asm_code, "\t%3, %2, %3\n\tsrlx\t%3, 32, %H0\n\tmov\t%3, %L0");
08863 }
08864
08865
08866
08867
08868 void
08869 sparc_profile_hook (labelno)
08870 int labelno;
08871 {
08872 char buf[32];
08873 rtx lab, fun;
08874
08875 ASM_GENERATE_INTERNAL_LABEL (buf, "LP", labelno);
08876 lab = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
08877 fun = gen_rtx_SYMBOL_REF (Pmode, MCOUNT_FUNCTION);
08878
08879 emit_library_call (fun, LCT_NORMAL, VOIDmode, 1, lab, Pmode);
08880 }
08881
08882
08883
08884
08885 static void
08886 mark_ultrasparc_pipeline_state (arg)
08887 void *arg;
08888 {
08889 struct ultrasparc_pipeline_state *ups;
08890 size_t i;
08891
08892 ups = (struct ultrasparc_pipeline_state *) arg;
08893 for (i = 0; i < sizeof (ups->group) / sizeof (rtx); ++i)
08894 ggc_mark_rtx (ups->group[i]);
08895 }
08896
08897
08898
08899
08900 static void
08901 sparc_add_gc_roots ()
08902 {
08903 ggc_add_rtx_root (&sparc_compare_op0, 1);
08904 ggc_add_rtx_root (&sparc_compare_op1, 1);
08905 ggc_add_rtx_root (&global_offset_table, 1);
08906 ggc_add_rtx_root (&get_pc_symbol, 1);
08907 ggc_add_rtx_root (&sparc_addr_diff_list, 1);
08908 ggc_add_rtx_root (&sparc_addr_list, 1);
08909 ggc_add_root (ultra_pipe_hist, ARRAY_SIZE (ultra_pipe_hist),
08910 sizeof (ultra_pipe_hist[0]), &mark_ultrasparc_pipeline_state);
08911 }
08912
08913 #ifdef OBJECT_FORMAT_ELF
08914 static void
08915 sparc_elf_asm_named_section (name, flags)
08916 const char *name;
08917 unsigned int flags;
08918 {
08919 if (flags & SECTION_MERGE)
08920 {
08921
08922
08923 default_elf_asm_named_section (name, flags);
08924 return;
08925 }
08926
08927 fprintf (asm_out_file, "\t.section\t\"%s\"", name);
08928
08929 if (!(flags & SECTION_DEBUG))
08930 fputs (",#alloc", asm_out_file);
08931 if (flags & SECTION_WRITE)
08932 fputs (",#write", asm_out_file);
08933 if (flags & SECTION_CODE)
08934 fputs (",#execinstr", asm_out_file);
08935
08936
08937
08938 fputc ('\n', asm_out_file);
08939 }
08940 #endif
08941
08942 int
08943 sparc_extra_constraint_check (op, c, strict)
08944 rtx op;
08945 int c;
08946 int strict;
08947 {
08948 int reload_ok_mem;
08949
08950 if (TARGET_ARCH64
08951 && (c == 'T' || c == 'U'))
08952 return 0;
08953
08954 switch (c)
08955 {
08956 case 'Q':
08957 return fp_sethi_p (op);
08958
08959 case 'R':
08960 return fp_mov_p (op);
08961
08962 case 'S':
08963 return fp_high_losum_p (op);
08964
08965 case 'U':
08966 if (! strict
08967 || (GET_CODE (op) == REG
08968 && (REGNO (op) < FIRST_PSEUDO_REGISTER
08969 || reg_renumber[REGNO (op)] >= 0)))
08970 return register_ok_for_ldd (op);
08971
08972 return 0;
08973
08974 case 'W':
08975 case 'T':
08976 break;
08977
08978 default:
08979 return 0;
08980 }
08981
08982
08983
08984
08985 if (GET_CODE (op) == MEM)
08986 {
08987 reload_ok_mem = 0;
08988 if ((TARGET_ARCH64 || mem_min_alignment (op, 8))
08989 && (! strict
08990 || strict_memory_address_p (Pmode, XEXP (op, 0))))
08991 reload_ok_mem = 1;
08992 }
08993 else
08994 {
08995 reload_ok_mem = (reload_in_progress
08996 && GET_CODE (op) == REG
08997 && REGNO (op) >= FIRST_PSEUDO_REGISTER
08998 && reg_renumber [REGNO (op)] < 0);
08999 }
09000
09001 return reload_ok_mem;
09002 }
09003
09004
09005
09006
09007 void
09008 sparc_output_mi_thunk (file, thunk_fndecl, delta, function)
09009 FILE *file;
09010 tree thunk_fndecl ATTRIBUTE_UNUSED;
09011 HOST_WIDE_INT delta;
09012 tree function;
09013 {
09014 rtx this, insn, funexp, delta_rtx, tmp;
09015
09016 reload_completed = 1;
09017 no_new_pseudos = 1;
09018 current_function_uses_only_leaf_regs = 1;
09019
09020 emit_note (NULL, NOTE_INSN_PROLOGUE_END);
09021
09022
09023
09024 if (TARGET_ARCH64 && aggregate_value_p (TREE_TYPE (TREE_TYPE (function))))
09025 this = gen_rtx_REG (Pmode, SPARC_INCOMING_INT_ARG_FIRST + 1);
09026 else
09027 this = gen_rtx_REG (Pmode, SPARC_INCOMING_INT_ARG_FIRST);
09028
09029
09030
09031 delta_rtx = GEN_INT (delta);
09032 if (!SPARC_SIMM13_P (delta))
09033 {
09034 rtx scratch = gen_rtx_REG (Pmode, 1);
09035 if (TARGET_ARCH64)
09036 sparc_emit_set_const64 (scratch, delta_rtx);
09037 else
09038 sparc_emit_set_const32 (scratch, delta_rtx);
09039 delta_rtx = scratch;
09040 }
09041
09042 tmp = gen_rtx_PLUS (Pmode, this, delta_rtx);
09043 emit_insn (gen_rtx_SET (VOIDmode, this, tmp));
09044
09045
09046 if (! TREE_USED (function))
09047 {
09048 assemble_external (function);
09049 TREE_USED (function) = 1;
09050 }
09051 funexp = XEXP (DECL_RTL (function), 0);
09052 funexp = gen_rtx_MEM (FUNCTION_MODE, funexp);
09053 insn = emit_call_insn (gen_sibcall (funexp));
09054 SIBLING_CALL_P (insn) = 1;
09055 emit_barrier ();
09056
09057
09058
09059
09060
09061 insn = get_insns ();
09062 shorten_branches (insn);
09063 final_start_function (insn, file, 1);
09064 final (insn, file, 1, 0);
09065 final_end_function ();
09066
09067 reload_completed = 0;
09068 no_new_pseudos = 0;
09069 }