#542

Decoded SQRTSS xmm1, xmm2 appears to read from xmm1

OpenMcSinyxopened 1y ago

Reproduced with this disasm-sqrtss.c:

#include <assert.h>
#include <stdio.h>
#include <Zydis/Zydis.h>

int main(void)
{
    const ZyanU8 data[] = {0xF3, 0x0F, 0x51, 0xCA};

    ZydisDisassembledInstruction instruction;
    assert(ZYAN_SUCCESS(ZydisDisassembleIntel(ZYDIS_MACHINE_MODE_LONG_64,
                                              0,
                                              data,
                                              sizeof(data),
                                              &instruction)));
    printf("%s\n", instruction.text);
    printf("first operand action read: %d\n",
           instruction.operands[0].actions & ZYDIS_OPERAND_ACTION_READ);

    return 0;
}
$ gcc -lZydis disasm-sqrtss.c 
$ ./a.out 
sqrtss xmm1, xmm2
first operand action read: 1

From the x86 manual, vol. 2B 4-665 (page 1891), xmm1 should be write-only.

Activity

2
Sir-Walrus1y ago

128-bit Legacy SSE version: The first source operand and the destination operand are the same. Bits (MAXVL-1:32) of the corresponding YMM destination register remain unchanged.

"remain unchanged" means the result depends on the incoming value in that register. I'd count that as a read, though it certainly is debatable.

And I do agree there's a bug somewhere.

0F 51 CA 
sqrtps xmm1, xmm2
first operand action read: 0
0F 53 CA 
rcpps xmm1, xmm2
first operand action read: 0
0F 10 CA 
movups xmm1, xmm2
first operand action read: 0
66 0F 3A 08 CA 01 
roundps xmm1, xmm2, 0x01
first operand action read: 0
F3 0F 51 CA 
sqrtss xmm1, xmm2
first operand action read: 1
F3 0F 53 CA 
rcpss xmm1, xmm2
first operand action read: 1
F3 0F 10 CA 
movss xmm1, xmm2
first operand action read: 0
66 0F 3A 0A CA 01 
roundss xmm1, xmm2, 0x01
first operand action read: 1
0F 4C C3 
cmovl eax, ebx
first operand action read: 0

Either 'leaves bits unchanged' is a read, in which case cmovl is wrong, or it's not a read, in which case sqrtss (and rcpss, roundss, and probably a few others) are wrong.

And in both cases, movss being different from sqrtss is a baffling result.

ZehMatt3mo ago

This sounds like the same as #585, if it is a partial write then it should mark it as read since it needs the previous value, this is in my opinion more correct than just having it marked as write.