好友
阅读权限10
听众
最后登录1970-1-1
|
#### X87(第一代)
vs系列需要选择使用x87
否则默认使用SSE2
![](index_files/de7c5918-eca6-4aad-a222-c455aaa18f2a.png)
FPU: 8个80位浮点寄存器(数据),16位状态寄存器,16位控制寄存器,16为标识寄存器。
使用FPU指令对这些寄存器进行操作,这些寄存器构成一个循环栈,st7栈底,st0栈顶,
当一个值被压入时,被存入st0,原来st0中的值被存入st7
![](index_files/d74874d3-ad5c-4eae-bc97-a27846591e23.png)
| 指令|含义 |例子|
|-------|------|------|
| fld | 将浮点值压入寄存器栈,源操作数可以是ST(i)或内存地址|fld b、fld st(1)|
| fld1 | 将浮点值1压入寄存器栈|fld1|
| fldz | 将浮点值0压入寄存器栈|fld0|
| fadd | 源操作数和目标操作数相加源操作数可以是内存地址或者FPU寄存器,目标操作数必须是FPU寄存器|fadd st(0),st(1)|
| faddp | ST(i)和ST(0)相加,计算结果存入ST(0)中|faddp st(1), st(0)|
| fstp | 拷贝ST(0)到ST(i)或内存位置,并且进行弹栈操作|fstp ret|
使用例子加法代码
```c
float a = 3.14f;
float b = 1.14f;
int ret1;
float ret2;
__asm
{
//
fld a
fld b
fld st(1)
//fadd st(0),st(1)
faddp st(1), st(0)
//fistp ret1
fstp ret2
}
```
#### MMX(并行)
MMX: 将8个FPU寄存器重命名为8个64位MMX寄存器,即mm0到mm7。取消了栈结构。
57条MMX指令,加快了整形浮点运算,但是对于复杂浮点运算无帮助
有符号饱和模式 127+1=127
无符号饱和模式 255+1=255
环绕模式 255+1=255
| 指令|含义 |例子|
|-------|------|------|
| movd | 复制MMX寄存器中的低位双字到一个通用寄存器或内存中,也可以把通用寄存器或内存中的数据复制到MMX寄存器的低位双字中|movd mm0,a movd b,mm0|
| movq | 把一个MMX寄存器的内容复制到另一个MMX寄存器中,这个指令也能被用来把一个内存区域中的内容复制到一个MMX寄存器中,或者把MMX寄存器中的内容复制到内存中|movq mm0,a movq b,mm0|
| paddb | 用mmx里面的一字节分别加|paddb mm0,mm1|
| paddsb | 有符号饱和模式、用mmx里面的一字节分别加|paddsb mm0,mm1|
| paddusb | 无符号饱和模式、用mmx里面的一字节分别加|paddusb mm0,mm1|
```c
char ary1[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
char ary2[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
char ary3[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
__asm
{
movq MM0, ary1
movq MM1, ary2
paddb MM0, MM1 //环绕
paddusb MM0, MM1 //饱和
}
```
执行结构很容易看到是分别按字节并行加的 1+1=2 2+2=4 ....
![](index_files/f75f5b24-1d20-4a81-a617-66c54a4d95dd.png)
**C语言使用MMX指令**
+ 首先包上头文件#include <mmintrin.h> //MMX指令集
进头文件看指令都封装成函数了
![](index_files/911eedb7-20a7-489a-8b7c-b2b43c6b6916.png)
```c
void mmx_add(char *ary, int size)
{
__m64 sum;
sum.m64_i64 = 0x0101010101010101L;
__m64 *p = (__m64 *)ary;
for (int i = 0; i < size; i++)
_m_paddb(p, sum);
}
```
#### 3DNOW
AMD才有的指令
被intel SSE所取代
#### SSE
8个128位寄存器(从xmm0到xmm7),MXSCR寄存器,EFLAGS寄存器,专有指令(复杂浮点运算)
并且 MMX是xmm的低64位
SSE的发展:
SSE SSE1 SSE2 SSE3 SSE4 SSE4.1 SSE4.2 SSE5.0(AVX)
SSE指令
SSE: MOVSS ADDSS ADDSD ADDPS ADDPD
头文件:
#include <xmmintrin.h> //sse
#include <emmintrin.h> //sse2
#include <pmmintrin.h> //sse3
```c
float sse_add(float *ary, int size)
{
__m128 sum = { 0.0f, 0.0f, 0.0f, 0.0f };
__m128 *p = (__m128*)ary;
for (int i = 0; i < size; i++)
sum = _mm_add_ps(sum, p);
return sum.m128_f32[0] + sum.m128_f32[1] + sum.m128_f32[2] + sum.m128_f32[3];
}
```
#### VAX(SSE 5.0)
//AVX: VMOVSS VADDSS
```c
#include <intrin.h> //all
#include <immintrin.h> //avx
```
```c
float avx_add(float *ary, int size)
{
__m256 sum = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
__m256 *p = (__m256*)ary;
for (int i = 0; i < size; i++)
sum = _mm256_add_ps(sum, p);
return sum.m256_f32[0];
}
``` |
|