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

VxWorks

开发平台:

C/C++

  1. /* ssin.s - Motorola 68040 FP sine routines (EXC) */
  2. /* Copyright 1991-1993 Wind River Systems, Inc. */
  3. .data
  4. .globl _copyright_wind_river
  5. .long _copyright_wind_river
  6. /*
  7. modification history
  8. --------------------
  9. 01f,21jul93,kdl  added .text (SPR #2372).
  10. 01e,23aug92,jcf  changed bxxx to jxx.
  11. 01d,26may92,rrr  the tree shuffle
  12. 01c,10jan92,kdl  added modification history; general cleanup.
  13. 01b,17dec91,kdl  put in changes from Motorola v3.3 (from FPSP 2.1):
  14.  reduce argument by one step before general reduction
  15.  loop.
  16. 01a,15aug91,kdl  original version, from Motorola FPSP v2.0.
  17. */
  18. /*
  19. DESCRIPTION
  20. ssinsa 3.2 12/18/90
  21.  WIND RIVER MODIFICATION HISTORY
  22.  01a,31jul91,kdl from Motorola FPSP v2.0.
  23. The entry point sSIN computes the sine of an input argument
  24. sCOS computes the cosine, and sSINCOS computes both. The
  25. corresponding entry points with a "d" computes the same
  26. corresponding function values for denormalized inputs.
  27. Input: Double-extended number X in location pointed to
  28. by address register a0.
  29. Output: The funtion value sin(X) or cos(X) returned in Fp0 if SIN or
  30. COS is requested. Otherwise, for SINCOS, sin(X) is returned
  31. in Fp0, and cos(X) is returned in Fp1.
  32. Modifies: Fp0 for SIN or COS|  both Fp0 and Fp1 for SINCOS.
  33. Accuracy and Monotonicity: The returned result is within 1 ulp in
  34. 64 significant bit, i.e. within 0.5001 ulp to 53 bits if the
  35. result is subsequently rounded to double precision. The
  36. result is provably monotonic in double precision.
  37. Speed: The programs sSIN and sCOS take approximately 150 cycles for
  38. input argument X such that |X| < 15Pi, which is the the usual
  39. situation. The speed for sSINCOS is approximately 190 cycles.
  40. Algorithm:
  41. SIN and COS:
  42. 1. If SIN is invoked, set AdjN := 0|  otherwise, set AdjN := 1.
  43. 2. If |X| >= 15Pi or |X| < 2**(-40), go to 7.
  44. 3. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let
  45. k = N mod 4, so in particular, k = 0,1,2,or 3. Overwirte
  46. k by k := k + AdjN.
  47. 4. If k is even, go to 6.
  48. 5. (k is odd) Set j := (k-1)/2, sgn := (-1)**j. Return sgn*cos(r)
  49. where cos(r) is approximated by an even polynomial in r,
  50. 1 + r*r*(B1+s*(B2+ |... + s*B8)), s = r*r.
  51. Exit.
  52. 6. (k is even) Set j := k/2, sgn := (-1)**j. Return sgn*sin(r)
  53. where sin(r) is approximated by an odd polynomial in r
  54. r + r*s*(A1+s*(A2+ |... + s*A7)), s = r*r.
  55. Exit.
  56. 7. If |X| > 1, go to 9.
  57. 8. (|X|<2**(-40)) If SIN is invoked, return X|  otherwise return 1.
  58. 9. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi, go back to 3.
  59. SINCOS:
  60. 1. If |X| >= 15Pi or |X| < 2**(-40), go to 6.
  61. 2. Decompose X as X = N(Pi/2) + r where |r| <= Pi/4. Let
  62. k = N mod 4, so in particular, k = 0,1,2,or 3.
  63. 3. If k is even, go to 5.
  64. 4. (k is odd) Set j1 := (k-1)/2, j2 := j1 (EOR) (k mod 2), i.e.
  65. j1 exclusive or with the ls.b. of k.
  66. sgn1 := (-1)**j1, sgn2 := (-1)**j2.
  67. SIN(X) = sgn1 * cos(r) and COS(X) = sgn2*sin(r) where
  68. sin(r) and cos(r) are computed as odd and even polynomials
  69. in r, respectively. Exit
  70. 5. (k is even) Set j1 := k/2, sgn1 := (-1)**j1.
  71. SIN(X) = sgn1 * sin(r) and COS(X) = sgn1*cos(r) where
  72. sin(r) and cos(r) are computed as odd and even polynomials
  73. in r, respectively. Exit
  74. 6. If |X| > 1, go to 8.
  75. 7. (|X|<2**(-40)) SIN(X) = X and COS(X) = 1. Exit.
  76. 8. Overwrite X by X := X rem 2Pi. Now that |X| <= Pi, go back to 2.
  77. Copyright (C) Motorola, Inc. 1990
  78. All Rights Reserved
  79. THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
  80. The copyright notice above does not evidence any
  81. actual or intended publication of such source code.
  82. SSIN idnt 2,1 Motorola 040 Floating Point Software Package
  83. section 8
  84. NOMANUAL
  85. */
  86. #include "fpsp040E.h"
  87. BOUNDS1: .long 0x3FD78000,0x4004BC7E
  88. TWOBYPI: .long 0x3FE45F30,0x6DC9C883
  89. SINA7: .long 0xBD6AAA77,0xCCC994F5
  90. SINA6: .long 0x3DE61209,0x7AAE8DA1
  91. SINA5: .long 0xBE5AE645,0x2A118AE4
  92. SINA4: .long 0x3EC71DE3,0xA5341531
  93. SINA3: .long 0xBF2A01A0,0x1A018B59,0x00000000,0x00000000
  94. SINA2: .long 0x3FF80000,0x88888888,0x888859AF,0x00000000
  95. SINA1: .long 0xBFFC0000,0xAAAAAAAA,0xAAAAAA99,0x00000000
  96. COSB8: .long 0x3D2AC4D0,0xD6011EE3
  97. COSB7: .long 0xBDA9396F,0x9F45AC19
  98. COSB6: .long 0x3E21EED9,0x0612C972
  99. COSB5: .long 0xBE927E4F,0xB79D9FCF
  100. COSB4: .long 0x3EFA01A0,0x1A01D423,0x00000000,0x00000000
  101. COSB3: .long 0xBFF50000,0xB60B60B6,0x0B61D438,0x00000000
  102. COSB2: .long 0x3FFA0000,0xAAAAAAAA,0xAAAAAB5E
  103. COSB1: .long 0xBF000000
  104. INVTWOPI: .long 0x3FFC0000,0xA2F9836E,0x4E44152A
  105. TWOPI1: .long 0x40010000,0xC90FDAA2,0x00000000,0x00000000
  106. TWOPI2: .long 0x3FDF0000,0x85A308D4,0x00000000,0x00000000
  107. | xref __x_PITBL
  108. #define INARG FP_SCR4
  109. #define X FP_SCR5
  110. #define XDCARE X+2
  111. #define XFRAC X+4
  112. #define RPRIME FP_SCR1
  113. #define SPRIME FP_SCR2
  114. #define POSNEG1 L_SCR1
  115. #define TWOTO63 L_SCR1
  116. #define ENDFLAG L_SCR2
  117. #define N L_SCR2
  118. #define ADJN L_SCR3
  119. | xref __x_t_frcinx
  120. | xref __x_t_extdnrm
  121. | xref __x_sto_cos
  122. .text
  123. .globl __x_ssind
  124. __x_ssind:
  125. |--SIN(X) = X FOR DENORMALIZED X
  126. jra  __x_t_extdnrm
  127. .globl __x_scosd
  128. __x_scosd:
  129. |--COS(X) = 1 FOR DENORMALIZED X
  130. /* fmoves &0x3F800000,fp0 */  .long 0xf23c4400,0x3f800000
  131. |
  132. | 9D25B Fix: Sometimes the previous fmoves sets fpsr bits
  133. |
  134. fmovel #0,fpsr
  135. |
  136. jra  __x_t_frcinx
  137. .globl __x_ssin
  138. __x_ssin:
  139. |--SET ADJN TO 0
  140. movel #0,a6@(ADJN)
  141. jra  SINBGN
  142. .globl __x_scos
  143. __x_scos:
  144. |--SET ADJN TO 1
  145. movel #1,a6@(ADJN)
  146. SINBGN:
  147. |--SAVE fpcr, FP1. CHECK IF |X| IS TOO SMALL OR LARGE
  148. fmovex a0@,fp0 |...lOAD INPUT
  149. movel A0@,d0
  150. movew A0@(4),d0
  151. fmovex fp0,a6@(X)
  152. andil #0x7FFFFFFF,d0 |...COMPACTIFY X
  153. cmpil #0x3FD78000,d0 |...|X| >= 2**(-40)?
  154. jge  SOK1
  155. jra  SINSM
  156. SOK1:
  157. cmpil #0x4004BC7E,d0 |...|X| < 15 PI?
  158. jlt  SINMAIN
  159. jra  REDUCEX
  160. SINMAIN:
  161. |--THIS IS THE USUAL CASE, |X| <= 15 PI.
  162. |--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP.
  163. fmovex fp0,fp1
  164. fmuld TWOBYPI,fp1 |...X*2/PI
  165. |--HIDE THE NEXT THREE INSTRUCTIONS
  166. lea __x_PITBL+0x200,a1 |...TABLE OF N*PI/2, N = -32,...,32
  167. |--FP1 IS NOW READY
  168. fmovel fp1,a6@(N) |...CONVERT TO INTEGER
  169. movel a6@(N),d0
  170. asll #4,d0
  171. addal d0,a1 |...A1 IS THE ADDRESS OF N*PIBY2
  172. | |...wHICH IS IN TWO PIECES Y1 # Y2
  173. fsubx A1@+,fp0 |...X-Y1
  174. |--HIDE THE NEXT ONE
  175. fsubs A1@,fp0 |...FP0 IS R = (X-Y1)-Y2
  176. SINCONT:
  177. |--continuation from REDUCEX
  178. |--GET N+ADJN AND SEE IF SIN(R) OR COS(R) IS NEEDED
  179. movel a6@(N),d0
  180. addl a6@(ADJN),d0 |...SEE IF d0 IS ODD OR EVEN
  181. rorl #1,d0 |...D0 WAS ODD IFF d0 IS NEGATIVE
  182. cmpil #0,d0
  183. jlt  COSPOLY
  184. SINPOLY:
  185. |--LET J BE THE LEAST SIG. BIT OF D0, LET SGN := (-1)**J.
  186. |--THEN WE RETURN SGN*SIN(R). SGN*SIN(R) IS COMPUTED BY
  187. /* |--R' + R'*S*(A1 + S(A2 + S(A3 + S(A4 + |... + SA7)))), WHERE */
  188. /* |--R' = SGN*R, S=R*R. THIS CAN BE REWRITTEN AS */
  189. /* |--R' + R'*S*( [A1+T(A3+T(A5+TA7))] + [S(A2+T(A4+TA6))]) */
  190. |--WHERE T=S*S.
  191. |--NOTE THAT A3 THROUGH A7 ARE STORED IN DOUBLE PRECISION
  192. |--WHILE A1 AND A2 ARE IN DOUBLE-EXTENDED FORMAT.
  193. fmovex fp0,a6@(X) |...X IS R
  194. fmulx fp0,fp0 |...FP0 IS S
  195. |---HIDE THE NEXT TWO WHILE WAITING FOR FP0
  196. fmoved SINA7,fp3
  197. fmoved SINA6,fp2
  198. |--FP0 IS NOW READY
  199. fmovex fp0,fp1
  200. fmulx fp1,fp1 |...FP1 IS T
  201. |--HIDE THE NEXT TWO WHILE WAITING FOR FP1
  202. rorl #1,d0
  203. andil #0x80000000,d0
  204. | |...lEAST SIG. BIT OF D0 IN SIGN POSITION
  205. eorl d0,a6@(X) /* |...X IS NOW R'= SGN*R */
  206. fmulx fp1,fp3 |...TA7
  207. fmulx fp1,fp2 |...TA6
  208. faddd SINA5,fp3 |...A5+TA7
  209. faddd SINA4,fp2 |...A4+TA6
  210. fmulx fp1,fp3 |...T(A5+TA7)
  211. fmulx fp1,fp2 |...T(A4+TA6)
  212. faddd SINA3,fp3 |...A3+T(A5+TA7)
  213. faddx SINA2,fp2 |...A2+T(A4+TA6)
  214. fmulx fp3,fp1 |...T(A3+T(A5+TA7))
  215. fmulx fp0,fp2 |...S(A2+T(A4+TA6))
  216. faddx SINA1,fp1 |...A1+T(A3+T(A5+TA7))
  217. fmulx a6@(X),fp0 /* |...R'*S */
  218. faddx fp2,fp1 |...[A1+T(A3+T(A5+TA7))]+[S(A2+T(A4+TA6))]
  219. |--FP3 RELEASED, RESTORE NOW AND TAKE SOME ADVANTAGE OF HIDING
  220. |--FP2 RELEASED, RESTORE NOW AND TAKE FULL ADVANTAGE OF HIDING
  221. fmulx fp1,fp0 /* |...SIN(R')-R' */
  222. |--FP1 RELEASED.
  223. fmovel d1,fpcr | restore users exceptions
  224. faddx a6@(X),fp0 | last inst - possible exception set
  225. jra  __x_t_frcinx
  226. COSPOLY:
  227. |--LET J BE THE LEAST SIG. BIT OF D0, LET SGN := (-1)**J.
  228. |--THEN WE RETURN SGN*COS(R). SGN*COS(R) IS COMPUTED BY
  229. /* |--SGN + S'*(B1 + S(B2 + S(B3 + S(B4 + |... + SB8)))), WHERE */
  230. /* |--S=R*R AND S'=SGN*S. THIS CAN BE REWRITTEN AS */
  231. /* |--SGN + S'*([B1+T(B3+T(B5+TB7))] + [S(B2+T(B4+T(B6+TB8)))]) */
  232. |--WHERE T=S*S.
  233. |--NOTE THAT B4 THROUGH B8 ARE STORED IN DOUBLE PRECISION
  234. |--WHILE B2 AND B3 ARE IN DOUBLE-EXTENDED FORMAT, B1 IS -1/2
  235. |--AND IS THEREFORE STORED AS SINGLE PRECISION.
  236. fmulx fp0,fp0 |...FP0 IS S
  237. |---HIDE THE NEXT TWO WHILE WAITING FOR FP0
  238. fmoved COSB8,fp2
  239. fmoved COSB7,fp3
  240. |--FP0 IS NOW READY
  241. fmovex fp0,fp1
  242. fmulx fp1,fp1 |...FP1 IS T
  243. |--HIDE THE NEXT TWO WHILE WAITING FOR FP1
  244. fmovex fp0,a6@(X) |...X IS S
  245. rorl #1,d0
  246. andil #0x80000000,d0
  247. | |...lEAST SIG. BIT OF D0 IN SIGN POSITION
  248. fmulx fp1,fp2 |...TB8
  249. |--HIDE THE NEXT TWO WHILE WAITING FOR THE XU
  250. eorl d0,a6@(X) /* |...X IS NOW S'= SGN*S */
  251. andil #0x80000000,d0
  252. fmulx fp1,fp3 |...TB7
  253. |--HIDE THE NEXT TWO WHILE WAITING FOR THE XU
  254. oril #0x3F800000,d0 |...D0 IS SGN IN SINGLE
  255. movel d0,a6@(POSNEG1)
  256. faddd COSB6,fp2 |...B6+TB8
  257. faddd COSB5,fp3 |...B5+TB7
  258. fmulx fp1,fp2 |...T(B6+TB8)
  259. fmulx fp1,fp3 |...T(B5+TB7)
  260. faddd COSB4,fp2 |...B4+T(B6+TB8)
  261. faddx COSB3,fp3 |...B3+T(B5+TB7)
  262. fmulx fp1,fp2 |...T(B4+T(B6+TB8))
  263. fmulx fp3,fp1 |...T(B3+T(B5+TB7))
  264. faddx COSB2,fp2 |...B2+T(B4+T(B6+TB8))
  265. fadds COSB1,fp1 |...B1+T(B3+T(B5+TB7))
  266. fmulx fp2,fp0 |...S(B2+T(B4+T(B6+TB8)))
  267. |--FP3 RELEASED, RESTORE NOW AND TAKE SOME ADVANTAGE OF HIDING
  268. |--FP2 RELEASED.
  269. faddx fp1,fp0
  270. |--FP1 RELEASED
  271. fmulx a6@(X),fp0
  272. fmovel d1,fpcr | restore users exceptions
  273. fadds a6@(POSNEG1),fp0 | last inst - possible exception set
  274. jra  __x_t_frcinx
  275. SINBORS:
  276. |--IF |X| > 15PI, WE USE THE GENERAL ARGUMENT REDUCTION.
  277. |--IF |X| < 2**(-40), RETURN X OR 1.
  278. cmpil #0x3FFF8000,d0
  279. jgt  REDUCEX
  280. SINSM:
  281. movel a6@(ADJN),d0
  282. cmpil #0,d0
  283. jgt  COSTINY
  284. SINTINY:
  285. movew #0x0000,a6@(XDCARE) |...JUST IN CASE
  286. fmovel d1,fpcr | restore users exceptions
  287. fmovex a6@(X),fp0 | last inst - possible exception set
  288. jra  __x_t_frcinx
  289. COSTINY:
  290. .long 0xf23c4400,0x3f800000 /*  fmoves  &0x3F800000,fp0 */
  291. fmovel d1,fpcr | restore users exceptions
  292. .long 0xf23c4428,0x00800000 /*  fsubs  &0x00800000,fp0 */
  293. jra  __x_t_frcinx
  294. REDUCEX:
  295. |--WHEN REDUCEX IS USED, THE CODE WILL INEVITABLY BE SLOW.
  296. |--THIS REDUCTION METHOD, HOWEVER, IS MUCH FASTER THAN USING
  297. |--THE REMAINDER INSTRUCTION WHICH IS NOW IN SOFTWARE.
  298. fmovemx fp2-fp5,A7@- |...save fp2 through fp5
  299. movel d2,A7@-
  300. /* fmoves &0x00000000,fp1 */  .long 0xf23c4480,0x00000000
  301. |--If compact form of abs(arg) in d0=0x7ffeffff, argument is so large that
  302. |--there is a danger of unwanted overflow in first LOOP iteration.  In this
  303. |--case, reduce argument by one remainder step to make subsequent reduction
  304. |--safe.
  305. cmpil #0x7ffeffff,d0 | is argument dangerously large?
  306. jne  LOOP
  307. movel #0x7ffe0000,a6@(FP_SCR2) | yes
  308. | | create 2**16383*PI/2
  309. movel #0xc90fdaa2,a6@(FP_SCR2+4)
  310. clrl a6@(FP_SCR2+8)
  311. ftstx fp0 | test sign of argument
  312. movel #0x7fdc0000,a6@(FP_SCR3) | create low half of 2**16383*
  313. | | PI/2 at FP_SCR3
  314. movel #0x85a308d3,a6@(FP_SCR3+4)
  315. clrl   a6@(FP_SCR3+8)
  316. fblt red_neg
  317. orw #0x8000,a6@(FP_SCR2) | positive arg
  318. orw #0x8000,a6@(FP_SCR3)
  319. red_neg:
  320. faddx  a6@(FP_SCR2),fp0 | high part of reduction is exact
  321. fmovex  fp0,fp1 | save high result in fp1
  322. faddx  a6@(FP_SCR3),fp0 | low part of reduction
  323. fsubx   fp0,fp1 | determine low component of result
  324. faddx  a6@(FP_SCR3),fp1 | fp0/fp1 are reduced argument.
  325. |--ON ENTRY, FP0 IS X, ON RETURN, FP0 IS X REM PI/2, |X| <= PI/4.
  326. |--integer quotient will be stored in N
  327. |--Intermeditate remainder is 66-bit long|  (R,r) in (FP0,FP1)
  328. LOOP:
  329. fmovex fp0,a6@(INARG) |...+-2**K * F, 1 <= F < 2
  330. movew a6@(INARG),d0
  331.         movel          d0,a1 |...save a copy of d0
  332. andil #0x00007FFF,d0
  333. subil #0x00003FFF,d0 |...D0 IS K
  334. cmpil #28,d0
  335. jle  LASTLOOP
  336. CONTLOOP:
  337. subil #27,d0  |...D0 IS L := K-27
  338. movel #0,a6@(ENDFLAG)
  339. jra  WORK
  340. LASTLOOP:
  341. clrl d0 |...D0 IS L := 0
  342. movel #1,a6@(ENDFLAG)
  343. WORK:
  344. |--FIND THE REMAINDER OF (R,r) W.R.T. 2**L * (PI/2). L IS SO CHOSEN
  345. |--THAT INT( X * (2/PI) / 2**(L) ) < 2**29.
  346. |--CREATE 2**(-L) * (2/PI), SIGN(INARG)*2**(63),
  347. |--2**L * (PIby2_1), 2**L * (PIby2_2)
  348. movel #0x00003FFE,d2 |...BIASED EXPO OF 2/PI
  349. subl d0,d2 |...BIASED EXPO OF 2**(-L)*(2/PI)
  350. movel #0xA2F9836E,a6@(FP_SCR1+4)
  351. movel #0x4E44152A,a6@(FP_SCR1+8)
  352. movew d2,a6@(FP_SCR1) |...FP_SCR1 is 2**(-L)*(2/PI)
  353. fmovex fp0,fp2
  354. fmulx a6@(FP_SCR1),fp2
  355. |--WE MUST NOW FIND INT(FP2). SINCE WE NEED THIS VALUE IN
  356. /* |--FLOATING POINT FORMAT, THE TWO FMOVE'S FMOVE.l FP <--> N */
  357. |--WILL BE TOO INEFFICIENT. THE WAY AROUND IT IS THAT
  358. |--(SIGN(INARG)*2**63 + FP2) - SIGN(INARG)*2**63 WILL GIVE
  359. |--US THE DESIRED VALUE IN FLOATING POINT.
  360. |--HIDE SIX CYCLES OF INSTRUCTION
  361.         movel a1,d2
  362.         swap d2
  363. andil #0x80000000,d2
  364. oril #0x5F000000,d2 |...D2 IS SIGN(INARG)*2**63 IN SGL
  365. movel d2,a6@(TWOTO63)
  366. movel d0,d2
  367. addil #0x00003FFF,d2 |...BIASED EXPO OF 2**L * (PI/2)
  368. |--FP2 IS READY
  369. fadds a6@(TWOTO63),fp2 |...THE FRACTIONAL PART OF fp1 IS ROUNDED
  370. |--HIDE 4 CYCLES OF INSTRUCTION|  creating 2**(L)*Piby2_1  and  2**(L)*Piby2_2
  371.         movew d2,a6@(FP_SCR2)
  372. clrw           a6@(FP_SCR2+2)
  373. movel #0xC90FDAA2,a6@(FP_SCR2+4)
  374. clrl a6@(FP_SCR2+8) |...FP_SCR2 is  2**(L) * Piby2_1
  375. |--FP2 IS READY
  376. fsubs a6@(TWOTO63),fp2 |...FP2 is N
  377. addil #0x00003FDD,d0
  378.         movew d0,a6@(FP_SCR3)
  379. clrw           a6@(FP_SCR3+2)
  380. movel #0x85A308D3,a6@(FP_SCR3+4)
  381. clrl a6@(FP_SCR3+8) |...FP_SCR3 is 2**(L) * Piby2_2
  382. movel a6@(ENDFLAG),d0
  383. |--We are now ready to perform (R+r) - N*P1 - N*P2, P1 = 2**(L) * Piby2_1 and
  384. |--P2 = 2**(L) * Piby2_2
  385. fmovex fp2,fp4
  386. fmulx a6@(FP_SCR2),fp4 |...w = N*P1
  387. fmovex fp2,fp5
  388. fmulx a6@(FP_SCR3),fp5 |...w = N*P2
  389. fmovex fp4,fp3
  390. |--we want P+p = W+w  but  |p| <= half ulp of P
  391. |--Then, we need to compute  A := R-P   and  a := r-p
  392. faddx fp5,fp3 |...FP3 is P
  393. fsubx fp3,fp4 |...w-P
  394. fsubx fp3,fp0 |...FP0 is A := R - P
  395.         faddx fp5,fp4 |...FP4 is p = (W-P)+w
  396. fmovex fp0,fp3 |...FP3 A
  397. fsubx fp4,fp1 |...FP1 is a := r - p
  398. |--Now we need to normalize (A,a) to  "new (R,r)" where R+r = A+a but
  399. |--|r| <= half ulp of R.
  400. faddx fp1,fp0 |...FP0 is R := A+a
  401. |--No need to calculate r if this is the last loop
  402. cmpil #0,d0
  403. jgt  RESTORE
  404. |--Need to calculate r
  405. fsubx fp0,fp3 |...A-R
  406. faddx fp3,fp1 |...FP1 is r := (A-R)+a
  407. jra  LOOP
  408. RESTORE:
  409.         fmovel fp2,a6@(N)
  410. movel A7@+,d2
  411. fmovemx A7@+,fp2-fp5
  412. movel a6@(ADJN),d0
  413. cmpil #4,d0
  414. jlt  SINCONT
  415. jra  SCCONT
  416. .globl __x_ssincosd
  417. __x_ssincosd:
  418. |--SIN AND COS OF X FOR DENORMALIZED X
  419. .long 0xf23c4480,0x3f800000 /*  fmoves  &0x3F800000,fp1 */
  420. bsrl __x_sto_cos | store cosine result
  421. jra  __x_t_extdnrm
  422. .globl __x_ssincos
  423. __x_ssincos:
  424. |--SET ADJN TO 4
  425. movel #4,a6@(ADJN)
  426. fmovex a0@,fp0 |...lOAD INPUT
  427. movel A0@,d0
  428. movew A0@(4),d0
  429. fmovex fp0,a6@(X)
  430. andil #0x7FFFFFFF,d0 |...COMPACTIFY X
  431. cmpil #0x3FD78000,d0 |...|X| >= 2**(-40)?
  432. jge  SCOK1
  433. jra  SCSM
  434. SCOK1:
  435. cmpil #0x4004BC7E,d0 |...|X| < 15 PI?
  436. jlt  SCMAIN
  437. jra  REDUCEX
  438. SCMAIN:
  439. |--THIS IS THE USUAL CASE, |X| <= 15 PI.
  440. |--THE ARGUMENT REDUCTION IS DONE BY TABLE LOOK UP.
  441. fmovex fp0,fp1
  442. fmuld TWOBYPI,fp1 |...X*2/PI
  443. |--HIDE THE NEXT THREE INSTRUCTIONS
  444. lea __x_PITBL+0x200,a1 |...TABLE OF N*PI/2, N = -32,...,32
  445. |--FP1 IS NOW READY
  446. fmovel fp1,a6@(N) |...CONVERT TO INTEGER
  447. movel a6@(N),d0
  448. asll #4,d0
  449. addal d0,a1 |...ADDRESS OF N*PIBY2, IN Y1, Y2
  450. fsubx A1@+,fp0 |...X-Y1
  451.         fsubs A1@,fp0 |...FP0 IS R = (X-Y1)-Y2
  452. SCCONT:
  453. |--continuation point from REDUCEX
  454. |--HIDE THE NEXT TWO
  455. movel a6@(N),d0
  456. rorl #1,d0
  457. cmpil #0,d0 |...D0 < 0 IFF N IS ODD
  458. jge  NEVEN
  459. NODD:
  460. |--REGISTERS SAVED SO FAR: D0, A0, FP2.
  461. fmovex fp0,a6@(RPRIME)
  462. fmulx fp0,fp0   |...FP0 IS S = R*R
  463. fmoved SINA7,fp1 |...A7
  464. fmoved COSB8,fp2 |...B8
  465. fmulx fp0,fp1   |...SA7
  466. movel d2,A7@-
  467. movel d0,d2
  468. fmulx fp0,fp2   |...SB8
  469. rorl #1,d2
  470. andil #0x80000000,d2
  471. faddd SINA6,fp1 |...A6+SA7
  472. eorl d0,d2
  473. andil #0x80000000,d2
  474. faddd COSB7,fp2 |...B7+SB8
  475. fmulx fp0,fp1   |...S(A6+SA7)
  476. eorl d2,a6@(RPRIME)
  477. movel A7@+,d2
  478. fmulx fp0,fp2   |...S(B7+SB8)
  479. rorl #1,d0
  480. andil #0x80000000,d0
  481. faddd SINA5,fp1 |...A5+S(A6+SA7)
  482. movel #0x3F800000,a6@(POSNEG1)
  483. eorl d0,a6@(POSNEG1)
  484. faddd COSB6,fp2 |...B6+S(B7+SB8)
  485. fmulx fp0,fp1   |...S(A5+S(A6+SA7))
  486. fmulx fp0,fp2   |...S(B6+S(B7+SB8))
  487. fmovex fp0,a6@(SPRIME)
  488. faddd SINA4,fp1 |...A4+S(A5+S(A6+SA7))
  489. eorl d0,a6@(SPRIME)
  490. faddd COSB5,fp2 |...B5+S(B6+S(B7+SB8))
  491. fmulx fp0,fp1   |...S(A4+...)
  492. fmulx fp0,fp2   |...S(B5+...)
  493. faddd SINA3,fp1 |...A3+S(A4+...)
  494. faddd COSB4,fp2 |...B4+S(B5+...)
  495. fmulx fp0,fp1   |...S(A3+...)
  496. fmulx fp0,fp2   |...S(B4+...)
  497. faddx SINA2,fp1 |...A2+S(A3+...)
  498. faddx COSB3,fp2 |...B3+S(B4+...)
  499. fmulx fp0,fp1   |...S(A2+...)
  500. fmulx fp0,fp2   |...S(B3+...)
  501. faddx SINA1,fp1 |...A1+S(A2+...)
  502. faddx COSB2,fp2 |...B2+S(B3+...)
  503. fmulx fp0,fp1   |...S(A1+...)
  504. fmulx fp2,fp0   |...S(B2+...)
  505. fmulx a6@(RPRIME),fp1 /* |...R'S(A1+...) */
  506. fadds COSB1,fp0 |...B1+S(B2...)
  507. fmulx a6@(SPRIME),fp0 /* |...S'(B1+S(B2+...)) */
  508. movel d1,a7@- | restore users mode # precision
  509. andil #0xff,d1 | mask off all exceptions
  510. fmovel d1,fpcr
  511. faddx a6@(RPRIME),fp1 |...COS(X)
  512. bsrl __x_sto_cos | store cosine result
  513. fmovel a7@+,fpcr | restore users exceptions
  514. fadds a6@(POSNEG1),fp0 |...SIN(X)
  515. jra  __x_t_frcinx
  516. NEVEN:
  517. |--REGISTERS SAVED SO FAR: FP2.
  518. fmovex fp0,a6@(RPRIME)
  519. fmulx fp0,fp0   |...FP0 IS S = R*R
  520. fmoved COSB8,fp1 |...B8
  521. fmoved SINA7,fp2 |...A7
  522. fmulx fp0,fp1   |...SB8
  523. fmovex fp0,a6@(SPRIME)
  524. fmulx fp0,fp2   |...SA7
  525. rorl #1,d0
  526. andil #0x80000000,d0
  527. faddd COSB7,fp1 |...B7+SB8
  528. faddd SINA6,fp2 |...A6+SA7
  529. eorl d0,a6@(RPRIME)
  530. eorl d0,a6@(SPRIME)
  531. fmulx fp0,fp1   |...S(B7+SB8)
  532. oril #0x3F800000,d0
  533. movel d0,a6@(POSNEG1)
  534. fmulx fp0,fp2   |...S(A6+SA7)
  535. faddd COSB6,fp1 |...B6+S(B7+SB8)
  536. faddd SINA5,fp2 |...A5+S(A6+SA7)
  537. fmulx fp0,fp1   |...S(B6+S(B7+SB8))
  538. fmulx fp0,fp2   |...S(A5+S(A6+SA7))
  539. faddd COSB5,fp1 |...B5+S(B6+S(B7+SB8))
  540. faddd SINA4,fp2 |...A4+S(A5+S(A6+SA7))
  541. fmulx fp0,fp1   |...S(B5+...)
  542. fmulx fp0,fp2   |...S(A4+...)
  543. faddd COSB4,fp1 |...B4+S(B5+...)
  544. faddd SINA3,fp2 |...A3+S(A4+...)
  545. fmulx fp0,fp1   |...S(B4+...)
  546. fmulx fp0,fp2   |...S(A3+...)
  547. faddx COSB3,fp1 |...B3+S(B4+...)
  548. faddx SINA2,fp2 |...A2+S(A3+...)
  549. fmulx fp0,fp1   |...S(B3+...)
  550. fmulx fp0,fp2   |...S(A2+...)
  551. faddx COSB2,fp1 |...B2+S(B3+...)
  552. faddx SINA1,fp2 |...A1+S(A2+...)
  553. fmulx fp0,fp1   |...S(B2+...)
  554. fmulx fp2,fp0   |...s(a1+...)
  555. fadds COSB1,fp1 |...B1+S(B2...)
  556. fmulx a6@(RPRIME),fp0 /* |...R'S(A1+...) */
  557. fmulx a6@(SPRIME),fp1 /* |...S'(B1+S(B2+...)) */
  558. movel d1,a7@- | save users mode # precision
  559. andil #0xff,d1 | mask off all exceptions
  560. fmovel d1,fpcr
  561. fadds a6@(POSNEG1),fp1 |...COS(X)
  562. bsrl __x_sto_cos | store cosine result
  563. fmovel a7@+,fpcr | restore users exceptions
  564. faddx a6@(RPRIME),fp0 |...SIN(X)
  565. jra  __x_t_frcinx
  566. SCBORS:
  567. cmpil #0x3FFF8000,d0
  568. jgt  REDUCEX
  569. SCSM:
  570. movew #0x0000,a6@(XDCARE)
  571. .long 0xf23c4480,0x3f800000 /*  fmoves  &0x3F800000,fp1 */
  572. movel d1,a7@- | save users mode # precision
  573. andil #0xff,d1 | mask off all exceptions
  574. fmovel d1,fpcr
  575. .long 0xf23c44a8,0x00800000 /*  fsubs  &0x00800000,fp1 */
  576. bsrl __x_sto_cos | store cosine result
  577. fmovel a7@+,fpcr | restore users exceptions
  578. fmovex a6@(X),fp0
  579. jra  __x_t_frcinx
  580. | end