about summary refs log tree commit diff
path: root/sysdeps/ia64/fpu/s_trunc.S
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/ia64/fpu/s_trunc.S')
-rw-r--r--sysdeps/ia64/fpu/s_trunc.S207
1 files changed, 121 insertions, 86 deletions
diff --git a/sysdeps/ia64/fpu/s_trunc.S b/sysdeps/ia64/fpu/s_trunc.S
index b9ad03b5a8..0be91200e3 100644
--- a/sysdeps/ia64/fpu/s_trunc.S
+++ b/sysdeps/ia64/fpu/s_trunc.S
@@ -1,10 +1,11 @@
 .file "trunc.s"
 
-
-// Copyright (c) 2000 - 2003, Intel Corporation
+// Copyright (C) 2000, 2001, Intel Corporation
 // All rights reserved.
-//
-// Contributed 2000 by the Intel Numerics Group, Intel Corporation
+// 
+// Contributed 7/7/2000 by John Harrison, Cristina Iordache, Ted Kubaska,
+// Bob Norin, Shane Story, and Ping Tak Peter Tang of the
+// Computational Software Lab, Intel Corporation.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -20,28 +21,33 @@
 // * 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://www.intel.com/software/products/opensource/libraries/num.htm.
+// problem reports or change requests be submitted to it directly at 
+// http://developer.intel.com/opensource.
 //
+.align 32
+.global trunc#
+
+.section .text
+.proc  trunc#
+.align 32
+
 // History
 //==============================================================
-// 07/07/00 Created
-// 05/20/02 Cleaned up namespace and sf0 syntax
-// 01/20/03 Improved performance and reduced code size
+// 7/7/00: Created 
 //==============================================================
 
 // API
@@ -49,28 +55,25 @@
 // double trunc(double x)
 //==============================================================
 
-// general input registers:
-// r14 - r18
+#include "libm_support.h"
 
-rExpBias   = r14
-rSignexp   = r15
-rExp       = r16
-rExpMask   = r17
-rBigexp    = r18
+// general input registers:  
+TRUNC_GR_FFFF      = r14
+TRUNC_GR_signexp   = r15
+TRUNC_GR_exponent  = r16
+TRUNC_GR_expmask   = r17
+TRUNC_GR_bigexp    = r18
 
 // floating-point registers:
-// f8 - f10
-
-fXtruncInt = f9
-fNormX     = f10
+// f8, f9, f11, f12
 
-// predicate registers used:
-// p6, p7
+// predicate registers used: 
+// p6, p7, p8, p9, p10, p11
 
 // Overview of operation
 //==============================================================
 // double trunc(double x)
-// Return an integer value (represented as a double) less than or
+// Return an integer value (represented as a double) less than or 
 // equal to x in magnitude.
 // This is x rounded toward zero to an integral value.
 //==============================================================
@@ -94,73 +97,105 @@ fNormX     = f10
 // If we multiply by 2^23, we no longer have a fractional part
 // So input is an integer value already.
 
-.section .text
-GLOBAL_LIBM_ENTRY(trunc)
+trunc:
 
 { .mfi
-      getf.exp         rSignexp  = f8        // Get signexp, recompute if unorm
-      fcvt.fx.trunc.s1 fXtruncInt  = f8      // Convert to int in significand
-      addl             rBigexp = 0x10033, r0 // Set exponent at which is integer
+      getf.exp         TRUNC_GR_signexp  = f8
+      fcvt.fx.trunc.s1 f9  = f8
+      addl             TRUNC_GR_bigexp = 0x10033, r0
 }
 { .mfi
-      mov              rExpBias    = 0x0FFFF // Form exponent bias
-      fnorm.s1         fNormX  = f8          // Normalize input
-      mov              rExpMask    = 0x1FFFF // Form exponent mask
-}
-;;
+      mov              TRUNC_GR_FFFF    = 0x0FFFF
+      fnorm.d          f11  = f8
+      mov              TRUNC_GR_expmask    = 0x1FFFF 
+};;
+//    get the exponent of x
+//    convert x to integer in signficand of f9 
+//    Normalize x - this will raise invalid on SNaNs, the
+//    denormal operand flag - and possibly a spurious U flag
+//    get exponent only mask (will exclude sign bit)
 
 { .mfi
       nop.m            0
-      fclass.m         p7,p0 = f8, 0x0b      // Test x unorm
+      fclass.m         p7,p8 = f8, 0x0b  
       nop.i            0
 }
