mirror of
https://github.com/qemu/qemu.git
synced 2026-07-08 17:46:10 +00:00
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>
This commit is contained in:
committed by
Alistair Francis
parent
11c2c6e025
commit
56db2b7eac
@@ -831,11 +831,8 @@ static void riscv_cpu_disas_set_info(const CPUState *s, disassemble_info *info)
|
||||
info->target_info = &cpu->cfg;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* RISC-V instructions are always little-endian, regardless of the
|
||||
* data endianness configured via MSTATUS UBE/SBE/MBE bits.
|
||||
*/
|
||||
info->endian = BFD_ENDIAN_LITTLE;
|
||||
|
||||
|
||||
@@ -714,6 +714,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)
|
||||
|
||||
@@ -62,16 +62,29 @@ static inline bool mmuidx_2stage(int mmu_idx)
|
||||
return mmu_idx & MMU_2STAGE_BIT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the endianness for the current privilege
|
||||
* level, based on the MSTATUS MBE/SBE/UBE bits.
|
||||
*/
|
||||
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;
|
||||
bool be = false;
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
switch (env->priv) {
|
||||
case PRV_M:
|
||||
be = env->mstatus & MSTATUS_MBE;
|
||||
break;
|
||||
case PRV_S:
|
||||
be = env->mstatus & MSTATUS_SBE;
|
||||
break;
|
||||
case PRV_U:
|
||||
be = env->mstatus & MSTATUS_UBE;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
#endif
|
||||
return be ? MO_BE : MO_LE;
|
||||
}
|
||||
|
||||
/* share data between vector helpers and decode code */
|
||||
|
||||
@@ -194,6 +194,8 @@ 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);
|
||||
ext_flags = FIELD_DP64(ext_flags, EXT_TB_FLAGS, BIG_ENDIAN,
|
||||
mo_endian_env(env) == MO_BE);
|
||||
|
||||
return (TCGTBCPUState){
|
||||
.pc = env->xl == MXL_RV32 ? env->pc & UINT32_MAX : env->pc,
|
||||
|
||||
@@ -130,18 +130,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)
|
||||
@@ -1365,7 +1353,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 = mo_endian(ctx);
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user