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

View of /branches/dev-api-4/xvidcore/src/quant/x86_asm/quantize_mpeg_xmm.asm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1192 - (download) (annotate)
Tue Oct 28 22:23:03 2003 UTC (20 years, 5 months ago) by edgomez
File size: 22432 byte(s)
* Applied same style to all asm files
* Replaced current sad sse2 operators with skal's ones
* Removed old and unused colorspace asm files
;/****************************************************************************
; *
; *  XVID MPEG-4 VIDEO CODEC
; *  - 3dne Quantization/Dequantization -
; *
; *  Copyright (C) 2002-2003 Peter Ross <pross@xvid.org>
; *                2002      Jaan Kalda
; *
; *  This program is free software ; you can redistribute it and/or modify
; *  it under the terms of the GNU General Public License as published by
; *  the Free Software Foundation ; either version 2 of the License, or
; *  (at your option) any later version.
; *
; *  This program is distributed in the hope that it will be useful,
; *  but WITHOUT ANY WARRANTY ; without even the implied warranty of
; *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
; *  GNU General Public License for more details.
; *
; *  You should have received a copy of the GNU General Public License
; *  along with this program ; if not, write to the Free Software
; *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
; *
; * $Id: quantize_mpeg_xmm.asm,v 1.1.2.3 2003-10-28 22:23:03 edgomez Exp $
; *
; ***************************************************************************/

; _3dne functions are compatible with iSSE, but are optimized specifically
; for K7 pipelines

%define SATURATE

BITS 32

%macro cglobal 1
	%ifdef PREFIX
		global _%1
		%define %1 _%1
	%else
		global %1
	%endif
%endmacro

%macro cextern 1
	%ifdef PREFIX
		extern _%1
		%define %1 _%1
	%else
		extern %1
	%endif
%endmacro

;=============================================================================
; Local data
;=============================================================================

SECTION .rodata

ALIGN 8
mmzero:
	dd 0,0
mmx_one:
	times 4 dw 1

;-----------------------------------------------------------------------------
; divide by 2Q table
;-----------------------------------------------------------------------------

ALIGN 16
mmx_divs:		;i>2
%assign i 1
%rep 31
	times 4 dw  ((1 << 15) / i + 1)
	%assign i i+1
%endrep

ALIGN 16
mmx_div:		;quant>2
	times 4 dw 65535 ; the div by 2 formula will overflow for the case
	                 ; quant=1 but we don't care much because quant=1
	                 ; is handled by a different piece of code that
	                 ; doesn't use this table.
%assign quant 2
%rep 31
	times 4 dw  ((1 << 16) / quant + 1)
	%assign quant quant+1
%endrep


;-----------------------------------------------------------------------------
; intra matrix
; (TODO remove dependency on external tables for instance safiness)
;-----------------------------------------------------------------------------

%macro FIXX 1
dw (1 << 16) / (%1) + 1
%endmacro

cextern intra_matrix_fixl
cextern intra_matrix_fix
cextern intra_matrix1
cextern intra_matrix

;-----------------------------------------------------------------------------
; inter matrix
; (TODO remove dependency on external tables for instance safiness)
;-----------------------------------------------------------------------------

cextern inter_matrix1
cextern inter_matrix
cextern inter_matrix_fix
cextern inter_matrix_fixl


%define nop4	db	08Dh, 074h, 026h,0
%define nop3	add	esp, byte 0
%define nop2	mov	esp, esp
%define nop7	db	08dh, 02ch, 02dh,0,0,0,0
%define nop6	add	ebp, dword 0

;-----------------------------------------------------------------------------
; quantd table
;-----------------------------------------------------------------------------

%define VM18P	3
%define VM18Q	4

ALIGN 16
quantd:
%assign i 1
%rep 31
	times 4 dw  (((VM18P*i) + (VM18Q/2)) / VM18Q)
	%assign i i+1
%endrep

