Loading target-i386/cpu.c +13 −3 Original line number Diff line number Diff line Loading @@ -389,10 +389,15 @@ typedef struct x86_def_t { CPUID_VME, CPUID_DTS, CPUID_SS, CPUID_HT, CPUID_TM, CPUID_PBE */ #define TCG_EXT_FEATURES (CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | \ CPUID_EXT_SSSE3 | CPUID_EXT_CX16 | CPUID_EXT_POPCNT | \ CPUID_EXT_HYPERVISOR) CPUID_EXT_MOVBE | CPUID_EXT_HYPERVISOR) /* missing: CPUID_EXT_DTES64, CPUID_EXT_DSCPL, CPUID_EXT_VMX, CPUID_EXT_EST, CPUID_EXT_TM2, CPUID_EXT_XTPR, CPUID_EXT_PDCM, CPUID_EXT_XSAVE */ CPUID_EXT_PCLMULQDQ, CPUID_EXT_DTES64, CPUID_EXT_DSCPL, CPUID_EXT_VMX, CPUID_EXT_SMX, CPUID_EXT_EST, CPUID_EXT_TM2, CPUID_EXT_CID, CPUID_EXT_FMA, CPUID_EXT_XTPR, CPUID_EXT_PDCM, CPUID_EXT_PCID, CPUID_EXT_DCA, CPUID_EXT_SSE41, CPUID_EXT_SSE42, CPUID_EXT_X2APIC, CPUID_EXT_TSC_DEADLINE_TIMER, CPUID_EXT_AES, CPUID_EXT_XSAVE, CPUID_EXT_OSXSAVE, CPUID_EXT_AVX, CPUID_EXT_F16C, CPUID_EXT_RDRAND */ #define TCG_EXT2_FEATURES ((TCG_FEATURES & CPUID_EXT2_AMD_ALIASES) | \ CPUID_EXT2_NX | CPUID_EXT2_MMXEXT | CPUID_EXT2_RDTSCP | \ CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT) Loading @@ -402,6 +407,11 @@ typedef struct x86_def_t { CPUID_EXT3_CR8LEG | CPUID_EXT3_ABM | CPUID_EXT3_SSE4A) #define TCG_SVM_FEATURES 0 #define TCG_7_0_EBX_FEATURES (CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_SMAP) /* missing: CPUID_7_0_EBX_FSGSBASE, CPUID_7_0_EBX_BMI1, CPUID_7_0_EBX_HLE, CPUID_7_0_EBX_AVX2, CPUID_7_0_EBX_BMI2, CPUID_7_0_EBX_ERMS, CPUID_7_0_EBX_INVPCID, CPUID_7_0_EBX_RTM, CPUID_7_0_EBX_RDSEED, CPUID_7_0_EBX_ADX */ /* built-in CPU model definitions */ Loading target-i386/translate.c +97 −25 Original line number Diff line number Diff line Loading @@ -3837,11 +3837,13 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, reg = ((modrm >> 3) & 7) | rex_r; gen_op_mov_reg_T0(OT_LONG, reg); break; case 0x138: if (s->prefix & PREFIX_REPNZ) goto crc32; case 0x038: b = modrm; if ((b & 0xf0) == 0xf0) { goto do_0f_38_fx; } modrm = cpu_ldub_code(env, s->pc++); rm = modrm & 7; reg = ((modrm >> 3) & 7) | rex_r; Loading Loading @@ -3914,26 +3916,29 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, set_cc_op(s, CC_OP_EFLAGS); } break; case 0x338: /* crc32 */ crc32: b = modrm; case 0x238: case 0x338: do_0f_38_fx: /* Various integer extensions at 0f 38 f[0-f]. */ b = modrm | (b1 << 8); modrm = cpu_ldub_code(env, s->pc++); reg = ((modrm >> 3) & 7) | rex_r; if (b != 0xf0 && b != 0xf1) goto illegal_op; if (!(s->cpuid_ext_features & CPUID_EXT_SSE42)) switch (b) { case 0x3f0: /* crc32 Gd,Eb */ case 0x3f1: /* crc32 Gd,Ey */ do_crc32: if (!(s->cpuid_ext_features & CPUID_EXT_SSE42)) { goto illegal_op; if (b == 0xf0) } if ((b & 0xff) == 0xf0) { ot = OT_BYTE; else if (b == 0xf1 && s->dflag != 2) if (s->prefix & PREFIX_DATA) ot = OT_WORD; else ot = OT_LONG; else } else if (s->dflag != 2) { ot = (s->prefix & PREFIX_DATA ? OT_WORD : OT_LONG); } else { ot = OT_QUAD; } gen_op_mov_TN_reg(OT_LONG, 0, reg); tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); Loading @@ -3944,6 +3949,73 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, ot = (s->dflag == 2) ? OT_QUAD : OT_LONG; gen_op_mov_reg_T0(ot, reg); break; case 0x1f0: /* crc32 or movbe */ case 0x1f1: /* For these insns, the f3 prefix is supposed to have priority over the 66 prefix, but that's not what we implement above setting b1. */ if (s->prefix & PREFIX_REPNZ) { goto do_crc32; } /* FALLTHRU */ case 0x0f0: /* movbe Gy,My */ case 0x0f1: /* movbe My,Gy */ if (!(s->cpuid_ext_features & CPUID_EXT_MOVBE)) { goto illegal_op; } if (s->dflag != 2) { ot = (s->prefix & PREFIX_DATA ? OT_WORD : OT_LONG); } else { ot = OT_QUAD; } /* Load the data incoming to the bswap. Note that the TCG implementation of bswap requires the input be zero extended. In the case of the loads, we simply know that gen_op_ld_v via gen_ldst_modrm does that already. */ if ((b & 1) == 0) { gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0); } else { switch (ot) { case OT_WORD: tcg_gen_ext16u_tl(cpu_T[0], cpu_regs[reg]); break; default: tcg_gen_ext32u_tl(cpu_T[0], cpu_regs[reg]); break; case OT_QUAD: tcg_gen_mov_tl(cpu_T[0], cpu_regs[reg]); break; } } switch (ot) { case OT_WORD: tcg_gen_bswap16_tl(cpu_T[0], cpu_T[0]); break; default: tcg_gen_bswap32_tl(cpu_T[0], cpu_T[0]); break; #ifdef TARGET_X86_64 case OT_QUAD: tcg_gen_bswap64_tl(cpu_T[0], cpu_T[0]); break; #endif } if ((b & 1) == 0) { gen_op_mov_reg_T0(ot, reg); } else { gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1); } break; default: goto illegal_op; } break; case 0x03a: case 0x13a: b = modrm; Loading Loading
target-i386/cpu.c +13 −3 Original line number Diff line number Diff line Loading @@ -389,10 +389,15 @@ typedef struct x86_def_t { CPUID_VME, CPUID_DTS, CPUID_SS, CPUID_HT, CPUID_TM, CPUID_PBE */ #define TCG_EXT_FEATURES (CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | \ CPUID_EXT_SSSE3 | CPUID_EXT_CX16 | CPUID_EXT_POPCNT | \ CPUID_EXT_HYPERVISOR) CPUID_EXT_MOVBE | CPUID_EXT_HYPERVISOR) /* missing: CPUID_EXT_DTES64, CPUID_EXT_DSCPL, CPUID_EXT_VMX, CPUID_EXT_EST, CPUID_EXT_TM2, CPUID_EXT_XTPR, CPUID_EXT_PDCM, CPUID_EXT_XSAVE */ CPUID_EXT_PCLMULQDQ, CPUID_EXT_DTES64, CPUID_EXT_DSCPL, CPUID_EXT_VMX, CPUID_EXT_SMX, CPUID_EXT_EST, CPUID_EXT_TM2, CPUID_EXT_CID, CPUID_EXT_FMA, CPUID_EXT_XTPR, CPUID_EXT_PDCM, CPUID_EXT_PCID, CPUID_EXT_DCA, CPUID_EXT_SSE41, CPUID_EXT_SSE42, CPUID_EXT_X2APIC, CPUID_EXT_TSC_DEADLINE_TIMER, CPUID_EXT_AES, CPUID_EXT_XSAVE, CPUID_EXT_OSXSAVE, CPUID_EXT_AVX, CPUID_EXT_F16C, CPUID_EXT_RDRAND */ #define TCG_EXT2_FEATURES ((TCG_FEATURES & CPUID_EXT2_AMD_ALIASES) | \ CPUID_EXT2_NX | CPUID_EXT2_MMXEXT | CPUID_EXT2_RDTSCP | \ CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT) Loading @@ -402,6 +407,11 @@ typedef struct x86_def_t { CPUID_EXT3_CR8LEG | CPUID_EXT3_ABM | CPUID_EXT3_SSE4A) #define TCG_SVM_FEATURES 0 #define TCG_7_0_EBX_FEATURES (CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_SMAP) /* missing: CPUID_7_0_EBX_FSGSBASE, CPUID_7_0_EBX_BMI1, CPUID_7_0_EBX_HLE, CPUID_7_0_EBX_AVX2, CPUID_7_0_EBX_BMI2, CPUID_7_0_EBX_ERMS, CPUID_7_0_EBX_INVPCID, CPUID_7_0_EBX_RTM, CPUID_7_0_EBX_RDSEED, CPUID_7_0_EBX_ADX */ /* built-in CPU model definitions */ Loading
target-i386/translate.c +97 −25 Original line number Diff line number Diff line Loading @@ -3837,11 +3837,13 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, reg = ((modrm >> 3) & 7) | rex_r; gen_op_mov_reg_T0(OT_LONG, reg); break; case 0x138: if (s->prefix & PREFIX_REPNZ) goto crc32; case 0x038: b = modrm; if ((b & 0xf0) == 0xf0) { goto do_0f_38_fx; } modrm = cpu_ldub_code(env, s->pc++); rm = modrm & 7; reg = ((modrm >> 3) & 7) | rex_r; Loading Loading @@ -3914,26 +3916,29 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, set_cc_op(s, CC_OP_EFLAGS); } break; case 0x338: /* crc32 */ crc32: b = modrm; case 0x238: case 0x338: do_0f_38_fx: /* Various integer extensions at 0f 38 f[0-f]. */ b = modrm | (b1 << 8); modrm = cpu_ldub_code(env, s->pc++); reg = ((modrm >> 3) & 7) | rex_r; if (b != 0xf0 && b != 0xf1) goto illegal_op; if (!(s->cpuid_ext_features & CPUID_EXT_SSE42)) switch (b) { case 0x3f0: /* crc32 Gd,Eb */ case 0x3f1: /* crc32 Gd,Ey */ do_crc32: if (!(s->cpuid_ext_features & CPUID_EXT_SSE42)) { goto illegal_op; if (b == 0xf0) } if ((b & 0xff) == 0xf0) { ot = OT_BYTE; else if (b == 0xf1 && s->dflag != 2) if (s->prefix & PREFIX_DATA) ot = OT_WORD; else ot = OT_LONG; else } else if (s->dflag != 2) { ot = (s->prefix & PREFIX_DATA ? OT_WORD : OT_LONG); } else { ot = OT_QUAD; } gen_op_mov_TN_reg(OT_LONG, 0, reg); tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); Loading @@ -3944,6 +3949,73 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, ot = (s->dflag == 2) ? OT_QUAD : OT_LONG; gen_op_mov_reg_T0(ot, reg); break; case 0x1f0: /* crc32 or movbe */ case 0x1f1: /* For these insns, the f3 prefix is supposed to have priority over the 66 prefix, but that's not what we implement above setting b1. */ if (s->prefix & PREFIX_REPNZ) { goto do_crc32; } /* FALLTHRU */ case 0x0f0: /* movbe Gy,My */ case 0x0f1: /* movbe My,Gy */ if (!(s->cpuid_ext_features & CPUID_EXT_MOVBE)) { goto illegal_op; } if (s->dflag != 2) { ot = (s->prefix & PREFIX_DATA ? OT_WORD : OT_LONG); } else { ot = OT_QUAD; } /* Load the data incoming to the bswap. Note that the TCG implementation of bswap requires the input be zero extended. In the case of the loads, we simply know that gen_op_ld_v via gen_ldst_modrm does that already. */ if ((b & 1) == 0) { gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0); } else { switch (ot) { case OT_WORD: tcg_gen_ext16u_tl(cpu_T[0], cpu_regs[reg]); break; default: tcg_gen_ext32u_tl(cpu_T[0], cpu_regs[reg]); break; case OT_QUAD: tcg_gen_mov_tl(cpu_T[0], cpu_regs[reg]); break; } } switch (ot) { case OT_WORD: tcg_gen_bswap16_tl(cpu_T[0], cpu_T[0]); break; default: tcg_gen_bswap32_tl(cpu_T[0], cpu_T[0]); break; #ifdef TARGET_X86_64 case OT_QUAD: tcg_gen_bswap64_tl(cpu_T[0], cpu_T[0]); break; #endif } if ((b & 1) == 0) { gen_op_mov_reg_T0(ot, reg); } else { gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1); } break; default: goto illegal_op; } break; case 0x03a: case 0x13a: b = modrm; Loading