2011-11-26 291 views
1

对不起,我没有一个好的标题...混淆关于XMM寄存器的位图

我读这个线程:Vector Matrix Multiplication In SSE

楼主有以下代码

// xmm0 = (v0,v1,v2,v3) 
movups xmm0, [eax] 

// xmm0 = (v0,v0,v0,v0) 
// xmm1 = (v1,v1,v1,v1) 
// xmm2 = (v2,v2,v2,v2) 
// xmm3 = (v3,v3,v3,v3) 
shufps xmm3, xmm0, 255 
shufps xmm2, xmm0, 170 
shufps xmm1, xmm0, 85 
shufps xmm0, xmm0, 0 

有人说如下:

但是根据手册确实发生了什么:(a,b,c,d)意思是一个位s 0至31,b是位32到63等

// xmm0 = (v0,v1,v2,v3) 
movups xmm0, [eax] 

// xmm0 = (v0, v0, v0, v0) 
shufps xmm0, xmm0, 0 

这是有意义的,因为我在线性阵列模型[elt0,ELT1,ELT2,....] elt0是阵列[0 ]。

令我困惑的是,根据手册xmm寄存器的位图是[127 ... 0](见下图)。

我就像看着位图的原始海报,认为[elt0,elt2,elt3,elt4]的最左端是位“11”。

所以,如果我想XMM0只包含V0

shufps xmm0, xmm0, 0xFF // 11 11 11 11 === 0xFF 

哪个解释是正确的?

enter image description here

回答

7

可能有一些混乱,因为在XMM寄存器位(和BTW所有其它寄存器)进行编号从右到左,也就是最低位是在右边,最高位在左边:

xmm0 = [bit 127, bit 126, ..., bit 1, bit 0] 

如果考虑XMM寄存器的内容,32位双字,他们还安排从右至左:

xmm0 = [dword 3, dword 2, dword 1, dword 0] 

这种混乱的来源是,如果你有在存储器

float A[4] = { 0.0f, 1.0f, 2.0f, 3.0f }; 

和加载这个数组xmm寄存器中的阵列中,元件出现在以相反的顺序对xmm寄存器中:

; xmm0 = (A3 = 3.0f, A2 = 2.0f, A1 = 1.0f, A0 = 0.0f) after the load 
movups xmm0, [A] 

因此,第一个DWORD到所有双字复制XMM寄存器的正确方法是

shufps xmm0, xmm0, 0 

另外,如果你想要做一个浮动的负载和广播到所有XMM寄存器的元素,出于性能考虑,最好是使用

; MOVSS can be much faster than MOVUPS, and is never slower 
; Load A[0] into low dword of xmm0 
movss xmm0, [A] 
; Copy low dword of xmm0 to all dwords of xmm0 
shufps xmm0, xmm0, 0 

AVX指令集(支持最近英特尔的Sandy Bridge和AMD推土机CPU)的具有特殊指令VBROADCASTSS WHI CH执行负载和广播:

; xmm0 = (A[0], A[0], A[0], A[0]) after execution of vbroadcastss 
vbroadcastss xmm0, [A] 

SSE3指令集包括了类似的指令MOVDDUP,然而,仅适用于双打

const double B = 2.718281828459045; 

; xmm0 = (2.718281828459045, 2.718281828459045) after execution of movddup 
movddup xmm0, [B] 
+0

非常感谢你。它有助于。 :) – CppLearner