diff mbox series

[v4,09/11] target/loongarch: Truncate high 32 bits of address in VA32 mode

Message ID 20230808015506.1705140-10-c@jia.je (mailing list archive)
State New, archived
Headers show
Series Add la32 & va32 mode for loongarch64-softmmu | expand

Commit Message

Jiajie Chen Aug. 8, 2023, 1:54 a.m. UTC
When running in VA32 mode(LA32 or VA32L[1-3] matching PLV), virtual
address is truncated to 32 bits before address mapping.

Signed-off-by: Jiajie Chen <c@jia.je>
---
 target/loongarch/cpu.h                          |  6 +++++-
 target/loongarch/insn_trans/trans_atomic.c.inc  |  1 +
 target/loongarch/insn_trans/trans_fmemory.c.inc |  8 ++++++++
 target/loongarch/insn_trans/trans_lsx.c.inc     |  6 ++++++
 target/loongarch/insn_trans/trans_memory.c.inc  | 10 ++++++++++
 target/loongarch/translate.c                    | 10 ++++++++++
 6 files changed, 40 insertions(+), 1 deletion(-)

Comments

Richard Henderson Aug. 8, 2023, 7:08 p.m. UTC | #1
On 8/7/23 18:54, Jiajie Chen wrote:
> When running in VA32 mode(LA32 or VA32L[1-3] matching PLV), virtual
> address is truncated to 32 bits before address mapping.
> 
> Signed-off-by: Jiajie Chen <c@jia.je>
> ---
>   target/loongarch/cpu.h                          |  6 +++++-
>   target/loongarch/insn_trans/trans_atomic.c.inc  |  1 +
>   target/loongarch/insn_trans/trans_fmemory.c.inc |  8 ++++++++
>   target/loongarch/insn_trans/trans_lsx.c.inc     |  6 ++++++
>   target/loongarch/insn_trans/trans_memory.c.inc  | 10 ++++++++++
>   target/loongarch/translate.c                    | 10 ++++++++++
>   6 files changed, 40 insertions(+), 1 deletion(-)
> 
> diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
> index 69589f0aef..9ad5fcc494 100644
> --- a/target/loongarch/cpu.h
> +++ b/target/loongarch/cpu.h
> @@ -457,7 +457,11 @@ static inline void cpu_get_tb_cpu_state(CPULoongArchState *env, vaddr *pc,
>           va32 = 1;
>       }
>   
> -    *pc = env->pc;
> +    if (va32) {
> +        *pc = (uint32_t)env->pc;
> +    } else {
> +        *pc = env->pc;
> +    }

This is not wrong, but it might be better to zero-extend when assigning to env->pc.  There 
are other consumers of env->pc, and we are not updating all of them.

> --- a/target/loongarch/insn_trans/trans_memory.c.inc
> +++ b/target/loongarch/insn_trans/trans_memory.c.inc
> @@ -13,6 +13,7 @@ static bool gen_load(DisasContext *ctx, arg_rr_i *a, MemOp mop)
>           tcg_gen_addi_tl(temp, addr, a->imm);
>           addr = temp;
>       }
> +    addr = va32_address(ctx, addr);

I did say that you should use a common helper and a single temp.
This is using two temps: one here and one in va32_address.

I suggest:

static TCGv make_address_x(DisasContext *ctx, TCGv base, TCGv addend)
{
     TCGv temp = NULL;

     if (addend || ctx->va32) {
         temp = tcg_temp_new();
     }
     if (addend) {
         tcg_gen_add_tl(temp, base, addend);
         base = temp;
     }
     if (ctx->va32) {
         tcg_gen_ext32u_tl(temp, base);
         base = temp;
     }
     return base;
}

static TCGv make_address_i(DisasContext *ctx, TCGv base, target_long ofs)
{
     TCGv addend = ofs ? tcg_constant_tl(ofs) : NULL;
     return make_address_x(ctx, base, addend);
}


So that gen_load uses

     addr = make_address_i(ctx, addr, a->imm);

and gen_loadx uses

     addr = make_address_x(ctx, src1, src2);

and gen_am uses

     addr = make_address_i(ctx, addr, 0);

and so on for all of the others.


r~
diff mbox series

Patch

diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 69589f0aef..9ad5fcc494 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -457,7 +457,11 @@  static inline void cpu_get_tb_cpu_state(CPULoongArchState *env, vaddr *pc,
         va32 = 1;
     }
 
-    *pc = env->pc;
+    if (va32) {
+        *pc = (uint32_t)env->pc;
+    } else {
+        *pc = env->pc;
+    }
     *cs_base = 0;
     *flags = env->CSR_CRMD & (R_CSR_CRMD_PLV_MASK | R_CSR_CRMD_PG_MASK);
     *flags |= FIELD_EX64(env->CSR_EUEN, CSR_EUEN, FPE) * HW_FLAGS_EUEN_FPE;
diff --git a/target/loongarch/insn_trans/trans_atomic.c.inc b/target/loongarch/insn_trans/trans_atomic.c.inc
index c69f31bc78..d9d950d642 100644
--- a/target/loongarch/insn_trans/trans_atomic.c.inc
+++ b/target/loongarch/insn_trans/trans_atomic.c.inc
@@ -10,6 +10,7 @@  static bool gen_ll(DisasContext *ctx, arg_rr_i *a, MemOp mop)
     TCGv t0 = tcg_temp_new();
 
     tcg_gen_addi_tl(t0, src1, a->imm);
+    t0 = va32_address(ctx, t0);
     tcg_gen_qemu_ld_i64(dest, t0, ctx->mem_idx, mop);
     tcg_gen_st_tl(t0, cpu_env, offsetof(CPULoongArchState, lladdr));
     tcg_gen_st_tl(dest, cpu_env, offsetof(CPULoongArchState, llval));
diff --git a/target/loongarch/insn_trans/trans_fmemory.c.inc b/target/loongarch/insn_trans/trans_fmemory.c.inc
index 91c09fb6d9..391af356d0 100644
--- a/target/loongarch/insn_trans/trans_fmemory.c.inc
+++ b/target/loongarch/insn_trans/trans_fmemory.c.inc
@@ -22,6 +22,7 @@  static bool gen_fload_i(DisasContext *ctx, arg_fr_i *a, MemOp mop)
         tcg_gen_addi_tl(temp, addr, a->imm);
         addr = temp;
     }
+    addr = va32_address(ctx, addr);
 
     tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop);
     maybe_nanbox_load(dest, mop);
@@ -42,6 +43,7 @@  static bool gen_fstore_i(DisasContext *ctx, arg_fr_i *a, MemOp mop)
         tcg_gen_addi_tl(temp, addr, a->imm);
         addr = temp;
     }
+    addr = va32_address(ctx, addr);
 
     tcg_gen_qemu_st_tl(src, addr, ctx->mem_idx, mop);
 
@@ -59,6 +61,7 @@  static bool gen_floadx(DisasContext *ctx, arg_frr *a, MemOp mop)
 
     addr = tcg_temp_new();
     tcg_gen_add_tl(addr, src1, src2);
+    addr = va32_address(ctx, addr);
     tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop);
     maybe_nanbox_load(dest, mop);
     set_fpr(a->fd, dest);
@@ -77,6 +80,7 @@  static bool gen_fstorex(DisasContext *ctx, arg_frr *a, MemOp mop)
 
     addr = tcg_temp_new();
     tcg_gen_add_tl(addr, src1, src2);
+    addr = va32_address(ctx, addr);
     tcg_gen_qemu_st_tl(src3, addr, ctx->mem_idx, mop);
 
     return true;
@@ -94,6 +98,7 @@  static bool gen_fload_gt(DisasContext *ctx, arg_frr *a, MemOp mop)
     addr = tcg_temp_new();
     gen_helper_asrtgt_d(cpu_env, src1, src2);
     tcg_gen_add_tl(addr, src1, src2);
+    addr = va32_address(ctx, addr);
     tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop);
     maybe_nanbox_load(dest, mop);
     set_fpr(a->fd, dest);
@@ -113,6 +118,7 @@  static bool gen_fstore_gt(DisasContext *ctx, arg_frr *a, MemOp mop)
     addr = tcg_temp_new();
     gen_helper_asrtgt_d(cpu_env, src1, src2);
     tcg_gen_add_tl(addr, src1, src2);
+    addr = va32_address(ctx, addr);
     tcg_gen_qemu_st_tl(src3, addr, ctx->mem_idx, mop);
 
     return true;
