00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "config.h"
00024 #include "system.h"
00025 #include "coretypes.h"
00026 #include "tm.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 "insn-flags.h"
00034 #include "output.h"
00035 #include "insn-attr.h"
00036 #include "flags.h"
00037 #include "recog.h"
00038 #include "reload.h"
00039 #include "toplev.h"
00040 #include "obstack.h"
00041 #include "tree.h"
00042 #include "expr.h"
00043 #include "optabs.h"
00044 #include "except.h"
00045 #include "function.h"
00046 #include "ggc.h"
00047 #include "target.h"
00048 #include "target-def.h"
00049 #include "tm_p.h"
00050 #include "langhooks.h"
00051 #include "tree-gimple.h"
00052
00053
00054
00055
00056 typedef enum
00057 {
00058 PP_pushm,
00059 PP_popm,
00060 PP_justcount
00061 } Push_Pop_Type;
00062
00063 static tree interrupt_handler (tree *, tree, tree, int, bool *);
00064 static int interrupt_p (tree node);
00065 static bool m32c_asm_integer (rtx, unsigned int, int);
00066 static int m32c_comp_type_attributes (tree, tree);
00067 static bool m32c_fixed_condition_code_regs (unsigned int *, unsigned int *);
00068 static struct machine_function *m32c_init_machine_status (void);
00069 static void m32c_insert_attributes (tree, tree *);
00070 static bool m32c_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
00071 tree, bool);
00072 static bool m32c_promote_prototypes (tree);
00073 static int m32c_pushm_popm (Push_Pop_Type);
00074 static bool m32c_strict_argument_naming (CUMULATIVE_ARGS *);
00075 static rtx m32c_struct_value_rtx (tree, int);
00076 static rtx m32c_subreg (enum machine_mode, rtx, enum machine_mode, int);
00077 static int need_to_save (int);
00078
00079 #define streq(a,b) (strcmp ((a), (b)) == 0)
00080
00081
00082
00083
00084
00085
00086 #define DEBUG0 0
00087 #define DEBUG1 1
00088
00089 #if DEBUG0
00090
00091
00092 static char const *class_names[LIM_REG_CLASSES] = REG_CLASS_NAMES;
00093 #endif
00094 static int class_contents[LIM_REG_CLASSES][1] = REG_CLASS_CONTENTS;
00095
00096
00097 static char pattern[30], *patternp;
00098 static GTY(()) rtx patternr[30];
00099 #define RTX_IS(x) (streq (pattern, x))
00100
00101
00102 #define IS_MEM_REGNO(regno) ((regno) >= MEM0_REGNO && (regno) <= MEM7_REGNO)
00103 #define IS_MEM_REG(rtx) (GET_CODE (rtx) == REG && IS_MEM_REGNO (REGNO (rtx)))
00104
00105 #define IS_CR_REGNO(regno) ((regno) >= SB_REGNO && (regno) <= PC_REGNO)
00106 #define IS_CR_REG(rtx) (GET_CODE (rtx) == REG && IS_CR_REGNO (REGNO (rtx)))
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121 static void
00122 encode_pattern_1 (rtx x)
00123 {
00124 int i;
00125
00126 if (patternp == pattern + sizeof (pattern) - 2)
00127 {
00128 patternp[-1] = '?';
00129 return;
00130 }
00131
00132 patternr[patternp - pattern] = x;
00133
00134 switch (GET_CODE (x))
00135 {
00136 case REG:
00137 *patternp++ = 'r';
00138 break;
00139 case SUBREG:
00140 if (GET_MODE_SIZE (GET_MODE (x)) !=
00141 GET_MODE_SIZE (GET_MODE (XEXP (x, 0))))
00142 *patternp++ = 'S';
00143 encode_pattern_1 (XEXP (x, 0));
00144 break;
00145 case MEM:
00146 *patternp++ = 'm';
00147 case CONST:
00148 encode_pattern_1 (XEXP (x, 0));
00149 break;
00150 case PLUS:
00151 *patternp++ = '+';
00152 encode_pattern_1 (XEXP (x, 0));
00153 encode_pattern_1 (XEXP (x, 1));
00154 break;
00155 case PRE_DEC:
00156 *patternp++ = '>';
00157 encode_pattern_1 (XEXP (x, 0));
00158 break;
00159 case POST_INC:
00160 *patternp++ = '<';
00161 encode_pattern_1 (XEXP (x, 0));
00162 break;
00163 case LO_SUM:
00164 *patternp++ = 'L';
00165 encode_pattern_1 (XEXP (x, 0));
00166 encode_pattern_1 (XEXP (x, 1));
00167 break;
00168 case HIGH:
00169 *patternp++ = 'H';
00170 encode_pattern_1 (XEXP (x, 0));
00171 break;
00172 case SYMBOL_REF:
00173 *patternp++ = 's';
00174 break;
00175 case LABEL_REF:
00176 *patternp++ = 'l';
00177 break;
00178 case CODE_LABEL:
00179 *patternp++ = 'c';
00180 break;
00181 case CONST_INT:
00182 case CONST_DOUBLE:
00183 *patternp++ = 'i';
00184 break;
00185 case UNSPEC:
00186 *patternp++ = 'u';
00187 *patternp++ = '0' + XCINT (x, 1, UNSPEC);
00188 for (i = 0; i < XVECLEN (x, 0); i++)
00189 encode_pattern_1 (XVECEXP (x, 0, i));
00190 break;
00191 case USE:
00192 *patternp++ = 'U';
00193 break;
00194 case PARALLEL:
00195 *patternp++ = '|';
00196 for (i = 0; i < XVECLEN (x, 0); i++)
00197 encode_pattern_1 (XVECEXP (x, 0, i));
00198 break;
00199 case EXPR_LIST:
00200 *patternp++ = 'E';
00201 encode_pattern_1 (XEXP (x, 0));
00202 if (XEXP (x, 1))
00203 encode_pattern_1 (XEXP (x, 1));
00204 break;
00205 default:
00206 *patternp++ = '?';
00207 #if DEBUG0
00208 fprintf (stderr, "can't encode pattern %s\n",
00209 GET_RTX_NAME (GET_CODE (x)));
00210 debug_rtx (x);
00211 gcc_unreachable ();
00212 #endif
00213 break;
00214 }
00215 }
00216
00217 static void
00218 encode_pattern (rtx x)
00219 {
00220 patternp = pattern;
00221 encode_pattern_1 (x);
00222 *patternp = 0;
00223 }
00224
00225
00226
00227
00228
00229 static const char *
00230 reg_name_with_mode (int regno, enum machine_mode mode)
00231 {
00232 int mlen = GET_MODE_SIZE (mode);
00233 if (regno == R0_REGNO && mlen == 1)
00234 return "r0l";
00235 if (regno == R0_REGNO && (mlen == 3 || mlen == 4))
00236 return "r2r0";
00237 if (regno == R0_REGNO && mlen == 6)
00238 return "r2r1r0";
00239 if (regno == R0_REGNO && mlen == 8)
00240 return "r3r1r2r0";
00241 if (regno == R1_REGNO && mlen == 1)
00242 return "r1l";
00243 if (regno == R1_REGNO && (mlen == 3 || mlen == 4))
00244 return "r3r1";
00245 if (regno == A0_REGNO && TARGET_A16 && (mlen == 3 || mlen == 4))
00246 return "a1a0";
00247 return reg_names[regno];
00248 }
00249
00250
00251
00252
00253
00254
00255
00256 static int
00257 reg_push_size (int regno)
00258 {
00259 switch (regno)
00260 {
00261 case R0_REGNO:
00262 case R1_REGNO:
00263 return 2;
00264 case R2_REGNO:
00265 case R3_REGNO:
00266 case FLG_REGNO:
00267 return 2;
00268 case A0_REGNO:
00269 case A1_REGNO:
00270 case SB_REGNO:
00271 case FB_REGNO:
00272 case SP_REGNO:
00273 if (TARGET_A16)
00274 return 2;
00275 else
00276 return 3;
00277 default:
00278 gcc_unreachable ();
00279 }
00280 }
00281
00282 static int *class_sizes = 0;
00283
00284
00285
00286
00287 static int
00288 reduce_class (int original_class, int limiting_class, int returned_if_empty)
00289 {
00290 int cc = class_contents[original_class][0];
00291 int i, best = NO_REGS;
00292 int best_size = 0;
00293
00294 if (original_class == limiting_class)
00295 return original_class;
00296
00297 if (!class_sizes)
00298 {
00299 int r;
00300 class_sizes = (int *) xmalloc (LIM_REG_CLASSES * sizeof (int));
00301 for (i = 0; i < LIM_REG_CLASSES; i++)
00302 {
00303 class_sizes[i] = 0;
00304 for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
00305 if (class_contents[i][0] & (1 << r))
00306 class_sizes[i]++;
00307 }
00308 }
00309
00310 cc &= class_contents[limiting_class][0];
00311 for (i = 0; i < LIM_REG_CLASSES; i++)
00312 {
00313 int ic = class_contents[i][0];
00314
00315 if ((~cc & ic) == 0)
00316 if (best_size < class_sizes[i])
00317 {
00318 best = i;
00319 best_size = class_sizes[i];
00320 }
00321
00322 }
00323 if (best == NO_REGS)
00324 return returned_if_empty;
00325 return best;
00326 }
00327
00328
00329
00330 static int
00331 classes_intersect (int class1, int class2)
00332 {
00333 return class_contents[class1][0] & class_contents[class2][0];
00334 }
00335
00336
00337
00338 static int
00339 class_can_hold_mode (int class, enum machine_mode mode)
00340 {
00341
00342 static char results[LIM_REG_CLASSES][MAX_MACHINE_MODE];
00343 if (results[class][mode] == 0)
00344 {
00345 int r, n, i;
00346 results[class][mode] = 1;
00347 for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
00348 if (class_contents[class][0] & (1 << r)
00349 && HARD_REGNO_MODE_OK (r, mode))
00350 {
00351 int ok = 1;
00352 n = HARD_REGNO_NREGS (r, mode);
00353 for (i = 1; i < n; i++)
00354 if (!(class_contents[class][0] & (1 << (r + i))))
00355 ok = 0;
00356 if (ok)
00357 {
00358 results[class][mode] = 2;
00359 break;
00360 }
00361 }
00362 }
00363 #if DEBUG0
00364 fprintf (stderr, "class %s can hold %s? %s\n",
00365 class_names[class], mode_name[mode],
00366 (results[class][mode] == 2) ? "yes" : "no");
00367 #endif
00368 return results[class][mode] == 2;
00369 }
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385 int target_memregs = 16;
00386 static bool target_memregs_set = FALSE;
00387 int ok_to_change_target_memregs = TRUE;
00388
00389 #undef TARGET_HANDLE_OPTION
00390 #define TARGET_HANDLE_OPTION m32c_handle_option
00391 static bool
00392 m32c_handle_option (size_t code,
00393 const char *arg ATTRIBUTE_UNUSED,
00394 int value ATTRIBUTE_UNUSED)
00395 {
00396 if (code == OPT_memregs_)
00397 {
00398 target_memregs_set = TRUE;
00399 target_memregs = atoi (arg);
00400 }
00401 return TRUE;
00402 }
00403
00404
00405
00406 void
00407 m32c_override_options (void)
00408 {
00409 if (target_memregs_set)
00410 {
00411 if (target_memregs < 0 || target_memregs > 16)
00412 error ("invalid target memregs value '%d'", target_memregs);
00413 }
00414 else
00415 target_memregs = 16;
00416 }
00417
00418
00419
00420
00421 static struct machine_function *
00422 m32c_init_machine_status (void)
00423 {
00424 struct machine_function *machine;
00425 machine =
00426 (machine_function *) ggc_alloc_cleared (sizeof (machine_function));
00427
00428 return machine;
00429 }
00430
00431
00432
00433 void
00434 m32c_init_expanders (void)
00435 {
00436 init_machine_status = m32c_init_machine_status;
00437 }
00438
00439
00440
00441 #undef TARGET_PROMOTE_FUNCTION_RETURN
00442 #define TARGET_PROMOTE_FUNCTION_RETURN m32c_promote_function_return
00443 bool
00444 m32c_promote_function_return (tree fntype ATTRIBUTE_UNUSED)
00445 {
00446 return false;
00447 }
00448
00449
00450
00451
00452
00453
00454
00455 static struct
00456 {
00457 char qi_regs;
00458 char hi_regs;
00459 char pi_regs;
00460 char si_regs;
00461 char di_regs;
00462 } nregs_table[FIRST_PSEUDO_REGISTER] =
00463 {
00464 { 1, 1, 2, 2, 4 },
00465 { 0, 1, 0, 0, 0 },
00466 { 1, 1, 2, 2, 0 },
00467 { 0, 1, 0, 0, 0 },
00468 { 0, 1, 1, 0, 0 },
00469 { 0, 1, 1, 0, 0 },
00470 { 0, 1, 1, 0, 0 },
00471 { 0, 1, 1, 0, 0 },
00472 { 0, 1, 1, 0, 0 },
00473 { 1, 1, 1, 0, 0 },
00474 { 0, 0, 0, 0, 0 },
00475 { 1, 1, 1, 0, 0 },
00476 { 1, 1, 2, 2, 4 },
00477 { 1, 1, 2, 2, 4 },
00478 { 1, 1, 2, 2, 4 },
00479 { 1, 1, 2, 2, 4 },
00480 { 1, 1, 2, 2, 4 },
00481 { 1, 1, 2, 2, 0 },
00482 { 1, 1, 2, 2, 0 },
00483 { 1, 1, 0, 0, 0 },
00484 };
00485
00486
00487
00488
00489
00490 void
00491 m32c_conditional_register_usage (void)
00492 {
00493 int i;
00494
00495 if (0 <= target_memregs && target_memregs <= 16)
00496 {
00497
00498
00499 for (i = target_memregs/2; i < 8; i++)
00500 {
00501 fixed_regs[MEM0_REGNO + i] = 1;
00502 CLEAR_HARD_REG_BIT (reg_class_contents[MEM_REGS], MEM0_REGNO + i);
00503 }
00504 }
00505
00506
00507 if (TARGET_A24)
00508 {
00509 call_used_regs[R1_REGNO] = 0;
00510 call_used_regs[R2_REGNO] = 0;
00511 call_used_regs[R3_REGNO] = 0;
00512 call_used_regs[A0_REGNO] = 0;
00513 call_used_regs[A1_REGNO] = 0;
00514 }
00515 }
00516
00517
00518
00519
00520
00521
00522 int
00523 m32c_hard_regno_nregs (int regno, enum machine_mode mode)
00524 {
00525 if (regno == FLG_REGNO && mode == CCmode)
00526 return 1;
00527 if (regno >= FIRST_PSEUDO_REGISTER)
00528 return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
00529
00530 if (regno >= MEM0_REGNO && regno <= MEM7_REGNO)
00531 return (GET_MODE_SIZE (mode) + 1) / 2;
00532
00533 if (GET_MODE_SIZE (mode) <= 1)
00534 return nregs_table[regno].qi_regs;
00535 if (GET_MODE_SIZE (mode) <= 2)
00536 return nregs_table[regno].hi_regs;
00537 if (regno == A0_REGNO && mode == PSImode && TARGET_A16)
00538 return 2;
00539 if ((GET_MODE_SIZE (mode) <= 3 || mode == PSImode) && TARGET_A24)
00540 return nregs_table[regno].pi_regs;
00541 if (GET_MODE_SIZE (mode) <= 4)
00542 return nregs_table[regno].si_regs;
00543 if (GET_MODE_SIZE (mode) <= 8)
00544 return nregs_table[regno].di_regs;
00545 return 0;
00546 }
00547
00548
00549
00550 int
00551 m32c_hard_regno_ok (int regno, enum machine_mode mode)
00552 {
00553 return m32c_hard_regno_nregs (regno, mode) != 0;
00554 }
00555
00556
00557
00558
00559
00560 int
00561 m32c_modes_tieable_p (enum machine_mode m1, enum machine_mode m2)
00562 {
00563 if (GET_MODE_SIZE (m1) == GET_MODE_SIZE (m2))
00564 return 1;
00565
00566 #if 0
00567 if (m1 == QImode || m2 == QImode)
00568 return 0;
00569 #endif
00570
00571 return 1;
00572 }
00573
00574
00575
00576
00577 enum machine_mode
00578 m32c_regno_reg_class (int regno)
00579 {
00580 switch (regno)
00581 {
00582 case R0_REGNO:
00583 return R0_REGS;
00584 case R1_REGNO:
00585 return R1_REGS;
00586 case R2_REGNO:
00587 return R2_REGS;
00588 case R3_REGNO:
00589 return R3_REGS;
00590 case A0_REGNO:
00591 case A1_REGNO:
00592 return A_REGS;
00593 case SB_REGNO:
00594 return SB_REGS;
00595 case FB_REGNO:
00596 return FB_REGS;
00597 case SP_REGNO:
00598 return SP_REGS;
00599 case FLG_REGNO:
00600 return FLG_REGS;
00601 default:
00602 if (IS_MEM_REGNO (regno))
00603 return MEM_REGS;
00604 return ALL_REGS;
00605 }
00606 }
00607
00608
00609
00610 int
00611 m32c_reg_class_from_constraint (char c ATTRIBUTE_UNUSED, const char *s)
00612 {
00613 if (memcmp (s, "Rsp", 3) == 0)
00614 return SP_REGS;
00615 if (memcmp (s, "Rfb", 3) == 0)
00616 return FB_REGS;
00617 if (memcmp (s, "Rsb", 3) == 0)
00618 return SB_REGS;
00619 if (memcmp (s, "Rcr", 3) == 0)
00620 return TARGET_A16 ? CR_REGS : NO_REGS;
00621 if (memcmp (s, "Rcl", 3) == 0)
00622 return TARGET_A24 ? CR_REGS : NO_REGS;
00623 if (memcmp (s, "R0w", 3) == 0)
00624 return R0_REGS;
00625 if (memcmp (s, "R1w", 3) == 0)
00626 return R1_REGS;
00627 if (memcmp (s, "R2w", 3) == 0)
00628 return R2_REGS;
00629 if (memcmp (s, "R3w", 3) == 0)
00630 return R3_REGS;
00631 if (memcmp (s, "R02", 3) == 0)
00632 return R02_REGS;
00633 if (memcmp (s, "R03", 3) == 0)
00634 return R03_REGS;
00635 if (memcmp (s, "Rdi", 3) == 0)
00636 return DI_REGS;
00637 if (memcmp (s, "Rhl", 3) == 0)
00638 return HL_REGS;
00639 if (memcmp (s, "R23", 3) == 0)
00640 return R23_REGS;
00641 if (memcmp (s, "Ra0", 3) == 0)
00642 return A0_REGS;
00643 if (memcmp (s, "Ra1", 3) == 0)
00644 return A1_REGS;
00645 if (memcmp (s, "Raa", 3) == 0)
00646 return A_REGS;
00647 if (memcmp (s, "Raw", 3) == 0)
00648 return TARGET_A16 ? A_REGS : NO_REGS;
00649 if (memcmp (s, "Ral", 3) == 0)
00650 return TARGET_A24 ? A_REGS : NO_REGS;
00651 if (memcmp (s, "Rqi", 3) == 0)
00652 return QI_REGS;
00653 if (memcmp (s, "Rad", 3) == 0)
00654 return AD_REGS;
00655 if (memcmp (s, "Rsi", 3) == 0)
00656 return SI_REGS;
00657 if (memcmp (s, "Rhi", 3) == 0)
00658 return HI_REGS;
00659 if (memcmp (s, "Rhc", 3) == 0)
00660 return HC_REGS;
00661 if (memcmp (s, "Rra", 3) == 0)
00662 return RA_REGS;
00663 if (memcmp (s, "Rfl", 3) == 0)
00664 return FLG_REGS;
00665 if (memcmp (s, "Rmm", 3) == 0)
00666 {
00667 if (fixed_regs[MEM0_REGNO])
00668 return NO_REGS;
00669 return MEM_REGS;
00670 }
00671
00672
00673 if (memcmp (s, "Rpi", 3) == 0)
00674 {
00675 if (TARGET_A16)
00676 return HI_REGS;
00677 else
00678 return RA_REGS;
00679 }
00680
00681
00682 if (memcmp (s, "Rpa", 3) == 0)
00683 return NO_REGS;
00684
00685 if (*s == 'R')
00686 {
00687 fprintf(stderr, "unrecognized R constraint: %.3s\n", s);
00688 gcc_unreachable();
00689 }
00690
00691 return NO_REGS;
00692 }
00693
00694
00695 int
00696 m32c_regno_ok_for_base_p (int regno)
00697 {
00698 if (regno == A0_REGNO
00699 || regno == A1_REGNO || regno >= FIRST_PSEUDO_REGISTER)
00700 return 1;
00701 return 0;
00702 }
00703
00704 #define DEBUG_RELOAD 0
00705
00706
00707
00708 int
00709 m32c_preferred_reload_class (rtx x, int rclass)
00710 {
00711 int newclass = rclass;
00712
00713 #if DEBUG_RELOAD
00714 fprintf (stderr, "\npreferred_reload_class for %s is ",
00715 class_names[rclass]);
00716 #endif
00717 if (rclass == NO_REGS)
00718 rclass = GET_MODE (x) == QImode ? HL_REGS : R03_REGS;
00719
00720 if (classes_intersect (rclass, CR_REGS))
00721 {
00722 switch (GET_MODE (x))
00723 {
00724 case QImode:
00725 newclass = HL_REGS;
00726 break;
00727 default:
00728
00729 break;
00730 }
00731 }
00732
00733 else if (newclass == QI_REGS && GET_MODE_SIZE (GET_MODE (x)) > 2)
00734 newclass = SI_REGS;
00735 else if (GET_MODE_SIZE (GET_MODE (x)) > 4
00736 && ~class_contents[rclass][0] & 0x000f)
00737 newclass = DI_REGS;
00738
00739 rclass = reduce_class (rclass, newclass, rclass);
00740
00741 if (GET_MODE (x) == QImode)
00742 rclass = reduce_class (rclass, HL_REGS, rclass);
00743
00744 #if DEBUG_RELOAD
00745 fprintf (stderr, "%s\n", class_names[rclass]);
00746 debug_rtx (x);
00747
00748 if (GET_CODE (x) == MEM
00749 && GET_CODE (XEXP (x, 0)) == PLUS
00750 && GET_CODE (XEXP (XEXP (x, 0), 0)) == PLUS)
00751 fprintf (stderr, "Glorm!\n");
00752 #endif
00753 return rclass;
00754 }
00755
00756
00757 int
00758 m32c_preferred_output_reload_class (rtx x, int rclass)
00759 {
00760 return m32c_preferred_reload_class (x, rclass);
00761 }
00762
00763
00764
00765
00766 int
00767 m32c_limit_reload_class (enum machine_mode mode, int rclass)
00768 {
00769 #if DEBUG_RELOAD
00770 fprintf (stderr, "limit_reload_class for %s: %s ->",
00771 mode_name[mode], class_names[rclass]);
00772 #endif
00773
00774 if (mode == QImode)
00775 rclass = reduce_class (rclass, HL_REGS, rclass);
00776 else if (mode == HImode)
00777 rclass = reduce_class (rclass, HI_REGS, rclass);
00778 else if (mode == SImode)
00779 rclass = reduce_class (rclass, SI_REGS, rclass);
00780
00781 if (rclass != A_REGS)
00782 rclass = reduce_class (rclass, DI_REGS, rclass);
00783
00784 #if DEBUG_RELOAD
00785 fprintf (stderr, " %s\n", class_names[rclass]);
00786 #endif
00787 return rclass;
00788 }
00789
00790
00791
00792
00793
00794 int
00795 m32c_secondary_reload_class (int rclass, enum machine_mode mode, rtx x)
00796 {
00797 int cc = class_contents[rclass][0];
00798 #if DEBUG0
00799 fprintf (stderr, "\nsecondary reload class %s %s\n",
00800 class_names[rclass], mode_name[mode]);
00801 debug_rtx (x);
00802 #endif
00803 if (mode == QImode
00804 && GET_CODE (x) == MEM && (cc & ~class_contents[R23_REGS][0]) == 0)
00805 return QI_REGS;
00806 if (classes_intersect (rclass, CR_REGS)
00807 && GET_CODE (x) == REG
00808 && REGNO (x) >= SB_REGNO && REGNO (x) <= SP_REGNO)
00809 return TARGET_A16 ? HI_REGS : A_REGS;
00810 return NO_REGS;
00811 }
00812
00813
00814
00815 int
00816 m32c_class_likely_spilled_p (int regclass)
00817 {
00818 if (regclass == A_REGS)
00819 return 1;
00820 return reg_class_size[regclass] == 1;
00821 }
00822
00823
00824
00825
00826 int
00827 m32c_class_max_nregs (int regclass, enum machine_mode mode)
00828 {
00829 int rn, max = 0;
00830
00831 for (rn = 0; rn < FIRST_PSEUDO_REGISTER; rn++)
00832 if (class_contents[regclass][0] & (1 << rn))
00833 {
00834 int n = m32c_hard_regno_nregs (rn, mode);
00835 if (max < n)
00836 max = n;
00837 }
00838 return max;
00839 }
00840
00841
00842
00843
00844
00845 int
00846 m32c_cannot_change_mode_class (enum machine_mode from,
00847 enum machine_mode to, int rclass)
00848 {
00849 #if DEBUG0
00850 fprintf (stderr, "cannot change from %s to %s in %s\n",
00851 mode_name[from], mode_name[to], class_names[rclass]);
00852 #endif
00853
00854 if (to == QImode)
00855 return (class_contents[rclass][0] & 0x1ffa);
00856
00857 if (class_contents[rclass][0] & 0x0005
00858 && GET_MODE_SIZE (from) > 1)
00859 return 0;
00860 if (GET_MODE_SIZE (from) > 2)
00861 return 0;
00862
00863 return 1;
00864 }
00865
00866
00867
00868 #define IS_REG(rtx,regno) (GET_CODE (rtx) == REG \
00869 && REGNO (rtx) == regno)
00870
00871
00872
00873 #define IS_PSEUDO(rtx,strict) (!strict && GET_CODE (rtx) == REG \
00874 && (REGNO (rtx) == AP_REGNO \
00875 || REGNO (rtx) >= FIRST_PSEUDO_REGISTER))
00876
00877
00878
00879
00880 int
00881 m32c_const_ok_for_constraint_p (HOST_WIDE_INT value,
00882 char c ATTRIBUTE_UNUSED, const char *str)
00883 {
00884
00885
00886
00887 if (memcmp (str, "Is3", 3) == 0)
00888 {
00889 return (-8 <= value && value <= 7);
00890 }
00891 if (memcmp (str, "IS1", 3) == 0)
00892 {
00893 return (-128 <= value && value <= 127);
00894 }
00895 if (memcmp (str, "IS2", 3) == 0)
00896 {
00897 return (-32768 <= value && value <= 32767);
00898 }
00899 if (memcmp (str, "IU2", 3) == 0)
00900 {
00901 return (0 <= value && value <= 65535);
00902 }
00903 if (memcmp (str, "IU3", 3) == 0)
00904 {
00905 return (0 <= value && value <= 0x00ffffff);
00906 }
00907 if (memcmp (str, "In4", 3) == 0)
00908 {
00909 return (-8 <= value && value && value <= 8);
00910 }
00911 if (memcmp (str, "In5", 3) == 0)
00912 {
00913 return (-16 <= value && value && value <= 16);
00914 }
00915 if (memcmp (str, "In6", 3) == 0)
00916 {
00917 return (-32 <= value && value && value <= 32);
00918 }
00919 if (memcmp (str, "IM2", 3) == 0)
00920 {
00921 return (-65536 <= value && value && value <= -1);
00922 }
00923 if (memcmp (str, "Ilb", 3) == 0)
00924 {
00925 int b = exact_log2 (value);
00926 return (b >= 0 && b <= 7);
00927 }
00928 if (memcmp (str, "Imb", 3) == 0)
00929 {
00930 int b = exact_log2 ((value ^ 0xff) & 0xff);
00931 return (b >= 0 && b <= 7);
00932 }
00933 if (memcmp (str, "Ilw", 3) == 0)
00934 {
00935 int b = exact_log2 (value);
00936 return (b >= 0 && b <= 15);
00937 }
00938 if (memcmp (str, "Imw", 3) == 0)
00939 {
00940 int b = exact_log2 ((value ^ 0xffff) & 0xffff);
00941 return (b >= 0 && b <= 15);
00942 }
00943 if (memcmp (str, "I00", 3) == 0)
00944 {
00945 return (value == 0);
00946 }
00947 return 0;
00948 }
00949
00950
00951
00952
00953 int
00954 m32c_extra_constraint_p2 (rtx value, char c ATTRIBUTE_UNUSED, const char *str)
00955 {
00956 encode_pattern (value);
00957 if (memcmp (str, "Sd", 2) == 0)
00958 {
00959
00960 rtx r;
00961 if (GET_CODE (value) == MEM && CONSTANT_P (XEXP (value, 0)))
00962 return 1;
00963 if (RTX_IS ("ms") || RTX_IS ("m+si"))
00964 return 1;
00965 if (RTX_IS ("m++rii"))
00966 {
00967 if (REGNO (patternr[3]) == FB_REGNO
00968 && INTVAL (patternr[4]) == 0)
00969 return 1;
00970 }
00971 if (RTX_IS ("mr"))
00972 r = patternr[1];
00973 else if (RTX_IS ("m+ri") || RTX_IS ("m+rs") || RTX_IS ("m+r+si"))
00974 r = patternr[2];
00975 else
00976 return 0;
00977 if (REGNO (r) == SP_REGNO)
00978 return 0;
00979 return m32c_legitimate_address_p (GET_MODE (value), XEXP (value, 0), 1);
00980 }
00981 else if (memcmp (str, "Sa", 2) == 0)
00982 {
00983 rtx r;
00984 if (RTX_IS ("mr"))
00985 r = patternr[1];
00986 else if (RTX_IS ("m+ri"))
00987 r = patternr[2];
00988 else
00989 return 0;
00990 return (IS_REG (r, A0_REGNO) || IS_REG (r, A1_REGNO));
00991 }
00992 else if (memcmp (str, "Si", 2) == 0)
00993 {
00994 return (RTX_IS ("mi") || RTX_IS ("ms") || RTX_IS ("m+si"));
00995 }
00996 else if (memcmp (str, "Ss", 2) == 0)
00997 {
00998 return ((RTX_IS ("mr")
00999 && (IS_REG (patternr[1], SP_REGNO)))
01000 || (RTX_IS ("m+ri") && (IS_REG (patternr[2], SP_REGNO))));
01001 }
01002 else if (memcmp (str, "Sf", 2) == 0)
01003 {
01004 return ((RTX_IS ("mr")
01005 && (IS_REG (patternr[1], FB_REGNO)))
01006 || (RTX_IS ("m+ri") && (IS_REG (patternr[2], FB_REGNO))));
01007 }
01008 else if (memcmp (str, "Sb", 2) == 0)
01009 {
01010 return ((RTX_IS ("mr")
01011 && (IS_REG (patternr[1], SB_REGNO)))
01012 || (RTX_IS ("m+ri") && (IS_REG (patternr[2], SB_REGNO))));
01013 }
01014 else if (memcmp (str, "Sp", 2) == 0)
01015 {
01016
01017 return (RTX_IS ("mi")
01018 && !(INTVAL (patternr[1]) & ~0x1fff));
01019 }
01020 else if (memcmp (str, "S1", 2) == 0)
01021 {
01022 return r1h_operand (value, QImode);
01023 }
01024
01025 gcc_assert (str[0] != 'S');
01026
01027 if (memcmp (str, "Rpa", 2) == 0)
01028 return GET_CODE (value) == PARALLEL;
01029
01030 return 0;
01031 }
01032
01033
01034 int
01035 m32c_extra_constraint_p (rtx value, char c, const char *str)
01036 {
01037 int rv = m32c_extra_constraint_p2 (value, c, str);
01038 #if DEBUG0
01039 fprintf (stderr, "\nconstraint %.*s: %d\n", CONSTRAINT_LEN (c, str), str,
01040 rv);
01041 debug_rtx (value);
01042 #endif
01043 return rv;
01044 }
01045
01046
01047
01048 int
01049 m32c_extra_memory_constraint (char c, const char *str ATTRIBUTE_UNUSED)
01050 {
01051 return c == 'S';
01052 }
01053
01054
01055
01056 int
01057 m32c_extra_address_constraint (char c, const char *str ATTRIBUTE_UNUSED)
01058 {
01059 return c == 'A';
01060 }
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070 rtx
01071 m32c_return_addr_rtx (int count)
01072 {
01073 enum machine_mode mode;
01074 int offset;
01075 rtx ra_mem;
01076
01077 if (count)
01078 return NULL_RTX;
01079
01080
01081 if (TARGET_A24)
01082 {
01083 mode = SImode;
01084 offset = 4;
01085 }
01086 else
01087 {
01088
01089 mode = HImode;
01090 offset = 2;
01091 }
01092
01093 ra_mem =
01094 gen_rtx_MEM (mode, plus_constant (gen_rtx_REG (Pmode, FP_REGNO), offset));
01095 return copy_to_mode_reg (mode, ra_mem);
01096 }
01097
01098
01099 rtx
01100 m32c_incoming_return_addr_rtx (void)
01101 {
01102
01103 return gen_rtx_MEM (PSImode, gen_rtx_REG (PSImode, SP_REGNO));
01104 }
01105
01106
01107
01108
01109
01110 int
01111 m32c_eh_return_data_regno (int n)
01112 {
01113 switch (n)
01114 {
01115 case 0:
01116 return A0_REGNO;
01117 case 1:
01118 return A1_REGNO;
01119 default:
01120 return INVALID_REGNUM;
01121 }
01122 }
01123
01124
01125
01126 rtx
01127 m32c_eh_return_stackadj_rtx (void)
01128 {
01129 if (!cfun->machine->eh_stack_adjust)
01130 {
01131 rtx sa;
01132
01133 sa = gen_reg_rtx (Pmode);
01134 cfun->machine->eh_stack_adjust = sa;
01135 }
01136 return cfun->machine->eh_stack_adjust;
01137 }
01138
01139
01140
01141
01142
01143
01144
01145
01146 unsigned int
01147 m32c_dwarf_frame_regnum (int n)
01148 {
01149 switch (n)
01150 {
01151 case R0_REGNO:
01152 return 5;
01153 case R1_REGNO:
01154 return 6;
01155 case R2_REGNO:
01156 return 7;
01157 case R3_REGNO:
01158 return 8;
01159 case A0_REGNO:
01160 return 9;
01161 case A1_REGNO:
01162 return 10;
01163 case FB_REGNO:
01164 return 11;
01165 case SB_REGNO:
01166 return 19;
01167
01168 case SP_REGNO:
01169 return 12;
01170 case PC_REGNO:
01171 return 13;
01172 default:
01173 return DWARF_FRAME_REGISTERS + 1;
01174 }
01175 }
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190 static rtx
01191 F (rtx x)
01192 {
01193 RTX_FRAME_RELATED_P (x) = 1;
01194 return x;
01195 }
01196
01197
01198
01199 static struct
01200 {
01201 int reg1;
01202 int bit;
01203 int a16_bytes;
01204 int a24_bytes;
01205 } pushm_info[] =
01206 {
01207
01208 { R0_REGNO, 0x80, 2, 2 },
01209 { R1_REGNO, 0x40, 2, 2 },
01210 { R2_REGNO, 0x20, 2, 2 },
01211 { R3_REGNO, 0x10, 2, 2 },
01212 { A0_REGNO, 0x08, 2, 4 },
01213 { A1_REGNO, 0x04, 2, 4 },
01214 { SB_REGNO, 0x02, 2, 4 },
01215 { FB_REGNO, 0x01, 2, 4 }
01216 };
01217
01218 #define PUSHM_N (sizeof(pushm_info)/sizeof(pushm_info[0]))
01219
01220
01221
01222
01223
01224
01225
01226
01227 static int
01228 need_to_save (int regno)
01229 {
01230 if (fixed_regs[regno])
01231 return 0;
01232 if (cfun->calls_eh_return)
01233 return 1;
01234 if (regno == FP_REGNO)
01235 return 0;
01236 if (cfun->machine->is_interrupt
01237 && (!cfun->machine->is_leaf || regno == A0_REGNO))
01238 return 1;
01239 if (regs_ever_live[regno]
01240 && (!call_used_regs[regno] || cfun->machine->is_interrupt))
01241 return 1;
01242 return 0;
01243 }
01244
01245
01246
01247
01248
01249
01250
01251
01252 static int
01253 m32c_pushm_popm (Push_Pop_Type ppt)
01254 {
01255 int reg_mask = 0;
01256 int byte_count = 0, bytes;
01257 int i;
01258 rtx dwarf_set[PUSHM_N];
01259 int n_dwarfs = 0;
01260 int nosave_mask = 0;
01261
01262 if (cfun->return_rtx
01263 && GET_CODE (cfun->return_rtx) == PARALLEL
01264 && !(cfun->calls_eh_return || cfun->machine->is_interrupt))
01265 {
01266 rtx exp = XVECEXP (cfun->return_rtx, 0, 0);
01267 rtx rv = XEXP (exp, 0);
01268 int rv_bytes = GET_MODE_SIZE (GET_MODE (rv));
01269
01270 if (rv_bytes > 2)
01271 nosave_mask |= 0x20;
01272 else
01273 nosave_mask |= 0xf0;
01274 if (rv_bytes > 4)
01275 nosave_mask |= 0x50;
01276 }
01277
01278 for (i = 0; i < (int) PUSHM_N; i++)
01279 {
01280
01281 if (!need_to_save (pushm_info[i].reg1))
01282 continue;
01283
01284 if (pushm_info[i].bit & nosave_mask)
01285 continue;
01286
01287 reg_mask |= pushm_info[i].bit;
01288 bytes = TARGET_A16 ? pushm_info[i].a16_bytes : pushm_info[i].a24_bytes;
01289
01290 if (ppt == PP_pushm)
01291 {
01292 enum machine_mode mode = (bytes == 2) ? HImode : SImode;
01293 rtx addr;
01294
01295
01296
01297
01298
01299 addr = stack_pointer_rtx;
01300
01301 if (byte_count != 0)
01302 addr = gen_rtx_PLUS (GET_MODE (addr), addr, GEN_INT (byte_count));
01303
01304 dwarf_set[n_dwarfs++] =
01305 gen_rtx_SET (VOIDmode,
01306 gen_rtx_MEM (mode, addr),
01307 gen_rtx_REG (mode, pushm_info[i].reg1));
01308 F (dwarf_set[n_dwarfs - 1]);
01309
01310 }
01311 byte_count += bytes;
01312 }
01313
01314 if (cfun->machine->is_interrupt)
01315 {
01316 cfun->machine->intr_pushm = reg_mask & 0xfe;
01317 reg_mask = 0;
01318 byte_count = 0;
01319 }
01320
01321 if (cfun->machine->is_interrupt)
01322 for (i = MEM0_REGNO; i <= MEM7_REGNO; i++)
01323 if (need_to_save (i))
01324 {
01325 byte_count += 2;
01326 cfun->machine->intr_pushmem[i - MEM0_REGNO] = 1;
01327 }
01328
01329 if (ppt == PP_pushm && byte_count)
01330 {
01331 rtx note = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (n_dwarfs + 1));
01332 rtx pushm;
01333
01334 if (reg_mask)
01335 {
01336 XVECEXP (note, 0, 0)
01337 = gen_rtx_SET (VOIDmode,
01338 stack_pointer_rtx,
01339 gen_rtx_PLUS (GET_MODE (stack_pointer_rtx),
01340 stack_pointer_rtx,
01341 GEN_INT (-byte_count)));
01342 F (XVECEXP (note, 0, 0));
01343
01344 for (i = 0; i < n_dwarfs; i++)
01345 XVECEXP (note, 0, i + 1) = dwarf_set[i];
01346
01347 pushm = F (emit_insn (gen_pushm (GEN_INT (reg_mask))));
01348
01349 REG_NOTES (pushm) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, note,
01350 REG_NOTES (pushm));
01351 }
01352
01353 if (cfun->machine->is_interrupt)
01354 for (i = MEM0_REGNO; i <= MEM7_REGNO; i++)
01355 if (cfun->machine->intr_pushmem[i - MEM0_REGNO])
01356 {
01357 if (TARGET_A16)
01358 pushm = emit_insn (gen_pushhi_16 (gen_rtx_REG (HImode, i)));
01359 else
01360 pushm = emit_insn (gen_pushhi_24 (gen_rtx_REG (HImode, i)));
01361 F (pushm);
01362 }
01363 }
01364 if (ppt == PP_popm && byte_count)
01365 {
01366 if (cfun->machine->is_interrupt)
01367 for (i = MEM7_REGNO; i >= MEM0_REGNO; i--)
01368 if (cfun->machine->intr_pushmem[i - MEM0_REGNO])
01369 {
01370 if (TARGET_A16)
01371 emit_insn (gen_pophi_16 (gen_rtx_REG (HImode, i)));
01372 else
01373 emit_insn (gen_pophi_24 (gen_rtx_REG (HImode, i)));
01374 }
01375 if (reg_mask)
01376 emit_insn (gen_popm (GEN_INT (reg_mask)));
01377 }
01378
01379 return byte_count;
01380 }
01381
01382
01383
01384 int
01385 m32c_initial_elimination_offset (int from, int to)
01386 {
01387 int ofs = 0;
01388
01389 if (from == AP_REGNO)
01390 {
01391 if (TARGET_A16)
01392 ofs += 5;
01393 else
01394 ofs += 8;
01395 }
01396
01397 if (to == SP_REGNO)
01398 {
01399 ofs += m32c_pushm_popm (PP_justcount);
01400 ofs += get_frame_size ();
01401 }
01402
01403
01404 if (TARGET_A24)
01405 ofs = (ofs + 1) & ~1;
01406 #if DEBUG0
01407 fprintf (stderr, "initial_elimination_offset from=%d to=%d, ofs=%d\n", from,
01408 to, ofs);
01409 #endif
01410 return ofs;
01411 }
01412
01413
01414
01415 #undef TARGET_PROMOTE_PROTOTYPES
01416 #define TARGET_PROMOTE_PROTOTYPES m32c_promote_prototypes
01417 static bool
01418 m32c_promote_prototypes (tree fntype ATTRIBUTE_UNUSED)
01419 {
01420 return 0;
01421 }
01422
01423
01424
01425 int
01426 m32c_push_rounding (int n)
01427 {
01428 if (TARGET_R8C || TARGET_M16C)
01429 return n;
01430 return (n + 1) & ~1;
01431 }
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451 rtx
01452 m32c_function_arg (CUMULATIVE_ARGS * ca,
01453 enum machine_mode mode, tree type, int named)
01454 {
01455
01456 rtx rv = NULL_RTX;
01457 #if DEBUG0
01458 fprintf (stderr, "func_arg %d (%s, %d)\n",
01459 ca->parm_num, mode_name[mode], named);
01460 debug_tree (type);
01461 #endif
01462
01463 if (mode == VOIDmode)
01464 return GEN_INT (0);
01465
01466 if (ca->force_mem || !named)
01467 {
01468 #if DEBUG0
01469 fprintf (stderr, "func arg: force %d named %d, mem\n", ca->force_mem,
01470 named);
01471 #endif
01472 return NULL_RTX;
01473 }
01474
01475 if (type && INTEGRAL_TYPE_P (type) && POINTER_TYPE_P (type))
01476 return NULL_RTX;
01477
01478 if (type && AGGREGATE_TYPE_P (type))
01479 return NULL_RTX;
01480
01481 switch (ca->parm_num)
01482 {
01483 case 1:
01484 if (GET_MODE_SIZE (mode) == 1 || GET_MODE_SIZE (mode) == 2)
01485 rv = gen_rtx_REG (mode, TARGET_A16 ? R1_REGNO : R0_REGNO);
01486 break;
01487
01488 case 2:
01489 if (TARGET_A16 && GET_MODE_SIZE (mode) == 2)
01490 rv = gen_rtx_REG (mode, R2_REGNO);
01491 break;
01492 }
01493
01494 #if DEBUG0
01495 debug_rtx (rv);
01496 #endif
01497 return rv;
01498 }
01499
01500 #undef TARGET_PASS_BY_REFERENCE
01501 #define TARGET_PASS_BY_REFERENCE m32c_pass_by_reference
01502 static bool
01503 m32c_pass_by_reference (CUMULATIVE_ARGS * ca ATTRIBUTE_UNUSED,
01504 enum machine_mode mode ATTRIBUTE_UNUSED,
01505 tree type ATTRIBUTE_UNUSED,
01506 bool named ATTRIBUTE_UNUSED)
01507 {
01508 return 0;
01509 }
01510
01511
01512 void
01513 m32c_init_cumulative_args (CUMULATIVE_ARGS * ca,
01514 tree fntype,
01515 rtx libname ATTRIBUTE_UNUSED,
01516 tree fndecl,
01517 int n_named_args ATTRIBUTE_UNUSED)
01518 {
01519 if (fntype && aggregate_value_p (TREE_TYPE (fntype), fndecl))
01520 ca->force_mem = 1;
01521 else
01522 ca->force_mem = 0;
01523 ca->parm_num = 1;
01524 }
01525
01526
01527
01528
01529
01530 void
01531 m32c_function_arg_advance (CUMULATIVE_ARGS * ca,
01532 enum machine_mode mode ATTRIBUTE_UNUSED,
01533 tree type ATTRIBUTE_UNUSED,
01534 int named ATTRIBUTE_UNUSED)
01535 {
01536 if (ca->force_mem)
01537 ca->force_mem = 0;
01538 else
01539 ca->parm_num++;
01540 }
01541
01542
01543 int
01544 m32c_function_arg_regno_p (int r)
01545 {
01546 if (TARGET_A24)
01547 return (r == R0_REGNO);
01548 return (r == R1_REGNO || r == R2_REGNO);
01549 }
01550
01551
01552
01553
01554 #undef TARGET_VALID_POINTER_MODE
01555 #define TARGET_VALID_POINTER_MODE m32c_valid_pointer_mode
01556 static bool
01557 m32c_valid_pointer_mode (enum machine_mode mode)
01558 {
01559 if (mode == HImode
01560 || mode == PSImode
01561 || mode == SImode
01562 )
01563 return 1;
01564 return 0;
01565 }
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576 rtx
01577 m32c_libcall_value (enum machine_mode mode)
01578 {
01579
01580 #if 0
01581
01582
01583
01584
01585 if (mode == DFmode)
01586 {
01587 rtx rv;
01588
01589 rv = gen_rtx_PARALLEL (mode, rtvec_alloc (4));
01590 XVECEXP (rv, 0, 0) = gen_rtx_EXPR_LIST (VOIDmode,
01591 gen_rtx_REG (HImode,
01592 R0_REGNO),
01593 GEN_INT (0));
01594 XVECEXP (rv, 0, 1) = gen_rtx_EXPR_LIST (VOIDmode,
01595 gen_rtx_REG (HImode,
01596 R1_REGNO),
01597 GEN_INT (2));
01598 XVECEXP (rv, 0, 2) = gen_rtx_EXPR_LIST (VOIDmode,
01599 gen_rtx_REG (HImode,
01600 R2_REGNO),
01601 GEN_INT (4));
01602 XVECEXP (rv, 0, 3) = gen_rtx_EXPR_LIST (VOIDmode,
01603 gen_rtx_REG (HImode,
01604 R3_REGNO),
01605 GEN_INT (6));
01606 return rv;
01607 }
01608
01609 if (TARGET_A24 && GET_MODE_SIZE (mode) > 2)
01610 {
01611 rtx rv;
01612
01613 rv = gen_rtx_PARALLEL (mode, rtvec_alloc (1));
01614 XVECEXP (rv, 0, 0) = gen_rtx_EXPR_LIST (VOIDmode,
01615 gen_rtx_REG (mode,
01616 R0_REGNO),
01617 GEN_INT (0));
01618 return rv;
01619 }
01620 #endif
01621
01622 if (GET_MODE_SIZE (mode) > 2)
01623 return gen_rtx_REG (mode, MEM0_REGNO);
01624 return gen_rtx_REG (mode, R0_REGNO);
01625 }
01626
01627
01628
01629 rtx
01630 m32c_function_value (tree valtype, tree func ATTRIBUTE_UNUSED)
01631 {
01632
01633 enum machine_mode mode = TYPE_MODE (valtype);
01634 return m32c_libcall_value (mode);
01635 }
01636
01637
01638
01639
01640
01641 #undef TARGET_STRUCT_VALUE_RTX
01642 #define TARGET_STRUCT_VALUE_RTX m32c_struct_value_rtx
01643 static rtx
01644 m32c_struct_value_rtx (tree fndecl ATTRIBUTE_UNUSED,
01645 int incoming ATTRIBUTE_UNUSED)
01646 {
01647 return 0;
01648 }
01649
01650
01651
01652
01653 int
01654 m32c_epilogue_uses (int regno ATTRIBUTE_UNUSED)
01655 {
01656 if (cfun->machine->is_interrupt)
01657 return 1;
01658 return 0;
01659 }
01660
01661
01662
01663 #undef TARGET_STRICT_ARGUMENT_NAMING
01664 #define TARGET_STRICT_ARGUMENT_NAMING m32c_strict_argument_naming
01665 static bool
01666 m32c_strict_argument_naming (CUMULATIVE_ARGS * ca ATTRIBUTE_UNUSED)
01667 {
01668 return 1;
01669 }
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684 int
01685 m32c_trampoline_size (void)
01686 {
01687
01688
01689
01690 return TARGET_A16 ? 8 : 10;
01691 }
01692
01693
01694 int
01695 m32c_trampoline_alignment (void)
01696 {
01697 return 2;
01698 }
01699
01700
01701 void
01702 m32c_initialize_trampoline (rtx tramp, rtx function, rtx chainval)
01703 {
01704 #define A0(m,i) gen_rtx_MEM (m, plus_constant (tramp, i))
01705 if (TARGET_A16)
01706 {
01707
01708
01709 emit_move_insn (A0 (HImode, 0), GEN_INT (0xc475 - 0x10000));
01710 emit_move_insn (A0 (HImode, 2), chainval);
01711 emit_move_insn (A0 (QImode, 4), GEN_INT (0xfc - 0x100));
01712
01713
01714 emit_move_insn (A0 (HImode, 5), function);
01715 emit_move_insn (A0 (QImode, 7), GEN_INT (0x00));
01716 }
01717 else
01718 {
01719
01720
01721
01722 emit_move_insn (A0 (QImode, 0), GEN_INT (0xbc - 0x100));
01723 emit_move_insn (A0 (PSImode, 1), chainval);
01724 emit_move_insn (A0 (QImode, 4), GEN_INT (0xcc - 0x100));
01725 emit_move_insn (A0 (PSImode, 5), function);
01726 }
01727 #undef A0
01728 }
01729
01730
01731
01732 #undef TARGET_INIT_LIBFUNCS
01733 #define TARGET_INIT_LIBFUNCS m32c_init_libfuncs
01734 static void
01735 m32c_init_libfuncs (void)
01736 {
01737 if (TARGET_A24)
01738 {
01739
01740
01741
01742
01743 setcc_gen_code[EQ] = CODE_FOR_seq_24;
01744 setcc_gen_code[NE] = CODE_FOR_sne_24;
01745 setcc_gen_code[GT] = CODE_FOR_sgt_24;
01746 setcc_gen_code[GE] = CODE_FOR_sge_24;
01747 setcc_gen_code[LT] = CODE_FOR_slt_24;
01748 setcc_gen_code[LE] = CODE_FOR_sle_24;
01749 setcc_gen_code[GTU] = CODE_FOR_sgtu_24;
01750 setcc_gen_code[GEU] = CODE_FOR_sgeu_24;
01751 setcc_gen_code[LTU] = CODE_FOR_sltu_24;
01752 setcc_gen_code[LEU] = CODE_FOR_sleu_24;
01753 }
01754 }
01755
01756
01757
01758
01759
01760
01761
01762
01763 int
01764 m32c_legitimate_address_p (enum machine_mode mode, rtx x, int strict)
01765 {
01766 int mode_adjust;
01767 if (CONSTANT_P (x))
01768 return 1;
01769
01770
01771
01772
01773 mode_adjust = GET_MODE_SIZE (mode) - 1;
01774
01775
01776 if (GET_CODE (x) == PRE_DEC
01777 || GET_CODE (x) == POST_INC || GET_CODE (x) == PRE_MODIFY)
01778 {
01779 return (GET_CODE (XEXP (x, 0)) == REG
01780 && REGNO (XEXP (x, 0)) == SP_REGNO);
01781 }
01782
01783 #if 0
01784
01785
01786
01787 if (TARGET_A24 && GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) != PLUS)
01788 {
01789 #if DEBUG_DOUBLE
01790 fprintf (stderr, "double indirect\n");
01791 #endif
01792 x = XEXP (x, 0);
01793 }
01794 #endif
01795
01796 encode_pattern (x);
01797 if (RTX_IS ("r"))
01798 {
01799
01800
01801
01802 switch (REGNO (patternr[0]))
01803 {
01804 case A0_REGNO:
01805 case A1_REGNO:
01806 case SB_REGNO:
01807 case FB_REGNO:
01808 case SP_REGNO:
01809 return 1;
01810
01811 default:
01812 if (IS_PSEUDO (patternr[0], strict))
01813 return 1;
01814 return 0;
01815 }
01816 }
01817 if (RTX_IS ("+ri"))
01818 {
01819
01820
01821
01822 int rn = REGNO (patternr[1]);
01823 HOST_WIDE_INT offs = INTVAL (patternr[2]);
01824 switch (rn)
01825 {
01826 case A0_REGNO:
01827 case A1_REGNO:
01828 case SB_REGNO:
01829
01830
01831
01832 if (TARGET_A16)
01833 return (offs >= -65536 && offs <= 65535 - mode_adjust);
01834 if (rn == SB_REGNO)
01835 return (offs >= 0 && offs <= 65535 - mode_adjust);
01836
01837 return (offs >= -16777216 && offs <= 16777215);
01838
01839 case FB_REGNO:
01840 if (TARGET_A16)
01841 return (offs >= -128 && offs <= 127 - mode_adjust);
01842 return (offs >= -65536 && offs <= 65535 - mode_adjust);
01843
01844 case SP_REGNO:
01845 return (offs >= -128 && offs <= 127 - mode_adjust);
01846
01847 default:
01848 if (IS_PSEUDO (patternr[1], strict))
01849 return 1;
01850 return 0;
01851 }
01852 }
01853 if (RTX_IS ("+rs") || RTX_IS ("+r+si"))
01854 {
01855 rtx reg = patternr[1];
01856
01857
01858
01859
01860 switch (REGNO (reg))
01861 {
01862 case A0_REGNO:
01863 case A1_REGNO:
01864
01865
01866
01867
01868 return 1;
01869 default:
01870 if (IS_PSEUDO (reg, strict))
01871 return 1;
01872 return 0;
01873 }
01874 }
01875 return 0;
01876 }
01877
01878
01879 int
01880 m32c_reg_ok_for_base_p (rtx x, int strict)
01881 {
01882 if (GET_CODE (x) != REG)
01883 return 0;
01884 switch (REGNO (x))
01885 {
01886 case A0_REGNO:
01887 case A1_REGNO:
01888 case SB_REGNO:
01889 case FB_REGNO:
01890 case SP_REGNO:
01891 return 1;
01892 default:
01893 if (IS_PSEUDO (x, strict))
01894 return 1;
01895 return 0;
01896 }
01897 }
01898
01899
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917
01918
01919
01920
01921
01922 #define BIG_FB_ADJ 0
01923
01924
01925
01926
01927
01928
01929 int
01930 m32c_legitimize_address (rtx * x ATTRIBUTE_UNUSED,
01931 rtx oldx ATTRIBUTE_UNUSED,
01932 enum machine_mode mode ATTRIBUTE_UNUSED)
01933 {
01934 #if DEBUG0
01935 fprintf (stderr, "m32c_legitimize_address for mode %s\n", mode_name[mode]);
01936 debug_rtx (*x);
01937 fprintf (stderr, "\n");
01938 #endif
01939
01940 if (GET_CODE (*x) == PLUS
01941 && GET_CODE (XEXP (*x, 0)) == REG
01942 && REGNO (XEXP (*x, 0)) == FB_REGNO
01943 && GET_CODE (XEXP (*x, 1)) == CONST_INT
01944 && (INTVAL (XEXP (*x, 1)) < -128
01945 || INTVAL (XEXP (*x, 1)) > (128 - GET_MODE_SIZE (mode))))
01946 {
01947
01948 rtx temp = gen_reg_rtx (Pmode);
01949 *x = copy_rtx (*x);
01950 emit_insn (gen_rtx_SET (VOIDmode, temp, XEXP (*x, 0)));
01951 XEXP (*x, 0) = temp;
01952 return 1;
01953 }
01954
01955 return 0;
01956 }
01957
01958
01959 int
01960 m32c_legitimize_reload_address (rtx * x,
01961 enum machine_mode mode,
01962 int opnum,
01963 int type, int ind_levels ATTRIBUTE_UNUSED)
01964 {
01965 #if DEBUG0
01966 fprintf (stderr, "\nm32c_legitimize_reload_address for mode %s\n",
01967 mode_name[mode]);
01968 debug_rtx (*x);
01969 #endif
01970
01971
01972
01973
01974
01975
01976
01977
01978
01979
01980 if (GET_CODE (*x) == PLUS
01981 && GET_CODE (XEXP (*x, 0)) == REG
01982 && REGNO (XEXP (*x, 0)) == FB_REGNO
01983 && GET_CODE (XEXP (*x, 1)) == CONST_INT
01984 && (INTVAL (XEXP (*x, 1)) < -128
01985 || INTVAL (XEXP (*x, 1)) > (128 - GET_MODE_SIZE (mode))))
01986 {
01987 rtx sum;
01988 int offset = INTVAL (XEXP (*x, 1));
01989 int adjustment = -BIG_FB_ADJ;
01990
01991 sum = gen_rtx_PLUS (Pmode, XEXP (*x, 0),
01992 GEN_INT (adjustment));
01993 *x = gen_rtx_PLUS (Pmode, sum, GEN_INT (offset - adjustment));
01994 if (type == RELOAD_OTHER)
01995 type = RELOAD_FOR_OTHER_ADDRESS;
01996 push_reload (sum, NULL_RTX, &XEXP (*x, 0), NULL,
01997 A_REGS, Pmode, VOIDmode, 0, 0, opnum,
01998 type);
01999 return 1;
02000 }
02001
02002 if (GET_CODE (*x) == PLUS
02003 && GET_CODE (XEXP (*x, 0)) == PLUS
02004 && GET_CODE (XEXP (XEXP (*x, 0), 0)) == REG
02005 && REGNO (XEXP (XEXP (*x, 0), 0)) == FB_REGNO
02006 && GET_CODE (XEXP (XEXP (*x, 0), 1)) == CONST_INT
02007 && GET_CODE (XEXP (*x, 1)) == CONST_INT
02008 )
02009 {
02010 if (type == RELOAD_OTHER)
02011 type = RELOAD_FOR_OTHER_ADDRESS;
02012 push_reload (XEXP (*x, 0), NULL_RTX, &XEXP (*x, 0), NULL,
02013 A_REGS, Pmode, VOIDmode, 0, 0, opnum,
02014 type);
02015 return 1;
02016 }
02017
02018 return 0;
02019 }
02020
02021
02022 int
02023 m32c_mode_dependent_address (rtx addr)
02024 {
02025 if (GET_CODE (addr) == POST_INC || GET_CODE (addr) == PRE_DEC)
02026 return 1;
02027 return 0;
02028 }
02029
02030
02031
02032 int
02033 m32c_legitimate_constant_p (rtx x ATTRIBUTE_UNUSED)
02034 {
02035 return 1;
02036 }
02037
02038
02039
02040
02041 #undef TARGET_FIXED_CONDITION_CODE_REGS
02042 #define TARGET_FIXED_CONDITION_CODE_REGS m32c_fixed_condition_code_regs
02043 static bool
02044 m32c_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2)
02045 {
02046 *p1 = FLG_REGNO;
02047 *p2 = INVALID_REGNUM;
02048 return true;
02049 }
02050
02051
02052
02053
02054
02055
02056
02057 int
02058 m32c_register_move_cost (enum machine_mode mode, int from, int to)
02059 {
02060 int cost = COSTS_N_INSNS (3);
02061 int cc = class_contents[from][0] | class_contents[to][0];
02062
02063 if (mode == QImode && (cc & class_contents[R23_REGS][0]))
02064 {
02065 if (!(cc & ~class_contents[R23_REGS][0]))
02066 cost = COSTS_N_INSNS (1000);
02067 else
02068 cost = COSTS_N_INSNS (80);
02069 }
02070
02071 if (!class_can_hold_mode (from, mode) || !class_can_hold_mode (to, mode))
02072 cost = COSTS_N_INSNS (1000);
02073
02074 if (classes_intersect (from, CR_REGS))
02075 cost += COSTS_N_INSNS (5);
02076
02077 if (classes_intersect (to, CR_REGS))
02078 cost += COSTS_N_INSNS (5);
02079
02080 if (from == MEM_REGS || to == MEM_REGS)
02081 cost += COSTS_N_INSNS (50);
02082 else if (classes_intersect (from, MEM_REGS)
02083 || classes_intersect (to, MEM_REGS))
02084 cost += COSTS_N_INSNS (10);
02085
02086 #if DEBUG0
02087 fprintf (stderr, "register_move_cost %s from %s to %s = %d\n",
02088 mode_name[mode], class_names[from], class_names[to], cost);
02089 #endif
02090 return cost;
02091 }
02092
02093
02094 int
02095 m32c_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
02096 int reg_class ATTRIBUTE_UNUSED,
02097 int in ATTRIBUTE_UNUSED)
02098 {
02099
02100 return COSTS_N_INSNS (10);
02101 }
02102
02103
02104
02105 #undef TARGET_RTX_COSTS
02106 #define TARGET_RTX_COSTS m32c_rtx_costs
02107 static bool
02108 m32c_rtx_costs (rtx x, int code, int outer_code, int *total)
02109 {
02110 switch (code)
02111 {
02112 case REG:
02113 if (REGNO (x) >= MEM0_REGNO && REGNO (x) <= MEM7_REGNO)
02114 *total += COSTS_N_INSNS (500);
02115 else
02116 *total += COSTS_N_INSNS (1);
02117 return true;
02118
02119 case ASHIFT:
02120 case LSHIFTRT:
02121 case ASHIFTRT:
02122 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
02123 {
02124
02125 *total += COSTS_N_INSNS (1);
02126 return true;
02127 }
02128 if (INTVAL (XEXP (x, 1)) > 8
02129 || INTVAL (XEXP (x, 1)) < -8)
02130 {
02131
02132
02133 *total += COSTS_N_INSNS (2);
02134 return true;
02135 }
02136 return true;
02137
02138 case LE:
02139 case LEU:
02140 case LT:
02141 case LTU:
02142 case GT:
02143 case GTU:
02144 case GE:
02145 case GEU:
02146 case NE:
02147 case EQ:
02148 if (outer_code == SET)
02149 {
02150 *total += COSTS_N_INSNS (2);
02151 return true;
02152 }
02153 break;
02154
02155 case ZERO_EXTRACT:
02156 {
02157 rtx dest = XEXP (x, 0);
02158 rtx addr = XEXP (dest, 0);
02159 switch (GET_CODE (addr))
02160 {
02161 case CONST_INT:
02162 *total += COSTS_N_INSNS (1);
02163 break;
02164 case SYMBOL_REF:
02165 *total += COSTS_N_INSNS (3);
02166 break;
02167 default:
02168 *total += COSTS_N_INSNS (2);
02169 break;
02170 }
02171 return true;
02172 }
02173 break;
02174
02175 default:
02176
02177 if (TARGET_A16 && GET_MODE(x) == SImode)
02178 *total += COSTS_N_INSNS (2);
02179 break;
02180 }
02181 return false;
02182 }
02183
02184 #undef TARGET_ADDRESS_COST
02185 #define TARGET_ADDRESS_COST m32c_address_cost
02186 static int
02187 m32c_address_cost (rtx addr)
02188 {
02189
02190
02191 switch (GET_CODE (addr))
02192 {
02193 case CONST_INT:
02194 return COSTS_N_INSNS(1);
02195 case SYMBOL_REF:
02196 return COSTS_N_INSNS(3);
02197 case REG:
02198 return COSTS_N_INSNS(2);
02199 default:
02200 return 0;
02201 }
02202 }
02203
02204
02205
02206
02207
02208 #undef TARGET_HAVE_NAMED_SECTIONS
02209 #define TARGET_HAVE_NAMED_SECTIONS true
02210
02211
02212
02213
02214
02215 #undef TARGET_ASM_INTEGER
02216 #define TARGET_ASM_INTEGER m32c_asm_integer
02217 static bool
02218 m32c_asm_integer (rtx x, unsigned int size, int aligned_p)
02219 {
02220 switch (size)
02221 {
02222 case 3:
02223 fprintf (asm_out_file, "\t.3byte\t");
02224 output_addr_const (asm_out_file, x);
02225 fputc ('\n', asm_out_file);
02226 return true;
02227 case 4:
02228 if (GET_CODE (x) == SYMBOL_REF)
02229 {
02230 fprintf (asm_out_file, "\t.long\t");
02231 output_addr_const (asm_out_file, x);
02232 fputc ('\n', asm_out_file);
02233 return true;
02234 }
02235 break;
02236 }
02237 return default_assemble_integer (x, size, aligned_p);
02238 }
02239
02240
02241
02242
02243
02244 static struct
02245 {
02246 char code;
02247 char const *pattern;
02248 char const *format;
02249 }
02250 const conversions[] = {
02251 { 0, "r", "0" },
02252
02253 { 0, "mr", "z[1]" },
02254 { 0, "m+ri", "3[2]" },
02255 { 0, "m+rs", "3[2]" },
02256 { 0, "m+r+si", "4+5[2]" },
02257 { 0, "ms", "1" },
02258 { 0, "mi", "1" },
02259 { 0, "m+si", "2+3" },
02260
02261 { 0, "mmr", "[z[2]]" },
02262 { 0, "mm+ri", "[4[3]]" },
02263 { 0, "mm+rs", "[4[3]]" },
02264 { 0, "mm+r+si", "[5+6[3]]" },
02265 { 0, "mms", "[[2]]" },
02266 { 0, "mmi", "[[2]]" },
02267 { 0, "mm+si", "[4[3]]" },
02268
02269 { 0, "i", "#0" },
02270 { 0, "s", "#0" },
02271 { 0, "+si", "#1+2" },
02272 { 0, "l", "#0" },
02273
02274 { 'l', "l", "0" },
02275 { 'd', "i", "0" },
02276 { 'd', "s", "0" },
02277 { 'd', "+si", "1+2" },
02278 { 'D', "i", "0" },
02279 { 'D', "s", "0" },
02280 { 'D', "+si", "1+2" },
02281 { 'x', "i", "#0" },
02282 { 'X', "i", "#0" },
02283 { 'm', "i", "#0" },
02284 { 'b', "i", "#0" },
02285 { 'B', "i", "0" },
02286 { 'p', "i", "0" },
02287
02288 { 0, 0, 0 }
02289 };
02290
02291
02292 static char const *pushm_regs[] = {
02293 "fb", "sb", "a1", "a0", "r3", "r2", "r1", "r0"
02294 };
02295
02296
02297 void
02298 m32c_print_operand (FILE * file, rtx x, int code)
02299 {
02300 int i, j, b;
02301 const char *comma;
02302 HOST_WIDE_INT ival;
02303 int unsigned_const = 0;
02304 int force_sign;
02305
02306
02307
02308
02309 if (code == 'u')
02310 {
02311 unsigned_const = 2;
02312 code = 0;
02313 }
02314 if (code == 'U')
02315 {
02316 unsigned_const = 1;
02317 code = 0;
02318 }
02319
02320
02321 if (code == '!')
02322 {
02323 fprintf (stderr, "dj: unreviewed pattern:");
02324 if (current_output_insn)
02325 debug_rtx (current_output_insn);
02326 gcc_unreachable ();
02327 }
02328
02329 if (code == '&')
02330 {
02331 if (TARGET_A16)
02332 fprintf (file, "w");
02333 else
02334 fprintf (file, "l");
02335 return;
02336 }
02337
02338 if (code == 'C')
02339 {
02340 switch (GET_CODE (x))
02341 {
02342 case LE:
02343 fputs ("gt", file);
02344 break;
02345 case LEU:
02346 fputs ("gtu", file);
02347 break;
02348 case LT:
02349 fputs ("ge", file);
02350 break;
02351 case LTU:
02352 fputs ("geu", file);
02353 break;
02354 case GT:
02355 fputs ("le", file);
02356 break;
02357 case GTU:
02358 fputs ("leu", file);
02359 break;
02360 case GE:
02361 fputs ("lt", file);
02362 break;
02363 case GEU:
02364 fputs ("ltu", file);
02365 break;
02366 case NE:
02367 fputs ("eq", file);
02368 break;
02369 case EQ:
02370 fputs ("ne", file);
02371 break;
02372 default:
02373 gcc_unreachable ();
02374 }
02375 return;
02376 }
02377
02378 if (code == 'c')
02379 {
02380 switch (GET_CODE (x))
02381 {
02382 case LE:
02383 fputs ("le", file);
02384 break;
02385 case LEU:
02386 fputs ("leu", file);
02387 break;
02388 case LT:
02389 fputs ("lt", file);
02390 break;
02391 case LTU:
02392 fputs ("ltu", file);
02393 break;
02394 case GT:
02395 fputs ("gt", file);
02396 break;
02397 case GTU:
02398 fputs ("gtu", file);
02399 break;
02400 case GE:
02401 fputs ("ge", file);
02402 break;
02403 case GEU:
02404 fputs ("geu", file);
02405 break;
02406 case NE:
02407 fputs ("ne", file);
02408 break;
02409 case EQ:
02410 fputs ("eq", file);
02411 break;
02412 default:
02413 gcc_unreachable ();
02414 }
02415 return;
02416 }
02417
02418
02419 if (code == 'h' && GET_MODE (x) == SImode)
02420 {
02421 x = m32c_subreg (HImode, x, SImode, 0);
02422 code = 0;
02423 }
02424 if (code == 'H' && GET_MODE (x) == SImode)
02425 {
02426 x = m32c_subreg (HImode, x, SImode, 2);
02427 code = 0;
02428 }
02429 if (code == 'h' && GET_MODE (x) == HImode)
02430 {
02431 x = m32c_subreg (QImode, x, HImode, 0);
02432 code = 0;
02433 }
02434 if (code == 'H' && GET_MODE (x) == HImode)
02435 {
02436
02437 if (GET_CODE (x) == REG)
02438 {
02439 switch (REGNO (x))
02440 {
02441 case R0_REGNO:
02442 fputs ("r0h", file);
02443 return;
02444 case R1_REGNO:
02445 fputs ("r1h", file);
02446 return;
02447 default:
02448 gcc_unreachable();
02449 }
02450 }
02451
02452 x = m32c_subreg (QImode, x, HImode, 1);
02453 code = 0;
02454 }
02455
02456 if (code == 'h' && GET_MODE (x) == QImode)
02457 {
02458 if (GET_CODE (x) == REG)
02459 x = gen_rtx_REG (HImode, REGNO (x));
02460 code = 0;
02461 }
02462
02463 if ((code == 'x' || code == 'X') && GET_CODE (x) != CONST_INT)
02464 code = 0;
02465
02466 encode_pattern (x);
02467 force_sign = 0;
02468 for (i = 0; conversions[i].pattern; i++)
02469 if (conversions[i].code == code
02470 && streq (conversions[i].pattern, pattern))
02471 {
02472 for (j = 0; conversions[i].format[j]; j++)
02473
02474 if (conversions[i].format[j] == '\\')
02475 {
02476 fputc (conversions[i].format[j + 1], file);
02477 j++;
02478 }
02479
02480
02481 else if (ISDIGIT (conversions[i].format[j]))
02482 {
02483 rtx r = patternr[conversions[i].format[j] - '0'];
02484 switch (GET_CODE (r))
02485 {
02486 case REG:
02487 fprintf (file, "%s",
02488 reg_name_with_mode (REGNO (r), GET_MODE (r)));
02489 break;
02490 case CONST_INT:
02491 switch (code)
02492 {
02493 case 'b':
02494 case 'B':
02495 {
02496 int v = INTVAL (r);
02497 int i = (int) exact_log2 (v);
02498 if (i == -1)
02499 i = (int) exact_log2 ((v ^ 0xffff) & 0xffff);
02500 if (i == -1)
02501 i = (int) exact_log2 ((v ^ 0xff) & 0xff);
02502
02503 fprintf (file, "%d", i);
02504 }
02505 break;
02506 case 'x':
02507
02508 fprintf (file, HOST_WIDE_INT_PRINT_HEX,
02509 INTVAL (r) & 0xff);
02510 break;
02511 case 'X':
02512
02513 fprintf (file, HOST_WIDE_INT_PRINT_HEX,
02514 INTVAL (r) & 0xffff);
02515 break;
02516 case 'p':
02517
02518 comma = "";
02519 for (b = 7; b >= 0; b--)
02520 if (INTVAL (r) & (1 << b))
02521 {
02522 fprintf (file, "%s%s", comma, pushm_regs[b]);
02523 comma = ",";
02524 }
02525 break;
02526 case 'm':
02527
02528 ival = (-INTVAL (r) & 0xffff);
02529 if (ival & 0x8000)
02530 ival = ival - 0x10000;
02531 fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival);
02532 break;
02533 default:
02534 ival = INTVAL (r);
02535 if (conversions[i].format[j + 1] == '[' && ival < 0)
02536 {
02537
02538
02539
02540
02541 rtx base =
02542 patternr[conversions[i].format[j + 2] - '0'];
02543 if (GET_CODE (base) == REG)
02544 switch (REGNO (base))
02545 {
02546 case A0_REGNO:
02547 case A1_REGNO:
02548 if (TARGET_A24)
02549 ival = 0x1000000 + ival;
02550 else
02551 ival = 0x10000 + ival;
02552 break;
02553 case SB_REGNO:
02554 if (TARGET_A16)
02555 ival = 0x10000 + ival;
02556 break;
02557 }
02558 }
02559 else if (code == 'd' && ival < 0 && j == 0)
02560
02561
02562
02563
02564
02565 ival = (TARGET_A24 ? 0x1000000 : 0x10000) + ival;
02566
02567 if (conversions[i].format[j] == '0')
02568 {
02569
02570 if (unsigned_const == 2)
02571 ival &= 0xffff;
02572 if (unsigned_const == 1)
02573 ival &= 0xff;
02574 }
02575 if (streq (conversions[i].pattern, "mi")
02576 || streq (conversions[i].pattern, "mmi"))
02577 {
02578
02579 ival &= (TARGET_A24 ? 0xffffff : 0xffff);
02580 }
02581 if (force_sign && ival >= 0)
02582 fputc ('+', file);
02583 fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival);
02584 break;
02585 }
02586 break;
02587 case CONST_DOUBLE:
02588
02589
02590 fprintf (file, "[const_double 0x%lx]",
02591 (unsigned long) CONST_DOUBLE_HIGH (r));
02592 break;
02593 case SYMBOL_REF:
02594 assemble_name (file, XSTR (r, 0));
02595 break;
02596 case LABEL_REF:
02597 output_asm_label (r);
02598 break;
02599 default:
02600 fprintf (stderr, "don't know how to print this operand:");
02601 debug_rtx (r);
02602 gcc_unreachable ();
02603 }
02604 }
02605 else
02606 {
02607 if (conversions[i].format[j] == 'z')
02608 {
02609
02610
02611 int k;
02612 for (k = j + 1; conversions[i].format[k]; k++)
02613 if (ISDIGIT (conversions[i].format[k]))
02614 {
02615 rtx reg = patternr[conversions[i].format[k] - '0'];
02616 if (GET_CODE (reg) == REG
02617 && (REGNO (reg) == SB_REGNO
02618 || REGNO (reg) == FB_REGNO
02619 || REGNO (reg) == SP_REGNO))
02620 fputc ('0', file);
02621 }
02622 continue;
02623 }
02624
02625
02626 if (conversions[i].format[j] == '+'
02627 && (!code || code == 'D' || code == 'd')
02628 && ISDIGIT (conversions[i].format[j + 1])
02629 && (GET_CODE (patternr[conversions[i].format[j + 1] - '0'])
02630 == CONST_INT))
02631 {
02632 force_sign = 1;
02633 continue;
02634 }
02635 fputc (conversions[i].format[j], file);
02636 }
02637 break;
02638 }
02639 if (!conversions[i].pattern)
02640 {
02641 fprintf (stderr, "unconvertible operand %c `%s'", code ? code : '-',
02642 pattern);
02643 debug_rtx (x);
02644 fprintf (file, "[%c.%s]", code ? code : '-', pattern);
02645 }
02646
02647 return;
02648 }
02649
02650
02651
02652 int
02653 m32c_print_operand_punct_valid_p (int c)
02654 {
02655 if (c == '&' || c == '!')
02656 return 1;
02657 return 0;
02658 }
02659
02660
02661 void
02662 m32c_print_operand_address (FILE * stream, rtx address)
02663 {
02664 gcc_assert (GET_CODE (address) == MEM);
02665 m32c_print_operand (stream, XEXP (address, 0), 0);
02666 }
02667
02668
02669
02670 void
02671 m32c_output_reg_push (FILE * s, int regno)
02672 {
02673 if (regno == FLG_REGNO)
02674 fprintf (s, "\tpushc\tflg\n");
02675 else
02676 fprintf (s, "\tpush.%c\t%s\n",
02677 " bwll"[reg_push_size (regno)], reg_names[regno]);
02678 }
02679
02680
02681 void
02682 m32c_output_reg_pop (FILE * s, int regno)
02683 {
02684 if (regno == FLG_REGNO)
02685 fprintf (s, "\tpopc\tflg\n");
02686 else
02687 fprintf (s, "\tpop.%c\t%s\n",
02688 " bwll"[reg_push_size (regno)], reg_names[regno]);
02689 }
02690
02691
02692
02693
02694
02695 #define M32C_ATTRIBUTES(decl) \
02696 (TYPE_P (decl)) ? TYPE_ATTRIBUTES (decl) \
02697 : DECL_ATTRIBUTES (decl) \
02698 ? (DECL_ATTRIBUTES (decl)) \
02699 : TYPE_ATTRIBUTES (TREE_TYPE (decl))
02700
02701
02702 static int
02703 interrupt_p (tree node ATTRIBUTE_UNUSED)
02704 {
02705 tree list = M32C_ATTRIBUTES (node);
02706 while (list)
02707 {
02708 if (is_attribute_p ("interrupt", TREE_PURPOSE (list)))
02709 return 1;
02710 list = TREE_CHAIN (list);
02711 }
02712 return 0;
02713 }
02714
02715 static tree
02716 interrupt_handler (tree * node ATTRIBUTE_UNUSED,
02717 tree name ATTRIBUTE_UNUSED,
02718 tree args ATTRIBUTE_UNUSED,
02719 int flags ATTRIBUTE_UNUSED,
02720 bool * no_add_attrs ATTRIBUTE_UNUSED)
02721 {
02722 return NULL_TREE;
02723 }
02724
02725 #undef TARGET_ATTRIBUTE_TABLE
02726 #define TARGET_ATTRIBUTE_TABLE m32c_attribute_table
02727 static const struct attribute_spec m32c_attribute_table[] = {
02728 {"interrupt", 0, 0, false, false, false, interrupt_handler},
02729 {0, 0, 0, 0, 0, 0, 0}
02730 };
02731
02732 #undef TARGET_COMP_TYPE_ATTRIBUTES
02733 #define TARGET_COMP_TYPE_ATTRIBUTES m32c_comp_type_attributes
02734 static int
02735 m32c_comp_type_attributes (tree type1 ATTRIBUTE_UNUSED,
02736 tree type2 ATTRIBUTE_UNUSED)
02737 {
02738
02739 return 1;
02740 }
02741
02742 #undef TARGET_INSERT_ATTRIBUTES
02743 #define TARGET_INSERT_ATTRIBUTES m32c_insert_attributes
02744 static void
02745 m32c_insert_attributes (tree node ATTRIBUTE_UNUSED,
02746 tree * attr_ptr ATTRIBUTE_UNUSED)
02747 {
02748
02749 }
02750
02751
02752
02753
02754
02755
02756
02757
02758 bool
02759 m32c_mov_ok (rtx * operands, enum machine_mode mode ATTRIBUTE_UNUSED)
02760 {
02761 rtx op0 = operands[0];
02762 rtx op1 = operands[1];
02763
02764 if (TARGET_A24)
02765 return true;
02766
02767 #define DEBUG_MOV_OK 0
02768 #if DEBUG_MOV_OK
02769 fprintf (stderr, "m32c_mov_ok %s\n", mode_name[mode]);
02770 debug_rtx (op0);
02771 debug_rtx (op1);
02772 #endif
02773
02774 if (GET_CODE (op0) == SUBREG)
02775 op0 = XEXP (op0, 0);
02776 if (GET_CODE (op1) == SUBREG)
02777 op1 = XEXP (op1, 0);
02778
02779 if (GET_CODE (op0) == MEM
02780 && GET_CODE (op1) == MEM
02781 && ! reload_completed)
02782 {
02783 #if DEBUG_MOV_OK
02784 fprintf (stderr, " - no, mem to mem\n");
02785 #endif
02786 return false;
02787 }
02788
02789 #if DEBUG_MOV_OK
02790 fprintf (stderr, " - ok\n");
02791 #endif
02792 return true;
02793 }
02794
02795
02796
02797
02798 bool
02799 m32c_immd_dbl_mov (rtx * operands,
02800 enum machine_mode mode ATTRIBUTE_UNUSED)
02801 {
02802 int flag = 0, okflag = 0, offset1 = 0, offset2 = 0, offsetsign = 0;
02803 const char *str1;
02804 const char *str2;
02805
02806 if (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
02807 && MEM_SCALAR_P (operands[0])
02808 && !MEM_IN_STRUCT_P (operands[0])
02809 && GET_CODE (XEXP (operands[2], 0)) == CONST
02810 && GET_CODE (XEXP (XEXP (operands[2], 0), 0)) == PLUS
02811 && GET_CODE (XEXP (XEXP (XEXP (operands[2], 0), 0), 0)) == SYMBOL_REF
02812 && GET_CODE (XEXP (XEXP (XEXP (operands[2], 0), 0), 1)) == CONST_INT
02813 && MEM_SCALAR_P (operands[2])
02814 && !MEM_IN_STRUCT_P (operands[2]))
02815 flag = 1;
02816
02817 else if (GET_CODE (XEXP (operands[0], 0)) == CONST
02818 && GET_CODE (XEXP (XEXP (operands[0], 0), 0)) == PLUS
02819 && GET_CODE (XEXP (XEXP (XEXP (operands[0], 0), 0), 0)) == SYMBOL_REF
02820 && MEM_SCALAR_P (operands[0])
02821 && !MEM_IN_STRUCT_P (operands[0])
02822 && !(XINT (XEXP (XEXP (XEXP (operands[0], 0), 0), 1), 0) %4)
02823 && GET_CODE (XEXP (operands[2], 0)) == CONST
02824 && GET_CODE (XEXP (XEXP (operands[2], 0), 0)) == PLUS
02825 && GET_CODE (XEXP (XEXP (XEXP (operands[2], 0), 0), 0)) == SYMBOL_REF
02826 && MEM_SCALAR_P (operands[2])
02827 && !MEM_IN_STRUCT_P (operands[2]))
02828 flag = 2;
02829
02830 else if (GET_CODE (XEXP (operands[0], 0)) == PLUS
02831 && GET_CODE (XEXP (XEXP (operands[0], 0), 0)) == REG
02832 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == FB_REGNO
02833 && GET_CODE (XEXP (XEXP (operands[0], 0), 1)) == CONST_INT
02834 && MEM_SCALAR_P (operands[0])
02835 && !MEM_IN_STRUCT_P (operands[0])
02836 && !(XINT (XEXP (XEXP (operands[0], 0), 1), 0) %4)
02837 && REGNO (XEXP (XEXP (operands[2], 0), 0)) == FB_REGNO
02838 && GET_CODE (XEXP (XEXP (operands[2], 0), 1)) == CONST_INT
02839 && MEM_SCALAR_P (operands[2])
02840 && !MEM_IN_STRUCT_P (operands[2]))
02841 flag = 3;
02842
02843 else
02844 return false;
02845
02846 switch (flag)
02847 {
02848 case 1:
02849 str1 = XSTR (XEXP (operands[0], 0), 0);
02850 str2 = XSTR (XEXP (XEXP (XEXP (operands[2], 0), 0), 0), 0);
02851 if (strcmp (str1, str2) == 0)
02852 okflag = 1;
02853 else
02854 okflag = 0;
02855 break;
02856 case 2:
02857 str1 = XSTR (XEXP (XEXP (XEXP (operands[0], 0), 0), 0), 0);
02858 str2 = XSTR (XEXP (XEXP (XEXP (operands[2], 0), 0), 0), 0);
02859 if (strcmp(str1,str2) == 0)
02860 okflag = 1;
02861 else
02862 okflag = 0;
02863 break;
02864 case 3:
02865 offset1 = XINT (XEXP (XEXP (operands[0], 0), 1), 0);
02866 offset2 = XINT (XEXP (XEXP (operands[2], 0), 1), 0);
02867 offsetsign = offset1 >> ((sizeof (offset1) * 8) -1);
02868 if (((offset2-offset1) == 2) && offsetsign != 0)
02869 okflag = 1;
02870 else
02871 okflag = 0;
02872 break;
02873 default:
02874 okflag = 0;
02875 }
02876
02877 if (okflag == 1)
02878 {
02879 HOST_WIDE_INT val;
02880 operands[4] = gen_rtx_MEM (SImode, XEXP (operands[0], 0));
02881
02882 val = (XINT (operands[3], 0) << 16) + (XINT (operands[1], 0) & 0xFFFF);
02883 operands[5] = gen_rtx_CONST_INT (VOIDmode, val);
02884
02885 return true;
02886 }
02887
02888 return false;
02889 }
02890
02891
02892
02893
02894
02895 static rtx
02896 m32c_subreg (enum machine_mode outer,
02897 rtx x, enum machine_mode inner, int byte)
02898 {
02899 int r, nr = -1;
02900
02901
02902
02903 if (GET_CODE (x) == SUBREG
02904 && SUBREG_BYTE (x) == 0
02905 && GET_CODE (SUBREG_REG (x)) == MEM
02906 && (GET_MODE_SIZE (GET_MODE (x))
02907 == GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
02908 {
02909 rtx oldx = x;
02910 x = gen_rtx_MEM (GET_MODE (x), XEXP (SUBREG_REG (x), 0));
02911 MEM_COPY_ATTRIBUTES (x, SUBREG_REG (oldx));
02912 }
02913
02914
02915 if (GET_CODE (x) == MEM
02916 && (GET_CODE (XEXP (x, 0)) == PRE_DEC
02917 || GET_CODE (XEXP (x, 0)) == POST_INC))
02918 return gen_rtx_MEM (outer, XEXP (x, 0));
02919 if (GET_CODE (x) == SUBREG
02920 && GET_CODE (XEXP (x, 0)) == MEM
02921 && (GET_CODE (XEXP (XEXP (x, 0), 0)) == PRE_DEC
02922 || GET_CODE (XEXP (XEXP (x, 0), 0)) == POST_INC))
02923 return gen_rtx_MEM (outer, XEXP (XEXP (x, 0), 0));
02924
02925 if (GET_CODE (x) != REG)
02926 return simplify_gen_subreg (outer, x, inner, byte);
02927
02928 r = REGNO (x);
02929 if (r >= FIRST_PSEUDO_REGISTER || r == AP_REGNO)
02930 return simplify_gen_subreg (outer, x, inner, byte);
02931
02932 if (IS_MEM_REGNO (r))
02933 return simplify_gen_subreg (outer, x, inner, byte);
02934
02935
02936
02937 if (byte == 0)
02938 nr = r;
02939 else if (outer == HImode)
02940 {
02941 if (r == R0_REGNO && byte == 2)
02942 nr = R2_REGNO;
02943 else if (r == R0_REGNO && byte == 4)
02944 nr = R1_REGNO;
02945 else if (r == R0_REGNO && byte == 6)
02946 nr = R3_REGNO;
02947 else if (r == R1_REGNO && byte == 2)
02948 nr = R3_REGNO;
02949 else if (r == A0_REGNO && byte == 2)
02950 nr = A1_REGNO;
02951 }
02952 else if (outer == SImode)
02953 {
02954 if (r == R0_REGNO && byte == 0)
02955 nr = R0_REGNO;
02956 else if (r == R0_REGNO && byte == 4)
02957 nr = R1_REGNO;
02958 }
02959 if (nr == -1)
02960 {
02961 fprintf (stderr, "m32c_subreg %s %s %d\n",
02962 mode_name[outer], mode_name[inner], byte);
02963 debug_rtx (x);
02964 gcc_unreachable ();
02965 }
02966 return gen_rtx_REG (outer, nr);
02967 }
02968
02969
02970
02971 int
02972 m32c_prepare_move (rtx * operands, enum machine_mode mode)
02973 {
02974 if (TARGET_A16 && mode == PSImode)
02975 return m32c_split_move (operands, mode, 1);
02976 if ((GET_CODE (operands[0]) == MEM)
02977 && (GET_CODE (XEXP (operands[0], 0)) == PRE_MODIFY))
02978 {
02979 rtx pmv = XEXP (operands[0], 0);
02980 rtx dest_reg = XEXP (pmv, 0);
02981 rtx dest_mod = XEXP (pmv, 1);
02982
02983 emit_insn (gen_rtx_SET (Pmode, dest_reg, dest_mod));
02984 operands[0] = gen_rtx_MEM (mode, dest_reg);
02985 }
02986 if (!no_new_pseudos && MEM_P (operands[0]) && MEM_P (operands[1]))
02987 operands[1] = copy_to_mode_reg (mode, operands[1]);
02988 return 0;
02989 }
02990
02991 #define DEBUG_SPLIT 0
02992
02993
02994
02995
02996 int
02997 m32c_split_psi_p (rtx * operands)
02998 {
02999 #if DEBUG_SPLIT
03000 fprintf (stderr, "\nm32c_split_psi_p\n");
03001 debug_rtx (operands[0]);
03002 debug_rtx (operands[1]);
03003 #endif
03004 if (TARGET_A16)
03005 {
03006 #if DEBUG_SPLIT
03007 fprintf (stderr, "yes, A16\n");
03008 #endif
03009 return 1;
03010 }
03011 if (GET_CODE (operands[1]) == MEM
03012 && GET_CODE (XEXP (operands[1], 0)) == POST_INC)
03013 {
03014 #if DEBUG_SPLIT
03015 fprintf (stderr, "yes, pop.l\n");
03016 #endif
03017 return 1;
03018 }
03019 #if DEBUG_SPLIT
03020 fprintf (stderr, "no, default\n");
03021 #endif
03022 return 0;
03023 }
03024
03025
03026
03027
03028 int
03029 m32c_split_move (rtx * operands, enum machine_mode mode, int split_all)
03030 {
03031 rtx s[4], d[4];
03032 int parts, si, di, rev = 0;
03033 int rv = 0, opi = 2;
03034 enum machine_mode submode = HImode;
03035 rtx *ops, local_ops[10];
03036
03037
03038
03039
03040 if (split_all == 3)
03041 ops = operands;
03042 else
03043 ops = local_ops;
03044
03045
03046 if (mode == DImode)
03047 submode = SImode;
03048
03049
03050
03051 if (!no_new_pseudos && MEM_P (operands[0]) && MEM_P (operands[1]))
03052 {
03053 #if DEBUG0
03054 fprintf (stderr, "force_reg...\n");
03055 debug_rtx (operands[1]);
03056 #endif
03057 operands[1] = force_reg (mode, operands[1]);
03058 #if DEBUG0
03059 debug_rtx (operands[1]);
03060 #endif
03061 }
03062
03063 parts = 2;
03064
03065 #if DEBUG_SPLIT
03066 fprintf (stderr, "\nsplit_move %d all=%d\n", no_new_pseudos, split_all);
03067 debug_rtx (operands[0]);
03068 debug_rtx (operands[1]);
03069 #endif
03070
03071
03072
03073
03074
03075 if (m32c_extra_constraint_p (operands[0], 'S', "Ss"))
03076 split_all = 3;
03077
03078
03079 if (TARGET_A24
03080 && split_all != 3
03081 && (mode == SImode || mode == PSImode)
03082 && !(GET_CODE (operands[1]) == MEM
03083 && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
03084 return 0;
03085
03086
03087 for (si = 0; si < parts; si++)
03088 {
03089 d[si] =
03090 m32c_subreg (submode, operands[0], mode,
03091 si * GET_MODE_SIZE (submode));
03092 s[si] =
03093 m32c_subreg (submode, operands[1], mode,
03094 si * GET_MODE_SIZE (submode));
03095 }
03096
03097
03098 if (GET_CODE (d[0]) == MEM && GET_CODE (XEXP (d[0], 0)) == PRE_DEC)
03099 {
03100 for (si = parts - 1; si >= 0; si--)
03101 {
03102 ops[opi++] = gen_rtx_MEM (submode,
03103 gen_rtx_PRE_DEC (Pmode,
03104 gen_rtx_REG (Pmode,
03105 SP_REGNO)));
03106 ops[opi++] = s[si];
03107 }
03108
03109 rv = 1;
03110 }
03111
03112 else if (GET_CODE (s[0]) == MEM && GET_CODE (XEXP (s[0], 0)) == POST_INC)
03113 {
03114 for (di = 0; di < parts; di++)
03115 {
03116 ops[opi++] = d[di];
03117 ops[opi++] = gen_rtx_MEM (submode,
03118 gen_rtx_POST_INC (Pmode,
03119 gen_rtx_REG (Pmode,
03120 SP_REGNO)));
03121 }
03122 rv = 1;
03123 }
03124 else if (split_all)
03125 {
03126
03127 for (di = 0; di < parts - 1; di++)
03128 for (si = di + 1; si < parts; si++)
03129 if (reg_mentioned_p (d[di], s[si]))
03130 rev = 1;
03131
03132 if (rev)
03133 for (si = 0; si < parts; si++)
03134 {
03135 ops[opi++] = d[si];
03136 ops[opi++] = s[si];
03137 }
03138 else
03139 for (si = parts - 1; si >= 0; si--)
03140 {
03141 ops[opi++] = d[si];
03142 ops[opi++] = s[si];
03143 }
03144 rv = 1;
03145 }
03146
03147 if (rv && split_all != 3)
03148 {
03149 int i;
03150 for (i = 2; i < opi; i += 2)
03151 emit_move_insn (ops[i], ops[i + 1]);
03152 }
03153 return rv;
03154 }
03155
03156
03157
03158
03159
03160
03161
03162
03163
03164
03165
03166
03167
03168 int
03169 m32c_expand_setmemhi(rtx *operands)
03170 {
03171 rtx desta, count, val;
03172 rtx desto, counto;
03173
03174 desta = XEXP (operands[0], 0);
03175 count = operands[1];
03176 val = operands[2];
03177
03178 desto = gen_reg_rtx (Pmode);
03179 counto = gen_reg_rtx (HImode);
03180
03181 if (GET_CODE (desta) != REG
03182 || REGNO (desta) < FIRST_PSEUDO_REGISTER)
03183 desta = copy_to_mode_reg (Pmode, desta);
03184
03185
03186
03187
03188
03189 if (GET_CODE (count) == CONST_INT
03190 && GET_CODE (val) == CONST_INT
03191 && ! (INTVAL (count) & 1)
03192 && (INTVAL (count) > 1)
03193 && (INTVAL (val) <= 7 && INTVAL (val) >= -8))
03194 {
03195 unsigned v = INTVAL (val) & 0xff;
03196 v = v | (v << 8);
03197 count = copy_to_mode_reg (HImode, GEN_INT (INTVAL (count) / 2));
03198 val = copy_to_mode_reg (HImode, GEN_INT (v));
03199 if (TARGET_A16)
03200 emit_insn (gen_setmemhi_whi_op (desto, counto, val, desta, count));
03201 else
03202 emit_insn (gen_setmemhi_wpsi_op (desto, counto, val, desta, count));
03203 return 1;
03204 }
03205
03206
03207 if (GET_CODE (val) != REG
03208 || REGNO (val) < FIRST_PSEUDO_REGISTER)
03209 val = copy_to_mode_reg (QImode, val);
03210
03211 if (GET_CODE (count) != REG
03212 || REGNO (count) < FIRST_PSEUDO_REGISTER)
03213 count = copy_to_mode_reg (HImode, count);
03214
03215 if (TARGET_A16)
03216 emit_insn (gen_setmemhi_bhi_op (desto, counto, val, desta, count));
03217 else
03218 emit_insn (gen_setmemhi_bpsi_op (desto, counto, val, desta, count));
03219
03220 return 1;
03221 }
03222
03223
03224
03225
03226
03227 int
03228 m32c_expand_movmemhi(rtx *operands)
03229 {
03230 rtx desta, srca, count;
03231 rtx desto, srco, counto;
03232
03233 desta = XEXP (operands[0], 0);
03234 srca = XEXP (operands[1], 0);
03235 count = operands[2];
03236
03237 desto = gen_reg_rtx (Pmode);
03238 srco = gen_reg_rtx (Pmode);
03239 counto = gen_reg_rtx (HImode);
03240
03241 if (GET_CODE (desta) != REG
03242 || REGNO (desta) < FIRST_PSEUDO_REGISTER)
03243 desta = copy_to_mode_reg (Pmode, desta);
03244
03245 if (GET_CODE (srca) != REG
03246 || REGNO (srca) < FIRST_PSEUDO_REGISTER)
03247 srca = copy_to_mode_reg (Pmode, srca);
03248
03249
03250 if (GET_CODE (count) == CONST_INT
03251 && ! (INTVAL (count) & 1)
03252 && (INTVAL (count) > 1))
03253 {
03254 count = copy_to_mode_reg (HImode, GEN_INT (INTVAL (count) / 2));
03255 if (TARGET_A16)
03256 emit_insn (gen_movmemhi_whi_op (desto, srco, counto, desta, srca, count));
03257 else
03258 emit_insn (gen_movmemhi_wpsi_op (desto, srco, counto, desta, srca, count));
03259 return 1;
03260 }
03261
03262
03263 if (GET_CODE (count) != REG
03264 || REGNO (count) < FIRST_PSEUDO_REGISTER)
03265 count = copy_to_mode_reg (HImode, count);
03266
03267 if (TARGET_A16)
03268 emit_insn (gen_movmemhi_bhi_op (desto, srco, counto, desta, srca, count));
03269 else
03270 emit_insn (gen_movmemhi_bpsi_op (desto, srco, counto, desta, srca, count));
03271
03272 return 1;
03273 }
03274
03275
03276
03277
03278
03279
03280 int
03281 m32c_expand_movstr(rtx *operands)
03282 {
03283 rtx desta, srca;
03284 rtx desto, srco;
03285
03286 desta = XEXP (operands[1], 0);
03287 srca = XEXP (operands[2], 0);
03288
03289 desto = gen_reg_rtx (Pmode);
03290 srco = gen_reg_rtx (Pmode);
03291
03292 if (GET_CODE (desta) != REG
03293 || REGNO (desta) < FIRST_PSEUDO_REGISTER)
03294 desta = copy_to_mode_reg (Pmode, desta);
03295
03296 if (GET_CODE (srca) != REG
03297 || REGNO (srca) < FIRST_PSEUDO_REGISTER)
03298 srca = copy_to_mode_reg (Pmode, srca);
03299
03300 emit_insn (gen_movstr_op (desto, srco, desta, srca));
03301
03302 emit_insn (gen_addpsi3 (operands[0], desto, GEN_INT (-1)));
03303
03304 return 1;
03305 }
03306
03307
03308
03309
03310
03311 int
03312 m32c_expand_cmpstr(rtx *operands)
03313 {
03314 rtx src1a, src2a;
03315
03316 src1a = XEXP (operands[1], 0);
03317 src2a = XEXP (operands[2], 0);
03318
03319 if (GET_CODE (src1a) != REG
03320 || REGNO (src1a) < FIRST_PSEUDO_REGISTER)
03321 src1a = copy_to_mode_reg (Pmode, src1a);
03322
03323 if (GET_CODE (src2a) != REG
03324 || REGNO (src2a) < FIRST_PSEUDO_REGISTER)
03325 src2a = copy_to_mode_reg (Pmode, src2a);
03326
03327 emit_insn (gen_cmpstrhi_op (src1a, src2a, src1a, src2a));
03328 emit_insn (gen_cond_to_int (operands[0]));
03329
03330 return 1;
03331 }
03332
03333
03334 typedef rtx (*shift_gen_func)(rtx, rtx, rtx);
03335
03336 static shift_gen_func
03337 shift_gen_func_for (int mode, int code)
03338 {
03339 #define GFF(m,c,f) if (mode == m && code == c) return f
03340 GFF(QImode, ASHIFT, gen_ashlqi3_i);
03341 GFF(QImode, ASHIFTRT, gen_ashrqi3_i);
03342 GFF(QImode, LSHIFTRT, gen_lshrqi3_i);
03343 GFF(HImode, ASHIFT, gen_ashlhi3_i);
03344 GFF(HImode, ASHIFTRT, gen_ashrhi3_i);
03345 GFF(HImode, LSHIFTRT, gen_lshrhi3_i);
03346 GFF(PSImode, ASHIFT, gen_ashlpsi3_i);
03347 GFF(PSImode, ASHIFTRT, gen_ashrpsi3_i);
03348 GFF(PSImode, LSHIFTRT, gen_lshrpsi3_i);
03349 GFF(SImode, ASHIFT, TARGET_A16 ? gen_ashlsi3_16 : gen_ashlsi3_24);
03350 GFF(SImode, ASHIFTRT, TARGET_A16 ? gen_ashrsi3_16 : gen_ashrsi3_24);
03351 GFF(SImode, LSHIFTRT, TARGET_A16 ? gen_lshrsi3_16 : gen_lshrsi3_24);
03352 #undef GFF
03353 gcc_unreachable ();
03354 }
03355
03356
03357
03358
03359
03360
03361 int
03362 m32c_prepare_shift (rtx * operands, int scale, int shift_code)
03363 {
03364 enum machine_mode mode = GET_MODE (operands[0]);
03365 shift_gen_func func = shift_gen_func_for (mode, shift_code);
03366 rtx temp;
03367
03368 if (GET_CODE (operands[2]) == CONST_INT)
03369 {
03370 int maxc = TARGET_A24 && (mode == PSImode || mode == SImode) ? 32 : 8;
03371 int count = INTVAL (operands[2]) * scale;
03372
03373 while (count > maxc)
03374 {
03375 temp = gen_reg_rtx (mode);
03376 emit_insn (func (temp, operands[1], GEN_INT (maxc)));
03377 operands[1] = temp;
03378 count -= maxc;
03379 }
03380 while (count < -maxc)
03381 {
03382 temp = gen_reg_rtx (mode);
03383 emit_insn (func (temp, operands[1], GEN_INT (-maxc)));
03384 operands[1] = temp;
03385 count += maxc;
03386 }
03387 emit_insn (func (operands[0], operands[1], GEN_INT (count)));
03388 return 1;
03389 }
03390
03391 temp = gen_reg_rtx (QImode);
03392 if (scale < 0)
03393
03394 emit_move_insn (temp, gen_rtx_NEG (QImode, operands[2]));
03395 else if (TARGET_A16 && mode == SImode)
03396
03397
03398 emit_move_insn (temp, operands[2]);
03399 else
03400
03401 temp = operands[2];
03402
03403 if (TARGET_A16 && GET_MODE_SIZE (mode) == 4)
03404 {
03405
03406
03407
03408
03409
03410
03411
03412
03413
03414
03415
03416
03417
03418
03419
03420
03421
03422
03423
03424
03425 rtx count;
03426 rtx label, lref, insn, tempvar;
03427
03428 emit_move_insn (operands[0], operands[1]);
03429
03430 count = temp;
03431 label = gen_label_rtx ();
03432 lref = gen_rtx_LABEL_REF (VOIDmode, label);
03433 LABEL_NUSES (label) ++;
03434
03435 tempvar = gen_reg_rtx (mode);
03436
03437 if (shift_code == ASHIFT)
03438 {
03439
03440 emit_jump_insn (gen_cbranchqi4 (gen_rtx_LE (VOIDmode, 0, 0),
03441 count, GEN_INT (16), label));
03442 emit_insn (func (tempvar, operands[0], GEN_INT (8)));
03443 emit_insn (func (operands[0], tempvar, GEN_INT (8)));
03444 insn = emit_insn (gen_addqi3 (count, count, GEN_INT (-16)));
03445 emit_label_after (label, insn);
03446 }
03447 else
03448 {
03449
03450 emit_jump_insn (gen_cbranchqi4 (gen_rtx_GE (VOIDmode, 0, 0),
03451 count, GEN_INT (-16), label));
03452 emit_insn (func (tempvar, operands[0], GEN_INT (-8)));
03453 emit_insn (func (operands[0], tempvar, GEN_INT (-8)));
03454 insn = emit_insn (gen_addqi3 (count, count, GEN_INT (16)));
03455 emit_label_after (label, insn);
03456 }
03457 operands[1] = operands[0];
03458 emit_insn (func (operands[0], operands[0], count));
03459 return 1;
03460 }
03461
03462 operands[2] = temp;
03463 return 0;
03464 }
03465
03466
03467
03468
03469
03470 void
03471 m32c_expand_neg_mulpsi3 (rtx * operands)
03472 {
03473
03474 rtx temp1;
03475 rtx scale ;
03476 rtx temp2;
03477
03478 temp1 = gen_reg_rtx (SImode);
03479 temp2 = gen_reg_rtx (SImode);
03480 if (GET_CODE (operands[2]) != CONST_INT)
03481 {
03482 scale = gen_reg_rtx (SImode);
03483 emit_insn (gen_zero_extendpsisi2 (scale, operands[2]));
03484 }
03485 else
03486 scale = copy_to_mode_reg (SImode, operands[2]);
03487
03488 emit_insn (gen_zero_extendpsisi2 (temp1, operands[1]));
03489 temp2 = expand_simple_binop (SImode, MULT, temp1, scale, temp2, 1, OPTAB_LIB);
03490 emit_insn (gen_truncsipsi2 (operands[0], temp2));
03491 }
03492
03493 static rtx compare_op0, compare_op1;
03494
03495 void
03496 m32c_pend_compare (rtx *operands)
03497 {
03498 compare_op0 = operands[0];
03499 compare_op1 = operands[1];
03500 }
03501
03502 void
03503 m32c_unpend_compare (void)
03504 {
03505 switch (GET_MODE (compare_op0))
03506 {
03507 case QImode:
03508 emit_insn (gen_cmpqi_op (compare_op0, compare_op1));
03509 case HImode:
03510 emit_insn (gen_cmphi_op (compare_op0, compare_op1));
03511 case PSImode:
03512 emit_insn (gen_cmppsi_op (compare_op0, compare_op1));
03513 }
03514 }
03515
03516 void
03517 m32c_expand_scc (int code, rtx *operands)
03518 {
03519 enum machine_mode mode = TARGET_A16 ? QImode : HImode;
03520
03521 emit_insn (gen_rtx_SET (mode,
03522 operands[0],
03523 gen_rtx_fmt_ee (code,
03524 mode,
03525 compare_op0,
03526 compare_op1)));
03527 }
03528
03529
03530
03531
03532
03533 rtx
03534 m32c_cmp_flg_0 (rtx cmp)
03535 {
03536 return gen_rtx_fmt_ee (GET_CODE (cmp),
03537 GET_MODE (cmp),
03538 gen_rtx_REG (CCmode, FLG_REGNO),
03539 GEN_INT (0));
03540 }
03541
03542 int
03543 m32c_expand_movcc (rtx *operands)
03544 {
03545 rtx rel = operands[1];
03546 rtx cmp;
03547
03548 if (GET_CODE (rel) != EQ && GET_CODE (rel) != NE)
03549 return 1;
03550 if (GET_CODE (operands[2]) != CONST_INT
03551 || GET_CODE (operands[3]) != CONST_INT)
03552 return 1;
03553 emit_insn (gen_cmpqi(XEXP (rel, 0), XEXP (rel, 1)));
03554 if (GET_CODE (rel) == NE)
03555 {
03556 rtx tmp = operands[2];
03557 operands[2] = operands[3];
03558 operands[3] = tmp;
03559 }
03560
03561 cmp = gen_rtx_fmt_ee (GET_CODE (rel),
03562 GET_MODE (rel),
03563 compare_op0,
03564 compare_op1);
03565
03566 emit_move_insn (operands[0],
03567 gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
03568 cmp,
03569 operands[2],
03570 operands[3]));
03571 return 0;
03572 }
03573
03574
03575 int
03576 m32c_expand_insv (rtx *operands)
03577 {
03578 rtx op0, src0, p;
03579 int mask;
03580
03581 if (INTVAL (operands[1]) != 1)
03582 return 1;
03583
03584
03585 if (GET_CODE (operands[3]) != CONST_INT)
03586 return 1;
03587 if (INTVAL (operands[3]) != 0
03588 && INTVAL (operands[3]) != 1
03589 && INTVAL (operands[3]) != -1)
03590 return 1;
03591
03592 mask = 1 << INTVAL (operands[2]);
03593
03594 op0 = operands[0];
03595 if (GET_CODE (op0) == SUBREG
03596 && SUBREG_BYTE (op0) == 0)
03597 {
03598 rtx sub = SUBREG_REG (op0);
03599 if (GET_MODE (sub) == HImode || GET_MODE (sub) == QImode)
03600 op0 = sub;
03601 }
03602
03603 if (no_new_pseudos
03604 || (GET_CODE (op0) == MEM && MEM_VOLATILE_P (op0)))
03605 src0 = op0;
03606 else
03607 {
03608 src0 = gen_reg_rtx (GET_MODE (op0));
03609 emit_move_insn (src0, op0);
03610 }
03611
03612 if (GET_MODE (op0) == HImode
03613 && INTVAL (operands[2]) >= 8
03614 && GET_MODE (op0) == MEM)
03615 {
03616
03617 rtx new_mem = gen_rtx_MEM (QImode, plus_constant (XEXP (op0, 0), 1));
03618 MEM_COPY_ATTRIBUTES (new_mem, op0);
03619 mask >>= 8;
03620 }
03621
03622
03623
03624 if (INTVAL (operands[3]) == 0)
03625 {
03626
03627 if (GET_MODE (op0) == HImode)
03628 mask ^= 0xffff;
03629 else
03630 mask ^= 0xff;
03631 }
03632
03633
03634 if (GET_MODE (op0) == HImode)
03635 {
03636 if (mask & 0x8000)
03637 mask -= 0x10000;
03638 }
03639 else
03640 {
03641 if (mask & 0x80)
03642 mask -= 0x100;
03643 }
03644
03645 switch ( (INTVAL (operands[3]) ? 4 : 0)
03646 + ((GET_MODE (op0) == HImode) ? 2 : 0)
03647 + (TARGET_A24 ? 1 : 0))
03648 {
03649 case 0: p = gen_andqi3_16 (op0, src0, GEN_INT (mask)); break;
03650 case 1: p = gen_andqi3_24 (op0, src0, GEN_INT (mask)); break;
03651 case 2: p = gen_andhi3_16 (op0, src0, GEN_INT (mask)); break;
03652 case 3: p = gen_andhi3_24 (op0, src0, GEN_INT (mask)); break;
03653 case 4: p = gen_iorqi3_16 (op0, src0, GEN_INT (mask)); break;
03654 case 5: p = gen_iorqi3_24 (op0, src0, GEN_INT (mask)); break;
03655 case 6: p = gen_iorhi3_16 (op0, src0, GEN_INT (mask)); break;
03656 case 7: p = gen_iorhi3_24 (op0, src0, GEN_INT (mask)); break;
03657 }
03658
03659 emit_insn (p);
03660 return 0;
03661 }
03662
03663 const char *
03664 m32c_scc_pattern(rtx *operands, RTX_CODE code)
03665 {
03666 static char buf[30];
03667 if (GET_CODE (operands[0]) == REG
03668 && REGNO (operands[0]) == R0_REGNO)
03669 {
03670 if (code == EQ)
03671 return "stzx\t#1,#0,r0l";
03672 if (code == NE)
03673 return "stzx\t#0,#1,r0l";
03674 }
03675 sprintf(buf, "bm%s\t0,%%h0\n\tand.b\t#1,%%0", GET_RTX_NAME (code));
03676 return buf;
03677 }
03678
03679
03680
03681
03682
03683
03684 static int
03685 m32c_leaf_function_p (void)
03686 {
03687 rtx saved_first, saved_last;
03688 struct sequence_stack *seq;
03689 int rv;
03690
03691 saved_first = cfun->emit->x_first_insn;
03692 saved_last = cfun->emit->x_last_insn;
03693 for (seq = cfun->emit->sequence_stack; seq && seq->next; seq = seq->next)
03694 ;
03695 if (seq)
03696 {
03697 cfun->emit->x_first_insn = seq->first;
03698 cfun->emit->x_last_insn = seq->last;
03699 }
03700
03701 rv = leaf_function_p ();
03702
03703 cfun->emit->x_first_insn = saved_first;
03704 cfun->emit->x_last_insn = saved_last;
03705 return rv;
03706 }
03707
03708
03709
03710
03711 static bool
03712 m32c_function_needs_enter (void)
03713 {
03714 rtx insn;
03715 struct sequence_stack *seq;
03716 rtx sp = gen_rtx_REG (Pmode, SP_REGNO);
03717 rtx fb = gen_rtx_REG (Pmode, FB_REGNO);
03718
03719 insn = get_insns ();
03720 for (seq = cfun->emit->sequence_stack;
03721 seq;
03722 insn = seq->first, seq = seq->next);
03723
03724 while (insn)
03725 {
03726 if (reg_mentioned_p (sp, insn))
03727 return true;
03728 if (reg_mentioned_p (fb, insn))
03729 return true;
03730 insn = NEXT_INSN (insn);
03731 }
03732 return false;
03733 }
03734
03735
03736
03737
03738
03739
03740
03741
03742 static rtx
03743 m32c_all_frame_related (rtx par)
03744 {
03745 int len = XVECLEN (par, 0);
03746 int i;
03747
03748 for (i = 0; i < len; i++)
03749 F (XVECEXP (par, 0, i));
03750
03751 return par;
03752 }
03753
03754
03755
03756
03757 void
03758 m32c_emit_prologue (void)
03759 {
03760 int frame_size, extra_frame_size = 0, reg_save_size;
03761 int complex_prologue = 0;
03762
03763 cfun->machine->is_leaf = m32c_leaf_function_p ();
03764 if (interrupt_p (cfun->decl))
03765 {
03766 cfun->machine->is_interrupt = 1;
03767 complex_prologue = 1;
03768 }
03769
03770 reg_save_size = m32c_pushm_popm (PP_justcount);
03771
03772 if (interrupt_p (cfun->decl))
03773 emit_insn (gen_pushm (GEN_INT (cfun->machine->intr_pushm)));
03774
03775 frame_size =
03776 m32c_initial_elimination_offset (FB_REGNO, SP_REGNO) - reg_save_size;
03777 if (frame_size == 0
03778 && !cfun->machine->is_interrupt
03779 && !m32c_function_needs_enter ())
03780 cfun->machine->use_rts = 1;
03781
03782 if (frame_size > 254)
03783 {
03784 extra_frame_size = frame_size - 254;
03785 frame_size = 254;
03786 }
03787 if (cfun->machine->use_rts == 0)
03788 F (emit_insn (m32c_all_frame_related
03789 (TARGET_A16
03790 ? gen_prologue_enter_16 (GEN_INT (frame_size))
03791 : gen_prologue_enter_24 (GEN_INT (frame_size)))));
03792
03793 if (extra_frame_size)
03794 {
03795 complex_prologue = 1;
03796 if (TARGET_A16)
03797 F (emit_insn (gen_addhi3 (gen_rtx_REG (HImode, SP_REGNO),
03798 gen_rtx_REG (HImode, SP_REGNO),
03799 GEN_INT (-extra_frame_size))));
03800 else
03801 F (emit_insn (gen_addpsi3 (gen_rtx_REG (PSImode, SP_REGNO),
03802 gen_rtx_REG (PSImode, SP_REGNO),
03803 GEN_INT (-extra_frame_size))));
03804 }
03805
03806 complex_prologue += m32c_pushm_popm (PP_pushm);
03807
03808
03809 if (complex_prologue)
03810 emit_insn (gen_prologue_end ());
03811 }
03812
03813
03814
03815
03816 void
03817 m32c_emit_epilogue (void)
03818 {
03819
03820 if (m32c_pushm_popm (PP_justcount) > 0 || cfun->machine->is_interrupt)
03821 emit_insn (gen_epilogue_start ());
03822
03823 m32c_pushm_popm (PP_popm);
03824
03825 if (cfun->machine->is_interrupt)
03826 {
03827 enum machine_mode spmode = TARGET_A16 ? HImode : PSImode;
03828
03829 emit_move_insn (gen_rtx_REG (spmode, A0_REGNO),
03830 gen_rtx_REG (spmode, FP_REGNO));
03831 emit_move_insn (gen_rtx_REG (spmode, SP_REGNO),
03832 gen_rtx_REG (spmode, A0_REGNO));
03833 if (TARGET_A16)
03834 emit_insn (gen_pophi_16 (gen_rtx_REG (HImode, FP_REGNO)));
03835 else
03836 emit_insn (gen_poppsi (gen_rtx_REG (PSImode, FP_REGNO)));
03837 emit_insn (gen_popm (GEN_INT (cfun->machine->intr_pushm)));
03838 emit_jump_insn (gen_epilogue_reit (GEN_INT (TARGET_A16 ? 4 : 6)));
03839 }
03840 else if (cfun->machine->use_rts)
03841 emit_jump_insn (gen_epilogue_rts ());
03842 else
03843 emit_jump_insn (gen_epilogue_exitd (GEN_INT (TARGET_A16 ? 2 : 4)));
03844 emit_barrier ();
03845 }
03846
03847 void
03848 m32c_emit_eh_epilogue (rtx ret_addr)
03849 {
03850
03851
03852
03853
03854 emit_jump_insn (gen_eh_epilogue (ret_addr, cfun->machine->eh_stack_adjust));
03855
03856 emit_barrier ();
03857 }
03858
03859
03860 static int
03861 flags_needed_for_conditional (rtx cond)
03862 {
03863 switch (GET_CODE (cond))
03864 {
03865 case LE:
03866 case GT:
03867 return FLAGS_OSZ;
03868 case LEU:
03869 case GTU:
03870 return FLAGS_ZC;
03871 case LT:
03872 case GE:
03873 return FLAGS_OS;
03874 case LTU:
03875 case GEU:
03876 return FLAGS_C;
03877 case EQ:
03878 case NE:
03879 return FLAGS_Z;
03880 default:
03881 return FLAGS_N;
03882 }
03883 }
03884
03885 #define DEBUG_CMP 0
03886
03887
03888
03889 static bool
03890 m32c_compare_redundant (rtx cmp, rtx *operands)
03891 {
03892 int flags_needed;
03893 int pflags;
03894 rtx prev, pp, next;
03895 rtx op0, op1, op2;
03896 #if DEBUG_CMP
03897 int prev_icode, i;
03898 #endif
03899
03900 op0 = operands[0];
03901 op1 = operands[1];
03902 op2 = operands[2];
03903
03904 #if DEBUG_CMP
03905 fprintf(stderr, "\n\033[32mm32c_compare_redundant\033[0m\n");
03906 debug_rtx(cmp);
03907 for (i=0; i<2; i++)
03908 {
03909 fprintf(stderr, "operands[%d] = ", i);
03910 debug_rtx(operands[i]);
03911 }
03912 #endif
03913
03914 next = next_nonnote_insn (cmp);
03915 if (!next || !INSN_P (next))
03916 {
03917 #if DEBUG_CMP
03918 fprintf(stderr, "compare not followed by insn\n");
03919 debug_rtx(next);
03920 #endif
03921 return false;
03922 }
03923 if (GET_CODE (PATTERN (next)) == SET
03924 && GET_CODE (XEXP ( PATTERN (next), 1)) == IF_THEN_ELSE)
03925 {
03926 next = XEXP (XEXP (PATTERN (next), 1), 0);
03927 }
03928 else if (GET_CODE (PATTERN (next)) == SET)
03929 {
03930
03931
03932 next = XEXP (PATTERN (next), 1);
03933 }
03934 else
03935 {
03936 #if DEBUG_CMP
03937 fprintf(stderr, "compare not followed by conditional\n");
03938 debug_rtx(next);
03939 #endif
03940 return false;
03941 }
03942 #if DEBUG_CMP
03943 fprintf(stderr, "conditional is: ");
03944 debug_rtx(next);
03945 #endif
03946
03947 flags_needed = flags_needed_for_conditional (next);
03948 if (flags_needed == FLAGS_N)
03949 {
03950 #if DEBUG_CMP
03951 fprintf(stderr, "compare not followed by conditional\n");
03952 debug_rtx(next);
03953 #endif
03954 return false;
03955 }
03956
03957
03958
03959 if (flags_needed & FLAGS_OC)
03960 return false;
03961
03962 prev = cmp;
03963 do {
03964 prev = prev_nonnote_insn (prev);
03965 if (!prev)
03966 {
03967 #if DEBUG_CMP
03968 fprintf(stderr, "No previous insn.\n");
03969 #endif
03970 return false;
03971 }
03972 if (!INSN_P (prev))
03973 {
03974 #if DEBUG_CMP
03975 fprintf(stderr, "Previous insn is a non-insn.\n");
03976 #endif
03977 return false;
03978 }
03979 pp = PATTERN (prev);
03980 if (GET_CODE (pp) != SET)
03981 {
03982 #if DEBUG_CMP
03983 fprintf(stderr, "Previous insn is not a SET.\n");
03984 #endif
03985 return false;
03986 }
03987 pflags = get_attr_flags (prev);
03988
03989
03990
03991 INSN_UID (cmp) = -1;
03992 recog (PATTERN (cmp), cmp, 0);
03993
03994 if (pflags == FLAGS_N
03995 && reg_mentioned_p (op0, pp))
03996 {
03997 #if DEBUG_CMP
03998 fprintf(stderr, "intermediate non-flags insn uses op:\n");
03999 debug_rtx(prev);
04000 #endif
04001 return false;
04002 }
04003 } while (pflags == FLAGS_N);
04004 #if DEBUG_CMP
04005 fprintf(stderr, "previous flag-setting insn:\n");
04006 debug_rtx(prev);
04007 debug_rtx(pp);
04008 #endif
04009
04010 if (GET_CODE (pp) == SET
04011 && GET_CODE (XEXP (pp, 0)) == REG
04012 && REGNO (XEXP (pp, 0)) == FLG_REGNO
04013 && GET_CODE (XEXP (pp, 1)) == COMPARE)
04014 {
04015
04016
04017 rtx pop0 = XEXP (XEXP (pp, 1), 0);
04018 rtx pop1 = XEXP (XEXP (pp, 1), 1);
04019 #if DEBUG_CMP
04020 fprintf(stderr, "adjacent cbranches\n");
04021 debug_rtx(pop0);
04022 debug_rtx(pop1);
04023 #endif
04024 if (rtx_equal_p (op0, pop0)
04025 && rtx_equal_p (op1, pop1))
04026 return true;
04027 #if DEBUG_CMP
04028 fprintf(stderr, "prev cmp not same\n");
04029 #endif
04030 return false;
04031 }
04032
04033
04034
04035
04036 if (!rtx_equal_p (op1, const0_rtx))
04037 {
04038 #if DEBUG_CMP
04039 fprintf(stderr, "operands[1] not const0_rtx\n");
04040 #endif
04041 return false;
04042 }
04043 if (GET_CODE (pp) != SET)
04044 {
04045 #if DEBUG_CMP
04046 fprintf (stderr, "pp not set\n");
04047 #endif
04048 return false;
04049 }
04050 if (!rtx_equal_p (op0, SET_SRC (pp))
04051 && !rtx_equal_p (op0, SET_DEST (pp)))
04052 {
04053 #if DEBUG_CMP
04054 fprintf(stderr, "operands[0] not found in set\n");
04055 #endif
04056 return false;
04057 }
04058
04059 #if DEBUG_CMP
04060 fprintf(stderr, "cmp flags %x prev flags %x\n", flags_needed, pflags);
04061 #endif
04062 if ((pflags & flags_needed) == flags_needed)
04063 return true;
04064
04065 return false;
04066 }
04067
04068
04069
04070
04071 char *
04072 m32c_output_compare (rtx insn, rtx *operands)
04073 {
04074 static char template[] = ";cmp.b\t%1,%0";
04075
04076
04077 template[5] = " bwll"[GET_MODE_SIZE(GET_MODE(operands[0]))];
04078 if (m32c_compare_redundant (insn, operands))
04079 {
04080 #if DEBUG_CMP
04081 fprintf(stderr, "cbranch: cmp not needed\n");
04082 #endif
04083 return template;
04084 }
04085
04086 #if DEBUG_CMP
04087 fprintf(stderr, "cbranch: cmp needed: `%s'\n", template);
04088 #endif
04089 return template + 1;
04090 }
04091
04092
04093
04094 struct gcc_target targetm = TARGET_INITIALIZER;
04095
04096 #include "gt-m32c.h"