From 1098cc3fcf952763fc9fd72c1c8fda30a18cc8ea Mon Sep 17 00:00:00 2001 From: Shivaprasad G Bhat Date: Tue, 2 May 2023 20:55:30 +0530 Subject: [PATCH 01/42] softfloat: Fix the incorrect computation in float32_exp2 The float32_exp2 function is computing wrong exponent of 2. For example, with the following set of values {0.1, 2.0, 2.0, -1.0}, the expected output would be {1.071773, 4.000000, 4.000000, 0.500000}. Instead, the function is computing {1.119102, 3.382044, 3.382044, -0.191022} Looking at the code, the float32_exp2() attempts to do this 2 3 4 5 n x x x x x x x e = 1 + --- + --- + --- + --- + --- + ... + --- + ... 1! 2! 3! 4! 5! n! But because of the typo it ends up doing x x x x x x x e = 1 + --- + --- + --- + --- + --- + ... + --- + ... 1! 2! 3! 4! 5! n! This is because instead of the xnp which holds the numerator, parts_muladd is using the xp which is just 'x'. Commit '572c4d862ff2' refactored this function, and mistakenly used xp instead of xnp. Cc: qemu-stable@nongnu.org Fixes: 572c4d862ff2 "softfloat: Convert float32_exp2 to FloatParts" Partially-Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1623 Reported-By: Luca Barbato (https://gitlab.com/lu-zero) Signed-off-by: Shivaprasad G Bhat Signed-off-by: Vaibhav Jain Message-Id: <168304110865.537992.13059030916325018670.stgit@localhost.localdomain> Reviewed-by: Richard Henderson Signed-off-by: Richard Henderson --- fpu/softfloat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fpu/softfloat.c b/fpu/softfloat.c index c7454c3eb1..108f9cb224 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -5135,7 +5135,7 @@ float32 float32_exp2(float32 a, float_status *status) float64_unpack_canonical(&rp, float64_one, status); for (i = 0 ; i < 15 ; i++) { float64_unpack_canonical(&tp, float32_exp2_coefficients[i], status); - rp = *parts_muladd(&tp, &xp, &rp, 0, status); + rp = *parts_muladd(&tp, &xnp, &rp, 0, status); xnp = *parts_mul(&xnp, &xp, status); } From 8b4506e5d27eead774ec233c98cb5d2b6ed1e03d Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 May 2023 14:57:33 +0100 Subject: [PATCH 02/42] target/avr: Finish conversion to tcg_gen_qemu_{ld,st}_* Convert away from the old interface with the implicit MemOp argument. Signed-off-by: Richard Henderson Reviewed-by: Anton Johansson Message-Id: <20230502135741.1158035-2-richard.henderson@linaro.org> --- target/avr/translate.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/target/avr/translate.c b/target/avr/translate.c index a6aeae6dfa..cd82f5d591 100644 --- a/target/avr/translate.c +++ b/target/avr/translate.c @@ -1492,7 +1492,7 @@ static void gen_data_store(DisasContext *ctx, TCGv data, TCGv addr) if (ctx->base.tb->flags & TB_FLAGS_FULL_ACCESS) { gen_helper_fullwr(cpu_env, data, addr); } else { - tcg_gen_qemu_st8(data, addr, MMU_DATA_IDX); /* mem[addr] = data */ + tcg_gen_qemu_st_tl(data, addr, MMU_DATA_IDX, MO_UB); } } @@ -1501,7 +1501,7 @@ static void gen_data_load(DisasContext *ctx, TCGv data, TCGv addr) if (ctx->base.tb->flags & TB_FLAGS_FULL_ACCESS) { gen_helper_fullrd(data, cpu_env, addr); } else { - tcg_gen_qemu_ld8u(data, addr, MMU_DATA_IDX); /* data = mem[addr] */ + tcg_gen_qemu_ld_tl(data, addr, MMU_DATA_IDX, MO_UB); } } @@ -1979,7 +1979,7 @@ static bool trans_LPM1(DisasContext *ctx, arg_LPM1 *a) tcg_gen_shli_tl(addr, H, 8); /* addr = H:L */ tcg_gen_or_tl(addr, addr, L); - tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */ + tcg_gen_qemu_ld_tl(Rd, addr, MMU_CODE_IDX, MO_UB); return true; } @@ -1996,7 +1996,7 @@ static bool trans_LPM2(DisasContext *ctx, arg_LPM2 *a) tcg_gen_shli_tl(addr, H, 8); /* addr = H:L */ tcg_gen_or_tl(addr, addr, L); - tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */ + tcg_gen_qemu_ld_tl(Rd, addr, MMU_CODE_IDX, MO_UB); return true; } @@ -2013,7 +2013,7 @@ static bool trans_LPMX(DisasContext *ctx, arg_LPMX *a) tcg_gen_shli_tl(addr, H, 8); /* addr = H:L */ tcg_gen_or_tl(addr, addr, L); - tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */ + tcg_gen_qemu_ld_tl(Rd, addr, MMU_CODE_IDX, MO_UB); tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */ tcg_gen_andi_tl(L, addr, 0xff); tcg_gen_shri_tl(addr, addr, 8); @@ -2045,7 +2045,7 @@ static bool trans_ELPM1(DisasContext *ctx, arg_ELPM1 *a) TCGv Rd = cpu_r[0]; TCGv addr = gen_get_zaddr(); - tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */ + tcg_gen_qemu_ld_tl(Rd, addr, MMU_CODE_IDX, MO_UB); return true; } @@ -2058,7 +2058,7 @@ static bool trans_ELPM2(DisasContext *ctx, arg_ELPM2 *a) TCGv Rd = cpu_r[a->rd]; TCGv addr = gen_get_zaddr(); - tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */ + tcg_gen_qemu_ld_tl(Rd, addr, MMU_CODE_IDX, MO_UB); return true; } @@ -2071,7 +2071,7 @@ static bool trans_ELPMX(DisasContext *ctx, arg_ELPMX *a) TCGv Rd = cpu_r[a->rd]; TCGv addr = gen_get_zaddr(); - tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */ + tcg_gen_qemu_ld_tl(Rd, addr, MMU_CODE_IDX, MO_UB); tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */ gen_set_zaddr(addr); return true; From a9a9c3fa6f2f3c04f4bb6a91731bbbc7d01da253 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 May 2023 14:57:34 +0100 Subject: [PATCH 03/42] target/cris: Finish conversion to tcg_gen_qemu_{ld,st}_* Convert away from the old interface with the implicit MemOp argument. In this case we can fold the calls using the size bits of MemOp. Signed-off-by: Richard Henderson Reviewed-by: Anton Johansson Message-Id: <20230502135741.1158035-3-richard.henderson@linaro.org> --- target/cris/translate_v10.c.inc | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/target/cris/translate_v10.c.inc b/target/cris/translate_v10.c.inc index 32338bb69b..b7b0517982 100644 --- a/target/cris/translate_v10.c.inc +++ b/target/cris/translate_v10.c.inc @@ -80,13 +80,9 @@ static void gen_store_v10_conditional(DisasContext *dc, TCGv addr, TCGv val, /* Store only if F flag isn't set */ tcg_gen_andi_tl(t1, cpu_PR[PR_CCS], F_FLAG_V10); tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1); - if (size == 1) { - tcg_gen_qemu_st8(tval, taddr, mem_index); - } else if (size == 2) { - tcg_gen_qemu_st16(tval, taddr, mem_index); - } else { - tcg_gen_qemu_st32(tval, taddr, mem_index); - } + + tcg_gen_qemu_st_tl(tval, taddr, mem_index, ctz32(size) | MO_TE); + gen_set_label(l1); tcg_gen_shri_tl(t1, t1, 1); /* shift F to P position */ tcg_gen_or_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], t1); /*P=F*/ @@ -109,13 +105,7 @@ static void gen_store_v10(DisasContext *dc, TCGv addr, TCGv val, return; } - if (size == 1) { - tcg_gen_qemu_st8(val, addr, mem_index); - } else if (size == 2) { - tcg_gen_qemu_st16(val, addr, mem_index); - } else { - tcg_gen_qemu_st32(val, addr, mem_index); - } + tcg_gen_qemu_st_tl(val, addr, mem_index, ctz32(size) | MO_TE); } From 53b26d253c12829b3adc68abffd5d0a664b5cb3c Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 May 2023 14:57:35 +0100 Subject: [PATCH 04/42] target/Hexagon: Finish conversion to tcg_gen_qemu_{ld, st}_* Convert away from the old interface with the implicit MemOp argument. Importantly, this removes some incorrect casts generated by idef-parser's gen_load(). Signed-off-by: Richard Henderson Tested-by: Taylor Simpson Reviewed-by: Taylor Simpson Reviewed-by: Anton Johansson Message-Id: <20230502135741.1158035-4-richard.henderson@linaro.org> --- target/hexagon/genptr.c | 8 +++--- target/hexagon/idef-parser/parser-helpers.c | 28 +++++++++--------- target/hexagon/macros.h | 14 ++++----- target/hexagon/translate.c | 32 ++++++++++----------- 4 files changed, 40 insertions(+), 42 deletions(-) diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c index 502c85ae35..244063b1d2 100644 --- a/target/hexagon/genptr.c +++ b/target/hexagon/genptr.c @@ -320,14 +320,14 @@ void gen_set_byte_i64(int N, TCGv_i64 result, TCGv src) static inline void gen_load_locked4u(TCGv dest, TCGv vaddr, int mem_index) { - tcg_gen_qemu_ld32u(dest, vaddr, mem_index); + tcg_gen_qemu_ld_tl(dest, vaddr, mem_index, MO_TEUL); tcg_gen_mov_tl(hex_llsc_addr, vaddr); tcg_gen_mov_tl(hex_llsc_val, dest); } static inline void gen_load_locked8u(TCGv_i64 dest, TCGv vaddr, int mem_index) { - tcg_gen_qemu_ld64(dest, vaddr, mem_index); + tcg_gen_qemu_ld_i64(dest, vaddr, mem_index, MO_TEUQ); tcg_gen_mov_tl(hex_llsc_addr, vaddr); tcg_gen_mov_i64(hex_llsc_val_i64, dest); } @@ -678,7 +678,7 @@ static void gen_load_frame(DisasContext *ctx, TCGv_i64 frame, TCGv EA) { Insn *insn = ctx->insn; /* Needed for CHECK_NOSHUF */ CHECK_NOSHUF(EA, 8); - tcg_gen_qemu_ld64(frame, EA, ctx->mem_idx); + tcg_gen_qemu_ld_i64(frame, EA, ctx->mem_idx, MO_TEUQ); } static void gen_return(DisasContext *ctx, TCGv_i64 dst, TCGv src) @@ -1019,7 +1019,7 @@ static void gen_vreg_load(DisasContext *ctx, intptr_t dstoff, TCGv src, tcg_gen_andi_tl(src, src, ~((int32_t)sizeof(MMVector) - 1)); } for (int i = 0; i < sizeof(MMVector) / 8; i++) { - tcg_gen_qemu_ld64(tmp, src, ctx->mem_idx); + tcg_gen_qemu_ld_i64(tmp, src, ctx->mem_idx, MO_TEUQ); tcg_gen_addi_tl(src, src, 8); tcg_gen_st_i64(tmp, cpu_env, dstoff + i * 8); } diff --git a/target/hexagon/idef-parser/parser-helpers.c b/target/hexagon/idef-parser/parser-helpers.c index 86511efb62..8734218e51 100644 --- a/target/hexagon/idef-parser/parser-helpers.c +++ b/target/hexagon/idef-parser/parser-helpers.c @@ -1737,36 +1737,34 @@ void gen_load_cancel(Context *c, YYLTYPE *locp) void gen_load(Context *c, YYLTYPE *locp, HexValue *width, HexSignedness signedness, HexValue *ea, HexValue *dst) { - char size_suffix[4] = {0}; - const char *sign_suffix; + unsigned dst_bit_width; + unsigned src_bit_width; + /* Memop width is specified in the load macro */ assert_signedness(c, locp, signedness); - sign_suffix = (width->imm.value > 4) - ? "" - : ((signedness == UNSIGNED) ? "u" : "s"); + /* If dst is a variable, assert that is declared and load the type info */ if (dst->type == VARID) { find_variable(c, locp, dst, dst); } - snprintf(size_suffix, 4, "%" PRIu64, width->imm.value * 8); + src_bit_width = width->imm.value * 8; + dst_bit_width = MAX(dst->bit_width, 32); + /* Lookup the effective address EA */ find_variable(c, locp, ea, ea); OUT(c, locp, "if (insn->slot == 0 && pkt->pkt_has_store_s1) {\n"); OUT(c, locp, "probe_noshuf_load(", ea, ", ", width, ", ctx->mem_idx);\n"); OUT(c, locp, "process_store(ctx, 1);\n"); OUT(c, locp, "}\n"); - OUT(c, locp, "tcg_gen_qemu_ld", size_suffix, sign_suffix); + + OUT(c, locp, "tcg_gen_qemu_ld_i", &dst_bit_width); OUT(c, locp, "("); - if (dst->bit_width > width->imm.value * 8) { - /* - * Cast to the correct TCG type if necessary, to avoid implict cast - * warnings. This is needed when the width of the destination var is - * larger than the size of the requested load. - */ - OUT(c, locp, "(TCGv) "); + OUT(c, locp, dst, ", ", ea, ", ctx->mem_idx, MO_", &src_bit_width); + if (signedness == SIGNED) { + OUT(c, locp, " | MO_SIGN"); } - OUT(c, locp, dst, ", ", ea, ", ctx->mem_idx);\n"); + OUT(c, locp, " | MO_TE);\n"); } void gen_store(Context *c, YYLTYPE *locp, HexValue *width, HexValue *ea, diff --git a/target/hexagon/macros.h b/target/hexagon/macros.h index 3e162de3a7..760630de8f 100644 --- a/target/hexagon/macros.h +++ b/target/hexagon/macros.h @@ -99,37 +99,37 @@ #define MEM_LOAD1s(DST, VA) \ do { \ CHECK_NOSHUF(VA, 1); \ - tcg_gen_qemu_ld8s(DST, VA, ctx->mem_idx); \ + tcg_gen_qemu_ld_tl(DST, VA, ctx->mem_idx, MO_SB); \ } while (0) #define MEM_LOAD1u(DST, VA) \ do { \ CHECK_NOSHUF(VA, 1); \ - tcg_gen_qemu_ld8u(DST, VA, ctx->mem_idx); \ + tcg_gen_qemu_ld_tl(DST, VA, ctx->mem_idx, MO_UB); \ } while (0) #define MEM_LOAD2s(DST, VA) \ do { \ CHECK_NOSHUF(VA, 2); \ - tcg_gen_qemu_ld16s(DST, VA, ctx->mem_idx); \ + tcg_gen_qemu_ld_tl(DST, VA, ctx->mem_idx, MO_TESW); \ } while (0) #define MEM_LOAD2u(DST, VA) \ do { \ CHECK_NOSHUF(VA, 2); \ - tcg_gen_qemu_ld16u(DST, VA, ctx->mem_idx); \ + tcg_gen_qemu_ld_tl(DST, VA, ctx->mem_idx, MO_TEUW); \ } while (0) #define MEM_LOAD4s(DST, VA) \ do { \ CHECK_NOSHUF(VA, 4); \ - tcg_gen_qemu_ld32s(DST, VA, ctx->mem_idx); \ + tcg_gen_qemu_ld_tl(DST, VA, ctx->mem_idx, MO_TESL); \ } while (0) #define MEM_LOAD4u(DST, VA) \ do { \ CHECK_NOSHUF(VA, 4); \ - tcg_gen_qemu_ld32s(DST, VA, ctx->mem_idx); \ + tcg_gen_qemu_ld_tl(DST, VA, ctx->mem_idx, MO_TEUL); \ } while (0) #define MEM_LOAD8u(DST, VA) \ do { \ CHECK_NOSHUF(VA, 8); \ - tcg_gen_qemu_ld64(DST, VA, ctx->mem_idx); \ + tcg_gen_qemu_ld_i64(DST, VA, ctx->mem_idx, MO_TEUQ); \ } while (0) #define MEM_STORE1_FUNC(X) \ diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c index c087f183d0..cddd7c5db4 100644 --- a/target/hexagon/translate.c +++ b/target/hexagon/translate.c @@ -627,27 +627,27 @@ void process_store(DisasContext *ctx, int slot_num) switch (ctx->store_width[slot_num]) { case 1: gen_check_store_width(ctx, slot_num); - tcg_gen_qemu_st8(hex_store_val32[slot_num], - hex_store_addr[slot_num], - ctx->mem_idx); + tcg_gen_qemu_st_tl(hex_store_val32[slot_num], + hex_store_addr[slot_num], + ctx->mem_idx, MO_UB); break; case 2: gen_check_store_width(ctx, slot_num); - tcg_gen_qemu_st16(hex_store_val32[slot_num], - hex_store_addr[slot_num], - ctx->mem_idx); + tcg_gen_qemu_st_tl(hex_store_val32[slot_num], + hex_store_addr[slot_num], + ctx->mem_idx, MO_TEUW); break; case 4: gen_check_store_width(ctx, slot_num); - tcg_gen_qemu_st32(hex_store_val32[slot_num], - hex_store_addr[slot_num], - ctx->mem_idx); + tcg_gen_qemu_st_tl(hex_store_val32[slot_num], + hex_store_addr[slot_num], + ctx->mem_idx, MO_TEUL); break; case 8: gen_check_store_width(ctx, slot_num); - tcg_gen_qemu_st64(hex_store_val64[slot_num], - hex_store_addr[slot_num], - ctx->mem_idx); + tcg_gen_qemu_st_i64(hex_store_val64[slot_num], + hex_store_addr[slot_num], + ctx->mem_idx, MO_TEUQ); break; default: { @@ -693,13 +693,13 @@ static void process_dczeroa(DisasContext *ctx) TCGv_i64 zero = tcg_constant_i64(0); tcg_gen_andi_tl(addr, hex_dczero_addr, ~0x1f); - tcg_gen_qemu_st64(zero, addr, ctx->mem_idx); + tcg_gen_qemu_st_i64(zero, addr, ctx->mem_idx, MO_UQ); tcg_gen_addi_tl(addr, addr, 8); - tcg_gen_qemu_st64(zero, addr, ctx->mem_idx); + tcg_gen_qemu_st_i64(zero, addr, ctx->mem_idx, MO_UQ); tcg_gen_addi_tl(addr, addr, 8); - tcg_gen_qemu_st64(zero, addr, ctx->mem_idx); + tcg_gen_qemu_st_i64(zero, addr, ctx->mem_idx, MO_UQ); tcg_gen_addi_tl(addr, addr, 8); - tcg_gen_qemu_st64(zero, addr, ctx->mem_idx); + tcg_gen_qemu_st_i64(zero, addr, ctx->mem_idx, MO_UQ); } } From b7a94da9550be04441ffd91f0865d604c8a804cd Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 May 2023 14:57:36 +0100 Subject: [PATCH 05/42] target/m68k: Finish conversion to tcg_gen_qemu_{ld,st}_* Convert away from the old interface with the implicit MemOp argument. Signed-off-by: Richard Henderson Reviewed-by: Anton Johansson Message-Id: <20230502135741.1158035-5-richard.henderson@linaro.org> --- target/m68k/translate.c | 76 ++++++++++++++--------------------------- 1 file changed, 25 insertions(+), 51 deletions(-) diff --git a/target/m68k/translate.c b/target/m68k/translate.c index 422f4652f1..744eb3748b 100644 --- a/target/m68k/translate.c +++ b/target/m68k/translate.c @@ -304,23 +304,14 @@ static inline void gen_addr_fault(DisasContext *s) static inline TCGv gen_load(DisasContext *s, int opsize, TCGv addr, int sign, int index) { - TCGv tmp; - tmp = tcg_temp_new_i32(); - switch(opsize) { + TCGv tmp = tcg_temp_new_i32(); + + switch (opsize) { case OS_BYTE: - if (sign) - tcg_gen_qemu_ld8s(tmp, addr, index); - else - tcg_gen_qemu_ld8u(tmp, addr, index); - break; case OS_WORD: - if (sign) - tcg_gen_qemu_ld16s(tmp, addr, index); - else - tcg_gen_qemu_ld16u(tmp, addr, index); - break; case OS_LONG: - tcg_gen_qemu_ld32u(tmp, addr, index); + tcg_gen_qemu_ld_tl(tmp, addr, index, + opsize | (sign ? MO_SIGN : 0) | MO_TE); break; default: g_assert_not_reached(); @@ -332,15 +323,11 @@ static inline TCGv gen_load(DisasContext *s, int opsize, TCGv addr, static inline void gen_store(DisasContext *s, int opsize, TCGv addr, TCGv val, int index) { - switch(opsize) { + switch (opsize) { case OS_BYTE: - tcg_gen_qemu_st8(val, addr, index); - break; case OS_WORD: - tcg_gen_qemu_st16(val, addr, index); - break; case OS_LONG: - tcg_gen_qemu_st32(val, addr, index); + tcg_gen_qemu_st_tl(val, addr, index, opsize | MO_TE); break; default: g_assert_not_reached(); @@ -971,23 +958,16 @@ static void gen_load_fp(DisasContext *s, int opsize, TCGv addr, TCGv_ptr fp, tmp = tcg_temp_new(); switch (opsize) { case OS_BYTE: - tcg_gen_qemu_ld8s(tmp, addr, index); - gen_helper_exts32(cpu_env, fp, tmp); - break; case OS_WORD: - tcg_gen_qemu_ld16s(tmp, addr, index); - gen_helper_exts32(cpu_env, fp, tmp); - break; - case OS_LONG: - tcg_gen_qemu_ld32u(tmp, addr, index); + tcg_gen_qemu_ld_tl(tmp, addr, index, opsize | MO_SIGN | MO_TE); gen_helper_exts32(cpu_env, fp, tmp); break; case OS_SINGLE: - tcg_gen_qemu_ld32u(tmp, addr, index); + tcg_gen_qemu_ld_tl(tmp, addr, index, MO_TEUL); gen_helper_extf32(cpu_env, fp, tmp); break; case OS_DOUBLE: - tcg_gen_qemu_ld64(t64, addr, index); + tcg_gen_qemu_ld_i64(t64, addr, index, MO_TEUQ); gen_helper_extf64(cpu_env, fp, t64); break; case OS_EXTENDED: @@ -995,11 +975,11 @@ static void gen_load_fp(DisasContext *s, int opsize, TCGv addr, TCGv_ptr fp, gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP); break; } - tcg_gen_qemu_ld32u(tmp, addr, index); + tcg_gen_qemu_ld_i32(tmp, addr, index, MO_TEUL); tcg_gen_shri_i32(tmp, tmp, 16); tcg_gen_st16_i32(tmp, fp, offsetof(FPReg, l.upper)); tcg_gen_addi_i32(tmp, addr, 4); - tcg_gen_qemu_ld64(t64, tmp, index); + tcg_gen_qemu_ld_i64(t64, tmp, index, MO_TEUQ); tcg_gen_st_i64(t64, fp, offsetof(FPReg, l.lower)); break; case OS_PACKED: @@ -1024,24 +1004,18 @@ static void gen_store_fp(DisasContext *s, int opsize, TCGv addr, TCGv_ptr fp, tmp = tcg_temp_new(); switch (opsize) { case OS_BYTE: - gen_helper_reds32(tmp, cpu_env, fp); - tcg_gen_qemu_st8(tmp, addr, index); - break; case OS_WORD: - gen_helper_reds32(tmp, cpu_env, fp); - tcg_gen_qemu_st16(tmp, addr, index); - break; case OS_LONG: gen_helper_reds32(tmp, cpu_env, fp); - tcg_gen_qemu_st32(tmp, addr, index); + tcg_gen_qemu_st_tl(tmp, addr, index, opsize | MO_TE); break; case OS_SINGLE: gen_helper_redf32(tmp, cpu_env, fp); - tcg_gen_qemu_st32(tmp, addr, index); + tcg_gen_qemu_st_tl(tmp, addr, index, MO_TEUL); break; case OS_DOUBLE: gen_helper_redf64(t64, cpu_env, fp); - tcg_gen_qemu_st64(t64, addr, index); + tcg_gen_qemu_st_i64(t64, addr, index, MO_TEUQ); break; case OS_EXTENDED: if (m68k_feature(s->env, M68K_FEATURE_CF_FPU)) { @@ -1050,10 +1024,10 @@ static void gen_store_fp(DisasContext *s, int opsize, TCGv addr, TCGv_ptr fp, } tcg_gen_ld16u_i32(tmp, fp, offsetof(FPReg, l.upper)); tcg_gen_shli_i32(tmp, tmp, 16); - tcg_gen_qemu_st32(tmp, addr, index); + tcg_gen_qemu_st_i32(tmp, addr, index, MO_TEUL); tcg_gen_addi_i32(tmp, addr, 4); tcg_gen_ld_i64(t64, fp, offsetof(FPReg, l.lower)); - tcg_gen_qemu_st64(t64, tmp, index); + tcg_gen_qemu_st_i64(t64, tmp, index, MO_TEUQ); break; case OS_PACKED: /* @@ -2079,14 +2053,14 @@ DISAS_INSN(movep) if (insn & 0x80) { for ( ; i > 0 ; i--) { tcg_gen_shri_i32(dbuf, reg, (i - 1) * 8); - tcg_gen_qemu_st8(dbuf, abuf, IS_USER(s)); + tcg_gen_qemu_st_i32(dbuf, abuf, IS_USER(s), MO_UB); if (i > 1) { tcg_gen_addi_i32(abuf, abuf, 2); } } } else { for ( ; i > 0 ; i--) { - tcg_gen_qemu_ld8u(dbuf, abuf, IS_USER(s)); + tcg_gen_qemu_ld_tl(dbuf, abuf, IS_USER(s), MO_UB); tcg_gen_deposit_i32(reg, reg, dbuf, (i - 1) * 8, 8); if (i > 1) { tcg_gen_addi_i32(abuf, abuf, 2); @@ -4337,14 +4311,14 @@ static void m68k_copy_line(TCGv dst, TCGv src, int index) t1 = tcg_temp_new_i64(); tcg_gen_andi_i32(addr, src, ~15); - tcg_gen_qemu_ld64(t0, addr, index); + tcg_gen_qemu_ld_i64(t0, addr, index, MO_TEUQ); tcg_gen_addi_i32(addr, addr, 8); - tcg_gen_qemu_ld64(t1, addr, index); + tcg_gen_qemu_ld_i64(t1, addr, index, MO_TEUQ); tcg_gen_andi_i32(addr, dst, ~15); - tcg_gen_qemu_st64(t0, addr, index); + tcg_gen_qemu_st_i64(t0, addr, index, MO_TEUQ); tcg_gen_addi_i32(addr, addr, 8); - tcg_gen_qemu_st64(t1, addr, index); + tcg_gen_qemu_st_i64(t1, addr, index, MO_TEUQ); } DISAS_INSN(move16_reg) @@ -4767,7 +4741,7 @@ static void gen_qemu_store_fcr(DisasContext *s, TCGv addr, int reg) tmp = tcg_temp_new(); gen_load_fcr(s, tmp, reg); - tcg_gen_qemu_st32(tmp, addr, index); + tcg_gen_qemu_st_tl(tmp, addr, index, MO_TEUL); } static void gen_qemu_load_fcr(DisasContext *s, TCGv addr, int reg) @@ -4776,7 +4750,7 @@ static void gen_qemu_load_fcr(DisasContext *s, TCGv addr, int reg) TCGv tmp; tmp = tcg_temp_new(); - tcg_gen_qemu_ld32u(tmp, addr, index); + tcg_gen_qemu_ld_tl(tmp, addr, index, MO_TEUL); gen_store_fcr(s, tmp, reg); } From 6d0cad12594243375b255de76cc10f9b607cb2c9 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 May 2023 14:57:37 +0100 Subject: [PATCH 06/42] target/mips: Finish conversion to tcg_gen_qemu_{ld,st}_* Convert away from the old interface with the implicit MemOp argument. Signed-off-by: Richard Henderson Reviewed-by: Anton Johansson Message-Id: <20230502135741.1158035-6-richard.henderson@linaro.org> --- target/mips/tcg/nanomips_translate.c.inc | 2 +- target/mips/tcg/translate.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/target/mips/tcg/nanomips_translate.c.inc b/target/mips/tcg/nanomips_translate.c.inc index 9398e28000..97b9572caa 100644 --- a/target/mips/tcg/nanomips_translate.c.inc +++ b/target/mips/tcg/nanomips_translate.c.inc @@ -998,7 +998,7 @@ static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset, TCGv tmp2 = tcg_temp_new(); gen_base_offset_addr(ctx, taddr, base, offset); - tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx); + tcg_gen_qemu_ld_i64(tval, taddr, ctx->mem_idx, MO_TEUQ); if (cpu_is_bigendian(ctx)) { tcg_gen_extr_i64_tl(tmp2, tmp1, tval); } else { diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c index 999fbb7cc1..a6ca2e5a3b 100644 --- a/target/mips/tcg/translate.c +++ b/target/mips/tcg/translate.c @@ -1949,13 +1949,13 @@ FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd)) /* load/store instructions. */ #ifdef CONFIG_USER_ONLY -#define OP_LD_ATOMIC(insn, fname) \ +#define OP_LD_ATOMIC(insn, memop) \ static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \ DisasContext *ctx) \ { \ TCGv t0 = tcg_temp_new(); \ tcg_gen_mov_tl(t0, arg1); \ - tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \ + tcg_gen_qemu_ld_tl(ret, arg1, ctx->mem_idx, memop); \ tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \ tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \ } @@ -1967,9 +1967,9 @@ static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \ gen_helper_##insn(ret, cpu_env, arg1, tcg_constant_i32(mem_idx)); \ } #endif -OP_LD_ATOMIC(ll, ld32s); +OP_LD_ATOMIC(ll, MO_TESL); #if defined(TARGET_MIPS64) -OP_LD_ATOMIC(lld, ld64); +OP_LD_ATOMIC(lld, MO_TEUQ); #endif #undef OP_LD_ATOMIC From e87027d02215c858ecf94bcb037f1d0bca595f97 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 May 2023 14:57:38 +0100 Subject: [PATCH 07/42] target/s390x: Finish conversion to tcg_gen_qemu_{ld, st}_* Convert away from the old interface with the implicit MemOp argument. Signed-off-by: Richard Henderson Reviewed-by: David Hildenbrand Reviewed-by: Ilya Leoshkevich Message-Id: <20230502135741.1158035-7-richard.henderson@linaro.org> --- target/s390x/tcg/translate.c | 152 ++++++++++++++++------------------- 1 file changed, 71 insertions(+), 81 deletions(-) diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c index 46b874e94d..a05205beb1 100644 --- a/target/s390x/tcg/translate.c +++ b/target/s390x/tcg/translate.c @@ -1973,32 +1973,24 @@ static DisasJumpType op_clc(DisasContext *s, DisasOps *o) { int l = get_field(s, l1); TCGv_i32 vl; + MemOp mop; switch (l + 1) { case 1: - tcg_gen_qemu_ld8u(cc_src, o->addr1, get_mem_index(s)); - tcg_gen_qemu_ld8u(cc_dst, o->in2, get_mem_index(s)); - break; case 2: - tcg_gen_qemu_ld16u(cc_src, o->addr1, get_mem_index(s)); - tcg_gen_qemu_ld16u(cc_dst, o->in2, get_mem_index(s)); - break; case 4: - tcg_gen_qemu_ld32u(cc_src, o->addr1, get_mem_index(s)); - tcg_gen_qemu_ld32u(cc_dst, o->in2, get_mem_index(s)); - break; case 8: - tcg_gen_qemu_ld64(cc_src, o->addr1, get_mem_index(s)); - tcg_gen_qemu_ld64(cc_dst, o->in2, get_mem_index(s)); - break; + mop = ctz32(l + 1) | MO_TE; + tcg_gen_qemu_ld_tl(cc_src, o->addr1, get_mem_index(s), mop); + tcg_gen_qemu_ld_tl(cc_dst, o->in2, get_mem_index(s), mop); + gen_op_update2_cc_i64(s, CC_OP_LTUGTU_64, cc_src, cc_dst); + return DISAS_NEXT; default: vl = tcg_constant_i32(l); gen_helper_clc(cc_op, cpu_env, vl, o->addr1, o->in2); set_cc_static(s); return DISAS_NEXT; } - gen_op_update2_cc_i64(s, CC_OP_LTUGTU_64, cc_src, cc_dst); - return DISAS_NEXT; } static DisasJumpType op_clcl(DisasContext *s, DisasOps *o) @@ -2199,7 +2191,7 @@ static DisasJumpType op_cvd(DisasContext *s, DisasOps *o) TCGv_i32 t2 = tcg_temp_new_i32(); tcg_gen_extrl_i64_i32(t2, o->in1); gen_helper_cvd(t1, t2); - tcg_gen_qemu_st64(t1, o->in2, get_mem_index(s)); + tcg_gen_qemu_st_i64(t1, o->in2, get_mem_index(s), MO_TEUQ); return DISAS_NEXT; } @@ -2457,7 +2449,7 @@ static DisasJumpType op_icm(DisasContext *s, DisasOps *o) switch (m3) { case 0xf: /* Effectively a 32-bit load. */ - tcg_gen_qemu_ld32u(tmp, o->in2, get_mem_index(s)); + tcg_gen_qemu_ld_i64(tmp, o->in2, get_mem_index(s), MO_TEUL); len = 32; goto one_insert; @@ -2465,7 +2457,7 @@ static DisasJumpType op_icm(DisasContext *s, DisasOps *o) case 0x6: case 0x3: /* Effectively a 16-bit load. */ - tcg_gen_qemu_ld16u(tmp, o->in2, get_mem_index(s)); + tcg_gen_qemu_ld_i64(tmp, o->in2, get_mem_index(s), MO_TEUW); len = 16; goto one_insert; @@ -2474,7 +2466,7 @@ static DisasJumpType op_icm(DisasContext *s, DisasOps *o) case 0x2: case 0x1: /* Effectively an 8-bit load. */ - tcg_gen_qemu_ld8u(tmp, o->in2, get_mem_index(s)); + tcg_gen_qemu_ld_i64(tmp, o->in2, get_mem_index(s), MO_UB); len = 8; goto one_insert; @@ -2490,7 +2482,7 @@ static DisasJumpType op_icm(DisasContext *s, DisasOps *o) ccm = 0; while (m3) { if (m3 & 0x8) { - tcg_gen_qemu_ld8u(tmp, o->in2, get_mem_index(s)); + tcg_gen_qemu_ld_i64(tmp, o->in2, get_mem_index(s), MO_UB); tcg_gen_addi_i64(o->in2, o->in2, 1); tcg_gen_deposit_i64(o->out, o->out, tmp, pos, 8); ccm |= 0xffull << pos; @@ -2746,25 +2738,25 @@ static DisasJumpType op_llgt(DisasContext *s, DisasOps *o) static DisasJumpType op_ld8s(DisasContext *s, DisasOps *o) { - tcg_gen_qemu_ld8s(o->out, o->in2, get_mem_index(s)); + tcg_gen_qemu_ld_i64(o->out, o->in2, get_mem_index(s), MO_SB); return DISAS_NEXT; } static DisasJumpType op_ld8u(DisasContext *s, DisasOps *o) { - tcg_gen_qemu_ld8u(o->out, o->in2, get_mem_index(s)); + tcg_gen_qemu_ld_i64(o->out, o->in2, get_mem_index(s), MO_UB); return DISAS_NEXT; } static DisasJumpType op_ld16s(DisasContext *s, DisasOps *o) { - tcg_gen_qemu_ld16s(o->out, o->in2, get_mem_index(s)); + tcg_gen_qemu_ld_i64(o->out, o->in2, get_mem_index(s), MO_TESW); return DISAS_NEXT; } static DisasJumpType op_ld16u(DisasContext *s, DisasOps *o) { - tcg_gen_qemu_ld16u(o->out, o->in2, get_mem_index(s)); + tcg_gen_qemu_ld_i64(o->out, o->in2, get_mem_index(s), MO_TEUW); return DISAS_NEXT; } @@ -2803,7 +2795,7 @@ static DisasJumpType op_lat(DisasContext *s, DisasOps *o) static DisasJumpType op_lgat(DisasContext *s, DisasOps *o) { TCGLabel *lab = gen_new_label(); - tcg_gen_qemu_ld64(o->out, o->in2, get_mem_index(s)); + tcg_gen_qemu_ld_i64(o->out, o->in2, get_mem_index(s), MO_TEUQ); /* The value is stored even in case of trap. */ tcg_gen_brcondi_i64(TCG_COND_NE, o->out, 0, lab); gen_trap(s); @@ -2825,7 +2817,8 @@ static DisasJumpType op_lfhat(DisasContext *s, DisasOps *o) static DisasJumpType op_llgfat(DisasContext *s, DisasOps *o) { TCGLabel *lab = gen_new_label(); - tcg_gen_qemu_ld32u(o->out, o->in2, get_mem_index(s)); + + tcg_gen_qemu_ld_i64(o->out, o->in2, get_mem_index(s), MO_TEUL); /* The value is stored even in case of trap. */ tcg_gen_brcondi_i64(TCG_COND_NE, o->out, 0, lab); gen_trap(s); @@ -2942,7 +2935,7 @@ static DisasJumpType op_lpswe(DisasContext *s, DisasOps *o) tcg_gen_qemu_ld_i64(t1, o->in2, get_mem_index(s), MO_TEUQ | MO_ALIGN_8); tcg_gen_addi_i64(o->in2, o->in2, 8); - tcg_gen_qemu_ld64(t2, o->in2, get_mem_index(s)); + tcg_gen_qemu_ld_i64(t2, o->in2, get_mem_index(s), MO_TEUQ); gen_helper_load_psw(cpu_env, t1, t2); return DISAS_NORETURN; } @@ -2966,7 +2959,7 @@ static DisasJumpType op_lm32(DisasContext *s, DisasOps *o) /* Only one register to read. */ t1 = tcg_temp_new_i64(); if (unlikely(r1 == r3)) { - tcg_gen_qemu_ld32u(t1, o->in2, get_mem_index(s)); + tcg_gen_qemu_ld_i64(t1, o->in2, get_mem_index(s), MO_TEUL); store_reg32_i64(r1, t1); return DISAS_NEXT; } @@ -2974,9 +2967,9 @@ static DisasJumpType op_lm32(DisasContext *s, DisasOps *o) /* First load the values of the first and last registers to trigger possible page faults. */ t2 = tcg_temp_new_i64(); - tcg_gen_qemu_ld32u(t1, o->in2, get_mem_index(s)); + tcg_gen_qemu_ld_i64(t1, o->in2, get_mem_index(s), MO_TEUL); tcg_gen_addi_i64(t2, o->in2, 4 * ((r3 - r1) & 15)); - tcg_gen_qemu_ld32u(t2, t2, get_mem_index(s)); + tcg_gen_qemu_ld_i64(t2, t2, get_mem_index(s), MO_TEUL); store_reg32_i64(r1, t1); store_reg32_i64(r3, t2); @@ -2991,7 +2984,7 @@ static DisasJumpType op_lm32(DisasContext *s, DisasOps *o) while (r1 != r3) { r1 = (r1 + 1) & 15; tcg_gen_add_i64(o->in2, o->in2, t2); - tcg_gen_qemu_ld32u(t1, o->in2, get_mem_index(s)); + tcg_gen_qemu_ld_i64(t1, o->in2, get_mem_index(s), MO_TEUL); store_reg32_i64(r1, t1); } return DISAS_NEXT; @@ -3006,7 +2999,7 @@ static DisasJumpType op_lmh(DisasContext *s, DisasOps *o) /* Only one register to read. */ t1 = tcg_temp_new_i64(); if (unlikely(r1 == r3)) { - tcg_gen_qemu_ld32u(t1, o->in2, get_mem_index(s)); + tcg_gen_qemu_ld_i64(t1, o->in2, get_mem_index(s), MO_TEUL); store_reg32h_i64(r1, t1); return DISAS_NEXT; } @@ -3014,9 +3007,9 @@ static DisasJumpType op_lmh(DisasContext *s, DisasOps *o) /* First load the values of the first and last registers to trigger possible page faults. */ t2 = tcg_temp_new_i64(); - tcg_gen_qemu_ld32u(t1, o->in2, get_mem_index(s)); + tcg_gen_qemu_ld_i64(t1, o->in2, get_mem_index(s), MO_TEUL); tcg_gen_addi_i64(t2, o->in2, 4 * ((r3 - r1) & 15)); - tcg_gen_qemu_ld32u(t2, t2, get_mem_index(s)); + tcg_gen_qemu_ld_i64(t2, t2, get_mem_index(s), MO_TEUL); store_reg32h_i64(r1, t1); store_reg32h_i64(r3, t2); @@ -3031,7 +3024,7 @@ static DisasJumpType op_lmh(DisasContext *s, DisasOps *o) while (r1 != r3) { r1 = (r1 + 1) & 15; tcg_gen_add_i64(o->in2, o->in2, t2); - tcg_gen_qemu_ld32u(t1, o->in2, get_mem_index(s)); + tcg_gen_qemu_ld_i64(t1, o->in2, get_mem_index(s), MO_TEUL); store_reg32h_i64(r1, t1); } return DISAS_NEXT; @@ -3045,7 +3038,7 @@ static DisasJumpType op_lm64(DisasContext *s, DisasOps *o) /* Only one register to read. */ if (unlikely(r1 == r3)) { - tcg_gen_qemu_ld64(regs[r1], o->in2, get_mem_index(s)); + tcg_gen_qemu_ld_i64(regs[r1], o->in2, get_mem_index(s), MO_TEUQ); return DISAS_NEXT; } @@ -3053,9 +3046,9 @@ static DisasJumpType op_lm64(DisasContext *s, DisasOps *o) possible page faults. */ t1 = tcg_temp_new_i64(); t2 = tcg_temp_new_i64(); - tcg_gen_qemu_ld64(t1, o->in2, get_mem_index(s)); + tcg_gen_qemu_ld_i64(t1, o->in2, get_mem_index(s), MO_TEUQ); tcg_gen_addi_i64(t2, o->in2, 8 * ((r3 - r1) & 15)); - tcg_gen_qemu_ld64(regs[r3], t2, get_mem_index(s)); + tcg_gen_qemu_ld_i64(regs[r3], t2, get_mem_index(s), MO_TEUQ); tcg_gen_mov_i64(regs[r1], t1); /* Only two registers to read. */ @@ -3069,7 +3062,7 @@ static DisasJumpType op_lm64(DisasContext *s, DisasOps *o) while (r1 != r3) { r1 = (r1 + 1) & 15; tcg_gen_add_i64(o->in2, o->in2, t1); - tcg_gen_qemu_ld64(regs[r1], o->in2, get_mem_index(s)); + tcg_gen_qemu_ld_i64(regs[r1], o->in2, get_mem_index(s), MO_TEUQ); } return DISAS_NEXT; } @@ -3923,15 +3916,15 @@ static DisasJumpType op_soc(DisasContext *s, DisasOps *o) a = get_address(s, 0, get_field(s, b2), get_field(s, d2)); switch (s->insn->data) { case 1: /* STOCG */ - tcg_gen_qemu_st64(regs[r1], a, get_mem_index(s)); + tcg_gen_qemu_st_i64(regs[r1], a, get_mem_index(s), MO_TEUQ); break; case 0: /* STOC */ - tcg_gen_qemu_st32(regs[r1], a, get_mem_index(s)); + tcg_gen_qemu_st_i64(regs[r1], a, get_mem_index(s), MO_TEUL); break; case 2: /* STOCFH */ h = tcg_temp_new_i64(); tcg_gen_shri_i64(h, regs[r1], 32); - tcg_gen_qemu_st32(h, a, get_mem_index(s)); + tcg_gen_qemu_st_i64(h, a, get_mem_index(s), MO_TEUL); break; default: g_assert_not_reached(); @@ -4050,7 +4043,7 @@ static DisasJumpType op_ectg(DisasContext *s, DisasOps *o) gen_addi_and_wrap_i64(s, o->addr1, regs[r3], 0); /* load the third operand into r3 before modifying anything */ - tcg_gen_qemu_ld64(regs[r3], o->addr1, get_mem_index(s)); + tcg_gen_qemu_ld_i64(regs[r3], o->addr1, get_mem_index(s), MO_TEUQ); /* subtract CPU timer from first operand and store in GR0 */ gen_helper_stpt(tmp, cpu_env); @@ -4128,9 +4121,9 @@ static DisasJumpType op_stcke(DisasContext *s, DisasOps *o) tcg_gen_shri_i64(c1, c1, 8); tcg_gen_ori_i64(c2, c2, 0x10000); tcg_gen_or_i64(c2, c2, todpr); - tcg_gen_qemu_st64(c1, o->in2, get_mem_index(s)); + tcg_gen_qemu_st_i64(c1, o->in2, get_mem_index(s), MO_TEUQ); tcg_gen_addi_i64(o->in2, o->in2, 8); - tcg_gen_qemu_st64(c2, o->in2, get_mem_index(s)); + tcg_gen_qemu_st_i64(c2, o->in2, get_mem_index(s), MO_TEUQ); /* ??? We don't implement clock states. */ gen_op_movi_cc(s, 0); return DISAS_NEXT; @@ -4343,7 +4336,7 @@ static DisasJumpType op_stnosm(DisasContext *s, DisasOps *o) restart, we'll have the wrong SYSTEM MASK in place. */ t = tcg_temp_new_i64(); tcg_gen_shri_i64(t, psw_mask, 56); - tcg_gen_qemu_st8(t, o->addr1, get_mem_index(s)); + tcg_gen_qemu_st_i64(t, o->addr1, get_mem_index(s), MO_UB); if (s->fields.op == 0xac) { tcg_gen_andi_i64(psw_mask, psw_mask, @@ -4380,13 +4373,13 @@ static DisasJumpType op_stfle(DisasContext *s, DisasOps *o) static DisasJumpType op_st8(DisasContext *s, DisasOps *o) { - tcg_gen_qemu_st8(o->in1, o->in2, get_mem_index(s)); + tcg_gen_qemu_st_i64(o->in1, o->in2, get_mem_index(s), MO_UB); return DISAS_NEXT; } static DisasJumpType op_st16(DisasContext *s, DisasOps *o) { - tcg_gen_qemu_st16(o->in1, o->in2, get_mem_index(s)); + tcg_gen_qemu_st_i64(o->in1, o->in2, get_mem_index(s), MO_TEUW); return DISAS_NEXT; } @@ -4424,7 +4417,7 @@ static DisasJumpType op_stcm(DisasContext *s, DisasOps *o) case 0xf: /* Effectively a 32-bit store. */ tcg_gen_shri_i64(tmp, o->in1, pos); - tcg_gen_qemu_st32(tmp, o->in2, get_mem_index(s)); + tcg_gen_qemu_st_i64(tmp, o->in2, get_mem_index(s), MO_TEUL); break; case 0xc: @@ -4432,7 +4425,7 @@ static DisasJumpType op_stcm(DisasContext *s, DisasOps *o) case 0x3: /* Effectively a 16-bit store. */ tcg_gen_shri_i64(tmp, o->in1, pos); - tcg_gen_qemu_st16(tmp, o->in2, get_mem_index(s)); + tcg_gen_qemu_st_i64(tmp, o->in2, get_mem_index(s), MO_TEUW); break; case 0x8: @@ -4441,7 +4434,7 @@ static DisasJumpType op_stcm(DisasContext *s, DisasOps *o) case 0x1: /* Effectively an 8-bit store. */ tcg_gen_shri_i64(tmp, o->in1, pos); - tcg_gen_qemu_st8(tmp, o->in2, get_mem_index(s)); + tcg_gen_qemu_st_i64(tmp, o->in2, get_mem_index(s), MO_UB); break; default: @@ -4450,7 +4443,7 @@ static DisasJumpType op_stcm(DisasContext *s, DisasOps *o) while (m3) { if (m3 & 0x8) { tcg_gen_shri_i64(tmp, o->in1, pos); - tcg_gen_qemu_st8(tmp, o->in2, get_mem_index(s)); + tcg_gen_qemu_st_i64(tmp, o->in2, get_mem_index(s), MO_UB); tcg_gen_addi_i64(o->in2, o->in2, 1); } m3 = (m3 << 1) & 0xf; @@ -4469,11 +4462,8 @@ static DisasJumpType op_stm(DisasContext *s, DisasOps *o) TCGv_i64 tsize = tcg_constant_i64(size); while (1) { - if (size == 8) { - tcg_gen_qemu_st64(regs[r1], o->in2, get_mem_index(s)); - } else { - tcg_gen_qemu_st32(regs[r1], o->in2, get_mem_index(s)); - } + tcg_gen_qemu_st_i64(regs[r1], o->in2, get_mem_index(s), + size == 8 ? MO_TEUQ : MO_TEUL); if (r1 == r3) { break; } @@ -4494,7 +4484,7 @@ static DisasJumpType op_stmh(DisasContext *s, DisasOps *o) while (1) { tcg_gen_shl_i64(t, regs[r1], t32); - tcg_gen_qemu_st32(t, o->in2, get_mem_index(s)); + tcg_gen_qemu_st_i64(t, o->in2, get_mem_index(s), MO_TEUL); if (r1 == r3) { break; } @@ -4804,28 +4794,28 @@ static DisasJumpType op_xc(DisasContext *s, DisasOps *o) l++; while (l >= 8) { - tcg_gen_qemu_st64(o->in2, o->addr1, get_mem_index(s)); + tcg_gen_qemu_st_i64(o->in2, o->addr1, get_mem_index(s), MO_UQ); l -= 8; if (l > 0) { tcg_gen_addi_i64(o->addr1, o->addr1, 8); } } if (l >= 4) { - tcg_gen_qemu_st32(o->in2, o->addr1, get_mem_index(s)); + tcg_gen_qemu_st_i64(o->in2, o->addr1, get_mem_index(s), MO_UL); l -= 4; if (l > 0) { tcg_gen_addi_i64(o->addr1, o->addr1, 4); } } if (l >= 2) { - tcg_gen_qemu_st16(o->in2, o->addr1, get_mem_index(s)); + tcg_gen_qemu_st_i64(o->in2, o->addr1, get_mem_index(s), MO_UW); l -= 2; if (l > 0) { tcg_gen_addi_i64(o->addr1, o->addr1, 2); } } if (l) { - tcg_gen_qemu_st8(o->in2, o->addr1, get_mem_index(s)); + tcg_gen_qemu_st_i64(o->in2, o->addr1, get_mem_index(s), MO_UB); } gen_op_movi_cc(s, 0); return DISAS_NEXT; @@ -5314,13 +5304,13 @@ static void wout_cond_e1e2(DisasContext *s, DisasOps *o) static void wout_m1_8(DisasContext *s, DisasOps *o) { - tcg_gen_qemu_st8(o->out, o->addr1, get_mem_index(s)); + tcg_gen_qemu_st_i64(o->out, o->addr1, get_mem_index(s), MO_UB); } #define SPEC_wout_m1_8 0 static void wout_m1_16(DisasContext *s, DisasOps *o) { - tcg_gen_qemu_st16(o->out, o->addr1, get_mem_index(s)); + tcg_gen_qemu_st_i64(o->out, o->addr1, get_mem_index(s), MO_TEUW); } #define SPEC_wout_m1_16 0 @@ -5334,7 +5324,7 @@ static void wout_m1_16a(DisasContext *s, DisasOps *o) static void wout_m1_32(DisasContext *s, DisasOps *o) { - tcg_gen_qemu_st32(o->out, o->addr1, get_mem_index(s)); + tcg_gen_qemu_st_i64(o->out, o->addr1, get_mem_index(s), MO_TEUL); } #define SPEC_wout_m1_32 0 @@ -5348,7 +5338,7 @@ static void wout_m1_32a(DisasContext *s, DisasOps *o) static void wout_m1_64(DisasContext *s, DisasOps *o) { - tcg_gen_qemu_st64(o->out, o->addr1, get_mem_index(s)); + tcg_gen_qemu_st_i64(o->out, o->addr1, get_mem_index(s), MO_TEUQ); } #define SPEC_wout_m1_64 0 @@ -5362,7 +5352,7 @@ static void wout_m1_64a(DisasContext *s, DisasOps *o) static void wout_m2_32(DisasContext *s, DisasOps *o) { - tcg_gen_qemu_st32(o->out, o->in2, get_mem_index(s)); + tcg_gen_qemu_st_i64(o->out, o->in2, get_mem_index(s), MO_TEUL); } #define SPEC_wout_m2_32 0 @@ -5557,7 +5547,7 @@ static void in1_m1_8u(DisasContext *s, DisasOps *o) { in1_la1(s, o); o->in1 = tcg_temp_new_i64(); - tcg_gen_qemu_ld8u(o->in1, o->addr1, get_mem_index(s)); + tcg_gen_qemu_ld_i64(o->in1, o->addr1, get_mem_index(s), MO_UB); } #define SPEC_in1_m1_8u 0 @@ -5565,7 +5555,7 @@ static void in1_m1_16s(DisasContext *s, DisasOps *o) { in1_la1(s, o); o->in1 = tcg_temp_new_i64(); - tcg_gen_qemu_ld16s(o->in1, o->addr1, get_mem_index(s)); + tcg_gen_qemu_ld_i64(o->in1, o->addr1, get_mem_index(s), MO_TESW); } #define SPEC_in1_m1_16s 0 @@ -5573,7 +5563,7 @@ static void in1_m1_16u(DisasContext *s, DisasOps *o) { in1_la1(s, o); o->in1 = tcg_temp_new_i64(); - tcg_gen_qemu_ld16u(o->in1, o->addr1, get_mem_index(s)); + tcg_gen_qemu_ld_i64(o->in1, o->addr1, get_mem_index(s), MO_TEUW); } #define SPEC_in1_m1_16u 0 @@ -5581,7 +5571,7 @@ static void in1_m1_32s(DisasContext *s, DisasOps *o) { in1_la1(s, o); o->in1 = tcg_temp_new_i64(); - tcg_gen_qemu_ld32s(o->in1, o->addr1, get_mem_index(s)); + tcg_gen_qemu_ld_i64(o->in1, o->addr1, get_mem_index(s), MO_TESL); } #define SPEC_in1_m1_32s 0 @@ -5589,7 +5579,7 @@ static void in1_m1_32u(DisasContext *s, DisasOps *o) { in1_la1(s, o); o->in1 = tcg_temp_new_i64(); - tcg_gen_qemu_ld32u(o->in1, o->addr1, get_mem_index(s)); + tcg_gen_qemu_ld_i64(o->in1, o->addr1, get_mem_index(s), MO_TEUL); } #define SPEC_in1_m1_32u 0 @@ -5597,7 +5587,7 @@ static void in1_m1_64(DisasContext *s, DisasOps *o) { in1_la1(s, o); o->in1 = tcg_temp_new_i64(); - tcg_gen_qemu_ld64(o->in1, o->addr1, get_mem_index(s)); + tcg_gen_qemu_ld_i64(o->in1, o->addr1, get_mem_index(s), MO_TEUQ); } #define SPEC_in1_m1_64 0 @@ -5811,35 +5801,35 @@ static void in2_sh(DisasContext *s, DisasOps *o) static void in2_m2_8u(DisasContext *s, DisasOps *o) { in2_a2(s, o); - tcg_gen_qemu_ld8u(o->in2, o->in2, get_mem_index(s)); + tcg_gen_qemu_ld_i64(o->in2, o->in2, get_mem_index(s), MO_UB); } #define SPEC_in2_m2_8u 0 static void in2_m2_16s(DisasContext *s, DisasOps *o) { in2_a2(s, o); - tcg_gen_qemu_ld16s(o->in2, o->in2, get_mem_index(s)); + tcg_gen_qemu_ld_i64(o->in2, o->in2, get_mem_index(s), MO_TESW); } #define SPEC_in2_m2_16s 0 static void in2_m2_16u(DisasContext *s, DisasOps *o) { in2_a2(s, o); - tcg_gen_qemu_ld16u(o->in2, o->in2, get_mem_index(s)); + tcg_gen_qemu_ld_i64(o->in2, o->in2, get_mem_index(s), MO_TEUW); } #define SPEC_in2_m2_16u 0 static void in2_m2_32s(DisasContext *s, DisasOps *o) { in2_a2(s, o); - tcg_gen_qemu_ld32s(o->in2, o->in2, get_mem_index(s)); + tcg_gen_qemu_ld_i64(o->in2, o->in2, get_mem_index(s), MO_TESL); } #define SPEC_in2_m2_32s 0 static void in2_m2_32u(DisasContext *s, DisasOps *o) { in2_a2(s, o); - tcg_gen_qemu_ld32u(o->in2, o->in2, get_mem_index(s)); + tcg_gen_qemu_ld_i64(o->in2, o->in2, get_mem_index(s), MO_TEUL); } #define SPEC_in2_m2_32u 0 @@ -5855,14 +5845,14 @@ static void in2_m2_32ua(DisasContext *s, DisasOps *o) static void in2_m2_64(DisasContext *s, DisasOps *o) { in2_a2(s, o); - tcg_gen_qemu_ld64(o->in2, o->in2, get_mem_index(s)); + tcg_gen_qemu_ld_i64(o->in2, o->in2, get_mem_index(s), MO_TEUQ); } #define SPEC_in2_m2_64 0 static void in2_m2_64w(DisasContext *s, DisasOps *o) { in2_a2(s, o); - tcg_gen_qemu_ld64(o->in2, o->in2, get_mem_index(s)); + tcg_gen_qemu_ld_i64(o->in2, o->in2, get_mem_index(s), MO_TEUQ); gen_addi_and_wrap_i64(s, o->in2, o->in2, 0); } #define SPEC_in2_m2_64w 0 @@ -5879,14 +5869,14 @@ static void in2_m2_64a(DisasContext *s, DisasOps *o) static void in2_mri2_16s(DisasContext *s, DisasOps *o) { o->in2 = tcg_temp_new_i64(); - tcg_gen_qemu_ld16s(o->in2, gen_ri2(s), get_mem_index(s)); + tcg_gen_qemu_ld_i64(o->in2, gen_ri2(s), get_mem_index(s), MO_TESW); } #define SPEC_in2_mri2_16s 0 static void in2_mri2_16u(DisasContext *s, DisasOps *o) { o->in2 = tcg_temp_new_i64(); - tcg_gen_qemu_ld16u(o->in2, gen_ri2(s), get_mem_index(s)); + tcg_gen_qemu_ld_i64(o->in2, gen_ri2(s), get_mem_index(s), MO_TEUW); } #define SPEC_in2_mri2_16u 0 From 08149118839735f8559e63a69ec41434d919e11b Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 May 2023 14:57:39 +0100 Subject: [PATCH 08/42] target/sparc: Finish conversion to tcg_gen_qemu_{ld, st}_* Convert away from the old interface with the implicit MemOp argument. Signed-off-by: Richard Henderson Reviewed-by: Anton Johansson Message-Id: <20230502135741.1158035-8-richard.henderson@linaro.org> --- target/sparc/translate.c | 43 ++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/target/sparc/translate.c b/target/sparc/translate.c index 137bdc5159..bc71e44e66 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -5179,15 +5179,18 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) switch (xop) { case 0x0: /* ld, V9 lduw, load unsigned word */ gen_address_mask(dc, cpu_addr); - tcg_gen_qemu_ld32u(cpu_val, cpu_addr, dc->mem_idx); + tcg_gen_qemu_ld_tl(cpu_val, cpu_addr, + dc->mem_idx, MO_TEUL); break; case 0x1: /* ldub, load unsigned byte */ gen_address_mask(dc, cpu_addr); - tcg_gen_qemu_ld8u(cpu_val, cpu_addr, dc->mem_idx); + tcg_gen_qemu_ld_tl(cpu_val, cpu_addr, + dc->mem_idx, MO_UB); break; case 0x2: /* lduh, load unsigned halfword */ gen_address_mask(dc, cpu_addr); - tcg_gen_qemu_ld16u(cpu_val, cpu_addr, dc->mem_idx); + tcg_gen_qemu_ld_tl(cpu_val, cpu_addr, + dc->mem_idx, MO_TEUW); break; case 0x3: /* ldd, load double word */ if (rd & 1) @@ -5197,7 +5200,8 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) gen_address_mask(dc, cpu_addr); t64 = tcg_temp_new_i64(); - tcg_gen_qemu_ld64(t64, cpu_addr, dc->mem_idx); + tcg_gen_qemu_ld_i64(t64, cpu_addr, + dc->mem_idx, MO_TEUQ); tcg_gen_trunc_i64_tl(cpu_val, t64); tcg_gen_ext32u_tl(cpu_val, cpu_val); gen_store_gpr(dc, rd + 1, cpu_val); @@ -5208,11 +5212,12 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) break; case 0x9: /* ldsb, load signed byte */ gen_address_mask(dc, cpu_addr); - tcg_gen_qemu_ld8s(cpu_val, cpu_addr, dc->mem_idx); + tcg_gen_qemu_ld_tl(cpu_val, cpu_addr, dc->mem_idx, MO_SB); break; case 0xa: /* ldsh, load signed halfword */ gen_address_mask(dc, cpu_addr); - tcg_gen_qemu_ld16s(cpu_val, cpu_addr, dc->mem_idx); + tcg_gen_qemu_ld_tl(cpu_val, cpu_addr, + dc->mem_idx, MO_TESW); break; case 0xd: /* ldstub */ gen_ldstub(dc, cpu_val, cpu_addr, dc->mem_idx); @@ -5266,11 +5271,13 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) #ifdef TARGET_SPARC64 case 0x08: /* V9 ldsw */ gen_address_mask(dc, cpu_addr); - tcg_gen_qemu_ld32s(cpu_val, cpu_addr, dc->mem_idx); + tcg_gen_qemu_ld_tl(cpu_val, cpu_addr, + dc->mem_idx, MO_TESL); break; case 0x0b: /* V9 ldx */ gen_address_mask(dc, cpu_addr); - tcg_gen_qemu_ld64(cpu_val, cpu_addr, dc->mem_idx); + tcg_gen_qemu_ld_tl(cpu_val, cpu_addr, + dc->mem_idx, MO_TEUQ); break; case 0x18: /* V9 ldswa */ gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_TESL); @@ -5369,15 +5376,17 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) switch (xop) { case 0x4: /* st, store word */ gen_address_mask(dc, cpu_addr); - tcg_gen_qemu_st32(cpu_val, cpu_addr, dc->mem_idx); + tcg_gen_qemu_st_tl(cpu_val, cpu_addr, + dc->mem_idx, MO_TEUL); break; case 0x5: /* stb, store byte */ gen_address_mask(dc, cpu_addr); - tcg_gen_qemu_st8(cpu_val, cpu_addr, dc->mem_idx); + tcg_gen_qemu_st_tl(cpu_val, cpu_addr, dc->mem_idx, MO_UB); break; case 0x6: /* sth, store halfword */ gen_address_mask(dc, cpu_addr); - tcg_gen_qemu_st16(cpu_val, cpu_addr, dc->mem_idx); + tcg_gen_qemu_st_tl(cpu_val, cpu_addr, + dc->mem_idx, MO_TEUW); break; case 0x7: /* std, store double word */ if (rd & 1) @@ -5390,7 +5399,8 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) lo = gen_load_gpr(dc, rd + 1); t64 = tcg_temp_new_i64(); tcg_gen_concat_tl_i64(t64, lo, cpu_val); - tcg_gen_qemu_st64(t64, cpu_addr, dc->mem_idx); + tcg_gen_qemu_st_i64(t64, cpu_addr, + dc->mem_idx, MO_TEUQ); } break; #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) @@ -5413,7 +5423,8 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) #ifdef TARGET_SPARC64 case 0x0e: /* V9 stx */ gen_address_mask(dc, cpu_addr); - tcg_gen_qemu_st64(cpu_val, cpu_addr, dc->mem_idx); + tcg_gen_qemu_st_tl(cpu_val, cpu_addr, + dc->mem_idx, MO_TEUQ); break; case 0x1e: /* V9 stxa */ gen_st_asi(dc, cpu_val, cpu_addr, insn, MO_TEUQ); @@ -5438,11 +5449,13 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) #ifdef TARGET_SPARC64 gen_address_mask(dc, cpu_addr); if (rd == 1) { - tcg_gen_qemu_st64(cpu_fsr, cpu_addr, dc->mem_idx); + tcg_gen_qemu_st_tl(cpu_fsr, cpu_addr, + dc->mem_idx, MO_TEUQ); break; } #endif - tcg_gen_qemu_st32(cpu_fsr, cpu_addr, dc->mem_idx); + tcg_gen_qemu_st_tl(cpu_fsr, cpu_addr, + dc->mem_idx, MO_TEUL); } break; case 0x26: From f0aca2a912a201823653ee8536b537017f1e98c2 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 May 2023 14:57:40 +0100 Subject: [PATCH 09/42] target/xtensa: Finish conversion to tcg_gen_qemu_{ld, st}_* Convert away from the old interface with the implicit MemOp argument. Signed-off-by: Richard Henderson Reviewed-by: Max Filippov Message-Id: <20230502135741.1158035-9-richard.henderson@linaro.org> --- target/xtensa/translate.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c index 0cf3075649..728aeebebf 100644 --- a/target/xtensa/translate.c +++ b/target/xtensa/translate.c @@ -1549,7 +1549,7 @@ static void translate_dcache(DisasContext *dc, const OpcodeArg arg[], TCGv_i32 res = tcg_temp_new_i32(); tcg_gen_addi_i32(addr, arg[0].in, arg[1].imm); - tcg_gen_qemu_ld8u(res, addr, dc->cring); + tcg_gen_qemu_ld_i32(res, addr, dc->cring, MO_UB); } static void translate_depbits(DisasContext *dc, const OpcodeArg arg[], @@ -1726,7 +1726,7 @@ static void translate_l32r(DisasContext *dc, const OpcodeArg arg[], } else { tmp = tcg_constant_i32(arg[1].imm); } - tcg_gen_qemu_ld32u(arg[0].out, tmp, dc->cring); + tcg_gen_qemu_ld_i32(arg[0].out, tmp, dc->cring, MO_TEUL); } static void translate_loop(DisasContext *dc, const OpcodeArg arg[], From 5fa7c0882d209124f5aa49dd0be5909dc0911b0b Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 May 2023 14:57:41 +0100 Subject: [PATCH 10/42] tcg: Remove compatability helpers for qemu ld/st Remove the old interfaces with the implicit MemOp argument. Signed-off-by: Richard Henderson Acked-by: David Hildenbrand Message-Id: <20230502135741.1158035-10-richard.henderson@linaro.org> --- include/tcg/tcg-op.h | 55 -------------------------------------------- 1 file changed, 55 deletions(-) diff --git a/include/tcg/tcg-op.h b/include/tcg/tcg-op.h index dff17c7072..4401fa493c 100644 --- a/include/tcg/tcg-op.h +++ b/include/tcg/tcg-op.h @@ -841,61 +841,6 @@ void tcg_gen_qemu_st_i64(TCGv_i64, TCGv, TCGArg, MemOp); void tcg_gen_qemu_ld_i128(TCGv_i128, TCGv, TCGArg, MemOp); void tcg_gen_qemu_st_i128(TCGv_i128, TCGv, TCGArg, MemOp); -static inline void tcg_gen_qemu_ld8u(TCGv ret, TCGv addr, int mem_index) -{ - tcg_gen_qemu_ld_tl(ret, addr, mem_index, MO_UB); -} - -static inline void tcg_gen_qemu_ld8s(TCGv ret, TCGv addr, int mem_index) -{ - tcg_gen_qemu_ld_tl(ret, addr, mem_index, MO_SB); -} - -static inline void tcg_gen_qemu_ld16u(TCGv ret, TCGv addr, int mem_index) -{ - tcg_gen_qemu_ld_tl(ret, addr, mem_index, MO_TEUW); -} - -static inline void tcg_gen_qemu_ld16s(TCGv ret, TCGv addr, int mem_index) -{ - tcg_gen_qemu_ld_tl(ret, addr, mem_index, MO_TESW); -} - -static inline void tcg_gen_qemu_ld32u(TCGv ret, TCGv addr, int mem_index) -{ - tcg_gen_qemu_ld_tl(ret, addr, mem_index, MO_TEUL); -} - -static inline void tcg_gen_qemu_ld32s(TCGv ret, TCGv addr, int mem_index) -{ - tcg_gen_qemu_ld_tl(ret, addr, mem_index, MO_TESL); -} - -static inline void tcg_gen_qemu_ld64(TCGv_i64 ret, TCGv addr, int mem_index) -{ - tcg_gen_qemu_ld_i64(ret, addr, mem_index, MO_TEUQ); -} - -static inline void tcg_gen_qemu_st8(TCGv arg, TCGv addr, int mem_index) -{ - tcg_gen_qemu_st_tl(arg, addr, mem_index, MO_UB); -} - -static inline void tcg_gen_qemu_st16(TCGv arg, TCGv addr, int mem_index) -{ - tcg_gen_qemu_st_tl(arg, addr, mem_index, MO_TEUW); -} - -static inline void tcg_gen_qemu_st32(TCGv arg, TCGv addr, int mem_index) -{ - tcg_gen_qemu_st_tl(arg, addr, mem_index, MO_TEUL); -} - -static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index) -{ - tcg_gen_qemu_st_i64(arg, addr, mem_index, MO_TEUQ); -} - void tcg_gen_atomic_cmpxchg_i32(TCGv_i32, TCGv, TCGv_i32, TCGv_i32, TCGArg, MemOp); void tcg_gen_atomic_cmpxchg_i64(TCGv_i64, TCGv, TCGv_i64, TCGv_i64, From 6ffaac9ca01094341ce64526411b8065df9ac39f Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 May 2023 15:31:25 +0100 Subject: [PATCH 11/42] target/alpha: Use MO_ALIGN for system UNALIGN() Signed-off-by: Richard Henderson --- target/alpha/translate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/alpha/translate.c b/target/alpha/translate.c index 9d25e21164..ffbac1c114 100644 --- a/target/alpha/translate.c +++ b/target/alpha/translate.c @@ -72,7 +72,7 @@ struct DisasContext { #ifdef CONFIG_USER_ONLY #define UNALIGN(C) (C)->unalign #else -#define UNALIGN(C) 0 +#define UNALIGN(C) MO_ALIGN #endif /* Target-specific return values from translate_one, indicating the From 33948b68a7ca99f05f88f4aac5d5019a11853662 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 May 2023 15:36:47 +0100 Subject: [PATCH 12/42] target/alpha: Use MO_ALIGN where required Mark all memory operations that are not already marked with UNALIGN. Signed-off-by: Richard Henderson --- target/alpha/translate.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/target/alpha/translate.c b/target/alpha/translate.c index ffbac1c114..be8adb2526 100644 --- a/target/alpha/translate.c +++ b/target/alpha/translate.c @@ -2399,21 +2399,21 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn) switch ((insn >> 12) & 0xF) { case 0x0: /* Longword physical access (hw_ldl/p) */ - tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LESL); + tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LESL | MO_ALIGN); break; case 0x1: /* Quadword physical access (hw_ldq/p) */ - tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LEUQ); + tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LEUQ | MO_ALIGN); break; case 0x2: /* Longword physical access with lock (hw_ldl_l/p) */ - tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LESL); + tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LESL | MO_ALIGN); tcg_gen_mov_i64(cpu_lock_addr, addr); tcg_gen_mov_i64(cpu_lock_value, va); break; case 0x3: /* Quadword physical access with lock (hw_ldq_l/p) */ - tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LEUQ); + tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LEUQ | MO_ALIGN); tcg_gen_mov_i64(cpu_lock_addr, addr); tcg_gen_mov_i64(cpu_lock_value, va); break; @@ -2438,11 +2438,13 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn) goto invalid_opc; case 0xA: /* Longword virtual access with protection check (hw_ldl/w) */ - tcg_gen_qemu_ld_i64(va, addr, MMU_KERNEL_IDX, MO_LESL); + tcg_gen_qemu_ld_i64(va, addr, MMU_KERNEL_IDX, + MO_LESL | MO_ALIGN); break; case 0xB: /* Quadword virtual access with protection check (hw_ldq/w) */ - tcg_gen_qemu_ld_i64(va, addr, MMU_KERNEL_IDX, MO_LEUQ); + tcg_gen_qemu_ld_i64(va, addr, MMU_KERNEL_IDX, + MO_LEUQ | MO_ALIGN); break; case 0xC: /* Longword virtual access with alt access mode (hw_ldl/a)*/ @@ -2453,12 +2455,14 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn) case 0xE: /* Longword virtual access with alternate access mode and protection checks (hw_ldl/wa) */ - tcg_gen_qemu_ld_i64(va, addr, MMU_USER_IDX, MO_LESL); + tcg_gen_qemu_ld_i64(va, addr, MMU_USER_IDX, + MO_LESL | MO_ALIGN); break; case 0xF: /* Quadword virtual access with alternate access mode and protection checks (hw_ldq/wa) */ - tcg_gen_qemu_ld_i64(va, addr, MMU_USER_IDX, MO_LEUQ); + tcg_gen_qemu_ld_i64(va, addr, MMU_USER_IDX, + MO_LEUQ | MO_ALIGN); break; } break; @@ -2659,7 +2663,7 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn) vb = load_gpr(ctx, rb); tmp = tcg_temp_new(); tcg_gen_addi_i64(tmp, vb, disp12); - tcg_gen_qemu_st_i64(va, tmp, MMU_PHYS_IDX, MO_LESL); + tcg_gen_qemu_st_i64(va, tmp, MMU_PHYS_IDX, MO_LESL | MO_ALIGN); break; case 0x1: /* Quadword physical access */ @@ -2667,17 +2671,17 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn) vb = load_gpr(ctx, rb); tmp = tcg_temp_new(); tcg_gen_addi_i64(tmp, vb, disp12); - tcg_gen_qemu_st_i64(va, tmp, MMU_PHYS_IDX, MO_LEUQ); + tcg_gen_qemu_st_i64(va, tmp, MMU_PHYS_IDX, MO_LEUQ | MO_ALIGN); break; case 0x2: /* Longword physical access with lock */ ret = gen_store_conditional(ctx, ra, rb, disp12, - MMU_PHYS_IDX, MO_LESL); + MMU_PHYS_IDX, MO_LESL | MO_ALIGN); break; case 0x3: /* Quadword physical access with lock */ ret = gen_store_conditional(ctx, ra, rb, disp12, - MMU_PHYS_IDX, MO_LEUQ); + MMU_PHYS_IDX, MO_LEUQ | MO_ALIGN); break; case 0x4: /* Longword virtual access */ @@ -2771,11 +2775,11 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn) break; case 0x2A: /* LDL_L */ - gen_load_int(ctx, ra, rb, disp16, MO_LESL, 0, 1); + gen_load_int(ctx, ra, rb, disp16, MO_LESL | MO_ALIGN, 0, 1); break; case 0x2B: /* LDQ_L */ - gen_load_int(ctx, ra, rb, disp16, MO_LEUQ, 0, 1); + gen_load_int(ctx, ra, rb, disp16, MO_LEUQ | MO_ALIGN, 0, 1); break; case 0x2C: /* STL */ @@ -2788,12 +2792,12 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn) case 0x2E: /* STL_C */ ret = gen_store_conditional(ctx, ra, rb, disp16, - ctx->mem_idx, MO_LESL); + ctx->mem_idx, MO_LESL | MO_ALIGN); break; case 0x2F: /* STQ_C */ ret = gen_store_conditional(ctx, ra, rb, disp16, - ctx->mem_idx, MO_LEUQ); + ctx->mem_idx, MO_LEUQ | MO_ALIGN); break; case 0x30: /* BR */ From e10e98bdb090c4ed7d8d7ed6e7ff4f08097b93ec Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 May 2023 09:43:44 +0100 Subject: [PATCH 13/42] target/alpha: Remove TARGET_ALIGNED_ONLY Signed-off-by: Richard Henderson --- configs/targets/alpha-linux-user.mak | 1 - configs/targets/alpha-softmmu.mak | 1 - 2 files changed, 2 deletions(-) diff --git a/configs/targets/alpha-linux-user.mak b/configs/targets/alpha-linux-user.mak index 7e62fd796a..f7d3fb4afa 100644 --- a/configs/targets/alpha-linux-user.mak +++ b/configs/targets/alpha-linux-user.mak @@ -1,4 +1,3 @@ TARGET_ARCH=alpha TARGET_SYSTBL_ABI=common TARGET_SYSTBL=syscall.tbl -TARGET_ALIGNED_ONLY=y diff --git a/configs/targets/alpha-softmmu.mak b/configs/targets/alpha-softmmu.mak index e4b874a19e..9dbe160740 100644 --- a/configs/targets/alpha-softmmu.mak +++ b/configs/targets/alpha-softmmu.mak @@ -1,3 +1,2 @@ TARGET_ARCH=alpha -TARGET_ALIGNED_ONLY=y TARGET_SUPPORTS_MTTCG=y From 2d4afb03e42aa4b77b5e04acf148781b565b36d2 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 May 2023 15:30:10 +0100 Subject: [PATCH 14/42] target/hppa: Use MO_ALIGN for system UNALIGN() Signed-off-by: Richard Henderson --- target/hppa/translate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/hppa/translate.c b/target/hppa/translate.c index 6a3154ebc6..59e4688bfa 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -271,7 +271,7 @@ typedef struct DisasContext { #ifdef CONFIG_USER_ONLY #define UNALIGN(C) (C)->unalign #else -#define UNALIGN(C) 0 +#define UNALIGN(C) MO_ALIGN #endif /* Note that ssm/rsm instructions number PSW_W and PSW_E differently. */ From 0bd447ee6491b7f3163271aebf753f94fa6b148d Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 May 2023 09:53:13 +0100 Subject: [PATCH 15/42] target/hppa: Remove TARGET_ALIGNED_ONLY Signed-off-by: Richard Henderson --- configs/targets/hppa-linux-user.mak | 1 - configs/targets/hppa-softmmu.mak | 1 - 2 files changed, 2 deletions(-) diff --git a/configs/targets/hppa-linux-user.mak b/configs/targets/hppa-linux-user.mak index db873a8796..361ea39d71 100644 --- a/configs/targets/hppa-linux-user.mak +++ b/configs/targets/hppa-linux-user.mak @@ -1,5 +1,4 @@ TARGET_ARCH=hppa TARGET_SYSTBL_ABI=common,32 TARGET_SYSTBL=syscall.tbl -TARGET_ALIGNED_ONLY=y TARGET_BIG_ENDIAN=y diff --git a/configs/targets/hppa-softmmu.mak b/configs/targets/hppa-softmmu.mak index 44f07b0332..a41662aa99 100644 --- a/configs/targets/hppa-softmmu.mak +++ b/configs/targets/hppa-softmmu.mak @@ -1,4 +1,3 @@ TARGET_ARCH=hppa -TARGET_ALIGNED_ONLY=y TARGET_BIG_ENDIAN=y TARGET_SUPPORTS_MTTCG=y From 316b6783f1a67aa6b124d864f06b75d43b710675 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 May 2023 16:12:44 +0100 Subject: [PATCH 16/42] target/sparc: Use MO_ALIGN where required Acked-by: Mark Cave-Ayland Signed-off-by: Richard Henderson --- target/sparc/translate.c | 66 +++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 32 deletions(-) diff --git a/target/sparc/translate.c b/target/sparc/translate.c index bc71e44e66..414e014b11 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -1899,7 +1899,7 @@ static void gen_swap(DisasContext *dc, TCGv dst, TCGv src, TCGv addr, int mmu_idx, MemOp memop) { gen_address_mask(dc, addr); - tcg_gen_atomic_xchg_tl(dst, addr, src, mmu_idx, memop); + tcg_gen_atomic_xchg_tl(dst, addr, src, mmu_idx, memop | MO_ALIGN); } static void gen_ldstub(DisasContext *dc, TCGv dst, TCGv addr, int mmu_idx) @@ -2155,12 +2155,12 @@ static void gen_ld_asi(DisasContext *dc, TCGv dst, TCGv addr, break; case GET_ASI_DIRECT: gen_address_mask(dc, addr); - tcg_gen_qemu_ld_tl(dst, addr, da.mem_idx, da.memop); + tcg_gen_qemu_ld_tl(dst, addr, da.mem_idx, da.memop | MO_ALIGN); break; default: { TCGv_i32 r_asi = tcg_constant_i32(da.asi); - TCGv_i32 r_mop = tcg_constant_i32(memop); + TCGv_i32 r_mop = tcg_constant_i32(memop | MO_ALIGN); save_state(dc); #ifdef TARGET_SPARC64 @@ -2201,7 +2201,7 @@ static void gen_st_asi(DisasContext *dc, TCGv src, TCGv addr, /* fall through */ case GET_ASI_DIRECT: gen_address_mask(dc, addr); - tcg_gen_qemu_st_tl(src, addr, da.mem_idx, da.memop); + tcg_gen_qemu_st_tl(src, addr, da.mem_idx, da.memop | MO_ALIGN); break; #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) case GET_ASI_BCOPY: @@ -2233,7 +2233,7 @@ static void gen_st_asi(DisasContext *dc, TCGv src, TCGv addr, default: { TCGv_i32 r_asi = tcg_constant_i32(da.asi); - TCGv_i32 r_mop = tcg_constant_i32(memop & MO_SIZE); + TCGv_i32 r_mop = tcg_constant_i32(memop | MO_ALIGN); save_state(dc); #ifdef TARGET_SPARC64 @@ -2283,7 +2283,7 @@ static void gen_cas_asi(DisasContext *dc, TCGv addr, TCGv cmpv, case GET_ASI_DIRECT: oldv = tcg_temp_new(); tcg_gen_atomic_cmpxchg_tl(oldv, addr, cmpv, gen_load_gpr(dc, rd), - da.mem_idx, da.memop); + da.mem_idx, da.memop | MO_ALIGN); gen_store_gpr(dc, rd, oldv); break; default: @@ -2347,7 +2347,7 @@ static void gen_ldf_asi(DisasContext *dc, TCGv addr, switch (size) { case 4: d32 = gen_dest_fpr_F(dc); - tcg_gen_qemu_ld_i32(d32, addr, da.mem_idx, da.memop); + tcg_gen_qemu_ld_i32(d32, addr, da.mem_idx, da.memop | MO_ALIGN); gen_store_fpr_F(dc, rd, d32); break; case 8: @@ -2397,7 +2397,8 @@ static void gen_ldf_asi(DisasContext *dc, TCGv addr, /* Valid for lddfa only. */ if (size == 8) { gen_address_mask(dc, addr); - tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2], addr, da.mem_idx, da.memop); + tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2], addr, da.mem_idx, + da.memop | MO_ALIGN); } else { gen_exception(dc, TT_ILL_INSN); } @@ -2406,7 +2407,7 @@ static void gen_ldf_asi(DisasContext *dc, TCGv addr, default: { TCGv_i32 r_asi = tcg_constant_i32(da.asi); - TCGv_i32 r_mop = tcg_constant_i32(da.memop); + TCGv_i32 r_mop = tcg_constant_i32(da.memop | MO_ALIGN); save_state(dc); /* According to the table in the UA2011 manual, the only @@ -2454,7 +2455,7 @@ static void gen_stf_asi(DisasContext *dc, TCGv addr, switch (size) { case 4: d32 = gen_load_fpr_F(dc, rd); - tcg_gen_qemu_st_i32(d32, addr, da.mem_idx, da.memop); + tcg_gen_qemu_st_i32(d32, addr, da.mem_idx, da.memop | MO_ALIGN); break; case 8: tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da.mem_idx, @@ -2506,7 +2507,8 @@ static void gen_stf_asi(DisasContext *dc, TCGv addr, /* Valid for stdfa only. */ if (size == 8) { gen_address_mask(dc, addr); - tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da.mem_idx, da.memop); + tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da.mem_idx, + da.memop | MO_ALIGN); } else { gen_exception(dc, TT_ILL_INSN); } @@ -2543,7 +2545,7 @@ static void gen_ldda_asi(DisasContext *dc, TCGv addr, int insn, int rd) TCGv_i64 tmp = tcg_temp_new_i64(); gen_address_mask(dc, addr); - tcg_gen_qemu_ld_i64(tmp, addr, da.mem_idx, da.memop); + tcg_gen_qemu_ld_i64(tmp, addr, da.mem_idx, da.memop | MO_ALIGN); /* Note that LE ldda acts as if each 32-bit register result is byte swapped. Having just performed one @@ -2613,7 +2615,7 @@ static void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr, tcg_gen_concat32_i64(t64, hi, lo); } gen_address_mask(dc, addr); - tcg_gen_qemu_st_i64(t64, addr, da.mem_idx, da.memop); + tcg_gen_qemu_st_i64(t64, addr, da.mem_idx, da.memop | MO_ALIGN); } break; @@ -2651,7 +2653,7 @@ static void gen_casx_asi(DisasContext *dc, TCGv addr, TCGv cmpv, case GET_ASI_DIRECT: oldv = tcg_temp_new(); tcg_gen_atomic_cmpxchg_tl(oldv, addr, cmpv, gen_load_gpr(dc, rd), - da.mem_idx, da.memop); + da.mem_idx, da.memop | MO_ALIGN); gen_store_gpr(dc, rd, oldv); break; default: @@ -2678,7 +2680,7 @@ static void gen_ldda_asi(DisasContext *dc, TCGv addr, int insn, int rd) return; case GET_ASI_DIRECT: gen_address_mask(dc, addr); - tcg_gen_qemu_ld_i64(t64, addr, da.mem_idx, da.memop); + tcg_gen_qemu_ld_i64(t64, addr, da.mem_idx, da.memop | MO_ALIGN); break; default: { @@ -2710,7 +2712,7 @@ static void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr, break; case GET_ASI_DIRECT: gen_address_mask(dc, addr); - tcg_gen_qemu_st_i64(t64, addr, da.mem_idx, da.memop); + tcg_gen_qemu_st_i64(t64, addr, da.mem_idx, da.memop | MO_ALIGN); break; case GET_ASI_BFILL: /* Store 32 bytes of T64 to ADDR. */ @@ -5180,7 +5182,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) case 0x0: /* ld, V9 lduw, load unsigned word */ gen_address_mask(dc, cpu_addr); tcg_gen_qemu_ld_tl(cpu_val, cpu_addr, - dc->mem_idx, MO_TEUL); + dc->mem_idx, MO_TEUL | MO_ALIGN); break; case 0x1: /* ldub, load unsigned byte */ gen_address_mask(dc, cpu_addr); @@ -5190,7 +5192,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) case 0x2: /* lduh, load unsigned halfword */ gen_address_mask(dc, cpu_addr); tcg_gen_qemu_ld_tl(cpu_val, cpu_addr, - dc->mem_idx, MO_TEUW); + dc->mem_idx, MO_TEUW | MO_ALIGN); break; case 0x3: /* ldd, load double word */ if (rd & 1) @@ -5201,7 +5203,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) gen_address_mask(dc, cpu_addr); t64 = tcg_temp_new_i64(); tcg_gen_qemu_ld_i64(t64, cpu_addr, - dc->mem_idx, MO_TEUQ); + dc->mem_idx, MO_TEUQ | MO_ALIGN); tcg_gen_trunc_i64_tl(cpu_val, t64); tcg_gen_ext32u_tl(cpu_val, cpu_val); gen_store_gpr(dc, rd + 1, cpu_val); @@ -5217,7 +5219,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) case 0xa: /* ldsh, load signed halfword */ gen_address_mask(dc, cpu_addr); tcg_gen_qemu_ld_tl(cpu_val, cpu_addr, - dc->mem_idx, MO_TESW); + dc->mem_idx, MO_TESW | MO_ALIGN); break; case 0xd: /* ldstub */ gen_ldstub(dc, cpu_val, cpu_addr, dc->mem_idx); @@ -5272,12 +5274,12 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) case 0x08: /* V9 ldsw */ gen_address_mask(dc, cpu_addr); tcg_gen_qemu_ld_tl(cpu_val, cpu_addr, - dc->mem_idx, MO_TESL); + dc->mem_idx, MO_TESL | MO_ALIGN); break; case 0x0b: /* V9 ldx */ gen_address_mask(dc, cpu_addr); tcg_gen_qemu_ld_tl(cpu_val, cpu_addr, - dc->mem_idx, MO_TEUQ); + dc->mem_idx, MO_TEUQ | MO_ALIGN); break; case 0x18: /* V9 ldswa */ gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_TESL); @@ -5328,7 +5330,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) gen_address_mask(dc, cpu_addr); cpu_dst_32 = gen_dest_fpr_F(dc); tcg_gen_qemu_ld_i32(cpu_dst_32, cpu_addr, - dc->mem_idx, MO_TEUL); + dc->mem_idx, MO_TEUL | MO_ALIGN); gen_store_fpr_F(dc, rd, cpu_dst_32); break; case 0x21: /* ldfsr, V9 ldxfsr */ @@ -5337,14 +5339,14 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) if (rd == 1) { TCGv_i64 t64 = tcg_temp_new_i64(); tcg_gen_qemu_ld_i64(t64, cpu_addr, - dc->mem_idx, MO_TEUQ); + dc->mem_idx, MO_TEUQ | MO_ALIGN); gen_helper_ldxfsr(cpu_fsr, cpu_env, cpu_fsr, t64); break; } #endif cpu_dst_32 = tcg_temp_new_i32(); tcg_gen_qemu_ld_i32(cpu_dst_32, cpu_addr, - dc->mem_idx, MO_TEUL); + dc->mem_idx, MO_TEUL | MO_ALIGN); gen_helper_ldfsr(cpu_fsr, cpu_env, cpu_fsr, cpu_dst_32); break; case 0x22: /* ldqf, load quad fpreg */ @@ -5377,7 +5379,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) case 0x4: /* st, store word */ gen_address_mask(dc, cpu_addr); tcg_gen_qemu_st_tl(cpu_val, cpu_addr, - dc->mem_idx, MO_TEUL); + dc->mem_idx, MO_TEUL | MO_ALIGN); break; case 0x5: /* stb, store byte */ gen_address_mask(dc, cpu_addr); @@ -5386,7 +5388,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) case 0x6: /* sth, store halfword */ gen_address_mask(dc, cpu_addr); tcg_gen_qemu_st_tl(cpu_val, cpu_addr, - dc->mem_idx, MO_TEUW); + dc->mem_idx, MO_TEUW | MO_ALIGN); break; case 0x7: /* std, store double word */ if (rd & 1) @@ -5400,7 +5402,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) t64 = tcg_temp_new_i64(); tcg_gen_concat_tl_i64(t64, lo, cpu_val); tcg_gen_qemu_st_i64(t64, cpu_addr, - dc->mem_idx, MO_TEUQ); + dc->mem_idx, MO_TEUQ | MO_ALIGN); } break; #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) @@ -5424,7 +5426,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) case 0x0e: /* V9 stx */ gen_address_mask(dc, cpu_addr); tcg_gen_qemu_st_tl(cpu_val, cpu_addr, - dc->mem_idx, MO_TEUQ); + dc->mem_idx, MO_TEUQ | MO_ALIGN); break; case 0x1e: /* V9 stxa */ gen_st_asi(dc, cpu_val, cpu_addr, insn, MO_TEUQ); @@ -5442,7 +5444,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) gen_address_mask(dc, cpu_addr); cpu_src1_32 = gen_load_fpr_F(dc, rd); tcg_gen_qemu_st_i32(cpu_src1_32, cpu_addr, - dc->mem_idx, MO_TEUL); + dc->mem_idx, MO_TEUL | MO_ALIGN); break; case 0x25: /* stfsr, V9 stxfsr */ { @@ -5450,12 +5452,12 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) gen_address_mask(dc, cpu_addr); if (rd == 1) { tcg_gen_qemu_st_tl(cpu_fsr, cpu_addr, - dc->mem_idx, MO_TEUQ); + dc->mem_idx, MO_TEUQ | MO_ALIGN); break; } #endif tcg_gen_qemu_st_tl(cpu_fsr, cpu_addr, - dc->mem_idx, MO_TEUL); + dc->mem_idx, MO_TEUL | MO_ALIGN); } break; case 0x26: From 60abd45224d0cb855bf32789b7b7b78061f1fbd6 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 May 2023 16:14:19 +0100 Subject: [PATCH 17/42] target/sparc: Use cpu_ld*_code_mmu This passes on the memop as given as argument to helper_ld_asi to the ultimate load primitive. Reviewed-by: Mark Cave-Ayland Signed-off-by: Richard Henderson --- target/sparc/ldst_helper.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/target/sparc/ldst_helper.c b/target/sparc/ldst_helper.c index a53580d9e4..7972d56a72 100644 --- a/target/sparc/ldst_helper.c +++ b/target/sparc/ldst_helper.c @@ -593,6 +593,7 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, #if defined(DEBUG_MXCC) || defined(DEBUG_ASI) uint32_t last_addr = addr; #endif + MemOpIdx oi; do_check_align(env, addr, size - 1, GETPC()); switch (asi) { @@ -692,19 +693,20 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, case ASI_M_IODIAG: /* Turbosparc IOTLB Diagnostic */ break; case ASI_KERNELTXT: /* Supervisor code access */ + oi = make_memop_idx(memop, cpu_mmu_index(env, true)); switch (size) { case 1: - ret = cpu_ldub_code(env, addr); + ret = cpu_ldb_code_mmu(env, addr, oi, GETPC()); break; case 2: - ret = cpu_lduw_code(env, addr); + ret = cpu_ldw_code_mmu(env, addr, oi, GETPC()); break; default: case 4: - ret = cpu_ldl_code(env, addr); + ret = cpu_ldl_code_mmu(env, addr, oi, GETPC()); break; case 8: - ret = cpu_ldq_code(env, addr); + ret = cpu_ldq_code_mmu(env, addr, oi, GETPC()); break; } break; From 3ed8d2d4c86e82f7f663695249c5045fa78539c7 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 May 2023 16:15:23 +0100 Subject: [PATCH 18/42] target/sparc: Remove TARGET_ALIGNED_ONLY Reviewed-by: Mark Cave-Ayland Signed-off-by: Richard Henderson --- configs/targets/sparc-linux-user.mak | 1 - configs/targets/sparc-softmmu.mak | 1 - configs/targets/sparc32plus-linux-user.mak | 1 - configs/targets/sparc64-linux-user.mak | 1 - configs/targets/sparc64-softmmu.mak | 1 - 5 files changed, 5 deletions(-) diff --git a/configs/targets/sparc-linux-user.mak b/configs/targets/sparc-linux-user.mak index 00e7bc1f07..abcfb8fc62 100644 --- a/configs/targets/sparc-linux-user.mak +++ b/configs/targets/sparc-linux-user.mak @@ -1,5 +1,4 @@ TARGET_ARCH=sparc TARGET_SYSTBL_ABI=common,32 TARGET_SYSTBL=syscall.tbl -TARGET_ALIGNED_ONLY=y TARGET_BIG_ENDIAN=y diff --git a/configs/targets/sparc-softmmu.mak b/configs/targets/sparc-softmmu.mak index a849190f01..454eb35499 100644 --- a/configs/targets/sparc-softmmu.mak +++ b/configs/targets/sparc-softmmu.mak @@ -1,3 +1,2 @@ TARGET_ARCH=sparc -TARGET_ALIGNED_ONLY=y TARGET_BIG_ENDIAN=y diff --git a/configs/targets/sparc32plus-linux-user.mak b/configs/targets/sparc32plus-linux-user.mak index a65c0951a1..6cc8fa516b 100644 --- a/configs/targets/sparc32plus-linux-user.mak +++ b/configs/targets/sparc32plus-linux-user.mak @@ -4,5 +4,4 @@ TARGET_BASE_ARCH=sparc TARGET_ABI_DIR=sparc TARGET_SYSTBL_ABI=common,32 TARGET_SYSTBL=syscall.tbl -TARGET_ALIGNED_ONLY=y TARGET_BIG_ENDIAN=y diff --git a/configs/targets/sparc64-linux-user.mak b/configs/targets/sparc64-linux-user.mak index 20fcb93fa4..52f05ec000 100644 --- a/configs/targets/sparc64-linux-user.mak +++ b/configs/targets/sparc64-linux-user.mak @@ -3,5 +3,4 @@ TARGET_BASE_ARCH=sparc TARGET_ABI_DIR=sparc TARGET_SYSTBL_ABI=common,64 TARGET_SYSTBL=syscall.tbl -TARGET_ALIGNED_ONLY=y TARGET_BIG_ENDIAN=y diff --git a/configs/targets/sparc64-softmmu.mak b/configs/targets/sparc64-softmmu.mak index c626ac3eae..d3f8a3b710 100644 --- a/configs/targets/sparc64-softmmu.mak +++ b/configs/targets/sparc64-softmmu.mak @@ -1,4 +1,3 @@ TARGET_ARCH=sparc64 TARGET_BASE_ARCH=sparc -TARGET_ALIGNED_ONLY=y TARGET_BIG_ENDIAN=y From bf12e2240d81f887427b75ad2bba8a6040d36366 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 6 Apr 2023 12:42:40 -0700 Subject: [PATCH 19/42] tcg/i386: Rationalize args to tcg_out_qemu_{ld,st} MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Interpret the variable argument placement in the caller. Pass data_type instead of is64 -- there are several places where we already convert back from bool to type. Clean things up by using type throughout. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- tcg/i386/tcg-target.c.inc | 111 +++++++++++++++++--------------------- 1 file changed, 50 insertions(+), 61 deletions(-) diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc index caf91a3151..cfa2349b03 100644 --- a/tcg/i386/tcg-target.c.inc +++ b/tcg/i386/tcg-target.c.inc @@ -1884,8 +1884,8 @@ static inline void tcg_out_tlb_load(TCGContext *s, TCGReg addrlo, TCGReg addrhi, * Record the context of a call to the out of line helper code for the slow path * for a load or store, so that we can later generate the correct helper code */ -static void add_qemu_ldst_label(TCGContext *s, bool is_ld, bool is_64, - MemOpIdx oi, +static void add_qemu_ldst_label(TCGContext *s, bool is_ld, + TCGType type, MemOpIdx oi, TCGReg datalo, TCGReg datahi, TCGReg addrlo, TCGReg addrhi, tcg_insn_unit *raddr, @@ -1895,7 +1895,7 @@ static void add_qemu_ldst_label(TCGContext *s, bool is_ld, bool is_64, label->is_ld = is_ld; label->oi = oi; - label->type = is_64 ? TCG_TYPE_I64 : TCG_TYPE_I32; + label->type = type; label->datalo_reg = datalo; label->datahi_reg = datahi; label->addrlo_reg = addrlo; @@ -2152,11 +2152,10 @@ static inline int setup_guest_base_seg(void) static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi, TCGReg base, int index, intptr_t ofs, - int seg, bool is64, MemOp memop) + int seg, TCGType type, MemOp memop) { - TCGType type = is64 ? TCG_TYPE_I64 : TCG_TYPE_I32; bool use_movbe = false; - int rexw = is64 * P_REXW; + int rexw = (type == TCG_TYPE_I32 ? 0 : P_REXW); int movop = OPC_MOVL_GvEv; /* Do big-endian loads with movbe. */ @@ -2246,50 +2245,34 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi, } } -/* XXX: qemu_ld and qemu_st could be modified to clobber only EDX and - EAX. It will be useful once fixed registers globals are less - common. */ -static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64) +static void tcg_out_qemu_ld(TCGContext *s, TCGReg datalo, TCGReg datahi, + TCGReg addrlo, TCGReg addrhi, + MemOpIdx oi, TCGType data_type) { - TCGReg datalo, datahi, addrlo; - TCGReg addrhi __attribute__((unused)); - MemOpIdx oi; - MemOp opc; + MemOp opc = get_memop(oi); + #if defined(CONFIG_SOFTMMU) - int mem_index; tcg_insn_unit *label_ptr[2]; -#else - unsigned a_bits; -#endif - datalo = *args++; - datahi = (TCG_TARGET_REG_BITS == 32 && is64 ? *args++ : 0); - addrlo = *args++; - addrhi = (TARGET_LONG_BITS > TCG_TARGET_REG_BITS ? *args++ : 0); - oi = *args++; - opc = get_memop(oi); - -#if defined(CONFIG_SOFTMMU) - mem_index = get_mmuidx(oi); - - tcg_out_tlb_load(s, addrlo, addrhi, mem_index, opc, + tcg_out_tlb_load(s, addrlo, addrhi, get_mmuidx(oi), opc, label_ptr, offsetof(CPUTLBEntry, addr_read)); /* TLB Hit. */ - tcg_out_qemu_ld_direct(s, datalo, datahi, TCG_REG_L1, -1, 0, 0, is64, opc); + tcg_out_qemu_ld_direct(s, datalo, datahi, TCG_REG_L1, + -1, 0, 0, data_type, opc); /* Record the current context of a load into ldst label */ - add_qemu_ldst_label(s, true, is64, oi, datalo, datahi, addrlo, addrhi, - s->code_ptr, label_ptr); + add_qemu_ldst_label(s, true, data_type, oi, datalo, datahi, + addrlo, addrhi, s->code_ptr, label_ptr); #else - a_bits = get_alignment_bits(opc); + unsigned a_bits = get_alignment_bits(opc); if (a_bits) { tcg_out_test_alignment(s, true, addrlo, addrhi, a_bits); } tcg_out_qemu_ld_direct(s, datalo, datahi, addrlo, x86_guest_base_index, x86_guest_base_offset, x86_guest_base_seg, - is64, opc); + data_type, opc); #endif } @@ -2345,40 +2328,26 @@ static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg datalo, TCGReg datahi, } } -static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is64) +static void tcg_out_qemu_st(TCGContext *s, TCGReg datalo, TCGReg datahi, + TCGReg addrlo, TCGReg addrhi, + MemOpIdx oi, TCGType data_type) { - TCGReg datalo, datahi, addrlo; - TCGReg addrhi __attribute__((unused)); - MemOpIdx oi; - MemOp opc; + MemOp opc = get_memop(oi); + #if defined(CONFIG_SOFTMMU) - int mem_index; tcg_insn_unit *label_ptr[2]; -#else - unsigned a_bits; -#endif - datalo = *args++; - datahi = (TCG_TARGET_REG_BITS == 32 && is64 ? *args++ : 0); - addrlo = *args++; - addrhi = (TARGET_LONG_BITS > TCG_TARGET_REG_BITS ? *args++ : 0); - oi = *args++; - opc = get_memop(oi); - -#if defined(CONFIG_SOFTMMU) - mem_index = get_mmuidx(oi); - - tcg_out_tlb_load(s, addrlo, addrhi, mem_index, opc, + tcg_out_tlb_load(s, addrlo, addrhi, get_mmuidx(oi), opc, label_ptr, offsetof(CPUTLBEntry, addr_write)); /* TLB Hit. */ tcg_out_qemu_st_direct(s, datalo, datahi, TCG_REG_L1, -1, 0, 0, opc); /* Record the current context of a store into ldst label */ - add_qemu_ldst_label(s, false, is64, oi, datalo, datahi, addrlo, addrhi, - s->code_ptr, label_ptr); + add_qemu_ldst_label(s, false, data_type, oi, datalo, datahi, + addrlo, addrhi, s->code_ptr, label_ptr); #else - a_bits = get_alignment_bits(opc); + unsigned a_bits = get_alignment_bits(opc); if (a_bits) { tcg_out_test_alignment(s, false, addrlo, addrhi, a_bits); } @@ -2673,17 +2642,37 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, break; case INDEX_op_qemu_ld_i32: - tcg_out_qemu_ld(s, args, 0); + if (TCG_TARGET_REG_BITS >= TARGET_LONG_BITS) { + tcg_out_qemu_ld(s, a0, -1, a1, -1, a2, TCG_TYPE_I32); + } else { + tcg_out_qemu_ld(s, a0, -1, a1, a2, args[3], TCG_TYPE_I32); + } break; case INDEX_op_qemu_ld_i64: - tcg_out_qemu_ld(s, args, 1); + if (TCG_TARGET_REG_BITS == 64) { + tcg_out_qemu_ld(s, a0, -1, a1, -1, a2, TCG_TYPE_I64); + } else if (TARGET_LONG_BITS == 32) { + tcg_out_qemu_ld(s, a0, a1, a2, -1, args[3], TCG_TYPE_I64); + } else { + tcg_out_qemu_ld(s, a0, a1, a2, args[3], args[4], TCG_TYPE_I64); + } break; case INDEX_op_qemu_st_i32: case INDEX_op_qemu_st8_i32: - tcg_out_qemu_st(s, args, 0); + if (TCG_TARGET_REG_BITS >= TARGET_LONG_BITS) { + tcg_out_qemu_st(s, a0, -1, a1, -1, a2, TCG_TYPE_I32); + } else { + tcg_out_qemu_st(s, a0, -1, a1, a2, args[3], TCG_TYPE_I32); + } break; case INDEX_op_qemu_st_i64: - tcg_out_qemu_st(s, args, 1); + if (TCG_TARGET_REG_BITS == 64) { + tcg_out_qemu_st(s, a0, -1, a1, -1, a2, TCG_TYPE_I64); + } else if (TARGET_LONG_BITS == 32) { + tcg_out_qemu_st(s, a0, a1, a2, -1, args[3], TCG_TYPE_I64); + } else { + tcg_out_qemu_st(s, a0, a1, a2, args[3], args[4], TCG_TYPE_I64); + } break; OP_32_64(mulu2): From 3174941fe096abe903a1acdec8ed0603b3c23e12 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 16 Apr 2023 15:56:41 +0200 Subject: [PATCH 20/42] tcg/i386: Generalize multi-part load overlap test Test for both base and index; use datahi as a temporary, overwritten by the final load. Always perform the loads in ascending order, so that any (user-only) fault sees the correct address. Signed-off-by: Richard Henderson --- tcg/i386/tcg-target.c.inc | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc index cfa2349b03..173f3c3172 100644 --- a/tcg/i386/tcg-target.c.inc +++ b/tcg/i386/tcg-target.c.inc @@ -2221,23 +2221,22 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi, if (TCG_TARGET_REG_BITS == 64) { tcg_out_modrm_sib_offset(s, movop + P_REXW + seg, datalo, base, index, 0, ofs); + break; + } + if (use_movbe) { + TCGReg t = datalo; + datalo = datahi; + datahi = t; + } + if (base == datalo || index == datalo) { + tcg_out_modrm_sib_offset(s, OPC_LEA, datahi, base, index, 0, ofs); + tcg_out_modrm_offset(s, movop + seg, datalo, datahi, 0); + tcg_out_modrm_offset(s, movop + seg, datahi, datahi, 4); } else { - if (use_movbe) { - TCGReg t = datalo; - datalo = datahi; - datahi = t; - } - if (base != datalo) { - tcg_out_modrm_sib_offset(s, movop + seg, datalo, - base, index, 0, ofs); - tcg_out_modrm_sib_offset(s, movop + seg, datahi, - base, index, 0, ofs + 4); - } else { - tcg_out_modrm_sib_offset(s, movop + seg, datahi, - base, index, 0, ofs + 4); - tcg_out_modrm_sib_offset(s, movop + seg, datalo, - base, index, 0, ofs); - } + tcg_out_modrm_sib_offset(s, movop + seg, datalo, + base, index, 0, ofs); + tcg_out_modrm_sib_offset(s, movop + seg, datahi, + base, index, 0, ofs + 4); } break; default: From 61713c29a912899a5195f7605b5bb328cc0f29e6 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 19 Apr 2023 18:29:14 +0200 Subject: [PATCH 21/42] tcg/i386: Introduce HostAddress MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Collect the 4 potential parts of the host address into a struct. Reorg tcg_out_qemu_{ld,st}_direct to use it. Reorg guest_base handling to use it. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- tcg/i386/tcg-target.c.inc | 165 +++++++++++++++++++++----------------- 1 file changed, 90 insertions(+), 75 deletions(-) diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc index 173f3c3172..909eecd4a3 100644 --- a/tcg/i386/tcg-target.c.inc +++ b/tcg/i386/tcg-target.c.inc @@ -1751,6 +1751,13 @@ static void tcg_out_nopn(TCGContext *s, int n) tcg_out8(s, 0x90); } +typedef struct { + TCGReg base; + int index; + int ofs; + int seg; +} HostAddress; + #if defined(CONFIG_SOFTMMU) /* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr, * int mmu_idx, uintptr_t ra) @@ -2113,17 +2120,13 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l) return tcg_out_fail_alignment(s, l); } -#if TCG_TARGET_REG_BITS == 32 -# define x86_guest_base_seg 0 -# define x86_guest_base_index -1 -# define x86_guest_base_offset guest_base -#else -static int x86_guest_base_seg; -static int x86_guest_base_index = -1; -static int32_t x86_guest_base_offset; -# if defined(__x86_64__) && defined(__linux__) -# include -# include +static HostAddress x86_guest_base = { + .index = -1 +}; + +#if defined(__x86_64__) && defined(__linux__) +# include +# include int arch_prctl(int code, unsigned long addr); static inline int setup_guest_base_seg(void) { @@ -2132,8 +2135,9 @@ static inline int setup_guest_base_seg(void) } return 0; } -# elif defined (__FreeBSD__) || defined (__FreeBSD_kernel__) -# include +#elif defined(__x86_64__) && \ + (defined (__FreeBSD__) || defined (__FreeBSD_kernel__)) +# include static inline int setup_guest_base_seg(void) { if (sysarch(AMD64_SET_GSBASE, &guest_base) == 0) { @@ -2141,18 +2145,16 @@ static inline int setup_guest_base_seg(void) } return 0; } -# else +#else static inline int setup_guest_base_seg(void) { return 0; } -# endif -#endif +#endif /* setup_guest_base_seg */ #endif /* SOFTMMU */ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi, - TCGReg base, int index, intptr_t ofs, - int seg, TCGType type, MemOp memop) + HostAddress h, TCGType type, MemOp memop) { bool use_movbe = false; int rexw = (type == TCG_TYPE_I32 ? 0 : P_REXW); @@ -2167,60 +2169,61 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi, switch (memop & MO_SSIZE) { case MO_UB: - tcg_out_modrm_sib_offset(s, OPC_MOVZBL + seg, datalo, - base, index, 0, ofs); + tcg_out_modrm_sib_offset(s, OPC_MOVZBL + h.seg, datalo, + h.base, h.index, 0, h.ofs); break; case MO_SB: - tcg_out_modrm_sib_offset(s, OPC_MOVSBL + rexw + seg, datalo, - base, index, 0, ofs); + tcg_out_modrm_sib_offset(s, OPC_MOVSBL + rexw + h.seg, datalo, + h.base, h.index, 0, h.ofs); break; case MO_UW: if (use_movbe) { /* There is no extending movbe; only low 16-bits are modified. */ - if (datalo != base && datalo != index) { + if (datalo != h.base && datalo != h.index) { /* XOR breaks dependency chains. */ tgen_arithr(s, ARITH_XOR, datalo, datalo); - tcg_out_modrm_sib_offset(s, OPC_MOVBE_GyMy + P_DATA16 + seg, - datalo, base, index, 0, ofs); + tcg_out_modrm_sib_offset(s, OPC_MOVBE_GyMy + P_DATA16 + h.seg, + datalo, h.base, h.index, 0, h.ofs); } else { - tcg_out_modrm_sib_offset(s, OPC_MOVBE_GyMy + P_DATA16 + seg, - datalo, base, index, 0, ofs); + tcg_out_modrm_sib_offset(s, OPC_MOVBE_GyMy + P_DATA16 + h.seg, + datalo, h.base, h.index, 0, h.ofs); tcg_out_ext16u(s, datalo, datalo); } } else { - tcg_out_modrm_sib_offset(s, OPC_MOVZWL + seg, datalo, - base, index, 0, ofs); + tcg_out_modrm_sib_offset(s, OPC_MOVZWL + h.seg, datalo, + h.base, h.index, 0, h.ofs); } break; case MO_SW: if (use_movbe) { - tcg_out_modrm_sib_offset(s, OPC_MOVBE_GyMy + P_DATA16 + seg, - datalo, base, index, 0, ofs); + tcg_out_modrm_sib_offset(s, OPC_MOVBE_GyMy + P_DATA16 + h.seg, + datalo, h.base, h.index, 0, h.ofs); tcg_out_ext16s(s, type, datalo, datalo); } else { - tcg_out_modrm_sib_offset(s, OPC_MOVSWL + rexw + seg, - datalo, base, index, 0, ofs); + tcg_out_modrm_sib_offset(s, OPC_MOVSWL + rexw + h.seg, + datalo, h.base, h.index, 0, h.ofs); } break; case MO_UL: - tcg_out_modrm_sib_offset(s, movop + seg, datalo, base, index, 0, ofs); + tcg_out_modrm_sib_offset(s, movop + h.seg, datalo, + h.base, h.index, 0, h.ofs); break; #if TCG_TARGET_REG_BITS == 64 case MO_SL: if (use_movbe) { - tcg_out_modrm_sib_offset(s, OPC_MOVBE_GyMy + seg, datalo, - base, index, 0, ofs); + tcg_out_modrm_sib_offset(s, OPC_MOVBE_GyMy + h.seg, datalo, + h.base, h.index, 0, h.ofs); tcg_out_ext32s(s, datalo, datalo); } else { - tcg_out_modrm_sib_offset(s, OPC_MOVSLQ + seg, datalo, - base, index, 0, ofs); + tcg_out_modrm_sib_offset(s, OPC_MOVSLQ + h.seg, datalo, + h.base, h.index, 0, h.ofs); } break; #endif case MO_UQ: if (TCG_TARGET_REG_BITS == 64) { - tcg_out_modrm_sib_offset(s, movop + P_REXW + seg, datalo, - base, index, 0, ofs); + tcg_out_modrm_sib_offset(s, movop + P_REXW + h.seg, datalo, + h.base, h.index, 0, h.ofs); break; } if (use_movbe) { @@ -2228,15 +2231,16 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi, datalo = datahi; datahi = t; } - if (base == datalo || index == datalo) { - tcg_out_modrm_sib_offset(s, OPC_LEA, datahi, base, index, 0, ofs); - tcg_out_modrm_offset(s, movop + seg, datalo, datahi, 0); - tcg_out_modrm_offset(s, movop + seg, datahi, datahi, 4); + if (h.base == datalo || h.index == datalo) { + tcg_out_modrm_sib_offset(s, OPC_LEA, datahi, + h.base, h.index, 0, h.ofs); + tcg_out_modrm_offset(s, movop + h.seg, datalo, datahi, 0); + tcg_out_modrm_offset(s, movop + h.seg, datahi, datahi, 4); } else { - tcg_out_modrm_sib_offset(s, movop + seg, datalo, - base, index, 0, ofs); - tcg_out_modrm_sib_offset(s, movop + seg, datahi, - base, index, 0, ofs + 4); + tcg_out_modrm_sib_offset(s, movop + h.seg, datalo, + h.base, h.index, 0, h.ofs); + tcg_out_modrm_sib_offset(s, movop + h.seg, datahi, + h.base, h.index, 0, h.ofs + 4); } break; default: @@ -2249,6 +2253,7 @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg datalo, TCGReg datahi, MemOpIdx oi, TCGType data_type) { MemOp opc = get_memop(oi); + HostAddress h; #if defined(CONFIG_SOFTMMU) tcg_insn_unit *label_ptr[2]; @@ -2257,8 +2262,11 @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg datalo, TCGReg datahi, label_ptr, offsetof(CPUTLBEntry, addr_read)); /* TLB Hit. */ - tcg_out_qemu_ld_direct(s, datalo, datahi, TCG_REG_L1, - -1, 0, 0, data_type, opc); + h.base = TCG_REG_L1; + h.index = -1; + h.ofs = 0; + h.seg = 0; + tcg_out_qemu_ld_direct(s, datalo, datahi, h, data_type, opc); /* Record the current context of a load into ldst label */ add_qemu_ldst_label(s, true, data_type, oi, datalo, datahi, @@ -2269,15 +2277,14 @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg datalo, TCGReg datahi, tcg_out_test_alignment(s, true, addrlo, addrhi, a_bits); } - tcg_out_qemu_ld_direct(s, datalo, datahi, addrlo, x86_guest_base_index, - x86_guest_base_offset, x86_guest_base_seg, - data_type, opc); + h = x86_guest_base; + h.base = addrlo; + tcg_out_qemu_ld_direct(s, datalo, datahi, h, data_type, opc); #endif } static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg datalo, TCGReg datahi, - TCGReg base, int index, intptr_t ofs, - int seg, MemOp memop) + HostAddress h, MemOp memop) { bool use_movbe = false; int movop = OPC_MOVL_EvGv; @@ -2296,30 +2303,31 @@ static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg datalo, TCGReg datahi, case MO_8: /* This is handled with constraints on INDEX_op_qemu_st8_i32. */ tcg_debug_assert(TCG_TARGET_REG_BITS == 64 || datalo < 4); - tcg_out_modrm_sib_offset(s, OPC_MOVB_EvGv + P_REXB_R + seg, - datalo, base, index, 0, ofs); + tcg_out_modrm_sib_offset(s, OPC_MOVB_EvGv + P_REXB_R + h.seg, + datalo, h.base, h.index, 0, h.ofs); break; case MO_16: - tcg_out_modrm_sib_offset(s, movop + P_DATA16 + seg, datalo, - base, index, 0, ofs); + tcg_out_modrm_sib_offset(s, movop + P_DATA16 + h.seg, datalo, + h.base, h.index, 0, h.ofs); break; case MO_32: - tcg_out_modrm_sib_offset(s, movop + seg, datalo, base, index, 0, ofs); + tcg_out_modrm_sib_offset(s, movop + h.seg, datalo, + h.base, h.index, 0, h.ofs); break; case MO_64: if (TCG_TARGET_REG_BITS == 64) { - tcg_out_modrm_sib_offset(s, movop + P_REXW + seg, datalo, - base, index, 0, ofs); + tcg_out_modrm_sib_offset(s, movop + P_REXW + h.seg, datalo, + h.base, h.index, 0, h.ofs); } else { if (use_movbe) { TCGReg t = datalo; datalo = datahi; datahi = t; } - tcg_out_modrm_sib_offset(s, movop + seg, datalo, - base, index, 0, ofs); - tcg_out_modrm_sib_offset(s, movop + seg, datahi, - base, index, 0, ofs + 4); + tcg_out_modrm_sib_offset(s, movop + h.seg, datalo, + h.base, h.index, 0, h.ofs); + tcg_out_modrm_sib_offset(s, movop + h.seg, datahi, + h.base, h.index, 0, h.ofs + 4); } break; default: @@ -2332,6 +2340,7 @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg datalo, TCGReg datahi, MemOpIdx oi, TCGType data_type) { MemOp opc = get_memop(oi); + HostAddress h; #if defined(CONFIG_SOFTMMU) tcg_insn_unit *label_ptr[2]; @@ -2340,7 +2349,11 @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg datalo, TCGReg datahi, label_ptr, offsetof(CPUTLBEntry, addr_write)); /* TLB Hit. */ - tcg_out_qemu_st_direct(s, datalo, datahi, TCG_REG_L1, -1, 0, 0, opc); + h.base = TCG_REG_L1; + h.index = -1; + h.ofs = 0; + h.seg = 0; + tcg_out_qemu_st_direct(s, datalo, datahi, h, opc); /* Record the current context of a store into ldst label */ add_qemu_ldst_label(s, false, data_type, oi, datalo, datahi, @@ -2351,8 +2364,10 @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg datalo, TCGReg datahi, tcg_out_test_alignment(s, false, addrlo, addrhi, a_bits); } - tcg_out_qemu_st_direct(s, datalo, datahi, addrlo, x86_guest_base_index, - x86_guest_base_offset, x86_guest_base_seg, opc); + h = x86_guest_base; + h.base = addrlo; + + tcg_out_qemu_st_direct(s, datalo, datahi, h, opc); #endif } @@ -4058,18 +4073,18 @@ static void tcg_target_qemu_prologue(TCGContext *s) (ARRAY_SIZE(tcg_target_callee_save_regs) + 2) * 4 + stack_addend); #else -# if !defined(CONFIG_SOFTMMU) && TCG_TARGET_REG_BITS == 64 +# if !defined(CONFIG_SOFTMMU) if (guest_base) { int seg = setup_guest_base_seg(); if (seg != 0) { - x86_guest_base_seg = seg; + x86_guest_base.seg = seg; } else if (guest_base == (int32_t)guest_base) { - x86_guest_base_offset = guest_base; + x86_guest_base.ofs = guest_base; } else { /* Choose R12 because, as a base, it requires a SIB byte. */ - x86_guest_base_index = TCG_REG_R12; - tcg_out_movi(s, TCG_TYPE_PTR, x86_guest_base_index, guest_base); - tcg_regset_set_reg(s->reserved_regs, x86_guest_base_index); + x86_guest_base.index = TCG_REG_R12; + tcg_out_movi(s, TCG_TYPE_PTR, x86_guest_base.index, guest_base); + tcg_regset_set_reg(s->reserved_regs, x86_guest_base.index); } } # endif From 3c2c35e23eb57eafb232c457d2c6d34262110701 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 19 Apr 2023 18:43:35 +0200 Subject: [PATCH 22/42] tcg/i386: Drop r0+r1 local variables from tcg_out_tlb_load MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use TCG_REG_L[01] constants directly. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- tcg/i386/tcg-target.c.inc | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc index 909eecd4a3..78160f453b 100644 --- a/tcg/i386/tcg-target.c.inc +++ b/tcg/i386/tcg-target.c.inc @@ -1810,8 +1810,6 @@ static inline void tcg_out_tlb_load(TCGContext *s, TCGReg addrlo, TCGReg addrhi, int mem_index, MemOp opc, tcg_insn_unit **label_ptr, int which) { - const TCGReg r0 = TCG_REG_L0; - const TCGReg r1 = TCG_REG_L1; TCGType ttype = TCG_TYPE_I32; TCGType tlbtype = TCG_TYPE_I32; int trexw = 0, hrexw = 0, tlbrexw = 0; @@ -1835,15 +1833,15 @@ static inline void tcg_out_tlb_load(TCGContext *s, TCGReg addrlo, TCGReg addrhi, } } - tcg_out_mov(s, tlbtype, r0, addrlo); - tcg_out_shifti(s, SHIFT_SHR + tlbrexw, r0, + tcg_out_mov(s, tlbtype, TCG_REG_L0, addrlo); + tcg_out_shifti(s, SHIFT_SHR + tlbrexw, TCG_REG_L0, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS); - tcg_out_modrm_offset(s, OPC_AND_GvEv + trexw, r0, TCG_AREG0, + tcg_out_modrm_offset(s, OPC_AND_GvEv + trexw, TCG_REG_L0, TCG_AREG0, TLB_MASK_TABLE_OFS(mem_index) + offsetof(CPUTLBDescFast, mask)); - tcg_out_modrm_offset(s, OPC_ADD_GvEv + hrexw, r0, TCG_AREG0, + tcg_out_modrm_offset(s, OPC_ADD_GvEv + hrexw, TCG_REG_L0, TCG_AREG0, TLB_MASK_TABLE_OFS(mem_index) + offsetof(CPUTLBDescFast, table)); @@ -1851,19 +1849,21 @@ static inline void tcg_out_tlb_load(TCGContext *s, TCGReg addrlo, TCGReg addrhi, copy the address and mask. For lesser alignments, check that we don't cross pages for the complete access. */ if (a_bits >= s_bits) { - tcg_out_mov(s, ttype, r1, addrlo); + tcg_out_mov(s, ttype, TCG_REG_L1, addrlo); } else { - tcg_out_modrm_offset(s, OPC_LEA + trexw, r1, addrlo, s_mask - a_mask); + tcg_out_modrm_offset(s, OPC_LEA + trexw, TCG_REG_L1, + addrlo, s_mask - a_mask); } tlb_mask = (target_ulong)TARGET_PAGE_MASK | a_mask; - tgen_arithi(s, ARITH_AND + trexw, r1, tlb_mask, 0); + tgen_arithi(s, ARITH_AND + trexw, TCG_REG_L1, tlb_mask, 0); - /* cmp 0(r0), r1 */ - tcg_out_modrm_offset(s, OPC_CMP_GvEv + trexw, r1, r0, which); + /* cmp 0(TCG_REG_L0), TCG_REG_L1 */ + tcg_out_modrm_offset(s, OPC_CMP_GvEv + trexw, + TCG_REG_L1, TCG_REG_L0, which); /* Prepare for both the fast path add of the tlb addend, and the slow path function argument setup. */ - tcg_out_mov(s, ttype, r1, addrlo); + tcg_out_mov(s, ttype, TCG_REG_L1, addrlo); /* jne slow_path */ tcg_out_opc(s, OPC_JCC_long + JCC_JNE, 0, 0, 0); @@ -1871,8 +1871,8 @@ static inline void tcg_out_tlb_load(TCGContext *s, TCGReg addrlo, TCGReg addrhi, s->code_ptr += 4; if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) { - /* cmp 4(r0), addrhi */ - tcg_out_modrm_offset(s, OPC_CMP_GvEv, addrhi, r0, which + 4); + /* cmp 4(TCG_REG_L0), addrhi */ + tcg_out_modrm_offset(s, OPC_CMP_GvEv, addrhi, TCG_REG_L0, which + 4); /* jne slow_path */ tcg_out_opc(s, OPC_JCC_long + JCC_JNE, 0, 0, 0); @@ -1882,8 +1882,8 @@ static inline void tcg_out_tlb_load(TCGContext *s, TCGReg addrlo, TCGReg addrhi, /* TLB Hit. */ - /* add addend(r0), r1 */ - tcg_out_modrm_offset(s, OPC_ADD_GvEv + hrexw, r1, r0, + /* add addend(TCG_REG_L0), TCG_REG_L1 */ + tcg_out_modrm_offset(s, OPC_ADD_GvEv + hrexw, TCG_REG_L1, TCG_REG_L0, offsetof(CPUTLBEntry, addend)); } From a48f1c7415c22c72faa040b52d34e303cff05b34 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 8 Nov 2022 14:30:27 +1100 Subject: [PATCH 23/42] tcg/i386: Introduce tcg_out_testi MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split out a helper for choosing testb vs testl. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- tcg/i386/tcg-target.c.inc | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc index 78160f453b..aae698121a 100644 --- a/tcg/i386/tcg-target.c.inc +++ b/tcg/i386/tcg-target.c.inc @@ -1751,6 +1751,23 @@ static void tcg_out_nopn(TCGContext *s, int n) tcg_out8(s, 0x90); } +/* Test register R vs immediate bits I, setting Z flag for EQ/NE. */ +static void __attribute__((unused)) +tcg_out_testi(TCGContext *s, TCGReg r, uint32_t i) +{ + /* + * This is used for testing alignment, so we can usually use testb. + * For i686, we have to use testl for %esi/%edi. + */ + if (i <= 0xff && (TCG_TARGET_REG_BITS == 64 || r < 4)) { + tcg_out_modrm(s, OPC_GRP3_Eb | P_REXB_RM, EXT3_TESTi, r); + tcg_out8(s, i); + } else { + tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_TESTi, r); + tcg_out32(s, i); + } +} + typedef struct { TCGReg base; int index; @@ -2051,18 +2068,7 @@ static void tcg_out_test_alignment(TCGContext *s, bool is_ld, TCGReg addrlo, unsigned a_mask = (1 << a_bits) - 1; TCGLabelQemuLdst *label; - /* - * We are expecting a_bits to max out at 7, so we can usually use testb. - * For i686, we have to use testl for %esi/%edi. - */ - if (a_mask <= 0xff && (TCG_TARGET_REG_BITS == 64 || addrlo < 4)) { - tcg_out_modrm(s, OPC_GRP3_Eb | P_REXB_RM, EXT3_TESTi, addrlo); - tcg_out8(s, a_mask); - } else { - tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_TESTi, addrlo); - tcg_out32(s, a_mask); - } - + tcg_out_testi(s, addrlo, a_mask); /* jne slow_path */ tcg_out_opc(s, OPC_JCC_long + JCC_JNE, 0, 0, 0); From ff0cc85ef32c00ddd39a4108a091b1e156939c49 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 6 Apr 2023 12:47:15 -0700 Subject: [PATCH 24/42] tcg/aarch64: Rationalize args to tcg_out_qemu_{ld,st} MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename the 'ext' parameter 'data_type' to make the use clearer; pass it to tcg_out_qemu_st as well to even out the interfaces. Rename the 'otype' local 'addr_type' to make the use clearer. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- tcg/aarch64/tcg-target.c.inc | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc index 4ec3cf3172..ecbf6564fc 100644 --- a/tcg/aarch64/tcg-target.c.inc +++ b/tcg/aarch64/tcg-target.c.inc @@ -1851,22 +1851,21 @@ static void tcg_out_qemu_st_direct(TCGContext *s, MemOp memop, } static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg, - MemOpIdx oi, TCGType ext) + MemOpIdx oi, TCGType data_type) { MemOp memop = get_memop(oi); - const TCGType otype = TARGET_LONG_BITS == 64 ? TCG_TYPE_I64 : TCG_TYPE_I32; + TCGType addr_type = TARGET_LONG_BITS == 64 ? TCG_TYPE_I64 : TCG_TYPE_I32; /* Byte swapping is left to middle-end expansion. */ tcg_debug_assert((memop & MO_BSWAP) == 0); #ifdef CONFIG_SOFTMMU - unsigned mem_index = get_mmuidx(oi); tcg_insn_unit *label_ptr; - tcg_out_tlb_read(s, addr_reg, memop, &label_ptr, mem_index, 1); - tcg_out_qemu_ld_direct(s, memop, ext, data_reg, - TCG_REG_X1, otype, addr_reg); - add_qemu_ldst_label(s, true, oi, ext, data_reg, addr_reg, + tcg_out_tlb_read(s, addr_reg, memop, &label_ptr, get_mmuidx(oi), 1); + tcg_out_qemu_ld_direct(s, memop, data_type, data_reg, + TCG_REG_X1, addr_type, addr_reg); + add_qemu_ldst_label(s, true, oi, data_type, data_reg, addr_reg, s->code_ptr, label_ptr); #else /* !CONFIG_SOFTMMU */ unsigned a_bits = get_alignment_bits(memop); @@ -1874,33 +1873,32 @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg, tcg_out_test_alignment(s, true, addr_reg, a_bits); } if (USE_GUEST_BASE) { - tcg_out_qemu_ld_direct(s, memop, ext, data_reg, - TCG_REG_GUEST_BASE, otype, addr_reg); + tcg_out_qemu_ld_direct(s, memop, data_type, data_reg, + TCG_REG_GUEST_BASE, addr_type, addr_reg); } else { - tcg_out_qemu_ld_direct(s, memop, ext, data_reg, + tcg_out_qemu_ld_direct(s, memop, data_type, data_reg, addr_reg, TCG_TYPE_I64, TCG_REG_XZR); } #endif /* CONFIG_SOFTMMU */ } static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg, - MemOpIdx oi) + MemOpIdx oi, TCGType data_type) { MemOp memop = get_memop(oi); - const TCGType otype = TARGET_LONG_BITS == 64 ? TCG_TYPE_I64 : TCG_TYPE_I32; + TCGType addr_type = TARGET_LONG_BITS == 64 ? TCG_TYPE_I64 : TCG_TYPE_I32; /* Byte swapping is left to middle-end expansion. */ tcg_debug_assert((memop & MO_BSWAP) == 0); #ifdef CONFIG_SOFTMMU - unsigned mem_index = get_mmuidx(oi); tcg_insn_unit *label_ptr; - tcg_out_tlb_read(s, addr_reg, memop, &label_ptr, mem_index, 0); + tcg_out_tlb_read(s, addr_reg, memop, &label_ptr, get_mmuidx(oi), 0); tcg_out_qemu_st_direct(s, memop, data_reg, - TCG_REG_X1, otype, addr_reg); - add_qemu_ldst_label(s, false, oi, (memop & MO_SIZE)== MO_64, - data_reg, addr_reg, s->code_ptr, label_ptr); + TCG_REG_X1, addr_type, addr_reg); + add_qemu_ldst_label(s, false, oi, data_type, data_reg, addr_reg, + s->code_ptr, label_ptr); #else /* !CONFIG_SOFTMMU */ unsigned a_bits = get_alignment_bits(memop); if (a_bits) { @@ -1908,7 +1906,7 @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg, } if (USE_GUEST_BASE) { tcg_out_qemu_st_direct(s, memop, data_reg, - TCG_REG_GUEST_BASE, otype, addr_reg); + TCG_REG_GUEST_BASE, addr_type, addr_reg); } else { tcg_out_qemu_st_direct(s, memop, data_reg, addr_reg, TCG_TYPE_I64, TCG_REG_XZR); @@ -2249,7 +2247,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, break; case INDEX_op_qemu_st_i32: case INDEX_op_qemu_st_i64: - tcg_out_qemu_st(s, REG0(0), a1, a2); + tcg_out_qemu_st(s, REG0(0), a1, a2, ext); break; case INDEX_op_bswap64_i64: From 7f65be51b65ae9a4e65b3de233b5fa069c67faf6 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 21 Apr 2023 09:52:25 +0100 Subject: [PATCH 25/42] tcg/aarch64: Introduce HostAddress MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Collect the 3 potential parts of the host address into a struct. Reorg tcg_out_qemu_{ld,st}_direct to use it. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- tcg/aarch64/tcg-target.c.inc | 86 +++++++++++++++++++++++++----------- 1 file changed, 59 insertions(+), 27 deletions(-) diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc index ecbf6564fc..d8d464e4a0 100644 --- a/tcg/aarch64/tcg-target.c.inc +++ b/tcg/aarch64/tcg-target.c.inc @@ -1587,6 +1587,12 @@ static void tcg_out_adr(TCGContext *s, TCGReg rd, const void *target) tcg_out_insn(s, 3406, ADR, rd, offset); } +typedef struct { + TCGReg base; + TCGReg index; + TCGType index_ext; +} HostAddress; + #ifdef CONFIG_SOFTMMU /* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr, * MemOpIdx oi, uintptr_t ra) @@ -1796,32 +1802,31 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l) #endif /* CONFIG_SOFTMMU */ static void tcg_out_qemu_ld_direct(TCGContext *s, MemOp memop, TCGType ext, - TCGReg data_r, TCGReg addr_r, - TCGType otype, TCGReg off_r) + TCGReg data_r, HostAddress h) { switch (memop & MO_SSIZE) { case MO_UB: - tcg_out_ldst_r(s, I3312_LDRB, data_r, addr_r, otype, off_r); + tcg_out_ldst_r(s, I3312_LDRB, data_r, h.base, h.index_ext, h.index); break; case MO_SB: tcg_out_ldst_r(s, ext ? I3312_LDRSBX : I3312_LDRSBW, - data_r, addr_r, otype, off_r); + data_r, h.base, h.index_ext, h.index); break; case MO_UW: - tcg_out_ldst_r(s, I3312_LDRH, data_r, addr_r, otype, off_r); + tcg_out_ldst_r(s, I3312_LDRH, data_r, h.base, h.index_ext, h.index); break; case MO_SW: tcg_out_ldst_r(s, (ext ? I3312_LDRSHX : I3312_LDRSHW), - data_r, addr_r, otype, off_r); + data_r, h.base, h.index_ext, h.index); break; case MO_UL: - tcg_out_ldst_r(s, I3312_LDRW, data_r, addr_r, otype, off_r); + tcg_out_ldst_r(s, I3312_LDRW, data_r, h.base, h.index_ext, h.index); break; case MO_SL: - tcg_out_ldst_r(s, I3312_LDRSWX, data_r, addr_r, otype, off_r); + tcg_out_ldst_r(s, I3312_LDRSWX, data_r, h.base, h.index_ext, h.index); break; case MO_UQ: - tcg_out_ldst_r(s, I3312_LDRX, data_r, addr_r, otype, off_r); + tcg_out_ldst_r(s, I3312_LDRX, data_r, h.base, h.index_ext, h.index); break; default: g_assert_not_reached(); @@ -1829,21 +1834,20 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, MemOp memop, TCGType ext, } static void tcg_out_qemu_st_direct(TCGContext *s, MemOp memop, - TCGReg data_r, TCGReg addr_r, - TCGType otype, TCGReg off_r) + TCGReg data_r, HostAddress h) { switch (memop & MO_SIZE) { case MO_8: - tcg_out_ldst_r(s, I3312_STRB, data_r, addr_r, otype, off_r); + tcg_out_ldst_r(s, I3312_STRB, data_r, h.base, h.index_ext, h.index); break; case MO_16: - tcg_out_ldst_r(s, I3312_STRH, data_r, addr_r, otype, off_r); + tcg_out_ldst_r(s, I3312_STRH, data_r, h.base, h.index_ext, h.index); break; case MO_32: - tcg_out_ldst_r(s, I3312_STRW, data_r, addr_r, otype, off_r); + tcg_out_ldst_r(s, I3312_STRW, data_r, h.base, h.index_ext, h.index); break; case MO_64: - tcg_out_ldst_r(s, I3312_STRX, data_r, addr_r, otype, off_r); + tcg_out_ldst_r(s, I3312_STRX, data_r, h.base, h.index_ext, h.index); break; default: g_assert_not_reached(); @@ -1855,6 +1859,7 @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg, { MemOp memop = get_memop(oi); TCGType addr_type = TARGET_LONG_BITS == 64 ? TCG_TYPE_I64 : TCG_TYPE_I32; + HostAddress h; /* Byte swapping is left to middle-end expansion. */ tcg_debug_assert((memop & MO_BSWAP) == 0); @@ -1863,8 +1868,14 @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg, tcg_insn_unit *label_ptr; tcg_out_tlb_read(s, addr_reg, memop, &label_ptr, get_mmuidx(oi), 1); - tcg_out_qemu_ld_direct(s, memop, data_type, data_reg, - TCG_REG_X1, addr_type, addr_reg); + + h = (HostAddress){ + .base = TCG_REG_X1, + .index = addr_reg, + .index_ext = addr_type + }; + tcg_out_qemu_ld_direct(s, memop, data_type, data_reg, h); + add_qemu_ldst_label(s, true, oi, data_type, data_reg, addr_reg, s->code_ptr, label_ptr); #else /* !CONFIG_SOFTMMU */ @@ -1873,12 +1884,19 @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg, tcg_out_test_alignment(s, true, addr_reg, a_bits); } if (USE_GUEST_BASE) { - tcg_out_qemu_ld_direct(s, memop, data_type, data_reg, - TCG_REG_GUEST_BASE, addr_type, addr_reg); + h = (HostAddress){ + .base = TCG_REG_GUEST_BASE, + .index = addr_reg, + .index_ext = addr_type + }; } else { - tcg_out_qemu_ld_direct(s, memop, data_type, data_reg, - addr_reg, TCG_TYPE_I64, TCG_REG_XZR); + h = (HostAddress){ + .base = addr_reg, + .index = TCG_REG_XZR, + .index_ext = TCG_TYPE_I64 + }; } + tcg_out_qemu_ld_direct(s, memop, data_type, data_reg, h); #endif /* CONFIG_SOFTMMU */ } @@ -1887,6 +1905,7 @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg, { MemOp memop = get_memop(oi); TCGType addr_type = TARGET_LONG_BITS == 64 ? TCG_TYPE_I64 : TCG_TYPE_I32; + HostAddress h; /* Byte swapping is left to middle-end expansion. */ tcg_debug_assert((memop & MO_BSWAP) == 0); @@ -1895,8 +1914,14 @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg, tcg_insn_unit *label_ptr; tcg_out_tlb_read(s, addr_reg, memop, &label_ptr, get_mmuidx(oi), 0); - tcg_out_qemu_st_direct(s, memop, data_reg, - TCG_REG_X1, addr_type, addr_reg); + + h = (HostAddress){ + .base = TCG_REG_X1, + .index = addr_reg, + .index_ext = addr_type + }; + tcg_out_qemu_st_direct(s, memop, data_reg, h); + add_qemu_ldst_label(s, false, oi, data_type, data_reg, addr_reg, s->code_ptr, label_ptr); #else /* !CONFIG_SOFTMMU */ @@ -1905,12 +1930,19 @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg, tcg_out_test_alignment(s, false, addr_reg, a_bits); } if (USE_GUEST_BASE) { - tcg_out_qemu_st_direct(s, memop, data_reg, - TCG_REG_GUEST_BASE, addr_type, addr_reg); + h = (HostAddress){ + .base = TCG_REG_GUEST_BASE, + .index = addr_reg, + .index_ext = addr_type + }; } else { - tcg_out_qemu_st_direct(s, memop, data_reg, - addr_reg, TCG_TYPE_I64, TCG_REG_XZR); + h = (HostAddress){ + .base = addr_reg, + .index = TCG_REG_XZR, + .index_ext = TCG_TYPE_I64 + }; } + tcg_out_qemu_st_direct(s, memop, data_reg, h); #endif /* CONFIG_SOFTMMU */ } From 737fb471ededa05e9e8bbd800c9f19b5af38cdc5 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 6 Apr 2023 12:51:01 -0700 Subject: [PATCH 26/42] tcg/arm: Rationalize args to tcg_out_qemu_{ld,st} MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Interpret the variable argument placement in the caller. Pass data_type instead of is_64. We need to set this in TCGLabelQemuLdst, so plumb this all the way through from tcg_out_op. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- tcg/arm/tcg-target.c.inc | 113 +++++++++++++++++++-------------------- 1 file changed, 56 insertions(+), 57 deletions(-) diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc index 83c818a58b..6ce52b9612 100644 --- a/tcg/arm/tcg-target.c.inc +++ b/tcg/arm/tcg-target.c.inc @@ -1526,15 +1526,18 @@ static TCGReg tcg_out_tlb_read(TCGContext *s, TCGReg addrlo, TCGReg addrhi, /* Record the context of a call to the out of line helper code for the slow path for a load or store, so that we can later generate the correct helper code. */ -static void add_qemu_ldst_label(TCGContext *s, bool is_ld, MemOpIdx oi, - TCGReg datalo, TCGReg datahi, TCGReg addrlo, - TCGReg addrhi, tcg_insn_unit *raddr, +static void add_qemu_ldst_label(TCGContext *s, bool is_ld, + MemOpIdx oi, TCGType type, + TCGReg datalo, TCGReg datahi, + TCGReg addrlo, TCGReg addrhi, + tcg_insn_unit *raddr, tcg_insn_unit *label_ptr) { TCGLabelQemuLdst *label = new_ldst_label(s); label->is_ld = is_ld; label->oi = oi; + label->type = type; label->datalo_reg = datalo; label->datahi_reg = datahi; label->addrlo_reg = addrlo; @@ -1796,41 +1799,28 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, MemOp opc, TCGReg datalo, } #endif -static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64) +static void tcg_out_qemu_ld(TCGContext *s, TCGReg datalo, TCGReg datahi, + TCGReg addrlo, TCGReg addrhi, + MemOpIdx oi, TCGType data_type) { - TCGReg addrlo, datalo, datahi, addrhi __attribute__((unused)); - MemOpIdx oi; - MemOp opc; -#ifdef CONFIG_SOFTMMU - int mem_index; - TCGReg addend; - tcg_insn_unit *label_ptr; -#else - unsigned a_bits; -#endif - - datalo = *args++; - datahi = (is64 ? *args++ : 0); - addrlo = *args++; - addrhi = (TARGET_LONG_BITS == 64 ? *args++ : 0); - oi = *args++; - opc = get_memop(oi); + MemOp opc = get_memop(oi); #ifdef CONFIG_SOFTMMU - mem_index = get_mmuidx(oi); - addend = tcg_out_tlb_read(s, addrlo, addrhi, opc, mem_index, 1); + TCGReg addend= tcg_out_tlb_read(s, addrlo, addrhi, opc, get_mmuidx(oi), 1); - /* This a conditional BL only to load a pointer within this opcode into LR - for the slow path. We will not be using the value for a tail call. */ - label_ptr = s->code_ptr; + /* + * This a conditional BL only to load a pointer within this opcode into + * LR for the slow path. We will not be using the value for a tail call. + */ + tcg_insn_unit *label_ptr = s->code_ptr; tcg_out_bl_imm(s, COND_NE, 0); tcg_out_qemu_ld_index(s, opc, datalo, datahi, addrlo, addend, true); - add_qemu_ldst_label(s, true, oi, datalo, datahi, addrlo, addrhi, - s->code_ptr, label_ptr); + add_qemu_ldst_label(s, true, oi, data_type, datalo, datahi, + addrlo, addrhi, s->code_ptr, label_ptr); #else /* !CONFIG_SOFTMMU */ - a_bits = get_alignment_bits(opc); + unsigned a_bits = get_alignment_bits(opc); if (a_bits) { tcg_out_test_alignment(s, true, addrlo, addrhi, a_bits); } @@ -1918,41 +1908,26 @@ static void tcg_out_qemu_st_direct(TCGContext *s, MemOp opc, TCGReg datalo, } #endif -static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is64) +static void tcg_out_qemu_st(TCGContext *s, TCGReg datalo, TCGReg datahi, + TCGReg addrlo, TCGReg addrhi, + MemOpIdx oi, TCGType data_type) { - TCGReg addrlo, datalo, datahi, addrhi __attribute__((unused)); - MemOpIdx oi; - MemOp opc; -#ifdef CONFIG_SOFTMMU - int mem_index; - TCGReg addend; - tcg_insn_unit *label_ptr; -#else - unsigned a_bits; -#endif - - datalo = *args++; - datahi = (is64 ? *args++ : 0); - addrlo = *args++; - addrhi = (TARGET_LONG_BITS == 64 ? *args++ : 0); - oi = *args++; - opc = get_memop(oi); + MemOp opc = get_memop(oi); #ifdef CONFIG_SOFTMMU - mem_index = get_mmuidx(oi); - addend = tcg_out_tlb_read(s, addrlo, addrhi, opc, mem_index, 0); + TCGReg addend = tcg_out_tlb_read(s, addrlo, addrhi, opc, get_mmuidx(oi), 0); tcg_out_qemu_st_index(s, COND_EQ, opc, datalo, datahi, addrlo, addend, true); /* The conditional call must come last, as we're going to return here. */ - label_ptr = s->code_ptr; + tcg_insn_unit *label_ptr = s->code_ptr; tcg_out_bl_imm(s, COND_NE, 0); - add_qemu_ldst_label(s, false, oi, datalo, datahi, addrlo, addrhi, - s->code_ptr, label_ptr); + add_qemu_ldst_label(s, false, oi, data_type, datalo, datahi, + addrlo, addrhi, s->code_ptr, label_ptr); #else /* !CONFIG_SOFTMMU */ - a_bits = get_alignment_bits(opc); + unsigned a_bits = get_alignment_bits(opc); if (a_bits) { tcg_out_test_alignment(s, false, addrlo, addrhi, a_bits); } @@ -2245,16 +2220,40 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, break; case INDEX_op_qemu_ld_i32: - tcg_out_qemu_ld(s, args, 0); + if (TARGET_LONG_BITS == 32) { + tcg_out_qemu_ld(s, args[0], -1, args[1], -1, + args[2], TCG_TYPE_I32); + } else { + tcg_out_qemu_ld(s, args[0], -1, args[1], args[2], + args[3], TCG_TYPE_I32); + } break; case INDEX_op_qemu_ld_i64: - tcg_out_qemu_ld(s, args, 1); + if (TARGET_LONG_BITS == 32) { + tcg_out_qemu_ld(s, args[0], args[1], args[2], -1, + args[3], TCG_TYPE_I64); + } else { + tcg_out_qemu_ld(s, args[0], args[1], args[2], args[3], + args[4], TCG_TYPE_I64); + } break; case INDEX_op_qemu_st_i32: - tcg_out_qemu_st(s, args, 0); + if (TARGET_LONG_BITS == 32) { + tcg_out_qemu_st(s, args[0], -1, args[1], -1, + args[2], TCG_TYPE_I32); + } else { + tcg_out_qemu_st(s, args[0], -1, args[1], args[2], + args[3], TCG_TYPE_I32); + } break; case INDEX_op_qemu_st_i64: - tcg_out_qemu_st(s, args, 1); + if (TARGET_LONG_BITS == 32) { + tcg_out_qemu_st(s, args[0], args[1], args[2], -1, + args[3], TCG_TYPE_I64); + } else { + tcg_out_qemu_st(s, args[0], args[1], args[2], args[3], + args[4], TCG_TYPE_I64); + } break; case INDEX_op_bswap16_i32: From 1df6d611bdc2f019ed1ddfcda7448b00910029a8 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 22 Apr 2023 05:32:22 +0100 Subject: [PATCH 27/42] tcg/arm: Introduce HostAddress Collect the parts of the host address, and condition, into a struct. Merge tcg_out_qemu_*_{index,direct} and use it. Signed-off-by: Richard Henderson --- tcg/arm/tcg-target.c.inc | 248 ++++++++++++++++++--------------------- 1 file changed, 115 insertions(+), 133 deletions(-) diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc index 6ce52b9612..b6b4ffc546 100644 --- a/tcg/arm/tcg-target.c.inc +++ b/tcg/arm/tcg-target.c.inc @@ -1337,6 +1337,13 @@ static void tcg_out_vldst(TCGContext *s, ARMInsn insn, tcg_out32(s, insn | (rn << 16) | encode_vd(rd) | 0xf); } +typedef struct { + ARMCond cond; + TCGReg base; + int index; + bool index_scratch; +} HostAddress; + #ifdef CONFIG_SOFTMMU /* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr, * int mmu_idx, uintptr_t ra) @@ -1696,29 +1703,49 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l) } #endif /* SOFTMMU */ -static void tcg_out_qemu_ld_index(TCGContext *s, MemOp opc, - TCGReg datalo, TCGReg datahi, - TCGReg addrlo, TCGReg addend, - bool scratch_addend) +static void tcg_out_qemu_ld_direct(TCGContext *s, MemOp opc, TCGReg datalo, + TCGReg datahi, HostAddress h) { + TCGReg base; + /* Byte swapping is left to middle-end expansion. */ tcg_debug_assert((opc & MO_BSWAP) == 0); switch (opc & MO_SSIZE) { case MO_UB: - tcg_out_ld8_r(s, COND_AL, datalo, addrlo, addend); + if (h.index < 0) { + tcg_out_ld8_12(s, h.cond, datalo, h.base, 0); + } else { + tcg_out_ld8_r(s, h.cond, datalo, h.base, h.index); + } break; case MO_SB: - tcg_out_ld8s_r(s, COND_AL, datalo, addrlo, addend); + if (h.index < 0) { + tcg_out_ld8s_8(s, h.cond, datalo, h.base, 0); + } else { + tcg_out_ld8s_r(s, h.cond, datalo, h.base, h.index); + } break; case MO_UW: - tcg_out_ld16u_r(s, COND_AL, datalo, addrlo, addend); + if (h.index < 0) { + tcg_out_ld16u_8(s, h.cond, datalo, h.base, 0); + } else { + tcg_out_ld16u_r(s, h.cond, datalo, h.base, h.index); + } break; case MO_SW: - tcg_out_ld16s_r(s, COND_AL, datalo, addrlo, addend); + if (h.index < 0) { + tcg_out_ld16s_8(s, h.cond, datalo, h.base, 0); + } else { + tcg_out_ld16s_r(s, h.cond, datalo, h.base, h.index); + } break; case MO_UL: - tcg_out_ld32_r(s, COND_AL, datalo, addrlo, addend); + if (h.index < 0) { + tcg_out_ld32_12(s, h.cond, datalo, h.base, 0); + } else { + tcg_out_ld32_r(s, h.cond, datalo, h.base, h.index); + } break; case MO_UQ: /* We used pair allocation for datalo, so already should be aligned. */ @@ -1726,87 +1753,59 @@ static void tcg_out_qemu_ld_index(TCGContext *s, MemOp opc, tcg_debug_assert(datahi == datalo + 1); /* LDRD requires alignment; double-check that. */ if (get_alignment_bits(opc) >= MO_64) { + if (h.index < 0) { + tcg_out_ldrd_8(s, h.cond, datalo, h.base, 0); + break; + } /* * Rm (the second address op) must not overlap Rt or Rt + 1. * Since datalo is aligned, we can simplify the test via alignment. * Flip the two address arguments if that works. */ - if ((addend & ~1) != datalo) { - tcg_out_ldrd_r(s, COND_AL, datalo, addrlo, addend); + if ((h.index & ~1) != datalo) { + tcg_out_ldrd_r(s, h.cond, datalo, h.base, h.index); break; } - if ((addrlo & ~1) != datalo) { - tcg_out_ldrd_r(s, COND_AL, datalo, addend, addrlo); + if ((h.base & ~1) != datalo) { + tcg_out_ldrd_r(s, h.cond, datalo, h.index, h.base); break; } } - if (scratch_addend) { - tcg_out_ld32_rwb(s, COND_AL, datalo, addend, addrlo); - tcg_out_ld32_12(s, COND_AL, datahi, addend, 4); + if (h.index < 0) { + base = h.base; + if (datalo == h.base) { + tcg_out_mov_reg(s, h.cond, TCG_REG_TMP, base); + base = TCG_REG_TMP; + } + } else if (h.index_scratch) { + tcg_out_ld32_rwb(s, h.cond, datalo, h.index, h.base); + tcg_out_ld32_12(s, h.cond, datahi, h.index, 4); + break; } else { - tcg_out_dat_reg(s, COND_AL, ARITH_ADD, TCG_REG_TMP, - addend, addrlo, SHIFT_IMM_LSL(0)); - tcg_out_ld32_12(s, COND_AL, datalo, TCG_REG_TMP, 0); - tcg_out_ld32_12(s, COND_AL, datahi, TCG_REG_TMP, 4); + tcg_out_dat_reg(s, h.cond, ARITH_ADD, TCG_REG_TMP, + h.base, h.index, SHIFT_IMM_LSL(0)); + base = TCG_REG_TMP; } + tcg_out_ld32_12(s, h.cond, datalo, base, 0); + tcg_out_ld32_12(s, h.cond, datahi, base, 4); break; default: g_assert_not_reached(); } } -#ifndef CONFIG_SOFTMMU -static void tcg_out_qemu_ld_direct(TCGContext *s, MemOp opc, TCGReg datalo, - TCGReg datahi, TCGReg addrlo) -{ - /* Byte swapping is left to middle-end expansion. */ - tcg_debug_assert((opc & MO_BSWAP) == 0); - - switch (opc & MO_SSIZE) { - case MO_UB: - tcg_out_ld8_12(s, COND_AL, datalo, addrlo, 0); - break; - case MO_SB: - tcg_out_ld8s_8(s, COND_AL, datalo, addrlo, 0); - break; - case MO_UW: - tcg_out_ld16u_8(s, COND_AL, datalo, addrlo, 0); - break; - case MO_SW: - tcg_out_ld16s_8(s, COND_AL, datalo, addrlo, 0); - break; - case MO_UL: - tcg_out_ld32_12(s, COND_AL, datalo, addrlo, 0); - break; - case MO_UQ: - /* We used pair allocation for datalo, so already should be aligned. */ - tcg_debug_assert((datalo & 1) == 0); - tcg_debug_assert(datahi == datalo + 1); - /* LDRD requires alignment; double-check that. */ - if (get_alignment_bits(opc) >= MO_64) { - tcg_out_ldrd_8(s, COND_AL, datalo, addrlo, 0); - } else if (datalo == addrlo) { - tcg_out_ld32_12(s, COND_AL, datahi, addrlo, 4); - tcg_out_ld32_12(s, COND_AL, datalo, addrlo, 0); - } else { - tcg_out_ld32_12(s, COND_AL, datalo, addrlo, 0); - tcg_out_ld32_12(s, COND_AL, datahi, addrlo, 4); - } - break; - default: - g_assert_not_reached(); - } -} -#endif - static void tcg_out_qemu_ld(TCGContext *s, TCGReg datalo, TCGReg datahi, TCGReg addrlo, TCGReg addrhi, MemOpIdx oi, TCGType data_type) { MemOp opc = get_memop(oi); + HostAddress h; #ifdef CONFIG_SOFTMMU - TCGReg addend= tcg_out_tlb_read(s, addrlo, addrhi, opc, get_mmuidx(oi), 1); + h.cond = COND_AL; + h.base = addrlo; + h.index_scratch = true; + h.index = tcg_out_tlb_read(s, addrlo, addrhi, opc, get_mmuidx(oi), 1); /* * This a conditional BL only to load a pointer within this opcode into @@ -1815,80 +1814,51 @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg datalo, TCGReg datahi, tcg_insn_unit *label_ptr = s->code_ptr; tcg_out_bl_imm(s, COND_NE, 0); - tcg_out_qemu_ld_index(s, opc, datalo, datahi, addrlo, addend, true); + tcg_out_qemu_ld_direct(s, opc, datalo, datahi, h); add_qemu_ldst_label(s, true, oi, data_type, datalo, datahi, addrlo, addrhi, s->code_ptr, label_ptr); -#else /* !CONFIG_SOFTMMU */ +#else unsigned a_bits = get_alignment_bits(opc); if (a_bits) { tcg_out_test_alignment(s, true, addrlo, addrhi, a_bits); } - if (guest_base) { - tcg_out_qemu_ld_index(s, opc, datalo, datahi, - addrlo, TCG_REG_GUEST_BASE, false); - } else { - tcg_out_qemu_ld_direct(s, opc, datalo, datahi, addrlo); - } + + h.cond = COND_AL; + h.base = addrlo; + h.index = guest_base ? TCG_REG_GUEST_BASE : -1; + h.index_scratch = false; + tcg_out_qemu_ld_direct(s, opc, datalo, datahi, h); #endif } -static void tcg_out_qemu_st_index(TCGContext *s, ARMCond cond, MemOp opc, - TCGReg datalo, TCGReg datahi, - TCGReg addrlo, TCGReg addend, - bool scratch_addend) -{ - /* Byte swapping is left to middle-end expansion. */ - tcg_debug_assert((opc & MO_BSWAP) == 0); - - switch (opc & MO_SIZE) { - case MO_8: - tcg_out_st8_r(s, cond, datalo, addrlo, addend); - break; - case MO_16: - tcg_out_st16_r(s, cond, datalo, addrlo, addend); - break; - case MO_32: - tcg_out_st32_r(s, cond, datalo, addrlo, addend); - break; - case MO_64: - /* We used pair allocation for datalo, so already should be aligned. */ - tcg_debug_assert((datalo & 1) == 0); - tcg_debug_assert(datahi == datalo + 1); - /* STRD requires alignment; double-check that. */ - if (get_alignment_bits(opc) >= MO_64) { - tcg_out_strd_r(s, cond, datalo, addrlo, addend); - } else if (scratch_addend) { - tcg_out_st32_rwb(s, cond, datalo, addend, addrlo); - tcg_out_st32_12(s, cond, datahi, addend, 4); - } else { - tcg_out_dat_reg(s, cond, ARITH_ADD, TCG_REG_TMP, - addend, addrlo, SHIFT_IMM_LSL(0)); - tcg_out_st32_12(s, cond, datalo, TCG_REG_TMP, 0); - tcg_out_st32_12(s, cond, datahi, TCG_REG_TMP, 4); - } - break; - default: - g_assert_not_reached(); - } -} - -#ifndef CONFIG_SOFTMMU static void tcg_out_qemu_st_direct(TCGContext *s, MemOp opc, TCGReg datalo, - TCGReg datahi, TCGReg addrlo) + TCGReg datahi, HostAddress h) { /* Byte swapping is left to middle-end expansion. */ tcg_debug_assert((opc & MO_BSWAP) == 0); switch (opc & MO_SIZE) { case MO_8: - tcg_out_st8_12(s, COND_AL, datalo, addrlo, 0); + if (h.index < 0) { + tcg_out_st8_12(s, h.cond, datalo, h.base, 0); + } else { + tcg_out_st8_r(s, h.cond, datalo, h.base, h.index); + } break; case MO_16: - tcg_out_st16_8(s, COND_AL, datalo, addrlo, 0); + if (h.index < 0) { + tcg_out_st16_8(s, h.cond, datalo, h.base, 0); + } else { + tcg_out_st16_r(s, h.cond, datalo, h.base, h.index); + } break; case MO_32: - tcg_out_st32_12(s, COND_AL, datalo, addrlo, 0); + if (h.index < 0) { + tcg_out_st32_12(s, h.cond, datalo, h.base, 0); + } else { + tcg_out_st32_r(s, h.cond, datalo, h.base, h.index); + } break; case MO_64: /* We used pair allocation for datalo, so already should be aligned. */ @@ -1896,29 +1866,39 @@ static void tcg_out_qemu_st_direct(TCGContext *s, MemOp opc, TCGReg datalo, tcg_debug_assert(datahi == datalo + 1); /* STRD requires alignment; double-check that. */ if (get_alignment_bits(opc) >= MO_64) { - tcg_out_strd_8(s, COND_AL, datalo, addrlo, 0); + if (h.index < 0) { + tcg_out_strd_8(s, h.cond, datalo, h.base, 0); + } else { + tcg_out_strd_r(s, h.cond, datalo, h.base, h.index); + } + } else if (h.index_scratch) { + tcg_out_st32_rwb(s, h.cond, datalo, h.index, h.base); + tcg_out_st32_12(s, h.cond, datahi, h.index, 4); } else { - tcg_out_st32_12(s, COND_AL, datalo, addrlo, 0); - tcg_out_st32_12(s, COND_AL, datahi, addrlo, 4); + tcg_out_dat_reg(s, h.cond, ARITH_ADD, TCG_REG_TMP, + h.base, h.index, SHIFT_IMM_LSL(0)); + tcg_out_st32_12(s, h.cond, datalo, TCG_REG_TMP, 0); + tcg_out_st32_12(s, h.cond, datahi, TCG_REG_TMP, 4); } break; default: g_assert_not_reached(); } } -#endif static void tcg_out_qemu_st(TCGContext *s, TCGReg datalo, TCGReg datahi, TCGReg addrlo, TCGReg addrhi, MemOpIdx oi, TCGType data_type) { MemOp opc = get_memop(oi); + HostAddress h; #ifdef CONFIG_SOFTMMU - TCGReg addend = tcg_out_tlb_read(s, addrlo, addrhi, opc, get_mmuidx(oi), 0); - - tcg_out_qemu_st_index(s, COND_EQ, opc, datalo, datahi, - addrlo, addend, true); + h.cond = COND_EQ; + h.base = addrlo; + h.index_scratch = true; + h.index = tcg_out_tlb_read(s, addrlo, addrhi, opc, get_mmuidx(oi), 0); + tcg_out_qemu_st_direct(s, opc, datalo, datahi, h); /* The conditional call must come last, as we're going to return here. */ tcg_insn_unit *label_ptr = s->code_ptr; @@ -1926,17 +1906,19 @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg datalo, TCGReg datahi, add_qemu_ldst_label(s, false, oi, data_type, datalo, datahi, addrlo, addrhi, s->code_ptr, label_ptr); -#else /* !CONFIG_SOFTMMU */ +#else unsigned a_bits = get_alignment_bits(opc); + + h.cond = COND_AL; if (a_bits) { tcg_out_test_alignment(s, false, addrlo, addrhi, a_bits); + h.cond = COND_EQ; } - if (guest_base) { - tcg_out_qemu_st_index(s, COND_AL, opc, datalo, datahi, - addrlo, TCG_REG_GUEST_BASE, false); - } else { - tcg_out_qemu_st_direct(s, opc, datalo, datahi, addrlo); - } + + h.base = addrlo; + h.index = guest_base ? TCG_REG_GUEST_BASE : -1; + h.index_scratch = false; + tcg_out_qemu_st_direct(s, opc, datalo, datahi, h); #endif } From 7f67e58236d7e52e7249789250a03eaabf96f936 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 8 Apr 2023 15:13:04 -0700 Subject: [PATCH 28/42] tcg/loongarch64: Rationalize args to tcg_out_qemu_{ld,st} MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Interpret the variable argument placement in the caller. Shift some code around slightly to share more between softmmu and user-only. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- tcg/loongarch64/tcg-target.c.inc | 100 +++++++++++++------------------ 1 file changed, 42 insertions(+), 58 deletions(-) diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc index 0940788c6f..2e3c67054b 100644 --- a/tcg/loongarch64/tcg-target.c.inc +++ b/tcg/loongarch64/tcg-target.c.inc @@ -1049,39 +1049,31 @@ static void tcg_out_qemu_ld_indexed(TCGContext *s, TCGReg rd, TCGReg rj, } } -static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, TCGType type) +static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg, + MemOpIdx oi, TCGType data_type) { - TCGReg addr_regl; - TCGReg data_regl; - MemOpIdx oi; - MemOp opc; -#if defined(CONFIG_SOFTMMU) + MemOp opc = get_memop(oi); + TCGReg base, index; + +#ifdef CONFIG_SOFTMMU tcg_insn_unit *label_ptr[1]; -#else - unsigned a_bits; -#endif - TCGReg base; - data_regl = *args++; - addr_regl = *args++; - oi = *args++; - opc = get_memop(oi); - -#if defined(CONFIG_SOFTMMU) - tcg_out_tlb_load(s, addr_regl, oi, label_ptr, 1); - base = tcg_out_zext_addr_if_32_bit(s, addr_regl, TCG_REG_TMP0); - tcg_out_qemu_ld_indexed(s, data_regl, base, TCG_REG_TMP2, opc, type); - add_qemu_ldst_label(s, 1, oi, type, - data_regl, addr_regl, - s->code_ptr, label_ptr); + tcg_out_tlb_load(s, addr_reg, oi, label_ptr, 1); + index = TCG_REG_TMP2; #else - a_bits = get_alignment_bits(opc); + unsigned a_bits = get_alignment_bits(opc); if (a_bits) { - tcg_out_test_alignment(s, true, addr_regl, a_bits); + tcg_out_test_alignment(s, true, addr_reg, a_bits); } - base = tcg_out_zext_addr_if_32_bit(s, addr_regl, TCG_REG_TMP0); - TCGReg guest_base_reg = USE_GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_ZERO; - tcg_out_qemu_ld_indexed(s, data_regl, base, guest_base_reg, opc, type); + index = USE_GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_ZERO; +#endif + + base = tcg_out_zext_addr_if_32_bit(s, addr_reg, TCG_REG_TMP0); + tcg_out_qemu_ld_indexed(s, data_reg, base, index, opc, data_type); + +#ifdef CONFIG_SOFTMMU + add_qemu_ldst_label(s, true, oi, data_type, data_reg, addr_reg, + s->code_ptr, label_ptr); #endif } @@ -1109,39 +1101,31 @@ static void tcg_out_qemu_st_indexed(TCGContext *s, TCGReg data, } } -static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, TCGType type) +static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg, + MemOpIdx oi, TCGType data_type) { - TCGReg addr_regl; - TCGReg data_regl; - MemOpIdx oi; - MemOp opc; -#if defined(CONFIG_SOFTMMU) + MemOp opc = get_memop(oi); + TCGReg base, index; + +#ifdef CONFIG_SOFTMMU tcg_insn_unit *label_ptr[1]; -#else - unsigned a_bits; -#endif - TCGReg base; - data_regl = *args++; - addr_regl = *args++; - oi = *args++; - opc = get_memop(oi); - -#if defined(CONFIG_SOFTMMU) - tcg_out_tlb_load(s, addr_regl, oi, label_ptr, 0); - base = tcg_out_zext_addr_if_32_bit(s, addr_regl, TCG_REG_TMP0); - tcg_out_qemu_st_indexed(s, data_regl, base, TCG_REG_TMP2, opc); - add_qemu_ldst_label(s, 0, oi, type, - data_regl, addr_regl, - s->code_ptr, label_ptr); + tcg_out_tlb_load(s, addr_reg, oi, label_ptr, 0); + index = TCG_REG_TMP2; #else - a_bits = get_alignment_bits(opc); + unsigned a_bits = get_alignment_bits(opc); if (a_bits) { - tcg_out_test_alignment(s, false, addr_regl, a_bits); + tcg_out_test_alignment(s, false, addr_reg, a_bits); } - base = tcg_out_zext_addr_if_32_bit(s, addr_regl, TCG_REG_TMP0); - TCGReg guest_base_reg = USE_GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_ZERO; - tcg_out_qemu_st_indexed(s, data_regl, base, guest_base_reg, opc); + index = USE_GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_ZERO; +#endif + + base = tcg_out_zext_addr_if_32_bit(s, addr_reg, TCG_REG_TMP0); + tcg_out_qemu_st_indexed(s, data_reg, base, index, opc); + +#ifdef CONFIG_SOFTMMU + add_qemu_ldst_label(s, false, oi, data_type, data_reg, addr_reg, + s->code_ptr, label_ptr); #endif } @@ -1564,16 +1548,16 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, break; case INDEX_op_qemu_ld_i32: - tcg_out_qemu_ld(s, args, TCG_TYPE_I32); + tcg_out_qemu_ld(s, a0, a1, a2, TCG_TYPE_I32); break; case INDEX_op_qemu_ld_i64: - tcg_out_qemu_ld(s, args, TCG_TYPE_I64); + tcg_out_qemu_ld(s, a0, a1, a2, TCG_TYPE_I64); break; case INDEX_op_qemu_st_i32: - tcg_out_qemu_st(s, args, TCG_TYPE_I32); + tcg_out_qemu_st(s, a0, a1, a2, TCG_TYPE_I32); break; case INDEX_op_qemu_st_i64: - tcg_out_qemu_st(s, args, TCG_TYPE_I64); + tcg_out_qemu_st(s, a0, a1, a2, TCG_TYPE_I64); break; case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ From 9a2027b7a268dbb2f94c399e7620abd7901eb082 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 23 Apr 2023 16:31:16 +0100 Subject: [PATCH 29/42] tcg/loongarch64: Introduce HostAddress MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Collect the 2 parts of the host address into a struct. Reorg tcg_out_qemu_{ld,st}_direct to use it. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- tcg/loongarch64/tcg-target.c.inc | 55 +++++++++++++++++--------------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc index 2e3c67054b..6a87a5e5a3 100644 --- a/tcg/loongarch64/tcg-target.c.inc +++ b/tcg/loongarch64/tcg-target.c.inc @@ -1013,36 +1013,41 @@ static TCGReg tcg_out_zext_addr_if_32_bit(TCGContext *s, return addr; } -static void tcg_out_qemu_ld_indexed(TCGContext *s, TCGReg rd, TCGReg rj, - TCGReg rk, MemOp opc, TCGType type) +typedef struct { + TCGReg base; + TCGReg index; +} HostAddress; + +static void tcg_out_qemu_ld_indexed(TCGContext *s, MemOp opc, TCGType type, + TCGReg rd, HostAddress h) { /* Byte swapping is left to middle-end expansion. */ tcg_debug_assert((opc & MO_BSWAP) == 0); switch (opc & MO_SSIZE) { case MO_UB: - tcg_out_opc_ldx_bu(s, rd, rj, rk); + tcg_out_opc_ldx_bu(s, rd, h.base, h.index); break; case MO_SB: - tcg_out_opc_ldx_b(s, rd, rj, rk); + tcg_out_opc_ldx_b(s, rd, h.base, h.index); break; case MO_UW: - tcg_out_opc_ldx_hu(s, rd, rj, rk); + tcg_out_opc_ldx_hu(s, rd, h.base, h.index); break; case MO_SW: - tcg_out_opc_ldx_h(s, rd, rj, rk); + tcg_out_opc_ldx_h(s, rd, h.base, h.index); break; case MO_UL: if (type == TCG_TYPE_I64) { - tcg_out_opc_ldx_wu(s, rd, rj, rk); + tcg_out_opc_ldx_wu(s, rd, h.base, h.index); break; } /* fallthrough */ case MO_SL: - tcg_out_opc_ldx_w(s, rd, rj, rk); + tcg_out_opc_ldx_w(s, rd, h.base, h.index); break; case MO_UQ: - tcg_out_opc_ldx_d(s, rd, rj, rk); + tcg_out_opc_ldx_d(s, rd, h.base, h.index); break; default: g_assert_not_reached(); @@ -1053,23 +1058,23 @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg, MemOpIdx oi, TCGType data_type) { MemOp opc = get_memop(oi); - TCGReg base, index; + HostAddress h; #ifdef CONFIG_SOFTMMU tcg_insn_unit *label_ptr[1]; tcg_out_tlb_load(s, addr_reg, oi, label_ptr, 1); - index = TCG_REG_TMP2; + h.index = TCG_REG_TMP2; #else unsigned a_bits = get_alignment_bits(opc); if (a_bits) { tcg_out_test_alignment(s, true, addr_reg, a_bits); } - index = USE_GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_ZERO; + h.index = USE_GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_ZERO; #endif - base = tcg_out_zext_addr_if_32_bit(s, addr_reg, TCG_REG_TMP0); - tcg_out_qemu_ld_indexed(s, data_reg, base, index, opc, data_type); + h.base = tcg_out_zext_addr_if_32_bit(s, addr_reg, TCG_REG_TMP0); + tcg_out_qemu_ld_indexed(s, opc, data_type, data_reg, h); #ifdef CONFIG_SOFTMMU add_qemu_ldst_label(s, true, oi, data_type, data_reg, addr_reg, @@ -1077,24 +1082,24 @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg, #endif } -static void tcg_out_qemu_st_indexed(TCGContext *s, TCGReg data, - TCGReg rj, TCGReg rk, MemOp opc) +static void tcg_out_qemu_st_indexed(TCGContext *s, MemOp opc, + TCGReg rd, HostAddress h) { /* Byte swapping is left to middle-end expansion. */ tcg_debug_assert((opc & MO_BSWAP) == 0); switch (opc & MO_SIZE) { case MO_8: - tcg_out_opc_stx_b(s, data, rj, rk); + tcg_out_opc_stx_b(s, rd, h.base, h.index); break; case MO_16: - tcg_out_opc_stx_h(s, data, rj, rk); + tcg_out_opc_stx_h(s, rd, h.base, h.index); break; case MO_32: - tcg_out_opc_stx_w(s, data, rj, rk); + tcg_out_opc_stx_w(s, rd, h.base, h.index); break; case MO_64: - tcg_out_opc_stx_d(s, data, rj, rk); + tcg_out_opc_stx_d(s, rd, h.base, h.index); break; default: g_assert_not_reached(); @@ -1105,23 +1110,23 @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg, MemOpIdx oi, TCGType data_type) { MemOp opc = get_memop(oi); - TCGReg base, index; + HostAddress h; #ifdef CONFIG_SOFTMMU tcg_insn_unit *label_ptr[1]; tcg_out_tlb_load(s, addr_reg, oi, label_ptr, 0); - index = TCG_REG_TMP2; + h.index = TCG_REG_TMP2; #else unsigned a_bits = get_alignment_bits(opc); if (a_bits) { tcg_out_test_alignment(s, false, addr_reg, a_bits); } - index = USE_GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_ZERO; + h.index = USE_GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_ZERO; #endif - base = tcg_out_zext_addr_if_32_bit(s, addr_reg, TCG_REG_TMP0); - tcg_out_qemu_st_indexed(s, data_reg, base, index, opc); + h.base = tcg_out_zext_addr_if_32_bit(s, addr_reg, TCG_REG_TMP0); + tcg_out_qemu_st_indexed(s, opc, data_reg, h); #ifdef CONFIG_SOFTMMU add_qemu_ldst_label(s, false, oi, data_type, data_reg, addr_reg, From eb664d0c5276a4009530a0e1d5ff6485293bf7e3 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 6 Apr 2023 12:52:26 -0700 Subject: [PATCH 30/42] tcg/mips: Rationalize args to tcg_out_qemu_{ld,st} MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Interpret the variable argument placement in the caller. There are several places where we already convert back from bool to type. Clean things up by using type throughout. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- tcg/mips/tcg-target.c.inc | 186 +++++++++++++++++++------------------- 1 file changed, 95 insertions(+), 91 deletions(-) diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc index a83ebe8729..ef8350e9cd 100644 --- a/tcg/mips/tcg-target.c.inc +++ b/tcg/mips/tcg-target.c.inc @@ -1479,7 +1479,7 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l) #endif /* SOFTMMU */ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg lo, TCGReg hi, - TCGReg base, MemOp opc, bool is_64) + TCGReg base, MemOp opc, TCGType type) { switch (opc & (MO_SSIZE | MO_BSWAP)) { case MO_UB: @@ -1503,7 +1503,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg lo, TCGReg hi, tcg_out_opc_imm(s, OPC_LH, lo, base, 0); break; case MO_UL | MO_BSWAP: - if (TCG_TARGET_REG_BITS == 64 && is_64) { + if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I64) { if (use_mips32r2_instructions) { tcg_out_opc_imm(s, OPC_LWU, lo, base, 0); tcg_out_bswap32(s, lo, lo, TCG_BSWAP_IZ | TCG_BSWAP_OZ); @@ -1528,7 +1528,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg lo, TCGReg hi, } break; case MO_UL: - if (TCG_TARGET_REG_BITS == 64 && is_64) { + if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I64) { tcg_out_opc_imm(s, OPC_LWU, lo, base, 0); break; } @@ -1583,7 +1583,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg lo, TCGReg hi, } static void tcg_out_qemu_ld_unalign(TCGContext *s, TCGReg lo, TCGReg hi, - TCGReg base, MemOp opc, bool is_64) + TCGReg base, MemOp opc, TCGType type) { const MIPSInsn lw1 = MIPS_BE ? OPC_LWL : OPC_LWR; const MIPSInsn lw2 = MIPS_BE ? OPC_LWR : OPC_LWL; @@ -1623,7 +1623,7 @@ static void tcg_out_qemu_ld_unalign(TCGContext *s, TCGReg lo, TCGReg hi, case MO_UL: tcg_out_opc_imm(s, lw1, lo, base, 0); tcg_out_opc_imm(s, lw2, lo, base, 3); - if (TCG_TARGET_REG_BITS == 64 && is_64 && !sgn) { + if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I64 && !sgn) { tcg_out_ext32u(s, lo, lo); } break; @@ -1634,18 +1634,18 @@ static void tcg_out_qemu_ld_unalign(TCGContext *s, TCGReg lo, TCGReg hi, tcg_out_opc_imm(s, lw1, lo, base, 0); tcg_out_opc_imm(s, lw2, lo, base, 3); tcg_out_bswap32(s, lo, lo, - TCG_TARGET_REG_BITS == 64 && is_64 + TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I64 ? (sgn ? TCG_BSWAP_OS : TCG_BSWAP_OZ) : 0); } else { const tcg_insn_unit *subr = - (TCG_TARGET_REG_BITS == 64 && is_64 && !sgn + (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I64 && !sgn ? bswap32u_addr : bswap32_addr); tcg_out_opc_imm(s, lw1, TCG_TMP0, base, 0); tcg_out_bswap_subr(s, subr); /* delay slot */ tcg_out_opc_imm(s, lw2, TCG_TMP0, base, 3); - tcg_out_mov(s, is_64 ? TCG_TYPE_I64 : TCG_TYPE_I32, lo, TCG_TMP3); + tcg_out_mov(s, type, lo, TCG_TMP3); } break; @@ -1702,68 +1702,59 @@ static void tcg_out_qemu_ld_unalign(TCGContext *s, TCGReg lo, TCGReg hi, } } -static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is_64) +static void tcg_out_qemu_ld(TCGContext *s, TCGReg datalo, TCGReg datahi, + TCGReg addrlo, TCGReg addrhi, + MemOpIdx oi, TCGType data_type) { - TCGReg addr_regl, addr_regh __attribute__((unused)); - TCGReg data_regl, data_regh; - MemOpIdx oi; - MemOp opc; -#if defined(CONFIG_SOFTMMU) - tcg_insn_unit *label_ptr[2]; -#else -#endif - unsigned a_bits, s_bits; - TCGReg base = TCG_REG_A0; - - data_regl = *args++; - data_regh = (TCG_TARGET_REG_BITS == 32 && is_64 ? *args++ : 0); - addr_regl = *args++; - addr_regh = (TCG_TARGET_REG_BITS < TARGET_LONG_BITS ? *args++ : 0); - oi = *args++; - opc = get_memop(oi); - a_bits = get_alignment_bits(opc); - s_bits = opc & MO_SIZE; + MemOp opc = get_memop(oi); + unsigned a_bits = get_alignment_bits(opc); + unsigned s_bits = opc & MO_SIZE; + TCGReg base; /* * R6 removes the left/right instructions but requires the * system to support misaligned memory accesses. */ #if defined(CONFIG_SOFTMMU) - tcg_out_tlb_load(s, base, addr_regl, addr_regh, oi, label_ptr, 1); + tcg_insn_unit *label_ptr[2]; + + base = TCG_REG_A0; + tcg_out_tlb_load(s, base, addrlo, addrhi, oi, label_ptr, 1); if (use_mips32r6_instructions || a_bits >= s_bits) { - tcg_out_qemu_ld_direct(s, data_regl, data_regh, base, opc, is_64); + tcg_out_qemu_ld_direct(s, datalo, datahi, base, opc, data_type); } else { - tcg_out_qemu_ld_unalign(s, data_regl, data_regh, base, opc, is_64); + tcg_out_qemu_ld_unalign(s, datalo, datahi, base, opc, data_type); } - add_qemu_ldst_label(s, 1, oi, - (is_64 ? TCG_TYPE_I64 : TCG_TYPE_I32), - data_regl, data_regh, addr_regl, addr_regh, - s->code_ptr, label_ptr); + add_qemu_ldst_label(s, true, oi, data_type, datalo, datahi, + addrlo, addrhi, s->code_ptr, label_ptr); #else + base = addrlo; if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) { - tcg_out_ext32u(s, base, addr_regl); - addr_regl = base; + tcg_out_ext32u(s, TCG_REG_A0, base); + base = TCG_REG_A0; } - if (guest_base == 0 && data_regl != addr_regl) { - base = addr_regl; - } else if (guest_base == (int16_t)guest_base) { - tcg_out_opc_imm(s, ALIAS_PADDI, base, addr_regl, guest_base); - } else { - tcg_out_opc_reg(s, ALIAS_PADD, base, TCG_GUEST_BASE_REG, addr_regl); + if (guest_base) { + if (guest_base == (int16_t)guest_base) { + tcg_out_opc_imm(s, ALIAS_PADDI, TCG_REG_A0, base, guest_base); + } else { + tcg_out_opc_reg(s, ALIAS_PADD, TCG_REG_A0, base, + TCG_GUEST_BASE_REG); + } + base = TCG_REG_A0; } if (use_mips32r6_instructions) { if (a_bits) { - tcg_out_test_alignment(s, true, addr_regl, addr_regh, a_bits); + tcg_out_test_alignment(s, true, addrlo, addrhi, a_bits); } - tcg_out_qemu_ld_direct(s, data_regl, data_regh, base, opc, is_64); + tcg_out_qemu_ld_direct(s, datalo, datahi, base, opc, data_type); } else { if (a_bits && a_bits != s_bits) { - tcg_out_test_alignment(s, true, addr_regl, addr_regh, a_bits); + tcg_out_test_alignment(s, true, addrlo, addrhi, a_bits); } if (a_bits >= s_bits) { - tcg_out_qemu_ld_direct(s, data_regl, data_regh, base, opc, is_64); + tcg_out_qemu_ld_direct(s, datalo, datahi, base, opc, data_type); } else { - tcg_out_qemu_ld_unalign(s, data_regl, data_regh, base, opc, is_64); + tcg_out_qemu_ld_unalign(s, datalo, datahi, base, opc, data_type); } } #endif @@ -1902,67 +1893,60 @@ static void tcg_out_qemu_st_unalign(TCGContext *s, TCGReg lo, TCGReg hi, g_assert_not_reached(); } } -static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is_64) -{ - TCGReg addr_regl, addr_regh __attribute__((unused)); - TCGReg data_regl, data_regh; - MemOpIdx oi; - MemOp opc; -#if defined(CONFIG_SOFTMMU) - tcg_insn_unit *label_ptr[2]; -#endif - unsigned a_bits, s_bits; - TCGReg base = TCG_REG_A0; - data_regl = *args++; - data_regh = (TCG_TARGET_REG_BITS == 32 && is_64 ? *args++ : 0); - addr_regl = *args++; - addr_regh = (TCG_TARGET_REG_BITS < TARGET_LONG_BITS ? *args++ : 0); - oi = *args++; - opc = get_memop(oi); - a_bits = get_alignment_bits(opc); - s_bits = opc & MO_SIZE; +static void tcg_out_qemu_st(TCGContext *s, TCGReg datalo, TCGReg datahi, + TCGReg addrlo, TCGReg addrhi, + MemOpIdx oi, TCGType data_type) +{ + MemOp opc = get_memop(oi); + unsigned a_bits = get_alignment_bits(opc); + unsigned s_bits = opc & MO_SIZE; + TCGReg base; /* * R6 removes the left/right instructions but requires the * system to support misaligned memory accesses. */ #if defined(CONFIG_SOFTMMU) - tcg_out_tlb_load(s, base, addr_regl, addr_regh, oi, label_ptr, 0); + tcg_insn_unit *label_ptr[2]; + + base = TCG_REG_A0; + tcg_out_tlb_load(s, base, addrlo, addrhi, oi, label_ptr, 0); if (use_mips32r6_instructions || a_bits >= s_bits) { - tcg_out_qemu_st_direct(s, data_regl, data_regh, base, opc); + tcg_out_qemu_st_direct(s, datalo, datahi, base, opc); } else { - tcg_out_qemu_st_unalign(s, data_regl, data_regh, base, opc); + tcg_out_qemu_st_unalign(s, datalo, datahi, base, opc); } - add_qemu_ldst_label(s, 0, oi, - (is_64 ? TCG_TYPE_I64 : TCG_TYPE_I32), - data_regl, data_regh, addr_regl, addr_regh, - s->code_ptr, label_ptr); + add_qemu_ldst_label(s, false, oi, data_type, datalo, datahi, + addrlo, addrhi, s->code_ptr, label_ptr); #else + base = addrlo; if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) { - tcg_out_ext32u(s, base, addr_regl); - addr_regl = base; + tcg_out_ext32u(s, TCG_REG_A0, base); + base = TCG_REG_A0; } - if (guest_base == 0) { - base = addr_regl; - } else if (guest_base == (int16_t)guest_base) { - tcg_out_opc_imm(s, ALIAS_PADDI, base, addr_regl, guest_base); - } else { - tcg_out_opc_reg(s, ALIAS_PADD, base, TCG_GUEST_BASE_REG, addr_regl); + if (guest_base) { + if (guest_base == (int16_t)guest_base) { + tcg_out_opc_imm(s, ALIAS_PADDI, TCG_REG_A0, base, guest_base); + } else { + tcg_out_opc_reg(s, ALIAS_PADD, TCG_REG_A0, base, + TCG_GUEST_BASE_REG); + } + base = TCG_REG_A0; } if (use_mips32r6_instructions) { if (a_bits) { - tcg_out_test_alignment(s, true, addr_regl, addr_regh, a_bits); + tcg_out_test_alignment(s, true, addrlo, addrhi, a_bits); } - tcg_out_qemu_st_direct(s, data_regl, data_regh, base, opc); + tcg_out_qemu_st_direct(s, datalo, datahi, base, opc); } else { if (a_bits && a_bits != s_bits) { - tcg_out_test_alignment(s, true, addr_regl, addr_regh, a_bits); + tcg_out_test_alignment(s, true, addrlo, addrhi, a_bits); } if (a_bits >= s_bits) { - tcg_out_qemu_st_direct(s, data_regl, data_regh, base, opc); + tcg_out_qemu_st_direct(s, datalo, datahi, base, opc); } else { - tcg_out_qemu_st_unalign(s, data_regl, data_regh, base, opc); + tcg_out_qemu_st_unalign(s, datalo, datahi, base, opc); } } #endif @@ -2425,16 +2409,36 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, break; case INDEX_op_qemu_ld_i32: - tcg_out_qemu_ld(s, args, false); + if (TCG_TARGET_REG_BITS >= TARGET_LONG_BITS) { + tcg_out_qemu_ld(s, a0, 0, a1, 0, a2, TCG_TYPE_I32); + } else { + tcg_out_qemu_ld(s, a0, 0, a1, a2, args[3], TCG_TYPE_I32); + } break; case INDEX_op_qemu_ld_i64: - tcg_out_qemu_ld(s, args, true); + if (TCG_TARGET_REG_BITS == 64) { + tcg_out_qemu_ld(s, a0, 0, a1, 0, a2, TCG_TYPE_I64); + } else if (TARGET_LONG_BITS == 32) { + tcg_out_qemu_ld(s, a0, a1, a2, 0, args[3], TCG_TYPE_I64); + } else { + tcg_out_qemu_ld(s, a0, a1, a2, args[3], args[4], TCG_TYPE_I64); + } break; case INDEX_op_qemu_st_i32: - tcg_out_qemu_st(s, args, false); + if (TCG_TARGET_REG_BITS >= TARGET_LONG_BITS) { + tcg_out_qemu_st(s, a0, 0, a1, 0, a2, TCG_TYPE_I32); + } else { + tcg_out_qemu_st(s, a0, 0, a1, a2, args[3], TCG_TYPE_I32); + } break; case INDEX_op_qemu_st_i64: - tcg_out_qemu_st(s, args, true); + if (TCG_TARGET_REG_BITS == 64) { + tcg_out_qemu_st(s, a0, 0, a1, 0, a2, TCG_TYPE_I64); + } else if (TARGET_LONG_BITS == 32) { + tcg_out_qemu_st(s, a0, a1, a2, 0, args[3], TCG_TYPE_I64); + } else { + tcg_out_qemu_st(s, a0, a1, a2, args[3], args[4], TCG_TYPE_I64); + } break; case INDEX_op_add2_i32: From 6073988eef3b23f27a06bef5d74bf138550f6df6 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 6 Apr 2023 12:53:46 -0700 Subject: [PATCH 31/42] tcg/ppc: Rationalize args to tcg_out_qemu_{ld,st} MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Interpret the variable argument placement in the caller. Pass data_type instead of is64 -- there are several places where we already convert back from bool to type. Clean things up by using type throughout. Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Daniel Henrique Barboza Signed-off-by: Richard Henderson --- tcg/ppc/tcg-target.c.inc | 110 +++++++++++++++++++++------------------ 1 file changed, 59 insertions(+), 51 deletions(-) diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc index 77abb7d20c..d1aa2a9f53 100644 --- a/tcg/ppc/tcg-target.c.inc +++ b/tcg/ppc/tcg-target.c.inc @@ -2118,7 +2118,8 @@ static TCGReg tcg_out_tlb_read(TCGContext *s, MemOp opc, /* Record the context of a call to the out of line helper code for the slow path for a load or store, so that we can later generate the correct helper code. */ -static void add_qemu_ldst_label(TCGContext *s, bool is_ld, MemOpIdx oi, +static void add_qemu_ldst_label(TCGContext *s, bool is_ld, + TCGType type, MemOpIdx oi, TCGReg datalo_reg, TCGReg datahi_reg, TCGReg addrlo_reg, TCGReg addrhi_reg, tcg_insn_unit *raddr, tcg_insn_unit *lptr) @@ -2126,6 +2127,7 @@ static void add_qemu_ldst_label(TCGContext *s, bool is_ld, MemOpIdx oi, TCGLabelQemuLdst *label = new_ldst_label(s); label->is_ld = is_ld; + label->type = type; label->oi = oi; label->datalo_reg = datalo_reg; label->datahi_reg = datahi_reg; @@ -2288,30 +2290,18 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l) #endif /* SOFTMMU */ -static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is_64) +static void tcg_out_qemu_ld(TCGContext *s, TCGReg datalo, TCGReg datahi, + TCGReg addrlo, TCGReg addrhi, + MemOpIdx oi, TCGType data_type) { - TCGReg datalo, datahi, addrlo, rbase; - TCGReg addrhi __attribute__((unused)); - MemOpIdx oi; - MemOp opc, s_bits; + MemOp opc = get_memop(oi); + MemOp s_bits = opc & MO_SIZE; + TCGReg rbase; + #ifdef CONFIG_SOFTMMU - int mem_index; tcg_insn_unit *label_ptr; -#else - unsigned a_bits; -#endif - datalo = *args++; - datahi = (TCG_TARGET_REG_BITS == 32 && is_64 ? *args++ : 0); - addrlo = *args++; - addrhi = (TCG_TARGET_REG_BITS < TARGET_LONG_BITS ? *args++ : 0); - oi = *args++; - opc = get_memop(oi); - s_bits = opc & MO_SIZE; - -#ifdef CONFIG_SOFTMMU - mem_index = get_mmuidx(oi); - addrlo = tcg_out_tlb_read(s, opc, addrlo, addrhi, mem_index, true); + addrlo = tcg_out_tlb_read(s, opc, addrlo, addrhi, get_mmuidx(oi), true); /* Load a pointer into the current opcode w/conditional branch-link. */ label_ptr = s->code_ptr; @@ -2319,7 +2309,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is_64) rbase = TCG_REG_R3; #else /* !CONFIG_SOFTMMU */ - a_bits = get_alignment_bits(opc); + unsigned a_bits = get_alignment_bits(opc); if (a_bits) { tcg_out_test_alignment(s, true, addrlo, addrhi, a_bits); } @@ -2364,35 +2354,23 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is_64) } #ifdef CONFIG_SOFTMMU - add_qemu_ldst_label(s, true, oi, datalo, datahi, addrlo, addrhi, - s->code_ptr, label_ptr); + add_qemu_ldst_label(s, true, data_type, oi, datalo, datahi, + addrlo, addrhi, s->code_ptr, label_ptr); #endif } -static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is_64) +static void tcg_out_qemu_st(TCGContext *s, TCGReg datalo, TCGReg datahi, + TCGReg addrlo, TCGReg addrhi, + MemOpIdx oi, TCGType data_type) { - TCGReg datalo, datahi, addrlo, rbase; - TCGReg addrhi __attribute__((unused)); - MemOpIdx oi; - MemOp opc, s_bits; + MemOp opc = get_memop(oi); + MemOp s_bits = opc & MO_SIZE; + TCGReg rbase; + #ifdef CONFIG_SOFTMMU - int mem_index; tcg_insn_unit *label_ptr; -#else - unsigned a_bits; -#endif - datalo = *args++; - datahi = (TCG_TARGET_REG_BITS == 32 && is_64 ? *args++ : 0); - addrlo = *args++; - addrhi = (TCG_TARGET_REG_BITS < TARGET_LONG_BITS ? *args++ : 0); - oi = *args++; - opc = get_memop(oi); - s_bits = opc & MO_SIZE; - -#ifdef CONFIG_SOFTMMU - mem_index = get_mmuidx(oi); - addrlo = tcg_out_tlb_read(s, opc, addrlo, addrhi, mem_index, false); + addrlo = tcg_out_tlb_read(s, opc, addrlo, addrhi, get_mmuidx(oi), false); /* Load a pointer into the current opcode w/conditional branch-link. */ label_ptr = s->code_ptr; @@ -2400,7 +2378,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is_64) rbase = TCG_REG_R3; #else /* !CONFIG_SOFTMMU */ - a_bits = get_alignment_bits(opc); + unsigned a_bits = get_alignment_bits(opc); if (a_bits) { tcg_out_test_alignment(s, false, addrlo, addrhi, a_bits); } @@ -2437,8 +2415,8 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is_64) } #ifdef CONFIG_SOFTMMU - add_qemu_ldst_label(s, false, oi, datalo, datahi, addrlo, addrhi, - s->code_ptr, label_ptr); + add_qemu_ldst_label(s, false, data_type, oi, datalo, datahi, + addrlo, addrhi, s->code_ptr, label_ptr); #endif } @@ -2972,16 +2950,46 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, break; case INDEX_op_qemu_ld_i32: - tcg_out_qemu_ld(s, args, false); + if (TCG_TARGET_REG_BITS >= TARGET_LONG_BITS) { + tcg_out_qemu_ld(s, args[0], -1, args[1], -1, + args[2], TCG_TYPE_I32); + } else { + tcg_out_qemu_ld(s, args[0], -1, args[1], args[2], + args[3], TCG_TYPE_I32); + } break; case INDEX_op_qemu_ld_i64: - tcg_out_qemu_ld(s, args, true); + if (TCG_TARGET_REG_BITS == 64) { + tcg_out_qemu_ld(s, args[0], -1, args[1], -1, + args[2], TCG_TYPE_I64); + } else if (TARGET_LONG_BITS == 32) { + tcg_out_qemu_ld(s, args[0], args[1], args[2], -1, + args[3], TCG_TYPE_I64); + } else { + tcg_out_qemu_ld(s, args[0], args[1], args[2], args[3], + args[4], TCG_TYPE_I64); + } break; case INDEX_op_qemu_st_i32: - tcg_out_qemu_st(s, args, false); + if (TCG_TARGET_REG_BITS >= TARGET_LONG_BITS) { + tcg_out_qemu_st(s, args[0], -1, args[1], -1, + args[2], TCG_TYPE_I32); + } else { + tcg_out_qemu_st(s, args[0], -1, args[1], args[2], + args[3], TCG_TYPE_I32); + } break; case INDEX_op_qemu_st_i64: - tcg_out_qemu_st(s, args, true); + if (TCG_TARGET_REG_BITS == 64) { + tcg_out_qemu_st(s, args[0], -1, args[1], -1, + args[2], TCG_TYPE_I64); + } else if (TARGET_LONG_BITS == 32) { + tcg_out_qemu_st(s, args[0], args[1], args[2], -1, + args[3], TCG_TYPE_I64); + } else { + tcg_out_qemu_st(s, args[0], args[1], args[2], args[3], + args[4], TCG_TYPE_I64); + } break; case INDEX_op_setcond_i32: From e3867bad0daca67df7e6312234bab6e20d4a7ae6 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 23 Apr 2023 20:10:00 +0100 Subject: [PATCH 32/42] tcg/ppc: Introduce HostAddress MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Collect the parts of the host address into a struct. Reorg tcg_out_qemu_{ld,st} to use it. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- tcg/ppc/tcg-target.c.inc | 90 +++++++++++++++++++++------------------- 1 file changed, 47 insertions(+), 43 deletions(-) diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc index d1aa2a9f53..cd473deb36 100644 --- a/tcg/ppc/tcg-target.c.inc +++ b/tcg/ppc/tcg-target.c.inc @@ -2287,67 +2287,71 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l) { return tcg_out_fail_alignment(s, l); } - #endif /* SOFTMMU */ +typedef struct { + TCGReg base; + TCGReg index; +} HostAddress; + static void tcg_out_qemu_ld(TCGContext *s, TCGReg datalo, TCGReg datahi, TCGReg addrlo, TCGReg addrhi, MemOpIdx oi, TCGType data_type) { MemOp opc = get_memop(oi); MemOp s_bits = opc & MO_SIZE; - TCGReg rbase; + HostAddress h; #ifdef CONFIG_SOFTMMU tcg_insn_unit *label_ptr; - addrlo = tcg_out_tlb_read(s, opc, addrlo, addrhi, get_mmuidx(oi), true); + h.index = tcg_out_tlb_read(s, opc, addrlo, addrhi, get_mmuidx(oi), true); + h.base = TCG_REG_R3; /* Load a pointer into the current opcode w/conditional branch-link. */ label_ptr = s->code_ptr; tcg_out32(s, BC | BI(7, CR_EQ) | BO_COND_FALSE | LK); - - rbase = TCG_REG_R3; #else /* !CONFIG_SOFTMMU */ unsigned a_bits = get_alignment_bits(opc); if (a_bits) { tcg_out_test_alignment(s, true, addrlo, addrhi, a_bits); } - rbase = guest_base ? TCG_GUEST_BASE_REG : 0; + h.base = guest_base ? TCG_GUEST_BASE_REG : 0; + h.index = addrlo; if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) { tcg_out_ext32u(s, TCG_REG_TMP1, addrlo); - addrlo = TCG_REG_TMP1; + h.index = TCG_REG_TMP1; } #endif if (TCG_TARGET_REG_BITS == 32 && s_bits == MO_64) { if (opc & MO_BSWAP) { - tcg_out32(s, ADDI | TAI(TCG_REG_R0, addrlo, 4)); - tcg_out32(s, LWBRX | TAB(datalo, rbase, addrlo)); - tcg_out32(s, LWBRX | TAB(datahi, rbase, TCG_REG_R0)); - } else if (rbase != 0) { - tcg_out32(s, ADDI | TAI(TCG_REG_R0, addrlo, 4)); - tcg_out32(s, LWZX | TAB(datahi, rbase, addrlo)); - tcg_out32(s, LWZX | TAB(datalo, rbase, TCG_REG_R0)); - } else if (addrlo == datahi) { - tcg_out32(s, LWZ | TAI(datalo, addrlo, 4)); - tcg_out32(s, LWZ | TAI(datahi, addrlo, 0)); + tcg_out32(s, ADDI | TAI(TCG_REG_R0, h.index, 4)); + tcg_out32(s, LWBRX | TAB(datalo, h.base, h.index)); + tcg_out32(s, LWBRX | TAB(datahi, h.base, TCG_REG_R0)); + } else if (h.base != 0) { + tcg_out32(s, ADDI | TAI(TCG_REG_R0, h.index, 4)); + tcg_out32(s, LWZX | TAB(datahi, h.base, h.index)); + tcg_out32(s, LWZX | TAB(datalo, h.base, TCG_REG_R0)); + } else if (h.index == datahi) { + tcg_out32(s, LWZ | TAI(datalo, h.index, 4)); + tcg_out32(s, LWZ | TAI(datahi, h.index, 0)); } else { - tcg_out32(s, LWZ | TAI(datahi, addrlo, 0)); - tcg_out32(s, LWZ | TAI(datalo, addrlo, 4)); + tcg_out32(s, LWZ | TAI(datahi, h.index, 0)); + tcg_out32(s, LWZ | TAI(datalo, h.index, 4)); } } else { uint32_t insn = qemu_ldx_opc[opc & (MO_BSWAP | MO_SSIZE)]; if (!have_isa_2_06 && insn == LDBRX) { - tcg_out32(s, ADDI | TAI(TCG_REG_R0, addrlo, 4)); - tcg_out32(s, LWBRX | TAB(datalo, rbase, addrlo)); - tcg_out32(s, LWBRX | TAB(TCG_REG_R0, rbase, TCG_REG_R0)); + tcg_out32(s, ADDI | TAI(TCG_REG_R0, h.index, 4)); + tcg_out32(s, LWBRX | TAB(datalo, h.base, h.index)); + tcg_out32(s, LWBRX | TAB(TCG_REG_R0, h.base, TCG_REG_R0)); tcg_out_rld(s, RLDIMI, datalo, TCG_REG_R0, 32, 0); } else if (insn) { - tcg_out32(s, insn | TAB(datalo, rbase, addrlo)); + tcg_out32(s, insn | TAB(datalo, h.base, h.index)); } else { insn = qemu_ldx_opc[opc & (MO_SIZE | MO_BSWAP)]; - tcg_out32(s, insn | TAB(datalo, rbase, addrlo)); + tcg_out32(s, insn | TAB(datalo, h.base, h.index)); tcg_out_movext(s, TCG_TYPE_REG, datalo, TCG_TYPE_REG, opc & MO_SSIZE, datalo); } @@ -2365,52 +2369,52 @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg datalo, TCGReg datahi, { MemOp opc = get_memop(oi); MemOp s_bits = opc & MO_SIZE; - TCGReg rbase; + HostAddress h; #ifdef CONFIG_SOFTMMU tcg_insn_unit *label_ptr; - addrlo = tcg_out_tlb_read(s, opc, addrlo, addrhi, get_mmuidx(oi), false); + h.index = tcg_out_tlb_read(s, opc, addrlo, addrhi, get_mmuidx(oi), false); + h.base = TCG_REG_R3; /* Load a pointer into the current opcode w/conditional branch-link. */ label_ptr = s->code_ptr; tcg_out32(s, BC | BI(7, CR_EQ) | BO_COND_FALSE | LK); - - rbase = TCG_REG_R3; #else /* !CONFIG_SOFTMMU */ unsigned a_bits = get_alignment_bits(opc); if (a_bits) { tcg_out_test_alignment(s, false, addrlo, addrhi, a_bits); } - rbase = guest_base ? TCG_GUEST_BASE_REG : 0; + h.base = guest_base ? TCG_GUEST_BASE_REG : 0; + h.index = addrlo; if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) { tcg_out_ext32u(s, TCG_REG_TMP1, addrlo); - addrlo = TCG_REG_TMP1; + h.index = TCG_REG_TMP1; } #endif if (TCG_TARGET_REG_BITS == 32 && s_bits == MO_64) { if (opc & MO_BSWAP) { - tcg_out32(s, ADDI | TAI(TCG_REG_R0, addrlo, 4)); - tcg_out32(s, STWBRX | SAB(datalo, rbase, addrlo)); - tcg_out32(s, STWBRX | SAB(datahi, rbase, TCG_REG_R0)); - } else if (rbase != 0) { - tcg_out32(s, ADDI | TAI(TCG_REG_R0, addrlo, 4)); - tcg_out32(s, STWX | SAB(datahi, rbase, addrlo)); - tcg_out32(s, STWX | SAB(datalo, rbase, TCG_REG_R0)); + tcg_out32(s, ADDI | TAI(TCG_REG_R0, h.index, 4)); + tcg_out32(s, STWBRX | SAB(datalo, h.base, h.index)); + tcg_out32(s, STWBRX | SAB(datahi, h.base, TCG_REG_R0)); + } else if (h.base != 0) { + tcg_out32(s, ADDI | TAI(TCG_REG_R0, h.index, 4)); + tcg_out32(s, STWX | SAB(datahi, h.base, h.index)); + tcg_out32(s, STWX | SAB(datalo, h.base, TCG_REG_R0)); } else { - tcg_out32(s, STW | TAI(datahi, addrlo, 0)); - tcg_out32(s, STW | TAI(datalo, addrlo, 4)); + tcg_out32(s, STW | TAI(datahi, h.index, 0)); + tcg_out32(s, STW | TAI(datalo, h.index, 4)); } } else { uint32_t insn = qemu_stx_opc[opc & (MO_BSWAP | MO_SIZE)]; if (!have_isa_2_06 && insn == STDBRX) { - tcg_out32(s, STWBRX | SAB(datalo, rbase, addrlo)); - tcg_out32(s, ADDI | TAI(TCG_REG_TMP1, addrlo, 4)); + tcg_out32(s, STWBRX | SAB(datalo, h.base, h.index)); + tcg_out32(s, ADDI | TAI(TCG_REG_TMP1, h.index, 4)); tcg_out_shri64(s, TCG_REG_R0, datalo, 32); - tcg_out32(s, STWBRX | SAB(TCG_REG_R0, rbase, TCG_REG_TMP1)); + tcg_out32(s, STWBRX | SAB(TCG_REG_R0, h.base, TCG_REG_TMP1)); } else { - tcg_out32(s, insn | SAB(datalo, rbase, addrlo)); + tcg_out32(s, insn | SAB(datalo, h.base, h.index)); } } From aeb6326ec5ea7eb65d21a4c513e7d1f716255625 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 23 Mar 2023 23:03:18 +0000 Subject: [PATCH 33/42] tcg/riscv: Require TCG_TARGET_REG_BITS == 64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The port currently does not support "oversize" guests, which means riscv32 can only target 32-bit guests. We will soon be building TCG once for all guests. This implies that we can only support riscv64. Since all Linux distributions target riscv64 not riscv32, this is not much of a restriction and simplifies the code. The brcond2 and setcond2 opcodes are exclusive to 32-bit hosts, so we can and should remove the stubs. Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Daniel Henrique Barboza Signed-off-by: Richard Henderson --- tcg/riscv/tcg-target-con-set.h | 8 -- tcg/riscv/tcg-target.c.inc | 232 +++++++++------------------------ tcg/riscv/tcg-target.h | 22 ++-- 3 files changed, 72 insertions(+), 190 deletions(-) diff --git a/tcg/riscv/tcg-target-con-set.h b/tcg/riscv/tcg-target-con-set.h index cf0ac4d751..d4cff673b0 100644 --- a/tcg/riscv/tcg-target-con-set.h +++ b/tcg/riscv/tcg-target-con-set.h @@ -13,18 +13,10 @@ C_O0_I1(r) C_O0_I2(LZ, L) C_O0_I2(rZ, r) C_O0_I2(rZ, rZ) -C_O0_I3(LZ, L, L) -C_O0_I3(LZ, LZ, L) -C_O0_I4(LZ, LZ, L, L) -C_O0_I4(rZ, rZ, rZ, rZ) C_O1_I1(r, L) C_O1_I1(r, r) -C_O1_I2(r, L, L) C_O1_I2(r, r, ri) C_O1_I2(r, r, rI) C_O1_I2(r, rZ, rN) C_O1_I2(r, rZ, rZ) -C_O1_I4(r, rZ, rZ, rZ, rZ) -C_O2_I1(r, r, L) -C_O2_I2(r, r, L, L) C_O2_I4(r, r, rZ, rZ, rM, rM) diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc index 266fe1433d..7a674ff5ce 100644 --- a/tcg/riscv/tcg-target.c.inc +++ b/tcg/riscv/tcg-target.c.inc @@ -137,15 +137,7 @@ static TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind kind, int slot) #define SOFTMMU_RESERVE_REGS 0 #endif - -static inline tcg_target_long sextreg(tcg_target_long val, int pos, int len) -{ - if (TCG_TARGET_REG_BITS == 32) { - return sextract32(val, pos, len); - } else { - return sextract64(val, pos, len); - } -} +#define sextreg sextract64 /* test if a constant matches the constraint */ static bool tcg_target_const_match(int64_t val, TCGType type, int ct) @@ -235,7 +227,6 @@ typedef enum { OPC_XOR = 0x4033, OPC_XORI = 0x4013, -#if TCG_TARGET_REG_BITS == 64 OPC_ADDIW = 0x1b, OPC_ADDW = 0x3b, OPC_DIVUW = 0x200503b, @@ -250,23 +241,6 @@ typedef enum { OPC_SRLIW = 0x501b, OPC_SRLW = 0x503b, OPC_SUBW = 0x4000003b, -#else - /* Simplify code throughout by defining aliases for RV32. */ - OPC_ADDIW = OPC_ADDI, - OPC_ADDW = OPC_ADD, - OPC_DIVUW = OPC_DIVU, - OPC_DIVW = OPC_DIV, - OPC_MULW = OPC_MUL, - OPC_REMUW = OPC_REMU, - OPC_REMW = OPC_REM, - OPC_SLLIW = OPC_SLLI, - OPC_SLLW = OPC_SLL, - OPC_SRAIW = OPC_SRAI, - OPC_SRAW = OPC_SRA, - OPC_SRLIW = OPC_SRLI, - OPC_SRLW = OPC_SRL, - OPC_SUBW = OPC_SUB, -#endif OPC_FENCE = 0x0000000f, OPC_NOP = OPC_ADDI, /* nop = addi r0,r0,0 */ @@ -500,7 +474,7 @@ static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd, tcg_target_long lo, hi, tmp; int shift, ret; - if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I32) { + if (type == TCG_TYPE_I32) { val = (int32_t)val; } @@ -511,7 +485,7 @@ static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd, } hi = val - lo; - if (TCG_TARGET_REG_BITS == 32 || val == (int32_t)val) { + if (val == (int32_t)val) { tcg_out_opc_upper(s, OPC_LUI, rd, hi); if (lo != 0) { tcg_out_opc_imm(s, OPC_ADDIW, rd, rd, lo); @@ -519,7 +493,6 @@ static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd, return; } - /* We can only be here if TCG_TARGET_REG_BITS != 32 */ tmp = tcg_pcrel_diff(s, (void *)val); if (tmp == (int32_t)tmp) { tcg_out_opc_upper(s, OPC_AUIPC, rd, 0); @@ -668,15 +641,15 @@ static void tcg_out_ldst(TCGContext *s, RISCVInsn opc, TCGReg data, static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1, intptr_t arg2) { - bool is32bit = (TCG_TARGET_REG_BITS == 32 || type == TCG_TYPE_I32); - tcg_out_ldst(s, is32bit ? OPC_LW : OPC_LD, arg, arg1, arg2); + RISCVInsn insn = type == TCG_TYPE_I32 ? OPC_LW : OPC_LD; + tcg_out_ldst(s, insn, arg, arg1, arg2); } static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1, intptr_t arg2) { - bool is32bit = (TCG_TARGET_REG_BITS == 32 || type == TCG_TYPE_I32); - tcg_out_ldst(s, is32bit ? OPC_SW : OPC_SD, arg, arg1, arg2); + RISCVInsn insn = type == TCG_TYPE_I32 ? OPC_SW : OPC_SD; + tcg_out_ldst(s, insn, arg, arg1, arg2); } static bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val, @@ -829,20 +802,6 @@ static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret, } } -static void tcg_out_brcond2(TCGContext *s, TCGCond cond, TCGReg al, TCGReg ah, - TCGReg bl, TCGReg bh, TCGLabel *l) -{ - /* todo */ - g_assert_not_reached(); -} - -static void tcg_out_setcond2(TCGContext *s, TCGCond cond, TCGReg ret, - TCGReg al, TCGReg ah, TCGReg bl, TCGReg bh) -{ - /* todo */ - g_assert_not_reached(); -} - static void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool tail) { TCGReg link = tail ? TCG_REG_ZERO : TCG_REG_RA; @@ -853,20 +812,18 @@ static void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool tail) if (offset == sextreg(offset, 0, 20)) { /* short jump: -2097150 to 2097152 */ tcg_out_opc_jump(s, OPC_JAL, link, offset); - } else if (TCG_TARGET_REG_BITS == 32 || offset == (int32_t)offset) { + } else if (offset == (int32_t)offset) { /* long jump: -2147483646 to 2147483648 */ tcg_out_opc_upper(s, OPC_AUIPC, TCG_REG_TMP0, 0); tcg_out_opc_imm(s, OPC_JALR, link, TCG_REG_TMP0, 0); ret = reloc_call(s->code_ptr - 2, arg); tcg_debug_assert(ret == true); - } else if (TCG_TARGET_REG_BITS == 64) { + } else { /* far jump: 64-bit */ tcg_target_long imm = sextreg((tcg_target_long)arg, 0, 12); tcg_target_long base = (tcg_target_long)arg - imm; tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP0, base); tcg_out_opc_imm(s, OPC_JALR, link, TCG_REG_TMP0, imm); - } else { - g_assert_not_reached(); } } @@ -942,9 +899,6 @@ static void * const qemu_st_helpers[MO_SIZE + 1] = { #endif }; -/* We don't support oversize guests */ -QEMU_BUILD_BUG_ON(TCG_TARGET_REG_BITS < TARGET_LONG_BITS); - /* We expect to use a 12-bit negative offset from ENV. */ QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) > 0); QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) < -(1 << 11)); @@ -956,8 +910,7 @@ static void tcg_out_goto(TCGContext *s, const tcg_insn_unit *target) tcg_debug_assert(ok); } -static TCGReg tcg_out_tlb_load(TCGContext *s, TCGReg addrl, - TCGReg addrh, MemOpIdx oi, +static TCGReg tcg_out_tlb_load(TCGContext *s, TCGReg addr, MemOpIdx oi, tcg_insn_unit **label_ptr, bool is_load) { MemOp opc = get_memop(oi); @@ -973,7 +926,7 @@ static TCGReg tcg_out_tlb_load(TCGContext *s, TCGReg addrl, tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, mask_base, mask_ofs); tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP1, table_base, table_ofs); - tcg_out_opc_imm(s, OPC_SRLI, TCG_REG_TMP2, addrl, + tcg_out_opc_imm(s, OPC_SRLI, TCG_REG_TMP2, addr, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS); tcg_out_opc_reg(s, OPC_AND, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP0); tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP1); @@ -992,10 +945,10 @@ static TCGReg tcg_out_tlb_load(TCGContext *s, TCGReg addrl, /* Clear the non-page, non-alignment bits from the address. */ compare_mask = (tcg_target_long)TARGET_PAGE_MASK | ((1 << a_bits) - 1); if (compare_mask == sextreg(compare_mask, 0, 12)) { - tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_TMP1, addrl, compare_mask); + tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_TMP1, addr, compare_mask); } else { tcg_out_movi(s, TCG_TYPE_TL, TCG_REG_TMP1, compare_mask); - tcg_out_opc_reg(s, OPC_AND, TCG_REG_TMP1, TCG_REG_TMP1, addrl); + tcg_out_opc_reg(s, OPC_AND, TCG_REG_TMP1, TCG_REG_TMP1, addr); } /* Compare masked address with the TLB entry. */ @@ -1003,29 +956,26 @@ static TCGReg tcg_out_tlb_load(TCGContext *s, TCGReg addrl, tcg_out_opc_branch(s, OPC_BNE, TCG_REG_TMP0, TCG_REG_TMP1, 0); /* TLB Hit - translate address using addend. */ - if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) { - tcg_out_ext32u(s, TCG_REG_TMP0, addrl); - addrl = TCG_REG_TMP0; + if (TARGET_LONG_BITS == 32) { + tcg_out_ext32u(s, TCG_REG_TMP0, addr); + addr = TCG_REG_TMP0; } - tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, TCG_REG_TMP2, addrl); + tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, TCG_REG_TMP2, addr); return TCG_REG_TMP0; } static void add_qemu_ldst_label(TCGContext *s, int is_ld, MemOpIdx oi, - TCGType ext, - TCGReg datalo, TCGReg datahi, - TCGReg addrlo, TCGReg addrhi, - void *raddr, tcg_insn_unit **label_ptr) + TCGType data_type, TCGReg data_reg, + TCGReg addr_reg, void *raddr, + tcg_insn_unit **label_ptr) { TCGLabelQemuLdst *label = new_ldst_label(s); label->is_ld = is_ld; label->oi = oi; - label->type = ext; - label->datalo_reg = datalo; - label->datahi_reg = datahi; - label->addrlo_reg = addrlo; - label->addrhi_reg = addrhi; + label->type = data_type; + label->datalo_reg = data_reg; + label->addrlo_reg = addr_reg; label->raddr = tcg_splitwx_to_rx(raddr); label->label_ptr[0] = label_ptr[0]; } @@ -1039,11 +989,6 @@ static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l) TCGReg a2 = tcg_target_call_iarg_regs[2]; TCGReg a3 = tcg_target_call_iarg_regs[3]; - /* We don't support oversize guests */ - if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) { - g_assert_not_reached(); - } - /* resolve label address */ if (!reloc_sbimm12(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) { return false; @@ -1073,11 +1018,6 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l) TCGReg a3 = tcg_target_call_iarg_regs[3]; TCGReg a4 = tcg_target_call_iarg_regs[4]; - /* We don't support oversize guests */ - if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) { - g_assert_not_reached(); - } - /* resolve label address */ if (!reloc_sbimm12(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) { return false; @@ -1146,7 +1086,7 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l) #endif /* CONFIG_SOFTMMU */ -static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg lo, TCGReg hi, +static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg val, TCGReg base, MemOp opc, bool is_64) { /* Byte swapping is left to middle-end expansion. */ @@ -1154,37 +1094,28 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg lo, TCGReg hi, switch (opc & (MO_SSIZE)) { case MO_UB: - tcg_out_opc_imm(s, OPC_LBU, lo, base, 0); + tcg_out_opc_imm(s, OPC_LBU, val, base, 0); break; case MO_SB: - tcg_out_opc_imm(s, OPC_LB, lo, base, 0); + tcg_out_opc_imm(s, OPC_LB, val, base, 0); break; case MO_UW: - tcg_out_opc_imm(s, OPC_LHU, lo, base, 0); + tcg_out_opc_imm(s, OPC_LHU, val, base, 0); break; case MO_SW: - tcg_out_opc_imm(s, OPC_LH, lo, base, 0); + tcg_out_opc_imm(s, OPC_LH, val, base, 0); break; case MO_UL: - if (TCG_TARGET_REG_BITS == 64 && is_64) { - tcg_out_opc_imm(s, OPC_LWU, lo, base, 0); + if (is_64) { + tcg_out_opc_imm(s, OPC_LWU, val, base, 0); break; } /* FALLTHRU */ case MO_SL: - tcg_out_opc_imm(s, OPC_LW, lo, base, 0); + tcg_out_opc_imm(s, OPC_LW, val, base, 0); break; case MO_UQ: - /* Prefer to load from offset 0 first, but allow for overlap. */ - if (TCG_TARGET_REG_BITS == 64) { - tcg_out_opc_imm(s, OPC_LD, lo, base, 0); - } else if (lo != base) { - tcg_out_opc_imm(s, OPC_LW, lo, base, 0); - tcg_out_opc_imm(s, OPC_LW, hi, base, 4); - } else { - tcg_out_opc_imm(s, OPC_LW, hi, base, 4); - tcg_out_opc_imm(s, OPC_LW, lo, base, 0); - } + tcg_out_opc_imm(s, OPC_LD, val, base, 0); break; default: g_assert_not_reached(); @@ -1193,8 +1124,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg lo, TCGReg hi, static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is_64) { - TCGReg addr_regl, addr_regh __attribute__((unused)); - TCGReg data_regl, data_regh; + TCGReg addr_reg, data_reg; MemOpIdx oi; MemOp opc; #if defined(CONFIG_SOFTMMU) @@ -1204,27 +1134,23 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is_64) #endif TCGReg base; - data_regl = *args++; - data_regh = (TCG_TARGET_REG_BITS == 32 && is_64 ? *args++ : 0); - addr_regl = *args++; - addr_regh = (TCG_TARGET_REG_BITS < TARGET_LONG_BITS ? *args++ : 0); + data_reg = *args++; + addr_reg = *args++; oi = *args++; opc = get_memop(oi); #if defined(CONFIG_SOFTMMU) - base = tcg_out_tlb_load(s, addr_regl, addr_regh, oi, label_ptr, 1); - tcg_out_qemu_ld_direct(s, data_regl, data_regh, base, opc, is_64); - add_qemu_ldst_label(s, 1, oi, - (is_64 ? TCG_TYPE_I64 : TCG_TYPE_I32), - data_regl, data_regh, addr_regl, addr_regh, - s->code_ptr, label_ptr); + base = tcg_out_tlb_load(s, addr_reg, oi, label_ptr, 1); + tcg_out_qemu_ld_direct(s, data_reg, base, opc, is_64); + add_qemu_ldst_label(s, 1, oi, (is_64 ? TCG_TYPE_I64 : TCG_TYPE_I32), + data_reg, addr_reg, s->code_ptr, label_ptr); #else a_bits = get_alignment_bits(opc); if (a_bits) { - tcg_out_test_alignment(s, true, addr_regl, a_bits); + tcg_out_test_alignment(s, true, addr_reg, a_bits); } - base = addr_regl; - if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) { + base = addr_reg; + if (TARGET_LONG_BITS == 32) { tcg_out_ext32u(s, TCG_REG_TMP0, base); base = TCG_REG_TMP0; } @@ -1232,11 +1158,11 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is_64) tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, TCG_GUEST_BASE_REG, base); base = TCG_REG_TMP0; } - tcg_out_qemu_ld_direct(s, data_regl, data_regh, base, opc, is_64); + tcg_out_qemu_ld_direct(s, data_reg, base, opc, is_64); #endif } -static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg lo, TCGReg hi, +static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg val, TCGReg base, MemOp opc) { /* Byte swapping is left to middle-end expansion. */ @@ -1244,21 +1170,16 @@ static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg lo, TCGReg hi, switch (opc & (MO_SSIZE)) { case MO_8: - tcg_out_opc_store(s, OPC_SB, base, lo, 0); + tcg_out_opc_store(s, OPC_SB, base, val, 0); break; case MO_16: - tcg_out_opc_store(s, OPC_SH, base, lo, 0); + tcg_out_opc_store(s, OPC_SH, base, val, 0); break; case MO_32: - tcg_out_opc_store(s, OPC_SW, base, lo, 0); + tcg_out_opc_store(s, OPC_SW, base, val, 0); break; case MO_64: - if (TCG_TARGET_REG_BITS == 64) { - tcg_out_opc_store(s, OPC_SD, base, lo, 0); - } else { - tcg_out_opc_store(s, OPC_SW, base, lo, 0); - tcg_out_opc_store(s, OPC_SW, base, hi, 4); - } + tcg_out_opc_store(s, OPC_SD, base, val, 0); break; default: g_assert_not_reached(); @@ -1267,8 +1188,7 @@ static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg lo, TCGReg hi, static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is_64) { - TCGReg addr_regl, addr_regh __attribute__((unused)); - TCGReg data_regl, data_regh; + TCGReg addr_reg, data_reg; MemOpIdx oi; MemOp opc; #if defined(CONFIG_SOFTMMU) @@ -1278,27 +1198,23 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is_64) #endif TCGReg base; - data_regl = *args++; - data_regh = (TCG_TARGET_REG_BITS == 32 && is_64 ? *args++ : 0); - addr_regl = *args++; - addr_regh = (TCG_TARGET_REG_BITS < TARGET_LONG_BITS ? *args++ : 0); + data_reg = *args++; + addr_reg = *args++; oi = *args++; opc = get_memop(oi); #if defined(CONFIG_SOFTMMU) - base = tcg_out_tlb_load(s, addr_regl, addr_regh, oi, label_ptr, 0); - tcg_out_qemu_st_direct(s, data_regl, data_regh, base, opc); - add_qemu_ldst_label(s, 0, oi, - (is_64 ? TCG_TYPE_I64 : TCG_TYPE_I32), - data_regl, data_regh, addr_regl, addr_regh, - s->code_ptr, label_ptr); + base = tcg_out_tlb_load(s, addr_reg, oi, label_ptr, 0); + tcg_out_qemu_st_direct(s, data_reg, base, opc); + add_qemu_ldst_label(s, 0, oi, (is_64 ? TCG_TYPE_I64 : TCG_TYPE_I32), + data_reg, addr_reg, s->code_ptr, label_ptr); #else a_bits = get_alignment_bits(opc); if (a_bits) { - tcg_out_test_alignment(s, false, addr_regl, a_bits); + tcg_out_test_alignment(s, false, addr_reg, a_bits); } - base = addr_regl; - if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) { + base = addr_reg; + if (TARGET_LONG_BITS == 32) { tcg_out_ext32u(s, TCG_REG_TMP0, base); base = TCG_REG_TMP0; } @@ -1306,7 +1222,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is_64) tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, TCG_GUEST_BASE_REG, base); base = TCG_REG_TMP0; } - tcg_out_qemu_st_direct(s, data_regl, data_regh, base, opc); + tcg_out_qemu_st_direct(s, data_reg, base, opc); #endif } @@ -1585,17 +1501,11 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, case INDEX_op_brcond_i64: tcg_out_brcond(s, a2, a0, a1, arg_label(args[3])); break; - case INDEX_op_brcond2_i32: - tcg_out_brcond2(s, args[4], a0, a1, a2, args[3], arg_label(args[5])); - break; case INDEX_op_setcond_i32: case INDEX_op_setcond_i64: tcg_out_setcond(s, args[3], a0, a1, a2); break; - case INDEX_op_setcond2_i32: - tcg_out_setcond2(s, args[5], a0, a1, a2, args[3], args[4]); - break; case INDEX_op_qemu_ld_i32: tcg_out_qemu_ld(s, args, false); @@ -1748,26 +1658,12 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) case INDEX_op_sub2_i64: return C_O2_I4(r, r, rZ, rZ, rM, rM); - case INDEX_op_brcond2_i32: - return C_O0_I4(rZ, rZ, rZ, rZ); - - case INDEX_op_setcond2_i32: - return C_O1_I4(r, rZ, rZ, rZ, rZ); - case INDEX_op_qemu_ld_i32: - return (TARGET_LONG_BITS <= TCG_TARGET_REG_BITS - ? C_O1_I1(r, L) : C_O1_I2(r, L, L)); - case INDEX_op_qemu_st_i32: - return (TARGET_LONG_BITS <= TCG_TARGET_REG_BITS - ? C_O0_I2(LZ, L) : C_O0_I3(LZ, L, L)); case INDEX_op_qemu_ld_i64: - return (TCG_TARGET_REG_BITS == 64 ? C_O1_I1(r, L) - : TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? C_O2_I1(r, r, L) - : C_O2_I2(r, r, L, L)); + return C_O1_I1(r, L); + case INDEX_op_qemu_st_i32: case INDEX_op_qemu_st_i64: - return (TCG_TARGET_REG_BITS == 64 ? C_O0_I2(LZ, L) - : TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? C_O0_I3(LZ, LZ, L) - : C_O0_I4(LZ, LZ, L, L)); + return C_O0_I2(LZ, L); default: g_assert_not_reached(); @@ -1843,9 +1739,7 @@ static void tcg_target_qemu_prologue(TCGContext *s) static void tcg_target_init(TCGContext *s) { tcg_target_available_regs[TCG_TYPE_I32] = 0xffffffff; - if (TCG_TARGET_REG_BITS == 64) { - tcg_target_available_regs[TCG_TYPE_I64] = 0xffffffff; - } + tcg_target_available_regs[TCG_TYPE_I64] = 0xffffffff; tcg_target_call_clobber_regs = -1u; tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S0); diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h index 0deb33701f..dddf2486c1 100644 --- a/tcg/riscv/tcg-target.h +++ b/tcg/riscv/tcg-target.h @@ -25,11 +25,14 @@ #ifndef RISCV_TCG_TARGET_H #define RISCV_TCG_TARGET_H -#if __riscv_xlen == 32 -# define TCG_TARGET_REG_BITS 32 -#elif __riscv_xlen == 64 -# define TCG_TARGET_REG_BITS 64 +/* + * We don't support oversize guests. + * Since we will only build tcg once, this in turn requires a 64-bit host. + */ +#if __riscv_xlen != 64 +#error "unsupported code generation mode" #endif +#define TCG_TARGET_REG_BITS 64 #define TCG_TARGET_INSN_UNIT_SIZE 4 #define TCG_TARGET_TLB_DISPLACEMENT_BITS 20 @@ -83,13 +86,8 @@ typedef enum { #define TCG_TARGET_STACK_ALIGN 16 #define TCG_TARGET_CALL_STACK_OFFSET 0 #define TCG_TARGET_CALL_ARG_I32 TCG_CALL_ARG_NORMAL -#if TCG_TARGET_REG_BITS == 32 -#define TCG_TARGET_CALL_ARG_I64 TCG_CALL_ARG_EVEN -#define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_EVEN -#else #define TCG_TARGET_CALL_ARG_I64 TCG_CALL_ARG_NORMAL #define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_NORMAL -#endif #define TCG_TARGET_CALL_RET_I128 TCG_CALL_RET_NORMAL /* optional instructions */ @@ -106,8 +104,8 @@ typedef enum { #define TCG_TARGET_HAS_sub2_i32 1 #define TCG_TARGET_HAS_mulu2_i32 0 #define TCG_TARGET_HAS_muls2_i32 0 -#define TCG_TARGET_HAS_muluh_i32 (TCG_TARGET_REG_BITS == 32) -#define TCG_TARGET_HAS_mulsh_i32 (TCG_TARGET_REG_BITS == 32) +#define TCG_TARGET_HAS_muluh_i32 0 +#define TCG_TARGET_HAS_mulsh_i32 0 #define TCG_TARGET_HAS_ext8s_i32 1 #define TCG_TARGET_HAS_ext16s_i32 1 #define TCG_TARGET_HAS_ext8u_i32 1 @@ -128,7 +126,6 @@ typedef enum { #define TCG_TARGET_HAS_setcond2 1 #define TCG_TARGET_HAS_qemu_st8_i32 0 -#if TCG_TARGET_REG_BITS == 64 #define TCG_TARGET_HAS_movcond_i64 0 #define TCG_TARGET_HAS_div_i64 1 #define TCG_TARGET_HAS_rem_i64 1 @@ -165,7 +162,6 @@ typedef enum { #define TCG_TARGET_HAS_muls2_i64 0 #define TCG_TARGET_HAS_muluh_i64 1 #define TCG_TARGET_HAS_mulsh_i64 1 -#endif #define TCG_TARGET_DEFAULT_MO (0) From f7041977a67c8af40d5b43e23c9de9c257e74202 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 6 Apr 2023 13:27:16 -0700 Subject: [PATCH 34/42] tcg/riscv: Rationalize args to tcg_out_qemu_{ld,st} MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Interpret the variable argument placement in the caller. Pass data_type instead of is64 -- there are several places where we already convert back from bool to type. Clean things up by using type throughout. Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Daniel Henrique Barboza Signed-off-by: Richard Henderson --- tcg/riscv/tcg-target.c.inc | 66 ++++++++++++++------------------------ 1 file changed, 24 insertions(+), 42 deletions(-) diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc index 7a674ff5ce..a4cf60ca75 100644 --- a/tcg/riscv/tcg-target.c.inc +++ b/tcg/riscv/tcg-target.c.inc @@ -1087,7 +1087,7 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l) #endif /* CONFIG_SOFTMMU */ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg val, - TCGReg base, MemOp opc, bool is_64) + TCGReg base, MemOp opc, TCGType type) { /* Byte swapping is left to middle-end expansion. */ tcg_debug_assert((opc & MO_BSWAP) == 0); @@ -1106,7 +1106,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg val, tcg_out_opc_imm(s, OPC_LH, val, base, 0); break; case MO_UL: - if (is_64) { + if (type == TCG_TYPE_I64) { tcg_out_opc_imm(s, OPC_LWU, val, base, 0); break; } @@ -1122,30 +1122,21 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg val, } } -static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is_64) +static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg, + MemOpIdx oi, TCGType data_type) { - TCGReg addr_reg, data_reg; - MemOpIdx oi; - MemOp opc; -#if defined(CONFIG_SOFTMMU) - tcg_insn_unit *label_ptr[1]; -#else - unsigned a_bits; -#endif + MemOp opc = get_memop(oi); TCGReg base; - data_reg = *args++; - addr_reg = *args++; - oi = *args++; - opc = get_memop(oi); - #if defined(CONFIG_SOFTMMU) + tcg_insn_unit *label_ptr[1]; + base = tcg_out_tlb_load(s, addr_reg, oi, label_ptr, 1); - tcg_out_qemu_ld_direct(s, data_reg, base, opc, is_64); - add_qemu_ldst_label(s, 1, oi, (is_64 ? TCG_TYPE_I64 : TCG_TYPE_I32), - data_reg, addr_reg, s->code_ptr, label_ptr); + tcg_out_qemu_ld_direct(s, data_reg, base, opc, data_type); + add_qemu_ldst_label(s, true, oi, data_type, data_reg, addr_reg, + s->code_ptr, label_ptr); #else - a_bits = get_alignment_bits(opc); + unsigned a_bits = get_alignment_bits(opc); if (a_bits) { tcg_out_test_alignment(s, true, addr_reg, a_bits); } @@ -1158,7 +1149,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is_64) tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, TCG_GUEST_BASE_REG, base); base = TCG_REG_TMP0; } - tcg_out_qemu_ld_direct(s, data_reg, base, opc, is_64); + tcg_out_qemu_ld_direct(s, data_reg, base, opc, data_type); #endif } @@ -1186,30 +1177,21 @@ static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg val, } } -static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is_64) +static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg, + MemOpIdx oi, TCGType data_type) { - TCGReg addr_reg, data_reg; - MemOpIdx oi; - MemOp opc; -#if defined(CONFIG_SOFTMMU) - tcg_insn_unit *label_ptr[1]; -#else - unsigned a_bits; -#endif + MemOp opc = get_memop(oi); TCGReg base; - data_reg = *args++; - addr_reg = *args++; - oi = *args++; - opc = get_memop(oi); - #if defined(CONFIG_SOFTMMU) + tcg_insn_unit *label_ptr[1]; + base = tcg_out_tlb_load(s, addr_reg, oi, label_ptr, 0); tcg_out_qemu_st_direct(s, data_reg, base, opc); - add_qemu_ldst_label(s, 0, oi, (is_64 ? TCG_TYPE_I64 : TCG_TYPE_I32), - data_reg, addr_reg, s->code_ptr, label_ptr); + add_qemu_ldst_label(s, false, oi, data_type, data_reg, addr_reg, + s->code_ptr, label_ptr); #else - a_bits = get_alignment_bits(opc); + unsigned a_bits = get_alignment_bits(opc); if (a_bits) { tcg_out_test_alignment(s, false, addr_reg, a_bits); } @@ -1508,16 +1490,16 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, break; case INDEX_op_qemu_ld_i32: - tcg_out_qemu_ld(s, args, false); + tcg_out_qemu_ld(s, a0, a1, a2, TCG_TYPE_I32); break; case INDEX_op_qemu_ld_i64: - tcg_out_qemu_ld(s, args, true); + tcg_out_qemu_ld(s, a0, a1, a2, TCG_TYPE_I64); break; case INDEX_op_qemu_st_i32: - tcg_out_qemu_st(s, args, false); + tcg_out_qemu_st(s, a0, a1, a2, TCG_TYPE_I32); break; case INDEX_op_qemu_st_i64: - tcg_out_qemu_st(s, args, true); + tcg_out_qemu_st(s, a0, a1, a2, TCG_TYPE_I64); break; case INDEX_op_extrh_i64_i32: From 01a3b5dead22d84cc4916687901a06552c63b3ff Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 6 Apr 2023 12:57:43 -0700 Subject: [PATCH 35/42] tcg/s390x: Pass TCGType to tcg_out_qemu_{ld,st} MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need to set this in TCGLabelQemuLdst, so plumb this all the way through from tcg_out_op. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- tcg/s390x/tcg-target.c.inc | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/tcg/s390x/tcg-target.c.inc b/tcg/s390x/tcg-target.c.inc index b399798664..e931f0cde4 100644 --- a/tcg/s390x/tcg-target.c.inc +++ b/tcg/s390x/tcg-target.c.inc @@ -1770,13 +1770,14 @@ static TCGReg tcg_out_tlb_read(TCGContext *s, TCGReg addr_reg, MemOp opc, } static void add_qemu_ldst_label(TCGContext *s, bool is_ld, MemOpIdx oi, - TCGReg data, TCGReg addr, + TCGType type, TCGReg data, TCGReg addr, tcg_insn_unit *raddr, tcg_insn_unit *label_ptr) { TCGLabelQemuLdst *label = new_ldst_label(s); label->is_ld = is_ld; label->oi = oi; + label->type = type; label->datalo_reg = data; label->addrlo_reg = addr; label->raddr = tcg_splitwx_to_rx(raddr); @@ -1900,7 +1901,7 @@ static void tcg_prepare_user_ldst(TCGContext *s, TCGReg *addr_reg, #endif /* CONFIG_SOFTMMU */ static void tcg_out_qemu_ld(TCGContext* s, TCGReg data_reg, TCGReg addr_reg, - MemOpIdx oi) + MemOpIdx oi, TCGType data_type) { MemOp opc = get_memop(oi); #ifdef CONFIG_SOFTMMU @@ -1916,7 +1917,8 @@ static void tcg_out_qemu_ld(TCGContext* s, TCGReg data_reg, TCGReg addr_reg, tcg_out_qemu_ld_direct(s, opc, data_reg, base_reg, TCG_REG_R2, 0); - add_qemu_ldst_label(s, 1, oi, data_reg, addr_reg, s->code_ptr, label_ptr); + add_qemu_ldst_label(s, true, oi, data_type, data_reg, addr_reg, + s->code_ptr, label_ptr); #else TCGReg index_reg; tcg_target_long disp; @@ -1931,7 +1933,7 @@ static void tcg_out_qemu_ld(TCGContext* s, TCGReg data_reg, TCGReg addr_reg, } static void tcg_out_qemu_st(TCGContext* s, TCGReg data_reg, TCGReg addr_reg, - MemOpIdx oi) + MemOpIdx oi, TCGType data_type) { MemOp opc = get_memop(oi); #ifdef CONFIG_SOFTMMU @@ -1947,7 +1949,8 @@ static void tcg_out_qemu_st(TCGContext* s, TCGReg data_reg, TCGReg addr_reg, tcg_out_qemu_st_direct(s, opc, data_reg, base_reg, TCG_REG_R2, 0); - add_qemu_ldst_label(s, 0, oi, data_reg, addr_reg, s->code_ptr, label_ptr); + add_qemu_ldst_label(s, false, oi, data_type, data_reg, addr_reg, + s->code_ptr, label_ptr); #else TCGReg index_reg; tcg_target_long disp; @@ -2307,13 +2310,16 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, break; case INDEX_op_qemu_ld_i32: - /* ??? Technically we can use a non-extending instruction. */ + tcg_out_qemu_ld(s, args[0], args[1], args[2], TCG_TYPE_I32); + break; case INDEX_op_qemu_ld_i64: - tcg_out_qemu_ld(s, args[0], args[1], args[2]); + tcg_out_qemu_ld(s, args[0], args[1], args[2], TCG_TYPE_I64); break; case INDEX_op_qemu_st_i32: + tcg_out_qemu_st(s, args[0], args[1], args[2], TCG_TYPE_I32); + break; case INDEX_op_qemu_st_i64: - tcg_out_qemu_st(s, args[0], args[1], args[2]); + tcg_out_qemu_st(s, args[0], args[1], args[2], TCG_TYPE_I64); break; case INDEX_op_ld16s_i64: From 036547487be7b563b1ae65b8c1656c816ab11519 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 23 Apr 2023 21:28:57 +0100 Subject: [PATCH 36/42] tcg/s390x: Introduce HostAddress MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Collect the 3 potential parts of the host address into a struct. Reorg tcg_out_qemu_{ld,st}_direct to use it. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- tcg/s390x/tcg-target.c.inc | 109 ++++++++++++++++++++----------------- 1 file changed, 60 insertions(+), 49 deletions(-) diff --git a/tcg/s390x/tcg-target.c.inc b/tcg/s390x/tcg-target.c.inc index e931f0cde4..da7ee5b085 100644 --- a/tcg/s390x/tcg-target.c.inc +++ b/tcg/s390x/tcg-target.c.inc @@ -1606,58 +1606,64 @@ static void tcg_out_call(TCGContext *s, const tcg_insn_unit *dest, tcg_out_call_int(s, dest); } +typedef struct { + TCGReg base; + TCGReg index; + int disp; +} HostAddress; + static void tcg_out_qemu_ld_direct(TCGContext *s, MemOp opc, TCGReg data, - TCGReg base, TCGReg index, int disp) + HostAddress h) { switch (opc & (MO_SSIZE | MO_BSWAP)) { case MO_UB: - tcg_out_insn(s, RXY, LLGC, data, base, index, disp); + tcg_out_insn(s, RXY, LLGC, data, h.base, h.index, h.disp); break; case MO_SB: - tcg_out_insn(s, RXY, LGB, data, base, index, disp); + tcg_out_insn(s, RXY, LGB, data, h.base, h.index, h.disp); break; case MO_UW | MO_BSWAP: /* swapped unsigned halfword load with upper bits zeroed */ - tcg_out_insn(s, RXY, LRVH, data, base, index, disp); + tcg_out_insn(s, RXY, LRVH, data, h.base, h.index, h.disp); tcg_out_ext16u(s, data, data); break; case MO_UW: - tcg_out_insn(s, RXY, LLGH, data, base, index, disp); + tcg_out_insn(s, RXY, LLGH, data, h.base, h.index, h.disp); break; case MO_SW | MO_BSWAP: /* swapped sign-extended halfword load */ - tcg_out_insn(s, RXY, LRVH, data, base, index, disp); + tcg_out_insn(s, RXY, LRVH, data, h.base, h.index, h.disp); tcg_out_ext16s(s, TCG_TYPE_REG, data, data); break; case MO_SW: - tcg_out_insn(s, RXY, LGH, data, base, index, disp); + tcg_out_insn(s, RXY, LGH, data, h.base, h.index, h.disp); break; case MO_UL | MO_BSWAP: /* swapped unsigned int load with upper bits zeroed */ - tcg_out_insn(s, RXY, LRV, data, base, index, disp); + tcg_out_insn(s, RXY, LRV, data, h.base, h.index, h.disp); tcg_out_ext32u(s, data, data); break; case MO_UL: - tcg_out_insn(s, RXY, LLGF, data, base, index, disp); + tcg_out_insn(s, RXY, LLGF, data, h.base, h.index, h.disp); break; case MO_SL | MO_BSWAP: /* swapped sign-extended int load */ - tcg_out_insn(s, RXY, LRV, data, base, index, disp); + tcg_out_insn(s, RXY, LRV, data, h.base, h.index, h.disp); tcg_out_ext32s(s, data, data); break; case MO_SL: - tcg_out_insn(s, RXY, LGF, data, base, index, disp); + tcg_out_insn(s, RXY, LGF, data, h.base, h.index, h.disp); break; case MO_UQ | MO_BSWAP: - tcg_out_insn(s, RXY, LRVG, data, base, index, disp); + tcg_out_insn(s, RXY, LRVG, data, h.base, h.index, h.disp); break; case MO_UQ: - tcg_out_insn(s, RXY, LG, data, base, index, disp); + tcg_out_insn(s, RXY, LG, data, h.base, h.index, h.disp); break; default: @@ -1666,44 +1672,44 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, MemOp opc, TCGReg data, } static void tcg_out_qemu_st_direct(TCGContext *s, MemOp opc, TCGReg data, - TCGReg base, TCGReg index, int disp) + HostAddress h) { switch (opc & (MO_SIZE | MO_BSWAP)) { case MO_UB: - if (disp >= 0 && disp < 0x1000) { - tcg_out_insn(s, RX, STC, data, base, index, disp); + if (h.disp >= 0 && h.disp < 0x1000) { + tcg_out_insn(s, RX, STC, data, h.base, h.index, h.disp); } else { - tcg_out_insn(s, RXY, STCY, data, base, index, disp); + tcg_out_insn(s, RXY, STCY, data, h.base, h.index, h.disp); } break; case MO_UW | MO_BSWAP: - tcg_out_insn(s, RXY, STRVH, data, base, index, disp); + tcg_out_insn(s, RXY, STRVH, data, h.base, h.index, h.disp); break; case MO_UW: - if (disp >= 0 && disp < 0x1000) { - tcg_out_insn(s, RX, STH, data, base, index, disp); + if (h.disp >= 0 && h.disp < 0x1000) { + tcg_out_insn(s, RX, STH, data, h.base, h.index, h.disp); } else { - tcg_out_insn(s, RXY, STHY, data, base, index, disp); + tcg_out_insn(s, RXY, STHY, data, h.base, h.index, h.disp); } break; case MO_UL | MO_BSWAP: - tcg_out_insn(s, RXY, STRV, data, base, index, disp); + tcg_out_insn(s, RXY, STRV, data, h.base, h.index, h.disp); break; case MO_UL: - if (disp >= 0 && disp < 0x1000) { - tcg_out_insn(s, RX, ST, data, base, index, disp); + if (h.disp >= 0 && h.disp < 0x1000) { + tcg_out_insn(s, RX, ST, data, h.base, h.index, h.disp); } else { - tcg_out_insn(s, RXY, STY, data, base, index, disp); + tcg_out_insn(s, RXY, STY, data, h.base, h.index, h.disp); } break; case MO_UQ | MO_BSWAP: - tcg_out_insn(s, RXY, STRVG, data, base, index, disp); + tcg_out_insn(s, RXY, STRVG, data, h.base, h.index, h.disp); break; case MO_UQ: - tcg_out_insn(s, RXY, STG, data, base, index, disp); + tcg_out_insn(s, RXY, STG, data, h.base, h.index, h.disp); break; default: @@ -1883,20 +1889,23 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l) return tcg_out_fail_alignment(s, l); } -static void tcg_prepare_user_ldst(TCGContext *s, TCGReg *addr_reg, - TCGReg *index_reg, tcg_target_long *disp) +static HostAddress tcg_prepare_user_ldst(TCGContext *s, TCGReg addr_reg) { + TCGReg index; + int disp; + if (TARGET_LONG_BITS == 32) { - tcg_out_ext32u(s, TCG_TMP0, *addr_reg); - *addr_reg = TCG_TMP0; + tcg_out_ext32u(s, TCG_TMP0, addr_reg); + addr_reg = TCG_TMP0; } if (guest_base < 0x80000) { - *index_reg = TCG_REG_NONE; - *disp = guest_base; + index = TCG_REG_NONE; + disp = guest_base; } else { - *index_reg = TCG_GUEST_BASE_REG; - *disp = 0; + index = TCG_GUEST_BASE_REG; + disp = 0; } + return (HostAddress){ .base = addr_reg, .index = index, .disp = disp }; } #endif /* CONFIG_SOFTMMU */ @@ -1904,31 +1913,32 @@ static void tcg_out_qemu_ld(TCGContext* s, TCGReg data_reg, TCGReg addr_reg, MemOpIdx oi, TCGType data_type) { MemOp opc = get_memop(oi); + HostAddress h; + #ifdef CONFIG_SOFTMMU unsigned mem_index = get_mmuidx(oi); tcg_insn_unit *label_ptr; - TCGReg base_reg; - base_reg = tcg_out_tlb_read(s, addr_reg, opc, mem_index, 1); + h.base = tcg_out_tlb_read(s, addr_reg, opc, mem_index, 1); + h.index = TCG_REG_R2; + h.disp = 0; tcg_out16(s, RI_BRC | (S390_CC_NE << 4)); label_ptr = s->code_ptr; s->code_ptr += 1; - tcg_out_qemu_ld_direct(s, opc, data_reg, base_reg, TCG_REG_R2, 0); + tcg_out_qemu_ld_direct(s, opc, data_reg, h); add_qemu_ldst_label(s, true, oi, data_type, data_reg, addr_reg, s->code_ptr, label_ptr); #else - TCGReg index_reg; - tcg_target_long disp; unsigned a_bits = get_alignment_bits(opc); if (a_bits) { tcg_out_test_alignment(s, true, addr_reg, a_bits); } - tcg_prepare_user_ldst(s, &addr_reg, &index_reg, &disp); - tcg_out_qemu_ld_direct(s, opc, data_reg, addr_reg, index_reg, disp); + h = tcg_prepare_user_ldst(s, addr_reg); + tcg_out_qemu_ld_direct(s, opc, data_reg, h); #endif } @@ -1936,31 +1946,32 @@ static void tcg_out_qemu_st(TCGContext* s, TCGReg data_reg, TCGReg addr_reg, MemOpIdx oi, TCGType data_type) { MemOp opc = get_memop(oi); + HostAddress h; + #ifdef CONFIG_SOFTMMU unsigned mem_index = get_mmuidx(oi); tcg_insn_unit *label_ptr; - TCGReg base_reg; - base_reg = tcg_out_tlb_read(s, addr_reg, opc, mem_index, 0); + h.base = tcg_out_tlb_read(s, addr_reg, opc, mem_index, 0); + h.index = TCG_REG_R2; + h.disp = 0; tcg_out16(s, RI_BRC | (S390_CC_NE << 4)); label_ptr = s->code_ptr; s->code_ptr += 1; - tcg_out_qemu_st_direct(s, opc, data_reg, base_reg, TCG_REG_R2, 0); + tcg_out_qemu_st_direct(s, opc, data_reg, h); add_qemu_ldst_label(s, false, oi, data_type, data_reg, addr_reg, s->code_ptr, label_ptr); #else - TCGReg index_reg; - tcg_target_long disp; unsigned a_bits = get_alignment_bits(opc); if (a_bits) { tcg_out_test_alignment(s, false, addr_reg, a_bits); } - tcg_prepare_user_ldst(s, &addr_reg, &index_reg, &disp); - tcg_out_qemu_st_direct(s, opc, data_reg, addr_reg, index_reg, disp); + h = tcg_prepare_user_ldst(s, addr_reg); + tcg_out_qemu_st_direct(s, opc, data_reg, h); #endif } From acfe94910e9bcd7ccf06d60fc51e5f5def132220 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 7 Apr 2023 19:26:24 -0500 Subject: [PATCH 37/42] tcg/sparc64: Drop is_64 test from tcg_out_qemu_ld data return MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In tcg_canonicalize_memop, we remove MO_SIGN from MO_32 operations with TCG_TYPE_I32. Thus this is never set. We already have an identical test just above which does not include is_64 Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- tcg/sparc64/tcg-target.c.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tcg/sparc64/tcg-target.c.inc b/tcg/sparc64/tcg-target.c.inc index 4f477d539c..dbe4bf96b9 100644 --- a/tcg/sparc64/tcg-target.c.inc +++ b/tcg/sparc64/tcg-target.c.inc @@ -1220,7 +1220,7 @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg data, TCGReg addr, tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_O2, oi); /* We let the helper sign-extend SB and SW, but leave SL for here. */ - if (is_64 && (memop & MO_SSIZE) == MO_SL) { + if ((memop & MO_SSIZE) == MO_SL) { tcg_out_ext32s(s, data, TCG_REG_O0); } else { tcg_out_mov(s, TCG_TYPE_REG, data, TCG_REG_O0); From e2adae3f6f7ebffff1b2f7ddacb376361f46a969 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 7 Apr 2023 19:32:51 -0500 Subject: [PATCH 38/42] tcg/sparc64: Pass TCGType to tcg_out_qemu_{ld,st} MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need to set this in TCGLabelQemuLdst, so plumb this all the way through from tcg_out_op. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- tcg/sparc64/tcg-target.c.inc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tcg/sparc64/tcg-target.c.inc b/tcg/sparc64/tcg-target.c.inc index dbe4bf96b9..7e6466d3b6 100644 --- a/tcg/sparc64/tcg-target.c.inc +++ b/tcg/sparc64/tcg-target.c.inc @@ -1178,7 +1178,7 @@ static const int qemu_st_opc[(MO_SIZE | MO_BSWAP) + 1] = { }; static void tcg_out_qemu_ld(TCGContext *s, TCGReg data, TCGReg addr, - MemOpIdx oi, bool is_64) + MemOpIdx oi, TCGType data_type) { MemOp memop = get_memop(oi); tcg_insn_unit *label_ptr; @@ -1636,10 +1636,10 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, break; case INDEX_op_qemu_ld_i32: - tcg_out_qemu_ld(s, a0, a1, a2, false); + tcg_out_qemu_ld(s, a0, a1, a2, TCG_TYPE_I32); break; case INDEX_op_qemu_ld_i64: - tcg_out_qemu_ld(s, a0, a1, a2, true); + tcg_out_qemu_ld(s, a0, a1, a2, TCG_TYPE_I64); break; case INDEX_op_qemu_st_i32: tcg_out_qemu_st(s, a0, a1, a2, TCG_TYPE_I32); From 2528f771f8250b8414482c5b0a1c7a2f5577ff9e Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 7 Apr 2023 18:18:03 -0500 Subject: [PATCH 39/42] tcg: Move TCGLabelQemuLdst to tcg.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- tcg/tcg-ldst.c.inc | 14 -------------- tcg/tcg.c | 13 +++++++++++++ 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/tcg/tcg-ldst.c.inc b/tcg/tcg-ldst.c.inc index 403cbb0f06..ffada04af0 100644 --- a/tcg/tcg-ldst.c.inc +++ b/tcg/tcg-ldst.c.inc @@ -20,20 +20,6 @@ * THE SOFTWARE. */ -typedef struct TCGLabelQemuLdst { - bool is_ld; /* qemu_ld: true, qemu_st: false */ - MemOpIdx oi; - TCGType type; /* result type of a load */ - TCGReg addrlo_reg; /* reg index for low word of guest virtual addr */ - TCGReg addrhi_reg; /* reg index for high word of guest virtual addr */ - TCGReg datalo_reg; /* reg index for low word to be loaded or stored */ - TCGReg datahi_reg; /* reg index for high word to be loaded or stored */ - const tcg_insn_unit *raddr; /* addr of the next IR of qemu_ld/st IR */ - tcg_insn_unit *label_ptr[2]; /* label pointers to be updated */ - QSIMPLEQ_ENTRY(TCGLabelQemuLdst) next; -} TCGLabelQemuLdst; - - /* * Generate TB finalization at the end of block */ diff --git a/tcg/tcg.c b/tcg/tcg.c index cfd3262a4a..6f5daaee5f 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -94,6 +94,19 @@ typedef struct QEMU_PACKED { DebugFrameFDEHeader fde; } DebugFrameHeader; +typedef struct TCGLabelQemuLdst { + bool is_ld; /* qemu_ld: true, qemu_st: false */ + MemOpIdx oi; + TCGType type; /* result type of a load */ + TCGReg addrlo_reg; /* reg index for low word of guest virtual addr */ + TCGReg addrhi_reg; /* reg index for high word of guest virtual addr */ + TCGReg datalo_reg; /* reg index for low word to be loaded or stored */ + TCGReg datahi_reg; /* reg index for high word to be loaded or stored */ + const tcg_insn_unit *raddr; /* addr of the next IR of qemu_ld/st IR */ + tcg_insn_unit *label_ptr[2]; /* label pointers to be updated */ + QSIMPLEQ_ENTRY(TCGLabelQemuLdst) next; +} TCGLabelQemuLdst; + static void tcg_register_jit_int(const void *buf, size_t size, const void *debug_frame, size_t debug_frame_size) From 338b61e9e96445d1dc386d812a81de3309ecb66c Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 8 Apr 2023 17:28:07 -0700 Subject: [PATCH 40/42] tcg: Replace REG_P with arg_loc_reg_p MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit An inline function is safer than a macro, and REG_P was rather too generic. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- tcg/tcg-internal.h | 4 ---- tcg/tcg.c | 16 +++++++++++++--- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/tcg/tcg-internal.h b/tcg/tcg-internal.h index e542a4e9b7..0f1ba01a9a 100644 --- a/tcg/tcg-internal.h +++ b/tcg/tcg-internal.h @@ -58,10 +58,6 @@ typedef struct TCGCallArgumentLoc { unsigned tmp_subindex : 2; } TCGCallArgumentLoc; -/* Avoid "unsigned < 0 is always false" Werror, when iarg_regs is empty. */ -#define REG_P(L) \ - ((int)(L)->arg_slot < (int)ARRAY_SIZE(tcg_target_call_iarg_regs)) - typedef struct TCGHelperInfo { void *func; const char *name; diff --git a/tcg/tcg.c b/tcg/tcg.c index 6f5daaee5f..fa28db0188 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -806,6 +806,16 @@ static void init_ffi_layouts(void) } #endif /* CONFIG_TCG_INTERPRETER */ +static inline bool arg_slot_reg_p(unsigned arg_slot) +{ + /* + * Split the sizeof away from the comparison to avoid Werror from + * "unsigned < 0 is always false", when iarg_regs is empty. + */ + unsigned nreg = ARRAY_SIZE(tcg_target_call_iarg_regs); + return arg_slot < nreg; +} + typedef struct TCGCumulativeArgs { int arg_idx; /* tcg_gen_callN args[] */ int info_in_idx; /* TCGHelperInfo in[] */ @@ -3231,7 +3241,7 @@ liveness_pass_1(TCGContext *s) case TCG_CALL_ARG_NORMAL: case TCG_CALL_ARG_EXTEND_U: case TCG_CALL_ARG_EXTEND_S: - if (REG_P(loc)) { + if (arg_slot_reg_p(loc->arg_slot)) { *la_temp_pref(ts) = 0; break; } @@ -3258,7 +3268,7 @@ liveness_pass_1(TCGContext *s) case TCG_CALL_ARG_NORMAL: case TCG_CALL_ARG_EXTEND_U: case TCG_CALL_ARG_EXTEND_S: - if (REG_P(loc)) { + if (arg_slot_reg_p(loc->arg_slot)) { tcg_regset_set_reg(*la_temp_pref(ts), tcg_target_call_iarg_regs[loc->arg_slot]); } @@ -4833,7 +4843,7 @@ static void load_arg_stk(TCGContext *s, int stk_slot, TCGTemp *ts, static void load_arg_normal(TCGContext *s, const TCGCallArgumentLoc *l, TCGTemp *ts, TCGRegSet *allocated_regs) { - if (REG_P(l)) { + if (arg_slot_reg_p(l->arg_slot)) { TCGReg reg = tcg_target_call_iarg_regs[l->arg_slot]; load_arg_reg(s, reg, ts, *allocated_regs); tcg_regset_set_reg(*allocated_regs, reg); From d78e4a4f7b3c147af2c93b0b7b60b715ec7324d3 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 8 Apr 2023 19:05:10 -0700 Subject: [PATCH 41/42] tcg: Introduce arg_slot_stk_ofs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unify all computation of argument stack offset in one function. This requires that we adjust ref_slot to be in the same units, by adding max_reg_slots during init_call_layout. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- tcg/tcg.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/tcg/tcg.c b/tcg/tcg.c index fa28db0188..057423c121 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -816,6 +816,15 @@ static inline bool arg_slot_reg_p(unsigned arg_slot) return arg_slot < nreg; } +static inline int arg_slot_stk_ofs(unsigned arg_slot) +{ + unsigned max = TCG_STATIC_CALL_ARGS_SIZE / sizeof(tcg_target_long); + unsigned stk_slot = arg_slot - ARRAY_SIZE(tcg_target_call_iarg_regs); + + tcg_debug_assert(stk_slot < max); + return TCG_TARGET_CALL_STACK_OFFSET + stk_slot * sizeof(tcg_target_long); +} + typedef struct TCGCumulativeArgs { int arg_idx; /* tcg_gen_callN args[] */ int info_in_idx; /* TCGHelperInfo in[] */ @@ -1055,6 +1064,7 @@ static void init_call_layout(TCGHelperInfo *info) } } assert(ref_base + cum.ref_slot <= max_stk_slots); + ref_base += max_reg_slots; if (ref_base != 0) { for (int i = cum.info_in_idx - 1; i >= 0; --i) { @@ -4826,7 +4836,7 @@ static void load_arg_reg(TCGContext *s, TCGReg reg, TCGTemp *ts, } } -static void load_arg_stk(TCGContext *s, int stk_slot, TCGTemp *ts, +static void load_arg_stk(TCGContext *s, unsigned arg_slot, TCGTemp *ts, TCGRegSet allocated_regs) { /* @@ -4836,8 +4846,7 @@ static void load_arg_stk(TCGContext *s, int stk_slot, TCGTemp *ts, */ temp_load(s, ts, tcg_target_available_regs[ts->type], allocated_regs, 0); tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, - TCG_TARGET_CALL_STACK_OFFSET + - stk_slot * sizeof(tcg_target_long)); + arg_slot_stk_ofs(arg_slot)); } static void load_arg_normal(TCGContext *s, const TCGCallArgumentLoc *l, @@ -4848,18 +4857,16 @@ static void load_arg_normal(TCGContext *s, const TCGCallArgumentLoc *l, load_arg_reg(s, reg, ts, *allocated_regs); tcg_regset_set_reg(*allocated_regs, reg); } else { - load_arg_stk(s, l->arg_slot - ARRAY_SIZE(tcg_target_call_iarg_regs), - ts, *allocated_regs); + load_arg_stk(s, l->arg_slot, ts, *allocated_regs); } } -static void load_arg_ref(TCGContext *s, int arg_slot, TCGReg ref_base, +static void load_arg_ref(TCGContext *s, unsigned arg_slot, TCGReg ref_base, intptr_t ref_off, TCGRegSet *allocated_regs) { TCGReg reg; - int stk_slot = arg_slot - ARRAY_SIZE(tcg_target_call_iarg_regs); - if (stk_slot < 0) { + if (arg_slot_reg_p(arg_slot)) { reg = tcg_target_call_iarg_regs[arg_slot]; tcg_reg_free(s, reg, *allocated_regs); tcg_out_addi_ptr(s, reg, ref_base, ref_off); @@ -4869,8 +4876,7 @@ static void load_arg_ref(TCGContext *s, int arg_slot, TCGReg ref_base, *allocated_regs, 0, false); tcg_out_addi_ptr(s, reg, ref_base, ref_off); tcg_out_st(s, TCG_TYPE_PTR, reg, TCG_REG_CALL_STACK, - TCG_TARGET_CALL_STACK_OFFSET - + stk_slot * sizeof(tcg_target_long)); + arg_slot_stk_ofs(arg_slot)); } } @@ -4900,8 +4906,7 @@ static void tcg_reg_alloc_call(TCGContext *s, TCGOp *op) case TCG_CALL_ARG_BY_REF: load_arg_stk(s, loc->ref_slot, ts, allocated_regs); load_arg_ref(s, loc->arg_slot, TCG_REG_CALL_STACK, - TCG_TARGET_CALL_STACK_OFFSET - + loc->ref_slot * sizeof(tcg_target_long), + arg_slot_stk_ofs(loc->ref_slot), &allocated_regs); break; case TCG_CALL_ARG_BY_REF_N: From 35a0bd63b458f30389b6bc6b7471c1665fe7b9d8 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 9 Apr 2023 22:11:39 -0700 Subject: [PATCH 42/42] tcg: Widen helper_*_st[bw]_mmu val arguments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While the old type was correct in the ideal sense, some ABIs require the argument to be zero-extended. Using uint32_t for all such values is a decent compromise. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- accel/tcg/cputlb.c | 6 +++--- include/tcg/tcg-ldst.h | 10 +++++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index c8bd642d0e..3117886af1 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -2508,7 +2508,7 @@ full_stb_mmu(CPUArchState *env, target_ulong addr, uint64_t val, store_helper(env, addr, val, oi, retaddr, MO_UB); } -void helper_ret_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val, +void helper_ret_stb_mmu(CPUArchState *env, target_ulong addr, uint32_t val, MemOpIdx oi, uintptr_t retaddr) { full_stb_mmu(env, addr, val, oi, retaddr); @@ -2521,7 +2521,7 @@ static void full_le_stw_mmu(CPUArchState *env, target_ulong addr, uint64_t val, store_helper(env, addr, val, oi, retaddr, MO_LEUW); } -void helper_le_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val, +void helper_le_stw_mmu(CPUArchState *env, target_ulong addr, uint32_t val, MemOpIdx oi, uintptr_t retaddr) { full_le_stw_mmu(env, addr, val, oi, retaddr); @@ -2534,7 +2534,7 @@ static void full_be_stw_mmu(CPUArchState *env, target_ulong addr, uint64_t val, store_helper(env, addr, val, oi, retaddr, MO_BEUW); } -void helper_be_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val, +void helper_be_stw_mmu(CPUArchState *env, target_ulong addr, uint32_t val, MemOpIdx oi, uintptr_t retaddr) { full_be_stw_mmu(env, addr, val, oi, retaddr); diff --git a/include/tcg/tcg-ldst.h b/include/tcg/tcg-ldst.h index 2ba22bd5fe..684e394b06 100644 --- a/include/tcg/tcg-ldst.h +++ b/include/tcg/tcg-ldst.h @@ -55,15 +55,19 @@ tcg_target_ulong helper_be_ldsw_mmu(CPUArchState *env, target_ulong addr, tcg_target_ulong helper_be_ldsl_mmu(CPUArchState *env, target_ulong addr, MemOpIdx oi, uintptr_t retaddr); -void helper_ret_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val, +/* + * Value extended to at least uint32_t, so that some ABIs do not require + * zero-extension from uint8_t or uint16_t. + */ +void helper_ret_stb_mmu(CPUArchState *env, target_ulong addr, uint32_t val, MemOpIdx oi, uintptr_t retaddr); -void helper_le_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val, +void helper_le_stw_mmu(CPUArchState *env, target_ulong addr, uint32_t val, MemOpIdx oi, uintptr_t retaddr); void helper_le_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val, MemOpIdx oi, uintptr_t retaddr); void helper_le_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val, MemOpIdx oi, uintptr_t retaddr); -void helper_be_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val, +void helper_be_stw_mmu(CPUArchState *env, target_ulong addr, uint32_t val, MemOpIdx oi, uintptr_t retaddr); void helper_be_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val, MemOpIdx oi, uintptr_t retaddr);