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

Diff of /xvidcore/src/quant/x86_asm/quantize_mpeg_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    ; *  - 3dne Quantization/Dequantization -
5    ; *
6    ; *  Copyright (C) 2002-2003 Peter Ross <pross@xvid.org>
7    ; *                2002-2003 Michael Militzer <isibaar@xvid.org>
8    ; *                2002-2003 Pascal Massimino <skal@planet-d.net>
9    ; *
10    ; *  This program is free software ; you can redistribute it and/or modify
11    ; *  it under the terms of the GNU General Public License as published by
12    ; *  the Free Software Foundation ; either version 2 of the License, or
13    ; *  (at your option) any later version.
14    ; *
15    ; *  This program 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
18    ; *  GNU General Public License for more details.
19    ; *
20    ; *  You should have received a copy of the GNU General Public License
21    ; *  along with this program ; if not, write to the Free Software
22    ; *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
23    ; *
24    ; * $Id$
25    ; *
26    ; *************************************************************************/
27    
28    ; data/text alignment
29    %define ALIGN 8
30    
31    %define SATURATE
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    %macro cextern 1
45            %ifdef PREFIX
46                    extern _%1
47                    %define %1 _%1
48            %else
49                    extern %1
50            %endif
51    %endmacro
52    
53    ;***************************************************************************
54    ; Local data
55    ;***************************************************************************
56    
57    %ifdef FORMAT_COFF
58    SECTION .data data
59    %else
60    SECTION .data data align=8
61    %endif
62    
63    mmx_one:
64            times 4 dw       1
65    
66    ;===========================================================================
67    ;
68    ; divide by 2Q table
69    ;
70    ;===========================================================================
71    
72    align 16
73    mmx_div:
74    %assign quant 1
75    %rep 31
76            times 4 dw  (1<<17) / (quant*2) + 1
77            %assign quant quant+1
78    %endrep
79    
80    ;===========================================================================
81    ;
82    ; intra matrix
83    ;
84    ;===========================================================================
85    
86    cextern intra_matrix
87    cextern intra_matrix_fix
88    
89    ;===========================================================================
90    ;
91    ; inter matrix
92    ;
93    ;===========================================================================
94    
95    cextern inter_matrix
96    cextern inter_matrix_fix
97    
98    
99    %define VM18P 3
100    %define VM18Q 4
101    
102    
103    ;===========================================================================
104    ;
105    ; quantd table
106    ;
107    ;===========================================================================
108    
109    quantd:
110    %assign quant 1
111    %rep 31
112            times 4 dw  ((VM18P*quant) + (VM18Q/2)) / VM18Q
113            %assign quant quant+1
114    %endrep
115    
116    ;===========================================================================
117    ;
118    ; multiple by 2Q table
119    ;
120    ;===========================================================================
121    
122    mmx_mul_quant:
123    %assign quant 1
124    %rep 31
125            times 4 dw  quant
126            %assign quant quant+1
127    %endrep
128    
129    ;===========================================================================
130    ;
131    ; saturation limits
132    ;
133    ;===========================================================================
134    
135    align 16
136    
137    mmx_32767_minus_2047:
138            times 4 dw (32767-2047)
139    mmx_32768_minus_2048:
140            times 4 dw (32768-2048)
141    mmx_2047:
142            times 4 dw 2047
143    mmx_minus_2048:
144            times 4 dw (-2048)
145    zero:
146            times 4 dw 0
147    
148    ;***************************************************************************
149    ; Local data
150    ;***************************************************************************
151    
152    section .text
153    
154    ;===========================================================================
155    ;
156    ; uint32_t quant_mpeg_intra_mmx(int16_t * coeff,
157    ;                               const int16_t const * data,
158    ;                               const uint32_t quant,
159    ;                               const uint32_t dcscalar);
160    ;
161    ;===========================================================================
162    
163    align ALIGN
164    cglobal quant_mpeg_intra_mmx
165    quant_mpeg_intra_mmx:
166    
167            push    ecx
168            push    esi
169            push    edi
170    
171            mov             edi, [esp + 12 + 4]             ; coeff
172            mov             esi, [esp + 12 + 8]             ; data
173            mov             eax, [esp + 12 + 12]    ; quant
174    
175            movq    mm5, [quantd + eax * 8 - 8] ; quantd -> mm5
176    
177            xor             ecx, ecx
178            cmp             al, 1
179            jz              near .q1loop
180    
181            cmp             al, 2
182            jz              near .q2loop
183    
184            movq    mm7, [mmx_div + eax * 8 - 8] ; multipliers[quant] -> mm7
185    
186    align ALIGN
187    .loop
188            movq    mm0, [esi + 8*ecx]              ; mm0 = [1st]
189            movq    mm3, [esi + 8*ecx + 8]  ;
190    
191            pxor    mm1, mm1                ; mm1 = 0
192            pxor    mm4, mm4
193    
194            pcmpgtw mm1, mm0                ; mm1 = (0 > mm0)
195            pcmpgtw mm4, mm3
196    
197            pxor    mm0, mm1                ; mm0 = |mm0|
198            pxor    mm3, mm4                ;
199            psubw   mm0, mm1                ; displace
200            psubw   mm3, mm4                ;
201    
202            psllw   mm0, 4                  ; level << 4
203            psllw   mm3, 4                  ;
204    
205            movq    mm2, [intra_matrix + 8*ecx]
206            psrlw   mm2, 1                  ; intra_matrix[i]>>1
207            paddw   mm0, mm2
208    
209            movq    mm2, [intra_matrix_fix + ecx*8]
210            pmulhw  mm0, mm2                ; (level<<4 + intra_matrix[i]>>1) / intra_matrix[i]
211    
212            movq    mm2, [intra_matrix + 8*ecx + 8]
213            psrlw   mm2, 1
214            paddw   mm3, mm2
215    
216            movq    mm2, [intra_matrix_fix + ecx*8 + 8]
217            pmulhw  mm3, mm2
218    
219            paddw   mm0, mm5                ; + quantd
220            paddw   mm3, mm5
221            pmulhw  mm0, mm7                ; mm0 = (mm0 / 2Q) >> 16
222            pmulhw  mm3, mm7                ;
223            psrlw   mm0, 1                  ; additional shift by 1 => 16 + 1 = 17
224            psrlw   mm3, 1
225    
226            pxor    mm0, mm1                ; mm0 *= sign(mm0)
227            pxor    mm3, mm4                ;
228            psubw   mm0, mm1                ; undisplace
229            psubw   mm3, mm4                ;
230    
231            movq    [edi + 8*ecx], mm0
232            movq    [edi + 8*ecx + 8], mm3
233    
234            add             ecx,2
235            cmp             ecx,16
236            jnz     near .loop
237    
238    .done
239                    ; caclulate  data[0] // (int32_t)dcscalar)
240    
241            mov     ecx, [esp + 12 + 16]    ; dcscalar
242            mov     edx, ecx
243            movsx   eax, word [esi] ; data[0]
244            shr     edx, 1                  ; edx = dcscalar /2
245            cmp             eax, 0
246            jg              .gtzero
247    
248            sub             eax, edx
249            jmp             short .mul
250    .gtzero
251            add             eax, edx
252    .mul
253            cdq                             ; expand eax -> edx:eax
254            idiv    ecx                     ; eax = edx:eax / dcscalar
255    
256            mov     [edi], ax               ; coeff[0] = ax
257    
258            pop     edi
259            pop     esi
260            pop     ecx
261    
262            xor eax, eax                            ; return(0);
263            ret
264    
265    align ALIGN
266    .q1loop
267            movq    mm0, [esi + 8*ecx]              ; mm0 = [1st]
268            movq    mm3, [esi + 8*ecx + 8]  ;
269    
270            pxor    mm1, mm1                ; mm1 = 0
271            pxor    mm4, mm4                ;
272    
273            pcmpgtw mm1, mm0                ; mm1 = (0 > mm0)
274            pcmpgtw mm4, mm3                ;
275    
276            pxor    mm0, mm1                ; mm0 = |mm0|
277            pxor    mm3, mm4                ;
278            psubw   mm0, mm1                ; displace
279            psubw   mm3, mm4                ;
280    
281            psllw   mm0, 4
282            psllw   mm3, 4
283    
284            movq    mm2, [intra_matrix + 8*ecx]
285            psrlw   mm2, 1
286            paddw   mm0, mm2
287    
288            movq    mm2, [intra_matrix_fix + ecx*8]
289            pmulhw  mm0, mm2                ; (level<<4 + intra_matrix[i]>>1) / intra_matrix[i]
290    
291            movq    mm2, [intra_matrix + 8*ecx + 8]
292            psrlw   mm2, 1
293            paddw   mm3, mm2
294    
295            movq    mm2, [intra_matrix_fix + ecx*8 + 8]
296            pmulhw  mm3, mm2
297    
298            paddw   mm0, mm5
299            paddw   mm3, mm5
300    
301            psrlw   mm0, 1                  ; mm0 >>= 1   (/2)
302            psrlw   mm3, 1                  ;
303    
304            pxor    mm0, mm1                ; mm0 *= sign(mm0)
305            pxor    mm3, mm4        ;
306            psubw   mm0, mm1                ; undisplace
307            psubw   mm3, mm4                ;
308    
309            movq    [edi + 8*ecx], mm0
310            movq    [edi + 8*ecx + 8], mm3
311    
312            add             ecx, 2
313            cmp             ecx, 16
314            jnz             near .q1loop
315            jmp             near .done
316    
317    
318    align ALIGN
319    .q2loop
320            movq    mm0, [esi + 8*ecx]              ; mm0 = [1st]
321            movq    mm3, [esi + 8*ecx + 8]  ;
322    
323            pxor    mm1, mm1                ; mm1 = 0
324            pxor    mm4, mm4                ;
325    
326            pcmpgtw mm1, mm0                ; mm1 = (0 > mm0)
327            pcmpgtw mm4, mm3                ;
328    
329            pxor    mm0, mm1                ; mm0 = |mm0|
330            pxor    mm3, mm4                ;
331            psubw   mm0, mm1                ; displace
332            psubw   mm3, mm4                ;
333    
334            psllw   mm0, 4
335            psllw   mm3, 4
336    
337            movq    mm2, [intra_matrix + 8*ecx]
338            psrlw   mm2, 1
339            paddw   mm0, mm2
340    
341            movq    mm2, [intra_matrix_fix + ecx*8]
342            pmulhw  mm0, mm2                ; (level<<4 + intra_matrix[i]>>1) / intra_matrix[i]
343    
344            movq    mm2, [intra_matrix + 8*ecx + 8]
345            psrlw   mm2, 1
346            paddw   mm3, mm2
347    
348            movq    mm2, [intra_matrix_fix + ecx*8 + 8]
349            pmulhw  mm3, mm2
350    
351            paddw   mm0, mm5
352            paddw   mm3, mm5
353    
354            psrlw   mm0, 2                  ; mm0 >>= 1   (/4)
355            psrlw   mm3, 2                  ;
356    
357            pxor    mm0, mm1                ; mm0 *= sign(mm0)
358            pxor    mm3, mm4        ;
359            psubw   mm0, mm1                ; undisplace
360            psubw   mm3, mm4                ;
361    
362            movq    [edi + 8*ecx], mm0
363            movq    [edi + 8*ecx + 8], mm3
364    
365            add             ecx,2
366            cmp             ecx,16
367            jnz             near .q2loop
368            jmp             near .done
369    
370    
371    ;===========================================================================
372    ;
373    ; uint32_t quant_mpeg_inter_mmx(int16_t * coeff,
374    ;                               const int16_t const * data,
375    ;                               const uint32_t quant);
376    ;
377    ;===========================================================================
378    
379    align ALIGN
380    cglobal quant_mpeg_inter_mmx
381    quant_mpeg_inter_mmx:
382    
383            push    ecx
384            push    esi
385            push    edi
386    
387            mov             edi, [esp + 12 + 4]             ; coeff
388            mov             esi, [esp + 12 + 8]             ; data
389            mov             eax, [esp + 12 + 12]    ; quant
390    
391            xor             ecx, ecx
392    
393            pxor    mm5, mm5                                        ; sum
394    
395            cmp             al, 1
396            jz              near .q1loop
397    
398            cmp             al, 2
399            jz              near .q2loop
400    
401            movq    mm7, [mmx_div + eax * 8 - 8]    ; divider
402    
403    align ALIGN
404    .loop
405            movq    mm0, [esi + 8*ecx]              ; mm0 = [1st]
406            movq    mm3, [esi + 8*ecx + 8]  ;
407            pxor    mm1, mm1                ; mm1 = 0
408            pxor    mm4, mm4                ;
409            pcmpgtw mm1, mm0                ; mm1 = (0 > mm0)
410            pcmpgtw mm4, mm3                ;
411            pxor    mm0, mm1                ; mm0 = |mm0|
412            pxor    mm3, mm4                ;
413            psubw   mm0, mm1                ; displace
414            psubw   mm3, mm4                ;
415    
416            psllw   mm0, 4
417            psllw   mm3, 4
418    
419            movq    mm2, [inter_matrix + 8*ecx]
420            psrlw   mm2, 1
421            paddw   mm0, mm2
422    
423            movq    mm2, [inter_matrix_fix + ecx*8]
424            pmulhw  mm0, mm2                ; (level<<4 + inter_matrix[i]>>1) / inter_matrix[i]
425    
426            movq    mm2, [inter_matrix + 8*ecx + 8]
427            psrlw   mm2, 1
428            paddw   mm3, mm2
429    
430            movq    mm2, [inter_matrix_fix + ecx*8 + 8]
431            pmulhw  mm3, mm2
432    
433            pmulhw  mm0, mm7                ; mm0 = (mm0 / 2Q) >> 16
434            pmulhw  mm3, mm7                ;
435            psrlw   mm0, 1                  ; additional shift by 1 => 16 + 1 = 17
436            psrlw   mm3, 1
437    
438            paddw   mm5, mm0                ; sum += mm0
439            pxor    mm0, mm1                ; mm0 *= sign(mm0)
440            paddw   mm5, mm3                ;
441            pxor    mm3, mm4                ;
442            psubw   mm0, mm1                ; undisplace
443            psubw   mm3, mm4
444            movq    [edi + 8*ecx], mm0
445            movq    [edi + 8*ecx + 8], mm3
446    
447            add             ecx, 2
448            cmp             ecx, 16
449            jnz             near .loop
450    
451    .done
452            pmaddwd mm5, [mmx_one]
453            movq    mm0, mm5
454            psrlq   mm5, 32
455            paddd   mm0, mm5
456            movd    eax, mm0                ; return sum
457    
458            pop             edi
459            pop             esi
460            pop             ecx
461    
462            ret
463    
464    align ALIGN
465    .q1loop
466            movq    mm0, [esi + 8*ecx]              ; mm0 = [1st]
467            movq    mm3, [esi + 8*ecx+ 8]
468                                    ;
469            pxor    mm1, mm1                ; mm1 = 0
470            pxor    mm4, mm4                ;
471    
472            pcmpgtw mm1, mm0                ; mm1 = (0 > mm0)
473            pcmpgtw mm4, mm3                ;
474    
475            pxor    mm0, mm1                ; mm0 = |mm0|
476            pxor    mm3, mm4                ;
477            psubw   mm0, mm1                ; displace
478            psubw   mm3, mm4                ;
479    
480            psllw   mm0, 4
481            psllw   mm3, 4
482    
483            movq    mm2, [inter_matrix + 8*ecx]
484            psrlw   mm2, 1
485            paddw   mm0, mm2
486    
487            movq    mm2, [inter_matrix_fix + ecx*8]
488            pmulhw  mm0, mm2                ; (level<<4 + inter_matrix[i]>>1) / inter_matrix[i]
489    
490            movq    mm2, [inter_matrix + 8*ecx + 8]
491            psrlw   mm2, 1
492            paddw   mm3, mm2
493    
494            movq    mm2, [inter_matrix_fix + ecx*8 + 8]
495            pmulhw  mm3, mm2
496    
497            psrlw   mm0, 1                  ; mm0 >>= 1   (/2)
498            psrlw   mm3, 1                  ;
499    
500            paddw   mm5, mm0                ; sum += mm0
501            pxor    mm0, mm1                ; mm0 *= sign(mm0)
502            paddw   mm5, mm3                ;
503            pxor    mm3, mm4                ;
504            psubw   mm0, mm1                ; undisplace
505            psubw   mm3, mm4
506    
507            movq    [edi + 8*ecx], mm0
508            movq    [edi + 8*ecx + 8], mm3
509    
510            add             ecx, 2
511            cmp             ecx, 16
512            jnz             near .q1loop
513    
514            jmp             .done
515    
516    
517    align ALIGN
518    .q2loop
519            movq    mm0, [esi + 8*ecx]              ; mm0 = [1st]
520            movq    mm3, [esi + 8*ecx+ 8]
521                                    ;
522            pxor    mm1, mm1                ; mm1 = 0
523            pxor    mm4, mm4                ;
524    
525            pcmpgtw mm1, mm0                ; mm1 = (0 > mm0)
526            pcmpgtw mm4, mm3                ;
527    
528            pxor    mm0, mm1                ; mm0 = |mm0|
529            pxor    mm3, mm4                ;
530            psubw   mm0, mm1                ; displace
531            psubw   mm3, mm4                ;
532    
533            psllw   mm0, 4
534            psllw   mm3, 4
535    
536            movq    mm2, [inter_matrix + 8*ecx]
537            psrlw   mm2, 1
538            paddw   mm0, mm2
539    
540            movq    mm2, [inter_matrix_fix + ecx*8]
541            pmulhw  mm0, mm2                ; (level<<4 + inter_matrix[i]>>1) / inter_matrix[i]
542    
543            movq    mm2, [inter_matrix + 8*ecx + 8]
544            psrlw   mm2, 1
545            paddw   mm3, mm2
546    
547            movq    mm2, [inter_matrix_fix + ecx*8 + 8]
548            pmulhw  mm3, mm2
549    
550            psrlw   mm0, 2                  ; mm0 >>= 1   (/2)
551            psrlw   mm3, 2                  ;
552    
553            paddw   mm5, mm0                ; sum += mm0
554            pxor    mm0, mm1                ; mm0 *= sign(mm0)
555            paddw   mm5, mm3                ;
556            pxor    mm3, mm4                ;
557            psubw   mm0, mm1                ; undisplace
558            psubw   mm3, mm4
559    
560            movq    [edi + 8*ecx], mm0
561            movq    [edi + 8*ecx + 8], mm3
562    
563            add             ecx, 2
564            cmp             ecx, 16
565            jnz             near .q2loop
566    
567            jmp     .done
568    
569    
570    ;===========================================================================
571    ;
572    ; uint32_t dequant_mpeg_intra_mmx(int16_t *data,
573    ;                                 const int16_t const *coeff,
574    ;                                 const uint32_t quant,
575    ;                                 const uint32_t dcscalar);
576    ;
577    ;===========================================================================
578    
579      ;   Note: in order to saturate 'easily', we pre-shift the quantifier
580      ; by 4. Then, the high-word of (coeff[]*matrix[i]*quant) are used to
581      ; build a saturating mask. It is non-zero only when an overflow occured.
582      ; We thus avoid packing/unpacking toward double-word.
583      ; Moreover, we perform the mult (matrix[i]*quant) first, instead of, e.g.,
584      ; (coeff[i]*matrix[i]). This is less prone to overflow if coeff[] are not
585      ; checked. Input ranges are: coeff in [-127,127], inter_matrix in [1..255],a
586      ; and quant in [1..31].
587      ;
588      ; The original loop is:
589      ;
590    %if 0
591            movq    mm0, [ecx+8*eax + 8*16]   ; mm0 = coeff[i]
592            pxor    mm1, mm1
593            pcmpgtw mm1, mm0
594            pxor    mm0, mm1     ; change sign if negative
595            psubw   mm0, mm1    ; -> mm0 = abs(coeff[i]), mm1 = sign of coeff[i]
596    
597            movq    mm2, mm7     ; mm2 = quant
598            pmullw  mm2, [intra_matrix + 8*eax + 8*16 ]  ; matrix[i]*quant.
599    
600            movq    mm6, mm2
601            pmulhw  mm2, mm0   ; high of coeff*(matrix*quant)  (should be 0 if no overflow)
602            pmullw  mm0, mm6   ; low  of coeff*(matrix*quant)
603    
604            pxor    mm5, mm5
605            pcmpgtw mm2, mm5  ; otherflow?
606            psrlw   mm2, 5      ; =0 if no clamp, 2047 otherwise
607            psrlw   mm0, 5
608            paddw   mm0, mm1    ; start restoring sign
609            por             mm0, mm2      ; saturate to 2047 if needed
610            pxor    mm0, mm1     ; finish negating back
611    
612            movq    [edx + 8*eax + 8*16], mm0   ; data[i]
613            add             eax, 1
614    %endif
615    
616      ;********************************************************************
617    
618    align 16
619    cglobal dequant_mpeg_intra_mmx
620    dequant_mpeg_intra_mmx:
621    
622            mov             edx, [esp+4]  ; data
623            mov             ecx, [esp+8]  ; coeff
624            mov             eax, [esp+12] ; quant
625    
626            movq    mm7, [mmx_mul_quant  + eax*8 - 8]
627            mov             eax, -16   ; to keep aligned, we regularly process coeff[0]
628            psllw   mm7, 2   ; << 2. See comment.
629            pxor    mm6, mm6   ; this is a NOP
630    
631    align 16
632    .loop
633            movq    mm0, [ecx+8*eax + 8*16]   ; mm0 = c  = coeff[i]
634            movq    mm3, [ecx+8*eax + 8*16 +8]; mm3 = c' = coeff[i+1]
635            pxor    mm1, mm1
636            pxor    mm4, mm4
637            pcmpgtw mm1, mm0  ; mm1 = sgn(c)
638            movq    mm2, mm7     ; mm2 = quant
639    
640            pcmpgtw mm4, mm3  ; mm4 = sgn(c')
641            pmullw  mm2,  [intra_matrix + 8*eax + 8*16 ]  ; matrix[i]*quant
642    
643            pxor    mm0, mm1     ; negate if negative
644            pxor    mm3, mm4     ; negate if negative
645    
646            psubw   mm0, mm1
647            psubw   mm3, mm4
648    
649        ; we're short on register, here. Poor pairing...
650    
651            movq    mm5, mm2
652            pmullw  mm2, mm0   ; low  of coeff*(matrix*quant)
653    
654            pmulhw  mm0, mm5   ; high of coeff*(matrix*quant)
655            movq    mm5, mm7     ; mm2 = quant
656    
657            pmullw  mm5,  [intra_matrix + 8*eax + 8*16 +8]  ; matrix[i+1]*quant
658    
659            movq    mm6, mm5
660            add             eax,2   ; z-flag will be tested later
661    
662            pmullw  mm6, mm3   ; low  of coeff*(matrix*quant)
663            pmulhw  mm3, mm5   ; high of coeff*(matrix*quant)
664    
665            pcmpgtw mm0, [zero]
666            paddusw mm2, mm0
667            psrlw   mm2, 5
668    
669            pcmpgtw mm3, [zero]
670            paddusw mm6, mm3
671            psrlw   mm6, 5
672    
673            pxor    mm2, mm1  ; start negating back
674            pxor    mm6, mm4  ; start negating back
675    
676            psubusw mm1, mm0
677            psubusw mm4, mm3
678    
679            psubw   mm2, mm1 ; finish negating back
680            psubw   mm6, mm4 ; finish negating back
681    
682            movq    [edx + 8*eax + 8*16   -2*8   ], mm2   ; data[i]
683            movq    [edx + 8*eax + 8*16   -2*8 +8], mm6   ; data[i+1]
684    
685            jnz             near .loop
686    
687        ; deal with DC
688    
689            movd    mm0, [ecx]
690            pmullw  mm0, [esp+16]  ; dcscalar
691            movq    mm2, [mmx_32767_minus_2047]
692            paddsw  mm0, mm2
693            psubsw  mm0, mm2
694            movq    mm2, [mmx_32768_minus_2048]
695            psubsw  mm0, mm2
696            paddsw  mm0, mm2
697            movd    eax, mm0
698            mov             [edx], ax
699    
700            xor             eax, eax
701            ret
702    
703    ;===========================================================================
704    ;
705    ; uint32_t dequant_mpeg_inter_mmx(int16_t * data,
706    ;                                 const int16_t * const coeff,
707    ;                                 const uint32_t quant);
708    ;
709    ;===========================================================================
710    
711        ; Note:  We use (2*c + sgn(c) - sgn(-c)) as multiplier
712        ; so we handle the 3 cases: c<0, c==0, and c>0 in one shot.
713        ; sgn(x) is the result of 'pcmpgtw 0,x':  0 if x>=0, -1 if x<0.
714        ; It's mixed with the extraction of the absolute value.
715    
716    align 16
717    cglobal dequant_mpeg_inter_mmx
718    dequant_mpeg_inter_mmx:
719    
720            mov             edx, [esp+ 4]        ; data
721            mov             ecx, [esp+ 8]        ; coeff
722            mov             eax, [esp+12]        ; quant
723            movq    mm7, [mmx_mul_quant  + eax*8 - 8]
724            mov             eax, -16
725            paddw   mm7, mm7    ; << 1
726            pxor    mm6, mm6 ; mismatch sum
727    
728    align 16
729    .loop
730            movq    mm0, [ecx+8*eax + 8*16   ]   ; mm0 = coeff[i]
731            movq    mm2, [ecx+8*eax + 8*16 +8]   ; mm2 = coeff[i+1]
732            add             eax, 2
733    
734            pxor    mm1, mm1
735            pxor    mm3, mm3
736            pcmpgtw mm1, mm0  ; mm1 = sgn(c)    (preserved)
737            pcmpgtw mm3, mm2  ; mm3 = sgn(c')   (preserved)
738            paddsw  mm0, mm1   ; c += sgn(c)
739            paddsw  mm2, mm3   ; c += sgn(c')
740            paddw   mm0, mm0    ; c *= 2
741            paddw   mm2, mm2    ; c'*= 2
742    
743            pxor    mm4, mm4
744            pxor    mm5, mm5
745            psubw   mm4, mm0    ; -c
746            psubw   mm5, mm2    ; -c'
747            psraw   mm4, 16     ; mm4 = sgn(-c)
748            psraw   mm5, 16     ; mm5 = sgn(-c')
749            psubsw  mm0, mm4   ; c  -= sgn(-c)
750            psubsw  mm2, mm5   ; c' -= sgn(-c')
751            pxor    mm0, mm1     ; finish changing sign if needed
752            pxor    mm2, mm3     ; finish changing sign if needed
753    
754        ; we're short on register, here. Poor pairing...
755    
756            movq    mm4, mm7     ; (matrix*quant)
757            pmullw  mm4,  [inter_matrix + 8*eax + 8*16 -2*8]
758            movq    mm5, mm4
759            pmulhw  mm5, mm0   ; high of c*(matrix*quant)
760            pmullw  mm0, mm4   ; low  of c*(matrix*quant)
761    
762            movq    mm4, mm7     ; (matrix*quant)
763            pmullw  mm4,  [inter_matrix + 8*eax + 8*16 -2*8 + 8]
764    
765            pcmpgtw mm5, [zero]
766            paddusw mm0, mm5
767            psrlw   mm0, 5
768            pxor    mm0, mm1     ; start restoring sign
769            psubusw mm1, mm5
770    
771            movq    mm5, mm4
772            pmulhw  mm5, mm2   ; high of c*(matrix*quant)
773            pmullw  mm2, mm4   ; low  of c*(matrix*quant)
774            psubw   mm0, mm1    ; finish restoring sign
775    
776            pcmpgtw mm5, [zero]
777            paddusw mm2, mm5
778            psrlw   mm2, 5
779            pxor    mm2, mm3    ; start restoring sign
780            psubusw mm3, mm5
781            psubw   mm2, mm3   ; finish restoring sign
782    
783            pxor    mm6, mm0     ; mismatch control
784            movq    [edx + 8*eax + 8*16 -2*8   ], mm0   ; data[i]
785            pxor    mm6, mm2     ; mismatch control
786            movq    [edx + 8*eax + 8*16 -2*8 +8], mm2   ; data[i+1]
787    
788            jnz             near .loop
789    
790      ; mismatch control
791    
792            movq    mm0, mm6
793            psrlq   mm0, 48
794            movq    mm1, mm6
795            movq    mm2, mm6
796            psrlq   mm1, 32
797            pxor    mm6, mm0
798            psrlq   mm2, 16
799            pxor    mm6, mm1
800            pxor    mm6, mm2
801            movd    eax, mm6
802            and             eax, 1
803            xor             eax, 1
804            xor             word [edx + 2*63], ax
805    
806            xor             eax, eax
807            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