/*
 * Copyright (c) 2007, 2008 University of Tsukuba
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 3. Neither the name of the University of Tsukuba nor the names of its
 *    contributors may be used to endorse or promote products derived from
 *    this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
/*
 * Copyright (c) 2010-2013 Yuichi Watanabe
 */

	SEG_SEL_PCPU32	= (8 * 8)
	SEG_SEL_PCPU64	= (16 * 8)
	gs_inthandling	= 0

	.include "longmode.h"

	.text
	.globl	int_handler
	.globl	int_receive

.if longmode
	# 64bit
	.align	8
/*
int_handler:
	push	%gs
	push	$SEG_SEL_PCPU64
	pop	%gs
	cmpq	$0,%gs:gs_inthandling
	je	1f
	pop	%rax
	pop	%rax		# interrupt number
	mov	%gs:gs_inthandling,%rsp
	ret			# return
*/	
int_handler:
	push	%gs
	push	$SEG_SEL_PCPU64
	pop	%gs
	cmpq	$0,%gs:gs_inthandling
	je	1f
	mov	32(%rsp),%rax	# 0:gs 8:vector 16:eip 24:cs 32 rflags
	and	$0xfffffffffffffdff,%rax	# clear IF bit
	mov	%rax,32(%rsp)
	pop	%gs		# pop gs
	pop	%rax		# pop vector
	iretq
1:
	push	$0
	push	$0
	push	$0
	push	$0
	push	%fs
	push	%rax
	mov	%es,%rax
	mov	%rax,8*5(%rsp)
	mov	%cs,%rax
	mov	%rax,8*4(%rsp)
	mov	%ss,%rax
	mov	%rax,8*3(%rsp)
	mov	%ds,%rax
	mov	%rax,8*2(%rsp)
	push	%rcx
	push	%rdx
	push	%rbx
	push	%rsp
	push	%rbp
	push	%rsi
	push	%rdi
	push	%r8
	push	%r9
	push	%r10
	push	%r11
	push	%r12
	push	%r13
	push	%r14
	push	%r15
	mov	%ss,%rax
	mov	%rax,%ds
	mov	%rax,%es
	mov	%rax,%fs
	mov	%rsp,%rdi /* 1st param */
	call	do_int
	pop	%r15
	pop	%r14
	pop	%r13
	pop	%r12
	pop	%r11
	pop	%r10
	pop	%r9
	pop	%r8
	pop	%rdi
	pop	%rsi
	pop	%rbp
	pop	%rsp
	pop	%rbx
	pop	%rdx
	pop	%rcx
	mov	8*2(%rsp),%rax
	mov	%rax,%ds
	mov	8*5(%rsp),%rax
	mov	%rax,%es
	# We can't mov rax to cs or ss.
	pop	%rax
	pop	%fs
	addq	$(8*4),%rsp
	pop	%gs
	addq	$8,%rsp # Pop vector pushed by int0xXXhandler.
	iretq
	.align	8
int_receive:
	mov	%rsp,%gs:gs_inthandling
	mov	$-1,%rax
	sti
	nop
	cli
	movq	$0,%gs:gs_inthandling
	ret
.else
	# 32bit
	.align	8
int_handler:
	push	%gs
	push	$SEG_SEL_PCPU32
	pop	%gs
	push	%es
	push	%cs
	push	%ss
	push	%ds
	push	%fs
	pusha
	sub	$32,%esp	# Push dummy.
	mov	%ss,%eax
	mov	%eax,%ds
	mov	%eax,%es
	mov	%eax,%fs
	push	%esp		# Push 1st param
	call	do_int
	add	$36,%esp	# Pop 1st param and dummy.
	popa
	pop	%fs
	pop	%ds
	pop	%ss
	pop	%es	# We can't pop to cs
	pop	%es
	pop	%gs
	addl	$4,%esp # Pop vector pushed by int0xXXhandler.
	iret
.endif
