#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "flags.h"
#include "rtl.h"
#include "tree.h"
#include "regs.h"
#include "hard-reg-set.h"
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
#include "output.h"
#include "recog.h"
#include "insn-attr.h"
#include "function.h"
#include "expr.h"
#include "optabs.h"
#include "toplev.h"
#include "tm_p.h"
#include "target.h"
#include "target-def.h"
#include "langhooks.h"
#include "tree-gimple.h"
static rtx find_addr_reg (rtx);
#ifndef I860_REG_PREFIX
#define I860_REG_PREFIX ""
#endif
const char *i860_reg_prefix = I860_REG_PREFIX;
rtx i860_compare_op0, i860_compare_op1;
int
safe_insn_src_p (rtx op, enum machine_mode mode)
{
switch (GET_CODE (op))
{
case CONST_INT:
case LABEL_REF:
case SYMBOL_REF:
case CONST:
return 1;
case REG:
return 1;
case MEM:
return CONSTANT_ADDRESS_P (XEXP (op, 0));
case NEG:
return (mode != SFmode && mode != DFmode);
case NOT:
case ZERO_EXTEND:
return 1;
case EQ:
case NE:
case LT:
case GT:
case LE:
case GE:
case LTU:
case GTU:
case LEU:
case GEU:
case MINUS:
case PLUS:
return (mode != SFmode && mode != DFmode);
case AND:
case IOR:
case XOR:
case ASHIFT:
case ASHIFTRT:
case LSHIFTRT:
if ((GET_CODE (XEXP (op, 0)) == CONST_INT && ! SMALL_INT (XEXP (op, 0)))
|| (GET_CODE (XEXP (op, 1)) == CONST_INT && ! SMALL_INT (XEXP (op, 1))))
return 0;
return 1;
default:
return 0;
}
}
static int
reg_clobbered_p (rtx reg, rtx in)
{
register enum rtx_code code;
if (in == 0)
return 0;
code = GET_CODE (in);
if (code == SET || code == CLOBBER)
{
rtx dest = SET_DEST (in);
int set = 0;
int used = 0;
while (GET_CODE (dest) == STRICT_LOW_PART
|| GET_CODE (dest) == SUBREG
|| GET_CODE (dest) == ZERO_EXTRACT)
dest = XEXP (dest, 0);
if (dest == reg)
set = 1;
else if (GET_CODE (dest) == REG
&& refers_to_regno_p (REGNO (reg),
REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
SET_DEST (in), 0))
{
set = 1;
if (dest != SET_DEST (in)
&& ! (GET_CODE (SET_DEST (in)) == SUBREG
|| UNITS_PER_WORD >= GET_MODE_SIZE (GET_MODE (dest))))
used = 1;
}
if (code == SET)
{
if (set)
used = refers_to_regno_p (REGNO (reg),
REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
SET_SRC (in), 0);
else
used = refers_to_regno_p (REGNO (reg),
REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
in, 0);
}
return set + used * 2;
}
if (refers_to_regno_p (REGNO (reg),
REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
in, 0))
return 2;
return 0;
}
int
operand_clobbered_before_used_after (rtx op, rtx after)
{
if (GET_CODE (op) == CC0)
return 1;
if (GET_CODE (op) == REG)
{
rtx insn;
if (op == stack_pointer_rtx)
return 0;
for (insn = NEXT_INSN (after); insn; insn = NEXT_INSN (insn))
{
if (GET_CODE (insn) == NOTE)
continue;
if (GET_CODE (insn) == INSN
|| GET_CODE (insn) == JUMP_INSN
|| GET_CODE (insn) == CALL_INSN)
{
switch (reg_clobbered_p (op, PATTERN (insn)))
{
default:
return 0;
case 1:
return 1;
case 0:
break;
}
}
else if (GET_CODE (insn) == CODE_LABEL)
return 0;
if (GET_CODE (insn) == JUMP_INSN)
{
if (condjump_p (insn))
return 0;
if (GET_CODE (PATTERN (insn)) == PARALLEL)
return 0;
if (! JUMP_LABEL (insn))
return 0;
insn = JUMP_LABEL (insn);
}
}
return 1;
}
if (GET_CODE (op) == MEM)
return (CONSTANT_ADDRESS_P (XEXP (op, 0)));
return 0;
}
int
reg_or_0_operand (rtx op, enum machine_mode mode)
{
return (op == const0_rtx || register_operand (op, mode)
|| op == CONST0_RTX (mode));
}
int
arith_operand (rtx op, enum machine_mode mode)
{
return (register_operand (op, mode)
|| (GET_CODE (op) == CONST_INT && SMALL_INT (op)));
}
int
logic_operand (rtx op, enum machine_mode mode)
{
return (register_operand (op, mode)
|| (GET_CODE (op) == CONST_INT && LOGIC_INT (op)));
}
int
shift_operand (rtx op, enum machine_mode mode)
{
return (register_operand (op, mode)
|| (GET_CODE (op) == CONST_INT));
}
int
compare_operand (rtx op, enum machine_mode mode)
{
return (register_operand (op, mode)
|| (GET_CODE (op) == CONST_INT && SMALL_INT (op) && LOGIC_INT (op)));
}
int
bte_operand (rtx op, enum machine_mode mode)
{
return (register_operand (op, mode)
|| (GET_CODE (op) == CONST_INT
&& (unsigned) INTVAL (op) < 0x20));
}
int
indexed_operand (rtx op, enum machine_mode mode)
{
return (GET_CODE (op) == MEM && GET_MODE (op) == mode
&& GET_CODE (XEXP (op, 0)) == PLUS
&& GET_MODE (XEXP (op, 0)) == SImode
&& register_operand (XEXP (XEXP (op, 0), 0), SImode)
&& register_operand (XEXP (XEXP (op, 0), 1), SImode));
}
int
load_operand (rtx op, enum machine_mode mode)
{
return (memory_operand (op, mode) || indexed_operand (op, mode));
}
int
small_int (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
return (GET_CODE (op) == CONST_INT && SMALL_INT (op));
}
int
logic_int (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
return (GET_CODE (op) == CONST_INT && LOGIC_INT (op));
}
int
call_insn_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
if (GET_CODE (op) == MEM
&& (CONSTANT_ADDRESS_P (XEXP (op, 0))
|| (GET_CODE (XEXP (op, 0)) == REG
&& XEXP (op, 0) != arg_pointer_rtx
&& !(REGNO (XEXP (op, 0)) >= FIRST_PSEUDO_REGISTER
&& REGNO (XEXP (op, 0)) <= LAST_VIRTUAL_REGISTER))))
return 1;
return 0;
}
static const char *
singlemove_string (rtx *operands)
{
if (GET_CODE (operands[0]) == MEM)
{
if (GET_CODE (operands[1]) != MEM)
if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
{
if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
&& (cc_prev_status.flags & CC_HI_R31_ADJ)
&& cc_prev_status.mdep == XEXP (operands[0], 0)))
{
CC_STATUS_INIT;
output_asm_insn ("orh %h0,%?r0,%?r31", operands);
}
cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
cc_status.mdep = XEXP (operands[0], 0);
return "st.l %r1,%L0(%?r31)";
}
else
return "st.l %r1,%0";
else
abort ();
#if 0
{
rtx xoperands[2];
cc_status.flags &= ~CC_F0_IS_0;
xoperands[0] = gen_rtx_REG (SFmode, 32);
xoperands[1] = operands[1];
output_asm_insn (singlemove_string (xoperands), xoperands);
xoperands[1] = xoperands[0];
xoperands[0] = operands[0];
output_asm_insn (singlemove_string (xoperands), xoperands);
return "";
}
#endif
}
if (GET_CODE (operands[1]) == MEM)
{
if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
{
if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
&& (cc_prev_status.flags & CC_HI_R31_ADJ)
&& cc_prev_status.mdep == XEXP (operands[1], 0)))
{
CC_STATUS_INIT;
output_asm_insn ("orh %h1,%?r0,%?r31", operands);
}
cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
cc_status.mdep = XEXP (operands[1], 0);
return "ld.l %L1(%?r31),%0";
}
return "ld.l %m1,%0";
}
if (GET_CODE (operands[1]) == CONST_INT)
{
if (operands[1] == const0_rtx)
return "mov %?r0,%0";
if((INTVAL (operands[1]) & 0xffff0000) == 0)
return "or %L1,%?r0,%0";
if((INTVAL (operands[1]) & 0xffff8000) == 0xffff8000)
return "adds %1,%?r0,%0";
if((INTVAL (operands[1]) & 0x0000ffff) == 0)
return "orh %H1,%?r0,%0";
return "orh %H1,%?r0,%0\n\tor %L1,%0,%0";
}
return "mov %1,%0";
}
const char *
output_move_double (rtx *operands)
{
enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
rtx latehalf[2];
rtx addreg0 = 0, addreg1 = 0;
int highest_first = 0;
int no_addreg1_decrement = 0;
if (REG_P (operands[0]))
optype0 = REGOP;
else if (offsettable_memref_p (operands[0]))
optype0 = OFFSOP;
else if (GET_CODE (operands[0]) == MEM)
optype0 = MEMOP;
else
optype0 = RNDOP;
if (REG_P (operands[1]))
optype1 = REGOP;
else if (CONSTANT_P (operands[1]))
optype1 = CNSTOP;
else if (offsettable_memref_p (operands[1]))
optype1 = OFFSOP;
else if (GET_CODE (operands[1]) == MEM)
optype1 = MEMOP;
else
optype1 = RNDOP;
if (optype0 == RNDOP || optype1 == RNDOP)
abort ();
if (optype0 == MEMOP)
addreg0 = find_addr_reg (XEXP (operands[0], 0));
if (optype1 == MEMOP)
addreg1 = find_addr_reg (XEXP (operands[1], 0));
if (optype0 == REGOP)
latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
else if (optype0 == OFFSOP)
latehalf[0] = adjust_address (operands[0], SImode, 4);
else
latehalf[0] = operands[0];
if (optype1 == REGOP)
latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
else if (optype1 == OFFSOP)
latehalf[1] = adjust_address (operands[1], SImode, 4);
else if (optype1 == CNSTOP)
{
if (GET_CODE (operands[1]) == CONST_DOUBLE)
split_double (operands[1], &operands[1], &latehalf[1]);
#if 0
else if (CONSTANT_P (operands[1]))
latehalf[1] = const0_rtx;
#else
else if (CONSTANT_P (operands[1]))
split_double (operands[1], &operands[1], &latehalf[1]);
#endif
}
else
latehalf[1] = operands[1];
if (optype0 == REGOP && optype1 == REGOP
&& REGNO (operands[0]) == REGNO (latehalf[1]))
{
CC_STATUS_PARTIAL_INIT;
if (addreg0)
output_asm_insn ("adds 0x4,%0,%0", &addreg0);
if (addreg1)
output_asm_insn ("adds 0x4,%0,%0", &addreg1);
output_asm_insn (singlemove_string (latehalf), latehalf);
if (addreg0)
output_asm_insn ("adds -0x4,%0,%0", &addreg0);
if (addreg1)
output_asm_insn ("adds -0x4,%0,%0", &addreg1);
return singlemove_string (operands);
}
else if (optype0 == REGOP && optype1 != REGOP
&& reg_overlap_mentioned_p (operands[0], operands[1]))
{
if (reg_mentioned_p (operands[0], XEXP (operands[1], 0))
&& reg_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
{
rtx xops[2];
xops[0] = latehalf[0];
xops[1] = operands[0];
output_asm_insn ("adds %1,%0,%1", xops);
operands[1] = gen_rtx_MEM (DImode, operands[0]);
latehalf[1] = adjust_address (operands[1], SImode, 4);
addreg1 = 0;
highest_first = 1;
}
else if (! reg_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
highest_first = 1;
else if (addreg1 && reg_mentioned_p (addreg1, latehalf[0]))
no_addreg1_decrement = 1;
}
if (! highest_first)
output_asm_insn (singlemove_string (operands), operands);
CC_STATUS_PARTIAL_INIT;
if (addreg0)
output_asm_insn ("adds 0x4,%0,%0", &addreg0);
if (addreg1)
output_asm_insn ("adds 0x4,%0,%0", &addreg1);
output_asm_insn (singlemove_string (latehalf), latehalf);
if (addreg0)
output_asm_insn ("adds -0x4,%0,%0", &addreg0);
if (addreg1 && !no_addreg1_decrement)
output_asm_insn ("adds -0x4,%0,%0", &addreg1);
if (highest_first)
output_asm_insn (singlemove_string (operands), operands);
return "";
}
const char *
output_fp_move_double (rtx *operands)
{
if (operands[1] == CONST0_RTX (GET_MODE (operands[1])))
operands[1] = gen_rtx_REG (DFmode, F0_REGNUM);
if (FP_REG_P (operands[0]))
{
if (FP_REG_P (operands[1]))
return "fmov.dd %1,%0";
if (GET_CODE (operands[1]) == REG)
{
output_asm_insn ("ixfr %1,%0", operands);
operands[0] = gen_rtx_REG (VOIDmode, REGNO (operands[0]) + 1);
operands[1] = gen_rtx_REG (VOIDmode, REGNO (operands[1]) + 1);
return "ixfr %1,%0";
}
if (operands[1] == CONST0_RTX (DFmode))
return "fmov.dd f0,%0";
if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
{
if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
&& (cc_prev_status.flags & CC_HI_R31_ADJ)
&& cc_prev_status.mdep == XEXP (operands[1], 0)))
{
CC_STATUS_INIT;
output_asm_insn ("orh %h1,%?r0,%?r31", operands);
}
cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
cc_status.mdep = XEXP (operands[1], 0);
return "fld.d %L1(%?r31),%0";
}
return "fld.d %1,%0";
}
else if (FP_REG_P (operands[1]))
{
if (GET_CODE (operands[0]) == REG)
{
output_asm_insn ("fxfr %1,%0", operands);
operands[0] = gen_rtx_REG (VOIDmode, REGNO (operands[0]) + 1);
operands[1] = gen_rtx_REG (VOIDmode, REGNO (operands[1]) + 1);
return "fxfr %1,%0";
}
if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
{
if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
&& (cc_prev_status.flags & CC_HI_R31_ADJ)
&& cc_prev_status.mdep == XEXP (operands[0], 0)))
{
CC_STATUS_INIT;
output_asm_insn ("orh %h0,%?r0,%?r31", operands);
}
cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
cc_status.mdep = XEXP (operands[0], 0);
return "fst.d %1,%L0(%?r31)";
}
return "fst.d %1,%0";
}
else
abort ();
return NULL;
}
static rtx
find_addr_reg (rtx addr)
{
while (GET_CODE (addr) == PLUS)
{
if (GET_CODE (XEXP (addr, 0)) == REG)
addr = XEXP (addr, 0);
else if (GET_CODE (XEXP (addr, 1)) == REG)
addr = XEXP (addr, 1);
else if (CONSTANT_P (XEXP (addr, 0)))
addr = XEXP (addr, 1);
else if (CONSTANT_P (XEXP (addr, 1)))
addr = XEXP (addr, 0);
else
abort ();
}
if (GET_CODE (addr) == REG)
return addr;
abort ();
return NULL;
}
static const char *
load_opcode (enum machine_mode mode, const char *args, rtx reg)
{
static char buf[30];
const char *opcode;
switch (mode)
{
case QImode:
opcode = "ld.b";
break;
case HImode:
opcode = "ld.s";
break;
case SImode:
case SFmode:
if (FP_REG_P (reg))
opcode = "fld.l";
else
opcode = "ld.l";
break;
case DImode:
if (!FP_REG_P (reg))
abort ();
case DFmode:
opcode = "fld.d";
break;
default:
abort ();
}
sprintf (buf, "%s %s", opcode, args);
return buf;
}
static const char *
store_opcode (enum machine_mode mode, const char *args, rtx reg)
{
static char buf[30];
const char *opcode;
switch (mode)
{
case QImode:
opcode = "st.b";
break;
case HImode:
opcode = "st.s";
break;
case SImode:
case SFmode:
if (FP_REG_P (reg))
opcode = "fst.l";
else
opcode = "st.l";
break;
case DImode:
if (!FP_REG_P (reg))
abort ();
case DFmode:
opcode = "fst.d";
break;
default:
abort ();
}
sprintf (buf, "%s %s", opcode, args);
return buf;
}
const char *
output_store (rtx *operands)
{
enum machine_mode mode = GET_MODE (operands[0]);
rtx address = XEXP (operands[0], 0);
cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
cc_status.mdep = address;
if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
&& (cc_prev_status.flags & CC_HI_R31_ADJ)
&& address == cc_prev_status.mdep))
{
CC_STATUS_INIT;
output_asm_insn ("orh %h0,%?r0,%?r31", operands);
cc_prev_status.mdep = address;
}
if (mode == DFmode && operands[1] == CONST0_RTX (DFmode))
return store_opcode (DFmode, "%r1,%L0(%?r31)", operands[1]);
if ((mode == DImode || mode == DFmode)
&& ! FP_REG_P (operands[1]))
return output_move_double (operands);
return store_opcode (mode, "%r1,%L0(%?r31)", operands[1]);
}
const char *
output_load (rtx *operands)
{
enum machine_mode mode = GET_MODE (operands[0]);
rtx address = XEXP (operands[1], 0);
cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
cc_status.mdep = address;
if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
&& (cc_prev_status.flags & CC_HI_R31_ADJ)
&& address == cc_prev_status.mdep
&& cc_prev_status.mdep == cc_status.mdep))
{
CC_STATUS_INIT;
output_asm_insn ("orh %h1,%?r0,%?r31", operands);
cc_prev_status.mdep = address;
}
if ((mode == DImode || mode == DFmode)
&& ! FP_REG_P (operands[0]))
return output_move_double (operands);
return load_opcode (mode, "%L1(%?r31),%0", operands[0]);
}
#if 0
void
output_load_address (rtx *operands)
{
rtx base, offset;
if (CONSTANT_P (operands[3]))
{
output_asm_insn ("mov %3,%0", operands);
return;
}
if (REG_P (operands[3]))
{
if (REGNO (operands[0]) != REGNO (operands[3]))
output_asm_insn ("shl %?r0,%3,%0", operands);
return;
}
if (GET_CODE (operands[3]) != PLUS)
abort ();
base = XEXP (operands[3], 0);
offset = XEXP (operands[3], 1);
if (GET_CODE (base) == CONST_INT)
{
rtx tmp = base;
base = offset;
offset = tmp;
}
if (GET_CODE (offset) != CONST_INT)
{
base = operands[3];
offset = const0_rtx;
}
if (REG_P (base))
{
operands[6] = base;
operands[7] = offset;
CC_STATUS_PARTIAL_INIT;
if (SMALL_INT (offset))
output_asm_insn ("adds %7,%6,%0", operands);
else
output_asm_insn ("mov %7,%0\n\tadds %0,%6,%0", operands);
}
else if (GET_CODE (base) == PLUS)
{
operands[6] = XEXP (base, 0);
operands[7] = XEXP (base, 1);
operands[8] = offset;
CC_STATUS_PARTIAL_INIT;
if (SMALL_INT (offset))
output_asm_insn ("adds %6,%7,%0\n\tadds %8,%0,%0", operands);
else
output_asm_insn ("mov %8,%0\n\tadds %0,%6,%0\n\tadds %0,%7,%0", operands);
}
else
abort ();
}
#endif
static void
output_size_for_block_move (rtx size, rtx reg, rtx align)
{
rtx xoperands[3];
xoperands[0] = reg;
xoperands[1] = size;
xoperands[2] = align;
#if 1
cc_status.flags &= ~ CC_KNOW_HI_R31;
output_asm_insn (singlemove_string (xoperands), xoperands);
#else
if (GET_CODE (size) == REG)
output_asm_insn ("sub %2,%1,%0", xoperands);
else
{
xoperands[1] = GEN_INT (INTVAL (size) - INTVAL (align));
cc_status.flags &= ~ CC_KNOW_HI_R31;
output_asm_insn ("mov %1,%0", xoperands);
}
#endif
}
const char *
output_block_move (rtx *operands)
{
rtx xoperands[10];
#if 0
rtx zoperands[10];
#endif
static int movmemsi_label = 0;
int i;
rtx temp1 = operands[4];
rtx alignrtx = operands[3];
int align = INTVAL (alignrtx);
int chunk_size;
xoperands[0] = operands[0];
xoperands[1] = operands[1];
xoperands[2] = temp1;
if (align > 4)
{
align = 4;
alignrtx = GEN_INT (4);
}
if (GET_CODE (operands[2]) == CONST_INT
&& ! CONSTANT_ADDRESS_P (operands[0])
&& ! CONSTANT_ADDRESS_P (operands[1]))
{
int size = INTVAL (operands[2]);
rtx op0 = xoperands[0];
rtx op1 = xoperands[1];
if ((align & 3) == 0 && (size & 3) == 0 && (size >> 2) <= 16)
{
if (memory_address_p (SImode, plus_constant (op0, size))
&& memory_address_p (SImode, plus_constant (op1, size)))
{
cc_status.flags &= ~CC_KNOW_HI_R31;
for (i = (size>>2)-1; i >= 0; i--)
{
xoperands[0] = plus_constant (op0, i * 4);
xoperands[1] = plus_constant (op1, i * 4);
output_asm_insn ("ld.l %a1,%?r31\n\tst.l %?r31,%a0",
xoperands);
}
return "";
}
}
else if ((align & 1) == 0 && (size & 1) == 0 && (size >> 1) <= 16)
{
if (memory_address_p (HImode, plus_constant (op0, size))
&& memory_address_p (HImode, plus_constant (op1, size)))
{
cc_status.flags &= ~CC_KNOW_HI_R31;
for (i = (size>>1)-1; i >= 0; i--)
{
xoperands[0] = plus_constant (op0, i * 2);
xoperands[1] = plus_constant (op1, i * 2);
output_asm_insn ("ld.s %a1,%?r31\n\tst.s %?r31,%a0",
xoperands);
}
return "";
}
}
else if (size <= 16)
{
if (memory_address_p (QImode, plus_constant (op0, size))
&& memory_address_p (QImode, plus_constant (op1, size)))
{
cc_status.flags &= ~CC_KNOW_HI_R31;
for (i = size-1; i >= 0; i--)
{
xoperands[0] = plus_constant (op0, i);
xoperands[1] = plus_constant (op1, i);
output_asm_insn ("ld.b %a1,%?r31\n\tst.b %?r31,%a0",
xoperands);
}
return "";
}
}
}
CC_STATUS_INIT;
output_size_for_block_move (operands[2], operands[4], alignrtx);
#if 0
zoperands[0] = operands[0];
zoperands[3] = plus_constant (operands[0], align);
output_load_address (zoperands);
#endif
xoperands[3] = GEN_INT (movmemsi_label++);
#if 0
if ((align & 3) == 0)
chunk_size = 4;
else if ((align & 1) == 0)
chunk_size = 2;
else
#endif
chunk_size = 1;
xoperands[4] = GEN_INT (- chunk_size);
xoperands[5] = operands[5];
output_asm_insn ("adds %4,%?r0,%5", xoperands);
output_asm_insn ("adds %5,%2,%2", xoperands);
output_asm_insn ("bc .Le%3", xoperands);
xoperands[6] = operands[6];
output_asm_insn ("subs %1,%5,%1", xoperands);
output_asm_insn ("bla %5,%2,.Lm%3", xoperands);
output_asm_insn ("adds %0,%2,%6", xoperands);
output_asm_insn ("\n.Lm%3:", xoperands);
output_asm_insn ("\n.Ls%3:", xoperands);
output_asm_insn ("adds %5,%6,%6", xoperands);
if (chunk_size == 4)
{
output_asm_insn ("ld.l %2(%1),%?r31", xoperands);
output_asm_insn ("bla %5,%2,.Ls%3", xoperands);
output_asm_insn ("st.l %?r31,8(%6)", xoperands);
}
else if (chunk_size == 2)
{
output_asm_insn ("ld.s %2(%1),%?r31", xoperands);
output_asm_insn ("bla %5,%2,.Ls%3", xoperands);
output_asm_insn ("st.s %?r31,4(%6)", xoperands);
}
else
{
output_asm_insn ("ld.b %2(%1),%?r31", xoperands);
output_asm_insn ("bla %5,%2,.Ls%3", xoperands);
output_asm_insn ("st.b %?r31,2(%6)", xoperands);
}
output_asm_insn ("\n.Le%3:", xoperands);
return "";
}
unsigned long
sfmode_constant_to_ulong (rtx x)
{
REAL_VALUE_TYPE d;
unsigned long l;
if (GET_CODE (x) != CONST_DOUBLE || GET_MODE (x) != SFmode)
abort ();
REAL_VALUE_FROM_CONST_DOUBLE (d, x);
REAL_VALUE_TO_TARGET_SINGLE (d, l);
return l;
}
#ifndef STACK_ALIGNMENT
#define STACK_ALIGNMENT 16
#endif
const char *current_function_original_name;
static int must_preserve_r1;
static unsigned must_preserve_bytes;
static void
i860_output_function_prologue (FILE *asm_file, HOST_WIDE_INT local_bytes)
{
register HOST_WIDE_INT frame_lower_bytes;
register HOST_WIDE_INT frame_upper_bytes;
register HOST_WIDE_INT total_fsize;
register unsigned preserved_reg_bytes = 0;
register unsigned i;
register unsigned preserved_so_far = 0;
must_preserve_r1 = (optimize < 2 || ! leaf_function_p ());
must_preserve_bytes = 4 + (must_preserve_r1 ? 4 : 0);
for (i = 1; i < FIRST_PSEUDO_REGISTER; i++)
{
if (regs_ever_live[i] && ! call_used_regs[i])
preserved_reg_bytes += 4;
}
frame_lower_bytes = (local_bytes + STACK_ALIGNMENT - 1) & -STACK_ALIGNMENT;
frame_upper_bytes = must_preserve_bytes + preserved_reg_bytes;
frame_upper_bytes
= (frame_upper_bytes + STACK_ALIGNMENT - 1) & -STACK_ALIGNMENT;
total_fsize = frame_upper_bytes + frame_lower_bytes;
#ifndef I860_STRICT_ABI_PROLOGUES
if (total_fsize > 0x7fff)
{
fprintf (asm_file, "\taddu -" HOST_WIDE_INT_PRINT_DEC ",%ssp,%ssp\n",
frame_upper_bytes, i860_reg_prefix, i860_reg_prefix);
fprintf (asm_file, "\tst.l %sfp,0(%ssp)\n",
i860_reg_prefix, i860_reg_prefix);
fprintf (asm_file, "\taddu 0,%ssp,%sfp\n",
i860_reg_prefix, i860_reg_prefix);
fprintf (asm_file, "\torh " HOST_WIDE_INT_PRINT_DEC ",%sr0,%sr31\n",
frame_lower_bytes >> 16, i860_reg_prefix, i860_reg_prefix);
fprintf (asm_file, "\tor " HOST_WIDE_INT_PRINT_DEC ",%sr31,%sr31\n",
frame_lower_bytes & 0xffff, i860_reg_prefix, i860_reg_prefix);
fprintf (asm_file, "\tsubu %ssp,%sr31,%ssp\n",
i860_reg_prefix, i860_reg_prefix, i860_reg_prefix);
for (i = 1; i < 32; i++)
if (regs_ever_live[i] && ! call_used_regs[i])
fprintf (asm_file, "\tst.l %s%s,%d(%sfp)\n",
i860_reg_prefix, reg_names[i],
must_preserve_bytes + (4 * preserved_so_far++),
i860_reg_prefix);
for (i = 32; i < 64; i++)
if (regs_ever_live[i] && ! call_used_regs[i])
fprintf (asm_file, "\tfst.l %s%s,%d(%sfp)\n",
i860_reg_prefix, reg_names[i],
must_preserve_bytes + (4 * preserved_so_far++),
i860_reg_prefix);
if (must_preserve_r1)
fprintf (asm_file, "\tst.l %sr1,4(%sfp)\n",
i860_reg_prefix, i860_reg_prefix);
}
else
{
fprintf (asm_file, "\taddu -" HOST_WIDE_INT_PRINT_DEC ",%ssp,%ssp\n",
total_fsize, i860_reg_prefix, i860_reg_prefix);
fprintf (asm_file, "\tst.l %sfp," HOST_WIDE_INT_PRINT_DEC "(%ssp)\n",
i860_reg_prefix, frame_lower_bytes, i860_reg_prefix);
fprintf (asm_file, "\taddu " HOST_WIDE_INT_PRINT_DEC ",%ssp,%sfp\n",
frame_lower_bytes, i860_reg_prefix, i860_reg_prefix);
for (i = 1; i < 32; i++)
if (regs_ever_live[i] && ! call_used_regs[i])
fprintf (asm_file, "\tst.l %s%s,%d(%sfp)\n",
i860_reg_prefix, reg_names[i],
must_preserve_bytes + (4 * preserved_so_far++),
i860_reg_prefix);
for (i = 32; i < 64; i++)
if (regs_ever_live[i] && ! call_used_regs[i])
fprintf (asm_file, "\tfst.l %s%s,%d(%sfp)\n",
i860_reg_prefix, reg_names[i],
must_preserve_bytes + (4 * preserved_so_far++),
i860_reg_prefix);
if (must_preserve_r1)
fprintf (asm_file, "\tst.l %sr1,4(%sfp)\n",
i860_reg_prefix, i860_reg_prefix);
}
#else
if (total_fsize > 0x7fff)
{
fprintf (asm_file, "\tadds -%d,%ssp,%ssp\n",
frame_upper_bytes, i860_reg_prefix, i860_reg_prefix);
fprintf (asm_file, "\tst.l %sfp,0(%ssp)\n",
i860_reg_prefix, i860_reg_prefix);
if (must_preserve_r1)
fprintf (asm_file, "\tst.l %sr1,4(%ssp)\n",
i860_reg_prefix, i860_reg_prefix);
fprintf (asm_file, "\torh %d,%sr0,%sr31\n",
frame_lower_bytes >> 16, i860_reg_prefix, i860_reg_prefix);
fprintf (asm_file, "\tor %d,%sr31,%sr31\n",
frame_lower_bytes & 0xffff, i860_reg_prefix, i860_reg_prefix);
fprintf (asm_file, "\tsubs %ssp,%sr31,%ssp\n",
i860_reg_prefix, i860_reg_prefix, i860_reg_prefix);
fprintf (asm_file, "\tadds %ssp,%sr31,%sr31\n",
i860_reg_prefix, i860_reg_prefix, i860_reg_prefix);
for (i = 1; i < 32; i++)
if (regs_ever_live[i] && ! call_used_regs[i])
fprintf (asm_file, "\tst.l %s%s,%d(%sr31)\n",
i860_reg_prefix, reg_names[i],
must_preserve_bytes + (4 * preserved_so_far++),
i860_reg_prefix);
for (i = 32; i < 64; i++)
if (regs_ever_live[i] && ! call_used_regs[i])
fprintf (asm_file, "\tfst.l %s%s,%d(%sr31)\n",
i860_reg_prefix, reg_names[i],
must_preserve_bytes + (4 * preserved_so_far++),
i860_reg_prefix);
fprintf (asm_file, "\tmov %sr31,%sfp\n",
i860_reg_prefix, i860_reg_prefix);
}
else
{
fprintf (asm_file, "\tadds -%d,%ssp,%ssp\n",
total_fsize, i860_reg_prefix, i860_reg_prefix);
fprintf (asm_file, "\tst.l %sfp,%d(%ssp)\n",
i860_reg_prefix, frame_lower_bytes, i860_reg_prefix);
if (must_preserve_r1)
fprintf (asm_file, "\tst.l %sr1,%d(%ssp)\n",
i860_reg_prefix, frame_lower_bytes + 4, i860_reg_prefix);
for (i = 1; i < 32; i++)
if (regs_ever_live[i] && ! call_used_regs[i])
fprintf (asm_file, "\tst.l %s%s,%d(%ssp)\n",
i860_reg_prefix, reg_names[i],
frame_lower_bytes + must_preserve_bytes + (4 * preserved_so_far++),
i860_reg_prefix);
for (i = 32; i < 64; i++)
if (regs_ever_live[i] && ! call_used_regs[i])
fprintf (asm_file, "\tfst.l %s%s,%d(%ssp)\n",
i860_reg_prefix, reg_names[i],
frame_lower_bytes + must_preserve_bytes + (4 * preserved_so_far++),
i860_reg_prefix);
fprintf (asm_file, "\tadds %d,%ssp,%sfp\n",
frame_lower_bytes, i860_reg_prefix, i860_reg_prefix);
}
#endif
#ifdef ASM_OUTPUT_PROLOGUE_SUFFIX
ASM_OUTPUT_PROLOGUE_SUFFIX (asm_file);
#endif
}
typedef struct TDESC_flags {
int version:4;
int reg_packing:1;
int callable_block:1;
int reserved:4;
int fregs:6;
int iregs:16;
} TDESC_flags;
typedef struct TDESC {
TDESC_flags flags;
int integer_reg_offset;
int floating_point_reg_offset;
unsigned int positive_frame_size;
unsigned int negative_frame_size;
} TDESC;
static void
i860_output_function_epilogue (FILE *asm_file, HOST_WIDE_INT local_bytes)
{
register HOST_WIDE_INT frame_upper_bytes;
register HOST_WIDE_INT frame_lower_bytes;
register HOST_WIDE_INT preserved_reg_bytes = 0;
register unsigned i;
register unsigned restored_so_far = 0;
register unsigned int_restored;
register unsigned mask;
unsigned intflags=0;
register TDESC_flags *flags = (TDESC_flags *) &intflags;
#ifdef OUTPUT_TDESC
const char *long_op = integer_asm_op (4, TRUE);
#endif
flags->version = 4;
flags->reg_packing = 1;
flags->iregs = 8;
frame_lower_bytes = (local_bytes + STACK_ALIGNMENT - 1) & -STACK_ALIGNMENT;
for (i = 1; i < FIRST_PSEUDO_REGISTER; i++)
{
if (regs_ever_live[i] && ! call_used_regs[i])
preserved_reg_bytes += 4;
}
frame_upper_bytes = must_preserve_bytes + preserved_reg_bytes;
frame_upper_bytes
= (frame_upper_bytes + STACK_ALIGNMENT - 1) & -STACK_ALIGNMENT;
mask = 2;
for (i = 1; i < 32; i++, mask<<=1)
if (regs_ever_live[i] && ! call_used_regs[i]) {
fprintf (asm_file, "\tld.l %d(%sfp),%s%s\n",
must_preserve_bytes + (4 * restored_so_far++),
i860_reg_prefix, i860_reg_prefix, reg_names[i]);
if (i > 3 && i < 16)
flags->iregs |= mask;
}
int_restored = restored_so_far;
mask = 1;
for (i = 32; i < 64; i++) {
if (regs_ever_live[i] && ! call_used_regs[i]) {
fprintf (asm_file, "\tfld.l %d(%sfp),%s%s\n",
must_preserve_bytes + (4 * restored_so_far++),
i860_reg_prefix, i860_reg_prefix, reg_names[i]);
if (i > 33 && i < 40)
flags->fregs |= mask;
}
if (i > 33 && i < 40)
mask<<=1;
}
fprintf (asm_file, "\tadds " HOST_WIDE_INT_PRINT_DEC ",%sfp,%sr31\n",
frame_upper_bytes, i860_reg_prefix, i860_reg_prefix);
if (must_preserve_r1) {
fprintf (asm_file, "\tld.l 4(%sfp),%sr1\n",
i860_reg_prefix, i860_reg_prefix);
flags->iregs |= 2;
}
fprintf (asm_file, "\tld.l 0(%sfp),%sfp\n",
i860_reg_prefix, i860_reg_prefix);
fprintf (asm_file, "\tbri %sr1\n\tmov %sr31,%ssp\n",
i860_reg_prefix, i860_reg_prefix, i860_reg_prefix);
#ifdef OUTPUT_TDESC
if (! frame_lower_bytes) {
flags->version--;
if (! frame_upper_bytes) {
flags->version--;
if (restored_so_far == int_restored)
flags->version--;
}
}
assemble_name(asm_file,current_function_original_name);
fputs(".TDESC:\n", asm_file);
fprintf(asm_file, "%s 0x%0x\n", long_op, intflags);
fprintf(asm_file, "%s %d\n", long_op,
int_restored ? must_preserve_bytes : 0);
if (flags->version > 1) {
fprintf(asm_file, "%s %d\n", long_op,
(restored_so_far == int_restored) ? 0 : must_preserve_bytes +
(4 * int_restored));
if (flags->version > 2) {
fprintf(asm_file, "%s %d\n", long_op, frame_upper_bytes);
if (flags->version > 3)
fprintf(asm_file, "%s %d\n", long_op, frame_lower_bytes);
}
}
tdesc_section();
fprintf(asm_file, "%s ", long_op);
assemble_name(asm_file, current_function_original_name);
fprintf(asm_file, "\n%s ", long_op);
assemble_name(asm_file, current_function_original_name);
fputs(".TDESC\n", asm_file);
text_section();
#endif
}
static rtx
i860_saveregs (void)
{
rtx fn = gen_rtx_SYMBOL_REF (Pmode, "__builtin_saveregs");
rtx save = gen_reg_rtx (Pmode);
rtx valreg = LIBCALL_VALUE (Pmode);
rtx ret;
emit_move_insn (save, valreg);
ret = emit_library_call_value (fn, NULL_RTX, 1, Pmode, 0);
if (GET_CODE (ret) != REG || REGNO (ret) < FIRST_PSEUDO_REGISTER)
ret = copy_to_reg (ret);
emit_move_insn (valreg, save);
return ret;
}
static tree
i860_build_builtin_va_list (void)
{
tree f_gpr, f_fpr, f_mem, f_sav, record, type_decl;
record = (*lang_hooks.types.make_type) (RECORD_TYPE);
type_decl = build_decl (TYPE_DECL, get_identifier ("__va_list_tag"), record);
f_gpr = build_decl (FIELD_DECL, get_identifier ("__ireg_used"),
unsigned_type_node);
f_fpr = build_decl (FIELD_DECL, get_identifier ("__freg_used"),
unsigned_type_node);
f_sav = build_decl (FIELD_DECL, get_identifier ("__reg_base"),
ptr_type_node);
f_mem = build_decl (FIELD_DECL, get_identifier ("__mem_ptr"),
ptr_type_node);
DECL_FIELD_CONTEXT (f_gpr) = record;
DECL_FIELD_CONTEXT (f_fpr) = record;
DECL_FIELD_CONTEXT (f_sav) = record;
DECL_FIELD_CONTEXT (f_mem) = record;
TREE_CHAIN (record) = type_decl;
TYPE_NAME (record) = type_decl;
#ifdef I860_SVR4_VA_LIST
TYPE_FIELDS (record) = f_gpr;
TREE_CHAIN (f_gpr) = f_fpr;
TREE_CHAIN (f_fpr) = f_sav;
TREE_CHAIN (f_sav) = f_mem;
#else
TYPE_FIELDS (record) = f_sav;
TREE_CHAIN (f_sav) = f_mem;
TREE_CHAIN (f_mem) = f_gpr;
TREE_CHAIN (f_gpr) = f_fpr;
#endif
layout_type (record);
return record;
}
void
i860_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
{
tree saveregs, t;
tree f_gpr, f_fpr, f_mem, f_sav;
tree gpr, fpr, mem, sav;
int off = 0;
saveregs = make_tree (ptr_type_node, expand_builtin_saveregs ());
#ifdef I860_SVR4_VA_LIST
f_gpr = TYPE_FIELDS (va_list_type_node);
f_fpr = TREE_CHAIN (f_gpr);
f_sav = TREE_CHAIN (f_fpr);
f_mem = TREE_CHAIN (f_sav);
#else
f_sav = TYPE_FIELDS (va_list_type_node);
f_mem = TREE_CHAIN (f_sav);
f_gpr = TREE_CHAIN (f_mem);
f_fpr = TREE_CHAIN (f_gpr);
#endif
gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE);
fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE);
sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE);
mem = build (COMPONENT_REF, TREE_TYPE (f_mem), valist, f_mem, NULL_TREE);
t = make_tree (TREE_TYPE (mem), virtual_incoming_args_rtx);
off = INTVAL (current_function_arg_offset_rtx);
off = off < 0 ? 0 : off;
t = build (PLUS_EXPR, TREE_TYPE (mem), t, build_int_cst (NULL_TREE, off, 0));
t = build (MODIFY_EXPR, TREE_TYPE (mem), mem, t);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
t = build_int_cst (NULL_TREE,
current_function_args_info.ints / UNITS_PER_WORD, 0);
t = build (MODIFY_EXPR, TREE_TYPE (gpr), gpr, t);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
t = build_int_cst (NULL_TREE,
current_function_args_info.floats / UNITS_PER_WORD, 0);
t = build (MODIFY_EXPR, TREE_TYPE (fpr), fpr, t);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
t = build (MODIFY_EXPR, TREE_TYPE (sav), sav, saveregs);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
}
#define NUM_PARM_FREGS 8
#define NUM_PARM_IREGS 12
#ifdef I860_SVR4_VA_LIST
#define FREG_OFFSET 0
#define IREG_OFFSET (NUM_PARM_FREGS * UNITS_PER_WORD)
#else
#define FREG_OFFSET (NUM_PARM_IREGS * UNITS_PER_WORD)
#define IREG_OFFSET 0
#endif
static tree
i860_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p, tree *post_p)
{
tree f_gpr, f_fpr, f_mem, f_sav;
tree gpr, fpr, mem, sav;
tree size, t, u, addr, type_ptr;
tree reg, n_reg, sav_ofs, lim_reg;
HOST_WIDE_INT isize;
bool indirect;
#ifdef I860_SVR4_VA_LIST
f_gpr = TYPE_FIELDS (va_list_type_node);
f_fpr = TREE_CHAIN (f_gpr);
f_sav = TREE_CHAIN (f_fpr);
f_mem = TREE_CHAIN (f_sav);
#else
f_sav = TYPE_FIELDS (va_list_type_node);
f_mem = TREE_CHAIN (f_sav);
f_gpr = TREE_CHAIN (f_mem);
f_fpr = TREE_CHAIN (f_gpr);
#endif
gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE);
fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE);
mem = build (COMPONENT_REF, TREE_TYPE (f_mem), valist, f_mem, NULL_TREE);
sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE);
indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
if (indirect)
type = build_pointer_type (type);
size = size_in_bytes (type);
type_ptr = build_pointer_type (type);
if (AGGREGATE_TYPE_P (type))
{
HOST_WIDE_INT align;
align = TYPE_ALIGN (type);
if (align < BITS_PER_WORD)
align = BITS_PER_WORD;
align /= BITS_PER_UNIT;
u = fold_convert (ptr_type_node, size_int (align - 1));
t = build (PLUS_EXPR, ptr_type_node, mem, u);
u = fold (build (BIT_NOT_EXPR, ptr_type_node, u));
t = build (BIT_AND_EXPR, ptr_type_node, t, u);
addr = get_initialized_tmp_var (t, pre_p, post_p);
u = fold_convert (ptr_type_node, size);
t = build (PLUS_EXPR, ptr_type_node, addr, size);
t = build (MODIFY_EXPR, ptr_type_node, mem, t);
gimplify_and_add (t, pre_p);
}
else
{
isize = tree_low_cst (size, 0);
if (FLOAT_TYPE_P (type) || (INTEGRAL_TYPE_P (type) && isize == 8))
{
reg = fpr;
n_reg = size_int (isize / UNITS_PER_WORD);
n_reg = fold_convert (unsigned_type_node, n_reg);
lim_reg = size_int (NUM_PARM_FREGS - (isize / UNITS_PER_WORD));
lim_reg = fold_convert (unsigned_type_node, lim_reg);
sav_ofs = size_int (FREG_OFFSET);
}
else
{
reg = gpr;
if ((isize + UNITS_PER_WORD - 1) / UNITS_PER_WORD > 1)
abort ();
n_reg = fold_convert (unsigned_type_node, integer_one_node);
lim_reg = size_int (NUM_PARM_IREGS - 1);
lim_reg = fold_convert (unsigned_type_node, lim_reg);
sav_ofs = size_int (IREG_OFFSET);
}
u = build (LE_EXPR, boolean_type_node, reg, lim_reg);
addr = build (COND_EXPR, ptr_type_node, u, NULL, NULL);
sav_ofs = fold_convert (ptr_type_node, sav_ofs);
sav_ofs = fold (build (PLUS_EXPR, ptr_type_node, sav, sav_ofs));
u = fold_convert (unsigned_type_node, size_int (UNITS_PER_WORD));
u = build (MULT_EXPR, unsigned_type_node, reg, u);
u = fold_convert (ptr_type_node, u);
u = build (PLUS_EXPR, ptr_type_node, sav_ofs, u);
COND_EXPR_THEN (addr) = u;
t = fold_convert (ptr_type_node, size);
u = build (POSTINCREMENT_EXPR, ptr_type_node, mem, t);
COND_EXPR_ELSE (addr) = u;
t = build (PLUS_EXPR, unsigned_type_node, reg, n_reg);
t = build (MODIFY_EXPR, unsigned_type_node, reg, t);
gimplify_and_add (t, post_p);
}
addr = fold_convert (type_ptr, addr);
if (indirect)
addr = build_fold_indirect_ref (addr);
return build_fold_indirect_ref (addr);
}
static bool
i860_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total)
{
switch (code)
{
case CONST_INT:
if (INTVAL (x) == 0)
*total = 0;
else if (INTVAL (x) < 0x2000 && INTVAL (x) >= -0x2000)
*total = 1;
return true;
case CONST:
case LABEL_REF:
case SYMBOL_REF:
*total = 4;
return true;
case CONST_DOUBLE:
*total = 6;
return true;
default:
return false;
}
}
static void
i860_internal_label (FILE *stream, const char *prefix, unsigned long labelno)
{
fprintf (stream, ".%s%ld:\n", prefix, labelno);
}
static void
i860_file_start (void)
{
output_file_directive (asm_out_file, main_input_filename);
fprintf (asm_out_file, "\t.version\t\"01.01\"\n");
}
static void
i860_init_libfuncs (void)
{
set_optab_libfunc (sdiv_optab, SImode, "*.div");
set_optab_libfunc (udiv_optab, SImode, "*.udiv");
set_optab_libfunc (smod_optab, SImode, "*.rem");
set_optab_libfunc (umod_optab, SImode, "*.urem");
}
static rtx
i860_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
int incoming ATTRIBUTE_UNUSED)
{
return gen_rtx_REG (Pmode, I860_STRUCT_VALUE_REGNUM);
}
#undef TARGET_RTX_COSTS
#define TARGET_RTX_COSTS i860_rtx_costs
#undef TARGET_ASM_INTERNAL_LABEL
#define TARGET_ASM_INTERNAL_LABEL i860_internal_label
#undef TARGET_ASM_FUNCTION_PROLOGUE
#define TARGET_ASM_FUNCTION_PROLOGUE i860_output_function_prologue
#undef TARGET_ASM_FUNCTION_EPILOGUE
#define TARGET_ASM_FUNCTION_EPILOGUE i860_output_function_epilogue
#undef TARGET_INIT_LIBFUNCS
#define TARGET_INIT_LIBFUNCS i860_init_libfuncs
#undef TARGET_BUILD_BUILTIN_VA_LIST
#define TARGET_BUILD_BUILTIN_VA_LIST i860_build_builtin_va_list
#undef TARGET_GIMPLIFY_VA_ARG_EXPR
#define TARGET_GIMPLIFY_VA_ARG_EXPR i860_gimplify_va_arg_expr
#undef TARGET_STRUCT_VALUE_RTX
#define TARGET_STRUCT_VALUE_RTX i860_struct_value_rtx
#undef TARGET_EXPAND_BUILTIN_SAVEREGS
#define TARGET_EXPAND_BUILTIN_SAVEREGS i860_saveregs
struct gcc_target targetm = TARGET_INITIALIZER;