【发布时间】:2017-02-07 04:06:11
【问题描述】:
我的数据类型名为TVector,如下所示:
type
TVector = record
x,y,z,w : single;
end;
我有名为 v1 和 v2 的变量,其中包含以下数据:
v1.x:=1;
v1.y:=2;
v1.z:=3;
v1.w:=4;
v2.x:=5;
v2.y:=6;
v2.z:=7;
v2.w:=8;
两个变量都传递给方法如下:
function TSSEVectorOperation.add(const vect1: TVector; const vect2: TVector): TVector; assembler;
asm
...
addps xmm1, xmm2
movaps xmm0, xmm1
...
end;
当我使用 Lazarus IDE(在 Ubuntu 中)调试并进入 add() 方法时,我了解到最初 xmm0 - xmm3 寄存器包含来自 v1 和 v2 的值,顺序如下
xmm0 = {1,2,0,0}
xmm1 = {3,4,0,0}
xmm2 = {5,6,0,0}
xmm3 = {7,8,0,0}
我的问题是为什么 Free Pascal 会这样?为什么不按以下顺序?
xmm0 = {1,2,3,4}
xmm1 = {5,6,7,8}
或者为什么不让我手动为 xmm 寄存器赋值?比如:
movaps xmm0, vect1
movaps xmm1, vect2
【问题讨论】:
-
平台调用约定决定了这一点。
-
有道理。默认调用约定是
register,它会尽可能多地将数据传递给寄存器。 -
没有。在 x64 平台上定义了调用约定,而 register、stdcall、cdecl 等都被忽略了。
-
是的。如果您为 Windows 或 32 位目标编译,则调用约定会有所不同。
-
原因是 Linux 上的 x86-64 结构可以通过 XMM 寄存器中的值传递。可以在 here 找到 64 位 Linux ABI 调用约定。传递结构的规则的一个特点是不能在 XMM 寄存器中传递超过 64 位的数据。 2 个浮点数是 8 个字节或 64 位。前两个将在 XMM0 中传递,后两个将在 XMM1 中传递。
标签: assembly sse inline-assembly simd freepascal