Remove support in configure for unsupported architectures
[glibc.git] / sysdeps / ia64 / fpu / libm_tan.S
blob179ea9c323242988e2ad7ba01719a89f227f7be6
1 .file "libm_tan.s"
3 // Copyright (C) 2000, 2001, Intel Corporation
4 // All rights reserved.
5 // 
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.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are
11 // met:
13 // * Redistributions of source code must retain the above copyright
14 // notice, this list of conditions and the following disclaimer.
16 // * Redistributions in binary form must reproduce the above copyright
17 // notice, this list of conditions and the following disclaimer in the
18 // documentation and/or other materials provided with the distribution.
20 // * The name of Intel Corporation may not be used to endorse or promote
21 // products derived from this software without specific prior written
22 // permission.
24 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
25 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
26 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS 
28 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
30 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
31 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
32 // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING
33 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
34 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
35 // 
36 // Intel Corporation is the author of this code, and requests that all
37 // problem reports or change requests be submitted to it directly at 
38 // http://developer.intel.com/opensource.
40 // *********************************************************************
42 // History:  
43 // 02/02/00 Initial Version 
44 // 4/04/00  Unwind support added
45 // 12/28/00 Fixed false invalid flags
47 // *********************************************************************
49 // Function:   tan(x) = tangent(x), for double precision x values
51 // *********************************************************************
53 // Accuracy:       Very accurate for double-precision values  
55 // *********************************************************************
57 // Resources Used:
59 //    Floating-Point Registers: f8 (Input and Return Value)
60 //                              f9-f15
61 //                              f32-f112
63 //    General Purpose Registers:
64 //      r32-r48
65 //      r49-r50 (Used to pass arguments to pi_by_2 reduce routine)
67 //    Predicate Registers:      p6-p15
69 // *********************************************************************
71 // IEEE Special Conditions:
73 //    Denormal  fault raised on denormal inputs
74 //    Overflow exceptions do not occur
75 //    Underflow exceptions raised when appropriate for tan 
76 //    (No specialized error handling for this routine)
77 //    Inexact raised when appropriate by algorithm
79 //    tan(SNaN) = QNaN
80 //    tan(QNaN) = QNaN
81 //    tan(inf) = QNaN
82 //    tan(+/-0) = +/-0
84 // *********************************************************************
86 // Mathematical Description
88 // We consider the computation of FPTAN of Arg. Now, given
90 //      Arg = N pi/2  + alpha,          |alpha| <= pi/4,
92 // basic mathematical relationship shows that
94 //      tan( Arg ) =  tan( alpha )     if N is even;
95 //                 = -cot( alpha )      otherwise.
97 // The value of alpha is obtained by argument reduction and
98 // represented by two working precision numbers r and c where
100 //      alpha =  r  +  c     accurately.
102 // The reduction method is described in a previous write up.
103 // The argument reduction scheme identifies 4 cases. For Cases 2
104 // and 4, because |alpha| is small, tan(r+c) and -cot(r+c) can be
105 // computed very easily by 2 or 3 terms of the Taylor series
106 // expansion as follows:
108 // Case 2:
109 // -------
111 //      tan(r + c) = r + c + r^3/3          ...accurately
112 //        -cot(r + c) = -1/(r+c) + r/3          ...accurately
114 // Case 4:
115 // -------
117 //      tan(r + c) = r + c + r^3/3 + 2r^5/15     ...accurately
118 //        -cot(r + c) = -1/(r+c) + r/3 + r^3/45     ...accurately
121 // The only cases left are Cases 1 and 3 of the argument reduction
122 // procedure. These two cases will be merged since after the
123 // argument is reduced in either cases, we have the reduced argument
124 // represented as r + c and that the magnitude |r + c| is not small
125 // enough to allow the usage of a very short approximation.
127 // The greatest challenge of this task is that the second terms of
128 // the Taylor series for tan(r) and -cot(r)
130 //      r + r^3/3 + 2 r^5/15 + ...
132 // and
134 //      -1/r + r/3 + r^3/45 + ...
136 // are not very small when |r| is close to pi/4 and the rounding
137 // errors will be a concern if simple polynomial accumulation is
138 // used. When |r| < 2^(-2), however, the second terms will be small
139 // enough (5 bits or so of right shift) that a normal Horner
140 // recurrence suffices. Hence there are two cases that we consider
141 // in the accurate computation of tan(r) and cot(r), |r| <= pi/4.
143 // Case small_r: |r| < 2^(-2)
144 // --------------------------
146 // Since Arg = N pi/4 + r + c accurately, we have
148 //      tan(Arg) =  tan(r+c)            for N even,
149 //            = -cot(r+c)          otherwise.
151 // Here for this case, both tan(r) and -cot(r) can be approximated
152 // by simple polynomials:
154 //      tan(r) =    r + P1_1 r^3 + P1_2 r^5 + ... + P1_9 r^19
155 //        -cot(r) = -1/r + Q1_1 r   + Q1_2 r^3 + ... + Q1_7 r^13
157 // accurately. Since |r| is relatively small, tan(r+c) and
158 // -cot(r+c) can be accurately approximated by replacing r with
159 // r+c only in the first two terms of the corresponding polynomials.
161 // Note that P1_1 (and Q1_1 for that matter) approximates 1/3 to
162 // almost 64 sig. bits, thus
164 //      P1_1 (r+c)^3 =  P1_1 r^3 + c * r^2     accurately.
166 // Hence,
168 //      tan(r+c) =    r + P1_1 r^3 + P1_2 r^5 + ... + P1_9 r^19
169 //                     + c*(1 + r^2)
171 //        -cot(r+c) = -1/(r+c) + Q1_1 r   + Q1_2 r^3 + ... + Q1_7 r^13
172 //               + Q1_1*c
175 // Case normal_r: 2^(-2) <= |r| <= pi/4
176 // ------------------------------------
178 // This case is more likely than the previous one if one considers
179 // r to be uniformly distributed in [-pi/4 pi/4].
181 // The required calculation is either
183 //      tan(r + c)  =  tan(r)  +  correction,  or
184 //        -cot(r + c)  = -cot(r)  +  correction.
186 // Specifically,
188 //      tan(r + c) =  tan(r) + c tan'(r)  + O(c^2)
189 //              =  tan(r) + c sec^2(r) + O(c^2)
190 //              =  tan(r) + c SEC_sq     ...accurately
191 //                as long as SEC_sq approximates sec^2(r)
192 //                to, say, 5 bits or so.
194 // Similarly,
196 //        -cot(r + c) = -cot(r) - c cot'(r)  + O(c^2)
197 //              = -cot(r) + c csc^2(r) + O(c^2)
198 //              = -cot(r) + c CSC_sq     ...accurately
199 //                as long as CSC_sq approximates csc^2(r)
200 //                to, say, 5 bits or so.
202 // We therefore concentrate on accurately calculating tan(r) and
203 // cot(r) for a working-precision number r, |r| <= pi/4 to within
204 // 0.1% or so.
206 // We will employ a table-driven approach. Let
208 //      r = sgn_r * 2^k * 1.b_1 b_2 ... b_5 ... b_63
209 //        = sgn_r * ( B + x )
211 // where
213 //      B = 2^k * 1.b_1 b_2 ... b_5 1
214 //         x = |r| - B
216 // Now,
217 //                   tan(B)  +   tan(x)
218 //      tan( B + x ) =  ------------------------
219 //                   1 -  tan(B)*tan(x)
221 //               /                         \ 
222 //               |   tan(B)  +   tan(x)          |
224 //      = tan(B) +  | ------------------------ - tan(B) |
225 //               |     1 -  tan(B)*tan(x)          |
226 //               \                         /
228 //                 sec^2(B) * tan(x)
229 //      = tan(B) + ------------------------
230 //                 1 -  tan(B)*tan(x)
232 //                (1/[sin(B)*cos(B)]) * tan(x)
233 //      = tan(B) + --------------------------------
234 //                      cot(B)  -  tan(x)
237 // Clearly, the values of tan(B), cot(B) and 1/(sin(B)*cos(B)) are
238 // calculated beforehand and stored in a table. Since
240 //      |x| <= 2^k * 2^(-6)  <= 2^(-7)  (because k = -1, -2)
242 // a very short polynomial will be sufficient to approximate tan(x)
243 // accurately. The details involved in computing the last expression
244 // will be given in the next section on algorithm description.
247 // Now, we turn to the case where cot( B + x ) is needed.
250 //                   1 - tan(B)*tan(x)
251 //      cot( B + x ) =  ------------------------
252 //                   tan(B)  +  tan(x)
254 //               /                           \ 
255 //               |   1 - tan(B)*tan(x)              |
257 //      = cot(B) +  | ----------------------- - cot(B) |
258 //               |     tan(B)  +  tan(x)            |
259 //               \                           /
261 //               [tan(B) + cot(B)] * tan(x)
262 //      = cot(B) - ----------------------------
263 //                   tan(B)  +  tan(x)
265 //                (1/[sin(B)*cos(B)]) * tan(x)
266 //      = cot(B) - --------------------------------
267 //                      tan(B)  +  tan(x)
270 // Note that the values of tan(B), cot(B) and 1/(sin(B)*cos(B)) that
271 // are needed are the same set of values needed in the previous
272 // case.
274 // Finally, we can put all the ingredients together as follows:
276 //      Arg = N * pi/2 +  r + c          ...accurately
278 //      tan(Arg) =  tan(r) + correction    if N is even;
279 //            = -cot(r) + correction    otherwise.
281 // For Cases 2 and 4,
283 //     Case 2:
284 //     tan(Arg) =  tan(r + c) = r + c + r^3/3           N even
285 //              = -cot(r + c) = -1/(r+c) + r/3           N odd
286 //     Case 4:
287 //     tan(Arg) =  tan(r + c) = r + c + r^3/3 + 2r^5/15  N even
288 //              = -cot(r + c) = -1/(r+c) + r/3 + r^3/45  N odd
291 // For Cases 1 and 3,
293 //     Case small_r: |r| < 2^(-2)
295 //      tan(Arg) =  r + P1_1 r^3 + P1_2 r^5 + ... + P1_9 r^19
296 //                     + c*(1 + r^2)               N even
298 //                  = -1/(r+c) + Q1_1 r   + Q1_2 r^3 + ... + Q1_7 r^13
299 //               + Q1_1*c                    N odd
301 //     Case normal_r: 2^(-2) <= |r| <= pi/4
303 //      tan(Arg) =  tan(r) + c * sec^2(r)     N even
304 //               = -cot(r) + c * csc^2(r)     otherwise
306 //     For N even,
308 //      tan(Arg) = tan(r) + c*sec^2(r)
309 //               = tan( sgn_r * (B+x) ) + c * sec^2(|r|)
310 //                  = sgn_r * ( tan(B+x)  + sgn_r*c*sec^2(|r|) )
311 //                  = sgn_r * ( tan(B+x)  + sgn_r*c*sec^2(B) )
313 // since B approximates |r| to 2^(-6) in relative accuracy.
315 //                 /            (1/[sin(B)*cos(B)]) * tan(x)
316 //    tan(Arg) = sgn_r * | tan(B) + --------------------------------
317 //                 \                     cot(B)  -  tan(x)
318 //                                        \ 
319 //                       + CORR  |
321 //                                     /
322 // where
324 //    CORR = sgn_r*c*tan(B)*SC_inv(B);  SC_inv(B) = 1/(sin(B)*cos(B)).
326 // For N odd,
328 //      tan(Arg) = -cot(r) + c*csc^2(r)
329 //               = -cot( sgn_r * (B+x) ) + c * csc^2(|r|)
330 //                  = sgn_r * ( -cot(B+x)  + sgn_r*c*csc^2(|r|) )
331 //                  = sgn_r * ( -cot(B+x)  + sgn_r*c*csc^2(B) )
333 // since B approximates |r| to 2^(-6) in relative accuracy.
335 //                 /            (1/[sin(B)*cos(B)]) * tan(x)
336 //    tan(Arg) = sgn_r * | -cot(B) + --------------------------------
337 //                 \                     tan(B)  +  tan(x)
338 //                                        \ 
339 //                       + CORR  |
341 //                                     /
342 // where
344 //    CORR = sgn_r*c*cot(B)*SC_inv(B);  SC_inv(B) = 1/(sin(B)*cos(B)).
347 // The actual algorithm prescribes how all the mathematical formulas
348 // are calculated.
351 // 2. Algorithmic Description
352 // ==========================
354 // 2.1 Computation for Cases 2 and 4.
355 // ----------------------------------
357 // For Case 2, we use two-term polynomials.
359 //    For N even,
361 //    rsq := r * r
362 //    Result := c + r * rsq * P1_1
363 //    Result := r + Result          ...in user-defined rounding
365 //    For N odd,
366 //    S_hi  := -frcpa(r)               ...8 bits
367 //    S_hi  := S_hi + S_hi*(1 + S_hi*r)     ...16 bits
368 //    S_hi  := S_hi + S_hi*(1 + S_hi*r)     ...32 bits
369 //    S_hi  := S_hi + S_hi*(1 + S_hi*r)     ...64 bits
370 //    S_lo  := S_hi*( (1 + S_hi*r) + S_hi*c )
371 //    ...S_hi + S_lo is -1/(r+c) to extra precision
372 //    S_lo  := S_lo + Q1_1*r
374 //    Result := S_hi + S_lo     ...in user-defined rounding
376 // For Case 4, we use three-term polynomials
378 //    For N even,
380 //    rsq := r * r
381 //    Result := c + r * rsq * (P1_1 + rsq * P1_2)
382 //    Result := r + Result          ...in user-defined rounding
384 //    For N odd,
385 //    S_hi  := -frcpa(r)               ...8 bits
386 //    S_hi  := S_hi + S_hi*(1 + S_hi*r)     ...16 bits
387 //    S_hi  := S_hi + S_hi*(1 + S_hi*r)     ...32 bits
388 //    S_hi  := S_hi + S_hi*(1 + S_hi*r)     ...64 bits
389 //    S_lo  := S_hi*( (1 + S_hi*r) + S_hi*c )
390 //    ...S_hi + S_lo is -1/(r+c) to extra precision
391 //    rsq   := r * r
392 //    P      := Q1_1 + rsq*Q1_2
393 //    S_lo  := S_lo + r*P
395 //    Result := S_hi + S_lo     ...in user-defined rounding
398 // Note that the coefficients P1_1, P1_2, Q1_1, and Q1_2 are
399 // the same as those used in the small_r case of Cases 1 and 3
400 // below.
403 // 2.2 Computation for Cases 1 and 3.
404 // ----------------------------------
405 // This is further divided into the case of small_r,
406 // where |r| < 2^(-2), and the case of normal_r, where |r| lies between
407 // 2^(-2) and pi/4.
409 // Algorithm for the case of small_r
410 // ---------------------------------
412 // For N even,
413 //      rsq   := r * r
414 //      Poly1 := rsq*(P1_1 + rsq*(P1_2 + rsq*P1_3))
415 //      r_to_the_8    := rsq * rsq
416 //      r_to_the_8    := r_to_the_8 * r_to_the_8
417 //      Poly2 := P1_4 + rsq*(P1_5 + rsq*(P1_6 + ... rsq*P1_9))
418 //      CORR  := c * ( 1 + rsq )
419 //      Poly  := Poly1 + r_to_the_8*Poly2
420 //      Result := r*Poly + CORR
421 //      Result := r + Result     ...in user-defined rounding
422 //      ...note that Poly1 and r_to_the_8 can be computed in parallel
423 //      ...with Poly2 (Poly1 is intentionally set to be much
424 //      ...shorter than Poly2 so that r_to_the_8 and CORR can be hidden)
426 // For N odd,
427 //      S_hi  := -frcpa(r)               ...8 bits
428 //      S_hi  := S_hi + S_hi*(1 + S_hi*r)     ...16 bits
429 //      S_hi  := S_hi + S_hi*(1 + S_hi*r)     ...32 bits
430 //      S_hi  := S_hi + S_hi*(1 + S_hi*r)     ...64 bits
431 //      S_lo  := S_hi*( (1 + S_hi*r) + S_hi*c )
432 //      ...S_hi + S_lo is -1/(r+c) to extra precision
433 //      S_lo  := S_lo + Q1_1*c
435 //      ...S_hi and S_lo are computed in parallel with
436 //      ...the following
437 //      rsq := r*r
438 //      P   := Q1_1 + rsq*(Q1_2 + rsq*(Q1_3 + ... + rsq*Q1_7))
440 //      Result :=  r*P + S_lo
441 //      Result :=  S_hi  +  Result      ...in user-defined rounding
444 // Algorithm for the case of normal_r
445 // ----------------------------------
447 // Here, we first consider the computation of tan( r + c ). As
448 // presented in the previous section,
450 //      tan( r + c )  =  tan(r) + c * sec^2(r)
451 //                 =  sgn_r * [ tan(B+x) + CORR ]
452 //      CORR = sgn_r * c * tan(B) * 1/[sin(B)*cos(B)]
454 // because sec^2(r) = sec^(|r|), and B approximate |r| to 6.5 bits.
456 //      tan( r + c ) =
457 //           /           (1/[sin(B)*cos(B)]) * tan(x)
458 //      sgn_r * | tan(B) + --------------------------------  +
459 //           \                     cot(B)  -  tan(x)
460 //                                \ 
461 //                          CORR  |
463 //                                /
465 // The values of tan(B), cot(B) and 1/(sin(B)*cos(B)) are
466 // calculated beforehand and stored in a table. Specifically,
467 // the table values are
469 //      tan(B)                as  T_hi  +  T_lo;
470 //      cot(B)             as  C_hi  +  C_lo;
471 //      1/[sin(B)*cos(B)]  as  SC_inv
473 // T_hi, C_hi are in  double-precision  memory format;
474 // T_lo, C_lo are in  single-precision  memory format;
475 // SC_inv     is  in extended-precision memory format.
477 // The value of tan(x) will be approximated by a short polynomial of
478 // the form
480 //      tan(x)  as  x  +  x * P, where
481 //           P  =   x^2 * (P2_1 + x^2 * (P2_2 + x^2 * P2_3))
483 // Because |x| <= 2^(-7), cot(B) - x approximates cot(B) - tan(x)
484 // to a relative accuracy better than 2^(-20). Thus, a good
485 // initial guess of 1/( cot(B) - tan(x) ) to initiate the iterative
486 // division is:
488 //      1/(cot(B) - tan(x))      is approximately
489 //      1/(cot(B) -   x)         is
490 //      tan(B)/(1 - x*tan(B))    is approximately
491 //      T_hi / ( 1 - T_hi * x )  is approximately
493 //      T_hi * [ 1 + (Thi * x) + (T_hi * x)^2 ]
495 // The calculation of tan(r+c) therefore proceed as follows:
497 //      Tx     := T_hi * x
498 //      xsq     := x * x
500 //      V_hi     := T_hi*(1 + Tx*(1 + Tx))
501 //      P     := xsq * (P1_1 + xsq*(P1_2 + xsq*P1_3))
502 //      ...V_hi serves as an initial guess of 1/(cot(B) - tan(x))
503 //         ...good to about 20 bits of accuracy
505 //      tanx     := x + x*P
506 //      D     := C_hi - tanx
507 //      ...D is a double precision denominator: cot(B) - tan(x)
509 //      V_hi     := V_hi + V_hi*(1 - V_hi*D)
510 //      ....V_hi approximates 1/(cot(B)-tan(x)) to 40 bits
512 //      V_lo     := V_hi * ( [ (1 - V_hi*C_hi) + V_hi*tanx ]
513 //                           - V_hi*C_lo )   ...observe all order
514 //         ...V_hi + V_lo approximates 1/(cot(B) - tan(x))
515 //      ...to extra accuracy
517 //      ...               SC_inv(B) * (x + x*P)
518 //      ...   tan(B) +      ------------------------- + CORR
519 //         ...                cot(B) - (x + x*P)
520 //      ...
521 //      ... = tan(B) + SC_inv(B)*(x + x*P)*(V_hi + V_lo) + CORR
522 //      ...
524 //      Sx     := SC_inv * x
525 //      CORR     := sgn_r * c * SC_inv * T_hi
527 //      ...put the ingredients together to compute
528 //      ...               SC_inv(B) * (x + x*P)
529 //      ...   tan(B) +      ------------------------- + CORR
530 //         ...                cot(B) - (x + x*P)
531 //      ...
532 //      ... = tan(B) + SC_inv(B)*(x + x*P)*(V_hi + V_lo) + CORR
533 //      ...
534 //      ... = T_hi + T_lo + CORR +
535 //      ...    Sx * V_hi + Sx * V_lo + Sx * P *(V_hi + V_lo)
537 //      CORR := CORR + T_lo
538 //      tail := V_lo + P*(V_hi + V_lo)
539 //         tail := Sx * tail  +  CORR
540 //      tail := Sx * V_hi  +  tail
541 //         T_hi := sgn_r * T_hi
543 //         ...T_hi + sgn_r*tail  now approximate
544 //      ...sgn_r*(tan(B+x) + CORR) accurately
546 //      Result :=  T_hi + sgn_r*tail  ...in user-defined
547 //                           ...rounding control
548 //      ...It is crucial that independent paths be fully
549 //      ...exploited for performance's sake.
552 // Next, we consider the computation of -cot( r + c ). As
553 // presented in the previous section,
555 //        -cot( r + c )  =  -cot(r) + c * csc^2(r)
556 //                 =  sgn_r * [ -cot(B+x) + CORR ]
557 //      CORR = sgn_r * c * cot(B) * 1/[sin(B)*cos(B)]
559 // because csc^2(r) = csc^(|r|), and B approximate |r| to 6.5 bits.
561 //        -cot( r + c ) =
562 //           /             (1/[sin(B)*cos(B)]) * tan(x)
563 //      sgn_r * | -cot(B) + --------------------------------  +
564 //           \                     tan(B)  +  tan(x)
565 //                                \ 
566 //                          CORR  |
568 //                                /
570 // The values of tan(B), cot(B) and 1/(sin(B)*cos(B)) are
571 // calculated beforehand and stored in a table. Specifically,
572 // the table values are
574 //      tan(B)                as  T_hi  +  T_lo;
575 //      cot(B)             as  C_hi  +  C_lo;
576 //      1/[sin(B)*cos(B)]  as  SC_inv
578 // T_hi, C_hi are in  double-precision  memory format;
579 // T_lo, C_lo are in  single-precision  memory format;
580 // SC_inv     is  in extended-precision memory format.
582 // The value of tan(x) will be approximated by a short polynomial of
583 // the form
585 //      tan(x)  as  x  +  x * P, where
586 //           P  =   x^2 * (P2_1 + x^2 * (P2_2 + x^2 * P2_3))
588 // Because |x| <= 2^(-7), tan(B) + x approximates tan(B) + tan(x)
589 // to a relative accuracy better than 2^(-18). Thus, a good
590 // initial guess of 1/( tan(B) + tan(x) ) to initiate the iterative
591 // division is:
593 //      1/(tan(B) + tan(x))      is approximately
594 //      1/(tan(B) +   x)         is
595 //      cot(B)/(1 + x*cot(B))    is approximately
596 //      C_hi / ( 1 + C_hi * x )  is approximately
598 //      C_hi * [ 1 - (C_hi * x) + (C_hi * x)^2 ]
600 // The calculation of -cot(r+c) therefore proceed as follows:
602 //      Cx     := C_hi * x
603 //      xsq     := x * x
605 //      V_hi     := C_hi*(1 - Cx*(1 - Cx))
606 //      P     := xsq * (P1_1 + xsq*(P1_2 + xsq*P1_3))
607 //      ...V_hi serves as an initial guess of 1/(tan(B) + tan(x))
608 //         ...good to about 18 bits of accuracy
610 //      tanx     := x + x*P
611 //      D     := T_hi + tanx
612 //      ...D is a double precision denominator: tan(B) + tan(x)
614 //      V_hi     := V_hi + V_hi*(1 - V_hi*D)
615 //      ....V_hi approximates 1/(tan(B)+tan(x)) to 40 bits
617 //      V_lo     := V_hi * ( [ (1 - V_hi*T_hi) - V_hi*tanx ]
618 //                           - V_hi*T_lo )   ...observe all order
619 //         ...V_hi + V_lo approximates 1/(tan(B) + tan(x))
620 //      ...to extra accuracy
622 //      ...               SC_inv(B) * (x + x*P)
623 //      ...  -cot(B) +      ------------------------- + CORR
624 //         ...                tan(B) + (x + x*P)
625 //      ...
626 //      ... =-cot(B) + SC_inv(B)*(x + x*P)*(V_hi + V_lo) + CORR
627 //      ...
629 //      Sx     := SC_inv * x
630 //      CORR     := sgn_r * c * SC_inv * C_hi
632 //      ...put the ingredients together to compute
633 //      ...               SC_inv(B) * (x + x*P)
634 //      ...  -cot(B) +      ------------------------- + CORR
635 //         ...                tan(B) + (x + x*P)
636 //      ...
637 //      ... =-cot(B) + SC_inv(B)*(x + x*P)*(V_hi + V_lo) + CORR
638 //      ...
639 //      ... =-C_hi - C_lo + CORR +
640 //      ...    Sx * V_hi + Sx * V_lo + Sx * P *(V_hi + V_lo)
642 //      CORR := CORR - C_lo
643 //      tail := V_lo + P*(V_hi + V_lo)
644 //         tail := Sx * tail  +  CORR
645 //      tail := Sx * V_hi  +  tail
646 //         C_hi := -sgn_r * C_hi
648 //         ...C_hi + sgn_r*tail now approximates
649 //      ...sgn_r*(-cot(B+x) + CORR) accurately
651 //      Result :=  C_hi + sgn_r*tail   in user-defined rounding control
652 //      ...It is crucial that independent paths be fully
653 //      ...exploited for performance's sake.
655 // 3. Implementation Notes
656 // =======================
658 //   Table entries T_hi, T_lo; C_hi, C_lo; SC_inv
660 //   Recall that 2^(-2) <= |r| <= pi/4;
662 //      r = sgn_r * 2^k * 1.b_1 b_2 ... b_63
664 //   and
666 //        B = 2^k * 1.b_1 b_2 b_3 b_4 b_5 1
668 //   Thus, for k = -2, possible values of B are
670 //          B = 2^(-2) * ( 1 + index/32  +  1/64 ),
671 //      index ranges from 0 to 31
673 //   For k = -1, however, since |r| <= pi/4 = 0.78...
674 //   possible values of B are
676 //        B = 2^(-1) * ( 1 + index/32  +  1/64 )
677 //      index ranges from 0 to 19.
681 #include "libm_support.h"
683 #ifdef _LIBC
684 .rodata
685 #else
686 .data
687 #endif
689 .align 128
691 TAN_BASE_CONSTANTS:
692 ASM_TYPE_DIRECTIVE(TAN_BASE_CONSTANTS,@object)
693 data4    0x4B800000, 0xCB800000, 0x38800000, 0xB8800000 // two**24, -two**24
694                                                         // two**-14, -two**-14
695 data4    0x4E44152A, 0xA2F9836E, 0x00003FFE, 0x00000000 // two_by_pi
696 data4    0xCE81B9F1, 0xC84D32B0, 0x00004016, 0x00000000 // P_0
697 data4    0x2168C235, 0xC90FDAA2, 0x00003FFF, 0x00000000 // P_1
698 data4    0xFC8F8CBB, 0xECE675D1, 0x0000BFBD, 0x00000000 // P_2
699 data4    0xACC19C60, 0xB7ED8FBB, 0x0000BF7C, 0x00000000 // P_3
700 data4    0x5F000000, 0xDF000000, 0x00000000, 0x00000000 // two_to_63, -two_to_63
701 data4    0x6EC6B45A, 0xA397E504, 0x00003FE7, 0x00000000 // Inv_P_0
702 data4    0xDBD171A1, 0x8D848E89, 0x0000BFBF, 0x00000000 // d_1
703 data4    0x18A66F8E, 0xD5394C36, 0x0000BF7C, 0x00000000 // d_2
704 data4    0x2168C234, 0xC90FDAA2, 0x00003FFE, 0x00000000 // PI_BY_4
705 data4    0x2168C234, 0xC90FDAA2, 0x0000BFFE, 0x00000000 // MPI_BY_4
706 data4    0x3E800000, 0xBE800000, 0x00000000, 0x00000000 // two**-2, -two**-2
707 data4    0x2F000000, 0xAF000000, 0x00000000, 0x00000000 // two**-33, -two**-33
708 data4    0xAAAAAABD, 0xAAAAAAAA, 0x00003FFD, 0x00000000 // P1_1
709 data4    0x88882E6A, 0x88888888, 0x00003FFC, 0x00000000 // P1_2
710 data4    0x0F0177B6, 0xDD0DD0DD, 0x00003FFA, 0x00000000 // P1_3
711 data4    0x646B8C6D, 0xB327A440, 0x00003FF9, 0x00000000 // P1_4
712 data4    0x1D5F7D20, 0x91371B25, 0x00003FF8, 0x00000000 // P1_5
713 data4    0x61C67914, 0xEB69A5F1, 0x00003FF6, 0x00000000 // P1_6
714 data4    0x019318D2, 0xBEDD37BE, 0x00003FF5, 0x00000000 // P1_7
715 data4    0x3C794015, 0x9979B146, 0x00003FF4, 0x00000000 // P1_8
716 data4    0x8C6EB58A, 0x8EBD21A3, 0x00003FF3, 0x00000000 // P1_9
717 data4    0xAAAAAAB4, 0xAAAAAAAA, 0x00003FFD, 0x00000000 // Q1_1
718 data4    0x0B5FC93E, 0xB60B60B6, 0x00003FF9, 0x00000000 // Q1_2
719 data4    0x0C9BBFBF, 0x8AB355E0, 0x00003FF6, 0x00000000 // Q1_3
720 data4    0xCBEE3D4C, 0xDDEBBC89, 0x00003FF2, 0x00000000 // Q1_4
721 data4    0x5F80BBB6, 0xB3548A68, 0x00003FEF, 0x00000000 // Q1_5
722 data4    0x4CED5BF1, 0x91362560, 0x00003FEC, 0x00000000 // Q1_6
723 data4    0x8EE92A83, 0xF189D95A, 0x00003FE8, 0x00000000 // Q1_7
724 data4    0xAAAB362F, 0xAAAAAAAA, 0x00003FFD, 0x00000000 // P2_1
725 data4    0xE97A6097, 0x88888886, 0x00003FFC, 0x00000000 // P2_2
726 data4    0x25E716A1, 0xDD108EE0, 0x00003FFA, 0x00000000 // P2_3
728 //  Entries T_hi   double-precision memory format
729 //  Index = 0,1,...,31  B = 2^(-2)*(1+Index/32+1/64)
730 //  Entries T_lo  single-precision memory format
731 //  Index = 0,1,...,31  B = 2^(-2)*(1+Index/32+1/64)
733 data4    0x62400794, 0x3FD09BC3, 0x23A05C32, 0x00000000
734 data4    0xDFFBC074, 0x3FD124A9, 0x240078B2, 0x00000000
735 data4    0x5BD4920F, 0x3FD1AE23, 0x23826B8E, 0x00000000
736 data4    0x15E2701D, 0x3FD23835, 0x22D31154, 0x00000000
737 data4    0x63739C2D, 0x3FD2C2E4, 0x2265C9E2, 0x00000000
738 data4    0xAFEEA48B, 0x3FD34E36, 0x245C05EB, 0x00000000
739 data4    0x7DBB35D1, 0x3FD3DA31, 0x24749F2D, 0x00000000
740 data4    0x67321619, 0x3FD466DA, 0x2462CECE, 0x00000000
741 data4    0x1F94A4D5, 0x3FD4F437, 0x246D0DF1, 0x00000000
742 data4    0x740C3E6D, 0x3FD5824D, 0x240A85B5, 0x00000000
743 data4    0x4CB1E73D, 0x3FD61123, 0x23F96E33, 0x00000000
744 data4    0xAD9EA64B, 0x3FD6A0BE, 0x247C5393, 0x00000000
745 data4    0xB804FD01, 0x3FD73125, 0x241F3B29, 0x00000000
746 data4    0xAB53EE83, 0x3FD7C25E, 0x2479989B, 0x00000000
747 data4    0xE6640EED, 0x3FD8546F, 0x23B343BC, 0x00000000
748 data4    0xE8AF1892, 0x3FD8E75F, 0x241454D1, 0x00000000
749 data4    0x53928BDA, 0x3FD97B35, 0x238613D9, 0x00000000
750 data4    0xEB9DE4DE, 0x3FDA0FF6, 0x22859FA7, 0x00000000
751 data4    0x99ECF92D, 0x3FDAA5AB, 0x237A6D06, 0x00000000
752 data4    0x6D8F1796, 0x3FDB3C5A, 0x23952F6C, 0x00000000
753 data4    0x9CFB8BE4, 0x3FDBD40A, 0x2280FC95, 0x00000000
754 data4    0x87943100, 0x3FDC6CC3, 0x245D2EC0, 0x00000000
755 data4    0xB736C500, 0x3FDD068C, 0x23C4AD7D, 0x00000000
756 data4    0xE1DDBC31, 0x3FDDA16D, 0x23D076E6, 0x00000000
757 data4    0xEB515A93, 0x3FDE3D6E, 0x244809A6, 0x00000000
758 data4    0xE6E9E5F1, 0x3FDEDA97, 0x220856C8, 0x00000000
759 data4    0x1963CE69, 0x3FDF78F1, 0x244BE993, 0x00000000
760 data4    0x7D635BCE, 0x3FE00C41, 0x23D21799, 0x00000000
761 data4    0x1C302CD3, 0x3FE05CAB, 0x248A1B1D, 0x00000000
762 data4    0xDB6A1FA0, 0x3FE0ADB9, 0x23D53E33, 0x00000000
763 data4    0x4A20BA81, 0x3FE0FF72, 0x24DB9ED5, 0x00000000
764 data4    0x153FA6F5, 0x3FE151D9, 0x24E9E451, 0x00000000
766 //  Entries T_hi   double-precision memory format
767 //  Index = 0,1,...,19  B = 2^(-1)*(1+Index/32+1/64)
768 //  Entries T_lo  single-precision memory format
769 //  Index = 0,1,...,19  B = 2^(-1)*(1+Index/32+1/64)
771 data4    0xBA1BE39E, 0x3FE1CEC4, 0x24B60F9E, 0x00000000
772 data4    0x5ABD9B2D, 0x3FE277E4, 0x248C2474, 0x00000000
773 data4    0x0272B110, 0x3FE32418, 0x247B8311, 0x00000000
774 data4    0x890E2DF0, 0x3FE3D38B, 0x24C55751, 0x00000000
775 data4    0x46236871, 0x3FE4866D, 0x24E5BC34, 0x00000000
776 data4    0x45E044B0, 0x3FE53CEE, 0x24001BA4, 0x00000000
777 data4    0x82EC06E4, 0x3FE5F742, 0x24B973DC, 0x00000000
778 data4    0x25DF43F9, 0x3FE6B5A1, 0x24895440, 0x00000000
779 data4    0xCAFD348C, 0x3FE77844, 0x240021CA, 0x00000000
780 data4    0xCEED6B92, 0x3FE83F6B, 0x24C45372, 0x00000000
781 data4    0xA34F3665, 0x3FE90B58, 0x240DAD33, 0x00000000
782 data4    0x2C1E56B4, 0x3FE9DC52, 0x24F846CE, 0x00000000
783 data4    0x27041578, 0x3FEAB2A4, 0x2323FB6E, 0x00000000
784 data4    0x9DD8C373, 0x3FEB8E9F, 0x24B3090B, 0x00000000
785 data4    0x65C9AA7B, 0x3FEC709B, 0x2449F611, 0x00000000
786 data4    0xACCF8435, 0x3FED58F4, 0x23616A7E, 0x00000000
787 data4    0x97635082, 0x3FEE480F, 0x24C2FEAE, 0x00000000
788 data4    0xF0ACC544, 0x3FEF3E57, 0x242CE964, 0x00000000
789 data4    0xF7E06E4B, 0x3FF01E20, 0x2480D3EE, 0x00000000
790 data4    0x8A798A69, 0x3FF0A125, 0x24DB8967, 0x00000000
792 //  Entries C_hi   double-precision memory format
793 //  Index = 0,1,...,31  B = 2^(-2)*(1+Index/32+1/64)
794 //  Entries C_lo  single-precision memory format
795 //  Index = 0,1,...,31  B = 2^(-2)*(1+Index/32+1/64)
797 data4    0xE63EFBD0, 0x400ED3E2, 0x259D94D4, 0x00000000
798 data4    0xC515DAB5, 0x400DDDB4, 0x245F0537, 0x00000000
799 data4    0xBE19A79F, 0x400CF57A, 0x25D4EA9F, 0x00000000
800 data4    0xD15298ED, 0x400C1A06, 0x24AE40A0, 0x00000000
801 data4    0x164B2708, 0x400B4A4C, 0x25A5AAB6, 0x00000000
802 data4    0x5285B068, 0x400A855A, 0x25524F18, 0x00000000
803 data4    0x3FFA549F, 0x4009CA5A, 0x24C999C0, 0x00000000
804 data4    0x646AF623, 0x4009188A, 0x254FD801, 0x00000000
805 data4    0x6084D0E7, 0x40086F3C, 0x2560F5FD, 0x00000000
806 data4    0xA29A76EE, 0x4007CDD2, 0x255B9D19, 0x00000000
807 data4    0x6C8ECA95, 0x400733BE, 0x25CB021B, 0x00000000
808 data4    0x1F8DDC52, 0x4006A07E, 0x24AB4722, 0x00000000
809 data4    0xC298AD58, 0x4006139B, 0x252764E2, 0x00000000
810 data4    0xBAD7164B, 0x40058CAB, 0x24DAF5DB, 0x00000000
811 data4    0xAE31A5D3, 0x40050B4B, 0x25EA20F4, 0x00000000
812 data4    0x89F85A8A, 0x40048F21, 0x2583A3E8, 0x00000000
813 data4    0xA862380D, 0x400417DA, 0x25DCC4CC, 0x00000000
814 data4    0x1088FCFE, 0x4003A52B, 0x2430A492, 0x00000000
815 data4    0xCD3527D5, 0x400336CC, 0x255F77CF, 0x00000000
816 data4    0x5760766D, 0x4002CC7F, 0x25DA0BDA, 0x00000000
817 data4    0x11CE02E3, 0x40026607, 0x256FF4A2, 0x00000000
818 data4    0xD37BBE04, 0x4002032C, 0x25208AED, 0x00000000
819 data4    0x7F050775, 0x4001A3BD, 0x24B72DD6, 0x00000000
820 data4    0xA554848A, 0x40014789, 0x24AB4DAA, 0x00000000
821 data4    0x323E81B7, 0x4000EE65, 0x2584C440, 0x00000000
822 data4    0x21CF1293, 0x40009827, 0x25C9428D, 0x00000000
823 data4    0x3D415EEB, 0x400044A9, 0x25DC8482, 0x00000000
824 data4    0xBD72C577, 0x3FFFE78F, 0x257F5070, 0x00000000
825 data4    0x75EFD28E, 0x3FFF4AC3, 0x23EBBF7A, 0x00000000
826 data4    0x60B52DDE, 0x3FFEB2AF, 0x22EECA07, 0x00000000
827 data4    0x35204180, 0x3FFE1F19, 0x24191079, 0x00000000
828 data4    0x54F7E60A, 0x3FFD8FCA, 0x248D3058, 0x00000000
830 //  Entries C_hi   double-precision memory format
831 //  Index = 0,1,...,19  B = 2^(-1)*(1+Index/32+1/64)
832 //  Entries C_lo  single-precision memory format
833 //  Index = 0,1,...,19  B = 2^(-1)*(1+Index/32+1/64)
835 data4    0x79F6FADE, 0x3FFCC06A, 0x239C7886, 0x00000000
836 data4    0x891662A6, 0x3FFBB91F, 0x250BD191, 0x00000000
837 data4    0x529F155D, 0x3FFABFB6, 0x256CC3E6, 0x00000000
838 data4    0x2E964AE9, 0x3FF9D300, 0x250843E3, 0x00000000
839 data4    0x89DCB383, 0x3FF8F1EF, 0x2277C87E, 0x00000000
840 data4    0x7C87DBD6, 0x3FF81B93, 0x256DA6CF, 0x00000000
841 data4    0x1042EDE4, 0x3FF74F14, 0x2573D28A, 0x00000000
842 data4    0x1784B360, 0x3FF68BAF, 0x242E489A, 0x00000000
843 data4    0x7C923C4C, 0x3FF5D0B5, 0x2532D940, 0x00000000
844 data4    0xF418EF20, 0x3FF51D88, 0x253C7DD6, 0x00000000
845 data4    0x02F88DAE, 0x3FF4719A, 0x23DB59BF, 0x00000000
846 data4    0x49DA0788, 0x3FF3CC66, 0x252B4756, 0x00000000
847 data4    0x0B980DB8, 0x3FF32D77, 0x23FE585F, 0x00000000
848 data4    0xE56C987A, 0x3FF2945F, 0x25378A63, 0x00000000
849 data4    0xB16523F6, 0x3FF200BD, 0x247BB2E0, 0x00000000
850 data4    0x8CE27778, 0x3FF17235, 0x24446538, 0x00000000
851 data4    0xFDEFE692, 0x3FF0E873, 0x2514638F, 0x00000000
852 data4    0x33154062, 0x3FF0632C, 0x24A7FC27, 0x00000000
853 data4    0xB3EF115F, 0x3FEFC42E, 0x248FD0FE, 0x00000000
854 data4    0x135D26F6, 0x3FEEC9E8, 0x2385C719, 0x00000000
856 //  Entries SC_inv in Swapped IEEE format (extended)
857 //  Index = 0,1,...,31  B = 2^(-2)*(1+Index/32+1/64)
859 data4    0x1BF30C9E, 0x839D6D4A, 0x00004001, 0x00000000
860 data4    0x554B0EB0, 0x80092804, 0x00004001, 0x00000000
861 data4    0xA1CF0DE9, 0xF959F94C, 0x00004000, 0x00000000
862 data4    0x77378677, 0xF3086BA0, 0x00004000, 0x00000000
863 data4    0xCCD4723C, 0xED154515, 0x00004000, 0x00000000
864 data4    0x1C27CF25, 0xE7790944, 0x00004000, 0x00000000
865 data4    0x8DDACB88, 0xE22D037D, 0x00004000, 0x00000000
866 data4    0x89C73522, 0xDD2B2D8A, 0x00004000, 0x00000000
867 data4    0xBB2C1171, 0xD86E1A23, 0x00004000, 0x00000000
868 data4    0xDFF5E0F9, 0xD3F0E288, 0x00004000, 0x00000000
869 data4    0x283BEBD5, 0xCFAF16B1, 0x00004000, 0x00000000
870 data4    0x0D88DD53, 0xCBA4AFAA, 0x00004000, 0x00000000
871 data4    0xCA67C43D, 0xC7CE03CC, 0x00004000, 0x00000000
872 data4    0x0CA0DDB0, 0xC427BC82, 0x00004000, 0x00000000
873 data4    0xF13D8CAB, 0xC0AECD57, 0x00004000, 0x00000000
874 data4    0x71ECE6B1, 0xBD606C38, 0x00004000, 0x00000000
875 data4    0xA44C4929, 0xBA3A0A96, 0x00004000, 0x00000000
876 data4    0xE5CCCEC1, 0xB7394F6F, 0x00004000, 0x00000000
877 data4    0x9637D8BC, 0xB45C1203, 0x00004000, 0x00000000
878 data4    0x92CB051B, 0xB1A05528, 0x00004000, 0x00000000
879 data4    0x6BA2FFD0, 0xAF04432B, 0x00004000, 0x00000000
880 data4    0x7221235F, 0xAC862A23, 0x00004000, 0x00000000
881 data4    0x5F00A9D1, 0xAA2478AF, 0x00004000, 0x00000000
882 data4    0x81E082BF, 0xA7DDBB0C, 0x00004000, 0x00000000
883 data4    0x45684FEE, 0xA5B0987D, 0x00004000, 0x00000000
884 data4    0x627A8F53, 0xA39BD0F5, 0x00004000, 0x00000000
885 data4    0x6EC5C8B0, 0xA19E3B03, 0x00004000, 0x00000000
886 data4    0x91CD7C66, 0x9FB6C1F0, 0x00004000, 0x00000000
887 data4    0x1FA3DF8A, 0x9DE46410, 0x00004000, 0x00000000
888 data4    0xA8F6B888, 0x9C263139, 0x00004000, 0x00000000
889 data4    0xC27B0450, 0x9A7B4968, 0x00004000, 0x00000000
890 data4    0x5EE614EE, 0x98E2DB7E, 0x00004000, 0x00000000
892 //  Entries SC_inv in Swapped IEEE format (extended)
893 //  Index = 0,1,...,19  B = 2^(-1)*(1+Index/32+1/64)
895 data4    0x13B2B5BA, 0x969F335C, 0x00004000, 0x00000000
896 data4    0xD4C0F548, 0x93D446D9, 0x00004000, 0x00000000
897 data4    0x61B798AF, 0x9147094F, 0x00004000, 0x00000000
898 data4    0x758787AC, 0x8EF317CC, 0x00004000, 0x00000000
899 data4    0xB99EEFDB, 0x8CD498B3, 0x00004000, 0x00000000
900 data4    0xDFF8BC37, 0x8AE82A7D, 0x00004000, 0x00000000
901 data4    0xE3C55D42, 0x892AD546, 0x00004000, 0x00000000
902 data4    0xD15573C1, 0x8799FEA9, 0x00004000, 0x00000000
903 data4    0x435A4B4C, 0x86335F88, 0x00004000, 0x00000000
904 data4    0x3E93A87B, 0x84F4FB6E, 0x00004000, 0x00000000
905 data4    0x80A382FB, 0x83DD1952, 0x00004000, 0x00000000
906 data4    0xA4CB8C9E, 0x82EA3D7F, 0x00004000, 0x00000000
907 data4    0x6861D0A8, 0x821B247C, 0x00004000, 0x00000000
908 data4    0x63E8D244, 0x816EBED1, 0x00004000, 0x00000000
909 data4    0x27E4CFC6, 0x80E42D91, 0x00004000, 0x00000000
910 data4    0x28E64AFD, 0x807ABF8D, 0x00004000, 0x00000000
911 data4    0x863B4FD8, 0x8031EF26, 0x00004000, 0x00000000
912 data4    0xAE8C11FD, 0x800960AD, 0x00004000, 0x00000000
913 data4    0x5FDBEC21, 0x8000E147, 0x00004000, 0x00000000
914 data4    0xA07791FA, 0x80186650, 0x00004000, 0x00000000
916 Arg                 = f8   
917 Result              = f8
918 fp_tmp              = f9
919 U_2                 = f10
920 rsq                =  f11
921 C_hi                = f12
922 C_lo                = f13
923 T_hi                = f14
924 T_lo                = f15
926 N_0                 = f32
927 d_1                 = f33
928 MPI_BY_4            = f34
929 tail                = f35
930 tanx                = f36
931 Cx                  = f37
932 Sx                  = f38
933 sgn_r               = f39
934 CORR                = f40
935 P                   = f41
936 D                   = f42
937 ArgPrime            = f43
938 P_0                 = f44
940 P2_1                = f45
941 P2_2                = f46
942 P2_3                = f47
944 P1_1                = f45
945 P1_2                = f46
946 P1_3                = f47
948 P1_4                = f48
949 P1_5                = f49
950 P1_6                = f50
951 P1_7                = f51
952 P1_8                = f52
953 P1_9                = f53
955 TWO_TO_63           = f54
956 NEGTWO_TO_63        = f55
957 x                   = f56
958 xsq                 = f57
959 Tx                  = f58
960 Tx1                 = f59
961 Set                 = f60
962 poly1               = f61
963 poly2               = f62
964 Poly                = f63
965 Poly1               = f64
966 Poly2               = f65
967 r_to_the_8          = f66
968 B                   = f67
969 SC_inv              = f68
970 Pos_r               = f69
971 N_0_fix             = f70
972 PI_BY_4             = f71
973 NEGTWO_TO_NEG2      = f72
974 TWO_TO_24           = f73
975 TWO_TO_NEG14        = f74
976 TWO_TO_NEG33        = f75
977 NEGTWO_TO_24        = f76
978 NEGTWO_TO_NEG14     = f76
979 NEGTWO_TO_NEG33     = f77
980 two_by_PI           = f78
981 N                   = f79
982 N_fix               = f80
983 P_1                 = f81
984 P_2                 = f82
985 P_3                 = f83
986 s_val               = f84
987 w                   = f85
988 c                   = f86
989 r                   = f87
990 Z                   = f88
991 A                   = f89
992 a                   = f90
993 t                   = f91
994 U_1                 = f92
995 d_2                 = f93
996 TWO_TO_NEG2         = f94
997 Q1_1                = f95
998 Q1_2                = f96
999 Q1_3                = f97
1000 Q1_4                = f98
1001 Q1_5                = f99
1002 Q1_6                = f100
1003 Q1_7                = f101
1004 Q1_8                = f102
1005 S_hi                = f103
1006 S_lo                = f104
1007 V_hi                = f105
1008 V_lo                = f106
1009 U_hi                = f107
1010 U_lo                = f108
1011 U_hiabs             = f109
1012 V_hiabs             = f110
1013 V                   = f111
1014 Inv_P_0             = f112
1016 GR_SAVE_B0     = r33
1017 GR_SAVE_GP     = r34
1018 GR_SAVE_PFS    = r35
1020 delta1         = r36
1021 table_ptr1     = r37
1022 table_ptr2     = r38
1023 i_0            = r39
1024 i_1            = r40 
1025 N_fix_gr       = r41 
1026 N_inc          = r42 
1027 exp_Arg        = r43 
1028 exp_r          = r44 
1029 sig_r          = r45 
1030 lookup         = r46   
1031 table_offset   = r47 
1032 Create_B       = r48 
1033 gr_tmp         = r49
1035 GR_Parameter_X = r49
1036 GR_Parameter_r = r50
1040 .global __libm_tan
1041 .section .text
1042 .proc __libm_tan
1045 __libm_tan: 
1047 { .mfi
1048 alloc r32 = ar.pfs, 0,17,2,0
1049 (p0)   fclass.m.unc  p6,p0 = Arg, 0x1E7
1050       addl gr_tmp = -1,r0             
1054 { .mfi
1055        nop.m 999
1056 (p0)   fclass.nm.unc  p7,p0 = Arg, 0x1FF
1057        nop.i 999
1061 { .mfi
1062 (p0)  addl           table_ptr1   = @ltoff(TAN_BASE_CONSTANTS), gp
1063        nop.f 999
1064        nop.i 999
1068 { .mmi
1069       ld8 table_ptr1 = [table_ptr1]
1070       setf.sig fp_tmp = gr_tmp   // Make a constant so fmpy produces inexact
1071       nop.i 999
1076 //     Check for NatVals, Infs , NaNs, and Zeros 
1077 //     Check for everything - if false, then must be pseudo-zero
1078 //     or pseudo-nan.
1079 //     Local table pointer
1082 { .mbb
1083 (p0)   add table_ptr2 = 96, table_ptr1
1084 (p6)   br.cond.spnt __libm_TAN_SPECIAL 
1085 (p7)   br.cond.spnt __libm_TAN_SPECIAL ;;
1088 //     Point to Inv_P_0
1089 //     Branch out to deal with unsupporteds and special values. 
1092 { .mmf
1093 (p0)   ldfs TWO_TO_24 = [table_ptr1],4
1094 (p0)   ldfs TWO_TO_63 = [table_ptr2],4
1096 //     Load -2**24, load -2**63.
1098 (p0)   fcmp.eq.s0 p0, p6 = Arg, f1 ;;
1101 { .mfi
1102 (p0)   ldfs NEGTWO_TO_63 = [table_ptr2],12
1103 (p0)   fnorm.s1     Arg = Arg
1104         nop.i 999
1107 //     Load 2**24, Load 2**63.
1110 { .mmi
1111 (p0)   ldfs NEGTWO_TO_24 = [table_ptr1],12 ;;
1113 //     Do fcmp to generate Denormal exception 
1114 //     - can't do FNORM (will generate Underflow when U is unmasked!)
1115 //     Normalize input argument.
1117 (p0)   ldfe two_by_PI = [table_ptr1],16
1118         nop.i 999
1121 { .mmi
1122 (p0)   ldfe Inv_P_0 = [table_ptr2],16 ;;
1123 (p0)   ldfe d_1 = [table_ptr2],16
1124         nop.i 999
1127 //     Decide about the paths to take:
1128 //     PR_1 and PR_3 set if -2**24 < Arg < 2**24 - CASE 1 OR 2
1129 //     OTHERWISE - CASE 3 OR 4
1130 //     Load inverse of P_0 .
1131 //     Set PR_6 if Arg <= -2**63
1132 //     Are there any Infs, NaNs, or zeros?
1135 { .mmi
1136 (p0)   ldfe P_0 = [table_ptr1],16 ;;
1137 (p0)   ldfe d_2 = [table_ptr2],16
1138         nop.i 999
1141 //     Set PR_8 if Arg <= -2**24
1142 //     Set PR_6 if Arg >=  2**63
1145 { .mmi
1146 (p0)   ldfe P_1 = [table_ptr1],16 ;;
1147 (p0)   ldfe PI_BY_4 = [table_ptr2],16
1148         nop.i 999
1151 //     Set PR_8 if Arg >= 2**24
1154 { .mmi
1155 (p0)   ldfe P_2 = [table_ptr1],16 ;;
1156 (p0)   ldfe   MPI_BY_4 = [table_ptr2],16
1157         nop.i 999
1160 //     Load  P_2 and PI_BY_4
1163 { .mfi
1164 (p0)   ldfe   P_3 = [table_ptr1],16
1165         nop.f 999
1166         nop.i 999 ;;
1169 { .mfi
1170         nop.m 999
1171 (p0)   fcmp.le.unc.s1 p6,p7 = Arg,NEGTWO_TO_63
1172         nop.i 999
1175 { .mfi
1176         nop.m 999
1177 (p0)   fcmp.le.unc.s1 p8,p9 = Arg,NEGTWO_TO_24
1178         nop.i 999 ;;
1181 { .mfi
1182         nop.m 999
1183 (p7)   fcmp.ge.s1 p6,p0 = Arg,TWO_TO_63
1184         nop.i 999
1187 { .mfi
1188         nop.m 999
1189 (p9)   fcmp.ge.s1 p8,p0 = Arg,TWO_TO_24
1190         nop.i 999 ;;
1193 { .mib
1194         nop.m 999
1195         nop.i 999
1197 //     Load  P_3 and -PI_BY_4
1199 (p6)   br.cond.spnt TAN_ARG_TOO_LARGE ;;
1202 { .mib
1203         nop.m 999
1204         nop.i 999
1206 //     Load 2**(-2).
1207 //     Load -2**(-2).
1208 //     Branch out if we have a special argument.
1209 //     Branch out if the magnitude of the input argument is too large
1210 //     - do this branch before the next.
1212 (p8)   br.cond.spnt TAN_LARGER_ARG ;;
1215 //     Branch to Cases 3 or 4 if Arg <= -2**24 or Arg >= 2**24
1218 { .mfi
1219 (p0)   ldfs TWO_TO_NEG2 = [table_ptr2],4
1220 //     ARGUMENT REDUCTION CODE - CASE 1 and 2
1221 //     Load 2**(-2).
1222 //     Load -2**(-2).
1223 (p0)   fmpy.s1 N = Arg,two_by_PI
1224         nop.i 999 ;;
1227 { .mfi
1228 (p0)   ldfs NEGTWO_TO_NEG2 = [table_ptr2],12
1230 //     N = Arg * 2/pi
1232 (p0)   fcmp.lt.unc.s1 p8,p9= Arg,PI_BY_4
1233         nop.i 999 ;;
1236 { .mfi
1237         nop.m 999
1239 //     if Arg < pi/4,  set PR_8.
1241 (p8)   fcmp.gt.s1 p8,p9= Arg,MPI_BY_4
1242         nop.i 999 ;;
1245 //     Case 1: Is |r| < 2**(-2).
1246 //     Arg is the same as r in this case.
1247 //     r = Arg
1248 //     c = 0
1251 { .mfi
1252 (p8)   mov N_fix_gr = r0
1254 //     if Arg > -pi/4, reset PR_8.
1255 //     Select the case when |Arg| < pi/4 - set PR[8] = true.
1256 //     Else Select the case when |Arg| >= pi/4 - set PR[9] = true.
1258 (p0)   fcvt.fx.s1 N_fix = N
1259         nop.i 999 ;;
1262 { .mfi
1263         nop.m 999
1265 //     Grab the integer part of N .
1267 (p8)   mov r = Arg
1268         nop.i 999
1271 { .mfi
1272         nop.m 999
1273 (p8)   mov c = f0
1274         nop.i 999 ;;
1277 { .mfi
1278         nop.m 999
1279 (p8)   fcmp.lt.unc.s1 p10, p11 = Arg, TWO_TO_NEG2
1280         nop.i 999 ;;
1283 { .mfi
1284         nop.m 999
1285 (p10)  fcmp.gt.s1 p10,p0 = Arg, NEGTWO_TO_NEG2
1286         nop.i 999 ;;
1289 { .mfi
1290         nop.m 999
1292 //     Case 2: Place integer part of N in GP register.
1294 (p9)   fcvt.xf N = N_fix
1295         nop.i 999 ;;
1298 { .mib
1299 (p9)   getf.sig N_fix_gr = N_fix
1300         nop.i 999
1302 //     Case 2: Convert integer N_fix back to normalized floating-point value.
1304 (p10)  br.cond.spnt TAN_SMALL_R ;;
1307 { .mib
1308         nop.m 999
1309         nop.i 999
1310 (p8)   br.cond.sptk TAN_NORMAL_R ;;
1313 //     Case 1: PR_3 is only affected  when PR_1 is set.
1316 { .mmi
1317 (p9)   ldfs TWO_TO_NEG33 = [table_ptr2], 4 ;;
1319 //     Case 2: Load 2**(-33).
1321 (p9)   ldfs NEGTWO_TO_NEG33 = [table_ptr2], 4
1322         nop.i 999 ;;
1325 { .mfi
1326         nop.m 999
1328 //     Case 2: Load -2**(-33).
1330 (p9)   fnma.s1 s_val = N, P_1, Arg
1331         nop.i 999
1334 { .mfi
1335         nop.m 999
1336 (p9)   fmpy.s1 w = N, P_2
1337         nop.i 999 ;;
1340 { .mfi
1341         nop.m 999
1343 //     Case 2: w = N * P_2
1344 //     Case 2: s_val = -N * P_1  + Arg
1346 (p0)   fcmp.lt.unc.s1 p9,p8 = s_val, TWO_TO_NEG33
1347         nop.i 999 ;;
1350 { .mfi
1351         nop.m 999
1353 //     Decide between case_1 and case_2 reduce:
1355 (p9)   fcmp.gt.s1 p9, p8 = s_val, NEGTWO_TO_NEG33
1356         nop.i 999 ;;
1359 { .mfi
1360         nop.m 999
1362 //     Case 1_reduce:  s <= -2**(-33) or s >= 2**(-33)
1363 //     Case 2_reduce: -2**(-33) < s < 2**(-33)
1365 (p8)   fsub.s1 r = s_val, w
1366         nop.i 999
1369 { .mfi
1370         nop.m 999
1371 (p9)   fmpy.s1 w = N, P_3
1372         nop.i 999 ;;
1375 { .mfi
1376         nop.m 999
1377 (p9)   fma.s1  U_1 = N, P_2, w
1378         nop.i 999
1381 { .mfi
1382         nop.m 999
1384 //     Case 1_reduce: Is |r| < 2**(-2), if so set PR_10
1385 //     else set PR_11.
1387 (p8)   fsub.s1 c = s_val, r
1388         nop.i 999 ;;
1391 { .mfi
1392         nop.m 999
1394 //     Case 1_reduce: r = s + w (change sign)
1395 //     Case 2_reduce: w = N * P_3 (change sign)
1397 (p8)   fcmp.lt.unc.s1 p10, p11 = r, TWO_TO_NEG2
1398         nop.i 999 ;;
1401 { .mfi
1402         nop.m 999
1403 (p10)  fcmp.gt.s1 p10, p11 = r, NEGTWO_TO_NEG2
1404         nop.i 999 ;;
1407 { .mfi
1408         nop.m 999
1409 (p9)   fsub.s1 r = s_val, U_1
1410         nop.i 999
1413 { .mfi
1414         nop.m 999
1416 //     Case 1_reduce: c is complete here.
1417 //     c = c + w (w has not been negated.)
1418 //     Case 2_reduce: r is complete here - continue to calculate c .
1419 //     r = s - U_1
1421 (p9)   fms.s1 U_2 = N, P_2, U_1
1422         nop.i 999 ;;
1425 { .mfi
1426         nop.m 999
1428 //     Case 1_reduce: c = s - r
1429 //     Case 2_reduce: U_1 = N * P_2 + w
1431 (p8)   fsub.s1 c = c, w
1432         nop.i 999 ;;
1435 { .mfi
1436         nop.m 999
1437 (p9)   fsub.s1 s_val = s_val, r
1438         nop.i 999
1441 { .mfb
1442         nop.m 999
1444 //     Case 2_reduce:
1445 //     U_2 = N * P_2 - U_1
1446 //     Not needed until later.
1448 (p9)   fadd.s1 U_2 = U_2, w
1450 //     Case 2_reduce:
1451 //     s = s - r
1452 //     U_2 = U_2 + w
1454 (p10)  br.cond.spnt TAN_SMALL_R ;;
1457 { .mib
1458         nop.m 999
1459         nop.i 999
1460 (p11)  br.cond.sptk TAN_NORMAL_R ;;
1463 { .mii
1464         nop.m 999
1466 //     Case 2_reduce:
1467 //     c = c - U_2
1468 //     c is complete here
1469 //     Argument reduction ends here.
1471 (p9)   extr.u i_1 = N_fix_gr, 0, 1 ;;
1472 (p9)   cmp.eq.unc p11, p12 = 0x0000,i_1 ;;
1475 { .mfi
1476         nop.m 999
1478 //     Is i_1  even or odd?
1479 //     if i_1 == 0, set p11, else set p12.
1481 (p11)  fmpy.s1 rsq = r, Z
1482         nop.i 999 ;;
1485 { .mfi
1486         nop.m 999
1487 (p12)  frcpa.s1 S_hi,p0 = f1, r
1488         nop.i 999
1492 //     Case 1: Branch to SMALL_R or NORMAL_R.
1493 //     Case 1 is done now.
1496 { .mfi
1497 (p9)  addl           table_ptr1   = @ltoff(TAN_BASE_CONSTANTS), gp
1498 (p9)   fsub.s1 c = s_val, U_1
1499         nop.i 999 ;;
1503 { .mmi
1504 (p9)  ld8 table_ptr1 = [table_ptr1]
1505       nop.m 999
1506       nop.i 999
1510 { .mmi
1511 (p9)   add table_ptr1 = 224, table_ptr1 ;;
1512 (p9)   ldfe P1_1 = [table_ptr1],144
1513         nop.i 999 ;;
1516 //     Get [i_1] -  lsb of N_fix_gr .
1517 //     Load P1_1 and point to Q1_1 .
1520 { .mfi
1521 (p9)   ldfe Q1_1 = [table_ptr1] , 0
1523 //     N even: rsq = r * Z
1524 //     N odd:  S_hi = frcpa(r)
1526 (p12)  fmerge.ns S_hi = S_hi, S_hi
1527         nop.i 999
1530 { .mfi
1531         nop.m 999
1533 //     Case 2_reduce:
1534 //     c = s - U_1
1536 (p9)   fsub.s1 c = c, U_2
1537         nop.i 999 ;;
1540 { .mfi
1541         nop.m 999
1542 (p12)  fma.s1  poly1 = S_hi, r, f1
1543         nop.i 999 ;;
1546 { .mfi
1547         nop.m 999
1549 //     N odd:  Change sign of S_hi
1551 (p11)  fmpy.s1 rsq = rsq, P1_1
1552         nop.i 999 ;;
1555 { .mfi
1556         nop.m 999
1557 (p12)  fma.s1 S_hi = S_hi, poly1, S_hi
1558         nop.i 999 ;;
1561 { .mfi
1562         nop.m 999
1564 //     N even: rsq = rsq * P1_1
1565 //     N odd:  poly1 =  1.0 +  S_hi * r    16 bits partial  account for necessary
1567 (p11)  fma.s1 Result = r, rsq, c
1568         nop.i 999 ;;
1571 { .mfi
1572         nop.m 999
1574 //     N even: Result = c  + r * rsq
1575 //     N odd:  S_hi  = S_hi + S_hi*poly1  16 bits account for necessary
1577 (p12)  fma.s1 poly1 = S_hi, r, f1
1578         nop.i 999 ;;
1581 { .mfi
1582         nop.m 999
1584 //     N even: Result = Result + r
1585 //     N odd:  poly1  = 1.0 + S_hi * r        32 bits partial
1587 (p11)  fadd.s0 Result = r, Result
1588         nop.i 999 ;;
1591 { .mfi
1592         nop.m 999
1593 (p12)  fma.s1  S_hi = S_hi, poly1, S_hi
1594         nop.i 999 ;;
1597 { .mfi
1598         nop.m 999
1600 //     N even: Result1 = Result + r
1601 //     N odd:   S_hi  = S_hi * poly1 + S_hi   32 bits
1603 (p12)  fma.s1 poly1 = S_hi, r, f1
1604         nop.i 999 ;;
1607 { .mfi
1608         nop.m 999
1610 //     N odd:  poly1  =  S_hi * r + 1.0       64 bits partial
1612 (p12)  fma.s1 S_hi = S_hi, poly1, S_hi
1613         nop.i 999 ;;
1616 { .mfi
1617         nop.m 999
1619 //     N odd:  poly1  =  S_hi * poly + 1.0    64 bits
1621 (p12)  fma.s1 poly1 = S_hi, r, f1
1622         nop.i 999 ;;
1625 { .mfi
1626         nop.m 999
1628 //     N odd:  poly1  =  S_hi * r + 1.0
1630 (p12)  fma.s1 poly1 = S_hi, c, poly1
1631         nop.i 999 ;;
1634 { .mfi
1635         nop.m 999
1637 //     N odd:  poly1  =  S_hi * c + poly1
1639 (p12)  fmpy.s1 S_lo = S_hi, poly1
1640         nop.i 999 ;;
1643 { .mfi
1644         nop.m 999
1646 //     N odd:  S_lo  =  S_hi *  poly1
1648 (p12)  fma.s1 S_lo = Q1_1, r, S_lo
1649         nop.i 999
1652 { .mfi
1653         nop.m 999
1655 //     N odd:  Result =  S_hi + S_lo
1657 (p0)   fmpy.s0 fp_tmp = fp_tmp, fp_tmp  // Dummy mult to set inexact
1658         nop.i 999 ;;
1661 { .mfb
1662         nop.m 999
1664 //     N odd:  S_lo  =  S_lo + Q1_1 * r
1666 (p12)  fadd.s0 Result = S_hi, S_lo
1667 (p0)   br.ret.sptk b0 ;;
1671 TAN_LARGER_ARG: 
1673 { .mmf
1674 (p0)  addl           table_ptr1   = @ltoff(TAN_BASE_CONSTANTS), gp
1675       nop.m 999
1676 (p0)  fmpy.s1 N_0 = Arg, Inv_P_0 
1681 // ARGUMENT REDUCTION CODE - CASE 3 and 4
1684 //    Adjust table_ptr1 to beginning of table.
1685 //    N_0 = Arg * Inv_P_0
1689 { .mmi
1690 (p0)  ld8 table_ptr1 = [table_ptr1]
1691       nop.m 999
1692       nop.i 999
1697 { .mmi
1698 (p0)  add table_ptr1 = 8, table_ptr1 ;;
1700 //    Point to  2*-14
1702 (p0)  ldfs TWO_TO_NEG14 = [table_ptr1], 4
1703         nop.i 999 ;;
1706 //    Load 2**(-14).
1709 { .mmi
1710 (p0)  ldfs NEGTWO_TO_NEG14 = [table_ptr1], 180 ;;
1712 //    N_0_fix  = integer part of N_0 .
1713 //    Adjust table_ptr1 to beginning of table.
1715 (p0)  ldfs TWO_TO_NEG2 = [table_ptr1], 4
1716         nop.i 999 ;;
1719 //    Make N_0 the integer part.
1722 { .mfi
1723 (p0)  ldfs NEGTWO_TO_NEG2 = [table_ptr1]
1725 //    Load -2**(-14).
1727 (p0)  fcvt.fx.s1 N_0_fix = N_0
1728         nop.i 999 ;;
1731 { .mfi
1732         nop.m 999
1733 (p0)  fcvt.xf N_0 = N_0_fix
1734         nop.i 999 ;;
1737 { .mfi
1738         nop.m 999
1739 (p0)  fnma.s1 ArgPrime = N_0, P_0, Arg
1740         nop.i 999
1743 { .mfi
1744         nop.m 999
1745 (p0)  fmpy.s1 w = N_0, d_1
1746         nop.i 999 ;;
1749 { .mfi
1750         nop.m 999
1752 //    ArgPrime = -N_0 * P_0 + Arg
1753 //    w  = N_0 * d_1
1755 (p0)  fmpy.s1 N = ArgPrime, two_by_PI
1756         nop.i 999 ;;
1759 { .mfi
1760         nop.m 999
1762 //    N = ArgPrime * 2/pi
1764 (p0)  fcvt.fx.s1 N_fix = N
1765         nop.i 999 ;;
1768 { .mfi
1769         nop.m 999
1771 //    N_fix is the integer part.
1773 (p0)  fcvt.xf N = N_fix
1774         nop.i 999 ;;
1777 { .mfi
1778 (p0)  getf.sig N_fix_gr = N_fix
1779         nop.f 999
1780         nop.i 999 ;;
1783 { .mfi
1784         nop.m 999
1786 //    N is the integer part of the reduced-reduced argument.
1787 //    Put the integer in a GP register.
1789 (p0)  fnma.s1 s_val = N, P_1, ArgPrime
1790         nop.i 999
1793 { .mfi
1794         nop.m 999
1795 (p0)  fnma.s1 w = N, P_2, w
1796         nop.i 999 ;;
1799 { .mfi
1800         nop.m 999
1802 //    s_val = -N*P_1 + ArgPrime
1803 //    w = -N*P_2 + w
1805 (p0)  fcmp.lt.unc.s1 p11, p10 = s_val, TWO_TO_NEG14
1806         nop.i 999 ;;
1809 { .mfi
1810         nop.m 999
1811 (p11) fcmp.gt.s1 p11, p10 = s_val, NEGTWO_TO_NEG14
1812         nop.i 999 ;;
1815 { .mfi
1816         nop.m 999
1818 //    Case 3: r = s_val + w (Z complete)
1819 //    Case 4: U_hi = N_0 * d_1
1821 (p10) fmpy.s1 V_hi = N, P_2
1822         nop.i 999
1825 { .mfi
1826         nop.m 999
1827 (p11) fmpy.s1 U_hi = N_0, d_1
1828         nop.i 999 ;;
1831 { .mfi
1832         nop.m 999
1834 //    Case 3: r = s_val + w (Z complete)
1835 //    Case 4: U_hi = N_0 * d_1
1837 (p11) fmpy.s1 V_hi = N, P_2
1838         nop.i 999
1841 { .mfi
1842         nop.m 999
1843 (p11) fmpy.s1 U_hi = N_0, d_1
1844         nop.i 999 ;;
1847 { .mfi
1848         nop.m 999
1850 //    Decide between case 3 and 4:
1851 //    Case 3:  s <= -2**(-14) or s >= 2**(-14)
1852 //    Case 4: -2**(-14) < s < 2**(-14)
1854 (p10) fadd.s1 r = s_val, w
1855         nop.i 999
1858 { .mfi
1859         nop.m 999
1860 (p11) fmpy.s1 w = N, P_3
1861         nop.i 999 ;;
1864 { .mfi
1865         nop.m 999
1867 //    Case 4: We need abs of both U_hi and V_hi - dont
1868 //    worry about switched sign of V_hi .
1870 (p11) fsub.s1 A = U_hi, V_hi
1871         nop.i 999
1874 { .mfi
1875         nop.m 999
1877 //    Case 4: A =  U_hi + V_hi
1878 //    Note: Worry about switched sign of V_hi, so subtract instead of add.
1880 (p11) fnma.s1 V_lo = N, P_2, V_hi
1881         nop.i 999 ;;
1884 { .mfi
1885         nop.m 999
1886 (p11) fms.s1 U_lo = N_0, d_1, U_hi
1887         nop.i 999 ;;
1890 { .mfi
1891         nop.m 999
1892 (p11) fabs V_hiabs = V_hi
1893         nop.i 999
1896 { .mfi
1897         nop.m 999
1899 //    Case 4: V_hi = N * P_2
1900 //            w = N * P_3
1901 //    Note the product does not include the (-) as in the writeup
1902 //    so (-) missing for V_hi and w .
1903 (p10) fadd.s1 r = s_val, w
1904         nop.i 999 ;;
1907 { .mfi
1908         nop.m 999
1910 //    Case 3: c = s_val - r
1911 //    Case 4: U_lo = N_0 * d_1 - U_hi
1913 (p11) fabs U_hiabs = U_hi
1914         nop.i 999
1917 { .mfi
1918         nop.m 999
1919 (p11) fmpy.s1 w = N, P_3
1920         nop.i 999 ;;
1923 { .mfi
1924         nop.m 999
1926 //    Case 4: Set P_12 if U_hiabs >= V_hiabs
1928 (p11) fadd.s1 C_hi = s_val, A
1929         nop.i 999 ;;
1932 { .mfi
1933         nop.m 999
1935 //    Case 4: C_hi = s_val + A
1937 (p11) fadd.s1 t = U_lo, V_lo
1938         nop.i 999 ;;
1941 { .mfi
1942         nop.m 999
1944 //    Case 3: Is |r| < 2**(-2), if so set PR_7
1945 //    else set PR_8.
1946 //    Case 3: If PR_7 is set, prepare to branch to Small_R.
1947 //    Case 3: If PR_8 is set, prepare to branch to Normal_R.
1949 (p10) fsub.s1 c = s_val, r
1950         nop.i 999 ;;
1953 { .mfi
1954         nop.m 999
1956 //    Case 3: c = (s - r) + w (c complete)
1958 (p11) fcmp.ge.unc.s1 p12, p13 = U_hiabs, V_hiabs
1959         nop.i 999
1962 { .mfi
1963         nop.m 999
1964 (p11) fms.s1 w = N_0, d_2, w
1965         nop.i 999 ;;
1968 { .mfi
1969         nop.m 999
1971 //    Case 4: V_hi = N * P_2
1972 //            w = N * P_3
1973 //    Note the product does not include the (-) as in the writeup
1974 //    so (-) missing for V_hi and w .
1976 (p10) fcmp.lt.unc.s1 p14, p15 = r, TWO_TO_NEG2
1977         nop.i 999 ;;
1980 { .mfi
1981         nop.m 999
1982 (p14) fcmp.gt.s1 p14, p15 = r, NEGTWO_TO_NEG2
1983         nop.i 999 ;;
1986 { .mfb
1987         nop.m 999
1989 //    Case 4: V_lo = -N * P_2 - V_hi (U_hi is in place of V_hi in writeup)
1990 //    Note: the (-) is still missing for V_hi .
1991 //    Case 4: w = w + N_0 * d_2
1992 //    Note: the (-) is now incorporated in w .
1994 (p10) fadd.s1 c = c, w
1996 //    Case 4: t = U_lo + V_lo
1997 //    Note: remember V_lo should be (-), subtract instead of add. NO
1999 (p14) br.cond.spnt TAN_SMALL_R ;;
2002 { .mib
2003         nop.m 999
2004         nop.i 999
2005 (p15) br.cond.spnt TAN_NORMAL_R ;;
2008 { .mfi
2009         nop.m 999
2011 //    Case 3: Vector off when |r| < 2**(-2).  Recall that PR_3 will be true.
2012 //    The remaining stuff is for Case 4.
2014 (p12) fsub.s1 a = U_hi, A
2015 (p11) extr.u i_1 = N_fix_gr, 0, 1 ;;
2018 { .mfi
2019         nop.m 999
2021 //    Case 4: C_lo = s_val - C_hi
2023 (p11) fadd.s1 t = t, w
2024         nop.i 999
2027 { .mfi
2028         nop.m 999
2029 (p13) fadd.s1 a = V_hi, A
2030         nop.i 999 ;;
2034 //    Case 4: a = U_hi - A
2035 //            a = V_hi - A (do an add to account for missing (-) on V_hi
2038 { .mfi
2039 (p11)  addl           table_ptr1   = @ltoff(TAN_BASE_CONSTANTS), gp
2040 (p11) fsub.s1 C_lo = s_val, C_hi
2041         nop.i 999
2045 { .mmi
2046 (p11) ld8 table_ptr1 = [table_ptr1]
2047       nop.m 999
2048       nop.i 999
2053 //    Case 4: a = (U_hi - A)  + V_hi
2054 //            a = (V_hi - A)  + U_hi
2055 //    In each case account for negative missing form V_hi .
2058 //    Case 4: C_lo = (s_val - C_hi) + A
2061 { .mmi
2062 (p11) add table_ptr1 = 224, table_ptr1 ;;
2063 (p11) ldfe P1_1 = [table_ptr1], 16
2064         nop.i 999 ;;
2067 { .mfi
2068 (p11) ldfe P1_2 = [table_ptr1], 128
2070 //    Case 4: w = U_lo + V_lo  + w
2072 (p12) fsub.s1 a = a, V_hi
2073         nop.i 999 ;;
2076 //    Case 4: r = C_hi + C_lo
2079 { .mfi
2080 (p11) ldfe Q1_1 = [table_ptr1], 16
2081 (p11) fadd.s1 C_lo = C_lo, A
2082         nop.i 999 ;;
2085 //    Case 4: c = C_hi - r
2086 //    Get [i_1] - lsb of N_fix_gr.
2089 { .mfi
2090 (p11) ldfe Q1_2 = [table_ptr1], 16
2091         nop.f 999
2092         nop.i 999 ;;
2095 { .mfi
2096         nop.m 999
2097 (p13) fsub.s1 a = U_hi, a
2098         nop.i 999 ;;
2101 { .mfi
2102         nop.m 999
2103 (p11) fadd.s1 t = t, a
2104         nop.i 999 ;;
2107 { .mfi
2108         nop.m 999
2110 //    Case 4: t = t + a
2112 (p11) fadd.s1 C_lo = C_lo, t
2113         nop.i 999 ;;
2116 { .mfi
2117         nop.m 999
2119 //    Case 4: C_lo = C_lo + t
2121 (p11) fadd.s1 r = C_hi, C_lo
2122         nop.i 999 ;;
2125 { .mfi
2126         nop.m 999
2127 (p11) fsub.s1 c = C_hi, r
2128         nop.i 999
2131 { .mfi
2132         nop.m 999
2134 //    Case 4: c = c + C_lo  finished.
2135 //    Is i_1  even or odd?
2136 //    if i_1 == 0, set PR_4, else set PR_5.
2138 // r and c have been computed.
2139 // We known whether this is the sine or cosine routine.
2140 // Make sure ftz mode is set - should be automatic when using wre
2141 (p0)  fmpy.s1 rsq = r, r
2142         nop.i 999 ;;
2145 { .mfi
2146         nop.m 999
2147 (p11) fadd.s1 c = c , C_lo
2148 (p11) cmp.eq.unc p11, p12 =  0x0000, i_1 ;;
2151 { .mfi
2152         nop.m 999
2153 (p12) frcpa.s1 S_hi, p0 = f1, r
2154         nop.i 999
2157 { .mfi
2158         nop.m 999
2160 //    N odd: Change sign of S_hi
2162 (p11) fma.s1 Result = rsq, P1_2, P1_1
2163         nop.i 999 ;;
2166 { .mfi
2167         nop.m 999
2168 (p12) fma.s1 P = rsq, Q1_2, Q1_1
2169         nop.i 999
2172 { .mfi
2173         nop.m 999
2175 //    N odd:  Result  =  S_hi + S_lo      (User supplied rounding mode for C1)
2177 (p0)   fmpy.s0 fp_tmp = fp_tmp, fp_tmp  // Dummy mult to set inexact
2178         nop.i 999 ;;
2181 { .mfi
2182         nop.m 999
2184 //    N even: rsq = r * r
2185 //    N odd:  S_hi = frcpa(r)
2187 (p12) fmerge.ns S_hi = S_hi, S_hi
2188         nop.i 999
2191 { .mfi
2192         nop.m 999
2194 //    N even: rsq = rsq * P1_2 + P1_1
2195 //    N odd:  poly1 =  1.0 +  S_hi * r    16 bits partial  account for necessary
2197 (p11) fmpy.s1 Result = rsq, Result
2198         nop.i 999 ;;
2201 { .mfi
2202         nop.m 999
2203 (p12) fma.s1 poly1 = S_hi, r,f1
2204         nop.i 999
2207 { .mfi
2208         nop.m 999
2210 //    N even: Result =  Result * rsq
2211 //    N odd:  S_hi  = S_hi + S_hi*poly1  16 bits account for necessary
2213 (p11) fma.s1 Result = r, Result, c
2214         nop.i 999 ;;
2217 { .mfi
2218         nop.m 999
2219 (p12) fma.s1 S_hi = S_hi, poly1, S_hi
2220         nop.i 999
2223 { .mfi
2224         nop.m 999
2226 //    N odd:   S_hi  = S_hi * poly1 + S_hi   32 bits
2228 (p11) fadd.s0 Result= r, Result
2229         nop.i 999 ;;
2232 { .mfi
2233         nop.m 999
2234 (p12) fma.s1 poly1 =  S_hi, r, f1
2235         nop.i 999 ;;
2238 { .mfi
2239         nop.m 999
2241 //    N even: Result = Result * r + c
2242 //    N odd:  poly1  = 1.0 + S_hi * r        32 bits partial
2244 (p12) fma.s1 S_hi = S_hi, poly1, S_hi
2245         nop.i 999 ;;
2248 { .mfi
2249         nop.m 999
2250 (p12) fma.s1 poly1 = S_hi, r, f1
2251         nop.i 999 ;;
2254 { .mfi
2255         nop.m 999
2257 //    N even: Result1 = Result + r  (Rounding mode S0)
2258 //    N odd:  poly1  =  S_hi * r + 1.0       64 bits partial
2260 (p12) fma.s1 S_hi = S_hi, poly1, S_hi
2261         nop.i 999 ;;
2264 { .mfi
2265         nop.m 999
2267 //    N odd:  poly1  =  S_hi * poly + S_hi    64 bits
2269 (p12) fma.s1 poly1 = S_hi, r, f1
2270         nop.i 999 ;;
2273 { .mfi
2274         nop.m 999
2276 //    N odd:  poly1  =  S_hi * r + 1.0
2278 (p12) fma.s1 poly1 = S_hi, c, poly1
2279         nop.i 999 ;;
2282 { .mfi
2283         nop.m 999
2285 //    N odd:  poly1  =  S_hi * c + poly1
2287 (p12) fmpy.s1 S_lo = S_hi, poly1
2288         nop.i 999 ;;
2291 { .mfi
2292         nop.m 999
2294 //    N odd:  S_lo  =  S_hi *  poly1
2296 (p12) fma.s1 S_lo = P, r, S_lo
2297         nop.i 999 ;;
2300 { .mfb
2301         nop.m 999
2303 //    N odd:  S_lo  =  S_lo + r * P
2305 (p12) fadd.s0 Result = S_hi, S_lo
2306 (p0)   br.ret.sptk b0 ;;
2310 TAN_SMALL_R: 
2312 { .mii
2313         nop.m 999
2314 (p0)  extr.u i_1 = N_fix_gr, 0, 1 ;;
2315 (p0)  cmp.eq.unc p11, p12 = 0x0000, i_1
2318 { .mfi
2319         nop.m 999
2320 (p0)  fmpy.s1 rsq = r, r
2321         nop.i 999 ;;
2324 { .mfi
2325         nop.m 999
2326 (p12) frcpa.s1 S_hi, p0 = f1, r
2327         nop.i 999
2330 { .mfi
2331 (p0)  addl           table_ptr1   = @ltoff(TAN_BASE_CONSTANTS), gp
2332         nop.f 999
2333         nop.i 999
2337 { .mmi
2338 (p0)  ld8 table_ptr1 = [table_ptr1]
2339       nop.m 999
2340       nop.i 999
2344 // *****************************************************************
2345 // *****************************************************************
2346 // *****************************************************************
2348 { .mmi
2349 (p0)  add table_ptr1 = 224, table_ptr1 ;;
2350 (p0)  ldfe P1_1 = [table_ptr1], 16
2351         nop.i 999 ;;
2353 //    r and c have been computed.
2354 //    We known whether this is the sine or cosine routine.
2355 //    Make sure ftz mode is set - should be automatic when using wre
2356 //    |r| < 2**(-2)
2358 { .mfi
2359 (p0)  ldfe P1_2 = [table_ptr1], 16
2360 (p11) fmpy.s1 r_to_the_8 = rsq, rsq
2361         nop.i 999 ;;
2364 //    Set table_ptr1 to beginning of constant table.
2365 //    Get [i_1] - lsb of N_fix_gr.
2368 { .mfi
2369 (p0)  ldfe P1_3 = [table_ptr1], 96
2371 //    N even: rsq = r * r
2372 //    N odd:  S_hi = frcpa(r)
2374 (p12) fmerge.ns S_hi = S_hi, S_hi
2375         nop.i 999 ;;
2378 //    Is i_1  even or odd?
2379 //    if i_1 == 0, set PR_11.
2380 //    if i_1 != 0, set PR_12.
2383 { .mfi
2384 (p11) ldfe P1_9 = [table_ptr1], -16
2386 //    N even: Poly2 = P1_7 + Poly2 * rsq
2387 //    N odd:  poly2 = Q1_5 + poly2 * rsq
2389 (p11) fadd.s1 CORR = rsq, f1
2390         nop.i 999 ;;
2393 { .mmi
2394 (p11) ldfe P1_8 = [table_ptr1], -16 ;;
2396 //    N even: Poly1 = P1_2 + P1_3 * rsq
2397 //    N odd:  poly1 =  1.0 +  S_hi * r     
2398 //    16 bits partial  account for necessary (-1)
2400 (p11) ldfe P1_7 = [table_ptr1], -16
2401         nop.i 999 ;;
2404 //    N even: Poly1 = P1_1 + Poly1 * rsq
2405 //    N odd:  S_hi  =  S_hi + S_hi * poly1)     16 bits account for necessary
2408 { .mfi
2409 (p11) ldfe P1_6 = [table_ptr1], -16
2411 //    N even: Poly2 = P1_5 + Poly2 * rsq
2412 //    N odd:  poly2 = Q1_3 + poly2 * rsq
2414 (p11) fmpy.s1 r_to_the_8 = r_to_the_8, r_to_the_8
2415         nop.i 999 ;;
2418 //    N even: Poly1 =  Poly1 * rsq
2419 //    N odd:  poly1  = 1.0 + S_hi * r         32 bits partial
2422 { .mfi
2423 (p11) ldfe P1_5 = [table_ptr1], -16
2424 (p12) fma.s1 poly1 =  S_hi, r, f1
2425         nop.i 999 ;;
2428 //    N even: CORR =  CORR * c
2429 //    N odd:  S_hi  =  S_hi * poly1 + S_hi    32 bits
2433 //    N even: Poly2 = P1_6 + Poly2 * rsq
2434 //    N odd:  poly2 = Q1_4 + poly2 * rsq
2436 { .mmf
2437 (p0)  addl           table_ptr2   = @ltoff(TAN_BASE_CONSTANTS), gp
2438 (p11) ldfe P1_4 = [table_ptr1], -16
2439 (p11) fmpy.s1 CORR =  CORR, c
2444 { .mmi
2445 (p0)  ld8 table_ptr2 = [table_ptr2]
2446       nop.m 999
2447       nop.i 999
2452 { .mii
2453 (p0)  add table_ptr2 = 464, table_ptr2
2454         nop.i 999 ;;
2455         nop.i 999
2458 { .mfi
2459         nop.m 999
2460 (p11) fma.s1 Poly1 = P1_3, rsq, P1_2
2461         nop.i 999 ;;
2464 { .mfi
2465 (p0)  ldfe Q1_7 = [table_ptr2], -16
2466 (p12) fma.s1 S_hi = S_hi, poly1, S_hi
2467         nop.i 999 ;;
2470 { .mfi
2471 (p0)  ldfe Q1_6 = [table_ptr2], -16
2472 (p11) fma.s1 Poly2 = P1_9, rsq, P1_8
2473         nop.i 999 ;;
2476 { .mmi
2477 (p0)  ldfe Q1_5 = [table_ptr2], -16 ;;
2478 (p12) ldfe Q1_4 = [table_ptr2], -16
2479         nop.i 999 ;;
2482 { .mfi
2483 (p12) ldfe Q1_3 = [table_ptr2], -16
2485 //    N even: Poly2 = P1_8 + P1_9 * rsq
2486 //    N odd:  poly2 = Q1_6 + Q1_7 * rsq
2488 (p11) fma.s1 Poly1 = Poly1, rsq, P1_1
2489         nop.i 999 ;;
2492 { .mfi
2493 (p12) ldfe Q1_2 = [table_ptr2], -16
2494 (p12) fma.s1 poly1 = S_hi, r, f1
2495         nop.i 999 ;;
2498 { .mfi
2499 (p12) ldfe Q1_1 = [table_ptr2], -16
2500 (p11) fma.s1 Poly2 = Poly2, rsq, P1_7
2501         nop.i 999 ;;
2504 { .mfi
2505         nop.m 999
2507 //    N even: CORR =  rsq + 1
2508 //    N even: r_to_the_8 =  rsq * rsq
2510 (p11) fmpy.s1 Poly1 = Poly1, rsq
2511         nop.i 999 ;;
2514 { .mfi
2515         nop.m 999
2516 (p12) fma.s1 S_hi = S_hi, poly1, S_hi
2517         nop.i 999
2520 { .mfi
2521         nop.m 999
2522 (p12) fma.s1 poly2 = Q1_7, rsq, Q1_6
2523         nop.i 999 ;;
2526 { .mfi
2527         nop.m 999
2528 (p11) fma.s1 Poly2 = Poly2, rsq, P1_6
2529         nop.i 999 ;;
2532 { .mfi
2533         nop.m 999
2534 (p12) fma.s1 poly1 = S_hi, r, f1
2535         nop.i 999
2538 { .mfi
2539         nop.m 999
2540 (p12) fma.s1 poly2 = poly2, rsq, Q1_5
2541         nop.i 999 ;;
2544 { .mfi
2545         nop.m 999
2546 (p11) fma.s1 Poly2= Poly2, rsq, P1_5
2547         nop.i 999 ;;
2550 { .mfi
2551         nop.m 999
2552 (p12) fma.s1 S_hi =  S_hi, poly1, S_hi
2553         nop.i 999
2556 { .mfi
2557         nop.m 999
2558 (p12) fma.s1 poly2 = poly2, rsq, Q1_4
2559         nop.i 999 ;;
2562 { .mfi
2563         nop.m 999
2565 //    N even: r_to_the_8 = r_to_the_8 * r_to_the_8
2566 //    N odd:  poly1  =  S_hi * r + 1.0       64 bits partial
2568 (p11) fma.s1 Poly2 = Poly2, rsq, P1_4
2569         nop.i 999 ;;
2572 { .mfi
2573         nop.m 999
2575 //    N even: Result = CORR + Poly * r
2576 //    N odd:  P = Q1_1 + poly2 * rsq
2578 (p12) fma.s1 poly1 = S_hi, r, f1
2579         nop.i 999
2582 { .mfi
2583         nop.m 999
2584 (p12) fma.s1 poly2 = poly2, rsq, Q1_3
2585         nop.i 999 ;;
2588 { .mfi
2589         nop.m 999
2591 //    N even: Poly2 = P1_4 + Poly2 * rsq
2592 //    N odd:  poly2 = Q1_2 + poly2 * rsq
2594 (p11) fma.s1 Poly = Poly2, r_to_the_8, Poly1
2595         nop.i 999 ;;
2598 { .mfi
2599         nop.m 999
2600 (p12) fma.s1 poly1 = S_hi, c, poly1
2601         nop.i 999
2604 { .mfi
2605         nop.m 999
2606 (p12) fma.s1 poly2 = poly2, rsq, Q1_2
2607         nop.i 999 ;;
2610 { .mfi
2611         nop.m 999
2613 //    N even: Poly = Poly1 + Poly2 * r_to_the_8
2614 //    N odd:  S_hi =  S_hi * poly1 + S_hi    64 bits
2616 (p11) fma.s1 Result = Poly, r, CORR
2617         nop.i 999 ;;
2620 { .mfi
2621         nop.m 999
2623 //    N even: Result =  r + Result  (User supplied rounding mode)
2624 //    N odd:  poly1  =  S_hi * c + poly1
2626 (p12) fmpy.s1 S_lo = S_hi, poly1
2627         nop.i 999
2630 { .mfi
2631         nop.m 999
2632 (p12) fma.s1 P = poly2, rsq, Q1_1
2633         nop.i 999 ;;
2636 { .mfi
2637         nop.m 999
2639 //    N odd:  poly1  =  S_hi * r + 1.0
2641 (p11) fadd.s0 Result = Result, r
2642         nop.i 999 ;;
2645 { .mfi
2646         nop.m 999
2648 //    N odd:  S_lo  =  S_hi *  poly1
2650 (p12) fma.s1 S_lo = Q1_1, c, S_lo
2651         nop.i 999
2654 { .mfi
2655         nop.m 999
2657 //    N odd:  Result = Result + S_hi  (user supplied rounding mode)
2659 (p0)   fmpy.s0 fp_tmp = fp_tmp, fp_tmp  // Dummy mult to set inexact
2660         nop.i 999 ;;
2663 { .mfi
2664         nop.m 999
2666 //    N odd:  S_lo  =  Q1_1 * c + S_lo
2668 (p12) fma.s1 Result = P, r, S_lo
2669         nop.i 999 ;;
2672 { .mfb
2673         nop.m 999
2675 //    N odd:  Result =  S_lo + r * P
2677 (p12) fadd.s0 Result = Result, S_hi
2678 (p0)   br.ret.sptk b0 ;;
2682 TAN_NORMAL_R: 
2684 { .mfi
2685 (p0)  getf.sig sig_r = r
2686 // *******************************************************************
2687 // *******************************************************************
2688 // *******************************************************************
2690 //    r and c have been computed.
2691 //    Make sure ftz mode is set - should be automatic when using wre
2694 //    Get [i_1] -  lsb of N_fix_gr alone.
2696 (p0)  fmerge.s  Pos_r = f1, r
2697 (p0)  extr.u i_1 = N_fix_gr, 0, 1 ;;
2700 { .mfi
2701         nop.m 999
2702 (p0)  fmerge.s  sgn_r =  r, f1
2703 (p0)  cmp.eq.unc p11, p12 = 0x0000, i_1 ;;
2706 { .mfi
2707         nop.m 999
2708         nop.f 999
2709 (p0)  extr.u lookup = sig_r, 58, 5
2712 { .mlx
2713         nop.m 999
2714 (p0)  movl Create_B = 0x8200000000000000 ;;
2717 { .mfi
2718 (p0)  addl           table_ptr1   = @ltoff(TAN_BASE_CONSTANTS), gp
2719         nop.f 999
2720 (p0)  dep Create_B = lookup, Create_B, 58, 5
2725 //    Get [i_1] -  lsb of N_fix_gr alone.
2726 //    Pos_r = abs (r)
2730 { .mmi
2731       ld8 table_ptr1 = [table_ptr1]
2732       nop.m 999
2733       nop.i 999
2738 { .mmi
2739         nop.m 999
2740 (p0)  setf.sig B = Create_B
2742 //    Set table_ptr1 and table_ptr2 to base address of
2743 //    constant table.
2745 (p0)  add table_ptr1 = 480, table_ptr1 ;;
2748 { .mmb
2749         nop.m 999
2751 //    Is i_1 or i_0  == 0 ?
2752 //    Create the constant  1 00000 1000000000000000000000...
2754 (p0)  ldfe P2_1 = [table_ptr1], 16
2755         nop.b 999
2758 { .mmi
2759         nop.m 999 ;;
2760 (p0)  getf.exp exp_r = Pos_r
2761         nop.i 999
2764 //    Get r's exponent
2765 //    Get r's significand
2768 { .mmi
2769 (p0)  ldfe P2_2 = [table_ptr1], 16 ;;
2771 //    Get the 5 bits or r for the lookup.   1.xxxxx ....
2772 //    from sig_r.
2773 //    Grab  lsb of exp of B
2775 (p0)  ldfe P2_3 = [table_ptr1], 16
2776         nop.i 999 ;;
2779 { .mii
2780         nop.m 999
2781 (p0)  andcm table_offset = 0x0001, exp_r ;;
2782 (p0)  shl table_offset = table_offset, 9 ;;
2785 { .mii
2786         nop.m 999
2788 //    Deposit   0 00000 1000000000000000000000... on
2789 //              1 xxxxx yyyyyyyyyyyyyyyyyyyyyy...,
2790 //    getting rid of the ys.
2791 //    Is  B = 2** -2 or  B= 2** -1? If 2**-1, then
2792 //    we want an offset of 512 for table addressing.
2794 (p0)  shladd table_offset = lookup, 4, table_offset ;;
2796 //    B =  ........ 1xxxxx 1000000000000000000...
2798 (p0)  add table_ptr1 = table_ptr1, table_offset ;;
2801 { .mmb
2802         nop.m 999
2804 //   B =  ........ 1xxxxx 1000000000000000000...
2805 //   Convert B so it has the same exponent as Pos_r
2807 (p0)  ldfd T_hi = [table_ptr1], 8
2808         nop.b 999 ;;
2812 //    x = |r| - B
2813 //    Load T_hi.
2814 //    Load C_hi.
2817 { .mmf
2818 (p0)  addl           table_ptr2   = @ltoff(TAN_BASE_CONSTANTS), gp
2819 (p0)  ldfs T_lo = [table_ptr1]
2820 (p0)  fmerge.se B = Pos_r, B
2824 { .mmi
2825       ld8 table_ptr2 = [table_ptr2]
2826       nop.m 999
2827       nop.i 999
2831 { .mii
2832 (p0)  add table_ptr2 = 1360, table_ptr2
2833         nop.i 999 ;;
2834 (p0)  add table_ptr2 = table_ptr2, table_offset ;;
2837 { .mfi
2838 (p0)  ldfd C_hi = [table_ptr2], 8
2839 (p0)  fsub.s1 x = Pos_r, B
2840         nop.i 999 ;;
2843 { .mii
2844 (p0)  ldfs C_lo = [table_ptr2],255
2845         nop.i 999 ;;
2847 //    xsq = x * x
2848 //    N even: Tx = T_hi * x
2849 //    Load T_lo.
2850 //    Load C_lo - increment pointer to get SC_inv 
2851 //    - cant get all the way, do an add later.
2853 (p0)  add table_ptr2 = 569, table_ptr2 ;;
2856 //    N even: Tx1 = Tx + 1
2857 //    N odd:  Cx1 = 1 - Cx
2860 { .mfi
2861 (p0)  ldfe SC_inv = [table_ptr2], 0
2862         nop.f 999
2863         nop.i 999 ;;
2866 { .mfi
2867         nop.m 999
2868 (p0)  fmpy.s1 xsq = x, x
2869         nop.i 999
2872 { .mfi
2873         nop.m 999
2874 (p11) fmpy.s1 Tx = T_hi, x
2875         nop.i 999 ;;
2878 { .mfi
2879         nop.m 999
2880 (p12) fmpy.s1 Cx = C_hi, x
2881         nop.i 999 ;;
2884 { .mfi
2885         nop.m 999
2887 //    N odd: Cx = C_hi * x
2889 (p0)  fma.s1 P = P2_3, xsq, P2_2
2890         nop.i 999
2893 { .mfi
2894         nop.m 999
2896 //    N even and odd: P = P2_3 + P2_2 * xsq
2898 (p11) fadd.s1 Tx1 = Tx, f1
2899         nop.i 999 ;;
2902 { .mfi
2903         nop.m 999
2905 //    N even: D = C_hi - tanx
2906 //    N odd: D = T_hi + tanx
2908 (p11) fmpy.s1 CORR = SC_inv, T_hi
2909         nop.i 999
2912 { .mfi
2913         nop.m 999
2914 (p0)  fmpy.s1 Sx = SC_inv, x
2915         nop.i 999 ;;
2918 { .mfi
2919         nop.m 999
2920 (p12) fmpy.s1 CORR = SC_inv, C_hi
2921         nop.i 999 ;;
2924 { .mfi
2925         nop.m 999
2926 (p12) fsub.s1 V_hi = f1, Cx
2927         nop.i 999 ;;
2930 { .mfi
2931         nop.m 999
2932 (p0)  fma.s1 P = P, xsq, P2_1
2933         nop.i 999
2936 { .mfi
2937         nop.m 999
2939 //    N even and odd: P = P2_1 + P * xsq
2941 (p11) fma.s1 V_hi = Tx, Tx1, f1
2942         nop.i 999 ;;
2945 { .mfi
2946         nop.m 999
2948 //    N even: Result  = sgn_r * tail + T_hi (user rounding mode for C1)
2949 //    N odd:  Result  = sgn_r * tail + C_hi (user rounding mode for C1)
2951 (p0)   fmpy.s0 fp_tmp = fp_tmp, fp_tmp  // Dummy mult to set inexact
2952         nop.i 999 ;;
2955 { .mfi
2956         nop.m 999
2957 (p0)  fmpy.s1 CORR = CORR, c
2958         nop.i 999 ;;
2961 { .mfi
2962         nop.m 999
2963 (p12) fnma.s1 V_hi = Cx,V_hi,f1
2964         nop.i 999 ;;
2967 { .mfi
2968         nop.m 999
2970 //    N even: V_hi = Tx * Tx1 + 1
2971 //    N odd: Cx1 = 1 - Cx * Cx1
2973 (p0)  fmpy.s1 P = P, xsq
2974         nop.i 999
2977 { .mfi
2978         nop.m 999
2980 //    N even and odd: P = P * xsq
2982 (p11) fmpy.s1 V_hi = V_hi, T_hi
2983         nop.i 999 ;;
2986 { .mfi
2987         nop.m 999
2989 //    N even and odd: tail = P * tail + V_lo
2991 (p11) fmpy.s1 T_hi = sgn_r, T_hi
2992         nop.i 999 ;;
2995 { .mfi
2996         nop.m 999
2997 (p0)  fmpy.s1 CORR = CORR, sgn_r
2998         nop.i 999 ;;
3001 { .mfi
3002         nop.m 999
3003 (p12) fmpy.s1 V_hi = V_hi,C_hi
3004         nop.i 999 ;;
3007 { .mfi
3008         nop.m 999
3010 //    N even: V_hi = T_hi * V_hi
3011 //    N odd: V_hi  = C_hi * V_hi
3013 (p0)  fma.s1 tanx = P, x, x
3014         nop.i 999
3017 { .mfi
3018         nop.m 999
3019 (p12) fnmpy.s1 C_hi = sgn_r, C_hi
3020         nop.i 999 ;;
3023 { .mfi
3024         nop.m 999
3026 //    N even: V_lo = 1 - V_hi + C_hi
3027 //    N odd: V_lo = 1 - V_hi + T_hi
3029 (p11) fadd.s1 CORR = CORR, T_lo
3030         nop.i 999
3033 { .mfi
3034         nop.m 999
3035 (p12) fsub.s1 CORR = CORR, C_lo
3036         nop.i 999 ;;
3039 { .mfi
3040         nop.m 999
3042 //    N even and odd: tanx = x + x * P
3043 //    N even and odd: Sx = SC_inv * x
3045 (p11) fsub.s1 D = C_hi, tanx
3046         nop.i 999
3049 { .mfi
3050         nop.m 999
3051 (p12) fadd.s1 D = T_hi, tanx
3052         nop.i 999 ;;
3055 { .mfi
3056         nop.m 999
3058 //    N odd: CORR = SC_inv * C_hi
3059 //    N even: CORR = SC_inv * T_hi
3061 (p0)  fnma.s1 D = V_hi, D, f1
3062         nop.i 999 ;;
3065 { .mfi
3066         nop.m 999
3068 //    N even and odd: D = 1 - V_hi * D
3069 //    N even and odd: CORR = CORR * c
3071 (p0)  fma.s1 V_hi = V_hi, D, V_hi
3072         nop.i 999 ;;
3075 { .mfi
3076         nop.m 999
3078 //    N even and odd: V_hi = V_hi + V_hi * D
3079 //    N even and odd: CORR = sgn_r * CORR
3081 (p11) fnma.s1 V_lo = V_hi, C_hi, f1
3082         nop.i 999
3085 { .mfi
3086         nop.m 999
3087 (p12) fnma.s1 V_lo = V_hi, T_hi, f1
3088         nop.i 999 ;;
3091 { .mfi
3092         nop.m 999
3094 //    N even: CORR = COOR + T_lo
3095 //    N odd: CORR = CORR - C_lo
3097 (p11) fma.s1 V_lo = tanx, V_hi, V_lo
3098         nop.i 999
3101 { .mfi
3102         nop.m 999
3103 (p12) fnma.s1 V_lo = tanx, V_hi, V_lo
3104         nop.i 999 ;;
3107 { .mfi
3108         nop.m 999
3110 //    N even: V_lo = V_lo + V_hi * tanx
3111 //    N odd: V_lo = V_lo - V_hi * tanx
3113 (p11) fnma.s1 V_lo = C_lo, V_hi, V_lo
3114         nop.i 999
3117 { .mfi
3118         nop.m 999
3119 (p12) fnma.s1 V_lo = T_lo, V_hi, V_lo
3120         nop.i 999 ;;
3123 { .mfi
3124         nop.m 999
3126 //    N  even: V_lo = V_lo - V_hi * C_lo
3127 //    N  odd: V_lo = V_lo - V_hi * T_lo
3129 (p0)  fmpy.s1 V_lo = V_hi, V_lo
3130         nop.i 999 ;;
3133 { .mfi
3134         nop.m 999
3136 //    N even and odd: V_lo = V_lo * V_hi
3138 (p0)  fadd.s1 tail = V_hi, V_lo
3139         nop.i 999 ;;
3142 { .mfi
3143         nop.m 999
3145 //    N even and odd: tail = V_hi + V_lo
3147 (p0)  fma.s1 tail = tail, P, V_lo
3148         nop.i 999 ;;
3151 { .mfi
3152         nop.m 999
3154 //    N even: T_hi = sgn_r * T_hi
3155 //    N odd : C_hi = -sgn_r * C_hi
3157 (p0)  fma.s1 tail = tail, Sx, CORR
3158         nop.i 999 ;;
3161 { .mfi
3162         nop.m 999
3164 //    N even and odd: tail = Sx * tail + CORR
3166 (p0)  fma.s1 tail = V_hi, Sx, tail
3167         nop.i 999 ;;
3170 { .mfi
3171         nop.m 999
3173 //    N even an odd: tail = Sx * V_hi + tail
3175 (p11) fma.s0 Result = sgn_r, tail, T_hi
3176         nop.i 999
3179 { .mfb
3180         nop.m 999
3181 (p12) fma.s0 Result = sgn_r, tail, C_hi
3182 (p0)   br.ret.sptk b0 ;;
3185 .endp __libm_tan
3186 ASM_SIZE_DIRECTIVE(__libm_tan)
3190 // *******************************************************************
3191 // *******************************************************************
3192 // *******************************************************************
3194 //     Special Code to handle very large argument case.
3195 //     Call int pi_by_2_reduce(&x,&r)
3196 //     for |arguments| >= 2**63
3197 //     (Arg or x) is in f8
3198 //     Address to save r and c as double
3200 //                 (1)                    (2)                 (3) (call)         (4)
3201 //            sp -> +               psp -> +            psp -> +           sp ->  +
3202 //                  |                      |                   |                  |
3203 //                  |                r50 ->| <- r50      f0  ->|           r50 -> | -> c
3204 //                  |                      |                   |                  |
3205 //         sp-32 -> | <- r50          f0 ->|             f0  ->| <- r50    r49 -> | -> r
3206 //                  |                      |                   |                  |
3207 //                  |               r49  ->| <- r49     Arg  ->| <- r49           | -> x
3208 //                  |                      |                   |                  |
3209 //         sp -64 ->|             sp -64 ->|          sp -64 ->|                  |
3211 //            save pfs           save b0                                     restore gp
3212 //            save gp                                                        restore b0
3213 //                                                                           restore pfs
3217 .proc __libm_callout
3218 __libm_callout:
3219 TAN_ARG_TOO_LARGE: 
3220 .prologue
3221 // (1)
3222 { .mfi
3223         add   GR_Parameter_r =-32,sp                        // Parameter: r address
3224         nop.f 0
3225 .save   ar.pfs,GR_SAVE_PFS
3226         mov  GR_SAVE_PFS=ar.pfs                 // Save ar.pfs
3228 { .mfi
3229 .fframe 64
3230         add sp=-64,sp                           // Create new stack
3231         nop.f 0
3232         mov GR_SAVE_GP=gp                       // Save gp
3235 // (2)
3236 { .mmi
3237         stfe [GR_Parameter_r ] = f0,16                      // Clear Parameter r on stack
3238         add  GR_Parameter_X = 16,sp                        // Parameter x address
3239 .save   b0, GR_SAVE_B0
3240         mov GR_SAVE_B0=b0                       // Save b0
3243 // (3)
3244 .body
3245 { .mib
3246         stfe [GR_Parameter_r ] = f0,-16                     // Clear Parameter c on stack
3247         nop.i 0
3248         nop.b 0
3250 { .mib
3251         stfe [GR_Parameter_X] = Arg                        // Store Parameter x on stack
3252         nop.i 0
3253 (p0)    br.call.sptk b0=__libm_pi_by_2_reduce#
3258 // (4)
3259 { .mmi
3260         mov   gp = GR_SAVE_GP                  // Restore gp
3261 (p0)    mov   N_fix_gr = r8 
3262         nop.i 999
3266 { .mmi
3267 (p0)    ldfe  Arg        =[GR_Parameter_X],16
3268 (p0)    ldfs  TWO_TO_NEG2 = [table_ptr2],4
3269         nop.i 999
3274 { .mmb
3275 (p0)    ldfe  r =[GR_Parameter_r ],16
3276 (p0)    ldfs  NEGTWO_TO_NEG2 = [table_ptr2],4
3277         nop.b 999 ;;
3280 { .mfi
3281 (p0)    ldfe  c =[GR_Parameter_r ]
3282         nop.f 999
3283         nop.i 999 ;;
3286 { .mfi
3287         nop.m 999
3289 //     Is |r| < 2**(-2)
3291 (p0)   fcmp.lt.unc.s1  p6, p0 = r, TWO_TO_NEG2
3292         mov   b0 = GR_SAVE_B0                  // Restore return address
3296 { .mfi
3297        nop.m 999
3298 (p6)   fcmp.gt.unc.s1  p6, p0 = r, NEGTWO_TO_NEG2
3299        mov   ar.pfs = GR_SAVE_PFS             // Restore ar.pfs
3303 { .mbb
3304 .restore sp
3305         add   sp = 64,sp                       // Restore stack pointer
3306 (p6)   br.cond.spnt TAN_SMALL_R
3307 (p0)   br.cond.sptk TAN_NORMAL_R 
3310 .endp __libm_callout
3311 ASM_SIZE_DIRECTIVE(__libm_callout)
3314 .proc __libm_TAN_SPECIAL
3315 __libm_TAN_SPECIAL:
3318 //     Code for NaNs, Unsupporteds, Infs, or +/- zero ?
3319 //     Invalid raised for Infs and SNaNs.
3322 { .mfb
3323         nop.m 999
3324 (p0)   fmpy.s0 Arg = Arg, f0
3325 (p0)   br.ret.sptk b0 
3327 .endp __libm_TAN_SPECIAL
3328 ASM_SIZE_DIRECTIVE(__libm_TAN_SPECIAL)
3331 .type __libm_pi_by_2_reduce#,@function
3332 .global __libm_pi_by_2_reduce#