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 "nextafter.s"
  30 
  31 #include "libm.h"
  32 LIBM_ANSI_PRAGMA_WEAK(nextafter,function)
  33         .weak _nextafter
  34         .type _nextafter,@function
  35 _nextafter      = __nextafter
  36 #include "libm_synonyms.h"
  37 #include "libm_protos.h"
  38 
  39         .data
  40         .align  8
  41 Fmin:   .long   0x1,0x0
  42 ftmp:   .long   0,0             /// WILL WRITE INTO
  43 
  44 
  45         ENTRY(nextafter)
  46         pushl   %ebp
  47         movl    %esp,%ebp
  48         fldl    16(%ebp)        / y
  49         subl    $8,%esp
  50         fldl    8(%ebp)         / load x
  51         fucom                   / x : y
  52         fstsw   %ax
  53         sahf
  54         jp      .NaN
  55         je      .equal
  56         fstp    %st(1)          / x
  57         ja      .bigger
  58         / x < y
  59         ftst
  60         movl    $1,%ecx         /// Fmin
  61         movl    %ecx,-8(%ebp)
  62         movl    $0,%ecx         /// Fmin+4
  63         movl    %ecx,-4(%ebp)
  64         fnstsw  %ax
  65         sahf
  66         je      .final
  67         ja      .addulp
  68         jb      .subulp
  69 .bigger:
  70         / x > y
  71         ftst
  72         movl    $1,%ecx         /// Fmin
  73         movl    %ecx,-8(%ebp)
  74         movl    $0,%ecx         /// Fmin+4
  75         xorl    $0x80000000,%ecx
  76         movl    %ecx,-4(%ebp)
  77         fnstsw  %ax
  78         sahf
  79         je      .final
  80         jb      .addulp
  81 .subulp:
  82         movl    8(%ebp),%eax    / low x
  83         movl    12(%ebp),%ecx   / high x
  84         subl    $1,%eax         / low x - ulp
  85         movl    %eax,-8(%ebp)
  86         sbbl    $0x0,%ecx
  87         movl    %ecx,-4(%ebp)
  88         jmp     .final
  89 .addulp:
  90         movl    8(%ebp),%eax    / low x
  91         movl    12(%ebp),%ecx   / high x
  92         addl    $1,%eax         / low x + ulp
  93         movl    %eax,-8(%ebp)
  94         adcl    $0x0,%ecx
  95         movl    %ecx,-4(%ebp)
  96 
  97 .final:
  98         fstp    %st(0)
  99         fldl    -8(%ebp)
 100         andl    $0x7ff00000,%ecx
 101         jz      .underflow
 102         cmpl    $0x7ff00000,%ecx
 103         je      .overflow
 104         jmp     .return
 105 .overflow:
 106         PIC_SETUP(1)
 107         pushl   $46
 108         fstp    %st(0)          / stack empty
 109         pushl   -4(%ebp)
 110         pushl   -8(%ebp)
 111         pushl   -4(%ebp)
 112         pushl   -8(%ebp)
 113         call    PIC_F(_SVID_libm_err)
 114         addl    $20,%esp
 115         PIC_WRAPUP
 116         jmp     .return
 117 .underflow:
 118         PIC_SETUP(2)
 119         fldl    PIC_L(Fmin)
 120         fmul    %st(0),%st
 121         fstpl   PIC_L(ftmp)     / create underflow signal
 122         PIC_WRAPUP
 123         jmp     .return
 124 .equal:
 125         fstp    %st(0)          / C99 says to return y when x == y
 126         jmp     .return
 127 .NaN:
 128         faddp   %st,%st(1)      / x+y,x
 129 .return:
 130         fwait
 131         leave
 132         ret
 133         .align  4
 134         SET_SIZE(nextafter)