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