The imm16 operand of RET and RETF specifies an unsigned 16-bit count
of additional bytes to release from the stack.
Previously, gen_RET() and gen_RETF() stored this operand in an int16_t.
For example, 0xcaf5 was interpreted as -13579 instead of 51957.
Use uint16_t for the adjustment in both functions to preserve the
immediate's unsigned value.
Tested locally with near and far returns in both 32-bit and 64-bit
modes. Each combination covered the form without an immediate and
immediate values 0x0000, 0x0001, 0x7fff, 0x8000, 0xcaf5, and 0xffff.
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2599
Signed-off-by: Artemii Mashanov <ralerrdirsardx@gmail.com>
---
target/i386/tcg/emit.c.inc | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc
index 473f415766..0c35403ebc 100644
--- a/target/i386/tcg/emit.c.inc
+++ b/target/i386/tcg/emit.c.inc
@@ -3598,7 +3598,7 @@ static void gen_RDxxBASE(DisasContext *s, X86DecodedInsn *decode)
static void gen_RET(DisasContext *s, X86DecodedInsn *decode)
{
- int16_t adjust = decode->e.op1 == X86_TYPE_I ? decode->immediate : 0;
+ uint16_t adjust = decode->e.op1 == X86_TYPE_I ? decode->immediate : 0;
MemOp ot = gen_pop_T0(s);
gen_stack_update(s, adjust + (1 << ot));
@@ -3609,7 +3609,7 @@ static void gen_RET(DisasContext *s, X86DecodedInsn *decode)
static void gen_RETF(DisasContext *s, X86DecodedInsn *decode)
{
- int16_t adjust = decode->e.op1 == X86_TYPE_I ? decode->immediate : 0;
+ uint16_t adjust = decode->e.op1 == X86_TYPE_I ? decode->immediate : 0;
if (!PE(s) || VM86(s)) {
gen_lea_ss_ofs(s, s->A0, cpu_regs[R_ESP], 0);
--
2.55.0