1// Copyright 2016 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5#include "textflag.h"
6
7// Various constants
8DATA sincosxnan<>+0(SB)/8, $0x7ff8000000000000
9GLOBL sincosxnan<>+0(SB), RODATA, $8
10DATA sincosxlim<>+0(SB)/8, $0x432921fb54442d19
11GLOBL sincosxlim<>+0(SB), RODATA, $8
12DATA sincosxadd<>+0(SB)/8, $0xc338000000000000
13GLOBL sincosxadd<>+0(SB), RODATA, $8
14DATA sincosxpi2l<>+0(SB)/8, $0.108285667392191389e-31
15GLOBL sincosxpi2l<>+0(SB), RODATA, $8
16DATA sincosxpi2m<>+0(SB)/8, $0.612323399573676480e-16
17GLOBL sincosxpi2m<>+0(SB), RODATA, $8
18DATA sincosxpi2h<>+0(SB)/8, $0.157079632679489656e+01
19GLOBL sincosxpi2h<>+0(SB), RODATA, $8
20DATA sincosrpi2<>+0(SB)/8, $0.636619772367581341e+00
21GLOBL sincosrpi2<>+0(SB), RODATA, $8
22
23// Minimax polynomial approximations
24DATA sincosc0<>+0(SB)/8, $0.100000000000000000E+01
25GLOBL sincosc0<>+0(SB), RODATA, $8
26DATA sincosc1<>+0(SB)/8, $-.499999999999999833E+00
27GLOBL sincosc1<>+0(SB), RODATA, $8
28DATA sincosc2<>+0(SB)/8, $0.416666666666625843E-01
29GLOBL sincosc2<>+0(SB), RODATA, $8
30DATA sincosc3<>+0(SB)/8, $-.138888888885498984E-02
31GLOBL sincosc3<>+0(SB), RODATA, $8
32DATA sincosc4<>+0(SB)/8, $0.248015871681607202E-04
33GLOBL sincosc4<>+0(SB), RODATA, $8
34DATA sincosc5<>+0(SB)/8, $-.275572911309937875E-06
35GLOBL sincosc5<>+0(SB), RODATA, $8
36DATA sincosc6<>+0(SB)/8, $0.208735047247632818E-08
37GLOBL sincosc6<>+0(SB), RODATA, $8
38DATA sincosc7<>+0(SB)/8, $-.112753632738365317E-10
39GLOBL sincosc7<>+0(SB), RODATA, $8
40DATA sincoss0<>+0(SB)/8, $0.100000000000000000E+01
41GLOBL sincoss0<>+0(SB), RODATA, $8
42DATA sincoss1<>+0(SB)/8, $-.166666666666666657E+00
43GLOBL sincoss1<>+0(SB), RODATA, $8
44DATA sincoss2<>+0(SB)/8, $0.833333333333309209E-02
45GLOBL sincoss2<>+0(SB), RODATA, $8
46DATA sincoss3<>+0(SB)/8, $-.198412698410701448E-03
47GLOBL sincoss3<>+0(SB), RODATA, $8
48DATA sincoss4<>+0(SB)/8, $0.275573191453906794E-05
49GLOBL sincoss4<>+0(SB), RODATA, $8
50DATA sincoss5<>+0(SB)/8, $-.250520918387633290E-07
51GLOBL sincoss5<>+0(SB), RODATA, $8
52DATA sincoss6<>+0(SB)/8, $0.160571285514715856E-09
53GLOBL sincoss6<>+0(SB), RODATA, $8
54DATA sincoss7<>+0(SB)/8, $-.753213484933210972E-12
55GLOBL sincoss7<>+0(SB), RODATA, $8
56
57// Sin returns the sine of the radian argument x.
58//
59// Special cases are:
60//      Sin(±0) = ±0
61//      Sin(±Inf) = NaN
62//      Sin(NaN) = NaN
63// The algorithm used is minimax polynomial approximation.
64// with coefficients determined with a Remez exchange algorithm.
65
66TEXT ·sinAsm(SB),NOSPLIT,$0-16
67	FMOVD   x+0(FP), F0
68	//special case Sin(±0) = ±0
69	FMOVD   $(0.0), F1
70	FCMPU   F0, F1
71	BEQ     sinIsZero
72	LTDBR	F0, F0
73	BLTU    L17
74	FMOVD   F0, F5
75L2:
76	MOVD    $sincosxlim<>+0(SB), R1
77	FMOVD   0(R1), F1
78	FCMPU   F5, F1
79	BGT     L16
80	MOVD    $sincoss7<>+0(SB), R1
81	FMOVD   0(R1), F4
82	MOVD    $sincoss6<>+0(SB), R1
83	FMOVD   0(R1), F1
84	MOVD    $sincoss5<>+0(SB), R1
85	VLEG    $0, 0(R1), V18
86	MOVD    $sincoss4<>+0(SB), R1
87	FMOVD   0(R1), F6
88	MOVD    $sincoss2<>+0(SB), R1
89	VLEG    $0, 0(R1), V16
90	MOVD    $sincoss3<>+0(SB), R1
91	FMOVD   0(R1), F7
92	MOVD    $sincoss1<>+0(SB), R1
93	FMOVD   0(R1), F3
94	MOVD    $sincoss0<>+0(SB), R1
95	FMOVD   0(R1), F2
96	WFCHDBS V2, V5, V2
97	BEQ     L18
98	MOVD    $sincosrpi2<>+0(SB), R1
99	FMOVD   0(R1), F3
100	MOVD    $sincosxadd<>+0(SB), R1
101	FMOVD   0(R1), F2
102	WFMSDB  V0, V3, V2, V3
103	FMOVD   0(R1), F6
104	FADD    F3, F6
105	MOVD    $sincosxpi2h<>+0(SB), R1
106	FMOVD   0(R1), F2
107	FMSUB   F2, F6, F0
108	MOVD    $sincosxpi2m<>+0(SB), R1
109	FMOVD   0(R1), F4
110	FMADD   F4, F6, F0
111	MOVD    $sincosxpi2l<>+0(SB), R1
112	WFMDB   V0, V0, V1
113	FMOVD   0(R1), F7
114	WFMDB   V1, V1, V2
115	LGDR    F3, R1
116	MOVD    $sincosxlim<>+0(SB), R2
117	TMLL	R1, $1
118	BEQ     L6
119	FMOVD   0(R2), F0
120	WFCHDBS V0, V5, V0
121	BNE     L14
122	MOVD    $sincosc7<>+0(SB), R2
123	FMOVD   0(R2), F0
124	MOVD    $sincosc6<>+0(SB), R2
125	FMOVD   0(R2), F4
126	MOVD    $sincosc5<>+0(SB), R2
127	WFMADB  V1, V0, V4, V0
128	FMOVD   0(R2), F6
129	MOVD    $sincosc4<>+0(SB), R2
130	WFMADB  V1, V0, V6, V0
131	FMOVD   0(R2), F4
132	MOVD    $sincosc2<>+0(SB), R2
133	FMOVD   0(R2), F6
134	WFMADB  V2, V4, V6, V4
135	MOVD    $sincosc3<>+0(SB), R2
136	FMOVD   0(R2), F3
137	MOVD    $sincosc1<>+0(SB), R2
138	WFMADB  V2, V0, V3, V0
139	FMOVD   0(R2), F6
140	WFMADB  V1, V4, V6, V4
141	TMLL	R1, $2
142	WFMADB  V2, V0, V4, V0
143	MOVD    $sincosc0<>+0(SB), R1
144	FMOVD   0(R1), F2
145	WFMADB  V1, V0, V2, V0
146	BNE     L15
147	FMOVD   F0, ret+8(FP)
148	RET
149
150L6:
151	FMOVD   0(R2), F4
152	WFCHDBS V4, V5, V4
153	BNE     L14
154	MOVD    $sincoss7<>+0(SB), R2
155	FMOVD   0(R2), F4
156	MOVD    $sincoss6<>+0(SB), R2
157	FMOVD   0(R2), F3
158	MOVD    $sincoss5<>+0(SB), R2
159	WFMADB  V1, V4, V3, V4
160	WFMADB  V6, V7, V0, V6
161	FMOVD   0(R2), F0
162	MOVD    $sincoss4<>+0(SB), R2
163	FMADD   F4, F1, F0
164	FMOVD   0(R2), F3
165	MOVD    $sincoss2<>+0(SB), R2
166	FMOVD   0(R2), F4
167	MOVD    $sincoss3<>+0(SB), R2
168	WFMADB  V2, V3, V4, V3
169	FMOVD   0(R2), F4
170	MOVD    $sincoss1<>+0(SB), R2
171	WFMADB  V2, V0, V4, V0
172	FMOVD   0(R2), F4
173	WFMADB  V1, V3, V4, V3
174	FNEG    F6, F4
175	WFMADB  V2, V0, V3, V2
176	WFMDB   V4, V1, V0
177	TMLL	R1, $2
178	WFMSDB  V0, V2, V6, V0
179	BNE     L15
180	FMOVD   F0, ret+8(FP)
181	RET
182
183L14:
184	MOVD    $sincosxnan<>+0(SB), R1
185	FMOVD   0(R1), F0
186	FMOVD   F0, ret+8(FP)
187	RET
188
189L18:
190	WFMDB   V0, V0, V2
191	WFMADB  V2, V4, V1, V4
192	WFMDB   V2, V2, V1
193	WFMADB  V2, V4, V18, V4
194	WFMADB  V1, V6, V16, V6
195	WFMADB  V1, V4, V7, V4
196	WFMADB  V2, V6, V3, V6
197	FMUL    F0, F2
198	WFMADB  V1, V4, V6, V4
199	FMADD   F4, F2, F0
200	FMOVD   F0, ret+8(FP)
201	RET
202
203L17:
204	FNEG    F0, F5
205	BR      L2
206L15:
207	FNEG    F0, F0
208	FMOVD   F0, ret+8(FP)
209	RET
210
211
212L16:
213	BR     ·sin(SB)		//tail call
214sinIsZero:
215	FMOVD   F0, ret+8(FP)
216	RET
217
218// Cos returns the cosine of the radian argument.
219//
220// Special cases are:
221//      Cos(±Inf) = NaN
222//      Cos(NaN) = NaN
223// The algorithm used is minimax polynomial approximation.
224// with coefficients determined with a Remez exchange algorithm.
225
226TEXT ·cosAsm(SB),NOSPLIT,$0-16
227	FMOVD   x+0(FP), F0
228	LTDBR	F0, F0
229	BLTU    L35
230	FMOVD   F0, F1
231L21:
232	MOVD    $sincosxlim<>+0(SB), R1
233	FMOVD   0(R1), F2
234	FCMPU   F1, F2
235	BGT     L30
236	MOVD    $sincosc7<>+0(SB), R1
237	FMOVD   0(R1), F4
238	MOVD    $sincosc6<>+0(SB), R1
239	VLEG    $0, 0(R1), V20
240	MOVD    $sincosc5<>+0(SB), R1
241	VLEG    $0, 0(R1), V18
242	MOVD    $sincosc4<>+0(SB), R1
243	FMOVD   0(R1), F6
244	MOVD    $sincosc2<>+0(SB), R1
245	VLEG    $0, 0(R1), V16
246	MOVD    $sincosc3<>+0(SB), R1
247	FMOVD   0(R1), F7
248	MOVD    $sincosc1<>+0(SB), R1
249	FMOVD   0(R1), F5
250	MOVD    $sincosrpi2<>+0(SB), R1
251	FMOVD   0(R1), F2
252	MOVD    $sincosxadd<>+0(SB), R1
253	FMOVD   0(R1), F3
254	MOVD    $sincoss0<>+0(SB), R1
255	WFMSDB  V0, V2, V3, V2
256	FMOVD   0(R1), F3
257	WFCHDBS V3, V1, V3
258	LGDR    F2, R1
259	BEQ     L36
260	MOVD    $sincosxadd<>+0(SB), R2
261	FMOVD   0(R2), F4
262	FADD    F2, F4
263	MOVD    $sincosxpi2h<>+0(SB), R2
264	FMOVD   0(R2), F2
265	WFMSDB  V4, V2, V0, V2
266	MOVD    $sincosxpi2m<>+0(SB), R2
267	FMOVD   0(R2), F0
268	WFMADB  V4, V0, V2, V0
269	MOVD    $sincosxpi2l<>+0(SB), R2
270	WFMDB   V0, V0, V2
271	FMOVD   0(R2), F5
272	WFMDB   V2, V2, V6
273	MOVD    $sincosxlim<>+0(SB), R2
274	TMLL	R1, $1
275	BNE     L25
276	FMOVD   0(R2), F0
277	WFCHDBS V0, V1, V0
278	BNE     L33
279	MOVD    $sincosc7<>+0(SB), R2
280	FMOVD   0(R2), F0
281	MOVD    $sincosc6<>+0(SB), R2
282	FMOVD   0(R2), F4
283	MOVD    $sincosc5<>+0(SB), R2
284	WFMADB  V2, V0, V4, V0
285	FMOVD   0(R2), F1
286	MOVD    $sincosc4<>+0(SB), R2
287	WFMADB  V2, V0, V1, V0
288	FMOVD   0(R2), F4
289	MOVD    $sincosc2<>+0(SB), R2
290	FMOVD   0(R2), F1
291	WFMADB  V6, V4, V1, V4
292	MOVD    $sincosc3<>+0(SB), R2
293	FMOVD   0(R2), F3
294	MOVD    $sincosc1<>+0(SB), R2
295	WFMADB  V6, V0, V3, V0
296	FMOVD   0(R2), F1
297	WFMADB  V2, V4, V1, V4
298	TMLL	R1, $2
299	WFMADB  V6, V0, V4, V0
300	MOVD    $sincosc0<>+0(SB), R1
301	FMOVD   0(R1), F4
302	WFMADB  V2, V0, V4, V0
303	BNE     L34
304	FMOVD   F0, ret+8(FP)
305	RET
306
307L25:
308	FMOVD   0(R2), F3
309	WFCHDBS V3, V1, V1
310	BNE     L33
311	MOVD    $sincoss7<>+0(SB), R2
312	FMOVD   0(R2), F1
313	MOVD    $sincoss6<>+0(SB), R2
314	FMOVD   0(R2), F3
315	MOVD    $sincoss5<>+0(SB), R2
316	WFMADB  V2, V1, V3, V1
317	FMOVD   0(R2), F3
318	MOVD    $sincoss4<>+0(SB), R2
319	WFMADB  V2, V1, V3, V1
320	FMOVD   0(R2), F3
321	MOVD    $sincoss2<>+0(SB), R2
322	FMOVD   0(R2), F7
323	WFMADB  V6, V3, V7, V3
324	MOVD    $sincoss3<>+0(SB), R2
325	FMADD   F5, F4, F0
326	FMOVD   0(R2), F4
327	MOVD    $sincoss1<>+0(SB), R2
328	FMADD   F1, F6, F4
329	FMOVD   0(R2), F1
330	FMADD   F3, F2, F1
331	FMUL    F0, F2
332	WFMADB  V6, V4, V1, V6
333	TMLL	R1, $2
334	FMADD   F6, F2, F0
335	BNE     L34
336	FMOVD   F0, ret+8(FP)
337	RET
338
339L33:
340	MOVD    $sincosxnan<>+0(SB), R1
341	FMOVD   0(R1), F0
342	FMOVD   F0, ret+8(FP)
343	RET
344
345L36:
346	FMUL    F0, F0
347	MOVD    $sincosc0<>+0(SB), R1
348	WFMDB   V0, V0, V1
349	WFMADB  V0, V4, V20, V4
350	WFMADB  V1, V6, V16, V6
351	WFMADB  V0, V4, V18, V4
352	WFMADB  V0, V6, V5, V6
353	WFMADB  V1, V4, V7, V4
354	FMOVD   0(R1), F2
355	WFMADB  V1, V4, V6, V4
356	WFMADB  V0, V4, V2, V0
357	FMOVD   F0, ret+8(FP)
358	RET
359
360L35:
361	FNEG    F0, F1
362	BR      L21
363L34:
364	FNEG    F0, F0
365	FMOVD   F0, ret+8(FP)
366	RET
367
368L30:
369	BR     ·cos(SB)		//tail call
370