l64v.S 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  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. * x86 convention is to use %rbp as the frame pointer,
  248. * so we just return that register
  249. */
  250. .global stackframe
  251. stackframe:
  252. movq %rbp, %rax
  253. retq
  254. /*
  255. * disable interrupts,
  256. * return old flags for splx()
  257. */
  258. .global splhi
  259. splhi:
  260. _splhi:
  261. PUSHFQ
  262. POPQ %rax
  263. TESTQ $If, %rax /* If - Interrupt Flag */
  264. JZ _alreadyhi
  265. movq 0(%rsp), %rdi
  266. movq %rdi, %gs:8 /* callerpc to m->splpc */
  267. _alreadyhi:
  268. CLI
  269. RET
  270. /*
  271. * enable interrupts,
  272. * return old flags for splx()
  273. */
  274. .global spllo
  275. spllo:
  276. _spllo:
  277. PUSHFQ
  278. POPQ %rax
  279. TESTQ $If, %rax /* If - Interrupt Flag */
  280. JNZ _alreadylo
  281. MOVQ $0, %gs:8 /* clear m->splpc */
  282. _alreadylo:
  283. STI
  284. RET
  285. /*
  286. * undo splhi or spllo,
  287. * %rdi has flags before splhi or spllo
  288. */
  289. .global splx
  290. splx:
  291. TESTQ $If, %rdi /* If - Interrupt Flag */
  292. JNZ _spllo /* If set: enable */
  293. JMP _splhi /* else: disable */
  294. .global spldone
  295. spldone:
  296. RET
  297. .global islo
  298. islo:
  299. PUSHFQ
  300. POPQ %rax
  301. ANDQ $If, %rax /* If - Interrupt Flag */
  302. RET
  303. .global infected_with_std
  304. infected_with_std:
  305. PUSHFQ
  306. POPQ %rax
  307. ANDQ $Df, %rax /* Df - Direction Flag */
  308. RET
  309. .global disinfect_std
  310. disinfect_std:
  311. CLD
  312. RET
  313. /*
  314. * Synchronisation
  315. */
  316. .global ainc
  317. ainc:
  318. MOVL $1, %eax
  319. LOCK; XADDL %eax, (%rdi)
  320. ADDL $1, %eax /* overflow if -ve or 0 */
  321. JG _return
  322. _trap:
  323. XORQ %rbx, %rbx
  324. MOVQ (%rbx), %rbx /* over under sideways down */
  325. _return:
  326. RET
  327. .global adec
  328. adec:
  329. MOVL $-1, %eax
  330. LOCK; XADDL %eax, (%rdi)
  331. SUBL $1, %eax /* underflow if -ve */
  332. JL _trap
  333. RET
  334. /*
  335. * Semaphores rely on negative values for the counter,
  336. * and don't have the same overflow/underflow conditions
  337. * as ainc/adec.
  338. */
  339. .global semainc
  340. semainc:
  341. MOVL $1, %eax
  342. LOCK; XADDL %eax, (%rdi)
  343. ADDL $1, %eax
  344. RET
  345. .global semadec
  346. semadec:
  347. MOVL $-1, %eax
  348. LOCK; XADDL %eax, (%rdi)
  349. SUBL $1, %eax
  350. RET
  351. .global tas32
  352. tas32:
  353. MOVL $0xdeaddead, %eax
  354. XCHGL %eax, (%rdi) /* */
  355. RET
  356. .global fas64
  357. fas64:
  358. MOVQ %rdi, %rax
  359. //LOCK; XCHGQ %eax, (%rdi) /* */
  360. RET
  361. // %rdi:&key, %esi:old, %edx:new
  362. // int cas32(void* %rdi, uint32_t %esi, uint32_t %edx);
  363. .global cas32
  364. cas32:
  365. movl %esi, %eax
  366. lock; cmpxchgl %edx, (%rdi)
  367. MOVL $1, %eax
  368. JNZ _cas32r0
  369. _cas32r1:
  370. RET
  371. _cas32r0:
  372. DECL %eax
  373. RET
  374. /*
  375. * Label consists of a stack pointer and a programme counter
  376. * 0(%rdi) is the SP, 8(%rdi) is the PC
  377. */
  378. .global gotolabel
  379. gotolabel:
  380. MOVQ %rdi, %rax
  381. MOVQ 0(%rdi), %rsp
  382. // Can't kill this quite yet.
  383. MOVQ (16+5*8)(%rdi), %rBP
  384. MOVQ 8(%rax), %rax /* put return PC on the stack */
  385. /* NOTE: replaces previous caller? */
  386. MOVQ %rax, (%rSP)
  387. MOVQ $1, %rax /* return 1 */
  388. RET
  389. /* save all registers on this stack, the save stack
  390. * in the label struct.
  391. */
  392. .global slim_setlabel
  393. slim_setlabel:
  394. // %rax is trashable.
  395. MOVQ 0(%rSP), %rax /* store return PC */
  396. MOVQ %rax, 8(%rdi)
  397. // Can't kill this quite yet.
  398. MOVQ %rBP, (16+5*8)(%rdi)
  399. MOVQ %rSP, 0(%rdi) /* store SP */
  400. MOVL $0, %eax /* return 0 */
  401. RET
  402. .global hardhalt
  403. hardhalt:
  404. STI
  405. HLT
  406. RET
  407. .global _monitor
  408. _monitor:
  409. MOVQ %rdi, %rax /* linear address to monitor */
  410. XORQ %rcx, %rcx /* no optional extensions yet */
  411. XORQ %rdx, %rdx /* no optional hints yet */
  412. .byte 0x0f; .byte 0x01; .byte 0xc8 /* MONITOR */
  413. RET
  414. .global _mwait
  415. _mwait:
  416. movq %rdi, %rcx /* optional extensions */
  417. .byte 0x0f; .byte 0x01; .byte 0xc9 /* MWAIT */
  418. RET
  419. .global k10mwait
  420. k10mwait:
  421. k10mwloop:
  422. MOVQ %rdi,%rcx
  423. MOVQ (%rcx), %rax
  424. CMPQ $0, %rax
  425. JNE k10mwdone
  426. MOVQ %rdi, %rax /* linear address to monitor */
  427. XORQ %rcx, %rcx /* no optional extensions yet */
  428. XORQ %rdx, %rdx /* no optional hints yet */
  429. .byte 0x0f; .byte 0x01; .byte 0xc8 /* MONITOR */
  430. MOVQ %rdi, %rcx
  431. MOVQ 0(%rcx), %rax
  432. CMPQ $0, %rax
  433. JNE k10mwdone
  434. XORQ %rcx, %rcx /* optional extensions */
  435. .byte 0x0f; .byte 0x01; .byte 0xc9 /* MWAIT */
  436. JMP k10mwloop
  437. k10mwdone:
  438. RET
  439. .global machp
  440. machp:
  441. pushfq
  442. popq %rax
  443. testq $If, %rax
  444. jnz _machp_bad
  445. _machp_out:
  446. movq %gs:0, %rax
  447. ret
  448. _machp_bad:
  449. pushq %rbp
  450. movq %rsp, %rbp
  451. callq machp_bad
  452. popq %rbp
  453. jmp _machp_out
  454. .global externup
  455. externup:
  456. movq %gs:40, %rax
  457. ret
  458. /* not needed.
  459. .global mul64fract
  460. mul64fract:
  461. MOVQ %rdi, %rax
  462. MULQ %rsi / * a*b *
  463. SHRQ $32, %rax:DX
  464. MOVQ %rax, (%rdi)
  465. RET
  466. */
  467. ///*
  468. // * Testing.
  469. // */
  470. //.global ud2
  471. ud2:
  472. // BYTE $0x0f; BYTE $0x0b
  473. // RET
  474. //