<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-Hans-CN">
	<id>http://wiki.foofun.cn//index.php?action=history&amp;feed=atom&amp;title=SSE</id>
	<title>SSE - 版本历史</title>
	<link rel="self" type="application/atom+xml" href="http://wiki.foofun.cn//index.php?action=history&amp;feed=atom&amp;title=SSE"/>
	<link rel="alternate" type="text/html" href="http://wiki.foofun.cn//index.php?title=SSE&amp;action=history"/>
	<updated>2026-04-05T02:28:51Z</updated>
	<subtitle>本wiki上该页面的版本历史</subtitle>
	<generator>MediaWiki 1.37.1</generator>
	<entry>
		<id>http://wiki.foofun.cn//index.php?title=SSE&amp;diff=1019&amp;oldid=prev</id>
		<title>Zhang3：创建页面，内容为“{{Floats}} ''' 流式单指令多数据扩展 (SSE-Streaming SIMD Extensions) '''  == Streaming SIMD Extensions (SSE) == === 简介 === 奔腾III中引入了SSE，并为英特尔指令集额外提供了70条指令。  SSE指令可以帮助增加由于单指令，多数据 (SIMD) 指令的数据。  这些指令可以在多个数据上并行执行公共表达式。    SSE附带8个(64位模式下为16个)XMM寄存器(XMM0-7(15))，它们是128位寄存器。…”</title>
		<link rel="alternate" type="text/html" href="http://wiki.foofun.cn//index.php?title=SSE&amp;diff=1019&amp;oldid=prev"/>
		<updated>2022-03-24T09:14:17Z</updated>

		<summary type="html">&lt;p&gt;创建页面，内容为“{{Floats}} &amp;#039;&amp;#039;&amp;#039; 流式单指令多数据扩展 (SSE-Streaming SIMD Extensions) &amp;#039;&amp;#039;&amp;#039;  == Streaming SIMD Extensions (SSE) == === 简介 === 奔腾III中引入了SSE，并为英特尔指令集额外提供了70条指令。  SSE指令可以帮助增加由于单指令，多数据 (SIMD) 指令的数据。  这些指令可以在多个数据上并行执行公共表达式。    SSE附带8个(64位模式下为16个)XMM寄存器(XMM0-7(15))，它们是128位寄存器。…”&lt;/p&gt;
&lt;p&gt;&lt;b&gt;新页面&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{Floats}}&lt;br /&gt;
''' 流式单指令多数据扩展 (SSE-Streaming SIMD Extensions) '''&lt;br /&gt;
&lt;br /&gt;
== Streaming SIMD Extensions (SSE) ==&lt;br /&gt;
=== 简介 ===&lt;br /&gt;
奔腾III中引入了SSE，并为英特尔指令集额外提供了70条指令。  SSE指令可以帮助增加由于单指令，多数据 (SIMD) 指令的数据。  这些指令可以在多个数据上并行执行公共表达式。  &lt;br /&gt;
&lt;br /&gt;
SSE附带8个(64位模式下为16个)XMM寄存器(XMM0-7(15))，它们是128位寄存器。  某些SSE指令 (movntdqa，movdqa，movdqu等...) 可以在单个操作中从内存中加载16个字节或将16个字节存储到内存中。  此外，SSE还引入了一些非时态提示指令（movntdqa和movntdq），允许将一次性内存位置存储在非时态内存中，以便这些位置引用不会污染小型片上缓存。  &lt;br /&gt;
&lt;br /&gt;
由于此更改添加了新的寄存器，因此默认禁用，因为当时的典型操作系统还不能将这些寄存器保存在任务交换机上。 为了支持SSE，您需要实现单独的代码路径来保存和恢复SSE状态 (因为这些指令将在不支持它的处理器上导致异常)，以及新异常的处理程序。 之后，您可以告诉CPU在userland任务中启用SSE使用。&lt;br /&gt;
&lt;br /&gt;
===检查SSE===&lt;br /&gt;
要检查SSE CPUID.01h: 需要设置EDX.SSE[bit25]&lt;br /&gt;
&amp;lt;source lang=&amp;quot;asm&amp;quot;&amp;gt;&lt;br /&gt;
mov eax, 0x1&lt;br /&gt;
cpuid&lt;br /&gt;
test edx, 1&amp;lt;&amp;lt;25&lt;br /&gt;
jz .noSSE&lt;br /&gt;
;SSE is available&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===增加支持===&lt;br /&gt;
为了允许执行SSE指令而不生成#UD，我们需要更改CR0和CR4寄存器。 &lt;br /&gt;
 清除 CR0.EM bit (bit 2) [ CR0 &amp;amp;= ~(1 &amp;lt;&amp;lt; 2) ]&lt;br /&gt;
 设置 CR0.MP bit (bit 1) [ CR0 |= (1 &amp;lt;&amp;lt; 1) ]&lt;br /&gt;
 设置 CR4.OSFXSR bit (bit 9) [ CR4 |= (1 &amp;lt;&amp;lt; 9) ]&lt;br /&gt;
 设定 CR4.OSXMMEXCPT bit (bit 10) [ CR4 |= (1 &amp;lt;&amp;lt; 10) ]&lt;br /&gt;
