# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1168344281 0
# Node ID 9518bff7c76229793086a5bff7c9336e3eabb005
# Parent 717f64715f3256b55f8af59c4e178285ae26a0b5
[XEN] Fill in some more opcode space in the emulator.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
xen/arch/x86/x86_emulate.c | 122 ++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 114 insertions(+), 8 deletions(-)
diff -r 717f64715f32 -r 9518bff7c762 xen/arch/x86/x86_emulate.c
--- a/xen/arch/x86/x86_emulate.c Tue Jan 09 11:52:15 2007 +0000
+++ b/xen/arch/x86/x86_emulate.c Tue Jan 09 12:04:41 2007 +0000
@@ -62,19 +62,19 @@ static uint8_t opcode_table[256] = {
/* 0x20 - 0x27 */
ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM,
ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM,
- ByteOp|DstReg|SrcImm, DstReg|SrcImm, 0, 0,
+ ByteOp|DstReg|SrcImm, DstReg|SrcImm, 0, ImplicitOps,
/* 0x28 - 0x2F */
ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM,
ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM,
- ByteOp|DstReg|SrcImm, DstReg|SrcImm, 0, 0,
+ ByteOp|DstReg|SrcImm, DstReg|SrcImm, 0, ImplicitOps,
/* 0x30 - 0x37 */
ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM,
ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM,
- ByteOp|DstReg|SrcImm, DstReg|SrcImm, 0, 0,
+ ByteOp|DstReg|SrcImm, DstReg|SrcImm, 0, ImplicitOps,
/* 0x38 - 0x3F */
ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM,
ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM,
- ByteOp|DstReg|SrcImm, DstReg|SrcImm, 0, 0,
+ ByteOp|DstReg|SrcImm, DstReg|SrcImm, 0, ImplicitOps,
/* 0x40 - 0x4F */
ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
@@ -113,7 +113,8 @@ static uint8_t opcode_table[256] = {
ByteOp|ImplicitOps|Mov, ImplicitOps|Mov,
ByteOp|ImplicitOps|Mov, ImplicitOps|Mov, 0, 0,
/* 0xA8 - 0xAF */
- 0, 0, ByteOp|ImplicitOps|Mov, ImplicitOps|Mov,
+ ByteOp|DstReg|SrcImm, DstReg|SrcImm,
+ ByteOp|ImplicitOps|Mov, ImplicitOps|Mov,
ByteOp|ImplicitOps|Mov, ImplicitOps|Mov, 0, 0,
/* 0xB0 - 0xB7 */
ByteOp|DstReg|SrcImm|Mov, ByteOp|DstReg|SrcImm|Mov,
@@ -131,7 +132,7 @@ static uint8_t opcode_table[256] = {
/* 0xD0 - 0xD7 */
ByteOp|DstMem|SrcImplicit|ModRM, DstMem|SrcImplicit|ModRM,
ByteOp|DstMem|SrcImplicit|ModRM, DstMem|SrcImplicit|ModRM,
- 0, 0, 0, 0,
+ ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
/* 0xD8 - 0xDF */
0, 0, 0, 0, 0, 0, 0, 0,
/* 0xE0 - 0xE7 */
@@ -227,6 +228,9 @@ struct operand {
#define EFLG_AF (1<<4)
#define EFLG_PF (1<<2)
#define EFLG_CF (1<<0)
+
+/* Exception definitions. */
+#define EXC_DE 0
/*
* Instruction emulation:
@@ -408,6 +412,23 @@ do{ __asm__ __volatile__ (
#define mode_64bit() (def_ad_bytes == 8)
+#define fail_if(p) \
+do { \
+ rc = (p) ? X86EMUL_UNHANDLEABLE : 0; \
+ if ( rc ) goto done; \
+} while (0)
+
+/* In future we will be able to generate arbitrary exceptions. */
+#define generate_exception_if(p, e) fail_if(p)
+
+/* Given byte has even parity (even number of 1s)? */
+static int even_parity(uint8_t v)
+{
+ __asm__ ( "test %%al,%%al; setp %%al"
+ : "=a" (v) : "0" (v) );
+ return v;
+}
+
/* Update address held in a register, based on addressing mode. */
#define _register_address_increment(reg, inc, byte_width) \
do { \
@@ -942,6 +963,9 @@ x86_emulate(
}
break;
+ case 0xa8 ... 0xa9: /* test imm,%%eax */
+ dst.reg = (unsigned long *)&_regs.eax;
+ dst.val = dst.orig_val = _regs.eax;
case 0x84 ... 0x85: test: /* test */
emulate_2op_SrcV("test", src, dst, _regs.eflags);
break;
@@ -960,8 +984,9 @@ x86_emulate(
lock_prefix = 1;
break;
+ case 0xc6 ... 0xc7: /* mov (sole member of Grp11) */
+ fail_if((modrm_reg & 7) != 0);
case 0x88 ... 0x8b: /* mov */
- case 0xc6 ... 0xc7: /* mov (sole member of Grp11) */
dst.val = src.val;
break;
@@ -970,6 +995,7 @@ x86_emulate(
break;
case 0x8f: /* pop (sole member of Grp1a) */
+ fail_if((modrm_reg & 7) != 0);
/* 64-bit mode: POP defaults to a 64-bit operand. */
if ( mode_64bit() && (dst.bytes == 4) )
dst.bytes = 8;
@@ -1056,7 +1082,9 @@ x86_emulate(
}
break;
- case 0xfe ... 0xff: /* Grp4/Grp5 */
+ case 0xfe: /* Grp4 */
+ fail_if((modrm_reg & 7) >= 2);
+ case 0xff: /* Grp5 */
switch ( modrm_reg & 7 )
{
case 0: /* inc */
@@ -1080,6 +1108,8 @@ x86_emulate(
goto done;
dst.val = dst.orig_val; /* skanky: disable writeback */
break;
+ case 7:
+ fail_if(1);
default:
goto cannot_emulate;
}
@@ -1142,6 +1172,43 @@ x86_emulate(
switch ( b )
{
+ case 0x27: /* daa */ {
+ uint8_t al = _regs.eax;
+ unsigned long tmp;
+ fail_if(mode_64bit());
+ __asm__ __volatile__ (
+ _PRE_EFLAGS("0","4","2") "daa; " _POST_EFLAGS("0","4","2")
+ : "=m" (_regs.eflags), "=a" (al), "=&r" (tmp)
+ : "a" (al), "i" (EFLAGS_MASK) );
+ *(uint8_t *)_regs.eax = al;
+ break;
+ }
+
+ case 0x2f: /* das */ {
+ uint8_t al = _regs.eax;
+ unsigned long tmp;
+ fail_if(mode_64bit());
+ __asm__ __volatile__ (
+ _PRE_EFLAGS("0","4","2") "das; " _POST_EFLAGS("0","4","2")
+ : "=m" (_regs.eflags), "=a" (al), "=&r" (tmp)
+ : "a" (al), "i" (EFLAGS_MASK) );
+ *(uint8_t *)_regs.eax = al;
+ break;
+ }
+
+ case 0x37: /* aaa */
+ case 0x3f: /* aas */
+ fail_if(mode_64bit());
+ _regs.eflags &= ~EFLG_CF;
+ if ( ((uint8_t)_regs.eax > 9) || (_regs.eflags & EFLG_AF) )
+ {
+ ((uint8_t *)&_regs.eax)[0] += (b == 0x37) ? 6 : -6;
+ ((uint8_t *)&_regs.eax)[1] += (b == 0x37) ? 1 : -1;
+ _regs.eflags |= EFLG_CF | EFLG_AF;
+ }
+ ((uint8_t *)&_regs.eax)[0] &= 0x0f;
+ break;
+
case 0x40 ... 0x4f: /* inc/dec reg */
dst.type = OP_REG;
dst.reg = decode_register(b & 7, &_regs, 0);
@@ -1253,6 +1320,45 @@ x86_emulate(
_regs.esi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
break;
+ case 0xd4: /* aam */ {
+ unsigned int base = insn_fetch_type(uint8_t);
+ uint8_t al = _regs.eax;
+ fail_if(mode_64bit());
+ generate_exception_if(base == 0, EXC_DE);
+ *(uint16_t *)&_regs.eax = ((al / base) << 8) | (al % base);
+ _regs.eflags &= ~(EFLG_SF|EFLG_ZF|EFLG_PF);
+ _regs.eflags |= ((uint8_t)_regs.eax == 0) ? EFLG_ZF : 0;
+ _regs.eflags |= (( int8_t)_regs.eax < 0) ? EFLG_SF : 0;
+ _regs.eflags |= even_parity(_regs.eax) ? EFLG_PF : 0;
+ break;
+ }
+
+ case 0xd5: /* aad */ {
+ unsigned int base = insn_fetch_type(uint8_t);
+ uint16_t ax = _regs.eax;
+ fail_if(mode_64bit());
+ *(uint16_t *)&_regs.eax = (uint8_t)(ax + ((ax >> 8) * base));
+ _regs.eflags &= ~(EFLG_SF|EFLG_ZF|EFLG_PF);
+ _regs.eflags |= ((uint8_t)_regs.eax == 0) ? EFLG_ZF : 0;
+ _regs.eflags |= (( int8_t)_regs.eax < 0) ? EFLG_SF : 0;
+ _regs.eflags |= even_parity(_regs.eax) ? EFLG_PF : 0;
+ break;
+ }
+
+ case 0xd6: /* salc */
+ fail_if(mode_64bit());
+ *(uint8_t *)&_regs.eax = (_regs.eflags & EFLG_CF) ? 0xff : 0x00;
+ break;
+
+ case 0xd7: /* xlat */ {
+ unsigned long al = (uint8_t)_regs.eax;
+ if ( (rc = ops->read(ea.mem.seg, truncate_ea(_regs.ebx + al),
+ &al, 1, ctxt)) != 0 )
+ goto done;
+ *(uint8_t *)&_regs.eax = al;
+ break;
+ }
+
case 0xe3: /* jcxz/jecxz (short) */ {
int rel = insn_fetch_type(int8_t);
if ( (ad_bytes == 2) ? !(uint16_t)_regs.ecx :
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|