diff options
Diffstat (limited to 'target-i386')
-rw-r--r-- | target-i386/translate.c | 104 |
1 files changed, 58 insertions, 46 deletions
diff --git a/target-i386/translate.c b/target-i386/translate.c index a902f4a8bf..1988dae290 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -38,18 +38,10 @@ #define PREFIX_ADR 0x10 #ifdef TARGET_X86_64 -#define X86_64_ONLY(x) x -#define X86_64_DEF(...) __VA_ARGS__ #define CODE64(s) ((s)->code64) #define REX_X(s) ((s)->rex_x) #define REX_B(s) ((s)->rex_b) -/* XXX: gcc generates push/pop in some opcodes, so we cannot use them */ -#if 1 -#define BUGGY_64(x) NULL -#endif #else -#define X86_64_ONLY(x) NULL -#define X86_64_DEF(...) #define CODE64(s) 0 #define REX_X(s) 0 #define REX_B(s) 0 @@ -271,11 +263,30 @@ static inline void gen_op_andl_A0_ffff(void) #define REG_LH_OFFSET 4 #endif +/* In instruction encodings for byte register accesses the + * register number usually indicates "low 8 bits of register N"; + * however there are some special cases where N 4..7 indicates + * [AH, CH, DH, BH], ie "bits 15..8 of register N-4". Return + * true for this special case, false otherwise. + */ +static inline bool byte_reg_is_xH(int reg) +{ + if (reg < 4) { + return false; + } +#ifdef TARGET_X86_64 + if (reg >= 8 || x86_64_hregs) { + return false; + } +#endif + return true; +} + static inline void gen_op_mov_reg_v(int ot, int reg, TCGv t0) { switch(ot) { case OT_BYTE: - if (reg < 4 X86_64_DEF( || reg >= 8 || x86_64_hregs)) { + if (!byte_reg_is_xH(reg)) { tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 8); } else { tcg_gen_deposit_tl(cpu_regs[reg - 4], cpu_regs[reg - 4], t0, 8, 8); @@ -330,19 +341,11 @@ static inline void gen_op_mov_reg_A0(int size, int reg) static inline void gen_op_mov_v_reg(int ot, TCGv t0, int reg) { - switch(ot) { - case OT_BYTE: - if (reg < 4 X86_64_DEF( || reg >= 8 || x86_64_hregs)) { - goto std_case; - } else { - tcg_gen_shri_tl(t0, cpu_regs[reg - 4], 8); - tcg_gen_ext8u_tl(t0, t0); - } - break; - default: - std_case: + if (ot == OT_BYTE && byte_reg_is_xH(reg)) { + tcg_gen_shri_tl(t0, cpu_regs[reg - 4], 8); + tcg_gen_ext8u_tl(t0, t0); + } else { tcg_gen_mov_tl(t0, cpu_regs[reg]); - break; } } @@ -2947,24 +2950,33 @@ static const SSEFunc_0_pp sse_op_table2[3 * 8][2] = { [16 + 7] = { NULL, gen_helper_pslldq_xmm }, }; -static const SSEFunc_0_pi sse_op_table3a[4] = { +static const SSEFunc_0_pi sse_op_table3ai[] = { gen_helper_cvtsi2ss, - gen_helper_cvtsi2sd, - X86_64_ONLY(gen_helper_cvtsq2ss), - X86_64_ONLY(gen_helper_cvtsq2sd), + gen_helper_cvtsi2sd }; -static const SSEFunc_i_p sse_op_table3b[4 * 2] = { +#ifdef TARGET_X86_64 +static const SSEFunc_0_pl sse_op_table3aq[] = { + gen_helper_cvtsq2ss, + gen_helper_cvtsq2sd +}; +#endif + +static const SSEFunc_i_p sse_op_table3bi[] = { gen_helper_cvttss2si, + gen_helper_cvtss2si, gen_helper_cvttsd2si, - X86_64_ONLY(gen_helper_cvttss2sq), - X86_64_ONLY(gen_helper_cvttsd2sq), + gen_helper_cvtsd2si +}; - gen_helper_cvtss2si, - gen_helper_cvtsd2si, - X86_64_ONLY(gen_helper_cvtss2sq), - X86_64_ONLY(gen_helper_cvtsd2sq), +#ifdef TARGET_X86_64 +static const SSEFunc_l_p sse_op_table3bq[] = { + gen_helper_cvttss2sq, + gen_helper_cvtss2sq, + gen_helper_cvttsd2sq, + gen_helper_cvtsd2sq }; +#endif static const SSEFunc_0_pp sse_op_table4[8][4] = { SSE_FOP(cmpeq), @@ -3097,10 +3109,6 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) { int b1, op1_offset, op2_offset, is_xmm, val, ot; int modrm, mod, rm, reg, reg_addr, offset_addr; - SSEFunc_i_p sse_fn_i_p; - SSEFunc_l_p sse_fn_l_p; - SSEFunc_0_pi sse_fn_pi; - SSEFunc_0_pl sse_fn_pl; SSEFunc_0_pp sse_fn_pp; SSEFunc_0_ppi sse_fn_ppi; SSEFunc_0_ppt sse_fn_ppt; @@ -3563,14 +3571,16 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) op1_offset = offsetof(CPUX86State,xmm_regs[reg]); tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); if (ot == OT_LONG) { - sse_fn_pi = sse_op_table3a[(s->dflag == 2) * 2 + - ((b >> 8) - 2)]; + SSEFunc_0_pi sse_fn_pi = sse_op_table3ai[(b >> 8) & 1]; tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); sse_fn_pi(cpu_ptr0, cpu_tmp2_i32); } else { - sse_fn_pl = sse_op_table3a[(s->dflag == 2) * 2 + - ((b >> 8) - 2)]; +#ifdef TARGET_X86_64 + SSEFunc_0_pl sse_fn_pl = sse_op_table3aq[(b >> 8) & 1]; sse_fn_pl(cpu_ptr0, cpu_T[0]); +#else + goto illegal_op; +#endif } break; case 0x02c: /* cvttps2pi */ @@ -3624,16 +3634,18 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) } tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset); if (ot == OT_LONG) { - sse_fn_i_p = sse_op_table3b[(s->dflag == 2) * 2 + - ((b >> 8) - 2) + - (b & 1) * 4]; + SSEFunc_i_p sse_fn_i_p = + sse_op_table3bi[((b >> 7) & 2) | (b & 1)]; sse_fn_i_p(cpu_tmp2_i32, cpu_ptr0); tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32); } else { - sse_fn_l_p = sse_op_table3b[(s->dflag == 2) * 2 + - ((b >> 8) - 2) + - (b & 1) * 4]; +#ifdef TARGET_X86_64 + SSEFunc_l_p sse_fn_l_p = + sse_op_table3bq[((b >> 7) & 2) | (b & 1)]; sse_fn_l_p(cpu_T[0], cpu_ptr0); +#else + goto illegal_op; +#endif } gen_op_mov_reg_T0(ot, reg); break; |