1.file "nearbyintl.s" 2 3 4// Copyright (c) 2000 - 2003, Intel Corporation 5// All rights reserved. 6// 7// 8// Redistribution and use in source and binary forms, with or without 9// modification, are permitted provided that the following conditions are 10// met: 11// 12// * Redistributions of source code must retain the above copyright 13// notice, this list of conditions and the following disclaimer. 14// 15// * Redistributions in binary form must reproduce the above copyright 16// notice, this list of conditions and the following disclaimer in the 17// documentation and/or other materials provided with the distribution. 18// 19// * The name of Intel Corporation may not be used to endorse or promote 20// products derived from this software without specific prior written 21// permission. 22 23// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS 27// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 28// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 29// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 31// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING 32// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34// 35// Intel Corporation is the author of this code, and requests that all 36// problem reports or change requests be submitted to it directly at 37// http://www.intel.com/software/products/opensource/libraries/num.htm. 38// 39// History 40//============================================================== 41// 10/19/00 Created 42// 02/08/01 Corrected behavior for all rounding modes. 43// 05/20/02 Cleaned up namespace and sf0 syntax 44// 02/10/03 Reordered header: .section, .global, .proc, .align 45// 07/25/03 Improved performance 46//============================================================== 47 48// API 49//============================================================== 50// long double nearbyintl(long double x) 51//============================================================== 52 53// general input registers: 54// r14 - r21 55 56rSignexp = r14 57rExp = r15 58rExpMask = r16 59rBigexp = r17 60rFpsr = r19 61rRcs0 = r20 62rRcs0Mask = r21 63 64// floating-point registers: 65// f8 - f10 66 67fXInt = f9 68fNormX = f10 69 70// predicate registers used: 71// p6 - p10 72 73// Overview of operation 74//============================================================== 75// long double nearbyintl(long double x) 76// Return an integer value (represented as a long double) that is x 77// rounded to integer in current rounding mode 78// Inexact is not set, otherwise result identical with rint. 79//============================================================== 80 81// double_extended 82// if the exponent is > 1003e => 3F(true) = 63(decimal) 83// we have a significand of 64 bits 1.63-bits. 84// If we multiply by 2^63, we no longer have a fractional part 85// So input is an integer value already. 86 87// double 88// if the exponent is >= 10033 => 34(true) = 52(decimal) 89// 34 + 3ff = 433 90// we have a significand of 53 bits 1.52-bits. (implicit 1) 91// If we multiply by 2^52, we no longer have a fractional part 92// So input is an integer value already. 93 94// single 95// if the exponent is > 10016 => 17(true) = 23(decimal) 96// we have a significand of 24 bits 1.23-bits. (implicit 1) 97// If we multiply by 2^23, we no longer have a fractional part 98// So input is an integer value already. 99 100.section .text 101GLOBAL_LIBM_ENTRY(__nearbyintl) 102 103{ .mfi 104 getf.exp rSignexp = f8 // Get signexp, recompute if unorm 105 fclass.m p7,p0 = f8, 0x0b // Test x unorm 106 addl rBigexp = 0x1003e, r0 // Set exponent at which is integer 107} 108{ .mfi 109 nop.m 0 110 fcvt.fx.s1 fXInt = f8 // Convert to int in significand 111 mov rExpMask = 0x1FFFF // Form exponent mask 112} 113;; 114 115{ .mfi 116 mov rFpsr = ar40 // Read fpsr -- check rc.s0 117 fclass.m p6,p0 = f8, 0x1e3 // Test x natval, nan, inf 118 nop.i 0 119} 120{ .mfb 121 nop.m 0 122 fnorm.s1 fNormX = f8 // Normalize input 123(p7) br.cond.spnt RINT_UNORM // Branch if x unorm 124} 125;; 126 127 128RINT_COMMON: 129// Return here from RINT_UNORM 130{ .mfb 131 and rExp = rSignexp, rExpMask // Get biased exponent 132(p6) fma.s0 f8 = f8, f1, f0 // Result if x natval, nan, inf 133(p6) br.ret.spnt b0 // Exit if x natval, nan, inf 134} 135;; 136 137{ .mfi 138 mov rRcs0Mask = 0x0c00 // Mask for rc.s0 139 fcvt.xf f8 = fXInt // Result assume |x| < 2^63 140 cmp.ge p7,p8 = rExp, rBigexp // Is |x| >= 2^63? 141} 142;; 143 144// We must correct result if |x| >= 2^63 145{ .mfi 146 nop.m 0 147(p7) fma.s0 f8 = fNormX, f1, f0 // If |x| >= 2^63, result x 148 nop.i 0 149} 150;; 151 152{ .mfi 153 nop.m 0 154(p8) fmerge.s f8 = fNormX, f8 // Make sign nearbyintl(x)= sign x 155 nop.i 0 156} 157;; 158 159{ .mfi 160(p8) and rRcs0 = rFpsr, rRcs0Mask // Get rounding mode for sf0 161 nop.f 0 162 nop.i 0 163} 164;; 165 166// If |x| < 2^63 we must test for other rounding modes 167{ .mbb 168(p8) cmp.ne.unc p10,p0 = rRcs0, r0 // Test for other rounding modes 169(p10) br.cond.spnt RINT_NOT_ROUND_NEAREST // Branch if not round nearest 170 br.ret.sptk b0 // Exit main path if round nearest 171} 172;; 173 174 175RINT_UNORM: 176// Here if x unorm 177{ .mfb 178 getf.exp rSignexp = fNormX // Get signexp, recompute if unorm 179 fcmp.eq.s0 p7,p0 = f8, f0 // Dummy op to set denormal flag 180 br.cond.sptk RINT_COMMON // Return to main path 181} 182;; 183 184RINT_NOT_ROUND_NEAREST: 185// Here if not round to nearest, and |x| < 2^63 186// Set rounding mode of s2 to that of s0, and repeat the conversion using s2 187{ .mfi 188 nop.m 0 189 fsetc.s2 0x7f, 0x40 190 nop.i 0 191} 192;; 193 194{ .mfi 195 nop.m 0 196 fcvt.fx.s2 fXInt = fNormX // Convert to int in significand 197 nop.i 0 198} 199;; 200 201{ .mfi 202 nop.m 0 203 fcvt.xf f8 = fXInt // Expected result 204 nop.i 0 205} 206;; 207 208// Be sure sign of result = sign of input. Fixes cases where result is 0. 209{ .mfb 210 nop.m 0 211 fmerge.s f8 = fNormX, f8 212 br.ret.sptk b0 // Exit main path 213} 214;; 215 216GLOBAL_LIBM_END(__nearbyintl) 217libm_alias_ldouble (__nearbyint, nearbyint) 218