Configure the vector table
When any exception is taken, the processor must handle the exception correctly. This means that the processor must detect the type of exception, then branch to an appropriate handler.
Let’s look at the code in vectors.s
. Here we can see how a vector table is configured to branch fiqFirstLevelHandler
when an FIQ event occurs:
.section VECTORS,"ax" .align 12 .global vectors vectors: .global fiqHandler // ------------------------------------------------------------ // Current EL with SP0 // ------------------------------------------------------------ .balign 128 sync_current_el_sp0: B . // Synchronous .balign 128 irq_current_el_sp0: B . // IRQ .balign 128 fiq_current_el_sp0: B fiqFirstLevelHandler // FIQ .balign 128 serror_current_el_sp0: B . // SError // // NB, CODE OMITTED! // fiqFirstLevelHandler: STP x29, x30, [sp, #-16]! STP x18, x19, [sp, #-16]! STP x16, x17, [sp, #-16]! STP x14, x15, [sp, #-16]! STP x12, x13, [sp, #-16]! STP x10, x11, [sp, #-16]! STP x8, x9, [sp, #-16]! STP x6, x7, [sp, #-16]! STP x4, x5, [sp, #-16]! STP x2, x3, [sp, #-16]! STP x0, x1, [sp, #-16]! BL fiqHandler LDP x0, x1, [sp], #16 LDP x2, x3, [sp], #16 LDP x4, x5, [sp], #16 LDP x6, x7, [sp], #16 LDP x8, x9, [sp], #16 LDP x10, x11, [sp], #16 LDP x12, x13, [sp], #16 LDP x14, x15, [sp], #16 LDP x16, x17, [sp], #16 LDP x18, x19, [sp], #16 LDP x29, x30, [sp], #16 ERET
In this case, only an FIQ entry and handler have been defined. In fact, fiqFirstLevelHandler
merely branches to fiqHandler
, a procedure that we will define later in C. Here, we have used the BL
instruction, or branch with link, which branches to the given label. The BL
instruction saves the current value of the program counter plus four bytes, the next instruction address, to register x30
.
Our C procedure ends with a return statement which compiles to a RET
instruction. By default (that is, if no other register is specified) RET
branches to the address stored in register x30
.
The handler also saves and restores all the general-purpose registers. This is because these registers may be modified by the procedure call.
The remaining entries branch to self, because the handlers have not been written. When you create your own image, you will need to define and configure your vector table to handle all required event types.