;-----------------------------------------------------------------------------
; multiple by 2Q table
;-----------------------------------------------------------------------------

ALIGN 16
mmx_mul_quant:
%assign i 1
%rep 31
	times 4 dw  i
	%assign i i+1
%endrep

;-----------------------------------------------------------------------------
; saturation limits
;-----------------------------------------------------------------------------

ALIGN 16
mmx_32767_minus_2047:
	times 4 dw (32767-2047)
mmx_32768_minus_2048:
	times 4 dw (32768-2048)
mmx_2047:
	times 4 dw 2047
mmx_minus_2048:
	times 4 dw (-2048)
zero:
	times 4 dw 0

int_div:
dd 0
%assign i 1
%rep 255
	dd  (1 << 17) / ( i) + 1
	%assign i i+1
%endrep

;=============================================================================
; Code
;=============================================================================

SECTION .text

cglobal quant_mpeg_intra_xmm
cglobal quant_mpeg_inter_xmm
cglobal dequant_mpeg_intra_3dne
cglobal dequant_mpeg_inter_3dne

;-----------------------------------------------------------------------------
;
; uint32_t quant_mpeg_intra_xmm(int16_t * coeff,
;                               const int16_t const * data,
;                               const uint32_t quant,
;                               const uint32_t dcscalar);
;
;-----------------------------------------------------------------------------

ALIGN 16
quant_mpeg_intra_xmm:
  mov eax, [esp  + 8]       ; data
  mov ecx, [esp  + 12]      ; quant
  mov edx, [esp  + 4]       ; coeff
  push esi
  push edi
  push ebx
  nop
  mov edi, mmzero
  mov esi, -14
  pxor mm0, mm0
  pxor mm3, mm3
  cmp ecx, byte 1
  je near .q1loop
  cmp ecx, byte 19
  jg near .lloop
  nop6

ALIGN 16
.loop
  movq mm1, [eax + 8*esi+112]   ; mm0 = [1st]
  psubw mm0, mm1                ;-mm1
  movq mm4, [eax + 8*esi + 120] ;
  psubw mm3, mm4                ;-mm4
  pmaxsw mm0, mm1               ;|src|
  pmaxsw mm3,mm4
  nop2
  psraw mm1, 15     ;sign src
  psraw mm4, 15
  psllw mm0, 4      ;level << 4 ;
  psllw mm3, 4
  paddw mm0, [intra_matrix1 + 8*esi+112]
  paddw mm3, [intra_matrix1 + 8*esi+120]
  movq mm5, [intra_matrix_fixl + 8*esi+112]
  movq mm7, [intra_matrix_fixl + 8*esi+120]
  pmulhuw mm5, mm0
  pmulhuw mm7, mm3
  mov esp, esp
  movq mm2, [intra_matrix + 8*esi+112]
  movq mm6, [intra_matrix + 8*esi+120]
  pmullw mm2, mm5
  pmullw mm6, mm7
  psubw mm0, mm2
  psubw mm3, mm6
  nop4
  movq mm2, [quantd + ecx * 8 - 8]
  movq mm6, [mmx_divs + ecx * 8 - 8]
  paddw mm5, mm2
  paddw mm7, mm2
  mov esp, esp
  pmulhuw mm0, [intra_matrix_fix + 8*esi+112]
  pmulhuw mm3, [intra_matrix_fix + 8*esi+120]
  paddw mm5, mm0
  paddw mm7, mm3
  movq mm0, [edi]
  movq mm3, [edi]
  pmulhuw mm5, mm6      ; mm0 = (mm0 / 2Q) >> 16
  pmulhuw mm7, mm6      ;  (level + quantd) / quant (0<quant<32)
  pxor mm5, mm1         ; mm0 *= sign(mm0)
  pxor mm7, mm4         ;
  psubw mm5, mm1        ; undisplace
  psubw mm7, mm4        ;
  movq [edx + 8*esi+112], mm5
  movq [edx + 8*esi +120], mm7
  add esi, byte 2
  jng near .loop

