3.11.3 浮点运算操作

3.11.3 浮点运算操作

图 3-49 描述了一组执行算术运算的标量 AVX2 浮点指令。每条指令有一个(S₁)或两个(S₁,S₂)源操作数,和一个目的操作数 D。第一个源操作数 S₁ 可以是一个 XMM 寄存器或一个内存位置。第二个源操作数和目的操作数都必须是 XMM 寄存器。每个操作都有一条针对单精度的指令和一条针对双精度的指令。结果存放在目的寄存器中。

单精度 双精度 效果 描述
vaddss vaddsd D ← S₂ + S₁ 浮点数加
vsubss vsubsd D ← S₂ - S₁ 浮点数减
vmulss vmulsd D ← S₂ × S₁ 浮点数乘
vdivss vdivsd D ← S₂ / S₁ 浮点数除
vmaxss vmaxsd D ← max(S₂, S₁) 浮点数最大值
vminss vminsd D ← min(S₂, S₁) 浮点数最小值
sqrtss sqrtsd D ← √S₁ 浮点数平方根

图 3-49 标量浮点算术运算。这些指令有一个或两个源操作数和一个目的操作数

来看一个例子,考虑下面的浮点函数:

double funct(double a, float x, double b, int i)
{
    return a*x - b/i;
}

x86-64 代码如下:

double funct(double a, float x, double b, int i)
a in %xmm0, x in %xmm1, b in %xmm2, i in %edi

1  funct:
       The following two instructions convert x to double
2      vunpcklps  %xmm1, %xmm1, %xmm1
3      vcvtps2pd  %xmm1, %xmm1
4      vmulsd     %xmm0, %xmm1, %xmm0    Multiply a by x
5      vcvtsi2sd  %edi, %xmm1, %xmm1     Convert i to double
6      vdivsd     %xmm1, %xmm2, %xmm2    Compute b/i
7      vsubsd     %xmm2, %xmm0, %xmm0    Subtract from a*x
8      ret                               Return

三个浮点参数 axb 通过 XMM 寄存器 %xmm0%xmm2 传递,而整数参数通过寄存器 %edi 传递。标准的双指令序列用以将参数 x 转换为双精度类型(第 2~3 行)。另一条转换指令用来将参数 i 转换为双精度类型(第 5 行)。该函数的值通过寄存器 %xmm0 返回。

练习题 3.53 对于下面的 C 函数,4 个参数的类型由 typedef 定义:

double funct1(arg1_t p, arg2_t q, arg3_t r, arg4_t s)
{
    return p/(q+r) - s;
}

编译时,GCC 产生如下代码:

double funct1(arg1_t p, arg2_t q, arg3_t r, arg4_t s)

1  funct1:
2      vcvtsi2ssq %rsi, %xmm2, %xmm2
3      vaddss     %xmm0, %xmm2, %xmm0
4      vcvtsi2ss  %edi, %xmm2, %xmm2
5      vdivss     %xmm0, %xmm2, %xmm0
6      vunpcklps  %xmm0, %xmm0, %xmm0
7      vcvtps2pd  %xmm0, %xmm0
8      vsubsd     %xmm1, %xmm0, %xmm0
9      ret

确定 4 个参数类型可能的组合(答案可能不止一种)。

练习题 3.54 函数 funct2 具有如下原型:

double funct2(double w, int x, float y, long z);

GCC 为该函数产生如下代码:

double funct2(double w, int x, float y, long z)
w in %xmm0, x in %edi, y in %xmm1, z in %rsi

1  funct2:
2      vcvtsi2ss  %edi, %xmm2, %xmm2
3      vmulss     %xmm1, %xmm2, %xmm1
4      vunpcklps  %xmm1, %xmm1, %xmm1
5      vcvtps2pd  %xmm1, %xmm2
6      vcvtsi2sdq %rsi, %xmm1, %xmm1
7      vdivsd     %xmm1, %xmm0, %xmm0
8      vsubsd     %xmm0, %xmm2, %xmm0
9      ret

写出 funct2 的 C 语言版本。