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

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

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