.done
; calculate  data[0] // (int32_t)dcscalar)
  mov esi, [esp + 12 + 16]  ; dcscalar
  movsx ecx, word [eax]
  mov edi, ecx
  mov edx, [esp + 12 + 16]
  shr edx, 1            ; ebx = dcscalar /2
  sar edi, 31           ; cdq is vectorpath
  xor edx, edi          ; ebx = eax V -eax -1
  sub ecx, edi
  add ecx, edx
  mov edx, [dword esp + 12 + 4]
  mov esi, [int_div+4*esi]
  imul ecx, esi
  sar ecx, 17
  lea ebx, [byte ecx + 1]
  cmovs ecx, ebx
  ; idiv    cx          ; ecx = edi:ecx / dcscalar

  mov ebx, [esp]
  mov edi, [esp+4]
  mov esi, [esp+8]
  add esp, byte 12
  mov [edx], cx     ; coeff[0] = ax

  xor eax, eax
  ret

ALIGN 16
.q1loop
  movq mm1, [eax + 8*esi+112]               ; mm0 = [1st]
  psubw mm0, mm1                            ;-mm1
  movq mm4, [eax + 8*esi+120]               ;
  psubw mm3, mm4                            ;-mm4
  pmaxsw mm0, mm1                           ;|src|
  pmaxsw mm3, mm4
  nop2
  psraw mm1, 15                             ;sign src
  psraw mm4, 15
  psllw mm0, 4                              ; level << 4
  psllw mm3, 4
  paddw mm0, [intra_matrix1 + 8*esi+112]    ;mm0 is to be divided
  paddw mm3, [intra_matrix1 + 8*esi+120]    ;intra1 contains fix for division by 1
  movq mm5, [intra_matrix_fixl + 8*esi+112] ;with rounding down
  movq mm7, [intra_matrix_fixl + 8*esi+120]
  pmulhuw mm5, mm0
  pmulhuw mm7, mm3      ;mm7: first approx of division
  mov esp, esp
  movq mm2, [intra_matrix + 8*esi+112]
  movq mm6, [intra_matrix + 8*esi+120]      ; divs for q<=16
  pmullw mm2, mm5       ;test value <= original
  pmullw mm6, mm7
  psubw mm0, mm2        ;mismatch
  psubw mm3, mm6
  nop4
  movq mm2, [quantd + ecx * 8 - 8]
  paddw mm5, mm2        ;first approx with quantd
  paddw mm7, mm2
  mov esp, esp
  pmulhuw mm0, [intra_matrix_fix + 8*esi+112]   ;correction
  pmulhuw mm3, [intra_matrix_fix + 8*esi+120]
  paddw mm5, mm0        ;final result with quantd
  paddw mm7, mm3
  movq mm0, [edi]
  movq mm3, [edi]
  mov esp, esp
  psrlw mm5, 1          ;  (level + quantd) /2  (quant = 1)
  psrlw mm7, 1
  pxor mm5, mm1         ; mm0 *= sign(mm0)
  pxor mm7, mm4         ;
  psubw mm5, mm1        ; undisplace
  psubw mm7, mm4        ;
  movq [edx + 8*esi+112], mm5
  movq [edx + 8*esi +120], mm7
  add esi, byte 2
  jng near .q1loop
  jmp near .done

