gcc: Altivec register adjustments from Apple.
Obtained from: gcc pre-4.3 (rev. 124763; GPLv2) MFC after: 3 weeks
This commit is contained in:
parent
7d07dd1cba
commit
99b77b1bb3
@ -31,6 +31,12 @@
|
||||
regs_invalidated_by_call, rather than just checking the
|
||||
membership of REGNO (REG).
|
||||
|
||||
2007-05-16 Eric Christopher <echristo@apple.com> (r124763)
|
||||
|
||||
* config/rs6000/rs6000.c (rs6000_emit_prologue): Move altivec register
|
||||
saving after stack push. Set sp_offset whenever we push.
|
||||
(rs6000_emit_epilogue): Move altivec register restore before stack push.
|
||||
|
||||
2007-05-03 Ian Lance Taylor <iant@google.com> (r124381)
|
||||
|
||||
* config/rs6000/rs6000.c (rs6000_override_options): Don't set
|
||||
|
@ -14466,77 +14466,6 @@ rs6000_emit_prologue (void)
|
||||
sp_offset = info->total_size;
|
||||
}
|
||||
|
||||
/* Save AltiVec registers if needed. */
|
||||
if (!WORLD_SAVE_P (info) && TARGET_ALTIVEC_ABI && info->altivec_size != 0)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* There should be a non inline version of this, for when we
|
||||
are saving lots of vector registers. */
|
||||
for (i = info->first_altivec_reg_save; i <= LAST_ALTIVEC_REGNO; ++i)
|
||||
if (info->vrsave_mask & ALTIVEC_REG_BIT (i))
|
||||
{
|
||||
rtx areg, savereg, mem;
|
||||
int offset;
|
||||
|
||||
offset = info->altivec_save_offset + sp_offset
|
||||
+ 16 * (i - info->first_altivec_reg_save);
|
||||
|
||||
savereg = gen_rtx_REG (V4SImode, i);
|
||||
|
||||
areg = gen_rtx_REG (Pmode, 0);
|
||||
emit_move_insn (areg, GEN_INT (offset));
|
||||
|
||||
/* AltiVec addressing mode is [reg+reg]. */
|
||||
mem = gen_frame_mem (V4SImode,
|
||||
gen_rtx_PLUS (Pmode, frame_reg_rtx, areg));
|
||||
|
||||
insn = emit_move_insn (mem, savereg);
|
||||
|
||||
rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
|
||||
areg, GEN_INT (offset));
|
||||
}
|
||||
}
|
||||
|
||||
/* VRSAVE is a bit vector representing which AltiVec registers
|
||||
are used. The OS uses this to determine which vector
|
||||
registers to save on a context switch. We need to save
|
||||
VRSAVE on the stack frame, add whatever AltiVec registers we
|
||||
used in this function, and do the corresponding magic in the
|
||||
epilogue. */
|
||||
|
||||
if (TARGET_ALTIVEC && TARGET_ALTIVEC_VRSAVE
|
||||
&& info->vrsave_mask != 0)
|
||||
{
|
||||
rtx reg, mem, vrsave;
|
||||
int offset;
|
||||
|
||||
/* Get VRSAVE onto a GPR. Note that ABI_V4 might be using r12
|
||||
as frame_reg_rtx and r11 as the static chain pointer for
|
||||
nested functions. */
|
||||
reg = gen_rtx_REG (SImode, 0);
|
||||
vrsave = gen_rtx_REG (SImode, VRSAVE_REGNO);
|
||||
if (TARGET_MACHO)
|
||||
emit_insn (gen_get_vrsave_internal (reg));
|
||||
else
|
||||
emit_insn (gen_rtx_SET (VOIDmode, reg, vrsave));
|
||||
|
||||
if (!WORLD_SAVE_P (info))
|
||||
{
|
||||
/* Save VRSAVE. */
|
||||
offset = info->vrsave_save_offset + sp_offset;
|
||||
mem = gen_frame_mem (SImode,
|
||||
gen_rtx_PLUS (Pmode, frame_reg_rtx,
|
||||
GEN_INT (offset)));
|
||||
insn = emit_move_insn (mem, reg);
|
||||
}
|
||||
|
||||
/* Include the registers in the mask. */
|
||||
emit_insn (gen_iorsi3 (reg, reg, GEN_INT ((int) info->vrsave_mask)));
|
||||
|
||||
insn = emit_insn (generate_set_vrsave (reg, info, 0));
|
||||
}
|
||||
|
||||
/* If we use the link register, get it into r0. */
|
||||
if (!WORLD_SAVE_P (info) && info->lr_save_p)
|
||||
{
|
||||
@ -14774,7 +14703,10 @@ rs6000_emit_prologue (void)
|
||||
for which it was done previously. */
|
||||
if (!WORLD_SAVE_P (info) && info->push_p
|
||||
&& !(DEFAULT_ABI == ABI_V4 || current_function_calls_eh_return))
|
||||
rs6000_emit_allocate_stack (info->total_size, FALSE);
|
||||
{
|
||||
rs6000_emit_allocate_stack (info->total_size, FALSE);
|
||||
sp_offset = info->total_size;
|
||||
}
|
||||
|
||||
/* Set frame pointer, if needed. */
|
||||
if (frame_pointer_needed)
|
||||
@ -14784,6 +14716,78 @@ rs6000_emit_prologue (void)
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
|
||||
/* Save AltiVec registers if needed. Save here because the red zone does
|
||||
not include AltiVec registers. */
|
||||
if (!WORLD_SAVE_P (info) && TARGET_ALTIVEC_ABI && info->altivec_size != 0)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* There should be a non inline version of this, for when we
|
||||
are saving lots of vector registers. */
|
||||
for (i = info->first_altivec_reg_save; i <= LAST_ALTIVEC_REGNO; ++i)
|
||||
if (info->vrsave_mask & ALTIVEC_REG_BIT (i))
|
||||
{
|
||||
rtx areg, savereg, mem;
|
||||
int offset;
|
||||
|
||||
offset = info->altivec_save_offset + sp_offset
|
||||
+ 16 * (i - info->first_altivec_reg_save);
|
||||
|
||||
savereg = gen_rtx_REG (V4SImode, i);
|
||||
|
||||
areg = gen_rtx_REG (Pmode, 0);
|
||||
emit_move_insn (areg, GEN_INT (offset));
|
||||
|
||||
/* AltiVec addressing mode is [reg+reg]. */
|
||||
mem = gen_frame_mem (V4SImode,
|
||||
gen_rtx_PLUS (Pmode, frame_reg_rtx, areg));
|
||||
|
||||
insn = emit_move_insn (mem, savereg);
|
||||
|
||||
rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
|
||||
areg, GEN_INT (offset));
|
||||
}
|
||||
}
|
||||
|
||||
/* VRSAVE is a bit vector representing which AltiVec registers
|
||||
are used. The OS uses this to determine which vector
|
||||
registers to save on a context switch. We need to save
|
||||
VRSAVE on the stack frame, add whatever AltiVec registers we
|
||||
used in this function, and do the corresponding magic in the
|
||||
epilogue. */
|
||||
|
||||
if (TARGET_ALTIVEC && TARGET_ALTIVEC_VRSAVE
|
||||
&& info->vrsave_mask != 0)
|
||||
{
|
||||
rtx reg, mem, vrsave;
|
||||
int offset;
|
||||
|
||||
/* Get VRSAVE onto a GPR. Note that ABI_V4 might be using r12
|
||||
as frame_reg_rtx and r11 as the static chain pointer for
|
||||
nested functions. */
|
||||
reg = gen_rtx_REG (SImode, 0);
|
||||
vrsave = gen_rtx_REG (SImode, VRSAVE_REGNO);
|
||||
if (TARGET_MACHO)
|
||||
emit_insn (gen_get_vrsave_internal (reg));
|
||||
else
|
||||
emit_insn (gen_rtx_SET (VOIDmode, reg, vrsave));
|
||||
|
||||
if (!WORLD_SAVE_P (info))
|
||||
{
|
||||
/* Save VRSAVE. */
|
||||
offset = info->vrsave_save_offset + sp_offset;
|
||||
mem = gen_frame_mem (SImode,
|
||||
gen_rtx_PLUS (Pmode, frame_reg_rtx,
|
||||
GEN_INT (offset)));
|
||||
insn = emit_move_insn (mem, reg);
|
||||
}
|
||||
|
||||
/* Include the registers in the mask. */
|
||||
emit_insn (gen_iorsi3 (reg, reg, GEN_INT ((int) info->vrsave_mask)));
|
||||
|
||||
insn = emit_insn (generate_set_vrsave (reg, info, 0));
|
||||
}
|
||||
|
||||
/* If we are using RS6000_PIC_OFFSET_TABLE_REGNUM, we need to set it up. */
|
||||
if ((TARGET_TOC && TARGET_MINIMAL_TOC && get_pool_size () != 0)
|
||||
|| (DEFAULT_ABI == ABI_V4
|
||||
@ -15041,33 +15045,10 @@ rs6000_emit_epilogue (int sibcall)
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we have a frame pointer, a call to alloca, or a large stack
|
||||
frame, restore the old stack pointer using the backchain. Otherwise,
|
||||
we know what size to update it with. */
|
||||
if (use_backchain_to_restore_sp)
|
||||
{
|
||||
/* Under V.4, don't reset the stack pointer until after we're done
|
||||
loading the saved registers. */
|
||||
if (DEFAULT_ABI == ABI_V4)
|
||||
frame_reg_rtx = gen_rtx_REG (Pmode, 11);
|
||||
|
||||
emit_move_insn (frame_reg_rtx,
|
||||
gen_rtx_MEM (Pmode, sp_reg_rtx));
|
||||
}
|
||||
else if (info->push_p)
|
||||
{
|
||||
if (DEFAULT_ABI == ABI_V4
|
||||
|| current_function_calls_eh_return)
|
||||
sp_offset = info->total_size;
|
||||
else
|
||||
{
|
||||
emit_insn (TARGET_32BIT
|
||||
? gen_addsi3 (sp_reg_rtx, sp_reg_rtx,
|
||||
GEN_INT (info->total_size))
|
||||
: gen_adddi3 (sp_reg_rtx, sp_reg_rtx,
|
||||
GEN_INT (info->total_size)));
|
||||
}
|
||||
}
|
||||
/* Set sp_offset based on the stack push from the prologue. */
|
||||
if ((DEFAULT_ABI == ABI_V4 || current_function_calls_eh_return)
|
||||
&& info->total_size < 32767)
|
||||
sp_offset = info->total_size;
|
||||
|
||||
/* Restore AltiVec registers if needed. */
|
||||
if (TARGET_ALTIVEC_ABI && info->altivec_size != 0)
|
||||
@ -15108,6 +15089,36 @@ rs6000_emit_epilogue (int sibcall)
|
||||
emit_insn (generate_set_vrsave (reg, info, 1));
|
||||
}
|
||||
|
||||
sp_offset = 0;
|
||||
|
||||
/* If we have a frame pointer, a call to alloca, or a large stack
|
||||
frame, restore the old stack pointer using the backchain. Otherwise,
|
||||
we know what size to update it with. */
|
||||
if (use_backchain_to_restore_sp)
|
||||
{
|
||||
/* Under V.4, don't reset the stack pointer until after we're done
|
||||
loading the saved registers. */
|
||||
if (DEFAULT_ABI == ABI_V4)
|
||||
frame_reg_rtx = gen_rtx_REG (Pmode, 11);
|
||||
|
||||
emit_move_insn (frame_reg_rtx,
|
||||
gen_rtx_MEM (Pmode, sp_reg_rtx));
|
||||
}
|
||||
else if (info->push_p)
|
||||
{
|
||||
if (DEFAULT_ABI == ABI_V4
|
||||
|| current_function_calls_eh_return)
|
||||
sp_offset = info->total_size;
|
||||
else
|
||||
{
|
||||
emit_insn (TARGET_32BIT
|
||||
? gen_addsi3 (sp_reg_rtx, sp_reg_rtx,
|
||||
GEN_INT (info->total_size))
|
||||
: gen_adddi3 (sp_reg_rtx, sp_reg_rtx,
|
||||
GEN_INT (info->total_size)));
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the old lr if we saved it. */
|
||||
if (info->lr_save_p)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user