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