Make data accesses honour the MSTATUS MBE/SBE/UBE endianness bits instead of being hardcoded to little-endian. A new helper, riscv_cpu_data_is_big_endian(), picks the bit corresponding to the current privilege level (MBE for M, SBE for S, UBE for U). The existing mo_endian_env() wrapper in internals.h now returns MO_BE or MO_LE based on that helper, so the hypervisor load/store helpers in op_helper.c pick up the runtime endianness automatically.
On the translator side, DisasContext gains a mo_endianness field holding MO_BE or MO_LE, which the generated load/store ops OR into their MemOp. The trivial mo_endian() wrapper is dropped and call sites reference ctx->mo_endianness directly. TB_FLAGS has no free bits, so the endianness is carried into the translator through bit 32 of cs_base (alongside misa_ext in bits 0-25). This keys TBs correctly on the current data endianness. The cs_base comment in include/exec/translation-block.h is updated to document the RISC-V usage. Instruction fetches remain MO_LE unconditionally; RISC-V instructions are always little-endian per the ISA specification. Signed-off-by: Djordje Todorovic <[email protected]> --- target/riscv/cpu.h | 23 +++++++++++++++++++ target/riscv/insn_trans/trans_rva.c.inc | 4 ++-- target/riscv/insn_trans/trans_rvd.c.inc | 4 ++-- target/riscv/insn_trans/trans_rvf.c.inc | 4 ++-- target/riscv/insn_trans/trans_rvi.c.inc | 8 +++---- target/riscv/insn_trans/trans_rvzacas.c.inc | 4 ++-- target/riscv/insn_trans/trans_rvzalasr.c.inc | 4 ++-- target/riscv/insn_trans/trans_rvzce.c.inc | 4 ++-- target/riscv/insn_trans/trans_rvzfh.c.inc | 4 ++-- target/riscv/insn_trans/trans_rvzicfiss.c.inc | 4 ++-- target/riscv/insn_trans/trans_xmips.c.inc | 8 +++---- target/riscv/insn_trans/trans_xthead.c.inc | 16 ++++++------- target/riscv/insn_trans/trans_zilsd.c.inc | 4 ++-- target/riscv/internals.h | 9 +------- target/riscv/tcg/tcg-cpu.c | 3 +++ target/riscv/translate.c | 22 ++++++------------ 16 files changed, 68 insertions(+), 57 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 81c41e3429..1f2d0777e8 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -705,6 +705,7 @@ FIELD(TB_FLAGS, PM_SIGNEXTEND, 31, 1) FIELD(EXT_TB_FLAGS, MISA_EXT, 0, 32) FIELD(EXT_TB_FLAGS, ALTFMT, 32, 1) +FIELD(EXT_TB_FLAGS, BIG_ENDIAN, 33, 1) #ifdef TARGET_RISCV32 #define riscv_cpu_mxl(env) ((void)(env), MXL_RV32) @@ -721,6 +722,28 @@ static inline const RISCVCPUConfig *riscv_cpu_cfg(CPURISCVState *env) return &env_archcpu(env)->cfg; } +/* + * Return true if data accesses are big-endian for the current privilege + * level, based on the MSTATUS MBE/SBE/UBE bits. + */ +static inline bool riscv_cpu_data_is_big_endian(CPURISCVState *env) +{ +#if defined(CONFIG_USER_ONLY) + return false; +#else + switch (env->priv) { + case PRV_M: + return env->mstatus & MSTATUS_MBE; + case PRV_S: + return env->mstatus & MSTATUS_SBE; + case PRV_U: + return env->mstatus & MSTATUS_UBE; + default: + g_assert_not_reached(); + } +#endif +} + #if !defined(CONFIG_USER_ONLY) static inline int cpu_address_mode(CPURISCVState *env) { diff --git a/target/riscv/insn_trans/trans_rva.c.inc b/target/riscv/insn_trans/trans_rva.c.inc index 62c0fe673d..44c1696fe4 100644 --- a/target/riscv/insn_trans/trans_rva.c.inc +++ b/target/riscv/insn_trans/trans_rva.c.inc @@ -35,7 +35,7 @@ static bool gen_lr(DisasContext *ctx, arg_atomic *a, MemOp mop) TCGv src1; mop |= MO_ALIGN; - mop |= mo_endian(ctx); + mop |= ctx->mo_endianness; decode_save_opc(ctx, 0); src1 = get_address(ctx, a->rs1, 0); @@ -65,7 +65,7 @@ static bool gen_sc(DisasContext *ctx, arg_atomic *a, MemOp mop) TCGLabel *l2 = gen_new_label(); mop |= MO_ALIGN; - mop |= mo_endian(ctx); + mop |= ctx->mo_endianness; decode_save_opc(ctx, 0); src1 = get_address(ctx, a->rs1, 0); diff --git a/target/riscv/insn_trans/trans_rvd.c.inc b/target/riscv/insn_trans/trans_rvd.c.inc index ffea0c2a1f..3b9a745520 100644 --- a/target/riscv/insn_trans/trans_rvd.c.inc +++ b/target/riscv/insn_trans/trans_rvd.c.inc @@ -60,7 +60,7 @@ static bool trans_fld(DisasContext *ctx, arg_fld *a) } else { memop |= MO_ATOM_IFALIGN; } - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; decode_save_opc(ctx, 0); addr = get_address(ctx, a->rs1, a->imm); @@ -85,7 +85,7 @@ static bool trans_fsd(DisasContext *ctx, arg_fsd *a) } else { memop |= MO_ATOM_IFALIGN; } - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; decode_save_opc(ctx, 0); addr = get_address(ctx, a->rs1, a->imm); diff --git a/target/riscv/insn_trans/trans_rvf.c.inc b/target/riscv/insn_trans/trans_rvf.c.inc index 89fb0f604a..e935523c93 100644 --- a/target/riscv/insn_trans/trans_rvf.c.inc +++ b/target/riscv/insn_trans/trans_rvf.c.inc @@ -48,7 +48,7 @@ static bool trans_flw(DisasContext *ctx, arg_flw *a) REQUIRE_FPU; REQUIRE_EXT(ctx, RVF); - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; if (ctx->cfg_ptr->ext_zama16b) { memop |= MO_ATOM_WITHIN16; } @@ -71,7 +71,7 @@ static bool trans_fsw(DisasContext *ctx, arg_fsw *a) REQUIRE_FPU; REQUIRE_EXT(ctx, RVF); - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; if (ctx->cfg_ptr->ext_zama16b) { memop |= MO_ATOM_WITHIN16; } diff --git a/target/riscv/insn_trans/trans_rvi.c.inc b/target/riscv/insn_trans/trans_rvi.c.inc index 2c82ae41a7..2de74fac3a 100644 --- a/target/riscv/insn_trans/trans_rvi.c.inc +++ b/target/riscv/insn_trans/trans_rvi.c.inc @@ -392,7 +392,7 @@ static bool gen_load_i128(DisasContext *ctx, arg_lb *a, MemOp memop) } } else { tcg_gen_qemu_ld_i128(t16, addrl, ctx->mem_idx, memop); - if (mo_endian(ctx) == MO_LE) { + if (ctx->mo_endianness == MO_LE) { tcg_gen_extr_i128_i64(tl, th, t16); } else { tcg_gen_extr_i128_i64(th, tl, t16); @@ -409,7 +409,7 @@ static bool gen_load(DisasContext *ctx, arg_lb *a, MemOp memop) { bool out; - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; if (ctx->cfg_ptr->ext_zama16b) { memop |= MO_ATOM_WITHIN16; } @@ -508,7 +508,7 @@ static bool gen_store_i128(DisasContext *ctx, arg_sb *a, MemOp memop) tcg_gen_ext_tl_i64(tl, src2l); tcg_gen_ext_tl_i64(th, src2h); - if (mo_endian(ctx) == MO_LE) { + if (ctx->mo_endianness == MO_LE) { tcg_gen_concat_i64_i128(t16, tl, th); } else { tcg_gen_concat_i64_i128(t16, th, tl); @@ -520,7 +520,7 @@ static bool gen_store_i128(DisasContext *ctx, arg_sb *a, MemOp memop) static bool gen_store(DisasContext *ctx, arg_sb *a, MemOp memop) { - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; if (ctx->cfg_ptr->ext_zama16b) { memop |= MO_ATOM_WITHIN16; } diff --git a/target/riscv/insn_trans/trans_rvzacas.c.inc b/target/riscv/insn_trans/trans_rvzacas.c.inc index 8d94b83ce9..79bca1e957 100644 --- a/target/riscv/insn_trans/trans_rvzacas.c.inc +++ b/target/riscv/insn_trans/trans_rvzacas.c.inc @@ -76,7 +76,7 @@ static bool gen_cmpxchg64(DisasContext *ctx, arg_atomic *a, MemOp mop) TCGv src1 = get_address(ctx, a->rs1, 0); TCGv_i64 src2 = get_gpr_pair(ctx, a->rs2); - mop |= mo_endian(ctx); + mop |= ctx->mo_endianness; decode_save_opc(ctx, RISCV_UW2_ALWAYS_STORE_AMO); tcg_gen_atomic_cmpxchg_i64(dest, src1, dest, src2, ctx->mem_idx, mop); @@ -121,7 +121,7 @@ static bool trans_amocas_q(DisasContext *ctx, arg_amocas_q *a) TCGv_i64 desth = get_gpr(ctx, a->rd == 0 ? 0 : a->rd + 1, EXT_NONE); MemOp memop = MO_ALIGN | MO_UO; - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; tcg_gen_concat_i64_i128(src2, src2l, src2h); tcg_gen_concat_i64_i128(dest, destl, desth); decode_save_opc(ctx, RISCV_UW2_ALWAYS_STORE_AMO); diff --git a/target/riscv/insn_trans/trans_rvzalasr.c.inc b/target/riscv/insn_trans/trans_rvzalasr.c.inc index 0f307affec..79b0b2c63b 100644 --- a/target/riscv/insn_trans/trans_rvzalasr.c.inc +++ b/target/riscv/insn_trans/trans_rvzalasr.c.inc @@ -29,7 +29,7 @@ static bool gen_load_acquire(DisasContext *ctx, arg_lb_aqrl *a, MemOp memop) return false; } - memop |= MO_ALIGN | mo_endian(ctx); + memop |= MO_ALIGN | ctx->mo_endianness; memop |= (ctx->cfg_ptr->ext_zama16b) ? MO_ATOM_WITHIN16 : 0; tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, memop); @@ -79,7 +79,7 @@ static bool gen_store_release(DisasContext *ctx, arg_sb_aqrl *a, MemOp memop) return false; } - memop |= MO_ALIGN | mo_endian(ctx); + memop |= MO_ALIGN | ctx->mo_endianness; memop |= (ctx->cfg_ptr->ext_zama16b) ? MO_ATOM_WITHIN16 : 0; /* Add a memory barrier implied by RL (mandatory) and AQ (optional) */ diff --git a/target/riscv/insn_trans/trans_rvzce.c.inc b/target/riscv/insn_trans/trans_rvzce.c.inc index 0d3ba40e52..71b4ca5473 100644 --- a/target/riscv/insn_trans/trans_rvzce.c.inc +++ b/target/riscv/insn_trans/trans_rvzce.c.inc @@ -185,7 +185,7 @@ static bool gen_pop(DisasContext *ctx, arg_cmpp *a, bool ret, bool ret_val) tcg_gen_addi_tl(addr, sp, stack_adj - reg_size); - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; for (i = X_Sn + 11; i >= 0; i--) { if (reg_bitmap & (1 << i)) { TCGv dest = dest_gpr(ctx, i); @@ -239,7 +239,7 @@ static bool trans_cm_push(DisasContext *ctx, arg_cm_push *a) tcg_gen_subi_tl(addr, sp, reg_size); - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; for (i = X_Sn + 11; i >= 0; i--) { if (reg_bitmap & (1 << i)) { TCGv val = get_gpr(ctx, i, EXT_NONE); diff --git a/target/riscv/insn_trans/trans_rvzfh.c.inc b/target/riscv/insn_trans/trans_rvzfh.c.inc index 791ee51f65..f36b46c211 100644 --- a/target/riscv/insn_trans/trans_rvzfh.c.inc +++ b/target/riscv/insn_trans/trans_rvzfh.c.inc @@ -49,7 +49,7 @@ static bool trans_flh(DisasContext *ctx, arg_flh *a) REQUIRE_FPU; REQUIRE_ZFHMIN_OR_ZFBFMIN(ctx); - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; decode_save_opc(ctx, 0); t0 = get_gpr(ctx, a->rs1, EXT_NONE); if (a->imm) { @@ -74,7 +74,7 @@ static bool trans_fsh(DisasContext *ctx, arg_fsh *a) REQUIRE_FPU; REQUIRE_ZFHMIN_OR_ZFBFMIN(ctx); - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; decode_save_opc(ctx, 0); t0 = get_gpr(ctx, a->rs1, EXT_NONE); if (a->imm) { diff --git a/target/riscv/insn_trans/trans_rvzicfiss.c.inc b/target/riscv/insn_trans/trans_rvzicfiss.c.inc index 0b6ad57965..43f586dce9 100644 --- a/target/riscv/insn_trans/trans_rvzicfiss.c.inc +++ b/target/riscv/insn_trans/trans_rvzicfiss.c.inc @@ -105,7 +105,7 @@ static bool trans_ssamoswap_w(DisasContext *ctx, arg_amoswap_w *a) decode_save_opc(ctx, RISCV_UW2_ALWAYS_STORE_AMO); src1 = get_address(ctx, a->rs1, 0); - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; tcg_gen_atomic_xchg_tl(dest, src1, src2, SS_MMU_INDEX(ctx), memop); gen_set_gpr(ctx, a->rd, dest); return true; @@ -135,7 +135,7 @@ static bool trans_ssamoswap_d(DisasContext *ctx, arg_amoswap_w *a) decode_save_opc(ctx, RISCV_UW2_ALWAYS_STORE_AMO); src1 = get_address(ctx, a->rs1, 0); - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; tcg_gen_atomic_xchg_tl(dest, src1, src2, SS_MMU_INDEX(ctx), memop); gen_set_gpr(ctx, a->rd, dest); return true; diff --git a/target/riscv/insn_trans/trans_xmips.c.inc b/target/riscv/insn_trans/trans_xmips.c.inc index c1a30156d3..1b9993a9b0 100644 --- a/target/riscv/insn_trans/trans_xmips.c.inc +++ b/target/riscv/insn_trans/trans_xmips.c.inc @@ -47,7 +47,7 @@ static bool trans_ccmov(DisasContext *ctx, arg_ccmov *a) /* Load Doubleword Pair. */ static bool trans_ldp(DisasContext *ctx, arg_ldp *a) { - MemOp memop = MO_SQ | mo_endian(ctx); + MemOp memop = MO_SQ | ctx->mo_endianness; REQUIRE_XMIPSLSP(ctx); REQUIRE_64_OR_128BIT(ctx); @@ -71,7 +71,7 @@ static bool trans_ldp(DisasContext *ctx, arg_ldp *a) /* Load Word Pair. */ static bool trans_lwp(DisasContext *ctx, arg_lwp *a) { - MemOp memop = MO_SL | mo_endian(ctx); + MemOp memop = MO_SL | ctx->mo_endianness; REQUIRE_XMIPSLSP(ctx); @@ -94,7 +94,7 @@ static bool trans_lwp(DisasContext *ctx, arg_lwp *a) /* Store Doubleword Pair. */ static bool trans_sdp(DisasContext *ctx, arg_sdp *a) { - MemOp memop = MO_UQ | mo_endian(ctx); + MemOp memop = MO_UQ | ctx->mo_endianness; REQUIRE_XMIPSLSP(ctx); REQUIRE_64_OR_128BIT(ctx); @@ -116,7 +116,7 @@ static bool trans_sdp(DisasContext *ctx, arg_sdp *a) /* Store Word Pair. */ static bool trans_swp(DisasContext *ctx, arg_swp *a) { - MemOp memop = MO_SL | mo_endian(ctx); + MemOp memop = MO_SL | ctx->mo_endianness; REQUIRE_XMIPSLSP(ctx); diff --git a/target/riscv/insn_trans/trans_xthead.c.inc b/target/riscv/insn_trans/trans_xthead.c.inc index f8b95c6498..f4e3051000 100644 --- a/target/riscv/insn_trans/trans_xthead.c.inc +++ b/target/riscv/insn_trans/trans_xthead.c.inc @@ -349,7 +349,7 @@ static bool gen_fload_idx(DisasContext *ctx, arg_th_memidx *a, MemOp memop, TCGv_i64 rd = cpu_fpr[a->rd]; TCGv addr = get_th_address_indexed(ctx, a->rs1, a->rs2, a->imm2, zext_offs); - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; tcg_gen_qemu_ld_i64(rd, addr, ctx->mem_idx, memop); if ((memop & MO_SIZE) == MO_32) { gen_nanbox_s(rd, rd); @@ -370,7 +370,7 @@ static bool gen_fstore_idx(DisasContext *ctx, arg_th_memidx *a, MemOp memop, TCGv_i64 rd = cpu_fpr[a->rd]; TCGv addr = get_th_address_indexed(ctx, a->rs1, a->rs2, a->imm2, zext_offs); - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; tcg_gen_qemu_st_i64(rd, addr, ctx->mem_idx, memop); return true; @@ -570,7 +570,7 @@ static bool gen_load_inc(DisasContext *ctx, arg_th_meminc *a, MemOp memop, TCGv rd = dest_gpr(ctx, a->rd); TCGv rs1 = get_gpr(ctx, a->rs1, EXT_NONE); - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; tcg_gen_qemu_ld_tl(rd, addr, ctx->mem_idx, memop); tcg_gen_addi_tl(rs1, rs1, imm); gen_set_gpr(ctx, a->rd, rd); @@ -591,7 +591,7 @@ static bool gen_store_inc(DisasContext *ctx, arg_th_meminc *a, MemOp memop, TCGv data = get_gpr(ctx, a->rd, EXT_NONE); TCGv rs1 = get_gpr(ctx, a->rs1, EXT_NONE); - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, memop); tcg_gen_addi_tl(rs1, rs1, imm); gen_set_gpr(ctx, a->rs1, rs1); @@ -747,7 +747,7 @@ static bool gen_load_idx(DisasContext *ctx, arg_th_memidx *a, MemOp memop, TCGv rd = dest_gpr(ctx, a->rd); TCGv addr = get_th_address_indexed(ctx, a->rs1, a->rs2, a->imm2, zext_offs); - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; tcg_gen_qemu_ld_tl(rd, addr, ctx->mem_idx, memop); gen_set_gpr(ctx, a->rd, rd); @@ -765,7 +765,7 @@ static bool gen_store_idx(DisasContext *ctx, arg_th_memidx *a, MemOp memop, TCGv data = get_gpr(ctx, a->rd, EXT_NONE); TCGv addr = get_th_address_indexed(ctx, a->rs1, a->rs2, a->imm2, zext_offs); - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, memop); return true; @@ -926,7 +926,7 @@ static bool gen_loadpair_tl(DisasContext *ctx, arg_th_pair *a, MemOp memop, addr1 = get_address(ctx, a->rs, imm); addr2 = get_address(ctx, a->rs, memop_size(memop) + imm); - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; tcg_gen_qemu_ld_tl(t1, addr1, ctx->mem_idx, memop); tcg_gen_qemu_ld_tl(t2, addr2, ctx->mem_idx, memop); gen_set_gpr(ctx, a->rd1, t1); @@ -965,7 +965,7 @@ static bool gen_storepair_tl(DisasContext *ctx, arg_th_pair *a, MemOp memop, addr1 = get_address(ctx, a->rs, imm); addr2 = get_address(ctx, a->rs, memop_size(memop) + imm); - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; tcg_gen_qemu_st_tl(data1, addr1, ctx->mem_idx, memop); tcg_gen_qemu_st_tl(data2, addr2, ctx->mem_idx, memop); return true; diff --git a/target/riscv/insn_trans/trans_zilsd.c.inc b/target/riscv/insn_trans/trans_zilsd.c.inc index f50c52f22c..8068cc1aec 100644 --- a/target/riscv/insn_trans/trans_zilsd.c.inc +++ b/target/riscv/insn_trans/trans_zilsd.c.inc @@ -30,7 +30,7 @@ static bool gen_load_i64(DisasContext *ctx, arg_ld *a) TCGv addr = get_address(ctx, a->rs1, a->imm); TCGv_i64 tmp = tcg_temp_new_i64(); - tcg_gen_qemu_ld_i64(tmp, addr, ctx->mem_idx, MO_SQ | mo_endian(ctx)); + tcg_gen_qemu_ld_i64(tmp, addr, ctx->mem_idx, MO_SQ | ctx->mo_endianness); if (a->rd == 0) { return true; @@ -85,7 +85,7 @@ static bool gen_store_i64(DisasContext *ctx, arg_sd *a) } else { tcg_gen_concat_tl_i64(tmp, data_low, data_high); } - tcg_gen_qemu_st_i64(tmp, addr, ctx->mem_idx, MO_SQ | mo_endian(ctx)); + tcg_gen_qemu_st_i64(tmp, addr, ctx->mem_idx, MO_SQ | ctx->mo_endianness); return true; } diff --git a/target/riscv/internals.h b/target/riscv/internals.h index bac6c8032a..dc505a9ab3 100644 --- a/target/riscv/internals.h +++ b/target/riscv/internals.h @@ -64,14 +64,7 @@ static inline bool mmuidx_2stage(int mmu_idx) static inline MemOp mo_endian_env(CPURISCVState *env) { - /* - * A couple of bits in MSTATUS set the endianness: - * - MSTATUS_UBE (User-mode), - * - MSTATUS_SBE (Supervisor-mode), - * - MSTATUS_MBE (Machine-mode) - * but we don't implement that yet. - */ - return MO_LE; + return riscv_cpu_data_is_big_endian(env) ? MO_BE : MO_LE; } /* share data between vector helpers and decode code */ diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index 02c98cc2db..81b56e5a62 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -193,6 +193,9 @@ static TCGTBCPUState riscv_get_tb_cpu_state(CPUState *cs) flags = FIELD_DP32(flags, TB_FLAGS, PM_SIGNEXTEND, pm_signext); ext_flags = FIELD_DP64(ext_flags, EXT_TB_FLAGS, MISA_EXT, env->misa_ext); + if (riscv_cpu_data_is_big_endian(env)) { + ext_flags = FIELD_DP64(ext_flags, EXT_TB_FLAGS, BIG_ENDIAN, 1); + } return (TCGTBCPUState){ .pc = env->xl == MXL_RV32 ? env->pc & UINT32_MAX : env->pc, diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 1e4f340256..35c6b37c0b 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -120,6 +120,8 @@ typedef struct DisasContext { bool fcfi_lp_expected; /* zicfiss extension, if shadow stack was enabled during TB gen */ bool bcfi_enabled; + /* Data endianness from MSTATUS UBE/SBE/MBE */ + MemOp mo_endianness; } DisasContext; static inline bool has_ext(DisasContext *ctx, uint32_t ext) @@ -127,18 +129,6 @@ static inline bool has_ext(DisasContext *ctx, uint32_t ext) return ctx->misa_ext & ext; } -static inline MemOp mo_endian(DisasContext *ctx) -{ - /* - * A couple of bits in MSTATUS set the endianness: - * - MSTATUS_UBE (User-mode), - * - MSTATUS_SBE (Supervisor-mode), - * - MSTATUS_MBE (Machine-mode) - * but we don't implement that yet. - */ - return MO_LE; -} - #ifdef TARGET_RISCV32 #define get_xl(ctx) MXL_RV32 #elif defined(CONFIG_USER_ONLY) @@ -155,7 +145,7 @@ static inline MemOp mo_endian(DisasContext *ctx) #define get_address_xl(ctx) ((ctx)->address_xl) #endif -#define mxl_memop(ctx) ((get_xl(ctx) + 1) | mo_endian(ctx)) +#define mxl_memop(ctx) ((get_xl(ctx) + 1) | (ctx)->mo_endianness) /* The word size for this machine mode. */ static inline int __attribute__((unused)) get_xlen(DisasContext *ctx) @@ -1156,7 +1146,7 @@ static bool gen_amo(DisasContext *ctx, arg_atomic *a, TCGv src1, src2 = get_gpr(ctx, a->rs2, EXT_NONE); MemOp size = mop & MO_SIZE; - mop |= mo_endian(ctx); + mop |= ctx->mo_endianness; if (ctx->cfg_ptr->ext_zama16b && size >= MO_32) { mop |= MO_ATOM_WITHIN16; } else { @@ -1177,7 +1167,7 @@ static bool gen_cmpxchg(DisasContext *ctx, arg_atomic *a, MemOp mop) TCGv src1 = get_address(ctx, a->rs1, 0); TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE); - mop |= mo_endian(ctx); + mop |= ctx->mo_endianness; decode_save_opc(ctx, RISCV_UW2_ALWAYS_STORE_AMO); tcg_gen_atomic_cmpxchg_tl(dest, src1, dest, src2, ctx->mem_idx, mop); @@ -1360,6 +1350,8 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) ctx->zero = tcg_constant_tl(0); ctx->virt_inst_excp = false; ctx->decoders = cpu->decoders; + ctx->mo_endianness = FIELD_EX64(ext_tb_flags, EXT_TB_FLAGS, BIG_ENDIAN) + ? MO_BE : MO_LE; } static void riscv_tr_tb_start(DisasContextBase *db, CPUState *cpu) -- 2.34.1
