00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "config.h"
00025 #include "system.h"
00026 #include "rtl.h"
00027 #include "tree.h"
00028 #include "regs.h"
00029 #include "hard-reg-set.h"
00030 #include "real.h"
00031 #include "insn-config.h"
00032 #include "conditions.h"
00033 #include "output.h"
00034 #include "insn-attr.h"
00035 #include "flags.h"
00036 #include "recog.h"
00037 #include "function.h"
00038 #include "expr.h"
00039 #include "obstack.h"
00040 #include "reload.h"
00041 #include "tm_p.h"
00042 #include "target.h"
00043 #include "target-def.h"
00044
00045 static int shift_constant_operand PARAMS ((rtx, enum machine_mode, int));
00046 static void a29k_set_memflags_1 PARAMS ((rtx, int, int, int, int));
00047 static void compute_regstack_size PARAMS ((void));
00048 static void check_epilogue_internal_label PARAMS ((FILE *));
00049 static void output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
00050 static void output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
00051 static void a29k_asm_named_section PARAMS ((const char *, unsigned int));
00052 static int a29k_adjust_cost PARAMS ((rtx, rtx, rtx, int));
00053
00054 #define min(A,B) ((A) < (B) ? (A) : (B))
00055
00056
00057
00058
00059 static int a29k_regstack_size;
00060
00061
00062
00063 static int a29k_makes_calls;
00064
00065
00066
00067
00068
00069 static char *a29k_last_prologue_insn;
00070
00071
00072
00073
00074 static char *a29k_first_epilogue_insn;
00075
00076
00077
00078
00079 static int a29k_first_epilogue_insn_used;
00080
00081
00082
00083
00084
00085 const char *a29k_function_name;
00086
00087
00088
00089
00090
00091 int a29k_debug_reg_map[FIRST_PSEUDO_REGISTER];
00092
00093
00094
00095
00096 rtx a29k_compare_op0, a29k_compare_op1;
00097 int a29k_compare_fp_p;
00098
00099
00100 #undef TARGET_ASM_ALIGNED_HI_OP
00101 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
00102 #undef TARGET_ASM_ALIGNED_SI_OP
00103 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
00104
00105 #undef TARGET_ASM_FUNCTION_PROLOGUE
00106 #define TARGET_ASM_FUNCTION_PROLOGUE output_function_prologue
00107 #undef TARGET_ASM_FUNCTION_EPILOGUE
00108 #define TARGET_ASM_FUNCTION_EPILOGUE output_function_epilogue
00109 #undef TARGET_SCHED_ADJUST_COST
00110 #define TARGET_SCHED_ADJUST_COST a29k_adjust_cost
00111
00112 struct gcc_target targetm = TARGET_INITIALIZER;
00113
00114
00115
00116 int
00117 cint_8_operand (op, mode)
00118 register rtx op;
00119 enum machine_mode mode ATTRIBUTE_UNUSED;
00120 {
00121 return GET_CODE (op) == CONST_INT && (INTVAL (op) & 0xffffff00) == 0;
00122 }
00123
00124
00125
00126 int
00127 cint_16_operand (op, mode)
00128 rtx op;
00129 enum machine_mode mode ATTRIBUTE_UNUSED;
00130 {
00131 return GET_CODE (op) == CONST_INT && (INTVAL (op) & 0xffff0000) == 0;
00132 }
00133
00134
00135
00136 int
00137 long_const_operand (op, mode)
00138 register rtx op;
00139 enum machine_mode mode ATTRIBUTE_UNUSED;
00140 {
00141 if (! CONSTANT_P (op))
00142 return 0;
00143
00144 if (TARGET_29050 && GET_CODE (op) == CONST_INT
00145 && (INTVAL (op) & 0xffff) == 0)
00146 return 0;
00147
00148 return (GET_CODE (op) != CONST_INT
00149 || ((INTVAL (op) & 0xffff0000) != 0
00150 && (INTVAL (op) & 0xffff0000) != 0xffff0000
00151 && INTVAL (op) != 0x80000000));
00152 }
00153
00154
00155
00156
00157
00158 static int
00159 shift_constant_operand (op, mode, val)
00160 rtx op;
00161 enum machine_mode mode ATTRIBUTE_UNUSED;
00162 int val;
00163 {
00164 return ((GET_CODE (op) == CONST_INT && INTVAL (op) == val)
00165 || (GET_CODE (op) == ASHIFT
00166 && GET_CODE (XEXP (op, 0)) == CONST_INT
00167 && INTVAL (XEXP (op, 0)) == val / 8
00168 && GET_CODE (XEXP (op, 1)) == CONST_INT
00169 && INTVAL (XEXP (op, 1)) == 3));
00170 }
00171
00172 int
00173 const_0_operand (op, mode)
00174 rtx op;
00175 enum machine_mode mode;
00176 {
00177 return shift_constant_operand (op, mode, 0);
00178 }
00179
00180 int
00181 const_8_operand (op, mode)
00182 rtx op;
00183 enum machine_mode mode;
00184 {
00185 return shift_constant_operand (op, mode, 8);
00186 }
00187
00188 int
00189 const_16_operand (op, mode)
00190 rtx op;
00191 enum machine_mode mode;
00192 {
00193 return shift_constant_operand (op, mode, 16);
00194 }
00195
00196 int
00197 const_24_operand (op, mode)
00198 rtx op;
00199 enum machine_mode mode;
00200 {
00201 return shift_constant_operand (op, mode, 24);
00202 }
00203
00204
00205
00206 int
00207 float_const_operand (op, mode)
00208 rtx op;
00209 enum machine_mode mode;
00210 {
00211 return GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == mode;
00212 }
00213
00214
00215
00216
00217 int
00218 gpc_reg_or_float_constant_operand (op, mode)
00219 rtx op;
00220 enum machine_mode mode;
00221 {
00222 return float_const_operand (op, mode) || gpc_reg_operand (op, mode);
00223 }
00224
00225
00226
00227
00228 int
00229 gpc_reg_or_integer_constant_operand (op, mode)
00230 rtx op;
00231 enum machine_mode mode;
00232 {
00233 return ((GET_MODE (op) == VOIDmode
00234 && (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE))
00235 || gpc_reg_operand (op, mode));
00236 }
00237
00238
00239
00240 int
00241 spec_reg_operand (op, mode)
00242 rtx op;
00243 enum machine_mode mode;
00244 {
00245 if (GET_CODE (op) != REG || GET_MODE (op) != mode)
00246 return 0;
00247
00248 switch (GET_MODE_CLASS (mode))
00249 {
00250 case MODE_PARTIAL_INT:
00251 return REGNO (op) >= R_BP && REGNO (op) <= R_CR;
00252 case MODE_INT:
00253 return REGNO (op) >= R_Q && REGNO (op) <= R_EXO;
00254 default:
00255 return 0;
00256 }
00257 }
00258
00259
00260
00261 int
00262 accum_reg_operand (op, mode)
00263 rtx op;
00264 enum machine_mode mode ATTRIBUTE_UNUSED;
00265 {
00266 return (GET_CODE (op) == REG
00267 && REGNO (op) >= R_ACU (0) && REGNO (op) <= R_ACU (3));
00268 }
00269
00270
00271
00272 int
00273 gpc_reg_operand (op, mode)
00274 rtx op;
00275 enum machine_mode mode;
00276 {
00277 int regno;
00278
00279 if (GET_MODE (op) != mode && mode != VOIDmode)
00280 return 0;
00281
00282 if (GET_CODE (op) == REG)
00283 regno = REGNO (op);
00284 else if (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG)
00285 {
00286 if (REGNO (SUBREG_REG (op)) < FIRST_PSEUDO_REGISTER)
00287 regno = subreg_regno (op);
00288 else
00289 regno = REGNO (SUBREG_REG (op));
00290 }
00291 else
00292 return 0;
00293
00294 return (regno >= FIRST_PSEUDO_REGISTER || regno < R_BP
00295 || (regno >= R_KR (0) && regno <= R_KR (31)));
00296 }
00297
00298
00299
00300
00301 int
00302 srcb_operand (op, mode)
00303 register rtx op;
00304 enum machine_mode mode;
00305 {
00306 if (GET_CODE (op) == CONST_INT
00307 && (mode == QImode
00308 || (INTVAL (op) & 0xffffff00) == 0))
00309 return 1;
00310
00311 if (GET_MODE (op) != mode && mode != VOIDmode)
00312 return 0;
00313
00314 return gpc_reg_operand (op, mode);
00315 }
00316
00317 int
00318 cmplsrcb_operand (op, mode)
00319 register rtx op;
00320 enum machine_mode mode;
00321 {
00322 if (GET_CODE (op) == CONST_INT
00323 && (mode == QImode
00324 || (INTVAL (op) & 0xffffff00) == 0xffffff00))
00325 return 1;
00326
00327 if (GET_MODE (op) != mode && mode != VOIDmode)
00328 return 0;
00329
00330 return gpc_reg_operand (op, mode);
00331 }
00332
00333
00334
00335
00336 int
00337 gpc_reg_or_immediate_operand (op, mode)
00338 rtx op;
00339 enum machine_mode mode;
00340 {
00341 return gpc_reg_operand (op, mode) || immediate_operand (op, mode);
00342 }
00343
00344
00345
00346
00347 int
00348 and_operand (op, mode)
00349 rtx op;
00350 enum machine_mode mode;
00351 {
00352 return (srcb_operand (op, mode)
00353 || (GET_CODE (op) == CONST_INT
00354 && ((unsigned) ((~ INTVAL (op)) & GET_MODE_MASK (mode)) < 256)));
00355 }
00356
00357
00358
00359
00360
00361 int
00362 add_operand (op, mode)
00363 rtx op;
00364 enum machine_mode mode;
00365 {
00366 return (srcb_operand (op, mode)
00367 || (GET_CODE (op) == CONST_INT
00368 && ((unsigned) ((- INTVAL (op)) & GET_MODE_MASK (mode)) < 256)));
00369 }
00370
00371
00372
00373
00374
00375 int
00376 call_operand (op, mode)
00377 rtx op;
00378 enum machine_mode mode ATTRIBUTE_UNUSED;
00379 {
00380 switch (GET_CODE (op))
00381 {
00382 case SYMBOL_REF:
00383 return (TARGET_SMALL_MEMORY
00384 || (! TARGET_LARGE_MEMORY
00385 && ((GET_CODE (op) == SYMBOL_REF && SYMBOL_REF_FLAG (op))
00386 || ! strcmp (XSTR (op, 0), current_function_name))));
00387
00388 case CONST_INT:
00389 return (unsigned HOST_WIDE_INT) INTVAL (op) < 0x40000;
00390
00391 default:
00392 return 0;
00393 }
00394 }
00395
00396
00397
00398 int
00399 in_operand (op, mode)
00400 rtx op;
00401 enum machine_mode mode;
00402 {
00403 if (! general_operand (op, mode))
00404 return 0;
00405
00406 while (GET_CODE (op) == SUBREG)
00407 op = SUBREG_REG (op);
00408
00409 switch (GET_CODE (op))
00410 {
00411 case REG:
00412 return 1;
00413
00414 case MEM:
00415 return (GET_MODE_SIZE (mode) >= UNITS_PER_WORD || TARGET_DW_ENABLE);
00416
00417 case CONST_INT:
00418 if (GET_MODE_CLASS (mode) != MODE_INT
00419 && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
00420 return 0;
00421
00422 return 1;
00423
00424 case CONST:
00425 case SYMBOL_REF:
00426 case LABEL_REF:
00427 return (GET_MODE (op) == mode
00428 || mode == SImode || mode == HImode || mode == QImode);
00429
00430 case CONST_DOUBLE:
00431 return ((GET_MODE_CLASS (mode) == MODE_FLOAT
00432 && mode == GET_MODE (op))
00433 || (GET_MODE (op) == VOIDmode
00434 && GET_MODE_CLASS (mode) == MODE_INT));
00435
00436 default:
00437 return 0;
00438 }
00439 }
00440
00441
00442
00443 int
00444 out_operand (op, mode)
00445 rtx op;
00446 enum machine_mode mode;
00447 {
00448 rtx orig_op = op;
00449
00450 if (! general_operand (op, mode))
00451 return 0;
00452
00453 while (GET_CODE (op) == SUBREG)
00454 op = SUBREG_REG (op);
00455
00456 if (GET_CODE (op) == REG)
00457 return (gpc_reg_operand (orig_op, mode)
00458 || spec_reg_operand (orig_op, mode)
00459 || (GET_MODE_CLASS (mode) == MODE_FLOAT
00460 && accum_reg_operand (orig_op, mode)));
00461
00462 else if (GET_CODE (op) == MEM)
00463 return (GET_MODE_SIZE (mode) >= UNITS_PER_WORD || TARGET_DW_ENABLE);
00464 else
00465 return 0;
00466 }
00467
00468
00469
00470 int
00471 reload_memory_operand (op, mode)
00472 rtx op;
00473 enum machine_mode mode ATTRIBUTE_UNUSED;
00474 {
00475 int regno = true_regnum (op);
00476
00477 return (! CONSTANT_P (op)
00478 && (regno == -1
00479 || (GET_CODE (op) == REG
00480 && REGNO (op) >= FIRST_PSEUDO_REGISTER)));
00481 }
00482
00483
00484
00485
00486 rtx
00487 a29k_get_reloaded_address (op)
00488 rtx op;
00489 {
00490 if (GET_CODE (op) == SUBREG)
00491 {
00492 if (SUBREG_BYTE (op) != 0)
00493 abort ();
00494
00495 op = SUBREG_REG (op);
00496 }
00497
00498 if (GET_CODE (op) == REG)
00499 op = reg_equiv_mem[REGNO (op)];
00500
00501 return find_replacement (&XEXP (op, 0));
00502 }
00503
00504
00505
00506
00507 static void
00508 a29k_set_memflags_1 (x, in_struct_p, scalar_p, volatile_p, unchanging_p)
00509 rtx x;
00510 int in_struct_p, scalar_p, volatile_p, unchanging_p;
00511 {
00512 int i;
00513
00514 switch (GET_CODE (x))
00515 {
00516 case SEQUENCE:
00517 case PARALLEL:
00518 for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
00519 a29k_set_memflags_1 (XVECEXP (x, 0, i), in_struct_p, scalar_p,
00520 volatile_p, unchanging_p);
00521 break;
00522
00523 case INSN:
00524 a29k_set_memflags_1 (PATTERN (x), in_struct_p, scalar_p, volatile_p,
00525 unchanging_p);
00526 break;
00527
00528 case SET:
00529 a29k_set_memflags_1 (SET_DEST (x), in_struct_p, scalar_p, volatile_p,
00530 unchanging_p);
00531 a29k_set_memflags_1 (SET_SRC (x), in_struct_p, scalar_p, volatile_p,
00532 unchanging_p);
00533 break;
00534
00535 case MEM:
00536 MEM_IN_STRUCT_P (x) = in_struct_p;
00537 MEM_SCALAR_P (x) = scalar_p;
00538 MEM_VOLATILE_P (x) = volatile_p;
00539 RTX_UNCHANGING_P (x) = unchanging_p;
00540 break;
00541
00542 default:
00543 break;
00544 }
00545 }
00546
00547
00548
00549
00550
00551
00552
00553 void
00554 a29k_set_memflags (insn, ref)
00555 rtx insn;
00556 rtx ref;
00557 {
00558
00559
00560 int in_struct_p = MEM_IN_STRUCT_P (ref);
00561 int scalar_p = MEM_SCALAR_P (ref);
00562 int volatile_p = MEM_VOLATILE_P (ref);
00563 int unchanging_p = RTX_UNCHANGING_P (ref);
00564
00565 if (GET_CODE (ref) != MEM
00566 || (! in_struct_p && ! volatile_p && ! unchanging_p))
00567 return;
00568
00569 a29k_set_memflags_1 (insn, in_struct_p, scalar_p, volatile_p, unchanging_p);
00570 }
00571
00572
00573
00574 int
00575 fp_comparison_operator (op, mode)
00576 rtx op;
00577 enum machine_mode mode;
00578 {
00579 return ((mode == VOIDmode || mode == GET_MODE (op))
00580 && (GET_CODE (op) == EQ || GET_CODE (op) == GT ||
00581 GET_CODE (op) == GE));
00582 }
00583
00584
00585
00586 int
00587 branch_operator (op, mode)
00588 rtx op;
00589 enum machine_mode mode;
00590 {
00591 return ((mode == VOIDmode || mode == GET_MODE (op))
00592 && (GET_CODE (op) == GE || GET_CODE (op) == LT));
00593 }
00594
00595
00596
00597
00598 int
00599 load_multiple_operation (op, mode)
00600 rtx op;
00601 enum machine_mode mode ATTRIBUTE_UNUSED;
00602 {
00603 int count = XVECLEN (op, 0) - 2;
00604 int dest_regno;
00605 rtx src_addr;
00606 int i;
00607
00608
00609 if (count <= 1
00610 || GET_CODE (XVECEXP (op, 0, 0)) != SET
00611 || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG
00612 || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != MEM)
00613 return 0;
00614
00615 dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));
00616 src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0);
00617
00618 for (i = 1; i < count; i++)
00619 {
00620 rtx elt = XVECEXP (op, 0, i + 2);
00621
00622 if (GET_CODE (elt) != SET
00623 || GET_CODE (SET_DEST (elt)) != REG
00624 || GET_MODE (SET_DEST (elt)) != SImode
00625 || REGNO (SET_DEST (elt)) != dest_regno + i
00626 || GET_CODE (SET_SRC (elt)) != MEM
00627 || GET_MODE (SET_SRC (elt)) != SImode
00628 || GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS
00629 || ! rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr)
00630 || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT
00631 || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) != i * 4)
00632 return 0;
00633 }
00634
00635 return 1;
00636 }
00637
00638
00639
00640 int
00641 store_multiple_operation (op, mode)
00642 rtx op;
00643 enum machine_mode mode ATTRIBUTE_UNUSED;
00644 {
00645 int num_special = TARGET_NO_STOREM_BUG ? 2 : 1;
00646 int count = XVECLEN (op, 0) - num_special;
00647 int src_regno;
00648 rtx dest_addr;
00649 int i;
00650
00651
00652 if (count <= 1
00653 || GET_CODE (XVECEXP (op, 0, 0)) != SET
00654 || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != MEM
00655 || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != REG)
00656 return 0;
00657
00658 src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0)));
00659 dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0);
00660
00661 for (i = 1; i < count; i++)
00662 {
00663 rtx elt = XVECEXP (op, 0, i + num_special);
00664
00665 if (GET_CODE (elt) != SET
00666 || GET_CODE (SET_SRC (elt)) != REG
00667 || GET_MODE (SET_SRC (elt)) != SImode
00668 || REGNO (SET_SRC (elt)) != src_regno + i
00669 || GET_CODE (SET_DEST (elt)) != MEM
00670 || GET_MODE (SET_DEST (elt)) != SImode
00671 || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS
00672 || ! rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr)
00673 || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT
00674 || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != i * 4)
00675 return 0;
00676 }
00677
00678 return 1;
00679 }
00680
00681
00682
00683
00684
00685 int
00686 masks_bits_for_special (reg, mask)
00687 rtx reg;
00688 rtx mask;
00689 {
00690 int needed_mask_value;
00691
00692 if (GET_CODE (reg) != REG || GET_CODE (mask) != CONST_INT)
00693 abort ();
00694
00695 switch (REGNO (reg))
00696 {
00697 case R_BP:
00698 case R_INT:
00699 needed_mask_value = 3;
00700 break;
00701
00702 case R_FC:
00703 needed_mask_value = 31;
00704 break;
00705
00706 case R_CR:
00707 case R_LRU:
00708 needed_mask_value = 255;
00709 break;
00710
00711 case R_FPE:
00712 needed_mask_value = 511;
00713 break;
00714
00715 case R_MMU:
00716 needed_mask_value = 0x3ff;
00717 break;
00718
00719 case R_OPS:
00720 case R_CPS:
00721 case R_RBP:
00722 case R_FPS:
00723 needed_mask_value = 0xffff;
00724 break;
00725
00726 case R_VAB:
00727 needed_mask_value = 0xffff0000;
00728 break;
00729
00730 case R_Q:
00731 case R_CFG:
00732 case R_CHA:
00733 case R_CHD:
00734 case R_CHC:
00735 case R_TMC:
00736 case R_TMR:
00737 case R_PC0:
00738 case R_PC1:
00739 case R_PC2:
00740 return 0;
00741
00742 default:
00743 abort ();
00744 }
00745
00746 return (INTVAL (mask) & ~ needed_mask_value) == 0;
00747 }
00748
00749
00750
00751
00752 int
00753 epilogue_operand (op, mode)
00754 rtx op;
00755 enum machine_mode mode ATTRIBUTE_UNUSED;
00756 {
00757 return next_active_insn (op) == 0 && a29k_first_epilogue_insn != 0;
00758 }
00759
00760
00761
00762
00763
00764 enum reg_class
00765 secondary_reload_class (class, mode, in)
00766 enum reg_class class;
00767 enum machine_mode mode;
00768 rtx in;
00769 {
00770 int regno = -1;
00771 enum rtx_code code = GET_CODE (in);
00772
00773 if (! CONSTANT_P (in))
00774 {
00775 regno = true_regnum (in);
00776
00777
00778 if (regno == -1 || regno >= FIRST_PSEUDO_REGISTER)
00779 code = MEM;
00780 }
00781
00782
00783
00784
00785 if (code == MEM && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
00786 return CR_REGS;
00787
00788
00789
00790
00791 if (code == MEM && ! TARGET_DW_ENABLE
00792 && GET_MODE_SIZE (mode) < UNITS_PER_WORD)
00793 return BP_REGS;
00794
00795
00796
00797 if (class == GENERAL_REGS
00798 || (regno != -1
00799 && (regno < R_BP
00800 || (regno >= R_KR (0) && regno <= R_KR (31)))))
00801 return NO_REGS;
00802
00803
00804 if (code == CONST_INT
00805 && (GET_MODE_BITSIZE (mode) <= 16 || (unsigned) INTVAL (in) <= 65535)
00806 && (class == BP_REGS || class == Q_REGS || class == SPECIAL_REGS))
00807 return NO_REGS;
00808
00809
00810 return GENERAL_REGS;
00811 }
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823 int
00824 incoming_reg (start, count)
00825 int start;
00826 int count;
00827 {
00828 int i;
00829
00830
00831
00832 if (start + count > 16)
00833 count = 16 - start;
00834
00835 if (! TARGET_NO_REUSE_ARGS)
00836
00837 for (i = R_AR (start); i < R_AR (start + count); i++)
00838 {
00839 fixed_regs[i] = call_used_regs[i] = call_fixed_regs[i] = 0;
00840 CLEAR_HARD_REG_BIT (fixed_reg_set, i);
00841 CLEAR_HARD_REG_BIT (call_used_reg_set, i);
00842 CLEAR_HARD_REG_BIT (call_fixed_reg_set, i);
00843 }
00844
00845
00846
00847
00848
00849
00850
00851 for (i = (R_AR (0) - 2 - start - count) & ~1; i < R_AR (0) - 2 - start; i++)
00852 {
00853 fixed_regs[i] = call_used_regs[i] = call_fixed_regs[i] = 1;
00854 SET_HARD_REG_BIT (fixed_reg_set, i);
00855 SET_HARD_REG_BIT (call_used_reg_set, i);
00856 SET_HARD_REG_BIT (call_fixed_reg_set, i);
00857 }
00858
00859 return R_AR (start);
00860 }
00861
00862
00863
00864
00865
00866 void
00867 a29k_clobbers_to (insn, op)
00868 rtx insn;
00869 rtx op;
00870 {
00871 int i;
00872 int high_regno;
00873
00874 if (op == 0)
00875 high_regno = R_LR (18);
00876 else if (GET_CODE (op) != REG || REGNO (op) < R_LR (0)
00877 || REGNO (op) > R_LR (18))
00878 abort ();
00879 else
00880 high_regno = REGNO (op);
00881
00882 for (i = R_LR (2); i < high_regno; i++)
00883 CALL_INSN_FUNCTION_USAGE (insn)
00884 = gen_rtx_EXPR_LIST (VOIDmode,
00885 gen_rtx_CLOBBER (VOIDmode,
00886 gen_rtx (REG, SImode, i)),
00887 CALL_INSN_FUNCTION_USAGE (insn));
00888 }
00889
00890
00891
00892
00893
00894
00895 int
00896 needs_regstack_p ()
00897 {
00898 int i;
00899 rtx insn;
00900
00901 if (frame_pointer_needed)
00902 return 1;
00903
00904
00905 for (i = R_LR (127); i >= R_LR (0); i --)
00906 if (regs_ever_live[i])
00907 return 1;
00908
00909
00910 for (insn = get_insns (); insn; insn = next_insn (insn))
00911 if (GET_CODE (insn) == CALL_INSN
00912 || (GET_CODE (insn) == INSN
00913 && GET_CODE (PATTERN (insn)) == SEQUENCE
00914 && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == CALL_INSN))
00915 return 1;
00916
00917
00918 return 0;
00919 }
00920
00921
00922
00923 int
00924 uses_local_reg_p (x)
00925 rtx x;
00926 {
00927 const char *fmt;
00928 int i, j;
00929
00930 switch (GET_CODE (x))
00931 {
00932 case REG:
00933 return REGNO (x) >= R_LR (0) && REGNO (x) <= R_FP;
00934
00935 case CONST_INT:
00936 case CONST:
00937 case PC:
00938 case CC0:
00939 case LABEL_REF:
00940 case SYMBOL_REF:
00941 return 0;
00942
00943 default:
00944 break;
00945 }
00946
00947 fmt = GET_RTX_FORMAT (GET_CODE (x));
00948 for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
00949 {
00950 if (fmt[i] == 'e')
00951 {
00952 if (uses_local_reg_p (XEXP (x, i)))
00953 return 1;
00954 }
00955 else if (fmt[i] == 'E')
00956 {
00957 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
00958 if (uses_local_reg_p (XVECEXP (x, i, j)))
00959 return 1;
00960 }
00961 }
00962
00963 return 0;
00964 }
00965
00966
00967
00968 int
00969 null_epilogue ()
00970 {
00971 return (reload_completed && ! needs_regstack_p ()
00972 && get_frame_size () == 0
00973 && current_function_pretend_args_size == 0);
00974 }
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006 void
01007 print_operand (file, x, code)
01008 FILE *file;
01009 rtx x;
01010 char code;
01011 {
01012 char buf[100];
01013
01014
01015 #define INT_P(X) \
01016 ((GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST_DOUBLE) \
01017 && GET_MODE (X) == VOIDmode)
01018
01019 #define INT_LOWPART(X) \
01020 (GET_CODE (X) == CONST_INT ? INTVAL (X) : CONST_DOUBLE_LOW (X))
01021
01022 switch (code)
01023 {
01024 case 'Q':
01025 if (GET_CODE (x) == REG)
01026 break;
01027 else if (! INT_P (x))
01028 output_operand_lossage ("invalid %%Q value");
01029 fprintf (file, "%d", INT_LOWPART (x) & 0xff);
01030 return;
01031
01032 case 'C':
01033 if (! INT_P (x))
01034 output_operand_lossage ("invalid %%C value");
01035 fprintf (file, "%d", (~ INT_LOWPART (x)) & 0xff);
01036 return;
01037
01038 case 'N':
01039 if (! INT_P (x))
01040 output_operand_lossage ("invalid %%N value");
01041 fprintf (file, "%d", (- INT_LOWPART (x)) & 0xff);
01042 return;
01043
01044 case 'M':
01045 if (! INT_P (x))
01046 output_operand_lossage ("invalid %%M value");
01047 fprintf (file, "%d", INT_LOWPART (x) & 0xffff);
01048 return;
01049
01050 case 'm':
01051 if (! INT_P (x))
01052 output_operand_lossage ("invalid %%m value");
01053 fprintf (file, "%d", (INT_LOWPART (x) & 0xffff) << 16);
01054 return;
01055
01056 case 'b':
01057 if (GET_CODE (x) == GE)
01058 fprintf (file, "f");
01059 else
01060 fprintf (file, "t");
01061 return;
01062
01063 case 'B':
01064 if (GET_CODE (x) == GE)
01065 fprintf (file, "t");
01066 else
01067 fprintf (file, "f");
01068 return;
01069
01070 case 'J':
01071
01072
01073 fprintf (file, GET_RTX_NAME (GET_CODE (x)));
01074 if (GET_CODE (x) == NE)
01075 fprintf (file, "q");
01076 return;
01077
01078 case 'e':
01079 if (optimize && flag_delayed_branch
01080 && a29k_last_prologue_insn == 0 && epilogue_operand (x, VOIDmode)
01081 && dbr_sequence_length () == 0)
01082 {
01083
01084
01085
01086
01087 while (NEXT_INSN (x) != 0)
01088 x = NEXT_INSN (x);
01089
01090 while (GET_CODE (x) != CODE_LABEL)
01091 x = PREV_INSN (x);
01092
01093 ASM_GENERATE_INTERNAL_LABEL (buf, "LX", CODE_LABEL_NUMBER (x));
01094 assemble_name (file, buf);
01095 }
01096 else
01097 output_asm_label (x);
01098 return;
01099
01100 case 'E':
01101 if (dbr_sequence_length ())
01102 ;
01103 else if (a29k_last_prologue_insn)
01104 {
01105 fprintf (file, "\n\t%s", a29k_last_prologue_insn);
01106 free (a29k_last_prologue_insn);
01107 a29k_last_prologue_insn = 0;
01108 }
01109 else if (optimize && flag_delayed_branch
01110 && epilogue_operand (x, VOIDmode))
01111 {
01112 fprintf (file, "\n\t%s", a29k_first_epilogue_insn);
01113 a29k_first_epilogue_insn_used = 1;
01114 }
01115 else
01116 fprintf (file, "\n\tnop");
01117 return;
01118
01119 case 'F':
01120 output_addr_const (file, x);
01121 if (dbr_sequence_length () == 0)
01122 {
01123
01124
01125
01126
01127 if (a29k_last_prologue_insn)
01128 {
01129 fprintf (file, "\n\t%s", a29k_last_prologue_insn);
01130 free (a29k_last_prologue_insn);
01131 a29k_last_prologue_insn = 0;
01132 }
01133 else if (GET_CODE (x) == SYMBOL_REF
01134 && ! strcmp (XSTR (x, 0), current_function_name))
01135 fprintf (file, "+4\n\t%s,%d",
01136 a29k_regstack_size >= 64 ? "const gr121" : "sub gr1,gr1",
01137 a29k_regstack_size * 4);
01138 else
01139 fprintf (file, "\n\tnop");
01140 }
01141 return;
01142
01143 case 'L':
01144 if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode)
01145 {
01146 union real_extract u;
01147
01148 memcpy ((char *) &u, (char *) &CONST_DOUBLE_LOW (x), sizeof u);
01149 fprintf (file, "$double1(%.20e)", u.d);
01150 }
01151 else if (GET_CODE (x) == REG)
01152 fprintf (file, "%s", reg_names[REGNO (x) + 1]);
01153 else
01154 output_operand_lossage ("invalid %%L value");
01155 return;
01156
01157 case 'O':
01158 if (GET_CODE (x) != REG)
01159 output_operand_lossage ("invalid %%O value");
01160 fprintf (file, "%s", reg_names[REGNO (x) + 2]);
01161 return;
01162
01163 case 'P':
01164 if (GET_CODE (x) != REG)
01165 output_operand_lossage ("invalid %%P value");
01166 fprintf (file, "%s", reg_names[REGNO (x) + 3]);
01167 return;
01168
01169 case 'S':
01170 fprintf (file, "%d", (GET_MODE_SIZE (GET_MODE (x)) / UNITS_PER_WORD)-1);
01171 return;
01172
01173 case 'V':
01174 if (GET_CODE (x) != PARALLEL)
01175 output_operand_lossage ("invalid %%V value");
01176 fprintf (file, "%d", XVECLEN (x, 0) - 2);
01177 return;
01178
01179 case '#':
01180 if (dbr_sequence_length () == 0)
01181 {
01182 if (a29k_last_prologue_insn)
01183 {
01184 fprintf (file, "\n\t%s", a29k_last_prologue_insn);
01185 free (a29k_last_prologue_insn);
01186 a29k_last_prologue_insn = 0;
01187 }
01188 else
01189 fprintf (file, "\n\tnop");
01190 }
01191 return;
01192
01193 case '*':
01194 fprintf (file, "%s", reg_names [R_TPC]);
01195 return;
01196 }
01197
01198 if (GET_CODE (x) == REG)
01199 fprintf (file, "%s", reg_names [REGNO (x)]);
01200
01201 else if (GET_CODE (x) == MEM)
01202 output_address (XEXP (x, 0));
01203
01204 else if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == SUBREG
01205 && GET_CODE (SUBREG_REG (XEXP (x, 0))) == CONST_DOUBLE)
01206 {
01207 union real_extract u;
01208
01209 if (GET_MODE (SUBREG_REG (XEXP (x, 0))) == SFmode)
01210 fprintf (file, "$float");
01211 else
01212 fprintf (file, "$double%d",
01213 (SUBREG_BYTE (XEXP (x, 0)) / GET_MODE_SIZE (GET_MODE (x))));
01214 memcpy ((char *) &u,
01215 (char *) &CONST_DOUBLE_LOW (SUBREG_REG (XEXP (x, 0))), sizeof u);
01216 fprintf (file, "(%.20e)", u.d);
01217 }
01218
01219 else if (GET_CODE (x) == CONST_DOUBLE
01220 && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
01221 {
01222 union real_extract u;
01223
01224 memcpy ((char *) &u, (char *) &CONST_DOUBLE_LOW (x), sizeof u);
01225 fprintf (file, "$%s(%.20e)",
01226 GET_MODE (x) == SFmode ? "float" : "double0", u.d);
01227 }
01228
01229 else
01230 output_addr_const (file, x);
01231 }
01232
01233
01234
01235
01236
01237
01238 static void
01239 compute_regstack_size ()
01240 {
01241 int i;
01242 rtx insn;
01243
01244
01245 a29k_makes_calls = 0;
01246 for (insn = get_insns (); insn; insn = next_insn (insn))
01247 if (GET_CODE (insn) == CALL_INSN
01248 || (GET_CODE (insn) == INSN
01249 && GET_CODE (PATTERN (insn)) == SEQUENCE
01250 && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == CALL_INSN))
01251 {
01252 a29k_makes_calls = 1;
01253 break;
01254 }
01255
01256
01257 for (i = R_LR (127); i >= R_LR (0); i--)
01258 if (regs_ever_live[i])
01259 break;
01260
01261 a29k_regstack_size = i - (R_LR (0) - 1);
01262
01263
01264 if (a29k_makes_calls && a29k_regstack_size < 2)
01265 a29k_regstack_size = 2;
01266
01267
01268
01269 a29k_regstack_size += frame_pointer_needed;
01270 if (a29k_regstack_size & 1) a29k_regstack_size++;
01271 }
01272
01273
01274
01275
01276 void
01277 a29k_compute_reg_names ()
01278 {
01279 int i;
01280
01281 compute_regstack_size ();
01282
01283
01284
01285
01286 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
01287 a29k_debug_reg_map[i] = i;
01288
01289 reg_names[FRAME_POINTER_REGNUM] = reg_names[R_LR (a29k_regstack_size - 1)];
01290 a29k_debug_reg_map[FRAME_POINTER_REGNUM] = R_LR (a29k_regstack_size - 1);
01291
01292 for (i = 0; i < 16; i++)
01293 {
01294 reg_names[R_AR (i)] = reg_names[R_LR (a29k_regstack_size + i + 2)];
01295 a29k_debug_reg_map[R_AR (i)] = R_LR (a29k_regstack_size + i + 2);
01296 }
01297
01298
01299
01300 if (TARGET_KERNEL_REGISTERS)
01301 for (i = 0; i < 32; i++)
01302 {
01303 int tem = a29k_debug_reg_map[i];
01304 a29k_debug_reg_map[i] = a29k_debug_reg_map[R_KR (i)];
01305 a29k_debug_reg_map[R_KR (i)] = tem;
01306 }
01307 }
01308
01309
01310
01311 static void
01312 output_function_prologue (file, size)
01313 FILE *file;
01314 HOST_WIDE_INT size;
01315 {
01316 int i;
01317 int arg_count = 0;
01318 rtx insn;
01319 unsigned int tag_word;
01320
01321
01322 for (i = R_AR (0); i < R_AR (16); i++)
01323 if (! fixed_regs[i])
01324 arg_count++;
01325
01326
01327 arg_count += 2;
01328
01329
01330
01331
01332 size += (current_function_pretend_args_size
01333 + current_function_outgoing_args_size);
01334 size = (size + 7) & ~7;
01335
01336
01337 tag_word = (frame_pointer_needed ? 0x400000 : 0) + (arg_count << 16);
01338
01339 if (size / 8 > 0xff)
01340 fprintf (file, "\t.word %d, 0x%0x\n", (size / 8) << 2,
01341 0x800000 + tag_word);
01342 else
01343 fprintf (file, "\t.word 0x%0x\n", tag_word + ((size / 8) << 3));
01344
01345
01346 assemble_name (file, a29k_function_name);
01347 fprintf (file, ":\n");
01348
01349
01350
01351 if (a29k_regstack_size >= 256/4)
01352 fprintf (file, "\tconst %s,%d\n\tsub gr1,gr1,%s\n",
01353 reg_names[R_TAV], a29k_regstack_size * 4, reg_names[R_TAV]);
01354 else if (a29k_regstack_size)
01355 fprintf (file, "\tsub gr1,gr1,%d\n", a29k_regstack_size * 4);
01356
01357
01358 if (a29k_regstack_size)
01359 fprintf (file, "\tasgeu V_%sSPILL,gr1,%s\n",
01360 TARGET_KERNEL_REGISTERS ? "K" : "", reg_names[R_RAB]);
01361
01362
01363 if (frame_pointer_needed)
01364 fprintf (file, "\tsll %s,%s,0\n", reg_names[FRAME_POINTER_REGNUM],
01365 reg_names[R_MSP]);
01366
01367
01368 if (size >= 256)
01369 {
01370 fprintf (file, "\tconst %s,%d\n", reg_names[R_TAV], size);
01371 if (size >= 65536)
01372 fprintf (file, "\tconsth %s,%d\n", reg_names[R_TAV], size);
01373 if (TARGET_STACK_CHECK)
01374 fprintf (file, "\tcall %s,__msp_check\n", reg_names[R_TPC]);
01375 fprintf (file, "\tsub %s,%s,%s\n",
01376 reg_names[R_MSP], reg_names[R_MSP], reg_names[R_TAV]);
01377 }
01378 else if (size)
01379 {
01380 if (TARGET_STACK_CHECK)
01381 fprintf (file, "\tcall %s,__msp_check\n", reg_names[R_TPC]);
01382 fprintf (file, "\tsub %s,%s,%d\n",
01383 reg_names[R_MSP], reg_names[R_MSP], size);
01384 }
01385
01386
01387
01388
01389
01390 a29k_last_prologue_insn = 0;
01391 if (a29k_makes_calls)
01392 {
01393 i = (a29k_regstack_size + arg_count) * 4;
01394 if (i >= 256)
01395 fprintf (file, "\tconst %s,%d\n\tadd lr1,gr1,%s\n",
01396 reg_names[R_TAV], i, reg_names[R_TAV]);
01397 else
01398 {
01399 if (optimize && flag_delayed_branch)
01400 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
01401 {
01402 if (GET_CODE (insn) == CODE_LABEL
01403 || (GET_CODE (insn) == INSN
01404 && GET_CODE (PATTERN (insn)) == SEQUENCE))
01405 break;
01406
01407 if (GET_CODE (insn) == NOTE
01408 || (GET_CODE (insn) == INSN
01409 && (GET_CODE (PATTERN (insn)) == USE
01410 || GET_CODE (PATTERN (insn)) == CLOBBER)))
01411 continue;
01412
01413 if (num_delay_slots (insn) > 0)
01414 {
01415 a29k_last_prologue_insn = (char *) xmalloc (100);
01416 sprintf (a29k_last_prologue_insn, "add lr1,gr1,%d", i);
01417 break;
01418 }
01419 }
01420
01421 if (a29k_last_prologue_insn == 0)
01422 fprintf (file, "\tadd lr1,gr1,%d\n", i);
01423 }
01424 }
01425
01426
01427 a29k_first_epilogue_insn_used = 0;
01428
01429 if (size == 0 && a29k_regstack_size == 0 && ! frame_pointer_needed)
01430 a29k_first_epilogue_insn = 0;
01431 else
01432 a29k_first_epilogue_insn = (char *) xmalloc (100);
01433
01434 if (frame_pointer_needed)
01435 sprintf (a29k_first_epilogue_insn, "sll %s,%s,0",
01436 reg_names[R_MSP], reg_names[FRAME_POINTER_REGNUM]);
01437 else if (a29k_regstack_size)
01438 {
01439 if (a29k_regstack_size >= 256 / 4)
01440 sprintf (a29k_first_epilogue_insn, "const %s,%d",
01441 reg_names[R_TAV], a29k_regstack_size * 4);
01442 else
01443 sprintf (a29k_first_epilogue_insn, "add gr1,gr1,%d",
01444 a29k_regstack_size * 4);
01445 }
01446 else if (size)
01447 {
01448 if (size >= 256)
01449 sprintf (a29k_first_epilogue_insn, "const %s,%d",
01450 reg_names[R_TAV], size);
01451 else
01452 sprintf (a29k_first_epilogue_insn, "add %s,%s,%d",
01453 reg_names[R_MSP], reg_names[R_MSP], size);
01454 }
01455 }
01456
01457
01458
01459
01460
01461 static void
01462 check_epilogue_internal_label (file)
01463 FILE *file;
01464 {
01465 rtx insn;
01466
01467 if (! a29k_first_epilogue_insn_used)
01468 return;
01469
01470 for (insn = get_last_insn ();
01471 GET_CODE (insn) != CODE_LABEL;
01472 insn = PREV_INSN (insn))
01473 ;
01474
01475 ASM_OUTPUT_INTERNAL_LABEL (file, "LX", CODE_LABEL_NUMBER (insn));
01476 a29k_first_epilogue_insn_used = 0;
01477 }
01478
01479
01480
01481
01482
01483 static void
01484 output_function_epilogue (file, size)
01485 FILE *file;
01486 HOST_WIDE_INT size;
01487 {
01488 rtx insn;
01489 int locals_unavailable = 0;
01490
01491
01492
01493
01494 insn = get_last_insn ();
01495 if (GET_CODE (insn) == NOTE)
01496 insn = prev_nonnote_insn (insn);
01497
01498 if (insn && GET_CODE (insn) == BARRIER)
01499 return;
01500
01501
01502
01503 if (frame_pointer_needed)
01504 {
01505 fprintf (file, "\tsll %s,%s,0\n",
01506 reg_names[R_MSP], reg_names[FRAME_POINTER_REGNUM]);
01507 check_epilogue_internal_label (file);
01508 }
01509
01510
01511 if (a29k_regstack_size)
01512 {
01513 if (a29k_regstack_size >= 256/4)
01514 {
01515 fprintf (file, "\tconst %s,%d\n",
01516 reg_names[R_TAV], a29k_regstack_size * 4);
01517 check_epilogue_internal_label (file);
01518 fprintf (file, "\tadd gr1,gr1,%s\n", reg_names[R_TAV]);
01519 }
01520 else
01521 {
01522 fprintf (file, "\tadd gr1,gr1,%d\n", a29k_regstack_size * 4);
01523 check_epilogue_internal_label (file);
01524 }
01525 locals_unavailable = 1;
01526 }
01527
01528
01529
01530
01531 size += (current_function_pretend_args_size
01532 + current_function_outgoing_args_size);
01533 size = (size + 7) & ~7;
01534
01535 if (size && ! frame_pointer_needed)
01536 {
01537 if (size >= 256)
01538 {
01539 fprintf (file, "\tconst %s,%d\n", reg_names[R_TAV], size);
01540 check_epilogue_internal_label (file);
01541 locals_unavailable = 0;
01542 if (size >= 65536)
01543 fprintf (file, "\tconsth %s,%d\n", reg_names[R_TAV], size);
01544 fprintf (file, "\tadd %s,%s,%s\n",
01545 reg_names[R_MSP], reg_names[R_MSP], reg_names[R_TAV]);
01546 }
01547 else
01548 {
01549 fprintf (file, "\tadd %s,%s,%d\n",
01550 reg_names[R_MSP], reg_names[R_MSP], size);
01551 check_epilogue_internal_label (file);
01552 locals_unavailable = 0;
01553 }
01554 }
01555
01556 if (locals_unavailable)
01557 {
01558
01559 if (current_function_epilogue_delay_list)
01560 final_scan_insn (XEXP (current_function_epilogue_delay_list, 0),
01561 file, 1, -2, 1);
01562 else
01563 fprintf (file, "\tnop\n");
01564 }
01565
01566 fprintf (file, "\tjmpi lr0\n");
01567 if (a29k_regstack_size)
01568 fprintf (file, "\tasleu V_%sFILL,lr1,%s\n",
01569 TARGET_KERNEL_REGISTERS ? "K" : "", reg_names[R_RFB]);
01570 else if (current_function_epilogue_delay_list)
01571 final_scan_insn (XEXP (current_function_epilogue_delay_list, 0),
01572 file, 1, -2, 1);
01573 else
01574 fprintf (file, "\tnop\n");
01575
01576 if (a29k_first_epilogue_insn)
01577 free (a29k_first_epilogue_insn);
01578 a29k_first_epilogue_insn = 0;
01579 }
01580
01581 static void
01582 a29k_asm_named_section (name, flags)
01583 const char *name;
01584 unsigned int flags ATTRIBUTE_UNUSED;
01585 {
01586
01587 fprintf (asm_out_file, "\t.sect %s, bss\n\t.use %s\n", name, name);
01588 }
01589
01590
01591
01592
01593
01594
01595 static int
01596 a29k_adjust_cost (insn, link, dep_insn, cost)
01597 rtx insn ATTRIBUTE_UNUSED;
01598 rtx link;
01599 rtx dep_insn ATTRIBUTE_UNUSED;
01600 int cost;
01601 {
01602 if (REG_NOTE_KIND (link) != 0)
01603 return 0;
01604
01605 return cost;
01606 }