diff --git a/src/cpu/exception.c b/src/cpu/exception.c index 5d23403..9d0677f 100644 --- a/src/cpu/exception.c +++ b/src/cpu/exception.c @@ -1,8 +1,9 @@ #include "exception.h" +#include "vriscv.h" #include -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(); } diff --git a/src/cpu/exception.h b/src/cpu/exception.h index 8877adb..3ce8b01 100644 --- a/src/cpu/exception.h +++ b/src/cpu/exception.h @@ -3,7 +3,7 @@ #include "rv32cpu.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); #define SCAUSE_INSTRUCTION_MISSALIGNED 0x0 #define SCAUSE_INSTRUCTION_ACCESS_FAULT 0x1 diff --git a/src/cpu/interrupt.c b/src/cpu/interrupt.c index c05f0b8..ed34b0d 100644 --- a/src/cpu/interrupt.c +++ b/src/cpu/interrupt.c @@ -42,6 +42,8 @@ void interrupt_trigger(rv32_cpu_t* cpu, uint32_t scause) cpu->csr[CSR_SSTATUS] |= 0x80; // Set xSTATUS.xPP (Previous Privilege) bit + // TODO : Allow user mode interrupts (by not setting this) + cpu->csr[CSR_SSTATUS] |= 0x100; // Unset xSTATUS.xIE (interrupt enable) bit cpu->csr[CSR_SSTATUS] &= ~0b10U; diff --git a/src/cpu/rv32cpu.c b/src/cpu/rv32cpu.c index a6b0bdd..0a3226c 100644 --- a/src/cpu/rv32cpu.c +++ b/src/cpu/rv32cpu.c @@ -759,6 +759,8 @@ __attribute__((noreturn)) void cpu_loop(rv32_cpu_t* cpu) // Let go of cpu mutex pthread_mutex_unlock(&cpu->mutex); } + + __builtin_unreachable(); } static void cpu_print_instruction(instruction_t* instruction)