Skip to content

Commit

Permalink
target-i386: Implement MOVBE
Browse files Browse the repository at this point in the history
Signed-off-by: Richard Henderson <rth@twiddle.net>
  • Loading branch information
rth7680 committed Feb 18, 2013
1 parent 701ed21 commit 111994e
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 28 deletions.
16 changes: 13 additions & 3 deletions target-i386/cpu.c
Expand Up @@ -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)
Expand All @@ -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
*/
Expand Down
122 changes: 97 additions & 25 deletions target-i386/translate.c
Expand Up @@ -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;
Expand Down Expand Up @@ -3914,36 +3916,106 @@ 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))
goto illegal_op;
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 & 0xff) == 0xf0) {
ot = OT_BYTE;
} else if (s->dflag != 2) {
ot = (s->prefix & PREFIX_DATA ? OT_WORD : OT_LONG);
} else {
ot = OT_QUAD;
}

if (b == 0xf0)
ot = OT_BYTE;
else if (b == 0xf1 && s->dflag != 2)
if (s->prefix & PREFIX_DATA)
ot = OT_WORD;
else
ot = 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]);
gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
gen_helper_crc32(cpu_T[0], cpu_tmp2_i32,
cpu_T[0], tcg_const_i32(8 << ot));

gen_op_mov_TN_reg(OT_LONG, 0, reg);
tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
gen_helper_crc32(cpu_T[0], cpu_tmp2_i32,
cpu_T[0], tcg_const_i32(8 << ot));
ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
gen_op_mov_reg_T0(ot, reg);
break;

ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
gen_op_mov_reg_T0(ot, reg);
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;
Expand Down

0 comments on commit 111994e

Please sign in to comment.