Signed-off-by: Richard Henderson <r...@twiddle.net> --- include/exec/exec-all.h | 16 +---------- tcg/aarch64/tcg-target.c | 69 ++++++++++++++++++++++++++---------------------- 2 files changed, 39 insertions(+), 46 deletions(-)
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index b3402a1..10e680d 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -325,7 +325,7 @@ extern uintptr_t tci_tb_ptr; (5) post-process (e.g. stack adjust) (6) jump to corresponding code of the next of fast path */ -# if defined(__i386__) || defined(__x86_64__) +# if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) # define GETRA() ((uintptr_t)__builtin_return_address(0)) /* The return address argument for ldst is passed directly. */ # define GETPC_LDST() (abort(), 0) @@ -334,20 +334,6 @@ extern uintptr_t tci_tb_ptr; # define GETPC_LDST() ((uintptr_t) ((*(int32_t *)(GETRA() - 4)) - 1)) # elif defined(__arm__) # define GETPC_EXT() GETPC() -# elif defined(__aarch64__) -# define GETRA() ((uintptr_t)__builtin_return_address(0)) -# define GETPC_LDST() tcg_getpc_ldst(GETRA()) -static inline uintptr_t tcg_getpc_ldst(uintptr_t ra) -{ - int32_t b; - ra += 4; /* skip one instruction */ - b = *(int32_t *)ra; /* load the branch insn */ - b = (b << 6) >> (6 - 2); /* extract the displacement */ - ra += b; /* apply the displacement */ - ra -= 4; /* return a pointer into the current opcode, - not the start of the next opcode */ - return ra; -} # else # error "CONFIG_QEMU_LDST_OPTIMIZATION needs GETPC_LDST() implementation!" # endif diff --git a/tcg/aarch64/tcg-target.c b/tcg/aarch64/tcg-target.c index a03da58..52c1be4 100644 --- a/tcg/aarch64/tcg-target.c +++ b/tcg/aarch64/tcg-target.c @@ -301,9 +301,6 @@ typedef enum { /* PC relative addressing instructions */ INSN_ADR = 0x10000000, INSN_ADRP = 0x90000000, - - /* System instructions */ - INSN_NOP = 0xd503201f, } AArch64Insn; typedef enum { @@ -522,6 +519,12 @@ static inline void tcg_out_movwi(TCGContext *s, AArch64Insn insn, tcg_out32(s, insn | ext | shift << 17 | value << 5 | rd); } +static inline void tcg_out_fmt_adr(TCGContext *s, AArch64Insn insn, + TCGReg rd, tcg_target_long diff) +{ + tcg_out32(s, insn | rd | (diff & 3) << 29 | (diff & 0x1ffffc) << (5 - 2)); +} + static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd, tcg_target_long value) { @@ -562,10 +565,7 @@ static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd, often when loading pointers to QEMU's data structures. */ valid = (value >> 12) - ((intptr_t)s->code_ptr >> 12); if (valid == sextract64(valid, 0, 21)) { - insn = INSN_ADRP | rd; - insn |= (valid & 3) << 29; - insn |= (valid & 0x1ffffc) << (5 - 2); - tcg_out32(s, insn); + tcg_out_fmt_adr(s, INSN_ADRP, rd, valid); if (value & 0xfff) { tcg_out_aimm(s, INSN_ADDI, ext, rd, rd, value & 0xfff); } @@ -985,32 +985,40 @@ static void tcg_out_addi(TCGContext *s, AArch64Ext ext, TCGReg rd, TCGReg rn, } } -static inline void tcg_out_nop(TCGContext *s) -{ - tcg_out32(s, INSN_NOP); -} - #ifdef CONFIG_SOFTMMU #include "exec/softmmu_defs.h" -/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr, - int mmu_idx) */ +/* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr, + * int mmu_idx, uintptr_t ra) + */ static const void * const qemu_ld_helpers[4] = { - helper_ldb_mmu, - helper_ldw_mmu, - helper_ldl_mmu, - helper_ldq_mmu, + helper_ret_ldb_mmu, + helper_ret_ldw_mmu, + helper_ret_ldl_mmu, + helper_ret_ldq_mmu, }; -/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr, - uintxx_t val, int mmu_idx) */ +/* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr, + * uintxx_t val, int mmu_idx, uintptr_t ra) + */ static const void * const qemu_st_helpers[4] = { - helper_stb_mmu, - helper_stw_mmu, - helper_stl_mmu, - helper_stq_mmu, + helper_ret_stb_mmu, + helper_ret_stw_mmu, + helper_ret_stl_mmu, + helper_ret_stq_mmu, }; +static inline void tcg_out_adr(TCGContext *s, TCGReg rd, tcg_target_long addr) +{ + tcg_out_fmt_adr(s, INSN_ADR, rd, addr - (tcg_target_long)s->code_ptr); +} + +/* See the GETPC definition in include/exec/exec-all.h. */ +static inline uintptr_t do_getpc(uint8_t *raddr) +{ + return (uintptr_t)raddr - 1; +} + static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb) { int opc = lb->opc; @@ -1021,9 +1029,9 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb) tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_X0, TCG_AREG0); tcg_out_mov(s, TCG_TYPE_TL, TCG_REG_X1, lb->addrlo_reg); tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_X2, lb->mem_index); - tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, - (tcg_target_long)qemu_ld_helpers[s_bits]); - tcg_out_callr(s, TCG_REG_TMP); + tcg_out_adr(s, TCG_REG_X3, do_getpc(lb->raddr)); + + tcg_out_call(s, (tcg_target_long)qemu_ld_helpers[s_bits]); if (opc & 0x04) { tcg_out_sxt(s, E64, s_bits, lb->datalo_reg, TCG_REG_X0); @@ -1046,11 +1054,10 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb) tcg_out_mov(s, s_bits == 3 ? TCG_TYPE_I64 : TCG_TYPE_I32, TCG_REG_X2, lb->datalo_reg); tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_X3, lb->mem_index); - tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, - (tcg_target_long)qemu_st_helpers[s_bits]); - tcg_out_callr(s, TCG_REG_TMP); + tcg_out_adr(s, TCG_REG_X4, do_getpc(lb->raddr)); + + tcg_out_call(s, (tcg_target_long)qemu_st_helpers[s_bits]); - tcg_out_nop(s); tcg_out_goto(s, (tcg_target_long)lb->raddr); } -- 1.8.3.1