[svn] / branches / dev-api-4 / xvidcore / src / quant / x86_asm / quantize_mmx.asm Repository:
ViewVC logotype

Diff of /branches/dev-api-4/xvidcore/src/quant/x86_asm/quantize_mmx.asm

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

revision 3, Fri Mar 8 02:46:11 2002 UTC revision 463, Tue Sep 10 21:16:45 2002 UTC
# Line 1  Line 1 
1  ;/**************************************************************************  ;/*****************************************************************************
2  ; *  ; *
3  ; *     XVID MPEG-4 VIDEO CODEC  ; *     XVID MPEG-4 VIDEO CODEC
4  ; *     mmx quantization/dequantization  ; *  mmx optimized quantization/dequantization
5    ; *
6    ; *  Copyright(C) 2002 Peter Ross <pross@xvid.org>
7    ; *  Copyright(C) 2002 Michael Militzer <michael@xvid.org>
8    ; *  Copyright(C) 2002 Pascal Massimino <skal@planet-d.net>
9  ; *  ; *
10  ; *     This program is an implementation of a part of one or more MPEG-4  ; *     This program is an implementation of a part of one or more MPEG-4
11  ; *     Video tools as specified in ISO/IEC 14496-2 standard.  Those intending  ; *     Video tools as specified in ISO/IEC 14496-2 standard.  Those intending
# Line 24  Line 28 
28  ; *  ; *
29  ; *     You should have received a copy of the GNU General Public License  ; *     You should have received a copy of the GNU General Public License
30  ; *     along with this program; if not, write to the Free Software  ; *     along with this program; if not, write to the Free Software
31  ; *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  ; *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 ; *  
 ; *************************************************************************/  
   
 ;/**************************************************************************  
 ; *  
 ; *     History:  
 ; *  
 ; * 26.12.2001  minor bug fixes, dequant saturate, further optimization  
 ; * 19.11.2001  quant_inter_mmx now returns sum of abs. coefficient values  
 ; *     04.11.2001      nasm version; (c)2001 peter ross <pross@cs.rmit.edu.au>  
32  ; *  ; *
33  ; *************************************************************************/  ; *************************************************************************/
34    
# Line 58  Line 52 
52          %endif          %endif
53  %endmacro  %endmacro
54    
55  plus_one times 4        dw       1  align 16
56    
57    plus_one times 8        dw       1
58    
59  ;===========================================================================  ;===========================================================================
60  ;  ;
# Line 70  Line 66 
66  times 4 dw %1 / 2  times 4 dw %1 / 2
67  %endmacro  %endmacro
68    
69  align ALIGN  align 16
70  mmx_sub  mmx_sub
71                  MMX_SUB 1                  MMX_SUB 1
72                  MMX_SUB 2                  MMX_SUB 2
# Line 120  Line 116 
116  times 4 dw  (1 << 16) / (%1 * 2) + 1  times 4 dw  (1 << 16) / (%1 * 2) + 1
117  %endmacro  %endmacro
118    
119  align ALIGN  align 16
120  mmx_div  mmx_div
121                  MMX_DIV 1                  MMX_DIV 1
122                  MMX_DIV 2                  MMX_DIV 2
# Line 170  Line 166 
166  %endif  %endif
167  %endmacro  %endmacro
168    
169  align ALIGN  align 16
170  mmx_add  mmx_add
171                  MMX_ADD 1                  MMX_ADD 1
172                  MMX_ADD 2                  MMX_ADD 2
# Line 215  Line 211 
211  times 4 dw %1 * 2  times 4 dw %1 * 2
212  %endmacro  %endmacro
213    
214  align ALIGN  align 16
215  mmx_mul  mmx_mul
216                  MMX_MUL 1                  MMX_MUL 1
217                  MMX_MUL 2                  MMX_MUL 2
# Line 256  Line 252 
252  ;  ;
253  ;===========================================================================  ;===========================================================================
254    
255  align ALIGN  align 16
256    sse2_2047       times 8 dw 2047
257    
258    align 16
259    mmx_2047        times 4 dw 2047
260    
261    align 8
262  mmx_32768_minus_2048                            times 4 dw (32768-2048)  mmx_32768_minus_2048                            times 4 dw (32768-2048)
263  mmx_32767_minus_2047                            times 4 dw (32767-2047)  mmx_32767_minus_2047                            times 4 dw (32767-2047)
264    
# Line 371  Line 373 
373    
374  ;===========================================================================  ;===========================================================================
375  ;  ;
376    ; void quant_intra_sse2(int16_t * coeff,
377    ;                                       const int16_t const * data,
378    ;                                       const uint32_t quant,
379    ;                                       const uint32_t dcscalar);
380    ;
381    ;===========================================================================
382    
383    align ALIGN
384    cglobal quant_intra_sse2
385    quant_intra_sse2
386    
387                    push    esi
388                    push    edi
389    
390                    mov             edi, [esp + 8 + 4]                      ; coeff
391                    mov             esi, [esp + 8 + 8]                      ; data
392                    mov             eax, [esp + 8 + 12]                     ; quant
393    
394                    xor             ecx, ecx
395                    cmp             al, 1
396                    jz              near .qas2_q1loop
397    
398    .qas2_not1
399                    movq    mm7, [mmx_div + eax*8 - 8]
400                    movq2dq xmm7, mm7
401                    movlhps xmm7, xmm7
402    
403    align 16
404    .qas2_loop
405                    movdqa  xmm0, [esi + ecx*8]                     ; xmm0 = [1st]
406                    movdqa  xmm3, [esi + ecx*8 + 16]        ; xmm3 = [2nd]
407                    pxor    xmm1, xmm1
408                    pxor    xmm4, xmm4
409                    pcmpgtw xmm1, xmm0
410                    pcmpgtw xmm4, xmm3
411                    pxor    xmm0, xmm1
412                    pxor    xmm3, xmm4
413                    psubw   xmm0, xmm1
414                    psubw   xmm3, xmm4
415                    pmulhw  xmm0, xmm7
416                    pmulhw  xmm3, xmm7
417                    pxor    xmm0, xmm1
418                    pxor    xmm3, xmm4
419                    psubw   xmm0, xmm1
420                    psubw   xmm3, xmm4
421                    movdqa  [edi + ecx*8], xmm0
422                    movdqa  [edi + ecx*8 + 16], xmm3
423    
424                    add             ecx, 4
425                    cmp             ecx, 16
426                    jnz     .qas2_loop
427    
428    .qas2_done
429                    mov     ecx, [esp + 8 + 16]     ; dcscalar
430                    mov     edx, ecx
431                    movsx   eax, word [esi]
432                    shr     edx, 1
433                    cmp             eax, 0
434                    jg              .qas2_gtzero
435    
436                    sub             eax, edx
437                    jmp             short .qas2_mul
438    .qas2_gtzero
439                    add             eax, edx
440    .qas2_mul
441                    cdq
442                    idiv    ecx
443    
444                    mov             [edi], ax
445    
446                    pop             edi
447                    pop             esi
448    
449                    ret
450    
451    align 16
452    .qas2_q1loop
453                    movdqa  xmm0, [esi + ecx*8]                     ; xmm0 = [1st]
454                    movdqa  xmm3, [esi + ecx*8 + 16]        ; xmm3 = [2nd]
455                    pxor    xmm1, xmm1
456                    pxor    xmm4, xmm4
457                    pcmpgtw xmm1, xmm0
458                    pcmpgtw xmm4, xmm3
459                    pxor    xmm0, xmm1
460                    pxor    xmm3, xmm4
461                    psubw   xmm0, xmm1
462                    psubw   xmm3, xmm4
463                    psrlw   xmm0, 1
464                    psrlw   xmm3, 1
465                    pxor    xmm0, xmm1
466                    pxor    xmm3, xmm4
467                    psubw   xmm0, xmm1
468                    psubw   xmm3, xmm4
469                    movdqa  [edi + ecx*8], xmm0
470                    movdqa  [edi + ecx*8 + 16], xmm3
471    
472                    add             ecx, 4
473                    cmp             ecx, 16
474                    jnz             .qas2_q1loop
475                    jmp             near .qas2_done
476    
477    
478    
479    ;===========================================================================
480    ;
481  ; uint32_t quant_inter_mmx(int16_t * coeff,  ; uint32_t quant_inter_mmx(int16_t * coeff,
482  ;                                       const int16_t const * data,  ;                                       const int16_t const * data,
483  ;                                       const uint32_t quant);  ;                                       const uint32_t quant);
# Line 476  Line 583 
583    
584  ;===========================================================================  ;===========================================================================
585  ;  ;
586    ; uint32_t quant_inter_sse2(int16_t * coeff,
587    ;                                       const int16_t const * data,
588    ;                                       const uint32_t quant);
589    ;
590    ;===========================================================================
591    
592    align 16
593    cglobal quant_inter_sse2
594                    quant_inter_sse2
595    
596                    push    esi
597                    push    edi
598    
599                    mov             edi, [esp + 8 + 4]                      ; coeff
600                    mov             esi, [esp + 8 + 8]                      ; data
601                    mov             eax, [esp + 8 + 12]                     ; quant
602    
603                    xor             ecx, ecx
604    
605                    pxor    xmm5, xmm5                                      ; sum
606    
607                    movq    mm0, [mmx_sub + eax*8 - 8]      ; sub
608                    movq2dq xmm6, mm0                                       ; load into low 8 bytes
609                    movlhps xmm6, xmm6                                      ; duplicate into high 8 bytes
610    
611                    cmp             al, 1
612                    jz              near .qes2_q1loop
613    
614    .qes2_not1
615                    movq    mm0, [mmx_div + eax*8 - 8]      ; divider
616                    movq2dq xmm7, mm0
617                    movlhps xmm7, xmm7
618    
619    align 16
620    .qes2_loop
621                    movdqa  xmm0, [esi + ecx*8]                     ; xmm0 = [1st]
622                    movdqa  xmm3, [esi + ecx*8 + 16]        ; xmm3 = [2nd]
623                    pxor    xmm1, xmm1
624                    pxor    xmm4, xmm4
625                    pcmpgtw xmm1, xmm0
626                    pcmpgtw xmm4, xmm3
627                    pxor    xmm0, xmm1
628                    pxor    xmm3, xmm4
629                    psubw   xmm0, xmm1
630                    psubw   xmm3, xmm4
631                    psubusw xmm0, xmm6
632                    psubusw xmm3, xmm6
633                    pmulhw  xmm0, xmm7
634                    pmulhw  xmm3, xmm7
635                    paddw   xmm5, xmm0
636                    pxor    xmm0, xmm1
637                    paddw   xmm5, xmm3
638                    pxor    xmm3, xmm4
639                    psubw   xmm0, xmm1
640                    psubw   xmm3, xmm4
641                    movdqa  [edi + ecx*8], xmm0
642                    movdqa  [edi + ecx*8 + 16], xmm3
643    
644                    add             ecx, 4
645                    cmp             ecx, 16
646                    jnz             .qes2_loop
647    
648    .qes2_done
649                    movdqu  xmm6, [plus_one]
650                    pmaddwd xmm5, xmm6
651                    movhlps xmm6, xmm5
652                    paddd   xmm5, xmm6
653                    movdq2q mm0, xmm5
654    
655                    movq    mm5, mm0
656                    psrlq   mm5, 32
657                    paddd   mm0, mm5
658                    movd    eax, mm0                                        ; return sum
659    
660                    pop             edi
661                    pop             esi
662    
663                    ret
664    
665    align 16
666    .qes2_q1loop
667                    movdqa  xmm0, [esi + ecx*8]                     ; xmm0 = [1st]
668                    movdqa  xmm3, [esi + ecx*8 + 16]        ; xmm3 = [2nd]
669                    pxor    xmm1, xmm1
670                    pxor    xmm4, xmm4
671                    pcmpgtw xmm1, xmm0
672                    pcmpgtw xmm4, xmm3
673                    pxor    xmm0, xmm1
674                    pxor    xmm3, xmm4
675                    psubw   xmm0, xmm1
676                    psubw   xmm3, xmm4
677                    psubusw xmm0, xmm6
678                    psubusw xmm3, xmm6
679                    psrlw   xmm0, 1
680                    psrlw   xmm3, 1
681                    paddw   xmm5, xmm0
682                    pxor    xmm0, xmm1
683                    paddw   xmm5, xmm3
684                    pxor    xmm3, xmm4
685                    psubw   xmm0, xmm1
686                    psubw   xmm3, xmm4
687                    movdqa  [edi + ecx*8], xmm0
688                    movdqa  [edi + ecx*8 + 16], xmm3
689    
690                    add             ecx,4
691                    cmp             ecx,16
692                    jnz             .qes2_q1loop
693                    jmp             .qes2_done
694    
695    
696    ;===========================================================================
697    ;
698  ; void dequant_intra_mmx(int16_t *data,  ; void dequant_intra_mmx(int16_t *data,
699  ;                                       const int16_t const *coeff,  ;                                       const int16_t const *coeff,
700  ;                                       const uint32_t quant,  ;                                       const uint32_t quant,
# Line 483  Line 702 
702  ;  ;
703  ;===========================================================================  ;===========================================================================
704    
705      ; note: we only saturate to +2047 *before* restoring the sign.
706      ; Hence, final clamp really is [-2048,2047]
707    
708  align ALIGN  align ALIGN
709  cglobal dequant_intra_mmx  cglobal dequant_intra_mmx
710  dequant_intra_mmx  dequant_intra_mmx:
   
                 push    esi  
                 push    edi  
711    
712                  mov     edi, [esp + 8 + 4]              ; data    mov    edx, [esp+ 4]        ; data
713                  mov     esi, [esp + 8 + 8]              ; coeff    mov    ecx, [esp+ 8]        ; coeff
714                  mov     eax, [esp + 8 + 12]             ; quant    mov    eax, [esp+12]        ; quant
715      movq mm6, [mmx_add + eax*8 - 8]  ; quant or quant-1
716                  movq    mm6, [mmx_add + eax * 8 - 8]    movq mm7, [mmx_mul + eax*8 - 8]  ; 2*quant
717                  movq    mm7, [mmx_mul + eax * 8 - 8]    mov eax, -16
                 xor eax, eax  
718    
719  align ALIGN  align ALIGN
720  .loop  .loop
721                  movq    mm0, [esi + 8*eax]              ; mm0 = [coeff]    movq mm0, [ecx+8*eax+8*16]      ; c  = coeff[i]
722                  movq    mm3, [esi + 8*eax + 8]  ;    movq mm3, [ecx+8*eax+8*16 + 8]  ; c' = coeff[i+1]
723                  pxor    mm1, mm1                ; mm1 = 0    pxor mm1, mm1
724                  pxor    mm4, mm4                ;    pxor mm4, mm4
725                  pcmpgtw mm1, mm0                ; mm1 = (0 > mm0)    pcmpgtw mm1, mm0  ; sign(c)
726                  pcmpgtw mm4, mm3                ;    pcmpgtw mm4, mm3  ; sign(c')
727                  pxor    mm2, mm2                ; mm2 = 0    pxor mm2, mm2
728                  pxor    mm5, mm5                ;    pxor mm5, mm5
729                  pcmpeqw mm2, mm0                ; mm2 = (0 == mm0)    pcmpeqw mm2, mm0  ; c is zero
730                  pcmpeqw mm5, mm3                ;    pcmpeqw mm5, mm3  ; c' is zero
731                  pandn   mm2, mm6                ; mm2 = (iszero ? 0 : add)    pandn mm2, mm6    ; offset = isZero ? 0 : quant_add
732                  pandn   mm5, mm6                ;    pandn mm5, mm6
733                  pxor    mm0, mm1                ; mm0 = |mm0|    pxor mm0, mm1     ; negate if negative
734                  pxor    mm3, mm4                ;    pxor mm3, mm4     ; negate if negative
735                  psubw   mm0, mm1                ; displace    psubw mm0, mm1
                 psubw   mm3, mm4                ;  
                 pmullw  mm0, mm7                ; mm0 *= 2Q  
                 pmullw  mm3, mm7                ;  
                 paddw   mm0, mm2                ; mm0 += mm2 (add)  
                 paddw   mm3, mm5                ;  
                 pxor    mm0, mm1                ; mm0 *= sign(mm0)  
                 pxor    mm3, mm4                ;  
                 psubw   mm0, mm1                ; undisplace  
736                  psubw   mm3, mm4                  psubw   mm3, mm4
737      pmullw mm0, mm7 ; *= 2Q
738      pmullw mm3, mm7 ; *= 2Q
739      paddw mm0, mm2 ; + offset
740      paddw mm3, mm5 ; + offset
741      paddw mm0, mm1 ; negate back
742      paddw mm3, mm4 ; negate back
743    
744  %ifdef SATURATE      ; saturates to +2047
745                  movq mm2, [mmx_32767_minus_2047]                  movq mm2, [mmx_32767_minus_2047]
746                  movq mm4, [mmx_32768_minus_2048]    add eax, 2
747                  paddsw  mm0, mm2                  paddsw  mm0, mm2
748                  paddsw  mm3, mm2                  paddsw  mm3, mm2
749                  psubsw  mm0, mm2                  psubsw  mm0, mm2
750                  psubsw  mm3, mm2                  psubsw  mm3, mm2
                 psubsw  mm0, mm4  
                 psubsw  mm3, mm4  
                 paddsw  mm0, mm4  
                 paddsw  mm3, mm4  
 %endif  
751    
752                  movq    [edi + 8*eax], mm0              ; [data] = mm0    pxor mm0, mm1
753                  movq    [edi + 8*eax + 8], mm3    pxor mm3, mm4
754      movq [edx + 8*eax + 8*16   - 2*8], mm0
755      movq [edx + 8*eax + 8*16+8 - 2*8], mm3
756      jnz   near .loop
757    
758        ; deal with DC
759    
760      movd mm0, [ecx]
761      pmullw mm0, [esp+16]    ; dcscalar
762      movq mm2, [mmx_32767_minus_2047]
763      paddsw mm0, mm2
764      psubsw mm0, mm2
765      movq mm3, [mmx_32768_minus_2048]
766      psubsw mm0, mm3
767      paddsw mm0, mm3
768      movd eax, mm0
769      mov [edx], ax
770    
771      ret
772    
773    ;===========================================================================
774    ;
775    ; void dequant_intra_xmm(int16_t *data,
776    ;                                       const int16_t const *coeff,
777    ;                                       const uint32_t quant,
778    ;                                       const uint32_t dcscalar);
779    ;
780    ;===========================================================================
781    
782      ; this is the same as dequant_inter_mmx, except that we're
783      ; saturating using 'pminsw' (saves 2 cycles/loop => ~5% faster)
784    
785    align ALIGN
786    cglobal dequant_intra_xmm
787    dequant_intra_xmm:
788    
789      mov    edx, [esp+ 4]        ; data
790      mov    ecx, [esp+ 8]        ; coeff
791      mov    eax, [esp+12]        ; quant
792      movq mm6, [mmx_add + eax*8 - 8]  ; quant or quant-1
793      movq mm7, [mmx_mul + eax*8 - 8]  ; 2*quant
794      mov eax, -16
795    
796    align ALIGN
797    .loop
798      movq mm0, [ecx+8*eax+8*16]      ; c  = coeff[i]
799      movq mm3, [ecx+8*eax+8*16 + 8]  ; c' = coeff[i+1]
800      pxor mm1, mm1
801      pxor mm4, mm4
802      pcmpgtw mm1, mm0  ; sign(c)
803      pcmpgtw mm4, mm3  ; sign(c')
804      pxor mm2, mm2
805      pxor mm5, mm5
806      pcmpeqw mm2, mm0  ; c is zero
807      pcmpeqw mm5, mm3  ; c' is zero
808      pandn mm2, mm6    ; offset = isZero ? 0 : quant_add
809      pandn mm5, mm6
810      pxor mm0, mm1     ; negate if negative
811      pxor mm3, mm4     ; negate if negative
812      psubw mm0, mm1
813      psubw mm3, mm4
814      pmullw mm0, mm7 ; *= 2Q
815      pmullw mm3, mm7 ; *= 2Q
816      paddw mm0, mm2 ; + offset
817      paddw mm3, mm5 ; + offset
818      paddw mm0, mm1 ; negate back
819      paddw mm3, mm4 ; negate back
820    
821        ; saturates to +2047
822      movq mm2, [mmx_2047]
823      pminsw mm0, mm2
824                  add eax, 2                  add eax, 2
825                  cmp eax, 16    pminsw mm3, mm2
826    
827      pxor mm0, mm1
828      pxor mm3, mm4
829      movq [edx + 8*eax + 8*16   - 2*8], mm0
830      movq [edx + 8*eax + 8*16+8 - 2*8], mm3
831                  jnz     near .loop                  jnz     near .loop
832    
833                  mov     ax, [esi]                                       ; ax = data[0]      ; deal with DC
                 imul ax, [esp + 8 + 16]                 ; eax = data[0] * dcscalar  
834    
835  %ifdef SATURATE    movd mm0, [ecx]
836                  cmp ax, -2048    pmullw mm0, [esp+16]    ; dcscalar
837                  jl .set_n2048    movq mm2, [mmx_32767_minus_2047]
838                  cmp ax, 2047    paddsw mm0, mm2
839                  jg .set_2047    psubsw mm0, mm2
840  %endif    movq mm2, [mmx_32768_minus_2048]
841                  mov     [edi], ax    psubsw mm0, mm2
842      paddsw mm0, mm2
843      movd eax, mm0
844      mov [edx], ax
845    
                 pop     edi  
                 pop     esi  
846                  ret                  ret
847    
848  %ifdef SATURATE  
849    ;===========================================================================
850    ;
851    ; void dequant_intra_sse2(int16_t *data,
852    ;                                       const int16_t const *coeff,
853    ;                                       const uint32_t quant,
854    ;                                       const uint32_t dcscalar);
855    ;
856    ;===========================================================================
857  align ALIGN  align ALIGN
858  .set_n2048  cglobal dequant_intra_sse2
859                  mov     word [edi], -2048  dequant_intra_sse2:
860                  pop     edi          mov edx, [esp+ 4]        ; data
861                  pop     esi          mov ecx, [esp+ 8]        ; coeff
862                  ret          mov eax, [esp+12]        ; quant
863            movq mm6, [mmx_add + eax * 8 - 8]
864            movq mm7, [mmx_mul + eax * 8 - 8]
865            movq2dq xmm6, mm6
866            movq2dq xmm7, mm7
867            movlhps xmm6, xmm6
868            movlhps xmm7, xmm7
869            mov eax, -16
870    
871  align ALIGN  align ALIGN
872  .set_2047  .loop
873                  mov     word [edi], 2047          movdqa xmm0, [ecx + 8*16 + 8*eax]      ; c  = coeff[i]
874                  pop     edi          movdqa xmm3, [ecx + 8*16 + 8*eax+ 16]
875                  pop     esi          pxor xmm1, xmm1
876            pxor xmm4, xmm4
877            pcmpgtw xmm1, xmm0  ; sign(c)
878            pcmpgtw xmm4, xmm3
879            pxor xmm2, xmm2
880            pxor xmm5, xmm5
881            pcmpeqw xmm2, xmm0  ; c is zero
882            pcmpeqw xmm5, xmm3
883            pandn xmm2, xmm6    ; offset = isZero ? 0 : quant_add
884            pandn xmm5, xmm6
885            pxor xmm0, xmm1     ; negate if negative
886            pxor xmm3, xmm4
887            psubw xmm0, xmm1
888            psubw xmm3, xmm4
889            pmullw xmm0, xmm7 ; *= 2Q
890            pmullw xmm3, xmm7
891            paddw xmm0, xmm2 ; + offset
892            paddw xmm3, xmm5
893            paddw xmm0, xmm1 ; negate back
894            paddw xmm3, xmm4
895    
896            ; saturates to +2047
897            movdqa xmm2, [sse2_2047]
898            pminsw xmm0, xmm2
899            add eax, 4
900            pminsw xmm3, xmm2
901    
902            pxor xmm0, xmm1
903            pxor xmm3, xmm4
904            movdqa [edx + 8*16 - 8*4 + 8*eax], xmm0
905            movdqa [edx + 8*16 - 8*4 + 8*eax + 16], xmm3
906            jnz     near .loop
907    
908            ; deal with DC
909            movd mm0, [ecx]
910            pmullw mm0, [esp+16]    ; dcscalar
911            movq mm2, [mmx_32767_minus_2047]
912            paddsw mm0, mm2
913            psubsw mm0, mm2
914            movq mm2, [mmx_32768_minus_2048]
915            psubsw mm0, mm2
916            paddsw mm0, mm2
917            movd eax, mm0
918            mov [edx], ax
919    
920                  ret                  ret
921  %endif  
922    
923    
924    
925  ;===========================================================================  ;===========================================================================
926  ;  ;
# Line 586  Line 932 
932    
933  align ALIGN  align ALIGN
934  cglobal dequant_inter_mmx  cglobal dequant_inter_mmx
935  dequant_inter_mmx  dequant_inter_mmx:
   
                 push    esi  
                 push    edi  
   
                 mov     edi, [esp + 8 + 4]      ; data  
                 mov     esi, [esp + 8 + 8]      ; coeff  
                 mov     eax, [esp + 8 + 12]     ; quant  
                 movq    mm6, [mmx_add + eax * 8 - 8]  
                 movq    mm7, [mmx_mul + eax * 8 - 8]  
936    
937                  xor eax, eax    mov    edx, [esp+ 4]        ; data
938      mov    ecx, [esp+ 8]        ; coeff
939      mov    eax, [esp+12]        ; quant
940      movq mm6, [mmx_add + eax*8 - 8]  ; quant or quant-1
941      movq mm7, [mmx_mul + eax*8 - 8]  ; 2*quant
942      mov eax, -16
943    
944  align ALIGN  align ALIGN
945  .loop  .loop
946                  movq    mm0, [esi + 8*eax]                      ; mm0 = [coeff]    movq mm0, [ecx+8*eax+8*16]      ; c  = coeff[i]
947                  movq    mm3, [esi + 8*eax + 8]          ;    movq mm3, [ecx+8*eax+8*16 + 8]  ; c' = coeff[i+1]
948                  pxor    mm1, mm1                ; mm1 = 0    pxor mm1, mm1
949                  pxor    mm4, mm4                ;    pxor mm4, mm4
950                  pcmpgtw mm1, mm0                ; mm1 = (0 > mm0)    pcmpgtw mm1, mm0  ; sign(c)
951                  pcmpgtw mm4, mm3                ;    pcmpgtw mm4, mm3  ; sign(c')
952                  pxor    mm2, mm2                ; mm2 = 0    pxor mm2, mm2
953                  pxor    mm5, mm5                ;    pxor mm5, mm5
954                  pcmpeqw mm2, mm0                ; mm2 = (0 == mm0)    pcmpeqw mm2, mm0  ; c is zero
955                  pcmpeqw mm5, mm3                ;    pcmpeqw mm5, mm3  ; c' is zero
956                  pandn   mm2, mm6                ; mm2 = (iszero ? 0 : add)    pandn mm2, mm6    ; offset = isZero ? 0 : quant_add
957                  pandn   mm5, mm6                ;    pandn mm5, mm6
958                  pxor    mm0, mm1                ; mm0 = |mm0|    pxor mm0, mm1     ; negate if negative
959                  pxor    mm3, mm4                ;    pxor mm3, mm4     ; negate if negative
960                  psubw   mm0, mm1                ; displace    psubw mm0, mm1
                 psubw   mm3, mm4                ;  
                 pmullw  mm0, mm7                ; mm0 *= 2Q  
                 pmullw  mm3, mm7                ;  
                 paddw   mm0, mm2                ; mm0 += mm2 (add)  
                 paddw   mm3, mm5                ;  
                 pxor    mm0, mm1                ; mm0 *= sign(mm0)  
                 pxor    mm3, mm4                ;  
                 psubw   mm0, mm1                ; undisplace  
961                  psubw   mm3, mm4                  psubw   mm3, mm4
962      pmullw mm0, mm7 ; *= 2Q
963      pmullw mm3, mm7 ; *= 2Q
964      paddw mm0, mm2 ; + offset
965      paddw mm3, mm5 ; + offset
966      paddw mm0, mm1 ; negate back
967      paddw mm3, mm4 ; negate back
968    
969  %ifdef SATURATE      ; saturates to +2047
970                  movq mm2, [mmx_32767_minus_2047]                  movq mm2, [mmx_32767_minus_2047]
971                  movq mm4, [mmx_32768_minus_2048]    add eax, 2
972                  paddsw  mm0, mm2                  paddsw  mm0, mm2
973                  paddsw  mm3, mm2                  paddsw  mm3, mm2
974                  psubsw  mm0, mm2                  psubsw  mm0, mm2
975                  psubsw  mm3, mm2                  psubsw  mm3, mm2
                 psubsw  mm0, mm4  
                 psubsw  mm3, mm4  
                 paddsw  mm0, mm4  
                 paddsw  mm3, mm4  
 %endif  
976    
977                  movq    [edi + 8*eax], mm0    pxor mm0, mm1
978                  movq    [edi + 8*eax + 8], mm3    pxor mm3, mm4
979      movq [edx + 8*eax + 8*16   - 2*8], mm0
980      movq [edx + 8*eax + 8*16+8 - 2*8], mm3
981      jnz   near .loop
982    
983      ret
984    
985    ;===========================================================================
986    ;
987    ; void dequant_inter_xmm(int16_t * data,
988    ;                                       const int16_t * const coeff,
989    ;                                       const uint32_t quant);
990    ;
991    ;===========================================================================
992    
993      ; this is the same as dequant_inter_mmx,
994      ; except that we're saturating using 'pminsw' (saves 2 cycles/loop)
995    
996    align ALIGN
997    cglobal dequant_inter_xmm
998    dequant_inter_xmm:
999    
1000      mov    edx, [esp+ 4]        ; data
1001      mov    ecx, [esp+ 8]        ; coeff
1002      mov    eax, [esp+12]        ; quant
1003      movq mm6, [mmx_add + eax*8 - 8]  ; quant or quant-1
1004      movq mm7, [mmx_mul + eax*8 - 8]  ; 2*quant
1005      mov eax, -16
1006    
1007    align ALIGN
1008    .loop
1009      movq mm0, [ecx+8*eax+8*16]      ; c  = coeff[i]
1010      movq mm3, [ecx+8*eax+8*16 + 8]  ; c' = coeff[i+1]
1011      pxor mm1, mm1
1012      pxor mm4, mm4
1013      pcmpgtw mm1, mm0  ; sign(c)
1014      pcmpgtw mm4, mm3  ; sign(c')
1015      pxor mm2, mm2
1016      pxor mm5, mm5
1017      pcmpeqw mm2, mm0  ; c is zero
1018      pcmpeqw mm5, mm3  ; c' is zero
1019      pandn mm2, mm6    ; offset = isZero ? 0 : quant_add
1020      pandn mm5, mm6
1021      pxor mm0, mm1     ; negate if negative
1022      pxor mm3, mm4     ; negate if negative
1023      psubw mm0, mm1
1024      psubw mm3, mm4
1025      pmullw mm0, mm7 ; *= 2Q
1026      pmullw mm3, mm7 ; *= 2Q
1027      paddw mm0, mm2 ; + offset
1028      paddw mm3, mm5 ; + offset
1029      paddw mm0, mm1 ; start restoring sign
1030      paddw mm3, mm4 ; start restoring sign
1031    
1032          ; saturates to +2047
1033      movq mm2, [mmx_2047]
1034      pminsw mm0, mm2
1035                  add eax, 2                  add eax, 2
1036                  cmp eax, 16    pminsw mm3, mm2
1037    
1038      pxor mm0, mm1 ; finish restoring sign
1039      pxor mm3, mm4 ; finish restoring sign
1040      movq [edx + 8*eax + 8*16   - 2*8], mm0
1041      movq [edx + 8*eax + 8*16+8 - 2*8], mm3
1042                  jnz     near .loop                  jnz     near .loop
1043    
1044                  pop     edi    ret
1045                  pop     esi  
1046    ;===========================================================================
1047    ;
1048    ; void dequant_inter_sse2(int16_t * data,
1049    ;                                       const int16_t * const coeff,
1050    ;                                       const uint32_t quant);
1051    ;
1052    ;===========================================================================
1053    align ALIGN
1054    cglobal dequant_inter_sse2
1055    dequant_inter_sse2
1056            mov edx, [esp + 4]      ; data
1057            mov ecx, [esp + 8]      ; coeff
1058            mov eax, [esp + 12]     ; quant
1059            movq mm6, [mmx_add + eax * 8 - 8]
1060            movq mm7, [mmx_mul + eax * 8 - 8]
1061            movq2dq xmm6, mm6
1062            movq2dq xmm7, mm7
1063            movlhps xmm6, xmm6
1064            movlhps xmm7, xmm7
1065            mov eax, -16
1066    
1067    align ALIGN
1068    .loop
1069            movdqa xmm0, [ecx + 8*16 + 8*eax]  ; c  = coeff[i]
1070            movdqa xmm3, [ecx + 8*16 + 8*eax + 16]
1071    
1072            pxor xmm1, xmm1
1073            pxor xmm4, xmm4
1074            pcmpgtw xmm1, xmm0  ; sign(c)
1075            pcmpgtw xmm4, xmm3
1076            pxor xmm2, xmm2
1077            pxor xmm5, xmm5
1078            pcmpeqw xmm2, xmm0  ; c is zero
1079            pcmpeqw xmm5, xmm3
1080            pandn xmm2, xmm6
1081            pandn xmm5, xmm6
1082            pxor xmm0, xmm1  ; negate if negative
1083            pxor xmm3, xmm4
1084            psubw xmm0, xmm1
1085            psubw xmm3, xmm4
1086            pmullw xmm0, xmm7  ; *= 2Q
1087            pmullw xmm3, xmm7
1088            paddw xmm0, xmm2  ; + offset
1089            paddw xmm3, xmm5
1090    
1091            paddw xmm0, xmm1  ; start restoring sign
1092            paddw xmm3, xmm4
1093    
1094            ; saturates to +2047
1095            movdqa xmm2, [sse2_2047]
1096            pminsw xmm0, xmm2
1097            add eax, 4
1098            pminsw xmm3, xmm2
1099    
1100            pxor xmm0, xmm1 ; finish restoring sign
1101            pxor xmm3, xmm4
1102            movdqa [edx + 8*16 - 8*4 + 8*eax], xmm0
1103            movdqa [edx + 8*16 - 8*4 + 8*eax + 16], xmm3
1104            jnz     near .loop
1105    
1106                  ret                  ret

Legend:
Removed from v.3  
changed lines
  Added in v.463

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