From ba20a39aa8e03db3d7b37375d64df4e31e933d8b Mon Sep 17 00:00:00 2001 From: Yusuf Date: Sat, 2 May 2026 07:53:47 +0300 Subject: [PATCH] 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. --- lifter/semantics/Semantics_Misc.ipp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lifter/semantics/Semantics_Misc.ipp b/lifter/semantics/Semantics_Misc.ipp index 02bb0b2..329d632 100644 --- a/lifter/semantics/Semantics_Misc.ipp +++ b/lifter/semantics/Semantics_Misc.ipp @@ -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( fnc->getParent()