Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 271527
b: refs/heads/master
c: a994554
h: refs/heads/master
i:
  271525: 25bb5c0
  271523: 0247586
  271519: b253839
v: v3
  • Loading branch information
Avi Kivity committed Sep 25, 2011
1 parent 9ad7de5 commit a0da990
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 60 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: f09ed83e211d253809e575e05bd4de1e335c0cb2
refs/heads/master: a99455499a86bde28fccd84e2119be9cd7c23a3f
146 changes: 87 additions & 59 deletions trunk/arch/x86/kvm/emulate.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,22 @@
#include "x86.h"
#include "tss.h"

/*
* Operand types
*/
#define OpNone 0
#define OpImplicit 1 /* No generic decode */
#define OpReg 2 /* Register */
#define OpMem 3 /* Memory */
#define OpAcc 4 /* Accumulator: AL/AX/EAX/RAX */
#define OpDI 5 /* ES:DI/EDI/RDI */
#define OpMem64 6 /* Memory, 64-bit */
#define OpImmUByte 7 /* Zero-extended 8-bit immediate */
#define OpDX 8 /* DX register */

#define OpBits 4 /* Width of operand field */
#define OpMask ((1 << OpBits) - 1)

/*
* Opcode effective-address decode tables.
* Note that we only emulate instructions that have at least one memory
Expand All @@ -40,15 +56,16 @@
/* Operand sizes: 8-bit operands or specified/overridden size. */
#define ByteOp (1<<0) /* 8-bit operands. */
/* Destination operand type. */
#define ImplicitOps (1<<1) /* Implicit in opcode. No generic decode. */
#define DstReg (2<<1) /* Register operand. */
#define DstMem (3<<1) /* Memory operand. */
#define DstAcc (4<<1) /* Destination Accumulator */
#define DstDI (5<<1) /* Destination is in ES:(E)DI */
#define DstMem64 (6<<1) /* 64bit memory operand */
#define DstImmUByte (7<<1) /* 8-bit unsigned immediate operand */
#define DstDX (8<<1) /* Destination is in DX register */
#define DstMask (0xf<<1)
#define DstShift 1
#define ImplicitOps (OpImplicit << DstShift)
#define DstReg (OpReg << DstShift)
#define DstMem (OpMem << DstShift)
#define DstAcc (OpAcc << DstShift)
#define DstDI (OpDI << DstShift)
#define DstMem64 (OpMem64 << DstShift)
#define DstImmUByte (OpImmUByte << DstShift)
#define DstDX (OpDX << DstShift)
#define DstMask (OpMask << DstShift)
/* Source operand type. */
#define SrcNone (0<<5) /* No source operand. */
#define SrcReg (1<<5) /* Register operand. */
Expand Down Expand Up @@ -3316,6 +3333,66 @@ static int decode_imm(struct x86_emulate_ctxt *ctxt, struct operand *op,
return rc;
}

static int decode_operand(struct x86_emulate_ctxt *ctxt, struct operand *op,
unsigned d)
{
int rc = X86EMUL_CONTINUE;

switch (d) {
case OpReg:
decode_register_operand(ctxt, op,
ctxt->twobyte && (ctxt->b == 0xb6 || ctxt->b == 0xb7));
break;
case OpImmUByte:
op->type = OP_IMM;
op->addr.mem.ea = ctxt->_eip;
op->bytes = 1;
op->val = insn_fetch(u8, ctxt);
break;
case OpMem:
case OpMem64:
*op = ctxt->memop;
ctxt->memopp = op;
if (d == OpMem64)
op->bytes = 8;
else
op->bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
if (ctxt->d & BitOp)
fetch_bit_operand(ctxt);
op->orig_val = op->val;
break;
case OpAcc:
op->type = OP_REG;
op->bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
op->addr.reg = &ctxt->regs[VCPU_REGS_RAX];
fetch_register_operand(op);
op->orig_val = op->val;
break;
case OpDI:
op->type = OP_MEM;
op->bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
op->addr.mem.ea =
register_address(ctxt, ctxt->regs[VCPU_REGS_RDI]);
op->addr.mem.seg = VCPU_SREG_ES;
op->val = 0;
break;
case OpDX:
op->type = OP_REG;
op->bytes = 2;
op->addr.reg = &ctxt->regs[VCPU_REGS_RDX];
fetch_register_operand(op);
break;
case OpImplicit:
/* Special instructions do their own operand decoding. */
default:
op->type = OP_NONE; /* Disable writeback. */
break;
}

done:
return rc;
}

int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
{
int rc = X86EMUL_CONTINUE;
Expand Down Expand Up @@ -3602,56 +3679,7 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
goto done;

/* Decode and fetch the destination operand: register or memory. */
switch (ctxt->d & DstMask) {
case DstReg:
decode_register_operand(ctxt, &ctxt->dst,
ctxt->twobyte && (ctxt->b == 0xb6 || ctxt->b == 0xb7));
break;
case DstImmUByte:
ctxt->dst.type = OP_IMM;
ctxt->dst.addr.mem.ea = ctxt->_eip;
ctxt->dst.bytes = 1;
ctxt->dst.val = insn_fetch(u8, ctxt);
break;
case DstMem:
case DstMem64:
ctxt->dst = ctxt->memop;
ctxt->memopp = &ctxt->dst;
if ((ctxt->d & DstMask) == DstMem64)
ctxt->dst.bytes = 8;
else
ctxt->dst.bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
if (ctxt->d & BitOp)
fetch_bit_operand(ctxt);
ctxt->dst.orig_val = ctxt->dst.val;
break;
case DstAcc:
ctxt->dst.type = OP_REG;
ctxt->dst.bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
ctxt->dst.addr.reg = &ctxt->regs[VCPU_REGS_RAX];
fetch_register_operand(&ctxt->dst);
ctxt->dst.orig_val = ctxt->dst.val;
break;
case DstDI:
ctxt->dst.type = OP_MEM;
ctxt->dst.bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
ctxt->dst.addr.mem.ea =
register_address(ctxt, ctxt->regs[VCPU_REGS_RDI]);
ctxt->dst.addr.mem.seg = VCPU_SREG_ES;
ctxt->dst.val = 0;
break;
case DstDX:
ctxt->dst.type = OP_REG;
ctxt->dst.bytes = 2;
ctxt->dst.addr.reg = &ctxt->regs[VCPU_REGS_RDX];
fetch_register_operand(&ctxt->dst);
break;
case ImplicitOps:
/* Special instructions do their own operand decoding. */
default:
ctxt->dst.type = OP_NONE; /* Disable writeback. */
break;
}
rc = decode_operand(ctxt, &ctxt->dst, (ctxt->d >> DstShift) & OpMask);

done:
if (ctxt->memopp && ctxt->memopp->type == OP_MEM && ctxt->rip_relative)
Expand Down

0 comments on commit a0da990

Please sign in to comment.