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