This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
powerpc patch 5 of 9
- From: Alan Modra <amodra at bigpond dot net dot au>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 20 Feb 2002 21:31:00 +1030
- Subject: powerpc patch 5 of 9
This patch allows use of _savef* and _restf* for ABI_V4, and fixes
a bug in the vrsave code which could have trashed frame_reg_rtx. Now
that r11 is being used (to match the ABI for _savef*), we sidestep
that particular problem.
* config/rs6000/rs6000.c (rs6000_emit_allocate_stack): Copy to
r11 instead of r12.
(rs6000_emit_prologue): Use r11 for frame_ptr_rtx, and always
use frame_ptr_rtx if ABI_V4 and !saving_FPRs_inline. Emit a USE
for frame_reg_rtx when !saving_FPRs_inline.
(rs6000_emit_epilogue): If ABI_V4 and !saving_FPRs_inline, set up
r11 for _restf, delay loading lr, and set up the call to _restf
before adjusting the stack.
* config/rs6000/rs6000.md (save_fpregs_si, save_fpregs_di): Tweak
for extra USE.
(rest_fpregs_si, rest_fpregs_di): New.
Index: gcc/config/rs6000/rs6000.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.286
diff -u -p -r1.286 rs6000.c
--- rs6000.c 2002/02/19 02:53:36 1.286
+++ rs6000.c 2002/02/20 01:35:44
@@ -8391,13 +8427,13 @@ rs6000_emit_stack_tie ()
}
/* Emit the correct code for allocating stack space, as insns.
- If COPY_R12, make sure a copy of the old frame is left in r12.
+ If COPY_R11, make sure a copy of the old frame is left in r11.
The generated code may use hard register 0 as a temporary. */
static void
-rs6000_emit_allocate_stack (size, copy_r12)
+rs6000_emit_allocate_stack (size, copy_r11)
HOST_WIDE_INT size;
- int copy_r12;
+ int copy_r11;
{
rtx insn;
rtx stack_reg = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
@@ -8439,8 +8475,8 @@ rs6000_emit_allocate_stack (size, copy_r
warning ("stack limit expression is not supported");
}
- if (copy_r12 || ! TARGET_UPDATE)
- emit_move_insn (gen_rtx_REG (Pmode, 12), stack_reg);
+ if (copy_r11 || ! TARGET_UPDATE)
+ emit_move_insn (gen_rtx_REG (Pmode, 11), stack_reg);
if (TARGET_UPDATE)
{
@@ -8468,7 +8504,7 @@ rs6000_emit_allocate_stack (size, copy_r
else
insn = emit_insn (gen_adddi3 (stack_reg, stack_reg, todec));
emit_move_insn (gen_rtx_MEM (Pmode, stack_reg),
- gen_rtx_REG (Pmode, 12));
+ gen_rtx_REG (Pmode, 11));
}
RTX_FRAME_RELATED_P (insn) = 1;
@@ -8656,7 +8692,7 @@ rs6000_emit_prologue ()
enum machine_mode reg_mode = TARGET_POWERPC64 ? DImode : SImode;
int reg_size = TARGET_POWERPC64 ? 8 : 4;
rtx sp_reg_rtx = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
- rtx frame_ptr_rtx = gen_rtx_REG (Pmode, 12);
+ rtx frame_ptr_rtx = gen_rtx_REG (Pmode, 11);
rtx frame_reg_rtx = sp_reg_rtx;
rtx cr_save_rtx = NULL;
rtx insn;
@@ -8672,7 +8708,7 @@ rs6000_emit_prologue ()
/* For V.4, update stack before we do any saving and set back pointer. */
if (info->push_p && DEFAULT_ABI == ABI_V4)
{
- if (info->total_size < 32767)
+ if (info->total_size < 32767 && saving_FPRs_inline)
sp_offset = info->total_size;
else
frame_reg_rtx = frame_ptr_rtx;
@@ -8757,7 +8793,7 @@ rs6000_emit_prologue ()
gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM));
/* If we need to save CR, put it into r12. */
- if (info->cr_save_p && frame_reg_rtx != frame_ptr_rtx)
+ if (info->cr_save_p)
{
cr_save_rtx = gen_rtx_REG (SImode, 12);
emit_insn (gen_movesi_from_cr (cr_save_rtx));
@@ -8792,15 +8828,16 @@ rs6000_emit_prologue ()
char rname[30];
const char *alloc_rname;
rtvec p;
- p = rtvec_alloc (2 + 64 - info->first_fp_reg_save);
+ p = rtvec_alloc (3 + 64 - info->first_fp_reg_save);
RTVEC_ELT (p, 0) = gen_rtx_CLOBBER (VOIDmode,
gen_rtx_REG (Pmode,
LINK_REGISTER_REGNUM));
+ RTVEC_ELT (p, 1) = gen_rtx_USE (VOIDmode, frame_reg_rtx);
sprintf (rname, "%s%d%s", SAVE_FP_PREFIX,
info->first_fp_reg_save - 32, SAVE_FP_SUFFIX);
alloc_rname = ggc_strdup (rname);
- RTVEC_ELT (p, 1) = gen_rtx_USE (VOIDmode,
+ RTVEC_ELT (p, 2) = gen_rtx_USE (VOIDmode,
gen_rtx_SYMBOL_REF (Pmode,
alloc_rname));
for (i = 0; i < 64 - info->first_fp_reg_save; i++)
@@ -8809,11 +8846,12 @@ rs6000_emit_prologue ()
reg = gen_rtx_REG (DFmode, info->first_fp_reg_save + i);
addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
GEN_INT (info->fp_save_offset
- + sp_offset + 8*i));
+ + sp_offset
+ + 8 * i));
mem = gen_rtx_MEM (DFmode, addr);
set_mem_alias_set (mem, rs6000_sr_alias_set);
- RTVEC_ELT (p, i + 2) = gen_rtx_SET (VOIDmode, mem, reg);
+ RTVEC_ELT (p, i + 3) = gen_rtx_SET (VOIDmode, mem, reg);
}
insn = emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
@@ -8921,13 +8959,6 @@ rs6000_emit_prologue ()
set_mem_alias_set (mem, rs6000_sr_alias_set);
- /* If r12 was used to hold the original sp, copy cr into r0 now
- that it's free. */
- if (REGNO (frame_reg_rtx) == 12)
- {
- cr_save_rtx = gen_rtx_REG (SImode, 0);
- emit_insn (gen_movesi_from_cr (cr_save_rtx));
- }
insn = emit_move_insn (mem, cr_save_rtx);
/* Now, there's no way that dwarf2out_frame_debug_expr is going
@@ -9093,6 +9124,17 @@ rs6000_emit_epilogue (sibcall)
gen_rtx_MEM (Pmode, sp_reg_rtx));
}
+ else if (!restoring_FPRs_inline
+ && info->first_fp_reg_save != 64
+ && DEFAULT_ABI == ABI_V4)
+ {
+ frame_reg_rtx = gen_rtx_REG (Pmode, 11);
+ emit_insn (TARGET_32BIT
+ ? gen_addsi3 (frame_reg_rtx, sp_reg_rtx,
+ GEN_INT (info->total_size))
+ : gen_adddi3 (frame_reg_rtx, sp_reg_rtx,
+ GEN_INT (info->total_size)));
+ }
else if (info->push_p)
{
if (DEFAULT_ABI == ABI_V4)
@@ -9172,7 +9214,9 @@ rs6000_emit_epilogue (sibcall)
}
/* Set LR here to try to overlap restores below. */
- if (info->lr_save_p)
+ if (info->lr_save_p
+ && (restoring_FPRs_inline
+ || ! (info->first_fp_reg_save != 64 && DEFAULT_ABI == ABI_V4)))
emit_move_insn (gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM),
gen_rtx_REG (Pmode, 0));
@@ -9245,22 +9289,64 @@ rs6000_emit_epilogue (sibcall)
/* Restore fpr's if we need to do it without calling a function. */
if (restoring_FPRs_inline)
- for (i = 0; i < 64 - info->first_fp_reg_save; i++)
- if ((regs_ever_live[info->first_fp_reg_save+i]
- && ! call_used_regs[info->first_fp_reg_save+i]))
+ {
+ for (i = 0; i < 64 - info->first_fp_reg_save; i++)
+ if ((regs_ever_live[info->first_fp_reg_save+i]
+ && ! call_used_regs[info->first_fp_reg_save+i]))
+ {
+ rtx addr, mem;
+ addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
+ GEN_INT (info->fp_save_offset
+ + sp_offset
+ + 8 * i));
+ mem = gen_rtx_MEM (DFmode, addr);
+ set_mem_alias_set (mem, rs6000_sr_alias_set);
+
+ emit_move_insn (gen_rtx_REG (DFmode,
+ info->first_fp_reg_save + i),
+ mem);
+ }
+ }
+ /* If we have to restore more than two FP registers, and we're using
+ the sysv4 abi, call the restore function. */
+ else if (info->first_fp_reg_save != 64 && DEFAULT_ABI == ABI_V4)
+ {
+ int i;
+ char rname[30];
+ const char *alloc_rname;
+ rtvec p;
+
+ p = rtvec_alloc (3 + 64 - info->first_fp_reg_save);
+ RTVEC_ELT (p, 0) = gen_rtx_CLOBBER (VOIDmode,
+ gen_rtx_REG (Pmode,
+ LINK_REGISTER_REGNUM));
+ RTVEC_ELT (p, 1) = gen_rtx_USE (VOIDmode, frame_reg_rtx);
+ sprintf (rname, "%s%d%s", RESTORE_FP_PREFIX,
+ info->first_fp_reg_save - 32, RESTORE_FP_SUFFIX);
+ alloc_rname = ggc_strdup (rname);
+ RTVEC_ELT (p, 2) = gen_rtx_USE (VOIDmode,
+ gen_rtx_SYMBOL_REF (Pmode,
+ alloc_rname));
+
+ for (i = 0; i < 64 - info->first_fp_reg_save; i++)
{
- rtx addr, mem;
+ rtx addr, reg, mem;
+ reg = gen_rtx_REG (DFmode, info->first_fp_reg_save + i);
addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
GEN_INT (info->fp_save_offset
- + sp_offset
+ + sp_offset
+ 8 * i));
mem = gen_rtx_MEM (DFmode, addr);
set_mem_alias_set (mem, rs6000_sr_alias_set);
- emit_move_insn (gen_rtx_REG (DFmode,
- info->first_fp_reg_save + i),
- mem);
+ RTVEC_ELT (p, i + 3) = gen_rtx_SET (VOIDmode, reg, mem);
}
+ emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
+
+ if (info->lr_save_p)
+ emit_move_insn (gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM),
+ gen_rtx_REG (Pmode, 0));
+ }
/* If we saved cr, restore it here. Just those that were used. */
if (info->cr_save_p)
@@ -9346,7 +9432,7 @@ rs6000_emit_epilogue (sibcall)
if (!sibcall)
{
rtvec p;
- if (! restoring_FPRs_inline)
+ if (! (restoring_FPRs_inline || DEFAULT_ABI == ABI_V4))
p = rtvec_alloc (3 + 64 - info->first_fp_reg_save);
else
p = rtvec_alloc (2);
@@ -9358,7 +9444,7 @@ rs6000_emit_epilogue (sibcall)
/* If we have to restore more than two FP registers, branch to the
restore function. It will return to our caller. */
- if (! restoring_FPRs_inline)
+ if (! (restoring_FPRs_inline || DEFAULT_ABI == ABI_V4))
{
int i;
char rname[30];
@@ -9373,16 +9459,14 @@ rs6000_emit_epilogue (sibcall)
for (i = 0; i < 64 - info->first_fp_reg_save; i++)
{
- rtx addr, mem;
+ rtx addr, mem, reg;
+ reg = gen_rtx_REG (DFmode, info->first_fp_reg_save + i);
addr = gen_rtx_PLUS (Pmode, sp_reg_rtx,
- GEN_INT (info->fp_save_offset + 8*i));
+ GEN_INT (info->fp_save_offset + 8 * i));
mem = gen_rtx_MEM (DFmode, addr);
set_mem_alias_set (mem, rs6000_sr_alias_set);
- RTVEC_ELT (p, i+3) =
- gen_rtx_SET (VOIDmode,
- gen_rtx_REG (DFmode, info->first_fp_reg_save + i),
- mem);
+ RTVEC_ELT (p, i+3) = gen_rtx_SET (VOIDmode, reg, mem);
}
}
Index: gcc/config/rs6000/rs6000.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.md,v
retrieving revision 1.168
diff -u -p -r1.168 rs6000.md
--- rs6000.md 2002/02/19 02:53:37 1.168
+++ rs6000.md 2002/02/20 01:35:54
@@ -13669,20 +13741,42 @@
(define_insn "*save_fpregs_si"
[(match_parallel 0 "any_operand"
[(clobber (match_operand:SI 1 "register_operand" "=l"))
- (use (match_operand:SI 2 "call_operand" "s"))
- (set (match_operand:DF 3 "memory_operand" "=m")
- (match_operand:DF 4 "gpc_reg_operand" "f"))])]
+ (use (match_operand:SI 2 "gpc_reg_operand" "r"))
+ (use (match_operand:SI 3 "call_operand" "s"))
+ (set (match_operand:DF 4 "memory_operand" "=m")
+ (match_operand:DF 5 "gpc_reg_operand" "f"))])]
"TARGET_32BIT"
- "bl %z2")
+ "bl %z3")
(define_insn "*save_fpregs_di"
[(match_parallel 0 "any_operand"
+ [(clobber (match_operand:DI 1 "register_operand" "=l"))
+ (use (match_operand:DI 2 "gpc_reg_operand" "r"))
+ (use (match_operand:DI 3 "call_operand" "s"))
+ (set (match_operand:DF 4 "memory_operand" "=m")
+ (match_operand:DF 5 "gpc_reg_operand" "f"))])]
+ "TARGET_64BIT"
+ "bl %z3")
+
+(define_insn "*rest_fpregs_si"
+ [(match_parallel 0 "any_operand"
+ [(clobber (match_operand:SI 1 "register_operand" "=l"))
+ (use (match_operand:SI 2 "gpc_reg_operand" "r"))
+ (use (match_operand:SI 3 "call_operand" "s"))
+ (set (match_operand:DF 4 "gpc_reg_operand" "=f")
+ (match_operand:DF 5 "memory_operand" "m"))])]
+ "TARGET_32BIT"
+ "bl %z3")
+
+(define_insn "*rest_fpregs_di"
+ [(match_parallel 0 "any_operand"
[(clobber (match_operand:DI 1 "register_operand" "=l"))
- (use (match_operand:DI 2 "call_operand" "s"))
- (set (match_operand:DF 3 "memory_operand" "=m")
- (match_operand:DF 4 "gpc_reg_operand" "f"))])]
+ (use (match_operand:DI 2 "gpc_reg_operand" "r"))
+ (use (match_operand:DI 3 "call_operand" "s"))
+ (set (match_operand:DF 4 "gpc_reg_operand" "=f")
+ (match_operand:DF 5 "memory_operand" "m"))])]
"TARGET_64BIT"
- "bl %z2")
+ "bl %z3")
; These are to explain that changes to the stack pointer should
; not be moved over stores to stack memory.
--
Alan Modra
IBM OzLabs - Linux Technology Centre