x86emu: Fix more mis-decoding of the data prefix

cc2c73ddcb4370a7c3ad439cda4da825156c26c9's three-cent titanium tax
doesn't go too far enough.  Fix the rest of the call and jmp
instructions to handle the data prefix correctly.

Reference: Intel 64 and IA-32 Architectures Software Developer's Manual
Volume 2A: Instruction Set Reference, A-M

http://www.intel.com/Assets/PDF/manual/253666.pdf

Reviewed-by: Julien Cristau <jcristau@debian.org>
Signed-off-by: Adam Jackson <ajax@redhat.com>
This commit is contained in:
Adam Jackson 2010-12-10 14:24:02 -05:00
parent 261d0d16af
commit bb18f27715

View File

@ -7065,15 +7065,20 @@ Handles opcode 0x9a
****************************************************************************/ ****************************************************************************/
static void x86emuOp_call_far_IMM(u8 X86EMU_UNUSED(op1)) static void x86emuOp_call_far_IMM(u8 X86EMU_UNUSED(op1))
{ {
u16 farseg, faroff; u32 farseg, faroff;
START_OF_INSTR(); START_OF_INSTR();
DECODE_PRINTF("CALL\t"); DECODE_PRINTF("CALL\t");
if (M.x86.mode & SYSMODE_PREFIX_DATA) {
faroff = fetch_long_imm();
farseg = fetch_word_imm();
} else {
faroff = fetch_word_imm(); faroff = fetch_word_imm();
farseg = fetch_word_imm(); farseg = fetch_word_imm();
DECODE_PRINTF2("%04x:", farseg); }
DECODE_PRINTF2("%04x\n", faroff); DECODE_PRINTF2("%04x:", farseg);
CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, farseg, faroff, "FAR "); DECODE_PRINTF2("%04x\n", faroff);
CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, farseg, faroff, "FAR ");
/* XXX /* XXX
* *
@ -7084,8 +7089,12 @@ static void x86emuOp_call_far_IMM(u8 X86EMU_UNUSED(op1))
TRACE_AND_STEP(); TRACE_AND_STEP();
push_word(M.x86.R_CS); push_word(M.x86.R_CS);
M.x86.R_CS = farseg; M.x86.R_CS = farseg;
push_word(M.x86.R_IP); if (M.x86.mode & SYSMODE_PREFIX_DATA) {
M.x86.R_IP = faroff; push_long(M.x86.R_EIP);
} else {
push_word(M.x86.R_IP);
}
M.x86.R_EIP = faroff & 0xffff;
DECODE_CLEAR_SEGOVR(); DECODE_CLEAR_SEGOVR();
END_OF_INSTR(); END_OF_INSTR();
} }
@ -9670,17 +9679,30 @@ Handles opcode 0xe8
****************************************************************************/ ****************************************************************************/
static void x86emuOp_call_near_IMM(u8 X86EMU_UNUSED(op1)) static void x86emuOp_call_near_IMM(u8 X86EMU_UNUSED(op1))
{ {
s16 ip; s16 ip16;
s32 ip32;
START_OF_INSTR(); START_OF_INSTR();
DECODE_PRINTF("CALL\t"); DECODE_PRINTF("CALL\t");
ip = (s16) fetch_word_imm(); if (M.x86.mode & SYSMODE_PREFIX_DATA) {
ip += (s16) M.x86.R_IP; /* CHECK SIGN */ ip32 = (s32) fetch_long_imm();
DECODE_PRINTF2("%04x\n", (u16)ip); ip32 += (s16) M.x86.R_IP; /* CHECK SIGN */
CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip, ""); DECODE_PRINTF2("%04x\n", (u16)ip32);
CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip32, "");
} else {
ip16 = (s16) fetch_word_imm();
ip16 += (s16) M.x86.R_IP; /* CHECK SIGN */
DECODE_PRINTF2("%04x\n", (u16)ip16);
CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip16, "");
}
TRACE_AND_STEP(); TRACE_AND_STEP();
push_word(M.x86.R_IP); if (M.x86.mode & SYSMODE_PREFIX_DATA) {
M.x86.R_IP = ip; push_long(M.x86.R_EIP);
M.x86.R_EIP = ip32 & 0xffff;
} else {
push_word(M.x86.R_IP);
M.x86.R_EIP = ip16;
}
DECODE_CLEAR_SEGOVR(); DECODE_CLEAR_SEGOVR();
END_OF_INSTR(); END_OF_INSTR();
} }
@ -9718,16 +9740,21 @@ Handles opcode 0xea
****************************************************************************/ ****************************************************************************/
static void x86emuOp_jump_far_IMM(u8 X86EMU_UNUSED(op1)) static void x86emuOp_jump_far_IMM(u8 X86EMU_UNUSED(op1))
{ {
u16 cs, ip; u16 cs;
u32 ip;
START_OF_INSTR(); START_OF_INSTR();
DECODE_PRINTF("JMP\tFAR "); DECODE_PRINTF("JMP\tFAR ");
ip = fetch_word_imm(); if (M.x86.mode & SYSMODE_PREFIX_DATA) {
ip = fetch_long_imm();
} else {
ip = fetch_word_imm();
}
cs = fetch_word_imm(); cs = fetch_word_imm();
DECODE_PRINTF2("%04x:", cs); DECODE_PRINTF2("%04x:", cs);
DECODE_PRINTF2("%04x\n", ip); DECODE_PRINTF2("%04x\n", ip);
TRACE_AND_STEP(); TRACE_AND_STEP();
M.x86.R_IP = ip; M.x86.R_EIP = ip & 0xffff;
M.x86.R_CS = cs; M.x86.R_CS = cs;
DECODE_CLEAR_SEGOVR(); DECODE_CLEAR_SEGOVR();
END_OF_INSTR(); END_OF_INSTR();