SSE指令集

本篇介绍sse指令接,sse是流化SIMD扩展(Streaming SIMD Extension, SSE),提供全新的一组寄存器,处理128位打包数据。

sse提供了xmm寄存器,xmm一组8个128位的寄存器,分别名为xmm0-xmm7,sse构架提供对打包单精度浮点数的SIMD支持。

sse提供了两个版本的指令,其一以后缀ps结尾,这组指令对打包单精度浮点值执行类似mmx操作运算,而第二种后缀ss,这些指令对一个量标单精度浮点 值进行运算操作,这些指令不对打包值中的所有浮点值操作,而只对打包值中的低位双字节执行操作,源操作数中剩余的3个值直接传送给结果。

指令说明
movaps 把4个对准的单精度值传送到xmm寄存器或者内存
movups 把4个不对准的单精度值传送到xmm寄存器或者内存
movss 把1个单精度值传送到内存或者寄存器的低位双字
movlps 把2个单精度值传送到内存或者寄存器的低四字
movhps 把2个单精度值传送到内存或者寄存器的高四字
movlhps 把2个单精度值从低四字传送到高四字
movhlps 把2个单精度值从高四字传送到低四字

其中对准操作movaps要求数据在内存中对准16字节的边界,以提交效率,否则应使用movups传送数据。

运算指令:

指令说明
addps 将两个打包值相加
subps 将两个打包值相减
mulps 将两个打包值相乘
divps 将两个打包值相除
rcpps 计算打包值的倒数
sqrtps 计算打包值的平方根
rsqrtps 计算打包值的平方根倒数
maxps 计算两个打包值中的最大值
minps 计算两个打包值中的最小值
andps 计算两个打包值的按位逻辑与
andnps 计算两个打包值的按位逻辑非
orps 计算两个打包值的按位逻辑或
xorps 计算两个打包值的按位逻辑异或

以上指令都是用两个操作数:源操作数可以是128位内存或者xmm寄存器,目标操作数必须是xmm寄存器。

这里举一个简单的例子,使用gdb查看最后结果:

.section .data
    value1: .float 12.12, 34.89, 56.23, 78.45
    value2: .float 31.12, 57.124, 234.23, 67.246
.section .text
.globl _main
_main:
    enter $0, $0

    movups value1, %xmm0
    movups value2, %xmm1
    addps %xmm0, %xmm1

    movups value2, %xmm1
    maxps %xmm0, %xmm1
    leave
    ret

编译时加-g参数加入调试信息,调用addps后查看xmm1寄存器的结果,命令如下:

(gdb) print $xmm1
$1 = {v4_float = {43.2400017, 92.0139999, 290.459991, 145.695999},
  v2_double = {26419069594869.762, 1245245520236216.2}, v16_int8 = {-61, -11,
    44, 66, 43, 7, -72, 66, -31, 58, -111, 67, 45, -78, 17, 67}, v8_int16 = {
    -2621, 16940, 1835, 17080, 15073, 17297, -19923, 17169}, v4_int32 = {
    1110242755, 1119356715, 1133591265, 1125233197}, v2_int64 = {
    4807600484593235395, 4832839782622116577},
  uint128 = 0x4311b22d43913ae142b8072b422cf5c3}
(gdb)

可以看到,调用加法指令之后,四组和都存储在xmm1寄存器中,gdb查看时由于不知道如何解析xmm1寄存器的内容,因为可能是单精度,也可能是双精度或者不同宽度的整数,所以只能按不同的解析方式全部显示,查看v4_float即四个单精度浮点数的显示。

下面介绍一下sse构架下的比较指令,sse的比较指令单独比较128位打包单精度浮点的每个元素,结果是一个掩码,满足比较条件的结果全为1值,不满足结果的全为0值(量标只对最低的双字执行)。

指令说明
cmpps 比较打包值
cmpss 比较标量值
comiss 比较标量值并且设置eflags寄存器
ucomiss 比较标量值(包括非法值)并设置eflags寄存器

看到这里,仅仅有一个比较指令,并没有说明大小,何为满足条件全1,不满足全0呢,这样说一下指令的使用:

