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

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

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

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