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