将2个QWORD从通用寄存器移入XMM寄存器为高/低

时间:2017-05-30 10:02:46

标签: assembly masm

使用masm for ml64,我试图将2个无符号qwords从r9和r10移动到xmm0作为无符号128b int

到目前为止,我提出了这个问题:

{this.state.showForm ?
<View>
  // Your form content here
</View>
: null }

我认为它有效,因为

mov r9, 111             ;low qword for test
mov r10, 222            ;high qword for test

movq xmm0, r9           ;move low to xmm0 lower bits
movq xmm1, r10          ;move high to xmm1 lower bits
pslldq xmm1, 4          ;shift xmm1 lower half to higher half   
por xmm0, xmm1          ;or the 2 halves together

返回正确的低值

movq rax, xmm0

返回正确的高值

问题是,有没有更好的方法呢?我浏览了英特尔内在指南,但我不太擅长猜测这些名称可能有什么说明。

2 个答案:

答案 0 :(得分:1)

您的字节移位/或中断,因为您仅移位了4个字节而不是8个字节;当您的8字节qword测试值的上半部分未设置任何位时,它就会起作用。


SSE / AVX SIMD指令集包含一个unpack instruction,可用于此目的:

mov r9, 111         ; test input: low half
mov r10, 222        ; test input: high half

vmovq xmm0, r9      ; move 64 bit wide general purpose register into lower xmm half
vmovq xmm1, r10     ; ditto

vpunpcklqdq xmm0, xmm0, xmm1    ; i.e. xmm0 = low(xmm1) low(xmm0)

这意味着vpunpcklqdq instruction将每个低源四字(= 64位)解压缩(或交织)为双四字(即XMM寄存器的完整宽度)。

与原始代码段相比,您节省了一条指令。

(我使用了VEX AVX助记符。如果要定位SSE2,则必须删除v前缀。)


或者,您可以使用insert instruction将第二个值移到上半部分:

mov r9, 111         ; test input
mov r10, 222        ; test input

vmovq xmm0, r9      ; move 64 bit wide general purpose register into lower xmm half

vpinsrq xmm0, xmm0, r10, 1    ; i.e. xmm0 = r9 low(ymm0)

在执行方面,在微操作级别上并没有太大的区别,即vpinsrqvmov + vpunpcklqdq一样“昂贵”,但可以编码为较短的代码。

此版本的非AVX要求pinsrq使用SSE4.1。

答案 1 :(得分:0)

在筹码的帮助下:

    push   r10
    push   r9
ifdef ALIGNED
    movdqa xmm0, xmmword ptr [esp]
else
    movdqu xmm0, xmmword ptr [esp]
endif
    add    esp, 16

如果你的__uint128恰好存在于堆栈中,只需删除多余的指令。