Add exception handler for easier debugging.

Change-Id: I1df809e97540f3f5504fe958b44d5ed8ce949fae
diff --git a/springbok/CMakeLists.txt b/springbok/CMakeLists.txt
index 0ba73f6..f8ffbc2 100644
--- a/springbok/CMakeLists.txt
+++ b/springbok/CMakeLists.txt
@@ -6,7 +6,9 @@
 target_sources(springbok_intrinsic
     PRIVATE
       crt0.s
+      irq_vector.s
       springbok_gloss.cpp
+      springbok.cpp
 )
 
 target_include_directories(springbok_intrinsic PUBLIC include)
diff --git a/springbok/crt0.s b/springbok/crt0.s
index e724a02..8e71aad 100644
--- a/springbok/crt0.s
+++ b/springbok/crt0.s
@@ -65,6 +65,8 @@
         li a1, 0x2000
         or a0, a0, a1
         csrw mstatus, a0
+        la a0, exception_handler
+        csrw mtvec, a0
 
         #############################################################
         # Clear BSS, stack and unused DTCM memory, set up sentinels #
@@ -256,3 +258,22 @@
         # stack corruption!
 2:      li   a0, 1
         ret
+
+.weak exception_handler
+exception_handler:
+        .word 0x0000307B # finish (encoded as custom3<func3=3>)
+        li   t4, 0 # ERROR logging level
+        li   t5, 0 # Return 0
+        la a0, exception_msg
+        csrr t5, mcause
+        .word 0x001E50EFB # simprint t4, a0, t5 (encoded as custom3<func3=0>)
+        call print_csrs
+        j _finish
+
+.weak print_csrs
+print_csrs:
+        mret
+
+.rodata
+exception_msg:
+        .string "Exception occurred\0"
diff --git a/springbok/irq_vector.s b/springbok/irq_vector.s
new file mode 100644
index 0000000..1787f67
--- /dev/null
+++ b/springbok/irq_vector.s
@@ -0,0 +1,8 @@
+  // Exception handler.
+  .section .vectors, "ax"
+  .option norvc
+  .option push
+  .option norelax
+  .org 0x00
+  j _start
+  j exception_handler
diff --git a/springbok/matcha.ld b/springbok/matcha.ld
index 7e5ccab..cabdf13 100644
--- a/springbok/matcha.ld
+++ b/springbok/matcha.ld
@@ -13,8 +13,14 @@
 PROVIDE( _stack_start_sentinel = ORIGIN(DTCM) + LENGTH(DTCM) - STACK_SIZE );
 PROVIDE( _stack_end_sentinel = ORIGIN(DTCM) + LENGTH(DTCM) - 64 );
 
+_boot_address = ORIGIN(ITCM);
+ENTRY(_boot_address)
+
 SECTIONS
 {
+        .vectors _boot_address : ALIGN(4) {
+                KEEP(*(.vectors))
+        } > ITCM
         .text :
         {
                 _stext = .;
diff --git a/springbok/springbok.cpp b/springbok/springbok.cpp
new file mode 100644
index 0000000..678e196
--- /dev/null
+++ b/springbok/springbok.cpp
@@ -0,0 +1,40 @@
+#include "springbok.h"
+
+extern "C" void print_csrs(void) {
+    uint32_t mcause;
+    uint32_t mepc;
+    uint32_t mtval;
+    uint32_t misa;
+    uint32_t mtvec;
+    uint32_t mhartid;
+    uint32_t marchid;
+    uint32_t mvendorid;
+    uint32_t mimpid;
+    __asm__ volatile("csrr %[MCAUSE], mcause"
+                   : [MCAUSE] "=r"(mcause):);
+    __asm__ volatile("csrr %[MEPC], mepc"
+                   : [MEPC] "=r"(mepc):);
+    __asm__ volatile("csrr %[MTVAL], mtval"
+                   : [MTVAL] "=r"(mtval):);
+    __asm__ volatile("csrr %[MISA], misa"
+                   : [MISA] "=r"(misa):);
+    __asm__ volatile("csrr %[MTVEC], mtvec"
+                   : [MTVEC] "=r"(mtvec):);
+    __asm__ volatile("csrr %[MHARTID], mhartid"
+                   : [MHARTID] "=r"(mhartid):);
+    __asm__ volatile("csrr %[MARCHID], marchid"
+                   : [MARCHID] "=r"(marchid):);
+    __asm__ volatile("csrr %[MVENDORID], mvendorid"
+                   : [MVENDORID] "=r"(mvendorid):);
+    __asm__ volatile("csrr %[MIMPID], mimpid"
+                   : [MIMPID] "=r"(mimpid):);
+    LOG_ERROR("MCAUSE:\t\t0x%08X", mcause);
+    LOG_ERROR("MEPC:\t\t0x%08X", mepc);
+    LOG_ERROR("MTVAL:\t\t0x%08X", mtval);
+    LOG_ERROR("MISA:\t\t0x%08X", misa);
+    LOG_ERROR("MTVEC:\t\t0x%08X", mtvec);
+    LOG_ERROR("MHARTID:\t\t0x%08X", mhartid);
+    LOG_ERROR("MARCHID:\t\t0x%08X", marchid);
+    LOG_ERROR("MVENDORID:\t0x%08X", mvendorid);
+    LOG_ERROR("MIMPID:\t\t0x%08X", mimpid);
+ }