l.s 30 KB

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