@@ -130,6 +136,7 @@  static bool gen_fload_le(DisasContext *ctx, arg_frr *a, MemOp mop)
     addr = tcg_temp_new();
     gen_helper_asrtle_d(cpu_env, src1, src2);
     tcg_gen_add_tl(addr, src1, src2);
+    addr = va32_address(ctx, addr);
     tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop);
     maybe_nanbox_load(dest, mop);
     set_fpr(a->fd, dest);
@@ -149,6 +156,7 @@  static bool gen_fstore_le(DisasContext *ctx, arg_frr *a, MemOp mop)
     addr = tcg_temp_new();
     gen_helper_asrtle_d(cpu_env, src1, src2);
     tcg_gen_add_tl(addr, src1, src2);
+    addr = va32_address(ctx, addr);
     tcg_gen_qemu_st_tl(src3, addr, ctx->mem_idx, mop);
 
     return true;
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc b/target/loongarch/insn_trans/trans_lsx.c.inc
index 68779daff6..b7325cfd8a 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -4271,6 +4271,7 @@  static bool trans_vld(DisasContext *ctx, arg_vr_i *a)
         tcg_gen_addi_tl(temp, addr, a->imm);
         addr = temp;
     }
+    addr = va32_address(ctx, addr);
 
     tcg_gen_qemu_ld_i128(val, addr, ctx->mem_idx, MO_128 | MO_TE);
     tcg_gen_extr_i128_i64(rl, rh, val);
@@ -4298,6 +4299,7 @@  static bool trans_vst(DisasContext *ctx, arg_vr_i *a)
         tcg_gen_addi_tl(temp, addr, a->imm);
         addr = temp;
     }
+    addr = va32_address(ctx, addr);
 
     get_vreg64(ah, a->vd, 1);
     get_vreg64(al, a->vd, 0);
@@ -4323,6 +4325,7 @@  static bool trans_vldx(DisasContext *ctx, arg_vrr *a)
     rh = tcg_temp_new_i64();
 
     tcg_gen_add_tl(addr, src1, src2);
+    addr = va32_address(ctx, addr);
     tcg_gen_qemu_ld_i128(val, addr, ctx->mem_idx, MO_128 | MO_TE);
     tcg_gen_extr_i128_i64(rl, rh, val);
     set_vreg64(rh, a->vd, 1);
@@ -4347,6 +4350,7 @@  static bool trans_vstx(DisasContext *ctx, arg_vrr *a)
     al = tcg_temp_new_i64();
 
     tcg_gen_add_tl(addr, src1, src2);
+    addr = va32_address(ctx, addr);
     get_vreg64(ah, a->vd, 1);
     get_vreg64(al, a->vd, 0);
     tcg_gen_concat_i64_i128(val, al, ah);
@@ -4371,6 +4375,7 @@  static bool trans_## NAME (DisasContext *ctx, arg_vr_i *a)                \
         tcg_gen_addi_tl(temp, addr, a->imm);                              \
         addr = temp;                                                      \
     }                                                                     \
+    addr = va32_address(ctx, addr);                                        \
                                                                           \
     tcg_gen_qemu_ld_i64(val, addr, ctx->mem_idx, MO);                     \
     tcg_gen_gvec_dup_i64(MO, vec_full_offset(a->vd), 16, ctx->vl/8, val); \
@@ -4399,6 +4404,7 @@  static bool trans_## NAME (DisasContext *ctx, arg_vr_ii *a)                  \
         tcg_gen_addi_tl(temp, addr, a->imm);                                 \
         addr = temp;                                                         \
     }                                                                        \
+    addr = va32_address(ctx, addr);                                           \
                                                                              \
     tcg_gen_ld_i64(val, cpu_env,                                             \
                    offsetof(CPULoongArchState, fpr[a->vd].vreg.E(a->imm2))); \
diff --git a/target/loongarch/insn_trans/trans_memory.c.inc b/target/loongarch/insn_trans/trans_memory.c.inc
index 858c97951b..5b45444be4 100644
--- a/target/loongarch/insn_trans/trans_memory.c.inc
+++ b/target/loongarch/insn_trans/trans_memory.c.inc
@@ -13,6 +13,7 @@  static bool gen_load(DisasContext *ctx, arg_rr_i *a, MemOp mop)
         tcg_gen_addi_tl(temp, addr, a->imm);
         addr = temp;
     }
