5. MMX2

MMX命令を拡張したものです. PIII, P4, AthlonなどのCPUで利用できます.

5.1 データ移動

maskmovq mm0, mm1
パックド1byte命令として作用します. 各mm1データのMSBが1ならmm0のデータを[edi]に書き込みます. キャッシュの汚染を最小限にするそうです[多分ediの内容をキャッシュに保存しないということだと思う].
	/* 疑似コード */
	unsigned char edi[8], mm0[8], mm1[8];
	if( mm1[0] & 0x80 ) edi[0] = mm0[0];
	if( mm1[1] & 0x80 ) edi[1] = mm0[1];
	if( mm1[2] & 0x80 ) edi[2] = mm0[2];
	if( mm1[3] & 0x80 ) edi[3] = mm0[3];
	if( mm1[4] & 0x80 ) edi[4] = mm0[4];
	if( mm1[5] & 0x80 ) edi[5] = mm0[5];
	if( mm1[6] & 0x80 ) edi[6] = mm0[6];
	if( mm1[7] & 0x80 ) edi[7] = mm0[7];

movntq [mem64],mm?
[mem64]の値を一度も読むことが無く書き込むだけのときに使います. キャッシュの汚染を最小限にします.

pextrw reg32, mm?, imm8
pinsrw mm?, reg32, imm8
それぞれimm8により指定された16bitを抽出/挿入します.
	/* pextrw eax, mm0, selの疑似コード */
	mm0 = [ W3 : W2 : W1 : W0 ];
	sel &= 3;
	eax = (unsigned int)W_{sel};

	/* pinsrw mm0, eax, selの疑似コード */
	sel &= 3;
	W_{sel} = (unsigned short)eax;

pmovmskb reg32, mm?
mm0をパックド8bitとしてそれぞれのMSBをeaxの下位8bitにコピーします.
	/* pmovmskb eax, mm0の疑似コード */
	mm0 = [ B7 : B6 : B5 : B4 : B3 : B2 : B1 : B0 ];
	eax = (B7 >> 7) << 7
	     |(B6 >> 7) << 6
	     |(B5 >> 7) << 5
	     |(B4 >> 7) << 4
	     |(B3 >> 7) << 3
	     |(B2 >> 7) << 2
	     |(B1 >> 7) << 1
	     |(B0 >> 7) << 0

5.2 種々の演算

pavgb, pavgw
srcとdestの平均を求めます. 平均は(a+b+1)/2という形の丸め処理が行われます. bは符号無し8bit, wは符号無し16bitです. 3D Now!命令にはオペコードは違いますがpavgusbというpavgbと同じ動作をする命令があります.

psadbw
srcとdestを符号無し8bitとしてそれぞれの差の絶対値を求めた総和を返します[頼むからもうちょい分かりやすい名前にしてくれ].
	/* psadbw mm0, mm1の疑似コード */
	mm0 = [ B7 : B6 : B5 : B4 : B3 : B2 : B1 : B0 ];
	mm1 = [ B7': B6': B5': B4': B3': B2': B1': B0'];
	mm0 = |B7 - B7'| + |B6 - B6'| + |B5 - B5'| + |B4 - B4'|
	     +|B3 - B3'| + |B2 - B2'| + |B1 - B1'| + |B0 - B0'|

pmulhuw
srcとdestを符号無し16bitとしてそれぞれの積をもとめその上位16bitを返します.MMXにもともとあるpmullw, pmulhwは符号付き16bitとしての積を求めます. pmulluwがないのは何故?
	/* pmulhuw mm0, mm1の疑似コード */
	mm0 = [ W3 : W2 : W1 : W0 ];
	mm1 = [ W3': W2': W1': W0'];
	mm0 = [ (W3*W3')>>16 : (W2*W2')>>16 : (W1*W1')>>16 : (W0*W0')>>16 ];

5.3 最大 / 最小

pmaxsw, pminsw, pmaxub, pminub
最大, 最小を求めます. swは符号付き16bit, ubは符号無し8bitとして処理します.

5.4 シャッフル演算

pshufw dest, src, imm8
srcの4つの16bitデータの入れ替えを行います.
PACK(a,b,c,d)=(a<<6)+(b<<4)+(c<<2)+(d)とすると(a,b,c,dは2bitデータ)

pshufw mm0, mm1, PACK(a,b,c,d)
レジスタ内容
mm0D3D2D1D0
mm1D3'D2'D1'D0'
mm0Da'Db'Dc'Dd'

SSEのshufps命令と違いsrcのみの本当のシャッフルをdestに書き込むことに注意してください. destの値には依存しません.
御意見は光成滋生<herumi@nifty.com>までお願いします