summaryrefslogtreecommitdiffstats
path: root/sys/boot/pc98/btx
diff options
context:
space:
mode:
authorkato <kato@FreeBSD.org>1999-02-03 08:39:09 +0000
committerkato <kato@FreeBSD.org>1999-02-03 08:39:09 +0000
commitc40db6cc734847f5d3013132b80d70a078c16615 (patch)
tree8460f4832d3da04f82cedbd05be800e5fd9063e4 /sys/boot/pc98/btx
parent850544e5d8903343f0bdde5c29f0147851ea1b4b (diff)
downloadFreeBSD-src-c40db6cc734847f5d3013132b80d70a078c16615.zip
FreeBSD-src-c40db6cc734847f5d3013132b80d70a078c16615.tar.gz
PC98 version of new boot loader. Because boot2 has not yet ported,
files in boot2 directory are copies from legacy biosboot. Submitted by: IMAI Takeshi <take-i@ceres.dti.ne.jp>
Diffstat (limited to 'sys/boot/pc98/btx')
-rw-r--r--sys/boot/pc98/btx/Makefile5
-rw-r--r--sys/boot/pc98/btx/btx/Makefile25
-rw-r--r--sys/boot/pc98/btx/btx/btx.S1071
-rw-r--r--sys/boot/pc98/btx/btx/btx.m459
-rw-r--r--sys/boot/pc98/btx/btx/btx.s1071
-rw-r--r--sys/boot/pc98/btx/btxldr/Makefile26
-rw-r--r--sys/boot/pc98/btx/btxldr/btxldr.S459
-rw-r--r--sys/boot/pc98/btx/btxldr/btxldr.s459
-rw-r--r--sys/boot/pc98/btx/lib/Makefile20
-rw-r--r--sys/boot/pc98/btx/lib/btxcsu.s43
-rw-r--r--sys/boot/pc98/btx/lib/btxsys.s40
-rw-r--r--sys/boot/pc98/btx/lib/btxv86.h63
-rw-r--r--sys/boot/pc98/btx/lib/btxv86.s85
13 files changed, 3426 insertions, 0 deletions
diff --git a/sys/boot/pc98/btx/Makefile b/sys/boot/pc98/btx/Makefile
new file mode 100644
index 0000000..49d05f0
--- /dev/null
+++ b/sys/boot/pc98/btx/Makefile
@@ -0,0 +1,5 @@
+# $Id: Makefile,v 1.4 1998/09/17 23:52:03 msmith Exp $
+
+SUBDIR= btx btxldr lib # client ldrtst
+
+.include <bsd.subdir.mk>
diff --git a/sys/boot/pc98/btx/btx/Makefile b/sys/boot/pc98/btx/btx/Makefile
new file mode 100644
index 0000000..b74deea
--- /dev/null
+++ b/sys/boot/pc98/btx/btx/Makefile
@@ -0,0 +1,25 @@
+# $Id: Makefile,v 1.5 1998/10/13 18:29:18 rnordier Exp $
+
+M4?= m4
+
+ORG= 0x9000
+
+AFLAGS+= --defsym PC98=1
+
+all: btx
+
+btx: btx.o
+.if ${OBJFORMAT} == aout
+ ${LD} -nostdlib -N -s -T ${ORG} -o btx.out btx.o
+ dd if=btx.out of=${.TARGET} ibs=32 skip=1
+.else
+ ${LD} -N -e start -Ttext ${ORG} -o btx.out btx.o
+ objcopy -S -O binary btx.out ${.TARGET}
+.endif
+
+btx.o: btx.m4 btx.s
+ (cd ${.CURDIR}; ${M4} btx.m4 btx.s) | ${AS} ${AFLAGS} -o ${.TARGET}
+
+CLEANFILES+= btx btx.out btx.o
+
+.include <bsd.prog.mk>
diff --git a/sys/boot/pc98/btx/btx/btx.S b/sys/boot/pc98/btx/btx/btx.S
new file mode 100644
index 0000000..b0bd4f2
--- /dev/null
+++ b/sys/boot/pc98/btx/btx/btx.S
@@ -0,0 +1,1071 @@
+#
+# Copyright (c) 1998 Robert Nordier
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms are freely
+# permitted provided that the above copyright notice and this
+# paragraph and the following disclaimer are duplicated in all
+# such forms.
+#
+# This software is provided "AS IS" and without any express or
+# implied warranties, including, without limitation, the implied
+# warranties of merchantability and fitness for a particular
+# purpose.
+#
+
+# $Id: btx.s,v 1.9 1999/01/22 13:07:17 rnordier Exp $
+
+#
+# Memory layout.
+#
+ .set MEM_BTX,0x1000 # Start of BTX memory
+ .set MEM_ESP0,0x1800 # Supervisor stack
+ .set MEM_BUF,0x1800 # Scratch buffer
+ .set MEM_ESP1,0x1e00 # Link stack
+ .set MEM_IDT,0x1e00 # IDT
+ .set MEM_TSS,0x1f98 # TSS
+ .set MEM_MAP,0x2000 # I/O bit map
+ .set MEM_DIR,0x4000 # Page directory
+ .set MEM_TBL,0x5000 # Page tables
+ .set MEM_ORG,0x9000 # BTX code
+ .set MEM_USR,0xa000 # Start of user memory
+#
+# Paging control.
+#
+ .set PAG_SIZ,0x1000 # Page size
+ .set PAG_CNT,0x1000 # Pages to map
+#
+# Segment selectors.
+#
+ .set SEL_SCODE,0x8 # Supervisor code
+ .set SEL_SDATA,0x10 # Supervisor data
+ .set SEL_RCODE,0x18 # Real mode code
+ .set SEL_RDATA,0x20 # Real mode data
+ .set SEL_UCODE,0x28|3 # User code
+ .set SEL_UDATA,0x30|3 # User data
+ .set SEL_TSS,0x38 # TSS
+#
+# Task state segment fields.
+#
+ .set TSS_ESP0,0x4 # PL 0 ESP
+ .set TSS_SS0,0x8 # PL 0 SS
+ .set TSS_ESP1,0xc # PL 1 ESP
+ .set TSS_MAP,0x66 # I/O bit map base
+#
+# System calls.
+#
+ .set SYS_EXIT,0x0 # Exit
+ .set SYS_EXEC,0x1 # Exec
+#
+# V86 constants.
+#
+ .set V86_FLG,0x208eff # V86 flag mask
+ .set V86_STK,0x400 # V86 stack allowance
+#
+# Dump format control bytes.
+#
+ .set DMP_X16,0x1 # Word
+ .set DMP_X32,0x2 # Long
+ .set DMP_MEM,0x4 # Memory
+ .set DMP_EOL,0x8 # End of line
+#
+# Screen defaults and assumptions.
+#
+.`ifdef' PC98
+ .set SCR_MAT,0xe1 # Mode/attribute
+.else
+ .set SCR_MAT,0x7 # Mode/attribute
+.endif
+ .set SCR_COL,0x50 # Columns per row
+ .set SCR_ROW,0x19 # Rows per screen
+#
+# BIOS Data Area locations.
+#
+.`ifdef' PC98
+ .set BDA_MEM,0xa1501 # Free memory
+ .set BDA_POS,0xa153e # Cursor position
+.else
+ .set BDA_MEM,0x413 # Free memory
+ .set BDA_SCR,0x449 # Video mode
+ .set BDA_POS,0x450 # Cursor position
+.endif
+#
+# Derivations, for brevity.
+#
+ .set _ESP0H,MEM_ESP0>>0x8 # Byte 1 of ESP0
+ .set _ESP1H,MEM_ESP1>>0x8 # Byte 1 of ESP1
+ .set _TSSIO,MEM_MAP-MEM_TSS # TSS I/O base
+ .set _TSSLM,MEM_DIR-MEM_TSS-1 # TSS limit
+ .set _IDTLM,MEM_TSS-MEM_IDT-1 # IDT limit
+#
+# Code segment.
+#
+ .globl start
+start: # Start of code
+#
+# BTX header.
+#
+btx_hdr: .byte 0xeb # Machine ID
+ .byte 0xe # Header size
+ .ascii "BTX" # Magic
+ .byte 0x1 # Major version
+ .byte 0x0 # Minor version
+ .byte 0x0 # Flags
+ .word PAG_CNT-MEM_ORG>>0xc # Paging control
+ .word break-start # Text size
+ .long 0x0 # Entry address
+#
+# Initialization routine.
+#
+init: cli # Disable interrupts
+ xorl %eax,%eax # Zero/segment
+ movl %ax,%ss # Set up
+ movwir(MEM_ESP0,_sp) # stack
+ movl %ax,%es # Address
+ movl %ax,%ds # data
+ pushw $0x2 # Clear
+ popfw # flags
+#
+# Initialize memory.
+#
+ movwir(MEM_IDT,_di) # Memory to initialize
+ movwir((MEM_ORG-MEM_IDT)/2,_cx) # Words to zero
+ pushl %edi # Save
+ rep # Zero-fill
+ stosl # memory
+ popl %edi # Restore
+#
+# Create IDT.
+#
+ movwir(idtctl,_si) # Control string
+init.1: lodsb # Get entry
+ cwde # count
+ xchgl %eax,%ecx # as word
+ jecxz init.4 # If done
+ lodsb # Get segment
+ xchgl %eax,%edx # P:DPL:type
+ lodsl # Get control
+ xchgl %eax,%ebx # set
+ lodsl # Get handler offset
+ movb $SEL_SCODE,%dh # Segment selector
+init.2: shrl %ebx # Handle this int?
+ jnc init.3 # No
+ movwr0(_ax,_di_) # Set handler offset
+ movbr1(_dh,0x2,_di_) # and selector
+ movbr1(_dl,0x5,_di_) # Set P:DPL:type
+ addwia(0x4) # Next handler
+init.3: leaw1r(0x8,_di_,_di) # Next entry
+ loop init.2 # Till set done
+ jmp init.1 # Continue
+#
+# Initialize TSS.
+#
+init.4: movbi1(_ESP0H,TSS_ESP0+1,_di_) # Set ESP0
+ movbi1(SEL_SDATA,TSS_SS0,_di_) # Set SS0
+ movbi1(_ESP1H,TSS_ESP1+1,_di_) # Set ESP1
+ movbi1(_TSSIO,TSS_MAP,_di_) # Set I/O bit map base
+#
+# Create page directory.
+#
+ xorw %dx,%dx # Page
+ movb $PAG_SIZ>>0x8,%dh # size
+ xorw %ax,%ax # Zero
+ movwir(MEM_DIR,_di) # Page directory
+ movb $PAG_CNT>>0xa,%cl # Entries
+ movwir(MEM_TBL|0x7,_ax) # First entry
+init.5: stosw # Write entry
+ addl %edx,%eax # To next
+ loop init.5 # Till done
+#
+# Create page tables.
+#
+ movwir(MEM_TBL,_di) # Page table
+ movb $PAG_CNT>>0x8,%ch # Entries
+ xorl %eax,%eax # Start address
+init.6: movb $0x7,%al # Set U:W:P flags
+ cmpwmr(btx_hdr+0x8,_cx) # Standard user page?
+ jb init.7 # Yes
+ cmpwir(PAG_CNT-MEM_BTX>>0xc,_cx)# BTX memory?
+ jae init.7 # No or first page
+ andb $~0x2,%al # Clear W flag
+ cmpwir(PAG_CNT-MEM_USR>>0xc,_cx)# User page zero?
+ jne init.7 # No
+ tstbim(0x80,btx_hdr+0x7) # Unmap it?
+ jz init.7 # No
+ andb $~0x1,%al # Clear P flag
+init.7: stosw # Set entry
+ addw %dx,%ax # Next address
+ loop init.6 # Till done
+#
+# Bring up the system.
+#
+ movwir(0x2820,_bx) # Set protected mode
+ callwi(setpic) # IRQ offsets
+ lidtwm(idtdesc) # Set IDT
+ xorw %ax,%ax # Set base
+ movb $MEM_DIR>>0x8,%ah # of page
+ movl %eax,%cr3 # directory
+ lgdtwm(gdtdesc) # Set GDT
+ movl %cr0,%eax # Switch to
+ o16 # protected mode
+ orl $0x80000001,%eax # and enable
+ movl %eax,%cr0 # paging
+ jmpfwi(SEL_SCODE,init.8) # To 32-bit code
+init.8: xorl %ecx,%ecx # Zero
+ movb $SEL_SDATA,%cl # To 32-bit
+ movl %cx,%ss # stack
+#
+# Launch user task.
+#
+ movb $SEL_TSS,%cl # Set task
+ ltrl %ecx # register
+ movl $MEM_USR,%edx # User base address
+ movzwl %ss:BDA_MEM,%eax # Get free memory
+.`ifdef' PC98
+ andl $0x7,%eax
+ incl %eax
+ shll $0x11,%eax # To bytes
+.else
+ shll $0xa,%eax # To bytes
+.endif
+ subl $0x1000,%eax # Less arg space
+ subl %edx,%eax # Less base
+ movb $SEL_UDATA,%cl # User data selector
+ pushl %ecx # Set SS
+ pushl %eax # Set ESP
+ pushl $0x202 # Set flags (IF set)
+ pushl $SEL_UCODE # Set CS
+ pushl btx_hdr+0xc # Set EIP
+ pushl %ecx # Set GS
+ pushl %ecx # Set FS
+ pushl %ecx # Set DS
+ pushl %ecx # Set ES
+ pushl %edx # Set EAX
+ movb $0x7,%cl # Set remaining
+init.9: pushb $0x0 # general
+ loop init.9 # registers
+ popa # and initialize
+ popl %es # Initialize
+ popl %ds # user
+ popl %fs # segment
+ popl %gs # registers
+ iret # To user mode
+#
+# Exit routine.
+#
+exit: cli # Disable interrupts
+ movl $MEM_ESP0,%esp # Clear stack
+#
+# Turn off paging.
+#
+ movl %cr0,%eax # Get CR0
+ andl $~0x80000000,%eax # Disable
+ movl %eax,%cr0 # paging
+ xorl %ecx,%ecx # Zero
+ movl %ecx,%cr3 # Flush TLB
+#
+# To 16 bits.
+#
+ o16 # Reload
+ jmpfwi(SEL_RCODE,exit.1) # CS
+exit.1: movb $SEL_RDATA,%cl # 16-bit selector
+ movl %cx,%ss # Reload SS
+ movl %cx,%ds # Load
+ movl %cx,%es # remaining
+ movl %cx,%fs # segment
+ movl %cx,%gs # registers
+#
+# To real-address mode.
+#
+ decl %eax # Switch to
+ movl %eax,%cr0 # real mode
+ jmpfwi(0x0,exit.2) # Reload CS
+exit.2: xorl %eax,%eax # Real mode segment
+ movl %ax,%ss # Reload SS
+ movl %ax,%ds # Address data
+.`ifdef' PC98
+ movwir(0x1008,_bx) # Set real mode
+.else
+ movwir(0x7008,_bx) # Set real mode
+.endif
+ callwi(setpic) # IRQ offsets
+ lidtwm(ivtdesc) # Set IVT
+#
+# Reboot or await reset.
+#
+ sti # Enable interrupts
+ tstbim(0x1,btx_hdr+0x7) # Reboot?
+exit.3: jz exit.3 # No
+.`ifdef' PC98
+ movb $0xa0,%al
+ outb %al,$0x35
+ movb 0,%al
+ outb %al,$0xf0
+exit.4: jmp exit.4
+.else
+ int $0x19 # BIOS: Reboot
+.endif
+#
+# Set IRQ offsets by reprogramming 8259A PICs.
+#
+.`ifdef' PC98
+setpic: inb $0x02,%al # Save master
+ pushl %eax # IMR
+ inb $0x0a,%al # Save slave
+ pushl %eax # IMR
+ movb $0x11,%al # ICW1 to
+ outb %al,$0x00 # master,
+ outb %al,$0x08 # slave
+ movb %bl,%al # ICW2 to
+ outb %al,$0x02 # master
+ movb %bh,%al # ICW2 to
+ outb %al,$0x0a # slave
+ movb $0x80,%al # ICW3 to
+ outb %al,$0x02 # master
+ movb $0x7,%al # ICW3 to
+ outb %al,$0x0a # slave
+ movb $0x1d,%al # ICW4 to
+ outb %al,$0x02 # master,
+ movb $0x9,%al # ICW4 to
+ outb %al,$0x0a # slave
+ popl %eax # Restore slave
+ outb %al,$0x0a # IMR
+ popl %eax # Restore master
+ outb %al,$0x02 # IMR
+.else
+setpic: inb $0x21,%al # Save master
+ pushl %eax # IMR
+ inb $0xa1,%al # Save slave
+ pushl %eax # IMR
+ movb $0x11,%al # ICW1 to
+ outb %al,$0x20 # master,
+ outb %al,$0xa0 # slave
+ movb %bl,%al # ICW2 to
+ outb %al,$0x21 # master
+ movb %bh,%al # ICW2 to
+ outb %al,$0xa1 # slave
+ movb $0x4,%al # ICW3 to
+ outb %al,$0x21 # master
+ movb $0x2,%al # ICW3 to
+ outb %al,$0xa1 # slave
+ movb $0x1,%al # ICW4 to
+ outb %al,$0x21 # master,
+ outb %al,$0xa1 # slave
+ popl %eax # Restore slave
+ outb %al,$0xa1 # IMR
+ popl %eax # Restore master
+ outb %al,$0x21 # IMR
+.endif
+ ret # To caller
+#
+# Initiate return from V86 mode to user mode.
+#
+inthlt: hlt # To supervisor mode
+#
+# Exception jump table.
+#
+intx00: pushb $0x0 # Int 0x0: #DE
+ jmp ex_noc # Divide error
+ pushb $0x1 # Int 0x1: #DB
+ jmp ex_noc # Debug
+ pushb $0x3 # Int 0x3: #BP
+ jmp ex_noc # Breakpoint
+ pushb $0x4 # Int 0x4: #OF
+ jmp ex_noc # Overflow
+ pushb $0x5 # Int 0x5: #BR
+ jmp ex_noc # BOUND range exceeded
+ pushb $0x6 # Int 0x6: #UD
+ jmp ex_noc # Invalid opcode
+ pushb $0x7 # Int 0x7: #NM
+ jmp ex_noc # Device not available
+ pushb $0x8 # Int 0x8: #DF
+ jmp except # Double fault
+ pushb $0xa # Int 0xa: #TS
+ jmp except # Invalid TSS
+ pushb $0xb # Int 0xb: #NP
+ jmp except # Segment not present
+ pushb $0xc # Int 0xc: #SS
+ jmp except # Stack segment fault
+ pushb $0xd # Int 0xd: #GP
+ jmp ex_v86 # General protection
+ pushb $0xe # Int 0xe: #PF
+ jmp except # Page fault
+intx10: pushb $0x10 # Int 0x10: #MF
+ jmp ex_noc # Floating-point error
+#
+# Handle #GP exception.
+#
+ex_v86: testb $0x2,0x12(%esp,1) # V86 mode?
+ jz except # No
+ jmp v86mon # To monitor
+#
+# Save a zero error code.
+#
+ex_noc: pushl (%esp,1) # Duplicate int no
+ movb $0x0,0x4(%esp,1) # Fake error code
+#
+# Handle exception.
+#
+except: cld # String ops inc
+ pushl %ds # Save
+ pushl %es # most
+ pusha # registers
+ movb $0x6,%al # Push loop count
+ testb $0x2,0x3a(%esp,1) # V86 mode?
+ jnz except.1 # Yes
+ pushl %gs # Set GS
+ pushl %fs # Set FS
+ pushl %ds # Set DS
+ pushl %es # Set ES
+ movb $0x2,%al # Push loop count
+ cmpw $SEL_SCODE,0x44(%esp,1) # Supervisor mode?
+ jne except.1 # No
+ pushl %ss # Set SS
+ leal 0x50(%esp,1),%eax # Set
+ pushl %eax # ESP
+ jmp except.2 # Join common code
+except.1: pushl 0x50(%esp,1) # Set GS, FS, DS, ES
+ decb %al # (if V86 mode), and
+ jne except.1 # SS, ESP
+except.2: pushl $SEL_SDATA # Set up
+ popl %ds # to
+ pushl %ds # address
+ popl %es # data
+ movl %esp,%ebx # Stack frame
+ movl $dmpfmt,%esi # Dump format string
+ movl $MEM_BUF,%edi # Buffer
+.`ifdef' PC98
+ pushl %eax
+ pushl %edx
+wait.1:
+ inb $0x60,%al
+ testb $0x04,%al
+ jz wait.1
+ movb $0xe0,%al
+ outb %al,$0x62
+wait.2:
+ inb $0x60,%al
+ testb $0x01,%al
+ jz wait.2
+ xorl %edx,%edx
+ inb $0x62,%al
+ movb %al,%dl
+ inb $0x62,%al
+ movb %al,%dh
+ inb $0x62,%al
+ inb $0x62,%al
+ inb $0x62,%al
+ movl %edx,%eax
+ shlw $1,%ax
+ movl $BDA_POS,%edx
+ movw %ax,(%edx)
+ popl %edx
+ popl %eax
+.endif
+ pushl %edi # Dump to
+ call dump # buffer
+ popl %esi # and
+ call putstr # display
+ leal 0x18(%esp,1),%esp # Discard frame
+ popa # Restore
+ popl %es # registers
+ popl %ds # saved
+ cmpb $0x3,(%esp,1) # Breakpoint?
+ je except.3 # Yes
+ jmp exit # Exit
+except.3: leal 0x8(%esp,1),%esp # Discard err, int no
+ iret # From interrupt
+#
+# Return to user mode from V86 mode.
+#
+intrtn: cld # String ops inc
+ pushl %ds # Address
+ popl %es # data
+ leal 0x3c(%ebp),%edx # V86 Segment registers
+ movl MEM_TSS+TSS_ESP1,%esi # Link stack pointer
+ lodsl # INT_V86 args pointer
+ movl %esi,%ebx # Saved exception frame
+ testl %eax,%eax # INT_V86 args?
+ jz intrtn.2 # No
+ movl $MEM_USR,%edi # User base
+ movl 0x1c(%esi),%ebx # User ESP
+ movl %eax,(%edi,%ebx,1) # Restore to user stack
+ leal 0x8(%edi,%eax,1),%edi # Arg segment registers
+ testb $0x4,-0x6(%edi) # Return flags?
+ jz intrtn.1 # No
+ movl 0x30(%ebp),%eax # Get V86 flags
+ movw %ax,0x18(%esi) # Set user flags
+intrtn.1: leal 0x10(%esi),%ebx # Saved exception frame
+ xchgl %edx,%esi # Segment registers
+ movb $0x4,%cl # Update seg regs
+ rep # in INT_V86
+ movsl # args
+intrtn.2: movl %edx,%esi # Segment registers
+ leal 0x28(%ebp),%edi # Set up seg
+ movb $0x4,%cl # regs for
+ rep # later
+ movsl # pop
+ movl %ebx,%esi # Restore exception
+ movb $0x5,%cl # frame to
+ rep # supervisor
+ movsl # stack
+ movl %esi,MEM_TSS+TSS_ESP1 # Link stack pointer
+ popa # Restore
+ leal 0x8(%esp,1),%esp # Discard err, int no
+ popl %es # Restore
+ popl %ds # user
+ popl %fs # segment
+ popl %gs # registers
+ iret # To user mode
+#
+# V86 monitor.
+#
+v86mon: cld # String ops inc
+ pushl $SEL_SDATA # Set up for
+ popl %ds # flat addressing
+ pusha # Save registers
+ movl %esp,%ebp # Address stack frame
+ movzwl 0x2c(%ebp),%edi # Load V86 CS
+ shll $0x4,%edi # To linear
+ movl 0x28(%ebp),%esi # Load V86 IP
+ addl %edi,%esi # Code pointer
+ xorl %ecx,%ecx # Zero
+ movb $0x2,%cl # 16-bit operands
+ xorl %eax,%eax # Zero
+v86mon.1: lodsb # Get opcode
+ cmpb $0x66,%al # Operand size prefix?
+ jne v86mon.2 # No
+ movb $0x4,%cl # 32-bit operands
+ jmp v86mon.1 # Continue
+v86mon.2: cmpb $0xf4,%al # HLT?
+ jne v86mon.3 # No
+ cmpl $inthlt+0x1,%esi # Is inthlt?
+ jne v86mon.6 # No (ignore)
+ jmp intrtn # Return to user mode
+v86mon.3: cmpb $0xfa,%al # CLI?
+ je v86cli # Yes
+ cmpb $0xfb,%al # STI?
+ je v86sti # Yes
+ movzwl 0x38(%ebp),%ebx # Load V86 SS
+ shll $0x4,%ebx # To offset
+ pushl %ebx # Save
+ addl 0x34(%ebp),%ebx # Add V86 SP
+ movl 0x30(%ebp),%edx # Load V86 flags
+ cmpb $0x9c,%al # PUSHF/PUSHFD?
+ je v86pushf # Yes
+ cmpb $0x9d,%al # POPF/POPFD?
+ je v86popf # Yes
+ cmpb $0xcd,%al # INT imm8?
+ je v86intn # Yes
+ cmpb $0xcf,%al # IRET/IRETD?
+ je v86iret # Yes
+ popl %ebx # Restore
+ popa # Restore
+ jmp except # Handle exception
+v86mon.4: movl %edx,0x30(%ebp) # Save V86 flags
+v86mon.5: popl %edx # V86 SS adjustment
+ subl %edx,%ebx # Save V86
+ movl %ebx,0x34(%ebp) # SP
+v86mon.6: subl %edi,%esi # From linear
+ movl %esi,0x28(%ebp) # Save V86 IP
+ popa # Restore
+ leal 0x8(%esp,1),%esp # Discard int no, error
+ iret # To V86 mode
+#
+# Emulate CLI.
+#
+v86cli: andb $~0x2,0x31(%ebp) # Clear IF
+ jmp v86mon.6 # Finish up
+#
+# Emulate STI.
+#
+v86sti: orb $0x2,0x31(%ebp) # Set IF
+ jmp v86mon.6 # Finish up
+#
+# Emulate PUSHF/PUSHFD.
+#
+v86pushf: subl %ecx,%ebx # Adjust SP
+ cmpb $0x4,%cl # 32-bit
+ je v86pushf.1 # Yes
+ o16 # 16-bit
+v86pushf.1: movl %edx,(%ebx) # Save flags
+ jmp v86mon.5 # Finish up
+#
+# Emulate IRET/IRETD.
+#
+v86iret: movzwl (%ebx),%esi # Load V86 IP
+ movzwl 0x2(%ebx),%edi # Load V86 CS
+ leal 0x4(%ebx),%ebx # Adjust SP
+ movl %edi,0x2c(%ebp) # Save V86 CS
+ xorl %edi,%edi # No ESI adjustment
+#
+# Emulate POPF/POPFD (and remainder of IRET/IRETD).
+#
+v86popf: cmpb $0x4,%cl # 32-bit?
+ je v86popf.1 # Yes
+ movl %edx,%eax # Initialize
+ o16 # 16-bit
+v86popf.1: movl (%ebx),%eax # Load flags
+ addl %ecx,%ebx # Adjust SP
+ andl $V86_FLG,%eax # Merge
+ andl $~V86_FLG,%edx # the
+ orl %eax,%edx # flags
+ jmp v86mon.4 # Finish up
+#
+# Emulate INT imm8.
+#
+v86intn: lodsb # Get int no
+ subl %edi,%esi # From
+ shrl $0x4,%edi # linear
+ movw %dx,-0x2(%ebx) # Save flags
+ movw %di,-0x4(%ebx) # Save CS
+ leal -0x6(%ebx),%ebx # Adjust SP
+ movw %si,(%ebx) # Save IP
+ shll $0x2,%eax # Scale
+ movzwl (%eax),%esi # Load IP
+ movzwl 0x2(%eax),%edi # Load CS
+ movl %edi,0x2c(%ebp) # Save CS
+ xorl %edi,%edi # No ESI adjustment
+ andb $~0x3,%dh # Clear IF and TF
+ jmp v86mon.4 # Finish up
+#
+# Hardware interrupt jump table.
+#
+intx20: pushb $0x8 # Int 0x20: IRQ0
+ jmp int_hw # V86 int 0x8
+ pushb $0x9 # Int 0x21: IRQ1
+ jmp int_hw # V86 int 0x9
+ pushb $0xa # Int 0x22: IRQ2
+ jmp int_hw # V86 int 0xa
+ pushb $0xb # Int 0x23: IRQ3
+ jmp int_hw # V86 int 0xb
+ pushb $0xc # Int 0x24: IRQ4
+ jmp int_hw # V86 int 0xc
+ pushb $0xd # Int 0x25: IRQ5
+ jmp int_hw # V86 int 0xd
+ pushb $0xe # Int 0x26: IRQ6
+ jmp int_hw # V86 int 0xe
+ pushb $0xf # Int 0x27: IRQ7
+ jmp int_hw # V86 int 0xf
+.`ifdef' PC98
+ pushb $0x10 # Int 0x28: IRQ8
+ jmp int_hw # V86 int 0x10
+ pushb $0x11 # Int 0x29: IRQ9
+ jmp int_hw # V86 int 0x11
+ pushb $0x12 # Int 0x2a: IRQ10
+ jmp int_hw # V86 int 0x12
+ pushb $0x13 # Int 0x2b: IRQ11
+ jmp int_hw # V86 int 0x13
+ pushb $0x14 # Int 0x2c: IRQ12
+ jmp int_hw # V86 int 0x14
+ pushb $0x15 # Int 0x2d: IRQ13
+ jmp int_hw # V86 int 0x15
+ pushb $0x16 # Int 0x2e: IRQ14
+ jmp int_hw # V86 int 0x16
+ pushb $0x17 # Int 0x2f: IRQ15
+ jmp int_hw # V86 int 0x17
+.else
+ pushb $0x70 # Int 0x28: IRQ8
+ jmp int_hw # V86 int 0x70
+ pushb $0x71 # Int 0x29: IRQ9
+ jmp int_hw # V86 int 0x71
+ pushb $0x72 # Int 0x2a: IRQ10
+ jmp int_hw # V86 int 0x72
+ pushb $0x73 # Int 0x2b: IRQ11
+ jmp int_hw # V86 int 0x73
+ pushb $0x74 # Int 0x2c: IRQ12
+ jmp int_hw # V86 int 0x74
+ pushb $0x75 # Int 0x2d: IRQ13
+ jmp int_hw # V86 int 0x75
+ pushb $0x76 # Int 0x2e: IRQ14
+ jmp int_hw # V86 int 0x76
+ pushb $0x77 # Int 0x2f: IRQ15
+ jmp int_hw # V86 int 0x77
+.endif
+#
+# Reflect hardware interrupts.
+#
+int_hw: testb $0x2,0xe(%esp,1) # V86 mode?
+ jz intusr # No
+ pushl $SEL_SDATA # Address
+ popl %ds # data
+ xchgl %eax,(%esp,1) # Swap EAX, int no
+ pushl %ebp # Address
+ movl %esp,%ebp # stack frame
+ pushl %ebx # Save
+ shll $0x2,%eax # Get int
+ movl (%eax),%eax # vector
+ subl $0x6,0x14(%ebp) # Adjust V86 ESP
+ movzwl 0x18(%ebp),%ebx # V86 SS
+ shll $0x4,%ebx # * 0x10
+ addl 0x14(%ebp),%ebx # + V86 ESP
+ xchgw %ax,0x8(%ebp) # Swap V86 IP
+ rorl $0x10,%eax # Swap words
+ xchgw %ax,0xc(%ebp) # Swap V86 CS
+ roll $0x10,%eax # Swap words
+ movl %eax,(%ebx) # CS:IP for IRET
+ movl 0x10(%ebp),%eax # V86 flags
+ movw %ax,0x4(%ebx) # Flags for IRET
+ andb $~0x3,0x11(%ebp) # Clear IF, TF
+ popl %ebx # Restore
+ popl %ebp # saved
+ popl %eax # registers
+ iret # To V86 mode
+#
+# Invoke V86 interrupt from user mode, with arguments.
+#
+intx31: stc # Have btx_v86
+ pushl %eax # Missing int no
+#
+# Invoke V86 interrupt from user mode.
+#
+intusr: std # String ops dec
+ pushl %eax # Expand
+ pushl %eax # stack
+ pushl %eax # frame
+ pusha # Save
+ pushl %gs # Save
+ movl %esp,%eax # seg regs
+ pushl %fs # and
+ pushl %ds # point
+ pushl %es # to them
+ pushb $SEL_SDATA # Set up
+ popl %ds # to
+ pushl %ds # address
+ popl %es # data
+ movl $MEM_USR,%ebx # User base
+ movl %ebx,%edx # address
+ jc intusr.1 # If btx_v86
+ xorl %edx,%edx # Control flags
+ xorl %ebp,%ebp # btx_v86 pointer
+intusr.1: leal 0x50(%esp,1),%esi # Base of frame
+ pushl %esi # Save
+ addl -0x4(%esi),%ebx # User ESP
+ movl MEM_TSS+TSS_ESP1,%edi # Link stack pointer
+ leal -0x4(%edi),%edi # Adjust for push
+ xorl %ecx,%ecx # Zero
+ movb $0x5,%cl # Push exception
+ rep # frame on
+ movsl # link stack
+ xchgl %eax,%esi # Saved seg regs
+ movl 0x40(%esp,1),%eax # Get int no
+ testl %edx,%edx # Have btx_v86?
+ jz intusr.2 # No
+ movl (%ebx),%ebp # btx_v86 pointer
+ movb $0x4,%cl # Count
+ addl %ecx,%ebx # Adjust for pop
+ rep # Push saved seg regs
+ movsl # on link stack
+ addl %ebp,%edx # Flatten btx_v86 ptr
+ leal 0x14(%edx),%esi # Seg regs pointer
+ movl 0x4(%edx),%eax # Get int no/address
+ movzwl 0x2(%edx),%edx # Get control flags
+intusr.2: movl %ebp,(%edi) # Push btx_v86 and
+ movl %edi,MEM_TSS+TSS_ESP1 # save link stack ptr
+ popl %edi # Base of frame
+ xchgl %eax,%ebp # Save intno/address
+ movl 0x48(%esp,1),%eax # Get flags
+ testb $0x2,%dl # Simulate CALLF?
+ jnz intusr.3 # Yes
+ decl %ebx # Push flags
+ decl %ebx # on V86
+ movw %ax,(%ebx) # stack
+intusr.3: movb $0x4,%cl # Count
+ subl %ecx,%ebx # Push return address
+ movl $inthlt,(%ebx) # on V86 stack
+ rep # Copy seg regs to
+ movsl # exception frame
+ xchgl %eax,%ecx # Save flags
+ movl %ebx,%eax # User ESP
+ subl $V86_STK,%eax # Less bytes
+ ja intusr.4 # to
+ xorl %eax,%eax # keep
+intusr.4: shrl $0x4,%eax # Gives segment
+ stosl # Set SS
+ shll $0x4,%eax # To bytes
+ xchgl %eax,%ebx # Swap
+ subl %ebx,%eax # Gives offset
+ stosl # Set ESP
+ xchgl %eax,%ecx # Get flags
+ btsl $0x11,%eax # Set VM
+ andb $~0x3,%ah # Clear IF and TF
+ stosl # Set EFL
+ xchgl %eax,%ebp # Get int no/address
+ testb $0x1,%dl # Address?
+ jnz intusr.5 # Yes
+ shll $0x2,%eax # Scale
+ movl (%eax),%eax # Load int vector
+intusr.5: movl %eax,%ecx # Save
+ shrl $0x10,%eax # Gives segment
+ stosl # Set CS
+ movw %cx,%ax # Restore
+ stosl # Set EIP
+ leal 0x10(%esp,1),%esp # Discard seg regs
+ popa # Restore
+ iret # To V86 mode
+#
+# System Call.
+#
+intx30: cmpl $SYS_EXEC,%eax # Exec system call?
+ jne intx30.1 # No
+ pushl %ss # Set up
+ popl %es # all
+ pushl %es # segment
+ popl %ds # registers
+ pushl %ds # for the
+ popl %fs # program
+ pushl %fs # we're
+ popl %gs # invoking
+ movl $MEM_USR,%eax # User base address
+ addl 0xc(%esp,1),%eax # Change to user
+ leal 0x4(%eax),%esp # stack
+ movl %cr0,%eax # Turn
+ andl $~0x80000000,%eax # off
+ movl %eax,%cr0 # paging
+ xorl %eax,%eax # Flush
+ movl %eax,%cr3 # TLB
+ popl %eax # Call
+ call *%eax # program
+intx30.1: incb %ss:btx_hdr+0x7 # Flag reboot
+ jmp exit # Exit
+#
+# Dump structure [EBX] to [EDI], using format string [ESI].
+#
+dump.0: stosb # Save char
+dump: lodsb # Load char
+ testb %al,%al # End of string?
+ jz dump.10 # Yes
+ testb $0x80,%al # Control?
+ jz dump.0 # No
+ movb %al,%ch # Save control
+ movb $'=',%al # Append
+ stosb # '='
+ lodsb # Get offset
+ pushl %esi # Save
+ movsbl %al,%esi # To
+ addl %ebx,%esi # pointer
+ testb $DMP_X16,%ch # Dump word?
+ jz dump.1 # No
+ lodsw # Get and
+ call hex16 # dump it
+dump.1: testb $DMP_X32,%ch # Dump long?
+ jz dump.2 # No
+ lodsl # Get and
+ call hex32 # dump it
+dump.2: testb $DMP_MEM,%ch # Dump memory?
+ jz dump.8 # No
+ pushl %ds # Save
+ testb $0x2,0x52(%ebx) # V86 mode?
+ jnz dump.3 # Yes
+ verrl 0x4(%esi) # Readable selector?
+ jnz dump.3 # No
+ ldsl (%esi),%esi # Load pointer
+ jmp dump.4 # Join common code
+dump.3: lodsl # Set offset
+ xchgl %eax,%edx # Save
+ lodsl # Get segment
+ shll $0x4,%eax # * 0x10
+ addl %edx,%eax # + offset
+ xchgl %eax,%esi # Set pointer
+dump.4: movb $0x10,%cl # Bytes to dump
+dump.5: lodsb # Get byte and
+ call hex8 # dump it
+ decb %cl # Keep count
+ jz dump.7 # If done
+ movb $'-',%al # Separator
+ cmpb $0x8,%cl # Half way?
+ je dump.6 # Yes
+ movb $' ',%al # Use space
+dump.6: stosb # Save separator
+ jmp dump.5 # Continue
+dump.7: popl %ds # Restore
+dump.8: popl %esi # Restore
+ movb $0xa,%al # Line feed
+ testb $DMP_EOL,%ch # End of line?
+ jnz dump.9 # Yes
+ movb $' ',%al # Use spaces
+ stosb # Save one
+dump.9: jmp dump.0 # Continue
+dump.10: stosb # Terminate string
+ ret # To caller
+#
+# Convert EAX, AX, or AL to hex, saving the result to [EDI].
+#
+hex32: pushl %eax # Save
+ shrl $0x10,%eax # Do upper
+ call hex16 # 16
+ popl %eax # Restore
+hex16: call hex16.1 # Do upper 8
+hex16.1: xchgb %ah,%al # Save/restore
+hex8: pushl %eax # Save
+ shrb $0x4,%al # Do upper
+ call hex8.1 # 4
+ popl %eax # Restore
+hex8.1: andb $0xf,%al # Get lower 4
+ cmpb $0xa,%al # Convert
+ sbbb $0x69,%al # to hex
+ das # digit
+ orb $0x20,%al # To lower case
+ stosb # Save char
+ ret # (Recursive)
+#
+# Output zero-terminated string [ESI] to the console.
+#
+putstr.0: call putchr # Output char
+putstr: lodsb # Load char
+ testb %al,%al # End of string?
+ jnz putstr.0 # No
+ ret # To caller
+#
+# Output character AL to the console.
+#
+putchr: pusha # Save
+ xorl %ecx,%ecx # Zero for loops
+ movb $SCR_MAT,%ah # Mode/attribute
+ movl $BDA_POS,%ebx # BDA pointer
+ movw (%ebx),%dx # Cursor position
+.`ifdef' PC98
+ movl $0xa0000,%edi
+.else
+ movl $0xb8000,%edi # Regen buffer (color)
+ cmpb %ah,BDA_SCR-BDA_POS(%ebx) # Mono mode?
+ jne putchr.1 # No
+ xorw %di,%di # Regen buffer (mono)
+.endif
+putchr.1: cmpb $0xa,%al # New line?
+ je putchr.2 # Yes
+.`ifdef' PC98
+ movw %dx,%cx
+ movb %al,(%edi,%ecx,1) # Write char
+ addl $0x2000,%ecx
+ movb %ah,(%edi,%ecx,1) # Write attr
+ addw $0x02,%dx
+ jmp putchr.3
+putchr.2: movw %dx,%ax
+ movb $SCR_COL*2,%dl
+ div %dl
+ incb %al
+ mul %dl
+ movw %ax,%dx
+putchr.3: cmpw $SCR_ROW*SCR_COL*2,%dx
+.else
+ xchgl %eax,%ecx # Save char
+ movb $SCR_COL,%al # Columns per row
+ mulb %dh # * row position
+ addb %dl,%al # + column
+ adcb $0x0,%ah # position
+ shll %eax # * 2
+ xchgl %eax,%ecx # Swap char, offset
+ movw %ax,(%edi,%ecx,1) # Write attr:char
+ incl %edx # Bump cursor
+ cmpb $SCR_COL,%dl # Beyond row?
+ jb putchr.3 # No
+putchr.2: xorb %dl,%dl # Zero column
+ incb %dh # Bump row
+putchr.3: cmpb $SCR_ROW,%dh # Beyond screen?
+.endif
+ jb putchr.4 # No
+ leal 2*SCR_COL(%edi),%esi # New top line
+ movw $(SCR_ROW-1)*SCR_COL/2,%cx # Words to move
+ rep # Scroll
+ movsl # screen
+ movb $' ',%al # Space
+.`ifdef' PC98
+ xorb %ah,%ah
+.endif
+ movb $SCR_COL,%cl # Columns to clear
+ rep # Clear
+ stosw # line
+.`ifdef' PC98
+ movw $(SCR_ROW-1)*SCR_COL*2,%dx
+.else
+ movb $SCR_ROW-1,%dh # Bottom line
+.endif
+putchr.4: movw %dx,(%ebx) # Update position
+ popa # Restore
+ ret # To caller
+
+ .p2align 4
+#
+# Global descriptor table.
+#
+gdt: .word 0x0,0x0,0x0,0x0 # Null entry
+ .word 0xffff,0x0,0x9a00,0xcf # SEL_SCODE
+ .word 0xffff,0x0,0x9200,0xcf # SEL_SDATA
+ .word 0xffff,0x0,0x9a00,0x0 # SEL_RCODE
+ .word 0xffff,0x0,0x9200,0x0 # SEL_RDATA
+ .word 0xffff,MEM_USR,0xfa00,0xcf# SEL_UCODE
+ .word 0xffff,MEM_USR,0xf200,0xcf# SEL_UDATA
+ .word _TSSLM,MEM_TSS,0x8900,0x0 # SEL_TSS
+gdt.1:
+#
+# Pseudo-descriptors.
+#
+gdtdesc: .word gdt.1-gdt-1,gdt,0x0 # GDT
+idtdesc: .word _IDTLM,MEM_IDT,0x0 # IDT
+ivtdesc: .word 0x400-0x0-1,0x0,0x0 # IVT
+#
+# IDT construction control string.
+#
+idtctl: .byte 0x10, 0x8e # Int 0x0-0xf
+ .word 0x7dfb,intx00 # (exceptions)
+ .byte 0x10, 0x8e # Int 0x10
+ .word 0x1, intx10 # (exception)
+ .byte 0x10, 0x8e # Int 0x20-0x2f
+ .word 0xffff,intx20 # (hardware)
+ .byte 0x1, 0xee # int 0x30
+ .word 0x1, intx30 # (system call)
+ .byte 0x2, 0xee # Int 0x31-0x32
+ .word 0x1, intx31 # (V86, null)
+ .byte 0x0 # End of string
+#
+# Dump format string.
+#
+dmpfmt: .byte '\n' # "\n"
+ .ascii "int" # "int="
+ .byte 0x80|DMP_X32, 0x40 # "00000000 "
+ .ascii "err" # "err="
+ .byte 0x80|DMP_X32, 0x44 # "00000000 "
+ .ascii "efl" # "efl="
+ .byte 0x80|DMP_X32, 0x50 # "00000000 "
+ .ascii "eip" # "eip="
+ .byte 0x80|DMP_X32|DMP_EOL,0x48 # "00000000\n"
+ .ascii "eax" # "eax="
+ .byte 0x80|DMP_X32, 0x34 # "00000000 "
+ .ascii "ebx" # "ebx="
+ .byte 0x80|DMP_X32, 0x28 # "00000000 "
+ .ascii "ecx" # "ecx="
+ .byte 0x80|DMP_X32, 0x30 # "00000000 "
+ .ascii "edx" # "edx="
+ .byte 0x80|DMP_X32|DMP_EOL,0x2c # "00000000\n"
+ .ascii "esi" # "esi="
+ .byte 0x80|DMP_X32, 0x1c # "00000000 "
+ .ascii "edi" # "edi="
+ .byte 0x80|DMP_X32, 0x18 # "00000000 "
+ .ascii "ebp" # "ebp="
+ .byte 0x80|DMP_X32, 0x20 # "00000000 "
+ .ascii "esp" # "esp="
+ .byte 0x80|DMP_X32|DMP_EOL,0x0 # "00000000\n"
+ .ascii "cs" # "cs="
+ .byte 0x80|DMP_X16, 0x4c # "0000 "
+ .ascii "ds" # "ds="
+ .byte 0x80|DMP_X16, 0xc # "0000 "
+ .ascii "es" # "es="
+ .byte 0x80|DMP_X16, 0x8 # "0000 "
+ .ascii " " # " "
+ .ascii "fs" # "fs="
+ .byte 0x80|DMP_X16, 0x10 # "0000 "
+ .ascii "gs" # "gs="
+ .byte 0x80|DMP_X16, 0x14 # "0000 "
+ .ascii "ss" # "ss="
+ .byte 0x80|DMP_X16|DMP_EOL,0x4 # "0000\n"
+ .ascii "cs:eip" # "cs:eip="
+ .byte 0x80|DMP_MEM|DMP_EOL,0x48 # "00 00 ... 00 00\n"
+ .ascii "ss:esp" # "ss:esp="
+ .byte 0x80|DMP_MEM|DMP_EOL,0x0 # "00 00 ... 00 00\n"
+ .asciz "System halted" # End
+#
+# End of BTX memory.
+#
+ .p2align 4
+break:
diff --git a/sys/boot/pc98/btx/btx/btx.m4 b/sys/boot/pc98/btx/btx/btx.m4
new file mode 100644
index 0000000..6526c6b
--- /dev/null
+++ b/sys/boot/pc98/btx/btx/btx.m4
@@ -0,0 +1,59 @@
+#
+# Copyright (c) 1998 Robert Nordier
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms are freely
+# permitted provided that the above copyright notice and this
+# paragraph and the following disclaimer are duplicated in all
+# such forms.
+#
+# This software is provided "AS IS" and without any express or
+# implied warranties, including, without limitation, the implied
+# warranties of merchantability and fitness for a particular
+# purpose.
+#
+
+# $Id: btx.m4,v 1.1.1.1 1998/09/12 04:29:23 rnordier Exp $
+
+define(_al,0x0)dnl
+define(_cl,0x1)dnl
+define(_dl,0x2)dnl
+define(_bl,0x3)dnl
+define(_ah,0x4)dnl
+define(_ch,0x5)dnl
+define(_dh,0x6)dnl
+define(_bh,0x7)dnl
+
+define(_ax,0x0)dnl
+define(_cx,0x1)dnl
+define(_dx,0x2)dnl
+define(_bx,0x3)dnl
+define(_sp,0x4)dnl
+define(_bp,0x5)dnl
+define(_si,0x6)dnl
+define(_di,0x7)dnl
+
+define(_bx_si,0x0)dnl
+define(_bx_di,0x1)dnl
+define(_bp_si,0x2)dnl
+define(_bp_di,0x3)dnl
+define(_si_,0x4)dnl
+define(_di_,0x5)dnl
+define(_bp_,0x6)dnl
+define(_bx_,0x7)dnl
+
+define(o16,`.byte 0x66')dnl
+
+define(addwia,`.byte 0x5; .word $1')dnl
+define(lgdtwm,`.byte 0xf; .byte 0x1; .byte 0x16; .word $1')dnl
+define(lidtwm,`.byte 0xf; .byte 0x1; .byte 0x1e; .word $1')dnl
+define(cmpwmr,`.byte 0x3b; .byte ($2 << 0x3) | 0x6; .word $1')dnl
+define(cmpwir,`.byte 0x81; .byte 0xf8 | $2; .word $1')dnl
+define(movbr1,`.byte 0x88; .byte 0x40 | ($1 << 0x3) | $3; .byte $2')dnl
+define(movwr0,`.byte 0x89; .byte ($1 << 0x3) | $2')dnl
+define(leaw1r,`.byte 0x8d; .byte 0x40 | ($3 << 0x3) | $2; .byte $1')dnl
+define(movwir,`.byte 0xb8 | $2; .word $1')dnl
+define(movbi1,`.byte 0xc6; .byte 0x40 | $3; .byte $2; .byte $1')dnl
+define(callwi,`.byte 0xe8; .word $1 - . - 0x2')dnl
+define(jmpfwi,`.byte 0xea; .word $2; .word $1')dnl
+define(tstbim,`.byte 0xf6; .byte 0x6; .word $2; .byte $1')dnl
diff --git a/sys/boot/pc98/btx/btx/btx.s b/sys/boot/pc98/btx/btx/btx.s
new file mode 100644
index 0000000..b0bd4f2
--- /dev/null
+++ b/sys/boot/pc98/btx/btx/btx.s
@@ -0,0 +1,1071 @@
+#
+# Copyright (c) 1998 Robert Nordier
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms are freely
+# permitted provided that the above copyright notice and this
+# paragraph and the following disclaimer are duplicated in all
+# such forms.
+#
+# This software is provided "AS IS" and without any express or
+# implied warranties, including, without limitation, the implied
+# warranties of merchantability and fitness for a particular
+# purpose.
+#
+
+# $Id: btx.s,v 1.9 1999/01/22 13:07:17 rnordier Exp $
+
+#
+# Memory layout.
+#
+ .set MEM_BTX,0x1000 # Start of BTX memory
+ .set MEM_ESP0,0x1800 # Supervisor stack
+ .set MEM_BUF,0x1800 # Scratch buffer
+ .set MEM_ESP1,0x1e00 # Link stack
+ .set MEM_IDT,0x1e00 # IDT
+ .set MEM_TSS,0x1f98 # TSS
+ .set MEM_MAP,0x2000 # I/O bit map
+ .set MEM_DIR,0x4000 # Page directory
+ .set MEM_TBL,0x5000 # Page tables
+ .set MEM_ORG,0x9000 # BTX code
+ .set MEM_USR,0xa000 # Start of user memory
+#
+# Paging control.
+#
+ .set PAG_SIZ,0x1000 # Page size
+ .set PAG_CNT,0x1000 # Pages to map
+#
+# Segment selectors.
+#
+ .set SEL_SCODE,0x8 # Supervisor code
+ .set SEL_SDATA,0x10 # Supervisor data
+ .set SEL_RCODE,0x18 # Real mode code
+ .set SEL_RDATA,0x20 # Real mode data
+ .set SEL_UCODE,0x28|3 # User code
+ .set SEL_UDATA,0x30|3 # User data
+ .set SEL_TSS,0x38 # TSS
+#
+# Task state segment fields.
+#
+ .set TSS_ESP0,0x4 # PL 0 ESP
+ .set TSS_SS0,0x8 # PL 0 SS
+ .set TSS_ESP1,0xc # PL 1 ESP
+ .set TSS_MAP,0x66 # I/O bit map base
+#
+# System calls.
+#
+ .set SYS_EXIT,0x0 # Exit
+ .set SYS_EXEC,0x1 # Exec
+#
+# V86 constants.
+#
+ .set V86_FLG,0x208eff # V86 flag mask
+ .set V86_STK,0x400 # V86 stack allowance
+#
+# Dump format control bytes.
+#
+ .set DMP_X16,0x1 # Word
+ .set DMP_X32,0x2 # Long
+ .set DMP_MEM,0x4 # Memory
+ .set DMP_EOL,0x8 # End of line
+#
+# Screen defaults and assumptions.
+#
+.`ifdef' PC98
+ .set SCR_MAT,0xe1 # Mode/attribute
+.else
+ .set SCR_MAT,0x7 # Mode/attribute
+.endif
+ .set SCR_COL,0x50 # Columns per row
+ .set SCR_ROW,0x19 # Rows per screen
+#
+# BIOS Data Area locations.
+#
+.`ifdef' PC98
+ .set BDA_MEM,0xa1501 # Free memory
+ .set BDA_POS,0xa153e # Cursor position
+.else
+ .set BDA_MEM,0x413 # Free memory
+ .set BDA_SCR,0x449 # Video mode
+ .set BDA_POS,0x450 # Cursor position
+.endif
+#
+# Derivations, for brevity.
+#
+ .set _ESP0H,MEM_ESP0>>0x8 # Byte 1 of ESP0
+ .set _ESP1H,MEM_ESP1>>0x8 # Byte 1 of ESP1
+ .set _TSSIO,MEM_MAP-MEM_TSS # TSS I/O base
+ .set _TSSLM,MEM_DIR-MEM_TSS-1 # TSS limit
+ .set _IDTLM,MEM_TSS-MEM_IDT-1 # IDT limit
+#
+# Code segment.
+#
+ .globl start
+start: # Start of code
+#
+# BTX header.
+#
+btx_hdr: .byte 0xeb # Machine ID
+ .byte 0xe # Header size
+ .ascii "BTX" # Magic
+ .byte 0x1 # Major version
+ .byte 0x0 # Minor version
+ .byte 0x0 # Flags
+ .word PAG_CNT-MEM_ORG>>0xc # Paging control
+ .word break-start # Text size
+ .long 0x0 # Entry address
+#
+# Initialization routine.
+#
+init: cli # Disable interrupts
+ xorl %eax,%eax # Zero/segment
+ movl %ax,%ss # Set up
+ movwir(MEM_ESP0,_sp) # stack
+ movl %ax,%es # Address
+ movl %ax,%ds # data
+ pushw $0x2 # Clear
+ popfw # flags
+#
+# Initialize memory.
+#
+ movwir(MEM_IDT,_di) # Memory to initialize
+ movwir((MEM_ORG-MEM_IDT)/2,_cx) # Words to zero
+ pushl %edi # Save
+ rep # Zero-fill
+ stosl # memory
+ popl %edi # Restore
+#
+# Create IDT.
+#
+ movwir(idtctl,_si) # Control string
+init.1: lodsb # Get entry
+ cwde # count
+ xchgl %eax,%ecx # as word
+ jecxz init.4 # If done
+ lodsb # Get segment
+ xchgl %eax,%edx # P:DPL:type
+ lodsl # Get control
+ xchgl %eax,%ebx # set
+ lodsl # Get handler offset
+ movb $SEL_SCODE,%dh # Segment selector
+init.2: shrl %ebx # Handle this int?
+ jnc init.3 # No
+ movwr0(_ax,_di_) # Set handler offset
+ movbr1(_dh,0x2,_di_) # and selector
+ movbr1(_dl,0x5,_di_) # Set P:DPL:type
+ addwia(0x4) # Next handler
+init.3: leaw1r(0x8,_di_,_di) # Next entry
+ loop init.2 # Till set done
+ jmp init.1 # Continue
+#
+# Initialize TSS.
+#
+init.4: movbi1(_ESP0H,TSS_ESP0+1,_di_) # Set ESP0
+ movbi1(SEL_SDATA,TSS_SS0,_di_) # Set SS0
+ movbi1(_ESP1H,TSS_ESP1+1,_di_) # Set ESP1
+ movbi1(_TSSIO,TSS_MAP,_di_) # Set I/O bit map base
+#
+# Create page directory.
+#
+ xorw %dx,%dx # Page
+ movb $PAG_SIZ>>0x8,%dh # size
+ xorw %ax,%ax # Zero
+ movwir(MEM_DIR,_di) # Page directory
+ movb $PAG_CNT>>0xa,%cl # Entries
+ movwir(MEM_TBL|0x7,_ax) # First entry
+init.5: stosw # Write entry
+ addl %edx,%eax # To next
+ loop init.5 # Till done
+#
+# Create page tables.
+#
+ movwir(MEM_TBL,_di) # Page table
+ movb $PAG_CNT>>0x8,%ch # Entries
+ xorl %eax,%eax # Start address
+init.6: movb $0x7,%al # Set U:W:P flags
+ cmpwmr(btx_hdr+0x8,_cx) # Standard user page?
+ jb init.7 # Yes
+ cmpwir(PAG_CNT-MEM_BTX>>0xc,_cx)# BTX memory?
+ jae init.7 # No or first page
+ andb $~0x2,%al # Clear W flag
+ cmpwir(PAG_CNT-MEM_USR>>0xc,_cx)# User page zero?
+ jne init.7 # No
+ tstbim(0x80,btx_hdr+0x7) # Unmap it?
+ jz init.7 # No
+ andb $~0x1,%al # Clear P flag
+init.7: stosw # Set entry
+ addw %dx,%ax # Next address
+ loop init.6 # Till done
+#
+# Bring up the system.
+#
+ movwir(0x2820,_bx) # Set protected mode
+ callwi(setpic) # IRQ offsets
+ lidtwm(idtdesc) # Set IDT
+ xorw %ax,%ax # Set base
+ movb $MEM_DIR>>0x8,%ah # of page
+ movl %eax,%cr3 # directory
+ lgdtwm(gdtdesc) # Set GDT
+ movl %cr0,%eax # Switch to
+ o16 # protected mode
+ orl $0x80000001,%eax # and enable
+ movl %eax,%cr0 # paging
+ jmpfwi(SEL_SCODE,init.8) # To 32-bit code
+init.8: xorl %ecx,%ecx # Zero
+ movb $SEL_SDATA,%cl # To 32-bit
+ movl %cx,%ss # stack
+#
+# Launch user task.
+#
+ movb $SEL_TSS,%cl # Set task
+ ltrl %ecx # register
+ movl $MEM_USR,%edx # User base address
+ movzwl %ss:BDA_MEM,%eax # Get free memory
+.`ifdef' PC98
+ andl $0x7,%eax
+ incl %eax
+ shll $0x11,%eax # To bytes
+.else
+ shll $0xa,%eax # To bytes
+.endif
+ subl $0x1000,%eax # Less arg space
+ subl %edx,%eax # Less base
+ movb $SEL_UDATA,%cl # User data selector
+ pushl %ecx # Set SS
+ pushl %eax # Set ESP
+ pushl $0x202 # Set flags (IF set)
+ pushl $SEL_UCODE # Set CS
+ pushl btx_hdr+0xc # Set EIP
+ pushl %ecx # Set GS
+ pushl %ecx # Set FS
+ pushl %ecx # Set DS
+ pushl %ecx # Set ES
+ pushl %edx # Set EAX
+ movb $0x7,%cl # Set remaining
+init.9: pushb $0x0 # general
+ loop init.9 # registers
+ popa # and initialize
+ popl %es # Initialize
+ popl %ds # user
+ popl %fs # segment
+ popl %gs # registers
+ iret # To user mode
+#
+# Exit routine.
+#
+exit: cli # Disable interrupts
+ movl $MEM_ESP0,%esp # Clear stack
+#
+# Turn off paging.
+#
+ movl %cr0,%eax # Get CR0
+ andl $~0x80000000,%eax # Disable
+ movl %eax,%cr0 # paging
+ xorl %ecx,%ecx # Zero
+ movl %ecx,%cr3 # Flush TLB
+#
+# To 16 bits.
+#
+ o16 # Reload
+ jmpfwi(SEL_RCODE,exit.1) # CS
+exit.1: movb $SEL_RDATA,%cl # 16-bit selector
+ movl %cx,%ss # Reload SS
+ movl %cx,%ds # Load
+ movl %cx,%es # remaining
+ movl %cx,%fs # segment
+ movl %cx,%gs # registers
+#
+# To real-address mode.
+#
+ decl %eax # Switch to
+ movl %eax,%cr0 # real mode
+ jmpfwi(0x0,exit.2) # Reload CS
+exit.2: xorl %eax,%eax # Real mode segment
+ movl %ax,%ss # Reload SS
+ movl %ax,%ds # Address data
+.`ifdef' PC98
+ movwir(0x1008,_bx) # Set real mode
+.else
+ movwir(0x7008,_bx) # Set real mode
+.endif
+ callwi(setpic) # IRQ offsets
+ lidtwm(ivtdesc) # Set IVT
+#
+# Reboot or await reset.
+#
+ sti # Enable interrupts
+ tstbim(0x1,btx_hdr+0x7) # Reboot?
+exit.3: jz exit.3 # No
+.`ifdef' PC98
+ movb $0xa0,%al
+ outb %al,$0x35
+ movb 0,%al
+ outb %al,$0xf0
+exit.4: jmp exit.4
+.else
+ int $0x19 # BIOS: Reboot
+.endif
+#
+# Set IRQ offsets by reprogramming 8259A PICs.
+#
+.`ifdef' PC98
+setpic: inb $0x02,%al # Save master
+ pushl %eax # IMR
+ inb $0x0a,%al # Save slave
+ pushl %eax # IMR
+ movb $0x11,%al # ICW1 to
+ outb %al,$0x00 # master,
+ outb %al,$0x08 # slave
+ movb %bl,%al # ICW2 to
+ outb %al,$0x02 # master
+ movb %bh,%al # ICW2 to
+ outb %al,$0x0a # slave
+ movb $0x80,%al # ICW3 to
+ outb %al,$0x02 # master
+ movb $0x7,%al # ICW3 to
+ outb %al,$0x0a # slave
+ movb $0x1d,%al # ICW4 to
+ outb %al,$0x02 # master,
+ movb $0x9,%al # ICW4 to
+ outb %al,$0x0a # slave
+ popl %eax # Restore slave
+ outb %al,$0x0a # IMR
+ popl %eax # Restore master
+ outb %al,$0x02 # IMR
+.else
+setpic: inb $0x21,%al # Save master
+ pushl %eax # IMR
+ inb $0xa1,%al # Save slave
+ pushl %eax # IMR
+ movb $0x11,%al # ICW1 to
+ outb %al,$0x20 # master,
+ outb %al,$0xa0 # slave
+ movb %bl,%al # ICW2 to
+ outb %al,$0x21 # master
+ movb %bh,%al # ICW2 to
+ outb %al,$0xa1 # slave
+ movb $0x4,%al # ICW3 to
+ outb %al,$0x21 # master
+ movb $0x2,%al # ICW3 to
+ outb %al,$0xa1 # slave
+ movb $0x1,%al # ICW4 to
+ outb %al,$0x21 # master,
+ outb %al,$0xa1 # slave
+ popl %eax # Restore slave
+ outb %al,$0xa1 # IMR
+ popl %eax # Restore master
+ outb %al,$0x21 # IMR
+.endif
+ ret # To caller
+#
+# Initiate return from V86 mode to user mode.
+#
+inthlt: hlt # To supervisor mode
+#
+# Exception jump table.
+#
+intx00: pushb $0x0 # Int 0x0: #DE
+ jmp ex_noc # Divide error
+ pushb $0x1 # Int 0x1: #DB
+ jmp ex_noc # Debug
+ pushb $0x3 # Int 0x3: #BP
+ jmp ex_noc # Breakpoint
+ pushb $0x4 # Int 0x4: #OF
+ jmp ex_noc # Overflow
+ pushb $0x5 # Int 0x5: #BR
+ jmp ex_noc # BOUND range exceeded
+ pushb $0x6 # Int 0x6: #UD
+ jmp ex_noc # Invalid opcode
+ pushb $0x7 # Int 0x7: #NM
+ jmp ex_noc # Device not available
+ pushb $0x8 # Int 0x8: #DF
+ jmp except # Double fault
+ pushb $0xa # Int 0xa: #TS
+ jmp except # Invalid TSS
+ pushb $0xb # Int 0xb: #NP
+ jmp except # Segment not present
+ pushb $0xc # Int 0xc: #SS
+ jmp except # Stack segment fault
+ pushb $0xd # Int 0xd: #GP
+ jmp ex_v86 # General protection
+ pushb $0xe # Int 0xe: #PF
+ jmp except # Page fault
+intx10: pushb $0x10 # Int 0x10: #MF
+ jmp ex_noc # Floating-point error
+#
+# Handle #GP exception.
+#
+ex_v86: testb $0x2,0x12(%esp,1) # V86 mode?
+ jz except # No
+ jmp v86mon # To monitor
+#
+# Save a zero error code.
+#
+ex_noc: pushl (%esp,1) # Duplicate int no
+ movb $0x0,0x4(%esp,1) # Fake error code
+#
+# Handle exception.
+#
+except: cld # String ops inc
+ pushl %ds # Save
+ pushl %es # most
+ pusha # registers
+ movb $0x6,%al # Push loop count
+ testb $0x2,0x3a(%esp,1) # V86 mode?
+ jnz except.1 # Yes
+ pushl %gs # Set GS
+ pushl %fs # Set FS
+ pushl %ds # Set DS
+ pushl %es # Set ES
+ movb $0x2,%al # Push loop count
+ cmpw $SEL_SCODE,0x44(%esp,1) # Supervisor mode?
+ jne except.1 # No
+ pushl %ss # Set SS
+ leal 0x50(%esp,1),%eax # Set
+ pushl %eax # ESP
+ jmp except.2 # Join common code
+except.1: pushl 0x50(%esp,1) # Set GS, FS, DS, ES
+ decb %al # (if V86 mode), and
+ jne except.1 # SS, ESP
+except.2: pushl $SEL_SDATA # Set up
+ popl %ds # to
+ pushl %ds # address
+ popl %es # data
+ movl %esp,%ebx # Stack frame
+ movl $dmpfmt,%esi # Dump format string
+ movl $MEM_BUF,%edi # Buffer
+.`ifdef' PC98
+ pushl %eax
+ pushl %edx
+wait.1:
+ inb $0x60,%al
+ testb $0x04,%al
+ jz wait.1
+ movb $0xe0,%al
+ outb %al,$0x62
+wait.2:
+ inb $0x60,%al
+ testb $0x01,%al
+ jz wait.2
+ xorl %edx,%edx
+ inb $0x62,%al
+ movb %al,%dl
+ inb $0x62,%al
+ movb %al,%dh
+ inb $0x62,%al
+ inb $0x62,%al
+ inb $0x62,%al
+ movl %edx,%eax
+ shlw $1,%ax
+ movl $BDA_POS,%edx
+ movw %ax,(%edx)
+ popl %edx
+ popl %eax
+.endif
+ pushl %edi # Dump to
+ call dump # buffer
+ popl %esi # and
+ call putstr # display
+ leal 0x18(%esp,1),%esp # Discard frame
+ popa # Restore
+ popl %es # registers
+ popl %ds # saved
+ cmpb $0x3,(%esp,1) # Breakpoint?
+ je except.3 # Yes
+ jmp exit # Exit
+except.3: leal 0x8(%esp,1),%esp # Discard err, int no
+ iret # From interrupt
+#
+# Return to user mode from V86 mode.
+#
+intrtn: cld # String ops inc
+ pushl %ds # Address
+ popl %es # data
+ leal 0x3c(%ebp),%edx # V86 Segment registers
+ movl MEM_TSS+TSS_ESP1,%esi # Link stack pointer
+ lodsl # INT_V86 args pointer
+ movl %esi,%ebx # Saved exception frame
+ testl %eax,%eax # INT_V86 args?
+ jz intrtn.2 # No
+ movl $MEM_USR,%edi # User base
+ movl 0x1c(%esi),%ebx # User ESP
+ movl %eax,(%edi,%ebx,1) # Restore to user stack
+ leal 0x8(%edi,%eax,1),%edi # Arg segment registers
+ testb $0x4,-0x6(%edi) # Return flags?
+ jz intrtn.1 # No
+ movl 0x30(%ebp),%eax # Get V86 flags
+ movw %ax,0x18(%esi) # Set user flags
+intrtn.1: leal 0x10(%esi),%ebx # Saved exception frame
+ xchgl %edx,%esi # Segment registers
+ movb $0x4,%cl # Update seg regs
+ rep # in INT_V86
+ movsl # args
+intrtn.2: movl %edx,%esi # Segment registers
+ leal 0x28(%ebp),%edi # Set up seg
+ movb $0x4,%cl # regs for
+ rep # later
+ movsl # pop
+ movl %ebx,%esi # Restore exception
+ movb $0x5,%cl # frame to
+ rep # supervisor
+ movsl # stack
+ movl %esi,MEM_TSS+TSS_ESP1 # Link stack pointer
+ popa # Restore
+ leal 0x8(%esp,1),%esp # Discard err, int no
+ popl %es # Restore
+ popl %ds # user
+ popl %fs # segment
+ popl %gs # registers
+ iret # To user mode
+#
+# V86 monitor.
+#
+v86mon: cld # String ops inc
+ pushl $SEL_SDATA # Set up for
+ popl %ds # flat addressing
+ pusha # Save registers
+ movl %esp,%ebp # Address stack frame
+ movzwl 0x2c(%ebp),%edi # Load V86 CS
+ shll $0x4,%edi # To linear
+ movl 0x28(%ebp),%esi # Load V86 IP
+ addl %edi,%esi # Code pointer
+ xorl %ecx,%ecx # Zero
+ movb $0x2,%cl # 16-bit operands
+ xorl %eax,%eax # Zero
+v86mon.1: lodsb # Get opcode
+ cmpb $0x66,%al # Operand size prefix?
+ jne v86mon.2 # No
+ movb $0x4,%cl # 32-bit operands
+ jmp v86mon.1 # Continue
+v86mon.2: cmpb $0xf4,%al # HLT?
+ jne v86mon.3 # No
+ cmpl $inthlt+0x1,%esi # Is inthlt?
+ jne v86mon.6 # No (ignore)
+ jmp intrtn # Return to user mode
+v86mon.3: cmpb $0xfa,%al # CLI?
+ je v86cli # Yes
+ cmpb $0xfb,%al # STI?
+ je v86sti # Yes
+ movzwl 0x38(%ebp),%ebx # Load V86 SS
+ shll $0x4,%ebx # To offset
+ pushl %ebx # Save
+ addl 0x34(%ebp),%ebx # Add V86 SP
+ movl 0x30(%ebp),%edx # Load V86 flags
+ cmpb $0x9c,%al # PUSHF/PUSHFD?
+ je v86pushf # Yes
+ cmpb $0x9d,%al # POPF/POPFD?
+ je v86popf # Yes
+ cmpb $0xcd,%al # INT imm8?
+ je v86intn # Yes
+ cmpb $0xcf,%al # IRET/IRETD?
+ je v86iret # Yes
+ popl %ebx # Restore
+ popa # Restore
+ jmp except # Handle exception
+v86mon.4: movl %edx,0x30(%ebp) # Save V86 flags
+v86mon.5: popl %edx # V86 SS adjustment
+ subl %edx,%ebx # Save V86
+ movl %ebx,0x34(%ebp) # SP
+v86mon.6: subl %edi,%esi # From linear
+ movl %esi,0x28(%ebp) # Save V86 IP
+ popa # Restore
+ leal 0x8(%esp,1),%esp # Discard int no, error
+ iret # To V86 mode
+#
+# Emulate CLI.
+#
+v86cli: andb $~0x2,0x31(%ebp) # Clear IF
+ jmp v86mon.6 # Finish up
+#
+# Emulate STI.
+#
+v86sti: orb $0x2,0x31(%ebp) # Set IF
+ jmp v86mon.6 # Finish up
+#
+# Emulate PUSHF/PUSHFD.
+#
+v86pushf: subl %ecx,%ebx # Adjust SP
+ cmpb $0x4,%cl # 32-bit
+ je v86pushf.1 # Yes
+ o16 # 16-bit
+v86pushf.1: movl %edx,(%ebx) # Save flags
+ jmp v86mon.5 # Finish up
+#
+# Emulate IRET/IRETD.
+#
+v86iret: movzwl (%ebx),%esi # Load V86 IP
+ movzwl 0x2(%ebx),%edi # Load V86 CS
+ leal 0x4(%ebx),%ebx # Adjust SP
+ movl %edi,0x2c(%ebp) # Save V86 CS
+ xorl %edi,%edi # No ESI adjustment
+#
+# Emulate POPF/POPFD (and remainder of IRET/IRETD).
+#
+v86popf: cmpb $0x4,%cl # 32-bit?
+ je v86popf.1 # Yes
+ movl %edx,%eax # Initialize
+ o16 # 16-bit
+v86popf.1: movl (%ebx),%eax # Load flags
+ addl %ecx,%ebx # Adjust SP
+ andl $V86_FLG,%eax # Merge
+ andl $~V86_FLG,%edx # the
+ orl %eax,%edx # flags
+ jmp v86mon.4 # Finish up
+#
+# Emulate INT imm8.
+#
+v86intn: lodsb # Get int no
+ subl %edi,%esi # From
+ shrl $0x4,%edi # linear
+ movw %dx,-0x2(%ebx) # Save flags
+ movw %di,-0x4(%ebx) # Save CS
+ leal -0x6(%ebx),%ebx # Adjust SP
+ movw %si,(%ebx) # Save IP
+ shll $0x2,%eax # Scale
+ movzwl (%eax),%esi # Load IP
+ movzwl 0x2(%eax),%edi # Load CS
+ movl %edi,0x2c(%ebp) # Save CS
+ xorl %edi,%edi # No ESI adjustment
+ andb $~0x3,%dh # Clear IF and TF
+ jmp v86mon.4 # Finish up
+#
+# Hardware interrupt jump table.
+#
+intx20: pushb $0x8 # Int 0x20: IRQ0
+ jmp int_hw # V86 int 0x8
+ pushb $0x9 # Int 0x21: IRQ1
+ jmp int_hw # V86 int 0x9
+ pushb $0xa # Int 0x22: IRQ2
+ jmp int_hw # V86 int 0xa
+ pushb $0xb # Int 0x23: IRQ3
+ jmp int_hw # V86 int 0xb
+ pushb $0xc # Int 0x24: IRQ4
+ jmp int_hw # V86 int 0xc
+ pushb $0xd # Int 0x25: IRQ5
+ jmp int_hw # V86 int 0xd
+ pushb $0xe # Int 0x26: IRQ6
+ jmp int_hw # V86 int 0xe
+ pushb $0xf # Int 0x27: IRQ7
+ jmp int_hw # V86 int 0xf
+.`ifdef' PC98
+ pushb $0x10 # Int 0x28: IRQ8
+ jmp int_hw # V86 int 0x10
+ pushb $0x11 # Int 0x29: IRQ9
+ jmp int_hw # V86 int 0x11
+ pushb $0x12 # Int 0x2a: IRQ10
+ jmp int_hw # V86 int 0x12
+ pushb $0x13 # Int 0x2b: IRQ11
+ jmp int_hw # V86 int 0x13
+ pushb $0x14 # Int 0x2c: IRQ12
+ jmp int_hw # V86 int 0x14
+ pushb $0x15 # Int 0x2d: IRQ13
+ jmp int_hw # V86 int 0x15
+ pushb $0x16 # Int 0x2e: IRQ14
+ jmp int_hw # V86 int 0x16
+ pushb $0x17 # Int 0x2f: IRQ15
+ jmp int_hw # V86 int 0x17
+.else
+ pushb $0x70 # Int 0x28: IRQ8
+ jmp int_hw # V86 int 0x70
+ pushb $0x71 # Int 0x29: IRQ9
+ jmp int_hw # V86 int 0x71
+ pushb $0x72 # Int 0x2a: IRQ10
+ jmp int_hw # V86 int 0x72
+ pushb $0x73 # Int 0x2b: IRQ11
+ jmp int_hw # V86 int 0x73
+ pushb $0x74 # Int 0x2c: IRQ12
+ jmp int_hw # V86 int 0x74
+ pushb $0x75 # Int 0x2d: IRQ13
+ jmp int_hw # V86 int 0x75
+ pushb $0x76 # Int 0x2e: IRQ14
+ jmp int_hw # V86 int 0x76
+ pushb $0x77 # Int 0x2f: IRQ15
+ jmp int_hw # V86 int 0x77
+.endif
+#
+# Reflect hardware interrupts.
+#
+int_hw: testb $0x2,0xe(%esp,1) # V86 mode?
+ jz intusr # No
+ pushl $SEL_SDATA # Address
+ popl %ds # data
+ xchgl %eax,(%esp,1) # Swap EAX, int no
+ pushl %ebp # Address
+ movl %esp,%ebp # stack frame
+ pushl %ebx # Save
+ shll $0x2,%eax # Get int
+ movl (%eax),%eax # vector
+ subl $0x6,0x14(%ebp) # Adjust V86 ESP
+ movzwl 0x18(%ebp),%ebx # V86 SS
+ shll $0x4,%ebx # * 0x10
+ addl 0x14(%ebp),%ebx # + V86 ESP
+ xchgw %ax,0x8(%ebp) # Swap V86 IP
+ rorl $0x10,%eax # Swap words
+ xchgw %ax,0xc(%ebp) # Swap V86 CS
+ roll $0x10,%eax # Swap words
+ movl %eax,(%ebx) # CS:IP for IRET
+ movl 0x10(%ebp),%eax # V86 flags
+ movw %ax,0x4(%ebx) # Flags for IRET
+ andb $~0x3,0x11(%ebp) # Clear IF, TF
+ popl %ebx # Restore
+ popl %ebp # saved
+ popl %eax # registers
+ iret # To V86 mode
+#
+# Invoke V86 interrupt from user mode, with arguments.
+#
+intx31: stc # Have btx_v86
+ pushl %eax # Missing int no
+#
+# Invoke V86 interrupt from user mode.
+#
+intusr: std # String ops dec
+ pushl %eax # Expand
+ pushl %eax # stack
+ pushl %eax # frame
+ pusha # Save
+ pushl %gs # Save
+ movl %esp,%eax # seg regs
+ pushl %fs # and
+ pushl %ds # point
+ pushl %es # to them
+ pushb $SEL_SDATA # Set up
+ popl %ds # to
+ pushl %ds # address
+ popl %es # data
+ movl $MEM_USR,%ebx # User base
+ movl %ebx,%edx # address
+ jc intusr.1 # If btx_v86
+ xorl %edx,%edx # Control flags
+ xorl %ebp,%ebp # btx_v86 pointer
+intusr.1: leal 0x50(%esp,1),%esi # Base of frame
+ pushl %esi # Save
+ addl -0x4(%esi),%ebx # User ESP
+ movl MEM_TSS+TSS_ESP1,%edi # Link stack pointer
+ leal -0x4(%edi),%edi # Adjust for push
+ xorl %ecx,%ecx # Zero
+ movb $0x5,%cl # Push exception
+ rep # frame on
+ movsl # link stack
+ xchgl %eax,%esi # Saved seg regs
+ movl 0x40(%esp,1),%eax # Get int no
+ testl %edx,%edx # Have btx_v86?
+ jz intusr.2 # No
+ movl (%ebx),%ebp # btx_v86 pointer
+ movb $0x4,%cl # Count
+ addl %ecx,%ebx # Adjust for pop
+ rep # Push saved seg regs
+ movsl # on link stack
+ addl %ebp,%edx # Flatten btx_v86 ptr
+ leal 0x14(%edx),%esi # Seg regs pointer
+ movl 0x4(%edx),%eax # Get int no/address
+ movzwl 0x2(%edx),%edx # Get control flags
+intusr.2: movl %ebp,(%edi) # Push btx_v86 and
+ movl %edi,MEM_TSS+TSS_ESP1 # save link stack ptr
+ popl %edi # Base of frame
+ xchgl %eax,%ebp # Save intno/address
+ movl 0x48(%esp,1),%eax # Get flags
+ testb $0x2,%dl # Simulate CALLF?
+ jnz intusr.3 # Yes
+ decl %ebx # Push flags
+ decl %ebx # on V86
+ movw %ax,(%ebx) # stack
+intusr.3: movb $0x4,%cl # Count
+ subl %ecx,%ebx # Push return address
+ movl $inthlt,(%ebx) # on V86 stack
+ rep # Copy seg regs to
+ movsl # exception frame
+ xchgl %eax,%ecx # Save flags
+ movl %ebx,%eax # User ESP
+ subl $V86_STK,%eax # Less bytes
+ ja intusr.4 # to
+ xorl %eax,%eax # keep
+intusr.4: shrl $0x4,%eax # Gives segment
+ stosl # Set SS
+ shll $0x4,%eax # To bytes
+ xchgl %eax,%ebx # Swap
+ subl %ebx,%eax # Gives offset
+ stosl # Set ESP
+ xchgl %eax,%ecx # Get flags
+ btsl $0x11,%eax # Set VM
+ andb $~0x3,%ah # Clear IF and TF
+ stosl # Set EFL
+ xchgl %eax,%ebp # Get int no/address
+ testb $0x1,%dl # Address?
+ jnz intusr.5 # Yes
+ shll $0x2,%eax # Scale
+ movl (%eax),%eax # Load int vector
+intusr.5: movl %eax,%ecx # Save
+ shrl $0x10,%eax # Gives segment
+ stosl # Set CS
+ movw %cx,%ax # Restore
+ stosl # Set EIP
+ leal 0x10(%esp,1),%esp # Discard seg regs
+ popa # Restore
+ iret # To V86 mode
+#
+# System Call.
+#
+intx30: cmpl $SYS_EXEC,%eax # Exec system call?
+ jne intx30.1 # No
+ pushl %ss # Set up
+ popl %es # all
+ pushl %es # segment
+ popl %ds # registers
+ pushl %ds # for the
+ popl %fs # program
+ pushl %fs # we're
+ popl %gs # invoking
+ movl $MEM_USR,%eax # User base address
+ addl 0xc(%esp,1),%eax # Change to user
+ leal 0x4(%eax),%esp # stack
+ movl %cr0,%eax # Turn
+ andl $~0x80000000,%eax # off
+ movl %eax,%cr0 # paging
+ xorl %eax,%eax # Flush
+ movl %eax,%cr3 # TLB
+ popl %eax # Call
+ call *%eax # program
+intx30.1: incb %ss:btx_hdr+0x7 # Flag reboot
+ jmp exit # Exit
+#
+# Dump structure [EBX] to [EDI], using format string [ESI].
+#
+dump.0: stosb # Save char
+dump: lodsb # Load char
+ testb %al,%al # End of string?
+ jz dump.10 # Yes
+ testb $0x80,%al # Control?
+ jz dump.0 # No
+ movb %al,%ch # Save control
+ movb $'=',%al # Append
+ stosb # '='
+ lodsb # Get offset
+ pushl %esi # Save
+ movsbl %al,%esi # To
+ addl %ebx,%esi # pointer
+ testb $DMP_X16,%ch # Dump word?
+ jz dump.1 # No
+ lodsw # Get and
+ call hex16 # dump it
+dump.1: testb $DMP_X32,%ch # Dump long?
+ jz dump.2 # No
+ lodsl # Get and
+ call hex32 # dump it
+dump.2: testb $DMP_MEM,%ch # Dump memory?
+ jz dump.8 # No
+ pushl %ds # Save
+ testb $0x2,0x52(%ebx) # V86 mode?
+ jnz dump.3 # Yes
+ verrl 0x4(%esi) # Readable selector?
+ jnz dump.3 # No
+ ldsl (%esi),%esi # Load pointer
+ jmp dump.4 # Join common code
+dump.3: lodsl # Set offset
+ xchgl %eax,%edx # Save
+ lodsl # Get segment
+ shll $0x4,%eax # * 0x10
+ addl %edx,%eax # + offset
+ xchgl %eax,%esi # Set pointer
+dump.4: movb $0x10,%cl # Bytes to dump
+dump.5: lodsb # Get byte and
+ call hex8 # dump it
+ decb %cl # Keep count
+ jz dump.7 # If done
+ movb $'-',%al # Separator
+ cmpb $0x8,%cl # Half way?
+ je dump.6 # Yes
+ movb $' ',%al # Use space
+dump.6: stosb # Save separator
+ jmp dump.5 # Continue
+dump.7: popl %ds # Restore
+dump.8: popl %esi # Restore
+ movb $0xa,%al # Line feed
+ testb $DMP_EOL,%ch # End of line?
+ jnz dump.9 # Yes
+ movb $' ',%al # Use spaces
+ stosb # Save one
+dump.9: jmp dump.0 # Continue
+dump.10: stosb # Terminate string
+ ret # To caller
+#
+# Convert EAX, AX, or AL to hex, saving the result to [EDI].
+#
+hex32: pushl %eax # Save
+ shrl $0x10,%eax # Do upper
+ call hex16 # 16
+ popl %eax # Restore
+hex16: call hex16.1 # Do upper 8
+hex16.1: xchgb %ah,%al # Save/restore
+hex8: pushl %eax # Save
+ shrb $0x4,%al # Do upper
+ call hex8.1 # 4
+ popl %eax # Restore
+hex8.1: andb $0xf,%al # Get lower 4
+ cmpb $0xa,%al # Convert
+ sbbb $0x69,%al # to hex
+ das # digit
+ orb $0x20,%al # To lower case
+ stosb # Save char
+ ret # (Recursive)
+#
+# Output zero-terminated string [ESI] to the console.
+#
+putstr.0: call putchr # Output char
+putstr: lodsb # Load char
+ testb %al,%al # End of string?
+ jnz putstr.0 # No
+ ret # To caller
+#
+# Output character AL to the console.
+#
+putchr: pusha # Save
+ xorl %ecx,%ecx # Zero for loops
+ movb $SCR_MAT,%ah # Mode/attribute
+ movl $BDA_POS,%ebx # BDA pointer
+ movw (%ebx),%dx # Cursor position
+.`ifdef' PC98
+ movl $0xa0000,%edi
+.else
+ movl $0xb8000,%edi # Regen buffer (color)
+ cmpb %ah,BDA_SCR-BDA_POS(%ebx) # Mono mode?
+ jne putchr.1 # No
+ xorw %di,%di # Regen buffer (mono)
+.endif
+putchr.1: cmpb $0xa,%al # New line?
+ je putchr.2 # Yes
+.`ifdef' PC98
+ movw %dx,%cx
+ movb %al,(%edi,%ecx,1) # Write char
+ addl $0x2000,%ecx
+ movb %ah,(%edi,%ecx,1) # Write attr
+ addw $0x02,%dx
+ jmp putchr.3
+putchr.2: movw %dx,%ax
+ movb $SCR_COL*2,%dl
+ div %dl
+ incb %al
+ mul %dl
+ movw %ax,%dx
+putchr.3: cmpw $SCR_ROW*SCR_COL*2,%dx
+.else
+ xchgl %eax,%ecx # Save char
+ movb $SCR_COL,%al # Columns per row
+ mulb %dh # * row position
+ addb %dl,%al # + column
+ adcb $0x0,%ah # position
+ shll %eax # * 2
+ xchgl %eax,%ecx # Swap char, offset
+ movw %ax,(%edi,%ecx,1) # Write attr:char
+ incl %edx # Bump cursor
+ cmpb $SCR_COL,%dl # Beyond row?
+ jb putchr.3 # No
+putchr.2: xorb %dl,%dl # Zero column
+ incb %dh # Bump row
+putchr.3: cmpb $SCR_ROW,%dh # Beyond screen?
+.endif
+ jb putchr.4 # No
+ leal 2*SCR_COL(%edi),%esi # New top line
+ movw $(SCR_ROW-1)*SCR_COL/2,%cx # Words to move
+ rep # Scroll
+ movsl # screen
+ movb $' ',%al # Space
+.`ifdef' PC98
+ xorb %ah,%ah
+.endif
+ movb $SCR_COL,%cl # Columns to clear
+ rep # Clear
+ stosw # line
+.`ifdef' PC98
+ movw $(SCR_ROW-1)*SCR_COL*2,%dx
+.else
+ movb $SCR_ROW-1,%dh # Bottom line
+.endif
+putchr.4: movw %dx,(%ebx) # Update position
+ popa # Restore
+ ret # To caller
+
+ .p2align 4
+#
+# Global descriptor table.
+#
+gdt: .word 0x0,0x0,0x0,0x0 # Null entry
+ .word 0xffff,0x0,0x9a00,0xcf # SEL_SCODE
+ .word 0xffff,0x0,0x9200,0xcf # SEL_SDATA
+ .word 0xffff,0x0,0x9a00,0x0 # SEL_RCODE
+ .word 0xffff,0x0,0x9200,0x0 # SEL_RDATA
+ .word 0xffff,MEM_USR,0xfa00,0xcf# SEL_UCODE
+ .word 0xffff,MEM_USR,0xf200,0xcf# SEL_UDATA
+ .word _TSSLM,MEM_TSS,0x8900,0x0 # SEL_TSS
+gdt.1:
+#
+# Pseudo-descriptors.
+#
+gdtdesc: .word gdt.1-gdt-1,gdt,0x0 # GDT
+idtdesc: .word _IDTLM,MEM_IDT,0x0 # IDT
+ivtdesc: .word 0x400-0x0-1,0x0,0x0 # IVT
+#
+# IDT construction control string.
+#
+idtctl: .byte 0x10, 0x8e # Int 0x0-0xf
+ .word 0x7dfb,intx00 # (exceptions)
+ .byte 0x10, 0x8e # Int 0x10
+ .word 0x1, intx10 # (exception)
+ .byte 0x10, 0x8e # Int 0x20-0x2f
+ .word 0xffff,intx20 # (hardware)
+ .byte 0x1, 0xee # int 0x30
+ .word 0x1, intx30 # (system call)
+ .byte 0x2, 0xee # Int 0x31-0x32
+ .word 0x1, intx31 # (V86, null)
+ .byte 0x0 # End of string
+#
+# Dump format string.
+#
+dmpfmt: .byte '\n' # "\n"
+ .ascii "int" # "int="
+ .byte 0x80|DMP_X32, 0x40 # "00000000 "
+ .ascii "err" # "err="
+ .byte 0x80|DMP_X32, 0x44 # "00000000 "
+ .ascii "efl" # "efl="
+ .byte 0x80|DMP_X32, 0x50 # "00000000 "
+ .ascii "eip" # "eip="
+ .byte 0x80|DMP_X32|DMP_EOL,0x48 # "00000000\n"
+ .ascii "eax" # "eax="
+ .byte 0x80|DMP_X32, 0x34 # "00000000 "
+ .ascii "ebx" # "ebx="
+ .byte 0x80|DMP_X32, 0x28 # "00000000 "
+ .ascii "ecx" # "ecx="
+ .byte 0x80|DMP_X32, 0x30 # "00000000 "
+ .ascii "edx" # "edx="
+ .byte 0x80|DMP_X32|DMP_EOL,0x2c # "00000000\n"
+ .ascii "esi" # "esi="
+ .byte 0x80|DMP_X32, 0x1c # "00000000 "
+ .ascii "edi" # "edi="
+ .byte 0x80|DMP_X32, 0x18 # "00000000 "
+ .ascii "ebp" # "ebp="
+ .byte 0x80|DMP_X32, 0x20 # "00000000 "
+ .ascii "esp" # "esp="
+ .byte 0x80|DMP_X32|DMP_EOL,0x0 # "00000000\n"
+ .ascii "cs" # "cs="
+ .byte 0x80|DMP_X16, 0x4c # "0000 "
+ .ascii "ds" # "ds="
+ .byte 0x80|DMP_X16, 0xc # "0000 "
+ .ascii "es" # "es="
+ .byte 0x80|DMP_X16, 0x8 # "0000 "
+ .ascii " " # " "
+ .ascii "fs" # "fs="
+ .byte 0x80|DMP_X16, 0x10 # "0000 "
+ .ascii "gs" # "gs="
+ .byte 0x80|DMP_X16, 0x14 # "0000 "
+ .ascii "ss" # "ss="
+ .byte 0x80|DMP_X16|DMP_EOL,0x4 # "0000\n"
+ .ascii "cs:eip" # "cs:eip="
+ .byte 0x80|DMP_MEM|DMP_EOL,0x48 # "00 00 ... 00 00\n"
+ .ascii "ss:esp" # "ss:esp="
+ .byte 0x80|DMP_MEM|DMP_EOL,0x0 # "00 00 ... 00 00\n"
+ .asciz "System halted" # End
+#
+# End of BTX memory.
+#
+ .p2align 4
+break:
diff --git a/sys/boot/pc98/btx/btxldr/Makefile b/sys/boot/pc98/btx/btxldr/Makefile
new file mode 100644
index 0000000..5bd155c
--- /dev/null
+++ b/sys/boot/pc98/btx/btxldr/Makefile
@@ -0,0 +1,26 @@
+# $Id: Makefile,v 1.6 1998/10/30 00:11:35 msmith Exp $
+
+ORG=0x100000
+#AFLAGS+= -x assembler-with-cpp
+
+#AFLAGS+= --defsym PC98=1 --defsym BTXLDR_VERBOSE=1
+AFLAGS+= --defsym PC98=1
+
+all: btxldr
+
+btxldr: btxldr.o
+.if ${OBJFORMAT} == aout
+ ${LD} -nostdlib -N -s -T ${ORG} -o btxldr.out btxldr.o
+ dd if=btxldr.out of=${.TARGET} ibs=32 skip=1
+.else
+ ${LD} -N -e start -Ttext ${ORG} -o btxldr.out btxldr.o
+ objcopy -S -O binary btxldr.out ${.TARGET}
+.endif
+
+btxldr.o: btxldr.s
+# ${CC} ${AFLAGS} -c -o ${.TARGET} ${.CURDIR}/btxldr.s
+ ${AS} ${AFLAGS} -o ${.TARGET} ${.CURDIR}/btxldr.s
+
+CLEANFILES+= btxldr btxldr.out btxldr.o
+
+.include <bsd.prog.mk>
diff --git a/sys/boot/pc98/btx/btxldr/btxldr.S b/sys/boot/pc98/btx/btxldr/btxldr.S
new file mode 100644
index 0000000..6217eb2
--- /dev/null
+++ b/sys/boot/pc98/btx/btxldr/btxldr.S
@@ -0,0 +1,459 @@
+#
+# Copyright (c) 1998 Robert Nordier
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms are freely
+# permitted provided that the above copyright notice and this
+# paragraph and the following disclaimer are duplicated in all
+# such forms.
+#
+# This software is provided "AS IS" and without any express or
+# implied warranties, including, without limitation, the implied
+# warranties of merchantability and fitness for a particular
+# purpose.
+#
+
+# $Id: btxldr.s,v 1.5 1999/01/22 13:07:17 rnordier Exp $
+
+#
+# Prototype BTX loader program, written in a couple of hours. The
+# real thing should probably be more flexible, and in C.
+#
+
+#
+# Memory locations.
+#
+ .set MEM_STUB,0x600 # Real mode stub
+ .set MEM_ESP,0x1000 # New stack pointer
+ .set MEM_TBL,0x5000 # BTX page tables
+ .set MEM_ENTRY,0x9010 # BTX entry point
+ .set MEM_DATA,0x101000 # Data segment
+#
+# Segment selectors.
+#
+ .set SEL_SCODE,0x8 # 4GB code
+ .set SEL_SDATA,0x10 # 4GB data
+ .set SEL_RCODE,0x18 # 64K code
+ .set SEL_RDATA,0x20 # 64K data
+#
+# Paging constants.
+#
+ .set PAG_SIZ,0x1000 # Page size
+ .set PAG_ENT,0x4 # Page entry size
+#
+# Screen constants.
+#
+.ifdef PC98
+ .set SCR_MAT,0xe1 # Mode/attribute
+.else
+ .set SCR_MAT,0x7 # Mode/attribute
+.endif
+ .set SCR_COL,0x50 # Columns per row
+ .set SCR_ROW,0x19 # Rows per screen
+#
+# BIOS Data Area locations.
+#
+.ifdef PC98
+ .set BDA_MEM,0xa1501 # Free memory
+ .set BDA_POS,0xa153e # Cursor position
+.else
+ .set BDA_MEM,0x413 # Free memory
+ .set BDA_SCR,0x449 # Video mode
+ .set BDA_POS,0x450 # Cursor position
+.endif
+#
+# Required by aout gas inadequacy.
+#
+ .set SIZ_STUB,0x1a # Size of stub
+#
+# We expect to be loaded by boot2 at 0x100000.
+#
+ .globl start
+#
+# BTX program loader for ELF clients.
+#
+start: cld # String ops inc
+.ifdef PC98
+ cli
+gdcwait.1: inb $0x60,%al
+ testb $0x04,%al
+ jz gdcwait.1
+ movb $0xe0,%al
+ outb %al,$0x62
+ nop
+gdcwait.2: inb $0x60,%al
+ testb $0x01,%al
+ jz gdcwait.2
+ inb $0x62,%al
+ movb %al,%dl
+ inb $0x62,%al
+ movb %al,%dh
+ inb $0x62,%al
+ inb $0x62,%al
+ inb $0x62,%al
+ shlw $1,%dx
+ movl $BDA_POS,%ebx
+ movw %dx,(%ebx)
+.endif
+ movl $m_logo,%esi # Identify
+ call putstr # ourselves
+ movzwl BDA_MEM,%eax # Get base memory
+.ifdef PC98
+ andl $0x7,%eax
+ incl %eax
+ shll $0x11,%eax # in bytes
+.else
+ shll $0xa,%eax # in bytes
+.endif
+ movl %eax,%ebp # Base of user stack
+ movl $m_mem,%esi # Display
+ call dhexout # amount of
+ call dputstr # base memory
+ lgdt gdtdesc # Load new GDT
+#
+# Relocate caller's arguments.
+#
+ movl $m_esp,%esi # Display
+ movl %esp,%eax # caller's
+ call dhexout # stack
+ call dputstr # pointer
+ movl $m_args,%esi # Format string
+ leal 0x4(%esp,1),%ebx # First argument
+ movl $0x6,%ecx # Count
+start.1: movl (%ebx),%eax # Get argument and
+ addl $0x4,%ebx # bump pointer
+ call dhexout # Display it
+ loop start.1 # Till done
+ call dputstr # End message
+ movl $0x48,%ecx # Allocate space
+ subl %ecx,%ebp # for bootinfo
+ movl 0x18(%esp,1),%esi # Source
+ movl %ebp,%edi # Destination
+ rep # Copy
+ movsb # it
+ movl %ebp,0x18(%esp,1) # Update pointer
+ movl $m_rel_bi,%esi # Display
+ movl %ebp,%eax # bootinfo
+ call dhexout # relocation
+ call dputstr # message
+ movl $0x18,%ecx # Allocate space
+ subl %ecx,%ebp # for arguments
+ leal 0x4(%esp,1),%esi # Source
+ movl %ebp,%edi # Destination
+ rep # Copy
+ movsb # them
+ movl $m_rel_args,%esi # Display
+ movl %ebp,%eax # argument
+ call dhexout # relocation
+ call dputstr # message
+#
+# Set up BTX kernel.
+#
+ movl $MEM_ESP,%esp # Set up new stack
+ movl $MEM_DATA,%ebx # Data segment
+ movl $m_vers,%esi # Display BTX
+ call putstr # version message
+ movb 0x5(%ebx),%al # Get major version
+ addb $'0',%al # Display
+ call putchr # it
+ movb $'.',%al # And a
+ call putchr # dot
+ movb 0x6(%ebx),%al # Get minor
+ xorb %ah,%ah # version
+ movb $0xa,%dl # Divide
+ divb %dl,%al # by 10
+ addb $'0',%al # Display
+ call putchr # tens
+ movb %ah,%al # Get units
+ addb $'0',%al # Display
+ call putchr # units
+ call putstr # End message
+ movl %ebx,%esi # BTX image
+ movzwl 0x8(%ebx),%edi # Compute
+ orl $PAG_SIZ/PAG_ENT-1,%edi # the
+ incl %edi # BTX
+ shll $0x2,%edi # load
+ addl $MEM_TBL,%edi # address
+ pushl %edi # Save
+ movzwl 0xa(%ebx),%ecx # Image size
+ pushl %ecx # Save
+ rep # Relocate
+ movsb # BTX
+ movl %esi,%ebx # Keep place
+ movl $m_rel_btx,%esi # Restore
+ popl %eax # parameters
+ call dhexout # and
+ popl %ebp # display
+ movl %ebp,%eax # the
+ call dhexout # relocation
+ call dputstr # message
+ addl $PAG_SIZ,%ebp # Display
+ movl $m_base,%esi # the
+ movl %ebp,%eax # user
+ call dhexout # base
+ call dputstr # address
+#
+# Set up ELF-format client program.
+#
+ cmpl $0x464c457f,(%ebx) # ELF magic number?
+ je start.3 # Yes
+ movl $e_fmt,%esi # Display error
+ call putstr # message
+start.2: jmp start.2 # Hang
+start.3: movl $m_elf,%esi # Display ELF
+ call dputstr # message
+ movl $m_segs,%esi # Format string
+ movl $0x2,%edi # Segment count
+ movl 0x1c(%ebx),%edx # Get e_phoff
+ addl %ebx,%edx # To pointer
+ movzwl 0x2c(%ebx),%ecx # Get e_phnum
+start.4: cmpl $0x1,(%edx) # Is p_type PT_LOAD?
+ jne start.6 # No
+ movl 0x4(%edx),%eax # Display
+ call dhexout # p_offset
+ movl 0x8(%edx),%eax # Display
+ call dhexout # p_vaddr
+ movl 0x10(%edx),%eax # Display
+ call dhexout # p_filesz
+ movl 0x14(%edx),%eax # Display
+ call dhexout # p_memsz
+ call dputstr # End message
+ pushl %esi # Save
+ pushl %edi # working
+ pushl %ecx # registers
+ movl 0x4(%edx),%esi # Get p_offset
+ addl %ebx,%esi # as pointer
+ movl 0x8(%edx),%edi # Get p_vaddr
+ addl %ebp,%edi # as pointer
+ movl 0x10(%edx),%ecx # Get p_filesz
+ rep # Set up
+ movsb # segment
+ movl 0x14(%edx),%ecx # Any bytes
+ subl 0x10(%edx),%ecx # to zero?
+ jz start.5 # No
+ xorb %al,%al # Then
+ rep # zero
+ stosb # them
+start.5: popl %ecx # Restore
+ popl %edi # working
+ popl %esi # registers
+ decl %edi # Segments to do
+ je start.7 # If none
+start.6: addl $0x20,%edx # To next entry
+ loop start.4 # Till done
+start.7: movl $m_done,%esi # Display done
+ call dputstr # message
+ movl $start.8,%esi # Real mode stub
+ movl $MEM_STUB,%edi # Destination
+ movl $SIZ_STUB,%ecx # Size
+ rep # Relocate
+ movsb # it
+ ljmp $SEL_RCODE,$MEM_STUB # To 16-bit code
+start.8: xorl %eax,%eax # Data
+ movb $SEL_RDATA,%al # selector
+ movl %eax,%ss # Reload SS
+ movl %eax,%ds # Reset
+ movl %eax,%es # other
+ movl %eax,%fs # segment
+ movl %eax,%gs # limits
+ movl %cr0,%eax # Switch to
+ decl %eax # real
+ movl %eax,%cr0 # mode
+ .byte 0xea # Jump to
+ .word MEM_ENTRY # BTX entry
+ .word 0x0 # point
+start.9:
+#
+# Output message [ESI] followed by EAX in hex.
+#
+dhexout:
+.ifndef BTXLDR_VERBOSE
+ ret
+.endif
+hexout: pushl %eax # Save
+ call putstr # Display message
+ popl %eax # Restore
+ pushl %esi # Save
+ pushl %edi # caller's
+ movl $buf,%edi # Buffer
+ pushl %edi # Save
+ call hex32 # To hex
+ xorb %al,%al # Terminate
+ stosb # string
+ popl %esi # Restore
+hexout.1: lodsb # Get a char
+ cmpb $'0',%al # Leading zero?
+ je hexout.1 # Yes
+ testb %al,%al # End of string?
+ jne hexout.2 # No
+ decl %esi # Undo
+hexout.2: decl %esi # Adjust for inc
+ call putstr # Display hex
+ popl %edi # Restore
+ popl %esi # caller's
+ ret # To caller
+#
+# Output zero-terminated string [ESI] to the console.
+#
+dputstr:
+.ifndef BTXLDR_VERBOSE
+ ret
+.else
+ jmp putstr
+.endif
+putstr.0: call putchr # Output char
+putstr: lodsb # Load char
+ testb %al,%al # End of string?
+ jne putstr.0 # No
+ ret # To caller
+#
+# Output character AL to the console.
+#
+dputchr:
+.ifndef BTXLDR_VERBOSE
+ ret
+.endif
+putchr: pusha # Save
+ xorl %ecx,%ecx # Zero for loops
+ movb $SCR_MAT,%ah # Mode/attribute
+ movl $BDA_POS,%ebx # BDA pointer
+ movw (%ebx),%dx # Cursor position
+.ifdef PC98
+ movl $0xa0000,%edi # Regen buffer (color)
+.else
+ movl $0xb8000,%edi # Regen buffer (color)
+ cmpb %ah,BDA_SCR-BDA_POS(%ebx) # Mono mode?
+ jne putchr.1 # No
+ xorw %di,%di # Regen buffer (mono)
+.endif
+putchr.1: cmpb $0xa,%al # New line?
+ je putchr.2 # Yes
+.ifdef PC98
+ movw %dx,%cx
+ movb %al,(%edi,%ecx,1) # Write char
+ addl $0x2000,%ecx
+ movb %ah,(%edi,%ecx,1) # Write attr
+ addw $0x2,%dx
+ jmp putchr.3
+putchr.2: movw %dx,%ax
+ movb $SCR_COL*2,%dl
+ div %dl
+ incb %al
+ mul %dl
+ movw %ax,%dx
+putchr.3: cmpw $SCR_COL*SCR_ROW*2,%dx
+.else
+ xchgl %eax,%ecx # Save char
+ movb $SCR_COL,%al # Columns per row
+ mulb %dh # * row position
+ addb %dl,%al # + column
+ adcb $0x0,%ah # position
+ shll %eax # * 2
+ xchgl %eax,%ecx # Swap char, offset
+ movw %ax,(%edi,%ecx,1) # Write attr:char
+ incl %edx # Bump cursor
+ cmpb $SCR_COL,%dl # Beyond row?
+ jb putchr.3 # No
+putchr.2: xorb %dl,%dl # Zero column
+ incb %dh # Bump row
+putchr.3: cmpb $SCR_ROW,%dh # Beyond screen?
+.endif
+ jb putchr.4 # No
+ leal 2*SCR_COL(%edi),%esi # New top line
+ movw $(SCR_ROW-1)*SCR_COL/2,%cx # Words to move
+ rep # Scroll
+ movsl # screen
+ movb $' ',%al # Space
+.ifdef PC98
+ xorb %ah,%ah
+.endif
+ movb $SCR_COL,%cl # Columns to clear
+ rep # Clear
+ stosw # line
+.ifdef PC98
+ movw $(SCR_ROW-1)*SCR_COL*2,%dx
+putchr.4: movw %dx,(%ebx) # Update position
+ shrw $1,%dx
+gdcwait.3: inb $0x60,%al
+ testb $0x04,%al
+ jz gdcwait.3
+ movb $0x49,%al
+ outb %al,$0x62
+ movb %dl,%al
+ outb %al,$0x60
+ movb %dh,%al
+ outb %al,$0x60
+.else
+ movb $SCR_ROW-1,%dh # Bottom line
+putchr.4: movw %dx,(%ebx) # Update position
+.endif
+ popa # Restore
+ ret # To caller
+#
+# Convert EAX, AX, or AL to hex, saving the result to [EDI].
+#
+hex32: pushl %eax # Save
+ shrl $0x10,%eax # Do upper
+ call hex16 # 16
+ popl %eax # Restore
+hex16: call hex16.1 # Do upper 8
+hex16.1: xchgb %ah,%al # Save/restore
+hex8: pushl %eax # Save
+ shrb $0x4,%al # Do upper
+ call hex8.1 # 4
+ popl %eax # Restore
+hex8.1: andb $0xf,%al # Get lower 4
+ cmpb $0xa,%al # Convert
+ sbbb $0x69,%al # to hex
+ das # digit
+ orb $0x20,%al # To lower case
+ stosb # Save char
+ ret # (Recursive)
+
+ .data
+ .p2align 4
+#
+# Global descriptor table.
+#
+gdt: .word 0x0,0x0,0x0,0x0 # Null entry
+ .word 0xffff,0x0,0x9a00,0xcf # SEL_SCODE
+ .word 0xffff,0x0,0x9200,0xcf # SEL_SDATA
+ .word 0xffff,0x0,0x9a00,0x0 # SEL_RCODE
+ .word 0xffff,0x0,0x9200,0x0 # SEL_RDATA
+gdt.1:
+gdtdesc: .word gdt.1-gdt-1 # Limit
+ .long gdt # Base
+#
+# Messages.
+#
+m_logo: .asciz "\nBTX loader 1.00 "
+m_vers: .asciz "BTX version is \0\n"
+e_fmt: .asciz "Error: Client format not supported\n"
+#.ifdef BTXLDR_VERBOSE
+m_mem: .asciz "Starting in protected mode (base mem=\0)\n"
+m_esp: .asciz "Arguments passed (esp=\0):\n"
+m_args: .asciz"<howto="
+ .asciz" bootdev="
+ .asciz" junk="
+ .asciz" "
+ .asciz" "
+ .asciz" bootinfo=\0>\n"
+m_rel_bi: .asciz "Relocated bootinfo (size=48) to \0\n"
+m_rel_args: .asciz "Relocated arguments (size=18) to \0\n"
+m_rel_btx: .asciz "Relocated kernel (size=\0) to \0\n"
+m_base: .asciz "Client base address is \0\n"
+m_elf: .asciz "Client format is ELF\n"
+m_segs: .asciz "text segment: offset="
+ .asciz " vaddr="
+ .asciz " filesz="
+ .asciz " memsz=\0\n"
+ .asciz "data segment: offset="
+ .asciz " vaddr="
+ .asciz " filesz="
+ .asciz " memsz=\0\n"
+m_done: .asciz "Loading complete\n"
+#.endif
+#
+# Uninitialized data area.
+#
+buf: # Scratch buffer
diff --git a/sys/boot/pc98/btx/btxldr/btxldr.s b/sys/boot/pc98/btx/btxldr/btxldr.s
new file mode 100644
index 0000000..6217eb2
--- /dev/null
+++ b/sys/boot/pc98/btx/btxldr/btxldr.s
@@ -0,0 +1,459 @@
+#
+# Copyright (c) 1998 Robert Nordier
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms are freely
+# permitted provided that the above copyright notice and this
+# paragraph and the following disclaimer are duplicated in all
+# such forms.
+#
+# This software is provided "AS IS" and without any express or
+# implied warranties, including, without limitation, the implied
+# warranties of merchantability and fitness for a particular
+# purpose.
+#
+
+# $Id: btxldr.s,v 1.5 1999/01/22 13:07:17 rnordier Exp $
+
+#
+# Prototype BTX loader program, written in a couple of hours. The
+# real thing should probably be more flexible, and in C.
+#
+
+#
+# Memory locations.
+#
+ .set MEM_STUB,0x600 # Real mode stub
+ .set MEM_ESP,0x1000 # New stack pointer
+ .set MEM_TBL,0x5000 # BTX page tables
+ .set MEM_ENTRY,0x9010 # BTX entry point
+ .set MEM_DATA,0x101000 # Data segment
+#
+# Segment selectors.
+#
+ .set SEL_SCODE,0x8 # 4GB code
+ .set SEL_SDATA,0x10 # 4GB data
+ .set SEL_RCODE,0x18 # 64K code
+ .set SEL_RDATA,0x20 # 64K data
+#
+# Paging constants.
+#
+ .set PAG_SIZ,0x1000 # Page size
+ .set PAG_ENT,0x4 # Page entry size
+#
+# Screen constants.
+#
+.ifdef PC98
+ .set SCR_MAT,0xe1 # Mode/attribute
+.else
+ .set SCR_MAT,0x7 # Mode/attribute
+.endif
+ .set SCR_COL,0x50 # Columns per row
+ .set SCR_ROW,0x19 # Rows per screen
+#
+# BIOS Data Area locations.
+#
+.ifdef PC98
+ .set BDA_MEM,0xa1501 # Free memory
+ .set BDA_POS,0xa153e # Cursor position
+.else
+ .set BDA_MEM,0x413 # Free memory
+ .set BDA_SCR,0x449 # Video mode
+ .set BDA_POS,0x450 # Cursor position
+.endif
+#
+# Required by aout gas inadequacy.
+#
+ .set SIZ_STUB,0x1a # Size of stub
+#
+# We expect to be loaded by boot2 at 0x100000.
+#
+ .globl start
+#
+# BTX program loader for ELF clients.
+#
+start: cld # String ops inc
+.ifdef PC98
+ cli
+gdcwait.1: inb $0x60,%al
+ testb $0x04,%al
+ jz gdcwait.1
+ movb $0xe0,%al
+ outb %al,$0x62
+ nop
+gdcwait.2: inb $0x60,%al
+ testb $0x01,%al
+ jz gdcwait.2
+ inb $0x62,%al
+ movb %al,%dl
+ inb $0x62,%al
+ movb %al,%dh
+ inb $0x62,%al
+ inb $0x62,%al
+ inb $0x62,%al
+ shlw $1,%dx
+ movl $BDA_POS,%ebx
+ movw %dx,(%ebx)
+.endif
+ movl $m_logo,%esi # Identify
+ call putstr # ourselves
+ movzwl BDA_MEM,%eax # Get base memory
+.ifdef PC98
+ andl $0x7,%eax
+ incl %eax
+ shll $0x11,%eax # in bytes
+.else
+ shll $0xa,%eax # in bytes
+.endif
+ movl %eax,%ebp # Base of user stack
+ movl $m_mem,%esi # Display
+ call dhexout # amount of
+ call dputstr # base memory
+ lgdt gdtdesc # Load new GDT
+#
+# Relocate caller's arguments.
+#
+ movl $m_esp,%esi # Display
+ movl %esp,%eax # caller's
+ call dhexout # stack
+ call dputstr # pointer
+ movl $m_args,%esi # Format string
+ leal 0x4(%esp,1),%ebx # First argument
+ movl $0x6,%ecx # Count
+start.1: movl (%ebx),%eax # Get argument and
+ addl $0x4,%ebx # bump pointer
+ call dhexout # Display it
+ loop start.1 # Till done
+ call dputstr # End message
+ movl $0x48,%ecx # Allocate space
+ subl %ecx,%ebp # for bootinfo
+ movl 0x18(%esp,1),%esi # Source
+ movl %ebp,%edi # Destination
+ rep # Copy
+ movsb # it
+ movl %ebp,0x18(%esp,1) # Update pointer
+ movl $m_rel_bi,%esi # Display
+ movl %ebp,%eax # bootinfo
+ call dhexout # relocation
+ call dputstr # message
+ movl $0x18,%ecx # Allocate space
+ subl %ecx,%ebp # for arguments
+ leal 0x4(%esp,1),%esi # Source
+ movl %ebp,%edi # Destination
+ rep # Copy
+ movsb # them
+ movl $m_rel_args,%esi # Display
+ movl %ebp,%eax # argument
+ call dhexout # relocation
+ call dputstr # message
+#
+# Set up BTX kernel.
+#
+ movl $MEM_ESP,%esp # Set up new stack
+ movl $MEM_DATA,%ebx # Data segment
+ movl $m_vers,%esi # Display BTX
+ call putstr # version message
+ movb 0x5(%ebx),%al # Get major version
+ addb $'0',%al # Display
+ call putchr # it
+ movb $'.',%al # And a
+ call putchr # dot
+ movb 0x6(%ebx),%al # Get minor
+ xorb %ah,%ah # version
+ movb $0xa,%dl # Divide
+ divb %dl,%al # by 10
+ addb $'0',%al # Display
+ call putchr # tens
+ movb %ah,%al # Get units
+ addb $'0',%al # Display
+ call putchr # units
+ call putstr # End message
+ movl %ebx,%esi # BTX image
+ movzwl 0x8(%ebx),%edi # Compute
+ orl $PAG_SIZ/PAG_ENT-1,%edi # the
+ incl %edi # BTX
+ shll $0x2,%edi # load
+ addl $MEM_TBL,%edi # address
+ pushl %edi # Save
+ movzwl 0xa(%ebx),%ecx # Image size
+ pushl %ecx # Save
+ rep # Relocate
+ movsb # BTX
+ movl %esi,%ebx # Keep place
+ movl $m_rel_btx,%esi # Restore
+ popl %eax # parameters
+ call dhexout # and
+ popl %ebp # display
+ movl %ebp,%eax # the
+ call dhexout # relocation
+ call dputstr # message
+ addl $PAG_SIZ,%ebp # Display
+ movl $m_base,%esi # the
+ movl %ebp,%eax # user
+ call dhexout # base
+ call dputstr # address
+#
+# Set up ELF-format client program.
+#
+ cmpl $0x464c457f,(%ebx) # ELF magic number?
+ je start.3 # Yes
+ movl $e_fmt,%esi # Display error
+ call putstr # message
+start.2: jmp start.2 # Hang
+start.3: movl $m_elf,%esi # Display ELF
+ call dputstr # message
+ movl $m_segs,%esi # Format string
+ movl $0x2,%edi # Segment count
+ movl 0x1c(%ebx),%edx # Get e_phoff
+ addl %ebx,%edx # To pointer
+ movzwl 0x2c(%ebx),%ecx # Get e_phnum
+start.4: cmpl $0x1,(%edx) # Is p_type PT_LOAD?
+ jne start.6 # No
+ movl 0x4(%edx),%eax # Display
+ call dhexout # p_offset
+ movl 0x8(%edx),%eax # Display
+ call dhexout # p_vaddr
+ movl 0x10(%edx),%eax # Display
+ call dhexout # p_filesz
+ movl 0x14(%edx),%eax # Display
+ call dhexout # p_memsz
+ call dputstr # End message
+ pushl %esi # Save
+ pushl %edi # working
+ pushl %ecx # registers
+ movl 0x4(%edx),%esi # Get p_offset
+ addl %ebx,%esi # as pointer
+ movl 0x8(%edx),%edi # Get p_vaddr
+ addl %ebp,%edi # as pointer
+ movl 0x10(%edx),%ecx # Get p_filesz
+ rep # Set up
+ movsb # segment
+ movl 0x14(%edx),%ecx # Any bytes
+ subl 0x10(%edx),%ecx # to zero?
+ jz start.5 # No
+ xorb %al,%al # Then
+ rep # zero
+ stosb # them
+start.5: popl %ecx # Restore
+ popl %edi # working
+ popl %esi # registers
+ decl %edi # Segments to do
+ je start.7 # If none
+start.6: addl $0x20,%edx # To next entry
+ loop start.4 # Till done
+start.7: movl $m_done,%esi # Display done
+ call dputstr # message
+ movl $start.8,%esi # Real mode stub
+ movl $MEM_STUB,%edi # Destination
+ movl $SIZ_STUB,%ecx # Size
+ rep # Relocate
+ movsb # it
+ ljmp $SEL_RCODE,$MEM_STUB # To 16-bit code
+start.8: xorl %eax,%eax # Data
+ movb $SEL_RDATA,%al # selector
+ movl %eax,%ss # Reload SS
+ movl %eax,%ds # Reset
+ movl %eax,%es # other
+ movl %eax,%fs # segment
+ movl %eax,%gs # limits
+ movl %cr0,%eax # Switch to
+ decl %eax # real
+ movl %eax,%cr0 # mode
+ .byte 0xea # Jump to
+ .word MEM_ENTRY # BTX entry
+ .word 0x0 # point
+start.9:
+#
+# Output message [ESI] followed by EAX in hex.
+#
+dhexout:
+.ifndef BTXLDR_VERBOSE
+ ret
+.endif
+hexout: pushl %eax # Save
+ call putstr # Display message
+ popl %eax # Restore
+ pushl %esi # Save
+ pushl %edi # caller's
+ movl $buf,%edi # Buffer
+ pushl %edi # Save
+ call hex32 # To hex
+ xorb %al,%al # Terminate
+ stosb # string
+ popl %esi # Restore
+hexout.1: lodsb # Get a char
+ cmpb $'0',%al # Leading zero?
+ je hexout.1 # Yes
+ testb %al,%al # End of string?
+ jne hexout.2 # No
+ decl %esi # Undo
+hexout.2: decl %esi # Adjust for inc
+ call putstr # Display hex
+ popl %edi # Restore
+ popl %esi # caller's
+ ret # To caller
+#
+# Output zero-terminated string [ESI] to the console.
+#
+dputstr:
+.ifndef BTXLDR_VERBOSE
+ ret
+.else
+ jmp putstr
+.endif
+putstr.0: call putchr # Output char
+putstr: lodsb # Load char
+ testb %al,%al # End of string?
+ jne putstr.0 # No
+ ret # To caller
+#
+# Output character AL to the console.
+#
+dputchr:
+.ifndef BTXLDR_VERBOSE
+ ret
+.endif
+putchr: pusha # Save
+ xorl %ecx,%ecx # Zero for loops
+ movb $SCR_MAT,%ah # Mode/attribute
+ movl $BDA_POS,%ebx # BDA pointer
+ movw (%ebx),%dx # Cursor position
+.ifdef PC98
+ movl $0xa0000,%edi # Regen buffer (color)
+.else
+ movl $0xb8000,%edi # Regen buffer (color)
+ cmpb %ah,BDA_SCR-BDA_POS(%ebx) # Mono mode?
+ jne putchr.1 # No
+ xorw %di,%di # Regen buffer (mono)
+.endif
+putchr.1: cmpb $0xa,%al # New line?
+ je putchr.2 # Yes
+.ifdef PC98
+ movw %dx,%cx
+ movb %al,(%edi,%ecx,1) # Write char
+ addl $0x2000,%ecx
+ movb %ah,(%edi,%ecx,1) # Write attr
+ addw $0x2,%dx
+ jmp putchr.3
+putchr.2: movw %dx,%ax
+ movb $SCR_COL*2,%dl
+ div %dl
+ incb %al
+ mul %dl
+ movw %ax,%dx
+putchr.3: cmpw $SCR_COL*SCR_ROW*2,%dx
+.else
+ xchgl %eax,%ecx # Save char
+ movb $SCR_COL,%al # Columns per row
+ mulb %dh # * row position
+ addb %dl,%al # + column
+ adcb $0x0,%ah # position
+ shll %eax # * 2
+ xchgl %eax,%ecx # Swap char, offset
+ movw %ax,(%edi,%ecx,1) # Write attr:char
+ incl %edx # Bump cursor
+ cmpb $SCR_COL,%dl # Beyond row?
+ jb putchr.3 # No
+putchr.2: xorb %dl,%dl # Zero column
+ incb %dh # Bump row
+putchr.3: cmpb $SCR_ROW,%dh # Beyond screen?
+.endif
+ jb putchr.4 # No
+ leal 2*SCR_COL(%edi),%esi # New top line
+ movw $(SCR_ROW-1)*SCR_COL/2,%cx # Words to move
+ rep # Scroll
+ movsl # screen
+ movb $' ',%al # Space
+.ifdef PC98
+ xorb %ah,%ah
+.endif
+ movb $SCR_COL,%cl # Columns to clear
+ rep # Clear
+ stosw # line
+.ifdef PC98
+ movw $(SCR_ROW-1)*SCR_COL*2,%dx
+putchr.4: movw %dx,(%ebx) # Update position
+ shrw $1,%dx
+gdcwait.3: inb $0x60,%al
+ testb $0x04,%al
+ jz gdcwait.3
+ movb $0x49,%al
+ outb %al,$0x62
+ movb %dl,%al
+ outb %al,$0x60
+ movb %dh,%al
+ outb %al,$0x60
+.else
+ movb $SCR_ROW-1,%dh # Bottom line
+putchr.4: movw %dx,(%ebx) # Update position
+.endif
+ popa # Restore
+ ret # To caller
+#
+# Convert EAX, AX, or AL to hex, saving the result to [EDI].
+#
+hex32: pushl %eax # Save
+ shrl $0x10,%eax # Do upper
+ call hex16 # 16
+ popl %eax # Restore
+hex16: call hex16.1 # Do upper 8
+hex16.1: xchgb %ah,%al # Save/restore
+hex8: pushl %eax # Save
+ shrb $0x4,%al # Do upper
+ call hex8.1 # 4
+ popl %eax # Restore
+hex8.1: andb $0xf,%al # Get lower 4
+ cmpb $0xa,%al # Convert
+ sbbb $0x69,%al # to hex
+ das # digit
+ orb $0x20,%al # To lower case
+ stosb # Save char
+ ret # (Recursive)
+
+ .data
+ .p2align 4
+#
+# Global descriptor table.
+#
+gdt: .word 0x0,0x0,0x0,0x0 # Null entry
+ .word 0xffff,0x0,0x9a00,0xcf # SEL_SCODE
+ .word 0xffff,0x0,0x9200,0xcf # SEL_SDATA
+ .word 0xffff,0x0,0x9a00,0x0 # SEL_RCODE
+ .word 0xffff,0x0,0x9200,0x0 # SEL_RDATA
+gdt.1:
+gdtdesc: .word gdt.1-gdt-1 # Limit
+ .long gdt # Base
+#
+# Messages.
+#
+m_logo: .asciz "\nBTX loader 1.00 "
+m_vers: .asciz "BTX version is \0\n"
+e_fmt: .asciz "Error: Client format not supported\n"
+#.ifdef BTXLDR_VERBOSE
+m_mem: .asciz "Starting in protected mode (base mem=\0)\n"
+m_esp: .asciz "Arguments passed (esp=\0):\n"
+m_args: .asciz"<howto="
+ .asciz" bootdev="
+ .asciz" junk="
+ .asciz" "
+ .asciz" "
+ .asciz" bootinfo=\0>\n"
+m_rel_bi: .asciz "Relocated bootinfo (size=48) to \0\n"
+m_rel_args: .asciz "Relocated arguments (size=18) to \0\n"
+m_rel_btx: .asciz "Relocated kernel (size=\0) to \0\n"
+m_base: .asciz "Client base address is \0\n"
+m_elf: .asciz "Client format is ELF\n"
+m_segs: .asciz "text segment: offset="
+ .asciz " vaddr="
+ .asciz " filesz="
+ .asciz " memsz=\0\n"
+ .asciz "data segment: offset="
+ .asciz " vaddr="
+ .asciz " filesz="
+ .asciz " memsz=\0\n"
+m_done: .asciz "Loading complete\n"
+#.endif
+#
+# Uninitialized data area.
+#
+buf: # Scratch buffer
diff --git a/sys/boot/pc98/btx/lib/Makefile b/sys/boot/pc98/btx/lib/Makefile
new file mode 100644
index 0000000..e47e653
--- /dev/null
+++ b/sys/boot/pc98/btx/lib/Makefile
@@ -0,0 +1,20 @@
+# $Id: Makefile,v 1.2 1998/10/11 11:27:48 rnordier Exp $
+
+OBJS= btxcsu.o btxsys.o btxv86.o
+AFLAGS+= -elf
+LDFLAGS+= -elf
+CLEANFILES+= crt0.o
+INTERNALLIB= true
+NOMAN= true
+NOPIC= true
+NOPROFILE= true
+
+all: crt0.o
+
+crt0.o: ${OBJS}
+ ${LD} ${LDFLAGS} -i -o ${.TARGET} ${OBJS}
+
+.include <bsd.lib.mk>
+
+.s.o:
+ ${AS} ${AFLAGS} -o ${.TARGET} ${.IMPSRC}
diff --git a/sys/boot/pc98/btx/lib/btxcsu.s b/sys/boot/pc98/btx/lib/btxcsu.s
new file mode 100644
index 0000000..28b878b
--- /dev/null
+++ b/sys/boot/pc98/btx/lib/btxcsu.s
@@ -0,0 +1,43 @@
+#
+# Copyright (c) 1998 Robert Nordier
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms are freely
+# permitted provided that the above copyright notice and this
+# paragraph and the following disclaimer are duplicated in all
+# such forms.
+#
+# This software is provided "AS IS" and without any express or
+# implied warranties, including, without limitation, the implied
+# warranties of merchantability and fitness for a particular
+# purpose.
+#
+
+# $Id: btxcsu.s,v 1.2 1998/10/04 21:15:45 rnordier Exp $
+
+#
+# BTX C startup code (ELF).
+#
+
+#
+# Globals.
+#
+ .global _start
+#
+# Constants.
+#
+ .set ARGADJ,0xfa0 # Argument adjustment
+#
+# Client entry point.
+#
+_start: movl %eax,__base # Set base address
+ movl %esp,%eax # Set
+ addl $ARGADJ,%eax # argument
+ movl %eax,__args # pointer
+ call main # Invoke client main()
+ call exit # Invoke client exit()
+#
+# Data.
+#
+ .comm __base,4 # Client base address
+ .comm __args,4 # Client arguments
diff --git a/sys/boot/pc98/btx/lib/btxsys.s b/sys/boot/pc98/btx/lib/btxsys.s
new file mode 100644
index 0000000..6273bfa
--- /dev/null
+++ b/sys/boot/pc98/btx/lib/btxsys.s
@@ -0,0 +1,40 @@
+#
+# Copyright (c) 1998 Robert Nordier
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms are freely
+# permitted provided that the above copyright notice and this
+# paragraph and the following disclaimer are duplicated in all
+# such forms.
+#
+# This software is provided "AS IS" and without any express or
+# implied warranties, including, without limitation, the implied
+# warranties of merchantability and fitness for a particular
+# purpose.
+#
+
+# $Id: btxsys.s,v 1.1 1998/09/14 10:37:00 rnordier Exp $
+
+#
+# BTX system calls.
+#
+
+#
+# Globals.
+#
+ .global __exit
+ .global __exec
+#
+# Constants.
+#
+ .set INT_SYS,0x30 # Interrupt number
+#
+# System call: exit
+#
+__exit: xorl %eax,%eax # BTX system
+ int $INT_SYS # call 0x0
+#
+# System call: exec
+#
+__exec: movl $0x1,%eax # BTX system
+ int $INT_SYS # call 0x1
diff --git a/sys/boot/pc98/btx/lib/btxv86.h b/sys/boot/pc98/btx/lib/btxv86.h
new file mode 100644
index 0000000..05708f2
--- /dev/null
+++ b/sys/boot/pc98/btx/lib/btxv86.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 1998 Robert Nordier
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are freely
+ * permitted provided that the above copyright notice and this
+ * paragraph and the following disclaimer are duplicated in all
+ * such forms.
+ *
+ * This software is provided "AS IS" and without any express or
+ * implied warranties, including, without limitation, the implied
+ * warranties of merchantability and fitness for a particular
+ * purpose.
+ */
+
+/*
+ * $Id: btxv86.h,v 1.4 1998/10/02 20:52:26 msmith Exp $
+ */
+
+#ifndef _BTXV86_H_
+#define _BTXV86_H_
+
+#include <sys/types.h>
+
+#define V86_ADDR 0x10000 /* Segment:offset address */
+#define V86_CALLF 0x20000 /* Emulate far call */
+#define V86_FLAGS 0x40000 /* Return flags */
+
+struct __v86 {
+ uint32_t ctl; /* Control flags */
+ uint32_t addr; /* Interrupt number or address */
+ uint32_t es; /* V86 ES register */
+ uint32_t ds; /* V86 DS register */
+ uint32_t fs; /* V86 FS register */
+ uint32_t gs; /* V86 GS register */
+ uint32_t eax; /* V86 EAX register */
+ uint32_t ecx; /* V86 ECX register */
+ uint32_t edx; /* V86 EDX register */
+ uint32_t ebx; /* V86 EBX register */
+ uint32_t efl; /* V86 eflags register */
+ uint32_t ebp; /* V86 EBP register */
+ uint32_t esi; /* V86 ESI register */
+ uint32_t edi; /* V86 EDI register */
+};
+
+extern struct __v86 __v86; /* V86 interface structure */
+void __v86int(void);
+
+#define v86 __v86
+#define v86int __v86int
+
+extern u_int32_t __base;
+extern u_int32_t __args;
+
+#define PTOV(pa) ((caddr_t)(pa) - __base)
+#define VTOP(va) ((vm_offset_t)(va) + __base)
+#define VTOPSEG(va) (u_int16_t)(VTOP((caddr_t)va) >> 4)
+#define VTOPOFF(va) (u_int16_t)(VTOP((caddr_t)va) & 0xf)
+
+void __exit(int) __attribute__((__noreturn__));
+void __exec(caddr_t, ...);
+
+#endif /* !_BTXV86_H_ */
diff --git a/sys/boot/pc98/btx/lib/btxv86.s b/sys/boot/pc98/btx/lib/btxv86.s
new file mode 100644
index 0000000..14b7767
--- /dev/null
+++ b/sys/boot/pc98/btx/lib/btxv86.s
@@ -0,0 +1,85 @@
+#
+# Copyright (c) 1998 Robert Nordier
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms are freely
+# permitted provided that the above copyright notice and this
+# paragraph and the following disclaimer are duplicated in all
+# such forms.
+#
+# This software is provided "AS IS" and without any express or
+# implied warranties, including, without limitation, the implied
+# warranties of merchantability and fitness for a particular
+# purpose.
+#
+
+# $Id: btxv86.s,v 1.2 1998/10/22 20:22:07 msmith Exp $
+
+#
+# BTX V86 interface.
+#
+
+#
+# Globals.
+#
+ .global __v86int
+#
+# Fields in V86 interface structure.
+#
+ .set V86_CTL,0x0 # Control flags
+ .set V86_ADDR,0x4 # Int number/address
+ .set V86_ES,0x8 # V86 ES
+ .set V86_DS,0xc # V86 DS
+ .set V86_FS,0x10 # V86 FS
+ .set V86_GS,0x14 # V86 GS
+ .set V86_EAX,0x18 # V86 EAX
+ .set V86_ECX,0x1c # V86 ECX
+ .set V86_EDX,0x20 # V86 EDX
+ .set V86_EBX,0x24 # V86 EBX
+ .set V86_EFL,0x28 # V86 eflags
+ .set V86_EBP,0x2c # V86 EBP
+ .set V86_ESI,0x30 # V86 ESI
+ .set V86_EDI,0x34 # V86 EDI
+#
+# Other constants.
+#
+ .set INT_V86,0x31 # Interrupt number
+ .set SIZ_V86,0x38 # Size of V86 structure
+#
+# V86 interface function.
+#
+__v86int: popl __v86ret # Save return address
+ pushl $__v86 # Push pointer
+ call __v86_swap # Load V86 registers
+ int $INT_V86 # To BTX
+ call __v86_swap # Load user registers
+ addl $0x4,%esp # Discard pointer
+ pushl __v86ret # Restore return address
+ ret # To user
+#
+# Swap V86 and user registers.
+#
+__v86_swap: xchgl %ebp,0x4(%esp,1) # Swap pointer, EBP
+ xchgl %eax,V86_EAX(%ebp) # Swap EAX
+ xchgl %ecx,V86_ECX(%ebp) # Swap ECX
+ xchgl %edx,V86_EDX(%ebp) # Swap EDX
+ xchgl %ebx,V86_EBX(%ebp) # Swap EBX
+ pushl %eax # Save
+ pushf # Put eflags
+ popl %eax # in EAX
+ xchgl %eax,V86_EFL(%ebp) # Swap
+ pushl %eax # Put EAX
+ popf # in eflags
+ movl 0x8(%esp,1),%eax # Load EBP
+ xchgl %eax,V86_EBP(%ebp) # Swap
+ movl %eax,0x8(%esp,1) # Save EBP
+ popl %eax # Restore
+ xchgl %esi,V86_ESI(%ebp) # Swap ESI
+ xchgl %edi,V86_EDI(%ebp) # Swap EDI
+ xchgl %ebp,0x4(%esp,1) # Swap pointer, EBP
+ ret # To caller
+#
+# V86 interface structure.
+#
+ .comm __v86,SIZ_V86
+ .comm __v86ret,4
OpenPOWER on IntegriCloud