]> CyberLeo.Net >> Repos - FreeBSD/releng/8.0.git/blob - sys/boot/pc98/btx/btx/btx.S
Adjust to reflect 8.0-RELEASE.
[FreeBSD/releng/8.0.git] / sys / boot / pc98 / btx / btx / btx.S
1 /*
2  * Copyright (c) 1998 Robert Nordier
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are freely
6  * permitted provided that the above copyright notice and this
7  * paragraph and the following disclaimer are duplicated in all
8  * such forms.
9  *
10  * This software is provided "AS IS" and without any express or
11  * implied warranties, including, without limitation, the implied
12  * warranties of merchantability and fitness for a particular
13  * purpose.
14  *
15  * $FreeBSD$
16  */
17
18 /*
19  * Memory layout.
20  */
21                 .set MEM_BTX,0x1000             # Start of BTX memory
22                 .set MEM_ESP0,0x1800            # Supervisor stack
23                 .set MEM_BUF,0x1800             # Scratch buffer
24                 .set MEM_ESP1,0x1e00            # Link stack
25                 .set MEM_IDT,0x1e00             # IDT
26                 .set MEM_TSS,0x1f98             # TSS
27                 .set MEM_MAP,0x2000             # I/O bit map
28                 .set MEM_TSS_END,0x3fff         # Page directory
29                 .set MEM_ORG,0x9000             # BTX code
30                 .set MEM_USR,0xa000             # Start of user memory
31 /*
32  * Paging control.
33  */
34                 .set PAG_SIZ,0x1000             # Page size
35                 .set PAG_CNT,0x1000             # Pages to map
36 /*
37  * Segment selectors.
38  */
39                 .set SEL_SCODE,0x8              # Supervisor code
40                 .set SEL_SDATA,0x10             # Supervisor data
41                 .set SEL_RCODE,0x18             # Real mode code
42                 .set SEL_RDATA,0x20             # Real mode data
43                 .set SEL_UCODE,0x28|3           # User code
44                 .set SEL_UDATA,0x30|3           # User data
45                 .set SEL_TSS,0x38               # TSS
46 /*
47  * Task state segment fields.
48  */
49                 .set TSS_ESP0,0x4               # PL 0 ESP
50                 .set TSS_SS0,0x8                # PL 0 SS
51                 .set TSS_ESP1,0xc               # PL 1 ESP
52                 .set TSS_MAP,0x66               # I/O bit map base
53 /*
54  * System calls.
55  */
56                 .set SYS_EXIT,0x0               # Exit
57                 .set SYS_EXEC,0x1               # Exec
58 /*
59  * V86 constants.
60  */
61                 .set V86_FLG,0x208eff           # V86 flag mask
62                 .set V86_STK,0x400              # V86 stack allowance
63 /*
64  * Dump format control bytes.
65  */
66                 .set DMP_X16,0x1                # Word
67                 .set DMP_X32,0x2                # Long
68                 .set DMP_MEM,0x4                # Memory
69                 .set DMP_EOL,0x8                # End of line
70 /*
71  * Screen defaults and assumptions.
72  */
73                 .set SCR_MAT,0xe1               # Mode/attribute
74                 .set SCR_COL,0x50               # Columns per row
75                 .set SCR_ROW,0x19               # Rows per screen
76 /*
77  * BIOS Data Area locations.
78  */
79                 .set BDA_MEM,0x501              # Free memory
80                 .set BDA_KEYFLAGS,0x53a         # Keyboard shift-state flags
81                 .set BDA_POS,0x53e              # Cursor position
82 /*
83  * Derivations, for brevity.
84  */
85                 .set _ESP0H,MEM_ESP0>>0x8       # Byte 1 of ESP0
86                 .set _ESP1H,MEM_ESP1>>0x8       # Byte 1 of ESP1
87                 .set _TSSIO,MEM_MAP-MEM_TSS     # TSS I/O base
88                 .set _TSSLM,MEM_TSS_END-MEM_TSS # TSS limit
89                 .set _IDTLM,MEM_TSS-MEM_IDT-1   # IDT limit
90 /*
91  * Code segment.
92  */
93                 .globl start
94                 .code16
95 start:                                          # Start of code
96 /*
97  * BTX header.
98  */
99 btx_hdr:        .byte 0xeb                      # Machine ID
100                 .byte 0xe                       # Header size
101                 .ascii "BTX"                    # Magic
102                 .byte 0x1                       # Major version
103                 .byte 0x1                       # Minor version
104                 .byte BTX_FLAGS                 # Flags
105                 .word PAG_CNT-MEM_ORG>>0xc      # Paging control
106                 .word break-start               # Text size
107                 .long 0x0                       # Entry address
108 /*
109  * Initialization routine.
110  */
111 init:           cli                             # Disable interrupts
112                 xor %ax,%ax                     # Zero/segment
113                 mov %ax,%ss                     # Set up
114                 mov $MEM_ESP0,%sp               #  stack
115                 mov %ax,%es                     # Address
116                 mov %ax,%ds                     #  data
117                 pushl $0x2                      # Clear
118                 popfl                           #  flags
119 /*
120  * Initialize memory.
121  */
122                 mov $MEM_IDT,%di                # Memory to initialize
123                 mov $(MEM_ORG-MEM_IDT)/2,%cx    # Words to zero
124                 push %di                        # Save
125                 rep                             # Zero-fill
126                 stosw                           #  memory
127                 pop %di                         # Restore
128 /*
129  * Create IDT.
130  */
131                 mov $idtctl,%si                 # Control string
132 init.1:         lodsb                           # Get entry
133                 cbw                             #  count
134                 xchg %ax,%cx                    #  as word
135                 jcxz init.4                     # If done
136                 lodsb                           # Get segment
137                 xchg %ax,%dx                    #  P:DPL:type
138                 lodsw                           # Get control
139                 xchg %ax,%bx                    #  set
140                 lodsw                           # Get handler offset
141                 mov $SEL_SCODE,%dh              # Segment selector
142 init.2:         shr %bx                         # Handle this int?
143                 jnc init.3                      # No
144                 mov %ax,(%di)                   # Set handler offset
145                 mov %dh,0x2(%di)                #  and selector
146                 mov %dl,0x5(%di)                # Set P:DPL:type
147                 add $0x4,%ax                    # Next handler
148 init.3:         lea 0x8(%di),%di                # Next entry
149                 loop init.2                     # Till set done
150                 jmp init.1                      # Continue
151 /*
152  * Initialize TSS.
153  */
154 init.4:         movb $_ESP0H,TSS_ESP0+1(%di)    # Set ESP0
155                 movb $SEL_SDATA,TSS_SS0(%di)    # Set SS0
156                 movb $_ESP1H,TSS_ESP1+1(%di)    # Set ESP1
157                 movb $_TSSIO,TSS_MAP(%di)       # Set I/O bit map base
158 /*
159  * Bring up the system.
160  */
161                 mov $0x2820,%bx                 # Set protected mode
162                 callw setpic                    #  IRQ offsets
163                 lidt idtdesc                    # Set IDT
164                 lgdt gdtdesc                    # Set GDT
165                 mov %cr0,%eax                   # Switch to protected
166                 inc %ax                         #  mode
167                 mov %eax,%cr0                   #
168                 ljmp $SEL_SCODE,$init.8         # To 32-bit code
169                 .code32
170 init.8:         xorl %ecx,%ecx                  # Zero
171                 movb $SEL_SDATA,%cl             # To 32-bit
172                 movw %cx,%ss                    #  stack
173 /*
174  * Launch user task.
175  */
176                 movb $SEL_TSS,%cl               # Set task
177                 ltr %cx                         #  register
178                 movl $MEM_USR,%edx              # User base address
179                 movzwl %ss:BDA_MEM,%eax         # Get free memory
180                 andl $0x7,%eax
181                 incl %eax
182                 shll $0x11,%eax                 # To bytes
183                 subl $0x1000,%eax               # Less arg space
184                 subl %edx,%eax                  # Less base
185                 movb $SEL_UDATA,%cl             # User data selector
186                 pushl %ecx                      # Set SS
187                 pushl %eax                      # Set ESP
188                 push $0x202                     # Set flags (IF set)
189                 push $SEL_UCODE                 # Set CS
190                 pushl btx_hdr+0xc               # Set EIP
191                 pushl %ecx                      # Set GS
192                 pushl %ecx                      # Set FS
193                 pushl %ecx                      # Set DS
194                 pushl %ecx                      # Set ES
195                 pushl %edx                      # Set EAX
196                 movb $0x7,%cl                   # Set remaining
197 init.9:         push $0x0                       #  general
198                 loop init.9                     #  registers
199 #ifdef BTX_SERIAL
200                 call sio_init                   # setup the serial console
201 #endif
202                 popa                            #  and initialize
203                 popl %es                        # Initialize
204                 popl %ds                        #  user
205                 popl %fs                        #  segment
206                 popl %gs                        #  registers
207                 iret                            # To user mode
208 /*
209  * Exit routine.
210  */
211 exit:           cli                             # Disable interrupts
212                 movl $MEM_ESP0,%esp             # Clear stack
213 /*
214  * Turn off paging.
215  */
216                 movl %cr0,%eax                  # Get CR0
217                 andl $~0x80000000,%eax          # Disable
218                 movl %eax,%cr0                  #  paging
219                 xorl %ecx,%ecx                  # Zero
220                 movl %ecx,%cr3                  # Flush TLB
221 /*
222  * Restore the GDT in case we caught a kernel trap.
223  */
224                 lgdt gdtdesc                    # Set GDT
225 /*
226  * To 16 bits.
227  */
228                 ljmpw $SEL_RCODE,$exit.1        # Reload CS
229                 .code16
230 exit.1:         mov $SEL_RDATA,%cl              # 16-bit selector
231                 mov %cx,%ss                     # Reload SS
232                 mov %cx,%ds                     # Load
233                 mov %cx,%es                     #  remaining
234                 mov %cx,%fs                     #  segment
235                 mov %cx,%gs                     #  registers
236 /*
237  * To real-address mode.
238  */
239                 dec %ax                         # Switch to
240                 mov %eax,%cr0                   #  real mode
241                 ljmp $0x0,$exit.2               # Reload CS
242 exit.2:         xor %ax,%ax                     # Real mode segment
243                 mov %ax,%ss                     # Reload SS
244                 mov %ax,%ds                     # Address data
245                 mov $0x1008,%bx                 # Set real mode
246                 callw setpic                    #  IRQ offsets
247                 lidt ivtdesc                    # Set IVT
248 /*
249  * Reboot or await reset.
250  */
251                 sti                             # Enable interrupts
252                 testb $0x1,btx_hdr+0x7          # Reboot?
253 exit.3:         jz exit.3                       # No
254                 movb $0xa0,%al
255                 outb %al,$0x35
256                 movb 0,%al
257                 outb %al,$0xf0
258 exit.4:         jmp exit.4
259 /*
260  * Set IRQ offsets by reprogramming 8259A PICs.
261  */
262 setpic:         in $0x02,%al                    # Save master
263                 push %ax                        #  IMR
264                 in $0x0a,%al                    # Save slave
265                 push %ax                        #  IMR
266                 movb $0x11,%al                  # ICW1 to
267                 outb %al,$0x00                  #  master,
268                 outb %al,$0x08                  #  slave
269                 movb %bl,%al                    # ICW2 to
270                 outb %al,$0x02                  #  master
271                 movb %bh,%al                    # ICW2 to
272                 outb %al,$0x0a                  #  slave
273                 movb $0x80,%al                  # ICW3 to
274                 outb %al,$0x02                  #  master
275                 movb $0x7,%al                   # ICW3 to
276                 outb %al,$0x0a                  #  slave
277                 movb $0x1d,%al                  # ICW4 to
278                 outb %al,$0x02                  #  master,
279                 movb $0x9,%al                   # ICW4 to
280                 outb %al,$0x0a                  #  slave
281                 pop %ax                         # Restore slave
282                 outb %al,$0x0a                  #  IMR
283                 pop %ax                         # Restore master
284                 outb %al,$0x02                  #  IMR
285                 retw                            # To caller
286                 .code32
287 /*
288  * Initiate return from V86 mode to user mode.
289  */
290 inthlt:         hlt                             # To supervisor mode
291 /*
292  * Exception jump table.
293  */
294 intx00:         push $0x0                       # Int 0x0: #DE
295                 jmp ex_noc                      # Divide error
296                 push $0x1                       # Int 0x1: #DB
297                 jmp ex_noc                      # Debug
298                 push $0x3                       # Int 0x3: #BP
299                 jmp ex_noc                      # Breakpoint
300                 push $0x4                       # Int 0x4: #OF
301                 jmp ex_noc                      # Overflow
302                 push $0x5                       # Int 0x5: #BR
303                 jmp ex_noc                      # BOUND range exceeded
304                 push $0x6                       # Int 0x6: #UD
305                 jmp ex_noc                      # Invalid opcode
306                 push $0x7                       # Int 0x7: #NM
307                 jmp ex_noc                      # Device not available
308                 push $0x8                       # Int 0x8: #DF
309                 jmp except                      # Double fault
310                 push $0xa                       # Int 0xa: #TS
311                 jmp except                      # Invalid TSS
312                 push $0xb                       # Int 0xb: #NP
313                 jmp except                      # Segment not present
314                 push $0xc                       # Int 0xc: #SS
315                 jmp except                      # Stack segment fault
316                 push $0xd                       # Int 0xd: #GP
317                 jmp ex_v86                      # General protection
318                 push $0xe                       # Int 0xe: #PF
319                 jmp except                      # Page fault
320 intx10:         push $0x10                      # Int 0x10: #MF
321                 jmp ex_noc                      # Floating-point error
322 /*
323  * Handle #GP exception.
324  */
325 ex_v86:         testb $0x2,0x12(%esp,1)         # V86 mode?
326                 jz except                       # No
327                 jmp v86mon                      # To monitor
328 /*
329  * Save a zero error code.
330  */
331 ex_noc:         pushl (%esp,1)                  # Duplicate int no
332                 movb $0x0,0x4(%esp,1)           # Fake error code
333 /*
334  * Handle exception.
335  */
336 except:         cld                             # String ops inc
337                 pushl %ds                       # Save
338                 pushl %es                       #  most
339                 pusha                           #  registers
340                 movb $0x6,%al                   # Push loop count
341                 testb $0x2,0x3a(%esp,1)         # V86 mode?
342                 jnz except.1                    # Yes
343                 pushl %gs                       # Set GS
344                 pushl %fs                       # Set FS
345                 pushl %ds                       # Set DS
346                 pushl %es                       # Set ES
347                 movb $0x2,%al                   # Push loop count
348                 cmpw $SEL_SCODE,0x44(%esp,1)    # Supervisor mode?
349                 jne except.1                    # No
350                 pushl %ss                       # Set SS
351                 leal 0x50(%esp,1),%eax          # Set
352                 pushl %eax                      #  ESP
353                 jmp except.2                    # Join common code
354 except.1:       pushl 0x50(%esp,1)              # Set GS, FS, DS, ES
355                 decb %al                        #  (if V86 mode), and
356                 jne except.1                    #  SS, ESP
357 except.2:       push $SEL_SDATA                 # Set up
358                 popl %ds                        #  to
359                 pushl %ds                       #  address
360                 popl %es                        #  data
361                 movl %esp,%ebx                  # Stack frame
362                 movl $dmpfmt,%esi               # Dump format string
363                 movl $MEM_BUF,%edi              # Buffer
364                 pushl %eax
365                 pushl %edx
366 wait.1:
367                 inb  $0x60,%al
368                 testb $0x04,%al
369                 jz   wait.1
370                 movb $0xe0,%al
371                 outb %al,$0x62
372 wait.2:
373                 inb  $0x60,%al
374                 testb $0x01,%al
375                 jz   wait.2
376                 xorl %edx,%edx
377                 inb  $0x62,%al
378                 movb %al,%dl
379                 inb  $0x62,%al
380                 movb %al,%dh
381                 inb  $0x62,%al
382                 inb  $0x62,%al
383                 inb  $0x62,%al
384                 movl %edx,%eax
385                 shlw $1,%ax
386                 movl $BDA_POS,%edx
387                 movw %ax,(%edx)
388                 popl  %edx
389                 popl  %eax
390                 pushl %edi                      # Dump to
391                 call dump                       #  buffer
392                 popl %esi                       #  and
393                 call putstr                     #  display
394                 leal 0x18(%esp,1),%esp          # Discard frame
395                 popa                            # Restore
396                 popl %es                        #  registers
397                 popl %ds                        #  saved
398                 cmpb $0x3,(%esp,1)              # Breakpoint?
399                 je except.3                     # Yes
400                 cmpb $0x1,(%esp,1)              # Debug?
401                 jne except.2a                   # No
402                 testl $0x100,0x10(%esp,1)       # Trap flag set?
403                 jnz except.3                    # Yes
404 except.2a:      jmp exit                        # Exit
405 except.3:       leal 0x8(%esp,1),%esp           # Discard err, int no
406                 iret                            # From interrupt
407 /*
408  * Return to user mode from V86 mode.
409  */
410 intrtn:         cld                             # String ops inc
411                 pushl %ds                       # Address
412                 popl %es                        #  data
413                 leal 0x3c(%ebp),%edx            # V86 Segment registers
414                 movl MEM_TSS+TSS_ESP1,%esi      # Link stack pointer
415                 lodsl                           # INT_V86 args pointer
416                 movl %esi,%ebx                  # Saved exception frame
417                 testl %eax,%eax                 # INT_V86 args?
418                 jz intrtn.2                     # No
419                 movl $MEM_USR,%edi              # User base
420                 movl 0x1c(%esi),%ebx            # User ESP
421                 movl %eax,(%edi,%ebx,1)         # Restore to user stack
422                 leal 0x8(%edi,%eax,1),%edi      # Arg segment registers
423                 testb $0x4,-0x6(%edi)           # Return flags?
424                 jz intrtn.1                     # No
425                 movl 0x30(%ebp),%eax            # Get V86 flags
426                 movw %ax,0x18(%esi)             # Set user flags
427 intrtn.1:       leal 0x10(%esi),%ebx            # Saved exception frame
428                 xchgl %edx,%esi                 # Segment registers
429                 movb $0x4,%cl                   # Update seg regs
430                 rep                             #  in INT_V86
431                 movsl                           #  args
432 intrtn.2:       xchgl %edx,%esi                 # Segment registers
433                 leal 0x28(%ebp),%edi            # Set up seg
434                 movb $0x4,%cl                   #  regs for
435                 rep                             #  later
436                 movsl                           #  pop
437                 xchgl %ebx,%esi                 # Restore exception
438                 movb $0x5,%cl                   #  frame to
439                 rep                             #  supervisor
440                 movsl                           #  stack
441                 movl %esi,MEM_TSS+TSS_ESP1      # Link stack pointer
442                 popa                            # Restore
443                 leal 0x8(%esp,1),%esp           # Discard err, int no
444                 popl %es                        # Restore
445                 popl %ds                        #  user
446                 popl %fs                        #  segment
447                 popl %gs                        #  registers
448                 iret                            # To user mode
449 /*
450  * V86 monitor.
451  */
452 v86mon:         cld                             # String ops inc
453                 pushl $SEL_SDATA                # Set up for
454                 popl %ds                        #  flat addressing
455                 pusha                           # Save registers
456                 movl %esp,%ebp                  # Address stack frame
457                 movzwl 0x2c(%ebp),%edi          # Load V86 CS
458                 shll $0x4,%edi                  # To linear
459                 movl 0x28(%ebp),%esi            # Load V86 IP
460                 addl %edi,%esi                  # Code pointer
461                 xorl %ecx,%ecx                  # Zero
462                 movb $0x2,%cl                   # 16-bit operands
463                 xorl %eax,%eax                  # Zero
464 v86mon.1:       lodsb                           # Get opcode
465                 cmpb $0x66,%al                  # Operand size prefix?
466                 jne v86mon.2                    # No
467                 movb $0x4,%cl                   # 32-bit operands
468                 jmp v86mon.1                    # Continue
469 v86mon.2:       cmpb $0xf4,%al                  # HLT?
470                 jne v86mon.3                    # No
471                 cmpl $inthlt+0x1,%esi           # Is inthlt?
472                 jne v86mon.7                    # No (ignore)
473                 jmp intrtn                      # Return to user mode
474 v86mon.3:       cmpb $0xf,%al                   # Prefixed instruction?
475                 jne v86mon.4                    # No
476                 cmpb $0x09,(%esi)               # Is it a WBINVD?
477                 je v86wbinvd                    # Yes
478                 cmpb $0x30,(%esi)               # Is it a WRMSR?
479                 je v86wrmsr                     # Yes
480                 cmpb $0x32,(%esi)               # Is it a RDMSR?
481                 je v86rdmsr                     # Yes
482                 cmpb $0x20,(%esi)               # Is this a MOV reg,CRx?
483                 je v86mov                       # Yes
484 v86mon.4:       cmpb $0xfa,%al                  # CLI?
485                 je v86cli                       # Yes
486                 cmpb $0xfb,%al                  # STI?
487                 je v86sti                       # Yes
488                 movzwl 0x38(%ebp),%ebx          # Load V86 SS
489                 shll $0x4,%ebx                  # To offset
490                 pushl %ebx                      # Save
491                 addl 0x34(%ebp),%ebx            # Add V86 SP
492                 movl 0x30(%ebp),%edx            # Load V86 flags
493                 cmpb $0x9c,%al                  # PUSHF/PUSHFD?
494                 je v86pushf                     # Yes
495                 cmpb $0x9d,%al                  # POPF/POPFD?
496                 je v86popf                      # Yes
497                 cmpb $0xcd,%al                  # INT imm8?
498                 je v86intn                      # Yes
499                 cmpb $0xcf,%al                  # IRET/IRETD?
500                 je v86iret                      # Yes
501                 popl %ebx                       # Restore
502                 popa                            # Restore
503                 jmp except                      # Handle exception
504 v86mon.5:       movl %edx,0x30(%ebp)            # Save V86 flags
505 v86mon.6:       popl %edx                       # V86 SS adjustment
506                 subl %edx,%ebx                  # Save V86
507                 movl %ebx,0x34(%ebp)            #  SP
508 v86mon.7:       subl %edi,%esi                  # From linear
509                 movl %esi,0x28(%ebp)            # Save V86 IP
510                 popa                            # Restore
511                 leal 0x8(%esp,1),%esp           # Discard int no, error
512                 iret                            # To V86 mode
513 /*
514  * Emulate MOV reg,CRx.
515  */
516 v86mov:         movb 0x1(%esi),%bl              # Fetch Mod R/M byte
517                 testb $0x10,%bl                 # Read CR2 or CR3?
518                 jnz v86mov.1                    # Yes
519                 movl %cr0,%eax                  # Read CR0
520                 testb $0x20,%bl                 # Read CR4 instead?
521                 jz v86mov.2                     # No
522                 movl %cr4,%eax                  # Read CR4
523                 jmp v86mov.2
524 v86mov.1:       movl %cr2,%eax                  # Read CR2
525                 testb $0x08,%bl                 # Read CR3 instead?
526                 jz v86mov.2                     # No
527                 movl %cr3,%eax                  # Read CR3
528 v86mov.2:       andl $0x7,%ebx                  # Compute offset in
529                 shl $2,%ebx                     #  frame of destination
530                 neg %ebx                        #  register
531                 movl %eax,0x1c(%ebp,%ebx,1)     # Store CR to reg
532                 incl %esi                       # Adjust IP
533 /*
534  * Return from emulating a 0x0f prefixed instruction
535  */
536 v86preret:      incl %esi                       # Adjust IP
537                 jmp v86mon.7                    # Finish up
538 /*
539  * Emulate WBINVD
540  */
541 v86wbinvd:      wbinvd                          # Write back and invalidate
542                                                 #  cache
543                 jmp v86preret                   # Finish up
544 /*
545  * Emulate WRMSR
546  */
547 v86wrmsr:       movl 0x18(%ebp),%ecx            # Get user's %ecx (MSR to write)
548                 movl 0x14(%ebp),%edx            # Load the value
549                 movl 0x1c(%ebp),%eax            #  to write
550                 wrmsr                           # Write MSR
551                 jmp v86preret                   # Finish up
552 /*
553  * Emulate RDMSR
554  */
555 v86rdmsr:       movl 0x18(%ebp),%ecx            # MSR to read
556                 rdmsr                           # Read the MSR
557                 movl %eax,0x1c(%ebp)            # Return the value of
558                 movl %edx,0x14(%ebp)            #  the MSR to the user
559                 jmp v86preret                   # Finish up
560 /*
561  * Emulate CLI.
562  */
563 v86cli:         andb $~0x2,0x31(%ebp)           # Clear IF
564                 jmp v86mon.7                    # Finish up
565 /*
566  * Emulate STI.
567  */
568 v86sti:         orb $0x2,0x31(%ebp)             # Set IF
569                 jmp v86mon.7                    # Finish up
570 /*
571  * Emulate PUSHF/PUSHFD.
572  */
573 v86pushf:       subl %ecx,%ebx                  # Adjust SP
574                 cmpb $0x4,%cl                   # 32-bit
575                 je v86pushf.1                   # Yes
576                 data16                          # 16-bit
577 v86pushf.1:     movl %edx,(%ebx)                # Save flags
578                 jmp v86mon.6                    # Finish up
579 /*
580  * Emulate IRET/IRETD.
581  */
582 v86iret:        movzwl (%ebx),%esi              # Load V86 IP
583                 movzwl 0x2(%ebx),%edi           # Load V86 CS
584                 leal 0x4(%ebx),%ebx             # Adjust SP
585                 movl %edi,0x2c(%ebp)            # Save V86 CS
586                 xorl %edi,%edi                  # No ESI adjustment
587 /*
588  * Emulate POPF/POPFD (and remainder of IRET/IRETD).
589  */
590 v86popf:        cmpb $0x4,%cl                   # 32-bit?
591                 je v86popf.1                    # Yes
592                 movl %edx,%eax                  # Initialize
593                 data16                          # 16-bit
594 v86popf.1:      movl (%ebx),%eax                # Load flags
595                 addl %ecx,%ebx                  # Adjust SP
596                 andl $V86_FLG,%eax              # Merge
597                 andl $~V86_FLG,%edx             #  the
598                 orl %eax,%edx                   #  flags
599                 jmp v86mon.5                    # Finish up
600 /*
601  * trap int 15, function 87
602  * reads %es:%si from saved registers on stack to find a GDT containing
603  * source and destination locations
604  * reads count of words from saved %cx
605  * returns success by setting %ah to 0
606  */
607 int15_87:       pushl %esi                      # Save 
608                 pushl %edi                      #  registers
609                 movl 0x3C(%ebp),%edi            # Load ES
610                 movzwl 0x4(%ebp),%eax           # Load user's SI
611                 shll $0x4,%edi                  # EDI = (ES << 4) +
612                 addl %eax,%edi                  #   SI
613                 movl 0x11(%edi),%eax            # Read base of
614                 movb 0x17(%edi),%al             #  GDT entry
615                 ror $8,%eax                     #  for source
616                 xchgl %eax,%esi                 #  into %esi
617                 movl 0x19(%edi),%eax            # Read base of
618                 movb 0x1f(%edi),%al             #  GDT entry for
619                 ror $8,%eax                     #  destination
620                 xchgl %eax,%edi                 #  into %edi
621                 pushl %ds                       # Make:
622                 popl %es                        # es = ds
623                 movzwl 0x18(%ebp),%ecx          # Get user's CX
624                 shll $0x1,%ecx                  # Convert count from words
625                 rep                             # repeat...
626                 movsb                           #  perform copy.
627                 popl %edi                       # Restore
628                 popl %esi                       #  registers
629                 movb $0x0,0x1d(%ebp)            # set ah = 0 to indicate
630                                                 #  success
631                 andb $0xfe,%dl                  # clear CF
632                 jmp v86mon.5                    # Finish up
633
634 /*
635  * Reboot the machine by setting the reboot flag and exiting
636  */
637 reboot:         orb $0x1,btx_hdr+0x7            # Set the reboot flag
638                 jmp exit                        # Terminate BTX and reboot
639
640 /*
641  * Emulate INT imm8... also make sure to check if it's int 15/87
642  */
643 v86intn:        lodsb                           # Get int no
644                 cmpb $0x19,%al                  # is it int 19?
645                 je reboot                       #  yes, reboot the machine
646                 cmpb $0x15,%al                  # is it int 15?
647                 jne v86intn.1                   #  no, skip parse
648                 cmpb $0x87,0x1d(%ebp)           # is it the memcpy subfunction?
649                 je int15_87                     #  yes
650                 cmpw $0x4f53,0x1c(%ebp)         # is it the delete key callout?
651                 jne v86intn.1                   #  no, handle the int normally
652                 movb BDA_KEYFLAGS,%ch           # get the shift key state
653                 andb $0x18,%ch                  # mask off just Ctrl and Alt
654                 cmpb $0x18,%ch                  # are both Ctrl and Alt down?
655                 je reboot                       # yes, reboot the machine
656 v86intn.1:      subl %edi,%esi                  # From
657                 shrl $0x4,%edi                  #  linear
658                 movw %dx,-0x2(%ebx)             # Save flags
659                 movw %di,-0x4(%ebx)             # Save CS
660                 leal -0x6(%ebx),%ebx            # Adjust SP
661                 movw %si,(%ebx)                 # Save IP
662                 shll $0x2,%eax                  # Scale
663                 movzwl (%eax),%esi              # Load IP
664                 movzwl 0x2(%eax),%edi           # Load CS
665                 movl %edi,0x2c(%ebp)            # Save CS
666                 xorl %edi,%edi                  # No ESI adjustment
667                 andb $~0x1,%dh                  # Clear TF
668                 jmp v86mon.5                    # Finish up
669 /*
670  * Hardware interrupt jump table.
671  */
672 intx20:         push $0x8                       # Int 0x20: IRQ0
673                 jmp int_hw                      # V86 int 0x8
674                 push $0x9                       # Int 0x21: IRQ1
675                 jmp int_hw                      # V86 int 0x9
676                 push $0xa                       # Int 0x22: IRQ2
677                 jmp int_hw                      # V86 int 0xa
678                 push $0xb                       # Int 0x23: IRQ3
679                 jmp int_hw                      # V86 int 0xb
680                 push $0xc                       # Int 0x24: IRQ4
681                 jmp int_hw                      # V86 int 0xc
682                 push $0xd                       # Int 0x25: IRQ5
683                 jmp int_hw                      # V86 int 0xd
684                 push $0xe                       # Int 0x26: IRQ6
685                 jmp int_hw                      # V86 int 0xe
686                 push $0xf                       # Int 0x27: IRQ7
687                 jmp int_hw                      # V86 int 0xf
688                 push $0x10                      # Int 0x28: IRQ8
689                 jmp int_hw                      # V86 int 0x10
690                 push $0x11                      # Int 0x29: IRQ9
691                 jmp int_hw                      # V86 int 0x11
692                 push $0x12                      # Int 0x2a: IRQ10
693                 jmp int_hw                      # V86 int 0x12
694                 push $0x13                      # Int 0x2b: IRQ11
695                 jmp int_hw                      # V86 int 0x13
696                 push $0x14                      # Int 0x2c: IRQ12
697                 jmp int_hw                      # V86 int 0x14
698                 push $0x15                      # Int 0x2d: IRQ13
699                 jmp int_hw                      # V86 int 0x15
700                 push $0x16                      # Int 0x2e: IRQ14
701                 jmp int_hw                      # V86 int 0x16
702                 push $0x17                      # Int 0x2f: IRQ15
703                 jmp int_hw                      # V86 int 0x17
704 /*
705  * Reflect hardware interrupts.
706  */
707 int_hw:         testb $0x2,0xe(%esp,1)          # V86 mode?
708                 jz intusr                       # No
709                 pushl $SEL_SDATA                # Address
710                 popl %ds                        #  data
711                 xchgl %eax,(%esp,1)             # Swap EAX, int no
712                 pushl %ebp                      # Address
713                 movl %esp,%ebp                  #  stack frame
714                 pushl %ebx                      # Save
715                 shll $0x2,%eax                  # Get int
716                 movl (%eax),%eax                #  vector
717                 subl $0x6,0x14(%ebp)            # Adjust V86 ESP
718                 movzwl 0x18(%ebp),%ebx          # V86 SS
719                 shll $0x4,%ebx                  #  * 0x10
720                 addl 0x14(%ebp),%ebx            #  + V86 ESP
721                 xchgw %ax,0x8(%ebp)             # Swap V86 IP
722                 rorl $0x10,%eax                 # Swap words
723                 xchgw %ax,0xc(%ebp)             # Swap V86 CS
724                 roll $0x10,%eax                 # Swap words
725                 movl %eax,(%ebx)                # CS:IP for IRET
726                 movl 0x10(%ebp),%eax            # V86 flags
727                 movw %ax,0x4(%ebx)              # Flags for IRET
728                 andb $~0x3,0x11(%ebp)           # Clear IF, TF
729                 popl %ebx                       # Restore
730                 popl %ebp                       #  saved
731                 popl %eax                       #  registers
732                 iret                            # To V86 mode
733 /*
734  * Invoke V86 interrupt from user mode, with arguments.
735  */
736 intx31:         stc                             # Have btx_v86
737                 pushl %eax                      # Missing int no
738 /*
739  * Invoke V86 interrupt from user mode.
740  */
741 intusr:         std                             # String ops dec
742                 pushl %eax                      # Expand
743                 pushl %eax                      #  stack
744                 pushl %eax                      #  frame
745                 pusha                           # Save
746                 pushl %gs                       # Save
747                 movl %esp,%eax                  #  seg regs
748                 pushl %fs                       #  and
749                 pushl %ds                       #  point
750                 pushl %es                       #  to them
751                 push $SEL_SDATA                 # Set up
752                 popl %ds                        #  to
753                 pushl %ds                       #  address
754                 popl %es                        #  data
755                 movl $MEM_USR,%ebx              # User base
756                 movl %ebx,%edx                  #  address
757                 jc intusr.1                     # If btx_v86
758                 xorl %edx,%edx                  # Control flags
759                 xorl %ebp,%ebp                  # btx_v86 pointer
760 intusr.1:       leal 0x50(%esp,1),%esi          # Base of frame
761                 pushl %esi                      # Save
762                 addl -0x4(%esi),%ebx            # User ESP
763                 movl MEM_TSS+TSS_ESP1,%edi      # Link stack pointer
764                 leal -0x4(%edi),%edi            # Adjust for push
765                 xorl %ecx,%ecx                  # Zero
766                 movb $0x5,%cl                   # Push exception
767                 rep                             #  frame on
768                 movsl                           #  link stack
769                 xchgl %eax,%esi                 # Saved seg regs
770                 movl 0x40(%esp,1),%eax          # Get int no
771                 testl %edx,%edx                 # Have btx_v86?
772                 jz intusr.2                     # No
773                 movl (%ebx),%ebp                # btx_v86 pointer
774                 movb $0x4,%cl                   # Count
775                 addl %ecx,%ebx                  # Adjust for pop
776                 rep                             # Push saved seg regs
777                 movsl                           #  on link stack
778                 addl %ebp,%edx                  # Flatten btx_v86 ptr
779                 leal 0x14(%edx),%esi            # Seg regs pointer
780                 movl 0x4(%edx),%eax             # Get int no/address
781                 movzwl 0x2(%edx),%edx           # Get control flags
782 intusr.2:       movl %ebp,(%edi)                # Push btx_v86 and
783                 movl %edi,MEM_TSS+TSS_ESP1      #  save link stack ptr
784                 popl %edi                       # Base of frame
785                 xchgl %eax,%ebp                 # Save intno/address
786                 movl 0x48(%esp,1),%eax          # Get flags
787                 testb $0x2,%dl                  # Simulate CALLF?
788                 jnz intusr.3                    # Yes
789                 decl %ebx                       # Push flags
790                 decl %ebx                       #  on V86
791                 movw %ax,(%ebx)                 #  stack
792 intusr.3:       movb $0x4,%cl                   # Count
793                 subl %ecx,%ebx                  # Push return address
794                 movl $inthlt,(%ebx)             #  on V86 stack
795                 rep                             # Copy seg regs to
796                 movsl                           #  exception frame
797                 xchgl %eax,%ecx                 # Save flags
798                 movl %ebx,%eax                  # User ESP
799                 subl $V86_STK,%eax              # Less bytes
800                 ja intusr.4                     #  to
801                 xorl %eax,%eax                  #  keep
802 intusr.4:       shrl $0x4,%eax                  # Gives segment
803                 stosl                           # Set SS
804                 shll $0x4,%eax                  # To bytes
805                 xchgl %eax,%ebx                 # Swap
806                 subl %ebx,%eax                  # Gives offset
807                 stosl                           # Set ESP
808                 xchgl %eax,%ecx                 # Get flags
809                 btsl $0x11,%eax                 # Set VM
810                 andb $~0x1,%ah                  # Clear TF
811                 stosl                           # Set EFL
812                 xchgl %eax,%ebp                 # Get int no/address
813                 testb $0x1,%dl                  # Address?
814                 jnz intusr.5                    # Yes
815                 shll $0x2,%eax                  # Scale
816                 movl (%eax),%eax                # Load int vector
817 intusr.5:       movl %eax,%ecx                  # Save
818                 shrl $0x10,%eax                 # Gives segment
819                 stosl                           # Set CS
820                 movw %cx,%ax                    # Restore
821                 stosl                           # Set EIP
822                 leal 0x10(%esp,1),%esp          # Discard seg regs
823                 popa                            # Restore
824                 iret                            # To V86 mode
825 /*
826  * System Call.
827  */
828 intx30:         cmpl $SYS_EXEC,%eax             # Exec system call?
829                 jne intx30.1                    # No
830                 pushl %ss                       # Set up
831                 popl %es                        #  all
832                 pushl %es                       #  segment
833                 popl %ds                        #  registers
834                 pushl %ds                       #  for the
835                 popl %fs                        #  program
836                 pushl %fs                       #  we're
837                 popl %gs                        #  invoking
838                 movl $MEM_USR,%eax              # User base address
839                 addl 0xc(%esp,1),%eax           # Change to user
840                 leal 0x4(%eax),%esp             #  stack
841                 popl %eax                       # Call
842                 call *%eax                      #  program
843 intx30.1:       orb $0x1,%ss:btx_hdr+0x7        # Flag reboot
844                 jmp exit                        # Exit
845 /*
846  * Dump structure [EBX] to [EDI], using format string [ESI].
847  */
848 dump.0:         stosb                           # Save char
849 dump:           lodsb                           # Load char
850                 testb %al,%al                   # End of string?
851                 jz dump.10                      # Yes
852                 testb $0x80,%al                 # Control?
853                 jz dump.0                       # No
854                 movb %al,%ch                    # Save control
855                 movb $'=',%al                   # Append
856                 stosb                           #  '='
857                 lodsb                           # Get offset
858                 pushl %esi                      # Save
859                 movsbl %al,%esi                 # To
860                 addl %ebx,%esi                  #  pointer
861                 testb $DMP_X16,%ch              # Dump word?
862                 jz dump.1                       # No
863                 lodsw                           # Get and
864                 call hex16                      #  dump it
865 dump.1:         testb $DMP_X32,%ch              # Dump long?
866                 jz dump.2                       # No
867                 lodsl                           # Get and
868                 call hex32                      #  dump it
869 dump.2:         testb $DMP_MEM,%ch              # Dump memory?
870                 jz dump.8                       # No
871                 pushl %ds                       # Save
872                 testb $0x2,0x52(%ebx)           # V86 mode?
873                 jnz dump.3                      # Yes
874                 verr 0x4(%esi)                  # Readable selector?
875                 jnz dump.3                      # No
876                 ldsl (%esi),%esi                # Load pointer
877                 jmp dump.4                      # Join common code
878 dump.3:         lodsl                           # Set offset
879                 xchgl %eax,%edx                 # Save
880                 lodsl                           # Get segment
881                 shll $0x4,%eax                  #  * 0x10
882                 addl %edx,%eax                  #  + offset
883                 xchgl %eax,%esi                 # Set pointer
884 dump.4:         movb $2,%dl                     # Num lines
885 dump.4a:        movb $0x10,%cl                  # Bytes to dump
886 dump.5:         lodsb                           # Get byte and
887                 call hex8                       #  dump it
888                 decb %cl                        # Keep count
889                 jz dump.6a                      # If done
890                 movb $'-',%al                   # Separator
891                 cmpb $0x8,%cl                   # Half way?
892                 je dump.6                       # Yes
893                 movb $' ',%al                   # Use space
894 dump.6:         stosb                           # Save separator
895                 jmp dump.5                      # Continue
896 dump.6a:        decb %dl                        # Keep count
897                 jz dump.7                       # If done
898                 movb $0xa,%al                   # Line feed
899                 stosb                           # Save one
900                 movb $7,%cl                     # Leading
901                 movb $' ',%al                   #  spaces
902 dump.6b:        stosb                           # Dump
903                 decb %cl                        #  spaces
904                 jnz dump.6b
905                 jmp dump.4a                     # Next line
906 dump.7:         popl %ds                        # Restore
907 dump.8:         popl %esi                       # Restore
908                 movb $0xa,%al                   # Line feed
909                 testb $DMP_EOL,%ch              # End of line?
910                 jnz dump.9                      # Yes
911                 movb $' ',%al                   # Use spaces
912                 stosb                           # Save one
913 dump.9:         jmp dump.0                      # Continue
914 dump.10:        stosb                           # Terminate string
915                 ret                             # To caller
916 /*
917  * Convert EAX, AX, or AL to hex, saving the result to [EDI].
918  */
919 hex32:          pushl %eax                      # Save
920                 shrl $0x10,%eax                 # Do upper
921                 call hex16                      #  16
922                 popl %eax                       # Restore
923 hex16:          call hex16.1                    # Do upper 8
924 hex16.1:        xchgb %ah,%al                   # Save/restore
925 hex8:           pushl %eax                      # Save
926                 shrb $0x4,%al                   # Do upper
927                 call hex8.1                     #  4
928                 popl %eax                       # Restore
929 hex8.1:         andb $0xf,%al                   # Get lower 4
930                 cmpb $0xa,%al                   # Convert
931                 sbbb $0x69,%al                  #  to hex
932                 das                             #  digit
933                 orb $0x20,%al                   # To lower case
934                 stosb                           # Save char
935                 ret                             # (Recursive)
936 /*
937  * Output zero-terminated string [ESI] to the console.
938  */
939 putstr.0:       call putchr                     # Output char
940 putstr:         lodsb                           # Load char
941                 testb %al,%al                   # End of string?
942                 jnz putstr.0                    # No
943                 ret                             # To caller
944 #ifdef BTX_SERIAL
945                 .set SIO_PRT,SIOPRT             # Base port
946                 .set SIO_FMT,SIOFMT             # 8N1
947                 .set SIO_DIV,(115200/SIOSPD)    # 115200 / SPD
948
949 /*
950  * void sio_init(void)
951  */
952 sio_init:       movw $SIO_PRT+0x3,%dx           # Data format reg
953                 movb $SIO_FMT|0x80,%al          # Set format
954                 outb %al,(%dx)                  #  and DLAB
955                 pushl %edx                      # Save
956                 subb $0x3,%dl                   # Divisor latch reg
957                 movw $SIO_DIV,%ax               # Set
958                 outw %ax,(%dx)                  #  BPS
959                 popl %edx                       # Restore
960                 movb $SIO_FMT,%al               # Clear
961                 outb %al,(%dx)                  #  DLAB
962                 incl %edx                       # Modem control reg
963                 movb $0x3,%al                   # Set RTS,
964                 outb %al,(%dx)                  #  DTR
965                 incl %edx                       # Line status reg
966
967 /*
968  * void sio_flush(void)
969  */
970 sio_flush.0:    call sio_getc.1                 # Get character
971 sio_flush:      call sio_ischar                 # Check for character
972                 jnz sio_flush.0                 # Till none
973                 ret                             # To caller
974
975 /*
976  * void sio_putc(int c)
977  */
978 sio_putc:       movw $SIO_PRT+0x5,%dx           # Line status reg
979                 xor %ecx,%ecx                   # Timeout
980                 movb $0x40,%ch                  #  counter
981 sio_putc.1:     inb (%dx),%al                   # Transmitter
982                 testb $0x20,%al                 #  buffer empty?
983                 loopz sio_putc.1                # No
984                 jz sio_putc.2                   # If timeout
985                 movb 0x4(%esp,1),%al            # Get character
986                 subb $0x5,%dl                   # Transmitter hold reg
987                 outb %al,(%dx)                  # Write character
988 sio_putc.2:     ret $0x4                        # To caller
989
990 /*
991  * int sio_getc(void)
992  */
993 sio_getc:       call sio_ischar                 # Character available?
994                 jz sio_getc                     # No
995 sio_getc.1:     subb $0x5,%dl                   # Receiver buffer reg
996                 inb (%dx),%al                   # Read character
997                 ret                             # To caller
998
999 /*
1000  * int sio_ischar(void)
1001  */
1002 sio_ischar:     movw $SIO_PRT+0x5,%dx           # Line status register
1003                 xorl %eax,%eax                  # Zero
1004                 inb (%dx),%al                   # Received data
1005                 andb $0x1,%al                   #  ready?
1006                 ret                             # To caller
1007
1008 /*
1009  * Output character AL to the serial console.
1010  */
1011 putchr:         pusha                           # Save
1012                 cmpb $10, %al                   # is it a newline?
1013                 jne putchr.1                    #  no?, then leave
1014                 push $13                        # output a carriage
1015                 call sio_putc                   #  return first
1016                 movb $10, %al                   # restore %al
1017 putchr.1:       pushl %eax                      # Push the character
1018                                                 #  onto the stack
1019                 call sio_putc                   # Output the character
1020                 popa                            # Restore
1021                 ret                             # To caller
1022 #else
1023 /*
1024  * Output character AL to the console.
1025  */
1026 putchr:         pusha                           # Save
1027                 xorl %ecx,%ecx                  # Zero for loops
1028                 movb $SCR_MAT,%ah               # Mode/attribute
1029                 movl $BDA_POS,%ebx              # BDA pointer
1030                 movw (%ebx),%dx                 # Cursor position
1031                 movl $0xa0000,%edi
1032 putchr.1:       cmpb $0xa,%al                   # New line?
1033                 je putchr.2                     # Yes
1034                 movw %dx,%cx
1035                 movb %al,(%edi,%ecx,1)          # Write char
1036                 addl $0x2000,%ecx
1037                 movb %ah,(%edi,%ecx,1)          # Write attr
1038                 addw $0x02,%dx
1039                 jmp putchr.3
1040 putchr.2:       movw %dx,%ax
1041                 movb $SCR_COL*2,%dl
1042                 div %dl
1043                 incb %al
1044                 mul %dl
1045                 movw %ax,%dx
1046 putchr.3:       cmpw $SCR_ROW*SCR_COL*2,%dx
1047                 jb putchr.4                     # No
1048                 leal 2*SCR_COL(%edi),%esi       # New top line
1049                 movw $(SCR_ROW-1)*SCR_COL/2,%cx # Words to move
1050                 rep                             # Scroll
1051                 movsl                           #  screen
1052                 movb $0x20,%al                  # Space
1053                 xorb %ah,%ah
1054                 movb $SCR_COL,%cl               # Columns to clear
1055                 rep                             # Clear
1056                 stosw                           #  line
1057                 movw $(SCR_ROW-1)*SCR_COL*2,%dx
1058 putchr.4:       movw %dx,(%ebx)                 # Update position
1059                 popa                            # Restore
1060                 ret                             # To caller
1061 #endif
1062
1063                 .p2align 4
1064 /*
1065  * Global descriptor table.
1066  */
1067 gdt:            .word 0x0,0x0,0x0,0x0           # Null entry
1068                 .word 0xffff,0x0,0x9a00,0xcf    # SEL_SCODE
1069                 .word 0xffff,0x0,0x9200,0xcf    # SEL_SDATA
1070                 .word 0xffff,0x0,0x9a00,0x0     # SEL_RCODE
1071                 .word 0xffff,0x0,0x9200,0x0     # SEL_RDATA
1072                 .word 0xffff,MEM_USR,0xfa00,0xcf# SEL_UCODE
1073                 .word 0xffff,MEM_USR,0xf200,0xcf# SEL_UDATA
1074                 .word _TSSLM,MEM_TSS,0x8900,0x0 # SEL_TSS
1075 gdt.1:
1076 /*
1077  * Pseudo-descriptors.
1078  */
1079 gdtdesc:        .word gdt.1-gdt-1,gdt,0x0       # GDT
1080 idtdesc:        .word _IDTLM,MEM_IDT,0x0        # IDT
1081 ivtdesc:        .word 0x400-0x0-1,0x0,0x0       # IVT
1082 /*
1083  * IDT construction control string.
1084  */
1085 idtctl:         .byte 0x10,  0x8e               # Int 0x0-0xf
1086                 .word 0x7dfb,intx00             #  (exceptions)
1087                 .byte 0x10,  0x8e               # Int 0x10
1088                 .word 0x1,   intx10             #  (exception)
1089                 .byte 0x10,  0x8e               # Int 0x20-0x2f
1090                 .word 0xffff,intx20             #  (hardware)
1091                 .byte 0x1,   0xee               # int 0x30
1092                 .word 0x1,   intx30             #  (system call)
1093                 .byte 0x2,   0xee               # Int 0x31-0x32
1094                 .word 0x1,   intx31             #  (V86, null)
1095                 .byte 0x0                       # End of string
1096 /*
1097  * Dump format string.
1098  */
1099 dmpfmt:         .byte '\n'                      # "\n"
1100                 .ascii "int"                    # "int="
1101                 .byte 0x80|DMP_X32,        0x40 # "00000000  "
1102                 .ascii "err"                    # "err="
1103                 .byte 0x80|DMP_X32,        0x44 # "00000000  "
1104                 .ascii "efl"                    # "efl="
1105                 .byte 0x80|DMP_X32,        0x50 # "00000000  "
1106                 .ascii "eip"                    # "eip="
1107                 .byte 0x80|DMP_X32|DMP_EOL,0x48 # "00000000\n"
1108                 .ascii "eax"                    # "eax="
1109                 .byte 0x80|DMP_X32,        0x34 # "00000000  "
1110                 .ascii "ebx"                    # "ebx="
1111                 .byte 0x80|DMP_X32,        0x28 # "00000000  "
1112                 .ascii "ecx"                    # "ecx="
1113                 .byte 0x80|DMP_X32,        0x30 # "00000000  "
1114                 .ascii "edx"                    # "edx="
1115                 .byte 0x80|DMP_X32|DMP_EOL,0x2c # "00000000\n"
1116                 .ascii "esi"                    # "esi="
1117                 .byte 0x80|DMP_X32,        0x1c # "00000000  "
1118                 .ascii "edi"                    # "edi="
1119                 .byte 0x80|DMP_X32,        0x18 # "00000000  "
1120                 .ascii "ebp"                    # "ebp="
1121                 .byte 0x80|DMP_X32,        0x20 # "00000000  "
1122                 .ascii "esp"                    # "esp="
1123                 .byte 0x80|DMP_X32|DMP_EOL,0x0  # "00000000\n"
1124                 .ascii "cs"                     # "cs="
1125                 .byte 0x80|DMP_X16,        0x4c # "0000  "
1126                 .ascii "ds"                     # "ds="
1127                 .byte 0x80|DMP_X16,        0xc  # "0000  "
1128                 .ascii "es"                     # "es="
1129                 .byte 0x80|DMP_X16,        0x8  # "0000  "
1130                 .ascii "  "                     # "  "
1131                 .ascii "fs"                     # "fs="
1132                 .byte 0x80|DMP_X16,        0x10 # "0000  "
1133                 .ascii "gs"                     # "gs="
1134                 .byte 0x80|DMP_X16,        0x14 # "0000  "
1135                 .ascii "ss"                     # "ss="
1136                 .byte 0x80|DMP_X16|DMP_EOL,0x4  # "0000\n"
1137                 .ascii "cs:eip"                 # "cs:eip="
1138                 .byte 0x80|DMP_MEM|DMP_EOL,0x48 # "00 00 ... 00 00\n"
1139                 .ascii "ss:esp"                 # "ss:esp="
1140                 .byte 0x80|DMP_MEM|DMP_EOL,0x0  # "00 00 ... 00 00\n"
1141                 .asciz "BTX halted\n"           # End
1142 /*
1143  * End of BTX memory.
1144  */
1145                 .p2align 4
1146 break: