00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "config.h"
00023 #include "system.h"
00024 #include "coretypes.h"
00025 #include "tm.h"
00026 #include "rtl.h"
00027 #include "tree.h"
00028 #include "regs.h"
00029 #include "hard-reg-set.h"
00030 #include "real.h"
00031 #include "insn-config.h"
00032 #include "conditions.h"
00033 #include "insn-flags.h"
00034 #include "output.h"
00035 #include "insn-attr.h"
00036 #include "flags.h"
00037 #include "recog.h"
00038 #include "reload.h"
00039 #include "expr.h"
00040 #include "obstack.h"
00041 #include "except.h"
00042 #include "function.h"
00043 #include "optabs.h"
00044 #include "toplev.h"
00045 #include "basic-block.h"
00046 #include "tm_p.h"
00047 #include "ggc.h"
00048 #include <ctype.h>
00049 #include "target.h"
00050 #include "target-def.h"
00051 #include "targhooks.h"
00052 #include "integrate.h"
00053 #include "langhooks.h"
00054
00055 #ifndef FRV_INLINE
00056 #define FRV_INLINE inline
00057 #endif
00058
00059
00060
00061 #define NUM_NOP_PATTERNS 3
00062
00063
00064
00065 enum frv_insn_group { GROUP_I, GROUP_FM, GROUP_B, GROUP_C, NUM_GROUPS };
00066
00067
00068 static const char *const frv_unit_names[] =
00069 {
00070 "c",
00071 "i0", "f0",
00072 "i1", "f1",
00073 "i2", "f2",
00074 "i3", "f3",
00075 "b0", "b1"
00076 };
00077
00078
00079 static const enum frv_insn_group frv_unit_groups[ARRAY_SIZE (frv_unit_names)] =
00080 {
00081 GROUP_C,
00082 GROUP_I, GROUP_FM,
00083 GROUP_I, GROUP_FM,
00084 GROUP_I, GROUP_FM,
00085 GROUP_I, GROUP_FM,
00086 GROUP_B, GROUP_B
00087 };
00088
00089
00090
00091 #define NTH_UNIT(GROUP, N) frv_unit_codes[(GROUP) + (N) * 2 + 1]
00092
00093
00094
00095 #define UNIT_NUMBER(UNIT) (((UNIT) - 1) / 2)
00096
00097
00098 static int frv_unit_codes[ARRAY_SIZE (frv_unit_names)];
00099
00100
00101
00102
00103 static unsigned int frv_type_to_unit[TYPE_UNKNOWN + 1];
00104
00105
00106
00107 static GTY(()) rtx frv_nops[NUM_NOP_PATTERNS];
00108
00109
00110 static unsigned int frv_num_nops;
00111
00112
00113
00114
00115 struct frv_io {
00116
00117
00118 enum { FRV_IO_UNKNOWN, FRV_IO_READ, FRV_IO_WRITE } type;
00119
00120
00121 HOST_WIDE_INT const_address;
00122
00123
00124 rtx var_address;
00125 };
00126
00127
00128
00129 #define PACKING_FLAG_P(INSN) (GET_MODE (INSN) == TImode)
00130
00131
00132 #define SET_PACKING_FLAG(INSN) PUT_MODE (INSN, TImode)
00133 #define CLEAR_PACKING_FLAG(INSN) PUT_MODE (INSN, VOIDmode)
00134
00135
00136 #define FOR_EACH_REGNO(REG, X) \
00137 for (REG = REGNO (X); \
00138 REG < REGNO (X) + HARD_REGNO_NREGS (REGNO (X), GET_MODE (X)); \
00139 REG++)
00140
00141
00142 struct machine_function GTY(())
00143 {
00144
00145 int frame_needed;
00146
00147
00148 bool has_membar_p;
00149 };
00150
00151
00152 typedef struct frv_tmp_reg_struct
00153 {
00154 HARD_REG_SET regs;
00155 int next_reg[N_REG_CLASSES];
00156 }
00157 frv_tmp_reg_t;
00158
00159
00160 #define REGSTATE_CC_MASK 0x07
00161 #define REGSTATE_MODIFIED 0x08
00162 #define REGSTATE_IF_TRUE 0x10
00163 #define REGSTATE_IF_FALSE 0x20
00164
00165 #define REGSTATE_IF_EITHER (REGSTATE_IF_TRUE | REGSTATE_IF_FALSE)
00166
00167 typedef unsigned char regstate_t;
00168
00169
00170
00171 enum frv_stack_op
00172 {
00173 FRV_LOAD,
00174 FRV_STORE
00175 };
00176
00177
00178 typedef struct
00179 {
00180
00181
00182
00183
00184 enum frv_stack_op op;
00185
00186
00187
00188
00189
00190 rtx base;
00191
00192
00193 int base_offset;
00194 } frv_frame_accessor_t;
00195
00196
00197
00198 rtx frv_compare_op0;
00199 rtx frv_compare_op1;
00200
00201
00202 typedef struct
00203 {
00204
00205
00206
00207 rtx added_insns_list;
00208
00209
00210
00211
00212
00213
00214 frv_tmp_reg_t tmp_reg;
00215
00216
00217
00218
00219
00220 HARD_REG_SET nested_cc_ok_rewrite;
00221
00222
00223
00224 rtx scratch_regs[FIRST_PSEUDO_REGISTER];
00225
00226
00227 int cur_scratch_regs;
00228
00229
00230 int num_nested_cond_exec;
00231
00232
00233 bitmap scratch_insns_bitmap;
00234
00235
00236 rtx cr_reg;
00237
00238
00239
00240
00241
00242
00243 rtx nested_cc_reg;
00244
00245
00246 rtx extra_int_cr;
00247 rtx extra_fp_cr;
00248
00249
00250
00251 rtx last_nested_if_cr;
00252 }
00253 frv_ifcvt_t;
00254
00255 static frv_ifcvt_t frv_ifcvt;
00256
00257
00258 enum reg_class regno_reg_class[FIRST_PSEUDO_REGISTER];
00259
00260
00261 enum reg_class reg_class_from_letter[256];
00262
00263
00264 static frv_stack_t *frv_stack_cache = (frv_stack_t *)0;
00265
00266
00267 frv_cpu_t frv_cpu_type = CPU_TYPE;
00268
00269
00270
00271 static bool frv_handle_option (size_t, const char *, int);
00272 static int frv_default_flags_for_cpu (void);
00273 static int frv_string_begins_with (tree, const char *);
00274 static FRV_INLINE bool frv_small_data_reloc_p (rtx, int);
00275 static void frv_print_operand_memory_reference_reg
00276 (FILE *, rtx);
00277 static void frv_print_operand_memory_reference (FILE *, rtx, int);
00278 static int frv_print_operand_jump_hint (rtx);
00279 static const char *comparison_string (enum rtx_code, rtx);
00280 static FRV_INLINE int frv_regno_ok_for_base_p (int, int);
00281 static rtx single_set_pattern (rtx);
00282 static int frv_function_contains_far_jump (void);
00283 static rtx frv_alloc_temp_reg (frv_tmp_reg_t *,
00284 enum reg_class,
00285 enum machine_mode,
00286 int, int);
00287 static rtx frv_frame_offset_rtx (int);
00288 static rtx frv_frame_mem (enum machine_mode, rtx, int);
00289 static rtx frv_dwarf_store (rtx, int);
00290 static void frv_frame_insn (rtx, rtx);
00291 static void frv_frame_access (frv_frame_accessor_t*,
00292 rtx, int);
00293 static void frv_frame_access_multi (frv_frame_accessor_t*,
00294 frv_stack_t *, int);
00295 static void frv_frame_access_standard_regs (enum frv_stack_op,
00296 frv_stack_t *);
00297 static struct machine_function *frv_init_machine_status (void);
00298 static rtx frv_int_to_acc (enum insn_code, int, rtx);
00299 static enum machine_mode frv_matching_accg_mode (enum machine_mode);
00300 static rtx frv_read_argument (tree *);
00301 static rtx frv_read_iacc_argument (enum machine_mode, tree *);
00302 static int frv_check_constant_argument (enum insn_code, int, rtx);
00303 static rtx frv_legitimize_target (enum insn_code, rtx);
00304 static rtx frv_legitimize_argument (enum insn_code, int, rtx);
00305 static rtx frv_legitimize_tls_address (rtx, enum tls_model);
00306 static rtx frv_expand_set_builtin (enum insn_code, tree, rtx);
00307 static rtx frv_expand_unop_builtin (enum insn_code, tree, rtx);
00308 static rtx frv_expand_binop_builtin (enum insn_code, tree, rtx);
00309 static rtx frv_expand_cut_builtin (enum insn_code, tree, rtx);
00310 static rtx frv_expand_binopimm_builtin (enum insn_code, tree, rtx);
00311 static rtx frv_expand_voidbinop_builtin (enum insn_code, tree);
00312 static rtx frv_expand_int_void2arg (enum insn_code, tree);
00313 static rtx frv_expand_prefetches (enum insn_code, tree);
00314 static rtx frv_expand_voidtriop_builtin (enum insn_code, tree);
00315 static rtx frv_expand_voidaccop_builtin (enum insn_code, tree);
00316 static rtx frv_expand_mclracc_builtin (tree);
00317 static rtx frv_expand_mrdacc_builtin (enum insn_code, tree);
00318 static rtx frv_expand_mwtacc_builtin (enum insn_code, tree);
00319 static rtx frv_expand_noargs_builtin (enum insn_code);
00320 static void frv_split_iacc_move (rtx, rtx);
00321 static rtx frv_emit_comparison (enum rtx_code, rtx, rtx);
00322 static int frv_clear_registers_used (rtx *, void *);
00323 static void frv_ifcvt_add_insn (rtx, rtx, int);
00324 static rtx frv_ifcvt_rewrite_mem (rtx, enum machine_mode, rtx);
00325 static rtx frv_ifcvt_load_value (rtx, rtx);
00326 static int frv_acc_group_1 (rtx *, void *);
00327 static unsigned int frv_insn_unit (rtx);
00328 static bool frv_issues_to_branch_unit_p (rtx);
00329 static int frv_cond_flags (rtx);
00330 static bool frv_regstate_conflict_p (regstate_t, regstate_t);
00331 static int frv_registers_conflict_p_1 (rtx *, void *);
00332 static bool frv_registers_conflict_p (rtx);
00333 static void frv_registers_update_1 (rtx, rtx, void *);
00334 static void frv_registers_update (rtx);
00335 static void frv_start_packet (void);
00336 static void frv_start_packet_block (void);
00337 static void frv_finish_packet (void (*) (void));
00338 static bool frv_pack_insn_p (rtx);
00339 static void frv_add_insn_to_packet (rtx);
00340 static void frv_insert_nop_in_packet (rtx);
00341 static bool frv_for_each_packet (void (*) (void));
00342 static bool frv_sort_insn_group_1 (enum frv_insn_group,
00343 unsigned int, unsigned int,
00344 unsigned int, unsigned int,
00345 state_t);
00346 static int frv_compare_insns (const void *, const void *);
00347 static void frv_sort_insn_group (enum frv_insn_group);
00348 static void frv_reorder_packet (void);
00349 static void frv_fill_unused_units (enum frv_insn_group);
00350 static void frv_align_label (void);
00351 static void frv_reorg_packet (void);
00352 static void frv_register_nop (rtx);
00353 static void frv_reorg (void);
00354 static void frv_pack_insns (void);
00355 static void frv_function_prologue (FILE *, HOST_WIDE_INT);
00356 static void frv_function_epilogue (FILE *, HOST_WIDE_INT);
00357 static bool frv_assemble_integer (rtx, unsigned, int);
00358 static void frv_init_builtins (void);
00359 static rtx frv_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
00360 static void frv_init_libfuncs (void);
00361 static bool frv_in_small_data_p (tree);
00362 static void frv_asm_output_mi_thunk
00363 (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, tree);
00364 static void frv_setup_incoming_varargs (CUMULATIVE_ARGS *,
00365 enum machine_mode,
00366 tree, int *, int);
00367 static rtx frv_expand_builtin_saveregs (void);
00368 static bool frv_rtx_costs (rtx, int, int, int*);
00369 static void frv_asm_out_constructor (rtx, int);
00370 static void frv_asm_out_destructor (rtx, int);
00371 static bool frv_function_symbol_referenced_p (rtx);
00372 static bool frv_cannot_force_const_mem (rtx);
00373 static const char *unspec_got_name (int);
00374 static void frv_output_const_unspec (FILE *,
00375 const struct frv_unspec *);
00376 static bool frv_function_ok_for_sibcall (tree, tree);
00377 static rtx frv_struct_value_rtx (tree, int);
00378 static bool frv_must_pass_in_stack (enum machine_mode mode, tree type);
00379 static int frv_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
00380 tree, bool);
00381 static void frv_output_dwarf_dtprel (FILE *, int, rtx)
00382 ATTRIBUTE_UNUSED;
00383
00384
00385 #ifndef DEFAULT_NO_ALLOC_CC
00386 #define MASK_DEFAULT_ALLOC_CC MASK_ALLOC_CC
00387 #else
00388 #define MASK_DEFAULT_ALLOC_CC 0
00389 #endif
00390
00391
00392 #undef TARGET_ASM_FUNCTION_PROLOGUE
00393 #define TARGET_ASM_FUNCTION_PROLOGUE frv_function_prologue
00394 #undef TARGET_ASM_FUNCTION_EPILOGUE
00395 #define TARGET_ASM_FUNCTION_EPILOGUE frv_function_epilogue
00396 #undef TARGET_ASM_INTEGER
00397 #define TARGET_ASM_INTEGER frv_assemble_integer
00398 #undef TARGET_DEFAULT_TARGET_FLAGS
00399 #define TARGET_DEFAULT_TARGET_FLAGS \
00400 (MASK_DEFAULT_ALLOC_CC \
00401 | MASK_COND_MOVE \
00402 | MASK_SCC \
00403 | MASK_COND_EXEC \
00404 | MASK_VLIW_BRANCH \
00405 | MASK_MULTI_CE \
00406 | MASK_NESTED_CE)
00407 #undef TARGET_HANDLE_OPTION
00408 #define TARGET_HANDLE_OPTION frv_handle_option
00409 #undef TARGET_INIT_BUILTINS
00410 #define TARGET_INIT_BUILTINS frv_init_builtins
00411 #undef TARGET_EXPAND_BUILTIN
00412 #define TARGET_EXPAND_BUILTIN frv_expand_builtin
00413 #undef TARGET_INIT_LIBFUNCS
00414 #define TARGET_INIT_LIBFUNCS frv_init_libfuncs
00415 #undef TARGET_IN_SMALL_DATA_P
00416 #define TARGET_IN_SMALL_DATA_P frv_in_small_data_p
00417 #undef TARGET_RTX_COSTS
00418 #define TARGET_RTX_COSTS frv_rtx_costs
00419 #undef TARGET_ASM_CONSTRUCTOR
00420 #define TARGET_ASM_CONSTRUCTOR frv_asm_out_constructor
00421 #undef TARGET_ASM_DESTRUCTOR
00422 #define TARGET_ASM_DESTRUCTOR frv_asm_out_destructor
00423
00424 #undef TARGET_ASM_OUTPUT_MI_THUNK
00425 #define TARGET_ASM_OUTPUT_MI_THUNK frv_asm_output_mi_thunk
00426 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
00427 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
00428
00429 #undef TARGET_SCHED_ISSUE_RATE
00430 #define TARGET_SCHED_ISSUE_RATE frv_issue_rate
00431
00432 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
00433 #define TARGET_FUNCTION_OK_FOR_SIBCALL frv_function_ok_for_sibcall
00434 #undef TARGET_CANNOT_FORCE_CONST_MEM
00435 #define TARGET_CANNOT_FORCE_CONST_MEM frv_cannot_force_const_mem
00436
00437 #undef TARGET_HAVE_TLS
00438 #define TARGET_HAVE_TLS HAVE_AS_TLS
00439
00440 #undef TARGET_STRUCT_VALUE_RTX
00441 #define TARGET_STRUCT_VALUE_RTX frv_struct_value_rtx
00442 #undef TARGET_MUST_PASS_IN_STACK
00443 #define TARGET_MUST_PASS_IN_STACK frv_must_pass_in_stack
00444 #undef TARGET_PASS_BY_REFERENCE
00445 #define TARGET_PASS_BY_REFERENCE hook_pass_by_reference_must_pass_in_stack
00446 #undef TARGET_ARG_PARTIAL_BYTES
00447 #define TARGET_ARG_PARTIAL_BYTES frv_arg_partial_bytes
00448
00449 #undef TARGET_EXPAND_BUILTIN_SAVEREGS
00450 #define TARGET_EXPAND_BUILTIN_SAVEREGS frv_expand_builtin_saveregs
00451 #undef TARGET_SETUP_INCOMING_VARARGS
00452 #define TARGET_SETUP_INCOMING_VARARGS frv_setup_incoming_varargs
00453 #undef TARGET_MACHINE_DEPENDENT_REORG
00454 #define TARGET_MACHINE_DEPENDENT_REORG frv_reorg
00455
00456 #if HAVE_AS_TLS
00457 #undef TARGET_ASM_OUTPUT_DWARF_DTPREL
00458 #define TARGET_ASM_OUTPUT_DWARF_DTPREL frv_output_dwarf_dtprel
00459 #endif
00460
00461 struct gcc_target targetm = TARGET_INITIALIZER;
00462
00463 #define FRV_SYMBOL_REF_TLS_P(RTX) \
00464 (GET_CODE (RTX) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (RTX) != 0)
00465
00466
00467
00468
00469
00470 static bool
00471 frv_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
00472 tree exp ATTRIBUTE_UNUSED)
00473 {
00474 return true;
00475 }
00476
00477
00478
00479
00480 static FRV_INLINE bool
00481 frv_small_data_reloc_p (rtx symbol, int reloc)
00482 {
00483 return (GET_CODE (symbol) == SYMBOL_REF
00484 && SYMBOL_REF_SMALL_P (symbol)
00485 && (!TARGET_FDPIC || flag_pic == 1)
00486 && (reloc == R_FRV_GOTOFF12 || reloc == R_FRV_GPREL12));
00487 }
00488
00489
00490
00491
00492 bool
00493 frv_const_unspec_p (rtx x, struct frv_unspec *unspec)
00494 {
00495 if (GET_CODE (x) == CONST)
00496 {
00497 unspec->offset = 0;
00498 x = XEXP (x, 0);
00499 if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == CONST_INT)
00500 {
00501 unspec->offset += INTVAL (XEXP (x, 1));
00502 x = XEXP (x, 0);
00503 }
00504 if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_GOT)
00505 {
00506 unspec->symbol = XVECEXP (x, 0, 0);
00507 unspec->reloc = INTVAL (XVECEXP (x, 0, 1));
00508
00509 if (unspec->offset == 0)
00510 return true;
00511
00512 if (frv_small_data_reloc_p (unspec->symbol, unspec->reloc)
00513 && unspec->offset > 0
00514 && (unsigned HOST_WIDE_INT) unspec->offset < g_switch_value)
00515 return true;
00516 }
00517 }
00518 return false;
00519 }
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540 static bool
00541 frv_cannot_force_const_mem (rtx x ATTRIBUTE_UNUSED)
00542 {
00543 return TARGET_FDPIC;
00544 }
00545
00546
00547
00548 static bool
00549 frv_handle_option (size_t code, const char *arg, int value ATTRIBUTE_UNUSED)
00550 {
00551 switch (code)
00552 {
00553 case OPT_mcpu_:
00554 if (strcmp (arg, "simple") == 0)
00555 frv_cpu_type = FRV_CPU_SIMPLE;
00556 else if (strcmp (arg, "tomcat") == 0)
00557 frv_cpu_type = FRV_CPU_TOMCAT;
00558 else if (strcmp (arg, "fr550") == 0)
00559 frv_cpu_type = FRV_CPU_FR550;
00560 else if (strcmp (arg, "fr500") == 0)
00561 frv_cpu_type = FRV_CPU_FR500;
00562 else if (strcmp (arg, "fr450") == 0)
00563 frv_cpu_type = FRV_CPU_FR450;
00564 else if (strcmp (arg, "fr405") == 0)
00565 frv_cpu_type = FRV_CPU_FR405;
00566 else if (strcmp (arg, "fr400") == 0)
00567 frv_cpu_type = FRV_CPU_FR400;
00568 else if (strcmp (arg, "fr300") == 0)
00569 frv_cpu_type = FRV_CPU_FR300;
00570 else if (strcmp (arg, "frv") == 0)
00571 frv_cpu_type = FRV_CPU_GENERIC;
00572 else
00573 return false;
00574 return true;
00575
00576 default:
00577 return true;
00578 }
00579 }
00580
00581 static int
00582 frv_default_flags_for_cpu (void)
00583 {
00584 switch (frv_cpu_type)
00585 {
00586 case FRV_CPU_GENERIC:
00587 return MASK_DEFAULT_FRV;
00588
00589 case FRV_CPU_FR550:
00590 return MASK_DEFAULT_FR550;
00591
00592 case FRV_CPU_FR500:
00593 case FRV_CPU_TOMCAT:
00594 return MASK_DEFAULT_FR500;
00595
00596 case FRV_CPU_FR450:
00597 return MASK_DEFAULT_FR450;
00598
00599 case FRV_CPU_FR405:
00600 case FRV_CPU_FR400:
00601 return MASK_DEFAULT_FR400;
00602
00603 case FRV_CPU_FR300:
00604 case FRV_CPU_SIMPLE:
00605 return MASK_DEFAULT_SIMPLE;
00606
00607 default:
00608 gcc_unreachable ();
00609 }
00610 }
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621 void
00622 frv_override_options (void)
00623 {
00624 int regno;
00625 unsigned int i;
00626
00627 target_flags |= (frv_default_flags_for_cpu () & ~target_flags_explicit);
00628
00629
00630
00631 if (TARGET_LIBPIC)
00632 {
00633 if (!flag_pic)
00634 flag_pic = 2;
00635
00636 if (! g_switch_set)
00637 {
00638 g_switch_set = 1;
00639 g_switch_value = 0;
00640 }
00641 }
00642
00643
00644
00645
00646
00647
00648 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
00649 {
00650 enum reg_class class;
00651
00652 if (GPR_P (regno))
00653 {
00654 int gpr_reg = regno - GPR_FIRST;
00655
00656 if (gpr_reg == GR8_REG)
00657 class = GR8_REGS;
00658
00659 else if (gpr_reg == GR9_REG)
00660 class = GR9_REGS;
00661
00662 else if (gpr_reg == GR14_REG)
00663 class = FDPIC_FPTR_REGS;
00664
00665 else if (gpr_reg == FDPIC_REGNO)
00666 class = FDPIC_REGS;
00667
00668 else if ((gpr_reg & 3) == 0)
00669 class = QUAD_REGS;
00670
00671 else if ((gpr_reg & 1) == 0)
00672 class = EVEN_REGS;
00673
00674 else
00675 class = GPR_REGS;
00676 }
00677
00678 else if (FPR_P (regno))
00679 {
00680 int fpr_reg = regno - GPR_FIRST;
00681 if ((fpr_reg & 3) == 0)
00682 class = QUAD_FPR_REGS;
00683
00684 else if ((fpr_reg & 1) == 0)
00685 class = FEVEN_REGS;
00686
00687 else
00688 class = FPR_REGS;
00689 }
00690
00691 else if (regno == LR_REGNO)
00692 class = LR_REG;
00693
00694 else if (regno == LCR_REGNO)
00695 class = LCR_REG;
00696
00697 else if (ICC_P (regno))
00698 class = ICC_REGS;
00699
00700 else if (FCC_P (regno))
00701 class = FCC_REGS;
00702
00703 else if (ICR_P (regno))
00704 class = ICR_REGS;
00705
00706 else if (FCR_P (regno))
00707 class = FCR_REGS;
00708
00709 else if (ACC_P (regno))
00710 {
00711 int r = regno - ACC_FIRST;
00712 if ((r & 3) == 0)
00713 class = QUAD_ACC_REGS;
00714 else if ((r & 1) == 0)
00715 class = EVEN_ACC_REGS;
00716 else
00717 class = ACC_REGS;
00718 }
00719
00720 else if (ACCG_P (regno))
00721 class = ACCG_REGS;
00722
00723 else
00724 class = NO_REGS;
00725
00726 regno_reg_class[regno] = class;
00727 }
00728
00729
00730 if (!g_switch_set)
00731 g_switch_value = SDATA_DEFAULT_SIZE;
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750 for (i = 0; i < 256; i++)
00751 reg_class_from_letter[i] = NO_REGS;
00752
00753 reg_class_from_letter['a'] = ACC_REGS;
00754 reg_class_from_letter['b'] = EVEN_ACC_REGS;
00755 reg_class_from_letter['c'] = CC_REGS;
00756 reg_class_from_letter['d'] = GPR_REGS;
00757 reg_class_from_letter['e'] = EVEN_REGS;
00758 reg_class_from_letter['f'] = FPR_REGS;
00759 reg_class_from_letter['h'] = FEVEN_REGS;
00760 reg_class_from_letter['l'] = LR_REG;
00761 reg_class_from_letter['q'] = QUAD_REGS;
00762 reg_class_from_letter['t'] = ICC_REGS;
00763 reg_class_from_letter['u'] = FCC_REGS;
00764 reg_class_from_letter['v'] = ICR_REGS;
00765 reg_class_from_letter['w'] = FCR_REGS;
00766 reg_class_from_letter['x'] = QUAD_FPR_REGS;
00767 reg_class_from_letter['y'] = LCR_REG;
00768 reg_class_from_letter['z'] = SPR_REGS;
00769 reg_class_from_letter['A'] = QUAD_ACC_REGS;
00770 reg_class_from_letter['B'] = ACCG_REGS;
00771 reg_class_from_letter['C'] = CR_REGS;
00772 reg_class_from_letter['W'] = FDPIC_CALL_REGS;
00773 reg_class_from_letter['Z'] = FDPIC_REGS;
00774
00775
00776
00777
00778 if (flag_pic || TARGET_FDPIC)
00779 targetm.asm_out.unaligned_op.si = 0;
00780
00781 if ((target_flags_explicit & MASK_LINKED_FP) == 0)
00782 target_flags |= MASK_LINKED_FP;
00783
00784 if ((target_flags_explicit & MASK_OPTIMIZE_MEMBAR) == 0)
00785 target_flags |= MASK_OPTIMIZE_MEMBAR;
00786
00787 for (i = 0; i < ARRAY_SIZE (frv_unit_names); i++)
00788 frv_unit_codes[i] = get_cpu_unit_code (frv_unit_names[i]);
00789
00790 for (i = 0; i < ARRAY_SIZE (frv_type_to_unit); i++)
00791 frv_type_to_unit[i] = ARRAY_SIZE (frv_unit_codes);
00792
00793 init_machine_status = frv_init_machine_status;
00794 }
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818 void
00819 frv_optimization_options (int level, int size ATTRIBUTE_UNUSED)
00820 {
00821 if (level >= 2)
00822 {
00823 #ifdef DISABLE_SCHED2
00824 flag_schedule_insns_after_reload = 0;
00825 #endif
00826 #ifdef ENABLE_RCSP
00827 flag_rcsp = 1;
00828 #endif
00829 }
00830 }
00831
00832
00833
00834
00835 static int
00836 frv_string_begins_with (tree name, const char *prefix)
00837 {
00838 int prefix_len = strlen (prefix);
00839
00840
00841 return (TREE_STRING_LENGTH (name) > prefix_len
00842 && strncmp (TREE_STRING_POINTER (name), prefix, prefix_len) == 0);
00843 }
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865 void
00866 frv_conditional_register_usage (void)
00867 {
00868 int i;
00869
00870 for (i = GPR_FIRST + NUM_GPRS; i <= GPR_LAST; i++)
00871 fixed_regs[i] = call_used_regs[i] = 1;
00872
00873 for (i = FPR_FIRST + NUM_FPRS; i <= FPR_LAST; i++)
00874 fixed_regs[i] = call_used_regs[i] = 1;
00875
00876
00877
00878 fixed_regs[ICC_TEMP] = call_used_regs[ICC_TEMP] = 1;
00879 fixed_regs[ICR_TEMP] = call_used_regs[ICR_TEMP] = 1;
00880
00881 if (TARGET_FIXED_CC)
00882 {
00883 fixed_regs[ICC_FIRST] = call_used_regs[ICC_FIRST] = 1;
00884 fixed_regs[FCC_FIRST] = call_used_regs[FCC_FIRST] = 1;
00885 fixed_regs[ICR_FIRST] = call_used_regs[ICR_FIRST] = 1;
00886 fixed_regs[FCR_FIRST] = call_used_regs[FCR_FIRST] = 1;
00887 }
00888
00889 if (TARGET_FDPIC)
00890 fixed_regs[GPR_FIRST + 16] = fixed_regs[GPR_FIRST + 17] =
00891 call_used_regs[GPR_FIRST + 16] = call_used_regs[GPR_FIRST + 17] = 0;
00892
00893 #if 0
00894
00895 if (g_switch_value == 0 && !flag_pic)
00896 fixed_regs[SDA_BASE_REG] = call_used_regs[SDA_BASE_REG] = 0;
00897
00898 if (!flag_pic)
00899 fixed_regs[PIC_REGNO] = call_used_regs[PIC_REGNO] = 0;
00900 #endif
00901 }
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070 frv_stack_t *
01071 frv_stack_info (void)
01072 {
01073 static frv_stack_t info, zero_info;
01074 frv_stack_t *info_ptr = &info;
01075 tree fndecl = current_function_decl;
01076 int varargs_p = 0;
01077 tree cur_arg;
01078 tree next_arg;
01079 int range;
01080 int alignment;
01081 int offset;
01082
01083
01084
01085 if (frv_stack_cache)
01086 return frv_stack_cache;
01087
01088
01089 info = zero_info;
01090
01091
01092 info_ptr->regs[STACK_REGS_GPR].name = "gpr";
01093 info_ptr->regs[STACK_REGS_GPR].first = LAST_ARG_REGNUM + 1;
01094 info_ptr->regs[STACK_REGS_GPR].last = GPR_LAST;
01095 info_ptr->regs[STACK_REGS_GPR].dword_p = TRUE;
01096
01097 info_ptr->regs[STACK_REGS_FPR].name = "fpr";
01098 info_ptr->regs[STACK_REGS_FPR].first = FPR_FIRST;
01099 info_ptr->regs[STACK_REGS_FPR].last = FPR_LAST;
01100 info_ptr->regs[STACK_REGS_FPR].dword_p = TRUE;
01101
01102 info_ptr->regs[STACK_REGS_LR].name = "lr";
01103 info_ptr->regs[STACK_REGS_LR].first = LR_REGNO;
01104 info_ptr->regs[STACK_REGS_LR].last = LR_REGNO;
01105 info_ptr->regs[STACK_REGS_LR].special_p = 1;
01106
01107 info_ptr->regs[STACK_REGS_CC].name = "cc";
01108 info_ptr->regs[STACK_REGS_CC].first = CC_FIRST;
01109 info_ptr->regs[STACK_REGS_CC].last = CC_LAST;
01110 info_ptr->regs[STACK_REGS_CC].field_p = TRUE;
01111
01112 info_ptr->regs[STACK_REGS_LCR].name = "lcr";
01113 info_ptr->regs[STACK_REGS_LCR].first = LCR_REGNO;
01114 info_ptr->regs[STACK_REGS_LCR].last = LCR_REGNO;
01115
01116 info_ptr->regs[STACK_REGS_STDARG].name = "stdarg";
01117 info_ptr->regs[STACK_REGS_STDARG].first = FIRST_ARG_REGNUM;
01118 info_ptr->regs[STACK_REGS_STDARG].last = LAST_ARG_REGNUM;
01119 info_ptr->regs[STACK_REGS_STDARG].dword_p = 1;
01120 info_ptr->regs[STACK_REGS_STDARG].special_p = 1;
01121
01122 info_ptr->regs[STACK_REGS_STRUCT].name = "struct";
01123 info_ptr->regs[STACK_REGS_STRUCT].first = FRV_STRUCT_VALUE_REGNUM;
01124 info_ptr->regs[STACK_REGS_STRUCT].last = FRV_STRUCT_VALUE_REGNUM;
01125 info_ptr->regs[STACK_REGS_STRUCT].special_p = 1;
01126
01127 info_ptr->regs[STACK_REGS_FP].name = "fp";
01128 info_ptr->regs[STACK_REGS_FP].first = FRAME_POINTER_REGNUM;
01129 info_ptr->regs[STACK_REGS_FP].last = FRAME_POINTER_REGNUM;
01130 info_ptr->regs[STACK_REGS_FP].special_p = 1;
01131
01132
01133
01134 if (cfun->stdarg)
01135 varargs_p = 1;
01136
01137 else
01138 {
01139
01140 for (cur_arg = DECL_ARGUMENTS (fndecl); cur_arg != (tree)0; cur_arg = next_arg)
01141 {
01142 next_arg = TREE_CHAIN (cur_arg);
01143 if (next_arg == (tree)0)
01144 {
01145 if (DECL_NAME (cur_arg)
01146 && !strcmp (IDENTIFIER_POINTER (DECL_NAME (cur_arg)), "__builtin_va_alist"))
01147 varargs_p = 1;
01148
01149 break;
01150 }
01151 }
01152 }
01153
01154
01155 for (range = 0; range < STACK_REGS_MAX; range++)
01156 {
01157 frv_stack_regs_t *reg_ptr = &(info_ptr->regs[range]);
01158 int first = reg_ptr->first;
01159 int last = reg_ptr->last;
01160 int size_1word = 0;
01161 int size_2words = 0;
01162 int regno;
01163
01164
01165 switch (range)
01166 {
01167 default:
01168 for (regno = first; regno <= last; regno++)
01169 {
01170 if ((regs_ever_live[regno] && !call_used_regs[regno])
01171 || (current_function_calls_eh_return
01172 && (regno >= FIRST_EH_REGNUM && regno <= LAST_EH_REGNUM))
01173 || (!TARGET_FDPIC && flag_pic
01174 && cfun->uses_pic_offset_table && regno == PIC_REGNO))
01175 {
01176 info_ptr->save_p[regno] = REG_SAVE_1WORD;
01177 size_1word += UNITS_PER_WORD;
01178 }
01179 }
01180 break;
01181
01182
01183
01184 case STACK_REGS_FP:
01185 break;
01186
01187 case STACK_REGS_LR:
01188 if (regs_ever_live[LR_REGNO]
01189 || profile_flag
01190
01191 || cfun->machine->frame_needed
01192 || (TARGET_LINKED_FP && frame_pointer_needed)
01193 || (!TARGET_FDPIC && flag_pic
01194 && cfun->uses_pic_offset_table))
01195 {
01196 info_ptr->save_p[LR_REGNO] = REG_SAVE_1WORD;
01197 size_1word += UNITS_PER_WORD;
01198 }
01199 break;
01200
01201 case STACK_REGS_STDARG:
01202 if (varargs_p)
01203 {
01204
01205
01206
01207 last -= (ADDR_ALIGN (cfun->pretend_args_size, UNITS_PER_WORD)
01208 / UNITS_PER_WORD);
01209
01210 for (regno = first; regno <= last; regno++)
01211 {
01212 info_ptr->save_p[regno] = REG_SAVE_1WORD;
01213 size_1word += UNITS_PER_WORD;
01214 }
01215
01216 info_ptr->stdarg_size = size_1word;
01217 }
01218 break;
01219
01220 case STACK_REGS_STRUCT:
01221 if (cfun->returns_struct)
01222 {
01223 info_ptr->save_p[FRV_STRUCT_VALUE_REGNUM] = REG_SAVE_1WORD;
01224 size_1word += UNITS_PER_WORD;
01225 }
01226 break;
01227 }
01228
01229
01230 if (size_1word)
01231 {
01232
01233 if (reg_ptr->field_p)
01234 size_1word = UNITS_PER_WORD;
01235
01236
01237 else if (reg_ptr->dword_p && TARGET_DWORD)
01238 {
01239 for (regno = first; regno < last; regno += 2)
01240 {
01241 if (info_ptr->save_p[regno] && info_ptr->save_p[regno+1])
01242 {
01243 size_2words += 2 * UNITS_PER_WORD;
01244 size_1word -= 2 * UNITS_PER_WORD;
01245 info_ptr->save_p[regno] = REG_SAVE_2WORDS;
01246 info_ptr->save_p[regno+1] = REG_SAVE_NO_SAVE;
01247 }
01248 }
01249 }
01250
01251 reg_ptr->size_1word = size_1word;
01252 reg_ptr->size_2words = size_2words;
01253
01254 if (! reg_ptr->special_p)
01255 {
01256 info_ptr->regs_size_1word += size_1word;
01257 info_ptr->regs_size_2words += size_2words;
01258 }
01259 }
01260 }
01261
01262
01263
01264
01265 alignment = (TARGET_DWORD? 2 * UNITS_PER_WORD : UNITS_PER_WORD);
01266
01267 info_ptr->parameter_size = ADDR_ALIGN (cfun->outgoing_args_size, alignment);
01268 info_ptr->regs_size = ADDR_ALIGN (info_ptr->regs_size_2words
01269 + info_ptr->regs_size_1word,
01270 alignment);
01271 info_ptr->vars_size = ADDR_ALIGN (get_frame_size (), alignment);
01272
01273 info_ptr->pretend_size = cfun->pretend_args_size;
01274
01275
01276
01277 info_ptr->total_size
01278 = (ADDR_ALIGN (info_ptr->parameter_size
01279 + info_ptr->regs_size
01280 + info_ptr->vars_size,
01281 2 * UNITS_PER_WORD)
01282 + ADDR_ALIGN (info_ptr->pretend_size
01283 + info_ptr->stdarg_size,
01284 2 * UNITS_PER_WORD));
01285
01286
01287 if (info_ptr->total_size > 0
01288 || frame_pointer_needed
01289 || info_ptr->regs[STACK_REGS_LR].size_1word > 0
01290 || info_ptr->regs[STACK_REGS_STRUCT].size_1word > 0)
01291 {
01292 offset = info_ptr->parameter_size;
01293 info_ptr->header_size = 4 * UNITS_PER_WORD;
01294 info_ptr->total_size += 4 * UNITS_PER_WORD;
01295
01296
01297 for (range = 0; range < STACK_REGS_MAX; range++)
01298 {
01299 frv_stack_regs_t *reg_ptr = &(info_ptr->regs[range]);
01300 if (! reg_ptr->special_p)
01301 {
01302 int first = reg_ptr->first;
01303 int last = reg_ptr->last;
01304 int regno;
01305
01306 for (regno = first; regno <= last; regno++)
01307 if (info_ptr->save_p[regno] == REG_SAVE_2WORDS
01308 && regno != FRAME_POINTER_REGNUM
01309 && (regno < FIRST_ARG_REGNUM
01310 || regno > LAST_ARG_REGNUM))
01311 {
01312 info_ptr->reg_offset[regno] = offset;
01313 offset += 2 * UNITS_PER_WORD;
01314 }
01315 }
01316 }
01317
01318
01319 for (range = 0; range < STACK_REGS_MAX; range++)
01320 {
01321 frv_stack_regs_t *reg_ptr = &(info_ptr->regs[range]);
01322 if (! reg_ptr->special_p)
01323 {
01324 int first = reg_ptr->first;
01325 int last = reg_ptr->last;
01326 int regno;
01327
01328 for (regno = first; regno <= last; regno++)
01329 if (info_ptr->save_p[regno] == REG_SAVE_1WORD
01330 && regno != FRAME_POINTER_REGNUM
01331 && (regno < FIRST_ARG_REGNUM
01332 || regno > LAST_ARG_REGNUM))
01333 {
01334 info_ptr->reg_offset[regno] = offset;
01335 offset += UNITS_PER_WORD;
01336 }
01337 }
01338 }
01339
01340
01341 offset = ADDR_ALIGN (offset, alignment);
01342 if (info_ptr->vars_size)
01343 {
01344 info_ptr->vars_offset = offset;
01345 offset += info_ptr->vars_size;
01346 }
01347
01348
01349 offset = ADDR_ALIGN (offset, 2 * UNITS_PER_WORD);
01350
01351
01352 info_ptr->save_p[FRAME_POINTER_REGNUM] = REG_SAVE_1WORD;
01353 info_ptr->reg_offset[FRAME_POINTER_REGNUM] = offset;
01354 info_ptr->regs[STACK_REGS_FP].size_1word = UNITS_PER_WORD;
01355
01356 info_ptr->save_p[LR_REGNO] = REG_SAVE_1WORD;
01357 info_ptr->reg_offset[LR_REGNO] = offset + 2*UNITS_PER_WORD;
01358 info_ptr->regs[STACK_REGS_LR].size_1word = UNITS_PER_WORD;
01359
01360 if (cfun->returns_struct)
01361 {
01362 info_ptr->save_p[FRV_STRUCT_VALUE_REGNUM] = REG_SAVE_1WORD;
01363 info_ptr->reg_offset[FRV_STRUCT_VALUE_REGNUM] = offset + UNITS_PER_WORD;
01364 info_ptr->regs[STACK_REGS_STRUCT].size_1word = UNITS_PER_WORD;
01365 }
01366
01367
01368
01369
01370
01371 if (info_ptr->stdarg_size)
01372 {
01373 int first = info_ptr->regs[STACK_REGS_STDARG].first;
01374 int last = info_ptr->regs[STACK_REGS_STDARG].last;
01375 int regno;
01376
01377
01378 offset += 4 * UNITS_PER_WORD;
01379 for (regno = first; regno <= last; regno++)
01380 {
01381 if (info_ptr->save_p[regno] == REG_SAVE_2WORDS)
01382 {
01383 info_ptr->reg_offset[regno] = offset;
01384 offset += 2 * UNITS_PER_WORD;
01385 }
01386 else if (info_ptr->save_p[regno] == REG_SAVE_1WORD)
01387 {
01388 info_ptr->reg_offset[regno] = offset;
01389 offset += UNITS_PER_WORD;
01390 }
01391 }
01392 }
01393 }
01394
01395 if (reload_completed)
01396 frv_stack_cache = info_ptr;
01397
01398 return info_ptr;
01399 }
01400
01401
01402
01403
01404 void
01405 frv_debug_stack (frv_stack_t *info)
01406 {
01407 int range;
01408
01409 if (!info)
01410 info = frv_stack_info ();
01411
01412 fprintf (stderr, "\nStack information for function %s:\n",
01413 ((current_function_decl && DECL_NAME (current_function_decl))
01414 ? IDENTIFIER_POINTER (DECL_NAME (current_function_decl))
01415 : "<unknown>"));
01416
01417 fprintf (stderr, "\ttotal_size\t= %6d\n", info->total_size);
01418 fprintf (stderr, "\tvars_size\t= %6d\n", info->vars_size);
01419 fprintf (stderr, "\tparam_size\t= %6d\n", info->parameter_size);
01420 fprintf (stderr, "\tregs_size\t= %6d, 1w = %3d, 2w = %3d\n",
01421 info->regs_size, info->regs_size_1word, info->regs_size_2words);
01422
01423 fprintf (stderr, "\theader_size\t= %6d\n", info->header_size);
01424 fprintf (stderr, "\tpretend_size\t= %6d\n", info->pretend_size);
01425 fprintf (stderr, "\tvars_offset\t= %6d\n", info->vars_offset);
01426 fprintf (stderr, "\tregs_offset\t= %6d\n", info->regs_offset);
01427
01428 for (range = 0; range < STACK_REGS_MAX; range++)
01429 {
01430 frv_stack_regs_t *regs = &(info->regs[range]);
01431 if ((regs->size_1word + regs->size_2words) > 0)
01432 {
01433 int first = regs->first;
01434 int last = regs->last;
01435 int regno;
01436
01437 fprintf (stderr, "\t%s\tsize\t= %6d, 1w = %3d, 2w = %3d, save =",
01438 regs->name, regs->size_1word + regs->size_2words,
01439 regs->size_1word, regs->size_2words);
01440
01441 for (regno = first; regno <= last; regno++)
01442 {
01443 if (info->save_p[regno] == REG_SAVE_1WORD)
01444 fprintf (stderr, " %s (%d)", reg_names[regno],
01445 info->reg_offset[regno]);
01446
01447 else if (info->save_p[regno] == REG_SAVE_2WORDS)
01448 fprintf (stderr, " %s-%s (%d)", reg_names[regno],
01449 reg_names[regno+1], info->reg_offset[regno]);
01450 }
01451
01452 fputc ('\n', stderr);
01453 }
01454 }
01455
01456 fflush (stderr);
01457 }
01458
01459
01460
01461
01462
01463
01464
01465
01466 static int frv_insn_packing_flag;
01467
01468
01469
01470 static int
01471 frv_function_contains_far_jump (void)
01472 {
01473 rtx insn = get_insns ();
01474 while (insn != NULL
01475 && !(GET_CODE (insn) == JUMP_INSN
01476
01477 && GET_CODE (PATTERN (insn)) != ADDR_VEC
01478 && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC
01479 && get_attr_far_jump (insn) == FAR_JUMP_YES))
01480 insn = NEXT_INSN (insn);
01481 return (insn != NULL);
01482 }
01483
01484
01485
01486
01487 static void
01488 frv_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
01489 {
01490
01491
01492
01493
01494
01495
01496 if (frv_stack_info ()->total_size == 0 && frv_function_contains_far_jump ())
01497 {
01498 rtx insn;
01499
01500
01501 gcc_assert (!regs_ever_live[GPR_FIRST + 3]);
01502
01503
01504 fprintf (file, "\tmovsg lr,gr3\n");
01505
01506
01507
01508
01509
01510 for (insn = get_insns(); insn != NULL; insn = NEXT_INSN (insn))
01511 if (GET_CODE (insn) == JUMP_INSN)
01512 {
01513 rtx pattern = PATTERN (insn);
01514 if (GET_CODE (pattern) == PARALLEL
01515 && XVECLEN (pattern, 0) >= 2
01516 && GET_CODE (XVECEXP (pattern, 0, 0)) == RETURN
01517 && GET_CODE (XVECEXP (pattern, 0, 1)) == USE)
01518 {
01519 rtx address = XEXP (XVECEXP (pattern, 0, 1), 0);
01520 if (GET_CODE (address) == REG && REGNO (address) == LR_REGNO)
01521 REGNO (address) = GPR_FIRST + 3;
01522 }
01523 }
01524 }
01525
01526 frv_pack_insns ();
01527
01528
01529 memset (frv_nops, 0, sizeof (frv_nops));
01530 }
01531
01532
01533
01534
01535 static rtx
01536 frv_alloc_temp_reg (
01537 frv_tmp_reg_t *info,
01538 enum reg_class class,
01539 enum machine_mode mode,
01540 int mark_as_used,
01541 int no_abort)
01542 {
01543 int regno = info->next_reg[ (int)class ];
01544 int orig_regno = regno;
01545 HARD_REG_SET *reg_in_class = ®_class_contents[ (int)class ];
01546 int i, nr;
01547
01548 for (;;)
01549 {
01550 if (TEST_HARD_REG_BIT (*reg_in_class, regno)
01551 && TEST_HARD_REG_BIT (info->regs, regno))
01552 break;
01553
01554 if (++regno >= FIRST_PSEUDO_REGISTER)
01555 regno = 0;
01556 if (regno == orig_regno)
01557 {
01558 gcc_assert (no_abort);
01559 return NULL_RTX;
01560 }
01561 }
01562
01563 nr = HARD_REGNO_NREGS (regno, mode);
01564 info->next_reg[ (int)class ] = regno + nr;
01565
01566 if (mark_as_used)
01567 for (i = 0; i < nr; i++)
01568 CLEAR_HARD_REG_BIT (info->regs, regno+i);
01569
01570 return gen_rtx_REG (mode, regno);
01571 }
01572
01573
01574
01575
01576
01577
01578
01579
01580 static rtx
01581 frv_frame_offset_rtx (int offset)
01582 {
01583 rtx offset_rtx = GEN_INT (offset);
01584 if (IN_RANGE_P (offset, -2048, 2047))
01585 return offset_rtx;
01586 else
01587 {
01588 rtx reg_rtx = gen_rtx_REG (SImode, OFFSET_REGNO);
01589 if (IN_RANGE_P (offset, -32768, 32767))
01590 emit_insn (gen_movsi (reg_rtx, offset_rtx));
01591 else
01592 {
01593 emit_insn (gen_movsi_high (reg_rtx, offset_rtx));
01594 emit_insn (gen_movsi_lo_sum (reg_rtx, offset_rtx));
01595 }
01596 return reg_rtx;
01597 }
01598 }
01599
01600
01601
01602 static rtx
01603 frv_frame_mem (enum machine_mode mode, rtx base, int offset)
01604 {
01605 return gen_rtx_MEM (mode, gen_rtx_PLUS (Pmode,
01606 base,
01607 frv_frame_offset_rtx (offset)));
01608 }
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619 static rtx
01620 frv_dwarf_store (rtx reg, int offset)
01621 {
01622 rtx set = gen_rtx_SET (VOIDmode,
01623 gen_rtx_MEM (GET_MODE (reg),
01624 plus_constant (stack_pointer_rtx,
01625 offset)),
01626 reg);
01627 RTX_FRAME_RELATED_P (set) = 1;
01628 return set;
01629 }
01630
01631
01632
01633
01634
01635
01636 static void
01637 frv_frame_insn (rtx pattern, rtx dwarf_pattern)
01638 {
01639 rtx insn = emit_insn (pattern);
01640 RTX_FRAME_RELATED_P (insn) = 1;
01641 REG_NOTES (insn) = alloc_EXPR_LIST (REG_FRAME_RELATED_EXPR,
01642 dwarf_pattern,
01643 REG_NOTES (insn));
01644 }
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663 static void
01664 frv_frame_access (frv_frame_accessor_t *accessor, rtx reg, int stack_offset)
01665 {
01666 enum machine_mode mode = GET_MODE (reg);
01667 rtx mem = frv_frame_mem (mode,
01668 accessor->base,
01669 stack_offset - accessor->base_offset);
01670
01671 if (accessor->op == FRV_LOAD)
01672 {
01673 if (SPR_P (REGNO (reg)))
01674 {
01675 rtx temp = gen_rtx_REG (mode, TEMP_REGNO);
01676 emit_insn (gen_rtx_SET (VOIDmode, temp, mem));
01677 emit_insn (gen_rtx_SET (VOIDmode, reg, temp));
01678 }
01679 else
01680 emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
01681 emit_insn (gen_rtx_USE (VOIDmode, reg));
01682 }
01683 else
01684 {
01685 if (SPR_P (REGNO (reg)))
01686 {
01687 rtx temp = gen_rtx_REG (mode, TEMP_REGNO);
01688 emit_insn (gen_rtx_SET (VOIDmode, temp, reg));
01689 frv_frame_insn (gen_rtx_SET (Pmode, mem, temp),
01690 frv_dwarf_store (reg, stack_offset));
01691 }
01692 else if (GET_MODE (reg) == DImode)
01693 {
01694
01695
01696 rtx reg1 = gen_rtx_REG (SImode, REGNO (reg));
01697 rtx reg2 = gen_rtx_REG (SImode, REGNO (reg) + 1);
01698 rtx set1 = frv_dwarf_store (reg1, stack_offset);
01699 rtx set2 = frv_dwarf_store (reg2, stack_offset + 4);
01700 frv_frame_insn (gen_rtx_SET (Pmode, mem, reg),
01701 gen_rtx_PARALLEL (VOIDmode,
01702 gen_rtvec (2, set1, set2)));
01703 }
01704 else
01705 frv_frame_insn (gen_rtx_SET (Pmode, mem, reg),
01706 frv_dwarf_store (reg, stack_offset));
01707 }
01708 }
01709
01710
01711
01712
01713
01714 static void
01715 frv_frame_access_multi (frv_frame_accessor_t *accessor,
01716 frv_stack_t *info,
01717 int reg_set)
01718 {
01719 frv_stack_regs_t *regs_info;
01720 int regno;
01721
01722 regs_info = &info->regs[reg_set];
01723 for (regno = regs_info->first; regno <= regs_info->last; regno++)
01724 if (info->save_p[regno])
01725 frv_frame_access (accessor,
01726 info->save_p[regno] == REG_SAVE_2WORDS
01727 ? gen_rtx_REG (DImode, regno)
01728 : gen_rtx_REG (SImode, regno),
01729 info->reg_offset[regno]);
01730 }
01731
01732
01733
01734
01735
01736 static void
01737 frv_frame_access_standard_regs (enum frv_stack_op op, frv_stack_t *info)
01738 {
01739 frv_frame_accessor_t accessor;
01740
01741 accessor.op = op;
01742 accessor.base = stack_pointer_rtx;
01743 accessor.base_offset = 0;
01744 frv_frame_access_multi (&accessor, info, STACK_REGS_GPR);
01745 frv_frame_access_multi (&accessor, info, STACK_REGS_FPR);
01746 frv_frame_access_multi (&accessor, info, STACK_REGS_LCR);
01747 }
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760 void
01761 frv_expand_prologue (void)
01762 {
01763 frv_stack_t *info = frv_stack_info ();
01764 rtx sp = stack_pointer_rtx;
01765 rtx fp = frame_pointer_rtx;
01766 frv_frame_accessor_t accessor;
01767
01768 if (TARGET_DEBUG_STACK)
01769 frv_debug_stack (info);
01770
01771 if (info->total_size == 0)
01772 return;
01773
01774
01775
01776
01777
01778
01779
01780
01781
01782
01783
01784
01785
01786
01787
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798 accessor.op = FRV_STORE;
01799 if (frame_pointer_needed && info->total_size > 2048)
01800 {
01801 rtx insn;
01802
01803 accessor.base = gen_rtx_REG (Pmode, OLD_SP_REGNO);
01804 accessor.base_offset = info->total_size;
01805 insn = emit_insn (gen_movsi (accessor.base, sp));
01806 }
01807 else
01808 {
01809 accessor.base = stack_pointer_rtx;
01810 accessor.base_offset = 0;
01811 }
01812
01813
01814 {
01815 rtx asm_offset = frv_frame_offset_rtx (-info->total_size);
01816 rtx dwarf_offset = GEN_INT (-info->total_size);
01817
01818 frv_frame_insn (gen_stack_adjust (sp, sp, asm_offset),
01819 gen_rtx_SET (Pmode,
01820 sp,
01821 gen_rtx_PLUS (Pmode, sp, dwarf_offset)));
01822 }
01823
01824
01825
01826 if (frame_pointer_needed)
01827 {
01828 int fp_offset = info->reg_offset[FRAME_POINTER_REGNUM];
01829
01830
01831
01832
01833 rtx asm_src = plus_constant (accessor.base,
01834 fp_offset - accessor.base_offset);
01835 rtx dwarf_src = plus_constant (sp, fp_offset);
01836
01837
01838 frv_frame_access (&accessor, fp, fp_offset);
01839
01840
01841 frv_frame_insn (gen_rtx_SET (VOIDmode, fp, asm_src),
01842 gen_rtx_SET (VOIDmode, fp, dwarf_src));
01843
01844
01845 accessor.base = fp;
01846 accessor.base_offset = fp_offset;
01847 }
01848
01849
01850 frv_frame_access_multi (&accessor, info, STACK_REGS_STRUCT);
01851 frv_frame_access_multi (&accessor, info, STACK_REGS_LR);
01852 frv_frame_access_multi (&accessor, info, STACK_REGS_STDARG);
01853
01854
01855 frv_frame_access_standard_regs (FRV_STORE, info);
01856
01857
01858
01859 if (info->stdarg_size > 0)
01860 emit_insn (gen_blockage ());
01861
01862
01863 if (!TARGET_FDPIC && flag_pic && cfun->uses_pic_offset_table)
01864 emit_insn (gen_pic_prologue (gen_rtx_REG (Pmode, PIC_REGNO),
01865 gen_rtx_REG (Pmode, LR_REGNO),
01866 gen_rtx_REG (SImode, OFFSET_REGNO)));
01867 }
01868
01869
01870
01871
01872
01873 static void
01874 frv_function_epilogue (FILE *file ATTRIBUTE_UNUSED,
01875 HOST_WIDE_INT size ATTRIBUTE_UNUSED)
01876 {
01877 frv_stack_cache = (frv_stack_t *)0;
01878
01879
01880 memset (&frv_ifcvt.tmp_reg, 0, sizeof (frv_ifcvt.tmp_reg));
01881
01882
01883 BITMAP_FREE (frv_ifcvt.scratch_insns_bitmap);
01884 }
01885
01886
01887
01888
01889
01890
01891
01892
01893
01894
01895 void
01896 frv_expand_epilogue (bool emit_return)
01897 {
01898 frv_stack_t *info = frv_stack_info ();
01899 rtx fp = frame_pointer_rtx;
01900 rtx sp = stack_pointer_rtx;
01901 rtx return_addr;
01902 int fp_offset;
01903
01904 fp_offset = info->reg_offset[FRAME_POINTER_REGNUM];
01905
01906
01907
01908 if (! current_function_sp_is_unchanging)
01909 emit_insn (gen_addsi3 (sp, fp, frv_frame_offset_rtx (-fp_offset)));
01910
01911
01912 frv_frame_access_standard_regs (FRV_LOAD, info);
01913
01914
01915
01916 if (info->save_p[LR_REGNO])
01917 {
01918 int lr_offset;
01919 rtx mem;
01920
01921
01922
01923
01924
01925
01926
01927 lr_offset = info->reg_offset[LR_REGNO];
01928 if (frame_pointer_needed)
01929 mem = frv_frame_mem (Pmode, fp, lr_offset - fp_offset);
01930 else
01931 mem = frv_frame_mem (Pmode, sp, lr_offset);
01932
01933
01934 return_addr = gen_rtx_REG (Pmode, TEMP_REGNO);
01935 emit_insn (gen_rtx_SET (VOIDmode, return_addr, mem));
01936 }
01937 else
01938 return_addr = gen_rtx_REG (Pmode, LR_REGNO);
01939
01940
01941
01942 if (frame_pointer_needed)
01943 {
01944 emit_insn (gen_rtx_SET (VOIDmode, fp, gen_rtx_MEM (Pmode, fp)));
01945 emit_insn (gen_rtx_USE (VOIDmode, fp));
01946 }
01947
01948
01949 if (info->total_size != 0)
01950 {
01951 rtx offset = frv_frame_offset_rtx (info->total_size);
01952 emit_insn (gen_stack_adjust (sp, sp, offset));
01953 }
01954
01955
01956 if (current_function_calls_eh_return)
01957 emit_insn (gen_stack_adjust (sp, sp, EH_RETURN_STACKADJ_RTX));
01958
01959 if (emit_return)
01960 emit_jump_insn (gen_epilogue_return (return_addr));
01961 else
01962 {
01963 rtx lr = return_addr;
01964
01965 if (REGNO (return_addr) != LR_REGNO)
01966 {
01967 lr = gen_rtx_REG (Pmode, LR_REGNO);
01968 emit_move_insn (lr, return_addr);
01969 }
01970
01971 emit_insn (gen_rtx_USE (VOIDmode, lr));
01972 }
01973 }
01974
01975
01976
01977
01978 static void
01979 frv_asm_output_mi_thunk (FILE *file,
01980 tree thunk_fndecl ATTRIBUTE_UNUSED,
01981 HOST_WIDE_INT delta,
01982 HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED,
01983 tree function)
01984 {
01985 const char *name_func = XSTR (XEXP (DECL_RTL (function), 0), 0);
01986 const char *name_arg0 = reg_names[FIRST_ARG_REGNUM];
01987 const char *name_jmp = reg_names[JUMP_REGNO];
01988 const char *parallel = (frv_issue_rate () > 1 ? ".p" : "");
01989
01990
01991 if (IN_RANGE_P (delta, -2048, 2047))
01992 fprintf (file, "\taddi %s,#%d,%s\n", name_arg0, (int) delta, name_arg0);
01993 else
01994 {
01995 const char *const name_add = reg_names[TEMP_REGNO];
01996 fprintf (file, "\tsethi%s #hi(" HOST_WIDE_INT_PRINT_DEC "),%s\n",
01997 parallel, delta, name_add);
01998 fprintf (file, "\tsetlo #lo(" HOST_WIDE_INT_PRINT_DEC "),%s\n",
01999 delta, name_add);
02000 fprintf (file, "\tadd %s,%s,%s\n", name_add, name_arg0, name_arg0);
02001 }
02002
02003 if (TARGET_FDPIC)
02004 {
02005 const char *name_pic = reg_names[FDPIC_REGNO];
02006 name_jmp = reg_names[FDPIC_FPTR_REGNO];
02007
02008 if (flag_pic != 1)
02009 {
02010 fprintf (file, "\tsethi%s #gotofffuncdeschi(", parallel);
02011 assemble_name (file, name_func);
02012 fprintf (file, "),%s\n", name_jmp);
02013
02014 fprintf (file, "\tsetlo #gotofffuncdesclo(");
02015 assemble_name (file, name_func);
02016 fprintf (file, "),%s\n", name_jmp);
02017
02018 fprintf (file, "\tldd @(%s,%s), %s\n", name_jmp, name_pic, name_jmp);
02019 }
02020 else
02021 {
02022 fprintf (file, "\tlddo @(%s,#gotofffuncdesc12(", name_pic);
02023 assemble_name (file, name_func);
02024 fprintf (file, "\t)), %s\n", name_jmp);
02025 }
02026 }
02027 else if (!flag_pic)
02028 {
02029 fprintf (file, "\tsethi%s #hi(", parallel);
02030 assemble_name (file, name_func);
02031 fprintf (file, "),%s\n", name_jmp);
02032
02033 fprintf (file, "\tsetlo #lo(");
02034 assemble_name (file, name_func);
02035 fprintf (file, "),%s\n", name_jmp);
02036 }
02037 else
02038 {
02039
02040 const char *name_lr = reg_names[LR_REGNO];
02041 const char *name_gppic = name_jmp;
02042 const char *name_tmp = reg_names[TEMP_REGNO];
02043
02044 fprintf (file, "\tmovsg %s,%s\n", name_lr, name_tmp);
02045 fprintf (file, "\tcall 1f\n");
02046 fprintf (file, "1:\tmovsg %s,%s\n", name_lr, name_gppic);
02047 fprintf (file, "\tmovgs %s,%s\n", name_tmp, name_lr);
02048 fprintf (file, "\tsethi%s #gprelhi(1b),%s\n", parallel, name_tmp);
02049 fprintf (file, "\tsetlo #gprello(1b),%s\n", name_tmp);
02050 fprintf (file, "\tsub %s,%s,%s\n", name_gppic, name_tmp, name_gppic);
02051
02052 fprintf (file, "\tsethi%s #gprelhi(", parallel);
02053 assemble_name (file, name_func);
02054 fprintf (file, "),%s\n", name_tmp);
02055
02056 fprintf (file, "\tsetlo #gprello(");
02057 assemble_name (file, name_func);
02058 fprintf (file, "),%s\n", name_tmp);
02059
02060 fprintf (file, "\tadd %s,%s,%s\n", name_gppic, name_tmp, name_jmp);
02061 }
02062
02063
02064 fprintf (file, "\tjmpl @(%s,%s)\n", name_jmp, reg_names[GPR_FIRST+0]);
02065 }
02066
02067
02068
02069
02070
02071
02072
02073
02074
02075
02076
02077
02078
02079
02080
02081
02082
02083
02084
02085
02086
02087
02088
02089 int
02090 frv_frame_pointer_required (void)
02091 {
02092
02093
02094 if (!TARGET_LINKED_FP)
02095 return !current_function_sp_is_unchanging;
02096
02097 if (! current_function_is_leaf)
02098 return TRUE;
02099
02100 if (get_frame_size () != 0)
02101 return TRUE;
02102
02103 if (cfun->stdarg)
02104 return TRUE;
02105
02106 if (!current_function_sp_is_unchanging)
02107 return TRUE;
02108
02109 if (!TARGET_FDPIC && flag_pic && cfun->uses_pic_offset_table)
02110 return TRUE;
02111
02112 if (profile_flag)
02113 return TRUE;
02114
02115 if (cfun->machine->frame_needed)
02116 return TRUE;
02117
02118 return FALSE;
02119 }
02120
02121
02122
02123
02124
02125
02126
02127
02128 int
02129 frv_initial_elimination_offset (int from, int to)
02130 {
02131 frv_stack_t *info = frv_stack_info ();
02132 int ret = 0;
02133
02134 if (to == STACK_POINTER_REGNUM && from == ARG_POINTER_REGNUM)
02135 ret = info->total_size - info->pretend_size;
02136
02137 else if (to == STACK_POINTER_REGNUM && from == FRAME_POINTER_REGNUM)
02138 ret = info->reg_offset[FRAME_POINTER_REGNUM];
02139
02140 else if (to == FRAME_POINTER_REGNUM && from == ARG_POINTER_REGNUM)
02141 ret = (info->total_size
02142 - info->reg_offset[FRAME_POINTER_REGNUM]
02143 - info->pretend_size);
02144
02145 else
02146 gcc_unreachable ();
02147
02148 if (TARGET_DEBUG_STACK)
02149 fprintf (stderr, "Eliminate %s to %s by adding %d\n",
02150 reg_names [from], reg_names[to], ret);
02151
02152 return ret;
02153 }
02154
02155
02156
02157
02158 static void
02159 frv_setup_incoming_varargs (CUMULATIVE_ARGS *cum,
02160 enum machine_mode mode,
02161 tree type ATTRIBUTE_UNUSED,
02162 int *pretend_size,
02163 int second_time)
02164 {
02165 if (TARGET_DEBUG_ARG)
02166 fprintf (stderr,
02167 "setup_vararg: words = %2d, mode = %4s, pretend_size = %d, second_time = %d\n",
02168 *cum, GET_MODE_NAME (mode), *pretend_size, second_time);
02169 }
02170
02171
02172
02173
02174 static rtx
02175 frv_expand_builtin_saveregs (void)
02176 {
02177 int offset = UNITS_PER_WORD * FRV_NUM_ARG_REGS;
02178
02179 if (TARGET_DEBUG_ARG)
02180 fprintf (stderr, "expand_builtin_saveregs: offset from ap = %d\n",
02181 offset);
02182
02183 return gen_rtx_PLUS (Pmode, virtual_incoming_args_rtx, GEN_INT (- offset));
02184 }
02185
02186
02187
02188
02189 void
02190 frv_expand_builtin_va_start (tree valist, rtx nextarg)
02191 {
02192 tree t;
02193 int num = cfun->args_info - FIRST_ARG_REGNUM - FRV_NUM_ARG_REGS;
02194
02195 nextarg = gen_rtx_PLUS (Pmode, virtual_incoming_args_rtx,
02196 GEN_INT (UNITS_PER_WORD * num));
02197
02198 if (TARGET_DEBUG_ARG)
02199 {
02200 fprintf (stderr, "va_start: args_info = %d, num = %d\n",
02201 cfun->args_info, num);
02202
02203 debug_rtx (nextarg);
02204 }
02205
02206 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist,
02207 make_tree (ptr_type_node, nextarg));
02208 TREE_SIDE_EFFECTS (t) = 1;
02209
02210 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
02211 }
02212
02213
02214
02215
02216
02217
02218
02219
02220
02221
02222
02223 #ifndef MAX_MOVE_REG
02224 #define MAX_MOVE_REG 4
02225 #endif
02226
02227
02228 #ifndef TOTAL_MOVE_REG
02229 #define TOTAL_MOVE_REG 8
02230 #endif
02231
02232 int
02233 frv_expand_block_move (rtx operands[])
02234 {
02235 rtx orig_dest = operands[0];
02236 rtx orig_src = operands[1];
02237 rtx bytes_rtx = operands[2];
02238 rtx align_rtx = operands[3];
02239 int constp = (GET_CODE (bytes_rtx) == CONST_INT);
02240 int align;
02241 int bytes;
02242 int offset;
02243 int num_reg;
02244 int i;
02245 rtx src_reg;
02246 rtx dest_reg;
02247 rtx src_addr;
02248 rtx dest_addr;
02249 rtx src_mem;
02250 rtx dest_mem;
02251 rtx tmp_reg;
02252 rtx stores[MAX_MOVE_REG];
02253 int move_bytes;
02254 enum machine_mode mode;
02255
02256
02257 if (! constp)
02258 return FALSE;
02259
02260
02261 gcc_assert (GET_CODE (align_rtx) == CONST_INT);
02262
02263 align = INTVAL (align_rtx);
02264
02265
02266 bytes = INTVAL (bytes_rtx);
02267 if (bytes <= 0)
02268 return TRUE;
02269
02270
02271 if (bytes > TOTAL_MOVE_REG*align)
02272 return FALSE;
02273
02274
02275 dest_reg = copy_addr_to_reg (XEXP (orig_dest, 0));
02276 src_reg = copy_addr_to_reg (XEXP (orig_src, 0));
02277
02278 num_reg = offset = 0;
02279 for ( ; bytes > 0; (bytes -= move_bytes), (offset += move_bytes))
02280 {
02281
02282 if (offset == 0)
02283 {
02284 src_addr = src_reg;
02285 dest_addr = dest_reg;
02286 }
02287 else
02288 {
02289 src_addr = plus_constant (src_reg, offset);
02290 dest_addr = plus_constant (dest_reg, offset);
02291 }
02292
02293
02294
02295 if (bytes >= 4 && align >= 4)
02296 mode = SImode;
02297 else if (bytes >= 2 && align >= 2)
02298 mode = HImode;
02299 else
02300 mode = QImode;
02301
02302 move_bytes = GET_MODE_SIZE (mode);
02303 tmp_reg = gen_reg_rtx (mode);
02304 src_mem = change_address (orig_src, mode, src_addr);
02305 dest_mem = change_address (orig_dest, mode, dest_addr);
02306 emit_insn (gen_rtx_SET (VOIDmode, tmp_reg, src_mem));
02307 stores[num_reg++] = gen_rtx_SET (VOIDmode, dest_mem, tmp_reg);
02308
02309 if (num_reg >= MAX_MOVE_REG)
02310 {
02311 for (i = 0; i < num_reg; i++)
02312 emit_insn (stores[i]);
02313 num_reg = 0;
02314 }
02315 }
02316
02317 for (i = 0; i < num_reg; i++)
02318 emit_insn (stores[i]);
02319
02320 return TRUE;
02321 }
02322
02323
02324
02325
02326
02327
02328
02329
02330
02331 int
02332 frv_expand_block_clear (rtx operands[])
02333 {
02334 rtx orig_dest = operands[0];
02335 rtx bytes_rtx = operands[1];
02336 rtx align_rtx = operands[3];
02337 int constp = (GET_CODE (bytes_rtx) == CONST_INT);
02338 int align;
02339 int bytes;
02340 int offset;
02341 int num_reg;
02342 rtx dest_reg;
02343 rtx dest_addr;
02344 rtx dest_mem;
02345 int clear_bytes;
02346 enum machine_mode mode;
02347
02348
02349 if (! constp)
02350 return FALSE;
02351
02352
02353 gcc_assert (GET_CODE (align_rtx) == CONST_INT);
02354
02355 align = INTVAL (align_rtx);
02356
02357
02358 bytes = INTVAL (bytes_rtx);
02359 if (bytes <= 0)
02360 return TRUE;
02361
02362
02363 if (bytes > TOTAL_MOVE_REG*align)
02364 return FALSE;
02365
02366
02367 dest_reg = copy_addr_to_reg (XEXP (orig_dest, 0));
02368
02369 num_reg = offset = 0;
02370 for ( ; bytes > 0; (bytes -= clear_bytes), (offset += clear_bytes))
02371 {
02372
02373 dest_addr = ((offset == 0)
02374 ? dest_reg
02375 : plus_constant (dest_reg, offset));
02376
02377
02378 if (bytes >= 4 && align >= 4)
02379 mode = SImode;
02380 else if (bytes >= 2 && align >= 2)
02381 mode = HImode;
02382 else
02383 mode = QImode;
02384
02385 clear_bytes = GET_MODE_SIZE (mode);
02386 dest_mem = change_address (orig_dest, mode, dest_addr);
02387 emit_insn (gen_rtx_SET (VOIDmode, dest_mem, const0_rtx));
02388 }
02389
02390 return TRUE;
02391 }
02392
02393
02394
02395
02396
02397 static rtx *frv_insn_operands;
02398
02399
02400
02401
02402 const char *
02403 frv_asm_output_opcode (FILE *f, const char *ptr)
02404 {
02405 int c;
02406
02407 if (frv_insn_packing_flag <= 0)
02408 return ptr;
02409
02410 for (; *ptr && *ptr != ' ' && *ptr != '\t';)
02411 {
02412 c = *ptr++;
02413 if (c == '%' && ((*ptr >= 'a' && *ptr <= 'z')
02414 || (*ptr >= 'A' && *ptr <= 'Z')))
02415 {
02416 int letter = *ptr++;
02417
02418 c = atoi (ptr);
02419 frv_print_operand (f, frv_insn_operands [c], letter);
02420 while ((c = *ptr) >= '0' && c <= '9')
02421 ptr++;
02422 }
02423 else
02424 fputc (c, f);
02425 }
02426
02427 fprintf (f, ".p");
02428
02429 return ptr;
02430 }
02431
02432
02433
02434
02435 void
02436 frv_final_prescan_insn (rtx insn, rtx *opvec,
02437 int noperands ATTRIBUTE_UNUSED)
02438 {
02439 if (INSN_P (insn))
02440 {
02441 if (frv_insn_packing_flag >= 0)
02442 {
02443 frv_insn_operands = opvec;
02444 frv_insn_packing_flag = PACKING_FLAG_P (insn);
02445 }
02446 else if (recog_memoized (insn) >= 0
02447 && get_attr_acc_group (insn) == ACC_GROUP_ODD)
02448
02449
02450 fprintf (asm_out_file, "\tmnop.p\n");
02451 }
02452 }
02453
02454
02455
02456
02457
02458
02459
02460
02461
02462
02463
02464
02465 rtx
02466 frv_dynamic_chain_address (rtx frame)
02467 {
02468 cfun->machine->frame_needed = 1;
02469 return frame;
02470 }
02471
02472
02473
02474
02475
02476
02477
02478
02479
02480
02481
02482
02483 rtx
02484 frv_return_addr_rtx (int count, rtx frame)
02485 {
02486 if (count != 0)
02487 return const0_rtx;
02488 cfun->machine->frame_needed = 1;
02489 return gen_rtx_MEM (Pmode, plus_constant (frame, 8));
02490 }
02491
02492
02493
02494
02495
02496
02497
02498
02499
02500 rtx
02501 frv_index_memory (rtx memref, enum machine_mode mode, int index)
02502 {
02503 rtx base = XEXP (memref, 0);
02504 if (GET_CODE (base) == PRE_MODIFY)
02505 base = XEXP (base, 0);
02506 return change_address (memref, mode,
02507 plus_constant (base, index * GET_MODE_SIZE (mode)));
02508 }
02509
02510
02511
02512 void
02513 frv_print_operand_address (FILE * stream, rtx x)
02514 {
02515 if (GET_CODE (x) == MEM)
02516 x = XEXP (x, 0);
02517
02518 switch (GET_CODE (x))
02519 {
02520 case REG:
02521 fputs (reg_names [ REGNO (x)], stream);
02522 return;
02523
02524 case CONST_INT:
02525 fprintf (stream, "%ld", (long) INTVAL (x));
02526 return;
02527
02528 case SYMBOL_REF:
02529 assemble_name (stream, XSTR (x, 0));
02530 return;
02531
02532 case LABEL_REF:
02533 case CONST:
02534 output_addr_const (stream, x);
02535 return;
02536
02537 default:
02538 break;
02539 }
02540
02541 fatal_insn ("bad insn to frv_print_operand_address:", x);
02542 }
02543
02544
02545 static void
02546 frv_print_operand_memory_reference_reg (FILE * stream, rtx x)
02547 {
02548 int regno = true_regnum (x);
02549 if (GPR_P (regno))
02550 fputs (reg_names[regno], stream);
02551 else
02552 fatal_insn ("bad register to frv_print_operand_memory_reference_reg:", x);
02553 }
02554
02555
02556
02557 static void
02558 frv_print_operand_memory_reference (FILE * stream, rtx x, int addr_offset)
02559 {
02560 struct frv_unspec unspec;
02561 rtx x0 = NULL_RTX;
02562 rtx x1 = NULL_RTX;
02563
02564 switch (GET_CODE (x))
02565 {
02566 case SUBREG:
02567 case REG:
02568 x0 = x;
02569 break;
02570
02571 case PRE_MODIFY:
02572 x0 = XEXP (x, 0);
02573 x1 = XEXP (XEXP (x, 1), 1);
02574 break;
02575
02576 case CONST_INT:
02577 x1 = x;
02578 break;
02579
02580 case PLUS:
02581 x0 = XEXP (x, 0);
02582 x1 = XEXP (x, 1);
02583 if (GET_CODE (x0) == CONST_INT)
02584 {
02585 x0 = XEXP (x, 1);
02586 x1 = XEXP (x, 0);
02587 }
02588 break;
02589
02590 default:
02591 fatal_insn ("bad insn to frv_print_operand_memory_reference:", x);
02592 break;
02593
02594 }
02595
02596 if (addr_offset)
02597 {
02598 if (!x1)
02599 x1 = const0_rtx;
02600 else if (GET_CODE (x1) != CONST_INT)
02601 fatal_insn ("bad insn to frv_print_operand_memory_reference:", x);
02602 }
02603
02604 fputs ("@(", stream);
02605 if (!x0)
02606 fputs (reg_names[GPR_R0], stream);
02607 else if (GET_CODE (x0) == REG || GET_CODE (x0) == SUBREG)
02608 frv_print_operand_memory_reference_reg (stream, x0);
02609 else
02610 fatal_insn ("bad insn to frv_print_operand_memory_reference:", x);
02611
02612 fputs (",", stream);
02613 if (!x1)
02614 fputs (reg_names [GPR_R0], stream);
02615
02616 else
02617 {
02618 switch (GET_CODE (x1))
02619 {
02620 case SUBREG:
02621 case REG:
02622 frv_print_operand_memory_reference_reg (stream, x1);
02623 break;
02624
02625 case CONST_INT:
02626 fprintf (stream, "%ld", (long) (INTVAL (x1) + addr_offset));
02627 break;
02628
02629 case CONST:
02630 if (!frv_const_unspec_p (x1, &unspec))
02631 fatal_insn ("bad insn to frv_print_operand_memory_reference:", x1);
02632 frv_output_const_unspec (stream, &unspec);
02633 break;
02634
02635 default:
02636 fatal_insn ("bad insn to frv_print_operand_memory_reference:", x);
02637 }
02638 }
02639
02640 fputs (")", stream);
02641 }
02642
02643
02644
02645
02646 #define FRV_JUMP_LIKELY 2
02647 #define FRV_JUMP_NOT_LIKELY 0
02648
02649 static int
02650 frv_print_operand_jump_hint (rtx insn)
02651 {
02652 rtx note;
02653 rtx labelref;
02654 int ret;
02655 HOST_WIDE_INT prob = -1;
02656 enum { UNKNOWN, BACKWARD, FORWARD } jump_type = UNKNOWN;
02657
02658 gcc_assert (GET_CODE (insn) == JUMP_INSN);
02659
02660
02661 if (! any_condjump_p (insn))
02662 ret = FRV_JUMP_LIKELY;
02663
02664 else
02665 {
02666 labelref = condjump_label (insn);
02667 if (labelref)
02668 {
02669 rtx label = XEXP (labelref, 0);
02670 jump_type = (insn_current_address > INSN_ADDRESSES (INSN_UID (label))
02671 ? BACKWARD
02672 : FORWARD);
02673 }
02674
02675 note = find_reg_note (insn, REG_BR_PROB, 0);
02676 if (!note)
02677 ret = ((jump_type == BACKWARD) ? FRV_JUMP_LIKELY : FRV_JUMP_NOT_LIKELY);
02678
02679 else
02680 {
02681 prob = INTVAL (XEXP (note, 0));
02682 ret = ((prob >= (REG_BR_PROB_BASE / 2))
02683 ? FRV_JUMP_LIKELY
02684 : FRV_JUMP_NOT_LIKELY);
02685 }
02686 }
02687
02688 #if 0
02689 if (TARGET_DEBUG)
02690 {
02691 char *direction;
02692
02693 switch (jump_type)
02694 {
02695 default:
02696 case UNKNOWN: direction = "unknown jump direction"; break;
02697 case BACKWARD: direction = "jump backward"; break;
02698 case FORWARD: direction = "jump forward"; break;
02699 }
02700
02701 fprintf (stderr,
02702 "%s: uid %ld, %s, probability = %ld, max prob. = %ld, hint = %d\n",
02703 IDENTIFIER_POINTER (DECL_NAME (current_function_decl)),
02704 (long)INSN_UID (insn), direction, (long)prob,
02705 (long)REG_BR_PROB_BASE, ret);
02706 }
02707 #endif
02708
02709 return ret;
02710 }
02711
02712
02713
02714
02715
02716 static const char *
02717 comparison_string (enum rtx_code code, rtx op0)
02718 {
02719 bool is_nz_p = GET_MODE (op0) == CC_NZmode;
02720 switch (code)
02721 {
02722 default: output_operand_lossage ("bad condition code");
02723 case EQ: return "eq";
02724 case NE: return "ne";
02725 case LT: return is_nz_p ? "n" : "lt";
02726 case LE: return "le";
02727 case GT: return "gt";
02728 case GE: return is_nz_p ? "p" : "ge";
02729 case LTU: return is_nz_p ? "no" : "c";
02730 case LEU: return is_nz_p ? "eq" : "ls";
02731 case GTU: return is_nz_p ? "ne" : "hi";
02732 case GEU: return is_nz_p ? "ra" : "nc";
02733 }
02734 }
02735
02736
02737
02738
02739
02740
02741
02742
02743
02744
02745
02746
02747
02748
02749
02750
02751
02752
02753
02754
02755
02756
02757
02758
02759
02760
02761
02762
02763
02764
02765
02766
02767
02768 void
02769 frv_print_operand (FILE * file, rtx x, int code)
02770 {
02771 struct frv_unspec unspec;
02772 HOST_WIDE_INT value;
02773 int offset;
02774
02775 if (code != 0 && !isalpha (code))
02776 value = 0;
02777
02778 else if (GET_CODE (x) == CONST_INT)
02779 value = INTVAL (x);
02780
02781 else if (GET_CODE (x) == CONST_DOUBLE)
02782 {
02783 if (GET_MODE (x) == SFmode)
02784 {
02785 REAL_VALUE_TYPE rv;
02786 long l;
02787
02788 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
02789 REAL_VALUE_TO_TARGET_SINGLE (rv, l);
02790 value = l;
02791 }
02792
02793 else if (GET_MODE (x) == VOIDmode)
02794 value = CONST_DOUBLE_LOW (x);
02795
02796 else
02797 fatal_insn ("bad insn in frv_print_operand, bad const_double", x);
02798 }
02799
02800 else
02801 value = 0;
02802
02803 switch (code)
02804 {
02805
02806 case '.':
02807
02808 fputs (reg_names[GPR_R0], file);
02809 break;
02810
02811 case '#':
02812 fprintf (file, "%d", frv_print_operand_jump_hint (current_output_insn));
02813 break;
02814
02815 case '@':
02816
02817 fputs (reg_names[SDA_BASE_REG], file);
02818 break;
02819
02820 case '~':
02821
02822 fputs (reg_names[PIC_REGNO], file);
02823 break;
02824
02825 case '*':
02826
02827 fputs (reg_names[ICR_TEMP], file);
02828 break;
02829
02830 case '&':
02831
02832 fputs (reg_names[ICC_TEMP], file);
02833 break;
02834
02835
02836
02837 case 'C':
02838
02839 fputs (comparison_string (reverse_condition (GET_CODE (x)),
02840 XEXP (x, 0)), file);
02841 break;
02842
02843 case 'c':
02844
02845 fputs (comparison_string (GET_CODE (x), XEXP (x, 0)), file);
02846 break;
02847
02848 case 'e':
02849
02850
02851 if (GET_CODE (x) == NE)
02852 fputs ("1", file);
02853
02854 else if (GET_CODE (x) == EQ)
02855 fputs ("0", file);
02856
02857 else
02858 fatal_insn ("bad insn to frv_print_operand, 'e' modifier:", x);
02859 break;
02860
02861 case 'F':
02862
02863 switch (GET_CODE (x))
02864 {
02865 default:
02866 fatal_insn ("bad insn to frv_print_operand, 'F' modifier:", x);
02867
02868 case EQ: fputs ("ne", file); break;
02869 case NE: fputs ("eq", file); break;
02870 case LT: fputs ("uge", file); break;
02871 case LE: fputs ("ug", file); break;
02872 case GT: fputs ("ule", file); break;
02873 case GE: fputs ("ul", file); break;
02874 }
02875 break;
02876
02877 case 'f':
02878
02879 switch (GET_CODE (x))
02880 {
02881 default:
02882 fatal_insn ("bad insn to frv_print_operand, 'f' modifier:", x);
02883
02884 case EQ: fputs ("eq", file); break;
02885 case NE: fputs ("ne", file); break;
02886 case LT: fputs ("lt", file); break;
02887 case LE: fputs ("le", file); break;
02888 case GT: fputs ("gt", file); break;
02889 case GE: fputs ("ge", file); break;
02890 }
02891 break;
02892
02893 case 'g':
02894
02895 if (GET_CODE (x) != CONST_INT)
02896 fatal_insn ("bad insn to frv_print_operand, 'g' modifier:", x);
02897 fputs (unspec_got_name (INTVAL (x)), file);
02898 break;
02899
02900 case 'I':
02901
02902
02903 if (GET_CODE (x) == MEM)
02904 x = ((GET_CODE (XEXP (x, 0)) == PLUS)
02905 ? XEXP (XEXP (x, 0), 1)
02906 : XEXP (x, 0));
02907 else if (GET_CODE (x) == PLUS)
02908 x = XEXP (x, 1);
02909
02910 switch (GET_CODE (x))
02911 {
02912 default:
02913 break;
02914
02915 case CONST_INT:
02916 case SYMBOL_REF:
02917 case CONST:
02918 fputs ("i", file);
02919 break;
02920 }
02921 break;
02922
02923 case 'i':
02924
02925
02926 if (GET_CODE (x) == CONST_INT)
02927 fputs ("i", file);
02928
02929 else
02930 {
02931 if (GET_CODE (x) == CONST_INT
02932 || (GET_CODE (x) == PLUS
02933 && (GET_CODE (XEXP (x, 1)) == CONST_INT
02934 || GET_CODE (XEXP (x, 0)) == CONST_INT)))
02935 fputs ("i", file);
02936 }
02937 break;
02938
02939 case 'L':
02940
02941 if (GET_CODE (x) == REG)
02942 fputs (reg_names[ REGNO (x)+1 ], file);
02943 else
02944 fatal_insn ("bad insn to frv_print_operand, 'L' modifier:", x);
02945 break;
02946
02947
02948
02949 case 'M':
02950 case 'N':
02951
02952
02953 offset = (code == 'M') ? 0 : UNITS_PER_WORD;
02954 switch (GET_CODE (x))
02955 {
02956 default:
02957 fatal_insn ("bad insn to frv_print_operand, 'M/N' modifier:", x);
02958
02959 case MEM:
02960 frv_print_operand_memory_reference (file, XEXP (x, 0), offset);
02961 break;
02962
02963 case REG:
02964 case SUBREG:
02965 case CONST_INT:
02966 case PLUS:
02967 case SYMBOL_REF:
02968 frv_print_operand_memory_reference (file, x, offset);
02969 break;
02970 }
02971 break;
02972
02973 case 'O':
02974
02975 switch (GET_CODE (x))
02976 {
02977 default:
02978 fatal_insn ("bad insn to frv_print_operand, 'O' modifier:", x);
02979
02980 case PLUS: fputs ("add", file); break;
02981 case MINUS: fputs ("sub", file); break;
02982 case AND: fputs ("and", file); break;
02983 case IOR: fputs ("or", file); break;
02984 case XOR: fputs ("xor", file); break;
02985 case ASHIFT: fputs ("sll", file); break;
02986 case ASHIFTRT: fputs ("sra", file); break;
02987 case LSHIFTRT: fputs ("srl", file); break;
02988 }
02989 break;
02990
02991
02992
02993 case 'P':
02994
02995 if (GET_CODE (x) != CONST_INT)
02996 fatal_insn ("bad insn to frv_print_operand, P modifier:", x);
02997
02998 fprintf (file, ".LCF%ld", (long)INTVAL (x));
02999 break;
03000
03001 case 'U':
03002
03003 if (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == PRE_MODIFY)
03004 fputs ("u", file);
03005 break;
03006
03007 case 'z':
03008
03009 if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0)
03010 fputs (reg_names[GPR_R0], file);
03011
03012 else if (GET_CODE (x) == REG)
03013 fputs (reg_names [REGNO (x)], file);
03014
03015 else
03016 fatal_insn ("bad insn in frv_print_operand, z case", x);
03017 break;
03018
03019 case 'x':
03020
03021 if (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)
03022 {
03023 fprintf (file, "%s0x%.4lx", IMMEDIATE_PREFIX, (long) value);
03024 break;
03025 }
03026
03027
03028
03029 case '\0':
03030 if (GET_CODE (x) == REG)
03031 fputs (reg_names [REGNO (x)], file);
03032
03033 else if (GET_CODE (x) == CONST_INT
03034 || GET_CODE (x) == CONST_DOUBLE)
03035 fprintf (file, "%s%ld", IMMEDIATE_PREFIX, (long) value);
03036
03037 else if (frv_const_unspec_p (x, &unspec))
03038 frv_output_const_unspec (file, &unspec);
03039
03040 else if (GET_CODE (x) == MEM)
03041 frv_print_operand_address (file, XEXP (x, 0));
03042
03043 else if (CONSTANT_ADDRESS_P (x))
03044 frv_print_operand_address (file, x);
03045
03046 else
03047 fatal_insn ("bad insn in frv_print_operand, 0 case", x);
03048
03049 break;
03050
03051 default:
03052 fatal_insn ("frv_print_operand: unknown code", x);
03053 break;
03054 }
03055
03056 return;
03057 }
03058
03059
03060
03061
03062
03063
03064
03065
03066
03067
03068
03069
03070
03071
03072
03073
03074
03075
03076 void
03077 frv_init_cumulative_args (CUMULATIVE_ARGS *cum,
03078 tree fntype,
03079 rtx libname,
03080 tree fndecl,
03081 int incoming)
03082 {
03083 *cum = FIRST_ARG_REGNUM;
03084
03085 if (TARGET_DEBUG_ARG)
03086 {
03087 fprintf (stderr, "\ninit_cumulative_args:");
03088 if (!fndecl && fntype)
03089 fputs (" indirect", stderr);
03090
03091 if (incoming)
03092 fputs (" incoming", stderr);
03093
03094 if (fntype)
03095 {
03096 tree ret_type = TREE_TYPE (fntype);
03097 fprintf (stderr, " return=%s,",
03098 tree_code_name[ (int)TREE_CODE (ret_type) ]);
03099 }
03100
03101 if (libname && GET_CODE (libname) == SYMBOL_REF)
03102 fprintf (stderr, " libname=%s", XSTR (libname, 0));
03103
03104 if (cfun->returns_struct)
03105 fprintf (stderr, " return-struct");
03106
03107 putc ('\n', stderr);
03108 }
03109 }
03110
03111
03112
03113
03114
03115 static bool
03116 frv_must_pass_in_stack (enum machine_mode mode, tree type)
03117 {
03118 if (mode == BLKmode)
03119 return true;
03120 if (type == NULL)
03121 return false;
03122 return AGGREGATE_TYPE_P (type);
03123 }
03124
03125
03126
03127
03128
03129 int
03130 frv_function_arg_boundary (enum machine_mode mode ATTRIBUTE_UNUSED,
03131 tree type ATTRIBUTE_UNUSED)
03132 {
03133 return BITS_PER_WORD;
03134 }
03135
03136 rtx
03137 frv_function_arg (CUMULATIVE_ARGS *cum,
03138 enum machine_mode mode,
03139 tree type ATTRIBUTE_UNUSED,
03140 int named,
03141 int incoming ATTRIBUTE_UNUSED)
03142 {
03143 enum machine_mode xmode = (mode == BLKmode) ? SImode : mode;
03144 int arg_num = *cum;
03145 rtx ret;
03146 const char *debstr;
03147
03148
03149 if (xmode == VOIDmode)
03150 {
03151 ret = const0_rtx;
03152 debstr = "<0>";
03153 }
03154
03155 else if (arg_num <= LAST_ARG_REGNUM)
03156 {
03157 ret = gen_rtx_REG (xmode, arg_num);
03158 debstr = reg_names[arg_num];
03159 }
03160
03161 else
03162 {
03163 ret = NULL_RTX;
03164 debstr = "memory";
03165 }
03166
03167 if (TARGET_DEBUG_ARG)
03168 fprintf (stderr,
03169 "function_arg: words = %2d, mode = %4s, named = %d, size = %3d, arg = %s\n",
03170 arg_num, GET_MODE_NAME (mode), named, GET_MODE_SIZE (mode), debstr);
03171
03172 return ret;
03173 }
03174
03175
03176
03177
03178
03179
03180
03181
03182
03183
03184
03185 void
03186 frv_function_arg_advance (CUMULATIVE_ARGS *cum,
03187 enum machine_mode mode,
03188 tree type ATTRIBUTE_UNUSED,
03189 int named)
03190 {
03191 enum machine_mode xmode = (mode == BLKmode) ? SImode : mode;
03192 int bytes = GET_MODE_SIZE (xmode);
03193 int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
03194 int arg_num = *cum;
03195
03196 *cum = arg_num + words;
03197
03198 if (TARGET_DEBUG_ARG)
03199 fprintf (stderr,
03200 "function_adv: words = %2d, mode = %4s, named = %d, size = %3d\n",
03201 arg_num, GET_MODE_NAME (mode), named, words * UNITS_PER_WORD);
03202 }
03203
03204
03205
03206
03207
03208
03209
03210
03211
03212
03213
03214
03215
03216
03217
03218
03219
03220
03221 static int
03222 frv_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
03223 tree type ATTRIBUTE_UNUSED, bool named ATTRIBUTE_UNUSED)
03224 {
03225 enum machine_mode xmode = (mode == BLKmode) ? SImode : mode;
03226 int bytes = GET_MODE_SIZE (xmode);
03227 int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
03228 int arg_num = *cum;
03229 int ret;
03230
03231 ret = ((arg_num <= LAST_ARG_REGNUM && arg_num + words > LAST_ARG_REGNUM+1)
03232 ? LAST_ARG_REGNUM - arg_num + 1
03233 : 0);
03234 ret *= UNITS_PER_WORD;
03235
03236 if (TARGET_DEBUG_ARG && ret)
03237 fprintf (stderr, "frv_arg_partial_bytes: %d\n", ret);
03238
03239 return ret;
03240 }
03241
03242
03243
03244
03245 static FRV_INLINE int
03246 frv_regno_ok_for_base_p (int regno, int strict_p)
03247 {
03248 if (GPR_P (regno))
03249 return TRUE;
03250
03251 if (strict_p)
03252 return (reg_renumber[regno] >= 0 && GPR_P (reg_renumber[regno]));
03253
03254 if (regno == ARG_POINTER_REGNUM)
03255 return TRUE;
03256
03257 return (regno >= FIRST_PSEUDO_REGISTER);
03258 }
03259
03260
03261
03262
03263
03264
03265
03266
03267
03268
03269
03270
03271
03272
03273
03274
03275
03276
03277
03278
03279
03280
03281
03282
03283
03284
03285
03286
03287
03288
03289
03290
03291
03292
03293
03294
03295
03296
03297
03298
03299
03300
03301
03302
03303
03304
03305
03306
03307
03308
03309
03310
03311
03312
03313
03314
03315
03316
03317 int
03318 frv_legitimate_address_p (enum machine_mode mode,
03319 rtx x,
03320 int strict_p,
03321 int condexec_p,
03322 int allow_double_reg_p)
03323 {
03324 rtx x0, x1;
03325 int ret = 0;
03326 HOST_WIDE_INT value;
03327 unsigned regno0;
03328
03329 if (FRV_SYMBOL_REF_TLS_P (x))
03330 return 0;
03331
03332 switch (GET_CODE (x))
03333 {
03334 default:
03335 break;
03336
03337 case SUBREG:
03338 x = SUBREG_REG (x);
03339 if (GET_CODE (x) != REG)
03340 break;
03341
03342
03343
03344 case REG:
03345 ret = frv_regno_ok_for_base_p (REGNO (x), strict_p);
03346 break;
03347
03348 case PRE_MODIFY:
03349 x0 = XEXP (x, 0);
03350 x1 = XEXP (x, 1);
03351 if (GET_CODE (x0) != REG
03352 || ! frv_regno_ok_for_base_p (REGNO (x0), strict_p)
03353 || GET_CODE (x1) != PLUS
03354 || ! rtx_equal_p (x0, XEXP (x1, 0))
03355 || GET_CODE (XEXP (x1, 1)) != REG
03356 || ! frv_regno_ok_for_base_p (REGNO (XEXP (x1, 1)), strict_p))
03357 break;
03358
03359 ret = 1;
03360 break;
03361
03362 case CONST_INT:
03363
03364 if (condexec_p)
03365 ret = FALSE;
03366 else
03367 {
03368 ret = IN_RANGE_P (INTVAL (x), -2048, 2047);
03369
03370
03371
03372 if (ret && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
03373 ret = IN_RANGE_P (INTVAL (x) + GET_MODE_SIZE (mode) - 1,
03374 -2048, 2047);
03375 }
03376 break;
03377
03378 case PLUS:
03379 x0 = XEXP (x, 0);
03380 x1 = XEXP (x, 1);
03381
03382 if (GET_CODE (x0) == SUBREG)
03383 x0 = SUBREG_REG (x0);
03384
03385 if (GET_CODE (x0) != REG)
03386 break;
03387
03388 regno0 = REGNO (x0);
03389 if (!frv_regno_ok_for_base_p (regno0, strict_p))
03390 break;
03391
03392 switch (GET_CODE (x1))
03393 {
03394 default:
03395 break;
03396
03397 case SUBREG:
03398 x1 = SUBREG_REG (x1);
03399 if (GET_CODE (x1) != REG)
03400 break;
03401
03402
03403
03404 case REG:
03405
03406
03407 if (!allow_double_reg_p && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
03408 ret = FALSE;
03409 else
03410 ret = frv_regno_ok_for_base_p (REGNO (x1), strict_p);
03411 break;
03412
03413 case CONST_INT:
03414
03415 if (condexec_p)
03416 ret = FALSE;
03417 else
03418 {
03419 value = INTVAL (x1);
03420 ret = IN_RANGE_P (value, -2048, 2047);
03421
03422
03423
03424 if (ret && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
03425 ret = IN_RANGE_P (value + GET_MODE_SIZE (mode) - 1, -2048, 2047);
03426 }
03427 break;
03428
03429 case CONST:
03430 if (!condexec_p && got12_operand (x1, VOIDmode))
03431 ret = TRUE;
03432 break;
03433
03434 }
03435 break;
03436 }
03437
03438 if (TARGET_DEBUG_ADDR)
03439 {
03440 fprintf (stderr, "\n========== GO_IF_LEGITIMATE_ADDRESS, mode = %s, result = %d, addresses are %sstrict%s\n",
03441 GET_MODE_NAME (mode), ret, (strict_p) ? "" : "not ",
03442 (condexec_p) ? ", inside conditional code" : "");
03443 debug_rtx (x);
03444 }
03445
03446 return ret;
03447 }
03448
03449
03450 static rtx
03451 gen_inlined_tls_plt (rtx addr)
03452 {
03453 rtx retval, dest;
03454 rtx picreg = get_hard_reg_initial_val (Pmode, FDPIC_REG);
03455
03456
03457 dest = gen_reg_rtx (DImode);
03458
03459 if (flag_pic == 1)
03460 {
03461
03462
03463
03464
03465
03466
03467 emit_insn (gen_tls_lddi (dest, addr, picreg));
03468 }
03469 else
03470 {
03471
03472
03473
03474
03475
03476
03477
03478
03479 rtx reguse = gen_reg_rtx (Pmode);
03480 emit_insn (gen_tlsoff_hilo (reguse, addr, GEN_INT (R_FRV_GOTTLSDESCHI)));
03481 emit_insn (gen_tls_tlsdesc_ldd (dest, picreg, reguse, addr));
03482 }
03483
03484 retval = gen_reg_rtx (Pmode);
03485 emit_insn (gen_tls_indirect_call (retval, addr, dest, picreg));
03486 return retval;
03487 }
03488
03489
03490
03491 static rtx
03492 gen_tlsmoff (rtx addr, rtx reg)
03493 {
03494 rtx dest = gen_reg_rtx (Pmode);
03495
03496 if (TARGET_BIG_TLS)
03497 {
03498
03499
03500
03501 dest = gen_reg_rtx (Pmode);
03502 emit_insn (gen_tlsoff_hilo (dest, addr,
03503 GEN_INT (R_FRV_TLSMOFFHI)));
03504 dest = gen_rtx_PLUS (Pmode, dest, reg);
03505 }
03506 else
03507 {
03508
03509
03510
03511
03512 dest = gen_reg_rtx (Pmode);
03513 emit_insn (gen_symGOTOFF2reg_i (dest, addr, reg,
03514 GEN_INT (R_FRV_TLSMOFF12)));
03515 }
03516 return dest;
03517 }
03518
03519
03520 static rtx
03521 frv_legitimize_tls_address (rtx addr, enum tls_model model)
03522 {
03523 rtx dest, tp = gen_rtx_REG (Pmode, 29);
03524 rtx picreg = get_hard_reg_initial_val (Pmode, 15);
03525
03526 switch (model)
03527 {
03528 case TLS_MODEL_INITIAL_EXEC:
03529 if (flag_pic == 1)
03530 {
03531
03532
03533
03534 dest = gen_reg_rtx (Pmode);
03535 emit_insn (gen_tls_load_gottlsoff12 (dest, addr, picreg));
03536 dest = gen_rtx_PLUS (Pmode, tp, dest);
03537 }
03538 else
03539 {
03540
03541
03542
03543
03544
03545
03546 rtx tmp = gen_reg_rtx (Pmode);
03547 dest = gen_reg_rtx (Pmode);
03548 emit_insn (gen_tlsoff_hilo (tmp, addr,
03549 GEN_INT (R_FRV_GOTTLSOFF_HI)));
03550
03551 emit_insn (gen_tls_tlsoff_ld (dest, picreg, tmp, addr));
03552 dest = gen_rtx_PLUS (Pmode, tp, dest);
03553 }
03554 break;
03555 case TLS_MODEL_LOCAL_DYNAMIC:
03556 {
03557 rtx reg, retval;
03558
03559 if (TARGET_INLINE_PLT)
03560 retval = gen_inlined_tls_plt (GEN_INT (0));
03561 else
03562 {
03563
03564 retval = gen_reg_rtx (Pmode);
03565 emit_insn (gen_call_gettlsoff (retval, GEN_INT (0), picreg));
03566 }
03567
03568 reg = gen_reg_rtx (Pmode);
03569 emit_insn (gen_rtx_SET (VOIDmode, reg,
03570 gen_rtx_PLUS (Pmode,
03571 retval, tp)));
03572
03573 dest = gen_tlsmoff (addr, reg);
03574
03575
03576
03577
03578
03579
03580
03581 break;
03582 }
03583 case TLS_MODEL_LOCAL_EXEC:
03584 dest = gen_tlsmoff (addr, gen_rtx_REG (Pmode, 29));
03585 break;
03586 case TLS_MODEL_GLOBAL_DYNAMIC:
03587 {
03588 rtx retval;
03589
03590 if (TARGET_INLINE_PLT)
03591 retval = gen_inlined_tls_plt (addr);
03592 else
03593 {
03594
03595 retval = gen_reg_rtx (Pmode);
03596 emit_insn (gen_call_gettlsoff (retval, addr, picreg));
03597 }
03598 dest = gen_rtx_PLUS (Pmode, retval, tp);
03599 break;
03600 }
03601 default:
03602 gcc_unreachable ();
03603 }
03604
03605 return dest;
03606 }
03607
03608 rtx
03609 frv_legitimize_address (rtx x,
03610 rtx oldx ATTRIBUTE_UNUSED,
03611 enum machine_mode mode ATTRIBUTE_UNUSED)
03612 {
03613 if (GET_CODE (x) == SYMBOL_REF)
03614 {
03615 enum tls_model model = SYMBOL_REF_TLS_MODEL (x);
03616 if (model != 0)
03617 return frv_legitimize_tls_address (x, model);
03618 }
03619
03620 return NULL_RTX;
03621 }
03622
03623
03624
03625
03626
03627 static bool
03628 frv_local_funcdesc_p (rtx fnx)
03629 {
03630 tree fn;
03631 enum symbol_visibility vis;
03632 bool ret;
03633
03634 if (! SYMBOL_REF_LOCAL_P (fnx))
03635 return FALSE;
03636
03637 fn = SYMBOL_REF_DECL (fnx);
03638
03639 if (! fn)
03640 return FALSE;
03641
03642 vis = DECL_VISIBILITY (fn);
03643
03644 if (vis == VISIBILITY_PROTECTED)
03645
03646
03647 vis = VISIBILITY_DEFAULT;
03648 else if (flag_shlib)
03649
03650
03651
03652 return TRUE;
03653
03654 ret = default_binds_local_p_1 (fn, flag_pic);
03655
03656 DECL_VISIBILITY (fn) = vis;
03657
03658 return ret;
03659 }
03660
03661
03662
03663
03664 rtx
03665 frv_gen_GPsym2reg (rtx dest, rtx src)
03666 {
03667 tree gp = get_identifier ("_gp");
03668 rtx gp_sym = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (gp));
03669
03670 return gen_symGOT2reg (dest, gp_sym, src, GEN_INT (R_FRV_GOT12));
03671 }
03672
03673 static const char *
03674 unspec_got_name (int i)
03675 {
03676 switch (i)
03677 {
03678 case R_FRV_GOT12: return "got12";
03679 case R_FRV_GOTHI: return "gothi";
03680 case R_FRV_GOTLO: return "gotlo";
03681 case R_FRV_FUNCDESC: return "funcdesc";
03682 case R_FRV_FUNCDESC_GOT12: return "gotfuncdesc12";
03683 case R_FRV_FUNCDESC_GOTHI: return "gotfuncdeschi";
03684 case R_FRV_FUNCDESC_GOTLO: return "gotfuncdesclo";
03685 case R_FRV_FUNCDESC_VALUE: return "funcdescvalue";
03686 case R_FRV_FUNCDESC_GOTOFF12: return "gotofffuncdesc12";
03687 case R_FRV_FUNCDESC_GOTOFFHI: return "gotofffuncdeschi";
03688 case R_FRV_FUNCDESC_GOTOFFLO: return "gotofffuncdesclo";
03689 case R_FRV_GOTOFF12: return "gotoff12";
03690 case R_FRV_GOTOFFHI: return "gotoffhi";
03691 case R_FRV_GOTOFFLO: return "gotofflo";
03692 case R_FRV_GPREL12: return "gprel12";
03693 case R_FRV_GPRELHI: return "gprelhi";
03694 case R_FRV_GPRELLO: return "gprello";
03695 case R_FRV_GOTTLSOFF_HI: return "gottlsoffhi";
03696 case R_FRV_GOTTLSOFF_LO: return "gottlsofflo";
03697 case R_FRV_TLSMOFFHI: return "tlsmoffhi";
03698 case R_FRV_TLSMOFFLO: return "tlsmofflo";
03699 case R_FRV_TLSMOFF12: return "tlsmoff12";
03700 case R_FRV_TLSDESCHI: return "tlsdeschi";
03701 case R_FRV_TLSDESCLO: return "tlsdesclo";
03702 case R_FRV_GOTTLSDESCHI: return "gottlsdeschi";
03703 case R_FRV_GOTTLSDESCLO: return "gottlsdesclo";
03704 default: gcc_unreachable ();
03705 }
03706 }
03707
03708
03709
03710
03711 static void
03712 frv_output_const_unspec (FILE *stream, const struct frv_unspec *unspec)
03713 {
03714 fprintf (stream, "#%s(", unspec_got_name (unspec->reloc));
03715 output_addr_const (stream, plus_constant (unspec->symbol, unspec->offset));
03716 fputs (")", stream);
03717 }
03718
03719
03720
03721
03722
03723 rtx
03724 frv_find_base_term (rtx x)
03725 {
03726 struct frv_unspec unspec;
03727
03728 if (frv_const_unspec_p (x, &unspec)
03729 && frv_small_data_reloc_p (unspec.symbol, unspec.reloc))
03730 return plus_constant (unspec.symbol, unspec.offset);
03731
03732 return x;
03733 }
03734
03735
03736
03737
03738 int
03739 frv_legitimate_memory_operand (rtx op, enum machine_mode mode, int condexec_p)
03740 {
03741 return ((GET_MODE (op) == mode || mode == VOIDmode)
03742 && GET_CODE (op) == MEM
03743 && frv_legitimate_address_p (mode, XEXP (op, 0),
03744 reload_completed, condexec_p, FALSE));
03745 }
03746
03747 void
03748 frv_expand_fdpic_call (rtx *operands, bool ret_value, bool sibcall)
03749 {
03750 rtx lr = gen_rtx_REG (Pmode, LR_REGNO);
03751 rtx picreg = get_hard_reg_initial_val (SImode, FDPIC_REG);
03752 rtx c, rvrtx=0;
03753 rtx addr;
03754
03755 if (ret_value)
03756 {
03757 rvrtx = operands[0];
03758 operands ++;
03759 }
03760
03761 addr = XEXP (operands[0], 0);
03762
03763
03764
03765
03766
03767
03768
03769
03770
03771
03772
03773
03774
03775
03776
03777
03778
03779
03780
03781
03782
03783
03784 if (GET_CODE (addr) == SYMBOL_REF
03785 && ((!SYMBOL_REF_LOCAL_P (addr) && TARGET_INLINE_PLT)
03786 || sibcall))
03787 {
03788 rtx x, dest;
03789 dest = gen_reg_rtx (SImode);
03790 if (flag_pic != 1)
03791 x = gen_symGOTOFF2reg_hilo (dest, addr, OUR_FDPIC_REG,
03792 GEN_INT (R_FRV_FUNCDESC_GOTOFF12));
03793 else
03794 x = gen_symGOTOFF2reg (dest, addr, OUR_FDPIC_REG,
03795 GEN_INT (R_FRV_FUNCDESC_GOTOFF12));
03796 emit_insn (x);
03797 cfun->uses_pic_offset_table = TRUE;
03798 addr = dest;
03799 }
03800 else if (GET_CODE (addr) == SYMBOL_REF)
03801 {
03802
03803
03804 if (ret_value)
03805 c = gen_call_value_fdpicsi (rvrtx, addr, operands[1],
03806 operands[2], picreg, lr);
03807 else
03808 c = gen_call_fdpicsi (addr, operands[1], operands[2], picreg, lr);
03809 emit_call_insn (c);
03810 return;
03811 }
03812 else if (! ldd_address_operand (addr, Pmode))
03813 addr = force_reg (Pmode, addr);
03814
03815 picreg = gen_reg_rtx (DImode);
03816 emit_insn (gen_movdi_ldd (picreg, addr));
03817
03818 if (sibcall && ret_value)
03819 c = gen_sibcall_value_fdpicdi (rvrtx, picreg, const0_rtx);
03820 else if (sibcall)
03821 c = gen_sibcall_fdpicdi (picreg, const0_rtx);
03822 else if (ret_value)
03823 c = gen_call_value_fdpicdi (rvrtx, picreg, const0_rtx, lr);
03824 else
03825 c = gen_call_fdpicdi (picreg, const0_rtx, lr);
03826 emit_call_insn (c);
03827 }
03828
03829
03830
03831
03832
03833
03834 static bool
03835 frv_function_symbol_referenced_p (rtx x)
03836 {
03837 const char *format;
03838 int length;
03839 int j;
03840
03841 if (GET_CODE (x) == SYMBOL_REF)
03842 return SYMBOL_REF_FUNCTION_P (x);
03843
03844 length = GET_RTX_LENGTH (GET_CODE (x));
03845 format = GET_RTX_FORMAT (GET_CODE (x));
03846
03847 for (j = 0; j < length; ++j)
03848 {
03849 switch (format[j])
03850 {
03851 case 'e':
03852 if (frv_function_symbol_referenced_p (XEXP (x, j)))
03853 return TRUE;
03854 break;
03855
03856 case 'V':
03857 case 'E':
03858 if (XVEC (x, j) != 0)
03859 {
03860 int k;
03861 for (k = 0; k < XVECLEN (x, j); ++k)
03862 if (frv_function_symbol_referenced_p (XVECEXP (x, j, k)))
03863 return TRUE;
03864 }
03865 break;
03866
03867 default:
03868
03869 break;
03870 }
03871 }
03872
03873 return FALSE;
03874 }
03875
03876
03877
03878
03879 int
03880 condexec_memory_operand (rtx op, enum machine_mode mode)
03881 {
03882 enum machine_mode op_mode = GET_MODE (op);
03883 rtx addr;
03884
03885 if (mode != VOIDmode && op_mode != mode)
03886 return FALSE;
03887
03888 switch (op_mode)
03889 {
03890 default:
03891 return FALSE;
03892
03893 case QImode:
03894 case HImode:
03895 case SImode:
03896 case SFmode:
03897 break;
03898 }
03899
03900 if (GET_CODE (op) != MEM)
03901 return FALSE;
03902
03903 addr = XEXP (op, 0);
03904 return frv_legitimate_address_p (mode, addr, reload_completed, TRUE, FALSE);
03905 }
03906
03907
03908
03909
03910 int
03911 direct_return_p (void)
03912 {
03913 frv_stack_t *info;
03914
03915 if (!reload_completed)
03916 return FALSE;
03917
03918 info = frv_stack_info ();
03919 return (info->total_size == 0);
03920 }
03921
03922
03923 void
03924 frv_emit_move (enum machine_mode mode, rtx dest, rtx src)
03925 {
03926 if (GET_CODE (src) == SYMBOL_REF)
03927 {
03928 enum tls_model model = SYMBOL_REF_TLS_MODEL (src);
03929 if (model != 0)
03930 src = frv_legitimize_tls_address (src, model);
03931 }
03932
03933 switch (mode)
03934 {
03935 case SImode:
03936 if (frv_emit_movsi (dest, src))
03937 return;
03938 break;
03939
03940 case QImode:
03941 case HImode:
03942 case DImode:
03943 case SFmode:
03944 case DFmode:
03945 if (!reload_in_progress
03946 && !reload_completed
03947 && !register_operand (dest, mode)
03948 && !reg_or_0_operand (src, mode))
03949 src = copy_to_mode_reg (mode, src);
03950 break;
03951
03952 default:
03953 gcc_unreachable ();
03954 }
03955
03956 emit_insn (gen_rtx_SET (VOIDmode, dest, src));
03957 }
03958
03959
03960
03961
03962
03963 int
03964 frv_emit_movsi (rtx dest, rtx src)
03965 {
03966 int base_regno = -1;
03967 int unspec = 0;
03968 rtx sym = src;
03969 struct frv_unspec old_unspec;
03970
03971 if (!reload_in_progress
03972 && !reload_completed
03973 && !register_operand (dest, SImode)
03974 && (!reg_or_0_operand (src, SImode)
03975
03976
03977
03978 || (GET_CODE (src) == REG
03979 && IN_RANGE_P (REGNO (src),
03980 FIRST_VIRTUAL_REGISTER,
03981 LAST_VIRTUAL_REGISTER))))
03982 {
03983 emit_insn (gen_rtx_SET (VOIDmode, dest, copy_to_mode_reg (SImode, src)));
03984 return TRUE;
03985 }
03986
03987
03988 switch (GET_CODE (src))
03989 {
03990 default:
03991 break;
03992
03993 case LABEL_REF:
03994 handle_label:
03995 if (TARGET_FDPIC)
03996 {
03997
03998
03999
04000
04001
04002
04003
04004
04005
04006
04007
04008
04009
04010
04011
04012
04013
04014
04015
04016
04017
04018
04019
04020
04021
04022
04023
04024
04025 if (TARGET_GPREL_RO)
04026 unspec = R_FRV_GPREL12;
04027 else
04028 unspec = R_FRV_GOT12;
04029 }
04030 else if (flag_pic)
04031 base_regno = PIC_REGNO;
04032
04033 break;
04034
04035 case CONST:
04036 if (frv_const_unspec_p (src, &old_unspec))
04037 break;
04038
04039 if (TARGET_FDPIC && frv_function_symbol_referenced_p (XEXP (src, 0)))
04040 {
04041 handle_whatever:
04042 src = force_reg (GET_MODE (XEXP (src, 0)), XEXP (src, 0));
04043 emit_move_insn (dest, src);
04044 return TRUE;
04045 }
04046 else
04047 {
04048 sym = XEXP (sym, 0);
04049 if (GET_CODE (sym) == PLUS
04050 && GET_CODE (XEXP (sym, 0)) == SYMBOL_REF
04051 && GET_CODE (XEXP (sym, 1)) == CONST_INT)
04052 sym = XEXP (sym, 0);
04053 if (GET_CODE (sym) == SYMBOL_REF)
04054 goto handle_sym;
04055 else if (GET_CODE (sym) == LABEL_REF)
04056 goto handle_label;
04057 else
04058 goto handle_whatever;
04059 }
04060 break;
04061
04062 case SYMBOL_REF:
04063 handle_sym:
04064 if (TARGET_FDPIC)
04065 {
04066 enum tls_model model = SYMBOL_REF_TLS_MODEL (sym);
04067
04068 if (model != 0)
04069 {
04070 src = frv_legitimize_tls_address (src, model);
04071 emit_move_insn (dest, src);
04072 return TRUE;
04073 }
04074
04075 if (SYMBOL_REF_FUNCTION_P (sym))
04076 {
04077 if (frv_local_funcdesc_p (sym))
04078 unspec = R_FRV_FUNCDESC_GOTOFF12;
04079 else
04080 unspec = R_FRV_FUNCDESC_GOT12;
04081 }
04082 else
04083 {
04084 if (CONSTANT_POOL_ADDRESS_P (sym))
04085 switch (GET_CODE (get_pool_constant (sym)))
04086 {
04087 case CONST:
04088 case SYMBOL_REF:
04089 case LABEL_REF:
04090 if (flag_pic)
04091 {
04092 unspec = R_FRV_GOTOFF12;
04093 break;
04094 }
04095
04096 default:
04097 if (TARGET_GPREL_RO)
04098 unspec = R_FRV_GPREL12;
04099 else
04100 unspec = R_FRV_GOT12;
04101 break;
04102 }
04103 else if (SYMBOL_REF_LOCAL_P (sym)
04104 && !SYMBOL_REF_EXTERNAL_P (sym)
04105 && SYMBOL_REF_DECL (sym)
04106 && (!DECL_P (SYMBOL_REF_DECL (sym))
04107 || !DECL_COMMON (SYMBOL_REF_DECL (sym))))
04108 {
04109 tree decl = SYMBOL_REF_DECL (sym);
04110 tree init = TREE_CODE (decl) == VAR_DECL
04111 ? DECL_INITIAL (decl)
04112 : TREE_CODE (decl) == CONSTRUCTOR
04113 ? decl : 0;
04114 int reloc = 0;
04115 bool named_section, readonly;
04116
04117 if (init && init != error_mark_node)
04118 reloc = compute_reloc_for_constant (init);
04119
04120 named_section = TREE_CODE (decl) == VAR_DECL
04121 && lookup_attribute ("section", DECL_ATTRIBUTES (decl));
04122 readonly = decl_readonly_section (decl, reloc);
04123
04124 if (named_section)
04125 unspec = R_FRV_GOT12;
04126 else if (!readonly)
04127 unspec = R_FRV_GOTOFF12;
04128 else if (readonly && TARGET_GPREL_RO)
04129 unspec = R_FRV_GPREL12;
04130 else
04131 unspec = R_FRV_GOT12;
04132 }
04133 else
04134 unspec = R_FRV_GOT12;
04135 }
04136 }
04137
04138 else if (SYMBOL_REF_SMALL_P (sym))
04139 base_regno = SDA_BASE_REG;
04140
04141 else if (flag_pic)
04142 base_regno = PIC_REGNO;
04143
04144 break;
04145 }
04146
04147 if (base_regno >= 0)
04148 {
04149 if (GET_CODE (sym) == SYMBOL_REF && SYMBOL_REF_SMALL_P (sym))
04150 emit_insn (gen_symGOTOFF2reg (dest, src,
04151 gen_rtx_REG (Pmode, base_regno),
04152 GEN_INT (R_FRV_GPREL12)));
04153 else
04154 emit_insn (gen_symGOTOFF2reg_hilo (dest, src,
04155 gen_rtx_REG (Pmode, base_regno),
04156 GEN_INT (R_FRV_GPREL12)));
04157 if (base_regno == PIC_REGNO)
04158 cfun->uses_pic_offset_table = TRUE;
04159 return TRUE;
04160 }
04161
04162 if (unspec)
04163 {
04164 rtx x;
04165
04166
04167
04168 gcc_assert (!reload_in_progress && !reload_completed);
04169
04170 switch (unspec)
04171 {
04172 case R_FRV_GOTOFF12:
04173 if (!frv_small_data_reloc_p (sym, unspec))
04174 x = gen_symGOTOFF2reg_hilo (dest, src, OUR_FDPIC_REG,
04175 GEN_INT (unspec));
04176 else
04177 x = gen_symGOTOFF2reg (dest, src, OUR_FDPIC_REG, GEN_INT (unspec));
04178 break;
04179 case R_FRV_GPREL12:
04180 if (!frv_small_data_reloc_p (sym, unspec))
04181 x = gen_symGPREL2reg_hilo (dest, src, OUR_FDPIC_REG,
04182 GEN_INT (unspec));
04183 else
04184 x = gen_symGPREL2reg (dest, src, OUR_FDPIC_REG, GEN_INT (unspec));
04185 break;
04186 case R_FRV_FUNCDESC_GOTOFF12:
04187 if (flag_pic != 1)
04188 x = gen_symGOTOFF2reg_hilo (dest, src, OUR_FDPIC_REG,
04189 GEN_INT (unspec));
04190 else
04191 x = gen_symGOTOFF2reg (dest, src, OUR_FDPIC_REG, GEN_INT (unspec));
04192 break;
04193 default:
04194 if (flag_pic != 1)
04195 x = gen_symGOT2reg_hilo (dest, src, OUR_FDPIC_REG,
04196 GEN_INT (unspec));
04197 else
04198 x = gen_symGOT2reg (dest, src, OUR_FDPIC_REG, GEN_INT (unspec));
04199 break;
04200 }
04201 emit_insn (x);
04202 cfun->uses_pic_offset_table = TRUE;
04203 return TRUE;
04204 }
04205
04206
04207 return FALSE;
04208 }
04209
04210
04211
04212
04213 const char *
04214 output_move_single (rtx operands[], rtx insn)
04215 {
04216 rtx dest = operands[0];
04217 rtx src = operands[1];
04218
04219 if (GET_CODE (dest) == REG)
04220 {
04221 int dest_regno = REGNO (dest);
04222 enum machine_mode mode = GET_MODE (dest);
04223
04224 if (GPR_P (dest_regno))
04225 {
04226 if (GET_CODE (src) == REG)
04227 {
04228
04229 int src_regno = REGNO (src);
04230
04231 if (GPR_P (src_regno))
04232 return "mov %1, %0";
04233
04234 else if (FPR_P (src_regno))
04235 return "movfg %1, %0";
04236
04237 else if (SPR_P (src_regno))
04238 return "movsg %1, %0";
04239 }
04240
04241 else if (GET_CODE (src) == MEM)
04242 {
04243
04244 switch (mode)
04245 {
04246 default:
04247 break;
04248
04249 case QImode:
04250 return "ldsb%I1%U1 %M1,%0";
04251
04252 case HImode:
04253 return "ldsh%I1%U1 %M1,%0";
04254
04255 case SImode:
04256 case SFmode:
04257 return "ld%I1%U1 %M1, %0";
04258 }
04259 }
04260
04261 else if (GET_CODE (src) == CONST_INT
04262 || GET_CODE (src) == CONST_DOUBLE)
04263 {
04264
04265 HOST_WIDE_INT value;
04266
04267 if (GET_CODE (src) == CONST_INT)
04268 value = INTVAL (src);
04269
04270 else if (mode == SFmode)
04271 {
04272 REAL_VALUE_TYPE rv;
04273 long l;
04274
04275 REAL_VALUE_FROM_CONST_DOUBLE (rv, src);
04276 REAL_VALUE_TO_TARGET_SINGLE (rv, l);
04277 value = l;
04278 }
04279
04280 else
04281 value = CONST_DOUBLE_LOW (src);
04282
04283 if (IN_RANGE_P (value, -32768, 32767))
04284 return "setlos %1, %0";
04285
04286 return "#";
04287 }
04288
04289 else if (GET_CODE (src) == SYMBOL_REF
04290 || GET_CODE (src) == LABEL_REF
04291 || GET_CODE (src) == CONST)
04292 {
04293 return "#";
04294 }
04295 }
04296
04297 else if (FPR_P (dest_regno))
04298 {
04299 if (GET_CODE (src) == REG)
04300 {
04301
04302 int src_regno = REGNO (src);
04303
04304 if (GPR_P (src_regno))
04305 return "movgf %1, %0";
04306
04307 else if (FPR_P (src_regno))
04308 {
04309 if (TARGET_HARD_FLOAT)
04310 return "fmovs %1, %0";
04311 else
04312 return "mor %1, %1, %0";
04313 }
04314 }
04315
04316 else if (GET_CODE (src) == MEM)
04317 {
04318
04319 switch (mode)
04320 {
04321 default:
04322 break;
04323
04324 case QImode:
04325 return "ldbf%I1%U1 %M1,%0";
04326
04327 case HImode:
04328 return "ldhf%I1%U1 %M1,%0";
04329
04330 case SImode:
04331 case SFmode:
04332 return "ldf%I1%U1 %M1, %0";
04333 }
04334 }
04335
04336 else if (ZERO_P (src))
04337 return "movgf %., %0";
04338 }
04339
04340 else if (SPR_P (dest_regno))
04341 {
04342 if (GET_CODE (src) == REG)
04343 {
04344
04345 int src_regno = REGNO (src);
04346
04347 if (GPR_P (src_regno))
04348 return "movgs %1, %0";
04349 }
04350 else if (ZERO_P (src))
04351 return "movgs %., %0";
04352 }
04353 }
04354
04355 else if (GET_CODE (dest) == MEM)
04356 {
04357 if (GET_CODE (src) == REG)
04358 {
04359 int src_regno = REGNO (src);
04360 enum machine_mode mode = GET_MODE (dest);
04361
04362 if (GPR_P (src_regno))
04363 {
04364 switch (mode)
04365 {
04366 default:
04367 break;
04368
04369 case QImode:
04370 return "stb%I0%U0 %1, %M0";
04371
04372 case HImode:
04373 return "sth%I0%U0 %1, %M0";
04374
04375 case SImode:
04376 case SFmode:
04377 return "st%I0%U0 %1, %M0";
04378 }
04379 }
04380
04381 else if (FPR_P (src_regno))
04382 {
04383 switch (mode)
04384 {
04385 default:
04386 break;
04387
04388 case QImode:
04389 return "stbf%I0%U0 %1, %M0";
04390
04391 case HImode:
04392 return "sthf%I0%U0 %1, %M0";
04393
04394 case SImode:
04395 case SFmode:
04396 return "stf%I0%U0 %1, %M0";
04397 }
04398 }
04399 }
04400
04401 else if (ZERO_P (src))
04402 {
04403 switch (GET_MODE (dest))
04404 {
04405 default:
04406 break;
04407
04408 case QImode:
04409 return "stb%I0%U0 %., %M0";
04410
04411 case HImode:
04412 return "sth%I0%U0 %., %M0";
04413
04414 case SImode:
04415 case SFmode:
04416 return "st%I0%U0 %., %M0";
04417 }
04418 }
04419 }
04420
04421 fatal_insn ("bad output_move_single operand", insn);
04422 return "";
04423 }
04424
04425
04426
04427
04428 const char *
04429 output_move_double (rtx operands[], rtx insn)
04430 {
04431 rtx dest = operands[0];
04432 rtx src = operands[1];
04433 enum machine_mode mode = GET_MODE (dest);
04434
04435 if (GET_CODE (dest) == REG)
04436 {
04437 int dest_regno = REGNO (dest);
04438
04439 if (GPR_P (dest_regno))
04440 {
04441 if (GET_CODE (src) == REG)
04442 {
04443
04444 int src_regno = REGNO (src);
04445
04446 if (GPR_P (src_regno))
04447 return "#";
04448
04449 else if (FPR_P (src_regno))
04450 {
04451 if (((dest_regno - GPR_FIRST) & 1) == 0
04452 && ((src_regno - FPR_FIRST) & 1) == 0)
04453 return "movfgd %1, %0";
04454
04455 return "#";
04456 }
04457 }
04458
04459 else if (GET_CODE (src) == MEM)
04460 {
04461
04462 if (dbl_memory_one_insn_operand (src, mode))
04463 return "ldd%I1%U1 %M1, %0";
04464
04465 return "#";
04466 }
04467
04468 else if (GET_CODE (src) == CONST_INT
04469 || GET_CODE (src) == CONST_DOUBLE)
04470 return "#";
04471 }
04472
04473 else if (FPR_P (dest_regno))
04474 {
04475 if (GET_CODE (src) == REG)
04476 {
04477
04478 int src_regno = REGNO (src);
04479
04480 if (GPR_P (src_regno))
04481 {
04482 if (((dest_regno - FPR_FIRST) & 1) == 0
04483 && ((src_regno - GPR_FIRST) & 1) == 0)
04484 return "movgfd %1, %0";
04485
04486 return "#";
04487 }
04488
04489 else if (FPR_P (src_regno))
04490 {
04491 if (TARGET_DOUBLE
04492 && ((dest_regno - FPR_FIRST) & 1) == 0
04493 && ((src_regno - FPR_FIRST) & 1) == 0)
04494 return "fmovd %1, %0";
04495
04496 return "#";
04497 }
04498 }
04499
04500 else if (GET_CODE (src) == MEM)
04501 {
04502
04503 if (dbl_memory_one_insn_operand (src, mode))
04504 return "lddf%I1%U1 %M1, %0";
04505
04506 return "#";
04507 }
04508
04509 else if (ZERO_P (src))
04510 return "#";
04511 }
04512 }
04513
04514 else if (GET_CODE (dest) == MEM)
04515 {
04516 if (GET_CODE (src) == REG)
04517 {
04518 int src_regno = REGNO (src);
04519
04520 if (GPR_P (src_regno))
04521 {
04522 if (((src_regno - GPR_FIRST) & 1) == 0
04523 && dbl_memory_one_insn_operand (dest, mode))
04524 return "std%I0%U0 %1, %M0";
04525
04526 return "#";
04527 }
04528
04529 if (FPR_P (src_regno))
04530 {
04531 if (((src_regno - FPR_FIRST) & 1) == 0
04532 && dbl_memory_one_insn_operand (dest, mode))
04533 return "stdf%I0%U0 %1, %M0";
04534
04535 return "#";
04536 }
04537 }
04538
04539 else if (ZERO_P (src))
04540 {
04541 if (dbl_memory_one_insn_operand (dest, mode))
04542 return "std%I0%U0 %., %M0";
04543
04544 return "#";
04545 }
04546 }
04547
04548 fatal_insn ("bad output_move_double operand", insn);
04549 return "";
04550 }
04551
04552
04553
04554
04555
04556
04557
04558
04559 const char *
04560 output_condmove_single (rtx operands[], rtx insn)
04561 {
04562 rtx dest = operands[2];
04563 rtx src = operands[3];
04564
04565 if (GET_CODE (dest) == REG)
04566 {
04567 int dest_regno = REGNO (dest);
04568 enum machine_mode mode = GET_MODE (dest);
04569
04570 if (GPR_P (dest_regno))
04571 {
04572 if (GET_CODE (src) == REG)
04573 {
04574
04575 int src_regno = REGNO (src);
04576
04577 if (GPR_P (src_regno))
04578 return "cmov %z3, %2, %1, %e0";
04579
04580 else if (FPR_P (src_regno))
04581 return "cmovfg %3, %2, %1, %e0";
04582 }
04583
04584 else if (GET_CODE (src) == MEM)
04585 {
04586
04587 switch (mode)
04588 {
04589 default:
04590 break;
04591
04592 case QImode:
04593 return "cldsb%I3%U3 %M3, %2, %1, %e0";
04594
04595 case HImode:
04596 return "cldsh%I3%U3 %M3, %2, %1, %e0";
04597
04598 case SImode:
04599 case SFmode:
04600 return "cld%I3%U3 %M3, %2, %1, %e0";
04601 }
04602 }
04603
04604 else if (ZERO_P (src))
04605 return "cmov %., %2, %1, %e0";
04606 }
04607
04608 else if (FPR_P (dest_regno))
04609 {
04610 if (GET_CODE (src) == REG)
04611 {
04612
04613 int src_regno = REGNO (src);
04614
04615 if (GPR_P (src_regno))
04616 return "cmovgf %3, %2, %1, %e0";
04617
04618 else if (FPR_P (src_regno))
04619 {
04620 if (TARGET_HARD_FLOAT)
04621 return "cfmovs %3,%2,%1,%e0";
04622 else
04623 return "cmor %3, %3, %2, %1, %e0";
04624 }
04625 }
04626
04627 else if (GET_CODE (src) == MEM)
04628 {
04629
04630 if (mode == SImode || mode == SFmode)
04631 return "cldf%I3%U3 %M3, %2, %1, %e0";
04632 }
04633
04634 else if (ZERO_P (src))
04635 return "cmovgf %., %2, %1, %e0";
04636 }
04637 }
04638
04639 else if (GET_CODE (dest) == MEM)
04640 {
04641 if (GET_CODE (src) == REG)
04642 {
04643 int src_regno = REGNO (src);
04644 enum machine_mode mode = GET_MODE (dest);
04645
04646 if (GPR_P (src_regno))
04647 {
04648 switch (mode)
04649 {
04650 default:
04651 break;
04652
04653 case QImode:
04654 return "cstb%I2%U2 %3, %M2, %1, %e0";
04655
04656 case HImode:
04657 return "csth%I2%U2 %3, %M2, %1, %e0";
04658
04659 case SImode:
04660 case SFmode:
04661 return "cst%I2%U2 %3, %M2, %1, %e0";
04662 }
04663 }
04664
04665 else if (FPR_P (src_regno) && (mode == SImode || mode == SFmode))
04666 return "cstf%I2%U2 %3, %M2, %1, %e0";
04667 }
04668
04669 else if (ZERO_P (src))
04670 {
04671 enum machine_mode mode = GET_MODE (dest);
04672 switch (mode)
04673 {
04674 default:
04675 break;
04676
04677 case QImode:
04678 return "cstb%I2%U2 %., %M2, %1, %e0";
04679
04680 case HImode:
04681 return "csth%I2%U2 %., %M2, %1, %e0";
04682
04683 case SImode:
04684 case SFmode:
04685 return "cst%I2%U2 %., %M2, %1, %e0";
04686 }
04687 }
04688 }
04689
04690 fatal_insn ("bad output_condmove_single operand", insn);
04691 return "";
04692 }
04693
04694
04695
04696
04697
04698 static rtx
04699 frv_emit_comparison (enum rtx_code test, rtx op0, rtx op1)
04700 {
04701 enum machine_mode cc_mode;
04702 rtx cc_reg;
04703
04704
04705 if (GET_MODE (op0) == CC_FPmode && GET_CODE (op1) != REG)
04706 op1 = force_reg (GET_MODE (op0), op1);
04707
04708
04709
04710 cc_mode = SELECT_CC_MODE (test, op0, op1);
04711 cc_reg = ((TARGET_ALLOC_CC)
04712 ? gen_reg_rtx (cc_mode)
04713 : gen_rtx_REG (cc_mode,
04714 (cc_mode == CC_FPmode) ? FCC_FIRST : ICC_FIRST));
04715
04716 emit_insn (gen_rtx_SET (VOIDmode, cc_reg,
04717 gen_rtx_COMPARE (cc_mode, op0, op1)));
04718
04719 return cc_reg;
04720 }
04721
04722
04723
04724
04725
04726
04727
04728
04729 int
04730 frv_emit_cond_branch (enum rtx_code test, rtx label)
04731 {
04732 rtx test_rtx;
04733 rtx label_ref;
04734 rtx if_else;
04735 rtx cc_reg = frv_emit_comparison (test, frv_compare_op0, frv_compare_op1);
04736 enum machine_mode cc_mode = GET_MODE (cc_reg);
04737
04738
04739
04740
04741
04742
04743 label_ref = gen_rtx_LABEL_REF (VOIDmode, label);
04744 test_rtx = gen_rtx_fmt_ee (test, cc_mode, cc_reg, const0_rtx);
04745 if_else = gen_rtx_IF_THEN_ELSE (cc_mode, test_rtx, label_ref, pc_rtx);
04746 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, if_else));
04747 return TRUE;
04748 }
04749
04750
04751
04752
04753
04754 int
04755 frv_emit_scc (enum rtx_code test, rtx target)
04756 {
04757 rtx set;
04758 rtx test_rtx;
04759 rtx clobber;
04760 rtx cr_reg;
04761 rtx cc_reg = frv_emit_comparison (test, frv_compare_op0, frv_compare_op1);
04762
04763
04764
04765
04766 test_rtx = gen_rtx_fmt_ee (test, SImode, cc_reg, const0_rtx);
04767 set = gen_rtx_SET (VOIDmode, target, test_rtx);
04768
04769 cr_reg = ((TARGET_ALLOC_CC)
04770 ? gen_reg_rtx (CC_CCRmode)
04771 : gen_rtx_REG (CC_CCRmode,
04772 ((GET_MODE (cc_reg) == CC_FPmode)
04773 ? FCR_FIRST
04774 : ICR_FIRST)));
04775
04776 clobber = gen_rtx_CLOBBER (VOIDmode, cr_reg);
04777 emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, set, clobber)));
04778 return TRUE;
04779 }
04780
04781
04782
04783
04784
04785 rtx
04786 frv_split_scc (rtx dest, rtx test, rtx cc_reg, rtx cr_reg, HOST_WIDE_INT value)
04787 {
04788 rtx ret;
04789
04790 start_sequence ();
04791
04792
04793 emit_insn (gen_rtx_SET (VOIDmode,
04794 cr_reg,
04795 gen_rtx_fmt_ee (GET_CODE (test),
04796 GET_MODE (cr_reg),
04797 cc_reg,
04798 const0_rtx)));
04799
04800
04801 emit_move_insn (dest, GEN_INT (value));
04802
04803
04804 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
04805 gen_rtx_EQ (GET_MODE (cr_reg),
04806 cr_reg,
04807 const0_rtx),
04808 gen_rtx_SET (VOIDmode, dest, const0_rtx)));
04809
04810
04811 ret = get_insns ();
04812 end_sequence ();
04813 return ret;
04814 }
04815
04816
04817
04818
04819
04820 int
04821 frv_emit_cond_move (rtx dest, rtx test_rtx, rtx src1, rtx src2)
04822 {
04823 rtx set;
04824 rtx clobber_cc;
04825 rtx test2;
04826 rtx cr_reg;
04827 rtx if_rtx;
04828 enum rtx_code test = GET_CODE (test_rtx);
04829 rtx cc_reg = frv_emit_comparison (test, frv_compare_op0, frv_compare_op1);
04830 enum machine_mode cc_mode = GET_MODE (cc_reg);
04831
04832
04833
04834
04835
04836
04837
04838
04839
04840 if (GET_CODE (src1) == CONST_INT && GET_CODE (src2) == CONST_INT)
04841 {
04842 HOST_WIDE_INT value1 = INTVAL (src1);
04843 HOST_WIDE_INT value2 = INTVAL (src2);
04844
04845
04846
04847 if (value1 == 0 || value2 == 0)
04848 ;
04849
04850
04851
04852
04853
04854 else if (IN_RANGE_P (value1, -2048, 2047)
04855 && IN_RANGE_P (value2 - value1, -2048, 2047))
04856 ;
04857
04858
04859
04860 else
04861 {
04862 src1 = force_reg (GET_MODE (dest), src1);
04863 src2 = force_reg (GET_MODE (dest), src2);
04864 }
04865 }
04866
04867
04868
04869 else
04870 {
04871 if (GET_CODE (src1) == CONST_INT && INTVAL (src1) != 0)
04872 src1 = force_reg (GET_MODE (dest), src1);
04873
04874 if (GET_CODE (src2) == CONST_INT && INTVAL (src2) != 0)
04875 src2 = force_reg (GET_MODE (dest), src2);
04876 }
04877
04878 test2 = gen_rtx_fmt_ee (test, cc_mode, cc_reg, const0_rtx);
04879 if_rtx = gen_rtx_IF_THEN_ELSE (GET_MODE (dest), test2, src1, src2);
04880
04881 set = gen_rtx_SET (VOIDmode, dest, if_rtx);
04882
04883 cr_reg = ((TARGET_ALLOC_CC)
04884 ? gen_reg_rtx (CC_CCRmode)
04885 : gen_rtx_REG (CC_CCRmode,
04886 (cc_mode == CC_FPmode) ? FCR_FIRST : ICR_FIRST));
04887
04888 clobber_cc = gen_rtx_CLOBBER (VOIDmode, cr_reg);
04889 emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, set, clobber_cc)));
04890 return TRUE;
04891 }
04892
04893
04894
04895
04896
04897 rtx
04898 frv_split_cond_move (rtx operands[])
04899 {
04900 rtx dest = operands[0];
04901 rtx test = operands[1];
04902 rtx cc_reg = operands[2];
04903 rtx src1 = operands[3];
04904 rtx src2 = operands[4];
04905 rtx cr_reg = operands[5];
04906 rtx ret;
04907 enum machine_mode cr_mode = GET_MODE (cr_reg);
04908
04909 start_sequence ();
04910
04911
04912 emit_insn (gen_rtx_SET (VOIDmode,
04913 cr_reg,
04914 gen_rtx_fmt_ee (GET_CODE (test),
04915 GET_MODE (cr_reg),
04916 cc_reg,
04917 const0_rtx)));
04918
04919
04920 if (GET_CODE (src1) == CONST_INT && GET_CODE (src2) == CONST_INT)
04921 {
04922 HOST_WIDE_INT value1 = INTVAL (src1);
04923 HOST_WIDE_INT value2 = INTVAL (src2);
04924
04925
04926
04927 if (value1 == 0)
04928 {
04929 emit_move_insn (dest, src2);
04930 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
04931 gen_rtx_NE (cr_mode, cr_reg,
04932 const0_rtx),
04933 gen_rtx_SET (VOIDmode, dest, src1)));
04934 }
04935
04936 else if (value2 == 0)
04937 {
04938 emit_move_insn (dest, src1);
04939 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
04940 gen_rtx_EQ (cr_mode, cr_reg,
04941 const0_rtx),
04942 gen_rtx_SET (VOIDmode, dest, src2)));
04943 }
04944
04945
04946
04947
04948
04949 else if (IN_RANGE_P (value1, -2048, 2047)
04950 && IN_RANGE_P (value2 - value1, -2048, 2047))
04951 {
04952 rtx dest_si = ((GET_MODE (dest) == SImode)
04953 ? dest
04954 : gen_rtx_SUBREG (SImode, dest, 0));
04955
04956 emit_move_insn (dest_si, GEN_INT (value2 - value1));
04957 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
04958 gen_rtx_NE (cr_mode, cr_reg,
04959 const0_rtx),
04960 gen_rtx_SET (VOIDmode, dest_si,
04961 const0_rtx)));
04962 emit_insn (gen_addsi3 (dest_si, dest_si, src1));
04963 }
04964
04965 else
04966 gcc_unreachable ();
04967 }
04968 else
04969 {
04970
04971 if (! rtx_equal_p (dest, src1))
04972 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
04973 gen_rtx_NE (cr_mode, cr_reg, const0_rtx),
04974 gen_rtx_SET (VOIDmode, dest, src1)));
04975
04976
04977 if (! rtx_equal_p (dest, src2))
04978 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
04979 gen_rtx_EQ (cr_mode, cr_reg, const0_rtx),
04980 gen_rtx_SET (VOIDmode, dest, src2)));
04981 }
04982
04983
04984 ret = get_insns ();
04985 end_sequence ();
04986 return ret;
04987 }
04988
04989
04990
04991
04992 void
04993 frv_split_double_load (rtx dest, rtx source)
04994 {
04995 int regno = REGNO (dest);
04996 rtx dest1 = gen_highpart (SImode, dest);
04997 rtx dest2 = gen_lowpart (SImode, dest);
04998 rtx address = XEXP (source, 0);
04999
05000
05001
05002
05003
05004
05005
05006
05007
05008
05009 if (GET_CODE (address) == PRE_MODIFY
05010 || ! refers_to_regno_p (regno, regno + 1, address, NULL))
05011 {
05012
05013 emit_move_insn (dest1, change_address (source, SImode, NULL));
05014 emit_move_insn (dest2, frv_index_memory (source, SImode, 1));
05015 }
05016 else
05017 {
05018
05019
05020
05021 emit_move_insn (dest2, frv_index_memory (source, SImode, 1));
05022 emit_move_insn (dest1, change_address (source, SImode, NULL));
05023 }
05024 }
05025
05026
05027
05028 void
05029 frv_split_double_store (rtx dest, rtx source)
05030 {
05031 rtx dest1 = change_address (dest, SImode, NULL);
05032 rtx dest2 = frv_index_memory (dest, SImode, 1);
05033 if (ZERO_P (source))
05034 {
05035 emit_move_insn (dest1, CONST0_RTX (SImode));
05036 emit_move_insn (dest2, CONST0_RTX (SImode));
05037 }
05038 else
05039 {
05040 emit_move_insn (dest1, gen_highpart (SImode, source));
05041 emit_move_insn (dest2, gen_lowpart (SImode, source));
05042 }
05043 }
05044
05045
05046
05047
05048
05049 rtx
05050 frv_split_minmax (rtx operands[])
05051 {
05052 rtx dest = operands[0];
05053 rtx minmax = operands[1];
05054 rtx src1 = operands[2];
05055 rtx src2 = operands[3];
05056 rtx cc_reg = operands[4];
05057 rtx cr_reg = operands[5];
05058 rtx ret;
05059 enum rtx_code test_code;
05060 enum machine_mode cr_mode = GET_MODE (cr_reg);
05061
05062 start_sequence ();
05063
05064
05065 switch (GET_CODE (minmax))
05066 {
05067 default:
05068 gcc_unreachable ();
05069
05070 case SMIN: test_code = LT; break;
05071 case SMAX: test_code = GT; break;
05072 case UMIN: test_code = LTU; break;
05073 case UMAX: test_code = GTU; break;
05074 }
05075
05076
05077 emit_insn (gen_rtx_SET (VOIDmode,
05078 cc_reg,
05079 gen_rtx_COMPARE (GET_MODE (cc_reg),
05080 src1, src2)));
05081
05082
05083 emit_insn (gen_rtx_SET (VOIDmode,
05084 cr_reg,
05085 gen_rtx_fmt_ee (test_code,
05086 GET_MODE (cr_reg),
05087 cc_reg,
05088 const0_rtx)));
05089
05090
05091
05092 if (GET_CODE (src2) == CONST_INT && INTVAL (src2) != 0)
05093 {
05094 gcc_assert (!rtx_equal_p (dest, src1));
05095
05096 emit_move_insn (dest, src2);
05097 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
05098 gen_rtx_NE (cr_mode, cr_reg, const0_rtx),
05099 gen_rtx_SET (VOIDmode, dest, src1)));
05100 }
05101
05102
05103 else
05104 {
05105
05106 if (! rtx_equal_p (dest, src1))
05107 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
05108 gen_rtx_NE (cr_mode, cr_reg, const0_rtx),
05109 gen_rtx_SET (VOIDmode, dest, src1)));
05110
05111
05112 if (! rtx_equal_p (dest, src2))
05113 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
05114 gen_rtx_EQ (cr_mode, cr_reg, const0_rtx),
05115 gen_rtx_SET (VOIDmode, dest, src2)));
05116 }
05117
05118
05119 ret = get_insns ();
05120 end_sequence ();
05121 return ret;
05122 }
05123
05124
05125
05126
05127
05128 rtx
05129 frv_split_abs (rtx operands[])
05130 {
05131 rtx dest = operands[0];
05132 rtx src = operands[1];
05133 rtx cc_reg = operands[2];
05134 rtx cr_reg = operands[3];
05135 rtx ret;
05136
05137 start_sequence ();
05138
05139
05140 emit_insn (gen_rtx_SET (VOIDmode,
05141 cc_reg,
05142 gen_rtx_COMPARE (CCmode, src, const0_rtx)));
05143
05144
05145 emit_insn (gen_rtx_SET (VOIDmode,
05146 cr_reg,
05147 gen_rtx_fmt_ee (LT, CC_CCRmode, cc_reg, const0_rtx)));
05148
05149
05150 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
05151 gen_rtx_NE (CC_CCRmode, cr_reg, const0_rtx),
05152 gen_negsi2 (dest, src)));
05153
05154
05155 if (! rtx_equal_p (dest, src))
05156 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
05157 gen_rtx_EQ (CC_CCRmode, cr_reg, const0_rtx),
05158 gen_rtx_SET (VOIDmode, dest, src)));
05159
05160
05161 ret = get_insns ();
05162 end_sequence ();
05163 return ret;
05164 }
05165
05166
05167
05168
05169
05170 static int
05171 frv_clear_registers_used (rtx *ptr, void *data)
05172 {
05173 if (GET_CODE (*ptr) == REG)
05174 {
05175 int regno = REGNO (*ptr);
05176 HARD_REG_SET *p_regs = (HARD_REG_SET *)data;
05177
05178 if (regno < FIRST_PSEUDO_REGISTER)
05179 {
05180 int reg_max = regno + HARD_REGNO_NREGS (regno, GET_MODE (*ptr));
05181
05182 while (regno < reg_max)
05183 {
05184 CLEAR_HARD_REG_BIT (*p_regs, regno);
05185 regno++;
05186 }
05187 }
05188 }
05189
05190 return 0;
05191 }
05192
05193
05194
05195
05196
05197
05198 void
05199 frv_ifcvt_init_extra_fields (ce_if_block_t *ce_info ATTRIBUTE_UNUSED)
05200 {
05201 frv_ifcvt.added_insns_list = NULL_RTX;
05202 frv_ifcvt.cur_scratch_regs = 0;
05203 frv_ifcvt.num_nested_cond_exec = 0;
05204 frv_ifcvt.cr_reg = NULL_RTX;
05205 frv_ifcvt.nested_cc_reg = NULL_RTX;
05206 frv_ifcvt.extra_int_cr = NULL_RTX;
05207 frv_ifcvt.extra_fp_cr = NULL_RTX;
05208 frv_ifcvt.last_nested_if_cr = NULL_RTX;
05209 }
05210
05211
05212
05213
05214
05215 static void
05216 frv_ifcvt_add_insn (rtx pattern, rtx insn, int before_p)
05217 {
05218 rtx link = alloc_EXPR_LIST (VOIDmode, pattern, insn);
05219
05220 link->jump = before_p;
05221 frv_ifcvt.added_insns_list = alloc_EXPR_LIST (VOIDmode, link,
05222 frv_ifcvt.added_insns_list);
05223
05224 if (TARGET_DEBUG_COND_EXEC)
05225 {
05226 fprintf (stderr,
05227 "\n:::::::::: frv_ifcvt_add_insn: add the following %s insn %d:\n",
05228 (before_p) ? "before" : "after",
05229 (int)INSN_UID (insn));
05230
05231 debug_rtx (pattern);
05232 }
05233 }
05234
05235
05236
05237
05238
05239
05240
05241
05242 void
05243 frv_ifcvt_modify_tests (ce_if_block_t *ce_info, rtx *p_true, rtx *p_false)
05244 {
05245 basic_block test_bb = ce_info->test_bb;
05246 basic_block then_bb = ce_info->then_bb;
05247 basic_block else_bb = ce_info->else_bb;
05248 basic_block join_bb = ce_info->join_bb;
05249 rtx true_expr = *p_true;
05250 rtx cr;
05251 rtx cc;
05252 rtx nested_cc;
05253 enum machine_mode mode = GET_MODE (true_expr);
05254 int j;
05255 basic_block *bb;
05256 int num_bb;
05257 frv_tmp_reg_t *tmp_reg = &frv_ifcvt.tmp_reg;
05258 rtx check_insn;
05259 rtx sub_cond_exec_reg;
05260 enum rtx_code code;
05261 enum rtx_code code_true;
05262 enum rtx_code code_false;
05263 enum reg_class cc_class;
05264 enum reg_class cr_class;
05265 int cc_first;
05266 int cc_last;
05267 reg_set_iterator rsi;
05268
05269
05270
05271
05272 if (!reload_completed || !TARGET_COND_EXEC
05273 || (!TARGET_NESTED_CE && ce_info->pass > 1))
05274 goto fail;
05275
05276
05277
05278
05279
05280 memset (&tmp_reg->regs, 0, sizeof (tmp_reg->regs));
05281 COPY_HARD_REG_SET (tmp_reg->regs, call_used_reg_set);
05282 AND_COMPL_HARD_REG_SET (tmp_reg->regs, fixed_reg_set);
05283 SET_HARD_REG_BIT (tmp_reg->regs, ICC_TEMP);
05284 SET_HARD_REG_BIT (tmp_reg->regs, ICR_TEMP);
05285
05286
05287
05288
05289
05290 if (ce_info->pass > 1)
05291 {
05292 CLEAR_HARD_REG_SET (frv_ifcvt.nested_cc_ok_rewrite);
05293 for (j = CC_FIRST; j <= CC_LAST; j++)
05294 if (TEST_HARD_REG_BIT (tmp_reg->regs, j))
05295 {
05296 if (REGNO_REG_SET_P (then_bb->il.rtl->global_live_at_start, j))
05297 continue;
05298
05299 if (else_bb
05300 && REGNO_REG_SET_P (else_bb->il.rtl->global_live_at_start, j))
05301 continue;
05302
05303 if (join_bb
05304 && REGNO_REG_SET_P (join_bb->il.rtl->global_live_at_start, j))
05305 continue;
05306
05307 SET_HARD_REG_BIT (frv_ifcvt.nested_cc_ok_rewrite, j);
05308 }
05309 }
05310
05311 for (j = 0; j < frv_ifcvt.cur_scratch_regs; j++)
05312 frv_ifcvt.scratch_regs[j] = NULL_RTX;
05313
05314 frv_ifcvt.added_insns_list = NULL_RTX;
05315 frv_ifcvt.cur_scratch_regs = 0;
05316
05317 bb = (basic_block *) alloca ((2 + ce_info->num_multiple_test_blocks)
05318 * sizeof (basic_block));
05319
05320 if (join_bb)
05321 {
05322 unsigned int regno;
05323
05324
05325
05326 EXECUTE_IF_SET_IN_REG_SET (join_bb->il.rtl->global_live_at_start, 0, regno, rsi)
05327 {
05328 if (regno < FIRST_PSEUDO_REGISTER)
05329 CLEAR_HARD_REG_BIT (tmp_reg->regs, regno);
05330 }
05331 }
05332
05333
05334 num_bb = 0;
05335 if (ce_info->num_multiple_test_blocks)
05336 {
05337 basic_block multiple_test_bb = ce_info->last_test_bb;
05338
05339 while (multiple_test_bb != test_bb)
05340 {
05341 bb[num_bb++] = multiple_test_bb;
05342 multiple_test_bb = EDGE_PRED (multiple_test_bb, 0)->src;
05343 }
05344 }
05345
05346
05347 bb[num_bb++] = then_bb;
05348 if (else_bb)
05349 bb[num_bb++] = else_bb;
05350
05351 sub_cond_exec_reg = NULL_RTX;
05352 frv_ifcvt.num_nested_cond_exec = 0;
05353
05354
05355 for (j = 0; j < num_bb; j++)
05356 {
05357 rtx last_insn = BB_END (bb[j]);
05358 rtx insn = BB_HEAD (bb[j]);
05359 unsigned int regno;
05360
05361 if (dump_file)
05362 fprintf (dump_file, "Scanning %s block %d, start %d, end %d\n",
05363 (bb[j] == else_bb) ? "else" : ((bb[j] == then_bb) ? "then" : "test"),
05364 (int) bb[j]->index,
05365 (int) INSN_UID (BB_HEAD (bb[j])),
05366 (int) INSN_UID (BB_END (bb[j])));
05367
05368
05369
05370 EXECUTE_IF_SET_IN_REG_SET (bb[j]->il.rtl->global_live_at_start, 0, regno, rsi)
05371 {
05372 if (regno < FIRST_PSEUDO_REGISTER)
05373 CLEAR_HARD_REG_BIT (tmp_reg->regs, regno);
05374 }
05375
05376
05377 for (;;)
05378 {
05379
05380
05381
05382 if (INSN_P (insn))
05383 {
05384 rtx pattern;
05385 rtx set;
05386 int skip_nested_if = FALSE;
05387
05388 for_each_rtx (&PATTERN (insn), frv_clear_registers_used,
05389 (void *)&tmp_reg->regs);
05390
05391 pattern = PATTERN (insn);
05392 if (GET_CODE (pattern) == COND_EXEC)
05393 {
05394 rtx reg = XEXP (COND_EXEC_TEST (pattern), 0);
05395
05396 if (reg != sub_cond_exec_reg)
05397 {
05398 sub_cond_exec_reg = reg;
05399 frv_ifcvt.num_nested_cond_exec++;
05400 }
05401 }
05402
05403 set = single_set_pattern (pattern);
05404 if (set)
05405 {
05406 rtx dest = SET_DEST (set);
05407 rtx src = SET_SRC (set);
05408
05409 if (GET_CODE (dest) == REG)
05410 {
05411 int regno = REGNO (dest);
05412 enum rtx_code src_code = GET_CODE (src);
05413
05414 if (CC_P (regno) && src_code == COMPARE)
05415 skip_nested_if = TRUE;
05416
05417 else if (CR_P (regno)
05418 && (src_code == IF_THEN_ELSE
05419 || COMPARISON_P (src)))
05420 skip_nested_if = TRUE;
05421 }
05422 }
05423
05424 if (! skip_nested_if)
05425 for_each_rtx (&PATTERN (insn), frv_clear_registers_used,
05426 (void *)&frv_ifcvt.nested_cc_ok_rewrite);
05427 }
05428
05429 if (insn == last_insn)
05430 break;
05431
05432 insn = NEXT_INSN (insn);
05433 }
05434 }
05435
05436
05437
05438
05439 if (ce_info->pass > 1)
05440 {
05441 for (j = CC_FIRST; j <= CC_LAST; j++)
05442 if (TEST_HARD_REG_BIT (frv_ifcvt.nested_cc_ok_rewrite, j))
05443 SET_HARD_REG_BIT (tmp_reg->regs, j);
05444 else
05445 CLEAR_HARD_REG_BIT (tmp_reg->regs, j);
05446 }
05447
05448 if (dump_file)
05449 {
05450 int num_gprs = 0;
05451 fprintf (dump_file, "Available GPRs: ");
05452
05453 for (j = GPR_FIRST; j <= GPR_LAST; j++)
05454 if (TEST_HARD_REG_BIT (tmp_reg->regs, j))
05455 {
05456 fprintf (dump_file, " %d [%s]", j, reg_names[j]);
05457 if (++num_gprs > GPR_TEMP_NUM+2)
05458 break;
05459 }
05460
05461 fprintf (dump_file, "%s\nAvailable CRs: ",
05462 (num_gprs > GPR_TEMP_NUM+2) ? " ..." : "");
05463
05464 for (j = CR_FIRST; j <= CR_LAST; j++)
05465 if (TEST_HARD_REG_BIT (tmp_reg->regs, j))
05466 fprintf (dump_file, " %d [%s]", j, reg_names[j]);
05467
05468 fputs ("\n", dump_file);
05469
05470 if (ce_info->pass > 1)
05471 {
05472 fprintf (dump_file, "Modifiable CCs: ");
05473 for (j = CC_FIRST; j <= CC_LAST; j++)
05474 if (TEST_HARD_REG_BIT (tmp_reg->regs, j))
05475 fprintf (dump_file, " %d [%s]", j, reg_names[j]);
05476
05477 fprintf (dump_file, "\n%d nested COND_EXEC statements\n",
05478 frv_ifcvt.num_nested_cond_exec);
05479 }
05480 }
05481
05482
05483
05484
05485 if (mode == CCmode || mode == CC_UNSmode || mode == CC_NZmode)
05486 {
05487 cr_class = ICR_REGS;
05488 cc_class = ICC_REGS;
05489 cc_first = ICC_FIRST;
05490 cc_last = ICC_LAST;
05491 }
05492 else if (mode == CC_FPmode)
05493 {
05494 cr_class = FCR_REGS;
05495 cc_class = FCC_REGS;
05496 cc_first = FCC_FIRST;
05497 cc_last = FCC_LAST;
05498 }
05499 else
05500 {
05501 cc_first = cc_last = 0;
05502 cr_class = cc_class = NO_REGS;
05503 }
05504
05505 cc = XEXP (true_expr, 0);
05506 nested_cc = cr = NULL_RTX;
05507 if (cc_class != NO_REGS)
05508 {
05509
05510
05511 int cc_regno;
05512
05513 for (cc_regno = cc_first; cc_regno <= cc_last; cc_regno++)
05514 {
05515 int cr_regno = cc_regno - CC_FIRST + CR_FIRST;
05516
05517 if (TEST_HARD_REG_BIT (frv_ifcvt.tmp_reg.regs, cc_regno)
05518 && TEST_HARD_REG_BIT (frv_ifcvt.tmp_reg.regs, cr_regno))
05519 {
05520 frv_ifcvt.tmp_reg.next_reg[ (int)cr_class ] = cr_regno;
05521 cr = frv_alloc_temp_reg (tmp_reg, cr_class, CC_CCRmode, TRUE,
05522 TRUE);
05523
05524 frv_ifcvt.tmp_reg.next_reg[ (int)cc_class ] = cc_regno;
05525 nested_cc = frv_alloc_temp_reg (tmp_reg, cc_class, CCmode,
05526 TRUE, TRUE);
05527 break;
05528 }
05529 }
05530 }
05531
05532 if (! cr)
05533 {
05534 if (dump_file)
05535 fprintf (dump_file, "Could not allocate a CR temporary register\n");
05536
05537 goto fail;
05538 }
05539
05540 if (dump_file)
05541 fprintf (dump_file,
05542 "Will use %s for conditional execution, %s for nested comparisons\n",
05543 reg_names[ REGNO (cr)],
05544 (nested_cc) ? reg_names[ REGNO (nested_cc) ] : "<none>");
05545
05546
05547
05548
05549 code = GET_CODE (true_expr);
05550 if (GET_MODE (cc) != CC_FPmode)
05551 {
05552 code = reverse_condition (code);
05553 code_true = EQ;
05554 code_false = NE;
05555 }
05556 else
05557 {
05558 code_true = NE;
05559 code_false = EQ;
05560 }
05561
05562 check_insn = gen_rtx_SET (VOIDmode, cr,
05563 gen_rtx_fmt_ee (code, CC_CCRmode, cc, const0_rtx));
05564
05565
05566 frv_ifcvt_add_insn (check_insn, BB_END (test_bb), TRUE);
05567
05568
05569 frv_ifcvt.cr_reg = cr;
05570 frv_ifcvt.nested_cc_reg = nested_cc;
05571 *p_true = gen_rtx_fmt_ee (code_true, CC_CCRmode, cr, const0_rtx);
05572 *p_false = gen_rtx_fmt_ee (code_false, CC_CCRmode, cr, const0_rtx);
05573 return;
05574
05575
05576 fail:
05577 *p_true = NULL_RTX;
05578 *p_false = NULL_RTX;
05579 if (dump_file)
05580 fprintf (dump_file, "Disabling this conditional execution.\n");
05581
05582 return;
05583 }
05584
05585
05586
05587
05588
05589
05590
05591
05592
05593
05594
05595
05596
05597
05598
05599 void
05600 frv_ifcvt_modify_multiple_tests (ce_if_block_t *ce_info,
05601 basic_block bb,
05602 rtx *p_true,
05603 rtx *p_false)
05604 {
05605 rtx old_true = XEXP (*p_true, 0);
05606 rtx old_false = XEXP (*p_false, 0);
05607 rtx true_expr = XEXP (*p_true, 1);
05608 rtx false_expr = XEXP (*p_false, 1);
05609 rtx test_expr;
05610 rtx old_test;
05611 rtx cr = XEXP (old_true, 0);
05612 rtx check_insn;
05613 rtx new_cr = NULL_RTX;
05614 rtx *p_new_cr = (rtx *)0;
05615 rtx if_else;
05616 rtx compare;
05617 rtx cc;
05618 enum reg_class cr_class;
05619 enum machine_mode mode = GET_MODE (true_expr);
05620 rtx (*logical_func)(rtx, rtx, rtx);
05621
05622 if (TARGET_DEBUG_COND_EXEC)
05623 {
05624 fprintf (stderr,
05625 "\n:::::::::: frv_ifcvt_modify_multiple_tests, before modification for %s\ntrue insn:\n",
05626 ce_info->and_and_p ? "&&" : "||");
05627
05628 debug_rtx (*p_true);
05629
05630 fputs ("\nfalse insn:\n", stderr);
05631 debug_rtx (*p_false);
05632 }
05633
05634 if (!TARGET_MULTI_CE)
05635 goto fail;
05636
05637 if (GET_CODE (cr) != REG)
05638 goto fail;
05639
05640 if (mode == CCmode || mode == CC_UNSmode || mode == CC_NZmode)
05641 {
05642 cr_class = ICR_REGS;
05643 p_new_cr = &frv_ifcvt.extra_int_cr;
05644 }
05645 else if (mode == CC_FPmode)
05646 {
05647 cr_class = FCR_REGS;
05648 p_new_cr = &frv_ifcvt.extra_fp_cr;
05649 }
05650 else
05651 goto fail;
05652
05653
05654
05655 new_cr = *p_new_cr;
05656 if (! new_cr)
05657 {
05658 new_cr = *p_new_cr = frv_alloc_temp_reg (&frv_ifcvt.tmp_reg, cr_class,
05659 CC_CCRmode, TRUE, TRUE);
05660 if (! new_cr)
05661 goto fail;
05662 }
05663
05664 if (ce_info->and_and_p)
05665 {
05666 old_test = old_false;
05667 test_expr = true_expr;
05668 logical_func = (GET_CODE (old_true) == EQ) ? gen_andcr : gen_andncr;
05669 *p_true = gen_rtx_NE (CC_CCRmode, cr, const0_rtx);
05670 *p_false = gen_rtx_EQ (CC_CCRmode, cr, const0_rtx);
05671 }
05672 else
05673 {
05674 old_test = old_false;
05675 test_expr = false_expr;
05676 logical_func = (GET_CODE (old_false) == EQ) ? gen_orcr : gen_orncr;
05677 *p_true = gen_rtx_EQ (CC_CCRmode, cr, const0_rtx);
05678 *p_false = gen_rtx_NE (CC_CCRmode, cr, const0_rtx);
05679 }
05680
05681
05682
05683
05684 frv_ifcvt_add_insn ((*logical_func) (cr, cr, new_cr), BB_END (bb), TRUE);
05685
05686
05687 cc = XEXP (test_expr, 0);
05688 compare = gen_rtx_fmt_ee (GET_CODE (test_expr), CC_CCRmode, cc, const0_rtx);
05689 if_else = gen_rtx_IF_THEN_ELSE (CC_CCRmode, old_test, compare, const0_rtx);
05690
05691 check_insn = gen_rtx_SET (VOIDmode, new_cr, if_else);
05692
05693
05694
05695 frv_ifcvt_add_insn (check_insn, BB_END (bb), TRUE);
05696
05697 if (TARGET_DEBUG_COND_EXEC)
05698 {
05699 fputs ("\n:::::::::: frv_ifcvt_modify_multiple_tests, after modification\ntrue insn:\n",
05700 stderr);
05701
05702 debug_rtx (*p_true);
05703
05704 fputs ("\nfalse insn:\n", stderr);
05705 debug_rtx (*p_false);
05706 }
05707
05708 return;
05709
05710 fail:
05711 *p_true = *p_false = NULL_RTX;
05712
05713
05714 if (new_cr)
05715 {
05716 CLEAR_HARD_REG_BIT (frv_ifcvt.tmp_reg.regs, REGNO (new_cr));
05717 *p_new_cr = NULL_RTX;
05718 }
05719
05720 if (TARGET_DEBUG_COND_EXEC)
05721 fputs ("\n:::::::::: frv_ifcvt_modify_multiple_tests, failed.\n", stderr);
05722
05723 return;
05724 }
05725
05726
05727
05728
05729
05730
05731 static rtx
05732 frv_ifcvt_load_value (rtx value, rtx insn ATTRIBUTE_UNUSED)
05733 {
05734 int num_alloc = frv_ifcvt.cur_scratch_regs;
05735 int i;
05736 rtx reg;
05737
05738
05739 if (value == const0_rtx)
05740 return gen_rtx_REG (SImode, GPR_FIRST);
05741
05742
05743
05744 if (CONSTANT_P (value)
05745 || (GET_CODE (value) == REG && REGNO (value) == LR_REGNO))
05746 {
05747 for (i = 0; i < num_alloc; i++)
05748 {
05749 if (rtx_equal_p (SET_SRC (frv_ifcvt.scratch_regs[i]), value))
05750 return SET_DEST (frv_ifcvt.scratch_regs[i]);
05751 }
05752 }
05753
05754
05755 if (num_alloc >= GPR_TEMP_NUM)
05756 {
05757 if (dump_file)
05758 fprintf (dump_file, "Too many temporary registers allocated\n");
05759
05760 return NULL_RTX;
05761 }
05762
05763
05764 reg = frv_alloc_temp_reg (&frv_ifcvt.tmp_reg, GPR_REGS, SImode, TRUE, TRUE);
05765 if (! reg)
05766 {
05767 if (dump_file)
05768 fputs ("Could not find a scratch register\n", dump_file);
05769
05770 return NULL_RTX;
05771 }
05772
05773 frv_ifcvt.cur_scratch_regs++;
05774 frv_ifcvt.scratch_regs[num_alloc] = gen_rtx_SET (VOIDmode, reg, value);
05775
05776 if (dump_file)
05777 {
05778 if (GET_CODE (value) == CONST_INT)
05779 fprintf (dump_file, "Register %s will hold %ld\n",
05780 reg_names[ REGNO (reg)], (long)INTVAL (value));
05781
05782 else if (GET_CODE (value) == REG && REGNO (value) == LR_REGNO)
05783 fprintf (dump_file, "Register %s will hold LR\n",
05784 reg_names[ REGNO (reg)]);
05785
05786 else
05787 fprintf (dump_file, "Register %s will hold a saved value\n",
05788 reg_names[ REGNO (reg)]);
05789 }
05790
05791 return reg;
05792 }
05793
05794
05795
05796
05797
05798
05799
05800
05801 static rtx
05802 frv_ifcvt_rewrite_mem (rtx mem, enum machine_mode mode, rtx insn)
05803 {
05804 rtx addr = XEXP (mem, 0);
05805
05806 if (!frv_legitimate_address_p (mode, addr, reload_completed, TRUE, FALSE))
05807 {
05808 if (GET_CODE (addr) == PLUS)
05809 {
05810 rtx addr_op0 = XEXP (addr, 0);
05811 rtx addr_op1 = XEXP (addr, 1);
05812
05813 if (GET_CODE (addr_op0) == REG && CONSTANT_P (addr_op1))
05814 {
05815 rtx reg = frv_ifcvt_load_value (addr_op1, insn);
05816 if (!reg)
05817 return NULL_RTX;
05818
05819 addr = gen_rtx_PLUS (Pmode, addr_op0, reg);
05820 }
05821
05822 else
05823 return NULL_RTX;
05824 }
05825
05826 else if (CONSTANT_P (addr))
05827 addr = frv_ifcvt_load_value (addr, insn);
05828
05829 else
05830 return NULL_RTX;
05831
05832 if (addr == NULL_RTX)
05833 return NULL_RTX;
05834
05835 else if (XEXP (mem, 0) != addr)
05836 return change_address (mem, mode, addr);
05837 }
05838
05839 return mem;
05840 }
05841
05842
05843
05844
05845
05846 static rtx
05847 single_set_pattern (rtx pattern)
05848 {
05849 rtx set;
05850 int i;
05851
05852 if (GET_CODE (pattern) == COND_EXEC)
05853 pattern = COND_EXEC_CODE (pattern);
05854
05855 if (GET_CODE (pattern) == SET)
05856 return pattern;
05857
05858 else if (GET_CODE (pattern) == PARALLEL)
05859 {
05860 for (i = 0, set = 0; i < XVECLEN (pattern, 0); i++)
05861 {
05862 rtx sub = XVECEXP (pattern, 0, i);
05863
05864 switch (GET_CODE (sub))
05865 {
05866 case USE:
05867 case CLOBBER:
05868 break;
05869
05870 case SET:
05871 if (set)
05872 return 0;
05873 else
05874 set = sub;
05875 break;
05876
05877 default:
05878 return 0;
05879 }
05880 }
05881 return set;
05882 }
05883
05884 return 0;
05885 }
05886
05887
05888
05889
05890
05891
05892
05893 rtx
05894 frv_ifcvt_modify_insn (ce_if_block_t *ce_info,
05895 rtx pattern,
05896 rtx insn)
05897 {
05898 rtx orig_ce_pattern = pattern;
05899 rtx set;
05900 rtx op0;
05901 rtx op1;
05902 rtx test;
05903
05904 gcc_assert (GET_CODE (pattern) == COND_EXEC);
05905
05906 test = COND_EXEC_TEST (pattern);
05907 if (GET_CODE (test) == AND)
05908 {
05909 rtx cr = frv_ifcvt.cr_reg;
05910 rtx test_reg;
05911
05912 op0 = XEXP (test, 0);
05913 if (! rtx_equal_p (cr, XEXP (op0, 0)))
05914 goto fail;
05915
05916 op1 = XEXP (test, 1);
05917 test_reg = XEXP (op1, 0);
05918 if (GET_CODE (test_reg) != REG)
05919 goto fail;
05920
05921
05922
05923 if (! frv_ifcvt.last_nested_if_cr)
05924 {
05925 rtx and_op;
05926
05927 frv_ifcvt.last_nested_if_cr = test_reg;
05928 if (GET_CODE (op0) == NE)
05929 and_op = gen_andcr (test_reg, cr, test_reg);
05930 else
05931 and_op = gen_andncr (test_reg, cr, test_reg);
05932
05933 frv_ifcvt_add_insn (and_op, insn, TRUE);
05934 }
05935
05936
05937
05938 else if (! rtx_equal_p (test_reg, frv_ifcvt.last_nested_if_cr))
05939 goto fail;
05940
05941 COND_EXEC_TEST (pattern) = test = op1;
05942 }
05943
05944
05945 else
05946 {
05947 frv_ifcvt.last_nested_if_cr = NULL_RTX;
05948 }
05949
05950 set = single_set_pattern (pattern);
05951 if (set)
05952 {
05953 rtx dest = SET_DEST (set);
05954 rtx src = SET_SRC (set);
05955 enum machine_mode mode = GET_MODE (dest);
05956
05957
05958 if (mode == SImode && ARITHMETIC_P (src))
05959 {
05960 op0 = XEXP (src, 0);
05961 op1 = XEXP (src, 1);
05962
05963 if (integer_register_operand (op0, SImode) && CONSTANT_P (op1))
05964 {
05965 op1 = frv_ifcvt_load_value (op1, insn);
05966 if (op1)
05967 COND_EXEC_CODE (pattern)
05968 = gen_rtx_SET (VOIDmode, dest, gen_rtx_fmt_ee (GET_CODE (src),
05969 GET_MODE (src),
05970 op0, op1));
05971 else
05972 goto fail;
05973 }
05974 }
05975
05976
05977
05978
05979 else if (mode == DImode && GET_CODE (src) == MULT)
05980 {
05981 op0 = XEXP (src, 0);
05982 op1 = XEXP (src, 1);
05983 if (GET_CODE (op0) == SIGN_EXTEND && GET_CODE (op1) == CONST_INT)
05984 {
05985 op1 = frv_ifcvt_load_value (op1, insn);
05986 if (op1)
05987 {
05988 op1 = gen_rtx_SIGN_EXTEND (DImode, op1);
05989 COND_EXEC_CODE (pattern)
05990 = gen_rtx_SET (VOIDmode, dest,
05991 gen_rtx_MULT (DImode, op0, op1));
05992 }
05993 else
05994 goto fail;
05995 }
05996
05997 frv_ifcvt_add_insn (gen_rtx_USE (VOIDmode, dest), insn, FALSE);
05998 }
05999
06000
06001
06002
06003
06004 else if (frv_ifcvt.scratch_insns_bitmap
06005 && bitmap_bit_p (frv_ifcvt.scratch_insns_bitmap,
06006 INSN_UID (insn))
06007 && REG_P (SET_DEST (set))
06008
06009
06010
06011
06012
06013
06014
06015
06016
06017
06018
06019
06020
06021
06022 && ce_info->join_bb
06023 && ! (REGNO_REG_SET_P
06024 (ce_info->join_bb->il.rtl->global_live_at_start,
06025 REGNO (SET_DEST (set))))
06026
06027
06028
06029 && (! ce_info->else_bb
06030 || BLOCK_FOR_INSN (insn) == ce_info->else_bb
06031 || ! (REGNO_REG_SET_P
06032 (ce_info->else_bb->il.rtl->global_live_at_start,
06033 REGNO (SET_DEST (set))))))
06034 pattern = set;
06035
06036 else if (mode == QImode || mode == HImode || mode == SImode
06037 || mode == SFmode)
06038 {
06039 int changed_p = FALSE;
06040
06041
06042 if (CONSTANT_P (src) && integer_register_operand (dest, mode))
06043 {
06044 src = frv_ifcvt_load_value (src, insn);
06045 if (!src)
06046 goto fail;
06047
06048 changed_p = TRUE;
06049 }
06050
06051
06052 if (GET_CODE (dest) == MEM)
06053 {
06054 rtx new_mem = frv_ifcvt_rewrite_mem (dest, mode, insn);
06055
06056 if (!new_mem)
06057 goto fail;
06058
06059 else if (new_mem != dest)
06060 {
06061 changed_p = TRUE;
06062 dest = new_mem;
06063 }
06064 }
06065
06066
06067 if (GET_CODE (src) == MEM)
06068 {
06069 rtx new_mem = frv_ifcvt_rewrite_mem (src, mode, insn);
06070
06071 if (!new_mem)
06072 goto fail;
06073
06074 else if (new_mem != src)
06075 {
06076 changed_p = TRUE;
06077 src = new_mem;
06078 }
06079 }
06080
06081
06082 if (changed_p)
06083 COND_EXEC_CODE (pattern) = gen_rtx_SET (VOIDmode, dest, src);
06084 }
06085
06086
06087
06088
06089 else if (mode == CC_CCRmode && COMPARISON_P (src))
06090 {
06091 int regno = REGNO (XEXP (src, 0));
06092 rtx if_else;
06093
06094 if (ce_info->pass > 1
06095 && regno != (int)REGNO (frv_ifcvt.nested_cc_reg)
06096 && TEST_HARD_REG_BIT (frv_ifcvt.nested_cc_ok_rewrite, regno))
06097 {
06098 src = gen_rtx_fmt_ee (GET_CODE (src),
06099 CC_CCRmode,
06100 frv_ifcvt.nested_cc_reg,
06101 XEXP (src, 1));
06102 }
06103
06104 if_else = gen_rtx_IF_THEN_ELSE (CC_CCRmode, test, src, const0_rtx);
06105 pattern = gen_rtx_SET (VOIDmode, dest, if_else);
06106 }
06107
06108
06109 else if (ce_info->pass > 1
06110 && GET_CODE (dest) == REG
06111 && CC_P (REGNO (dest))
06112 && REGNO (dest) != REGNO (frv_ifcvt.nested_cc_reg)
06113 && TEST_HARD_REG_BIT (frv_ifcvt.nested_cc_ok_rewrite,
06114 REGNO (dest))
06115 && GET_CODE (src) == COMPARE)
06116 {
06117 PUT_MODE (frv_ifcvt.nested_cc_reg, GET_MODE (dest));
06118 COND_EXEC_CODE (pattern)
06119 = gen_rtx_SET (VOIDmode, frv_ifcvt.nested_cc_reg, copy_rtx (src));
06120 }
06121 }
06122
06123 if (TARGET_DEBUG_COND_EXEC)
06124 {
06125 rtx orig_pattern = PATTERN (insn);
06126
06127 PATTERN (insn) = pattern;
06128 fprintf (stderr,
06129 "\n:::::::::: frv_ifcvt_modify_insn: pass = %d, insn after modification:\n",
06130 ce_info->pass);
06131
06132 debug_rtx (insn);
06133 PATTERN (insn) = orig_pattern;
06134 }
06135
06136 return pattern;
06137
06138 fail:
06139 if (TARGET_DEBUG_COND_EXEC)
06140 {
06141 rtx orig_pattern = PATTERN (insn);
06142
06143 PATTERN (insn) = orig_ce_pattern;
06144 fprintf (stderr,
06145 "\n:::::::::: frv_ifcvt_modify_insn: pass = %d, insn could not be modified:\n",
06146 ce_info->pass);
06147
06148 debug_rtx (insn);
06149 PATTERN (insn) = orig_pattern;
06150 }
06151
06152 return NULL_RTX;
06153 }
06154
06155
06156
06157
06158
06159
06160 void
06161 frv_ifcvt_modify_final (ce_if_block_t *ce_info ATTRIBUTE_UNUSED)
06162 {
06163 rtx existing_insn;
06164 rtx check_insn;
06165 rtx p = frv_ifcvt.added_insns_list;
06166 int i;
06167
06168
06169
06170 gcc_assert (p);
06171
06172 do
06173 {
06174 rtx check_and_insert_insns = XEXP (p, 0);
06175 rtx old_p = p;
06176
06177 check_insn = XEXP (check_and_insert_insns, 0);
06178 existing_insn = XEXP (check_and_insert_insns, 1);
06179 p = XEXP (p, 1);
06180
06181
06182
06183 if (check_and_insert_insns->jump)
06184 {
06185 emit_insn_before (check_insn, existing_insn);
06186 check_and_insert_insns->jump = 0;
06187 }
06188 else
06189 emit_insn_after (check_insn, existing_insn);
06190
06191 free_EXPR_LIST_node (check_and_insert_insns);
06192 free_EXPR_LIST_node (old_p);
06193 }
06194 while (p != NULL_RTX);
06195
06196
06197 for (i = 0; i < frv_ifcvt.cur_scratch_regs; i++)
06198 {
06199 rtx insn = emit_insn_before (frv_ifcvt.scratch_regs[i], existing_insn);
06200 if (! frv_ifcvt.scratch_insns_bitmap)
06201 frv_ifcvt.scratch_insns_bitmap = BITMAP_ALLOC (NULL);
06202 bitmap_set_bit (frv_ifcvt.scratch_insns_bitmap, INSN_UID (insn));
06203 frv_ifcvt.scratch_regs[i] = NULL_RTX;
06204 }
06205
06206 frv_ifcvt.added_insns_list = NULL_RTX;
06207 frv_ifcvt.cur_scratch_regs = 0;
06208 }
06209
06210
06211
06212
06213
06214
06215 void
06216 frv_ifcvt_modify_cancel (ce_if_block_t *ce_info ATTRIBUTE_UNUSED)
06217 {
06218 int i;
06219 rtx p = frv_ifcvt.added_insns_list;
06220
06221
06222 while (p != NULL_RTX)
06223 {
06224 rtx check_and_jump = XEXP (p, 0);
06225 rtx old_p = p;
06226
06227 p = XEXP (p, 1);
06228 free_EXPR_LIST_node (check_and_jump);
06229 free_EXPR_LIST_node (old_p);
06230 }
06231
06232
06233 for (i = 0; i < frv_ifcvt.cur_scratch_regs; i++)
06234 frv_ifcvt.scratch_regs[i] = NULL_RTX;
06235
06236 frv_ifcvt.added_insns_list = NULL_RTX;
06237 frv_ifcvt.cur_scratch_regs = 0;
06238 return;
06239 }
06240
06241
06242
06243
06244
06245
06246
06247
06248
06249
06250 int
06251 frv_trampoline_size (void)
06252 {
06253 if (TARGET_FDPIC)
06254
06255
06256 return 8 + 6 * 4;
06257 return 5 * 4 ;
06258 }
06259
06260
06261
06262
06263
06264
06265
06266
06267
06268
06269
06270
06271
06272
06273
06274 void
06275 frv_initialize_trampoline (rtx addr, rtx fnaddr, rtx static_chain)
06276 {
06277 rtx sc_reg = force_reg (Pmode, static_chain);
06278
06279 emit_library_call (gen_rtx_SYMBOL_REF (SImode, "__trampoline_setup"),
06280 FALSE, VOIDmode, 4,
06281 addr, Pmode,
06282 GEN_INT (frv_trampoline_size ()), SImode,
06283 fnaddr, Pmode,
06284 sc_reg, Pmode);
06285 }
06286
06287
06288
06289
06290
06291
06292
06293
06294
06295
06296
06297
06298
06299
06300
06301
06302
06303
06304
06305
06306
06307
06308
06309
06310
06311
06312
06313
06314
06315
06316
06317
06318
06319
06320
06321
06322
06323
06324
06325
06326
06327
06328
06329
06330
06331
06332
06333
06334
06335
06336
06337
06338
06339
06340 enum reg_class
06341 frv_secondary_reload_class (enum reg_class class,
06342 enum machine_mode mode ATTRIBUTE_UNUSED,
06343 rtx x,
06344 int in_p ATTRIBUTE_UNUSED)
06345 {
06346 enum reg_class ret;
06347
06348 switch (class)
06349 {
06350 default:
06351 ret = NO_REGS;
06352 break;
06353
06354
06355
06356 case QUAD_REGS:
06357 case EVEN_REGS:
06358 case GPR_REGS:
06359 ret = NO_REGS;
06360 if (x && GET_CODE (x) == REG)
06361 {
06362 int regno = REGNO (x);
06363
06364 if (ACC_P (regno) || ACCG_P (regno))
06365 ret = FPR_REGS;
06366 }
06367 break;
06368
06369
06370 case QUAD_FPR_REGS:
06371 case FEVEN_REGS:
06372 case FPR_REGS:
06373 if (x && CONSTANT_P (x) && !ZERO_P (x))
06374 ret = GPR_REGS;
06375 else
06376 ret = NO_REGS;
06377 break;
06378
06379
06380 case ICC_REGS:
06381 case FCC_REGS:
06382 case CC_REGS:
06383 case ICR_REGS:
06384 case FCR_REGS:
06385 case CR_REGS:
06386 case LCR_REG:
06387 case LR_REG:
06388 ret = GPR_REGS;
06389 break;
06390
06391
06392 case ACC_REGS:
06393 case EVEN_ACC_REGS:
06394 case QUAD_ACC_REGS:
06395 case ACCG_REGS:
06396 ret = FPR_REGS;
06397 break;
06398 }
06399
06400 return ret;
06401 }
06402
06403
06404
06405
06406
06407
06408
06409
06410
06411
06412
06413
06414
06415
06416
06417
06418
06419 int
06420 frv_class_likely_spilled_p (enum reg_class class)
06421 {
06422 switch (class)
06423 {
06424 default:
06425 break;
06426
06427 case GR8_REGS:
06428 case GR9_REGS:
06429 case GR89_REGS:
06430 case FDPIC_FPTR_REGS:
06431 case FDPIC_REGS:
06432 case ICC_REGS:
06433 case FCC_REGS:
06434 case CC_REGS:
06435 case ICR_REGS:
06436 case FCR_REGS:
06437 case CR_REGS:
06438 case LCR_REG:
06439 case LR_REG:
06440 case SPR_REGS:
06441 case QUAD_ACC_REGS:
06442 case EVEN_ACC_REGS:
06443 case ACC_REGS:
06444 case ACCG_REGS:
06445 return TRUE;
06446 }
06447
06448 return FALSE;
06449 }
06450
06451
06452
06453
06454
06455
06456
06457
06458
06459
06460
06461
06462
06463
06464
06465
06466
06467
06468
06469
06470
06471
06472
06473
06474
06475
06476
06477
06478
06479
06480
06481
06482
06483
06484
06485
06486
06487
06488
06489
06490
06491
06492
06493
06494
06495
06496
06497
06498
06499 int
06500 frv_adjust_field_align (tree field, int computed)
06501 {
06502
06503 if (DECL_BIT_FIELD (field)
06504 && !DECL_ARTIFICIAL (field))
06505 {
06506 tree parent = DECL_CONTEXT (field);
06507 tree prev = NULL_TREE;
06508 tree cur;
06509
06510 for (cur = TYPE_FIELDS (parent); cur && cur != field; cur = TREE_CHAIN (cur))
06511 {
06512 if (TREE_CODE (cur) != FIELD_DECL)
06513 continue;
06514
06515 prev = cur;
06516 }
06517
06518 gcc_assert (cur);
06519
06520
06521
06522
06523 if (prev
06524 && ! DECL_PACKED (field)
06525 && ! integer_zerop (DECL_SIZE (field))
06526 && DECL_BIT_FIELD_TYPE (field) != DECL_BIT_FIELD_TYPE (prev))
06527 {
06528 int prev_align = TYPE_ALIGN (TREE_TYPE (prev));
06529 int cur_align = TYPE_ALIGN (TREE_TYPE (field));
06530 computed = (prev_align > cur_align) ? prev_align : cur_align;
06531 }
06532 }
06533
06534 return computed;
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
06560
06561
06562
06563
06564
06565
06566
06567
06568
06569
06570
06571
06572
06573
06574
06575
06576
06577
06578
06579
06580
06581
06582
06583
06584
06585
06586
06587
06588
06589
06590
06591
06592 int
06593 frv_hard_regno_mode_ok (int regno, enum machine_mode mode)
06594 {
06595 int base;
06596 int mask;
06597
06598 switch (mode)
06599 {
06600 case CCmode:
06601 case CC_UNSmode:
06602 case CC_NZmode:
06603 return ICC_P (regno) || GPR_P (regno);
06604
06605 case CC_CCRmode:
06606 return CR_P (regno) || GPR_P (regno);
06607
06608 case CC_FPmode:
06609 return FCC_P (regno) || GPR_P (regno);
06610
06611 default:
06612 break;
06613 }
06614
06615
06616
06617
06618 if (INTEGRAL_MODE_P (mode) || FLOAT_MODE_P (mode) || VECTOR_MODE_P (mode))
06619 {
06620 if (ACCG_P (regno))
06621 {
06622
06623
06624
06625 base = ACCG_FIRST;
06626 mask = GET_MODE_SIZE (mode) - 1;
06627 }
06628 else
06629 {
06630
06631 if (GPR_P (regno) || regno == AP_FIRST)
06632 base = GPR_FIRST;
06633
06634 else if (FPR_P (regno))
06635 base = FPR_FIRST;
06636
06637 else if (ACC_P (regno))
06638 base = ACC_FIRST;
06639
06640 else if (SPR_P (regno))
06641 return mode == SImode;
06642
06643
06644 else
06645 return 0;
06646
06647
06648 if (GET_MODE_SIZE (mode) < 4)
06649 return 1;
06650
06651 mask = (GET_MODE_SIZE (mode) / 4) - 1;
06652 }
06653 return (((regno - base) & mask) == 0);
06654 }
06655
06656 return 0;
06657 }
06658
06659
06660
06661
06662
06663
06664
06665
06666
06667
06668
06669
06670
06671
06672
06673
06674
06675 int
06676 frv_hard_regno_nregs (int regno, enum machine_mode mode)
06677 {
06678 if (ACCG_P (regno))
06679 return GET_MODE_SIZE (mode);
06680 else
06681 return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
06682 }
06683
06684
06685
06686
06687
06688
06689
06690
06691
06692
06693
06694
06695
06696
06697 int
06698 frv_class_max_nregs (enum reg_class class, enum machine_mode mode)
06699 {
06700 if (class == ACCG_REGS)
06701
06702 return GET_MODE_SIZE (mode);
06703 else
06704 return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
06705 }
06706
06707
06708
06709
06710
06711
06712
06713 int
06714 frv_legitimate_constant_p (rtx x)
06715 {
06716 enum machine_mode mode = GET_MODE (x);
06717
06718
06719
06720
06721
06722
06723
06724
06725
06726
06727
06728
06729
06730
06731 if (TARGET_FDPIC)
06732 return LEGITIMATE_PIC_OPERAND_P (x);
06733
06734
06735 if (GET_CODE (x) != CONST_DOUBLE)
06736 return TRUE;
06737
06738
06739 if (mode == VOIDmode || mode == DImode)
06740 return TRUE;
06741
06742
06743 if (x == CONST0_RTX (mode))
06744 return TRUE;
06745
06746
06747
06748 if (!TARGET_HAS_FPRS)
06749 return TRUE;
06750
06751 if (mode == DFmode && !TARGET_DOUBLE)
06752 return TRUE;
06753
06754
06755 return FALSE;
06756 }
06757
06758
06759
06760
06761
06762
06763 enum machine_mode
06764 frv_select_cc_mode (enum rtx_code code, rtx x, rtx y)
06765 {
06766 if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
06767 return CC_FPmode;
06768
06769 switch (code)
06770 {
06771 case EQ:
06772 case NE:
06773 case LT:
06774 case GE:
06775 return y == const0_rtx ? CC_NZmode : CCmode;
06776
06777 case GTU:
06778 case GEU:
06779 case LTU:
06780 case LEU:
06781 return y == const0_rtx ? CC_NZmode : CC_UNSmode;
06782
06783 default:
06784 return CCmode;
06785 }
06786 }
06787
06788
06789
06790
06791
06792
06793
06794
06795
06796
06797
06798
06799
06800
06801
06802
06803
06804 #define HIGH_COST 40
06805 #define MEDIUM_COST 3
06806 #define LOW_COST 1
06807
06808 int
06809 frv_register_move_cost (enum reg_class from, enum reg_class to)
06810 {
06811 switch (from)
06812 {
06813 default:
06814 break;
06815
06816 case QUAD_REGS:
06817 case EVEN_REGS:
06818 case GPR_REGS:
06819 switch (to)
06820 {
06821 default:
06822 break;
06823
06824 case QUAD_REGS:
06825 case EVEN_REGS:
06826 case GPR_REGS:
06827 return LOW_COST;
06828
06829 case FEVEN_REGS:
06830 case FPR_REGS:
06831 return LOW_COST;
06832
06833 case LCR_REG:
06834 case LR_REG:
06835 case SPR_REGS:
06836 return LOW_COST;
06837 }
06838
06839 case FEVEN_REGS:
06840 case FPR_REGS:
06841 switch (to)
06842 {
06843 default:
06844 break;
06845
06846 case QUAD_REGS:
06847 case EVEN_REGS:
06848 case GPR_REGS:
06849 case ACC_REGS:
06850 case EVEN_ACC_REGS:
06851 case QUAD_ACC_REGS:
06852 case ACCG_REGS:
06853 return MEDIUM_COST;
06854
06855 case FEVEN_REGS:
06856 case FPR_REGS:
06857 return LOW_COST;
06858 }
06859
06860 case LCR_REG:
06861 case LR_REG:
06862 case SPR_REGS:
06863 switch (to)
06864 {
06865 default:
06866 break;
06867
06868 case QUAD_REGS:
06869 case EVEN_REGS:
06870 case GPR_REGS:
06871 return MEDIUM_COST;
06872 }
06873
06874 case ACC_REGS:
06875 case EVEN_ACC_REGS:
06876 case QUAD_ACC_REGS:
06877 case ACCG_REGS:
06878 switch (to)
06879 {
06880 default:
06881 break;
06882
06883 case FEVEN_REGS:
06884 case FPR_REGS:
06885 return MEDIUM_COST;
06886
06887 }
06888 }
06889
06890 return HIGH_COST;
06891 }
06892
06893
06894
06895
06896
06897 static bool
06898 frv_assemble_integer (rtx value, unsigned int size, int aligned_p)
06899 {
06900 if ((flag_pic || TARGET_FDPIC) && size == UNITS_PER_WORD)
06901 {
06902 if (GET_CODE (value) == CONST
06903 || GET_CODE (value) == SYMBOL_REF
06904 || GET_CODE (value) == LABEL_REF)
06905 {
06906 if (TARGET_FDPIC && GET_CODE (value) == SYMBOL_REF
06907 && SYMBOL_REF_FUNCTION_P (value))
06908 {
06909 fputs ("\t.picptr\tfuncdesc(", asm_out_file);
06910 output_addr_const (asm_out_file, value);
06911 fputs (")\n", asm_out_file);
06912 return true;
06913 }
06914 else if (TARGET_FDPIC && GET_CODE (value) == CONST
06915 && frv_function_symbol_referenced_p (value))
06916 return false;
06917 if (aligned_p && !TARGET_FDPIC)
06918 {
06919 static int label_num = 0;
06920 char buf[256];
06921 const char *p;
06922
06923 ASM_GENERATE_INTERNAL_LABEL (buf, "LCP", label_num++);
06924 p = (* targetm.strip_name_encoding) (buf);
06925
06926 fprintf (asm_out_file, "%s:\n", p);
06927 fprintf (asm_out_file, "%s\n", FIXUP_SECTION_ASM_OP);
06928 fprintf (asm_out_file, "\t.picptr\t%s\n", p);
06929 fprintf (asm_out_file, "\t.previous\n");
06930 }
06931 assemble_integer_with_op ("\t.picptr\t", value);
06932 return true;
06933 }
06934 if (!aligned_p)
06935 {
06936
06937
06938 assemble_integer_with_op ("\t.4byte\t", value);
06939 return true;
06940 }
06941 }
06942 return default_assemble_integer (value, size, aligned_p);
06943 }
06944
06945
06946
06947 static struct machine_function *
06948 frv_init_machine_status (void)
06949 {
06950 return ggc_alloc_cleared (sizeof (struct machine_function));
06951 }
06952
06953
06954
06955 int
06956 frv_issue_rate (void)
06957 {
06958 if (!TARGET_PACK)
06959 return 1;
06960
06961 switch (frv_cpu_type)
06962 {
06963 default:
06964 case FRV_CPU_FR300:
06965 case FRV_CPU_SIMPLE:
06966 return 1;
06967
06968 case FRV_CPU_FR400:
06969 case FRV_CPU_FR405:
06970 case FRV_CPU_FR450:
06971 return 2;
06972
06973 case FRV_CPU_GENERIC:
06974 case FRV_CPU_FR500:
06975 case FRV_CPU_TOMCAT:
06976 return 4;
06977
06978 case FRV_CPU_FR550:
06979 return 8;
06980 }
06981 }
06982
06983
06984
06985
06986
06987
06988 static int
06989 frv_acc_group_1 (rtx *x, void *data ATTRIBUTE_UNUSED)
06990 {
06991 if (REG_P (*x))
06992 {
06993 if (ACC_P (REGNO (*x)))
06994 return (REGNO (*x) - ACC_FIRST) & 4 ? ACC_GROUP_ODD : ACC_GROUP_EVEN;
06995 if (ACCG_P (REGNO (*x)))
06996 return (REGNO (*x) - ACCG_FIRST) & 4 ? ACC_GROUP_ODD : ACC_GROUP_EVEN;
06997 }
06998 return 0;
06999 }
07000
07001
07002
07003 int
07004 frv_acc_group (rtx insn)
07005 {
07006
07007 if (frv_cpu_type != FRV_CPU_FR550)
07008 return ACC_GROUP_NONE;
07009 return for_each_rtx (&PATTERN (insn), frv_acc_group_1, 0);
07010 }
07011
07012
07013
07014
07015
07016 static unsigned int
07017 frv_insn_unit (rtx insn)
07018 {
07019 enum attr_type type;
07020
07021 type = get_attr_type (insn);
07022 if (frv_type_to_unit[type] == ARRAY_SIZE (frv_unit_codes))
07023 {
07024
07025 state_t state;
07026 unsigned int unit;
07027
07028
07029 state = alloca (state_size ());
07030 state_reset (state);
07031 state_transition (state, insn);
07032
07033
07034 for (unit = 0; unit < ARRAY_SIZE (frv_unit_codes); unit++)
07035 if (cpu_unit_reservation_p (state, frv_unit_codes[unit]))
07036 break;
07037
07038 gcc_assert (unit != ARRAY_SIZE (frv_unit_codes));
07039
07040 frv_type_to_unit[type] = unit;
07041 }
07042 return frv_type_to_unit[type];
07043 }
07044
07045
07046
07047 static bool
07048 frv_issues_to_branch_unit_p (rtx insn)
07049 {
07050 return frv_unit_groups[frv_insn_unit (insn)] == GROUP_B;
07051 }
07052
07053
07054 static struct {
07055
07056 state_t dfa_state;
07057
07058
07059
07060 regstate_t regstate[FIRST_PSEUDO_REGISTER];
07061
07062
07063
07064
07065 struct {
07066 rtx mem;
07067 regstate_t cond;
07068 } mems[2];
07069
07070
07071
07072 unsigned int num_mems;
07073
07074
07075 unsigned int issue_rate;
07076
07077
07078 struct frv_packet_group {
07079
07080 unsigned int num_insns;
07081
07082
07083
07084 rtx insns[ARRAY_SIZE (frv_unit_codes)];
07085
07086
07087
07088
07089 rtx sorted[ARRAY_SIZE (frv_unit_codes)];
07090
07091
07092 rtx nop;
07093 } groups[NUM_GROUPS];
07094
07095
07096 rtx insns[ARRAY_SIZE (frv_unit_codes)];
07097 unsigned int num_insns;
07098 } frv_packet;
07099
07100
07101
07102
07103 static int
07104 frv_cond_flags (rtx cond)
07105 {
07106 gcc_assert ((GET_CODE (cond) == EQ || GET_CODE (cond) == NE)
07107 && GET_CODE (XEXP (cond, 0)) == REG
07108 && CR_P (REGNO (XEXP (cond, 0)))
07109 && XEXP (cond, 1) == const0_rtx);
07110 return ((REGNO (XEXP (cond, 0)) - CR_FIRST)
07111 | (GET_CODE (cond) == NE
07112 ? REGSTATE_IF_TRUE
07113 : REGSTATE_IF_FALSE));
07114 }
07115
07116
07117
07118
07119
07120 static bool
07121 frv_regstate_conflict_p (regstate_t cond1, regstate_t cond2)
07122 {
07123
07124 if ((cond1 & REGSTATE_IF_EITHER) == 0
07125 || (cond2 & REGSTATE_IF_EITHER) == 0)
07126 return true;
07127
07128
07129
07130 if ((cond1 & REGSTATE_CC_MASK) != (cond2 & REGSTATE_CC_MASK))
07131 return true;
07132
07133
07134
07135 if ((cond1 & cond2 & REGSTATE_IF_EITHER) != 0)
07136 return true;
07137
07138 return false;
07139 }
07140
07141
07142
07143
07144
07145
07146 static int
07147 frv_registers_conflict_p_1 (rtx *x, void *data)
07148 {
07149 unsigned int regno, i;
07150 regstate_t cond;
07151
07152 cond = *(regstate_t *) data;
07153
07154 if (GET_CODE (*x) == REG)
07155 FOR_EACH_REGNO (regno, *x)
07156 if ((frv_packet.regstate[regno] & REGSTATE_MODIFIED) != 0)
07157 if (frv_regstate_conflict_p (frv_packet.regstate[regno], cond))
07158 return 1;
07159
07160 if (GET_CODE (*x) == MEM)
07161 {
07162
07163 if (frv_packet.num_mems > ARRAY_SIZE (frv_packet.mems))
07164 return 1;
07165
07166
07167 for (i = 0; i < frv_packet.num_mems; i++)
07168 if (frv_regstate_conflict_p (frv_packet.mems[i].cond, cond))
07169 {
07170 if (true_dependence (frv_packet.mems[i].mem, VOIDmode,
07171 *x, rtx_varies_p))
07172 return 1;
07173
07174 if (output_dependence (frv_packet.mems[i].mem, *x))
07175 return 1;
07176 }
07177 }
07178
07179
07180
07181 if (GET_CODE (*x) == SET && GET_CODE (SET_SRC (*x)) == CALL)
07182 {
07183 if (for_each_rtx (&SET_SRC (*x), frv_registers_conflict_p_1, data))
07184 return 1;
07185 return -1;
07186 }
07187
07188
07189 return 0;
07190 }
07191
07192
07193
07194
07195
07196 static bool
07197 frv_registers_conflict_p (rtx x)
07198 {
07199 regstate_t flags;
07200
07201 flags = 0;
07202 if (GET_CODE (x) == COND_EXEC)
07203 {
07204 if (for_each_rtx (&XEXP (x, 0), frv_registers_conflict_p_1, &flags))
07205 return true;
07206
07207 flags |= frv_cond_flags (XEXP (x, 0));
07208 x = XEXP (x, 1);
07209 }
07210 return for_each_rtx (&x, frv_registers_conflict_p_1, &flags);
07211 }
07212
07213
07214
07215
07216
07217 static void
07218 frv_registers_update_1 (rtx x, rtx pat ATTRIBUTE_UNUSED, void *data)
07219 {
07220 unsigned int regno;
07221
07222 if (GET_CODE (x) == REG)
07223 FOR_EACH_REGNO (regno, x)
07224 frv_packet.regstate[regno] |= *(regstate_t *) data;
07225
07226 if (GET_CODE (x) == MEM)
07227 {
07228 if (frv_packet.num_mems < ARRAY_SIZE (frv_packet.mems))
07229 {
07230 frv_packet.mems[frv_packet.num_mems].mem = x;
07231 frv_packet.mems[frv_packet.num_mems].cond = *(regstate_t *) data;
07232 }
07233 frv_packet.num_mems++;
07234 }
07235 }
07236
07237
07238
07239
07240
07241 static void
07242 frv_registers_update (rtx x)
07243 {
07244 regstate_t flags;
07245
07246 flags = REGSTATE_MODIFIED;
07247 if (GET_CODE (x) == COND_EXEC)
07248 {
07249 flags |= frv_cond_flags (XEXP (x, 0));
07250 x = XEXP (x, 1);
07251 }
07252 note_stores (x, frv_registers_update_1, &flags);
07253 }
07254
07255
07256
07257
07258 static void
07259 frv_start_packet (void)
07260 {
07261 enum frv_insn_group group;
07262
07263 memset (frv_packet.regstate, 0, sizeof (frv_packet.regstate));
07264 frv_packet.num_mems = 0;
07265 frv_packet.num_insns = 0;
07266 for (group = 0; group < NUM_GROUPS; group++)
07267 frv_packet.groups[group].num_insns = 0;
07268 }
07269
07270
07271
07272
07273 static void
07274 frv_start_packet_block (void)
07275 {
07276 state_reset (frv_packet.dfa_state);
07277 frv_start_packet ();
07278 }
07279
07280
07281
07282
07283
07284 static void
07285 frv_finish_packet (void (*handle_packet) (void))
07286 {
07287 if (frv_packet.num_insns > 0)
07288 {
07289 handle_packet ();
07290 state_transition (frv_packet.dfa_state, 0);
07291 frv_start_packet ();
07292 }
07293 }
07294
07295
07296
07297
07298
07299 static bool
07300 frv_pack_insn_p (rtx insn)
07301 {
07302
07303 if (frv_packet.num_insns == frv_packet.issue_rate)
07304 return false;
07305
07306
07307
07308
07309
07310
07311
07312
07313
07314
07315
07316
07317
07318
07319
07320
07321
07322
07323
07324 if (frv_packet.num_insns > 0
07325 && GET_CODE (insn) == INSN
07326 && GET_MODE (insn) == TImode
07327 && GET_CODE (PATTERN (insn)) != COND_EXEC)
07328 return false;
07329
07330
07331
07332
07333 if (get_attr_type (insn) != TYPE_SETLO)
07334 if (frv_registers_conflict_p (PATTERN (insn)))
07335 return false;
07336
07337 return state_transition (frv_packet.dfa_state, insn) < 0;
07338 }
07339
07340
07341
07342
07343 static void
07344 frv_add_insn_to_packet (rtx insn)
07345 {
07346 struct frv_packet_group *packet_group;
07347
07348 packet_group = &frv_packet.groups[frv_unit_groups[frv_insn_unit (insn)]];
07349 packet_group->insns[packet_group->num_insns++] = insn;
07350 frv_packet.insns[frv_packet.num_insns++] = insn;
07351
07352 frv_registers_update (PATTERN (insn));
07353 }
07354
07355
07356
07357
07358
07359
07360 static void
07361 frv_insert_nop_in_packet (rtx insn)
07362 {
07363 struct frv_packet_group *packet_group;
07364 rtx last;
07365
07366 packet_group = &frv_packet.groups[frv_unit_groups[frv_insn_unit (insn)]];
07367 last = frv_packet.insns[frv_packet.num_insns - 1];
07368 if (GET_CODE (last) != INSN)
07369 {
07370 insn = emit_insn_before (PATTERN (insn), last);
07371 frv_packet.insns[frv_packet.num_insns - 1] = insn;
07372 frv_packet.insns[frv_packet.num_insns++] = last;
07373 }
07374 else
07375 {
07376 insn = emit_insn_after (PATTERN (insn), last);
07377 frv_packet.insns[frv_packet.num_insns++] = insn;
07378 }
07379 packet_group->insns[packet_group->num_insns++] = insn;
07380 }
07381
07382
07383
07384
07385
07386 static bool
07387 frv_for_each_packet (void (*handle_packet) (void))
07388 {
07389 rtx insn, next_insn;
07390
07391 frv_packet.issue_rate = frv_issue_rate ();
07392
07393
07394 if (!optimize
07395 || !flag_schedule_insns_after_reload
07396 || !TARGET_VLIW_BRANCH
07397 || frv_packet.issue_rate == 1)
07398 return false;
07399
07400
07401 dfa_start ();
07402 frv_packet.dfa_state = alloca (state_size ());
07403
07404 frv_start_packet_block ();
07405 for (insn = get_insns (); insn != 0; insn = next_insn)
07406 {
07407 enum rtx_code code;
07408 bool eh_insn_p;
07409
07410 code = GET_CODE (insn);
07411 next_insn = NEXT_INSN (insn);
07412
07413 if (code == CODE_LABEL)
07414 {
07415 frv_finish_packet (handle_packet);
07416 frv_start_packet_block ();
07417 }
07418
07419 if (INSN_P (insn))
07420 switch (GET_CODE (PATTERN (insn)))
07421 {
07422 case USE:
07423 case CLOBBER:
07424 case ADDR_VEC:
07425 case ADDR_DIFF_VEC:
07426 break;
07427
07428 default:
07429
07430 if (GET_CODE (insn) == CALL_INSN && frv_cpu_type == FRV_CPU_TOMCAT)
07431 frv_finish_packet (handle_packet);
07432
07433
07434
07435
07436
07437
07438 eh_insn_p = (find_reg_note (insn, REG_EH_REGION, NULL) != NULL);
07439 if (eh_insn_p && !frv_issues_to_branch_unit_p (insn))
07440 frv_finish_packet (handle_packet);
07441
07442
07443
07444 if (!frv_pack_insn_p (insn))
07445 {
07446 frv_finish_packet (handle_packet);
07447 while (!frv_pack_insn_p (insn))
07448 state_transition (frv_packet.dfa_state, 0);
07449 }
07450
07451
07452 frv_add_insn_to_packet (insn);
07453
07454
07455
07456 if (code == CALL_INSN || code == JUMP_INSN || eh_insn_p)
07457 frv_finish_packet (handle_packet);
07458 break;
07459 }
07460 }
07461 frv_finish_packet (handle_packet);
07462 dfa_finish ();
07463 return true;
07464 }
07465
07466
07467
07468
07469
07470
07471
07472
07473
07474
07475
07476
07477
07478
07479 static bool
07480 frv_sort_insn_group_1 (enum frv_insn_group group,
07481 unsigned int lower_slot, unsigned int upper_slot,
07482 unsigned int issued, unsigned int num_insns,
07483 state_t state)
07484 {
07485 struct frv_packet_group *packet_group;
07486 unsigned int i;
07487 state_t test_state;
07488 size_t dfa_size;
07489 rtx insn;
07490
07491
07492 if (lower_slot == upper_slot)
07493 return true;
07494
07495 packet_group = &frv_packet.groups[group];
07496 dfa_size = state_size ();
07497 test_state = alloca (dfa_size);
07498
07499
07500 for (i = num_insns - 1; i + 1 != 0; i--)
07501 if (~issued & (1 << i))
07502 {
07503 insn = packet_group->sorted[i];
07504 memcpy (test_state, state, dfa_size);
07505 if (state_transition (test_state, insn) < 0
07506 && cpu_unit_reservation_p (test_state,
07507 NTH_UNIT (group, upper_slot - 1))
07508 && frv_sort_insn_group_1 (group, lower_slot, upper_slot - 1,
07509 issued | (1 << i), num_insns,
07510 test_state))
07511 {
07512 packet_group->sorted[upper_slot - 1] = insn;
07513 return true;
07514 }
07515 }
07516
07517 return false;
07518 }
07519
07520
07521
07522 static int
07523 frv_compare_insns (const void *first, const void *second)
07524 {
07525 const rtx *insn1 = first, *insn2 = second;
07526 return frv_insn_unit (*insn1) - frv_insn_unit (*insn2);
07527 }
07528
07529
07530
07531
07532
07533 static void
07534 frv_sort_insn_group (enum frv_insn_group group)
07535 {
07536 struct frv_packet_group *packet_group;
07537 unsigned int first, i, nop, max_unit, num_slots;
07538 state_t state, test_state;
07539 size_t dfa_size;
07540
07541 packet_group = &frv_packet.groups[group];
07542
07543
07544 packet_group->nop = 0;
07545
07546 if (packet_group->num_insns == 0)
07547 return;
07548
07549
07550 memcpy (packet_group->sorted, packet_group->insns,
07551 sizeof (rtx) * packet_group->num_insns);
07552
07553
07554 if (packet_group->num_insns > 1)
07555 qsort (packet_group->sorted, packet_group->num_insns,
07556 sizeof (rtx), frv_compare_insns);
07557
07558
07559 if (group == GROUP_B || group == GROUP_C)
07560 return;
07561
07562 dfa_size = state_size ();
07563 state = alloca (dfa_size);
07564 test_state = alloca (dfa_size);
07565
07566
07567
07568
07569 state_reset (test_state);
07570 for (first = 0; first < packet_group->num_insns; first++)
07571 {
07572 memcpy (state, test_state, dfa_size);
07573 if (state_transition (test_state, packet_group->sorted[first]) >= 0
07574 || !cpu_unit_reservation_p (test_state, NTH_UNIT (group, first)))
07575 break;
07576 }
07577
07578
07579 if (first == packet_group->num_insns)
07580 return;
07581
07582
07583
07584 for (nop = 0; nop < frv_num_nops; nop++)
07585 {
07586 max_unit = frv_insn_unit (frv_nops[nop]);
07587 if (frv_unit_groups[max_unit] == group)
07588 {
07589 packet_group->nop = frv_nops[nop];
07590 num_slots = UNIT_NUMBER (max_unit) + 1;
07591 for (i = packet_group->num_insns; i < num_slots; i++)
07592 packet_group->sorted[i] = frv_nops[nop];
07593 if (frv_sort_insn_group_1 (group, first, num_slots,
07594 (1 << first) - 1, num_slots, state))
07595 return;
07596 }
07597 }
07598 gcc_unreachable ();
07599 }
07600
07601
07602
07603
07604 static void
07605 frv_reorder_packet (void)
07606 {
07607 unsigned int cursor[NUM_GROUPS];
07608 rtx insns[ARRAY_SIZE (frv_unit_groups)];
07609 unsigned int unit, to, from;
07610 enum frv_insn_group group;
07611 struct frv_packet_group *packet_group;
07612
07613
07614 for (group = 0; group < NUM_GROUPS; group++)
07615 {
07616 cursor[group] = 0;
07617 frv_sort_insn_group (group);
07618 }
07619
07620
07621
07622 to = 0;
07623 for (unit = 0; unit < ARRAY_SIZE (frv_unit_groups); unit++)
07624 {
07625 group = frv_unit_groups[unit];
07626 packet_group = &frv_packet.groups[group];
07627 if (cursor[group] < packet_group->num_insns)
07628 {
07629
07630 gcc_assert (packet_group->sorted[cursor[group]]
07631 != packet_group->nop);
07632 insns[to++] = packet_group->sorted[cursor[group]++];
07633 }
07634 }
07635
07636 gcc_assert (to == frv_packet.num_insns);
07637
07638
07639
07640 CLEAR_PACKING_FLAG (insns[to - 1]);
07641 for (from = 0; from < to - 1; from++)
07642 {
07643 remove_insn (insns[from]);
07644 add_insn_before (insns[from], insns[to - 1]);
07645 SET_PACKING_FLAG (insns[from]);
07646 }
07647 }
07648
07649
07650
07651
07652
07653
07654
07655
07656
07657 static void
07658 frv_pack_insns (void)
07659 {
07660 if (frv_for_each_packet (frv_reorder_packet))
07661 frv_insn_packing_flag = 0;
07662 else
07663 frv_insn_packing_flag = -1;
07664 }
07665
07666
07667
07668
07669 static void
07670 frv_fill_unused_units (enum frv_insn_group group)
07671 {
07672 unsigned int non_nops, nops, i;
07673 struct frv_packet_group *packet_group;
07674
07675 packet_group = &frv_packet.groups[group];
07676
07677
07678
07679 frv_sort_insn_group (group);
07680
07681
07682 i = nops = 0;
07683 for (non_nops = 0; non_nops < packet_group->num_insns; non_nops++)
07684 while (packet_group->sorted[i++] == packet_group->nop)
07685 nops++;
07686
07687
07688 while (nops-- > 0)
07689 frv_insert_nop_in_packet (packet_group->nop);
07690 }
07691
07692
07693
07694 static bool
07695 frv_same_doubleword_p (const struct frv_io *io1, const struct frv_io *io2)
07696 {
07697 if (io1->const_address != 0 && io2->const_address != 0)
07698 return io1->const_address == io2->const_address;
07699
07700 if (io1->var_address != 0 && io2->var_address != 0)
07701 return rtx_equal_p (io1->var_address, io2->var_address);
07702
07703 return false;
07704 }
07705
07706
07707
07708
07709 static bool
07710 frv_io_fixed_order_p (const struct frv_io *io1, const struct frv_io *io2)
07711 {
07712
07713 if (io1->type == FRV_IO_WRITE && io2->type == FRV_IO_WRITE)
07714 return true;
07715
07716
07717 if (io1->type != FRV_IO_WRITE && io2->type != FRV_IO_WRITE)
07718 return false;
07719
07720
07721
07722
07723 return frv_same_doubleword_p (io1, io2);
07724 }
07725
07726
07727
07728 static void
07729 frv_io_union (struct frv_io *x, const struct frv_io *y)
07730 {
07731 if (x->type != y->type)
07732 x->type = FRV_IO_UNKNOWN;
07733 if (!frv_same_doubleword_p (x, y))
07734 {
07735 x->const_address = 0;
07736 x->var_address = 0;
07737 }
07738 }
07739
07740
07741
07742
07743 static void
07744 frv_extract_membar (struct frv_io *io, rtx insn)
07745 {
07746 extract_insn (insn);
07747 io->type = INTVAL (recog_data.operand[2]);
07748 io->const_address = INTVAL (recog_data.operand[1]);
07749 io->var_address = XEXP (recog_data.operand[0], 0);
07750 }
07751
07752
07753
07754
07755 static void
07756 frv_io_check_address (rtx x, rtx pat ATTRIBUTE_UNUSED, void *data)
07757 {
07758 rtx *other = data;
07759
07760 if (REG_P (x) && *other != 0 && reg_overlap_mentioned_p (x, *other))
07761 *other = 0;
07762 }
07763
07764
07765
07766
07767 static void
07768 frv_io_handle_set (rtx x, rtx pat ATTRIBUTE_UNUSED, void *data)
07769 {
07770 HARD_REG_SET *set = data;
07771 unsigned int regno;
07772
07773 if (REG_P (x))
07774 FOR_EACH_REGNO (regno, x)
07775 CLEAR_HARD_REG_BIT (*set, regno);
07776 }
07777
07778
07779
07780
07781 static int
07782 frv_io_handle_use_1 (rtx *x, void *data)
07783 {
07784 HARD_REG_SET *set = data;
07785 unsigned int regno;
07786
07787 if (REG_P (*x))
07788 FOR_EACH_REGNO (regno, *x)
07789 SET_HARD_REG_BIT (*set, regno);
07790
07791 return 0;
07792 }
07793
07794
07795
07796
07797 static void
07798 frv_io_handle_use (rtx *x, void *data)
07799 {
07800 for_each_rtx (x, frv_io_handle_use_1, data);
07801 }
07802
07803
07804
07805
07806
07807
07808
07809
07810
07811
07812
07813
07814
07815
07816
07817
07818
07819
07820
07821 static void
07822 frv_optimize_membar_local (basic_block bb, struct frv_io *next_io,
07823 rtx *last_membar)
07824 {
07825 HARD_REG_SET used_regs;
07826 rtx next_membar, set, insn;
07827 bool next_is_end_p;
07828
07829
07830
07831 memset (next_io, 0, sizeof (*next_io));
07832
07833
07834 next_is_end_p = true;
07835
07836
07837
07838
07839
07840
07841
07842 next_membar = 0;
07843
07844
07845
07846 CLEAR_HARD_REG_SET (used_regs);
07847
07848 for (insn = BB_END (bb); insn != BB_HEAD (bb); insn = PREV_INSN (insn))
07849 if (GET_CODE (insn) == CALL_INSN)
07850 {
07851
07852 memset (next_io, 0, sizeof (struct frv_io));
07853 next_is_end_p = false;
07854 CLEAR_HARD_REG_SET (used_regs);
07855 }
07856 else if (INSN_P (insn))
07857 switch (recog_memoized (insn))
07858 {
07859 case CODE_FOR_optional_membar_qi:
07860 case CODE_FOR_optional_membar_hi:
07861 case CODE_FOR_optional_membar_si:
07862 case CODE_FOR_optional_membar_di:
07863 next_membar = insn;
07864 if (next_is_end_p)
07865 {
07866
07867
07868 *last_membar = insn;
07869 frv_extract_membar (next_io, insn);
07870 next_is_end_p = false;
07871 }
07872 else
07873 {
07874
07875
07876
07877 struct frv_io prev_io;
07878
07879 frv_extract_membar (&prev_io, insn);
07880 if (frv_io_fixed_order_p (&prev_io, next_io))
07881 {
07882 if (dump_file)
07883 fprintf (dump_file,
07884 ";; [Local] Removing membar %d since order"
07885 " of accesses is guaranteed\n",
07886 INSN_UID (next_membar));
07887
07888 insn = NEXT_INSN (insn);
07889 delete_insn (next_membar);
07890 next_membar = 0;
07891 }
07892 *next_io = prev_io;
07893 }
07894 break;
07895
07896 default:
07897
07898
07899 if (next_io->var_address)
07900 note_stores (PATTERN (insn), frv_io_check_address,
07901 &next_io->var_address);
07902
07903
07904
07905
07906
07907 set = PATTERN (insn);
07908 if (next_io->type == FRV_IO_READ
07909 && next_io->var_address != 0
07910 && next_membar != 0
07911 && GET_CODE (set) == SET
07912 && GET_CODE (SET_DEST (set)) == REG
07913 && TEST_HARD_REG_BIT (used_regs, REGNO (SET_DEST (set))))
07914 {
07915 rtx src;
07916
07917 src = SET_SRC (set);
07918 if (GET_CODE (src) == ZERO_EXTEND)
07919 src = XEXP (src, 0);
07920
07921 if (GET_CODE (src) == MEM
07922 && rtx_equal_p (XEXP (src, 0), next_io->var_address))
07923 {
07924 if (dump_file)
07925 fprintf (dump_file,
07926 ";; [Local] Removing membar %d since the target"
07927 " of %d is used before the I/O operation\n",
07928 INSN_UID (next_membar), INSN_UID (insn));
07929
07930 if (next_membar == *last_membar)
07931 *last_membar = 0;
07932
07933 delete_insn (next_membar);
07934 next_membar = 0;
07935 }
07936 }
07937
07938
07939
07940
07941 if (volatile_refs_p (PATTERN (insn)))
07942 CLEAR_HARD_REG_SET (used_regs);
07943 else
07944 note_stores (PATTERN (insn), frv_io_handle_set, &used_regs);
07945
07946 note_uses (&PATTERN (insn), frv_io_handle_use, &used_regs);
07947 break;
07948 }
07949 }
07950
07951
07952
07953
07954 static void
07955 frv_optimize_membar_global (basic_block bb, struct frv_io *first_io,
07956 rtx membar)
07957 {
07958 struct frv_io this_io, next_io;
07959 edge succ;
07960 edge_iterator ei;
07961
07962
07963 FOR_EACH_EDGE (succ, ei, bb->succs)
07964
07965 if (succ->dest == EXIT_BLOCK_PTR)
07966 return;
07967
07968
07969 ei = ei_start (bb->succs);
07970 ei_cond (ei, &succ);
07971
07972 next_io = first_io[succ->dest->index];
07973 ei = ei_start (bb->succs);
07974 if (ei_cond (ei, &succ))
07975 {
07976 for (ei_next (&ei); ei_cond (ei, &succ); ei_next (&ei))
07977
07978 frv_io_union (&next_io, &first_io[succ->dest->index]);
07979 }
07980 else
07981 gcc_unreachable ();
07982
07983 frv_extract_membar (&this_io, membar);
07984 if (frv_io_fixed_order_p (&this_io, &next_io))
07985 {
07986 if (dump_file)
07987 fprintf (dump_file,
07988 ";; [Global] Removing membar %d since order of accesses"
07989 " is guaranteed\n", INSN_UID (membar));
07990
07991 delete_insn (membar);
07992 }
07993 }
07994
07995
07996
07997 static void
07998 frv_optimize_membar (void)
07999 {
08000 basic_block bb;
08001 struct frv_io *first_io;
08002 rtx *last_membar;
08003
08004 compute_bb_for_insn ();
08005 first_io = xcalloc (last_basic_block, sizeof (struct frv_io));
08006 last_membar = xcalloc (last_basic_block, sizeof (rtx));
08007
08008 FOR_EACH_BB (bb)
08009 frv_optimize_membar_local (bb, &first_io[bb->index],
08010 &last_membar[bb->index]);
08011
08012 FOR_EACH_BB (bb)
08013 if (last_membar[bb->index] != 0)
08014 frv_optimize_membar_global (bb, first_io, last_membar[bb->index]);
08015
08016 free (first_io);
08017 free (last_membar);
08018 }
08019
08020
08021 static unsigned int frv_packet_address;
08022
08023
08024
08025
08026 static void
08027 frv_align_label (void)
08028 {
08029 unsigned int alignment, target, nop;
08030 rtx x, last, barrier, label;
08031
08032
08033
08034
08035 last = frv_packet.insns[frv_packet.num_insns - 1];
08036 label = barrier = 0;
08037 alignment = 4;
08038 for (x = NEXT_INSN (last); x != 0 && !INSN_P (x); x = NEXT_INSN (x))
08039 {
08040 if (LABEL_P (x))
08041 {
08042 unsigned int subalign = 1 << label_to_alignment (x);
08043 alignment = MAX (alignment, subalign);
08044 label = x;
08045 }
08046 if (BARRIER_P (x))
08047 barrier = x;
08048 }
08049
08050
08051
08052 if (TARGET_ALIGN_LABELS
08053 && label != 0
08054 && barrier == 0
08055 && frv_packet.num_insns < frv_packet.issue_rate)
08056 alignment = MAX (alignment, 8);
08057
08058
08059 frv_packet_address += frv_packet.num_insns * 4;
08060
08061
08062 target = (frv_packet_address + alignment - 1) & -alignment;
08063
08064
08065
08066 if (barrier == 0)
08067 {
08068
08069 for (nop = 0; nop < frv_num_nops; nop++)
08070 while (frv_packet_address < target && frv_pack_insn_p (frv_nops[nop]))
08071 {
08072 frv_insert_nop_in_packet (frv_nops[nop]);
08073 frv_packet_address += 4;
08074 }
08075
08076
08077
08078
08079
08080
08081
08082
08083
08084
08085
08086
08087 last = frv_packet.insns[frv_packet.num_insns - 1];
08088 nop = 0;
08089 while (frv_packet_address < target)
08090 {
08091 last = emit_insn_after (PATTERN (frv_nops[nop]), last);
08092 frv_packet_address += 4;
08093 if (frv_num_nops > 1)
08094 nop ^= 1;
08095 }
08096 }
08097
08098 frv_packet_address = target;
08099 }
08100
08101
08102
08103
08104 static void
08105 frv_reorg_packet (void)
08106 {
08107 frv_fill_unused_units (GROUP_I);
08108 frv_fill_unused_units (GROUP_FM);
08109 frv_align_label ();
08110 }
08111
08112
08113
08114 static void
08115 frv_register_nop (rtx nop)
08116 {
08117 nop = make_insn_raw (nop);
08118 NEXT_INSN (nop) = 0;
08119 PREV_INSN (nop) = 0;
08120 frv_nops[frv_num_nops++] = nop;
08121 }
08122
08123
08124
08125
08126
08127
08128
08129 static void
08130 frv_reorg (void)
08131 {
08132 if (optimize > 0 && TARGET_OPTIMIZE_MEMBAR && cfun->machine->has_membar_p)
08133 frv_optimize_membar ();
08134
08135 frv_num_nops = 0;
08136 frv_register_nop (gen_nop ());
08137 if (TARGET_MEDIA)
08138 frv_register_nop (gen_mnop ());
08139 if (TARGET_HARD_FLOAT)
08140 frv_register_nop (gen_fnop ());
08141
08142
08143
08144 shorten_branches (get_insns ());
08145
08146 frv_packet_address = 0;
08147 frv_for_each_packet (frv_reorg_packet);
08148 }
08149
08150 #define def_builtin(name, type, code) \
08151 lang_hooks.builtin_function ((name), (type), (code), BUILT_IN_MD, NULL, NULL)
08152
08153 struct builtin_description
08154 {
08155 enum insn_code icode;
08156 const char *name;
08157 enum frv_builtins code;
08158 enum rtx_code comparison;
08159 unsigned int flag;
08160 };
08161
08162
08163
08164 static struct builtin_description bdesc_set[] =
08165 {
08166 { CODE_FOR_mhdsets, "__MHDSETS", FRV_BUILTIN_MHDSETS, 0, 0 }
08167 };
08168
08169
08170
08171 static struct builtin_description bdesc_1arg[] =
08172 {
08173 { CODE_FOR_mnot, "__MNOT", FRV_BUILTIN_MNOT, 0, 0 },
08174 { CODE_FOR_munpackh, "__MUNPACKH", FRV_BUILTIN_MUNPACKH, 0, 0 },
08175 { CODE_FOR_mbtoh, "__MBTOH", FRV_BUILTIN_MBTOH, 0, 0 },
08176 { CODE_FOR_mhtob, "__MHTOB", FRV_BUILTIN_MHTOB, 0, 0 },
08177 { CODE_FOR_mabshs, "__MABSHS", FRV_BUILTIN_MABSHS, 0, 0 },
08178 { CODE_FOR_scutss, "__SCUTSS", FRV_BUILTIN_SCUTSS, 0, 0 }
08179 };
08180
08181
08182
08183 static struct builtin_description bdesc_2arg[] =
08184 {
08185 { CODE_FOR_mand, "__MAND", FRV_BUILTIN_MAND, 0, 0 },
08186 { CODE_FOR_mor, "__MOR", FRV_BUILTIN_MOR, 0, 0 },
08187 { CODE_FOR_mxor, "__MXOR", FRV_BUILTIN_MXOR, 0, 0 },
08188 { CODE_FOR_maveh, "__MAVEH", FRV_BUILTIN_MAVEH, 0, 0 },
08189 { CODE_FOR_msaths, "__MSATHS", FRV_BUILTIN_MSATHS, 0, 0 },
08190 { CODE_FOR_msathu, "__MSATHU", FRV_BUILTIN_MSATHU, 0, 0 },
08191 { CODE_FOR_maddhss, "__MADDHSS", FRV_BUILTIN_MADDHSS, 0, 0 },
08192 { CODE_FOR_maddhus, "__MADDHUS", FRV_BUILTIN_MADDHUS, 0, 0 },
08193 { CODE_FOR_msubhss, "__MSUBHSS", FRV_BUILTIN_MSUBHSS, 0, 0 },
08194 { CODE_FOR_msubhus, "__MSUBHUS", FRV_BUILTIN_MSUBHUS, 0, 0 },
08195 { CODE_FOR_mqaddhss, "__MQADDHSS", FRV_BUILTIN_MQADDHSS, 0, 0 },
08196 { CODE_FOR_mqaddhus, "__MQADDHUS", FRV_BUILTIN_MQADDHUS, 0, 0 },
08197 { CODE_FOR_mqsubhss, "__MQSUBHSS", FRV_BUILTIN_MQSUBHSS, 0, 0 },
08198 { CODE_FOR_mqsubhus, "__MQSUBHUS", FRV_BUILTIN_MQSUBHUS, 0, 0 },
08199 { CODE_FOR_mpackh, "__MPACKH", FRV_BUILTIN_MPACKH, 0, 0 },
08200 { CODE_FOR_mcop1, "__Mcop1", FRV_BUILTIN_MCOP1, 0, 0 },
08201 { CODE_FOR_mcop2, "__Mcop2", FRV_BUILTIN_MCOP2, 0, 0 },
08202 { CODE_FOR_mwcut, "__MWCUT", FRV_BUILTIN_MWCUT, 0, 0 },
08203 { CODE_FOR_mqsaths, "__MQSATHS", FRV_BUILTIN_MQSATHS, 0, 0 },
08204 { CODE_FOR_mqlclrhs, "__MQLCLRHS", FRV_BUILTIN_MQLCLRHS, 0, 0 },
08205 { CODE_FOR_mqlmths, "__MQLMTHS", FRV_BUILTIN_MQLMTHS, 0, 0 },
08206 { CODE_FOR_smul, "__SMUL", FRV_BUILTIN_SMUL, 0, 0 },
08207 { CODE_FOR_umul, "__UMUL", FRV_BUILTIN_UMUL, 0, 0 },
08208 { CODE_FOR_addss, "__ADDSS", FRV_BUILTIN_ADDSS, 0, 0 },
08209 { CODE_FOR_subss, "__SUBSS", FRV_BUILTIN_SUBSS, 0, 0 },
08210 { CODE_FOR_slass, "__SLASS", FRV_BUILTIN_SLASS, 0, 0 },
08211 { CODE_FOR_scan, "__SCAN", FRV_BUILTIN_SCAN, 0, 0 }
08212 };
08213
08214
08215
08216 static struct builtin_description bdesc_int_void2arg[] =
08217 {
08218 { CODE_FOR_smass, "__SMASS", FRV_BUILTIN_SMASS, 0, 0 },
08219 { CODE_FOR_smsss, "__SMSSS", FRV_BUILTIN_SMSSS, 0, 0 },
08220 { CODE_FOR_smu, "__SMU", FRV_BUILTIN_SMU, 0, 0 }
08221 };
08222
08223 static struct builtin_description bdesc_prefetches[] =
08224 {
08225 { CODE_FOR_frv_prefetch0, "__data_prefetch0", FRV_BUILTIN_PREFETCH0, 0, 0 },
08226 { CODE_FOR_frv_prefetch, "__data_prefetch", FRV_BUILTIN_PREFETCH, 0, 0 }
08227 };
08228
08229
08230
08231 static struct builtin_description bdesc_cut[] =
08232 {
08233 { CODE_FOR_mcut, "__MCUT", FRV_BUILTIN_MCUT, 0, 0 },
08234 { CODE_FOR_mcutss, "__MCUTSS", FRV_BUILTIN_MCUTSS, 0, 0 },
08235 { CODE_FOR_mdcutssi, "__MDCUTSSI", FRV_BUILTIN_MDCUTSSI, 0, 0 }
08236 };
08237
08238
08239
08240 static struct builtin_description bdesc_2argimm[] =
08241 {
08242 { CODE_FOR_mrotli, "__MROTLI", FRV_BUILTIN_MROTLI, 0, 0 },
08243 { CODE_FOR_mrotri, "__MROTRI", FRV_BUILTIN_MROTRI, 0, 0 },
08244 { CODE_FOR_msllhi, "__MSLLHI", FRV_BUILTIN_MSLLHI, 0, 0 },
08245 { CODE_FOR_msrlhi, "__MSRLHI", FRV_BUILTIN_MSRLHI, 0, 0 },
08246 { CODE_FOR_msrahi, "__MSRAHI", FRV_BUILTIN_MSRAHI, 0, 0 },
08247 { CODE_FOR_mexpdhw, "__MEXPDHW", FRV_BUILTIN_MEXPDHW, 0, 0 },
08248 { CODE_FOR_mexpdhd, "__MEXPDHD", FRV_BUILTIN_MEXPDHD, 0, 0 },
08249 { CODE_FOR_mdrotli, "__MDROTLI", FRV_BUILTIN_MDROTLI, 0, 0 },
08250 { CODE_FOR_mcplhi, "__MCPLHI", FRV_BUILTIN_MCPLHI, 0, 0 },
08251 { CODE_FOR_mcpli, "__MCPLI", FRV_BUILTIN_MCPLI, 0, 0 },
08252 { CODE_FOR_mhsetlos, "__MHSETLOS", FRV_BUILTIN_MHSETLOS, 0, 0 },
08253 { CODE_FOR_mhsetloh, "__MHSETLOH", FRV_BUILTIN_MHSETLOH, 0, 0 },
08254 { CODE_FOR_mhsethis, "__MHSETHIS", FRV_BUILTIN_MHSETHIS, 0, 0 },
08255 { CODE_FOR_mhsethih, "__MHSETHIH", FRV_BUILTIN_MHSETHIH, 0, 0 },
08256 { CODE_FOR_mhdseth, "__MHDSETH", FRV_BUILTIN_MHDSETH, 0, 0 },
08257 { CODE_FOR_mqsllhi, "__MQSLLHI", FRV_BUILTIN_MQSLLHI, 0, 0 },
08258 { CODE_FOR_mqsrahi, "__MQSRAHI", FRV_BUILTIN_MQSRAHI, 0, 0 }
08259 };
08260
08261
08262
08263
08264 static struct builtin_description bdesc_void2arg[] =
08265 {
08266 { CODE_FOR_mdunpackh, "__MDUNPACKH", FRV_BUILTIN_MDUNPACKH, 0, 0 },
08267 { CODE_FOR_mbtohe, "__MBTOHE", FRV_BUILTIN_MBTOHE, 0, 0 },
08268 };
08269
08270
08271
08272
08273 static struct builtin_description bdesc_void3arg[] =
08274 {
08275 { CODE_FOR_mcpxrs, "__MCPXRS", FRV_BUILTIN_MCPXRS, 0, 0 },
08276 { CODE_FOR_mcpxru, "__MCPXRU", FRV_BUILTIN_MCPXRU, 0, 0 },
08277 { CODE_FOR_mcpxis, "__MCPXIS", FRV_BUILTIN_MCPXIS, 0, 0 },
08278 { CODE_FOR_mcpxiu, "__MCPXIU", FRV_BUILTIN_MCPXIU, 0, 0 },
08279 { CODE_FOR_mmulhs, "__MMULHS", FRV_BUILTIN_MMULHS, 0, 0 },
08280 { CODE_FOR_mmulhu, "__MMULHU", FRV_BUILTIN_MMULHU, 0, 0 },
08281 { CODE_FOR_mmulxhs, "__MMULXHS", FRV_BUILTIN_MMULXHS, 0, 0 },
08282 { CODE_FOR_mmulxhu, "__MMULXHU", FRV_BUILTIN_MMULXHU, 0, 0 },
08283 { CODE_FOR_mmachs, "__MMACHS", FRV_BUILTIN_MMACHS, 0, 0 },
08284 { CODE_FOR_mmachu, "__MMACHU", FRV_BUILTIN_MMACHU, 0, 0 },
08285 { CODE_FOR_mmrdhs, "__MMRDHS", FRV_BUILTIN_MMRDHS, 0, 0 },
08286 { CODE_FOR_mmrdhu, "__MMRDHU", FRV_BUILTIN_MMRDHU, 0, 0 },
08287 { CODE_FOR_mqcpxrs, "__MQCPXRS", FRV_BUILTIN_MQCPXRS, 0, 0 },
08288 { CODE_FOR_mqcpxru, "__MQCPXRU", FRV_BUILTIN_MQCPXRU, 0, 0 },
08289 { CODE_FOR_mqcpxis, "__MQCPXIS", FRV_BUILTIN_MQCPXIS, 0, 0 },
08290 { CODE_FOR_mqcpxiu, "__MQCPXIU", FRV_BUILTIN_MQCPXIU, 0, 0 },
08291 { CODE_FOR_mqmulhs, "__MQMULHS", FRV_BUILTIN_MQMULHS, 0, 0 },
08292 { CODE_FOR_mqmulhu, "__MQMULHU", FRV_BUILTIN_MQMULHU, 0, 0 },
08293 { CODE_FOR_mqmulxhs, "__MQMULXHS", FRV_BUILTIN_MQMULXHS, 0, 0 },
08294 { CODE_FOR_mqmulxhu, "__MQMULXHU", FRV_BUILTIN_MQMULXHU, 0, 0 },
08295 { CODE_FOR_mqmachs, "__MQMACHS", FRV_BUILTIN_MQMACHS, 0, 0 },
08296 { CODE_FOR_mqmachu, "__MQMACHU", FRV_BUILTIN_MQMACHU, 0, 0 },
08297 { CODE_FOR_mqxmachs, "__MQXMACHS", FRV_BUILTIN_MQXMACHS, 0, 0 },
08298 { CODE_FOR_mqxmacxhs, "__MQXMACXHS", FRV_BUILTIN_MQXMACXHS, 0, 0 },
08299 { CODE_FOR_mqmacxhs, "__MQMACXHS", FRV_BUILTIN_MQMACXHS, 0, 0 }
08300 };
08301
08302
08303
08304
08305 static struct builtin_description bdesc_voidacc[] =
08306 {
08307 { CODE_FOR_maddaccs, "__MADDACCS", FRV_BUILTIN_MADDACCS, 0, 0 },
08308 { CODE_FOR_msubaccs, "__MSUBACCS", FRV_BUILTIN_MSUBACCS, 0, 0 },
08309 { CODE_FOR_masaccs, "__MASACCS", FRV_BUILTIN_MASACCS, 0, 0 },
08310 { CODE_FOR_mdaddaccs, "__MDADDACCS", FRV_BUILTIN_MDADDACCS, 0, 0 },
08311 { CODE_FOR_mdsubaccs, "__MDSUBACCS", FRV_BUILTIN_MDSUBACCS, 0, 0 },
08312 { CODE_FOR_mdasaccs, "__MDASACCS", FRV_BUILTIN_MDASACCS, 0, 0 }
08313 };
08314
08315
08316
08317
08318 static struct builtin_description bdesc_loads[] =
08319 {
08320 { CODE_FOR_optional_membar_qi, "__builtin_read8",
08321 FRV_BUILTIN_READ8, 0, 0 },
08322 { CODE_FOR_optional_membar_hi, "__builtin_read16",
08323 FRV_BUILTIN_READ16, 0, 0 },
08324 { CODE_FOR_optional_membar_si, "__builtin_read32",
08325 FRV_BUILTIN_READ32, 0, 0 },
08326 { CODE_FOR_optional_membar_di, "__builtin_read64",
08327 FRV_BUILTIN_READ64, 0, 0 }
08328 };
08329
08330
08331
08332 static struct builtin_description bdesc_stores[] =
08333 {
08334 { CODE_FOR_optional_membar_qi, "__builtin_write8",
08335 FRV_BUILTIN_WRITE8, 0, 0 },
08336 { CODE_FOR_optional_membar_hi, "__builtin_write16",
08337 FRV_BUILTIN_WRITE16, 0, 0 },
08338 { CODE_FOR_optional_membar_si, "__builtin_write32",
08339 FRV_BUILTIN_WRITE32, 0, 0 },
08340 { CODE_FOR_optional_membar_di, "__builtin_write64",
08341 FRV_BUILTIN_WRITE64, 0, 0 },
08342 };
08343
08344
08345
08346 static void
08347 frv_init_builtins (void)
08348 {
08349 tree endlink = void_list_node;
08350 tree accumulator = integer_type_node;
08351 tree integer = integer_type_node;
08352 tree voidt = void_type_node;
08353 tree uhalf = short_unsigned_type_node;
08354 tree sword1 = long_integer_type_node;
08355 tree uword1 = long_unsigned_type_node;
08356 tree sword2 = long_long_integer_type_node;
08357 tree uword2 = long_long_unsigned_type_node;
08358 tree uword4 = build_pointer_type (uword1);
08359 tree vptr = build_pointer_type (build_type_variant (void_type_node, 0, 1));
08360 tree ubyte = unsigned_char_type_node;
08361 tree iacc = integer_type_node;
08362
08363 #define UNARY(RET, T1) \
08364 build_function_type (RET, tree_cons (NULL_TREE, T1, endlink))
08365
08366 #define BINARY(RET, T1, T2) \
08367 build_function_type (RET, tree_cons (NULL_TREE, T1, \
08368 tree_cons (NULL_TREE, T2, endlink)))
08369
08370 #define TRINARY(RET, T1, T2, T3) \
08371 build_function_type (RET, tree_cons (NULL_TREE, T1, \
08372 tree_cons (NULL_TREE, T2, \
08373 tree_cons (NULL_TREE, T3, endlink))))
08374
08375 #define QUAD(RET, T1, T2, T3, T4) \
08376 build_function_type (RET, tree_cons (NULL_TREE, T1, \
08377 tree_cons (NULL_TREE, T2, \
08378 tree_cons (NULL_TREE, T3, \
08379 tree_cons (NULL_TREE, T4, endlink)))))
08380
08381 tree void_ftype_void = build_function_type (voidt, endlink);
08382
08383 tree void_ftype_acc = UNARY (voidt, accumulator);
08384 tree void_ftype_uw4_uw1 = BINARY (voidt, uword4, uword1);
08385 tree void_ftype_uw4_uw2 = BINARY (voidt, uword4, uword2);
08386 tree void_ftype_acc_uw1 = BINARY (voidt, accumulator, uword1);
08387 tree void_ftype_acc_acc = BINARY (voidt, accumulator, accumulator);
08388 tree void_ftype_acc_uw1_uw1 = TRINARY (voidt, accumulator, uword1, uword1);
08389 tree void_ftype_acc_sw1_sw1 = TRINARY (voidt, accumulator, sword1, sword1);
08390 tree void_ftype_acc_uw2_uw2 = TRINARY (voidt, accumulator, uword2, uword2);
08391 tree void_ftype_acc_sw2_sw2 = TRINARY (voidt, accumulator, sword2, sword2);
08392
08393 tree uw1_ftype_uw1 = UNARY (uword1, uword1);
08394 tree uw1_ftype_sw1 = UNARY (uword1, sword1);
08395 tree uw1_ftype_uw2 = UNARY (uword1, uword2);
08396 tree uw1_ftype_acc = UNARY (uword1, accumulator);
08397 tree uw1_ftype_uh_uh = BINARY (uword1, uhalf, uhalf);
08398 tree uw1_ftype_uw1_uw1 = BINARY (uword1, uword1, uword1);
08399 tree uw1_ftype_uw1_int = BINARY (uword1, uword1, integer);
08400 tree uw1_ftype_acc_uw1 = BINARY (uword1, accumulator, uword1);
08401 tree uw1_ftype_acc_sw1 = BINARY (uword1, accumulator, sword1);
08402 tree uw1_ftype_uw2_uw1 = BINARY (uword1, uword2, uword1);
08403 tree uw1_ftype_uw2_int = BINARY (uword1, uword2, integer);
08404
08405 tree sw1_ftype_int = UNARY (sword1, integer);
08406 tree sw1_ftype_sw1_sw1 = BINARY (sword1, sword1, sword1);
08407 tree sw1_ftype_sw1_int = BINARY (sword1, sword1, integer);
08408
08409 tree uw2_ftype_uw1 = UNARY (uword2, uword1);
08410 tree uw2_ftype_uw1_int = BINARY (uword2, uword1, integer);
08411 tree uw2_ftype_uw2_uw2 = BINARY (uword2, uword2, uword2);
08412 tree uw2_ftype_uw2_int = BINARY (uword2, uword2, integer);
08413 tree uw2_ftype_acc_int = BINARY (uword2, accumulator, integer);
08414 tree uw2_ftype_uh_uh_uh_uh = QUAD (uword2, uhalf, uhalf, uhalf, uhalf);
08415
08416 tree sw2_ftype_sw2_sw2 = BINARY (sword2, sword2, sword2);
08417 tree sw2_ftype_sw2_int = BINARY (sword2, sword2, integer);
08418 tree uw2_ftype_uw1_uw1 = BINARY (uword2, uword1, uword1);
08419 tree sw2_ftype_sw1_sw1 = BINARY (sword2, sword1, sword1);
08420 tree void_ftype_sw1_sw1 = BINARY (voidt, sword1, sword1);
08421 tree void_ftype_iacc_sw2 = BINARY (voidt, iacc, sword2);
08422 tree void_ftype_iacc_sw1 = BINARY (voidt, iacc, sword1);
08423 tree sw1_ftype_sw1 = UNARY (sword1, sword1);
08424 tree sw2_ftype_iacc = UNARY (sword2, iacc);
08425 tree sw1_ftype_iacc = UNARY (sword1, iacc);
08426 tree void_ftype_ptr = UNARY (voidt, const_ptr_type_node);
08427 tree uw1_ftype_vptr = UNARY (uword1, vptr);
08428 tree uw2_ftype_vptr = UNARY (uword2, vptr);
08429 tree void_ftype_vptr_ub = BINARY (voidt, vptr, ubyte);
08430 tree void_ftype_vptr_uh = BINARY (voidt, vptr, uhalf);
08431 tree void_ftype_vptr_uw1 = BINARY (voidt, vptr, uword1);
08432 tree void_ftype_vptr_uw2 = BINARY (voidt, vptr, uword2);
08433
08434 def_builtin ("__MAND", uw1_ftype_uw1_uw1, FRV_BUILTIN_MAND);
08435 def_builtin ("__MOR", uw1_ftype_uw1_uw1, FRV_BUILTIN_MOR);
08436 def_builtin ("__MXOR", uw1_ftype_uw1_uw1, FRV_BUILTIN_MXOR);
08437 def_builtin ("__MNOT", uw1_ftype_uw1, FRV_BUILTIN_MNOT);
08438 def_builtin ("__MROTLI", uw1_ftype_uw1_int, FRV_BUILTIN_MROTLI);
08439 def_builtin ("__MROTRI", uw1_ftype_uw1_int, FRV_BUILTIN_MROTRI);
08440 def_builtin ("__MWCUT", uw1_ftype_uw2_uw1, FRV_BUILTIN_MWCUT);
08441 def_builtin ("__MAVEH", uw1_ftype_uw1_uw1, FRV_BUILTIN_MAVEH);
08442 def_builtin ("__MSLLHI", uw1_ftype_uw1_int, FRV_BUILTIN_MSLLHI);
08443 def_builtin ("__MSRLHI", uw1_ftype_uw1_int, FRV_BUILTIN_MSRLHI);
08444 def_builtin ("__MSRAHI", sw1_ftype_sw1_int, FRV_BUILTIN_MSRAHI);
08445 def_builtin ("__MSATHS", sw1_ftype_sw1_sw1, FRV_BUILTIN_MSATHS);
08446 def_builtin ("__MSATHU", uw1_ftype_uw1_uw1, FRV_BUILTIN_MSATHU);
08447 def_builtin ("__MADDHSS", sw1_ftype_sw1_sw1, FRV_BUILTIN_MADDHSS);
08448 def_builtin ("__MADDHUS", uw1_ftype_uw1_uw1, FRV_BUILTIN_MADDHUS);
08449 def_builtin ("__MSUBHSS", sw1_ftype_sw1_sw1, FRV_BUILTIN_MSUBHSS);
08450 def_builtin ("__MSUBHUS", uw1_ftype_uw1_uw1, FRV_BUILTIN_MSUBHUS);
08451 def_builtin ("__MMULHS", void_ftype_acc_sw1_sw1, FRV_BUILTIN_MMULHS);
08452 def_builtin ("__MMULHU", void_ftype_acc_uw1_uw1, FRV_BUILTIN_MMULHU);
08453 def_builtin ("__MMULXHS", void_ftype_acc_sw1_sw1, FRV_BUILTIN_MMULXHS);
08454 def_builtin ("__MMULXHU", void_ftype_acc_uw1_uw1, FRV_BUILTIN_MMULXHU);
08455 def_builtin ("__MMACHS", void_ftype_acc_sw1_sw1, FRV_BUILTIN_MMACHS);
08456 def_builtin ("__MMACHU", void_ftype_acc_uw1_uw1, FRV_BUILTIN_MMACHU);
08457 def_builtin ("__MMRDHS", void_ftype_acc_sw1_sw1, FRV_BUILTIN_MMRDHS);
08458 def_builtin ("__MMRDHU", void_ftype_acc_uw1_uw1, FRV_BUILTIN_MMRDHU);
08459 def_builtin ("__MQADDHSS", sw2_ftype_sw2_sw2, FRV_BUILTIN_MQADDHSS);
08460 def_builtin ("__MQADDHUS", uw2_ftype_uw2_uw2, FRV_BUILTIN_MQADDHUS);
08461 def_builtin ("__MQSUBHSS", sw2_ftype_sw2_sw2, FRV_BUILTIN_MQSUBHSS);
08462 def_builtin ("__MQSUBHUS", uw2_ftype_uw2_uw2, FRV_BUILTIN_MQSUBHUS);
08463 def_builtin ("__MQMULHS", void_ftype_acc_sw2_sw2, FRV_BUILTIN_MQMULHS);
08464 def_builtin ("__MQMULHU", void_ftype_acc_uw2_uw2, FRV_BUILTIN_MQMULHU);
08465 def_builtin ("__MQMULXHS", void_ftype_acc_sw2_sw2, FRV_BUILTIN_MQMULXHS);
08466 def_builtin ("__MQMULXHU", void_ftype_acc_uw2_uw2, FRV_BUILTIN_MQMULXHU);
08467 def_builtin ("__MQMACHS", void_ftype_acc_sw2_sw2, FRV_BUILTIN_MQMACHS);
08468 def_builtin ("__MQMACHU", void_ftype_acc_uw2_uw2, FRV_BUILTIN_MQMACHU);
08469 def_builtin ("__MCPXRS", void_ftype_acc_sw1_sw1, FRV_BUILTIN_MCPXRS);
08470 def_builtin ("__MCPXRU", void_ftype_acc_uw1_uw1, FRV_BUILTIN_MCPXRU);
08471 def_builtin ("__MCPXIS", void_ftype_acc_sw1_sw1, FRV_BUILTIN_MCPXIS);
08472 def_builtin ("__MCPXIU", void_ftype_acc_uw1_uw1, FRV_BUILTIN_MCPXIU);
08473 def_builtin ("__MQCPXRS", void_ftype_acc_sw2_sw2, FRV_BUILTIN_MQCPXRS);
08474 def_builtin ("__MQCPXRU", void_ftype_acc_uw2_uw2, FRV_BUILTIN_MQCPXRU);
08475 def_builtin ("__MQCPXIS", void_ftype_acc_sw2_sw2, FRV_BUILTIN_MQCPXIS);
08476 def_builtin ("__MQCPXIU", void_ftype_acc_uw2_uw2, FRV_BUILTIN_MQCPXIU);
08477 def_builtin ("__MCUT", uw1_ftype_acc_uw1, FRV_BUILTIN_MCUT);
08478 def_builtin ("__MCUTSS", uw1_ftype_acc_sw1, FRV_BUILTIN_MCUTSS);
08479 def_builtin ("__MEXPDHW", uw1_ftype_uw1_int, FRV_BUILTIN_MEXPDHW);
08480 def_builtin ("__MEXPDHD", uw2_ftype_uw1_int, FRV_BUILTIN_MEXPDHD);
08481 def_builtin ("__MPACKH", uw1_ftype_uh_uh, FRV_BUILTIN_MPACKH);
08482 def_builtin ("__MUNPACKH", uw2_ftype_uw1, FRV_BUILTIN_MUNPACKH);
08483 def_builtin ("__MDPACKH", uw2_ftype_uh_uh_uh_uh, FRV_BUILTIN_MDPACKH);
08484 def_builtin ("__MDUNPACKH", void_ftype_uw4_uw2, FRV_BUILTIN_MDUNPACKH);
08485 def_builtin ("__MBTOH", uw2_ftype_uw1, FRV_BUILTIN_MBTOH);
08486 def_builtin ("__MHTOB", uw1_ftype_uw2, FRV_BUILTIN_MHTOB);
08487 def_builtin ("__MBTOHE", void_ftype_uw4_uw1, FRV_BUILTIN_MBTOHE);
08488 def_builtin ("__MCLRACC", void_ftype_acc, FRV_BUILTIN_MCLRACC);
08489 def_builtin ("__MCLRACCA", void_ftype_void, FRV_BUILTIN_MCLRACCA);
08490 def_builtin ("__MRDACC", uw1_ftype_acc, FRV_BUILTIN_MRDACC);
08491 def_builtin ("__MRDACCG", uw1_ftype_acc, FRV_BUILTIN_MRDACCG);
08492 def_builtin ("__MWTACC", void_ftype_acc_uw1, FRV_BUILTIN_MWTACC);
08493 def_builtin ("__MWTACCG", void_ftype_acc_uw1, FRV_BUILTIN_MWTACCG);
08494 def_builtin ("__Mcop1", uw1_ftype_uw1_uw1, FRV_BUILTIN_MCOP1);
08495 def_builtin ("__Mcop2", uw1_ftype_uw1_uw1, FRV_BUILTIN_MCOP2);
08496 def_builtin ("__MTRAP", void_ftype_void, FRV_BUILTIN_MTRAP);
08497 def_builtin ("__MQXMACHS", void_ftype_acc_sw2_sw2, FRV_BUILTIN_MQXMACHS);
08498 def_builtin ("__MQXMACXHS", void_ftype_acc_sw2_sw2, FRV_BUILTIN_MQXMACXHS);
08499 def_builtin ("__MQMACXHS", void_ftype_acc_sw2_sw2, FRV_BUILTIN_MQMACXHS);
08500 def_builtin ("__MADDACCS", void_ftype_acc_acc, FRV_BUILTIN_MADDACCS);
08501 def_builtin ("__MSUBACCS", void_ftype_acc_acc, FRV_BUILTIN_MSUBACCS);
08502 def_builtin ("__MASACCS", void_ftype_acc_acc, FRV_BUILTIN_MASACCS);
08503 def_builtin ("__MDADDACCS", void_ftype_acc_acc, FRV_BUILTIN_MDADDACCS);
08504 def_builtin ("__MDSUBACCS", void_ftype_acc_acc, FRV_BUILTIN_MDSUBACCS);
08505 def_builtin ("__MDASACCS", void_ftype_acc_acc, FRV_BUILTIN_MDASACCS);
08506 def_builtin ("__MABSHS", uw1_ftype_sw1, FRV_BUILTIN_MABSHS);
08507 def_builtin ("__MDROTLI", uw2_ftype_uw2_int, FRV_BUILTIN_MDROTLI);
08508 def_builtin ("__MCPLHI", uw1_ftype_uw2_int, FRV_BUILTIN_MCPLHI);
08509 def_builtin ("__MCPLI", uw1_ftype_uw2_int, FRV_BUILTIN_MCPLI);
08510 def_builtin ("__MDCUTSSI", uw2_ftype_acc_int, FRV_BUILTIN_MDCUTSSI);
08511 def_builtin ("__MQSATHS", sw2_ftype_sw2_sw2, FRV_BUILTIN_MQSATHS);
08512 def_builtin ("__MHSETLOS", sw1_ftype_sw1_int, FRV_BUILTIN_MHSETLOS);
08513 def_builtin ("__MHSETHIS", sw1_ftype_sw1_int, FRV_BUILTIN_MHSETHIS);
08514 def_builtin ("__MHDSETS", sw1_ftype_int, FRV_BUILTIN_MHDSETS);
08515 def_builtin ("__MHSETLOH", uw1_ftype_uw1_int, FRV_BUILTIN_MHSETLOH);
08516 def_builtin ("__MHSETHIH", uw1_ftype_uw1_int, FRV_BUILTIN_MHSETHIH);
08517 def_builtin ("__MHDSETH", uw1_ftype_uw1_int, FRV_BUILTIN_MHDSETH);
08518 def_builtin ("__MQLCLRHS", sw2_ftype_sw2_sw2, FRV_BUILTIN_MQLCLRHS);
08519 def_builtin ("__MQLMTHS", sw2_ftype_sw2_sw2, FRV_BUILTIN_MQLMTHS);
08520 def_builtin ("__MQSLLHI", uw2_ftype_uw2_int, FRV_BUILTIN_MQSLLHI);
08521 def_builtin ("__MQSRAHI", sw2_ftype_sw2_int, FRV_BUILTIN_MQSRAHI);
08522 def_builtin ("__SMUL", sw2_ftype_sw1_sw1, FRV_BUILTIN_SMUL);
08523 def_builtin ("__UMUL", uw2_ftype_uw1_uw1, FRV_BUILTIN_UMUL);
08524 def_builtin ("__SMASS", void_ftype_sw1_sw1, FRV_BUILTIN_SMASS);
08525 def_builtin ("__SMSSS", void_ftype_sw1_sw1, FRV_BUILTIN_SMSSS);
08526 def_builtin ("__SMU", void_ftype_sw1_sw1, FRV_BUILTIN_SMU);
08527 def_builtin ("__ADDSS", sw1_ftype_sw1_sw1, FRV_BUILTIN_ADDSS);
08528 def_builtin ("__SUBSS", sw1_ftype_sw1_sw1, FRV_BUILTIN_SUBSS);
08529 def_builtin ("__SLASS", sw1_ftype_sw1_sw1, FRV_BUILTIN_SLASS);
08530 def_builtin ("__SCAN", sw1_ftype_sw1_sw1, FRV_BUILTIN_SCAN);
08531 def_builtin ("__SCUTSS", sw1_ftype_sw1, FRV_BUILTIN_SCUTSS);
08532 def_builtin ("__IACCreadll", sw2_ftype_iacc, FRV_BUILTIN_IACCreadll);
08533 def_builtin ("__IACCreadl", sw1_ftype_iacc, FRV_BUILTIN_IACCreadl);
08534 def_builtin ("__IACCsetll", void_ftype_iacc_sw2, FRV_BUILTIN_IACCsetll);
08535 def_builtin ("__IACCsetl", void_ftype_iacc_sw1, FRV_BUILTIN_IACCsetl);
08536 def_builtin ("__data_prefetch0", void_ftype_ptr, FRV_BUILTIN_PREFETCH0);
08537 def_builtin ("__data_prefetch", void_ftype_ptr, FRV_BUILTIN_PREFETCH);
08538 def_builtin ("__builtin_read8", uw1_ftype_vptr, FRV_BUILTIN_READ8);
08539 def_builtin ("__builtin_read16", uw1_ftype_vptr, FRV_BUILTIN_READ16);
08540 def_builtin ("__builtin_read32", uw1_ftype_vptr, FRV_BUILTIN_READ32);
08541 def_builtin ("__builtin_read64", uw2_ftype_vptr, FRV_BUILTIN_READ64);
08542
08543 def_builtin ("__builtin_write8", void_ftype_vptr_ub, FRV_BUILTIN_WRITE8);
08544 def_builtin ("__builtin_write16", void_ftype_vptr_uh, FRV_BUILTIN_WRITE16);
08545 def_builtin ("__builtin_write32", void_ftype_vptr_uw1, FRV_BUILTIN_WRITE32);
08546 def_builtin ("__builtin_write64", void_ftype_vptr_uw2, FRV_BUILTIN_WRITE64);
08547
08548 #undef UNARY
08549 #undef BINARY
08550 #undef TRINARY
08551 #undef QUAD
08552 }
08553
08554
08555
08556 static void
08557 frv_init_libfuncs (void)
08558 {
08559 set_optab_libfunc (smod_optab, SImode, "__modi");
08560 set_optab_libfunc (umod_optab, SImode, "__umodi");
08561
08562 set_optab_libfunc (add_optab, DImode, "__addll");
08563 set_optab_libfunc (sub_optab, DImode, "__subll");
08564 set_optab_libfunc (smul_optab, DImode, "__mulll");
08565 set_optab_libfunc (sdiv_optab, DImode, "__divll");
08566 set_optab_libfunc (smod_optab, DImode, "__modll");
08567 set_optab_libfunc (umod_optab, DImode, "__umodll");
08568 set_optab_libfunc (and_optab, DImode, "__andll");
08569 set_optab_libfunc (ior_optab, DImode, "__orll");
08570 set_optab_libfunc (xor_optab, DImode, "__xorll");
08571 set_optab_libfunc (one_cmpl_optab, DImode, "__notll");
08572
08573 set_optab_libfunc (add_optab, SFmode, "__addf");
08574 set_optab_libfunc (sub_optab, SFmode, "__subf");
08575 set_optab_libfunc (smul_optab, SFmode, "__mulf");
08576 set_optab_libfunc (sdiv_optab, SFmode, "__divf");
08577
08578 set_optab_libfunc (add_optab, DFmode, "__addd");
08579 set_optab_libfunc (sub_optab, DFmode, "__subd");
08580 set_optab_libfunc (smul_optab, DFmode, "__muld");
08581 set_optab_libfunc (sdiv_optab, DFmode, "__divd");
08582
08583 set_conv_libfunc (sext_optab, DFmode, SFmode, "__ftod");
08584 set_conv_libfunc (trunc_optab, SFmode, DFmode, "__dtof");
08585
08586 set_conv_libfunc (sfix_optab, SImode, SFmode, "__ftoi");
08587 set_conv_libfunc (sfix_optab, DImode, SFmode, "__ftoll");
08588 set_conv_libfunc (sfix_optab, SImode, DFmode, "__dtoi");
08589 set_conv_libfunc (sfix_optab, DImode, DFmode, "__dtoll");
08590
08591 set_conv_libfunc (ufix_optab, SImode, SFmode, "__ftoui");
08592 set_conv_libfunc (ufix_optab, DImode, SFmode, "__ftoull");
08593 set_conv_libfunc (ufix_optab, SImode, DFmode, "__dtoui");
08594 set_conv_libfunc (ufix_optab, DImode, DFmode, "__dtoull");
08595
08596 set_conv_libfunc (sfloat_optab, SFmode, SImode, "__itof");
08597 set_conv_libfunc (sfloat_optab, SFmode, DImode, "__lltof");
08598 set_conv_libfunc (sfloat_optab, DFmode, SImode, "__itod");
08599 set_conv_libfunc (sfloat_optab, DFmode, DImode, "__lltod");
08600 }
08601
08602
08603
08604
08605
08606
08607
08608 static rtx
08609 frv_int_to_acc (enum insn_code icode, int opnum, rtx opval)
08610 {
08611 rtx reg;
08612 int i;
08613
08614
08615
08616
08617 for (i = 0; i <= ACC_MASK; i++)
08618 if ((i & ACC_MASK) == i)
08619 global_regs[i + ACC_FIRST] = global_regs[i + ACCG_FIRST] = 1;
08620
08621 if (GET_CODE (opval) != CONST_INT)
08622 {
08623 error ("accumulator is not a constant integer");
08624 return NULL_RTX;
08625 }
08626 if ((INTVAL (opval) & ~ACC_MASK) != 0)
08627 {
08628 error ("accumulator number is out of bounds");
08629 return NULL_RTX;
08630 }
08631
08632 reg = gen_rtx_REG (insn_data[icode].operand[opnum].mode,
08633 ACC_FIRST + INTVAL (opval));
08634 if (! (*insn_data[icode].operand[opnum].predicate) (reg, VOIDmode))
08635 REGNO (reg) = ACCG_FIRST + INTVAL (opval);
08636
08637 if (! (*insn_data[icode].operand[opnum].predicate) (reg, VOIDmode))
08638 {
08639 error ("inappropriate accumulator for %qs", insn_data[icode].name);
08640 return NULL_RTX;
08641 }
08642 return reg;
08643 }
08644
08645
08646
08647
08648 static enum machine_mode
08649 frv_matching_accg_mode (enum machine_mode mode)
08650 {
08651 switch (mode)
08652 {
08653 case V4SImode:
08654 return V4QImode;
08655
08656 case DImode:
08657 return HImode;
08658
08659 case SImode:
08660 return QImode;
08661
08662 default:
08663 gcc_unreachable ();
08664 }
08665 }
08666
08667
08668
08669
08670
08671 static rtx
08672 frv_io_address_cookie (rtx address)
08673 {
08674 return (GET_CODE (address) == CONST_INT
08675 ? GEN_INT (INTVAL (address) / 8 * 8)
08676 : const0_rtx);
08677 }
08678
08679
08680
08681
08682
08683 rtx
08684 frv_matching_accg_for_acc (rtx acc)
08685 {
08686 return gen_rtx_REG (frv_matching_accg_mode (GET_MODE (acc)),
08687 REGNO (acc) - ACC_FIRST + ACCG_FIRST);
08688 }
08689
08690
08691
08692
08693
08694 static rtx
08695 frv_read_argument (tree *arglistptr)
08696 {
08697 tree next = TREE_VALUE (*arglistptr);
08698 *arglistptr = TREE_CHAIN (*arglistptr);
08699 return expand_expr (next, NULL_RTX, VOIDmode, 0);
08700 }
08701
08702
08703
08704
08705 static rtx
08706 frv_read_iacc_argument (enum machine_mode mode, tree *arglistptr)
08707 {
08708 int i, regno;
08709 rtx op;
08710
08711 op = frv_read_argument (arglistptr);
08712 if (GET_CODE (op) != CONST_INT
08713 || INTVAL (op) < 0
08714 || INTVAL (op) > IACC_LAST - IACC_FIRST
08715 || ((INTVAL (op) * 4) & (GET_MODE_SIZE (mode) - 1)) != 0)
08716 {
08717 error ("invalid IACC argument");
08718 op = const0_rtx;
08719 }
08720
08721
08722
08723
08724 regno = INTVAL (op) + IACC_FIRST;
08725 for (i = 0; i < HARD_REGNO_NREGS (regno, mode); i++)
08726 global_regs[regno + i] = 1;
08727
08728 return gen_rtx_REG (mode, regno);
08729 }
08730
08731
08732
08733
08734
08735 static int
08736 frv_check_constant_argument (enum insn_code icode, int opnum, rtx opval)
08737 {
08738 if (GET_CODE (opval) != CONST_INT)
08739 {
08740 error ("%qs expects a constant argument", insn_data[icode].name);
08741 return FALSE;
08742 }
08743 if (! (*insn_data[icode].operand[opnum].predicate) (opval, VOIDmode))
08744 {
08745 error ("constant argument out of range for %qs", insn_data[icode].name);
08746 return FALSE;
08747 }
08748 return TRUE;
08749 }
08750
08751
08752
08753
08754
08755 static rtx
08756 frv_legitimize_target (enum insn_code icode, rtx target)
08757 {
08758 enum machine_mode mode = insn_data[icode].operand[0].mode;
08759
08760 if (! target
08761 || GET_MODE (target) != mode
08762 || ! (*insn_data[icode].operand[0].predicate) (target, mode))
08763 return gen_reg_rtx (mode);
08764 else
08765 return target;
08766 }
08767
08768
08769
08770
08771
08772
08773 static rtx
08774 frv_legitimize_argument (enum insn_code icode, int opnum, rtx arg)
08775 {
08776 enum machine_mode mode = insn_data[icode].operand[opnum].mode;
08777
08778 if ((*insn_data[icode].operand[opnum].predicate) (arg, mode))
08779 return arg;
08780 else
08781 return copy_to_mode_reg (mode, arg);
08782 }
08783
08784
08785
08786 static rtx
08787 frv_volatile_memref (enum machine_mode mode, rtx arg)
08788 {
08789 rtx mem;
08790
08791 mem = gen_rtx_MEM (mode, memory_address (mode, arg));
08792 MEM_VOLATILE_P (mem) = 1;
08793 return mem;
08794 }
08795
08796
08797
08798
08799 static rtx
08800 frv_expand_set_builtin (enum insn_code icode, tree arglist, rtx target)
08801 {
08802 rtx pat;
08803 rtx op0 = frv_read_argument (&arglist);
08804
08805 if (! frv_check_constant_argument (icode, 1, op0))
08806 return NULL_RTX;
08807
08808 target = frv_legitimize_target (icode, target);
08809 pat = GEN_FCN (icode) (target, op0);
08810 if (! pat)
08811 return NULL_RTX;
08812
08813 emit_insn (pat);
08814 return target;
08815 }
08816
08817
08818
08819 static rtx
08820 frv_expand_unop_builtin (enum insn_code icode, tree arglist, rtx target)
08821 {
08822 rtx pat;
08823 rtx op0 = frv_read_argument (&arglist);
08824
08825 target = frv_legitimize_target (icode, target);
08826 op0 = frv_legitimize_argument (icode, 1, op0);
08827 pat = GEN_FCN (icode) (target, op0);
08828 if (! pat)
08829 return NULL_RTX;
08830
08831 emit_insn (pat);
08832 return target;
08833 }
08834
08835
08836
08837 static rtx
08838 frv_expand_binop_builtin (enum insn_code icode, tree arglist, rtx target)
08839 {
08840 rtx pat;
08841 rtx op0 = frv_read_argument (&arglist);
08842 rtx op1 = frv_read_argument (&arglist);
08843
08844 target = frv_legitimize_target (icode, target);
08845 op0 = frv_legitimize_argument (icode, 1, op0);
08846 op1 = frv_legitimize_argument (icode, 2, op1);
08847 pat = GEN_FCN (icode) (target, op0, op1);
08848 if (! pat)
08849 return NULL_RTX;
08850
08851 emit_insn (pat);
08852 return target;
08853 }
08854
08855
08856
08857
08858 static rtx
08859 frv_expand_cut_builtin (enum insn_code icode, tree arglist, rtx target)
08860 {
08861 rtx pat;
08862 rtx op0 = frv_read_argument (&arglist);
08863 rtx op1 = frv_read_argument (&arglist);
08864 rtx op2;
08865
08866 target = frv_legitimize_target (icode, target);
08867 op0 = frv_int_to_acc (icode, 1, op0);
08868 if (! op0)
08869 return NULL_RTX;
08870
08871 if (icode == CODE_FOR_mdcutssi || GET_CODE (op1) == CONST_INT)
08872 {
08873 if (! frv_check_constant_argument (icode, 2, op1))
08874 return NULL_RTX;
08875 }
08876 else
08877 op1 = frv_legitimize_argument (icode, 2, op1);
08878
08879 op2 = frv_matching_accg_for_acc (op0);
08880 pat = GEN_FCN (icode) (target, op0, op1, op2);
08881 if (! pat)
08882 return NULL_RTX;
08883
08884 emit_insn (pat);
08885 return target;
08886 }
08887
08888
08889
08890 static rtx
08891 frv_expand_binopimm_builtin (enum insn_code icode, tree arglist, rtx target)
08892 {
08893 rtx pat;
08894 rtx op0 = frv_read_argument (&arglist);
08895 rtx op1 = frv_read_argument (&arglist);
08896
08897 if (! frv_check_constant_argument (icode, 2, op1))
08898 return NULL_RTX;
08899
08900 target = frv_legitimize_target (icode, target);
08901 op0 = frv_legitimize_argument (icode, 1, op0);
08902 pat = GEN_FCN (icode) (target, op0, op1);
08903 if (! pat)
08904 return NULL_RTX;
08905
08906 emit_insn (pat);
08907 return target;
08908 }
08909
08910
08911
08912
08913 static rtx
08914 frv_expand_voidbinop_builtin (enum insn_code icode, tree arglist)
08915 {
08916 rtx pat;
08917 rtx op0 = frv_read_argument (&arglist);
08918 rtx op1 = frv_read_argument (&arglist);
08919 enum machine_mode mode0 = insn_data[icode].operand[0].mode;
08920 rtx addr;
08921
08922 if (GET_CODE (op0) != MEM)
08923 {
08924 rtx reg = op0;
08925
08926 if (! offsettable_address_p (0, mode0, op0))
08927 {
08928 reg = gen_reg_rtx (Pmode);
08929 emit_insn (gen_rtx_SET (VOIDmode, reg, op0));
08930 }
08931
08932 op0 = gen_rtx_MEM (SImode, reg);
08933 }
08934
08935 addr = XEXP (op0, 0);
08936 if (! offsettable_address_p (0, mode0, addr))
08937 addr = copy_to_mode_reg (Pmode, op0);
08938
08939 op0 = change_address (op0, V4SImode, addr);
08940 op1 = frv_legitimize_argument (icode, 1, op1);
08941 pat = GEN_FCN (icode) (op0, op1);
08942 if (! pat)
08943 return 0;
08944
08945 emit_insn (pat);
08946 return 0;
08947 }
08948
08949
08950
08951 static rtx
08952 frv_expand_int_void2arg (enum insn_code icode, tree arglist)
08953 {
08954 rtx pat;
08955 rtx op0 = frv_read_argument (&arglist);
08956 rtx op1 = frv_read_argument (&arglist);
08957
08958 op0 = frv_legitimize_argument (icode, 1, op0);
08959 op1 = frv_legitimize_argument (icode, 1, op1);
08960 pat = GEN_FCN (icode) (op0, op1);
08961 if (! pat)
08962 return NULL_RTX;
08963
08964 emit_insn (pat);
08965 return NULL_RTX;
08966 }
08967
08968
08969
08970 static rtx
08971 frv_expand_prefetches (enum insn_code icode, tree arglist)
08972 {
08973 rtx pat;
08974 rtx op0 = frv_read_argument (&arglist);
08975
08976 pat = GEN_FCN (icode) (force_reg (Pmode, op0));
08977 if (! pat)
08978 return 0;
08979
08980 emit_insn (pat);
08981 return 0;
08982 }
08983
08984
08985
08986
08987
08988
08989 static rtx
08990 frv_expand_voidtriop_builtin (enum insn_code icode, tree arglist)
08991 {
08992 rtx pat;
08993 rtx op0 = frv_read_argument (&arglist);
08994 rtx op1 = frv_read_argument (&arglist);
08995 rtx op2 = frv_read_argument (&arglist);
08996 rtx op3;
08997
08998 op0 = frv_int_to_acc (icode, 0, op0);
08999 if (! op0)
09000 return NULL_RTX;
09001
09002 op1 = frv_legitimize_argument (icode, 1, op1);
09003 op2 = frv_legitimize_argument (icode, 2, op2);
09004 op3 = frv_matching_accg_for_acc (op0);
09005 pat = GEN_FCN (icode) (op0, op1, op2, op3);
09006 if (! pat)
09007 return NULL_RTX;
09008
09009 emit_insn (pat);
09010 return NULL_RTX;
09011 }
09012
09013
09014
09015
09016
09017 static rtx
09018 frv_expand_voidaccop_builtin (enum insn_code icode, tree arglist)
09019 {
09020 rtx pat;
09021 rtx op0 = frv_read_argument (&arglist);
09022 rtx op1 = frv_read_argument (&arglist);
09023 rtx op2;
09024 rtx op3;
09025
09026 op0 = frv_int_to_acc (icode, 0, op0);
09027 if (! op0)
09028 return NULL_RTX;
09029
09030 op1 = frv_int_to_acc (icode, 1, op1);
09031 if (! op1)
09032 return NULL_RTX;
09033
09034 op2 = frv_matching_accg_for_acc (op0);
09035 op3 = frv_matching_accg_for_acc (op1);
09036 pat = GEN_FCN (icode) (op0, op1, op2, op3);
09037 if (! pat)
09038 return NULL_RTX;
09039
09040 emit_insn (pat);
09041 return NULL_RTX;
09042 }
09043
09044
09045
09046
09047 static rtx
09048 frv_expand_load_builtin (enum insn_code icode, enum machine_mode target_mode,
09049 tree arglist, rtx target)
09050 {
09051 rtx op0 = frv_read_argument (&arglist);
09052 rtx cookie = frv_io_address_cookie (op0);
09053
09054 if (target == 0 || !REG_P (target))
09055 target = gen_reg_rtx (target_mode);
09056 op0 = frv_volatile_memref (insn_data[icode].operand[0].mode, op0);
09057 convert_move (target, op0, 1);
09058 emit_insn (GEN_FCN (icode) (copy_rtx (op0), cookie, GEN_INT (FRV_IO_READ)));
09059 cfun->machine->has_membar_p = 1;
09060 return target;
09061 }
09062
09063
09064
09065 static rtx
09066 frv_expand_store_builtin (enum insn_code icode, tree arglist)
09067 {
09068 rtx op0 = frv_read_argument (&arglist);
09069 rtx op1 = frv_read_argument (&arglist);
09070 rtx cookie = frv_io_address_cookie (op0);
09071
09072 op0 = frv_volatile_memref (insn_data[icode].operand[0].mode, op0);
09073 convert_move (op0, force_reg (insn_data[icode].operand[0].mode, op1), 1);
09074 emit_insn (GEN_FCN (icode) (copy_rtx (op0), cookie, GEN_INT (FRV_IO_WRITE)));
09075 cfun->machine->has_membar_p = 1;
09076 return NULL_RTX;
09077 }
09078
09079
09080
09081
09082
09083
09084 static rtx
09085 frv_expand_mdpackh_builtin (tree arglist, rtx target)
09086 {
09087 enum insn_code icode = CODE_FOR_mdpackh;
09088 rtx pat, op0, op1;
09089 rtx arg1 = frv_read_argument (&arglist);
09090 rtx arg2 = frv_read_argument (&arglist);
09091 rtx arg3 = frv_read_argument (&arglist);
09092 rtx arg4 = frv_read_argument (&arglist);
09093
09094 target = frv_legitimize_target (icode, target);
09095 op0 = gen_reg_rtx (DImode);
09096 op1 = gen_reg_rtx (DImode);
09097
09098
09099
09100 emit_insn (gen_rtx_CLOBBER (DImode, op0));
09101 emit_insn (gen_rtx_CLOBBER (DImode, op1));
09102
09103
09104 emit_move_insn (simplify_gen_subreg (HImode, op0, DImode, 2), arg1);
09105 emit_move_insn (simplify_gen_subreg (HImode, op0, DImode, 6), arg2);
09106 emit_move_insn (simplify_gen_subreg (HImode, op1, DImode, 2), arg3);
09107 emit_move_insn (simplify_gen_subreg (HImode, op1, DImode, 6), arg4);
09108
09109 pat = GEN_FCN (icode) (target, op0, op1);
09110 if (! pat)
09111 return NULL_RTX;
09112
09113 emit_insn (pat);
09114 return target;
09115 }
09116
09117
09118
09119
09120 static rtx
09121 frv_expand_mclracc_builtin (tree arglist)
09122 {
09123 enum insn_code icode = CODE_FOR_mclracc;
09124 rtx pat;
09125 rtx op0 = frv_read_argument (&arglist);
09126
09127 op0 = frv_int_to_acc (icode, 0, op0);
09128 if (! op0)
09129 return NULL_RTX;
09130
09131 pat = GEN_FCN (icode) (op0);
09132 if (pat)
09133 emit_insn (pat);
09134
09135 return NULL_RTX;
09136 }
09137
09138
09139
09140 static rtx
09141 frv_expand_noargs_builtin (enum insn_code icode)
09142 {
09143 rtx pat = GEN_FCN (icode) (const0_rtx);
09144 if (pat)
09145 emit_insn (pat);
09146
09147 return NULL_RTX;
09148 }
09149
09150
09151
09152
09153 static rtx
09154 frv_expand_mrdacc_builtin (enum insn_code icode, tree arglist)
09155 {
09156 rtx pat;
09157 rtx target = gen_reg_rtx (SImode);
09158 rtx op0 = frv_read_argument (&arglist);
09159
09160 op0 = frv_int_to_acc (icode, 1, op0);
09161 if (! op0)
09162 return NULL_RTX;
09163
09164 pat = GEN_FCN (icode) (target, op0);
09165 if (! pat)
09166 return NULL_RTX;
09167
09168 emit_insn (pat);
09169 return target;
09170 }
09171
09172
09173
09174
09175
09176 static rtx
09177 frv_expand_mwtacc_builtin (enum insn_code icode, tree arglist)
09178 {
09179 rtx pat;
09180 rtx op0 = frv_read_argument (&arglist);
09181 rtx op1 = frv_read_argument (&arglist);
09182
09183 op0 = frv_int_to_acc (icode, 0, op0);
09184 if (! op0)
09185 return NULL_RTX;
09186
09187 op1 = frv_legitimize_argument (icode, 1, op1);
09188 pat = GEN_FCN (icode) (op0, op1);
09189 if (pat)
09190 emit_insn (pat);
09191
09192 return NULL_RTX;
09193 }
09194
09195
09196
09197
09198 static void
09199 frv_split_iacc_move (rtx dest, rtx src)
09200 {
09201 enum machine_mode inner;
09202 int i;
09203
09204 inner = GET_MODE (dest);
09205 for (i = 0; i < GET_MODE_SIZE (inner); i += GET_MODE_SIZE (SImode))
09206 emit_move_insn (simplify_gen_subreg (SImode, dest, inner, i),
09207 simplify_gen_subreg (SImode, src, inner, i));
09208 }
09209
09210
09211
09212 static rtx
09213 frv_expand_builtin (tree exp,
09214 rtx target,
09215 rtx subtarget ATTRIBUTE_UNUSED,
09216 enum machine_mode mode ATTRIBUTE_UNUSED,
09217 int ignore ATTRIBUTE_UNUSED)
09218 {
09219 tree arglist = TREE_OPERAND (exp, 1);
09220 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
09221 unsigned fcode = (unsigned)DECL_FUNCTION_CODE (fndecl);
09222 unsigned i;
09223 struct builtin_description *d;
09224
09225 if (fcode < FRV_BUILTIN_FIRST_NONMEDIA && !TARGET_MEDIA)
09226 {
09227 error ("media functions are not available unless -mmedia is used");
09228 return NULL_RTX;
09229 }
09230
09231 switch (fcode)
09232 {
09233 case FRV_BUILTIN_MCOP1:
09234 case FRV_BUILTIN_MCOP2:
09235 case FRV_BUILTIN_MDUNPACKH:
09236 case FRV_BUILTIN_MBTOHE:
09237 if (! TARGET_MEDIA_REV1)
09238 {
09239 error ("this media function is only available on the fr500");
09240 return NULL_RTX;
09241 }
09242 break;
09243
09244 case FRV_BUILTIN_MQXMACHS:
09245 case FRV_BUILTIN_MQXMACXHS:
09246 case FRV_BUILTIN_MQMACXHS:
09247 case FRV_BUILTIN_MADDACCS:
09248 case FRV_BUILTIN_MSUBACCS:
09249 case FRV_BUILTIN_MASACCS:
09250 case FRV_BUILTIN_MDADDACCS:
09251 case FRV_BUILTIN_MDSUBACCS:
09252 case FRV_BUILTIN_MDASACCS:
09253 case FRV_BUILTIN_MABSHS:
09254 case FRV_BUILTIN_MDROTLI:
09255 case FRV_BUILTIN_MCPLHI:
09256 case FRV_BUILTIN_MCPLI:
09257 case FRV_BUILTIN_MDCUTSSI:
09258 case FRV_BUILTIN_MQSATHS:
09259 case FRV_BUILTIN_MHSETLOS:
09260 case FRV_BUILTIN_MHSETLOH:
09261 case FRV_BUILTIN_MHSETHIS:
09262 case FRV_BUILTIN_MHSETHIH:
09263 case FRV_BUILTIN_MHDSETS:
09264 case FRV_BUILTIN_MHDSETH:
09265 if (! TARGET_MEDIA_REV2)
09266 {
09267 error ("this media function is only available on the fr400"
09268 " and fr550");
09269 return NULL_RTX;
09270 }
09271 break;
09272
09273 case FRV_BUILTIN_SMASS:
09274 case FRV_BUILTIN_SMSSS:
09275 case FRV_BUILTIN_SMU:
09276 case FRV_BUILTIN_ADDSS:
09277 case FRV_BUILTIN_SUBSS:
09278 case FRV_BUILTIN_SLASS:
09279 case FRV_BUILTIN_SCUTSS:
09280 case FRV_BUILTIN_IACCreadll:
09281 case FRV_BUILTIN_IACCreadl:
09282 case FRV_BUILTIN_IACCsetll:
09283 case FRV_BUILTIN_IACCsetl:
09284 if (!TARGET_FR405_BUILTINS)
09285 {
09286 error ("this builtin function is only available"
09287 " on the fr405 and fr450");
09288 return NULL_RTX;
09289 }
09290 break;
09291
09292 case FRV_BUILTIN_PREFETCH:
09293 if (!TARGET_FR500_FR550_BUILTINS)
09294 {
09295 error ("this builtin function is only available on the fr500"
09296 " and fr550");
09297 return NULL_RTX;
09298 }
09299 break;
09300
09301 case FRV_BUILTIN_MQLCLRHS:
09302 case FRV_BUILTIN_MQLMTHS:
09303 case FRV_BUILTIN_MQSLLHI:
09304 case FRV_BUILTIN_MQSRAHI:
09305 if (!TARGET_MEDIA_FR450)
09306 {
09307 error ("this builtin function is only available on the fr450");
09308 return NULL_RTX;
09309 }
09310 break;
09311
09312 default:
09313 break;
09314 }
09315
09316
09317
09318 switch (fcode)
09319 {
09320 case FRV_BUILTIN_MTRAP:
09321 return frv_expand_noargs_builtin (CODE_FOR_mtrap);
09322
09323 case FRV_BUILTIN_MCLRACC:
09324 return frv_expand_mclracc_builtin (arglist);
09325
09326 case FRV_BUILTIN_MCLRACCA:
09327 if (TARGET_ACC_8)
09328 return frv_expand_noargs_builtin (CODE_FOR_mclracca8);
09329 else
09330 return frv_expand_noargs_builtin (CODE_FOR_mclracca4);
09331
09332 case FRV_BUILTIN_MRDACC:
09333 return frv_expand_mrdacc_builtin (CODE_FOR_mrdacc, arglist);
09334
09335 case FRV_BUILTIN_MRDACCG:
09336 return frv_expand_mrdacc_builtin (CODE_FOR_mrdaccg, arglist);
09337
09338 case FRV_BUILTIN_MWTACC:
09339 return frv_expand_mwtacc_builtin (CODE_FOR_mwtacc, arglist);
09340
09341 case FRV_BUILTIN_MWTACCG:
09342 return frv_expand_mwtacc_builtin (CODE_FOR_mwtaccg, arglist);
09343
09344 case FRV_BUILTIN_MDPACKH:
09345 return frv_expand_mdpackh_builtin (arglist, target);
09346
09347 case FRV_BUILTIN_IACCreadll:
09348 {
09349 rtx src = frv_read_iacc_argument (DImode, &arglist);
09350 if (target == 0 || !REG_P (target))
09351 target = gen_reg_rtx (DImode);
09352 frv_split_iacc_move (target, src);
09353 return target;
09354 }
09355
09356 case FRV_BUILTIN_IACCreadl:
09357 return frv_read_iacc_argument (SImode, &arglist);
09358
09359 case FRV_BUILTIN_IACCsetll:
09360 {
09361 rtx dest = frv_read_iacc_argument (DImode, &arglist);
09362 rtx src = frv_read_argument (&arglist);
09363 frv_split_iacc_move (dest, force_reg (DImode, src));
09364 return 0;
09365 }
09366
09367 case FRV_BUILTIN_IACCsetl:
09368 {
09369 rtx dest = frv_read_iacc_argument (SImode, &arglist);
09370 rtx src = frv_read_argument (&arglist);
09371 emit_move_insn (dest, force_reg (SImode, src));
09372 return 0;
09373 }
09374
09375 default:
09376 break;
09377 }
09378
09379
09380
09381 for (i = 0, d = bdesc_set; i < ARRAY_SIZE (bdesc_set); i++, d++)
09382 if (d->code == fcode)
09383 return frv_expand_set_builtin (d->icode, arglist, target);
09384
09385 for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
09386 if (d->code == fcode)
09387 return frv_expand_unop_builtin (d->icode, arglist, target);
09388
09389 for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
09390 if (d->code == fcode)
09391 return frv_expand_binop_builtin (d->icode, arglist, target);
09392
09393 for (i = 0, d = bdesc_cut; i < ARRAY_SIZE (bdesc_cut); i++, d++)
09394 if (d->code == fcode)
09395 return frv_expand_cut_builtin (d->icode, arglist, target);
09396
09397 for (i = 0, d = bdesc_2argimm; i < ARRAY_SIZE (bdesc_2argimm); i++, d++)
09398 if (d->code == fcode)
09399 return frv_expand_binopimm_builtin (d->icode, arglist, target);
09400
09401 for (i = 0, d = bdesc_void2arg; i < ARRAY_SIZE (bdesc_void2arg); i++, d++)
09402 if (d->code == fcode)
09403 return frv_expand_voidbinop_builtin (d->icode, arglist);
09404
09405 for (i = 0, d = bdesc_void3arg; i < ARRAY_SIZE (bdesc_void3arg); i++, d++)
09406 if (d->code == fcode)
09407 return frv_expand_voidtriop_builtin (d->icode, arglist);
09408
09409 for (i = 0, d = bdesc_voidacc; i < ARRAY_SIZE (bdesc_voidacc); i++, d++)
09410 if (d->code == fcode)
09411 return frv_expand_voidaccop_builtin (d->icode, arglist);
09412
09413 for (i = 0, d = bdesc_int_void2arg;
09414 i < ARRAY_SIZE (bdesc_int_void2arg); i++, d++)
09415 if (d->code == fcode)
09416 return frv_expand_int_void2arg (d->icode, arglist);
09417
09418 for (i = 0, d = bdesc_prefetches;
09419 i < ARRAY_SIZE (bdesc_prefetches); i++, d++)
09420 if (d->code == fcode)
09421 return frv_expand_prefetches (d->icode, arglist);
09422
09423 for (i = 0, d = bdesc_loads; i < ARRAY_SIZE (bdesc_loads); i++, d++)
09424 if (d->code == fcode)
09425 return frv_expand_load_builtin (d->icode, TYPE_MODE (TREE_TYPE (exp)),
09426 arglist, target);
09427
09428 for (i = 0, d = bdesc_stores; i < ARRAY_SIZE (bdesc_stores); i++, d++)
09429 if (d->code == fcode)
09430 return frv_expand_store_builtin (d->icode, arglist);
09431
09432 return 0;
09433 }
09434
09435 static bool
09436 frv_in_small_data_p (tree decl)
09437 {
09438 HOST_WIDE_INT size;
09439 tree section_name;
09440
09441
09442
09443
09444
09445 if (TREE_CODE (decl) != VAR_DECL || DECL_ARTIFICIAL (decl))
09446 return false;
09447
09448
09449
09450 section_name = DECL_SECTION_NAME (decl);
09451 if (section_name)
09452 {
09453 gcc_assert (TREE_CODE (section_name) == STRING_CST);
09454 if (frv_string_begins_with (section_name, ".sdata"))
09455 return true;
09456 if (frv_string_begins_with (section_name, ".sbss"))
09457 return true;
09458 return false;
09459 }
09460
09461 size = int_size_in_bytes (TREE_TYPE (decl));
09462 if (size > 0 && (unsigned HOST_WIDE_INT) size <= g_switch_value)
09463 return true;
09464
09465 return false;
09466 }
09467
09468 static bool
09469 frv_rtx_costs (rtx x,
09470 int code ATTRIBUTE_UNUSED,
09471 int outer_code ATTRIBUTE_UNUSED,
09472 int *total)
09473 {
09474 if (outer_code == MEM)
09475 {
09476
09477
09478 *total = COSTS_N_INSNS (0);
09479 return true;
09480 }
09481
09482 switch (code)
09483 {
09484 case CONST_INT:
09485
09486 if (IN_RANGE_P (INTVAL (x), -2048, 2047))
09487 {
09488 *total = 0;
09489 return true;
09490 }
09491
09492
09493 case CONST:
09494 case LABEL_REF:
09495 case SYMBOL_REF:
09496 case CONST_DOUBLE:
09497 *total = COSTS_N_INSNS (2);
09498 return true;
09499
09500 case PLUS:
09501 case MINUS:
09502 case AND:
09503 case IOR:
09504 case XOR:
09505 case ASHIFT:
09506 case ASHIFTRT:
09507 case LSHIFTRT:
09508 case NOT:
09509 case NEG:
09510 case COMPARE:
09511 if (GET_MODE (x) == SImode)
09512 *total = COSTS_N_INSNS (1);
09513 else if (GET_MODE (x) == DImode)
09514 *total = COSTS_N_INSNS (2);
09515 else
09516 *total = COSTS_N_INSNS (3);
09517 return true;
09518
09519 case MULT:
09520 if (GET_MODE (x) == SImode)
09521 *total = COSTS_N_INSNS (2);
09522 else
09523 *total = COSTS_N_INSNS (6);
09524 return true;
09525
09526 case DIV:
09527 case UDIV:
09528 case MOD:
09529 case UMOD:
09530 *total = COSTS_N_INSNS (18);
09531 return true;
09532
09533 case MEM:
09534 *total = COSTS_N_INSNS (3);
09535 return true;
09536
09537 default:
09538 return false;
09539 }
09540 }
09541
09542 static void
09543 frv_asm_out_constructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
09544 {
09545 switch_to_section (ctors_section);
09546 assemble_align (POINTER_SIZE);
09547 if (TARGET_FDPIC)
09548 {
09549 int ok = frv_assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, 1);
09550
09551 gcc_assert (ok);
09552 return;
09553 }
09554 assemble_integer_with_op ("\t.picptr\t", symbol);
09555 }
09556
09557 static void
09558 frv_asm_out_destructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
09559 {
09560 switch_to_section (dtors_section);
09561 assemble_align (POINTER_SIZE);
09562 if (TARGET_FDPIC)
09563 {
09564 int ok = frv_assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, 1);
09565
09566 gcc_assert (ok);
09567 return;
09568 }
09569 assemble_integer_with_op ("\t.picptr\t", symbol);
09570 }
09571
09572
09573
09574 static rtx
09575 frv_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
09576 int incoming ATTRIBUTE_UNUSED)
09577 {
09578 return gen_rtx_REG (Pmode, FRV_STRUCT_VALUE_REGNUM);
09579 }
09580
09581 #define TLS_BIAS (2048 - 16)
09582
09583
09584
09585
09586 static void
09587 frv_output_dwarf_dtprel (FILE *file, int size, rtx x)
09588 {
09589 gcc_assert (size == 4);
09590 fputs ("\t.picptr\ttlsmoff(", file);
09591
09592
09593 output_addr_const (file, plus_constant (x, TLS_BIAS));
09594 fputs (")", file);
09595 }
09596
09597 #include "gt-frv.h"