Skip to content

Commit

Permalink
KVM: x86 emulator: consolidate immediate decode into a function
Browse files Browse the repository at this point in the history
Signed-off-by: Avi Kivity <avi@redhat.com>
  • Loading branch information
Avi Kivity committed Oct 24, 2010
1 parent 48bb5d3 commit 39f21ee
Showing 1 changed file with 64 additions and 45 deletions.
109 changes: 64 additions & 45 deletions arch/x86/kvm/emulate.c
Original file line number Diff line number Diff line change
Expand Up @@ -2541,6 +2541,55 @@ static struct opcode twobyte_table[256] = {
#undef GD
#undef I

static unsigned imm_size(struct decode_cache *c)
{
unsigned size;

size = (c->d & ByteOp) ? 1 : c->op_bytes;
if (size == 8)
size = 4;
return size;
}

static int decode_imm(struct x86_emulate_ctxt *ctxt, struct operand *op,
unsigned size, bool sign_extension)
{
struct decode_cache *c = &ctxt->decode;
struct x86_emulate_ops *ops = ctxt->ops;
int rc = X86EMUL_CONTINUE;

op->type = OP_IMM;
op->bytes = size;
op->addr.mem = c->eip;
/* NB. Immediates are sign-extended as necessary. */
switch (op->bytes) {
case 1:
op->val = insn_fetch(s8, 1, c->eip);
break;
case 2:
op->val = insn_fetch(s16, 2, c->eip);
break;
case 4:
op->val = insn_fetch(s32, 4, c->eip);
break;
}
if (!sign_extension) {
switch (op->bytes) {
case 1:
op->val &= 0xff;
break;
case 2:
op->val &= 0xffff;
break;
case 4:
op->val &= 0xffffffff;
break;
}
}
done:
return rc;
}

int
x86_decode_insn(struct x86_emulate_ctxt *ctxt)
{
Expand Down Expand Up @@ -2730,52 +2779,19 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt)
c->src = memop;
break;
case SrcImmU16:
c->src.bytes = 2;
goto srcimm;
rc = decode_imm(ctxt, &c->src, 2, false);
break;
case SrcImm:
rc = decode_imm(ctxt, &c->src, imm_size(c), true);
break;
case SrcImmU:
c->src.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
if (c->src.bytes == 8)
c->src.bytes = 4;
srcimm:
c->src.type = OP_IMM;
c->src.addr.mem = c->eip;
/* NB. Immediates are sign-extended as necessary. */
switch (c->src.bytes) {
case 1:
c->src.val = insn_fetch(s8, 1, c->eip);
break;
case 2:
c->src.val = insn_fetch(s16, 2, c->eip);
break;
case 4:
c->src.val = insn_fetch(s32, 4, c->eip);
break;
}
if ((c->d & SrcMask) == SrcImmU
|| (c->d & SrcMask) == SrcImmU16) {
switch (c->src.bytes) {
case 1:
c->src.val &= 0xff;
break;
case 2:
c->src.val &= 0xffff;
break;
case 4:
c->src.val &= 0xffffffff;
break;
}
}
rc = decode_imm(ctxt, &c->src, imm_size(c), false);
break;
case SrcImmByte:
rc = decode_imm(ctxt, &c->src, 1, true);
break;
case SrcImmUByte:
c->src.type = OP_IMM;
c->src.addr.mem = c->eip;
c->src.bytes = 1;
if ((c->d & SrcMask) == SrcImmByte)
c->src.val = insn_fetch(s8, 1, c->eip);
else
c->src.val = insn_fetch(u8, 1, c->eip);
rc = decode_imm(ctxt, &c->src, 1, false);
break;
case SrcAcc:
c->src.type = OP_REG;
Expand Down Expand Up @@ -2807,6 +2823,9 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt)
break;
}

if (rc != X86EMUL_CONTINUE)
goto done;

/*
* Decode and fetch the second source operand: register, memory
* or immediate.
Expand All @@ -2819,17 +2838,17 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt)
c->src2.val = c->regs[VCPU_REGS_RCX] & 0x8;
break;
case Src2ImmByte:
c->src2.type = OP_IMM;
c->src2.addr.mem = c->eip;
c->src2.bytes = 1;
c->src2.val = insn_fetch(u8, 1, c->eip);
rc = decode_imm(ctxt, &c->src2, 1, true);
break;
case Src2One:
c->src2.bytes = 1;
c->src2.val = 1;
break;
}

if (rc != X86EMUL_CONTINUE)
goto done;

/* Decode and fetch the destination operand: register or memory. */
switch (c->d & DstMask) {
case DstReg:
Expand Down

0 comments on commit 39f21ee

Please sign in to comment.