]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/l.s
merge
[plan9front.git] / sys / src / 9 / pc / l.s
1 #include "mem.h"
2 #undef DELAY
3
4 #define PADDR(a)        ((a) & ~KZERO)
5 #define KADDR(a)        (KZERO|(a))
6
7 /*
8  * Some machine instructions not handled by 8[al].
9  */
10 #define OP16            BYTE $0x66
11 #define DELAY           BYTE $0xEB; BYTE $0x00  /* JMP .+2 */
12 #define CPUID           BYTE $0x0F; BYTE $0xA2  /* CPUID, argument in AX */
13 #define WRMSR           BYTE $0x0F; BYTE $0x30  /* WRMSR, argument in AX/DX (lo/hi) */
14 #define RDTSC           BYTE $0x0F; BYTE $0x31  /* RDTSC, result in AX/DX (lo/hi) */
15 #define RDMSR           BYTE $0x0F; BYTE $0x32  /* RDMSR, result in AX/DX (lo/hi) */
16 #define HLT             BYTE $0xF4
17 #define INVLPG  BYTE $0x0F; BYTE $0x01; BYTE $0x39      /* INVLPG (%ecx) */
18 #define WBINVD  BYTE $0x0F; BYTE $0x09
19
20 #define VectorSYSCALL   0x40
21
22 /*
23  * Macros for calculating offsets within the page directory base
24  * and page tables. Note that these are assembler-specific hence
25  * the '<<2'.
26  */
27 #define PDO(a)          (((((a))>>22) & 0x03FF)<<2)
28 #define PTO(a)          (((((a))>>12) & 0x03FF)<<2)
29
30 /*
31  * For backwards compatiblity with 9load - should go away when 9load is changed
32  * 9load currently sets up the mmu, however the first 16MB of memory is identity
33  * mapped, so behave as if the mmu was not setup
34  */
35 TEXT _startKADDR(SB), $0
36         MOVL    $_startPADDR(SB), AX
37         ANDL    $~KZERO, AX
38         JMP*    AX
39
40 /*
41  * Must be 4-byte aligned.
42  */
43 TEXT _multibootheader(SB), $0
44         LONG    $0x1BADB002                     /* magic */
45         LONG    $0x00010007                     /* flags */
46         LONG    $-(0x1BADB002 + 0x00010007)     /* checksum */
47         LONG    $_multibootheader-KZERO(SB)     /* header_addr */
48         LONG    $_startKADDR-KZERO(SB)          /* load_addr */
49         LONG    $edata-KZERO(SB)                /* load_end_addr */
50         LONG    $end-KZERO(SB)                  /* bss_end_addr */
51         LONG    $_multibootentry-KZERO(SB)              /* entry_addr */
52         LONG    $0                              /* mode_type */
53         LONG    $0                              /* width */
54         LONG    $0                              /* height */
55         LONG    $32                             /* depth */
56
57 /* 
58  * the kernel expects the data segment to be page-aligned
59  * multiboot bootloaders put the data segment right behind text
60  */
61 TEXT _multibootentry(SB), $0
62         MOVL    $etext-KZERO(SB), SI
63         MOVL    SI, DI
64         ADDL    $0xfff, DI
65         ANDL    $~0xfff, DI
66         MOVL    $edata-KZERO(SB), CX
67         SUBL    DI, CX
68         ADDL    CX, SI
69         ADDL    CX, DI
70         INCL    CX      /* one more for post decrement */
71         STD
72         REP; MOVSB
73         MOVL    BX, multibootptr-KZERO(SB)
74         MOVL    $_startPADDR(SB), AX
75         ANDL    $~KZERO, AX
76         JMP*    AX
77
78 /* multiboot structure pointer (physical address) */
79 TEXT multibootptr(SB), $0
80         LONG    $0
81
82 /*
83  * In protected mode with paging turned off and segment registers setup
84  * to linear map all memory. Entered via a jump to PADDR(entry),
85  * the physical address of the virtual kernel entry point of KADDR(entry).
86  * Make the basic page tables for processor 0. Six pages are needed for
87  * the basic set:
88  *      a page directory;
89  *      page tables for mapping the first 8MB of physical memory to KZERO;
90  *      a page for the GDT;
91  *      virtual and physical pages for mapping the Mach structure.
92  * The remaining PTEs will be allocated later when memory is sized.
93  * An identity mmu map is also needed for the switch to virtual mode.
94  * This identity mapping is removed once the MMU is going and the JMP has
95  * been made to virtual memory.
96  */
97 TEXT _startPADDR(SB), $0
98         CLI                                     /* make sure interrupts are off */
99
100         /* set up the gdt so we have sane plan 9 style gdts. */
101         MOVL    $tgdtptr(SB), AX
102         ANDL    $~KZERO, AX
103         MOVL    (AX), GDTR
104         MOVW    $1, AX
105         MOVW    AX, MSW
106
107         /* clear prefetch queue (weird code to avoid optimizations) */
108         DELAY
109
110         /* set segs to something sane (avoid traps later) */
111         MOVW    $(1<<3), AX
112         MOVW    AX, DS
113         MOVW    AX, SS
114         MOVW    AX, ES
115         MOVW    AX, FS
116         MOVW    AX, GS
117
118 /*      JMP     $(2<<3):$mode32bit(SB) /**/
119          BYTE   $0xEA
120          LONG   $mode32bit-KZERO(SB)
121          WORD   $(2<<3)
122
123 /*
124  *  gdt to get us to 32-bit/segmented/unpaged mode
125  */
126 TEXT tgdt(SB), $0
127
128         /* null descriptor */
129         LONG    $0
130         LONG    $0
131
132         /* data segment descriptor for 4 gigabytes (PL 0) */
133         LONG    $(0xFFFF)
134         LONG    $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW)
135
136         /* exec segment descriptor for 4 gigabytes (PL 0) */
137         LONG    $(0xFFFF)
138         LONG    $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
139
140 /*
141  *  pointer to initial gdt
142  *  Note the -KZERO which puts the physical address in the gdtptr. 
143  *  that's needed as we start executing in physical addresses. 
144  */
145 TEXT tgdtptr(SB), $0
146         WORD    $(3*8)
147         LONG    $tgdt-KZERO(SB)
148
149 TEXT m0rgdtptr(SB), $0
150         WORD    $(NGDT*8-1)
151         LONG    $(CPU0GDT-KZERO)
152
153 TEXT m0gdtptr(SB), $0
154         WORD    $(NGDT*8-1)
155         LONG    $CPU0GDT
156
157 TEXT m0idtptr(SB), $0
158         WORD $(256*8-1)
159         LONG $IDTADDR
160
161 TEXT mode32bit(SB), $0
162         /* At this point, the GDT setup is done. */
163
164         MOVL    $((CPU0END-CPU0PDB)>>2), CX
165         MOVL    $PADDR(CPU0PDB), DI
166         XORL    AX, AX
167
168         CLD
169         REP;    STOSL
170
171         MOVL    $PADDR(CPU0PTE), DX
172         MOVL    $(PTEWRITE|PTEVALID), BX        /* page permissions */
173         ORL     BX, DX
174
175         MOVL    $PADDR(CPU0PDB), AX
176         ADDL    $PDO(KZERO), AX                 /* page directory offset for KZERO */
177
178         MOVL    DX, 0(AX)                       /* PTE's for KZERO */
179         ADDL    $BY2PG, DX
180         MOVL    DX, 4(AX)                       /* PTE's for KZERO+4MB */
181         ADDL    $BY2PG, DX
182         MOVL    DX, 8(AX)                       /* PTE's for KZERO+8MB */
183         ADDL    $BY2PG, DX
184         MOVL    DX, 12(AX)                      /* PTE's for KZERO+12MB */
185
186         MOVL    $PADDR(CPU0PTE), AX             /* first page of page table */
187         MOVL    $end-KZERO(SB), CX
188
189         ADDL    $(16*1024), CX                  /* qemu puts multiboot data after the kernel */
190
191         ADDL    $(BY2XPG-1), CX
192         ANDL    $~(BY2XPG-1), CX                /* round to 4MB */
193         MOVL    CX, MemMin-KZERO(SB)            /* see memory.c */
194         SHRL    $PGSHIFT, CX
195         MOVL    BX, DX
196 _setpte:
197         MOVL    DX, (AX)
198         ADDL    $BY2PG, DX
199         ADDL    $4, AX
200         LOOP    _setpte
201
202         MOVL    $PADDR(CPU0PTE), AX
203         ADDL    $PTO(MACHADDR), AX              /* page table entry offset for MACHADDR */
204         ORL     $PADDR(CPU0MACH), BX
205         MOVL    BX, (AX)                        /* PTE for Mach */
206
207 /*
208  * Now ready to use the new map. Make sure the processor options are what is wanted.
209  * It is necessary on some processors to immediately follow mode switching with a JMP instruction
210  * to clear the prefetch queues.
211  */
212         MOVL    $PADDR(CPU0PDB), CX             /* load address of page directory */
213         MOVL    (PDO(KZERO))(CX), DX            /* double-map KZERO at 0 */
214         MOVL    DX, (PDO(0))(CX)
215         MOVL    CX, CR3
216         DELAY                                   /* JMP .+2 */
217
218         MOVL    CR0, DX
219         ORL     $0x80010000, DX                 /* PG|WP */
220         ANDL    $~0x6000000A, DX                /* ~(CD|NW|TS|MP) */
221
222         MOVL    $_startpg(SB), AX               /* this is a virtual address */
223         MOVL    DX, CR0                         /* turn on paging */
224         JMP*    AX                              /* jump to the virtual nirvana */
225
226 /*
227  * Basic machine environment set, can clear BSS and create a stack.
228  * The stack starts at the top of the page containing the Mach structure.
229  * The x86 architecture forces the use of the same virtual address for
230  * each processor's Mach structure, so the global Mach pointer 'm' can
231  * be initialised here.
232  */
233 TEXT _startpg(SB), $0
234         MOVL    $0, (PDO(0))(CX)                /* undo double-map of KZERO at 0 */
235         MOVL    CX, CR3                         /* load and flush the mmu */
236
237 _clearbss:
238         MOVL    $edata(SB), DI
239         XORL    AX, AX
240         MOVL    $end(SB), CX
241         SUBL    DI, CX                          /* end-edata bytes */
242         SHRL    $2, CX                          /* end-edata doublewords */
243
244         CLD
245         REP;    STOSL                           /* clear BSS */
246
247         MOVL    $MACHADDR, SP
248         MOVL    SP, m(SB)                       /* initialise global Mach pointer */
249         MOVL    $0, 0(SP)                       /* initialise m->machno */
250
251
252         ADDL    $(MACHSIZE-4), SP               /* initialise stack */
253
254 /*
255  * Need to do one final thing to ensure a clean machine environment,
256  * clear the EFLAGS register, which can only be done once there is a stack.
257  */
258         MOVL    $0, AX
259         PUSHL   AX
260         POPFL
261
262         CALL    main(SB)
263
264 /*
265  * Park a processor. Should never fall through a return from main to here,
266  * should only be called by application processors when shutting down.
267  */
268 TEXT idle(SB), $0
269 _idle:
270         STI
271         HLT
272         JMP     _idle
273
274
275 TEXT load_fs(SB), $0
276         MOVW fs+0(FP), AX
277         MOVW AX, FS
278         RET
279
280 TEXT load_gs(SB), $0
281         MOVW gs+0(FP), AX
282         MOVW AX, GS
283         RET
284
285 /*
286  * BIOS32.
287  */
288 TEXT bios32call(SB), $0
289         MOVL    ci+0(FP), BP
290         MOVL    0(BP), AX
291         MOVL    4(BP), BX
292         MOVL    8(BP), CX
293         MOVL    12(BP), DX
294         MOVL    16(BP), SI
295         MOVL    20(BP), DI
296         PUSHL   BP
297
298         MOVL    12(SP), BP                      /* ptr */
299         BYTE $0xFF; BYTE $0x5D; BYTE $0x00      /* CALL FAR 0(BP) */
300
301         POPL    BP
302         MOVL    DI, 20(BP)
303         MOVL    SI, 16(BP)
304         MOVL    DX, 12(BP)
305         MOVL    CX, 8(BP)
306         MOVL    BX, 4(BP)
307         MOVL    AX, 0(BP)
308
309         XORL    AX, AX
310         JCC     _bios32xxret
311         INCL    AX
312
313 _bios32xxret:
314         RET
315
316 /*
317  * Port I/O.
318  *      in[bsl]         input a byte|short|long
319  *      ins[bsl]        input a string of bytes|shorts|longs
320  *      out[bsl]        output a byte|short|long
321  *      outs[bsl]       output a string of bytes|shorts|longs
322  */
323 TEXT inb(SB), $0
324         MOVL    port+0(FP), DX
325         XORL    AX, AX
326         INB
327         RET
328
329 TEXT insb(SB), $0
330         MOVL    port+0(FP), DX
331         MOVL    address+4(FP), DI
332         MOVL    count+8(FP), CX
333         CLD
334         REP;    INSB
335         RET
336
337 TEXT ins(SB), $0
338         MOVL    port+0(FP), DX
339         XORL    AX, AX
340         OP16;   INL
341         RET
342
343 TEXT inss(SB), $0
344         MOVL    port+0(FP), DX
345         MOVL    address+4(FP), DI
346         MOVL    count+8(FP), CX
347         CLD
348         REP;    OP16; INSL
349         RET
350
351 TEXT inl(SB), $0
352         MOVL    port+0(FP), DX
353         INL
354         RET
355
356 TEXT insl(SB), $0
357         MOVL    port+0(FP), DX
358         MOVL    address+4(FP), DI
359         MOVL    count+8(FP), CX
360         CLD
361         REP;    INSL
362         RET
363
364 TEXT outb(SB), $0
365         MOVL    port+0(FP), DX
366         MOVL    byte+4(FP), AX
367         OUTB
368         RET
369
370 TEXT outsb(SB), $0
371         MOVL    port+0(FP), DX
372         MOVL    address+4(FP), SI
373         MOVL    count+8(FP), CX
374         CLD
375         REP;    OUTSB
376         RET
377
378 TEXT outs(SB), $0
379         MOVL    port+0(FP), DX
380         MOVL    short+4(FP), AX
381         OP16;   OUTL
382         RET
383
384 TEXT outss(SB), $0
385         MOVL    port+0(FP), DX
386         MOVL    address+4(FP), SI
387         MOVL    count+8(FP), CX
388         CLD
389         REP;    OP16; OUTSL
390         RET
391
392 TEXT outl(SB), $0
393         MOVL    port+0(FP), DX
394         MOVL    long+4(FP), AX
395         OUTL
396         RET
397
398 TEXT outsl(SB), $0
399         MOVL    port+0(FP), DX
400         MOVL    address+4(FP), SI
401         MOVL    count+8(FP), CX
402         CLD
403         REP;    OUTSL
404         RET
405
406 /*
407  * Read/write various system registers.
408  * CR4 and the 'model specific registers' should only be read/written
409  * after it has been determined the processor supports them
410  */
411 TEXT lgdt(SB), $0                               /* GDTR - global descriptor table */
412         MOVL    gdtptr+0(FP), AX
413         MOVL    (AX), GDTR
414         RET
415
416 TEXT lldt(SB), $0                               /* LDTR - local descriptor table */
417         MOVL    sel+0(FP), AX
418         BYTE $0x0F; BYTE $0x00; BYTE $0xD0      /* LLDT AX */
419         RET
420
421 TEXT lidt(SB), $0                               /* IDTR - interrupt descriptor table */
422         MOVL    idtptr+0(FP), AX
423         MOVL    (AX), IDTR
424         RET
425
426 TEXT ltr(SB), $0                                /* TR - task register */
427         MOVL    tptr+0(FP), AX
428         MOVW    AX, TASK
429         RET
430
431 TEXT getcr0(SB), $0                             /* CR0 - processor control */
432         MOVL    CR0, AX
433         RET
434
435 TEXT getcr2(SB), $0                             /* CR2 - page fault linear address */
436         MOVL    CR2, AX
437         RET
438
439 TEXT putcr2(SB), $0
440         MOVL    cr2+0(FP), AX
441         MOVL    AX, CR2
442         RET
443
444 TEXT getcr3(SB), $0                             /* CR3 - page directory base */
445         MOVL    CR3, AX
446         RET
447
448 TEXT putcr0(SB), $0
449         MOVL    cr0+0(FP), AX
450         MOVL    AX, CR0
451         RET
452
453 TEXT putcr3(SB), $0
454         MOVL    cr3+0(FP), AX
455         MOVL    AX, CR3
456         RET
457
458 TEXT getcr4(SB), $0                             /* CR4 - extensions */
459         MOVL    CR4, AX
460         RET
461
462 TEXT putcr4(SB), $0
463         MOVL    cr4+0(FP), AX
464         MOVL    AX, CR4
465         RET
466
467 TEXT invlpg(SB), $0
468         /* 486+ only */
469         MOVL    va+0(FP), CX
470         INVLPG
471         RET
472
473 TEXT wbinvd(SB), $0
474         WBINVD
475         RET
476
477 TEXT _cycles(SB), $0                            /* time stamp counter */
478         RDTSC
479         MOVL    vlong+0(FP), CX                 /* &vlong */
480         MOVL    AX, 0(CX)                       /* lo */
481         MOVL    DX, 4(CX)                       /* hi */
482         RET
483
484 /*
485  * stub for:
486  * time stamp counter; low-order 32 bits of 64-bit cycle counter
487  * Runs at fasthz/4 cycles per second (m->clkin>>3)
488  */
489 TEXT lcycles(SB),1,$0
490         RDTSC
491         RET
492
493 TEXT rdmsr(SB), $0                              /* model-specific register */
494         MOVL    $0, BP
495         MOVL    index+0(FP), CX
496 TEXT _rdmsrinst(SB), $0
497         RDMSR
498         MOVL    vlong+4(FP), CX                 /* &vlong */
499         MOVL    AX, 0(CX)                       /* lo */
500         MOVL    DX, 4(CX)                       /* hi */
501         MOVL    BP, AX                          /* BP set to -1 if traped */
502         RET
503         
504 TEXT wrmsr(SB), $0
505         MOVL    $0, BP
506         MOVL    index+0(FP), CX
507         MOVL    lo+4(FP), AX
508         MOVL    hi+8(FP), DX
509 TEXT _wrmsrinst(SB), $0
510         WRMSR
511         MOVL    BP, AX                          /* BP set to -1 if traped */
512         RET
513
514 /*
515  * Try to determine the CPU type which requires fiddling with EFLAGS.
516  * If the Id bit can be toggled then the CPUID instruction can be used
517  * to determine CPU identity and features. First have to check if it's
518  * a 386 (Ac bit can't be set). If it's not a 386 and the Id bit can't be
519  * toggled then it's an older 486 of some kind.
520  *
521  *      cpuid(fun, regs[4]);
522  */
523 TEXT cpuid(SB), $0
524         MOVL    $0x240000, AX
525         PUSHL   AX
526         POPFL                                   /* set Id|Ac */
527         PUSHFL
528         POPL    BX                              /* retrieve value */
529         MOVL    $0, AX
530         PUSHL   AX
531         POPFL                                   /* clear Id|Ac, EFLAGS initialised */
532         PUSHFL
533         POPL    AX                              /* retrieve value */
534         XORL    BX, AX
535         TESTL   $0x040000, AX                   /* Ac */
536         JZ      _cpu386                         /* can't set this bit on 386 */
537         TESTL   $0x200000, AX                   /* Id */
538         JZ      _cpu486                         /* can't toggle this bit on some 486 */
539         MOVL    fn+0(FP), AX
540         CPUID
541         JMP     _cpuid
542 _cpu486:
543         MOVL    $0x400, AX
544         JMP     _maybezapax
545 _cpu386:
546         MOVL    $0x300, AX
547 _maybezapax:
548         CMPL    fn+0(FP), $1
549         JE      _zaprest
550         XORL    AX, AX
551 _zaprest:
552         XORL    BX, BX
553         XORL    CX, CX
554         XORL    DX, DX
555 _cpuid:
556         MOVL    regs+4(FP), BP
557         MOVL    AX, 0(BP)
558         MOVL    BX, 4(BP)
559         MOVL    CX, 8(BP)
560         MOVL    DX, 12(BP)
561         RET
562
563 /*
564  * Basic timing loop to determine CPU frequency.
565  */
566 TEXT aamloop(SB), $0
567         MOVL    count+0(FP), CX
568 _aamloop:
569         AAM
570         LOOP    _aamloop
571         RET
572
573 /*
574  * Floating point.
575  * Note: the encodings for the FCLEX, FINIT, FSAVE, FSTCW, FSENV and FSTSW
576  * instructions do NOT have the WAIT prefix byte (i.e. they act like their
577  * FNxxx variations) so WAIT instructions must be explicitly placed in the
578  * code as necessary.
579  */
580 #define FPOFF                                                    ;\
581         MOVL    CR0, AX                                          ;\
582         ORL     $0x28, AX                       /* NE=1, TS=1 */ ;\
583         MOVL    AX, CR0
584
585 #define FPON                                                     ;\
586         MOVL    CR0, AX                                          ;\
587         ANDL    $~0xC, AX                       /* EM=0, TS=0 */ ;\
588         MOVL    AX, CR0
589
590 TEXT fpoff(SB), $0                              /* disable */
591         FPOFF
592         RET
593
594 TEXT fpinit(SB), $0                             /* enable and init */
595         FPON
596         FINIT
597         WAIT
598         /* setfcr(FPPDBL|FPRNR|FPINVAL|FPZDIV|FPOVFL) */
599         /* note that low 6 bits are masks, not enables, on this chip */
600         PUSHW   $0x0232
601         FLDCW   0(SP)
602         POPW    AX
603         WAIT
604         RET
605
606 TEXT fpx87save0(SB), $0                         /* save state and disable */
607         MOVL    p+0(FP), AX
608         FSAVE   0(AX)                           /* no WAIT */
609         FPOFF
610         RET
611
612 TEXT fpx87restore0(SB), $0                      /* enable and restore state */
613         FPON
614         MOVL    p+0(FP), AX
615         FRSTOR  0(AX)
616         WAIT
617         RET
618
619 TEXT fpclear(SB), $0                            /* clear pending exceptions */
620         FPON
621         FCLEX                                   /* no WAIT */
622         FPOFF
623         RET
624
625 TEXT fpssesave(SB), $0                          /* save state and disable */
626         MOVL    p+0(FP), AX
627         FXSAVE  0(AX)                           /* no WAIT */
628         FPOFF
629         RET
630
631 TEXT fpsserestore(SB), $0                       /* enable and restore state */
632         FPON
633         MOVL    p+0(FP), AX
634         FXRSTOR 0(AX)
635         WAIT
636         RET
637
638 TEXT ldmxcsr(SB), $0                            /* Load MXCSR */
639         LDMXCSR mxcsr+0(FP)
640         RET
641
642 /*
643  */
644 TEXT splhi(SB), $0
645 shi:
646         PUSHFL
647         POPL    AX
648         TESTL   $0x200, AX
649         JZ      alreadyhi
650         MOVL    $(MACHADDR+0x04), CX            /* save PC in m->splpc */
651         MOVL    (SP), BX
652         MOVL    BX, (CX)
653 alreadyhi:
654         CLI
655         RET
656
657 TEXT spllo(SB), $0
658 slo:
659         PUSHFL
660         POPL    AX
661         TESTL   $0x200, AX
662         JNZ     alreadylo
663         MOVL    $(MACHADDR+0x04), CX            /* clear m->splpc */
664         MOVL    $0, (CX)
665 alreadylo:
666         STI
667         RET
668
669 TEXT splx(SB), $0
670         MOVL    s+0(FP), AX
671         TESTL   $0x200, AX
672         JNZ     slo
673         JMP     shi
674
675 TEXT spldone(SB), $0
676         RET
677
678 TEXT islo(SB), $0
679         PUSHFL
680         POPL    AX
681         ANDL    $0x200, AX                      /* interrupt enable flag */
682         RET
683
684 /*
685  * Test-And-Set
686  */
687 TEXT tas(SB), $0
688 TEXT _tas(SB), $0
689         MOVL    $0xDEADDEAD, AX
690         MOVL    lock+0(FP), BX
691         XCHGL   AX, (BX)                        /* lock->key */
692         RET
693
694 TEXT mb386(SB), $0
695         POPL    AX                              /* return PC */
696         PUSHFL
697         PUSHL   CS
698         PUSHL   AX
699         IRETL
700
701 TEXT mb586(SB), $0
702         XORL    AX, AX
703         CPUID
704         RET
705
706 TEXT sfence(SB), $0
707         BYTE $0x0f
708         BYTE $0xae
709         BYTE $0xf8
710         RET
711
712 TEXT lfence(SB), $0
713         BYTE $0x0f
714         BYTE $0xae
715         BYTE $0xe8
716         RET
717
718 TEXT mfence(SB), $0
719         BYTE $0x0f
720         BYTE $0xae
721         BYTE $0xf0
722         RET
723
724 TEXT xchgw(SB), $0
725         MOVL    v+4(FP), AX
726         MOVL    p+0(FP), BX
727         XCHGW   AX, (BX)
728         RET
729
730 TEXT cmpswap486(SB), $0
731         MOVL    addr+0(FP), BX
732         MOVL    old+4(FP), AX
733         MOVL    new+8(FP), CX
734         LOCK
735         BYTE $0x0F; BYTE $0xB1; BYTE $0x0B      /* CMPXCHGL CX, (BX) */
736         JNZ didnt
737         MOVL    $1, AX
738         RET
739 didnt:
740         XORL    AX,AX
741         RET
742
743 TEXT mul64fract(SB), $0
744 /*
745  * Multiply two 64-bit number s and keep the middle 64 bits from the 128-bit result
746  * See ../port/tod.c for motivation.
747  */
748         MOVL    r+0(FP), CX
749         XORL    BX, BX                          /* BX = 0 */
750
751         MOVL    a+8(FP), AX
752         MULL    b+16(FP)                        /* a1*b1 */
753         MOVL    AX, 4(CX)                       /* r2 = lo(a1*b1) */
754
755         MOVL    a+8(FP), AX
756         MULL    b+12(FP)                        /* a1*b0 */
757         MOVL    AX, 0(CX)                       /* r1 = lo(a1*b0) */
758         ADDL    DX, 4(CX)                       /* r2 += hi(a1*b0) */
759
760         MOVL    a+4(FP), AX
761         MULL    b+16(FP)                        /* a0*b1 */
762         ADDL    AX, 0(CX)                       /* r1 += lo(a0*b1) */
763         ADCL    DX, 4(CX)                       /* r2 += hi(a0*b1) + carry */
764
765         MOVL    a+4(FP), AX
766         MULL    b+12(FP)                        /* a0*b0 */
767         ADDL    DX, 0(CX)                       /* r1 += hi(a0*b0) */
768         ADCL    BX, 4(CX)                       /* r2 += carry */
769         RET
770
771 /*
772  *  label consists of a stack pointer and a PC
773  */
774 TEXT gotolabel(SB), $0
775         MOVL    label+0(FP), AX
776         MOVL    0(AX), SP                       /* restore sp */
777         MOVL    4(AX), AX                       /* put return pc on the stack */
778         MOVL    AX, 0(SP)
779         MOVL    $1, AX                          /* return 1 */
780         RET
781
782 TEXT setlabel(SB), $0
783         MOVL    label+0(FP), AX
784         MOVL    SP, 0(AX)                       /* store sp */
785         MOVL    0(SP), BX                       /* store return pc */
786         MOVL    BX, 4(AX)
787         MOVL    $0, AX                          /* return 0 */
788         RET
789
790 /*
791  * Attempt at power saving. -rsc
792  */
793 TEXT halt(SB), $0
794         CLI
795         CMPL    nrdy(SB), $0
796         JEQ     _nothingready
797         STI
798         RET
799
800 _nothingready:
801         STI
802         HLT
803         RET
804
805 TEXT mwait(SB), $0
806         MOVL    addr+0(FP), AX
807         MOVL    (AX), CX
808         ORL     CX, CX
809         JNZ     _mwaitdone
810         XORL    DX, DX
811         BYTE $0x0f; BYTE $0x01; BYTE $0xc8      /* MONITOR */
812         MOVL    (AX), CX
813         ORL     CX, CX
814         JNZ     _mwaitdone
815         XORL    AX, AX
816         BYTE $0x0f; BYTE $0x01; BYTE $0xc9      /* MWAIT */
817 _mwaitdone:
818         RET
819
820 #define RDRANDAX        BYTE $0x0f; BYTE $0xc7; BYTE $0xf0
821
822 TEXT rdrand32(SB), $-4
823 _rloop32:
824         RDRANDAX
825         JCC     _rloop32
826         RET
827
828 TEXT rdrandbuf(SB), $0
829         MOVL    buf+0(FP), DI
830         MOVL    cnt+4(FP), CX
831         CLD
832         MOVL    CX, DX
833         SHRL    $2, CX
834         CMPL    CX, $0
835         JE      _rndleft
836 _rnddwords:
837         CALL    rdrand32(SB)
838         STOSL
839         LOOP _rnddwords
840 _rndleft:
841         MOVL    DX, CX
842         ANDL    $3, CX
843         CMPL    CX, $0
844         JE      _rnddone
845 _rndbytes:
846         CALL rdrand32(SB)
847         STOSB
848         LOOP _rndbytes
849 _rnddone:
850         RET
851
852 /* debug register access */
853
854 TEXT putdr(SB), $0
855         MOVL    p+0(FP), SI
856         MOVL    28(SI), AX
857         MOVL    AX, DR7
858 _putdr01236:
859         MOVL    0(SI), AX
860         MOVL    AX, DR0
861         MOVL    4(SI), AX
862         MOVL    AX, DR1
863         MOVL    8(SI), AX
864         MOVL    AX, DR2
865         MOVL    12(SI), AX
866         MOVL    AX, DR3
867         MOVL    24(SI), AX
868         MOVL    AX, DR6
869         RET
870
871 TEXT putdr01236(SB), $0
872         MOVL p+0(FP), SI
873         JMP _putdr01236
874
875 TEXT getdr6(SB), $0
876         MOVL    DR6, AX
877         RET
878
879 TEXT putdr6(SB), $0
880         MOVL    p+0(FP), AX
881         MOVL    AX, DR6
882         RET
883         
884 TEXT putdr7(SB), $0
885         MOVL    p+0(FP), AX
886         MOVL    AX, DR7
887         RET
888
889 /* VMX instructions */
890 TEXT vmxon(SB), $0
891         /* VMXON 4(SP) */
892         BYTE    $0xf3; BYTE $0x0f; BYTE $0xc7; BYTE $0x74; BYTE $0x24; BYTE $0x04
893         JMP     _vmout
894
895 TEXT vmxoff(SB), $0
896         BYTE    $0x0f; BYTE $0x01; BYTE $0xc4
897         JMP     _vmout
898
899 TEXT vmclear(SB), $0
900         /* VMCLEAR 4(SP) */
901         BYTE    $0x66; BYTE $0x0f; BYTE $0xc7; BYTE $0x74; BYTE $0x24; BYTE $0x04
902         JMP     _vmout
903
904 TEXT vmlaunch(SB), $0
905         MOVL    $0x6C14, DI
906         MOVL    SP, DX
907         BYTE    $0x0f; BYTE $0x79; BYTE $0xfa /* VMWRITE DX, DI */
908         JBE     _vmout
909         MOVL    $0x6C16, DI
910         MOVL    $vmrestore(SB), DX
911         BYTE    $0x0f; BYTE $0x79; BYTE $0xfa /* VMWRITE DX, DI */
912         JBE     _vmout
913         
914         MOVL    resume+4(FP), AX
915         TESTL   AX, AX
916         MOVL    ureg+0(FP), DI
917         MOVL    4(DI), SI
918         MOVL    8(DI), BP
919         MOVL    16(DI), BX
920         MOVL    20(DI), DX
921         MOVL    24(DI), CX
922         MOVL    28(DI), AX
923         MOVL    0(DI), DI
924         JNE     _vmresume
925         BYTE    $0x0f; BYTE $0x01; BYTE $0xc2 /* VMLAUNCH */
926         JMP     _vmout
927 _vmresume:
928         BYTE    $0x0f; BYTE $0x01; BYTE $0xc3 /* VMRESUME */
929         JMP _vmout
930
931 TEXT vmrestore(SB), $0
932         PUSHL   DI
933         MOVL    ureg+0(FP), DI
934         POPL    0(DI)
935         MOVL    SI, 4(DI)
936         MOVL    BP, 8(DI)
937         MOVL    BX, 16(DI)
938         MOVL    DX, 20(DI)
939         MOVL    CX, 24(DI)
940         MOVL    AX, 28(DI)
941         XORL    AX, AX
942         RET
943
944 TEXT vmptrld(SB), $0
945         /* VMPTRLD 4(SP) */
946         BYTE $0x0f; BYTE $0xc7; BYTE $0x74; BYTE $0x24; BYTE $0x04
947         JMP _vmout
948
949 TEXT vmwrite(SB), $0
950         MOVL addr+0(FP),DI
951         MOVL val+4(FP),DX
952         /* VMWRITE DX, DI */
953         BYTE $0x0f; BYTE $0x79; BYTE $0xfa
954         JMP _vmout
955
956 TEXT vmread(SB), $0
957         MOVL addr+0(FP),DI
958         MOVL valp+4(FP),SI
959         /* VMREAD (SI), DI */
960         BYTE $0x0f; BYTE $0x78; BYTE $0x3e
961         JMP _vmout
962
963 TEXT invept(SB), $0
964         MOVL type+0(FP), AX
965         /* INVEPT AX, 8(SP) */
966         BYTE $0x66; BYTE $0x0f; BYTE $0x38; BYTE $0x80; BYTE $0x44; BYTE $0x24; BYTE $0x08
967         JMP _vmout
968
969 TEXT invvpid(SB), $0
970         MOVL type+0(FP), AX
971         /* INVVPID AX, 8(SP) */
972         BYTE $0x66; BYTE $0x0f; BYTE $0x38; BYTE $0x81; BYTE $0x44; BYTE $0x24; BYTE $0x08
973         JMP _vmout
974
975 _vmout:
976         JC _vmout1
977         JZ _vmout2
978         XORL AX, AX
979         RET
980 _vmout1:
981         MOVL $-1, AX
982         RET
983 _vmout2:
984         MOVL $-2, AX
985         RET
986
987 /*
988  *  Used to get to the first process:
989  *      set up an interrupt return frame and IRET to user level.
990  */
991 TEXT touser(SB), $0
992         PUSHL   $(UDSEL)                        /* old ss */
993         MOVL    sp+0(FP), AX                    /* old sp */
994         PUSHL   AX
995         MOVL    $0x200, AX                      /* interrupt enable flag */
996         PUSHL   AX                              /* old flags */
997         PUSHL   $(UESEL)                        /* old cs */
998         PUSHL   $(UTZERO+32)                    /* old pc */
999         MOVL    $(UDSEL), AX
1000         MOVW    AX, DS
1001         MOVW    AX, ES
1002         MOVW    AX, GS
1003         MOVW    AX, FS
1004         IRETL
1005
1006 /*
1007  * Interrupt/exception handling.
1008  * Each entry in the vector table calls either _strayintr or _strayintrx depending
1009  * on whether an error code has been automatically pushed onto the stack
1010  * (_strayintrx) or not, in which case a dummy entry must be pushed before retrieving
1011  * the trap type from the vector table entry and placing it on the stack as part
1012  * of the Ureg structure.
1013  * The size of each entry in the vector table (6 bytes) is known in trapinit().
1014  */
1015 TEXT _strayintr(SB), $0
1016         PUSHL   AX                      /* save AX */
1017         MOVL    4(SP), AX               /* return PC from vectortable(SB) */
1018         JMP     intrcommon
1019
1020 TEXT _strayintrx(SB), $0
1021         XCHGL   AX, (SP)                /* swap AX with vectortable CALL PC */
1022 intrcommon:
1023         PUSHL   DS                      /* save DS */
1024         PUSHL   $(KDSEL)
1025         POPL    DS                      /* fix up DS */
1026         MOVBLZX (AX), AX                /* trap type -> AX */
1027         XCHGL   AX, 4(SP)               /* exchange trap type with saved AX */
1028
1029         PUSHL   ES                      /* save ES */
1030         PUSHL   $(KDSEL)
1031         POPL    ES                      /* fix up ES */
1032
1033         PUSHL   FS                      /* save the rest of the Ureg struct */
1034         PUSHL   GS
1035         PUSHAL
1036
1037         PUSHL   SP                      /* Ureg* argument to trap */
1038         CALL    trap(SB)
1039
1040 TEXT forkret(SB), $0
1041         POPL    AX
1042         POPAL
1043 TEXT _forkretpopgs(SB), $0
1044         POPL    GS
1045 TEXT _forkretpopfs(SB), $0
1046         POPL    FS
1047 TEXT _forkretpopes(SB), $0
1048         POPL    ES
1049 TEXT _forkretpopds(SB), $0
1050         POPL    DS
1051         ADDL    $8, SP                  /* pop error code and trap type */
1052 TEXT _forkretiret(SB), $0
1053         IRETL
1054
1055 /*
1056  * This is merely _strayintr optimised to vector
1057  * to syscall() without going through trap().
1058  */
1059 TEXT _syscallintr(SB), $0
1060         PUSHL   $VectorSYSCALL          /* trap type */
1061
1062         PUSHL   DS
1063         PUSHL   ES
1064         PUSHL   FS
1065         PUSHL   GS
1066         PUSHAL
1067         MOVL    $(KDSEL), AX
1068         MOVW    AX, DS
1069         MOVW    AX, ES
1070
1071         MOVL    $syscall(SB), AX
1072
1073         PUSHL   SP                      /* Ureg* argument to syscall */
1074         PUSHL   $forkret(SB)            /* return pc */
1075         JMP     *AX
1076
1077 TEXT vectortable(SB), $0
1078         CALL _strayintr(SB); BYTE $0x00         /* divide error */
1079         CALL _strayintr(SB); BYTE $0x01         /* debug exception */
1080         CALL _strayintr(SB); BYTE $0x02         /* NMI interrupt */
1081         CALL _strayintr(SB); BYTE $0x03         /* breakpoint */
1082         CALL _strayintr(SB); BYTE $0x04         /* overflow */
1083         CALL _strayintr(SB); BYTE $0x05         /* bound */
1084         CALL _strayintr(SB); BYTE $0x06         /* invalid opcode */
1085         CALL _strayintr(SB); BYTE $0x07         /* no coprocessor available */
1086         CALL _strayintrx(SB); BYTE $0x08        /* double fault */
1087         CALL _strayintr(SB); BYTE $0x09         /* coprocessor segment overflow */
1088         CALL _strayintrx(SB); BYTE $0x0A        /* invalid TSS */
1089         CALL _strayintrx(SB); BYTE $0x0B        /* segment not available */
1090         CALL _strayintrx(SB); BYTE $0x0C        /* stack exception */
1091         CALL _strayintrx(SB); BYTE $0x0D        /* general protection error */
1092         CALL _strayintrx(SB); BYTE $0x0E        /* page fault */
1093         CALL _strayintr(SB); BYTE $0x0F         /*  */
1094         CALL _strayintr(SB); BYTE $0x10         /* coprocessor error */
1095         CALL _strayintrx(SB); BYTE $0x11        /* alignment check */
1096         CALL _strayintr(SB); BYTE $0x12         /* machine check */
1097         CALL _strayintr(SB); BYTE $0x13         /* simd error */
1098         CALL _strayintr(SB); BYTE $0x14
1099         CALL _strayintr(SB); BYTE $0x15
1100         CALL _strayintr(SB); BYTE $0x16
1101         CALL _strayintr(SB); BYTE $0x17
1102         CALL _strayintr(SB); BYTE $0x18
1103         CALL _strayintr(SB); BYTE $0x19
1104         CALL _strayintr(SB); BYTE $0x1A
1105         CALL _strayintr(SB); BYTE $0x1B
1106         CALL _strayintr(SB); BYTE $0x1C
1107         CALL _strayintr(SB); BYTE $0x1D
1108         CALL _strayintr(SB); BYTE $0x1E
1109         CALL _strayintr(SB); BYTE $0x1F
1110         CALL _strayintr(SB); BYTE $0x20         /* VectorLAPIC */
1111         CALL _strayintr(SB); BYTE $0x21
1112         CALL _strayintr(SB); BYTE $0x22
1113         CALL _strayintr(SB); BYTE $0x23
1114         CALL _strayintr(SB); BYTE $0x24
1115         CALL _strayintr(SB); BYTE $0x25
1116         CALL _strayintr(SB); BYTE $0x26
1117         CALL _strayintr(SB); BYTE $0x27
1118         CALL _strayintr(SB); BYTE $0x28
1119         CALL _strayintr(SB); BYTE $0x29
1120         CALL _strayintr(SB); BYTE $0x2A
1121         CALL _strayintr(SB); BYTE $0x2B
1122         CALL _strayintr(SB); BYTE $0x2C
1123         CALL _strayintr(SB); BYTE $0x2D
1124         CALL _strayintr(SB); BYTE $0x2E
1125         CALL _strayintr(SB); BYTE $0x2F
1126         CALL _strayintr(SB); BYTE $0x30
1127         CALL _strayintr(SB); BYTE $0x31
1128         CALL _strayintr(SB); BYTE $0x32
1129         CALL _strayintr(SB); BYTE $0x33
1130         CALL _strayintr(SB); BYTE $0x34
1131         CALL _strayintr(SB); BYTE $0x35
1132         CALL _strayintr(SB); BYTE $0x36
1133         CALL _strayintr(SB); BYTE $0x37
1134         CALL _strayintr(SB); BYTE $0x38
1135         CALL _strayintr(SB); BYTE $0x39
1136         CALL _strayintr(SB); BYTE $0x3A
1137         CALL _strayintr(SB); BYTE $0x3B
1138         CALL _strayintr(SB); BYTE $0x3C
1139         CALL _strayintr(SB); BYTE $0x3D
1140         CALL _strayintr(SB); BYTE $0x3E
1141         CALL _strayintr(SB); BYTE $0x3F
1142         CALL _syscallintr(SB); BYTE $0x40       /* VectorSYSCALL */
1143         CALL _strayintr(SB); BYTE $0x41
1144         CALL _strayintr(SB); BYTE $0x42
1145         CALL _strayintr(SB); BYTE $0x43
1146         CALL _strayintr(SB); BYTE $0x44
1147         CALL _strayintr(SB); BYTE $0x45
1148         CALL _strayintr(SB); BYTE $0x46
1149         CALL _strayintr(SB); BYTE $0x47
1150         CALL _strayintr(SB); BYTE $0x48
1151         CALL _strayintr(SB); BYTE $0x49
1152         CALL _strayintr(SB); BYTE $0x4A
1153         CALL _strayintr(SB); BYTE $0x4B
1154         CALL _strayintr(SB); BYTE $0x4C
1155         CALL _strayintr(SB); BYTE $0x4D
1156         CALL _strayintr(SB); BYTE $0x4E
1157         CALL _strayintr(SB); BYTE $0x4F
1158         CALL _strayintr(SB); BYTE $0x50
1159         CALL _strayintr(SB); BYTE $0x51
1160         CALL _strayintr(SB); BYTE $0x52
1161         CALL _strayintr(SB); BYTE $0x53
1162         CALL _strayintr(SB); BYTE $0x54
1163         CALL _strayintr(SB); BYTE $0x55
1164         CALL _strayintr(SB); BYTE $0x56
1165         CALL _strayintr(SB); BYTE $0x57
1166         CALL _strayintr(SB); BYTE $0x58
1167         CALL _strayintr(SB); BYTE $0x59
1168         CALL _strayintr(SB); BYTE $0x5A
1169         CALL _strayintr(SB); BYTE $0x5B
1170         CALL _strayintr(SB); BYTE $0x5C
1171         CALL _strayintr(SB); BYTE $0x5D
1172         CALL _strayintr(SB); BYTE $0x5E
1173         CALL _strayintr(SB); BYTE $0x5F
1174         CALL _strayintr(SB); BYTE $0x60
1175         CALL _strayintr(SB); BYTE $0x61
1176         CALL _strayintr(SB); BYTE $0x62
1177         CALL _strayintr(SB); BYTE $0x63
1178         CALL _strayintr(SB); BYTE $0x64
1179         CALL _strayintr(SB); BYTE $0x65
1180         CALL _strayintr(SB); BYTE $0x66
1181         CALL _strayintr(SB); BYTE $0x67
1182         CALL _strayintr(SB); BYTE $0x68
1183         CALL _strayintr(SB); BYTE $0x69
1184         CALL _strayintr(SB); BYTE $0x6A
1185         CALL _strayintr(SB); BYTE $0x6B
1186         CALL _strayintr(SB); BYTE $0x6C
1187         CALL _strayintr(SB); BYTE $0x6D
1188         CALL _strayintr(SB); BYTE $0x6E
1189         CALL _strayintr(SB); BYTE $0x6F
1190         CALL _strayintr(SB); BYTE $0x70
1191         CALL _strayintr(SB); BYTE $0x71
1192         CALL _strayintr(SB); BYTE $0x72
1193         CALL _strayintr(SB); BYTE $0x73
1194         CALL _strayintr(SB); BYTE $0x74
1195         CALL _strayintr(SB); BYTE $0x75
1196         CALL _strayintr(SB); BYTE $0x76
1197         CALL _strayintr(SB); BYTE $0x77
1198         CALL _strayintr(SB); BYTE $0x78
1199         CALL _strayintr(SB); BYTE $0x79
1200         CALL _strayintr(SB); BYTE $0x7A
1201         CALL _strayintr(SB); BYTE $0x7B
1202         CALL _strayintr(SB); BYTE $0x7C
1203         CALL _strayintr(SB); BYTE $0x7D
1204         CALL _strayintr(SB); BYTE $0x7E
1205         CALL _strayintr(SB); BYTE $0x7F
1206         CALL _strayintr(SB); BYTE $0x80         /* Vector[A]PIC */
1207         CALL _strayintr(SB); BYTE $0x81
1208         CALL _strayintr(SB); BYTE $0x82
1209         CALL _strayintr(SB); BYTE $0x83
1210         CALL _strayintr(SB); BYTE $0x84
1211         CALL _strayintr(SB); BYTE $0x85
1212         CALL _strayintr(SB); BYTE $0x86
1213         CALL _strayintr(SB); BYTE $0x87
1214         CALL _strayintr(SB); BYTE $0x88
1215         CALL _strayintr(SB); BYTE $0x89
1216         CALL _strayintr(SB); BYTE $0x8A
1217         CALL _strayintr(SB); BYTE $0x8B
1218         CALL _strayintr(SB); BYTE $0x8C
1219         CALL _strayintr(SB); BYTE $0x8D
1220         CALL _strayintr(SB); BYTE $0x8E
1221         CALL _strayintr(SB); BYTE $0x8F
1222         CALL _strayintr(SB); BYTE $0x90
1223         CALL _strayintr(SB); BYTE $0x91
1224         CALL _strayintr(SB); BYTE $0x92
1225         CALL _strayintr(SB); BYTE $0x93
1226         CALL _strayintr(SB); BYTE $0x94
1227         CALL _strayintr(SB); BYTE $0x95
1228         CALL _strayintr(SB); BYTE $0x96
1229         CALL _strayintr(SB); BYTE $0x97
1230         CALL _strayintr(SB); BYTE $0x98
1231         CALL _strayintr(SB); BYTE $0x99
1232         CALL _strayintr(SB); BYTE $0x9A
1233         CALL _strayintr(SB); BYTE $0x9B
1234         CALL _strayintr(SB); BYTE $0x9C
1235         CALL _strayintr(SB); BYTE $0x9D
1236         CALL _strayintr(SB); BYTE $0x9E
1237         CALL _strayintr(SB); BYTE $0x9F
1238         CALL _strayintr(SB); BYTE $0xA0
1239         CALL _strayintr(SB); BYTE $0xA1
1240         CALL _strayintr(SB); BYTE $0xA2
1241         CALL _strayintr(SB); BYTE $0xA3
1242         CALL _strayintr(SB); BYTE $0xA4
1243         CALL _strayintr(SB); BYTE $0xA5
1244         CALL _strayintr(SB); BYTE $0xA6
1245         CALL _strayintr(SB); BYTE $0xA7
1246         CALL _strayintr(SB); BYTE $0xA8
1247         CALL _strayintr(SB); BYTE $0xA9
1248         CALL _strayintr(SB); BYTE $0xAA
1249         CALL _strayintr(SB); BYTE $0xAB
1250         CALL _strayintr(SB); BYTE $0xAC
1251         CALL _strayintr(SB); BYTE $0xAD
1252         CALL _strayintr(SB); BYTE $0xAE
1253         CALL _strayintr(SB); BYTE $0xAF
1254         CALL _strayintr(SB); BYTE $0xB0
1255         CALL _strayintr(SB); BYTE $0xB1
1256         CALL _strayintr(SB); BYTE $0xB2
1257         CALL _strayintr(SB); BYTE $0xB3
1258         CALL _strayintr(SB); BYTE $0xB4
1259         CALL _strayintr(SB); BYTE $0xB5
1260         CALL _strayintr(SB); BYTE $0xB6
1261         CALL _strayintr(SB); BYTE $0xB7
1262         CALL _strayintr(SB); BYTE $0xB8
1263         CALL _strayintr(SB); BYTE $0xB9
1264         CALL _strayintr(SB); BYTE $0xBA
1265         CALL _strayintr(SB); BYTE $0xBB
1266         CALL _strayintr(SB); BYTE $0xBC
1267         CALL _strayintr(SB); BYTE $0xBD
1268         CALL _strayintr(SB); BYTE $0xBE
1269         CALL _strayintr(SB); BYTE $0xBF
1270         CALL _strayintr(SB); BYTE $0xC0
1271         CALL _strayintr(SB); BYTE $0xC1
1272         CALL _strayintr(SB); BYTE $0xC2
1273         CALL _strayintr(SB); BYTE $0xC3
1274         CALL _strayintr(SB); BYTE $0xC4
1275         CALL _strayintr(SB); BYTE $0xC5
1276         CALL _strayintr(SB); BYTE $0xC6
1277         CALL _strayintr(SB); BYTE $0xC7
1278         CALL _strayintr(SB); BYTE $0xC8
1279         CALL _strayintr(SB); BYTE $0xC9
1280         CALL _strayintr(SB); BYTE $0xCA
1281         CALL _strayintr(SB); BYTE $0xCB
1282         CALL _strayintr(SB); BYTE $0xCC
1283         CALL _strayintr(SB); BYTE $0xCD
1284         CALL _strayintr(SB); BYTE $0xCE
1285         CALL _strayintr(SB); BYTE $0xCF
1286         CALL _strayintr(SB); BYTE $0xD0
1287         CALL _strayintr(SB); BYTE $0xD1
1288         CALL _strayintr(SB); BYTE $0xD2
1289         CALL _strayintr(SB); BYTE $0xD3
1290         CALL _strayintr(SB); BYTE $0xD4
1291         CALL _strayintr(SB); BYTE $0xD5
1292         CALL _strayintr(SB); BYTE $0xD6
1293         CALL _strayintr(SB); BYTE $0xD7
1294         CALL _strayintr(SB); BYTE $0xD8
1295         CALL _strayintr(SB); BYTE $0xD9
1296         CALL _strayintr(SB); BYTE $0xDA
1297         CALL _strayintr(SB); BYTE $0xDB
1298         CALL _strayintr(SB); BYTE $0xDC
1299         CALL _strayintr(SB); BYTE $0xDD
1300         CALL _strayintr(SB); BYTE $0xDE
1301         CALL _strayintr(SB); BYTE $0xDF
1302         CALL _strayintr(SB); BYTE $0xE0
1303         CALL _strayintr(SB); BYTE $0xE1
1304         CALL _strayintr(SB); BYTE $0xE2
1305         CALL _strayintr(SB); BYTE $0xE3
1306         CALL _strayintr(SB); BYTE $0xE4
1307         CALL _strayintr(SB); BYTE $0xE5
1308         CALL _strayintr(SB); BYTE $0xE6
1309         CALL _strayintr(SB); BYTE $0xE7
1310         CALL _strayintr(SB); BYTE $0xE8
1311         CALL _strayintr(SB); BYTE $0xE9
1312         CALL _strayintr(SB); BYTE $0xEA
1313         CALL _strayintr(SB); BYTE $0xEB
1314         CALL _strayintr(SB); BYTE $0xEC
1315         CALL _strayintr(SB); BYTE $0xED
1316         CALL _strayintr(SB); BYTE $0xEE
1317         CALL _strayintr(SB); BYTE $0xEF
1318         CALL _strayintr(SB); BYTE $0xF0
1319         CALL _strayintr(SB); BYTE $0xF1
1320         CALL _strayintr(SB); BYTE $0xF2
1321         CALL _strayintr(SB); BYTE $0xF3
1322         CALL _strayintr(SB); BYTE $0xF4
1323         CALL _strayintr(SB); BYTE $0xF5
1324         CALL _strayintr(SB); BYTE $0xF6
1325         CALL _strayintr(SB); BYTE $0xF7
1326         CALL _strayintr(SB); BYTE $0xF8
1327         CALL _strayintr(SB); BYTE $0xF9
1328         CALL _strayintr(SB); BYTE $0xFA
1329         CALL _strayintr(SB); BYTE $0xFB
1330         CALL _strayintr(SB); BYTE $0xFC
1331         CALL _strayintr(SB); BYTE $0xFD
1332         CALL _strayintr(SB); BYTE $0xFE
1333         CALL _strayintr(SB); BYTE $0xFF