]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc64/l.s
bcm, bcm64: add support for device tree parameter passing
[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 /* fault-proof memcpy */
453 TEXT peek(SB), 1, $-4
454         MOVQ    RARG, SI
455         MOVQ    dst+8(FP), DI
456         MOVL    cnt+16(FP), CX
457         CLD
458 TEXT _peekinst(SB), $0
459         REP; MOVSB
460         MOVL    CX, AX
461         RET
462         
463
464 TEXT invlpg(SB), 1, $-4
465         INVLPG  (RARG)
466         RET
467
468 TEXT wbinvd(SB), 1, $-4
469         WBINVD
470         RET
471
472 /*
473  * Serialisation.
474  */
475 TEXT lfence(SB), 1, $-4
476         LFENCE
477         RET
478
479 TEXT mfence(SB), 1, $-4
480         MFENCE
481         RET
482
483 TEXT sfence(SB), 1, $-4
484         SFENCE
485         RET
486
487 /*
488  * Note: CLI and STI are not serialising instructions.
489  * Is that assumed anywhere?
490  */
491 TEXT splhi(SB), 1, $-4
492 _splhi:
493         PUSHFQ
494         POPQ    AX
495         TESTQ   $0x200, AX                      /* 0x200 - Interrupt Flag */
496         JZ      _alreadyhi                      /* use CMOVLEQ etc. here? */
497
498         MOVQ    (SP), BX
499         MOVQ    BX, 8(RMACH)                    /* save PC in m->splpc */
500
501 _alreadyhi:
502         CLI
503         RET
504
505 TEXT spllo(SB), 1, $-4
506 _spllo:
507         PUSHFQ
508         POPQ    AX
509         TESTQ   $0x200, AX                      /* 0x200 - Interrupt Flag */
510         JNZ     _alreadylo                      /* use CMOVLEQ etc. here? */
511
512         MOVQ    $0, 8(RMACH)                    /* clear m->splpc */
513
514 _alreadylo:
515         STI
516         RET
517
518 TEXT splx(SB), 1, $-4
519         TESTQ   $0x200, RARG                    /* 0x200 - Interrupt Flag */
520         JNZ     _spllo
521         JMP     _splhi
522
523 TEXT spldone(SB), 1, $-4
524         RET
525
526 TEXT islo(SB), 1, $-4
527         PUSHFQ
528         POPQ    AX
529         ANDQ    $0x200, AX                      /* 0x200 - Interrupt Flag */
530         RET
531
532 /*
533  * Synchronisation
534  */
535 TEXT tas(SB), 1, $-4
536 TEXT _tas(SB), 1, $-4
537         MOVL    $0xdeaddead, AX
538         XCHGL   AX, (RARG)                      /*  */
539         RET
540
541 TEXT cmpswap486(SB), 1, $-4
542 TEXT cas(SB), 1, $-4
543         MOVL    exp+8(FP), AX
544         MOVL    new+16(FP), BX
545         LOCK; CMPXCHGL BX, (RARG)
546         MOVL    $1, AX                          /* use CMOVLEQ etc. here? */
547         JNZ     _cas32r0
548 _cas32r1:
549         RET
550 _cas32r0:
551         DECL    AX
552         RET
553
554 /*
555  * Label consists of a stack pointer and a programme counter
556  */
557 TEXT gotolabel(SB), 1, $-4
558         MOVQ    0(RARG), SP                     /* restore SP */
559         MOVQ    8(RARG), AX                     /* put return PC on the stack */
560         MOVQ    AX, 0(SP)
561         MOVL    $1, AX                          /* return 1 */
562         RET
563
564 TEXT setlabel(SB), 1, $-4
565         MOVQ    SP, 0(RARG)                     /* store SP */
566         MOVQ    0(SP), BX                       /* store return PC */
567         MOVQ    BX, 8(RARG)
568         MOVL    $0, AX                          /* return 0 */
569         RET
570
571 TEXT halt(SB), 1, $-4
572         CLI
573         CMPL    nrdy(SB), $0
574         JEQ     _nothingready
575         STI
576         RET
577 _nothingready:
578         STI
579         HLT
580         RET
581
582 TEXT mwait(SB), 1, $-4
583         MOVQ    RARG, AX
584         MOVL    (AX), CX
585         ORL     CX, CX
586         JNZ     _mwaitdone
587         XORL    DX, DX
588         BYTE $0x0f; BYTE $0x01; BYTE $0xc8      /* MONITOR */
589         MOVL    (AX), CX
590         ORL     CX, CX
591         JNZ     _mwaitdone
592         XORL    AX, AX
593         BYTE $0x0f; BYTE $0x01; BYTE $0xc9      /* MWAIT */
594 _mwaitdone:
595         RET
596
597 /*
598  * SIMD Floating Point.
599  * Note: for x87 instructions which have both a 'wait' and 'nowait' version,
600  * 8a only knows the 'wait' mnemonic but does NOT insertthe WAIT prefix byte
601  * (i.e. they act like their FNxxx variations) so WAIT instructions must be
602  * explicitly placed in the code if necessary.
603  */
604 TEXT _clts(SB), 1, $-4
605         CLTS
606         RET
607
608 TEXT _fldcw(SB), 1, $-4                         /* Load x87 FPU Control Word */
609         MOVQ    RARG, cw+0(FP)
610         FLDCW   cw+0(FP)
611         RET
612
613 TEXT _fnclex(SB), 1, $-4
614         FCLEX
615         RET
616
617 TEXT _fninit(SB), 1, $-4
618         FINIT                                   /* no WAIT */
619         RET
620
621 TEXT _fxrstor(SB), 1, $-4
622         FXRSTOR64 (RARG)
623         RET
624
625 TEXT _fxsave(SB), 1, $-4
626         FXSAVE64 (RARG)
627         RET
628
629 TEXT _fwait(SB), 1, $-4
630         WAIT
631         RET
632
633 TEXT _ldmxcsr(SB), 1, $-4                       /* Load MXCSR */
634         MOVQ    RARG, mxcsr+0(FP)
635         LDMXCSR mxcsr+0(FP)
636         RET
637
638 TEXT _stts(SB), 1, $-4
639         MOVQ    CR0, AX
640         ORQ     $8, AX                          /* Ts */
641         MOVQ    AX, CR0
642         RET
643
644 TEXT mul64fract(SB), 1, $-4
645         MOVQ    a+8(FP), AX
646         MULQ    b+16(FP)                        /* a*b */
647         SHRQ    $32, AX:DX
648         MOVQ    AX, (RARG)
649         RET
650
651 #define RDRANDAX        BYTE $0x0f; BYTE $0xc7; BYTE $0xf0
652 #define RDRAND64AX      BYTE $0x48; BYTE $0x0f; BYTE $0xc7;  BYTE $0xf0
653
654 TEXT rdrand32(SB), $-4
655 loop32:
656         RDRANDAX
657         JCC             loop32
658         RET
659
660 TEXT rdrand64(SB), $-4
661 loop64:
662         RDRAND64AX
663         JCC             loop64
664         RET
665
666 TEXT rdrandbuf(SB), $0
667         MOVQ    RARG, DX
668
669         MOVLQZX cnt+8(FP), CX
670         SHRQ    $3, CX
671 eights:
672         CMPL    CX, $0
673         JLE     f1
674         CALL    rdrand64(SB)
675         MOVQ    AX, 0(DX)
676         ADDQ    $8, DX
677         SUBL    $1, CX
678         JMP     eights
679
680 f1:
681         MOVLQZX cnt+8(FP), CX
682         ANDL    $7, CX
683         SHRQ    $2, CX
684 fours:
685         CMPL    CX, $0
686         JLE     f2
687         CALL    rdrand32(SB)
688         MOVL    AX, 0(DX)
689         ADDQ    $4, DX
690         SUBL    $1, CX
691         JMP     fours
692
693 f2:
694         MOVLQZX cnt+8(FP), CX
695         ANDL    $3, CX
696 ones:
697         CMPL    CX, $0
698         JLE     f3
699         CALL    rdrand32(SB)
700         MOVB    AX, 0(DX)
701         ADDQ    $1, DX
702         SUBL    $1, CX
703         JMP     ones
704
705 f3:
706         RET
707
708 /* debug register access */
709
710 TEXT putdr(SB), 1, $-4
711         MOVQ    56(BP), AX
712         MOVQ    AX, DR7
713         /* wet floor */
714 TEXT putdr01236(SB), 1, $-4
715         MOVQ    0(BP), AX
716         MOVQ    AX, DR0
717         MOVQ    8(BP), AX
718         MOVQ    AX, DR1
719         MOVQ    16(BP), AX
720         MOVQ    AX, DR2
721         MOVQ    24(BP), AX
722         MOVQ    AX, DR3
723         MOVQ    48(BP), AX
724         MOVQ    AX, DR6
725         RET
726
727 TEXT getdr6(SB), 1, $-4
728         MOVQ    DR6, AX
729         RET
730
731 TEXT putdr6(SB), 1, $-4
732         MOVQ    BP, DR6
733         RET
734
735 TEXT putdr7(SB), 1, $-4
736         MOVQ    BP, DR7
737         RET
738
739 /* VMX instructions */
740 TEXT vmxon(SB), 1, $-4
741         MOVQ    BP, 8(SP)
742         /* VMXON 8(SP) */
743         BYTE    $0xf3; BYTE $0x0f; BYTE $0xc7; BYTE $0x74; BYTE $0x24; BYTE $0x08
744         JMP     _vmout
745
746 TEXT vmxoff(SB), 1, $-4
747         BYTE    $0x0f; BYTE $0x01; BYTE $0xc4
748         JMP     _vmout
749
750 TEXT vmclear(SB), 1, $-4
751         MOVQ    BP, 8(SP)
752         /* VMCLEAR 8(SP) */
753         BYTE    $0x66;  BYTE $0x0f; BYTE $0xc7; BYTE $0x74; BYTE $0x24; BYTE $0x08
754         JMP     _vmout
755
756 TEXT vmlaunch(SB), 1, $-4
757         MOVL    $0x6C14, DI
758         MOVQ    SP, DX
759         BYTE    $0x0f; BYTE $0x79; BYTE $0xfa /* VMWRITE DX, DI */
760         JBE     _vmout
761         MOVL    $0x6C16, DI
762         MOVQ    $vmrestore(SB), DX
763         BYTE    $0x0f; BYTE $0x79; BYTE $0xfa /* VMWRITE DX, DI */
764         JBE     _vmout
765         
766         MOVQ    BP, ureg+0(FP)
767         MOVL    resume+8(FP), AX
768         TESTL   AX, AX
769         MOVQ    0x00(BP), AX
770         MOVQ    0x08(BP), BX
771         MOVQ    0x10(BP), CX
772         MOVQ    0x18(BP), DX
773         MOVQ    0x20(BP), SI
774         MOVQ    0x28(BP), DI
775         MOVQ    0x38(BP), R8
776         MOVQ    0x40(BP), R9
777         MOVQ    0x48(BP), R10
778         MOVQ    0x50(BP), R11
779         MOVQ    0x58(BP), R12
780         MOVQ    0x60(BP), R13
781         MOVQ    0x68(BP), R14
782         MOVQ    0x70(BP), R15
783         MOVQ    0x30(BP), BP
784         JNE     _vmresume
785         BYTE    $0x0f; BYTE $0x01; BYTE $0xc2 /* VMLAUNCH */
786         JMP     _vmout
787 _vmresume:
788         BYTE    $0x0f; BYTE $0x01; BYTE $0xc3 /* VMRESUME */
789         JMP _vmout
790         
791 TEXT vmrestore(SB), 1, $-4
792         PUSHQ   BP
793         MOVQ    ureg+0(FP), BP
794         MOVQ    AX, 0x00(BP)
795         MOVQ    BX, 0x08(BP)
796         MOVQ    CX, 0x10(BP)
797         MOVQ    DX, 0x18(BP)
798         MOVQ    SI, 0x20(BP)
799         MOVQ    DI, 0x28(BP)
800         POPQ    0x30(BP)
801         MOVQ    R8, 0x38(BP)
802         MOVQ    R9, 0x40(BP)
803         MOVQ    R10, 0x48(BP)
804         MOVQ    R11, 0x50(BP)
805         MOVQ    R12, 0x58(BP)
806         MOVQ    R13, 0x60(BP)
807         MOVQ    R14, 0x68(BP)
808         MOVQ    R15, 0x70(BP)
809         
810         BYTE    $0x65; MOVQ 0, RMACH /* MOVQ GS:(0), RMACH */
811         MOVQ    16(RMACH), RUSER
812         XORL    AX, AX
813         RET
814
815 TEXT vmptrld(SB), 1, $-4
816         MOVQ    BP, 8(SP)
817         /* VMMPTRLD 8(SP) */
818         BYTE    $0x0f; BYTE $0xc7; BYTE $0x74; BYTE $0x24; BYTE $0x08
819         JMP _vmout
820
821 TEXT vmwrite(SB), 1, $-4
822         MOVQ    val+8(FP), DX
823         /* VMWRITE DX, BP */
824         BYTE    $0x0f; BYTE $0x79; BYTE $0xea
825         JMP _vmout
826
827 TEXT vmread(SB), 1, $-4
828         MOVQ    valp+8(FP), DI
829         /* VMREAD BP, (DI) */
830         BYTE    $0x0f; BYTE $0x78; BYTE $0x2f
831         JMP _vmout
832
833 TEXT invept(SB), 1, $-4
834         /* INVEPT BP, 16(SP) */
835         BYTE    $0x66; BYTE $0x0f; BYTE $0x38; BYTE $0x80; BYTE $0x6c; BYTE $0x24; BYTE $0x10
836         JMP _vmout
837
838 TEXT invvpid(SB), 1, $-4
839         /* INVVPID BP, 16(SP) */
840         BYTE    $0x66; BYTE $0x0f; BYTE $0x38; BYTE $0x81; BYTE $0x6c; BYTE $0x24; BYTE $0x10
841         JMP _vmout
842
843 _vmout:
844         JC      _vmout1
845         JZ      _vmout2
846         XORL    AX, AX
847         RET
848 _vmout1:
849         MOVQ    $-1, AX
850         RET
851 _vmout2:
852         MOVQ    $-2, AX
853         RET
854
855 /*
856  */
857 TEXT touser(SB), 1, $-4
858         CLI
859         SWAPGS
860
861         MOVL    $0, RMACH
862         MOVL    $0, RUSER
863
864         MOVQ    $(UTZERO+0x28), CX              /* ip */
865         MOVL    $0x200, R11                     /* flags */
866         MOVQ    RARG, SP                        /* sp */
867
868         BYTE $0x48; SYSRET                      /* SYSRETQ */
869
870 /*
871  */
872 TEXT syscallentry(SB), 1, $-4
873         SWAPGS
874         BYTE $0x65; MOVQ 0, AX                  /* m-> (MOVQ GS:0x0, AX) */
875         MOVQ    16(AX), BX                      /* m->proc */
876         MOVQ    SP, R13
877         MOVQ    16(BX), SP                      /* m->proc->kstack */
878         ADDQ    $KSTACK, SP
879
880         PUSHQ   $UDSEL                          /* old stack segment */
881         PUSHQ   R13                             /* old sp */
882         PUSHQ   R11                             /* old flags */
883         PUSHQ   $UESEL                          /* old code segment */
884         PUSHQ   CX                              /* old ip */
885         PUSHQ   $0                              /* error code */
886         PUSHQ   $64                             /* trap number (VectorSYSCALL) */
887
888         SUBQ    $(8 + 23*8-7*8), SP             /* arg + sizeof(Ureg)-pushed */
889
890         MOVQ    RMACH, (15*8)(SP)               /* old r15 */
891         MOVQ    RUSER, (14*8)(SP)               /* old r14 */
892
893         MOVQ    RARG, (7*8)(SP)                 /* system call number */
894
895         MOVQ    AX, RMACH                       /* m */
896         MOVQ    BX, RUSER                       /* up */
897
898         LEAQ    8(SP), RARG                     /* Ureg* arg */
899
900         CALL    syscall(SB)
901
902 TEXT forkret(SB), 1, $-4
903         CLI
904         SWAPGS
905
906         MOVQ    8(SP), AX                       /* return value */
907
908         MOVQ    (15*8)(SP), RMACH               /* r15 */
909         MOVQ    (14*8)(SP), RUSER               /* r14 */
910
911         MOVQ    (19*8)(SP), CX                  /* ip */
912         MOVQ    (21*8)(SP), R11                 /* flags */
913         MOVQ    (22*8)(SP), SP                  /* sp */
914
915         BYTE $0x48; SYSRET                      /* SYSRETQ */
916
917 /*
918  * Interrupt/exception handling.
919  */
920
921 TEXT _strayintr(SB), 1, $-4                     /* no error code pushed */
922         PUSHQ   AX                              /* save AX */
923         MOVQ    8(SP), AX                       /* vectortable(SB) PC */
924         JMP     _intrcommon
925
926 TEXT _strayintrx(SB), 1, $-4                    /* error code pushed */
927         XCHGQ   AX, (SP)
928 _intrcommon:
929         MOVBQZX (AX), AX
930         XCHGQ   AX, (SP)
931
932         SUBQ    $24, SP                         /* R1[45], [DEFG]S */
933         CMPW    48(SP), $KESEL                  /* old CS */
934         JEQ     _intrnested
935
936         MOVQ    RUSER, 0(SP)
937         MOVQ    RMACH, 8(SP)
938
939         SWAPGS
940         BYTE $0x65; MOVQ 0, RMACH               /* m-> (MOVQ GS:0x0, R15) */
941         MOVQ    16(RMACH), RUSER                /* up */
942
943 _intrnested:
944         PUSHQ   R13
945         PUSHQ   R12
946         PUSHQ   R11
947         PUSHQ   R10
948         PUSHQ   R9
949         PUSHQ   R8
950         PUSHQ   BP
951         PUSHQ   DI
952         PUSHQ   SI
953         PUSHQ   DX
954         PUSHQ   CX
955         PUSHQ   BX
956         PUSHQ   AX
957
958         MOVQ    SP, RARG
959         PUSHQ   SP
960         CALL    trap(SB)
961
962 TEXT _intrr(SB), 1, $-4
963 _intrestore:
964         POPQ    AX
965
966         POPQ    AX
967         POPQ    BX
968         POPQ    CX
969         POPQ    DX
970         POPQ    SI
971         POPQ    DI
972         POPQ    BP
973         POPQ    R8
974         POPQ    R9
975         POPQ    R10
976         POPQ    R11
977         POPQ    R12
978         POPQ    R13
979
980         CMPQ    48(SP), $KESEL
981         JEQ     _iretnested
982
983         SWAPGS
984
985         MOVQ    8(SP), RMACH
986         MOVQ    0(SP), RUSER
987
988 _iretnested:
989         ADDQ    $40, SP
990         IRETQ
991
992 TEXT noteret(SB), 1, $-4
993         CLI
994         JMP     _intrestore
995
996 TEXT vectortable(SB), $0
997         CALL _strayintr(SB); BYTE $0x00         /* divide error */
998         CALL _strayintr(SB); BYTE $0x01         /* debug exception */
999         CALL _strayintr(SB); BYTE $0x02         /* NMI interrupt */
1000         CALL _strayintr(SB); BYTE $0x03         /* breakpoint */
1001         CALL _strayintr(SB); BYTE $0x04         /* overflow */
1002         CALL _strayintr(SB); BYTE $0x05         /* bound */
1003         CALL _strayintr(SB); BYTE $0x06         /* invalid opcode */
1004         CALL _strayintr(SB); BYTE $0x07         /* no coprocessor available */
1005         CALL _strayintrx(SB); BYTE $0x08        /* double fault */
1006         CALL _strayintr(SB); BYTE $0x09         /* coprocessor segment overflow */
1007         CALL _strayintrx(SB); BYTE $0x0A        /* invalid TSS */
1008         CALL _strayintrx(SB); BYTE $0x0B        /* segment not available */
1009         CALL _strayintrx(SB); BYTE $0x0C        /* stack exception */
1010         CALL _strayintrx(SB); BYTE $0x0D        /* general protection error */
1011         CALL _strayintrx(SB); BYTE $0x0E        /* page fault */
1012         CALL _strayintr(SB); BYTE $0x0F         /*  */
1013         CALL _strayintr(SB); BYTE $0x10         /* coprocessor error */
1014         CALL _strayintrx(SB); BYTE $0x11        /* alignment check */
1015         CALL _strayintr(SB); BYTE $0x12         /* machine check */
1016         CALL _strayintr(SB); BYTE $0x13         /* simd error */
1017         CALL _strayintr(SB); BYTE $0x14
1018         CALL _strayintr(SB); BYTE $0x15
1019         CALL _strayintr(SB); BYTE $0x16
1020         CALL _strayintr(SB); BYTE $0x17
1021         CALL _strayintr(SB); BYTE $0x18
1022         CALL _strayintr(SB); BYTE $0x19
1023         CALL _strayintr(SB); BYTE $0x1A
1024         CALL _strayintr(SB); BYTE $0x1B
1025         CALL _strayintr(SB); BYTE $0x1C
1026         CALL _strayintr(SB); BYTE $0x1D
1027         CALL _strayintr(SB); BYTE $0x1E
1028         CALL _strayintr(SB); BYTE $0x1F
1029         CALL _strayintr(SB); BYTE $0x20         /* VectorLAPIC */
1030         CALL _strayintr(SB); BYTE $0x21
1031         CALL _strayintr(SB); BYTE $0x22
1032         CALL _strayintr(SB); BYTE $0x23
1033         CALL _strayintr(SB); BYTE $0x24
1034         CALL _strayintr(SB); BYTE $0x25
1035         CALL _strayintr(SB); BYTE $0x26
1036         CALL _strayintr(SB); BYTE $0x27
1037         CALL _strayintr(SB); BYTE $0x28
1038         CALL _strayintr(SB); BYTE $0x29
1039         CALL _strayintr(SB); BYTE $0x2A
1040         CALL _strayintr(SB); BYTE $0x2B
1041         CALL _strayintr(SB); BYTE $0x2C
1042         CALL _strayintr(SB); BYTE $0x2D
1043         CALL _strayintr(SB); BYTE $0x2E
1044         CALL _strayintr(SB); BYTE $0x2F
1045         CALL _strayintr(SB); BYTE $0x30
1046         CALL _strayintr(SB); BYTE $0x31
1047         CALL _strayintr(SB); BYTE $0x32
1048         CALL _strayintr(SB); BYTE $0x33
1049         CALL _strayintr(SB); BYTE $0x34
1050         CALL _strayintr(SB); BYTE $0x35
1051         CALL _strayintr(SB); BYTE $0x36
1052         CALL _strayintr(SB); BYTE $0x37
1053         CALL _strayintr(SB); BYTE $0x38
1054         CALL _strayintr(SB); BYTE $0x39
1055         CALL _strayintr(SB); BYTE $0x3A
1056         CALL _strayintr(SB); BYTE $0x3B
1057         CALL _strayintr(SB); BYTE $0x3C
1058         CALL _strayintr(SB); BYTE $0x3D
1059         CALL _strayintr(SB); BYTE $0x3E
1060         CALL _strayintr(SB); BYTE $0x3F
1061         CALL _strayintr(SB); BYTE $0x40         /* was VectorSYSCALL */
1062         CALL _strayintr(SB); BYTE $0x41
1063         CALL _strayintr(SB); BYTE $0x42
1064         CALL _strayintr(SB); BYTE $0x43
1065         CALL _strayintr(SB); BYTE $0x44
1066         CALL _strayintr(SB); BYTE $0x45
1067         CALL _strayintr(SB); BYTE $0x46
1068         CALL _strayintr(SB); BYTE $0x47
1069         CALL _strayintr(SB); BYTE $0x48
1070         CALL _strayintr(SB); BYTE $0x49
1071         CALL _strayintr(SB); BYTE $0x4A
1072         CALL _strayintr(SB); BYTE $0x4B
1073         CALL _strayintr(SB); BYTE $0x4C
1074         CALL _strayintr(SB); BYTE $0x4D
1075         CALL _strayintr(SB); BYTE $0x4E
1076         CALL _strayintr(SB); BYTE $0x4F
1077         CALL _strayintr(SB); BYTE $0x50
1078         CALL _strayintr(SB); BYTE $0x51
1079         CALL _strayintr(SB); BYTE $0x52
1080         CALL _strayintr(SB); BYTE $0x53
1081         CALL _strayintr(SB); BYTE $0x54
1082         CALL _strayintr(SB); BYTE $0x55
1083         CALL _strayintr(SB); BYTE $0x56
1084         CALL _strayintr(SB); BYTE $0x57
1085         CALL _strayintr(SB); BYTE $0x58
1086         CALL _strayintr(SB); BYTE $0x59
1087         CALL _strayintr(SB); BYTE $0x5A
1088         CALL _strayintr(SB); BYTE $0x5B
1089         CALL _strayintr(SB); BYTE $0x5C
1090         CALL _strayintr(SB); BYTE $0x5D
1091         CALL _strayintr(SB); BYTE $0x5E
1092         CALL _strayintr(SB); BYTE $0x5F
1093         CALL _strayintr(SB); BYTE $0x60
1094         CALL _strayintr(SB); BYTE $0x61
1095         CALL _strayintr(SB); BYTE $0x62
1096         CALL _strayintr(SB); BYTE $0x63
1097         CALL _strayintr(SB); BYTE $0x64
1098         CALL _strayintr(SB); BYTE $0x65
1099         CALL _strayintr(SB); BYTE $0x66
1100         CALL _strayintr(SB); BYTE $0x67
1101         CALL _strayintr(SB); BYTE $0x68
1102         CALL _strayintr(SB); BYTE $0x69
1103         CALL _strayintr(SB); BYTE $0x6A
1104         CALL _strayintr(SB); BYTE $0x6B
1105         CALL _strayintr(SB); BYTE $0x6C
1106         CALL _strayintr(SB); BYTE $0x6D
1107         CALL _strayintr(SB); BYTE $0x6E
1108         CALL _strayintr(SB); BYTE $0x6F
1109         CALL _strayintr(SB); BYTE $0x70
1110         CALL _strayintr(SB); BYTE $0x71
1111         CALL _strayintr(SB); BYTE $0x72
1112         CALL _strayintr(SB); BYTE $0x73
1113         CALL _strayintr(SB); BYTE $0x74
1114         CALL _strayintr(SB); BYTE $0x75
1115         CALL _strayintr(SB); BYTE $0x76
1116         CALL _strayintr(SB); BYTE $0x77
1117         CALL _strayintr(SB); BYTE $0x78
1118         CALL _strayintr(SB); BYTE $0x79
1119         CALL _strayintr(SB); BYTE $0x7A
1120         CALL _strayintr(SB); BYTE $0x7B
1121         CALL _strayintr(SB); BYTE $0x7C
1122         CALL _strayintr(SB); BYTE $0x7D
1123         CALL _strayintr(SB); BYTE $0x7E
1124         CALL _strayintr(SB); BYTE $0x7F
1125         CALL _strayintr(SB); BYTE $0x80         /* Vector[A]PIC */
1126         CALL _strayintr(SB); BYTE $0x81
1127         CALL _strayintr(SB); BYTE $0x82
1128         CALL _strayintr(SB); BYTE $0x83
1129         CALL _strayintr(SB); BYTE $0x84
1130         CALL _strayintr(SB); BYTE $0x85
1131         CALL _strayintr(SB); BYTE $0x86
1132         CALL _strayintr(SB); BYTE $0x87
1133         CALL _strayintr(SB); BYTE $0x88
1134         CALL _strayintr(SB); BYTE $0x89
1135         CALL _strayintr(SB); BYTE $0x8A
1136         CALL _strayintr(SB); BYTE $0x8B
1137         CALL _strayintr(SB); BYTE $0x8C
1138         CALL _strayintr(SB); BYTE $0x8D
1139         CALL _strayintr(SB); BYTE $0x8E
1140         CALL _strayintr(SB); BYTE $0x8F
1141         CALL _strayintr(SB); BYTE $0x90
1142         CALL _strayintr(SB); BYTE $0x91
1143         CALL _strayintr(SB); BYTE $0x92
1144         CALL _strayintr(SB); BYTE $0x93
1145         CALL _strayintr(SB); BYTE $0x94
1146         CALL _strayintr(SB); BYTE $0x95
1147         CALL _strayintr(SB); BYTE $0x96
1148         CALL _strayintr(SB); BYTE $0x97
1149         CALL _strayintr(SB); BYTE $0x98
1150         CALL _strayintr(SB); BYTE $0x99
1151         CALL _strayintr(SB); BYTE $0x9A
1152         CALL _strayintr(SB); BYTE $0x9B
1153         CALL _strayintr(SB); BYTE $0x9C
1154         CALL _strayintr(SB); BYTE $0x9D
1155         CALL _strayintr(SB); BYTE $0x9E
1156         CALL _strayintr(SB); BYTE $0x9F
1157         CALL _strayintr(SB); BYTE $0xA0
1158         CALL _strayintr(SB); BYTE $0xA1
1159         CALL _strayintr(SB); BYTE $0xA2
1160         CALL _strayintr(SB); BYTE $0xA3
1161         CALL _strayintr(SB); BYTE $0xA4
1162         CALL _strayintr(SB); BYTE $0xA5
1163         CALL _strayintr(SB); BYTE $0xA6
1164         CALL _strayintr(SB); BYTE $0xA7
1165         CALL _strayintr(SB); BYTE $0xA8
1166         CALL _strayintr(SB); BYTE $0xA9
1167         CALL _strayintr(SB); BYTE $0xAA
1168         CALL _strayintr(SB); BYTE $0xAB
1169         CALL _strayintr(SB); BYTE $0xAC
1170         CALL _strayintr(SB); BYTE $0xAD
1171         CALL _strayintr(SB); BYTE $0xAE
1172         CALL _strayintr(SB); BYTE $0xAF
1173         CALL _strayintr(SB); BYTE $0xB0
1174         CALL _strayintr(SB); BYTE $0xB1
1175         CALL _strayintr(SB); BYTE $0xB2
1176         CALL _strayintr(SB); BYTE $0xB3
1177         CALL _strayintr(SB); BYTE $0xB4
1178         CALL _strayintr(SB); BYTE $0xB5
1179         CALL _strayintr(SB); BYTE $0xB6
1180         CALL _strayintr(SB); BYTE $0xB7
1181         CALL _strayintr(SB); BYTE $0xB8
1182         CALL _strayintr(SB); BYTE $0xB9
1183         CALL _strayintr(SB); BYTE $0xBA
1184         CALL _strayintr(SB); BYTE $0xBB
1185         CALL _strayintr(SB); BYTE $0xBC
1186         CALL _strayintr(SB); BYTE $0xBD
1187         CALL _strayintr(SB); BYTE $0xBE
1188         CALL _strayintr(SB); BYTE $0xBF
1189         CALL _strayintr(SB); BYTE $0xC0
1190         CALL _strayintr(SB); BYTE $0xC1
1191         CALL _strayintr(SB); BYTE $0xC2
1192         CALL _strayintr(SB); BYTE $0xC3
1193         CALL _strayintr(SB); BYTE $0xC4
1194         CALL _strayintr(SB); BYTE $0xC5
1195         CALL _strayintr(SB); BYTE $0xC6
1196         CALL _strayintr(SB); BYTE $0xC7
1197         CALL _strayintr(SB); BYTE $0xC8
1198         CALL _strayintr(SB); BYTE $0xC9
1199         CALL _strayintr(SB); BYTE $0xCA
1200         CALL _strayintr(SB); BYTE $0xCB
1201         CALL _strayintr(SB); BYTE $0xCC
1202         CALL _strayintr(SB); BYTE $0xCD
1203         CALL _strayintr(SB); BYTE $0xCE
1204         CALL _strayintr(SB); BYTE $0xCF
1205         CALL _strayintr(SB); BYTE $0xD0
1206         CALL _strayintr(SB); BYTE $0xD1
1207         CALL _strayintr(SB); BYTE $0xD2
1208         CALL _strayintr(SB); BYTE $0xD3
1209         CALL _strayintr(SB); BYTE $0xD4
1210         CALL _strayintr(SB); BYTE $0xD5
1211         CALL _strayintr(SB); BYTE $0xD6
1212         CALL _strayintr(SB); BYTE $0xD7
1213         CALL _strayintr(SB); BYTE $0xD8
1214         CALL _strayintr(SB); BYTE $0xD9
1215         CALL _strayintr(SB); BYTE $0xDA
1216         CALL _strayintr(SB); BYTE $0xDB
1217         CALL _strayintr(SB); BYTE $0xDC
1218         CALL _strayintr(SB); BYTE $0xDD
1219         CALL _strayintr(SB); BYTE $0xDE
1220         CALL _strayintr(SB); BYTE $0xDF
1221         CALL _strayintr(SB); BYTE $0xE0
1222         CALL _strayintr(SB); BYTE $0xE1
1223         CALL _strayintr(SB); BYTE $0xE2
1224         CALL _strayintr(SB); BYTE $0xE3
1225         CALL _strayintr(SB); BYTE $0xE4
1226         CALL _strayintr(SB); BYTE $0xE5
1227         CALL _strayintr(SB); BYTE $0xE6
1228         CALL _strayintr(SB); BYTE $0xE7
1229         CALL _strayintr(SB); BYTE $0xE8
1230         CALL _strayintr(SB); BYTE $0xE9
1231         CALL _strayintr(SB); BYTE $0xEA
1232         CALL _strayintr(SB); BYTE $0xEB
1233         CALL _strayintr(SB); BYTE $0xEC
1234         CALL _strayintr(SB); BYTE $0xED
1235         CALL _strayintr(SB); BYTE $0xEE
1236         CALL _strayintr(SB); BYTE $0xEF
1237         CALL _strayintr(SB); BYTE $0xF0
1238         CALL _strayintr(SB); BYTE $0xF1
1239         CALL _strayintr(SB); BYTE $0xF2
1240         CALL _strayintr(SB); BYTE $0xF3
1241         CALL _strayintr(SB); BYTE $0xF4
1242         CALL _strayintr(SB); BYTE $0xF5
1243         CALL _strayintr(SB); BYTE $0xF6
1244         CALL _strayintr(SB); BYTE $0xF7
1245         CALL _strayintr(SB); BYTE $0xF8
1246         CALL _strayintr(SB); BYTE $0xF9
1247         CALL _strayintr(SB); BYTE $0xFA
1248         CALL _strayintr(SB); BYTE $0xFB
1249         CALL _strayintr(SB); BYTE $0xFC
1250         CALL _strayintr(SB); BYTE $0xFD
1251         CALL _strayintr(SB); BYTE $0xFE
1252         CALL _strayintr(SB); BYTE $0xFF