summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuc Verhaegen <libv@skynet.be>2010-10-24 23:57:06 +0200
committerJulien Cristau <jcristau@debian.org>2011-01-09 11:54:21 +0100
commit2194c381c8a0b4e1a163f9b0f6abe92093f531fa (patch)
tree5aa32930c27f5f26e98366179514bd08acb6a12a
parentc038d008e4004914dc5ad58ba73d51baf0cd91ac (diff)
x86emu: fix jump_near_IMM to handle DATA: flag correctly.
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=24348 Before (data flag ignored -> broken): 66 DATA: e944f1 JMP 1ff6 After (fixed): 66 DATA: e944f1ffff JMP 00001ff8 This subtle difference in the length of decoded instruction meant that the VBE call jumped to the routine setting AX=0x14F (VBE Failed) instead of the routine that set AX=0x4F (VBE success). The ability to run the same code in vm86 significantly aided the debugging of this issue. Those X.org developers who would like to drop vm86 better take special care towards _all_ vesa bugs, as those will expose further issues. Patch applies easily to even xserver 1.4.2. Signed-off-by: Luc Verhaegen <libv@skynet.be> Tested-by: Luc Verhaegen <libv@skynet.be> Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Keith Packard <keithp@keithp.com> (cherry picked from commit cc2c73ddcb4370a7c3ad439cda4da825156c26c9)
-rw-r--r--hw/xfree86/x86emu/ops.c20
1 files changed, 14 insertions, 6 deletions
diff --git a/hw/xfree86/x86emu/ops.c b/hw/xfree86/x86emu/ops.c
index 21a034712..c6b2f0a4b 100644
--- a/hw/xfree86/x86emu/ops.c
+++ b/hw/xfree86/x86emu/ops.c
@@ -9691,15 +9691,23 @@ Handles opcode 0xe9
****************************************************************************/
static void x86emuOp_jump_near_IMM(u8 X86EMU_UNUSED(op1))
{
- int ip;
+ u32 ip;
START_OF_INSTR();
DECODE_PRINTF("JMP\t");
- ip = (s16)fetch_word_imm();
- ip += (s16)M.x86.R_IP;
- DECODE_PRINTF2("%04x\n", (u16)ip);
- TRACE_AND_STEP();
- M.x86.R_IP = (u16)ip;
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ ip = (u32)fetch_long_imm();
+ ip += (u32)M.x86.R_EIP;
+ DECODE_PRINTF2("%08x\n", (u32)ip);
+ TRACE_AND_STEP();
+ M.x86.R_EIP = (u32)ip;
+ } else {
+ ip = (s16)fetch_word_imm();
+ ip += (s16)M.x86.R_IP;
+ DECODE_PRINTF2("%04x\n", (u16)ip);
+ TRACE_AND_STEP();
+ M.x86.R_IP = (u16)ip;
+ }
DECODE_CLEAR_SEGOVR();
END_OF_INSTR();
}