Perform the X86_VEX_REPScalar transformation on X86OpEntry instead of X86DecodedOp; everything else can be checked equally well before immediates are fetched etc.
This is especially important for APX, which may decode operands differently depending on the NDD bit: if EVEX.NDD=0, VEX.vvvv is ignored and must be zero. Signed-off-by: Paolo Bonzini <[email protected]> --- target/i386/tcg/decode-new.c.inc | 54 ++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc index 3205a046a6b..a17fc8550fb 100644 --- a/target/i386/tcg/decode-new.c.inc +++ b/target/i386/tcg/decode-new.c.inc @@ -2610,6 +2610,22 @@ static bool decode_ops(DisasContext *s, CPUX86State *env, X86DecodeFunc decode_f decode->immediate = insn_get_signed(env, s, MO_8); } + if (e->vex_class == 12) { + /* Check no overlap between registers. */ + if (!decode->op[0].has_ea && + (decode->op[0].n == decode->mem.index || decode->op[0].n == decode->op[1].n)) { + return false; + } + assert(!decode->op[1].has_ea); + if (decode->op[1].n == decode->mem.index) { + return false; + } + if (!decode->op[2].has_ea && + (decode->op[2].n == decode->mem.index || decode->op[2].n == decode->op[1].n)) { + return false; + } + } + return true; } @@ -2716,9 +2732,9 @@ static bool validate_vex(DisasContext *s, X86DecodedInsn *decode) if (s->vex_l) { goto illegal; } - assert(decode->e.s2 == X86_SIZE_x); - if (decode->op[2].has_ea) { - decode->op[2].ot = s->prefix & PREFIX_REPZ ? MO_32 : MO_64; + assert(e->op2 == X86_TYPE_W && e->s2 == X86_SIZE_x); + if ((s->modrm >> 6) != 3) { + e->s2 = s->prefix & PREFIX_REPNZ ? X86_SIZE_sd : X86_SIZE_ss; } } break; @@ -2735,10 +2751,7 @@ static bool validate_vex(DisasContext *s, X86DecodedInsn *decode) switch (e->vex_class) { case 0: - if (s->prefix & PREFIX_VEX) { - goto illegal; - } - return true; + g_assert_not_reached(); case 1: case 2: case 3: @@ -2763,19 +2776,6 @@ static bool validate_vex(DisasContext *s, X86DecodedInsn *decode) goto illegal; } - /* Check no overlap between registers. */ - if (!decode->op[0].has_ea && - (decode->op[0].n == decode->mem.index || decode->op[0].n == decode->op[1].n)) { - goto illegal; - } - assert(!decode->op[1].has_ea); - if (decode->op[1].n == decode->mem.index) { - goto illegal; - } - if (!decode->op[2].has_ea && - (decode->op[2].n == decode->mem.index || decode->op[2].n == decode->op[1].n)) { - goto illegal; - } /* fall through */ case 6: case 11: @@ -3118,6 +3118,16 @@ static void disas_insn(DisasContext *s, CPUState *cpu) get_modrm(s, env); } + if (decode.e.vex_class == 0) { + if (s->prefix & (PREFIX_VEX | PREFIX_EVEX)) { + goto illegal_op; + } + } else { + if (!validate_vex(s, &decode)) { + return; + } + } + if (!decode_ops(s, env, decode_func, &decode)) { goto illegal_op; } @@ -3179,10 +3189,6 @@ static void disas_insn(DisasContext *s, CPUState *cpu) goto illegal_op; } - if (!validate_vex(s, &decode)) { - return; - } - /* * Checks that result in #GP or VMEXIT come second. Intercepts are * generally checked after non-memory exceptions (i.e. after all -- 2.52.0