ALIGN 8
.lloop
  movq mm1, [eax + 8*esi+112]       ; mm0 = [1st]
  psubw mm0, mm1        ;-mm1
  movq mm4, [eax + 8*esi+120]
  psubw mm3, mm4        ;-mm4
  pmaxsw mm0, mm1       ;|src|
  pmaxsw mm3, mm4
  nop2
  psraw mm1, 15         ;sign src
  psraw mm4, 15
  psllw mm0, 4          ; level << 4
  psllw mm3, 4          ;
  paddw mm0, [intra_matrix1 + 8*esi+112] ;mm0 is to be divided intra1 contains fix for division by 1
  paddw mm3, [intra_matrix1 + 8*esi+120]
  movq mm5, [intra_matrix_fixl + 8*esi+112]
  movq mm7, [intra_matrix_fixl + 8*esi+120]
  pmulhuw mm5, mm0
  pmulhuw mm7, mm3      ;mm7: first approx of division
  mov esp, esp
  movq mm2, [intra_matrix + 8*esi+112]
  movq mm6, [intra_matrix + 8*esi+120]
  pmullw mm2, mm5       ;test value <= original
  pmullw mm6, mm7
  psubw mm0, mm2        ;mismatch
  psubw mm3, mm6
  nop4
  movq mm2, [quantd + ecx * 8 - 8]
  movq mm6, [mmx_div + ecx * 8 - 8] ; divs for q<=16
  paddw mm5, mm2        ;first approx with quantd
  paddw mm7, mm2
  mov esp, esp
  pmulhuw mm0, [intra_matrix_fix + 8*esi+112] ;correction
  pmulhuw mm3, [intra_matrix_fix + 8*esi+120]
  paddw mm5, mm0        ;final result with quantd
  paddw mm7, mm3
  movq mm0, [edi]
  movq mm3, [edi]
  mov esp, esp
  pmulhuw mm5, mm6      ; mm0 = (mm0 / 2Q) >> 16
  pmulhuw mm7, mm6      ;  (level + quantd) / quant (0<quant<32)
  psrlw mm5, 1          ; (level + quantd) / (2*quant)
  psrlw mm7, 1
  pxor mm5, mm1         ; mm0 *= sign(mm0)
  pxor mm7, mm4         ;
  psubw mm5, mm1        ; undisplace
  psubw mm7, mm4        ;
  movq [edx + 8*esi+112], mm5
  movq [edx + 8*esi +120], mm7
  add esi,byte 2
  jng near .lloop
  jmp near .done

;-----------------------------------------------------------------------------
;
; uint32_t quant_mpeg_inter_xmm(int16_t * coeff,
;                               const int16_t const * data,
;                               const uint32_t quant);
;
;-----------------------------------------------------------------------------

ALIGN 16
quant_mpeg_inter_xmm:
  mov eax, [esp  + 8]       ; data
  mov ecx, [esp  + 12]      ; quant
  mov edx, [esp  + 4]       ; coeff
  push esi
  push edi
  push ebx
  nop
  mov edi, mmzero
  mov esi, -14
  mov ebx, esp
  sub esp, byte 24
  lea ebx, [esp+8]
  and ebx, byte -8 ;ALIGN 8
  pxor mm0, mm0
  pxor mm3, mm3
  movq [byte ebx],mm0
  db 0Fh, 7Fh, 44h, 23h, 8 ;movq [ebx+8],mm0
  cmp ecx, byte 1
  je near .q1loop
  cmp ecx, byte 19
  jg near .lloop
  nop

