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