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