X86 如何为我的独立可引导代码启用SSE?

X86 如何为我的独立可引导代码启用SSE?,x86,sse,instruction-set,X86,Sse,Instruction Set,(这个问题最初是关于CVTSI2SD指令的,我认为它在奔腾M CPU上不起作用,但事实上,这是因为我使用的是自定义操作系统,需要手动启用SSE。) 我有一个奔腾M CPU和一个自定义操作系统,到目前为止没有使用SSE指令,但我现在需要使用它们 尝试执行任何SSE指令都会导致中断6,即非法操作码(在Linux中会导致SIGILL,但这不是Linux),在(从现在起我称之为IASDM)中也称为#UD-无效操作码(未定义的操作码) 编辑:Peter Cordes实际上找到了正确的原因,并为我指出了解决

(这个问题最初是关于
CVTSI2SD
指令的,我认为它在奔腾M CPU上不起作用,但事实上,这是因为我使用的是自定义操作系统,需要手动启用SSE。)

我有一个奔腾M CPU和一个自定义操作系统,到目前为止没有使用SSE指令,但我现在需要使用它们

尝试执行任何SSE指令都会导致中断6,即非法操作码(在Linux中会导致
SIGILL
,但这不是Linux),在(从现在起我称之为IASDM)中也称为#UD-无效操作码(未定义的操作码)

编辑:Peter Cordes实际上找到了正确的原因,并为我指出了解决方案,我在下面继续:


如果您正在运行一个不支持在上下文开关上保存XMM regs的古老操作系统,则不会设置其中一个机器控制寄存器中的SSE启用位

事实上,IASDM提到了这一点:

如果操作系统没有为SSE提供足够的系统级支持,则执行SSE或SSE2指令也会生成#UD

Peter Cordes向我指出了,其中描述了如何通过写入
CR0
CR4
控制寄存器来启用SSE:

clear the CR0.EM bit (bit 2) [ CR0 &= ~(1 << 2) ]
set the CR0.MP bit (bit 1) [ CR0 |= (1 << 1) ]
set the CR4.OSFXSR bit (bit 9) [ CR4 |= (1 << 9) ]
set the CR4.OSXMMEXCPT bit (bit 10) [ CR4 |= (1 << 10) ]

清除CR0.EM位(位2)[CR0&=~(1我建议您在有此类问题时咨询


手册中明确指出,
CVTSI2SD
是一条SSE2指令。

如果您运行的是不支持在上下文开关上保存XMM regs的古老或定制操作系统,则不会在机器控制寄存器中设置SSE启用位。在这种情况下,所有与XMM regs相关的指令都会出现故障

我花了几秒钟才找到,但解释了如何更改CR0和CR4,以允许SSE指令在裸机上运行,而无需
#UD


我对你的老问题的第一个想法是 您可能已经使用
-mavx
-march=sandybridge
或等效工具编译了您的程序,导致编译器发出所有内容的VEX编码版本

CVTSI2SD   xmm1, xmm2/m32         ; SSE2
VCVTSI2SD  xmm1, xmm2, xmm3/m32   ; AVX
有关链接,请参阅,包括英特尔insn set ref手册



相关:有一些关于如何检查AVX和AVX512支持的详细信息(这也引入了新的体系结构状态,因此操作系统必须设置一个位,否则硬件将出现故障)。这是从另一个角度讲的,但链接应该指出如何激活/禁用AVX支持。

“然而,奔腾M不识别CVTSI2SD”来源?导致崩溃的原因是什么?
SIGILL
(“非法指令”)或其他什么?请您在GDB下运行应用程序,并向我们提供
(GDB)的错误和输出disas/r
在坠机现场?你确定你实际上没有一个吗?你能在执行
mov-eax,1/cpuid
后发布
eax
的值吗?我使用的是一个旧的GCC,它似乎没有那种架构。我查看了程序集,还尝试通过
asm()直接插入指令
,所以这种情况发生的可能性很小。它是-mavx,oops。看看反汇编。如果它是
vcvt…
,并且你的程序因SIGILL而死亡,那么这是一个AVX问题。否则,你可能会得到一个SIGSEGV,而不是SIGILL。如果它是SIGILL,那么会发生一些奇怪的事情,你应该在gdb下运行它,所以它是正确的在发生故障的指令上执行ops。我尝试编译一些专门包含
CVTSI2SD
的汇编代码,以确保它是罪魁祸首,我得到了中断6。但是
CVTSI2SS
也发生了中断,因此这实际上是一个与SSE相关的问题。包含对
%xmmN
寄存器引用的指令不起作用k、 关于检测操作系统支持有一个答案。但是IIRC,Intel建议检测操作系统支持的方法是尝试运行SSE指令,看看它是否与#UD有关。是的,非常糟糕,尤其是对于库或其他东西,因为这迫使调用程序处理操作系统必须设置的机器控制寄存器SIGILL!IIRC甚至不能被非特权代码读取。@anol:我按照我的建议进行了编辑。希望这能吸引操作系统类型的专家帮助。当您尝试使用
mov cr
指令时,您可能想提及CPU处于什么状态。(实模式?32位保护模式?)CPUID报告支持的指令是什么?
less/proc/cpuinfo|grep flags
如果您在Linux上。@在手册中,您要阅读的部分是第3卷第13.1节,为SSE扩展提供操作系统支持。这一节对SSE支持必须做的事情有非常清楚的描述和列表。Michael,你肯定应该在你的答案中加入对这一部分的参考。