Log10() optimisé MMX
Publié : dim. 01/mai/2005 15:47
Bonjour, je vous présente mon premier code asm ... honteusement copié depuis le Visual C++ Processor Pack.
J'avais besoin d'une telle fonction et je l'ai adaptée pour PureBasic :
J'avais besoin d'une telle fonction et je l'ai adaptée pour PureBasic :
Code : Tout sélectionner
;- Start Of Misc Asm Functions
; Taken from the VisualC++ Processor Pack and adapted for use with PureBasic
Global fval.f
Global mant
Global expo
Global one
Global half
Global two
Global rt2
Global edec
Global bias
Global ln2lo
Global ln2hi
Global c2
Global c1
Global c0
Global maxn
Global rle10
Procedure a_log()
!movd mm6, [v_mant] ; mask for mantissa
!movq mm4, mm0 ; save x
!movd mm2, [v_expo] ; mask for exponent
!pand mm0, mm6 ; extract mantissa of x => m
!movd mm3, [v_one] ; 1.0
!pand mm4, mm2 ; extract biased exponent of x => e
!por mm0, mm3 ; float(m)
!movd mm3, [v_rt2] ; sqrt(2)
!psrld mm4, 23 ; biased exponent e
!movq mm2, mm0 ; save m
!pxor mm5, mm5 ; create 0
!movd mm6, [v_edec] ; 0x0080000
!pcmpgtd mm0, mm3 ; m > sqrt(2) ? 0xFFFFFFFF : 0
!pcmpeqd mm5, mm4 ; sel = (e == 0) ? 0xFFFFFFFFL : 0
!psubd mm4, mm0 ; increment e if m > sqrt(2)
!movd mm3, [v_bias] ; 127
!pand mm0, mm6 ; m > sqrt(2) ? 0x00800000 : 0
!movd mm6, [v_one] ; 1.0
!psubd mm2, mm0 ; if m > sqrt(2), m = m/2
!psubd mm4, mm3 ; true exponent = i
!movq mm0, mm2 ; save m
!pfadd mm2, mm6 ; m + 1
!pfsub mm0, mm6 ; m - 1
!pi2fd mm4, mm4 ; float(i)
!movd mm7, [v_ln2lo] ; lower 24 bits of ln(2)
!pfrcp mm6, mm2 ; approx 1/mm+1) lo
!movd mm3, [v_ln2hi] ; upper 16 bits of ln(2)
!pfrcpit1 mm2, mm6 ; refine 1/mm+1)
!pfmul mm7, mm4 ; i*ln2lo
!pfmul mm3, mm4 ; i*ln2hi
!movd mm4, [v_c2] ; c2
!pfrcpit2 mm2, mm6 ; 1/mm+1)
!movd mm1, [v_c1] ; c1
!pfmul mm2, mm0 ; z=mm+1)/mm-1)
!movq mm0, mm2 ; save z
!pfadd mm0, mm0 ; 2*z
!pfmul mm2, mm2 ; z^2
!movq mm6, mm2 ; save z^2
!pfmul mm2, mm4 ; c2 * z^2
!movd mm4, [v_c0] ; c0
!pfadd mm2, mm1 ; c2 * z^2 + c1
!pfmul mm2, mm6 ; (c2 * z^2 + c1) * z^2
!movd mm1, [v_maxn] ; maxn (negative largest normal)
!pfmul mm6, mm0 ; 2*z^3
!pfadd mm2, mm4 ; px = (c2 * z^2 + c1) * z^2 + c0
!pfmul mm2, mm6 ; px*2*z^3
!pfadd mm2, mm0 ; px*2*z^3+2*z
!movq mm0, mm5 ; sel
!pand mm5, mm1 ; select largest negative normal if e = 0
!pfadd mm2, mm7 ; px*2*z^3+2*z+i*ln2lo
!pfadd mm2, mm3 ; ln(z)=px*2*z^3+2*z+i*ln2lo+i*ln2hi
!pandn mm0, mm2 ; select regular result if e != 0
!por mm0, mm5 ; mux in either normal or special result
EndProcedure
Procedure a_Log10(x.f, *out.f)
mant = $007FFFFF
expo = $7F800000
one = $3F800000
half = $3F000000
two = $40000000
rt2 = $3FB504F3
edec = $00800000
bias = $0000007F
ln2lo = $35BFBE8E
ln2hi = $3F317200
c2 = $3E18EFE2
c1 = $3E4CAF6F
c0 = $3EAAAABD
maxn = $FF7FFFFF
rle10 = $3EDE5BDB
!FEMMS
!movd mm0, dword [esp]
a_log() ; mm0 = ln(x)
!movd mm1, [v_rle10] ; mm1 = 1/ln(10)
!pfmul mm0, mm1 ; mm0 = ln(x) / ln(10)
!movd [v_fval], mm0 ; Result in mm0
!FEMMS
PokeF(*out, fval)
EndProcedure