target/i386: add CPUID feature checks to new decoder

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Paolo Bonzini 2022-09-01 14:51:35 +02:00
parent 268dc4648f
commit caa01fadbe
2 changed files with 75 additions and 0 deletions

View file

@ -85,6 +85,7 @@
#define X86_OP_ENTRY0(op, ...) \
X86_OP_ENTRY3(op, None, None, None, None, None, None, ## __VA_ARGS__)
#define cpuid(feat) .cpuid = X86_FEAT_##feat,
#define i64 .special = X86_SPECIAL_i64,
#define o64 .special = X86_SPECIAL_o64,
#define xchg .special = X86_SPECIAL_Locked,
@ -513,6 +514,56 @@ static bool decode_insn(DisasContext *s, CPUX86State *env, X86DecodeFunc decode_
return true;
}
static bool has_cpuid_feature(DisasContext *s, X86CPUIDFeature cpuid)
{
switch (cpuid) {
case X86_FEAT_None:
return true;
case X86_FEAT_MOVBE:
return (s->cpuid_ext_features & CPUID_EXT_MOVBE);
case X86_FEAT_PCLMULQDQ:
return (s->cpuid_ext_features & CPUID_EXT_PCLMULQDQ);
case X86_FEAT_SSE:
return (s->cpuid_ext_features & CPUID_SSE);
case X86_FEAT_SSE2:
return (s->cpuid_ext_features & CPUID_SSE2);
case X86_FEAT_SSE3:
return (s->cpuid_ext_features & CPUID_EXT_SSE3);
case X86_FEAT_SSSE3:
return (s->cpuid_ext_features & CPUID_EXT_SSSE3);
case X86_FEAT_SSE41:
return (s->cpuid_ext_features & CPUID_EXT_SSE41);
case X86_FEAT_SSE42:
return (s->cpuid_ext_features & CPUID_EXT_SSE42);
case X86_FEAT_AES:
if (!(s->cpuid_ext_features & CPUID_EXT_AES)) {
return false;
} else if (!(s->prefix & PREFIX_VEX)) {
return true;
} else if (!(s->cpuid_ext_features & CPUID_EXT_AVX)) {
return false;
} else {
return !s->vex_l || (s->cpuid_7_0_ecx_features & CPUID_7_0_ECX_VAES);
}
case X86_FEAT_AVX:
return (s->cpuid_ext_features & CPUID_EXT_AVX);
case X86_FEAT_SSE4A:
return (s->cpuid_ext3_features & CPUID_EXT3_SSE4A);
case X86_FEAT_ADX:
return (s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_ADX);
case X86_FEAT_BMI1:
return (s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1);
case X86_FEAT_BMI2:
return (s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2);
case X86_FEAT_AVX2:
return (s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_AVX2);
}
g_assert_not_reached();
}
static void decode_temp_free(X86DecodedOp *op)
{
if (op->v_ptr) {
@ -701,6 +752,10 @@ static void disas_insn_new(DisasContext *s, CPUState *cpu, int b)
goto unknown_op;
}
if (!has_cpuid_feature(s, decode.e.cpuid)) {
goto illegal_op;
}
switch (decode.e.special) {
case X86_SPECIAL_None:
break;

View file

@ -93,6 +93,25 @@ typedef enum X86OpSize {
X86_SIZE_f64,
} X86OpSize;
typedef enum X86CPUIDFeature {
X86_FEAT_None,
X86_FEAT_ADX,
X86_FEAT_AES,
X86_FEAT_AVX,
X86_FEAT_AVX2,
X86_FEAT_BMI1,
X86_FEAT_BMI2,
X86_FEAT_MOVBE,
X86_FEAT_PCLMULQDQ,
X86_FEAT_SSE,
X86_FEAT_SSE2,
X86_FEAT_SSE3,
X86_FEAT_SSSE3,
X86_FEAT_SSE41,
X86_FEAT_SSE42,
X86_FEAT_SSE4A,
} X86CPUIDFeature;
/* Execution flags */
typedef enum X86OpUnit {
@ -160,6 +179,7 @@ struct X86OpEntry {
X86OpSize s3:8;
X86InsnSpecial special:8;
X86CPUIDFeature cpuid:8;
bool is_decode:1;
};