Signed-off-by: Paolo Bonzini <pbonz...@redhat.com> --- target/i386/tcg/decode-new.c.inc | 30 ++++++++++++++++++++++++++++++ target/i386/tcg/emit.c.inc | 27 +++++++++++++++++++++++++++ 2 files changed, 57 insertions(+)
diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc index 6892000aaf..07a2aea540 100644 --- a/target/i386/tcg/decode-new.c.inc +++ b/target/i386/tcg/decode-new.c.inc @@ -476,6 +476,20 @@ static void decode_group_0x63(DisasContext *s, CPUX86State *env, X86OpEntry *ent } } +static void decode_group_1(DisasContext *s, CPUX86State *env, X86OpEntry *entry, uint8_t *b) +{ + static X86GenFunc group1_gen[8] = { + gen_ADD, gen_OR, gen_ADC, gen_SBB, gen_AND, gen_SUB, gen_XOR, gen_SUB, + }; + int op = (get_modrm(s, env) >> 3) & 7; + entry->gen = group1_gen[op]; + + if (op == 7) { + /* CMP */ + entry->special = X86_SPECIAL_NoWriteback; + } +} + static X86OpEntry A2_00_F7[16][8] = { { X86_OP_ENTRY2(ADD, E,b, G,b), @@ -558,8 +572,24 @@ static X86OpEntry A2_00_F7[16][8] = { X86_OP_ENTRYr(Jcc, J,b), }, { + X86_OP_GROUP2(1, E,b, I,b), + X86_OP_GROUP2(1, E,v, I,z), + X86_OP_GROUP2(1, E,b, I,b, i64), + X86_OP_GROUP2(1, E,v, I,b), + X86_OP_ENTRY2(AND, E,b, G,b, nowb), + X86_OP_ENTRY2(AND, E,v, G,v, nowb), + X86_OP_ENTRY2(XCHG, E,b, G,b, xchg), + X86_OP_ENTRY2(XCHG, E,v, G,v, xchg), }, { + X86_OP_ENTRY2(XCHG, 0,v, LoBits,v), + X86_OP_ENTRY2(XCHG, 0,v, LoBits,v), + X86_OP_ENTRY2(XCHG, 0,v, LoBits,v), + X86_OP_ENTRY2(XCHG, 0,v, LoBits,v), + X86_OP_ENTRY2(XCHG, 0,v, LoBits,v), + X86_OP_ENTRY2(XCHG, 0,v, LoBits,v), + X86_OP_ENTRY2(XCHG, 0,v, LoBits,v), + X86_OP_ENTRY2(XCHG, 0,v, LoBits,v), }, { }, diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc index ae82ebd8c9..80f6541464 100644 --- a/target/i386/tcg/emit.c.inc +++ b/target/i386/tcg/emit.c.inc @@ -325,6 +325,7 @@ static void gen_MOV(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { /* nothing to do! */ } +#define gen_NOP gen_MOV static void gen_MOVSXD(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { @@ -391,6 +392,32 @@ static void gen_SUB(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) gen_alu_op(s, OP_SUBL, decode->op[0].ot); } +static void gen_XCHG(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + if (decode->b == 0x90 && !REX_B(s)) { + if (s->prefix & PREFIX_REPZ) { + gen_update_cc_op(s); + gen_jmp_im(s, s->pc_start - s->cs_base); + gen_helper_pause(cpu_env, tcg_const_i32(s->pc - s->pc_start)); + s->base.is_jmp = DISAS_NORETURN; + } + /* No writeback. */ + decode->op[0].alu_op_type = X86_ALU_SKIP; + return; + } + + if (s->prefix & PREFIX_LOCK) { + tcg_gen_atomic_xchg_tl(s->T0, s->A0, s->T1, + s->mem_index, decode->op[0].ot | MO_LE); + /* now store old value into register operand */ + gen_op_mov_reg_v(s, decode->op[2].ot, decode->op[2].n, s->T0); + } else { + /* move destination value into source operand, source preserved in T1 */ + gen_op_mov_reg_v(s, decode->op[2].ot, decode->op[2].n, s->T0); + tcg_gen_mov_tl(s->T0, s->T1); + } +} + static void gen_XOR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { /* special case XOR reg, reg */ -- 2.37.1