&lt;br /&gt;
这是一个asm示例:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;asm&amp;quot;&amp;gt;&lt;br /&gt;
;now enable SSE and the like&lt;br /&gt;
mov eax, cr0&lt;br /&gt;
and ax, 0xFFFB		; 清除协处理器仿真CR0.EM&lt;br /&gt;
or ax, 0x2			;设置协处理器监控CR0.MP&lt;br /&gt;
mov cr0, eax&lt;br /&gt;
mov eax, cr4&lt;br /&gt;
or ax, 3 &amp;lt;&amp;lt; 9		; 同时设置CR4.OSFXSR和CR4.OSXMMEXCPT&lt;br /&gt;
mov cr4, eax&lt;br /&gt;
ret&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== FXSAVE 和 FXRSTOR ===&lt;br /&gt;
FXSAVE和FXRSTOR用于从内存中保存和加载完整的SSE、x87 FPU和MMX状态。  主机需要为存储分配512字节，并将该内存指针用作FXSAVE或FXRSTOR的操作数。  在使用这两条指令之前，请确保检查FXSR位的CPUID功能。  另外，像大多数SSE指令一样，内存操作数需要对齐16字节，否则将发生#GP异常。  记住在*任何MXCSR修改发生之前执行FXSAVE*，否则寄存器很可能会被覆盖或根据未知状态MXCSR_MASK设置为0。  &lt;br /&gt;
&lt;br /&gt;
示例用法：&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
char fxsave_region[512] __attribute__((aligned(16)));&lt;br /&gt;
asm volatile(&amp;quot; fxsave %0 &amp;quot;::&amp;quot;m&amp;quot;(fxsave_region));&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
or in asm:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;asm&amp;quot;&amp;gt;&lt;br /&gt;
segment .code&lt;br /&gt;
SaveFloats:&lt;br /&gt;
fxsave [SavedFloats]&lt;br /&gt;
segment .data&lt;br /&gt;
align 16&lt;br /&gt;
SavedFloats: TIMES 512 db 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
陷阱: 仅支持一级保存。&lt;br /&gt;
&lt;br /&gt;
===MXCSR及其助手LDMXCSR和STMXCSR===&lt;br /&gt;
MXCSR寄存器保存用于SSE浮点运算的所有掩码和标志信息。  就像x87 FPU控制字一样，如果您想屏蔽某些异常或想指定舍入类型，则需要修改MXCSR。  位16-31是保留的，如果设置，将导致#GP异常。  LDMXCSR和STMXCSR分别加载和写入MXCSR寄存器。  它们都需要一个32位的内存操作数。  在使用这些指令(CR4.OSFXSR=1、CR0.EM=0和CR0.TS=0)之前，需要已经设置SSE支持。  如果设置了7-12位，则所有SSE浮点异常都将被屏蔽。  位0-5是异常状态标志，在发生相应异常时设置。  位13-14是RC(舍入控制)位。  RC:0 = 取最近，RC:1 = 向下取，RC:2 = 向上取，RC:3 = 截断。 &lt;br /&gt;
 &lt;br /&gt;
