executeProgram-win64.asm 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. ;# Copyright (c) 2018 tevador
  2. ;#
  3. ;# This file is part of RandomX.
  4. ;#
  5. ;# RandomX is free software: you can redistribute it and/or modify
  6. ;# it under the terms of the GNU General Public License as published by
  7. ;# the Free Software Foundation, either version 3 of the License, or
  8. ;# (at your option) any later version.
  9. ;#
  10. ;# RandomX is distributed in the hope that it will be useful,
  11. ;# but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ;# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ;# GNU General Public License for more details.
  14. ;#
  15. ;# You should have received a copy of the GNU General Public License
  16. ;# along with RandomX. If not, see<http://www.gnu.org/licenses/>.
  17. _RANDOMX_EXECUTE_PROGRAM SEGMENT PAGE READ EXECUTE
  18. PUBLIC executeProgram
  19. executeProgram PROC
  20. ; REGISTER ALLOCATION:
  21. ; rax -> temporary
  22. ; rbx -> beginning of VM stack
  23. ; rcx -> temporary
  24. ; rdx -> temporary
  25. ; rsi -> convertible_t& scratchpad
  26. ; rdi -> "mx"
  27. ; rbp -> "ic"
  28. ; rsp -> end of VM stack
  29. ; r8 -> "r0"
  30. ; r9 -> "r1"
  31. ; r10 -> "r2"
  32. ; r11 -> "r3"
  33. ; r12 -> "r4"
  34. ; r13 -> "r5"
  35. ; r14 -> "r6"
  36. ; r15 -> "r7"
  37. ; xmm0 -> temporary
  38. ; xmm1 -> temporary
  39. ; xmm2 -> "f2"
  40. ; xmm3 -> "f3"
  41. ; xmm4 -> "f4"
  42. ; xmm5 -> "f5"
  43. ; xmm6 -> "f6"
  44. ; xmm7 -> "f7"
  45. ; xmm8 -> "f0"
  46. ; xmm9 -> "f1"
  47. ; xmm10 -> absolute value mask
  48. ; STACK STRUCTURE:
  49. ; |
  50. ; |
  51. ; | saved registers
  52. ; |
  53. ; v
  54. ; [rbx+8] RegisterFile& registerFile
  55. ; [rbx+0] uint8_t* dataset
  56. ; |
  57. ; |
  58. ; | VM stack
  59. ; |
  60. ; v
  61. ; [rsp] last element of VM stack
  62. ; store callee-saved registers
  63. push rbx
  64. push rbp
  65. push rdi
  66. push rsi
  67. push r12
  68. push r13
  69. push r14
  70. push r15
  71. sub rsp, 80
  72. movdqu xmmword ptr [rsp+64], xmm6
  73. movdqu xmmword ptr [rsp+48], xmm7
  74. movdqu xmmword ptr [rsp+32], xmm8
  75. movdqu xmmword ptr [rsp+16], xmm9
  76. movdqu xmmword ptr [rsp+0], xmm10
  77. ; function arguments
  78. push rcx ; RegisterFile& registerFile
  79. mov edi, dword ptr [rdx] ; "mx"
  80. mov rax, qword ptr [rdx+8] ; uint8_t* dataset
  81. push rax
  82. mov rsi, r8 ; convertible_t* scratchpad
  83. mov rbx, rsp ; beginning of VM stack
  84. mov ebp, 1048577 ; number of VM instructions to execute + 1
  85. xorps xmm10, xmm10
  86. cmpeqpd xmm10, xmm10
  87. psrlq xmm10, 1 ; mask for absolute value = 0x7fffffffffffffff7fffffffffffffff
  88. ; reset rounding mode
  89. mov dword ptr [rsp-8], 40896
  90. ldmxcsr dword ptr [rsp-8]
  91. ; load integer registers
  92. mov r8, qword ptr [rcx+0]
  93. mov r9, qword ptr [rcx+8]
  94. mov r10, qword ptr [rcx+16]
  95. mov r11, qword ptr [rcx+24]
  96. mov r12, qword ptr [rcx+32]
  97. mov r13, qword ptr [rcx+40]
  98. mov r14, qword ptr [rcx+48]
  99. mov r15, qword ptr [rcx+56]
  100. ; load register f0 hi, lo
  101. xorps xmm8, xmm8
  102. cvtsi2sd xmm8, qword ptr [rcx+72]
  103. pslldq xmm8, 8
  104. cvtsi2sd xmm8, qword ptr [rcx+64]
  105. ; load register f1 hi, lo
  106. xorps xmm9, xmm9
  107. cvtsi2sd xmm9, qword ptr [rcx+88]
  108. pslldq xmm9, 8
  109. cvtsi2sd xmm9, qword ptr [rcx+80]
  110. ; load register f2 hi, lo
  111. xorps xmm2, xmm2
  112. cvtsi2sd xmm2, qword ptr [rcx+104]
  113. pslldq xmm2, 8
  114. cvtsi2sd xmm2, qword ptr [rcx+96]
  115. ; load register f3 hi, lo
  116. xorps xmm3, xmm3
  117. cvtsi2sd xmm3, qword ptr [rcx+120]
  118. pslldq xmm3, 8
  119. cvtsi2sd xmm3, qword ptr [rcx+112]
  120. lea rcx, [rcx+64]
  121. ; load register f4 hi, lo
  122. xorps xmm4, xmm4
  123. cvtsi2sd xmm4, qword ptr [rcx+72]
  124. pslldq xmm4, 8
  125. cvtsi2sd xmm4, qword ptr [rcx+64]
  126. ; load register f5 hi, lo
  127. xorps xmm5, xmm5
  128. cvtsi2sd xmm5, qword ptr [rcx+88]
  129. pslldq xmm5, 8
  130. cvtsi2sd xmm5, qword ptr [rcx+80]
  131. ; load register f6 hi, lo
  132. xorps xmm6, xmm6
  133. cvtsi2sd xmm6, qword ptr [rcx+104]
  134. pslldq xmm6, 8
  135. cvtsi2sd xmm6, qword ptr [rcx+96]
  136. ; load register f7 hi, lo
  137. xorps xmm7, xmm7
  138. cvtsi2sd xmm7, qword ptr [rcx+120]
  139. pslldq xmm7, 8
  140. cvtsi2sd xmm7, qword ptr [rcx+112]
  141. ; program body
  142. include program.inc
  143. rx_finish:
  144. ; unroll the stack
  145. mov rsp, rbx
  146. ; save VM register values
  147. pop rcx
  148. pop rcx
  149. mov qword ptr [rcx+0], r8
  150. mov qword ptr [rcx+8], r9
  151. mov qword ptr [rcx+16], r10
  152. mov qword ptr [rcx+24], r11
  153. mov qword ptr [rcx+32], r12
  154. mov qword ptr [rcx+40], r13
  155. mov qword ptr [rcx+48], r14
  156. mov qword ptr [rcx+56], r15
  157. movdqa xmmword ptr [rcx+64], xmm8
  158. movdqa xmmword ptr [rcx+80], xmm9
  159. movdqa xmmword ptr [rcx+96], xmm2
  160. movdqa xmmword ptr [rcx+112], xmm3
  161. lea rcx, [rcx+64]
  162. movdqa xmmword ptr [rcx+64], xmm4
  163. movdqa xmmword ptr [rcx+80], xmm5
  164. movdqa xmmword ptr [rcx+96], xmm6
  165. movdqa xmmword ptr [rcx+112], xmm7
  166. ; load callee-saved registers
  167. movdqu xmm10, xmmword ptr [rsp]
  168. movdqu xmm9, xmmword ptr [rsp+16]
  169. movdqu xmm8, xmmword ptr [rsp+32]
  170. movdqu xmm7, xmmword ptr [rsp+48]
  171. movdqu xmm6, xmmword ptr [rsp+64]
  172. add rsp, 80
  173. pop r15
  174. pop r14
  175. pop r13
  176. pop r12
  177. pop rsi
  178. pop rdi
  179. pop rbp
  180. pop rbx
  181. ; return
  182. ret
  183. TransformAddress MACRO reg32, reg64
  184. ;# Transforms the address in the register so that the transformed address
  185. ;# lies in a different cache line than the original address (mod 2^N).
  186. ;# This is done to prevent a load-store dependency.
  187. ;# There are 3 different transformations that can be used: x -> 9*x+C, x -> x+C, x -> x^C
  188. lea reg32, [reg64+reg64*8+127] ;# C = -119 -110 -101 -92 -83 -74 -65 -55 -46 -37 -28 -19 -10 -1 9 18 27 36 45 54 63 73 82 91 100 109 118 127
  189. ;lea reg32, [reg64-128] ;# C = all except -7 to +7
  190. ;xor reg32, -8 ;# C = all except 0 to 7
  191. ENDM
  192. ReadMemoryRandom MACRO spmask, float
  193. ;# IN ecx = random 32-bit address
  194. ;# OUT rax = 64-bit integer return value
  195. ;# OUT xmm0 = 128-bit floating point return value
  196. ;# GLOBAL rbp = "ic" number of instructions until the end of the program
  197. ;# GLOBAL rbx = address of the dataset address
  198. ;# GLOBAL rsi = address of the scratchpad
  199. ;# GLOBAL rdi = low 32 bits = "mx", high 32 bits = "ma"
  200. ;# MODIFY rcx, rdx
  201. LOCAL L_prefetch_read, L_return
  202. test ebp, 63
  203. jz short L_prefetch_read ;# "ic" divisible by 64 -> prefetch + read
  204. xor rdi, rcx ;# randomize "mx"
  205. L_return:
  206. and ecx, spmask ;# limit address to the specified scratchpad size
  207. IF float
  208. cvtdq2pd xmm0, qword ptr [rsi+rcx*8]
  209. ELSE
  210. mov rax, qword ptr [rsi+rcx*8]
  211. ENDIF
  212. ret
  213. L_prefetch_read:
  214. ; prefetch cacheline "mx"
  215. mov rax, qword ptr [rbx] ;# load the dataset address
  216. and rdi, -64 ;# align "mx" to the start of a cache line
  217. mov edx, edi ;# edx = mx
  218. prefetchnta byte ptr [rax+rdx]
  219. ; read cacheline "ma"
  220. ror rdi, 32 ;# swap "ma" and "mx"
  221. mov edx, edi ;# edx = ma
  222. push rcx
  223. TransformAddress ecx, rcx ;# TransformAddress function
  224. and ecx, spmask-7 ;# limit address to the specified scratchpad size aligned to multiple of 8
  225. call rx_read_dataset
  226. pop rcx
  227. jmp short L_return
  228. ENDM
  229. ALIGN 64
  230. rx_readint_l1:
  231. ReadMemoryRandom 2047, 0
  232. ALIGN 64
  233. rx_readint_l2:
  234. ReadMemoryRandom 32767, 0
  235. ALIGN 64
  236. rx_readfloat_l1:
  237. ReadMemoryRandom 2047, 1
  238. ALIGN 64
  239. rx_readfloat_l2:
  240. ReadMemoryRandom 32767, 1
  241. ALIGN 64
  242. rx_read_dataset:
  243. ;# IN rax = dataset address
  244. ;# IN ecx = scratchpad index - must be divisible by 8
  245. ;# IN edx = dataset index - must be divisible by 64
  246. ;# GLOBAL rsi = address of the scratchpad
  247. ;# MODIFY rax, rcx, rdx
  248. lea rcx, [rsi+rcx*8] ;# scratchpad cache line
  249. lea rax, [rax+rdx] ;# dataset cache line
  250. mov rdx, qword ptr [rax+0] ;# load first dataset quadword (prefetched into the cache by now)
  251. xor qword ptr [rcx+0], rdx ;# XOR the dataset item with a scratchpad item, repeat for the rest of the cacheline
  252. mov rdx, qword ptr [rax+8]
  253. xor qword ptr [rcx+8], rdx
  254. mov rdx, qword ptr [rax+16]
  255. xor qword ptr [rcx+16], rdx
  256. mov rdx, qword ptr [rax+24]
  257. xor qword ptr [rcx+24], rdx
  258. mov rdx, qword ptr [rax+32]
  259. xor qword ptr [rcx+32], rdx
  260. mov rdx, qword ptr [rax+40]
  261. xor qword ptr [rcx+40], rdx
  262. mov rdx, qword ptr [rax+48]
  263. xor qword ptr [rcx+48], rdx
  264. mov rdx, qword ptr [rax+56]
  265. xor qword ptr [rcx+56], rdx
  266. ret
  267. executeProgram ENDP
  268. _RANDOMX_EXECUTE_PROGRAM ENDS
  269. END