[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [XEN] Fix/implement JMP/CALL/RET emulation.
# HG changeset patch # User kfraser@xxxxxxxxxxxxxxxxxxxxx # Date 1168537633 0 # Node ID f455a26a4170b84e3bcbda1c8701c89cb66380ac # Parent 66eba8d1b83a9d22b5b88d0f11fe8aa79895f1cb [XEN] Fix/implement JMP/CALL/RET emulation. Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx> --- xen/arch/x86/x86_emulate.c | 96 ++++++++++++++++++++++++++++++++++++--------- 1 files changed, 77 insertions(+), 19 deletions(-) diff -r 66eba8d1b83a -r f455a26a4170 xen/arch/x86/x86_emulate.c --- a/xen/arch/x86/x86_emulate.c Thu Jan 11 17:03:11 2007 +0000 +++ b/xen/arch/x86/x86_emulate.c Thu Jan 11 17:47:13 2007 +0000 @@ -85,9 +85,11 @@ static uint8_t opcode_table[256] = { ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov, - /* 0x60 - 0x6F */ + /* 0x60 - 0x67 */ 0, 0, 0, DstReg|SrcMem32|ModRM|Mov /* movsxd (x86/64) */, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, + /* 0x68 - 0x6F */ + ImplicitOps|Mov, 0, ImplicitOps|Mov, 0, 0, 0, 0, 0, /* 0x70 - 0x77 */ ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, @@ -125,7 +127,8 @@ static uint8_t opcode_table[256] = { DstReg|SrcImm|Mov, DstReg|SrcImm|Mov, DstReg|SrcImm|Mov, DstReg|SrcImm|Mov, DstReg|SrcImm|Mov, DstReg|SrcImm|Mov, DstReg|SrcImm|Mov, DstReg|SrcImm|Mov, /* 0xC0 - 0xC7 */ - ByteOp|DstMem|SrcImm|ModRM, DstMem|SrcImmByte|ModRM, 0, 0, + ByteOp|DstMem|SrcImm|ModRM, DstMem|SrcImmByte|ModRM, + ImplicitOps, ImplicitOps, 0, 0, ByteOp|DstMem|SrcImm|ModRM|Mov, DstMem|SrcImm|ModRM|Mov, /* 0xC8 - 0xCF */ 0, 0, 0, 0, 0, 0, 0, 0, @@ -138,7 +141,7 @@ static uint8_t opcode_table[256] = { /* 0xE0 - 0xE7 */ 0, 0, 0, ImplicitOps, 0, 0, 0, 0, /* 0xE8 - 0xEF */ - 0, ImplicitOps, 0, ImplicitOps, 0, 0, 0, 0, + ImplicitOps, ImplicitOps, 0, ImplicitOps, 0, 0, 0, 0, /* 0xF0 - 0xF7 */ 0, 0, 0, 0, 0, ImplicitOps, ByteOp|DstMem|SrcNone|ModRM, DstMem|SrcNone|ModRM, @@ -1110,6 +1113,20 @@ x86_emulate( case 1: /* dec */ emulate_1op("dec", dst, _regs.eflags); break; + case 2: /* call (near) */ + case 3: /* jmp (near) */ + if ( ((op_bytes = dst.bytes) != 8) && mode_64bit() ) + { + dst.bytes = op_bytes = 8; + if ( (rc = ops->read(dst.mem.seg, dst.mem.off, + &dst.val, 8, ctxt)) != 0 ) + goto done; + } + src.val = _regs.eip; + _regs.eip = dst.val; + if ( (modrm_reg & 7) == 2 ) + goto push; /* call */ + break; case 6: /* push */ /* 64-bit mode: PUSH defaults to a 64-bit operand. */ if ( mode_64bit() && (dst.bytes == 4) ) @@ -1264,16 +1281,9 @@ x86_emulate( break; case 0x50 ... 0x57: /* push reg */ - dst.type = OP_MEM; - dst.bytes = op_bytes; - if ( mode_64bit() && (dst.bytes == 4) ) - dst.bytes = 8; - dst.val = *(unsigned long *)decode_register( + src.val = *(unsigned long *)decode_register( (b & 7) | ((rex_prefix & 1) << 3), &_regs, 0); - register_address_increment(_regs.esp, -dst.bytes); - dst.mem.seg = x86_seg_ss; - dst.mem.off = truncate_ea(_regs.esp); - break; + goto push; case 0x58 ... 0x5f: /* pop reg */ dst.type = OP_REG; @@ -1286,6 +1296,26 @@ x86_emulate( &dst.val, dst.bytes, ctxt)) != 0 ) goto done; register_address_increment(_regs.esp, dst.bytes); + break; + + case 0x68: /* push imm{16,32,64} */ + src.val = ((op_bytes == 2) + ? (int32_t)insn_fetch_type(int16_t) + : insn_fetch_type(int32_t)); + goto push; + + case 0x6a: /* push imm8 */ + src.val = insn_fetch_type(int8_t); + push: + d |= Mov; /* force writeback */ + dst.type = OP_MEM; + dst.bytes = op_bytes; + if ( mode_64bit() && (dst.bytes == 4) ) + dst.bytes = 8; + dst.val = src.val; + register_address_increment(_regs.esp, -dst.bytes); + dst.mem.seg = x86_seg_ss; + dst.mem.off = truncate_ea(_regs.esp); break; case 0x70 ... 0x7f: /* jcc (short) */ { @@ -1371,6 +1401,18 @@ x86_emulate( _regs.esi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes); break; + case 0xc2: /* ret imm16 (near) */ + case 0xc3: /* ret (near) */ { + int offset = (b == 0xc2) ? insn_fetch_type(uint16_t) : 0; + op_bytes = mode_64bit() ? 8 : op_bytes; + if ( (rc = ops->read(x86_seg_ss, truncate_ea(_regs.esp), + &dst.val, op_bytes, ctxt)) != 0 ) + goto done; + _regs.eip = dst.val; + register_address_increment(_regs.esp, op_bytes + offset); + break; + } + case 0xd4: /* aam */ { unsigned int base = insn_fetch_type(uint8_t); uint8_t al = _regs.eax; @@ -1418,12 +1460,26 @@ x86_emulate( break; } - case 0xe9: /* jmp (short) */ + case 0xe8: /* call (near) */ { + int rel = (((op_bytes == 2) && !mode_64bit()) + ? (int32_t)insn_fetch_type(int16_t) + : insn_fetch_type(int32_t)); + op_bytes = mode_64bit() ? 8 : op_bytes; + src.val = _regs.eip; + jmp_rel(rel); + goto push; + } + + case 0xe9: /* jmp (near) */ { + int rel = (((op_bytes == 2) && !mode_64bit()) + ? (int32_t)insn_fetch_type(int16_t) + : insn_fetch_type(int32_t)); + jmp_rel(rel); + break; + } + + case 0xeb: /* jmp (short) */ jmp_rel(insn_fetch_type(int8_t)); - break; - - case 0xeb: /* jmp (near) */ - jmp_rel(insn_fetch_bytes(mode_64bit() ? 4 : op_bytes)); break; case 0xf5: /* cmc */ @@ -1550,7 +1606,9 @@ x86_emulate( break; case 0x80 ... 0x8f: /* jcc (near) */ { - int rel = insn_fetch_bytes(mode_64bit() ? 4 : op_bytes); + int rel = (((op_bytes == 2) && !mode_64bit()) + ? (int32_t)insn_fetch_type(int16_t) + : insn_fetch_type(int32_t)); if ( test_cc(b, _regs.eflags) ) jmp_rel(rel); break; _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |