[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 265, Sun Jul 7 10:59:14 2002 UTC
# Line 42  Line 42 
42  ; *                                                                            *  ; *                                                                            *
43  ; *  Revision history:                                                         *  ; *  Revision history:                                                         *
44  ; *                                                                            *  ; *                                                                            *
45    ; *  14.06.2002  mmx dequant4_* funcs revamped  -Skal-                         *
46  ; *  22.01.2002 initial version                                                *  ; *  22.01.2002 initial version                                                *
47  ; *                                                                            *  ; *                                                                            *
48  ; ******************************************************************************/  ; ******************************************************************************/
# Line 237  Line 238 
238  ;===========================================================================  ;===========================================================================
239    
240  align 16  align 16
241  mmx_32768_minus_2048                times 4 dw (32768-2048)  
242  mmx_32767_minus_2047                times 4 dw (32767-2047)  mmx_32767_minus_2047                times 4 dw (32767-2047)
243    mmx_32768_minus_2048                            times 4 dw (32768-2048)
244    mmx_2047 times 4 dw 2047
245    mmx_minus_2048 times 4 dw (-2048)
246    zero times 4 dw 0
247    
248  section .text  section .text
249    
# Line 667  Line 672 
672  ;  ;
673  ;===========================================================================  ;===========================================================================
674    
675  align 16    ;   Note: in order to saturate 'easily', we pre-shift the quantifier
676  cglobal dequant4_intra_mmx    ; by 4. Then, the high-word of (coeff[]*matrix[i]*quant) are used to
677  dequant4_intra_mmx    ; build a saturating mask. It is non-zero only when an overflow occured.
678      ; We thus avoid packing/unpacking toward double-word.
679      ; Moreover, we perform the mult (matrix[i]*quant) first, instead of, e.g.,
680      ; (coeff[i]*matrix[i]). This is less prone to overflow if coeff[] are not
681      ; checked. Input ranges are: coeff in [-127,127], inter_matrix in [1..255],a
682      ; and quant in [1..31].
683      ;
684      ; The original loop is:
685      ;
686    %if 0
687      movq mm0, [ecx+8*eax + 8*16]   ; mm0 = coeff[i]
688      pxor mm1, mm1
689      pcmpgtw mm1, mm0
690      pxor mm0, mm1     ; change sign if negative
691      psubw mm0, mm1    ; -> mm0 = abs(coeff[i]), mm1 = sign of coeff[i]
692    
693      movq mm2, mm7     ; mm2 = quant
694      pmullw mm2,  [intra_matrix + 8*eax + 8*16 ]  ; matrix[i]*quant.
695    
696      movq mm6, mm2
697      pmulhw mm2, mm0   ; high of coeff*(matrix*quant)  (should be 0 if no overflow)
698      pmullw mm0, mm6   ; low  of coeff*(matrix*quant)
699    
700      pxor mm5, mm5
701      pcmpgtw mm2, mm5  ; otherflow?
702      psrlw mm2, 5      ; =0 if no clamp, 2047 otherwise
703      psrlw mm0, 5
704      paddw mm0, mm1    ; start restoring sign
705      por mm0, mm2      ; saturate to 2047 if needed
706      pxor mm0, mm1     ; finish negating back
707    
708          push    esi    movq [edx + 8*eax + 8*16], mm0   ; data[i]
709          push    edi    add eax, 1
710    %endif
711    
712          mov    edi, [esp + 8 + 4]        ; data    ;********************************************************************
         mov    esi, [esp + 8 + 8]        ; coeff  
         mov    eax, [esp + 8 + 12]        ; quant  
713    
714          movq mm7, [mmx_mul_quant  + eax*8 - 8]  align 16
715    cglobal dequant4_intra_mmx
716    dequant4_intra_mmx:
717    
718          xor eax, eax    mov edx, [esp+4]  ; data
719      mov ecx, [esp+8]  ; coeff
720      mov eax, [esp+12] ; quant
721    
722      movq mm7, [mmx_mul_quant  + eax*8 - 8]
723      mov eax, -16   ; to keep aligned, we regularly process coeff[0]
724      psllw mm7, 2   ; << 2. See comment.
725      pxor mm6, mm6   ; this is a NOP
726    
727  align 16  align 16
728  .loop  .loop
729          movq    mm0, [esi + 8*eax]        ; mm0 = [coeff]    movq mm0, [ecx+8*eax + 8*16]   ; mm0 = c  = coeff[i]
730      movq mm3, [ecx+8*eax + 8*16 +8]; mm3 = c' = coeff[i+1]
731      pxor mm1, mm1
732      pxor mm4, mm4
733      pcmpgtw mm1, mm0  ; mm1 = sgn(c)
734      movq mm2, mm7     ; mm2 = quant
735    
736          pxor    mm1, mm1                ; mm1 = 0    pcmpgtw mm4, mm3  ; mm4 = sgn(c')
737          pcmpeqw    mm1, mm0                ; mm1 = (0 == mm0)    pmullw mm2,  [intra_matrix + 8*eax + 8*16 ]  ; matrix[i]*quant
738    
739      pxor mm0, mm1     ; negate if negative
740      pxor mm3, mm4     ; negate if negative
741    
742          pxor    mm2, mm2                ; mm2 = 0    psubw mm0, mm1
743          pcmpgtw    mm2, mm0                ; mm2 = (0 > mm0)    psubw mm3, mm4
         pxor    mm0, mm2                ; mm0 = |mm0|  
         psubw    mm0, mm2                ; displace  
744    
745          pmullw    mm0, mm7                ; mm0 *= quant      ; we're short on register, here. Poor pairing...
746    
747          movq    mm3, [intra_matrix + 8*eax]    movq mm5, mm2
748      pmullw mm2, mm0   ; low  of coeff*(matrix*quant)
749    
750          movq  mm4, mm0                    ;    pmulhw mm0, mm5   ; high of coeff*(matrix*quant)
751          pmullw    mm0, mm3                ; mm0 = low(mm0 * mm3)    movq mm5, mm7     ; mm2 = quant
         pmulhw    mm3, mm4                ; mm3 = high(mm0 * mm3)  
752    
753          movq    mm4, mm0                ; mm0,mm4 = unpack(mm3, mm0)    pmullw mm5,  [intra_matrix + 8*eax + 8*16 +8]  ; matrix[i+1]*quant
         punpcklwd mm0, mm3                ;  
         punpckhwd mm4, mm3                ;  
         psrld mm0, 3                    ; mm0,mm4 /= 8  
         psrld mm4, 3                    ;  
         packssdw mm0, mm4                ; mm0 = pack(mm4, mm0)  
754    
755          pxor    mm0, mm2                ; mm0 *= sign(mm0)    movq mm6, mm5
756          psubw    mm0, mm2                ; undisplace    add eax,2   ; z-flag will be tested later
         pandn    mm1, mm0                ; mm1 = ~(iszero) & mm0  
757    
758  %ifdef SATURATE    pmullw mm6, mm3   ; low  of coeff*(matrix*quant)
759          movq mm2, [mmx_32767_minus_2047]    pmulhw mm3, mm5   ; high of coeff*(matrix*quant)
         movq mm6, [mmx_32768_minus_2048]  
         paddsw    mm1, mm2  
         psubsw    mm1, mm2  
         psubsw    mm1, mm6  
         paddsw    mm1, mm6  
 %endif  
760    
761          movq    [edi + 8*eax], mm1        ; [data] = mm0    pcmpgtw mm0, [zero]
762      paddusw mm2, mm0
763      psrlw mm2, 5
764    
765          add eax, 1    pcmpgtw mm3, [zero]
766          cmp eax, 16    paddusw mm6, mm3
767          jnz    near .loop    psrlw mm6, 5
768    
769          mov    ax, [esi]                    ; ax = data[0]    pxor mm2, mm1  ; start negating back
770          imul     ax, [esp + 8 + 16]        ; eax = data[0] * dcscalar    pxor mm6, mm4  ; start negating back
         mov    [edi], ax                    ; data[0] = ax  
   
 %ifdef SATURATE  
         cmp ax, -2048  
         jl .set_n2048  
         cmp ax, 2047  
         jg .set_2047  
 %endif  
771    
772          pop    edi    psubusw mm1, mm0
773          pop    esi    psubusw mm4, mm3
         ret  
774    
775  %ifdef SATURATE    psubw mm2, mm1 ; finish negating back
776  .set_n2048    psubw mm6, mm4 ; finish negating back
         mov    word [edi], -2048  
         pop    edi  
         pop    esi  
         ret  
777    
778  .set_2047    movq [edx + 8*eax + 8*16   -2*8   ], mm2   ; data[i]
779          mov    word [edi], 2047    movq [edx + 8*eax + 8*16   -2*8 +8], mm6   ; data[i+1]
         pop    edi  
         pop    esi  
780    
781                  ret    jz .noloop
782  %endif    jmp .loop
783    .noloop
784    
785        ; deal with DC
786    
787      movd mm0, [ecx]
788      pmullw mm0, [esp+16]  ; dcscalar
789      movq mm2, [mmx_32767_minus_2047]
790      paddsw mm0, mm2
791      psubsw mm0, mm2
792      movq mm2, [mmx_32768_minus_2048]
793      psubsw mm0, mm2
794      paddsw mm0, mm2
795      movd eax, mm0
796      mov [edx], ax
797    
798      ret
799    
800  ;===========================================================================  ;===========================================================================
801  ;  ;
# Line 769  Line 805 
805  ;  ;
806  ;===========================================================================  ;===========================================================================
807    
808        ; Note:  We use (2*c + sgn(c) - sgn(-c)) as multiplier
809        ; so we handle the 3 cases: c<0, c==0, and c>0 in one shot.
810        ; sgn(x) is the result of 'pcmpgtw 0,x':  0 if x>=0, -1 if x<0.
811        ; It's mixed with the extraction of the absolute value.
812    
813  align 16  align 16
814  cglobal dequant4_inter_mmx  cglobal dequant4_inter_mmx
815  dequant4_inter_mmx  dequant4_inter_mmx:
816    
817          push    esi    mov    edx, [esp+ 4]        ; data
818          push    edi    mov    ecx, [esp+ 8]        ; coeff
819      mov    eax, [esp+12]        ; quant
         mov    edi, [esp + 8 + 4]        ; data  
         mov    esi, [esp + 8 + 8]        ; coeff  
         mov    eax, [esp + 8 + 12]        ; quant  
820          movq mm7, [mmx_mul_quant  + eax*8 - 8]          movq mm7, [mmx_mul_quant  + eax*8 - 8]
821          movq mm6, [mmx_one]    mov eax, -16
822          xor eax, eax    paddw mm7, mm7    ; << 1
823          pxor mm5, mm5        ; mismatch sum    pxor mm6, mm6 ; mismatch sum
   
824    
825  align 16  align 16
826  .loop  .loop
827          movq    mm0, [esi + 8*eax]                        ; mm0 = [coeff]    movq mm0, [ecx+8*eax + 8*16   ]   ; mm0 = coeff[i]
828      movq mm2, [ecx+8*eax + 8*16 +8]   ; mm2 = coeff[i+1]
829          pxor    mm1, mm1                ; mm1 = 0    add eax,2
830          pcmpeqw    mm1, mm0                ; mm1 = (0 == mm0)  
831      pxor mm1, mm1
832          pxor    mm2, mm2                ; mm2 = 0    pxor mm3, mm3
833          pcmpgtw    mm2, mm0                ; mm2 = (0 > mm0)    pcmpgtw mm1, mm0  ; mm1 = sgn(c)    (preserved)
834          pxor    mm0, mm2                ; mm0 = |mm0|    pcmpgtw mm3, mm2  ; mm3 = sgn(c')   (preserved)
835          psubw    mm0, mm2                ; displace    paddsw mm0, mm1   ; c += sgn(c)
836      paddsw mm2, mm3   ; c += sgn(c')
837          psllw    mm0, 1                ;    paddw mm0, mm0    ; c *= 2
838          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            ;  
   
         psrad mm0, 4                ; mm0,mm4 /= 16  
         psrad mm4, 4                ;  
         packssdw mm0, mm4            ; mm0 = pack(mm4, mm0)  
839    
840          pxor    mm0, mm2            ; mm0 *= sign(mm0)    pxor mm4, mm4
841          psubw    mm0, mm2            ; undisplace    pxor mm5, mm5
842          pandn    mm1, mm0            ; mm1 = ~(iszero) & mm0    psubw mm4, mm0    ; -c
843      psubw mm5, mm2    ; -c'
844      psraw mm4, 16     ; mm4 = sgn(-c)
845  ;%ifdef SATURATE    psraw mm5, 16     ; mm5 = sgn(-c')
846          movq mm2, [mmx_32767_minus_2047]    psubsw mm0, mm4   ; c  -= sgn(-c)
847          movq mm4, [mmx_32768_minus_2048]    psubsw mm2, mm5   ; c' -= sgn(-c')
848          paddsw    mm1, mm2    pxor mm0, mm1     ; finish changing sign if needed
849          psubsw    mm1, mm2    pxor mm2, mm3     ; finish changing sign if needed
850          psubsw    mm1, mm4  
851          paddsw    mm1, mm4      ; we're short on register, here. Poor pairing...
852  ;%endif  
853      movq mm4, mm7     ; (matrix*quant)
854          pxor mm5, mm1        ; mismatch    pmullw mm4,  [inter_matrix + 8*eax + 8*16 -2*8]
855      movq mm5, mm4
856          movq    [edi + 8*eax], mm1        ; [data] = mm0    pmulhw mm5, mm0   ; high of c*(matrix*quant)
857      pmullw mm0, mm4   ; low  of c*(matrix*quant)
858          add eax, 1  
859          cmp eax, 16    movq mm4, mm7     ; (matrix*quant)
860          jnz    near .loop    pmullw mm4,  [inter_matrix + 8*eax + 8*16 -2*8 + 8]
861    
862      pcmpgtw mm5, [zero]
863      paddusw mm0, mm5
864      psrlw mm0, 5
865      pxor mm0, mm1     ; start restoring sign
866      psubusw mm1, mm5
867    
868      movq mm5, mm4
869      pmulhw mm5, mm2   ; high of c*(matrix*quant)
870      pmullw mm2, mm4   ; low  of c*(matrix*quant)
871      psubw mm0, mm1    ; finish restoring sign
872    
873      pcmpgtw mm5, [zero]
874      paddusw mm2, mm5
875      psrlw mm2, 5
876      pxor mm2, mm3    ; start restoring sign
877      psubusw mm3, mm5
878      psubw mm2, mm3   ; finish restoring sign
879    
880      pxor mm6, mm0     ; mismatch control
881      movq [edx + 8*eax + 8*16 -2*8   ], mm0   ; data[i]
882      pxor mm6, mm2     ; mismatch control
883      movq [edx + 8*eax + 8*16 -2*8 +8], mm2   ; data[i+1]
884    
885      jz .noloop
886      jmp .loop
887    .noloop
888    
889          ; mismatch control          ; mismatch control
890    
891          movq mm0, mm5    movq mm0, mm6
         movq mm1, mm5  
         movq mm2, mm5  
892          psrlq mm0, 48          psrlq mm0, 48
893      movq mm1, mm6
894      movq mm2, mm6
895          psrlq mm1, 32          psrlq mm1, 32
896      pxor mm6, mm0
897          psrlq mm2, 16          psrlq mm2, 16
898          pxor mm5, mm0    pxor mm6, mm1
899          pxor mm5, mm1    pxor mm6, mm2
900          pxor mm5, mm2    movd eax, mm6
901      and eax, 1
902          movd eax, mm5    xor eax, 1
903          test eax, 0x1    xor word [edx + 2*63], ax
         jnz .done  
   
         xor word [edi + 2*63], 1  
   
 .done  
         pop    edi  
         pop    esi  
904    
905          ret          ret
906    

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

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