diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2003-11-13 23:09:07 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2003-11-13 23:09:07 +0000 |
commit | 77729c244527432e5795ae1811c2d0226b6cff9b (patch) | |
tree | 9e2ff82846b9e3d84823985a91637789e62ca728 /target-i386 | |
parent | d71b9a8b2fa294c7689e43d97ee15dc56bb99853 (diff) |
fixed pop %sp bug
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@458 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-i386')
-rw-r--r-- | target-i386/translate.c | 20 |
1 files changed, 15 insertions, 5 deletions
diff --git a/target-i386/translate.c b/target-i386/translate.c index 8457b6c237..3ab09a3280 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -2304,8 +2304,9 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) case 0x58 ... 0x5f: /* pop */ ot = dflag ? OT_LONG : OT_WORD; gen_pop_T0(s); - gen_op_mov_reg_T0[ot][b & 7](); + /* NOTE: order is important for pop %sp */ gen_pop_update(s); + gen_op_mov_reg_T0[ot][b & 7](); break; case 0x60: /* pusha */ gen_pusha(s); @@ -2326,11 +2327,20 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) case 0x8f: /* pop Ev */ ot = dflag ? OT_LONG : OT_WORD; modrm = ldub_code(s->pc++); + mod = (modrm >> 6) & 3; gen_pop_T0(s); - s->popl_esp_hack = 2 << dflag; - gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); - s->popl_esp_hack = 0; - gen_pop_update(s); + if (mod == 3) { + /* NOTE: order is important for pop %sp */ + gen_pop_update(s); + rm = modrm & 7; + gen_op_mov_reg_T0[ot][rm](); + } else { + /* NOTE: order is important too for MMU exceptions */ + s->popl_esp_hack = 2 << dflag; + gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); + s->popl_esp_hack = 0; + gen_pop_update(s); + } break; case 0xc8: /* enter */ { |