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