Commit 111994ee authored by Richard Henderson's avatar Richard Henderson
Browse files

target-i386: Implement MOVBE

parent 701ed211
Loading
Loading
Loading
Loading
+13 −3
Original line number Diff line number Diff line
@@ -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)
@@ -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
 */
+97 −25
Original line number Diff line number Diff line
@@ -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;
@@ -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]);
@@ -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;