bits 32

global syscall_isr
global quit_isr
global yield_isr
global _start_user_mode
global kbd_isr

global udf_isr
global dfa_isr
global tsf_isr
global npf_isr
global ssf_isr
global gpf_isr
global pff_isr

extern syscall_table
extern active_task

extern delete_task
extern advance_active_task
extern on_kbd_isr
extern make_sure_tasks
extern exception_halt
extern pf_check_stack
extern dump

n_syscalls equ 0x1a

;section .bss
;_debug_is_start_task resb 1
;extern switch_to_kernel_cr3
;extern switch_to_task_cr3

section .text
syscall_isr:
  cmp eax, n_syscalls
  jge .bad

;  mov byte [_debug_is_start_task], 0
;  cmp eax, 0x4
;  jne .dont_set_debug
;  mov byte [_debug_is_start_task], 1
;.dont_set_debug:

  mov eax, dword [syscall_table + eax * 4]

  push edi
  push esi
  push edx
  push ecx
  push ebx

  call eax

  add esp, 20

;  cmp byte [_debug_is_start_task], 0
;  je .dont_do_debug
;  push eax
;  call switch_to_kernel_cr3
;  jmp $
;  call switch_to_task_cr3
;  pop eax
;.dont_do_debug:

._before_return:
  iret

.bad:
  mov eax, -1
  iret

quit_isr:
  push dword [active_task]
  call delete_task
  call make_sure_tasks
  mov dword [esp], yield_isr.return_to_task
  jmp advance_active_task

yield_isr:
  mov eax, dword [active_task]

  mov dword [eax +  8], ebx
  mov dword [eax + 12], ecx
  mov dword [eax + 16], edx
  mov dword [eax + 20], esi
  mov dword [eax + 24], edi
  mov dword [eax + 28], ebp

  mov edx, dword [esp]
  mov dword [eax], edx

  mov edx, cr3
  mov dword [eax + 4], edx

  mov edx, dword [esp + 12]
  mov dword [eax + 32], edx

  call advance_active_task

.return_to_task:
  mov eax, dword [active_task]

  mov edx, dword [eax]
  mov dword [esp], edx

  mov edx, dword [eax + 4]
  mov cr3, edx

  mov edx, dword [eax + 32]
  mov dword [esp + 12], edx

  mov ebx, dword [eax +  8]
  mov ecx, dword [eax + 12]
  mov edx, dword [eax + 16]
  mov esi, dword [eax + 20]
  mov edi, dword [eax + 24]
  mov ebp, dword [eax + 28]

._before_return:
  iret

_start_user_mode:
  mov ax, 0x2b
  mov ds, ax
  mov es, ax

  push dword 0x2b
  sub esp, 4
  push dword 0x00000200;interrupt flag
  push dword 0x23
  sub esp, 4
  jmp yield_isr.return_to_task

kbd_isr:
  push eax
  push ecx
  push edx

  call on_kbd_isr

  test eax, eax
  jz .no_debug

  push ebx
  push esi
  push edi
  push eax
  call dump
  add esp, 16

.no_debug:
  mov al, 0x20
  out 0x0020, al

  pop edx
  pop ecx
  pop eax
  iret

udf_isr:
  push 0
  push udid
  jmp exception

dfa_isr:
  push dfid
  jmp exception

tsf_isr:
  push tsid
  jmp exception

npf_isr:
  push npid
  jmp exception

ssf_isr:
  push ssid
  jmp exception

gpf_isr:
  push gpid
  jmp exception

pff_isr:
  push eax
  push ecx
  push edx

  mov eax, cr2
  push eax
  call pf_check_stack
  add esp, 4

  pop edx
  pop ecx
  test eax, eax
  jz .not_stack

  pop eax
  add esp, 4
  iret

.not_stack:
  pop eax
  push pfid
  jmp exception

exception:
  push edi
  push esi
  push edx
  push ecx
  push ebx
  push eax
  call exception_halt

section .rodata
udid db "UD", 0
dfid db "DF", 0
tsid db "TS", 0
npid db "NP", 0
ssid db "SS", 0
gpid db "GP", 0
pfid db "PF", 0