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