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