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 "tree.h"
00027 #include "rtl.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 "output.h"
00034 #include "insn-attr.h"
00035 #include "flags.h"
00036 #include "expr.h"
00037 #include "function.h"
00038 #include "recog.h"
00039 #include "toplev.h"
00040 #include "ggc.h"
00041 #include "integrate.h"
00042 #include "tm_p.h"
00043 #include "target.h"
00044 #include "target-def.h"
00045
00046
00047
00048 rtx m32r_compare_op0, m32r_compare_op1;
00049
00050
00051 char m32r_punct_chars[256];
00052
00053
00054 enum m32r_model m32r_model = M32R_MODEL_DEFAULT;
00055
00056
00057 enum m32r_sdata m32r_sdata = M32R_SDATA_DEFAULT;
00058
00059
00060 #define SYMBOL_FLAG_MODEL_SHIFT SYMBOL_FLAG_MACH_DEP_SHIFT
00061 #define SYMBOL_REF_MODEL(X) \
00062 ((enum m32r_model) ((SYMBOL_REF_FLAGS (X) >> SYMBOL_FLAG_MODEL_SHIFT) & 3))
00063
00064
00065 #define LIT_NAME_P(NAME) ((NAME)[0] == '*' && (NAME)[1] == '.')
00066
00067
00068 static bool m32r_handle_option (size_t, const char *, int);
00069 static void init_reg_tables (void);
00070 static void block_move_call (rtx, rtx, rtx);
00071 static int m32r_is_insn (rtx);
00072 const struct attribute_spec m32r_attribute_table[];
00073 static tree m32r_handle_model_attribute (tree *, tree, tree, int, bool *);
00074 static void m32r_output_function_prologue (FILE *, HOST_WIDE_INT);
00075 static void m32r_output_function_epilogue (FILE *, HOST_WIDE_INT);
00076
00077 static void m32r_file_start (void);
00078
00079 static int m32r_adjust_priority (rtx, int);
00080 static int m32r_issue_rate (void);
00081
00082 static void m32r_encode_section_info (tree, rtx, int);
00083 static bool m32r_in_small_data_p (tree);
00084 static bool m32r_return_in_memory (tree, tree);
00085 static void m32r_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
00086 tree, int *, int);
00087 static void init_idents (void);
00088 static bool m32r_rtx_costs (rtx, int, int, int *);
00089 static bool m32r_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
00090 tree, bool);
00091 static int m32r_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
00092 tree, bool);
00093
00094
00095 #undef TARGET_ATTRIBUTE_TABLE
00096 #define TARGET_ATTRIBUTE_TABLE m32r_attribute_table
00097
00098 #undef TARGET_ASM_ALIGNED_HI_OP
00099 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
00100 #undef TARGET_ASM_ALIGNED_SI_OP
00101 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
00102
00103 #undef TARGET_ASM_FUNCTION_PROLOGUE
00104 #define TARGET_ASM_FUNCTION_PROLOGUE m32r_output_function_prologue
00105 #undef TARGET_ASM_FUNCTION_EPILOGUE
00106 #define TARGET_ASM_FUNCTION_EPILOGUE m32r_output_function_epilogue
00107
00108 #undef TARGET_ASM_FILE_START
00109 #define TARGET_ASM_FILE_START m32r_file_start
00110
00111 #undef TARGET_SCHED_ADJUST_PRIORITY
00112 #define TARGET_SCHED_ADJUST_PRIORITY m32r_adjust_priority
00113 #undef TARGET_SCHED_ISSUE_RATE
00114 #define TARGET_SCHED_ISSUE_RATE m32r_issue_rate
00115
00116 #undef TARGET_DEFAULT_TARGET_FLAGS
00117 #define TARGET_DEFAULT_TARGET_FLAGS TARGET_CPU_DEFAULT
00118 #undef TARGET_HANDLE_OPTION
00119 #define TARGET_HANDLE_OPTION m32r_handle_option
00120
00121 #undef TARGET_ENCODE_SECTION_INFO
00122 #define TARGET_ENCODE_SECTION_INFO m32r_encode_section_info
00123 #undef TARGET_IN_SMALL_DATA_P
00124 #define TARGET_IN_SMALL_DATA_P m32r_in_small_data_p
00125
00126 #undef TARGET_RTX_COSTS
00127 #define TARGET_RTX_COSTS m32r_rtx_costs
00128 #undef TARGET_ADDRESS_COST
00129 #define TARGET_ADDRESS_COST hook_int_rtx_0
00130
00131 #undef TARGET_PROMOTE_PROTOTYPES
00132 #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
00133 #undef TARGET_RETURN_IN_MEMORY
00134 #define TARGET_RETURN_IN_MEMORY m32r_return_in_memory
00135 #undef TARGET_SETUP_INCOMING_VARARGS
00136 #define TARGET_SETUP_INCOMING_VARARGS m32r_setup_incoming_varargs
00137 #undef TARGET_MUST_PASS_IN_STACK
00138 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
00139 #undef TARGET_PASS_BY_REFERENCE
00140 #define TARGET_PASS_BY_REFERENCE m32r_pass_by_reference
00141 #undef TARGET_ARG_PARTIAL_BYTES
00142 #define TARGET_ARG_PARTIAL_BYTES m32r_arg_partial_bytes
00143
00144 struct gcc_target targetm = TARGET_INITIALIZER;
00145
00146
00147
00148 static bool
00149 m32r_handle_option (size_t code, const char *arg, int value)
00150 {
00151 switch (code)
00152 {
00153 case OPT_m32r:
00154 target_flags &= ~(MASK_M32R2 | MASK_M32RX);
00155 return true;
00156
00157 case OPT_mmodel_:
00158 if (strcmp (arg, "small") == 0)
00159 m32r_model = M32R_MODEL_SMALL;
00160 else if (strcmp (arg, "medium") == 0)
00161 m32r_model = M32R_MODEL_MEDIUM;
00162 else if (strcmp (arg, "large") == 0)
00163 m32r_model = M32R_MODEL_LARGE;
00164 else
00165 return false;
00166 return true;
00167
00168 case OPT_msdata_:
00169 if (strcmp (arg, "none") == 0)
00170 m32r_sdata = M32R_SDATA_NONE;
00171 else if (strcmp (arg, "sdata") == 0)
00172 m32r_sdata = M32R_SDATA_SDATA;
00173 else if (strcmp (arg, "use") == 0)
00174 m32r_sdata = M32R_SDATA_USE;
00175 else
00176 return false;
00177 return true;
00178
00179 case OPT_mno_flush_func:
00180 m32r_cache_flush_func = NULL;
00181 return true;
00182
00183 case OPT_mflush_trap_:
00184 return value <= 15;
00185
00186 case OPT_mno_flush_trap:
00187 m32r_cache_flush_trap = -1;
00188 return true;
00189
00190 default:
00191 return true;
00192 }
00193 }
00194
00195
00196
00197 void
00198 m32r_init (void)
00199 {
00200 init_reg_tables ();
00201
00202
00203 memset (m32r_punct_chars, 0, sizeof (m32r_punct_chars));
00204 m32r_punct_chars['#'] = 1;
00205 m32r_punct_chars['@'] = 1;
00206
00207
00208 if (!g_switch_set)
00209 g_switch_value = SDATA_DEFAULT_SIZE;
00210 }
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221 enum m32r_mode_class
00222 {
00223 C_MODE,
00224 S_MODE, D_MODE, T_MODE, O_MODE,
00225 SF_MODE, DF_MODE, TF_MODE, OF_MODE, A_MODE
00226 };
00227
00228
00229 #define C_MODES (1 << (int) C_MODE)
00230
00231
00232 #define S_MODES ((1 << (int) S_MODE) | (1 << (int) SF_MODE))
00233
00234
00235 #define D_MODES (S_MODES | (1 << (int) D_MODE) | (1 << DF_MODE))
00236
00237
00238 #define T_MODES (D_MODES | (1 << (int) T_MODE) | (1 << (int) TF_MODE))
00239
00240
00241 #define A_MODES (1 << (int) A_MODE)
00242
00243
00244
00245 const unsigned int m32r_hard_regno_mode_ok[FIRST_PSEUDO_REGISTER] =
00246 {
00247 T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES,
00248 T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, S_MODES, S_MODES, S_MODES,
00249 S_MODES, C_MODES, A_MODES, A_MODES
00250 };
00251
00252 unsigned int m32r_mode_class [NUM_MACHINE_MODES];
00253
00254 enum reg_class m32r_regno_reg_class[FIRST_PSEUDO_REGISTER];
00255
00256 static void
00257 init_reg_tables (void)
00258 {
00259 int i;
00260
00261 for (i = 0; i < NUM_MACHINE_MODES; i++)
00262 {
00263 switch (GET_MODE_CLASS (i))
00264 {
00265 case MODE_INT:
00266 case MODE_PARTIAL_INT:
00267 case MODE_COMPLEX_INT:
00268 if (GET_MODE_SIZE (i) <= 4)
00269 m32r_mode_class[i] = 1 << (int) S_MODE;
00270 else if (GET_MODE_SIZE (i) == 8)
00271 m32r_mode_class[i] = 1 << (int) D_MODE;
00272 else if (GET_MODE_SIZE (i) == 16)
00273 m32r_mode_class[i] = 1 << (int) T_MODE;
00274 else if (GET_MODE_SIZE (i) == 32)
00275 m32r_mode_class[i] = 1 << (int) O_MODE;
00276 else
00277 m32r_mode_class[i] = 0;
00278 break;
00279 case MODE_FLOAT:
00280 case MODE_COMPLEX_FLOAT:
00281 if (GET_MODE_SIZE (i) <= 4)
00282 m32r_mode_class[i] = 1 << (int) SF_MODE;
00283 else if (GET_MODE_SIZE (i) == 8)
00284 m32r_mode_class[i] = 1 << (int) DF_MODE;
00285 else if (GET_MODE_SIZE (i) == 16)
00286 m32r_mode_class[i] = 1 << (int) TF_MODE;
00287 else if (GET_MODE_SIZE (i) == 32)
00288 m32r_mode_class[i] = 1 << (int) OF_MODE;
00289 else
00290 m32r_mode_class[i] = 0;
00291 break;
00292 case MODE_CC:
00293 m32r_mode_class[i] = 1 << (int) C_MODE;
00294 break;
00295 default:
00296 m32r_mode_class[i] = 0;
00297 break;
00298 }
00299 }
00300
00301 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
00302 {
00303 if (GPR_P (i))
00304 m32r_regno_reg_class[i] = GENERAL_REGS;
00305 else if (i == ARG_POINTER_REGNUM)
00306 m32r_regno_reg_class[i] = GENERAL_REGS;
00307 else
00308 m32r_regno_reg_class[i] = NO_REGS;
00309 }
00310 }
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324 static tree small_ident1;
00325 static tree small_ident2;
00326 static tree medium_ident1;
00327 static tree medium_ident2;
00328 static tree large_ident1;
00329 static tree large_ident2;
00330
00331 static void
00332 init_idents (void)
00333 {
00334 if (small_ident1 == 0)
00335 {
00336 small_ident1 = get_identifier ("small");
00337 small_ident2 = get_identifier ("__small__");
00338 medium_ident1 = get_identifier ("medium");
00339 medium_ident2 = get_identifier ("__medium__");
00340 large_ident1 = get_identifier ("large");
00341 large_ident2 = get_identifier ("__large__");
00342 }
00343 }
00344
00345 const struct attribute_spec m32r_attribute_table[] =
00346 {
00347
00348 { "interrupt", 0, 0, true, false, false, NULL },
00349 { "model", 1, 1, true, false, false, m32r_handle_model_attribute },
00350 { NULL, 0, 0, false, false, false, NULL }
00351 };
00352
00353
00354
00355
00356 static tree
00357 m32r_handle_model_attribute (tree *node ATTRIBUTE_UNUSED, tree name,
00358 tree args, int flags ATTRIBUTE_UNUSED,
00359 bool *no_add_attrs)
00360 {
00361 tree arg;
00362
00363 init_idents ();
00364 arg = TREE_VALUE (args);
00365
00366 if (arg != small_ident1
00367 && arg != small_ident2
00368 && arg != medium_ident1
00369 && arg != medium_ident2
00370 && arg != large_ident1
00371 && arg != large_ident2)
00372 {
00373 warning (OPT_Wattributes, "invalid argument of %qs attribute",
00374 IDENTIFIER_POINTER (name));
00375 *no_add_attrs = true;
00376 }
00377
00378 return NULL_TREE;
00379 }
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390 static void
00391 m32r_encode_section_info (tree decl, rtx rtl, int first)
00392 {
00393 int extra_flags = 0;
00394 tree model_attr;
00395 enum m32r_model model;
00396
00397 default_encode_section_info (decl, rtl, first);
00398
00399 if (!DECL_P (decl))
00400 return;
00401
00402 model_attr = lookup_attribute ("model", DECL_ATTRIBUTES (decl));
00403 if (model_attr)
00404 {
00405 tree id;
00406
00407 init_idents ();
00408
00409 id = TREE_VALUE (TREE_VALUE (model_attr));
00410
00411 if (id == small_ident1 || id == small_ident2)
00412 model = M32R_MODEL_SMALL;
00413 else if (id == medium_ident1 || id == medium_ident2)
00414 model = M32R_MODEL_MEDIUM;
00415 else if (id == large_ident1 || id == large_ident2)
00416 model = M32R_MODEL_LARGE;
00417 else
00418 gcc_unreachable ();
00419 }
00420 else
00421 {
00422 if (TARGET_MODEL_SMALL)
00423 model = M32R_MODEL_SMALL;
00424 else if (TARGET_MODEL_MEDIUM)
00425 model = M32R_MODEL_MEDIUM;
00426 else if (TARGET_MODEL_LARGE)
00427 model = M32R_MODEL_LARGE;
00428 else
00429 gcc_unreachable ();
00430 }
00431 extra_flags |= model << SYMBOL_FLAG_MODEL_SHIFT;
00432
00433 if (extra_flags)
00434 SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= extra_flags;
00435 }
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447 static bool
00448 m32r_in_small_data_p (tree decl)
00449 {
00450 tree section;
00451
00452 if (TREE_CODE (decl) != VAR_DECL)
00453 return false;
00454
00455 if (lookup_attribute ("model", DECL_ATTRIBUTES (decl)))
00456 return false;
00457
00458 section = DECL_SECTION_NAME (decl);
00459 if (section)
00460 {
00461 char *name = (char *) TREE_STRING_POINTER (section);
00462 if (strcmp (name, ".sdata") == 0 || strcmp (name, ".sbss") == 0)
00463 return true;
00464 }
00465 else
00466 {
00467 if (! TREE_READONLY (decl) && ! TARGET_SDATA_NONE)
00468 {
00469 int size = int_size_in_bytes (TREE_TYPE (decl));
00470
00471 if (size > 0 && (unsigned HOST_WIDE_INT) size <= g_switch_value)
00472 return true;
00473 }
00474 }
00475
00476 return false;
00477 }
00478
00479
00480
00481 void
00482 m32r_init_expanders (void)
00483 {
00484
00485
00486 }
00487
00488 int
00489 call_operand (rtx op, enum machine_mode mode)
00490 {
00491 if (GET_CODE (op) != MEM)
00492 return 0;
00493 op = XEXP (op, 0);
00494 return call_address_operand (op, mode);
00495 }
00496
00497
00498
00499 int
00500 small_data_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
00501 {
00502 if (! TARGET_SDATA_USE)
00503 return 0;
00504
00505 if (GET_CODE (op) == SYMBOL_REF)
00506 return SYMBOL_REF_SMALL_P (op);
00507
00508 if (GET_CODE (op) == CONST
00509 && GET_CODE (XEXP (op, 0)) == PLUS
00510 && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
00511 && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT
00512 && INT16_P (INTVAL (XEXP (XEXP (op, 0), 1))))
00513 return SYMBOL_REF_SMALL_P (XEXP (XEXP (op, 0), 0));
00514
00515 return 0;
00516 }
00517
00518
00519
00520 int
00521 addr24_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
00522 {
00523 rtx sym;
00524
00525 if (flag_pic)
00526 return 0;
00527
00528 if (GET_CODE (op) == LABEL_REF)
00529 return TARGET_ADDR24;
00530
00531 if (GET_CODE (op) == SYMBOL_REF)
00532 sym = op;
00533 else if (GET_CODE (op) == CONST
00534 && GET_CODE (XEXP (op, 0)) == PLUS
00535 && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
00536 && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT
00537 && UINT24_P (INTVAL (XEXP (XEXP (op, 0), 1))))
00538 sym = XEXP (XEXP (op, 0), 0);
00539 else
00540 return 0;
00541
00542 if (SYMBOL_REF_MODEL (sym) == M32R_MODEL_SMALL)
00543 return 1;
00544
00545 if (TARGET_ADDR24
00546 && (CONSTANT_POOL_ADDRESS_P (sym)
00547 || LIT_NAME_P (XSTR (sym, 0))))
00548 return 1;
00549
00550 return 0;
00551 }
00552
00553
00554
00555 int
00556 addr32_operand (rtx op, enum machine_mode mode)
00557 {
00558 rtx sym;
00559
00560 if (GET_CODE (op) == LABEL_REF)
00561 return TARGET_ADDR32;
00562
00563 if (GET_CODE (op) == SYMBOL_REF)
00564 sym = op;
00565 else if (GET_CODE (op) == CONST
00566 && GET_CODE (XEXP (op, 0)) == PLUS
00567 && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
00568 && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT
00569 && ! flag_pic)
00570 sym = XEXP (XEXP (op, 0), 0);
00571 else
00572 return 0;
00573
00574 return (! addr24_operand (sym, mode)
00575 && ! small_data_operand (sym, mode));
00576 }
00577
00578
00579
00580 int
00581 call26_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
00582 {
00583 if (flag_pic)
00584 return 1;
00585
00586 if (GET_CODE (op) == SYMBOL_REF)
00587 return SYMBOL_REF_MODEL (op) != M32R_MODEL_LARGE;
00588
00589 return TARGET_CALL26;
00590 }
00591
00592
00593
00594
00595
00596 int
00597 easy_di_const (rtx op)
00598 {
00599 rtx high_rtx, low_rtx;
00600 HOST_WIDE_INT high, low;
00601
00602 split_double (op, &high_rtx, &low_rtx);
00603 high = INTVAL (high_rtx);
00604 low = INTVAL (low_rtx);
00605
00606 if (high >= -128 && high <= 127
00607 && low >= -128 && low <= 127)
00608 return 1;
00609 return 0;
00610 }
00611
00612
00613
00614
00615
00616 int
00617 easy_df_const (rtx op)
00618 {
00619 REAL_VALUE_TYPE r;
00620 long l[2];
00621
00622 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
00623 REAL_VALUE_TO_TARGET_DOUBLE (r, l);
00624 if (l[0] == 0 && l[1] == 0)
00625 return 1;
00626 if ((l[0] & 0xffff) == 0 && l[1] == 0)
00627 return 1;
00628 return 0;
00629 }
00630
00631
00632
00633
00634 int
00635 memreg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
00636 {
00637 return GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == REG;
00638 }
00639
00640
00641
00642 static bool
00643 m32r_pass_by_reference (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
00644 enum machine_mode mode, tree type,
00645 bool named ATTRIBUTE_UNUSED)
00646 {
00647 int size;
00648
00649 if (type)
00650 size = int_size_in_bytes (type);
00651 else
00652 size = GET_MODE_SIZE (mode);
00653
00654 return (size < 0 || size > 8);
00655 }
00656
00657
00658
00659
00660
00661
00662
00663
00664 rtx
00665 gen_compare (enum rtx_code code, rtx x, rtx y, int need_compare)
00666 {
00667 enum rtx_code compare_code;
00668 enum rtx_code branch_code;
00669 rtx cc_reg = gen_rtx_REG (CCmode, CARRY_REGNUM);
00670 int must_swap = 0;
00671
00672 switch (code)
00673 {
00674 case EQ: compare_code = EQ; branch_code = NE; break;
00675 case NE: compare_code = EQ; branch_code = EQ; break;
00676 case LT: compare_code = LT; branch_code = NE; break;
00677 case LE: compare_code = LT; branch_code = EQ; must_swap = 1; break;
00678 case GT: compare_code = LT; branch_code = NE; must_swap = 1; break;
00679 case GE: compare_code = LT; branch_code = EQ; break;
00680 case LTU: compare_code = LTU; branch_code = NE; break;
00681 case LEU: compare_code = LTU; branch_code = EQ; must_swap = 1; break;
00682 case GTU: compare_code = LTU; branch_code = NE; must_swap = 1; break;
00683 case GEU: compare_code = LTU; branch_code = EQ; break;
00684
00685 default:
00686 gcc_unreachable ();
00687 }
00688
00689 if (need_compare)
00690 {
00691 switch (compare_code)
00692 {
00693 case EQ:
00694 if (GET_CODE (y) == CONST_INT
00695 && CMP_INT16_P (INTVAL (y))
00696 && y != const0_rtx)
00697 {
00698 rtx tmp = gen_reg_rtx (SImode);
00699
00700 emit_insn (gen_addsi3 (tmp, x, GEN_INT (-INTVAL (y))));
00701 x = tmp;
00702 y = const0_rtx;
00703 }
00704 else if (CONSTANT_P (y))
00705 {
00706 rtx tmp = force_reg (GET_MODE (x), y);
00707 y = tmp;
00708 }
00709
00710 if (register_operand (y, SImode)
00711 || y == const0_rtx)
00712 {
00713 emit_insn (gen_cmp_eqsi_insn (x, y));
00714
00715 return gen_rtx_fmt_ee (code, CCmode, cc_reg, const0_rtx);
00716 }
00717 break;
00718
00719 case LT:
00720 if (register_operand (y, SImode)
00721 || (GET_CODE (y) == CONST_INT && CMP_INT16_P (INTVAL (y))))
00722 {
00723 rtx tmp = gen_reg_rtx (SImode);
00724
00725 switch (code)
00726 {
00727 case LT:
00728 emit_insn (gen_cmp_ltsi_insn (x, y));
00729 code = EQ;
00730 break;
00731 case LE:
00732 if (y == const0_rtx)
00733 tmp = const1_rtx;
00734 else
00735 emit_insn (gen_addsi3 (tmp, y, constm1_rtx));
00736 emit_insn (gen_cmp_ltsi_insn (x, tmp));
00737 code = EQ;
00738 break;
00739 case GT:
00740 if (GET_CODE (y) == CONST_INT)
00741 tmp = gen_rtx_PLUS (SImode, y, const1_rtx);
00742 else
00743 emit_insn (gen_addsi3 (tmp, y, constm1_rtx));
00744 emit_insn (gen_cmp_ltsi_insn (x, tmp));
00745 code = NE;
00746 break;
00747 case GE:
00748 emit_insn (gen_cmp_ltsi_insn (x, y));
00749 code = NE;
00750 break;
00751 default:
00752 gcc_unreachable ();
00753 }
00754
00755 return gen_rtx_fmt_ee (code, CCmode, cc_reg, const0_rtx);
00756 }
00757 break;
00758
00759 case LTU:
00760 if (register_operand (y, SImode)
00761 || (GET_CODE (y) == CONST_INT && CMP_INT16_P (INTVAL (y))))
00762 {
00763 rtx tmp = gen_reg_rtx (SImode);
00764
00765 switch (code)
00766 {
00767 case LTU:
00768 emit_insn (gen_cmp_ltusi_insn (x, y));
00769 code = EQ;
00770 break;
00771 case LEU:
00772 if (y == const0_rtx)
00773 tmp = const1_rtx;
00774 else
00775 emit_insn (gen_addsi3 (tmp, y, constm1_rtx));
00776 emit_insn (gen_cmp_ltusi_insn (x, tmp));
00777 code = EQ;
00778 break;
00779 case GTU:
00780 if (GET_CODE (y) == CONST_INT)
00781 tmp = gen_rtx_PLUS (SImode, y, const1_rtx);
00782 else
00783 emit_insn (gen_addsi3 (tmp, y, constm1_rtx));
00784 emit_insn (gen_cmp_ltusi_insn (x, tmp));
00785 code = NE;
00786 break;
00787 case GEU:
00788 emit_insn (gen_cmp_ltusi_insn (x, y));
00789 code = NE;
00790 break;
00791 default:
00792 gcc_unreachable ();
00793 }
00794
00795 return gen_rtx_fmt_ee (code, CCmode, cc_reg, const0_rtx);
00796 }
00797 break;
00798
00799 default:
00800 gcc_unreachable ();
00801 }
00802 }
00803 else
00804 {
00805
00806 if (compare_code == EQ
00807 && register_operand (y, SImode))
00808 return gen_rtx_fmt_ee (code, CCmode, x, y);
00809
00810
00811 if ((compare_code == EQ || compare_code == LT)
00812 && y == const0_rtx)
00813 return gen_rtx_fmt_ee (code, CCmode, x, y);
00814
00815
00816 if (compare_code == EQ
00817 && GET_CODE (y) == CONST_INT
00818 && CMP_INT16_P (INTVAL (y)))
00819 {
00820 rtx tmp = gen_reg_rtx (SImode);
00821
00822 emit_insn (gen_addsi3 (tmp, x, GEN_INT (-INTVAL (y))));
00823 return gen_rtx_fmt_ee (code, CCmode, tmp, const0_rtx);
00824 }
00825
00826
00827 if (compare_code == EQ
00828 && CONSTANT_P (y))
00829 {
00830 rtx tmp = force_reg (GET_MODE (x), y);
00831
00832 return gen_rtx_fmt_ee (code, CCmode, x, tmp);
00833 }
00834 }
00835
00836 if (CONSTANT_P (y))
00837 {
00838 if (must_swap)
00839 y = force_reg (GET_MODE (x), y);
00840 else
00841 {
00842 int ok_const = reg_or_int16_operand (y, GET_MODE (y));
00843
00844 if (! ok_const)
00845 y = force_reg (GET_MODE (x), y);
00846 }
00847 }
00848
00849 switch (compare_code)
00850 {
00851 case EQ :
00852 emit_insn (gen_cmp_eqsi_insn (must_swap ? y : x, must_swap ? x : y));
00853 break;
00854 case LT :
00855 emit_insn (gen_cmp_ltsi_insn (must_swap ? y : x, must_swap ? x : y));
00856 break;
00857 case LTU :
00858 emit_insn (gen_cmp_ltusi_insn (must_swap ? y : x, must_swap ? x : y));
00859 break;
00860
00861 default:
00862 gcc_unreachable ();
00863 }
00864
00865 return gen_rtx_fmt_ee (branch_code, VOIDmode, cc_reg, CONST0_RTX (CCmode));
00866 }
00867
00868
00869
00870 rtx
00871 gen_split_move_double (rtx operands[])
00872 {
00873 enum machine_mode mode = GET_MODE (operands[0]);
00874 rtx dest = operands[0];
00875 rtx src = operands[1];
00876 rtx val;
00877
00878
00879
00880
00881 if (GET_CODE (dest) == SUBREG)
00882 alter_subreg (&dest);
00883 if (GET_CODE (src) == SUBREG)
00884 alter_subreg (&src);
00885
00886 start_sequence ();
00887 if (GET_CODE (dest) == REG)
00888 {
00889 int dregno = REGNO (dest);
00890
00891
00892 if (GET_CODE (src) == REG)
00893 {
00894 int sregno = REGNO (src);
00895
00896 int reverse = (dregno == sregno + 1);
00897
00898
00899
00900
00901 emit_insn (gen_rtx_SET (VOIDmode,
00902 operand_subword (dest, reverse, TRUE, mode),
00903 operand_subword (src, reverse, TRUE, mode)));
00904
00905 emit_insn (gen_rtx_SET (VOIDmode,
00906 operand_subword (dest, !reverse, TRUE, mode),
00907 operand_subword (src, !reverse, TRUE, mode)));
00908 }
00909
00910
00911 else if (GET_CODE (src) == CONST_INT || GET_CODE (src) == CONST_DOUBLE)
00912 {
00913 rtx words[2];
00914 split_double (src, &words[0], &words[1]);
00915 emit_insn (gen_rtx_SET (VOIDmode,
00916 operand_subword (dest, 0, TRUE, mode),
00917 words[0]));
00918
00919 emit_insn (gen_rtx_SET (VOIDmode,
00920 operand_subword (dest, 1, TRUE, mode),
00921 words[1]));
00922 }
00923
00924
00925 else if (GET_CODE (src) == MEM)
00926 {
00927
00928
00929 int reverse
00930 = (refers_to_regno_p (dregno, dregno + 1, XEXP (src, 0), 0) != 0);
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943 emit_insn (gen_rtx_SET (VOIDmode,
00944 operand_subword (dest, reverse, TRUE, mode),
00945 adjust_address (src, SImode,
00946 reverse * UNITS_PER_WORD)));
00947
00948 emit_insn (gen_rtx_SET (VOIDmode,
00949 operand_subword (dest, !reverse, TRUE, mode),
00950 adjust_address (src, SImode,
00951 !reverse * UNITS_PER_WORD)));
00952 }
00953 else
00954 gcc_unreachable ();
00955 }
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969 else if (GET_CODE (dest) == MEM && GET_CODE (src) == REG)
00970 {
00971 emit_insn (gen_rtx_SET (VOIDmode,
00972 adjust_address (dest, SImode, 0),
00973 operand_subword (src, 0, TRUE, mode)));
00974
00975 emit_insn (gen_rtx_SET (VOIDmode,
00976 adjust_address (dest, SImode, UNITS_PER_WORD),
00977 operand_subword (src, 1, TRUE, mode)));
00978 }
00979
00980 else
00981 gcc_unreachable ();
00982
00983 val = get_insns ();
00984 end_sequence ();
00985 return val;
00986 }
00987
00988
00989 static int
00990 m32r_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
00991 tree type, bool named ATTRIBUTE_UNUSED)
00992 {
00993 int words;
00994 unsigned int size =
00995 (((mode == BLKmode && type)
00996 ? (unsigned int) int_size_in_bytes (type)
00997 : GET_MODE_SIZE (mode)) + UNITS_PER_WORD - 1)
00998 / UNITS_PER_WORD;
00999
01000 if (*cum >= M32R_MAX_PARM_REGS)
01001 words = 0;
01002 else if (*cum + size > M32R_MAX_PARM_REGS)
01003 words = (*cum + size) - M32R_MAX_PARM_REGS;
01004 else
01005 words = 0;
01006
01007 return words * UNITS_PER_WORD;
01008 }
01009
01010
01011
01012 static bool
01013 m32r_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
01014 {
01015 return m32r_pass_by_reference (NULL, TYPE_MODE (type), type, false);
01016 }
01017
01018
01019
01020
01021
01022
01023
01024
01025 static void
01026 m32r_setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
01027 tree type, int *pretend_size, int no_rtl)
01028 {
01029 int first_anon_arg;
01030
01031 if (no_rtl)
01032 return;
01033
01034
01035 gcc_assert (mode != BLKmode);
01036
01037 first_anon_arg = (ROUND_ADVANCE_CUM (*cum, mode, type)
01038 + ROUND_ADVANCE_ARG (mode, type));
01039
01040 if (first_anon_arg < M32R_MAX_PARM_REGS)
01041 {
01042
01043 int first_reg_offset = first_anon_arg;
01044
01045 int size = M32R_MAX_PARM_REGS - first_reg_offset;
01046 rtx regblock;
01047
01048 regblock = gen_rtx_MEM (BLKmode,
01049 plus_constant (arg_pointer_rtx,
01050 FIRST_PARM_OFFSET (0)));
01051 set_mem_alias_set (regblock, get_varargs_alias_set ());
01052 move_block_from_reg (first_reg_offset, regblock, size);
01053
01054 *pretend_size = (size * UNITS_PER_WORD);
01055 }
01056 }
01057
01058
01059
01060
01061 static int
01062 m32r_is_insn (rtx insn)
01063 {
01064 return (INSN_P (insn)
01065 && GET_CODE (PATTERN (insn)) != USE
01066 && GET_CODE (PATTERN (insn)) != CLOBBER
01067 && GET_CODE (PATTERN (insn)) != ADDR_VEC);
01068 }
01069
01070
01071
01072
01073 static int
01074 m32r_adjust_priority (rtx insn, int priority)
01075 {
01076 if (m32r_is_insn (insn)
01077 && get_attr_insn_size (insn) != INSN_SIZE_SHORT)
01078 priority <<= 3;
01079
01080 return priority;
01081 }
01082
01083
01084
01085
01086
01087
01088
01089
01090 static int
01091 m32r_issue_rate (void)
01092 {
01093 return ((TARGET_LOW_ISSUE_RATE) ? 1 : 2);
01094 }
01095
01096
01097
01098 static bool
01099 m32r_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total)
01100 {
01101 switch (code)
01102 {
01103
01104
01105
01106 case CONST_INT:
01107 if (INT16_P (INTVAL (x)))
01108 {
01109 *total = 0;
01110 return true;
01111 }
01112
01113
01114 case CONST:
01115 case LABEL_REF:
01116 case SYMBOL_REF:
01117 *total = COSTS_N_INSNS (1);
01118 return true;
01119
01120 case CONST_DOUBLE:
01121 {
01122 rtx high, low;
01123
01124 split_double (x, &high, &low);
01125 *total = COSTS_N_INSNS (!INT16_P (INTVAL (high))
01126 + !INT16_P (INTVAL (low)));
01127 return true;
01128 }
01129
01130 case MULT:
01131 *total = COSTS_N_INSNS (3);
01132 return true;
01133
01134 case DIV:
01135 case UDIV:
01136 case MOD:
01137 case UMOD:
01138 *total = COSTS_N_INSNS (10);
01139 return true;
01140
01141 default:
01142 return false;
01143 }
01144 }
01145
01146
01147
01148
01149
01150
01151 enum m32r_function_type
01152 m32r_compute_function_type (tree decl)
01153 {
01154
01155 static enum m32r_function_type fn_type = M32R_FUNCTION_UNKNOWN;
01156
01157 static tree last_fn = NULL_TREE;
01158
01159
01160 if (decl == NULL_TREE)
01161 {
01162 fn_type = M32R_FUNCTION_UNKNOWN;
01163 last_fn = NULL_TREE;
01164 return fn_type;
01165 }
01166
01167 if (decl == last_fn && fn_type != M32R_FUNCTION_UNKNOWN)
01168 return fn_type;
01169
01170
01171 fn_type = (lookup_attribute ("interrupt", DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE
01172 ? M32R_FUNCTION_INTERRUPT
01173 : M32R_FUNCTION_NORMAL);
01174
01175 last_fn = decl;
01176 return fn_type;
01177 }
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229 struct m32r_frame_info
01230 {
01231 unsigned int total_size;
01232 unsigned int extra_size;
01233 unsigned int pretend_size;
01234 unsigned int args_size;
01235 unsigned int reg_size;
01236 unsigned int var_size;
01237 unsigned int gmask;
01238 unsigned int save_fp;
01239 unsigned int save_lr;
01240 int initialized;
01241 };
01242
01243
01244 static struct m32r_frame_info current_frame_info;
01245
01246
01247 static struct m32r_frame_info zero_frame_info;
01248
01249 #define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM))
01250 #define RETURN_ADDR_MASK (1 << (RETURN_ADDR_REGNUM))
01251
01252
01253
01254
01255 #define MUST_SAVE_REGISTER(regno, interrupt_p) \
01256 ((regno) != RETURN_ADDR_REGNUM && (regno) != FRAME_POINTER_REGNUM \
01257 && (regs_ever_live[regno] && (!call_really_used_regs[regno] || interrupt_p)))
01258
01259 #define MUST_SAVE_FRAME_POINTER (regs_ever_live[FRAME_POINTER_REGNUM])
01260 #define MUST_SAVE_RETURN_ADDR (regs_ever_live[RETURN_ADDR_REGNUM] || current_function_profile)
01261
01262 #define SHORT_INSN_SIZE 2
01263 #define LONG_INSN_SIZE 4
01264
01265
01266
01267
01268
01269
01270 unsigned int
01271 m32r_compute_frame_size (int size)
01272 {
01273 int regno;
01274 unsigned int total_size, var_size, args_size, pretend_size, extra_size;
01275 unsigned int reg_size, frame_size;
01276 unsigned int gmask;
01277 enum m32r_function_type fn_type;
01278 int interrupt_p;
01279 int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
01280 | current_function_profile);
01281
01282 var_size = M32R_STACK_ALIGN (size);
01283 args_size = M32R_STACK_ALIGN (current_function_outgoing_args_size);
01284 pretend_size = current_function_pretend_args_size;
01285 extra_size = FIRST_PARM_OFFSET (0);
01286 total_size = extra_size + pretend_size + args_size + var_size;
01287 reg_size = 0;
01288 gmask = 0;
01289
01290
01291
01292 fn_type = m32r_compute_function_type (current_function_decl);
01293 interrupt_p = M32R_INTERRUPT_P (fn_type);
01294
01295
01296 for (regno = 0; regno < M32R_MAX_INT_REGS; regno++)
01297 {
01298 if (MUST_SAVE_REGISTER (regno, interrupt_p)
01299 || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
01300 {
01301 reg_size += UNITS_PER_WORD;
01302 gmask |= 1 << regno;
01303 }
01304 }
01305
01306 current_frame_info.save_fp = MUST_SAVE_FRAME_POINTER;
01307 current_frame_info.save_lr = MUST_SAVE_RETURN_ADDR || pic_reg_used;
01308
01309 reg_size += ((current_frame_info.save_fp + current_frame_info.save_lr)
01310 * UNITS_PER_WORD);
01311 total_size += reg_size;
01312
01313
01314
01315 total_size = M32R_STACK_ALIGN (total_size);
01316
01317 frame_size = total_size - (pretend_size + reg_size);
01318
01319
01320 current_frame_info.total_size = total_size;
01321 current_frame_info.extra_size = extra_size;
01322 current_frame_info.pretend_size = pretend_size;
01323 current_frame_info.var_size = var_size;
01324 current_frame_info.args_size = args_size;
01325 current_frame_info.reg_size = reg_size;
01326 current_frame_info.gmask = gmask;
01327 current_frame_info.initialized = reload_completed;
01328
01329
01330 return total_size;
01331 }
01332
01333
01334 static rtx global_offset_table;
01335
01336 static void
01337 m32r_reload_lr (rtx sp, int size)
01338 {
01339 rtx lr = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
01340
01341 if (size == 0)
01342 emit_insn (gen_movsi (lr, gen_rtx_MEM (Pmode, sp)));
01343 else if (size < 32768)
01344 emit_insn (gen_movsi (lr, gen_rtx_MEM (Pmode,
01345 gen_rtx_PLUS (Pmode, sp,
01346 GEN_INT (size)))));
01347 else
01348 {
01349 rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM);
01350
01351 emit_insn (gen_movsi (tmp, GEN_INT (size)));
01352 emit_insn (gen_addsi3 (tmp, tmp, sp));
01353 emit_insn (gen_movsi (lr, gen_rtx_MEM (Pmode, tmp)));
01354 }
01355
01356 emit_insn (gen_rtx_USE (VOIDmode, lr));
01357 }
01358
01359 void
01360 m32r_load_pic_register (void)
01361 {
01362 global_offset_table = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
01363 emit_insn (gen_get_pc (pic_offset_table_rtx, global_offset_table,
01364 GEN_INT (TARGET_MODEL_SMALL)));
01365
01366
01367
01368 emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
01369 }
01370
01371
01372
01373 void
01374 m32r_expand_prologue (void)
01375 {
01376 int regno;
01377 int frame_size;
01378 unsigned int gmask;
01379 int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
01380 | current_function_profile);
01381
01382 if (! current_frame_info.initialized)
01383 m32r_compute_frame_size (get_frame_size ());
01384
01385 gmask = current_frame_info.gmask;
01386
01387
01388 gcc_assert (current_frame_info.total_size || !gmask);
01389
01390
01391 if (current_frame_info.pretend_size != 0)
01392 {
01393
01394
01395 HOST_WIDE_INT pretend_size = current_frame_info.pretend_size;
01396 emit_insn (gen_addsi3 (stack_pointer_rtx,
01397 stack_pointer_rtx,
01398 GEN_INT (-pretend_size)));
01399 }
01400
01401
01402 if (current_frame_info.save_fp)
01403 emit_insn (gen_movsi_push (stack_pointer_rtx, frame_pointer_rtx));
01404
01405 gmask &= ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK);
01406
01407
01408
01409 for (regno = 0; regno <= M32R_MAX_INT_REGS; ++regno)
01410 {
01411 if ((gmask & (1 << regno)) != 0)
01412 emit_insn (gen_movsi_push (stack_pointer_rtx,
01413 gen_rtx_REG (Pmode, regno)));
01414 }
01415
01416 if (current_frame_info.save_lr)
01417 emit_insn (gen_movsi_push (stack_pointer_rtx,
01418 gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM)));
01419
01420
01421 frame_size = (current_frame_info.total_size
01422 - (current_frame_info.pretend_size
01423 + current_frame_info.reg_size));
01424
01425 if (frame_size == 0)
01426 ;
01427 else if (frame_size <= 32768)
01428 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
01429 GEN_INT (-frame_size)));
01430 else
01431 {
01432 rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM);
01433
01434 emit_insn (gen_movsi (tmp, GEN_INT (frame_size)));
01435 emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp));
01436 }
01437
01438 if (frame_pointer_needed)
01439 emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));
01440
01441 if (current_function_profile)
01442
01443 emit_insn (gen_movsi_push (stack_pointer_rtx,
01444 gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM)));
01445
01446 if (pic_reg_used)
01447 {
01448 m32r_load_pic_register ();
01449 m32r_reload_lr (stack_pointer_rtx,
01450 (current_function_profile ? 0 : frame_size));
01451 }
01452
01453 if (current_function_profile && !pic_reg_used)
01454 emit_insn (gen_blockage ());
01455 }
01456
01457
01458
01459
01460
01461
01462 static void
01463 m32r_output_function_prologue (FILE * file, HOST_WIDE_INT size)
01464 {
01465 enum m32r_function_type fn_type = m32r_compute_function_type (current_function_decl);
01466
01467
01468 if (M32R_INTERRUPT_P (fn_type))
01469 fprintf (file, "\t%s interrupt handler\n", ASM_COMMENT_START);
01470
01471 if (! current_frame_info.initialized)
01472 m32r_compute_frame_size (size);
01473
01474
01475 fprintf (file,
01476 "\t%s PROLOGUE, vars= %d, regs= %d, args= %d, extra= %d\n",
01477 ASM_COMMENT_START,
01478 current_frame_info.var_size,
01479 current_frame_info.reg_size / 4,
01480 current_frame_info.args_size,
01481 current_frame_info.extra_size);
01482 }
01483
01484
01485
01486
01487 static void
01488 m32r_output_function_epilogue (FILE * file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
01489 {
01490 int regno;
01491 int noepilogue = FALSE;
01492 int total_size;
01493 enum m32r_function_type fn_type = m32r_compute_function_type (current_function_decl);
01494
01495
01496 fprintf (file, "\t%s EPILOGUE\n", ASM_COMMENT_START);
01497
01498 gcc_assert (current_frame_info.initialized);
01499 total_size = current_frame_info.total_size;
01500
01501 if (total_size == 0)
01502 {
01503 rtx insn = get_last_insn ();
01504
01505
01506
01507 if (GET_CODE (insn) == NOTE)
01508 insn = prev_nonnote_insn (insn);
01509 if (insn && GET_CODE (insn) == BARRIER)
01510 noepilogue = TRUE;
01511 }
01512
01513 if (!noepilogue)
01514 {
01515 unsigned int var_size = current_frame_info.var_size;
01516 unsigned int args_size = current_frame_info.args_size;
01517 unsigned int gmask = current_frame_info.gmask;
01518 int can_trust_sp_p = !current_function_calls_alloca;
01519 const char * sp_str = reg_names[STACK_POINTER_REGNUM];
01520 const char * fp_str = reg_names[FRAME_POINTER_REGNUM];
01521
01522
01523
01524 if (can_trust_sp_p)
01525 {
01526 unsigned int reg_offset = var_size + args_size;
01527 if (reg_offset == 0)
01528 ;
01529 else if (reg_offset < 128)
01530 fprintf (file, "\taddi %s,%s%d\n",
01531 sp_str, IMMEDIATE_PREFIX, reg_offset);
01532 else if (reg_offset < 32768)
01533 fprintf (file, "\tadd3 %s,%s,%s%d\n",
01534 sp_str, sp_str, IMMEDIATE_PREFIX, reg_offset);
01535 else if (reg_offset < (1 << 24))
01536 fprintf (file, "\tld24 %s,%s%d\n\tadd %s,%s\n",
01537 reg_names[PROLOGUE_TMP_REGNUM],
01538 IMMEDIATE_PREFIX, reg_offset,
01539 sp_str, reg_names[PROLOGUE_TMP_REGNUM]);
01540 else
01541 fprintf (file, "\tseth %s,%s%d\n\tor3 %s,%s,%s%d\n\tadd %s,%s\n",
01542 reg_names[PROLOGUE_TMP_REGNUM],
01543 IMMEDIATE_PREFIX, reg_offset >> 16,
01544 reg_names[PROLOGUE_TMP_REGNUM],
01545 reg_names[PROLOGUE_TMP_REGNUM],
01546 IMMEDIATE_PREFIX, reg_offset & 0xffff,
01547 sp_str, reg_names[PROLOGUE_TMP_REGNUM]);
01548 }
01549 else if (frame_pointer_needed)
01550 {
01551 unsigned int reg_offset = var_size + args_size;
01552
01553 if (reg_offset == 0)
01554 fprintf (file, "\tmv %s,%s\n", sp_str, fp_str);
01555 else if (reg_offset < 32768)
01556 fprintf (file, "\tadd3 %s,%s,%s%d\n",
01557 sp_str, fp_str, IMMEDIATE_PREFIX, reg_offset);
01558 else if (reg_offset < (1 << 24))
01559 fprintf (file, "\tld24 %s,%s%d\n\tadd %s,%s\n",
01560 reg_names[PROLOGUE_TMP_REGNUM],
01561 IMMEDIATE_PREFIX, reg_offset,
01562 sp_str, reg_names[PROLOGUE_TMP_REGNUM]);
01563 else
01564 fprintf (file, "\tseth %s,%s%d\n\tor3 %s,%s,%s%d\n\tadd %s,%s\n",
01565 reg_names[PROLOGUE_TMP_REGNUM],
01566 IMMEDIATE_PREFIX, reg_offset >> 16,
01567 reg_names[PROLOGUE_TMP_REGNUM],
01568 reg_names[PROLOGUE_TMP_REGNUM],
01569 IMMEDIATE_PREFIX, reg_offset & 0xffff,
01570 sp_str, reg_names[PROLOGUE_TMP_REGNUM]);
01571 }
01572 else
01573 gcc_unreachable ();
01574
01575 if (current_frame_info.save_lr)
01576 fprintf (file, "\tpop %s\n", reg_names[RETURN_ADDR_REGNUM]);
01577
01578
01579 gmask &= ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK);
01580 for (regno = M32R_MAX_INT_REGS - 1; regno >= 0; --regno)
01581 {
01582 if ((gmask & (1L << regno)) != 0)
01583 fprintf (file, "\tpop %s\n", reg_names[regno]);
01584 }
01585
01586 if (current_frame_info.save_fp)
01587 fprintf (file, "\tpop %s\n", fp_str);
01588
01589
01590 if (current_frame_info.pretend_size != 0)
01591 fprintf (file, "\taddi %s,%s%d\n",
01592 sp_str, IMMEDIATE_PREFIX, current_frame_info.pretend_size);
01593
01594
01595 if (M32R_INTERRUPT_P (fn_type))
01596 fprintf (file, "\trte\n");
01597 else
01598 fprintf (file, "\tjmp %s\n", reg_names[RETURN_ADDR_REGNUM]);
01599 }
01600
01601
01602 current_frame_info = zero_frame_info;
01603 m32r_compute_function_type (NULL_TREE);
01604 }
01605
01606
01607
01608
01609 int
01610 direct_return (void)
01611 {
01612 if (!reload_completed)
01613 return FALSE;
01614
01615 if (! current_frame_info.initialized)
01616 m32r_compute_frame_size (get_frame_size ());
01617
01618 return current_frame_info.total_size == 0;
01619 }
01620
01621
01622
01623
01624 int
01625 m32r_legitimate_pic_operand_p (rtx x)
01626 {
01627 if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)
01628 return 0;
01629
01630 if (GET_CODE (x) == CONST
01631 && GET_CODE (XEXP (x, 0)) == PLUS
01632 && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
01633 || GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF)
01634 && (GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT))
01635 return 0;
01636
01637 return 1;
01638 }
01639
01640 rtx
01641 m32r_legitimize_pic_address (rtx orig, rtx reg)
01642 {
01643 #ifdef DEBUG_PIC
01644 printf("m32r_legitimize_pic_address()\n");
01645 #endif
01646
01647 if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF)
01648 {
01649 rtx pic_ref, address;
01650 rtx insn;
01651 int subregs = 0;
01652
01653 if (reg == 0)
01654 {
01655 gcc_assert (!reload_in_progress && !reload_completed);
01656 reg = gen_reg_rtx (Pmode);
01657
01658 subregs = 1;
01659 }
01660
01661 if (subregs)
01662 address = gen_reg_rtx (Pmode);
01663 else
01664 address = reg;
01665
01666 current_function_uses_pic_offset_table = 1;
01667
01668 if (GET_CODE (orig) == LABEL_REF
01669 || (GET_CODE (orig) == SYMBOL_REF && SYMBOL_REF_LOCAL_P (orig)))
01670 {
01671 emit_insn (gen_gotoff_load_addr (reg, orig));
01672 emit_insn (gen_addsi3 (reg, reg, pic_offset_table_rtx));
01673 return reg;
01674 }
01675
01676 emit_insn (gen_pic_load_addr (address, orig));
01677
01678 emit_insn (gen_addsi3 (address, address, pic_offset_table_rtx));
01679 pic_ref = gen_const_mem (Pmode, address);
01680 insn = emit_move_insn (reg, pic_ref);
01681 #if 0
01682
01683
01684 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, orig,
01685 REG_NOTES (insn));
01686 #endif
01687 return reg;
01688 }
01689 else if (GET_CODE (orig) == CONST)
01690 {
01691 rtx base, offset;
01692
01693 if (GET_CODE (XEXP (orig, 0)) == PLUS
01694 && XEXP (XEXP (orig, 0), 1) == pic_offset_table_rtx)
01695 return orig;
01696
01697 if (reg == 0)
01698 {
01699 gcc_assert (!reload_in_progress && !reload_completed);
01700 reg = gen_reg_rtx (Pmode);
01701 }
01702
01703 if (GET_CODE (XEXP (orig, 0)) == PLUS)
01704 {
01705 base = m32r_legitimize_pic_address (XEXP (XEXP (orig, 0), 0), reg);
01706 if (base == reg)
01707 offset = m32r_legitimize_pic_address (XEXP (XEXP (orig, 0), 1), NULL_RTX);
01708 else
01709 offset = m32r_legitimize_pic_address (XEXP (XEXP (orig, 0), 1), reg);
01710 }
01711 else
01712 return orig;
01713
01714 if (GET_CODE (offset) == CONST_INT)
01715 {
01716 if (INT16_P (INTVAL (offset)))
01717 return plus_constant (base, INTVAL (offset));
01718 else
01719 {
01720 gcc_assert (! reload_in_progress && ! reload_completed);
01721 offset = force_reg (Pmode, offset);
01722 }
01723 }
01724
01725 return gen_rtx_PLUS (Pmode, base, offset);
01726 }
01727
01728 return orig;
01729 }
01730
01731
01732
01733
01734
01735
01736
01737 void
01738 m32r_initialize_trampoline (rtx tramp ATTRIBUTE_UNUSED,
01739 rtx fnaddr ATTRIBUTE_UNUSED,
01740 rtx cxt ATTRIBUTE_UNUSED)
01741 {
01742 }
01743
01744 static void
01745 m32r_file_start (void)
01746 {
01747 default_file_start ();
01748
01749 if (flag_verbose_asm)
01750 fprintf (asm_out_file,
01751 "%s M32R/D special options: -G " HOST_WIDE_INT_PRINT_UNSIGNED "\n",
01752 ASM_COMMENT_START, g_switch_value);
01753
01754 if (TARGET_LITTLE_ENDIAN)
01755 fprintf (asm_out_file, "\t.little\n");
01756 }
01757
01758
01759
01760
01761
01762 void
01763 m32r_print_operand (FILE * file, rtx x, int code)
01764 {
01765 rtx addr;
01766
01767 switch (code)
01768 {
01769
01770
01771 case 's':
01772 if (GET_CODE (x) == REG)
01773 fprintf (file, "@+%s", reg_names [REGNO (x)]);
01774 else
01775 output_operand_lossage ("invalid operand to %%s code");
01776 return;
01777
01778 case 'p':
01779 if (GET_CODE (x) == REG)
01780 fprintf (file, "@%s+", reg_names [REGNO (x)]);
01781 else
01782 output_operand_lossage ("invalid operand to %%p code");
01783 return;
01784
01785 case 'R' :
01786
01787
01788 if (GET_CODE (x) == REG)
01789 fputs (reg_names[REGNO (x)+1], file);
01790 else if (GET_CODE (x) == MEM)
01791 {
01792 fprintf (file, "@(");
01793
01794
01795
01796
01797 if (GET_CODE (XEXP (x, 0)) == PRE_INC
01798 || GET_CODE (XEXP (x, 0)) == PRE_DEC)
01799 output_address (plus_constant (XEXP (XEXP (x, 0), 0), 4));
01800 else
01801 output_address (plus_constant (XEXP (x, 0), 4));
01802 fputc (')', file);
01803 }
01804 else
01805 output_operand_lossage ("invalid operand to %%R code");
01806 return;
01807
01808 case 'H' :
01809 case 'L' :
01810 if (GET_CODE (x) == REG)
01811 {
01812
01813 if ((WORDS_BIG_ENDIAN != 0) ^ (code == 'L'))
01814 fputs (reg_names[REGNO (x)], file);
01815 else
01816 fputs (reg_names[REGNO (x)+1], file);
01817 }
01818 else if (GET_CODE (x) == CONST_INT
01819 || GET_CODE (x) == CONST_DOUBLE)
01820 {
01821 rtx first, second;
01822
01823 split_double (x, &first, &second);
01824 fprintf (file, HOST_WIDE_INT_PRINT_HEX,
01825 code == 'L' ? INTVAL (first) : INTVAL (second));
01826 }
01827 else
01828 output_operand_lossage ("invalid operand to %%H/%%L code");
01829 return;
01830
01831 case 'A' :
01832 {
01833 char str[30];
01834
01835 if (GET_CODE (x) != CONST_DOUBLE
01836 || GET_MODE_CLASS (GET_MODE (x)) != MODE_FLOAT)
01837 fatal_insn ("bad insn for 'A'", x);
01838
01839 real_to_decimal (str, CONST_DOUBLE_REAL_VALUE (x), sizeof (str), 0, 1);
01840 fprintf (file, "%s", str);
01841 return;
01842 }
01843
01844 case 'B' :
01845 case 'T' :
01846
01847
01848
01849
01850
01851
01852 switch (GET_CODE (x))
01853 {
01854 case CONST_INT :
01855 case CONST_DOUBLE :
01856 {
01857 rtx first, second;
01858
01859 split_double (x, &first, &second);
01860 x = WORDS_BIG_ENDIAN ? second : first;
01861 fprintf (file, HOST_WIDE_INT_PRINT_HEX,
01862 (code == 'B'
01863 ? INTVAL (x) & 0xffff
01864 : (INTVAL (x) >> 16) & 0xffff));
01865 }
01866 return;
01867 case CONST :
01868 case SYMBOL_REF :
01869 if (code == 'B'
01870 && small_data_operand (x, VOIDmode))
01871 {
01872 fputs ("sda(", file);
01873 output_addr_const (file, x);
01874 fputc (')', file);
01875 return;
01876 }
01877
01878 case LABEL_REF :
01879 fputs (code == 'T' ? "shigh(" : "low(", file);
01880 output_addr_const (file, x);
01881 fputc (')', file);
01882 return;
01883 default :
01884 output_operand_lossage ("invalid operand to %%T/%%B code");
01885 return;
01886 }
01887 break;
01888
01889 case 'U' :
01890
01891
01892 if (GET_CODE (x) == MEM)
01893 {
01894 if (GET_CODE (XEXP (x, 0)) == PRE_INC
01895 || GET_CODE (XEXP (x, 0)) == PRE_DEC)
01896 fputs (".a", file);
01897 }
01898 else
01899 output_operand_lossage ("invalid operand to %%U code");
01900 return;
01901
01902 case 'N' :
01903
01904 if (GET_CODE (x) == CONST_INT)
01905 output_addr_const (file, GEN_INT (- INTVAL (x)));
01906 else
01907 output_operand_lossage ("invalid operand to %%N code");
01908 return;
01909
01910 case 'X' :
01911
01912 if (GET_CODE (x) == CONST_INT)
01913 fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL (x));
01914 return;
01915
01916 case '#' :
01917 fputs (IMMEDIATE_PREFIX, file);
01918 return;
01919
01920 case 0 :
01921
01922 break;
01923
01924 default :
01925
01926 output_operand_lossage ("invalid operand output code");
01927 }
01928
01929 switch (GET_CODE (x))
01930 {
01931 case REG :
01932 fputs (reg_names[REGNO (x)], file);
01933 break;
01934
01935 case MEM :
01936 addr = XEXP (x, 0);
01937 if (GET_CODE (addr) == PRE_INC)
01938 {
01939 if (GET_CODE (XEXP (addr, 0)) != REG)
01940 fatal_insn ("pre-increment address is not a register", x);
01941
01942 fprintf (file, "@+%s", reg_names[REGNO (XEXP (addr, 0))]);
01943 }
01944 else if (GET_CODE (addr) == PRE_DEC)
01945 {
01946 if (GET_CODE (XEXP (addr, 0)) != REG)
01947 fatal_insn ("pre-decrement address is not a register", x);
01948
01949 fprintf (file, "@-%s", reg_names[REGNO (XEXP (addr, 0))]);
01950 }
01951 else if (GET_CODE (addr) == POST_INC)
01952 {
01953 if (GET_CODE (XEXP (addr, 0)) != REG)
01954 fatal_insn ("post-increment address is not a register", x);
01955
01956 fprintf (file, "@%s+", reg_names[REGNO (XEXP (addr, 0))]);
01957 }
01958 else
01959 {
01960 fputs ("@(", file);
01961 output_address (XEXP (x, 0));
01962 fputc (')', file);
01963 }
01964 break;
01965
01966 case CONST_DOUBLE :
01967
01968 if (GET_MODE (x) == SFmode)
01969 {
01970 REAL_VALUE_TYPE d;
01971 long l;
01972
01973 REAL_VALUE_FROM_CONST_DOUBLE (d, x);
01974 REAL_VALUE_TO_TARGET_SINGLE (d, l);
01975 fprintf (file, "0x%08lx", l);
01976 break;
01977 }
01978
01979
01980
01981 default :
01982 output_addr_const (file, x);
01983 break;
01984 }
01985 }
01986
01987
01988
01989 void
01990 m32r_print_operand_address (FILE * file, rtx addr)
01991 {
01992 rtx base;
01993 rtx index = 0;
01994 int offset = 0;
01995
01996 switch (GET_CODE (addr))
01997 {
01998 case REG :
01999 fputs (reg_names[REGNO (addr)], file);
02000 break;
02001
02002 case PLUS :
02003 if (GET_CODE (XEXP (addr, 0)) == CONST_INT)
02004 offset = INTVAL (XEXP (addr, 0)), base = XEXP (addr, 1);
02005 else if (GET_CODE (XEXP (addr, 1)) == CONST_INT)
02006 offset = INTVAL (XEXP (addr, 1)), base = XEXP (addr, 0);
02007 else
02008 base = XEXP (addr, 0), index = XEXP (addr, 1);
02009 if (GET_CODE (base) == REG)
02010 {
02011
02012 if (index == 0)
02013 {
02014 if (offset != 0)
02015 fprintf (file, "%d,", offset);
02016 fputs (reg_names[REGNO (base)], file);
02017 }
02018
02019 else if (GET_CODE (index) == REG)
02020 fprintf (file, "%s,%s",
02021 reg_names[REGNO (base)], reg_names[REGNO (index)]);
02022
02023 else if (GET_CODE (index) == SYMBOL_REF)
02024 {
02025 output_addr_const (file, index);
02026 fputc (',', file);
02027 fputs (reg_names[REGNO (base)], file);
02028 }
02029 else
02030 fatal_insn ("bad address", addr);
02031 }
02032 else if (GET_CODE (base) == LO_SUM)
02033 {
02034 gcc_assert (!index && GET_CODE (XEXP (base, 0)) == REG);
02035 if (small_data_operand (XEXP (base, 1), VOIDmode))
02036 fputs ("sda(", file);
02037 else
02038 fputs ("low(", file);
02039 output_addr_const (file, plus_constant (XEXP (base, 1), offset));
02040 fputs ("),", file);
02041 fputs (reg_names[REGNO (XEXP (base, 0))], file);
02042 }
02043 else
02044 fatal_insn ("bad address", addr);
02045 break;
02046
02047 case LO_SUM :
02048 if (GET_CODE (XEXP (addr, 0)) != REG)
02049 fatal_insn ("lo_sum not of register", addr);
02050 if (small_data_operand (XEXP (addr, 1), VOIDmode))
02051 fputs ("sda(", file);
02052 else
02053 fputs ("low(", file);
02054 output_addr_const (file, XEXP (addr, 1));
02055 fputs ("),", file);
02056 fputs (reg_names[REGNO (XEXP (addr, 0))], file);
02057 break;
02058
02059 case PRE_INC :
02060 fprintf (file, "+%s", reg_names[REGNO (XEXP (addr, 0))]);
02061 break;
02062
02063 case PRE_DEC :
02064 fprintf (file, "-%s", reg_names[REGNO (XEXP (addr, 0))]);
02065 break;
02066
02067 case POST_INC :
02068 fprintf (file, "%s+", reg_names[REGNO (XEXP (addr, 0))]);
02069 break;
02070
02071 default :
02072 output_addr_const (file, addr);
02073 break;
02074 }
02075 }
02076
02077
02078
02079 int
02080 zero_and_one (rtx operand1, rtx operand2)
02081 {
02082 return
02083 GET_CODE (operand1) == CONST_INT
02084 && GET_CODE (operand2) == CONST_INT
02085 && ( ((INTVAL (operand1) == 0) && (INTVAL (operand2) == 1))
02086 ||((INTVAL (operand1) == 1) && (INTVAL (operand2) == 0)));
02087 }
02088
02089
02090
02091
02092
02093
02094
02095 char *
02096 emit_cond_move (rtx * operands, rtx insn ATTRIBUTE_UNUSED)
02097 {
02098 static char buffer [100];
02099 const char * dest = reg_names [REGNO (operands [0])];
02100
02101 buffer [0] = 0;
02102
02103
02104 gcc_assert (GET_CODE (operands [0]) == REG);
02105 gcc_assert (conditional_move_operand (operands [2], SImode));
02106 gcc_assert (conditional_move_operand (operands [3], SImode));
02107
02108
02109 if (GET_CODE (operands [1]) == NE)
02110 {
02111 rtx tmp = operands [2];
02112 operands [2] = operands [3];
02113 operands [3] = tmp;
02114 }
02115
02116 sprintf (buffer, "mvfc %s, cbr", dest);
02117
02118
02119 if (INTVAL (operands [2]) == 0)
02120 sprintf (buffer + strlen (buffer), "\n\txor3 %s, %s, #1",
02121 dest, dest);
02122
02123 return buffer;
02124 }
02125
02126
02127
02128
02129 int
02130 m32r_not_same_reg (rtx a, rtx b)
02131 {
02132 int reg_a = -1;
02133 int reg_b = -2;
02134
02135 while (GET_CODE (a) == SUBREG)
02136 a = SUBREG_REG (a);
02137
02138 if (GET_CODE (a) == REG)
02139 reg_a = REGNO (a);
02140
02141 while (GET_CODE (b) == SUBREG)
02142 b = SUBREG_REG (b);
02143
02144 if (GET_CODE (b) == REG)
02145 reg_b = REGNO (b);
02146
02147 return reg_a != reg_b;
02148 }
02149
02150
02151 rtx
02152 m32r_function_symbol (const char *name)
02153 {
02154 int extra_flags = 0;
02155 enum m32r_model model;
02156 rtx sym = gen_rtx_SYMBOL_REF (Pmode, name);
02157
02158 if (TARGET_MODEL_SMALL)
02159 model = M32R_MODEL_SMALL;
02160 else if (TARGET_MODEL_MEDIUM)
02161 model = M32R_MODEL_MEDIUM;
02162 else if (TARGET_MODEL_LARGE)
02163 model = M32R_MODEL_LARGE;
02164 else
02165 gcc_unreachable ();
02166 extra_flags |= model << SYMBOL_FLAG_MODEL_SHIFT;
02167
02168 if (extra_flags)
02169 SYMBOL_REF_FLAGS (sym) |= extra_flags;
02170
02171 return sym;
02172 }
02173
02174
02175
02176 static void
02177 block_move_call (rtx dest_reg, rtx src_reg, rtx bytes_rtx)
02178 {
02179
02180
02181 if (GET_MODE (bytes_rtx) != VOIDmode
02182 && GET_MODE (bytes_rtx) != Pmode)
02183 bytes_rtx = convert_to_mode (Pmode, bytes_rtx, 1);
02184
02185 emit_library_call (m32r_function_symbol ("memcpy"), 0,
02186 VOIDmode, 3, dest_reg, Pmode, src_reg, Pmode,
02187 convert_to_mode (TYPE_MODE (sizetype), bytes_rtx,
02188 TYPE_UNSIGNED (sizetype)),
02189 TYPE_MODE (sizetype));
02190 }
02191
02192
02193
02194
02195
02196
02197
02198
02199
02200
02201 int
02202 m32r_expand_block_move (rtx operands[])
02203 {
02204 rtx orig_dst = operands[0];
02205 rtx orig_src = operands[1];
02206 rtx bytes_rtx = operands[2];
02207 rtx align_rtx = operands[3];
02208 int constp = GET_CODE (bytes_rtx) == CONST_INT;
02209 HOST_WIDE_INT bytes = constp ? INTVAL (bytes_rtx) : 0;
02210 int align = INTVAL (align_rtx);
02211 int leftover;
02212 rtx src_reg;
02213 rtx dst_reg;
02214
02215 if (constp && bytes <= 0)
02216 return 1;
02217
02218
02219 dst_reg = copy_addr_to_reg (XEXP (orig_dst, 0));
02220 src_reg = copy_addr_to_reg (XEXP (orig_src, 0));
02221
02222 if (align > UNITS_PER_WORD)
02223 align = UNITS_PER_WORD;
02224
02225
02226
02227
02228 if (optimize_size || ! constp || align != UNITS_PER_WORD)
02229 {
02230 block_move_call (dst_reg, src_reg, bytes_rtx);
02231 return 0;
02232 }
02233
02234 leftover = bytes % MAX_MOVE_BYTES;
02235 bytes -= leftover;
02236
02237
02238 if (bytes)
02239 {
02240 rtx label = NULL_RTX;
02241 rtx final_src = NULL_RTX;
02242 rtx at_a_time = GEN_INT (MAX_MOVE_BYTES);
02243 rtx rounded_total = GEN_INT (bytes);
02244 rtx new_dst_reg = gen_reg_rtx (SImode);
02245 rtx new_src_reg = gen_reg_rtx (SImode);
02246
02247
02248
02249
02250
02251 if (bytes > MAX_MOVE_BYTES)
02252 {
02253 final_src = gen_reg_rtx (Pmode);
02254
02255 if (INT16_P(bytes))
02256 emit_insn (gen_addsi3 (final_src, src_reg, rounded_total));
02257 else
02258 {
02259 emit_insn (gen_movsi (final_src, rounded_total));
02260 emit_insn (gen_addsi3 (final_src, final_src, src_reg));
02261 }
02262
02263 label = gen_label_rtx ();
02264 emit_label (label);
02265 }
02266
02267
02268
02269
02270
02271 emit_insn (gen_movmemsi_internal (dst_reg, src_reg, at_a_time,
02272 new_dst_reg, new_src_reg));
02273 emit_move_insn (dst_reg, new_dst_reg);
02274 emit_move_insn (src_reg, new_src_reg);
02275 emit_insn (gen_addsi3 (dst_reg, dst_reg, GEN_INT (4)));
02276
02277 if (bytes > MAX_MOVE_BYTES)
02278 {
02279 emit_insn (gen_cmpsi (src_reg, final_src));
02280 emit_jump_insn (gen_bne (label));
02281 }
02282 }
02283
02284 if (leftover)
02285 emit_insn (gen_movmemsi_internal (dst_reg, src_reg, GEN_INT (leftover),
02286 gen_reg_rtx (SImode),
02287 gen_reg_rtx (SImode)));
02288 return 1;
02289 }
02290
02291
02292
02293
02294
02295
02296
02297
02298
02299
02300 void
02301 m32r_output_block_move (rtx insn ATTRIBUTE_UNUSED, rtx operands[])
02302 {
02303 HOST_WIDE_INT bytes = INTVAL (operands[2]);
02304 int first_time;
02305 int got_extra = 0;
02306
02307 gcc_assert (bytes >= 1 && bytes <= MAX_MOVE_BYTES);
02308
02309
02310
02311
02312
02313
02314
02315 first_time = 1;
02316
02317 while (bytes > 0)
02318 {
02319 if (bytes >= 8)
02320 {
02321 if (first_time)
02322 {
02323 output_asm_insn ("ld\t%5, %p1", operands);
02324 output_asm_insn ("ld\t%6, %p1", operands);
02325 output_asm_insn ("st\t%5, @%0", operands);
02326 output_asm_insn ("st\t%6, %s0", operands);
02327 }
02328 else
02329 {
02330 output_asm_insn ("ld\t%5, %p1", operands);
02331 output_asm_insn ("ld\t%6, %p1", operands);
02332 output_asm_insn ("st\t%5, %s0", operands);
02333 output_asm_insn ("st\t%6, %s0", operands);
02334 }
02335
02336 bytes -= 8;
02337 }
02338 else if (bytes >= 4)
02339 {
02340 if (bytes > 4)
02341 got_extra = 1;
02342
02343 output_asm_insn ("ld\t%5, %p1", operands);
02344
02345 if (got_extra)
02346 output_asm_insn ("ld\t%6, %p1", operands);
02347
02348 if (first_time)
02349 output_asm_insn ("st\t%5, @%0", operands);
02350 else
02351 output_asm_insn ("st\t%5, %s0", operands);
02352
02353 bytes -= 4;
02354 }
02355 else
02356 {
02357
02358
02359
02360
02361
02362 int dst_offset = first_time ? 0 : 4;
02363
02364
02365 int dst_inc_amount = dst_offset + bytes - 4;
02366
02367 int src_inc_amount = bytes;
02368 int last_shift;
02369 rtx my_operands[3];
02370
02371
02372
02373 if (! got_extra)
02374 output_asm_insn ("ld\t%6, @%1", operands);
02375
02376 if (bytes >= 2)
02377 {
02378 bytes -= 2;
02379
02380 output_asm_insn ("sra3\t%5, %6, #16", operands);
02381 my_operands[0] = operands[5];
02382 my_operands[1] = GEN_INT (dst_offset);
02383 my_operands[2] = operands[0];
02384 output_asm_insn ("sth\t%0, @(%1,%2)", my_operands);
02385
02386
02387
02388
02389
02390
02391 if (bytes > 0)
02392 {
02393 dst_offset += 2;
02394 last_shift = 8;
02395 }
02396 }
02397 else
02398 last_shift = 24;
02399
02400 if (bytes > 0)
02401 {
02402 my_operands[0] = operands[6];
02403 my_operands[1] = GEN_INT (last_shift);
02404 output_asm_insn ("srai\t%0, #%1", my_operands);
02405 my_operands[0] = operands[6];
02406 my_operands[1] = GEN_INT (dst_offset);
02407 my_operands[2] = operands[0];
02408 output_asm_insn ("stb\t%0, @(%1,%2)", my_operands);
02409 }
02410
02411
02412
02413
02414 if (dst_inc_amount
02415 && !find_reg_note (insn, REG_UNUSED, operands[0]))
02416 {
02417 my_operands[0] = operands[0];
02418 my_operands[1] = GEN_INT (dst_inc_amount);
02419 output_asm_insn ("addi\t%0, #%1", my_operands);
02420 }
02421
02422
02423
02424
02425 if (src_inc_amount
02426 && !find_reg_note (insn, REG_UNUSED, operands[1]))
02427 {
02428 my_operands[0] = operands[1];
02429 my_operands[1] = GEN_INT (src_inc_amount);
02430 output_asm_insn ("addi\t%0, #%1", my_operands);
02431 }
02432
02433 bytes = 0;
02434 }
02435
02436 first_time = 0;
02437 }
02438 }
02439
02440
02441
02442 int
02443 m32r_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED,
02444 unsigned int new_reg)
02445 {
02446
02447 if (lookup_attribute ("interrupt", DECL_ATTRIBUTES (current_function_decl))
02448 && !regs_ever_live[new_reg])
02449 return 0;
02450
02451
02452
02453 if (current_function_is_leaf && new_reg == RETURN_ADDR_REGNUM)
02454 return 0;
02455
02456 return 1;
02457 }
02458
02459 rtx
02460 m32r_return_addr (int count)
02461 {
02462 if (count != 0)
02463 return const0_rtx;
02464
02465 return get_hard_reg_initial_val (Pmode, RETURN_ADDR_REGNUM);
02466 }