Signed-off-by: Paolo Bonzini <[email protected]>
---
target/i386/tcg/decode-new.h | 6 ++++++
target/i386/tcg/translate.c | 1 -
target/i386/tcg/decode-new.c.inc | 8 +++-----
3 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/target/i386/tcg/decode-new.h b/target/i386/tcg/decode-new.h
index 5f76b0c1b7a..a823143bbdf 100644
--- a/target/i386/tcg/decode-new.h
+++ b/target/i386/tcg/decode-new.h
@@ -242,6 +242,12 @@ typedef enum X86InsnSpecial {
/* Memory operand size of MOV from segment register is MO_16 */
X86_SPECIAL_Op0_Mw,
+
+ /*
+ * If the address uses ESP as the base register, use the value
+ * of ESP after the pop.
+ */
+ X86_SPECIAL_PopESP,
} X86InsnSpecial;
/*
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 5199c330ac7..b2cbce046cb 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -108,7 +108,6 @@ typedef struct DisasContext {
uint8_t vex_v; /* vex vvvv register, without 1's complement. */
bool vex_ndd; /* is this a 3-operand instruction? */
bool vex_w; /* used by AVX even on 32-bit processors */
- uint8_t popl_esp_hack; /* for correct popl with esp base handling */
uint8_t rip_offset; /* only used in x86_64, but left for simplicity */
uint8_t rex_r; /* 0 for i386, but left for simplicity */
diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
index 3845fab5c85..2756953c744 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -1615,8 +1615,7 @@ static void decode_group1A(DisasContext *s, CPUX86State
*env, X86OpEntry *entry,
*entry = UNKNOWN_OPCODE;
} else {
entry->gen = gen_POP;
- /* The address must use the value of ESP after the pop. */
- s->popl_esp_hack = 1 << mo_pushpop(s, s->dflag);
+ entry->special = X86_SPECIAL_PopESP;
}
}
@@ -2360,8 +2359,8 @@ static void decode_modrm(DisasContext *s, CPUX86State
*env,
}
/* For correct popl handling with esp. */
- if (base == R_ESP && s->popl_esp_hack) {
- disp += s->popl_esp_hack;
+ if (base == R_ESP && decode->e.special == X86_SPECIAL_PopESP) {
+ disp += 1 << mo_pushpop(s, s->dflag);
}
if (base == R_EBP || base == R_ESP) {
def_seg = R_SS;
@@ -3287,7 +3286,6 @@ static void disas_insn(DisasContext *s, CPUState *cpu)
s->pc = s->base.pc_next;
s->override = -1;
- s->popl_esp_hack = 0;
#ifdef TARGET_X86_64
s->rex_r = 0;
s->rex_x = 0;
--
2.56.0