ref: ae12fbde1cae1e9e3b3957350412e69d58903365
parent: ca61e286b4ef4513671ac0f8171fd6d59380d857
author: zhiliang wang <zhilwang@cisco.com>
date: Tue Jul 8 15:25:31 EDT 2014
Add x86 64bit asm code for downsample
--- a/codec/processing/src/downsample/downsample.cpp
+++ b/codec/processing/src/downsample/downsample.cpp
@@ -57,21 +57,21 @@
sDownsampleFunc.pfGeneralRatioLuma = GeneralBilinearFastDownsampler_c;
#if defined(X86_ASM)
if (iCpuFlag & WELS_CPU_SSE) {
- /* sDownsampleFunc.pfHalfAverage[0] = DyadicBilinearDownsamplerWidthx32_sse;
- sDownsampleFunc.pfHalfAverage[1] = DyadicBilinearDownsamplerWidthx16_sse;
- sDownsampleFunc.pfHalfAverage[2] = DyadicBilinearDownsamplerWidthx8_sse;*/
+ sDownsampleFunc.pfHalfAverage[0] = DyadicBilinearDownsamplerWidthx32_sse;
+ sDownsampleFunc.pfHalfAverage[1] = DyadicBilinearDownsamplerWidthx16_sse;
+ sDownsampleFunc.pfHalfAverage[2] = DyadicBilinearDownsamplerWidthx8_sse;
}
if (iCpuFlag & WELS_CPU_SSE2) {
- // sDownsampleFunc.pfGeneralRatioChroma = GeneralBilinearAccurateDownsamplerWrap_sse2;
- // sDownsampleFunc.pfGeneralRatioLuma = GeneralBilinearFastDownsamplerWrap_sse2;
+ sDownsampleFunc.pfGeneralRatioChroma = GeneralBilinearAccurateDownsamplerWrap_sse2;
+ sDownsampleFunc.pfGeneralRatioLuma = GeneralBilinearFastDownsamplerWrap_sse2;
}
if (iCpuFlag & WELS_CPU_SSSE3) {
- // sDownsampleFunc.pfHalfAverage[0] = DyadicBilinearDownsamplerWidthx32_ssse3;
- // sDownsampleFunc.pfHalfAverage[1] = DyadicBilinearDownsamplerWidthx16_ssse3;
+ sDownsampleFunc.pfHalfAverage[0] = DyadicBilinearDownsamplerWidthx32_ssse3;
+ sDownsampleFunc.pfHalfAverage[1] = DyadicBilinearDownsamplerWidthx16_ssse3;
}
if (iCpuFlag & WELS_CPU_SSE41) {
- // sDownsampleFunc.pfHalfAverage[0] = DyadicBilinearDownsamplerWidthx32_sse4;
- // sDownsampleFunc.pfHalfAverage[1] = DyadicBilinearDownsamplerWidthx16_sse4;
+ sDownsampleFunc.pfHalfAverage[0] = DyadicBilinearDownsamplerWidthx32_sse4;
+ sDownsampleFunc.pfHalfAverage[1] = DyadicBilinearDownsamplerWidthx16_sse4;
}
#endif//X86_ASM
--- a/codec/processing/src/downsample/downsamplefuncs.cpp
+++ b/codec/processing/src/downsample/downsamplefuncs.cpp
@@ -202,31 +202,31 @@
#ifdef X86_ASM
-//void GeneralBilinearFastDownsamplerWrap_sse2 (uint8_t* pDst, const int32_t kiDstStride, const int32_t kiDstWidth,
-// const int32_t kiDstHeight,
-// uint8_t* pSrc, const int32_t kiSrcStride, const int32_t kiSrcWidth, const int32_t kiSrcHeight) {
-// const int32_t kiScaleBitWidth = 16, kiScaleBitHeight = 15;
-// const uint32_t kuiScaleWidth = (1 << kiScaleBitWidth), kuiScaleHeight = (1 << kiScaleBitHeight);
-//
-// uint32_t uiScalex = WELS_ROUND ((float)kiSrcWidth / (float)kiDstWidth * kuiScaleWidth);
-// uint32_t uiScaley = WELS_ROUND ((float)kiSrcHeight / (float)kiDstHeight * kuiScaleHeight);
-//
-// GeneralBilinearFastDownsampler_sse2 (pDst, kiDstStride, kiDstWidth, kiDstHeight,
-// pSrc, kiSrcStride, kiSrcWidth, kiSrcHeight, uiScalex, uiScaley);
-//}
-//
-//void GeneralBilinearAccurateDownsamplerWrap_sse2 (uint8_t* pDst, const int32_t kiDstStride, const int32_t kiDstWidth,
-// const int32_t kiDstHeight,
-// uint8_t* pSrc, const int32_t kiSrcStride, const int32_t kiSrcWidth, const int32_t kiSrcHeight) {
-// const int32_t kiScaleBit = 15;
-// const uint32_t kuiScale = (1 << kiScaleBit);
-//
-// uint32_t uiScalex = WELS_ROUND ((float)kiSrcWidth / (float)kiDstWidth * kuiScale);
-// uint32_t uiScaley = WELS_ROUND ((float)kiSrcHeight / (float)kiDstHeight * kuiScale);
-//
-// GeneralBilinearAccurateDownsampler_sse2 (pDst, kiDstStride, kiDstWidth, kiDstHeight,
-// pSrc, kiSrcStride, kiSrcWidth, kiSrcHeight, uiScalex, uiScaley);
-//}
+void GeneralBilinearFastDownsamplerWrap_sse2 (uint8_t* pDst, const int32_t kiDstStride, const int32_t kiDstWidth,
+ const int32_t kiDstHeight,
+ uint8_t* pSrc, const int32_t kiSrcStride, const int32_t kiSrcWidth, const int32_t kiSrcHeight) {
+ const int32_t kiScaleBitWidth = 16, kiScaleBitHeight = 15;
+ const uint32_t kuiScaleWidth = (1 << kiScaleBitWidth), kuiScaleHeight = (1 << kiScaleBitHeight);
+
+ uint32_t uiScalex = WELS_ROUND ((float)kiSrcWidth / (float)kiDstWidth * kuiScaleWidth);
+ uint32_t uiScaley = WELS_ROUND ((float)kiSrcHeight / (float)kiDstHeight * kuiScaleHeight);
+
+ GeneralBilinearFastDownsampler_sse2 (pDst, kiDstStride, kiDstWidth, kiDstHeight,
+ pSrc, kiSrcStride, kiSrcWidth, kiSrcHeight, uiScalex, uiScaley);
+}
+
+void GeneralBilinearAccurateDownsamplerWrap_sse2 (uint8_t* pDst, const int32_t kiDstStride, const int32_t kiDstWidth,
+ const int32_t kiDstHeight,
+ uint8_t* pSrc, const int32_t kiSrcStride, const int32_t kiSrcWidth, const int32_t kiSrcHeight) {
+ const int32_t kiScaleBit = 15;
+ const uint32_t kuiScale = (1 << kiScaleBit);
+
+ uint32_t uiScalex = WELS_ROUND ((float)kiSrcWidth / (float)kiDstWidth * kuiScale);
+ uint32_t uiScaley = WELS_ROUND ((float)kiSrcHeight / (float)kiDstHeight * kuiScale);
+
+ GeneralBilinearAccurateDownsampler_sse2 (pDst, kiDstStride, kiDstWidth, kiDstHeight,
+ pSrc, kiSrcStride, kiSrcWidth, kiSrcHeight, uiScalex, uiScaley);
+}
#endif //X86_ASM
#ifdef HAVE_NEON
--- a/codec/processing/src/x86/downsample_bilinear.asm
+++ b/codec/processing/src/x86/downsample_bilinear.asm
@@ -39,7 +39,7 @@
;*
;*************************************************************************/
%include "asm_inc.asm"
-%ifdef X86_32
+
;***********************************************************************
; Macros and other preprocessor constants
;***********************************************************************
@@ -64,6 +64,8 @@
db 00h, 80h, 02h, 80h, 04h, 80h, 06h, 80h, 08h, 80h, 0ah, 80h, 0ch, 80h, 0eh, 80h
shufb_mask_high:
db 01h, 80h, 03h, 80h, 05h, 80h, 07h, 80h, 09h, 80h, 0bh, 80h, 0dh, 80h, 0fh, 80h
+add_extra_half:
+ dd 16384,0,0,0
;***********************************************************************
@@ -78,28 +80,36 @@
; const int iSrcWidth, const int iSrcHeight );
;***********************************************************************
WELS_EXTERN DyadicBilinearDownsamplerWidthx32_sse
- push ebx
- push edx
- push esi
- push edi
- push ebp
+%ifdef X86_32
+ push r6
+ %assign push_num 1
+%else
+ %assign push_num 0
+%endif
+ LOAD_6_PARA
+ SIGN_EXTENSION r1, r1d
+ SIGN_EXTENSION r3, r3d
+ SIGN_EXTENSION r4, r4d
+ SIGN_EXTENSION r5, r5d
- mov edi, [esp+24] ; pDst
- mov edx, [esp+28] ; iDstStride
- mov esi, [esp+32] ; pSrc
- mov ecx, [esp+36] ; iSrcStride
- mov ebp, [esp+44] ; iSrcHeight
+%ifndef X86_32
+ push r12
+ mov r12, r4
+%endif
+ sar r5, $01 ; iSrcHeight >> 1
- sar ebp, $01 ; iSrcHeight >> 1
-
-.yloops:
- mov eax, [esp+40] ; iSrcWidth
- sar eax, $01 ; iSrcWidth >> 1
- mov ebx, eax ; iDstWidth restored at ebx
- sar eax, $04 ; (iSrcWidth >> 1) / 16 ; loop count = num_of_mb
- neg ebx ; - (iSrcWidth >> 1)
+.yloops1:
+%ifdef X86_32
+ mov r4, arg5
+%else
+ mov r4, r12
+%endif
+ sar r4, $01 ; iSrcWidth >> 1
+ mov r6, r4 ; iDstWidth restored at ebx
+ sar r4, $04 ; (iSrcWidth >> 1) / 16 ; loop count = num_of_mb
+ neg r6 ; - (iSrcWidth >> 1)
; each loop = source bandwidth: 32 bytes
-.xloops:
+.xloops1:
; 1st part horizonal loop: x16 bytes
; mem hi<- ->lo
;1st Line Src: mm0: d D c C b B a A mm1: h H g G f F e E
@@ -108,10 +118,10 @@
;: H G F E D C B A, P O N M L K J I
;: h g f e d c b a, p o n m l k j i
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- movq mm0, [esi] ; 1st pSrc line
- movq mm1, [esi+8] ; 1st pSrc line + 8
- movq mm2, [esi+ecx] ; 2nd pSrc line
- movq mm3, [esi+ecx+8] ; 2nd pSrc line + 8
+ movq mm0, [r2] ; 1st pSrc line
+ movq mm1, [r2+8] ; 1st pSrc line + 8
+ movq mm2, [r2+r3] ; 2nd pSrc line
+ movq mm3, [r2+r3+8] ; 2nd pSrc line + 8
; to handle mm0, mm1, mm2, mm3
pshufw mm4, mm0, 0d8h ; d D b B c C a A ; 11011000 B
@@ -156,10 +166,10 @@
;: H G F E D C B A, P O N M L K J I
;: h g f e d c b a, p o n m l k j i
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- movq mm1, [esi+16] ; 1st pSrc line + 16
- movq mm2, [esi+24] ; 1st pSrc line + 24
- movq mm3, [esi+ecx+16] ; 2nd pSrc line + 16
- movq mm4, [esi+ecx+24] ; 2nd pSrc line + 24
+ movq mm1, [r2+16] ; 1st pSrc line + 16
+ movq mm2, [r2+24] ; 1st pSrc line + 24
+ movq mm3, [r2+r3+16] ; 2nd pSrc line + 16
+ movq mm4, [r2+r3+24] ; 2nd pSrc line + 24
; to handle mm1, mm2, mm3, mm4
pshufw mm5, mm1, 0d8h ; d D b B c C a A ; 11011000 B
@@ -196,31 +206,33 @@
pavgb mm3, mm7 ; (I+i+1)>>1, .., (P+p+1)>>1, temp_row2
pavgb mm2, mm3 ; (temp_row1+temp_row2+1)>>1, done in another 2nd horizonal part
- movq [edi ], mm0
- movq [edi+8], mm2
+ movq [r0 ], mm0
+ movq [r0+8], mm2
; next SMB
- lea esi, [esi+32]
- lea edi, [edi+16]
+ lea r2, [r2+32]
+ lea r0, [r0+16]
- dec eax
- jg near .xloops
+ dec r4
+ jg near .xloops1
; next line
- lea esi, [esi+2*ecx] ; next end of lines
- lea esi, [esi+2*ebx] ; reset to base 0 [- 2 * iDstWidth]
- lea edi, [edi+edx]
- lea edi, [edi+ebx] ; reset to base 0 [- iDstWidth]
+ lea r2, [r2+2*r3] ; next end of lines
+ lea r2, [r2+2*r6] ; reset to base 0 [- 2 * iDstWidth]
+ lea r0, [r0+r1]
+ lea r0, [r0+r6] ; reset to base 0 [- iDstWidth]
- dec ebp
- jg near .yloops
+ dec r5
+ jg near .yloops1
WELSEMMS
- pop ebp
- pop edi
- pop esi
- pop edx
- pop ebx
+%ifndef X86_32
+ pop r12
+%endif
+ LOAD_6_PARA_POP
+%ifdef X86_32
+ pop r6
+%endif
ret
;***********************************************************************
@@ -229,28 +241,36 @@
; const int iSrcWidth, const int iSrcHeight );
;***********************************************************************
WELS_EXTERN DyadicBilinearDownsamplerWidthx16_sse
- push ebx
- push edx
- push esi
- push edi
- push ebp
+%ifdef X86_32
+ push r6
+ %assign push_num 1
+%else
+ %assign push_num 0
+%endif
+ LOAD_6_PARA
+ SIGN_EXTENSION r1, r1d
+ SIGN_EXTENSION r3, r3d
+ SIGN_EXTENSION r4, r4d
+ SIGN_EXTENSION r5, r5d
- mov edi, [esp+24] ; pDst
- mov edx, [esp+28] ; iDstStride
- mov esi, [esp+32] ; pSrc
- mov ecx, [esp+36] ; iSrcStride
- mov ebp, [esp+44] ; iSrcHeight
+%ifndef X86_32
+ push r12
+ mov r12, r4
+%endif
+ sar r5, $01 ; iSrcHeight >> 1
- sar ebp, $01 ; iSrcHeight >> 1
-
-.yloops:
- mov eax, [esp+40] ; iSrcWidth
- sar eax, $01 ; iSrcWidth >> 1
- mov ebx, eax ; iDstWidth restored at ebx
- sar eax, $03 ; (iSrcWidth >> 1) / 8 ; loop count = num_of_mb
- neg ebx ; - (iSrcWidth >> 1)
+.yloops2:
+%ifdef X86_32
+ mov r4, arg5
+%else
+ mov r4, r12
+%endif
+ sar r4, $01 ; iSrcWidth >> 1
+ mov r6, r4 ; iDstWidth restored at ebx
+ sar r4, $03 ; (iSrcWidth >> 1) / 8 ; loop count = num_of_mb
+ neg r6 ; - (iSrcWidth >> 1)
; each loop = source bandwidth: 16 bytes
-.xloops:
+.xloops2:
; 1st part horizonal loop: x16 bytes
; mem hi<- ->lo
;1st Line Src: mm0: d D c C b B a A mm1: h H g G f F e E
@@ -259,10 +279,10 @@
;: H G F E D C B A, P O N M L K J I
;: h g f e d c b a, p o n m l k j i
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- movq mm0, [esi] ; 1st pSrc line
- movq mm1, [esi+8] ; 1st pSrc line + 8
- movq mm2, [esi+ecx] ; 2nd pSrc line
- movq mm3, [esi+ecx+8] ; 2nd pSrc line + 8
+ movq mm0, [r2] ; 1st pSrc line
+ movq mm1, [r2+8] ; 1st pSrc line + 8
+ movq mm2, [r2+r3] ; 2nd pSrc line
+ movq mm3, [r2+r3+8] ; 2nd pSrc line + 8
; to handle mm0, mm1, mm2, mm3
pshufw mm4, mm0, 0d8h ; d D b B c C a A ; 11011000 B
@@ -299,30 +319,32 @@
pavgb mm1, mm6 ; (I+i+1)>>1, .., (P+p+1)>>1, temp_row2
pavgb mm0, mm1 ; (temp_row1+temp_row2+1)>>1, pending here and wait another horizonal part done then write memory once
- movq [edi ], mm0
+ movq [r0 ], mm0
; next SMB
- lea esi, [esi+16]
- lea edi, [edi+8]
+ lea r2, [r2+16]
+ lea r0, [r0+8]
- dec eax
- jg near .xloops
+ dec r4
+ jg near .xloops2
; next line
- lea esi, [esi+2*ecx] ; next end of lines
- lea esi, [esi+2*ebx] ; reset to base 0 [- 2 * iDstWidth]
- lea edi, [edi+edx]
- lea edi, [edi+ebx] ; reset to base 0 [- iDstWidth]
+ lea r2, [r2+2*r3] ; next end of lines
+ lea r2, [r2+2*r6] ; reset to base 0 [- 2 * iDstWidth]
+ lea r0, [r0+r1]
+ lea r0, [r0+r6] ; reset to base 0 [- iDstWidth]
- dec ebp
- jg near .yloops
+ dec r5
+ jg near .yloops2
WELSEMMS
- pop ebp
- pop edi
- pop esi
- pop edx
- pop ebx
+%ifndef X86_32
+ pop r12
+%endif
+ LOAD_6_PARA_POP
+%ifdef X86_32
+ pop r6
+%endif
ret
;***********************************************************************
@@ -331,28 +353,36 @@
; const int iSrcWidth, const int iSrcHeight );
;***********************************************************************
WELS_EXTERN DyadicBilinearDownsamplerWidthx8_sse
- push ebx
- push edx
- push esi
- push edi
- push ebp
+%ifdef X86_32
+ push r6
+ %assign push_num 1
+%else
+ %assign push_num 0
+%endif
+ LOAD_6_PARA
+ SIGN_EXTENSION r1, r1d
+ SIGN_EXTENSION r3, r3d
+ SIGN_EXTENSION r4, r4d
+ SIGN_EXTENSION r5, r5d
- mov edi, [esp+24] ; pDst
- mov edx, [esp+28] ; iDstStride
- mov esi, [esp+32] ; pSrc
- mov ecx, [esp+36] ; iSrcStride
- mov ebp, [esp+44] ; iSrcHeight
+%ifndef X86_32
+ push r12
+ mov r12, r4
+%endif
+ sar r5, $01 ; iSrcHeight >> 1
- sar ebp, $01 ; iSrcHeight >> 1
-
-.yloops:
- mov eax, [esp+40] ; iSrcWidth
- sar eax, $01 ; iSrcWidth >> 1
- mov ebx, eax ; iDstWidth restored at ebx
- sar eax, $02 ; (iSrcWidth >> 1) / 4 ; loop count = num_of_mb
- neg ebx ; - (iSrcWidth >> 1)
+.yloops3:
+%ifdef X86_32
+ mov r4, arg5
+%else
+ mov r4, r12
+%endif
+ sar r4, $01 ; iSrcWidth >> 1
+ mov r6, r4 ; iDstWidth restored at ebx
+ sar r4, $02 ; (iSrcWidth >> 1) / 4 ; loop count = num_of_mb
+ neg r6 ; - (iSrcWidth >> 1)
; each loop = source bandwidth: 8 bytes
-.xloops:
+.xloops3:
; 1st part horizonal loop: x8 bytes
; mem hi<- ->lo
;1st Line Src: mm0: d D c C b B a A
@@ -361,8 +391,8 @@
;: H G F E D C B A
;: h g f e d c b a
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- movq mm0, [esi] ; 1st pSrc line
- movq mm1, [esi+ecx] ; 2nd pSrc line
+ movq mm0, [r2] ; 1st pSrc line
+ movq mm1, [r2+r3] ; 2nd pSrc line
; to handle mm0, mm1, mm2, mm3
pshufw mm2, mm0, 0d8h ; d D b B c C a A ; 11011000 B
@@ -385,30 +415,32 @@
pshufw mm1, mm0, 04eh ; 01001110 B
pavgb mm0, mm1 ; (temp_row1+temp_row2+1)>>1, pending here and wait another horizonal part done then write memory once
- movd [edi], mm0
+ movd [r0], mm0
; next unit
- lea esi, [esi+8]
- lea edi, [edi+4]
+ lea r2, [r2+8]
+ lea r0, [r0+4]
- dec eax
- jg near .xloops
+ dec r4
+ jg near .xloops3
; next line
- lea esi, [esi+2*ecx] ; next end of lines
- lea esi, [esi+2*ebx] ; reset to base 0 [- 2 * iDstWidth]
- lea edi, [edi+edx]
- lea edi, [edi+ebx] ; reset to base 0 [- iDstWidth]
+ lea r2, [r2+2*r3] ; next end of lines
+ lea r2, [r2+2*r6] ; reset to base 0 [- 2 * iDstWidth]
+ lea r0, [r0+r1]
+ lea r0, [r0+r6] ; reset to base 0 [- iDstWidth]
- dec ebp
- jg near .yloops
+ dec r5
+ jg near .yloops3
WELSEMMS
- pop ebp
- pop edi
- pop esi
- pop edx
- pop ebx
+%ifndef X86_32
+ pop r12
+%endif
+ LOAD_6_PARA_POP
+%ifdef X86_32
+ pop r6
+%endif
ret
@@ -420,31 +452,56 @@
; const int iSrcWidth, const int iSrcHeight );
;***********************************************************************
WELS_EXTERN DyadicBilinearDownsamplerWidthx32_ssse3
- push ebx
- push edx
- push esi
- push edi
- push ebp
+ ;push ebx
+ ;push edx
+ ;push esi
+ ;push edi
+ ;push ebp
- mov edi, [esp+24] ; pDst
- mov edx, [esp+28] ; iDstStride
- mov esi, [esp+32] ; pSrc
- mov ecx, [esp+36] ; iSrcStride
- mov ebp, [esp+44] ; iSrcHeight
+ ;mov edi, [esp+24] ; pDst
+ ;mov edx, [esp+28] ; iDstStride
+ ;mov esi, [esp+32] ; pSrc
+ ;mov ecx, [esp+36] ; iSrcStride
+ ;mov ebp, [esp+44] ; iSrcHeight
+%ifdef X86_32
+ push r6
+ %assign push_num 1
+%else
+ %assign push_num 0
+%endif
+ LOAD_6_PARA
+ PUSH_XMM 8
+ SIGN_EXTENSION r1, r1d
+ SIGN_EXTENSION r3, r3d
+ SIGN_EXTENSION r4, r4d
+ SIGN_EXTENSION r5, r5d
- sar ebp, $01 ; iSrcHeight >> 1
+%ifndef X86_32
+ push r12
+ mov r12, r4
+%endif
+ sar r5, $01 ; iSrcHeight >> 1
movdqa xmm7, [shufb_mask_low] ; mask low
movdqa xmm6, [shufb_mask_high] ; mask high
-.yloops:
- mov eax, [esp+40] ; iSrcWidth
- sar eax, $01 ; iSrcWidth >> 1
- mov ebx, eax ; iDstWidth restored at ebx
- sar eax, $04 ; (iSrcWidth >> 1) / 16 ; loop count = num_of_mb
- neg ebx ; - (iSrcWidth >> 1)
+.yloops4:
+ ;mov eax, [esp+40] ; iSrcWidth
+ ;sar eax, $01 ; iSrcWidth >> 1
+ ;mov ebx, eax ; iDstWidth restored at ebx
+ ;sar eax, $04 ; (iSrcWidth >> 1) / 16 ; loop count = num_of_mb
+ ;neg ebx ; - (iSrcWidth >> 1)
+%ifdef X86_32
+ mov r4, arg5
+%else
+ mov r4, r12
+%endif
+ sar r4, $01 ; iSrcWidth >> 1
+ mov r6, r4 ; iDstWidth restored at ebx
+ sar r4, $04 ; (iSrcWidth >> 1) / 16 ; loop count = num_of_mb
+ neg r6 ; - (iSrcWidth >> 1)
; each loop = source bandwidth: 32 bytes
-.xloops:
+.xloops4:
; 1st part horizonal loop: x16 bytes
; mem hi<- ->lo
;1st Line Src: xmm0: h H g G f F e E d D c C b B a A
@@ -458,10 +515,10 @@
;: p .. a
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- movdqa xmm0, [esi] ; 1st_src_line
- movdqa xmm1, [esi+16] ; 1st_src_line + 16
- movdqa xmm2, [esi+ecx] ; 2nd_src_line
- movdqa xmm3, [esi+ecx+16] ; 2nd_src_line + 16
+ movdqa xmm0, [r2] ; 1st_src_line
+ movdqa xmm1, [r2+16] ; 1st_src_line + 16
+ movdqa xmm2, [r2+r3] ; 2nd_src_line
+ movdqa xmm3, [r2+r3+16] ; 2nd_src_line + 16
; packing & avg
movdqa xmm4, xmm0 ; h H g G f F e E d D c C b B a A
@@ -498,29 +555,33 @@
pavgb xmm0, xmm2
; write pDst
- movdqa [edi], xmm0
+ movdqa [r0], xmm0
; next SMB
- lea esi, [esi+32]
- lea edi, [edi+16]
+ lea r2, [r2+32]
+ lea r0, [r0+16]
- dec eax
- jg near .xloops
+ dec r4
+ jg near .xloops4
; next line
- lea esi, [esi+2*ecx] ; next end of lines
- lea esi, [esi+2*ebx] ; reset to base 0 [- 2 * iDstWidth]
- lea edi, [edi+edx]
- lea edi, [edi+ebx] ; reset to base 0 [- iDstWidth]
+ lea r2, [r2+2*r3] ; next end of lines
+ lea r2, [r2+2*r6] ; reset to base 0 [- 2 * iDstWidth]
+ lea r0, [r0+r1]
+ lea r0, [r0+r6] ; reset to base 0 [- iDstWidth]
- dec ebp
- jg near .yloops
+ dec r5
+ jg near .yloops4
- pop ebp
- pop edi
- pop esi
- pop edx
- pop ebx
+%ifndef X86_32
+ pop r12
+%endif
+
+ POP_XMM
+ LOAD_6_PARA_POP
+%ifdef X86_32
+ pop r6
+%endif
ret
;***********************************************************************
@@ -529,30 +590,39 @@
; const int iSrcWidth, const int iSrcHeight );
;***********************************************************************
WELS_EXTERN DyadicBilinearDownsamplerWidthx16_ssse3
- push ebx
- push edx
- push esi
- push edi
- push ebp
+%ifdef X86_32
+ push r6
+ %assign push_num 1
+%else
+ %assign push_num 0
+%endif
+ LOAD_6_PARA
+ PUSH_XMM 6
+ SIGN_EXTENSION r1, r1d
+ SIGN_EXTENSION r3, r3d
+ SIGN_EXTENSION r4, r4d
+ SIGN_EXTENSION r5, r5d
- mov edi, [esp+24] ; pDst
- mov edx, [esp+28] ; iDstStride
- mov esi, [esp+32] ; pSrc
- mov ecx, [esp+36] ; iSrcStride
- mov ebp, [esp+44] ; iSrcHeight
+%ifndef X86_32
+ push r12
+ mov r12, r4
+%endif
+ sar r5, $01 ; iSrcHeight >> 1
+ movdqa xmm5, [shufb_mask_low] ; mask low
+ movdqa xmm4, [shufb_mask_high] ; mask high
- sar ebp, $01 ; iSrcHeight >> 1
- movdqa xmm7, [shufb_mask_low] ; mask low
- movdqa xmm6, [shufb_mask_high] ; mask high
-
-.yloops:
- mov eax, [esp+40] ; iSrcWidth
- sar eax, $01 ; iSrcWidth >> 1
- mov ebx, eax ; iDstWidth restored at ebx
- sar eax, $03 ; (iSrcWidth >> 1) / 8 ; loop count = num_of_mb
- neg ebx ; - (iSrcWidth >> 1)
+.yloops5:
+%ifdef X86_32
+ mov r4, arg5
+%else
+ mov r4, r12
+%endif
+ sar r4, $01 ; iSrcWidth >> 1
+ mov r6, r4 ; iDstWidth restored at ebx
+ sar r4, $03 ; (iSrcWidth >> 1) / 8 ; loop count = num_of_mb
+ neg r6 ; - (iSrcWidth >> 1)
; each loop = source bandwidth: 16 bytes
-.xloops:
+.xloops5:
; horizonal loop: x16 bytes by source
; mem hi<- ->lo
;1st line pSrc: xmm0: h H g G f F e E d D c C b B a A
@@ -562,13 +632,13 @@
;: h g f e d c b a, p o n m l k j i
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- movdqa xmm0, [esi] ; 1st_src_line
- movdqa xmm1, [esi+ecx] ; 2nd_src_line
+ movdqa xmm0, [r2] ; 1st_src_line
+ movdqa xmm1, [r2+r3] ; 2nd_src_line
; packing & avg
movdqa xmm2, xmm0 ; h H g G f F e E d D c C b B a A
- pshufb xmm0, xmm7 ; 0 H 0 G 0 F 0 E 0 D 0 C 0 B 0 A
- pshufb xmm2, xmm6 ; 0 h 0 g 0 f 0 e 0 d 0 c 0 b 0 a
+ pshufb xmm0, xmm5 ; 0 H 0 G 0 F 0 E 0 D 0 C 0 B 0 A
+ pshufb xmm2, xmm4 ; 0 h 0 g 0 f 0 e 0 d 0 c 0 b 0 a
; another implementation for xmm2 high bits
; psubb xmm2, xmm0 ; h 0 g 0 f 0 e 0 d 0 c 0 b 0 a 0
; psrlw xmm2, 8 ; 0 h 0 g 0 f 0 e 0 d 0 c 0 b 0 a
@@ -575,8 +645,8 @@
pavgb xmm0, xmm2
movdqa xmm3, xmm1
- pshufb xmm1, xmm7
- pshufb xmm3, xmm6
+ pshufb xmm1, xmm5
+ pshufb xmm3, xmm4
; psubb xmm3, xmm1
; psrlw xmm3, 8
pavgb xmm1, xmm3
@@ -585,29 +655,32 @@
packuswb xmm0, xmm1
; write pDst
- movq [edi], xmm0
+ movq [r0], xmm0
; next SMB
- lea esi, [esi+16]
- lea edi, [edi+8]
+ lea r2, [r2+16]
+ lea r0, [r0+8]
- dec eax
- jg near .xloops
+ dec r4
+ jg near .xloops5
- ; next line
- lea esi, [esi+2*ecx] ; next end of lines
- lea esi, [esi+2*ebx] ; reset to base 0 [- 2 * iDstWidth]
- lea edi, [edi+edx]
- lea edi, [edi+ebx] ; reset to base 0 [- iDstWidth]
+ lea r2, [r2+2*r3] ; next end of lines
+ lea r2, [r2+2*r6] ; reset to base 0 [- 2 * iDstWidth]
+ lea r0, [r0+r1]
+ lea r0, [r0+r6] ; reset to base 0 [- iDstWidth]
- dec ebp
- jg near .yloops
+ dec r5
+ jg near .yloops5
- pop ebp
- pop edi
- pop esi
- pop edx
- pop ebx
+%ifndef X86_32
+ pop r12
+%endif
+
+ POP_XMM
+ LOAD_6_PARA_POP
+%ifdef X86_32
+ pop r6
+%endif
ret
; got about 65% improvement over DyadicBilinearDownsamplerWidthx32_sse
@@ -617,31 +690,40 @@
; const int iSrcWidth, const int iSrcHeight );
;***********************************************************************
WELS_EXTERN DyadicBilinearDownsamplerWidthx32_sse4
- push ebx
- push edx
- push esi
- push edi
- push ebp
+%ifdef X86_32
+ push r6
+ %assign push_num 1
+%else
+ %assign push_num 0
+%endif
+ LOAD_6_PARA
+ PUSH_XMM 8
+ SIGN_EXTENSION r1, r1d
+ SIGN_EXTENSION r3, r3d
+ SIGN_EXTENSION r4, r4d
+ SIGN_EXTENSION r5, r5d
- mov edi, [esp+24] ; pDst
- mov edx, [esp+28] ; iDstStride
- mov esi, [esp+32] ; pSrc
- mov ecx, [esp+36] ; iSrcStride
- mov ebp, [esp+44] ; iSrcHeight
+%ifndef X86_32
+ push r12
+ mov r12, r4
+%endif
+ sar r5, $01 ; iSrcHeight >> 1
- sar ebp, $01 ; iSrcHeight >> 1
-
movdqa xmm7, [shufb_mask_low] ; mask low
movdqa xmm6, [shufb_mask_high] ; mask high
-.yloops:
- mov eax, [esp+40] ; iSrcWidth
- sar eax, $01 ; iSrcWidth >> 1
- mov ebx, eax ; iDstWidth restored at ebx
- sar eax, $04 ; (iSrcWidth >> 1) / 16 ; loop count = num_of_mb
- neg ebx ; - (iSrcWidth >> 1)
+.yloops6:
+%ifdef X86_32
+ mov r4, arg5
+%else
+ mov r4, r12
+%endif
+ sar r4, $01 ; iSrcWidth >> 1
+ mov r6, r4 ; iDstWidth restored at ebx
+ sar r4, $04 ; (iSrcWidth >> 1) / 16 ; loop count = num_of_mb
+ neg r6 ; - (iSrcWidth >> 1)
; each loop = source bandwidth: 32 bytes
-.xloops:
+.xloops6:
; 1st part horizonal loop: x16 bytes
; mem hi<- ->lo
;1st Line Src: xmm0: h H g G f F e E d D c C b B a A
@@ -655,10 +737,10 @@
;: p .. a
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- movntdqa xmm0, [esi] ; 1st_src_line
- movntdqa xmm1, [esi+16] ; 1st_src_line + 16
- movntdqa xmm2, [esi+ecx] ; 2nd_src_line
- movntdqa xmm3, [esi+ecx+16] ; 2nd_src_line + 16
+ movntdqa xmm0, [r2] ; 1st_src_line
+ movntdqa xmm1, [r2+16] ; 1st_src_line + 16
+ movntdqa xmm2, [r2+r3] ; 2nd_src_line
+ movntdqa xmm3, [r2+r3+16] ; 2nd_src_line + 16
; packing & avg
movdqa xmm4, xmm0 ; h H g G f F e E d D c C b B a A
@@ -694,29 +776,32 @@
pavgb xmm0, xmm2
; write pDst
- movdqa [edi], xmm0
+ movdqa [r0], xmm0
; next SMB
- lea esi, [esi+32]
- lea edi, [edi+16]
+ lea r2, [r2+32]
+ lea r0, [r0+16]
- dec eax
- jg near .xloops
+ dec r4
+ jg near .xloops6
- ; next line
- lea esi, [esi+2*ecx] ; next end of lines
- lea esi, [esi+2*ebx] ; reset to base 0 [- 2 * iDstWidth]
- lea edi, [edi+edx]
- lea edi, [edi+ebx] ; reset to base 0 [- iDstWidth]
+ lea r2, [r2+2*r3] ; next end of lines
+ lea r2, [r2+2*r6] ; reset to base 0 [- 2 * iDstWidth]
+ lea r0, [r0+r1]
+ lea r0, [r0+r6] ; reset to base 0 [- iDstWidth]
- dec ebp
- jg near .yloops
+ dec r5
+ jg near .yloops6
- pop ebp
- pop edi
- pop esi
- pop edx
- pop ebx
+%ifndef X86_32
+ pop r12
+%endif
+
+ POP_XMM
+ LOAD_6_PARA_POP
+%ifdef X86_32
+ pop r6
+%endif
ret
;***********************************************************************
@@ -725,30 +810,39 @@
; const int iSrcWidth, const int iSrcHeight );
;***********************************************************************
WELS_EXTERN DyadicBilinearDownsamplerWidthx16_sse4
- push ebx
- push edx
- push esi
- push edi
- push ebp
+%ifdef X86_32
+ push r6
+ %assign push_num 1
+%else
+ %assign push_num 0
+%endif
+ LOAD_6_PARA
+ PUSH_XMM 6
+ SIGN_EXTENSION r1, r1d
+ SIGN_EXTENSION r3, r3d
+ SIGN_EXTENSION r4, r4d
+ SIGN_EXTENSION r5, r5d
- mov edi, [esp+24] ; pDst
- mov edx, [esp+28] ; iDstStride
- mov esi, [esp+32] ; pSrc
- mov ecx, [esp+36] ; iSrcStride
- mov ebp, [esp+44] ; iSrcHeight
+%ifndef X86_32
+ push r12
+ mov r12, r4
+%endif
+ sar r5, $01 ; iSrcHeight >> 1
+ movdqa xmm5, [shufb_mask_low] ; mask low
+ movdqa xmm4, [shufb_mask_high] ; mask high
- sar ebp, $01 ; iSrcHeight >> 1
- movdqa xmm7, [shufb_mask_low] ; mask low
- movdqa xmm6, [shufb_mask_high] ; mask high
-
-.yloops:
- mov eax, [esp+40] ; iSrcWidth
- sar eax, $01 ; iSrcWidth >> 1
- mov ebx, eax ; iDstWidth restored at ebx
- sar eax, $03 ; (iSrcWidth >> 1) / 8 ; loop count = num_of_mb
- neg ebx ; - (iSrcWidth >> 1)
+.yloops7:
+%ifdef X86_32
+ mov r4, arg5
+%else
+ mov r4, r12
+%endif
+ sar r4, $01 ; iSrcWidth >> 1
+ mov r6, r4 ; iDstWidth restored at ebx
+ sar r4, $03 ; (iSrcWidth >> 1) / 8 ; loop count = num_of_mb
+ neg r6 ; - (iSrcWidth >> 1)
; each loop = source bandwidth: 16 bytes
-.xloops:
+.xloops7:
; horizonal loop: x16 bytes by source
; mem hi<- ->lo
;1st line pSrc: xmm0: h H g G f F e E d D c C b B a A
@@ -758,20 +852,20 @@
;: h g f e d c b a, p o n m l k j i
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- movntdqa xmm0, [esi] ; 1st_src_line
- movntdqa xmm1, [esi+ecx] ; 2nd_src_line
+ movntdqa xmm0, [r2] ; 1st_src_line
+ movntdqa xmm1, [r2+r3] ; 2nd_src_line
; packing & avg
movdqa xmm2, xmm0 ; h H g G f F e E d D c C b B a A
- pshufb xmm0, xmm7 ; 0 H 0 G 0 F 0 E 0 D 0 C 0 B 0 A
- pshufb xmm2, xmm6 ; 0 h 0 g 0 f 0 e 0 d 0 c 0 b 0 a
+ pshufb xmm0, xmm5 ; 0 H 0 G 0 F 0 E 0 D 0 C 0 B 0 A
+ pshufb xmm2, xmm4 ; 0 h 0 g 0 f 0 e 0 d 0 c 0 b 0 a
; psubb xmm2, xmm0 ; h 0 g 0 f 0 e 0 d 0 c 0 b 0 a 0
; psrlw xmm2, 8 ; 0 h 0 g 0 f 0 e 0 d 0 c 0 b 0 a
pavgb xmm0, xmm2
movdqa xmm3, xmm1
- pshufb xmm1, xmm7
- pshufb xmm3, xmm6
+ pshufb xmm1, xmm5
+ pshufb xmm3, xmm4
; psubb xmm3, xmm1
; psrlw xmm3, 8
pavgb xmm1, xmm3
@@ -780,38 +874,40 @@
packuswb xmm0, xmm1
; write pDst
- movq [edi], xmm0
+ movq [r0], xmm0
; next SMB
- lea esi, [esi+16]
- lea edi, [edi+8]
+ lea r2, [r2+16]
+ lea r0, [r0+8]
- dec eax
- jg near .xloops
+ dec r4
+ jg near .xloops7
; next line
- lea esi, [esi+2*ecx] ; next end of lines
- lea esi, [esi+2*ebx] ; reset to base 0 [- 2 * iDstWidth]
- lea edi, [edi+edx]
- lea edi, [edi+ebx] ; reset to base 0 [- iDstWidth]
+ lea r2, [r2+2*r3] ; next end of lines
+ lea r2, [r2+2*r6] ; reset to base 0 [- 2 * iDstWidth]
+ lea r0, [r0+r1]
+ lea r0, [r0+r6] ; reset to base 0 [- iDstWidth]
- dec ebp
- jg near .yloops
+ dec r5
+ jg near .yloops7
- pop ebp
- pop edi
- pop esi
- pop edx
- pop ebx
+%ifndef X86_32
+ pop r12
+%endif
+
+ POP_XMM
+ LOAD_6_PARA_POP
+%ifdef X86_32
+ pop r6
+%endif
ret
-
-
-
+%ifdef X86_32
;**************************************************************************************************************
;int GeneralBilinearAccurateDownsampler_sse2( unsigned char* pDst, const int iDstStride, const int iDstWidth, const int iDstHeight,
-; unsigned char* pSrc, const int iSrcStride, const int iSrcWidth, const int iSrcHeight,
+; unsigned char* pSrc, const int iSrcStride,
; unsigned int uiScaleX, unsigned int uiScaleY );
;{
;**************************************************************************************************************
@@ -822,7 +918,7 @@
push edi
push ebx
%define pushsize 16
-%define localsize 28
+%define localsize 16
%define pDstData esp + pushsize + localsize + 4
%define dwDstStride esp + pushsize + localsize + 8
%define dwDstWidth esp + pushsize + localsize + 12
@@ -829,19 +925,15 @@
%define dwDstHeight esp + pushsize + localsize + 16
%define pSrcData esp + pushsize + localsize + 20
%define dwSrcStride esp + pushsize + localsize + 24
-%define dwSrcWidth esp + pushsize + localsize + 28
-%define dwSrcHeight esp + pushsize + localsize + 32
-%define scale esp + 0
-%define uiScaleX esp + pushsize + localsize + 36
-%define uiScaleY esp + pushsize + localsize + 40
-%define tmpHeight esp + 12
-%define yInverse esp + 16
-%define xInverse esp + 20
-%define dstStep esp + 24
+%define uiScaleX esp + pushsize + localsize + 28
+%define uiScaleY esp + pushsize + localsize + 32
+%define tmpHeight esp + 0
+%define yInverse esp + 4
+%define xInverse esp + 8
+%define dstStep esp + 12
sub esp, localsize
pxor xmm0, xmm0
- mov edx, 32767
mov eax, [uiScaleX]
and eax, 32767
mov ebx, eax
@@ -999,7 +1091,6 @@
%undef dwDstWidth
%undef dwDstHeight
%undef dwDstStride
-%undef scale
%undef uiScaleX
%undef uiScaleY
%undef tmpHeight
@@ -1013,7 +1104,7 @@
;**************************************************************************************************************
;int GeneralBilinearFastDownsampler_sse2( unsigned char* pDst, const int iDstStride, const int iDstWidth, const int iDstHeight,
-; unsigned char* pSrc, const int iSrcStride, const int iSrcWidth, const int iSrcHeight,
+; unsigned char* pSrc, const int iSrcStride,
; unsigned int uiScaleX, unsigned int uiScaleY );
;{
;**************************************************************************************************************
@@ -1024,7 +1115,7 @@
push edi
push ebx
%define pushsize 16
-%define localsize 28
+%define localsize 16
%define pDstData esp + pushsize + localsize + 4
%define dwDstStride esp + pushsize + localsize + 8
%define dwDstWidth esp + pushsize + localsize + 12
@@ -1031,15 +1122,12 @@
%define dwDstHeight esp + pushsize + localsize + 16
%define pSrcData esp + pushsize + localsize + 20
%define dwSrcStride esp + pushsize + localsize + 24
-%define dwSrcWidth esp + pushsize + localsize + 28
-%define dwSrcHeight esp + pushsize + localsize + 32
-%define scale esp + 0
-%define uiScaleX esp + pushsize + localsize + 36
-%define uiScaleY esp + pushsize + localsize + 40
-%define tmpHeight esp + 12
-%define yInverse esp + 16
-%define xInverse esp + 20
-%define dstStep esp + 24
+%define uiScaleX esp + pushsize + localsize + 28
+%define uiScaleY esp + pushsize + localsize + 32
+%define tmpHeight esp + 0
+%define yInverse esp + 4
+%define xInverse esp + 8
+%define dstStep esp + 12
sub esp, localsize
pxor xmm0, xmm0
@@ -1191,10 +1279,7 @@
%undef dwSrcHeight
%undef dwSrcStride
%undef pDstData
-%undef dwDstWidth
-%undef dwDstHeight
%undef dwDstStride
-%undef scale
%undef uiScaleX
%undef uiScaleY
%undef tmpHeight
@@ -1201,5 +1286,613 @@
%undef yInverse
%undef xInverse
%undef dstStep
+ ret
+
+%elifdef WIN64
+
+;**************************************************************************************************************
+;int GeneralBilinearAccurateDownsampler_sse2( unsigned char* pDst, const int iDstStride, const int iDstWidth, const int iDstHeight,
+; unsigned char* pSrc, const int iSrcStride,
+; unsigned int uiScaleX, unsigned int uiScaleY );
+;{
+;**************************************************************************************************************
+
+WELS_EXTERN GeneralBilinearAccurateDownsampler_sse2
+ push r12
+ push r13
+ push r14
+ push r15
+ push rsi
+ push rdi
+ push rbx
+ push rbp
+ %assign push_num 8
+ LOAD_7_PARA
+ PUSH_XMM 8
+ SIGN_EXTENSION r1, r1d
+ SIGN_EXTENSION r2, r2d
+ SIGN_EXTENSION r3, r3d
+ SIGN_EXTENSION r5, r5d
+ SIGN_EXTENSION r6, r6d
+
+ pxor xmm0, xmm0
+ mov r12d, r6d
+ and r12d, 32767
+ mov r13d, r12d
+ neg r13d
+ and r13d, 32767
+ movd xmm1, r12d ; uinc(uiScaleX mod 32767)
+ movd xmm2, r13d ; -uinc
+ psllq xmm1, 32
+ por xmm1, xmm2 ; 0 0 uinc -uinc (dword)
+ pshufd xmm7, xmm1, 01000100b ; xmm7: uinc -uinc uinc -uinc
+
+ mov r12, arg8
+ SIGN_EXTENSION r12, r12d
+ mov rbp, r12
+ and r12d, 32767
+ mov r13d, r12d
+ neg r13d
+ and r13d, 32767
+ movd xmm6, r12d ; vinc(uiScaleY mod 32767)
+ movd xmm2, r13d ; -vinc
+ psllq xmm6, 32
+ por xmm6, xmm2 ; 0 0 vinc -vinc (dword)
+ pshufd xmm6, xmm6, 01010000b ; xmm6: vinc vinc -vinc -vinc
+
+ mov r12d, 40003fffh
+ movd xmm5, r12d
+ punpcklwd xmm5, xmm0 ; 16384 16383
+ pshufd xmm5, xmm5, 01000100b ; xmm5: 16384 16383 16384 16383
+
+DOWNSAMPLE:
+ sub r1, r2 ; stride - width
+ dec r3
+ mov r14,16384
+ pshufd xmm4, xmm5, 01010000b ; initial v to 16384 16384 16383 16383
+
+HEIGHT:
+ ;mov r12, r4
+ mov r12, r14
+ shr r12, 15
+ imul r12, r5
+ add r12, r4 ; get current row address
+ mov r13, r12
+ add r13, r5
+
+ mov r15, 16384
+ mov rsi, r2
+ dec rsi
+ movdqa xmm3, xmm5 ; initial u to 16384 16383 16384 16383
+
+WIDTH:
+ mov rdi, r15
+ shr rdi, 15
+
+ movd xmm1, [r12+rdi] ; xxxxxxba
+ movd xmm2, [r13+rdi] ; xxxxxxdc
+ pxor xmm0, xmm0
+ punpcklwd xmm1, xmm2 ; xxxxdcba
+ punpcklbw xmm1, xmm0 ; 0d0c0b0a
+ punpcklwd xmm1, xmm0 ; 000d000c000b000a
+
+ movdqa xmm2, xmm4 ; xmm2: vv(1-v)(1-v) tmpv
+ pmaddwd xmm2, xmm3 ; mul u(1-u)u(1-u) on xmm2
+ movdqa xmm0, xmm2
+ pmuludq xmm2, xmm1
+ psrlq xmm0, 32
+ psrlq xmm1, 32
+ pmuludq xmm0, xmm1
+ paddq xmm2, xmm0
+ pshufd xmm1, xmm2, 00001110b
+ paddq xmm2, xmm1
+ psrlq xmm2, 29
+
+ movd ebx, xmm2
+ inc ebx
+ shr ebx, 1
+ mov [r0], bl
+ inc r0
+
+ add r15, r6
+ paddw xmm3, xmm7 ; inc u
+ psllw xmm3, 1
+ psrlw xmm3, 1
+
+ dec rsi
+ jg WIDTH
+
+WIDTH_END:
+ shr r15, 15
+ mov bl, [r12+r15]
+ mov [r0],bl
+ inc r0
+ add r14, rbp
+ add r0, r1
+
+ paddw xmm4, xmm6 ; inc v
+ psllw xmm4, 1
+ psrlw xmm4, 1
+
+ dec r3
+ jg HEIGHT
+
+LAST_ROW:
+ shr r14, 15
+ imul r14, r5
+ add r4, r14
+ mov r15, 16384
+
+LAST_ROW_WIDTH:
+ mov rdi, r15
+ shr rdi, 15
+ mov bl, [r4+rdi]
+ mov [r0],bl
+ inc r0
+
+ add r15, r6
+ dec r2
+ jg LAST_ROW_WIDTH
+
+LAST_ROW_END:
+
+ POP_XMM
+ pop rbp
+ pop rbx
+ pop rdi
+ pop rsi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ ret
+
+;**************************************************************************************************************
+;int GeneralBilinearFastDownsampler_sse2( unsigned char* pDst, const int iDstStride, const int iDstWidth, const int iDstHeight,
+; unsigned char* pSrc, const int iSrcStride,
+; unsigned int uiScaleX, unsigned int uiScaleY );
+;{
+;**************************************************************************************************************
+
+WELS_EXTERN GeneralBilinearFastDownsampler_sse2
+ push r12
+ push r13
+ push r14
+ push r15
+ push rsi
+ push rdi
+ push rbx
+ push rbp
+ %assign push_num 8
+ LOAD_7_PARA
+ PUSH_XMM 8
+ SIGN_EXTENSION r1, r1d
+ SIGN_EXTENSION r2, r2d
+ SIGN_EXTENSION r3, r3d
+ SIGN_EXTENSION r5, r5d
+ SIGN_EXTENSION r6, r6d
+
+ pxor xmm0, xmm0
+ mov r12d, r6d
+ and r12d, 65535
+ mov r13d, r12d
+ neg r13d
+ and r13d, 65535
+ movd xmm1, r12d ; uinc(uiScaleX mod 65536)
+ movd xmm2, r13d ; -uinc
+ psllq xmm1, 32
+ por xmm1, xmm2 ; 0 uinc 0 -uinc
+ pshuflw xmm7, xmm1, 10001000b ; xmm7: uinc -uinc uinc -uinc
+
+ mov r12, arg8
+ SIGN_EXTENSION r12, r12d
+ mov rbp, r12
+ and r12d, 32767
+ mov r13d, r12d
+ neg r13d
+ and r13d, 32767
+ movd xmm6, r12d ; vinc(uiScaleY mod 32767)
+ movd xmm2, r13d ; -vinc
+ psllq xmm6, 32
+ por xmm6, xmm2 ; 0 vinc 0 -vinc
+ pshuflw xmm6, xmm6, 10100000b ; xmm6: vinc vinc -vinc -vinc
+
+ mov r12d, 80007fffh ; 32768 32767
+ movd xmm5, r12d
+ pshuflw xmm5, xmm5, 01000100b ; 32768 32767 32768 32767
+
+FAST_DOWNSAMPLE:
+ sub r1, r2 ; stride - width
+ dec r3
+ mov r14,16384
+
+ pshuflw xmm4, xmm5, 01010000b
+ psrlw xmm4, 1 ; initial v to 16384 16384 16383 16383
+
+FAST_HEIGHT:
+ mov r12, r14
+ shr r12, 15
+ imul r12, r5
+ add r12, r4 ; get current row address
+ mov r13, r12
+ add r13, r5
+
+ mov r15, 32768
+ mov rsi, r2
+ dec rsi
+
+ movdqa xmm3, xmm5 ; initial u to 32768 32767 32768 32767
+
+FAST_WIDTH:
+ mov rdi, r15
+ shr rdi, 16
+
+ movd xmm1, [r12+rdi] ; xxxxxxba
+ movd xmm2, [r13+rdi] ; xxxxxxdc
+ punpcklwd xmm1, xmm2 ; xxxxdcba
+ punpcklbw xmm1, xmm0 ; 0d0c0b0a
+
+ movdqa xmm2, xmm4 ; xmm2: vv(1-v)(1-v) tmpv
+ pmulhuw xmm2, xmm3 ; mul u(1-u)u(1-u) on xmm2
+ pmaddwd xmm2, xmm1
+ pshufd xmm1, xmm2, 00000001b
+ paddd xmm2, xmm1
+ movdqa xmm1, [add_extra_half]
+ paddd xmm2, xmm1
+ psrld xmm2, 15
+
+ packuswb xmm2, xmm0
+ movd ebx, xmm2
+ mov [r0], bl
+ inc r0
+
+ add r15, r6
+
+ paddw xmm3, xmm7 ; inc u
+ dec rsi
+ jg FAST_WIDTH
+
+FAST_WIDTH_END:
+ shr r15, 16
+ mov bl, [r12+r15]
+ mov [r0],bl
+ inc r0
+ add r14, rbp
+ add r0, r1
+
+ paddw xmm4, xmm6 ; inc v
+ psllw xmm4, 1
+ psrlw xmm4, 1
+
+ dec r3
+ jg FAST_HEIGHT
+
+
+FAST_LAST_ROW:
+ shr r14, 15
+ imul r14, r5
+ add r4, r14
+ mov r15, 32768
+
+FAST_LAST_ROW_WIDTH:
+ mov rdi, r15
+ shr rdi, 16
+ mov bl, [r4+rdi]
+ mov [r0],bl
+ inc r0
+
+ add r15, r6
+ dec r2
+ jg FAST_LAST_ROW_WIDTH
+
+FAST_LAST_ROW_END:
+
+ POP_XMM
+ pop rbp
+ pop rbx
+ pop rdi
+ pop rsi
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ ret
+
+%elifdef UNIX64
+
+;**************************************************************************************************************
+;int GeneralBilinearAccurateDownsampler_sse2( unsigned char* pDst, const int iDstStride, const int iDstWidth, const int iDstHeight,
+; unsigned char* pSrc, const int iSrcStride,
+; unsigned int uiScaleX, unsigned int uiScaleY );
+;{
+;**************************************************************************************************************
+
+WELS_EXTERN GeneralBilinearAccurateDownsampler_sse2
+ push r12
+ push r13
+ push r14
+ push r15
+ push rbx
+ push rbp
+ %assign push_num 6
+ LOAD_7_PARA
+ SIGN_EXTENSION r1, r1d
+ SIGN_EXTENSION r2, r2d
+ SIGN_EXTENSION r3, r3d
+ SIGN_EXTENSION r5, r5d
+ SIGN_EXTENSION r6, r6d
+
+ pxor xmm0, xmm0
+ mov r12d, r6d
+ and r12d, 32767
+ mov r13d, r12d
+ neg r13d
+ and r13d, 32767
+ movd xmm1, r12d ; uinc(uiScaleX mod 32767)
+ movd xmm2, r13d ; -uinc
+ psllq xmm1, 32
+ por xmm1, xmm2 ; 0 0 uinc -uinc (dword)
+ pshufd xmm7, xmm1, 01000100b ; xmm7: uinc -uinc uinc -uinc
+
+ mov r12, arg8
+ SIGN_EXTENSION r12, r12d
+ mov rbp, r12
+ and r12d, 32767
+ mov r13d, r12d
+ neg r13d
+ and r13d, 32767
+ movd xmm6, r12d ; vinc(uiScaleY mod 32767)
+ movd xmm2, r13d ; -vinc
+ psllq xmm6, 32
+ por xmm6, xmm2 ; 0 0 vinc -vinc (dword)
+ pshufd xmm6, xmm6, 01010000b ; xmm6: vinc vinc -vinc -vinc
+
+ mov r12d, 40003fffh
+ movd xmm5, r12d
+ punpcklwd xmm5, xmm0 ; 16384 16383
+ pshufd xmm5, xmm5, 01000100b ; xmm5: 16384 16383 16384 16383
+
+DOWNSAMPLE:
+ sub r1, r2 ; stride - width
+ dec r3
+ mov r14,16384
+ pshufd xmm4, xmm5, 01010000b ; initial v to 16384 16384 16383 16383
+
+HEIGHT:
+ ;mov r12, r4
+ mov r12, r14
+ shr r12, 15
+ imul r12, r5
+ add r12, r4 ; get current row address
+ mov r13, r12
+ add r13, r5
+
+ mov r15, 16384
+ mov rax, r2
+ dec rax
+ movdqa xmm3, xmm5 ; initial u to 16384 16383 16384 16383
+
+WIDTH:
+ mov r11, r15
+ shr r11, 15
+
+ movd xmm1, [r12+r11] ; xxxxxxba
+ movd xmm2, [r13+r11] ; xxxxxxdc
+ pxor xmm0, xmm0
+ punpcklwd xmm1, xmm2 ; xxxxdcba
+ punpcklbw xmm1, xmm0 ; 0d0c0b0a
+ punpcklwd xmm1, xmm0 ; 000d000c000b000a
+
+ movdqa xmm2, xmm4 ; xmm2: vv(1-v)(1-v) tmpv
+ pmaddwd xmm2, xmm3 ; mul u(1-u)u(1-u) on xmm2
+ movdqa xmm0, xmm2
+ pmuludq xmm2, xmm1
+ psrlq xmm0, 32
+ psrlq xmm1, 32
+ pmuludq xmm0, xmm1
+ paddq xmm2, xmm0
+ pshufd xmm1, xmm2, 00001110b
+ paddq xmm2, xmm1
+ psrlq xmm2, 29
+
+ movd ebx, xmm2
+ inc ebx
+ shr ebx, 1
+ mov [r0], bl
+ inc r0
+
+ add r15, r6
+ paddw xmm3, xmm7 ; inc u
+ psllw xmm3, 1
+ psrlw xmm3, 1
+
+ dec rax
+ jg WIDTH
+
+WIDTH_END:
+ shr r15, 15
+ mov bl, [r12+r15]
+ mov [r0],bl
+ inc r0
+ add r14, rbp
+ add r0, r1
+
+ paddw xmm4, xmm6 ; inc v
+ psllw xmm4, 1
+ psrlw xmm4, 1
+
+ dec r3
+ jg HEIGHT
+
+LAST_ROW:
+ shr r14, 15
+ imul r14, r5
+ add r4, r14
+ mov r15, 16384
+
+LAST_ROW_WIDTH:
+ mov r11, r15
+ shr r11, 15
+ mov bl, [r4+r11]
+ mov [r0],bl
+ inc r0
+
+ add r15, r6
+ dec r2
+ jg LAST_ROW_WIDTH
+
+LAST_ROW_END:
+
+ pop rbp
+ pop rbx
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ ret
+
+;**************************************************************************************************************
+;int GeneralBilinearFastDownsampler_sse2( unsigned char* pDst, const int iDstStride, const int iDstWidth, const int iDstHeight,
+; unsigned char* pSrc, const int iSrcStride,
+; unsigned int uiScaleX, unsigned int uiScaleY );
+;{
+;**************************************************************************************************************
+
+WELS_EXTERN GeneralBilinearFastDownsampler_sse2
+ push r12
+ push r13
+ push r14
+ push r15
+ push rbx
+ push rbp
+ %assign push_num 6
+ LOAD_7_PARA
+ SIGN_EXTENSION r1, r1d
+ SIGN_EXTENSION r2, r2d
+ SIGN_EXTENSION r3, r3d
+ SIGN_EXTENSION r5, r5d
+ SIGN_EXTENSION r6, r6d
+
+ pxor xmm0, xmm0
+ mov r12d, r6d
+ and r12d, 65535
+ mov r13d, r12d
+ neg r13d
+ and r13d, 65535
+ movd xmm1, r12d ; uinc(uiScaleX mod 65536)
+ movd xmm2, r13d ; -uinc
+ psllq xmm1, 32
+ por xmm1, xmm2 ; 0 uinc 0 -uinc
+ pshuflw xmm7, xmm1, 10001000b ; xmm7: uinc -uinc uinc -uinc
+
+ mov r12, arg8
+ SIGN_EXTENSION r12, r12d
+ mov rbp, r12
+ and r12d, 32767
+ mov r13d, r12d
+ neg r13d
+ and r13d, 32767
+ movd xmm6, r12d ; vinc(uiScaleY mod 32767)
+ movd xmm2, r13d ; -vinc
+ psllq xmm6, 32
+ por xmm6, xmm2 ; 0 vinc 0 -vinc
+ pshuflw xmm6, xmm6, 10100000b ; xmm6: vinc vinc -vinc -vinc
+
+ mov r12d, 80007fffh ; 32768 32767
+ movd xmm5, r12d
+ pshuflw xmm5, xmm5, 01000100b ; 32768 32767 32768 32767
+
+FAST_DOWNSAMPLE:
+ sub r1, r2 ; stride - width
+ dec r3
+ mov r14,16384
+
+ pshuflw xmm4, xmm5, 01010000b
+ psrlw xmm4, 1 ; initial v to 16384 16384 16383 16383
+
+FAST_HEIGHT:
+ mov r12, r14
+ shr r12, 15
+ imul r12, r5
+ add r12, r4 ; get current row address
+ mov r13, r12
+ add r13, r5
+
+ mov r15, 32768
+ mov rax, r2
+ dec rax
+
+ movdqa xmm3, xmm5 ; initial u to 32768 32767 32768 32767
+
+FAST_WIDTH:
+ mov r11, r15
+ shr r11, 16
+
+ movd xmm1, [r12+r11] ; xxxxxxba
+ movd xmm2, [r13+r11] ; xxxxxxdc
+ punpcklwd xmm1, xmm2 ; xxxxdcba
+ punpcklbw xmm1, xmm0 ; 0d0c0b0a
+
+ movdqa xmm2, xmm4 ; xmm2: vv(1-v)(1-v) tmpv
+ pmulhuw xmm2, xmm3 ; mul u(1-u)u(1-u) on xmm2
+ pmaddwd xmm2, xmm1
+ pshufd xmm1, xmm2, 00000001b
+ paddd xmm2, xmm1
+ movdqa xmm1, [add_extra_half]
+ paddd xmm2, xmm1
+ psrld xmm2, 15
+
+ packuswb xmm2, xmm0
+ movd ebx, xmm2
+ mov [r0], bl
+ inc r0
+
+ add r15, r6
+
+ paddw xmm3, xmm7 ; inc u
+ dec rax
+ jg FAST_WIDTH
+
+FAST_WIDTH_END:
+ shr r15, 16
+ mov bl, [r12+r15]
+ mov [r0],bl
+ inc r0
+ add r14, rbp
+ add r0, r1
+
+ paddw xmm4, xmm6 ; inc v
+ psllw xmm4, 1
+ psrlw xmm4, 1
+
+ dec r3
+ jg FAST_HEIGHT
+
+
+FAST_LAST_ROW:
+ shr r14, 15
+ imul r14, r5
+ add r4, r14
+ mov r15, 32768
+
+FAST_LAST_ROW_WIDTH:
+ mov r11, r15
+ shr r11, 16
+ mov bl, [r4+r11]
+ mov [r0],bl
+ inc r0
+
+ add r15, r6
+ dec r2
+ jg FAST_LAST_ROW_WIDTH
+
+FAST_LAST_ROW_END:
+
+ pop rbp
+ pop rbx
+ pop r15
+ pop r14
+ pop r13
+ pop r12
ret
%endif