diff options
author | kato <kato@FreeBSD.org> | 1999-02-03 08:39:09 +0000 |
---|---|---|
committer | kato <kato@FreeBSD.org> | 1999-02-03 08:39:09 +0000 |
commit | c40db6cc734847f5d3013132b80d70a078c16615 (patch) | |
tree | 8460f4832d3da04f82cedbd05be800e5fd9063e4 /sys/boot/pc98/btx | |
parent | 850544e5d8903343f0bdde5c29f0147851ea1b4b (diff) | |
download | FreeBSD-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/Makefile | 5 | ||||
-rw-r--r-- | sys/boot/pc98/btx/btx/Makefile | 25 | ||||
-rw-r--r-- | sys/boot/pc98/btx/btx/btx.S | 1071 | ||||
-rw-r--r-- | sys/boot/pc98/btx/btx/btx.m4 | 59 | ||||
-rw-r--r-- | sys/boot/pc98/btx/btx/btx.s | 1071 | ||||
-rw-r--r-- | sys/boot/pc98/btx/btxldr/Makefile | 26 | ||||
-rw-r--r-- | sys/boot/pc98/btx/btxldr/btxldr.S | 459 | ||||
-rw-r--r-- | sys/boot/pc98/btx/btxldr/btxldr.s | 459 | ||||
-rw-r--r-- | sys/boot/pc98/btx/lib/Makefile | 20 | ||||
-rw-r--r-- | sys/boot/pc98/btx/lib/btxcsu.s | 43 | ||||
-rw-r--r-- | sys/boot/pc98/btx/lib/btxsys.s | 40 | ||||
-rw-r--r-- | sys/boot/pc98/btx/lib/btxv86.h | 63 | ||||
-rw-r--r-- | sys/boot/pc98/btx/lib/btxv86.s | 85 |
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 |