Loading target-i386/ops_template.h +0 −14 Original line number Diff line number Diff line Loading @@ -415,20 +415,6 @@ void OPPROTO glue(op_setle_T0_sub, SUFFIX)(void) T0 = ((DATA_STYPE)src1 <= (DATA_STYPE)src2); } #undef MEM_WRITE #include "ops_template_mem.h" #define MEM_WRITE 0 #include "ops_template_mem.h" #if !defined(CONFIG_USER_ONLY) #define MEM_WRITE 1 #include "ops_template_mem.h" #define MEM_WRITE 2 #include "ops_template_mem.h" #endif /* bit operations */ #if DATA_BITS >= 16 Loading target-i386/ops_template_mem.hdeleted 100644 → 0 +0 −119 Original line number Diff line number Diff line /* * i386 micro operations (included several times to generate * different operand sizes) * * Copyright (c) 2003 Fabrice Bellard * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef MEM_WRITE #if MEM_WRITE == 0 #if DATA_BITS == 8 #define MEM_SUFFIX b_raw #elif DATA_BITS == 16 #define MEM_SUFFIX w_raw #elif DATA_BITS == 32 #define MEM_SUFFIX l_raw #elif DATA_BITS == 64 #define MEM_SUFFIX q_raw #endif #elif MEM_WRITE == 1 #if DATA_BITS == 8 #define MEM_SUFFIX b_kernel #elif DATA_BITS == 16 #define MEM_SUFFIX w_kernel #elif DATA_BITS == 32 #define MEM_SUFFIX l_kernel #elif DATA_BITS == 64 #define MEM_SUFFIX q_kernel #endif #elif MEM_WRITE == 2 #if DATA_BITS == 8 #define MEM_SUFFIX b_user #elif DATA_BITS == 16 #define MEM_SUFFIX w_user #elif DATA_BITS == 32 #define MEM_SUFFIX l_user #elif DATA_BITS == 64 #define MEM_SUFFIX q_user #endif #else #error invalid MEM_WRITE #endif #else #define MEM_SUFFIX SUFFIX #endif /* carry add/sub (we only need to set CC_OP differently) */ void OPPROTO glue(glue(op_adc, MEM_SUFFIX), _T0_T1_cc)(void) { int cf; cf = cc_table[CC_OP].compute_c(); T0 = T0 + T1 + cf; #ifdef MEM_WRITE glue(st, MEM_SUFFIX)(A0, T0); #endif CC_SRC = T1; CC_DST = T0; CC_OP = CC_OP_ADDB + SHIFT + cf * 4; } void OPPROTO glue(glue(op_sbb, MEM_SUFFIX), _T0_T1_cc)(void) { int cf; cf = cc_table[CC_OP].compute_c(); T0 = T0 - T1 - cf; #ifdef MEM_WRITE glue(st, MEM_SUFFIX)(A0, T0); #endif CC_SRC = T1; CC_DST = T0; CC_OP = CC_OP_SUBB + SHIFT + cf * 4; } void OPPROTO glue(glue(op_cmpxchg, MEM_SUFFIX), _T0_T1_EAX_cc)(void) { target_ulong src, dst; src = T0; dst = EAX - T0; if ((DATA_TYPE)dst == 0) { T0 = T1; #ifdef MEM_WRITE glue(st, MEM_SUFFIX)(A0, T0); #endif } else { EAX = (EAX & ~DATA_MASK) | (T0 & DATA_MASK); } CC_SRC = src; CC_DST = dst; FORCE_RET(); } #undef MEM_SUFFIX #undef MEM_WRITE target-i386/translate.c +151 −172 Original line number Diff line number Diff line Loading @@ -498,65 +498,6 @@ static GenOpFunc *gen_op_cmov_reg_T1_T0[NB_OP_SIZES - 1][CPU_NB_REGS] = { #endif }; #define DEF_ARITHC(SUFFIX)\ {\ gen_op_adcb ## SUFFIX ## _T0_T1_cc,\ gen_op_sbbb ## SUFFIX ## _T0_T1_cc,\ },\ {\ gen_op_adcw ## SUFFIX ## _T0_T1_cc,\ gen_op_sbbw ## SUFFIX ## _T0_T1_cc,\ },\ {\ gen_op_adcl ## SUFFIX ## _T0_T1_cc,\ gen_op_sbbl ## SUFFIX ## _T0_T1_cc,\ },\ {\ X86_64_ONLY(gen_op_adcq ## SUFFIX ## _T0_T1_cc),\ X86_64_ONLY(gen_op_sbbq ## SUFFIX ## _T0_T1_cc),\ }, static GenOpFunc *gen_op_arithc_T0_T1_cc[4][2] = { DEF_ARITHC( ) }; static GenOpFunc *gen_op_arithc_mem_T0_T1_cc[3 * 4][2] = { DEF_ARITHC(_raw) #ifndef CONFIG_USER_ONLY DEF_ARITHC(_kernel) DEF_ARITHC(_user) #endif }; static const int cc_op_arithb[8] = { CC_OP_ADDB, CC_OP_LOGICB, CC_OP_ADDB, CC_OP_SUBB, CC_OP_LOGICB, CC_OP_SUBB, CC_OP_LOGICB, CC_OP_SUBB, }; #define DEF_CMPXCHG(SUFFIX)\ gen_op_cmpxchgb ## SUFFIX ## _T0_T1_EAX_cc,\ gen_op_cmpxchgw ## SUFFIX ## _T0_T1_EAX_cc,\ gen_op_cmpxchgl ## SUFFIX ## _T0_T1_EAX_cc,\ X86_64_ONLY(gen_op_cmpxchgq ## SUFFIX ## _T0_T1_EAX_cc), static GenOpFunc *gen_op_cmpxchg_T0_T1_EAX_cc[4] = { DEF_CMPXCHG( ) }; static GenOpFunc *gen_op_cmpxchg_mem_T0_T1_EAX_cc[3 * 4] = { DEF_CMPXCHG(_raw) #ifndef CONFIG_USER_ONLY DEF_CMPXCHG(_kernel) DEF_CMPXCHG(_user) #endif }; static GenOpFunc *gen_op_btx_T0_T1_cc[3][4] = { [0] = { gen_op_btw_T0_T1_cc, Loading Loading @@ -1257,11 +1198,53 @@ static void *helper_fp_arith_STN_ST0[8] = { helper_fdiv_STN_ST0, }; /* compute eflags.C to reg */ static void gen_compute_eflags_c(TCGv reg) { #if TCG_TARGET_REG_BITS == 32 tcg_gen_shli_i32(cpu_tmp2_i32, cpu_cc_op, 3); tcg_gen_addi_i32(cpu_tmp2_i32, cpu_tmp2_i32, (long)cc_table + offsetof(CCTable, compute_c)); tcg_gen_ld_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0); tcg_gen_call(&tcg_ctx, cpu_tmp2_i32, TCG_CALL_PURE, 1, &cpu_tmp2_i32, 0, NULL); #else tcg_gen_extu_i32_tl(cpu_tmp1_i64, cpu_cc_op); tcg_gen_shli_i64(cpu_tmp1_i64, cpu_tmp1_i64, 4); tcg_gen_addi_i64(cpu_tmp1_i64, cpu_tmp1_i64, (long)cc_table + offsetof(CCTable, compute_c)); tcg_gen_ld_i64(cpu_tmp1_i64, cpu_tmp1_i64, 0); tcg_gen_call(&tcg_ctx, cpu_tmp1_i64, TCG_CALL_PURE, 1, &cpu_tmp2_i32, 0, NULL); #endif tcg_gen_extu_i32_tl(reg, cpu_tmp2_i32); } /* compute all eflags to cc_src */ static void gen_compute_eflags(TCGv reg) { #if TCG_TARGET_REG_BITS == 32 tcg_gen_shli_i32(cpu_tmp2_i32, cpu_cc_op, 3); tcg_gen_addi_i32(cpu_tmp2_i32, cpu_tmp2_i32, (long)cc_table + offsetof(CCTable, compute_all)); tcg_gen_ld_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0); tcg_gen_call(&tcg_ctx, cpu_tmp2_i32, TCG_CALL_PURE, 1, &cpu_tmp2_i32, 0, NULL); #else tcg_gen_extu_i32_tl(cpu_tmp1_i64, cpu_cc_op); tcg_gen_shli_i64(cpu_tmp1_i64, cpu_tmp1_i64, 4); tcg_gen_addi_i64(cpu_tmp1_i64, cpu_tmp1_i64, (long)cc_table + offsetof(CCTable, compute_all)); tcg_gen_ld_i64(cpu_tmp1_i64, cpu_tmp1_i64, 0); tcg_gen_call(&tcg_ctx, cpu_tmp1_i64, TCG_CALL_PURE, 1, &cpu_tmp2_i32, 0, NULL); #endif tcg_gen_extu_i32_tl(reg, cpu_tmp2_i32); } /* if d == OR_TMP0, it means memory operand (address in A0) */ static void gen_op(DisasContext *s1, int op, int ot, int d) { GenOpFunc *gen_update_cc; if (d != OR_TMP0) { gen_op_mov_TN_reg(ot, 0, d); } else { Loading @@ -1269,104 +1252,90 @@ static void gen_op(DisasContext *s1, int op, int ot, int d) } switch(op) { case OP_ADCL: if (s1->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s1->cc_op); gen_compute_eflags_c(cpu_tmp4); tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]); tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_tmp4); if (d != OR_TMP0) gen_op_mov_reg_T0(ot, d); else gen_op_st_T0_A0(ot + s1->mem_index); tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]); tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_tmp4); tcg_gen_shli_i32(cpu_tmp2_i32, cpu_tmp2_i32, 2); tcg_gen_addi_i32(cpu_cc_op, cpu_tmp2_i32, CC_OP_ADDB + ot); s1->cc_op = CC_OP_DYNAMIC; break; case OP_SBBL: if (s1->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s1->cc_op); if (d != OR_TMP0) { gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL](); gen_compute_eflags_c(cpu_tmp4); tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]); tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_tmp4); if (d != OR_TMP0) gen_op_mov_reg_T0(ot, d); } else { gen_op_arithc_mem_T0_T1_cc[ot + s1->mem_index][op - OP_ADCL](); } else gen_op_st_T0_A0(ot + s1->mem_index); tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]); tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_tmp4); tcg_gen_shli_i32(cpu_tmp2_i32, cpu_tmp2_i32, 2); tcg_gen_addi_i32(cpu_cc_op, cpu_tmp2_i32, CC_OP_SUBB + ot); s1->cc_op = CC_OP_DYNAMIC; goto the_end; break; case OP_ADDL: gen_op_addl_T0_T1(); if (d != OR_TMP0) gen_op_mov_reg_T0(ot, d); else gen_op_st_T0_A0(ot + s1->mem_index); gen_op_update2_cc(); s1->cc_op = CC_OP_ADDB + ot; gen_update_cc = gen_op_update2_cc; break; case OP_SUBL: tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]); if (d != OR_TMP0) gen_op_mov_reg_T0(ot, d); else gen_op_st_T0_A0(ot + s1->mem_index); gen_op_update2_cc(); s1->cc_op = CC_OP_SUBB + ot; gen_update_cc = gen_op_update2_cc; break; default: case OP_ANDL: tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]); if (d != OR_TMP0) gen_op_mov_reg_T0(ot, d); else gen_op_st_T0_A0(ot + s1->mem_index); gen_op_update1_cc(); s1->cc_op = CC_OP_LOGICB + ot; gen_update_cc = gen_op_update1_cc; break; case OP_ORL: tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_T[1]); if (d != OR_TMP0) gen_op_mov_reg_T0(ot, d); else gen_op_st_T0_A0(ot + s1->mem_index); gen_op_update1_cc(); s1->cc_op = CC_OP_LOGICB + ot; gen_update_cc = gen_op_update1_cc; break; case OP_XORL: tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_T[1]); if (d != OR_TMP0) gen_op_mov_reg_T0(ot, d); else gen_op_st_T0_A0(ot + s1->mem_index); gen_op_update1_cc(); s1->cc_op = CC_OP_LOGICB + ot; gen_update_cc = gen_op_update1_cc; break; case OP_CMPL: gen_op_cmpl_T0_T1_cc(); s1->cc_op = CC_OP_SUBB + ot; gen_update_cc = NULL; break; } if (op != OP_CMPL) { if (d != OR_TMP0) gen_op_mov_reg_T0(ot, d); else gen_op_st_T0_A0(ot + s1->mem_index); } /* the flags update must happen after the memory write (precise exception support) */ if (gen_update_cc) gen_update_cc(); the_end: ; } /* compute eflags.C to reg */ static void gen_compute_eflags_c(TCGv reg) { #if TCG_TARGET_REG_BITS == 32 tcg_gen_shli_i32(cpu_tmp2_i32, cpu_cc_op, 3); tcg_gen_addi_i32(cpu_tmp2_i32, cpu_tmp2_i32, (long)cc_table + offsetof(CCTable, compute_c)); tcg_gen_ld_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0); tcg_gen_call(&tcg_ctx, cpu_tmp2_i32, TCG_CALL_PURE, 1, ®, 0, NULL); #else tcg_gen_extu_i32_tl(cpu_tmp1_i64, cpu_cc_op); tcg_gen_shli_i64(cpu_tmp1_i64, cpu_tmp1_i64, 4); tcg_gen_addi_i64(cpu_tmp1_i64, cpu_tmp1_i64, (long)cc_table + offsetof(CCTable, compute_c)); tcg_gen_ld_i64(cpu_tmp1_i64, cpu_tmp1_i64, 0); tcg_gen_call(&tcg_ctx, cpu_tmp1_i64, TCG_CALL_PURE, 1, &cpu_tmp2_i32, 0, NULL); tcg_gen_extu_i32_tl(reg, cpu_tmp2_i32); #endif } /* compute all eflags to cc_src */ static void gen_compute_eflags(TCGv reg) { #if TCG_TARGET_REG_BITS == 32 tcg_gen_shli_i32(cpu_tmp2_i32, cpu_cc_op, 3); tcg_gen_addi_i32(cpu_tmp2_i32, cpu_tmp2_i32, (long)cc_table + offsetof(CCTable, compute_all)); tcg_gen_ld_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0); tcg_gen_call(&tcg_ctx, cpu_tmp2_i32, TCG_CALL_PURE, 1, ®, 0, NULL); #else tcg_gen_extu_i32_tl(cpu_tmp1_i64, cpu_cc_op); tcg_gen_shli_i64(cpu_tmp1_i64, cpu_tmp1_i64, 4); tcg_gen_addi_i64(cpu_tmp1_i64, cpu_tmp1_i64, (long)cc_table + offsetof(CCTable, compute_all)); tcg_gen_ld_i64(cpu_tmp1_i64, cpu_tmp1_i64, 0); tcg_gen_call(&tcg_ctx, cpu_tmp1_i64, TCG_CALL_PURE, 1, &cpu_tmp2_i32, 0, NULL); tcg_gen_extu_i32_tl(reg, cpu_tmp2_i32); #endif } /* if d == OR_TMP0, it means memory operand (address in A0) */ Loading @@ -1393,6 +1362,23 @@ static void gen_inc(DisasContext *s1, int ot, int d, int c) gen_compute_eflags_c(cpu_cc_src); } static void gen_extu(int ot, TCGv reg) { switch(ot) { case OT_BYTE: tcg_gen_ext8u_tl(reg, reg); break; case OT_WORD: tcg_gen_ext16u_tl(reg, reg); break; case OT_LONG: tcg_gen_ext32u_tl(reg, reg); break; default: break; } } /* XXX: add faster immediate case */ static void gen_shift_rm_T1(DisasContext *s, int ot, int op1, int is_right, int is_arith) Loading Loading @@ -1433,19 +1419,7 @@ static void gen_shift_rm_T1(DisasContext *s, int ot, int op1, tcg_gen_sar_tl(cpu_T3, cpu_T[0], cpu_tmp5); tcg_gen_sar_tl(cpu_T[0], cpu_T[0], cpu_T[1]); } else { switch(ot) { case OT_BYTE: tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]); break; case OT_WORD: tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]); break; case OT_LONG: tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]); break; default: break; } gen_extu(ot, cpu_T[0]); tcg_gen_shr_tl(cpu_T3, cpu_T[0], cpu_tmp5); tcg_gen_shr_tl(cpu_T[0], cpu_T[0], cpu_T[1]); } Loading Loading @@ -1516,19 +1490,7 @@ static void gen_rot_rm_T1(DisasContext *s, int ot, int op1, else tcg_gen_mov_tl(cpu_tmp0, cpu_T[1]); switch(ot) { case OT_BYTE: tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]); break; case OT_WORD: tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]); break; case OT_LONG: tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]); break; default: break; } gen_extu(ot, cpu_T[0]); tcg_gen_mov_tl(cpu_T3, cpu_T[0]); data_bits = 8 << ot; Loading Loading @@ -4270,6 +4232,9 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) break; case 0x1b0: case 0x1b1: /* cmpxchg Ev, Gv */ { int label1; if ((b & 1) == 0) ot = OT_BYTE; else Loading @@ -4281,14 +4246,28 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (mod == 3) { rm = (modrm & 7) | REX_B(s); gen_op_mov_TN_reg(ot, 0, rm); gen_op_cmpxchg_T0_T1_EAX_cc[ot](); gen_op_mov_reg_T0(ot, rm); } else { gen_lea_modrm(s, modrm, ®_addr, &offset_addr); gen_op_ld_T0_A0(ot + s->mem_index); gen_op_cmpxchg_mem_T0_T1_EAX_cc[ot + s->mem_index](); rm = 0; /* avoid warning */ } label1 = gen_new_label(); tcg_gen_ld_tl(cpu_T3, cpu_env, offsetof(CPUState, regs[R_EAX])); tcg_gen_sub_tl(cpu_T3, cpu_T3, cpu_T[0]); gen_extu(ot, cpu_T3); tcg_gen_brcond_tl(TCG_COND_EQ, cpu_T3, tcg_const_tl(0), label1); tcg_gen_mov_tl(cpu_T[1], cpu_T[0]); gen_op_mov_reg_T0(ot, R_EAX); gen_set_label(label1); if (mod == 3) { gen_op_mov_reg_T1(ot, rm); } else { gen_op_st_T1_A0(ot + s->mem_index); } tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]); tcg_gen_mov_tl(cpu_cc_dst, cpu_T3); s->cc_op = CC_OP_SUBB + ot; } break; case 0x1c7: /* cmpxchg8b */ modrm = ldub_code(s->pc++); Loading Loading
target-i386/ops_template.h +0 −14 Original line number Diff line number Diff line Loading @@ -415,20 +415,6 @@ void OPPROTO glue(op_setle_T0_sub, SUFFIX)(void) T0 = ((DATA_STYPE)src1 <= (DATA_STYPE)src2); } #undef MEM_WRITE #include "ops_template_mem.h" #define MEM_WRITE 0 #include "ops_template_mem.h" #if !defined(CONFIG_USER_ONLY) #define MEM_WRITE 1 #include "ops_template_mem.h" #define MEM_WRITE 2 #include "ops_template_mem.h" #endif /* bit operations */ #if DATA_BITS >= 16 Loading
target-i386/ops_template_mem.hdeleted 100644 → 0 +0 −119 Original line number Diff line number Diff line /* * i386 micro operations (included several times to generate * different operand sizes) * * Copyright (c) 2003 Fabrice Bellard * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef MEM_WRITE #if MEM_WRITE == 0 #if DATA_BITS == 8 #define MEM_SUFFIX b_raw #elif DATA_BITS == 16 #define MEM_SUFFIX w_raw #elif DATA_BITS == 32 #define MEM_SUFFIX l_raw #elif DATA_BITS == 64 #define MEM_SUFFIX q_raw #endif #elif MEM_WRITE == 1 #if DATA_BITS == 8 #define MEM_SUFFIX b_kernel #elif DATA_BITS == 16 #define MEM_SUFFIX w_kernel #elif DATA_BITS == 32 #define MEM_SUFFIX l_kernel #elif DATA_BITS == 64 #define MEM_SUFFIX q_kernel #endif #elif MEM_WRITE == 2 #if DATA_BITS == 8 #define MEM_SUFFIX b_user #elif DATA_BITS == 16 #define MEM_SUFFIX w_user #elif DATA_BITS == 32 #define MEM_SUFFIX l_user #elif DATA_BITS == 64 #define MEM_SUFFIX q_user #endif #else #error invalid MEM_WRITE #endif #else #define MEM_SUFFIX SUFFIX #endif /* carry add/sub (we only need to set CC_OP differently) */ void OPPROTO glue(glue(op_adc, MEM_SUFFIX), _T0_T1_cc)(void) { int cf; cf = cc_table[CC_OP].compute_c(); T0 = T0 + T1 + cf; #ifdef MEM_WRITE glue(st, MEM_SUFFIX)(A0, T0); #endif CC_SRC = T1; CC_DST = T0; CC_OP = CC_OP_ADDB + SHIFT + cf * 4; } void OPPROTO glue(glue(op_sbb, MEM_SUFFIX), _T0_T1_cc)(void) { int cf; cf = cc_table[CC_OP].compute_c(); T0 = T0 - T1 - cf; #ifdef MEM_WRITE glue(st, MEM_SUFFIX)(A0, T0); #endif CC_SRC = T1; CC_DST = T0; CC_OP = CC_OP_SUBB + SHIFT + cf * 4; } void OPPROTO glue(glue(op_cmpxchg, MEM_SUFFIX), _T0_T1_EAX_cc)(void) { target_ulong src, dst; src = T0; dst = EAX - T0; if ((DATA_TYPE)dst == 0) { T0 = T1; #ifdef MEM_WRITE glue(st, MEM_SUFFIX)(A0, T0); #endif } else { EAX = (EAX & ~DATA_MASK) | (T0 & DATA_MASK); } CC_SRC = src; CC_DST = dst; FORCE_RET(); } #undef MEM_SUFFIX #undef MEM_WRITE
target-i386/translate.c +151 −172 Original line number Diff line number Diff line Loading @@ -498,65 +498,6 @@ static GenOpFunc *gen_op_cmov_reg_T1_T0[NB_OP_SIZES - 1][CPU_NB_REGS] = { #endif }; #define DEF_ARITHC(SUFFIX)\ {\ gen_op_adcb ## SUFFIX ## _T0_T1_cc,\ gen_op_sbbb ## SUFFIX ## _T0_T1_cc,\ },\ {\ gen_op_adcw ## SUFFIX ## _T0_T1_cc,\ gen_op_sbbw ## SUFFIX ## _T0_T1_cc,\ },\ {\ gen_op_adcl ## SUFFIX ## _T0_T1_cc,\ gen_op_sbbl ## SUFFIX ## _T0_T1_cc,\ },\ {\ X86_64_ONLY(gen_op_adcq ## SUFFIX ## _T0_T1_cc),\ X86_64_ONLY(gen_op_sbbq ## SUFFIX ## _T0_T1_cc),\ }, static GenOpFunc *gen_op_arithc_T0_T1_cc[4][2] = { DEF_ARITHC( ) }; static GenOpFunc *gen_op_arithc_mem_T0_T1_cc[3 * 4][2] = { DEF_ARITHC(_raw) #ifndef CONFIG_USER_ONLY DEF_ARITHC(_kernel) DEF_ARITHC(_user) #endif }; static const int cc_op_arithb[8] = { CC_OP_ADDB, CC_OP_LOGICB, CC_OP_ADDB, CC_OP_SUBB, CC_OP_LOGICB, CC_OP_SUBB, CC_OP_LOGICB, CC_OP_SUBB, }; #define DEF_CMPXCHG(SUFFIX)\ gen_op_cmpxchgb ## SUFFIX ## _T0_T1_EAX_cc,\ gen_op_cmpxchgw ## SUFFIX ## _T0_T1_EAX_cc,\ gen_op_cmpxchgl ## SUFFIX ## _T0_T1_EAX_cc,\ X86_64_ONLY(gen_op_cmpxchgq ## SUFFIX ## _T0_T1_EAX_cc), static GenOpFunc *gen_op_cmpxchg_T0_T1_EAX_cc[4] = { DEF_CMPXCHG( ) }; static GenOpFunc *gen_op_cmpxchg_mem_T0_T1_EAX_cc[3 * 4] = { DEF_CMPXCHG(_raw) #ifndef CONFIG_USER_ONLY DEF_CMPXCHG(_kernel) DEF_CMPXCHG(_user) #endif }; static GenOpFunc *gen_op_btx_T0_T1_cc[3][4] = { [0] = { gen_op_btw_T0_T1_cc, Loading Loading @@ -1257,11 +1198,53 @@ static void *helper_fp_arith_STN_ST0[8] = { helper_fdiv_STN_ST0, }; /* compute eflags.C to reg */ static void gen_compute_eflags_c(TCGv reg) { #if TCG_TARGET_REG_BITS == 32 tcg_gen_shli_i32(cpu_tmp2_i32, cpu_cc_op, 3); tcg_gen_addi_i32(cpu_tmp2_i32, cpu_tmp2_i32, (long)cc_table + offsetof(CCTable, compute_c)); tcg_gen_ld_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0); tcg_gen_call(&tcg_ctx, cpu_tmp2_i32, TCG_CALL_PURE, 1, &cpu_tmp2_i32, 0, NULL); #else tcg_gen_extu_i32_tl(cpu_tmp1_i64, cpu_cc_op); tcg_gen_shli_i64(cpu_tmp1_i64, cpu_tmp1_i64, 4); tcg_gen_addi_i64(cpu_tmp1_i64, cpu_tmp1_i64, (long)cc_table + offsetof(CCTable, compute_c)); tcg_gen_ld_i64(cpu_tmp1_i64, cpu_tmp1_i64, 0); tcg_gen_call(&tcg_ctx, cpu_tmp1_i64, TCG_CALL_PURE, 1, &cpu_tmp2_i32, 0, NULL); #endif tcg_gen_extu_i32_tl(reg, cpu_tmp2_i32); } /* compute all eflags to cc_src */ static void gen_compute_eflags(TCGv reg) { #if TCG_TARGET_REG_BITS == 32 tcg_gen_shli_i32(cpu_tmp2_i32, cpu_cc_op, 3); tcg_gen_addi_i32(cpu_tmp2_i32, cpu_tmp2_i32, (long)cc_table + offsetof(CCTable, compute_all)); tcg_gen_ld_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0); tcg_gen_call(&tcg_ctx, cpu_tmp2_i32, TCG_CALL_PURE, 1, &cpu_tmp2_i32, 0, NULL); #else tcg_gen_extu_i32_tl(cpu_tmp1_i64, cpu_cc_op); tcg_gen_shli_i64(cpu_tmp1_i64, cpu_tmp1_i64, 4); tcg_gen_addi_i64(cpu_tmp1_i64, cpu_tmp1_i64, (long)cc_table + offsetof(CCTable, compute_all)); tcg_gen_ld_i64(cpu_tmp1_i64, cpu_tmp1_i64, 0); tcg_gen_call(&tcg_ctx, cpu_tmp1_i64, TCG_CALL_PURE, 1, &cpu_tmp2_i32, 0, NULL); #endif tcg_gen_extu_i32_tl(reg, cpu_tmp2_i32); } /* if d == OR_TMP0, it means memory operand (address in A0) */ static void gen_op(DisasContext *s1, int op, int ot, int d) { GenOpFunc *gen_update_cc; if (d != OR_TMP0) { gen_op_mov_TN_reg(ot, 0, d); } else { Loading @@ -1269,104 +1252,90 @@ static void gen_op(DisasContext *s1, int op, int ot, int d) } switch(op) { case OP_ADCL: if (s1->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s1->cc_op); gen_compute_eflags_c(cpu_tmp4); tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]); tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_tmp4); if (d != OR_TMP0) gen_op_mov_reg_T0(ot, d); else gen_op_st_T0_A0(ot + s1->mem_index); tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]); tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_tmp4); tcg_gen_shli_i32(cpu_tmp2_i32, cpu_tmp2_i32, 2); tcg_gen_addi_i32(cpu_cc_op, cpu_tmp2_i32, CC_OP_ADDB + ot); s1->cc_op = CC_OP_DYNAMIC; break; case OP_SBBL: if (s1->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s1->cc_op); if (d != OR_TMP0) { gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL](); gen_compute_eflags_c(cpu_tmp4); tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]); tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_tmp4); if (d != OR_TMP0) gen_op_mov_reg_T0(ot, d); } else { gen_op_arithc_mem_T0_T1_cc[ot + s1->mem_index][op - OP_ADCL](); } else gen_op_st_T0_A0(ot + s1->mem_index); tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]); tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_tmp4); tcg_gen_shli_i32(cpu_tmp2_i32, cpu_tmp2_i32, 2); tcg_gen_addi_i32(cpu_cc_op, cpu_tmp2_i32, CC_OP_SUBB + ot); s1->cc_op = CC_OP_DYNAMIC; goto the_end; break; case OP_ADDL: gen_op_addl_T0_T1(); if (d != OR_TMP0) gen_op_mov_reg_T0(ot, d); else gen_op_st_T0_A0(ot + s1->mem_index); gen_op_update2_cc(); s1->cc_op = CC_OP_ADDB + ot; gen_update_cc = gen_op_update2_cc; break; case OP_SUBL: tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]); if (d != OR_TMP0) gen_op_mov_reg_T0(ot, d); else gen_op_st_T0_A0(ot + s1->mem_index); gen_op_update2_cc(); s1->cc_op = CC_OP_SUBB + ot; gen_update_cc = gen_op_update2_cc; break; default: case OP_ANDL: tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]); if (d != OR_TMP0) gen_op_mov_reg_T0(ot, d); else gen_op_st_T0_A0(ot + s1->mem_index); gen_op_update1_cc(); s1->cc_op = CC_OP_LOGICB + ot; gen_update_cc = gen_op_update1_cc; break; case OP_ORL: tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_T[1]); if (d != OR_TMP0) gen_op_mov_reg_T0(ot, d); else gen_op_st_T0_A0(ot + s1->mem_index); gen_op_update1_cc(); s1->cc_op = CC_OP_LOGICB + ot; gen_update_cc = gen_op_update1_cc; break; case OP_XORL: tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_T[1]); if (d != OR_TMP0) gen_op_mov_reg_T0(ot, d); else gen_op_st_T0_A0(ot + s1->mem_index); gen_op_update1_cc(); s1->cc_op = CC_OP_LOGICB + ot; gen_update_cc = gen_op_update1_cc; break; case OP_CMPL: gen_op_cmpl_T0_T1_cc(); s1->cc_op = CC_OP_SUBB + ot; gen_update_cc = NULL; break; } if (op != OP_CMPL) { if (d != OR_TMP0) gen_op_mov_reg_T0(ot, d); else gen_op_st_T0_A0(ot + s1->mem_index); } /* the flags update must happen after the memory write (precise exception support) */ if (gen_update_cc) gen_update_cc(); the_end: ; } /* compute eflags.C to reg */ static void gen_compute_eflags_c(TCGv reg) { #if TCG_TARGET_REG_BITS == 32 tcg_gen_shli_i32(cpu_tmp2_i32, cpu_cc_op, 3); tcg_gen_addi_i32(cpu_tmp2_i32, cpu_tmp2_i32, (long)cc_table + offsetof(CCTable, compute_c)); tcg_gen_ld_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0); tcg_gen_call(&tcg_ctx, cpu_tmp2_i32, TCG_CALL_PURE, 1, ®, 0, NULL); #else tcg_gen_extu_i32_tl(cpu_tmp1_i64, cpu_cc_op); tcg_gen_shli_i64(cpu_tmp1_i64, cpu_tmp1_i64, 4); tcg_gen_addi_i64(cpu_tmp1_i64, cpu_tmp1_i64, (long)cc_table + offsetof(CCTable, compute_c)); tcg_gen_ld_i64(cpu_tmp1_i64, cpu_tmp1_i64, 0); tcg_gen_call(&tcg_ctx, cpu_tmp1_i64, TCG_CALL_PURE, 1, &cpu_tmp2_i32, 0, NULL); tcg_gen_extu_i32_tl(reg, cpu_tmp2_i32); #endif } /* compute all eflags to cc_src */ static void gen_compute_eflags(TCGv reg) { #if TCG_TARGET_REG_BITS == 32 tcg_gen_shli_i32(cpu_tmp2_i32, cpu_cc_op, 3); tcg_gen_addi_i32(cpu_tmp2_i32, cpu_tmp2_i32, (long)cc_table + offsetof(CCTable, compute_all)); tcg_gen_ld_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0); tcg_gen_call(&tcg_ctx, cpu_tmp2_i32, TCG_CALL_PURE, 1, ®, 0, NULL); #else tcg_gen_extu_i32_tl(cpu_tmp1_i64, cpu_cc_op); tcg_gen_shli_i64(cpu_tmp1_i64, cpu_tmp1_i64, 4); tcg_gen_addi_i64(cpu_tmp1_i64, cpu_tmp1_i64, (long)cc_table + offsetof(CCTable, compute_all)); tcg_gen_ld_i64(cpu_tmp1_i64, cpu_tmp1_i64, 0); tcg_gen_call(&tcg_ctx, cpu_tmp1_i64, TCG_CALL_PURE, 1, &cpu_tmp2_i32, 0, NULL); tcg_gen_extu_i32_tl(reg, cpu_tmp2_i32); #endif } /* if d == OR_TMP0, it means memory operand (address in A0) */ Loading @@ -1393,6 +1362,23 @@ static void gen_inc(DisasContext *s1, int ot, int d, int c) gen_compute_eflags_c(cpu_cc_src); } static void gen_extu(int ot, TCGv reg) { switch(ot) { case OT_BYTE: tcg_gen_ext8u_tl(reg, reg); break; case OT_WORD: tcg_gen_ext16u_tl(reg, reg); break; case OT_LONG: tcg_gen_ext32u_tl(reg, reg); break; default: break; } } /* XXX: add faster immediate case */ static void gen_shift_rm_T1(DisasContext *s, int ot, int op1, int is_right, int is_arith) Loading Loading @@ -1433,19 +1419,7 @@ static void gen_shift_rm_T1(DisasContext *s, int ot, int op1, tcg_gen_sar_tl(cpu_T3, cpu_T[0], cpu_tmp5); tcg_gen_sar_tl(cpu_T[0], cpu_T[0], cpu_T[1]); } else { switch(ot) { case OT_BYTE: tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]); break; case OT_WORD: tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]); break; case OT_LONG: tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]); break; default: break; } gen_extu(ot, cpu_T[0]); tcg_gen_shr_tl(cpu_T3, cpu_T[0], cpu_tmp5); tcg_gen_shr_tl(cpu_T[0], cpu_T[0], cpu_T[1]); } Loading Loading @@ -1516,19 +1490,7 @@ static void gen_rot_rm_T1(DisasContext *s, int ot, int op1, else tcg_gen_mov_tl(cpu_tmp0, cpu_T[1]); switch(ot) { case OT_BYTE: tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]); break; case OT_WORD: tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]); break; case OT_LONG: tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]); break; default: break; } gen_extu(ot, cpu_T[0]); tcg_gen_mov_tl(cpu_T3, cpu_T[0]); data_bits = 8 << ot; Loading Loading @@ -4270,6 +4232,9 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) break; case 0x1b0: case 0x1b1: /* cmpxchg Ev, Gv */ { int label1; if ((b & 1) == 0) ot = OT_BYTE; else Loading @@ -4281,14 +4246,28 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (mod == 3) { rm = (modrm & 7) | REX_B(s); gen_op_mov_TN_reg(ot, 0, rm); gen_op_cmpxchg_T0_T1_EAX_cc[ot](); gen_op_mov_reg_T0(ot, rm); } else { gen_lea_modrm(s, modrm, ®_addr, &offset_addr); gen_op_ld_T0_A0(ot + s->mem_index); gen_op_cmpxchg_mem_T0_T1_EAX_cc[ot + s->mem_index](); rm = 0; /* avoid warning */ } label1 = gen_new_label(); tcg_gen_ld_tl(cpu_T3, cpu_env, offsetof(CPUState, regs[R_EAX])); tcg_gen_sub_tl(cpu_T3, cpu_T3, cpu_T[0]); gen_extu(ot, cpu_T3); tcg_gen_brcond_tl(TCG_COND_EQ, cpu_T3, tcg_const_tl(0), label1); tcg_gen_mov_tl(cpu_T[1], cpu_T[0]); gen_op_mov_reg_T0(ot, R_EAX); gen_set_label(label1); if (mod == 3) { gen_op_mov_reg_T1(ot, rm); } else { gen_op_st_T1_A0(ot + s->mem_index); } tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]); tcg_gen_mov_tl(cpu_cc_dst, cpu_T3); s->cc_op = CC_OP_SUBB + ot; } break; case 0x1c7: /* cmpxchg8b */ modrm = ldub_code(s->pc++); Loading