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