diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index c49f59d..01985ba 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -843,7 +843,7 @@ private: try { { uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm); - int16_t res = (int16_t)readSpace2(traits::MEM, *(X+rs1) + (int16_t)sext<12>(imm)); + int16_t res = (int16_t)readSpace2(traits::MEM, load_address); if(rd != 0) *(X+rd) = res; } } catch(...){} @@ -888,7 +888,7 @@ private: try { { uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm); - int32_t res = (int32_t)readSpace4(traits::MEM, *(X+rs1) + (int16_t)sext<12>(imm)); + int32_t res = (int32_t)readSpace4(traits::MEM, load_address); if(rd != 0) *(X+rd) = (uint32_t)res; } } catch(...){} @@ -977,7 +977,7 @@ private: try { { uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm); - uint16_t res = (uint16_t)readSpace2(traits::MEM, *(X+rs1) + (int16_t)sext<12>(imm)); + uint16_t res = (uint16_t)readSpace2(traits::MEM, load_address); if(rd != 0) *(X+rd) = res; } } catch(...){} @@ -4113,6 +4113,10 @@ inline bool is_count_limit_enabled(finish_cond_e cond){ return (cond & finish_cond_e::COUNT_LIMIT) == finish_cond_e::COUNT_LIMIT; } +inline bool is_jump_to_self_enabled(finish_cond_e cond){ + return (cond & finish_cond_e::JUMP_TO_SELF) == finish_cond_e::JUMP_TO_SELF; +} + template typename vm_impl::compile_func vm_impl::decode_inst(code_word_t instr){ for(auto& e: qlut[instr&0x3]){ @@ -4124,7 +4128,6 @@ typename vm_impl::compile_func vm_impl::decode_inst(code_word_t inst template 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; @@ -4132,14 +4135,14 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co !(is_count_limit_enabled(cond) && 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, 0); - res = fetch_ins(virt_addr_t{access_type::FETCH, new_pc}, data); - if(res!=iss::Ok) throw simulation_stopped(0); + this->do_sync(POST_SYNC, std::numeric_limits::max()); + pc.val = super::core.enter_trap(std::numeric_limits::max(), pc.val, 0); + } else { + if (is_jump_to_self_enabled(cond) && + (insn == 0x0000006f || (insn&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0' + auto f = decode_inst(insn); + pc = (this->*f)(pc, insn); } - 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 f = decode_inst(insn); - pc = (this->*f)(pc, insn); } return pc; }