fix exception behavior

This commit is contained in:
Eyck Jentzsch 2021-11-02 15:10:20 +01:00
parent ac6d7ea5d4
commit 039746112b
2 changed files with 34 additions and 4 deletions

View File

@ -959,9 +959,16 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_m_p<BASE, FEAT>::e
if (cause == 11) cause = 0x8 + PRIV_M; // adjust environment call cause if (cause == 11) cause = 0x8 + PRIV_M; // adjust environment call cause
// store ret addr in xepc register // store ret addr in xepc register
csr[mepc] = static_cast<reg_t>(addr) & get_pc_mask(); // store actual address instruction of exception csr[mepc] = static_cast<reg_t>(addr) & get_pc_mask(); // store actual address instruction of exception
/*
* write mtval if new_priv=M_MODE, spec says:
* When a hardware breakpoint is triggered, or an instruction-fetch, load,
* or store address-misaligned,
* access, or page-fault exception occurs, mtval is written with the
* faulting effective address.
*/
switch(cause){ switch(cause){
case 0: case 0:
csr[mtval] = addr; csr[mtval] = static_cast<reg_t>(addr);
break; break;
case 2: case 2:
csr[mtval] = (instr & 0x3)==3?instr:instr&0xffff; csr[mtval] = (instr & 0x3)==3?instr:instr&0xffff;
@ -970,10 +977,14 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_m_p<BASE, FEAT>::e
//TODO: implement debug mode behavior //TODO: implement debug mode behavior
// csr[dpc] = addr; // csr[dpc] = addr;
// csr[dcsr] = (csr[dcsr] & ~0x1c3) | (1<<6) | PRIV_M; //FIXME: cause should not be 4 (stepi) // csr[dcsr] = (csr[dcsr] & ~0x1c3) | (1<<6) | PRIV_M; //FIXME: cause should not be 4 (stepi)
csr[mtval] = addr; csr[mtval] = 0;
break;
case 4:
case 6:
csr[mtval] = fault_data;
break; break;
default: default:
csr[mtval] = fault_data; csr[mtval] = 0;
} }
fault_data = 0; fault_data = 0;
} else { } else {

View File

@ -1220,7 +1220,26 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_mu_p<BASE, FEAT>::
* access, or page-fault exception occurs, mtval is written with the * access, or page-fault exception occurs, mtval is written with the
* faulting effective address. * faulting effective address.
*/ */
csr[utval | (new_priv << 8)] = cause==2?((instr & 0x3)==3?instr:instr&0xffff):fault_data; switch(cause){
case 0:
csr[utval | (new_priv << 8)] = static_cast<reg_t>(addr);
break;
case 2:
csr[utval | (new_priv << 8)] = (instr & 0x3)==3?instr:instr&0xffff;
break;
case 3:
//TODO: implement debug mode behavior
// csr[dpc] = addr;
// csr[dcsr] = (csr[dcsr] & ~0x1c3) | (1<<6) | PRIV_M; //FIXME: cause should not be 4 (stepi)
csr[utval | (new_priv << 8)] = 0;
break;
case 4:
case 6:
csr[utval | (new_priv << 8)] = fault_data;
break;
default:
csr[utval | (new_priv << 8)] = 0;
}
fault_data = 0; fault_data = 0;
} else { } else {
if (this->reg.PRIV != PRIV_M && ((csr[mideleg] >> cause) & 0x1) != 0) if (this->reg.PRIV != PRIV_M && ((csr[mideleg] >> cause) & 0x1) != 0)