l.s 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805
  1. #include "x16.h"
  2. #include "mem.h"
  3. #define PDB 0x08000 /* temporary page tables (24KB) */
  4. #define NoScreenBlank 1
  5. /*#define ResetDiscs 1*/
  6. TEXT origin(SB), $0
  7. /*
  8. * This part of l.s is used only in the boot kernel.
  9. * It assumes that we are in real address mode, i.e.,
  10. * that we look like an 8086.
  11. *
  12. * Make sure the segments are reasonable.
  13. * If we were started directly from the BIOS
  14. * (i.e. no MS-DOS) then DS may not be
  15. * right.
  16. */
  17. MOVW CS, AX
  18. MOVW AX, DS
  19. #ifdef NoScreenBlank
  20. /*
  21. * Get the current video mode. If it isn't mode 3,
  22. * set text mode 3.
  23. * Well, no. Windows95 won't co-operate here so we have
  24. * to explicitly set mode 3.
  25. */
  26. XORL AX, AX
  27. MOVB $0x0F, AH
  28. INT $0x10 /* get current video mode in AL */
  29. CMPB AL, $03
  30. JEQ sayhello
  31. #endif /* NoScreenBlank */
  32. XORL AX, AX
  33. MOVB $0x03, AL
  34. INT $0x10 /* set video mode in AL */
  35. sayhello:
  36. LWI(hello(SB), rSI)
  37. CALL16(biosputs(SB))
  38. #ifdef ResetDiscs
  39. XORL AX, AX /* reset disc system */
  40. XORL DX, DX
  41. MOVB $0x80, DL
  42. INT $0x13
  43. #endif /* ResetDiscs */
  44. #ifdef DOTCOM
  45. /*
  46. * relocate everything to a half meg and jump there
  47. * - looks weird because it is being assembled by a 32 bit
  48. * assembler for a 16 bit world
  49. *
  50. * only b.com does this - not 9load
  51. */
  52. MOVL $0,BX
  53. INCL BX
  54. SHLL $15,BX
  55. MOVL BX,CX
  56. MOVW BX,ES
  57. MOVL $0,SI
  58. MOVL SI,DI
  59. CLD
  60. REP
  61. MOVSL
  62. /*
  63. * Jump to the copied image;
  64. * fix up the DS for the new location.
  65. */
  66. FARJUMP16(0x8000, _start8000(SB))
  67. TEXT _start8000(SB), $0
  68. MFSR(rCS, rAX) /* fix up DS, ES (0x8000) */
  69. MTSR(rAX, rDS)
  70. MTSR(rAX, rES)
  71. /*
  72. * If we are already in protected mode, have to get back
  73. * to real mode before trying any privileged operations
  74. * (like going into protected mode...).
  75. * Try to reset with a restart vector.
  76. */
  77. MFCR(rCR0, rAX) /* are we in protected mode? */
  78. ANDI(0x0001, rAX)
  79. JEQ _real
  80. CLR(rBX)
  81. MTSR(rBX, rES)
  82. LWI(0x0467, rBX) /* reset entry point */
  83. LWI(_start8000(SB), rAX) /* offset within segment */
  84. BYTE $0x26
  85. BYTE $0x89
  86. BYTE $0x07 /* MOVW AX, ES:[BX] */
  87. LBI(0x69, rBL)
  88. MFSR(rCS, rAX) /* segment */
  89. BYTE $0x26
  90. BYTE $0x89
  91. BYTE $0x07 /* MOVW AX, ES:[BX] */
  92. CLR(rDX)
  93. OUTPORTB(0x70, 0x8F)
  94. OUTPORTB(0x71, 0x0A)
  95. FARJUMP16(0xFFFF, 0x0000) /* reset */
  96. #endif /* DOTCOM */
  97. _real:
  98. /*
  99. * do things that need to be done in real mode.
  100. * the results get written to CONFADDR (0x1200)
  101. * in a series of <4-byte-magic-number><block-of-data>
  102. * the data length is dependent on the magic number.
  103. *
  104. * this gets parsed by conf.c:/^readlsconf
  105. *
  106. * N.B. CALL16 kills rDI, so we can't call anything.
  107. */
  108. LWI(0x0000, rAX)
  109. MTSR(rAX, rES)
  110. LWI(0x1200, rDI)
  111. /*
  112. * turn off interrupts
  113. */
  114. CLI
  115. /*
  116. * detect APM1.2 bios support
  117. */
  118. /* save DI */
  119. SW(rDI, rock(SB))
  120. /* disconnect anyone else */
  121. LWI(0x5304, rAX)
  122. LWI(0x0000, rBX)
  123. INT $0x15
  124. /* connect */
  125. CLC
  126. LWI(0x5303, rAX)
  127. LWI(0x0000, rBX)
  128. INT $0x15
  129. CLI /* apm put interrupts back? */
  130. JC noapm
  131. OPSIZE; PUSHR(rSI)
  132. OPSIZE; PUSHR(rBX)
  133. PUSHR(rDI)
  134. PUSHR(rDX)
  135. PUSHR(rCX)
  136. PUSHR(rAX)
  137. /* put DI, ES back */
  138. LW(rock(SB), rDI)
  139. LWI(0x0000, rAX)
  140. MTSR(rAX, rES)
  141. /*
  142. * write APM data. first four bytes are APM\0.
  143. */
  144. LWI(0x5041, rAX)
  145. STOSW
  146. LWI(0x004d, rAX)
  147. STOSW
  148. LWI(8, rCX)
  149. apmmove:
  150. POPR(rAX)
  151. STOSW
  152. LOOP apmmove
  153. noapm:
  154. /*
  155. * end of real mode hacks: write terminator, put ES back.
  156. */
  157. LWI(0x0000, rAX)
  158. STOSW
  159. STOSW
  160. MFSR(rCS, rAX) /* fix up ES (0x8000) */
  161. MTSR(rAX, rES)
  162. /*
  163. * goto protected mode
  164. */
  165. /* MOVL tgdtptr(SB),GDTR /**/
  166. BYTE $0x0f
  167. BYTE $0x01
  168. BYTE $0x16
  169. WORD $tgdtptr(SB)
  170. LWI(1, rAX)
  171. /* MOV AX,MSW */
  172. BYTE $0x0F; BYTE $0x01; BYTE $0xF0
  173. /*
  174. * clear prefetch queue (weird code to avoid optimizations)
  175. */
  176. /* JMP .+2 */
  177. BYTE $0xEB
  178. BYTE $0x00
  179. /*
  180. * set all segs
  181. */
  182. /* MOVW $SELECTOR(1, SELGDT, 0),AX /**/
  183. BYTE $0xc7
  184. BYTE $0xc0
  185. WORD $SELECTOR(1, SELGDT, 0)
  186. MOVW AX,DS
  187. MOVW AX,SS
  188. MOVW AX,ES
  189. MOVW AX,FS
  190. MOVW AX,GS
  191. /* JMPFAR SELECTOR(2, SELGDT, 0):$mode32bit(SB) /**/
  192. BYTE $0x66
  193. BYTE $0xEA
  194. LONG $mode32bit-KZERO(SB)
  195. WORD $SELECTOR(2, SELGDT, 0)
  196. TEXT mode32bit(SB),$0
  197. /*
  198. * make a bottom level page table page that maps the first
  199. * 16 meg of physical memory
  200. */
  201. MOVL $PDB, DI /* clear 6 pages for the tables etc. */
  202. XORL AX, AX
  203. MOVL $(6*BY2PG), CX
  204. SHRL $2, CX
  205. CLD
  206. REP; STOSL
  207. MOVL $PDB, AX /* phys addr of temporary page table */
  208. MOVL $(4*1024),CX /* pte's per page */
  209. MOVL $((((4*1024)-1)<<PGSHIFT)|PTEVALID|PTEKERNEL|PTEWRITE),BX
  210. setpte:
  211. MOVL BX,-4(AX)(CX*4)
  212. SUBL $(1<<PGSHIFT),BX
  213. LOOP setpte
  214. /*
  215. * make a top level page table page that maps the first
  216. * 16 meg of memory to 0 thru 16meg and to KZERO thru KZERO+16meg
  217. */
  218. MOVL AX,BX
  219. ADDL $(4*BY2PG),AX
  220. ADDL $(PTEVALID|PTEKERNEL|PTEWRITE),BX
  221. MOVL BX,0(AX)
  222. MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+0)(AX)
  223. ADDL $BY2PG,BX
  224. MOVL BX,4(AX)
  225. MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+4)(AX)
  226. ADDL $BY2PG,BX
  227. MOVL BX,8(AX)
  228. MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+8)(AX)
  229. ADDL $BY2PG,BX
  230. MOVL BX,12(AX)
  231. MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+12)(AX)
  232. /*
  233. * point processor to top level page & turn on paging
  234. *
  235. * this produces the apparently harmless "VMX|F(125):468 Dis 0x0:0x0"
  236. * message in the VMware log.
  237. */
  238. MOVL AX,CR3
  239. MOVL CR0,AX
  240. ORL $0X80000000,AX
  241. MOVL AX,CR0
  242. /*
  243. * use a jump to an absolute location to get the PC into
  244. * KZERO.
  245. */
  246. LEAL tokzero(SB),AX
  247. JMP* AX
  248. /*
  249. * When we load 9load from DOS, the bootstrap jumps
  250. * to the instruction right after `JUMP', which gets
  251. * us into kzero.
  252. *
  253. * The name prevents it from being optimized away.
  254. */
  255. TEXT jumplabel(SB), $0
  256. BYTE $'J'; BYTE $'U'; BYTE $'M'; BYTE $'P'
  257. LEAL tokzero(SB),AX
  258. JMP* AX
  259. TEXT tokzero(SB),$0
  260. /*
  261. * Clear BSS
  262. */
  263. LEAL edata(SB),SI
  264. MOVL SI,DI
  265. ADDL $4,DI
  266. MOVL $0,AX
  267. MOVL AX,(SI)
  268. LEAL end(SB),CX
  269. SUBL DI,CX
  270. SHRL $2,CX
  271. CLD
  272. REP
  273. MOVSL
  274. /*
  275. * stack and mach
  276. */
  277. MOVL $mach0(SB),SP
  278. MOVL SP,m(SB)
  279. MOVL $0,0(SP)
  280. ADDL $(MACHSIZE-4),SP /* start stack above machine struct */
  281. CALL main(SB)
  282. loop:
  283. JMP loop
  284. GLOBL mach0+0(SB), $MACHSIZE
  285. GLOBL m(SB), $4
  286. /*
  287. * gdt to get us to 32-bit/segmented/unpaged mode
  288. */
  289. TEXT tgdt(SB),$0
  290. /* null descriptor */
  291. LONG $0
  292. LONG $0
  293. /* data segment descriptor for 4 gigabytes (PL 0) */
  294. LONG $(0xFFFF)
  295. LONG $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW)
  296. /* exec segment descriptor for 4 gigabytes (PL 0) */
  297. LONG $(0xFFFF)
  298. LONG $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
  299. /*
  300. * pointer to initial gdt
  301. */
  302. TEXT tgdtptr(SB),$0
  303. WORD $(3*8)
  304. LONG $tgdt-KZERO(SB)
  305. /*
  306. * Output a string to the display.
  307. * String argument is in rSI.
  308. */
  309. TEXT biosputs(SB), $0
  310. PUSHA
  311. CLR(rBX)
  312. _BIOSputs:
  313. LODSB
  314. ORB(rAL, rAL)
  315. JEQ _BIOSputsret
  316. LBI(0x0E, rAH)
  317. BIOSCALL(0x10)
  318. JMP _BIOSputs
  319. _BIOSputsret:
  320. POPA
  321. RET
  322. /*
  323. * input a byte
  324. */
  325. TEXT inb(SB),$0
  326. MOVL p+0(FP),DX
  327. XORL AX,AX
  328. INB
  329. RET
  330. /*
  331. * input a short from a port
  332. */
  333. TEXT ins(SB), $0
  334. MOVL p+0(FP), DX
  335. XORL AX, AX
  336. OPSIZE; INL
  337. RET
  338. /*
  339. * input a long from a port
  340. */
  341. TEXT inl(SB), $0
  342. MOVL p+0(FP), DX
  343. XORL AX, AX
  344. INL
  345. RET
  346. /*
  347. * output a byte
  348. */
  349. TEXT outb(SB),$0
  350. MOVL p+0(FP),DX
  351. MOVL b+4(FP),AX
  352. OUTB
  353. RET
  354. /*
  355. * output a short to a port
  356. */
  357. TEXT outs(SB), $0
  358. MOVL p+0(FP), DX
  359. MOVL s+4(FP), AX
  360. OPSIZE; OUTL
  361. RET
  362. /*
  363. * output a long to a port
  364. */
  365. TEXT outl(SB), $0
  366. MOVL p+0(FP), DX
  367. MOVL s+4(FP), AX
  368. OUTL
  369. RET
  370. /*
  371. * input a string of bytes from a port
  372. */
  373. TEXT insb(SB),$0
  374. MOVL p+0(FP),DX
  375. MOVL a+4(FP),DI
  376. MOVL c+8(FP),CX
  377. CLD; REP; INSB
  378. RET
  379. /*
  380. * input a string of shorts from a port
  381. */
  382. TEXT inss(SB),$0
  383. MOVL p+0(FP),DX
  384. MOVL a+4(FP),DI
  385. MOVL c+8(FP),CX
  386. CLD
  387. REP; OPSIZE; INSL
  388. RET
  389. /*
  390. * output a string of bytes to a port
  391. */
  392. TEXT outsb(SB),$0
  393. MOVL p+0(FP),DX
  394. MOVL a+4(FP),SI
  395. MOVL c+8(FP),CX
  396. CLD; REP; OUTSB
  397. RET
  398. /*
  399. * output a string of shorts to a port
  400. */
  401. TEXT outss(SB),$0
  402. MOVL p+0(FP),DX
  403. MOVL a+4(FP),SI
  404. MOVL c+8(FP),CX
  405. CLD
  406. REP; OPSIZE; OUTSL
  407. RET
  408. /*
  409. * input a string of longs from a port
  410. */
  411. TEXT insl(SB),$0
  412. MOVL p+0(FP),DX
  413. MOVL a+4(FP),DI
  414. MOVL c+8(FP),CX
  415. CLD; REP; INSL
  416. RET
  417. /*
  418. * output a string of longs to a port
  419. */
  420. TEXT outsl(SB),$0
  421. MOVL p+0(FP),DX
  422. MOVL a+4(FP),SI
  423. MOVL c+8(FP),CX
  424. CLD; REP; OUTSL
  425. RET
  426. /*
  427. * routines to load/read various system registers
  428. */
  429. GLOBL idtptr(SB),$6
  430. TEXT putidt(SB),$0 /* interrupt descriptor table */
  431. MOVL t+0(FP),AX
  432. MOVL AX,idtptr+2(SB)
  433. MOVL l+4(FP),AX
  434. MOVW AX,idtptr(SB)
  435. MOVL idtptr(SB),IDTR
  436. RET
  437. TEXT putcr3(SB),$0 /* top level page table pointer */
  438. MOVL t+0(FP),AX
  439. MOVL AX,CR3
  440. RET
  441. TEXT getcr0(SB),$0 /* coprocessor bits */
  442. MOVL CR0,AX
  443. RET
  444. TEXT getcr2(SB),$0 /* fault address */
  445. MOVL CR2,AX
  446. RET
  447. TEXT getcr3(SB),$0 /* page directory base */
  448. MOVL CR3,AX
  449. RET
  450. TEXT getcr4(SB), $0 /* CR4 - extensions */
  451. MOVL CR4, AX
  452. RET
  453. /*
  454. * special traps
  455. */
  456. TEXT intr0(SB),$0
  457. PUSHL $0
  458. PUSHL $0
  459. JMP intrcommon
  460. TEXT intr1(SB),$0
  461. PUSHL $0
  462. PUSHL $1
  463. JMP intrcommon
  464. TEXT intr2(SB),$0
  465. PUSHL $0
  466. PUSHL $2
  467. JMP intrcommon
  468. TEXT intr3(SB),$0
  469. PUSHL $0
  470. PUSHL $3
  471. JMP intrcommon
  472. TEXT intr4(SB),$0
  473. PUSHL $0
  474. PUSHL $4
  475. JMP intrcommon
  476. TEXT intr5(SB),$0
  477. PUSHL $0
  478. PUSHL $5
  479. JMP intrcommon
  480. TEXT intr6(SB),$0
  481. PUSHL $0
  482. PUSHL $6
  483. JMP intrcommon
  484. TEXT intr7(SB),$0
  485. PUSHL $0
  486. PUSHL $7
  487. JMP intrcommon
  488. TEXT intr8(SB),$0
  489. PUSHL $8
  490. JMP intrcommon
  491. TEXT intr9(SB),$0
  492. PUSHL $0
  493. PUSHL $9
  494. JMP intrcommon
  495. TEXT intr10(SB),$0
  496. PUSHL $10
  497. JMP intrcommon
  498. TEXT intr11(SB),$0
  499. PUSHL $11
  500. JMP intrcommon
  501. TEXT intr12(SB),$0
  502. PUSHL $12
  503. JMP intrcommon
  504. TEXT intr13(SB),$0
  505. PUSHL $13
  506. JMP intrcommon
  507. TEXT intr14(SB),$0
  508. PUSHL $14
  509. JMP intrcommon
  510. TEXT intr15(SB),$0
  511. PUSHL $0
  512. PUSHL $15
  513. JMP intrcommon
  514. TEXT intr16(SB),$0
  515. PUSHL $0
  516. PUSHL $16
  517. JMP intrcommon
  518. TEXT intr24(SB),$0
  519. PUSHL $0
  520. PUSHL $24
  521. JMP intrcommon
  522. TEXT intr25(SB),$0
  523. PUSHL $0
  524. PUSHL $25
  525. JMP intrcommon
  526. TEXT intr26(SB),$0
  527. PUSHL $0
  528. PUSHL $26
  529. JMP intrcommon
  530. TEXT intr27(SB),$0
  531. PUSHL $0
  532. PUSHL $27
  533. JMP intrcommon
  534. TEXT intr28(SB),$0
  535. PUSHL $0
  536. PUSHL $28
  537. JMP intrcommon
  538. TEXT intr29(SB),$0
  539. PUSHL $0
  540. PUSHL $29
  541. JMP intrcommon
  542. TEXT intr30(SB),$0
  543. PUSHL $0
  544. PUSHL $30
  545. JMP intrcommon
  546. TEXT intr31(SB),$0
  547. PUSHL $0
  548. PUSHL $31
  549. JMP intrcommon
  550. TEXT intr32(SB),$0
  551. PUSHL $0
  552. PUSHL $32
  553. JMP intrcommon
  554. TEXT intr33(SB),$0
  555. PUSHL $0
  556. PUSHL $33
  557. JMP intrcommon
  558. TEXT intr34(SB),$0
  559. PUSHL $0
  560. PUSHL $34
  561. JMP intrcommon
  562. TEXT intr35(SB),$0
  563. PUSHL $0
  564. PUSHL $35
  565. JMP intrcommon
  566. TEXT intr36(SB),$0
  567. PUSHL $0
  568. PUSHL $36
  569. JMP intrcommon
  570. TEXT intr37(SB),$0
  571. PUSHL $0
  572. PUSHL $37
  573. JMP intrcommon
  574. TEXT intr38(SB),$0
  575. PUSHL $0
  576. PUSHL $38
  577. JMP intrcommon
  578. TEXT intr39(SB),$0
  579. PUSHL $0
  580. PUSHL $39
  581. JMP intrcommon
  582. TEXT intr64(SB),$0
  583. PUSHL $0
  584. PUSHL $64
  585. JMP intrcommon
  586. TEXT intrbad(SB),$0
  587. PUSHL $0
  588. PUSHL $0x1ff
  589. JMP intrcommon
  590. intrcommon:
  591. PUSHL DS
  592. PUSHL ES
  593. PUSHL FS
  594. PUSHL GS
  595. PUSHAL
  596. MOVL $(KDSEL),AX
  597. MOVW AX,DS
  598. MOVW AX,ES
  599. LEAL 0(SP),AX
  600. PUSHL AX
  601. CALL trap(SB)
  602. POPL AX
  603. POPAL
  604. POPL GS
  605. POPL FS
  606. POPL ES
  607. POPL DS
  608. ADDL $8,SP /* error code and trap type */
  609. IRETL
  610. /*
  611. * interrupt level is interrupts on or off
  612. */
  613. TEXT spllo(SB),$0
  614. PUSHFL
  615. POPL AX
  616. STI
  617. RET
  618. TEXT splhi(SB),$0
  619. PUSHFL
  620. POPL AX
  621. CLI
  622. RET
  623. TEXT splx(SB),$0
  624. MOVL s+0(FP),AX
  625. PUSHL AX
  626. POPFL
  627. RET
  628. /*
  629. * do nothing whatsoever till interrupt happens
  630. */
  631. TEXT idle(SB),$0
  632. HLT
  633. RET
  634. /*
  635. * Try to determine the CPU type which requires fiddling with EFLAGS.
  636. * If the Id bit can be toggled then the CPUID instruciton can be used
  637. * to determine CPU identity and features. First have to check if it's
  638. * a 386 (Ac bit can't be set). If it's not a 386 and the Id bit can't be
  639. * toggled then it's an older 486 of some kind.
  640. *
  641. * cpuid(id[], &ax, &dx);
  642. */
  643. #define CPUID BYTE $0x0F; BYTE $0xA2 /* CPUID, argument in AX */
  644. TEXT cpuid(SB), $0
  645. MOVL $0x240000, AX
  646. PUSHL AX
  647. POPFL /* set Id|Ac */
  648. PUSHFL
  649. POPL BX /* retrieve value */
  650. MOVL $0, AX
  651. PUSHL AX
  652. POPFL /* clear Id|Ac, EFLAGS initialised */
  653. PUSHFL
  654. POPL AX /* retrieve value */
  655. XORL BX, AX
  656. TESTL $0x040000, AX /* Ac */
  657. JZ _cpu386 /* can't set this bit on 386 */
  658. TESTL $0x200000, AX /* Id */
  659. JZ _cpu486 /* can't toggle this bit on some 486 */
  660. MOVL $0, AX
  661. CPUID
  662. MOVL id+0(FP), BP
  663. MOVL BX, 0(BP) /* "Genu" "Auth" "Cyri" */
  664. MOVL DX, 4(BP) /* "ineI" "enti" "xIns" */
  665. MOVL CX, 8(BP) /* "ntel" "cAMD" "tead" */
  666. MOVL $1, AX
  667. CPUID
  668. JMP _cpuid
  669. _cpu486:
  670. MOVL $0x400, AX
  671. MOVL $0, DX
  672. JMP _cpuid
  673. _cpu386:
  674. MOVL $0x300, AX
  675. MOVL $0, DX
  676. _cpuid:
  677. MOVL ax+4(FP), BP
  678. MOVL AX, 0(BP)
  679. MOVL dx+8(FP), BP
  680. MOVL DX, 0(BP)
  681. RET
  682. /*
  683. * basic timing loop to determine CPU frequency
  684. */
  685. TEXT aamloop(SB),$0
  686. MOVL c+0(FP),CX
  687. aaml1:
  688. AAM
  689. LOOP aaml1
  690. RET
  691. TEXT hello(SB), $0
  692. BYTE $'P'; BYTE $'l'; BYTE $'a'; BYTE $'n';
  693. BYTE $' '; BYTE $'9'; BYTE $' '; BYTE $'f';
  694. BYTE $'r'; BYTE $'o'; BYTE $'m'; BYTE $' ';
  695. BYTE $'B'; BYTE $'e'; BYTE $'l'; BYTE $'l';
  696. BYTE $' '; BYTE $'L'; BYTE $'a'; BYTE $'b';
  697. BYTE $'s';
  698. BYTE $'\r';
  699. BYTE $'\n';
  700. BYTE $'\z';
  701. TEXT rock(SB), $0
  702. BYTE $0; BYTE $0; BYTE $0; BYTE $0;