All of lore.kernel.org
 help / color / mirror / Atom feed
From: Laurent Vivier <Laurent.Vivier-6ktuUTfB/bM@public.gmane.org>
To: kvm-devel <kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
Subject: [PATCH 2/5][RESEND] move all x86_emulate_memop() to a structure
Date: Tue, 18 Sep 2007 11:27:09 +0200	[thread overview]
Message-ID: <46EF99ED.2010006@bull.net> (raw)

[-- Attachment #1: Type: text/plain, Size: 892 bytes --]

move all x86_emulate_memop() common variables between decode and execute to a
structure decode_cache.

            struct decode_cache {
                u8 twobyte;
                u8 b;
                u8 lock_prefix;
                u8 rep_prefix;
                u8 op_bytes;
                u8 ad_bytes;
                struct operand src;
                struct operand dst;
                unsigned long *override_base;
                unsigned int d;
                unsigned long regs[NR_VCPU_REGS];
                unsigned long eip;
                /* modrm */
                u8 modrm;
                u8 modrm_mod;
                u8 modrm_reg;
                u8 modrm_rm;
                u8 use_modrm_ea;
                unsigned long modrm_ea;
                unsigned long modrm_val;
           };

Signed-off-by: Laurent Vivier <Laurent.Vivier-6ktuUTfB/bM@public.gmane.org>


[-- Attachment #2: x86_emulate-context --]
[-- Type: text/plain, Size: 48604 bytes --]

Index: kvm/drivers/kvm/x86_emulate.c
===================================================================
--- kvm.orig/drivers/kvm/x86_emulate.c	2007-09-18 10:01:56.000000000 +0200
+++ kvm/drivers/kvm/x86_emulate.c	2007-09-18 10:05:42.000000000 +0200
@@ -221,13 +221,6 @@ static u16 twobyte_table[256] = {
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 };
 
-/* Type, address-of, and value of an instruction's operand. */
-struct operand {
-	enum { OP_REG, OP_MEM, OP_IMM } type;
-	unsigned int bytes;
-	unsigned long val, orig_val, *ptr;
-};
-
 /* EFLAGS bit definitions. */
 #define EFLG_OF (1<<11)
 #define EFLG_DF (1<<10)
@@ -430,25 +423,28 @@ struct operand {
 
 /* Access/update address held in a register, based on addressing mode. */
 #define address_mask(reg)						\
-	((ad_bytes == sizeof(unsigned long)) ? 				\
-		(reg) :	((reg) & ((1UL << (ad_bytes << 3)) - 1)))
+	((decode->ad_bytes == sizeof(unsigned long)) ? 			\
+		(reg) :	((reg) & ((1UL << (decode->ad_bytes << 3)) - 1)))
 #define register_address(base, reg)                                     \
 	((base) + address_mask(reg))
 #define register_address_increment(reg, inc)                            \
 	do {								\
 		/* signed type ensures sign extension to long */        \
 		int _inc = (inc);					\
-		if ( ad_bytes == sizeof(unsigned long) )		\
+		if (decode->ad_bytes == sizeof(unsigned long))		\
 			(reg) += _inc;					\
 		else							\
-			(reg) = ((reg) & ~((1UL << (ad_bytes << 3)) - 1)) | \
-			   (((reg) + _inc) & ((1UL << (ad_bytes << 3)) - 1)); \
+			(reg) = ((reg) & 				\
+			     ~((1UL << (decode->ad_bytes << 3)) - 1)) | \
+			   (((reg) + _inc) & 				\
+			       ((1UL << (decode->ad_bytes << 3)) - 1)); \
 	} while (0)
 
 #define JMP_REL(rel) 							\
 	do {								\
-		_eip += (int)(rel);					\
-		_eip = ((op_bytes == 2) ? (uint16_t)_eip : (uint32_t)_eip); \
+		decode->eip += (int)(rel);				\
+		decode->eip = ((decode->op_bytes == 2) ? 		\
+			(uint16_t)decode->eip : (uint32_t)decode->eip); \
 	} while (0)
 
 /*
@@ -524,39 +520,35 @@ static int test_cc(unsigned int conditio
 int
 x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
 {
-	unsigned d;
-	u8 b, sib, twobyte = 0, rex_prefix = 0;
-	u8 modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0;
-	unsigned long *override_base = NULL;
-	unsigned int op_bytes, ad_bytes, lock_prefix = 0, rep_prefix = 0, i;
+	struct decode_cache *decode = &ctxt->decode;
+	u8 sib, rex_prefix = 0;
+	unsigned int i;
 	int rc = 0;
-	struct operand src, dst;
 	unsigned long cr2 = ctxt->cr2;
 	int mode = ctxt->mode;
-	unsigned long modrm_ea;
-	int use_modrm_ea, index_reg = 0, base_reg = 0, scale, rip_relative = 0;
+	int index_reg = 0, base_reg = 0, scale, rip_relative = 0;
 	int no_wb = 0;
 	u64 msr_data;
 
 	/* Shadow copy of register state. Committed on successful emulation. */
-	unsigned long _regs[NR_VCPU_REGS];
-	unsigned long _eip = ctxt->vcpu->rip, _eflags = ctxt->eflags;
-	unsigned long modrm_val = 0;
+	unsigned long _eflags = ctxt->eflags;
 
-	memcpy(_regs, ctxt->vcpu->regs, sizeof _regs);
+	memset(decode, 0, sizeof(struct decode_cache));
+	decode->eip = ctxt->vcpu->rip;
+	memcpy(decode->regs, ctxt->vcpu->regs, sizeof decode->regs);
 
 	switch (mode) {
 	case X86EMUL_MODE_REAL:
 	case X86EMUL_MODE_PROT16:
-		op_bytes = ad_bytes = 2;
+		decode->op_bytes = decode->ad_bytes = 2;
 		break;
 	case X86EMUL_MODE_PROT32:
-		op_bytes = ad_bytes = 4;
+		decode->op_bytes = decode->ad_bytes = 4;
 		break;
 #ifdef CONFIG_X86_64
 	case X86EMUL_MODE_PROT64:
-		op_bytes = 4;
-		ad_bytes = 8;
+		decode->op_bytes = 4;
+		decode->ad_bytes = 8;
 		break;
 #endif
 	default:
@@ -565,39 +557,41 @@ x86_emulate_memop(struct x86_emulate_ctx
 
 	/* Legacy prefixes. */
 	for (i = 0; i < 8; i++) {
-		switch (b = insn_fetch(u8, 1, _eip)) {
+		switch (decode->b = insn_fetch(u8, 1, decode->eip)) {
 		case 0x66:	/* operand-size override */
-			op_bytes ^= 6;	/* switch between 2/4 bytes */
+			decode->op_bytes ^= 6;	/* switch between 2/4 bytes */
 			break;
 		case 0x67:	/* address-size override */
 			if (mode == X86EMUL_MODE_PROT64)
-				ad_bytes ^= 12;	/* switch between 4/8 bytes */
+				/* switch between 4/8 bytes */
+				decode->ad_bytes ^= 12;
 			else
-				ad_bytes ^= 6;	/* switch between 2/4 bytes */
+				/* switch between 2/4 bytes */
+				decode->ad_bytes ^= 6;
 			break;
 		case 0x2e:	/* CS override */
-			override_base = &ctxt->cs_base;
+			decode->override_base = &ctxt->cs_base;
 			break;
 		case 0x3e:	/* DS override */
-			override_base = &ctxt->ds_base;
+			decode->override_base = &ctxt->ds_base;
 			break;
 		case 0x26:	/* ES override */
-			override_base = &ctxt->es_base;
+			decode->override_base = &ctxt->es_base;
 			break;
 		case 0x64:	/* FS override */
-			override_base = &ctxt->fs_base;
+			decode->override_base = &ctxt->fs_base;
 			break;
 		case 0x65:	/* GS override */
-			override_base = &ctxt->gs_base;
+			decode->override_base = &ctxt->gs_base;
 			break;
 		case 0x36:	/* SS override */
-			override_base = &ctxt->ss_base;
+			decode->override_base = &ctxt->ss_base;
 			break;
 		case 0xf0:	/* LOCK */
-			lock_prefix = 1;
+			decode->lock_prefix = 1;
 			break;
 		case 0xf3:	/* REP/REPE/REPZ */
-			rep_prefix = 1;
+			decode->rep_prefix = 1;
 			break;
 		case 0xf2:	/* REPNE/REPNZ */
 			break;
@@ -609,177 +603,193 @@ x86_emulate_memop(struct x86_emulate_ctx
 done_prefixes:
 
 	/* REX prefix. */
-	if ((mode == X86EMUL_MODE_PROT64) && ((b & 0xf0) == 0x40)) {
-		rex_prefix = b;
-		if (b & 8)
-			op_bytes = 8;	/* REX.W */
-		modrm_reg = (b & 4) << 1;	/* REX.R */
-		index_reg = (b & 2) << 2; /* REX.X */
-		modrm_rm = base_reg = (b & 1) << 3; /* REG.B */
-		b = insn_fetch(u8, 1, _eip);
+	if ((mode == X86EMUL_MODE_PROT64) && ((decode->b & 0xf0) == 0x40)) {
+		rex_prefix = decode->b;
+		if (decode->b & 8)
+			decode->op_bytes = 8;	/* REX.W */
+		decode->modrm_reg = (decode->b & 4) << 1;	/* REX.R */
+		index_reg = (decode->b & 2) << 2; /* REX.X */
+		decode->modrm_rm = base_reg = (decode->b & 1) << 3; /* REG.B */
+		decode->b = insn_fetch(u8, 1, decode->eip);
 	}
 
 	/* Opcode byte(s). */
-	d = opcode_table[b];
-	if (d == 0) {
+	decode->d = opcode_table[decode->b];
+	if (decode->d == 0) {
 		/* Two-byte opcode? */
-		if (b == 0x0f) {
-			twobyte = 1;
-			b = insn_fetch(u8, 1, _eip);
-			d = twobyte_table[b];
+		if (decode->b == 0x0f) {
+			decode->twobyte = 1;
+			decode->b = insn_fetch(u8, 1, decode->eip);
+			decode->d = twobyte_table[decode->b];
 		}
 
 		/* Unrecognised? */
-		if (d == 0)
+		if (decode->d == 0)
 			goto cannot_emulate;
 	}
 
 	/* ModRM and SIB bytes. */
-	if (d & ModRM) {
-		modrm = insn_fetch(u8, 1, _eip);
-		modrm_mod |= (modrm & 0xc0) >> 6;
-		modrm_reg |= (modrm & 0x38) >> 3;
-		modrm_rm |= (modrm & 0x07);
-		modrm_ea = 0;
-		use_modrm_ea = 1;
-
-		if (modrm_mod == 3) {
-			modrm_val = *(unsigned long *)
-				decode_register(modrm_rm, _regs, d & ByteOp);
+	if (decode->d & ModRM) {
+		decode->modrm = insn_fetch(u8, 1, decode->eip);
+		decode->modrm_mod |= (decode->modrm & 0xc0) >> 6;
+		decode->modrm_reg |= (decode->modrm & 0x38) >> 3;
+		decode->modrm_rm |= (decode->modrm & 0x07);
+		decode->modrm_ea = 0;
+		decode->use_modrm_ea = 1;
+
+		if (decode->modrm_mod == 3) {
+			decode->modrm_val = *(unsigned long *)
+				decode_register(decode->modrm_rm,
+						decode->regs,
+						decode->d & ByteOp);
 			goto modrm_done;
 		}
 
-		if (ad_bytes == 2) {
-			unsigned bx = _regs[VCPU_REGS_RBX];
-			unsigned bp = _regs[VCPU_REGS_RBP];
-			unsigned si = _regs[VCPU_REGS_RSI];
-			unsigned di = _regs[VCPU_REGS_RDI];
+		if (decode->ad_bytes == 2) {
+			unsigned bx = decode->regs[VCPU_REGS_RBX];
+			unsigned bp = decode->regs[VCPU_REGS_RBP];
+			unsigned si = decode->regs[VCPU_REGS_RSI];
+			unsigned di = decode->regs[VCPU_REGS_RDI];
 
 			/* 16-bit ModR/M decode. */
-			switch (modrm_mod) {
+			switch (decode->modrm_mod) {
 			case 0:
-				if (modrm_rm == 6)
-					modrm_ea += insn_fetch(u16, 2, _eip);
+				if (decode->modrm_rm == 6)
+					decode->modrm_ea +=
+						insn_fetch(u16, 2, decode->eip);
 				break;
 			case 1:
-				modrm_ea += insn_fetch(s8, 1, _eip);
+				decode->modrm_ea +=
+						insn_fetch(s8, 1, decode->eip);
 				break;
 			case 2:
-				modrm_ea += insn_fetch(u16, 2, _eip);
+				decode->modrm_ea +=
+						insn_fetch(u16, 2, decode->eip);
 				break;
 			}
-			switch (modrm_rm) {
+			switch (decode->modrm_rm) {
 			case 0:
-				modrm_ea += bx + si;
+				decode->modrm_ea += bx + si;
 				break;
 			case 1:
-				modrm_ea += bx + di;
+				decode->modrm_ea += bx + di;
 				break;
 			case 2:
-				modrm_ea += bp + si;
+				decode->modrm_ea += bp + si;
 				break;
 			case 3:
-				modrm_ea += bp + di;
+				decode->modrm_ea += bp + di;
 				break;
 			case 4:
-				modrm_ea += si;
+				decode->modrm_ea += si;
 				break;
 			case 5:
-				modrm_ea += di;
+				decode->modrm_ea += di;
 				break;
 			case 6:
-				if (modrm_mod != 0)
-					modrm_ea += bp;
+				if (decode->modrm_mod != 0)
+					decode->modrm_ea += bp;
 				break;
 			case 7:
-				modrm_ea += bx;
+				decode->modrm_ea += bx;
 				break;
 			}
-			if (modrm_rm == 2 || modrm_rm == 3 ||
-			    (modrm_rm == 6 && modrm_mod != 0))
-				if (!override_base)
-					override_base = &ctxt->ss_base;
-			modrm_ea = (u16)modrm_ea;
+			if (decode->modrm_rm == 2 || decode->modrm_rm == 3 ||
+			    (decode->modrm_rm == 6 && decode->modrm_mod != 0))
+				if (!decode->override_base)
+					decode->override_base = &ctxt->ss_base;
+			decode->modrm_ea = (u16)decode->modrm_ea;
 		} else {
 			/* 32/64-bit ModR/M decode. */
-			switch (modrm_rm) {
+			switch (decode->modrm_rm) {
 			case 4:
 			case 12:
-				sib = insn_fetch(u8, 1, _eip);
+				sib = insn_fetch(u8, 1, decode->eip);
 				index_reg |= (sib >> 3) & 7;
 				base_reg |= sib & 7;
 				scale = sib >> 6;
 
 				switch (base_reg) {
 				case 5:
-					if (modrm_mod != 0)
-						modrm_ea += _regs[base_reg];
+					if (decode->modrm_mod != 0)
+						decode->modrm_ea +=
+							decode->regs[base_reg];
 					else
-						modrm_ea += insn_fetch(s32, 4, _eip);
+						decode->modrm_ea +=
+							insn_fetch(s32, 4,
+							decode->eip);
 					break;
 				default:
-					modrm_ea += _regs[base_reg];
+					decode->modrm_ea +=
+							decode->regs[base_reg];
 				}
 				switch (index_reg) {
 				case 4:
 					break;
 				default:
-					modrm_ea += _regs[index_reg] << scale;
+					decode->modrm_ea +=
+					decode->regs[index_reg] << scale;
 
 				}
 				break;
 			case 5:
-				if (modrm_mod != 0)
-					modrm_ea += _regs[modrm_rm];
+				if (decode->modrm_mod != 0)
+					decode->modrm_ea +=
+						decode->regs[decode->modrm_rm];
 				else if (mode == X86EMUL_MODE_PROT64)
 					rip_relative = 1;
 				break;
 			default:
-				modrm_ea += _regs[modrm_rm];
+				decode->modrm_ea +=
+						decode->regs[decode->modrm_rm];
 				break;
 			}
-			switch (modrm_mod) {
+			switch (decode->modrm_mod) {
 			case 0:
-				if (modrm_rm == 5)
-					modrm_ea += insn_fetch(s32, 4, _eip);
+				if (decode->modrm_rm == 5)
+					decode->modrm_ea +=
+						insn_fetch(s32, 4, decode->eip);
 				break;
 			case 1:
-				modrm_ea += insn_fetch(s8, 1, _eip);
+				decode->modrm_ea +=
+						insn_fetch(s8, 1, decode->eip);
 				break;
 			case 2:
-				modrm_ea += insn_fetch(s32, 4, _eip);
+				decode->modrm_ea +=
+						insn_fetch(s32, 4, decode->eip);
 				break;
 			}
 		}
-		if (!override_base)
-			override_base = &ctxt->ds_base;
+		if (!decode->override_base)
+			decode->override_base = &ctxt->ds_base;
 		if (mode == X86EMUL_MODE_PROT64 &&
-		    override_base != &ctxt->fs_base &&
-		    override_base != &ctxt->gs_base)
-			override_base = NULL;
+		    decode->override_base != &ctxt->fs_base &&
+		    decode->override_base != &ctxt->gs_base)
+			decode->override_base = NULL;
 
-		if (override_base)
-			modrm_ea += *override_base;
+		if (decode->override_base)
+			decode->modrm_ea += *decode->override_base;
 
 		if (rip_relative) {
-			modrm_ea += _eip;
-			switch (d & SrcMask) {
+			decode->modrm_ea += decode->eip;
+			switch (decode->d & SrcMask) {
 			case SrcImmByte:
-				modrm_ea += 1;
+				decode->modrm_ea += 1;
 				break;
 			case SrcImm:
-				if (d & ByteOp)
-					modrm_ea += 1;
+				if (decode->d & ByteOp)
+					decode->modrm_ea += 1;
 				else
-					if (op_bytes == 8)
-						modrm_ea += 4;
+					if (decode->op_bytes == 8)
+						decode->modrm_ea += 4;
 					else
-						modrm_ea += op_bytes;
+						decode->modrm_ea +=
+							decode->op_bytes;
 			}
 		}
-		if (ad_bytes != 8)
-			modrm_ea = (u32)modrm_ea;
-		cr2 = modrm_ea;
+		if (decode->ad_bytes != 8)
+			decode->modrm_ea = (u32)decode->modrm_ea;
+		cr2 = decode->modrm_ea;
 	modrm_done:
 		;
 	}
@@ -788,195 +798,212 @@ done_prefixes:
 	 * Decode and fetch the source operand: register, memory
 	 * or immediate.
 	 */
-	switch (d & SrcMask) {
+	switch (decode->d & SrcMask) {
 	case SrcNone:
 		break;
 	case SrcReg:
-		src.type = OP_REG;
-		if (d & ByteOp) {
-			src.ptr = decode_register(modrm_reg, _regs,
+		decode->src.type = OP_REG;
+		if (decode->d & ByteOp) {
+			decode->src.ptr =
+				decode_register(decode->modrm_reg, decode->regs,
 						  (rex_prefix == 0));
-			src.val = src.orig_val = *(u8 *) src.ptr;
-			src.bytes = 1;
+			decode->src.val = decode->src.orig_val =
+							*(u8 *) decode->src.ptr;
+			decode->src.bytes = 1;
 		} else {
-			src.ptr = decode_register(modrm_reg, _regs, 0);
-			switch ((src.bytes = op_bytes)) {
+			decode->src.ptr =
+			    decode_register(decode->modrm_reg, decode->regs, 0);
+			switch ((decode->src.bytes = decode->op_bytes)) {
 			case 2:
-				src.val = src.orig_val = *(u16 *) src.ptr;
+				decode->src.val = decode->src.orig_val =
+						       *(u16 *) decode->src.ptr;
 				break;
 			case 4:
-				src.val = src.orig_val = *(u32 *) src.ptr;
+				decode->src.val = decode->src.orig_val =
+						       *(u32 *) decode->src.ptr;
 				break;
 			case 8:
-				src.val = src.orig_val = *(u64 *) src.ptr;
+				decode->src.val = decode->src.orig_val =
+						       *(u64 *) decode->src.ptr;
 				break;
 			}
 		}
 		break;
 	case SrcMem16:
-		src.bytes = 2;
+		decode->src.bytes = 2;
 		goto srcmem_common;
 	case SrcMem32:
-		src.bytes = 4;
+		decode->src.bytes = 4;
 		goto srcmem_common;
 	case SrcMem:
-		src.bytes = (d & ByteOp) ? 1 : op_bytes;
+		decode->src.bytes = (decode->d & ByteOp) ? 1 :
+							   decode->op_bytes;
 		/* Don't fetch the address for invlpg: it could be unmapped. */
-		if (twobyte && b == 0x01 && modrm_reg == 7)
+		if (decode->twobyte && decode->b == 0x01
+				    && decode->modrm_reg == 7)
 			break;
 	      srcmem_common:
-		src.type = OP_MEM;
-		src.ptr = (unsigned long *)cr2;
-		src.val = 0;
-		if ((rc = ops->read_emulated((unsigned long)src.ptr,
-					     &src.val, src.bytes, ctxt->vcpu)) != 0)
+		decode->src.type = OP_MEM;
+		decode->src.ptr = (unsigned long *)cr2;
+		decode->src.val = 0;
+		if ((rc = ops->read_emulated((unsigned long)decode->src.ptr,
+					   &decode->src.val,
+					   decode->src.bytes, ctxt->vcpu)) != 0)
 			goto done;
-		src.orig_val = src.val;
+		decode->src.orig_val = decode->src.val;
 		break;
 	case SrcImm:
-		src.type = OP_IMM;
-		src.ptr = (unsigned long *)_eip;
-		src.bytes = (d & ByteOp) ? 1 : op_bytes;
-		if (src.bytes == 8)
-			src.bytes = 4;
+		decode->src.type = OP_IMM;
+		decode->src.ptr = (unsigned long *)decode->eip;
+		decode->src.bytes = (decode->d & ByteOp) ? 1 : decode->op_bytes;
+		if (decode->src.bytes == 8)
+			decode->src.bytes = 4;
 		/* NB. Immediates are sign-extended as necessary. */
-		switch (src.bytes) {
+		switch (decode->src.bytes) {
 		case 1:
-			src.val = insn_fetch(s8, 1, _eip);
+			decode->src.val = insn_fetch(s8, 1, decode->eip);
 			break;
 		case 2:
-			src.val = insn_fetch(s16, 2, _eip);
+			decode->src.val = insn_fetch(s16, 2, decode->eip);
 			break;
 		case 4:
-			src.val = insn_fetch(s32, 4, _eip);
+			decode->src.val = insn_fetch(s32, 4, decode->eip);
 			break;
 		}
 		break;
 	case SrcImmByte:
-		src.type = OP_IMM;
-		src.ptr = (unsigned long *)_eip;
-		src.bytes = 1;
-		src.val = insn_fetch(s8, 1, _eip);
+		decode->src.type = OP_IMM;
+		decode->src.ptr = (unsigned long *)decode->eip;
+		decode->src.bytes = 1;
+		decode->src.val = insn_fetch(s8, 1, decode->eip);
 		break;
 	}
 
 	/* Decode and fetch the destination operand: register or memory. */
-	switch (d & DstMask) {
+	switch (decode->d & DstMask) {
 	case ImplicitOps:
 		/* Special instructions do their own operand decoding. */
 		goto special_insn;
 	case DstReg:
-		dst.type = OP_REG;
-		if ((d & ByteOp)
-		    && !(twobyte && (b == 0xb6 || b == 0xb7))) {
-			dst.ptr = decode_register(modrm_reg, _regs,
+		decode->dst.type = OP_REG;
+		if ((decode->d & ByteOp)
+		    && !(decode->twobyte &&
+			(decode->b == 0xb6 || decode->b == 0xb7))) {
+			decode->dst.ptr =
+				decode_register(decode->modrm_reg, decode->regs,
 						  (rex_prefix == 0));
-			dst.val = *(u8 *) dst.ptr;
-			dst.bytes = 1;
+			decode->dst.val = *(u8 *) decode->dst.ptr;
+			decode->dst.bytes = 1;
 		} else {
-			dst.ptr = decode_register(modrm_reg, _regs, 0);
-			switch ((dst.bytes = op_bytes)) {
+			decode->dst.ptr =
+			    decode_register(decode->modrm_reg, decode->regs, 0);
+			switch ((decode->dst.bytes = decode->op_bytes)) {
 			case 2:
-				dst.val = *(u16 *)dst.ptr;
+				decode->dst.val = *(u16 *)decode->dst.ptr;
 				break;
 			case 4:
-				dst.val = *(u32 *)dst.ptr;
+				decode->dst.val = *(u32 *)decode->dst.ptr;
 				break;
 			case 8:
-				dst.val = *(u64 *)dst.ptr;
+				decode->dst.val = *(u64 *)decode->dst.ptr;
 				break;
 			}
 		}
 		break;
 	case DstMem:
-		dst.type = OP_MEM;
-		dst.ptr = (unsigned long *)cr2;
-		dst.bytes = (d & ByteOp) ? 1 : op_bytes;
-		dst.val = 0;
-		if (d & BitOp) {
-			unsigned long mask = ~(dst.bytes * 8 - 1);
-
-			dst.ptr = (void *)dst.ptr + (src.val & mask) / 8;
-		}
-		if (!(d & Mov) && /* optimisation - avoid slow emulated read */
-		    ((rc = ops->read_emulated((unsigned long)dst.ptr,
-					      &dst.val, dst.bytes, ctxt->vcpu)) != 0))
+		decode->dst.type = OP_MEM;
+		decode->dst.ptr = (unsigned long *)cr2;
+		decode->dst.bytes = (decode->d & ByteOp) ? 1 : decode->op_bytes;
+		decode->dst.val = 0;
+		if (decode->d & BitOp) {
+			unsigned long mask = ~(decode->dst.bytes * 8 - 1);
+
+			decode->dst.ptr = (void *)decode->dst.ptr +
+						   (decode->src.val & mask) / 8;
+		}
+		if (!(decode->d & Mov) &&
+				   /* optimisation - avoid slow emulated read */
+		    ((rc = ops->read_emulated((unsigned long)decode->dst.ptr,
+					   &decode->dst.val,
+					  decode->dst.bytes, ctxt->vcpu)) != 0))
 			goto done;
 		break;
 	}
-	dst.orig_val = dst.val;
+	decode->dst.orig_val = decode->dst.val;
 
-	if (twobyte)
+	if (decode->twobyte)
 		goto twobyte_insn;
 
-	switch (b) {
+	switch (decode->b) {
 	case 0x00 ... 0x05:
 	      add:		/* add */
-		emulate_2op_SrcV("add", src, dst, _eflags);
+		emulate_2op_SrcV("add", decode->src, decode->dst, _eflags);
 		break;
 	case 0x08 ... 0x0d:
 	      or:		/* or */
-		emulate_2op_SrcV("or", src, dst, _eflags);
+		emulate_2op_SrcV("or", decode->src, decode->dst, _eflags);
 		break;
 	case 0x10 ... 0x15:
 	      adc:		/* adc */
-		emulate_2op_SrcV("adc", src, dst, _eflags);
+		emulate_2op_SrcV("adc", decode->src, decode->dst, _eflags);
 		break;
 	case 0x18 ... 0x1d:
 	      sbb:		/* sbb */
-		emulate_2op_SrcV("sbb", src, dst, _eflags);
+		emulate_2op_SrcV("sbb", decode->src, decode->dst, _eflags);
 		break;
 	case 0x20 ... 0x23:
 	      and:		/* and */
-		emulate_2op_SrcV("and", src, dst, _eflags);
+		emulate_2op_SrcV("and", decode->src, decode->dst, _eflags);
 		break;
 	case 0x24:              /* and al imm8 */
-		dst.type = OP_REG;
-		dst.ptr = &_regs[VCPU_REGS_RAX];
-		dst.val = *(u8 *)dst.ptr;
-		dst.bytes = 1;
-		dst.orig_val = dst.val;
+		decode->dst.type = OP_REG;
+		decode->dst.ptr = &decode->regs[VCPU_REGS_RAX];
+		decode->dst.val = *(u8 *)decode->dst.ptr;
+		decode->dst.bytes = 1;
+		decode->dst.orig_val = decode->dst.val;
 		goto and;
 	case 0x25:              /* and ax imm16, or eax imm32 */
-		dst.type = OP_REG;
-		dst.bytes = op_bytes;
-		dst.ptr = &_regs[VCPU_REGS_RAX];
-		if (op_bytes == 2)
-			dst.val = *(u16 *)dst.ptr;
+		decode->dst.type = OP_REG;
+		decode->dst.bytes = decode->op_bytes;
+		decode->dst.ptr = &decode->regs[VCPU_REGS_RAX];
+		if (decode->op_bytes == 2)
+			decode->dst.val = *(u16 *)decode->dst.ptr;
 		else
-			dst.val = *(u32 *)dst.ptr;
-		dst.orig_val = dst.val;
+			decode->dst.val = *(u32 *)decode->dst.ptr;
+		decode->dst.orig_val = decode->dst.val;
 		goto and;
 	case 0x28 ... 0x2d:
 	      sub:		/* sub */
-		emulate_2op_SrcV("sub", src, dst, _eflags);
+		emulate_2op_SrcV("sub", decode->src, decode->dst, _eflags);
 		break;
 	case 0x30 ... 0x35:
 	      xor:		/* xor */
-		emulate_2op_SrcV("xor", src, dst, _eflags);
+		emulate_2op_SrcV("xor", decode->src, decode->dst, _eflags);
 		break;
 	case 0x38 ... 0x3d:
 	      cmp:		/* cmp */
-		emulate_2op_SrcV("cmp", src, dst, _eflags);
+		emulate_2op_SrcV("cmp", decode->src, decode->dst, _eflags);
 		break;
 	case 0x63:		/* movsxd */
 		if (mode != X86EMUL_MODE_PROT64)
 			goto cannot_emulate;
-		dst.val = (s32) src.val;
+		decode->dst.val = (s32) decode->src.val;
 		break;
 	case 0x6a: /* push imm8 */
-		src.val = 0L;
-		src.val = insn_fetch(s8, 1, _eip);
+		decode->src.val = 0L;
+		decode->src.val = insn_fetch(s8, 1, decode->eip);
 push:
-		dst.type  = OP_MEM;
-		dst.bytes = op_bytes;
-		dst.val = src.val;
-		register_address_increment(_regs[VCPU_REGS_RSP], -op_bytes);
-		dst.ptr = (void *) register_address(ctxt->ss_base,
-							_regs[VCPU_REGS_RSP]);
+		decode->dst.type  = OP_MEM;
+		decode->dst.bytes = decode->op_bytes;
+		decode->dst.val = decode->src.val;
+		register_address_increment(decode->regs[VCPU_REGS_RSP],
+					   -decode->op_bytes);
+		decode->dst.ptr = (void *) register_address(
+						ctxt->ss_base,
+						decode->regs[VCPU_REGS_RSP]);
 		break;
 	case 0x80 ... 0x83:	/* Grp1 */
-		switch (modrm_reg) {
+		switch (decode->modrm_reg) {
 		case 0:
 			goto add;
 		case 1:
@@ -997,180 +1024,199 @@ push:
 		break;
 	case 0x84 ... 0x85:
 	      test:		/* test */
-		emulate_2op_SrcV("test", src, dst, _eflags);
+		emulate_2op_SrcV("test", decode->src, decode->dst, _eflags);
 		break;
 	case 0x86 ... 0x87:	/* xchg */
 		/* Write back the register source. */
-		switch (dst.bytes) {
+		switch (decode->dst.bytes) {
 		case 1:
-			*(u8 *) src.ptr = (u8) dst.val;
+			*(u8 *) decode->src.ptr = (u8) decode->dst.val;
 			break;
 		case 2:
-			*(u16 *) src.ptr = (u16) dst.val;
+			*(u16 *) decode->src.ptr = (u16) decode->dst.val;
 			break;
 		case 4:
-			*src.ptr = (u32) dst.val;
+			*decode->src.ptr = (u32) decode->dst.val;
 			break;	/* 64b reg: zero-extend */
 		case 8:
-			*src.ptr = dst.val;
+			*decode->src.ptr = decode->dst.val;
 			break;
 		}
 		/*
 		 * Write back the memory destination with implicit LOCK
 		 * prefix.
 		 */
-		dst.val = src.val;
-		lock_prefix = 1;
+		decode->dst.val = decode->src.val;
+		decode->lock_prefix = 1;
 		break;
 	case 0x88 ... 0x8b:	/* mov */
 		goto mov;
 	case 0x8d: /* lea r16/r32, m */
-		dst.val = modrm_val;
+		decode->dst.val = decode->modrm_val;
 		break;
 	case 0x8f:		/* pop (sole member of Grp1a) */
 		/* 64-bit mode: POP always pops a 64-bit operand. */
 		if (mode == X86EMUL_MODE_PROT64)
-			dst.bytes = 8;
-		if ((rc = ops->read_std(register_address(ctxt->ss_base,
-							 _regs[VCPU_REGS_RSP]),
-					&dst.val, dst.bytes, ctxt->vcpu)) != 0)
+			decode->dst.bytes = 8;
+		if ((rc = ops->read_std(register_address(
+						   ctxt->ss_base,
+						   decode->regs[VCPU_REGS_RSP]),
+						   &decode->dst.val,
+						   decode->dst.bytes,
+						   ctxt->vcpu)) != 0)
 			goto done;
-		register_address_increment(_regs[VCPU_REGS_RSP], dst.bytes);
+		register_address_increment(decode->regs[VCPU_REGS_RSP],
+					   decode->dst.bytes);
 		break;
 	case 0xa0 ... 0xa1:	/* mov */
-		dst.ptr = (unsigned long *)&_regs[VCPU_REGS_RAX];
-		dst.val = src.val;
-		_eip += ad_bytes;	/* skip src displacement */
+		decode->dst.ptr = (unsigned long *)&decode->regs[VCPU_REGS_RAX];
+		decode->dst.val = decode->src.val;
+		/* skip src displacement */
+		decode->eip += decode->ad_bytes;
 		break;
 	case 0xa2 ... 0xa3:	/* mov */
-		dst.val = (unsigned long)_regs[VCPU_REGS_RAX];
-		_eip += ad_bytes;	/* skip dst displacement */
+		decode->dst.val = (unsigned long)decode->regs[VCPU_REGS_RAX];
+		/* skip decode->dst displacement */
+		decode->eip += decode->ad_bytes;
 		break;
 	case 0xc0 ... 0xc1:
 	      grp2:		/* Grp2 */
-		switch (modrm_reg) {
+		switch (decode->modrm_reg) {
 		case 0:	/* rol */
-			emulate_2op_SrcB("rol", src, dst, _eflags);
+			emulate_2op_SrcB("rol",
+					 decode->src, decode->dst, _eflags);
 			break;
 		case 1:	/* ror */
-			emulate_2op_SrcB("ror", src, dst, _eflags);
+			emulate_2op_SrcB("ror",
+					 decode->src, decode->dst, _eflags);
 			break;
 		case 2:	/* rcl */
-			emulate_2op_SrcB("rcl", src, dst, _eflags);
+			emulate_2op_SrcB("rcl",
+					 decode->src, decode->dst, _eflags);
 			break;
 		case 3:	/* rcr */
-			emulate_2op_SrcB("rcr", src, dst, _eflags);
+			emulate_2op_SrcB("rcr",
+					 decode->src, decode->dst, _eflags);
 			break;
 		case 4:	/* sal/shl */
 		case 6:	/* sal/shl */
-			emulate_2op_SrcB("sal", src, dst, _eflags);
+			emulate_2op_SrcB("sal",
+					 decode->src, decode->dst, _eflags);
 			break;
 		case 5:	/* shr */
-			emulate_2op_SrcB("shr", src, dst, _eflags);
+			emulate_2op_SrcB("shr",
+					 decode->src, decode->dst, _eflags);
 			break;
 		case 7:	/* sar */
-			emulate_2op_SrcB("sar", src, dst, _eflags);
+			emulate_2op_SrcB("sar",
+					 decode->src, decode->dst, _eflags);
 			break;
 		}
 		break;
 	case 0xc6 ... 0xc7:	/* mov (sole member of Grp11) */
 	mov:
-		dst.val = src.val;
+		decode->dst.val = decode->src.val;
 		break;
 	case 0xd0 ... 0xd1:	/* Grp2 */
-		src.val = 1;
+		decode->src.val = 1;
 		goto grp2;
 	case 0xd2 ... 0xd3:	/* Grp2 */
-		src.val = _regs[VCPU_REGS_RCX];
+		decode->src.val = decode->regs[VCPU_REGS_RCX];
 		goto grp2;
 	case 0xe8: /* call (near) */ {
 		long int rel;
-		switch (op_bytes) {
+		switch (decode->op_bytes) {
 		case 2:
-			rel = insn_fetch(s16, 2, _eip);
+			rel = insn_fetch(s16, 2, decode->eip);
 			break;
 		case 4:
-			rel = insn_fetch(s32, 4, _eip);
+			rel = insn_fetch(s32, 4, decode->eip);
 			break;
 		case 8:
-			rel = insn_fetch(s64, 8, _eip);
+			rel = insn_fetch(s64, 8, decode->eip);
 			break;
 		default:
 			DPRINTF("Call: Invalid op_bytes\n");
 			goto cannot_emulate;
 		}
-		src.val = (unsigned long) _eip;
+		decode->src.val = (unsigned long) decode->eip;
 		JMP_REL(rel);
 		goto push;
 	}
 	case 0xe9: /* jmp rel */
 	case 0xeb: /* jmp rel short */
-		JMP_REL(src.val);
+		JMP_REL(decode->src.val);
 		no_wb = 1; /* Disable writeback. */
 		break;
 	case 0xf6 ... 0xf7:	/* Grp3 */
-		switch (modrm_reg) {
+		switch (decode->modrm_reg) {
 		case 0 ... 1:	/* test */
 			/*
 			 * Special case in Grp3: test has an immediate
 			 * source operand.
 			 */
-			src.type = OP_IMM;
-			src.ptr = (unsigned long *)_eip;
-			src.bytes = (d & ByteOp) ? 1 : op_bytes;
-			if (src.bytes == 8)
-				src.bytes = 4;
-			switch (src.bytes) {
+			decode->src.type = OP_IMM;
+			decode->src.ptr = (unsigned long *)decode->eip;
+			decode->src.bytes = (decode->d & ByteOp) ? 1 :
+							       decode->op_bytes;
+			if (decode->src.bytes == 8)
+				decode->src.bytes = 4;
+			switch (decode->src.bytes) {
 			case 1:
-				src.val = insn_fetch(s8, 1, _eip);
+				decode->src.val = insn_fetch(s8, 1,
+							     decode->eip);
 				break;
 			case 2:
-				src.val = insn_fetch(s16, 2, _eip);
+				decode->src.val = insn_fetch(s16, 2,
+							     decode->eip);
 				break;
 			case 4:
-				src.val = insn_fetch(s32, 4, _eip);
+				decode->src.val = insn_fetch(s32, 4,
+							     decode->eip);
 				break;
 			}
 			goto test;
 		case 2:	/* not */
-			dst.val = ~dst.val;
+			decode->dst.val = ~decode->dst.val;
 			break;
 		case 3:	/* neg */
-			emulate_1op("neg", dst, _eflags);
+			emulate_1op("neg", decode->dst, _eflags);
 			break;
 		default:
 			goto cannot_emulate;
 		}
 		break;
 	case 0xfe ... 0xff:	/* Grp4/Grp5 */
-		switch (modrm_reg) {
+		switch (decode->modrm_reg) {
 		case 0:	/* inc */
-			emulate_1op("inc", dst, _eflags);
+			emulate_1op("inc", decode->dst, _eflags);
 			break;
 		case 1:	/* dec */
-			emulate_1op("dec", dst, _eflags);
+			emulate_1op("dec", decode->dst, _eflags);
 			break;
 		case 4: /* jmp abs */
-			if (b == 0xff)
-				_eip = dst.val;
+			if (decode->b == 0xff)
+				decode->eip = decode->dst.val;
 			else
 				goto cannot_emulate;
 			break;
 		case 6:	/* push */
 			/* 64-bit mode: PUSH always pushes a 64-bit operand. */
 			if (mode == X86EMUL_MODE_PROT64) {
-				dst.bytes = 8;
-				if ((rc = ops->read_std((unsigned long)dst.ptr,
-							&dst.val, 8,
-							ctxt->vcpu)) != 0)
+				decode->dst.bytes = 8;
+				if ((rc = ops->read_std(
+						 (unsigned long)decode->dst.ptr,
+						 &decode->dst.val, 8,
+						 ctxt->vcpu)) != 0)
 					goto done;
 			}
-			register_address_increment(_regs[VCPU_REGS_RSP],
-						   -dst.bytes);
+			register_address_increment(decode->regs[VCPU_REGS_RSP],
+						   -decode->dst.bytes);
 			if ((rc = ops->write_std(
 				     register_address(ctxt->ss_base,
-						      _regs[VCPU_REGS_RSP]),
-				     &dst.val, dst.bytes, ctxt->vcpu)) != 0)
+					  decode->regs[VCPU_REGS_RSP]),
+					  &decode->dst.val,
+					   decode->dst.bytes, ctxt->vcpu)) != 0)
 				goto done;
 			no_wb = 1;
 			break;
@@ -1182,34 +1228,40 @@ push:
 
 writeback:
 	if (!no_wb) {
-		switch (dst.type) {
+		switch (decode->dst.type) {
 		case OP_REG:
-			/* The 4-byte case *is* correct: in 64-bit mode we zero-extend. */
-			switch (dst.bytes) {
+			/* The 4-byte case *is* correct:
+			 * in 64-bit mode we zero-extend.
+			 */
+			switch (decode->dst.bytes) {
 			case 1:
-				*(u8 *)dst.ptr = (u8)dst.val;
+				*(u8 *)decode->dst.ptr = (u8)decode->dst.val;
 				break;
 			case 2:
-				*(u16 *)dst.ptr = (u16)dst.val;
+				*(u16 *)decode->dst.ptr = (u16)decode->dst.val;
 				break;
 			case 4:
-				*dst.ptr = (u32)dst.val;
+				*decode->dst.ptr = (u32)decode->dst.val;
 				break;	/* 64b: zero-ext */
 			case 8:
-				*dst.ptr = dst.val;
+				*decode->dst.ptr = decode->dst.val;
 				break;
 			}
 			break;
 		case OP_MEM:
-			if (lock_prefix)
-				rc = ops->cmpxchg_emulated((unsigned long)dst.
-							   ptr, &dst.orig_val,
-							   &dst.val, dst.bytes,
-							   ctxt->vcpu);
+			if (decode->lock_prefix)
+				rc = ops->cmpxchg_emulated(
+						(unsigned long)decode->dst.ptr,
+						&decode->dst.orig_val,
+						&decode->dst.val,
+						decode->dst.bytes,
+						ctxt->vcpu);
 			else
-				rc = ops->write_emulated((unsigned long)dst.ptr,
-							 &dst.val, dst.bytes,
-							 ctxt->vcpu);
+				rc = ops->write_emulated(
+						(unsigned long)decode->dst.ptr,
+						&decode->dst.val,
+						decode->dst.bytes,
+						ctxt->vcpu);
 			if (rc != 0)
 				goto done;
 		default:
@@ -1218,134 +1270,145 @@ writeback:
 	}
 
 	/* Commit shadow register state. */
-	memcpy(ctxt->vcpu->regs, _regs, sizeof _regs);
+	memcpy(ctxt->vcpu->regs, decode->regs, sizeof decode->regs);
 	ctxt->eflags = _eflags;
-	ctxt->vcpu->rip = _eip;
+	ctxt->vcpu->rip = decode->eip;
 
 done:
 	return (rc == X86EMUL_UNHANDLEABLE) ? -1 : 0;
 
 special_insn:
-	if (twobyte)
+	if (decode->twobyte)
 		goto twobyte_special_insn;
-	switch(b) {
+	switch (decode->b) {
 	case 0x50 ... 0x57:  /* push reg */
-		if (op_bytes == 2)
-			src.val = (u16) _regs[b & 0x7];
+		if (decode->op_bytes == 2)
+			decode->src.val = (u16) decode->regs[decode->b & 0x7];
 		else
-			src.val = (u32) _regs[b & 0x7];
-		dst.type  = OP_MEM;
-		dst.bytes = op_bytes;
-		dst.val = src.val;
-		register_address_increment(_regs[VCPU_REGS_RSP], -op_bytes);
-		dst.ptr = (void *) register_address(
-			ctxt->ss_base, _regs[VCPU_REGS_RSP]);
+			decode->src.val = (u32) decode->regs[decode->b & 0x7];
+		decode->dst.type  = OP_MEM;
+		decode->dst.bytes = decode->op_bytes;
+		decode->dst.val = decode->src.val;
+		register_address_increment(decode->regs[VCPU_REGS_RSP],
+					   -decode->op_bytes);
+		decode->dst.ptr = (void *) register_address(
+			ctxt->ss_base, decode->regs[VCPU_REGS_RSP]);
 		break;
 	case 0x58 ... 0x5f: /* pop reg */
-		dst.ptr = (unsigned long *)&_regs[b & 0x7];
+		decode->dst.ptr =
+				(unsigned long *)&decode->regs[decode->b & 0x7];
 	pop_instruction:
 		if ((rc = ops->read_std(register_address(ctxt->ss_base,
-			_regs[VCPU_REGS_RSP]), dst.ptr, op_bytes, ctxt->vcpu))
-			!= 0)
+			decode->regs[VCPU_REGS_RSP]), decode->dst.ptr,
+			decode->op_bytes, ctxt->vcpu)) != 0)
 			goto done;
 
-		register_address_increment(_regs[VCPU_REGS_RSP], op_bytes);
+		register_address_increment(decode->regs[VCPU_REGS_RSP],
+					   decode->op_bytes);
 		no_wb = 1; /* Disable writeback. */
 		break;
 	case 0x6c:		/* insb */
 	case 0x6d:		/* insw/insd */
 		 if (kvm_emulate_pio_string(ctxt->vcpu, NULL,
-				1, 					/* in */
-				(d & ByteOp) ? 1 : op_bytes, 		/* size */
-				rep_prefix ?
-				address_mask(_regs[VCPU_REGS_RCX]) : 1,	/* count */
-				(_eflags & EFLG_DF),			/* down */
+				1,
+				(decode->d & ByteOp) ? 1 : decode->op_bytes,
+				decode->rep_prefix ?
+				address_mask(decode->regs[VCPU_REGS_RCX]) : 1,
+				(_eflags & EFLG_DF),
 				register_address(ctxt->es_base,
-						 _regs[VCPU_REGS_RDI]),	/* address */
-				rep_prefix,
-				_regs[VCPU_REGS_RDX]			/* port */
-				) == 0)
+						 decode->regs[VCPU_REGS_RDI]),
+				decode->rep_prefix,
+				decode->regs[VCPU_REGS_RDX]) == 0)
 			return -1;
 		return 0;
 	case 0x6e:		/* outsb */
 	case 0x6f:		/* outsw/outsd */
 		if (kvm_emulate_pio_string(ctxt->vcpu, NULL,
-				0, 					/* in */
-				(d & ByteOp) ? 1 : op_bytes, 		/* size */
-				rep_prefix ?
-				address_mask(_regs[VCPU_REGS_RCX]) : 1,	/* count */
-				(_eflags & EFLG_DF),			/* down */
-				register_address(override_base ?
-						 *override_base : ctxt->ds_base,
-						 _regs[VCPU_REGS_RSI]),	/* address */
-				rep_prefix,
-				_regs[VCPU_REGS_RDX]			/* port */
-				) == 0)
+				0,
+				(decode->d & ByteOp) ? 1 : decode->op_bytes,
+				decode->rep_prefix ?
+				address_mask(decode->regs[VCPU_REGS_RCX]) : 1,
+				(_eflags & EFLG_DF),
+				register_address(decode->override_base ?
+							*decode->override_base :
+							ctxt->ds_base,
+						 decode->regs[VCPU_REGS_RSI]),
+				decode->rep_prefix,
+				decode->regs[VCPU_REGS_RDX]) == 0)
 			return -1;
 		return 0;
 	case 0x70 ... 0x7f: /* jcc (short) */ {
-		int rel = insn_fetch(s8, 1, _eip);
+		int rel = insn_fetch(s8, 1, decode->eip);
 
-		if (test_cc(b, _eflags))
+		if (test_cc(decode->b, _eflags))
 		JMP_REL(rel);
 		break;
 	}
 	case 0x9c: /* pushf */
-		src.val =  (unsigned long) _eflags;
+		decode->src.val =  (unsigned long) _eflags;
 		goto push;
 	case 0x9d: /* popf */
-		dst.ptr = (unsigned long *) &_eflags;
+		decode->dst.ptr = (unsigned long *) &_eflags;
 		goto pop_instruction;
 	case 0xc3: /* ret */
-		dst.ptr = &_eip;
+		decode->dst.ptr = &decode->eip;
 		goto pop_instruction;
 	case 0xf4:              /* hlt */
 		ctxt->vcpu->halt_request = 1;
 		goto done;
 	}
-	if (rep_prefix) {
-		if (_regs[VCPU_REGS_RCX] == 0) {
-			ctxt->vcpu->rip = _eip;
+	if (decode->rep_prefix) {
+		if (decode->regs[VCPU_REGS_RCX] == 0) {
+			ctxt->vcpu->rip = decode->eip;
 			goto done;
 		}
-		_regs[VCPU_REGS_RCX]--;
-		_eip = ctxt->vcpu->rip;
+		decode->regs[VCPU_REGS_RCX]--;
+		decode->eip = ctxt->vcpu->rip;
 	}
-	switch (b) {
+	switch (decode->b) {
 	case 0xa4 ... 0xa5:	/* movs */
-		dst.type = OP_MEM;
-		dst.bytes = (d & ByteOp) ? 1 : op_bytes;
-		dst.ptr = (unsigned long *)register_address(ctxt->es_base,
-							_regs[VCPU_REGS_RDI]);
+		decode->dst.type = OP_MEM;
+		decode->dst.bytes = (decode->d & ByteOp) ? 1 : decode->op_bytes;
+		decode->dst.ptr = (unsigned long *)register_address(
+						   ctxt->es_base,
+						   decode->regs[VCPU_REGS_RDI]);
 		if ((rc = ops->read_emulated(register_address(
-		      override_base ? *override_base : ctxt->ds_base,
-		      _regs[VCPU_REGS_RSI]), &dst.val, dst.bytes, ctxt->vcpu)) != 0)
+		      decode->override_base ? *decode->override_base :
+					ctxt->ds_base,
+					decode->regs[VCPU_REGS_RSI]),
+					&decode->dst.val,
+					decode->dst.bytes, ctxt->vcpu)) != 0)
 			goto done;
-		register_address_increment(_regs[VCPU_REGS_RSI],
-			     (_eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
-		register_address_increment(_regs[VCPU_REGS_RDI],
-			     (_eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
+		register_address_increment(decode->regs[VCPU_REGS_RSI],
+				       (_eflags & EFLG_DF) ? -decode->dst.bytes
+							   : decode->dst.bytes);
+		register_address_increment(decode->regs[VCPU_REGS_RDI],
+				       (_eflags & EFLG_DF) ? -decode->dst.bytes
+							   : decode->dst.bytes);
 		break;
 	case 0xa6 ... 0xa7:	/* cmps */
 		DPRINTF("Urk! I don't handle CMPS.\n");
 		goto cannot_emulate;
 	case 0xaa ... 0xab:	/* stos */
-		dst.type = OP_MEM;
-		dst.bytes = (d & ByteOp) ? 1 : op_bytes;
-		dst.ptr = (unsigned long *)cr2;
-		dst.val = _regs[VCPU_REGS_RAX];
-		register_address_increment(_regs[VCPU_REGS_RDI],
-			     (_eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
+		decode->dst.type = OP_MEM;
+		decode->dst.bytes = (decode->d & ByteOp) ? 1 : decode->op_bytes;
+		decode->dst.ptr = (unsigned long *)cr2;
+		decode->dst.val = decode->regs[VCPU_REGS_RAX];
+		register_address_increment(decode->regs[VCPU_REGS_RDI],
+				       (_eflags & EFLG_DF) ? -decode->dst.bytes
+							   : decode->dst.bytes);
 		break;
 	case 0xac ... 0xad:	/* lods */
-		dst.type = OP_REG;
-		dst.bytes = (d & ByteOp) ? 1 : op_bytes;
-		dst.ptr = (unsigned long *)&_regs[VCPU_REGS_RAX];
-		if ((rc = ops->read_emulated(cr2, &dst.val, dst.bytes,
+		decode->dst.type = OP_REG;
+		decode->dst.bytes = (decode->d & ByteOp) ? 1 : decode->op_bytes;
+		decode->dst.ptr = (unsigned long *)&decode->regs[VCPU_REGS_RAX];
+		if ((rc = ops->read_emulated(cr2, &decode->dst.val,
+					     decode->dst.bytes,
 					     ctxt->vcpu)) != 0)
 			goto done;
-		register_address_increment(_regs[VCPU_REGS_RSI],
-			   (_eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
+		register_address_increment(decode->regs[VCPU_REGS_RSI],
+				       (_eflags & EFLG_DF) ? -decode->dst.bytes
+							   : decode->dst.bytes);
 		break;
 	case 0xae ... 0xaf:	/* scas */
 		DPRINTF("Urk! I don't handle SCAS.\n");
@@ -1355,38 +1418,39 @@ special_insn:
 	goto writeback;
 
 twobyte_insn:
-	switch (b) {
+	switch (decode->b) {
 	case 0x01: /* lgdt, lidt, lmsw */
 		/* Disable writeback. */
 		no_wb = 1;
-		switch (modrm_reg) {
+		switch (decode->modrm_reg) {
 			u16 size;
 			unsigned long address;
 
 		case 2: /* lgdt */
-			rc = read_descriptor(ctxt, ops, src.ptr,
-					     &size, &address, op_bytes);
+			rc = read_descriptor(ctxt, ops, decode->src.ptr,
+					     &size, &address, decode->op_bytes);
 			if (rc)
 				goto done;
 			realmode_lgdt(ctxt->vcpu, size, address);
 			break;
 		case 3: /* lidt */
-			rc = read_descriptor(ctxt, ops, src.ptr,
-					     &size, &address, op_bytes);
+			rc = read_descriptor(ctxt, ops, decode->src.ptr,
+					     &size, &address, decode->op_bytes);
 			if (rc)
 				goto done;
 			realmode_lidt(ctxt->vcpu, size, address);
 			break;
 		case 4: /* smsw */
-			if (modrm_mod != 3)
+			if (decode->modrm_mod != 3)
 				goto cannot_emulate;
-			*(u16 *)&_regs[modrm_rm]
+			*(u16 *)&decode->regs[decode->modrm_rm]
 				= realmode_get_cr(ctxt->vcpu, 0);
 			break;
 		case 6: /* lmsw */
-			if (modrm_mod != 3)
+			if (decode->modrm_mod != 3)
 				goto cannot_emulate;
-			realmode_lmsw(ctxt->vcpu, (u16)modrm_val, &_eflags);
+			realmode_lmsw(ctxt->vcpu,
+				      (u16)decode->modrm_val, &_eflags);
 			break;
 		case 7: /* invlpg*/
 			emulate_invlpg(ctxt->vcpu, cr2);
@@ -1397,24 +1461,26 @@ twobyte_insn:
 		break;
 	case 0x21: /* mov from dr to reg */
 		no_wb = 1;
-		if (modrm_mod != 3)
+		if (decode->modrm_mod != 3)
 			goto cannot_emulate;
-		rc = emulator_get_dr(ctxt, modrm_reg, &_regs[modrm_rm]);
+		rc = emulator_get_dr(ctxt, decode->modrm_reg,
+				     &decode->regs[decode->modrm_rm]);
 		break;
 	case 0x23: /* mov from reg to dr */
 		no_wb = 1;
-		if (modrm_mod != 3)
+		if (decode->modrm_mod != 3)
 			goto cannot_emulate;
-		rc = emulator_set_dr(ctxt, modrm_reg, _regs[modrm_rm]);
+		rc = emulator_set_dr(ctxt, decode->modrm_reg,
+				     decode->regs[decode->modrm_rm]);
 		break;
 	case 0x40 ... 0x4f:	/* cmov */
-		dst.val = dst.orig_val = src.val;
+		decode->dst.val = decode->dst.orig_val = decode->src.val;
 		no_wb = 1;
 		/*
 		 * First, assume we're decoding an even cmov opcode
 		 * (lsb == 0).
 		 */
-		switch ((b & 15) >> 1) {
+		switch ((decode->b & 15) >> 1) {
 		case 0:	/* cmovo */
 			no_wb = (_eflags & EFLG_OF) ? 0 : 1;
 			break;
@@ -1442,46 +1508,54 @@ twobyte_insn:
 			break;
 		}
 		/* Odd cmov opcodes (lsb == 1) have inverted sense. */
-		no_wb ^= b & 1;
+		no_wb ^= decode->b & 1;
 		break;
 	case 0xa3:
 	      bt:		/* bt */
-		src.val &= (dst.bytes << 3) - 1; /* only subword offset */
-		emulate_2op_SrcV_nobyte("bt", src, dst, _eflags);
+		/* only subword offset */
+		decode->src.val &= (decode->dst.bytes << 3) - 1;
+		emulate_2op_SrcV_nobyte("bt",
+					decode->src, decode->dst, _eflags);
 		break;
 	case 0xab:
 	      bts:		/* bts */
-		src.val &= (dst.bytes << 3) - 1; /* only subword offset */
-		emulate_2op_SrcV_nobyte("bts", src, dst, _eflags);
+		/* only subword offset */
+		decode->src.val &= (decode->dst.bytes << 3) - 1;
+		emulate_2op_SrcV_nobyte("bts",
+					decode->src, decode->dst, _eflags);
 		break;
 	case 0xb0 ... 0xb1:	/* cmpxchg */
 		/*
 		 * Save real source value, then compare EAX against
 		 * destination.
 		 */
-		src.orig_val = src.val;
-		src.val = _regs[VCPU_REGS_RAX];
-		emulate_2op_SrcV("cmp", src, dst, _eflags);
+		decode->src.orig_val = decode->src.val;
+		decode->src.val = decode->regs[VCPU_REGS_RAX];
+		emulate_2op_SrcV("cmp", decode->src, decode->dst, _eflags);
 		if (_eflags & EFLG_ZF) {
 			/* Success: write back to memory. */
-			dst.val = src.orig_val;
+			decode->dst.val = decode->src.orig_val;
 		} else {
 			/* Failure: write the value we saw to EAX. */
-			dst.type = OP_REG;
-			dst.ptr = (unsigned long *)&_regs[VCPU_REGS_RAX];
+			decode->dst.type = OP_REG;
+			decode->dst.ptr =
+				  (unsigned long *)&decode->regs[VCPU_REGS_RAX];
 		}
 		break;
 	case 0xb3:
 	      btr:		/* btr */
-		src.val &= (dst.bytes << 3) - 1; /* only subword offset */
-		emulate_2op_SrcV_nobyte("btr", src, dst, _eflags);
+		/* only subword offset */
+		decode->src.val &= (decode->dst.bytes << 3) - 1;
+		emulate_2op_SrcV_nobyte("btr",
+					decode->src, decode->dst, _eflags);
 		break;
 	case 0xb6 ... 0xb7:	/* movzx */
-		dst.bytes = op_bytes;
-		dst.val = (d & ByteOp) ? (u8) src.val : (u16) src.val;
+		decode->dst.bytes = decode->op_bytes;
+		decode->dst.val = (decode->d & ByteOp) ? (u8) decode->src.val
+						       : (u16) decode->src.val;
 		break;
 	case 0xba:		/* Grp8 */
-		switch (modrm_reg & 3) {
+		switch (decode->modrm_reg & 3) {
 		case 0:
 			goto bt;
 		case 1:
@@ -1494,12 +1568,15 @@ twobyte_insn:
 		break;
 	case 0xbb:
 	      btc:		/* btc */
-		src.val &= (dst.bytes << 3) - 1; /* only subword offset */
-		emulate_2op_SrcV_nobyte("btc", src, dst, _eflags);
+		/* only subword offset */
+		decode->src.val &= (decode->dst.bytes << 3) - 1;
+		emulate_2op_SrcV_nobyte("btc",
+					decode->src, decode->dst, _eflags);
 		break;
 	case 0xbe ... 0xbf:	/* movsx */
-		dst.bytes = op_bytes;
-		dst.val = (d & ByteOp) ? (s8) src.val : (s16) src.val;
+		decode->dst.bytes = decode->op_bytes;
+		decode->dst.val = (decode->d & ByteOp) ? (s8) decode->src.val :
+							(s16) decode->src.val;
 		break;
 	}
 	goto writeback;
@@ -1507,7 +1584,7 @@ twobyte_insn:
 twobyte_special_insn:
 	/* Disable writeback. */
 	no_wb = 1;
-	switch (b) {
+	switch (decode->b) {
 	case 0x06:
 		emulate_clts(ctxt->vcpu);
 		break;
@@ -1517,56 +1594,60 @@ twobyte_special_insn:
 	case 0x18:		/* Grp16 (prefetch/nop) */
 		break;
 	case 0x20: /* mov cr, reg */
-		if (modrm_mod != 3)
+		if (decode->modrm_mod != 3)
 			goto cannot_emulate;
-		_regs[modrm_rm] = realmode_get_cr(ctxt->vcpu, modrm_reg);
+		decode->regs[decode->modrm_rm] =
+				realmode_get_cr(ctxt->vcpu, decode->modrm_reg);
 		break;
 	case 0x22: /* mov reg, cr */
-		if (modrm_mod != 3)
+		if (decode->modrm_mod != 3)
 			goto cannot_emulate;
-		realmode_set_cr(ctxt->vcpu, modrm_reg, modrm_val, &_eflags);
+		realmode_set_cr(ctxt->vcpu,
+				decode->modrm_reg, decode->modrm_val, &_eflags);
 		break;
 	case 0x30:
 		/* wrmsr */
-		msr_data = (u32)_regs[VCPU_REGS_RAX]
-			| ((u64)_regs[VCPU_REGS_RDX] << 32);
-		rc = kvm_set_msr(ctxt->vcpu, _regs[VCPU_REGS_RCX], msr_data);
+		msr_data = (u32)decode->regs[VCPU_REGS_RAX]
+			| ((u64)decode->regs[VCPU_REGS_RDX] << 32);
+		rc = kvm_set_msr(ctxt->vcpu,
+					decode->regs[VCPU_REGS_RCX], msr_data);
 		if (rc) {
 			kvm_x86_ops->inject_gp(ctxt->vcpu, 0);
-			_eip = ctxt->vcpu->rip;
+			decode->eip = ctxt->vcpu->rip;
 		}
 		rc = X86EMUL_CONTINUE;
 		break;
 	case 0x32:
 		/* rdmsr */
-		rc = kvm_get_msr(ctxt->vcpu, _regs[VCPU_REGS_RCX], &msr_data);
+		rc = kvm_get_msr(ctxt->vcpu,
+				 decode->regs[VCPU_REGS_RCX], &msr_data);
 		if (rc) {
 			kvm_x86_ops->inject_gp(ctxt->vcpu, 0);
-			_eip = ctxt->vcpu->rip;
+			decode->eip = ctxt->vcpu->rip;
 		} else {
-			_regs[VCPU_REGS_RAX] = (u32)msr_data;
-			_regs[VCPU_REGS_RDX] = msr_data >> 32;
+			decode->regs[VCPU_REGS_RAX] = (u32)msr_data;
+			decode->regs[VCPU_REGS_RDX] = msr_data >> 32;
 		}
 		rc = X86EMUL_CONTINUE;
 		break;
 	case 0x80 ... 0x8f: /* jnz rel, etc*/ {
 		long int rel;
 
-		switch (op_bytes) {
+		switch (decode->op_bytes) {
 		case 2:
-			rel = insn_fetch(s16, 2, _eip);
+			rel = insn_fetch(s16, 2, decode->eip);
 			break;
 		case 4:
-			rel = insn_fetch(s32, 4, _eip);
+			rel = insn_fetch(s32, 4, decode->eip);
 			break;
 		case 8:
-			rel = insn_fetch(s64, 8, _eip);
+			rel = insn_fetch(s64, 8, decode->eip);
 			break;
 		default:
 			DPRINTF("jnz: Invalid op_bytes\n");
 			goto cannot_emulate;
 		}
-		if (test_cc(b, _eflags))
+		if (test_cc(decode->b, _eflags))
 			JMP_REL(rel);
 		break;
 	}
@@ -1576,14 +1657,16 @@ twobyte_special_insn:
 			if ((rc = ops->read_emulated(cr2, &old, 8, ctxt->vcpu))
 									!= 0)
 				goto done;
-			if (((u32) (old >> 0) != (u32) _regs[VCPU_REGS_RAX]) ||
-			    ((u32) (old >> 32) != (u32) _regs[VCPU_REGS_RDX])) {
-				_regs[VCPU_REGS_RAX] = (u32) (old >> 0);
-				_regs[VCPU_REGS_RDX] = (u32) (old >> 32);
+			if (((u32) (old >> 0) !=
+					(u32) decode->regs[VCPU_REGS_RAX]) ||
+			    ((u32) (old >> 32) !=
+					(u32) decode->regs[VCPU_REGS_RDX])) {
+				decode->regs[VCPU_REGS_RAX] = (u32) (old >> 0);
+				decode->regs[VCPU_REGS_RDX] = (u32) (old >> 32);
 				_eflags &= ~EFLG_ZF;
 			} else {
-				new = ((u64)_regs[VCPU_REGS_RCX] << 32)
-					| (u32) _regs[VCPU_REGS_RBX];
+				new = ((u64)decode->regs[VCPU_REGS_RCX] << 32)
+					| (u32) decode->regs[VCPU_REGS_RBX];
 				if ((rc = ops->cmpxchg_emulated(cr2, &old,
 							  &new, 8, ctxt->vcpu)) != 0)
 					goto done;
@@ -1595,6 +1678,6 @@ twobyte_special_insn:
 	goto writeback;
 
 cannot_emulate:
-	DPRINTF("Cannot emulate %02x\n", b);
+	DPRINTF("Cannot emulate %02x\n", decode->b);
 	return -1;
 }
Index: kvm/drivers/kvm/x86_emulate.h
===================================================================
--- kvm.orig/drivers/kvm/x86_emulate.h	2007-09-18 10:01:56.000000000 +0200
+++ kvm/drivers/kvm/x86_emulate.h	2007-09-18 10:01:59.000000000 +0200
@@ -112,6 +112,36 @@ struct x86_emulate_ops {
 
 };
 
+/* Type, address-of, and value of an instruction's operand. */
+struct operand {
+	enum { OP_REG, OP_MEM, OP_IMM } type;
+	unsigned int bytes;
+	unsigned long val, orig_val, *ptr;
+};
+
+struct decode_cache {
+	u8 twobyte;
+	u8 b;
+	u8 lock_prefix;
+	u8 rep_prefix;
+	u8 op_bytes;
+	u8 ad_bytes;
+	struct operand src;
+	struct operand dst;
+	unsigned long *override_base;
+	unsigned int d;
+	unsigned long regs[NR_VCPU_REGS];
+	unsigned long eip;
+	/* modrm */
+	u8 modrm;
+	u8 modrm_mod;
+	u8 modrm_reg;
+	u8 modrm_rm;
+	u8 use_modrm_ea;
+	unsigned long modrm_ea;
+	unsigned long modrm_val;
+};
+
 struct x86_emulate_ctxt {
 	/* Register state before/after emulation. */
 	struct kvm_vcpu *vcpu;
@@ -129,6 +159,10 @@ struct x86_emulate_ctxt {
 	unsigned long ss_base;
 	unsigned long gs_base;
 	unsigned long fs_base;
+
+	/* decode cache */
+
+	struct decode_cache decode;
 };
 
 /* Execution mode, passed to the emulator. */

[-- Attachment #3: Type: text/plain, Size: 228 bytes --]

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

[-- Attachment #4: Type: text/plain, Size: 186 bytes --]

_______________________________________________
kvm-devel mailing list
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
https://lists.sourceforge.net/lists/listinfo/kvm-devel

                 reply	other threads:[~2007-09-18  9:27 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=46EF99ED.2010006@bull.net \
    --to=laurent.vivier-6ktuutfb/bm@public.gmane.org \
    --cc=kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.