-;;
-
-{ .mfb
+{ .mfi
       nop.m            0
-      fclass.m         p6,p0 = f8, 0x1e3     // Test x natval, nan, inf
-(p7)  br.cond.spnt     TRUNC_UNORM           // Branch if x unorm
-}
-;;
-
-TRUNC_COMMON:
-// Return here from TRUNC_UNORM
+      fcmp.eq.unc.s1   p9,p0 = f8,f0
+      nop.i      0       
+};;
+//    fclass to set p7 if unnorm 
+{ .mmi
+      and              TRUNC_GR_exponent = TRUNC_GR_signexp, TRUNC_GR_expmask ;;
+(p8)  cmp.ge.unc       p10,p11 = TRUNC_GR_exponent, TRUNC_GR_bigexp
+(p8)  cmp.ne.unc       p6,p0 = TRUNC_GR_exponent, TRUNC_GR_signexp
+};;
+//    Get the exponent of x
+//    Test if exponent such that result already an integer
+//    Test if x < 0
+{ .mmi
+(p9)  cmp.eq.andcm     p10,p11 = r0, r0 
+(p6)  cmp.lt.unc       p6,p0 = TRUNC_GR_exponent, TRUNC_GR_FFFF
+      nop.i 0 
+};;
+//    If -1 < x < 0, set p6, turn off p10 and p11, and set result to -0.0
+{ .mfb
+(p6)  cmp.eq.andcm     p10,p11 = r0, r0 
+(p6)  fmerge.s         f8 = f8, f0
+      nop.b 0
+};;
+//    If not a unnorm, set p10 if x already is a big int, nan, or inf?
+//    If not a unnorm, set p10 if x already is a big int, nan, or inf?
+.pred.rel "mutex",p10,p11    
 { .mfb
-      and              rExp = rSignexp, rExpMask // Get biased exponent
-(p6)  fma.d.s0         f8 = f8, f1, f0       // Result if x natval, nan, inf
-(p6)  br.ret.spnt      b0                    // Exit if x natval, nan, inf
-}
-;;
-
-{ .mfi
-      cmp.lt           p6,p0 = rExp, rExpBias // Is |x| < 1?
-      fcvt.xf          f8 = fXtruncInt        // Result, assume 1 <= |x| < 2^52
-      cmp.ge           p7,p0 = rExp, rBigexp  // Is |x| >= 2^52?
-}
-;;
-
-// We must correct result if |x| < 1, or |x| >= 2^52
-.pred.rel "mutex",p6,p7
-{ .mfi
       nop.m            0
-(p6)  fmerge.s         f8 = fNormX, f0        // If |x| < 1, result sgn(x)*0
-      nop.i            0
+(p11) fcvt.xf          f8   = f9 
+      nop.b            0 
 }
 { .mfb
       nop.m            0
-(p7)  fma.d.s0         f8 = fNormX, f1, f0    // If |x| >= 2^52, result x
-      br.ret.sptk      b0                     // Exit main path
-}
-;;
-
-
-TRUNC_UNORM:
-// Here if x unorm
+(p10) fma.d.s1         f8   = f11,f1,f0 
+(p8)  br.ret.sptk      b0 
+};;
+//    If not a unnorm and not an big int, nan,or +/-inf convert signficand
+//    back to f8.
+//    If not a unorm  and a big int, nan, or +/-inf, return fnorm'd x 
+//    If not a unorm, Return
+//    If unnorm, get the exponent again - perhaps it wasn't a denorm. 
+{ .mfb
+(p7)  getf.exp         TRUNC_GR_signexp  = f11
+(p7)  fcvt.fx.trunc.s1 f12   = f11 
+      nop.b 0
+};;
+{ .mfb
+      and              TRUNC_GR_exponent = TRUNC_GR_signexp, TRUNC_GR_expmask
+      fcmp.lt.unc.s1   p9,p0 = f8,f0
+      nop.b            0
+};;
 { .mfb
-      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     TRUNC_COMMON           // Return to main path
+      cmp.ge.unc       p10,p11 = TRUNC_GR_exponent, TRUNC_GR_bigexp
+      nop.f            0
+      nop.b            0
+};;
+// If a unnorm, check to see if value is already a big int. 
+{ .mfb
+      nop.m 0
+(p11) fcvt.xf          f8   = f12 
+      nop.b 0
 }
-;;
-
-GLOBAL_LIBM_END(trunc)
+{ .mfi
+      nop.m 0
+(p10) fma.d.s1         f8   = f11,f1,f0 
+      nop.i 0
+};;
+{ .mfb
+      nop.m 0
+(p9)  fmerge.ns        f8   = f1,f8 
+      br.ret.sptk      b0 
+};;
+// If so return it. Otherwise, return (fcvt.xf(fcvt.fx.trunc(x)))
+// Make sure the result is negative if it should be - that is
+// negative(denormal) -> -0.
+.endp trunc
+ASM_SIZE_DIRECTIVE(trunc)