1.file "modfl.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// 02/02/00 Initial version 42// 04/04/00 Improved speed, corrected result for NaN input 43// 05/30/00 Fixed bug for exponent 0x1003e 44// 12/22/00 Fixed so inexact flag is never set, and invalid is not set for 45// qnans nor for inputs larger than 2^63. 46// 05/20/02 Cleaned up namespace and sf0 syntax 47// 02/10/03 Reordered header: .section, .global, .proc, .align 48// 49// API 50//============================================================== 51// long double modfl(long double x, long double *iptr) 52// break a floating point x number into fraction and an exponent 53// 54// input floating point f8, address in r34 55// output floating point f8 (x fraction), and *iptr (x integral part) 56// 57// OVERVIEW 58//============================================================== 59// 60// NO FRACTIONAL PART: HUGE 61// If 62// for double-extended 63// If the true exponent is >= 63 64// 1003e ==> 1003e -ffff = 3f = 63(dec) 65// then 66// we are already an integer (p9 true) 67 68// NO INTEGER PART: SMALL 69// Is f8 exponent less than register bias (that is, is it 70// less than 1). If it is, get the right sign of 71// zero and store this in iptr. 72 73// CALCULATION: NOT HUGE, NOT SMALL 74// To get the integer part 75// Take the floating-point input and truncate 76// then convert this integer to fp Call it MODF_INTEGER_PART 77 78// Subtract MODF_INTEGER_PART from MODF_NORM_F8 to get fraction part 79// Then put fraction part in f8 80// put integer part MODF_INTEGER_PART into *iptr 81 82// Registers used 83//============================================================== 84 85// predicate registers used: 86// p6 - p13 87 88// 0xFFFF 0x1003e 89// -----------------------+-----------------+------------- 90// SMALL | NORMAL | HUGE 91// p11 --------------->|<----- p12 ----->| <-------------- p9 92// p10 --------------------------------->| 93// p13 --------------------------------------------------->| 94// 95 96// floating-point registers used: 97MODF_NORM_F8 = f9 98MODF_FRACTION_PART = f10 99MODF_INTEGER_PART = f11 100MODF_INT_INTEGER_PART = f12 101 102 103// general registers used 104modf_signexp = r14 105modf_GR_no_frac = r15 106modf_GR_FFFF = r16 107modf_17_ones = r17 108modf_exp = r18 109// r34 = iptr 110 111 112.section .text 113GLOBAL_LIBM_ENTRY(modfl) 114 115// Main path is p9, p11, p8 FALSE and p12 TRUE 116 117// Assume input is normalized and get signexp 118// Normalize input just in case 119// Form exponent bias 120{ .mfi 121 getf.exp modf_signexp = f8 122 fnorm.s0 MODF_NORM_F8 = f8 123 addl modf_GR_FFFF = 0xffff, r0 124} 125// Get integer part of input 126// Form exponent mask 127{ .mfi 128 nop.m 999 129 fcvt.fx.trunc.s1 MODF_INT_INTEGER_PART = f8 130 mov modf_17_ones = 0x1ffff ;; 131} 132 133// Is x nan or inf? 134// qnan snan inf norm unorm 0 -+ 135// 1 1 1 0 0 0 11 = 0xe3 NAN_INF 136// Form biased exponent where input only has an integer part 137{ .mfi 138 nop.m 999 139 fclass.m.unc p6,p13 = f8, 0xe3 140 addl modf_GR_no_frac = 0x1003e, r0 ;; 141} 142 143// Mask to get exponent 144// Is x unnorm? 145// qnan snan inf norm unorm 0 -+ 146// 0 0 0 0 1 0 11 = 0x0b UNORM 147// Set p13 to indicate calculation path, else p6 if nan or inf 148{ .mfi 149 and modf_exp = modf_17_ones, modf_signexp 150 fclass.m.unc p8,p0 = f8, 0x0b 151 nop.i 999 ;; 152} 153 154// p11 <== SMALL, no integer part, fraction is everyting 155// p9 <== HUGE, no fraction part, integer is everything 156// p12 <== NORMAL, fraction part and integer part 157{ .mii 158(p13) cmp.lt.unc p11,p10 = modf_exp, modf_GR_FFFF 159 nop.i 999 160 nop.i 999 ;; 161} 162 163// Is x inf? p6 if inf, p7 if nan 164{ .mfb 165(p10) cmp.ge.unc p9,p12 = modf_exp, modf_GR_no_frac 166(p6) fclass.m.unc p6,p7 = f8, 0x23 167(p8) br.cond.spnt MODF_DENORM ;; 168} 169 170MODF_COMMON: 171// For HUGE set fraction to signed 0 172{ .mfi 173 nop.m 999 174(p9) fmerge.s f8 = f8,f0 175 nop.i 999 176} 177// For HUGE set integer part to normalized input 178{ .mfi 179 nop.m 999 180(p9) fnorm.s0 MODF_INTEGER_PART = MODF_NORM_F8 181 nop.i 999 ;; 182} 183 184// For SMALL set fraction to normalized input, integer part to signed 0 185{ .mfi 186 nop.m 999 187(p11) fmerge.s MODF_INTEGER_PART = f8,f0 188 nop.i 999 189} 190{ .mfi 191 nop.m 999 192(p11) fnorm.s0 f8 = MODF_NORM_F8 193 nop.i 999 ;; 194} 195 196// For NORMAL float the integer part 197{ .mfi 198 nop.m 999 199(p12) fcvt.xf MODF_INTEGER_PART = MODF_INT_INTEGER_PART 200 nop.i 999 ;; 201} 202 203// If x inf set integer part to INF, fraction to signed 0 204{ .mfi 205(p6) stfe [r34] = MODF_NORM_F8 206(p6) fmerge.s f8 = f8,f0 207 nop.i 999 ;; 208} 209 210// If x nan set integer and fraction parts to NaN (quietized) 211{ .mfi 212(p7) stfe [r34] = MODF_NORM_F8 213(p7) fmerge.s f8 = MODF_NORM_F8, MODF_NORM_F8 214 nop.i 999 ;; 215} 216 217{ .mmi 218(p9) stfe [r34] = MODF_INTEGER_PART 219 nop.m 999 220 nop.i 999 ;; 221} 222 223// For NORMAL compute fraction part 224{ .mfi 225(p11) stfe [r34] = MODF_INTEGER_PART 226(p12) fms.s0 f8 = MODF_NORM_F8,f1, MODF_INTEGER_PART 227 nop.i 999 ;; 228} 229 230// For NORMAL test if fraction part is zero; if so append correct sign 231{ .mfi 232 nop.m 999 233(p12) fcmp.eq.unc.s0 p7,p0 = MODF_NORM_F8, MODF_INTEGER_PART 234 nop.i 999 ;; 235} 236 237{ .mfi 238(p12) stfe [r34] = MODF_INTEGER_PART 239 nop.f 999 240 nop.i 999 ;; 241} 242 243// For NORMAL if fraction part is zero append sign of input 244{ .mfb 245 nop.m 999 246(p7) fmerge.s f8 = MODF_NORM_F8, f0 247 br.ret.sptk b0 ;; 248} 249 250MODF_DENORM: 251// If x unorm get signexp from normalized input 252// If x unorm get integer part from normalized input 253{ .mfi 254 getf.exp modf_signexp = MODF_NORM_F8 255 fcvt.fx.trunc.s1 MODF_INT_INTEGER_PART = MODF_NORM_F8 256 nop.i 999 ;; 257} 258 259// If x unorm mask to get exponent 260{ .mmi 261 and modf_exp = modf_17_ones, modf_signexp ;; 262 cmp.lt.unc p11,p10 = modf_exp, modf_GR_FFFF 263 nop.i 999 ;; 264} 265 266{ .mfb 267(p10) cmp.ge.unc p9,p12 = modf_exp, modf_GR_no_frac 268 nop.f 999 269 br.cond.spnt MODF_COMMON ;; 270} 271 272GLOBAL_LIBM_END(modfl) 273libm_alias_ldouble_other (modf, modf) 274