From: Andrew Waterman Date: Sat, 6 Feb 2016 02:18:06 +0000 (-0800) Subject: WIP on priv spec v1.9 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=66a37a5104172a874ae72c80480cba4edceb7505;p=riscv-isa-sim.git WIP on priv spec v1.9 --- diff --git a/riscv/decode.h b/riscv/decode.h index f525ff1..1dfeac1 100644 --- a/riscv/decode.h +++ b/riscv/decode.h @@ -177,7 +177,7 @@ private: #define set_field(reg, mask, val) (((reg) & ~(decltype(reg))(mask)) | (((decltype(reg))(val) * ((mask) & ~((mask) << 1))) & (decltype(reg))(mask))) #define require(x) if (unlikely(!(x))) throw trap_illegal_instruction() -#define require_privilege(p) require(get_field(STATE.mstatus, MSTATUS_PRV) >= (p)) +#define require_privilege(p) require(STATE.prv >= (p)) #define require_rv64 require(xlen == 64) #define require_rv32 require(xlen == 32) #define require_extension(s) require(p->supports_extension(s)) @@ -207,10 +207,9 @@ private: #define validate_csr(which, write) ({ \ if (!STATE.serialized) return PC_SERIALIZE; \ STATE.serialized = false; \ - unsigned my_priv = get_field(STATE.mstatus, MSTATUS_PRV); \ unsigned csr_priv = get_field((which), 0x300); \ unsigned csr_read_only = get_field((which), 0xC00) == 3; \ - if (((write) && csr_read_only) || my_priv < csr_priv) \ + if (((write) && csr_read_only) || STATE.prv < csr_priv) \ throw trap_illegal_instruction(); \ (which); }) diff --git a/riscv/encoding.h b/riscv/encoding.h index e9a495f..df04845 100644 --- a/riscv/encoding.h +++ b/riscv/encoding.h @@ -3,37 +3,41 @@ #ifndef RISCV_CSR_ENCODING_H #define RISCV_CSR_ENCODING_H -#define MSTATUS_IE 0x00000001 -#define MSTATUS_PRV 0x00000006 -#define MSTATUS_IE1 0x00000008 -#define MSTATUS_PRV1 0x00000030 -#define MSTATUS_IE2 0x00000040 -#define MSTATUS_PRV2 0x00000180 -#define MSTATUS_IE3 0x00000200 -#define MSTATUS_PRV3 0x00000C00 -#define MSTATUS_FS 0x00003000 -#define MSTATUS_XS 0x0000C000 -#define MSTATUS_MPRV 0x00010000 -#define MSTATUS_VM 0x003E0000 +#define MSTATUS_UIE 0x00000001 +#define MSTATUS_SIE 0x00000002 +#define MSTATUS_HIE 0x00000004 +#define MSTATUS_MIE 0x00000008 +#define MSTATUS_UPIE 0x00000010 +#define MSTATUS_SPIE 0x00000020 +#define MSTATUS_HPIE 0x00000040 +#define MSTATUS_MPIE 0x00000080 +#define MSTATUS_SPP 0x00000100 +#define MSTATUS_HPP 0x00000600 +#define MSTATUS_MPP 0x00001800 +#define MSTATUS_FS 0x00006000 +#define MSTATUS_XS 0x00018000 +#define MSTATUS_MPRV 0x00020000 +#define MSTATUS_VM 0x007C0000 #define MSTATUS32_SD 0x80000000 #define MSTATUS64_SD 0x8000000000000000 -#define SSTATUS_IE 0x00000001 -#define SSTATUS_PIE 0x00000008 -#define SSTATUS_PS 0x00000010 -#define SSTATUS_FS 0x00003000 -#define SSTATUS_XS 0x0000C000 -#define SSTATUS_MPRV 0x00010000 -#define SSTATUS_TIE 0x01000000 +#define SSTATUS_UIE 0x00000001 +#define SSTATUS_SIE 0x00000002 +#define SSTATUS_UPIE 0x00000010 +#define SSTATUS_SPIE 0x00000020 +#define SSTATUS_SPP 0x00000100 +#define SSTATUS_FS 0x00006000 +#define SSTATUS_XS 0x00018000 +#define SSTATUS_VM 0x007C0000 #define SSTATUS32_SD 0x80000000 #define SSTATUS64_SD 0x8000000000000000 -#define MIP_SSIP 0x00000002 -#define MIP_HSIP 0x00000004 -#define MIP_MSIP 0x00000008 -#define MIP_STIP 0x00000020 -#define MIP_HTIP 0x00000040 -#define MIP_MTIP 0x00000080 +#define MIP_SSIP (1 << IRQ_S_SOFT) +#define MIP_HSIP (1 << IRQ_H_SOFT) +#define MIP_MSIP (1 << IRQ_M_SOFT) +#define MIP_STIP (1 << IRQ_S_TIMER) +#define MIP_HTIP (1 << IRQ_H_TIMER) +#define MIP_MTIP (1 << IRQ_M_TIMER) #define SIP_SSIP MIP_SSIP #define SIP_STIP MIP_STIP @@ -50,14 +54,14 @@ #define VM_SV39 9 #define VM_SV48 10 -#define UA_RV32 0 -#define UA_RV64 4 -#define UA_RV128 8 - -#define IRQ_SOFT 0 -#define IRQ_TIMER 1 -#define IRQ_HOST 2 -#define IRQ_COP 3 +#define IRQ_S_SOFT 1 +#define IRQ_H_SOFT 2 +#define IRQ_M_SOFT 3 +#define IRQ_S_TIMER 5 +#define IRQ_H_TIMER 6 +#define IRQ_M_TIMER 7 +#define IRQ_COP 8 +#define IRQ_HOST 9 #define IMPL_ROCKET 1 @@ -335,18 +339,12 @@ #define MASK_SCALL 0xffffffff #define MATCH_SBREAK 0x100073 #define MASK_SBREAK 0xffffffff -#define MATCH_SRET 0x10000073 +#define MATCH_SRET 0x10200073 #define MASK_SRET 0xffffffff -#define MATCH_SFENCE_VM 0x10100073 +#define MATCH_SFENCE_VM 0x10400073 #define MASK_SFENCE_VM 0xfff07fff -#define MATCH_WFI 0x10200073 +#define MATCH_WFI 0x10500073 #define MASK_WFI 0xffffffff -#define MATCH_MRTH 0x30600073 -#define MASK_MRTH 0xffffffff -#define MATCH_MRTS 0x30500073 -#define MASK_MRTS 0xffffffff -#define MATCH_HRTS 0x20500073 -#define MASK_HRTS 0xffffffff #define MATCH_CSRRW 0x1073 #define MASK_CSRRW 0x707f #define MATCH_CSRRS 0x2073 @@ -643,6 +641,8 @@ #define CSR_SIE 0x104 #define CSR_SSCRATCH 0x140 #define CSR_SEPC 0x141 +#define CSR_SCAUSE 0x142 +#define CSR_SBADADDR 0x143 #define CSR_SIP 0x144 #define CSR_SPTBR 0x180 #define CSR_SASID 0x181 @@ -650,12 +650,11 @@ #define CSR_TIMEW 0x901 #define CSR_INSTRETW 0x902 #define CSR_STIME 0xd01 -#define CSR_SCAUSE 0xd42 -#define CSR_SBADADDR 0xd43 #define CSR_STIMEW 0xa01 #define CSR_MSTATUS 0x300 #define CSR_MTVEC 0x301 -#define CSR_MTDELEG 0x302 +#define CSR_MEDELEG 0x302 +#define CSR_MIDELEG 0x303 #define CSR_MIE 0x304 #define CSR_MTIMECMP 0x321 #define CSR_MSCRATCH 0x340 @@ -787,9 +786,6 @@ DECLARE_INSN(sbreak, MATCH_SBREAK, MASK_SBREAK) DECLARE_INSN(sret, MATCH_SRET, MASK_SRET) DECLARE_INSN(sfence_vm, MATCH_SFENCE_VM, MASK_SFENCE_VM) DECLARE_INSN(wfi, MATCH_WFI, MASK_WFI) -DECLARE_INSN(mrth, MATCH_MRTH, MASK_MRTH) -DECLARE_INSN(mrts, MATCH_MRTS, MASK_MRTS) -DECLARE_INSN(hrts, MATCH_HRTS, MASK_HRTS) DECLARE_INSN(csrrw, MATCH_CSRRW, MASK_CSRRW) DECLARE_INSN(csrrs, MATCH_CSRRS, MASK_CSRRS) DECLARE_INSN(csrrc, MATCH_CSRRC, MASK_CSRRC) @@ -954,6 +950,8 @@ DECLARE_CSR(stvec, CSR_STVEC) DECLARE_CSR(sie, CSR_SIE) DECLARE_CSR(sscratch, CSR_SSCRATCH) DECLARE_CSR(sepc, CSR_SEPC) +DECLARE_CSR(scause, CSR_SCAUSE) +DECLARE_CSR(sbadaddr, CSR_SBADADDR) DECLARE_CSR(sip, CSR_SIP) DECLARE_CSR(sptbr, CSR_SPTBR) DECLARE_CSR(sasid, CSR_SASID) @@ -961,12 +959,11 @@ DECLARE_CSR(cyclew, CSR_CYCLEW) DECLARE_CSR(timew, CSR_TIMEW) DECLARE_CSR(instretw, CSR_INSTRETW) DECLARE_CSR(stime, CSR_STIME) -DECLARE_CSR(scause, CSR_SCAUSE) -DECLARE_CSR(sbadaddr, CSR_SBADADDR) DECLARE_CSR(stimew, CSR_STIMEW) DECLARE_CSR(mstatus, CSR_MSTATUS) DECLARE_CSR(mtvec, CSR_MTVEC) -DECLARE_CSR(mtdeleg, CSR_MTDELEG) +DECLARE_CSR(medeleg, CSR_MEDELEG) +DECLARE_CSR(mideleg, CSR_MIDELEG) DECLARE_CSR(mie, CSR_MIE) DECLARE_CSR(mtimecmp, CSR_MTIMECMP) DECLARE_CSR(mscratch, CSR_MSCRATCH) diff --git a/riscv/execute.cc b/riscv/execute.cc index 4711b49..a2e71a1 100644 --- a/riscv/execute.cc +++ b/riscv/execute.cc @@ -8,7 +8,7 @@ static void commit_log_stash_privilege(state_t* state) { #ifdef RISCV_ENABLE_COMMITLOG - state->last_inst_priv = get_field(state->mstatus, MSTATUS_PRV); + state->last_inst_priv = state->prv; #endif } diff --git a/riscv/extension.cc b/riscv/extension.cc index 00cd24f..5321c42 100644 --- a/riscv/extension.cc +++ b/riscv/extension.cc @@ -14,12 +14,11 @@ void extension_t::illegal_instruction() void extension_t::raise_interrupt() { - int priv = get_field(p->get_state()->mstatus, MSTATUS_PRV); - int ie = get_field(p->get_state()->mstatus, MSTATUS_IE); + reg_t prv = p->get_state()->prv; + reg_t mie = get_field(p->get_state()->mstatus, MSTATUS_MIE); - if (priv < PRV_M || (priv == PRV_M && ie)) { + if (prv < PRV_M || (prv == PRV_M && mie)) p->raise_interrupt(IRQ_COP); - } throw std::logic_error("a COP exception was posted, but interrupts are disabled!"); } diff --git a/riscv/htif.cc b/riscv/htif.cc index ecaaf20..14f6381 100644 --- a/riscv/htif.cc +++ b/riscv/htif.cc @@ -94,7 +94,7 @@ void htif_isasim_t::tick_once() case CSR_MFROMHOST: old_val = proc->get_state()->fromhost; if (write && old_val == 0) - proc->get_state()->fromhost = new_val; + proc->set_csr(CSR_MFROMHOST, new_val); break; case CSR_MRESET: old_val = !proc->running(); diff --git a/riscv/insns/hrts.h b/riscv/insns/hrts.h deleted file mode 100644 index a627bbe..0000000 --- a/riscv/insns/hrts.h +++ /dev/null @@ -1 +0,0 @@ -throw trap_illegal_instruction(); diff --git a/riscv/insns/mrth.h b/riscv/insns/mrth.h deleted file mode 100644 index a627bbe..0000000 --- a/riscv/insns/mrth.h +++ /dev/null @@ -1 +0,0 @@ -throw trap_illegal_instruction(); diff --git a/riscv/insns/mrts.h b/riscv/insns/mrts.h deleted file mode 100644 index 34675b7..0000000 --- a/riscv/insns/mrts.h +++ /dev/null @@ -1,6 +0,0 @@ -require_privilege(PRV_M); -p->set_csr(CSR_MSTATUS, set_field(STATE.mstatus, MSTATUS_PRV, PRV_S)); -STATE.sbadaddr = STATE.mbadaddr; -STATE.scause = STATE.mcause; -STATE.sepc = STATE.mepc; -set_pc(STATE.stvec); diff --git a/riscv/insns/scall.h b/riscv/insns/scall.h index e8a0555..a933e4d 100644 --- a/riscv/insns/scall.h +++ b/riscv/insns/scall.h @@ -1,4 +1,4 @@ -switch (get_field(STATE.mstatus, MSTATUS_PRV)) +switch (STATE.prv) { case PRV_U: throw trap_user_ecall(); case PRV_S: throw trap_supervisor_ecall(); diff --git a/riscv/insns/sret.h b/riscv/insns/sret.h index 8c4bb8e..eacf5be 100644 --- a/riscv/insns/sret.h +++ b/riscv/insns/sret.h @@ -1,8 +1,16 @@ require_privilege(PRV_S); -switch (get_field(STATE.mstatus, MSTATUS_PRV)) +switch (STATE.prv) { case PRV_S: set_pc(p->get_state()->sepc); break; case PRV_M: set_pc(p->get_state()->mepc); break; default: abort(); } -p->pop_privilege_stack(); + +reg_t s = STATE.mstatus; +reg_t pie = get_field(s, MSTATUS_UPIE << STATE.prv); +reg_t prev_prv = get_field(s, STATE.prv == PRV_S ? MSTATUS_SPP : MSTATUS_MPP); +s = set_field(s, MSTATUS_UIE << prev_prv, pie); // [[prv]PP]IE = [prv]PIE +s = set_field(s, MSTATUS_UPIE << STATE.prv, 0); // [prv]PIE <- 0 +p->set_privilege(prev_prv); // prv <- [prv]PP +s = set_field(s, STATE.prv == PRV_S ? MSTATUS_SPP : MSTATUS_MPP, PRV_U); // [prv]PP = U +p->set_csr(CSR_MSTATUS, s); diff --git a/riscv/mmu.cc b/riscv/mmu.cc index 0073a8a..0ba3785 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -34,9 +34,10 @@ reg_t mmu_t::translate(reg_t addr, access_type type) if (!proc) return addr; - reg_t mode = get_field(proc->state.mstatus, MSTATUS_PRV); - if (type != FETCH && get_field(proc->state.mstatus, MSTATUS_MPRV)) - mode = get_field(proc->state.mstatus, MSTATUS_PRV1); + reg_t mode = proc->state.prv; + if (type != FETCH && proc->state.prv == PRV_M && + get_field(proc->state.mstatus, MSTATUS_MPRV)) + mode = get_field(proc->state.mstatus, MSTATUS_MPP); if (get_field(proc->state.mstatus, MSTATUS_VM) == VM_MBARE) mode = PRV_M; diff --git a/riscv/processor.cc b/riscv/processor.cc index 8347b9d..a79ee7b 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -109,9 +109,7 @@ void processor_t::parse_isa_string(const char* str) void state_t::reset() { memset(this, 0, sizeof(*this)); - mstatus = set_field(mstatus, MSTATUS_PRV, PRV_M); - mstatus = set_field(mstatus, MSTATUS_PRV1, PRV_U); - mstatus = set_field(mstatus, MSTATUS_PRV2, PRV_U); + prv = PRV_M; pc = DEFAULT_MTVEC + 0x100; load_reservation = -1; } @@ -152,30 +150,28 @@ void processor_t::raise_interrupt(reg_t which) throw trap_t(((reg_t)1 << (max_xlen-1)) | which); } -void processor_t::take_interrupt() +static int ctz(reg_t val) { - int priv = get_field(state.mstatus, MSTATUS_PRV); - int ie = get_field(state.mstatus, MSTATUS_IE); - reg_t interrupts = state.mie & state.mip; - - if (priv < PRV_M || (priv == PRV_M && ie)) { - if (interrupts & MIP_MSIP) - raise_interrupt(IRQ_SOFT); - - if (interrupts & MIP_MTIP) - raise_interrupt(IRQ_TIMER); + int res = 0; + if (val) + while ((val & 1) == 0) + val >>= 1, res++; + return res; +} - if (state.fromhost != 0) - raise_interrupt(IRQ_HOST); - } +void processor_t::take_interrupt() +{ + reg_t interrupts = state.mip & state.mie; - if (priv < PRV_S || (priv == PRV_S && ie)) { - if (interrupts & MIP_SSIP) - raise_interrupt(IRQ_SOFT); + reg_t m_interrupts = interrupts & ~state.mideleg; + reg_t mie = get_field(state.mstatus, MSTATUS_MIE); + if ((state.prv < PRV_M || (state.prv == PRV_M && mie)) && m_interrupts) + raise_interrupt(ctz(m_interrupts)); - if (interrupts & MIP_STIP) - raise_interrupt(IRQ_TIMER); - } + reg_t s_interrupts = interrupts & state.mideleg; + reg_t sie = get_field(state.mstatus, MSTATUS_SIE); + if ((state.prv < PRV_S || (state.prv == PRV_S && sie)) && s_interrupts) + raise_interrupt(ctz(s_interrupts)); } void processor_t::check_timer() @@ -184,29 +180,16 @@ void processor_t::check_timer() state.mip |= MIP_MTIP; } -void processor_t::push_privilege_stack() +static bool validate_priv(reg_t priv) { - reg_t s = state.mstatus; - s = set_field(s, MSTATUS_PRV2, get_field(state.mstatus, MSTATUS_PRV1)); - s = set_field(s, MSTATUS_IE2, get_field(state.mstatus, MSTATUS_IE1)); - s = set_field(s, MSTATUS_PRV1, get_field(state.mstatus, MSTATUS_PRV)); - s = set_field(s, MSTATUS_IE1, get_field(state.mstatus, MSTATUS_IE)); - s = set_field(s, MSTATUS_PRV, PRV_M); - s = set_field(s, MSTATUS_MPRV, 0); - s = set_field(s, MSTATUS_IE, 0); - set_csr(CSR_MSTATUS, s); + return priv == PRV_U || priv == PRV_S || priv == PRV_M; } -void processor_t::pop_privilege_stack() +void processor_t::set_privilege(reg_t prv) { - reg_t s = state.mstatus; - s = set_field(s, MSTATUS_PRV, get_field(state.mstatus, MSTATUS_PRV1)); - s = set_field(s, MSTATUS_IE, get_field(state.mstatus, MSTATUS_IE1)); - s = set_field(s, MSTATUS_PRV1, get_field(state.mstatus, MSTATUS_PRV2)); - s = set_field(s, MSTATUS_IE1, get_field(state.mstatus, MSTATUS_IE2)); - s = set_field(s, MSTATUS_PRV2, PRV_U); - s = set_field(s, MSTATUS_IE2, 1); - set_csr(CSR_MSTATUS, s); + assert(validate_priv(prv)); + mmu->flush_tlb(); + state.prv = prv; } void processor_t::take_trap(trap_t& t, reg_t epc) @@ -215,12 +198,41 @@ void processor_t::take_trap(trap_t& t, reg_t epc) fprintf(stderr, "core %3d: exception %s, epc 0x%016" PRIx64 "\n", id, t.name(), epc); - state.pc = DEFAULT_MTVEC + 0x40 * get_field(state.mstatus, MSTATUS_PRV); - push_privilege_stack(); + // by default, trap to M-mode, unless delegated to S-mode + reg_t bit = t.cause(); + reg_t deleg = state.medeleg; + if (bit & ((reg_t)1 << (max_xlen-1))) + deleg = state.mideleg, bit &= ~((reg_t)1 << (max_xlen-1)); + if (state.prv <= PRV_S && bit < max_xlen && ((deleg >> bit) & 1)) { + // handle the trap in S-mode + state.pc = state.stvec; + state.scause = t.cause(); + state.sepc = epc; + if (t.has_badaddr()) + state.sbadaddr = t.get_badaddr(); + + reg_t s = state.mstatus; + s = set_field(s, MSTATUS_SPIE, get_field(s, MSTATUS_UIE << state.prv)); + s = set_field(s, MSTATUS_SPP, state.prv); + s = set_field(s, MSTATUS_SIE, 0); + set_csr(CSR_MSTATUS, s); + set_privilege(PRV_S); + } else { + state.pc = DEFAULT_MTVEC + 0x40 * state.prv; + state.mcause = t.cause(); + state.mepc = epc; + if (t.has_badaddr()) + state.mbadaddr = t.get_badaddr(); + + reg_t s = state.mstatus; + s = set_field(s, MSTATUS_MPIE, get_field(s, MSTATUS_UIE << state.prv)); + s = set_field(s, MSTATUS_MPP, state.prv); + s = set_field(s, MSTATUS_MIE, 0); + set_csr(CSR_MSTATUS, s); + set_privilege(PRV_M); + } + yield_load_reservation(); - state.mcause = t.cause(); - state.mepc = epc; - t.side_effects(&state); // might set badvaddr etc. } void processor_t::disasm(insn_t insn) @@ -230,11 +242,6 @@ void processor_t::disasm(insn_t insn) id, state.pc, bits, disassembler->disassemble(insn).c_str()); } -static bool validate_priv(reg_t priv) -{ - return priv == PRV_U || priv == PRV_S || priv == PRV_M; -} - static bool validate_vm(int max_xlen, reg_t vm) { if (max_xlen == 64 && (vm == VM_SV39 || vm == VM_SV48)) @@ -246,6 +253,8 @@ static bool validate_vm(int max_xlen, reg_t vm) void processor_t::set_csr(int which, reg_t val) { + reg_t all_ints = MIP_SSIP | MIP_MSIP | MIP_STIP | MIP_MTIP | (1UL << IRQ_HOST); + reg_t s_ints = MIP_SSIP | MIP_STIP; switch (which) { case CSR_FFLAGS: @@ -294,20 +303,17 @@ void processor_t::set_csr(int which, reg_t val) state.suinstret_delta = (val << 32) | (uint32_t)state.suinstret_delta; break; case CSR_MSTATUS: { - if ((val ^ state.mstatus) & (MSTATUS_VM | MSTATUS_PRV | MSTATUS_PRV1 | MSTATUS_MPRV)) + if ((val ^ state.mstatus) & (MSTATUS_VM | MSTATUS_MPP | MSTATUS_MPRV)) mmu->flush_tlb(); - reg_t mask = MSTATUS_IE | MSTATUS_IE1 | MSTATUS_IE2 | MSTATUS_MPRV - | MSTATUS_FS | (ext ? MSTATUS_XS : 0); + reg_t mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE + | MSTATUS_SPP | MSTATUS_MPRV | MSTATUS_FS + | (ext ? MSTATUS_XS : 0); if (validate_vm(max_xlen, get_field(val, MSTATUS_VM))) mask |= MSTATUS_VM; - if (validate_priv(get_field(val, MSTATUS_PRV))) - mask |= MSTATUS_PRV; - if (validate_priv(get_field(val, MSTATUS_PRV1))) - mask |= MSTATUS_PRV1; - if (validate_priv(get_field(val, MSTATUS_PRV2))) - mask |= MSTATUS_PRV2; + if (validate_priv(get_field(val, MSTATUS_MPP))) + mask |= MSTATUS_MPP; state.mstatus = (state.mstatus & ~mask) | (val & mask); @@ -324,36 +330,40 @@ void processor_t::set_csr(int which, reg_t val) break; } case CSR_MIP: { - reg_t mask = MIP_SSIP | MIP_MSIP | MIP_STIP; + reg_t mask = all_ints &~ MIP_MTIP; state.mip = (state.mip & ~mask) | (val & mask); break; } - case CSR_MIPI: { + case CSR_MIPI: state.mip = set_field(state.mip, MIP_MSIP, val & 1); break; - } - case CSR_MIE: { - reg_t mask = MIP_SSIP | MIP_MSIP | MIP_STIP | MIP_MTIP; - state.mie = (state.mie & ~mask) | (val & mask); + case CSR_MIE: + state.mie = (state.mie & ~all_ints) | (val & all_ints); + break; + case CSR_MIDELEG: + state.mideleg = (state.mideleg & ~s_ints) | (val & s_ints); + break; + case CSR_MEDELEG: { + reg_t mask = 0; +#define DECLARE_CAUSE(name, value) mask |= 1ULL << (value); +#include "encoding.h" +#undef DECLARE_CAUSE + state.medeleg = (state.medeleg & ~mask) | (val & mask); break; } case CSR_SSTATUS: { - reg_t ms = state.mstatus; - ms = set_field(ms, MSTATUS_IE, get_field(val, SSTATUS_IE)); - ms = set_field(ms, MSTATUS_IE1, get_field(val, SSTATUS_PIE)); - ms = set_field(ms, MSTATUS_PRV1, get_field(val, SSTATUS_PS)); - ms = set_field(ms, MSTATUS_FS, get_field(val, SSTATUS_FS)); - ms = set_field(ms, MSTATUS_XS, get_field(val, SSTATUS_XS)); - ms = set_field(ms, MSTATUS_MPRV, get_field(val, SSTATUS_MPRV)); - return set_csr(CSR_MSTATUS, ms); + reg_t mask = SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_SPP | SSTATUS_FS + | SSTATUS_XS; + set_csr(CSR_MSTATUS, (state.mstatus & ~mask) | (val & mask)); + break; } case CSR_SIP: { - reg_t mask = MIP_SSIP; + reg_t mask = s_ints &~ MIP_STIP; state.mip = (state.mip & ~mask) | (val & mask); break; } case CSR_SIE: { - reg_t mask = MIP_SSIP | MIP_STIP; + reg_t mask = s_ints; state.mie = (state.mie & ~mask) | (val & mask); break; } @@ -361,6 +371,8 @@ void processor_t::set_csr(int which, reg_t val) case CSR_STVEC: state.stvec = val >> 2 << 2; break; case CSR_SPTBR: state.sptbr = zext_xlen(val & -PGSIZE); break; case CSR_SSCRATCH: state.sscratch = val; break; + case CSR_SCAUSE: state.scause = val; break; + case CSR_SBADADDR: state.sbadaddr = val; break; case CSR_MEPC: state.mepc = val; break; case CSR_MSCRATCH: state.mscratch = val; break; case CSR_MCAUSE: state.mcause = val; break; @@ -373,7 +385,10 @@ void processor_t::set_csr(int which, reg_t val) if (state.tohost == 0) state.tohost = val; break; - case CSR_MFROMHOST: state.fromhost = val; break; + case CSR_MFROMHOST: + state.mip = (state.mip & ~(1 << IRQ_HOST)) | (val ? (1 << IRQ_HOST) : 0); + state.fromhost = val; + break; } } @@ -425,16 +440,12 @@ reg_t processor_t::get_csr(int which) break; return (state.minstret + state.suinstret_delta) >> 32; case CSR_SSTATUS: { - reg_t ss = 0; - ss = set_field(ss, SSTATUS_IE, get_field(state.mstatus, MSTATUS_IE)); - ss = set_field(ss, SSTATUS_PIE, get_field(state.mstatus, MSTATUS_IE1)); - ss = set_field(ss, SSTATUS_PS, get_field(state.mstatus, MSTATUS_PRV1)); - ss = set_field(ss, SSTATUS_FS, get_field(state.mstatus, MSTATUS_FS)); - ss = set_field(ss, SSTATUS_XS, get_field(state.mstatus, MSTATUS_XS)); - ss = set_field(ss, SSTATUS_MPRV, get_field(state.mstatus, MSTATUS_MPRV)); - if (get_field(state.mstatus, MSTATUS64_SD)) - ss = set_field(ss, (xlen == 32 ? SSTATUS32_SD : SSTATUS64_SD), 1); - return ss; + reg_t sstatus = state.mstatus & + (SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS); + if ((sstatus & SSTATUS_FS) == SSTATUS_FS || + (sstatus & SSTATUS_XS) == SSTATUS_XS) + sstatus |= (xlen == 32 ? SSTATUS32_SD : SSTATUS64_SD); + return sstatus; } case CSR_SIP: return state.mip & (MIP_SSIP | MIP_STIP); case CSR_SIE: return state.mie & (MIP_SSIP | MIP_STIP); @@ -461,7 +472,8 @@ reg_t processor_t::get_csr(int which) case CSR_MIMPID: return IMPL_ROCKET; case CSR_MHARTID: return id; case CSR_MTVEC: return DEFAULT_MTVEC; - case CSR_MTDELEG: return 0; + case CSR_MEDELEG: return state.medeleg; + case CSR_MIDELEG: return state.mideleg; case CSR_MTOHOST: sim->get_htif()->tick(); // not necessary, but faster return state.tohost; diff --git a/riscv/processor.h b/riscv/processor.h index 13c4cbb..80cea36 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -41,6 +41,7 @@ struct state_t regfile_t FPR; // control and status registers + reg_t prv; reg_t mstatus; reg_t mepc; reg_t mbadaddr; @@ -50,6 +51,8 @@ struct state_t reg_t minstret; reg_t mie; reg_t mip; + reg_t medeleg; + reg_t mideleg; reg_t sepc; reg_t sbadaddr; reg_t sscratch; @@ -94,8 +97,7 @@ public: if (ext >= 'a' && ext <= 'z') ext += 'A' - 'a'; return ext >= 'A' && ext <= 'Z' && ((cpuid >> (ext - 'A')) & 1); } - void push_privilege_stack(); - void pop_privilege_stack(); + void set_privilege(reg_t); void yield_load_reservation() { state.load_reservation = (reg_t)-1; } void update_histogram(reg_t pc); @@ -114,8 +116,8 @@ private: state_t state; reg_t cpuid; uint32_t id; - int max_xlen; - int xlen; + unsigned max_xlen; + unsigned xlen; std::string isa; bool run; // !reset bool debug; diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in index 7d71fb5..1d9b301 100644 --- a/riscv/riscv.mk.in +++ b/riscv/riscv.mk.in @@ -190,7 +190,6 @@ riscv_insn_list = \ fsub_d \ fsub_s \ fsw \ - hrts \ jal \ jalr \ lb \ @@ -203,8 +202,6 @@ riscv_insn_list = \ lui \ lw \ lwu \ - mrth \ - mrts \ mul \ mulh \ mulhsu \ diff --git a/riscv/trap.cc b/riscv/trap.cc index 5add05d..4ac2f1f 100644 --- a/riscv/trap.cc +++ b/riscv/trap.cc @@ -10,8 +10,3 @@ const char* trap_t::name() sprintf(_name, fmt, uint8_t(which)); return _name; } - -void mem_trap_t::side_effects(state_t* state) -{ - state->mbadaddr = badvaddr; -} diff --git a/riscv/trap.h b/riscv/trap.h index b03bf67..7f35c5f 100644 --- a/riscv/trap.h +++ b/riscv/trap.h @@ -4,6 +4,7 @@ #define _RISCV_TRAP_H #include "decode.h" +#include struct state_t; @@ -12,7 +13,8 @@ class trap_t public: trap_t(reg_t which) : which(which) {} virtual const char* name(); - virtual void side_effects(state_t* state) {} + virtual bool has_badaddr() { return false; } + virtual reg_t get_badaddr() { abort(); } reg_t cause() { return which; } private: char _name[16]; @@ -22,12 +24,12 @@ class trap_t class mem_trap_t : public trap_t { public: - mem_trap_t(reg_t which, reg_t badvaddr) - : trap_t(which), badvaddr(badvaddr) {} - void side_effects(state_t* state); - reg_t get_badvaddr() { return badvaddr; } + mem_trap_t(reg_t which, reg_t badaddr) + : trap_t(which), badaddr(badaddr) {} + bool has_badaddr() override { return true; } + reg_t get_badaddr() override { return badaddr; } private: - reg_t badvaddr; + reg_t badaddr; }; #define DECLARE_TRAP(n, x) class trap_##x : public trap_t { \ @@ -38,7 +40,7 @@ class mem_trap_t : public trap_t #define DECLARE_MEM_TRAP(n, x) class trap_##x : public mem_trap_t { \ public: \ - trap_##x(reg_t badvaddr) : mem_trap_t(n, badvaddr) {} \ + trap_##x(reg_t badaddr) : mem_trap_t(n, badaddr) {} \ const char* name() { return "trap_"#x; } \ };