[svn] / trunk / xvidcore / src / quant / x86_asm / quantize4_mmx.asm Repository:
ViewVC logotype

Diff of /trunk/xvidcore/src/quant/x86_asm/quantize4_mmx.asm

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

revision 4, Fri Mar 8 19:17:46 2002 UTC revision 463, Tue Sep 10 21:16:45 2002 UTC
# Line 1  Line 1 
1  ;/******************************************************************************  ;/*****************************************************************************
2  ; *                                                                            *  ; *
3  ; *  This file is part of XviD, a free MPEG-4 video encoder/decoder            *  ; *  XVID MPEG-4 VIDEO CODEC
4  ; *                                                                            *  ; *  mmx optimized MPEG quantization/dequantization
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    *  ; *  Copyright(C) 2002 Peter Ross <pross@xvid.org>
7  ; *  software module in hardware or software products are advised that its     *  ; *  Copyright(C) 2002 Michael Militzer <michael@xvid.org>
8  ; *  use may infringe existing patents or copyrights, and any such use         *  ; *  Copyright(C) 2002 Pascal Massimino <skal@planet-d.net>
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     *  ; *  This program is an implementation of a part of one or more MPEG-4
11  ; *  companies, will have no liability for use of this software or             *  ; *  Video tools as specified in ISO/IEC 14496-2 standard.  Those intending
12  ; *  modifications or derivatives thereof.                                     *  ; *  to use this software module in hardware or software products are
13  ; *                                                                            *  ; *  advised that its use may infringe existing patents or copyrights, and
14  ; *  XviD is free software; you can redistribute it and/or modify it           *  ; *  any such use would be at such party's own risk.  The original
15  ; *  under the terms of the GNU General Public License as published by         *  ; *  developer of this software module and his/her company, and subsequent
16  ; *  the Free Software Foundation; either version 2 of the License, or         *  ; *  editors and their companies, will have no liability for use of this
17  ; *  (at your option) any later version.                                       *  ; *  software or modifications or derivatives thereof.
18  ; *                                                                            *  ; *
19  ; *  XviD is distributed in the hope that it will be useful, but               *  ; *  This program is free software; you can redistribute it and/or modify
20  ; *  WITHOUT ANY WARRANTY; without even the implied warranty of                *  ; *  it under the terms of the GNU General Public License as published by
21  ; *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *  ; *  the Free Software Foundation; either version 2 of the License, or
22  ; *  GNU General Public License for more details.                              *  ; *  (at your option) any later version.
23  ; *                                                                            *  ; *
24  ; *  You should have received a copy of the GNU General Public License         *  ; *  This program is distributed in the hope that it will be useful,
25  ; *  along with this program; if not, write to the Free Software               *  ; *  but WITHOUT ANY WARRANTY; without even the implied warranty of
26  ; *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA  *  ; *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27  ; *                                                                            *  ; *  GNU General Public License for more details.
28  ; ******************************************************************************/  ; *
29  ;  ; *  You should have received a copy of the GNU General Public License
30  ;/******************************************************************************  ; *  along with this program; if not, write to the Free Software
31  ; *                                                                            *  ; *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
32  ; *  quantize4.asm, MMX optimized MPEG quantization/dequantization             *  ; *
33  ; *                                                                            *  ; *************************************************************************/
 ; *  Copyright (C) 2002 - Peter Ross <pross@cs.rmit.edu.au>                    *  
 ; *  Copyright (C) 2002 - Michael Militzer <isibaar@xvid.org>                  *  
 ; *                                                                            *  
 ; *  For more information visit the XviD homepage: http://www.xvid.org         *  
 ; *                                                                            *  
 ; ******************************************************************************/  
 ;  
 ;/******************************************************************************  
 ; *                                                                            *  
 ; *  Revision history:                                                         *  
 ; *                                                                            *  
 ; *  22.01.2002 initial version                                                *  
 ; *                                                                            *  
 ; ******************************************************************************/  
