[sw/test_rom] Embed IRQ vector config in startup asm.

The test ROM defines the IRQ vectors in a separate asm file, however,
the production mask ROM configures the IRQ vector in the asm startup
code. This commit aligns the test ROM IRQ vector configs to be similar
to the production mask ROM.

This partially addresses #9787.

Signed-off-by: Timothy Trippel <ttrippel@google.com>
diff --git a/sw/device/lib/testing/test_rom/BUILD b/sw/device/lib/testing/test_rom/BUILD
index 24b7c5a..b503376 100644
--- a/sw/device/lib/testing/test_rom/BUILD
+++ b/sw/device/lib/testing/test_rom/BUILD
@@ -2,20 +2,17 @@
 # Licensed under the Apache License, Version 2.0, see LICENSE for details.
 # SPDX-License-Identifier: Apache-2.0
 
-package(default_visibility = ["//visibility:public"])
-
 load("//rules:opentitan.bzl", "OPENTITAN_CPU", "opentitan_binary", "opentitan_functest")
 load("//rules:autogen.bzl", "autogen_chip_info")
 
+package(default_visibility = ["//visibility:public"])
+
 autogen_chip_info(
     name = "chip_info",
 )
 
 opentitan_binary(
     name = "test_rom",
-    srcs = [
-        "test_rom_irq_vector.S",
-    ],
     linkopts = [
         "-T $(location test_rom.ld)",
     ],
diff --git a/sw/device/lib/testing/test_rom/meson.build b/sw/device/lib/testing/test_rom/meson.build
index 3ad7f9d..2e29acd 100644
--- a/sw/device/lib/testing/test_rom/meson.build
+++ b/sw/device/lib/testing/test_rom/meson.build
@@ -41,7 +41,6 @@
       hw_ip_edn_reg_h,
       'test_rom.c',
       'bootstrap.c',
-      'test_rom_irq_vector.S',
       'test_rom_start.S',
     ],
     name_suffix: 'elf',