+    addr = va32_address(ctx, addr);
 
     tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop);
     gen_set_gpr(a->rd, dest, EXT_NONE);
@@ -29,6 +30,7 @@  static bool gen_store(DisasContext *ctx, arg_rr_i *a, MemOp mop)
         tcg_gen_addi_tl(temp, addr, a->imm);
         addr = temp;
     }
+    addr = va32_address(ctx, addr);
 
     tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, mop);
     return true;
@@ -42,6 +44,7 @@  static bool gen_loadx(DisasContext *ctx, arg_rrr *a, MemOp mop)
     TCGv addr = tcg_temp_new();
 
     tcg_gen_add_tl(addr, src1, src2);
+    addr = va32_address(ctx, addr);
     tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop);
     gen_set_gpr(a->rd, dest, EXT_NONE);
 
@@ -56,6 +59,7 @@  static bool gen_storex(DisasContext *ctx, arg_rrr *a, MemOp mop)
     TCGv addr = tcg_temp_new();
 
     tcg_gen_add_tl(addr, src1, src2);
+    addr = va32_address(ctx, addr);
     tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, mop);
 
     return true;
@@ -68,6 +72,7 @@  static bool gen_load_gt(DisasContext *ctx, arg_rrr *a, MemOp mop)
     TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
 
     gen_helper_asrtgt_d(cpu_env, src1, src2);
+    src1 = va32_address(ctx, src1);
     tcg_gen_qemu_ld_tl(dest, src1, ctx->mem_idx, mop);
     gen_set_gpr(a->rd, dest, EXT_NONE);
 
@@ -81,6 +86,7 @@  static bool gen_load_le(DisasContext *ctx, arg_rrr *a, MemOp mop)
     TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
 
     gen_helper_asrtle_d(cpu_env, src1, src2);
+    src1 = va32_address(ctx, src1);
     tcg_gen_qemu_ld_tl(dest, src1, ctx->mem_idx, mop);
     gen_set_gpr(a->rd, dest, EXT_NONE);
 
@@ -94,6 +100,7 @@  static bool gen_store_gt(DisasContext *ctx, arg_rrr *a, MemOp mop)
     TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
 
     gen_helper_asrtgt_d(cpu_env, src1, src2);
+    src1 = va32_address(ctx, src1);
     tcg_gen_qemu_st_tl(data, src1, ctx->mem_idx, mop);
 
     return true;
@@ -106,6 +113,7 @@  static bool gen_store_le(DisasContext *ctx, arg_rrr *a, MemOp mop)
     TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
 
     gen_helper_asrtle_d(cpu_env, src1, src2);
+    src1 = va32_address(ctx, src1);
     tcg_gen_qemu_st_tl(data, src1, ctx->mem_idx, mop);
 
     return true;
@@ -138,6 +146,7 @@  static bool gen_ldptr(DisasContext *ctx, arg_rr_i *a, MemOp mop)
         tcg_gen_addi_tl(temp, addr, a->imm);
         addr = temp;
     }
+    addr = va32_address(ctx, addr);
 
     tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop);
     gen_set_gpr(a->rd, dest, EXT_NONE);
@@ -154,6 +163,7 @@  static bool gen_stptr(DisasContext *ctx, arg_rr_i *a, MemOp mop)
         tcg_gen_addi_tl(temp, addr, a->imm);
         addr = temp;
     }
+    addr = va32_address(ctx, addr);
 
     tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, mop);
     return true;
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
index f1e5fe4cf8..9cd2f13778 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -208,6 +208,16 @@  static void set_fpr(int reg_num, TCGv val)
                    offsetof(CPULoongArchState, fpr[reg_num].vreg.D(0)));
 }
 
+static TCGv va32_address(DisasContext *ctx, TCGv addr)
+{
+    if (ctx->va32) {
+        TCGv temp = tcg_temp_new();
+        tcg_gen_ext32u_tl(temp, addr);
+        addr = temp;
+    }
+    return addr;
+}
+
 #include "decode-insns.c.inc"
 #include "insn_trans/trans_arith.c.inc"
 #include "insn_trans/trans_shift.c.inc"