diff options
Diffstat (limited to 'bin86-0.3/bccfp/frexp.x')
-rw-r--r-- | bin86-0.3/bccfp/frexp.x | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/bin86-0.3/bccfp/frexp.x b/bin86-0.3/bccfp/frexp.x new file mode 100644 index 0000000..318fc34 --- /dev/null +++ b/bin86-0.3/bccfp/frexp.x @@ -0,0 +1,66 @@ +! bcc 386 floating point routines (version 2) -- _frexp +! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans + +#include "fplib.h" + + .extern fpdenormal + +! void frexp(double value, int *exponent); +! splits a double into exponent and fraction (where 0.5 <= fraction < 1.0) + + .globl _frexp + .align ALIGNMENT +_frexp: +push ebx +#undef PC_SIZE +#define PC_SIZE 8 + mov eax,PC_SIZE+D_LOW[esp] ! lower dword of x + mov ebx,PC_SIZE+D_HIGH[esp] ! upper dword of x + mov edx,PC_SIZE+D_SIZE[esp] ! exponent pointer + mov ecx,ebx ! extract exponent here + and ecx,#D_EXP_MASK + jz exp_x_0 + + shr ecx,#D_EXP_SHIFT ! exponent + bias +got_x: + sub ecx,#D_EXP_BIAS-1 ! D_EXP_BIAS is for 1.x form, we want 0.1x form + mov [edx],ecx ! return exponent + and ebx,#D_SIGN_MASK | D_FRAC_MASK ! extract sign and fraction + or ebx,#(D_EXP_BIAS-1) << D_EXP_SHIFT ! set new exponent for 0.1x +mov edx,ebx +pop ebx + ret + + .align ALIGNMENT +exp_x_0: + test ebx,#D_FRAC_MASK + jnz xu_denorm + test eax,eax + jnz xl_denorm + mov [edx],ecx ! return zero exponent + mov ebx,ecx ! guard against -0 (may not be necessary) +mov edx,ebx +pop ebx + ret + + .align ALIGNMENT +xl_denorm: + call fpdenormal + bsr ecx,eax ! zzzz + neg ecx + add ecx,#REG_BIT-1 + shl eax,cl + shld ebx,eax,#D_NORM_BIT+1 + shl eax,#D_NORM_BIT+1 + sub ecx,#D_NORM_BIT+1 + jmp got_x + + .align ALIGNMENT +xu_denorm: + call fpdenormal + bsr ecx,ebx + neg ecx + add ecx,#D_NORM_BIT + shld ebx,eax,cl + shl eax,cl + jmp got_x |