This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

arm-pe: Do not generate type 2 LDM instructions with writeback


Hi Guys,

  Whilst looking over the arm-pe port I found that it was generating
  LDM instructions using writeback "sp!" and CPSR update "^" which is
  UNPREDICTABLE if the PC is not one of the registers being loaded.
  The following patch takes care of this problem and fixes quite a few
  unexpected failures in the gcc testsuite.  (There are still lots
  more that need to be looked at though - maybe one day).

Cheers
        Nick

PS.  Sorry Richard - this patch adds more code :-(

2003-03-13  Nick Clifton  <nickc at redhat dot com>

	* config/arm/arm.c (print_multi_reg): Do not generate a type 2
        LDM instructions with writeback enabled.
        (output_return_instruction): Likewise.

Index: gcc/config/arm/arm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/arm.c,v
retrieving revision 1.265
diff -c -3 -p -w -r1.265 arm.c
*** gcc/config/arm/arm.c	10 Mar 2003 17:53:18 -0000	1.265
--- gcc/config/arm/arm.c	13 Mar 2003 11:55:55 -0000
*************** print_multi_reg (stream, instr, reg, mas
*** 7204,7210 ****
  	not_first = TRUE;
        }
  
!   fprintf (stream, "}%s\n", TARGET_APCS_32 ? "" : "^");
  }
  
  /* Output a 'call' insn.  */
--- 7204,7220 ----
  	not_first = TRUE;
        }
  
!   fprintf (stream, "}");
! 
!   /* Add a ^ character for the 26-bit ABI, but only if we were loading
!      the PC or not updating the stack pointer.  Otherwise we generate
!      an UNPREDICTABLE instruction.  */
!   if (! TARGET_APCS_32
!       && (((mask & (1 << PC_REGNUM)) != 0)
! 	  || strchr (instr, '!') == NULL))
!     fprintf (stream, "^");
!   
!   fprintf (stream, "\n");
  }
  
  /* Output a 'call' insn.  */
*************** output_return_instruction (operand, real
*** 8210,8229 ****
  	  
  	  if (live_regs_mask & (1 << LR_REGNUM))
  	    {
! 	      int l = strlen (return_reg);
! 
! 	      if (! first)
! 		{
! 		  memcpy (p, ", ", 2);
! 		  p += 2;
! 		}
! 
! 	      memcpy (p, "%|", 2);
! 	      memcpy (p + 2, return_reg, l);
! 	      strcpy (p + 2 + l, ((TARGET_APCS_32 
! 				   && !IS_INTERRUPT (func_type)) 
! 				  || !really_return) 
! 		      ? "}" : "}^");
  	    }
  	  else
  	    strcpy (p, "}");
--- 8220,8245 ----
  	  
  	  if (live_regs_mask & (1 << LR_REGNUM))
  	    {
! 	      sprintf (p, "%s%%|%s}", first ? "" : ", ", return_reg);
! 	      /* Decide if we need to add the ^ symbol to the end of the
! 		 register list.	 This causes the saved condition codes
! 		 register to be copied into the current condition codes
! 		 register.  We do the copy if we are conforming to the 32-bit
! 		 ABI and this is an interrupt function, or if we are
! 		 conforming to the 26-bit ABI.  There is a special case for
! 		 the 26-bit ABI however, which is if we are writing back the
! 		 stack pointer but not loading the PC.  In this case adding
! 		 the ^ symbol would create a type 2 LDM instruction, where
! 		 writeback is UNPREDICTABLE.  We are safe in leaving the ^
! 		 character off in this case however, since the actual return
! 		 instruction will be a MOVS which will restore the CPSR.  */
! 	      if ((TARGET_APCS_32 && IS_INTERRUPT (func_type))
! 		  || (really_return
! 		      && ! frame_pointer_needed
! 		      && ((live_regs_mask & (1 << SP_REGNUM)) == 0)
! 		      && ((live_regs_mask & (1 << PC_REGNUM)) == 0))
! 		  )
! 		strcat (p, "^");
  	    }
  	  else
  	    strcpy (p, "}");


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]