summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dyngen-exec.h2
-rw-r--r--exec-all.h18
2 files changed, 19 insertions, 1 deletions
diff --git a/dyngen-exec.h b/dyngen-exec.h
index 9f5fcc6ce5..75d27ce169 100644
--- a/dyngen-exec.h
+++ b/dyngen-exec.h
@@ -254,7 +254,7 @@ extern int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3;
#define GOTO_LABEL_PARAM(n) asm volatile ("b " ASM_NAME(__op_gen_label) #n)
#elif defined(__s390__)
#define EXIT_TB() asm volatile ("br %r14")
-#define GOTO_LABEL_PARAM(n) asm volatile ("b " ASM_NAME(__op_gen_label) #n)
+#define GOTO_LABEL_PARAM(n) asm volatile ("bras %r7,8; .long " ASM_NAME(__op_gen_label) #n "; l %r7, 0(%r7); br %r7")
#elif defined(__alpha__)
#define EXIT_TB() asm volatile ("ret")
#elif defined(__ia64__)
diff --git a/exec-all.h b/exec-all.h
index 8ea057b79c..31914ee2f3 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -340,6 +340,24 @@ do {\
"1:\n");\
} while (0)
+#elif defined(__s390__)
+/* GCC spills R13, so we have to restore it before branching away */
+
+#define GOTO_TB(opname, tbparam, n)\
+do {\
+ static void __attribute__((used)) *dummy ## n = &&dummy_label ## n;\
+ static void __attribute__((used)) *__op_label ## n \
+ __asm__(ASM_OP_LABEL_NAME(n, opname)) = &&label ## n;\
+ __asm__ __volatile__ ( \
+ "l %%r13,52(%%r15)\n" \
+ "br %0\n" \
+ : : "r" (((TranslationBlock*)tbparam)->tb_next[n]));\
+ \
+ for(;*((int*)0);); /* just to keep GCC busy */ \
+label ## n: ;\
+dummy_label ## n: ;\
+} while(0)
+
#else
/* jump to next block operations (more portable code, does not need