mirror of git://gcc.gnu.org/git/gcc.git
mn10300: Emit the movm stores in the correct order.
From-SVN: r168671
This commit is contained in:
parent
e3b5c2f3ea
commit
cc909bba64
|
@ -1,5 +1,11 @@
|
||||||
2011-01-11 Richard Henderson <rth@redhat.com>
|
2011-01-11 Richard Henderson <rth@redhat.com>
|
||||||
|
|
||||||
|
* config/mn10300/mn10300.c (mn10300_gen_multiple_store): Make static.
|
||||||
|
Emit register stores with the same offsets as the hardware.
|
||||||
|
(mn10300_store_multiple_operation): Don't check that the register
|
||||||
|
save offsets are monotonic.
|
||||||
|
* config/mn10300/mn10300-protos.h: Update.
|
||||||
|
|
||||||
* config/mn10300/mn10300.h (ASM_PN_FORMAT): Delete.
|
* config/mn10300/mn10300.h (ASM_PN_FORMAT): Delete.
|
||||||
|
|
||||||
* config/mn10300/mn10300.h (INCOMING_RETURN_ADDR_RTX): Define
|
* config/mn10300/mn10300.h (INCOMING_RETURN_ADDR_RTX): Define
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
extern rtx mn10300_legitimize_pic_address (rtx, rtx);
|
extern rtx mn10300_legitimize_pic_address (rtx, rtx);
|
||||||
extern int mn10300_legitimate_pic_operand_p (rtx);
|
extern int mn10300_legitimate_pic_operand_p (rtx);
|
||||||
extern bool mn10300_function_value_regno_p (const unsigned int);
|
extern bool mn10300_function_value_regno_p (const unsigned int);
|
||||||
extern void mn10300_gen_multiple_store (int);
|
|
||||||
extern int mn10300_get_live_callee_saved_regs (void);
|
extern int mn10300_get_live_callee_saved_regs (void);
|
||||||
extern bool mn10300_hard_regno_mode_ok (unsigned int, Mmode);
|
extern bool mn10300_hard_regno_mode_ok (unsigned int, Mmode);
|
||||||
extern bool mn10300_legitimate_constant_p (rtx);
|
extern bool mn10300_legitimate_constant_p (rtx);
|
||||||
|
|
|
@ -689,51 +689,61 @@ F (rtx r)
|
||||||
(const_int -N*4)))
|
(const_int -N*4)))
|
||||||
(reg:SI R1))) */
|
(reg:SI R1))) */
|
||||||
|
|
||||||
void
|
static void
|
||||||
mn10300_gen_multiple_store (int mask)
|
mn10300_gen_multiple_store (unsigned int mask)
|
||||||
{
|
{
|
||||||
if (mask != 0)
|
/* The order in which registers are stored, from SP-4 through SP-N*4. */
|
||||||
|
static const unsigned int store_order[8] = {
|
||||||
|
/* e2, e3: never saved */
|
||||||
|
FIRST_EXTENDED_REGNUM + 4,
|
||||||
|
FIRST_EXTENDED_REGNUM + 5,
|
||||||
|
FIRST_EXTENDED_REGNUM + 6,
|
||||||
|
FIRST_EXTENDED_REGNUM + 7,
|
||||||
|
/* e0, e1, mdrq, mcrh, mcrl, mcvf: never saved. */
|
||||||
|
FIRST_DATA_REGNUM + 2,
|
||||||
|
FIRST_DATA_REGNUM + 3,
|
||||||
|
FIRST_ADDRESS_REGNUM + 2,
|
||||||
|
FIRST_ADDRESS_REGNUM + 3,
|
||||||
|
/* d0, d1, a0, a1, mdr, lir, lar: never saved. */
|
||||||
|
};
|
||||||
|
|
||||||
|
rtx x, elts[9];
|
||||||
|
unsigned int i;
|
||||||
|
int count;
|
||||||
|
|
||||||
|
if (mask == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = count = 0; i < ARRAY_SIZE(store_order); ++i)
|
||||||
{
|
{
|
||||||
int i;
|
unsigned regno = store_order[i];
|
||||||
int count;
|
|
||||||
rtx par;
|
|
||||||
int pari;
|
|
||||||
|
|
||||||
/* Count how many registers need to be saved. */
|
if (((mask >> regno) & 1) == 0)
|
||||||
count = 0;
|
continue;
|
||||||
for (i = 0; i <= LAST_EXTENDED_REGNUM; i++)
|
|
||||||
if ((mask & (1 << i)) != 0)
|
|
||||||
count += 1;
|
|
||||||
|
|
||||||
/* We need one PARALLEL element to update the stack pointer and
|
++count;
|
||||||
an additional element for each register that is stored. */
|
x = plus_constant (stack_pointer_rtx, count * -4);
|
||||||
par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count + 1));
|
x = gen_frame_mem (SImode, x);
|
||||||
|
x = gen_rtx_SET (VOIDmode, x, gen_rtx_REG (SImode, regno));
|
||||||
|
elts[count] = F(x);
|
||||||
|
|
||||||
/* Create the instruction that updates the stack pointer. */
|
/* Remove the register from the mask so that... */
|
||||||
XVECEXP (par, 0, 0)
|
mask &= ~(1u << regno);
|
||||||
= F (gen_rtx_SET (SImode,
|
|
||||||
stack_pointer_rtx,
|
|
||||||
gen_rtx_PLUS (SImode,
|
|
||||||
stack_pointer_rtx,
|
|
||||||
GEN_INT (-count * 4))));
|
|
||||||
|
|
||||||
/* Create each store. */
|
|
||||||
pari = 1;
|
|
||||||
for (i = LAST_EXTENDED_REGNUM; i >= 0; i--)
|
|
||||||
if ((mask & (1 << i)) != 0)
|
|
||||||
{
|
|
||||||
rtx address = gen_rtx_PLUS (SImode,
|
|
||||||
stack_pointer_rtx,
|
|
||||||
GEN_INT (-pari * 4));
|
|
||||||
XVECEXP(par, 0, pari)
|
|
||||||
= F (gen_rtx_SET (VOIDmode,
|
|
||||||
gen_rtx_MEM (SImode, address),
|
|
||||||
gen_rtx_REG (SImode, i)));
|
|
||||||
pari += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
F (emit_insn (par));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ... we can make sure that we didn't try to use a register
|
||||||
|
not listed in the store order. */
|
||||||
|
gcc_assert (mask == 0);
|
||||||
|
|
||||||
|
/* Create the instruction that updates the stack pointer. */
|
||||||
|
x = plus_constant (stack_pointer_rtx, count * -4);
|
||||||
|
x = gen_rtx_SET (VOIDmode, stack_pointer_rtx, x);
|
||||||
|
elts[0] = F(x);
|
||||||
|
|
||||||
|
/* We need one PARALLEL element to update the stack pointer and
|
||||||
|
an additional element for each register that is stored. */
|
||||||
|
x = gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (count + 1, elts));
|
||||||
|
F (emit_insn (x));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1273,27 +1283,19 @@ mn10300_store_multiple_operation (rtx op,
|
||||||
|| INTVAL (XEXP (elt, 1)) != -(count - 1) * 4)
|
|| INTVAL (XEXP (elt, 1)) != -(count - 1) * 4)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Now go through the rest of the vector elements. They must be
|
|
||||||
ordered so that the first instruction stores the highest-numbered
|
|
||||||
register to the highest stack slot and that subsequent instructions
|
|
||||||
store a lower-numbered register to the slot below.
|
|
||||||
|
|
||||||
LAST keeps track of the smallest-numbered register stored so far.
|
|
||||||
MASK is the set of stored registers. */
|
|
||||||
last = LAST_EXTENDED_REGNUM + 1;
|
|
||||||
mask = 0;
|
mask = 0;
|
||||||
for (i = 1; i < count; i++)
|
for (i = 1; i < count; i++)
|
||||||
{
|
{
|
||||||
/* Check that element i is a (set (mem M) R) and that R is valid. */
|
/* Check that element i is a (set (mem M) R). */
|
||||||
|
/* ??? Validate the register order a-la mn10300_gen_multiple_store.
|
||||||
|
Remember: the ordering is *not* monotonic. */
|
||||||
elt = XVECEXP (op, 0, i);
|
elt = XVECEXP (op, 0, i);
|
||||||
if (GET_CODE (elt) != SET
|
if (GET_CODE (elt) != SET
|
||||||
|| (! MEM_P (SET_DEST (elt)))
|
|| (! MEM_P (SET_DEST (elt)))
|
||||||
|| (! REG_P (SET_SRC (elt)))
|
|| (! REG_P (SET_SRC (elt))))
|
||||||
|| REGNO (SET_SRC (elt)) >= last)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* R was OK, so provisionally add it to MASK. We return 0 in any
|
/* Remember which registers are to be saved. */
|
||||||
case if the rest of the instruction has a flaw. */
|
|
||||||
last = REGNO (SET_SRC (elt));
|
last = REGNO (SET_SRC (elt));
|
||||||
mask |= (1 << last);
|
mask |= (1 << last);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue