.section .vector_t  , "ax"
.extern irq_handler

.macro    ventry    label
.align 7
b    \label
.endm

.global vector_table
vector_table:
    // Exceptions from current EL using SP_EL0
    ventry .
    ventry .
    ventry .
    ventry .

    // Exceptions from the current EL using SP_ELx
    ventry synchronous_interrupt_no_el_change       // Synchronous Exception  0x200
    ventry irq_handler                              // IRQ(Interrupt Request) 0x280
    ventry .                                        // FIQ(Fast Interrupt Request) 0x300
    ventry .                                        // SError 0x580

    // Exceptions from lower EL AArch64
    ventry synchronous_interrupt_imm_lower_aarch64  // Synchronous Exception 0x400
    ventry irq_handler                              // IRQ(Interrupt Request) 0x480
    ventry .                                        //  FIQ(Fast Interrupt Request) 0x500
    ventry .                                        // SError 0x580

    // Exceptions from lower EL AArch32
    ventry .
    ventry .
    ventry .
    ventry .

.align 4
irq_handler:
    sub sp, sp, #176
    stp x0, x1, [sp, #0]
    stp x2, x3, [sp, #16]
    stp x4, x5, [sp, #32]
    stp x6, x7, [sp, #48]
    stp x8, x9, [sp, #64]
    stp x10, x11, [sp, #80]
    stp x12, x13, [sp, #96]
    stp x14, x15, [sp, #112]
    stp x16, x17, [sp, #128]
    stp x18, x29, [sp, #144]
    stp x30, xzr, [sp, #160]

    bl rust_irq_handler

    ldp x0, x1, [sp, #0]
    ldp x2, x3, [sp, #16]
    ldp x4, x5, [sp, #32]
    ldp x6, x7, [sp, #48]
    ldp x8, x9, [sp, #64]
    ldp x10, x11, [sp, #80]
    ldp x12, x13, [sp, #96]
    ldp x14, x15, [sp, #112]
    ldp x16, x17, [sp, #128]
    ldp x18, x29, [sp, #144]
    ldp x30, xzr, [sp, #160]
    add sp, sp, #176

    eret

.align 4
synchronous_interrupt_imm_lower_aarch64:
    sub sp, sp, #176
    stp x0, x1, [sp, #0]
    stp x2, x3, [sp, #16]
    stp x4, x5, [sp, #32]
    stp x6, x7, [sp, #48]
    stp x8, x9, [sp, #64]
    stp x10, x11, [sp, #80]
    stp x12, x13, [sp, #96]
    stp x14, x15, [sp, #112]
    stp x16, x17, [sp, #128]
    stp x18, x29, [sp, #144]
    stp x30, xzr, [sp, #160]

    mov x0, sp
    bl rust_synchronous_interrupt_imm_lower_aarch64
    str x0, [sp, #0]

    ldp x0, x1, [sp, #0]
    ldp x2, x3, [sp, #16]
    ldp x4, x5, [sp, #32]
    ldp x6, x7, [sp, #48]
    ldp x8, x9, [sp, #64]
    ldp x10, x11, [sp, #80]
    ldp x12, x13, [sp, #96]
    ldp x14, x15, [sp, #112]
    ldp x16, x17, [sp, #128]
    ldp x18, x29, [sp, #144]
    ldp x30, xzr, [sp, #160]
    add sp, sp, #176

    eret

.align 4
synchronous_interrupt_no_el_change:
    sub sp, sp, #176
    stp x0, x1, [sp, #0]
    stp x2, x3, [sp, #16]
    stp x4, x5, [sp, #32]
    stp x6, x7, [sp, #48]
    stp x8, x9, [sp, #64]
    stp x10, x11, [sp, #80]
    stp x12, x13, [sp, #96]
    stp x14, x15, [sp, #112]
    stp x16, x17, [sp, #128]
    stp x18, x29, [sp, #144]
    stp x30, xzr, [sp, #160]

    mov x0, sp
    bl rust_synchronous_interrupt_no_el_change
    str x0, [sp, #0]

    ldp x0, x1, [sp, #0]
    ldp x2, x3, [sp, #16]
    ldp x4, x5, [sp, #32]
    ldp x6, x7, [sp, #48]
    ldp x8, x9, [sp, #64]
    ldp x10, x11, [sp, #80]
    ldp x12, x13, [sp, #96]
    ldp x14, x15, [sp, #112]
    ldp x16, x17, [sp, #128]
    ldp x18, x29, [sp, #144]
    ldp x30, xzr, [sp, #160]
    add sp, sp, #176

    eret
