While trying to track down the vector unwind problems on ppc-darwin, I
made some tidy-ups for "save_world()".
In the end, that was not where the main problem, lay - but I did find
a few things wrong there on the way - they should be fixed, even if
there's no specific bug filed at present.
I'm also attaching a second patch which is purely cosmetic white-space/
comment tidies I'd also like to apply.
checked on powerpc-darwin{8-G4,9-G5} and crosses to powerpc-eabisim
and powerpc-ibm-aix6.1.3.0
===
In due course, we should be able to split the save_world_p logic out
of rs6000_emit_{pro,epi}logue.
The attached patch moves also one step nearer that - by doing the
VRSave changes within the save_world() routine when that is in use -
- actually, this is necessary really - if one remembers that vec code
that should only be present in the prologue when the target cpu is a
G4 or better.
OK for trunk?
Iain
gcc:
* config/rs6000/rs6000.c (first_altivec_reg_to_save): Amend comment.
(compute_vrsave_mask): Likewise.
(rs6000_emit_prologue): Move update of VRSave mask to save_world()
when that is in use.
libgcc:
* config/rs6000/darwin-world.S (toplevel): Make it clear that this
function is
not used for PPC64. (save_world): Amend comments. Update the VRsave
mask to reflect the saved regs.
(rest_world): Update comments, do not clobber r10, do not use r8.
(eh_rest_world_r10): Amend comments, do not use r8.
(rest_world_eh_r7r8): Make local, move restore of CR and target address
to end of routine, do not use r8.
===
part 2.
libgcc:
* config/rs6000/darwin-world.S: Amend whitespace and comments.
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c (revision 181818)
+++ gcc/config/rs6000/rs6000.c (working copy)
@@ -17284,9 +17284,10 @@ first_altivec_reg_to_save (void)
if (! TARGET_ALTIVEC_ABI)
return LAST_ALTIVEC_REGNO + 1;
- /* On Darwin, the unwind routines are compiled without
- TARGET_ALTIVEC, and use save_world to save/restore the
- altivec registers when necessary. */
+ /* When generating code for earlier versions of Darwin, which might run on
+ hardware with or without Altivec, we use out-of-line save/restores in
+ function prologues/epilogues that require it. These routines determine
+ whether to save/restore Altivec at runtime. */
if (DEFAULT_ABI == ABI_DARWIN && crtl->calls_eh_return
&& ! TARGET_ALTIVEC)
return FIRST_ALTIVEC_REGNO + 20;
@@ -17308,9 +17309,10 @@ compute_vrsave_mask (void)
{
unsigned int i, mask = 0;
- /* On Darwin, the unwind routines are compiled without
- TARGET_ALTIVEC, and use save_world to save/restore the
- call-saved altivec registers when necessary. */
+/* When generating code for earlier versions of Darwin, which might run on
+ hardware with or without Altivec, we use out-of-line save/restores in
+ function prologues/epilogues that require it. These routines determine
+ whether to save/restore Altivec at runtime. */
if (DEFAULT_ABI == ABI_DARWIN && crtl->calls_eh_return
&& ! TARGET_ALTIVEC)
mask |= 0xFFF;
@@ -19902,7 +19909,9 @@ rs6000_emit_prologue (void)
used in this function, and do the corresponding magic in the
epilogue. */
- if (TARGET_ALTIVEC && TARGET_ALTIVEC_VRSAVE
+ if (!WORLD_SAVE_P (info)
+ && TARGET_ALTIVEC
+ && TARGET_ALTIVEC_VRSAVE
&& info->vrsave_mask != 0)
{
rtx reg, mem, vrsave;
@@ -19918,15 +19927,12 @@ rs6000_emit_prologue (void)
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);
- }
+ /* 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)));
Index: libgcc/config/rs6000/darwin-world.S
===================================================================
--- libgcc/config/rs6000/darwin-world.S (revision 181818)
+++ libgcc/config/rs6000/darwin-world.S (working copy)
@@ -24,6 +24,8 @@
* <http://www.gnu.org/licenses/>.
*/
+#ifndef __ppc64__
+
.machine ppc7400
.data
.align 2
@@ -33,12 +35,7 @@
.non_lazy_symbol_pointer
L_has_vec$non_lazy_ptr:
.indirect_symbol __cpu_has_altivec
-#ifdef __ppc64__
- .quad 0
-#else
.long 0
-#endif
-
#else
/* For static, "pretend" we have a non-lazy-pointer. */
@@ -57,12 +54,11 @@ L_has_vec$non_lazy_ptr:
provided by the System Framework to determine this.)
SAVE_WORLD takes R0 (the caller`s caller`s return address) and R11
- (the stack frame size) as parameters. It returns VRsave in R0 if
- we`re on a CPU with vector regs.
+ (the stack frame size) as parameters. It returns the updated VRsave
+ in R0 if we`re on a CPU with vector regs.
- With gcc3, we now need to save and restore CR as well, since gcc3's
- scheduled prologs can cause comparisons to be moved before calls to
- save_world!
+ For gcc3 onward, we need to save and restore CR as well, since scheduled
+ prologs can cause comparisons to be moved before calls to save_world.
USES: R0 R11 R12 */
@@ -143,69 +139,62 @@ L$saveVMX:
stvx v30,r11,r12
mfspr r0,VRsave
li r11,-16
- stvx v31,r11,r12
- /* VRsave lives at -224(R1) */
- stw r0,0(r12)
+ stvx v31,r11,r12
+ stw r0,0(r12) /* VRsave lives at -224(R1). */
+ ori r0,r0,0xfff /* We just saved these. */
+ mtspr VRsave,r0
blr
+/* rest_world is jumped to, not called, so no need to worry about LR.
+ clobbers R0, R7, R11 and R12. This just undoes the work done above. */
+ .private_extern rest_world
+rest_world:
+
+ lwz r11, 0(r1) /* Pickup previous SP */
+ li r7, 0 /* Stack offset is zero, r10 is ignored. */
+ b Lrest_world_eh_r7r8
+
/* eh_rest_world_r10 is jumped to, not called, so no need to worry about LR.
R10 is the C++ EH stack adjust parameter, we return to the caller`s caller.
- USES: R0 R10 R11 R12 and R7 R8
- RETURNS: C++ EH Data registers (R3 - R6.)
+ clobbers: R0, R7, R11 and R12
+ uses : R10
+ RETURNS : C++ EH Data registers (R3 - R6). */
- We now set up R7/R8 and jump to rest_world_eh_r7r8.
-
- rest_world doesn't use the R10 stack adjust parameter, nor does it
- pick up the R3-R6 exception handling stuff. */
-
-.private_extern rest_world
-rest_world:
- /* Pickup previous SP */
- lwz r11, 0(r1)
- li r7, 0
- lwz r8, 8(r11)
- li r10, 0
- b rest_world_eh_r7r8
-
-.private_extern eh_rest_world_r10
+ .private_extern eh_rest_world_r10
eh_rest_world_r10:
- /* Pickup previous SP */
- lwz r11, 0(r1)
- mr r7,r10
- lwz r8, 8(r11)
- /* pickup the C++ EH data regs (R3 - R6.) */
+
+ lwz r11, 0(r1) /* Pickup previous SP */
+ mr r7,r10 /* Stack offset. */
+
+ /* pickup the C++ EH data regs (R3 - R6.) */
lwz r6,-420(r11)
lwz r5,-424(r11)
lwz r4,-428(r11)
lwz r3,-432(r11)
- b rest_world_eh_r7r8
+ /* Fall through to Lrest_world_eh_r7r8. */
-/* rest_world_eh_r7r8 is jumped to -- not called! -- when we're doing
- the exception-handling epilog. R7 contains the offset to add to
- the SP, and R8 contains the 'real' return address.
+/* When we are doing the exception-handling epilog, R7 contains the offset to
+ add to the SP.
- USES: R0 R11 R12 [R7/R8]
- RETURNS: C++ EH Data registers (R3 - R6.) */
+ clobbers: R0, R11 and R12
+ uses : R7. */
-rest_world_eh_r7r8:
+Lrest_world_eh_r7r8:
+ /* See if we have Altivec. */
bcl 20,31,Lr7r8$pb
Lr7r8$pb: mflr r12
- lwz r11,0(r1)
- /* R11 := previous SP */
+
addis r12,r12,ha16(L_has_vec$non_lazy_ptr-Lr7r8$pb)
lwz r12,lo16(L_has_vec$non_lazy_ptr-Lr7r8$pb)(r12)
- lwz r0,4(r11)
- /* R0 := old CR */
- lwz r12,0(r12)
- /* R12 := HAS_VEC */
- mtcr r0
+ lwz r12,0(r12) /* R12 := HAS_VEC */
cmpwi r12,0
lmw r13,-220(r11)
beq L.rest_world_fp_eh
- /* restore VRsave and V20..V31 */
+
+ /* We have Altivec, restore VRsave and V20..V31 */
lwz r0,-224(r11)
li r12,-416
mtspr VRsave,r0
@@ -234,6 +223,7 @@ Lr7r8$pb: mflr r12
lvx v31,r11,r12
L.rest_world_fp_eh:
+ lwz r0,4(r11) /* recover saved CR */
lfd f14,-144(r11)
lfd f15,-136(r11)
lfd f16,-128(r11)
@@ -251,9 +241,23 @@ L.rest_world_fp_eh:
lfd f28,-32(r11)
lfd f29,-24(r11)
lfd f30,-16(r11)
- /* R8 is the exception-handler's address */
- mtctr r8
- lfd f31,-8(r11)
- /* set SP to original value + R7 offset */
- add r1,r11,r7
+ mtcr r0 /* restore the saved cr. */
+ lwz r0, 8(r11) /* Pick up the 'real' return address. */
+ lfd f31,-8(r11)
+ mtctr r0 /* exception-handler ret. address */
+ add r1,r11,r7 /* set SP to original value + R7 offset */
bctr
+
+#else /* ... ppc64 we should never be called for this ... */
+ .machine ppc64
+
+ .private_extern save_world
+save_world:
+ trap
+
+ .private_extern eh_rest_world_r10
+eh_rest_world_r10:
+ trap
+
+#endif
+ /* Done. */
--- libgcc/config/rs6000/darwin-world.S-1 2011-11-30 14:04:49.000000000
+0000
+++ libgcc/config/rs6000/darwin-world.S-ids 2011-11-26 17:19:25.000000000
+0000
@@ -32,7 +32,7 @@
#ifdef __DYNAMIC__
-.non_lazy_symbol_pointer
+ .non_lazy_symbol_pointer
L_has_vec$non_lazy_ptr:
.indirect_symbol __cpu_has_altivec
.long 0
@@ -45,8 +45,7 @@ L_has_vec$non_lazy_ptr:
#endif
-
-.text
+ .text
.align 2
/* save_world and rest_world save/restore F14-F31 and possibly V20-V31
@@ -62,7 +61,7 @@ L_has_vec$non_lazy_ptr:
USES: R0 R11 R12 */
-.private_extern save_world
+ .private_extern save_world
save_world:
stw r0,8(r1)
mflr r0
@@ -72,10 +71,10 @@ Ls$pb: mflr r12
lwz r12,lo16(L_has_vec$non_lazy_ptr-Ls$pb)(r12)
mtlr r0
lwz r12,0(r12)
- /* grab CR */
- mfcr r0
- /* test HAS_VEC */
- cmpwi r12,0
+
+ mfcr r0 /* grab incoming CR */
+ cmpwi r12,0 /* test HAS_VEC */
+ /* Save the FPRs... */
stfd f14,-144(r1)
stfd f15,-136(r1)
stfd f16,-128(r1)
@@ -94,25 +93,22 @@ Ls$pb: mflr r12
stfd f29,-24(r1)
stfd f30,-16(r1)
stfd f31,-8(r1)
+ /* ... and the GPRs ... */
stmw r13,-220(r1)
- /* stash CR */
+ /* ... the CR */
stw r0,4(r1)
- /* set R12 pointing at Vector Reg save area */
- addi r12,r1,-224
- /* allocate stack frame */
- stwux r1,r1,r11
- /* ...but return if HAS_VEC is zero */
- bne+ L$saveVMX
- /* Not forgetting to restore CR. */
- mtcr r0
+ addi r12,r1,-224 /* set R12 pointing at Vector Reg save area */
+ stwux r1,r1,r11 /* allocate stack frame */
+ bne+ L$saveVMX /* ...but return if HAS_VEC is zero */
+ mtcr r0 /* Not forgetting to restore CR. */
blr
L$saveVMX:
- /* We're saving Vector regs too. */
- /* Restore CR from R0. No More Branches! */
- mtcr r0
+ /* We are saving Vector regs too. */
+
+ mtcr r0 /* Restore CR from R0. No More Branches! */
- /* We should really use VRSAVE to figure out which vector regs
+ /* ??? We should really use VRSAVE to figure out which vector regs
we actually need to save and restore. Some other time :-/ */
li r11,-192