00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "config.h"
00030 #include "system.h"
00031 #include "flags.h"
00032 #include "rtl.h"
00033 #include "tree.h"
00034 #include "regs.h"
00035 #include "hard-reg-set.h"
00036 #include "real.h"
00037 #include "insn-config.h"
00038 #include "conditions.h"
00039 #include "output.h"
00040 #include "recog.h"
00041 #include "insn-attr.h"
00042 #include "function.h"
00043 #include "expr.h"
00044 #include "tm_p.h"
00045 #include "target.h"
00046 #include "target-def.h"
00047
00048 static rtx find_addr_reg PARAMS ((rtx));
00049 static int reg_clobbered_p PARAMS ((rtx, rtx));
00050 static const char *singlemove_string PARAMS ((rtx *));
00051 static const char *load_opcode PARAMS ((enum machine_mode, const char *, rtx));
00052 static const char *store_opcode PARAMS ((enum machine_mode, const char *, rtx));
00053 static void output_size_for_block_move PARAMS ((rtx, rtx, rtx));
00054 static void i860_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
00055 static void i860_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
00056
00057 #ifndef I860_REG_PREFIX
00058 #define I860_REG_PREFIX ""
00059 #endif
00060
00061 const char *i860_reg_prefix = I860_REG_PREFIX;
00062
00063
00064
00065 rtx i860_compare_op0, i860_compare_op1;
00066
00067
00068 #undef TARGET_ASM_FUNCTION_PROLOGUE
00069 #define TARGET_ASM_FUNCTION_PROLOGUE i860_output_function_prologue
00070 #undef TARGET_ASM_FUNCTION_EPILOGUE
00071 #define TARGET_ASM_FUNCTION_EPILOGUE i860_output_function_epilogue
00072
00073 struct gcc_target targetm = TARGET_INITIALIZER;
00074
00075
00076
00077 int
00078 safe_insn_src_p (op, mode)
00079 rtx op;
00080 enum machine_mode mode;
00081 {
00082
00083
00084
00085
00086 switch (GET_CODE (op))
00087 {
00088 case CONST_INT:
00089 case LABEL_REF:
00090 case SYMBOL_REF:
00091 case CONST:
00092 return 1;
00093
00094 case REG:
00095 return 1;
00096
00097 case MEM:
00098 return CONSTANT_ADDRESS_P (XEXP (op, 0));
00099
00100
00101 case NEG:
00102 return (mode != SFmode && mode != DFmode);
00103 case NOT:
00104 case ZERO_EXTEND:
00105 return 1;
00106
00107 case EQ:
00108 case NE:
00109 case LT:
00110 case GT:
00111 case LE:
00112 case GE:
00113 case LTU:
00114 case GTU:
00115 case LEU:
00116 case GEU:
00117 case MINUS:
00118 case PLUS:
00119 return (mode != SFmode && mode != DFmode);
00120 case AND:
00121 case IOR:
00122 case XOR:
00123 case ASHIFT:
00124 case ASHIFTRT:
00125 case LSHIFTRT:
00126 if ((GET_CODE (XEXP (op, 0)) == CONST_INT && ! SMALL_INT (XEXP (op, 0)))
00127 || (GET_CODE (XEXP (op, 1)) == CONST_INT && ! SMALL_INT (XEXP (op, 1))))
00128 return 0;
00129 return 1;
00130
00131 default:
00132 return 0;
00133 }
00134 }
00135
00136
00137
00138
00139
00140
00141 static int
00142 reg_clobbered_p (reg, in)
00143 rtx reg;
00144 rtx in;
00145 {
00146 register enum rtx_code code;
00147
00148 if (in == 0)
00149 return 0;
00150
00151 code = GET_CODE (in);
00152
00153 if (code == SET || code == CLOBBER)
00154 {
00155 rtx dest = SET_DEST (in);
00156 int set = 0;
00157 int used = 0;
00158
00159 while (GET_CODE (dest) == STRICT_LOW_PART
00160 || GET_CODE (dest) == SUBREG
00161 || GET_CODE (dest) == SIGN_EXTRACT
00162 || GET_CODE (dest) == ZERO_EXTRACT)
00163 dest = XEXP (dest, 0);
00164
00165 if (dest == reg)
00166 set = 1;
00167 else if (GET_CODE (dest) == REG
00168 && refers_to_regno_p (REGNO (reg),
00169 REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
00170 SET_DEST (in), 0))
00171 {
00172 set = 1;
00173
00174
00175
00176
00177 if (dest != SET_DEST (in)
00178 && ! (GET_CODE (SET_DEST (in)) == SUBREG
00179 || UNITS_PER_WORD >= GET_MODE_SIZE (GET_MODE (dest))))
00180 used = 1;
00181 }
00182
00183 if (code == SET)
00184 {
00185 if (set)
00186 used = refers_to_regno_p (REGNO (reg),
00187 REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
00188 SET_SRC (in), 0);
00189 else
00190 used = refers_to_regno_p (REGNO (reg),
00191 REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
00192 in, 0);
00193 }
00194
00195 return set + used * 2;
00196 }
00197
00198 if (refers_to_regno_p (REGNO (reg),
00199 REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
00200 in, 0))
00201 return 2;
00202 return 0;
00203 }
00204
00205
00206
00207
00208
00209 int
00210 operand_clobbered_before_used_after (op, after)
00211 rtx op;
00212 rtx after;
00213 {
00214
00215 if (GET_CODE (op) == CC0)
00216 return 1;
00217 if (GET_CODE (op) == REG)
00218 {
00219 rtx insn;
00220
00221 if (op == stack_pointer_rtx)
00222 return 0;
00223
00224
00225
00226
00227 for (insn = NEXT_INSN (after); insn; insn = NEXT_INSN (insn))
00228 {
00229 if (GET_CODE (insn) == NOTE)
00230 continue;
00231 if (GET_CODE (insn) == INSN
00232 || GET_CODE (insn) == JUMP_INSN
00233 || GET_CODE (insn) == CALL_INSN)
00234 {
00235 switch (reg_clobbered_p (op, PATTERN (insn)))
00236 {
00237 default:
00238 return 0;
00239 case 1:
00240 return 1;
00241 case 0:
00242 break;
00243 }
00244 }
00245
00246
00247 else if (GET_CODE (insn) == CODE_LABEL)
00248 return 0;
00249 if (GET_CODE (insn) == JUMP_INSN)
00250 {
00251 if (condjump_p (insn))
00252 return 0;
00253
00254
00255 if (GET_CODE (PATTERN (insn)) == PARALLEL)
00256 return 0;
00257 if (! JUMP_LABEL (insn))
00258 return 0;
00259
00260 insn = JUMP_LABEL (insn);
00261 }
00262 }
00263 return 1;
00264 }
00265
00266
00267
00268
00269 if (GET_CODE (op) == MEM)
00270 return (CONSTANT_ADDRESS_P (XEXP (op, 0)));
00271
00272 return 0;
00273 }
00274
00275
00276
00277 int
00278 single_insn_src_p (op, mode)
00279 rtx op;
00280 enum machine_mode mode;
00281 {
00282 switch (GET_CODE (op))
00283 {
00284 case CONST_INT:
00285
00286
00287 return 1;
00288
00289 case SYMBOL_REF:
00290 case CONST:
00291
00292
00293 return 1;
00294
00295 case REG:
00296 return 1;
00297
00298 case MEM:
00299 return 1;
00300
00301
00302 case NEG:
00303 return (mode != DFmode);
00304 case NOT:
00305 case ZERO_EXTEND:
00306 return 1;
00307
00308 case PLUS:
00309 case MINUS:
00310
00311 if (CONSTANT_P (XEXP (op, 1))
00312 && !(GET_CODE (XEXP (op, 1)) == CONST_INT
00313 && SMALL_INT (XEXP (op, 1))))
00314 return 0;
00315 case EQ:
00316 case NE:
00317 case LT:
00318 case GT:
00319 case LE:
00320 case GE:
00321 case LTU:
00322 case GTU:
00323 case LEU:
00324 case GEU:
00325
00326
00327 return (mode != SFmode && mode != DFmode);
00328
00329 case AND:
00330 if (GET_CODE (XEXP (op, 1)) == NOT)
00331 {
00332 rtx arg = XEXP (XEXP (op, 1), 0);
00333 if (CONSTANT_P (arg)
00334 && !(GET_CODE (arg) == CONST_INT
00335 && (SMALL_INT (arg)
00336 || (INTVAL (arg) & 0xffff) == 0)))
00337 return 0;
00338 }
00339 case IOR:
00340 case XOR:
00341
00342
00343 if (CONSTANT_P (XEXP (op, 1))
00344 && !(GET_CODE (XEXP (op, 1)) == CONST_INT
00345 && (SMALL_INT (XEXP (op, 1))
00346 || (INTVAL (XEXP (op, 1)) & 0xffff) == 0)))
00347 return 0;
00348
00349 case ASHIFT:
00350 case ASHIFTRT:
00351 case LSHIFTRT:
00352 return 1;
00353
00354 case SUBREG:
00355 if (SUBREG_BYTE (op) != 0)
00356 return 0;
00357 return single_insn_src_p (SUBREG_REG (op), mode);
00358
00359
00360
00361 case FLOAT_EXTEND:
00362 case FLOAT_TRUNCATE:
00363 case FLOAT:
00364 case FIX:
00365 case UNSIGNED_FLOAT:
00366 case UNSIGNED_FIX:
00367 return 0;
00368
00369 default:
00370 return 0;
00371 }
00372 }
00373
00374
00375
00376 int
00377 reg_or_0_operand (op, mode)
00378 rtx op;
00379 enum machine_mode mode;
00380 {
00381 return (op == const0_rtx || register_operand (op, mode)
00382 || op == CONST0_RTX (mode));
00383 }
00384
00385
00386
00387
00388 int
00389 arith_operand (op, mode)
00390 rtx op;
00391 enum machine_mode mode;
00392 {
00393 return (register_operand (op, mode)
00394 || (GET_CODE (op) == CONST_INT && SMALL_INT (op)));
00395 }
00396
00397
00398
00399 int
00400 logic_operand (op, mode)
00401 rtx op;
00402 enum machine_mode mode;
00403 {
00404 return (register_operand (op, mode)
00405 || (GET_CODE (op) == CONST_INT && LOGIC_INT (op)));
00406 }
00407
00408
00409
00410 int
00411 shift_operand (op, mode)
00412 rtx op;
00413 enum machine_mode mode;
00414 {
00415 return (register_operand (op, mode)
00416 || (GET_CODE (op) == CONST_INT));
00417 }
00418
00419
00420
00421
00422 int
00423 compare_operand (op, mode)
00424 rtx op;
00425 enum machine_mode mode;
00426 {
00427 return (register_operand (op, mode)
00428 || (GET_CODE (op) == CONST_INT && SMALL_INT (op) && LOGIC_INT (op)));
00429 }
00430
00431
00432
00433
00434 int
00435 bte_operand (op, mode)
00436 rtx op;
00437 enum machine_mode mode;
00438 {
00439 return (register_operand (op, mode)
00440 || (GET_CODE (op) == CONST_INT
00441 && (unsigned) INTVAL (op) < 0x20));
00442 }
00443
00444
00445
00446 int
00447 indexed_operand (op, mode)
00448 rtx op;
00449 enum machine_mode mode;
00450 {
00451 return (GET_CODE (op) == MEM && GET_MODE (op) == mode
00452 && GET_CODE (XEXP (op, 0)) == PLUS
00453 && GET_MODE (XEXP (op, 0)) == SImode
00454 && register_operand (XEXP (XEXP (op, 0), 0), SImode)
00455 && register_operand (XEXP (XEXP (op, 0), 1), SImode));
00456 }
00457
00458
00459
00460
00461 int
00462 load_operand (op, mode)
00463 rtx op;
00464 enum machine_mode mode;
00465 {
00466 return (memory_operand (op, mode) || indexed_operand (op, mode));
00467 }
00468
00469
00470
00471
00472 int
00473 small_int (op, mode)
00474 rtx op;
00475 enum machine_mode mode ATTRIBUTE_UNUSED;
00476 {
00477 return (GET_CODE (op) == CONST_INT && SMALL_INT (op));
00478 }
00479
00480
00481
00482
00483 int
00484 logic_int (op, mode)
00485 rtx op;
00486 enum machine_mode mode ATTRIBUTE_UNUSED;
00487 {
00488 return (GET_CODE (op) == CONST_INT && LOGIC_INT (op));
00489 }
00490
00491
00492
00493
00494
00495
00496 int
00497 call_insn_operand (op, mode)
00498 rtx op;
00499 enum machine_mode mode ATTRIBUTE_UNUSED;
00500 {
00501 if (GET_CODE (op) == MEM
00502 && (CONSTANT_ADDRESS_P (XEXP (op, 0))
00503 || (GET_CODE (XEXP (op, 0)) == REG
00504 && XEXP (op, 0) != arg_pointer_rtx
00505 && !(REGNO (XEXP (op, 0)) >= FIRST_PSEUDO_REGISTER
00506 && REGNO (XEXP (op, 0)) <= LAST_VIRTUAL_REGISTER))))
00507 return 1;
00508 return 0;
00509 }
00510
00511
00512
00513
00514 static const char *
00515 singlemove_string (operands)
00516 rtx *operands;
00517 {
00518 if (GET_CODE (operands[0]) == MEM)
00519 {
00520 if (GET_CODE (operands[1]) != MEM)
00521 if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
00522 {
00523 if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
00524 && (cc_prev_status.flags & CC_HI_R31_ADJ)
00525 && cc_prev_status.mdep == XEXP (operands[0], 0)))
00526 {
00527 CC_STATUS_INIT;
00528 output_asm_insn ("orh %h0,%?r0,%?r31", operands);
00529 }
00530 cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
00531 cc_status.mdep = XEXP (operands[0], 0);
00532 return "st.l %r1,%L0(%?r31)";
00533 }
00534 else
00535 return "st.l %r1,%0";
00536 else
00537 abort ();
00538 #if 0
00539 {
00540 rtx xoperands[2];
00541
00542 cc_status.flags &= ~CC_F0_IS_0;
00543 xoperands[0] = gen_rtx_REG (SFmode, 32);
00544 xoperands[1] = operands[1];
00545 output_asm_insn (singlemove_string (xoperands), xoperands);
00546 xoperands[1] = xoperands[0];
00547 xoperands[0] = operands[0];
00548 output_asm_insn (singlemove_string (xoperands), xoperands);
00549 return "";
00550 }
00551 #endif
00552 }
00553 if (GET_CODE (operands[1]) == MEM)
00554 {
00555 if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
00556 {
00557 if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
00558 && (cc_prev_status.flags & CC_HI_R31_ADJ)
00559 && cc_prev_status.mdep == XEXP (operands[1], 0)))
00560 {
00561 CC_STATUS_INIT;
00562 output_asm_insn ("orh %h1,%?r0,%?r31", operands);
00563 }
00564 cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
00565 cc_status.mdep = XEXP (operands[1], 0);
00566 return "ld.l %L1(%?r31),%0";
00567 }
00568 return "ld.l %m1,%0";
00569 }
00570 if (GET_CODE (operands[1]) == CONST_INT)
00571 {
00572 if (operands[1] == const0_rtx)
00573 return "mov %?r0,%0";
00574 if((INTVAL (operands[1]) & 0xffff0000) == 0)
00575 return "or %L1,%?r0,%0";
00576 if((INTVAL (operands[1]) & 0xffff8000) == 0xffff8000)
00577 return "adds %1,%?r0,%0";
00578 if((INTVAL (operands[1]) & 0x0000ffff) == 0)
00579 return "orh %H1,%?r0,%0";
00580
00581 return "orh %H1,%?r0,%0\n\tor %L1,%0,%0";
00582 }
00583 return "mov %1,%0";
00584 }
00585
00586
00587
00588
00589 const char *
00590 output_move_double (operands)
00591 rtx *operands;
00592 {
00593 enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
00594 rtx latehalf[2];
00595 rtx addreg0 = 0, addreg1 = 0;
00596 int highest_first = 0;
00597 int no_addreg1_decrement = 0;
00598
00599
00600
00601 if (REG_P (operands[0]))
00602 optype0 = REGOP;
00603 else if (offsettable_memref_p (operands[0]))
00604 optype0 = OFFSOP;
00605 else if (GET_CODE (operands[0]) == MEM)
00606 optype0 = MEMOP;
00607 else
00608 optype0 = RNDOP;
00609
00610 if (REG_P (operands[1]))
00611 optype1 = REGOP;
00612 else if (CONSTANT_P (operands[1]))
00613 optype1 = CNSTOP;
00614 else if (offsettable_memref_p (operands[1]))
00615 optype1 = OFFSOP;
00616 else if (GET_CODE (operands[1]) == MEM)
00617 optype1 = MEMOP;
00618 else
00619 optype1 = RNDOP;
00620
00621
00622
00623
00624
00625 if (optype0 == RNDOP || optype1 == RNDOP)
00626 abort ();
00627
00628
00629
00630
00631 if (optype0 == MEMOP)
00632 addreg0 = find_addr_reg (XEXP (operands[0], 0));
00633
00634 if (optype1 == MEMOP)
00635 addreg1 = find_addr_reg (XEXP (operands[1], 0));
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649 if (optype0 == REGOP)
00650 latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
00651 else if (optype0 == OFFSOP)
00652 latehalf[0] = adjust_address (operands[0], SImode, 4);
00653 else
00654 latehalf[0] = operands[0];
00655
00656 if (optype1 == REGOP)
00657 latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
00658 else if (optype1 == OFFSOP)
00659 latehalf[1] = adjust_address (operands[1], SImode, 4);
00660 else if (optype1 == CNSTOP)
00661 {
00662 if (GET_CODE (operands[1]) == CONST_DOUBLE)
00663 split_double (operands[1], &operands[1], &latehalf[1]);
00664 else if (CONSTANT_P (operands[1]))
00665 latehalf[1] = const0_rtx;
00666 }
00667 else
00668 latehalf[1] = operands[1];
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681 if (optype0 == REGOP && optype1 == REGOP
00682 && REGNO (operands[0]) == REGNO (latehalf[1]))
00683 {
00684 CC_STATUS_PARTIAL_INIT;
00685
00686 if (addreg0)
00687 output_asm_insn ("adds 0x4,%0,%0", &addreg0);
00688 if (addreg1)
00689 output_asm_insn ("adds 0x4,%0,%0", &addreg1);
00690
00691
00692 output_asm_insn (singlemove_string (latehalf), latehalf);
00693
00694
00695 if (addreg0)
00696 output_asm_insn ("adds -0x4,%0,%0", &addreg0);
00697 if (addreg1)
00698 output_asm_insn ("adds -0x4,%0,%0", &addreg1);
00699
00700
00701 return singlemove_string (operands);
00702 }
00703 else if (optype0 == REGOP && optype1 != REGOP
00704 && reg_overlap_mentioned_p (operands[0], operands[1]))
00705 {
00706
00707
00708
00709 if (reg_mentioned_p (operands[0], XEXP (operands[1], 0))
00710 && reg_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
00711 {
00712 rtx xops[2];
00713 xops[0] = latehalf[0];
00714 xops[1] = operands[0];
00715 output_asm_insn ("adds %1,%0,%1", xops);
00716 operands[1] = gen_rtx_MEM (DImode, operands[0]);
00717 latehalf[1] = adjust_address (operands[1], SImode, 4);
00718 addreg1 = 0;
00719 highest_first = 1;
00720 }
00721
00722
00723
00724 else if (! reg_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
00725 highest_first = 1;
00726
00727
00728
00729
00730
00731 else if (addreg1 && reg_mentioned_p (addreg1, latehalf[0]))
00732 no_addreg1_decrement = 1;
00733 }
00734
00735
00736
00737
00738 if (! highest_first)
00739 output_asm_insn (singlemove_string (operands), operands);
00740
00741 CC_STATUS_PARTIAL_INIT;
00742
00743 if (addreg0)
00744 output_asm_insn ("adds 0x4,%0,%0", &addreg0);
00745 if (addreg1)
00746 output_asm_insn ("adds 0x4,%0,%0", &addreg1);
00747
00748
00749 output_asm_insn (singlemove_string (latehalf), latehalf);
00750
00751
00752 if (addreg0)
00753 output_asm_insn ("adds -0x4,%0,%0", &addreg0);
00754 if (addreg1 && !no_addreg1_decrement)
00755 output_asm_insn ("adds -0x4,%0,%0", &addreg1);
00756
00757 if (highest_first)
00758 output_asm_insn (singlemove_string (operands), operands);
00759
00760 return "";
00761 }
00762
00763 const char *
00764 output_fp_move_double (operands)
00765 rtx *operands;
00766 {
00767
00768
00769 if (operands[1] == CONST0_RTX (GET_MODE (operands[1])))
00770 operands[1] = gen_rtx_REG (DFmode, F0_REGNUM);
00771
00772 if (FP_REG_P (operands[0]))
00773 {
00774 if (FP_REG_P (operands[1]))
00775 return "fmov.dd %1,%0";
00776 if (GET_CODE (operands[1]) == REG)
00777 {
00778 output_asm_insn ("ixfr %1,%0", operands);
00779 operands[0] = gen_rtx_REG (VOIDmode, REGNO (operands[0]) + 1);
00780 operands[1] = gen_rtx_REG (VOIDmode, REGNO (operands[1]) + 1);
00781 return "ixfr %1,%0";
00782 }
00783 if (operands[1] == CONST0_RTX (DFmode))
00784 return "fmov.dd f0,%0";
00785 if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
00786 {
00787 if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
00788 && (cc_prev_status.flags & CC_HI_R31_ADJ)
00789 && cc_prev_status.mdep == XEXP (operands[1], 0)))
00790 {
00791 CC_STATUS_INIT;
00792 output_asm_insn ("orh %h1,%?r0,%?r31", operands);
00793 }
00794 cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
00795 cc_status.mdep = XEXP (operands[1], 0);
00796 return "fld.d %L1(%?r31),%0";
00797 }
00798 return "fld.d %1,%0";
00799 }
00800 else if (FP_REG_P (operands[1]))
00801 {
00802 if (GET_CODE (operands[0]) == REG)
00803 {
00804 output_asm_insn ("fxfr %1,%0", operands);
00805 operands[0] = gen_rtx_REG (VOIDmode, REGNO (operands[0]) + 1);
00806 operands[1] = gen_rtx_REG (VOIDmode, REGNO (operands[1]) + 1);
00807 return "fxfr %1,%0";
00808 }
00809 if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
00810 {
00811 if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
00812 && (cc_prev_status.flags & CC_HI_R31_ADJ)
00813 && cc_prev_status.mdep == XEXP (operands[0], 0)))
00814 {
00815 CC_STATUS_INIT;
00816 output_asm_insn ("orh %h0,%?r0,%?r31", operands);
00817 }
00818 cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
00819 cc_status.mdep = XEXP (operands[0], 0);
00820 return "fst.d %1,%L0(%?r31)";
00821 }
00822 return "fst.d %1,%0";
00823 }
00824 else
00825 abort ();
00826
00827 return NULL;
00828 }
00829
00830
00831
00832
00833 static rtx
00834 find_addr_reg (addr)
00835 rtx addr;
00836 {
00837 while (GET_CODE (addr) == PLUS)
00838 {
00839 if (GET_CODE (XEXP (addr, 0)) == REG)
00840 addr = XEXP (addr, 0);
00841 else if (GET_CODE (XEXP (addr, 1)) == REG)
00842 addr = XEXP (addr, 1);
00843 else if (CONSTANT_P (XEXP (addr, 0)))
00844 addr = XEXP (addr, 1);
00845 else if (CONSTANT_P (XEXP (addr, 1)))
00846 addr = XEXP (addr, 0);
00847 else
00848 abort ();
00849 }
00850 if (GET_CODE (addr) == REG)
00851 return addr;
00852 abort ();
00853
00854 return NULL;
00855 }
00856
00857
00858
00859
00860
00861
00862 static const char *
00863 load_opcode (mode, args, reg)
00864 enum machine_mode mode;
00865 const char *args;
00866 rtx reg;
00867 {
00868 static char buf[30];
00869 const char *opcode;
00870
00871 switch (mode)
00872 {
00873 case QImode:
00874 opcode = "ld.b";
00875 break;
00876
00877 case HImode:
00878 opcode = "ld.s";
00879 break;
00880
00881 case SImode:
00882 case SFmode:
00883 if (FP_REG_P (reg))
00884 opcode = "fld.l";
00885 else
00886 opcode = "ld.l";
00887 break;
00888
00889 case DImode:
00890 if (!FP_REG_P (reg))
00891 abort ();
00892 case DFmode:
00893 opcode = "fld.d";
00894 break;
00895
00896 default:
00897 abort ();
00898 }
00899
00900 sprintf (buf, "%s %s", opcode, args);
00901 return buf;
00902 }
00903
00904
00905
00906
00907
00908
00909 static const char *
00910 store_opcode (mode, args, reg)
00911 enum machine_mode mode;
00912 const char *args;
00913 rtx reg;
00914 {
00915 static char buf[30];
00916 const char *opcode;
00917
00918 switch (mode)
00919 {
00920 case QImode:
00921 opcode = "st.b";
00922 break;
00923
00924 case HImode:
00925 opcode = "st.s";
00926 break;
00927
00928 case SImode:
00929 case SFmode:
00930 if (FP_REG_P (reg))
00931 opcode = "fst.l";
00932 else
00933 opcode = "st.l";
00934 break;
00935
00936 case DImode:
00937 if (!FP_REG_P (reg))
00938 abort ();
00939 case DFmode:
00940 opcode = "fst.d";
00941 break;
00942
00943 default:
00944 abort ();
00945 }
00946
00947 sprintf (buf, "%s %s", opcode, args);
00948 return buf;
00949 }
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960 const char *
00961 output_store (operands)
00962 rtx *operands;
00963 {
00964 enum machine_mode mode = GET_MODE (operands[0]);
00965 rtx address = XEXP (operands[0], 0);
00966
00967 cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
00968 cc_status.mdep = address;
00969
00970 if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
00971 && (cc_prev_status.flags & CC_HI_R31_ADJ)
00972 && address == cc_prev_status.mdep))
00973 {
00974 CC_STATUS_INIT;
00975 output_asm_insn ("orh %h0,%?r0,%?r31", operands);
00976 cc_prev_status.mdep = address;
00977 }
00978
00979
00980 if (mode == DFmode && operands[1] == CONST0_RTX (DFmode))
00981 return store_opcode (DFmode, "%r1,%L0(%?r31)", operands[1]);
00982
00983
00984
00985 if ((mode == DImode || mode == DFmode)
00986 && ! FP_REG_P (operands[1]))
00987 return output_move_double (operands);
00988
00989 return store_opcode (mode, "%r1,%L0(%?r31)", operands[1]);
00990 }
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001 const char *
01002 output_load (operands)
01003 rtx *operands;
01004 {
01005 enum machine_mode mode = GET_MODE (operands[0]);
01006 rtx address = XEXP (operands[1], 0);
01007
01008
01009
01010
01011 cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
01012 cc_status.mdep = address;
01013
01014 if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
01015 && (cc_prev_status.flags & CC_HI_R31_ADJ)
01016 && address == cc_prev_status.mdep
01017 && cc_prev_status.mdep == cc_status.mdep))
01018 {
01019 CC_STATUS_INIT;
01020 output_asm_insn ("orh %h1,%?r0,%?r31", operands);
01021 cc_prev_status.mdep = address;
01022 }
01023
01024
01025
01026 if ((mode == DImode || mode == DFmode)
01027 && ! FP_REG_P (operands[0]))
01028 return output_move_double (operands);
01029
01030 return load_opcode (mode, "%L1(%?r31),%0", operands[0]);
01031 }
01032
01033 #if 0
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048 void
01049 output_load_address (operands)
01050 rtx *operands;
01051 {
01052 rtx base, offset;
01053
01054 if (CONSTANT_P (operands[3]))
01055 {
01056 output_asm_insn ("mov %3,%0", operands);
01057 return;
01058 }
01059
01060 if (REG_P (operands[3]))
01061 {
01062 if (REGNO (operands[0]) != REGNO (operands[3]))
01063 output_asm_insn ("shl %?r0,%3,%0", operands);
01064 return;
01065 }
01066
01067 if (GET_CODE (operands[3]) != PLUS)
01068 abort ();
01069
01070 base = XEXP (operands[3], 0);
01071 offset = XEXP (operands[3], 1);
01072
01073 if (GET_CODE (base) == CONST_INT)
01074 {
01075 rtx tmp = base;
01076 base = offset;
01077 offset = tmp;
01078 }
01079
01080 if (GET_CODE (offset) != CONST_INT)
01081 {
01082
01083 base = operands[3];
01084 offset = const0_rtx;
01085 }
01086
01087 if (REG_P (base))
01088 {
01089 operands[6] = base;
01090 operands[7] = offset;
01091 CC_STATUS_PARTIAL_INIT;
01092 if (SMALL_INT (offset))
01093 output_asm_insn ("adds %7,%6,%0", operands);
01094 else
01095 output_asm_insn ("mov %7,%0\n\tadds %0,%6,%0", operands);
01096 }
01097 else if (GET_CODE (base) == PLUS)
01098 {
01099 operands[6] = XEXP (base, 0);
01100 operands[7] = XEXP (base, 1);
01101 operands[8] = offset;
01102
01103 CC_STATUS_PARTIAL_INIT;
01104 if (SMALL_INT (offset))
01105 output_asm_insn ("adds %6,%7,%0\n\tadds %8,%0,%0", operands);
01106 else
01107 output_asm_insn ("mov %8,%0\n\tadds %0,%6,%0\n\tadds %0,%7,%0", operands);
01108 }
01109 else
01110 abort ();
01111 }
01112 #endif
01113
01114
01115
01116
01117
01118
01119
01120 static void
01121 output_size_for_block_move (size, reg, align)
01122 rtx size, reg, align;
01123 {
01124 rtx xoperands[3];
01125
01126 xoperands[0] = reg;
01127 xoperands[1] = size;
01128 xoperands[2] = align;
01129
01130 #if 1
01131 cc_status.flags &= ~ CC_KNOW_HI_R31;
01132 output_asm_insn (singlemove_string (xoperands), xoperands);
01133 #else
01134 if (GET_CODE (size) == REG)
01135 output_asm_insn ("sub %2,%1,%0", xoperands);
01136 else
01137 {
01138 xoperands[1] = GEN_INT (INTVAL (size) - INTVAL (align));
01139 cc_status.flags &= ~ CC_KNOW_HI_R31;
01140 output_asm_insn ("mov %1,%0", xoperands);
01141 }
01142 #endif
01143 }
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153 const char *
01154 output_block_move (operands)
01155 rtx *operands;
01156 {
01157
01158
01159 rtx xoperands[10];
01160 #if 0
01161 rtx zoperands[10];
01162 #endif
01163 static int movstrsi_label = 0;
01164 int i;
01165 rtx temp1 = operands[4];
01166 rtx alignrtx = operands[3];
01167 int align = INTVAL (alignrtx);
01168 int chunk_size;
01169
01170 xoperands[0] = operands[0];
01171 xoperands[1] = operands[1];
01172 xoperands[2] = temp1;
01173
01174
01175
01176 if (align > 4)
01177 {
01178 align = 4;
01179 alignrtx = GEN_INT (4);
01180 }
01181
01182
01183
01184
01185
01186
01187
01188
01189 if (GET_CODE (operands[2]) == CONST_INT
01190 && ! CONSTANT_ADDRESS_P (operands[0])
01191 && ! CONSTANT_ADDRESS_P (operands[1]))
01192 {
01193 int size = INTVAL (operands[2]);
01194 rtx op0 = xoperands[0];
01195 rtx op1 = xoperands[1];
01196
01197 if ((align & 3) == 0 && (size & 3) == 0 && (size >> 2) <= 16)
01198 {
01199 if (memory_address_p (SImode, plus_constant (op0, size))
01200 && memory_address_p (SImode, plus_constant (op1, size)))
01201 {
01202 cc_status.flags &= ~CC_KNOW_HI_R31;
01203 for (i = (size>>2)-1; i >= 0; i--)
01204 {
01205 xoperands[0] = plus_constant (op0, i * 4);
01206 xoperands[1] = plus_constant (op1, i * 4);
01207 output_asm_insn ("ld.l %a1,%?r31\n\tst.l %?r31,%a0",
01208 xoperands);
01209 }
01210 return "";
01211 }
01212 }
01213 else if ((align & 1) == 0 && (size & 1) == 0 && (size >> 1) <= 16)
01214 {
01215 if (memory_address_p (HImode, plus_constant (op0, size))
01216 && memory_address_p (HImode, plus_constant (op1, size)))
01217 {
01218 cc_status.flags &= ~CC_KNOW_HI_R31;
01219 for (i = (size>>1)-1; i >= 0; i--)
01220 {
01221 xoperands[0] = plus_constant (op0, i * 2);
01222 xoperands[1] = plus_constant (op1, i * 2);
01223 output_asm_insn ("ld.s %a1,%?r31\n\tst.s %?r31,%a0",
01224 xoperands);
01225 }
01226 return "";
01227 }
01228 }
01229 else if (size <= 16)
01230 {
01231 if (memory_address_p (QImode, plus_constant (op0, size))
01232 && memory_address_p (QImode, plus_constant (op1, size)))
01233 {
01234 cc_status.flags &= ~CC_KNOW_HI_R31;
01235 for (i = size-1; i >= 0; i--)
01236 {
01237 xoperands[0] = plus_constant (op0, i);
01238 xoperands[1] = plus_constant (op1, i);
01239 output_asm_insn ("ld.b %a1,%?r31\n\tst.b %?r31,%a0",
01240 xoperands);
01241 }
01242 return "";
01243 }
01244 }
01245 }
01246
01247
01248 CC_STATUS_INIT;
01249
01250
01251
01252
01253 output_size_for_block_move (operands[2], operands[4], alignrtx);
01254
01255 #if 0
01256
01257 zoperands[0] = operands[0];
01258 zoperands[3] = plus_constant (operands[0], align);
01259 output_load_address (zoperands);
01260 #endif
01261
01262
01263
01264 xoperands[3] = GEN_INT (movstrsi_label++);
01265
01266
01267
01268 #if 0
01269 if ((align & 3) == 0)
01270 chunk_size = 4;
01271 else if ((align & 1) == 0)
01272 chunk_size = 2;
01273 else
01274 #endif
01275 chunk_size = 1;
01276
01277
01278
01279 xoperands[4] = GEN_INT (- chunk_size);
01280 xoperands[5] = operands[5];
01281 output_asm_insn ("adds %4,%?r0,%5", xoperands);
01282
01283
01284
01285
01286
01287
01288 output_asm_insn ("adds %5,%2,%2", xoperands);
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300 output_asm_insn ("bc .Le%3", xoperands);
01301
01302
01303
01304 xoperands[6] = operands[6];
01305
01306
01307
01308
01309
01310 output_asm_insn ("subs %1,%5,%1", xoperands);
01311 output_asm_insn ("bla %5,%2,.Lm%3", xoperands);
01312 output_asm_insn ("adds %0,%2,%6", xoperands);
01313 output_asm_insn ("\n.Lm%3:", xoperands);
01314 output_asm_insn ("\n.Ls%3:", xoperands);
01315 output_asm_insn ("adds %5,%6,%6", xoperands);
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326 if (chunk_size == 4)
01327 {
01328 output_asm_insn ("ld.l %2(%1),%?r31", xoperands);
01329 output_asm_insn ("bla %5,%2,.Ls%3", xoperands);
01330 output_asm_insn ("st.l %?r31,8(%6)", xoperands);
01331 }
01332 else if (chunk_size == 2)
01333 {
01334 output_asm_insn ("ld.s %2(%1),%?r31", xoperands);
01335 output_asm_insn ("bla %5,%2,.Ls%3", xoperands);
01336 output_asm_insn ("st.s %?r31,4(%6)", xoperands);
01337 }
01338 else
01339 {
01340 output_asm_insn ("ld.b %2(%1),%?r31", xoperands);
01341 output_asm_insn ("bla %5,%2,.Ls%3", xoperands);
01342 output_asm_insn ("st.b %?r31,2(%6)", xoperands);
01343 }
01344 output_asm_insn ("\n.Le%3:", xoperands);
01345
01346 return "";
01347 }
01348
01349 #if 0
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374 const char *
01375 output_delayed_branch (template, operands, insn)
01376 const char *template;
01377 rtx *operands;
01378 rtx insn;
01379 {
01380 rtx src = XVECEXP (PATTERN (insn), 0, 1);
01381 rtx dest = XVECEXP (PATTERN (insn), 0, 0);
01382
01383
01384
01385
01386
01387
01388
01389 if ( (GET_CODE (src) == CONST_INT
01390 && ((unsigned) INTVAL (src) & (unsigned) 0xffff0000) != (unsigned) 0)
01391 || (GET_CODE (src) == SYMBOL_REF)
01392 || (GET_CODE (src) == LABEL_REF)
01393 || (GET_CODE (src) == CONST))
01394 {
01395 rtx xoperands[2];
01396 xoperands[0] = dest;
01397 xoperands[1] = src;
01398
01399 CC_STATUS_PARTIAL_INIT;
01400
01401 output_asm_insn ("orh %H1,%?r0,%0", xoperands);
01402
01403
01404 output_asm_insn (template, operands);
01405
01406
01407 output_asm_insn ("or %L1,%0,%0", xoperands);
01408 }
01409 else if ((GET_CODE (src) == MEM
01410 && CONSTANT_ADDRESS_P (XEXP (src, 0)))
01411 || (GET_CODE (dest) == MEM
01412 && CONSTANT_ADDRESS_P (XEXP (dest, 0))))
01413 {
01414 rtx xoperands[2];
01415 const char *split_template;
01416 xoperands[0] = dest;
01417 xoperands[1] = src;
01418
01419
01420 if (GET_CODE (src) == MEM)
01421 {
01422 if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
01423 && (cc_prev_status.flags & CC_HI_R31_ADJ)
01424 && cc_prev_status.mdep == XEXP (operands[1], 0)))
01425 {
01426 CC_STATUS_INIT;
01427 output_asm_insn ("orh %h1,%?r0,%?r31", xoperands);
01428 }
01429 split_template = load_opcode (GET_MODE (dest),
01430 "%L1(%?r31),%0", dest);
01431 }
01432 else
01433 {
01434 if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
01435 && (cc_prev_status.flags & CC_HI_R31_ADJ)
01436 && cc_prev_status.mdep == XEXP (operands[0], 0)))
01437 {
01438 CC_STATUS_INIT;
01439 output_asm_insn ("orh %h0,%?r0,%?r31", xoperands);
01440 }
01441 split_template = store_opcode (GET_MODE (dest),
01442 "%r1,%L0(%?r31)", src);
01443 }
01444
01445
01446 output_asm_insn (template, operands);
01447
01448
01449
01450 output_asm_insn (split_template, xoperands);
01451 }
01452 else
01453 {
01454 int insn_code_number;
01455 rtx pat = gen_rtx_SET (VOIDmode, dest, src);
01456 rtx delay_insn = gen_rtx_INSN (VOIDmode, 0, 0, 0, pat, -1, 0, 0);
01457 int i;
01458
01459
01460 output_asm_insn (template, operands);
01461
01462
01463
01464
01465 INSN_CODE (delay_insn) = insn_code_number
01466 = recog (pat, delay_insn, NULL);
01467 if (insn_code_number == -1)
01468 abort ();
01469
01470 for (i = 0; i < insn_data[insn_code_number].n_operands; i++)
01471 {
01472 if (GET_CODE (recog_data.operand[i]) == SUBREG)
01473 alter_subreg (&recog_data.operand[i]);
01474 }
01475
01476 insn_extract (delay_insn);
01477 if (! constrain_operands (1))
01478 fatal_insn_not_found (delay_insn);
01479
01480 template = get_insn_template (insn_code_number, delay_insn);
01481 output_asm_insn (template, recog_data.operand);
01482 }
01483 CC_STATUS_INIT;
01484 return "";
01485 }
01486
01487
01488 const char *
01489 output_delay_insn (delay_insn)
01490 rtx delay_insn;
01491 {
01492 const char *template;
01493 int insn_code_number;
01494 int i;
01495
01496
01497
01498
01499 insn_code_number = recog_memoized (delay_insn);
01500 if (insn_code_number == -1)
01501 abort ();
01502
01503
01504 INSN_CODE (delay_insn) = insn_code_number;
01505 insn_extract (delay_insn);
01506
01507
01508
01509
01510
01511 for (i = 0; i < insn_data[insn_code_number].n_operands; i++)
01512 {
01513 if (GET_CODE (recog_data.operand[i]) == SUBREG)
01514 alter_subreg (&recog_data.operand[i]);
01515 }
01516
01517 if (! constrain_operands (1))
01518 abort ();
01519
01520 cc_prev_status = cc_status;
01521
01522
01523
01524
01525
01526
01527 NOTICE_UPDATE_CC (PATTERN (delay_insn), delay_insn);
01528
01529
01530
01531
01532 template = get_insn_template (insn_code_number, delay_insn);
01533 output_asm_insn (template, recog_data.operand);
01534 return "";
01535 }
01536 #endif
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547 unsigned long
01548 sfmode_constant_to_ulong (x)
01549 rtx x;
01550 {
01551 REAL_VALUE_TYPE d;
01552 union { float f; unsigned long i; } u2;
01553
01554 if (GET_CODE (x) != CONST_DOUBLE || GET_MODE (x) != SFmode)
01555 abort ();
01556
01557 #if TARGET_FLOAT_FORMAT != HOST_FLOAT_FORMAT
01558 error IEEE emulation needed
01559 #endif
01560 REAL_VALUE_FROM_CONST_DOUBLE (d, x);
01561 u2.f = d;
01562 return u2.i;
01563 }
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660 #ifndef STACK_ALIGNMENT
01661 #define STACK_ALIGNMENT 16
01662 #endif
01663
01664 const char *current_function_original_name;
01665
01666 static int must_preserve_r1;
01667 static unsigned must_preserve_bytes;
01668
01669 static void
01670 i860_output_function_prologue (asm_file, local_bytes)
01671 register FILE *asm_file;
01672 register HOST_WIDE_INT local_bytes;
01673 {
01674 register HOST_WIDE_INT frame_lower_bytes;
01675 register HOST_WIDE_INT frame_upper_bytes;
01676 register HOST_WIDE_INT total_fsize;
01677 register unsigned preserved_reg_bytes = 0;
01678 register unsigned i;
01679 register unsigned preserved_so_far = 0;
01680
01681 must_preserve_r1 = (optimize < 2 || ! leaf_function_p ());
01682 must_preserve_bytes = 4 + (must_preserve_r1 ? 4 : 0);
01683
01684
01685
01686
01687 for (i = 1; i < FIRST_PSEUDO_REGISTER; i++)
01688 {
01689 if (regs_ever_live[i] && ! call_used_regs[i])
01690 preserved_reg_bytes += 4;
01691 }
01692
01693
01694
01695 frame_lower_bytes = (local_bytes + STACK_ALIGNMENT - 1) & -STACK_ALIGNMENT;
01696
01697
01698
01699
01700
01701 frame_upper_bytes = must_preserve_bytes + preserved_reg_bytes;
01702
01703
01704
01705 frame_upper_bytes
01706 = (frame_upper_bytes + STACK_ALIGNMENT - 1) & -STACK_ALIGNMENT;
01707
01708 total_fsize = frame_upper_bytes + frame_lower_bytes;
01709
01710 #ifndef I860_STRICT_ABI_PROLOGUES
01711
01712
01713
01714
01715
01716
01717
01718 if (total_fsize > 0x7fff)
01719 {
01720
01721
01722
01723 fprintf (asm_file, "\taddu -%d,%ssp,%ssp\n",
01724 frame_upper_bytes, i860_reg_prefix, i860_reg_prefix);
01725
01726
01727
01728 fprintf (asm_file, "\tst.l %sfp,0(%ssp)\n",
01729 i860_reg_prefix, i860_reg_prefix);
01730
01731
01732
01733
01734
01735 fprintf (asm_file, "\taddu 0,%ssp,%sfp\n",
01736 i860_reg_prefix, i860_reg_prefix);
01737
01738
01739
01740 fprintf (asm_file, "\torh %d,%sr0,%sr31\n",
01741 frame_lower_bytes >> 16, i860_reg_prefix, i860_reg_prefix);
01742 fprintf (asm_file, "\tor %d,%sr31,%sr31\n",
01743 frame_lower_bytes & 0xffff, i860_reg_prefix, i860_reg_prefix);
01744
01745
01746
01747
01748 fprintf (asm_file, "\tsubu %ssp,%sr31,%ssp\n",
01749 i860_reg_prefix, i860_reg_prefix, i860_reg_prefix);
01750
01751
01752
01753
01754
01755 for (i = 1; i < 32; i++)
01756 if (regs_ever_live[i] && ! call_used_regs[i])
01757 fprintf (asm_file, "\tst.l %s%s,%d(%sfp)\n",
01758 i860_reg_prefix, reg_names[i],
01759 must_preserve_bytes + (4 * preserved_so_far++),
01760 i860_reg_prefix);
01761
01762 for (i = 32; i < 64; i++)
01763 if (regs_ever_live[i] && ! call_used_regs[i])
01764 fprintf (asm_file, "\tfst.l %s%s,%d(%sfp)\n",
01765 i860_reg_prefix, reg_names[i],
01766 must_preserve_bytes + (4 * preserved_so_far++),
01767 i860_reg_prefix);
01768
01769
01770
01771 if (must_preserve_r1)
01772 fprintf (asm_file, "\tst.l %sr1,4(%sfp)\n",
01773 i860_reg_prefix, i860_reg_prefix);
01774 }
01775 else
01776 {
01777
01778
01779
01780 fprintf (asm_file, "\taddu -%d,%ssp,%ssp\n",
01781 total_fsize, i860_reg_prefix, i860_reg_prefix);
01782
01783
01784
01785 fprintf (asm_file, "\tst.l %sfp,%d(%ssp)\n",
01786 i860_reg_prefix, frame_lower_bytes, i860_reg_prefix);
01787
01788
01789
01790
01791
01792
01793 fprintf (asm_file, "\taddu %d,%ssp,%sfp\n",
01794 frame_lower_bytes, i860_reg_prefix, i860_reg_prefix);
01795
01796
01797
01798
01799
01800 for (i = 1; i < 32; i++)
01801 if (regs_ever_live[i] && ! call_used_regs[i])
01802 fprintf (asm_file, "\tst.l %s%s,%d(%sfp)\n",
01803 i860_reg_prefix, reg_names[i],
01804 must_preserve_bytes + (4 * preserved_so_far++),
01805 i860_reg_prefix);
01806
01807 for (i = 32; i < 64; i++)
01808 if (regs_ever_live[i] && ! call_used_regs[i])
01809 fprintf (asm_file, "\tfst.l %s%s,%d(%sfp)\n",
01810 i860_reg_prefix, reg_names[i],
01811 must_preserve_bytes + (4 * preserved_so_far++),
01812 i860_reg_prefix);
01813
01814
01815
01816
01817
01818
01819 if (must_preserve_r1)
01820 fprintf (asm_file, "\tst.l %sr1,4(%sfp)\n",
01821 i860_reg_prefix, i860_reg_prefix);
01822 }
01823
01824 #else
01825
01826
01827
01828
01829
01830
01831
01832 if (total_fsize > 0x7fff)
01833 {
01834
01835
01836 fprintf (asm_file, "\tadds -%d,%ssp,%ssp\n",
01837 frame_upper_bytes, i860_reg_prefix, i860_reg_prefix);
01838
01839
01840
01841 fprintf (asm_file, "\tst.l %sfp,0(%ssp)\n",
01842 i860_reg_prefix, i860_reg_prefix);
01843
01844
01845
01846 if (must_preserve_r1)
01847 fprintf (asm_file, "\tst.l %sr1,4(%ssp)\n",
01848 i860_reg_prefix, i860_reg_prefix);
01849
01850
01851
01852 fprintf (asm_file, "\torh %d,%sr0,%sr31\n",
01853 frame_lower_bytes >> 16, i860_reg_prefix, i860_reg_prefix);
01854 fprintf (asm_file, "\tor %d,%sr31,%sr31\n",
01855 frame_lower_bytes & 0xffff, i860_reg_prefix, i860_reg_prefix);
01856
01857
01858
01859 fprintf (asm_file, "\tsubs %ssp,%sr31,%ssp\n",
01860 i860_reg_prefix, i860_reg_prefix, i860_reg_prefix);
01861
01862
01863
01864 fprintf (asm_file, "\tadds %ssp,%sr31,%sr31\n",
01865 i860_reg_prefix, i860_reg_prefix, i860_reg_prefix);
01866
01867
01868
01869 for (i = 1; i < 32; i++)
01870 if (regs_ever_live[i] && ! call_used_regs[i])
01871 fprintf (asm_file, "\tst.l %s%s,%d(%sr31)\n",
01872 i860_reg_prefix, reg_names[i],
01873 must_preserve_bytes + (4 * preserved_so_far++),
01874 i860_reg_prefix);
01875
01876 for (i = 32; i < 64; i++)
01877 if (regs_ever_live[i] && ! call_used_regs[i])
01878 fprintf (asm_file, "\tfst.l %s%s,%d(%sr31)\n",
01879 i860_reg_prefix, reg_names[i],
01880 must_preserve_bytes + (4 * preserved_so_far++),
01881 i860_reg_prefix);
01882
01883
01884
01885 fprintf (asm_file, "\tmov %sr31,%sfp\n",
01886 i860_reg_prefix, i860_reg_prefix);
01887 }
01888 else
01889 {
01890
01891
01892 fprintf (asm_file, "\tadds -%d,%ssp,%ssp\n",
01893 total_fsize, i860_reg_prefix, i860_reg_prefix);
01894
01895
01896
01897 fprintf (asm_file, "\tst.l %sfp,%d(%ssp)\n",
01898 i860_reg_prefix, frame_lower_bytes, i860_reg_prefix);
01899
01900
01901
01902 if (must_preserve_r1)
01903 fprintf (asm_file, "\tst.l %sr1,%d(%ssp)\n",
01904 i860_reg_prefix, frame_lower_bytes + 4, i860_reg_prefix);
01905
01906
01907
01908 for (i = 1; i < 32; i++)
01909 if (regs_ever_live[i] && ! call_used_regs[i])
01910 fprintf (asm_file, "\tst.l %s%s,%d(%ssp)\n",
01911 i860_reg_prefix, reg_names[i],
01912 frame_lower_bytes + must_preserve_bytes + (4 * preserved_so_far++),
01913 i860_reg_prefix);
01914
01915 for (i = 32; i < 64; i++)
01916 if (regs_ever_live[i] && ! call_used_regs[i])
01917 fprintf (asm_file, "\tfst.l %s%s,%d(%ssp)\n",
01918 i860_reg_prefix, reg_names[i],
01919 frame_lower_bytes + must_preserve_bytes + (4 * preserved_so_far++),
01920 i860_reg_prefix);
01921
01922
01923
01924 fprintf (asm_file, "\tadds %d,%ssp,%sfp\n",
01925 frame_lower_bytes, i860_reg_prefix, i860_reg_prefix);
01926 }
01927 #endif
01928
01929 #ifdef ASM_OUTPUT_PROLOGUE_SUFFIX
01930 ASM_OUTPUT_PROLOGUE_SUFFIX (asm_file);
01931 #endif
01932 }
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961
01962
01963
01964
01965
01966
01967
01968
01969
01970
01971
01972
01973 typedef struct TDESC_flags {
01974 int version:4;
01975 int reg_packing:1;
01976 int callable_block:1;
01977 int reserved:4;
01978 int fregs:6;
01979 int iregs:16;
01980 } TDESC_flags;
01981
01982 typedef struct TDESC {
01983 TDESC_flags flags;
01984 int integer_reg_offset;
01985 int floating_point_reg_offset;
01986 unsigned int positive_frame_size;
01987 unsigned int negative_frame_size;
01988 } TDESC;
01989
01990 static void
01991 i860_output_function_epilogue (asm_file, local_bytes)
01992 register FILE *asm_file;
01993 register HOST_WIDE_INT local_bytes;
01994 {
01995 register HOST_WIDE_INT frame_upper_bytes;
01996 register HOST_WIDE_INT frame_lower_bytes;
01997 register HOST_WIDE_INT preserved_reg_bytes = 0;
01998 register unsigned i;
01999 register unsigned restored_so_far = 0;
02000 register unsigned int_restored;
02001 register unsigned mask;
02002 unsigned intflags=0;
02003 register TDESC_flags *flags = (TDESC_flags *) &intflags;
02004 #ifdef OUTPUT_TDESC
02005 const char *long_op = integer_asm_op (4, TRUE);
02006 #endif
02007
02008 flags->version = 4;
02009 flags->reg_packing = 1;
02010 flags->iregs = 8;
02011
02012
02013
02014 frame_lower_bytes = (local_bytes + STACK_ALIGNMENT - 1) & -STACK_ALIGNMENT;
02015
02016
02017
02018
02019 for (i = 1; i < FIRST_PSEUDO_REGISTER; i++)
02020 {
02021 if (regs_ever_live[i] && ! call_used_regs[i])
02022 preserved_reg_bytes += 4;
02023 }
02024
02025
02026
02027
02028
02029 frame_upper_bytes = must_preserve_bytes + preserved_reg_bytes;
02030
02031
02032
02033 frame_upper_bytes
02034 = (frame_upper_bytes + STACK_ALIGNMENT - 1) & -STACK_ALIGNMENT;
02035
02036
02037
02038 mask = 2;
02039
02040 for (i = 1; i < 32; i++, mask<<=1)
02041 if (regs_ever_live[i] && ! call_used_regs[i]) {
02042 fprintf (asm_file, "\tld.l %d(%sfp),%s%s\n",
02043 must_preserve_bytes + (4 * restored_so_far++),
02044 i860_reg_prefix, i860_reg_prefix, reg_names[i]);
02045 if (i > 3 && i < 16)
02046 flags->iregs |= mask;
02047 }
02048
02049 int_restored = restored_so_far;
02050 mask = 1;
02051
02052 for (i = 32; i < 64; i++) {
02053 if (regs_ever_live[i] && ! call_used_regs[i]) {
02054 fprintf (asm_file, "\tfld.l %d(%sfp),%s%s\n",
02055 must_preserve_bytes + (4 * restored_so_far++),
02056 i860_reg_prefix, i860_reg_prefix, reg_names[i]);
02057 if (i > 33 && i < 40)
02058 flags->fregs |= mask;
02059 }
02060 if (i > 33 && i < 40)
02061 mask<<=1;
02062 }
02063
02064
02065
02066 fprintf (asm_file, "\tadds %d,%sfp,%sr31\n",
02067 frame_upper_bytes, i860_reg_prefix, i860_reg_prefix);
02068
02069
02070
02071 if (must_preserve_r1) {
02072 fprintf (asm_file, "\tld.l 4(%sfp),%sr1\n",
02073 i860_reg_prefix, i860_reg_prefix);
02074 flags->iregs |= 2;
02075 }
02076
02077 fprintf (asm_file, "\tld.l 0(%sfp),%sfp\n",
02078 i860_reg_prefix, i860_reg_prefix);
02079
02080
02081
02082 fprintf (asm_file, "\tbri %sr1\n\tmov %sr31,%ssp\n",
02083 i860_reg_prefix, i860_reg_prefix, i860_reg_prefix);
02084
02085 #ifdef OUTPUT_TDESC
02086 if (! frame_lower_bytes) {
02087 flags->version--;
02088 if (! frame_upper_bytes) {
02089 flags->version--;
02090 if (restored_so_far == int_restored)
02091 flags->version--;
02092 }
02093 }
02094 assemble_name(asm_file,current_function_original_name);
02095 fputs(".TDESC:\n", asm_file);
02096 fprintf(asm_file, "%s 0x%0x\n", long_op, intflags);
02097 fprintf(asm_file, "%s %d\n", long_op,
02098 int_restored ? must_preserve_bytes : 0);
02099 if (flags->version > 1) {
02100 fprintf(asm_file, "%s %d\n", long_op,
02101 (restored_so_far == int_restored) ? 0 : must_preserve_bytes +
02102 (4 * int_restored));
02103 if (flags->version > 2) {
02104 fprintf(asm_file, "%s %d\n", long_op, frame_upper_bytes);
02105 if (flags->version > 3)
02106 fprintf(asm_file, "%s %d\n", long_op, frame_lower_bytes);
02107 }
02108 }
02109 tdesc_section();
02110 fprintf(asm_file, "%s ", long_op);
02111 assemble_name(asm_file, current_function_original_name);
02112 fprintf(asm_file, "\n%s ", long_op);
02113 assemble_name(asm_file, current_function_original_name);
02114 fputs(".TDESC\n", asm_file);
02115 text_section();
02116 #endif
02117 }
02118
02119
02120
02121 rtx
02122 i860_saveregs ()
02123 {
02124 rtx fn = gen_rtx_SYMBOL_REF (Pmode, "__builtin_saveregs");
02125 rtx save = gen_reg_rtx (Pmode);
02126 rtx valreg = LIBCALL_VALUE (Pmode);
02127 rtx ret;
02128
02129
02130
02131 emit_move_insn (save, valreg);
02132 ret = emit_library_call_value (fn, NULL_RTX, 1, Pmode, 0);
02133 if (GET_CODE (ret) != REG || REGNO (ret) < FIRST_PSEUDO_REGISTER)
02134 ret = copy_to_reg (ret);
02135 emit_move_insn (valreg, save);
02136
02137 return ret;
02138 }
02139
02140 tree
02141 i860_build_va_list ()
02142 {
02143 tree field_ireg_used, field_freg_used, field_reg_base, field_mem_ptr;
02144 tree record;
02145
02146 record = make_node (RECORD_TYPE);
02147
02148 field_ireg_used = build_decl (FIELD_DECL, get_identifier ("__ireg_used"),
02149 unsigned_type_node);
02150 field_freg_used = build_decl (FIELD_DECL, get_identifier ("__freg_used"),
02151 unsigned_type_node);
02152 field_reg_base = build_decl (FIELD_DECL, get_identifier ("__reg_base"),
02153 ptr_type_node);
02154 field_mem_ptr = build_decl (FIELD_DECL, get_identifier ("__mem_ptr"),
02155 ptr_type_node);
02156
02157 DECL_FIELD_CONTEXT (field_ireg_used) = record;
02158 DECL_FIELD_CONTEXT (field_freg_used) = record;
02159 DECL_FIELD_CONTEXT (field_reg_base) = record;
02160 DECL_FIELD_CONTEXT (field_mem_ptr) = record;
02161
02162 #ifdef I860_SVR4_VA_LIST
02163 TYPE_FIELDS (record) = field_ireg_used;
02164 TREE_CHAIN (field_ireg_used) = field_freg_used;
02165 TREE_CHAIN (field_freg_used) = field_reg_base;
02166 TREE_CHAIN (field_reg_base) = field_mem_ptr;
02167 #else
02168 TYPE_FIELDS (record) = field_reg_base;
02169 TREE_CHAIN (field_reg_base) = field_mem_ptr;
02170 TREE_CHAIN (field_mem_ptr) = field_ireg_used;
02171 TREE_CHAIN (field_ireg_used) = field_freg_used;
02172 #endif
02173
02174 layout_type (record);
02175 return record;
02176 }
02177
02178 void
02179 i860_va_start (stdarg_p, valist, nextarg)
02180 int stdarg_p;
02181 tree valist;
02182 rtx nextarg;
02183 {
02184 tree saveregs, t;
02185
02186 saveregs = make_tree (build_pointer_type (va_list_type_node),
02187 expand_builtin_saveregs ());
02188 saveregs = build1 (INDIRECT_REF, va_list_type_node, saveregs);
02189
02190 if (stdarg_p)
02191 {
02192 tree field_ireg_used, field_freg_used, field_reg_base, field_mem_ptr;
02193 tree ireg_used, freg_used, reg_base, mem_ptr;
02194
02195 #ifdef I860_SVR4_VA_LIST
02196 field_ireg_used = TYPE_FIELDS (va_list_type_node);
02197 field_freg_used = TREE_CHAIN (field_ireg_used);
02198 field_reg_base = TREE_CHAIN (field_freg_used);
02199 field_mem_ptr = TREE_CHAIN (field_reg_base);
02200 #else
02201 field_reg_base = TYPE_FIELDS (va_list_type_node);
02202 field_mem_ptr = TREE_CHAIN (field_reg_base);
02203 field_ireg_used = TREE_CHAIN (field_mem_ptr);
02204 field_freg_used = TREE_CHAIN (field_ireg_used);
02205 #endif
02206
02207 ireg_used = build (COMPONENT_REF, TREE_TYPE (field_ireg_used),
02208 valist, field_ireg_used);
02209 freg_used = build (COMPONENT_REF, TREE_TYPE (field_freg_used),
02210 valist, field_freg_used);
02211 reg_base = build (COMPONENT_REF, TREE_TYPE (field_reg_base),
02212 valist, field_reg_base);
02213 mem_ptr = build (COMPONENT_REF, TREE_TYPE (field_mem_ptr),
02214 valist, field_mem_ptr);
02215
02216 t = build_int_2 (current_function_args_info.ints, 0);
02217 t = build (MODIFY_EXPR, TREE_TYPE (ireg_used), ireg_used, t);
02218 TREE_SIDE_EFFECTS (t) = 1;
02219 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
02220
02221 t = build_int_2 (ROUNDUP (current_function_args_info.floats, 8), 0);
02222 t = build (MODIFY_EXPR, TREE_TYPE (freg_used), freg_used, t);
02223 TREE_SIDE_EFFECTS (t) = 1;
02224 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
02225
02226 t = build (COMPONENT_REF, TREE_TYPE (field_reg_base),
02227 saveregs, field_reg_base);
02228 t = build (MODIFY_EXPR, TREE_TYPE (reg_base), reg_base, t);
02229 TREE_SIDE_EFFECTS (t) = 1;
02230 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
02231
02232 t = make_tree (ptr_type_node, nextarg);
02233 t = build (MODIFY_EXPR, TREE_TYPE (mem_ptr), mem_ptr, t);
02234 TREE_SIDE_EFFECTS (t) = 1;
02235 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
02236 }
02237 else
02238 {
02239 t = build (MODIFY_EXPR, va_list_type_node, valist, saveregs);
02240 TREE_SIDE_EFFECTS (t) = 1;
02241 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
02242 }
02243 }
02244
02245 #define NUM_PARM_FREGS 8
02246 #define NUM_PARM_IREGS 12
02247 #ifdef I860_SVR4_VARARGS
02248 #define FREG_OFFSET 0
02249 #define IREG_OFFSET (NUM_PARM_FREGS * UNITS_PER_WORD)
02250 #else
02251 #define FREG_OFFSET (NUM_PARM_IREGS * UNITS_PER_WORD)
02252 #define IREG_OFFSET 0
02253 #endif
02254
02255 rtx
02256 i860_va_arg (valist, type)
02257 tree valist, type;
02258 {
02259 tree field_ireg_used, field_freg_used, field_reg_base, field_mem_ptr;
02260 tree type_ptr_node, t;
02261 rtx lab_over = NULL_RTX;
02262 rtx ret, val;
02263 HOST_WIDE_INT align;
02264
02265 #ifdef I860_SVR4_VA_LIST
02266 field_ireg_used = TYPE_FIELDS (va_list_type_node);
02267 field_freg_used = TREE_CHAIN (field_ireg_used);
02268 field_reg_base = TREE_CHAIN (field_freg_used);
02269 field_mem_ptr = TREE_CHAIN (field_reg_base);
02270 #else
02271 field_reg_base = TYPE_FIELDS (va_list_type_node);
02272 field_mem_ptr = TREE_CHAIN (field_reg_base);
02273 field_ireg_used = TREE_CHAIN (field_mem_ptr);
02274 field_freg_used = TREE_CHAIN (field_ireg_used);
02275 #endif
02276
02277 field_ireg_used = build (COMPONENT_REF, TREE_TYPE (field_ireg_used),
02278 valist, field_ireg_used);
02279 field_freg_used = build (COMPONENT_REF, TREE_TYPE (field_freg_used),
02280 valist, field_freg_used);
02281 field_reg_base = build (COMPONENT_REF, TREE_TYPE (field_reg_base),
02282 valist, field_reg_base);
02283 field_mem_ptr = build (COMPONENT_REF, TREE_TYPE (field_mem_ptr),
02284 valist, field_mem_ptr);
02285
02286 ret = gen_reg_rtx (Pmode);
02287 type_ptr_node = build_pointer_type (type);
02288
02289 if (! AGGREGATE_TYPE_P (type))
02290 {
02291 int nparm, incr, ofs;
02292 tree field;
02293 rtx lab_false;
02294
02295 if (FLOAT_TYPE_P (type))
02296 {
02297 field = field_freg_used;
02298 nparm = NUM_PARM_FREGS;
02299 incr = 2;
02300 ofs = FREG_OFFSET;
02301 }
02302 else
02303 {
02304 field = field_ireg_used;
02305 nparm = NUM_PARM_IREGS;
02306 incr = int_size_in_bytes (type) / UNITS_PER_WORD;
02307 ofs = IREG_OFFSET;
02308 }
02309
02310 lab_false = gen_label_rtx ();
02311 lab_over = gen_label_rtx ();
02312
02313 emit_cmp_and_jump_insns (expand_expr (field, NULL_RTX, 0, 0),
02314 GEN_INT (nparm - incr), GT, const0_rtx,
02315 TYPE_MODE (TREE_TYPE (field)),
02316 TREE_UNSIGNED (field), lab_false);
02317
02318 t = fold (build (POSTINCREMENT_EXPR, TREE_TYPE (field), field,
02319 build_int_2 (incr, 0)));
02320 TREE_SIDE_EFFECTS (t) = 1;
02321
02322 t = fold (build (MULT_EXPR, TREE_TYPE (field), field,
02323 build_int_2 (UNITS_PER_WORD, 0)));
02324 TREE_SIDE_EFFECTS (t) = 1;
02325
02326 t = fold (build (PLUS_EXPR, ptr_type_node, field_reg_base,
02327 fold (build (PLUS_EXPR, TREE_TYPE (field), t,
02328 build_int_2 (ofs, 0)))));
02329 TREE_SIDE_EFFECTS (t) = 1;
02330
02331 val = expand_expr (t, ret, VOIDmode, EXPAND_NORMAL);
02332 if (val != ret)
02333 emit_move_insn (ret, val);
02334
02335 emit_jump_insn (gen_jump (lab_over));
02336 emit_barrier ();
02337 emit_label (lab_false);
02338 }
02339
02340 align = TYPE_ALIGN (type);
02341 if (align < BITS_PER_WORD)
02342 align = BITS_PER_WORD;
02343 align /= BITS_PER_UNIT;
02344
02345 t = build (PLUS_EXPR, ptr_type_node, field_mem_ptr,
02346 build_int_2 (align - 1, 0));
02347 t = build (BIT_AND_EXPR, ptr_type_node, t, build_int_2 (-align, -1));
02348
02349 val = expand_expr (t, ret, VOIDmode, EXPAND_NORMAL);
02350 if (val != ret)
02351 emit_move_insn (ret, val);
02352
02353 t = fold (build (PLUS_EXPR, ptr_type_node,
02354 make_tree (ptr_type_node, ret),
02355 build_int_2 (int_size_in_bytes (type), 0)));
02356 t = build (MODIFY_EXPR, ptr_type_node, field_mem_ptr, t);
02357 TREE_SIDE_EFFECTS (t) = 1;
02358 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
02359
02360 if (lab_over)
02361 emit_label (lab_over);
02362
02363 return ret;
02364 }