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~

Reply via email to