From 3e81796db755ca8b8b5c16b27e01d2e865f97ae4 Mon Sep 17 00:00:00 2001
From: Michael Scire <SciresM@gmail.com>
Date: Sat, 21 Aug 2021 11:17:16 -0700
Subject: [PATCH] fusee-cpp: setup exception handlers during crt0

---
 fusee_cpp/program/source/fusee_crt0.cpp       | 21 +++++++++++++++++++
 .../source/fusee_exception_handler.hpp        |  2 +-
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/fusee_cpp/program/source/fusee_crt0.cpp b/fusee_cpp/program/source/fusee_crt0.cpp
index 791faa796..58cad7488 100644
--- a/fusee_cpp/program/source/fusee_crt0.cpp
+++ b/fusee_cpp/program/source/fusee_crt0.cpp
@@ -14,14 +14,35 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 #include <exosphere.hpp>
+#include "fusee_exception_handler.hpp"
 
 extern "C" void __libc_init_array();
 
 namespace ams::nxboot::crt0 {
 
+    namespace {
+
+        ALWAYS_INLINE void SetExceptionVector(u32 which, uintptr_t impl) {
+            reg::Write(secmon::MemoryRegionPhysicalDeviceExceptionVectors.GetAddress() + 0x200 + sizeof(u32) * which, static_cast<u32>(impl));
+        }
+
+    }
+
     void Initialize(uintptr_t bss_start, uintptr_t bss_end) {
         /* TODO: Collect timing information? */
 
+        /* Setup exception vectors. */
+        {
+            SetExceptionVector(0, reinterpret_cast<uintptr_t>(::ams::nxboot::ExceptionHandler0));
+            SetExceptionVector(1, reinterpret_cast<uintptr_t>(::ams::nxboot::ExceptionHandler1));
+            SetExceptionVector(2, reinterpret_cast<uintptr_t>(::ams::nxboot::ExceptionHandler2));
+            SetExceptionVector(3, reinterpret_cast<uintptr_t>(::ams::nxboot::ExceptionHandler3));
+            SetExceptionVector(4, reinterpret_cast<uintptr_t>(::ams::nxboot::ExceptionHandler4));
+            SetExceptionVector(5, reinterpret_cast<uintptr_t>(::ams::nxboot::ExceptionHandler5));
+            SetExceptionVector(6, reinterpret_cast<uintptr_t>(::ams::nxboot::ExceptionHandler6));
+            SetExceptionVector(7, reinterpret_cast<uintptr_t>(::ams::nxboot::ExceptionHandler7));
+        }
+
         /* Clear bss. */
         std::memset(reinterpret_cast<void *>(bss_start),      0, bss_end - bss_start);
 
diff --git a/fusee_cpp/program/source/fusee_exception_handler.hpp b/fusee_cpp/program/source/fusee_exception_handler.hpp
index 6695f1e5f..168edc206 100644
--- a/fusee_cpp/program/source/fusee_exception_handler.hpp
+++ b/fusee_cpp/program/source/fusee_exception_handler.hpp
@@ -16,7 +16,7 @@
 #include <exosphere.hpp>
 #pragma once
 
-namespace ams::nxboot::loader {
+namespace ams::nxboot {
 
     NORETURN void ExceptionHandler();