Something went wrong. Try again.
Cider Isn't Darwin Emulation, Really
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136// double hypot(double x, double y)// double cabs(double complex z)//// Returns sqrt(x*x + y*y), computed without spurious overflow or underflow.//// -- Stephen Canon, August 2009
#if !defined __i386__ && !defined __x86_64__#error This implementation is for i386 and x86_64 only#endif
.text.globl _hypot.globl _cabs
#if defined __i386__
#define ABSHI $0x7fffffff#define INFHI $0x7ff00000
// Entry point --------------------------------------------------------
.align 4_cabs:_hypot: mov 8(%esp), %eax mov 16(%esp), %edx mov ABSHI, %ecx // Detect special cases ----------------------------------------------- and %ecx, %eax // |x| jz L_xHiIsZero // L_returnFromXHiIsZero: and %ecx, %edx // |y| jz L_yHiIsZero //L_returnFromYHiIsZero: cmp INFHI, %eax // we need to detect if either x or y is jae L_xIsSpecial // an infinity and return +infinity if so; cmp INFHI, %edx // this is because hypot(inf, NaN) needs jae L_returnAbsY // to return +inf, not NaN. // Mainline computation -----------------------------------------------
fldl 4(%esp) // x87 stack: { x } fmul %st(0), %st(0) // { x*x } fldl 12(%esp) // { y x*x } fmul %st(0), %st(0) // { y*y x*x } faddp // { y*y+x*x } fsqrt // { sqrt(y*y + x*x) } fstpl 4(%esp) // round to double fldl 4(%esp) ret
// Special case handling ----------------------------------------------
L_xHiIsZero: cmpl $0, 4(%esp) // is the low word of x zero? jnz L_returnFromXHiIsZero // if not, jump back to mainlineL_returnAbsY: and %ecx, 16(%esp) fldl 12(%esp) ret
L_yHiIsZero: cmpl $0, 12(%esp) // is the low word of y zero? jnz L_returnFromYHiIsZero // if not, jump back to mainlineL_returnAbsX: and %ecx, 8(%esp) fldl 4(%esp) ret L_xIsSpecial: cmp INFHI, %edx // check if y is infinity jnz L_returnAbsX cmpl $0, 12(%esp) jz L_returnAbsY jmp L_returnAbsX #else // defined __i386__
#define ABSMASK $0x7fffffffffffffff#define INFINITY $0x7ff0000000000000
// Entry point --------------------------------------------------------
.align 4_cabs:_hypot: movd %xmm0, %rax movd %xmm1, %rdx mov ABSMASK, %rcx // Detect special cases ----------------------------------------------- and %rcx, %rax // |x| jz L_returnAbsY // and %rcx, %rdx // |y| jz L_returnAbsX // mov INFINITY, %rdi // movsd %xmm0, -8(%rsp) // store x to the red zone movsd %xmm1, -16(%rsp) // store y to the red zone cmp %rdi, %rax // we need to detect if either x or y is jae L_xIsSpecial // an infinity and return +infinity if so; cmp %rdi, %rdx // this is because hypot(inf, NaN) needs jae L_returnAbsY // to return +inf, not NaN. // Mainline computation ----------------------------------------------- fldl -8(%rsp) // x87 stack: { x } fmul %st(0), %st(0) // { x*x } fldl -16(%rsp) // { y x*x } fmul %st(0), %st(0) // { y*y x*x } faddp // { y*y+x*x } fsqrt // { sqrt(y*y + x*x) } fstpl -8(%rsp) // round result to double movsd -8(%rsp), %xmm0 // and load in xmm register to return ret
// Special case handling ----------------------------------------------
L_xIsSpecial: // x is either inf or NaN cmp %rdi, %rdx jz L_returnAbsY // if y is infinity, return |y|L_returnAbsX: movd %rax, %xmm0 // otherwise, return |x| retL_returnAbsY: and %rcx, %rdx movd %rdx, %xmm0 // return |y| ret #endif // defined __i386__