summary refs log tree commit diff
path: root/sysdeps/ia64/fpu/s_ceil.S
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/ia64/fpu/s_ceil.S')
-rw-r--r--sysdeps/ia64/fpu/s_ceil.S274
1 files changed, 118 insertions, 156 deletions
diff --git a/sysdeps/ia64/fpu/s_ceil.S b/sysdeps/ia64/fpu/s_ceil.S
index f7e6d2cfa6..d1d2980618 100644
--- a/sysdeps/ia64/fpu/s_ceil.S
+++ b/sysdeps/ia64/fpu/s_ceil.S
@@ -1,10 +1,10 @@
 .file "ceil.s"
 
-// Copyright (C) 2000, 2001, Intel Corporation
+
+// Copyright (c) 2000 - 2003, Intel Corporation
 // All rights reserved.
-// 
-// Contributed 2/2/2000 by John Harrison, Ted Kubaska, Bob Norin, Shane Story,
-// and Ping Tak Peter Tang of the Computational Software Lab, Intel Corporation.
+//
+// Contributed 2000 by the Intel Numerics Group, Intel Corporation
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -20,90 +20,67 @@
 // * The name of Intel Corporation may not be used to endorse or promote
 // products derived from this software without specific prior written
 // permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS 
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS
 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
-// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING
-// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
-// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
-// 
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
 // Intel Corporation is the author of this code, and requests that all
-// problem reports or change requests be submitted to it directly at 
-// http://developer.intel.com/opensource.
+// problem reports or change requests be submitted to it directly at
+// http://www.intel.com/software/products/opensource/libraries/num.htm.
 //
-
-#include "libm_support.h"
-
-.align 32
-.global ceil#
-
-.section .text
-.proc  ceil#
-.align 32
-
 // History
 //==============================================================
-// 2/02/00: Initial version
-// 6/13/00: Improved speed
-// 6/27/00: Eliminated incorrect invalid flag setting
+// 02/02/00 Initial version
+// 06/13/00 Improved speed
+// 06/27/00 Eliminated incorrect invalid flag setting
+// 05/20/02 Cleaned up namespace and sf0 syntax
+// 01/28/03 Improved performance
+//==============================================================
 
 // API
 //==============================================================
 // double ceil(double x)
+//==============================================================
 
-// general input registers:  
-
-ceil_GR_FFFF      = r14
-ceil_GR_signexp   = r15
-ceil_GR_exponent  = r16
-ceil_GR_expmask   = r17
-ceil_GR_bigexp    = r18
-
-
-// predicate registers used: 
+// general input registers:
+// r14 - r19
 
-// p6  ==> Input is NaN, infinity, zero
-// p7  ==> Input is denormal
-// p8  ==> Input is <0
-// p9  ==> Input is >=0
-// p10 ==> Input is already an integer (bigger than largest integer)
-// p11 ==> Input is not a large integer
-// p12 ==> Input is a smaller integer
-// p13 ==> Input is not an even integer, so inexact must be set
-// p14 ==> Input is between -1 and 0, so result will be -0 and inexact
+rSignexp   = r14
+rExp       = r15
+rExpMask   = r16
+rBigexp    = r17
+rM1        = r18
+rSignexpM1 = r19
 
+// floating-point registers:
+// f8 - f13
 
-// floating-point registers used: 
+fXInt      = f9
+fNormX     = f10
+fTmp       = f11
+fAdj       = f12
+fPreResult = f13
 
-CEIL_SIGNED_ZERO  = f7
-CEIL_NORM_f8      = f9                        
-CEIL_FFFF         = f10 
-CEIL_INEXACT      = f11 
-CEIL_FLOAT_INT_f8 = f12
-CEIL_INT_f8       = f13
-CEIL_adj          = f14
-CEIL_MINUS_ONE    = f15
+// predicate registers used:
+// p6 - p10
 
 // Overview of operation
 //==============================================================
-
 // double ceil(double x)
-// Return an integer value (represented as a double) that is the smallest 
+// Return an integer value (represented as a double) that is the smallest
 // value not less than x
 // This is x rounded toward +infinity to an integral value.
 // Inexact is set if x != ceil(x)
-// **************************************************************************
-
-// Set denormal flag for denormal input and
-// and take denormal fault if necessary.
-
-// Is the input an integer value already?
+//==============================================================
 
 // double_extended
 // if the exponent is > 1003e => 3F(true) = 63(decimal)
