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