/*
 * Interrupt/exception handling.
 */
#include "amd64l.h"

MODE $64

TEXT _acintrp<>(SB), 1, $-4			/* no error code pushed */
	PUSHQ	AX				/* save AX */
	MOVQ	8(SP), AX			/* idthandlers(SB) PC */
	JMP	_acintrcommon

TEXT _acintre<>(SB), 1, $-4			/* error code pushed */
	XCHGQ	AX, (SP)
_acintrcommon:
	MOVBQZX	(AX), AX
	XCHGQ	AX, (SP)

	SUBQ	$24, SP				/* R1[45], [DEFG]S */
	CMPW	48(SP), $SSEL(SiCS, SsTIGDT|SsRPL0)	/* old CS */
	JEQ	_acintrnested

	MOVQ	RUSER, 0(SP)
	MOVQ	RMACH, 8(SP)
	MOVW	DS, 16(SP)
	MOVW	ES, 18(SP)
	MOVW	FS, 20(SP)
	MOVW	GS, 22(SP)

	SWAPGS
	BYTE $0x65; MOVQ 0, RMACH		/* m-> (MOVQ GS:0x0, R15) */
	MOVQ	16(RMACH), RUSER		/* up */

_acintrnested:
	PUSHQ	R13
	PUSHQ	R12
	PUSHQ	R11
	PUSHQ	R10
	PUSHQ	R9
	PUSHQ	R8
	PUSHQ	BP
	PUSHQ	DI
	PUSHQ	SI
	PUSHQ	DX
	PUSHQ	CX
	PUSHQ	BX
	PUSHQ	AX

	MOVQ	SP, RARG
	PUSHQ	SP
	CALL	actrap(SB)

TEXT _acintrr<>(SB), 1, $-4			/* so ktrace can pop frame */
	POPQ	AX

	POPQ	AX
	POPQ	BX
	POPQ	CX
	POPQ	DX
	POPQ	SI
	POPQ	DI
	POPQ	BP
	POPQ	R8
	POPQ	R9
	POPQ	R10
	POPQ	R11
	POPQ	R12
	POPQ	R13

	CMPQ	48(SP), $SSEL(SiCS, SsTIGDT|SsRPL0)
	JEQ	_aciretnested

	SWAPGS
	MOVW	22(SP), GS
	MOVW	20(SP), FS
	MOVW	18(SP), ES
	MOVW	16(SP), DS
	MOVQ	8(SP), RMACH
	MOVQ	0(SP), RUSER

_aciretnested:
	ADDQ	$40, SP
	IRETQ

