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]

Re: IA64 HP-UX ILP32 patch for __builtin_return_address (PR 11535)


There is a bug in my earlier patch for __builtin_return_address on IA64
that my testing did not catch.  Here is an updated patch for the
__builtin_return_address bug.  This replaces

	http://gcc.gnu.org/ml/gcc-patches/2003-07/msg02993.html

(to which this mail is a followup) but my other (non-IA64 specific) patch

	http://gcc.gnu.org/ml/gcc-patches/2003-07/msg02962.html

is still needed as well.  This latest change modifies ia64_expand_move
to handle the new situation where ia64_move_ok returns FALSE because we
are trying to move a branch register into memory with a store
instruction.  Branch registers can only be moved to/from general
registers on IA64.

Steve Ellcey
sje@cup.hp.com

2003-08-01  Steve Ellcey  <sje@cup.hp.com>

	* config/ia64/ia64.h (GENERAL_REGNO_P): Do not consider 
	RETURN_ADDRESS_POINTER_REGNUM to be a general regiter.
	(BR_REGNO_P): Recognize RETURN_ADDRESS_POINTER_REGNUM as
	a branch register.
	* config/ia64/ia64.c (hard_br_register_operand): New routine.
	(ia64_move_ok): Branch registers can only be moved to/from
	general registers.
	(ia64_expand_move): Handle store of branch register to memory.



*** gcc.orig/gcc/gcc/config/ia64/ia64.h	Thu Jul 31 09:49:30 2003
--- gcc/gcc/gcc/config/ia64/ia64.h	Thu Jul 31 09:52:04 2003
*************** while (0)
*** 462,472 ****
  #define GR_REGNO_P(REGNO) ((unsigned HOST_WIDE_INT) (REGNO) <= 127)
  #define FR_REGNO_P(REGNO) ((REGNO) >= 128 && (REGNO) <= 255)
  #define PR_REGNO_P(REGNO) ((REGNO) >= 256 && (REGNO) <= 319)
! #define BR_REGNO_P(REGNO) ((REGNO) >= 320 && (REGNO) <= 327)
  #define GENERAL_REGNO_P(REGNO) \
    (GR_REGNO_P (REGNO)							\
!    || (REGNO) == FRAME_POINTER_REGNUM					\
!    || (REGNO) == RETURN_ADDRESS_POINTER_REGNUM)
  
  #define GR_REG(REGNO) ((REGNO) + 0)
  #define FR_REG(REGNO) ((REGNO) + 128)
--- 462,473 ----
  #define GR_REGNO_P(REGNO) ((unsigned HOST_WIDE_INT) (REGNO) <= 127)
  #define FR_REGNO_P(REGNO) ((REGNO) >= 128 && (REGNO) <= 255)
  #define PR_REGNO_P(REGNO) ((REGNO) >= 256 && (REGNO) <= 319)
! #define BR_REGNO_P(REGNO) (((REGNO) >= 320 && (REGNO) <= 327)		\
!    || ((REGNO) == RETURN_ADDRESS_POINTER_REGNUM))
! 	
  #define GENERAL_REGNO_P(REGNO) \
    (GR_REGNO_P (REGNO)							\
!    || (REGNO) == FRAME_POINTER_REGNUM)
  
  #define GR_REG(REGNO) ((REGNO) + 0)
  #define FR_REG(REGNO) ((REGNO) + 128)
*** gcc.orig/gcc/gcc/config/ia64/ia64.c	Thu Jul 31 09:49:33 2003
--- gcc/gcc/gcc/config/ia64/ia64.c	Fri Aug  1 13:38:24 2003
*************** static void do_restore PARAMS ((rtx (*)(
*** 180,185 ****
--- 180,186 ----
  static rtx gen_movdi_x PARAMS ((rtx, rtx, rtx));
  static rtx gen_fr_spill_x PARAMS ((rtx, rtx, rtx));
  static rtx gen_fr_restore_x PARAMS ((rtx, rtx, rtx));
+ static int hard_br_register_operand PARAMS ((rtx, enum machine_mode));
  
  static enum machine_mode hfa_element_mode PARAMS ((tree, int));
  static bool ia64_function_ok_for_sibcall PARAMS ((tree, tree));
*************** gr_register_operand (op, mode)
*** 584,589 ****
--- 585,611 ----
    return 1;
  }
  
+ 
+ /* Return 1 if OP is a register operand that is a BR reg.  */
+ 
+ static int
+ hard_br_register_operand (op, mode)
+      rtx op;
+      enum machine_mode mode;
+ {
+   if (! register_operand (op, mode))
+     return 0;
+   if (GET_CODE (op) == SUBREG)
+     op = SUBREG_REG (op);
+   if (GET_CODE (op) == REG)
+     {
+       unsigned int regno = REGNO (op);
+       if (regno < FIRST_PSEUDO_REGISTER)
+ 	return BR_REGNO_P (regno);
+     }
+   return 0;
+ }
+ 
  /* Return 1 if OP is a register operand that is (or could be) an FR reg.  */
  
  int
*************** int
*** 1046,1051 ****
--- 1068,1080 ----
  ia64_move_ok (dst, src)
       rtx dst, src;
  {
+   /* Branch registers can only be moved to/from general registers and
+      only in DImode.  */
+   if (hard_br_register_operand (dst, VOIDmode))
+     return gr_register_operand (src, DImode);
+   if (hard_br_register_operand (src, VOIDmode))
+     return gr_register_operand (dst, DImode);
+ 
    /* If we're under init_recog_no_volatile, we'll not be able to use
       memory_operand.  So check the code directly and don't worry about
       the validity of the underlying address, which should have been
*************** ia64_expand_move (op0, op1)
*** 1295,1301 ****
    enum machine_mode mode = GET_MODE (op0);
  
    if (!reload_in_progress && !reload_completed && !ia64_move_ok (op0, op1))
!     op1 = force_reg (mode, op1);
  
    if ((mode == Pmode || mode == ptr_mode) && symbolic_operand (op1, VOIDmode))
      {
--- 1324,1343 ----
    enum machine_mode mode = GET_MODE (op0);
  
    if (!reload_in_progress && !reload_completed && !ia64_move_ok (op0, op1))
!     {
!       op1 = force_reg (mode, op1);
!       if (!ia64_move_ok (op0, op1))
! 	{
! 	  if (hard_br_register_operand(op1, VOIDmode))
! 	    {
! 	      rtx temp_reg = gen_reg_rtx (mode);
! 	      emit_move_insn (temp_reg, op1);
! 	      op1 = temp_reg;
! 	    }
!           if (!ia64_move_ok (op0, op1))
! 	    abort ();
! 	}
!     }
  
    if ((mode == Pmode || mode == ptr_mode) && symbolic_operand (op1, VOIDmode))
      {


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