KVM: x86 emulator: consolidate immediate decode into a function

Signed-off-by: Avi Kivity <avi@redhat.com>
This commit is contained in:
Avi Kivity 2010-08-18 19:20:21 +03:00
parent 48bb5d3c40
commit 39f21ee546

View File

@ -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)
{
@ -2730,52 +2779,19 @@ done_prefixes:
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;
@ -2807,6 +2823,9 @@ done_prefixes:
break;
}
if (rc != X86EMUL_CONTINUE)
goto done;
/*
* Decode and fetch the second source operand: register, memory
* or immediate.
@ -2819,10 +2838,7 @@ done_prefixes:
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;
@ -2830,6 +2846,9 @@ done_prefixes:
break;
}
if (rc != X86EMUL_CONTINUE)
goto done;
/* Decode and fetch the destination operand: register or memory. */
switch (c->d & DstMask) {
case DstReg: