diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2003-03-26 22:33:47 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2003-03-26 22:33:47 +0000 |
commit | 31bb950be6d1f144d349d9793c88fbb28ca5fb58 (patch) | |
tree | 99e1f0921ab93e0169c1cd066d64c47ec831d47c /translate-i386.c | |
parent | 8083a3e50895abb6070d9f339363d05d2c5e0017 (diff) |
xchg lock, xlat instr
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@49 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'translate-i386.c')
-rw-r--r-- | translate-i386.c | 40 |
1 files changed, 39 insertions, 1 deletions
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; |