aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Stallman <rms@gnu.org>1993-04-29 16:55:35 +0000
committerRichard Stallman <rms@gnu.org>1993-04-29 16:55:35 +0000
commit2505bc9700f24c9e1478c19822fd82c0f5c6f9e9 (patch)
treeb7979570d503576e1b73f025935ecd040057a854 /gcc
parent32c454f6c71d154c5f51188ce44f82727db8d0a7 (diff)
downloadgcc-2505bc9700f24c9e1478c19822fd82c0f5c6f9e9.zip
gcc-2505bc9700f24c9e1478c19822fd82c0f5c6f9e9.tar.gz
gcc-2505bc9700f24c9e1478c19822fd82c0f5c6f9e9.tar.bz2
(output_move_double): Support XFmode moves.
From-SVN: r4274
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/m68k/m68k.c176
1 files changed, 152 insertions, 24 deletions
diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
index 08b73bf..f0ba65b 100644
--- a/gcc/config/m68k/m68k.c
+++ b/gcc/config/m68k/m68k.c
@@ -870,6 +870,7 @@ singlemove_string (operands)
return "sub%.l %0,%0";
}
+
/* Output assembler code to perform a doubleword move insn
with operands OPERANDS. */
@@ -877,9 +878,17 @@ char *
output_move_double (operands)
rtx *operands;
{
- enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
+ enum
+ {
+ REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP
+ } optype0, optype1;
rtx latehalf[2];
+ rtx middlehalf[2];
rtx addreg0 = 0, addreg1 = 0;
+ int size = GET_MODE_SIZE (GET_MODE (operands[1]));
+
+ middlehalf[0] = 0;
+ middlehalf[1] = 0;
/* First classify both operands. */
@@ -925,15 +934,31 @@ output_move_double (operands)
if (optype0 == PUSHOP && optype1 == POPOP)
{
operands[0] = XEXP (XEXP (operands[0], 0), 0);
- output_asm_insn ("subq%.l %#8,%0", operands);
- operands[0] = gen_rtx (MEM, DImode, operands[0]);
+ if (size == 12)
+ output_asm_insn ("sub%.l %#12,%0", operands);
+ else
+ output_asm_insn ("subq%.l %#8,%0", operands);
+ if (GET_MODE (operands[1]) == XFmode)
+ operands[0] = gen_rtx (MEM, XFmode, operands[0]);
+ else if (GET_MODE (operands[0]) == DFmode)
+ operands[0] = gen_rtx (MEM, DFmode, operands[0]);
+ else
+ operands[0] = gen_rtx (MEM, DImode, operands[0]);
optype0 = OFFSOP;
}
if (optype0 == POPOP && optype1 == PUSHOP)
{
operands[1] = XEXP (XEXP (operands[1], 0), 0);
- output_asm_insn ("subq%.l %#8,%1", operands);
- operands[1] = gen_rtx (MEM, DImode, operands[1]);
+ if (size == 12)
+ output_asm_insn ("sub%.l %#12,%1", operands);
+ else
+ output_asm_insn ("subq%.l %#8,%1", operands);
+ if (GET_MODE (operands[1]) == XFmode)
+ operands[1] = gen_rtx (MEM, XFmode, operands[1]);
+ else if (GET_MODE (operands[1]) == DFmode)
+ operands[1] = gen_rtx (MEM, DFmode, operands[1]);
+ else
+ operands[1] = gen_rtx (MEM, DImode, operands[1]);
optype1 = OFFSOP;
}
@@ -955,21 +980,83 @@ output_move_double (operands)
for the high-numbered word and in some cases alter the
operands in OPERANDS to be suitable for the low-numbered word. */
- if (optype0 == REGOP)
- latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
- else if (optype0 == OFFSOP)
- latehalf[0] = adj_offsettable_operand (operands[0], 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] = adj_offsettable_operand (operands[1], 4);
- else if (optype1 == CNSTOP)
- split_double (operands[1], &operands[1], &latehalf[1]);
+ if (size == 12)
+ {
+ if (optype0 == REGOP)
+ {
+ latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 2);
+ middlehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ }
+ else if (optype0 == OFFSOP)
+ {
+ middlehalf[0] = adj_offsettable_operand (operands[0], 4);
+ latehalf[0] = adj_offsettable_operand (operands[0], size - 4);
+ }
+ else
+ {
+ middlehalf[0] = operands[0];
+ latehalf[0] = operands[0];
+ }
+
+ if (optype1 == REGOP)
+ {
+ latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 2);
+ middlehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+ }
+ else if (optype1 == OFFSOP)
+ {
+ middlehalf[1] = adj_offsettable_operand (operands[1], 4);
+ latehalf[1] = adj_offsettable_operand (operands[1], size - 4);
+ }
+ else if (optype1 == CNSTOP)
+ {
+ if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ {
+ REAL_VALUE_TYPE r;
+ long l[3];
+
+ REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
+ REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, l);
+ operands[1] = GEN_INT (l[0]);
+ middlehalf[1] = GEN_INT (l[1]);
+ latehalf[1] = GEN_INT (l[2]);
+ }
+ else if (CONSTANT_P (operands[1]))
+ {
+ /* actually, no non-CONST_DOUBLE constant should ever
+ appear here. */
+ abort ();
+ if (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) < 0)
+ latehalf[1] = constm1_rtx;
+ else
+ latehalf[1] = const0_rtx;
+ }
+ }
+ else
+ {
+ middlehalf[1] = operands[1];
+ latehalf[1] = operands[1];
+ }
+ }
else
- latehalf[1] = operands[1];
+ /* size is not 12: */
+ {
+ if (optype0 == REGOP)
+ latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ else if (optype0 == OFFSOP)
+ latehalf[0] = adj_offsettable_operand (operands[0], size - 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] = adj_offsettable_operand (operands[1], size - 4);
+ else if (optype1 == CNSTOP)
+ split_double (operands[1], &operands[1], &latehalf[1]);
+ else
+ latehalf[1] = operands[1];
+ }
/* If insn is effectively movd N(sp),-(sp) then we will do the
high word first. We should use the adjusted operand 1 (which is N+4(sp))
@@ -989,13 +1076,24 @@ output_move_double (operands)
if (optype0 == PUSHOP || optype1 == PUSHOP
|| (optype0 == REGOP && optype1 == REGOP
- && REGNO (operands[0]) == REGNO (latehalf[1])))
+ && ((middlehalf[1] && REGNO (operands[0]) == REGNO (middlehalf[1]))
+ || REGNO (operands[0]) == REGNO (latehalf[1]))))
{
/* Make any unoffsettable addresses point at high-numbered word. */
if (addreg0)
- output_asm_insn ("addql %#4,%0", &addreg0);
+ {
+ if (size == 12)
+ output_asm_insn ("addql %#8,%0", &addreg0);
+ else
+ output_asm_insn ("addql %#4,%0", &addreg0);
+ }
if (addreg1)
- output_asm_insn ("addql %#4,%0", &addreg1);
+ {
+ if (size == 12)
+ output_asm_insn ("addql %#8,%0", &addreg1);
+ else
+ output_asm_insn ("addql %#4,%0", &addreg1);
+ }
/* Do that word. */
output_asm_insn (singlemove_string (latehalf), latehalf);
@@ -1006,6 +1104,15 @@ output_move_double (operands)
if (addreg1)
output_asm_insn ("subql %#4,%0", &addreg1);
+ if (size == 12)
+ {
+ output_asm_insn (singlemove_string (middlehalf), middlehalf);
+ if (addreg0)
+ output_asm_insn ("subql %#4,%0", &addreg0);
+ if (addreg1)
+ output_asm_insn ("subql %#4,%0", &addreg1);
+ }
+
/* Do low-numbered word. */
return singlemove_string (operands);
}
@@ -1014,6 +1121,17 @@ output_move_double (operands)
output_asm_insn (singlemove_string (operands), operands);
+ /* Do the middle one of the three words for long double */
+ if (size == 12)
+ {
+ if (addreg0)
+ output_asm_insn ("addql %#4,%0", &addreg0);
+ if (addreg1)
+ output_asm_insn ("addql %#4,%0", &addreg1);
+
+ output_asm_insn (singlemove_string (middlehalf), middlehalf);
+ }
+
/* Make any unoffsettable addresses point at high-numbered word. */
if (addreg0)
output_asm_insn ("addql %#4,%0", &addreg0);
@@ -1025,9 +1143,19 @@ output_move_double (operands)
/* Undo the adds we just did. */
if (addreg0)
- output_asm_insn ("subql %#4,%0", &addreg0);
+ {
+ if (size == 12)
+ output_asm_insn ("subql %#8,%0", &addreg0);
+ else
+ output_asm_insn ("subql %#4,%0", &addreg0);
+ }
if (addreg1)
- output_asm_insn ("subql %#4,%0", &addreg1);
+ {
+ if (size == 12)
+ output_asm_insn ("subql %#8,%0", &addreg1);
+ else
+ output_asm_insn ("subql %#4,%0", &addreg1);
+ }
return "";
}