;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; お約束 .586 .mmx .model flat _TEXT64 segment page public use32 'CODE' align 8 ;------------------------------------------------------------------- ; 定数 c_offset dq 00C000C000C000C000h adjust dq 00000f000f000f000fh _0000_ffff_0000_ffff dq 00000ffff0000ffffh _ffff_0000_ffff_0000 dq 0ffff0000ffff0000h ;------------------------------------------------------------------- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; yuv444_to_bgr_mmx - YUV -> RGB 変換コア ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;------------------------------------------------------------------- PUBLIC C _yuv444_to_bgr_mmx@16 ; void __stdcall yuv444_to_bgr_mmx( ; [esp + 4] = FRAME *top, ; [esp + 8] = FRAME *bottom, ; [esp +12] = unsigned char *out, ; [esp +16] = BGR_CONVERSION_PARAMETER *prm ; ) _yuv444_to_bgr_mmx@16 PROC ;------------------------------------------------------------------- ; 使用するレジスタ ; ; edi - 出力先アドレス ; esi - Y アドレス ; eax - U アドレス ; ebx - V アドレス ; ecx - 幅カウンタ ; edx - 行カウンタ ; ebp - esp 保存 ; ; total 28 byte ;------------------------------------------------------------------- ; 使用するローカル変数 ; ; [esp+ 8] work - 24 byte - 行終端処理作業領域 ; [esp+ 32] y_offset - 8 byte - Y 黒レベル ; [esp+ 40] y_gain - 8 byte - Y の増幅率 ; [esp+ 48] bu - 8 byte - U to Blue 変換係数 ; [esp+ 56] gu - 8 byte - U to Green 変換係数 ; [esp+ 64] gv - 8 byte - V to Green 変換係数 ; [esp+ 72] rv - 8 byte - V to Red 変換係数 ; ; ここまでは 8 byte alignment 保証する必要あり ; ; [esp+ 80] y_src - 4 byte - Y の行先頭アドレス ; [esp+ 84] u_src - 4 byte - U の行先頭アドレス ; [esp+ 88] v_src - 4 byte - V の行先頭アドレス ; [esp+ 92] y_src_next - 4 byte - 次の Y 先頭アドレス ; [esp+ 96] u_src_next - 4 byte - 次の U 先頭アドレス ; [esp+100] v_src_next - 4 byte - 次の V 先頭アドレス ; [esp+104] out - 4 byte - 出力先アドレス ; [esp+108] width/8 - 4 byte - 幅 / 8 ; [esp+112] (width%8)*3 - 4 byte - (幅 % 8) * 3 ; [esp+116] in_step*2 - 4 byte - 入力ステップ ; [esp+120] out_step - 4 byte - 出力ステップ ; ; total 124 + (alignment adjustment) ; ;------------------------------------------------------------------- ; レジスタの退避 push ebp push edi push esi push edx push ecx push ebx push eax ;------------------------------------------------------------------- ; ベースポインタにスタックアドレスを記憶 mov ebp, esp ;------------------------------------------------------------------- ; ローカル変数領域の確保 sub esp, 128 and esp, 0fffffff8h ;------------------------------------------------------------------- ; 変換係数の作成 mov eax, [ebp+28+16] ; prm movd mm0, [eax+4*4] ; prm->yo movd mm1, [eax+5*4] ; prm->yg movd mm2, [eax+6*4] ; prm->bu movd mm3, [eax+7*4] ; prm->gu movd mm4, [eax+8*4] ; prm->gv movd mm5, [eax+9*4] ; prm->rv punpckldq mm0, mm0 ; YO_YO punpckldq mm1, mm1 ; YG_YG punpckldq mm2, mm2 ; BU_BU punpckldq mm3, mm3 ; GU_GU punpckldq mm4, mm4 ; GV_GV punpckldq mm5, mm5 ; RV_RV pslld mm0, 7 psrad mm1, 3 psrad mm2, 3 psrad mm3, 3 psrad mm4, 3 psrad mm5, 3 packssdw mm0, mm0 ; YO_YO_YO_YO packssdw mm1, mm1 ; YG_YG_YG_YG packssdw mm2, mm2 ; BU_BU_BU_BU packssdw mm3, mm3 ; GU_GU_GU_GU packssdw mm4, mm4 ; GV_GV_GV_GV packssdw mm5, mm5 ; RV_RV_RV_RV movq [esp+32], mm0 movq [esp+40], mm1 movq [esp+48], mm2 movq [esp+56], mm3 movq [esp+64], mm4 movq [esp+72], mm5 ;------------------------------------------------------------------- ; 入出力パラメータ作成 mov edi, [eax+3*4] ; prm->out_step mov ebx, [eax+0*4] ; prm->width mov edx, [eax+1*4] ; prm->height mov ecx, [eax+2*4] ; prm->in_step mov eax, ebx ; prm->width shr ebx, 3 ; prm->width / 8 and eax, 7 ; prm->width % 8 mov [esp+108], ebx mov ebx, eax ; prm->width % 8 mov [esp+120], edi ; out_step shl ebx, 1 ; (prm->width % 8) * 2 add eax, ebx ; (prm->width % 8) * 3 mov [esp+112], eax ; mov edi, [ebp+28+8] ; bottom mov esi, [edi+3*4] ; bottom->y mov eax, [edi+4*4] ; bottom->u mov ebx, [edi+5*4] ; bottom->v add esi, ecx add eax, ecx add ebx, ecx mov [esp+ 92], esi ; y_src_next mov [esp+ 96], eax ; u_src_next mov [esp+100], ebx ; v_src_next ; shl ecx, 1 ; prm->in_step * 2 mov edi, [ebp+28+4] ; top mov esi, [edi+3*4] ; top->y mov eax, [edi+4*4] ; top->u mov ebx, [edi+5*4] ; top->v mov [esp+116], ecx ; in_step * 2 mov [esp+ 80], esi ; y_src mov [esp+ 84], eax ; u_src mov [esp+ 88], ebx ; v_src mov edi, [ebp+28+12] ; out mov [esp+104], edi ; out yuv444_to_bgr_mmx_next_line: ;------------------------------------------------------------------- ; 行処理開始 mov ecx, [esp+108] ; width / 8 yuv444_to_bgr_mmx_next_8pixel: ;------------------------------------------------------------------- ; 変換コア pxor mm7, mm7 movq mm0, [esi] ; Y7_Y6_Y5_Y4_Y3_Y2_Y1_Y0 movq mm1, [eax] ; U7_U6_U5_U4_U3_U2_U1_U0 movq mm2, [ebx] ; V7_V6_V5_V4_V3_V2_V1_V0 lea esi, [esi+8] lea eax, [eax+8] lea ebx, [ebx+8] movq mm3, mm0 movq mm4, mm1 movq mm5, mm2 punpcklbw mm0, mm7 ; 00Y3_00Y2_00Y1_00Y0 punpcklbw mm1, mm7 ; 00U3_00U2_00U1_00U0 punpcklbw mm2, mm7 ; 00V3_00V2_00V1_00V0 punpckhbw mm3, mm7 ; 00Y7_00Y6_00Y5_00Y4 punpckhbw mm4, mm7 ; 00U7_00U6_00U5_00U4 punpckhbw mm5, mm7 ; 00V7_00V6_00V5_00V4 psllw mm0, 7 psllw mm1, 7 psllw mm2, 7 psllw mm3, 7 psllw mm4, 7 psllw mm5, 7 psubw mm0, [esp+32] ; y_offset psubw mm3, [esp+32] ; y_offset pmulhw mm0, [esp+40] ; y_gain pmulhw mm3, [esp+40] ; y_gain paddw mm0, adjust paddw mm3, adjust paddw mm1, c_offset paddw mm2, c_offset paddw mm4, c_offset paddw mm5, c_offset movq mm6, mm1 movq mm7, mm2 pmulhw mm1, [esp+48] ; bu pmulhw mm2, [esp+64] ; gv pmulhw mm6, [esp+56] ; gu pmulhw mm7, [esp+72] ; rv paddw mm1, mm0 paddw mm2, mm0 paddw mm0, mm7 paddw mm2, mm6 psraw mm0, 4 ; R3_R2_R1_R0 psraw mm1, 4 ; B3_B2_B1_B0 psraw mm2, 4 ; G3_G2_G1_G0 movq mm6, mm4 movq mm7, mm5 pmulhw mm4, [esp+48] ; bu pmulhw mm5, [esp+64] ; gv pmulhw mm6, [esp+56] ; gu pmulhw mm7, [esp+72] ; rv paddw mm4, mm3 paddw mm5, mm3 paddw mm3, mm7 paddw mm5, mm6 psraw mm3, 4 ; R7_R6_R5_R4 psraw mm4, 4 ; B7_B6_B5_B4 psraw mm5, 4 ; G7_G6_G5_G4 ; ; レジスタ状況 ; ; mm0 - R3_R2_R1_R0 ; mm1 - B3_B2_B1_B0 ; mm2 - G3_G2_G1_G0 ; mm3 - R7_R6_R5_R4 ; mm4 - B7_B6_B5_B4 ; mm5 - G7_G6_G5_G4 ; ; ここから ; ; G2_B2_R1_G1_B1_R0_G0_B0 ; B5_R4_G4_B4_R3_G3_B3_R2 ; R7_G7_B7_R6_G6_B6_R5_G5 ; ; とするのが目的 ; packuswb mm0, mm3 ; R7R6R5R4R3R2R1R0 packuswb mm1, mm4 ; B7B6B5B4B3B2B1B0 packuswb mm2, mm5 ; G7G6G5G4G3G2G1G0 movq mm3, mm0 movq mm4, mm1 movq mm5, mm1 movq mm6, mm2 psrlq mm4, 8 ; 00B7B6B5B4B3B2B1 punpcklbw mm1, mm2 ; G3B3G2B2G1B1G0B0 x3x0 punpcklbw mm2, mm0 ; R3G3R2G2R1G1R0G0 5x2x punpcklbw mm0, mm4 ; B4R3B3R2B2R1B1R0 x4x1 punpckhbw mm5, mm6 ; G7B7G6B6G5B5G4B4 x9x6 punpckhbw mm6, mm3 ; R7G7R6G6R5G5R4G4 Bx8x punpckhbw mm3, mm4 ; 00R7B7R6B6R5B5R4 xAx7 movq mm4, _0000_ffff_0000_ffff movq mm7, _ffff_0000_ffff_0000 pand mm1, mm4 ; x3x0 pand mm2, mm7 ; 5x2x pand mm0, mm4 ; x4x1 pand mm5, mm4 ; x9x6 pand mm6, mm7 ; Bx8x pand mm3, mm4 ; xAx7 movq mm7, mm1 ; x4x1 movq mm4, mm5 ; x9x6 punpcklwd mm1, mm0 ; xx10 por mm7, mm2 ; 5320 por mm0, mm2 ; 5421 psrlq mm7, 16 ; x532 psrlq mm0, 32 ; 0054 punpcklwd mm5, mm3 ; xx76 por mm4, mm6 ; B986 por mm3, mm6 ; BA87 psrlq mm4, 16 ; xB98 psrlq mm3, 32 ; xxBA movd [edi], mm1 movd [edi+4], mm7 movd [edi+8], mm0 movd [edi+12], mm5 movd [edi+16], mm4 movd [edi+20], mm3 lea edi, [edi+24] ; ; 8 ピクセルの処理完了 ; dec ecx test ecx, ecx jnz yuv444_to_bgr_mmx_next_8pixel ; ; 幅 % 8 のチェック ; mov ecx, [esp+112] test ecx, ecx jz yuv444_to_bgr_mmx_line_end ;------------------------------------------------------------------- ; 幅 % 8 分の処理 ; ; 方針 - 同様に変換し、スタックに出力してから rep mosb でコピーする ; pxor mm7, mm7 movq mm0, [esi] ; Y7_Y6_Y5_Y4_Y3_Y2_Y1_Y0 movq mm1, [eax] ; U7_U6_U5_U4_U3_U2_U1_U0 movq mm2, [ebx] ; V7_V6_V5_V4_V3_V2_V1_V0 movq mm3, mm0 movq mm4, mm1 movq mm5, mm2 punpcklbw mm0, mm7 ; 00Y3_00Y2_00Y1_00Y0 punpcklbw mm1, mm7 ; 00U3_00U2_00U1_00U0 punpcklbw mm2, mm7 ; 00V3_00V2_00V1_00V0 punpckhbw mm3, mm7 ; 00Y7_00Y6_00Y5_00Y4 punpckhbw mm4, mm7 ; 00U7_00U6_00U5_00U4 punpckhbw mm5, mm7 ; 00V7_00V6_00V5_00V4 psllw mm0, 7 psllw mm1, 7 psllw mm2, 7 psllw mm3, 7 psllw mm4, 7 psllw mm5, 7 psubw mm0, [esp+32] ; y_offset psubw mm3, [esp+32] ; y_offset pmulhw mm0, [esp+48] ; y_gain pmulhw mm3, [esp+48] ; y_gain paddw mm0, adjust paddw mm3, adjust paddw mm1, c_offset paddw mm2, c_offset paddw mm4, c_offset paddw mm5, c_offset movq mm6, mm1 movq mm7, mm2 pmulhw mm1, [esp+48] ; bu pmulhw mm2, [esp+64] ; gv pmulhw mm6, [esp+56] ; gu pmulhw mm7, [esp+72] ; rv paddw mm1, mm0 paddw mm2, mm0 paddw mm0, mm7 paddw mm2, mm6 psraw mm0, 4 ; R3_R2_R1_R0 psraw mm1, 4 ; B3_B2_B1_B0 psraw mm2, 4 ; G3_G2_G1_G0 movq mm6, mm4 movq mm7, mm5 pmulhw mm4, [esp+48] ; bu pmulhw mm5, [esp+64] ; gv pmulhw mm6, [esp+56] ; gu pmulhw mm7, [esp+72] ; rv paddw mm4, mm3 paddw mm5, mm3 paddw mm3, mm7 paddw mm5, mm6 psraw mm3, 4 ; R7_R6_R5_R4 psraw mm4, 4 ; B7_B6_B5_B4 psraw mm5, 4 ; G7_G6_G5_G4 packuswb mm0, mm3 ; R7R6R5R4R3R2R1R0 packuswb mm1, mm4 ; B7B6B5B4B3B2B1B0 packuswb mm2, mm5 ; G7G6G5G4G3G2G1G0 movq mm3, mm0 movq mm4, mm1 movq mm5, mm1 movq mm6, mm2 psrlq mm4, 8 ; 00B7B6B5B4B3B2B1 punpcklbw mm1, mm2 ; G3B3G2B2G1B1G0B0 x3x0 punpcklbw mm2, mm0 ; R3G3R2G2R1G1R0G0 5x2x punpcklbw mm0, mm4 ; B4R3B3R2B2R1B1R0 x4x1 punpckhbw mm5, mm6 ; G7B7G6B6G5B5G4B4 x9x6 punpckhbw mm6, mm3 ; R7G7R6G6R5G5R4G4 Bx8x punpckhbw mm3, mm4 ; 00R7B7R6B6R5B5R4 xAx7 movq mm4, _0000_ffff_0000_ffff movq mm7, _ffff_0000_ffff_0000 pand mm1, mm4 ; x3x0 pand mm2, mm7 ; 5x2x pand mm0, mm4 ; x4x1 pand mm5, mm4 ; x9x6 pand mm6, mm7 ; Bx8x pand mm3, mm4 ; xAx7 movq mm7, mm1 ; x4x1 movq mm4, mm5 ; x9x6 punpcklwd mm1, mm0 ; xx10 por mm7, mm2 ; 5320 por mm0, mm2 ; 5421 psrlq mm7, 16 ; x532 psrlq mm0, 32 ; xx54 punpcklwd mm5, mm3 ; xx76 por mm4, mm6 ; B986 por mm3, mm6 ; BA87 psllq mm4, 16 ; 986x punpckldq mm1, mm7 ; 3210 punpckldq mm0, mm5 ; 7654 punpckhdq mm4, mm3 ; BA76 movq [esp+8], mm1 movq [esp+8+8], mm0 movq [esp+8+16], mm4 lea esi, [esp+8] rep movsb ; バイト単位で esi から edi へ ecx コピー ; ; 幅 % 8 部分終了 ; yuv444_to_bgr_mmx_line_end: ;------------------------------------------------------------------- ; 行処理の最後 mov edi, [esp+116] ; in_step * 2 mov ecx, [esp+80] mov esi, [esp+92] add ecx, edi mov [esp+80], esi mov [esp+92], ecx mov ecx, [esp+84] mov eax, [esp+96] add ecx, edi mov [esp+84], eax mov [esp+96], ecx mov ecx, [esp+88] mov ebx, [esp+100] add ecx, edi mov [esp+88], ebx mov [esp+100], ecx mov edi, [esp+104] add edi, [esp+120] mov [esp+104], edi dec edx test edx,edx jnz yuv444_to_bgr_mmx_next_line ;------------------------------------------------------------------- ; 後始末 mov esp, ebp pop eax pop ebx pop ecx pop edx pop esi pop edi pop ebp ret 16 ; _yuv444_to_bgr_mmx@16 ENDP ;------------------------------------------------------------------- ; 終了 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; chroma420i_to_422_mmx - インタレース 420 から 422 への補間 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; 基本方針: ; 16bit 精度で 4 並列計算させる ; (y*4+2) = ((y*2 ) * 5 + (y*2+2) * 3 )>> 3 ; (y*4+3) = ((y*2+1) * 7 + (y*2+3) * 1 )>> 3 ; (y*4+4) = ((y*2 ) * 1 + (y*2+2) * 7 )>> 3 ; (y*4+5) = ((y*2+1) * 3 + (y*2+3) * 5 )>> 3 ; 一つのループで、これを4ピクセル分計算する ;------------------------------------------------------------------- ; 定数 _3 dq 00003000300030003h _5 dq 00005000500050005h _7 dq 00007000700070007h ;------------------------------------------------------------------- PUBLIC C _chroma420i_to_422_mmx@12 ; void __stdcall chroma420i_to_422_mmx( ; [esp + 4] = unsigned char *data, ; [esp + 8] = int width, ; [esp +12] = int height ; ) ; _chroma420i_to_422_mmx@12 PROC ;------------------------------------------------------------------- ; 使用するレジスタ ; esi - 入力 ; edi - 出力 ; eax - ループカウンタ - 幅 >> 3 を入れ、dec していく ; ebx - 幅 ; ecx - 幅 x 3 - 4, レベル2ループインクリメント用(sub で使用) ; 補間例外時のループカウンタ(REP & MOVSD 使用) ; edx - ループカウンタ - 高さ / 4 - 2, dec していく ; ; 要するに、esp & ebp 以外全部使う。 ; レジスタ退避用のスタックは 24 バイト ;------------------------------------------------------------------- ; ローカル変数 ; IN_DEC [esp+4] 縦の入力元アドレスデクリメント。幅 x 2 + 幅 / 2 ; OUT_DEC [esp+8] 縦の出力先アドレスデクリメント。幅 x 4 + 幅 / 2 ; ; 全部で 8 byte ;------------------------------------------------------------------- ; 用途固定 MMX レジスタ ; mm4 - 0 ; mm5 - _3 ; mm6 - _5 ; mm7 - _7 ;------------------------------------------------------------------- ; レジスタ退避 push edi push esi push ecx push edx push ebx push eax ;------------------------------------------------------------------- ; 引数からのデータ受け取り mov edi, [esp+24+ 4]; メモリブロック先頭アドレス mov ebx, [esp+24+ 8]; 幅 mov edx, [esp+24+12]; 高さ ;------------------------------------------------------------------- ; ローカル変数用領域確保 sub esp, 8 ;------------------------------------------------------------------- ; ループパラメータ作成 mov eax, ebx mov ecx, ebx shl eax, 1 shr ecx, 1 add ecx, eax mov [esp+4], ecx add ecx, eax mov [esp+8], ecx ; 縦ループアドレスデクリメント値作成終了(ローカル変数としてストア) mov eax, ebx mov ecx, edx mov esi, edi sub ecx, 2 imul ecx, ebx lea edi, [edi+ecx] shr ecx, 1 sub ecx, ebx lea esi, [esi+ecx] shr eax, 1 ;------------------------------------------------------------------- ; 補間例外(最終2行単純コピー) cld mov ecx, eax shr ecx, 2 rep movsd; lea edi, [edi+eax] lea esi, [esi+eax] mov ecx, eax shr ecx, 2 rep movsd; ;------------------------------------------------------------------- ; ループパラメータ修正 sub edi, eax mov ecx, ebx shl ecx, 2 sub edi, ecx sub edi, ebx ; 出力アドレス修正完了 lea esi, [esi+eax] sub esi, ecx ; 入力アドレス修正完了 shr ecx, 1 add ecx, ebx sub ecx, 4 ; L2 ループアドレスインクリメント完成 shr edx, 2 sub edx, 1 ; L1 ループカウンタ設定完了 shr eax, 2 ; L2 ループカウンタ設定完了 ;------------------------------------------------------------------- ; 補間係数作成 pxor mm4, mm4 movq mm5, _3 movq mm6, _5 movq mm7, _7 ;------------------------------------------------------------------- ; メインループ(レベル1‐縦方向) chroma420i_to_422_loop_level1: ;------------------------------------------------------------------- ; メインループ(レベル2‐横方向) chroma420i_to_422_loop_level2: ;------------------------------------------------------------------- ; 補間コア(入出力込み) ; 使用可能レジスタ - mm0 - mm3 movd mm0, [esi]; 00000000_03020100 lea esi, [esi+ebx] movd mm1, [esi]; 00000000_13121110 lea esi, [esi+ebx] movd mm2, [esi]; 00000000_23222120 lea esi, [esi+ebx] punpcklbw mm0, mm4; 0003_0002_0001_0000 punpcklbw mm2, mm4; 0023_0022_0021_0020 movq mm3, mm2 pmullw mm2, mm7 paddw mm2, mm0 psrlw mm2, 3 pmullw mm0, mm6 pmullw mm3, mm5 paddw mm0, mm3 psrlw mm0, 3 packuswb mm0, mm2 movd mm3, [esi]; 00000000_33323130 ; 入力ステップ終了 - トップフィールド補間終了 ; 空きレジスタ - mm2 movd [edi], mm0 lea edi, [edi+ebx] psrlq mm0, 32 ; 空きレジスタ - mm2, mm0 punpcklbw mm1, mm4; 0013_0012_0011_0010 punpcklbw mm3, mm4; 0033_0032_0031_0030 movq mm2, mm1 pmullw mm1, mm7 paddw mm1, mm3 psrlw mm1, 3 pmullw mm2, mm5 pmullw mm3, mm6 paddw mm3, mm2 psrlw mm3, 3 packuswb mm1, mm3 ; ボトムフィールド補間終了 movd [edi], mm1; [OUT-1] lea edi, [edi+ebx] movd [edi], mm0; [OUT-2] lea edi, [edi+ebx] psrlq mm1, 32 movd [edi], mm1; [OUT-3] ; 出力ステップ終了 dec eax sub esi, ecx sub edi, ecx ;------------------------------------------------------------------- ; レベル2ループ終端チェック test eax, eax jnz chroma420i_to_422_loop_level2 ; レベル2ループパラメータ補正 dec edx sub esi, [esp+4] sub edi, [esp+8] mov eax, ebx shr eax, 3 ;------------------------------------------------------------------- ; レベル1ループ終端チェック test edx, edx jnz chroma420i_to_422_loop_level1 ;------------------------------------------------------------------- ; 後始末 add esp, 8 ; ローカル変数解放 pop eax; レジスタ復元 pop ebx pop edx pop ecx pop esi pop edi ret 12 ;------------------------------------------------------------------- _chroma420i_to_422_mmx@12 ENDP ;------------------------------------------------------------------- ; 終了 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; chroma420p_to_422_mmx - プログレッシブ 420 から 422 への補間 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; 基本方針: ; 2 ライン読み取り、2 ライン出力(8 ピクセルずつ処理) ; ; [o1] = ([i0] * 3 + [i1]) / 4 ; [o2] = ([i0] + [i1] * 3) / 4 ; ;------------------------------------------------------------------- PUBLIC C _chroma420p_to_422_mmx@12 ; void __stdcall chroma420p_to_422_mmx( ; [esp + 4] = unsigned char *data, ; [esp + 8] = int width, ; [esp +12] = int height ; ) ; _chroma420p_to_422_mmx@12 PROC ;------------------------------------------------------------------- ; 使用するレジスタ ; esi - 入力 ; edi - 出力 ; eax - 水平方向ループ、カウンタ: 幅 / 16 ; ebx - 幅 ; ecx - 水平方向ループ、アドレスインクリメント: 幅 - 8 ; 補間例外時、ループカウンタ: 幅 / 8 ; edx - 垂直方向ループカウンタ: 高さ / 2, dec してく ; ; esp & ebp 以外全部使う。 ; レジスタ退避用のスタックは 24 バイト ;------------------------------------------------------------------- ; ローカル変数 ; IN_DEC [esp+4] 縦の入力元アドレスデクリメント。幅 + 幅 / 2 ; OUT_DEC [esp+8] 縦の出力先アドレスデクリメント。幅 x 2 + 幅 / 2 ; ; 全部で 8 byte ;------------------------------------------------------------------- ; 用途固定 MMX レジスタ ; mm6 - 0003_0003_0003_0003 ; mm7 - 0 ;------------------------------------------------------------------- ; レジスタ退避 push edi push esi push ecx push edx push ebx push eax ;------------------------------------------------------------------- ; 引数からのデータ受け取り mov esi, [esp+24+ 4] ; メモリブロック先頭アドレス mov ebx, [esp+24+ 8] ; 幅 mov edx, [esp+24+12] ; 高さ ;------------------------------------------------------------------- ; ローカル変数用領域確保 sub esp, 8 ;------------------------------------------------------------------- ; ループパラメータ作成 mov ecx, ebx shr ecx, 1 add ecx, ebx mov [esp+4], ecx add ecx, ebx mov [esp+8], ecx ; 垂直方向ループ、アドレスデクリメント値作成終了 mov edi, esi mov ecx, edx imul ecx, ebx add edi, ecx shr ecx, 1 add esi, ecx sub edi, ebx sub esi, ebx ; 入出力アドレス初期値(補完例外用)作成完了 ;------------------------------------------------------------------- ; 補間係数作成 movq mm6, _3 pxor mm7, mm7 ;------------------------------------------------------------------- ; 補間例外(最終行単純コピー) cld mov ecx, ebx shr ecx, 3 rep movsd ;------------------------------------------------------------------- ; ループパラメータ修正 mov ecx, ebx mov eax, ebx shr edx, 1 shr eax, 4 sub ecx, 8 dec edx ; ループカウンタ及びアドレスインクリメント作成終了 sub esi, [esp+4] sub edi, [esp+8] ; 入出アドレス修正完了 ;------------------------------------------------------------------- ; メインループ(レベル1‐垂直方向) chroma420p_to_422_loop_level1: ;------------------------------------------------------------------- ; メインループ(レベル2‐水平方向) chroma420p_to_422_loop_level2: ;------------------------------------------------------------------- ; 補間コア(入出力込み) movq mm0, [esi] ; 07_06_05_04_03_02_01_00 add esi, ebx movq mm1, [esi] ; 17_16_15_14_13_12_11_10 movq mm2, mm0 movq mm3, mm1 punpcklbw mm0, mm7 ; 0003_0002_0001_0000 punpcklbw mm1, mm7 ; 0013_0012_0011_0010 punpckhbw mm2, mm7 ; 0007_0006_0005_0004 punpckhbw mm3, mm7 ; 0017_0016_0015_0014 movq mm4, mm0 movq mm5, mm2 pmullw mm0, mm6 pmullw mm2, mm6 paddw mm0, mm1 paddw mm2, mm3 psrlw mm0, 2 psrlw mm2, 2 packuswb mm0, mm2 pmullw mm1, mm6 pmullw mm3, mm6 paddw mm1, mm4 paddw mm3, mm5 psrlw mm1, 2 psrlw mm3, 2 packuswb mm1, mm3 movq [edi], mm0 add edi, ebx movq [edi], mm1 sub esi, ecx sub edi, ecx dec eax ;------------------------------------------------------------------- ; 水平方向ループ終端チェック test eax, eax jnz chroma420p_to_422_loop_level2 ; 水平方向ループパラメータ修正 dec edx sub esi, [esp+4] sub edi, [esp+8] mov eax, ebx shr eax, 4 ;------------------------------------------------------------------- ; レベル1ループ終端チェック test edx, edx jnz chroma420p_to_422_loop_level1 ;------------------------------------------------------------------- ; 後始末 add esp, 8; ローカル変数領域解放 pop eax; レジスタ復元 pop ebx pop edx pop ecx pop esi pop edi ret 12 ;------------------------------------------------------------------- _chroma420p_to_422_mmx@12 ENDP ;------------------------------------------------------------------- ; 終了 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; chroma422_to_444_mmx - 422 から 444 への補間 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; PUBLIC C _chroma422_to_444_mmx@12 ; void __stdcall chroma422_to_444_mmx( ; [esp + 4] = unsigned char *data, ; [esp + 8] = int width, ; [esp +12] = int height ; ) ; _chroma422_to_444_mmx@12 PROC ;------------------------------------------------------------------- ; 使用するレジスタ ; esi - 入力アドレス ; edi - 出力アドレス ; eax - ループカウンタ レベル 1 ; ebx - ループカウンタ レベル 2 ; ecx - 4 ; edx - 8 ; 早い話が esp & ebp 以外の全部、レジスタ退避サイズは 24 バイト ;------------------------------------------------------------------- ; ローカル変数 ; IN_INC - [esp+4] 縦ループ時入力元アドレスデクリメント。幅 / 2 ;------------------------------------------------------------------- ; 用途固定 MMX レジスタ ; mm7 - 0 ;------------------------------------------------------------------- ; レジスタ退避 push edi push esi push ecx push edx push ebx push eax ;------------------------------------------------------------------- ; 引数からのデータ受け取り mov esi, [esp+24+ 4]; *data mov ebx, [esp+24+ 8]; width mov eax, [esp+24+12]; height ;------------------------------------------------------------------- ; ローカル変数用領域確保 mov ecx, 4 sub esp, ecx ;------------------------------------------------------------------- ; ループパラメータ設定 mov edx, ebx imul edx, eax; width * height lea esi, [esi+edx] mov edi, esi shr ebx, 1 mov [esp+4], ebx sub esi, ebx mov edx, ecx; shl edx, 1 sub edi, edx; sub esi, ecx; shr ebx, 2 pxor mm7, mm7 ;------------------------------------------------------------------- ; メインループ - レベル1 - 縦 chroma422_to_444_loop_level1: ;------------------------------------------------------------------- ; 補間例外(右端 4 ピクセル) movd mm0, [esi]; 00000000_i3i2i1i0 dec ebx movq mm1, mm0 movq mm2, mm0 psrlq mm1, 24; 00000000_000000i3 psllq mm1, 32; 000000i3_00000000 por mm1, mm0; 000000i3_i3i2i1i0 psrlq mm1, 8; 00000000_i3i3i2i1 punpcklbw mm1, mm7; 00i3_00i3_00i2_00i1 punpcklbw mm0, mm7; 00i3_00i2_00i1_00i0 paddw mm1, mm0; 0o77_0o55_0o33_0o11 psrlw mm1, 1; 00o7_00o5_00o3_00o1 psllq mm1, 8; o700_o500_o300_o100 por mm1, mm0; o7_i3_o5_i2_o3_i1_o1_i0 movq [edi], mm1 sub esi, ecx sub edi, edx ;------------------------------------------------------------------- ; メインループ - レベル2 - 横 chroma422_to_444_loop_level2: ;------------------------------------------------------------------- ; 補間コア(入出力込み) movd mm0, [esi]; 00000000_i3i2i1i0 dec ebx movq mm1, mm2; 00000000_i7i6i5i4 movq mm2, mm0; psllq mm1, 32; i7i6i5i4_00000000 por mm1, mm0; i7i6i5i4_i3i2i1i0 psrlq mm1, 8; 00i7i6i5_i4i3i2i1 punpcklbw mm1, mm7; 00i4_00i3_00i2_00i1 punpcklbw mm0, mm7; 00i3_00i2_00i1_00i0 paddw mm1, mm0; 0o77_0o55_0o33_0o11 psrlw mm1, 1; 00o7_00o5_00o3_00o1 psllq mm1, 8; o700_o500_o300_o100 por mm1, mm0; o7_i3_o5_i2_o3_i1_o1_i0 movq [edi], mm1 sub esi, ecx sub edi, edx ;------------------------------------------------------------------- ; メインループ - レベル2 終端チェック test ebx, ebx jnz chroma422_to_444_loop_level2 ; レベル2ループパラメータ修正 dec eax mov ebx, [esp+4] sub esi, ebx shr ebx, 2; 幅 / 8 ;------------------------------------------------------------------- ; メインループ - レベル1 終端チェック test eax, eax jnz chroma422_to_444_loop_level1 ;------------------------------------------------------------------- ; 後始末 add esp, ecx; ローカル変数解放 pop eax; レジスタ復元 pop ebx pop edx pop ecx pop esi pop edi ret 12 ;------------------------------------------------------------------- _chroma422_to_444_mmx@12 ENDP ;------------------------------------------------------------------- ; 終了 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; _TEXT64 セグメントの終了 END ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;