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 "rtl.h"
00026 #include "tree.h"
00027 #include "regs.h"
00028 #include "hard-reg-set.h"
00029 #include "real.h"
00030 #include "insn-config.h"
00031 #include "conditions.h"
00032 #include "output.h"
00033 #include "insn-attr.h"
00034 #include "flags.h"
00035 #include "recog.h"
00036 #include "expr.h"
00037 #include "optabs.h"
00038 #include "function.h"
00039 #include "obstack.h"
00040 #include "toplev.h"
00041 #include "tm_p.h"
00042 #include "target.h"
00043 #include "target-def.h"
00044
00045
00046
00047
00048 #define REG_SAVE_BYTES (4 * regs_ever_live[2] \
00049 + 4 * regs_ever_live[3] \
00050 + 4 * regs_ever_live[6] \
00051 + 4 * regs_ever_live[7] \
00052 + 16 * (regs_ever_live[14] || regs_ever_live[15] \
00053 || regs_ever_live[16] || regs_ever_live[17]))
00054
00055
00056 #undef TARGET_ASM_ALIGNED_HI_OP
00057 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
00058
00059 struct gcc_target targetm = TARGET_INITIALIZER;
00060
00061 void
00062 asm_file_start (file)
00063 FILE *file;
00064 {
00065 fprintf (file, "#\tGCC For the Matsushita MN10300\n");
00066 if (optimize)
00067 fprintf (file, "# -O%d\n", optimize);
00068 else
00069 fprintf (file, "\n\n");
00070
00071 if (TARGET_AM33)
00072 fprintf (file, "\t.am33\n");
00073 output_file_directive (file, main_input_filename);
00074 }
00075
00076
00077
00078
00079
00080 void
00081 print_operand (file, x, code)
00082 FILE *file;
00083 rtx x;
00084 int code;
00085 {
00086 switch (code)
00087 {
00088 case 'b':
00089 case 'B':
00090
00091 switch (code == 'b' ? GET_CODE (x) : reverse_condition (GET_CODE (x)))
00092 {
00093 case NE:
00094 fprintf (file, "ne");
00095 break;
00096 case EQ:
00097 fprintf (file, "eq");
00098 break;
00099 case GE:
00100 fprintf (file, "ge");
00101 break;
00102 case GT:
00103 fprintf (file, "gt");
00104 break;
00105 case LE:
00106 fprintf (file, "le");
00107 break;
00108 case LT:
00109 fprintf (file, "lt");
00110 break;
00111 case GEU:
00112 fprintf (file, "cc");
00113 break;
00114 case GTU:
00115 fprintf (file, "hi");
00116 break;
00117 case LEU:
00118 fprintf (file, "ls");
00119 break;
00120 case LTU:
00121 fprintf (file, "cs");
00122 break;
00123 default:
00124 abort ();
00125 }
00126 break;
00127 case 'C':
00128
00129
00130
00131 if (GET_CODE (x) == REG)
00132 {
00133 fputc ('(', file);
00134 print_operand (file, x, 0);
00135 fputc (')', file);
00136 }
00137 else
00138 print_operand (file, x, 0);
00139 break;
00140
00141
00142 case 'L':
00143 switch (GET_CODE (x))
00144 {
00145 case MEM:
00146 fputc ('(', file);
00147 output_address (XEXP (x, 0));
00148 fputc (')', file);
00149 break;
00150
00151 case REG:
00152 fprintf (file, "%s", reg_names[REGNO (x)]);
00153 break;
00154
00155 case SUBREG:
00156 fprintf (file, "%s", reg_names[subreg_regno (x)]);
00157 break;
00158
00159 case CONST_DOUBLE:
00160 {
00161 long val[2];
00162 REAL_VALUE_TYPE rv;
00163
00164 switch (GET_MODE (x))
00165 {
00166 case DFmode:
00167 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
00168 REAL_VALUE_TO_TARGET_DOUBLE (rv, val);
00169 fprintf (file, "0x%lx", val[0]);
00170 break;;
00171 case SFmode:
00172 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
00173 REAL_VALUE_TO_TARGET_SINGLE (rv, val[0]);
00174 fprintf (file, "0x%lx", val[0]);
00175 break;;
00176 case VOIDmode:
00177 case DImode:
00178 print_operand_address (file,
00179 GEN_INT (CONST_DOUBLE_LOW (x)));
00180 break;
00181 default:
00182 break;
00183 }
00184 break;
00185 }
00186
00187 case CONST_INT:
00188 {
00189 rtx low, high;
00190 split_double (x, &low, &high);
00191 fprintf (file, "%ld", (long)INTVAL (low));
00192 break;
00193 }
00194
00195 default:
00196 abort ();
00197 }
00198 break;
00199
00200
00201 case 'H':
00202 switch (GET_CODE (x))
00203 {
00204 case MEM:
00205 fputc ('(', file);
00206 x = adjust_address (x, SImode, 4);
00207 output_address (XEXP (x, 0));
00208 fputc (')', file);
00209 break;
00210
00211 case REG:
00212 fprintf (file, "%s", reg_names[REGNO (x) + 1]);
00213 break;
00214
00215 case SUBREG:
00216 fprintf (file, "%s", reg_names[subreg_regno (x) + 1]);
00217 break;
00218
00219 case CONST_DOUBLE:
00220 {
00221 long val[2];
00222 REAL_VALUE_TYPE rv;
00223
00224 switch (GET_MODE (x))
00225 {
00226 case DFmode:
00227 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
00228 REAL_VALUE_TO_TARGET_DOUBLE (rv, val);
00229 fprintf (file, "0x%lx", val[1]);
00230 break;;
00231 case SFmode:
00232 abort ();
00233 case VOIDmode:
00234 case DImode:
00235 print_operand_address (file,
00236 GEN_INT (CONST_DOUBLE_HIGH (x)));
00237 break;
00238 default:
00239 break;
00240 }
00241 break;
00242 }
00243
00244 case CONST_INT:
00245 {
00246 rtx low, high;
00247 split_double (x, &low, &high);
00248 fprintf (file, "%ld", (long)INTVAL (high));
00249 break;
00250 }
00251
00252 default:
00253 abort ();
00254 }
00255 break;
00256
00257 case 'A':
00258 fputc ('(', file);
00259 if (GET_CODE (XEXP (x, 0)) == REG)
00260 output_address (gen_rtx_PLUS (SImode, XEXP (x, 0), GEN_INT (0)));
00261 else
00262 output_address (XEXP (x, 0));
00263 fputc (')', file);
00264 break;
00265
00266 case 'N':
00267 output_address (GEN_INT ((~INTVAL (x)) & 0xff));
00268 break;
00269
00270
00271
00272
00273
00274 case 'S':
00275 if (GET_CODE (x) == CONST_INT)
00276 {
00277 fprintf (file, "%d", INTVAL (x) & 0x1f);
00278 break;
00279 }
00280
00281
00282 default:
00283 switch (GET_CODE (x))
00284 {
00285 case MEM:
00286 fputc ('(', file);
00287 output_address (XEXP (x, 0));
00288 fputc (')', file);
00289 break;
00290
00291 case PLUS:
00292 output_address (x);
00293 break;
00294
00295 case REG:
00296 fprintf (file, "%s", reg_names[REGNO (x)]);
00297 break;
00298
00299 case SUBREG:
00300 fprintf (file, "%s", reg_names[subreg_regno (x)]);
00301 break;
00302
00303
00304 case CONST_DOUBLE:
00305 {
00306 unsigned long val;
00307 REAL_VALUE_TYPE rv;
00308
00309 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
00310 REAL_VALUE_TO_TARGET_SINGLE (rv, val);
00311 fprintf (file, "0x%lx", val);
00312 break;
00313 }
00314
00315 case CONST_INT:
00316 case SYMBOL_REF:
00317 case CONST:
00318 case LABEL_REF:
00319 case CODE_LABEL:
00320 print_operand_address (file, x);
00321 break;
00322 default:
00323 abort ();
00324 }
00325 break;
00326 }
00327 }
00328
00329
00330
00331 void
00332 print_operand_address (file, addr)
00333 FILE *file;
00334 rtx addr;
00335 {
00336 switch (GET_CODE (addr))
00337 {
00338 case POST_INC:
00339 print_operand_address (file, XEXP (addr, 0));
00340 fputc ('+', file);
00341 break;
00342 case REG:
00343 print_operand (file, addr, 0);
00344 break;
00345 case PLUS:
00346 {
00347 rtx base, index;
00348 if (REG_P (XEXP (addr, 0))
00349 && REG_OK_FOR_BASE_P (XEXP (addr, 0)))
00350 base = XEXP (addr, 0), index = XEXP (addr, 1);
00351 else if (REG_P (XEXP (addr, 1))
00352 && REG_OK_FOR_BASE_P (XEXP (addr, 1)))
00353 base = XEXP (addr, 1), index = XEXP (addr, 0);
00354 else
00355 abort ();
00356 print_operand (file, index, 0);
00357 fputc (',', file);
00358 print_operand (file, base, 0);;
00359 break;
00360 }
00361 case SYMBOL_REF:
00362 output_addr_const (file, addr);
00363 break;
00364 default:
00365 output_addr_const (file, addr);
00366 break;
00367 }
00368 }
00369
00370
00371
00372
00373
00374
00375
00376 void
00377 mn10300_print_reg_list (file, mask)
00378 FILE *file;
00379 int mask;
00380 {
00381 int need_comma;
00382 int i;
00383
00384 need_comma = 0;
00385 fputc ('[', file);
00386
00387 for (i = 0; i < FIRST_EXTENDED_REGNUM; i++)
00388 if ((mask & (1 << i)) != 0)
00389 {
00390 if (need_comma)
00391 fputc (',', file);
00392 fputs (reg_names [i], file);
00393 need_comma = 1;
00394 }
00395
00396 if ((mask & 0x3c000) != 0)
00397 {
00398 if ((mask & 0x3c000) != 0x3c000)
00399 abort();
00400 if (need_comma)
00401 fputc (',', file);
00402 fputs ("exreg1", file);
00403 need_comma = 1;
00404 }
00405
00406 fputc (']', file);
00407 }
00408
00409 int
00410 can_use_return_insn ()
00411 {
00412
00413 int size = get_frame_size () + current_function_outgoing_args_size;
00414
00415
00416 size += current_function_outgoing_args_size ? 4 : 0;
00417
00418 return (reload_completed
00419 && size == 0
00420 && !regs_ever_live[2]
00421 && !regs_ever_live[3]
00422 && !regs_ever_live[6]
00423 && !regs_ever_live[7]
00424 && !regs_ever_live[14]
00425 && !regs_ever_live[15]
00426 && !regs_ever_live[16]
00427 && !regs_ever_live[17]
00428 && !frame_pointer_needed);
00429 }
00430
00431
00432
00433
00434
00435 int
00436 mn10300_get_live_callee_saved_regs ()
00437 {
00438 int mask;
00439 int i;
00440
00441 mask = 0;
00442 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
00443 if (regs_ever_live[i] && ! call_used_regs[i])
00444 mask |= (1 << i);
00445 if ((mask & 0x3c000) != 0)
00446 mask |= 0x3c000;
00447
00448 return mask;
00449 }
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470 void
00471 mn10300_gen_multiple_store (mask)
00472 int mask;
00473 {
00474 if (mask != 0)
00475 {
00476 int i;
00477 int count;
00478 rtx par;
00479 int pari;
00480
00481
00482 count = 0;
00483 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
00484 if ((mask & (1 << i)) != 0)
00485 count += 1;
00486
00487
00488
00489 par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count + 1));
00490
00491
00492 XVECEXP (par, 0, 0)
00493 = gen_rtx_SET (SImode,
00494 stack_pointer_rtx,
00495 gen_rtx_PLUS (SImode,
00496 stack_pointer_rtx,
00497 GEN_INT (-count * 4)));
00498
00499
00500 pari = 1;
00501 for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
00502 if ((mask & (1 << i)) != 0)
00503 {
00504 rtx address = gen_rtx_PLUS (SImode,
00505 stack_pointer_rtx,
00506 GEN_INT (-pari * 4));
00507 XVECEXP(par, 0, pari)
00508 = gen_rtx_SET (VOIDmode,
00509 gen_rtx_MEM (SImode, address),
00510 gen_rtx_REG (SImode, i));
00511 pari += 1;
00512 }
00513
00514 par = emit_insn (par);
00515 RTX_FRAME_RELATED_P (par) = 1;
00516 }
00517 }
00518
00519 void
00520 expand_prologue ()
00521 {
00522 HOST_WIDE_INT size;
00523
00524
00525 size = get_frame_size () + current_function_outgoing_args_size;
00526 size += (current_function_outgoing_args_size ? 4 : 0);
00527
00528
00529
00530 if (current_function_varargs)
00531 {
00532 emit_move_insn (gen_rtx_MEM (SImode,
00533 plus_constant (stack_pointer_rtx, 4)),
00534 gen_rtx_REG (SImode, 0));
00535 emit_move_insn (gen_rtx_MEM (SImode,
00536 plus_constant (stack_pointer_rtx, 8)),
00537 gen_rtx_REG (SImode, 1));
00538 }
00539
00540
00541 mn10300_gen_multiple_store (mn10300_get_live_callee_saved_regs ());
00542
00543
00544 if (frame_pointer_needed)
00545 emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
00546
00547
00548 if (size)
00549 emit_insn (gen_addsi3 (stack_pointer_rtx,
00550 stack_pointer_rtx,
00551 GEN_INT (-size)));
00552 }
00553
00554 void
00555 expand_epilogue ()
00556 {
00557 HOST_WIDE_INT size;
00558
00559
00560 size = get_frame_size () + current_function_outgoing_args_size;
00561 size += (current_function_outgoing_args_size ? 4 : 0);
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578 if (frame_pointer_needed)
00579 {
00580 emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
00581 size = 0;
00582 }
00583 else if (size + REG_SAVE_BYTES > 255)
00584 {
00585 emit_insn (gen_addsi3 (stack_pointer_rtx,
00586 stack_pointer_rtx,
00587 GEN_INT (size)));
00588 size = 0;
00589 }
00590
00591
00592 if (size || regs_ever_live[2] || regs_ever_live[3]
00593 || regs_ever_live[6] || regs_ever_live[7]
00594 || regs_ever_live[14] || regs_ever_live[15]
00595 || regs_ever_live[16] || regs_ever_live[17]
00596 || frame_pointer_needed)
00597 emit_jump_insn (gen_return_internal_regs
00598 (GEN_INT (size + REG_SAVE_BYTES)));
00599 else
00600 emit_jump_insn (gen_return_internal ());
00601 }
00602
00603
00604
00605 void
00606 notice_update_cc (body, insn)
00607 rtx body;
00608 rtx insn;
00609 {
00610 switch (get_attr_cc (insn))
00611 {
00612 case CC_NONE:
00613
00614 break;
00615
00616 case CC_NONE_0HIT:
00617
00618 if (cc_status.value1 != 0
00619 && reg_overlap_mentioned_p (recog_data.operand[0], cc_status.value1))
00620 cc_status.value1 = 0;
00621 break;
00622
00623 case CC_SET_ZN:
00624
00625
00626 CC_STATUS_INIT;
00627 cc_status.flags |= CC_NO_CARRY | CC_OVERFLOW_UNUSABLE;
00628 cc_status.value1 = recog_data.operand[0];
00629 break;
00630
00631 case CC_SET_ZNV:
00632
00633
00634 CC_STATUS_INIT;
00635 cc_status.flags |= CC_NO_CARRY;
00636 cc_status.value1 = recog_data.operand[0];
00637 break;
00638
00639 case CC_COMPARE:
00640
00641 CC_STATUS_INIT;
00642 cc_status.value1 = SET_SRC (body);
00643 break;
00644
00645 case CC_INVERT:
00646
00647 CC_STATUS_INIT;
00648 cc_status.value1 = SET_SRC (body);
00649 cc_status.flags |= CC_INVERTED;
00650 break;
00651
00652 case CC_CLOBBER:
00653
00654 CC_STATUS_INIT;
00655 break;
00656
00657 default:
00658 abort ();
00659 }
00660 }
00661
00662
00663
00664
00665
00666
00667 int
00668 store_multiple_operation (op, mode)
00669 rtx op;
00670 enum machine_mode mode ATTRIBUTE_UNUSED;
00671 {
00672 int count;
00673 int mask;
00674 int i;
00675 unsigned int last;
00676 rtx elt;
00677
00678 count = XVECLEN (op, 0);
00679 if (count < 2)
00680 return 0;
00681
00682
00683 elt = XVECEXP (op, 0, 0);
00684 if (GET_CODE (elt) != SET
00685 || GET_CODE (SET_DEST (elt)) != REG
00686 || REGNO (SET_DEST (elt)) != STACK_POINTER_REGNUM
00687 || GET_CODE (SET_SRC (elt)) != PLUS)
00688 return 0;
00689
00690
00691
00692
00693
00694 elt = SET_SRC (elt);
00695 if (GET_CODE (XEXP (elt, 0)) != REG
00696 || REGNO (XEXP (elt, 0)) != STACK_POINTER_REGNUM
00697 || GET_CODE (XEXP (elt, 1)) != CONST_INT
00698 || INTVAL (XEXP (elt, 1)) != -(count - 1) * 4)
00699 return 0;
00700
00701
00702
00703
00704
00705
00706
00707
00708 last = FIRST_PSEUDO_REGISTER;
00709 mask = 0;
00710 for (i = 1; i < count; i++)
00711 {
00712
00713 elt = XVECEXP (op, 0, i);
00714 if (GET_CODE (elt) != SET
00715 || GET_CODE (SET_DEST (elt)) != MEM
00716 || GET_CODE (SET_SRC (elt)) != REG
00717 || REGNO (SET_SRC (elt)) >= last)
00718 return 0;
00719
00720
00721
00722 last = REGNO (SET_SRC (elt));
00723 mask |= (1 << last);
00724
00725
00726 elt = XEXP (SET_DEST (elt), 0);
00727 if (GET_CODE (elt) != PLUS
00728 || GET_CODE (XEXP (elt, 0)) != REG
00729 || REGNO (XEXP (elt, 0)) != STACK_POINTER_REGNUM
00730 || GET_CODE (XEXP (elt, 1)) != CONST_INT
00731 || INTVAL (XEXP (elt, 1)) != -i * 4)
00732 return 0;
00733 }
00734
00735
00736 if ((mask & 0x3c000) != 0
00737 && (mask & 0x3c000) != 0x3c000)
00738 return 0;
00739
00740 return mask;
00741 }
00742
00743
00744
00745 int
00746 call_address_operand (op, mode)
00747 rtx op;
00748 enum machine_mode mode ATTRIBUTE_UNUSED;
00749 {
00750 return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == REG);
00751 }
00752
00753
00754
00755
00756
00757 enum reg_class
00758 secondary_reload_class (class, mode, in)
00759 enum reg_class class;
00760 enum machine_mode mode;
00761 rtx in;
00762 {
00763
00764
00765
00766 if ((GET_CODE (in) == MEM
00767 || (GET_CODE (in) == REG
00768 && REGNO (in) >= FIRST_PSEUDO_REGISTER)
00769 || (GET_CODE (in) == SUBREG
00770 && GET_CODE (SUBREG_REG (in)) == REG
00771 && REGNO (SUBREG_REG (in)) >= FIRST_PSEUDO_REGISTER))
00772 && (mode == QImode || mode == HImode)
00773 && (class == ADDRESS_REGS || class == SP_REGS
00774 || class == SP_OR_ADDRESS_REGS))
00775 {
00776 if (TARGET_AM33)
00777 return DATA_OR_EXTENDED_REGS;
00778 return DATA_REGS;
00779 }
00780
00781
00782
00783 if (class != SP_REGS
00784 && class != ADDRESS_REGS
00785 && class != SP_OR_ADDRESS_REGS
00786 && class != SP_OR_EXTENDED_REGS
00787 && class != ADDRESS_OR_EXTENDED_REGS
00788 && class != SP_OR_ADDRESS_OR_EXTENDED_REGS
00789 && (in == stack_pointer_rtx
00790 || (GET_CODE (in) == PLUS
00791 && (XEXP (in, 0) == stack_pointer_rtx
00792 || XEXP (in, 1) == stack_pointer_rtx))))
00793 return ADDRESS_REGS;
00794
00795 if (GET_CODE (in) == PLUS
00796 && (XEXP (in, 0) == stack_pointer_rtx
00797 || XEXP (in, 1) == stack_pointer_rtx))
00798 {
00799 if (TARGET_AM33)
00800 return DATA_OR_EXTENDED_REGS;
00801 return DATA_REGS;
00802 }
00803
00804
00805 return NO_REGS;
00806 }
00807
00808 int
00809 initial_offset (from, to)
00810 int from, to;
00811 {
00812
00813
00814 if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
00815 {
00816 if (regs_ever_live[2] || regs_ever_live[3]
00817 || regs_ever_live[6] || regs_ever_live[7]
00818 || regs_ever_live[14] || regs_ever_live[15]
00819 || regs_ever_live[16] || regs_ever_live[17]
00820 || frame_pointer_needed)
00821 return REG_SAVE_BYTES;
00822 else
00823 return 0;
00824 }
00825
00826
00827
00828
00829 if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
00830 {
00831 if (regs_ever_live[2] || regs_ever_live[3]
00832 || regs_ever_live[6] || regs_ever_live[7]
00833 || regs_ever_live[14] || regs_ever_live[15]
00834 || regs_ever_live[16] || regs_ever_live[17]
00835 || frame_pointer_needed)
00836 return (get_frame_size () + REG_SAVE_BYTES
00837 + (current_function_outgoing_args_size
00838 ? current_function_outgoing_args_size + 4 : 0));
00839 else
00840 return (get_frame_size ()
00841 + (current_function_outgoing_args_size
00842 ? current_function_outgoing_args_size + 4 : 0));
00843 }
00844
00845
00846
00847
00848 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
00849 return (get_frame_size ()
00850 + (current_function_outgoing_args_size
00851 ? current_function_outgoing_args_size + 4 : 0));
00852
00853 abort ();
00854 }
00855
00856
00857
00858 rtx
00859 mn10300_builtin_saveregs ()
00860 {
00861 rtx offset, mem;
00862 tree fntype = TREE_TYPE (current_function_decl);
00863 int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0
00864 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
00865 != void_type_node)))
00866 ? UNITS_PER_WORD : 0);
00867 int set = get_varargs_alias_set ();
00868
00869 if (argadj)
00870 offset = plus_constant (current_function_arg_offset_rtx, argadj);
00871 else
00872 offset = current_function_arg_offset_rtx;
00873
00874 mem = gen_rtx_MEM (SImode, current_function_internal_arg_pointer);
00875 set_mem_alias_set (mem, set);
00876 emit_move_insn (mem, gen_rtx_REG (SImode, 0));
00877
00878 mem = gen_rtx_MEM (SImode,
00879 plus_constant (current_function_internal_arg_pointer, 4));
00880 set_mem_alias_set (mem, set);
00881 emit_move_insn (mem, gen_rtx_REG (SImode, 1));
00882
00883 return copy_to_reg (expand_binop (Pmode, add_optab,
00884 current_function_internal_arg_pointer,
00885 offset, 0, 0, OPTAB_LIB_WIDEN));
00886 }
00887
00888 void
00889 mn10300_va_start (stdarg_p, valist, nextarg)
00890 int stdarg_p;
00891 tree valist;
00892 rtx nextarg;
00893 {
00894 if (stdarg_p)
00895 nextarg = expand_builtin_saveregs ();
00896
00897 std_expand_builtin_va_start (stdarg_p, valist, nextarg);
00898 }
00899
00900 rtx
00901 mn10300_va_arg (valist, type)
00902 tree valist, type;
00903 {
00904 HOST_WIDE_INT align, rsize;
00905 tree t, ptr, pptr;
00906
00907
00908 align = PARM_BOUNDARY / BITS_PER_UNIT;
00909 rsize = (((int_size_in_bytes (type) + align - 1) / align) * align);
00910
00911 t = build (POSTINCREMENT_EXPR, TREE_TYPE (valist), valist,
00912 build_int_2 ((rsize > 8 ? 4 : rsize), 0));
00913 TREE_SIDE_EFFECTS (t) = 1;
00914
00915 ptr = build_pointer_type (type);
00916
00917
00918 if (rsize > 8)
00919 {
00920 pptr = build_pointer_type (ptr);
00921 t = build1 (NOP_EXPR, pptr, t);
00922 TREE_SIDE_EFFECTS (t) = 1;
00923
00924 t = build1 (INDIRECT_REF, ptr, t);
00925 TREE_SIDE_EFFECTS (t) = 1;
00926 }
00927 else
00928 {
00929 t = build1 (NOP_EXPR, ptr, t);
00930 TREE_SIDE_EFFECTS (t) = 1;
00931 }
00932
00933
00934 return expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
00935 }
00936
00937
00938
00939
00940 rtx
00941 function_arg (cum, mode, type, named)
00942 CUMULATIVE_ARGS *cum;
00943 enum machine_mode mode;
00944 tree type;
00945 int named ATTRIBUTE_UNUSED;
00946 {
00947 rtx result = 0;
00948 int size, align;
00949
00950
00951 int nregs = 2;
00952
00953
00954 if (mode == BLKmode)
00955 size = int_size_in_bytes (type);
00956 else
00957 size = GET_MODE_SIZE (mode);
00958
00959
00960 align = size;
00961
00962 cum->nbytes = (cum->nbytes + 3) & ~3;
00963
00964
00965
00966 if (cum->nbytes > nregs * UNITS_PER_WORD)
00967 return 0;
00968
00969
00970
00971 if (type == NULL_TREE
00972 && cum->nbytes + size > nregs * UNITS_PER_WORD)
00973 return 0;
00974
00975 switch (cum->nbytes / UNITS_PER_WORD)
00976 {
00977 case 0:
00978 result = gen_rtx_REG (mode, 0);
00979 break;
00980 case 1:
00981 result = gen_rtx_REG (mode, 1);
00982 break;
00983 default:
00984 result = 0;
00985 }
00986
00987 return result;
00988 }
00989
00990
00991
00992
00993 int
00994 function_arg_partial_nregs (cum, mode, type, named)
00995 CUMULATIVE_ARGS *cum;
00996 enum machine_mode mode;
00997 tree type;
00998 int named ATTRIBUTE_UNUSED;
00999 {
01000 int size, align;
01001
01002
01003 int nregs = 2;
01004
01005
01006 if (mode == BLKmode)
01007 size = int_size_in_bytes (type);
01008 else
01009 size = GET_MODE_SIZE (mode);
01010
01011
01012 align = size;
01013
01014 cum->nbytes = (cum->nbytes + 3) & ~3;
01015
01016
01017
01018 if (cum->nbytes > nregs * UNITS_PER_WORD)
01019 return 0;
01020
01021 if (cum->nbytes + size <= nregs * UNITS_PER_WORD)
01022 return 0;
01023
01024
01025
01026 if (type == NULL_TREE
01027 && cum->nbytes + size > nregs * UNITS_PER_WORD)
01028 return 0;
01029
01030 return (nregs * UNITS_PER_WORD - cum->nbytes) / UNITS_PER_WORD;
01031 }
01032
01033
01034 const char *
01035 output_tst (operand, insn)
01036 rtx operand, insn;
01037 {
01038 rtx temp;
01039 int past_call = 0;
01040
01041
01042
01043 temp = PREV_INSN (insn);
01044 while (optimize && temp)
01045 {
01046 rtx set;
01047
01048
01049
01050
01051 if (GET_CODE (temp) == CODE_LABEL
01052 || GET_CODE (temp) == JUMP_INSN
01053 || GET_CODE (temp) == BARRIER)
01054 break;
01055
01056 if (GET_CODE (temp) == CALL_INSN)
01057 past_call = 1;
01058
01059 if (GET_CODE (temp) == NOTE)
01060 {
01061 temp = PREV_INSN (temp);
01062 continue;
01063 }
01064
01065
01066 set = single_set (temp);
01067 if (!set)
01068 {
01069 temp = PREV_INSN (temp);
01070 continue;
01071 }
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083 if (REG_P (SET_DEST (set))
01084 && SET_SRC (set) == CONST0_RTX (GET_MODE (SET_DEST (set)))
01085 && !reg_set_between_p (SET_DEST (set), temp, insn)
01086 && (REGNO_REG_CLASS (REGNO (SET_DEST (set)))
01087 == REGNO_REG_CLASS (REGNO (operand)))
01088 && REGNO_REG_CLASS (REGNO (SET_DEST (set))) != EXTENDED_REGS
01089 && REGNO (SET_DEST (set)) != REGNO (operand)
01090 && (!past_call
01091 || !call_used_regs[REGNO (SET_DEST (set))]))
01092 {
01093 rtx xoperands[2];
01094 xoperands[0] = operand;
01095 xoperands[1] = SET_DEST (set);
01096
01097 output_asm_insn ("cmp %1,%0", xoperands);
01098 return "";
01099 }
01100
01101 if (REGNO_REG_CLASS (REGNO (operand)) == EXTENDED_REGS
01102 && REG_P (SET_DEST (set))
01103 && SET_SRC (set) == CONST0_RTX (GET_MODE (SET_DEST (set)))
01104 && !reg_set_between_p (SET_DEST (set), temp, insn)
01105 && (REGNO_REG_CLASS (REGNO (SET_DEST (set)))
01106 != REGNO_REG_CLASS (REGNO (operand)))
01107 && REGNO_REG_CLASS (REGNO (SET_DEST (set))) == EXTENDED_REGS
01108 && REGNO (SET_DEST (set)) != REGNO (operand)
01109 && (!past_call
01110 || !call_used_regs[REGNO (SET_DEST (set))]))
01111 {
01112 rtx xoperands[2];
01113 xoperands[0] = operand;
01114 xoperands[1] = SET_DEST (set);
01115
01116 output_asm_insn ("cmp %1,%0", xoperands);
01117 return "";
01118 }
01119 temp = PREV_INSN (temp);
01120 }
01121 return "cmp 0,%0";
01122 }
01123
01124 int
01125 impossible_plus_operand (op, mode)
01126 rtx op;
01127 enum machine_mode mode ATTRIBUTE_UNUSED;
01128 {
01129 if (GET_CODE (op) != PLUS)
01130 return 0;
01131
01132 if (XEXP (op, 0) == stack_pointer_rtx
01133 || XEXP (op, 1) == stack_pointer_rtx)
01134 return 1;
01135
01136 return 0;
01137 }
01138
01139
01140
01141
01142 int
01143 const_8bit_operand (op, mode)
01144 register rtx op;
01145 enum machine_mode mode ATTRIBUTE_UNUSED;
01146 {
01147 return (GET_CODE (op) == CONST_INT
01148 && INTVAL (op) >= 0
01149 && INTVAL (op) < 256);
01150 }
01151
01152
01153
01154 int
01155 mask_ok_for_mem_btst (len, bit)
01156 int len;
01157 int bit;
01158 {
01159 int mask = 0;
01160
01161 while (len > 0)
01162 {
01163 mask |= (1 << bit);
01164 bit++;
01165 len--;
01166 }
01167
01168
01169 return (((mask & 0xff) == mask)
01170 || ((mask & 0xff00) == mask)
01171 || ((mask & 0xff0000) == mask)
01172 || ((mask & 0xff000000) == mask));
01173 }
01174
01175
01176
01177
01178 int
01179 symbolic_operand (op, mode)
01180 register rtx op;
01181 enum machine_mode mode ATTRIBUTE_UNUSED;
01182 {
01183 switch (GET_CODE (op))
01184 {
01185 case SYMBOL_REF:
01186 case LABEL_REF:
01187 return 1;
01188 case CONST:
01189 op = XEXP (op, 0);
01190 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
01191 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
01192 && GET_CODE (XEXP (op, 1)) == CONST_INT);
01193 default:
01194 return 0;
01195 }
01196 }
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213 rtx
01214 legitimize_address (x, oldx, mode)
01215 rtx x;
01216 rtx oldx ATTRIBUTE_UNUSED;
01217 enum machine_mode mode ATTRIBUTE_UNUSED;
01218 {
01219
01220
01221
01222 if (GET_CODE (x) == PLUS
01223 && symbolic_operand (XEXP (x, 1), VOIDmode))
01224 {
01225
01226
01227
01228
01229 rtx regx1, regy1, regy2, y;
01230
01231
01232 y = XEXP (x, 1);
01233 if (GET_CODE (y) == CONST)
01234 y = XEXP (y, 0);
01235
01236 if (GET_CODE (y) == PLUS || GET_CODE (y) == MINUS)
01237 {
01238 regx1 = force_reg (Pmode, force_operand (XEXP (x, 0), 0));
01239 regy1 = force_reg (Pmode, force_operand (XEXP (y, 0), 0));
01240 regy2 = force_reg (Pmode, force_operand (XEXP (y, 1), 0));
01241 regx1 = force_reg (Pmode,
01242 gen_rtx (GET_CODE (y), Pmode, regx1, regy2));
01243 return force_reg (Pmode, gen_rtx_PLUS (Pmode, regx1, regy1));
01244 }
01245 }
01246 return x;
01247 }
01248
01249 int
01250 mn10300_address_cost (x, unsig)
01251 rtx x;
01252 int *unsig;
01253 {
01254 int _s = 0;
01255 if (unsig == 0)
01256 unsig = &_s;
01257
01258 switch (GET_CODE (x))
01259 {
01260 case REG:
01261 switch (REGNO_REG_CLASS (REGNO (x)))
01262 {
01263 case SP_REGS:
01264 *unsig = 1;
01265 return 0;
01266
01267 case ADDRESS_REGS:
01268 return 1;
01269
01270 case DATA_REGS:
01271 case EXTENDED_REGS:
01272 return 3;
01273
01274 case NO_REGS:
01275 return 5;
01276
01277 default:
01278 abort ();
01279 }
01280
01281 case PLUS:
01282 case MINUS:
01283 case ASHIFT:
01284 case AND:
01285 case IOR:
01286 return (mn10300_address_cost (XEXP (x, 0), unsig)
01287 + mn10300_address_cost (XEXP (x, 1), unsig));
01288
01289 case EXPR_LIST:
01290 case SUBREG:
01291 case MEM:
01292 return ADDRESS_COST (XEXP (x, 0));
01293
01294 case ZERO_EXTEND:
01295 *unsig = 1;
01296 return mn10300_address_cost (XEXP (x, 0), unsig);
01297
01298 case CONST_INT:
01299 if (INTVAL (x) == 0)
01300 return 0;
01301 if (INTVAL (x) + (*unsig ? 0 : 0x80) < 0x100)
01302 return 1;
01303 if (INTVAL (x) + (*unsig ? 0 : 0x8000) < 0x10000)
01304 return 3;
01305 if (INTVAL (x) + (*unsig ? 0 : 0x800000) < 0x1000000)
01306 return 5;
01307 return 7;
01308
01309 case CONST:
01310 case SYMBOL_REF:
01311 case LABEL_REF:
01312 return 8;
01313
01314 case ADDRESSOF:
01315 switch (GET_CODE (XEXP (x, 0)))
01316 {
01317 case MEM:
01318 return ADDRESS_COST (XEXP (x, 0));
01319
01320 case REG:
01321 return 1;
01322
01323 default:
01324 abort ();
01325 }
01326
01327 default:
01328 abort ();
01329
01330 }
01331 }