Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:49

0001 #include "fpsp-namespace.h"
0002 //
0003 //
0004 //  stanh.sa 3.1 12/10/90
0005 //
0006 //  The entry point sTanh computes the hyperbolic tangent of
0007 //  an input argument; sTanhd does the same except for denormalized
0008 //  input.
0009 //
0010 //  Input: Double-extended number X in location pointed to
0011 //      by address register a0.
0012 //
0013 //  Output: The value tanh(X) returned in floating-point register Fp0.
0014 //
0015 //  Accuracy and Monotonicity: The returned result is within 3 ulps in
0016 //      64 significant bit, i.e. within 0.5001 ulp to 53 bits if the
0017 //      result is subsequently rounded to double precision. The
0018 //      result is provably monotonic in double precision.
0019 //
0020 //  Speed: The program stanh takes approximately 270 cycles.
0021 //
0022 //  Algorithm:
0023 //
0024 //  TANH
0025 //  1. If |X| >= (5/2) log2 or |X| <= 2**(-40), go to 3.
0026 //
0027 //  2. (2**(-40) < |X| < (5/2) log2) Calculate tanh(X) by
0028 //      sgn := sign(X), y := 2|X|, z := expm1(Y), and
0029 //      tanh(X) = sgn*( z/(2+z) ).
0030 //      Exit.
0031 //
0032 //  3. (|X| <= 2**(-40) or |X| >= (5/2) log2). If |X| < 1,
0033 //      go to 7.
0034 //
0035 //  4. (|X| >= (5/2) log2) If |X| >= 50 log2, go to 6.
0036 //
0037 //  5. ((5/2) log2 <= |X| < 50 log2) Calculate tanh(X) by
0038 //      sgn := sign(X), y := 2|X|, z := exp(Y),
0039 //      tanh(X) = sgn - [ sgn*2/(1+z) ].
0040 //      Exit.
0041 //
0042 //  6. (|X| >= 50 log2) Tanh(X) = +-1 (round to nearest). Thus, we
0043 //      calculate Tanh(X) by
0044 //      sgn := sign(X), Tiny := 2**(-126),
0045 //      tanh(X) := sgn - sgn*Tiny.
0046 //      Exit.
0047 //
0048 //  7. (|X| < 2**(-40)). Tanh(X) = X.   Exit.
0049 //
0050 
0051 //      Copyright (C) Motorola, Inc. 1990
0052 //          All Rights Reserved
0053 //
0054 //  THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
0055 //  The copyright notice above does not evidence any
0056 //  actual or intended publication of such source code.
0057 
0058 //STANH idnt    2,1 | Motorola 040 Floating Point Software Package
0059 
0060     |section    8
0061 
0062 #include "fpsp.defs"
0063 
0064     .set    X,FP_SCR5
0065     .set    XDCARE,X+2
0066     .set    XFRAC,X+4
0067 
0068     .set    SGN,L_SCR3
0069 
0070     .set    V,FP_SCR6
0071 
0072 BOUNDS1:    .long 0x3FD78000,0x3FFFDDCE // ... 2^(-40), (5/2)LOG2
0073 
0074     |xref   t_frcinx
0075     |xref   t_extdnrm
0076     |xref   setox
0077     |xref   setoxm1
0078 
0079     .global stanhd
0080 stanhd:
0081 //--TANH(X) = X FOR DENORMALIZED X
0082 
0083     bra     t_extdnrm
0084 
0085     .global stanh
0086 stanh:
0087     fmovex      (%a0),%fp0  // ...LOAD INPUT
0088 
0089     fmovex      %fp0,X(%a6)
0090     movel       (%a0),%d0
0091     movew       4(%a0),%d0
0092     movel       %d0,X(%a6)
0093     andl        #0x7FFFFFFF,%d0
0094     cmp2l       BOUNDS1(%pc),%d0    // ...2**(-40) < |X| < (5/2)LOG2 ?
0095     bcss        TANHBORS
0096 
0097 //--THIS IS THE USUAL CASE
0098 //--Y = 2|X|, Z = EXPM1(Y), TANH(X) = SIGN(X) * Z / (Z+2).
0099 
0100     movel       X(%a6),%d0
0101     movel       %d0,SGN(%a6)
0102     andl        #0x7FFF0000,%d0
0103     addl        #0x00010000,%d0 // ...EXPONENT OF 2|X|
0104     movel       %d0,X(%a6)
0105     andl        #0x80000000,SGN(%a6)
0106     fmovex      X(%a6),%fp0     // ...FP0 IS Y = 2|X|
0107 
0108     movel       %d1,-(%a7)
0109     clrl        %d1
0110     fmovemx %fp0-%fp0,(%a0)
0111     bsr     setoxm1     // ...FP0 IS Z = EXPM1(Y)
0112     movel       (%a7)+,%d1
0113 
0114     fmovex      %fp0,%fp1
0115     fadds       #0x40000000,%fp1    // ...Z+2
0116     movel       SGN(%a6),%d0
0117     fmovex      %fp1,V(%a6)
0118     eorl        %d0,V(%a6)
0119 
0120     fmovel      %d1,%FPCR       //restore users exceptions
0121     fdivx       V(%a6),%fp0
0122     bra     t_frcinx
0123 
0124 TANHBORS:
0125     cmpl        #0x3FFF8000,%d0
0126     blt     TANHSM
0127 
0128     cmpl        #0x40048AA1,%d0
0129     bgt     TANHHUGE
0130 
0131 //-- (5/2) LOG2 < |X| < 50 LOG2,
0132 //--TANH(X) = 1 - (2/[EXP(2X)+1]). LET Y = 2|X|, SGN = SIGN(X),
0133 //--TANH(X) = SGN - SGN*2/[EXP(Y)+1].
0134 
0135     movel       X(%a6),%d0
0136     movel       %d0,SGN(%a6)
0137     andl        #0x7FFF0000,%d0
0138     addl        #0x00010000,%d0 // ...EXPO OF 2|X|
0139     movel       %d0,X(%a6)      // ...Y = 2|X|
0140     andl        #0x80000000,SGN(%a6)
0141     movel       SGN(%a6),%d0
0142     fmovex      X(%a6),%fp0     // ...Y = 2|X|
0143 
0144     movel       %d1,-(%a7)
0145     clrl        %d1
0146     fmovemx %fp0-%fp0,(%a0)
0147     bsr     setox       // ...FP0 IS EXP(Y)
0148     movel       (%a7)+,%d1
0149     movel       SGN(%a6),%d0
0150     fadds       #0x3F800000,%fp0    // ...EXP(Y)+1
0151 
0152     eorl        #0xC0000000,%d0 // ...-SIGN(X)*2
0153     fmoves      %d0,%fp1        // ...-SIGN(X)*2 IN SGL FMT
0154     fdivx       %fp0,%fp1       // ...-SIGN(X)2 / [EXP(Y)+1 ]
0155 
0156     movel       SGN(%a6),%d0
0157     orl     #0x3F800000,%d0 // ...SGN
0158     fmoves      %d0,%fp0        // ...SGN IN SGL FMT
0159 
0160     fmovel      %d1,%FPCR       //restore users exceptions
0161     faddx       %fp1,%fp0
0162 
0163     bra     t_frcinx
0164 
0165 TANHSM:
0166     movew       #0x0000,XDCARE(%a6)
0167 
0168     fmovel      %d1,%FPCR       //restore users exceptions
0169     fmovex      X(%a6),%fp0     //last inst - possible exception set
0170 
0171     bra     t_frcinx
0172 
0173 TANHHUGE:
0174 //---RETURN SGN(X) - SGN(X)EPS
0175     movel       X(%a6),%d0
0176     andl        #0x80000000,%d0
0177     orl     #0x3F800000,%d0
0178     fmoves      %d0,%fp0
0179     andl        #0x80000000,%d0
0180     eorl        #0x80800000,%d0 // ...-SIGN(X)*EPS
0181 
0182     fmovel      %d1,%FPCR       //restore users exceptions
0183     fadds       %d0,%fp0
0184 
0185     bra     t_frcinx
0186 
0187     |end