assembly 如何在x87寄存器和SSE寄存器之间移动数据?

v6ylcynt  于 2023-06-30  发布在  其他
关注(0)|答案(1)|浏览(113)

我不确定这是否可行,但我想找到一种方法来在x87 FPU寄存器(例如st(0))和SSE寄存器(例如xmm1)之间移动值。上下文是我正在计算存储在内存中的一些浮点值的正弦。我目前的解决方案将这个值加载到st(0)寄存器中,调用fsin,将结果存储到一个临时全局变量中,然后将其移动到xmm1中。有没有一种方法可以直接进入xmm1寄存器,而不涉及这种内存加载和内存加载?
我知道这不是最优雅的x64汇编,但更广泛的背景是它适用于我正在编写的编译器(它主要使用SSE指令和寄存器,但我看到我需要深入了解x87的三角指令)。

.section .data
    outfloatfmt: .asciz "%lf\n"
    val: .double 90
    tmp: .double 0
    sinres: .double 0
.section .text
    .extern printf
    .global main
main:
    pushq %rbp
    movq %rsp, %rbp
    fld val(%rip)               # Load value into st(0)
    fsin                        # For some reason, this computes the sine of zero...
    fst tmp(%rip)               # Store sine in temp val.
    movsd tmp(%rip), %xmm1      # Load tmp sine into xmm1.
    movsd %xmm1, sinres(%rip)   # THIS is where I want to store the res.
    movsd sinres(%rip), %xmm0
    leaq outfloatfmt(%rip), %rdi
    movq $1, %rax
    callq printf
    movq %rbp, %rsp
    popq %rbp
    ret

另一个问题是,我认为st(0)没有从内存中加载正确的值。在调用fld之后,我通过GDB检查寄存器,但它总是读取0。如果输入值为90,则应返回1。

pbpqsu0x

pbpqsu0x1#

从英特尔手册中可以看出,没有办法直接通过寄存器在x87和MMX之间进行数据移动,即使是在CPU整数寄存器中临时存储浮点数也不行。人们可能希望从某个CPU代开始,将有一条指令将64位“双”浮点存储到长模式64位寄存器或一对32位寄存器中/从长模式64位寄存器或一对32位寄存器中加载64位“双”浮点,作为实际的IEEE格式编码,就像对存储器所做的那样。但幸运的是,大多数具有缓存的CPU将有效地处理堆栈指针附近的存储和加载。

相关问题