diff options
Diffstat (limited to 'libc/i386fp/fpushi.x')
-rw-r--r-- | libc/i386fp/fpushi.x | 126 |
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 |