Patch to fix x86 output_move_double corrupting cc0 (version 2)
John Wehle
john@feith.com
Mon Apr 19 21:27:00 GMT 1999
[ As it turns out there is no such thing as a non-offsettable memory
operand on the x86. This version of the patch removes unnecessary code. ]
The x86 port has the naive belief that register to register and
register to memory moves don't modify cc0. Unfortunately the port
has a habit of using add, dec, inc, sub, etc. when generating the
actual move. One such function that does this is output_move_double
if the operand is a non-offsettable memory operand.
ChangeLog:
Mon Apr 19 22:33:26 EDT 1999 John Wehle (john@feith.com)
* i386.c (output_move_double): Abort if a non-offsettable
memory operand is encountered. Delete unused code.
(find_addr_reg): Remove.
Enjoy!
-- John Wehle
------------------8<------------------------8<------------------------
*** gcc/config/i386/i386.c.ORIGINAL Mon Apr 19 16:12:28 1999
--- gcc/config/i386/i386.c Mon Apr 19 16:52:32 1999
*************** singlemove_string (operands)
*** 992,1023 ****
}
}
- /* Return a REG that occurs in ADDR with coefficient 1.
- ADDR can be effectively incremented by incrementing REG. */
-
- static rtx
- find_addr_reg (addr)
- 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 ();
- }
-
/* Output an insn to add the constant N to the register X. */
static void
--- 992,997 ----
*************** output_move_double (operands)
*** 1055,1061 ****
rtx latehalf[2];
rtx middlehalf[2];
rtx xops[2];
- rtx addreg0 = 0, addreg1 = 0;
int dest_overlapped_low = 0;
int size = GET_MODE_SIZE (GET_MODE (operands[0]));
--- 1029,1034 ----
*************** output_move_double (operands)
*** 1092,1102 ****
else
optype1 = RNDOP;
! /* Check for the cases that the operand constraints are not
! supposed to allow to happen. Abort if we get one,
! because generating code for these cases is painful. */
! if (optype0 == RNDOP || optype1 == RNDOP)
abort ();
/* If one operand is decrementing and one is incrementing
--- 1065,1078 ----
else
optype1 = RNDOP;
! /* Check for the cases that are not supposed to happen
! either due to the operand constraints or the fact
! that all memory operands on the x86 are offsettable.
! Abort if we get one, because generating code for these
! cases is painful. */
! if (optype0 == RNDOP || optype1 == RNDOP
! || optype0 == MEMOP || optype1 == MEMOP)
abort ();
/* If one operand is decrementing and one is incrementing
*************** output_move_double (operands)
*** 1131,1145 ****
optype1 = OFFSOP;
}
- /* If an operand is an unoffsettable memory ref, find a register
- we can increment temporarily to make it refer to the second word. */
-
- if (optype0 == MEMOP)
- addreg0 = find_addr_reg (XEXP (operands[0], 0));
-
- if (optype1 == MEMOP)
- addreg1 = find_addr_reg (XEXP (operands[1], 0));
-
/* Ok, we can do one word at a time.
Normally we do the low-numbered word first,
but if either operand is autodecrementing then we
--- 1107,1112 ----
*************** output_move_double (operands)
*** 1236,1243 ****
emit the move late-half first. Otherwise, compute the MEM address
into the upper part of N and use that as a pointer to the memory
operand. */
! if (optype0 == REGOP
! && (optype1 == OFFSOP || optype1 == MEMOP))
{
if (reg_mentioned_p (operands[0], XEXP (operands[1], 0))
&& reg_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
--- 1203,1209 ----
emit the move late-half first. Otherwise, compute the MEM address
into the upper part of N and use that as a pointer to the memory
operand. */
! if (optype0 == REGOP && optype1 == OFFSOP)
{
if (reg_mentioned_p (operands[0], XEXP (operands[1], 0))
&& reg_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
*************** output_move_double (operands)
*** 1269,1278 ****
|| reg_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
goto compadr;
- /* JRV says this can't happen: */
- if (addreg0 || addreg1)
- abort ();
-
/* Only the middle reg conflicts; simply put it last. */
output_asm_insn (singlemove_string (operands), operands);
output_asm_insn (singlemove_string (latehalf), latehalf);
--- 1235,1240 ----
*************** output_move_double (operands)
*** 1307,1335 ****
|| REGNO (operands[0]) == REGNO (latehalf[1])))
|| dest_overlapped_low)
{
! /* Make any unoffsettable addresses point at high-numbered word. */
! if (addreg0)
! asm_add (size-4, addreg0);
! if (addreg1)
! asm_add (size-4, addreg1);
!
! /* Do that word. */
output_asm_insn (singlemove_string (latehalf), latehalf);
- /* Undo the adds we just did. */
- if (addreg0)
- asm_add (-4, addreg0);
- if (addreg1)
- asm_add (-4, addreg1);
-
if (size == 12)
! {
! output_asm_insn (singlemove_string (middlehalf), middlehalf);
! if (addreg0)
! asm_add (-4, addreg0);
! if (addreg1)
! asm_add (-4, addreg1);
! }
/* Do low-numbered word. */
return singlemove_string (operands);
--- 1269,1279 ----
|| REGNO (operands[0]) == REGNO (latehalf[1])))
|| dest_overlapped_low)
{
! /* Do the high-numbered word. */
output_asm_insn (singlemove_string (latehalf), latehalf);
if (size == 12)
! output_asm_insn (singlemove_string (middlehalf), middlehalf);
/* Do low-numbered word. */
return singlemove_string (operands);
*************** output_move_double (operands)
*** 1341,1369 ****
/* Do the middle one of the three words for long double */
if (size == 12)
! {
! if (addreg0)
! asm_add (4, addreg0);
! if (addreg1)
! asm_add (4, addreg1);
!
! output_asm_insn (singlemove_string (middlehalf), middlehalf);
! }
! /* Make any unoffsettable addresses point at high-numbered word. */
! if (addreg0)
! asm_add (4, addreg0);
! if (addreg1)
! asm_add (4, addreg1);
!
! /* Do that word. */
output_asm_insn (singlemove_string (latehalf), latehalf);
-
- /* Undo the adds we just did. */
- if (addreg0)
- asm_add (4-size, addreg0);
- if (addreg1)
- asm_add (4-size, addreg1);
return "";
}
--- 1285,1294 ----
/* Do the middle one of the three words for long double */
if (size == 12)
! output_asm_insn (singlemove_string (middlehalf), middlehalf);
! /* Do the high-numbered word. */
output_asm_insn (singlemove_string (latehalf), latehalf);
return "";
}
-------------------------------------------------------------------------
| Feith Systems | Voice: 1-215-646-8000 | Email: john@feith.com |
| John Wehle | Fax: 1-215-540-5495 | |
-------------------------------------------------------------------------
More information about the Gcc-patches
mailing list