@@ -124,139 +101,124 @@ CEIL_MINUS_ONE    = f15
 // If we multiply by 2^23, we no longer have a fractional part
 // So input is an integer value already.
 
-// If x is NAN, ZERO, or INFINITY, then  return
-
-// qnan snan inf norm     unorm 0 -+
-// 1    1    1   0        0     1 11     0xe7
-
 
-ceil:
+.section .text
+GLOBAL_LIBM_ENTRY(ceil)
 
 { .mfi
-      getf.exp ceil_GR_signexp  = f8
-      fcvt.fx.trunc.s1     CEIL_INT_f8  = f8
-      addl        ceil_GR_bigexp = 0x10033, r0
+      getf.exp         rSignexp  = f8        // Get signexp, recompute if unorm
+      fclass.m         p7,p0 = f8, 0x0b      // Test x unorm
+      addl             rBigexp = 0x10033, r0 // Set exponent at which is integer
 }
 { .mfi
-      addl        ceil_GR_FFFF      = -1,r0
-      fcmp.lt.s1  p8,p9 = f8,f0
-      mov         ceil_GR_expmask    = 0x1FFFF ;;
+      mov              rM1 = -1              // Set all ones
+      fcvt.fx.trunc.s1 fXInt  = f8           // Convert to int in significand
+      mov              rExpMask    = 0x1FFFF // Form exponent mask
 }
+;;
 
-// p7 ==> denorm
 { .mfi
-      setf.sig    CEIL_FFFF  = ceil_GR_FFFF
-      fclass.m    p7,p0 = f8, 0x0b
-      nop.i 999
+      mov              rSignexpM1  = 0x2FFFF // Form signexp of -1
+      fcmp.lt.s1       p8,p9 = f8, f0        // Test x < 0
+      nop.i            0
 }
