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:
parent
261d0d16af
commit
bb18f27715
|
@ -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();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user