lifter: accept Register64/Memory64 source for punpcklqdq

Iced classifies operand types by the bytes the instruction actually
accesses, not by physical register width. PUNPCKLQDQ only reads the
low 64 bits of its second operand, so Iced reports Register64 (or
Memory64 for the m128 form) for a source whose physical encoding is
`xmm/m128`. The lift handler's accept check rejected anything other
than Register128/Memory128 and fell through to the not_implemented
exit, so every `punpcklqdq xmm, xmm/m128` site lowered to a bogus
`call @not_implemented; ret` instead of the unpack semantic.

Widen the accept set to Register64 and Memory64 too. The body
already truncates the source to i64 before OR'ing it into the high
half of the result, so a 64-bit-typed source is semantically
identical to a 128-bit one for this handler.

Fixes the two pre-existing oracle test failures
`punpcklqdq_xmm0_xmm1_basic` and
`punpcklqdq_xmm0_xmm1_zero_upper_from_zero_source`. `python test.py
all` stays at 244/244, confirming no semantic regressions.
This commit is contained in:
Yusuf
2026-05-02 07:53:47 +03:00
parent 127505952e
commit ba20a39aa8
+9 -1
View File
@@ -210,9 +210,17 @@ MERGEN_LIFTER_DEFINITION_TEMPLATES(void)::lift_punpcklqdq() {
LLVMContext& context = builder->getContext();
auto destinationType = instruction.types[0];
auto sourceType = instruction.types[1];
// Iced classifies the source operand by the bytes the instruction actually
// accesses, not by the physical register width. PUNPCKLQDQ only reads the
// low 64 bits of its second operand, so Iced reports Register64/Memory64
// even though the encoding is `xmm/m128`. Accept both shapes -- the
// body below truncates to i64 anyway, so a 64-bit-typed source is
// semantically identical to a 128-bit one for this handler.
bool destinationIsXmm = destinationType == OperandType::Register128;
bool sourceIsXmm = sourceType == OperandType::Register128 ||
sourceType == OperandType::Memory128;
sourceType == OperandType::Register64 ||
sourceType == OperandType::Memory128 ||
sourceType == OperandType::Memory64;
if (!destinationIsXmm || !sourceIsXmm) {
Function* externFunc = cast<Function>(
fnc->getParent()