diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index e5b7d86..c8b3af2 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -85,7 +85,7 @@ protected: inline const char *name(size_t index){return traits::reg_aliases.at(index);} - virt_addr_t execute_inst(virt_addr_t start, std::function pred) override; + virt_addr_t execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit) override; // some compile time constants // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; @@ -273,19 +273,21 @@ vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) } template -typename vm_base::virt_addr_t vm_impl::execute_inst(virt_addr_t start, std::function pred) { +typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit){ // we fetch at max 4 byte, alignment is 2 enum {TRAP_ID=1<<16}; code_word_t insn = 0; auto *const data = (uint8_t *)&insn; auto pc=start; - while(pred(pc)){ + while(!core.should_stop() && + !((cond & finish_cond_e::COUNT_LIMIT) && core.get_icount() < icount)){ auto res = fetch_ins(pc, data); if(res!=iss::Ok){ auto new_pc = super::core.enter_trap(TRAP_ID, pc.val); res = fetch_ins(virt_addr_t{access_type::FETCH, new_pc}, data); if(res!=iss::Ok) throw simulation_stopped(0); } + if ((cond & finish_cond_e::JUMP_TO_SELF) && (insn == 0x0000006f || (insn&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0' auto lut_val = extract_fields(insn); auto f = qlut[insn & 0x3][lut_val]; if (!f) diff --git a/src/vm/interp/vm_tgf_c.cpp b/src/vm/interp/vm_tgf_c.cpp index 156836a..2764ac8 100644 --- a/src/vm/interp/vm_tgf_c.cpp +++ b/src/vm/interp/vm_tgf_c.cpp @@ -85,7 +85,7 @@ protected: inline const char *name(size_t index){return traits::reg_aliases.at(index);} - virt_addr_t execute_inst(virt_addr_t start, std::function pred) override; + virt_addr_t execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit) override; // some compile time constants // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; @@ -3436,19 +3436,23 @@ vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) } template -typename vm_base::virt_addr_t vm_impl::execute_inst(virt_addr_t start, std::function pred) { +typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit){ // we fetch at max 4 byte, alignment is 2 enum {TRAP_ID=1<<16}; code_word_t insn = 0; auto *const data = (uint8_t *)&insn; auto pc=start; - while(pred(pc)){ + while(!this->core.should_stop() && + !((cond & finish_cond_e::COUNT_LIMIT) == finish_cond_e::COUNT_LIMIT && + this->core.get_icount() < icount_limit)){ auto res = fetch_ins(pc, data); if(res!=iss::Ok){ auto new_pc = super::core.enter_trap(TRAP_ID, pc.val); res = fetch_ins(virt_addr_t{access_type::FETCH, new_pc}, data); if(res!=iss::Ok) throw simulation_stopped(0); } + if ((cond & finish_cond_e::JUMP_TO_SELF) == finish_cond_e::JUMP_TO_SELF && + (insn == 0x0000006f || (insn&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0' auto lut_val = extract_fields(insn); auto f = qlut[insn & 0x3][lut_val]; if (!f)