X86 endianness如何使用SIMD寄存器?

X86 endianness如何使用SIMD寄存器?,x86,sse,endianness,simd,X86,Sse,Endianness,Simd,我正在研究整数和SSE,对于endianness如何影响数据进出寄存器,我感到非常困惑 我最初的理解是错误的 最初我的理解如下。如果我有一个4字节整数的数组,那么内存的布局如下,因为x86体系结构是小端的: 0D 0C 0B 0A 1D 1C 1B 1A 2D 2C 2B 2A .... nD nC nB nA 其中字母A、B、C和D索引整数元素中的字节,数字索引元素 在XMM寄存器中,我的理解是四个整数的布局如下: 0A 0B 0C 0D 1A 1B 1C 1D 2A 2B 2C 2D 3A

我正在研究整数和SSE,对于endianness如何影响数据进出寄存器,我感到非常困惑

我最初的理解是错误的 最初我的理解如下。如果我有一个4字节整数的数组,那么内存的布局如下,因为x86体系结构是小端的:

0D 0C 0B 0A 1D 1C 1B 1A 2D 2C 2B 2A .... nD nC nB nA
其中字母
A
B
C
D
索引整数元素中的字节,数字索引元素

在XMM寄存器中,我的理解是四个整数的布局如下:

0A 0B 0C 0D 1A 1B 1C 1D 2A 2B 2C 2D 3A 3B 3C 3D
然而,我很确定这张照片是错误的,原因有几个。第一个是关于
mm_load_si128
内在函数的文档,它应该适用于任何整数数据,但在上图中只适用于一个字大小。类似地,也有。最后,我看到人们编写如下代码:

__declspec(align(16)) int32_t A[N];
__m128i* As = (__m128i*)A;
可能正确的图片 维基百科关于endianness的文章说,我应该考虑内存地址从右向左递增。那么下面这张图片怎么样

nA nB nC nD ... 2A 2B 2C 2D 1A 1B 1C 1D 0A 0B 0C 0D
然后在登记册中:

3A 3B 3C 3D 2A 2B 2C 2D 1A 1B 1C 1D 0A 0B 0C 0D

这只是一个解释的问题。我们从左到右读/写数字,从最高数字到最低数字。因此,对于一个32位的数字,其最高字节是a,然后是B,然后是C,最低字节是D,我们将读/写ABCD。我们对128位整数做同样的表示

3A3B3C3D 2A2B2C2D 1A1B1C1D 0A0B0C0D
但是在一个小小的endian系统中,它读写从最低地址到最高地址的数字,就像这样

0D0C0B0A 1D1C1B1A 2D2C2B2A 3D3C3B3A
对于16位整数,这是相同的逻辑。我们可以把它读/写为

7A7B 6A6B 5A5B 4A4B 3A3B 2A2B 1A1B 0A0B
而little endian计算机将其从最低地址读取/存储为

0B0A 1B1A 2B2A 3B3A 4B4A 5B5A 6A6B 7B7A
这就是为什么在128位寄存器中只有一条读取/写入32位、16位和8字节整数的指令:即movdqa和movaps(或未对齐的变体movdqu和movups)。

详细说明,SIMD实现中必然存在隐式的endianness,由于存在以下说明:

  • 从内存读取或写入128位SIMD寄存器。由于必须始终通过字节偏移量访问内存(无论指令或它存储或获取的字节数),并且随后可以通过其他非SIMD方式进行检查,
    movaps
    movdqa
    movdqu
    ,等等。指令本身就意味着结束性
  • 使用指令索引向量的元素,如
    pshufd
    ,甚至使用使用整数索引选择元素的
    pshufb
    运行时变量索引。这意味着元素具有类似地址的内容,而宽元素包含多个可独立寻址的窄元素。(当然不是内存地址空间的一部分,但与标量寄存器不同的是,我们有第二种方法来讨论宽元素中的左/右移位以外的位置。这与内存的端性问题相同。)
    寄存器中元素的索引被选择为匹配内存中的顺序(小尾端),但可能有所不同
  • 使用
    pslld
    psrld
    或整个向量字节移位等,在SIMD寄存器的字节边界上移位。请注意,跨越“字节边界”包括单个
    dword
    qword
    组件内,因为(出于前一点中提到的相同原因),寄存器随后可以成像到内存中。整个向量的字节移位将一个字的低字节与相邻字的高字节分组,其方式取决于端度
  • 只需重新解释组件大小(
    byte
    word
    dword
    ,或
    qword
    )这是一个现有的SIMD登记器内容的模拟。这是一个类似于在内存中读取代码“字节> dWord/代码>的字节:它们有一个顺序。使用<代码> pSUFD 围绕QQuffle需要在选择洗牌控件时考虑到字节数,以保持正确的高:低成对的DWORD分组在正确的顺序。
所以,如果你从来没有做过这些事情,也就是说你只使用SIMD内存映像和SIMD寄存器,匹配组件大小,不检查内存,并且在这些SIMD寄存器上的操作中保持一致的组件大小,那么你就不必担心SIMD端性。否则,继续读

既然我们知道SIMD有一个endianness,那它是什么呢?我们已经知道Intel架构是,意思是
word
dword
,和
qword
(分别是16位、32位和64位内存访问)递归交换。例如,存储单个
qword
会交换其两个
DWORD
的存储,每个DWORD都交换其两个
,每个字都交换其两个
字节
。这会导致CPU寄存器的内存映像总体上具有反转的
字节
顺序

为了与在相同大小上运行的非SIMD指令兼容,SIMD寄存器的每个单独组件的内存映像对于每个组件大小都应与现有的(小端)内存映像位相同格式。
word
dword
qword
访问之前存在的非SIMD指令表示硬约束,这些SIMD组件必须显示小端图像

但是对于128位内存访问,没有预先的非SIMD指令,因此对
dqword
SIMD寄存器本身的
(qword,qword)
布局没有预先的约束。这就留下了一个可能的问题:递归小端交换模式是否存在(
word
dword
qword