@samitouri / QOSamiQemu / commits / ce0ee66044

target/i386: fix incorrect decoding of EXTRQ_i

The decoding of the extrq instruction with an immediate operand (EXTRQ_i) is incorrect. Per the AMD manual the instruction encoding looks as follows: EXTRQ xmm1, imm8, imm8 66 0F 78 /0 ib ib The /0 indicates that the "Reg" field of the ModR/M byte must be equal to 0 and the XMM register operand is specified by the "R/M" field. However, qemu incorrectly uses the "Reg" field to extract the register operand. This patch instead extracts the XMM register operand from the "R/M" field. Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3611 Signed-off-by: Simon Scherer <scherer.simon89@gmail.com> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Link: https://lore.kernel.org/r/20260625155613.192643-1-scherer.simon89@gmail.com [Check for the reg field to be 0. Make decoding of REPZ+66 consistent between 0F 78 and 0F 79. - Paolo] Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Simon Scherer committed Jun 25, 2026 at 17:56 UTC ce0ee66044be066cbbf076a7530fe4e8f638f847
1 file changed +19 -9
target/i386/tcg/decode-new.c.inc
+19 -9
@@ -603,23 +603,33 @@ static void decode_0F77(DisasContext *s, CPUX86State *env, X86OpEntry *entry, ui
603
604 static void decode_0F78(DisasContext *s, CPUX86State *env, X86OpEntry *entry, uint8_t *b)
605 {
606 - static const X86OpEntry opcodes_0F78[4] = {
607 - {},
608 - X86_OP_ENTRY3(EXTRQ_i, V,x, None,None, I,w, cpuid(SSE4A)), /* AMD extension */
609 - {},
610 - X86_OP_ENTRY3(INSERTQ_i, V,x, U,x, I,w, cpuid(SSE4A)), /* AMD extension */
611 - };
612 - *entry = *decode_by_prefix(s, opcodes_0F78);
606 + static const X86OpEntry opcodes_0F78_f2 =
607 + X86_OP_ENTRY3(INSERTQ_i, V,x, U,x, I,w, cpuid(SSE4A)); /* AMD extension */
608 + static const X86OpEntry opcodes_0F78_66 =
609 + X86_OP_ENTRY3(EXTRQ_i, U,x, None,None, I,w, cpuid(SSE4A)); /* AMD extension */
610 +
611 + entry->gen = NULL;
612 + if (s->prefix & PREFIX_REPNZ) {
613 + *entry = opcodes_0F78_f2;
614 + } else if (s->prefix & PREFIX_REPZ) {
615 + /* undefined */
616 + } else if (s->prefix & PREFIX_DATA) {
617 + int op = (get_modrm(s, env) >> 3) & 7;
618 + if (op == 0) {
619 + *entry = opcodes_0F78_66;
620 + }
621 + }
622 }
623
624 static void decode_0F79(DisasContext *s, CPUX86State *env, X86OpEntry *entry, uint8_t *b)
625 {
626 + entry->gen = NULL;
627 if (s->prefix & PREFIX_REPNZ) {
628 entry->gen = gen_INSERTQ_r; /* AMD extension */
629 + } else if (s->prefix & PREFIX_REPZ) {
630 + /* undefined */
631 } else if (s->prefix & PREFIX_DATA) {
632 entry->gen = gen_EXTRQ_r; /* AMD extension */
621 - } else {
622 - entry->gen = NULL;
633 };
634 }
635