-{ .mfi
-      nop.m 999
-      fnorm           CEIL_NORM_f8  = f8
-      nop.i 999 ;;
+{ .mfb
+      setf.sig         fTmp = rM1            // Make const for setting inexact
+      fnorm.s1         fNormX  = f8          // Normalize input
+(p7)  br.cond.spnt     CEIL_UNORM            // Branch if x unorm
 }
+;;
 
-// Form 0 with sign of input in case negative zero is needed
-{ .mfi
-      nop.m 999
-      fmerge.s           CEIL_SIGNED_ZERO = f8, f0
-      nop.i 999
-}
+CEIL_COMMON:
+// Return here from CEIL_UNORM
 { .mfi
-      nop.m 999
-      fsub.s1           CEIL_MINUS_ONE = f0, f1
-      nop.i 999 ;;
-}
-
-// p6 ==> NAN, INF, ZERO
-{ .mfb
-      nop.m 999
-      fclass.m      p6,p10 = f8, 0xe7
-(p7)  br.cond.spnt  L(CEIL_DENORM) ;;
+      nop.m            0
+      fclass.m         p6,p0 = f8, 0x1e7     // Test x natval, nan, inf, 0
+      nop.i            0
 }
+;;
 
-L(CEIL_COMMON):
 .pred.rel "mutex",p8,p9
-// Set adjustment to add to trunc(x) for result
-//   If x>0,  adjustment is 1.0
-//   If x<=0, adjustment is 0.0
 { .mfi
-      and      ceil_GR_exponent = ceil_GR_signexp, ceil_GR_expmask
-(p9)  fadd.s1  CEIL_adj = f1,f0
-      nop.i 999
+      nop.m            0
+(p8)  fma.s1           fAdj = f0, f0, f0     // If x < 0, adjustment is 0
+      nop.i            0
 }
 { .mfi
-      nop.m 999
-(p8)  fadd.s1  CEIL_adj = f0,f0
-      nop.i 999 ;;
+      nop.m            0
+(p9)  fma.s1           fAdj = f1, f1, f0     // If x > 0, adjustment is +1
+      nop.i            0
 }
+;;
 
 { .mfi
-(p10) cmp.ge.unc    p10,p11 = ceil_GR_exponent, ceil_GR_bigexp
-(p6)  fnorm.d f8 = f8
-      nop.i 999 ;;
+      nop.m            0
+      fcvt.xf          fPreResult = fXInt    // trunc(x)
+      nop.i            0
 }
-
-{ .mfi
-      nop.m 999
-(p11) fcvt.xf         CEIL_FLOAT_INT_f8   = CEIL_INT_f8
-      nop.i 999 ;;
+{ .mfb
+      nop.m            0
+(p6)  fma.d.s0         f8 = f8, f1, f0       // Result if x natval, nan, inf, 0
+(p6)  br.ret.spnt      b0                    // Exit if x natval, nan, inf, 0
 }
+;;
 
-{ .mfi
-      nop.m 999
-(p10) fnorm.d f8 = CEIL_NORM_f8
-      nop.i 999 ;;
+{ .mmi
+      and              rExp = rSignexp, rExpMask // Get biased exponent
+;;
+      cmp.ge           p7,p6 = rExp, rBigexp  // Is |x| >= 2^52?
+(p8)  cmp.lt.unc       p10,p0 = rSignexp, rSignexpM1 // Is -1 < x < 0?
 }
+;;
 
-// Is -1 < x < 0?  If so, result will be -0.  Special case it with p14 set.
+// If -1 < x < 0, we turn off p6 and compute result as -0
 { .mfi
-      nop.m 999
-(p8)  fcmp.gt.unc.s1 p14,p0 = CEIL_NORM_f8, CEIL_MINUS_ONE
-      nop.i 999 ;;
+(p10) cmp.ne           p6,p0 = r0,r0
+(p10) fmerge.s         f8 = fNormX, f0
+      nop.i            0
 }
+;;
 
+.pred.rel "mutex",p6,p7
 { .mfi
-(p14) cmp.ne  p11,p0 = r0,r0
-(p14) fnorm.d f8 = CEIL_SIGNED_ZERO
-      nop.i 999
+      nop.m            0
+(p6)  fma.d.s0         f8 = fPreResult, f1, fAdj // Result if !int, |x| < 2^52
+      nop.i            0
 }
 { .mfi
-      nop.m 999
-(p14) fmpy.s0     CEIL_INEXACT = CEIL_FFFF,CEIL_FFFF
-      nop.i 999 ;;
+      nop.m            0
+(p7)  fma.d.s0         f8 = fNormX, f1, f0    // Result, if |x| >= 2^52
+(p10) cmp.eq           p6,p0 = r0,r0          // If -1 < x < 0, turn on p6 again
 }
+;;
 
 { .mfi
-      nop.m 999
-(p11) fadd.d   f8 = CEIL_FLOAT_INT_f8,CEIL_adj
-      nop.i 999 ;;
-}
-{ .mfi
-      nop.m 999
-(p11) fcmp.eq.unc.s1  p12,p13  = CEIL_FLOAT_INT_f8, CEIL_NORM_f8
-      nop.i 999 ;;
+      nop.m            0
+(p6)  fcmp.eq.unc.s1   p8, p9 = fPreResult, fNormX // Is trunc(x) = x ?
+      nop.i            0
 }
+;;
 
-// Set inexact if result not equal to input
 { .mfi
-      nop.m 999
-(p13) fmpy.s0     CEIL_INEXACT = CEIL_FFFF,CEIL_FFFF
-      nop.i 999
+      nop.m            0
+(p9)  fmpy.s0          fTmp = fTmp, fTmp      // Dummy to set inexact
+      nop.i            0
 }
-// Set result to input if integer
 { .mfb
-      nop.m 999
-(p12) fnorm.d f8 = CEIL_NORM_f8
-      br.ret.sptk    b0 ;;
+      nop.m            0
+(p8)  fma.d.s0         f8 = fNormX, f1, f0    // If x int, result normalized x
+      br.ret.sptk      b0                     // Exit main path, 0 < |x| < 2^52
 }
+;;
+
 
-// Here if input denorm
-L(CEIL_DENORM):
+CEIL_UNORM:
+// Here if x unorm
 { .mfb
-      getf.exp ceil_GR_signexp  = CEIL_NORM_f8
-      fcvt.fx.trunc.s1     CEIL_INT_f8  = CEIL_NORM_f8
-      br.cond.sptk  L(CEIL_COMMON) ;;
+      getf.exp         rSignexp  = fNormX     // Get signexp, recompute if unorm
+      fcmp.eq.s0       p7,p0 = f8, f0         // Dummy op to set denormal flag
+      br.cond.sptk     CEIL_COMMON            // Return to main path
 }
+;;
 
-.endp ceil
-ASM_SIZE_DIRECTIVE(ceil)
+GLOBAL_LIBM_END(ceil)