我遇到了一个有趣的情况,代码如下:

    static void DivideByZero() {
      // volatile to prevent compiler optimizations.
      volatile float zero = 0.0f;
      volatile float result __attribute__((unused)) = 123.0f / zero;
    }
  DivideByZero();
  int raised = fetestexcept(FE_DIVBYZERO | FE_OVERFLOW);
  ASSERT_TRUE((raised & FE_DIVBYZERO) != 0);

当我使用KVM支持运行qemu设备时,得到了以下结果:
 FE_DIVBYZERO !=0; //and it's ok

但是当我运行同一个源而不支持KVM时:
 FE_DIVBYZERO ==0; //and it's not ok

据我所知,这种情况会发生,因为在mxcsr中没有设置寄存器位(div by zero)。但我不明白为什么这一点没有设定。
有什么想法吗?
更新:
基于qemu的android仿真器也出现了同样的情况。
emulator -avd test -qemu

返回:feu divbyzero!=0;
emulator -avd test -qemu -disable-kvm

返回:feu divbyzero==0;

最佳答案

MXCSR寄存器在
Intel® 64 and IA-32 Architectures Software Developer’s Manual
在现代x86处理器上,编译器使用与指令相同的资源将浮点操作映射为scalarsimd。
vector (SSE)寄存器控制MXCSRscalar浮点指令的操作。我在下面包含了描述MXCSR的相关部分。vector (SSE)是除以零掩码,如果清除(0),则当检测到除以零时,CPU将引发异常。当您在虚拟机中运行时,异常被“虚拟化”,它们由“虚拟机管理程序”处理,在您的情况下是KVM。然后,管理程序决定是否将异常反映回来宾虚拟机。我的理论是清除除以零掩码,引发异常,kvm和/或qemu正在清除指示发生了除以零异常的标志MXCSR[9],并恢复虚拟机。因此,这可能是kvm/qemu中的一个bug。
您可以在MXCSR[2]之前发出fegetexcept(),以确定被零除的异常是否被屏蔽(1)或不被屏蔽(0)。如果它没有被屏蔽,那么您可以使用fedisableexcept()来屏蔽它。

08-28 10:17