曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 6006|回复: 2
打印 上一主题 下一主题

SSE, SSE2 浮点值及相关传送指令

[复制链接]

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34395
跳转到指定楼层
楼主
发表于 2010-1-4 11:03:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
IA-32 指令集包含传送 SSE 浮点数据类型值的指令。这些指令分为对打包单精度浮点数据进行操作的SSE指令,以及对打包双精度浮点数据进行操作的SSE2指令。

有一个完整的指令集用于在内存和处理器上的 XMM 寄存器之间传送 128 位打包单精度浮点值,下标列出这些指令:
指令
描述
MOVAPS
把4个对准的打包单精度值传送到XMM寄存器或者内存
MOVUPS
把4个不对准的打包单精度值传送到XMM寄存器或者内存
MOVSS
把1个单精度值传送到内存或者寄存器的低双字
MOVLPS
把2个单精度值传送到内存或者寄存器的低四字
MOVHPS
把2个单精度值传送到内存或者寄存器的高四字
MOVLHPS
把2个单精度值从低四字传送到高四字
MOVHLPS
把2个单精度值从高四字传送到低四字

上面的指令的每一条都使用 128 位 XMM 寄存器在 XMM 寄存器和内存之间传送打包 32 位单精度浮点值。它们不仅可以传送整组的打包单精度浮点值,也可以在 XMM 寄存器之间传送 2 个打包单精度浮点值的子集。

下面程序测试传送 SSE 打包单精度浮点值:
.section .data
value1:
        .float 12.34, 2345.543, -3493.2, 0.44901
value2:
        .float -5439.234, 32121.4, 1.0094, 0.00003

.section .bss
        .lcomm data, 16

.section .text
.global _start
_start:
        nop
        movups value1, %xmm0
        movups value2, %xmm1
        movups %xmm0, %xmm2
        movups %xmm0, data

        movl $1, %eax
        movl $0, %ebx
        int $0x80
在执行前面 3 条 movups 指令后,在调试器中查看程序执行的情况:
(gdb) print $xmm0
$1 = {v4_float = {12.3400002, 2345.54297, -3493.19995, 0.449010015}, v2_double = {
    5.6204289471764299e+24, 1.0439462282443856e-05}, v16_int8 = {-92, 112, 69, 65, -80, -104, 18,
    69, 51, 83, 90, -59, -92, -28, -27, 62}, v8_int16 = {28836, 16709, -26448, 17682, 21299,
    -15014, -7004, 16101}, v4_int32 = {1095069860, 1158846640, -983936205, 1055253668},
  v2_int64 = {4977208420974555300, 4532279996355072819},
  uint128 = 0x3ee5e4a4c55a5333451298b0414570a4}
(gdb) print $xmm1
$2 = {v4_float = {-5439.23389, 32121.4004, 1.00940001, 2.99999992e-05}, v2_double = {
    8.7452727745837517e+33, 5.0800159140664774e-39}, v16_int8 = {-33, -7, -87, -59, -51, -14, -6,
    70, 5, 52, -127, 63, -126, -88, -5, 55}, v8_int16 = {-1569, -14935, -3379, 18170, 13317,
    16257, -22398, 14331}, v4_int32 = {-978716193, 1190851277, 1065432069, 939239554}, v2_int64 = {
    5114667292431088095, 4034003168605058053}, uint128 = 0x37fba8823f81340546faf2cdc5a9f9df}
(gdb) print $xmm2
$3 = {v4_float = {12.3400002, 2345.54297, -3493.19995, 0.449010015}, v2_double = {
    5.6204289471764299e+24, 1.0439462282443856e-05}, v16_int8 = {-92, 112, 69, 65, -80, -104, 18,
    69, 51, 83, 90, -59, -92, -28, -27, 62}, v8_int16 = {28836, 16709, -26448, 17682, 21299,
    -15014, -7004, 16101}, v4_int32 = {1095069860, 1158846640, -983936205, 1055253668},
  v2_int64 = {4977208420974555300, 4532279996355072819},
  uint128 = 0x3ee5e4a4c55a5333451298b0414570a4}
从输出可以发现,所有数据都被正确的加载到了 XMM 寄存器中。v4_float 格式显示使用的打包单精度浮点值。

最后的一条 movups 指令是把 XMM 寄存器的值复制到 data 位置。可以使用 x/4f 命令显示结果:
(gdb) x/4f &data
0x80490c0 <data>:       12.3400002      2345.54297      -3493.19995     0.449010015
为了把存储在内存位置 data 中的字节显示为 4 个单精度浮点值,可以使用 x 命令的 4f 选项。

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34395
沙发
 楼主| 发表于 2010-1-4 11:26:06 | 只看该作者

