[cvs] / xvidcore / src / quant / x86_asm / quantize_h263_mmx.asm Repository:
ViewVC logotype

Diff of /xvidcore/src/quant/x86_asm/quantize_h263_mmx.asm

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.1, Tue Oct 7 13:02:35 2003 UTC revision 1.1.2.2, Thu Oct 9 18:50:22 2003 UTC
# Line 0  Line 1 
1    ;/*****************************************************************************
2    ; *
3    ; *  XVID MPEG-4 VIDEO CODEC
4    ; *  - MPEG4 Quantization H263 implementation / MMX optimized -
5    ; *
6    ; *  Copyright(C) 2001-2003 Peter Ross <pross@xvid.org>
7    ; *               2002-2003 Pascal Massimino <skal@planet-d.net>
8    ; *
9    ; *  This program is free software ; you can redistribute it and/or modify
10    ; *  it under the terms of the GNU General Public License as published by
11    ; *  the Free Software Foundation ; either version 2 of the License, or
12    ; *  (at your option) any later version.
13    ; *
14    ; *  This program 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
17    ; *  GNU General Public License for more details.
18    ; *
19    ; *  You should have received a copy of the GNU General Public License
20    ; *  along with this program ; if not, write to the Free Software
21    ; *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
22    ; *
23    ; * $Id$
24    ; *
25    ; ****************************************************************************/
26    
27    ; enable dequant saturate [-2048,2047], test purposes only.
28    %define SATURATE
29    
30    ; data/text alignment
31    %define ALIGN 8
32    
33    bits 32
34    
35    %macro cglobal 1
36           %ifdef PREFIX
37                    global _%1
38                    %define %1 _%1
39            %else
40                    global %1
41            %endif
42    %endmacro
43    
44    ;***************************************************************************
45    ; Local data
46    ;***************************************************************************
47    
48    %ifdef FORMAT_COFF
49    section .data data
50    %else
51    section .data data align=16
52    %endif
53    
54    align 16
55    plus_one:
56            times 8 dw 1
57    
58    ;===========================================================================
59    ;
60    ; subtract by Q/2 table
61    ;
62    ;===========================================================================
63    
64    align 16
65    mmx_sub:
66    %assign quant 1
67    %rep 31
68            times 4 dw  quant / 2
69            %assign quant quant+1
70    %endrep
71    
72    ;===========================================================================
73    ;
74    ; divide by 2Q table
75    ;
76    ; use a shift of 16 to take full advantage of _pmulhw_
77    ; for q=1, _pmulhw_ will overflow so it is treated seperately
78    ; (3dnow2 provides _pmulhuw_ which wont cause overflow)
79    ;
80    ;===========================================================================
81    
82    align 16
83    mmx_div:
84    %assign quant 1
85    %rep 31
86            times 4 dw  (1<<16) / (quant*2) + 1
87            %assign quant quant+1
88    %endrep
89    
90    ;===========================================================================
91    ;
92    ; add by (odd(Q) ? Q : Q - 1) table
93    ;
94    ;===========================================================================
95    
96    align 16
97    mmx_add:
98    %assign quant 1
99    %rep 31
100            %if quant % 2 != 0
101            times 4 dw  quant
102            %else
103            times 4 dw quant - 1
104            %endif
105            %assign quant quant+1
106    %endrep
107    
108    ;===========================================================================
109    ;
110    ; multiple by 2Q table
111    ;
112    ;===========================================================================
113    
114    align 16
115    mmx_mul:
116    %assign quant 1
117    %rep 31
118            times 4 dw  quant*2
119            %assign quant quant+1
120    %endrep
121    
122    ;===========================================================================
123    ;
124    ; saturation limits
125    ;
126    ;===========================================================================
127    
128    align 16
129    sse2_2047:
130            times 8 dw 2047
131    
132    align 16
133    mmx_2047:
134            times 4 dw 2047
135    
136    align 8
137    mmx_32768_minus_2048:
138            times 4 dw (32768-2048)
139    
140    mmx_32767_minus_2047:
141            times 4 dw (32767-2047)
142    
143    
144    ;***************************************************************************
145    ; Code
146    ;***************************************************************************
147    
148    section .text
149    
150    
151    ;===========================================================================
152    ;
153    ; uint32_t quant_h263_intra_mmx(int16_t * coeff,
154    ;                               const int16_t const * data,
155    ;                               const uint32_t quant,
156    ;                               const uint32_t dcscalar);
157    ;
158    ;===========================================================================
159    
160    align ALIGN
161    cglobal quant_h263_intra_mmx
162    quant_h263_intra_mmx:
163    
164            push    ecx
165            push    esi
166            push    edi
167    
168            mov             edi, [esp + 12 + 4]     ; coeff
169            mov             esi, [esp + 12 + 8]     ; data
170            mov             eax, [esp + 12 + 12]    ; quant
171    
172            xor             ecx, ecx
173            cmp             al, 1
174            jz              .q1loop
175    
176            movq    mm7, [mmx_div + eax * 8 - 8]
177    
178    align ALIGN
179    .loop
180            movq    mm0, [esi + 8*ecx]      ; mm0 = [1st]
181            movq    mm3, [esi + 8*ecx + 8]
182            pxor    mm1, mm1                ; mm1 = 0
183            pxor    mm4, mm4                ;
184            pcmpgtw mm1, mm0                ; mm1 = (0 > mm0)
185            pcmpgtw mm4, mm3                ;
186            pxor    mm0, mm1                ; mm0 = |mm0|
187            pxor    mm3, mm4                ;
188            psubw   mm0, mm1                ; displace
189            psubw   mm3, mm4                ;
190            pmulhw  mm0, mm7                ; mm0 = (mm0 / 2Q) >> 16
191            pmulhw  mm3, mm7                ;
192            pxor    mm0, mm1                ; mm0 *= sign(mm0)
193            pxor    mm3, mm4                ;
194            psubw   mm0, mm1                ; undisplace
195            psubw   mm3, mm4                ;
196            movq    [edi + 8*ecx], mm0
197            movq    [edi + 8*ecx + 8], mm3
198    
199            add             ecx, 2
200            cmp             ecx, 16
201            jnz             .loop
202    
203    .done
204    
205            ; caclulate  data[0] // (int32_t)dcscalar)
206            mov     ecx, [esp + 12 + 16]    ; dcscalar
207            mov     edx, ecx
208            movsx   eax, word [esi]         ; data[0]
209            shr     edx, 1                  ; edx = dcscalar /2
210            cmp             eax, 0
211            jg              .gtzero
212    
213            sub             eax, edx
214            jmp             short .mul
215    
216    .gtzero
217            add             eax, edx
218    .mul
219            cdq                 ; expand eax -> edx:eax
220            idiv    ecx         ; eax = edx:eax / dcscalar
221            mov             [edi], ax   ; coeff[0] = ax
222    
223            xor             eax, eax    ; return(0);
224            pop             edi
225            pop             esi
226            pop             ecx
227    
228            ret
229    
230    align ALIGN
231    .q1loop
232            movq    mm0, [esi + 8*ecx]      ; mm0 = [1st]
233            movq    mm3, [esi + 8*ecx + 8]
234            pxor    mm1, mm1                ; mm1 = 0
235            pxor    mm4, mm4                ;
236            pcmpgtw mm1, mm0                ; mm1 = (0 > mm0)
237            pcmpgtw mm4, mm3                ;
238            pxor    mm0, mm1                ; mm0 = |mm0|
239            pxor    mm3, mm4                ;
240            psubw   mm0, mm1                ; displace
241            psubw   mm3, mm4                ;
242            psrlw   mm0, 1                  ; mm0 >>= 1   (/2)
243            psrlw   mm3, 1                  ;
244            pxor    mm0, mm1                ; mm0 *= sign(mm0)
245            pxor    mm3, mm4
246        psubw       mm0, mm1                ; undisplace
247            psubw   mm3, mm4                ;
248            movq    [edi + 8*ecx], mm0
249            movq    [edi + 8*ecx + 8], mm3
250    
251            add             ecx, 2
252            cmp             ecx, 16
253            jnz             .q1loop
254            jmp             short .done
255    
256    
257    
258    ;===========================================================================
259    ;
260    ; uint32_t quant_h263_intra_sse2(int16_t * coeff,
261    ;                                const int16_t const * data,
262    ;                                const uint32_t quant,
263    ;                                const uint32_t dcscalar);
264    ;
265    ;===========================================================================
266    
267    align ALIGN
268    cglobal quant_h263_intra_sse2
269    quant_h263_intra_sse2:
270    
271            push    esi
272            push    edi
273    
274            mov             edi, [esp + 8 + 4]                ; coeff
275            mov             esi, [esp + 8 + 8]                ; data
276            mov             eax, [esp + 8 + 12]               ; quant
277    
278            xor             ecx, ecx
279            cmp             al, 1
280            jz              near .qas2_q1loop
281    
282    .qas2_not1
283            movq    mm7, [mmx_div + eax*8 - 8]
284            movq2dq xmm7, mm7
285            movlhps xmm7, xmm7
286    
287    align 16
288    .qas2_loop
289            movdqa  xmm0, [esi + ecx*8]                ; xmm0 = [1st]
290            movdqa  xmm3, [esi + ecx*8 + 16]           ; xmm3 = [2nd]
291            pxor    xmm1, xmm1
292            pxor    xmm4, xmm4
293            pcmpgtw xmm1, xmm0
294            pcmpgtw xmm4, xmm3
295            pxor    xmm0, xmm1
296            pxor    xmm3, xmm4
297            psubw   xmm0, xmm1
298            psubw   xmm3, xmm4
299            pmulhw  xmm0, xmm7
300            pmulhw  xmm3, xmm7
301            pxor    xmm0, xmm1
302            pxor    xmm3, xmm4
303            psubw   xmm0, xmm1
304            psubw   xmm3, xmm4
305            movdqa  [edi + ecx*8], xmm0
306            movdqa  [edi + ecx*8 + 16], xmm3
307    
308            add             ecx, 4
309            cmp             ecx, 16
310            jnz     .qas2_loop
311    
312    .qas2_done
313            mov     ecx, [esp + 8 + 16]     ; dcscalar
314            mov     edx, ecx
315            movsx   eax, word [esi]
316            shr     edx, 1
317            cmp             eax, 0
318            jg              .qas2_gtzero
319    
320            sub             eax, edx
321            jmp             short .qas2_mul
322    
323    .qas2_gtzero
324            add             eax, edx
325    
326    .qas2_mul
327            cdq
328            idiv    ecx
329    
330            mov             [edi], ax
331    
332            xor             eax, eax                ; return(0);
333            pop             edi
334            pop             esi
335    
336            ret
337    
338    align 16
339    .qas2_q1loop
340            movdqa  xmm0, [esi + ecx*8]         ; xmm0 = [1st]
341            movdqa  xmm3, [esi + ecx*8 + 16]    ; xmm3 = [2nd]
342            pxor    xmm1, xmm1
343            pxor    xmm4, xmm4
344            pcmpgtw xmm1, xmm0
345            pcmpgtw xmm4, xmm3
346            pxor    xmm0, xmm1
347            pxor    xmm3, xmm4
348            psubw   xmm0, xmm1
349            psubw   xmm3, xmm4
350            psrlw   xmm0, 1
351            psrlw   xmm3, 1
352            pxor    xmm0, xmm1
353            pxor    xmm3, xmm4
354            psubw   xmm0, xmm1
355            psubw   xmm3, xmm4
356            movdqa  [edi + ecx*8], xmm0
357            movdqa  [edi + ecx*8 + 16], xmm3
358    
359            add             ecx, 4
360            cmp             ecx, 16
361            jnz             .qas2_q1loop
362            jmp             near .qas2_done
363    
364    
365    
366    ;===========================================================================
367    ;
368    ; uint32_t quant_h263_inter_mmx(int16_t * coeff,
369    ;                               const int16_t const * data,
370    ;                               const uint32_t quant);
371    ;
372    ;===========================================================================
373    
374    align ALIGN
375    cglobal quant_h263_inter_mmx
376    quant_h263_inter_mmx:
377    
378            push    ecx
379            push    esi
380            push    edi
381    
382            mov             edi, [esp + 12 + 4]         ; coeff
383            mov             esi, [esp + 12 + 8]         ; data
384            mov             eax, [esp + 12 + 12]        ; quant
385    
386            xor             ecx, ecx
387    
388            pxor    mm5, mm5                    ; sum
389            movq    mm6, [mmx_sub + eax * 8 - 8]; sub
390    
391            cmp             al, 1
392            jz              .q1loop
393    
394            movq    mm7, [mmx_div + eax * 8 - 8] ; divider
395    
396    align ALIGN
397    .loop
398            movq    mm0, [esi + 8*ecx]      ; mm0 = [1st]
399            movq    mm3, [esi + 8*ecx + 8]
400            pxor    mm1, mm1                ; mm1 = 0
401            pxor    mm4, mm4                ;
402            pcmpgtw mm1, mm0                ; mm1 = (0 > mm0)
403            pcmpgtw mm4, mm3                ;
404            pxor    mm0, mm1                ; mm0 = |mm0|
405            pxor    mm3, mm4                ;
406            psubw   mm0, mm1                ; displace
407            psubw   mm3, mm4                ;
408            psubusw mm0, mm6                ; mm0 -= sub (unsigned, dont go < 0)
409            psubusw mm3, mm6                ;
410            pmulhw  mm0, mm7                ; mm0 = (mm0 / 2Q) >> 16
411            pmulhw  mm3, mm7                ;
412            paddw   mm5, mm0                ; sum += mm0
413            pxor    mm0, mm1                ; mm0 *= sign(mm0)
414            paddw   mm5, mm3                ;
415            pxor    mm3, mm4                ;
416            psubw   mm0, mm1                ; undisplace
417            psubw   mm3, mm4
418            movq    [edi + 8*ecx], mm0
419            movq    [edi + 8*ecx + 8], mm3
420    
421            add             ecx, 2
422            cmp             ecx, 16
423            jnz             .loop
424    
425    .done
426            pmaddwd mm5, [plus_one]
427            movq    mm0, mm5
428            psrlq   mm5, 32
429            paddd   mm0, mm5
430    
431            movd    eax, mm0                ; return sum
432            pop             edi
433            pop             esi
434            pop     ecx
435    
436            ret
437    
438    align ALIGN
439    .q1loop
440            movq    mm0, [esi + 8*ecx]              ; mm0 = [1st]
441            movq    mm3, [esi + 8*ecx+ 8]           ;
442            pxor    mm1, mm1                ; mm1 = 0
443            pxor    mm4, mm4                ;
444            pcmpgtw mm1, mm0                ; mm1 = (0 > mm0)
445            pcmpgtw mm4, mm3                ;
446            pxor    mm0, mm1                ; mm0 = |mm0|
447            pxor    mm3, mm4                ;
448            psubw   mm0, mm1                ; displace
449            psubw   mm3, mm4                ;
450            psubusw mm0, mm6                ; mm0 -= sub (unsigned, dont go < 0)
451            psubusw mm3, mm6                ;
452            psrlw   mm0, 1                  ; mm0 >>= 1   (/2)
453            psrlw   mm3, 1                  ;
454            paddw   mm5, mm0                ; sum += mm0
455            pxor    mm0, mm1                ; mm0 *= sign(mm0)
456            paddw   mm5, mm3                ;
457            pxor    mm3, mm4                ;
458            psubw   mm0, mm1                ; undisplace
459            psubw   mm3, mm4
460            movq    [edi + 8*ecx], mm0
461            movq    [edi + 8*ecx + 8], mm3
462    
463            add             ecx, 2
464            cmp             ecx, 16
465            jnz             .q1loop
466    
467            jmp             .done
468    
469    
470    
471    ;===========================================================================
472    ;
473    ; uint32_t quant_h263_inter_sse2(int16_t * coeff,
474    ;                                const int16_t const * data,
475    ;                                const uint32_t quant);
476    ;
477    ;===========================================================================
478    
479    align 16
480    cglobal quant_h263_inter_sse2
481    quant_h263_inter_sse2:
482    
483            push    esi
484            push    edi
485    
486            mov             edi, [esp + 8 + 4]      ; coeff
487            mov             esi, [esp + 8 + 8]      ; data
488            mov             eax, [esp + 8 + 12]     ; quant
489    
490            xor             ecx, ecx
491    
492            pxor    xmm5, xmm5                      ; sum
493    
494            movq    mm0, [mmx_sub + eax*8 - 8]  ; sub
495            movq2dq xmm6, mm0                       ; load into low 8 bytes
496            movlhps xmm6, xmm6                      ; duplicate into high 8 bytes
497    
498            cmp             al, 1
499            jz              near .qes2_q1loop
500    
501    .qes2_not1
502            movq    mm0, [mmx_div + eax*8 - 8]  ; divider
503            movq2dq xmm7, mm0
504            movlhps xmm7, xmm7
505    
506    align 16
507    .qes2_loop
508            movdqa  xmm0, [esi + ecx*8]                ; xmm0 = [1st]
509            movdqa  xmm3, [esi + ecx*8 + 16]           ; xmm3 = [2nd]
510            pxor    xmm1, xmm1
511            pxor    xmm4, xmm4
512            pcmpgtw xmm1, xmm0
513            pcmpgtw xmm4, xmm3
514            pxor    xmm0, xmm1
515            pxor    xmm3, xmm4
516            psubw   xmm0, xmm1
517            psubw   xmm3, xmm4
518            psubusw xmm0, xmm6
519            psubusw xmm3, xmm6
520            pmulhw  xmm0, xmm7
521            pmulhw  xmm3, xmm7
522            paddw   xmm5, xmm0
523            pxor    xmm0, xmm1
524            paddw   xmm5, xmm3
525            pxor    xmm3, xmm4
526            psubw   xmm0, xmm1
527            psubw   xmm3, xmm4
528            movdqa  [edi + ecx*8], xmm0
529            movdqa  [edi + ecx*8 + 16], xmm3
530    
531            add             ecx, 4
532            cmp             ecx, 16
533            jnz             .qes2_loop
534    
535    .qes2_done
536            movdqu  xmm6, [plus_one]
537            pmaddwd xmm5, xmm6
538            movhlps xmm6, xmm5
539            paddd   xmm5, xmm6
540            movdq2q mm0, xmm5
541    
542            movq    mm5, mm0
543            psrlq   mm5, 32
544            paddd   mm0, mm5
545    
546            movd    eax, mm0                        ; return sum
547    
548            pop     edi
549            pop     esi
550    
551            ret
552    
553    align 16
554    .qes2_q1loop
555            movdqa  xmm0, [esi + ecx*8]             ; xmm0 = [1st]
556            movdqa  xmm3, [esi + ecx*8 + 16]        ; xmm3 = [2nd]
557            pxor    xmm1, xmm1
558            pxor    xmm4, xmm4
559            pcmpgtw xmm1, xmm0
560            pcmpgtw xmm4, xmm3
561            pxor    xmm0, xmm1
562            pxor    xmm3, xmm4
563            psubw   xmm0, xmm1
564            psubw   xmm3, xmm4
565            psubusw xmm0, xmm6
566            psubusw xmm3, xmm6
567            psrlw   xmm0, 1
568            psrlw   xmm3, 1
569            paddw   xmm5, xmm0
570            pxor    xmm0, xmm1
571            paddw   xmm5, xmm3
572            pxor    xmm3, xmm4
573            psubw   xmm0, xmm1
574            psubw   xmm3, xmm4
575            movdqa  [edi + ecx*8], xmm0
576            movdqa  [edi + ecx*8 + 16], xmm3
577    
578            add             ecx, 4
579            cmp             ecx, 16
580            jnz             .qes2_q1loop
581            jmp             .qes2_done
582    
583    
584    ;===========================================================================
585    ;
586    ; uint32_t dequant_h263_intra_mmx(int16_t *data,
587    ;                                 const int16_t const *coeff,
588    ;                                 const uint32_t quant,
589    ;                                 const uint32_t dcscalar);
590    ;
591    ;===========================================================================
592    
593      ; note: we only saturate to +2047 *before* restoring the sign.
594      ; Hence, final clamp really is [-2048,2047]
595    
596    align ALIGN
597    cglobal dequant_h263_intra_mmx
598    dequant_h263_intra_mmx:
599    
600            mov             edx, [esp+ 4]                   ; data
601            mov             ecx, [esp+ 8]                   ; coeff
602            mov             eax, [esp+12]                   ; quant
603            movq    mm6, [mmx_add + eax*8 - 8]      ; quant or quant-1
604            movq    mm7, [mmx_mul + eax*8 - 8]      ; 2*quant
605            mov             eax, -16
606    
607    align ALIGN
608    .loop
609            movq    mm0, [ecx+8*eax+8*16]           ; c  = coeff[i]
610            movq    mm3, [ecx+8*eax+8*16 + 8]       ; c' = coeff[i+1]
611            pxor    mm1, mm1
612            pxor    mm4, mm4
613            pcmpgtw mm1, mm0                        ; sign(c)
614            pcmpgtw mm4, mm3                        ; sign(c')
615            pxor    mm2, mm2
616            pxor    mm5, mm5
617            pcmpeqw mm2, mm0                        ; c is zero
618            pcmpeqw mm5, mm3                        ; c' is zero
619            pandn   mm2, mm6                        ; offset = isZero ? 0 : quant_add
620            pandn   mm5, mm6
621            pxor    mm0, mm1                        ; negate if negative
622            pxor    mm3, mm4                        ; negate if negative
623            psubw   mm0, mm1
624            psubw   mm3, mm4
625            pmullw  mm0, mm7                        ; *= 2Q
626            pmullw  mm3, mm7                        ; *= 2Q
627            paddw   mm0, mm2                        ; + offset
628            paddw   mm3, mm5                        ; + offset
629            paddw   mm0, mm1                        ; negate back
630            paddw   mm3, mm4                        ; negate back
631    
632            ; saturates to +2047
633            movq    mm2, [mmx_32767_minus_2047]
634            add             eax, 2
635            paddsw  mm0, mm2
636            paddsw  mm3, mm2
637            psubsw  mm0, mm2
638            psubsw  mm3, mm2
639    
640            pxor    mm0, mm1
641            pxor    mm3, mm4
642            movq    [edx + 8*eax + 8*16   - 2*8], mm0
643            movq    [edx + 8*eax + 8*16+8 - 2*8], mm3
644            jnz             near .loop
645    
646            ; deal with DC
647            movd    mm0, [ecx]
648            pmullw  mm0, [esp+16]                   ; dcscalar
649            movq    mm2, [mmx_32767_minus_2047]
650            paddsw  mm0, mm2
651            psubsw  mm0, mm2
652            movq    mm3, [mmx_32768_minus_2048]
653            psubsw  mm0, mm3
654            paddsw  mm0, mm3
655            movd    eax, mm0
656            mov             [edx], ax
657    
658            xor              eax, eax                               ; return(0);
659            ret
660    
661    ;===========================================================================
662    ;
663    ; uint32_t dequant_h263_intra_xmm(int16_t *data,
664    ;                                 const int16_t const *coeff,
665    ;                                 const uint32_t quant,
666    ;                                 const uint32_t dcscalar);
667    ;
668    ;===========================================================================
669    
670      ; this is the same as dequant_inter_mmx, except that we're
671      ; saturating using 'pminsw' (saves 2 cycles/loop => ~5% faster)
672    
673    align ALIGN
674    cglobal dequant_h263_intra_xmm
675    dequant_h263_intra_xmm:
676    
677            mov             edx, [esp+ 4]        ; data
678            mov             ecx, [esp+ 8]        ; coeff
679            mov             eax, [esp+12]        ; quant
680            movq    mm6, [mmx_add + eax*8 - 8]  ; quant or quant-1
681            movq    mm7, [mmx_mul + eax*8 - 8]  ; 2*quant
682            mov             eax, -16
683    
684    align ALIGN
685    .loop
686            movq    mm0, [ecx+8*eax+8*16]      ; c  = coeff[i]
687            movq    mm3, [ecx+8*eax+8*16 + 8]  ; c' = coeff[i+1]
688            pxor    mm1, mm1
689            pxor    mm4, mm4
690            pcmpgtw mm1, mm0  ; sign(c)
691            pcmpgtw mm4, mm3  ; sign(c')
692            pxor    mm2, mm2
693            pxor    mm5, mm5
694            pcmpeqw mm2, mm0  ; c is zero
695            pcmpeqw mm5, mm3  ; c' is zero
696            pandn   mm2, mm6    ; offset = isZero ? 0 : quant_add
697            pandn   mm5, mm6
698            pxor    mm0, mm1     ; negate if negative
699            pxor    mm3, mm4     ; negate if negative
700            psubw   mm0, mm1
701            psubw   mm3, mm4
702            pmullw  mm0, mm7 ; *= 2Q
703            pmullw  mm3, mm7 ; *= 2Q
704            paddw   mm0, mm2 ; + offset
705            paddw   mm3, mm5 ; + offset
706            paddw   mm0, mm1 ; negate back
707            paddw   mm3, mm4 ; negate back
708    
709       ; saturates to +2047
710            movq    mm2, [mmx_2047]
711            pminsw  mm0, mm2
712            add             eax, 2
713            pminsw  mm3, mm2
714    
715            pxor    mm0, mm1
716            pxor    mm3, mm4
717            movq    [edx + 8*eax + 8*16   - 2*8], mm0
718            movq    [edx + 8*eax + 8*16+8 - 2*8], mm3
719            jnz             near .loop
720    
721        ; deal with DC
722            movd    mm0, [ecx]
723            pmullw  mm0, [esp+16]    ; dcscalar
724            movq    mm2, [mmx_32767_minus_2047]
725            paddsw  mm0, mm2
726            psubsw  mm0, mm2
727            movq    mm2, [mmx_32768_minus_2048]
728            psubsw  mm0, mm2
729            paddsw  mm0, mm2
730            movd    eax, mm0
731            mov             [edx], ax
732    
733            xor             eax, eax
734            ret
735    
736    
737    ;===========================================================================
738    ;
739    ; uint32_t dequant_h263_intra_sse2(int16_t *data,
740    ;                                  const int16_t const *coeff,
741    ;                                  const uint32_t quant,
742    ;                                  const uint32_t dcscalar);
743    ;
744    ;===========================================================================
745    
746    align ALIGN
747    cglobal dequant_h263_intra_sse2
748    dequant_h263_intra_sse2:
749            mov             edx, [esp+ 4]        ; data
750            mov             ecx, [esp+ 8]        ; coeff
751            mov             eax, [esp+12]        ; quant
752            movq    mm6, [mmx_add + eax * 8 - 8]
753            movq    mm7, [mmx_mul + eax * 8 - 8]
754            movq2dq xmm6, mm6
755            movq2dq xmm7, mm7
756            movlhps xmm6, xmm6
757            movlhps xmm7, xmm7
758            mov             eax, -16
759    
760    align ALIGN
761    .loop
762            movdqa  xmm0, [ecx + 8*16 + 8*eax]      ; c  = coeff[i]
763            movdqa  xmm3, [ecx + 8*16 + 8*eax+ 16]
764            pxor    xmm1, xmm1
765            pxor    xmm4, xmm4
766            pcmpgtw xmm1, xmm0  ; sign(c)
767            pcmpgtw xmm4, xmm3
768            pxor    xmm2, xmm2
769            pxor    xmm5, xmm5
770            pcmpeqw xmm2, xmm0  ; c is zero
771            pcmpeqw xmm5, xmm3
772            pandn   xmm2, xmm6    ; offset = isZero ? 0 : quant_add
773            pandn   xmm5, xmm6
774            pxor    xmm0, xmm1     ; negate if negative
775            pxor    xmm3, xmm4
776            psubw   xmm0, xmm1
777            psubw   xmm3, xmm4
778            pmullw  xmm0, xmm7 ; *= 2Q
779            pmullw  xmm3, xmm7
780            paddw   xmm0, xmm2 ; + offset
781            paddw   xmm3, xmm5
782            paddw   xmm0, xmm1 ; negate back
783            paddw   xmm3, xmm4
784    
785            ; saturates to +2047
786            movdqa  xmm2, [sse2_2047]
787            pminsw  xmm0, xmm2
788            add             eax, 4
789            pminsw  xmm3, xmm2
790    
791            pxor    xmm0, xmm1
792            pxor    xmm3, xmm4
793            movdqa  [edx + 8*16 - 8*4 + 8*eax], xmm0
794            movdqa  [edx + 8*16 - 8*4 + 8*eax + 16], xmm3
795            jnz             near .loop
796    
797            ; deal with DC
798            movd    mm0, [ecx]
799            pmullw  mm0, [esp+16]    ; dcscalar
800            movq    mm2, [mmx_32767_minus_2047]
801            paddsw  mm0, mm2
802            psubsw  mm0, mm2
803            movq    mm2, [mmx_32768_minus_2048]
804            psubsw  mm0, mm2
805            paddsw  mm0, mm2
806            movd    eax, mm0
807            mov             [edx], ax
808    
809            xor             eax, eax
810            ret
811    
812    ;===========================================================================
813    ;
814    ; uint32t dequant_h263_inter_mmx(int16_t * data,
815    ;                                const int16_t * const coeff,
816    ;                                const uint32_t quant);
817    ;
818    ;===========================================================================
819    
820    align ALIGN
821    cglobal dequant_h263_inter_mmx
822    dequant_h263_inter_mmx:
823    
824            mov             edx, [esp+ 4]        ; data
825            mov             ecx, [esp+ 8]        ; coeff
826            mov             eax, [esp+12]        ; quant
827            movq    mm6, [mmx_add + eax*8 - 8]  ; quant or quant-1
828            movq    mm7, [mmx_mul + eax*8 - 8]  ; 2*quant
829            mov             eax, -16
830    
831    align ALIGN
832    .loop
833            movq    mm0, [ecx+8*eax+8*16]      ; c  = coeff[i]
834            movq    mm3, [ecx+8*eax+8*16 + 8]  ; c' = coeff[i+1]
835            pxor    mm1, mm1
836            pxor    mm4, mm4
837            pcmpgtw mm1, mm0  ; sign(c)
838            pcmpgtw mm4, mm3  ; sign(c')
839            pxor    mm2, mm2
840            pxor    mm5, mm5
841            pcmpeqw mm2, mm0  ; c is zero
842            pcmpeqw mm5, mm3  ; c' is zero
843            pandn   mm2, mm6    ; offset = isZero ? 0 : quant_add
844            pandn   mm5, mm6
845            pxor    mm0, mm1     ; negate if negative
846            pxor    mm3, mm4     ; negate if negative
847            psubw   mm0, mm1
848            psubw   mm3, mm4
849            pmullw  mm0, mm7 ; *= 2Q
850            pmullw  mm3, mm7 ; *= 2Q
851            paddw   mm0, mm2 ; + offset
852            paddw   mm3, mm5 ; + offset
853            paddw   mm0, mm1 ; negate back
854            paddw   mm3, mm4 ; negate back
855                                                            ; saturates to +2047
856            movq    mm2, [mmx_32767_minus_2047]
857            add             eax, 2
858            paddsw  mm0, mm2
859            paddsw  mm3, mm2
860            psubsw  mm0, mm2
861            psubsw  mm3, mm2
862    
863            pxor    mm0, mm1
864            pxor    mm3, mm4
865            movq    [edx + 8*eax + 8*16   - 2*8], mm0
866            movq    [edx + 8*eax + 8*16+8 - 2*8], mm3
867            jnz             near .loop
868    
869            xor             eax, eax
870            ret
871    
872    ;===========================================================================
873    ;
874    ; uint32_t dequant_h263_inter_xmm(int16_t * data,
875    ;                                 const int16_t * const coeff,
876    ;                                 const uint32_t quant);
877    ;
878    ;===========================================================================
879    
880      ; this is the same as dequant_inter_mmx,
881      ; except that we're saturating using 'pminsw' (saves 2 cycles/loop)
882    
883    align ALIGN
884    cglobal dequant_h263_inter_xmm
885    dequant_h263_inter_xmm:
886    
887            mov             edx, [esp+ 4]        ; data
888            mov             ecx, [esp+ 8]        ; coeff
889            mov             eax, [esp+12]        ; quant
890            movq    mm6, [mmx_add + eax*8 - 8]  ; quant or quant-1
891            movq    mm7, [mmx_mul + eax*8 - 8]  ; 2*quant
892            mov             eax, -16
893    
894    align ALIGN
895    .loop
896            movq    mm0, [ecx+8*eax+8*16]      ; c  = coeff[i]
897            movq    mm3, [ecx+8*eax+8*16 + 8]  ; c' = coeff[i+1]
898            pxor    mm1, mm1
899            pxor    mm4, mm4
900            pcmpgtw mm1, mm0  ; sign(c)
901            pcmpgtw mm4, mm3  ; sign(c')
902            pxor    mm2, mm2
903            pxor    mm5, mm5
904            pcmpeqw mm2, mm0  ; c is zero
905            pcmpeqw mm5, mm3  ; c' is zero
906            pandn   mm2, mm6    ; offset = isZero ? 0 : quant_add
907            pandn   mm5, mm6
908            pxor    mm0, mm1     ; negate if negative
909            pxor    mm3, mm4     ; negate if negative
910            psubw   mm0, mm1
911            psubw   mm3, mm4
912            pmullw  mm0, mm7 ; *= 2Q
913            pmullw  mm3, mm7 ; *= 2Q
914            paddw   mm0, mm2 ; + offset
915            paddw   mm3, mm5 ; + offset
916            paddw   mm0, mm1 ; start restoring sign
917            paddw   mm3, mm4 ; start restoring sign
918                                                            ; saturates to +2047
919            movq    mm2, [mmx_2047]
920            pminsw  mm0, mm2
921            add             eax, 2
922            pminsw  mm3, mm2
923    
924            pxor    mm0, mm1 ; finish restoring sign
925            pxor    mm3, mm4 ; finish restoring sign
926            movq    [edx + 8*eax + 8*16   - 2*8], mm0
927            movq    [edx + 8*eax + 8*16+8 - 2*8], mm3
928            jnz             near .loop
929    
930            xor             eax, eax
931            ret
932    
933    ;===========================================================================
934    ;
935    ; uint32_t dequant_h263_inter_sse2(int16_t * data,
936    ;                                  const int16_t * const coeff,
937    ;                                  const uint32_t quant);
938    ;
939    ;===========================================================================
940    
941    align ALIGN
942    cglobal dequant_h263_inter_sse2
943    dequant_h263_inter_sse2:
944            mov             edx, [esp + 4]  ; data
945            mov             ecx, [esp + 8]  ; coeff
946            mov             eax, [esp + 12] ; quant
947            movq    mm6, [mmx_add + eax * 8 - 8]
948            movq    mm7, [mmx_mul + eax * 8 - 8]
949            movq2dq xmm6, mm6
950            movq2dq xmm7, mm7
951            movlhps xmm6, xmm6
952            movlhps xmm7, xmm7
953            mov             eax, -16
954    
955    align ALIGN
956    .loop
957            movdqa  xmm0, [ecx + 8*16 + 8*eax]  ; c  = coeff[i]
958            movdqa  xmm3, [ecx + 8*16 + 8*eax + 16]
959    
960            pxor    xmm1, xmm1
961            pxor    xmm4, xmm4
962            pcmpgtw xmm1, xmm0  ; sign(c)
963            pcmpgtw xmm4, xmm3
964            pxor    xmm2, xmm2
965            pxor    xmm5, xmm5
966            pcmpeqw xmm2, xmm0  ; c is zero
967            pcmpeqw xmm5, xmm3
968            pandn   xmm2, xmm6
969            pandn   xmm5, xmm6
970            pxor    xmm0, xmm1  ; negate if negative
971            pxor    xmm3, xmm4
972            psubw   xmm0, xmm1
973            psubw   xmm3, xmm4
974            pmullw  xmm0, xmm7  ; *= 2Q
975            pmullw  xmm3, xmm7
976            paddw   xmm0, xmm2  ; + offset
977            paddw   xmm3, xmm5
978    
979            paddw   xmm0, xmm1  ; start restoring sign
980            paddw   xmm3, xmm4
981    
982            ; saturates to +2047
983            movdqa  xmm2, [sse2_2047]
984            pminsw  xmm0, xmm2
985            add             eax, 4
986            pminsw  xmm3, xmm2
987    
988            pxor    xmm0, xmm1 ; finish restoring sign
989            pxor    xmm3, xmm4
990            movdqa  [edx + 8*16 - 8*4 + 8*eax], xmm0
991            movdqa  [edx + 8*16 - 8*4 + 8*eax + 16], xmm3
992            jnz             near .loop
993    
994            xor             eax, eax
995            ret

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.1.2.2

No admin address has been configured
ViewVC Help
Powered by ViewVC 1.0.4