From 759599553bab6c95399253ba366a0f5b1b3dd48f Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Fri, 31 May 2024 01:24:02 -0700 Subject: Avoid checking ELP before every instruction fetch Serialize after setting ELP. That way, we can hoist the check outside of the main simulation loop. --- riscv/execute.cc | 4 ++-- riscv/insns/c_jalr.h | 1 + riscv/insns/c_jr.h | 1 + riscv/insns/jalr.h | 1 + riscv/processor.cc | 16 ++++++---------- riscv/processor.h | 2 +- 6 files changed, 12 insertions(+), 13 deletions(-) diff --git a/riscv/execute.cc b/riscv/execute.cc index b2532c9..f263dce 100644 --- a/riscv/execute.cc +++ b/riscv/execute.cc @@ -247,6 +247,8 @@ void processor_t::step(size_t n) { take_pending_interrupt(); + check_if_lpad_required(); + if (unlikely(slow_path())) { // Main simulation loop, slow path. @@ -280,7 +282,6 @@ void processor_t::step(size_t n) in_wfi = false; insn_fetch_t fetch = mmu->load_insn(pc); - execute_insn_prehook(fetch.insn); if (debug && !state.serialized) disasm(fetch.insn); pc = execute_insn_logged(this, pc, fetch); @@ -292,7 +293,6 @@ void processor_t::step(size_t n) // Main simulation loop, fast path. for (auto ic_entry = _mmu->access_icache(pc); ; ) { auto fetch = ic_entry->data; - execute_insn_prehook(fetch.insn); pc = execute_insn_fast(this, pc, fetch); ic_entry = ic_entry->next; if (unlikely(ic_entry->tag != pc)) diff --git a/riscv/insns/c_jalr.h b/riscv/insns/c_jalr.h index 12bc7f9..694f183 100644 --- a/riscv/insns/c_jalr.h +++ b/riscv/insns/c_jalr.h @@ -6,4 +6,5 @@ WRITE_REG(X_RA, tmp); if (ZICFILP_xLPE(STATE.v, STATE.prv)) { STATE.elp = ZICFILP_IS_LP_EXPECTED(insn.rvc_rs1()); + serialize(); } diff --git a/riscv/insns/c_jr.h b/riscv/insns/c_jr.h index c5162e9..af43dd3 100644 --- a/riscv/insns/c_jr.h +++ b/riscv/insns/c_jr.h @@ -4,4 +4,5 @@ set_pc(RVC_RS1 & ~reg_t(1)); if (ZICFILP_xLPE(STATE.v, STATE.prv)) { STATE.elp = ZICFILP_IS_LP_EXPECTED(insn.rvc_rs1()); + serialize(); } diff --git a/riscv/insns/jalr.h b/riscv/insns/jalr.h index 0622a22..0606f67 100644 --- a/riscv/insns/jalr.h +++ b/riscv/insns/jalr.h @@ -4,4 +4,5 @@ WRITE_RD(tmp); if (ZICFILP_xLPE(STATE.v, STATE.prv)) { STATE.elp = ZICFILP_IS_LP_EXPECTED(insn.rs1()); + serialize(); } diff --git a/riscv/processor.cc b/riscv/processor.cc index 0564731..da49a37 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -94,14 +94,6 @@ 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) { @@ -991,9 +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) +void processor_t::check_if_lpad_required() { - zicfilp_check_if_lpad_required(state.elp, insn); + if (unlikely(state.elp == elp_t::LP_EXPECTED)) { + // also see insns/lpad.h for more checks performed + insn_fetch_t fetch = mmu->load_insn(state.pc); + software_check((fetch.insn.bits() & MASK_LPAD) == MATCH_LPAD, LANDING_PAD_FAULT); + } } void processor_t::disasm(insn_t insn) diff --git a/riscv/processor.h b/riscv/processor.h index f3e5294..3e37b43 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -319,7 +319,7 @@ public: void clear_waiting_for_interrupt() { in_wfi = false; }; bool is_waiting_for_interrupt() { return in_wfi; }; - void execute_insn_prehook(insn_t insn); + void check_if_lpad_required(); private: const isa_parser_t * const isa; -- cgit v1.1