btx.S revision 43561
143561Skato#
243561Skato# Copyright (c) 1998 Robert Nordier
343561Skato# All rights reserved.
443561Skato#
543561Skato# Redistribution and use in source and binary forms are freely
643561Skato# permitted provided that the above copyright notice and this
743561Skato# paragraph and the following disclaimer are duplicated in all
843561Skato# such forms.
943561Skato#
1043561Skato# This software is provided "AS IS" and without any express or
1143561Skato# implied warranties, including, without limitation, the implied
1243561Skato# warranties of merchantability and fitness for a particular
1343561Skato# purpose.
1443561Skato#
1543561Skato
1643561Skato#	$Id: btx.s,v 1.9 1999/01/22 13:07:17 rnordier Exp $
1743561Skato
1843561Skato#
1943561Skato# Memory layout.
2043561Skato#
2143561Skato		.set MEM_BTX,0x1000		# Start of BTX memory
2243561Skato		.set MEM_ESP0,0x1800		# Supervisor stack
2343561Skato		.set MEM_BUF,0x1800		# Scratch buffer
2443561Skato		.set MEM_ESP1,0x1e00		# Link stack
2543561Skato		.set MEM_IDT,0x1e00		# IDT
2643561Skato		.set MEM_TSS,0x1f98		# TSS
2743561Skato		.set MEM_MAP,0x2000		# I/O bit map
2843561Skato		.set MEM_DIR,0x4000		# Page directory
2943561Skato		.set MEM_TBL,0x5000		# Page tables
3043561Skato		.set MEM_ORG,0x9000		# BTX code
3143561Skato		.set MEM_USR,0xa000		# Start of user memory
3243561Skato#
3343561Skato# Paging control.
3443561Skato#
3543561Skato		.set PAG_SIZ,0x1000		# Page size
3643561Skato		.set PAG_CNT,0x1000		# Pages to map
3743561Skato#
3843561Skato# Segment selectors.
3943561Skato#
4043561Skato		.set SEL_SCODE,0x8		# Supervisor code
4143561Skato		.set SEL_SDATA,0x10		# Supervisor data
4243561Skato		.set SEL_RCODE,0x18		# Real mode code
4343561Skato		.set SEL_RDATA,0x20		# Real mode data
4443561Skato		.set SEL_UCODE,0x28|3		# User code
4543561Skato		.set SEL_UDATA,0x30|3		# User data
4643561Skato		.set SEL_TSS,0x38		# TSS
4743561Skato#
4843561Skato# Task state segment fields.
4943561Skato#
5043561Skato		.set TSS_ESP0,0x4		# PL 0 ESP
5143561Skato		.set TSS_SS0,0x8		# PL 0 SS
5243561Skato		.set TSS_ESP1,0xc		# PL 1 ESP
5343561Skato		.set TSS_MAP,0x66		# I/O bit map base
5443561Skato#
5543561Skato# System calls.
5643561Skato#
5743561Skato		.set SYS_EXIT,0x0		# Exit
5843561Skato		.set SYS_EXEC,0x1		# Exec
5943561Skato#
6043561Skato# V86 constants.
6143561Skato#
6243561Skato		.set V86_FLG,0x208eff		# V86 flag mask
6343561Skato		.set V86_STK,0x400		# V86 stack allowance
6443561Skato#
6543561Skato# Dump format control bytes.
6643561Skato#
6743561Skato		.set DMP_X16,0x1		# Word
6843561Skato		.set DMP_X32,0x2		# Long
6943561Skato		.set DMP_MEM,0x4		# Memory
7043561Skato		.set DMP_EOL,0x8		# End of line
7143561Skato#
7243561Skato# Screen defaults and assumptions.
7343561Skato#
7443561Skato.`ifdef' PC98
7543561Skato		.set SCR_MAT,0xe1		# Mode/attribute
7643561Skato.else
7743561Skato		.set SCR_MAT,0x7		# Mode/attribute
7843561Skato.endif
7943561Skato		.set SCR_COL,0x50		# Columns per row
8043561Skato		.set SCR_ROW,0x19		# Rows per screen
8143561Skato#
8243561Skato# BIOS Data Area locations.
8343561Skato#
8443561Skato.`ifdef' PC98
8543561Skato		.set BDA_MEM,0xa1501		# Free memory
8643561Skato		.set BDA_POS,0xa153e		# Cursor position
8743561Skato.else
8843561Skato		.set BDA_MEM,0x413		# Free memory
8943561Skato		.set BDA_SCR,0x449		# Video mode
9043561Skato		.set BDA_POS,0x450		# Cursor position
9143561Skato.endif
9243561Skato#
9343561Skato# Derivations, for brevity.
9443561Skato#
9543561Skato		.set _ESP0H,MEM_ESP0>>0x8	# Byte 1 of ESP0
9643561Skato		.set _ESP1H,MEM_ESP1>>0x8	# Byte 1 of ESP1
9743561Skato		.set _TSSIO,MEM_MAP-MEM_TSS	# TSS I/O base
9843561Skato		.set _TSSLM,MEM_DIR-MEM_TSS-1	# TSS limit
9943561Skato		.set _IDTLM,MEM_TSS-MEM_IDT-1	# IDT limit
10043561Skato#
10143561Skato# Code segment.
10243561Skato#
10343561Skato		.globl start
10443561Skatostart:						# Start of code
10543561Skato#
10643561Skato# BTX header.
10743561Skato#
10843561Skatobtx_hdr:	.byte 0xeb			# Machine ID
10943561Skato		.byte 0xe			# Header size
11043561Skato		.ascii "BTX"			# Magic
11143561Skato		.byte 0x1			# Major version
11243561Skato		.byte 0x0			# Minor version
11343561Skato		.byte 0x0			# Flags
11443561Skato		.word PAG_CNT-MEM_ORG>>0xc	# Paging control
11543561Skato		.word break-start		# Text size
11643561Skato		.long 0x0			# Entry address
11743561Skato#
11843561Skato# Initialization routine.
11943561Skato#
12043561Skatoinit:		cli				# Disable interrupts
12143561Skato		xorl %eax,%eax			# Zero/segment
12243561Skato		movl %ax,%ss			# Set up
12343561Skato		movwir(MEM_ESP0,_sp)		#  stack
12443561Skato		movl %ax,%es			# Address
12543561Skato		movl %ax,%ds			#  data
12643561Skato		pushw $0x2			# Clear
12743561Skato		popfw				#  flags
12843561Skato#
12943561Skato# Initialize memory.
13043561Skato#
13143561Skato		movwir(MEM_IDT,_di)		# Memory to initialize
13243561Skato		movwir((MEM_ORG-MEM_IDT)/2,_cx) # Words to zero
13343561Skato		pushl %edi			# Save
13443561Skato		rep				# Zero-fill
13543561Skato		stosl				#  memory
13643561Skato		popl %edi			# Restore
13743561Skato#
13843561Skato# Create IDT.
13943561Skato#
14043561Skato		movwir(idtctl,_si)		# Control string
14143561Skatoinit.1: 	lodsb				# Get entry
14243561Skato		cwde				#  count
14343561Skato		xchgl %eax,%ecx 		#  as word
14443561Skato		jecxz init.4			# If done
14543561Skato		lodsb				# Get segment
14643561Skato		xchgl %eax,%edx 		#  P:DPL:type
14743561Skato		lodsl				# Get control
14843561Skato		xchgl %eax,%ebx 		#  set
14943561Skato		lodsl				# Get handler offset
15043561Skato		movb $SEL_SCODE,%dh		# Segment selector
15143561Skatoinit.2: 	shrl %ebx			# Handle this int?
15243561Skato		jnc init.3			# No
15343561Skato		movwr0(_ax,_di_)		# Set handler offset
15443561Skato		movbr1(_dh,0x2,_di_)		#  and selector
15543561Skato		movbr1(_dl,0x5,_di_)		# Set P:DPL:type
15643561Skato		addwia(0x4)			# Next handler
15743561Skatoinit.3: 	leaw1r(0x8,_di_,_di)		# Next entry
15843561Skato		loop init.2			# Till set done
15943561Skato		jmp init.1			# Continue
16043561Skato#
16143561Skato# Initialize TSS.
16243561Skato#
16343561Skatoinit.4: 	movbi1(_ESP0H,TSS_ESP0+1,_di_)	# Set ESP0
16443561Skato		movbi1(SEL_SDATA,TSS_SS0,_di_)	# Set SS0
16543561Skato		movbi1(_ESP1H,TSS_ESP1+1,_di_)	# Set ESP1
16643561Skato		movbi1(_TSSIO,TSS_MAP,_di_)	# Set I/O bit map base
16743561Skato#
16843561Skato# Create page directory.
16943561Skato#
17043561Skato		xorw %dx,%dx			# Page
17143561Skato		movb $PAG_SIZ>>0x8,%dh		#  size
17243561Skato		xorw %ax,%ax			# Zero
17343561Skato		movwir(MEM_DIR,_di)		# Page directory
17443561Skato		movb $PAG_CNT>>0xa,%cl		# Entries
17543561Skato		movwir(MEM_TBL|0x7,_ax) 	# First entry
17643561Skatoinit.5: 	stosw				# Write entry
17743561Skato		addl %edx,%eax			# To next
17843561Skato		loop init.5			# Till done
17943561Skato#
18043561Skato# Create page tables.
18143561Skato#
18243561Skato		movwir(MEM_TBL,_di)		# Page table
18343561Skato		movb $PAG_CNT>>0x8,%ch		# Entries
18443561Skato		xorl %eax,%eax			# Start address
18543561Skatoinit.6: 	movb $0x7,%al			# Set U:W:P flags
18643561Skato		cmpwmr(btx_hdr+0x8,_cx) 	# Standard user page?
18743561Skato		jb init.7			# Yes
18843561Skato		cmpwir(PAG_CNT-MEM_BTX>>0xc,_cx)# BTX memory?
18943561Skato		jae init.7			# No or first page
19043561Skato		andb $~0x2,%al			# Clear W flag
19143561Skato		cmpwir(PAG_CNT-MEM_USR>>0xc,_cx)# User page zero?
19243561Skato		jne init.7			# No
19343561Skato		tstbim(0x80,btx_hdr+0x7)	# Unmap it?
19443561Skato		jz init.7			# No
19543561Skato		andb $~0x1,%al			# Clear P flag
19643561Skatoinit.7: 	stosw				# Set entry
19743561Skato		addw %dx,%ax			# Next address
19843561Skato		loop init.6			# Till done
19943561Skato#
20043561Skato# Bring up the system.
20143561Skato#
20243561Skato		movwir(0x2820,_bx)		# Set protected mode
20343561Skato		callwi(setpic)			#  IRQ offsets
20443561Skato		lidtwm(idtdesc) 		# Set IDT
20543561Skato		xorw %ax,%ax			# Set base
20643561Skato		movb $MEM_DIR>>0x8,%ah		#  of page
20743561Skato		movl %eax,%cr3			#  directory
20843561Skato		lgdtwm(gdtdesc) 		# Set GDT
20943561Skato		movl %cr0,%eax			# Switch to
21043561Skato		o16				#  protected mode
21143561Skato		orl $0x80000001,%eax		#  and enable
21243561Skato		movl %eax,%cr0			#  paging
21343561Skato		jmpfwi(SEL_SCODE,init.8)	# To 32-bit code
21443561Skatoinit.8: 	xorl %ecx,%ecx			# Zero
21543561Skato		movb $SEL_SDATA,%cl		# To 32-bit
21643561Skato		movl %cx,%ss			#  stack
21743561Skato#
21843561Skato# Launch user task.
21943561Skato#
22043561Skato		movb $SEL_TSS,%cl		# Set task
22143561Skato		ltrl %ecx			#  register
22243561Skato		movl $MEM_USR,%edx		# User base address
22343561Skato		movzwl %ss:BDA_MEM,%eax 	# Get free memory
22443561Skato.`ifdef' PC98
22543561Skato		andl $0x7,%eax
22643561Skato		incl %eax
22743561Skato		shll $0x11,%eax			# To bytes
22843561Skato.else
22943561Skato		shll $0xa,%eax			# To bytes
23043561Skato.endif
23143561Skato		subl $0x1000,%eax		# Less arg space
23243561Skato		subl %edx,%eax			# Less base
23343561Skato		movb $SEL_UDATA,%cl		# User data selector
23443561Skato		pushl %ecx			# Set SS
23543561Skato		pushl %eax			# Set ESP
23643561Skato		pushl $0x202			# Set flags (IF set)
23743561Skato		pushl $SEL_UCODE		# Set CS
23843561Skato		pushl btx_hdr+0xc		# Set EIP
23943561Skato		pushl %ecx			# Set GS
24043561Skato		pushl %ecx			# Set FS
24143561Skato		pushl %ecx			# Set DS
24243561Skato		pushl %ecx			# Set ES
24343561Skato		pushl %edx			# Set EAX
24443561Skato		movb $0x7,%cl			# Set remaining
24543561Skatoinit.9:		pushb $0x0			#  general
24643561Skato		loop init.9			#  registers
24743561Skato		popa				#  and initialize
24843561Skato		popl %es			# Initialize
24943561Skato		popl %ds			#  user
25043561Skato		popl %fs			#  segment
25143561Skato		popl %gs			#  registers
25243561Skato		iret				# To user mode
25343561Skato#
25443561Skato# Exit routine.
25543561Skato#
25643561Skatoexit:		cli				# Disable interrupts
25743561Skato		movl $MEM_ESP0,%esp		# Clear stack
25843561Skato#
25943561Skato# Turn off paging.
26043561Skato#
26143561Skato		movl %cr0,%eax			# Get CR0
26243561Skato		andl $~0x80000000,%eax		# Disable
26343561Skato		movl %eax,%cr0			#  paging
26443561Skato		xorl %ecx,%ecx			# Zero
26543561Skato		movl %ecx,%cr3			# Flush TLB
26643561Skato#
26743561Skato# To 16 bits.
26843561Skato#
26943561Skato		o16				# Reload
27043561Skato		jmpfwi(SEL_RCODE,exit.1)	#  CS
27143561Skatoexit.1: 	movb $SEL_RDATA,%cl		# 16-bit selector
27243561Skato		movl %cx,%ss			# Reload SS
27343561Skato		movl %cx,%ds			# Load
27443561Skato		movl %cx,%es			#  remaining
27543561Skato		movl %cx,%fs			#  segment
27643561Skato		movl %cx,%gs			#  registers
27743561Skato#
27843561Skato# To real-address mode.
27943561Skato#
28043561Skato		decl %eax			# Switch to
28143561Skato		movl %eax,%cr0			#  real mode
28243561Skato		jmpfwi(0x0,exit.2)		# Reload CS
28343561Skatoexit.2: 	xorl %eax,%eax			# Real mode segment
28443561Skato		movl %ax,%ss			# Reload SS
28543561Skato		movl %ax,%ds			# Address data
28643561Skato.`ifdef' PC98
28743561Skato		movwir(0x1008,_bx)		# Set real mode
28843561Skato.else
28943561Skato		movwir(0x7008,_bx)		# Set real mode
29043561Skato.endif
29143561Skato		callwi(setpic)			#  IRQ offsets
29243561Skato		lidtwm(ivtdesc) 		# Set IVT
29343561Skato#
29443561Skato# Reboot or await reset.
29543561Skato#
29643561Skato		sti				# Enable interrupts
29743561Skato		tstbim(0x1,btx_hdr+0x7)		# Reboot?
29843561Skatoexit.3:		jz exit.3			# No
29943561Skato.`ifdef' PC98
30043561Skato		movb $0xa0,%al
30143561Skato		outb %al,$0x35
30243561Skato		movb 0,%al
30343561Skato		outb %al,$0xf0
30443561Skatoexit.4:		jmp exit.4
30543561Skato.else
30643561Skato		int $0x19			# BIOS: Reboot
30743561Skato.endif
30843561Skato#
30943561Skato# Set IRQ offsets by reprogramming 8259A PICs.
31043561Skato#
31143561Skato.`ifdef' PC98
31243561Skatosetpic: 	inb $0x02,%al			# Save master
31343561Skato		pushl %eax			#  IMR
31443561Skato		inb $0x0a,%al			# Save slave
31543561Skato		pushl %eax			#  IMR
31643561Skato		movb $0x11,%al			# ICW1 to
31743561Skato		outb %al,$0x00			#  master,
31843561Skato		outb %al,$0x08			#  slave
31943561Skato		movb %bl,%al			# ICW2 to
32043561Skato		outb %al,$0x02			#  master
32143561Skato		movb %bh,%al			# ICW2 to
32243561Skato		outb %al,$0x0a			#  slave
32343561Skato		movb $0x80,%al			# ICW3 to
32443561Skato		outb %al,$0x02			#  master
32543561Skato		movb $0x7,%al			# ICW3 to
32643561Skato		outb %al,$0x0a			#  slave
32743561Skato		movb $0x1d,%al			# ICW4 to
32843561Skato		outb %al,$0x02			#  master,
32943561Skato		movb $0x9,%al			# ICW4 to
33043561Skato		outb %al,$0x0a			#  slave
33143561Skato		popl %eax			# Restore slave
33243561Skato		outb %al,$0x0a			#  IMR
33343561Skato		popl %eax			# Restore master
33443561Skato		outb %al,$0x02			#  IMR
33543561Skato.else
33643561Skatosetpic: 	inb $0x21,%al			# Save master
33743561Skato		pushl %eax			#  IMR
33843561Skato		inb $0xa1,%al			# Save slave
33943561Skato		pushl %eax			#  IMR
34043561Skato		movb $0x11,%al			# ICW1 to
34143561Skato		outb %al,$0x20			#  master,
34243561Skato		outb %al,$0xa0			#  slave
34343561Skato		movb %bl,%al			# ICW2 to
34443561Skato		outb %al,$0x21			#  master
34543561Skato		movb %bh,%al			# ICW2 to
34643561Skato		outb %al,$0xa1			#  slave
34743561Skato		movb $0x4,%al			# ICW3 to
34843561Skato		outb %al,$0x21			#  master
34943561Skato		movb $0x2,%al			# ICW3 to
35043561Skato		outb %al,$0xa1			#  slave
35143561Skato		movb $0x1,%al			# ICW4 to
35243561Skato		outb %al,$0x21			#  master,
35343561Skato		outb %al,$0xa1			#  slave
35443561Skato		popl %eax			# Restore slave
35543561Skato		outb %al,$0xa1			#  IMR
35643561Skato		popl %eax			# Restore master
35743561Skato		outb %al,$0x21			#  IMR
35843561Skato.endif
35943561Skato		ret				# To caller
36043561Skato#
36143561Skato# Initiate return from V86 mode to user mode.
36243561Skato#
36343561Skatointhlt: 	hlt				# To supervisor mode
36443561Skato#
36543561Skato# Exception jump table.
36643561Skato#
36743561Skatointx00: 	pushb $0x0			# Int 0x0: #DE
36843561Skato		jmp ex_noc			# Divide error
36943561Skato		pushb $0x1			# Int 0x1: #DB
37043561Skato		jmp ex_noc			# Debug
37143561Skato		pushb $0x3			# Int 0x3: #BP
37243561Skato		jmp ex_noc			# Breakpoint
37343561Skato		pushb $0x4			# Int 0x4: #OF
37443561Skato		jmp ex_noc			# Overflow
37543561Skato		pushb $0x5			# Int 0x5: #BR
37643561Skato		jmp ex_noc			# BOUND range exceeded
37743561Skato		pushb $0x6			# Int 0x6: #UD
37843561Skato		jmp ex_noc			# Invalid opcode
37943561Skato		pushb $0x7			# Int 0x7: #NM
38043561Skato		jmp ex_noc			# Device not available
38143561Skato		pushb $0x8			# Int 0x8: #DF
38243561Skato		jmp except			# Double fault
38343561Skato		pushb $0xa			# Int 0xa: #TS
38443561Skato		jmp except			# Invalid TSS
38543561Skato		pushb $0xb			# Int 0xb: #NP
38643561Skato		jmp except			# Segment not present
38743561Skato		pushb $0xc			# Int 0xc: #SS
38843561Skato		jmp except			# Stack segment fault
38943561Skato		pushb $0xd			# Int 0xd: #GP
39043561Skato		jmp ex_v86			# General protection
39143561Skato		pushb $0xe			# Int 0xe: #PF
39243561Skato		jmp except			# Page fault
39343561Skatointx10: 	pushb $0x10			# Int 0x10: #MF
39443561Skato		jmp ex_noc			# Floating-point error
39543561Skato#
39643561Skato# Handle #GP exception.
39743561Skato#
39843561Skatoex_v86: 	testb $0x2,0x12(%esp,1) 	# V86 mode?
39943561Skato		jz except			# No
40043561Skato		jmp v86mon			# To monitor
40143561Skato#
40243561Skato# Save a zero error code.
40343561Skato#
40443561Skatoex_noc: 	pushl (%esp,1)			# Duplicate int no
40543561Skato		movb $0x0,0x4(%esp,1)		# Fake error code
40643561Skato#
40743561Skato# Handle exception.
40843561Skato#
40943561Skatoexcept: 	cld				# String ops inc
41043561Skato		pushl %ds			# Save
41143561Skato		pushl %es			#  most
41243561Skato		pusha				#  registers
41343561Skato		movb $0x6,%al			# Push loop count
41443561Skato		testb $0x2,0x3a(%esp,1) 	# V86 mode?
41543561Skato		jnz except.1			# Yes
41643561Skato		pushl %gs			# Set GS
41743561Skato		pushl %fs			# Set FS
41843561Skato		pushl %ds			# Set DS
41943561Skato		pushl %es			# Set ES
42043561Skato		movb $0x2,%al			# Push loop count
42143561Skato		cmpw $SEL_SCODE,0x44(%esp,1)	# Supervisor mode?
42243561Skato		jne except.1			# No
42343561Skato		pushl %ss			# Set SS
42443561Skato		leal 0x50(%esp,1),%eax		# Set
42543561Skato		pushl %eax			#  ESP
42643561Skato		jmp except.2			# Join common code
42743561Skatoexcept.1:	pushl 0x50(%esp,1)		# Set GS, FS, DS, ES
42843561Skato		decb %al			#  (if V86 mode), and
42943561Skato		jne except.1			#  SS, ESP
43043561Skatoexcept.2:	pushl $SEL_SDATA		# Set up
43143561Skato		popl %ds			#  to
43243561Skato		pushl %ds			#  address
43343561Skato		popl %es			#  data
43443561Skato		movl %esp,%ebx			# Stack frame
43543561Skato		movl $dmpfmt,%esi		# Dump format string
43643561Skato		movl $MEM_BUF,%edi		# Buffer
43743561Skato.`ifdef' PC98
43843561Skato		pushl %eax
43943561Skato		pushl %edx
44043561Skatowait.1:
44143561Skato		inb  $0x60,%al
44243561Skato		testb $0x04,%al
44343561Skato		jz   wait.1
44443561Skato		movb $0xe0,%al
44543561Skato		outb %al,$0x62
44643561Skatowait.2:
44743561Skato		inb  $0x60,%al
44843561Skato		testb $0x01,%al
44943561Skato		jz   wait.2
45043561Skato		xorl %edx,%edx
45143561Skato		inb  $0x62,%al
45243561Skato		movb %al,%dl
45343561Skato		inb  $0x62,%al
45443561Skato		movb %al,%dh
45543561Skato		inb  $0x62,%al
45643561Skato		inb  $0x62,%al
45743561Skato		inb  $0x62,%al
45843561Skato		movl %edx,%eax
45943561Skato		shlw $1,%ax
46043561Skato		movl $BDA_POS,%edx
46143561Skato		movw %ax,(%edx)
46243561Skato		popl  %edx
46343561Skato		popl  %eax
46443561Skato.endif
46543561Skato		pushl %edi			# Dump to
46643561Skato		call dump			#  buffer
46743561Skato		popl %esi			#  and
46843561Skato		call putstr			#  display
46943561Skato		leal 0x18(%esp,1),%esp		# Discard frame
47043561Skato		popa				# Restore
47143561Skato		popl %es			#  registers
47243561Skato		popl %ds			#  saved
47343561Skato		cmpb $0x3,(%esp,1)		# Breakpoint?
47443561Skato		je except.3			# Yes
47543561Skato		jmp exit			# Exit
47643561Skatoexcept.3:	leal 0x8(%esp,1),%esp		# Discard err, int no
47743561Skato		iret				# From interrupt
47843561Skato#
47943561Skato# Return to user mode from V86 mode.
48043561Skato#
48143561Skatointrtn: 	cld				# String ops inc
48243561Skato		pushl %ds			# Address
48343561Skato		popl %es			#  data
48443561Skato		leal 0x3c(%ebp),%edx		# V86 Segment registers
48543561Skato		movl MEM_TSS+TSS_ESP1,%esi	# Link stack pointer
48643561Skato		lodsl				# INT_V86 args pointer
48743561Skato		movl %esi,%ebx			# Saved exception frame
48843561Skato		testl %eax,%eax 		# INT_V86 args?
48943561Skato		jz intrtn.2			# No
49043561Skato		movl $MEM_USR,%edi		# User base
49143561Skato		movl 0x1c(%esi),%ebx		# User ESP
49243561Skato		movl %eax,(%edi,%ebx,1) 	# Restore to user stack
49343561Skato		leal 0x8(%edi,%eax,1),%edi	# Arg segment registers
49443561Skato		testb $0x4,-0x6(%edi)		# Return flags?
49543561Skato		jz intrtn.1			# No
49643561Skato		movl 0x30(%ebp),%eax		# Get V86 flags
49743561Skato		movw %ax,0x18(%esi)		# Set user flags
49843561Skatointrtn.1:	leal 0x10(%esi),%ebx		# Saved exception frame
49943561Skato		xchgl %edx,%esi 		# Segment registers
50043561Skato		movb $0x4,%cl			# Update seg regs
50143561Skato		rep				#  in INT_V86
50243561Skato		movsl				#  args
50343561Skatointrtn.2:	movl %edx,%esi			# Segment registers
50443561Skato		leal 0x28(%ebp),%edi		# Set up seg
50543561Skato		movb $0x4,%cl			#  regs for
50643561Skato		rep				#  later
50743561Skato		movsl				#  pop
50843561Skato		movl %ebx,%esi			# Restore exception
50943561Skato		movb $0x5,%cl			#  frame to
51043561Skato		rep				#  supervisor
51143561Skato		movsl				#  stack
51243561Skato		movl %esi,MEM_TSS+TSS_ESP1	# Link stack pointer
51343561Skato		popa				# Restore
51443561Skato		leal 0x8(%esp,1),%esp		# Discard err, int no
51543561Skato		popl %es			# Restore
51643561Skato		popl %ds			#  user
51743561Skato		popl %fs			#  segment
51843561Skato		popl %gs			#  registers
51943561Skato		iret				# To user mode
52043561Skato#
52143561Skato# V86 monitor.
52243561Skato#
52343561Skatov86mon: 	cld				# String ops inc
52443561Skato		pushl $SEL_SDATA		# Set up for
52543561Skato		popl %ds			#  flat addressing
52643561Skato		pusha				# Save registers
52743561Skato		movl %esp,%ebp			# Address stack frame
52843561Skato		movzwl 0x2c(%ebp),%edi		# Load V86 CS
52943561Skato		shll $0x4,%edi			# To linear
53043561Skato		movl 0x28(%ebp),%esi		# Load V86 IP
53143561Skato		addl %edi,%esi			# Code pointer
53243561Skato		xorl %ecx,%ecx			# Zero
53343561Skato		movb $0x2,%cl			# 16-bit operands
53443561Skato		xorl %eax,%eax			# Zero
53543561Skatov86mon.1:	lodsb				# Get opcode
53643561Skato		cmpb $0x66,%al			# Operand size prefix?
53743561Skato		jne v86mon.2			# No
53843561Skato		movb $0x4,%cl			# 32-bit operands
53943561Skato		jmp v86mon.1			# Continue
54043561Skatov86mon.2:	cmpb $0xf4,%al			# HLT?
54143561Skato		jne v86mon.3			# No
54243561Skato		cmpl $inthlt+0x1,%esi		# Is inthlt?
54343561Skato		jne v86mon.6			# No (ignore)
54443561Skato		jmp intrtn			# Return to user mode
54543561Skatov86mon.3:	cmpb $0xfa,%al			# CLI?
54643561Skato		je v86cli			# Yes
54743561Skato		cmpb $0xfb,%al			# STI?
54843561Skato		je v86sti			# Yes
54943561Skato		movzwl 0x38(%ebp),%ebx		# Load V86 SS
55043561Skato		shll $0x4,%ebx			# To offset
55143561Skato		pushl %ebx			# Save
55243561Skato		addl 0x34(%ebp),%ebx		# Add V86 SP
55343561Skato		movl 0x30(%ebp),%edx		# Load V86 flags
55443561Skato		cmpb $0x9c,%al			# PUSHF/PUSHFD?
55543561Skato		je v86pushf			# Yes
55643561Skato		cmpb $0x9d,%al			# POPF/POPFD?
55743561Skato		je v86popf			# Yes
55843561Skato		cmpb $0xcd,%al			# INT imm8?
55943561Skato		je v86intn			# Yes
56043561Skato		cmpb $0xcf,%al			# IRET/IRETD?
56143561Skato		je v86iret			# Yes
56243561Skato		popl %ebx			# Restore
56343561Skato		popa				# Restore
56443561Skato		jmp except			# Handle exception
56543561Skatov86mon.4:	movl %edx,0x30(%ebp)		# Save V86 flags
56643561Skatov86mon.5:	popl %edx			# V86 SS adjustment
56743561Skato		subl %edx,%ebx			# Save V86
56843561Skato		movl %ebx,0x34(%ebp)		#  SP
56943561Skatov86mon.6:	subl %edi,%esi			# From linear
57043561Skato		movl %esi,0x28(%ebp)		# Save V86 IP
57143561Skato		popa				# Restore
57243561Skato		leal 0x8(%esp,1),%esp		# Discard int no, error
57343561Skato		iret				# To V86 mode
57443561Skato#
57543561Skato# Emulate CLI.
57643561Skato#
57743561Skatov86cli: 	andb $~0x2,0x31(%ebp)		# Clear IF
57843561Skato		jmp v86mon.6			# Finish up
57943561Skato#
58043561Skato# Emulate STI.
58143561Skato#
58243561Skatov86sti: 	orb $0x2,0x31(%ebp)		# Set IF
58343561Skato		jmp v86mon.6			# Finish up
58443561Skato#
58543561Skato# Emulate PUSHF/PUSHFD.
58643561Skato#
58743561Skatov86pushf:	subl %ecx,%ebx			# Adjust SP
58843561Skato		cmpb $0x4,%cl			# 32-bit
58943561Skato		je v86pushf.1			# Yes
59043561Skato		o16				# 16-bit
59143561Skatov86pushf.1:	movl %edx,(%ebx)		# Save flags
59243561Skato		jmp v86mon.5			# Finish up
59343561Skato#
59443561Skato# Emulate IRET/IRETD.
59543561Skato#
59643561Skatov86iret:	movzwl (%ebx),%esi		# Load V86 IP
59743561Skato		movzwl 0x2(%ebx),%edi		# Load V86 CS
59843561Skato		leal 0x4(%ebx),%ebx		# Adjust SP
59943561Skato		movl %edi,0x2c(%ebp)		# Save V86 CS
60043561Skato		xorl %edi,%edi			# No ESI adjustment
60143561Skato#
60243561Skato# Emulate POPF/POPFD (and remainder of IRET/IRETD).
60343561Skato#
60443561Skatov86popf:	cmpb $0x4,%cl			# 32-bit?
60543561Skato		je v86popf.1			# Yes
60643561Skato		movl %edx,%eax			# Initialize
60743561Skato		o16				# 16-bit
60843561Skatov86popf.1:	movl (%ebx),%eax		# Load flags
60943561Skato		addl %ecx,%ebx			# Adjust SP
61043561Skato		andl $V86_FLG,%eax		# Merge
61143561Skato		andl $~V86_FLG,%edx		#  the
61243561Skato		orl %eax,%edx			#  flags
61343561Skato		jmp v86mon.4			# Finish up
61443561Skato#
61543561Skato# Emulate INT imm8.
61643561Skato#
61743561Skatov86intn:	lodsb				# Get int no
61843561Skato		subl %edi,%esi			# From
61943561Skato		shrl $0x4,%edi			#  linear
62043561Skato		movw %dx,-0x2(%ebx)		# Save flags
62143561Skato		movw %di,-0x4(%ebx)		# Save CS
62243561Skato		leal -0x6(%ebx),%ebx		# Adjust SP
62343561Skato		movw %si,(%ebx) 		# Save IP
62443561Skato		shll $0x2,%eax			# Scale
62543561Skato		movzwl (%eax),%esi		# Load IP
62643561Skato		movzwl 0x2(%eax),%edi		# Load CS
62743561Skato		movl %edi,0x2c(%ebp)		# Save CS
62843561Skato		xorl %edi,%edi			# No ESI adjustment
62943561Skato		andb $~0x3,%dh			# Clear IF and TF
63043561Skato		jmp v86mon.4			# Finish up
63143561Skato#
63243561Skato# Hardware interrupt jump table.
63343561Skato#
63443561Skatointx20: 	pushb $0x8			# Int 0x20: IRQ0
63543561Skato		jmp int_hw			# V86 int 0x8
63643561Skato		pushb $0x9			# Int 0x21: IRQ1
63743561Skato		jmp int_hw			# V86 int 0x9
63843561Skato		pushb $0xa			# Int 0x22: IRQ2
63943561Skato		jmp int_hw			# V86 int 0xa
64043561Skato		pushb $0xb			# Int 0x23: IRQ3
64143561Skato		jmp int_hw			# V86 int 0xb
64243561Skato		pushb $0xc			# Int 0x24: IRQ4
64343561Skato		jmp int_hw			# V86 int 0xc
64443561Skato		pushb $0xd			# Int 0x25: IRQ5
64543561Skato		jmp int_hw			# V86 int 0xd
64643561Skato		pushb $0xe			# Int 0x26: IRQ6
64743561Skato		jmp int_hw			# V86 int 0xe
64843561Skato		pushb $0xf			# Int 0x27: IRQ7
64943561Skato		jmp int_hw			# V86 int 0xf
65043561Skato.`ifdef' PC98
65143561Skato		pushb $0x10			# Int 0x28: IRQ8
65243561Skato		jmp int_hw			# V86 int 0x10
65343561Skato		pushb $0x11			# Int 0x29: IRQ9
65443561Skato		jmp int_hw			# V86 int 0x11
65543561Skato		pushb $0x12			# Int 0x2a: IRQ10
65643561Skato		jmp int_hw			# V86 int 0x12
65743561Skato		pushb $0x13			# Int 0x2b: IRQ11
65843561Skato		jmp int_hw			# V86 int 0x13
65943561Skato		pushb $0x14			# Int 0x2c: IRQ12
66043561Skato		jmp int_hw			# V86 int 0x14
66143561Skato		pushb $0x15			# Int 0x2d: IRQ13
66243561Skato		jmp int_hw			# V86 int 0x15
66343561Skato		pushb $0x16			# Int 0x2e: IRQ14
66443561Skato		jmp int_hw			# V86 int 0x16
66543561Skato		pushb $0x17			# Int 0x2f: IRQ15
66643561Skato		jmp int_hw			# V86 int 0x17
66743561Skato.else
66843561Skato		pushb $0x70			# Int 0x28: IRQ8
66943561Skato		jmp int_hw			# V86 int 0x70
67043561Skato		pushb $0x71			# Int 0x29: IRQ9
67143561Skato		jmp int_hw			# V86 int 0x71
67243561Skato		pushb $0x72			# Int 0x2a: IRQ10
67343561Skato		jmp int_hw			# V86 int 0x72
67443561Skato		pushb $0x73			# Int 0x2b: IRQ11
67543561Skato		jmp int_hw			# V86 int 0x73
67643561Skato		pushb $0x74			# Int 0x2c: IRQ12
67743561Skato		jmp int_hw			# V86 int 0x74
67843561Skato		pushb $0x75			# Int 0x2d: IRQ13
67943561Skato		jmp int_hw			# V86 int 0x75
68043561Skato		pushb $0x76			# Int 0x2e: IRQ14
68143561Skato		jmp int_hw			# V86 int 0x76
68243561Skato		pushb $0x77			# Int 0x2f: IRQ15
68343561Skato		jmp int_hw			# V86 int 0x77
68443561Skato.endif
68543561Skato#
68643561Skato# Reflect hardware interrupts.
68743561Skato#
68843561Skatoint_hw: 	testb $0x2,0xe(%esp,1)		# V86 mode?
68943561Skato		jz intusr			# No
69043561Skato		pushl $SEL_SDATA		# Address
69143561Skato		popl %ds			#  data
69243561Skato		xchgl %eax,(%esp,1)		# Swap EAX, int no
69343561Skato		pushl %ebp			# Address
69443561Skato		movl %esp,%ebp			#  stack frame
69543561Skato		pushl %ebx			# Save
69643561Skato		shll $0x2,%eax			# Get int
69743561Skato		movl (%eax),%eax		#  vector
69843561Skato		subl $0x6,0x14(%ebp)		# Adjust V86 ESP
69943561Skato		movzwl 0x18(%ebp),%ebx		# V86 SS
70043561Skato		shll $0x4,%ebx			#  * 0x10
70143561Skato		addl 0x14(%ebp),%ebx		#  + V86 ESP
70243561Skato		xchgw %ax,0x8(%ebp)		# Swap V86 IP
70343561Skato		rorl $0x10,%eax 		# Swap words
70443561Skato		xchgw %ax,0xc(%ebp)		# Swap V86 CS
70543561Skato		roll $0x10,%eax 		# Swap words
70643561Skato		movl %eax,(%ebx)		# CS:IP for IRET
70743561Skato		movl 0x10(%ebp),%eax		# V86 flags
70843561Skato		movw %ax,0x4(%ebx)		# Flags for IRET
70943561Skato		andb $~0x3,0x11(%ebp)		# Clear IF, TF
71043561Skato		popl %ebx			# Restore
71143561Skato		popl %ebp			#  saved
71243561Skato		popl %eax			#  registers
71343561Skato		iret				# To V86 mode
71443561Skato#
71543561Skato# Invoke V86 interrupt from user mode, with arguments.
71643561Skato#
71743561Skatointx31: 	stc				# Have btx_v86
71843561Skato		pushl %eax			# Missing int no
71943561Skato#
72043561Skato# Invoke V86 interrupt from user mode.
72143561Skato#
72243561Skatointusr: 	std				# String ops dec
72343561Skato		pushl %eax			# Expand
72443561Skato		pushl %eax			#  stack
72543561Skato		pushl %eax			#  frame
72643561Skato		pusha				# Save
72743561Skato		pushl %gs			# Save
72843561Skato		movl %esp,%eax			#  seg regs
72943561Skato		pushl %fs			#  and
73043561Skato		pushl %ds			#  point
73143561Skato		pushl %es			#  to them
73243561Skato		pushb $SEL_SDATA		# Set up
73343561Skato		popl %ds			#  to
73443561Skato		pushl %ds			#  address
73543561Skato		popl %es			#  data
73643561Skato		movl $MEM_USR,%ebx		# User base
73743561Skato		movl %ebx,%edx			#  address
73843561Skato		jc intusr.1			# If btx_v86
73943561Skato		xorl %edx,%edx			# Control flags
74043561Skato		xorl %ebp,%ebp			# btx_v86 pointer
74143561Skatointusr.1:	leal 0x50(%esp,1),%esi		# Base of frame
74243561Skato		pushl %esi			# Save
74343561Skato		addl -0x4(%esi),%ebx		# User ESP
74443561Skato		movl MEM_TSS+TSS_ESP1,%edi	# Link stack pointer
74543561Skato		leal -0x4(%edi),%edi		# Adjust for push
74643561Skato		xorl %ecx,%ecx			# Zero
74743561Skato		movb $0x5,%cl			# Push exception
74843561Skato		rep				#  frame on
74943561Skato		movsl				#  link stack
75043561Skato		xchgl %eax,%esi 		# Saved seg regs
75143561Skato		movl 0x40(%esp,1),%eax		# Get int no
75243561Skato		testl %edx,%edx 		# Have btx_v86?
75343561Skato		jz intusr.2			# No
75443561Skato		movl (%ebx),%ebp		# btx_v86 pointer
75543561Skato		movb $0x4,%cl			# Count
75643561Skato		addl %ecx,%ebx			# Adjust for pop
75743561Skato		rep				# Push saved seg regs
75843561Skato		movsl				#  on link stack
75943561Skato		addl %ebp,%edx			# Flatten btx_v86 ptr
76043561Skato		leal 0x14(%edx),%esi		# Seg regs pointer
76143561Skato		movl 0x4(%edx),%eax		# Get int no/address
76243561Skato		movzwl 0x2(%edx),%edx		# Get control flags
76343561Skatointusr.2:	movl %ebp,(%edi)		# Push btx_v86 and
76443561Skato		movl %edi,MEM_TSS+TSS_ESP1	#  save link stack ptr
76543561Skato		popl %edi			# Base of frame
76643561Skato		xchgl %eax,%ebp 		# Save intno/address
76743561Skato		movl 0x48(%esp,1),%eax		# Get flags
76843561Skato		testb $0x2,%dl			# Simulate CALLF?
76943561Skato		jnz intusr.3			# Yes
77043561Skato		decl %ebx			# Push flags
77143561Skato		decl %ebx			#  on V86
77243561Skato		movw %ax,(%ebx) 		#  stack
77343561Skatointusr.3:	movb $0x4,%cl			# Count
77443561Skato		subl %ecx,%ebx			# Push return address
77543561Skato		movl $inthlt,(%ebx)		#  on V86 stack
77643561Skato		rep				# Copy seg regs to
77743561Skato		movsl				#  exception frame
77843561Skato		xchgl %eax,%ecx 		# Save flags
77943561Skato		movl %ebx,%eax			# User ESP
78043561Skato		subl $V86_STK,%eax		# Less bytes
78143561Skato		ja intusr.4			#  to
78243561Skato		xorl %eax,%eax			#  keep
78343561Skatointusr.4:	shrl $0x4,%eax			# Gives segment
78443561Skato		stosl				# Set SS
78543561Skato		shll $0x4,%eax			# To bytes
78643561Skato		xchgl %eax,%ebx 		# Swap
78743561Skato		subl %ebx,%eax			# Gives offset
78843561Skato		stosl				# Set ESP
78943561Skato		xchgl %eax,%ecx 		# Get flags
79043561Skato		btsl $0x11,%eax 		# Set VM
79143561Skato		andb $~0x3,%ah			# Clear IF and TF
79243561Skato		stosl				# Set EFL
79343561Skato		xchgl %eax,%ebp 		# Get int no/address
79443561Skato		testb $0x1,%dl			# Address?
79543561Skato		jnz intusr.5			# Yes
79643561Skato		shll $0x2,%eax			# Scale
79743561Skato		movl (%eax),%eax		# Load int vector
79843561Skatointusr.5:	movl %eax,%ecx			# Save
79943561Skato		shrl $0x10,%eax 		# Gives segment
80043561Skato		stosl				# Set CS
80143561Skato		movw %cx,%ax			# Restore
80243561Skato		stosl				# Set EIP
80343561Skato		leal 0x10(%esp,1),%esp		# Discard seg regs
80443561Skato		popa				# Restore
80543561Skato		iret				# To V86 mode
80643561Skato#
80743561Skato# System Call.
80843561Skato#
80943561Skatointx30: 	cmpl $SYS_EXEC,%eax		# Exec system call?
81043561Skato		jne intx30.1			# No
81143561Skato		pushl %ss			# Set up
81243561Skato		popl %es			#  all
81343561Skato		pushl %es			#  segment
81443561Skato		popl %ds			#  registers
81543561Skato		pushl %ds			#  for the
81643561Skato		popl %fs			#  program
81743561Skato		pushl %fs			#  we're
81843561Skato		popl %gs			#  invoking
81943561Skato		movl $MEM_USR,%eax		# User base address
82043561Skato		addl 0xc(%esp,1),%eax		# Change to user
82143561Skato		leal 0x4(%eax),%esp		#  stack
82243561Skato		movl %cr0,%eax			# Turn
82343561Skato		andl $~0x80000000,%eax		#  off
82443561Skato		movl %eax,%cr0			#  paging
82543561Skato		xorl %eax,%eax			# Flush
82643561Skato		movl %eax,%cr3			#  TLB
82743561Skato		popl %eax			# Call
82843561Skato		call *%eax			#  program
82943561Skatointx30.1:	incb %ss:btx_hdr+0x7		# Flag reboot
83043561Skato		jmp exit			# Exit
83143561Skato#
83243561Skato# Dump structure [EBX] to [EDI], using format string [ESI].
83343561Skato#
83443561Skatodump.0: 	stosb				# Save char
83543561Skatodump:		lodsb				# Load char
83643561Skato		testb %al,%al			# End of string?
83743561Skato		jz dump.10			# Yes
83843561Skato		testb $0x80,%al 		# Control?
83943561Skato		jz dump.0			# No
84043561Skato		movb %al,%ch			# Save control
84143561Skato		movb $'=',%al			# Append
84243561Skato		stosb				#  '='
84343561Skato		lodsb				# Get offset
84443561Skato		pushl %esi			# Save
84543561Skato		movsbl %al,%esi 		# To
84643561Skato		addl %ebx,%esi			#  pointer
84743561Skato		testb $DMP_X16,%ch		# Dump word?
84843561Skato		jz dump.1			# No
84943561Skato		lodsw				# Get and
85043561Skato		call hex16			#  dump it
85143561Skatodump.1: 	testb $DMP_X32,%ch		# Dump long?
85243561Skato		jz dump.2			# No
85343561Skato		lodsl				# Get and
85443561Skato		call hex32			#  dump it
85543561Skatodump.2: 	testb $DMP_MEM,%ch		# Dump memory?
85643561Skato		jz dump.8			# No
85743561Skato		pushl %ds			# Save
85843561Skato		testb $0x2,0x52(%ebx)		# V86 mode?
85943561Skato		jnz dump.3			# Yes
86043561Skato		verrl 0x4(%esi) 		# Readable selector?
86143561Skato		jnz dump.3			# No
86243561Skato		ldsl (%esi),%esi		# Load pointer
86343561Skato		jmp dump.4			# Join common code
86443561Skatodump.3: 	lodsl				# Set offset
86543561Skato		xchgl %eax,%edx 		# Save
86643561Skato		lodsl				# Get segment
86743561Skato		shll $0x4,%eax			#  * 0x10
86843561Skato		addl %edx,%eax			#  + offset
86943561Skato		xchgl %eax,%esi 		# Set pointer
87043561Skatodump.4: 	movb $0x10,%cl			# Bytes to dump
87143561Skatodump.5: 	lodsb				# Get byte and
87243561Skato		call hex8			#  dump it
87343561Skato		decb %cl			# Keep count
87443561Skato		jz dump.7			# If done
87543561Skato		movb $'-',%al			# Separator
87643561Skato		cmpb $0x8,%cl			# Half way?
87743561Skato		je dump.6			# Yes
87843561Skato		movb $' ',%al			# Use space
87943561Skatodump.6: 	stosb				# Save separator
88043561Skato		jmp dump.5			# Continue
88143561Skatodump.7: 	popl %ds			# Restore
88243561Skatodump.8: 	popl %esi			# Restore
88343561Skato		movb $0xa,%al			# Line feed
88443561Skato		testb $DMP_EOL,%ch		# End of line?
88543561Skato		jnz dump.9			# Yes
88643561Skato		movb $' ',%al			# Use spaces
88743561Skato		stosb				# Save one
88843561Skatodump.9: 	jmp dump.0			# Continue
88943561Skatodump.10:	stosb				# Terminate string
89043561Skato		ret				# To caller
89143561Skato#
89243561Skato# Convert EAX, AX, or AL to hex, saving the result to [EDI].
89343561Skato#
89443561Skatohex32:		pushl %eax			# Save
89543561Skato		shrl $0x10,%eax 		# Do upper
89643561Skato		call hex16			#  16
89743561Skato		popl %eax			# Restore
89843561Skatohex16:		call hex16.1			# Do upper 8
89943561Skatohex16.1:	xchgb %ah,%al			# Save/restore
90043561Skatohex8:		pushl %eax			# Save
90143561Skato		shrb $0x4,%al			# Do upper
90243561Skato		call hex8.1			#  4
90343561Skato		popl %eax			# Restore
90443561Skatohex8.1: 	andb $0xf,%al			# Get lower 4
90543561Skato		cmpb $0xa,%al			# Convert
90643561Skato		sbbb $0x69,%al			#  to hex
90743561Skato		das				#  digit
90843561Skato		orb $0x20,%al			# To lower case
90943561Skato		stosb				# Save char
91043561Skato		ret				# (Recursive)
91143561Skato#
91243561Skato# Output zero-terminated string [ESI] to the console.
91343561Skato#
91443561Skatoputstr.0:	call putchr			# Output char
91543561Skatoputstr: 	lodsb				# Load char
91643561Skato		testb %al,%al			# End of string?
91743561Skato		jnz putstr.0			# No
91843561Skato		ret				# To caller
91943561Skato#
92043561Skato# Output character AL to the console.
92143561Skato#
92243561Skatoputchr: 	pusha				# Save
92343561Skato		xorl %ecx,%ecx			# Zero for loops
92443561Skato		movb $SCR_MAT,%ah		# Mode/attribute
92543561Skato		movl $BDA_POS,%ebx		# BDA pointer
92643561Skato		movw (%ebx),%dx 		# Cursor position
92743561Skato.`ifdef' PC98
92843561Skato		movl $0xa0000,%edi
92943561Skato.else
93043561Skato		movl $0xb8000,%edi		# Regen buffer (color)
93143561Skato		cmpb %ah,BDA_SCR-BDA_POS(%ebx)	# Mono mode?
93243561Skato		jne putchr.1			# No
93343561Skato		xorw %di,%di			# Regen buffer (mono)
93443561Skato.endif
93543561Skatoputchr.1:	cmpb $0xa,%al			# New line?
93643561Skato		je putchr.2			# Yes
93743561Skato.`ifdef' PC98
93843561Skato		movw %dx,%cx
93943561Skato		movb %al,(%edi,%ecx,1)		# Write char
94043561Skato		addl $0x2000,%ecx
94143561Skato		movb %ah,(%edi,%ecx,1)		# Write attr
94243561Skato		addw $0x02,%dx
94343561Skato		jmp putchr.3
94443561Skatoputchr.2:	movw %dx,%ax
94543561Skato		movb $SCR_COL*2,%dl
94643561Skato		div %dl
94743561Skato		incb %al
94843561Skato		mul %dl
94943561Skato		movw %ax,%dx
95043561Skatoputchr.3:	cmpw $SCR_ROW*SCR_COL*2,%dx
95143561Skato.else
95243561Skato		xchgl %eax,%ecx 		# Save char
95343561Skato		movb $SCR_COL,%al		# Columns per row
95443561Skato		mulb %dh			#  * row position
95543561Skato		addb %dl,%al			#  + column
95643561Skato		adcb $0x0,%ah			#  position
95743561Skato		shll %eax			#  * 2
95843561Skato		xchgl %eax,%ecx 		# Swap char, offset
95943561Skato		movw %ax,(%edi,%ecx,1)		# Write attr:char
96043561Skato		incl %edx			# Bump cursor
96143561Skato		cmpb $SCR_COL,%dl		# Beyond row?
96243561Skato		jb putchr.3			# No
96343561Skatoputchr.2:	xorb %dl,%dl			# Zero column
96443561Skato		incb %dh			# Bump row
96543561Skatoputchr.3:	cmpb $SCR_ROW,%dh		# Beyond screen?
96643561Skato.endif
96743561Skato		jb putchr.4			# No
96843561Skato		leal 2*SCR_COL(%edi),%esi	# New top line
96943561Skato		movw $(SCR_ROW-1)*SCR_COL/2,%cx # Words to move
97043561Skato		rep				# Scroll
97143561Skato		movsl				#  screen
97243561Skato		movb $' ',%al			# Space
97343561Skato.`ifdef' PC98
97443561Skato		xorb %ah,%ah
97543561Skato.endif
97643561Skato		movb $SCR_COL,%cl		# Columns to clear
97743561Skato		rep				# Clear
97843561Skato		stosw				#  line
97943561Skato.`ifdef' PC98
98043561Skato		movw $(SCR_ROW-1)*SCR_COL*2,%dx
98143561Skato.else
98243561Skato		movb $SCR_ROW-1,%dh		# Bottom line
98343561Skato.endif
98443561Skatoputchr.4:	movw %dx,(%ebx) 		# Update position
98543561Skato		popa				# Restore
98643561Skato		ret				# To caller
98743561Skato
98843561Skato		.p2align 4
98943561Skato#
99043561Skato# Global descriptor table.
99143561Skato#
99243561Skatogdt:		.word 0x0,0x0,0x0,0x0		# Null entry
99343561Skato		.word 0xffff,0x0,0x9a00,0xcf	# SEL_SCODE
99443561Skato		.word 0xffff,0x0,0x9200,0xcf	# SEL_SDATA
99543561Skato		.word 0xffff,0x0,0x9a00,0x0	# SEL_RCODE
99643561Skato		.word 0xffff,0x0,0x9200,0x0	# SEL_RDATA
99743561Skato		.word 0xffff,MEM_USR,0xfa00,0xcf# SEL_UCODE
99843561Skato		.word 0xffff,MEM_USR,0xf200,0xcf# SEL_UDATA
99943561Skato		.word _TSSLM,MEM_TSS,0x8900,0x0 # SEL_TSS
100043561Skatogdt.1:
100143561Skato#
100243561Skato# Pseudo-descriptors.
100343561Skato#
100443561Skatogdtdesc:	.word gdt.1-gdt-1,gdt,0x0	# GDT
100543561Skatoidtdesc:	.word _IDTLM,MEM_IDT,0x0	# IDT
100643561Skatoivtdesc:	.word 0x400-0x0-1,0x0,0x0	# IVT
100743561Skato#
100843561Skato# IDT construction control string.
100943561Skato#
101043561Skatoidtctl: 	.byte 0x10,  0x8e		# Int 0x0-0xf
101143561Skato		.word 0x7dfb,intx00		#  (exceptions)
101243561Skato		.byte 0x10,  0x8e		# Int 0x10
101343561Skato		.word 0x1,   intx10		#  (exception)
101443561Skato		.byte 0x10,  0x8e		# Int 0x20-0x2f
101543561Skato		.word 0xffff,intx20		#  (hardware)
101643561Skato		.byte 0x1,   0xee		# int 0x30
101743561Skato		.word 0x1,   intx30		#  (system call)
101843561Skato		.byte 0x2,   0xee		# Int 0x31-0x32
101943561Skato		.word 0x1,   intx31		#  (V86, null)
102043561Skato		.byte 0x0			# End of string
102143561Skato#
102243561Skato# Dump format string.
102343561Skato#
102443561Skatodmpfmt: 	.byte '\n'			# "\n"
102543561Skato		.ascii "int"			# "int="
102643561Skato		.byte 0x80|DMP_X32,	   0x40 # "00000000  "
102743561Skato		.ascii "err"			# "err="
102843561Skato		.byte 0x80|DMP_X32,	   0x44 # "00000000  "
102943561Skato		.ascii "efl"			# "efl="
103043561Skato		.byte 0x80|DMP_X32,	   0x50 # "00000000  "
103143561Skato		.ascii "eip"			# "eip="
103243561Skato		.byte 0x80|DMP_X32|DMP_EOL,0x48 # "00000000\n"
103343561Skato		.ascii "eax"			# "eax="
103443561Skato		.byte 0x80|DMP_X32,	   0x34 # "00000000  "
103543561Skato		.ascii "ebx"			# "ebx="
103643561Skato		.byte 0x80|DMP_X32,	   0x28 # "00000000  "
103743561Skato		.ascii "ecx"			# "ecx="
103843561Skato		.byte 0x80|DMP_X32,	   0x30 # "00000000  "
103943561Skato		.ascii "edx"			# "edx="
104043561Skato		.byte 0x80|DMP_X32|DMP_EOL,0x2c # "00000000\n"
104143561Skato		.ascii "esi"			# "esi="
104243561Skato		.byte 0x80|DMP_X32,	   0x1c # "00000000  "
104343561Skato		.ascii "edi"			# "edi="
104443561Skato		.byte 0x80|DMP_X32,	   0x18 # "00000000  "
104543561Skato		.ascii "ebp"			# "ebp="
104643561Skato		.byte 0x80|DMP_X32,	   0x20 # "00000000  "
104743561Skato		.ascii "esp"			# "esp="
104843561Skato		.byte 0x80|DMP_X32|DMP_EOL,0x0	# "00000000\n"
104943561Skato		.ascii "cs"			# "cs="
105043561Skato		.byte 0x80|DMP_X16,	   0x4c # "0000  "
105143561Skato		.ascii "ds"			# "ds="
105243561Skato		.byte 0x80|DMP_X16,	   0xc	# "0000  "
105343561Skato		.ascii "es"			# "es="
105443561Skato		.byte 0x80|DMP_X16,	   0x8	# "0000  "
105543561Skato		.ascii "  "			# "  "
105643561Skato		.ascii "fs"			# "fs="
105743561Skato		.byte 0x80|DMP_X16,	   0x10 # "0000  "
105843561Skato		.ascii "gs"			# "gs="
105943561Skato		.byte 0x80|DMP_X16,	   0x14 # "0000  "
106043561Skato		.ascii "ss"			# "ss="
106143561Skato		.byte 0x80|DMP_X16|DMP_EOL,0x4	# "0000\n"
106243561Skato		.ascii "cs:eip" 		# "cs:eip="
106343561Skato		.byte 0x80|DMP_MEM|DMP_EOL,0x48 # "00 00 ... 00 00\n"
106443561Skato		.ascii "ss:esp" 		# "ss:esp="
106543561Skato		.byte 0x80|DMP_MEM|DMP_EOL,0x0	# "00 00 ... 00 00\n"
106643561Skato		.asciz "System halted"		# End
106743561Skato#
106843561Skato# End of BTX memory.
106943561Skato#
107043561Skato		.p2align 4
107143561Skatobreak:
1072