.intel_syntax noprefix

// void context_switch(UINT64* old_rsp, UINT64 new_rsp)
// rdi = &old_rsp  (pointer to save current RSP)
// rsi = new_rsp   (value of new stack pointer)
//
// Saves/restores callee-saved registers only.
// The caller-saved registers are already saved on the task's stack
// by the ISR stub (for preemptive switching) or are not in use
// (for the initial switch).
//
// For preemptive switching:
//   - Timer IRQ fires, ISR stub pushes rax-r11 + trap_frame
//   - C code runs (isr_dispatch → timer handler → scheduler)
//   - context_switch saves/restores callee-saved regs + switches RSP
//   - On return, C code unwinds, isr_common pops rax-r11 + iretq
//
// For new tasks:
//   - task_create sets up a fake trap_frame on the stack
//   - context_switch pops callee-saved regs, returns into task_entry_trampoline
.global context_switch
context_switch:
    push rbx
    push rbp
    push r12
    push r13
    push r14
    push r15

    mov [rdi], rsp      // save current RSP
    mov rsp, rsi        // switch to new stack

    pop r15
    pop r14
    pop r13
    pop r12
    pop rbp
    pop rbx

    ret

.section .note.GNU-stack,"",@progbits
