Browse Source

Fix vsstatus.FS misbehavior (#661)

* Simplify Boolean logic

No functional change intended.

* Apply same logic to virtualize sstatus.XS as used for VS and FS

Though this macro does not seem to be used anywhere today.

* Extract common macro to DRY up code

* Dirty both mstatus and vsstatus FP fields

Fixes https://github.com/riscv/riscv-isa-sim/issues/660
pull/670/head
Scott Johnson 6 years ago
committed by GitHub
parent
commit
853320fc11
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 17
      riscv/decode.h
  2. 28
      riscv/processor.cc

17
riscv/decode.h

@ -217,9 +217,13 @@ private:
#define FRS1 READ_FREG(insn.rs1())
#define FRS2 READ_FREG(insn.rs2())
#define FRS3 READ_FREG(insn.rs3())
#define dirty_fp_state (STATE.mstatus |= MSTATUS_FS | (xlen == 64 ? MSTATUS64_SD : MSTATUS32_SD))
#define dirty_ext_state (STATE.mstatus |= MSTATUS_XS | (xlen == 64 ? MSTATUS64_SD : MSTATUS32_SD))
#define dirty_vs_state (STATE.mstatus |= MSTATUS_VS | (xlen == 64 ? MSTATUS64_SD : MSTATUS32_SD))
#define dirty_mstatus(bits) ({ reg_t dirties = (bits) | (xlen == 64 ? MSTATUS64_SD : MSTATUS32_SD); \
STATE.mstatus |= dirties; \
if (STATE.v) STATE.vsstatus |= dirties; \
})
#define dirty_fp_state dirty_mstatus(MSTATUS_FS)
#define dirty_ext_state dirty_mstatus(MSTATUS_XS)
#define dirty_vs_state dirty_mstatus(MSTATUS_VS)
#define DO_WRITE_FREG(reg, value) (STATE.FPR.write(reg, value), dirty_fp_state)
#define WRITE_FRD(value) WRITE_FREG(insn.rd(), value)
@ -242,10 +246,9 @@ private:
#define require_extension(s) require(p->supports_extension(s))
#define require_either_extension(A,B) require(p->supports_extension(A) || p->supports_extension(B));
#define require_impl(s) require(p->supports_impl(s))
#define require_fp require((((STATE.mstatus & MSTATUS_FS) != 0) && (STATE.v == 0)) || (((STATE.mstatus & MSTATUS_FS) != 0) && ((STATE.vsstatus & SSTATUS_FS) != 0) && STATE.v))
#define require_accelerator require((STATE.mstatus & MSTATUS_XS) != 0)
#define require_vector_vs require((((STATE.mstatus & MSTATUS_VS) != 0) && (STATE.v == 0)) || (((STATE.mstatus & MSTATUS_VS) != 0) && ((STATE.vsstatus & SSTATUS_VS) != 0) && STATE.v))
#define require_fp require(((STATE.mstatus & MSTATUS_FS) != 0) && ((STATE.v == 0) || ((STATE.vsstatus & SSTATUS_FS) != 0)))
#define require_accelerator require(((STATE.mstatus & MSTATUS_XS) != 0) && ((STATE.v == 0) || ((STATE.vsstatus & SSTATUS_XS) != 0)))
#define require_vector_vs require(((STATE.mstatus & MSTATUS_VS) != 0) && ((STATE.v == 0) || ((STATE.vsstatus & SSTATUS_VS) != 0)))
#define require_vector(alu) \
do { \
require_vector_vs; \

28
riscv/processor.cc

@ -644,34 +644,6 @@ void processor_t::set_virt(bool virt)
* set_virt() is always used in conjucter with set_privilege() and
* set_privilege() will flush TLB unconditionally.
*/
if (state.v and !virt) {
/*
* When transitioning from virt-on (VS/VU) to virt-off (HS/M)
* we should mark Host extension status (i.e. FS, VS, and XS
* bits) as dirty when Guest/VM extension status is dirty and
* Host extension status is initial, clean, or dirty.
*/
if ((state.vsstatus & SSTATUS_FS) &&
((state.mstatus & SSTATUS_FS) == SSTATUS_FS)) {
state.vsstatus |= SSTATUS_FS;
}
if (supports_extension('V') &&
(state.vsstatus & SSTATUS_VS) &&
((state.mstatus & SSTATUS_VS) == SSTATUS_VS)) {
state.vsstatus |= SSTATUS_VS;
}
if ((state.vsstatus & SSTATUS_XS) &&
((state.mstatus & SSTATUS_XS) == SSTATUS_XS)) {
state.vsstatus |= SSTATUS_XS;
}
/* Update SD bit of Host */
state.vsstatus &= (xlen == 64 ? ~SSTATUS64_SD : ~SSTATUS32_SD);
if (((state.mstatus & SSTATUS_FS) == SSTATUS_FS) ||
((state.vsstatus & SSTATUS_VS) == SSTATUS_VS) ||
((state.vsstatus & SSTATUS_XS) == SSTATUS_XS)) {
state.vsstatus |= (xlen == 64 ? SSTATUS64_SD : SSTATUS32_SD);
}
}
mask = SSTATUS_VS_MASK;
mask |= (supports_extension('V') ? SSTATUS_VS : 0);
mask |= (xlen == 64 ? SSTATUS64_SD : SSTATUS32_SD);

Loading…
Cancel
Save