; (c) Hundredsoft Corporation 2012 All rights reserved.
;
;    Ldouble.asm -  VC 拡張倍精度関数(x64)
;
;
.data
deffcw  word   033fh ; round to nearest, 64 bits, exceptions disabled
cutfcw  word   0f3fh ; round to zero, 64 bits, exceptions disabled
half    real8  +0.5

.code
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
public Ldouble_init
Ldouble_init proc
   fldcw  [deffcw]   ; 0x33fならfninitと同じ
   ret
Ldouble_init endp

public LdoubleToDouble
LdoubleToDouble proc
   fld    tbyte ptr [rcx]
   fstp   qword ptr [rsp+8]
   movupd xmm0, [rsp+8]
   ret
LdoubleToDouble endp

public Ldouble_int64
Ldouble_int64 proc
   fild qword ptr [rdx]
   fstp tbyte ptr [rcx]
   ret
Ldouble_int64 endp

public Ldouble_double
Ldouble_double proc
   fld  qword ptr [rdx]
   fstp tbyte ptr [rcx]
   ret
Ldouble_double endp

public Ldouble_plus_eq
Ldouble_plus_eq proc
   fld  tbyte ptr [rcx]
   fld  tbyte ptr [rdx]
   fadd
   fstp tbyte ptr [rcx]
   ret
Ldouble_plus_eq endp

public Ldouble_minus_eq
Ldouble_minus_eq proc
   fld  tbyte ptr [rcx]
   fld  tbyte ptr [rdx]
   fsub
   fstp tbyte ptr [rcx]
   ret
Ldouble_minus_eq endp

public Ldouble_mul_eq
Ldouble_mul_eq proc
   fld  tbyte ptr [rcx]
   fld  tbyte ptr [rdx]
   fmul
   fstp tbyte ptr [rcx]
   ret
Ldouble_mul_eq endp

public Ldouble_div_eq
Ldouble_div_eq proc
   fld  tbyte ptr [rcx]
   fld  tbyte ptr [rdx]
   fdiv
   fstp tbyte ptr [rcx]
   ret
Ldouble_div_eq endp

public Ldouble_rem_eq
Ldouble_rem_eq proc
   fld  tbyte ptr [rdx]
   fld  tbyte ptr [rcx]
   fprem
   fstp tbyte ptr [rcx]
   fstp qword ptr [rsp+8]
   ret
Ldouble_rem_eq endp

public Ldouble_comp
Ldouble_comp proc
   fld  tbyte ptr [rcx]
   fld  tbyte ptr [rdx]
   fcompp
   fnstsw word ptr [r8d]
   ret
Ldouble_comp endp

public Ldouble_frndint
Ldouble_frndint proc
   fldcw  [cutfcw]
   fld  tbyte ptr [rcx]
   frndint
   fstp tbyte ptr [rcx]
   fldcw  [deffcw]         ; 0x33fならfninitと同じ
   ret
Ldouble_frndint endp

public Ldouble_frnddec
Ldouble_frnddec proc
   fldcw  [cutfcw]
   fld  tbyte ptr [rcx]
   fld  st(0)
   frndint
   fsub
   fstp tbyte ptr [rcx]
   fldcw  [deffcw]
   ret
Ldouble_frnddec endp

public Ldouble_sin
Ldouble_sin proc
   fld  tbyte ptr [rcx]
   fsin
   fstp tbyte ptr [rcx]
   ret
Ldouble_sin endp

public Ldouble_cos
Ldouble_cos proc
   fld  tbyte ptr [rcx]
   fcos
   fstp tbyte ptr [rcx]
   ret
Ldouble_cos endp

public Ldouble_sincos
Ldouble_sincos proc
   fld  tbyte ptr [rcx]
   fsincos
   fstp tbyte ptr [rdx]
   fstp tbyte ptr [rcx]
   ret
Ldouble_sincos endp

public Ldouble_tan
Ldouble_tan proc
   fld  tbyte ptr [rcx]
   fptan
   fstp qword ptr [rsp+8]
   fstp tbyte ptr [rcx]
   ret
Ldouble_tan endp

public Ldouble_atan
Ldouble_atan proc
   fld  tbyte ptr [rcx]
   fld1
   fpatan
   fstp tbyte ptr [rcx]
   ret
Ldouble_atan endp

