5. MMX2
MMX命令を拡張したものです. PIII, P4, AthlonなどのCPUで利用できます.
5.1 データ移動
パックド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];
[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;
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 種々の演算
srcとdestの平均を求めます. 平均は(a+b+1)/2という形の丸め処理が行われます. bは符号無し8bit, wは符号無し16bitです. 3D Now!命令にはオペコードは違いますがpavgusbというpavgbと同じ動作をする命令があります.
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'|
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 シャッフル演算
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) |
---|
レジスタ | 内容 |
mm0 | D3 | D2 | D1 | D0 |
mm1 | D3' | D2' | D1' | D0' |
↓ |
mm0 | Da' | Db' | Dc' | Dd'
|
SSEのshufps命令と違いsrcのみの本当のシャッフルをdestに書き込むことに注意してください. destの値には依存しません.
御意見は光成滋生<herumi@nifty.com>までお願いします