Add an alternative implementation of VG_MINIMAL_{SET,LONG}JMP
for ppc32-linux, that works for gcc >= 4.4. Related to #259977.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@11688 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/m_debuginfo/readdwarf3.c b/coregrind/m_debuginfo/readdwarf3.c
index 918c425..3fe43db 100644
--- a/coregrind/m_debuginfo/readdwarf3.c
+++ b/coregrind/m_debuginfo/readdwarf3.c
@@ -3955,7 +3955,7 @@
static Bool d3rd_jmpbuf_valid = False;
static HChar* d3rd_jmpbuf_reason = NULL;
-static VG_MINIMAL_JMP_BUF d3rd_jmpbuf;
+static VG_MINIMAL_JMP_BUF(d3rd_jmpbuf);
static __attribute__((noreturn)) void barf ( HChar* reason ) {
vg_assert(d3rd_jmpbuf_valid);
diff --git a/coregrind/m_libcsetjmp.c b/coregrind/m_libcsetjmp.c
index 8d1c2c2..ae0b620 100644
--- a/coregrind/m_libcsetjmp.c
+++ b/coregrind/m_libcsetjmp.c
@@ -36,7 +36,112 @@
/* See include/pub_tool_libcsetjmp.h for background and rationale. */
-/* No alternative implementations at present. */
+/* The only alternative implementations are for ppc{32,64}-linux. See
+ #259977. */
+
+#if defined(VGP_ppc32_linux)
+
+__asm__(
+".text" "\n"
+"" "\n"
+".global VG_MINIMAL_SETJMP" "\n" // r3 = jmp_buf
+"VG_MINIMAL_SETJMP:" "\n"
+" stw 0, 0(3)" "\n"
+" stw 1, 4(3)" "\n"
+" stw 2, 8(3)" "\n"
+" stw 3, 12(3)" "\n"
+" stw 4, 16(3)" "\n"
+" stw 5, 20(3)" "\n"
+" stw 6, 24(3)" "\n"
+" stw 7, 28(3)" "\n"
+" stw 8, 32(3)" "\n"
+" stw 9, 36(3)" "\n"
+" stw 10, 40(3)" "\n"
+" stw 11, 44(3)" "\n"
+" stw 12, 48(3)" "\n"
+" stw 13, 52(3)" "\n"
+" stw 14, 56(3)" "\n"
+" stw 15, 60(3)" "\n"
+" stw 16, 64(3)" "\n"
+" stw 17, 68(3)" "\n"
+" stw 18, 72(3)" "\n"
+" stw 19, 76(3)" "\n"
+" stw 20, 80(3)" "\n"
+" stw 21, 84(3)" "\n"
+" stw 22, 88(3)" "\n"
+" stw 23, 92(3)" "\n"
+" stw 24, 96(3)" "\n"
+" stw 25, 100(3)" "\n"
+" stw 26, 104(3)" "\n"
+" stw 27, 108(3)" "\n"
+" stw 28, 112(3)" "\n"
+" stw 29, 116(3)" "\n"
+" stw 30, 120(3)" "\n"
+" stw 31, 124(3)" "\n"
+ // must use a caller-save register here as scratch, hence r4
+" mflr 4" "\n"
+" stw 4, 128(3)" "\n"
+" mfcr 4" "\n"
+" stw 4, 132(3)" "\n"
+" li 3, 0" "\n"
+" blr" "\n"
+"" "\n"
+
+
+".global VG_MINIMAL_LONGJMP" "\n"
+"VG_MINIMAL_LONGJMP:" "\n" // r3 = jmp_buf
+ // do r4 = 1
+ // and park it in the restore slot for r3 (the ret reg)
+" li 4, 1" "\n"
+" stw 4, 12(3)" "\n"
+ // restore everything except r3
+ // then r3 last of all
+ // then blr
+" lwz 0, 128(3)" "\n"
+" mtlr 0" "\n"
+" lwz 0, 132(3)" "\n"
+" mtcr 0" "\n"
+" lwz 0, 0(3)" "\n"
+" lwz 1, 4(3)" "\n"
+" lwz 2, 8(3)" "\n"
+ // r3 is done at the end
+" lwz 4, 16(3)" "\n"
+" lwz 5, 20(3)" "\n"
+" lwz 6, 24(3)" "\n"
+" lwz 7, 28(3)" "\n"
+" lwz 8, 32(3)" "\n"
+" lwz 9, 36(3)" "\n"
+" lwz 10, 40(3)" "\n"
+" lwz 11, 44(3)" "\n"
+" lwz 12, 48(3)" "\n"
+" lwz 13, 52(3)" "\n"
+" lwz 14, 56(3)" "\n"
+" lwz 15, 60(3)" "\n"
+" lwz 16, 64(3)" "\n"
+" lwz 17, 68(3)" "\n"
+" lwz 18, 72(3)" "\n"
+" lwz 19, 76(3)" "\n"
+" lwz 20, 80(3)" "\n"
+" lwz 21, 84(3)" "\n"
+" lwz 22, 88(3)" "\n"
+" lwz 23, 92(3)" "\n"
+" lwz 24, 96(3)" "\n"
+" lwz 25, 100(3)" "\n"
+" lwz 26, 104(3)" "\n"
+" lwz 27, 108(3)" "\n"
+" lwz 28, 112(3)" "\n"
+" lwz 29, 116(3)" "\n"
+" lwz 30, 120(3)" "\n"
+" lwz 31, 124(3)" "\n"
+" lwz 3, 12(3)" "\n"
+" blr" "\n"
+"" "\n"
+
+
+".previous" "\n"
+);
+
+#endif /* VGP_ppc32_linux */
/*--------------------------------------------------------------------*/
diff --git a/coregrind/m_machine.c b/coregrind/m_machine.c
index 521569d..fe404fc 100644
--- a/coregrind/m_machine.c
+++ b/coregrind/m_machine.c
@@ -423,7 +423,7 @@
#if defined(VGA_ppc32) || defined(VGA_ppc64) \
|| defined(VGA_arm) || defined(VGA_s390x)
#include "pub_tool_libcsetjmp.h"
-static VG_MINIMAL_JMP_BUF env_unsup_insn;
+static VG_MINIMAL_JMP_BUF(env_unsup_insn);
static void handler_unsup_insn ( Int x ) {
VG_MINIMAL_LONGJMP(env_unsup_insn);
}
diff --git a/coregrind/pub_core_threadstate.h b/coregrind/pub_core_threadstate.h
index 639ef73..ebfc907 100644
--- a/coregrind/pub_core_threadstate.h
+++ b/coregrind/pub_core_threadstate.h
@@ -356,7 +356,7 @@
/* Per-thread jmp_buf to resume scheduler after a signal */
Bool sched_jmpbuf_valid;
- VG_MINIMAL_JMP_BUF sched_jmpbuf;
+ VG_MINIMAL_JMP_BUF(sched_jmpbuf);
}
ThreadState;