diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2003-06-30 10:11:50 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2003-06-30 10:11:50 +0000 |
commit | 5797fa5d7ef49ce4beec9586af0cc9c63f7a4b3a (patch) | |
tree | 65e1699621d97cf7a9abef99c8ff6ca644e8679d | |
parent | 8ef9a8ece3aa8c92eccf998aaac5f38d74acb757 (diff) |
first step to fix precise eflags update in case of exception
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@293 c046a42c-6fe2-441c-8c8c-71466251a162
-rw-r--r-- | op-i386.c | 46 | ||||
-rw-r--r-- | op_string.h | 12 | ||||
-rw-r--r-- | ops_template.h | 54 | ||||
-rw-r--r-- | translate-i386.c | 155 |
4 files changed, 129 insertions, 138 deletions
@@ -80,62 +80,34 @@ static inline int lshift(int x, int n) /* operations with flags */ -void OPPROTO op_addl_T0_T1_cc(void) +/* update flags with T0 and T1 (add/sub case) */ +void OPPROTO op_update2_cc(void) { - CC_SRC = T0; - T0 += T1; + CC_SRC = T1; CC_DST = T0; } -void OPPROTO op_orl_T0_T1_cc(void) +/* update flags with T0 (logic operation case) */ +void OPPROTO op_update1_cc(void) { - T0 |= T1; - CC_DST = T0; -} - -void OPPROTO op_andl_T0_T1_cc(void) -{ - T0 &= T1; CC_DST = T0; } -void OPPROTO op_subl_T0_T1_cc(void) +void OPPROTO op_update_neg_cc(void) { - CC_SRC = T0; - T0 -= T1; - CC_DST = T0; -} - -void OPPROTO op_xorl_T0_T1_cc(void) -{ - T0 ^= T1; + CC_SRC = -T0; CC_DST = T0; } void OPPROTO op_cmpl_T0_T1_cc(void) { - CC_SRC = T0; + CC_SRC = T1; CC_DST = T0 - T1; } -void OPPROTO op_negl_T0_cc(void) -{ - CC_SRC = 0; - T0 = -T0; - CC_DST = T0; -} - -void OPPROTO op_incl_T0_cc(void) -{ - CC_SRC = cc_table[CC_OP].compute_c(); - T0++; - CC_DST = T0; -} - -void OPPROTO op_decl_T0_cc(void) +void OPPROTO op_update_inc_cc(void) { CC_SRC = cc_table[CC_OP].compute_c(); - T0--; CC_DST = T0; } diff --git a/op_string.h b/op_string.h index c7ff74c05c..66945b92e9 100644 --- a/op_string.h +++ b/op_string.h @@ -86,7 +86,7 @@ void OPPROTO glue(glue(op_scas, SUFFIX), STRING_SUFFIX)(void) v = glue(ldu, SUFFIX)(DI_ADDR); inc = (DF << SHIFT); INC_DI(); - CC_SRC = EAX; + CC_SRC = v; CC_DST = EAX - v; } @@ -105,7 +105,7 @@ void OPPROTO glue(glue(op_repz_scas, SUFFIX), STRING_SUFFIX)(void) if (v1 != v2) break; } while (CX != 0); - CC_SRC = v1; + CC_SRC = v2; CC_DST = v1 - v2; CC_OP = CC_OP_SUBB + SHIFT; } @@ -127,7 +127,7 @@ void OPPROTO glue(glue(op_repnz_scas, SUFFIX), STRING_SUFFIX)(void) if (v1 == v2) break; } while (CX != 0); - CC_SRC = v1; + CC_SRC = v2; CC_DST = v1 - v2; CC_OP = CC_OP_SUBB + SHIFT; } @@ -142,7 +142,7 @@ void OPPROTO glue(glue(op_cmps, SUFFIX), STRING_SUFFIX)(void) inc = (DF << SHIFT); INC_SI(); INC_DI(); - CC_SRC = v1; + CC_SRC = v2; CC_DST = v1 - v2; } @@ -160,7 +160,7 @@ void OPPROTO glue(glue(op_repz_cmps, SUFFIX), STRING_SUFFIX)(void) if (v1 != v2) break; } while (CX != 0); - CC_SRC = v1; + CC_SRC = v2; CC_DST = v1 - v2; CC_OP = CC_OP_SUBB + SHIFT; } @@ -181,7 +181,7 @@ void OPPROTO glue(glue(op_repnz_cmps, SUFFIX), STRING_SUFFIX)(void) if (v1 == v2) break; } while (CX != 0); - CC_SRC = v1; + CC_SRC = v2; CC_DST = v1 - v2; CC_OP = CC_OP_SUBB + SHIFT; } diff --git a/ops_template.h b/ops_template.h index 784c27805c..c6e2b6b971 100644 --- a/ops_template.h +++ b/ops_template.h @@ -93,8 +93,8 @@ static int glue(compute_all_sub, SUFFIX)(void) { int cf, pf, af, zf, sf, of; int src1, src2; - src1 = CC_SRC; - src2 = CC_SRC - CC_DST; + src1 = CC_DST + CC_SRC; + src2 = CC_SRC; cf = (DATA_TYPE)src1 < (DATA_TYPE)src2; pf = parity_table[(uint8_t)CC_DST]; af = (CC_DST ^ src1 ^ src2) & 0x10; @@ -107,8 +107,8 @@ static int glue(compute_all_sub, SUFFIX)(void) static int glue(compute_c_sub, SUFFIX)(void) { int src1, src2, cf; - src1 = CC_SRC; - src2 = CC_SRC - CC_DST; + src1 = CC_DST + CC_SRC; + src2 = CC_SRC; cf = (DATA_TYPE)src1 < (DATA_TYPE)src2; return cf; } @@ -117,8 +117,8 @@ static int glue(compute_all_sbb, SUFFIX)(void) { int cf, pf, af, zf, sf, of; int src1, src2; - src1 = CC_SRC; - src2 = CC_SRC - CC_DST - 1; + src1 = CC_DST + CC_SRC + 1; + src2 = CC_SRC; cf = (DATA_TYPE)src1 <= (DATA_TYPE)src2; pf = parity_table[(uint8_t)CC_DST]; af = (CC_DST ^ src1 ^ src2) & 0x10; @@ -131,8 +131,8 @@ static int glue(compute_all_sbb, SUFFIX)(void) static int glue(compute_c_sbb, SUFFIX)(void) { int src1, src2, cf; - src1 = CC_SRC; - src2 = CC_SRC - CC_DST - 1; + src1 = CC_DST + CC_SRC + 1; + src2 = CC_SRC; cf = (DATA_TYPE)src1 <= (DATA_TYPE)src2; return cf; } @@ -234,8 +234,8 @@ static int glue(compute_all_sar, SUFFIX)(void) void OPPROTO glue(op_jb_sub, SUFFIX)(void) { int src1, src2; - src1 = CC_SRC; - src2 = CC_SRC - CC_DST; + src1 = CC_DST + CC_SRC; + src2 = CC_SRC; if ((DATA_TYPE)src1 < (DATA_TYPE)src2) JUMP_TB(PARAM1, 0, PARAM2); @@ -256,8 +256,8 @@ void OPPROTO glue(op_jz_sub, SUFFIX)(void) void OPPROTO glue(op_jbe_sub, SUFFIX)(void) { int src1, src2; - src1 = CC_SRC; - src2 = CC_SRC - CC_DST; + src1 = CC_DST + CC_SRC; + src2 = CC_SRC; if ((DATA_TYPE)src1 <= (DATA_TYPE)src2) JUMP_TB(PARAM1, 0, PARAM2); @@ -278,8 +278,8 @@ void OPPROTO glue(op_js_sub, SUFFIX)(void) void OPPROTO glue(op_jl_sub, SUFFIX)(void) { int src1, src2; - src1 = CC_SRC; - src2 = CC_SRC - CC_DST; + src1 = CC_DST + CC_SRC; + src2 = CC_SRC; if ((DATA_STYPE)src1 < (DATA_STYPE)src2) JUMP_TB(PARAM1, 0, PARAM2); @@ -291,8 +291,8 @@ void OPPROTO glue(op_jl_sub, SUFFIX)(void) void OPPROTO glue(op_jle_sub, SUFFIX)(void) { int src1, src2; - src1 = CC_SRC; - src2 = CC_SRC - CC_DST; + src1 = CC_DST + CC_SRC; + src2 = CC_SRC; if ((DATA_STYPE)src1 <= (DATA_STYPE)src2) JUMP_TB(PARAM1, 0, PARAM2); @@ -361,8 +361,8 @@ void OPPROTO glue(op_jecxz, SUFFIX)(void) void OPPROTO glue(op_setb_T0_sub, SUFFIX)(void) { int src1, src2; - src1 = CC_SRC; - src2 = CC_SRC - CC_DST; + src1 = CC_DST + CC_SRC; + src2 = CC_SRC; T0 = ((DATA_TYPE)src1 < (DATA_TYPE)src2); } @@ -375,8 +375,8 @@ void OPPROTO glue(op_setz_T0_sub, SUFFIX)(void) void OPPROTO glue(op_setbe_T0_sub, SUFFIX)(void) { int src1, src2; - src1 = CC_SRC; - src2 = CC_SRC - CC_DST; + src1 = CC_DST + CC_SRC; + src2 = CC_SRC; T0 = ((DATA_TYPE)src1 <= (DATA_TYPE)src2); } @@ -389,8 +389,8 @@ void OPPROTO glue(op_sets_T0_sub, SUFFIX)(void) void OPPROTO glue(op_setl_T0_sub, SUFFIX)(void) { int src1, src2; - src1 = CC_SRC; - src2 = CC_SRC - CC_DST; + src1 = CC_DST + CC_SRC; + src2 = CC_SRC; T0 = ((DATA_STYPE)src1 < (DATA_STYPE)src2); } @@ -398,8 +398,8 @@ void OPPROTO glue(op_setl_T0_sub, SUFFIX)(void) void OPPROTO glue(op_setle_T0_sub, SUFFIX)(void) { int src1, src2; - src1 = CC_SRC; - src2 = CC_SRC - CC_DST; + src1 = CC_DST + CC_SRC; + src2 = CC_SRC; T0 = ((DATA_STYPE)src1 <= (DATA_STYPE)src2); } @@ -714,9 +714,7 @@ void OPPROTO glue(glue(op_adc, SUFFIX), _T0_T1_cc)(void) { int cf; cf = cc_table[CC_OP].compute_c(); - CC_SRC = T0; T0 = T0 + T1 + cf; - CC_DST = T0; CC_OP = CC_OP_ADDB + SHIFT + cf * 3; } @@ -724,15 +722,13 @@ void OPPROTO glue(glue(op_sbb, SUFFIX), _T0_T1_cc)(void) { int cf; cf = cc_table[CC_OP].compute_c(); - CC_SRC = T0; T0 = T0 - T1 - cf; - CC_DST = T0; CC_OP = CC_OP_SUBB + SHIFT + cf * 3; } void OPPROTO glue(glue(op_cmpxchg, SUFFIX), _T0_T1_EAX_cc)(void) { - CC_SRC = EAX; + CC_SRC = T0; CC_DST = EAX - T0; if ((DATA_TYPE)CC_DST == 0) { T0 = T1; diff --git a/translate-i386.c b/translate-i386.c index d986752dae..b477ac4adb 100644 --- a/translate-i386.c +++ b/translate-i386.c @@ -365,14 +365,14 @@ static GenOpFunc *gen_op_cmov_reg_T1_T0[2][8] = { }; static GenOpFunc *gen_op_arith_T0_T1_cc[8] = { - gen_op_addl_T0_T1_cc, - gen_op_orl_T0_T1_cc, NULL, + gen_op_orl_T0_T1, + NULL, + NULL, + gen_op_andl_T0_T1, + NULL, + gen_op_xorl_T0_T1, NULL, - gen_op_andl_T0_T1_cc, - gen_op_subl_T0_T1_cc, - gen_op_xorl_T0_T1_cc, - gen_op_cmpl_T0_T1_cc, }; static GenOpFunc *gen_op_arithc_T0_T1_cc[3][2] = { @@ -748,46 +748,83 @@ static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = { gen_op_fdiv_STN_ST0, }; -static void gen_op(DisasContext *s1, int op, int ot, int d, int s) +/* if d == OR_TMP0, it means memory operand (address in A0) */ +static void gen_op(DisasContext *s1, int op, int ot, int d) { - if (d != OR_TMP0) + GenOpFunc *gen_update_cc; + + if (d != OR_TMP0) { gen_op_mov_TN_reg[ot][0][d](); - if (s != OR_TMP1) - gen_op_mov_TN_reg[ot][1][s](); - if (op == OP_ADCL || op == OP_SBBL) { + } else { + gen_op_ld_T0_A0[ot](); + } + switch(op) { + case OP_ADCL: + case OP_SBBL: if (s1->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s1->cc_op); gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL](); s1->cc_op = CC_OP_DYNAMIC; - } else { + /* XXX: incorrect: CC_OP must also be modified AFTER memory access */ + gen_update_cc = gen_op_update2_cc; + break; + case OP_ADDL: + gen_op_addl_T0_T1(); + s1->cc_op = CC_OP_ADDB + ot; + gen_update_cc = gen_op_update2_cc; + break; + case OP_SUBL: + gen_op_subl_T0_T1(); + s1->cc_op = CC_OP_SUBB + ot; + gen_update_cc = gen_op_update2_cc; + break; + default: + case OP_ANDL: + case OP_ORL: + case OP_XORL: gen_op_arith_T0_T1_cc[op](); - s1->cc_op = cc_op_arithb[op] + ot; + 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 (d != OR_TMP0 && op != OP_CMPL) - gen_op_mov_reg_T0[ot][d](); -} - -static void gen_opi(DisasContext *s1, int op, int ot, int d, int c) -{ - gen_op_movl_T1_im(c); - gen_op(s1, op, ot, d, OR_TMP1); + if (op != OP_CMPL) { + if (d != OR_TMP0) + gen_op_mov_reg_T0[ot][d](); + else + gen_op_st_T0_A0[ot](); + } + /* the flags update must happen after the memory write (precise + exception support) */ + if (gen_update_cc) + gen_update_cc(); } +/* if d == OR_TMP0, it means memory operand (address in A0) */ static void gen_inc(DisasContext *s1, int ot, int d, int c) { if (d != OR_TMP0) gen_op_mov_TN_reg[ot][0][d](); + else + gen_op_ld_T0_A0[ot](); if (s1->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s1->cc_op); if (c > 0) { - gen_op_incl_T0_cc(); + gen_op_incl_T0(); s1->cc_op = CC_OP_INCB + ot; } else { - gen_op_decl_T0_cc(); + gen_op_decl_T0(); s1->cc_op = CC_OP_DECB + ot; } if (d != OR_TMP0) gen_op_mov_reg_T0[ot][d](); + else + gen_op_st_T0_A0[ot](); + gen_op_update_inc_cc(); } static void gen_shift(DisasContext *s1, int op, int ot, int d, int s) @@ -1459,15 +1496,12 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) rm = modrm & 7; if (mod != 3) { gen_lea_modrm(s, modrm, ®_addr, &offset_addr); - gen_op_ld_T0_A0[ot](); opreg = OR_TMP0; } else { opreg = OR_EAX + rm; } - gen_op(s, op, ot, opreg, reg); - if (mod != 3 && op != 7) { - gen_op_st_T0_A0[ot](); - } + gen_op_mov_TN_reg[ot][1][reg](); + gen_op(s, op, ot, opreg); break; case 1: /* OP Gv, Ev */ modrm = ldub(s->pc++); @@ -1477,15 +1511,15 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) if (mod != 3) { gen_lea_modrm(s, modrm, ®_addr, &offset_addr); gen_op_ld_T1_A0[ot](); - opreg = OR_TMP1; } else { - opreg = OR_EAX + rm; + gen_op_mov_TN_reg[ot][1][rm](); } - gen_op(s, op, ot, reg, opreg); + gen_op(s, op, ot, reg); break; case 2: /* OP A, Iv */ val = insn_get(s, ot); - gen_opi(s, op, ot, OR_EAX, val); + gen_op_movl_T1_im(val); + gen_op(s, op, ot, OR_EAX); break; } } @@ -1509,7 +1543,6 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) if (mod != 3) { gen_lea_modrm(s, modrm, ®_addr, &offset_addr); - gen_op_ld_T0_A0[ot](); opreg = OR_TMP0; } else { opreg = rm + OR_EAX; @@ -1525,11 +1558,8 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) val = (int8_t)insn_get(s, OT_BYTE); break; } - - gen_opi(s, op, ot, opreg, val); - if (op != 7 && mod != 3) { - gen_op_st_T0_A0[ot](); - } + gen_op_movl_T1_im(val); + gen_op(s, op, ot, opreg); } break; @@ -1577,12 +1607,13 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) } break; case 3: /* neg */ - gen_op_negl_T0_cc(); + gen_op_negl_T0(); if (mod != 3) { gen_op_st_T0_A0[ot](); } else { gen_op_mov_reg_T0[ot][rm](); } + gen_op_update_neg_cc(); s->cc_op = CC_OP_SUBB + ot; break; case 4: /* mul */ @@ -1664,7 +1695,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) } if (mod != 3) { gen_lea_modrm(s, modrm, ®_addr, &offset_addr); - if (op != 3 && op != 5) + if (op >= 2 && op != 3 && op != 5) gen_op_ld_T0_A0[ot](); } else { gen_op_mov_TN_reg[ot][0][rm](); @@ -1672,18 +1703,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) switch(op) { case 0: /* inc Ev */ - gen_inc(s, ot, OR_TMP0, 1); if (mod != 3) - gen_op_st_T0_A0[ot](); + opreg = OR_TMP0; else - gen_op_mov_reg_T0[ot][rm](); + opreg = rm; + gen_inc(s, ot, opreg, 1); break; case 1: /* dec Ev */ - gen_inc(s, ot, OR_TMP0, -1); if (mod != 3) - gen_op_st_T0_A0[ot](); + opreg = OR_TMP0; else - gen_op_mov_reg_T0[ot][rm](); + opreg = rm; + gen_inc(s, ot, opreg, -1); break; case 2: /* call Ev */ /* XXX: optimize if memory (no and is necessary) */ @@ -1822,17 +1853,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) rm = modrm & 7; gen_op_mov_TN_reg[ot][0][reg](); gen_op_mov_TN_reg[ot][1][rm](); - gen_op_addl_T0_T1_cc(); + gen_op_addl_T0_T1(); gen_op_mov_reg_T0[ot][rm](); gen_op_mov_reg_T1[ot][reg](); } else { gen_lea_modrm(s, modrm, ®_addr, &offset_addr); gen_op_mov_TN_reg[ot][0][reg](); gen_op_ld_T1_A0[ot](); - gen_op_addl_T0_T1_cc(); + gen_op_addl_T0_T1(); gen_op_st_T0_A0[ot](); gen_op_mov_reg_T1[ot][reg](); } + gen_op_update2_cc(); s->cc_op = CC_OP_ADDB + ot; break; case 0x1b0: @@ -3607,8 +3639,7 @@ static uint16_t opc_read_flags[NB_OPS] = { [INDEX_op_sbbl_T0_T1_cc] = CC_C, /* subtle: due to the incl/decl implementation, C is used */ - [INDEX_op_incl_T0_cc] = CC_C, - [INDEX_op_decl_T0_cc] = CC_C, + [INDEX_op_update_inc_cc] = CC_C, [INDEX_op_into] = CC_O, @@ -3688,22 +3719,18 @@ static uint16_t opc_read_flags[NB_OPS] = { /* flags written by an operation */ static uint16_t opc_write_flags[NB_OPS] = { - [INDEX_op_addl_T0_T1_cc] = CC_OSZAPC, - [INDEX_op_orl_T0_T1_cc] = CC_OSZAPC, + [INDEX_op_update2_cc] = CC_OSZAPC, + [INDEX_op_update1_cc] = CC_OSZAPC, [INDEX_op_adcb_T0_T1_cc] = CC_OSZAPC, [INDEX_op_adcw_T0_T1_cc] = CC_OSZAPC, [INDEX_op_adcl_T0_T1_cc] = CC_OSZAPC, [INDEX_op_sbbb_T0_T1_cc] = CC_OSZAPC, [INDEX_op_sbbw_T0_T1_cc] = CC_OSZAPC, [INDEX_op_sbbl_T0_T1_cc] = CC_OSZAPC, - [INDEX_op_andl_T0_T1_cc] = CC_OSZAPC, - [INDEX_op_subl_T0_T1_cc] = CC_OSZAPC, - [INDEX_op_xorl_T0_T1_cc] = CC_OSZAPC, [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC, - [INDEX_op_negl_T0_cc] = CC_OSZAPC, + [INDEX_op_update_neg_cc] = CC_OSZAPC, /* subtle: due to the incl/decl implementation, C is used */ - [INDEX_op_incl_T0_cc] = CC_OSZAPC, - [INDEX_op_decl_T0_cc] = CC_OSZAPC, + [INDEX_op_update_inc_cc] = CC_OSZAPC, [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC, [INDEX_op_mulb_AL_T0] = CC_OSZAPC, @@ -3812,14 +3839,10 @@ static uint16_t opc_write_flags[NB_OPS] = { /* simpler form of an operation if no flags need to be generated */ static uint16_t opc_simpler[NB_OPS] = { - [INDEX_op_addl_T0_T1_cc] = INDEX_op_addl_T0_T1, - [INDEX_op_orl_T0_T1_cc] = INDEX_op_orl_T0_T1, - [INDEX_op_andl_T0_T1_cc] = INDEX_op_andl_T0_T1, - [INDEX_op_subl_T0_T1_cc] = INDEX_op_subl_T0_T1, - [INDEX_op_xorl_T0_T1_cc] = INDEX_op_xorl_T0_T1, - [INDEX_op_negl_T0_cc] = INDEX_op_negl_T0, - [INDEX_op_incl_T0_cc] = INDEX_op_incl_T0, - [INDEX_op_decl_T0_cc] = INDEX_op_decl_T0, + [INDEX_op_update2_cc] = INDEX_op_nop, + [INDEX_op_update1_cc] = INDEX_op_nop, + [INDEX_op_update_neg_cc] = INDEX_op_nop, + [INDEX_op_update_inc_cc] = INDEX_op_nop, [INDEX_op_rolb_T0_T1_cc] = INDEX_op_rolb_T0_T1, [INDEX_op_rolw_T0_T1_cc] = INDEX_op_rolw_T0_T1, |