It was found that running libquantum on riscv-linux qemu produced an incorrect result. After investigation, FP registers are not saved during context switch due to incorrect mstatus.FS.
Because ctx->mstatus_fs changes dynamically during runtime, we should remove the mstatus_fs check at the translation stage. Signed-off-by: ShihPo Hung <shihpo.h...@sifive.com> Cc: Palmer Dabbelt <pal...@dabbelt.com> Cc: Alistair Francis <alistair.fran...@wdc.com> Cc: Sagar Karandikar <sag...@eecs.berkeley.edu> Cc: Bastian Koppelmann <kbast...@mail.uni-paderborn.de> Cc: qemu-ri...@nongnu.org --- target/riscv/csr.c | 3 +-- target/riscv/insn_trans/trans_rvd.inc.c | 1 - target/riscv/insn_trans/trans_rvf.inc.c | 1 - target/riscv/translate.c | 6 +----- 4 files changed, 2 insertions(+), 9 deletions(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index da02f9f..0e34c29 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -341,8 +341,7 @@ static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val) mstatus = (mstatus & ~mask) | (val & mask); - dirty = (riscv_cpu_fp_enabled(env) && - ((mstatus & MSTATUS_FS) == MSTATUS_FS)) | + dirty = ((mstatus & MSTATUS_FS) == MSTATUS_FS) | ((mstatus & MSTATUS_XS) == MSTATUS_XS); mstatus = set_field(mstatus, MSTATUS_SD, dirty); env->mstatus = mstatus; diff --git a/target/riscv/insn_trans/trans_rvd.inc.c b/target/riscv/insn_trans/trans_rvd.inc.c index 393fa02..ea1044f 100644 --- a/target/riscv/insn_trans/trans_rvd.inc.c +++ b/target/riscv/insn_trans/trans_rvd.inc.c @@ -43,7 +43,6 @@ static bool trans_fsd(DisasContext *ctx, arg_fsd *a) tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], t0, ctx->mem_idx, MO_TEQ); - mark_fs_dirty(ctx); tcg_temp_free(t0); return true; } diff --git a/target/riscv/insn_trans/trans_rvf.inc.c b/target/riscv/insn_trans/trans_rvf.inc.c index 172dbfa..e23cd63 100644 --- a/target/riscv/insn_trans/trans_rvf.inc.c +++ b/target/riscv/insn_trans/trans_rvf.inc.c @@ -52,7 +52,6 @@ static bool trans_fsw(DisasContext *ctx, arg_fsw *a) tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], t0, ctx->mem_idx, MO_TEUL); tcg_temp_free(t0); - mark_fs_dirty(ctx); return true; } diff --git a/target/riscv/translate.c b/target/riscv/translate.c index ab6a891..4ef7300 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -386,15 +386,11 @@ static void gen_store_c(DisasContext *ctx, uint32_t opc, int rs1, int rs2, static void mark_fs_dirty(DisasContext *ctx) { TCGv tmp; - if (ctx->mstatus_fs == MSTATUS_FS) { - return; - } - /* Remember the state change for the rest of the TB. */ - ctx->mstatus_fs = MSTATUS_FS; tmp = tcg_temp_new(); tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus)); tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS); + tcg_gen_ori_tl(tmp, tmp, MSTATUS_SD); tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus)); tcg_temp_free(tmp); } -- 2.7.4