@samitouri / QOSamiQemu / commits / c4e6bc6385

target/riscv: Fix size of gpr and gprh

gprh is only needed for TARGET_RISCV64 when modeling 128-bit registers, fixing their size to 64 bits makes sense. gpr is also fixed to 64 bits since all direct uses of env->gpr correctly zero extend/truncate to/from target_ulong, meaning !TARGET_RISCV64 will behave as expected. We do however need to be a bit careful when mapping 64-bit fields to 32-bit TCGv globals on big endian hosts. Note, the cpu/rv128 VMSTATE version is bumped, breaking migration from older versions. Signed-off-by: Anton Johansson <anjo@rev.ng> Acked-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Message-ID: <20260520125406.28693-2-anjo@rev.ng> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>

Anton Johansson committed May 20, 2026 at 14:53 UTC c4e6bc63853c7831737d41b7ff83333f8aa9fe52
5 files changed +22 -10
target/riscv/cpu.c
+1 -1
@@ -612,7 +612,7 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags)
612 #endif
613
614 for (i = 0; i < 32; i++) {
615 - qemu_fprintf(f, " %-8s " TARGET_FMT_lx,
615 + qemu_fprintf(f, " %-8s %" PRIx64,
616 riscv_int_regnames[i], env->gpr[i]);
617 if ((i & 3) == 3) {
618 qemu_fprintf(f, "\n");
target/riscv/cpu.h
+2 -2
@@ -214,8 +214,8 @@ typedef struct PMUFixedCtrState {
214 } PMUFixedCtrState;
215
216 struct CPUArchState {
217 - target_ulong gpr[32];
218 - target_ulong gprh[32]; /* 64 top bits of the 128-bit registers */
217 + uint64_t gpr[32];
218 + uint64_t gprh[32]; /* 64 top bits of the 128-bit registers */
219
220 /* vector coprocessor state. */
221 uint64_t vreg[32 * RV_VLEN_MAX / 64] QEMU_ALIGNED(16);
target/riscv/machine.c
+4 -4
@@ -178,11 +178,11 @@ static bool rv128_needed(void *opaque)
178
179 static const VMStateDescription vmstate_rv128 = {
180 .name = "cpu/rv128",
181 - .version_id = 1,
182 - .minimum_version_id = 1,
181 + .version_id = 2,
182 + .minimum_version_id = 2,
183 .needed = rv128_needed,
184 .fields = (const VMStateField[]) {
185 - VMSTATE_UINTTL_ARRAY(env.gprh, RISCVCPU, 32),
185 + VMSTATE_UINT64_ARRAY(env.gprh, RISCVCPU, 32),
186 VMSTATE_UINT64(env.mscratchh, RISCVCPU),
187 VMSTATE_UINT64(env.sscratchh, RISCVCPU),
188 VMSTATE_END_OF_LIST()
@@ -449,7 +449,7 @@ const VMStateDescription vmstate_riscv_cpu = {
449 .minimum_version_id = 11,
450 .post_load = riscv_cpu_post_load,
451 .fields = (const VMStateField[]) {
452 - VMSTATE_UINTTL_ARRAY(env.gpr, RISCVCPU, 32),
452 + VMSTATE_UINT64_ARRAY(env.gpr, RISCVCPU, 32),
453 VMSTATE_UINT64_ARRAY(env.fpr, RISCVCPU, 32),
454 VMSTATE_UINT8_ARRAY(env.miprio, RISCVCPU, 64),
455 VMSTATE_UINT8_ARRAY(env.siprio, RISCVCPU, 64),
target/riscv/monitor.c
+1 -1
@@ -248,7 +248,7 @@ static bool reg_is_ulong_integer(CPURISCVState *env, const char *name,
248 target_ulong *val, bool is_gprh)
249 {
250 const char * const *reg_names;
251 - target_ulong *vals;
251 + uint64_t *vals;
252
253 if (is_gprh) {
254 reg_names = riscv_int_regnamesh;
target/riscv/translate.c
+14 -2
@@ -1469,12 +1469,24 @@ void riscv_translate_init(void)
1469 */
1470 cpu_gpr[0] = NULL;
1471 cpu_gprh[0] = NULL;
1472 + /*
1473 + * Be careful with big endian hosts when mapping 64-bit CPUArchState fields
1474 + * to 32-bit TCGv globals. An offset of 4 bytes is applied so the least
1475 + * significant bytes are correctly written to.
1476 + */
1477 +#if HOST_BIG_ENDIAN && !defined(TARGET_RISCV64)
1478 + size_t field_offset = 4;
1479 +#else
1480 + size_t field_offset = 0;
1481 +#endif
1482
1483 for (i = 1; i < 32; i++) {
1484 cpu_gpr[i] = tcg_global_mem_new(tcg_env,
1475 - offsetof(CPURISCVState, gpr[i]), riscv_int_regnames[i]);
1485 + offsetof(CPURISCVState, gpr[i]) + field_offset,
1486 + riscv_int_regnames[i]);
1487 cpu_gprh[i] = tcg_global_mem_new(tcg_env,
1477 - offsetof(CPURISCVState, gprh[i]), riscv_int_regnamesh[i]);
1488 + offsetof(CPURISCVState, gprh[i]) + field_offset,
1489 + riscv_int_regnamesh[i]);
1490 }
1491
1492 for (i = 0; i < 32; i++) {