From patchwork Thu Dec 8 11:35:30 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Beulich X-Patchwork-Id: 9466175 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 E6E45607D3 for ; Thu, 8 Dec 2016 11:38:04 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E1FE728448 for ; Thu, 8 Dec 2016 11:38:04 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D69A9284ED; Thu, 8 Dec 2016 11:38:04 +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 BFBC828448 for ; Thu, 8 Dec 2016 11:38:03 +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 1cEwz9-0001i3-H7; Thu, 08 Dec 2016 11:35:35 +0000 Received: from mail6.bemta5.messagelabs.com ([195.245.231.135]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cEwz8-0001hx-KL for xen-devel@lists.xenproject.org; Thu, 08 Dec 2016 11:35:34 +0000 Received: from [85.158.139.211] by server-3.bemta-5.messagelabs.com id BA/58-01948-58549485; Thu, 08 Dec 2016 11:35:33 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFtrDIsWRWlGSWpSXmKPExsXS6fjDS7fF1TP CYOcqY4vvWyYzOTB6HP5whSWAMYo1My8pvyKBNWPGsfKCvmmMFfMaZrI2MK5N7mLk5BASyJOY sb6XBcTmFbCT2D+/gxHElhAwlHj6/jobiM0ioCpxYOU0VhCbTUBdou3ZdiCbg0NEwEDi3NEkE JNZQF9i2zqwKcICrhJbbvQzQUy3k1j2YhtYnFPAXmL/h4dsIOW8AoISf3cIg4SZgUpaD7xgnM DIMwshMwtJBsLWknj46xYLhK0tsWzha+ZZYHulJZb/44AIW0n07e1nRVUCYrtKdM6dyrSAkWM Vo0ZxalFZapGukbleUlFmekZJbmJmjq6hgalebmpxcWJ6ak5iUrFecn7uJkZgqNYzMDDuYLy6 xe8QoyQHk5Io764J7hFCfEn5KZUZicUZ8UWlOanFhxhlODiUJHh1XTwjhASLUtNTK9Iyc4BRA 5OW4OBREuF1dQJK8xYXJOYWZ6ZDpE4xKkqJ8yqD9AmAJDJK8+DaYJF6iVFWSpiXkYGBQYinIL UoN7MEVf4VozgHo5Iwrx7IFJ7MvBK46a+AFjMBLZ53wx1kcUkiQkqqgTHnrsWVPZO+strbF+1 mddyges1h34rCsIeyWnzZPpo1/CfEJxZe73RasvbDqVmsZbKqBakW32I7A/wn3nrQxC9znllR 9MzxmKn2T0+tdVJrOaXGqSrpzBL2Yl2zldn2x4/WzLS68G7OBbuv7KlTl2z+FfRlf1eRUqDuz fYAm89Oq1qlGm5wPldiKc5INNRiLipOBAB7Vl7+zwIAAA== X-Env-Sender: JBeulich@suse.com X-Msg-Ref: server-11.tower-206.messagelabs.com!1481196928!62268084!1 X-Originating-IP: [137.65.248.74] X-SpamReason: No, hits=0.5 required=7.0 tests=BODY_RANDOM_LONG X-StarScan-Received: X-StarScan-Version: 9.0.16; banners=-,-,- X-VirusChecked: Checked Received: (qmail 50279 invoked from network); 8 Dec 2016 11:35:30 -0000 Received: from prv-mh.provo.novell.com (HELO prv-mh.provo.novell.com) (137.65.248.74) by server-11.tower-206.messagelabs.com with DHE-RSA-AES256-GCM-SHA384 encrypted SMTP; 8 Dec 2016 11:35:30 -0000 Received: from INET-PRV-MTA by prv-mh.provo.novell.com with Novell_GroupWise; Thu, 08 Dec 2016 04:35:30 -0700 Message-Id: <584953920200007800126A95@prv-mh.provo.novell.com> X-Mailer: Novell GroupWise Internet Agent 14.2.1 Date: Thu, 08 Dec 2016 04:35:30 -0700 From: "Jan Beulich" To: "xen-devel" References: <584951630200007800126A86@prv-mh.provo.novell.com> In-Reply-To: <584951630200007800126A86@prv-mh.provo.novell.com> Mime-Version: 1.0 Cc: Andrew Cooper Subject: [Xen-devel] [PATCH v2 1/6] x86emul: extend / amend supported FPU opcodes 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 First of all there are a number of secondary encodings both Intel and AMD support, but which aren't formally documented. See e.g. www.sandpile.org/x86/opc_fpu.htm for inofficial documentation. Next there are a few more no-ops - instructions which served a purpose only on 8087 or 287. Further switch from fail_if() to raising of #UD in a couple of places (as the decoding of FPU opcodes should now be complete except where explicitly marked as todo). Also adjust a few comments. Signed-off-by: Jan Beulich Reviewed-by: Andrew Cooper --- v2: Correct placement of ffreep case. Use generate_exception(...) in favor of generate_exception_if(true, ...). Add sandpile.org reference. x86emul: extend / amend supported FPU opcodes First of all there are a number of secondary encodings both Intel and AMD support, but which aren't formally documented. See e.g. www.sandpile.org/x86/opc_fpu.htm for inofficial documentation. Next there are a few more no-ops - instructions which served a purpose only on 8087 or 287. Further switch from fail_if() to raising of #UD in a couple of places (as the decoding of FPU opcodes should now be complete except where explicitly marked as todo). Also adjust a few comments. Signed-off-by: Jan Beulich --- v2: Correct placement of ffreep case. Use generate_exception(...) in favor of generate_exception_if(true, ...). Add sandpile.org reference. --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -3577,18 +3577,18 @@ x86_emulate( host_and_vcpu_must_have(fpu); switch ( modrm ) { - case 0xc0 ... 0xc7: /* fadd %stN,%stN */ - case 0xc8 ... 0xcf: /* fmul %stN,%stN */ - case 0xd0 ... 0xd7: /* fcom %stN,%stN */ - case 0xd8 ... 0xdf: /* fcomp %stN,%stN */ - case 0xe0 ... 0xe7: /* fsub %stN,%stN */ - case 0xe8 ... 0xef: /* fsubr %stN,%stN */ - case 0xf0 ... 0xf7: /* fdiv %stN,%stN */ - case 0xf8 ... 0xff: /* fdivr %stN,%stN */ + case 0xc0 ... 0xc7: /* fadd %stN,%st */ + case 0xc8 ... 0xcf: /* fmul %stN,%st */ + case 0xd0 ... 0xd7: /* fcom %stN,%st */ + case 0xd8 ... 0xdf: /* fcomp %stN,%st */ + case 0xe0 ... 0xe7: /* fsub %stN,%st */ + case 0xe8 ... 0xef: /* fsubr %stN,%st */ + case 0xf0 ... 0xf7: /* fdiv %stN,%st */ + case 0xf8 ... 0xff: /* fdivr %stN,%st */ emulate_fpu_insn_stub(0xd8, modrm); break; default: - fail_if(modrm >= 0xc0); + ASSERT(ea.type == OP_MEM); ea.bytes = 4; src = ea; if ( (rc = ops->read(src.mem.seg, src.mem.off, &src.val, @@ -3634,6 +3634,7 @@ x86_emulate( case 0xc0 ... 0xc7: /* fld %stN */ case 0xc8 ... 0xcf: /* fxch %stN */ case 0xd0: /* fnop */ + case 0xd8 ... 0xdf: /* fstp %stN (alternative encoding) */ case 0xe0: /* fchs */ case 0xe1: /* fabs */ case 0xe4: /* ftst */ @@ -3663,7 +3664,7 @@ x86_emulate( emulate_fpu_insn_stub(0xd9, modrm); break; default: - fail_if(modrm >= 0xc0); + generate_exception_if(ea.type != OP_MEM, EXC_UD); switch ( modrm_reg & 7 ) { case 0: /* fld m32fp */ @@ -3686,7 +3687,8 @@ x86_emulate( dst.type = OP_MEM; emulate_fpu_insn_memdst("fstps", dst.val); break; - /* case 4: fldenv - TODO */ + case 4: /* fldenv - TODO */ + goto cannot_emulate; case 5: /* fldcw m2byte */ ea.bytes = 2; src = ea; @@ -3695,7 +3697,8 @@ x86_emulate( goto done; emulate_fpu_insn_memsrc("fldcw", src.val); break; - /* case 6: fstenv - TODO */ + case 6: /* fnstenv - TODO */ + goto cannot_emulate; case 7: /* fnstcw m2byte */ ea.bytes = 2; dst = ea; @@ -3703,7 +3706,7 @@ x86_emulate( emulate_fpu_insn_memdst("fnstcw", dst.val); break; default: - goto cannot_emulate; + generate_exception(EXC_UD); } } break; @@ -3723,7 +3726,7 @@ x86_emulate( emulate_fpu_insn_stub(0xda, modrm); break; default: - fail_if(modrm >= 0xc0); + generate_exception_if(ea.type != OP_MEM, EXC_UD); ea.bytes = 4; src = ea; if ( (rc = ops->read(src.mem.seg, src.mem.off, &src.val, @@ -3772,16 +3775,16 @@ x86_emulate( vcpu_must_have_cmov(); emulate_fpu_insn_stub_eflags(0xdb, modrm); break; + case 0xe0: /* fneni - 8087 only, ignored by 287 */ + case 0xe1: /* fndisi - 8087 only, ignored by 287 */ case 0xe2: /* fnclex */ - emulate_fpu_insn("fnclex"); - break; case 0xe3: /* fninit */ - emulate_fpu_insn("fninit"); - break; - case 0xe4: /* fsetpm - 287 only, ignored by 387 */ + case 0xe4: /* fnsetpm - 287 only, ignored by 387 */ + /* case 0xe5: frstpm - 287 only, #UD on 387 */ + emulate_fpu_insn_stub(0xdb, modrm); break; default: - fail_if(modrm >= 0xc0); + generate_exception_if(ea.type != OP_MEM, EXC_UD); switch ( modrm_reg & 7 ) { case 0: /* fild m32i */ @@ -3826,7 +3829,7 @@ x86_emulate( emulate_fpu_insn_memdst("fstpt", dst.val); break; default: - goto cannot_emulate; + generate_exception(EXC_UD); } } break; @@ -3835,16 +3838,18 @@ x86_emulate( host_and_vcpu_must_have(fpu); switch ( modrm ) { - case 0xc0 ... 0xc7: /* fadd %stN */ - case 0xc8 ... 0xcf: /* fmul %stN */ - case 0xe0 ... 0xe7: /* fsubr %stN */ - case 0xe8 ... 0xef: /* fsub %stN */ - case 0xf0 ... 0xf7: /* fdivr %stN */ - case 0xf8 ... 0xff: /* fdiv %stN */ + case 0xc0 ... 0xc7: /* fadd %st,%stN */ + case 0xc8 ... 0xcf: /* fmul %st,%stN */ + case 0xd0 ... 0xd7: /* fcom %stN,%st (alternative encoding) */ + case 0xd8 ... 0xdf: /* fcomp %stN,%st (alternative encoding) */ + case 0xe0 ... 0xe7: /* fsubr %st,%stN */ + case 0xe8 ... 0xef: /* fsub %st,%stN */ + case 0xf0 ... 0xf7: /* fdivr %st,%stN */ + case 0xf8 ... 0xff: /* fdiv %st,%stN */ emulate_fpu_insn_stub(0xdc, modrm); break; default: - fail_if(modrm >= 0xc0); + ASSERT(ea.type == OP_MEM); ea.bytes = 8; src = ea; if ( (rc = ops->read(src.mem.seg, src.mem.off, &src.val, @@ -3885,6 +3890,7 @@ x86_emulate( switch ( modrm ) { case 0xc0 ... 0xc7: /* ffree %stN */ + case 0xc8 ... 0xcf: /* fxch %stN (alternative encoding) */ case 0xd0 ... 0xd7: /* fst %stN */ case 0xd8 ... 0xdf: /* fstp %stN */ case 0xe0 ... 0xe7: /* fucom %stN */ @@ -3892,7 +3898,7 @@ x86_emulate( emulate_fpu_insn_stub(0xdd, modrm); break; default: - fail_if(modrm >= 0xc0); + generate_exception_if(ea.type != OP_MEM, EXC_UD); switch ( modrm_reg & 7 ) { case 0: /* fld m64fp */; @@ -3922,6 +3928,9 @@ x86_emulate( dst.type = OP_MEM; emulate_fpu_insn_memdst("fstpl", dst.val); break; + case 4: /* frstor - TODO */ + case 6: /* fnsave - TODO */ + goto cannot_emulate; case 7: /* fnstsw m2byte */ ea.bytes = 2; dst = ea; @@ -3929,7 +3938,7 @@ x86_emulate( emulate_fpu_insn_memdst("fnstsw", dst.val); break; default: - goto cannot_emulate; + generate_exception(EXC_UD); } } break; @@ -3940,6 +3949,7 @@ x86_emulate( { case 0xc0 ... 0xc7: /* faddp %stN */ case 0xc8 ... 0xcf: /* fmulp %stN */ + case 0xd0 ... 0xd7: /* fcomp %stN (alternative encoding) */ case 0xd9: /* fcompp */ case 0xe0 ... 0xe7: /* fsubrp %stN */ case 0xe8 ... 0xef: /* fsubp %stN */ @@ -3948,7 +3958,7 @@ x86_emulate( emulate_fpu_insn_stub(0xde, modrm); break; default: - fail_if(modrm >= 0xc0); + generate_exception_if(ea.type != OP_MEM, EXC_UD); ea.bytes = 2; src = ea; if ( (rc = ops->read(src.mem.seg, src.mem.off, &src.val, @@ -4000,8 +4010,14 @@ x86_emulate( vcpu_must_have_cmov(); emulate_fpu_insn_stub_eflags(0xdf, modrm); break; + case 0xc0 ... 0xc7: /* ffreep %stN */ + case 0xc8 ... 0xcf: /* fxch %stN (alternative encoding) */ + case 0xd0 ... 0xd7: /* fstp %stN (alternative encoding) */ + case 0xd8 ... 0xdf: /* fstp %stN (alternative encoding) */ + emulate_fpu_insn_stub(0xdf, modrm); + break; default: - fail_if(modrm >= 0xc0); + generate_exception_if(ea.type != OP_MEM, EXC_UD); switch ( modrm_reg & 7 ) { case 0: /* fild m16i */ --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -3577,18 +3577,18 @@ x86_emulate( host_and_vcpu_must_have(fpu); switch ( modrm ) { - case 0xc0 ... 0xc7: /* fadd %stN,%stN */ - case 0xc8 ... 0xcf: /* fmul %stN,%stN */ - case 0xd0 ... 0xd7: /* fcom %stN,%stN */ - case 0xd8 ... 0xdf: /* fcomp %stN,%stN */ - case 0xe0 ... 0xe7: /* fsub %stN,%stN */ - case 0xe8 ... 0xef: /* fsubr %stN,%stN */ - case 0xf0 ... 0xf7: /* fdiv %stN,%stN */ - case 0xf8 ... 0xff: /* fdivr %stN,%stN */ + case 0xc0 ... 0xc7: /* fadd %stN,%st */ + case 0xc8 ... 0xcf: /* fmul %stN,%st */ + case 0xd0 ... 0xd7: /* fcom %stN,%st */ + case 0xd8 ... 0xdf: /* fcomp %stN,%st */ + case 0xe0 ... 0xe7: /* fsub %stN,%st */ + case 0xe8 ... 0xef: /* fsubr %stN,%st */ + case 0xf0 ... 0xf7: /* fdiv %stN,%st */ + case 0xf8 ... 0xff: /* fdivr %stN,%st */ emulate_fpu_insn_stub(0xd8, modrm); break; default: - fail_if(modrm >= 0xc0); + ASSERT(ea.type == OP_MEM); ea.bytes = 4; src = ea; if ( (rc = ops->read(src.mem.seg, src.mem.off, &src.val, @@ -3634,6 +3634,7 @@ x86_emulate( case 0xc0 ... 0xc7: /* fld %stN */ case 0xc8 ... 0xcf: /* fxch %stN */ case 0xd0: /* fnop */ + case 0xd8 ... 0xdf: /* fstp %stN (alternative encoding) */ case 0xe0: /* fchs */ case 0xe1: /* fabs */ case 0xe4: /* ftst */ @@ -3663,7 +3664,7 @@ x86_emulate( emulate_fpu_insn_stub(0xd9, modrm); break; default: - fail_if(modrm >= 0xc0); + generate_exception_if(ea.type != OP_MEM, EXC_UD); switch ( modrm_reg & 7 ) { case 0: /* fld m32fp */ @@ -3686,7 +3687,8 @@ x86_emulate( dst.type = OP_MEM; emulate_fpu_insn_memdst("fstps", dst.val); break; - /* case 4: fldenv - TODO */ + case 4: /* fldenv - TODO */ + goto cannot_emulate; case 5: /* fldcw m2byte */ ea.bytes = 2; src = ea; @@ -3695,7 +3697,8 @@ x86_emulate( goto done; emulate_fpu_insn_memsrc("fldcw", src.val); break; - /* case 6: fstenv - TODO */ + case 6: /* fnstenv - TODO */ + goto cannot_emulate; case 7: /* fnstcw m2byte */ ea.bytes = 2; dst = ea; @@ -3703,7 +3706,7 @@ x86_emulate( emulate_fpu_insn_memdst("fnstcw", dst.val); break; default: - goto cannot_emulate; + generate_exception(EXC_UD); } } break; @@ -3723,7 +3726,7 @@ x86_emulate( emulate_fpu_insn_stub(0xda, modrm); break; default: - fail_if(modrm >= 0xc0); + generate_exception_if(ea.type != OP_MEM, EXC_UD); ea.bytes = 4; src = ea; if ( (rc = ops->read(src.mem.seg, src.mem.off, &src.val, @@ -3772,16 +3775,16 @@ x86_emulate( vcpu_must_have_cmov(); emulate_fpu_insn_stub_eflags(0xdb, modrm); break; + case 0xe0: /* fneni - 8087 only, ignored by 287 */ + case 0xe1: /* fndisi - 8087 only, ignored by 287 */ case 0xe2: /* fnclex */ - emulate_fpu_insn("fnclex"); - break; case 0xe3: /* fninit */ - emulate_fpu_insn("fninit"); - break; - case 0xe4: /* fsetpm - 287 only, ignored by 387 */ + case 0xe4: /* fnsetpm - 287 only, ignored by 387 */ + /* case 0xe5: frstpm - 287 only, #UD on 387 */ + emulate_fpu_insn_stub(0xdb, modrm); break; default: - fail_if(modrm >= 0xc0); + generate_exception_if(ea.type != OP_MEM, EXC_UD); switch ( modrm_reg & 7 ) { case 0: /* fild m32i */ @@ -3826,7 +3829,7 @@ x86_emulate( emulate_fpu_insn_memdst("fstpt", dst.val); break; default: - goto cannot_emulate; + generate_exception(EXC_UD); } } break; @@ -3835,16 +3838,18 @@ x86_emulate( host_and_vcpu_must_have(fpu); switch ( modrm ) { - case 0xc0 ... 0xc7: /* fadd %stN */ - case 0xc8 ... 0xcf: /* fmul %stN */ - case 0xe0 ... 0xe7: /* fsubr %stN */ - case 0xe8 ... 0xef: /* fsub %stN */ - case 0xf0 ... 0xf7: /* fdivr %stN */ - case 0xf8 ... 0xff: /* fdiv %stN */ + case 0xc0 ... 0xc7: /* fadd %st,%stN */ + case 0xc8 ... 0xcf: /* fmul %st,%stN */ + case 0xd0 ... 0xd7: /* fcom %stN,%st (alternative encoding) */ + case 0xd8 ... 0xdf: /* fcomp %stN,%st (alternative encoding) */ + case 0xe0 ... 0xe7: /* fsubr %st,%stN */ + case 0xe8 ... 0xef: /* fsub %st,%stN */ + case 0xf0 ... 0xf7: /* fdivr %st,%stN */ + case 0xf8 ... 0xff: /* fdiv %st,%stN */ emulate_fpu_insn_stub(0xdc, modrm); break; default: - fail_if(modrm >= 0xc0); + ASSERT(ea.type == OP_MEM); ea.bytes = 8; src = ea; if ( (rc = ops->read(src.mem.seg, src.mem.off, &src.val, @@ -3885,6 +3890,7 @@ x86_emulate( switch ( modrm ) { case 0xc0 ... 0xc7: /* ffree %stN */ + case 0xc8 ... 0xcf: /* fxch %stN (alternative encoding) */ case 0xd0 ... 0xd7: /* fst %stN */ case 0xd8 ... 0xdf: /* fstp %stN */ case 0xe0 ... 0xe7: /* fucom %stN */ @@ -3892,7 +3898,7 @@ x86_emulate( emulate_fpu_insn_stub(0xdd, modrm); break; default: - fail_if(modrm >= 0xc0); + generate_exception_if(ea.type != OP_MEM, EXC_UD); switch ( modrm_reg & 7 ) { case 0: /* fld m64fp */; @@ -3922,6 +3928,9 @@ x86_emulate( dst.type = OP_MEM; emulate_fpu_insn_memdst("fstpl", dst.val); break; + case 4: /* frstor - TODO */ + case 6: /* fnsave - TODO */ + goto cannot_emulate; case 7: /* fnstsw m2byte */ ea.bytes = 2; dst = ea; @@ -3929,7 +3938,7 @@ x86_emulate( emulate_fpu_insn_memdst("fnstsw", dst.val); break; default: - goto cannot_emulate; + generate_exception(EXC_UD); } } break; @@ -3940,6 +3949,7 @@ x86_emulate( { case 0xc0 ... 0xc7: /* faddp %stN */ case 0xc8 ... 0xcf: /* fmulp %stN */ + case 0xd0 ... 0xd7: /* fcomp %stN (alternative encoding) */ case 0xd9: /* fcompp */ case 0xe0 ... 0xe7: /* fsubrp %stN */ case 0xe8 ... 0xef: /* fsubp %stN */ @@ -3948,7 +3958,7 @@ x86_emulate( emulate_fpu_insn_stub(0xde, modrm); break; default: - fail_if(modrm >= 0xc0); + generate_exception_if(ea.type != OP_MEM, EXC_UD); ea.bytes = 2; src = ea; if ( (rc = ops->read(src.mem.seg, src.mem.off, &src.val, @@ -4000,8 +4010,14 @@ x86_emulate( vcpu_must_have_cmov(); emulate_fpu_insn_stub_eflags(0xdf, modrm); break; + case 0xc0 ... 0xc7: /* ffreep %stN */ + case 0xc8 ... 0xcf: /* fxch %stN (alternative encoding) */ + case 0xd0 ... 0xd7: /* fstp %stN (alternative encoding) */ + case 0xd8 ... 0xdf: /* fstp %stN (alternative encoding) */ + emulate_fpu_insn_stub(0xdf, modrm); + break; default: - fail_if(modrm >= 0xc0); + generate_exception_if(ea.type != OP_MEM, EXC_UD); switch ( modrm_reg & 7 ) { case 0: /* fild m16i */