From patchwork Wed Sep 28 08:08:53 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Beulich X-Patchwork-Id: 9353185 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 506BB6077A for ; Wed, 28 Sep 2016 08:11:08 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3FB1229186 for ; Wed, 28 Sep 2016 08:11:08 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2FA9F293EA; Wed, 28 Sep 2016 08:11:08 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 2CE4929186 for ; Wed, 28 Sep 2016 08:11:07 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bp9vI-00084k-F8; Wed, 28 Sep 2016 08:09:00 +0000 Received: from mail6.bemta6.messagelabs.com ([193.109.254.103]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bp9vH-00084S-8M for xen-devel@lists.xenproject.org; Wed, 28 Sep 2016 08:08:59 +0000 Received: from [193.109.254.147] by server-7.bemta-6.messagelabs.com id 90/2E-15404-A9A7BE75; Wed, 28 Sep 2016 08:08:58 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrJIsWRWlGSWpSXmKPExsXS6fjDS3dm1et wg7dnBC2+b5nM5MDocfjDFZYAxijWzLyk/IoE1oylH/oYC+7MYaxoPHCDpYFxWVkXIyeHkECe xIXbP5lBbF4BO4m375cwgtgSAoYST99fZwOxWQRUJaa/+MoEYrMJqEu0PdvO2sXIwSEiYCBx7 mgSiMksoC+xbR0LSIWwgJ/Ex/6rbBDT7SQev34DFucUsJf4eu0LWCevgKDE3x3CIGFmoJJ9TW 3MExh5ZiFkZiHJQNhaEg9/3WKBsLUlli18zTwLbK+0xPJ/HBBhW4muhlZ2VCUgtofE3M8/GRc wcqxi1ChOLSpLLdI1MtdLKspMzyjJTczM0TU0MNPLTS0uTkxPzUlMKtZLzs/dxAgMVgYg2MG4 eG3gIUZJDiYlUd7N4a/DhfiS8lMqMxKLM+KLSnNSiw8xanBwCGzbtfoCoxRLXn5eqpIEr0clU J1gUWp6akVaZg4wnmBKJTh4lER43UHSvMUFibnFmekQqVOMilLivLkgCQGQREZpHlwbLIYvMc pKCfMyAh0lxFOQWpSbWYIq/4pRnINRSZjXG2QKT2ZeCdz0V0CLmYAWLz3xAmRxSSJCSqqBMV2 8d10ko8MOCxGbULYZy03aD00RWf4g+sXquj08qap1G8NvnGq0TLyce6fU9vqEUmEP5zjReO9P HSs2qKuqc70/uPl0f1hkYo/Fjfee3eVKjmv33Jz8iCF9cb7Y+xo24xuXD+zu9pl+b836LxVJM d1O8VcCHD5Y/+O7+aE0VV8v/2/YtvmXlFiKMxINtZiLihMBW8pBzdwCAAA= X-Env-Sender: JBeulich@suse.com X-Msg-Ref: server-6.tower-27.messagelabs.com!1475050135!61968745!1 X-Originating-IP: [137.65.248.74] X-SpamReason: No, hits=0.0 required=7.0 tests= X-StarScan-Received: X-StarScan-Version: 8.84; banners=-,-,- X-VirusChecked: Checked Received: (qmail 45109 invoked from network); 28 Sep 2016 08:08:56 -0000 Received: from prv-mh.provo.novell.com (HELO prv-mh.provo.novell.com) (137.65.248.74) by server-6.tower-27.messagelabs.com with DHE-RSA-AES256-GCM-SHA384 encrypted SMTP; 28 Sep 2016 08:08:56 -0000 Received: from INET-PRV-MTA by prv-mh.provo.novell.com with Novell_GroupWise; Wed, 28 Sep 2016 02:08:54 -0600 Message-Id: <57EB96B50200007800113195@prv-mh.provo.novell.com> X-Mailer: Novell GroupWise Internet Agent 14.2.1 Date: Wed, 28 Sep 2016 02:08:53 -0600 From: "Jan Beulich" To: "xen-devel" References: <57EB94940200007800113179@prv-mh.provo.novell.com> In-Reply-To: <57EB94940200007800113179@prv-mh.provo.novell.com> Mime-Version: 1.0 Cc: Andrew Cooper Subject: [Xen-devel] [PATCH v2 04/16] x86emul: complete decoding of two-byte instructions X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP This way we can at least size (and e.g. skip) them if needed, and we also won't raise the wrong fault due to not having read all relevant bytes. This at once adds correct raising of #UD for the three "ud" flavors (Intel names only "ud2", but AMD names all three of them in their opcode maps), as that may make a difference to callers compared to getting back X86EMUL_UNHANDLEABLE. Note on opcodes 0FA6 and 0FA7: These are VIA's PadLock instructions, which have a ModRM like byte where only register forms are valid. I.e. we could also use SrcImmByte there, but ModRM is more likely to be correct for a hypothetical extension allowing non-register operations. Note on opcode 0FB8: I think we're safe to ignore the Itanium specific JMPE (which doesn't take a ModRM byte, but an immediate). Signed-off-by: Jan Beulich x86emul: complete decoding of two-byte instructions This way we can at least size (and e.g. skip) them if needed, and we also won't raise the wrong fault due to not having read all relevant bytes. This at once adds correct raising of #UD for the three "ud" flavors (Intel names only "ud2", but AMD names all three of them in their opcode maps), as that may make a difference to callers compared to getting back X86EMUL_UNHANDLEABLE. Note on opcodes 0FA6 and 0FA7: These are VIA's PadLock instructions, which have a ModRM like byte where only register forms are valid. I.e. we could also use SrcImmByte there, but ModRM is more likely to be correct for a hypothetical extension allowing non-register operations. Note on opcode 0FB8: I think we're safe to ignore the Itanium specific JMPE (which doesn't take a ModRM byte, but an immediate). Signed-off-by: Jan Beulich --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -182,11 +182,14 @@ static const opcode_desc_t opcode_table[ static const opcode_desc_t twobyte_table[256] = { /* 0x00 - 0x07 */ - SrcMem16|ModRM, ImplicitOps|ModRM, 0, 0, 0, ImplicitOps, ImplicitOps, 0, + SrcMem16|ModRM, ImplicitOps|ModRM, ModRM, ModRM, + 0, ImplicitOps, ImplicitOps, ImplicitOps, /* 0x08 - 0x0F */ - ImplicitOps, ImplicitOps, 0, 0, 0, ImplicitOps|ModRM, 0, 0, + ImplicitOps, ImplicitOps, 0, ImplicitOps, + 0, ImplicitOps|ModRM, ImplicitOps, ModRM|SrcImmByte, /* 0x10 - 0x17 */ - ImplicitOps|ModRM, ImplicitOps|ModRM, 0, 0, 0, 0, 0, 0, + ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, + ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, /* 0x18 - 0x1F */ ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, @@ -194,12 +197,13 @@ static const opcode_desc_t twobyte_table ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, 0, 0, 0, 0, /* 0x28 - 0x2F */ - ImplicitOps|ModRM, ImplicitOps|ModRM, 0, ImplicitOps|ModRM, 0, 0, 0, 0, + ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, + ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, /* 0x30 - 0x37 */ - ImplicitOps, ImplicitOps, ImplicitOps, 0, - ImplicitOps, ImplicitOps, 0, 0, + ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, + ImplicitOps, ImplicitOps, 0, ImplicitOps, /* 0x38 - 0x3F */ - DstReg|SrcMem|ModRM, 0, 0, 0, 0, 0, 0, 0, + DstReg|SrcMem|ModRM, 0, DstReg|SrcImmByte|ModRM, 0, 0, 0, 0, 0, /* 0x40 - 0x47 */ DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov, @@ -211,11 +215,15 @@ static const opcode_desc_t twobyte_table DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov, /* 0x50 - 0x5F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, + ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, /* 0x60 - 0x6F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps|ModRM, + ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, + ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ImplicitOps|ModRM, /* 0x70 - 0x7F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps|ModRM, + SrcImmByte|ModRM, SrcImmByte|ModRM, SrcImmByte|ModRM, SrcImmByte|ModRM, + ModRM, ModRM, ModRM, ImplicitOps, + ModRM, ModRM, 0, 0, ModRM, ModRM, ModRM, ImplicitOps|ModRM, /* 0x80 - 0x87 */ DstImplicit|SrcImm, DstImplicit|SrcImm, DstImplicit|SrcImm, DstImplicit|SrcImm, @@ -238,9 +246,9 @@ static const opcode_desc_t twobyte_table ByteOp|DstMem|SrcNone|ModRM|Mov, ByteOp|DstMem|SrcNone|ModRM|Mov, /* 0xA0 - 0xA7 */ ImplicitOps, ImplicitOps, ImplicitOps, DstBitBase|SrcReg|ModRM, - DstMem|SrcImmByte|ModRM, DstMem|SrcReg|ModRM, 0, 0, + DstMem|SrcImmByte|ModRM, DstMem|SrcReg|ModRM, ModRM, ModRM, /* 0xA8 - 0xAF */ - ImplicitOps, ImplicitOps, 0, DstBitBase|SrcReg|ModRM, + ImplicitOps, ImplicitOps, ImplicitOps, DstBitBase|SrcReg|ModRM, DstMem|SrcImmByte|ModRM, DstMem|SrcReg|ModRM, ImplicitOps|ModRM, DstReg|SrcMem|ModRM, /* 0xB0 - 0xB7 */ @@ -249,22 +257,26 @@ static const opcode_desc_t twobyte_table DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov, ByteOp|DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem16|ModRM|Mov, /* 0xB8 - 0xBF */ - 0, 0, DstBitBase|SrcImmByte|ModRM, DstBitBase|SrcReg|ModRM, + DstReg|SrcMem|ModRM, ModRM, + DstBitBase|SrcImmByte|ModRM, DstBitBase|SrcReg|ModRM, DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM, ByteOp|DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem16|ModRM|Mov, /* 0xC0 - 0xC7 */ ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM, - 0, DstMem|SrcReg|ModRM|Mov, - 0, 0, 0, ImplicitOps|ModRM, + SrcImmByte|ModRM, DstMem|SrcReg|ModRM|Mov, + SrcImmByte|ModRM, SrcImmByte|ModRM, SrcImmByte|ModRM, ImplicitOps|ModRM, /* 0xC8 - 0xCF */ ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, /* 0xD0 - 0xDF */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, + ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, /* 0xE0 - 0xEF */ - 0, 0, 0, 0, 0, 0, 0, ImplicitOps|ModRM, 0, 0, 0, 0, 0, 0, 0, 0, + ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ImplicitOps|ModRM, + ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, /* 0xF0 - 0xFF */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, + ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ModRM }; #define REX_PREFIX 0x40 @@ -1574,7 +1586,12 @@ int x86emul_unhandleable_rw( struct x86_emulate_state { unsigned int op_bytes, ad_bytes; - enum { ext_none, ext_0f, ext_0f38 } ext; + enum { + ext_none = vex_none, + ext_0f = vex_0f, + ext_0f38 = vex_0f38, + ext_0f3a = vex_0f3a, + } ext; uint8_t opcode; uint8_t modrm, modrm_mod, modrm_reg, modrm_rm; uint8_t rex_prefix; @@ -1651,6 +1668,34 @@ x86_decode_onebyte( } static int +x86_decode_twobyte( + struct x86_emulate_state *state, + struct x86_emulate_ctxt *ctxt, + const struct x86_emulate_ops *ops) +{ + int rc = X86EMUL_OKAY; + + switch ( state->opcode ) + { + case 0x78: + if ( vex.opcx ) + break; + switch ( vex.pfx ) + { + case vex_66: /* extrq $imm8, $imm8, xmm */ + case vex_f2: /* insertq $imm8, $imm8, xmm, xmm */ + imm1 = insn_fetch_type(uint8_t); + imm2 = insn_fetch_type(uint8_t); + break; + } + break; + } + + done: + return rc; +} + +static int x86_decode( struct x86_emulate_state *state, struct x86_emulate_ctxt *ctxt, @@ -1754,6 +1799,10 @@ x86_decode( b = insn_fetch_type(uint8_t); ext = ext_0f38; break; + case 0x3a: + b = insn_fetch_type(uint8_t); + ext = ext_0f3a; + break; } } } @@ -1809,10 +1858,22 @@ x86_decode( if ( mode_64bit() && !vex.r ) rex_prefix |= REX_R; - fail_if(vex.opcx != vex_0f); - ext = ext_0f; b = insn_fetch_type(uint8_t); - d = twobyte_table[b]; + switch ( ext = vex.opcx ) + { + case vex_0f: + d = twobyte_table[b]; + break; + case vex_0f38: + d = twobyte_table[0x38]; + break; + case vex_0f3a: + d = twobyte_table[0x3a]; + break; + default: + rc = X86EMUL_UNHANDLEABLE; + goto done; + } modrm = insn_fetch_type(uint8_t); modrm_mod = (modrm & 0xc0) >> 6; @@ -1870,9 +1931,12 @@ x86_decode( break; case ext_0f: + case ext_0f3a: break; case ext_0f38: + if ( vex.opcx ) + break; switch ( b ) { case 0xf0: /* movbe / crc32 */ @@ -2052,7 +2116,11 @@ x86_decode( break; case ext_0f: + rc = x86_decode_twobyte(state, ctxt, ops); + break; + case ext_0f38: + case ext_0f3a: break; default: @@ -2268,6 +2336,7 @@ x86_emulate( goto ext_0f38_insn; default: ASSERT_UNREACHABLE(); + case ext_0f3a: goto cannot_emulate; } @@ -4211,6 +4280,11 @@ x86_emulate( goto done; break; + case 0x0b: /* ud2 */ + case 0xb9: /* ud1 */ + case 0xff: /* ud0 */ + generate_exception_if(1, EXC_UD, -1); + case 0x0d: /* GrpP (prefetch) */ case 0x18: /* Grp16 (prefetch/nop) */ case 0x19 ... 0x1f: /* nop (amd-defined) */ --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -182,11 +182,14 @@ static const opcode_desc_t opcode_table[ static const opcode_desc_t twobyte_table[256] = { /* 0x00 - 0x07 */ - SrcMem16|ModRM, ImplicitOps|ModRM, 0, 0, 0, ImplicitOps, ImplicitOps, 0, + SrcMem16|ModRM, ImplicitOps|ModRM, ModRM, ModRM, + 0, ImplicitOps, ImplicitOps, ImplicitOps, /* 0x08 - 0x0F */ - ImplicitOps, ImplicitOps, 0, 0, 0, ImplicitOps|ModRM, 0, 0, + ImplicitOps, ImplicitOps, 0, ImplicitOps, + 0, ImplicitOps|ModRM, ImplicitOps, ModRM|SrcImmByte, /* 0x10 - 0x17 */ - ImplicitOps|ModRM, ImplicitOps|ModRM, 0, 0, 0, 0, 0, 0, + ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, + ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, /* 0x18 - 0x1F */ ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, @@ -194,12 +197,13 @@ static const opcode_desc_t twobyte_table ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, 0, 0, 0, 0, /* 0x28 - 0x2F */ - ImplicitOps|ModRM, ImplicitOps|ModRM, 0, ImplicitOps|ModRM, 0, 0, 0, 0, + ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, + ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, /* 0x30 - 0x37 */ - ImplicitOps, ImplicitOps, ImplicitOps, 0, - ImplicitOps, ImplicitOps, 0, 0, + ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, + ImplicitOps, ImplicitOps, 0, ImplicitOps, /* 0x38 - 0x3F */ - DstReg|SrcMem|ModRM, 0, 0, 0, 0, 0, 0, 0, + DstReg|SrcMem|ModRM, 0, DstReg|SrcImmByte|ModRM, 0, 0, 0, 0, 0, /* 0x40 - 0x47 */ DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov, @@ -211,11 +215,15 @@ static const opcode_desc_t twobyte_table DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov, /* 0x50 - 0x5F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, + ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, /* 0x60 - 0x6F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps|ModRM, + ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, + ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ImplicitOps|ModRM, /* 0x70 - 0x7F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps|ModRM, + SrcImmByte|ModRM, SrcImmByte|ModRM, SrcImmByte|ModRM, SrcImmByte|ModRM, + ModRM, ModRM, ModRM, ImplicitOps, + ModRM, ModRM, 0, 0, ModRM, ModRM, ModRM, ImplicitOps|ModRM, /* 0x80 - 0x87 */ DstImplicit|SrcImm, DstImplicit|SrcImm, DstImplicit|SrcImm, DstImplicit|SrcImm, @@ -238,9 +246,9 @@ static const opcode_desc_t twobyte_table ByteOp|DstMem|SrcNone|ModRM|Mov, ByteOp|DstMem|SrcNone|ModRM|Mov, /* 0xA0 - 0xA7 */ ImplicitOps, ImplicitOps, ImplicitOps, DstBitBase|SrcReg|ModRM, - DstMem|SrcImmByte|ModRM, DstMem|SrcReg|ModRM, 0, 0, + DstMem|SrcImmByte|ModRM, DstMem|SrcReg|ModRM, ModRM, ModRM, /* 0xA8 - 0xAF */ - ImplicitOps, ImplicitOps, 0, DstBitBase|SrcReg|ModRM, + ImplicitOps, ImplicitOps, ImplicitOps, DstBitBase|SrcReg|ModRM, DstMem|SrcImmByte|ModRM, DstMem|SrcReg|ModRM, ImplicitOps|ModRM, DstReg|SrcMem|ModRM, /* 0xB0 - 0xB7 */ @@ -249,22 +257,26 @@ static const opcode_desc_t twobyte_table DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov, ByteOp|DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem16|ModRM|Mov, /* 0xB8 - 0xBF */ - 0, 0, DstBitBase|SrcImmByte|ModRM, DstBitBase|SrcReg|ModRM, + DstReg|SrcMem|ModRM, ModRM, + DstBitBase|SrcImmByte|ModRM, DstBitBase|SrcReg|ModRM, DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM, ByteOp|DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem16|ModRM|Mov, /* 0xC0 - 0xC7 */ ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM, - 0, DstMem|SrcReg|ModRM|Mov, - 0, 0, 0, ImplicitOps|ModRM, + SrcImmByte|ModRM, DstMem|SrcReg|ModRM|Mov, + SrcImmByte|ModRM, SrcImmByte|ModRM, SrcImmByte|ModRM, ImplicitOps|ModRM, /* 0xC8 - 0xCF */ ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, /* 0xD0 - 0xDF */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, + ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, /* 0xE0 - 0xEF */ - 0, 0, 0, 0, 0, 0, 0, ImplicitOps|ModRM, 0, 0, 0, 0, 0, 0, 0, 0, + ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ImplicitOps|ModRM, + ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, /* 0xF0 - 0xFF */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, + ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ModRM, ModRM }; #define REX_PREFIX 0x40 @@ -1574,7 +1586,12 @@ int x86emul_unhandleable_rw( struct x86_emulate_state { unsigned int op_bytes, ad_bytes; - enum { ext_none, ext_0f, ext_0f38 } ext; + enum { + ext_none = vex_none, + ext_0f = vex_0f, + ext_0f38 = vex_0f38, + ext_0f3a = vex_0f3a, + } ext; uint8_t opcode; uint8_t modrm, modrm_mod, modrm_reg, modrm_rm; uint8_t rex_prefix; @@ -1651,6 +1668,34 @@ x86_decode_onebyte( } static int +x86_decode_twobyte( + struct x86_emulate_state *state, + struct x86_emulate_ctxt *ctxt, + const struct x86_emulate_ops *ops) +{ + int rc = X86EMUL_OKAY; + + switch ( state->opcode ) + { + case 0x78: + if ( vex.opcx ) + break; + switch ( vex.pfx ) + { + case vex_66: /* extrq $imm8, $imm8, xmm */ + case vex_f2: /* insertq $imm8, $imm8, xmm, xmm */ + imm1 = insn_fetch_type(uint8_t); + imm2 = insn_fetch_type(uint8_t); + break; + } + break; + } + + done: + return rc; +} + +static int x86_decode( struct x86_emulate_state *state, struct x86_emulate_ctxt *ctxt, @@ -1754,6 +1799,10 @@ x86_decode( b = insn_fetch_type(uint8_t); ext = ext_0f38; break; + case 0x3a: + b = insn_fetch_type(uint8_t); + ext = ext_0f3a; + break; } } } @@ -1809,10 +1858,22 @@ x86_decode( if ( mode_64bit() && !vex.r ) rex_prefix |= REX_R; - fail_if(vex.opcx != vex_0f); - ext = ext_0f; b = insn_fetch_type(uint8_t); - d = twobyte_table[b]; + switch ( ext = vex.opcx ) + { + case vex_0f: + d = twobyte_table[b]; + break; + case vex_0f38: + d = twobyte_table[0x38]; + break; + case vex_0f3a: + d = twobyte_table[0x3a]; + break; + default: + rc = X86EMUL_UNHANDLEABLE; + goto done; + } modrm = insn_fetch_type(uint8_t); modrm_mod = (modrm & 0xc0) >> 6; @@ -1870,9 +1931,12 @@ x86_decode( break; case ext_0f: + case ext_0f3a: break; case ext_0f38: + if ( vex.opcx ) + break; switch ( b ) { case 0xf0: /* movbe / crc32 */ @@ -2052,7 +2116,11 @@ x86_decode( break; case ext_0f: + rc = x86_decode_twobyte(state, ctxt, ops); + break; + case ext_0f38: + case ext_0f3a: break; default: @@ -2268,6 +2336,7 @@ x86_emulate( goto ext_0f38_insn; default: ASSERT_UNREACHABLE(); + case ext_0f3a: goto cannot_emulate; } @@ -4211,6 +4280,11 @@ x86_emulate( goto done; break; + case 0x0b: /* ud2 */ + case 0xb9: /* ud1 */ + case 0xff: /* ud0 */ + generate_exception_if(1, EXC_UD, -1); + case 0x0d: /* GrpP (prefetch) */ case 0x18: /* Grp16 (prefetch/nop) */ case 0x19 ... 0x1f: /* nop (amd-defined) */