diff options
-rw-r--r-- | target-i386/helper.h | 3 | ||||
-rw-r--r-- | target-i386/int_helper.c | 32 | ||||
-rw-r--r-- | target-i386/translate.c | 36 |
3 files changed, 71 insertions, 0 deletions
diff --git a/target-i386/helper.h b/target-i386/helper.h index d750754742..81e0fbdd6d 100644 --- a/target-i386/helper.h +++ b/target-i386/helper.h @@ -194,9 +194,12 @@ DEF_HELPER_3(fsave, void, env, tl, int) DEF_HELPER_3(frstor, void, env, tl, int) DEF_HELPER_3(fxsave, void, env, tl, int) DEF_HELPER_3(fxrstor, void, env, tl, int) + DEF_HELPER_1(bsf, tl, tl) DEF_HELPER_1(bsr, tl, tl) DEF_HELPER_2(lzcnt, tl, tl, int) +DEF_HELPER_FLAGS_2(pdep, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(pext, TCG_CALL_NO_RWG_SE, tl, tl, tl) /* MMX/SSE */ diff --git a/target-i386/int_helper.c b/target-i386/int_helper.c index 4ec8cb78d2..527af40281 100644 --- a/target-i386/int_helper.c +++ b/target-i386/int_helper.c @@ -488,6 +488,38 @@ target_ulong helper_bsr(target_ulong t0) return helper_lzcnt(t0, 0); } +#if TARGET_LONG_BITS == 32 +# define ctztl ctz32 +#else +# define ctztl ctz64 +#endif + +target_ulong helper_pdep(target_ulong src, target_ulong mask) +{ + target_ulong dest = 0; + int i, o; + + for (i = 0; mask != 0; i++) { + o = ctztl(mask); + mask &= mask - 1; + dest |= ((src >> i) & 1) << o; + } + return dest; +} + +target_ulong helper_pext(target_ulong src, target_ulong mask) +{ + target_ulong dest = 0; + int i, o; + + for (o = 0; mask != 0; o++) { + i = ctztl(mask); + mask &= mask - 1; + dest |= ((src >> i) & 1) << o; + } + return dest; +} + #define SHIFT 0 #include "shift_helper_template.h" #undef SHIFT diff --git a/target-i386/translate.c b/target-i386/translate.c index 3017d63163..51016fedd5 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -4138,6 +4138,42 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, } break; + case 0x3f5: /* pdep Gy, By, Ey */ + if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2) + || !(s->prefix & PREFIX_VEX) + || s->vex_l != 0) { + goto illegal_op; + } + ot = s->dflag == 2 ? OT_QUAD : OT_LONG; + gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0); + /* Note that by zero-extending the mask operand, we + automatically handle zero-extending the result. */ + if (s->dflag == 2) { + tcg_gen_mov_tl(cpu_T[1], cpu_regs[s->vex_v]); + } else { + tcg_gen_ext32u_tl(cpu_T[1], cpu_regs[s->vex_v]); + } + gen_helper_pdep(cpu_regs[reg], cpu_T[0], cpu_T[1]); + break; + + case 0x2f5: /* pext Gy, By, Ey */ + if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2) + || !(s->prefix & PREFIX_VEX) + || s->vex_l != 0) { + goto illegal_op; + } + ot = s->dflag == 2 ? OT_QUAD : OT_LONG; + gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0); + /* Note that by zero-extending the mask operand, we + automatically handle zero-extending the result. */ + if (s->dflag == 2) { + tcg_gen_mov_tl(cpu_T[1], cpu_regs[s->vex_v]); + } else { + tcg_gen_ext32u_tl(cpu_T[1], cpu_regs[s->vex_v]); + } + gen_helper_pext(cpu_regs[reg], cpu_T[0], cpu_T[1]); + break; + case 0x0f3: case 0x1f3: case 0x2f3: |