From fd9933fbd5dd06ca309a345cff81c16d7b2725eb Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 27 Feb 2018 23:58:20 -0500 Subject: [PATCH] target-arm: Rearrange aa32 load and store functions Stop specializing on TARGET_LONG_BITS == 32; unconditionally allocate a temp and expand with tcg_gen_extu_i32_tl. Split out gen_aa32_addr, gen_aa32_frob64, gen_aa32_ld_i32 and gen_aa32_st_i32 as separate interfaces. Backports commit 7f5616f53896a4e08ad37de3ac50d3a4cc8eff7a from qemu --- qemu/target-arm/translate.c | 201 +++++++++++++++--------------------- 1 file changed, 84 insertions(+), 117 deletions(-) diff --git a/qemu/target-arm/translate.c b/qemu/target-arm/translate.c index 9db75633..ba60feda 100644 --- a/qemu/target-arm/translate.c +++ b/qemu/target-arm/translate.c @@ -961,145 +961,112 @@ static inline void store_reg_from_load(DisasContext *s, int reg, TCGv_i32 var) * These functions work like tcg_gen_qemu_{ld,st}* except * that the address argument is TCGv_i32 rather than TCGv. */ -#if TARGET_LONG_BITS == 32 - -#define DO_GEN_LD(SUFF, OPC, BE32_XOR) \ -static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, TCGv_i32 addr, int index) \ -{ \ - TCGContext *tcg_ctx = s->uc->tcg_ctx; \ - TCGMemOp opc = (OPC) | s->be_data; \ - /* Not needed for user-mode BE32, where we use MO_BE instead. */ \ - if (!IS_USER_ONLY && s->sctlr_b && BE32_XOR) { \ - TCGv addr_be = tcg_temp_new(tcg_ctx); \ - tcg_gen_xori_i32(tcg_ctx, addr_be, addr, BE32_XOR); \ - tcg_gen_qemu_ld_i32(s->uc, val, addr_be, index, opc); \ - tcg_temp_free(tcg_ctx, addr_be); \ - return; \ - } \ - tcg_gen_qemu_ld_i32(s->uc, val, addr, index, opc); \ -} - -#define DO_GEN_ST(SUFF, OPC, BE32_XOR) \ -static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, TCGv_i32 addr, int index) \ -{ \ - TCGContext *tcg_ctx = s->uc->tcg_ctx; \ - TCGMemOp opc = (OPC) | s->be_data; \ - /* Not needed for user-mode BE32, where we use MO_BE instead. */ \ - if (!IS_USER_ONLY && s->sctlr_b && BE32_XOR) { \ - TCGv addr_be = tcg_temp_new(tcg_ctx); \ - tcg_gen_xori_i32(tcg_ctx, addr_be, addr, BE32_XOR); \ - tcg_gen_qemu_st_i32(s->uc, val, addr_be, index, opc); \ - tcg_temp_free(tcg_ctx, addr_be); \ - return; \ - } \ - tcg_gen_qemu_st_i32(s->uc, val, addr, index, opc); \ -} - -static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val, TCGv_i32 addr, int index) +static inline TCGv gen_aa32_addr(DisasContext *s, TCGv_i32 a32, TCGMemOp op) { TCGContext *tcg_ctx = s->uc->tcg_ctx; - TCGMemOp opc = MO_Q | s->be_data; - tcg_gen_qemu_ld_i64(s->uc, val, addr, index, opc); + TCGv addr = tcg_temp_new(tcg_ctx); + tcg_gen_extu_i32_tl(tcg_ctx, addr, a32); + + /* Not needed for user-mode BE32, where we use MO_BE instead. */ + if (!IS_USER_ONLY && s->sctlr_b && (op & MO_SIZE) < MO_32) { + tcg_gen_xori_tl(tcg_ctx, addr, addr, 4 - (1 << (op & MO_SIZE))); + } + return addr; +} + +static void gen_aa32_ld_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32, + int index, TCGMemOp opc) +{ + TCGContext *tcg_ctx = s->uc->tcg_ctx; + TCGv addr = gen_aa32_addr(s, a32, opc); + tcg_gen_qemu_ld_i32(s->uc, val, addr, index, opc); + tcg_temp_free(tcg_ctx, addr); +} + +static void gen_aa32_st_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32, + int index, TCGMemOp opc) +{ + TCGContext *tcg_ctx = s->uc->tcg_ctx; + TCGv addr = gen_aa32_addr(s, a32, opc); + tcg_gen_qemu_st_i32(s->uc, val, addr, index, opc); + tcg_temp_free(tcg_ctx, addr); +} + +#define DO_GEN_LD(SUFF, OPC) \ +static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, \ + TCGv_i32 a32, int index) \ +{ \ + gen_aa32_ld_i32(s, val, a32, index, OPC | s->be_data); \ +} + +#define DO_GEN_ST(SUFF, OPC) \ +static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, \ + TCGv_i32 a32, int index) \ +{ \ + gen_aa32_st_i32(s, val, a32, index, OPC | s->be_data); \ +} + +static inline void gen_aa32_frob64(DisasContext *s, TCGv_i64 val) +{ + TCGContext *tcg_ctx = s->uc->tcg_ctx; + /* Not needed for user-mode BE32, where we use MO_BE instead. */ if (!IS_USER_ONLY && s->sctlr_b) { tcg_gen_rotri_i64(tcg_ctx, val, val, 32); } } -static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val, TCGv_i32 addr, int index) +static void gen_aa32_ld_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32, + int index, TCGMemOp opc) { TCGContext *tcg_ctx = s->uc->tcg_ctx; - TCGMemOp opc = MO_Q | s->be_data; + TCGv addr = gen_aa32_addr(s, a32, opc); + tcg_gen_qemu_ld_i64(s->uc, val, addr, index, opc); + gen_aa32_frob64(s, val); + tcg_temp_free(tcg_ctx, addr); +} + +static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val, + TCGv_i32 a32, int index) +{ + gen_aa32_ld_i64(s, val, a32, index, MO_Q | s->be_data); +} + +static void gen_aa32_st_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32, + int index, TCGMemOp opc) +{ + TCGContext *tcg_ctx = s->uc->tcg_ctx; + TCGv addr = gen_aa32_addr(s, a32, opc); + /* Not needed for user-mode BE32, where we use MO_BE instead. */ if (!IS_USER_ONLY && s->sctlr_b) { TCGv_i64 tmp = tcg_temp_new_i64(tcg_ctx); tcg_gen_rotri_i64(tcg_ctx, tmp, val, 32); tcg_gen_qemu_st_i64(s->uc, tmp, addr, index, opc); tcg_temp_free_i64(tcg_ctx, tmp); - return; - } - tcg_gen_qemu_st_i64(s->uc, val, addr, index, opc); -} - -#else - -#define DO_GEN_LD(SUFF, OPC, BE32_XOR) \ -static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, TCGv_i32 addr, int index) \ -{ \ - TCGContext *tcg_ctx = s->uc->tcg_ctx; \ - TCGMemOp opc = (OPC) | s->be_data; \ - TCGv addr64 = tcg_temp_new(tcg_ctx); \ - tcg_gen_extu_i32_i64(tcg_ctx, addr64, addr); \ - /* Not needed for user-mode BE32, where we use MO_BE instead. */ \ - if (!IS_USER_ONLY && s->sctlr_b && BE32_XOR) { \ - tcg_gen_xori_i64(tcg_ctx, addr64, addr64, BE32_XOR); \ - } \ - tcg_gen_qemu_ld_i32(s->uc, val, addr64, index, opc); \ - tcg_temp_free(tcg_ctx, addr64); \ -} - -#define DO_GEN_ST(SUFF, OPC, BE32_XOR) \ -static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, TCGv_i32 addr, int index) \ -{ \ - TCGContext *tcg_ctx = s->uc->tcg_ctx; \ - TCGMemOp opc = (OPC) | s->be_data; \ - TCGv addr64 = tcg_temp_new(tcg_ctx); \ - tcg_gen_extu_i32_i64(tcg_ctx, addr64, addr); \ - /* Not needed for user-mode BE32, where we use MO_BE instead. */ \ - if (!IS_USER_ONLY && s->sctlr_b && BE32_XOR) { \ - tcg_gen_xori_i64(tcg_ctx, addr64, addr64, BE32_XOR); \ - } \ - tcg_gen_qemu_st_i32(s->uc, val, addr64, index, opc); \ - tcg_temp_free(tcg_ctx, addr64); \ -} - -static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val, TCGv_i32 addr, int index) -{ - TCGContext *tcg_ctx = s->uc->tcg_ctx; - TCGMemOp opc = MO_Q | s->be_data; - TCGv addr64 = tcg_temp_new(tcg_ctx); - tcg_gen_extu_i32_i64(tcg_ctx, addr64, addr); - tcg_gen_qemu_ld_i64(s->uc, val, addr64, index, opc); - - /* Not needed for user-mode BE32, where we use MO_BE instead. */ - if (!IS_USER_ONLY && s->sctlr_b) { - tcg_gen_rotri_i64(tcg_ctx, val, val, 32); - } - tcg_temp_free(tcg_ctx, addr64); -} - -static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val, TCGv_i32 addr, int index) -{ - TCGContext *tcg_ctx = s->uc->tcg_ctx; - TCGMemOp opc = MO_Q | s->be_data; - TCGv addr64 = tcg_temp_new(tcg_ctx); - tcg_gen_extu_i32_i64(tcg_ctx, addr64, addr); - - /* Not needed for user-mode BE32, where we use MO_BE instead. */ - if (!IS_USER_ONLY && s->sctlr_b) { - TCGv tmp = tcg_temp_new(tcg_ctx); - tcg_gen_rotri_i64(tcg_ctx, tmp, val, 32); - tcg_gen_qemu_st_i64(s->uc, tmp, addr64, index, opc); - tcg_temp_free(tcg_ctx, tmp); } else { - tcg_gen_qemu_st_i64(s->uc, val, addr64, index, opc); + tcg_gen_qemu_st_i64(s->uc, val, addr, index, opc); } - tcg_temp_free(tcg_ctx, addr64); + tcg_temp_free(tcg_ctx, addr); } -#endif +static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val, + TCGv_i32 a32, int index) +{ + gen_aa32_st_i64(s, val, a32, index, MO_Q | s->be_data); +} -DO_GEN_LD(8s, MO_SB, 3) -DO_GEN_LD(8u, MO_UB, 3) -DO_GEN_LD(16s, MO_SW, 2) -DO_GEN_LD(16u, MO_UW, 2) -DO_GEN_LD(32u, MO_UL, 0) +DO_GEN_LD(8s, MO_SB) +DO_GEN_LD(8u, MO_UB) +DO_GEN_LD(16s, MO_SW) +DO_GEN_LD(16u, MO_UW) +DO_GEN_LD(32u, MO_UL) /* 'a' variants include an alignment check */ -DO_GEN_LD(16ua, MO_UW | MO_ALIGN, 2) -DO_GEN_LD(32ua, MO_UL | MO_ALIGN, 0) -DO_GEN_ST(8, MO_UB, 3) -DO_GEN_ST(16, MO_UW, 2) -DO_GEN_ST(32, MO_UL, 0) +DO_GEN_LD(16ua, MO_UW | MO_ALIGN) +DO_GEN_LD(32ua, MO_UL | MO_ALIGN) +DO_GEN_ST(8, MO_UB) +DO_GEN_ST(16, MO_UW) +DO_GEN_ST(32, MO_UL) static inline void gen_set_pc_im(DisasContext *s, target_ulong val) {