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

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/DPFNCS: IEEE Double Precision Functions
  21. |DPFNCS idnt    1,0             ; IEEE Double Precision Functions
  22. |                               ; DPFNCS.A68
  23. |
  24. |* * * * * * * * * *
  25. |
  26. |       68000 DPAC  --  Double 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. |  Double Precision Floating Point Function library.
  51. |
  52. |  These functions operate on double precision floating point values,
  53. |  yielding double 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        -708.40 < a < 709.78    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 forward branches to SHORT
  86. |
  87.         .globl  DPEXP
  88.         .globl  DPLN
  89.         .globl  DPLOG
  90.         .globl  DPXTOI
  91.         .globl  DPSQRT
  92.         .globl  DPATN
  93.         .globl  DPCOS
  94.         .globl  DPSIN
  95.         .globl  DPTAN
  96. |
  97. |
  98. |       xref    DPMUL           ;Floating point operations
  99. |       xref    DPDIV
  100. |       xref    DPRDIV
  101. |       xref    DPADD
  102. |       xref    DAINT           ;Basic floating point functions
  103. |       xref    DFLOAT
  104. |       xref    DINT
  105. |
  106. |       xref    DNANRS
  107. |       xref    DINFRS
  108. |       xref    DUNFRS
  109. |       xref    DZERRS
  110. |
  111. |
  112. |
  113. |
  114. |       .set    DBIAS,1023
  115. |
  116. |
  117. |       xref    FPERR
  118. |
  119. |
  120. |       .set    ERUNF,1         |FPERR UNDERFLOW ERROR CODE
  121. |       .set    EROVF,2         |FPERR OVERFLOW ERROR CODE
  122. |       .set    ERNAN,3         |FPERR INVALID OPERATION ERROR CODE
  123. /*
  124. |
  125. |
  126. |
  127. | ###   SUBTTL  DPEXP: Exponentiation of e Function
  128. |       page
  129. |
  130. |
  131. |  EXP:   Calculate e to the power specified by the stack argument.
  132. |         The result is returned on the stack.
  133. |         placed at DI.
  134. |
  135. |         FPERR is set upon overflow, underflow, or NaN argument.
  136. |
  137. |  Algorithm:
  138. |  The argument is multiplied by 1/LN 2.  The integer portion of the
  139. |  product becomes the two*s exponent.  A Taylor series approximation
  140. |  about zero is used to compute 2**FRAC(ARG * 1/LN 2).
  141. |
  142. */
  143.         .text
  144. |
  145. DEXPCN:
  146.         |dsw    0               | EXP CONSTANT LIST (2**X EVALUATION)
  147. |
  148. | ???     (LN 2)^16/16!   =   1.3570 24794 87551 47193 D-16
  149. | ???   DC.L    $3CA38E89,$AE79F8B4
  150. |         (LN 2)^15/15!   =   3.1324 36707 08842 86216 D-15
  151.         .long   0x3CEC36E8,0x43B04022
  152. |         (LN 2)^14/14!   =   6.7787 26354 82254 56335 D-14
  153.         .long   0x3D331496,0x4D5878A9
  154. |         (LN 2)^13/13!   =   1.3691 48885 39041 28881 D-12
  155.         .long   0x3D781619,0x3166D0F9
  156. |         (LN 2)^12/12!   =   2.5678 43599 34882 05142 D-11
  157.         .long   0x3DBC3BD6,0x50FC2986
  158. |         (LN 2)^11/11!   =   4.4455 38271 87081 14976 D-10
  159.         .long   0x3DFE8CAC,0x7351BB25
  160. |         (LN 2)^10/10!   =   7.0549 11620 80112 33299 D-09
  161.         .long   0x3E3E4CF5,0x158B8ECA
  162. |         (LN 2)^ 9/ 9!   =   1.0178 08600 92396 99728 D-07
  163.         .long   0x3E7B5253,0xD395E7C4
  164. |         (LN 2)^ 8/ 8!   =   1.3215 48679 01443 09488 D-06
  165.         .long   0x3EB62C02,0x23A5C824
  166. |         (LN 2)^ 7/ 7!   =   1.5252 73380 40598 40280 D-05
  167.         .long   0x3EEFFCBF,0xC588B0C7
  168. |         (LN 2)^ 6/ 6!   =   1.5403 53039 33816 09954 D-04
  169.         .long   0x3F243091,0x2F86C787
  170. |         (LN 2)^ 5/ 5!   =   1.3333 55814 64284 43423 D-03
  171.         .long   0x3F55D87F,0xE78A6731
  172. |         (LN 2)^ 4/ 4!   =   9.6181 29107 62847 71620 D-03
  173.         .long   0x3F83B2AB,0x6FBA4E77
  174. |         (LN 2)^ 3/ 3!   =   5.5504 10866 48215 79953 D-02
  175.         .long   0x3FAC6B08,0xD704A0C0
  176. |         (LN 2)^ 2/ 2!   =   2.4022 65069 59100 71233 D-01
  177.         .long   0x3FCEBFBD,0xFF82C58F
  178. |         (LN 2)^1/ 1!   =   6.9314 71805 59945 30942 D-01
  179. DLN2:
  180.         .long   0x3FE62E42,0xFEFA39EF
  181. |                             1.0000 00000 00000 00000 D+00
  182.         .long   0x3FF00000,0x00000000
  183. |
  184. |       .set    DNEXPC,16               | Number of constants in DEXP poly
  185. |
  186. |         1 / LN 2  =  1.4426 95040 88896 34074 D+00
  187. DINLN2:
  188.         .long   0x3FF71547,0x652B82FE
  189. |
  190. |
  191. |
  192. | ###   PUBLIC  DPEXP
  193. |
  194. DPEXP:
  195.         |dsw    0
  196.         bsr     DPFADJ          | Set-up for DP functions
  197. |
  198.         jvs     DFNANR          | NaN parm -> NaN result
  199.         jcc     DEXP01          | J/ arg not INF
  200. |
  201.         jmi     DFUNFR          | -INF parm -> underflow result
  202.         jra     DFPINR          | +INF parm -> positive INF result
  203. |
  204. DEXP01:
  205.         movel   DINLN2+4,sp@-   | 1/LN 2 on stack
  206.         movel   DINLN2+0,sp@-
  207.         jsr     DPMUL           | Convert to 2^ function
  208. |
  209.         movew   sp@,d1
  210.         andiw   #0x7FF0,d1
  211.         cmpiw   #16*DBIAS+144,d1
  212.         jhi     DEXP10          | J/ overflow or underflow  >= +/- 2^10
  213.         jne     DEXP20          | J/ within range            < +/- 2^09
  214.         tstb    sp@
  215.         jpl     DEXP20          | J/ result >= 1.0
  216. |
  217.         movel   sp@,d2          | Examine top 12 bits of mantissa
  218.         rorl    #8,d2
  219.         andiw   #0x0FFF,d2
  220.         cmpiw   #0x0FF8,d2
  221.         jcs     DEXP20          | J/ result >= 2^-1022
  222. |
  223. DEXP10:
  224.         tstb    sp@
  225.         jpl     DFPINR          | J/ DP function +INF result
  226.         jra     DFUNFR          | J/ DP function underflow result
  227. |
  228. DEXP20:
  229.         movel   a7@(4),sp@-
  230.         movel   a7@(4),sp@-     | Double the argument on the stack
  231. |
  232.         jsr     DINT
  233. |
  234.         movew   d1,a7@(8)       | Save result of DINT
  235. |
  236.         negl    d1
  237.         negxl   d0              | Negate integer
  238.         jsr     DFLOAT
  239.         jsr     DPADD           | Special DFRAC
  240. |
  241.         pea     DEXPCN
  242.         movel   sp@+,a6 | Point a6 to constant list
  243.         moveq   #DNEXPC ,d0      | d0 holds the number of constants
  244.         moveq   #DNEXPC, d0      | d0 holds the number of constants
  245.         moveq   #16,d0      | XXX DEBUG DEBUG
  246.         bsr     DXSER           | Polynomial series
  247. |
  248.         movew   a7@(8),d0       | Fetch power of two scaling
  249.         lslw    #4,d0
  250.         swap    d0
  251.         clrw    d0
  252.         addl    sp@+,d0 | Combine with DXSER result
  253. |
  254.         movel   sp@,a7@(4)      | Downshift result
  255.         movel   d0,sp@
  256.         jmp     a4@             | Return
  257. /*
  258. |
  259. | ###   SUBTTL  DPLOG, DPLN: Logarithm Functions
  260. |       page
  261. |
  262. |  LOGARITHM (BASE E) FUNCTION.
  263. |
  264. |  The natural logarithm of the double precision floating point
  265. |  value on the stack is computed using a split domain polynomial
  266. |  approximation.  The common log is computed by scaling the
  267. |  result of the natural log computation.
  268. |
  269. |  TWOS = FLOAT(ARG.EXPONENT) * LOG(2)
  270. |
  271. |  The argument, (after the two's power scaling, 2.0 > arg' >= 1.0),
  272. |  is sorted into one of five classes.  Within that class, a center
  273. |  point with a known log value is used in combination with a 9th
  274. |  degree Chebyshey polynomial approximation, to calculate a
  275. |  logarithm.
  276. |
  277. |  The center point of each class is adjusted so that its natural
  278. |  logarithm expressed in double precision form is accurate to
  279. |  more than 80 bits.
  280. |
  281. |  log(arg) = two's log + center point log + polynomial approximation
  282. |
  283. |  Polynomial approximation:
  284. |
  285. |  log((1-t)/(1+t)) = t*(c1*t^8 + c2*t^6 + c3*t^4 + c4*t^2 + c5)
  286. |         (accurate with 1.0E-17 for t within 0.1 of 1.0)
  287. |
  288. |  t = - (center - arg')/(center + arg')  [to calc log of arg'/center]
  289. |
  290. */
  291. DLNCNS:
  292.         |dsw    0               | LN constants list
  293. |
  294. |         c1  =   0.22330 022
  295.         .long   0x3FCC951A,0x03000000
  296. |         c2  =   0.28571 20487
  297.         .long   0x3FD2491B,0x30450000
  298. |         c3  =   0.40000 00018 947
  299.         .long   0x3FD99999,0x9BA26900
  300. |         c4  =   0.66666 66666 66105
  301.         .long   0x3FE55555,0x55554192
  302. |         c5  =   2.00000 00000 00000 00000
  303.         .long   0x40000000,0x00000000
  304. |
  305. |       .set    DNLNCN,5                | Number of constants in DLN poly
  306. |
  307. |
  308. DLNCEN:
  309.         |dsw    0               | Center Points
  310. |         Center  #1 = 1.0000 00000 00000 00000
  311.         .long   0x3FF00000,0x00000000
  312. |         Center  #2 = 1.1892 07115 00272 05647  (close to 2^(1/4))
  313.         .long   0x3FF306FE,0x0A31B713
  314. |         Center  #3 = 1.4142 13562 37309 38548  (close to 2^(1/2))
  315.         .long   0x3FF6A09E,0x667F3BC7
  316. |         Center  #4 = 1.6817 92830 50742 54625  (close to 2^(3/4))
  317.         .long   0x3FFAE89F,0x995AD39D
  318. |         Center  #5 = 2.0000 00000 00000 00000
  319. | ---     shifted to 1.0 center..
  320. |
  321. DLNLOG:
  322.         |dsw    0               | DLNCEN values adj for exact ln values
  323. |         LN(Center #2) = 0.17328 67951 39985 90522
  324.         .long   0x3FC62E42,0xFEFA39E0
  325. |         LN(Center #3) = 0.34657 35902 79971 81045
  326.         .long   0x3FD62E42,0xFEFA39E0
  327. |         LN(Center #4) = 0.51986 03854 19956 82749
  328.         .long   0x3FE0A2B2,0x3F3BAB60
  329. |
  330. |
  331. |         1 / LN 10  =  0.43429 44819 03251 82765
  332. DILN10:
  333.         .long   0x3FDBCB7B,0x1526E50E
  334. |
  335. |
  336. |
  337. | ###   PUBLIC  DPLN
  338. | ###   PUBLIC  DPLOG
  339. |
  340. DPLOG:
  341.         |dsw    0
  342.         moveq   #-1,d0          | Signal common log scaling
  343.         jra     DLN000
  344. |
  345. DPLN:
  346.         |dsw    0
  347.         clrb    d0              | Signal no post calculation scaling
  348. |
  349. DLN000:
  350.         bsr     DPFADJ          | Adjust parameter on stack
  351. |
  352.         jvs     DFNANR          | J/ NaN arg -> NaN result
  353.         jmi     DFNANR          | J/ Neg arg -> NaN result
  354.         jeq     DFMINR          | J/ 0.0 arg -> -INF result
  355.         jcs     DFPINR          | J/ +INF arg -> +INF result
  356. |
  357.         moveb   d0,a7@(10)      | Save natural/common flag
  358. |
  359.         movew   sp@,d1          | Prepare to calc parm sign and exp
  360.         lsrw    #4,d1           | Position exponent (right justified)
  361.         subiw   #DBIAS,d1
  362.         movew   d1,a7@(8)       | /* Save two's exponent value */
  363. |
  364.         lslw    #4,d1           | Scale parameter
  365.         subw    d1,sp@
  366. |
  367.         clrw    d0              | Set class number to 0
  368.         movel   sp@,d1
  369.         lsrl    #8,d1           | d1.W = 0xEMMM
  370. |
  371.         cmpiw   #0xF000+371,d1
  372.         jcs     DLN050          | J/ < 1 +  371/4096  (1.090576)
  373.         addqw   #8,d0
  374.         cmpiw   #0xF000+1216,d1
  375.         jcs     DLN050          | J/ < 1 + 1216/4096  (1.296875)
  376.         addqw   #8,d0
  377.         cmpiw   #0xF000+2221,d1
  378.         jcs     DLN050          | J/ < 1 + 2221/4096  (1.542236)
  379.         addqw   #8,d0
  380.         cmpiw   #0xF000+3416,d1
  381.         jcs     DLN050          | J/ < 1 + 3416/4096  (1.833984)
  382.         addqw   #1,a7@(8)       | /* Class 4: Bump two's exp, then class 0 */
  383.         clrw    d0
  384.         subib   #0x10,a7@(1)    | Reduce scaled exponent
  385. |
  386. DLN050:
  387.         moveb   d0,a7@(11)      | Save center number
  388. |
  389.         pea     DLNCEN
  390.         movel   sp@+,a2
  391.         movel   a2@(4,d0:W),sp@- |Place center on stack
  392.         movel   a2@(0,d0:W),sp@-
  393. |
  394.         movel   a7@(12),sp@-    | Copy scaled argument
  395.         movel   a7@(12),sp@-
  396. |
  397.         movel   a2@(4,d0:W),sp@- |Place center on stack
  398.         movel   a2@(0,d0:W),sp@-
  399. |
  400.         jsr     DPADD           | /* Calc  (CENTER + PARM') */
  401. |
  402.         movel   sp@,d0          | Exch top stack item w/ 3rd
  403.         movel   a7@(16),d1
  404.         movel   d1,sp@
  405.         movel   d0,a7@(16)
  406.         movel   a7@(4),d0
  407.         movel   a7@(20),d1
  408.         movel   d1,a7@(4)
  409.         movel   d0,a7@(20)
  410. |
  411.         bset    #7,a7@(8)       | Negate CENTER
  412. |
  413.         jsr     DPADD           | /* Calc  - (CENTER - PARM') */
  414.         jsr     DPRDIV          | /* T = - (CENTER-PARM')/(CENTER+PARM) */
  415. |
  416.         movel   a7@(4),sp@-     | Duplicate t
  417.         movel   a7@(4),sp@-
  418. |
  419.         pea     DLNCNS
  420.         movel   sp@+,a6 | Poly approx
  421.         moveq   #DNLNCN,d0
  422.         bsr     DX2SER
  423. |
  424.         jsr     DPMUL           | Times t
  425.         clrw    d0
  426.         moveb   a7@(11),d0
  427.         jeq     DLN060          | J/ center = 0 -> no additive log val
  428. |
  429.         pea     DLNLOG-8
  430.         movel   sp@+,a6
  431.         movel   a6@(4,d0:W),sp@-
  432.         movel   a6@(0,d0:W),sp@-
  433.         jsr     DPADD           | Add in center log value
  434. |
  435. DLN060:
  436.         movew   a7@(8),d1       | /* Get two's exponent value */
  437.         clrl    d0
  438.         extl    d1
  439.         jpl     DLN061
  440.         moveq   #-1,d0
  441. DLN061:
  442.         |dsw    0
  443. |
  444.         jsr     DFLOAT
  445. |
  446.         movel   DLN2+4,sp@-     | Log of 2 on stack
  447.         movel   DLN2+0,sp@-
  448.         jsr     DPMUL
  449.         jsr     DPADD
  450. |
  451.         tstb    a7@(10)
  452.         jeq     DLN070          | J/ natural log
  453. |
  454.         movel   DILN10+4,sp@-   | Scaling value
  455.         movel   DILN10+0,sp@-
  456.         jsr     DPMUL
  457. |
  458. DLN070:
  459.         movel   a7@(4),a7@(8)
  460.         movel   sp@+,sp@
  461.         jmp     a4@
  462. /*
  463. | ###   SUBTTL  DPXTOI: Floating Point Number to Integer Power Function
  464. |       page
  465. |
  466. |  X to I power Function.
  467. |
  468. |  The double precision floating point value on the stack is
  469. |  raised to the power specified in D0.W then returned on stack.
  470. |
  471. |  A shift and multiply technique is used (possibly with a trailing
  472. |  recipication.
  473. |
  474. |
  475. | ###   PUBLIC  DPXTOI
  476. |
  477. */
  478. DPXTOI:
  479.         |dsw    0
  480.         bsr     DPFADJ
  481. |
  482.         jvs     DFNANR          | J/ NaN arg -> NaN result
  483.         jcc     DPXT10          | J/ arg is not INF
  484. |
  485.         tstw    d0
  486.         jeq     DFNANR          | J/ arg is +/- INF, I is 0 -> NaN
  487.         jmi     DFUNFR          | J/ x is +/- INF, I < 0 -> underflow
  488. |
  489.         rorw    #1,d0
  490.         andw    sp@,d0
  491.         jmi     DFMINR          | J/ arg is -INF, I is +odd -> -INF
  492.         jra     DFPINR          | else -> +INF
  493. |
  494. |
  495. DPXT10:
  496.         jne     DPXT15          | J/ parm is a number <> 0.0
  497. |
  498.         tstw    d0
  499.         jmi     DFPINR          | J/ 0.0 to -int -> +INF
  500.         jeq     DFNANR          | J/ 0.0 to 0 -> NaN
  501.         jra     DFZERR          | J/ 0.0 to +int -> 0.0
  502. |
  503. DPXT15:
  504.         tstw    d0
  505.         jeq     DFONER          | J/ num to 0 -> 1.0
  506. |
  507.         movew   d0,a7@(10)      | Save int as its own sign flag
  508.         jpl     DPXT20
  509.         negw    d0
  510. DPXT20:
  511.         |dsw    0
  512. |
  513.         movel   a7@(4),sp@-     | Result init to parm value
  514.         movel   a7@(4),sp@-
  515. |
  516.         moveq   #16,d1          | Find MS bit of power
  517. DPXT21:
  518.         lslw    #1,d0
  519.         jcs     DPXT22          | J/ MS bit moved into carry
  520.         dbra    d1,DPXT21       | Dec d1 and jump (will always jump)
  521. |
  522. DPXT22:
  523.         movew   d0,a7@(16)      | Power pattern on stack
  524.         moveb   d1,a7@(19)      | Bit slots left count on stack
  525. |
  526. |
  527. DPXT30:
  528.         subqb   #1,a7@(19)      | Decrement bit slots left
  529.         jeq     DPXT35          | J/ evaluation complete
  530. |
  531.         movel   a7@(4),sp@-     | Square result value
  532.         movel   a7@(4),sp@-
  533.         jsr     DPMUL           | Square it
  534. |
  535.         lslw    a7@(16)         | Shift power pattern
  536.         jcc     DPXT30          | J/ this product bit not set
  537. |
  538.         movel   a7@(12),sp@-    | Copy parm value
  539.         movel   a7@(12),sp@-
  540.         jsr     DPMUL
  541.         jra     DPXT30
  542. |
  543. DPXT35:
  544.         tstb    a7@(18)         | Check for recipocation
  545.         jpl     DPXT36          | J/ no recipocation
  546. |
  547.         clrl    sp@-            | Place 1.0 on stack
  548.         movel   #0x3FF00000,sp@-
  549.         jsr     DPRDIV
  550. |
  551. DPXT36:
  552.         movel   sp@+,a7@(8)     | Shift result value
  553.         movel   sp@+,a7@(8)
  554.         addql   #4,sp           | Delete excess stack area
  555.         jmp     a4@             | Return.
  556. /*
  557. |
  558. | ###   SUBTTL  DPSQRT: Square Root Function
  559. |       page
  560. |
  561. |  Square Root Function.
  562. |
  563. |  Take square root of the double precision floating point value
  564. |  on the top of the stack.
  565. |
  566. |  Use the Newton iteration technique to compute the square root.
  567. |
  568. |      X(n+1) = (X(n) + Z/X(n)) / 2
  569. |
  570. |  The two*s exponent is scaled to restrict the solution domain to 1.0
  571. |  through 4.0.  A linear approximation to the square root is used to
  572. |  produce a first guess with greater than 4 bits of accuracy.  Three
  573. |  successive iterations are performed in registers to obtain accuracy
  574. |  of about 30 bits.  The final iteration is performed in the floating
  575. |  point domain.
  576. |
  577. | ###   PUBLIC  DPSQRT
  578. |
  579. */
  580. DPSQRT:
  581.         |dsw    0
  582.         bsr     DPFADJ
  583. |
  584.         jvs     DFNANR          | J/ NaN arg -> NaN result
  585.         jmi     DFNANR          | J/ neg arg -> NaN result
  586.         jcs     DFPINR          | J/ +INF arg -> +INF result
  587.         jeq     DFZERR          | J/ 0.0 arg -> 0.0 result
  588. |
  589.         movew   sp@,d1          | Get S/E/M word
  590.         subiw   #16*DBIAS,d1    | Extract argument's two's exp
  591.         andib   #0xE0,d1                | Make it a factor of two
  592.         subw    d1,sp@          | /* Scale arg. range to 4.0 > arg' >= 1.0 */
  593.         asrw    #1,d1           | Square root of scaled two power
  594.         movew   d1,a7@(8)       | /* Save two's exp of result on stack */
  595. |
  596.         movel   sp@,d1          | Create fixed point integer for approx
  597.         movew   a7@(4),d2
  598.         lsll    #8,d1           | /* Produce arg' * 2^30 in d1 */
  599.         lsll    #3,d1
  600.         lsrl    #5,d2
  601.         orw     d2,d1
  602.         bset    #31,d1          | Set implicit bit
  603.         jeq     DPSQ10          | /* J/ arg' >= 2.0 */
  604. |
  605.         lsrl    #1,d1           | Adjust d1
  606. |
  607. DPSQ10:
  608.         movew   #42720-65536,d2 | d2 = 0.325926 * 2^17
  609.         swap    d1              | /* d1.W = arg' * 2^14 */
  610.         mulu    d1,d2           | /* d2 = arg' * 0.325926 * 2^31 */
  611.         swap    d2
  612.         addiw   #23616,d2       | + 0.7207 * 2^15 - to 4+ bits
  613.         subxw   d3,d3
  614.         orw     d3,d2           | Top out approximation at 1.99997
  615. |
  616.         swap    d1
  617.         lsrl    #1,d1           | /* Arg' * 2^29 in d1 (prevent overflow) */
  618. |
  619.         movel   d1,d3           | Copy into d3
  620.         divu    d2,d3           | /* Arg'/X0 * 2^14 in d3 */
  621.         lsrw    #1,d2
  622.         addw    d3,d2           | X1 in d2 - to 8 bits
  623. |
  624.         movel   d1,d3           | Second in-register iteration
  625.         divu    d2,d3
  626.         lsrw    #1,d2
  627.         addw    d3,d2           | X2 in d2 - to 16 bits
  628. |
  629.         movel   d1,d3
  630.         divu    d2,d3
  631.         movew   d3,d4
  632.         clrw    d3
  633.         swap    d4
  634.         divu    d2,d3
  635.         movew   d3,d4           | 32 bit division result
  636.         swap    d2
  637.         clrw    d2
  638.         lsrl    #1,d2
  639.         addl    d4,d2           | X3 in d2 - to 29 bits
  640.         subxl   d4,d4
  641.         orl     d4,d2           | Top out at 1.9999999995
  642. |
  643.         movel   a7@(4),sp@-     | /* Down shift arg' */
  644.         movel   a7@(4),sp@-
  645. |
  646.         lsll    #1,d2           | Create DP of X3 (good to 29 bits) ...
  647.         clrl    d3              | ... in d2:d3
  648.         movew   d2,d3
  649.         andiw   #0xFFF,d3
  650.         eorw    d3,d2
  651.         oriw    #DBIAS,d2       | Scale to floating point
  652.         moveq   #12,d0          | Shift count in d0
  653.         rorl    d0,d2           | Position bits
  654.         rorl    d0,d3
  655. |
  656.         movel   d2,a7@(8)       | /* On stack: X4, arg', X4, <flags> */
  657.         movel   d3,a7@(12)
  658.         movel   d3,sp@-
  659.         movel   d2,sp@-
  660.         jsr     DPDIV           | Last iter - to X4 - in DP domain
  661.         jsr     DPADD
  662.         subiw   #0x0010,sp@     | "Divide" by 2
  663. |
  664.         movew   a7@(8),d7
  665.         addw    d7,sp@          | Scale result
  666.         movel   a7@(4),a7@(8)   | Down shift result
  667.         movel   sp@+,sp@
  668.         jmp     a4@
  669. /*
  670. | ###   SUBTTL  DPATN: Arctangent Function
  671. |       page
  672. |
  673. |  ARCTANGENT Function.
  674. |
  675. |  The arctangent of the double precision floating point value at SI is
  676. |  computed by using a split domain with a polynomial approximation.
  677. |  A principal range radian value is returned.
  678. |
  679. |  The domain is split at 0.125 (eight) intervals.  A polynomial is
  680. |  used to approximate the arctangent for magnitudes less than 1/16.
  681. |
  682. |  Using the trigonometric identity:
  683. |         ARCTAN(y) + ARCTAN(z) = ARCTAN((y+z)/(1+yz))
  684. |         If z = (x-y)/(1+xy) then ARCTAN((y+z)/(1+yz)) = ARCTAN(x).
  685. |
  686. |         ARCTAN(-v) = -ARCTAN(v)        * make argument positive
  687. |         ARCTAN(1/v) = PI/2 - ARCTAN(v) * reduce argument to <= 1.0
  688. |
  689. |
  690. |  ARCTANGENT approximation polynomical coefficients
  691. |
  692. |         C4  =    1.1022 81616 12614 90000E-01
  693. */
  694. DATNCN:
  695.         .long   0x3FBC37E9,0xAD397134
  696. |         C3  =   -1.4285 41305 08745 00000E-01
  697.         .long   0xBFC2490B,0x4D511901
  698. |         C2  =    1.9999 99958 01446 40000E-01
  699.         .long   0x3FC99999,0x90956BB6
  700. |         C1  =   -3.3333 33333 31284 50000E-01
  701.         .long   0xBFD55555,0x5554C529
  702. |         C0  =    1.0000 00000 00000 00000E+00
  703.         .long   0x3FF00000,0x00000000
  704. |
  705. |       .set    NDATNC,5
  706. |
  707. |
  708. |
  709. |  Table of ARCTANGENT values at 0.125 intervals
  710. |
  711. |         ATAN(1/8)  =  1.2435 49945 46761 43503E-01
  712. DATNTB:
  713.         .long   0x3FBFD5BA,0x9AAC2F6E
  714. |         ATAN(2/8)  =  2.4497 86631 26864 15417E-01
  715.         .long   0x3FCF5B75,0xF92C80DE
  716. |         ATAN(3/8)  =  3.5877 06702 70572 22040E-01
  717.         .long   0x3FD6F619,0x41E4DEF1
  718. |         ATAN(4/8)  =  4.6364 76090 00806 11621E-01
  719.         .long   0x3FDDAC67,0x0561BB4F
  720. |         ATAN(5/8)  =  5.5859 93153 43562 43597E-01
  721.         .long   0x3FE1E00B,0xABDEFEB4
  722. |         ATAN(6/8)  =  6.4350 11087 93284 38680E-01
  723.         .long   0x3FE4978F,0xA3269EE1
  724. |         ATAN(7/8)  =  7.1882 99996 21624 50542E-01
  725.         .long   0x3FE700A7,0xC5784634
  726. |         ATAN(8/8)  =  7.8539 81633 97448 30962E-01   ( = PI/4)
  727.         .long   0x3FE921FB,0x54442D18
  728. |
  729. |
  730. |  DP PI/2 (duplicate of DPIO2 because of assembler bug)
  731. |
  732. DXPIO2:
  733.         .long   0x3FF921FB,0x54442D18
  734. |
  735. | ###   PUBLIC  DPATN
  736. |
  737. DPATN:
  738.         |dsw    0
  739.         bsr     DPFADJ
  740. |
  741.         jvs     DFNANR          | J/ NaN arg -> NaN result
  742.         jcc     DPAT10          | J/ not INF
  743. |
  744.         movel   DXPIO2+0,d1     | Get top long word of PI/2
  745.         roxll   #1,d1
  746.         roxlw   sp@             | INF sign bit into X
  747.         roxrl   #1,d1           | PI/2 given sign of INF
  748.         addql   #4,sp           | Delete four bytes from the stack
  749.         movel   DXPIO2+4,a7@(4)
  750.         movel   d1,sp@
  751.         jmp     a4@
  752. |
  753. DPAT10:
  754.         jeq     DFZERR          | J/ 0.0 arg -> 0.0 result
  755. |
  756.         bclr    #7,sp@          | Insure argument positive
  757.         sne     d0              | Create flag byte (0xFF iff negative)
  758.         andib   #0x80,d0                | Keep sign bit only
  759.         moveb   d0,a7@(10)      | Save flag byte
  760. |
  761.         movew   sp@,d1
  762.         cmpiw   #16*DBIAS,d1
  763.         jle     DPAT20          | J/ arg < 1 + 1/16
  764. |
  765.         addqb   #1,a7@(10)
  766. |
  767.         clrl    sp@-            | Place 1.0 onstack
  768.         movel   #0x3FF00000,sp@-
  769.         jsr     DPRDIV          | Invert the number
  770. |
  771. DPAT20:
  772.         movew   sp@,d1
  773.         cmpiw   #16*DBIAS-64,d1
  774.         jlt     DPAT30          | J/ arg < 1/16
  775. |
  776.         moveb   d1,d2           | Number of sixteenths in d2
  777.         andib   #0x0F,d2
  778.         orib    #0x10,d2                | Implicit bit
  779.         lsrw    #4,d1
  780.         moveq   #-1,d3
  781.         subb    d1,d3
  782.         lsrb    d3,d2
  783.         addqb   #1,d2
  784.         lsrb    #1,d2           | Rounded eighths in d2.B
  785. |
  786.         clrl    d0
  787.         clrl    d1
  788.         moveb   d2,d1           | 64 bit integer in d0:d1
  789. |
  790.         lslb    #3,d2
  791.         addb    d2,a7@(10)      | Save 8 * eigths on stack
  792. |
  793.         jsr     DFLOAT
  794.         subiw   #16*3,sp@       | Produce y, floating point eighths
  795. |
  796.         moveq   #4-1,d0
  797. DPAT25:
  798.         movel   a7@(12),sp@-
  799.         dbra    d0,DPAT25       | On stack:  y, arg', y, arg', <temps>
  800. |
  801.         jsr     DPMUL           | /* arg'*y */
  802.         clrl    sp@-            | Place 1.0 on stack
  803.         movel   #0x3FF00000,sp@-
  804.         jsr     DPADD           | /* 1.0 + arg'*y */
  805. |
  806.         movel   a7@(16),d0      | Exchange stack item
  807.         movel   a7@(20),d1
  808.         movel   sp@,a7@(16)
  809.         movel   a7@(4),a7@(20)
  810.         movel   d0,sp@
  811.         movel   d1,a7@(4)       | On stack: arg', y, (1+arg'*y), <tmps>
  812.         bset    #7,a7@(8)       | Negate y
  813.         jsr     DPADD           | /* (arg'-y) */
  814.         jsr     DPRDIV          | /* (arg'-y) / (1 + arg'*y) */
  815. |
  816. DPAT30:
  817.         |dsw    0
  818.         movel   a7@(4),sp@-     | Duplicate z
  819.         movel   a7@(4),sp@-
  820. |
  821.         pea     DATNCN
  822.         movel   sp@+,a6 | Polynomial approximation to small ATN
  823.         moveq   #NDATNC,d0
  824.         bsr     DX2SER
  825.         jsr     DPMUL           | Complete approximation
  826. |
  827.         moveb   a7@(10),d0
  828.         andiw   #0x0078,d0      | Trim to table index
  829.         jeq     DPAT40          | J/ y = 0.0, ARCTAN(y) = 0.0
  830. |
  831.         pea     DATNTB-8
  832.         movel   sp@+,a6
  833.         movel   a6@(4,d0:W),sp@-
  834.         movel   a6@(0,d0:W),sp@-
  835.         jsr     DPADD           | Add in ARCTAN(y)
  836. |
  837. DPAT40:
  838.         btst    #0,a7@(10)      | Check for inversion
  839.         jeq     DPAT50          | J/ no inversion
  840. |
  841.         bset    #7,sp@          | Negate ARCTAN
  842.         movel   DXPIO2+4,sp@-
  843.         movel   DXPIO2+0,sp@-
  844.         jsr     DPADD           | Inversion via subtraction
  845. |
  846. DPAT50:
  847.         tstb    a7@(10)         | Check sign of result
  848.         jpl     DPAT60          | J/ positive
  849. |
  850.         bset    #7,sp@          | Negate result
  851. |
  852. DPAT60:
  853.         movel   a7@(4),a7@(8)   | Downshift result
  854.         movel   sp@+,sp@
  855.         jmp     a4@
  856. /*
  857. |
  858. | ###   SUBTTL  DPCOS, DPSIN, DPTAN: Trigonometric Functions
  859. |       page
  860. |
  861. |  TRIG ROUTINES.
  862. |
  863. |  The support routine DTRGSV converts the radian mode argument to
  864. |  an quadrant value between -0.5 and 0.5 (quadrants).  The sign of the
  865. |  is saved (the argument is forced non-negative).  Computations are
  866. |  performed for values quadrant values of -0.5 to 0.5* other values
  867. |  are transformed as per the following transformation formulae
  868. |  and table:
  869. |
  870. |     Let:     z = shifted quadrant value
  871. |     Recall:  sin(-x) = -sin(x)    tan(-x) = -tan(x)
  872. |              cos(-x) =  cos(x)
  873. |
  874. |     l========l=================l=================l=================l
  875. |     l  QUAD  l       SIN       l       COS       l       TAN       l
  876. |     l========l=================l=================l=================l
  877. |     l    0   l      sin(z)     l      cos(z)     l      tan(z)     l
  878. |     l    1   l      cos(z)     l     -sin(z)     l   -1/tan(z)     l
  879. |     l    2   l     -sin(z)     l     -cos(z)     l      tan(z)     l
  880. |     l    3   l     -cos(z)     l      sin(z)     l   -1/tan(z)     l
  881. |     l========l=================l=================l=================l
  882. |
  883. |  The sign of the argument is, by the equations above, important only
  884. |  when computing SIN and TAN.
  885. |
  886. |  Chebyshev Polynomials are used to approximate the trigonometric
  887. |  value in the range -0.5 to 0.5 quandrants.  (Note: constants are
  888. |  adjusted to reflect calculations done in quadrant mode instead
  889. |  of radian mode).
  890. |
  891. |
  892. |
  893. |         C16  =   6.5659 63114 97947 23622E-11
  894. */
  895. DCOSCN:
  896.         .long   0x3DD20C62,0xC2F2D7F5
  897. |         C14  =  -6.3866 03083 79185 22411E-09
  898.         .long   0xBE3B6E24,0xF44B128F
  899. |         C12  =   4.7108 74778 81817 15037E-07
  900.         .long   0x3E9F9D38,0xA3763CC3
  901. |         C10  =  -2.5202 04237 30606 05481E-05
  902.         .long   0xBEFA6D1F,0x2A204A8C
  903. |         C08  =   9.1926 02748 39426 58024E-04
  904.         .long   0x3F4E1F50,0x6891BABB
  905. |         C06  =  -2.0863 48076 33529 96087E-02
  906.         .long   0xBF955D3C,0x7E3CBFFA
  907. |         C04  =   2.5366 95079 01048 01364E-01
  908.         .long   0x3FD03C1F,0x081B5AC4
  909. |         C02  =  -1.2337 00550 13616 98274E+00
  910.         .long   0xBFF3BD3C,0xC9BE45DE
  911. |         C00  =   1.0000 00000 00000 00000E+00
  912.         .long   0x3FF00000,0x00000000
  913. |
  914. |       .set    NDCOSC,9
  915. |
  916. |
  917. |
  918. |         C15  =  -6.6880 35109 81146 72325E-10
  919. DSINCN:
  920.         .long   0xBE06FADB,0x9F155744
  921. |         C13  =   5.6921 72921 96792 68118E-08
  922.         .long   0x3E6E8F43,0x4D018D63
  923. |         C11  =  -3.5988 43235 21208 53405E-06
  924.         .long   0xBECE3074,0xFDE8871F
  925. |         C09  =   1.6044 11847 87359 82187E-04
  926.         .long   0x3F250783,0x487EE782
  927. |         C07 =   -4.6817 54135 31868 81007E-03
  928.         .long   0xBF732D2C,0xCE62BD86
  929. |         C05  =   7.9692 62624 61670 45121E-02
  930.         .long   0x3FB466BC,0x6775AAE2
  931. |         C03  =  -6.4596 40975 06246 25366E-01
  932.         .long   0xBFE4ABBC,0xE625BE53
  933. |         C01  =   1.5707 96326 79489 66192E+00
  934. DPIO2:
  935.         .long   0x3FF921FB,0x54442D18
  936. |
  937. |       .set    NDSINC,8
  938. |
  939. |
  940. |
  941. |         Q3  =    1.7732 32244 08118 84863E+01
  942. DTNQCN:
  943.         .long   0x4031BB79,0x7BC569F8
  944. |         Q2  =   -8.0485 82645 07638 77427E+02
  945.         .long   0xC08926DD,0xB9C83D02
  946. |         Q1  =    6.4501 55566 23337 83845E+03
  947.         .long   0x40B93227,0xD3304CB9
  948. |         Q0  =   -5.6630 29630 56808 22115E+03
  949.         .long   0xC0B61F07,0x95DE70E0
  950. |
  951. |       .set    NDTNQC,4
  952. |
  953. |
  954. |         P3  =    1.0000 00000 00000 00000E+00
  955. DTNPCN:
  956.         .long   0x3FF00000,0x00000000
  957. |         P2  =   -1.5195 78275 66504 79235E+02
  958.         .long   0xC062FEA6,0x85FF2B0D
  959. |         P1  =    2.8156 53021 77302 44048E+03
  960.         .long   0x40A5FF4E,0x58DEAD6E
  961. |         P0  =   -8.8954 66142 22700 41047E+03
  962.         .long   0xC0C15FBB,0xAA8C6A22
  963. |
  964. |       .set    NDTNPC,4
  965. |
  966. |
  967. |         INV2PI  =  1 / 2*PI  =   1.5915 49430 91895 33577E-01
  968. DIN2PI:
  969.         .long   0x3FC45F30,0x6DC9C883
  970. |
  971. |
  972. | ###   PUBLIC  DPCOS
  973. |
  974. DPCOS:
  975.         bsr     DTRGSV          | Prepare argument for operation
  976. |
  977.         moveb   d0,d1           | Copy into d1
  978.         andib   #3,d0           | Strip sign bit
  979.         addqb   #1,d0
  980.         rorb    #2,d0           | Move sign bit to B7
  981.         moveb   d0,a7@(8)       | Save it
  982.         rorb    #1,d1
  983.         jcs     DSINOP          | Compute sine
  984. |
  985. |
  986. DCOSOP:
  987.         pea     DCOSCN
  988.         movel   sp@+,a6
  989.         moveq   #NDCOSC,d0
  990.         bsr     DX2SER
  991. |
  992. DTRGFN:
  993.         moveb   a7@(8),d0
  994.         andib   #0x80,d0                | Isolate sign bit
  995.         eorb    d0,sp@
  996. |
  997.         movel   a7@(4),a7@(8)
  998.         movel   sp@+,sp@
  999.         jmp     a4@
  1000. |
  1001. |
  1002. |
  1003. | ###   PUBLIC  DPSIN
  1004. |
  1005. DPSIN:
  1006.         bsr     DTRGSV          | Prepare argument
  1007. |
  1008.         addib   #0x7E,a7@(8)    | Compute sign
  1009.         rorb    #1,d0
  1010.         jcs     DCOSOP
  1011. |
  1012. |
  1013. DSINOP:
  1014.         movel   a7@(4),sp@-     | Duplicate argument
  1015.         movel   a7@(4),sp@-
  1016. |
  1017.         pea     DSINCN
  1018.         movel   sp@+,a6
  1019.         moveq   #NDSINC,d0
  1020.         bsr     DX2SER
  1021.         jsr     DPMUL
  1022. |
  1023.         jra     DTRGFN
  1024. |
  1025. |
  1026. |
  1027. | ###   PUBLIC  DPTAN
  1028. |
  1029. DPTAN:
  1030.         bsr     DTRGSV          | Prepare argument
  1031. |
  1032.         rorb    #1,d0
  1033.         andib   #0x80,d0
  1034.         eorb    d0,a7@(8)
  1035. |
  1036.         moveq   #4-1,d1         | Double duplication of argument
  1037. DPTN01:
  1038.         movel   a7@(4),sp@-
  1039.         dbra    d1,DPTN01
  1040. |
  1041.         pea     DTNPCN
  1042.         movel   sp@+,a6
  1043.         moveq   #NDTNPC,d0
  1044.         bsr     DX2SER
  1045.         jsr     DPMUL
  1046. |
  1047.         movel   a7@(8),d0
  1048.         movel   a7@(12),d1
  1049.         movel   sp@,a7@(8)
  1050.         movel   a7@(4),a7@(12)
  1051.         movel   d0,sp@
  1052.         movel   d1,a7@(4)
  1053. |
  1054.         pea     DTNQCN
  1055.         movel   sp@+,a6
  1056.         moveq   #NDTNQC,d0
  1057.         bsr     DX2SER
  1058. |
  1059.         btst    #0,a7@(16)
  1060.         jne     DPTN20          | J/ reverse division
  1061. |
  1062.         jsr     DPDIV
  1063.         jra     DTRGFN
  1064. |
  1065. DPTN20:
  1066.         jsr     DPRDIV
  1067.         jra     DTRGFN
  1068. /*
  1069. |
  1070. |       page
  1071. |
  1072. |  Trigonometric Service Routine
  1073. |
  1074. |  The double precision floating point value to be processed is on the
  1075. |  stack.  Excess 2 PI's are removed from the argument.  The range of
  1076. |  the argument is then scaled to within PI/4 of 0.  The shift size
  1077. |  (in number of quadrants) is returned in D0.  The original sign bit
  1078. |  is returned in the D0.B sign bit.
  1079. |
  1080. |  If the argument is NaN, +INF, -INF, or too large (>= 2^16), this
  1081. |  routine causes a return to the caller with a NaN result.
  1082. |
  1083. */
  1084. DTRGSV:
  1085.         moveal  sp@+,a6 | DTRGSV return addr
  1086. |
  1087.         bsr     DPFADJ
  1088.         jcs     DFNANR          | Return NAN if +/- INF
  1089.         jvs     DFNANR          | Return NaN if NaN
  1090. |
  1091.         clrw    a7@(8)          | Create arg type return byte
  1092. |
  1093.         roxlw   sp@             | Sign bit into X
  1094.         roxrw   a7@(8)          | Sign bit into temp byte
  1095.         roxrw   sp@             | Restore DP value (with sign = +)
  1096. |
  1097.         cmpiw   #16*DBIAS+256,sp@
  1098.         jge     DFNANR          | J/ return NaN if ABS(arg) >= 2^16
  1099. |
  1100.         movel   DIN2PI+4,sp@-   | Scale arg by 1/(2*PI)
  1101.         movel   DIN2PI+0,sp@-
  1102.         jsr     DPMUL
  1103. |
  1104.         cmpiw   #16*DBIAS,sp@
  1105.         jlt     DTS10           | /* J/ no excess two PI's */
  1106. |
  1107.         movel   a7@(4),sp@-     | Double the scaled argument
  1108.         movel   a7@(4),sp@-
  1109.         jsr     DINT
  1110.         negl    d1
  1111.         negxl   d0
  1112.         jsr     DFLOAT
  1113.         jsr     DPADD
  1114. |
  1115. DTS10:
  1116.         tstw    sp@
  1117.         jeq     DTS20
  1118. |
  1119.         addiw   #16*3,sp@       | Multiply value by 8
  1120.         cmpiw   #16*DBIAS,sp@
  1121.         jlt     DTS20           | J/ < 1
  1122. |
  1123.         movel   a7@(4),sp@-     | Double parameter
  1124.         movel   a7@(4),sp@-
  1125.         jsr     DINT
  1126.         addqb   #1,d1
  1127.         lsrb    #1,d1
  1128.         addb    d1,a7@(8)       | Mix quadrant number with sign bit
  1129. |
  1130.         lslb    #1,d1
  1131.         negl    d1
  1132.         negxl   d0
  1133.         jsr     DFLOAT
  1134.         jsr     DPADD
  1135. |
  1136. DTS20:
  1137.         tstw    sp@
  1138.         jeq     DTS30           | J/ arg = 0.0
  1139. |
  1140.         subiw   #16*1,sp@       | Range result to -0.5 to 0.5
  1141. |
  1142. DTS30:
  1143.         andib   #0x83,a7@(8)    | Limit quadrant shift to 0 thru 3
  1144.         moveb   a7@(8),d0       | Return cntl byte in d0 and at a7@(8)
  1145.         jmp     a6@
  1146. /*
  1147. |
  1148. | ###   SUBTTL  Polynomial Evaluation Routine
  1149. |       page
  1150. |
  1151. |  Polynomial Evaluation Routines.
  1152. |
  1153. |  A list of constants is pointed to by A6.  X is on the stack.  D0
  1154. |  contains the number of constants (the polynomial degree plus one).
  1155. |
  1156. |  A6 enters pointing to C[1].  Upon return, the value on stack has
  1157. |  been replaced with:
  1158. |  DXSER   = C[1]*X^(N-1)  + C[2]*X^(N-2)  + ... + C[N-1]*X   + C[N]
  1159. |
  1160. |  DX2SER  = C[1]*X^(2N-2) + C[2]*X^(2N-4) + ... + C[N-1]*X^2 + C[N]
  1161. |
  1162. |
  1163. */
  1164. DX2SER:
  1165.         moveal  a4,a5           | Save a4 in a5
  1166.         bsr     DPFADJ
  1167. |
  1168.         moveb   d0,a7@(8)       | Save count
  1169. |
  1170.         movel   a7@(4),sp@-     | Square the argument
  1171.         movel   a7@(4),sp@-
  1172.         jsr     DPMUL
  1173.         jra     DXSR01          | J/ join DXSER routine
  1174. |
  1175. DXSER:
  1176.         moveal  a4,a5
  1177.         bsr     DPFADJ
  1178. |
  1179.         moveb   d0,a7@(8)
  1180. |
  1181. DXSR01:
  1182.         movel   a6@(4),sp@-     | Place C[1] on stack as accum
  1183.         movel   a6@,sp@-
  1184.         addql   #8,a6
  1185. |
  1186.         subqb   #1,a7@(16)
  1187. |
  1188. DXSR02:
  1189.         movel   a7@(12),sp@-    | Copy X
  1190.         movel   a7@(12),sp@-
  1191.         jsr     DPMUL
  1192.         movel   a6@(4),sp@-     | Add in next coefficient
  1193.         movel   a6@,sp@-
  1194.         addql   #8,a6           | Advance to next coefficient
  1195.         jsr     DPADD
  1196. |
  1197.         subqb   #1,a7@(16)
  1198.         jne     DXSR02          | J/ more coefficients
  1199. |
  1200.         movel   a7@(4),a7@(16)  | Adjust return
  1201.         movel   sp@+,a7@(8)
  1202.         addql   #8,sp
  1203. |
  1204.         moveal  a4,a3
  1205.         moveal  a5,a4           | Restore return address
  1206.         jmp     a3@
  1207. /*
  1208. |
  1209. | ###   SUBTTL  Function Completion Segments
  1210. |       page
  1211. |
  1212. |  DPFADJ - Adjust the stack for double precision functions.
  1213. |          Move the return address to the function caller into A4.
  1214. |          Shift the double precision floating point argument down
  1215. |          four bytes, leaving a temporary area of four bytes at
  1216. |          8(A7) thru 11(A7).  Set the condition code bits N, Z,
  1217. |          C (INF), and V (NaN) to quickly type the argument.
  1218. |
  1219. */
  1220. DPFADJ:
  1221.         moveal  sp@+,a3 | Function return addr
  1222.         moveal  sp@,a4          | Caller return addr
  1223.         movel   a7@(4),sp@      | Down shift parameter
  1224.         movel   a7@(8),a7@(4)
  1225. |
  1226.         movew   sp@,d2          | Get SEM word
  1227.         rolw    #1,d2
  1228.         cmpiw   #32*0x7FF,d2
  1229.         jcs     DPFA10          | J/ not INF or NaN
  1230. |
  1231.         andiw   #0x1E,d2
  1232.         jeq     DPFA05
  1233. |
  1234.         orib    #0x02,ccr       | Set -V- bit -> NaN argument
  1235.         jmp     a3@
  1236. |
  1237. DPFA05:
  1238.         tstb    sp@             | /* Set N bit as req'd, clear Z bit. */
  1239.         orib    #0x01,ccr       | Set -C- bit -> INF argument
  1240.         jmp     a3@
  1241. |
  1242. DPFA10:
  1243.         tstw    sp@             | /* Set N, Z bits as req'd, clear V, C */
  1244.         jmp     a3@
  1245. |
  1246. |
  1247. |
  1248. DFPINR:
  1249.         |dsw    0               | Result is positive overflow
  1250.         moveq   #0,d0           | Sign is positive
  1251.         jra     DFIN01
  1252. |
  1253. DFMINR:
  1254.         |dsw    0               | Result in negative overflow
  1255.         moveq   #-1,d0          | Sign is negative
  1256. |
  1257. DFIN01:
  1258.         moveaw  d0,a2           | Sign into a2
  1259.         addql   #8,sp           | Delete twelve bytes from the stack
  1260.         addql   #4,sp
  1261.         moveal  a4,a0           | Return addr in a0
  1262.         jmp     DINFRS          | (Use DPOPNS exception return)
  1263. |
  1264. |
  1265. DFNANR:
  1266.         |dsw    0               | Result is NaN
  1267.         addql   #8,sp           | Delete twelve bytes from the stack
  1268.         addql   #4,sp
  1269.         moveal  a4,a0
  1270.         jmp     DNANRS
  1271. |
  1272. |
  1273. DFZERR:
  1274.         |dsw    0               | Result is zero
  1275.         addql   #8,sp
  1276.         addql   #4,sp
  1277.         moveal  a4,a0
  1278.         jmp     DZERRS
  1279. |
  1280. |
  1281. DFUNFR:
  1282.         |dsw    0               | Underflow result
  1283.         addql   #8,sp           | Delete twelve bytes from the stack
  1284.         addql   #4,sp
  1285.         moveal  a4,a0           | Return address into a0
  1286.         jmp     DUNFRS
  1287. |
  1288. |
  1289. DFONER:
  1290.         |dsw    0               | Result is 1.0
  1291.         addql   #4,sp
  1292.         movel   #0x3FF00000,sp@
  1293.         clrl    a7@(4)
  1294.         clrb    FPERR
  1295.         jmp     a4@
  1296. |
  1297. |       end