/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2006-09-15     QiuYi        The first version
 */

/**
 * @addtogroup I386
 */
/*@{*/

#define ENTRY(proc)\
	.align 2;\
	.globl proc;\
	.type proc,@function;\
	proc:
#define HDINTERRUPTFNC(name,num) \
	ENTRY(name)\
	pushl $(num);\
	jmp _hdinterrupts;\
	.data;\
	.long name;\
	.text

.globl hdinterrupt_func
	.data
	.align 4
	.type hdinterrupt_func,@object
	hdinterrupt_func :
.text

/* the external device interrupts */
HDINTERRUPTFNC(irq0, 0)
HDINTERRUPTFNC(irq1, 1)
HDINTERRUPTFNC(irq2, 2)
HDINTERRUPTFNC(irq3, 3)
HDINTERRUPTFNC(irq4, 4)
HDINTERRUPTFNC(irq5, 5)
HDINTERRUPTFNC(irq6, 6)
HDINTERRUPTFNC(irq7, 7)
HDINTERRUPTFNC(irq8, 8)
HDINTERRUPTFNC(irq9, 9)
HDINTERRUPTFNC(irq10, 10)
HDINTERRUPTFNC(irq11, 11)
HDINTERRUPTFNC(irq12, 12)
HDINTERRUPTFNC(irq13, 13)
HDINTERRUPTFNC(irq14, 14)
HDINTERRUPTFNC(irq15, 15)

.p2align 4,0x90
.globl _hdinterrupts
.type _hdinterrupts,@function
.globl rt_interrupt_enter
.globl rt_interrupt_leave
.globl rt_hw_isr
.globl rt_thread_switch_interrupt_flag
.globl rt_interrupt_from_thread
.globl rt_interrupt_to_thread

_hdinterrupts:
	push %ds
	push %es
	pushal
	movw $0x10, %ax
	movw %ax, %ds
	movw %ax, %es
	pushl %esp

	call rt_interrupt_enter

	movl %esp, %eax	      /* copy esp to eax */
	addl $0x2c, %eax      /* move to vector address */
	movl (%eax), %eax     /* vector(eax) = *eax */

	pushl %eax            /* push argument : int vector */
	call rt_hw_isr
	add $4, %esp          /* restore argument */

	call rt_interrupt_leave

	/* if rt_thread_switch_interrupt_flag set, jump to _interrupt_thread_switch and don't return */
	movl $rt_thread_switch_interrupt_flag, %eax
	movl (%eax), %ebx
	cmp $0x1, %ebx
	jz _interrupt_thread_switch

	popl %esp
	popal
	pop %es
	pop %ds
	add $4,%esp
	iret

_interrupt_thread_switch:
	popl %esp

	movl $0x0, %ebx
	movl %ebx, (%eax)

	movl $rt_interrupt_from_thread, %eax
	movl (%eax), %ebx
	movl %esp, (%ebx)

	movl $rt_interrupt_to_thread, %ecx
	movl (%ecx), %edx
	movl (%edx), %esp

	popal
	pop %es
	pop %ds
	add $4,%esp
	iret

/*@}*/