l64v.S 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535
  1. #include "amd64.h"
  2. .code64
  3. /*
  4. * Port I/O.
  5. */
  6. .global inb
  7. inb:
  8. MOVL %edi, %edx /* MOVL port+0(FP), DX */
  9. XORL %eax, %eax
  10. INB %dx
  11. RET
  12. .global insb
  13. insb:
  14. MOVL %edi, %edx /* MOVL port+0(FP), DX */
  15. MOVQ %rsi, %rdi
  16. MOVL %edx, %ecx
  17. CLD
  18. REP; INSB
  19. RET
  20. .global ins
  21. ins:
  22. MOVL %edi, %edx /* MOVL port+0(FP), DX */
  23. XORL %eax, %eax
  24. INW %dx
  25. RET
  26. .global inss
  27. inss:
  28. MOVL %edi, %edx /* MOVL port+0(FP), DX */
  29. MOVQ %rsi, %rdi
  30. MOVL %edx, %ecx
  31. CLD
  32. REP; INSW
  33. RET
  34. .global inl
  35. inl:
  36. MOVL %edi, %edx /* MOVL port+0(FP), DX */
  37. INL %dx
  38. RET
  39. .global insl
  40. insl:
  41. MOVL %edi, %edx /* MOVL port+0(FP), DX */
  42. MOVQ %rsi, %rdi
  43. MOVL %edx, %ecx
  44. CLD
  45. REP; INSL
  46. RET
  47. .global outb
  48. outb:
  49. MOVL %edi, %edx /* MOVL port+0(FP), DX */
  50. MOVL %esi, %eax
  51. OUTB %dx
  52. RET
  53. .global outsb
  54. outsb:
  55. MOVL %edi, %edx /* MOVL port+0(FP), DX */
  56. MOVQ %rsi, %rdi
  57. MOVL %edx, %ecx
  58. CLD
  59. REP; OUTSB
  60. RET
  61. .global outs
  62. outs:
  63. MOVL %edi, %edx /* MOVL port+0(FP), DX */
  64. MOVL %esi, %eax
  65. OUTW %dx
  66. RET
  67. .global outss
  68. outss:
  69. MOVL %edi, %edx /* MOVL port+0(FP), DX */
  70. MOVL %edx, %ecx
  71. CLD
  72. REP; OUTSW
  73. RET
  74. .global outl
  75. outl:
  76. MOVL %edi, %edx /* MOVL port+0(FP), DX */
  77. MOVL %esi, %eax
  78. OUTL %dx
  79. RET
  80. .global outsl
  81. outsl:
  82. MOVL %edi, %edx /* MOVL port+0(FP), DX */
  83. MOVQ %rsi, %rdi
  84. MOVL %edx, %ecx
  85. CLD
  86. REP; OUTSL
  87. RET
  88. /*
  89. * Load/store segment descriptor tables:
  90. * GDT - global descriptor table
  91. * IDT - interrupt descriptor table
  92. * TR - task register
  93. * GDTR and LDTR take an m16:m64 argument,
  94. * so shuffle the stack arguments to
  95. * get it in the right format.
  96. */
  97. .global gdtget
  98. gdtget:
  99. // panic.
  100. mov 0, %rax
  101. //sgdt %rdi
  102. // MOVL GDTR, (RARG) /* Note: 10 bytes returned */
  103. RET
  104. // Called with the address of gdt in rdi.
  105. // Load the gdt, then do a ret which will use the argument on the stack as
  106. // a segment #. This stuff is just crazy.
  107. // We have to push %rsi, then 16 bits(really!) of %rdi.
  108. .global gdtput
  109. gdtput:
  110. pushq %rsi
  111. movq %rdi, %rax
  112. pushw %ax
  113. mov %rsp, %rax
  114. lgdt (%rax)
  115. popw %ax
  116. popq %rax
  117. XORQ %rax, %rax
  118. MOVW %ax, %ds
  119. MOVW %ax, %es
  120. MOVW %ax, %fs
  121. MOVW %ax, %gs
  122. MOVW %ax, %ss
  123. POPQ %rax
  124. PUSHQ %rdx
  125. PUSHQ %rax
  126. lretq
  127. .global idtput
  128. idtput:
  129. // save %rdi, since we are going to modify it.
  130. pushq %rdi
  131. // Push the two quads onto the stack,
  132. // which arranges them in memory.
  133. pushq %rsi
  134. shlq $48, %rdi
  135. pushq %rdi
  136. movq %rsp, %rax
  137. addq $6, %rax
  138. lidt (%rax)
  139. popq %rdi
  140. popq %rsi
  141. popq %rdi
  142. RET
  143. .global trput
  144. trput:
  145. // panic
  146. mov 0, %rax
  147. //ltr %rdi
  148. RET
  149. /*
  150. * Read/write various system registers.
  151. */
  152. .global cr0get
  153. cr0get:
  154. MOVQ %cr0, %rax
  155. RET
  156. .global cr0put
  157. cr0put:
  158. MOVQ %rdi, %rax
  159. MOVQ %rax, %cr0
  160. RET
  161. .global cr2get
  162. cr2get:
  163. MOVQ %cr2, %rax
  164. RET
  165. .global cr3get
  166. cr3get:
  167. MOVQ %cr3, %rax
  168. RET
  169. .global cr3put
  170. cr3put:
  171. MOVQ %rdi, %rax
  172. MOVQ %rax, %CR3
  173. RET
  174. .global cr4get
  175. cr4get:
  176. MOVQ %CR4, %rax
  177. RET
  178. .global cr4put
  179. cr4put:
  180. MOVQ %rdi, %rax
  181. MOVQ %rax, %CR4
  182. RET
  183. .global read_bp
  184. read_bp:
  185. movq %rbp, %rax
  186. ret
  187. .global rdtsc
  188. rdtsc:
  189. RDTSC
  190. /* u64int rdtsc(void); */
  191. XCHGL %edx, %eax /* swap lo/hi, zero-extend */
  192. SHLQ $32, %rax /* hi<<32 */
  193. ORQ %rdx, %rax /* (hi<<32)|lo */
  194. RET
  195. .global rdmsr
  196. rdmsr:
  197. PUSHQ %rcx
  198. PUSHQ %rdx
  199. MOVL %edi, %ecx
  200. RDMSR
  201. /* u64int rdmsr(u32int); */
  202. XCHGL %edx, %eax /* swap lo/hi, zero-extend */
  203. SHLQ $32, %rax /* hi<<32 */
  204. ORQ %rdx, %rax /* (hi<<32)|lo */
  205. POPQ %rdx
  206. POPQ %rcx
  207. RET
  208. .global wrmsr
  209. wrmsr:
  210. PUSHQ %rax // do we need to do this?
  211. PUSHQ %rcx
  212. PUSHQ %rdx
  213. MOVL %edi, %ecx
  214. MOVL %esi, %eax
  215. MOVQ %rsi, %rdx
  216. SHRQ $32, %rdx
  217. WRMSR
  218. POPQ %rdx
  219. POPQ %rcx
  220. POPQ %rax
  221. RET
  222. .global invlpg
  223. invlpg:
  224. # MOVQ %rdi, va+0(FP)
  225. # INVLPG va+0(FP)
  226. RET
  227. .global wbinvd
  228. wbinvd:
  229. WBINVD
  230. RET
  231. /*
  232. * Serialisation.
  233. */
  234. .global lfence
  235. lfence:
  236. LFENCE
  237. RET
  238. .global mfence
  239. mfence:
  240. MFENCE
  241. RET
  242. .global sfence
  243. sfence:
  244. SFENCE
  245. RET
  246. /*
  247. * Note: CLI and STI are not serialising instructions.
  248. * Is that assumed anywhere?
  249. */
  250. .global splhi
  251. splhi:
  252. _splhi:
  253. PUSHFQ
  254. POPQ %rax
  255. TESTQ $If, %rax /* If - Interrupt Flag */
  256. JZ _alreadyhi /* use CMOVLEQ etc. here? */
  257. MOVQ %gs:0, %rax
  258. // Until we know we have a register we can trash, we have to
  259. // save and restore this one. Callee save
  260. PUSHQ %rbx
  261. MOVQ 8(%rsp), %rbx
  262. MOVQ %rbx, 8(%rax) /* save PC in m->splpc */
  263. POPQ %rbx
  264. _alreadyhi:
  265. CLI
  266. RET
  267. .global spllo
  268. spllo:
  269. _spllo:
  270. PUSHFQ
  271. POPQ %rax
  272. TESTQ $If, %rax /* If - Interrupt Flag */
  273. JNZ _alreadylo /* use CMOVLEQ etc. here? */
  274. MOVQ %gs:0, %rax
  275. MOVQ $0, 8(%rax) /* clear m->splpc */
  276. _alreadylo:
  277. STI
  278. RET
  279. .global splx
  280. splx:
  281. TESTQ $If, %rdi /* If - Interrupt Flag */
  282. JNZ _spllo
  283. JMP _splhi
  284. .global spldone
  285. spldone:
  286. RET
  287. .global islo
  288. islo:
  289. PUSHFQ
  290. POPQ %rax
  291. ANDQ $If, %rax /* If - Interrupt Flag */
  292. RET
  293. /*
  294. * Synchronisation
  295. */
  296. .global ainc
  297. ainc:
  298. MOVL $1, %eax
  299. LOCK; XADDL %eax, (%rdi)
  300. ADDL $1, %eax /* overflow if -ve or 0 */
  301. JG _return
  302. _trap:
  303. XORQ %rbx, %rbx
  304. MOVQ (%rbx), %rbx /* over under sideways down */
  305. _return:
  306. RET
  307. .global adec
  308. adec:
  309. MOVL $-1, %eax
  310. LOCK; XADDL %eax, (%rdi)
  311. SUBL $1, %eax /* underflow if -ve */
  312. JL _trap
  313. RET
  314. /*
  315. * Semaphores rely on negative values for the counter,
  316. * and don't have the same overflow/underflow conditions
  317. * as ainc/adec.
  318. */
  319. .global semainc
  320. semainc:
  321. MOVL $1, %eax
  322. LOCK; XADDL %eax, (%rdi)
  323. ADDL $1, %eax
  324. RET
  325. .global semadec
  326. semadec:
  327. MOVL $-1, %eax
  328. LOCK; XADDL %eax, (%rdi)
  329. SUBL $1, %eax
  330. RET
  331. .global tas32
  332. tas32:
  333. MOVL $0xdeaddead, %eax
  334. XCHGL %eax, (%rdi) /* */
  335. RET
  336. .global fas64
  337. fas64:
  338. MOVQ %rdi, %rax
  339. //LOCK; XCHGQ %eax, (%rdi) /* */
  340. RET
  341. // %rdi:&key, %esi:old, %edx:new
  342. // int cas32(void* %rdi, uint32_t %esi, uint32_t %edx);
  343. .global cas32
  344. cas32:
  345. movl %esi, %eax
  346. lock; cmpxchgl %edx, (%rdi)
  347. MOVL $1, %eax
  348. JNZ _cas32r0
  349. _cas32r1:
  350. RET
  351. _cas32r0:
  352. DECL %eax
  353. RET
  354. /*
  355. * Label consists of a stack pointer and a programme counter
  356. * 0(%rdi) is the SP, 8(%rdi) is the PC
  357. */
  358. .global gotolabel
  359. gotolabel:
  360. MOVQ %rdi, %rax
  361. MOVQ 0(%rdi), %rsp
  362. MOVQ (16+0*8)(%rdi), %rBX
  363. MOVQ (16+1*8)(%rdi), %rCX
  364. MOVQ (16+2*8)(%rdi), %rDX
  365. MOVQ (16+3*8)(%rdi), %rSI
  366. MOVQ (16+5*8)(%rdi), %rBP
  367. MOVQ (16+6*8)(%rdi), %r8
  368. MOVQ (16+7*8)(%rdi), %r9
  369. MOVQ (16+8*8)(%rdi), %r10
  370. MOVQ (16+9*8)(%rdi), %r11
  371. MOVQ (16+10*8)(%rdi), %r12
  372. MOVQ (16+11*8)(%rdi), %r13
  373. MOVQ (16+12*8)(%rdi), %r14
  374. MOVQ (16+13*8)(%rdi), %r15
  375. MOVQ (16+4*8)(%rdi), %rDI
  376. MOVQ 8(%rax), %rax /* put return PC on the stack */
  377. /* NOTE: replaces previous caller? */
  378. MOVQ %rax, (%rSP)
  379. MOVQ $1, %rax /* return 1 */
  380. RET
  381. /* save all registers on this stack, the save stack
  382. * in the label struct.
  383. */
  384. .global setlabel
  385. setlabel:
  386. // %rax is trashable.
  387. MOVQ 0(%rSP), %rax /* store return PC */
  388. MOVQ %rax, 8(%rdi)
  389. MOVQ %rBX, (16+0*8)(%rdi)
  390. MOVQ %rCX, (16+1*8)(%rdi)
  391. MOVQ %rDX, (16+2*8)(%rdi)
  392. MOVQ %rSI, (16+3*8)(%rdi)
  393. MOVQ %rDI, (16+4*8)(%rdi)
  394. MOVQ %rBP, (16+5*8)(%rdi)
  395. MOVQ %r8, (16+6*8)(%rdi)
  396. MOVQ %r9, (16+7*8)(%rdi)
  397. MOVQ %r10, (16+8*8)(%rdi)
  398. MOVQ %r11, (16+9*8)(%rdi)
  399. MOVQ %r12, (16+10*8)(%rdi)
  400. MOVQ %r13, (16+11*8)(%rdi)
  401. MOVQ %r14, (16+12*8)(%rdi)
  402. MOVQ %r15, (16+13*8)(%rdi)
  403. MOVQ %rSP, 0(%rdi) /* store SP */
  404. MOVL $0, %eax /* return 0 */
  405. RET
  406. .global hardhalt
  407. hardhalt:
  408. STI
  409. HLT
  410. RET
  411. .global _monitor
  412. _monitor:
  413. MOVQ %rdi, %rax /* linear address to monitor */
  414. XORQ %rcx, %rcx /* no optional extensions yet */
  415. XORQ %rdx, %rdx /* no optional hints yet */
  416. .byte 0x0f; .byte 0x01; .byte 0xc8 /* MONITOR */
  417. RET
  418. .global _mwait
  419. _mwait:
  420. movq %rdi, %rcx /* optional extensions */
  421. .byte 0x0f; .byte 0x01; .byte 0xc9 /* MWAIT */
  422. RET
  423. .global k10mwait
  424. k10mwait:
  425. k10mwloop:
  426. MOVQ %rdi,%rcx
  427. MOVQ (%rcx), %rax
  428. CMPQ $0, %rax
  429. JNE k10mwdone
  430. MOVQ %rdi, %rax /* linear address to monitor */
  431. XORQ %rcx, %rcx /* no optional extensions yet */
  432. XORQ %rdx, %rdx /* no optional hints yet */
  433. .byte 0x0f; .byte 0x01; .byte 0xc8 /* MONITOR */
  434. MOVQ %rdi, %rcx
  435. MOVQ 0(%rcx), %rax
  436. CMPQ $0, %rax
  437. JNE k10mwdone
  438. XORQ %rcx, %rcx /* optional extensions */
  439. .byte 0x0f; .byte 0x01; .byte 0xc9 /* MWAIT */
  440. JMP k10mwloop
  441. k10mwdone:
  442. RET
  443. .global machp
  444. machp:
  445. movq %gs:0, %rax
  446. ret
  447. .global externup
  448. externup:
  449. movq %gs:40, %rax
  450. ret
  451. /* not needed.
  452. .global mul64fract
  453. mul64fract:
  454. MOVQ %rdi, %rax
  455. MULQ %rsi / * a*b *
  456. SHRQ $32, %rax:DX
  457. MOVQ %rax, (%rdi)
  458. RET
  459. */
  460. ///*
  461. // * Testing.
  462. // */
  463. //.global ud2
  464. ud2:
  465. // BYTE $0x0f; BYTE $0x0b
  466. // RET
  467. //