; K6 系 SYSCALL/SYSRET 命令のテストプログラムです。(LEMM v2.12a 以降専用)

		.586p

CR		equ	00Dh
LF		equ	00Ah
syscall		equ	<db 00Fh,005h>
sysret		equ	<db 00Fh,007h>

movflat		macro	a, b, c
		mov	a, b
		lea	a, [ a+a ]
		lea	a, [ a*8+c ]
		endm

code16		segment	use16
		assume	cs: code16
start:
	.repeat

		pushfd
		cli
		pushfd
		pop	eax
		bts	eax, 21
		push	eax
		popfd
		pushfd
		pop	eax
		popfd
		bt	eax, 21
		.break.if (!carry?)

		xor	eax, eax
		xor	ebx, ebx
		xor	ecx, ecx
		xor	edx, edx
		cpuid
		.break.if (ebx != 068747541h)	; "Auth"
		.break.if (edx != 069746E65h)	; "enti"
		.break.if (ecx != 0444D4163h)	; "cAMD"
comment`
		mov	eax, 1
		xor	edx, edx
		cpuid
		and	ax, 00FF0h
		.break.if (ax < 00580h)
`
		mov	eax, 080000001h
		xor	edx, edx
		cpuid
		.break.if (!(dh & 1000b))

		mov	ecx, 0C0000080h
		rdmsr
		bts	eax, 0
		wrmsr

		mov	ecx, 0C0000081h
		movflat	eax, code32, start_syscall
		mov	edx, 0009B0088h
		wrmsr

		movzx	esp, sp
		movflat	ebp, ss, esp
		stc
		syscall

	.until (1)

		mov	ax, 04CFFh
		int	021h

code16		ends

code32		segment	use32
		assume	cs: code32
start_syscall:
start_sysret:
		mov	esp, ebp
		mov	eax, ss
		mov	ds, ax
		mov	es, ax
		mov	fs, ax
		mov	gs, ax

		sti

		.if (carry?)
			call	putstring32
			db	"hello, syscall world", CR, LF, 0

			movflat	ecx, code32, start_sysret
			mov	ebp, esp
			clc
			sysret
		.endif

		call	putstring32
		db	"hello, sysret world", CR, LF, 0

		mov	ax, 04C00h
		int	021h

putstring32	proc	near

		pop	esi
		cld
		.while (1)
			lodsb
			.break.if !(al & al)
			int	029h
		.endw
		jmp	esi

putstring32	endp

code32		ends

stack		segment	stack

		db	4096 dup(?)

stack		ends

		end	start