1.file "logb.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// 02/16/00 Modified to conform to C9X 43// 03/16/00 Improved speed 44// 04/04/00 Unwind support added 45// 05/30/00 Fixed bug when x double-extended denormal 46// 08/15/00 Bundle added after call to __libm_error_support to properly 47// set [the previously overwritten] GR_Parameter_RESULT. 48// 05/20/02 Cleaned up namespace and sf0 syntax 49// 01/20/03 Improved performance 50// 51// API 52//============================================================== 53// double logb( double x ); 54// 55// Overview of operation 56//============================================================== 57// The logb function extracts the exponent of x as an integer in 58// floating-point format. 59// logb computes log2 of x as a double 60// 61// logb is similar to ilogb but differs in the following ways: 62// +-inf 63// ilogb: returns INT_MAX 64// logb: returns +inf 65// Nan returns FP_LOGBNAN (which is either INT_MAX or INT_MIN) 66// ilogb: returns INT_MAX (7fffffff) 67// logb: returns QNAN (quietized SNAN) 68// 0 returns FP_ILOGB0 (which is either INT_MIN or -INT_MAX) 69// ilogb: returns -INT_MAX (80000001) 70// logb: returns -inf, raises the divide-by-zero exception, 71// and calls libm_error_support to set domain error 72// 73// Registers used 74//============================================================== 75// general registers used: 76// r26 -> r38 77// r35 -> r38 used as parameters to error path 78// 79// predicate registers used: 80// p6, p7, p8 81// floating-point registers used: 82// f9, f10, f11 83// f8, input 84 85rExpBias = r26 86rExpMask = r27 87rSignexp_x = r28 88rExp_x = r29 89rTrueExp_x = r30 90rExp_2to64 = r31 91 92GR_SAVE_PFS = r32 93GR_SAVE_B0 = r33 94GR_SAVE_GP = r34 95 96GR_Parameter_X = r35 97GR_Parameter_Y = r36 98GR_Parameter_RESULT = r37 99GR_Parameter_TAG = r38 100 101fExp_in_signif = f9 102fNorm_x = f10 103fFloat_Exp = f10 104f2to64 = f11 105 106.section .text 107GLOBAL_LIBM_ENTRY(logb) 108 109// X NORMAL 110// TrueExp_x = exp(f8) - 0xffff 111// sig = TrueExp_x 112// f8 = convert_to_fp (sig)) 113{ .mfi 114 getf.exp rSignexp_x = f8 115 fclass.m p8,p0 = f8, 0x0b // Test for x unorm 116 mov rExpBias = 0xffff // Exponent bias 117} 118{ .mfi 119 nop.m 0 120 fnorm.s1 fNorm_x = f8 121 mov rExpMask = 0x1ffff // Exponent mask 122} 123;; 124 125// Form signexp of 2^64 in case need to scale denormal 126{ .mfb 127 mov rExp_2to64 = 0x1003f 128 fclass.m p6,p0 = f8, 0x1e3 // Test x natval, nan, inf 129(p8) br.cond.spnt LOGB_DENORM // Branch if x unorm 130} 131;; 132 133LOGB_COMMON: 134// Return here from LOGB_DENORM 135{ .mfi 136 and rExp_x = rSignexp_x, rExpMask // Get biased exponent 137 fclass.m p7,p0 = f8, 0x07 // Test x zero 138 nop.i 0 139} 140;; 141 142// X NAN or INFINITY, return f8 * f8 143{ .mfb 144 sub rTrueExp_x = rExp_x, rExpBias // Get true exponent 145(p6) fma.d.s0 f8= f8,f8,f0 // Result if x natval, nan, inf 146(p6) br.ret.spnt b0 // Exit if x natval, nan, inf 147} 148;; 149 150{ .mib 151 setf.sig fExp_in_signif = rTrueExp_x // Exponent as integer in fp 152 nop.i 999 153(p7) br.cond.spnt LOGB_ZERO 154} 155;; 156 157// Result can be represented in less than 24 bits, so no precision completer 158// is needed. 159{ .mfb 160 nop.m 0 161 fcvt.xf f8 = fExp_in_signif 162 br.ret.sptk b0 // Exit main path, 0 < |x| < inf 163} 164;; 165 166LOGB_DENORM: 167// Form 2^64 in case need to scale denormal 168// Check to see if double-extended denormal 169{ .mfi 170 setf.exp f2to64 = rExp_2to64 171 fclass.m p8,p0 = fNorm_x, 0x0b 172 nop.i 0 173} 174;; 175 176{ .mfi 177 nop.m 0 178 fcmp.eq.s0 p7,p0 = f8, f0 // Dummy op to set denormal flag 179 nop.i 0 180} 181;; 182 183// If double-extended denormal add 64 to exponent bias for scaling 184// If double-extended denormal form x * 2^64 which is normal 185{ .mfi 186(p8) add rExpBias = 64, rExpBias 187(p8) fmpy.s1 fNorm_x = fNorm_x, f2to64 188 nop.i 0 189} 190;; 191 192// Logic is the same as normal path but use normalized input 193{ .mib 194 getf.exp rSignexp_x = fNorm_x 195 nop.i 0 196 br.cond.sptk LOGB_COMMON // Return to main path 197} 198;; 199 200LOGB_ZERO: 201// Here if x zero 202// f10 = -|f8| 203// f9 = 1.0/f10 = -1.0/|f8| = -inf 204 205{ .mmf 206 alloc r32=ar.pfs,1,2,4,0 207 mov GR_Parameter_TAG = 151 // Error code 208 fmerge.ns f10 = f0,f8 209} 210;; 211 212{ .mfb 213 nop.m 0 214 frcpa.s0 f9,p6 = f1,f10 // Produce -inf, Z flag 215 br.cond.sptk __libm_error_region // Call error support 216} 217;; 218 219GLOBAL_LIBM_END(logb) 220libm_alias_double_other (logb, logb) 221 222 223LOCAL_LIBM_ENTRY(__libm_error_region) 224.prologue 225 226{ .mfi 227 add GR_Parameter_Y=-32,sp // Parameter 2 value 228 nop.f 0 229.save ar.pfs,GR_SAVE_PFS 230 mov GR_SAVE_PFS=ar.pfs // Save ar.pfs 231} 232{ .mfi 233.fframe 64 234 add sp=-64,sp // Create new stack 235 nop.f 0 236 mov GR_SAVE_GP=gp // Save gp 237};; 238 239{ .mmi 240 stfd [GR_Parameter_Y] = f0,16 // STORE Parameter 2 on stack 241 add GR_Parameter_X = 16,sp // Parameter 1 address 242.save b0, GR_SAVE_B0 243 mov GR_SAVE_B0=b0 // Save b0 244};; 245 246.body 247{ .mib 248 stfd [GR_Parameter_X] = f8 // STORE Parameter 1 on stack 249 add GR_Parameter_RESULT = 0,GR_Parameter_Y // Parameter 3 address 250 nop.b 0 251} 252{ .mib 253 stfd [GR_Parameter_Y] = f9 // Store Parameter 3 on stack 254 add GR_Parameter_Y = -16,GR_Parameter_Y 255 br.call.sptk b0=__libm_error_support# // Call error handling function 256};; 257 258{ .mmi 259 add GR_Parameter_RESULT = 48,sp 260 nop.m 0 261 nop.i 0 262};; 263 264{ .mmi 265 ldfd f8 = [GR_Parameter_RESULT] // Get return result off stack 266.restore sp 267 add sp = 64,sp // Restore stack pointer 268 mov b0 = GR_SAVE_B0 // Restore return address 269};; 270 271{ .mib 272 mov gp = GR_SAVE_GP // Restore gp 273 mov ar.pfs = GR_SAVE_PFS // Restore ar.pfs 274 br.ret.sptk b0 275};; 276 277LOCAL_LIBM_END(__libm_error_region) 278 279 280.type __libm_error_support#,@function 281.global __libm_error_support# 282