]> git.sesse.net Git - ffmpeg/blob - libavcodec/x86/fft_mmx.asm
Port pred8x8l_horizontal_down_sse2/ssse3 (H.264 intra prediction) from x264
[ffmpeg] / libavcodec / x86 / fft_mmx.asm
1 ;******************************************************************************
2 ;* FFT transform with SSE/3DNow optimizations
3 ;* Copyright (c) 2008 Loren Merritt
4 ;*
5 ;* This algorithm (though not any of the implementation details) is
6 ;* based on libdjbfft by D. J. Bernstein.
7 ;*
8 ;* This file is part of FFmpeg.
9 ;*
10 ;* FFmpeg is free software; you can redistribute it and/or
11 ;* modify it under the terms of the GNU Lesser General Public
12 ;* License as published by the Free Software Foundation; either
13 ;* version 2.1 of the License, or (at your option) any later version.
14 ;*
15 ;* FFmpeg is distributed in the hope that it will be useful,
16 ;* but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 ;* Lesser General Public License for more details.
19 ;*
20 ;* You should have received a copy of the GNU Lesser General Public
21 ;* License along with FFmpeg; if not, write to the Free Software
22 ;* 51, Inc., Foundation Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 ;******************************************************************************
24
25 ; These functions are not individually interchangeable with the C versions.
26 ; While C takes arrays of FFTComplex, SSE/3DNow leave intermediate results
27 ; in blocks as conventient to the vector size.
28 ; i.e. {4x real, 4x imaginary, 4x real, ...} (or 2x respectively)
29
30 %include "x86inc.asm"
31
32 %ifdef ARCH_X86_64
33 %define pointer resq
34 %else
35 %define pointer resd
36 %endif
37
38 struc FFTContext
39     .nbits:    resd 1
40     .reverse:  resd 1
41     .revtab:   pointer 1
42     .tmpbuf:   pointer 1
43     .mdctsize: resd 1
44     .mdctbits: resd 1
45     .tcos:     pointer 1
46     .tsin:     pointer 1
47 endstruc
48
49 SECTION_RODATA
50
51 %define M_SQRT1_2 0.70710678118654752440
52 ps_root2: times 4 dd M_SQRT1_2
53 ps_root2mppm: dd -M_SQRT1_2, M_SQRT1_2, M_SQRT1_2, -M_SQRT1_2
54 ps_m1p1: dd 1<<31, 0
55
56 %assign i 16
57 %rep 13
58 cextern cos_ %+ i
59 %assign i i<<1
60 %endrep
61
62 %ifdef ARCH_X86_64
63     %define pointer dq
64 %else
65     %define pointer dd
66 %endif
67
68 %macro IF0 1+
69 %endmacro
70 %macro IF1 1+
71     %1
72 %endmacro
73
74 section .text align=16
75
76 %macro T2_3DN 4 ; z0, z1, mem0, mem1
77     mova     %1, %3
78     mova     %2, %1
79     pfadd    %1, %4
80     pfsub    %2, %4
81 %endmacro
82
83 %macro T4_3DN 6 ; z0, z1, z2, z3, tmp0, tmp1
84     mova     %5, %3
85     pfsub    %3, %4
86     pfadd    %5, %4 ; {t6,t5}
87     pxor     %3, [ps_m1p1] ; {t8,t7}
88     mova     %6, %1
89     pswapd   %3, %3
90     pfadd    %1, %5 ; {r0,i0}
91     pfsub    %6, %5 ; {r2,i2}
92     mova     %4, %2
93     pfadd    %2, %3 ; {r1,i1}
94     pfsub    %4, %3 ; {r3,i3}
95     SWAP     %3, %6
96 %endmacro
97
98 ; in:  %1={r0,i0,r1,i1} %2={r2,i2,r3,i3}
99 ; out: %1={r0,r1,r2,r3} %2={i0,i1,i2,i3}
100 %macro T4_SSE 3
101     mova     %3, %1
102     shufps   %1, %2, 0x64 ; {r0,i0,r3,i2}
103     shufps   %3, %2, 0xce ; {r1,i1,r2,i3}
104     mova     %2, %1
105     addps    %1, %3       ; {t1,t2,t6,t5}
106     subps    %2, %3       ; {t3,t4,t8,t7}
107     mova     %3, %1
108     shufps   %1, %2, 0x44 ; {t1,t2,t3,t4}
109     shufps   %3, %2, 0xbe ; {t6,t5,t7,t8}
110     mova     %2, %1
111     addps    %1, %3       ; {r0,i0,r1,i1}
112     subps    %2, %3       ; {r2,i2,r3,i3}
113     mova     %3, %1
114     shufps   %1, %2, 0x88 ; {r0,r1,r2,r3}
115     shufps   %3, %2, 0xdd ; {i0,i1,i2,i3}
116     SWAP     %2, %3
117 %endmacro
118
119 %macro T8_SSE 6 ; r0,i0,r1,i1,t0,t1
120     mova     %5, %3
121     shufps   %3, %4, 0x44 ; {r4,i4,r6,i6}
122     shufps   %5, %4, 0xee ; {r5,i5,r7,i7}
123     mova     %6, %3
124     subps    %3, %5       ; {r5,i5,r7,i7}
125     addps    %6, %5       ; {t1,t2,t3,t4}
126     mova     %5, %3
127     shufps   %5, %5, 0xb1 ; {i5,r5,i7,r7}
128     mulps    %3, [ps_root2mppm] ; {-r5,i5,r7,-i7}
129     mulps    %5, [ps_root2]
130     addps    %3, %5       ; {t8,t7,ta,t9}
131     mova     %5, %6
132     shufps   %6, %3, 0x36 ; {t3,t2,t9,t8}
133     shufps   %5, %3, 0x9c ; {t1,t4,t7,ta}
134     mova     %3, %6
135     addps    %6, %5       ; {t1,t2,t9,ta}
136     subps    %3, %5       ; {t6,t5,tc,tb}
137     mova     %5, %6
138     shufps   %6, %3, 0xd8 ; {t1,t9,t5,tb}
139     shufps   %5, %3, 0x8d ; {t2,ta,t6,tc}
140     mova     %3, %1
141     mova     %4, %2
142     addps    %1, %6       ; {r0,r1,r2,r3}
143     addps    %2, %5       ; {i0,i1,i2,i3}
144     subps    %3, %6       ; {r4,r5,r6,r7}
145     subps    %4, %5       ; {i4,i5,i6,i7}
146 %endmacro
147
148 ; scheduled for cpu-bound sizes
149 %macro PASS_SMALL 3 ; (to load m4-m7), wre, wim
150 IF%1 mova    m4, Z(4)
151 IF%1 mova    m5, Z(5)
152     mova     m0, %2 ; wre
153     mova     m2, m4
154     mova     m1, %3 ; wim
155     mova     m3, m5
156     mulps    m2, m0 ; r2*wre
157 IF%1 mova    m6, Z2(6)
158     mulps    m3, m1 ; i2*wim
159 IF%1 mova    m7, Z2(7)
160     mulps    m4, m1 ; r2*wim
161     mulps    m5, m0 ; i2*wre
162     addps    m2, m3 ; r2*wre + i2*wim
163     mova     m3, m1
164     mulps    m1, m6 ; r3*wim
165     subps    m5, m4 ; i2*wre - r2*wim
166     mova     m4, m0
167     mulps    m3, m7 ; i3*wim
168     mulps    m4, m6 ; r3*wre
169     mulps    m0, m7 ; i3*wre
170     subps    m4, m3 ; r3*wre - i3*wim
171     mova     m3, Z(0)
172     addps    m0, m1 ; i3*wre + r3*wim
173     mova     m1, m4
174     addps    m4, m2 ; t5
175     subps    m1, m2 ; t3
176     subps    m3, m4 ; r2
177     addps    m4, Z(0) ; r0
178     mova     m6, Z(2)
179     mova   Z(4), m3
180     mova   Z(0), m4
181     mova     m3, m5
182     subps    m5, m0 ; t4
183     mova     m4, m6
184     subps    m6, m5 ; r3
185     addps    m5, m4 ; r1
186     mova  Z2(6), m6
187     mova   Z(2), m5
188     mova     m2, Z(3)
189     addps    m3, m0 ; t6
190     subps    m2, m1 ; i3
191     mova     m7, Z(1)
192     addps    m1, Z(3) ; i1
193     mova  Z2(7), m2
194     mova   Z(3), m1
195     mova     m4, m7
196     subps    m7, m3 ; i2
197     addps    m3, m4 ; i0
198     mova   Z(5), m7
199     mova   Z(1), m3
200 %endmacro
201
202 ; scheduled to avoid store->load aliasing
203 %macro PASS_BIG 1 ; (!interleave)
204     mova     m4, Z(4) ; r2
205     mova     m5, Z(5) ; i2
206     mova     m2, m4
207     mova     m0, [wq] ; wre
208     mova     m3, m5
209     mova     m1, [wq+o1q] ; wim
210     mulps    m2, m0 ; r2*wre
211     mova     m6, Z2(6) ; r3
212     mulps    m3, m1 ; i2*wim
213     mova     m7, Z2(7) ; i3
214     mulps    m4, m1 ; r2*wim
215     mulps    m5, m0 ; i2*wre
216     addps    m2, m3 ; r2*wre + i2*wim
217     mova     m3, m1
218     mulps    m1, m6 ; r3*wim
219     subps    m5, m4 ; i2*wre - r2*wim
220     mova     m4, m0
221     mulps    m3, m7 ; i3*wim
222     mulps    m4, m6 ; r3*wre
223     mulps    m0, m7 ; i3*wre
224     subps    m4, m3 ; r3*wre - i3*wim
225     mova     m3, Z(0)
226     addps    m0, m1 ; i3*wre + r3*wim
227     mova     m1, m4
228     addps    m4, m2 ; t5
229     subps    m1, m2 ; t3
230     subps    m3, m4 ; r2
231     addps    m4, Z(0) ; r0
232     mova     m6, Z(2)
233     mova   Z(4), m3
234     mova   Z(0), m4
235     mova     m3, m5
236     subps    m5, m0 ; t4
237     mova     m4, m6
238     subps    m6, m5 ; r3
239     addps    m5, m4 ; r1
240 IF%1 mova Z2(6), m6
241 IF%1 mova  Z(2), m5
242     mova     m2, Z(3)
243     addps    m3, m0 ; t6
244     subps    m2, m1 ; i3
245     mova     m7, Z(1)
246     addps    m1, Z(3) ; i1
247 IF%1 mova Z2(7), m2
248 IF%1 mova  Z(3), m1
249     mova     m4, m7
250     subps    m7, m3 ; i2
251     addps    m3, m4 ; i0
252 IF%1 mova  Z(5), m7
253 IF%1 mova  Z(1), m3
254 %if %1==0
255     mova     m4, m5 ; r1
256     mova     m0, m6 ; r3
257     unpcklps m5, m1
258     unpckhps m4, m1
259     unpcklps m6, m2
260     unpckhps m0, m2
261     mova     m1, Z(0)
262     mova     m2, Z(4)
263     mova   Z(2), m5
264     mova   Z(3), m4
265     mova  Z2(6), m6
266     mova  Z2(7), m0
267     mova     m5, m1 ; r0
268     mova     m4, m2 ; r2
269     unpcklps m1, m3
270     unpckhps m5, m3
271     unpcklps m2, m7
272     unpckhps m4, m7
273     mova   Z(0), m1
274     mova   Z(1), m5
275     mova   Z(4), m2
276     mova   Z(5), m4
277 %endif
278 %endmacro
279
280 %macro PUNPCK 3
281     mova      %3, %1
282     punpckldq %1, %2
283     punpckhdq %3, %2
284 %endmacro
285
286 INIT_XMM
287 %define mova movaps
288
289 %define Z(x) [r0+mmsize*x]
290 %define Z2(x) [r0+mmsize*x]
291
292 align 16
293 fft4_sse:
294     mova     m0, Z(0)
295     mova     m1, Z(1)
296     T4_SSE   m0, m1, m2
297     mova   Z(0), m0
298     mova   Z(1), m1
299     ret
300
301 align 16
302 fft8_sse:
303     mova     m0, Z(0)
304     mova     m1, Z(1)
305     T4_SSE   m0, m1, m2
306     mova     m2, Z(2)
307     mova     m3, Z(3)
308     T8_SSE   m0, m1, m2, m3, m4, m5
309     mova   Z(0), m0
310     mova   Z(1), m1
311     mova   Z(2), m2
312     mova   Z(3), m3
313     ret
314
315 align 16
316 fft16_sse:
317     mova     m0, Z(0)
318     mova     m1, Z(1)
319     T4_SSE   m0, m1, m2
320     mova     m2, Z(2)
321     mova     m3, Z(3)
322     T8_SSE   m0, m1, m2, m3, m4, m5
323     mova     m4, Z(4)
324     mova     m5, Z(5)
325     mova   Z(0), m0
326     mova   Z(1), m1
327     mova   Z(2), m2
328     mova   Z(3), m3
329     T4_SSE   m4, m5, m6
330     mova     m6, Z2(6)
331     mova     m7, Z2(7)
332     T4_SSE   m6, m7, m0
333     PASS_SMALL 0, [cos_16], [cos_16+16]
334     ret
335
336
337 INIT_MMX
338
339 %macro FFT48_3DN 1
340 align 16
341 fft4%1:
342     T2_3DN   m0, m1, Z(0), Z(1)
343     mova     m2, Z(2)
344     mova     m3, Z(3)
345     T4_3DN   m0, m1, m2, m3, m4, m5
346     PUNPCK   m0, m1, m4
347     PUNPCK   m2, m3, m5
348     mova   Z(0), m0
349     mova   Z(1), m4
350     mova   Z(2), m2
351     mova   Z(3), m5
352     ret
353
354 align 16
355 fft8%1:
356     T2_3DN   m0, m1, Z(0), Z(1)
357     mova     m2, Z(2)
358     mova     m3, Z(3)
359     T4_3DN   m0, m1, m2, m3, m4, m5
360     mova   Z(0), m0
361     mova   Z(2), m2
362     T2_3DN   m4, m5,  Z(4),  Z(5)
363     T2_3DN   m6, m7, Z2(6), Z2(7)
364     pswapd   m0, m5
365     pswapd   m2, m7
366     pxor     m0, [ps_m1p1]
367     pxor     m2, [ps_m1p1]
368     pfsub    m5, m0
369     pfadd    m7, m2
370     pfmul    m5, [ps_root2]
371     pfmul    m7, [ps_root2]
372     T4_3DN   m1, m3, m5, m7, m0, m2
373     mova   Z(5), m5
374     mova  Z2(7), m7
375     mova     m0, Z(0)
376     mova     m2, Z(2)
377     T4_3DN   m0, m2, m4, m6, m5, m7
378     PUNPCK   m0, m1, m5
379     PUNPCK   m2, m3, m7
380     mova   Z(0), m0
381     mova   Z(1), m5
382     mova   Z(2), m2
383     mova   Z(3), m7
384     PUNPCK   m4,  Z(5), m5
385     PUNPCK   m6, Z2(7), m7
386     mova   Z(4), m4
387     mova   Z(5), m5
388     mova  Z2(6), m6
389     mova  Z2(7), m7
390     ret
391 %endmacro
392
393 FFT48_3DN _3dn2
394
395 %macro pswapd 2
396 %ifidn %1, %2
397     movd [r0+12], %1
398     punpckhdq %1, [r0+8]
399 %else
400     movq  %1, %2
401     psrlq %1, 32
402     punpckldq %1, %2
403 %endif
404 %endmacro
405
406 FFT48_3DN _3dn
407
408
409 %define Z(x) [zq + o1q*(x&6) + mmsize*(x&1)]
410 %define Z2(x) [zq + o3q + mmsize*(x&1)]
411
412 %macro DECL_PASS 2+ ; name, payload
413 align 16
414 %1:
415 DEFINE_ARGS z, w, n, o1, o3
416     lea o3q, [nq*3]
417     lea o1q, [nq*8]
418     shl o3q, 4
419 .loop:
420     %2
421     add zq, mmsize*2
422     add wq, mmsize
423     sub nd, mmsize/8
424     jg .loop
425     rep ret
426 %endmacro
427
428 INIT_XMM
429 %define mova movaps
430 DECL_PASS pass_sse, PASS_BIG 1
431 DECL_PASS pass_interleave_sse, PASS_BIG 0
432
433 INIT_MMX
434 %define mulps pfmul
435 %define addps pfadd
436 %define subps pfsub
437 %define unpcklps punpckldq
438 %define unpckhps punpckhdq
439 DECL_PASS pass_3dn, PASS_SMALL 1, [wq], [wq+o1q]
440 DECL_PASS pass_interleave_3dn, PASS_BIG 0
441 %define pass_3dn2 pass_3dn
442 %define pass_interleave_3dn2 pass_interleave_3dn
443
444 %ifdef PIC
445 %define SECTION_REL - $$
446 %else
447 %define SECTION_REL
448 %endif
449
450 %macro FFT_DISPATCH 2; clobbers 5 GPRs, 8 XMMs
451     lea r2, [dispatch_tab%1]
452     mov r2, [r2 + (%2q-2)*gprsize]
453 %ifdef PIC
454     lea r3, [$$]
455     add r2, r3
456 %endif
457     call r2
458 %endmacro ; FFT_DISPATCH
459
460 %macro DECL_FFT 2-3 ; nbits, cpu, suffix
461 %xdefine list_of_fft fft4%2 SECTION_REL, fft8%2 SECTION_REL
462 %if %1==5
463 %xdefine list_of_fft list_of_fft, fft16%2 SECTION_REL
464 %endif
465
466 %assign n 1<<%1
467 %rep 17-%1
468 %assign n2 n/2
469 %assign n4 n/4
470 %xdefine list_of_fft list_of_fft, fft %+ n %+ %3%2 SECTION_REL
471
472 align 16
473 fft %+ n %+ %3%2:
474     call fft %+ n2 %+ %2
475     add r0, n*4 - (n&(-2<<%1))
476     call fft %+ n4 %+ %2
477     add r0, n*2 - (n2&(-2<<%1))
478     call fft %+ n4 %+ %2
479     sub r0, n*6 + (n2&(-2<<%1))
480     lea r1, [cos_ %+ n]
481     mov r2d, n4/2
482     jmp pass%3%2
483
484 %assign n n*2
485 %endrep
486 %undef n
487
488 align 8
489 dispatch_tab%3%2: pointer list_of_fft
490
491 section .text
492
493 ; On x86_32, this function does the register saving and restoring for all of fft.
494 ; The others pass args in registers and don't spill anything.
495 cglobal fft_dispatch%3%2, 2,5,8, z, nbits
496     FFT_DISPATCH %3%2, nbits
497     RET
498 %endmacro ; DECL_FFT
499
500 DECL_FFT 5, _sse
501 DECL_FFT 5, _sse, _interleave
502 DECL_FFT 4, _3dn
503 DECL_FFT 4, _3dn, _interleave
504 DECL_FFT 4, _3dn2
505 DECL_FFT 4, _3dn2, _interleave
506
507 INIT_XMM
508 %undef mulps
509 %undef addps
510 %undef subps
511 %undef unpcklps
512 %undef unpckhps
513
514 %macro PREROTATER 5 ;-2*k, 2*k, input+n4, tcos+n8, tsin+n8
515     movaps   xmm0, [%3+%2*4]
516     movaps   xmm1, [%3+%1*4-0x10]
517     movaps   xmm2, xmm0
518     shufps   xmm0, xmm1, 0x88
519     shufps   xmm1, xmm2, 0x77
520     movlps   xmm4, [%4+%2*2]
521     movlps   xmm5, [%5+%2*2+0x0]
522     movhps   xmm4, [%4+%1*2-0x8]
523     movhps   xmm5, [%5+%1*2-0x8]
524     movaps   xmm2, xmm0
525     movaps   xmm3, xmm1
526     mulps    xmm0, xmm5
527     mulps    xmm1, xmm4
528     mulps    xmm2, xmm4
529     mulps    xmm3, xmm5
530     subps    xmm1, xmm0
531     addps    xmm2, xmm3
532     movaps   xmm0, xmm1
533     unpcklps xmm1, xmm2
534     unpckhps xmm0, xmm2
535 %endmacro
536
537 %macro CMUL 6 ;j, xmm0, xmm1, 3, 4, 5
538     movaps   xmm6, [%4+%1*2]
539     movaps   %2,   [%4+%1*2+0x10]
540     movaps   %3,   xmm6
541     movaps   xmm7, %2
542     mulps    xmm6, [%5+%1]
543     mulps    %2,   [%6+%1]
544     mulps    %3,   [%6+%1]
545     mulps    xmm7, [%5+%1]
546     subps    %2,   xmm6
547     addps    %3,   xmm7
548 %endmacro
549
550 %macro POSROTATESHUF 5 ;j, k, z+n8, tcos+n8, tsin+n8
551 .post:
552     CMUL     %1,   xmm0, xmm1, %3, %4, %5
553     CMUL     %2,   xmm4, xmm5, %3, %4, %5
554     shufps   xmm1, xmm1, 0x1b
555     shufps   xmm5, xmm5, 0x1b
556     movaps   xmm6, xmm4
557     unpckhps xmm4, xmm1
558     unpcklps xmm6, xmm1
559     movaps   xmm2, xmm0
560     unpcklps xmm0, xmm5
561     unpckhps xmm2, xmm5
562     movaps   [%3+%2*2],      xmm6
563     movaps   [%3+%2*2+0x10], xmm4
564     movaps   [%3+%1*2],      xmm0
565     movaps   [%3+%1*2+0x10], xmm2
566     sub      %2,   0x10
567     add      %1,   0x10
568     jl       .post
569 %endmacro
570
571 cglobal imdct_half_sse, 3,7,8; FFTContext *s, FFTSample *output, const FFTSample *input
572 %ifdef ARCH_X86_64
573 %define rrevtab r10
574 %define rtcos   r11
575 %define rtsin   r12
576     push  r12
577     push  r13
578     push  r14
579 %else
580 %define rrevtab r6
581 %define rtsin   r6
582 %define rtcos   r5
583 %endif
584     mov   r3d, [r0+FFTContext.mdctsize]
585     add   r2, r3
586     shr   r3, 1
587     mov   rtcos, [r0+FFTContext.tcos]
588     mov   rtsin, [r0+FFTContext.tsin]
589     add   rtcos, r3
590     add   rtsin, r3
591 %ifndef ARCH_X86_64
592     push  rtcos
593     push  rtsin
594 %endif
595     shr   r3, 1
596     mov   rrevtab, [r0+FFTContext.revtab]
597     add   rrevtab, r3
598 %ifndef ARCH_X86_64
599     push  rrevtab
600 %endif
601
602     sub   r3, 4
603 %ifdef ARCH_X86_64
604     xor   r4, r4
605     sub   r4, r3
606 %endif
607 .pre:
608 %ifndef ARCH_X86_64
609 ;unspill
610     xor   r4, r4
611     sub   r4, r3
612     mov   rtsin, [esp+4]
613     mov   rtcos, [esp+8]
614 %endif
615
616     PREROTATER r4, r3, r2, rtcos, rtsin
617 %ifdef ARCH_X86_64
618     movzx  r5,  word [rrevtab+r4-4]
619     movzx  r6,  word [rrevtab+r4-2]
620     movzx  r13, word [rrevtab+r3]
621     movzx  r14, word [rrevtab+r3+2]
622     movlps [r1+r5 *8], xmm0
623     movhps [r1+r6 *8], xmm0
624     movlps [r1+r13*8], xmm1
625     movhps [r1+r14*8], xmm1
626     add    r4, 4
627 %else
628     mov    r6, [esp]
629     movzx  r5, word [r6+r4-4]
630     movzx  r4, word [r6+r4-2]
631     movlps [r1+r5*8], xmm0
632     movhps [r1+r4*8], xmm0
633     movzx  r5, word [r6+r3]
634     movzx  r4, word [r6+r3+2]
635     movlps [r1+r5*8], xmm1
636     movhps [r1+r4*8], xmm1
637 %endif
638     sub    r3, 4
639     jns    .pre
640
641     mov  r5, r0
642     mov  r6, r1
643     mov  r0, r1
644     mov  r1d, [r5+FFTContext.nbits]
645
646     FFT_DISPATCH _sse, r1
647
648     mov  r0d, [r5+FFTContext.mdctsize]
649     add  r6, r0
650     shr  r0, 1
651 %ifndef ARCH_X86_64
652 %define rtcos r2
653 %define rtsin r3
654     mov  rtcos, [esp+8]
655     mov  rtsin, [esp+4]
656 %endif
657     neg  r0
658     mov  r1, -16
659     sub  r1, r0
660     POSROTATESHUF r0, r1, r6, rtcos, rtsin
661 %ifdef ARCH_X86_64
662     pop  r14
663     pop  r13
664     pop  r12
665 %else
666     add esp, 12
667 %endif
668     RET