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