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

Commit f5b4edcd authored by Avi Kivity's avatar Avi Kivity
Browse files

KVM: x86 emulator: simplify rip relative decoding



rip relative decoding is relative to the instruction pointer of the next
instruction; by moving address adjustment until after decoding is complete,
we remove the need to determine the instruction size.

Signed-off-by: default avatarAvi Kivity <avi@qumranet.com>
parent 84411d85
Loading
Loading
Loading
Loading
+5 −18
Original line number Original line Diff line number Diff line
@@ -664,7 +664,7 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt,
{
{
	struct decode_cache *c = &ctxt->decode;
	struct decode_cache *c = &ctxt->decode;
	u8 sib;
	u8 sib;
	int index_reg = 0, base_reg = 0, scale, rip_relative = 0;
	int index_reg = 0, base_reg = 0, scale;
	int rc = 0;
	int rc = 0;


	if (c->rex_prefix) {
	if (c->rex_prefix) {
@@ -754,7 +754,7 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt,
				c->modrm_ea += c->regs[index_reg] << scale;
				c->modrm_ea += c->regs[index_reg] << scale;
		} else if ((c->modrm_rm & 7) == 5 && c->modrm_mod == 0) {
		} else if ((c->modrm_rm & 7) == 5 && c->modrm_mod == 0) {
			if (ctxt->mode == X86EMUL_MODE_PROT64)
			if (ctxt->mode == X86EMUL_MODE_PROT64)
				rip_relative = 1;
				c->rip_relative = 1;
		} else
		} else
			c->modrm_ea += c->regs[c->modrm_rm];
			c->modrm_ea += c->regs[c->modrm_rm];
		switch (c->modrm_mod) {
		switch (c->modrm_mod) {
@@ -770,22 +770,6 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt,
			break;
			break;
		}
		}
	}
	}
	if (rip_relative) {
		c->modrm_ea += c->eip;
		switch (c->d & SrcMask) {
		case SrcImmByte:
			c->modrm_ea += 1;
			break;
		case SrcImm:
			if (c->d & ByteOp)
				c->modrm_ea += 1;
			else
				if (c->op_bytes == 8)
					c->modrm_ea += 4;
				else
					c->modrm_ea += c->op_bytes;
		}
	}
done:
done:
	return rc;
	return rc;
}
}
@@ -1044,6 +1028,9 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
		break;
		break;
	}
	}


	if (c->rip_relative)
		c->modrm_ea += c->eip;

done:
done:
	return (rc == X86EMUL_UNHANDLEABLE) ? -1 : 0;
	return (rc == X86EMUL_UNHANDLEABLE) ? -1 : 0;
}
}
+1 −0
Original line number Original line Diff line number Diff line
@@ -134,6 +134,7 @@ struct decode_cache {
	u8 modrm_reg;
	u8 modrm_reg;
	u8 modrm_rm;
	u8 modrm_rm;
	u8 use_modrm_ea;
	u8 use_modrm_ea;
	bool rip_relative;
	unsigned long modrm_ea;
	unsigned long modrm_ea;
	void *modrm_ptr;
	void *modrm_ptr;
	unsigned long modrm_val;
	unsigned long modrm_val;