If I have an instruction buffer for x86 is there an easy way to check if an instruction is an SSE instruction without having to check if the opcode is within the ranges for the SSE instructions? By this I mean is there a common instruction prefix or processor state (such as a register) that can be checked?
Share
(Updated)
Depending on how you define easy the answer is
either yes orno 🙂The instruction format is described in section 2 of the Intel 64 and IA-32 Architectures Software Developer’s Manual
Combined Volumes 2A and 2B: Instruction Set Reference, A-Z. One of the problematic parts is the prefixes. Some of these are mandatory for some SSE instructions (
66F2F3), while they have a different meaning for other opcodes (operand size override,REPNZandREPZ).To see how the prefixes are used to distinguish between different instructions, consider these 4 forms of adding two xmm registers together (output obtained with
objdump -D -b binary -m i386:x86-64:intel --insn-width=12):It seems that the default is to add two single precision scalars,
66(normally: operand size override prefix) selects the double precision version,F3(repz) selects the packed single version and finallyF2(repnz) selects the packed double version.Additionally they can sometimes be combined and in 64-bit mode you also have to worry about the REX prefix (pg. 2-9). Here is an example are different versions of roughly the same base instructions with different prefixes in 64-bit mode. I don’t know if you care about AVX instructions but I included one anyway as an example:
So as far as I can see you will always have to loop over all prefixes to determine if an instruction is an SSE instruction.
Update:
An additional complication is the existence of instructions that only differ in their ModRM encoding. Consider:
To find these and all the other ways they can be encoded it’s easiest to use an opcode map.
Because I’ve been meaning to look at writing a disassembler anyway I figured it would be a fun challenge to see what it takes. It should find most SSE instructions, though obviously I can’t and won’t guarantee it. I transformed the above opcode map into a series of tests that the code passes (tests.c – too big for inlining). The code tests a series of text strings containing hex digits of the opcode encoding (it stops parsing at the first non-hex digit, the last character in the string signifies whether it is an SSE instruction or not).
It first scans all prefixes, then uses the opcode tables to test if the instruction matches with extra logic to handle the nested tables needed for multi-byte opcodes and the need to match digits in the following modrm byte.
ssedetect.c:
inst_table.h: