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