xref: /freebsd/stand/i386/btx/btx/btx.S (revision b3e76948)
1ca987d46SWarner Losh/*
2ca987d46SWarner Losh * Copyright (c) 1998 Robert Nordier
3ca987d46SWarner Losh * All rights reserved.
4ca987d46SWarner Losh *
5ca987d46SWarner Losh * Redistribution and use in source and binary forms are freely
6ca987d46SWarner Losh * permitted provided that the above copyright notice and this
7ca987d46SWarner Losh * paragraph and the following disclaimer are duplicated in all
8ca987d46SWarner Losh * such forms.
9ca987d46SWarner Losh *
10ca987d46SWarner Losh * This software is provided "AS IS" and without any express or
11ca987d46SWarner Losh * implied warranties, including, without limitation, the implied
12ca987d46SWarner Losh * warranties of merchantability and fitness for a particular
13ca987d46SWarner Losh * purpose.
14ca987d46SWarner Losh */
15ca987d46SWarner Losh
16ca987d46SWarner Losh#include <bootargs.h>
17ca987d46SWarner Losh
18ca987d46SWarner Losh/*
19ca987d46SWarner Losh * Memory layout.
20ca987d46SWarner Losh */
21ca987d46SWarner Losh		.set MEM_BTX,0x1000		# Start of BTX memory
22ca987d46SWarner Losh		.set MEM_ESP0,0x1800		# Supervisor stack
23ca987d46SWarner Losh		.set MEM_BUF,0x1800		# Scratch buffer
24ca987d46SWarner Losh		.set MEM_ESPR,0x5e00		# Real mode stack
25ca987d46SWarner Losh		.set MEM_IDT,0x5e00		# IDT
26ca987d46SWarner Losh		.set MEM_TSS,0x5f98		# TSS
27ca987d46SWarner Losh		.set MEM_MAP,0x6000		# I/O bit map
28ca987d46SWarner Losh		.set MEM_TSS_END,0x7fff		# End of TSS
29ca987d46SWarner Losh		.set MEM_ORG,0x9000		# BTX code
30ca987d46SWarner Losh		.set MEM_USR,0xa000		# Start of user memory
31ca987d46SWarner Losh/*
32ca987d46SWarner Losh * Paging control.
33ca987d46SWarner Losh */
34ca987d46SWarner Losh		.set PAG_SIZ,0x1000		# Page size
35ca987d46SWarner Losh		.set PAG_CNT,0x1000		# Pages to map
36ca987d46SWarner Losh/*
37ca987d46SWarner Losh * Fields in %eflags.
38ca987d46SWarner Losh */
39ca987d46SWarner Losh		.set PSL_RESERVED_DEFAULT,0x00000002
40ca987d46SWarner Losh		.set PSL_T,0x00000100		# Trap flag
41ca987d46SWarner Losh		.set PSL_I,0x00000200		# Interrupt enable flag
42ca987d46SWarner Losh		.set PSL_D,0x00000400		# String instruction direction
43ca987d46SWarner Losh		.set PSL_NT,0x00004000		# Nested task flag
44ca987d46SWarner Losh		.set PSL_VM,0x00020000		# Virtual 8086 mode flag
45ca987d46SWarner Losh		.set PSL_AC,0x00040000		# Alignment check flag
46ca987d46SWarner Losh/*
47ca987d46SWarner Losh * Segment selectors.
48ca987d46SWarner Losh */
49ca987d46SWarner Losh		.set SEL_SCODE,0x8		# Supervisor code
50ca987d46SWarner Losh		.set SEL_SDATA,0x10		# Supervisor data
51ca987d46SWarner Losh		.set SEL_RCODE,0x18		# Real mode code
52ca987d46SWarner Losh		.set SEL_RDATA,0x20		# Real mode data
53ca987d46SWarner Losh		.set SEL_UCODE,0x28|3		# User code
54ca987d46SWarner Losh		.set SEL_UDATA,0x30|3		# User data
55ca987d46SWarner Losh		.set SEL_TSS,0x38		# TSS
56ca987d46SWarner Losh/*
57ca987d46SWarner Losh * Task state segment fields.
58ca987d46SWarner Losh */
59ca987d46SWarner Losh		.set TSS_ESP0,0x4		# PL 0 ESP
60ca987d46SWarner Losh		.set TSS_SS0,0x8		# PL 0 SS
61ca987d46SWarner Losh		.set TSS_MAP,0x66		# I/O bit map base
62ca987d46SWarner Losh/*
63ca987d46SWarner Losh * System calls.
64ca987d46SWarner Losh */
65ca987d46SWarner Losh		.set SYS_EXIT,0x0		# Exit
66ca987d46SWarner Losh		.set SYS_EXEC,0x1		# Exec
67ca987d46SWarner Losh/*
68ca987d46SWarner Losh * Fields in V86 interface structure.
69ca987d46SWarner Losh */
70ca987d46SWarner Losh		.set V86_CTL,0x0		# Control flags
71ca987d46SWarner Losh		.set V86_ADDR,0x4		# Int number/address
72ca987d46SWarner Losh		.set V86_ES,0x8			# V86 ES
73ca987d46SWarner Losh		.set V86_DS,0xc			# V86 DS
74ca987d46SWarner Losh		.set V86_FS,0x10		# V86 FS
75ca987d46SWarner Losh		.set V86_GS,0x14		# V86 GS
76ca987d46SWarner Losh/*
77ca987d46SWarner Losh * V86 control flags.
78ca987d46SWarner Losh */
79ca987d46SWarner Losh		.set V86F_ADDR,0x10000		# Segment:offset address
80ca987d46SWarner Losh		.set V86F_CALLF,0x20000		# Emulate far call
81ca987d46SWarner Losh		.set V86F_FLAGS,0x40000		# Return flags
82ca987d46SWarner Losh/*
83ca987d46SWarner Losh * Dump format control bytes.
84ca987d46SWarner Losh */
85ca987d46SWarner Losh		.set DMP_X16,0x1		# Word
86ca987d46SWarner Losh		.set DMP_X32,0x2		# Long
87ca987d46SWarner Losh		.set DMP_MEM,0x4		# Memory
88ca987d46SWarner Losh		.set DMP_EOL,0x8		# End of line
89ca987d46SWarner Losh/*
90ca987d46SWarner Losh * Screen defaults and assumptions.
91ca987d46SWarner Losh */
92ca987d46SWarner Losh		.set SCR_MAT,0x7		# Mode/attribute
93ca987d46SWarner Losh		.set SCR_COL,0x50		# Columns per row
94ca987d46SWarner Losh		.set SCR_ROW,0x19		# Rows per screen
95ca987d46SWarner Losh/*
96ca987d46SWarner Losh * BIOS Data Area locations.
97ca987d46SWarner Losh */
98ca987d46SWarner Losh		.set BDA_MEM,0x413		# Free memory
99ca987d46SWarner Losh		.set BDA_SCR,0x449		# Video mode
100ca987d46SWarner Losh		.set BDA_POS,0x450		# Cursor position
101ca987d46SWarner Losh		.set BDA_BOOT,0x472		# Boot howto flag
102ca987d46SWarner Losh/*
103ca987d46SWarner Losh * Derivations, for brevity.
104ca987d46SWarner Losh */
105ca987d46SWarner Losh		.set _ESP0H,MEM_ESP0>>0x8	# Byte 1 of ESP0
106ca987d46SWarner Losh		.set _TSSIO,MEM_MAP-MEM_TSS	# TSS I/O base
107ca987d46SWarner Losh		.set _TSSLM,MEM_TSS_END-MEM_TSS	# TSS limit
108ca987d46SWarner Losh		.set _IDTLM,MEM_TSS-MEM_IDT-1	# IDT limit
109ca987d46SWarner Losh/*
110ca987d46SWarner Losh * Code segment.
111ca987d46SWarner Losh */
112ca987d46SWarner Losh		.globl start
113ca987d46SWarner Losh		.code16
114ca987d46SWarner Loshstart:						# Start of code
115ca987d46SWarner Losh/*
116ca987d46SWarner Losh * BTX header.
117ca987d46SWarner Losh */
118ca987d46SWarner Loshbtx_hdr:	.byte 0xeb			# Machine ID
119ca987d46SWarner Losh		.byte 0xe			# Header size
120ca987d46SWarner Losh		.ascii "BTX"			# Magic
121ca987d46SWarner Losh		.byte 0x1			# Major version
122ca987d46SWarner Losh		.byte 0x2			# Minor version
123ca987d46SWarner Losh		.byte BTX_FLAGS			# Flags
124ca987d46SWarner Losh		.word PAG_CNT-MEM_ORG>>0xc	# Paging control
125ca987d46SWarner Losh		.word break-start		# Text size
126ca987d46SWarner Losh		.long 0x0			# Entry address
127ca987d46SWarner Losh/*
128ca987d46SWarner Losh * Initialization routine.
129ca987d46SWarner Losh */
130ca987d46SWarner Loshinit:		cli				# Disable interrupts
131ca987d46SWarner Losh		xor %ax,%ax			# Zero/segment
132ca987d46SWarner Losh		mov %ax,%ss			# Set up
133ca987d46SWarner Losh		mov $MEM_ESP0,%sp		#  stack
134ca987d46SWarner Losh		mov %ax,%es			# Address
135ca987d46SWarner Losh		mov %ax,%ds			#  data
136ca987d46SWarner Losh		pushl $0x2			# Clear
137ca987d46SWarner Losh		popfl				#  flags
138ca987d46SWarner Losh/*
139ca987d46SWarner Losh * Initialize memory.
140ca987d46SWarner Losh */
141ca987d46SWarner Losh		mov $MEM_IDT,%di		# Memory to initialize
142ca987d46SWarner Losh		mov $(MEM_ORG-MEM_IDT)/2,%cx	# Words to zero
143ca987d46SWarner Losh		rep				# Zero-fill
144ca987d46SWarner Losh		stosw				#  memory
145ca987d46SWarner Losh/*
146ca987d46SWarner Losh * Update real mode IDT for reflecting hardware interrupts.
147ca987d46SWarner Losh */
148ca987d46SWarner Losh		mov $intr20,%bx			# Address first handler
149ca987d46SWarner Losh		mov $0x10,%cx			# Number of handlers
150ca987d46SWarner Losh		mov $0x20*4,%di			# First real mode IDT entry
151ca987d46SWarner Loshinit.0:		mov %bx,(%di)			# Store IP
152ca987d46SWarner Losh		inc %di				# Address next
153ca987d46SWarner Losh		inc %di				#  entry
154ca987d46SWarner Losh		stosw				# Store CS
155ca987d46SWarner Losh		add $4,%bx			# Next handler
156ca987d46SWarner Losh		loop init.0			# Next IRQ
157ca987d46SWarner Losh/*
158ca987d46SWarner Losh * Create IDT.
159ca987d46SWarner Losh */
160ca987d46SWarner Losh		mov $MEM_IDT,%di
161ca987d46SWarner Losh		mov $idtctl,%si			# Control string
162ca987d46SWarner Loshinit.1: 	lodsb				# Get entry
163ca987d46SWarner Losh		cbw				#  count
164ca987d46SWarner Losh		xchg %ax,%cx			#  as word
165ca987d46SWarner Losh		jcxz init.4			# If done
166ca987d46SWarner Losh		lodsb				# Get segment
167ca987d46SWarner Losh		xchg %ax,%dx	 		#  P:DPL:type
168ca987d46SWarner Losh		lodsw				# Get control
169ca987d46SWarner Losh		xchg %ax,%bx			#  set
170ca987d46SWarner Losh		lodsw				# Get handler offset
171ca987d46SWarner Losh		mov $SEL_SCODE,%dh		# Segment selector
172ca987d46SWarner Loshinit.2: 	shr %bx				# Handle this int?
173ca987d46SWarner Losh		jnc init.3			# No
174ca987d46SWarner Losh		mov %ax,(%di)			# Set handler offset
175ca987d46SWarner Losh		mov %dh,0x2(%di)		#  and selector
176ca987d46SWarner Losh		mov %dl,0x5(%di)		# Set P:DPL:type
177ca987d46SWarner Losh		add $0x4,%ax			# Next handler
178ca987d46SWarner Loshinit.3: 	lea 0x8(%di),%di		# Next entry
179ca987d46SWarner Losh		loop init.2			# Till set done
180ca987d46SWarner Losh		jmp init.1			# Continue
181ca987d46SWarner Losh/*
182ca987d46SWarner Losh * Initialize TSS.
183ca987d46SWarner Losh */
184ca987d46SWarner Loshinit.4: 	movb $_ESP0H,TSS_ESP0+1(%di)	# Set ESP0
185ca987d46SWarner Losh		movb $SEL_SDATA,TSS_SS0(%di)	# Set SS0
186ca987d46SWarner Losh		movb $_TSSIO,TSS_MAP(%di)	# Set I/O bit map base
187ca987d46SWarner Losh/*
188ca987d46SWarner Losh * Bring up the system.
189ca987d46SWarner Losh */
190ca987d46SWarner Losh		mov $0x2820,%bx			# Set protected mode
191ca987d46SWarner Losh		callw setpic			#  IRQ offsets
192ca987d46SWarner Losh		lidt idtdesc	 		# Set IDT
193ca987d46SWarner Losh		lgdt gdtdesc	 		# Set GDT
194ca987d46SWarner Losh		mov %cr0,%eax			# Switch to protected
195ca987d46SWarner Losh		inc %ax				#  mode
196ca987d46SWarner Losh		mov %eax,%cr0			#
197ca987d46SWarner Losh		ljmp $SEL_SCODE,$init.8		# To 32-bit code
198ca987d46SWarner Losh		.code32
199ca987d46SWarner Loshinit.8: 	xorl %ecx,%ecx			# Zero
200ca987d46SWarner Losh		movb $SEL_SDATA,%cl		# To 32-bit
201ca987d46SWarner Losh		movw %cx,%ss			#  stack
202ca987d46SWarner Losh/*
203ca987d46SWarner Losh * Launch user task.
204ca987d46SWarner Losh */
205ca987d46SWarner Losh		movb $SEL_TSS,%cl		# Set task
206ca987d46SWarner Losh		ltr %cx				#  register
207ca987d46SWarner Losh		movl $MEM_USR,%edx		# User base address
208ca987d46SWarner Losh		movzwl %ss:BDA_MEM,%eax 	# Get free memory
209ca987d46SWarner Losh		shll $0xa,%eax			# To bytes
210ca987d46SWarner Losh		subl $ARGSPACE,%eax		# Less arg space
211ca987d46SWarner Losh		subl %edx,%eax			# Less base
212ca987d46SWarner Losh		movb $SEL_UDATA,%cl		# User data selector
213ca987d46SWarner Losh		pushl %ecx			# Set SS
214ca987d46SWarner Losh		pushl %eax			# Set ESP
215ca987d46SWarner Losh		push $0x202			# Set flags (IF set)
216ca987d46SWarner Losh		push $SEL_UCODE			# Set CS
217ca987d46SWarner Losh		pushl btx_hdr+0xc		# Set EIP
218ca987d46SWarner Losh		pushl %ecx			# Set GS
219ca987d46SWarner Losh		pushl %ecx			# Set FS
220ca987d46SWarner Losh		pushl %ecx			# Set DS
221ca987d46SWarner Losh		pushl %ecx			# Set ES
222ca987d46SWarner Losh		pushl %edx			# Set EAX
223ca987d46SWarner Losh		movb $0x7,%cl			# Set remaining
224ca987d46SWarner Loshinit.9:		push $0x0			#  general
225ca987d46SWarner Losh		loop init.9			#  registers
226ca987d46SWarner Losh#ifdef BTX_SERIAL
227ca987d46SWarner Losh		call sio_init			# setup the serial console
228ca987d46SWarner Losh#endif
229ca987d46SWarner Losh		popa				#  and initialize
230ca987d46SWarner Losh		popl %es			# Initialize
231ca987d46SWarner Losh		popl %ds			#  user
232ca987d46SWarner Losh		popl %fs			#  segment
233ca987d46SWarner Losh		popl %gs			#  registers
234ca987d46SWarner Losh		iret				# To user mode
235ca987d46SWarner Losh/*
236ca987d46SWarner Losh * Exit routine.
237ca987d46SWarner Losh */
238ca987d46SWarner Loshexit:		cli				# Disable interrupts
239ca987d46SWarner Losh		movl $MEM_ESP0,%esp		# Clear stack
240ca987d46SWarner Losh/*
241ca987d46SWarner Losh * Turn off paging.
242ca987d46SWarner Losh */
243ca987d46SWarner Losh		movl %cr0,%eax			# Get CR0
244ca987d46SWarner Losh		andl $~0x80000000,%eax		# Disable
245ca987d46SWarner Losh		movl %eax,%cr0			#  paging
246ca987d46SWarner Losh		xorl %ecx,%ecx			# Zero
247ca987d46SWarner Losh		movl %ecx,%cr3			# Flush TLB
248ca987d46SWarner Losh/*
249ca987d46SWarner Losh * Restore the GDT in case we caught a kernel trap.
250ca987d46SWarner Losh */
251ca987d46SWarner Losh		lgdt %cs:gdtdesc		# Set GDT
252ca987d46SWarner Losh/*
253ca987d46SWarner Losh * To 16 bits.
254ca987d46SWarner Losh */
255ca987d46SWarner Losh		ljmpw $SEL_RCODE,$exit.1	# Reload CS
256ca987d46SWarner Losh		.code16
257ca987d46SWarner Loshexit.1: 	mov $SEL_RDATA,%cl		# 16-bit selector
258ca987d46SWarner Losh		mov %cx,%ss			# Reload SS
259ca987d46SWarner Losh		mov %cx,%ds			# Load
260ca987d46SWarner Losh		mov %cx,%es			#  remaining
261ca987d46SWarner Losh		mov %cx,%fs			#  segment
262ca987d46SWarner Losh		mov %cx,%gs			#  registers
263ca987d46SWarner Losh/*
264ca987d46SWarner Losh * To real-address mode.
265ca987d46SWarner Losh */
266ca987d46SWarner Losh		dec %ax				# Switch to
267ca987d46SWarner Losh		mov %eax,%cr0			#  real mode
268ca987d46SWarner Losh		ljmp $0x0,$exit.2		# Reload CS
269ca987d46SWarner Loshexit.2: 	xor %ax,%ax			# Real mode segment
270ca987d46SWarner Losh		mov %ax,%ss			# Reload SS
271ca987d46SWarner Losh		mov %ax,%ds			# Address data
272ca987d46SWarner Losh		mov $0x7008,%bx			# Set real mode
273ca987d46SWarner Losh		callw setpic			#  IRQ offsets
274ca987d46SWarner Losh		lidt ivtdesc	 		# Set IVT
275ca987d46SWarner Losh/*
276ca987d46SWarner Losh * Reboot or await reset.
277ca987d46SWarner Losh */
278ca987d46SWarner Losh		sti				# Enable interrupts
279ca987d46SWarner Losh		testb $0x1,btx_hdr+0x7		# Reboot?
280ca987d46SWarner Loshexit.3:		jz exit.3			# No
281ca987d46SWarner Losh		movw $0x1234, BDA_BOOT		# Do a warm boot
282ca987d46SWarner Losh		ljmp $0xf000,$0xfff0		# reboot the machine
283ca987d46SWarner Losh/*
284ca987d46SWarner Losh * Set IRQ offsets by reprogramming 8259A PICs.
285ca987d46SWarner Losh */
286ca987d46SWarner Loshsetpic: 	in $0x21,%al			# Save master
287ca987d46SWarner Losh		push %ax			#  IMR
288ca987d46SWarner Losh		in $0xa1,%al			# Save slave
289ca987d46SWarner Losh		push %ax			#  IMR
290ca987d46SWarner Losh		movb $0x11,%al			# ICW1 to
291ca987d46SWarner Losh		outb %al,$0x20			#  master,
292ca987d46SWarner Losh		outb %al,$0xa0			#  slave
293ca987d46SWarner Losh		movb %bl,%al			# ICW2 to
294ca987d46SWarner Losh		outb %al,$0x21			#  master
295ca987d46SWarner Losh		movb %bh,%al			# ICW2 to
296ca987d46SWarner Losh		outb %al,$0xa1			#  slave
297ca987d46SWarner Losh		movb $0x4,%al			# ICW3 to
298ca987d46SWarner Losh		outb %al,$0x21			#  master
299ca987d46SWarner Losh		movb $0x2,%al			# ICW3 to
300ca987d46SWarner Losh		outb %al,$0xa1			#  slave
301ca987d46SWarner Losh		movb $0x1,%al			# ICW4 to
302ca987d46SWarner Losh		outb %al,$0x21			#  master,
303ca987d46SWarner Losh		outb %al,$0xa1			#  slave
304ca987d46SWarner Losh		pop %ax				# Restore slave
305ca987d46SWarner Losh		outb %al,$0xa1			#  IMR
306ca987d46SWarner Losh		pop %ax				# Restore master
307ca987d46SWarner Losh		outb %al,$0x21			#  IMR
308ca987d46SWarner Losh		retw				# To caller
309ca987d46SWarner Losh		.code32
310ca987d46SWarner Losh/*
311ca987d46SWarner Losh * Exception jump table.
312ca987d46SWarner Losh */
313ca987d46SWarner Loshintx00: 	push $0x0			# Int 0x0: #DE
314ca987d46SWarner Losh		jmp ex_noc			# Divide error
315ca987d46SWarner Losh		push $0x1			# Int 0x1: #DB
316ca987d46SWarner Losh		jmp ex_noc			# Debug
317ca987d46SWarner Losh		push $0x3			# Int 0x3: #BP
318ca987d46SWarner Losh		jmp ex_noc			# Breakpoint
319ca987d46SWarner Losh		push $0x4			# Int 0x4: #OF
320ca987d46SWarner Losh		jmp ex_noc			# Overflow
321ca987d46SWarner Losh		push $0x5			# Int 0x5: #BR
322ca987d46SWarner Losh		jmp ex_noc			# BOUND range exceeded
323ca987d46SWarner Losh		push $0x6			# Int 0x6: #UD
324ca987d46SWarner Losh		jmp ex_noc			# Invalid opcode
325ca987d46SWarner Losh		push $0x7			# Int 0x7: #NM
326ca987d46SWarner Losh		jmp ex_noc			# Device not available
327ca987d46SWarner Losh		push $0x8			# Int 0x8: #DF
328ca987d46SWarner Losh		jmp except			# Double fault
329ca987d46SWarner Losh		push $0xa			# Int 0xa: #TS
330ca987d46SWarner Losh		jmp except			# Invalid TSS
331ca987d46SWarner Losh		push $0xb			# Int 0xb: #NP
332ca987d46SWarner Losh		jmp except			# Segment not present
333ca987d46SWarner Losh		push $0xc			# Int 0xc: #SS
334ca987d46SWarner Losh		jmp except			# Stack segment fault
335ca987d46SWarner Losh		push $0xd			# Int 0xd: #GP
336ca987d46SWarner Losh		jmp except			# General protection
337ca987d46SWarner Losh		push $0xe			# Int 0xe: #PF
338ca987d46SWarner Losh		jmp except			# Page fault
339ca987d46SWarner Loshintx10: 	push $0x10			# Int 0x10: #MF
340ca987d46SWarner Losh		jmp ex_noc			# Floating-point error
341ca987d46SWarner Losh/*
342ca987d46SWarner Losh * Save a zero error code.
343ca987d46SWarner Losh */
344ca987d46SWarner Loshex_noc: 	pushl (%esp,1)			# Duplicate int no
345ca987d46SWarner Losh		movb $0x0,0x4(%esp,1)		# Fake error code
346ca987d46SWarner Losh/*
347ca987d46SWarner Losh * Handle exception.
348ca987d46SWarner Losh */
349ca987d46SWarner Loshexcept: 	cld				# String ops inc
350ca987d46SWarner Losh		pushl %ds			# Save
351ca987d46SWarner Losh		pushl %es			#  most
352ca987d46SWarner Losh		pusha				#  registers
353ca987d46SWarner Losh		pushl %gs			# Set GS
354ca987d46SWarner Losh		pushl %fs			# Set FS
355ca987d46SWarner Losh		pushl %ds			# Set DS
356ca987d46SWarner Losh		pushl %es			# Set ES
357ca987d46SWarner Losh		cmpw $SEL_SCODE,0x44(%esp,1)	# Supervisor mode?
358ca987d46SWarner Losh		jne except.1			# No
359ca987d46SWarner Losh		pushl %ss			# Set SS
360ca987d46SWarner Losh		jmp except.2			# Join common code
361ca987d46SWarner Loshexcept.1:	pushl 0x50(%esp,1)		# Set SS
362ca987d46SWarner Loshexcept.2:	pushl 0x50(%esp,1)		# Set ESP
363ca987d46SWarner Losh		push $SEL_SDATA			# Set up
364ca987d46SWarner Losh		popl %ds			#  to
365ca987d46SWarner Losh		pushl %ds			#  address
366ca987d46SWarner Losh		popl %es			#  data
367ca987d46SWarner Losh		movl %esp,%ebx			# Stack frame
368ca987d46SWarner Losh		movl $dmpfmt,%esi		# Dump format string
369ca987d46SWarner Losh		movl $MEM_BUF,%edi		# Buffer
370ca987d46SWarner Losh		pushl %edi			# Dump to
371ca987d46SWarner Losh		call dump			#  buffer
372ca987d46SWarner Losh		popl %esi			#  and
373ca987d46SWarner Losh		call putstr			#  display
374ca987d46SWarner Losh		leal 0x18(%esp,1),%esp		# Discard frame
375ca987d46SWarner Losh		popa				# Restore
376ca987d46SWarner Losh		popl %es			#  registers
377ca987d46SWarner Losh		popl %ds			#  saved
378ca987d46SWarner Losh		cmpb $0x3,(%esp,1)		# Breakpoint?
379ca987d46SWarner Losh		je except.3			# Yes
380ca987d46SWarner Losh		cmpb $0x1,(%esp,1)		# Debug?
381ca987d46SWarner Losh		jne except.2a			# No
382ca987d46SWarner Losh		testl $PSL_T,0x10(%esp,1)	# Trap flag set?
383ca987d46SWarner Losh		jnz except.3			# Yes
384ca987d46SWarner Loshexcept.2a:	jmp exit			# Exit
385ca987d46SWarner Loshexcept.3:	leal 0x8(%esp,1),%esp		# Discard err, int no
386ca987d46SWarner Losh		iret				# From interrupt
387ca987d46SWarner Losh
388ca987d46SWarner Losh/*
389ca987d46SWarner Losh * Reboot the machine by setting the reboot flag and exiting
390ca987d46SWarner Losh */
391ca987d46SWarner Loshreboot:		orb $0x1,btx_hdr+0x7		# Set the reboot flag
392ca987d46SWarner Losh		jmp exit			# Terminate BTX and reboot
393ca987d46SWarner Losh
394ca987d46SWarner Losh/*
395ca987d46SWarner Losh * Protected Mode Hardware interrupt jump table.
396ca987d46SWarner Losh */
397ca987d46SWarner Loshintx20: 	push $0x8			# Int 0x20: IRQ0
398ca987d46SWarner Losh		jmp int_hw			# V86 int 0x8
399ca987d46SWarner Losh		push $0x9			# Int 0x21: IRQ1
400ca987d46SWarner Losh		jmp int_hw			# V86 int 0x9
401ca987d46SWarner Losh		push $0xa			# Int 0x22: IRQ2
402ca987d46SWarner Losh		jmp int_hw			# V86 int 0xa
403ca987d46SWarner Losh		push $0xb			# Int 0x23: IRQ3
404ca987d46SWarner Losh		jmp int_hw			# V86 int 0xb
405ca987d46SWarner Losh		push $0xc			# Int 0x24: IRQ4
406ca987d46SWarner Losh		jmp int_hw			# V86 int 0xc
407ca987d46SWarner Losh		push $0xd			# Int 0x25: IRQ5
408ca987d46SWarner Losh		jmp int_hw			# V86 int 0xd
409ca987d46SWarner Losh		push $0xe			# Int 0x26: IRQ6
410ca987d46SWarner Losh		jmp int_hw			# V86 int 0xe
411ca987d46SWarner Losh		push $0xf			# Int 0x27: IRQ7
412ca987d46SWarner Losh		jmp int_hw			# V86 int 0xf
413ca987d46SWarner Losh		push $0x70			# Int 0x28: IRQ8
414ca987d46SWarner Losh		jmp int_hw			# V86 int 0x70
415ca987d46SWarner Losh		push $0x71			# Int 0x29: IRQ9
416ca987d46SWarner Losh		jmp int_hw			# V86 int 0x71
417ca987d46SWarner Losh		push $0x72			# Int 0x2a: IRQ10
418ca987d46SWarner Losh		jmp int_hw			# V86 int 0x72
419ca987d46SWarner Losh		push $0x73			# Int 0x2b: IRQ11
420ca987d46SWarner Losh		jmp int_hw			# V86 int 0x73
421ca987d46SWarner Losh		push $0x74			# Int 0x2c: IRQ12
422ca987d46SWarner Losh		jmp int_hw			# V86 int 0x74
423ca987d46SWarner Losh		push $0x75			# Int 0x2d: IRQ13
424ca987d46SWarner Losh		jmp int_hw			# V86 int 0x75
425ca987d46SWarner Losh		push $0x76			# Int 0x2e: IRQ14
426ca987d46SWarner Losh		jmp int_hw			# V86 int 0x76
427ca987d46SWarner Losh		push $0x77			# Int 0x2f: IRQ15
428ca987d46SWarner Losh		jmp int_hw			# V86 int 0x77
429ca987d46SWarner Losh
430ca987d46SWarner Losh/*
431ca987d46SWarner Losh * Invoke real mode interrupt/function call from user mode with arguments.
432ca987d46SWarner Losh */
433ca987d46SWarner Loshintx31: 	pushl $-1			# Dummy int no for btx_v86
434ca987d46SWarner Losh/*
435ca987d46SWarner Losh * Invoke real mode interrupt/function call from protected mode.
436ca987d46SWarner Losh *
437ca987d46SWarner Losh * We place a trampoline on the user stack that will return to rret_tramp
438ca987d46SWarner Losh * which will reenter protected mode and then finally return to the user
439ca987d46SWarner Losh * client.
440ca987d46SWarner Losh *
441ca987d46SWarner Losh * Kernel frame %esi points to:		Real mode stack frame at MEM_ESPR:
442ca987d46SWarner Losh *
443ca987d46SWarner Losh * -0x00 user %ss			-0x04 kernel %esp (with full frame)
444ca987d46SWarner Losh * -0x04 user %esp			-0x08 btx_v86 pointer
445ca987d46SWarner Losh * -0x08 user %eflags			-0x0c flags (only used if interrupt)
446ca987d46SWarner Losh * -0x0c user %cs			-0x10 real mode CS:IP return trampoline
447ca987d46SWarner Losh * -0x10 user %eip			-0x12 real mode flags
448ca987d46SWarner Losh * -0x14 int no				-0x16 real mode CS:IP (target)
449ca987d46SWarner Losh * -0x18 %eax
450ca987d46SWarner Losh * -0x1c %ecx
451ca987d46SWarner Losh * -0x20 %edx
452ca987d46SWarner Losh * -0x24 %ebx
453ca987d46SWarner Losh * -0x28 %esp
454ca987d46SWarner Losh * -0x2c %ebp
455ca987d46SWarner Losh * -0x30 %esi
456ca987d46SWarner Losh * -0x34 %edi
457ca987d46SWarner Losh * -0x38 %gs
458ca987d46SWarner Losh * -0x3c %fs
459ca987d46SWarner Losh * -0x40 %ds
460ca987d46SWarner Losh * -0x44 %es
461ca987d46SWarner Losh * -0x48 zero %eax (hardware int only)
462ca987d46SWarner Losh * -0x4c zero %ecx (hardware int only)
463ca987d46SWarner Losh * -0x50 zero %edx (hardware int only)
464ca987d46SWarner Losh * -0x54 zero %ebx (hardware int only)
465ca987d46SWarner Losh * -0x58 zero %esp (hardware int only)
466ca987d46SWarner Losh * -0x5c zero %ebp (hardware int only)
467ca987d46SWarner Losh * -0x60 zero %esi (hardware int only)
468ca987d46SWarner Losh * -0x64 zero %edi (hardware int only)
469ca987d46SWarner Losh * -0x68 zero %gs (hardware int only)
470ca987d46SWarner Losh * -0x6c zero %fs (hardware int only)
471ca987d46SWarner Losh * -0x70 zero %ds (hardware int only)
472ca987d46SWarner Losh * -0x74 zero %es (hardware int only)
473ca987d46SWarner Losh */
474ca987d46SWarner Loshint_hw: 	cld				# String ops inc
475ca987d46SWarner Losh		pusha				# Save gp regs
476ca987d46SWarner Losh		pushl %gs			# Save
477ca987d46SWarner Losh		pushl %fs			#  seg
478ca987d46SWarner Losh		pushl %ds			#  regs
479ca987d46SWarner Losh		pushl %es
480ca987d46SWarner Losh		push $SEL_SDATA			# Set up
481ca987d46SWarner Losh		popl %ds			#  to
482ca987d46SWarner Losh		pushl %ds			#  address
483ca987d46SWarner Losh		popl %es			#  data
484ca987d46SWarner Losh		leal 0x44(%esp,1),%esi		# Base of frame
485ca987d46SWarner Losh		movl %esp,MEM_ESPR-0x04		# Save kernel stack pointer
486ca987d46SWarner Losh		movl -0x14(%esi),%eax		# Get Int no
487ca987d46SWarner Losh		cmpl $-1,%eax			# Hardware interrupt?
488ca987d46SWarner Losh		jne intusr.1			# Yes
489ca987d46SWarner Losh/*
490ca987d46SWarner Losh * v86 calls save the btx_v86 pointer on the real mode stack and read
491ca987d46SWarner Losh * the address and flags from the btx_v86 structure.  For interrupt
492ca987d46SWarner Losh * handler invocations (VM86 INTx requests), disable interrupts,
493ca987d46SWarner Losh * tracing, and alignment checking while the handler runs.
494ca987d46SWarner Losh */
495ca987d46SWarner Losh		movl $MEM_USR,%ebx		# User base
496ca987d46SWarner Losh		movl %ebx,%edx			#  address
497ca987d46SWarner Losh		addl -0x4(%esi),%ebx		# User ESP
498ca987d46SWarner Losh		movl (%ebx),%ebp		# btx_v86 pointer
499ca987d46SWarner Losh		addl %ebp,%edx			# Flatten btx_v86 ptr
500ca987d46SWarner Losh		movl %edx,MEM_ESPR-0x08		# Save btx_v86 ptr
501ca987d46SWarner Losh		movl V86_ADDR(%edx),%eax	# Get int no/address
502ca987d46SWarner Losh		movl V86_CTL(%edx),%edx		# Get control flags
503ca987d46SWarner Losh		movl -0x08(%esi),%ebx		# Save user flags in %ebx
504ca987d46SWarner Losh		testl $V86F_ADDR,%edx		# Segment:offset?
505ca987d46SWarner Losh		jnz intusr.4			# Yes
506ca987d46SWarner Losh		andl $~(PSL_I|PSL_T|PSL_AC),%ebx # Disable interrupts, tracing,
507ca987d46SWarner Losh						#  and alignment checking for
508ca987d46SWarner Losh						#  interrupt handler
509ca987d46SWarner Losh		jmp intusr.3			# Skip hardware interrupt
510ca987d46SWarner Losh/*
511ca987d46SWarner Losh * Hardware interrupts store a NULL btx_v86 pointer and use the
512ca987d46SWarner Losh * address (interrupt number) from the stack with empty flags.  Also,
513ca987d46SWarner Losh * push a dummy frame of zeros onto the stack for all the general
514ca987d46SWarner Losh * purpose and segment registers and clear %eflags.  This gives the
515ca987d46SWarner Losh * hardware interrupt handler a clean slate.
516ca987d46SWarner Losh */
517ca987d46SWarner Loshintusr.1:	xorl %edx,%edx			# Control flags
518ca987d46SWarner Losh		movl %edx,MEM_ESPR-0x08		# NULL btx_v86 ptr
519ca987d46SWarner Losh		movl $12,%ecx			# Frame is 12 dwords
520ca987d46SWarner Loshintusr.2:	pushl $0x0			# Fill frame
521ca987d46SWarner Losh		loop intusr.2			#  with zeros
522ca987d46SWarner Losh		movl $PSL_RESERVED_DEFAULT,%ebx # Set clean %eflags
523ca987d46SWarner Losh/*
524ca987d46SWarner Losh * Look up real mode IDT entry for hardware interrupts and VM86 INTx
525ca987d46SWarner Losh * requests.
526ca987d46SWarner Losh */
527ca987d46SWarner Loshintusr.3:	shll $0x2,%eax			# Scale
528ca987d46SWarner Losh		movl (%eax),%eax		# Load int vector
529ca987d46SWarner Losh		jmp intusr.5			# Skip CALLF test
530ca987d46SWarner Losh/*
531ca987d46SWarner Losh * Panic if V86F_CALLF isn't set with V86F_ADDR.
532ca987d46SWarner Losh */
533ca987d46SWarner Loshintusr.4:	testl $V86F_CALLF,%edx		# Far call?
534ca987d46SWarner Losh		jnz intusr.5			# Ok
535ca987d46SWarner Losh		movl %edx,0x30(%esp,1)		# Place VM86 flags in int no
536ca987d46SWarner Losh		movl $badvm86,%esi		# Display bad
537ca987d46SWarner Losh		call putstr			#  VM86 call
538ca987d46SWarner Losh		popl %es			# Restore
539ca987d46SWarner Losh		popl %ds			#  seg
540ca987d46SWarner Losh		popl %fs			#  regs
541ca987d46SWarner Losh		popl %gs
542ca987d46SWarner Losh		popal				# Restore gp regs
543ca987d46SWarner Losh		jmp ex_noc			# Panic
544ca987d46SWarner Losh/*
545ca987d46SWarner Losh * %eax now holds the segment:offset of the function.
546ca987d46SWarner Losh * %ebx now holds the %eflags to pass to real mode.
547ca987d46SWarner Losh * %edx now holds the V86F_* flags.
548ca987d46SWarner Losh */
549ca987d46SWarner Loshintusr.5:	movw %bx,MEM_ESPR-0x12		# Pass user flags to real mode
550ca987d46SWarner Losh						#  target
551ca987d46SWarner Losh/*
552ca987d46SWarner Losh * If this is a v86 call, copy the seg regs out of the btx_v86 structure.
553ca987d46SWarner Losh */
554ca987d46SWarner Losh		movl MEM_ESPR-0x08,%ecx		# Get btx_v86 ptr
555ca987d46SWarner Losh		jecxz intusr.6			# Skip for hardware ints
556ca987d46SWarner Losh		leal -0x44(%esi),%edi		# %edi => kernel stack seg regs
557ca987d46SWarner Losh		pushl %esi			# Save
558ca987d46SWarner Losh		leal V86_ES(%ecx),%esi		# %esi => btx_v86 seg regs
559ca987d46SWarner Losh		movl $4,%ecx			# Copy seg regs
560ca987d46SWarner Losh		rep				#  from btx_v86
561ca987d46SWarner Losh		movsl				#  to kernel stack
562ca987d46SWarner Losh		popl %esi			# Restore
563ca987d46SWarner Loshintusr.6:	movl -0x08(%esi),%ebx		# Copy user flags to real
564ca987d46SWarner Losh		movl %ebx,MEM_ESPR-0x0c		#  mode return trampoline
565ca987d46SWarner Losh		movl $rret_tramp,%ebx		# Set return trampoline
566ca987d46SWarner Losh		movl %ebx,MEM_ESPR-0x10		#  CS:IP
567ca987d46SWarner Losh		movl %eax,MEM_ESPR-0x16		# Real mode target CS:IP
568ca987d46SWarner Losh		ljmpw $SEL_RCODE,$intusr.7	# Change to 16-bit segment
569ca987d46SWarner Losh		.code16
570ca987d46SWarner Loshintusr.7:	movl %cr0,%eax			# Leave
571ca987d46SWarner Losh		dec %al				#  protected
572ca987d46SWarner Losh		movl %eax,%cr0			#  mode
573ca987d46SWarner Losh		ljmpw $0x0,$intusr.8
574ca987d46SWarner Loshintusr.8:	xorw %ax,%ax			# Reset %ds
575ca987d46SWarner Losh		movw %ax,%ds			#  and
576ca987d46SWarner Losh		movw %ax,%ss			#  %ss
577ca987d46SWarner Losh		lidt ivtdesc	 		# Set IVT
578ca987d46SWarner Losh		popl %es			# Restore
579ca987d46SWarner Losh		popl %ds			#  seg
580ca987d46SWarner Losh		popl %fs			#  regs
581ca987d46SWarner Losh		popl %gs
582ca987d46SWarner Losh		popal				# Restore gp regs
583ca987d46SWarner Losh		movw $MEM_ESPR-0x16,%sp		# Switch to real mode stack
584ca987d46SWarner Losh		iret				# Call target routine
585ca987d46SWarner Losh/*
586ca987d46SWarner Losh * For the return to real mode we setup a stack frame like this on the real
587ca987d46SWarner Losh * mode stack.  Note that callf calls won't pop off the flags, but we just
588ca987d46SWarner Losh * ignore that by repositioning %sp to be just above the btx_v86 pointer
589ca987d46SWarner Losh * so it is aligned.  The stack is relative to MEM_ESPR.
590ca987d46SWarner Losh *
591ca987d46SWarner Losh * -0x04	kernel %esp
592ca987d46SWarner Losh * -0x08	btx_v86
593ca987d46SWarner Losh * -0x0c	%eax
594ca987d46SWarner Losh * -0x10	%ecx
595ca987d46SWarner Losh * -0x14	%edx
596ca987d46SWarner Losh * -0x18	%ebx
597ca987d46SWarner Losh * -0x1c	%esp
598ca987d46SWarner Losh * -0x20	%ebp
599ca987d46SWarner Losh * -0x24	%esi
600ca987d46SWarner Losh * -0x28	%edi
601ca987d46SWarner Losh * -0x2c	%gs
602ca987d46SWarner Losh * -0x30	%fs
603ca987d46SWarner Losh * -0x34	%ds
604ca987d46SWarner Losh * -0x38	%es
605ca987d46SWarner Losh * -0x3c	%eflags
606ca987d46SWarner Losh */
607ca987d46SWarner Loshrret_tramp:	movw $MEM_ESPR-0x08,%sp		# Reset stack pointer
608ca987d46SWarner Losh		pushal				# Save gp regs
609ca987d46SWarner Losh		pushl %gs			# Save
610ca987d46SWarner Losh		pushl %fs			#  seg
611ca987d46SWarner Losh		pushl %ds			#  regs
612ca987d46SWarner Losh		pushl %es
613ca987d46SWarner Losh		pushfl				# Save %eflags
614ca987d46SWarner Losh		pushl $PSL_RESERVED_DEFAULT|PSL_D # Use clean %eflags with
615ca987d46SWarner Losh		popfl				#  string ops dec
616ca987d46SWarner Losh		xorw %ax,%ax			# Reset seg
617ca987d46SWarner Losh		movw %ax,%ds			#  regs
618ca987d46SWarner Losh		movw %ax,%es			#  (%ss is already 0)
619ca987d46SWarner Losh		lidt idtdesc	 		# Set IDT
620ca987d46SWarner Losh		lgdt gdtdesc	 		# Set GDT
621ca987d46SWarner Losh		mov %cr0,%eax			# Switch to protected
622ca987d46SWarner Losh		inc %ax				#  mode
623ca987d46SWarner Losh		mov %eax,%cr0			#
624ca987d46SWarner Losh		ljmp $SEL_SCODE,$rret_tramp.1	# To 32-bit code
625ca987d46SWarner Losh		.code32
626ca987d46SWarner Loshrret_tramp.1:	xorl %ecx,%ecx			# Zero
627ca987d46SWarner Losh		movb $SEL_SDATA,%cl		# Setup
628ca987d46SWarner Losh		movw %cx,%ss			#  32-bit
629ca987d46SWarner Losh		movw %cx,%ds			#  seg
630ca987d46SWarner Losh		movw %cx,%es			#  regs
631ca987d46SWarner Losh		movl MEM_ESPR-0x04,%esp		# Switch to kernel stack
632ca987d46SWarner Losh		leal 0x44(%esp,1),%esi		# Base of frame
633ca987d46SWarner Losh		andb $~0x2,tss_desc+0x5		# Clear TSS busy
634ca987d46SWarner Losh		movb $SEL_TSS,%cl		# Set task
635ca987d46SWarner Losh		ltr %cx				#  register
636ca987d46SWarner Losh/*
637ca987d46SWarner Losh * Now we are back in protected mode.  The kernel stack frame set up
638ca987d46SWarner Losh * before entering real mode is still intact. For hardware interrupts,
639ca987d46SWarner Losh * leave the frame unchanged.
640ca987d46SWarner Losh */
641ca987d46SWarner Losh		cmpl $0,MEM_ESPR-0x08		# Leave saved regs unchanged
642ca987d46SWarner Losh		jz rret_tramp.3			#  for hardware ints
643ca987d46SWarner Losh/*
644ca987d46SWarner Losh * For V86 calls, copy the registers off of the real mode stack onto
645ca987d46SWarner Losh * the kernel stack as we want their updated values.  Also, initialize
646ca987d46SWarner Losh * the segment registers on the kernel stack.
647ca987d46SWarner Losh *
648ca987d46SWarner Losh * Note that the %esp in the kernel stack after this is garbage, but popa
649ca987d46SWarner Losh * ignores it, so we don't have to fix it up.
650ca987d46SWarner Losh */
651ca987d46SWarner Losh		leal -0x18(%esi),%edi		# Kernel stack GP regs
652ca987d46SWarner Losh		pushl %esi			# Save
653ca987d46SWarner Losh		movl $MEM_ESPR-0x0c,%esi	# Real mode stack GP regs
654ca987d46SWarner Losh		movl $8,%ecx			# Copy GP regs from
655ca987d46SWarner Losh		rep				#  real mode stack
656ca987d46SWarner Losh		movsl				#  to kernel stack
657ca987d46SWarner Losh		movl $SEL_UDATA,%eax		# Selector for data seg regs
658ca987d46SWarner Losh		movl $4,%ecx			# Initialize %ds,
659ca987d46SWarner Losh		rep				#  %es, %fs, and
660ca987d46SWarner Losh		stosl				#  %gs
661ca987d46SWarner Losh/*
662ca987d46SWarner Losh * For V86 calls, copy the saved seg regs on the real mode stack back
663ca987d46SWarner Losh * over to the btx_v86 structure.  Also, conditionally update the
664ca987d46SWarner Losh * saved eflags on the kernel stack based on the flags from the user.
665ca987d46SWarner Losh */
666ca987d46SWarner Losh		movl MEM_ESPR-0x08,%ecx		# Get btx_v86 ptr
667ca987d46SWarner Losh		leal V86_GS(%ecx),%edi		# %edi => btx_v86 seg regs
668ca987d46SWarner Losh		leal MEM_ESPR-0x2c,%esi		# %esi => real mode seg regs
669ca987d46SWarner Losh		xchgl %ecx,%edx			# Save btx_v86 ptr
670ca987d46SWarner Losh		movl $4,%ecx			# Copy seg regs
671ca987d46SWarner Losh		rep				#  from real mode stack
672ca987d46SWarner Losh		movsl				#  to btx_v86
673ca987d46SWarner Losh		popl %esi			# Restore
674ca987d46SWarner Losh		movl V86_CTL(%edx),%edx		# Read V86 control flags
675ca987d46SWarner Losh		testl $V86F_FLAGS,%edx		# User wants flags?
676ca987d46SWarner Losh		jz rret_tramp.3			# No
677ca987d46SWarner Losh		movl MEM_ESPR-0x3c,%eax		# Read real mode flags
678ca987d46SWarner Losh		andl $~(PSL_T|PSL_NT),%eax	# Clear unsafe flags
679ca987d46SWarner Losh		movw %ax,-0x08(%esi)		# Update user flags (low 16)
680ca987d46SWarner Losh/*
681ca987d46SWarner Losh * Return to the user task
682ca987d46SWarner Losh */
683ca987d46SWarner Loshrret_tramp.3:	popl %es			# Restore
684ca987d46SWarner Losh		popl %ds			#  seg
685ca987d46SWarner Losh		popl %fs			#  regs
686ca987d46SWarner Losh		popl %gs
687ca987d46SWarner Losh		popal				# Restore gp regs
688ca987d46SWarner Losh		addl $4,%esp			# Discard int no
689ca987d46SWarner Losh		iret				# Return to user mode
690ca987d46SWarner Losh
691ca987d46SWarner Losh/*
692ca987d46SWarner Losh * System Call.
693ca987d46SWarner Losh */
694ca987d46SWarner Loshintx30: 	cmpl $SYS_EXEC,%eax		# Exec system call?
695ca987d46SWarner Losh		jne intx30.1			# No
696ca987d46SWarner Losh		pushl %ss			# Set up
697ca987d46SWarner Losh		popl %es			#  all
698ca987d46SWarner Losh		pushl %es			#  segment
699ca987d46SWarner Losh		popl %ds			#  registers
700ca987d46SWarner Losh		pushl %ds			#  for the
701ca987d46SWarner Losh		popl %fs			#  program
702ca987d46SWarner Losh		pushl %fs			#  we're
703ca987d46SWarner Losh		popl %gs			#  invoking
704ca987d46SWarner Losh		movl $MEM_USR,%eax		# User base address
705ca987d46SWarner Losh		addl 0xc(%esp,1),%eax		# Change to user
706ca987d46SWarner Losh		leal 0x4(%eax),%esp		#  stack
707ca987d46SWarner Losh		popl %eax			# Call
708ca987d46SWarner Losh		call *%eax			#  program
709ca987d46SWarner Loshintx30.1:	orb $0x1,%ss:btx_hdr+0x7	# Flag reboot
710ca987d46SWarner Losh		jmp exit			# Exit
711ca987d46SWarner Losh/*
712ca987d46SWarner Losh * Dump structure [EBX] to [EDI], using format string [ESI].
713ca987d46SWarner Losh */
714ca987d46SWarner Loshdump.0: 	stosb				# Save char
715ca987d46SWarner Loshdump:		lodsb				# Load char
716ca987d46SWarner Losh		testb %al,%al			# End of string?
717ca987d46SWarner Losh		jz dump.10			# Yes
718ca987d46SWarner Losh		testb $0x80,%al 		# Control?
719ca987d46SWarner Losh		jz dump.0			# No
720ca987d46SWarner Losh		movb %al,%ch			# Save control
721ca987d46SWarner Losh		movb $'=',%al			# Append
722ca987d46SWarner Losh		stosb				#  '='
723ca987d46SWarner Losh		lodsb				# Get offset
724ca987d46SWarner Losh		pushl %esi			# Save
725ca987d46SWarner Losh		movsbl %al,%esi 		# To
726ca987d46SWarner Losh		addl %ebx,%esi			#  pointer
727ca987d46SWarner Losh		testb $DMP_X16,%ch		# Dump word?
728ca987d46SWarner Losh		jz dump.1			# No
729ca987d46SWarner Losh		lodsw				# Get and
730ca987d46SWarner Losh		call hex16			#  dump it
731ca987d46SWarner Loshdump.1: 	testb $DMP_X32,%ch		# Dump long?
732ca987d46SWarner Losh		jz dump.2			# No
733ca987d46SWarner Losh		lodsl				# Get and
734ca987d46SWarner Losh		call hex32			#  dump it
735ca987d46SWarner Loshdump.2: 	testb $DMP_MEM,%ch		# Dump memory?
736ca987d46SWarner Losh		jz dump.8			# No
737ca987d46SWarner Losh		pushl %ds			# Save
738ca987d46SWarner Losh		testl $PSL_VM,0x50(%ebx)	# V86 mode?
739ca987d46SWarner Losh		jnz dump.3			# Yes
740ca987d46SWarner Losh		verr 0x4(%esi)	 		# Readable selector?
741ca987d46SWarner Losh		jnz dump.3			# No
742ca987d46SWarner Losh		ldsl (%esi),%esi		# Load pointer
743ca987d46SWarner Losh		jmp dump.4			# Join common code
744ca987d46SWarner Loshdump.3: 	lodsl				# Set offset
745ca987d46SWarner Losh		xchgl %eax,%edx 		# Save
746ca987d46SWarner Losh		lodsl				# Get segment
747ca987d46SWarner Losh		shll $0x4,%eax			#  * 0x10
748ca987d46SWarner Losh		addl %edx,%eax			#  + offset
749ca987d46SWarner Losh		xchgl %eax,%esi 		# Set pointer
750ca987d46SWarner Loshdump.4: 	movb $2,%dl			# Num lines
751ca987d46SWarner Loshdump.4a:	movb $0x10,%cl			# Bytes to dump
752ca987d46SWarner Loshdump.5: 	lodsb				# Get byte and
753ca987d46SWarner Losh		call hex8			#  dump it
754ca987d46SWarner Losh		decb %cl			# Keep count
755ca987d46SWarner Losh		jz dump.6a			# If done
756ca987d46SWarner Losh		movb $'-',%al			# Separator
757ca987d46SWarner Losh		cmpb $0x8,%cl			# Half way?
758ca987d46SWarner Losh		je dump.6			# Yes
759ca987d46SWarner Losh		movb $' ',%al			# Use space
760ca987d46SWarner Loshdump.6: 	stosb				# Save separator
761ca987d46SWarner Losh		jmp dump.5			# Continue
762ca987d46SWarner Loshdump.6a:	decb %dl			# Keep count
763ca987d46SWarner Losh		jz dump.7			# If done
764ca987d46SWarner Losh		movb $0xa,%al			# Line feed
765ca987d46SWarner Losh		stosb				# Save one
766ca987d46SWarner Losh		movb $7,%cl			# Leading
767ca987d46SWarner Losh		movb $' ',%al			#  spaces
768ca987d46SWarner Loshdump.6b:	stosb				# Dump
769ca987d46SWarner Losh		decb %cl			#  spaces
770ca987d46SWarner Losh		jnz dump.6b
771ca987d46SWarner Losh		jmp dump.4a			# Next line
772ca987d46SWarner Loshdump.7: 	popl %ds			# Restore
773ca987d46SWarner Loshdump.8: 	popl %esi			# Restore
774ca987d46SWarner Losh		movb $0xa,%al			# Line feed
775ca987d46SWarner Losh		testb $DMP_EOL,%ch		# End of line?
776ca987d46SWarner Losh		jnz dump.9			# Yes
777ca987d46SWarner Losh		movb $' ',%al			# Use spaces
778ca987d46SWarner Losh		stosb				# Save one
779ca987d46SWarner Loshdump.9: 	jmp dump.0			# Continue
780ca987d46SWarner Loshdump.10:	stosb				# Terminate string
781ca987d46SWarner Losh		ret				# To caller
782ca987d46SWarner Losh/*
783ca987d46SWarner Losh * Convert EAX, AX, or AL to hex, saving the result to [EDI].
784ca987d46SWarner Losh */
785ca987d46SWarner Loshhex32:		pushl %eax			# Save
786ca987d46SWarner Losh		shrl $0x10,%eax 		# Do upper
787ca987d46SWarner Losh		call hex16			#  16
788ca987d46SWarner Losh		popl %eax			# Restore
789ca987d46SWarner Loshhex16:		call hex16.1			# Do upper 8
790ca987d46SWarner Loshhex16.1:	xchgb %ah,%al			# Save/restore
791ca987d46SWarner Loshhex8:		pushl %eax			# Save
792ca987d46SWarner Losh		shrb $0x4,%al			# Do upper
793ca987d46SWarner Losh		call hex8.1			#  4
794ca987d46SWarner Losh		popl %eax			# Restore
795ca987d46SWarner Loshhex8.1: 	andb $0xf,%al			# Get lower 4
796ca987d46SWarner Losh		cmpb $0xa,%al			# Convert
797ca987d46SWarner Losh		sbbb $0x69,%al			#  to hex
798ca987d46SWarner Losh		das				#  digit
799ca987d46SWarner Losh		orb $0x20,%al			# To lower case
800ca987d46SWarner Losh		stosb				# Save char
801ca987d46SWarner Losh		ret				# (Recursive)
802ca987d46SWarner Losh/*
803ca987d46SWarner Losh * Output zero-terminated string [ESI] to the console.
804ca987d46SWarner Losh */
805ca987d46SWarner Loshputstr.0:	call putchr			# Output char
806ca987d46SWarner Loshputstr: 	lodsb				# Load char
807ca987d46SWarner Losh		testb %al,%al			# End of string?
808ca987d46SWarner Losh		jnz putstr.0			# No
809ca987d46SWarner Losh		ret				# To caller
810ca987d46SWarner Losh#ifdef BTX_SERIAL
811ca987d46SWarner Losh		.set SIO_PRT,SIOPRT		# Base port
812ca987d46SWarner Losh		.set SIO_FMT,SIOFMT		# 8N1
813ca987d46SWarner Losh		.set SIO_DIV,(115200/SIOSPD)	# 115200 / SPD
814ca987d46SWarner Losh
815ca987d46SWarner Losh/*
816ca987d46SWarner Losh * int sio_init(void)
817ca987d46SWarner Losh */
818ca987d46SWarner Loshsio_init:	movw $SIO_PRT+0x3,%dx		# Data format reg
819ca987d46SWarner Losh		movb $SIO_FMT|0x80,%al		# Set format
820ca987d46SWarner Losh		outb %al,(%dx)			#  and DLAB
821ca987d46SWarner Losh		pushl %edx			# Save
822ca987d46SWarner Losh		subb $0x3,%dl			# Divisor latch reg
823ca987d46SWarner Losh		movw $SIO_DIV,%ax		# Set
824ca987d46SWarner Losh		outw %ax,(%dx)			#  BPS
825ca987d46SWarner Losh		popl %edx			# Restore
826ca987d46SWarner Losh		movb $SIO_FMT,%al		# Clear
827ca987d46SWarner Losh		outb %al,(%dx)			#  DLAB
828ca987d46SWarner Losh		incl %edx			# Modem control reg
829ca987d46SWarner Losh		movb $0x3,%al			# Set RTS,
830ca987d46SWarner Losh		outb %al,(%dx)			#  DTR
831ca987d46SWarner Losh		incl %edx			# Line status reg
832ca987d46SWarner Losh		call sio_getc.1 		# Get character
833ca987d46SWarner Losh
834ca987d46SWarner Losh/*
835ca987d46SWarner Losh * int sio_flush(void)
836ca987d46SWarner Losh */
837ca987d46SWarner Loshsio_flush:	xorl %eax,%eax			# Return value
838ca987d46SWarner Losh		xorl %ecx,%ecx			# Timeout
839ca987d46SWarner Losh		movb $0x80,%ch			#  counter
840ca987d46SWarner Loshsio_flush.1:	call sio_ischar 		# Check for character
841ca987d46SWarner Losh		jz sio_flush.2			# Till none
842ca987d46SWarner Losh		loop sio_flush.1		#  or counter is zero
843ca987d46SWarner Losh		movb $1, %al			# Exhausted all tries
844ca987d46SWarner Loshsio_flush.2:	ret				# To caller
845ca987d46SWarner Losh
846ca987d46SWarner Losh/*
847ca987d46SWarner Losh * void sio_putc(int c)
848ca987d46SWarner Losh */
849ca987d46SWarner Loshsio_putc:	movw $SIO_PRT+0x5,%dx		# Line status reg
850ca987d46SWarner Losh		xor %ecx,%ecx			# Timeout
851ca987d46SWarner Losh		movb $0x40,%ch			#  counter
852ca987d46SWarner Loshsio_putc.1:	inb (%dx),%al			# Transmitter
853ca987d46SWarner Losh		testb $0x20,%al 		#  buffer empty?
854ca987d46SWarner Losh		loopz sio_putc.1		# No
855ca987d46SWarner Losh		jz sio_putc.2			# If timeout
856ca987d46SWarner Losh		movb 0x4(%esp,1),%al		# Get character
857ca987d46SWarner Losh		subb $0x5,%dl			# Transmitter hold reg
858ca987d46SWarner Losh		outb %al,(%dx)			# Write character
859ca987d46SWarner Loshsio_putc.2:	ret $0x4			# To caller
860ca987d46SWarner Losh
861ca987d46SWarner Losh/*
862ca987d46SWarner Losh * int sio_getc(void)
863ca987d46SWarner Losh */
864ca987d46SWarner Loshsio_getc:	call sio_ischar 		# Character available?
865ca987d46SWarner Losh		jz sio_getc			# No
866ca987d46SWarner Loshsio_getc.1:	subb $0x5,%dl			# Receiver buffer reg
867ca987d46SWarner Losh		inb (%dx),%al			# Read character
868ca987d46SWarner Losh		ret				# To caller
869ca987d46SWarner Losh
870ca987d46SWarner Losh/*
871ca987d46SWarner Losh * int sio_ischar(void)
872ca987d46SWarner Losh */
873ca987d46SWarner Loshsio_ischar:	movw $SIO_PRT+0x5,%dx		# Line status register
874ca987d46SWarner Losh		xorl %eax,%eax			# Zero
875ca987d46SWarner Losh		inb (%dx),%al			# Received data
876ca987d46SWarner Losh		andb $0x1,%al			#  ready?
877ca987d46SWarner Losh		ret				# To caller
878ca987d46SWarner Losh
879ca987d46SWarner Losh/*
880ca987d46SWarner Losh * Output character AL to the serial console.
881ca987d46SWarner Losh */
882ca987d46SWarner Loshputchr: 	pusha				# Save
883ca987d46SWarner Losh		cmpb $10, %al			# is it a newline?
884ca987d46SWarner Losh		jne putchr.1			#  no?, then leave
885ca987d46SWarner Losh		push $13			# output a carriage
886ca987d46SWarner Losh		call sio_putc			#  return first
887ca987d46SWarner Losh		movb $10, %al			# restore %al
888ca987d46SWarner Loshputchr.1:	pushl %eax			# Push the character
889ca987d46SWarner Losh						#  onto the stack
890ca987d46SWarner Losh		call sio_putc			# Output the character
891ca987d46SWarner Losh		popa				# Restore
892ca987d46SWarner Losh		ret				# To caller
893ca987d46SWarner Losh#else
894ca987d46SWarner Losh/*
895ca987d46SWarner Losh * Output character AL to the console.
896ca987d46SWarner Losh */
897ca987d46SWarner Loshputchr: 	pusha				# Save
898ca987d46SWarner Losh		xorl %ecx,%ecx			# Zero for loops
899ca987d46SWarner Losh		movb $SCR_MAT,%ah		# Mode/attribute
900ca987d46SWarner Losh		movl $BDA_POS,%ebx		# BDA pointer
901ca987d46SWarner Losh		movw (%ebx),%dx 		# Cursor position
902ca987d46SWarner Losh		movl $0xb8000,%edi		# Regen buffer (color)
903ca987d46SWarner Losh		cmpb %ah,BDA_SCR-BDA_POS(%ebx)	# Mono mode?
904ca987d46SWarner Losh		jne putchr.1			# No
905ca987d46SWarner Losh		xorw %di,%di			# Regen buffer (mono)
906ca987d46SWarner Loshputchr.1:	cmpb $0xa,%al			# New line?
907ca987d46SWarner Losh		je putchr.2			# Yes
908ca987d46SWarner Losh		xchgl %eax,%ecx 		# Save char
909ca987d46SWarner Losh		movb $SCR_COL,%al		# Columns per row
910ca987d46SWarner Losh		mulb %dh			#  * row position
911ca987d46SWarner Losh		addb %dl,%al			#  + column
912ca987d46SWarner Losh		adcb $0x0,%ah			#  position
913ca987d46SWarner Losh		shll %eax			#  * 2
914ca987d46SWarner Losh		xchgl %eax,%ecx 		# Swap char, offset
915ca987d46SWarner Losh		movw %ax,(%edi,%ecx,1)		# Write attr:char
916ca987d46SWarner Losh		incl %edx			# Bump cursor
917ca987d46SWarner Losh		cmpb $SCR_COL,%dl		# Beyond row?
918ca987d46SWarner Losh		jb putchr.3			# No
919ca987d46SWarner Loshputchr.2:	xorb %dl,%dl			# Zero column
920ca987d46SWarner Losh		incb %dh			# Bump row
921ca987d46SWarner Loshputchr.3:	cmpb $SCR_ROW,%dh		# Beyond screen?
922ca987d46SWarner Losh		jb putchr.4			# No
923ca987d46SWarner Losh		leal 2*SCR_COL(%edi),%esi	# New top line
924ca987d46SWarner Losh		movw $(SCR_ROW-1)*SCR_COL/2,%cx # Words to move
925ca987d46SWarner Losh		rep				# Scroll
926ca987d46SWarner Losh		movsl				#  screen
927ca987d46SWarner Losh		movb $0x20,%al			# Space
928ca987d46SWarner Losh		movb $SCR_COL,%cl		# Columns to clear
929ca987d46SWarner Losh		rep				# Clear
930ca987d46SWarner Losh		stosw				#  line
931ca987d46SWarner Losh		movb $SCR_ROW-1,%dh		# Bottom line
932ca987d46SWarner Loshputchr.4:	movw %dx,(%ebx) 		# Update position
933ca987d46SWarner Losh		popa				# Restore
934ca987d46SWarner Losh		ret				# To caller
935ca987d46SWarner Losh#endif
936ca987d46SWarner Losh
937ca987d46SWarner Losh		.code16
938ca987d46SWarner Losh/*
939ca987d46SWarner Losh * Real Mode Hardware interrupt jump table.
940ca987d46SWarner Losh */
941ca987d46SWarner Loshintr20: 	push $0x8			# Int 0x20: IRQ0
942ca987d46SWarner Losh		jmp int_hwr			# V86 int 0x8
943ca987d46SWarner Losh		push $0x9			# Int 0x21: IRQ1
944ca987d46SWarner Losh		jmp int_hwr			# V86 int 0x9
945ca987d46SWarner Losh		push $0xa			# Int 0x22: IRQ2
946ca987d46SWarner Losh		jmp int_hwr			# V86 int 0xa
947ca987d46SWarner Losh		push $0xb			# Int 0x23: IRQ3
948ca987d46SWarner Losh		jmp int_hwr			# V86 int 0xb
949ca987d46SWarner Losh		push $0xc			# Int 0x24: IRQ4
950ca987d46SWarner Losh		jmp int_hwr			# V86 int 0xc
951ca987d46SWarner Losh		push $0xd			# Int 0x25: IRQ5
952ca987d46SWarner Losh		jmp int_hwr			# V86 int 0xd
953ca987d46SWarner Losh		push $0xe			# Int 0x26: IRQ6
954ca987d46SWarner Losh		jmp int_hwr			# V86 int 0xe
955ca987d46SWarner Losh		push $0xf			# Int 0x27: IRQ7
956ca987d46SWarner Losh		jmp int_hwr			# V86 int 0xf
957ca987d46SWarner Losh		push $0x70			# Int 0x28: IRQ8
958ca987d46SWarner Losh		jmp int_hwr			# V86 int 0x70
959ca987d46SWarner Losh		push $0x71			# Int 0x29: IRQ9
960ca987d46SWarner Losh		jmp int_hwr			# V86 int 0x71
961ca987d46SWarner Losh		push $0x72			# Int 0x2a: IRQ10
962ca987d46SWarner Losh		jmp int_hwr			# V86 int 0x72
963ca987d46SWarner Losh		push $0x73			# Int 0x2b: IRQ11
964ca987d46SWarner Losh		jmp int_hwr			# V86 int 0x73
965ca987d46SWarner Losh		push $0x74			# Int 0x2c: IRQ12
966ca987d46SWarner Losh		jmp int_hwr			# V86 int 0x74
967ca987d46SWarner Losh		push $0x75			# Int 0x2d: IRQ13
968ca987d46SWarner Losh		jmp int_hwr			# V86 int 0x75
969ca987d46SWarner Losh		push $0x76			# Int 0x2e: IRQ14
970ca987d46SWarner Losh		jmp int_hwr			# V86 int 0x76
971ca987d46SWarner Losh		push $0x77			# Int 0x2f: IRQ15
972ca987d46SWarner Losh		jmp int_hwr			# V86 int 0x77
973ca987d46SWarner Losh/*
974ca987d46SWarner Losh * Reflect hardware interrupts in real mode.
975ca987d46SWarner Losh */
976ca987d46SWarner Loshint_hwr: 	push %ax			# Save
977ca987d46SWarner Losh		push %ds			# Save
978ca987d46SWarner Losh		push %bp			# Save
979ca987d46SWarner Losh		mov %sp,%bp			# Address stack frame
980ca987d46SWarner Losh		xchg %bx,6(%bp)			# Swap BX, int no
981ca987d46SWarner Losh		xor %ax,%ax			# Set %ds:%bx to
982ca987d46SWarner Losh		shl $2,%bx			#  point to
983ca987d46SWarner Losh		mov %ax,%ds			#  IDT entry
984ca987d46SWarner Losh		mov (%bx),%ax			# Load IP
985ca987d46SWarner Losh		mov 2(%bx),%bx			# Load CS
986ca987d46SWarner Losh		xchg %ax,4(%bp)			# Swap saved %ax,%bx with
987ca987d46SWarner Losh		xchg %bx,6(%bp)			#  CS:IP of handler
988ca987d46SWarner Losh		pop %bp				# Restore
989ca987d46SWarner Losh		pop %ds				# Restore
990ca987d46SWarner Losh		lret				# Jump to handler
991ca987d46SWarner Losh
992ca987d46SWarner Losh		.p2align 4
993ca987d46SWarner Losh/*
994ca987d46SWarner Losh * Global descriptor table.
995ca987d46SWarner Losh */
996ca987d46SWarner Loshgdt:		.word 0x0,0x0,0x0,0x0		# Null entry
997ca987d46SWarner Losh		.word 0xffff,0x0,0x9a00,0xcf	# SEL_SCODE
998ca987d46SWarner Losh		.word 0xffff,0x0,0x9200,0xcf	# SEL_SDATA
999ca987d46SWarner Losh		.word 0xffff,0x0,0x9a00,0x0	# SEL_RCODE
1000ca987d46SWarner Losh		.word 0xffff,0x0,0x9200,0x0	# SEL_RDATA
1001ca987d46SWarner Losh		.word 0xffff,MEM_USR,0xfa00,0xcf# SEL_UCODE
1002ca987d46SWarner Losh		.word 0xffff,MEM_USR,0xf200,0xcf# SEL_UDATA
1003ca987d46SWarner Loshtss_desc:	.word _TSSLM,MEM_TSS,0x8900,0x0 # SEL_TSS
1004ca987d46SWarner Loshgdt.1:
1005ca987d46SWarner Losh/*
1006ca987d46SWarner Losh * Pseudo-descriptors.
1007ca987d46SWarner Losh */
1008ca987d46SWarner Loshgdtdesc:	.word gdt.1-gdt-1,gdt,0x0	# GDT
1009ca987d46SWarner Loshidtdesc:	.word _IDTLM,MEM_IDT,0x0	# IDT
1010ca987d46SWarner Loshivtdesc:	.word 0x400-0x0-1,0x0,0x0	# IVT
1011ca987d46SWarner Losh/*
1012ca987d46SWarner Losh * IDT construction control string.
1013ca987d46SWarner Losh */
1014ca987d46SWarner Loshidtctl: 	.byte 0x10,  0x8e		# Int 0x0-0xf
1015ca987d46SWarner Losh		.word 0x7dfb,intx00		#  (exceptions)
1016ca987d46SWarner Losh		.byte 0x10,  0x8e		# Int 0x10
1017ca987d46SWarner Losh		.word 0x1,   intx10		#  (exception)
1018ca987d46SWarner Losh		.byte 0x10,  0x8e		# Int 0x20-0x2f
1019ca987d46SWarner Losh		.word 0xffff,intx20		#  (hardware)
1020ca987d46SWarner Losh		.byte 0x1,   0xee		# int 0x30
1021ca987d46SWarner Losh		.word 0x1,   intx30		#  (system call)
1022ca987d46SWarner Losh		.byte 0x2,   0xee		# Int 0x31-0x32
1023ca987d46SWarner Losh		.word 0x1,   intx31		#  (V86, null)
1024ca987d46SWarner Losh		.byte 0x0			# End of string
1025ca987d46SWarner Losh/*
1026ca987d46SWarner Losh * Dump format string.
1027ca987d46SWarner Losh */
1028ca987d46SWarner Loshdmpfmt: 	.byte '\n'			# "\n"
1029ca987d46SWarner Losh		.ascii "int"			# "int="
1030ca987d46SWarner Losh		.byte 0x80|DMP_X32,	   0x40 # "00000000  "
1031ca987d46SWarner Losh		.ascii "err"			# "err="
1032ca987d46SWarner Losh		.byte 0x80|DMP_X32,	   0x44 # "00000000  "
1033ca987d46SWarner Losh		.ascii "efl"			# "efl="
1034ca987d46SWarner Losh		.byte 0x80|DMP_X32,	   0x50 # "00000000  "
1035ca987d46SWarner Losh		.ascii "eip"			# "eip="
1036ca987d46SWarner Losh		.byte 0x80|DMP_X32|DMP_EOL,0x48 # "00000000\n"
1037ca987d46SWarner Losh		.ascii "eax"			# "eax="
1038ca987d46SWarner Losh		.byte 0x80|DMP_X32,	   0x34 # "00000000  "
1039ca987d46SWarner Losh		.ascii "ebx"			# "ebx="
1040ca987d46SWarner Losh		.byte 0x80|DMP_X32,	   0x28 # "00000000  "
1041ca987d46SWarner Losh		.ascii "ecx"			# "ecx="
1042ca987d46SWarner Losh		.byte 0x80|DMP_X32,	   0x30 # "00000000  "
1043ca987d46SWarner Losh		.ascii "edx"			# "edx="
1044ca987d46SWarner Losh		.byte 0x80|DMP_X32|DMP_EOL,0x2c # "00000000\n"
1045ca987d46SWarner Losh		.ascii "esi"			# "esi="
1046ca987d46SWarner Losh		.byte 0x80|DMP_X32,	   0x1c # "00000000  "
1047ca987d46SWarner Losh		.ascii "edi"			# "edi="
1048ca987d46SWarner Losh		.byte 0x80|DMP_X32,	   0x18 # "00000000  "
1049ca987d46SWarner Losh		.ascii "ebp"			# "ebp="
1050ca987d46SWarner Losh		.byte 0x80|DMP_X32,	   0x20 # "00000000  "
1051ca987d46SWarner Losh		.ascii "esp"			# "esp="
1052ca987d46SWarner Losh		.byte 0x80|DMP_X32|DMP_EOL,0x0	# "00000000\n"
1053ca987d46SWarner Losh		.ascii "cs"			# "cs="
1054ca987d46SWarner Losh		.byte 0x80|DMP_X16,	   0x4c # "0000  "
1055ca987d46SWarner Losh		.ascii "ds"			# "ds="
1056ca987d46SWarner Losh		.byte 0x80|DMP_X16,	   0xc	# "0000  "
1057ca987d46SWarner Losh		.ascii "es"			# "es="
1058ca987d46SWarner Losh		.byte 0x80|DMP_X16,	   0x8	# "0000  "
1059ca987d46SWarner Losh		.ascii "  "			# "  "
1060ca987d46SWarner Losh		.ascii "fs"			# "fs="
1061ca987d46SWarner Losh		.byte 0x80|DMP_X16,	   0x10 # "0000  "
1062ca987d46SWarner Losh		.ascii "gs"			# "gs="
1063ca987d46SWarner Losh		.byte 0x80|DMP_X16,	   0x14 # "0000  "
1064ca987d46SWarner Losh		.ascii "ss"			# "ss="
1065ca987d46SWarner Losh		.byte 0x80|DMP_X16|DMP_EOL,0x4	# "0000\n"
1066ca987d46SWarner Losh		.ascii "cs:eip" 		# "cs:eip="
1067ca987d46SWarner Losh		.byte 0x80|DMP_MEM|DMP_EOL,0x48 # "00 00 ... 00 00\n"
1068ca987d46SWarner Losh		.ascii "ss:esp" 		# "ss:esp="
1069ca987d46SWarner Losh		.byte 0x80|DMP_MEM|DMP_EOL,0x0	# "00 00 ... 00 00\n"
1070ca987d46SWarner Losh		.asciz "BTX halted\n"		# End
1071ca987d46SWarner Losh/*
1072ca987d46SWarner Losh * Bad VM86 call panic
1073ca987d46SWarner Losh */
1074ca987d46SWarner Loshbadvm86:	.asciz "Invalid VM86 Request\n"
1075ca987d46SWarner Losh
1076ca987d46SWarner Losh/*
1077ca987d46SWarner Losh * End of BTX memory.
1078ca987d46SWarner Losh */
1079ca987d46SWarner Losh		.p2align 4
1080ca987d46SWarner Loshbreak:
1081