summaryrefslogtreecommitdiff
path: root/libc/i386fp/ldexp.x
diff options
context:
space:
mode:
Diffstat (limited to 'libc/i386fp/ldexp.x')
-rw-r--r--libc/i386fp/ldexp.x74
1 files changed, 74 insertions, 0 deletions
diff --git a/libc/i386fp/ldexp.x b/libc/i386fp/ldexp.x
new file mode 100644
index 0000000..bc9dd03
--- /dev/null
+++ b/libc/i386fp/ldexp.x
@@ -0,0 +1,74 @@
+! bcc 386 floating point routines (version 2) -- _ldexp
+! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans
+
+#include "fplib.h"
+
+ .extern fpoverflow
+ .extern fpunderflow
+
+! void ldexp(double value, int exponent);
+! returns value * (2 ** exponent)
+
+ .globl _ldexp
+ .align ALIGNMENT
+_ldexp:
+push ebx
+#undef PC_SIZE
+#define PC_SIZE 8
+ mov ebx,PC_SIZE+D_HIGH[esp] ! upper dword of x
+ mov ecx,PC_SIZE+D_SIZE[esp] ! exponent arg
+ mov eax,ebx ! extract exponent (of x) here
+ and eax,#D_EXP_MASK
+! jz exp_y_0 ! may need check for preposterous exponent arg too
+
+ shr eax,#D_EXP_SHIFT ! shift to low bits just for testing
+ jz underflow ! denormal?
+ add eax,ecx ! test-add the exponents
+ jz underflow ! XXX probably need to fiddle norm bit
+ cmp eax,#D_EXP_INFINITE ! check if still within range
+ jae outofbounds ! the unsigned compare catches all overflow cases
+ ! because the exponent of x is non-negative
+
+ shl ecx,#D_EXP_SHIFT ! shift exponent arg bits into final position ...
+ add ebx,ecx ! ... safe to add it to exponent of x now
+ mov eax,PC_SIZE+D_LOW[esp] ! lower dword of x
+mov edx,ebx
+pop ebx
+ ret
+
+
+ .align ALIGNMENT
+outofbounds:
+ test ecx,ecx ! overflow or underflow?
+ jns overflow
+underflow:
+ mov edx,ebx ! put sign in usual reg
+ push edi
+ push esi
+ mov edi,eax ! put exponent in usual reg
+ mov eax,2*GENREG_SIZE+PC_SIZE+D_LOW[esp]
+ ! put lower dword of x in usual reg
+ mov esi,ebx ! put upper dword of x in usual reg
+ and esi,#D_EXP_MASK | D_FRAC_MASK
+ test esi,#D_EXP_MASK
+ jz foo
+ and esi,#D_FRAC_MASK
+ or esi,#D_NORM_MASK
+foo:
+ neg edi
+! inc edi ! XXX ?
+ call fpunderflow
+ pop esi
+ pop edi
+ mov ebx,edx ! XXX = wrong reg
+pop ebx
+ ret
+
+ .align ALIGNMENT
+overflow:
+ mov edx,ebx ! put sign in usual reg
+ call fpoverflow
+ mov eax,ecx ! XXX = wrong reg
+ mov ebx,edx ! XXX = wrong reg
+pop ebx
+ ret