|
|
|
@ -1,8 +1,9 @@ |
|
|
|
|
#include "exception.h" |
|
|
|
|
#include "vriscv.h" |
|
|
|
|
|
|
|
|
|
#include <stdio.h> |
|
|
|
|
|
|
|
|
|
void exception_trigger(rv32_cpu_t* cpu, uint32_t scause, uint32_t tval) |
|
|
|
|
__attribute__((noreturn)) void exception_trigger(rv32_cpu_t* cpu, uint32_t scause, uint32_t tval) |
|
|
|
|
{ |
|
|
|
|
// An exception can only be triggered by the CPU itself,
|
|
|
|
|
// so we know we already own the mutex
|
|
|
|
@ -14,21 +15,31 @@ void exception_trigger(rv32_cpu_t* cpu, uint32_t scause, uint32_t tval) |
|
|
|
|
|
|
|
|
|
// Exceptions cannot be disabled
|
|
|
|
|
|
|
|
|
|
// Unset SIE (interrupt enable) bit
|
|
|
|
|
cpu->csr[CSR_SSTATUS] &= ~0b10U; |
|
|
|
|
|
|
|
|
|
// Set xCAUSE : exception cause, with interrupt bit set to null
|
|
|
|
|
cpu->csr[CSR_SCAUSE] = scause; |
|
|
|
|
if(gdbstub && scause == SCAUSE_BREAKPOINT) |
|
|
|
|
{ |
|
|
|
|
cpu->sim_ticks_left = 0; |
|
|
|
|
// No simulation ticks left : wakeup people waiting on sim end
|
|
|
|
|
pthread_cond_signal(&cpu->sim_condition); |
|
|
|
|
// Then, wait for simulation state to change until we get more ticks to simulate
|
|
|
|
|
while(!cpu->sim_ticks_left) |
|
|
|
|
pthread_cond_wait(&cpu->sim_condition, &cpu->mutex); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Save previous interrupt enable in xSTATUS.xPIE
|
|
|
|
|
if(cpu->csr[CSR_SSTATUS] & 0b10U) |
|
|
|
|
cpu->csr[CSR_SSTATUS] |= 0x80; |
|
|
|
|
|
|
|
|
|
// Set previous privilege mode in xSTATUS.xPP
|
|
|
|
|
// TODO
|
|
|
|
|
|
|
|
|
|
// Unset SIE (interrupt enable) bit
|
|
|
|
|
cpu->csr[CSR_SSTATUS] &= ~0b10U; |
|
|
|
|
// TODO : Allow user mode exceptions (by not setting this)
|
|
|
|
|
cpu->csr[CSR_SSTATUS] |= 0x100; |
|
|
|
|
|
|
|
|
|
// Set privilege mode for exception handling, checking for delegation
|
|
|
|
|
// TODO
|
|
|
|
|
// TODO
|
|
|
|
|
|
|
|
|
|
// Set xTVAL, exception-specific information related to xCAUSE
|
|
|
|
|
cpu->csr[CSR_STVAL] = tval; |
|
|
|
@ -41,9 +52,12 @@ void exception_trigger(rv32_cpu_t* cpu, uint32_t scause, uint32_t tval) |
|
|
|
|
// Exceptions are not vectored (we can safely ignore mode)
|
|
|
|
|
cpu->pc = cpu->csr[CSR_STVEC] & 0xFFFFFFFC; |
|
|
|
|
|
|
|
|
|
// Unlock cpu mutex, cpu_loop will lock it just after
|
|
|
|
|
// Unlock cpu mutex, cpu_loop will lock it just after
|
|
|
|
|
pthread_mutex_unlock(&cpu->mutex); |
|
|
|
|
|
|
|
|
|
// cpu loop (attribute noreturn should erase previous stack)
|
|
|
|
|
// TODO : Hard reset the stack pointer
|
|
|
|
|
// cpu loop
|
|
|
|
|
cpu_loop(cpu); |
|
|
|
|
|
|
|
|
|
__builtin_unreachable(); |
|
|
|
|
} |
|
|
|
|