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_protos.h"
  34 
  35         .data
  36         .align  4
  37 inf:
  38         .long   0x7f800000
  39 
  40         ENTRY(hypot)
  41         movl    8(%esp),%eax            / eax <-- hi_32(x)
  42         andl    $0x7fffffff,%eax        / eax <-- hi_32(|x|)
  43         jz      .x_maybe_0              / if x = +/-0, return |y|
  44         subl    $0x7ff00000,%eax        / eax <-- hi_32(|x|) - hi_32(INF)
  45         jz      .x_maybe_inf
  46 .check_y:
  47         movl    16(%esp),%eax           / eax <-- hi_32(y)
  48         andl    $0x7fffffff,%eax        / eax <-- hi_32(|y|)
  49         jz      .y_maybe_0              / if y = +/-0, return |x|
  50         subl    $0x7ff00000,%eax        / eax <-- hi_32(|y|) - hi_32(INF)
  51         jz      .y_maybe_inf
  52 .do_hypot:
  53         fldl    12(%esp)                / ,y
  54         fmul    %st(0),%st              / ,y*y
  55         fldl    4(%esp)                 / x,y*y
  56         fmul    %st(0),%st              / x*x,y*y
  57         faddp   %st,%st(1)              / x*x+y*y
  58         fsqrt                           / sqrt(x*x+y*y)
  59         subl    $8,%esp
  60         fstpl   (%esp)                  / round to double
  61         fldl    (%esp)                  / sqrt(x*x+y*y) rounded to double
  62         PIC_SETUP(1)
  63         flds    PIC_L(inf)              / inf , sqrt(x*x+y*y)
  64         PIC_WRAPUP
  65         addl    $8,%esp
  66         fucomp
  67         fstsw   %ax                     / store status in %ax
  68         sahf                            / 80387 flags in %ah to 80386 flags
  69         jz      .maybe_ovflw
  70         ret
  71 
  72 .maybe_ovflw:
  73         jnp     .ovflw
  74         ret
  75 
  76 .ovflw:
  77         /       overflow occurred
  78         fstp    %st(0)                  / stack empty
  79         pushl   %ebp
  80         movl    %esp,%ebp
  81         PIC_SETUP(2)
  82         pushl   $4
  83         pushl   20(%ebp)                / high y
  84         pushl   16(%ebp)                / low y
  85         pushl   12(%ebp)                / high x
  86         pushl   8(%ebp)                 / low x
  87         call    PIC_F(_SVID_libm_err)
  88         addl    $20,%esp
  89         PIC_WRAPUP
  90         leave
  91         ret
  92 
  93 .x_maybe_0:
  94         movl    4(%esp),%ecx            / ecx <-- lo_32(x)
  95         orl     %ecx,%eax               / is x = +/-0?
  96         jnz     .check_y                / branch if x is denormal
  97         /  x = +/-0, so return |y|
  98         fldl    12(%esp)
  99         fabs
 100         ret
 101 
 102 .x_maybe_inf:
 103         movl    4(%esp),%ecx            / ecx <-- lo_32(x)
 104         orl     %ecx,%eax               / is x = +/-INF?
 105         jnz     .check_y                / branch if x is NaN
 106         / push&pop y in case y is a SNaN
 107         fldl    12(%esp)
 108         fstp    %st(0)
 109         / x = +/-INF, so return |x|
 110         fldl    4(%esp)
 111         fabs
 112         ret
 113 
 114 .y_maybe_0:
 115         movl    12(%esp),%ecx           / ecx <-- lo_32(y)
 116         orl     %ecx,%eax               / is y = +/-0?
 117         jnz     .do_hypot               / branch if y is denormal
 118         /  y = +/-0, so return |x|
 119         fldl    4(%esp)
 120         fabs
 121         ret
 122 
 123 .y_maybe_inf:
 124         movl    12(%esp),%ecx           / ecx <-- lo_32(y)
 125         orl     %ecx,%eax               / is y = +/-INF?
 126         jnz     .do_hypot               / branch if y is NaN
 127         / push&pop x in case x is a SNaN
 128         fldl    4(%esp)
 129         fstp    %st(0)
 130         /  y = +/-INF, so return |y|
 131         fldl    12(%esp)
 132         fabs
 133         ret
 134         .align  4
 135         SET_SIZE(hypot)