@@ -60,3 +60,56 @@ pub fn floor(mut x: f64) -> f64 {
6060    } 
6161    x
6262} 
63+ 
64+ macro_rules!  x87exp { 
65+     ( $float_ty: ident,  $word_size: literal,  $fn_name: ident,   $load_op: literal)  => { 
66+         pub  fn  $fn_name( mut  x:  $float_ty)  -> $float_ty {  unsafe  { 
67+             core:: arch:: asm!( 
68+                 // Prepare the register stack as 
69+                 // ``` 
70+                 // st(0) = y = x*log2(base) 
71+                 // st(1) = 1.0 
72+                 // st(2) = round(y) 
73+                 // ``` 
74+                 concat!( $load_op,  " " ,  $word_size,  " ptr [{x}]" ) , 
75+                 "fld1" , 
76+                 "fld st(1)" , 
77+                 "frndint" , 
78+                 "fxch st(2)" , 
79+ 
80+                 // Compare y with round(y) to determine if y is finite and 
81+                 // not an integer. If so, compute `exp2(y - round(y))` into 
82+                 // st(1). Otherwise skip ahead with `st(1) = 1.0` 
83+                 "fucom st(2)" , 
84+                 "fstsw ax" , 
85+                 "test ax, 0x4000" , 
86+                 "jnz 2f" , 
87+                 "fsub st(0), st(2)" ,  // st(0) = y - round(y) 
88+                 "f2xm1" ,              // st(0) = 2^st(0) - 1.0 
89+                 "fadd st(1), st(0)" ,  // st(1) = 1 + st(0) = exp2(y - round(y)) 
90+                 "2:" , 
91+ 
92+                 // Finally, scale by `exp2(round(y))` and clear the stack. 
93+                 "fstp st(0)" , 
94+                 "fscale" , 
95+                 concat!( "fstp " ,  $word_size,  " ptr [{x}]" ) , 
96+                 "fstp st(0)" , 
97+                 x = in( reg)  & mut  x, 
98+                 out( "ax" )  _, 
99+                 out( "st(0)" )  _,  out( "st(1)" )  _, 
100+                 out( "st(2)" )  _,  out( "st(3)" )  _, 
101+                 out( "st(4)" )  _,  out( "st(5)" )  _, 
102+                 out( "st(6)" )  _,  out( "st(7)" )  _, 
103+                 options( nostack) , 
104+             ) ; 
105+             x
106+         } } 
107+     } ; 
108+ } 
109+ 
110+ x87exp ! ( f32 ,  "dword" ,  x87_exp2f,  "fld" ) ; 
111+ x87exp ! ( f64 ,  "qword" ,  x87_exp2,  "fld" ) ; 
112+ x87exp ! ( f32 ,  "dword" ,  x87_exp10f,  "fldl2t\n fmul" ) ; 
113+ x87exp ! ( f64 ,  "qword" ,  x87_exp10,  "fldl2t\n fmul" ) ; 
114+ x87exp ! ( f32 ,  "dword" ,  x87_expf,  "fldl2e\n fmul" ) ; 
115+ x87exp ! ( f64 ,  "qword" ,  x87_exp,  "fldl2e\n fmul" ) ; 
0 commit comments