Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 39f21ee5 authored by Avi Kivity's avatar Avi Kivity
Browse files

KVM: x86 emulator: consolidate immediate decode into a function



Signed-off-by: default avatarAvi Kivity <avi@redhat.com>
parent 48bb5d3c
Loading
Loading
Loading
Loading
+64 −45
Original line number Diff line number Diff line
@@ -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 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt)
		c->src = memop;
		break;
	case SrcImmU16:
		c->src.bytes = 2;
		goto srcimm;
	case SrcImm:
	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);
		rc = decode_imm(ctxt, &c->src, 2, false);
		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;
	case SrcImm:
		rc = decode_imm(ctxt, &c->src, imm_size(c), true);
		break;
			}
		}
	case SrcImmU:
		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 @@ 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.
@@ -2819,10 +2838,7 @@ 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;
@@ -2830,6 +2846,9 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt)
		break;
	}

	if (rc != X86EMUL_CONTINUE)
		goto done;

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