public Ldouble_atan2
Ldouble_atan2 proc
   fld  tbyte ptr [rcx]
   fld  tbyte ptr [rdx]
   fpatan
   fstp tbyte ptr [rdx]
   ret
Ldouble_atan2 endp

public Ldouble_sqrt
Ldouble_sqrt proc
   fld  tbyte ptr [rcx]
   fsqrt
   fstp tbyte ptr [rcx]
   ret
Ldouble_sqrt endp

public Ldouble_pi
Ldouble_pi proc
   fldpi
   fstp tbyte ptr [rcx]
   ret
Ldouble_pi endp

public Ldouble_log
Ldouble_log proc
   fldln2
   fld  tbyte ptr [rcx]
   fyl2x
   fstp tbyte ptr [rcx]
   ret
Ldouble_log endp

public Ldouble_log10
Ldouble_log10 proc
   fldlg2
   fld  tbyte ptr [rcx]
   fyl2x
   fstp tbyte ptr [rcx]
   ret
Ldouble_log10 endp

public Ldouble_exp
Ldouble_exp proc
   mov  eax, dword ptr [edx]
   fldl2e                 ;// log2e
   fld  tbyte ptr [rcx]   ;// log2e, v
   fmul                   ;// log2e*v
   fld  st(0)             ;// log2e*v, log2e*v
   fld  qword ptr [half]  ;// log2e*v, log2e*v, 0.5
   fsub                   ;// log2e*v, log2e*v-0.5
   frndint                ;// log2e*v, (int)(log2e*v-0.5)
   fxch                   ;// (int)(log2e*v-0.5), log2e*v
   fsub  st(0), st(1)     ;// (int)(log2e*v-0.5), log2e*v - (int)(log2e*v-0.5)
   f2xm1                  ;// (int)(log2e*v-0.5), 2^(log2e*v - (int)(log2e*v-0.5))-1
   fld1                   ;// (int)(log2e*v-0.5), 2^(log2e*v - (int)(log2e*v-0.5))-1, 1
   fadd                   ;// (int)(log2e*v-0.5), 2^(log2e*v - (int)(log2e*v-0.5))
   fscale                 ;// (int)(log2e*v-0.5), 2^(log2e*v - (int)(log2e*v-0.5)) * 2^(int)(log2e*v-0.5)
   fstp tbyte ptr [rcx]   ;// (int)(log2e*v-0.5)
   fstp qword ptr [rsp+8] ;// 
   and  eax, 1
   jz   Ldouble_exp$lab1
   fld1
   fld  tbyte ptr [rcx]
   fdiv
   fstp tbyte ptr [rcx]
Ldouble_exp$lab1:
   ret
Ldouble_exp endp

public Ldouble_pow
Ldouble_pow proc
   mov  eax, dword ptr [r8d]
   fld1                   ;// 1
   fld  tbyte ptr [rcx]   ;// 1, x
   fyl2x                  ;// log2x
   fld  tbyte ptr [rdx]   ;// log2x, v
   fmul                   ;// log2x*v
   fld  st(0)             ;// log2x*v, log2x*v
   fld  qword ptr [half]  ;// log2x*v, log2x*v, 0.5
   fsub                   ;// log2x*v, log2x*v-0.5
   frndint                ;// log2x*v, (int)(log2x*v-0.5)
   fxch                   ;// (int)(log2x*v-0.5), log2x*v
   fsub  st(0), st(1)     ;// (int)(log2x*v-0.5), log2x*v - (int)(log2x*v-0.5)
   f2xm1                  ;// (int)(log2x*v-0.5), 2^(log2x*v - (int)(log2x*v-0.5))-1
   fld1                   ;// (int)(log2x*v-0.5), 2^(log2x*v - (int)(log2x*v-0.5))-1, 1
   fadd                   ;// (int)(log2x*v-0.5), 2^(log2x*v - (int)(log2x*v-0.5))
   fscale                 ;// (int)(log2x*v-0.5), 2^(log2x*v - (int)(log2x*v-0.5)) * 2^(int)(log2x*v-0.5)
   fstp tbyte ptr [rdx]   ;// (int)(log2x*v-0.5)
   fstp qword ptr [rsp+8] ;// 
   and  eax, 1
   jz   Ldouble_pow$lab1
   fld1
   fld  tbyte ptr [rdx]
   fdiv
   fstp tbyte ptr [rdx]
Ldouble_pow$lab1:
   ret
Ldouble_pow endp

end