ALIGN 16
.loop
  movq mm1, [eax + 8*esi+112]       ; mm0 = [1st]
  psubw mm0, mm1 ;-mm1
  movq mm4, [eax + 8*esi + 120] ;
  psubw mm3, mm4 ;-mm4
  pmaxsw mm0, mm1 ;|src|
  pmaxsw mm3, mm4
  nop2
  psraw mm1, 15         ;sign src
  psraw mm4, 15
  psllw mm0, 4          ; level << 4
  psllw mm3, 4          ;
  paddw mm0, [inter_matrix1 + 8*esi+112]
  paddw mm3, [inter_matrix1 + 8*esi+120]
  movq mm5, [inter_matrix_fixl + 8*esi+112]
  movq mm7, [inter_matrix_fixl + 8*esi+120]
  pmulhuw mm5, mm0
  pmulhuw mm7, mm3
  mov esp, esp
  movq mm2, [inter_matrix + 8*esi+112]
  movq mm6, [inter_matrix + 8*esi+120]
  pmullw mm2, mm5
  pmullw mm6, mm7
  psubw mm0, mm2
  psubw mm3, mm6
  movq mm2, [byte ebx]
  movq mm6, [mmx_divs + ecx * 8 - 8]
  pmulhuw mm0, [inter_matrix_fix + 8*esi+112]
  pmulhuw mm3, [inter_matrix_fix + 8*esi+120]
  paddw mm2, [ebx+8]    ;sum
  paddw mm5, mm0
  paddw mm7, mm3
  movq mm0, [edi]
  movq mm3, [edi]
  pmulhuw mm5, mm6      ; mm0 = (mm0 / 2Q) >> 16
  pmulhuw mm7, mm6      ;  (level ) / quant (0<quant<32)
  add esi, byte 2
  paddw mm2, mm5        ;sum += x1
  movq [ebx], mm7       ;store x2
  pxor mm5, mm1         ; mm0 *= sign(mm0)
  pxor mm7, mm4         ;
  psubw mm5, mm1        ; undisplace
  psubw mm7, mm4        ;
  db 0Fh, 7Fh, 54h, 23h, 08 ;movq   [ebx+8],mm2 ;store sum
  movq [edx + 8*esi+112-16], mm5
  movq [edx + 8*esi +120-16], mm7
  jng near .loop

.done
; calculate  data[0] // (int32_t)dcscalar)
  paddw mm2, [ebx]
  mov ebx, [esp+24]
  mov edi, [esp+4+24]
  mov esi, [esp+8+24]
  add esp, byte 12+24
  pmaddwd mm2, [mmx_one]
  punpckldq mm0, mm2 ;get low dw to mm0:high
  paddd mm0,mm2
  punpckhdq mm0, mm0 ;get result to low
  movd eax, mm0

  ret

ALIGN 16
.q1loop
  movq mm1, [eax + 8*esi+112]       ; mm0 = [1st]
  psubw mm0, mm1                    ;-mm1
  movq mm4, [eax + 8*esi+120]
  psubw mm3, mm4                    ;-mm4
  pmaxsw mm0, mm1                   ;|src|
  pmaxsw mm3, mm4
  nop2
  psraw mm1, 15                             ; sign src
  psraw mm4, 15
  psllw mm0, 4                              ; level << 4
  psllw mm3, 4
  paddw mm0, [inter_matrix1 + 8*esi+112]    ;mm0 is to be divided
  paddw mm3, [inter_matrix1 + 8*esi+120]    ; inter1 contains fix for division by 1
  movq mm5, [inter_matrix_fixl + 8*esi+112] ;with rounding down
  movq mm7, [inter_matrix_fixl + 8*esi+120]
  pmulhuw mm5, mm0
  pmulhuw mm7, mm3                          ;mm7: first approx of division
  mov esp, esp
  movq mm2, [inter_matrix + 8*esi+112]
  movq mm6, [inter_matrix + 8*esi+120]      ; divs for q<=16
  pmullw mm2, mm5                           ;test value <= original
  pmullw mm6, mm7
  psubw mm0, mm2                            ;mismatch
  psubw mm3, mm6
  movq mm2, [byte ebx]
  pmulhuw mm0, [inter_matrix_fix + 8*esi+112]  ;correction
  pmulhuw mm3, [inter_matrix_fix + 8*esi+120]
  paddw mm2, [ebx+8]    ;sum
  paddw mm5, mm0        ;final result
  paddw mm7, mm3
  movq mm0, [edi]
  movq mm3, [edi]
  psrlw mm5, 1          ;  (level ) /2  (quant = 1)
  psrlw mm7, 1
  add esi, byte 2
  paddw mm2, mm5        ;sum += x1
  movq [ebx], mm7       ;store x2
  pxor mm5, mm1         ; mm0 *= sign(mm0)
  pxor mm7, mm4         ;
  psubw mm5, mm1        ; undisplace
  psubw mm7, mm4        ;
  movq [ebx+8], mm2     ;store sum
  movq [edx + 8*esi+112-16], mm5
  movq [edx + 8*esi +120-16], mm7
  jng near .q1loop
  jmp near .done

