3.11.5 在浮点代码中使用位级操作
3.11.5 在浮点代码中使用位级操作
有时,我们会发现 GCC 生成的代码会在 XMM 寄存器上执行位级操作,得到有用的浮点结果。图 3-50 展示了一些相关的指令,类似于它们在通用寄存器上对应的操作。这些操作都作用于封装好的数据,即它们更新整个目的 XMM 寄存器,对两个源寄存器的所有位都实施指定的位级操作。和前面一样,我们只对标量数据感兴趣,只想了解这些指令对目的寄存器的低 4 或 8 字节的影响。从下面的例子中可以看出,运用这些操作通常可以简单方便地操作浮点数。
| 单精度 | 双精度 | 效果 | 描述 |
|---|---|---|---|
vxorps |
vxorpd |
D ← S₂ ^ S₁ | 位级异或(EXCLUSIVE-OR) |
vandps |
vandpd |
D ← S₂ & S₁ | 位级与(AND) |
图 3-50 对封装数据的位级操作(这些指令对一个 XMM 寄存器中的所有 128 位进行布尔操作)
练习题 3.56 考虑下面的 C 函数,其中 EXPR 是用 #define 定义的宏:
double simplefun(double x) {
return EXPR(x);
}下面,我们给出了为不同的 EXPR 定义生成的 AVX2 代码,其中,x 的值保存在 %xmm0 中。这些代码都对应于某些对浮点数值有用的操作。确定这些操作都是什么。要理解从内存中取出的常数字的位模式才能找出答案。
1 vmovsd .LC1(%rip), %xmm1
2 vandpd %xmm1, %xmm0, %xmm0
3 .LC1:
4 .long 4294967295
5 .long 2147483647
6 .long 0
7 .long 0
1 vxorpd %xmm0, %xmm0, %xmm0
1 vmovsd .LC2(%rip), %xmm1
2 vxorpd %xmm1, %xmm0, %xmm0
3 .LC2:
4 .long 0
5 .long -2147483648
6 .long 0
7 .long 0