cmpps imp, source, destination

其中多出来的imp是一个无符号整数,这个整数表示的含义就是条件,这个条件值如下表所示:

整数说明
0 等于
1 小于
2 小于或等于
3 无序
4 不等于
5 不小于
6 不小于或等于
7 有序

如果需要比较两个数是否相等,传imp为0即可作为条件,满足条件结果全1,这是sse的比较方式。这里说明一下条件中的无序,因为是浮点比较,寄存器或内存中的有些值并不符合规定的浮点存储格式,相互比较是没有意义的,称为无序。

除了对浮点数的支持,sse指令集也有指令对mmx提供的功能进行扩展,他们对mmx寄存器中的数据执行操作:

指令说明
pavgb 计算打包无符号字节整数的平均值
pavgw 计算打包无符号字整数的平均值
pextrw 把一个字从mmx寄存器复制到通用寄存器
pinsrw 把一个字从通用寄存器复制到mmx寄存器
pmaxub 计算打包无符号字节整数的最大值
pmaxsw 计算打包有符号字整数的最大值
pminub 计算打包无符号字节整数的最小值
pminsw 计算打包有符号字整数的最小值
pmulhuw 将打包无符号字整数相乘并且存储高位结果
psadbw 计算无符号字节整数的绝对差的总和

SSE2 指令集又对 SSE 指令集做了很多扩充,主要对操作双精度浮点数和128位打包整数值执行数学操作,下面介绍SSE2的使用,先来看数据传送指令:

指令说明
movapd 把2个对准的双精度值传送到xmm寄存器或者内存
movupd 把2个不对准的双精度值传送到xmm寄存器或者内存
movdqa 把2个对准的四字节整数传送到xmm寄存器或者内存
movdqu 把2个不对准的四字节整数传送到xmm寄存器或者内存
movsd 把1个双精度值传送到内存或者寄存器的低四字
movhpd 把1个双精度值传送到内存或者寄存器的高四字
movlpd 把1个双精度值传送到内存或者寄存器的低四字

SSE2指令集提供处理打包双精度浮点数,打包字整数,打包双字整数和打包四字整数值的数学指令,这里列举SSE2的加法指令来说明这一系列指令格式:

指令说明
addpd 将打包双精度浮点值相加
addsd 将量标双精度浮点值相加
paddsb 将打包带符号字节整数相加
paddsw 将打包带符号字整数相加
paddd 将打包带符号双字整数相加
paddq 将打包带符号四字整数相加

这里虽然只列举add系列指令,这些选项也存在于乘法和除法操作中(mulpd, mulsd, divpd, divsd等)。 另外同sse指令集,sse2指令集也提供专门的数学操作,sqrt, max, min。

最后我们来看SSE3指令集,SSE3构架并没有提供任何新的数据类型,仅仅添加了几条指令,用于更快的执行标准函数,下面是新指令的列表:

指令说明
fisttp 把第一个fpu寄存器的值转换为整数(舍入)并且从fpu堆栈弹出
lddqu 快速从内存加载128位不对准的数据值
movshdup 传送128位值,复制第2个和第4个32位数据元素
movsldup 传送128位值,复制第1个和第3个32位数据元素
movddup 传送64位值,赋值值,使之成为128位值
addsubps 对于打包单精度浮点数,对第2个和第4个32位执行加法,第1和第3个32位执行减法
addsubpd 对于打包单精度浮点数,对第2对64位值执行加法,第1对位执行减法
haddps 对操作数的相邻的元素执行单精度浮点加法操作
haddpd 对操作数的相邻的元素执行双精度浮点加法操作
hsubps 对操作数的相邻的元素执行单精度浮点减法操作
hsubpd 对操作数的相邻的元素执行双精度浮点减法操作

SSE指令繁多,这里举得例子却很少,以后我会在此文继续附加一些说明例子,方便理解。

转载:http://fancymore.com/reading/assembler-sse-instruct.html

posted @ 2017-08-15 21:10  DeeLMind  阅读(4898)  评论(0编辑  收藏  举报