この投稿の追加投稿。
Gcc 4.4.7 にて下記の除算のみを行うソースをコンパイルして逆アセンブルすると除算は、SSE2の命令である"DIVSD" (*1 p.728)が出力されていることが確認できます。
-div.c-
#include <stdio.h>
int
main(void)
{
double a,b,c;
a=3.0;
b=0.0;
c=a/b;
return 0;
}
$ gcc -o div div.c
$ objdump -d div > div.d
-div.d のmainの一部-
40048f: f2 0f 10 45 e8 movsd -0x18(%rbp),%xmm0
400494: f2 0f 5e 45 f0 divsd -0x10(%rbp),%xmm0
400499: f2 0f 11 45 f8 movsd %xmm0,-0x8(%rbp)
前回投稿したコードは、x87 FPUのFPE(Floating Point Exception)のマスクを解除するものであり、当たり前ですがSSE2のFPEを解除しているわけではないので、mainの最後でdouble同士の除算をしてもSSE2の命令が出力されているのでFPEは発生しません。
今回は、SSE2のFPEのマスクを外すコードをメモ。
- sse2.c -
1 #include <stdio.h>
2
3 int
4 main(void)
5 {
6 double a,b,c;
7 unsigned char buff[512] __attribute__((aligned(16)));
8
9 a=3.0;
10 b=0.0;
11 c=1.0;
12
13 c = a/b;
14
15 asm volatile(
16 "fxsave %0" // get valueof mxcsr register
17 :"=m"(buff):);
18
19 printf("SSE2 FPE bit mask= %X\n", buff[25]);
20 buff[25] = buff[25] ^ 0x2;
21 printf("SSE2 FPE bit mask= %X\n", buff[25]);
22
23 asm volatile(
24 "fxrstor %0" // set operand to mxcsr register
25 : :"m"(*buff));
26
27 c = a/b;
28
29 return 0;
30 }
fxsave(*1 P.846)/fxstor(*1 P.843) は、指定されたメモリ領域から/にMXCSR(*1 P.230)というSSE2の浮動小数点演算時に用いる情報を保持するレジスターに/の値を保存する。
20行目で該当するビットをクリアすることで、ゼロ割によるFPEのマスクを外している。
$ gcc --o sse2 sse2.c
$ ./sse2
SSE2 FPE bit mask= 1F
SSE2 FPE bit mask= 1D
Floating exception (core dumped)
[補足]
ちなみに、-mfpmath=387 というオプションをつけてコンパイルするとx87 FPUの除算命令を出力する。
*1 Intel® 64 and IA-32 Architectures Software Developer’s Manual Combined Volumes: 1, 2A, 2B, 2C, 3A, 3B, and 3C
0 件のコメント:
コメントを投稿