SSE2 浮点值

和 SSE 数据类型类似,IA-32 平台包含用于传送 SSE2 打包双精度浮点数据类型的指令,如下表所示:
指令
描述
MOVAPD
把2个对准的双精度值传送到XMM寄存器或者内存
MOVUPD
把2个不对准的双精度值传送到XMM寄存器或者内存
MOVSD
把1个双精度值传送到内存或者寄存器的低四字
MOVHPD
把1个双精度值传送到内存或者寄存器的高四字
MOVLPD
把1个双精度值传送到内存或者寄存器的低四字

下面程序测试相关指令:
.section .data
value1:
        .double 12.34, 2345.543
value2:
        .double -5439.234, 32121.4

.section .bss
        .lcomm data, 16

.section .text
.global _start
_start:
        nop
        movupd value1, %xmm0
        movupd value2, %xmm1
        movupd %xmm0, %xmm2
        movupd %xmm0, data

        movl $1, %eax
        movl $0, %ebx
        int $0x80
同样在调试器中可以查看相关的 XMM 寄存器中的值(在输出里,需要查看的是 v2_double 部分的值):
(gdb) print $xmm0
$1 = {v4_float = {5.84860315e+35, 2.63562489, 1.79352231e-36, 5.07264233}, v2_double = {12.34,
    2345.5430000000001}, v16_int8 = {-82, 71, -31, 122, 20, -82, 40, 64, 117, -109, 24, 4, 22, 83,
    -94, 64}, v8_int16 = {18350, 31457, -20972, 16424, -27787, 1048, 21270, 16546}, v4_int32 = {
    2061584302, 1076407828, 68719477, 1084379926}, v2_int64 = {4623136420479977390,
    4657376318677619573}, uint128 = 0x40a25316041893754028ae147ae147ae}
(gdb) print $xmm1
$2 = {v4_float = {-1.11704749e+24, -5.66396856, -1.58818684e-23, 6.98026705}, v2_double = {
    -5439.2340000000004, 32121.400000000001}, v16_int8 = {68, -117, 108, -25, 59, 63, -75, -64,
    -102, -103, -103, -103, 89, 94, -33, 64}, v8_int16 = {-29884, -6292, 16187, -16203, -26214,
    -26215, 24153, 16607}, v4_int32 = {-412316860, -1061863621, -1717986918, 1088380505},
  v2_int64 = {-4560669521124488380, 4674558677155944858},
  uint128 = 0x40df5e599999999ac0b53f3be76c8b44}
(gdb) print $xmm2
$3 = {v4_float = {5.84860315e+35, 2.63562489, 1.79352231e-36, 5.07264233}, v2_double = {12.34,
    2345.5430000000001}, v16_int8 = {-82, 71, -31, 122, 20, -82, 40, 64, 117, -109, 24, 4, 22, 83,
    -94, 64}, v8_int16 = {18350, 31457, -20972, 16424, -27787, 1048, 21270, 16546}, v4_int32 = {
    2061584302, 1076407828, 68719477, 1084379926}, v2_int64 = {4623136420479977390,
    4657376318677619573}, uint128 = 0x40a25316041893754028ae147ae147ae}

再看一下 data 内存位置处的值的情况:
(gdb) x/2gf &data
0x80490c0 <data>:       12.34   2345.5430000000001
上面的 2gf 表示查看 2 个双精度浮点值,输出结果正如所期望的那样。

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34395
板凳
 楼主| 发表于 2010-1-4 11:34:43 | 只看该作者

SSE3 指令

在较新的 Intel CPU (支持超线程(Hyperthreading)的 Pentium4 开始)上支持 SSE3指令。SSE3 指令添加了 3 个附加指令来帮助传送打包的双精度浮点值:
      MOVSHDUP : 从内存或者 XMM 寄存器传送 128 位值,复制第 2 个和第 4 个 32 位数据元素。因此,传送由 32 位单精度浮点值 DCBA 构成的数据元素将创建由 CCAA 构成的 128 位打包单精度浮点值。
      MOVSLDUP : 从内存或者 XMM 寄存器传送 128 位值,复制第 1 个和第 3 个 32 位数据元素。因此,传送由 32 位单精度浮点值 DCBA 构成的数据元素将创建由 CCAA 构成的 128 位打包单精度浮点值。
      MOVDDUP : 从内存或者 XMM 寄存器传送 64 位双精度浮点值,把它复制到 128 位 XMM 寄存器中。因此,传送由 64 位双精度浮点值 A 构成的数据元素将创建 128 位打包的双精度浮点值 AA 。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2025-5-3 12:32 , Processed in 0.080069 second(s), 21 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表