diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index 567737d..2bd17fb 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -117,7 +117,12 @@ protected: this->core.wait_until(type); } + inline void set_tval(uint64_t new_tval){ + tval = new_tval; + } + uint64_t fetch_count{0}; + uint64_t tval{0}; using yield_t = boost::coroutines2::coroutine::push_type; using coro_t = boost::coroutines2::coroutine::pull_type; @@ -341,7 +346,9 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // this->core.reg.trap_state = this->core.reg.pending_trap; // trap check if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val, instr); + //In case of Instruction address misaligned (cause = 0 and trapid = 0) need the targeted addr (in tval) + auto mcause = (trap_state>>16) & 0xff; + super::core.enter_trap(trap_state, pc.val, mcause ? instr:tval); } else { icount++; instret++; diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index d257d9c..e45f292 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -1207,7 +1207,7 @@ template void riscv_hart_m_p::check } } -template uint64_t riscv_hart_m_p::enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) { +template uint64_t riscv_hart_m_p::enter_trap(uint64_t flags, uint64_t addr, uint64_t tval) { // flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0] // calculate and write mcause val auto const trap_id = bit_sub<0, 16>(flags); @@ -1228,10 +1228,10 @@ template uint64_t riscv_hart_m_p::e */ switch(cause) { case 0: - csr[mtval] = static_cast(addr); + csr[mtval] = static_cast(tval); break; case 2: - csr[mtval] = (!has_compressed() || (instr & 0x3) == 3) ? instr : instr & 0xffff; + csr[mtval] = (!has_compressed() || (tval & 0x3) == 3) ? tval : tval & 0xffff; break; case 3: if((FEAT & FEAT_DEBUG) && (csr[dcsr] & 0x8000)) { diff --git a/src/vm/interp/vm_tgc5c.cpp b/src/vm/interp/vm_tgc5c.cpp index ee4edfb..0656c4b 100644 --- a/src/vm/interp/vm_tgc5c.cpp +++ b/src/vm/interp/vm_tgc5c.cpp @@ -113,7 +113,12 @@ protected: this->core.wait_until(type); } + inline void set_tval(uint64_t new_tval){ + tval = new_tval; + } + uint64_t fetch_count{0}; + uint64_t tval{0}; using yield_t = boost::coroutines2::coroutine::push_type; using coro_t = boost::coroutines2::coroutine::pull_type; @@ -463,14 +468,16 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); } else { - if(imm % traits::INSTR_ALIGNMENT) { + uint32_t new_pc = (uint32_t)((uint64_t)(*PC ) + (uint64_t)((int32_t)sext<21>(imm) )); + if(new_pc % traits::INSTR_ALIGNMENT) { + set_tval(new_pc); raise(0, 0); } else { if(rd != 0) { *(X+rd) = (uint32_t)((uint64_t)(*PC ) + (uint64_t)(4 )); } - *NEXT_PC = (uint32_t)((uint64_t)(*PC ) + (uint64_t)((int32_t)sext<21>(imm) )); + *NEXT_PC = new_pc; this->core.reg.last_branch = 1; } } @@ -500,6 +507,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co uint32_t addr_mask = (uint32_t)- 2; uint32_t new_pc = (uint32_t)(((uint64_t)(*(X+rs1) ) + (uint64_t)((int16_t)sext<12>(imm) )) & (int64_t)(addr_mask )); if(new_pc % traits::INSTR_ALIGNMENT) { + set_tval(new_pc); raise(0, 0); } else { @@ -534,11 +542,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if(*(X+rs1) == *(X+rs2)) { - if((uint32_t)(imm ) % traits::INSTR_ALIGNMENT) { + uint32_t new_pc = (uint32_t)((uint64_t)(*PC ) + (uint64_t)((int16_t)sext<13>(imm) )); + if(new_pc % traits::INSTR_ALIGNMENT) { + set_tval(new_pc); raise(0, 0); } else { - *NEXT_PC = (uint32_t)((uint64_t)(*PC ) + (uint64_t)((int16_t)sext<13>(imm) )); + *NEXT_PC = new_pc; this->core.reg.last_branch = 1; } } @@ -567,11 +577,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if(*(X+rs1) != *(X+rs2)) { - if((uint32_t)(imm ) % traits::INSTR_ALIGNMENT) { + uint32_t new_pc = (uint32_t)((uint64_t)(*PC ) + (uint64_t)((int16_t)sext<13>(imm) )); + if(new_pc % traits::INSTR_ALIGNMENT) { + set_tval(new_pc); raise(0, 0); } else { - *NEXT_PC = (uint32_t)((uint64_t)(*PC ) + (uint64_t)((int16_t)sext<13>(imm) )); + *NEXT_PC = new_pc; this->core.reg.last_branch = 1; } } @@ -600,11 +612,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if((int32_t)*(X+rs1) < (int32_t)*(X+rs2)) { - if((uint32_t)(imm ) % traits::INSTR_ALIGNMENT) { + uint32_t new_pc = (uint32_t)((uint64_t)(*PC ) + (uint64_t)((int16_t)sext<13>(imm) )); + if(new_pc % traits::INSTR_ALIGNMENT) { + set_tval(new_pc); raise(0, 0); } else { - *NEXT_PC = (uint32_t)((uint64_t)(*PC ) + (uint64_t)((int16_t)sext<13>(imm) )); + *NEXT_PC = new_pc; this->core.reg.last_branch = 1; } } @@ -633,11 +647,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if((int32_t)*(X+rs1) >= (int32_t)*(X+rs2)) { - if((uint32_t)(imm ) % traits::INSTR_ALIGNMENT) { + uint32_t new_pc = (uint32_t)((uint64_t)(*PC ) + (uint64_t)((int16_t)sext<13>(imm) )); + if(new_pc % traits::INSTR_ALIGNMENT) { + set_tval(new_pc); raise(0, 0); } else { - *NEXT_PC = (uint32_t)((uint64_t)(*PC ) + (uint64_t)((int16_t)sext<13>(imm) )); + *NEXT_PC = new_pc; this->core.reg.last_branch = 1; } } @@ -666,11 +682,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if(*(X+rs1) < *(X+rs2)) { - if((uint32_t)(imm ) % traits::INSTR_ALIGNMENT) { + uint32_t new_pc = (uint32_t)((uint64_t)(*PC ) + (uint64_t)((int16_t)sext<13>(imm) )); + if(new_pc % traits::INSTR_ALIGNMENT) { + set_tval(new_pc); raise(0, 0); } else { - *NEXT_PC = (uint32_t)((uint64_t)(*PC ) + (uint64_t)((int16_t)sext<13>(imm) )); + *NEXT_PC = new_pc; this->core.reg.last_branch = 1; } } @@ -699,11 +717,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if(*(X+rs1) >= *(X+rs2)) { - if((uint32_t)(imm ) % traits::INSTR_ALIGNMENT) { + uint32_t new_pc = (uint32_t)((uint64_t)(*PC ) + (uint64_t)((int16_t)sext<13>(imm) )); + if(new_pc % traits::INSTR_ALIGNMENT) { + set_tval(new_pc); raise(0, 0); } else { - *NEXT_PC = (uint32_t)((uint64_t)(*PC ) + (uint64_t)((int16_t)sext<13>(imm) )); + *NEXT_PC = new_pc; this->core.reg.last_branch = 1; } } @@ -2675,7 +2695,9 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // this->core.reg.trap_state = this->core.reg.pending_trap; // trap check if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val, instr); + //In case of Instruction address misaligned (cause = 0 and trapid = 0) need the targeted addr (in tval) + auto mcause = (trap_state>>16) & 0xff; + super::core.enter_trap(trap_state, pc.val, mcause ? instr:tval); } else { icount++; instret++;