x86/dsputil: fix VECTOR_CLIP_INT32 macro
[ffmpeg.git] / libavcodec / x86 / dsputil.asm
1 ;******************************************************************************
2 ;* MMX optimized DSP utils
3 ;* Copyright (c) 2008 Loren Merritt
4 ;* Copyright (c) 2003-2013 Michael Niedermayer
5 ;* Copyright (c) 2013 Daniel Kang
6 ;*
7 ;* This file is part of FFmpeg.
8 ;*
9 ;* FFmpeg is free software; you can redistribute it and/or
10 ;* modify it under the terms of the GNU Lesser General Public
11 ;* License as published by the Free Software Foundation; either
12 ;* version 2.1 of the License, or (at your option) any later version.
13 ;*
14 ;* FFmpeg is distributed in the hope that it will be useful,
15 ;* but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 ;* Lesser General Public License for more details.
18 ;*
19 ;* You should have received a copy of the GNU Lesser General Public
20 ;* License along with FFmpeg; if not, write to the Free Software
21 ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 ;******************************************************************************
23
24 %include "libavutil/x86/x86util.asm"
25
26 SECTION_RODATA
27 pb_f: times 16 db 15
28 pb_zzzzzzzz77777777: times 8 db -1
29 pb_7: times 8 db 7
30 pb_zzzz3333zzzzbbbb: db -1,-1,-1,-1,3,3,3,3,-1,-1,-1,-1,11,11,11,11
31 pb_zz11zz55zz99zzdd: db -1,-1,1,1,-1,-1,5,5,-1,-1,9,9,-1,-1,13,13
32 pb_bswap32: db 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12
33
34 cextern pb_80
35
36 SECTION_TEXT
37
38 %macro SCALARPRODUCT 0
39 ; int ff_scalarproduct_int16(int16_t *v1, int16_t *v2, int order)
40 cglobal scalarproduct_int16, 3,3,3, v1, v2, order
41     shl orderq, 1
42     add v1q, orderq
43     add v2q, orderq
44     neg orderq
45     pxor    m2, m2
46 .loop:
47     movu    m0, [v1q + orderq]
48     movu    m1, [v1q + orderq + mmsize]
49     pmaddwd m0, [v2q + orderq]
50     pmaddwd m1, [v2q + orderq + mmsize]
51     paddd   m2, m0
52     paddd   m2, m1
53     add     orderq, mmsize*2
54     jl .loop
55     HADDD   m2, m0
56     movd   eax, m2
57 %if mmsize == 8
58     emms
59 %endif
60     RET
61
62 ; int ff_scalarproduct_and_madd_int16(int16_t *v1, int16_t *v2, int16_t *v3,
63 ;                                     int order, int mul)
64 cglobal scalarproduct_and_madd_int16, 4,4,8, v1, v2, v3, order, mul
65     shl orderq, 1
66     movd    m7, mulm
67 %if mmsize == 16
68     pshuflw m7, m7, 0
69     punpcklqdq m7, m7
70 %else
71     pshufw  m7, m7, 0
72 %endif
73     pxor    m6, m6
74     add v1q, orderq
75     add v2q, orderq
76     add v3q, orderq
77     neg orderq
78 .loop:
79     movu    m0, [v2q + orderq]
80     movu    m1, [v2q + orderq + mmsize]
81     mova    m4, [v1q + orderq]
82     mova    m5, [v1q + orderq + mmsize]
83     movu    m2, [v3q + orderq]
84     movu    m3, [v3q + orderq + mmsize]
85     pmaddwd m0, m4
86     pmaddwd m1, m5
87     pmullw  m2, m7
88     pmullw  m3, m7
89     paddd   m6, m0
90     paddd   m6, m1
91     paddw   m2, m4
92     paddw   m3, m5
93     mova    [v1q + orderq], m2
94     mova    [v1q + orderq + mmsize], m3
95     add     orderq, mmsize*2
96     jl .loop
97     HADDD   m6, m0
98     movd   eax, m6
99     RET
100 %endmacro
101
102 INIT_MMX mmxext
103 SCALARPRODUCT
104 INIT_XMM sse2
105 SCALARPRODUCT
106
107 %macro SCALARPRODUCT_LOOP 1
108 align 16
109 .loop%1:
110     sub     orderq, mmsize*2
111 %if %1
112     mova    m1, m4
113     mova    m4, [v2q + orderq]
114     mova    m0, [v2q + orderq + mmsize]
115     palignr m1, m0, %1
116     palignr m0, m4, %1
117     mova    m3, m5
118     mova    m5, [v3q + orderq]
119     mova    m2, [v3q + orderq + mmsize]
120     palignr m3, m2, %1
121     palignr m2, m5, %1
122 %else
123     mova    m0, [v2q + orderq]
124     mova    m1, [v2q + orderq + mmsize]
125     mova    m2, [v3q + orderq]
126     mova    m3, [v3q + orderq + mmsize]
127 %endif
128     %define t0  [v1q + orderq]
129     %define t1  [v1q + orderq + mmsize]
130 %if ARCH_X86_64
131     mova    m8, t0
132     mova    m9, t1
133     %define t0  m8
134     %define t1  m9
135 %endif
136     pmaddwd m0, t0
137     pmaddwd m1, t1
138     pmullw  m2, m7
139     pmullw  m3, m7
140     paddw   m2, t0
141     paddw   m3, t1
142     paddd   m6, m0
143     paddd   m6, m1
144     mova    [v1q + orderq], m2
145     mova    [v1q + orderq + mmsize], m3
146     jg .loop%1
147 %if %1
148     jmp .end
149 %endif
150 %endmacro
151
152 ; int ff_scalarproduct_and_madd_int16(int16_t *v1, int16_t *v2, int16_t *v3,
153 ;                                     int order, int mul)
154 INIT_XMM ssse3
155 cglobal scalarproduct_and_madd_int16, 4,5,10, v1, v2, v3, order, mul
156     shl orderq, 1
157     movd    m7, mulm
158     pshuflw m7, m7, 0
159     punpcklqdq m7, m7
160     pxor    m6, m6
161     mov    r4d, v2d
162     and    r4d, 15
163     and    v2q, ~15
164     and    v3q, ~15
165     mova    m4, [v2q + orderq]
166     mova    m5, [v3q + orderq]
167     ; linear is faster than branch tree or jump table, because the branches taken are cyclic (i.e. predictable)
168     cmp    r4d, 0
169     je .loop0
170     cmp    r4d, 2
171     je .loop2
172     cmp    r4d, 4
173     je .loop4
174     cmp    r4d, 6
175     je .loop6
176     cmp    r4d, 8
177     je .loop8
178     cmp    r4d, 10
179     je .loop10
180     cmp    r4d, 12
181     je .loop12
182 SCALARPRODUCT_LOOP 14
183 SCALARPRODUCT_LOOP 12
184 SCALARPRODUCT_LOOP 10
185 SCALARPRODUCT_LOOP 8
186 SCALARPRODUCT_LOOP 6
187 SCALARPRODUCT_LOOP 4
188 SCALARPRODUCT_LOOP 2
189 SCALARPRODUCT_LOOP 0
190 .end:
191     HADDD   m6, m0
192     movd   eax, m6
193     RET
194
195
196 ; void ff_add_hfyu_median_prediction_mmxext(uint8_t *dst, const uint8_t *top,
197 ;                                           const uint8_t *diff, int w,
198 ;                                           int *left, int *left_top)
199 INIT_MMX mmxext
200 cglobal add_hfyu_median_prediction, 6,6,0, dst, top, diff, w, left, left_top
201     movq    mm0, [topq]
202     movq    mm2, mm0
203     movd    mm4, [left_topq]
204     psllq   mm2, 8
205     movq    mm1, mm0
206     por     mm4, mm2
207     movd    mm3, [leftq]
208     psubb   mm0, mm4 ; t-tl
209     add    dstq, wq
210     add    topq, wq
211     add   diffq, wq
212     neg      wq
213     jmp .skip
214 .loop:
215     movq    mm4, [topq+wq]
216     movq    mm0, mm4
217     psllq   mm4, 8
218     por     mm4, mm1
219     movq    mm1, mm0 ; t
220     psubb   mm0, mm4 ; t-tl
221 .skip:
222     movq    mm2, [diffq+wq]
223 %assign i 0
224 %rep 8
225     movq    mm4, mm0
226     paddb   mm4, mm3 ; t-tl+l
227     movq    mm5, mm3
228     pmaxub  mm3, mm1
229     pminub  mm5, mm1
230     pminub  mm3, mm4
231     pmaxub  mm3, mm5 ; median
232     paddb   mm3, mm2 ; +residual
233 %if i==0
234     movq    mm7, mm3
235     psllq   mm7, 56
236 %else
237     movq    mm6, mm3
238     psrlq   mm7, 8
239     psllq   mm6, 56
240     por     mm7, mm6
241 %endif
242 %if i<7
243     psrlq   mm0, 8
244     psrlq   mm1, 8
245     psrlq   mm2, 8
246 %endif
247 %assign i i+1
248 %endrep
249     movq [dstq+wq], mm7
250     add      wq, 8
251     jl .loop
252     movzx   r2d, byte [dstq-1]
253     mov [leftq], r2d
254     movzx   r2d, byte [topq-1]
255     mov [left_topq], r2d
256     RET
257
258
259 %macro ADD_HFYU_LEFT_LOOP 2 ; %1 = dst_is_aligned, %2 = src_is_aligned
260     add     srcq, wq
261     add     dstq, wq
262     neg     wq
263 %%.loop:
264 %if %2
265     mova    m1, [srcq+wq]
266 %else
267     movu    m1, [srcq+wq]
268 %endif
269     mova    m2, m1
270     psllw   m1, 8
271     paddb   m1, m2
272     mova    m2, m1
273     pshufb  m1, m3
274     paddb   m1, m2
275     pshufb  m0, m5
276     mova    m2, m1
277     pshufb  m1, m4
278     paddb   m1, m2
279 %if mmsize == 16
280     mova    m2, m1
281     pshufb  m1, m6
282     paddb   m1, m2
283 %endif
284     paddb   m0, m1
285 %if %1
286     mova    [dstq+wq], m0
287 %else
288     movq    [dstq+wq], m0
289     movhps  [dstq+wq+8], m0
290 %endif
291     add     wq, mmsize
292     jl %%.loop
293     mov     eax, mmsize-1
294     sub     eax, wd
295     movd    m1, eax
296     pshufb  m0, m1
297     movd    eax, m0
298     RET
299 %endmacro
300
301 ; int ff_add_hfyu_left_prediction(uint8_t *dst, const uint8_t *src,
302 ;                                 int w, int left)
303 INIT_MMX ssse3
304 cglobal add_hfyu_left_prediction, 3,3,7, dst, src, w, left
305 .skip_prologue:
306     mova    m5, [pb_7]
307     mova    m4, [pb_zzzz3333zzzzbbbb]
308     mova    m3, [pb_zz11zz55zz99zzdd]
309     movd    m0, leftm
310     psllq   m0, 56
311     ADD_HFYU_LEFT_LOOP 1, 1
312
313 INIT_XMM sse4
314 cglobal add_hfyu_left_prediction, 3,3,7, dst, src, w, left
315     mova    m5, [pb_f]
316     mova    m6, [pb_zzzzzzzz77777777]
317     mova    m4, [pb_zzzz3333zzzzbbbb]
318     mova    m3, [pb_zz11zz55zz99zzdd]
319     movd    m0, leftm
320     pslldq  m0, 15
321     test    srcq, 15
322     jnz .src_unaligned
323     test    dstq, 15
324     jnz .dst_unaligned
325     ADD_HFYU_LEFT_LOOP 1, 1
326 .dst_unaligned:
327     ADD_HFYU_LEFT_LOOP 0, 1
328 .src_unaligned:
329     ADD_HFYU_LEFT_LOOP 0, 0
330
331
332 ;-----------------------------------------------------------------------------
333 ; void ff_vector_clip_int32(int32_t *dst, const int32_t *src, int32_t min,
334 ;                           int32_t max, unsigned int len)
335 ;-----------------------------------------------------------------------------
336
337 ; %1 = number of xmm registers used
338 ; %2 = number of inline load/process/store loops per asm loop
339 ; %3 = process 4*mmsize (%3=0) or 8*mmsize (%3=1) bytes per loop
340 ; %4 = CLIPD function takes min/max as float instead of int (CLIPD_SSE2)
341 ; %5 = suffix
342 %macro VECTOR_CLIP_INT32 4-5
343 cglobal vector_clip_int32%5, 5,5,%1, dst, src, min, max, len
344 %if %4
345     cvtsi2ss  m4, minm
346     cvtsi2ss  m5, maxm
347 %else
348     movd      m4, minm
349     movd      m5, maxm
350 %endif
351     SPLATD    m4
352     SPLATD    m5
353 .loop:
354 %assign %%i 0
355 %rep %2
356     mova      m0,  [srcq+mmsize*(0+%%i)]
357     mova      m1,  [srcq+mmsize*(1+%%i)]
358     mova      m2,  [srcq+mmsize*(2+%%i)]
359     mova      m3,  [srcq+mmsize*(3+%%i)]
360 %if %3
361     mova      m7,  [srcq+mmsize*(4+%%i)]
362     mova      m8,  [srcq+mmsize*(5+%%i)]
363     mova      m9,  [srcq+mmsize*(6+%%i)]
364     mova      m10, [srcq+mmsize*(7+%%i)]
365 %endif
366     CLIPD  m0,  m4, m5, m6
367     CLIPD  m1,  m4, m5, m6
368     CLIPD  m2,  m4, m5, m6
369     CLIPD  m3,  m4, m5, m6
370 %if %3
371     CLIPD  m7,  m4, m5, m6
372     CLIPD  m8,  m4, m5, m6
373     CLIPD  m9,  m4, m5, m6
374     CLIPD  m10, m4, m5, m6
375 %endif
376     mova  [dstq+mmsize*(0+%%i)], m0
377     mova  [dstq+mmsize*(1+%%i)], m1
378     mova  [dstq+mmsize*(2+%%i)], m2
379     mova  [dstq+mmsize*(3+%%i)], m3
380 %if %3
381     mova  [dstq+mmsize*(4+%%i)], m7
382     mova  [dstq+mmsize*(5+%%i)], m8
383     mova  [dstq+mmsize*(6+%%i)], m9
384     mova  [dstq+mmsize*(7+%%i)], m10
385 %endif
386 %assign %%i %%i+4*(%3+1)
387 %endrep
388     add     srcq, mmsize*4*(%2+%3)
389     add     dstq, mmsize*4*(%2+%3)
390     sub     lend, mmsize*(%2+%3)
391     jg .loop
392     REP_RET
393 %endmacro
394
395 INIT_MMX mmx
396 %define CLIPD CLIPD_MMX
397 VECTOR_CLIP_INT32 0, 1, 0, 0
398 INIT_XMM sse2
399 VECTOR_CLIP_INT32 6, 1, 0, 0, _int
400 %define CLIPD CLIPD_SSE2
401 VECTOR_CLIP_INT32 6, 2, 0, 1
402 INIT_XMM sse4
403 %define CLIPD CLIPD_SSE41
404 %ifdef m8
405 VECTOR_CLIP_INT32 11, 1, 1, 0
406 %else
407 VECTOR_CLIP_INT32 6, 1, 0, 0
408 %endif
409
410 ; %1 = aligned/unaligned
411 %macro BSWAP_LOOPS  1
412     mov      r3, r2
413     sar      r2, 3
414     jz       .left4_%1
415 .loop8_%1:
416     mov%1    m0, [r1 +  0]
417     mov%1    m1, [r1 + 16]
418 %if cpuflag(ssse3)
419     pshufb   m0, m2
420     pshufb   m1, m2
421     mov%1    [r0 +  0], m0
422     mov%1    [r0 + 16], m1
423 %else
424     pshuflw  m0, m0, 10110001b
425     pshuflw  m1, m1, 10110001b
426     pshufhw  m0, m0, 10110001b
427     pshufhw  m1, m1, 10110001b
428     mova     m2, m0
429     mova     m3, m1
430     psllw    m0, 8
431     psllw    m1, 8
432     psrlw    m2, 8
433     psrlw    m3, 8
434     por      m2, m0
435     por      m3, m1
436     mov%1    [r0 +  0], m2
437     mov%1    [r0 + 16], m3
438 %endif
439     add      r0, 32
440     add      r1, 32
441     dec      r2
442     jnz      .loop8_%1
443 .left4_%1:
444     mov      r2, r3
445     and      r3, 4
446     jz       .left
447     mov%1    m0, [r1]
448 %if cpuflag(ssse3)
449     pshufb   m0, m2
450     mov%1    [r0], m0
451 %else
452     pshuflw  m0, m0, 10110001b
453     pshufhw  m0, m0, 10110001b
454     mova     m2, m0
455     psllw    m0, 8
456     psrlw    m2, 8
457     por      m2, m0
458     mov%1    [r0], m2
459 %endif
460     add      r1, 16
461     add      r0, 16
462 %endmacro
463
464 ; void ff_bswap_buf(uint32_t *dst, const uint32_t *src, int w);
465 %macro BSWAP32_BUF 0
466 %if cpuflag(ssse3)
467 cglobal bswap32_buf, 3,4,3
468     mov      r3, r1
469     mova     m2, [pb_bswap32]
470 %else
471 cglobal bswap32_buf, 3,4,5
472     mov      r3, r1
473 %endif
474     or       r3, r0
475     and      r3, 15
476     jz       .start_align
477     BSWAP_LOOPS  u
478     jmp      .left
479 .start_align:
480     BSWAP_LOOPS  a
481 .left:
482 %if cpuflag(ssse3)
483     mov      r3, r2
484     and      r2, 2
485     jz       .left1
486     movq     m0, [r1]
487     pshufb   m0, m2
488     movq     [r0], m0
489     add      r1, 8
490     add      r0, 8
491 .left1:
492     and      r3, 1
493     jz       .end
494     mov      r2d, [r1]
495     bswap    r2d
496     mov      [r0], r2d
497 %else
498     and      r2, 3
499     jz       .end
500 .loop2:
501     mov      r3d, [r1]
502     bswap    r3d
503     mov      [r0], r3d
504     add      r1, 4
505     add      r0, 4
506     dec      r2
507     jnz      .loop2
508 %endif
509 .end:
510     RET
511 %endmacro
512
513 INIT_XMM sse2
514 BSWAP32_BUF
515
516 INIT_XMM ssse3
517 BSWAP32_BUF
518
519 ;----------------------------------------
520 ; void ff_clear_block(int16_t *blocks);
521 ;----------------------------------------
522 ; %1 = number of xmm registers used
523 ; %2 = number of inline store loops
524 %macro CLEAR_BLOCK 2
525 cglobal clear_block, 1, 1, %1, blocks
526     ZERO  m0, m0
527 %assign %%i 0
528 %rep %2
529     mova  [blocksq+mmsize*(0+%%i)], m0
530     mova  [blocksq+mmsize*(1+%%i)], m0
531     mova  [blocksq+mmsize*(2+%%i)], m0
532     mova  [blocksq+mmsize*(3+%%i)], m0
533     mova  [blocksq+mmsize*(4+%%i)], m0
534     mova  [blocksq+mmsize*(5+%%i)], m0
535     mova  [blocksq+mmsize*(6+%%i)], m0
536     mova  [blocksq+mmsize*(7+%%i)], m0
537 %assign %%i %%i+8
538 %endrep
539     RET
540 %endmacro
541
542 INIT_MMX mmx
543 %define ZERO pxor
544 CLEAR_BLOCK 0, 2
545 INIT_XMM sse
546 %define ZERO xorps
547 CLEAR_BLOCK 1, 1
548
549 ;-----------------------------------------
550 ; void ff_clear_blocks(int16_t *blocks);
551 ;-----------------------------------------
552 ; %1 = number of xmm registers used
553 %macro CLEAR_BLOCKS 1
554 cglobal clear_blocks, 1, 2, %1, blocks, len
555     add   blocksq, 768
556     mov      lenq, -768
557     ZERO       m0, m0
558 .loop
559     mova  [blocksq+lenq+mmsize*0], m0
560     mova  [blocksq+lenq+mmsize*1], m0
561     mova  [blocksq+lenq+mmsize*2], m0
562     mova  [blocksq+lenq+mmsize*3], m0
563     mova  [blocksq+lenq+mmsize*4], m0
564     mova  [blocksq+lenq+mmsize*5], m0
565     mova  [blocksq+lenq+mmsize*6], m0
566     mova  [blocksq+lenq+mmsize*7], m0
567     add   lenq, mmsize*8
568     js .loop
569     RET
570 %endmacro
571
572 INIT_MMX mmx
573 %define ZERO pxor
574 CLEAR_BLOCKS 0
575 INIT_XMM sse
576 %define ZERO xorps
577 CLEAR_BLOCKS 1
578
579 ;--------------------------------------------------------------------------
580 ;void ff_put_signed_pixels_clamped(const int16_t *block, uint8_t *pixels,
581 ;                                  int line_size)
582 ;--------------------------------------------------------------------------
583
584 %macro PUT_SIGNED_PIXELS_CLAMPED_HALF 1
585     mova     m1, [blockq+mmsize*0+%1]
586     mova     m2, [blockq+mmsize*2+%1]
587 %if mmsize == 8
588     mova     m3, [blockq+mmsize*4+%1]
589     mova     m4, [blockq+mmsize*6+%1]
590 %endif
591     packsswb m1, [blockq+mmsize*1+%1]
592     packsswb m2, [blockq+mmsize*3+%1]
593 %if mmsize == 8
594     packsswb m3, [blockq+mmsize*5+%1]
595     packsswb m4, [blockq+mmsize*7+%1]
596 %endif
597     paddb    m1, m0
598     paddb    m2, m0
599 %if mmsize == 8
600     paddb    m3, m0
601     paddb    m4, m0
602     movq     [pixelsq+lsizeq*0], m1
603     movq     [pixelsq+lsizeq*1], m2
604     movq     [pixelsq+lsizeq*2], m3
605     movq     [pixelsq+lsize3q ], m4
606 %else
607     movq     [pixelsq+lsizeq*0], m1
608     movhps   [pixelsq+lsizeq*1], m1
609     movq     [pixelsq+lsizeq*2], m2
610     movhps   [pixelsq+lsize3q ], m2
611 %endif
612 %endmacro
613
614 %macro PUT_SIGNED_PIXELS_CLAMPED 1
615 cglobal put_signed_pixels_clamped, 3, 4, %1, block, pixels, lsize, lsize3
616     mova     m0, [pb_80]
617     lea      lsize3q, [lsizeq*3]
618     PUT_SIGNED_PIXELS_CLAMPED_HALF 0
619     lea      pixelsq, [pixelsq+lsizeq*4]
620     PUT_SIGNED_PIXELS_CLAMPED_HALF 64
621     RET
622 %endmacro
623
624 INIT_MMX mmx
625 PUT_SIGNED_PIXELS_CLAMPED 0
626 INIT_XMM sse2
627 PUT_SIGNED_PIXELS_CLAMPED 3
628
629 ;-----------------------------------------------------
630 ;void ff_vector_clipf(float *dst, const float *src,
631 ;                     float min, float max, int len)
632 ;-----------------------------------------------------
633 INIT_XMM sse
634 %if ARCH_X86_32
635 cglobal vector_clipf, 5,5,6, dst, src, min, max, len
636 %else
637 cglobal vector_clipf, 3,3,6, dst, src, len
638 %endif
639 %if WIN64
640     SWAP 0, 2
641     SWAP 1, 3
642 %elif ARCH_X86_32
643     movss   m0, minm
644     movss   m1, maxm
645 %endif
646     SPLATD  m0
647     SPLATD  m1
648         shl lenq, 2
649         add srcq, lenq
650         add dstq, lenq
651         neg lenq
652 .loop:
653     mova    m2,  [srcq+lenq+mmsize*0]
654     mova    m3,  [srcq+lenq+mmsize*1]
655     mova    m4,  [srcq+lenq+mmsize*2]
656     mova    m5,  [srcq+lenq+mmsize*3]
657     maxps   m2, m0
658     maxps   m3, m0
659     maxps   m4, m0
660     maxps   m5, m0
661     minps   m2, m1
662     minps   m3, m1
663     minps   m4, m1
664     minps   m5, m1
665     mova    [dstq+lenq+mmsize*0], m2
666     mova    [dstq+lenq+mmsize*1], m3
667     mova    [dstq+lenq+mmsize*2], m4
668     mova    [dstq+lenq+mmsize*3], m5
669     add     lenq, mmsize*4
670     jl .loop
671     REP_RET