l.s 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704
  1. /*
  2. * Memory and machine-specific definitions. Used in C and assembler.
  3. */
  4. /*
  5. * Sizes
  6. */
  7. #define BI2BY 8 /* bits per byte */
  8. #define BI2WD 32 /* bits per word */
  9. #define BY2WD 4 /* bytes per word */
  10. #define BY2PG 4096 /* bytes per page */
  11. #define WD2PG (BY2PG/BY2WD) /* words per page */
  12. #define PGSHIFT 12 /* log(BY2PG) */
  13. #define PGROUND(s) (((s)+(BY2PG-1))&~(BY2PG-1))
  14. #define MAXMACH 1 /* max # cpus system can run */
  15. /*
  16. * Time
  17. */
  18. #define HZ (20) /* clock frequency */
  19. #define MS2HZ (1000/HZ) /* millisec per clock tick */
  20. #define TK2SEC(t) ((t)/HZ) /* ticks to seconds */
  21. #define TK2MS(t) ((((ulong)(t))*1000)/HZ) /* ticks to milliseconds */
  22. #define MS2TK(t) ((((ulong)(t))*HZ)/1000) /* milliseconds to ticks */
  23. /*
  24. * Fundamental addresses
  25. */
  26. /*
  27. * Address spaces
  28. *
  29. * User is at 0-2GB
  30. * Kernel is at 2GB-4GB
  31. *
  32. * To avoid an extra page map, both the user stack (USTKTOP) and
  33. * the temporary user stack (TSTKTOP) should be in the the same
  34. * 4 meg.
  35. */
  36. #define UZERO 0 /* base of user address space */
  37. #define UTZERO (UZERO+BY2PG) /* first address in user text */
  38. #define KZERO 0x80000000 /* base of kernel address space */
  39. #define KTZERO KZERO /* first address in kernel text */
  40. #define USERADDR 0xC0000000 /* struct User */
  41. #define UREGADDR (USERADDR+BY2PG-4*19)
  42. #define TSTKTOP USERADDR /* end of new stack in sysexec */
  43. #define TSTKSIZ 10
  44. #define USTKTOP (TSTKTOP-TSTKSIZ*BY2PG) /* byte just beyond user stack */
  45. #define USTKSIZE (16*1024*1024 - TSTKSIZ*BY2PG) /* size of user stack */
  46. #define ROMBIOS (KZERO|0xF0000)
  47. #define MACHSIZE 4096
  48. #define isphys(x) (((ulong)x)&KZERO)
  49. /*
  50. * known 80386 segments (in GDT) and their selectors
  51. */
  52. #define NULLSEG 0 /* null segment */
  53. #define KDSEG 1 /* kernel data/stack */
  54. #define KESEG 2 /* kernel executable */
  55. #define UDSEG 3 /* user data/stack */
  56. #define UESEG 4 /* user executable */
  57. #define TSSSEG 5 /* task segment */
  58. #define SELGDT (0<<3) /* selector is in gdt */
  59. #define SELLDT (1<<3) /* selector is in ldt */
  60. #define SELECTOR(i, t, p) (((i)<<3) | (t) | (p))
  61. #define NULLSEL SELECTOR(NULLSEG, SELGDT, 0)
  62. #define KESEL SELECTOR(KESEG, SELGDT, 0)
  63. #define KDSEL SELECTOR(KDSEG, SELGDT, 0)
  64. #define UESEL SELECTOR(UESEG, SELGDT, 3)
  65. #define UDSEL SELECTOR(UDSEG, SELGDT, 3)
  66. #define TSSSEL SELECTOR(TSSSEG, SELGDT, 0)
  67. /*
  68. * fields in segment descriptors
  69. */
  70. #define SEGDATA (0x10<<8) /* data/stack segment */
  71. #define SEGEXEC (0x18<<8) /* executable segment */
  72. #define SEGTSS (0x9<<8) /* TSS segment */
  73. #define SEGCG (0x0C<<8) /* call gate */
  74. #define SEGIG (0x0E<<8) /* interrupt gate */
  75. #define SEGTG (0x0F<<8) /* task gate */
  76. #define SEGTYPE (0x1F<<8)
  77. #define SEGP (1<<15) /* segment present */
  78. #define SEGPL(x) ((x)<<13) /* priority level */
  79. #define SEGB (1<<22) /* granularity 1==4k (for expand-down) */
  80. #define SEGG (1<<23) /* granularity 1==4k (for other) */
  81. #define SEGE (1<<10) /* expand down */
  82. #define SEGW (1<<9) /* writable (for data/stack) */
  83. #define SEGR (1<<9) /* readable (for code) */
  84. #define SEGD (1<<22) /* default 1==32bit (for code) */
  85. /*
  86. * virtual MMU
  87. */
  88. #define PTEMAPMEM (1024*1024) /* ??? */
  89. #define SEGMAPSIZE 16 /* ??? */
  90. #define PTEPERTAB (PTEMAPMEM/BY2PG) /* ??? */
  91. #define PPN(x) ((x)&~(BY2PG-1))
  92. /*
  93. * physical MMU
  94. */
  95. #define PTEVALID (1<<0)
  96. #define PTEUNCACHED 0 /* everything is uncached */
  97. #define PTEWRITE (1<<1)
  98. #define PTERONLY (0<<1)
  99. #define PTEKERNEL (0<<2)
  100. #define PTEUSER (1<<2)
  101. /*
  102. * flag register bits that we care about
  103. */
  104. #define IFLAG 0x200
  105. #define OP16 BYTE $0x66
  106. /*
  107. * about to walk all over ms/dos - turn off interrupts
  108. */
  109. TEXT origin(SB),$0
  110. CLI
  111. #ifdef BOOT
  112. /*
  113. * This part of l.s is used only in the boot kernel.
  114. * It assumes that we are in real address mode, i.e.,
  115. * that we look like an 8086.
  116. */
  117. /*
  118. * relocate everything to a half meg and jump there
  119. * - looks wierd because it is being assembled by a 32 bit
  120. * assembler for a 16 bit world
  121. */
  122. MOVL $0,BX
  123. INCL BX
  124. SHLL $15,BX
  125. MOVL BX,CX
  126. MOVW BX,ES
  127. MOVL $0,SI
  128. MOVL SI,DI
  129. CLD; REP; MOVSL
  130. /* JMPFAR 0X8000:$lowcore(SB) /**/
  131. BYTE $0xEA
  132. WORD $lowcore(SB)
  133. WORD $0X8000
  134. TEXT lowcore(SB),$0
  135. /*
  136. * now that we're in low core, update the DS
  137. */
  138. MOVW BX,DS
  139. /*
  140. * goto protected mode
  141. */
  142. /* MOVL tgdtptr(SB),GDTR /**/
  143. BYTE $0x0f
  144. BYTE $0x01
  145. BYTE $0x16
  146. WORD $tgdtptr(SB)
  147. MOVL CR0,AX
  148. ORL $1,AX
  149. MOVL AX,CR0
  150. /*
  151. * clear prefetch queue (wierd code to avoid optimizations)
  152. */
  153. CLC
  154. JCC flush
  155. MOVL AX,AX
  156. flush:
  157. /*
  158. * set all segs
  159. */
  160. /* MOVW $SELECTOR(1, SELGDT, 0),AX /**/
  161. BYTE $0xc7
  162. BYTE $0xc0
  163. WORD $SELECTOR(1, SELGDT, 0)
  164. MOVW AX,DS
  165. MOVW AX,SS
  166. MOVW AX,ES
  167. MOVW AX,FS
  168. MOVW AX,GS
  169. /* JMPFAR SELECTOR(2, SELGDT, 0):$mode32bit(SB) /**/
  170. BYTE $0x66
  171. BYTE $0xEA
  172. LONG $mode32bit-KZERO(SB)
  173. WORD $SELECTOR(2, SELGDT, 0)
  174. TEXT mode32bit(SB),$0
  175. #endif BOOT
  176. /*
  177. * Clear BSS
  178. */
  179. LEAL edata-KZERO(SB),SI
  180. MOVL SI,DI
  181. ADDL $4,DI
  182. MOVL $0,AX
  183. MOVL AX,(SI)
  184. LEAL end-KZERO(SB),CX
  185. SUBL DI,CX
  186. SHRL $2,CX
  187. CLD; REP; MOVSL
  188. /*
  189. * make a bottom level page table page that maps the first
  190. * 16 meg of physical memory
  191. */
  192. LEAL tpt-KZERO(SB),AX /* get phys addr of temporary page table */
  193. ADDL $(BY2PG-1),AX /* must be page alligned */
  194. ANDL $(~(BY2PG-1)),AX /* ... */
  195. MOVL $(4*1024),CX /* pte's per page */
  196. MOVL $((((4*1024)-1)<<PGSHIFT)|PTEVALID|PTEKERNEL|PTEWRITE),BX
  197. setpte:
  198. MOVL BX,-4(AX)(CX*4)
  199. SUBL $(1<<PGSHIFT),BX
  200. LOOP setpte
  201. /*
  202. * make a top level page table page that maps the first
  203. * 16 meg of memory to 0 thru 16meg and to KZERO thru KZERO+16meg
  204. */
  205. MOVL AX,BX
  206. ADDL $(4*BY2PG),AX
  207. ADDL $(PTEVALID|PTEKERNEL|PTEWRITE),BX
  208. MOVL BX,0(AX)
  209. MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+0)(AX)
  210. ADDL $BY2PG,BX
  211. MOVL BX,4(AX)
  212. MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+4)(AX)
  213. ADDL $BY2PG,BX
  214. MOVL BX,8(AX)
  215. MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+8)(AX)
  216. ADDL $BY2PG,BX
  217. MOVL BX,12(AX)
  218. MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+12)(AX)
  219. /*
  220. * point processor to top level page & turn on paging
  221. */
  222. MOVL AX,CR3
  223. MOVL CR0,AX
  224. ORL $0X80000000,AX
  225. ANDL $~(0x8|0x2),AX /* TS=0, MP=0 */
  226. MOVL AX,CR0
  227. /*
  228. * use a jump to an absolute location to get the PC into
  229. * KZERO.
  230. */
  231. LEAL tokzero(SB),AX
  232. JMP* AX
  233. TEXT tokzero(SB),$0
  234. /*
  235. * stack and mach
  236. */
  237. MOVL $mach0(SB),SP
  238. MOVL SP,m(SB)
  239. MOVL $0,0(SP)
  240. ADDL $(MACHSIZE-4),SP /* start stack under machine struct */
  241. MOVL $0, u(SB)
  242. /*
  243. * clear flags
  244. */
  245. MOVL $0,AX
  246. PUSHL AX
  247. POPFL
  248. CALL main(SB)
  249. loop:
  250. JMP loop
  251. GLOBL mach0+0(SB), $MACHSIZE
  252. GLOBL u(SB), $4
  253. GLOBL m(SB), $4
  254. GLOBL tpt(SB), $(BY2PG*6)
  255. /*
  256. * gdt to get us to 32-bit/segmented/unpaged mode
  257. */
  258. TEXT tgdt(SB),$0
  259. /* null descriptor */
  260. LONG $0
  261. LONG $0
  262. /* data segment descriptor for 4 gigabytes (PL 0) */
  263. LONG $(0xFFFF)
  264. LONG $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW)
  265. /* exec segment descriptor for 4 gigabytes (PL 0) */
  266. LONG $(0xFFFF)
  267. LONG $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
  268. /*
  269. * pointer to initial gdt
  270. */
  271. TEXT tgdtptr(SB),$0
  272. WORD $(3*8)
  273. LONG $tgdt-KZERO(SB)
  274. /*
  275. * input a byte
  276. */
  277. TEXT inb(SB),$0
  278. MOVL p+0(FP),DX
  279. XORL AX,AX
  280. INB
  281. RET
  282. /*
  283. * output a byte
  284. */
  285. TEXT outb(SB),$0
  286. MOVL p+0(FP),DX
  287. MOVL b+4(FP),AX
  288. OUTB
  289. RET
  290. /*
  291. * input a string of shorts from a port
  292. */
  293. TEXT inss(SB),$0
  294. MOVL p+0(FP),DX
  295. MOVL a+4(FP),DI
  296. MOVL c+8(FP),CX
  297. CLD; REP; OP16; INSL
  298. RET
  299. /*
  300. * output a string of shorts to a port
  301. */
  302. TEXT outss(SB),$0
  303. MOVL p+0(FP),DX
  304. MOVL a+4(FP),SI
  305. MOVL c+8(FP),CX
  306. CLD; REP; OP16; OUTSL
  307. RET
  308. /*
  309. * test and set
  310. */
  311. TEXT tas(SB),$0
  312. MOVL $0xdeadead,AX
  313. MOVL l+0(FP),BX
  314. XCHGL AX,(BX)
  315. RET
  316. /*
  317. * routines to load/read various system registers
  318. */
  319. GLOBL idtptr(SB),$6
  320. TEXT putidt(SB),$0 /* interrupt descriptor table */
  321. MOVL t+0(FP),AX
  322. MOVL AX,idtptr+2(SB)
  323. MOVL l+4(FP),AX
  324. MOVW AX,idtptr(SB)
  325. MOVL idtptr(SB),IDTR
  326. RET
  327. GLOBL gdtptr(SB),$6
  328. TEXT putgdt(SB),$0 /* global descriptor table */
  329. MOVL t+0(FP),AX
  330. MOVL AX,gdtptr+2(SB)
  331. MOVL l+4(FP),AX
  332. MOVW AX,gdtptr(SB)
  333. MOVL gdtptr(SB),GDTR
  334. RET
  335. TEXT putcr3(SB),$0 /* top level page table pointer */
  336. MOVL t+0(FP),AX
  337. MOVL AX,CR3
  338. RET
  339. TEXT puttr(SB),$0 /* task register */
  340. MOVL t+0(FP),AX
  341. MOVW AX,TASK
  342. RET
  343. TEXT getcr0(SB),$0 /* coprocessor bits */
  344. MOVL CR0,AX
  345. RET
  346. TEXT getcr2(SB),$0 /* fault address */
  347. MOVL CR2,AX
  348. RET
  349. #define FPOFF\
  350. WAIT;\
  351. MOVL CR0,AX;\
  352. ORL $0x4,AX /* EM=1 */;\
  353. MOVL AX,CR0
  354. #define FPON\
  355. MOVL CR0,AX;\
  356. ANDL $~0x4,AX /* EM=0 */;\
  357. MOVL AX,CR0
  358. TEXT fpoff(SB),$0 /* turn off floating point */
  359. FPOFF
  360. RET
  361. TEXT fpinit(SB),$0 /* turn on & init the floating point */
  362. FPON
  363. FINIT
  364. WAIT
  365. PUSHW $0x0330
  366. FLDCW 0(SP) /* ignore underflow/precision, signal others */
  367. POPW AX
  368. WAIT
  369. RET
  370. TEXT fpsave(SB),$0 /* save floating point state and turn off */
  371. MOVL p+0(FP),AX
  372. WAIT
  373. FSAVE 0(AX)
  374. FPOFF
  375. RET
  376. TEXT fprestore(SB),$0 /* turn on floating point and restore regs */
  377. FPON
  378. MOVL p+0(FP),AX
  379. FRSTOR 0(AX)
  380. WAIT
  381. RET
  382. TEXT fpstatus(SB),$0 /* get floating point status */
  383. FSTSW AX
  384. RET
  385. /*
  386. * special traps
  387. */
  388. TEXT intr0(SB),$0
  389. PUSHL $0
  390. PUSHL $0
  391. JMP intrcommon
  392. TEXT intr1(SB),$0
  393. PUSHL $0
  394. PUSHL $1
  395. JMP intrcommon
  396. TEXT intr2(SB),$0
  397. PUSHL $0
  398. PUSHL $2
  399. JMP intrcommon
  400. TEXT intr3(SB),$0
  401. PUSHL $0
  402. PUSHL $3
  403. JMP intrcommon
  404. TEXT intr4(SB),$0
  405. PUSHL $0
  406. PUSHL $4
  407. JMP intrcommon
  408. TEXT intr5(SB),$0
  409. PUSHL $0
  410. PUSHL $5
  411. JMP intrcommon
  412. TEXT intr6(SB),$0
  413. PUSHL $0
  414. PUSHL $6
  415. JMP intrcommon
  416. TEXT intr7(SB),$0
  417. PUSHL $0
  418. PUSHL $7
  419. JMP intrcommon
  420. TEXT intr8(SB),$0
  421. PUSHL $8
  422. JMP intrscommon
  423. TEXT intr9(SB),$0
  424. PUSHL $0
  425. PUSHL $9
  426. JMP intrcommon
  427. TEXT intr10(SB),$0
  428. PUSHL $10
  429. JMP intrscommon
  430. TEXT intr11(SB),$0
  431. PUSHL $11
  432. JMP intrscommon
  433. TEXT intr12(SB),$0
  434. PUSHL $12
  435. JMP intrscommon
  436. TEXT intr13(SB),$0
  437. PUSHL $13
  438. JMP intrscommon
  439. TEXT intr14(SB),$0
  440. PUSHL $14
  441. JMP intrscommon
  442. TEXT intr15(SB),$0
  443. PUSHL $0
  444. PUSHL $15
  445. JMP intrcommon
  446. TEXT intr16(SB),$0
  447. PUSHL $0
  448. PUSHL $16
  449. JMP intrcommon
  450. TEXT intr24(SB),$0
  451. PUSHL $0
  452. PUSHL $24
  453. JMP intrcommon
  454. TEXT intr25(SB),$0
  455. PUSHL $0
  456. PUSHL $25
  457. JMP intrcommon
  458. TEXT intr26(SB),$0
  459. PUSHL $0
  460. PUSHL $26
  461. JMP intrcommon
  462. TEXT intr27(SB),$0
  463. PUSHL $0
  464. PUSHL $27
  465. JMP intrcommon
  466. TEXT intr28(SB),$0
  467. PUSHL $0
  468. PUSHL $28
  469. JMP intrcommon
  470. TEXT intr29(SB),$0
  471. PUSHL $0
  472. PUSHL $29
  473. JMP intrcommon
  474. TEXT intr30(SB),$0
  475. PUSHL $0
  476. PUSHL $30
  477. JMP intrcommon
  478. TEXT intr31(SB),$0
  479. PUSHL $0
  480. PUSHL $31
  481. JMP intrcommon
  482. TEXT intr32(SB),$0
  483. PUSHL $0
  484. PUSHL $16
  485. JMP intrcommon
  486. TEXT intr33(SB),$0
  487. PUSHL $0
  488. PUSHL $33
  489. JMP intrcommon
  490. TEXT intr34(SB),$0
  491. PUSHL $0
  492. PUSHL $34
  493. JMP intrcommon
  494. TEXT intr35(SB),$0
  495. PUSHL $0
  496. PUSHL $35
  497. JMP intrcommon
  498. TEXT intr36(SB),$0
  499. PUSHL $0
  500. PUSHL $36
  501. JMP intrcommon
  502. TEXT intr37(SB),$0
  503. PUSHL $0
  504. PUSHL $37
  505. JMP intrcommon
  506. TEXT intr38(SB),$0
  507. PUSHL $0
  508. PUSHL $38
  509. JMP intrcommon
  510. TEXT intr39(SB),$0
  511. PUSHL $0
  512. PUSHL $39
  513. JMP intrcommon
  514. TEXT intr64(SB),$0
  515. PUSHL $0
  516. PUSHL $64
  517. JMP intrcommon
  518. TEXT intrbad(SB),$0
  519. PUSHL $0
  520. PUSHL $0x1ff
  521. JMP intrcommon
  522. intrcommon:
  523. PUSHL DS
  524. PUSHL ES
  525. PUSHL FS
  526. PUSHL GS
  527. PUSHAL
  528. MOVL $(KDSEL),AX
  529. MOVW AX,DS
  530. MOVW AX,ES
  531. LEAL 0(SP),AX
  532. PUSHL AX
  533. CALL trap(SB)
  534. POPL AX
  535. POPAL
  536. POPL GS
  537. POPL FS
  538. POPL ES
  539. POPL DS
  540. ADDL $8,SP /* error code and trap type */
  541. IRETL
  542. intrscommon:
  543. PUSHL DS
  544. PUSHL ES
  545. PUSHL FS
  546. PUSHL GS
  547. PUSHAL
  548. MOVL $(KDSEL),AX
  549. MOVW AX,DS
  550. MOVW AX,ES
  551. LEAL 0(SP),AX
  552. PUSHL AX
  553. CALL trap(SB)
  554. POPL AX
  555. POPAL
  556. POPL GS
  557. POPL FS
  558. POPL ES
  559. POPL DS
  560. ADDL $8,SP /* error code and trap type */
  561. IRETL
  562. /*
  563. * interrupt level is interrupts on or off
  564. */
  565. TEXT spllo(SB),$0
  566. PUSHFL
  567. POPL AX
  568. STI
  569. RET
  570. TEXT splhi(SB),$0
  571. PUSHFL
  572. POPL AX
  573. CLI
  574. RET
  575. TEXT splx(SB),$0
  576. MOVL s+0(FP),AX
  577. PUSHL AX
  578. POPFL
  579. RET
  580. /*
  581. * do nothing whatsoever till interrupt happens
  582. */
  583. TEXT idle(SB),$0
  584. HLT
  585. RET
  586. /*
  587. * label consists of a stack pointer and a PC
  588. */
  589. TEXT gotolabel(SB),$0
  590. MOVL l+0(FP),AX
  591. MOVL 0(AX),SP /* restore sp */
  592. MOVL 4(AX),AX /* put return pc on the stack */
  593. MOVL AX,0(SP)
  594. MOVL $1,AX /* return 1 */
  595. RET
  596. TEXT setlabel(SB),$0
  597. MOVL l+0(FP),AX
  598. MOVL SP,0(AX) /* store sp */
  599. MOVL 0(SP),BX /* store return pc */
  600. MOVL BX,4(AX)
  601. MOVL $0,AX /* return 0 */
  602. RET
  603. /*
  604. * Used to get to the first process.
  605. * Set up an interrupt return frame and IRET to user level.
  606. */
  607. TEXT touser(SB),$0
  608. PUSHL $(UDSEL) /* old ss */
  609. PUSHL $(USTKTOP) /* old sp */
  610. PUSHFL /* old flags */
  611. PUSHL $(UESEL) /* old cs */
  612. PUSHL $(UTZERO+32) /* old pc */
  613. MOVL $(UDSEL),AX
  614. MOVW AX,DS
  615. MOVW AX,ES
  616. MOVW AX,GS
  617. MOVW AX,FS
  618. IRETL
  619. /*
  620. * set configuration register
  621. */
  622. TEXT config(SB),$0
  623. MOVL l+0(FP),AX
  624. MOVL $0x3F3,DX
  625. OUTB
  626. OUTB
  627. RET