@samitouri / QOSamiQemu / commits / 56db2b7eac

target/riscv: Implement runtime data endianness via MSTATUS bits

Make data accesses honour the MSTATUS MBE/SBE/UBE endianness bits instead of being hardcoded to little-endian. Update mo_endian_env() to pick the bit corresponding to the current privilege level (MBE for M, SBE for S, UBE for U). Remove the now unused mo_endian() helper. Note, TB_FLAGS has no free bits, so the data endianness is carried in the extended RISC-V TB flags stored in cs_base. It uses EXT_TB_FLAGS.BIG_ENDIAN at bit 33, leaving bit 32 for EXT_TB_FLAGS.ALTFMT. This keys TBs correctly on the current data endianness. Instruction fetches remain MO_LE unconditionally; RISC-V instructions are always little-endian per the ISA specification. Update the disassembler comment to clarify that BFD_ENDIAN_LITTLE is correct. Signed-off-by: Djordje Todorovic <djordje.todorovic@htecgroup.com> Co-developed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com> Message-ID: <20260527201348.29511-3-philmd@linaro.org> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>

Djordje Todorovic committed May 27, 2026 at 22:13 UTC 56db2b7eac0b00149d8996f8575e7f389a0056b4
5 files changed +28 -26
target/riscv/cpu.c
+2 -5
@@ -831,11 +831,8 @@ static void riscv_cpu_disas_set_info(const CPUState *s, disassemble_info *info)
831 info->target_info = &cpu->cfg;
832
833 /*
834 - * A couple of bits in MSTATUS set the endianness:
835 - * - MSTATUS_UBE (User-mode),
836 - * - MSTATUS_SBE (Supervisor-mode),
837 - * - MSTATUS_MBE (Machine-mode)
838 - * but we don't implement that yet.
834 + * RISC-V instructions are always little-endian, regardless of the
835 + * data endianness configured via MSTATUS UBE/SBE/MBE bits.
836 */
837 info->endian = BFD_ENDIAN_LITTLE;
838
target/riscv/cpu.h
+1
@@ -714,6 +714,7 @@ FIELD(TB_FLAGS, PM_SIGNEXTEND, 31, 1)
714
715 FIELD(EXT_TB_FLAGS, MISA_EXT, 0, 32)
716 FIELD(EXT_TB_FLAGS, ALTFMT, 32, 1)
717 +FIELD(EXT_TB_FLAGS, BIG_ENDIAN, 33, 1)
718
719 #ifdef TARGET_RISCV32
720 #define riscv_cpu_mxl(env) ((void)(env), MXL_RV32)
target/riscv/internals.h
+21 -8
@@ -62,16 +62,29 @@ static inline bool mmuidx_2stage(int mmu_idx)
62 return mmu_idx & MMU_2STAGE_BIT;
63 }
64
65 +/*
66 + * Return the endianness for the current privilege
67 + * level, based on the MSTATUS MBE/SBE/UBE bits.
68 + */
69 static inline MemOp mo_endian_env(CPURISCVState *env)
70 {
67 - /*
68 - * A couple of bits in MSTATUS set the endianness:
69 - * - MSTATUS_UBE (User-mode),
70 - * - MSTATUS_SBE (Supervisor-mode),
71 - * - MSTATUS_MBE (Machine-mode)
72 - * but we don't implement that yet.
73 - */
74 - return MO_LE;
71 + bool be = false;
72 +#if !defined(CONFIG_USER_ONLY)
73 + switch (env->priv) {
74 + case PRV_M:
75 + be = env->mstatus & MSTATUS_MBE;
76 + break;
77 + case PRV_S:
78 + be = env->mstatus & MSTATUS_SBE;
79 + break;
80 + case PRV_U:
81 + be = env->mstatus & MSTATUS_UBE;
82 + break;
83 + default:
84 + g_assert_not_reached();
85 + }
86 +#endif
87 + return be ? MO_BE : MO_LE;
88 }
89
90 /* share data between vector helpers and decode code */
target/riscv/tcg/tcg-cpu.c
+2
@@ -194,6 +194,8 @@ static TCGTBCPUState riscv_get_tb_cpu_state(CPUState *cs)
194 flags = FIELD_DP32(flags, TB_FLAGS, PM_SIGNEXTEND, pm_signext);
195
196 ext_flags = FIELD_DP64(ext_flags, EXT_TB_FLAGS, MISA_EXT, env->misa_ext);
197 + ext_flags = FIELD_DP64(ext_flags, EXT_TB_FLAGS, BIG_ENDIAN,
198 + mo_endian_env(env) == MO_BE);
199
200 return (TCGTBCPUState){
201 .pc = env->xl == MXL_RV32 ? env->pc & UINT32_MAX : env->pc,
target/riscv/translate.c
+2 -13
@@ -130,18 +130,6 @@ static inline bool has_ext(DisasContext *ctx, uint32_t ext)
130 return ctx->misa_ext & ext;
131 }
132
133 -static inline MemOp mo_endian(DisasContext *ctx)
134 -{
135 - /*
136 - * A couple of bits in MSTATUS set the endianness:
137 - * - MSTATUS_UBE (User-mode),
138 - * - MSTATUS_SBE (Supervisor-mode),
139 - * - MSTATUS_MBE (Machine-mode)
140 - * but we don't implement that yet.
141 - */
142 - return MO_LE;
143 -}
144 -
133 #ifdef TARGET_RISCV32
134 #define get_xl(ctx) MXL_RV32
135 #elif defined(CONFIG_USER_ONLY)
@@ -1365,7 +1353,8 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
1353 ctx->zero = tcg_constant_tl(0);
1354 ctx->virt_inst_excp = false;
1355 ctx->decoders = cpu->decoders;
1368 - ctx->mo_endianness = mo_endian(ctx);
1356 + ctx->mo_endianness = FIELD_EX64(ext_tb_flags, EXT_TB_FLAGS, BIG_ENDIAN)
1357 + ? MO_BE : MO_LE;
1358 }
1359
1360 static void riscv_tr_tb_start(DisasContextBase *db, CPUState *cpu)