;
;  @author  xamidev <xamidev@riseup.net>
;  @brief   Stub for Interrupt Descriptor Table handlers
;  @license GPL-3.0-only
;

bits 64

extern interrupt_dispatch

global interrupt_stub
global vector_0_handler
global vector_1_handler
global vector_2_handler
global vector_3_handler
global vector_4_handler
global vector_5_handler
global vector_6_handler
global vector_7_handler
global vector_8_handler
global vector_9_handler
global vector_10_handler
global vector_11_handler
global vector_12_handler
global vector_13_handler
global vector_14_handler
global vector_15_handler
global vector_16_handler
global vector_17_handler
global vector_18_handler
global vector_19_handler
global vector_20_handler
global vector_21_handler

global vector_128_handler

interrupt_stub:
    ; We'll push all general-purpose registers to the stack,
    ; so they're intact and don't bother the code that was
    ; executed when the interrupt happened.
    ; (except rsp because it will already be saved in the iret frame)
    
    push qword rax
    push qword rbx
    push qword rcx
    push qword rdx
    push qword rsi 
    push qword rdi
    ;push qword rsp
    push qword rbp
    push qword r8
    push qword r9
    push qword r10
    push qword r11
    push qword r12
    push qword r13
    push qword r14
    push qword r15

    ; Put stack pointer as first argument of our function
    mov rdi, rsp
    call interrupt_dispatch
    ; What the function returns (new stack pointer) is saved in rbp
    mov rsp, rax

    pop qword r15
    pop qword r14
    pop qword r13
    pop qword r12
    pop qword r11
    pop qword r10
    pop qword r9
    pop qword r8
    pop qword rbp
    ;pop qword rsp
    pop qword rdi
    pop qword rsi
    pop qword rdx
    pop qword rcx
    pop qword rbx
    pop qword rax

    ; Removing the error code and vector number so stack doesn't
    ; get corrupted
    add rsp, 16
    
    ; Restore ss, rsp, rflags, cs, rip of code that was executing
    ; before the interrupt
    iretq

; Vector handlers will be 16-byte aligned so that we can loop over them
; like <vector_no> * 16 to get each one's address

; Divide Error
align 16
vector_0_handler:
    ; error code (nothing, so we push a dummy 0 quadword, 64bits/8bytes long)
    push qword 0
    ; vector number (so our interrupt stub knows which one it is)
    push qword 0
    jmp interrupt_stub

; Debug Exception
align 16
vector_1_handler:
    push qword 0
    push qword 1
    jmp interrupt_stub

; NMI
align 16
vector_2_handler:
    push qword 0
    push qword 2
    jmp interrupt_stub

; Breakpoint
align 16
vector_3_handler:
    push qword 0
    push qword 3
    jmp interrupt_stub

; Overflow
align 16
vector_4_handler:
    push qword 0
    push qword 4
    jmp interrupt_stub

; BOUND Range exceeded
align 16
vector_5_handler:
    push qword 0
    push qword 5
    jmp interrupt_stub

; Invalid Opcode
align 16
vector_6_handler:
    push qword 0
    push qword 6
    jmp interrupt_stub

; Device Not Available
align 16
vector_7_handler:
    push qword 0
    push qword 7
    jmp interrupt_stub

; Double Fault
align 16
vector_8_handler:
    ; No error code, we only push vector number
    push qword 8
    jmp interrupt_stub

; Coprocessor Segment Overrun
align 16
vector_9_handler:
    push qword 0
    push qword 9
    jmp interrupt_stub

; Invalid TSS
align 16
vector_10_handler:
    push qword 10
    jmp interrupt_stub

; Segment Not Present
align 16
vector_11_handler:
    push qword 11
    jmp interrupt_stub

; Stack-Segment Fault
align 16
vector_12_handler:
    push qword 12
    jmp interrupt_stub

; General Protection
align 16
vector_13_handler:
    push qword 13
    jmp interrupt_stub

; Page Fault
align 16
vector_14_handler:
    push qword 14
    jmp interrupt_stub

; Intel reserved
align 16
vector_15_handler:
    push qword 0
    push qword 15
    jmp interrupt_stub

; x87 FPU Floating-Point Error
align 16
vector_16_handler:
    push qword 0
    push qword 16
    jmp interrupt_stub

; Alignment Check
align 16
vector_17_handler:
    push qword 17
    jmp interrupt_stub

; Machine Check
align 16
vector_18_handler:
    push qword 0
    push qword 18
    jmp interrupt_stub

; SIMD Floating-Point Exception
align 16
vector_19_handler:
    push qword 0
    push qword 19
    jmp interrupt_stub

; Virtualization Exception
align 16
vector_20_handler:
    push qword 0
    push qword 20
    jmp interrupt_stub

; Control Protection Exception
align 16
vector_21_handler:
    push qword 21
    jmp interrupt_stub

; The others are reserved (22->31) or external (32->255) interrupts

align 16
vector_22_handler:
    push qword 0
    push qword 22
    jmp interrupt_stub

align 16
vector_23_handler:
    push qword 0
    push qword 23
    jmp interrupt_stub

align 16
vector_24_handler:
    push qword 0
    push qword 24
    jmp interrupt_stub

align 16
vector_25_handler:
    push qword 0
    push qword 25
    jmp interrupt_stub

align 16
vector_26_handler:
    push qword 0
    push qword 26
    jmp interrupt_stub

align 16
vector_27_handler:
    push qword 0
    push qword 27
    jmp interrupt_stub

align 16
vector_28_handler:
    push qword 0
    push qword 28
    jmp interrupt_stub

align 16
vector_29_handler:
    push qword 0
    push qword 29
    jmp interrupt_stub

align 16
vector_30_handler:
    push qword 0
    push qword 30
    jmp interrupt_stub

align 16
vector_31_handler:
    push qword 0
    push qword 31
    jmp interrupt_stub

; PIT timer
align 16
vector_32_handler:
    push qword 0
    push qword 32
    jmp interrupt_stub

; PS/2 Keyboard
align 16
vector_33_handler:
    push qword 0
    push qword 33
    jmp interrupt_stub

; Syscall Interrupt (0x80)
align 16
vector_128_handler:
    push qword 0
    push qword 128
    jmp interrupt_stub