ALIGN 8
.lloop
  movq mm1, [eax + 8*esi+112]       ; mm0 = [1st]
  psubw mm0,mm1         ;-mm1
  movq mm4, [eax + 8*esi+120]
  psubw mm3,mm4         ;-mm4
  pmaxsw mm0,mm1        ;|src|
  pmaxsw mm3,mm4
  nop2
  psraw mm1,15          ;sign src
  psraw mm4,15
  psllw mm0, 4          ; level << 4
  psllw mm3, 4          ;
  paddw mm0, [inter_matrix1 + 8*esi+112] ;mm0 is to be divided inter1 contains fix for division by 1
  paddw mm3, [inter_matrix1 + 8*esi+120]
  movq mm5,[inter_matrix_fixl + 8*esi+112]
  movq mm7,[inter_matrix_fixl + 8*esi+120]
  pmulhuw mm5,mm0
  pmulhuw mm7,mm3       ;mm7: first approx of division
  mov esp,esp
  movq mm2,[inter_matrix + 8*esi+112]
  movq mm6,[inter_matrix + 8*esi+120]
  pmullw mm2,mm5        ;test value <= original
  pmullw mm6,mm7
  psubw mm0,mm2         ;mismatch
  psubw mm3,mm6
  movq mm2,[byte ebx]
  movq mm6,[mmx_div + ecx * 8 - 8]  ; divs for q<=16
  pmulhuw mm0,[inter_matrix_fix + 8*esi+112] ;correction
  pmulhuw mm3,[inter_matrix_fix + 8*esi+120]
  paddw mm2,[ebx+8]     ;sum
  paddw mm5,mm0         ;final result
  paddw mm7,mm3
  movq mm0,[edi]
  movq mm3,[edi]
  pmulhuw mm5, mm6      ; mm0 = (mm0 / 2Q) >> 16
  pmulhuw mm7, mm6      ;  (level ) / quant (0<quant<32)
  add esi,byte 2
  psrlw mm5, 1          ; (level ) / (2*quant)
  paddw mm2,mm5         ;sum += x1
  psrlw mm7, 1
  movq [ebx],mm7        ;store x2
  pxor mm5, mm1         ; mm0 *= sign(mm0)
  pxor mm7, mm4         ;
  psubw mm5, mm1        ; undisplace
  psubw mm7, mm4        ;
  db 0Fh, 7Fh, 54h, 23h, 08 ;movq   [ebx+8],mm2 ;store sum
  movq [edx + 8*esi+112-16], mm5
  movq [edx + 8*esi +120-16], mm7
  jng near .lloop
  jmp near .done


;-----------------------------------------------------------------------------
;
; uint32_t dequant_mpeg_intra_3dne(int16_t *data,
;                                  const int16_t const *coeff,
;                                  const uint32_t quant,
;                                  const uint32_t dcscalar);
;
;-----------------------------------------------------------------------------

  ;   Note: in order to saturate 'easily', we pre-shift the quantifier
  ; by 4. Then, the high-word of (coeff[]*matrix[i]*quant) are used to
  ; build a saturating mask. It is non-zero only when an overflow occured.
  ; We thus avoid packing/unpacking toward double-word.
  ; Moreover, we perform the mult (matrix[i]*quant) first, instead of, e.g.,
  ; (coeff[i]*matrix[i]). This is less prone to overflow if coeff[] are not
  ; checked. Input ranges are: coeff in [-127,127], inter_matrix in [1..255],a
  ; and quant in [1..31].
  ;

