70 lines
2.3 KiB
C
70 lines
2.3 KiB
C
#include "exception.h"
|
|
#include "vriscv.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
__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
|
|
// We are in the CPU thread itself, but we need
|
|
// the return of this function to be the beginning of
|
|
// the cpu loop
|
|
// To achieve that, we can just call cpu_loop (noreturn)
|
|
// at the end of this function
|
|
|
|
// Exceptions cannot be disabled
|
|
|
|
// TODO : Check medeleg to see if we should handle exception in S mode or M mode
|
|
|
|
// Unset SIE (interrupt enable) bit
|
|
csr_write(cpu, CSR_SSTATUS, csr_read(cpu, CSR_SSTATUS) & (~STATUS_SIE));
|
|
|
|
// Set xCAUSE : exception cause, with interrupt bit set to null
|
|
csr_write(cpu, 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(csr_read(cpu, CSR_SSTATUS) & STATUS_SIE)
|
|
csr_write(cpu, CSR_SSTATUS, csr_read(cpu, CSR_SSTATUS) | STATUS_SPIE);
|
|
else
|
|
csr_write(cpu, CSR_SSTATUS, csr_read(cpu, CSR_SSTATUS) & (~STATUS_SPIE));
|
|
|
|
// Set previous privilege mode in xSTATUS.xPP
|
|
if(cpu->privilege_mode == SUPERVISOR)
|
|
csr_write(cpu, CSR_SSTATUS, csr_read(cpu, CSR_SSTATUS) | STATUS_SPP);
|
|
else if(cpu->privilege_mode == USER)
|
|
csr_write(cpu, CSR_SSTATUS, csr_read(cpu, CSR_SSTATUS) & (~STATUS_SPP));
|
|
|
|
// Set privilege mode for exception handling, checking for delegation
|
|
// TODO
|
|
|
|
// Set xTVAL, exception-specific information related to xCAUSE
|
|
csr_write(cpu, CSR_STVAL, tval);
|
|
|
|
// Set SEPC to instruction that caused exception
|
|
csr_write(cpu, CSR_SEPC, cpu->pc);
|
|
|
|
// Set PC to xTVEC : exception handling code
|
|
// xTVEC: [Base(30bits) Mode(2 bits)], address 4-byte aligned in base
|
|
// Exceptions are not vectored (we can safely ignore mode)
|
|
cpu->pc = csr_read(cpu, CSR_STVEC) & 0xFFFFFFFC;
|
|
|
|
// Unlock cpu mutex, cpu_loop will lock it just after
|
|
pthread_mutex_unlock(&cpu->mutex);
|
|
|
|
// TODO : Hard reset the stack pointer
|
|
// cpu loop
|
|
cpu_loop(cpu);
|
|
|
|
__builtin_unreachable();
|
|
}
|