--- quantize_mpeg_mmx.asm 2003/11/03 15:51:50 1.1.2.4 +++ quantize_mpeg_mmx.asm 2008/11/11 20:46:24 1.10 @@ -21,7 +21,7 @@ ; * 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_mmx.asm,v 1.1.2.4 2003/11/03 15:51:50 edgomez Exp $ +; * $Id: quantize_mpeg_mmx.asm,v 1.10 2008/11/11 20:46:24 Isibaar Exp $ ; * ; *************************************************************************/ @@ -31,10 +31,23 @@ %macro cglobal 1 %ifdef PREFIX - global _%1 - %define %1 _%1 + %ifdef MARK_FUNCS + global _%1:function %1.endfunc-%1 + %define %1 _%1:function %1.endfunc-%1 + %define ENDFUNC .endfunc + %else + global _%1 + %define %1 _%1 + %define ENDFUNC + %endif %else - global %1 + %ifdef MARK_FUNCS + global %1:function %1.endfunc-%1 + %define ENDFUNC .endfunc + %else + global %1 + %define ENDFUNC + %endif %endif %endmacro @@ -52,9 +65,9 @@ ;============================================================================= %ifdef FORMAT_COFF -SECTION .rodata data +SECTION .rodata %else -SECTION .rodata data align=16 +SECTION .rodata align=16 %endif mmx_one: @@ -76,21 +89,6 @@ %assign quant quant+1 %endrep -;----------------------------------------------------------------------------- -; intra matrix -;----------------------------------------------------------------------------- - -cextern intra_matrix -cextern intra_matrix_fix - -;----------------------------------------------------------------------------- -; inter matrix -;----------------------------------------------------------------------------- - -cextern inter_matrix -cextern inter_matrix_fix - - %define VM18P 3 %define VM18Q 4 @@ -135,6 +133,16 @@ times 4 dw 0 ;============================================================================= +; rounding +;============================================================================= + +mmx_rounding: + dw (1<<13) + dw 0 + dw (1<<13) + dw 0 + +;============================================================================= ; Code ;============================================================================= @@ -145,192 +153,103 @@ cglobal dequant_mpeg_intra_mmx cglobal dequant_mpeg_inter_mmx + +%macro QUANT_MMX 1 + movq mm0, [eax + 16*(%1)] ; data + movq mm2, [ecx + 16*(%1) + 128] ; intra_matrix_rec + movq mm4, [eax + 16*(%1) + 8] ; data + movq mm6, [ecx + 16*(%1) + 128 + 8] ; intra_matrix_rec + + movq mm1, mm0 + movq mm5, mm4 + + pmullw mm0, mm2 ; low results + pmulhw mm1, mm2 ; high results + pmullw mm4, mm6 ; low results + pmulhw mm5, mm6 ; high results + + movq mm2, mm0 + movq mm6, mm4 + + punpckhwd mm0, mm1 + punpcklwd mm2, mm1 + punpckhwd mm4, mm5 + punpcklwd mm6, mm5 + + paddd mm2, mm7 + paddd mm0, mm7 + paddd mm6, mm7 + paddd mm4, mm7 + + psrad mm2, 14 + psrad mm0, 14 + psrad mm6, 14 + psrad mm4, 14 + + packssdw mm2, mm0 + packssdw mm6, mm4 + + movq [edi + 16*(%1)], mm2 + movq [edi + 16*(%1)+8], mm6 +%endmacro + ;----------------------------------------------------------------------------- ; ; uint32_t quant_mpeg_intra_mmx(int16_t * coeff, ; const int16_t const * data, ; const uint32_t quant, -; const uint32_t dcscalar); +; const uint32_t dcscalar, +; const uint16_t *mpeg_matrices); ; ;----------------------------------------------------------------------------- ALIGN 16 quant_mpeg_intra_mmx: - push ecx - push esi push edi + movq mm7, [mmx_rounding] - mov edi, [esp + 12 + 4] ; coeff - mov esi, [esp + 12 + 8] ; data - mov eax, [esp + 12 + 12] ; quant - - movq mm5, [quantd + eax * 8 - 8] ; quantd -> mm5 - - xor ecx, ecx - cmp al, 1 - jz near .q1loop - - cmp al, 2 - jz near .q2loop - - movq mm7, [mmx_div + eax * 8 - 8] ; multipliers[quant] -> mm7 - -ALIGN 16 -.loop - movq mm0, [esi + 8*ecx] ; mm0 = [1st] - movq mm3, [esi + 8*ecx + 8] ; - pxor mm1, mm1 ; mm1 = 0 - pxor mm4, mm4 - pcmpgtw mm1, mm0 ; mm1 = (0 > mm0) - pcmpgtw mm4, mm3 - pxor mm0, mm1 ; mm0 = |mm0| - pxor mm3, mm4 ; - psubw mm0, mm1 ; displace - psubw mm3, mm4 ; - psllw mm0, 4 ; level << 4 - psllw mm3, 4 - movq mm2, [intra_matrix + 8*ecx] - psrlw mm2, 1 ; intra_matrix[i]>>1 - paddw mm0, mm2 - movq mm2, [intra_matrix_fix + ecx*8] - pmulhw mm0, mm2 ; (level<<4 + intra_matrix[i]>>1) / intra_matrix[i] - movq mm2, [intra_matrix + 8*ecx + 8] - psrlw mm2, 1 - paddw mm3, mm2 - movq mm2, [intra_matrix_fix + ecx*8 + 8] - pmulhw mm3, mm2 - paddw mm0, mm5 ; + quantd - paddw mm3, mm5 - pmulhw mm0, mm7 ; mm0 = (mm0 / 2Q) >> 16 - pmulhw mm3, mm7 ; - psrlw mm0, 1 ; additional shift by 1 => 16 + 1 = 17 - psrlw mm3, 1 - pxor mm0, mm1 ; mm0 *= sign(mm0) - pxor mm3, mm4 ; - psubw mm0, mm1 ; undisplace - psubw mm3, mm4 ; - - movq [edi + 8*ecx], mm0 - movq [edi + 8*ecx + 8], mm3 - - add ecx,2 - cmp ecx,16 - jnz near .loop - -.done - ; caclulate data[0] // (int32_t)dcscalar) - mov ecx, [esp + 12 + 16] ; dcscalar - mov edx, ecx - movsx eax, word [esi] ; data[0] - shr edx, 1 ; edx = dcscalar /2 - cmp eax, 0 - jg .gtzero - - sub eax, edx - jmp short .mul -.gtzero - add eax, edx -.mul - cdq ; expand eax -> edx:eax - idiv ecx ; eax = edx:eax / dcscalar - - mov [edi], ax ; coeff[0] = ax - + mov eax, [esp + 4 + 8] ; data + mov ecx, [esp + 4 + 20] ; mpeg_quant_matrices + mov edi, [esp + 4 + 4] ; coeff + + QUANT_MMX(0) + QUANT_MMX(1) + QUANT_MMX(2) + QUANT_MMX(3) + QUANT_MMX(4) + QUANT_MMX(5) + QUANT_MMX(6) + QUANT_MMX(7) + + ; calculate DC + movsx eax, word [eax] ; data[0] + mov ecx, [esp + 4 + 16] ; dcscalar + mov edx, eax + mov edi, ecx + shr ecx, 1 ; ecx = dcscalar/2 + sar edx, 31 ; edx = sign extend of eax (ready for division too) + xor ecx, edx ; adjust ecx according to the sign of data[0] + sub ecx, edx + add eax, ecx + + mov ecx, [esp + 4 + 4] ; coeff again + idiv edi ; eax = edx:eax / dcscalar + mov [ecx], ax ; coeff[0] = ax + pop edi - pop esi - pop ecx xor eax, eax ; return(0); ret - -ALIGN 16 -.q1loop - movq mm0, [esi + 8*ecx] ; mm0 = [1st] - movq mm3, [esi + 8*ecx + 8] ; - pxor mm1, mm1 ; mm1 = 0 - pxor mm4, mm4 ; - pcmpgtw mm1, mm0 ; mm1 = (0 > mm0) - pcmpgtw mm4, mm3 ; - pxor mm0, mm1 ; mm0 = |mm0| - pxor mm3, mm4 ; - psubw mm0, mm1 ; displace - psubw mm3, mm4 ; - psllw mm0, 4 - psllw mm3, 4 - movq mm2, [intra_matrix + 8*ecx] - psrlw mm2, 1 - paddw mm0, mm2 - movq mm2, [intra_matrix_fix + ecx*8] - pmulhw mm0, mm2 ; (level<<4 + intra_matrix[i]>>1) / intra_matrix[i] - movq mm2, [intra_matrix + 8*ecx + 8] - psrlw mm2, 1 - paddw mm3, mm2 - movq mm2, [intra_matrix_fix + ecx*8 + 8] - pmulhw mm3, mm2 - paddw mm0, mm5 - paddw mm3, mm5 - psrlw mm0, 1 ; mm0 >>= 1 (/2) - psrlw mm3, 1 ; - pxor mm0, mm1 ; mm0 *= sign(mm0) - pxor mm3, mm4 ; - psubw mm0, mm1 ; undisplace - psubw mm3, mm4 ; - movq [edi + 8*ecx], mm0 - movq [edi + 8*ecx + 8], mm3 - - add ecx, 2 - cmp ecx, 16 - jnz near .q1loop - jmp near .done - - -ALIGN 16 -.q2loop - movq mm0, [esi + 8*ecx] ; mm0 = [1st] - movq mm3, [esi + 8*ecx + 8] ; - pxor mm1, mm1 ; mm1 = 0 - pxor mm4, mm4 ; - pcmpgtw mm1, mm0 ; mm1 = (0 > mm0) - pcmpgtw mm4, mm3 ; - pxor mm0, mm1 ; mm0 = |mm0| - pxor mm3, mm4 ; - psubw mm0, mm1 ; displace - psubw mm3, mm4 ; - psllw mm0, 4 - psllw mm3, 4 - movq mm2, [intra_matrix + 8*ecx] - psrlw mm2, 1 - paddw mm0, mm2 - movq mm2, [intra_matrix_fix + ecx*8] - pmulhw mm0, mm2 ; (level<<4 + intra_matrix[i]>>1) / intra_matrix[i] - movq mm2, [intra_matrix + 8*ecx + 8] - psrlw mm2, 1 - paddw mm3, mm2 - movq mm2, [intra_matrix_fix + ecx*8 + 8] - pmulhw mm3, mm2 - paddw mm0, mm5 - paddw mm3, mm5 - psrlw mm0, 2 ; mm0 >>= 1 (/4) - psrlw mm3, 2 ; - pxor mm0, mm1 ; mm0 *= sign(mm0) - pxor mm3, mm4 ; - psubw mm0, mm1 ; undisplace - psubw mm3, mm4 ; - movq [edi + 8*ecx], mm0 - movq [edi + 8*ecx + 8], mm3 - - add ecx,2 - cmp ecx,16 - jnz near .q2loop - jmp near .done +ENDFUNC ;----------------------------------------------------------------------------- ; ; uint32_t quant_mpeg_inter_mmx(int16_t * coeff, ; const int16_t const * data, -; const uint32_t quant); +; const uint32_t quant, +; const uint16_t *mpeg_matrices); ; ;----------------------------------------------------------------------------- @@ -340,10 +259,12 @@ push ecx push esi push edi + push ebx - mov edi, [esp + 12 + 4] ; coeff - mov esi, [esp + 12 + 8] ; data - mov eax, [esp + 12 + 12] ; quant + mov edi, [esp + 16 + 4] ; coeff + mov esi, [esp + 16 + 8] ; data + mov eax, [esp + 16 + 12] ; quant + mov ebx, [esp + 16 + 16] ; mpeg_quant_matrices xor ecx, ecx @@ -358,7 +279,7 @@ movq mm7, [mmx_div + eax * 8 - 8] ; divider ALIGN 16 -.loop +.loop: movq mm0, [esi + 8*ecx] ; mm0 = [1st] movq mm3, [esi + 8*ecx + 8] ; pxor mm1, mm1 ; mm1 = 0 @@ -371,15 +292,15 @@ psubw mm3, mm4 ; psllw mm0, 4 psllw mm3, 4 - movq mm2, [inter_matrix + 8*ecx] + movq mm2, [ebx + 512 + 8*ecx] psrlw mm2, 1 paddw mm0, mm2 - movq mm2, [inter_matrix_fix + ecx*8] + movq mm2, [ebx + 768 + ecx*8] pmulhw mm0, mm2 ; (level<<4 + inter_matrix[i]>>1) / inter_matrix[i] - movq mm2, [inter_matrix + 8*ecx + 8] + movq mm2, [ebx + 512 + 8*ecx + 8] psrlw mm2, 1 paddw mm3, mm2 - movq mm2, [inter_matrix_fix + ecx*8 + 8] + movq mm2, [ebx + 768 + ecx*8 + 8] pmulhw mm3, mm2 pmulhw mm0, mm7 ; mm0 = (mm0 / 2Q) >> 16 pmulhw mm3, mm7 ; @@ -398,13 +319,14 @@ cmp ecx, 16 jnz near .loop -.done +.done: pmaddwd mm5, [mmx_one] movq mm0, mm5 psrlq mm5, 32 paddd mm0, mm5 movd eax, mm0 ; return sum + pop ebx pop edi pop esi pop ecx @@ -412,7 +334,7 @@ ret ALIGN 16 -.q1loop +.q1loop: movq mm0, [esi + 8*ecx] ; mm0 = [1st] movq mm3, [esi + 8*ecx+ 8] pxor mm1, mm1 ; mm1 = 0 @@ -425,15 +347,15 @@ psubw mm3, mm4 ; psllw mm0, 4 psllw mm3, 4 - movq mm2, [inter_matrix + 8*ecx] + movq mm2, [ebx + 512 + 8*ecx] psrlw mm2, 1 paddw mm0, mm2 - movq mm2, [inter_matrix_fix + ecx*8] + movq mm2, [ebx + 768 + ecx*8] pmulhw mm0, mm2 ; (level<<4 + inter_matrix[i]>>1) / inter_matrix[i] - movq mm2, [inter_matrix + 8*ecx + 8] + movq mm2, [ebx + 512 + 8*ecx + 8] psrlw mm2, 1 paddw mm3, mm2 - movq mm2, [inter_matrix_fix + ecx*8 + 8] + movq mm2, [ebx + 768 + ecx*8 + 8] pmulhw mm3, mm2 psrlw mm0, 1 ; mm0 >>= 1 (/2) psrlw mm3, 1 ; @@ -452,9 +374,8 @@ jmp .done - ALIGN 16 -.q2loop +.q2loop: movq mm0, [esi + 8*ecx] ; mm0 = [1st] movq mm3, [esi + 8*ecx+ 8] pxor mm1, mm1 ; mm1 = 0 @@ -467,15 +388,15 @@ psubw mm3, mm4 ; psllw mm0, 4 psllw mm3, 4 - movq mm2, [inter_matrix + 8*ecx] + movq mm2, [ebx + 512 + 8*ecx] psrlw mm2, 1 paddw mm0, mm2 - movq mm2, [inter_matrix_fix + ecx*8] + movq mm2, [ebx + 768 + ecx*8] pmulhw mm0, mm2 ; (level<<4 + inter_matrix[i]>>1) / inter_matrix[i] - movq mm2, [inter_matrix + 8*ecx + 8] + movq mm2, [ebx + 512 + 8*ecx + 8] psrlw mm2, 1 paddw mm3, mm2 - movq mm2, [inter_matrix_fix + ecx*8 + 8] + movq mm2, [ebx + 768 + ecx*8 + 8] pmulhw mm3, mm2 psrlw mm0, 2 ; mm0 >>= 1 (/2) psrlw mm3, 2 ; @@ -493,6 +414,7 @@ jnz near .q2loop jmp .done +ENDFUNC ;----------------------------------------------------------------------------- @@ -500,7 +422,8 @@ ; uint32_t dequant_mpeg_intra_mmx(int16_t *data, ; const int16_t const *coeff, ; const uint32_t quant, -; const uint32_t dcscalar); +; const uint32_t dcscalar, +; const uint16_t *mpeg_matrices); ; ;----------------------------------------------------------------------------- @@ -523,7 +446,7 @@ psubw mm0, mm1 ; -> mm0 = abs(coeff[i]), mm1 = sign of coeff[i] movq mm2, mm7 ; mm2 = quant - pmullw mm2, [intra_matrix + 8*eax + 8*16 ] ; matrix[i]*quant. + pmullw mm2, [ebx + 8*eax + 8*16 ] ; matrix[i]*quant. movq mm6, mm2 pmulhw mm2, mm0 ; high of coeff*(matrix*quant) (should be 0 if no overflow) @@ -546,9 +469,12 @@ ALIGN 16 dequant_mpeg_intra_mmx: - mov edx, [esp+4] ; data - mov ecx, [esp+8] ; coeff - mov eax, [esp+12] ; quant + push ebx + + mov edx, [esp + 4 + 4] ; data + mov ecx, [esp + 4 + 8] ; coeff + mov eax, [esp + 4 + 12] ; quant + mov ebx, [esp + 4 + 20] ; mpeg_quant_matrices movq mm7, [mmx_mul_quant + eax*8 - 8] mov eax, -16 ; to keep ALIGNed, we regularly process coeff[0] @@ -556,7 +482,7 @@ pxor mm6, mm6 ; this is a NOP ALIGN 16 -.loop +.loop: movq mm0, [ecx+8*eax + 8*16] ; mm0 = c = coeff[i] movq mm3, [ecx+8*eax + 8*16 +8]; mm3 = c' = coeff[i+1] pxor mm1, mm1 @@ -565,7 +491,7 @@ movq mm2, mm7 ; mm2 = quant pcmpgtw mm4, mm3 ; mm4 = sgn(c') - pmullw mm2, [intra_matrix + 8*eax + 8*16 ] ; matrix[i]*quant + pmullw mm2, [ebx + 8*eax + 8*16 ] ; matrix[i]*quant pxor mm0, mm1 ; negate if negative pxor mm3, mm4 ; negate if negative @@ -581,7 +507,7 @@ pmulhw mm0, mm5 ; high of coeff*(matrix*quant) movq mm5, mm7 ; mm2 = quant - pmullw mm5, [intra_matrix + 8*eax + 8*16 +8] ; matrix[i+1]*quant + pmullw mm5, [ebx + 8*eax + 8*16 +8] ; matrix[i+1]*quant movq mm6, mm5 add eax,2 ; z-flag will be tested later @@ -613,7 +539,7 @@ ; deal with DC movd mm0, [ecx] - pmullw mm0, [esp+16] ; dcscalar + pmullw mm0, [esp + 4 + 16] ; dcscalar movq mm2, [mmx_32767_minus_2047] paddsw mm0, mm2 psubsw mm0, mm2 @@ -624,13 +550,18 @@ mov [edx], ax xor eax, eax + + pop ebx + ret +ENDFUNC ;----------------------------------------------------------------------------- ; ; uint32_t dequant_mpeg_inter_mmx(int16_t * data, ; const int16_t * const coeff, -; const uint32_t quant); +; const uint32_t quant, +; const uint16_t *mpeg_matrices); ; ;----------------------------------------------------------------------------- @@ -642,16 +573,20 @@ ALIGN 16 dequant_mpeg_inter_mmx: - mov edx, [esp+ 4] ; data - mov ecx, [esp+ 8] ; coeff - mov eax, [esp+12] ; quant + push ebx + + mov edx, [esp + 4 + 4] ; data + mov ecx, [esp + 4 + 8] ; coeff + mov eax, [esp + 4 + 12] ; quant + mov ebx, [esp + 4 + 16] ; mpeg_quant_matrices + movq mm7, [mmx_mul_quant + eax*8 - 8] mov eax, -16 paddw mm7, mm7 ; << 1 pxor mm6, mm6 ; mismatch sum ALIGN 16 -.loop +.loop: movq mm0, [ecx+8*eax + 8*16 ] ; mm0 = coeff[i] movq mm2, [ecx+8*eax + 8*16 +8] ; mm2 = coeff[i+1] add eax, 2 @@ -679,13 +614,13 @@ ; we're short on register, here. Poor pairing... movq mm4, mm7 ; (matrix*quant) - pmullw mm4, [inter_matrix + 8*eax + 8*16 -2*8] + pmullw mm4, [ebx + 512 + 8*eax + 8*16 -2*8] 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 + 8*16 -2*8 + 8] + pmullw mm4, [ebx + 512 + 8*eax + 8*16 -2*8 + 8] pcmpgtw mm5, [zero] paddusw mm0, mm5 @@ -729,4 +664,14 @@ xor word [edx + 2*63], ax xor eax, eax + + pop ebx + ret +ENDFUNC + + +%ifidn __OUTPUT_FORMAT__,elf +section ".note.GNU-stack" noalloc noexec nowrite progbits +%endif +