34    
35  ; data/text alignment  ; data/text alignment
36  %define ALIGN 8  %define ALIGN 8
# Line 237  Line 223 
223  ;===========================================================================  ;===========================================================================
224    
225  align 16  align 16
226  mmx_32768_minus_2048                times 4 dw (32768-2048)  
227  mmx_32767_minus_2047                times 4 dw (32767-2047)  mmx_32767_minus_2047                times 4 dw (32767-2047)
228    mmx_32768_minus_2048                            times 4 dw (32768-2048)
229    mmx_2047 times 4 dw 2047
230    mmx_minus_2048 times 4 dw (-2048)
231    zero times 4 dw 0
232    
233  section .text  section .text
234    
# Line 667  Line 657 
657  ;  ;
658  ;===========================================================================  ;===========================================================================
659    
660  align 16    ;   Note: in order to saturate 'easily', we pre-shift the quantifier
661  cglobal dequant4_intra_mmx    ; by 4. Then, the high-word of (coeff[]*matrix[i]*quant) are used to
662  dequant4_intra_mmx    ; build a saturating mask. It is non-zero only when an overflow occured.
663      ; We thus avoid packing/unpacking toward double-word.
664      ; Moreover, we perform the mult (matrix[i]*quant) first, instead of, e.g.,
665      ; (coeff[i]*matrix[i]). This is less prone to overflow if coeff[] are not
666      ; checked. Input ranges are: coeff in [-127,127], inter_matrix in [1..255],a
667      ; and quant in [1..31].
668      ;
669      ; The original loop is:
670      ;
671    %if 0
672      movq mm0, [ecx+8*eax + 8*16]   ; mm0 = coeff[i]
673      pxor mm1, mm1
674      pcmpgtw mm1, mm0
675      pxor mm0, mm1     ; change sign if negative
676      psubw mm0, mm1    ; -> mm0 = abs(coeff[i]), mm1 = sign of coeff[i]
677    
678      movq mm2, mm7     ; mm2 = quant
679      pmullw mm2,  [intra_matrix + 8*eax + 8*16 ]  ; matrix[i]*quant.
680    
681      movq mm6, mm2
682      pmulhw mm2, mm0   ; high of coeff*(matrix*quant)  (should be 0 if no overflow)
683      pmullw mm0, mm6   ; low  of coeff*(matrix*quant)
684    
685      pxor mm5, mm5
686      pcmpgtw mm2, mm5  ; otherflow?
687      psrlw mm2, 5      ; =0 if no clamp, 2047 otherwise
688      psrlw mm0, 5
689      paddw mm0, mm1    ; start restoring sign
690      por mm0, mm2      ; saturate to 2047 if needed
691      pxor mm0, mm1     ; finish negating back
692    
693          push    esi    movq [edx + 8*eax + 8*16], mm0   ; data[i]
694          push    edi    add eax, 1
695    %endif
696    
697          mov    edi, [esp + 8 + 4]        ; data    ;********************************************************************
         mov    esi, [esp + 8 + 8]        ; coeff  
         mov    eax, [esp + 8 + 12]        ; quant  
