/*
 * Copyright (c) 2026, Chloe M.
 * Provided under the BSD-3 clause.
 *
 * Description: AMD64 trapframe helpers
 * Author:      Chloe M.
 */

#ifndef _MACHINE_FRAMEASM_H_
#define _MACHINE_FRAMEASM_H_ 1

/*
 * Push all general purpose registers alongside an
 * interrupt vector number
 */
#define _TRAP_PUSHALL(VEC)   \
    push %r15               ;\
    push %r14               ;\
    push %r13               ;\
    push %r12               ;\
    push %r11               ;\
    push %r10               ;\
    push %r9                ;\
    push %r8                ;\
    push %rbp               ;\
    push %rdi               ;\
    push %rsi               ;\
    push %rdx               ;\
    push %rcx               ;\
    push %rbx               ;\
    push %rax               ;\
    push VEC

/*
 * Pop an interrupt vector alongside all general purpose
 * registers
 */
#define _TRAP_POPALL()      ;\
    add $8, %rsp            ;\
    pop %rax                ;\
    pop %rbx                ;\
    pop %rcx                ;\
    pop %rdx                ;\
    pop %rsi                ;\
    pop %rdi                ;\
    pop %rbp                ;\
    pop %r8                 ;\
    pop %r9                 ;\
    pop %r10                ;\
    pop %r11                ;\
    pop %r12                ;\
    pop %r13                ;\
    pop %r14                ;\
    pop %r15                ;\
    add $8, %rsp

/*
 * Interrupt entry macro used when the CPU pushes an error
 * code onto the stack.
 */
#define INTR_ENTRY_EC(VEC)   \
    cld                     ;\
    _TRAP_PUSHALL(VEC)      ;\
    testb $3, 16(%rsp)      ;\
    jz 1f                   ;\
    lfence                  ;\
    swapgs                  ;\
1:

/*
 * Interrupt entry macro used when there is no error code pushed
 * onto the stack.
 */
#define INTR_ENTRY(VEC)     ;\
    cld                     ;\
    testb $3, 8(%rsp)       ;\
    jz 1f                   ;\
    lfence                  ;\
    swapgs                  ;\
1:  push $0                 ;\
    _TRAP_PUSHALL(VEC)      ;\

/*
 * Interrupt exit macro used when there is no error code
 * pushed onto the stack.
 */
#define INTR_EXIT()         ;\
    _TRAP_POPALL()          ;\
    testb $3, 8(%rsp)       ;\
    jz 1f                   ;\
    lfence                  ;\
    swapgs                  ;\
1:  iretq

#endif  /* !_MACHINE_FRAMEASM_H_ */
