aboutsummaryrefslogtreecommitdiff
path: root/target-i386
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2003-11-13 23:09:07 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2003-11-13 23:09:07 +0000
commit77729c244527432e5795ae1811c2d0226b6cff9b (patch)
tree9e2ff82846b9e3d84823985a91637789e62ca728 /target-i386
parentd71b9a8b2fa294c7689e43d97ee15dc56bb99853 (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.c20
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 */
{