📄 e_exp.s
字号:
.file "exp.s"// Copyright (C) 2000, 2001, 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.//// Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions are// met://// * Redistributions of source code must retain the above copyright// notice, this list of conditions and the following disclaimer.//// * Redistributions in binary form must reproduce the above copyright// notice, this list of conditions and the following disclaimer in the// documentation and/or other materials provided with the distribution.//// * 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 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR// 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 // 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. // // 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.//// History//==============================================================// 2/02/00 Initial version // 3/07/00 exp(inf) = inf but now does NOT call error support// exp(-inf) = 0 but now does NOT call error support// 4/04/00 Unwind support added// 8/15/00 Bundle added after call to __libm_error_support to properly// set [the previously overwritten] GR_Parameter_RESULT.// 11/30/00 Reworked to shorten main path, widen main path to include all// args in normal range, and add quick exit for 0, nan, inf.// 12/05/00 Loaded constants earlier with setf to save 2 cycles.// API//==============================================================// double exp(double)// Overview of operation//==============================================================// Take the input x. w is "how many log2/128 in x?"// w = x * 128/log2// n = int(w)// x = n log2/128 + r + delta// n = 128M + index_1 + 2^4 index_2// x = M log2 + (log2/128) index_1 + (log2/8) index_2 + r + delta// exp(x) = 2^M 2^(index_1/128) 2^(index_2/8) exp(r) exp(delta)// Construct 2^M// Get 2^(index_1/128) from table_1;// Get 2^(index_2/8) from table_2;// Calculate exp(r) by series// r = x - n (log2/128)_high// delta = - n (log2/128)_low// Calculate exp(delta) as 1 + delta// Special values //==============================================================// exp(+0) = 1.0// exp(-0) = 1.0// exp(+qnan) = +qnan // exp(-qnan) = -qnan // exp(+snan) = +qnan // exp(-snan) = -qnan // exp(-inf) = +0 // exp(+inf) = +inf// Overfow and Underfow//=======================// exp(-x) = smallest double normal when// x = -708.396 = c086232bdd7abcd2// exp(x) = largest double normal when// x = 709.7827 = 40862e42fefa39ef// Registers used//==============================================================// Floating Point registers used: // f8, input// f9 -> f15, f32 -> f60// General registers used: // r32 -> r60 // Predicate registers used:// p6 -> p15#include "libm_support.h"// Assembly macros//==============================================================exp_GR_rshf = r33EXP_AD_TB1 = r34EXP_AD_TB2 = r35EXP_AD_P = r36exp_GR_N = r37exp_GR_index_1 = r38exp_GR_index_2_16 = r39exp_GR_biased_M = r40exp_GR_index_1_16 = r41EXP_AD_T1 = r42EXP_AD_T2 = r43exp_GR_sig_inv_ln2 = r44exp_GR_17ones = r45exp_GR_one = r46exp_TB1_size = r47exp_TB2_size = r48exp_GR_rshf_2to56 = r49exp_GR_gt_ln = r50exp_GR_exp_2tom56 = r51exp_GR_17ones_m1 = r52GR_SAVE_B0 = r53GR_SAVE_PFS = r54GR_SAVE_GP = r55GR_SAVE_SP = r56GR_Parameter_X = r57GR_Parameter_Y = r58GR_Parameter_RESULT = r59GR_Parameter_TAG = r60FR_X = f10FR_Y = f1FR_RESULT = f8EXP_RSHF_2TO56 = f6EXP_INV_LN2_2TO63 = f7EXP_W_2TO56_RSH = f9EXP_2TOM56 = f11exp_P4 = f12 exp_P3 = f13 exp_P2 = f14 exp_P1 = f15 exp_ln2_by_128_hi = f33 exp_ln2_by_128_lo = f34 EXP_RSHF = f35EXP_Nfloat = f36 exp_W = f37exp_r = f38exp_f = f39exp_rsq = f40exp_rcube = f41EXP_2M = f42exp_S1 = f43exp_T1 = f44EXP_MIN_DBL_OFLOW_ARG = f45EXP_MAX_DBL_ZERO_ARG = f46EXP_MAX_DBL_NORM_ARG = f47EXP_MAX_DBL_UFLOW_ARG = f48EXP_MIN_DBL_NORM_ARG = f49exp_rP4pP3 = f50exp_P_lo = f51exp_P_hi = f52exp_P = f53exp_S = f54EXP_NORM_f8 = f56 exp_wre_urm_f8 = f57exp_ftz_urm_f8 = f57exp_gt_pln = f58exp_S2 = f59exp_T2 = f60// Data tables//==============================================================#ifdef _LIBC.rodata#else.data#endif.align 16// ************* DO NOT CHANGE ORDER OF THESE TABLES ********************// double-extended 1/ln(2)// 3fff b8aa 3b29 5c17 f0bb be87fed0691d3e88// 3fff b8aa 3b29 5c17 f0bc // For speed the significand will be loaded directly with a movl and setf.sig// and the exponent will be bias+63 instead of bias+0. Thus subsequent// computations need to scale appropriately.// The constant 128/ln(2) is needed for the computation of w. This is also // obtained by scaling the computations.//// Two shifting constants are loaded directly with movl and setf.d. // 1. EXP_RSHF_2TO56 = 1.1000..00 * 2^(63-7) // This constant is added to x*1/ln2 to shift the integer part of// x*128/ln2 into the rightmost bits of the significand.// The result of this fma is EXP_W_2TO56_RSH.// 2. EXP_RSHF = 1.1000..00 * 2^(63) // This constant is subtracted from EXP_W_2TO56_RSH * 2^(-56) to give// the integer part of w, n, as a floating-point number.// The result of this fms is EXP_Nfloat.exp_table_1:ASM_TYPE_DIRECTIVE(exp_table_1,@object)data8 0x40862e42fefa39f0 // smallest dbl overflow argdata8 0xc0874c0000000000 // approx largest arg for zero resultdata8 0x40862e42fefa39ef // largest dbl arg to give normal dbl resultdata8 0xc086232bdd7abcd3 // largest dbl underflow argdata8 0xc086232bdd7abcd2 // smallest dbl arg to give normal dbl resultdata8 0x0 // paddata8 0xb17217f7d1cf79ab , 0x00003ff7 // ln2/128 hidata8 0xc9e3b39803f2f6af , 0x00003fb7 // ln2/128 lo// Table 1 is 2^(index_1/128) where// index_1 goes from 0 to 15data8 0x8000000000000000 , 0x00003FFFdata8 0x80B1ED4FD999AB6C , 0x00003FFFdata8 0x8164D1F3BC030773 , 0x00003FFFdata8 0x8218AF4373FC25EC , 0x00003FFFdata8 0x82CD8698AC2BA1D7 , 0x00003FFFdata8 0x8383594EEFB6EE37 , 0x00003FFFdata8 0x843A28C3ACDE4046 , 0x00003FFFdata8 0x84F1F656379C1A29 , 0x00003FFFdata8 0x85AAC367CC487B15 , 0x00003FFFdata8 0x8664915B923FBA04 , 0x00003FFFdata8 0x871F61969E8D1010 , 0x00003FFFdata8 0x87DB357FF698D792 , 0x00003FFFdata8 0x88980E8092DA8527 , 0x00003FFFdata8 0x8955EE03618E5FDD , 0x00003FFFdata8 0x8A14D575496EFD9A , 0x00003FFFdata8 0x8AD4C6452C728924 , 0x00003FFFASM_SIZE_DIRECTIVE(exp_table_1)// Table 2 is 2^(index_1/8) where// index_2 goes from 0 to 7exp_table_2:ASM_TYPE_DIRECTIVE(exp_table_2,@object)data8 0x8000000000000000 , 0x00003FFFdata8 0x8B95C1E3EA8BD6E7 , 0x00003FFFdata8 0x9837F0518DB8A96F , 0x00003FFFdata8 0xA5FED6A9B15138EA , 0x00003FFFdata8 0xB504F333F9DE6484 , 0x00003FFFdata8 0xC5672A115506DADD , 0x00003FFFdata8 0xD744FCCAD69D6AF4 , 0x00003FFFdata8 0xEAC0C6E7DD24392F , 0x00003FFFASM_SIZE_DIRECTIVE (exp_table_2)exp_p_table:ASM_TYPE_DIRECTIVE(exp_p_table,@object)data8 0x3f8111116da21757 //P_4data8 0x3fa55555d787761c //P_3data8 0x3fc5555555555414 //P_2data8 0x3fdffffffffffd6a //P_1ASM_SIZE_DIRECTIVE(exp_p_table).align 32.global exp#.section .text.proc exp#.align 32exp: #ifdef _LIBC.global __ieee754_exp#__ieee754_exp:#endif{ .mlx alloc r32=ar.pfs,1,24,4,0 movl exp_GR_sig_inv_ln2 = 0xb8aa3b295c17f0bc // significand of 1/ln2}{ .mlx addl EXP_AD_TB1 = @ltoff(exp_table_1), gp movl exp_GR_rshf_2to56 = 0x4768000000000000 ;; // 1.10000 2^(63+56)};;// We do this fnorm right at the beginning to take any enabled// faults and to normalize any input unnormals so that SWA is not taken.{ .mfi ld8 EXP_AD_TB1 = [EXP_AD_TB1] fclass.m p8,p0 = f8,0x07 // Test for x=0 mov exp_GR_17ones = 0x1FFFF }{ .mfi mov exp_TB1_size = 0x100 fnorm EXP_NORM_f8 = f8 mov exp_GR_exp_2tom56 = 0xffff-56};;// Form two constants we need// 1/ln2 * 2^63 to compute w = x * 1/ln2 * 128 // 1.1000..000 * 2^(63+63-7) to right shift int(w) into the significand{ .mmf setf.sig EXP_INV_LN2_2TO63 = exp_GR_sig_inv_ln2 // form 1/ln2 * 2^63 setf.d EXP_RSHF_2TO56 = exp_GR_rshf_2to56 // Form const 1.100 * 2^(63+56) fclass.m p9,p0 = f8,0x22 // Test for x=-inf};;{ .mlx setf.exp EXP_2TOM56 = exp_GR_exp_2tom56 // form 2^-56 for scaling Nfloat movl exp_GR_rshf = 0x43e8000000000000 // 1.10000 2^63 for right shift}{ .mfb mov exp_TB2_size = 0x80(p8) fma.d f8 = f1,f1,f0 // quick exit for x=0(p8) br.ret.spnt b0;;}{ .mfi ldfpd EXP_MIN_DBL_OFLOW_ARG, EXP_MAX_DBL_ZERO_ARG = [EXP_AD_TB1],16 fclass.m p10,p0 = f8,0x21 // Test for x=+inf nop.i 999}{ .mfb nop.m 999(p9) fma.d f8 = f0,f0,f0 // quick exit for x=-inf(p9) br.ret.spnt b0;; }{ .mmf ldfpd EXP_MAX_DBL_NORM_ARG, EXP_MAX_DBL_UFLOW_ARG = [EXP_AD_TB1],16 setf.d EXP_RSHF = exp_GR_rshf // Form right shift const 1.100 * 2^63 fclass.m p11,p0 = f8,0xc3 // Test for x=nan;;}{ .mfb ldfd EXP_MIN_DBL_NORM_ARG = [EXP_AD_TB1],16 nop.f 999(p10) br.ret.spnt b0 // quick exit for x=+inf;;}{ .mfi ldfe exp_ln2_by_128_hi = [EXP_AD_TB1],16 nop.f 999 nop.i 999;;}{ .mfb ldfe exp_ln2_by_128_lo = [EXP_AD_TB1],16(p11) fmerge.s f8 = EXP_NORM_f8, EXP_NORM_f8(p11) br.ret.spnt b0 // quick exit for x=nan;;}// After that last load, EXP_AD_TB1 points to the beginning of table 1// W = X * Inv_log2_by_128// By adding 1.10...0*2^63 we shift and get round_int(W) in significand.// We actually add 1.10...0*2^56 to X * Inv_log2 to do the same thing.{ .mfi nop.m 999 fma.s1 EXP_W_2TO56_RSH = EXP_NORM_f8, EXP_INV_LN2_2TO63, EXP_RSHF_2TO56 nop.i 999;;}// Divide arguments into the following categories:// Certain Underflow/zero p11 - -inf < x <= MAX_DBL_ZERO_ARG // Certain Underflow p12 - MAX_DBL_ZERO_ARG < x <= MAX_DBL_UFLOW_ARG // Possible Underflow p13 - MAX_DBL_UFLOW_ARG < x < MIN_DBL_NORM_ARG// Certain Safe - MIN_DBL_NORM_ARG <= x <= MAX_DBL_NORM_ARG// Possible Overflow p14 - MAX_DBL_NORM_ARG < x < MIN_DBL_OFLOW_ARG// Certain Overflow p15 - MIN_DBL_OFLOW_ARG <= x < +inf//// If the input is really a double arg, then there will never be "Possible// Underflow" or "Possible Overflow" arguments.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -