2014年5月22日木曜日
Unmask floating point exception
x86 なプロセッサ上のLinuxでは、浮動小数点同士の除算でゼロ割を行ってもSIGFPEは普通発生しない。これは、FPU control word*1 というFPUのレジスタ中のFloating point exception のマスク状態を表すフラグが立っているためである。
gfortran -ffpe-trap=zero というオプションを指定すると浮動小数点のゼロ割でSIGFPEが発生するようになる。今回は、gcc インラインアセンブラでFloating point exception のマスクを解除してみた。
#include <stdio.h>
int
main(void)
{
double a,b,c;
unsigned short int fctr;
a=3.0;
b=0.0;
c=1.0;
asm volatile(
"fstcw %w1\n\t" // get FPU control word
"fdiv %3,%2"
:"=&t"(c):"m"(fctr),"f"(a),"f"(b));
printf("c= %f FPU control word= %X\n", c, fctr);
fctr = fctr ^ 0x4;
printf("Value for FPU control word= %X\n", fctr);
asm volatile(
"fldcw %w1\n\t" // set operand to FPU control word
"fdiv %3,%2"
:"=&t"(c):"m"(fctr),"f"(a),"f"(b));
printf("c= %f FPU control word= %X\n", c, fctr);
return 0;
}
[実行結果]
$ ./a.out
c= inf FPU control word= 37F
Value for FPU control word= 37B
Floating exception (core dumped)
*1 Intel® 64 and IA-32 Architectures Software Developer’s Manual Combined Volumes: 1, 2A, 2B, 2C, 3A, 3B, and 3C p.p.189-190
登録:
コメントの投稿 (Atom)
0 件のコメント:
コメントを投稿