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