gcc: Altivec register adjustments from Apple.

Obtained from:	gcc pre-4.3 (rev. 124763; GPLv2)
MFC after:	3 weeks
This commit is contained in:
Pedro F. Giffuni 2013-11-26 14:52:29 +00:00
parent 55050ab560
commit 7b0d23ce5a
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=258651
2 changed files with 116 additions and 99 deletions

View File

@ -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

View File

@ -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)
{