diff --git a/sw/device/lib/testing/test_rom/test_rom.ld b/sw/device/lib/testing/test_rom/test_rom.ld
index e667651..a7785b5 100644
--- a/sw/device/lib/testing/test_rom/test_rom.ld
+++ b/sw/device/lib/testing/test_rom/test_rom.ld
@@ -61,7 +61,7 @@
  */
 SECTIONS {
   /**
-   * Ibex interrupt vector. See test_rom_irq_vector.S for more information.
+   * Ibex interrupt vector. See test_rom_start.S for more information.
    *
    * This has to be set up at the boot address, so that execution jumps to the
    * reset handler correctly.
diff --git a/sw/device/lib/testing/test_rom/test_rom_irq_vector.S b/sw/device/lib/testing/test_rom/test_rom_irq_vector.S
deleted file mode 100644
index 861f29c..0000000
--- a/sw/device/lib/testing/test_rom/test_rom_irq_vector.S
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright lowRISC contributors.
-// Licensed under the Apache License, Version 2.0, see LICENSE for details.
-// SPDX-License-Identifier: Apache-2.0
-
-/**
- * Interrupt handler vector, set up so that all interrupts are 
- * caught and loop forever.
- *
- * See the Ibex manual, Chapter 11, for more information.
- */
-  // NOTE: The "ax" flag below is necessary to ensure that this section 
-  // is allocated executable space in ROM by the linker.
-  .section .vectors, "ax"
-  .option push
-
-  // Disable RISC-V instruction compression: we need all instructions to 
-  // be exactly word wide in the interrupt vector.
-  .option norvc
-
-  // Disable RISC-V linker relaxation, as it can compress instructions at
-  // link-time, which we also really don't want.
-  .option norelax
-
-  // Exception handler.
-  .org 0x00
-  j exception_handler
-
-  // Software interrupt handler.
-  .org 0x0c
-  j default_irq_handler
-
-  // Timer interrupt handler.
-  .org 0x1c
-  j default_irq_handler
-
-  // External interrupt handler
-  .org 0x2c
-  j default_irq_handler
-
-  // Fast interrupts, 0 through 14.
-  // Since there are 15 of these in a continuous block,
-  // we just repeat the same instruction.
-  .org 0x40
-  .rept 15
-  j default_irq_handler
-  .endr
-
-  // Non-maskable interrupt (NMI) handler.
-  .org 0x7c
-  j default_irq_handler
-
-  // Reset vector, the initial entry point after reset.
-  .org 0x80
-  j _reset_start
-
-  .option pop
-
-  // Put these handlers in the code section.
-  .text
-/**
- * Default exception handler; loops forever.
- */
-exception_handler:
-  wfi
-  j exception_handler
-
-/**
- * Default interrupt handler; loops forever.
- */
-default_irq_handler:
-  wfi
-  j default_irq_handler
diff --git a/sw/device/lib/testing/test_rom/test_rom_start.S b/sw/device/lib/testing/test_rom/test_rom_start.S
index e4b14eb..39ba6e3 100644
--- a/sw/device/lib/testing/test_rom/test_rom_start.S
+++ b/sw/device/lib/testing/test_rom/test_rom_start.S
@@ -2,15 +2,70 @@
 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
 // SPDX-License-Identifier: Apache-2.0
 
+#include "hw/top_earlgrey/sw/autogen/top_earlgrey_memory.h"
+#include "sram_ctrl_regs.h"
+#include "entropy_src_regs.h"
+#include "csrng_regs.h"
+#include "edn_regs.h"
+
 /**
- * Boot ROM runtime initialization code.
+ * Test ROM interrupt vectors.
+ *
+ * After reset all interrupts are disabled. Only exceptions (interrupt 0) and
+ * non-maskable interrupts (interrupt 31) are possible. For simplicity however
+ * we just set all interrupt handlers in the Test ROM to use the same handler,
+ * which loops forever.
+ *
+ * Interrupt vectors in Ibex have 32 entries for 32 possible interrupts. The
+ * vector must be 256-byte aligned, as Ibex's vectoring mechanism requires that.
+ *
+ * Note that the Ibex reset handler (entry point) immediately follows this
+ * interrupt vector and can be thought of as an extra entry.
+ *
+ * More information about Ibex's interrupts can be found here:
+ *   https://ibex-core.readthedocs.io/en/latest/03_reference/exception_interrupts.html
  */
 
-  #include "hw/top_earlgrey/sw/autogen/top_earlgrey_memory.h"
-  #include "sram_ctrl_regs.h"
-  #include "entropy_src_regs.h"
-  #include "csrng_regs.h"
-  #include "edn_regs.h"
+  // Push Test ROM interrupt vector options.
+  .option push
+
+  // Disable RISC-V instruction compression: we need all instructions to
+  // be exactly word wide in the interrupt vector.
+  .option norvc
+
+  // Disable RISC-V linker relaxation, as it can compress instructions at
+  // link-time, which we also really don't want.
+  .option norelax
+
+  // NOTE: The "ax" flag below is necessary to ensure that this section
+  // is allocated executable space in ROM by the linker.
+  .section .vectors, "ax"
+  .balign 256
+  .globl _test_rom_interrupt_vector
+  .type _test_rom_interrupt_vector, @function
+_test_rom_interrupt_vector:
+
+  // Each jump instruction must be exactly 4 bytes in order to ensure that the
+  // entries are properly located.
+  .rept 32
+  j _test_rom_irq_handler
+  .endr
+
+  // Ibex reset vector, the initial entry point after reset. (This falls at IRQ
+  // handler 0x80.)
+  j _reset_start
+
+  // Set size so this vector can be disassembled.
+  .size _test_rom_interrupt_vector, .-_test_rom_interrupt_vector
+
+  // Pop Mask ROM interrupt vector options.
+  //
+  // Re-enable compressed instructions, linker relaxation.
+  .option pop
+
+/**
+ * Test ROM runtime initialization code.
+ */
 
   // NOTE: The "ax" flag below is necessary to ensure that this section
   // is allocated executable space in ROM by the linker.
@@ -22,8 +77,6 @@
 /**
  * Entry point after reset. This symbol is jumped to from the handler
  * for IRQ 0x80.
- *
- * Sets up the stack, then jumps to `_start`.
  */
 _reset_start:
   .globl _reset_start
@@ -127,7 +180,18 @@
   // Jump into the C program entry point.
   call _boot_start
 
-  // Loop forever if _boot_start somehow returns.
-1:
+  // Enter a wait for interrupt loop, the device should reset shortly.
+.L_wfi_loop:
   wfi
-  j 1b
+  j   .L_wfi_loop
+
+/**
+ * Test ROM IRQ/exception handler; loops forever.
+ */
+
+  // Put this handler in the code section.
+ .section .text
+
+_test_rom_irq_handler:
+  wfi
+  j _test_rom_irq_handler