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