]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc64/l.s
wifi: use protocol constants from ip/ip.h and ip/ipv6.h for dmatproxy()
[plan9front.git] / sys / src / 9 / pc64 / l.s
1 #include "mem.h"
2
3 MODE $32
4
5 #define DELAY           BYTE $0xEB; BYTE $0x00  /* JMP .+2 */
6
7 #define pFARJMP32(s, o) BYTE $0xea;             /* far jump to ptr32:16 */\
8                         LONG $o; WORD $s
9
10 /*
11  * Enter here in 32-bit protected mode. Welcome to 1982.
12  * Make sure the GDT is set as it should be:
13  *      disable interrupts;
14  *      load the GDT with the table in _gdt32p;
15  *      load all the data segments
16  *      load the code segment via a far jump.
17  */
18 TEXT _protected<>(SB), 1, $-4
19         CLI
20
21         MOVL    $_gdtptr32p<>-KZERO(SB), AX
22         MOVL    (AX), GDTR
23
24         MOVL    $SELECTOR(2, SELGDT, 0), AX
25         MOVW    AX, DS
26         MOVW    AX, ES
27         MOVW    AX, FS
28         MOVW    AX, GS
29         MOVW    AX, SS
30
31         pFARJMP32(SELECTOR(3, SELGDT, 0), _warp64<>-KZERO(SB))
32
33         BYTE    $0x90   /* align */
34
35 /*
36  * Must be 4-byte aligned.
37  */
38 TEXT _multibootheader<>(SB), 1, $-4
39         LONG    $0x1BADB002                     /* magic */
40         LONG    $0x00010007                     /* flags */
41         LONG    $-(0x1BADB002 + 0x00010007)     /* checksum */
42         LONG    $_multibootheader<>-KZERO(SB)   /* header_addr */
43         LONG    $_protected<>-KZERO(SB)         /* load_addr */
44         LONG    $edata-KZERO(SB)                /* load_end_addr */
45         LONG    $end-KZERO(SB)                  /* bss_end_addr */
46         LONG    $_multibootentry<>-KZERO(SB)    /* entry_addr */
47         LONG    $0                              /* mode_type */
48         LONG    $0                              /* width */
49         LONG    $0                              /* height */
50         LONG    $32                             /* depth */
51
52 /* 
53  * the kernel expects the data segment to be page-aligned
54  * multiboot bootloaders put the data segment right behind text
55  */
56 TEXT _multibootentry<>(SB), 1, $-4
57         MOVL    $etext-KZERO(SB), SI
58         MOVL    SI, DI
59         ADDL    $(BY2PG-1), DI
60         ANDL    $~(BY2PG-1), DI
61         MOVL    $edata-KZERO(SB), CX
62         SUBL    DI, CX
63         ADDL    CX, SI
64         ADDL    CX, DI
65         INCL    CX      /* one more for post decrement */
66         STD
67         REP; MOVSB
68         MOVL    BX, multibootptr-KZERO(SB)
69         MOVL    $_protected<>-KZERO(SB), AX
70         JMP*    AX
71
72 /* multiboot structure pointer (physical address) */
73 TEXT multibootptr(SB), 1, $-4
74         LONG    $0
75
76 TEXT _gdt<>(SB), 1, $-4
77         /* null descriptor */
78         LONG    $0
79         LONG    $0
80
81         /* (KESEG) 64 bit long mode exec segment */
82         LONG    $(0xFFFF)
83         LONG    $(SEGL|SEGG|SEGP|(0xF<<16)|SEGPL(0)|SEGEXEC|SEGR)
84
85         /* 32 bit data segment descriptor for 4 gigabytes (PL 0) */
86         LONG    $(0xFFFF)
87         LONG    $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW)
88
89         /* 32 bit exec segment descriptor for 4 gigabytes (PL 0) */
90         LONG    $(0xFFFF)
91         LONG    $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
92
93
94 TEXT _gdtptr32p<>(SB), 1, $-4
95         WORD    $(4*8-1)
96         LONG    $_gdt<>-KZERO(SB)
97
98 TEXT _gdtptr64p<>(SB), 1, $-4
99         WORD    $(4*8-1)
100         QUAD    $_gdt<>-KZERO(SB)
101
102 TEXT _gdtptr64v<>(SB), 1, $-4
103         WORD    $(4*8-1)
104         QUAD    $_gdt<>(SB)
105
106 /*
107  * Macros for accessing page table entries; change the
108  * C-style array-index macros into a page table byte offset
109  */
110 #define PML4O(v)        ((PTLX((v), 3))<<3)
111 #define PDPO(v)         ((PTLX((v), 2))<<3)
112 #define PDO(v)          ((PTLX((v), 1))<<3)
113 #define PTO(v)          ((PTLX((v), 0))<<3)
114
115 TEXT _warp64<>(SB), 1, $-4
116
117         /* clear mach and page tables */
118         MOVL    $((CPU0END-CPU0PML4)>>2), CX
119         MOVL    $(CPU0PML4-KZERO), SI
120         MOVL    SI, DI
121         XORL    AX, AX
122         CLD
123         REP;    STOSL
124
125         MOVL    SI, AX                          /* PML4 */
126         MOVL    AX, DX
127         ADDL    $(PTSZ|PTEWRITE|PTEVALID), DX   /* PDP at PML4 + PTSZ */
128         MOVL    DX, PML4O(0)(AX)                /* PML4E for double-map */
129         MOVL    DX, PML4O(KZERO)(AX)            /* PML4E for KZERO */
130
131         ADDL    $PTSZ, AX                       /* PDP at PML4 + PTSZ */
132         ADDL    $PTSZ, DX                       /* PD0 at PML4 + 2*PTSZ */
133         MOVL    DX, PDPO(0)(AX)                 /* PDPE for double-map */
134         MOVL    DX, PDPO(KZERO)(AX)             /* PDPE for KZERO */
135
136         /*
137          * add PDPE for KZERO+1GB early as Vmware
138          * hangs when modifying kernel PDP
139          */
140         ADDL    $PTSZ, DX                       /* PD1 */
141         MOVL    DX, PDPO(KZERO+GiB)(AX)
142
143         ADDL    $PTSZ, AX                       /* PD0 at PML4 + 2*PTSZ */
144         MOVL    $(PTESIZE|PTEGLOBAL|PTEWRITE|PTEVALID), DX
145         MOVL    DX, PDO(0)(AX)                  /* PDE for double-map */
146
147         /*
148          * map from KZERO to end using 2MB pages
149          */
150         ADDL    $PDO(KZERO), AX
151         MOVL    $end-KZERO(SB), CX
152
153         ADDL    $(16*1024), CX                  /* qemu puts multiboot data after the kernel */
154
155         ADDL    $(PGLSZ(1)-1), CX
156         ANDL    $~(PGLSZ(1)-1), CX
157         MOVL    CX, MemMin-KZERO(SB)            /* see memory.c */
158         SHRL    $(1*PTSHIFT+PGSHIFT), CX
159 memloop:
160         MOVL    DX, (AX)
161         ADDL    $PGLSZ(1), DX
162         ADDL    $8, AX
163         LOOP    memloop
164
165 /*
166  * Enable and activate Long Mode. From the manual:
167  *      make sure Page Size Extentions are off, and Page Global
168  *      Extensions and Physical Address Extensions are on in CR4;
169  *      set Long Mode Enable in the Extended Feature Enable MSR;
170  *      set Paging Enable in CR0;
171  *      make an inter-segment jump to the Long Mode code.
172  * It's all in 32-bit mode until the jump is made.
173  */
174 TEXT _lme<>(SB), 1, $-4
175         MOVL    SI, CR3                         /* load the mmu */
176         DELAY
177
178         MOVL    CR4, AX
179         ANDL    $~0x00000010, AX                        /* Page Size */
180         ORL     $0x000000A0, AX                 /* Page Global, Phys. Address */
181         MOVL    AX, CR4
182
183         MOVL    $0xc0000080, CX                 /* Extended Feature Enable */
184         RDMSR
185         ORL     $0x00000100, AX                 /* Long Mode Enable */
186         WRMSR
187
188         MOVL    CR0, DX
189         ANDL    $~0x6000000a, DX
190         ORL     $0x80010000, DX                 /* Paging Enable, Write Protect */
191         MOVL    DX, CR0
192
193         pFARJMP32(SELECTOR(KESEG, SELGDT, 0), _identity<>-KZERO(SB))
194
195 /*
196  * Long mode. Welcome to 2003.
197  * Jump out of the identity map space;
198  * load a proper long mode GDT.
199  */
200 MODE $64
201
202 TEXT _identity<>(SB), 1, $-4
203         MOVQ    $_start64v<>(SB), AX
204         JMP*    AX
205
206 TEXT _start64v<>(SB), 1, $-4
207         MOVQ    $_gdtptr64v<>(SB), AX
208         MOVL    (AX), GDTR
209
210         XORQ    AX, AX
211         MOVW    AX, DS                          /* not used in long mode */
212         MOVW    AX, ES                          /* not used in long mode */
213         MOVW    AX, FS
214         MOVW    AX, GS
215         MOVW    AX, SS                          /* not used in long mode */
216
217         MOVW    AX, LDTR
218
219         MOVQ    $(CPU0MACH+MACHSIZE), SP
220         MOVQ    $(CPU0MACH), RMACH
221         MOVQ    AX, RUSER                       /* up = 0; */
222
223 _clearbss:
224         MOVQ    $edata(SB), DI
225         MOVQ    $end(SB), CX
226         SUBQ    DI, CX                          /* end-edata bytes */
227         SHRQ    $2, CX                          /* end-edata doublewords */
228
229         CLD
230         REP;    STOSL                           /* clear BSS */
231
232         PUSHQ   AX                              /* clear flags */
233         POPFQ
234
235         CALL    main(SB)
236
237 /*
238  * Park a processor. Should never fall through a return from main to here,
239  * should only be called by application processors when shutting down.
240  */
241 TEXT idle(SB), 1, $-4
242 _idle:
243         STI
244         HLT
245         JMP     _idle
246
247 /*
248  * The CPUID instruction is always supported on the amd64.
249  */
250 TEXT cpuid(SB), $-4
251         MOVL    RARG, AX                        /* function in AX */
252         CPUID
253
254         MOVQ    info+8(FP), BP
255         MOVL    AX, 0(BP)
256         MOVL    BX, 4(BP)
257         MOVL    CX, 8(BP)
258         MOVL    DX, 12(BP)
259         RET
260
261 /*
262  * Port I/O.
263  */
264 TEXT inb(SB), 1, $-4
265         MOVL    RARG, DX                        /* MOVL port+0(FP), DX */
266         XORL    AX, AX
267         INB
268         RET
269
270 TEXT insb(SB), 1, $-4
271         MOVL    RARG, DX                        /* MOVL port+0(FP), DX */
272         MOVQ    address+8(FP), DI
273         MOVL    count+16(FP), CX
274         CLD
275         REP;    INSB
276         RET
277
278 TEXT ins(SB), 1, $-4
279         MOVL    RARG, DX                        /* MOVL port+0(FP), DX */
280         XORL    AX, AX
281         INW
282         RET
283
284 TEXT inss(SB), 1, $-4
285         MOVL    RARG, DX                        /* MOVL port+0(FP), DX */
286         MOVQ    address+8(FP), DI
287         MOVL    count+16(FP), CX
288         CLD
289         REP;    INSW
290         RET
291
292 TEXT inl(SB), 1, $-4
293         MOVL    RARG, DX                        /* MOVL port+0(FP), DX */
294         INL
295         RET
296
297 TEXT insl(SB), 1, $-4
298         MOVL    RARG, DX                        /* MOVL port+0(FP), DX */
299         MOVQ    address+8(FP), DI
300         MOVL    count+16(FP), CX
301         CLD
302         REP; INSL
303         RET
304
305 TEXT outb(SB), 1, $-1
306         MOVL    RARG, DX                        /* MOVL port+0(FP), DX */
307         MOVL    byte+8(FP), AX
308         OUTB
309         RET
310
311 TEXT outsb(SB), 1, $-4
312         MOVL    RARG, DX                        /* MOVL port+0(FP), DX */
313         MOVQ    address+8(FP), SI
314         MOVL    count+16(FP), CX
315         CLD
316         REP; OUTSB
317         RET
318
319 TEXT outs(SB), 1, $-4
320         MOVL    RARG, DX                        /* MOVL port+0(FP), DX */
321         MOVL    short+8(FP), AX
322         OUTW
323         RET
324
325 TEXT outss(SB), 1, $-4
326         MOVL    RARG, DX                        /* MOVL port+0(FP), DX */
327         MOVQ    address+8(FP), SI
328         MOVL    count+16(FP), CX
329         CLD
330         REP; OUTSW
331         RET
332
333 TEXT outl(SB), 1, $-4
334         MOVL    RARG, DX                        /* MOVL port+0(FP), DX */
335         MOVL    long+8(FP), AX
336         OUTL
337         RET
338
339 TEXT outsl(SB), 1, $-4
340         MOVL    RARG, DX                        /* MOVL port+0(FP), DX */
341         MOVQ    address+8(FP), SI
342         MOVL    count+16(FP), CX
343         CLD
344         REP; OUTSL
345         RET
346
347 TEXT getgdt(SB), 1, $-4
348         MOVQ    RARG, AX
349         MOVL    GDTR, (AX)                      /* Note: 10 bytes returned */
350         RET
351
352 TEXT lgdt(SB), $0                               /* GDTR - global descriptor table */
353         MOVQ    RARG, AX
354         MOVL    (AX), GDTR
355         RET
356
357 TEXT lidt(SB), $0                               /* IDTR - interrupt descriptor table */
358         MOVQ    RARG, AX
359         MOVL    (AX), IDTR
360         RET
361
362 TEXT ltr(SB), 1, $-4
363         MOVW    RARG, AX
364         MOVW    AX, TASK
365         RET
366
367 /*
368  * Read/write various system registers.
369  */
370 TEXT getcr0(SB), 1, $-4                         /* Processor Control */
371         MOVQ    CR0, AX
372         RET
373
374 TEXT putcr0(SB), 1, $-4
375         MOVQ    RARG, CR0
376         RET
377
378 TEXT getcr2(SB), 1, $-4                         /* #PF Linear Address */
379         MOVQ    CR2, AX
380         RET
381
382 TEXT putcr2(SB), 1, $-4
383         MOVQ    BP, CR2
384         RET
385
386 TEXT getcr3(SB), 1, $-4                         /* PML4 Base */
387         MOVQ    CR3, AX
388         RET
389
390 TEXT putcr3(SB), 1, $-4
391         MOVQ    RARG, CR3
392         RET
393
394 TEXT getcr4(SB), 1, $-4                         /* Extensions */
395         MOVQ    CR4, AX
396         RET
397
398 TEXT putcr4(SB), 1, $-4
399         MOVQ    RARG, CR4
400         RET
401
402 TEXT mb386(SB), 1, $-4                          /* hack */
403 TEXT mb586(SB), 1, $-4
404         XORL    AX, AX
405         CPUID
406         RET
407
408 /*
409  * BIOS32.
410  */
411 TEXT bios32call(SB), 1, $-4
412         XORL    AX, AX
413         INCL    AX
414         RET
415
416 /*
417  * Basic timing loop to determine CPU frequency.
418  */
419 TEXT aamloop(SB), 1, $-4
420         MOVL    RARG, CX
421 _aamloop:
422         LOOP    _aamloop
423         RET
424
425 TEXT _cycles(SB), 1, $-4                        /* time stamp counter */
426         RDTSC
427         MOVL    AX, 0(RARG)                     /* lo */
428         MOVL    DX, 4(RARG)                     /* hi */
429         RET
430
431 TEXT rdmsr(SB), 1, $-4                          /* Model-Specific Register */
432         MOVL    RARG, CX
433         MOVQ    $0, BP
434 TEXT _rdmsrinst(SB), $0
435         RDMSR
436         MOVQ    vlong+8(FP), CX                 /* &vlong */
437         MOVL    AX, 0(CX)                       /* lo */
438         MOVL    DX, 4(CX)                       /* hi */
439         MOVQ    BP, AX                          /* BP set to -1 if traped */
440         RET
441         
442 TEXT wrmsr(SB), 1, $-4
443         MOVL    RARG, CX
444         MOVL    lo+8(FP), AX
445         MOVL    hi+12(FP), DX
446         MOVQ    $0, BP
447 TEXT _wrmsrinst(SB), $0
448         WRMSR
449         MOVQ    BP, AX                          /* BP set to -1 if traped */
450         RET
451
452 TEXT invlpg(SB), 1, $-4                         /* INVLPG va+0(FP) */
453         MOVQ    RARG, va+0(FP)
454
455         INVLPG  va+0(FP)
456
457         RET
458
459 TEXT wbinvd(SB), 1, $-4
460         WBINVD
461         RET
462
463 /*
464  * Serialisation.
465  */
466 TEXT lfence(SB), 1, $-4
467         LFENCE
468         RET
469
470 TEXT mfence(SB), 1, $-4
471         MFENCE
472         RET
473
474 TEXT sfence(SB), 1, $-4
475         SFENCE
476         RET
477
478 /*
479  * Note: CLI and STI are not serialising instructions.
480  * Is that assumed anywhere?
481  */
482 TEXT splhi(SB), 1, $-4
483 _splhi:
484         PUSHFQ
485         POPQ    AX
486         TESTQ   $0x200, AX                      /* 0x200 - Interrupt Flag */
487         JZ      _alreadyhi                      /* use CMOVLEQ etc. here? */
488
489         MOVQ    (SP), BX
490         MOVQ    BX, 8(RMACH)                    /* save PC in m->splpc */
491
492 _alreadyhi:
493         CLI
494         RET
495
496 TEXT spllo(SB), 1, $-4
497 _spllo:
498         PUSHFQ
499         POPQ    AX
500         TESTQ   $0x200, AX                      /* 0x200 - Interrupt Flag */
501         JNZ     _alreadylo                      /* use CMOVLEQ etc. here? */
502
503         MOVQ    $0, 8(RMACH)                    /* clear m->splpc */
504
505 _alreadylo:
506         STI
507         RET
508
509 TEXT splx(SB), 1, $-4
510         TESTQ   $0x200, RARG                    /* 0x200 - Interrupt Flag */
511         JNZ     _spllo
512         JMP     _splhi
513
514 TEXT spldone(SB), 1, $-4
515         RET
516
517 TEXT islo(SB), 1, $-4
518         PUSHFQ
519         POPQ    AX
520         ANDQ    $0x200, AX                      /* 0x200 - Interrupt Flag */
521         RET
522
523 /*
524  * Synchronisation
525  */
526 TEXT tas(SB), 1, $-4
527 TEXT _tas(SB), 1, $-4
528         MOVL    $0xdeaddead, AX
529         XCHGL   AX, (RARG)                      /*  */
530         RET
531
532 TEXT cmpswap486(SB), 1, $-4
533 TEXT cas(SB), 1, $-4
534         MOVL    exp+8(FP), AX
535         MOVL    new+16(FP), BX
536         LOCK; CMPXCHGL BX, (RARG)
537         MOVL    $1, AX                          /* use CMOVLEQ etc. here? */
538         JNZ     _cas32r0
539 _cas32r1:
540         RET
541 _cas32r0:
542         DECL    AX
543         RET
544
545 /*
546  * Label consists of a stack pointer and a programme counter
547  */
548 TEXT gotolabel(SB), 1, $-4
549         MOVQ    0(RARG), SP                     /* restore SP */
550         MOVQ    8(RARG), AX                     /* put return PC on the stack */
551         MOVQ    AX, 0(SP)
552         MOVL    $1, AX                          /* return 1 */
553         RET
554
555 TEXT setlabel(SB), 1, $-4
556         MOVQ    SP, 0(RARG)                     /* store SP */
557         MOVQ    0(SP), BX                       /* store return PC */
558         MOVQ    BX, 8(RARG)
559         MOVL    $0, AX                          /* return 0 */
560         RET
561
562 TEXT halt(SB), 1, $-4
563         CLI
564         CMPL    nrdy(SB), $0
565         JEQ     _nothingready
566         STI
567         RET
568 _nothingready:
569         STI
570         HLT
571         RET
572
573 TEXT mwait(SB), 1, $-4
574         MOVQ    RARG, AX
575         MOVL    (AX), CX
576         ORL     CX, CX
577         JNZ     _mwaitdone
578         XORL    DX, DX
579         BYTE $0x0f; BYTE $0x01; BYTE $0xc8      /* MONITOR */
580         MOVL    (AX), CX
581         ORL     CX, CX
582         JNZ     _mwaitdone
583         XORL    AX, AX
584         BYTE $0x0f; BYTE $0x01; BYTE $0xc9      /* MWAIT */
585 _mwaitdone:
586         RET
587
588 /*
589  * SIMD Floating Point.
590  * Note: for x87 instructions which have both a 'wait' and 'nowait' version,
591  * 8a only knows the 'wait' mnemonic but does NOT insertthe WAIT prefix byte
592  * (i.e. they act like their FNxxx variations) so WAIT instructions must be
593  * explicitly placed in the code if necessary.
594  */
595 TEXT _clts(SB), 1, $-4
596         CLTS
597         RET
598
599 TEXT _fldcw(SB), 1, $-4                         /* Load x87 FPU Control Word */
600         MOVQ    RARG, cw+0(FP)
601         FLDCW   cw+0(FP)
602         RET
603
604 TEXT _fnclex(SB), 1, $-4
605         FCLEX
606         RET
607
608 TEXT _fninit(SB), 1, $-4
609         FINIT                                   /* no WAIT */
610         RET
611
612 TEXT _fxrstor(SB), 1, $-4
613         FXRSTOR64 (RARG)
614         RET
615
616 TEXT _fxsave(SB), 1, $-4
617         FXSAVE64 (RARG)
618         RET
619
620 TEXT _fwait(SB), 1, $-4
621         WAIT
622         RET
623
624 TEXT _ldmxcsr(SB), 1, $-4                       /* Load MXCSR */
625         MOVQ    RARG, mxcsr+0(FP)
626         LDMXCSR mxcsr+0(FP)
627         RET
628
629 TEXT _stts(SB), 1, $-4
630         MOVQ    CR0, AX
631         ORQ     $8, AX                          /* Ts */
632         MOVQ    AX, CR0
633         RET
634
635 TEXT mul64fract(SB), 1, $-4
636         MOVQ    a+8(FP), AX
637         MULQ    b+16(FP)                        /* a*b */
638         SHRQ    $32, AX:DX
639         MOVQ    AX, (RARG)
640         RET
641
642 #define RDRANDAX        BYTE $0x0f; BYTE $0xc7; BYTE $0xf0
643 #define RDRAND64AX      BYTE $0x48; BYTE $0x0f; BYTE $0xc7;  BYTE $0xf0
644
645 TEXT rdrand32(SB), $-4
646 loop32:
647         RDRANDAX
648         JCC             loop32
649         RET
650
651 TEXT rdrand64(SB), $-4
652 loop64:
653         RDRAND64AX
654         JCC             loop64
655         RET
656
657 TEXT rdrandbuf(SB), $0
658         MOVQ    RARG, DX
659
660         MOVLQZX cnt+8(FP), CX
661         SHRQ    $3, CX
662 eights:
663         CMPL    CX, $0
664         JLE     f1
665         CALL    rdrand64(SB)
666         MOVQ    AX, 0(DX)
667         ADDQ    $8, DX
668         SUBL    $1, CX
669         JMP     eights
670
671 f1:
672         MOVLQZX cnt+8(FP), CX
673         ANDL    $7, CX
674         SHRQ    $2, CX
675 fours:
676         CMPL    CX, $0
677         JLE     f2
678         CALL    rdrand32(SB)
679         MOVL    AX, 0(DX)
680         ADDQ    $4, DX
681         SUBL    $1, CX
682         JMP     fours
683
684 f2:
685         MOVLQZX cnt+8(FP), CX
686         ANDL    $3, CX
687 ones:
688         CMPL    CX, $0
689         JLE     f3
690         CALL    rdrand32(SB)
691         MOVB    AX, 0(DX)
692         ADDQ    $1, DX
693         SUBL    $1, CX
694         JMP     ones
695
696 f3:
697         RET
698
699 /* debug register access */
700
701 TEXT putdr(SB), 1, $-4
702         MOVQ    56(BP), AX
703         MOVQ    AX, DR7
704         /* wet floor */
705 TEXT putdr01236(SB), 1, $-4
706         MOVQ    0(BP), AX
707         MOVQ    AX, DR0
708         MOVQ    8(BP), AX
709         MOVQ    AX, DR1
710         MOVQ    16(BP), AX
711         MOVQ    AX, DR2
712         MOVQ    24(BP), AX
713         MOVQ    AX, DR3
714         MOVQ    48(BP), AX
715         MOVQ    AX, DR6
716         RET
717
718 TEXT getdr6(SB), 1, $-4
719         MOVQ    DR6, AX
720         RET
721
722 TEXT putdr6(SB), 1, $-4
723         MOVQ    BP, DR6
724         RET
725
726 TEXT putdr7(SB), 1, $-4
727         MOVQ    BP, DR7
728         RET
729
730 /* VMX instructions */
731 TEXT vmxon(SB), 1, $-4
732         MOVQ    BP, 8(SP)
733         /* VMXON 8(SP) */
734         BYTE    $0xf3; BYTE $0x0f; BYTE $0xc7; BYTE $0x74; BYTE $0x24; BYTE $0x08
735         JMP     _vmout
736
737 TEXT vmxoff(SB), 1, $-4
738         BYTE    $0x0f; BYTE $0x01; BYTE $0xc4
739         JMP     _vmout
740
741 TEXT vmclear(SB), 1, $-4
742         MOVQ    BP, 8(SP)
743         /* VMCLEAR 8(SP) */
744         BYTE    $0x66;  BYTE $0x0f; BYTE $0xc7; BYTE $0x74; BYTE $0x24; BYTE $0x08
745         JMP     _vmout
746
747 TEXT vmlaunch(SB), 1, $-4
748         MOVL    $0x6C14, DI
749         MOVQ    SP, DX
750         BYTE    $0x0f; BYTE $0x79; BYTE $0xfa /* VMWRITE DX, DI */
751         JBE     _vmout
752         MOVL    $0x6C16, DI
753         MOVQ    $vmrestore(SB), DX
754         BYTE    $0x0f; BYTE $0x79; BYTE $0xfa /* VMWRITE DX, DI */
755         JBE     _vmout
756         
757         MOVQ    BP, ureg+0(FP)
758         MOVL    resume+8(FP), AX
759         TESTL   AX, AX
760         MOVQ    0x00(BP), AX
761         MOVQ    0x08(BP), BX
762         MOVQ    0x10(BP), CX
763         MOVQ    0x18(BP), DX
764         MOVQ    0x20(BP), SI
765         MOVQ    0x28(BP), DI
766         MOVQ    0x38(BP), R8
767         MOVQ    0x40(BP), R9
768         MOVQ    0x48(BP), R10
769         MOVQ    0x50(BP), R11
770         MOVQ    0x58(BP), R12
771         MOVQ    0x60(BP), R13
772         MOVQ    0x68(BP), R14
773         MOVQ    0x70(BP), R15
774         MOVQ    0x30(BP), BP
775         JNE     _vmresume
776         BYTE    $0x0f; BYTE $0x01; BYTE $0xc2 /* VMLAUNCH */
777         JMP     _vmout
778 _vmresume:
779         BYTE    $0x0f; BYTE $0x01; BYTE $0xc3 /* VMRESUME */
780         JMP _vmout
781         
782 TEXT vmrestore(SB), 1, $-4
783         PUSHQ   BP
784         MOVQ    ureg+0(FP), BP
785         MOVQ    AX, 0x00(BP)
786         MOVQ    BX, 0x08(BP)
787         MOVQ    CX, 0x10(BP)
788         MOVQ    DX, 0x18(BP)
789         MOVQ    SI, 0x20(BP)
790         MOVQ    DI, 0x28(BP)
791         POPQ    0x30(BP)
792         MOVQ    R8, 0x38(BP)
793         MOVQ    R9, 0x40(BP)
794         MOVQ    R10, 0x48(BP)
795         MOVQ    R11, 0x50(BP)
796         MOVQ    R12, 0x58(BP)
797         MOVQ    R13, 0x60(BP)
798         MOVQ    R14, 0x68(BP)
799         MOVQ    R15, 0x70(BP)
800         
801         BYTE    $0x65; MOVQ 0, RMACH /* MOVQ GS:(0), RMACH */
802         MOVQ    16(RMACH), RUSER
803         XORL    AX, AX
804         RET
805
806 TEXT vmptrld(SB), 1, $-4
807         MOVQ    BP, 8(SP)
808         /* VMMPTRLD 8(SP) */
809         BYTE    $0x0f; BYTE $0xc7; BYTE $0x74; BYTE $0x24; BYTE $0x08
810         JMP _vmout
811
812 TEXT vmwrite(SB), 1, $-4
813         MOVQ    val+8(FP), DX
814         /* VMWRITE DX, BP */
815         BYTE    $0x0f; BYTE $0x79; BYTE $0xea
816         JMP _vmout
817
818 TEXT vmread(SB), 1, $-4
819         MOVQ    valp+8(FP), DI
820         /* VMREAD BP, (DI) */
821         BYTE    $0x0f; BYTE $0x78; BYTE $0x2f
822         JMP _vmout
823
824 TEXT invept(SB), 1, $-4
825         /* INVEPT BP, 16(SP) */
826         BYTE    $0x66; BYTE $0x0f; BYTE $0x38; BYTE $0x80; BYTE $0x6c; BYTE $0x24; BYTE $0x10
827         JMP _vmout
828
829 TEXT invvpid(SB), 1, $-4
830         /* INVVPID BP, 16(SP) */
831         BYTE    $0x66; BYTE $0x0f; BYTE $0x38; BYTE $0x81; BYTE $0x6c; BYTE $0x24; BYTE $0x10
832         JMP _vmout
833
834 _vmout:
835         JC      _vmout1
836         JZ      _vmout2
837         XORL    AX, AX
838         RET
839 _vmout1:
840         MOVQ    $-1, AX
841         RET
842 _vmout2:
843         MOVQ    $-2, AX
844         RET
845
846 /*
847  */
848 TEXT touser(SB), 1, $-4
849         CLI
850         SWAPGS
851
852         MOVL    $0, RMACH
853         MOVL    $0, RUSER
854
855         MOVQ    $(UTZERO+0x28), CX              /* ip */
856         MOVL    $0x200, R11                     /* flags */
857         MOVQ    RARG, SP                        /* sp */
858
859         BYTE $0x48; SYSRET                      /* SYSRETQ */
860
861 /*
862  */
863 TEXT syscallentry(SB), 1, $-4
864         SWAPGS
865         BYTE $0x65; MOVQ 0, AX                  /* m-> (MOVQ GS:0x0, AX) */
866         MOVQ    16(AX), BX                      /* m->proc */
867         MOVQ    SP, R13
868         MOVQ    16(BX), SP                      /* m->proc->kstack */
869         ADDQ    $KSTACK, SP
870
871         PUSHQ   $UDSEL                          /* old stack segment */
872         PUSHQ   R13                             /* old sp */
873         PUSHQ   R11                             /* old flags */
874         PUSHQ   $UESEL                          /* old code segment */
875         PUSHQ   CX                              /* old ip */
876         PUSHQ   $0                              /* error code */
877         PUSHQ   $64                             /* trap number (VectorSYSCALL) */
878
879         SUBQ    $(8 + 23*8-7*8), SP             /* arg + sizeof(Ureg)-pushed */
880
881         MOVQ    RMACH, (15*8)(SP)               /* old r15 */
882         MOVQ    RUSER, (14*8)(SP)               /* old r14 */
883
884         MOVQ    RARG, (7*8)(SP)                 /* system call number */
885
886         MOVQ    AX, RMACH                       /* m */
887         MOVQ    BX, RUSER                       /* up */
888
889         LEAQ    8(SP), RARG                     /* Ureg* arg */
890
891         CALL    syscall(SB)
892
893 TEXT forkret(SB), 1, $-4
894         CLI
895         SWAPGS
896
897         MOVQ    8(SP), AX                       /* return value */
898
899         MOVQ    (15*8)(SP), RMACH               /* r15 */
900         MOVQ    (14*8)(SP), RUSER               /* r14 */
901
902         MOVQ    (19*8)(SP), CX                  /* ip */
903         MOVQ    (21*8)(SP), R11                 /* flags */
904         MOVQ    (22*8)(SP), SP                  /* sp */
905
906         BYTE $0x48; SYSRET                      /* SYSRETQ */
907
908 TEXT noteret(SB), 1, $-4
909         CLI
910         JMP _intrestore
911
912 /*
913  * Interrupt/exception handling.
914  */
915
916 TEXT _strayintr(SB), 1, $-4                     /* no error code pushed */
917         PUSHQ   AX                              /* save AX */
918         MOVQ    8(SP), AX                       /* vectortable(SB) PC */
919         JMP     _intrcommon
920
921 TEXT _strayintrx(SB), 1, $-4                    /* error code pushed */
922         XCHGQ   AX, (SP)
923 _intrcommon:
924         MOVBQZX (AX), AX
925         XCHGQ   AX, (SP)
926
927         SUBQ    $24, SP                         /* R1[45], [DEFG]S */
928         CMPW    48(SP), $KESEL                  /* old CS */
929         JEQ     _intrnested
930
931         MOVQ    RUSER, 0(SP)
932         MOVQ    RMACH, 8(SP)
933
934         SWAPGS
935         BYTE $0x65; MOVQ 0, RMACH               /* m-> (MOVQ GS:0x0, R15) */
936         MOVQ    16(RMACH), RUSER                /* up */
937
938 _intrnested:
939         PUSHQ   R13
940         PUSHQ   R12
941         PUSHQ   R11
942         PUSHQ   R10
943         PUSHQ   R9
944         PUSHQ   R8
945         PUSHQ   BP
946         PUSHQ   DI
947         PUSHQ   SI
948         PUSHQ   DX
949         PUSHQ   CX
950         PUSHQ   BX
951         PUSHQ   AX
952
953         MOVQ    SP, RARG
954         PUSHQ   SP
955         CALL    trap(SB)
956
957 _intrestore:
958         POPQ    AX
959
960         POPQ    AX
961         POPQ    BX
962         POPQ    CX
963         POPQ    DX
964         POPQ    SI
965         POPQ    DI
966         POPQ    BP
967         POPQ    R8
968         POPQ    R9
969         POPQ    R10
970         POPQ    R11
971         POPQ    R12
972         POPQ    R13
973
974         CMPQ    48(SP), $KESEL
975         JEQ     _iretnested
976
977         SWAPGS
978
979         MOVQ    8(SP), RMACH
980         MOVQ    0(SP), RUSER
981
982 _iretnested:
983         ADDQ    $40, SP
984         IRETQ
985
986 TEXT vectortable(SB), $0
987         CALL _strayintr(SB); BYTE $0x00         /* divide error */
988         CALL _strayintr(SB); BYTE $0x01         /* debug exception */
989         CALL _strayintr(SB); BYTE $0x02         /* NMI interrupt */
990         CALL _strayintr(SB); BYTE $0x03         /* breakpoint */
991         CALL _strayintr(SB); BYTE $0x04         /* overflow */
992         CALL _strayintr(SB); BYTE $0x05         /* bound */
993         CALL _strayintr(SB); BYTE $0x06         /* invalid opcode */
994         CALL _strayintr(SB); BYTE $0x07         /* no coprocessor available */
995         CALL _strayintrx(SB); BYTE $0x08        /* double fault */
996         CALL _strayintr(SB); BYTE $0x09         /* coprocessor segment overflow */
997         CALL _strayintrx(SB); BYTE $0x0A        /* invalid TSS */
998         CALL _strayintrx(SB); BYTE $0x0B        /* segment not available */
999         CALL _strayintrx(SB); BYTE $0x0C        /* stack exception */
1000         CALL _strayintrx(SB); BYTE $0x0D        /* general protection error */
1001         CALL _strayintrx(SB); BYTE $0x0E        /* page fault */
1002         CALL _strayintr(SB); BYTE $0x0F         /*  */
1003         CALL _strayintr(SB); BYTE $0x10         /* coprocessor error */
1004         CALL _strayintrx(SB); BYTE $0x11        /* alignment check */
1005         CALL _strayintr(SB); BYTE $0x12         /* machine check */
1006         CALL _strayintr(SB); BYTE $0x13         /* simd error */
1007         CALL _strayintr(SB); BYTE $0x14
1008         CALL _strayintr(SB); BYTE $0x15
1009         CALL _strayintr(SB); BYTE $0x16
1010         CALL _strayintr(SB); BYTE $0x17
1011         CALL _strayintr(SB); BYTE $0x18
1012         CALL _strayintr(SB); BYTE $0x19
1013         CALL _strayintr(SB); BYTE $0x1A
1014         CALL _strayintr(SB); BYTE $0x1B
1015         CALL _strayintr(SB); BYTE $0x1C
1016         CALL _strayintr(SB); BYTE $0x1D
1017         CALL _strayintr(SB); BYTE $0x1E
1018         CALL _strayintr(SB); BYTE $0x1F
1019         CALL _strayintr(SB); BYTE $0x20         /* VectorLAPIC */
1020         CALL _strayintr(SB); BYTE $0x21
1021         CALL _strayintr(SB); BYTE $0x22
1022         CALL _strayintr(SB); BYTE $0x23
1023         CALL _strayintr(SB); BYTE $0x24
1024         CALL _strayintr(SB); BYTE $0x25
1025         CALL _strayintr(SB); BYTE $0x26
1026         CALL _strayintr(SB); BYTE $0x27
1027         CALL _strayintr(SB); BYTE $0x28
1028         CALL _strayintr(SB); BYTE $0x29
1029         CALL _strayintr(SB); BYTE $0x2A
1030         CALL _strayintr(SB); BYTE $0x2B
1031         CALL _strayintr(SB); BYTE $0x2C
1032         CALL _strayintr(SB); BYTE $0x2D
1033         CALL _strayintr(SB); BYTE $0x2E
1034         CALL _strayintr(SB); BYTE $0x2F
1035         CALL _strayintr(SB); BYTE $0x30
1036         CALL _strayintr(SB); BYTE $0x31
1037         CALL _strayintr(SB); BYTE $0x32
1038         CALL _strayintr(SB); BYTE $0x33
1039         CALL _strayintr(SB); BYTE $0x34
1040         CALL _strayintr(SB); BYTE $0x35
1041         CALL _strayintr(SB); BYTE $0x36
1042         CALL _strayintr(SB); BYTE $0x37
1043         CALL _strayintr(SB); BYTE $0x38
1044         CALL _strayintr(SB); BYTE $0x39
1045         CALL _strayintr(SB); BYTE $0x3A
1046         CALL _strayintr(SB); BYTE $0x3B
1047         CALL _strayintr(SB); BYTE $0x3C
1048         CALL _strayintr(SB); BYTE $0x3D
1049         CALL _strayintr(SB); BYTE $0x3E
1050         CALL _strayintr(SB); BYTE $0x3F
1051         CALL _strayintr(SB); BYTE $0x40         /* was VectorSYSCALL */
1052         CALL _strayintr(SB); BYTE $0x41
1053         CALL _strayintr(SB); BYTE $0x42
1054         CALL _strayintr(SB); BYTE $0x43
1055         CALL _strayintr(SB); BYTE $0x44
1056         CALL _strayintr(SB); BYTE $0x45
1057         CALL _strayintr(SB); BYTE $0x46
1058         CALL _strayintr(SB); BYTE $0x47
1059         CALL _strayintr(SB); BYTE $0x48
1060         CALL _strayintr(SB); BYTE $0x49
1061         CALL _strayintr(SB); BYTE $0x4A
1062         CALL _strayintr(SB); BYTE $0x4B
1063         CALL _strayintr(SB); BYTE $0x4C
1064         CALL _strayintr(SB); BYTE $0x4D
1065         CALL _strayintr(SB); BYTE $0x4E
1066         CALL _strayintr(SB); BYTE $0x4F
1067         CALL _strayintr(SB); BYTE $0x50
1068         CALL _strayintr(SB); BYTE $0x51
1069         CALL _strayintr(SB); BYTE $0x52
1070         CALL _strayintr(SB); BYTE $0x53
1071         CALL _strayintr(SB); BYTE $0x54
1072         CALL _strayintr(SB); BYTE $0x55
1073         CALL _strayintr(SB); BYTE $0x56
1074         CALL _strayintr(SB); BYTE $0x57
1075         CALL _strayintr(SB); BYTE $0x58
1076         CALL _strayintr(SB); BYTE $0x59
1077         CALL _strayintr(SB); BYTE $0x5A
1078         CALL _strayintr(SB); BYTE $0x5B
1079         CALL _strayintr(SB); BYTE $0x5C
1080         CALL _strayintr(SB); BYTE $0x5D
1081         CALL _strayintr(SB); BYTE $0x5E
1082         CALL _strayintr(SB); BYTE $0x5F
1083         CALL _strayintr(SB); BYTE $0x60
1084         CALL _strayintr(SB); BYTE $0x61
1085         CALL _strayintr(SB); BYTE $0x62
1086         CALL _strayintr(SB); BYTE $0x63
1087         CALL _strayintr(SB); BYTE $0x64
1088         CALL _strayintr(SB); BYTE $0x65
1089         CALL _strayintr(SB); BYTE $0x66
1090         CALL _strayintr(SB); BYTE $0x67
1091         CALL _strayintr(SB); BYTE $0x68
1092         CALL _strayintr(SB); BYTE $0x69
1093         CALL _strayintr(SB); BYTE $0x6A
1094         CALL _strayintr(SB); BYTE $0x6B
1095         CALL _strayintr(SB); BYTE $0x6C
1096         CALL _strayintr(SB); BYTE $0x6D
1097         CALL _strayintr(SB); BYTE $0x6E
1098         CALL _strayintr(SB); BYTE $0x6F
1099         CALL _strayintr(SB); BYTE $0x70
1100         CALL _strayintr(SB); BYTE $0x71
1101         CALL _strayintr(SB); BYTE $0x72
1102         CALL _strayintr(SB); BYTE $0x73
1103         CALL _strayintr(SB); BYTE $0x74
1104         CALL _strayintr(SB); BYTE $0x75
1105         CALL _strayintr(SB); BYTE $0x76
1106         CALL _strayintr(SB); BYTE $0x77
1107         CALL _strayintr(SB); BYTE $0x78
1108         CALL _strayintr(SB); BYTE $0x79
1109         CALL _strayintr(SB); BYTE $0x7A
1110         CALL _strayintr(SB); BYTE $0x7B
1111         CALL _strayintr(SB); BYTE $0x7C
1112         CALL _strayintr(SB); BYTE $0x7D
1113         CALL _strayintr(SB); BYTE $0x7E
1114         CALL _strayintr(SB); BYTE $0x7F
1115         CALL _strayintr(SB); BYTE $0x80         /* Vector[A]PIC */
1116         CALL _strayintr(SB); BYTE $0x81
1117         CALL _strayintr(SB); BYTE $0x82
1118         CALL _strayintr(SB); BYTE $0x83
1119         CALL _strayintr(SB); BYTE $0x84
1120         CALL _strayintr(SB); BYTE $0x85
1121         CALL _strayintr(SB); BYTE $0x86
1122         CALL _strayintr(SB); BYTE $0x87
1123         CALL _strayintr(SB); BYTE $0x88
1124         CALL _strayintr(SB); BYTE $0x89
1125         CALL _strayintr(SB); BYTE $0x8A
1126         CALL _strayintr(SB); BYTE $0x8B
1127         CALL _strayintr(SB); BYTE $0x8C
1128         CALL _strayintr(SB); BYTE $0x8D
1129         CALL _strayintr(SB); BYTE $0x8E
1130         CALL _strayintr(SB); BYTE $0x8F
1131         CALL _strayintr(SB); BYTE $0x90
1132         CALL _strayintr(SB); BYTE $0x91
1133         CALL _strayintr(SB); BYTE $0x92
1134         CALL _strayintr(SB); BYTE $0x93
1135         CALL _strayintr(SB); BYTE $0x94
1136         CALL _strayintr(SB); BYTE $0x95
1137         CALL _strayintr(SB); BYTE $0x96
1138         CALL _strayintr(SB); BYTE $0x97
1139         CALL _strayintr(SB); BYTE $0x98
1140         CALL _strayintr(SB); BYTE $0x99
1141         CALL _strayintr(SB); BYTE $0x9A
1142         CALL _strayintr(SB); BYTE $0x9B
1143         CALL _strayintr(SB); BYTE $0x9C
1144         CALL _strayintr(SB); BYTE $0x9D
1145         CALL _strayintr(SB); BYTE $0x9E
1146         CALL _strayintr(SB); BYTE $0x9F
1147         CALL _strayintr(SB); BYTE $0xA0
1148         CALL _strayintr(SB); BYTE $0xA1
1149         CALL _strayintr(SB); BYTE $0xA2
1150         CALL _strayintr(SB); BYTE $0xA3
1151         CALL _strayintr(SB); BYTE $0xA4
1152         CALL _strayintr(SB); BYTE $0xA5
1153         CALL _strayintr(SB); BYTE $0xA6
1154         CALL _strayintr(SB); BYTE $0xA7
1155         CALL _strayintr(SB); BYTE $0xA8
1156         CALL _strayintr(SB); BYTE $0xA9
1157         CALL _strayintr(SB); BYTE $0xAA
1158         CALL _strayintr(SB); BYTE $0xAB
1159         CALL _strayintr(SB); BYTE $0xAC
1160         CALL _strayintr(SB); BYTE $0xAD
1161         CALL _strayintr(SB); BYTE $0xAE
1162         CALL _strayintr(SB); BYTE $0xAF
1163         CALL _strayintr(SB); BYTE $0xB0
1164         CALL _strayintr(SB); BYTE $0xB1
1165         CALL _strayintr(SB); BYTE $0xB2
1166         CALL _strayintr(SB); BYTE $0xB3
1167         CALL _strayintr(SB); BYTE $0xB4
1168         CALL _strayintr(SB); BYTE $0xB5
1169         CALL _strayintr(SB); BYTE $0xB6
1170         CALL _strayintr(SB); BYTE $0xB7
1171         CALL _strayintr(SB); BYTE $0xB8
1172         CALL _strayintr(SB); BYTE $0xB9
1173         CALL _strayintr(SB); BYTE $0xBA
1174         CALL _strayintr(SB); BYTE $0xBB
1175         CALL _strayintr(SB); BYTE $0xBC
1176         CALL _strayintr(SB); BYTE $0xBD
1177         CALL _strayintr(SB); BYTE $0xBE
1178         CALL _strayintr(SB); BYTE $0xBF
1179         CALL _strayintr(SB); BYTE $0xC0
1180         CALL _strayintr(SB); BYTE $0xC1
1181         CALL _strayintr(SB); BYTE $0xC2
1182         CALL _strayintr(SB); BYTE $0xC3
1183         CALL _strayintr(SB); BYTE $0xC4
1184         CALL _strayintr(SB); BYTE $0xC5
1185         CALL _strayintr(SB); BYTE $0xC6
1186         CALL _strayintr(SB); BYTE $0xC7
1187         CALL _strayintr(SB); BYTE $0xC8
1188         CALL _strayintr(SB); BYTE $0xC9
1189         CALL _strayintr(SB); BYTE $0xCA
1190         CALL _strayintr(SB); BYTE $0xCB
1191         CALL _strayintr(SB); BYTE $0xCC
1192         CALL _strayintr(SB); BYTE $0xCD
1193         CALL _strayintr(SB); BYTE $0xCE
1194         CALL _strayintr(SB); BYTE $0xCF
1195         CALL _strayintr(SB); BYTE $0xD0
1196         CALL _strayintr(SB); BYTE $0xD1
1197         CALL _strayintr(SB); BYTE $0xD2
1198         CALL _strayintr(SB); BYTE $0xD3
1199         CALL _strayintr(SB); BYTE $0xD4
1200         CALL _strayintr(SB); BYTE $0xD5
1201         CALL _strayintr(SB); BYTE $0xD6
1202         CALL _strayintr(SB); BYTE $0xD7
1203         CALL _strayintr(SB); BYTE $0xD8
1204         CALL _strayintr(SB); BYTE $0xD9
1205         CALL _strayintr(SB); BYTE $0xDA
1206         CALL _strayintr(SB); BYTE $0xDB
1207         CALL _strayintr(SB); BYTE $0xDC
1208         CALL _strayintr(SB); BYTE $0xDD
1209         CALL _strayintr(SB); BYTE $0xDE
1210         CALL _strayintr(SB); BYTE $0xDF
1211         CALL _strayintr(SB); BYTE $0xE0
1212         CALL _strayintr(SB); BYTE $0xE1
1213         CALL _strayintr(SB); BYTE $0xE2
1214         CALL _strayintr(SB); BYTE $0xE3
1215         CALL _strayintr(SB); BYTE $0xE4
1216         CALL _strayintr(SB); BYTE $0xE5
1217         CALL _strayintr(SB); BYTE $0xE6
1218         CALL _strayintr(SB); BYTE $0xE7
1219         CALL _strayintr(SB); BYTE $0xE8
1220         CALL _strayintr(SB); BYTE $0xE9
1221         CALL _strayintr(SB); BYTE $0xEA
1222         CALL _strayintr(SB); BYTE $0xEB
1223         CALL _strayintr(SB); BYTE $0xEC
1224         CALL _strayintr(SB); BYTE $0xED
1225         CALL _strayintr(SB); BYTE $0xEE
1226         CALL _strayintr(SB); BYTE $0xEF
1227         CALL _strayintr(SB); BYTE $0xF0
1228         CALL _strayintr(SB); BYTE $0xF1
1229         CALL _strayintr(SB); BYTE $0xF2
1230         CALL _strayintr(SB); BYTE $0xF3
1231         CALL _strayintr(SB); BYTE $0xF4
1232         CALL _strayintr(SB); BYTE $0xF5
1233         CALL _strayintr(SB); BYTE $0xF6
1234         CALL _strayintr(SB); BYTE $0xF7
1235         CALL _strayintr(SB); BYTE $0xF8
1236         CALL _strayintr(SB); BYTE $0xF9
1237         CALL _strayintr(SB); BYTE $0xFA
1238         CALL _strayintr(SB); BYTE $0xFB
1239         CALL _strayintr(SB); BYTE $0xFC
1240         CALL _strayintr(SB); BYTE $0xFD
1241         CALL _strayintr(SB); BYTE $0xFE
1242         CALL _strayintr(SB); BYTE $0xFF