Something went wrong. Try again.
Cider Isn't Darwin Emulation, Really
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
/* * expl.s * * by Ian Ollmann * * C99 expl for Mac OS X for Intel */
#include "abi.h"#include "machine/asm.h" .literal4inf: .long 0x7f800000minf: .long 0xff800000
.const.align 4maxldbl: .quad 0xffffffffffffffff, 0x7ffeminldbl: .quad 0x8000000000000000, 0x0001ln2_hi: .quad 0xB17217F7D1D00000, 0x3ffeln2_lo: .quad 0x8654361C4C67FC0D, 0xbFCE
#if defined( __i386__ ) #define RELATIVE_ADDR( _a ) ((_a) - 0b)(%ecx)#else #define RELATIVE_ADDR( _a ) _a(%rip)#endif
.text ENTRY( expl ) fldt FRAME_SIZE( STACKP ) // { x } movswl 8+FRAME_SIZE( STACKP ), %eax // sign + exponent movl %eax, %edx // sign + exponent andl $0x7fff, %eax // exponent subl $(16383-64), %eax // subtract out most of the bias -- push expoents less than -64 negative cmpl $(64+14), %eax // if( exponent < -64 || exponent > 14 || isnan(x) ja 2f // goto 2 fldl2e // { log2(e), x } andl $0x80000000, %edx // signof (x) fmul %st(1), %st(0) // { x * log2(e), x } orl $0x3f000000, %edx // copysign( 0.5f, x ) movl %edx, FRAME_SIZE(STACKP) fadds FRAME_SIZE( STACKP ) // { x * log2(e) + copysign( 0.5, x ), x } //truncate the top of stack#if defined( __SSE3__ ) fisttpl FRAME_SIZE(STACKP) // { x } movl FRAME_SIZE(STACKP), %edx fildl FRAME_SIZE(STACKP) // { round(2(x * log2(e)), x }#else fstpl FRAME_SIZE(STACKP) // { x } cvtsd2si FRAME_SIZE(STACKP), %edx movl %edx, FRAME_SIZE(STACKP) fildl FRAME_SIZE(STACKP) // { round(2(x * log2(e)), x }#endif
// PIC#if defined( __i386__ ) call 0f0: popl %ecx#endif
// reduce x to the fractional part fldt RELATIVE_ADDR(ln2_hi) // { ln(2) hi part, round(2(x * log2(e)), x } fmul %st(1), %st(0) // { ln(2) hi part * round(2(x * log2(e)), round(2(x * log2(e)), x } fsubrp %st(0), %st(2) // { round(2(x * log2(e)), x - log2(e) hi part * round(2(x * log2(e)) } fldt RELATIVE_ADDR(ln2_lo) // { ln2 fmul %st(1), %st(0) // { round(2(x * log2(e)) * ln(2) lo part, round(2(x * log2(e)), x - log2(e) hi part * round(2(x * log2(e)) } fsubrp %st(0), %st(2) // { round(2(x * log2(e)), reduced x } fxch // { reduced x, round(2(x * log2(e)) }
// multiply by log2(e) fldl2e // { log2(e), x - ln(2) hi part * round(2(x * log2(e)) - round(2(x * log2(e)) * ln(2) lo part } fmulp // { log2(e) * reduced x, round(2(x * log2(e)) }
// calculate 2**(log2(e) * reduced x ) f2xm1 // { 2**f - 1, round(2(x * log2(e)) } fld1 // { 1, 2**f - 1, round(2(x * log2(e)) } faddp // { 2**f, round(2(x * log2(e)) }
// scale results fscale // { result, , round(2(x * log2(e)) } fstp %st(1)
// The scale may fail to set underflow. Check to see if we need to do that fldt RELATIVE_ADDR( minldbl ) // { 0x1.0p-16382, result } fucomip %st(1), %st(0) // { 0x1.0p-16382, result } ja 1f
// Nope! We're done ret
1: // set underflow fldt RELATIVE_ADDR( minldbl ) // { 0x1.0p-16382, result } fmul %st(0), %st(0) fstp %st(0) ret //0x1.p-64 > |x| || 0x1.p14 < |x| || isnan(x) 2: jg 3f
// 0x1.p-64 > |x| fld1 // { 1, x } faddp // { 1 + x } ret
// 0x1.p14 < |x| || isnan(x) 3:#if defined( __i386__ ) call 0f0: popl %ecx#endif cmpl $0, %edx // if ( x < 0 ) jl 4f // goto 4
// 0x1.p14 < x || isnan(x) fldt RELATIVE_ADDR(maxldbl) // { LDBL_MAX, x } fmulp // { x * LDBL_MAX } set overflow, Inf or quiet nan ret
// -0x1.p14 > x || isnan(x)4: flds RELATIVE_ADDR( minf ) // { -inf, x } set overflow, Inf or quiet nan fucomip %st(1), %st(0) // { x } je 6f
// set underflow, return 05: fldt RELATIVE_ADDR( minldbl ) // { LDBL_MIN, x } fmul %st(0), %st(1) // { LDBL_MIN, LDBL_MIN * x } fmul %st(0), %st(1) // { LDBL_MIN, LDBL_MIN * x } fchs // { -LDBL_MIN, LDBL_MIN * x } fmulp // { -LDBL_MIN * (LDBL_MIN * x) } ret // x == -inf or nan 6: jp 5b
// x == -inf fstp %st(0) fldz ret
ENTRY( expl$fenv_access_off ) fldt FRAME_SIZE( STACKP ) // { x } movswl 8+FRAME_SIZE( STACKP ), %eax // sign + exponent movl %eax, %edx // sign + exponent andl $0x7fff, %eax // exponent subl $(16383-64), %eax // subtract out most of the bias -- push expoents less than -64 negative cmpl $(64+14), %eax // if( exponent < -64 || exponent > 14 || isnan(x) ja 2f // goto 2 fldl2e // { log2(e), x } andl $0x80000000, %edx // signof (x) fmul %st(1), %st(0) // { x * log2(e), x } orl $0x3f000000, %edx // copysign( 0.5f, x ) movl %edx, FRAME_SIZE(STACKP) fadds FRAME_SIZE( STACKP ) // { x * log2(e) + copysign( 0.5, x ), x } //truncate the top of stack#if defined( __SSE3__ ) fisttpl FRAME_SIZE(STACKP) // { x } movl FRAME_SIZE(STACKP), %edx fildl FRAME_SIZE(STACKP) // { round(2(x * log2(e)), x }#else fstpl FRAME_SIZE(STACKP) // { x } cvtsd2si FRAME_SIZE(STACKP), %edx movl %edx, FRAME_SIZE(STACKP) fildl FRAME_SIZE(STACKP) // { round(2(x * log2(e)), x }#endif
// PIC#if defined( __i386__ ) call 0f0: popl %ecx#endif
// reduce x to the fractional part flds RELATIVE_ADDR(ln2_hi) // { ln(2) hi part, round(2(x * log2(e)), x } fmul %st(1), %st(0) // { ln(2) hi part * round(2(x * log2(e)), round(2(x * log2(e)), x } fsubrp %st(0), %st(2) // { round(2(x * log2(e)), x - log2(e) hi part * round(2(x * log2(e)) } fldt RELATIVE_ADDR(ln2_lo) // { ln2 fmul %st(1), %st(0) // { round(2(x * log2(e)) * ln(2) lo part, round(2(x * log2(e)), x - log2(e) hi part * round(2(x * log2(e)) } fsubrp %st(0), %st(2) // { round(2(x * log2(e)), reduced x } fxch // { reduced x, round(2(x * log2(e)) }
// multiply by log2(e) fldl2e // { log2(e), x - ln(2) hi part * round(2(x * log2(e)) - round(2(x * log2(e)) * ln(2) lo part } fmulp // { log2(e) * reduced x, round(2(x * log2(e)) }
// calculate 2**(log2(e) * reduced x ) f2xm1 // { 2**f - 1, round(2(x * log2(e)) } fld1 // { 1, 2**f - 1, round(2(x * log2(e)) } faddp // { 2**f, round(2(x * log2(e)) }
// scale results fscale // { result, , round(2(x * log2(e)) } fstp %st(1) ret
//0x1.p-64 > |x| || 0x1.p14 < |x| || isnan(x) 2: jg 3f
// 0x1.p-64 > |x| fld1 // { 1, x } faddp // { 1 + x } ret
// 0x1.p14 < |x| || isnan(x) 3:#if defined( __i386__ ) call 0f0: popl %ecx#endif cmpl $0, %edx // if ( x < 0 ) jl 4f // goto 4
// 0x1.p14 < x || isnan(x) fldt RELATIVE_ADDR(maxldbl) // { LDBL_MAX, x } fmulp // { x * LDBL_MAX } set overflow, Inf or quiet nan ret
// -0x1.p14 > x || isnan(x)4: flds RELATIVE_ADDR( minf ) // { -inf, x } set overflow, Inf or quiet nan fucomip %st(1), %st(0) // { x } je 6f
// set underflow, return 05: fldt RELATIVE_ADDR( minldbl ) // { LDBL_MIN, x } fmul %st(0), %st(1) // { LDBL_MIN, LDBL_MIN * x } fmul %st(0), %st(1) // { LDBL_MIN, LDBL_MIN * x } fchs // { -LDBL_MIN, LDBL_MIN * x } fmulp // { -LDBL_MIN * (LDBL_MIN * x) } ret // x == -inf or nan 6: jp 5b
// x == -inf fstp %st(0) fldz ret