TEXT acidthandlers(SB), 1, $-4
	CALL _acintrp<>(SB); BYTE $IdtDE		/* #DE Divide-by-Zero Error */
	CALL _acintrp<>(SB); BYTE $IdtDB		/* #DB Debug */
	CALL _acintrp<>(SB); BYTE $IdtNMI		/* #NMI Borked */
	CALL _acintrp<>(SB); BYTE $IdtBP		/* #BP Breakpoint */
	CALL _acintrp<>(SB); BYTE $IdtOF		/* #OF Overflow */
	CALL _acintrp<>(SB); BYTE $IdtBR		/* #BR Bound-Range */
	CALL _acintrp<>(SB); BYTE $IdtUD		/* #UD Invalid-Opcode */
	CALL _acintrp<>(SB); BYTE $IdtNM		/* #NM Device-Not-Available */
	CALL _acintre<>(SB); BYTE $IdtDF		/* #DF Double-Fault */
	CALL _acintrp<>(SB); BYTE $Idt09		/* reserved */
	CALL _acintre<>(SB); BYTE $IdtTS		/* #TS Invalid-TSS */
	CALL _acintre<>(SB); BYTE $IdtNP		/* #NP Segment-Not-Present */
	CALL _acintre<>(SB); BYTE $IdtSS		/* #SS Stack */
	CALL _acintre<>(SB); BYTE $IdtGP		/* #GP General-Protection */
	CALL _acintre<>(SB); BYTE $IdtPF		/* #PF Page-Fault */
	CALL _acintrp<>(SB); BYTE $Idt0F		/* reserved */
	CALL _acintrp<>(SB); BYTE $IdtMF		/* #MF x87 FPE-Pending */
	CALL _acintre<>(SB); BYTE $IdtAC		/* #AC Alignment-Check */
	CALL _acintrp<>(SB); BYTE $IdtMC		/* #MC Machine-Check */
	CALL _acintrp<>(SB); BYTE $IdtXF		/* #XF SIMD Floating-Point */
	CALL _acintrp<>(SB); BYTE $0x14		/* reserved */
	CALL _acintrp<>(SB); BYTE $0x15		/* reserved */
	CALL _acintrp<>(SB); BYTE $0x16		/* reserved */
	CALL _acintrp<>(SB); BYTE $0x17		/* reserved */
	CALL _acintrp<>(SB); BYTE $0x18		/* reserved */
	CALL _acintrp<>(SB); BYTE $0x19		/* reserved */
	CALL _acintrp<>(SB); BYTE $0x1a		/* reserved */
	CALL _acintrp<>(SB); BYTE $0x1b		/* reserved */
	CALL _acintrp<>(SB); BYTE $0x1c		/* reserved */
	CALL _acintrp<>(SB); BYTE $0x1d		/* reserved */
	CALL _acintrp<>(SB); BYTE $0x1e		/* reserved */
	CALL _acintrp<>(SB); BYTE $0x1f		/* reserved */
	CALL _acintrp<>(SB); BYTE $0x20
	CALL _acintrp<>(SB); BYTE $0x21
	CALL _acintrp<>(SB); BYTE $0x22
	CALL _acintrp<>(SB); BYTE $0x23
	CALL _acintrp<>(SB); BYTE $0x24
	CALL _acintrp<>(SB); BYTE $0x25
	CALL _acintrp<>(SB); BYTE $0x26
	CALL _acintrp<>(SB); BYTE $0x27
	CALL _acintrp<>(SB); BYTE $0x28
	CALL _acintrp<>(SB); BYTE $0x29
	CALL _acintrp<>(SB); BYTE $0x2a
	CALL _acintrp<>(SB); BYTE $0x2b
	CALL _acintrp<>(SB); BYTE $0x2c
	CALL _acintrp<>(SB); BYTE $0x2d
	CALL _acintrp<>(SB); BYTE $0x2e
	CALL _acintrp<>(SB); BYTE $0x2f
	CALL _acintrp<>(SB); BYTE $0x30
	CALL _acintrp<>(SB); BYTE $0x31
	CALL _acintrp<>(SB); BYTE $0x32
	CALL _acintrp<>(SB); BYTE $0x33
	CALL _acintrp<>(SB); BYTE $0x34
	CALL _acintrp<>(SB); BYTE $0x35
	CALL _acintrp<>(SB); BYTE $0x36
	CALL _acintrp<>(SB); BYTE $0x37
	CALL _acintrp<>(SB); BYTE $0x38
	CALL _acintrp<>(SB); BYTE $0x39
	CALL _acintrp<>(SB); BYTE $0x3a
	CALL _acintrp<>(SB); BYTE $0x3b
	CALL _acintrp<>(SB); BYTE $0x3c
	CALL _acintrp<>(SB); BYTE $0x3d
	CALL _acintrp<>(SB); BYTE $0x3e
	CALL _acintrp<>(SB); BYTE $0x3f
	CALL _acintrp<>(SB); BYTE $0x40
	CALL _acintrp<>(SB); BYTE $0x41
	CALL _acintrp<>(SB); BYTE $0x42
	CALL _acintrp<>(SB); BYTE $0x43
	CALL _acintrp<>(SB); BYTE $0x44
	CALL _acintrp<>(SB); BYTE $0x45
	CALL _acintrp<>(SB); BYTE $0x46
	CALL _acintrp<>(SB); BYTE $0x47
	CALL _acintrp<>(SB); BYTE $0x48
	CALL _acintrp<>(SB); BYTE $0x49
	CALL _acintrp<>(SB); BYTE $0x4a
	CALL _acintrp<>(SB); BYTE $0x4b
	CALL _acintrp<>(SB); BYTE $0x4c
	CALL _acintrp<>(SB); BYTE $0x4d
	CALL _acintrp<>(SB); BYTE $0x4e
	CALL _acintrp<>(SB); BYTE $0x4f
	CALL _acintrp<>(SB); BYTE $0x50
	CALL _acintrp<>(SB); BYTE $0x51
	CALL _acintrp<>(SB); BYTE $0x52
	CALL _acintrp<>(SB); BYTE $0x53
	CALL _acintrp<>(SB); BYTE $0x54
	CALL _acintrp<>(SB); BYTE $0x55
	CALL _acintrp<>(SB); BYTE $0x56
	CALL _acintrp<>(SB); BYTE $0x57
	CALL _acintrp<>(SB); BYTE $0x58
	CALL _acintrp<>(SB); BYTE $0x59
	CALL _acintrp<>(SB); BYTE $0x5a
	CALL _acintrp<>(SB); BYTE $0x5b
	CALL _acintrp<>(SB); BYTE $0x5c
	CALL _acintrp<>(SB); BYTE $0x5d
	CALL _acintrp<>(SB); BYTE $0x5e
	CALL _acintrp<>(SB); BYTE $0x5f
	CALL _acintrp<>(SB); BYTE $0x60
	CALL _acintrp<>(SB); BYTE $0x61
	CALL _acintrp<>(SB); BYTE $0x62
	CALL _acintrp<>(SB); BYTE $0x63
	CALL _acintrp<>(SB); BYTE $0x64
	CALL _acintrp<>(SB); BYTE $0x65
	CALL _acintrp<>(SB); BYTE $0x66
	CALL _acintrp<>(SB); BYTE $0x67
	CALL _acintrp<>(SB); BYTE $0x68
	CALL _acintrp<>(SB); BYTE $0x69
	CALL _acintrp<>(SB); BYTE $0x6a
	CALL _acintrp<>(SB); BYTE $0x6b
	CALL _acintrp<>(SB); BYTE $0x6c
	CALL _acintrp<>(SB); BYTE $0x6d
	CALL _acintrp<>(SB); BYTE $0x6e
	CALL _acintrp<>(SB); BYTE $0x6f
	CALL _acintrp<>(SB); BYTE $0x70
	CALL _acintrp<>(SB); BYTE $0x71
	CALL _acintrp<>(SB); BYTE $0x72
	CALL _acintrp<>(SB); BYTE $0x73
	CALL _acintrp<>(SB); BYTE $0x74
	CALL _acintrp<>(SB); BYTE $0x75
	CALL _acintrp<>(SB); BYTE $0x76
	CALL _acintrp<>(SB); BYTE $0x77
	CALL _acintrp<>(SB); BYTE $0x78
	CALL _acintrp<>(SB); BYTE $0x79
	CALL _acintrp<>(SB); BYTE $0x7a
	CALL _acintrp<>(SB); BYTE $0x7b
	CALL _acintrp<>(SB); BYTE $0x7c
	CALL _acintrp<>(SB); BYTE $0x7d
	CALL _acintrp<>(SB); BYTE $0x7e
	CALL _acintrp<>(SB); BYTE $0x7f
	CALL _acintrp<>(SB); BYTE $0x80
	CALL _acintrp<>(SB); BYTE $0x81
	CALL _acintrp<>(SB); BYTE $0x82
	CALL _acintrp<>(SB); BYTE $0x83
	CALL _acintrp<>(SB); BYTE $0x84
	CALL _acintrp<>(SB); BYTE $0x85
	CALL _acintrp<>(SB); BYTE $0x86
	CALL _acintrp<>(SB); BYTE $0x87
	CALL _acintrp<>(SB); BYTE $0x88
	CALL _acintrp<>(SB); BYTE $0x89
	CALL _acintrp<>(SB); BYTE $0x8a
	CALL _acintrp<>(SB); BYTE $0x8b
	CALL _acintrp<>(SB); BYTE $0x8c
	CALL _acintrp<>(SB); BYTE $0x8d
	CALL _acintrp<>(SB); BYTE $0x8e
	CALL _acintrp<>(SB); BYTE $0x8f
	CALL _acintrp<>(SB); BYTE $0x90
	CALL _acintrp<>(SB); BYTE $0x91
	CALL _acintrp<>(SB); BYTE $0x92
	CALL _acintrp<>(SB); BYTE $0x93
	CALL _acintrp<>(SB); BYTE $0x94
	CALL _acintrp<>(SB); BYTE $0x95
	CALL _acintrp<>(SB); BYTE $0x96
	CALL _acintrp<>(SB); BYTE $0x97
	CALL _acintrp<>(SB); BYTE $0x98
	CALL _acintrp<>(SB); BYTE $0x99
	CALL _acintrp<>(SB); BYTE $0x9a
	CALL _acintrp<>(SB); BYTE $0x9b
	CALL _acintrp<>(SB); BYTE $0x9c
	CALL _acintrp<>(SB); BYTE $0x9d
	CALL _acintrp<>(SB); BYTE $0x9e
	CALL _acintrp<>(SB); BYTE $0x9f
	CALL _acintrp<>(SB); BYTE $0xa0
	CALL _acintrp<>(SB); BYTE $0xa1
	CALL _acintrp<>(SB); BYTE $0xa2
	CALL _acintrp<>(SB); BYTE $0xa3
	CALL _acintrp<>(SB); BYTE $0xa4
	CALL _acintrp<>(SB); BYTE $0xa5
	CALL _acintrp<>(SB); BYTE $0xa6
	CALL _acintrp<>(SB); BYTE $0xa7
	CALL _acintrp<>(SB); BYTE $0xa8
	CALL _acintrp<>(SB); BYTE $0xa9
	CALL _acintrp<>(SB); BYTE $0xaa
	CALL _acintrp<>(SB); BYTE $0xab
	CALL _acintrp<>(SB); BYTE $0xac
	CALL _acintrp<>(SB); BYTE $0xad
	CALL _acintrp<>(SB); BYTE $0xae
	CALL _acintrp<>(SB); BYTE $0xaf
	CALL _acintrp<>(SB); BYTE $0xb0
	CALL _acintrp<>(SB); BYTE $0xb1
	CALL _acintrp<>(SB); BYTE $0xb2
	CALL _acintrp<>(SB); BYTE $0xb3
	CALL _acintrp<>(SB); BYTE $0xb4
	CALL _acintrp<>(SB); BYTE $0xb5
	CALL _acintrp<>(SB); BYTE $0xb6
	CALL _acintrp<>(SB); BYTE $0xb7
	CALL _acintrp<>(SB); BYTE $0xb8
	CALL _acintrp<>(SB); BYTE $0xb9
	CALL _acintrp<>(SB); BYTE $0xba
	CALL _acintrp<>(SB); BYTE $0xbb
	CALL _acintrp<>(SB); BYTE $0xbc
	CALL _acintrp<>(SB); BYTE $0xbd
	CALL _acintrp<>(SB); BYTE $0xbe
	CALL _acintrp<>(SB); BYTE $0xbf
	CALL _acintrp<>(SB); BYTE $0xc0
	CALL _acintrp<>(SB); BYTE $0xc1
	CALL _acintrp<>(SB); BYTE $0xc2
	CALL _acintrp<>(SB); BYTE $0xc3
	CALL _acintrp<>(SB); BYTE $0xc4
	CALL _acintrp<>(SB); BYTE $0xc5
	CALL _acintrp<>(SB); BYTE $0xc6
	CALL _acintrp<>(SB); BYTE $0xc7
	CALL _acintrp<>(SB); BYTE $0xc8
	CALL _acintrp<>(SB); BYTE $0xc9
	CALL _acintrp<>(SB); BYTE $0xca
	CALL _acintrp<>(SB); BYTE $0xcb
	CALL _acintrp<>(SB); BYTE $0xcc
	CALL _acintrp<>(SB); BYTE $0xce
	CALL _acintrp<>(SB); BYTE $0xce
	CALL _acintrp<>(SB); BYTE $0xcf
	CALL _acintrp<>(SB); BYTE $0xd0
	CALL _acintrp<>(SB); BYTE $0xd1
	CALL _acintrp<>(SB); BYTE $0xd2
	CALL _acintrp<>(SB); BYTE $0xd3
	CALL _acintrp<>(SB); BYTE $0xd4
	CALL _acintrp<>(SB); BYTE $0xd5
	CALL _acintrp<>(SB); BYTE $0xd6
	CALL _acintrp<>(SB); BYTE $0xd7
	CALL _acintrp<>(SB); BYTE $0xd8
	CALL _acintrp<>(SB); BYTE $0xd9
	CALL _acintrp<>(SB); BYTE $0xda
	CALL _acintrp<>(SB); BYTE $0xdb
	CALL _acintrp<>(SB); BYTE $0xdc
	CALL _acintrp<>(SB); BYTE $0xdd
	CALL _acintrp<>(SB); BYTE $0xde
	CALL _acintrp<>(SB); BYTE $0xdf
	CALL _acintrp<>(SB); BYTE $0xe0
	CALL _acintrp<>(SB); BYTE $0xe1
	CALL _acintrp<>(SB); BYTE $0xe2
	CALL _acintrp<>(SB); BYTE $0xe3
	CALL _acintrp<>(SB); BYTE $0xe4
	CALL _acintrp<>(SB); BYTE $0xe5
	CALL _acintrp<>(SB); BYTE $0xe6
	CALL _acintrp<>(SB); BYTE $0xe7
	CALL _acintrp<>(SB); BYTE $0xe8
	CALL _acintrp<>(SB); BYTE $0xe9
	CALL _acintrp<>(SB); BYTE $0xea
	CALL _acintrp<>(SB); BYTE $0xeb
	CALL _acintrp<>(SB); BYTE $0xec
	CALL _acintrp<>(SB); BYTE $0xed
	CALL _acintrp<>(SB); BYTE $0xee
	CALL _acintrp<>(SB); BYTE $0xef
	CALL _acintrp<>(SB); BYTE $0xf0
	CALL _acintrp<>(SB); BYTE $0xf1
	CALL _acintrp<>(SB); BYTE $0xf2
	CALL _acintrp<>(SB); BYTE $0xf3
	CALL _acintrp<>(SB); BYTE $0xf4
	CALL _acintrp<>(SB); BYTE $0xf5
	CALL _acintrp<>(SB); BYTE $0xf6
	CALL _acintrp<>(SB); BYTE $0xf7
	CALL _acintrp<>(SB); BYTE $0xf8
	CALL _acintrp<>(SB); BYTE $0xf9
	CALL _acintrp<>(SB); BYTE $0xfa
	CALL _acintrp<>(SB); BYTE $0xfb
	CALL _acintrp<>(SB); BYTE $0xfc
	CALL _acintrp<>(SB); BYTE $0xfd
	CALL _acintrp<>(SB); BYTE $0xfe
	CALL _acintrp<>(SB); BYTE $0xff
