3 // Copyright (c) 2000, 2001, Intel Corporation
4 // All rights reserved.
6 // Contributed 2/2/2000 by John Harrison, Ted Kubaska, Bob Norin, Shane Story,
7 // and Ping Tak Peter Tang of the Computational Software Lab, Intel Corporation.
11 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
12 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
13 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
14 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS
15 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
16 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
17 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
18 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
19 // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING
20 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 // Intel Corporation is the author of this code, and requests that all
24 // problem reports or change requests be submitted to it directly at
25 // http://developer.intel.com/opensource.
28 //==============================================================
29 // 2/02/00 Initial version
30 // 1/26/01 Scalb completely reworked and now standalone version
33 //==============================================================
34 // double = scalb (double x, double n)
35 // input floating point f8 and floating point f9
36 // output floating point f8
38 // Returns x* 2**n using an fma and detects overflow
43 #include "libm_support.h"
71 GR_Parameter_RESULT = r37
83 .global __ieee754_scalb
84 .type __ieee754_scalb,@function
89 // Is x NAN, INF, ZERO, +-?
92 alloc r32=ar.pfs,0,3,4,0
93 fclass.m.unc p7,p0 = FR_Floating_X, 0xe7 //@snan | @qnan | @inf | @zero
94 addl GR_Scratch = 0x019C3F,r0
97 // Is y a NAN, INF, ZERO, +-?
101 fclass.m.unc p6,p0 = FR_Floating_N, 0xe7 //@snan | @qnan | @inf | @zero
102 addl GR_Scratch1 = 0x063BF,r0
107 // Convert N to a fp integer
112 fnorm.s1 FR_Norm_N = FR_Floating_N
117 fnorm.s1 FR_Norm_X = FR_Floating_X
125 // Branch on special values.
128 setf.exp FR_Big = GR_Scratch
130 (p6) br.cond.spnt L(SCALB_NAN_INF_ZERO)
133 setf.exp FR_NBig = GR_Scratch1
135 (p7) br.cond.spnt L(SCALB_NAN_INF_ZERO)
139 // Convert N to a fp integer
143 addl GR_Scratch = 1,r0
144 fcvt.fx.trunc.s1 FR_N_float_int = FR_Norm_N
145 addl GR_NBig = -35000,r0
150 // Put N if a GP register
151 // Convert N_float_int to floating point value
153 // Build the exponent Bias
156 getf.sig GR_N_as_int = FR_N_float_int
157 shl GR_Scratch = GR_Scratch,63
158 addl GR_Big = 35000,r0
161 addl GR_Bias = 0x0FFFF,r0
162 fcvt.xf FR_N_float_int = FR_N_float_int
167 // Catch those fp values that are beyond 2**64-1
172 cmp.ne.unc p9,p10 = GR_N_as_int,GR_Scratch
177 cmp.ge.unc p6, p0 = GR_N_as_int, GR_Big
178 cmp.le.unc p8, p0 = GR_N_as_int, GR_NBig
183 // Is N really an int, only for those non-int indefinites?
187 add GR_N_Biased = GR_Bias,GR_N_as_int
188 (p9) fcmp.neq.unc.s1 p7,p0 = FR_Norm_N, FR_N_float_int
193 // Branch and return if N is not an int.
194 // Main path, create 2**N
197 setf.exp FR_Two_N = GR_N_Biased
202 (p7) frcpa f8,p11 = f0,f0
207 // Set denormal on denormal input x and denormal input N
211 (p10)fcmp.ge.s1 p6,p8 = FR_Norm_N,f0
216 fcmp.ge.s0 p0,p11 = FR_Floating_X,f0
221 fcmp.ge.s0 p12,p13 = FR_Floating_N,f0
226 // Adjust 2**N if N was very small or very large
231 (p6) fma.s1 FR_Two_N = FR_Big,f1,f0
236 (p0) movl GR_Scratch = 0x00000000000303FF
240 (p8) fma.s1 FR_Two_N = FR_NBig,f1,f0
245 (p0) movl GR_Scratch1= 0x00000000000103FF
248 // Set up necessary status fields
250 // S0 user supplied status
251 // S2 user supplied status + WRE + TD (Overflows)
252 // S3 user supplied status + FZ + TD (Underflows)
256 (p0) fsetc.s3 0x7F,0x41
261 (p0) fsetc.s2 0x7F,0x42
266 // Do final operation
269 setf.exp FR_NBig = GR_Scratch
270 fma.d.s0 FR_Result = FR_Two_N,FR_Norm_X,f0
275 fma.d.s3 FR_Result3 = FR_Two_N,FR_Norm_X,f0
279 setf.exp FR_Big = GR_Scratch1
280 fma.d.s2 FR_Result2 = FR_Two_N,FR_Norm_X,f0
284 // Check for overflow or underflow.
286 // S0 user supplied status
287 // S2 user supplied status + WRE + TD (Overflow)
288 // S3 user supplied status + FZ + TD (Underflow)
306 // Is the result zero?
310 fclass.m.unc p6, p0 = FR_Result3, 0x007
315 fcmp.ge.unc.s1 p7, p8 = FR_Result2 , FR_Big
320 // Detect masked underflow - Tiny + Inexact Only
324 (p6) fcmp.neq.unc.s1 p6, p0 = FR_Result , FR_Result2
329 // Is result bigger the allowed range?
330 // Branch out for underflow
333 (p6) addl GR_Tag = 54, r0
334 (p8) fcmp.le.unc.s1 p9, p10 = FR_Result2 , FR_NBig
335 (p6) br.cond.spnt L(SCALB_UNDERFLOW)
339 // Branch out for overflow
343 (p7) br.cond.spnt L(SCALB_OVERFLOW)
344 (p9) br.cond.spnt L(SCALB_OVERFLOW)
348 // Return from main path.
356 L(SCALB_NAN_INF_ZERO):
359 // Convert N to a fp integer
362 addl GR_Scratch = 1,r0
363 fcvt.fx.trunc.s1 FR_N_float_int = FR_Norm_N
368 fclass.m.unc p6,p0 = FR_Floating_N, 0xc3 //@snan | @qnan
373 fclass.m.unc p7,p0 = FR_Floating_X, 0xc3 //@snan | @qnan
374 shl GR_Scratch = GR_Scratch,63
378 fclass.m.unc p8,p0 = FR_Floating_N, 0x21 // @inf
383 fclass.m.unc p9,p0 = FR_Floating_N, 0x22 // @-inf
388 // Either X or N is a Nan, return result and possible raise invalid.
392 (p6) fma.d.s0 FR_Result = FR_Floating_N,FR_Floating_X,f0
396 getf.sig GR_N_as_int = FR_N_float_int
397 (p7) fma.d.s0 FR_Result = FR_Floating_N,FR_Floating_X,f0
402 // If N + Inf do something special
403 // For N = -Inf, create Int
407 (p8) fma.d.s0 FR_Result = FR_Floating_X, FR_Floating_N,f0
412 (p9) fnma.d.s0 FR_Floating_N = FR_Floating_N, f1, f0
417 // If N==-Inf,return x/(-N)
421 (p9) frcpa.s0 FR_Result,p6 = FR_Floating_X,FR_Floating_N
426 // Convert N_float_int to floating point value
429 cmp.ne.unc p9,p0 = GR_N_as_int,GR_Scratch
430 fcvt.xf FR_N_float_int = FR_N_float_int
439 (p9) fcmp.neq.unc.s1 p7,p0 = FR_Norm_N, FR_N_float_int
444 // If N not an int, return NaN and raise invalid.
448 (p7) frcpa.s0 FR_Result,p6 = f0,f0
453 // Always return x in other path.
457 fma.d.s0 FR_Result = FR_Floating_X,f1,f0
462 ASM_SIZE_DIRECTIVE(scalb)
464 ASM_SIZE_DIRECTIVE(__ieee754_scalb)
466 .proc __libm_error_region
473 // Get stack address of N
477 add GR_Parameter_Y=-32,sp
479 .save ar.pfs,GR_SAVE_PFS
480 mov GR_SAVE_PFS=ar.pfs
493 // Store N on stack in correct position
494 // Locate the address of x on stack
497 stfd [GR_Parameter_Y] = FR_Norm_N,16
498 add GR_Parameter_X = 16,sp
504 // Store x on the stack.
505 // Get address for result on stack.
509 stfd [GR_Parameter_X] = FR_Norm_X
510 add GR_Parameter_RESULT = 0,GR_Parameter_Y
514 stfd [GR_Parameter_Y] = FR_Result
515 add GR_Parameter_Y = -16,GR_Parameter_Y
516 br.call.sptk b0=__libm_error_support#
520 // Get location of result on stack
525 add GR_Parameter_RESULT = 48,sp
529 // Get the new result
532 ldfd FR_Result = [GR_Parameter_RESULT]
539 // Restore gp, ar.pfs and return
543 mov ar.pfs = GR_SAVE_PFS
547 .endp __libm_error_region
548 ASM_SIZE_DIRECTIVE(__libm_error_region)
550 .type __libm_error_support#,@function
551 .global __libm_error_support#