IA64 HP-UX ILP32 patch for __builtin_return_address (PR 11535)
Steve Ellcey
sje@cup.hp.com
Thu Jul 31 18:18:00 GMT 2003
Combined with my earlier patch
(http://gcc.gnu.org/ml/gcc-patches/2003-07/msg02962.html) this fixes PR
11535. The problem here is that on IA64 branch registers can only be
moved from/to general registers. They cannot be loaded or stored
directly from memory and they cannot be accessed in a subreg mode, they
have to be moved as entire 8 byte quantities. I tested this on ToT and
am currently testing on the 3.3 branch. I would like to check in this
and the earlier patch on both.
Steve Ellcey
sje@cup.hp.com
2003-07-31 Steve Ellcey <sje@cup.hp.com>
* config/ia64/ia64.h (GENERAL_REGNO_P): Do not consider
RETURN_ADDRESS_POINTER_REGNUM to be a general register.
(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.
*** 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 Thu Jul 31 09:55:05 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
More information about the Gcc-patches
mailing list