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