+2004-07-19 Andreas Krebbel <krebbel1@de.ibm.com>
+
+ * config/s390/s390-protos.h (s390_return_address_offset): Prototype
+ added.
+ * config/s390/s390.c (regclass_map initializer): Register 35 added to
+ ADDR_REGS.
+ (load_multiple_operation, store_multiple_operation): Removed
+ pointless sanity check.
+ (s390_decompose_address): Added check for return_address_pointer_rtx.
+ (s390_return_addr_rtx): Use return_address_pointer_rtx for count == 0.
+ (s390_return_address_offset): New function.
+ * config/s390/s390.h (FIRST_PSEUDO_REGISTER): Increased to 36.
+ (FRAME_REGNO_P): Added check for register 35.
+ (FIXED_REGISTERS, CALL_USED_REGISTERS, CALL_REALLY_USED_REGISTERS,
+ REG_ALLOC_ORDER): Appended entry for register 35.
+ (REG_CLASS_CONTENTS): Adjusted class masks for register 35.
+ (EH_RETURN_HANDLER_RTX): Use return_address_pointer_rtx.
+ (RETURN_ADDRESS_POINTER_REGNUM): New macro.
+ (ELIMINABLE_REGS, INITIAL_ELIMINATION_OFFSET): Return address pointer
+ is eliminable using stack pointer or hard frame pointer.
+ (REGISTER_NAMES): Added name for register 35.
+ * config/s390/s390.md ("load_multiple", "store_multiple"): Removed
+ pointless sanity check.
+
2004-07-19 Roger Sayle <roger@eyesopen.com>
* fold-const.c (tree_expr_nonzero_p): Add function prototype.
FP_REGS, FP_REGS, FP_REGS, FP_REGS,
FP_REGS, FP_REGS, FP_REGS, FP_REGS,
FP_REGS, FP_REGS, FP_REGS, FP_REGS,
- ADDR_REGS, NO_REGS, ADDR_REGS
+ ADDR_REGS, NO_REGS, ADDR_REGS, ADDR_REGS
};
/* Return attribute type of insn. */
else
return 0;
- if (src_addr == frame_pointer_rtx || src_addr == arg_pointer_rtx)
- return 0;
-
for (i = 1; i < count; i++)
{
rtx elt = XVECEXP (op, 0, i);
else
return 0;
- if (dest_addr == frame_pointer_rtx || dest_addr == arg_pointer_rtx)
- return 0;
-
for (i = 1; i < count; i++)
{
rtx elt = XVECEXP (op, 0, i);
/* Validate displacement. */
if (!disp)
{
- /* If the argument pointer is involved, the displacement will change
- later anyway as the argument pointer gets eliminated. This could
- make a valid displacement invalid, but it is more likely to make
- an invalid displacement valid, because we sometimes access the
- register save area via negative offsets to the arg pointer.
+ /* If the argument pointer or the return address pointer are involved,
+ the displacement will change later anyway as the virtual registers get
+ eliminated. This could make a valid displacement invalid, but it is
+ more likely to make an invalid displacement valid, because we sometimes
+ access the register save area via negative offsets to one of those
+ registers.
Thus we don't check the displacement for validity here. If after
elimination the displacement turns out to be invalid after all,
this is fixed up by reload in any case. */
- if (base != arg_pointer_rtx && indx != arg_pointer_rtx)
+ if (base != arg_pointer_rtx
+ && indx != arg_pointer_rtx
+ && base != return_address_pointer_rtx
+ && indx != return_address_pointer_rtx)
if (!DISP_IN_RANGE (offset))
return FALSE;
}
frame pointer of that frame. */
rtx
-s390_return_addr_rtx (int count, rtx frame)
+s390_return_addr_rtx (int count, rtx frame ATTRIBUTE_UNUSED)
{
rtx addr;
value of RETURN_REGNUM is actually saved. */
if (count == 0)
- cfun->machine->save_return_addr_p = true;
-
- /* To retrieve the return address we read the stack slot where the
- corresponding RETURN_REGNUM value was saved. */
+ {
+ cfun->machine->save_return_addr_p = true;
+ return gen_rtx_MEM (Pmode, return_address_pointer_rtx);
+ }
addr = plus_constant (frame, RETURN_REGNUM * UNITS_PER_WORD);
addr = memory_address (Pmode, addr);
return cfun->machine->frame_size + STACK_POINTER_OFFSET;
}
+/* Return offset between return address pointer (location of r14
+ on the stack) and frame pointer initially after prologue. */
+
+HOST_WIDE_INT
+s390_return_address_offset (void)
+{
+ s390_frame_info (1, 1);
+
+ return cfun->machine->frame_size + RETURN_REGNUM * UNITS_PER_WORD;
+}
+
/* Emit insn to save fpr REGNUM at offset OFFSET relative
to register BASE. Return generated insn. */
Reg 33: Condition code
Reg 34: Frame pointer */
-#define FIRST_PSEUDO_REGISTER 35
+#define FIRST_PSEUDO_REGISTER 36
/* Standard register usage. */
#define GENERAL_REGNO_P(N) ((int)(N) >= 0 && (N) < 16)
#define ADDR_REGNO_P(N) ((N) >= 1 && (N) < 16)
#define FP_REGNO_P(N) ((N) >= 16 && (N) < (TARGET_IEEE_FLOAT? 32 : 20))
#define CC_REGNO_P(N) ((N) == 33)
-#define FRAME_REGNO_P(N) ((N) == 32 || (N) == 34)
+#define FRAME_REGNO_P(N) ((N) == 32 || (N) == 34 || (N) == 35)
#define GENERAL_REG_P(X) (REG_P (X) && GENERAL_REGNO_P (REGNO (X)))
#define ADDR_REG_P(X) (REG_P (X) && ADDR_REGNO_P (REGNO (X)))
0, 0, 0, 0, \
0, 0, 0, 0, \
0, 0, 0, 0, \
- 1, 1, 1 }
+ 1, 1, 1, 1 }
#define CALL_USED_REGISTERS \
{ 1, 1, 1, 1, \
1, 1, 1, 1, \
1, 1, 1, 1, \
1, 1, 1, 1, \
- 1, 1, 1 }
+ 1, 1, 1, 1 }
#define CALL_REALLY_USED_REGISTERS \
{ 1, 1, 1, 1, \
1, 1, 1, 1, \
1, 1, 1, 1, \
1, 1, 1, 1, \
- 1, 1, 1 }
+ 1, 1, 1, 1 }
#define CONDITIONAL_REGISTER_USAGE s390_conditional_register_usage ()
{ 1, 2, 3, 4, 5, 0, 13, 12, 11, 10, 9, 8, 7, 6, 14, \
16, 17, 18, 19, 20, 21, 22, 23, \
24, 25, 26, 27, 28, 29, 30, 31, \
- 15, 32, 33, 34 }
+ 15, 32, 33, 34, 35 }
/* Fitting values into registers. */
#define REG_CLASS_CONTENTS \
{ \
{ 0x00000000, 0x00000000 }, /* NO_REGS */ \
- { 0x0000fffe, 0x00000005 }, /* ADDR_REGS */ \
- { 0x0000ffff, 0x00000005 }, /* GENERAL_REGS */ \
+ { 0x0000fffe, 0x0000000d }, /* ADDR_REGS */ \
+ { 0x0000ffff, 0x0000000d }, /* GENERAL_REGS */ \
{ 0xffff0000, 0x00000000 }, /* FP_REGS */ \
- { 0xfffffffe, 0x00000005 }, /* ADDR_FP_REGS */ \
- { 0xffffffff, 0x00000005 }, /* GENERAL_FP_REGS */ \
- { 0xffffffff, 0x00000007 }, /* ALL_REGS */ \
+ { 0xfffffffe, 0x0000000d }, /* ADDR_FP_REGS */ \
+ { 0xffffffff, 0x0000000d }, /* GENERAL_FP_REGS */ \
+ { 0xffffffff, 0x0000000f }, /* ALL_REGS */ \
}
/* Register -> class mapping. */
/* Describe how we implement __builtin_eh_return. */
#define EH_RETURN_DATA_REGNO(N) ((N) < 4 ? (N) + 6 : INVALID_REGNUM)
-#define EH_RETURN_HANDLER_RTX \
- gen_rtx_MEM (Pmode, plus_constant (arg_pointer_rtx, \
- -STACK_POINTER_OFFSET + UNITS_PER_WORD*RETURN_REGNUM))
-
+#define EH_RETURN_HANDLER_RTX gen_rtx_MEM (Pmode, return_address_pointer_rtx)
+
/* Select a format to encode pointers in exception handling data. */
#define ASM_PREFERRED_EH_DATA_FORMAT(CODE, GLOBAL) \
(flag_pic \
#define FRAME_POINTER_REGNUM 34
#define HARD_FRAME_POINTER_REGNUM 11
#define ARG_POINTER_REGNUM 32
+#define RETURN_ADDRESS_POINTER_REGNUM 35
/* The static chain must be call-clobbered, but not used for
function argument passing. As register 1 is clobbered by
#define INITIAL_FRAME_POINTER_OFFSET(DEPTH) (DEPTH) = 0
-#define ELIMINABLE_REGS \
-{{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
- { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \
- { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
- { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}}
+#define ELIMINABLE_REGS \
+{{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
+ { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \
+ { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
+ { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \
+ { RETURN_ADDRESS_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
+ { RETURN_ADDRESS_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}}
#define CAN_ELIMINATE(FROM, TO) (1)
{ (OFFSET) = s390_arg_frame_offset (); } \
else if ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \
{ (OFFSET) = s390_arg_frame_offset (); } \
+ else if ((FROM) == RETURN_ADDRESS_POINTER_REGNUM \
+ && ((TO) == STACK_POINTER_REGNUM \
+ || (TO) == HARD_FRAME_POINTER_REGNUM)) \
+ { (OFFSET) = s390_return_address_offset (); } \
else \
abort(); \
}
indexed by compiler's hard-register-number (see above). */
#define REGISTER_NAMES \
{ "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7", \
- "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", \
+ "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", \
"%f0", "%f2", "%f4", "%f6", "%f1", "%f3", "%f5", "%f7", \
- "%f8", "%f10", "%f12", "%f14", "%f9", "%f11", "%f13", "%f15", \
- "%ap", "%cc", "%fp" \
+ "%f8", "%f10", "%f12", "%f14", "%f9", "%f11", "%f13", "%f15", \
+ "%ap", "%cc", "%fp", "%rp" \
}
/* Emit a dtp-relative reference to a TLS variable. */