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