.text

int_nestcnt:
	.long 0

.macro asm_int_handler intno
.global asm_int_handler\intno
asm_int_handler\intno:
	pusha
	pushl	%gs
	pushl	%fs
	pushl	%es
	pushl	%ds

	cli
	movl	int_nestcnt, %eax
	addl	$1, %eax
	movl	%eax, int_nestcnt
	cmpl	$1, %eax
	jne	1f

	movl    _ZN13TaskScheduler10CurrentTcbE, %ebx
	movl    %esp, %edx
	movl    %edx, 4(%ebx)
1:
	sti

        pushl   $\intno
        pushl   $InterruptManager
        call    _ZN6IntMgr15dispatchHandlerENS_6IrqNumE
        addl    $8, %esp

	cli
	movl	int_nestcnt, %eax
	subl	$1, %eax
	movl	%eax, int_nestcnt
	cmpl	$0, %eax
	jne	1f

	movl    _ZN13TaskScheduler10CurrentTcbE, %eax
	jmp     _context_restore

1:
	jmp	_load_context

.endm

.global task_dispatch
task_dispatch:
	cli
	movl    4(%esp), %eax
	push    %cs
	call    _context_change
	sti
	ret

.global _context_change
.global _context_restore
_context_change:
	pushl   %eax
	pushl   %eax
	pushf
	movl    12(%esp), %eax
	movl    %eax, 8(%esp)
	movl    16(%esp), %eax
	movl    %eax, 12(%esp)
	movl    (%esp), %eax
	movl    %eax, 16(%esp)
	addl    $4, %esp
	popl    %eax

	pusha
	pushl   %gs
	pushl   %fs
	pushl   %es
	pushl   %ds

	movl    _ZN13TaskScheduler10CurrentTcbE, %ebx
	movl    %esp, %edx
	movl    %edx, 4(%ebx)

_context_restore:
	movl    4(%eax), %edx
	movl    %edx, %esp

	/* current task change!! */
	movl    %eax, _ZN13TaskScheduler10CurrentTcbE 

_load_context:
	popl    %ds
	popl    %es
	popl    %fs
	popl    %gs
	popa

	iret

asm_int_handler 0
asm_int_handler 1
