diff options
author | Andrew Waterman <andrew@sifive.com> | 2024-03-21 13:21:31 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-21 13:21:31 -0700 |
commit | 2e86ec4b83c2fe3eb19669244357d288be8b45fa (patch) | |
tree | 4c11369a500362d979a17a6538af402fcdcf3aa9 /riscv/processor.cc | |
parent | d527f1e4df711af07f3a20a478aa187d7146feb1 (diff) | |
parent | 677e030594aa51ea8d6304d24b7da2ecd7006fe8 (diff) | |
download | riscv-isa-sim-2e86ec4b83c2fe3eb19669244357d288be8b45fa.zip riscv-isa-sim-2e86ec4b83c2fe3eb19669244357d288be8b45fa.tar.gz riscv-isa-sim-2e86ec4b83c2fe3eb19669244357d288be8b45fa.tar.bz2 |
Merge pull request #1582 from mylai-mtk/zicfilp-upstream
Support Zicfilp
Diffstat (limited to 'riscv/processor.cc')
-rw-r--r-- | riscv/processor.cc | 39 |
1 files changed, 34 insertions, 5 deletions
diff --git a/riscv/processor.cc b/riscv/processor.cc index 1c0486b..347fff3 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -94,6 +94,14 @@ processor_t::~processor_t() delete disassembler; } +static void zicfilp_check_if_lpad_required(const elp_t elp, insn_t insn) +{ + if (unlikely(elp == elp_t::LP_EXPECTED)) { + // also see riscv/lpad.h for more checks performed + software_check((insn.bits() & MASK_LPAD) == MATCH_LPAD, LANDING_PAD_FAULT); + } +} + static void bad_option_string(const char *option, const char *value, const char *msg) { @@ -374,7 +382,8 @@ void state_t::reset(processor_t* const proc, reg_t max_isa) (1 << CAUSE_USER_ECALL) | (1 << CAUSE_FETCH_PAGE_FAULT) | (1 << CAUSE_LOAD_PAGE_FAULT) | - (1 << CAUSE_STORE_PAGE_FAULT); + (1 << CAUSE_STORE_PAGE_FAULT) | + (1 << CAUSE_SOFTWARE_CHECK_FAULT); csrmap[CSR_HEDELEG] = hedeleg = std::make_shared<masked_csr_t>(proc, CSR_HEDELEG, hedeleg_mask, 0); csrmap[CSR_HCOUNTEREN] = hcounteren = std::make_shared<masked_csr_t>(proc, CSR_HCOUNTEREN, counteren_mask, 0); htimedelta = std::make_shared<basic_csr_t>(proc, CSR_HTIMEDELTA, 0); @@ -443,7 +452,8 @@ void state_t::reset(processor_t* const proc, reg_t max_isa) (proc->extension_enabled(EXT_ZICBOZ) ? MENVCFG_CBZE : 0) | (proc->extension_enabled(EXT_SVADU) ? MENVCFG_ADUE: 0) | (proc->extension_enabled(EXT_SVPBMT) ? MENVCFG_PBMTE : 0) | - (proc->extension_enabled(EXT_SSTC) ? MENVCFG_STCE : 0); + (proc->extension_enabled(EXT_SSTC) ? MENVCFG_STCE : 0) | + (proc->extension_enabled(EXT_ZICFILP) ? MENVCFG_LPE : 0); const reg_t menvcfg_init = (proc->extension_enabled(EXT_SVPBMT) ? MENVCFG_PBMTE : 0); menvcfg = std::make_shared<envcfg_csr_t>(proc, CSR_MENVCFG, menvcfg_mask, menvcfg_init); if (xlen == 32) { @@ -453,13 +463,15 @@ void state_t::reset(processor_t* const proc, reg_t max_isa) csrmap[CSR_MENVCFG] = menvcfg; } const reg_t senvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? SENVCFG_CBCFE | SENVCFG_CBIE : 0) | - (proc->extension_enabled(EXT_ZICBOZ) ? SENVCFG_CBZE : 0); + (proc->extension_enabled(EXT_ZICBOZ) ? SENVCFG_CBZE : 0) | + (proc->extension_enabled(EXT_ZICFILP) ? SENVCFG_LPE : 0); csrmap[CSR_SENVCFG] = senvcfg = std::make_shared<senvcfg_csr_t>(proc, CSR_SENVCFG, senvcfg_mask, 0); const reg_t henvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? HENVCFG_CBCFE | HENVCFG_CBIE : 0) | (proc->extension_enabled(EXT_ZICBOZ) ? HENVCFG_CBZE : 0) | (proc->extension_enabled(EXT_SVADU) ? HENVCFG_ADUE: 0) | (proc->extension_enabled(EXT_SVPBMT) ? HENVCFG_PBMTE : 0) | - (proc->extension_enabled(EXT_SSTC) ? HENVCFG_STCE : 0); + (proc->extension_enabled(EXT_SSTC) ? HENVCFG_STCE : 0) | + (proc->extension_enabled(EXT_ZICFILP) ? HENVCFG_LPE : 0); const reg_t henvcfg_init = (proc->extension_enabled(EXT_SVPBMT) ? HENVCFG_PBMTE : 0); henvcfg = std::make_shared<henvcfg_csr_t>(proc, CSR_HENVCFG, henvcfg_mask, henvcfg_init, menvcfg); if (xlen == 32) { @@ -590,6 +602,8 @@ void state_t::reset(processor_t* const proc, reg_t max_isa) last_inst_priv = 0; last_inst_xlen = 0; last_inst_flen = 0; + + elp = elp_t::NO_LP_EXPECTED; } void processor_t::set_debug(bool value) @@ -810,8 +824,10 @@ const char* processor_t::get_privilege_string() void processor_t::enter_debug_mode(uint8_t cause) { + const bool has_zicfilp = extension_enabled(EXT_ZICFILP); state.debug_mode = true; - state.dcsr->write_cause_and_prv(cause, state.prv, state.v); + state.dcsr->update_fields(cause, state.prv, state.v, state.elp); + state.elp = elp_t::NO_LP_EXPECTED; set_privilege(PRV_M, false); state.dpc->write(state.pc); state.pc = DEBUG_ROM_ENTRY; @@ -880,6 +896,8 @@ void processor_t::take_trap(trap_t& t, reg_t epc) s = set_field(s, MSTATUS_SPIE, get_field(s, MSTATUS_SIE)); s = set_field(s, MSTATUS_SPP, state.prv); s = set_field(s, MSTATUS_SIE, 0); + s = set_field(s, MSTATUS_SPELP, state.elp); + state.elp = elp_t::NO_LP_EXPECTED; state.sstatus->write(s); set_privilege(PRV_S, true); } else if (state.prv <= PRV_S && bit < max_xlen && ((hsdeleg >> bit) & 1)) { @@ -896,6 +914,8 @@ void processor_t::take_trap(trap_t& t, reg_t epc) s = set_field(s, MSTATUS_SPIE, get_field(s, MSTATUS_SIE)); s = set_field(s, MSTATUS_SPP, state.prv); s = set_field(s, MSTATUS_SIE, 0); + s = set_field(s, MSTATUS_SPELP, state.elp); + state.elp = elp_t::NO_LP_EXPECTED; state.nonvirtual_sstatus->write(s); if (extension_enabled('H')) { s = state.hstatus->read(); @@ -927,6 +947,8 @@ void processor_t::take_trap(trap_t& t, reg_t epc) s = set_field(s, MSTATUS_MIE, 0); s = set_field(s, MSTATUS_MPV, curr_virt); s = set_field(s, MSTATUS_GVA, t.has_gva()); + s = set_field(s, MSTATUS_MPELP, state.elp); + state.elp = elp_t::NO_LP_EXPECTED; state.mstatus->write(s); if (state.mstatush) state.mstatush->write(s >> 32); // log mstatush change set_privilege(PRV_M, false); @@ -961,6 +983,13 @@ const char* processor_t::get_symbol(uint64_t addr) return sim->get_symbol(addr); } +void processor_t::execute_insn_prehook(insn_t insn) +{ + if (extension_enabled(EXT_ZICFILP)) { + zicfilp_check_if_lpad_required(state.elp, insn); + } +} + void processor_t::disasm(insn_t insn) { uint64_t bits = insn.bits(); |