android - Qemu,除以零,mxcsr 寄存器

标签 android c floating-point qemu kvm

我用下面的代码遇到了一个有趣的情况:

    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 中未设置寄存器位(除以零)。但是我不明白为什么没有设置这个位。 有任何想法吗?

更新:
同样的情况也发生在基于 qemu 的 android 模拟器上。

emulator -avd test -qemu  

返回:FE_DIVBYZERO !=0;

emulator -avd test -qemu -disable-kvm

返回:FE_DIVBYZERO ==0;

最佳答案

MXCSR 寄存器在 Intel® 64 and IA-32 Architectures Software Developer’s Manual

在现代 x86 处理器上,编译器将浮点运算映射为 scalar SIMD,使用与vector (SSE) 指令相同的资源。

MXCSR 寄存器控制着scalarvector (SSE) 浮点指令的操作。我在下面包含了描述 MXCSR 的相关部分。 MXCSR[9] 是除以零掩码,如果清除 (0) 那么当检测到除以零时 CPU 将引发异常。当您在虚拟机中运行时,异常被“虚拟化”,它们由“管理程序”处理,KVM在你的情况下。然后管理程序决定是否将异常反射(reflect)回客户虚拟机。我的理论是除以零掩码被清除,引发异常,KVM 和/或 QEMU 正在清除指示发生除以零异常的标志 MXCSR[2] 并恢复你的虚拟机。因此,这可能是 KVM/QEMU 中的错误。

你可以发出 fegetexcept()DivideByZero() 之前查明除以零异常是否被屏蔽 (1) 或不屏蔽 (0)。如果它没有被屏蔽,那么你可以使用 fedisableexcept()掩盖它。

MXCSR Control/Status Register

关于android - Qemu,除以零,mxcsr 寄存器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15134189/

相关文章:

OpenCV 从二进制创建浮点 Mat

android - 包含许多 Activity 的滑动菜单

c++ - 在 C++ 中读取 Lua 嵌套表

c++ - 可以在没有 epsilon 的情况下将 float 与 0.0 进行比较吗?

c - 'For' 中的 'If' 使游戏崩溃 - C 语言

c 使用结构指针数组写入和读取文件

javascript - JS 智能舍入小数

Android 应用程序在方向更改时重置,最佳处理方式?

android - 如何在 Android Studio/IntelliJ 中导入 Maven 依赖项?

java - 我如何在Android上粘贴一些行文本不会出错