Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/planix-v0/sys/src/9/pc/l.s – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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