summaryrefslogtreecommitdiff
path: root/libc/i386fp/fpushi.x
diff options
context:
space:
mode:
Diffstat (limited to 'libc/i386fp/fpushi.x')
-rw-r--r--libc/i386fp/fpushi.x126
1 files changed, 126 insertions, 0 deletions
diff --git a/libc/i386fp/fpushi.x b/libc/i386fp/fpushi.x
new file mode 100644
index 0000000..b19aae2
--- /dev/null
+++ b/libc/i386fp/fpushi.x
@@ -0,0 +1,126 @@
+! bcc 386 floating point routines (version 2)
+! -- Fpushi, Fpushl, Fpushs, Fpushc, Fpushuc, Fpushui, Fpushul, Fpushus
+! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans
+
+#include "fplib.h"
+
+! Convert the short in ax to double and push on stack
+
+ .globl Fpushs
+ .align ALIGNMENT
+Fpushs:
+ cwde
+ add eax,#0 ! fast 3-byte instruction to align
+
+! Convert the int or long in eax to double and push on stack
+
+ .globl Fpushi
+ .globl Fpushl
+! .align ALIGNMENT ! don't do this until it pads with nop's
+Fpushi:
+Fpushl:
+ test eax,eax
+ jz return_eax ! got 0 in eax
+ mov ebx,#(D_EXP_BIAS+D_NORM_BIT) << D_EXP_SHIFT ! set no-sign and exponent
+ jns normalize ! sign and fraction bits already set up
+ mov ebx,#D_SIGN_MASK | ((D_EXP_BIAS+D_NORM_BIT) << D_EXP_SHIFT) ! adjust sign
+ neg eax ! adjust fraction
+ jmp normalize
+
+ .align ALIGNMENT
+ret1:
+ mov eax,#D_EXP_BIAS << D_EXP_SHIFT
+ add eax,#0 ! fast 3-byte instruction to align
+
+! .align ALIGNMENT ! don't do this until it pads with nop's
+return_eax:
+ pop ecx
+ push eax ! upper dword
+ push dword #0 ! lower dword = 0
+ jmp ecx ! return
+
+! Convert the (unsigned) char in al to double and push on stack
+
+ .globl Fpushc
+ .globl Fpushuc
+ .align ALIGNMENT
+Fpushc:
+Fpushuc:
+ and eax,#(1 << CHAR_BIT)-1
+ add eax,#0 ! fast 3-byte instruction to align
+
+! Convert the unsigned short in ax to double and push on stack
+
+ .globl Fpushus
+! .align ALIGNMENT ! don't do this until it pads with nop's
+Fpushus:
+ and eax,#(1 << SHORT_BIT)-1
+ add eax,#0 ! fast 3-byte instruction to align
+
+! Convert the unsigned int or long in eax to double and push on stack
+
+ .globl Fpushui
+ .globl Fpushul
+! .align ALIGNMENT ! don't do this until it pads with nop's
+Fpushui:
+Fpushul:
+ cmp eax,#1 ! this tests for both 0 and 1
+ jb return_eax ! got 0 in eax
+ jz ret1
+ mov ebx,#(D_EXP_BIAS+D_NORM_BIT) << D_EXP_SHIFT ! set no-sign and exponent
+
+! .align ALIGNMENT ! don't do this until it pads with nop's
+normalize:
+ sub edx,edx ! clear lower dword of result
+
+! Find first nonzero bit
+! Don't use bsr, it is slow (const + 3n on 386, const + n on 486)
+
+ sub ecx,ecx ! prepare unsigned extension of cl
+ test eax,#~D_FRAC_MASK
+ jnz large
+ test eax,#0xFF << (D_NORM_BIT-8)
+ jnz middle
+ shl eax,#8
+ sub ebx,#8 << D_EXP_SHIFT
+ test eax,#0xFF << (D_NORM_BIT-8)
+ jnz middle
+ shl eax,#8
+ sub ebx,#8 << D_EXP_SHIFT
+middle:
+ shld ecx,eax,#D_NORM_BIT
+ mov cl,bsr_table[ecx]
+ add ecx,#REG_BIT-D_NORM_BIT-D_NORM_BIT
+ neg ecx
+ shl eax,cl
+ shl ecx,#D_EXP_SHIFT
+ sub ebx,ecx
+return:
+ and eax,#D_FRAC_MASK ! remove normalization bit
+ or eax,ebx ! include exponent (and sign) to fraction
+ pop ecx
+ push eax ! upper dword
+ push edx ! lower dword
+ jmp ecx ! return
+
+ .align ALIGNMENT
+large:
+ shld ecx,eax,#REG_BIT-(D_NORM_BIT+8)
+ jnz huge
+ shld ecx,eax,#REG_BIT-D_NORM_BIT
+ mov cl,bsr_table[ecx]
+got_shift_right:
+ shrd edx,eax,cl
+ shr eax,cl
+ shl ecx,#D_EXP_SHIFT
+ add ebx,ecx
+ jmp return
+
+ .align ALIGNMENT
+huge:
+ mov cl,bsr_table[ecx]
+ add cl,#8
+ jmp got_shift_right
+
+ .data
+ .extern bsr_table