diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2012-10-07 17:55:26 +0200 |
---|---|---|
committer | Richard Henderson <rth@twiddle.net> | 2013-02-18 15:03:57 -0800 |
commit | f32d3781de8328237c2db45ff774cbd4b30134d6 (patch) | |
tree | 732d53fc951146f8b890ade52106fdfb7523e4d1 | |
parent | cc8b6f5b39ae47a93074a5384faa734bf2a6ae61 (diff) | |
download | qemu-f32d3781de8328237c2db45ff774cbd4b30134d6.zip qemu-f32d3781de8328237c2db45ff774cbd4b30134d6.tar.gz qemu-f32d3781de8328237c2db45ff774cbd4b30134d6.tar.bz2 |
target-i386: introduce gen_cmovcc1
Signed-off-by: Richard Henderson <rth@twiddle.net>
-rw-r--r-- | target-i386/translate.c | 72 |
1 files changed, 38 insertions, 34 deletions
diff --git a/target-i386/translate.c b/target-i386/translate.c index c83b56f..4b0a701 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -2414,6 +2414,40 @@ static inline void gen_jcc(DisasContext *s, int b, } } +static void gen_cmovcc1(CPUX86State *env, DisasContext *s, int ot, int b, + int modrm, int reg) +{ + int l1, mod = (modrm >> 6) & 3; + TCGv t0 = tcg_temp_local_new(); + + if (mod != 3) { + int reg_addr, offset_addr; + gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr); + gen_op_ld_v(ot + s->mem_index, t0, cpu_A0); + } else { + int rm = (modrm & 7) | REX_B(s); + gen_op_mov_v_reg(ot, t0, rm); + } + + l1 = gen_new_label(); + gen_jcc1(s, b ^ 1, l1); + switch (ot) { +#ifdef TARGET_X86_64 + case OT_LONG: + tcg_gen_mov_tl(cpu_regs[reg], t0); + gen_set_label(l1); + tcg_gen_ext32u_tl(cpu_regs[reg], cpu_regs[reg]); + break; +#endif + default: + gen_op_mov_reg_v(ot, reg, t0); + gen_set_label(l1); + break; + } + + tcg_temp_free(t0); +} + static inline void gen_op_movl_T0_seg(int seg_reg) { tcg_gen_ld32u_tl(cpu_T[0], cpu_env, @@ -6427,40 +6461,10 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, gen_ldst_modrm(env, s, modrm, OT_BYTE, OR_TMP0, 1); break; case 0x140 ... 0x14f: /* cmov Gv, Ev */ - { - int l1; - TCGv t0; - - ot = dflag + OT_WORD; - modrm = cpu_ldub_code(env, s->pc++); - reg = ((modrm >> 3) & 7) | rex_r; - mod = (modrm >> 6) & 3; - t0 = tcg_temp_local_new(); - if (mod != 3) { - gen_lea_modrm(env, s, modrm, ®_addr, &offset_addr); - gen_op_ld_v(ot + s->mem_index, t0, cpu_A0); - } else { - rm = (modrm & 7) | REX_B(s); - gen_op_mov_v_reg(ot, t0, rm); - } -#ifdef TARGET_X86_64 - if (ot == OT_LONG) { - /* XXX: specific Intel behaviour ? */ - l1 = gen_new_label(); - gen_jcc1(s, b ^ 1, l1); - tcg_gen_mov_tl(cpu_regs[reg], t0); - gen_set_label(l1); - tcg_gen_ext32u_tl(cpu_regs[reg], cpu_regs[reg]); - } else -#endif - { - l1 = gen_new_label(); - gen_jcc1(s, b ^ 1, l1); - gen_op_mov_reg_v(ot, reg, t0); - gen_set_label(l1); - } - tcg_temp_free(t0); - } + ot = dflag + OT_WORD; + modrm = cpu_ldub_code(env, s->pc++); + reg = ((modrm >> 3) & 7) | rex_r; + gen_cmovcc1(env, s, ot, b, modrm, reg); break; /************************/ |