1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  23  */
  24 /*
  25  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  26  * Use is subject to license terms.
  27  */
  28 
  29         .file "hypot.s"
  30 
  31 #include "libm.h"
  32 LIBM_ANSI_PRAGMA_WEAK(hypot,function)
  33 #include "libm_synonyms.h"
  34 #include "libm_protos.h"
  35 
  36 #undef fabs
  37 
  38         .data
  39         .align  4
  40 inf:
  41         .long   0x7f800000
  42 
  43         ENTRY(hypot)
  44         movl    8(%esp),%eax            / eax <-- hi_32(x)
  45         andl    $0x7fffffff,%eax        / eax <-- hi_32(|x|)
  46         jz      .x_maybe_0              / if x = +/-0, return |y|
  47         subl    $0x7ff00000,%eax        / eax <-- hi_32(|x|) - hi_32(INF)
  48         jz      .x_maybe_inf
  49 .check_y:
  50         movl    16(%esp),%eax           / eax <-- hi_32(y)
  51         andl    $0x7fffffff,%eax        / eax <-- hi_32(|y|)
  52         jz      .y_maybe_0              / if y = +/-0, return |x|
  53         subl    $0x7ff00000,%eax        / eax <-- hi_32(|y|) - hi_32(INF)
  54         jz      .y_maybe_inf
  55 .do_hypot:
  56         fldl    12(%esp)                / ,y
  57         fmul    %st(0),%st              / ,y*y
  58         fldl    4(%esp)                 / x,y*y
  59         fmul    %st(0),%st              / x*x,y*y
  60         faddp   %st,%st(1)              / x*x+y*y
  61         fsqrt                           / sqrt(x*x+y*y)
  62         subl    $8,%esp
  63         fstpl   (%esp)                  / round to double
  64         fldl    (%esp)                  / sqrt(x*x+y*y) rounded to double
  65         PIC_SETUP(1)
  66         flds    PIC_L(inf)              / inf , sqrt(x*x+y*y)
  67         PIC_WRAPUP
  68         addl    $8,%esp
  69         fucomp
  70         fstsw   %ax                     / store status in %ax
  71         sahf                            / 80387 flags in %ah to 80386 flags
  72         jz      .maybe_ovflw
  73         ret
  74 
  75 .maybe_ovflw:
  76         jnp     .ovflw
  77         ret
  78 
  79 .ovflw:
  80         /       overflow occurred
  81         fstp    %st(0)                  / stack empty
  82         pushl   %ebp
  83         movl    %esp,%ebp
  84         PIC_SETUP(2)
  85         pushl   $4
  86         pushl   20(%ebp)                / high y
  87         pushl   16(%ebp)                / low y
  88         pushl   12(%ebp)                / high x
  89         pushl   8(%ebp)                 / low x
  90         call    PIC_F(_SVID_libm_err)
  91         addl    $20,%esp
  92         PIC_WRAPUP
  93         leave
  94         ret
  95 
  96 .x_maybe_0:
  97         movl    4(%esp),%ecx            / ecx <-- lo_32(x)
  98         orl     %ecx,%eax               / is x = +/-0?
  99         jnz     .check_y                / branch if x is denormal
 100         /  x = +/-0, so return |y|
 101         fldl    12(%esp)
 102         fabs
 103         ret
 104 
 105 .x_maybe_inf:
 106         movl    4(%esp),%ecx            / ecx <-- lo_32(x)
 107         orl     %ecx,%eax               / is x = +/-INF?
 108         jnz     .check_y                / branch if x is NaN
 109         / push&pop y in case y is a SNaN
 110         fldl    12(%esp)
 111         fstp    %st(0)
 112         / x = +/-INF, so return |x|
 113         fldl    4(%esp)
 114         fabs
 115         ret
 116 
 117 .y_maybe_0:
 118         movl    12(%esp),%ecx           / ecx <-- lo_32(y)
 119         orl     %ecx,%eax               / is y = +/-0?
 120         jnz     .do_hypot               / branch if y is denormal
 121         /  y = +/-0, so return |x|
 122         fldl    4(%esp)
 123         fabs
 124         ret
 125 
 126 .y_maybe_inf:
 127         movl    12(%esp),%ecx           / ecx <-- lo_32(y)
 128         orl     %ecx,%eax               / is y = +/-INF?
 129         jnz     .do_hypot               / branch if y is NaN
 130         / push&pop x in case x is a SNaN
 131         fldl    4(%esp)
 132         fstp    %st(0)
 133         /  y = +/-INF, so return |y|
 134         fldl    12(%esp)
 135         fabs
 136         ret
 137         .align  4
 138         SET_SIZE(hypot)