== 更新到SSE ==&lt;br /&gt;
后来的处理器为要在向量寄存器（vector registers）上执行的不同工作添加了更多指令。 在适当的SSE支持下支持它们不需要操作系统方面的任何努力 (AVX除外，请参见下文)。 然而，指令的实际用户应该检查这些指令是否确实存在。&lt;br /&gt;
===CPUID位===&lt;br /&gt;
=====SSE2=====&lt;br /&gt;
&amp;lt;small&amp;gt;'''Streaming SIMD Extensions 2 (SSE2)'''&amp;lt;/small&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
SSE2的位可以在CPUID page 1的EDX位26中找到。&lt;br /&gt;
=====SSE3=====&lt;br /&gt;
&amp;lt;small&amp;gt;'''Streaming SIMD Extensions 3 (SSE3)'''&amp;lt;/small&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
SSE3的位可以在CPUID page 1的ECX位0中找到。&lt;br /&gt;
=====SSSE3=====&lt;br /&gt;
&amp;lt;small&amp;gt;'''Supplemental Streaming SIMD Extensions 3 (SSSE3)'''&amp;lt;/small&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
SSSE3的位可以在CPUID page 1的ECX位9中找到。&lt;br /&gt;
&lt;br /&gt;
=====SSE4=====&lt;br /&gt;
&amp;lt;small&amp;gt;'''Streaming SIMD Extensions 4 (SSE4)'''&amp;lt;/small&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
SSE4.1的位可以在CPUID page 1的ECX位19中找到&lt;br /&gt;
&lt;br /&gt;
SSE4.2的位可以在CPUID page 1的ECX位20中找到&lt;br /&gt;
&lt;br /&gt;
SSE4A的位可以在CPUID page 1的ECX位6中找到&lt;br /&gt;
&lt;br /&gt;
=====SSE5=====&lt;br /&gt;
&amp;lt;small&amp;gt;'''Streaming SIMD Extensions 5 (SSE5)'''&amp;lt;/small&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
SSE5计划作为一个单元，但分成了几个：&lt;br /&gt;
======XOP======&lt;br /&gt;
XOP的位可以在CPUID page 1的ECX位11中找到&lt;br /&gt;
======FMA4======&lt;br /&gt;
FMA4的位可以在CPUID page 1的ECX位16中找到&lt;br /&gt;
======CVT16======&lt;br /&gt;
CVT16的位可在CPUID page 1的ECX位29中找到&lt;br /&gt;
======AVX======&lt;br /&gt;
AVX的位可以在CPUID page 1的ECX位28中找到&lt;br /&gt;
======XSAVE======&lt;br /&gt;
XSAVE (管理扩展处理器状态所需) 的位可以在CPUID page 1的ECX位26中找到&lt;br /&gt;
======AVX2======&lt;br /&gt;
The bit for AVX2 can be found on CPUID page 7, 0, in EDX bit 26&lt;br /&gt;
=====AVX-512=====&lt;br /&gt;
The bits for AVX-512 are in CPUID page 0x0D, 0x0, EAX bits 5-7&lt;br /&gt;
&lt;br /&gt;
===X86_64===&lt;br /&gt;
当[[X86-64]]体系结构推出时，AMD要求最低级别的SSE支持，以简化操作系统代码。 任何支持长模式的系统都应该至少支持SSE和SSE2，这意味着内核不需要关心旧的FPU保存代码。&lt;br /&gt;
X86-64将8个SSE寄存器 (xmm8 - xmm15) 添加到混合中。 但是，您只能在64位模式下访问这些。&lt;br /&gt;
&lt;br /&gt;
'''Advanced Vector Extensions（高级矢量扩展）'''是英特尔于2011年推出的‘’SIMD‘’(单指令、多数据)指令集。&lt;br /&gt;
&lt;br /&gt;
=== AVX ===&lt;br /&gt;
&lt;br /&gt;
AVX需要内核启用后才能使用。 忘记这样做会在第一次AVX通话时引发#UD。&lt;br /&gt;
在允许之前，必须同时启用SSE和OSXSAVE。 如果不这样做，也会产生一个#UD。&lt;br /&gt;
&lt;br /&gt;
AVX通过设置XCR0寄存器的第2位启用。 还必须设置XCR0的位1(表示支持SSE)。&lt;br /&gt;
&lt;br /&gt;
以下是启用SSE后启用AVX的汇编代码示例 (您应该首先检查AVX和XSAVE是否支持，请参见上文):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;asm&amp;quot;&amp;gt;&lt;br /&gt;
enable_avx:&lt;br /&gt;
    push rax&lt;br /&gt;
    push rcx&lt;br /&gt;
    push rdx&lt;br /&gt;
&lt;br /&gt;
    xor rcx, rcx&lt;br /&gt;
    xgetbv ;Load XCR0 register&lt;br /&gt;
    or eax, 7 ;Set AVX, SSE, X87 bits&lt;br /&gt;
    xsetbv ;Save back to XCR0&lt;br /&gt;
&lt;br /&gt;
    pop rdx&lt;br /&gt;
    pop rcx&lt;br /&gt;
    pop rax&lt;br /&gt;
    ret&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
要启用AVX-512，请设置XCR0的OPMASK（位5）、ZMM_Hi256（位6）、Hi16_ZMM（位7）。 您必须首先确保这些位有效(见上文)。&lt;br /&gt;
&lt;br /&gt;
== 另见 ==&lt;br /&gt;
* [[MMX]]&lt;br /&gt;
* The [[User:01000101/optlib/|optimisation library]] of 01000101, containing example code&lt;br /&gt;
&lt;br /&gt;
===参考资料===&lt;br /&gt;
* The [[Wikipedia:EN:Streaming_SIMD_Extensions|Wikipedia article]] on SSE &lt;br /&gt;
* The [[Wikipedia:EN:AVX-512|Wikipedia article]] on AVX-512&lt;br /&gt;
[[Category:X86]]&lt;/div&gt;</summary>
		<author><name>Zhang3</name></author>
	</entry>
</feed>