Something went wrong. Try again.
Cider Isn't Darwin Emulation, Really
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148// double scalbn( double x, int n );// double ldexp( double x, int n );// double scalb( double x, double n );// double scalbln( double x, long int n );//// Returns x * 2^n computed efficiently, without undue over/underflow.// Adapted from Ian Ollmann's scalbn implementation of 2005.// // -- Stephen Canon, January 2010
.globl _scalbn.globl _ldexp.globl _scalb.globl _scalbln
#if defined __x86_64__
.literal8threek: .quad 0x40a7700000000000mthreek: .quad 0xc0a7700000000000
#define floatval -24(%rsp) #define n %edi #define ln %rdi #define clamphi threek(%rip) #define clamplo mthreek(%rip) .text.align 4_scalb: movsd %xmm0, floatval pcmpeqd %xmm0, %xmm0 fldl floatval // load x on x87 psllq $63, %xmm0 // conjure long dbl mantissa of 2^n ucomisd %xmm1, %xmm1 // if isnan(n) jp L_nIsNaN // branch to return n minsd clamphi, %xmm1 // clamp n to [-3000, 3000] maxsd clamplo, %xmm1 cvtsd2si %xmm1, n // convert clamped n to integer jmp L_common // and jump to the shared scalbn path L_nIsNaN: fstp %st(0) movapd %xmm1, %xmm0 // since n is a NaN, we just return n ret
.align 4_scalbln: movsd %xmm0, floatval pcmpeqd %xmm0, %xmm0 fldl floatval // load x on x87 psllq $63, %xmm0 // conjure long dbl mantissa of 2^n mov $3000, %rdx cmp %rdx, ln // if n > 3000 cmovg %rdx, ln // n == 3000 neg %rdx cmp %rdx, ln // if n < -3000 cmovl %rdx, ln // n == -3000 jmp L_common
.align 4_scalbn:_ldexp: movsd %xmm0, floatval fldl floatval // load x on x87 pcmpeqd %xmm0, %xmm0 psllq $63, %xmm0 // conjure long dbl mantissa of 2^n mov $3000, %edx cmp %edx, n // if n > 3000 cmovg %edx, n // n == 3000 neg %edx cmp %edx, n // if n < -3000 cmovl %edx, n // n == -3000 L_common: add $0x3fff, n // long dbl exponent field of 2^n pinsrw $4, n, %xmm0 // insert exponent to make 2^n movdqa %xmm0, floatval fldt floatval fmulp // x * 2^n fstpl floatval // round to double movsd floatval, %xmm0 ret #elif defined __i386__
.literal8threek: .quad 0x40a7700000000000mthreek: .quad 0xc0a7700000000000
#define floatval 4(%esp) #define exponent 12(%esp) #define n %eax #define nw %ax #define clamphi (threek-0b)(%ecx) #define clamplo (mthreek-0b)(%ecx)
.text.align 4_scalb: call 0f 0: pop %ecx // conjure pic info movsd 12(%esp), %xmm1 // load n fldl floatval // load x on x87 ucomisd %xmm1, %xmm1 // if isnan(n) jp L_nIsNaN // branch to return n fld1 fstpt floatval // conjure 1.0L minsd clamphi, %xmm1 // clamp n to [-3000, 3000] maxsd clamplo, %xmm1 cvtsd2si %xmm1, n // convert clamped n to integer jmp L_common // and jump to the shared scalbn path L_nIsNaN: fstp %st(0) fldl 12(%esp) // n is nan, return n ret
.align 4_scalbln:_scalbn:_ldexp: mov 12(%esp), n // load n fldl floatval // load x on x87 fld1 fstpt floatval // conjure 1.0L mov $3000, %edx cmp %edx, n // if n > 3000 cmovg %edx, n // n == 3000 mov $-3000, %edx cmp %edx, n // if n < -3000 cmovl %edx, n // n == -3000 L_common: add nw, exponent // 2^n in memory fldt floatval fmulp // x * 2^n fstpl floatval // round to double fldl floatval ret #else #error "This implementation supports 32- and 64-bit Intel only"#endif