|
@@ -212,7 +212,8 @@ static u16 twobyte_table[256] = {
|
|
|
0, 0, ByteOp | DstReg | SrcMem | ModRM | Mov,
|
|
|
DstReg | SrcMem16 | ModRM | Mov,
|
|
|
/* 0xC0 - 0xCF */
|
|
|
- 0, 0, 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
+ 0, 0, 0, DstMem | SrcReg | ModRM | Mov, 0, 0, 0, ImplicitOps | ModRM,
|
|
|
+ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
/* 0xD0 - 0xDF */
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
/* 0xE0 - 0xEF */
|
|
@@ -596,11 +597,10 @@ x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
|
|
|
case 0xf0: /* LOCK */
|
|
|
lock_prefix = 1;
|
|
|
break;
|
|
|
+ case 0xf2: /* REPNE/REPNZ */
|
|
|
case 0xf3: /* REP/REPE/REPZ */
|
|
|
rep_prefix = 1;
|
|
|
break;
|
|
|
- case 0xf2: /* REPNE/REPNZ */
|
|
|
- break;
|
|
|
default:
|
|
|
goto done_prefixes;
|
|
|
}
|
|
@@ -825,6 +825,14 @@ done_prefixes:
|
|
|
if (twobyte && b == 0x01 && modrm_reg == 7)
|
|
|
break;
|
|
|
srcmem_common:
|
|
|
+ /*
|
|
|
+ * For instructions with a ModR/M byte, switch to register
|
|
|
+ * access if Mod = 3.
|
|
|
+ */
|
|
|
+ if ((d & ModRM) && modrm_mod == 3) {
|
|
|
+ src.type = OP_REG;
|
|
|
+ break;
|
|
|
+ }
|
|
|
src.type = OP_MEM;
|
|
|
src.ptr = (unsigned long *)cr2;
|
|
|
src.val = 0;
|
|
@@ -893,6 +901,14 @@ done_prefixes:
|
|
|
dst.ptr = (unsigned long *)cr2;
|
|
|
dst.bytes = (d & ByteOp) ? 1 : op_bytes;
|
|
|
dst.val = 0;
|
|
|
+ /*
|
|
|
+ * For instructions with a ModR/M byte, switch to register
|
|
|
+ * access if Mod = 3.
|
|
|
+ */
|
|
|
+ if ((d & ModRM) && modrm_mod == 3) {
|
|
|
+ dst.type = OP_REG;
|
|
|
+ break;
|
|
|
+ }
|
|
|
if (d & BitOp) {
|
|
|
unsigned long mask = ~(dst.bytes * 8 - 1);
|
|
|
|
|
@@ -1083,31 +1099,6 @@ push:
|
|
|
case 0xd2 ... 0xd3: /* Grp2 */
|
|
|
src.val = _regs[VCPU_REGS_RCX];
|
|
|
goto grp2;
|
|
|
- case 0xe8: /* call (near) */ {
|
|
|
- long int rel;
|
|
|
- switch (op_bytes) {
|
|
|
- case 2:
|
|
|
- rel = insn_fetch(s16, 2, _eip);
|
|
|
- break;
|
|
|
- case 4:
|
|
|
- rel = insn_fetch(s32, 4, _eip);
|
|
|
- break;
|
|
|
- case 8:
|
|
|
- rel = insn_fetch(s64, 8, _eip);
|
|
|
- break;
|
|
|
- default:
|
|
|
- DPRINTF("Call: Invalid op_bytes\n");
|
|
|
- goto cannot_emulate;
|
|
|
- }
|
|
|
- src.val = (unsigned long) _eip;
|
|
|
- JMP_REL(rel);
|
|
|
- goto push;
|
|
|
- }
|
|
|
- case 0xe9: /* jmp rel */
|
|
|
- case 0xeb: /* jmp rel short */
|
|
|
- JMP_REL(src.val);
|
|
|
- no_wb = 1; /* Disable writeback. */
|
|
|
- break;
|
|
|
case 0xf6 ... 0xf7: /* Grp3 */
|
|
|
switch (modrm_reg) {
|
|
|
case 0 ... 1: /* test */
|
|
@@ -1350,6 +1341,32 @@ special_insn:
|
|
|
case 0xae ... 0xaf: /* scas */
|
|
|
DPRINTF("Urk! I don't handle SCAS.\n");
|
|
|
goto cannot_emulate;
|
|
|
+ case 0xe8: /* call (near) */ {
|
|
|
+ long int rel;
|
|
|
+ switch (op_bytes) {
|
|
|
+ case 2:
|
|
|
+ rel = insn_fetch(s16, 2, _eip);
|
|
|
+ break;
|
|
|
+ case 4:
|
|
|
+ rel = insn_fetch(s32, 4, _eip);
|
|
|
+ break;
|
|
|
+ case 8:
|
|
|
+ rel = insn_fetch(s64, 8, _eip);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ DPRINTF("Call: Invalid op_bytes\n");
|
|
|
+ goto cannot_emulate;
|
|
|
+ }
|
|
|
+ src.val = (unsigned long) _eip;
|
|
|
+ JMP_REL(rel);
|
|
|
+ goto push;
|
|
|
+ }
|
|
|
+ case 0xe9: /* jmp rel */
|
|
|
+ case 0xeb: /* jmp rel short */
|
|
|
+ JMP_REL(src.val);
|
|
|
+ no_wb = 1; /* Disable writeback. */
|
|
|
+ break;
|
|
|
+
|
|
|
|
|
|
}
|
|
|
goto writeback;
|
|
@@ -1501,6 +1518,10 @@ twobyte_insn:
|
|
|
dst.bytes = op_bytes;
|
|
|
dst.val = (d & ByteOp) ? (s8) src.val : (s16) src.val;
|
|
|
break;
|
|
|
+ case 0xc3: /* movnti */
|
|
|
+ dst.bytes = op_bytes;
|
|
|
+ dst.val = (op_bytes == 4) ? (u32) src.val : (u64) src.val;
|
|
|
+ break;
|
|
|
}
|
|
|
goto writeback;
|
|
|
|