diff options
Diffstat (limited to 'sysdeps/ia64/fpu/s_ceil.S')
-rw-r--r-- | sysdeps/ia64/fpu/s_ceil.S | 274 |
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) |