summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--exec-all.h2
-rw-r--r--tcg/ppc/tcg-target.c32
2 files changed, 25 insertions, 9 deletions
diff --git a/exec-all.h b/exec-all.h
index 94ed613e37..6b3272ab9e 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -337,7 +337,7 @@ extern uintptr_t tci_tb_ptr;
*(int32_t *)((void *)GETRA() + 3) - 1))
# elif defined (_ARCH_PPC) && !defined (_ARCH_PPC64)
# define GETRA() ((uintptr_t)__builtin_return_address(0))
-# define GETPC_LDST() ((uintptr_t) ((*(int32_t *)(GETRA() + 4)) - 1))
+# define GETPC_LDST() ((uintptr_t) ((*(int32_t *)(GETRA() - 4)) - 1))
# else
# error "CONFIG_QEMU_LDST_OPTIMIZATION needs GETPC_LDST() implementation!"
# endif
diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c
index a1c74cea63..34a0693c58 100644
--- a/tcg/ppc/tcg-target.c
+++ b/tcg/ppc/tcg-target.c
@@ -569,6 +569,9 @@ static const void * const qemu_st_helpers[4] = {
helper_stq_mmu,
};
+static void *ld_trampolines[4];
+static void *st_trampolines[4];
+
static void tcg_out_tlb_check (TCGContext *s, int r0, int r1, int r2,
int addr_reg, int addr_reg2, int s_bits,
int offset1, int offset2, uint8_t **label_ptr)
@@ -848,8 +851,7 @@ static void tcg_out_qemu_ld_slow_path (TCGContext *s, TCGLabelQemuLdst *label)
reloc_pc14 (label_ptr[0], (tcg_target_long) s->code_ptr);
/* slow path */
- ir = 3;
- tcg_out_mov (s, TCG_TYPE_I32, ir++, TCG_AREG0);
+ ir = 4;
#if TARGET_LONG_BITS == 32
tcg_out_mov (s, TCG_TYPE_I32, ir++, addr_reg);
#else
@@ -860,8 +862,7 @@ static void tcg_out_qemu_ld_slow_path (TCGContext *s, TCGLabelQemuLdst *label)
tcg_out_mov (s, TCG_TYPE_I32, ir++, addr_reg);
#endif
tcg_out_movi (s, TCG_TYPE_I32, ir, mem_index);
- tcg_out_call (s, (tcg_target_long) qemu_ld_helpers[s_bits], 1);
- tcg_out32 (s, B | 8);
+ tcg_out_call (s, (tcg_target_long) ld_trampolines[s_bits], 1);
tcg_out32 (s, (tcg_target_long) raddr);
switch (opc) {
case 0|4:
@@ -916,8 +917,7 @@ static void tcg_out_qemu_st_slow_path (TCGContext *s, TCGLabelQemuLdst *label)
reloc_pc14 (label_ptr[0], (tcg_target_long) s->code_ptr);
/* slow path */
- ir = 3;
- tcg_out_mov (s, TCG_TYPE_I32, ir++, TCG_AREG0);
+ ir = 4;
#if TARGET_LONG_BITS == 32
tcg_out_mov (s, TCG_TYPE_I32, ir++, addr_reg);
#else
@@ -959,8 +959,7 @@ static void tcg_out_qemu_st_slow_path (TCGContext *s, TCGLabelQemuLdst *label)
ir++;
tcg_out_movi (s, TCG_TYPE_I32, ir, mem_index);
- tcg_out_call (s, (tcg_target_long) qemu_st_helpers[opc], 1);
- tcg_out32 (s, B | 8);
+ tcg_out_call (s, (tcg_target_long) st_trampolines[opc], 1);
tcg_out32 (s, (tcg_target_long) raddr);
tcg_out_b (s, 0, (tcg_target_long) raddr);
}
@@ -983,6 +982,15 @@ void tcg_out_tb_finalize(TCGContext *s)
}
#endif
+static void emit_ldst_trampoline (TCGContext *s, const void *ptr)
+{
+ tcg_out32 (s, MFSPR | RT (3) | LR);
+ tcg_out32 (s, ADDI | RT (3) | RA (3) | 4);
+ tcg_out32 (s, MTSPR | RS (3) | LR);
+ tcg_out_mov (s, TCG_TYPE_I32, 3, TCG_AREG0);
+ tcg_out_b (s, 0, (tcg_target_long) ptr);
+}
+
static void tcg_target_qemu_prologue (TCGContext *s)
{
int i, frame_size;
@@ -1043,6 +1051,14 @@ static void tcg_target_qemu_prologue (TCGContext *s)
tcg_out32 (s, MTSPR | RS (0) | LR);
tcg_out32 (s, ADDI | RT (1) | RA (1) | frame_size);
tcg_out32 (s, BCLR | BO_ALWAYS);
+
+ for (i = 0; i < 4; ++i) {
+ ld_trampolines[i] = s->code_ptr;
+ emit_ldst_trampoline (s, qemu_ld_helpers[i]);
+
+ st_trampolines[i] = s->code_ptr;
+ emit_ldst_trampoline (s, qemu_st_helpers[i]);
+ }
}
static void tcg_out_ld (TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,