%macro DEQUANT4INTRAMMX 1
  movq mm1, [byte ecx+ 16 * %1] ; mm0 = c  = coeff[i]
  movq mm4, [ecx+ 16 * %1 +8]   ; mm3 = c' = coeff[i+1]
  psubw mm0, mm1
  psubw mm3, mm4
  pmaxsw mm0, mm1
  pmaxsw mm3, mm4
  psraw mm1, 15
  psraw mm4, 15
%if %1
  movq mm2, [eax+8] ;preshifted quant
  movq mm7, [eax+8]
%endif
  pmullw mm2, [intra_matrix + 16 * %1 ]     ; matrix[i]*quant
  pmullw mm7, [intra_matrix + 16 * %1 +8]   ; matrix[i+1]*quant
  movq mm5, mm0
  movq mm6, mm3
  pmulhw mm0, mm2   ; high of coeff*(matrix*quant)
  pmulhw mm3, mm7   ; high of coeff*(matrix*quant)
  pmullw mm2, mm5   ; low  of coeff*(matrix*quant)
  pmullw mm7, mm6   ; low  of coeff*(matrix*quant)
  pcmpgtw mm0, [eax]
  pcmpgtw mm3, [eax]
  paddusw mm2, mm0
  paddusw mm7, mm3
  psrlw mm2, 5
  psrlw mm7, 5
  pxor mm2, mm1     ; start negating back
  pxor mm7, mm4     ; start negating back
  psubusw mm1, mm0
  psubusw mm4, mm3
  movq mm0, [eax]   ;zero
  movq mm3, [eax]   ;zero
  psubw mm2, mm1    ; finish negating back
  psubw mm7, mm4    ; finish negating back
  movq [byte edx + 16 * %1], mm2   ; data[i]
  movq [edx + 16 * %1  +8], mm7   ; data[i+1]
%endmacro

ALIGN 16
dequant_mpeg_intra_3dne:
  mov eax, [esp+12] ; quant
  mov ecx, [esp+8]  ; coeff
  movq mm7, [mmx_mul_quant  + eax*8 - 8]
  psllw mm7, 2      ; << 2. See comment.
  mov edx, [esp+4]  ; data
  push ebx
  movsx ebx, word [ecx]
  pxor mm0, mm0
  pxor mm3, mm3
  push esi
  lea eax, [esp-28]
  sub esp, byte 32
  and eax, byte -8  ;points to qword ALIGNed space on stack
  movq [eax], mm0
  movq [eax+8], mm7
  imul ebx, [esp+16+8+32]    ; dcscalar
  movq mm2, mm7

ALIGN 4

  DEQUANT4INTRAMMX 0

  mov esi, -2048
  nop
  cmp ebx, esi

  DEQUANT4INTRAMMX 1

  cmovl ebx, esi
  neg esi
  sub esi, byte 1 ;2047

  DEQUANT4INTRAMMX 2

  cmp ebx, esi
  cmovg ebx, esi
  lea ebp, [byte ebp]

  DEQUANT4INTRAMMX 3

  mov esi, [esp+32]
  mov [byte edx], bx
  mov ebx, [esp+32+4]

  DEQUANT4INTRAMMX 4
  DEQUANT4INTRAMMX 5
  DEQUANT4INTRAMMX 6
  DEQUANT4INTRAMMX 7

  add esp, byte 32+8

  xor eax, eax
  ret

;-----------------------------------------------------------------------------
;
; uint32_t dequant_mpeg_inter_3dne(int16_t * data,
;                                  const int16_t * const coeff,
;                                  const uint32_t quant);
;
;-----------------------------------------------------------------------------

    ; Note:  We use (2*c + sgn(c) - sgn(-c)) as multiplier
    ; so we handle the 3 cases: c<0, c==0, and c>0 in one shot.
    ; sgn(x) is the result of 'pcmpgtw 0,x':  0 if x>=0, -1 if x<0.
    ; It's mixed with the extraction of the absolute value.

