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