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   "nexttowardl.s"
  30 
  31 #include "libm.h"
  32 LIBM_ANSI_PRAGMA_WEAK(nexttowardl,function)
  33 #include "libm_synonyms.h"
  34 
  35         .section .rodata
  36         .align  4
  37 .LFmaxl:        .long   0xffffffff,0xffffffff,0x00007ffe
  38 .LFminl:        .long   0x1,0x0,0x0
  39 
  40 
  41         ENTRY(nexttowardl)
  42         pushl   %ebp
  43         movl    %esp,%ebp
  44         fldt    20(%ebp)        / y
  45         subl    $12,%esp
  46         fldt    8(%ebp)         / load x
  47         fucom                   / x : y
  48         fstsw   %ax
  49         sahf
  50         jp      .LNaN
  51         je      .Lequal
  52         fstp    %st(1)          / x
  53         ja      .Lbigger
  54         / x < y
  55         ftst
  56         movl    $1,-12(%ebp)    /// -12(%ebp) contains Fminl
  57         movl    $0,-8(%ebp)
  58         movl    $0,%ecx                 /// final needs this
  59         movl    %ecx,-4(%ebp)
  60         fnstsw  %ax
  61         sahf
  62         je      .Lfinal
  63         ja      .Laddulp
  64         jb      .Lsubulp
  65 .Lbigger:
  66         / x > y
  67         ftst
  68         movl    $1,-12(%ebp)    /// -12(%ebp) contains -Fminl
  69         movl    $0,-8(%ebp)
  70         movl    $0x00008000,%ecx        /// final needs this
  71         movl    %ecx,-4(%ebp)
  72         fnstsw  %ax
  73         sahf
  74         je      .Lfinal
  75         jb      .Laddulp
  76 .Lsubulp:
  77         movl    12(%ebp),%edx   / high word of significand of x
  78         movl    16(%ebp),%ecx   / x's exponent
  79         andl    $0x0000ffff,%ecx
  80         movl    %edx,%eax
  81         not     %eax
  82         andl    $0x80000000,%eax        / look at explicit leading bit
  83         orl     %ecx,%eax
  84         andl    $0x80007fff,%eax
  85         jnz     .Lnot_pseudonormal      / zero value implies pseudonormal
  86         addl    $1,%ecx         / if pseudonormal, turn into equivalent normal
  87 .Lnot_pseudonormal:
  88         movl    8(%ebp),%eax    / low x
  89         subl    $1,%eax         / low x - ulp
  90         movl    %eax,-12(%ebp)
  91         cmpl    $0xffffffff,%eax        / this means low x was 0
  92         jz      .Lborrow
  93         movl    %edx,-8(%ebp)
  94         movl    %ecx,-4(%ebp)
  95         jmp     .Lfinal
  96 .Lborrow:
  97         cmpl    $0x80000000,%edx        / look at high x
  98         je      .Lsecond_borrow
  99         subl    $1,%edx
 100         movl    %edx,-8(%ebp)
 101         movl    %ecx,-4(%ebp)
 102         jmp     .Lfinal
 103 .Lsecond_borrow:
 104         movl    %ecx,%eax
 105         andl    $0x7fff,%eax    / look at exp x without sign bit
 106         cmpl    $1,%eax
 107         jbe     .Lsubnormal_result      / exp > 1 ==> result will be normal
 108         movl    $0xffffffff,-8(%ebp)
 109         subl    $1,%ecx
 110         movl    %ecx,-4(%ebp)
 111         jmp     .Lfinal
 112 .Lsubnormal_result:
 113         movl    $0x7fffffff,-8(%ebp)
 114         movl    %ecx,%eax
 115         andl    $0x8000,%eax    / look at sign bit
 116         jz      .Lpositive
 117         movl    $0x8000,%ecx
 118         movl    %ecx,-4(%ebp)
 119         jmp     .Lfinal
 120 .Lpositive:
 121         movl    $0,%ecx
 122         movl    %ecx,-4(%ebp)
 123         jmp     .Lfinal
 124 .Laddulp:
 125         movl    12(%ebp),%edx   / high x
 126         movl    16(%ebp),%ecx   / x's exponent
 127         andl    $0x0000ffff,%ecx
 128         movl    %edx,%eax
 129         not     %eax
 130         andl    $0x80000000,%eax        / look at explicit leading bit
 131         orl     %ecx,%eax
 132         andl    $0x80007fff,%eax
 133         jnz     .Lnot_pseudonormal_2    / zero value implies pseudonormal
 134         addl    $1,%ecx
 135 .Lnot_pseudonormal_2:
 136         movl    8(%ebp),%eax    / low x
 137         addl    $1,%eax         / low x + ulp
 138         movl    %eax,-12(%ebp)
 139         jz      .Lcarry         / jump if the content of %eax is 0
 140         movl    %edx,-8(%ebp)
 141         movl    %ecx,-4(%ebp)
 142         jmp .Lfinal
 143 .Lcarry:
 144         movl    %edx,%eax
 145         andl    $0x7fffffff,%eax
 146         cmpl    $0x7fffffff,%eax        / look at high x
 147         je      .Lsecond_carry
 148         addl    $1,%edx
 149         movl    %edx,-8(%ebp)
 150         movl    %ecx,-4(%ebp)
 151         jmp     .Lfinal
 152 .Lsecond_carry:
 153         movl    $0x80000000,-8(%ebp)
 154         addl    $1,%ecx
 155         movl    %ecx,-4(%ebp)
 156 .Lfinal:
 157         fstp    %st(0)
 158         fldt    -12(%ebp)
 159         andl    $0x00007fff,%ecx
 160         jz      .Lunderflow
 161         cmpw    $0x7fff,%cx
 162         je      .Loverflow
 163         jmp     .Lreturn
 164 .Loverflow:
 165         PIC_SETUP(1)
 166         fldt    PIC_L(.LFmaxl)
 167         PIC_WRAPUP
 168         fmulp   %st,%st(0)      / create overflow signal
 169         jmp     .Lreturn
 170 .Lunderflow:
 171         PIC_SETUP(2)
 172         fldt    PIC_L(.LFminl)
 173         PIC_WRAPUP
 174         fmulp   %st,%st(0)      / create underflow signal
 175         jmp     .Lreturn
 176 .Lequal:
 177         fstp    %st(0)          / C99 says to return y when x == y
 178         jmp     .Lreturn
 179 .LNaN:
 180         faddp   %st,%st(1)      / x+y,x
 181 .Lreturn:
 182         fwait
 183         leave
 184         ret
 185         .align  4
 186         SET_SIZE(nexttowardl)