698    
699          movq mm7, [mmx_mul_quant  + eax*8 - 8]  align 16
700    cglobal dequant4_intra_mmx
701    dequant4_intra_mmx:
702    
703          xor eax, eax    mov edx, [esp+4]  ; data
704      mov ecx, [esp+8]  ; coeff
705      mov eax, [esp+12] ; quant
706    
707      movq mm7, [mmx_mul_quant  + eax*8 - 8]
708      mov eax, -16   ; to keep aligned, we regularly process coeff[0]
709      psllw mm7, 2   ; << 2. See comment.
710      pxor mm6, mm6   ; this is a NOP
711    
712  align 16  align 16
713  .loop  .loop
714          movq    mm0, [esi + 8*eax]        ; mm0 = [coeff]    movq mm0, [ecx+8*eax + 8*16]   ; mm0 = c  = coeff[i]
715      movq mm3, [ecx+8*eax + 8*16 +8]; mm3 = c' = coeff[i+1]
716      pxor mm1, mm1
717      pxor mm4, mm4
718      pcmpgtw mm1, mm0  ; mm1 = sgn(c)
719      movq mm2, mm7     ; mm2 = quant
720    
721          pxor    mm1, mm1                ; mm1 = 0    pcmpgtw mm4, mm3  ; mm4 = sgn(c')
722          pcmpeqw    mm1, mm0                ; mm1 = (0 == mm0)    pmullw mm2,  [intra_matrix + 8*eax + 8*16 ]  ; matrix[i]*quant
723    
724          pxor    mm2, mm2                ; mm2 = 0    pxor mm0, mm1     ; negate if negative
725          pcmpgtw    mm2, mm0                ; mm2 = (0 > mm0)    pxor mm3, mm4     ; negate if negative
         pxor    mm0, mm2                ; mm0 = |mm0|  
         psubw    mm0, mm2                ; displace  
726    
727          pmullw    mm0, mm7                ; mm0 *= quant    psubw mm0, mm1
728      psubw mm3, mm4
729    
730          movq    mm3, [intra_matrix + 8*eax]      ; we're short on register, here. Poor pairing...
731    
732          movq  mm4, mm0                    ;    movq mm5, mm2
733          pmullw    mm0, mm3                ; mm0 = low(mm0 * mm3)    pmullw mm2, mm0   ; low  of coeff*(matrix*quant)
         pmulhw    mm3, mm4                ; mm3 = high(mm0 * mm3)  
734    
735          movq    mm4, mm0                ; mm0,mm4 = unpack(mm3, mm0)    pmulhw mm0, mm5   ; high of coeff*(matrix*quant)
736          punpcklwd mm0, mm3                ;    movq mm5, mm7     ; mm2 = quant
         punpckhwd mm4, mm3                ;  
         psrld mm0, 3                    ; mm0,mm4 /= 8  
         psrld mm4, 3                    ;  
         packssdw mm0, mm4                ; mm0 = pack(mm4, mm0)  
737    
738          pxor    mm0, mm2                ; mm0 *= sign(mm0)    pmullw mm5,  [intra_matrix + 8*eax + 8*16 +8]  ; matrix[i+1]*quant
         psubw    mm0, mm2                ; undisplace  
         pandn    mm1, mm0                ; mm1 = ~(iszero) & mm0  
739    
740  %ifdef SATURATE    movq mm6, mm5
741          movq mm2, [mmx_32767_minus_2047]    add eax,2   ; z-flag will be tested later
         movq mm6, [mmx_32768_minus_2048]  
         paddsw    mm1, mm2  
         psubsw    mm1, mm2  
         psubsw    mm1, mm6  
         paddsw    mm1, mm6  
 %endif  
742    
743          movq    [edi + 8*eax], mm1        ; [data] = mm0    pmullw mm6, mm3   ; low  of coeff*(matrix*quant)
744      pmulhw mm3, mm5   ; high of coeff*(matrix*quant)
745    
746          add eax, 1    pcmpgtw mm0, [zero]
747          cmp eax, 16    paddusw mm2, mm0
748          jnz    near .loop    psrlw mm2, 5
749    
750          mov    ax, [esi]                    ; ax = data[0]    pcmpgtw mm3, [zero]
751          imul     ax, [esp + 8 + 16]        ; eax = data[0] * dcscalar    paddusw mm6, mm3
752          mov    [edi], ax                    ; data[0] = ax    psrlw mm6, 5
   
 %ifdef SATURATE  
         cmp ax, -2048  
         jl .set_n2048  
         cmp ax, 2047  
         jg .set_2047  
 %endif  
753    
754          pop    edi    pxor mm2, mm1  ; start negating back
755          pop    esi    pxor mm6, mm4  ; start negating back
         ret  
756    
757  %ifdef SATURATE    psubusw mm1, mm0
758  .set_n2048    psubusw mm4, mm3
         mov    word [edi], -2048  
         pop    edi  
         pop    esi  
         ret  
759    
760  .set_2047    psubw mm2, mm1 ; finish negating back
761          mov    word [edi], 2047    psubw mm6, mm4 ; finish negating back
         pop    edi  
         pop    esi  
762    
763                  ret    movq [edx + 8*eax + 8*16   -2*8   ], mm2   ; data[i]
764  %endif    movq [edx + 8*eax + 8*16   -2*8 +8], mm6   ; data[i+1]
765    
766      jnz near .loop
767    
768        ; deal with DC
769    
770      movd mm0, [ecx]
771      pmullw mm0, [esp+16]  ; dcscalar
772      movq mm2, [mmx_32767_minus_2047]
773      paddsw mm0, mm2
774      psubsw mm0, mm2
775      movq mm2, [mmx_32768_minus_2048]
776      psubsw mm0, mm2
777      paddsw mm0, mm2
778      movd eax, mm0
779      mov [edx], ax
780    
781      ret
782    
783  ;===========================================================================  ;===========================================================================
784  ;  ;
# Line 769  Line 788 
788  ;  ;
789  ;===========================================================================  ;===========================================================================
790    
791        ; Note:  We use (2*c + sgn(c) - sgn(-c)) as multiplier
792        ; so we handle the 3 cases: c<0, c==0, and c>0 in one shot.
793        ; sgn(x) is the result of 'pcmpgtw 0,x':  0 if x>=0, -1 if x<0.
794        ; It's mixed with the extraction of the absolute value.
795    
796  align 16  align 16
797  cglobal dequant4_inter_mmx  cglobal dequant4_inter_mmx
798  dequant4_inter_mmx  dequant4_inter_mmx:
   
         push    esi  
         push    edi  
799    
800          mov    edi, [esp + 8 + 4]        ; data    mov    edx, [esp+ 4]        ; data
801          mov    esi, [esp + 8 + 8]        ; coeff    mov    ecx, [esp+ 8]        ; coeff
802          mov    eax, [esp + 8 + 12]        ; quant    mov    eax, [esp+12]        ; quant
803          movq mm7, [mmx_mul_quant  + eax*8 - 8]          movq mm7, [mmx_mul_quant  + eax*8 - 8]
804          movq mm6, [mmx_one]    mov eax, -16
805          xor eax, eax    paddw mm7, mm7    ; << 1
806          pxor mm5, mm5        ; mismatch sum    pxor mm6, mm6 ; mismatch sum
   
807    
808  align 16  align 16
809  .loop  .loop
810          movq    mm0, [esi + 8*eax]                        ; mm0 = [coeff]    movq mm0, [ecx+8*eax + 8*16   ]   ; mm0 = coeff[i]
811      movq mm2, [ecx+8*eax + 8*16 +8]   ; mm2 = coeff[i+1]
812          pxor    mm1, mm1                ; mm1 = 0    add eax,2
813          pcmpeqw    mm1, mm0                ; mm1 = (0 == mm0)  
814      pxor mm1, mm1
815          pxor    mm2, mm2                ; mm2 = 0    pxor mm3, mm3
816          pcmpgtw    mm2, mm0                ; mm2 = (0 > mm0)    pcmpgtw mm1, mm0  ; mm1 = sgn(c)    (preserved)
817          pxor    mm0, mm2                ; mm0 = |mm0|    pcmpgtw mm3, mm2  ; mm3 = sgn(c')   (preserved)
818          psubw    mm0, mm2                ; displace    paddsw mm0, mm1   ; c += sgn(c)
819      paddsw mm2, mm3   ; c += sgn(c')
820          psllw    mm0, 1                ;    paddw mm0, mm0    ; c *= 2
821          paddsw    mm0, mm6            ; mm0 = 2*mm0 + 1    paddw mm2, mm2    ; c'*= 2
         pmullw    mm0, mm7            ; mm0 *= quant  
   
         movq    mm3, [inter_matrix + 8*eax]  
   
         movq  mm4, mm0  
         pmullw    mm0, mm3            ; mm0 = low(mm0 * mm3)  
         pmulhw    mm3, mm4            ; mm3 = high(mm0 * mm3)  
   
         movq    mm4, mm0            ; mm0,mm4 = unpack(mm3, mm0)  
         punpcklwd mm0, mm3            ;  
         punpckhwd mm4, mm3            ;  
822    
823          psrad mm0, 4                ; mm0,mm4 /= 16    pxor mm4, mm4
824          psrad mm4, 4                ;    pxor mm5, mm5
825          packssdw mm0, mm4            ; mm0 = pack(mm4, mm0)    psubw mm4, mm0    ; -c
826      psubw mm5, mm2    ; -c'
827          pxor    mm0, mm2            ; mm0 *= sign(mm0)    psraw mm4, 16     ; mm4 = sgn(-c)
828          psubw    mm0, mm2            ; undisplace    psraw mm5, 16     ; mm5 = sgn(-c')
829          pandn    mm1, mm0            ; mm1 = ~(iszero) & mm0    psubsw mm0, mm4   ; c  -= sgn(-c)
830      psubsw mm2, mm5   ; c' -= sgn(-c')
831      pxor mm0, mm1     ; finish changing sign if needed
832  ;%ifdef SATURATE    pxor mm2, mm3     ; finish changing sign if needed
833          movq mm2, [mmx_32767_minus_2047]  
834          movq mm4, [mmx_32768_minus_2048]      ; we're short on register, here. Poor pairing...
835          paddsw    mm1, mm2  
836          psubsw    mm1, mm2    movq mm4, mm7     ; (matrix*quant)
837          psubsw    mm1, mm4    pmullw mm4,  [inter_matrix + 8*eax + 8*16 -2*8]
838          paddsw    mm1, mm4    movq mm5, mm4
839  ;%endif    pmulhw mm5, mm0   ; high of c*(matrix*quant)
840      pmullw mm0, mm4   ; low  of c*(matrix*quant)
841          pxor mm5, mm1        ; mismatch  
842      movq mm4, mm7     ; (matrix*quant)
843          movq    [edi + 8*eax], mm1        ; [data] = mm0    pmullw mm4,  [inter_matrix + 8*eax + 8*16 -2*8 + 8]
844    
845      pcmpgtw mm5, [zero]
846      paddusw mm0, mm5
847      psrlw mm0, 5
848      pxor mm0, mm1     ; start restoring sign
849      psubusw mm1, mm5
850    
851      movq mm5, mm4
852      pmulhw mm5, mm2   ; high of c*(matrix*quant)
853      pmullw mm2, mm4   ; low  of c*(matrix*quant)
854      psubw mm0, mm1    ; finish restoring sign
855    
856      pcmpgtw mm5, [zero]
857      paddusw mm2, mm5
858      psrlw mm2, 5
859      pxor mm2, mm3    ; start restoring sign
860      psubusw mm3, mm5
861      psubw mm2, mm3   ; finish restoring sign
862    
863      pxor mm6, mm0     ; mismatch control
864      movq [edx + 8*eax + 8*16 -2*8   ], mm0   ; data[i]
865      pxor mm6, mm2     ; mismatch control
866      movq [edx + 8*eax + 8*16 -2*8 +8], mm2   ; data[i+1]
867    
         add eax, 1  
         cmp eax, 16  
868          jnz    near .loop          jnz    near .loop
869    
870          ; mismatch control          ; mismatch control
871    
872          movq mm0, mm5    movq mm0, mm6
         movq mm1, mm5  
         movq mm2, mm5  
873          psrlq mm0, 48          psrlq mm0, 48
874      movq mm1, mm6
875      movq mm2, mm6
876          psrlq mm1, 32          psrlq mm1, 32
877      pxor mm6, mm0
878          psrlq mm2, 16          psrlq mm2, 16
879          pxor mm5, mm0    pxor mm6, mm1
880          pxor mm5, mm1    pxor mm6, mm2
881          pxor mm5, mm2    movd eax, mm6
882      and eax, 1
883          movd eax, mm5    xor eax, 1
884          test eax, 0x1    xor word [edx + 2*63], ax
         jnz .done  
   
         xor word [edi + 2*63], 1  
   
 .done  
         pop    edi  
         pop    esi  
885    
886          ret          ret
887    

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

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