Last active
March 26, 2020 17:43
-
-
Save qtxie/f69b60e6011d02e49405fd6590f88640 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Red/System [] | |
int64!: alias struct! [ | |
low [integer!] | |
high [integer!] | |
] | |
sub64: func [ ;-- result: a - b | |
a [int64! value] | |
b [int64! value] | |
result [int64!] | |
][ | |
;-- mov eax, DWORD PTR [ebp+8] | |
;-- mov edx, DWORD PTR [ebp+12] | |
;-- sub eax, DWORD PTR [ebp+16] | |
;-- sbb edx, DWORD PTR [ebp+20] | |
;-- mov ecx, DWORD PTR [ebp+24] | |
;-- mov DWORD PTR [ecx], eax | |
;-- mov DWORD PTR [ecx+4], edx | |
#inline #{8B45088B550C2B45101B55148B4D188901895104} | |
] | |
add64: func [ | |
a [int64! value] | |
b [int64! value] | |
result [int64!] | |
][ | |
;-- mov eax, DWORD PTR [ebp+16] | |
;-- mov edx, DWORD PTR [ebp+20] | |
;-- add eax, DWORD PTR [ebp+8] | |
;-- adc edx, DWORD PTR [ebp+12] | |
;-- mov ecx, DWORD PTR [ebp+24] | |
;-- mov DWORD PTR [ecx], eax | |
;-- mov DWORD PTR [ecx+4], edx | |
#inline #{8B45108B551403450813550C8B4D188901895104} | |
] | |
mul64: func [ | |
a [int64! value] | |
b [int64! value] | |
result [int64!] | |
][ | |
;-- push ebx | |
;-- mov eax, DWORD PTR [ebp+8] | |
;-- mov edx, DWORD PTR [ebp+16] | |
;-- mov ecx, edx | |
;-- imul ecx, DWORD PTR [ebp+12] | |
;-- mov ebx, eax | |
;-- imul ebx, DWORD PTR [ebp+20] | |
;-- add ecx, ebx | |
;-- mul edx | |
;-- add edx, ecx | |
;-- mov ecx, DWORD PTR [ebp+24] | |
;-- mov DWORD PTR [ecx], eax | |
;-- mov DWORD PTR [ecx+4], edx | |
;-- pop ebx | |
#inline #{538B45088B551089D10FAF4D0C89C30FAF5D1401D9F7E201CA8B4D1889018951045B} | |
] | |
div64: func [ | |
a [int64! value] | |
b [int64! value] | |
result [int64!] | |
][ | |
;; [ebp + 8] stack address of dividend (a) | |
;; [ebp + 16] stack address of divisor (b) | |
; push edi | |
; push esi | |
; push ebx | |
;; Determine sign of the result (edi = 0 if result is positive, non-zero | |
;; otherwise) and make operands positive. | |
; xor edi,edi ; result sign assumed positive | |
; mov eax, dword ptr [ebp + 12] ; hi word of a | |
; or eax,eax ; test to see if signed | |
; jge short L1 ; skip rest if a is already positive | |
; inc edi ; complement result sign flag | |
; mov edx,dword ptr [ebp + 8] ; lo word of a | |
; neg eax ; make a positive | |
; neg edx | |
; sbb eax,0 | |
; mov dword ptr [ebp + 12],eax ; save positive value | |
; mov dword ptr [ebp + 8],edx | |
;L1: | |
; mov eax,dword ptr [ebp + 20] ; hi word of b | |
; or eax,eax ; test to see if signed | |
; jge short L2 ; skip rest if b is already positive | |
; inc edi ; complement the result sign flag | |
; mov edx,dword ptr [ebp + 16] ; lo word of b | |
; neg eax ; make b positive | |
; neg edx | |
; sbb eax,0 | |
; mov dword ptr [ebp + 20],eax ; save positive value | |
; mov dword ptr [ebp + 16],edx | |
;L2: | |
;; | |
;; Now do the divide. First look to see if the divisor is less than 4194304K. | |
;; If so, then we can use a simple algorithm with word divides, otherwise | |
;; things get a little more complex. | |
;; | |
;; NOTE - eax currently contains the high order word of DVSR | |
;; | |
; or eax,eax ; check to see if divisor < 4194304K | |
; jnz short L3 ; nope, gotta do this the hard way | |
; mov ecx,dword ptr [ebp + 16] ; load divisor | |
; mov eax,dword ptr [ebp + 12] ; load high word of dividend | |
; xor edx,edx | |
; div ecx ; eax <- high order bits of quotient | |
; mov ebx,eax ; save high bits of quotient | |
; mov eax,dword ptr [ebp + 8] ; edx:eax <- remainder:lo word of dividend | |
; div ecx ; eax <- low order bits of quotient | |
; mov edx,ebx ; edx:eax <- quotient | |
; jmp short L4 ; set sign, restore stack and return | |
;; | |
;; Here we do it the hard way. Remember, eax contains the high word of DVSR | |
;; | |
;L3: | |
; mov ebx,eax ; ebx:ecx <- divisor | |
; mov ecx,dword ptr [ebp + 16] | |
; mov edx,dword ptr [ebp + 12] ; edx:eax <- dividend | |
; mov eax,dword ptr [ebp + 8] | |
;L5: | |
; shr ebx,1 ; shift divisor right one bit | |
; rcr ecx,1 | |
; shr edx,1 ; shift dividend right one bit | |
; rcr eax,1 | |
; or ebx,ebx | |
; jnz short L5 ; loop until divisor < 4194304K | |
; div ecx ; now divide, ignore remainder | |
; mov esi,eax ; save quotient | |
;; | |
;; We may be off by one, so to check, we will multiply the quotient | |
;; by the divisor and check the result against the orignal dividend | |
;; Note that we must also check for overflow, which can occur if the | |
;; dividend is close to 2**64 and the quotient is off by 1. | |
;; | |
; mul dword ptr [ebp + 20] ; QUOT * dword ptr [ebp + 20] | |
; mov ecx,eax | |
; mov eax,dword ptr [ebp + 16] | |
; mul esi ; QUOT * dword ptr [ebp + 16] | |
; add edx,ecx ; EDX:EAX = QUOT * DVSR | |
; jc short L6 ; carry means Quotient is off by 1 | |
;; | |
;; do long compare here between original dividend and the result of the | |
;; multiply in edx:eax. If original is larger or equal, we are ok, otherwise | |
;; subtract one (1) from the quotient. | |
;; | |
; cmp edx,dword ptr [ebp + 12] ; compare hi words of result and original | |
; ja short L6 ; if result > original, do subtract | |
; jb short L7 ; if result < original, we are ok | |
; cmp eax,dword ptr [ebp + 8] ; hi words are equal, compare lo words | |
; jbe short L7 ; if less or equal we are ok, else subtract | |
;L6: | |
; dec esi ; subtract 1 from quotient | |
;L7: | |
; xor edx,edx ; edx:eax <- quotient | |
; mov eax,esi | |
;; | |
;; Just the cleanup left to do. edx:eax contains the quotient. Set the sign | |
;; according to the save value, cleanup the stack, and return. | |
;; | |
;L4: | |
; dec edi ; check to see if result is negative | |
; jnz short L8 ; if EDI == 0, result should be negative | |
; neg edx ; otherwise, negate the result | |
; neg eax | |
; sbb edx,0 | |
;; | |
;; Restore the saved registers and return. | |
;; | |
;L8: | |
; pop ebx | |
; pop esi | |
; pop edi | |
;; Save result. | |
; mov ecx, DWORD PTR [ebp+24] | |
; mov DWORD PTR [ecx], eax | |
; mov DWORD PTR [ecx+4], edx | |
#inline #{57565331FF8B450C09C07D11478B5508F7D8F7DA83D80089450C8955088B451409C07D11478B5510F7D8F7DA83D80089451489551009C075158B4D108B450C31D2F7F189C38B4508F7F189DAEB3A89C38B4D108B550C8B4508D1EBD1D9D1EAD1D809DB75F4F7F189C6F7651489C18B4510F7E601CA720C3B550C770772063B450876014E31D289F04F7507F7DAF7D883DA005B5E5F8B4D188901895104} | |
] | |
equal64?: func [ | |
a [int64!] | |
b [int64!] | |
return: [logic!] | |
][ | |
all [ | |
a/low = b/low | |
a/high = b/high | |
] | |
] | |
rdtsc: func [n [int64!]][ | |
;-- rdtsc | |
;-- cdq | |
;-- mov ecx, DWORD PTR [ebp+8] | |
;-- mov DWORD PTR [ecx], eax | |
;-- mov DWORD PTR [ecx+4], edx | |
#inline #{0F31998B4D088901895104} | |
] | |
test: func [ | |
/local | |
f [float!] | |
n [integer!] | |
t1 [int64! value] | |
t2 [int64! value] | |
t3 [int64! value] | |
t4 [int64! value] | |
][ | |
rdtsc :t1 | |
n: 0 | |
loop 100000 [n: n + 1] | |
rdtsc :t2 | |
sub64 t2 t1 :t3 | |
probe [as int-ptr! t1/high as int-ptr! t1/low] | |
probe [as int-ptr! t2/high as int-ptr! t2/low] | |
probe [as int-ptr! t3/high as int-ptr! t3/low] | |
rdtsc :t1 | |
f: 0.0 | |
loop 100000 [f: f + 1.0] | |
rdtsc :t2 | |
sub64 t2 t1 :t3 | |
probe 2 | |
probe [as int-ptr! t1/high as int-ptr! t1/low] | |
probe [as int-ptr! t2/high as int-ptr! t2/low] | |
probe [as int-ptr! t3/high as int-ptr! t3/low] | |
add64 t3 t1 :t4 | |
probe 3 | |
probe [as int-ptr! t1/high as int-ptr! t1/low] | |
probe [as int-ptr! t3/high as int-ptr! t3/low] | |
probe [as int-ptr! t4/high as int-ptr! t4/low] | |
probe equal64? :t2 :t4 | |
probe [as int-ptr! t1/high as int-ptr! t1/low] | |
probe [as int-ptr! t2/high as int-ptr! t2/low] | |
probe [as int-ptr! t3/high as int-ptr! t3/low] | |
t1/low: 3 | |
t1/high: 1 | |
t2/low: 2 | |
t2/high: 0 | |
mul64 t1 t2 :t3 | |
probe [as int-ptr! t3/high as int-ptr! t3/low] | |
t1/low: 3 | |
t1/high: 1 | |
t2/low: 2 | |
t2/high: 0 | |
div64 t1 t2 :t3 | |
probe [as int-ptr! t3/high as int-ptr! t3/low] | |
] | |
test |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment