Something went wrong. Try again.
Cider Isn't Darwin Emulation, Really
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
/* * frexp.s * * by Ian Ollmann * * Copyright � 2007 Apple Inc. All Rights Reserved. */ #define LOCAL_STACK_SIZE (32 - FRAME_SIZE)
#include "machine/asm.h"#include "abi.h"
#if defined( __LP64__ ) #define RESULT_P %rdi#else #define RESULT_P %edx#endif
ENTRY( frexpf ) //Fetch the arguments#if defined( __i386__ ) movl FRAME_SIZE( STACKP ), %eax movl 4+FRAME_SIZE( STACKP ), RESULT_P#else movd %xmm0, %eax#endif
movl %eax, %ecx // x andl $0x7f800000, %eax // biased exponent addl $0x00800000, %eax // add one to exponent cmpl $0x00800000, %eax // if( isdenormal(x) || isinf(x) || isnan(x) ) jle 1f // goto 1
andl $0x807fffff, %ecx // sign + significand sarl $23, %eax // shift exponent to units position orl $0x3f000000, %ecx // set return exponent to -1 subl $127, %eax // remove bias //return result#if defined( __i386__ ) movl %ecx, FRAME_SIZE( STACKP ) flds FRAME_SIZE( STACKP )#else movd %ecx, %xmm0#endif movl %eax, (RESULT_P) // store exponent ret
// 0, denorm, nan, inf1: jl 3f // NaN, inf goto 3
// 0 or denor movl %ecx, %eax // x andl $0x7fffffff, %ecx // |x| jz 3f // if the value is zero, goto 3
// denormal bsrl %ecx, %ecx // count leading zeros subl $23, %ecx // correct for the backwards bit numbering scheme negl %ecx // fix sign shl %cl, %eax // move high bit to lowest exponent bit addl $125, %ecx // find exponent andl $0x007fffff, %eax // trim high bit negl %ecx movl %ecx, (RESULT_P) // write out exponent -- we need the register
#if defined( __i386__ ) movl FRAME_SIZE( STACKP ), %ecx // we lost the sign bit along the way. Get it back#else movd %xmm0, %ecx // we lost the sign bit along the way. Get it back#endif orl $0x3f000000, %eax andl $0x80000000, %ecx orl %ecx, %eax
#if defined( __i386__ ) movl %eax, FRAME_SIZE( STACKP ) flds FRAME_SIZE(STACKP)#else movd %eax, %xmm0#endif ret 3: // 0, inf, NaN#if defined( __i386__ ) flds FRAME_SIZE(STACKP)#endif movl $0, (RESULT_P) ret
ENTRY( frexp ) SUBP $LOCAL_STACK_SIZE, STACKP //Load exponent of argument and result pointer#if defined( __i386__ ) movl 4+FIRST_ARG_OFFSET(STACKP), %eax movl 8+FIRST_ARG_OFFSET(STACKP), RESULT_P#else movd %xmm0, %rax shrq $32, %rax#endif //make a copy of mantissa top bits and sign movl %eax, %ecx //expose the exponent andl $0x7FF00000, %eax //extract sign + mantissa high bits andl $0x800FFFFF, %ecx
//add 1 to the exponent addl $0x00100000, %eax //or in -1 + bias as the new exponent for the mantissa orl $0x3fe00000, %ecx
//test to see if we are in an exceptional case. (0x00800000 -> 0 or denormal, 0x80000000 -> NaN or Inf) cmpl $0x00100000, %eax jle 1f //Merge high and low mantissa parts and move to return register movd %ecx, %xmm1#if defined( __i386__ ) movd FIRST_ARG_OFFSET(STACKP), %xmm0#endif punpckldq %xmm1, %xmm0#if defined( __i386__ ) movq %xmm0, (STACKP) fldl (STACKP)#endif
//move exponent to units precision, and store sarl $20, %eax addl $-1023, %eax //remove bias movl %eax, (RESULT_P)
//exit ADDP $LOCAL_STACK_SIZE, STACKP ret
//special case code1: je 3f //handle zeros and denormals in 3
2: movl $0, (RESULT_P) //Infs, zeros and NaNs -- return input value#if defined( __i386__ ) fldl FIRST_ARG_OFFSET( STACKP )#endif ADDP $LOCAL_STACK_SIZE, STACKP ret
//zeros and denormals3: #if defined( __i386__ ) fldl FIRST_ARG_OFFSET( STACKP ) // { 0 or denormal } fldz // { 0, 0 or denormal } fucomip %st(1), %st(0) // { 0 or denormal } fstpt (STACKP) // save out in 80-bit format (normalizes denorms), and empty stack je 2b
movsxw 8(STACKP), %eax // load sign + exponent movl %eax, %ecx // copy to ecx andl $0x7fff, %eax // extract exponent andl $0x8000, %ecx // extract sign addl $-16382, %eax // subtract bias from exponent orl $0x3ffe, %ecx // copy sign bit to a new exponent of -1 movl %eax, (RESULT_P) // store our exponent to the result pointer movw %cx, 8(STACKP) // write the other exponent back to the 80-bit FP value fldt (STACKP) // load the manittsa in
ADDP $LOCAL_STACK_SIZE, STACKP ret
#else xorpd %xmm1, %xmm1 ucomisd %xmm0, %xmm1 je 2b // read value from xmm movd %xmm0, %rax movq %rax, %rcx //set aside sign for later //take absolute value shlq $1, %rax shrq $1, %rax //save sign bit for later xorq %rax, %rcx //read |x| as integer -- multiplies denormal by 2**(1022+52) to get normal number cvtsi2sd %rax, %xmm1 movd %xmm1, %rax
//prepare an exponent mask movq $0x7ff, %rdx shlq $52, %rdx // 0x7ff0000000000000 //extract exponent and mantissa andq %rax, %rdx // exponent xorq %rdx, %rax // mantissa //reduce exponent to units precision shrq $52, %rdx //or in sign bit to mantissa orq %rcx, %rax
//prepare 0.5 movq $0x3fe, %rcx shlq $52, %rcx // 0x3fe0000000000000 //subtract out the bias in the exponent subq $(1022+52+1022), %rdx //set mantissa exponent to 2**-1 orq %rcx, %rax //write out the exponent movl %edx, (RESULT_P) //move result to destination register movd %rax, %xmm0 ADDP $LOCAL_STACK_SIZE, STACKP ret#endif
ENTRY( frexpl ) SUBP $LOCAL_STACK_SIZE, STACKP //Load the sign + exponent movsxw 8+FIRST_ARG_OFFSET(STACKP), %eax movl %eax, %ecx
//Load result pointer if necessary#if defined( __i386__ ) movl SECOND_ARG_OFFSET(STACKP), RESULT_P#endif //Copy value to stack fldt FIRST_ARG_OFFSET(STACKP) fstpt (STACKP)
//extract exponent andl $0x7fff, %eax addl $1, %eax cmpw $1, %ax jle 1f //special case code for zero, nan, denormal, inf addl $-16383, %eax movl %eax, (RESULT_P)
//prepare new exponent for mantissa andl $0x8000, %ecx orl $0x3ffe, %ecx movw %cx, 8(STACKP) fldt (STACKP) //exit ADDP $LOCAL_STACK_SIZE, STACKP ret
1: fldt FIRST_ARG_OFFSET(STACKP) je 3f //denormals and zeros are handled elsewhere
2: movl $0, (RESULT_P) ADDP $LOCAL_STACK_SIZE, STACKP ret
//handle zero case3: fldz fucomip %st(1), %st(0) je 2b fstp %st(0)
//we have a denormal. Load the mantissa as an integer, and convert to normal floating point number. fildll (STACKP) // {|f| * 2**(16382+63)} //note: fails for malformed normals that have 0 exponent, but leading bit set. However, since this is a stack copy of the data, we naively hope that the hardware took care of that. fld %st(0) // {|f| * 2**(16382+63), |f| * 2**(16382+63)} fchs // {-|f| * 2**(16382+63), |f| * 2**(16382+63)} fcmovb %st(1), %st(0) // { f * 2**(16382+63), |f| * 2**(16382+63) } fstpt (STACKP) // { |f| * 2**(16382+63) } fstp %st(0) // {} //repeat frexpl with new bias //Load the sign + exponent movsxw 8(STACKP), %eax movl %eax, %ecx //extract exponent andl $0x7fff, %eax addl $(-16383-16382-63+1), %eax movl %eax, (RESULT_P) //prepare new exponent for mantissa andl $0x8000, %ecx orl $0x3ffe, %ecx movw %cx, 8(STACKP) fldt (STACKP)
//exit ADDP $LOCAL_STACK_SIZE, STACKP ret