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

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