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         RO_DATA
  40         .align  8
  41 .Lconstant:
  42 two54   = 0x00
  43         .word   0x43500000,0x0          !  2**54
  44 twom54  = 0x08
  45         .word   0x3c900000,0x0          !  2**-54
  46 tiny    = 0x10
  47         .word   0x00100000,0x0          !  tiny
  48 
  49 ! variable using fp
  50 x       = -0x8
  51 y       = -0x10
  52 
  53         ENTRY(nextafter)
  54         save    %sp,-128,%sp
  55         PIC_SETUP(l7)
  56         std     %i0,[%fp+x]
  57         or      %g0,%i0,%o0             ! save original arguments
  58         or      %g0,%i1,%o1
  59         std     %i2,[%fp+y]
  60         or      %g0,%i2,%o2
  61         or      %g0,%i3,%o3
  62         ldd     [%fp+x],%f2             ! x
  63         ldd     [%fp+y],%f0             ! y
  64         fcmpd   %f2,%f0                 ! x:y
  65         PIC_SET(l7,.Lconstant,l0)
  66         sethi   %hi(0x80000000),%l1
  67         andn    %i0,%l1,%l4
  68         fbe     9f                      ! next_return
  69         nop
  70         fbu,a   9f                      ! next_return
  71         fmuld   %f2,%f0,%f0             ! + -> * for Cheetah
  72         orcc    %i1,%l4,%g0             ! see if x is zero
  73         bne     1f
  74         tst     %i0
  75     ! x is zero, return sign(y)*min
  76         and     %i2,%l1,%i0
  77         ba      4f                      ! next_final
  78         mov     1,%i1
  79 1:      bge     2f
  80         nop
  81     ! x is negative
  82         fbl     1f                      ! next_subulp
  83         nop
  84         fbg     3f                      ! next_addulp
  85         nop
  86 2:
  87         fbl     3f                      ! next_addulp
  88         nop
  89 1:                                      ! next_subulp
  90         subcc   %i1,1,%i1
  91         ba      4f                      ! next_final
  92         subx    %i0,0,%i0
  93 3:                                      ! next_addulp
  94         addcc   %i1,1,%i1
  95         addx    %i0,0,%i0
  96 4:                                      ! next_final
  97         sethi   %hi(0x7ff00000),%l3
  98         std     %i0,[%fp+x]
  99         andcc   %i0,%l3,%i2
 100         be,a    1f                      ! xflow
 101         ldd     [%l0+tiny],%f2
 102         cmp     %i2,%l3
 103         bne,a   9f                      ! next_return
 104         ldd     [%fp+x],%f0
 105         call    NAME(_SVID_libm_err)    ! overflow
 106         or      %g0,46,%o4
 107         ba      9f
 108         nop
 109 1:                                      ! xflow
 110         fmuld   %f2,%f2,%f2
 111         ldd     [%fp+x],%f0
 112 9:                                      ! next_return
 113         ret
 114         restore
 115 
 116         SET_SIZE(nextafter)