diff options
-rw-r--r-- | op-i386.c | 5 | ||||
-rw-r--r-- | opc-i386.h | 1 | ||||
-rw-r--r-- | translate-i386.c | 40 |
3 files changed, 45 insertions, 1 deletions
@@ -489,6 +489,11 @@ void OPPROTO op_addl_A0_im(void) A0 += PARAM1; } +void OPPROTO op_addl_A0_AL(void) +{ + A0 += (EAX & 0xff); +} + void OPPROTO op_andl_A0_ffff(void) { A0 = A0 & 0xffff; diff --git a/opc-i386.h b/opc-i386.h index 9d9f8471b5..eceecf41b8 100644 --- a/opc-i386.h +++ b/opc-i386.h @@ -210,6 +210,7 @@ DEF(addl_T1_im) DEF(movl_T1_A0) DEF(movl_A0_im) DEF(addl_A0_im) +DEF(addl_A0_AL) DEF(andl_A0_ffff) DEF(ldub_T0_A0) DEF(ldsb_T0_A0) diff --git a/translate-i386.c b/translate-i386.c index afe7f3543a..d7f6520e8f 100644 --- a/translate-i386.c +++ b/translate-i386.c @@ -2083,7 +2083,40 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) gen_op_st_T0_A0[ot](); } break; - + case 0xd7: /* xlat */ + /* handle override */ + gen_op_movl_A0_reg[R_EBX](); + gen_op_addl_A0_AL(); + if (s->aflag == 0) + gen_op_andl_A0_ffff(); + /* XXX: factorize that */ + { + int override, must_add_seg; + override = R_DS; + must_add_seg = s->addseg; + if (s->prefix & (PREFIX_CS | PREFIX_SS | PREFIX_DS | + PREFIX_ES | PREFIX_FS | PREFIX_GS)) { + if (s->prefix & PREFIX_ES) + override = R_ES; + else if (s->prefix & PREFIX_CS) + override = R_CS; + else if (s->prefix & PREFIX_SS) + override = R_SS; + else if (s->prefix & PREFIX_DS) + override = R_DS; + else if (s->prefix & PREFIX_FS) + override = R_FS; + else + override = R_GS; + must_add_seg = 1; + } + if (must_add_seg) { + gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base)); + } + } + gen_op_ldub_T0_A0(); + gen_op_mov_reg_T0[OT_BYTE][R_EAX](); + break; case 0xb0 ... 0xb7: /* mov R, Ib */ val = insn_get(s, OT_BYTE); gen_op_movl_T0_im(val); @@ -2121,8 +2154,13 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) } else { gen_lea_modrm(s, modrm, ®_addr, &offset_addr); gen_op_mov_TN_reg[ot][0][reg](); + /* for xchg, lock is implicit */ + if (!(prefixes & PREFIX_LOCK)) + gen_op_lock(); gen_op_ld_T1_A0[ot](); gen_op_st_T0_A0[ot](); + if (!(prefixes & PREFIX_LOCK)) + gen_op_unlock(); gen_op_mov_reg_T1[ot][reg](); } break; |