【问题标题】:SSE register return with SSE disabledSSE 寄存器返回,SSE 禁用
【发布时间】:2009-10-12 18:31:17
【问题描述】:

我的情况如下:

  • 我正在为不允许 SSE 指令的内核编写代码
  • 我需要做浮点运算
  • 我正在为 x86_64 平台进行编译

这是一个说明问题的代码示例:

int
main(int argc, char** argv)
{
    double d = 0.0, dbase;
    uint64_t base_value = 300;

    d = (2200.0 - 1000.0)/(1000.0);
    dbase = d * base_value;
    printf("d = %f, dbase = %f\n", d, dbase);
    base_value = dbase;
    printf("base_value = %llu\n", (long long unsigned)base_value);
    return 0;
}

这里是 makefile 中的相关行:

CFLAGS +=   -mcmodel=kernel -mno-red-zone -mfpmath=387 -mno-sse -mno-sse2 -mno-mmx -mno-3dnow \
            -msoft-float -fno-asynchronous-unwind-tables -fno-omit-frame-pointer

运行构建时出现此错误:

SSE register return with SSE disabled

(错误指向d和base_value相乘的那一行)

知道我能做些什么来解决这个问题吗?删除 -mno-sse 不是一个选项,但似乎编译器应该能够生成非 sse 代码来进行乘法运算。

谢谢 内森

【问题讨论】:

  • gcc 可能无法处理这种情况,因为它假定所有 x86-64 处理器都有 SSE。
  • 这是否意味着没有人在 64 位版本的 FreeBSD 内核中乘以任何东西?
  • 我工作过的任何内核都倾向于尽可能避免浮点。
  • 是的。内核人员讨厌需要保存和恢复更多寄存器。
  • gcc 可以很好地执行 x87 数学运算(如果您告诉内核保存/恢复用户空间 x87 FPU 状态)。问题是将double 作为函数arg 传递,因为您正在编译一个在XMM 寄存器中传递double args 的调用约定。如果你省略了printf("d = %f, dbase = %f\n", d, dbase);,你可以编写使用 FP 数学的函数,即使是 -mno-sse:例如有关简单函数的 asm 输出,请参见 godbolt.org/g/oIM1rS

标签: c gcc floating-point sse


【解决方案1】:

听起来编译器正在调用库例程来为您执行浮点乘法(可能不使用 SSE),但正在尝试使用 ABI 进行调用,该调用具有在 SSE 中传递的返回值。显然,这是行不通的。

如果在你的内核中完全可以使用浮点,那么应该有一个特殊的运行时库来执行不使用通常的(用户态)参数传递和返回约定的软浮点操作。但是,据我所知,BSD 内核中不支持浮点。几年前肯定是这样。

您可能应该只询问 BSD 内核开发电子邮件列表是否可以使用浮点;我怀疑它会给你一个比 SO 更快更明确的答案。

【讨论】:

  • 我决定只使用定点算法(有问题的内核基于 FreeBSD 内核,但有很大的改变,所以我不确定任何官方邮件列表都会给出比“不要那样做”更好的答案。
  • 啊。很抱歉,没有比这更满意的答案了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-22
  • 1970-01-01
  • 2014-11-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多