/* SPDX-License-Identifier: MPL-2.0 */

.text
.code64

.global context_switch
.type context_switch, @function
context_switch: # (nxt: *const TaskContext, cur: *mut TaskContext)
  # Save cur's register
  mov rax, [rsp] # return address
  mov [rsi + 56], rax # 56 = offsetof(TaskContext, rip)
  mov [rsi + 0], rsp
  mov [rsi + 8], rbx
  mov [rsi + 16], rbp
  mov [rsi + 24], r12
  mov [rsi + 32], r13
  mov [rsi + 40], r14
  mov [rsi + 48], r15
  rdfsbase r15
  mov [rsi + 64], r15 # 64 = offsetof(TaskContext, fsbase)
  # Fallthrough

.global first_context_switch
.type first_context_switch, @function
first_context_switch: # (nxt: *const TaskContext)
  # Restore nxt's registers
  mov r15, [rdi + 64]
  wrfsbase r15
  mov rsp, [rdi + 0]
  mov rbx, [rdi + 8]
  mov rbp, [rdi + 16]
  mov r12, [rdi + 24]
  mov r13, [rdi + 32]
  mov r14, [rdi + 40]
  mov r15, [rdi + 48]
  mov rax, [rdi + 56] # restore return address
  mov [rsp], rax # for stack balance, must use mov instead of push

  ret
.size context_switch, .-context_switch
.size first_context_switch, .-first_context_switch

.global kernel_task_entry_wrapper
.type kernel_task_entry_wrapper, @function
kernel_task_entry_wrapper:
  .cfi_startproc
  .cfi_undefined rip # mark return address as undefined to indicate end of call stack
  add rsp, 8 # for stack balance, must increase rsp before the following call
  call kernel_task_entry
  .cfi_endproc
.size kernel_task_entry_wrapper, .-kernel_task_entry_wrapper
