Click to See Complete Forum and Search --> : _MM_SHUFFLE question


swati24
April 16th, 2005, 05:12 AM
Hi,

This question is regarding the SSE macro function for shuffle operations. I don't understand it fully.

MSDN says that _MM_SHUFFLE(z,y,x,w) expands to :

(z << 6) | (y <<4) | (x << 2) | w

This macro is used in conjunction with SHUFPS or MMX instrinsic function _mm_shuffle_ps(m1, m2, int mask), where mask is replaced by the macro that acts on m1 and m2. m1 and m2 are 128 bit registers.

MSDN has the following example:

Let m1 be a : b : c : d
Let m2 be e : f : g : h

where each of the a,b,c,d,e,f,g,h are 32 bit single precision floating point values. a is the highest double word and d is the lowest double word. Similarly, e is the highest double word and h is the lowest double word.

Now, when the following function is performed on the m1 and m2 MMX registers:

_mm_shuffle_ps(m1,m2,_MM_SHUFFLE(1,0,3,2))

we get

m3 g : h : a : b

-------------
Working

I tried to work this example myself but couldn't arrive at the right answer.

1 << 6 gives 0100 0000
0 << 4 gives 0000 0000
3 << 2 gives 0000 1100
2 gives 0000 0010

Bitwise OR operation gives 0100 1110

If we apply this mask on m1 and m2 how do we end up with m3? What am I doing wrong here. Any insights will be most helpful.

Thank you
Swati

Hobson
April 16th, 2005, 05:42 AM
According to Intel Instruction Reference Manual:


SHUFPS—Shuffle Single-FP operations
FP_SELECT = (imm8 >> 0) AND 0X3;
IF (FP_SELECT = 0) THEN
DEST[31-0] = DEST[31-0];
ELSE
IF (FP_SELECT = 1) THEN
DEST[31-0] = DEST[63-32];
ELSE
IF (FP_SELECT = 2) THEN
DEST[31-0] = DEST[95-64];
ELSE
DEST[31-0] = DEST[127-96];
FI
FI
FI

FP_SELECT = (imm8 >> 2) AND 0X3;
IF (FP_SELECT = 0) THEN
DEST[63-32] = DEST[31-0];
ELSE
IF (FP_SELECT = 1) THEN
DEST[63-32] = DEST[63-32];
ELSE
IF (FP_SELECT = 2) THEN
DEST[63-32] = DEST[95-64];
ELSE
DEST[63-32] = DEST[127-96];
FI
FI
FI

FP_SELECT = (imm8 >> 4) AND 0X3;
IF (FP_SELECT = 0) THEN
DEST[95-64] = SRC/m128[31-0];
ELSE
IF (FP_SELECT = 1) THEN
DEST[95-64] = SRC/m128 [63-32];
ELSE
IF (FP_SELECT = 2) THEN
DEST[95-64] = SRC/m128 [95-64];
ELSE
DEST[95-64] = SRC/m128 [127-96];
FI
FI
FI

FP_SELECT = (imm8 >> 6) AND 0X3;
IF (FP_SELECT = 0) THEN
DEST[127-96] = SRC/m128 [31-0];
ELSE
IF (FP_SELECT = 1) THEN
DEST[127-96] = SRC/m128 [63-32];
ELSE
IF (FP_SELECT = 2) THEN
DEST[127-96] = SRC/m128 [95-64];
ELSE
DEST[127-96] = SRC/m128 [127-96];
FI
FI
FI


This is not very complicated instruction, all it does is that it decomposites 8bit mask to 4 2bit numbers, and selects appropriate fragments from appropriate source operands and places them in appropriate places in dest operand. There is no shifting\xoring\anding or any other bit logic magic.

Hob

swati24
April 16th, 2005, 05:46 AM
I should have included the URL for the MSDN explanation of _MM_SHUFFLE, here it is:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vcrefmacrofunctionforshuffleusingstreamingsimdextensions.asp

swati24
April 16th, 2005, 05:59 AM
Thank you Hobson. That was very useful. It is a simple selection operation of the operands m1 and m2. So, _MM_SHUFFLE(z,y,x,w) selects x&w 32 bit double words from m1 and z&y from m2. How simple!!.

Thanks
Swati

Hobson
April 16th, 2005, 06:10 AM
Yes, it is simple, however, one little very formal suggestion:
_MM_SHUFFLE(z,y,x,w) does not select anything, this macro just creates a mask. SHUFPS instruction (or _mm_shuffle_ps wrapper function) performs selection, using mask created by _MM_SHUFFLE macro.

Hob