mother64.asm 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. %include "defs.asm"
  2. ; ----------------------------- MOTHER64.ASM -----------------------------
  3. ; Author: Agner Fog
  4. ; Date created: 1998
  5. ; Last modified: 2013-09-11
  6. ; Source URL: www.agner.org/optimize
  7. ; Project: asmlib.zip
  8. ; Language: assembly, NASM/YASM syntax, 64 bit
  9. ; Description:
  10. ; Mother-of-All random number generator by Agner Fog
  11. ; 64-bit mode version for x86-64 compatible microprocessors.
  12. ;
  13. ; This is a multiply-with-carry type of random number generator
  14. ; invented by George Marsaglia. The algorithm is:
  15. ; S = 2111111111*X[n-4] + 1492*X[n-3] + 1776*X[n-2] + 5115*X[n-1] + C
  16. ; X[n] = S modulo 2^32
  17. ; C = floor(S / 2^32)
  18. ;
  19. ; C++ prototypes:
  20. ; extern "C" void MotRandomInit(void * Pthis, int seed); // Initialization
  21. ; extern "C" int MotIRandom(void * Pthis, int min, int max); // Get integer random number in desired interval
  22. ; extern "C" double MotRandom(void * Pthis); // Get floating point random number
  23. ; extern "C" unsigned int MotBRandom(void * Pthis); // Output random bits
  24. ;
  25. ; Copyright (c) 2008-2013 GNU General Public License www.gnu.org/licenses
  26. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  27. default rel
  28. ; structure definition and constants:
  29. %INCLUDE "randomah.asi"
  30. ; publics:
  31. global MotherBRandom, MotBRandom, ?Windows_MotBRandom
  32. global MotherRandom, MotRandom, MotherIRandom, MotIRandom
  33. global MotherRandomInit, MotRandomInit
  34. section .data
  35. align 16
  36. ; Data for single instance of random number generator
  37. MotherInstance: ISTRUC CRandomMotherA
  38. IEND
  39. ; Size of structure
  40. MotherSize equ $-MotherInstance
  41. SECTION .CODE ALIGN=16 ; code segment
  42. ; Single threaded version:
  43. ; extern "C" unsigned int MotherBRandom(); // Output random bits
  44. MotherBRandom: ; PROC ; entry for both Windows and Linux call
  45. lea rcx, [MotherInstance] ; Point to instance
  46. jmp ?Windows_MotBRandom
  47. ;MotherBRandom ENDP
  48. ; Thread-safe version:
  49. ; extern "C" unsigned int MotBRandom(void * Pthis); // Output random bits
  50. MotBRandom: ; PROC
  51. %IFDEF UNIX
  52. mov rcx, rdi ; translate calling convention
  53. %ENDIF
  54. ?Windows_MotBRandom:
  55. and rcx, -16 ; align
  56. movdqa xmm1, oword [rcx+CRandomMotherA.M3] ; load M3,M2,M1,M0
  57. mov eax, [rcx+CRandomMotherA.M0] ; Retrieve previous random number
  58. movdqa xmm2, xmm1 ; copy
  59. movdqa xmm3, oword [rcx+CRandomMotherA.MF3] ; factors
  60. psrlq xmm2, 32 ; move M2,M0 down
  61. movq qword [rcx+CRandomMotherA.M4], xmm1 ; M4=M3, M3=M2
  62. movhps qword [rcx+CRandomMotherA.M2], xmm1 ; M2=M1, M1=M0
  63. pmuludq xmm1, xmm3 ; M3*MF3, M1*MF1
  64. psrlq xmm3, 32 ; move MF2,MF0 down
  65. pmuludq xmm2, xmm3 ; M2*MF2, M0*MF0
  66. paddq xmm1, xmm2 ; P2+P3, P0+P1
  67. movhlps xmm2, xmm1 ; Get high qword
  68. paddq xmm1, xmm2 ; P0+P1+P2+P3
  69. paddq xmm1, oword [rcx+CRandomMotherA.MC] ; +carry
  70. movq qword [rcx+CRandomMotherA.M0], xmm1 ; Store new M0 and carry
  71. ; convert to double precision float
  72. psllq xmm1, 32 ; Discard carry bits
  73. psrlq xmm1, 12 ; Get bits into mantissa position
  74. por xmm1, oword [rcx+CRandomMotherA.one] ; Add exponent bits to get number in interval [1,2)
  75. movq [rcx+CRandomMotherA.RanP1], xmm1 ; Store floating point number
  76. ret
  77. ;MotBRandom ENDP
  78. ; Single threaded version:
  79. ; extern "C" unsigned int MotherRandom(); // Get floating point random number
  80. MotherRandom:
  81. %IFDEF UNIX
  82. lea rdi, [MotherInstance] ; Point to instance
  83. %ENDIF
  84. %IFDEF WINDOWS
  85. lea rcx, [MotherInstance] ; Point to instance
  86. %ENDIF
  87. ; Thread-safe version:
  88. ; extern "C" double MotRandom(void * Pthis); // Get floating point random number
  89. MotRandom:
  90. %IFDEF UNIX
  91. mov rcx, rdi ; translate calling convention
  92. %ENDIF
  93. and rcx, -16 ; align
  94. ; get previously prepared random number
  95. movsd xmm0, [rcx+CRandomMotherA.RanP1]
  96. subsd xmm0, [rcx+CRandomMotherA.one]
  97. ; make new random number ready for next time
  98. call ?Windows_MotBRandom
  99. ret
  100. ;MotherRandom ENDP
  101. ; Single threaded version:
  102. ; extern "C" unsigned int MotherIRandom(int min, int max); // Get integer random number in desired interval
  103. MotherIRandom: ; PROC
  104. %IFDEF UNIX
  105. mov r8d, esi ; max
  106. mov edx, edi ; min
  107. lea rcx, [MotherInstance] ; Pthis = point to instance
  108. jmp ?Windows_MotIRandom
  109. %ENDIF
  110. %IFDEF WINDOWS
  111. mov r8d, edx ; max
  112. mov edx, ecx ; min
  113. lea rcx, [MotherInstance] ; Pthis = point to instance
  114. jmp ?Windows_MotIRandom
  115. %ENDIF
  116. ; MotherIRandom ENDP
  117. ; Thread-safe version:
  118. ; extern "C" int MotIRandom(void * Pthis, int min, int max); // Get integer random number in desired interval
  119. MotIRandom:
  120. %IFDEF UNIX
  121. ; translate calling convention
  122. mov r8d, edx ; max
  123. mov edx, esi ; min
  124. mov rcx, rdi ; Pthis
  125. %ENDIF
  126. ?Windows_MotIRandom: ; LABEL NEAR ; entry for Windows call
  127. and rcx, -16 ; align
  128. push r8
  129. push rdx
  130. call ?Windows_MotBRandom ; make random number
  131. pop rcx ; min
  132. pop r8 ; max
  133. sub r8d, ecx
  134. js short rerror ; max < min
  135. inc r8d ; interval = max - min + 1
  136. mul r8d ; multiply random number eax by interval and truncate
  137. lea eax, [rdx+rcx] ; add min to interval*BRandom >> 32
  138. ret ; ret 8 if not _cdecl calling
  139. rerror: mov eax, 80000000h ; error exit
  140. ret ; ret 8 if not _cdecl calling
  141. ;MotIRandom ENDP
  142. ; Single threaded version:
  143. ; extern "C" unsigned int MotherRandomInit(int seed); // Initialization
  144. MotherRandomInit: ; PROC
  145. %IFDEF UNIX
  146. mov edx, edi ; seed
  147. lea rcx, [MotherInstance] ; Pthis = point to instance
  148. jmp ?Windows_MotRandomInit
  149. %ENDIF
  150. %IFDEF WINDOWS
  151. mov edx, ecx ; seed
  152. lea rcx, [MotherInstance] ; Pthis = point to instance
  153. jmp ?Windows_MotRandomInit
  154. %ENDIF
  155. ;MotherRandomInit ENDP
  156. ; Thread-safe version:
  157. ; extern "C" void MotRandomInit(void * Pthis, int seed); // Initialization
  158. MotRandomInit: ; PROC
  159. %IFDEF UNIX
  160. ; translate calling convention
  161. mov edx, esi ; seed
  162. mov rcx, rdi ; Pthis
  163. %ENDIF
  164. ?Windows_MotRandomInit: ; LABEL NEAR ; entry for Windows call
  165. and rcx, -16 ; align
  166. ; clear my buffer
  167. push rdi
  168. push rcx
  169. mov rdi, rcx ; Pthis
  170. add rdi, 16
  171. mov ecx, (MotherSize - 16) / 4
  172. xor eax, eax
  173. cld
  174. rep stosd
  175. pop rcx
  176. ; insert constants
  177. mov dword [rcx+CRandomMotherA.one+4], 3FF00000H ; high dword of 1.0
  178. mov dword [rcx+CRandomMotherA.MF0], 5115 ; factors
  179. mov dword [rcx+CRandomMotherA.MF1], 1776
  180. mov dword [rcx+CRandomMotherA.MF2], 1492
  181. mov dword [rcx+CRandomMotherA.MF3], 2111111111
  182. ; initialize from seed
  183. mov eax, edx ; seed
  184. ; make random numbers and put them into buffer
  185. mov edx, 29943829
  186. imul eax, edx
  187. dec eax
  188. mov [rcx+CRandomMotherA.M0], eax
  189. imul eax, edx
  190. dec eax
  191. mov [rcx+CRandomMotherA.M1], eax
  192. imul eax, edx
  193. dec eax
  194. mov [rcx+CRandomMotherA.M2], eax
  195. imul eax, edx
  196. dec eax
  197. mov [rcx+CRandomMotherA.M3], eax
  198. imul eax, edx
  199. dec eax
  200. mov [rcx+CRandomMotherA.MC], eax
  201. ; randomize some more
  202. mov edi, 20 ; loop counter
  203. r90: call ?Windows_MotBRandom ; (rcx and rdi unchanged)
  204. dec edi
  205. jnz r90
  206. pop rdi
  207. ret
  208. ;MotRandomInit ENDP
  209. ; END