uss_fpfncs.s
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:33k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* Copyright 1991-1992 Wind River Systems, Inc. */
  2. .data
  3. .globl _copyright_wind_river
  4. .long _copyright_wind_river
  5. /*
  6. modification history
  7. --------------------
  8. 01f,23aug92,jcf  changed bxxx to jxx.
  9. 01e,05jun92,kdl  changed external branches to jumps (and bsr's to jsr's).
  10. 01d,26may92,rrr  the tree shuffle
  11. 01c,30mar92,kdl  added include of "uss_fp.h"; commented-out ".set" directives
  12.  (SPR #1398).
  13. 01b,04oct91,rrr  passed through the ansification filter
  14.   -changed ASMLANGUAGE to _ASMLANGUAGE
  15.   -changed copyright notice
  16. 01a,28jan91,kdl  original US Software version.
  17. */
  18. /*
  19. DESCRIPTION
  20. |       ttl     FPAC 68K/FPFNCS: IEEE Single Precision Functions
  21. |FPFNCS idnt    1,0             ; IEEE Single Precision Functions
  22. |                               ; FPFNCS.A68
  23. |
  24. |* * * * * * * * * *
  25. |
  26. |       68000 FPAC  --  Single Precision Functions
  27. |
  28. |       Copyright (C) 1984 - 1990 By
  29. |       United States Software Corporation
  30. |       14215 N.W. Science Park Drive
  31. |       Portland, Oregon 97229
  32. |
  33. |       This software is furnished under a license and may be used
  34. |       and copied only in accordance with the terms of such license
  35. |       and with the inclusion of the above copyright notice.
  36. |       This software or any other copies thereof may not be provided
  37. |       or otherwise made available to any other person.  No title to
  38. |       and ownership of the software is hereby transferred.
  39. |
  40. |       The information in this software is subject to change without
  41. |       notice and should not be construed as a commitment by United
  42. |       States Software Corporation.
  43. |
  44. |       Version:        See VSNLOG.TXT
  45. |       Released:       01 Jan 1984
  46. |
  47. |* * * * * * * * * *
  48. |
  49. |
  50. |  Single Precision Floating Point Function library.
  51. |
  52. |  These functions operate on single precision floating point values,
  53. |  yielding single precision floating point results.  All functions
  54. |  process the value on top of the stack and return a result on the
  55. |  stack.  The XTOI function expects its integer argument in D0.
  56. |
  57. |
  58. |  NAME       ARGUMENT                DESCRIPTION
  59. |  ========== =====================   =================================
  60. |  EXP        -87.43 < a < 88.72      e to the power specified.
  61. |                                     (if out of range, 0.0 or +INF)
  62. |
  63. |  LN         a > 0.0                 natural log of value specified.
  64. |                                     (invalid opn if neg or zero)
  65. |
  66. |  XTOI       all value pairs         number raised to integer power.
  67. |
  68. |  ATN        any numeric value       arc whose tanget is given value
  69. |                                     (no domain restriction, result in
  70. |                                     the range is -PI/2 to +PI/2)
  71. |
  72. |  SQRT       a >= 0.0                square root of the given value
  73. |                                     (invalid operation if negative)
  74. |
  75. |  COS                                All trigonometric functions
  76. |  SIN                                expect a radian mode argument
  77. |  TAN                                whose magnitude is < 65536 (2^16)
  78. |
  79. NOMANUAL
  80. */
  81. #define _ASMLANGUAGE
  82. #include "uss_fp.h"
  83. |       page
  84. |
  85. |       opt     BRS             ; Default to forward branches SHORT
  86. |
  87.         .globl  FPEXP
  88.         .globl  FPLN
  89.         .globl  FPLOG
  90.         .globl  FPXTOI
  91.         .globl  FPATN
  92.         .globl  FPSQRT
  93.         .globl  FPCOS
  94.         .globl  FPSIN
  95.         .globl  FPTAN
  96. |
  97. |       xref    FPMUL   ;Floating point operations
  98. |       xref    FPDIV
  99. |       xref    FPRDIV
  100. |       xref    FPADD
  101. |       xref    FLOAT
  102. |       xref    INT
  103. |
  104. |       xref    FNANRS
  105. |       xref    FINFRS
  106. |       xref    FUNFRS
  107. |       xref    FZERRS
  108. |
  109. |       xref    FPERR
  110. |
  111. |
  112. |       .set    FBIAS,127
  113. |
  114. |       .set    ERUNF,1 |FPERR UNDERFLOW ERROR CODE
  115. |       .set    EROVF,2 |FPERR OVERFLOW ERROR CODE
  116. |       .set    ERNAN,3 |FPERR INVALID OPERATION ERROR CODE
  117. /*
  118. |
  119. |
  120. |
  121. | ###   SUBTTL  FPEXP: Exponentiation of e Function
  122. |       page
  123. |
  124. |
  125. |  EXP:   Calculate e to the power specified by the stack argument.
  126. |         The result is returned on the stack.
  127. |
  128. |         FPERR is set upon overflow, underflow, or NaN argument.
  129. |
  130. |  Algorithm:
  131. |  The argument is multiplied by 1/LN 2.  The integer portion of the
  132. |  product becomes the two*s exponent.  A Taylor series approximation
  133. |  about zero is used to compute 2**FRAC(ARG * 1/LN 2).
  134. |
  135. */
  136.         .text
  137. |
  138. FEXPCN:
  139.         |dsw    0       | EXP CONSTANT LIST (2**X EVALUATION)
  140. |
  141. |         (LN 2)^ 9/ 9!   =   1.0178 08601E-07
  142.         .long   0x33DA929E
  143. |         (LN 2)^ 8/ 8!   =   1.3215 48679E-06
  144.         .long   0x35B16011
  145. |         (LN 2)^ 7/ 7!   =   1.5252 73380E-05
  146.         .long   0x377FE5FE
  147. |         (LN 2)^ 6/ 6!   =   1.5403 53039E-04
  148.         .long   0x39218489
  149. |         (LN 2)^ 5/ 5!   =   1.3333 55815E-03
  150.         .long   0x3AAEC3FF
  151. |         (LN 2)^ 4/ 4!   =   9.6181 29108E-03
  152.         .long   0x3C1D955B
  153. |         (LN 2)^ 3/ 3!   =   5.5504 10866E-02
  154.         .long   0x3D635847
  155. |         (LN 2)^ 2/ 2!   =   2.4022 65070E-01
  156.         .long   0x3E75FDF0
  157. |         (LN 2)^ 1/ 1!   =   6.9314 71806E-01
  158. FLN2:
  159.         .long   0x3F317218
  160. |                             1.0000 00000E+00
  161.         .long   0x3F800000
  162. |
  163. |       .set    FNEXPC,10               | Number of constants in FEXP poly
  164. |
  165. |         1 / LN 2  =  1.4426 95040 88896 34074 D+00
  166. FINLN2:
  167.         .long   0x3FB8AA3B
  168. |
  169. |
  170. |
  171. | ###   PUBLIC  FPEXP
  172. |
  173. FPEXP:
  174.         |dsw    0
  175.         bsr     FPFADJ          | Set-up for FP functions
  176. |
  177.         jvs     FFNANR          | NaN parm -> NaN result
  178.         jcc     FEXP01          | J/ arg not INF
  179. |
  180.         jmi     FFUNFR          | -INF parm -> underflow result
  181.         jra     FFPINR          | +INF parm -> positive INF result
  182. |
  183. FEXP01:
  184.         movel   FINLN2,sp@-     | 1/LN 2 on stack
  185.         jsr     FPMUL           | Convert to 2^ function
  186. |
  187.         movew   sp@,d1
  188.         rorw    #7,d1           | Exponent in d1.B
  189.         cmpib   #FBIAS+6,d1
  190.         jhi     FEXP10          | J/ overflow or underflow  >= +/- 2^7
  191.         jne     FEXP20          | J/ within range            < +/- 2^6
  192.         tstb    sp@
  193.         jpl     FEXP20          | J/ result >= 1.0
  194. |
  195.         cmpiw   #0xF800+0x0100+FBIAS+6,d1       | Check ms 7 man bits (+s+exp)
  196.         jcs     FEXP20                  | J/ result >= 2^-126
  197. |
  198. FEXP10:
  199.         tstb    sp@
  200.         jpl     FFPINR          | J/ FP function +INF result
  201.         jra     FFUNFR          | J/ FP function underflow result
  202. |
  203. FEXP20:
  204.         movel   sp@,sp@-        | Duplicate the argument on the stack
  205. |
  206.         jsr     INT
  207. |
  208.         movew   d0,a7@(4)       | Save result of INT
  209. |
  210.         negl    d0              | Negate integer
  211.         jsr     FLOAT
  212.         jsr     FPADD           | Special FFRAC
  213. |
  214.         pea     FEXPCN
  215.         movel   sp@+,a6 | Point a6 to constant list
  216.         moveq   #FNEXPC,d0      | d0 holds the number of constants
  217.         bsr     FXSER           | Polynomial series
  218. |
  219.         movew   a7@(4),d0       | Fetch power of two scaling
  220.         lslw    #7,d0
  221.         addw    d0,sp@          | Combine with FXSER result
  222. |
  223.         movel   sp@+,sp@        | Downshift result
  224.         jmp     a4@             | Return
  225. /*
  226. |
  227. | ###   SUBTTL  FPLOG, FPLN: Logarithm Functions
  228. |       page
  229. |
  230. |  LOGARITHM (BASE E) FUNCTION.
  231. |
  232. |  The natural logarithm of the single precision floating point
  233. |  value on the stack is computed using a split domain polynomial
  234. |  approximation.  The common log is computed by scaling the
  235. |  result of the natural log computation.
  236. |
  237. |  TWOS = FLOAT(ARG.EXPONENT) * LOG(2)
  238. |
  239. |  The argument, (after the two's power scaling, 2.0 > arg' >= 1.0),
  240. |  is sorted into one of five classes.  Within that class, a center
  241. |  point with a known log value is used in combination with a 7th
  242. |  degree Chebyshey polynomial approximation, to calculate a
  243. |  logarithm.
  244. |
  245. |  The center point of each class is adjusted so that its natural
  246. |  logarithm expressed in single precision form is accurate to
  247. |  more than 40 bits.
  248. |
  249. |  log(arg) = two's log + center point log + polynomial approximation
  250. |
  251. |  Polynomial approximation:
  252. |
  253. |  log((1-t)/(1+t)) = t*(c1*t^8 + c2*t^6 + c3*t^4 + c4*t^2 + c5)
  254. |         (accurate with 1.0E-17 for t within 0.1 of 1.0)
  255. |
  256. |  t = - (center - arg')/(center + arg')  [to calc log of arg'/center]
  257. |
  258. */
  259. FLNCNS:
  260.         |dsw    0               | LN constants list
  261. |
  262. |         c1  =   0.28571 20487
  263.         .long   0x3E9248DA
  264. |         c2  =   0.40000 00019
  265.         .long   0x3ECCCCCD
  266. |         c3  =   0.66666 66667
  267.         .long   0x3F2AAAAB
  268. |         c4  =   2.00000 00000
  269.         .long   0x40000000
  270. |
  271. |       .set    FNLNCN,4                | Number of constants in FLN poly
  272. |
  273. |
  274. FLNCEN:
  275.         |dsw    0               | Center Points
  276. |         Center  #1 = 1.0000 00000 00000 00000
  277.         .long   0x3F800000
  278. |         Center  #2 = 1.1892 07098     (close to 2^(1/4))
  279.         .long   0x3F9837F0
  280. |         Center  #3 = 1.4142 13521     (close to 2^(1/2))
  281.         .long   0x3FB504F3
  282. |         Center  #4 = 1.6817 92733     (close to 2^(3/4))
  283.         .long   0x3FD744FC
  284. |         Center  #5 = 2.0000 00000
  285. | ---     shifted to 1.0 center..
  286. |
  287. FLNLOG:
  288.         |dsw    0               | FLNCEN values adj for exact ln values
  289. |         LN(Center #2) = 0.17328 67807
  290.         .long   0x3E317217
  291. |         LN(Center #3) = 0.34657 35614
  292.         .long   0x3EB17217
  293. |         LN(Center #4) = 0.51986 03272
  294.         .long   0x3F051591
  295. |
  296. |
  297. |         1 / LN 10  =  0.43429 44819
  298. FILN10:
  299.         .long   0x3EDE5BD9
  300. |
  301. |
  302. |
  303. | ###   PUBLIC  FPLN
  304. | ###   PUBLIC  FPLOG
  305. |
  306. FPLOG:
  307.         |dsw    0
  308.         moveq   #-1,d0          | Signal common log scaling
  309.         jra     FLN000
  310. |
  311. FPLN:
  312.         |dsw    0
  313.         clrb    d0              | Signal no post calculation scaling
  314. |
  315. FLN000:
  316.         bsr     FPFADJ          | Adjust parameter on stack
  317. |
  318.         jvs     FFNANR          | J/ NaN arg -> NaN result
  319.         jmi     FFNANR          | J/ Neg arg -> NaN result
  320.         jeq     FFMINR          | J/ 0.0 arg -> -INF result
  321.         jcs     FFPINR          | J/ +INF arg -> +INF result
  322. |
  323.         moveb   d0,a7@(6)       | Save natural/common flag
  324. |
  325.         movew   sp@,d1          | Prepare to calc parm sign and exp
  326.         lsrw    #7,d1           | Position exponent (right justified)
  327.         subiw   #FBIAS,d1
  328.         movew   d1,a7@(4)       | /* Save two's exponent value */
  329. |
  330.         lslw    #7,d1           | Scale parameter
  331.         subw    d1,sp@
  332. |
  333.         clrw    d0              | Set class number to 0
  334.         movel   sp@,d1
  335.         lsrl    #8,d1           | d1.W = 0xEMMM
  336. |
  337.         cmpiw   #0x8000+2966,d1
  338.         jcs     FLN050          | J/ < 1 +  2966/32768  (1.090515)
  339.         addqw   #4,d0
  340.         cmpiw   #0x8000+9727,d1
  341.         jcs     FLN050          | J/ < 1 +  9727/32768  (1.296844)
  342.         addqw   #4,d0
  343.         cmpiw   #0x8000+17767,d1
  344.         jcs     FLN050          | J/ < 1 + 17767/32768  (1.542206)
  345.         addqw   #4,d0
  346.         cmpiw   #0x8000+27329,d1
  347.         jcs     FLN050          | J/ < 1 + 27329/32768  (1.834015)
  348.         addqw   #1,a7@(4)       | /* Class 4: Bump two's exp, then class 0 */
  349.         clrw    d0
  350.         subib   #0x80,a7@(1)    | Reduce scaled exponent
  351. |
  352. FLN050:
  353.         moveb   d0,a7@(7)       | Save center number
  354. |
  355.         pea     FLNCEN
  356.         movel   sp@+,a2
  357.         movel   a2@(0,d0:W),sp@- |Place center on stack
  358. |
  359.         movel   a7@(4),sp@-     | Copy scaled argument
  360. |
  361.         movel   a2@(0,d0:W),sp@- |Place center on stack
  362. |
  363.         jsr     FPADD           | /* Calc  (CENTER + PARM') */
  364. |
  365.         movel   sp@,d0          | Exch top stack item w/ 3rd
  366.         movel   a7@(8),d1
  367.         movel   d1,sp@
  368.         movel   d0,a7@(8)
  369. |
  370.         bset    #7,a7@(4)       | Negate CENTER
  371. |
  372.         jsr     FPADD           | /* Calc  - (CENTER - PARM') */
  373.         jsr     FPRDIV          | /* T = - (CENTER-PARM')/(CENTER+PARM) */
  374. |
  375.         movel   sp@,sp@-        | Duplicate t
  376. |
  377.         pea     FLNCNS
  378.         movel   sp@+,a6 | Poly approx
  379.         moveq   #FNLNCN,d0
  380.         bsr     FX2SER
  381. |
  382.         jsr     FPMUL           | Times t
  383.         clrw    d0
  384.         moveb   a7@(7),d0
  385.         jeq     FLN060          | J/ center = 0 -> no additive log val
  386. |
  387.         pea     FLNLOG-4
  388.         movel   sp@+,a6
  389.         movel   a6@(0,d0:W),sp@-
  390.         jsr     FPADD           | Add in center log value
  391. |
  392. FLN060:
  393.         movew   a7@(4),d0       | /* Get two's exponent value */
  394.         extl    d0
  395. | ##    DC.W    $48C0           ; (Assembled  EXT.L D0 instruction)
  396.         jsr     FLOAT
  397. |
  398.         movel   FLN2,sp@-       | Log of 2 on stack
  399.         jsr     FPMUL
  400.         jsr     FPADD
  401. |
  402.         tstb    a7@(6)
  403.         jeq     FLN070          | J/ natural log
  404. |
  405.         movel   FILN10,sp@-     | Scaling value
  406.         jsr     FPMUL
  407. |
  408. FLN070:
  409.         movel   sp@+,sp@
  410.         jmp     a4@
  411. /*
  412. | ###   SUBTTL  FPXTOI: Floating Point Number to Integer Power Function
  413. |       page
  414. |
  415. |  X to I power Function.
  416. |
  417. |  The single precision floating point value on the stack is
  418. |  raised to the power specified in D0.W then returned on stack.
  419. |
  420. |  A shift and multiply technique is used (possibly with a trailing
  421. |  recipication.
  422. |
  423. |
  424. | ###   PUBLIC  FPXTOI
  425. |
  426. */
  427. FPXTOI:
  428.         |dsw    0
  429.         bsr     FPFADJ
  430. |
  431.         jvs     FFNANR          | J/ NaN arg -> NaN result
  432.         jcc     FPXT10          | J/ arg is not INF
  433. |
  434.         tstw    d0
  435.         jeq     FFNANR          | J/ arg is +/- INF, I is 0 -> NaN
  436.         jmi     FFUNFR          | J/ x is +/- INF, I < 0 -> underflow
  437. |
  438.         rorb    #1,d0
  439.         andb    sp@,d0
  440.         jmi     FFMINR          | J/ arg is -INF, I is +odd -> -INF
  441.         jra     FFPINR          | else -> +INF
  442. |
  443. |
  444. FPXT10:
  445.         jne     FPXT15          | J/ parm is a number <> 0.0
  446. |
  447.         tstw    d0
  448.         jmi     FFPINR          | J/ 0.0 to -int -> +INF
  449.         jeq     FFNANR          | J/ 0.0 to 0 -> NaN
  450.         jra     FFZERR          | J/ 0.0 to +int -> 0.0
  451. |
  452. FPXT15:
  453.         tstw    d0
  454.         jeq     FFONER          | J/ num to 0 -> 1.0
  455. |
  456.         movew   d0,a7@(6)       | Save int as its own sign flag
  457.         jpl     FPXT20
  458.         negw    d0
  459. FPXT20:
  460.         |dsw    0
  461. |
  462.         movel   sp@,sp@-        | Result init to parm value
  463. |
  464.         moveq   #16,d1          | Find MS bit of power
  465. FPXT21:
  466.         lslw    #1,d0
  467.         jcs     FPXT22          | J/ MS bit moved into carry
  468.         dbra    d1,FPXT21       | Dec d1 and jump (will always jump)
  469. |
  470. FPXT22:
  471.         movew   d0,a7@(8)       | Power pattern on stack
  472.         moveb   d1,a7@(11)      | Bit slots left count on stack
  473. |
  474. |
  475. FPXT30:
  476.         subqb   #1,a7@(11)      | Decrement bit slots left
  477.         jeq     FPXT35          | J/ evaluation complete
  478. |
  479.         movel   sp@,sp@-        | Square result value
  480.         jsr     FPMUL           | Square it
  481. |
  482.         lslw    a7@(8)          | Shift power pattern
  483.         jcc     FPXT30          | J/ this product bit not set
  484. |
  485.         movel   a7@(4),sp@-     | Copy parm value
  486.         jsr     FPMUL
  487.         jra     FPXT30
  488. |
  489. FPXT35:
  490.         tstb    a7@(10)         | Check for recipocation
  491.         jpl     FPXT36          | J/ no recipocation
  492. |
  493.         movel   #0x3F800000,sp@- |Place 1.0 on stack
  494.         jsr     FPRDIV
  495. |
  496. FPXT36:
  497.         movel   sp@+,a7@(4)     | Shift result value
  498.         addql   #4,sp           | Delete excess stack area
  499.         jmp     a4@             | Return.
  500. /*
  501. |
  502. | ###   SUBTTL  FPSQRT: Square Root Function
  503. |       page
  504. |
  505. |  Square Root Function.
  506. |
  507. |  Take square root of the single precision floating point value
  508. |  on the top of the stack.
  509. |
  510. |  Use the Newton iteration technique to compute the square root.
  511. |
  512. |      X(n+1) = (X(n) + Z/X(n)) / 2
  513. |
  514. |  The two*s exponent is scaled to restrict the solution domain to 1.0
  515. |  through 4.0.  A linear approximation to the square root is used to
  516. |  produce a first guess with greater than 4 bits of accuracy.  Three
  517. |  successive iterations are performed in registers to obtain accuracy
  518. |  of about 30 bits.  The final iteration is performed in the floating
  519. |  point domain.
  520. |
  521. | ###   PUBLIC  FPSQRT
  522. |
  523. */
  524. FPSQRT:
  525.         |dsw    0
  526.         bsr     FPFADJ
  527. |
  528.         jvs     FFNANR          | J/ NaN arg -> NaN result
  529.         jmi     FFNANR          | J/ neg arg -> NaN result
  530.         jcs     FFPINR          | J/ +INF arg -> +INF result
  531.         jeq     FFZERR          | J/ 0.0 arg -> 0.0 result
  532. |
  533.         movew   sp@,d1          | Get S/E/M word
  534.         subiw   #128*FBIAS,d1   | Extract argument's two's exp
  535.         clrb    d1              | Make it a factor of two
  536.         subw    d1,sp@          | /* Scale arg. range to 4.0 > arg' >= 1.0 */
  537.         asrw    #8,d1           | Square root of scaled two power
  538.         moveb   d1,a7@(4)       | /* Save two's exp of result on stack */
  539. |
  540.         movel   sp@,d1          | Create fixed point integer for approx
  541.         lsll    #8,d1           | /* Produce arg' * 2^30 in d1 */
  542.         bset    #31,d1          | Set implicit bit
  543.         jeq     FPSQ10          | /* J/ arg' >= 2.0 */
  544. |
  545.         lsrl    #1,d1           | Adjust d1
  546. |
  547. FPSQ10:
  548.         movew   #42720-65536,d2 | d2 = 0.325926 * 2^17
  549.         swap    d1              | /* d1.W = arg' * 2^14 */
  550.         mulu    d1,d2           | /* d2 = arg' * 0.325926 * 2^31 */
  551.         swap    d2
  552.         addiw   #23616,d2       | + 0.7207 * 2^15 - to 4+ bits
  553.         subxw   d3,d3
  554.         orw     d3,d2           | Top out approximation at 1.99997
  555. |
  556.         swap    d1
  557.         lsrl    #1,d1           | /* Arg' * 2^29 in d1 (prevent overflow) */
  558. |
  559.         movel   d1,d3           | Copy into d3
  560.         divu    d2,d3           | /* Arg'/X0 * 2^14 in d3 */
  561.         lsrw    #1,d2
  562.         addw    d3,d2           | X1 in d2 - to 8 bits
  563. |
  564.         movel   d1,d3           | Second in-register iteration
  565.         divu    d2,d3
  566.         lsrw    #1,d2
  567.         addw    d3,d2           | X2 in d2 - to 16 bits
  568. |
  569.         movel   d1,d3
  570.         divu    d2,d3
  571.         movew   d3,d4
  572.         clrw    d3
  573.         swap    d4
  574.         divu    d2,d3
  575.         movew   d3,d4           | 32 bit division result
  576.         swap    d2
  577.         clrw    d2
  578.         lsrl    #1,d2
  579.         addl    d4,d2           | X3 in d2 - to 24+ bits
  580. |
  581.         moveq   #0x7F,d1
  582.         addl    d1,d2           | Round value in d2 to 24 bits
  583.         roll    #1,d2           | Strip implicit bit
  584. |       .set    XBIAS,127               | *** for assembler bug ***
  585.         moveb   #XBIAS,d2       | Place bias value
  586.         addb    a7@(4),d2       | Scale result
  587.         rorl    #8,d2           | Position FP value
  588.         lsrl    #1,d2           | Force sign bit to 0
  589.         addql   #4,sp           | Delete four bytes from the stack
  590.         movel   d2,sp@
  591.         jmp     a4@
  592. /*
  593. |
  594. | ###   SUBTTL  FPATN: Arctangent Function
  595. |       page
  596. |
  597. |  ARCTANGENT Function.
  598. |
  599. |  The arctangent of the single precision floating point value on
  600. |  the stack computed by using a split domain with a polynomial
  601. |  approximation.  A principal range radian value is returned.
  602. |
  603. |  The domain is split at 0.25 (four) intervals.  A polynomial is
  604. |  used to approximate the arctangent for magnitudes less than 1/8.
  605. |
  606. |  Using the trigonometric identity:
  607. |         ARCTAN(y) + ARCTAN(z) = ARCTAN((y+z)/(1+yz))
  608. |         If z = (x-y)/(1+xy) then ARCTAN((y+z)/(1+yz)) = ARCTAN(x).
  609. |
  610. |         ARCTAN(-v) = -ARCTAN(v)        * make argument positive
  611. |         ARCTAN(1/v) = PI/2 - ARCTAN(v) * reduce argument to <= 1.0
  612. |
  613. |
  614. |  ARCTANGENT approximation polynomical coefficients
  615. |
  616. |         C3  =   -1.4285 71429E-01     = -1/7
  617. */
  618. FATNCN:
  619.         .long   0xBE124925
  620. |         C2  =    2.0000 00000E-01     =  1/5
  621.         .long   0x3E4CCCCD
  622. |         C1  =   -3.3333 33333E-01     = -1/3
  623.         .long   0xBEAAAAAB
  624. |         C0  =    1.0000 00000E+00     =  1/1
  625.         .long   0x3F800000
  626. |
  627. |       .set    NFATNC,4
  628. |
  629. |
  630. |
  631. |  Table of ARCTANGENT values at 0.125 intervals
  632. |
  633. |         ATAN(1/4)  =  2.4497 86631E-01
  634. FATNTB:
  635.         .long   0x3E7ADBB0
  636. |         ATAN(2/4)  =  4.6364 76090E-01
  637.         .long   0x3EED6338
  638. |         ATAN(3/4)  =  6.4350 11088E-01
  639.         .long   0x3F24BC7D
  640. |         ATAN(1/1)  =  7.8539 81634E-01   ( = PI/4)
  641.         .long   0x3F490FDB
  642. |
  643. |
  644. |  FP PI/2 (duplicate of FPIO2 because of assembler bug)
  645. |
  646. FXPIO2:
  647.         .long   0x3FC90FDB
  648. |
  649. | ###   PUBLIC  FPATN
  650. |
  651. FPATN:
  652.         |dsw    0
  653.         bsr     FPFADJ
  654. |
  655.         jvs     FFNANR          | J/ NaN arg -> NaN result
  656.         jcc     FPAT10          | J/ not INF
  657. |
  658.         movel   FXPIO2,d1       | Get PI/2
  659.         roxll   #1,d1
  660.         roxlw   sp@             | INF sign bit into X
  661.         roxrl   #1,d1           | PI/2 given sign of INF
  662.         addql   #4,sp           | Delete four bytes from the stack
  663.         movel   d1,sp@
  664.         jmp     a4@
  665. |
  666. FPAT10:
  667.         jeq     FFZERR          | J/ 0.0 arg -> 0.0 result
  668. |
  669.         bclr    #7,sp@          | Insure argument positive
  670.         sne     d0              | Create flag byte (0xFF iff negative)
  671.         andib   #0x80,d0                | Keep sign bit only
  672.         moveb   d0,a7@(6)       | Save flag byte
  673. |
  674.         movew   sp@,d1
  675.         cmpiw   #128*FBIAS+0x10,d1      | (top word of 1.125)
  676.         jlt     FPAT20                  | J/ arg < 1 + 1/8
  677. |
  678.         addqb   #1,a7@(6)
  679. |
  680.         movel   #0x3F800000,sp@- |Place 1.0 onstack
  681.         jsr     FPRDIV          | Invert the number
  682. |
  683. FPAT20:
  684.         movew   sp@,d1
  685.         cmpiw   #128*FBIAS-256,d1
  686.         jlt     FPAT30          | J/ arg < 1/4
  687. |
  688.         moveb   d1,d2           | Number of eights in d2
  689.         orib    #0x80,d2                | Implicit bit
  690.         lsrw    #7,d1
  691.         moveq   #FBIAS+4-256,d3
  692.         subb    d1,d3
  693.         lsrb    d3,d2
  694.         addqb   #1,d2
  695.         lsrb    #1,d2           | Rounded quarters in d2.B
  696. |
  697.         clrl    d0
  698.         moveb   d2,d0           | 32 bit integer in d0
  699. |
  700.         lslb    #2,d2
  701.         addb    d2,a7@(6)       | Save 4 * quarters on stack
  702. |
  703.         jsr     FLOAT
  704.         subiw   #128*2,sp@      | Produce y, floating point quarters
  705. |
  706.         movel   a7@(4),sp@-
  707.         movel   a7@(4),sp@-     | On stack:  y, arg', y, arg', <temps>
  708. |
  709.         jsr     FPMUL           | /* arg'*y */
  710.         movel   #0x3F800000,sp@-
  711.         jsr     FPADD           | /* 1.0 + arg'*y */
  712. |
  713.         movel   a7@(8),d0       | Exchange stack items
  714.         movel   sp@,a7@(8)
  715.         movel   d0,sp@          | On stack: arg', y, (1+arg'*y), <tmps>
  716.         bset    #7,a7@(4)       | Negate y
  717.         jsr     FPADD           | /* (arg'-y) */
  718.         jsr     FPRDIV          | (arg'-y) / (1 + arg'*y)
  719. |
  720. FPAT30:
  721.         |dsw    0
  722.         movel   sp@,sp@-        | Duplicate z
  723. |
  724.         pea     FATNCN
  725.         movel   sp@+,a6 | Polynomial approximation to small ATN
  726.         moveq   #NFATNC,d0
  727.         bsr     FX2SER
  728.         jsr     FPMUL           | Complete approximation
  729. |
  730.         moveb   a7@(6),d0
  731.         andiw   #0x001C,d0      | Trim to table index
  732.         jeq     FPAT40          | J/ y = 0.0, ARCTAN(y) = 0.0
  733. |
  734.         pea     FATNTB-4
  735.         movel   sp@+,a6
  736.         movel   a6@(0,d0:W),sp@-
  737.         jsr     FPADD           | Add in ARCTAN(y)
  738. |
  739. FPAT40:
  740.         btst    #0,a7@(6)       | Check for inversion
  741.         jeq     FPAT50          | J/ no inversion
  742. |
  743.         bset    #7,sp@          | Negate ARCTAN
  744.         movel   FXPIO2,sp@-
  745.         jsr     FPADD           | Inversion via subtraction
  746. |
  747. FPAT50:
  748.         tstb    a7@(6)          | Check sign of result
  749.         jpl     FPAT60          | J/ positive
  750. |
  751.         bset    #7,sp@          | Negate result
  752. |
  753. FPAT60:
  754.         movel   sp@+,sp@        | Downshift result
  755.         jmp     a4@
  756. /*
  757. |
  758. | ###   SUBTTL  FPCOS, FPSIN, FPTAN: Trigonometric Functions
  759. |       page
  760. |
  761. |  TRIG ROUTINES.
  762. |
  763. |  The support routine FTRGSV converts the radian mode argument to
  764. |  an quadrant value between -0.5 and 0.5 (quadrants).  The sign of the
  765. |  is saved (the argument is forced non-negative).  Computations are
  766. |  performed for values quadrant values of -0.5 to 0.5* other values
  767. |  are transformed as per the following transformation formulae
  768. |  and table:
  769. |
  770. |     Let:     z = shifted quadrant value
  771. |     Recall:  sin(-x) = -sin(x)    tan(-x) = -tan(x)
  772. |              cos(-x) =  cos(x)
  773. |
  774. |     l========l=================l=================l=================l
  775. |     l  QUAD  l       SIN       l       COS       l       TAN       l
  776. |     l========l=================l=================l=================l
  777. |     l    0   l      sin(z)     l      cos(z)     l      tan(z)     l
  778. |     l    1   l      cos(z)     l     -sin(z)     l   -1/tan(z)     l
  779. |     l    2   l     -sin(z)     l     -cos(z)     l      tan(z)     l
  780. |     l    3   l     -cos(z)     l      sin(z)     l   -1/tan(z)     l
  781. |     l========l=================l=================l=================l
  782. |
  783. |  The sign of the argument is, by the equations above, important only
  784. |  when computing SIN and TAN.
  785. |
  786. |  Chebyshev Polynomials are used to approximate the trigonometric
  787. |  value in the range -0.5 to 0.5 quandrants.  (Note: constants are
  788. |  adjusted to reflect calculations done in quadrant mode instead
  789. |  of radian mode).
  790. |
  791. |
  792. |
  793. |         C08  =   9.1926 02748E-04
  794. */
  795. FCOSCN:
  796.         .long   0x3A70FA83
  797. |         C06  =  -2.0863 48076E-02
  798.         .long   0xBCAAE9E4
  799. |         C04  =   2.5366 95079E-01
  800.         .long   0x3E81E0F8
  801. |         C02  =  -1.2337 00550E+00
  802.         .long   0xBF9DE9E6
  803. |         C00  =   1.0000 00000E+00
  804.         .long   0x3F800000
  805. |
  806. |       .set    NFCOSC,5
  807. |
  808. |
  809. |
  810. |         C09  =   1.6044 11848E-04
  811. FSINCN:
  812.         .long   0x39283C1A
  813. |         C07 =   -4.6817 54135E-03
  814.         .long   0xBB996966
  815. |         C05  =   7.9692 62625E-02
  816.         .long   0x3DA335E3
  817. |         C03  =  -6.4596 40975E-01
  818.         .long   0xBF255DE7
  819. |         C01  =   1.5707 96327E+00
  820. FPIO2:
  821.         .long   0x3FC90FDB
  822. |
  823. |       .set    NFSINC,5
  824. |
  825. |
  826. |
  827. |         Q3  =    1.7732 32244E+01
  828. FTNQCN:
  829.         .long   0x418DDBCC
  830. |         Q2  =   -8.0485 82645E+02
  831.         .long   0xC44936EE
  832. |         Q1  =    6.4501 55566E+03
  833.         .long   0x45C9913F
  834. |         Q0  =   -5.6630 29631E+03
  835.         .long   0xC5B0F83D
  836. |
  837. |       .set    NFTNQC,4
  838. |
  839. |
  840. |         P3  =    1.0000 00000E+00
  841. FTNPCN:
  842.         .long   0x3F800000
  843. |         P2  =   -1.5195 78276E+02
  844.         .long   0xC317F534
  845. |         P1  =    2.8156 53022E+03
  846.         .long   0x452FFA73
  847. |         P0  =   -8.8954 66142E+03
  848.         .long   0xC60AFDDD
  849. |
  850. |       .set    NFTNPC,4
  851. |
  852. |
  853. |         INV2PI  =  1 / 2*PI  =   1.5915 49431E-01
  854. FIN2PI:
  855.         .long   0x3E22F983
  856. |
  857. |
  858. | ###   PUBLIC  FPCOS
  859. |
  860. FPCOS:
  861.         bsr     FTRGSV          | Prepare argument for operation
  862. |
  863.         moveb   d0,d1           | Copy into d1
  864.         andib   #3,d0           | Strip sign bit
  865.         addqb   #1,d0
  866.         rorb    #2,d0           | Move sign bit to B7
  867.         moveb   d0,a7@(4)       | Save it
  868.         rorb    #1,d1
  869.         jcs     FSINOP          | Compute sine
  870. |
  871. |
  872. FCOSOP:
  873.         pea     FCOSCN
  874.         movel   sp@+,a6
  875.         moveq   #NFCOSC,d0
  876.         bsr     FX2SER
  877. |
  878. FTRGFN:
  879.         moveb   a7@(4),d0
  880.         andib   #0x80,d0                | Isolate sign bit
  881.         eorb    d0,sp@
  882. |
  883.         movel   sp@+,sp@
  884.         jmp     a4@
  885. |
  886. |
  887. |
  888. | ###   PUBLIC  FPSIN
  889. |
  890. FPSIN:
  891.         bsr     FTRGSV          | Prepare argument
  892. |
  893.         addib   #0x7E,a7@(4)    | Compute sign
  894.         rorb    #1,d0
  895.         jcs     FCOSOP
  896. |
  897. |
  898. FSINOP:
  899.         movel   sp@,sp@-        | Duplicate argument
  900. |
  901.         pea     FSINCN
  902.         movel   sp@+,a6
  903.         moveq   #NFSINC,d0
  904.         bsr     FX2SER
  905.         jsr     FPMUL
  906. |
  907.         jra     FTRGFN
  908. |
  909. |
  910. |
  911. | ###   PUBLIC  FPTAN
  912. |
  913. FPTAN:
  914.         bsr     FTRGSV          | Prepare argument
  915. |
  916.         rorb    #1,d0
  917.         andib   #0x80,d0
  918.         eorb    d0,a7@(4)
  919. |
  920.         movel   sp@,sp@-        | Double duplication of argument
  921.         movel   sp@,sp@-
  922. |
  923.         pea     FTNPCN
  924.         movel   sp@+,a6
  925.         moveq   #NFTNPC,d0
  926.         bsr     FX2SER
  927.         jsr     FPMUL
  928. |
  929.         movel   a7@(4),d0
  930.         movel   sp@,a7@(4)
  931.         movel   d0,sp@
  932. |
  933.         pea     FTNQCN
  934.         movel   sp@+,a6
  935.         moveq   #NFTNQC,d0
  936.         bsr     FX2SER
  937. |
  938.         btst    #0,a7@(8)
  939.         jne     FPTN20          | J/ reverse division
  940. |
  941.         jsr     FPDIV
  942.         jra     FTRGFN
  943. |
  944. FPTN20:
  945.         jsr     FPRDIV
  946.         jra     FTRGFN
  947. /*
  948. |
  949. |       page
  950. |
  951. |  Trigonometric Service Routine
  952. |
  953. |  The single precision floating point value to be processed is on the
  954. |  stack.  Excess 2 PI's are removed from the argument.  The range of
  955. |  the argument is then scaled to within PI/4 of 0.  The shift size
  956. |  (in number of quadrants) is returned in D0.  The original sign bit
  957. |  is returned in the D0.B sign bit.
  958. |
  959. |  If the argument is NaN, +INF, -INF, or too large (>= 2^16), this
  960. |  routine causes a return to the caller with a NaN result.
  961. |
  962. */
  963. FTRGSV:
  964.         moveal  sp@+,a6 | FTRGSV return addr
  965. |
  966.         bsr     FPFADJ
  967.         jcs     FFNANR          | Return NAN if +/- INF
  968.         jvs     FFNANR          | Return NaN if NaN
  969. |
  970.         clrw    a7@(4)          | Create arg type return byte
  971. |
  972.         roxlw   sp@             | Sign bit into X
  973.         roxrw   a7@(4)          | Sign bit into temp byte
  974.         roxrw   sp@             | Restore FP value (with sign = +)
  975. |
  976.         cmpiw   #128*FBIAS+2048,sp@     | (2048 = 128*16)
  977.         jge     FFNANR                  | J/ return NaN if ABS(arg) >= 2^16
  978. |
  979.         movel   FIN2PI,sp@-     | Scale arg by 1/(2*PI)
  980.         jsr     FPMUL
  981. |
  982.         cmpiw   #128*FBIAS,sp@
  983.         jlt     FTS10           | /* J/ no excess two PI's */
  984. |
  985.         movel   sp@,sp@-        | Double the scaled argument
  986.         jsr     INT
  987.         negl    d0
  988.         jsr     FLOAT
  989.         jsr     FPADD
  990. |
  991. FTS10:
  992.         tstw    sp@
  993.         jeq     FTS20
  994. |
  995.         addiw   #128*3,sp@      | Multiply value by 8
  996.         cmpiw   #128*FBIAS,sp@
  997.         jlt     FTS20           | J/ < 1
  998. |
  999.         movel   sp@,sp@-        | Double parameter
  1000.         jsr     INT
  1001.         addqb   #1,d0
  1002.         lsrb    #1,d0
  1003.         addb    d0,a7@(4)       | Mix quadrant number with sign bit
  1004. |
  1005.         lslb    #1,d0
  1006.         negl    d0
  1007.         jsr     FLOAT
  1008.         jsr     FPADD
  1009. |
  1010. FTS20:
  1011.         tstw    sp@
  1012.         jeq     FTS30           | J/ arg = 0.0
  1013. |
  1014.         subiw   #128*1,sp@      | Range result to -0.5 to 0.5
  1015. |
  1016. FTS30:
  1017.         andib   #0x83,a7@(4)    | Limit quadrant shift to 0 thru 3
  1018.         moveb   a7@(4),d0       | Return cntl byte in d0 and at a7@(4)
  1019.         jmp     a6@
  1020. /*
  1021. |
  1022. | ###   SUBTTL  Polynomial Evaluation Routine
  1023. |       page
  1024. |
  1025. |  Polynomial Evaluation Routines.
  1026. |
  1027. |  A list of constants is pointed to by A6.  X is on the stack.  D0
  1028. |  contains the number of constants (the polynomial degree plus one).
  1029. |
  1030. |  A6 enters pointing to C[1].  Upon return, the value on stack has
  1031. |  been replaced with:
  1032. |  FXSER   = C[1]*X^(N-1)  + C[2]*X^(N-2)  + ... + C[N-1]*X   + C[N]
  1033. |
  1034. |  FX2SER  = C[1]*X^(2N-2) + C[2]*X^(2N-4) + ... + C[N-1]*X^2 + C[N]
  1035. |
  1036. |
  1037. */
  1038. FX2SER:
  1039.         moveal  a4,a5           | Save a4 in a5
  1040.         bsr     FPFADJ
  1041. |
  1042.         moveb   d0,a7@(4)       | Save count
  1043. |
  1044.         movel   sp@,sp@-        | Square the argument
  1045.         jsr     FPMUL
  1046.         jra     FXSR01          | J/ join FXSER routine
  1047. |
  1048. FXSER:
  1049.         moveal  a4,a5
  1050.         bsr     FPFADJ
  1051. |
  1052.         moveb   d0,a7@(4)
  1053. |
  1054. FXSR01:
  1055.         movel   a6@+,sp@-       | Place C[1] on stack as accum
  1056. |
  1057.         subqb   #1,a7@(8)
  1058. |
  1059. FXSR02:
  1060.         movel   a7@(4),sp@-     | Copy X
  1061.         jsr     FPMUL
  1062.         movel   a6@+,sp@-       | Add in next coefficient
  1063.         jsr     FPADD
  1064. |
  1065.         subqb   #1,a7@(8)
  1066.         jne     FXSR02          | J/ more coefficients
  1067. |
  1068.         movel   sp@,a7@(8)      | Adjust return
  1069.         addql   #8,sp
  1070. |
  1071.         moveal  a4,a3
  1072.         moveal  a5,a4           | Restore return address
  1073.         jmp     a3@
  1074. /*
  1075. |
  1076. | ###   SUBTTL  Function Completion Segments
  1077. |       page
  1078. |
  1079. |  FPFADJ - Adjust the stack for single precision functions.
  1080. |          Move the return address to the function caller into A4.
  1081. |          Shift the single precision floating point argument down
  1082. |          four bytes, leaving a temporary area of four bytes at
  1083. |          4(A7) thru 7(A7).  Set the condition code bits N, Z,
  1084. |          C (INF), and V (NaN) to quickly type the argument.
  1085. |
  1086. */
  1087. FPFADJ:
  1088.         moveal  sp@+,a3 | Function return addr
  1089.         moveal  sp@,a4          | Caller return addr
  1090.         movel   a7@(4),sp@      | Down shift parameter
  1091. |
  1092.         movew   sp@,d2          | Get SEM word
  1093.         rolw    #1,d2
  1094.         cmpiw   #256*0xFF,d2
  1095.         jcs     FPFA10          | J/ not INF or NaN
  1096. |
  1097.         andiw   #0xFE,d2
  1098.         jeq     FPFA05
  1099. |
  1100.         orib    #0x02,ccr       | Set -V- bit -> NaN argument
  1101. | ##    DC.W    $003C,$0002
  1102.         jmp     a3@
  1103. |
  1104. FPFA05:
  1105.         tstb    sp@             | /* Set N bit as req'd, clear Z bit. */
  1106.         orib    #0x01,ccr       | Set -C- bit -> INF argument
  1107. | ##    DC.W    $003C,$0001
  1108.         jmp     a3@
  1109. |
  1110. FPFA10:
  1111.         tstw    sp@             | /* Set N, Z bits as req'd, clear V, C */
  1112.         jmp     a3@
  1113. |
  1114. |
  1115. |
  1116. FFPINR:
  1117.         |dsw    0               | Result is positive overflow
  1118.         moveq   #0,d0           | Sign is positive
  1119.         jra     FFIN01
  1120. |
  1121. FFMINR:
  1122.         |dsw    0               | Result in negative overflow
  1123.         moveq   #-1,d0          | Sign is negative
  1124. |
  1125. FFIN01:
  1126.         moveaw  d0,a2           | Sign into a2
  1127.         addql   #8,sp           | Delete eight bytes from the stack
  1128.         moveal  a4,a0           | Return addr in a0
  1129.         jmp     FINFRS          | (Use FPOPNS exception return)
  1130. |
  1131. |
  1132. FFNANR:
  1133.         |dsw    0               | Result is NaN
  1134.         addql   #8,sp           | Delete eight bytes from the stack
  1135.         moveal  a4,a0
  1136.         jmp     FNANRS
  1137. |
  1138. |
  1139. FFZERR:
  1140.         |dsw    0               | Result is zero
  1141.         addql   #8,sp
  1142.         moveal  a4,a0
  1143.         jmp     FZERRS
  1144. |
  1145. |
  1146. FFUNFR:
  1147.         |dsw    0               | Underflow result
  1148.         addql   #8,sp           | Delete eight bytes from the stack
  1149.         moveal  a4,a0           | Return address into a0
  1150.         jmp     FUNFRS
  1151. |
  1152. |
  1153. FFONER:
  1154.         |dsw    0               | Result is 1.0
  1155.         addql   #4,sp
  1156.         movel   #0x3F800000,sp@
  1157.         clrb    FPERR
  1158.         jmp     a4@
  1159. |
  1160. |
  1161. |       end