ALIGN 16
dequant_mpeg_inter_3dne:
  mov edx, [esp+ 4]        ; data
  mov ecx, [esp+ 8]        ; coeff
  mov eax, [esp+12]        ; quant
  movq mm7, [mmx_mul_quant  + eax*8 - 8]
  mov eax, -14
  paddw mm7, mm7    ; << 1
  pxor mm6, mm6     ; mismatch sum
  push esi
  mov esi, mmzero
  pxor mm1, mm1
  pxor mm3, mm3
  nop
  nop4

ALIGN 16
.loop
  movq mm0, [ecx+8*eax + 7*16   ]   ; mm0 = coeff[i]
  pcmpgtw mm1, mm0  ; mm1 = sgn(c)    (preserved)
  movq mm2, [ecx+8*eax + 7*16 +8]   ; mm2 = coeff[i+1]
  pcmpgtw mm3, mm2  ; mm3 = sgn(c')   (preserved)
  paddsw mm0, mm1   ; c += sgn(c)
  paddsw mm2, mm3   ; c += sgn(c')
  paddw mm0, mm0    ; c *= 2
  paddw mm2, mm2    ; c'*= 2

  movq mm4, [esi]
  movq mm5, [esi]
  psubw mm4, mm0    ; -c
  psubw mm5, mm2    ; -c'

  psraw mm4, 16     ; mm4 = sgn(-c)
  psraw mm5, 16     ; mm5 = sgn(-c')
  psubsw mm0, mm4   ; c  -= sgn(-c)
  psubsw mm2, mm5   ; c' -= sgn(-c')
  pxor mm0, mm1     ; finish changing sign if needed
  pxor mm2, mm3     ; finish changing sign if needed

 ; we're short on register, here. Poor pairing...

  movq mm4, mm7     ; (matrix*quant)
  nop
  pmullw mm4, [inter_matrix + 8*eax + 7*16]
  movq mm5, mm4
  pmulhw mm5, mm0   ; high of c*(matrix*quant)
  pmullw mm0, mm4   ; low  of c*(matrix*quant)

  movq mm4, mm7     ; (matrix*quant)
  pmullw mm4, [inter_matrix + 8*eax + 7*16 + 8]
  add eax, byte 2

  pcmpgtw mm5, [esi]
  paddusw mm0, mm5
  psrlw mm0, 5
  pxor mm0, mm1     ; start restoring sign
  psubusw mm1, mm5

  movq mm5, mm4
  pmulhw mm5, mm2   ; high of c*(matrix*quant)
  pmullw mm2, mm4   ; low  of c*(matrix*quant)
  psubw mm0, mm1    ; finish restoring sign

  pcmpgtw mm5, [esi]
  paddusw mm2, mm5
  psrlw mm2, 5
  pxor mm2, mm3     ; start restoring sign
  psubusw mm3, mm5
  psubw mm2, mm3    ; finish restoring sign
  movq mm1, [esi]
  movq mm3, [byte esi]
  pxor mm6, mm0                             ; mismatch control
  movq [edx + 8*eax + 7*16 -2*8   ], mm0    ; data[i]
  pxor mm6, mm2                             ; mismatch control
  movq [edx + 8*eax + 7*16 -2*8 +8], mm2    ; data[i+1]

  jng .loop
  nop

 ; mismatch control

  pshufw mm0, mm6, 01010101b
  pshufw mm1, mm6, 10101010b
  pshufw mm2, mm6, 11111111b
  pxor mm6, mm0
  pxor mm1, mm2
  pxor mm6, mm1
  movd eax, mm6
  and eax, byte 1
  xor eax, byte 1
  mov esi, [esp]
  add esp, byte 4
  xor word [edx + 2*63], ax

  xor eax, eax
  ret

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