btx.S revision 78650
143561Skato# 243561Skato# Copyright (c) 1998 Robert Nordier 343561Skato# All rights reserved. 443561Skato# 543561Skato# Redistribution and use in source and binary forms are freely 643561Skato# permitted provided that the above copyright notice and this 743561Skato# paragraph and the following disclaimer are duplicated in all 843561Skato# such forms. 943561Skato# 1043561Skato# This software is provided "AS IS" and without any express or 1143561Skato# implied warranties, including, without limitation, the implied 1243561Skato# warranties of merchantability and fitness for a particular 1343561Skato# purpose. 1443561Skato# 1543561Skato 1650477Speter# $FreeBSD: head/sys/boot/pc98/btx/btx/btx.S 78650 2001-06-23 08:04:14Z kato $ 1743561Skato 1843561Skato# 1943561Skato# Memory layout. 2043561Skato# 2143561Skato .set MEM_BTX,0x1000 # Start of BTX memory 2243561Skato .set MEM_ESP0,0x1800 # Supervisor stack 2343561Skato .set MEM_BUF,0x1800 # Scratch buffer 2443561Skato .set MEM_ESP1,0x1e00 # Link stack 2543561Skato .set MEM_IDT,0x1e00 # IDT 2643561Skato .set MEM_TSS,0x1f98 # TSS 2743561Skato .set MEM_MAP,0x2000 # I/O bit map 2843561Skato .set MEM_DIR,0x4000 # Page directory 2943561Skato .set MEM_TBL,0x5000 # Page tables 3043561Skato .set MEM_ORG,0x9000 # BTX code 3143561Skato .set MEM_USR,0xa000 # Start of user memory 3243561Skato# 3343561Skato# Paging control. 3443561Skato# 3543561Skato .set PAG_SIZ,0x1000 # Page size 3643561Skato .set PAG_CNT,0x1000 # Pages to map 3743561Skato# 3843561Skato# Segment selectors. 3943561Skato# 4043561Skato .set SEL_SCODE,0x8 # Supervisor code 4143561Skato .set SEL_SDATA,0x10 # Supervisor data 4243561Skato .set SEL_RCODE,0x18 # Real mode code 4343561Skato .set SEL_RDATA,0x20 # Real mode data 4443561Skato .set SEL_UCODE,0x28|3 # User code 4543561Skato .set SEL_UDATA,0x30|3 # User data 4643561Skato .set SEL_TSS,0x38 # TSS 4743561Skato# 4843561Skato# Task state segment fields. 4943561Skato# 5043561Skato .set TSS_ESP0,0x4 # PL 0 ESP 5143561Skato .set TSS_SS0,0x8 # PL 0 SS 5243561Skato .set TSS_ESP1,0xc # PL 1 ESP 5343561Skato .set TSS_MAP,0x66 # I/O bit map base 5443561Skato# 5543561Skato# System calls. 5643561Skato# 5743561Skato .set SYS_EXIT,0x0 # Exit 5843561Skato .set SYS_EXEC,0x1 # Exec 5943561Skato# 6043561Skato# V86 constants. 6143561Skato# 6243561Skato .set V86_FLG,0x208eff # V86 flag mask 6343561Skato .set V86_STK,0x400 # V86 stack allowance 6443561Skato# 6543561Skato# Dump format control bytes. 6643561Skato# 6743561Skato .set DMP_X16,0x1 # Word 6843561Skato .set DMP_X32,0x2 # Long 6943561Skato .set DMP_MEM,0x4 # Memory 7043561Skato .set DMP_EOL,0x8 # End of line 7143561Skato# 7243561Skato# Screen defaults and assumptions. 7343561Skato# 7443561Skato.`ifdef' PC98 7543561Skato .set SCR_MAT,0xe1 # Mode/attribute 7643561Skato.else 7743561Skato .set SCR_MAT,0x7 # Mode/attribute 7843561Skato.endif 7943561Skato .set SCR_COL,0x50 # Columns per row 8043561Skato .set SCR_ROW,0x19 # Rows per screen 8143561Skato# 8243561Skato# BIOS Data Area locations. 8343561Skato# 8443561Skato.`ifdef' PC98 8558871Skato .set BDA_MEM,0x501 # Free memory 8658871Skato .set BDA_KEYFLAGS,0x53a # Keyboard shift-state flags 8758871Skato .set BDA_POS,0x53e # Cursor position 8843561Skato.else 8943561Skato .set BDA_MEM,0x413 # Free memory 9058871Skato .set BDA_KEYFLAGS,0x417 # Keyboard shift-state flags 9143561Skato .set BDA_SCR,0x449 # Video mode 9243561Skato .set BDA_POS,0x450 # Cursor position 9358871Skato .set BDA_BOOT,0x472 # Boot howto flag 9443561Skato.endif 9543561Skato# 9643561Skato# Derivations, for brevity. 9743561Skato# 9843561Skato .set _ESP0H,MEM_ESP0>>0x8 # Byte 1 of ESP0 9943561Skato .set _ESP1H,MEM_ESP1>>0x8 # Byte 1 of ESP1 10043561Skato .set _TSSIO,MEM_MAP-MEM_TSS # TSS I/O base 10143561Skato .set _TSSLM,MEM_DIR-MEM_TSS-1 # TSS limit 10243561Skato .set _IDTLM,MEM_TSS-MEM_IDT-1 # IDT limit 10343561Skato# 10443561Skato# Code segment. 10543561Skato# 10643561Skato .globl start 10761064Snyan .code16 10843561Skatostart: # Start of code 10943561Skato# 11043561Skato# BTX header. 11143561Skato# 11243561Skatobtx_hdr: .byte 0xeb # Machine ID 11343561Skato .byte 0xe # Header size 11443561Skato .ascii "BTX" # Magic 11543561Skato .byte 0x1 # Major version 11644368Skato .byte 0x1 # Minor version 11768358Snyan .byte BTX_FLAGS # Flags 11843561Skato .word PAG_CNT-MEM_ORG>>0xc # Paging control 11943561Skato .word break-start # Text size 12043561Skato .long 0x0 # Entry address 12143561Skato# 12243561Skato# Initialization routine. 12343561Skato# 12443561Skatoinit: cli # Disable interrupts 12561064Snyan xor %ax,%ax # Zero/segment 12661064Snyan mov %ax,%ss # Set up 12761064Snyan mov $MEM_ESP0,%sp # stack 12861064Snyan mov %ax,%es # Address 12961064Snyan mov %ax,%ds # data 13061064Snyan pushl $0x2 # Clear 13161064Snyan popfl # flags 13243561Skato# 13343561Skato# Initialize memory. 13443561Skato# 13561064Snyan mov $MEM_IDT,%di # Memory to initialize 13661064Snyan mov $(MEM_ORG-MEM_IDT)/2,%cx # Words to zero 13761064Snyan push %di # Save 13843561Skato rep # Zero-fill 13961064Snyan stosw # memory 14061064Snyan pop %di # Restore 14143561Skato# 14243561Skato# Create IDT. 14343561Skato# 14461064Snyan mov $idtctl,%si # Control string 14543561Skatoinit.1: lodsb # Get entry 14661064Snyan cbw # count 14761064Snyan xchg %ax,%cx # as word 14861064Snyan jcxz init.4 # If done 14943561Skato lodsb # Get segment 15061064Snyan xchg %ax,%dx # P:DPL:type 15161064Snyan lodsw # Get control 15261064Snyan xchg %ax,%bx # set 15361064Snyan lodsw # Get handler offset 15461064Snyan mov $SEL_SCODE,%dh # Segment selector 15561064Snyaninit.2: shr %bx # Handle this int? 15643561Skato jnc init.3 # No 15761064Snyan mov %ax,(%di) # Set handler offset 15861064Snyan mov %dh,0x2(%di) # and selector 15961064Snyan mov %dl,0x5(%di) # Set P:DPL:type 16061064Snyan add $0x4,%ax # Next handler 16161064Snyaninit.3: lea 0x8(%di),%di # Next entry 16243561Skato loop init.2 # Till set done 16343561Skato jmp init.1 # Continue 16443561Skato# 16543561Skato# Initialize TSS. 16643561Skato# 16761064Snyaninit.4: movb $_ESP0H,TSS_ESP0+1(%di) # Set ESP0 16861064Snyan movb $SEL_SDATA,TSS_SS0(%di) # Set SS0 16961064Snyan movb $_ESP1H,TSS_ESP1+1(%di) # Set ESP1 17061064Snyan movb $_TSSIO,TSS_MAP(%di) # Set I/O bit map base 17152202Skatoifdef(`PAGING',` 17243561Skato# 17343561Skato# Create page directory. 17443561Skato# 17561064Snyan xor %edx,%edx # Page 17661064Snyan mov $PAG_SIZ>>0x8,%dh # size 17761064Snyan xor %eax,%eax # Zero 17861064Snyan mov $MEM_DIR,%di # Page directory 17961064Snyan mov $PAG_CNT>>0xa,%cl # Entries 18061064Snyan mov $MEM_TBL|0x7,%ax # First entry 18161064Snyaninit.5: stosl # Write entry 18261064Snyan add %dx,%ax # To next 18343561Skato loop init.5 # Till done 18443561Skato# 18543561Skato# Create page tables. 18643561Skato# 18761064Snyan mov $MEM_TBL,%di # Page table 18861064Snyan mov $PAG_CNT>>0x8,%ch # Entries 18961064Snyan xor %ax,%ax # Start address 19061064Snyaninit.6: mov $0x7,%al # Set U:W:P flags 19161064Snyan cmp btx_hdr+0x8,%cx # Standard user page? 19243561Skato jb init.7 # Yes 19361064Snyan cmp $PAG_CNT-MEM_BTX>>0xc,%cx # BTX memory? 19443561Skato jae init.7 # No or first page 19561064Snyan and $~0x2,%al # Clear W flag 19661064Snyan cmp $PAG_CNT-MEM_USR>>0xc,%cx # User page zero? 19743561Skato jne init.7 # No 19861064Snyan testb $0x80,btx_hdr+0x7 # Unmap it? 19943561Skato jz init.7 # No 20061064Snyan and $~0x1,%al # Clear P flag 20161064Snyaninit.7: stosl # Set entry 20261064Snyan add %edx,%eax # Next address 20343561Skato loop init.6 # Till done 20452202Skato') 20543561Skato# 20643561Skato# Bring up the system. 20743561Skato# 20861064Snyan mov $0x2820,%bx # Set protected mode 20961064Snyan callw setpic # IRQ offsets 21061064Snyan lidt idtdesc # Set IDT 21152202Skatoifdef(`PAGING',` 21261064Snyan xor %eax,%eax # Set base 21361064Snyan mov $MEM_DIR>>0x8,%ah # of page 21461064Snyan mov %eax,%cr3 # directory 21552202Skato') 21661064Snyan lgdt gdtdesc # Set GDT 21761064Snyan mov %cr0,%eax # Switch to protected 21852827Snyanifdef(`PAGING',` 21961064Snyan or $0x80000001,%eax # mode and enable paging 22052827Snyan',` 22161064Snyan or $0x01,%eax # mode 22252827Snyan') 22361064Snyan mov %eax,%cr0 # 22461064Snyan ljmp $SEL_SCODE,$init.8 # To 32-bit code 22561064Snyan .code32 22643561Skatoinit.8: xorl %ecx,%ecx # Zero 22743561Skato movb $SEL_SDATA,%cl # To 32-bit 22861064Snyan movw %cx,%ss # stack 22943561Skato# 23043561Skato# Launch user task. 23143561Skato# 23243561Skato movb $SEL_TSS,%cl # Set task 23361064Snyan ltr %cx # register 23443561Skato movl $MEM_USR,%edx # User base address 23543561Skato movzwl %ss:BDA_MEM,%eax # Get free memory 23643561Skato.`ifdef' PC98 23743561Skato andl $0x7,%eax 23843561Skato incl %eax 23943561Skato shll $0x11,%eax # To bytes 24043561Skato.else 24143561Skato shll $0xa,%eax # To bytes 24243561Skato.endif 24343561Skato subl $0x1000,%eax # Less arg space 24443561Skato subl %edx,%eax # Less base 24543561Skato movb $SEL_UDATA,%cl # User data selector 24643561Skato pushl %ecx # Set SS 24743561Skato pushl %eax # Set ESP 24861064Snyan push $0x202 # Set flags (IF set) 24961064Snyan push $SEL_UCODE # Set CS 25043561Skato pushl btx_hdr+0xc # Set EIP 25143561Skato pushl %ecx # Set GS 25243561Skato pushl %ecx # Set FS 25343561Skato pushl %ecx # Set DS 25443561Skato pushl %ecx # Set ES 25543561Skato pushl %edx # Set EAX 25643561Skato movb $0x7,%cl # Set remaining 25761064Snyaninit.9: push $0x0 # general 25843561Skato loop init.9 # registers 25943561Skato popa # and initialize 26043561Skato popl %es # Initialize 26143561Skato popl %ds # user 26243561Skato popl %fs # segment 26343561Skato popl %gs # registers 26443561Skato iret # To user mode 26543561Skato# 26643561Skato# Exit routine. 26743561Skato# 26843561Skatoexit: cli # Disable interrupts 26943561Skato movl $MEM_ESP0,%esp # Clear stack 27043561Skato# 27143561Skato# Turn off paging. 27243561Skato# 27343561Skato movl %cr0,%eax # Get CR0 27443561Skato andl $~0x80000000,%eax # Disable 27543561Skato movl %eax,%cr0 # paging 27643561Skato xorl %ecx,%ecx # Zero 27743561Skato movl %ecx,%cr3 # Flush TLB 27843561Skato# 27976927Snyan# Restore the GDT in case we caught a kernel trap. 28076927Snyan# 28176927Snyan lgdt gdtdesc # Set GDT 28276927Snyan# 28343561Skato# To 16 bits. 28443561Skato# 28561064Snyan ljmpw $SEL_RCODE,$exit.1 # Reload CS 28661064Snyan .code16 28761064Snyanexit.1: mov $SEL_RDATA,%cl # 16-bit selector 28861064Snyan mov %cx,%ss # Reload SS 28961064Snyan mov %cx,%ds # Load 29061064Snyan mov %cx,%es # remaining 29161064Snyan mov %cx,%fs # segment 29261064Snyan mov %cx,%gs # registers 29343561Skato# 29443561Skato# To real-address mode. 29543561Skato# 29661064Snyan dec %ax # Switch to 29761064Snyan mov %eax,%cr0 # real mode 29861064Snyan ljmp $0x0,$exit.2 # Reload CS 29961064Snyanexit.2: xor %ax,%ax # Real mode segment 30061064Snyan mov %ax,%ss # Reload SS 30161064Snyan mov %ax,%ds # Address data 30243561Skato.`ifdef' PC98 30361064Snyan mov $0x1008,%bx # Set real mode 30443561Skato.else 30561064Snyan mov $0x7008,%bx # Set real mode 30643561Skato.endif 30761064Snyan callw setpic # IRQ offsets 30861064Snyan lidt ivtdesc # Set IVT 30943561Skato# 31043561Skato# Reboot or await reset. 31143561Skato# 31243561Skato sti # Enable interrupts 31361064Snyan testb $0x1,btx_hdr+0x7 # Reboot? 31443561Skatoexit.3: jz exit.3 # No 31543561Skato.`ifdef' PC98 31643561Skato movb $0xa0,%al 31743561Skato outb %al,$0x35 31843561Skato movb 0,%al 31943561Skato outb %al,$0xf0 32043561Skatoexit.4: jmp exit.4 32143561Skato.else 32258871Skato movw $0x1234, BDA_BOOT # Do a warm boot 32361064Snyan ljmp $0xffff,$0x0 # reboot the machine 32443561Skato.endif 32543561Skato# 32643561Skato# Set IRQ offsets by reprogramming 8259A PICs. 32743561Skato# 32843561Skato.`ifdef' PC98 32961064Snyansetpic: in $0x02,%al # Save master 33061064Snyan push %ax # IMR 33161064Snyan in $0x0a,%al # Save slave 33261064Snyan push %ax # IMR 33343561Skato movb $0x11,%al # ICW1 to 33443561Skato outb %al,$0x00 # master, 33543561Skato outb %al,$0x08 # slave 33643561Skato movb %bl,%al # ICW2 to 33743561Skato outb %al,$0x02 # master 33843561Skato movb %bh,%al # ICW2 to 33943561Skato outb %al,$0x0a # slave 34043561Skato movb $0x80,%al # ICW3 to 34143561Skato outb %al,$0x02 # master 34243561Skato movb $0x7,%al # ICW3 to 34343561Skato outb %al,$0x0a # slave 34443561Skato movb $0x1d,%al # ICW4 to 34543561Skato outb %al,$0x02 # master, 34643561Skato movb $0x9,%al # ICW4 to 34743561Skato outb %al,$0x0a # slave 34861064Snyan pop %ax # Restore slave 34943561Skato outb %al,$0x0a # IMR 35061064Snyan pop %ax # Restore master 35143561Skato outb %al,$0x02 # IMR 35243561Skato.else 35361064Snyansetpic: in $0x21,%al # Save master 35461064Snyan push %ax # IMR 35561064Snyan in $0xa1,%al # Save slave 35661064Snyan push %ax # IMR 35743561Skato movb $0x11,%al # ICW1 to 35843561Skato outb %al,$0x20 # master, 35943561Skato outb %al,$0xa0 # slave 36043561Skato movb %bl,%al # ICW2 to 36143561Skato outb %al,$0x21 # master 36243561Skato movb %bh,%al # ICW2 to 36343561Skato outb %al,$0xa1 # slave 36443561Skato movb $0x4,%al # ICW3 to 36543561Skato outb %al,$0x21 # master 36643561Skato movb $0x2,%al # ICW3 to 36743561Skato outb %al,$0xa1 # slave 36843561Skato movb $0x1,%al # ICW4 to 36943561Skato outb %al,$0x21 # master, 37043561Skato outb %al,$0xa1 # slave 37161064Snyan pop %ax # Restore slave 37243561Skato outb %al,$0xa1 # IMR 37361064Snyan pop %ax # Restore master 37443561Skato outb %al,$0x21 # IMR 37543561Skato.endif 37661064Snyan retw # To caller 37761064Snyan .code32 37843561Skato# 37943561Skato# Initiate return from V86 mode to user mode. 38043561Skato# 38143561Skatointhlt: hlt # To supervisor mode 38243561Skato# 38343561Skato# Exception jump table. 38443561Skato# 38561064Snyanintx00: push $0x0 # Int 0x0: #DE 38643561Skato jmp ex_noc # Divide error 38761064Snyan push $0x1 # Int 0x1: #DB 38843561Skato jmp ex_noc # Debug 38961064Snyan push $0x3 # Int 0x3: #BP 39043561Skato jmp ex_noc # Breakpoint 39161064Snyan push $0x4 # Int 0x4: #OF 39243561Skato jmp ex_noc # Overflow 39361064Snyan push $0x5 # Int 0x5: #BR 39443561Skato jmp ex_noc # BOUND range exceeded 39561064Snyan push $0x6 # Int 0x6: #UD 39643561Skato jmp ex_noc # Invalid opcode 39761064Snyan push $0x7 # Int 0x7: #NM 39843561Skato jmp ex_noc # Device not available 39961064Snyan push $0x8 # Int 0x8: #DF 40043561Skato jmp except # Double fault 40161064Snyan push $0xa # Int 0xa: #TS 40243561Skato jmp except # Invalid TSS 40361064Snyan push $0xb # Int 0xb: #NP 40443561Skato jmp except # Segment not present 40561064Snyan push $0xc # Int 0xc: #SS 40643561Skato jmp except # Stack segment fault 40761064Snyan push $0xd # Int 0xd: #GP 40843561Skato jmp ex_v86 # General protection 40961064Snyan push $0xe # Int 0xe: #PF 41043561Skato jmp except # Page fault 41161064Snyanintx10: push $0x10 # Int 0x10: #MF 41243561Skato jmp ex_noc # Floating-point error 41343561Skato# 41443561Skato# Handle #GP exception. 41543561Skato# 41643561Skatoex_v86: testb $0x2,0x12(%esp,1) # V86 mode? 41743561Skato jz except # No 41843561Skato jmp v86mon # To monitor 41943561Skato# 42043561Skato# Save a zero error code. 42143561Skato# 42243561Skatoex_noc: pushl (%esp,1) # Duplicate int no 42343561Skato movb $0x0,0x4(%esp,1) # Fake error code 42443561Skato# 42543561Skato# Handle exception. 42643561Skato# 42743561Skatoexcept: cld # String ops inc 42843561Skato pushl %ds # Save 42943561Skato pushl %es # most 43043561Skato pusha # registers 43143561Skato movb $0x6,%al # Push loop count 43243561Skato testb $0x2,0x3a(%esp,1) # V86 mode? 43343561Skato jnz except.1 # Yes 43443561Skato pushl %gs # Set GS 43543561Skato pushl %fs # Set FS 43643561Skato pushl %ds # Set DS 43743561Skato pushl %es # Set ES 43843561Skato movb $0x2,%al # Push loop count 43943561Skato cmpw $SEL_SCODE,0x44(%esp,1) # Supervisor mode? 44043561Skato jne except.1 # No 44143561Skato pushl %ss # Set SS 44243561Skato leal 0x50(%esp,1),%eax # Set 44343561Skato pushl %eax # ESP 44443561Skato jmp except.2 # Join common code 44543561Skatoexcept.1: pushl 0x50(%esp,1) # Set GS, FS, DS, ES 44643561Skato decb %al # (if V86 mode), and 44743561Skato jne except.1 # SS, ESP 44861064Snyanexcept.2: push $SEL_SDATA # Set up 44943561Skato popl %ds # to 45043561Skato pushl %ds # address 45143561Skato popl %es # data 45243561Skato movl %esp,%ebx # Stack frame 45343561Skato movl $dmpfmt,%esi # Dump format string 45443561Skato movl $MEM_BUF,%edi # Buffer 45543561Skato.`ifdef' PC98 45643561Skato pushl %eax 45743561Skato pushl %edx 45843561Skatowait.1: 45943561Skato inb $0x60,%al 46043561Skato testb $0x04,%al 46143561Skato jz wait.1 46243561Skato movb $0xe0,%al 46343561Skato outb %al,$0x62 46443561Skatowait.2: 46543561Skato inb $0x60,%al 46643561Skato testb $0x01,%al 46743561Skato jz wait.2 46843561Skato xorl %edx,%edx 46943561Skato inb $0x62,%al 47043561Skato movb %al,%dl 47143561Skato inb $0x62,%al 47243561Skato movb %al,%dh 47343561Skato inb $0x62,%al 47443561Skato inb $0x62,%al 47543561Skato inb $0x62,%al 47643561Skato movl %edx,%eax 47743561Skato shlw $1,%ax 47843561Skato movl $BDA_POS,%edx 47943561Skato movw %ax,(%edx) 48043561Skato popl %edx 48143561Skato popl %eax 48243561Skato.endif 48343561Skato pushl %edi # Dump to 48443561Skato call dump # buffer 48543561Skato popl %esi # and 48643561Skato call putstr # display 48743561Skato leal 0x18(%esp,1),%esp # Discard frame 48843561Skato popa # Restore 48943561Skato popl %es # registers 49043561Skato popl %ds # saved 49143561Skato cmpb $0x3,(%esp,1) # Breakpoint? 49243561Skato je except.3 # Yes 49343561Skato jmp exit # Exit 49443561Skatoexcept.3: leal 0x8(%esp,1),%esp # Discard err, int no 49543561Skato iret # From interrupt 49643561Skato# 49743561Skato# Return to user mode from V86 mode. 49843561Skato# 49943561Skatointrtn: cld # String ops inc 50043561Skato pushl %ds # Address 50143561Skato popl %es # data 50243561Skato leal 0x3c(%ebp),%edx # V86 Segment registers 50343561Skato movl MEM_TSS+TSS_ESP1,%esi # Link stack pointer 50443561Skato lodsl # INT_V86 args pointer 50543561Skato movl %esi,%ebx # Saved exception frame 50643561Skato testl %eax,%eax # INT_V86 args? 50743561Skato jz intrtn.2 # No 50843561Skato movl $MEM_USR,%edi # User base 50943561Skato movl 0x1c(%esi),%ebx # User ESP 51043561Skato movl %eax,(%edi,%ebx,1) # Restore to user stack 51143561Skato leal 0x8(%edi,%eax,1),%edi # Arg segment registers 51243561Skato testb $0x4,-0x6(%edi) # Return flags? 51343561Skato jz intrtn.1 # No 51443561Skato movl 0x30(%ebp),%eax # Get V86 flags 51543561Skato movw %ax,0x18(%esi) # Set user flags 51643561Skatointrtn.1: leal 0x10(%esi),%ebx # Saved exception frame 51743561Skato xchgl %edx,%esi # Segment registers 51843561Skato movb $0x4,%cl # Update seg regs 51943561Skato rep # in INT_V86 52043561Skato movsl # args 52143561Skatointrtn.2: movl %edx,%esi # Segment registers 52243561Skato leal 0x28(%ebp),%edi # Set up seg 52343561Skato movb $0x4,%cl # regs for 52443561Skato rep # later 52543561Skato movsl # pop 52643561Skato movl %ebx,%esi # Restore exception 52743561Skato movb $0x5,%cl # frame to 52843561Skato rep # supervisor 52943561Skato movsl # stack 53043561Skato movl %esi,MEM_TSS+TSS_ESP1 # Link stack pointer 53143561Skato popa # Restore 53243561Skato leal 0x8(%esp,1),%esp # Discard err, int no 53343561Skato popl %es # Restore 53443561Skato popl %ds # user 53543561Skato popl %fs # segment 53643561Skato popl %gs # registers 53743561Skato iret # To user mode 53843561Skato# 53943561Skato# V86 monitor. 54043561Skato# 54143561Skatov86mon: cld # String ops inc 54243561Skato pushl $SEL_SDATA # Set up for 54343561Skato popl %ds # flat addressing 54443561Skato pusha # Save registers 54543561Skato movl %esp,%ebp # Address stack frame 54643561Skato movzwl 0x2c(%ebp),%edi # Load V86 CS 54743561Skato shll $0x4,%edi # To linear 54843561Skato movl 0x28(%ebp),%esi # Load V86 IP 54943561Skato addl %edi,%esi # Code pointer 55043561Skato xorl %ecx,%ecx # Zero 55143561Skato movb $0x2,%cl # 16-bit operands 55243561Skato xorl %eax,%eax # Zero 55343561Skatov86mon.1: lodsb # Get opcode 55443561Skato cmpb $0x66,%al # Operand size prefix? 55543561Skato jne v86mon.2 # No 55643561Skato movb $0x4,%cl # 32-bit operands 55743561Skato jmp v86mon.1 # Continue 55843561Skatov86mon.2: cmpb $0xf4,%al # HLT? 55943561Skato jne v86mon.3 # No 56043561Skato cmpl $inthlt+0x1,%esi # Is inthlt? 56144368Skato jne v86mon.7 # No (ignore) 56243561Skato jmp intrtn # Return to user mode 56364019Snyanv86mon.3: cmpb $0xf,%al # Prefixed instruction? 56464019Snyan jne v86mon.4 # No 56564019Snyan cmpb $0x09,(%esi) # Is it a WBINVD? 56664019Snyan je v86wbinvd # Yes 56764019Snyan cmpb $0x30,(%esi) # Is it a WRMSR? 56864019Snyan je v86wrmsr # Yes 56964019Snyan cmpb $0x32,(%esi) # Is it a RDMSR? 57064019Snyan je v86rdmsr # Yes 57164019Snyan cmpb $0x20,(%esi) # Is this a 57244368Skato jne v86mon.4 # MOV EAX,CR0 57344368Skato cmpb $0xc0,0x1(%esi) # instruction? 57444368Skato je v86mov # Yes 57544368Skatov86mon.4: cmpb $0xfa,%al # CLI? 57643561Skato je v86cli # Yes 57743561Skato cmpb $0xfb,%al # STI? 57843561Skato je v86sti # Yes 57943561Skato movzwl 0x38(%ebp),%ebx # Load V86 SS 58043561Skato shll $0x4,%ebx # To offset 58143561Skato pushl %ebx # Save 58243561Skato addl 0x34(%ebp),%ebx # Add V86 SP 58343561Skato movl 0x30(%ebp),%edx # Load V86 flags 58443561Skato cmpb $0x9c,%al # PUSHF/PUSHFD? 58543561Skato je v86pushf # Yes 58643561Skato cmpb $0x9d,%al # POPF/POPFD? 58743561Skato je v86popf # Yes 58843561Skato cmpb $0xcd,%al # INT imm8? 58943561Skato je v86intn # Yes 59043561Skato cmpb $0xcf,%al # IRET/IRETD? 59143561Skato je v86iret # Yes 59243561Skato popl %ebx # Restore 59343561Skato popa # Restore 59443561Skato jmp except # Handle exception 59544368Skatov86mon.5: movl %edx,0x30(%ebp) # Save V86 flags 59644368Skatov86mon.6: popl %edx # V86 SS adjustment 59743561Skato subl %edx,%ebx # Save V86 59843561Skato movl %ebx,0x34(%ebp) # SP 59944368Skatov86mon.7: subl %edi,%esi # From linear 60043561Skato movl %esi,0x28(%ebp) # Save V86 IP 60143561Skato popa # Restore 60243561Skato leal 0x8(%esp,1),%esp # Discard int no, error 60343561Skato iret # To V86 mode 60443561Skato# 60544368Skato# Emulate MOV EAX,CR0. 60644368Skato# 60744368Skatov86mov: movl %cr0,%eax # CR0 to 60844368Skato movl %eax,0x1c(%ebp) # saved EAX 60964019Snyan incl %esi # Adjust IP 61064019Snyan# 61164019Snyan# Return from emulating a 0x0f prefixed instruction 61264019Snyan# 61364019Snyanv86preret: incl %esi # Adjust IP 61444368Skato jmp v86mon.7 # Finish up 61544368Skato# 61664019Snyan# Emulate WBINVD 61764019Snyan# 61864019Snyanv86wbinvd: wbinvd # Write back and invalidate 61964019Snyan # cache 62064019Snyan jmp v86preret # Finish up 62164019Snyan# 62264019Snyan# Emulate WRMSR 62364019Snyan# 62464019Snyanv86wrmsr: movl 0x18(%ebp),%ecx # Get user's %ecx (MSR to write) 62564019Snyan movl 0x14(%ebp),%edx # Load the value 62664019Snyan movl 0x1c(%ebp),%eax # to write 62764019Snyan wrmsr # Write MSR 62864019Snyan jmp v86preret # Finish up 62964019Snyan# 63064019Snyan# Emulate RDMSR 63164019Snyan# 63264019Snyanv86rdmsr: movl 0x18(%ebp),%ecx # MSR to read 63364019Snyan rdmsr # Read the MSR 63464019Snyan movl %eax,0x1c(%ebp) # Return the value of 63564019Snyan movl %edx,0x14(%ebp) # the MSR to the user 63664019Snyan jmp v86preret # Finish up 63764019Snyan# 63843561Skato# Emulate CLI. 63943561Skato# 64043561Skatov86cli: andb $~0x2,0x31(%ebp) # Clear IF 64144368Skato jmp v86mon.7 # Finish up 64243561Skato# 64343561Skato# Emulate STI. 64443561Skato# 64543561Skatov86sti: orb $0x2,0x31(%ebp) # Set IF 64644368Skato jmp v86mon.7 # Finish up 64743561Skato# 64843561Skato# Emulate PUSHF/PUSHFD. 64943561Skato# 65043561Skatov86pushf: subl %ecx,%ebx # Adjust SP 65143561Skato cmpb $0x4,%cl # 32-bit 65243561Skato je v86pushf.1 # Yes 65361064Snyan data16 # 16-bit 65443561Skatov86pushf.1: movl %edx,(%ebx) # Save flags 65544368Skato jmp v86mon.6 # Finish up 65643561Skato# 65743561Skato# Emulate IRET/IRETD. 65843561Skato# 65943561Skatov86iret: movzwl (%ebx),%esi # Load V86 IP 66043561Skato movzwl 0x2(%ebx),%edi # Load V86 CS 66143561Skato leal 0x4(%ebx),%ebx # Adjust SP 66243561Skato movl %edi,0x2c(%ebp) # Save V86 CS 66343561Skato xorl %edi,%edi # No ESI adjustment 66443561Skato# 66543561Skato# Emulate POPF/POPFD (and remainder of IRET/IRETD). 66643561Skato# 66743561Skatov86popf: cmpb $0x4,%cl # 32-bit? 66843561Skato je v86popf.1 # Yes 66943561Skato movl %edx,%eax # Initialize 67061064Snyan data16 # 16-bit 67143561Skatov86popf.1: movl (%ebx),%eax # Load flags 67243561Skato addl %ecx,%ebx # Adjust SP 67343561Skato andl $V86_FLG,%eax # Merge 67443561Skato andl $~V86_FLG,%edx # the 67543561Skato orl %eax,%edx # flags 67644368Skato jmp v86mon.5 # Finish up 67743561Skato# 67852202Skato# trap int 15, function 87 67952202Skato# reads %es:%si from saved registers on stack to find a GDT containing 68052202Skato# source and destination locations 68152202Skato# reads count of words from saved %cx 68252202Skato# returns success by setting %ah to 0 68343561Skato# 68452202Skatoint15_87: pushl %eax # Save 68552202Skato pushl %ebx # some information 68652202Skato pushl %esi # onto the stack. 68752202Skato pushl %edi 68852202Skato xorl %eax,%eax # clean EAX 68952202Skato xorl %ebx,%ebx # clean EBX 69052202Skato movl 0x4(%ebp),%esi # Get user's ESI 69152202Skato movl 0x3C(%ebp),%ebx # store ES 69252202Skato movw %si,%ax # store SI 69352202Skato shll $0x4,%ebx # Make it a seg. 69452202Skato addl %eax,%ebx # ebx=(es<<4)+si 69552202Skato movb 0x14(%ebx),%al # Grab the 69652202Skato movb 0x17(%ebx),%ah # necessary 69752202Skato shll $0x10,%eax # information 69852202Skato movw 0x12(%ebx),%ax # from 69952202Skato movl %eax,%esi # the 70052202Skato movb 0x1c(%ebx),%al # GDT in order to 70152202Skato movb 0x1f(%ebx),%ah # have %esi offset 70252202Skato shll $0x10,%eax # of source and %edi 70352202Skato movw 0x1a(%ebx),%ax # of destination. 70452202Skato movl %eax,%edi 70552202Skato pushl %ds # Make: 70652202Skato popl %es # es = ds 70752202Skato pushl %ecx # stash ECX 70852202Skato xorl %ecx,%ecx # highw of ECX is clear 70952202Skato movw 0x18(%ebp),%cx # Get user's ECX 71058871Skato shll $0x1,%ecx # Convert from num words to num 71158871Skato # bytes 71252202Skato rep # repeat... 71352202Skato movsb # perform copy. 71452202Skato popl %ecx # Restore 71552202Skato popl %edi 71652202Skato popl %esi # previous 71752202Skato popl %ebx # register 71852202Skato popl %eax # values. 71952202Skato movb $0x0,0x1d(%ebp) # set ah = 0 to indicate 72052202Skato # success 72152202Skato andb $0xfe,%dl # clear CF 72252202Skato jmp v86mon.5 # Finish up 72352202Skato 72452202Skato# 72558871Skato# Reboot the machine by setting the reboot flag and exiting 72658871Skato# 72758871Skatoreboot: orb $0x1,btx_hdr+0x7 # Set the reboot flag 72858871Skato jmp exit # Terminate BTX and reboot 72958871Skato 73058871Skato# 73152202Skato# Emulate INT imm8... also make sure to check if it's int 15/87 73252202Skato# 73343561Skatov86intn: lodsb # Get int no 73458871Skato cmpb $0x19,%al # is it int 19? 73558871Skato je reboot # yes, reboot the machine 73652202Skato cmpb $0x15,%al # is it int 15? 73758871Skato jne v86intn.3 # no, skip parse 73852202Skato pushl %eax # stash EAX 73952202Skato movl 0x1c(%ebp),%eax # user's saved EAX 74058871Skato cmpb $0x87,%ah # is it the memcpy subfunction? 74158871Skato jne v86intn.1 # no, keep checking 74252202Skato popl %eax # get the stack straight 74352202Skato jmp int15_87 # it's our cue 74458871Skatov86intn.1: cmpw $0x4f53,%ax # is it the delete key callout? 74558871Skato jne v86intn.2 # no, handle the int normally 74658871Skato movb BDA_KEYFLAGS,%al # get the shift key state 74758871Skato.`ifdef' PC98 74858871Skato andb $0x18,%al # mask off just Ctrl and Alt 74958871Skato cmpb $0x18,%al # are both Ctrl and Alt down? 75058871Skato.else 75158871Skato andb $0xc,%al # mask off just Ctrl and Alt 75258871Skato cmpb $0xc,%al # are both Ctrl and Alt down? 75358871Skato.endif 75458871Skato jne v86intn.2 # no, handle the int normally 75558871Skato popl %eax # restore EAX 75658871Skato jmp reboot # reboot the machine 75758871Skatov86intn.2: popl %eax # restore EAX 75858871Skatov86intn.3: subl %edi,%esi # From 75943561Skato shrl $0x4,%edi # linear 76043561Skato movw %dx,-0x2(%ebx) # Save flags 76143561Skato movw %di,-0x4(%ebx) # Save CS 76243561Skato leal -0x6(%ebx),%ebx # Adjust SP 76343561Skato movw %si,(%ebx) # Save IP 76443561Skato shll $0x2,%eax # Scale 76543561Skato movzwl (%eax),%esi # Load IP 76643561Skato movzwl 0x2(%eax),%edi # Load CS 76743561Skato movl %edi,0x2c(%ebp) # Save CS 76843561Skato xorl %edi,%edi # No ESI adjustment 76961064Snyan andb $~0x1,%dh # Clear TF 77044368Skato jmp v86mon.5 # Finish up 77143561Skato# 77243561Skato# Hardware interrupt jump table. 77343561Skato# 77461064Snyanintx20: push $0x8 # Int 0x20: IRQ0 77543561Skato jmp int_hw # V86 int 0x8 77661064Snyan push $0x9 # Int 0x21: IRQ1 77743561Skato jmp int_hw # V86 int 0x9 77861064Snyan push $0xa # Int 0x22: IRQ2 77943561Skato jmp int_hw # V86 int 0xa 78061064Snyan push $0xb # Int 0x23: IRQ3 78143561Skato jmp int_hw # V86 int 0xb 78261064Snyan push $0xc # Int 0x24: IRQ4 78343561Skato jmp int_hw # V86 int 0xc 78461064Snyan push $0xd # Int 0x25: IRQ5 78543561Skato jmp int_hw # V86 int 0xd 78661064Snyan push $0xe # Int 0x26: IRQ6 78743561Skato jmp int_hw # V86 int 0xe 78861064Snyan push $0xf # Int 0x27: IRQ7 78943561Skato jmp int_hw # V86 int 0xf 79043561Skato.`ifdef' PC98 79161064Snyan push $0x10 # Int 0x28: IRQ8 79243561Skato jmp int_hw # V86 int 0x10 79361064Snyan push $0x11 # Int 0x29: IRQ9 79443561Skato jmp int_hw # V86 int 0x11 79561064Snyan push $0x12 # Int 0x2a: IRQ10 79643561Skato jmp int_hw # V86 int 0x12 79761064Snyan push $0x13 # Int 0x2b: IRQ11 79843561Skato jmp int_hw # V86 int 0x13 79961064Snyan push $0x14 # Int 0x2c: IRQ12 80043561Skato jmp int_hw # V86 int 0x14 80161064Snyan push $0x15 # Int 0x2d: IRQ13 80243561Skato jmp int_hw # V86 int 0x15 80361064Snyan push $0x16 # Int 0x2e: IRQ14 80443561Skato jmp int_hw # V86 int 0x16 80561064Snyan push $0x17 # Int 0x2f: IRQ15 80643561Skato jmp int_hw # V86 int 0x17 80743561Skato.else 80861064Snyan push $0x70 # Int 0x28: IRQ8 80943561Skato jmp int_hw # V86 int 0x70 81061064Snyan push $0x71 # Int 0x29: IRQ9 81143561Skato jmp int_hw # V86 int 0x71 81261064Snyan push $0x72 # Int 0x2a: IRQ10 81343561Skato jmp int_hw # V86 int 0x72 81461064Snyan push $0x73 # Int 0x2b: IRQ11 81543561Skato jmp int_hw # V86 int 0x73 81661064Snyan push $0x74 # Int 0x2c: IRQ12 81743561Skato jmp int_hw # V86 int 0x74 81861064Snyan push $0x75 # Int 0x2d: IRQ13 81943561Skato jmp int_hw # V86 int 0x75 82061064Snyan push $0x76 # Int 0x2e: IRQ14 82143561Skato jmp int_hw # V86 int 0x76 82261064Snyan push $0x77 # Int 0x2f: IRQ15 82343561Skato jmp int_hw # V86 int 0x77 82443561Skato.endif 82543561Skato# 82643561Skato# Reflect hardware interrupts. 82743561Skato# 82843561Skatoint_hw: testb $0x2,0xe(%esp,1) # V86 mode? 82943561Skato jz intusr # No 83043561Skato pushl $SEL_SDATA # Address 83143561Skato popl %ds # data 83243561Skato xchgl %eax,(%esp,1) # Swap EAX, int no 83343561Skato pushl %ebp # Address 83443561Skato movl %esp,%ebp # stack frame 83543561Skato pushl %ebx # Save 83643561Skato shll $0x2,%eax # Get int 83743561Skato movl (%eax),%eax # vector 83843561Skato subl $0x6,0x14(%ebp) # Adjust V86 ESP 83943561Skato movzwl 0x18(%ebp),%ebx # V86 SS 84043561Skato shll $0x4,%ebx # * 0x10 84143561Skato addl 0x14(%ebp),%ebx # + V86 ESP 84243561Skato xchgw %ax,0x8(%ebp) # Swap V86 IP 84343561Skato rorl $0x10,%eax # Swap words 84443561Skato xchgw %ax,0xc(%ebp) # Swap V86 CS 84543561Skato roll $0x10,%eax # Swap words 84643561Skato movl %eax,(%ebx) # CS:IP for IRET 84743561Skato movl 0x10(%ebp),%eax # V86 flags 84843561Skato movw %ax,0x4(%ebx) # Flags for IRET 84943561Skato andb $~0x3,0x11(%ebp) # Clear IF, TF 85043561Skato popl %ebx # Restore 85143561Skato popl %ebp # saved 85243561Skato popl %eax # registers 85343561Skato iret # To V86 mode 85443561Skato# 85543561Skato# Invoke V86 interrupt from user mode, with arguments. 85643561Skato# 85743561Skatointx31: stc # Have btx_v86 85843561Skato pushl %eax # Missing int no 85943561Skato# 86043561Skato# Invoke V86 interrupt from user mode. 86143561Skato# 86243561Skatointusr: std # String ops dec 86343561Skato pushl %eax # Expand 86443561Skato pushl %eax # stack 86543561Skato pushl %eax # frame 86643561Skato pusha # Save 86743561Skato pushl %gs # Save 86843561Skato movl %esp,%eax # seg regs 86943561Skato pushl %fs # and 87043561Skato pushl %ds # point 87143561Skato pushl %es # to them 87261064Snyan push $SEL_SDATA # Set up 87343561Skato popl %ds # to 87443561Skato pushl %ds # address 87543561Skato popl %es # data 87643561Skato movl $MEM_USR,%ebx # User base 87743561Skato movl %ebx,%edx # address 87843561Skato jc intusr.1 # If btx_v86 87943561Skato xorl %edx,%edx # Control flags 88043561Skato xorl %ebp,%ebp # btx_v86 pointer 88143561Skatointusr.1: leal 0x50(%esp,1),%esi # Base of frame 88243561Skato pushl %esi # Save 88343561Skato addl -0x4(%esi),%ebx # User ESP 88443561Skato movl MEM_TSS+TSS_ESP1,%edi # Link stack pointer 88543561Skato leal -0x4(%edi),%edi # Adjust for push 88643561Skato xorl %ecx,%ecx # Zero 88743561Skato movb $0x5,%cl # Push exception 88843561Skato rep # frame on 88943561Skato movsl # link stack 89043561Skato xchgl %eax,%esi # Saved seg regs 89143561Skato movl 0x40(%esp,1),%eax # Get int no 89243561Skato testl %edx,%edx # Have btx_v86? 89343561Skato jz intusr.2 # No 89443561Skato movl (%ebx),%ebp # btx_v86 pointer 89543561Skato movb $0x4,%cl # Count 89643561Skato addl %ecx,%ebx # Adjust for pop 89743561Skato rep # Push saved seg regs 89843561Skato movsl # on link stack 89943561Skato addl %ebp,%edx # Flatten btx_v86 ptr 90043561Skato leal 0x14(%edx),%esi # Seg regs pointer 90143561Skato movl 0x4(%edx),%eax # Get int no/address 90243561Skato movzwl 0x2(%edx),%edx # Get control flags 90343561Skatointusr.2: movl %ebp,(%edi) # Push btx_v86 and 90443561Skato movl %edi,MEM_TSS+TSS_ESP1 # save link stack ptr 90543561Skato popl %edi # Base of frame 90643561Skato xchgl %eax,%ebp # Save intno/address 90743561Skato movl 0x48(%esp,1),%eax # Get flags 90843561Skato testb $0x2,%dl # Simulate CALLF? 90943561Skato jnz intusr.3 # Yes 91043561Skato decl %ebx # Push flags 91143561Skato decl %ebx # on V86 91243561Skato movw %ax,(%ebx) # stack 91343561Skatointusr.3: movb $0x4,%cl # Count 91443561Skato subl %ecx,%ebx # Push return address 91543561Skato movl $inthlt,(%ebx) # on V86 stack 91643561Skato rep # Copy seg regs to 91743561Skato movsl # exception frame 91843561Skato xchgl %eax,%ecx # Save flags 91943561Skato movl %ebx,%eax # User ESP 92043561Skato subl $V86_STK,%eax # Less bytes 92143561Skato ja intusr.4 # to 92243561Skato xorl %eax,%eax # keep 92343561Skatointusr.4: shrl $0x4,%eax # Gives segment 92443561Skato stosl # Set SS 92543561Skato shll $0x4,%eax # To bytes 92643561Skato xchgl %eax,%ebx # Swap 92743561Skato subl %ebx,%eax # Gives offset 92843561Skato stosl # Set ESP 92943561Skato xchgl %eax,%ecx # Get flags 93043561Skato btsl $0x11,%eax # Set VM 93161064Snyan andb $~0x1,%ah # Clear TF 93243561Skato stosl # Set EFL 93343561Skato xchgl %eax,%ebp # Get int no/address 93443561Skato testb $0x1,%dl # Address? 93543561Skato jnz intusr.5 # Yes 93643561Skato shll $0x2,%eax # Scale 93743561Skato movl (%eax),%eax # Load int vector 93843561Skatointusr.5: movl %eax,%ecx # Save 93943561Skato shrl $0x10,%eax # Gives segment 94043561Skato stosl # Set CS 94143561Skato movw %cx,%ax # Restore 94243561Skato stosl # Set EIP 94343561Skato leal 0x10(%esp,1),%esp # Discard seg regs 94443561Skato popa # Restore 94543561Skato iret # To V86 mode 94643561Skato# 94743561Skato# System Call. 94843561Skato# 94943561Skatointx30: cmpl $SYS_EXEC,%eax # Exec system call? 95043561Skato jne intx30.1 # No 95143561Skato pushl %ss # Set up 95243561Skato popl %es # all 95343561Skato pushl %es # segment 95443561Skato popl %ds # registers 95543561Skato pushl %ds # for the 95643561Skato popl %fs # program 95743561Skato pushl %fs # we're 95843561Skato popl %gs # invoking 95943561Skato movl $MEM_USR,%eax # User base address 96043561Skato addl 0xc(%esp,1),%eax # Change to user 96143561Skato leal 0x4(%eax),%esp # stack 96256813Skatoifdef(`PAGING',` 96343561Skato movl %cr0,%eax # Turn 96443561Skato andl $~0x80000000,%eax # off 96543561Skato movl %eax,%cr0 # paging 96643561Skato xorl %eax,%eax # Flush 96743561Skato movl %eax,%cr3 # TLB 96856813Skato') 96943561Skato popl %eax # Call 97043561Skato call *%eax # program 97178650Skatointx30.1: orb $0x1,%ss:btx_hdr+0x7 # Flag reboot 97243561Skato jmp exit # Exit 97343561Skato# 97443561Skato# Dump structure [EBX] to [EDI], using format string [ESI]. 97543561Skato# 97643561Skatodump.0: stosb # Save char 97743561Skatodump: lodsb # Load char 97843561Skato testb %al,%al # End of string? 97943561Skato jz dump.10 # Yes 98043561Skato testb $0x80,%al # Control? 98143561Skato jz dump.0 # No 98243561Skato movb %al,%ch # Save control 98343561Skato movb $'=',%al # Append 98443561Skato stosb # '=' 98543561Skato lodsb # Get offset 98643561Skato pushl %esi # Save 98743561Skato movsbl %al,%esi # To 98843561Skato addl %ebx,%esi # pointer 98943561Skato testb $DMP_X16,%ch # Dump word? 99043561Skato jz dump.1 # No 99143561Skato lodsw # Get and 99243561Skato call hex16 # dump it 99343561Skatodump.1: testb $DMP_X32,%ch # Dump long? 99443561Skato jz dump.2 # No 99543561Skato lodsl # Get and 99643561Skato call hex32 # dump it 99743561Skatodump.2: testb $DMP_MEM,%ch # Dump memory? 99843561Skato jz dump.8 # No 99943561Skato pushl %ds # Save 100043561Skato testb $0x2,0x52(%ebx) # V86 mode? 100143561Skato jnz dump.3 # Yes 100261064Snyan verr 0x4(%esi) # Readable selector? 100343561Skato jnz dump.3 # No 100443561Skato ldsl (%esi),%esi # Load pointer 100543561Skato jmp dump.4 # Join common code 100643561Skatodump.3: lodsl # Set offset 100743561Skato xchgl %eax,%edx # Save 100843561Skato lodsl # Get segment 100943561Skato shll $0x4,%eax # * 0x10 101043561Skato addl %edx,%eax # + offset 101143561Skato xchgl %eax,%esi # Set pointer 101243561Skatodump.4: movb $0x10,%cl # Bytes to dump 101343561Skatodump.5: lodsb # Get byte and 101443561Skato call hex8 # dump it 101543561Skato decb %cl # Keep count 101643561Skato jz dump.7 # If done 101743561Skato movb $'-',%al # Separator 101843561Skato cmpb $0x8,%cl # Half way? 101943561Skato je dump.6 # Yes 102043561Skato movb $' ',%al # Use space 102143561Skatodump.6: stosb # Save separator 102243561Skato jmp dump.5 # Continue 102343561Skatodump.7: popl %ds # Restore 102443561Skatodump.8: popl %esi # Restore 102543561Skato movb $0xa,%al # Line feed 102643561Skato testb $DMP_EOL,%ch # End of line? 102743561Skato jnz dump.9 # Yes 102843561Skato movb $' ',%al # Use spaces 102943561Skato stosb # Save one 103043561Skatodump.9: jmp dump.0 # Continue 103143561Skatodump.10: stosb # Terminate string 103243561Skato ret # To caller 103343561Skato# 103443561Skato# Convert EAX, AX, or AL to hex, saving the result to [EDI]. 103543561Skato# 103643561Skatohex32: pushl %eax # Save 103743561Skato shrl $0x10,%eax # Do upper 103843561Skato call hex16 # 16 103943561Skato popl %eax # Restore 104043561Skatohex16: call hex16.1 # Do upper 8 104143561Skatohex16.1: xchgb %ah,%al # Save/restore 104243561Skatohex8: pushl %eax # Save 104343561Skato shrb $0x4,%al # Do upper 104443561Skato call hex8.1 # 4 104543561Skato popl %eax # Restore 104643561Skatohex8.1: andb $0xf,%al # Get lower 4 104743561Skato cmpb $0xa,%al # Convert 104843561Skato sbbb $0x69,%al # to hex 104943561Skato das # digit 105043561Skato orb $0x20,%al # To lower case 105143561Skato stosb # Save char 105243561Skato ret # (Recursive) 105343561Skato# 105443561Skato# Output zero-terminated string [ESI] to the console. 105543561Skato# 105643561Skatoputstr.0: call putchr # Output char 105743561Skatoputstr: lodsb # Load char 105843561Skato testb %al,%al # End of string? 105943561Skato jnz putstr.0 # No 106043561Skato ret # To caller 106143561Skato# 106243561Skato# Output character AL to the console. 106343561Skato# 106443561Skatoputchr: pusha # Save 106543561Skato xorl %ecx,%ecx # Zero for loops 106643561Skato movb $SCR_MAT,%ah # Mode/attribute 106743561Skato movl $BDA_POS,%ebx # BDA pointer 106843561Skato movw (%ebx),%dx # Cursor position 106943561Skato.`ifdef' PC98 107043561Skato movl $0xa0000,%edi 107143561Skato.else 107243561Skato movl $0xb8000,%edi # Regen buffer (color) 107343561Skato cmpb %ah,BDA_SCR-BDA_POS(%ebx) # Mono mode? 107443561Skato jne putchr.1 # No 107543561Skato xorw %di,%di # Regen buffer (mono) 107643561Skato.endif 107743561Skatoputchr.1: cmpb $0xa,%al # New line? 107843561Skato je putchr.2 # Yes 107943561Skato.`ifdef' PC98 108043561Skato movw %dx,%cx 108143561Skato movb %al,(%edi,%ecx,1) # Write char 108243561Skato addl $0x2000,%ecx 108343561Skato movb %ah,(%edi,%ecx,1) # Write attr 108443561Skato addw $0x02,%dx 108543561Skato jmp putchr.3 108643561Skatoputchr.2: movw %dx,%ax 108743561Skato movb $SCR_COL*2,%dl 108843561Skato div %dl 108943561Skato incb %al 109043561Skato mul %dl 109143561Skato movw %ax,%dx 109243561Skatoputchr.3: cmpw $SCR_ROW*SCR_COL*2,%dx 109343561Skato.else 109443561Skato xchgl %eax,%ecx # Save char 109543561Skato movb $SCR_COL,%al # Columns per row 109643561Skato mulb %dh # * row position 109743561Skato addb %dl,%al # + column 109843561Skato adcb $0x0,%ah # position 109943561Skato shll %eax # * 2 110043561Skato xchgl %eax,%ecx # Swap char, offset 110143561Skato movw %ax,(%edi,%ecx,1) # Write attr:char 110243561Skato incl %edx # Bump cursor 110343561Skato cmpb $SCR_COL,%dl # Beyond row? 110443561Skato jb putchr.3 # No 110543561Skatoputchr.2: xorb %dl,%dl # Zero column 110643561Skato incb %dh # Bump row 110743561Skatoputchr.3: cmpb $SCR_ROW,%dh # Beyond screen? 110843561Skato.endif 110943561Skato jb putchr.4 # No 111043561Skato leal 2*SCR_COL(%edi),%esi # New top line 111143561Skato movw $(SCR_ROW-1)*SCR_COL/2,%cx # Words to move 111243561Skato rep # Scroll 111343561Skato movsl # screen 111443561Skato movb $' ',%al # Space 111543561Skato.`ifdef' PC98 111643561Skato xorb %ah,%ah 111743561Skato.endif 111843561Skato movb $SCR_COL,%cl # Columns to clear 111943561Skato rep # Clear 112043561Skato stosw # line 112143561Skato.`ifdef' PC98 112243561Skato movw $(SCR_ROW-1)*SCR_COL*2,%dx 112343561Skato.else 112443561Skato movb $SCR_ROW-1,%dh # Bottom line 112543561Skato.endif 112643561Skatoputchr.4: movw %dx,(%ebx) # Update position 112743561Skato popa # Restore 112843561Skato ret # To caller 112943561Skato 113043561Skato .p2align 4 113143561Skato# 113243561Skato# Global descriptor table. 113343561Skato# 113443561Skatogdt: .word 0x0,0x0,0x0,0x0 # Null entry 113543561Skato .word 0xffff,0x0,0x9a00,0xcf # SEL_SCODE 113643561Skato .word 0xffff,0x0,0x9200,0xcf # SEL_SDATA 113743561Skato .word 0xffff,0x0,0x9a00,0x0 # SEL_RCODE 113843561Skato .word 0xffff,0x0,0x9200,0x0 # SEL_RDATA 113943561Skato .word 0xffff,MEM_USR,0xfa00,0xcf# SEL_UCODE 114043561Skato .word 0xffff,MEM_USR,0xf200,0xcf# SEL_UDATA 114143561Skato .word _TSSLM,MEM_TSS,0x8900,0x0 # SEL_TSS 114243561Skatogdt.1: 114343561Skato# 114443561Skato# Pseudo-descriptors. 114543561Skato# 114643561Skatogdtdesc: .word gdt.1-gdt-1,gdt,0x0 # GDT 114743561Skatoidtdesc: .word _IDTLM,MEM_IDT,0x0 # IDT 114843561Skatoivtdesc: .word 0x400-0x0-1,0x0,0x0 # IVT 114943561Skato# 115043561Skato# IDT construction control string. 115143561Skato# 115243561Skatoidtctl: .byte 0x10, 0x8e # Int 0x0-0xf 115343561Skato .word 0x7dfb,intx00 # (exceptions) 115443561Skato .byte 0x10, 0x8e # Int 0x10 115543561Skato .word 0x1, intx10 # (exception) 115643561Skato .byte 0x10, 0x8e # Int 0x20-0x2f 115743561Skato .word 0xffff,intx20 # (hardware) 115843561Skato .byte 0x1, 0xee # int 0x30 115943561Skato .word 0x1, intx30 # (system call) 116043561Skato .byte 0x2, 0xee # Int 0x31-0x32 116143561Skato .word 0x1, intx31 # (V86, null) 116243561Skato .byte 0x0 # End of string 116343561Skato# 116443561Skato# Dump format string. 116543561Skato# 116643561Skatodmpfmt: .byte '\n' # "\n" 116743561Skato .ascii "int" # "int=" 116843561Skato .byte 0x80|DMP_X32, 0x40 # "00000000 " 116943561Skato .ascii "err" # "err=" 117043561Skato .byte 0x80|DMP_X32, 0x44 # "00000000 " 117143561Skato .ascii "efl" # "efl=" 117243561Skato .byte 0x80|DMP_X32, 0x50 # "00000000 " 117343561Skato .ascii "eip" # "eip=" 117443561Skato .byte 0x80|DMP_X32|DMP_EOL,0x48 # "00000000\n" 117543561Skato .ascii "eax" # "eax=" 117643561Skato .byte 0x80|DMP_X32, 0x34 # "00000000 " 117743561Skato .ascii "ebx" # "ebx=" 117843561Skato .byte 0x80|DMP_X32, 0x28 # "00000000 " 117943561Skato .ascii "ecx" # "ecx=" 118043561Skato .byte 0x80|DMP_X32, 0x30 # "00000000 " 118143561Skato .ascii "edx" # "edx=" 118243561Skato .byte 0x80|DMP_X32|DMP_EOL,0x2c # "00000000\n" 118343561Skato .ascii "esi" # "esi=" 118443561Skato .byte 0x80|DMP_X32, 0x1c # "00000000 " 118543561Skato .ascii "edi" # "edi=" 118643561Skato .byte 0x80|DMP_X32, 0x18 # "00000000 " 118743561Skato .ascii "ebp" # "ebp=" 118843561Skato .byte 0x80|DMP_X32, 0x20 # "00000000 " 118943561Skato .ascii "esp" # "esp=" 119043561Skato .byte 0x80|DMP_X32|DMP_EOL,0x0 # "00000000\n" 119143561Skato .ascii "cs" # "cs=" 119243561Skato .byte 0x80|DMP_X16, 0x4c # "0000 " 119343561Skato .ascii "ds" # "ds=" 119443561Skato .byte 0x80|DMP_X16, 0xc # "0000 " 119543561Skato .ascii "es" # "es=" 119643561Skato .byte 0x80|DMP_X16, 0x8 # "0000 " 119743561Skato .ascii " " # " " 119843561Skato .ascii "fs" # "fs=" 119943561Skato .byte 0x80|DMP_X16, 0x10 # "0000 " 120043561Skato .ascii "gs" # "gs=" 120143561Skato .byte 0x80|DMP_X16, 0x14 # "0000 " 120243561Skato .ascii "ss" # "ss=" 120343561Skato .byte 0x80|DMP_X16|DMP_EOL,0x4 # "0000\n" 120443561Skato .ascii "cs:eip" # "cs:eip=" 120543561Skato .byte 0x80|DMP_MEM|DMP_EOL,0x48 # "00 00 ... 00 00\n" 120643561Skato .ascii "ss:esp" # "ss:esp=" 120743561Skato .byte 0x80|DMP_MEM|DMP_EOL,0x0 # "00 00 ... 00 00\n" 120864019Snyan .asciz "BTX halted" # End 120943561Skato# 121043561Skato# End of BTX memory. 121143561Skato# 121243561Skato .p2align 4 121343561Skatobreak: 1214