]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/l.s
devvmx: support debug registers; simplify assembly
[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    $0x00010003                     /* flags */
46         LONG    $-(0x1BADB002 + 0x00010003)     /* 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    $0                              /* 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         ADDL    $KZERO, BX
74         MOVL    BX, multiboot-KZERO(SB)
75         MOVL    $_startPADDR(SB), AX
76         ANDL    $~KZERO, AX
77         JMP*    AX
78
79 /* multiboot structure pointer */
80 TEXT multiboot(SB), $0
81         LONG    $0
82
83 /*
84  * In protected mode with paging turned off and segment registers setup
85  * to linear map all memory. Entered via a jump to PADDR(entry),
86  * the physical address of the virtual kernel entry point of KADDR(entry).
87  * Make the basic page tables for processor 0. Six pages are needed for
88  * the basic set:
89  *      a page directory;
90  *      page tables for mapping the first 8MB of physical memory to KZERO;
91  *      a page for the GDT;
92  *      virtual and physical pages for mapping the Mach structure.
93  * The remaining PTEs will be allocated later when memory is sized.
94  * An identity mmu map is also needed for the switch to virtual mode.
95  * This identity mapping is removed once the MMU is going and the JMP has
96  * been made to virtual memory.
97  */
98 TEXT _startPADDR(SB), $0
99         CLI                                     /* make sure interrupts are off */
100
101         /* set up the gdt so we have sane plan 9 style gdts. */
102         MOVL    $tgdtptr(SB), AX
103         ANDL    $~KZERO, AX
104         MOVL    (AX), GDTR
105         MOVW    $1, AX
106         MOVW    AX, MSW
107
108         /* clear prefetch queue (weird code to avoid optimizations) */
109         DELAY
110
111         /* set segs to something sane (avoid traps later) */
112         MOVW    $(1<<3), AX
113         MOVW    AX, DS
114         MOVW    AX, SS
115         MOVW    AX, ES
116         MOVW    AX, FS
117         MOVW    AX, GS
118
119 /*      JMP     $(2<<3):$mode32bit(SB) /**/
120          BYTE   $0xEA
121          LONG   $mode32bit-KZERO(SB)
122          WORD   $(2<<3)
123
124 /*
125  *  gdt to get us to 32-bit/segmented/unpaged mode
126  */
127 TEXT tgdt(SB), $0
128
129         /* null descriptor */
130         LONG    $0
131         LONG    $0
132
133         /* data segment descriptor for 4 gigabytes (PL 0) */
134         LONG    $(0xFFFF)
135         LONG    $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW)
136
137         /* exec segment descriptor for 4 gigabytes (PL 0) */
138         LONG    $(0xFFFF)
139         LONG    $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
140
141 /*
142  *  pointer to initial gdt
143  *  Note the -KZERO which puts the physical address in the gdtptr. 
144  *  that's needed as we start executing in physical addresses. 
145  */
146 TEXT tgdtptr(SB), $0
147         WORD    $(3*8)
148         LONG    $tgdt-KZERO(SB)
149
150 TEXT m0rgdtptr(SB), $0
151         WORD    $(NGDT*8-1)
152         LONG    $(CPU0GDT-KZERO)
153
154 TEXT m0gdtptr(SB), $0
155         WORD    $(NGDT*8-1)
156         LONG    $CPU0GDT
157
158 TEXT m0idtptr(SB), $0
159         WORD $(256*8-1)
160         LONG $IDTADDR
161
162 TEXT mode32bit(SB), $0
163         /* At this point, the GDT setup is done. */
164
165         MOVL    $((CPU0END-CPU0PDB)>>2), CX
166         MOVL    $PADDR(CPU0PDB), DI
167         XORL    AX, AX
168
169         CLD
170         REP;    STOSL
171
172         MOVL    $PADDR(CPU0PTE), DX
173         MOVL    $(PTEWRITE|PTEVALID), BX        /* page permissions */
174         ORL     BX, DX
175
176         MOVL    $PADDR(CPU0PDB), AX
177         ADDL    $PDO(KZERO), AX                 /* page directory offset for KZERO */
178
179         MOVL    DX, 0(AX)                       /* PTE's for KZERO */
180         ADDL    $BY2PG, DX
181         MOVL    DX, 4(AX)                       /* PTE's for KZERO+4MB */
182         ADDL    $BY2PG, DX
183         MOVL    DX, 8(AX)                       /* PTE's for KZERO+8MB */
184         ADDL    $BY2PG, DX
185         MOVL    DX, 12(AX)                      /* PTE's for KZERO+12MB */
186
187         MOVL    $PADDR(CPU0PTE), AX             /* first page of page table */
188         MOVL    $end-KZERO(SB), CX
189
190         ADDL    $(16*1024), CX                  /* qemu puts multiboot data after the kernel */
191
192         ADDL    $(BY2XPG-1), CX
193         ANDL    $~(BY2XPG-1), CX                /* round to 4MB */
194         MOVL    CX, MemMin-KZERO(SB)            /* see memory.c */
195         SHRL    $PGSHIFT, CX
196         MOVL    BX, DX
197 _setpte:
198         MOVL    DX, (AX)
199         ADDL    $BY2PG, DX
200         ADDL    $4, AX
201         LOOP    _setpte
202
203         MOVL    $PADDR(CPU0PTE), AX
204         ADDL    $PTO(MACHADDR), AX              /* page table entry offset for MACHADDR */
205         ORL     $PADDR(CPU0MACH), BX
206         MOVL    BX, (AX)                        /* PTE for Mach */
207
208 /*
209  * Now ready to use the new map. Make sure the processor options are what is wanted.
210  * It is necessary on some processors to immediately follow mode switching with a JMP instruction
211  * to clear the prefetch queues.
212  */
213         MOVL    $PADDR(CPU0PDB), CX             /* load address of page directory */
214         MOVL    (PDO(KZERO))(CX), DX            /* double-map KZERO at 0 */
215         MOVL    DX, (PDO(0))(CX)
216         MOVL    CX, CR3
217         DELAY                                   /* JMP .+2 */
218
219         MOVL    CR0, DX
220         ORL     $0x80010000, DX                 /* PG|WP */
221         ANDL    $~0x6000000A, DX                /* ~(CD|NW|TS|MP) */
222
223         MOVL    $_startpg(SB), AX               /* this is a virtual address */
224         MOVL    DX, CR0                         /* turn on paging */
225         JMP*    AX                              /* jump to the virtual nirvana */
226
227 /*
228  * Basic machine environment set, can clear BSS and create a stack.
229  * The stack starts at the top of the page containing the Mach structure.
230  * The x86 architecture forces the use of the same virtual address for
231  * each processor's Mach structure, so the global Mach pointer 'm' can
232  * be initialised here.
233  */
234 TEXT _startpg(SB), $0
235         MOVL    $0, (PDO(0))(CX)                /* undo double-map of KZERO at 0 */
236         MOVL    CX, CR3                         /* load and flush the mmu */
237
238 _clearbss:
239         MOVL    $edata(SB), DI
240         XORL    AX, AX
241         MOVL    $end(SB), CX
242         SUBL    DI, CX                          /* end-edata bytes */
243         SHRL    $2, CX                          /* end-edata doublewords */
244
245         CLD
246         REP;    STOSL                           /* clear BSS */
247
248         MOVL    $MACHADDR, SP
249         MOVL    SP, m(SB)                       /* initialise global Mach pointer */
250         MOVL    $0, 0(SP)                       /* initialise m->machno */
251
252
253         ADDL    $(MACHSIZE-4), SP               /* initialise stack */
254
255 /*
256  * Need to do one final thing to ensure a clean machine environment,
257  * clear the EFLAGS register, which can only be done once there is a stack.
258  */
259         MOVL    $0, AX
260         PUSHL   AX
261         POPFL
262
263         CALL    main(SB)
264
265 /*
266  * Park a processor. Should never fall through a return from main to here,
267  * should only be called by application processors when shutting down.
268  */
269 TEXT idle(SB), $0
270 _idle:
271         STI
272         HLT
273         JMP     _idle
274
275
276 TEXT load_fs(SB), $0
277         MOVW fs+0(FP), AX
278         MOVW AX, FS
279         RET
280
281 TEXT load_gs(SB), $0
282         MOVW gs+0(FP), AX
283         MOVW AX, GS
284         RET
285
286 /*
287  * BIOS32.
288  */
289 TEXT bios32call(SB), $0
290         MOVL    ci+0(FP), BP
291         MOVL    0(BP), AX
292         MOVL    4(BP), BX
293         MOVL    8(BP), CX
294         MOVL    12(BP), DX
295         MOVL    16(BP), SI
296         MOVL    20(BP), DI
297         PUSHL   BP
298
299         MOVL    12(SP), BP                      /* ptr */
300         BYTE $0xFF; BYTE $0x5D; BYTE $0x00      /* CALL FAR 0(BP) */
301
302         POPL    BP
303         MOVL    DI, 20(BP)
304         MOVL    SI, 16(BP)
305         MOVL    DX, 12(BP)
306         MOVL    CX, 8(BP)
307         MOVL    BX, 4(BP)
308         MOVL    AX, 0(BP)
309
310         XORL    AX, AX
311         JCC     _bios32xxret
312         INCL    AX
313
314 _bios32xxret:
315         RET
316
317 /*
318  * Port I/O.
319  *      in[bsl]         input a byte|short|long
320  *      ins[bsl]        input a string of bytes|shorts|longs
321  *      out[bsl]        output a byte|short|long
322  *      outs[bsl]       output a string of bytes|shorts|longs
323  */
324 TEXT inb(SB), $0
325         MOVL    port+0(FP), DX
326         XORL    AX, AX
327         INB
328         RET
329
330 TEXT insb(SB), $0
331         MOVL    port+0(FP), DX
332         MOVL    address+4(FP), DI
333         MOVL    count+8(FP), CX
334         CLD
335         REP;    INSB
336         RET
337
338 TEXT ins(SB), $0
339         MOVL    port+0(FP), DX
340         XORL    AX, AX
341         OP16;   INL
342         RET
343
344 TEXT inss(SB), $0
345         MOVL    port+0(FP), DX
346         MOVL    address+4(FP), DI
347         MOVL    count+8(FP), CX
348         CLD
349         REP;    OP16; INSL
350         RET
351
352 TEXT inl(SB), $0
353         MOVL    port+0(FP), DX
354         INL
355         RET
356
357 TEXT insl(SB), $0
358         MOVL    port+0(FP), DX
359         MOVL    address+4(FP), DI
360         MOVL    count+8(FP), CX
361         CLD
362         REP;    INSL
363         RET
364
365 TEXT outb(SB), $0
366         MOVL    port+0(FP), DX
367         MOVL    byte+4(FP), AX
368         OUTB
369         RET
370
371 TEXT outsb(SB), $0
372         MOVL    port+0(FP), DX
373         MOVL    address+4(FP), SI
374         MOVL    count+8(FP), CX
375         CLD
376         REP;    OUTSB
377         RET
378
379 TEXT outs(SB), $0
380         MOVL    port+0(FP), DX
381         MOVL    short+4(FP), AX
382         OP16;   OUTL
383         RET
384
385 TEXT outss(SB), $0
386         MOVL    port+0(FP), DX
387         MOVL    address+4(FP), SI
388         MOVL    count+8(FP), CX
389         CLD
390         REP;    OP16; OUTSL
391         RET
392
393 TEXT outl(SB), $0
394         MOVL    port+0(FP), DX
395         MOVL    long+4(FP), AX
396         OUTL
397         RET
398
399 TEXT outsl(SB), $0
400         MOVL    port+0(FP), DX
401         MOVL    address+4(FP), SI
402         MOVL    count+8(FP), CX
403         CLD
404         REP;    OUTSL
405         RET
406
407 /*
408  * Read/write various system registers.
409  * CR4 and the 'model specific registers' should only be read/written
410  * after it has been determined the processor supports them
411  */
412 TEXT lgdt(SB), $0                               /* GDTR - global descriptor table */
413         MOVL    gdtptr+0(FP), AX
414         MOVL    (AX), GDTR
415         RET
416
417 TEXT lldt(SB), $0                               /* LDTR - local descriptor table */
418         MOVL    sel+0(FP), AX
419         BYTE $0x0F; BYTE $0x00; BYTE $0xD0      /* LLDT AX */
420         RET
421
422 TEXT lidt(SB), $0                               /* IDTR - interrupt descriptor table */
423         MOVL    idtptr+0(FP), AX
424         MOVL    (AX), IDTR
425         RET
426
427 TEXT ltr(SB), $0                                /* TR - task register */
428         MOVL    tptr+0(FP), AX
429         MOVW    AX, TASK
430         RET
431
432 TEXT getcr0(SB), $0                             /* CR0 - processor control */
433         MOVL    CR0, AX
434         RET
435
436 TEXT getcr2(SB), $0                             /* CR2 - page fault linear address */
437         MOVL    CR2, AX
438         RET
439
440 TEXT getcr3(SB), $0                             /* CR3 - page directory base */
441         MOVL    CR3, AX
442         RET
443
444 TEXT putcr0(SB), $0
445         MOVL    cr0+0(FP), AX
446         MOVL    AX, CR0
447         RET
448
449 TEXT putcr3(SB), $0
450         MOVL    cr3+0(FP), AX
451         MOVL    AX, CR3
452         RET
453
454 TEXT getcr4(SB), $0                             /* CR4 - extensions */
455         MOVL    CR4, AX
456         RET
457
458 TEXT putcr4(SB), $0
459         MOVL    cr4+0(FP), AX
460         MOVL    AX, CR4
461         RET
462
463 TEXT invlpg(SB), $0
464         /* 486+ only */
465         MOVL    va+0(FP), CX
466         INVLPG
467         RET
468
469 TEXT wbinvd(SB), $0
470         WBINVD
471         RET
472
473 TEXT _cycles(SB), $0                            /* time stamp counter */
474         RDTSC
475         MOVL    vlong+0(FP), CX                 /* &vlong */
476         MOVL    AX, 0(CX)                       /* lo */
477         MOVL    DX, 4(CX)                       /* hi */
478         RET
479
480 /*
481  * stub for:
482  * time stamp counter; low-order 32 bits of 64-bit cycle counter
483  * Runs at fasthz/4 cycles per second (m->clkin>>3)
484  */
485 TEXT lcycles(SB),1,$0
486         RDTSC
487         RET
488
489 TEXT rdmsr(SB), $0                              /* model-specific register */
490         MOVL    $0, BP
491         MOVL    index+0(FP), CX
492 TEXT _rdmsrinst(SB), $0
493         RDMSR
494         MOVL    vlong+4(FP), CX                 /* &vlong */
495         MOVL    AX, 0(CX)                       /* lo */
496         MOVL    DX, 4(CX)                       /* hi */
497         MOVL    BP, AX                          /* BP set to -1 if traped */
498         RET
499         
500 TEXT wrmsr(SB), $0
501         MOVL    $0, BP
502         MOVL    index+0(FP), CX
503         MOVL    lo+4(FP), AX
504         MOVL    hi+8(FP), DX
505 TEXT _wrmsrinst(SB), $0
506         WRMSR
507         MOVL    BP, AX                          /* BP set to -1 if traped */
508         RET
509
510 /*
511  * Try to determine the CPU type which requires fiddling with EFLAGS.
512  * If the Id bit can be toggled then the CPUID instruction can be used
513  * to determine CPU identity and features. First have to check if it's
514  * a 386 (Ac bit can't be set). If it's not a 386 and the Id bit can't be
515  * toggled then it's an older 486 of some kind.
516  *
517  *      cpuid(fun, regs[4]);
518  */
519 TEXT cpuid(SB), $0
520         MOVL    $0x240000, AX
521         PUSHL   AX
522         POPFL                                   /* set Id|Ac */
523         PUSHFL
524         POPL    BX                              /* retrieve value */
525         MOVL    $0, AX
526         PUSHL   AX
527         POPFL                                   /* clear Id|Ac, EFLAGS initialised */
528         PUSHFL
529         POPL    AX                              /* retrieve value */
530         XORL    BX, AX
531         TESTL   $0x040000, AX                   /* Ac */
532         JZ      _cpu386                         /* can't set this bit on 386 */
533         TESTL   $0x200000, AX                   /* Id */
534         JZ      _cpu486                         /* can't toggle this bit on some 486 */
535         MOVL    fn+0(FP), AX
536         CPUID
537         JMP     _cpuid
538 _cpu486:
539         MOVL    $0x400, AX
540         JMP     _maybezapax
541 _cpu386:
542         MOVL    $0x300, AX
543 _maybezapax:
544         CMPL    fn+0(FP), $1
545         JE      _zaprest
546         XORL    AX, AX
547 _zaprest:
548         XORL    BX, BX
549         XORL    CX, CX
550         XORL    DX, DX
551 _cpuid:
552         MOVL    regs+4(FP), BP
553         MOVL    AX, 0(BP)
554         MOVL    BX, 4(BP)
555         MOVL    CX, 8(BP)
556         MOVL    DX, 12(BP)
557         RET
558
559 /*
560  * Basic timing loop to determine CPU frequency.
561  */
562 TEXT aamloop(SB), $0
563         MOVL    count+0(FP), CX
564 _aamloop:
565         AAM
566         LOOP    _aamloop
567         RET
568
569 /*
570  * Floating point.
571  * Note: the encodings for the FCLEX, FINIT, FSAVE, FSTCW, FSENV and FSTSW
572  * instructions do NOT have the WAIT prefix byte (i.e. they act like their
573  * FNxxx variations) so WAIT instructions must be explicitly placed in the
574  * code as necessary.
575  */
576 #define FPOFF                                                    ;\
577         MOVL    CR0, AX                                          ;\
578         ORL     $0x28, AX                       /* NE=1, TS=1 */ ;\
579         MOVL    AX, CR0
580
581 #define FPON                                                     ;\
582         MOVL    CR0, AX                                          ;\
583         ANDL    $~0xC, AX                       /* EM=0, TS=0 */ ;\
584         MOVL    AX, CR0
585
586 TEXT fpoff(SB), $0                              /* disable */
587         FPOFF
588         RET
589
590 TEXT fpinit(SB), $0                             /* enable and init */
591         FPON
592         FINIT
593         WAIT
594         /* setfcr(FPPDBL|FPRNR|FPINVAL|FPZDIV|FPOVFL) */
595         /* note that low 6 bits are masks, not enables, on this chip */
596         PUSHW   $0x0232
597         FLDCW   0(SP)
598         POPW    AX
599         WAIT
600         RET
601
602 TEXT fpx87save0(SB), $0                         /* save state and disable */
603         MOVL    p+0(FP), AX
604         FSAVE   0(AX)                           /* no WAIT */
605         FPOFF
606         RET
607
608 TEXT fpx87restore0(SB), $0                      /* enable and restore state */
609         FPON
610         MOVL    p+0(FP), AX
611         FRSTOR  0(AX)
612         WAIT
613         RET
614
615 TEXT fpclear(SB), $0                            /* clear pending exceptions */
616         FPON
617         FCLEX                                   /* no WAIT */
618         FPOFF
619         RET
620
621 TEXT fpssesave0(SB), $0                         /* save state and disable */
622         MOVL    p+0(FP), AX
623         FXSAVE  0(AX)                           /* no WAIT */
624         FPOFF
625         RET
626
627 TEXT fpsserestore0(SB), $0                      /* enable and restore state */
628         FPON
629         MOVL    p+0(FP), AX
630         FXRSTOR 0(AX)
631         WAIT
632         RET
633
634 TEXT ldmxcsr(SB), $0                            /* Load MXCSR */
635         LDMXCSR mxcsr+0(FP)
636         RET
637
638 /*
639  */
640 TEXT splhi(SB), $0
641 shi:
642         PUSHFL
643         POPL    AX
644         TESTL   $0x200, AX
645         JZ      alreadyhi
646         MOVL    $(MACHADDR+0x04), CX            /* save PC in m->splpc */
647         MOVL    (SP), BX
648         MOVL    BX, (CX)
649 alreadyhi:
650         CLI
651         RET
652
653 TEXT spllo(SB), $0
654 slo:
655         PUSHFL
656         POPL    AX
657         TESTL   $0x200, AX
658         JNZ     alreadylo
659         MOVL    $(MACHADDR+0x04), CX            /* clear m->splpc */
660         MOVL    $0, (CX)
661 alreadylo:
662         STI
663         RET
664
665 TEXT splx(SB), $0
666         MOVL    s+0(FP), AX
667         TESTL   $0x200, AX
668         JNZ     slo
669         JMP     shi
670
671 TEXT spldone(SB), $0
672         RET
673
674 TEXT islo(SB), $0
675         PUSHFL
676         POPL    AX
677         ANDL    $0x200, AX                      /* interrupt enable flag */
678         RET
679
680 /*
681  * Test-And-Set
682  */
683 TEXT tas(SB), $0
684 TEXT _tas(SB), $0
685         MOVL    $0xDEADDEAD, AX
686         MOVL    lock+0(FP), BX
687         XCHGL   AX, (BX)                        /* lock->key */
688         RET
689
690 TEXT mb386(SB), $0
691         POPL    AX                              /* return PC */
692         PUSHFL
693         PUSHL   CS
694         PUSHL   AX
695         IRETL
696
697 TEXT mb586(SB), $0
698         XORL    AX, AX
699         CPUID
700         RET
701
702 TEXT sfence(SB), $0
703         BYTE $0x0f
704         BYTE $0xae
705         BYTE $0xf8
706         RET
707
708 TEXT lfence(SB), $0
709         BYTE $0x0f
710         BYTE $0xae
711         BYTE $0xe8
712         RET
713
714 TEXT mfence(SB), $0
715         BYTE $0x0f
716         BYTE $0xae
717         BYTE $0xf0
718         RET
719
720 TEXT xchgw(SB), $0
721         MOVL    v+4(FP), AX
722         MOVL    p+0(FP), BX
723         XCHGW   AX, (BX)
724         RET
725
726 TEXT cmpswap486(SB), $0
727         MOVL    addr+0(FP), BX
728         MOVL    old+4(FP), AX
729         MOVL    new+8(FP), CX
730         LOCK
731         BYTE $0x0F; BYTE $0xB1; BYTE $0x0B      /* CMPXCHGL CX, (BX) */
732         JNZ didnt
733         MOVL    $1, AX
734         RET
735 didnt:
736         XORL    AX,AX
737         RET
738
739 TEXT mul64fract(SB), $0
740 /*
741  * Multiply two 64-bit number s and keep the middle 64 bits from the 128-bit result
742  * See ../port/tod.c for motivation.
743  */
744         MOVL    r+0(FP), CX
745         XORL    BX, BX                          /* BX = 0 */
746
747         MOVL    a+8(FP), AX
748         MULL    b+16(FP)                        /* a1*b1 */
749         MOVL    AX, 4(CX)                       /* r2 = lo(a1*b1) */
750
751         MOVL    a+8(FP), AX
752         MULL    b+12(FP)                        /* a1*b0 */
753         MOVL    AX, 0(CX)                       /* r1 = lo(a1*b0) */
754         ADDL    DX, 4(CX)                       /* r2 += hi(a1*b0) */
755
756         MOVL    a+4(FP), AX
757         MULL    b+16(FP)                        /* a0*b1 */
758         ADDL    AX, 0(CX)                       /* r1 += lo(a0*b1) */
759         ADCL    DX, 4(CX)                       /* r2 += hi(a0*b1) + carry */
760
761         MOVL    a+4(FP), AX
762         MULL    b+12(FP)                        /* a0*b0 */
763         ADDL    DX, 0(CX)                       /* r1 += hi(a0*b0) */
764         ADCL    BX, 4(CX)                       /* r2 += carry */
765         RET
766
767 /*
768  *  label consists of a stack pointer and a PC
769  */
770 TEXT gotolabel(SB), $0
771         MOVL    label+0(FP), AX
772         MOVL    0(AX), SP                       /* restore sp */
773         MOVL    4(AX), AX                       /* put return pc on the stack */
774         MOVL    AX, 0(SP)
775         MOVL    $1, AX                          /* return 1 */
776         RET
777
778 TEXT setlabel(SB), $0
779         MOVL    label+0(FP), AX
780         MOVL    SP, 0(AX)                       /* store sp */
781         MOVL    0(SP), BX                       /* store return pc */
782         MOVL    BX, 4(AX)
783         MOVL    $0, AX                          /* return 0 */
784         RET
785
786 /*
787  * Attempt at power saving. -rsc
788  */
789 TEXT halt(SB), $0
790         CLI
791         CMPL    nrdy(SB), $0
792         JEQ     _nothingready
793         STI
794         RET
795
796 _nothingready:
797         STI
798         HLT
799         RET
800
801 TEXT mwait(SB), $0
802         MOVL    addr+0(FP), AX
803         MOVL    (AX), CX
804         ORL     CX, CX
805         JNZ     _mwaitdone
806         XORL    DX, DX
807         BYTE $0x0f; BYTE $0x01; BYTE $0xc8      /* MONITOR */
808         MOVL    (AX), CX
809         ORL     CX, CX
810         JNZ     _mwaitdone
811         XORL    AX, AX
812         BYTE $0x0f; BYTE $0x01; BYTE $0xc9      /* MWAIT */
813 _mwaitdone:
814         RET
815
816 #define RDRANDAX        BYTE $0x0f; BYTE $0xc7; BYTE $0xf0
817
818 TEXT rdrand32(SB), $-4
819 _rloop32:
820         RDRANDAX
821         JCC     _rloop32
822         RET
823
824 TEXT rdrandbuf(SB), $0
825         MOVL    buf+0(FP), DI
826         MOVL    cnt+4(FP), CX
827         CLD
828         MOVL    CX, DX
829         SHRL    $2, CX
830         CMPL    CX, $0
831         JE      _rndleft
832 _rnddwords:
833         CALL    rdrand32(SB)
834         STOSL
835         LOOP _rnddwords
836 _rndleft:
837         MOVL    DX, CX
838         ANDL    $3, CX
839         CMPL    CX, $0
840         JE      _rnddone
841 _rndbytes:
842         CALL rdrand32(SB)
843         STOSB
844         LOOP _rndbytes
845 _rnddone:
846         RET
847
848 /* debug register access */
849
850 TEXT putdr(SB), $0
851         MOVL    p+0(FP), SI
852         MOVL    28(SI), AX
853         MOVL    AX, DR7
854 _putdr01236:
855         MOVL    0(SI), AX
856         MOVL    AX, DR0
857         MOVL    4(SI), AX
858         MOVL    AX, DR1
859         MOVL    8(SI), AX
860         MOVL    AX, DR2
861         MOVL    12(SI), AX
862         MOVL    AX, DR3
863         MOVL    24(SI), AX
864         MOVL    AX, DR6
865         RET
866
867 TEXT putdr01236(SB), $0
868         MOVL p+0(FP), SI
869         JMP _putdr01236
870
871 TEXT getdr6(SB), $0
872         MOVL    DR6, AX
873         RET
874
875 TEXT putdr6(SB), $0
876         MOVL    p+0(FP), AX
877         MOVL    AX, DR6
878         RET
879         
880 TEXT putdr7(SB), $0
881         MOVL    p+0(FP), AX
882         MOVL    AX, DR7
883         RET
884
885 /* VMX instructions */
886 TEXT vmxon(SB), $0
887         /* VMXON 4(SP) */
888         BYTE    $0xf3; BYTE $0x0f; BYTE $0xc7; BYTE $0x74; BYTE $0x24; BYTE $0x04
889         JMP     _vmout
890
891 TEXT vmxoff(SB), $0
892         BYTE    $0x0f; BYTE $0x01; BYTE $0xc4
893         JMP     _vmout
894
895 TEXT vmclear(SB), $0
896         /* VMCLEAR 4(SP) */
897         BYTE    $0x66; BYTE $0x0f; BYTE $0xc7; BYTE $0x74; BYTE $0x24; BYTE $0x04
898         JMP     _vmout
899
900 TEXT vmlaunch(SB), $0
901         MOVL    $0x6C14, DI
902         MOVL    SP, DX
903         BYTE    $0x0f; BYTE $0x79; BYTE $0xfa /* VMWRITE DX, DI */
904         JBE     _vmout
905         MOVL    $0x6C16, DI
906         MOVL    $vmrestore(SB), DX
907         BYTE    $0x0f; BYTE $0x79; BYTE $0xfa /* VMWRITE DX, DI */
908         JBE     _vmout
909         
910         MOVL    resume+4(FP), AX
911         TESTL   AX, AX
912         MOVL    ureg+0(FP), DI
913         MOVL    32(DI), AX
914         MOVL    AX, CR2
915         MOVL    4(DI), SI
916         MOVL    8(DI), BP
917         MOVL    16(DI), BX
918         MOVL    20(DI), DX
919         MOVL    24(DI), CX
920         MOVL    28(DI), AX
921         MOVL    0(DI), DI
922         JNE     _vmresume
923         BYTE    $0x0f; BYTE $0x01; BYTE $0xc2 /* VMLAUNCH       */
924         JMP     _vmout
925 _vmresume:
926         BYTE    $0x0f; BYTE $0x01; BYTE $0xc3 /* VMRESUME       */
927         JMP _vmout
928
929 TEXT vmrestore(SB), $0
930         PUSHL   DI
931         MOVL    ureg+0(FP), DI
932         POPL    0(DI)
933         MOVL    SI, 4(DI)
934         MOVL    BP, 8(DI)
935         MOVL    BX, 16(DI)
936         MOVL    DX, 20(DI)
937         MOVL    CX, 24(DI)
938         MOVL    AX, 28(DI)
939         MOVL    CR2, AX
940         MOVL    AX, 32(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