Add a big_endian field to RISCVCPUConfig and wire it into the CPU reset path. When cfg.big_endian is set, riscv_cpu_reset_hold() writes 1 into the MSTATUS MBE/SBE/UBE fields using set_field(); otherwise it writes 0. This makes the reset value deterministic on both cold and warm reset.
This models fixed-endian harts, not mixed-endian implementations where the guest can toggle MBE/SBE/UBE at runtime. The MBE/SBE/UBE bits are not included in the writable mask of any mstatus/mstatush/sstatus CSR write path (unchanged by this series), so the value chosen at reset is effectively hardwired per section 3.1.6.5 of the RISC-V Privileged Specification. The user-facing property and documentation are added in a later patch, once the full endianness support is in place. Also update the disassembler comment to clarify that BFD_ENDIAN_LITTLE is correct because RISC-V instructions are always little-endian per the ISA specification. Signed-off-by: Djordje Todorovic <[email protected]> --- target/riscv/cpu.c | 14 +++++++++----- target/riscv/cpu_cfg_fields.h.inc | 1 + 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index ce15a17c37..42d1b3662c 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -720,6 +720,13 @@ static void riscv_cpu_reset_hold(Object *obj, ResetType type) env->mstatus = set_field(env->mstatus, MSTATUS_MDT, 1); } } + /* + * Model fixed-endian harts: MBE/SBE/UBE are initialized from the + * CPU configuration and are intentionally not writable via status CSRs. + */ + env->mstatus = set_field(env->mstatus, MSTATUS_MBE, cpu->cfg.big_endian); + env->mstatus = set_field(env->mstatus, MSTATUS_SBE, cpu->cfg.big_endian); + env->mstatus = set_field(env->mstatus, MSTATUS_UBE, cpu->cfg.big_endian); env->mcause = 0; env->miclaim = MIP_SGEIP; env->pc = env->resetvec; @@ -807,11 +814,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; diff --git a/target/riscv/cpu_cfg_fields.h.inc b/target/riscv/cpu_cfg_fields.h.inc index 734fa079f2..9eb47af0a7 100644 --- a/target/riscv/cpu_cfg_fields.h.inc +++ b/target/riscv/cpu_cfg_fields.h.inc @@ -157,6 +157,7 @@ BOOL_FIELD(ext_xmipscmov) BOOL_FIELD(ext_xmipslsp) BOOL_FIELD(ext_xlrbr) +BOOL_FIELD(big_endian) BOOL_FIELD(mmu) BOOL_FIELD(pmp) BOOL_FIELD(debug) -- 2.34.1
