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