{
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;
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;
}
{
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;
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;
}
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);
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);
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);
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);
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);
}
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);
}
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);
}
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);
}
{
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;
}
{
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;
};
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] = {
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)
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++);
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;
}
}
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;
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;
}
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 */
}
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]();
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) */
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:
[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,
/* 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,
/* 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,