diff options
author | Borislav Petkov <bp@suse.de> | 2013-10-29 12:54:10 +0100 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2013-10-30 18:54:41 +0100 |
commit | 0bc5eedb82a54ccd9cbf79825226dd068427a94a (patch) | |
tree | 82462a3c8c6e7a6d865e3ca33d6ed8cfa7ec4aa8 /arch/x86/kvm | |
parent | b51e974fcdabd00c8f5943ee7943c4ea788f57b6 (diff) |
kvm, emulator: Add initial three-byte insns support
Add initial support for handling three-byte instructions in the
emulator.
Signed-off-by: Borislav Petkov <bp@suse.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'arch/x86/kvm')
-rw-r--r-- | arch/x86/kvm/emulate.c | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 54180152722..6c5cfe962b2 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -3892,6 +3892,25 @@ static const struct opcode twobyte_table[256] = { N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N }; +static const struct gprefix three_byte_0f_38_f0 = { + N, N, N, N +}; + +static const struct gprefix three_byte_0f_38_f1 = { + N, N, N, N +}; + +/* + * Insns below are selected by the prefix which indexed by the third opcode + * byte. + */ +static const struct opcode opcode_map_0f_38[256] = { + /* 0x00 - 0x7f */ + X16(N), X16(N), X16(N), X16(N), X16(N), X16(N), X16(N), X16(N), + /* 0x80 - 0xff */ + X16(N), X16(N), X16(N), X16(N), X16(N), X16(N), X16(N), X16(N) +}; + #undef D #undef N #undef G @@ -4212,6 +4231,13 @@ done_prefixes: ctxt->opcode_len = 2; ctxt->b = insn_fetch(u8, ctxt); opcode = twobyte_table[ctxt->b]; + + /* 0F_38 opcode map */ + if (ctxt->b == 0x38) { + ctxt->opcode_len = 3; + ctxt->b = insn_fetch(u8, ctxt); + opcode = opcode_map_0f_38[ctxt->b]; + } } ctxt->d = opcode.flags; @@ -4543,6 +4569,8 @@ special_insn: if (ctxt->opcode_len == 2) goto twobyte_insn; + else if (ctxt->opcode_len == 3) + goto threebyte_insn; switch (ctxt->b) { case 0x63: /* movsxd */ @@ -4727,6 +4755,8 @@ twobyte_insn: goto cannot_emulate; } +threebyte_insn: + if (rc != X86EMUL_CONTINUE) goto done; |