diff mbox series

[08/37] target/i386: add CPUID feature checks to new decoder

Message ID 20220911230418.340941-9-pbonzini@redhat.com
State New
Headers show
Series target/i386: new decoder + AVX implementation | expand

Commit Message

Paolo Bonzini Sept. 11, 2022, 11:03 p.m. UTC
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 target/i386/tcg/decode-new.c.inc | 51 ++++++++++++++++++++++++++++++++
 target/i386/tcg/decode-new.h     | 20 +++++++++++++
 2 files changed, 71 insertions(+)

Comments

Richard Henderson Sept. 12, 2022, 10:05 a.m. UTC | #1
On 9/12/22 00:03, Paolo Bonzini wrote:
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>   target/i386/tcg/decode-new.c.inc | 51 ++++++++++++++++++++++++++++++++
>   target/i386/tcg/decode-new.h     | 20 +++++++++++++
>   2 files changed, 71 insertions(+)
> 
> diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
> index 7f76051b2d..a9b8b6c05f 100644
> --- a/target/i386/tcg/decode-new.c.inc
> +++ b/target/i386/tcg/decode-new.c.inc
> @@ -83,6 +83,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,
> @@ -506,6 +507,52 @@ 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->vex_l) {
> +            return (s->cpuid_7_0_ecx_features & CPUID_7_0_ECX_VAES);
> +        } else {
> +            return (s->cpuid_ext_features & CPUID_EXT_AES);
> +        }
> +    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);
> +    default:
> +        abort();
> +    }

g_assert_not_reached().

I'll also note that for cases like this, where every case returns, and is intended to be 
present, it can be better to leave the default case outside the switch, so that the 
compiler can Werror early for missing enumerator entries instead of aborting at runtime.

Otherwise,
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>


r~
diff mbox series

Patch

diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
index 7f76051b2d..a9b8b6c05f 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -83,6 +83,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,
@@ -506,6 +507,52 @@  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->vex_l) {
+            return (s->cpuid_7_0_ecx_features & CPUID_7_0_ECX_VAES);
+        } else {
+            return (s->cpuid_ext_features & CPUID_EXT_AES);
+        }
+    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);
+    default:
+        abort();
+    }
+}
+
 /* convert one instruction. s->base.is_jmp is set if the translation must
    be stopped. Return the next pc value */
 static target_ulong disas_insn_new(DisasContext *s, CPUState *cpu, int b)
@@ -690,6 +737,10 @@  static target_ulong 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;
diff --git a/target/i386/tcg/decode-new.h b/target/i386/tcg/decode-new.h
index a2d3c3867f..6fb2d9151e 100644
--- a/target/i386/tcg/decode-new.h
+++ b/target/i386/tcg/decode-new.h
@@ -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;
 };