Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 80703
b: refs/heads/master
c: 1c73ef6
h: refs/heads/master
i:
  80701: 8a7d00f
  80699: 4a52c0a
  80695: 5e30a60
  80687: e7e657e
  80671: 6a3152e
  80639: 4ec94cc
v: v3
  • Loading branch information
Avi Kivity committed Jan 30, 2008
1 parent ac1be61 commit 4dee9ca
Show file tree
Hide file tree
Showing 2 changed files with 178 additions and 161 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 3b6fff198c2ae3ca87ee8c9103d52ac9e8f40dd5
refs/heads/master: 1c73ef66502311d9aff7fed7d7f970288329c6cb
337 changes: 177 additions & 160 deletions trunk/drivers/kvm/x86_emulate.c
Original file line number Diff line number Diff line change
Expand Up @@ -548,14 +548,182 @@ static void decode_register_operand(struct operand *op,
op->orig_val = op->val;
}

static int decode_modrm(struct x86_emulate_ctxt *ctxt,
struct x86_emulate_ops *ops)
{
struct decode_cache *c = &ctxt->decode;
u8 sib;
int index_reg = 0, base_reg = 0, scale, rip_relative = 0;
int rc = 0;

if (c->rex_prefix) {
c->modrm_reg = (c->rex_prefix & 4) << 1; /* REX.R */
index_reg = (c->rex_prefix & 2) << 2; /* REX.X */
c->modrm_rm = base_reg = (c->rex_prefix & 1) << 3; /* REG.B */
}

c->modrm = insn_fetch(u8, 1, c->eip);
c->modrm_mod |= (c->modrm & 0xc0) >> 6;
c->modrm_reg |= (c->modrm & 0x38) >> 3;
c->modrm_rm |= (c->modrm & 0x07);
c->modrm_ea = 0;
c->use_modrm_ea = 1;

if (c->modrm_mod == 3) {
c->modrm_val = *(unsigned long *)
decode_register(c->modrm_rm, c->regs, c->d & ByteOp);
return rc;
}

if (c->ad_bytes == 2) {
unsigned bx = c->regs[VCPU_REGS_RBX];
unsigned bp = c->regs[VCPU_REGS_RBP];
unsigned si = c->regs[VCPU_REGS_RSI];
unsigned di = c->regs[VCPU_REGS_RDI];

/* 16-bit ModR/M decode. */
switch (c->modrm_mod) {
case 0:
if (c->modrm_rm == 6)
c->modrm_ea += insn_fetch(u16, 2, c->eip);
break;
case 1:
c->modrm_ea += insn_fetch(s8, 1, c->eip);
break;
case 2:
c->modrm_ea += insn_fetch(u16, 2, c->eip);
break;
}
switch (c->modrm_rm) {
case 0:
c->modrm_ea += bx + si;
break;
case 1:
c->modrm_ea += bx + di;
break;
case 2:
c->modrm_ea += bp + si;
break;
case 3:
c->modrm_ea += bp + di;
break;
case 4:
c->modrm_ea += si;
break;
case 5:
c->modrm_ea += di;
break;
case 6:
if (c->modrm_mod != 0)
c->modrm_ea += bp;
break;
case 7:
c->modrm_ea += bx;
break;
}
if (c->modrm_rm == 2 || c->modrm_rm == 3 ||
(c->modrm_rm == 6 && c->modrm_mod != 0))
if (!c->override_base)
c->override_base = &ctxt->ss_base;
c->modrm_ea = (u16)c->modrm_ea;
} else {
/* 32/64-bit ModR/M decode. */
switch (c->modrm_rm) {
case 4:
case 12:
sib = insn_fetch(u8, 1, c->eip);
index_reg |= (sib >> 3) & 7;
base_reg |= sib & 7;
scale = sib >> 6;

switch (base_reg) {
case 5:
if (c->modrm_mod != 0)
c->modrm_ea += c->regs[base_reg];
else
c->modrm_ea +=
insn_fetch(s32, 4, c->eip);
break;
default:
c->modrm_ea += c->regs[base_reg];
}
switch (index_reg) {
case 4:
break;
default:
c->modrm_ea += c->regs[index_reg] << scale;
}
break;
case 5:
if (c->modrm_mod != 0)
c->modrm_ea += c->regs[c->modrm_rm];
else if (ctxt->mode == X86EMUL_MODE_PROT64)
rip_relative = 1;
break;
default:
c->modrm_ea += c->regs[c->modrm_rm];
break;
}
switch (c->modrm_mod) {
case 0:
if (c->modrm_rm == 5)
c->modrm_ea += insn_fetch(s32, 4, c->eip);
break;
case 1:
c->modrm_ea += insn_fetch(s8, 1, c->eip);
break;
case 2:
c->modrm_ea += insn_fetch(s32, 4, c->eip);
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:
return rc;
}

static int decode_abs(struct x86_emulate_ctxt *ctxt,
struct x86_emulate_ops *ops)
{
struct decode_cache *c = &ctxt->decode;
int rc = 0;

switch (c->ad_bytes) {
case 2:
c->modrm_ea = insn_fetch(u16, 2, c->eip);
break;
case 4:
c->modrm_ea = insn_fetch(u32, 4, c->eip);
break;
case 8:
c->modrm_ea = insn_fetch(u64, 8, c->eip);
break;
}
done:
return rc;
}

int
x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
{
struct decode_cache *c = &ctxt->decode;
u8 sib;
int rc = 0;
int mode = ctxt->mode;
int index_reg = 0, base_reg = 0, scale, rip_relative = 0;

/* Shadow copy of register state. Committed on successful emulation. */

Expand Down Expand Up @@ -637,13 +805,9 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
done_prefixes:

/* REX prefix. */
if (c->rex_prefix) {
if (c->rex_prefix)
if (c->rex_prefix & 8)
c->op_bytes = 8; /* REX.W */
c->modrm_reg = (c->rex_prefix & 4) << 1; /* REX.R */
index_reg = (c->rex_prefix & 2) << 2; /* REX.X */
c->modrm_rm = base_reg = (c->rex_prefix & 1) << 3; /* REG.B */
}

/* Opcode byte(s). */
c->d = opcode_table[c->b];
Expand All @@ -663,159 +827,12 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
}

/* ModRM and SIB bytes. */
if (c->d & ModRM) {
c->modrm = insn_fetch(u8, 1, c->eip);
c->modrm_mod |= (c->modrm & 0xc0) >> 6;
c->modrm_reg |= (c->modrm & 0x38) >> 3;
c->modrm_rm |= (c->modrm & 0x07);
c->modrm_ea = 0;
c->use_modrm_ea = 1;

if (c->modrm_mod == 3) {
c->modrm_val = *(unsigned long *)
decode_register(c->modrm_rm, c->regs, c->d & ByteOp);
goto modrm_done;
}

if (c->ad_bytes == 2) {
unsigned bx = c->regs[VCPU_REGS_RBX];
unsigned bp = c->regs[VCPU_REGS_RBP];
unsigned si = c->regs[VCPU_REGS_RSI];
unsigned di = c->regs[VCPU_REGS_RDI];

/* 16-bit ModR/M decode. */
switch (c->modrm_mod) {
case 0:
if (c->modrm_rm == 6)
c->modrm_ea +=
insn_fetch(u16, 2, c->eip);
break;
case 1:
c->modrm_ea += insn_fetch(s8, 1, c->eip);
break;
case 2:
c->modrm_ea += insn_fetch(u16, 2, c->eip);
break;
}
switch (c->modrm_rm) {
case 0:
c->modrm_ea += bx + si;
break;
case 1:
c->modrm_ea += bx + di;
break;
case 2:
c->modrm_ea += bp + si;
break;
case 3:
c->modrm_ea += bp + di;
break;
case 4:
c->modrm_ea += si;
break;
case 5:
c->modrm_ea += di;
break;
case 6:
if (c->modrm_mod != 0)
c->modrm_ea += bp;
break;
case 7:
c->modrm_ea += bx;
break;
}
if (c->modrm_rm == 2 || c->modrm_rm == 3 ||
(c->modrm_rm == 6 && c->modrm_mod != 0))
if (!c->override_base)
c->override_base = &ctxt->ss_base;
c->modrm_ea = (u16)c->modrm_ea;
} else {
/* 32/64-bit ModR/M decode. */
switch (c->modrm_rm) {
case 4:
case 12:
sib = insn_fetch(u8, 1, c->eip);
index_reg |= (sib >> 3) & 7;
base_reg |= sib & 7;
scale = sib >> 6;

switch (base_reg) {
case 5:
if (c->modrm_mod != 0)
c->modrm_ea +=
c->regs[base_reg];
else
c->modrm_ea +=
insn_fetch(s32, 4, c->eip);
break;
default:
c->modrm_ea += c->regs[base_reg];
}
switch (index_reg) {
case 4:
break;
default:
c->modrm_ea +=
c->regs[index_reg] << scale;

}
break;
case 5:
if (c->modrm_mod != 0)
c->modrm_ea += c->regs[c->modrm_rm];
else if (mode == X86EMUL_MODE_PROT64)
rip_relative = 1;
break;
default:
c->modrm_ea += c->regs[c->modrm_rm];
break;
}
switch (c->modrm_mod) {
case 0:
if (c->modrm_rm == 5)
c->modrm_ea +=
insn_fetch(s32, 4, c->eip);
break;
case 1:
c->modrm_ea += insn_fetch(s8, 1, c->eip);
break;
case 2:
c->modrm_ea += insn_fetch(s32, 4, c->eip);
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;
}
}
modrm_done:
;
} else if (c->d & MemAbs) {
switch (c->ad_bytes) {
case 2:
c->modrm_ea = insn_fetch(u16, 2, c->eip);
break;
case 4:
c->modrm_ea = insn_fetch(u32, 4, c->eip);
break;
case 8:
c->modrm_ea = insn_fetch(u64, 8, c->eip);
break;
}

}
if (c->d & ModRM)
rc = decode_modrm(ctxt, ops);
else if (c->d & MemAbs)
rc = decode_abs(ctxt, ops);
if (rc)
goto done;

if (!c->override_base)
c->override_base = &ctxt->ds_base;
Expand Down

0 comments on commit 4dee9ca

Please sign in to comment.