@samitouri / QOSamiQemu / commits / e45fd081db

target/i386/tcg: simplify decoding of 0F 38 F0...FF

These lines are shown in the manual with a weird representation that confers a special meaning to 0x66 0xF2 prefixes. In reality, this is just the CRC32 instruction (chosen by 0xF2) plus a data size override prefix. All other instruction in the range that use the 0xF2 prefix are VEX-encoded and therefore they do not support multiple prefixes. Because of this, it is possible to handle the four prefixes normally using decode_by_prefix; the 0x66 0xF2 combination for CRC32 is handled naturally by the "v" operand size. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Paolo Bonzini committed Mar 31, 2026 at 08:52 UTC e45fd081dbf36fc6abb2fa518a80b9c37f0474a2
1 file changed +3 -18
target/i386/tcg/decode-new.c.inc
+3 -18
@@ -873,8 +873,8 @@ static const X86OpEntry opcodes_0F38_00toEF[240] = {
873 [0xef] = X86_OP_ENTRY3(CMPccXADD, M,y, G,y, B,y, vex13 xchg chk(o64) cpuid(CMPCCXADD) p_66),
874 };
875
876 -/* five rows for no prefix, 66, F3, F2, 66+F2 */
877 -static const X86OpEntry opcodes_0F38_F0toFF[16][5] = {
876 +/* four rows for no prefix, 66, F3, F2 (including 66+F2 operand size override) */
877 +static const X86OpEntry opcodes_0F38_F0toFF[16][4] = {
878 /*
879 * MOVBE and CRC32 are incorrectly listed as always doing 32-bit operation
880 * without prefix and 16-bit operation with 0x66.
@@ -884,49 +884,42 @@ static const X86OpEntry opcodes_0F38_F0toFF[16][5] = {
884 X86_OP_ENTRYwr(MOVBE, G,v, M,v, cpuid(MOVBE)),
885 {},
886 X86_OP_ENTRY2(CRC32, G,d, E,b, cpuid(SSE42)),
887 - X86_OP_ENTRY2(CRC32, G,d, E,b, cpuid(SSE42)),
887 },
888 [1] = {
889 X86_OP_ENTRYwr(MOVBE, M,v, G,v, cpuid(MOVBE)),
890 X86_OP_ENTRYwr(MOVBE, M,v, G,v, cpuid(MOVBE)),
891 {},
892 X86_OP_ENTRY2(CRC32, G,d, E,v, cpuid(SSE42)),
894 - X86_OP_ENTRY2(CRC32, G,d, E,v, cpuid(SSE42)),
893 },
894 [2] = {
895 X86_OP_ENTRY3(ANDN, G,y, B,y, E,y, vex13 cpuid(BMI1)),
896 {},
897 {},
898 {},
901 - {},
899 },
900 [3] = {
901 X86_OP_GROUP3(group17, B,y, None,None, E,y, vex13 cpuid(BMI1)),
902 {},
903 {},
904 {},
908 - {},
905 },
906 [5] = {
907 X86_OP_ENTRY3(BZHI, G,y, E,y, B,y, vex13 cpuid(BMI1)),
908 {},
909 X86_OP_ENTRY3(PEXT, G,y, B,y, E,y, vex13 zextT0 cpuid(BMI2)),
910 X86_OP_ENTRY3(PDEP, G,y, B,y, E,y, vex13 zextT0 cpuid(BMI2)),
915 - {},
911 },
912 [6] = {
913 {},
914 X86_OP_ENTRY2(ADCX, G,y, E,y, cpuid(ADX)),
915 X86_OP_ENTRY2(ADOX, G,y, E,y, cpuid(ADX)),
916 X86_OP_ENTRY3(MULX, /* B,y, */ G,y, E,y, 2,y, vex13 cpuid(BMI2)),
922 - {},
917 },
918 [7] = {
919 X86_OP_ENTRY3(BEXTR, G,y, E,y, B,y, vex13 zextT0 cpuid(BMI1)),
920 X86_OP_ENTRY3(SHLX, G,y, E,y, B,y, vex13 cpuid(BMI1)),
921 X86_OP_ENTRY3(SARX, G,y, E,y, B,y, vex13 sextT0 cpuid(BMI1)),
922 X86_OP_ENTRY3(SHRX, G,y, E,y, B,y, vex13 zextT0 cpuid(BMI1)),
929 - {},
923 },
924 };
925
@@ -936,15 +929,7 @@ static void decode_0F38(DisasContext *s, CPUX86State *env, X86OpEntry *entry, ui
929 if (*b < 0xf0) {
930 *entry = opcodes_0F38_00toEF[*b];
931 } else {
939 - int row = 0;
940 - if (s->prefix & PREFIX_REPZ) {
941 - /* The REPZ (F3) prefix has priority over 66 */
942 - row = 2;
943 - } else {
944 - row += s->prefix & PREFIX_REPNZ ? 3 : 0;
945 - row += s->prefix & PREFIX_DATA ? 1 : 0;
946 - }
947 - *entry = opcodes_0F38_F0toFF[*b & 15][row];
932 + *entry = *decode_by_prefix(s, opcodes_0F38_F0toFF[*b & 15]);
933 }
934 }
935