From patchwork Tue Apr 9 16:43:05 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 13622947 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id B1B21C67861 for ; Tue, 9 Apr 2024 16:44:53 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ruEa0-0000Xs-7U; Tue, 09 Apr 2024 12:44:17 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ruEZW-0000J4-Gu for qemu-devel@nongnu.org; Tue, 09 Apr 2024 12:43:55 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ruEZJ-00080g-VB for qemu-devel@nongnu.org; Tue, 09 Apr 2024 12:43:44 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1712681011; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=GKj06Q1UJNgdnNLxDCGMfDe5mX6d9Zq1tXhx357YV8A=; b=b3r/9InZOEpb11j9ToUHkB1bASrARKsiSETAjMv9h0GihQ3p5tZXznEvjoZdpFmXkY1q/w 8M84n6pkEIW7KD5i3dME60H37o1J2kbrtLJcWAj2GfwXIE5kK0Yg5niJtVViAlbPuzOI2S mMqSiMwAP9+HQka34aWqjXJ9lDL+DJo= Received: from mail-wm1-f72.google.com (mail-wm1-f72.google.com [209.85.128.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-528-SE7KX8kIONWvqWp1tpxwHA-1; Tue, 09 Apr 2024 12:43:30 -0400 X-MC-Unique: SE7KX8kIONWvqWp1tpxwHA-1 Received: by mail-wm1-f72.google.com with SMTP id 5b1f17b1804b1-4162b93067dso22902785e9.3 for ; Tue, 09 Apr 2024 09:43:30 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712681008; x=1713285808; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=GKj06Q1UJNgdnNLxDCGMfDe5mX6d9Zq1tXhx357YV8A=; b=um1n836DGdmJkASz5GzLm0qlkx3QzEfbyPAofVOFPHRBoF40MbPXx0pGlxBXqx1W5a HqYNeG7FFzmoUw6FIWPNNJMlhYgUnRFb7lf3Qc6/ijWmGtqF7fEYNjGsYK9qtvnVDY63 1XDjyn7QtzP5N1snEQ9H5OEV47FCpmbQ/iPpxavlpq3coRhc3dn/onhNp+nFbjZXTmOk WNlQovrO5rwJLWMqNGC8XCVCz/x5dolkuxKxcyM/nt2P/JSWd22/DjitMYixjrjzaNAr cafAdXniBRBy7Hby7N8nGnPOO63lR2PBK1+DyVAGeasXhP/V29RcClWUfnVgFbLR6yKy ObeA== X-Gm-Message-State: AOJu0YxV0iQIDpHhgOlJQu/DVqlCwktQV2sWVvugCfwiJqvmeW5ZYtO9 g/qhLByeJ/BpsR1Gc/U4yMOlGpKcWwZJ9dmnlS+IXxfUF/aZQZO0R9R8GXaULS6WCDRO1WGU84O fc1JvpfEIdZ/dApZEFfnlC31FY4H1ShOrXSj9+RSAdTKH9amEzz6uxORpRGfnFSzQvd+srszl+s v3WQX22/zhM/2ZIE5wHBPnRQ4F0enYTIGF3VBb X-Received: by 2002:a05:600c:1c8d:b0:416:99bb:f7d8 with SMTP id k13-20020a05600c1c8d00b0041699bbf7d8mr191135wms.2.1712681008179; Tue, 09 Apr 2024 09:43:28 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHnufMPcdiTQXDHgqbeClFYuABzJhUOh06CYIIn9ENjxatTXZbyUNcLSSBKMh4WryrsQeE8mQ== X-Received: by 2002:a05:600c:1c8d:b0:416:99bb:f7d8 with SMTP id k13-20020a05600c1c8d00b0041699bbf7d8mr191118wms.2.1712681007677; Tue, 09 Apr 2024 09:43:27 -0700 (PDT) Received: from avogadro.local ([151.95.152.232]) by smtp.gmail.com with ESMTPSA id r10-20020a05600c35ca00b0041622c88852sm21410520wmq.16.2024.04.09.09.43.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 09 Apr 2024 09:43:26 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Cc: Richard Henderson Subject: [PATCH for-9.1 01/19] target/i386: use TSTEQ/TSTNE to test low bits Date: Tue, 9 Apr 2024 18:43:05 +0200 Message-ID: <20240409164323.776660-2-pbonzini@redhat.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240409164323.776660-1-pbonzini@redhat.com> References: <20240409164323.776660-1-pbonzini@redhat.com> MIME-Version: 1.0 Received-SPF: pass client-ip=170.10.133.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -37 X-Spam_score: -3.8 X-Spam_bar: --- X-Spam_report: (-3.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1.701, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org When testing the sign bit or equality to zero of a partial register, it is useful to use a single TSTEQ or TSTNE operation. It can also be used to test the parity flag, using bit 0 of the population count. Do not do this for target_ulong-sized values however; the optimizer would produce a comparison against zero anyway, and it avoids shifts by 64 which are undefined behavior. Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/tcg/translate.c | 28 ++++++++++++++++++++-------- target/i386/tcg/emit.c.inc | 5 ++--- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 76a42c679c7..b7117393961 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -928,11 +928,21 @@ typedef struct CCPrepare { bool no_setcond; } CCPrepare; +static CCPrepare gen_prepare_sign_nz(TCGv src, MemOp size) +{ + if (size == MO_TL) { + return (CCPrepare) { .cond = TCG_COND_LT, .reg = src, .mask = -1 }; + } else { + return (CCPrepare) { .cond = TCG_COND_TSTNE, .reg = src, .mask = -1, + .imm = 1ull << ((8 << size) - 1) }; + } +} + /* compute eflags.C to reg */ static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv reg) { TCGv t0, t1; - int size, shift; + MemOp size; switch (s->cc_op) { case CC_OP_SUBB ... CC_OP_SUBQ: @@ -967,9 +977,7 @@ static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv reg) case CC_OP_SHLB ... CC_OP_SHLQ: /* (CC_SRC >> (DATA_BITS - 1)) & 1 */ size = s->cc_op - CC_OP_SHLB; - shift = (8 << size) - 1; - return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src, - .mask = (target_ulong)1 << shift }; + return gen_prepare_sign_nz(cpu_cc_src, size); case CC_OP_MULB ... CC_OP_MULQ: return (CCPrepare) { .cond = TCG_COND_NE, @@ -1029,8 +1037,7 @@ static CCPrepare gen_prepare_eflags_s(DisasContext *s, TCGv reg) default: { MemOp size = (s->cc_op - CC_OP_ADDB) & 3; - TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, true); - return (CCPrepare) { .cond = TCG_COND_LT, .reg = t0, .mask = -1 }; + return gen_prepare_sign_nz(cpu_cc_dst, size); } } } @@ -1077,8 +1084,13 @@ static CCPrepare gen_prepare_eflags_z(DisasContext *s, TCGv reg) default: { MemOp size = (s->cc_op - CC_OP_ADDB) & 3; - TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, false); - return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 }; + if (size == MO_TL) { + return (CCPrepare) { .cond = TCG_COND_EQ, .reg = cpu_cc_dst, + .mask = -1 }; + } else { + return (CCPrepare) { .cond = TCG_COND_TSTEQ, .reg = cpu_cc_dst, + .mask = -1, .imm = (1ull << (8 << size)) - 1 }; + } } } } diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc index 6bcf88ecd71..0e00f6635dd 100644 --- a/target/i386/tcg/emit.c.inc +++ b/target/i386/tcg/emit.c.inc @@ -1209,7 +1209,7 @@ static void gen_CMPccXADD(DisasContext *s, CPUX86State *env, X86DecodedInsn *dec [JCC_Z] = TCG_COND_EQ, [JCC_BE] = TCG_COND_LEU, [JCC_S] = TCG_COND_LT, /* test sign bit by comparing against 0 */ - [JCC_P] = TCG_COND_EQ, /* even parity - tests low bit of popcount */ + [JCC_P] = TCG_COND_TSTEQ, /* even parity - tests low bit of popcount */ [JCC_L] = TCG_COND_LT, [JCC_LE] = TCG_COND_LE, }; @@ -1260,8 +1260,7 @@ static void gen_CMPccXADD(DisasContext *s, CPUX86State *env, X86DecodedInsn *dec case JCC_P: tcg_gen_ext8u_tl(s->tmp0, s->T0); tcg_gen_ctpop_tl(s->tmp0, s->tmp0); - tcg_gen_andi_tl(s->tmp0, s->tmp0, 1); - cmp_lhs = s->tmp0, cmp_rhs = tcg_constant_tl(0); + cmp_lhs = s->tmp0, cmp_rhs = tcg_constant_tl(1); break; case JCC_S: From patchwork Tue Apr 9 16:43:06 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 13622958 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 0F3AFCD128A for ; Tue, 9 Apr 2024 16:49:49 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ruEa6-0000d3-NH; Tue, 09 Apr 2024 12:44:22 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ruEZk-0000Pz-TW for qemu-devel@nongnu.org; Tue, 09 Apr 2024 12:44:05 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ruEZT-00080z-Qv for qemu-devel@nongnu.org; Tue, 09 Apr 2024 12:44:00 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1712681014; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=VUAOjPBKa8O8uU5nsfNDvHxk44hxE+Dv6mb+elp+vLc=; b=KZkMhJvaOGqozbAsWrqT5Ica9yt2wjkh2Ro3VsuSR4lRYlU1UDMd1EZBIBIahOhJ3NpK0R za5Q/GLXMAcL4OLDxD6gsJ6hB64JrfNQmSDMEvIOmYsGh8cf+eVGoh118LLCQGZoD+SGqT ovDiS0DNnxpk7OH49VlZeXH2puJk3DY= Received: from mail-wr1-f69.google.com (mail-wr1-f69.google.com [209.85.221.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-377-Muu7uMFRPaeC3xwZVPq8lg-1; Tue, 09 Apr 2024 12:43:33 -0400 X-MC-Unique: Muu7uMFRPaeC3xwZVPq8lg-1 Received: by mail-wr1-f69.google.com with SMTP id ffacd0b85a97d-343bc1e4ef3so3629334f8f.1 for ; Tue, 09 Apr 2024 09:43:32 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712681011; x=1713285811; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=VUAOjPBKa8O8uU5nsfNDvHxk44hxE+Dv6mb+elp+vLc=; b=IPrUldA0diFfLV+1M7PkMlA4dB9AjjrCT/KDQqPag0uuBAsWj3H9WJas45QoADI6F0 Qe75iH4UXVltnFhPYt4jn4sWoEmhwoU559iM+4wLHrv+vRgP+XHUhP4unz4duSylMqzV g3h/EcNsh16iwvinB0kmhOMzOaI4y1ArPnD5ZxoaBSTElaBbfEJMProA2u7XxWvMdeqn QJs3ZZVPonRb1Gy1A0CSr5krKKwO9VG5/YSxz8hUoReinB+Eo/aN+ldTjdS/b16d9ZQZ psXCEpyfT8AxifZ07ko3gy3pxjVI+NOgzT+DRRpyIzxjzYsbs/6UPGSUaDakG+ck0baW ipEA== X-Gm-Message-State: AOJu0YyamUpX3bQf4ZuPn0y7/L8P4xLz1pbiUsZZpdqsd7lVKQpM60xU uoCGtGVQpXtylzYbu3wPaRpJjnG0NWtqYZ8p78Rth7WyI+FKM719DdN3aVTIWF2DSiR8xCjZvE3 dHTrm2lYmVaZmD+52UH+eBpz6b9VWg7bsFwBmHhf9ig9tSsSnFawGvsnpIbhuXdqffJxTpePOPd rz0lHxMWRdv6sI65oCwYHxL2dr1goJOENWyayW X-Received: by 2002:adf:fc46:0:b0:33e:cf4d:c583 with SMTP id e6-20020adffc46000000b0033ecf4dc583mr206671wrs.16.1712681010934; Tue, 09 Apr 2024 09:43:30 -0700 (PDT) X-Google-Smtp-Source: AGHT+IH/pgzA3H9Rq0+p40nLDAF5Vw1QXkQeADKzyaB8VIOxV/ldBlYXZoCBuxQB+vSIVX5OgIXbDw== X-Received: by 2002:adf:fc46:0:b0:33e:cf4d:c583 with SMTP id e6-20020adffc46000000b0033ecf4dc583mr206654wrs.16.1712681010571; Tue, 09 Apr 2024 09:43:30 -0700 (PDT) Received: from avogadro.local ([151.95.152.232]) by smtp.gmail.com with ESMTPSA id l10-20020adfe58a000000b003434f526cb5sm11737856wrm.95.2024.04.09.09.43.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 09 Apr 2024 09:43:28 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Cc: Richard Henderson Subject: [PATCH for-9.1 02/19] target/i386: use TSTEQ/TSTNE to check flags Date: Tue, 9 Apr 2024 18:43:06 +0200 Message-ID: <20240409164323.776660-3-pbonzini@redhat.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240409164323.776660-1-pbonzini@redhat.com> References: <20240409164323.776660-1-pbonzini@redhat.com> MIME-Version: 1.0 Received-SPF: pass client-ip=170.10.129.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -37 X-Spam_score: -3.8 X-Spam_bar: --- X-Spam_report: (-3.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1.701, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org The new conditions obviously come in handy when testing individual bits of EFLAGS, and they make it possible to remove the .mask field of CCPrepare. Lowering to shift+and is done by the optimizer if necessary. Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/tcg/translate.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index b7117393961..4de5090846a 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -996,8 +996,8 @@ static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv reg) case CC_OP_EFLAGS: case CC_OP_SARB ... CC_OP_SARQ: /* CC_SRC & 1 */ - return (CCPrepare) { .cond = TCG_COND_NE, - .reg = cpu_cc_src, .mask = CC_C }; + return (CCPrepare) { .cond = TCG_COND_TSTNE, + .reg = cpu_cc_src, .mask = -1, .imm = CC_C }; default: /* The need to compute only C from CC_OP_DYNAMIC is important @@ -1014,8 +1014,8 @@ static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv reg) static CCPrepare gen_prepare_eflags_p(DisasContext *s, TCGv reg) { gen_compute_eflags(s); - return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src, - .mask = CC_P }; + return (CCPrepare) { .cond = TCG_COND_TSTNE, .reg = cpu_cc_src, + .mask = -1, .imm = CC_P }; } /* compute eflags.S to reg */ @@ -1029,8 +1029,8 @@ static CCPrepare gen_prepare_eflags_s(DisasContext *s, TCGv reg) case CC_OP_ADCX: case CC_OP_ADOX: case CC_OP_ADCOX: - return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src, - .mask = CC_S }; + return (CCPrepare) { .cond = TCG_COND_TSTNE, .reg = cpu_cc_src, + .mask = -1, .imm = CC_S }; case CC_OP_CLR: case CC_OP_POPCNT: return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 }; @@ -1058,8 +1058,8 @@ static CCPrepare gen_prepare_eflags_o(DisasContext *s, TCGv reg) .reg = cpu_cc_src, .mask = -1 }; default: gen_compute_eflags(s); - return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src, - .mask = CC_O }; + return (CCPrepare) { .cond = TCG_COND_TSTNE, .reg = cpu_cc_src, + .mask = -1, .imm = CC_O }; } } @@ -1074,8 +1074,8 @@ static CCPrepare gen_prepare_eflags_z(DisasContext *s, TCGv reg) case CC_OP_ADCX: case CC_OP_ADOX: case CC_OP_ADCOX: - return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src, - .mask = CC_Z }; + return (CCPrepare) { .cond = TCG_COND_TSTNE, .reg = cpu_cc_src, + .mask = -1, .imm = CC_Z }; case CC_OP_CLR: return (CCPrepare) { .cond = TCG_COND_ALWAYS, .mask = -1 }; case CC_OP_POPCNT: @@ -1153,8 +1153,8 @@ static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg) break; case JCC_BE: gen_compute_eflags(s); - cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src, - .mask = CC_Z | CC_C }; + cc = (CCPrepare) { .cond = TCG_COND_TSTNE, .reg = cpu_cc_src, + .mask = -1, .imm = CC_Z | CC_C }; break; case JCC_S: cc = gen_prepare_eflags_s(s, reg); @@ -1168,8 +1168,8 @@ static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg) reg = s->tmp0; } tcg_gen_addi_tl(reg, cpu_cc_src, CC_O - CC_S); - cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg, - .mask = CC_O }; + cc = (CCPrepare) { .cond = TCG_COND_TSTNE, .reg = reg, + .mask = -1, .imm = CC_O }; break; default: case JCC_LE: @@ -1178,8 +1178,8 @@ static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg) reg = s->tmp0; } tcg_gen_addi_tl(reg, cpu_cc_src, CC_O - CC_S); - cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg, - .mask = CC_O | CC_Z }; + cc = (CCPrepare) { .cond = TCG_COND_TSTNE, .reg = reg, + .mask = -1, .imm = CC_O | CC_Z }; break; } break; From patchwork Tue Apr 9 16:43:07 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 13622948 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id B3AE0CD1297 for ; Tue, 9 Apr 2024 16:44:53 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ruEZw-0000XY-Jb; Tue, 09 Apr 2024 12:44:15 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ruEZd-0000KU-5X for qemu-devel@nongnu.org; Tue, 09 Apr 2024 12:43:56 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ruEZV-00081M-8A for qemu-devel@nongnu.org; Tue, 09 Apr 2024 12:43:52 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1712681018; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=k1KQQnQGmYnGuwtQD09Q9lKvxrOfBHUYPnj8qF07koM=; b=OBbKVfq/ZoiR9eFG9UhUDmHYW5f0wdBm0gEObewifNuzfH0riERTGbi8cDDXUVlrmoYY6V Dnpm37OW2vcWEWS+pfL2zIUIIZBD8irrHHj1aW6X8q2Igq1u81rfLiOaJSetoN6TJTFCJg Uzd0b1eahRmurDa6HgCnRVa8hGIuCY8= Received: from mail-wr1-f70.google.com (mail-wr1-f70.google.com [209.85.221.70]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-335-n-pb9CH5Oa6L5DgraZSfIA-1; Tue, 09 Apr 2024 12:43:36 -0400 X-MC-Unique: n-pb9CH5Oa6L5DgraZSfIA-1 Received: by mail-wr1-f70.google.com with SMTP id ffacd0b85a97d-343e00c8979so2680171f8f.1 for ; Tue, 09 Apr 2024 09:43:36 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712681014; x=1713285814; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=k1KQQnQGmYnGuwtQD09Q9lKvxrOfBHUYPnj8qF07koM=; b=Aopqg6MAlgI+ZXxZdbvdYjJLttTr8R4eDobnIUpEDP6vsyGELq7gB8mrXKmbzKVhvL UfCybdCm/cCb9fxr0/Qnp2H8S44LKbSokfGDzXmqpHxmbrjAbBr9Zr9wYcE/gYhvP0H3 i4j+ipaDtjtOMGB/rx5iMfXHKxKxz/mxJ/Xy2zs2yr0ipzy6nqXx2otx37qUzKEqPUBT gRjir/w3Aj63lRUOX2pKI/Kiy34bo0TgfxeWvyRjan3DKOGUpgf4PJpy6pA+dL8j+OEE zt+EC+F0WihDut9jYQ1jMF2BNjDo57oeLpjLffeT/lp/otCtsK+d97cCgsQf3iA3GhDZ CrIw== X-Gm-Message-State: AOJu0YxdU6zTAW8/V8x6ypFjtQiDP+j5vQu+kbgLhaPVtn/n8Se8+XFx jvtHeb1wc1SpPvwLjfFVM4RnlzznAovTByeEQzJ24uRo4rV7y2ZSr8QUQMzvWVk2g+fghSJRm4a rm0cI4bHmkzUeR7txDYSXFDSSyK42rVks0vkFu0+2PujMp4gSWTd2EXTMiEw3NertiOqGrnvkDf iNJvxFXfoBcRG3bgJxUH+0dP4jBYt2WbvsNnJi X-Received: by 2002:a5d:628c:0:b0:343:ad7e:5bc5 with SMTP id k12-20020a5d628c000000b00343ad7e5bc5mr170270wru.57.1712681014272; Tue, 09 Apr 2024 09:43:34 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGZW+p/EeqhK3wNBH/1eqnN+lF7t76+K38nUcqRm6zj2HBLRl2PtNbtuOHu4yIB4ZXh6SHhhA== X-Received: by 2002:a5d:628c:0:b0:343:ad7e:5bc5 with SMTP id k12-20020a5d628c000000b00343ad7e5bc5mr170254wru.57.1712681013811; Tue, 09 Apr 2024 09:43:33 -0700 (PDT) Received: from avogadro.local ([151.95.152.232]) by smtp.gmail.com with ESMTPSA id c18-20020adffb52000000b00346266b612csm1912538wrs.81.2024.04.09.09.43.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 09 Apr 2024 09:43:32 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Cc: Richard Henderson Subject: [PATCH for-9.1 03/19] target/i386: remove mask from CCPrepare Date: Tue, 9 Apr 2024 18:43:07 +0200 Message-ID: <20240409164323.776660-4-pbonzini@redhat.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240409164323.776660-1-pbonzini@redhat.com> References: <20240409164323.776660-1-pbonzini@redhat.com> MIME-Version: 1.0 Received-SPF: pass client-ip=170.10.129.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -37 X-Spam_score: -3.8 X-Spam_bar: --- X-Spam_report: (-3.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1.701, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org With the introduction of TSTEQ and TSTNE the .mask field is always -1, so remove all the now-unnecessary code. Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini Reviewed-by: Philippe Mathieu-Daudé --- target/i386/tcg/translate.c | 81 +++++++++++++------------------------ 1 file changed, 27 insertions(+), 54 deletions(-) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 4de5090846a..197cccb6c96 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -923,7 +923,6 @@ typedef struct CCPrepare { TCGv reg; TCGv reg2; target_ulong imm; - target_ulong mask; bool use_reg2; bool no_setcond; } CCPrepare; @@ -931,9 +930,9 @@ typedef struct CCPrepare { static CCPrepare gen_prepare_sign_nz(TCGv src, MemOp size) { if (size == MO_TL) { - return (CCPrepare) { .cond = TCG_COND_LT, .reg = src, .mask = -1 }; + return (CCPrepare) { .cond = TCG_COND_LT, .reg = src }; } else { - return (CCPrepare) { .cond = TCG_COND_TSTNE, .reg = src, .mask = -1, + return (CCPrepare) { .cond = TCG_COND_TSTNE, .reg = src, .imm = 1ull << ((8 << size) - 1) }; } } @@ -962,17 +961,17 @@ static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv reg) t0 = gen_ext_tl(reg, cpu_cc_dst, size, false); add_sub: return (CCPrepare) { .cond = TCG_COND_LTU, .reg = t0, - .reg2 = t1, .mask = -1, .use_reg2 = true }; + .reg2 = t1, .use_reg2 = true }; case CC_OP_LOGICB ... CC_OP_LOGICQ: case CC_OP_CLR: case CC_OP_POPCNT: - return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 }; + return (CCPrepare) { .cond = TCG_COND_NEVER }; case CC_OP_INCB ... CC_OP_INCQ: case CC_OP_DECB ... CC_OP_DECQ: return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src, - .mask = -1, .no_setcond = true }; + .no_setcond = true }; case CC_OP_SHLB ... CC_OP_SHLQ: /* (CC_SRC >> (DATA_BITS - 1)) & 1 */ @@ -981,23 +980,23 @@ static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv reg) case CC_OP_MULB ... CC_OP_MULQ: return (CCPrepare) { .cond = TCG_COND_NE, - .reg = cpu_cc_src, .mask = -1 }; + .reg = cpu_cc_src }; case CC_OP_BMILGB ... CC_OP_BMILGQ: size = s->cc_op - CC_OP_BMILGB; t0 = gen_ext_tl(reg, cpu_cc_src, size, false); - return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 }; + return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0 }; case CC_OP_ADCX: case CC_OP_ADCOX: return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_dst, - .mask = -1, .no_setcond = true }; + .no_setcond = true }; case CC_OP_EFLAGS: case CC_OP_SARB ... CC_OP_SARQ: /* CC_SRC & 1 */ return (CCPrepare) { .cond = TCG_COND_TSTNE, - .reg = cpu_cc_src, .mask = -1, .imm = CC_C }; + .reg = cpu_cc_src, .imm = CC_C }; default: /* The need to compute only C from CC_OP_DYNAMIC is important @@ -1006,7 +1005,7 @@ static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv reg) gen_helper_cc_compute_c(reg, cpu_cc_dst, cpu_cc_src, cpu_cc_src2, cpu_cc_op); return (CCPrepare) { .cond = TCG_COND_NE, .reg = reg, - .mask = -1, .no_setcond = true }; + .no_setcond = true }; } } @@ -1015,7 +1014,7 @@ static CCPrepare gen_prepare_eflags_p(DisasContext *s, TCGv reg) { gen_compute_eflags(s); return (CCPrepare) { .cond = TCG_COND_TSTNE, .reg = cpu_cc_src, - .mask = -1, .imm = CC_P }; + .imm = CC_P }; } /* compute eflags.S to reg */ @@ -1030,10 +1029,10 @@ static CCPrepare gen_prepare_eflags_s(DisasContext *s, TCGv reg) case CC_OP_ADOX: case CC_OP_ADCOX: return (CCPrepare) { .cond = TCG_COND_TSTNE, .reg = cpu_cc_src, - .mask = -1, .imm = CC_S }; + .imm = CC_S }; case CC_OP_CLR: case CC_OP_POPCNT: - return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 }; + return (CCPrepare) { .cond = TCG_COND_NEVER }; default: { MemOp size = (s->cc_op - CC_OP_ADDB) & 3; @@ -1049,17 +1048,16 @@ static CCPrepare gen_prepare_eflags_o(DisasContext *s, TCGv reg) case CC_OP_ADOX: case CC_OP_ADCOX: return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src2, - .mask = -1, .no_setcond = true }; + .no_setcond = true }; case CC_OP_CLR: case CC_OP_POPCNT: - return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 }; + return (CCPrepare) { .cond = TCG_COND_NEVER }; case CC_OP_MULB ... CC_OP_MULQ: - return (CCPrepare) { .cond = TCG_COND_NE, - .reg = cpu_cc_src, .mask = -1 }; + return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src }; default: gen_compute_eflags(s); return (CCPrepare) { .cond = TCG_COND_TSTNE, .reg = cpu_cc_src, - .mask = -1, .imm = CC_O }; + .imm = CC_O }; } } @@ -1075,21 +1073,19 @@ static CCPrepare gen_prepare_eflags_z(DisasContext *s, TCGv reg) case CC_OP_ADOX: case CC_OP_ADCOX: return (CCPrepare) { .cond = TCG_COND_TSTNE, .reg = cpu_cc_src, - .mask = -1, .imm = CC_Z }; + .imm = CC_Z }; case CC_OP_CLR: - return (CCPrepare) { .cond = TCG_COND_ALWAYS, .mask = -1 }; + return (CCPrepare) { .cond = TCG_COND_ALWAYS }; case CC_OP_POPCNT: - return (CCPrepare) { .cond = TCG_COND_EQ, .reg = cpu_cc_src, - .mask = -1 }; + return (CCPrepare) { .cond = TCG_COND_EQ, .reg = cpu_cc_src }; default: { MemOp size = (s->cc_op - CC_OP_ADDB) & 3; if (size == MO_TL) { - return (CCPrepare) { .cond = TCG_COND_EQ, .reg = cpu_cc_dst, - .mask = -1 }; + return (CCPrepare) { .cond = TCG_COND_EQ, .reg = cpu_cc_dst }; } else { return (CCPrepare) { .cond = TCG_COND_TSTEQ, .reg = cpu_cc_dst, - .mask = -1, .imm = (1ull << (8 << size)) - 1 }; + .imm = (1ull << (8 << size)) - 1 }; } } } @@ -1117,7 +1113,7 @@ static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg) gen_extu(size, s->tmp4); t0 = gen_ext_tl(s->tmp0, cpu_cc_src, size, false); cc = (CCPrepare) { .cond = TCG_COND_LEU, .reg = s->tmp4, - .reg2 = t0, .mask = -1, .use_reg2 = true }; + .reg2 = t0, .use_reg2 = true }; break; case JCC_L: @@ -1130,7 +1126,7 @@ static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg) gen_exts(size, s->tmp4); t0 = gen_ext_tl(s->tmp0, cpu_cc_src, size, true); cc = (CCPrepare) { .cond = cond, .reg = s->tmp4, - .reg2 = t0, .mask = -1, .use_reg2 = true }; + .reg2 = t0, .use_reg2 = true }; break; default: @@ -1154,7 +1150,7 @@ static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg) case JCC_BE: gen_compute_eflags(s); cc = (CCPrepare) { .cond = TCG_COND_TSTNE, .reg = cpu_cc_src, - .mask = -1, .imm = CC_Z | CC_C }; + .imm = CC_Z | CC_C }; break; case JCC_S: cc = gen_prepare_eflags_s(s, reg); @@ -1169,7 +1165,7 @@ static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg) } tcg_gen_addi_tl(reg, cpu_cc_src, CC_O - CC_S); cc = (CCPrepare) { .cond = TCG_COND_TSTNE, .reg = reg, - .mask = -1, .imm = CC_O }; + .imm = CC_O }; break; default: case JCC_LE: @@ -1179,7 +1175,7 @@ static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg) } tcg_gen_addi_tl(reg, cpu_cc_src, CC_O - CC_S); cc = (CCPrepare) { .cond = TCG_COND_TSTNE, .reg = reg, - .mask = -1, .imm = CC_O | CC_Z }; + .imm = CC_O | CC_Z }; break; } break; @@ -1204,16 +1200,6 @@ static void gen_setcc1(DisasContext *s, int b, TCGv reg) return; } - if (cc.cond == TCG_COND_NE && !cc.use_reg2 && cc.imm == 0 && - cc.mask != 0 && (cc.mask & (cc.mask - 1)) == 0) { - tcg_gen_shri_tl(reg, cc.reg, ctztl(cc.mask)); - tcg_gen_andi_tl(reg, reg, 1); - return; - } - if (cc.mask != -1) { - tcg_gen_andi_tl(reg, cc.reg, cc.mask); - cc.reg = reg; - } if (cc.use_reg2) { tcg_gen_setcond_tl(cc.cond, reg, cc.reg, cc.reg2); } else { @@ -1232,10 +1218,6 @@ static inline void gen_jcc1_noeob(DisasContext *s, int b, TCGLabel *l1) { CCPrepare cc = gen_prepare_cc(s, b, s->T0); - if (cc.mask != -1) { - tcg_gen_andi_tl(s->T0, cc.reg, cc.mask); - cc.reg = s->T0; - } if (cc.use_reg2) { tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1); } else { @@ -1251,10 +1233,6 @@ static inline void gen_jcc1(DisasContext *s, int b, TCGLabel *l1) CCPrepare cc = gen_prepare_cc(s, b, s->T0); gen_update_cc_op(s); - if (cc.mask != -1) { - tcg_gen_andi_tl(s->T0, cc.reg, cc.mask); - cc.reg = s->T0; - } set_cc_op(s, CC_OP_DYNAMIC); if (cc.use_reg2) { tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1); @@ -2519,11 +2497,6 @@ static void gen_cmovcc1(DisasContext *s, int b, TCGv dest, TCGv src) { CCPrepare cc = gen_prepare_cc(s, b, s->T1); - if (cc.mask != -1) { - TCGv t0 = tcg_temp_new(); - tcg_gen_andi_tl(t0, cc.reg, cc.mask); - cc.reg = t0; - } if (!cc.use_reg2) { cc.reg2 = tcg_constant_tl(cc.imm); } From patchwork Tue Apr 9 16:43:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 13622957 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 59513CD128A for ; Tue, 9 Apr 2024 16:47:33 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ruEa6-0000c8-45; Tue, 09 Apr 2024 12:44:22 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ruEZp-0000SL-FS for qemu-devel@nongnu.org; Tue, 09 Apr 2024 12:44:05 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ruEZY-00081j-Ey for qemu-devel@nongnu.org; Tue, 09 Apr 2024 12:44:00 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1712681020; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=5qQRcWwTmeCYOgNULC5SnXW502wZ5qxCsGLvfObFDcM=; b=DpWlc0C47oMI+D8AHg0LjdcXfp28PpeWxCDhMJbEnb1dUk4ZcFCyS8UV3erpEdv4psegwL cVTgUSXRG10IrhmteY9RhTRSCgzjV/5e8AXao/9Md0WXGGjvjeaaeIs7Z49UIGeSxiN+ou oV4rO8JWJ4J+HOSkvDmZE53Kc6XIeFY= Received: from mail-wr1-f72.google.com (mail-wr1-f72.google.com [209.85.221.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-219-lPrQGdllMTyLs3agXo7yUw-1; Tue, 09 Apr 2024 12:43:39 -0400 X-MC-Unique: lPrQGdllMTyLs3agXo7yUw-1 Received: by mail-wr1-f72.google.com with SMTP id ffacd0b85a97d-343d7cd8f46so2738569f8f.2 for ; Tue, 09 Apr 2024 09:43:39 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712681018; x=1713285818; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=5qQRcWwTmeCYOgNULC5SnXW502wZ5qxCsGLvfObFDcM=; b=LD+5S6Whb6Xy2jQARM6CQmwv+EFlnzOv3FKW/GpviOtKeeVjK9Y3R77NOYJB7bZIcD z+4rnf0wbf4k3ulzAr3R3aeTdNFWw2oz5nr+svD4Nm0BWXVqI6EgCTmWxyTj7bZMJYZN bTiNxeLdRtXDdnJ7TZrdwtXnrM0yeDrnsyhsHq+GpTRsspxRbck55XppE2yo1phE2vtg SMBg6xv85ri4KM99cSv4GzHs/qEKQGOZXQSFCvxGNao/eSZ0XrddQdTSjf/hG7plT1fS sLVkOZy67ospar5HUwM5EEvsONi3+aQwmqvNnMd6ewrp12oMkGQ1HNiVjcA15dIYkVkJ yvBg== X-Gm-Message-State: AOJu0Ywz2I5YKe5w1wfO1dTrCqSGaeGe+eUKKZwlg6AI1izr0jUtgGtw R8j0yI3ApNH7uU5xnz64AmWOTh1lOZFXtOHDbubqayN0nNXPYeTCTdRBIixnZOlF1XkNGUb6kPL 7K0G9hrd6cCU0KMa5Ykr4Yg7Ux1qMEDVYD1plClJzg6DiFAh95OXzSLS5dsgb1YLR1rireh2gXq RrGoOvB2/Zgmj4aR6QQUo0td53cf0Kzmrr5FYq X-Received: by 2002:a5d:4a51:0:b0:343:3542:b6aa with SMTP id v17-20020a5d4a51000000b003433542b6aamr159751wrs.58.1712681017705; Tue, 09 Apr 2024 09:43:37 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFt5NVyftS0GGrN8cjmAT452HlFD9dKL0ia5nKyU/lJXngb6QkjgyS8qB+lNHbVPBgnVkZF5Q== X-Received: by 2002:a5d:4a51:0:b0:343:3542:b6aa with SMTP id v17-20020a5d4a51000000b003433542b6aamr159737wrs.58.1712681017256; Tue, 09 Apr 2024 09:43:37 -0700 (PDT) Received: from avogadro.local ([151.95.152.232]) by smtp.gmail.com with ESMTPSA id d6-20020a056000114600b003456c693fa4sm7615585wrx.93.2024.04.09.09.43.35 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 09 Apr 2024 09:43:35 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Subject: [PATCH for-9.1 04/19] target/i386: do not use s->tmp0 and s->tmp4 to compute flags Date: Tue, 9 Apr 2024 18:43:08 +0200 Message-ID: <20240409164323.776660-5-pbonzini@redhat.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240409164323.776660-1-pbonzini@redhat.com> References: <20240409164323.776660-1-pbonzini@redhat.com> MIME-Version: 1.0 Received-SPF: pass client-ip=170.10.129.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -37 X-Spam_score: -3.8 X-Spam_bar: --- X-Spam_report: (-3.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1.701, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, T_SPF_TEMPERROR=0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Create a new temporary whenever flags have to use one, instead of using s->tmp0 or s->tmp4. NULL can now be passed as the scratch register to gen_prepare_*. Signed-off-by: Paolo Bonzini Reviewed-by: Richard Henderson --- target/i386/tcg/translate.c | 54 +++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 197cccb6c96..debc1b27283 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -947,9 +947,9 @@ static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv reg) case CC_OP_SUBB ... CC_OP_SUBQ: /* (DATA_TYPE)CC_SRCT < (DATA_TYPE)CC_SRC */ size = s->cc_op - CC_OP_SUBB; - t1 = gen_ext_tl(s->tmp0, cpu_cc_src, size, false); - /* If no temporary was used, be careful not to alias t1 and t0. */ - t0 = t1 == cpu_cc_src ? s->tmp0 : reg; + /* Be careful not to alias t1 and t0. */ + t1 = gen_ext_tl(NULL, cpu_cc_src, size, false); + t0 = (reg == t1 || !reg) ? tcg_temp_new() : reg; tcg_gen_mov_tl(t0, s->cc_srcT); gen_extu(size, t0); goto add_sub; @@ -957,8 +957,9 @@ static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv reg) case CC_OP_ADDB ... CC_OP_ADDQ: /* (DATA_TYPE)CC_DST < (DATA_TYPE)CC_SRC */ size = s->cc_op - CC_OP_ADDB; - t1 = gen_ext_tl(s->tmp0, cpu_cc_src, size, false); - t0 = gen_ext_tl(reg, cpu_cc_dst, size, false); + /* Be careful not to alias t1 and t0. */ + t1 = gen_ext_tl(NULL, cpu_cc_src, size, false); + t0 = gen_ext_tl(reg == t1 ? NULL : reg, cpu_cc_dst, size, false); add_sub: return (CCPrepare) { .cond = TCG_COND_LTU, .reg = t0, .reg2 = t1, .use_reg2 = true }; @@ -1002,6 +1003,9 @@ static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv reg) /* The need to compute only C from CC_OP_DYNAMIC is important in efficiently implementing e.g. INC at the start of a TB. */ gen_update_cc_op(s); + if (!reg) { + reg = tcg_temp_new(); + } gen_helper_cc_compute_c(reg, cpu_cc_dst, cpu_cc_src, cpu_cc_src2, cpu_cc_op); return (CCPrepare) { .cond = TCG_COND_NE, .reg = reg, @@ -1098,7 +1102,7 @@ static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg) int inv, jcc_op, cond; MemOp size; CCPrepare cc; - TCGv t0; + TCGv t0, t1; inv = b & 1; jcc_op = (b >> 1) & 7; @@ -1109,11 +1113,13 @@ static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg) size = s->cc_op - CC_OP_SUBB; switch (jcc_op) { case JCC_BE: - tcg_gen_mov_tl(s->tmp4, s->cc_srcT); - gen_extu(size, s->tmp4); - t0 = gen_ext_tl(s->tmp0, cpu_cc_src, size, false); - cc = (CCPrepare) { .cond = TCG_COND_LEU, .reg = s->tmp4, - .reg2 = t0, .use_reg2 = true }; + /* Be careful not to alias t1 and t0. */ + t1 = gen_ext_tl(NULL, cpu_cc_src, size, false); + t0 = (reg == t1 || !reg) ? tcg_temp_new() : reg; + tcg_gen_mov_tl(t0, s->cc_srcT); + gen_extu(size, t0); + cc = (CCPrepare) { .cond = TCG_COND_LEU, .reg = t0, + .reg2 = t1, .use_reg2 = true }; break; case JCC_L: @@ -1122,11 +1128,13 @@ static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg) case JCC_LE: cond = TCG_COND_LE; fast_jcc_l: - tcg_gen_mov_tl(s->tmp4, s->cc_srcT); - gen_exts(size, s->tmp4); - t0 = gen_ext_tl(s->tmp0, cpu_cc_src, size, true); - cc = (CCPrepare) { .cond = cond, .reg = s->tmp4, - .reg2 = t0, .use_reg2 = true }; + /* Be careful not to alias t1 and t0. */ + t1 = gen_ext_tl(NULL, cpu_cc_src, size, true); + t0 = (reg == t1 || !reg) ? tcg_temp_new() : reg; + tcg_gen_mov_tl(t0, s->cc_srcT); + gen_exts(size, t0); + cc = (CCPrepare) { .cond = cond, .reg = t0, + .reg2 = t1, .use_reg2 = true }; break; default: @@ -1160,8 +1168,8 @@ static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg) break; case JCC_L: gen_compute_eflags(s); - if (reg == cpu_cc_src) { - reg = s->tmp0; + if (reg == cpu_cc_src || !reg) { + reg = tcg_temp_new(); } tcg_gen_addi_tl(reg, cpu_cc_src, CC_O - CC_S); cc = (CCPrepare) { .cond = TCG_COND_TSTNE, .reg = reg, @@ -1170,8 +1178,8 @@ static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg) default: case JCC_LE: gen_compute_eflags(s); - if (reg == cpu_cc_src) { - reg = s->tmp0; + if (reg == cpu_cc_src || !reg) { + reg = tcg_temp_new(); } tcg_gen_addi_tl(reg, cpu_cc_src, CC_O - CC_S); cc = (CCPrepare) { .cond = TCG_COND_TSTNE, .reg = reg, @@ -1216,7 +1224,7 @@ static inline void gen_compute_eflags_c(DisasContext *s, TCGv reg) value 'b'. In the fast case, T0 is guaranteed not to be used. */ static inline void gen_jcc1_noeob(DisasContext *s, int b, TCGLabel *l1) { - CCPrepare cc = gen_prepare_cc(s, b, s->T0); + CCPrepare cc = gen_prepare_cc(s, b, NULL); if (cc.use_reg2) { tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1); @@ -1230,7 +1238,7 @@ static inline void gen_jcc1_noeob(DisasContext *s, int b, TCGLabel *l1) A translation block must end soon. */ static inline void gen_jcc1(DisasContext *s, int b, TCGLabel *l1) { - CCPrepare cc = gen_prepare_cc(s, b, s->T0); + CCPrepare cc = gen_prepare_cc(s, b, NULL); gen_update_cc_op(s); set_cc_op(s, CC_OP_DYNAMIC); @@ -2495,7 +2503,7 @@ static void gen_jcc(DisasContext *s, int b, int diff) static void gen_cmovcc1(DisasContext *s, int b, TCGv dest, TCGv src) { - CCPrepare cc = gen_prepare_cc(s, b, s->T1); + CCPrepare cc = gen_prepare_cc(s, b, NULL); if (!cc.use_reg2) { cc.reg2 = tcg_constant_tl(cc.imm); From patchwork Tue Apr 9 16:43:09 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 13622951 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 7047AC67861 for ; Tue, 9 Apr 2024 16:45:31 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ruEab-0000wL-OS; Tue, 09 Apr 2024 12:44:54 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ruEZz-0000YQ-Fm for qemu-devel@nongnu.org; Tue, 09 Apr 2024 12:44:16 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ruEZX-000821-G1 for qemu-devel@nongnu.org; Tue, 09 Apr 2024 12:44:10 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1712681023; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=wf2tVfaTh1bvwuOTSvtg3oyPPERZ0LSpwFLl2wx9qrs=; b=XDq3rcsL/+kqOmbFGl0nJECfJjsqQSwEcC6dKLY1RHWpHC9oErxJmxxrIHpyLVMw1irjiI BlS6EyJmb8UPQ0ETtqHsvwEzZjoc/z67sMx51BPY9HzhQOnnZc6Xug9fb79qQmgin1Zbku HXDhA9mv42e/zZvZKvANKge7InOpkMs= Received: from mail-wm1-f71.google.com (mail-wm1-f71.google.com [209.85.128.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-437-GWgI80D6P5ujEAiJVMU6ug-1; Tue, 09 Apr 2024 12:43:41 -0400 X-MC-Unique: GWgI80D6P5ujEAiJVMU6ug-1 Received: by mail-wm1-f71.google.com with SMTP id 5b1f17b1804b1-415591b1500so34080715e9.3 for ; Tue, 09 Apr 2024 09:43:41 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712681020; x=1713285820; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=wf2tVfaTh1bvwuOTSvtg3oyPPERZ0LSpwFLl2wx9qrs=; b=n+FY0VmMDPrHSd5A/vRMolN5atM8d9g95AjzlTG6j2TqUASNndWUtkXqPcHoR6tUfd xziaSPXWb8NgEE/RSkHywL64IOYB0EIwpw0yVkovWYjtojJboTvfkjwFcu3tfw/95n57 6a3LDZg74OXuXcRSbv4PG77eVRPWI6RLAQ8u2XAYpwtyKgIWqymkk62vOk4Tb4Tc2FnG zqshH5xXZ2YfNmU3Ofq1K81VT0S1vc25HUaYdrFk/++z5IgVmmhfDQVHAv1fGEoo+sQz JqiVK6IyKOuLJmXwnp4EUn7SOiCWhY3Os1oofyie9Xo1sccP/cZx6f76hWTPReRx8REP vQlA== X-Gm-Message-State: AOJu0Yz5vFk4aj/847TvFVstg214aBGNLH4nx3WKyfP43K8wI2i8Q6Kb yoAjbL/KHRt6Ekgkax+TvHzCf7NDa99+s5yfXdMu2QQa/c5EwaHys3Rz/DQxAx5hM/G6B2gxCmU 1e2KiCyEToIZRgzhoYWpBck7hSHpcHKu0bappjzfvjAQUkl4oOYmiHQ/Np3//ENqx9FF3bGYXOh EorKWO0vxfV6Br9XT08KTjPiWrRSgB2RZMk9X+ X-Received: by 2002:a05:600c:5104:b0:413:3941:d9ae with SMTP id o4-20020a05600c510400b004133941d9aemr175598wms.31.1712681019966; Tue, 09 Apr 2024 09:43:39 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGc7iztGQehHuU8rcP8F/QdP7gkULtuqlzV6C8w6ZdEdUCeD3Y31wMUhfa8qrKaLOHJafp4+w== X-Received: by 2002:a05:600c:5104:b0:413:3941:d9ae with SMTP id o4-20020a05600c510400b004133941d9aemr175585wms.31.1712681019572; Tue, 09 Apr 2024 09:43:39 -0700 (PDT) Received: from avogadro.local ([151.95.152.232]) by smtp.gmail.com with ESMTPSA id z5-20020a05600c0a0500b00416290b3e1dsm18187798wmp.24.2024.04.09.09.43.39 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 09 Apr 2024 09:43:39 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Subject: [PATCH for-9.1 05/19] target/i386: reintroduce debugging mechanism Date: Tue, 9 Apr 2024 18:43:09 +0200 Message-ID: <20240409164323.776660-6-pbonzini@redhat.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240409164323.776660-1-pbonzini@redhat.com> References: <20240409164323.776660-1-pbonzini@redhat.com> MIME-Version: 1.0 Received-SPF: pass client-ip=170.10.129.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -37 X-Spam_score: -3.8 X-Spam_bar: --- X-Spam_report: (-3.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1.701, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, T_SPF_TEMPERROR=0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Signed-off-by: Paolo Bonzini --- target/i386/tcg/translate.c | 27 +++++++++++++++++++++++++++ target/i386/tcg/decode-new.c.inc | 3 +++ 2 files changed, 30 insertions(+) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index debc1b27283..2a372842db4 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -2971,6 +2971,9 @@ static void gen_sty_env_A0(DisasContext *s, int offset, bool align) tcg_gen_qemu_st_i128(t, s->tmp0, mem_index, mop); } +static bool first = true; +static unsigned long limit; + #include "decode-new.h" #include "emit.c.inc" #include "decode-new.c.inc" @@ -3126,15 +3129,39 @@ static bool disas_insn(DisasContext *s, CPUState *cpu) prefixes = 0; + if (first) { + const char *limit_str = getenv("QEMU_I386_LIMIT"); + limit = limit_str ? atol(limit_str) : -1; + first = false; + } + bool use_new = true; +#ifdef CONFIG_USER_ONLY + use_new &= limit > 0; +#endif + next_byte: s->prefix = prefixes; b = x86_ldub_code(env, s); /* Collect prefixes. */ switch (b) { default: +#ifndef CONFIG_USER_ONLY + use_new &= b <= limit; +#endif + if (use_new && 0) { + disas_insn_new(s, cpu, b); + return true; + } break; case 0x0f: b = x86_ldub_code(env, s) + 0x100; +#ifndef CONFIG_USER_ONLY + use_new &= b <= limit; +#endif + if (use_new && 0) { + disas_insn_new(s, cpu, b); + return true; + } break; case 0xf3: prefixes |= PREFIX_REPZ; diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc index 426c4594120..3fc6485d74c 100644 --- a/target/i386/tcg/decode-new.c.inc +++ b/target/i386/tcg/decode-new.c.inc @@ -1689,6 +1689,9 @@ static void disas_insn_new(DisasContext *s, CPUState *cpu, int b) X86DecodeFunc decode_func = decode_root; uint8_t cc_live; +#ifdef CONFIG_USER_ONLY + if (limit) { --limit; } +#endif s->has_modrm = false; next_byte: From patchwork Tue Apr 9 16:43:10 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 13622959 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 99A93CD1297 for ; Tue, 9 Apr 2024 16:49:52 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ruEaX-0000l2-Q2; Tue, 09 Apr 2024 12:44:51 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ruEZs-0000Vl-7L for qemu-devel@nongnu.org; Tue, 09 Apr 2024 12:44:08 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ruEZf-00082F-0U for qemu-devel@nongnu.org; Tue, 09 Apr 2024 12:44:07 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1712681026; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=jil+htFRzvf6aPlzOtZ9Y7Dok7rKW7xkrEHwvqOyfxQ=; b=HDa7I+xwDlju9hc5wLnS4X9nJsKjRTuuBxgbO1FZFAYUub2qsAexGXSGfkZT2Rn7MY1MSm I3nga2GnA6AMNQDxopyyUlc97PxMhe7rLjH0dTOMt1C7a9g9pgnaYbj04gFoAGFtJow+Kb aKZlexNqSnyacWA4WlyN4CaJNKoEktI= Received: from mail-wm1-f69.google.com (mail-wm1-f69.google.com [209.85.128.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-482-XEvuUECOM1SvrORaz4UYQw-1; Tue, 09 Apr 2024 12:43:44 -0400 X-MC-Unique: XEvuUECOM1SvrORaz4UYQw-1 Received: by mail-wm1-f69.google.com with SMTP id 5b1f17b1804b1-416612274e7so9280635e9.2 for ; Tue, 09 Apr 2024 09:43:44 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712681023; x=1713285823; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=jil+htFRzvf6aPlzOtZ9Y7Dok7rKW7xkrEHwvqOyfxQ=; b=rQq+bDJgJZCwGVWTdk3rU1oEiaOjyWFdz4zgnOhJ510/CB8qmW8wXnqjwy4ADGbn9o KTwws1UFkH0ffn+VD0AxZ2dPkVo6l7wkglOJkKTv7TI8E7Iz7REwAfnOfLUSkWdO+dnm eKjMFTc03AJfKZta6/I+ZmPKazAcw+P6DnUyK+4PYWpw1iBIGBmCh3NYvqOJcmmj3yhz WJQfOUotm8m3D6JeEX5xyFe8TVgd0p4gyw0bB8U9G8eoFDn9NWBwDJIRku03Cdj6aSjl 1T7iHRf+GzAp/y7P1UT9F+f6keurxhXX7YPJCKt38x6/DFxud6HIKn9imJs1CKFThBDn qaLA== X-Gm-Message-State: AOJu0Yw8Ubq6pCTKIN7+KeZ459/56i4nXh1xOc275t1o8A9so3ZzYfCX nakNg7ho80We79r97TpbJWddkxujxaFeUnCDGpF4xDdmyZ99w27ZGK/v0uqtB3FgSyb8MdpZH3i Kxj5bmtxA7o6mpNVZ5XM0VbBpADhYXgjQlpu3E0R8A9ywNHf+8StQ62xlhnx1xi9J3BZaYnquZx EuaBjeihjTtVOUUzmDpsz7gbf3n1bre5GA1VHR X-Received: by 2002:a05:600c:cce:b0:416:bbf8:27e7 with SMTP id fk14-20020a05600c0cce00b00416bbf827e7mr176700wmb.24.1712681022818; Tue, 09 Apr 2024 09:43:42 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGPdAMK26dmrdXahME7CjbeNJysX3y+1mqtjtfIjDpNnUK9egz4rUe0624r2pbecLecBeH2Dg== X-Received: by 2002:a05:600c:cce:b0:416:bbf8:27e7 with SMTP id fk14-20020a05600c0cce00b00416bbf827e7mr176687wmb.24.1712681022202; Tue, 09 Apr 2024 09:43:42 -0700 (PDT) Received: from avogadro.local ([151.95.152.232]) by smtp.gmail.com with ESMTPSA id bg8-20020a05600c3c8800b00414807ef8dfsm17908983wmb.5.2024.04.09.09.43.41 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 09 Apr 2024 09:43:41 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Subject: [PATCH for-9.1 06/19] target/i386: move 00-5F opcodes to new decoder Date: Tue, 9 Apr 2024 18:43:10 +0200 Message-ID: <20240409164323.776660-7-pbonzini@redhat.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240409164323.776660-1-pbonzini@redhat.com> References: <20240409164323.776660-1-pbonzini@redhat.com> MIME-Version: 1.0 Received-SPF: pass client-ip=170.10.133.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -37 X-Spam_score: -3.8 X-Spam_bar: --- X-Spam_report: (-3.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1.701, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, T_SPF_TEMPERROR=0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Signed-off-by: Paolo Bonzini Reviewed-by: Richard Henderson --- target/i386/tcg/translate.c | 2 +- target/i386/tcg/decode-new.c.inc | 120 ++++++++++++++++++ target/i386/tcg/emit.c.inc | 202 +++++++++++++++++++++++++++++++ 3 files changed, 323 insertions(+), 1 deletion(-) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 2a372842db4..e501d4701b6 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -3148,7 +3148,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu) #ifndef CONFIG_USER_ONLY use_new &= b <= limit; #endif - if (use_new && 0) { + if (use_new && b <= 0x5f) { disas_insn_new(s, cpu, b); return true; } diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc index 3fc6485d74c..1e792426ff5 100644 --- a/target/i386/tcg/decode-new.c.inc +++ b/target/i386/tcg/decode-new.c.inc @@ -121,6 +121,8 @@ #define X86_OP_GROUP2(op, op0, s0, op1, s1, ...) \ X86_OP_GROUP3(op, op0, s0, 2op, s0, op1, s1, ## __VA_ARGS__) +#define X86_OP_GROUPw(op, op0, s0, ...) \ + X86_OP_GROUP3(op, op0, s0, None, None, None, None, ## __VA_ARGS__) #define X86_OP_GROUP0(op, ...) \ X86_OP_GROUP3(op, None, None, None, None, None, None, ## __VA_ARGS__) @@ -140,12 +142,23 @@ .op3 = X86_TYPE_I, .s3 = X86_SIZE_b, \ ## __VA_ARGS__) +/* + * Short forms that are mostly useful for ALU opcodes and other + * one-byte opcodes. For vector instructions it is usually + * clearer to write all three operands explicitly, because the + * corresponding gen_* function will use OP_PTRn rather than s->T0 + * and s->T1. + */ +#define X86_OP_ENTRYrr(op, op0, s0, op1, s1, ...) \ + X86_OP_ENTRY3(op, None, None, op0, s0, op1, s1, ## __VA_ARGS__) #define X86_OP_ENTRY2(op, op0, s0, op1, s1, ...) \ X86_OP_ENTRY3(op, op0, s0, 2op, s0, op1, s1, ## __VA_ARGS__) #define X86_OP_ENTRYw(op, op0, s0, ...) \ X86_OP_ENTRY3(op, op0, s0, None, None, None, None, ## __VA_ARGS__) #define X86_OP_ENTRYr(op, op0, s0, ...) \ X86_OP_ENTRY3(op, None, None, None, None, op0, s0, ## __VA_ARGS__) +#define X86_OP_ENTRY1(op, op0, s0, ...) \ + X86_OP_ENTRY3(op, op0, s0, 2op, s0, None, None, ## __VA_ARGS__) #define X86_OP_ENTRY0(op, ...) \ X86_OP_ENTRY3(op, None, None, None, None, None, None, ## __VA_ARGS__) @@ -1096,7 +1109,114 @@ static void decode_0F(DisasContext *s, CPUX86State *env, X86OpEntry *entry, uint } static const X86OpEntry opcodes_root[256] = { + [0x00] = X86_OP_ENTRY2(ADD, E,b, G,b, lock), + [0x01] = X86_OP_ENTRY2(ADD, E,v, G,v, lock), + [0x02] = X86_OP_ENTRY2(ADD, G,b, E,b, lock), + [0x03] = X86_OP_ENTRY2(ADD, G,v, E,v, lock), + [0x04] = X86_OP_ENTRY2(ADD, 0,b, I,b, lock), /* AL, Ib */ + [0x05] = X86_OP_ENTRY2(ADD, 0,v, I,z, lock), /* rAX, Iz */ + [0x06] = X86_OP_ENTRYr(PUSH, ES, w, chk(i64)), + [0x07] = X86_OP_ENTRYw(POP, ES, w, chk(i64)), + + [0x10] = X86_OP_ENTRY2(ADC, E,b, G,b, lock), + [0x11] = X86_OP_ENTRY2(ADC, E,v, G,v, lock), + [0x12] = X86_OP_ENTRY2(ADC, G,b, E,b, lock), + [0x13] = X86_OP_ENTRY2(ADC, G,v, E,v, lock), + [0x14] = X86_OP_ENTRY2(ADC, 0,b, I,b, lock), /* AL, Ib */ + [0x15] = X86_OP_ENTRY2(ADC, 0,v, I,z, lock), /* rAX, Iz */ + [0x16] = X86_OP_ENTRYr(PUSH, SS, w, chk(i64)), + [0x17] = X86_OP_ENTRYw(POP, SS, w, chk(i64)), + + [0x20] = X86_OP_ENTRY2(AND, E,b, G,b, lock), + [0x21] = X86_OP_ENTRY2(AND, E,v, G,v, lock), + [0x22] = X86_OP_ENTRY2(AND, G,b, E,b, lock), + [0x23] = X86_OP_ENTRY2(AND, G,v, E,v, lock), + [0x24] = X86_OP_ENTRY2(AND, 0,b, I,b, lock), /* AL, Ib */ + [0x25] = X86_OP_ENTRY2(AND, 0,v, I,z, lock), /* rAX, Iz */ + [0x26] = {}, + [0x27] = X86_OP_ENTRY0(DAA, chk(i64)), + + [0x30] = X86_OP_ENTRY2(XOR, E,b, G,b, lock), + [0x31] = X86_OP_ENTRY2(XOR, E,v, G,v, lock), + [0x32] = X86_OP_ENTRY2(XOR, G,b, E,b, lock), + [0x33] = X86_OP_ENTRY2(XOR, G,v, E,v, lock), + [0x34] = X86_OP_ENTRY2(XOR, 0,b, I,b, lock), /* AL, Ib */ + [0x35] = X86_OP_ENTRY2(XOR, 0,v, I,z, lock), /* rAX, Iz */ + [0x36] = {}, + [0x37] = X86_OP_ENTRY0(AAA, chk(i64)), + + [0x40] = X86_OP_ENTRY1(INC, 0,v, chk(i64)), + [0x41] = X86_OP_ENTRY1(INC, 1,v, chk(i64)), + [0x42] = X86_OP_ENTRY1(INC, 2,v, chk(i64)), + [0x43] = X86_OP_ENTRY1(INC, 3,v, chk(i64)), + [0x44] = X86_OP_ENTRY1(INC, 4,v, chk(i64)), + [0x45] = X86_OP_ENTRY1(INC, 5,v, chk(i64)), + [0x46] = X86_OP_ENTRY1(INC, 6,v, chk(i64)), + [0x47] = X86_OP_ENTRY1(INC, 7,v, chk(i64)), + + [0x50] = X86_OP_ENTRYr(PUSH, LoBits,d64), + [0x51] = X86_OP_ENTRYr(PUSH, LoBits,d64), + [0x52] = X86_OP_ENTRYr(PUSH, LoBits,d64), + [0x53] = X86_OP_ENTRYr(PUSH, LoBits,d64), + [0x54] = X86_OP_ENTRYr(PUSH, LoBits,d64), + [0x55] = X86_OP_ENTRYr(PUSH, LoBits,d64), + [0x56] = X86_OP_ENTRYr(PUSH, LoBits,d64), + [0x57] = X86_OP_ENTRYr(PUSH, LoBits,d64), + + + [0x08] = X86_OP_ENTRY2(OR, E,b, G,b, lock), + [0x09] = X86_OP_ENTRY2(OR, E,v, G,v, lock), + [0x0A] = X86_OP_ENTRY2(OR, G,b, E,b, lock), + [0x0B] = X86_OP_ENTRY2(OR, G,v, E,v, lock), + [0x0C] = X86_OP_ENTRY2(OR, 0,b, I,b, lock), /* AL, Ib */ + [0x0D] = X86_OP_ENTRY2(OR, 0,v, I,z, lock), /* rAX, Iz */ + [0x0E] = X86_OP_ENTRYr(PUSH, CS, w, chk(i64)), [0x0F] = X86_OP_GROUP0(0F), + + [0x18] = X86_OP_ENTRY2(SBB, E,b, G,b, lock), + [0x19] = X86_OP_ENTRY2(SBB, E,v, G,v, lock), + [0x1A] = X86_OP_ENTRY2(SBB, G,b, E,b, lock), + [0x1B] = X86_OP_ENTRY2(SBB, G,v, E,v, lock), + [0x1C] = X86_OP_ENTRY2(SBB, 0,b, I,b, lock), /* AL, Ib */ + [0x1D] = X86_OP_ENTRY2(SBB, 0,v, I,z, lock), /* rAX, Iz */ + [0x1E] = X86_OP_ENTRYr(PUSH, DS, w, chk(i64)), + [0x1F] = X86_OP_ENTRYw(POP, DS, w, chk(i64)), + + [0x28] = X86_OP_ENTRY2(SUB, E,b, G,b, lock), + [0x29] = X86_OP_ENTRY2(SUB, E,v, G,v, lock), + [0x2A] = X86_OP_ENTRY2(SUB, G,b, E,b, lock), + [0x2B] = X86_OP_ENTRY2(SUB, G,v, E,v, lock), + [0x2C] = X86_OP_ENTRY2(SUB, 0,b, I,b, lock), /* AL, Ib */ + [0x2D] = X86_OP_ENTRY2(SUB, 0,v, I,z, lock), /* rAX, Iz */ + [0x2E] = {}, + [0x2F] = X86_OP_ENTRY0(DAS, chk(i64)), + + [0x38] = X86_OP_ENTRYrr(SUB, E,b, G,b), + [0x39] = X86_OP_ENTRYrr(SUB, E,v, G,v), + [0x3A] = X86_OP_ENTRYrr(SUB, G,b, E,b), + [0x3B] = X86_OP_ENTRYrr(SUB, G,v, E,v), + [0x3C] = X86_OP_ENTRYrr(SUB, 0,b, I,b), /* AL, Ib */ + [0x3D] = X86_OP_ENTRYrr(SUB, 0,v, I,z), /* rAX, Iz */ + [0x3E] = {}, + [0x3F] = X86_OP_ENTRY0(AAS, chk(i64)), + + [0x48] = X86_OP_ENTRY1(DEC, 0,v, chk(i64)), + [0x49] = X86_OP_ENTRY1(DEC, 1,v, chk(i64)), + [0x4A] = X86_OP_ENTRY1(DEC, 2,v, chk(i64)), + [0x4B] = X86_OP_ENTRY1(DEC, 3,v, chk(i64)), + [0x4C] = X86_OP_ENTRY1(DEC, 4,v, chk(i64)), + [0x4D] = X86_OP_ENTRY1(DEC, 5,v, chk(i64)), + [0x4E] = X86_OP_ENTRY1(DEC, 6,v, chk(i64)), + [0x4F] = X86_OP_ENTRY1(DEC, 7,v, chk(i64)), + + [0x58] = X86_OP_ENTRYw(POP, LoBits,d64), + [0x59] = X86_OP_ENTRYw(POP, LoBits,d64), + [0x5A] = X86_OP_ENTRYw(POP, LoBits,d64), + [0x5B] = X86_OP_ENTRYw(POP, LoBits,d64), + [0x5C] = X86_OP_ENTRYw(POP, LoBits,d64), + [0x5D] = X86_OP_ENTRYw(POP, LoBits,d64), + [0x5E] = X86_OP_ENTRYw(POP, LoBits,d64), + [0x5F] = X86_OP_ENTRYw(POP, LoBits,d64), }; #undef mmx diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc index 0e00f6635dd..a64186b8957 100644 --- a/target/i386/tcg/emit.c.inc +++ b/target/i386/tcg/emit.c.inc @@ -352,6 +352,20 @@ static void prepare_update2_cc(X86DecodedInsn *decode, DisasContext *s, CCOp op) decode->cc_op = op; } +static void prepare_update_cc_incdec(X86DecodedInsn *decode, DisasContext *s, CCOp op) +{ + gen_compute_eflags_c(s, s->T1); + prepare_update2_cc(decode, s, op); +} + +static void prepare_update3_cc(X86DecodedInsn *decode, DisasContext *s, CCOp op, TCGv reg) +{ + decode->cc_src2 = reg; + decode->cc_src = s->T1; + decode->cc_dst = s->T0; + decode->cc_op = op; +} + static void gen_store_sse(DisasContext *s, X86DecodedInsn *decode, int src_ofs) { MemOp ot = decode->op[0].ot; @@ -1040,6 +1054,37 @@ static void gen_##uname(DisasContext *s, CPUX86State *env, X86DecodedInsn *decod VSIB_AVX(VPGATHERD, vpgatherd) VSIB_AVX(VPGATHERQ, vpgatherq) +static void gen_AAA(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + gen_update_cc_op(s); + gen_helper_aaa(tcg_env); + set_cc_op(s, CC_OP_EFLAGS); +} + +static void gen_AAS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + gen_update_cc_op(s); + gen_helper_aas(tcg_env); + set_cc_op(s, CC_OP_EFLAGS); +} + +static void gen_ADC(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + MemOp ot = decode->op[1].ot; + TCGv c_in = tcg_temp_new(); + + gen_compute_eflags_c(s, c_in); + if (s->prefix & PREFIX_LOCK) { + tcg_gen_add_tl(s->T0, c_in, s->T1); + tcg_gen_atomic_add_fetch_tl(s->T0, s->A0, s->T0, + s->mem_index, ot | MO_LE); + } else { + tcg_gen_add_tl(s->T0, s->T0, s->T1); + tcg_gen_add_tl(s->T0, s->T0, c_in); + } + prepare_update3_cc(decode, s, CC_OP_ADCB + ot, c_in); +} + /* ADCX/ADOX do not have memory operands and can use set_cc_op. */ static void gen_ADCOX(DisasContext *s, CPUX86State *env, MemOp ot, int cc_op) { @@ -1093,11 +1138,37 @@ static void gen_ADCX(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) gen_ADCOX(s, env, decode->op[0].ot, CC_OP_ADCX); } +static void gen_ADD(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + MemOp ot = decode->op[1].ot; + + if (s->prefix & PREFIX_LOCK) { + tcg_gen_atomic_add_fetch_tl(s->T0, s->A0, s->T1, + s->mem_index, ot | MO_LE); + } else { + tcg_gen_add_tl(s->T0, s->T0, s->T1); + } + prepare_update2_cc(decode, s, CC_OP_ADDB + ot); +} + static void gen_ADOX(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { gen_ADCOX(s, env, decode->op[0].ot, CC_OP_ADOX); } +static void gen_AND(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + MemOp ot = decode->op[1].ot; + + if (s->prefix & PREFIX_LOCK) { + tcg_gen_atomic_and_fetch_tl(s->T0, s->A0, s->T1, + s->mem_index, ot | MO_LE); + } else { + tcg_gen_and_tl(s->T0, s->T0, s->T1); + } + prepare_update1_cc(decode, s, CC_OP_LOGICB + ot); +} + static void gen_ANDN(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { MemOp ot = decode->op[0].ot; @@ -1331,6 +1402,34 @@ static void gen_CVTTPx2PI(DisasContext *s, CPUX86State *env, X86DecodedInsn *dec } } +static void gen_DAA(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + gen_update_cc_op(s); + gen_helper_daa(tcg_env); + set_cc_op(s, CC_OP_EFLAGS); +} + +static void gen_DAS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + gen_update_cc_op(s); + gen_helper_das(tcg_env); + set_cc_op(s, CC_OP_EFLAGS); +} + +static void gen_DEC(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + MemOp ot = decode->op[1].ot; + + tcg_gen_movi_tl(s->T1, -1); + if (s->prefix & PREFIX_LOCK) { + tcg_gen_atomic_add_fetch_tl(s->T0, s->A0, s->T1, + s->mem_index, ot | MO_LE); + } else { + tcg_gen_add_tl(s->T0, s->T0, s->T1); + } + prepare_update_cc_incdec(decode, s, CC_OP_DECB + ot); +} + static void gen_EMMS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { gen_helper_emms(tcg_env); @@ -1349,6 +1448,20 @@ static void gen_EXTRQ_r(DisasContext *s, CPUX86State *env, X86DecodedInsn *decod gen_helper_extrq_r(tcg_env, OP_PTR0, OP_PTR2); } +static void gen_INC(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + MemOp ot = decode->op[1].ot; + + tcg_gen_movi_tl(s->T1, 1); + if (s->prefix & PREFIX_LOCK) { + tcg_gen_atomic_add_fetch_tl(s->T0, s->A0, s->T1, + s->mem_index, ot | MO_LE); + } else { + tcg_gen_add_tl(s->T0, s->T0, s->T1); + } + prepare_update_cc_incdec(decode, s, CC_OP_INCB + ot); +} + static void gen_INSERTQ_i(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { TCGv_i32 length = tcg_constant_i32(decode->immediate & 63); @@ -1501,6 +1614,19 @@ static void gen_MULX(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) } } +static void gen_OR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + MemOp ot = decode->op[1].ot; + + if (s->prefix & PREFIX_LOCK) { + tcg_gen_atomic_or_fetch_tl(s->T0, s->A0, s->T1, + s->mem_index, ot | MO_LE); + } else { + tcg_gen_or_tl(s->T0, s->T0, s->T1); + } + prepare_update1_cc(decode, s, CC_OP_LOGICB + ot); +} + static void gen_PALIGNR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { TCGv_i32 imm = tcg_constant8u_i32(decode->immediate); @@ -1744,6 +1870,18 @@ static void gen_PMOVMSKB(DisasContext *s, CPUX86State *env, X86DecodedInsn *deco } } +static void gen_POP(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + MemOp ot = gen_pop_T0(s); + if (decode->op[0].has_ea) { + /* NOTE: order is important for MMU exceptions */ + gen_op_st_v(s, ot, s->T0, s->A0); + decode->op[0].unit = X86_OP_SKIP; + } + /* NOTE: writing back registers after update is important for pop %sp */ + gen_pop_update(s, ot); +} + static void gen_PSHUFW(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { TCGv_i32 imm = tcg_constant8u_i32(decode->immediate); @@ -1890,6 +2028,11 @@ static void gen_PSLLDQ_i(DisasContext *s, CPUX86State *env, X86DecodedInsn *deco } } +static void gen_PUSH(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + gen_push_v(s, s->T1); +} + static void gen_RORX(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { MemOp ot = decode->op[0].ot; @@ -1924,6 +2067,28 @@ static void gen_SARX(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) tcg_gen_sar_tl(s->T0, s->T0, s->T1); } +static void gen_SBB(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + MemOp ot = decode->op[0].ot; + TCGv c_in = tcg_temp_new(); + + gen_compute_eflags_c(s, c_in); + if (s->prefix & PREFIX_LOCK) { + tcg_gen_add_tl(s->T0, s->T1, c_in); + tcg_gen_neg_tl(s->T0, s->T0); + tcg_gen_atomic_add_fetch_tl(s->T0, s->A0, s->T0, + s->mem_index, ot | MO_LE); + } else { + /* + * TODO: SBB reg, reg could use gen_prepare_eflags_c followed by + * negsetcond, and CC_OP_SUBB as the cc_op. + */ + tcg_gen_sub_tl(s->T0, s->T0, s->T1); + tcg_gen_sub_tl(s->T0, s->T0, c_in); + } + prepare_update3_cc(decode, s, CC_OP_SBBB + ot, c_in); +} + static void gen_SHA1NEXTE(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { gen_helper_sha1nexte(OP_PTR0, OP_PTR1, OP_PTR2); @@ -2011,6 +2176,22 @@ static void gen_STMXCSR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decod tcg_gen_ld32u_tl(s->T0, tcg_env, offsetof(CPUX86State, mxcsr)); } +static void gen_SUB(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + MemOp ot = decode->op[1].ot; + + if (s->prefix & PREFIX_LOCK) { + tcg_gen_neg_tl(s->T0, s->T1); + tcg_gen_atomic_fetch_add_tl(s->cc_srcT, s->A0, s->T0, + s->mem_index, ot | MO_LE); + tcg_gen_sub_tl(s->T0, s->cc_srcT, s->T1); + } else { + tcg_gen_mov_tl(s->cc_srcT, s->T0); + tcg_gen_sub_tl(s->T0, s->T0, s->T1); + } + prepare_update2_cc(decode, s, CC_OP_SUBB + ot); +} + static void gen_VAESIMC(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { assert(!s->vex_l); @@ -2490,3 +2671,24 @@ static void gen_VZEROUPPER(DisasContext *s, CPUX86State *env, X86DecodedInsn *de tcg_gen_gvec_dup_imm(MO_64, offset, 16, 16, 0); } } + +static void gen_XOR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + /* special case XOR reg, reg */ + if (decode->op[1].unit == X86_OP_INT && + decode->op[2].unit == X86_OP_INT && + decode->op[1].n == decode->op[2].n) { + tcg_gen_movi_tl(s->T0, 0); + decode->cc_op = CC_OP_CLR; + } else { + MemOp ot = decode->op[1].ot; + + if (s->prefix & PREFIX_LOCK) { + tcg_gen_atomic_xor_fetch_tl(s->T0, s->A0, s->T1, + s->mem_index, ot | MO_LE); + } else { + tcg_gen_xor_tl(s->T0, s->T0, s->T1); + } + prepare_update1_cc(decode, s, CC_OP_LOGICB + ot); + } +} From patchwork Tue Apr 9 16:43:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 13622952 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id C44ACCD1297 for ; Tue, 9 Apr 2024 16:46:52 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ruEa6-0000d2-Od; Tue, 09 Apr 2024 12:44:22 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ruEa0-0000ac-Jk for qemu-devel@nongnu.org; Tue, 09 Apr 2024 12:44:18 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ruEZh-00082c-OV for qemu-devel@nongnu.org; Tue, 09 Apr 2024 12:44:16 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1712681029; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=EDRyAYQEO1VEJbNs8swUTPMQb7B504Kpjs1Z+adXy3k=; b=UPsWgdhvp6q7k/xky2UqiuzaUQEfz0NzfE8+djBNCDcvDDobnRSnzt+cb26UrjzQ/b7ERO pZJlInT7Lgmtu2Fhib195wJHnfexwMVqzBcOGii+tlxt+2f0Magacn2ZaRz6NlvWSCAIyG m8XdVRPjSMdCYCUikcosnv+dP59Eit8= Received: from mail-wm1-f71.google.com (mail-wm1-f71.google.com [209.85.128.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-630-dn70Q0enP3C1VJbkrFHPng-1; Tue, 09 Apr 2024 12:43:48 -0400 X-MC-Unique: dn70Q0enP3C1VJbkrFHPng-1 Received: by mail-wm1-f71.google.com with SMTP id 5b1f17b1804b1-416612274e7so9280935e9.2 for ; Tue, 09 Apr 2024 09:43:47 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712681026; x=1713285826; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=EDRyAYQEO1VEJbNs8swUTPMQb7B504Kpjs1Z+adXy3k=; b=iW1HHvi0+k16qVNTAtdODaOtIfvr9mo/CUIIzxCds6fR5xt5a2Din0WPojxRrRHZLg 9PQTw3LBh0AstxMjx8Yga6YZYA5yiM7GDpF/OtMj+/cvCOMaSM1PwTERaMplmuO6nzeo NzzIpCcOPYLZf+vKYMTunjFZL8Oy5rlEVKCjOG4DLl7cluaAtFuJuni91jeE7iUfRj1u JHETGvKVXRnJJJEKgj2tBSDvWYcQFVC3+qVFGNs2VLeXITdEIQfr0ji+tkzunaC0KhzY KaKRZ8xTj/EtYlDMHPNiNxPxjvdwg8AmSzhsmbtxtoSmXXcZBBRi+z/VQI6OEFe3KMG8 VXDw== X-Gm-Message-State: AOJu0YzagYv3srqtWzYrry15ikU5d7vCrs0vHHKMyAPLNEyF8095mcz+ ypH1Xi5KzQ8B09iTC24oam+8k3vcDHArHLcIzZ/maDsIi+inugeIK+FzFrkDfh2d1YbB9ybtEUw UHk8JDqDpWJYjeQ+76M11va654dUq9O04W6C3yrM3Dy24yybszzTtP/1zAm8KvjMn10nFL3YzK0 S7FLPLo1nrNeTsIApyx5+zRfQ+YDpUQIaUqKq6 X-Received: by 2002:a05:600c:444d:b0:416:9877:e1a2 with SMTP id v13-20020a05600c444d00b004169877e1a2mr206971wmn.3.1712681026188; Tue, 09 Apr 2024 09:43:46 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEjKqo/yrOqYAjO22SCtomCl9KEwkp/fpBxwgeFyShCnwGNGrI0u2OWDakWonirUftwb16YFQ== X-Received: by 2002:a05:600c:444d:b0:416:9877:e1a2 with SMTP id v13-20020a05600c444d00b004169877e1a2mr206958wmn.3.1712681025761; Tue, 09 Apr 2024 09:43:45 -0700 (PDT) Received: from avogadro.local ([151.95.152.232]) by smtp.gmail.com with ESMTPSA id l35-20020a05600c1d2300b0041680911b0fsm6902271wms.30.2024.04.09.09.43.44 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 09 Apr 2024 09:43:44 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Subject: [PATCH for-9.1 07/19] target/i386: extract gen_far_call/jmp, reordering temporaries Date: Tue, 9 Apr 2024 18:43:11 +0200 Message-ID: <20240409164323.776660-8-pbonzini@redhat.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240409164323.776660-1-pbonzini@redhat.com> References: <20240409164323.776660-1-pbonzini@redhat.com> MIME-Version: 1.0 Received-SPF: pass client-ip=170.10.133.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -37 X-Spam_score: -3.8 X-Spam_bar: --- X-Spam_report: (-3.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1.701, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Extract the code into new functions, and swap T0/T1 so that T0 corresponds to the first immediate in the instruction stream. Signed-off-by: Paolo Bonzini Reviewed-by: Richard Henderson --- target/i386/tcg/translate.c | 93 +++++++++++++++++++++---------------- 1 file changed, 53 insertions(+), 40 deletions(-) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index e501d4701b6..c251fa21e6d 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -2518,12 +2518,13 @@ static inline void gen_op_movl_T0_seg(DisasContext *s, X86Seg seg_reg) offsetof(CPUX86State,segs[seg_reg].selector)); } -static inline void gen_op_movl_seg_T0_vm(DisasContext *s, X86Seg seg_reg) +static void gen_op_movl_seg_real(DisasContext *s, X86Seg seg_reg, TCGv seg) { - tcg_gen_ext16u_tl(s->T0, s->T0); - tcg_gen_st32_tl(s->T0, tcg_env, + TCGv selector = tcg_temp_new(); + tcg_gen_ext16u_tl(selector, seg); + tcg_gen_st32_tl(selector, tcg_env, offsetof(CPUX86State,segs[seg_reg].selector)); - tcg_gen_shli_tl(cpu_seg_base[seg_reg], s->T0, 4); + tcg_gen_shli_tl(cpu_seg_base[seg_reg], selector, 4); } /* move T0 to seg_reg and compute if the CPU state may change. Never @@ -2543,13 +2544,45 @@ static void gen_movl_seg_T0(DisasContext *s, X86Seg seg_reg) s->base.is_jmp = DISAS_EOB_NEXT; } } else { - gen_op_movl_seg_T0_vm(s, seg_reg); + gen_op_movl_seg_real(s, seg_reg, s->T0); if (seg_reg == R_SS) { s->base.is_jmp = DISAS_EOB_INHIBIT_IRQ; } } } +static void gen_far_call(DisasContext *s) +{ + TCGv_i32 new_cs = tcg_temp_new_i32(); + tcg_gen_trunc_tl_i32(new_cs, s->T1); + if (PE(s) && !VM86(s)) { + gen_helper_lcall_protected(tcg_env, new_cs, s->T0, + tcg_constant_i32(s->dflag - 1), + eip_next_tl(s)); + } else { + TCGv_i32 new_eip = tcg_temp_new_i32(); + tcg_gen_trunc_tl_i32(new_eip, s->T0); + gen_helper_lcall_real(tcg_env, new_cs, new_eip, + tcg_constant_i32(s->dflag - 1), + eip_next_i32(s)); + } + s->base.is_jmp = DISAS_JUMP; +} + +static void gen_far_jmp(DisasContext *s) +{ + if (PE(s) && !VM86(s)) { + TCGv_i32 new_cs = tcg_temp_new_i32(); + tcg_gen_trunc_tl_i32(new_cs, s->T1); + gen_helper_ljmp_protected(tcg_env, new_cs, s->T0, + eip_next_tl(s)); + } else { + gen_op_movl_seg_real(s, R_CS, s->T1); + gen_op_jmp_v(s, s->T0); + } + s->base.is_jmp = DISAS_JUMP; +} + static void gen_svm_check_intercept(DisasContext *s, uint32_t type) { /* no SVM activated; fast case */ @@ -3656,23 +3689,10 @@ static bool disas_insn(DisasContext *s, CPUState *cpu) if (mod == 3) { goto illegal_op; } - gen_op_ld_v(s, ot, s->T1, s->A0); + gen_op_ld_v(s, ot, s->T0, s->A0); gen_add_A0_im(s, 1 << ot); - gen_op_ld_v(s, MO_16, s->T0, s->A0); - do_lcall: - if (PE(s) && !VM86(s)) { - tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); - gen_helper_lcall_protected(tcg_env, s->tmp2_i32, s->T1, - tcg_constant_i32(dflag - 1), - eip_next_tl(s)); - } else { - tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); - tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1); - gen_helper_lcall_real(tcg_env, s->tmp2_i32, s->tmp3_i32, - tcg_constant_i32(dflag - 1), - eip_next_i32(s)); - } - s->base.is_jmp = DISAS_JUMP; + gen_op_ld_v(s, MO_16, s->T1, s->A0); + gen_far_call(s); break; case 4: /* jmp Ev */ if (dflag == MO_16) { @@ -3686,19 +3706,10 @@ static bool disas_insn(DisasContext *s, CPUState *cpu) if (mod == 3) { goto illegal_op; } - gen_op_ld_v(s, ot, s->T1, s->A0); + gen_op_ld_v(s, ot, s->T0, s->A0); gen_add_A0_im(s, 1 << ot); - gen_op_ld_v(s, MO_16, s->T0, s->A0); - do_ljmp: - if (PE(s) && !VM86(s)) { - tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); - gen_helper_ljmp_protected(tcg_env, s->tmp2_i32, s->T1, - eip_next_tl(s)); - } else { - gen_op_movl_seg_T0_vm(s, R_CS); - gen_op_jmp_v(s, s->T1); - } - s->base.is_jmp = DISAS_JUMP; + gen_op_ld_v(s, MO_16, s->T1, s->A0); + gen_far_jmp(s); break; case 6: /* push Ev */ gen_push_v(s, s->T0); @@ -5138,7 +5149,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu) /* pop selector */ gen_add_A0_im(s, 1 << dflag); gen_op_ld_v(s, dflag, s->T0, s->A0); - gen_op_movl_seg_T0_vm(s, R_CS); + gen_op_movl_seg_real(s, R_CS, s->T0); /* add stack offset */ gen_stack_update(s, val + (2 << dflag)); } @@ -5182,10 +5193,11 @@ static bool disas_insn(DisasContext *s, CPUState *cpu) offset = insn_get(env, s, ot); selector = insn_get(env, s, MO_16); - tcg_gen_movi_tl(s->T0, selector); - tcg_gen_movi_tl(s->T1, offset); + tcg_gen_movi_tl(s->T0, offset); + tcg_gen_movi_tl(s->T1, selector); } - goto do_lcall; + gen_far_call(s); + break; case 0xe9: /* jmp im */ { int diff = (dflag != MO_16 @@ -5205,10 +5217,11 @@ static bool disas_insn(DisasContext *s, CPUState *cpu) offset = insn_get(env, s, ot); selector = insn_get(env, s, MO_16); - tcg_gen_movi_tl(s->T0, selector); - tcg_gen_movi_tl(s->T1, offset); + tcg_gen_movi_tl(s->T0, offset); + tcg_gen_movi_tl(s->T1, selector); } - goto do_ljmp; + gen_far_jmp(s); + break; case 0xeb: /* jmp Jb */ { int diff = (int8_t)insn_get(env, s, MO_8); From patchwork Tue Apr 9 16:43:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 13622953 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id EA969CD128A for ; Tue, 9 Apr 2024 16:47:07 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ruEaY-0000mR-UN; Tue, 09 Apr 2024 12:44:50 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ruEa0-0000aK-Gg for qemu-devel@nongnu.org; Tue, 09 Apr 2024 12:44:16 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ruEZh-000838-1h for qemu-devel@nongnu.org; Tue, 09 Apr 2024 12:44:13 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1712681032; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=tJUYhX/+ukGLYf+DwUCr8Vts+Fg0GPkTuEhT/LD1lYg=; b=QEGFmfHjoJt0qz0HR7erIrzN8MjajTGhdpoBwdivgQpNhlrTtjPed1KmJ21aj/qcdzRdsQ HwemZoWpD5ABdOnsbzT+4thDi6pW5L/mEWSqcModz4BE0nhL0WDPvR2dZYVhRkbtWmP+Fq V+yjQHmy5c5edCjFo1fU/r5eikh8Wyc= Received: from mail-wm1-f69.google.com (mail-wm1-f69.google.com [209.85.128.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-261-aCiibbLOPMKCby_yQW2TKw-1; Tue, 09 Apr 2024 12:43:50 -0400 X-MC-Unique: aCiibbLOPMKCby_yQW2TKw-1 Received: by mail-wm1-f69.google.com with SMTP id 5b1f17b1804b1-416b91d1328so2313045e9.0 for ; Tue, 09 Apr 2024 09:43:50 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712681029; x=1713285829; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=tJUYhX/+ukGLYf+DwUCr8Vts+Fg0GPkTuEhT/LD1lYg=; b=bduxPTmzIMx2w68Iw769wnzOWevqgDG1qj82QyLOn7NQ9Yr7q9avms0MAFJ0XGE1M8 SxX197iCRrFWqq9B2AOMu4uDkDvECaRTv17KWtzaMkixKSLPIBJe8F23oMlIHuJoNe7Q gR8X+dk0yr2+3AwOWZ2Ye4NIagmVDrAbnjF2UiXpjEv0IcPcrk3omZBu2SEP+bTfDPJU KKrTNXcyloKHUdFUkb2h+6G4jqi5suyC7GxT2suPPElWrTda2QAQNXuiJobhUhy8iUtq 0EQTNIJ3rOYirXKR6VqhH9RFwdqKlq1puS/bd5slII5dSOQdY4F96ugF+7TRpmQ1ZOp0 +uaA== X-Gm-Message-State: AOJu0Yz+6Aq0XQLEIkN1XtSxDOyNb7Hk08Enn+W8zz+21IWQ8m3q72Ck yBZbQ0L+wdC3heOv3cdfAjGeuoA1Dq+CwzLIPhgjKRYH9zKSi4U60gBGn4HFumrdh6B913hPP6W lyUWMgi1hFogUPWj7kUT/qD8xJ/eHTNDRpxmhnWnTdQGYfPELar7Jo37ybuldiy6y2Z9hzLNRbt 3Ar1ztcCvDKOMcgtgik7bz5DCHNmb/FqiwdBVt X-Received: by 2002:a5d:64e9:0:b0:343:4c4a:2a8b with SMTP id g9-20020a5d64e9000000b003434c4a2a8bmr228921wri.34.1712681028806; Tue, 09 Apr 2024 09:43:48 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGrQM9GH1p2cO6CLeDiOoCxWxyRoseISnG3AB49lOxYRHZJbVXX0t00ZdRaZiqW7HN7A6mFyA== X-Received: by 2002:a5d:64e9:0:b0:343:4c4a:2a8b with SMTP id g9-20020a5d64e9000000b003434c4a2a8bmr228910wri.34.1712681028514; Tue, 09 Apr 2024 09:43:48 -0700 (PDT) Received: from avogadro.local ([151.95.152.232]) by smtp.gmail.com with ESMTPSA id c11-20020adffb4b000000b00345bcb4fdb9sm5206475wrs.16.2024.04.09.09.43.47 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 09 Apr 2024 09:43:47 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Subject: [PATCH for-9.1 08/19] target/i386: allow instructions with more than one immediate Date: Tue, 9 Apr 2024 18:43:12 +0200 Message-ID: <20240409164323.776660-9-pbonzini@redhat.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240409164323.776660-1-pbonzini@redhat.com> References: <20240409164323.776660-1-pbonzini@redhat.com> MIME-Version: 1.0 Received-SPF: pass client-ip=170.10.129.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -37 X-Spam_score: -3.8 X-Spam_bar: --- X-Spam_report: (-3.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1.701, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org While keeping decode->immediate for convenience and for 4-operand instructions, store the immediate in X86DecodedOp as well. This enables instructions with more than one immediate such as ENTER. It can also be used for far calls and jumps. Signed-off-by: Paolo Bonzini Reviewed-by: Richard Henderson --- target/i386/tcg/decode-new.h | 17 ++++++++++++----- target/i386/tcg/decode-new.c.inc | 2 +- target/i386/tcg/emit.c.inc | 4 +++- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/target/i386/tcg/decode-new.h b/target/i386/tcg/decode-new.h index 15e6bfef4b1..8ffde8d1cd6 100644 --- a/target/i386/tcg/decode-new.h +++ b/target/i386/tcg/decode-new.h @@ -271,16 +271,23 @@ typedef struct X86DecodedOp { bool has_ea; int offset; /* For MMX and SSE */ - /* - * This field is used internally by macros OP0_PTR/OP1_PTR/OP2_PTR, - * do not access directly! - */ - TCGv_ptr v_ptr; + union { + target_ulong imm; + /* + * This field is used internally by macros OP0_PTR/OP1_PTR/OP2_PTR, + * do not access directly! + */ + TCGv_ptr v_ptr; + }; } X86DecodedOp; struct X86DecodedInsn { X86OpEntry e; X86DecodedOp op[3]; + /* + * Rightmost immediate, for convenience since most instructions have + * one (and also for 4-operand instructions). + */ target_ulong immediate; AddressParts mem; diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc index 1e792426ff5..c6fd7a053bd 100644 --- a/target/i386/tcg/decode-new.c.inc +++ b/target/i386/tcg/decode-new.c.inc @@ -1473,7 +1473,7 @@ static bool decode_op(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode, case X86_TYPE_I: /* Immediate */ case X86_TYPE_J: /* Relative offset for a jump */ op->unit = X86_OP_IMM; - decode->immediate = insn_get_signed(env, s, op->ot); + decode->immediate = op->imm = insn_get_signed(env, s, op->ot); break; case X86_TYPE_L: /* The upper 4 bits of the immediate select a 128-bit register */ diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc index a64186b8957..a27d3040e03 100644 --- a/target/i386/tcg/emit.c.inc +++ b/target/i386/tcg/emit.c.inc @@ -259,7 +259,7 @@ static void gen_load(DisasContext *s, X86DecodedInsn *decode, int opn, TCGv v) } break; case X86_OP_IMM: - tcg_gen_movi_tl(v, decode->immediate); + tcg_gen_movi_tl(v, op->imm); break; case X86_OP_MMX: @@ -283,6 +283,8 @@ static void gen_load(DisasContext *s, X86DecodedInsn *decode, int opn, TCGv v) static TCGv_ptr op_ptr(X86DecodedInsn *decode, int opn) { X86DecodedOp *op = &decode->op[opn]; + + assert (op->unit == X86_OP_MMX || op->unit == X86_OP_SSE); if (op->v_ptr) { return op->v_ptr; } From patchwork Tue Apr 9 16:43:13 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 13622964 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 36405CD129A for ; Tue, 9 Apr 2024 16:51:14 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ruEaf-00016b-DM; Tue, 09 Apr 2024 12:44:57 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ruEa5-0000cp-Ra for qemu-devel@nongnu.org; Tue, 09 Apr 2024 12:44:22 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ruEZi-00083f-Ou for qemu-devel@nongnu.org; Tue, 09 Apr 2024 12:44:21 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1712681036; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=H7kuvGUyNjF9Gk7QruTz9vwv2t8JzBSenWQmIxkLMMI=; b=GHTuIXT2RybufTP2nlVNsC0VZQw8e7Ozf0zHSBQ0uOg39nDjW7CwonHfzj3YQrgF/fZ+Kr l93LqIOepGTm0OgsBg1inrBZiW/LcIhNZgT7ICb7qL828Ae2C6dwMc6+WCUCrR7SL99tsj W7OdP6mNQRM+AZQyJluovGImVoHP4Y4= Received: from mail-wm1-f69.google.com (mail-wm1-f69.google.com [209.85.128.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-642-4wchsIyyMxSfCvsW8db1Ig-1; Tue, 09 Apr 2024 12:43:54 -0400 X-MC-Unique: 4wchsIyyMxSfCvsW8db1Ig-1 Received: by mail-wm1-f69.google.com with SMTP id 5b1f17b1804b1-4154f2b314cso26311375e9.3 for ; Tue, 09 Apr 2024 09:43:53 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712681032; x=1713285832; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=H7kuvGUyNjF9Gk7QruTz9vwv2t8JzBSenWQmIxkLMMI=; b=FwU0yz0IpRAZHWqnytpN41A3Q6R+kHx7sw9rQdMlPpP1H7nowBVAVYTsIOoDVneGyu om3YcZ57jYWlOMA/zv1xthn3CJAZMVG4MnNkG6dNhVuHv+CcZfTO3hbtWGw5VwghP2qW BdIXK5A0pLHhS3NMAzaSYkZP9dNYp1nck4wSIqYuUB30sY9dq1UbtKWiSW05bGVvNlrt Yh9uP2MlUcKwrwGqIP9sWPXmQftUARJqwb/YaOhPqFmJiPXgOyOCBG+hL2sqwnewIjEd oLbhUQKnlpBgGAp1cKblW1R4AEcgLaBtxKZy+kf6QoqlwmEnxBBsvY1DOfj/dXX6jfwq Ndxw== X-Gm-Message-State: AOJu0Yzzi19jHkNsouLI5a3oVLofLjG1ra7Fqd6i4NcCsXioGMZZ16DO 4FhPVRglr6t4x8ZsA0LHYopFQX0PCC51kUwB2XImc8NlOCm16yskcLNmPl8Q5zuh3jG0hSzGSGd bX4SKL4qU4O9F130MbdugKoHss6tuNdGyLbkixVdK2ki4f3H3r/93EGuNoIm/cFHOyveAmpR8eK e1vsiRhf74cctDjZvj8xTqYQfAscNKMYteJSIw X-Received: by 2002:a05:600c:2104:b0:416:b75e:ffb9 with SMTP id u4-20020a05600c210400b00416b75effb9mr174768wml.19.1712681031888; Tue, 09 Apr 2024 09:43:51 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFUiIniMzMhxmdJU370qKyXVJ7jtr1GtiFxzJg+USZQ9kNTqaU4FGrR28ZiJAMJbPoSlfieFA== X-Received: by 2002:a05:600c:2104:b0:416:b75e:ffb9 with SMTP id u4-20020a05600c210400b00416b75effb9mr174748wml.19.1712681031237; Tue, 09 Apr 2024 09:43:51 -0700 (PDT) Received: from avogadro.local ([151.95.152.232]) by smtp.gmail.com with ESMTPSA id k2-20020a5d5242000000b00343c0c24a65sm11840762wrc.89.2024.04.09.09.43.50 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 09 Apr 2024 09:43:50 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Subject: [PATCH for-9.1 09/19] target/i386: move 60-BF opcodes to new decoder Date: Tue, 9 Apr 2024 18:43:13 +0200 Message-ID: <20240409164323.776660-10-pbonzini@redhat.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240409164323.776660-1-pbonzini@redhat.com> References: <20240409164323.776660-1-pbonzini@redhat.com> MIME-Version: 1.0 Received-SPF: pass client-ip=170.10.133.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -37 X-Spam_score: -3.8 X-Spam_bar: --- X-Spam_report: (-3.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1.701, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, T_SPF_TEMPERROR=0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Compared to the old decoder, the main differences in translation are for the little-used ARPL instruction. IMUL is adjusted a bit to share more code to produce flags, but is otherwise very similar. Signed-off-by: Paolo Bonzini --- target/i386/tcg/decode-new.h | 2 + target/i386/tcg/translate.c | 9 +- target/i386/tcg/decode-new.c.inc | 171 +++++++++++++++++ target/i386/tcg/emit.c.inc | 317 +++++++++++++++++++++++++++++++ 4 files changed, 497 insertions(+), 2 deletions(-) diff --git a/target/i386/tcg/decode-new.h b/target/i386/tcg/decode-new.h index 8ffde8d1cd6..ca99a620ce9 100644 --- a/target/i386/tcg/decode-new.h +++ b/target/i386/tcg/decode-new.h @@ -165,6 +165,8 @@ typedef enum X86InsnSpecial { /* Always locked if it has a memory operand (XCHG) */ X86_SPECIAL_Locked, + /* Do not apply segment base to effective address */ + X86_SPECIAL_NoSeg, /* * Rd/Mb or Rd/Mw in the manual: register operand 0 is treated as 32 bits * (and writeback zero-extends it to 64 bits if applicable). PREFIX_DATA diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index c251fa21e6d..de1ccb6ea7f 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -1296,7 +1296,11 @@ static void gen_cmps(DisasContext *s, MemOp ot) gen_string_movl_A0_EDI(s); gen_op_ld_v(s, ot, s->T1, s->A0); gen_string_movl_A0_ESI(s); - gen_op(s, OP_CMPL, ot, OR_TMP0); + gen_op_ld_v(s, ot, s->T0, s->A0); + tcg_gen_mov_tl(cpu_cc_src, s->T1); + tcg_gen_mov_tl(s->cc_srcT, s->T0); + tcg_gen_sub_tl(cpu_cc_dst, s->T0, s->T1); + set_cc_op(s, CC_OP_SUBB + ot); dshift = gen_compute_Dshift(s, ot); gen_op_add_reg(s, s->aflag, R_ESI, dshift); @@ -3124,6 +3128,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu) s->pc = s->base.pc_next; s->override = -1; + s->popl_esp_hack = 0; #ifdef TARGET_X86_64 s->rex_r = 0; s->rex_x = 0; @@ -3181,7 +3186,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu) #ifndef CONFIG_USER_ONLY use_new &= b <= limit; #endif - if (use_new && b <= 0x5f) { + if (use_new && b <= 0xbf) { disas_insn_new(s, cpu, b); return true; } diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc index c6fd7a053bd..f6d6873dd83 100644 --- a/target/i386/tcg/decode-new.c.inc +++ b/target/i386/tcg/decode-new.c.inc @@ -33,6 +33,13 @@ * ("cannot encode 16-bit or 32-bit size in 64-bit mode") as modifiers of the * "v" or "z" sizes. The decoder simply makes them separate operand sizes. * + * The manual lists immediate far destinations as Ap (technically an implicit + * argument). The decoder splits them into two immediates, using "Ip" for + * the offset part (that comes first in the instruction stream) and "Iw" for + * the segment/selector part. The size of the offset is given by s->dflag + * and the instructions are illegal in 64-bit mode, so the choice of "Ip" + * is somewhat arbitrary; "Iv" or "Iz" would work just as well. + * * Vector operands * --------------- * @@ -151,6 +158,8 @@ */ #define X86_OP_ENTRYrr(op, op0, s0, op1, s1, ...) \ X86_OP_ENTRY3(op, None, None, op0, s0, op1, s1, ## __VA_ARGS__) +#define X86_OP_ENTRYwr(op, op0, s0, op1, s1, ...) \ + X86_OP_ENTRY3(op, op0, s0, None, None, op1, s1, ## __VA_ARGS__) #define X86_OP_ENTRY2(op, op0, s0, op1, s1, ...) \ X86_OP_ENTRY3(op, op0, s0, 2op, s0, op1, s1, ## __VA_ARGS__) #define X86_OP_ENTRYw(op, op0, s0, ...) \ @@ -163,6 +172,7 @@ X86_OP_ENTRY3(op, None, None, None, None, None, None, ## __VA_ARGS__) #define cpuid(feat) .cpuid = X86_FEAT_##feat, +#define noseg .special = X86_SPECIAL_NoSeg, #define xchg .special = X86_SPECIAL_Locked, #define lock .special = X86_SPECIAL_HasLock, #define mmx .special = X86_SPECIAL_MMX, @@ -209,6 +219,8 @@ #define p_66_f3_f2 .valid_prefix = P_66 | P_F3 | P_F2, #define p_00_66_f3_f2 .valid_prefix = P_00 | P_66 | P_F3 | P_F2, +#define UNKNOWN_OPCODE ((X86OpEntry) {}) + static uint8_t get_modrm(DisasContext *s, CPUX86State *env) { if (!s->has_modrm) { @@ -1108,6 +1120,51 @@ static void decode_0F(DisasContext *s, CPUX86State *env, X86OpEntry *entry, uint do_decode_0F(s, env, entry, b); } +static void decode_63(DisasContext *s, CPUX86State *env, X86OpEntry *entry, uint8_t *b) +{ + static const X86OpEntry arpl = X86_OP_ENTRY2(ARPL, E,w, G,w, chk(prot)); + static const X86OpEntry mov = X86_OP_ENTRY3(MOV, G,v, E,v, None, None); + static const X86OpEntry movsxd = X86_OP_ENTRY3(MOV, G,v, E,d, None, None, sextT0); + if (!CODE64(s)) { + *entry = arpl; + } else if (REX_W(s)) { + *entry = movsxd; + } else { + *entry = mov; + } +} + +static void decode_group1(DisasContext *s, CPUX86State *env, X86OpEntry *entry, uint8_t *b) +{ + static const X86GenFunc group1_gen[8] = { + gen_ADD, gen_OR, gen_ADC, gen_SBB, gen_AND, gen_SUB, gen_XOR, gen_SUB, + }; + int op = (get_modrm(s, env) >> 3) & 7; + entry->gen = group1_gen[op]; + + if (op == 7) { + /* prevent writeback for CMP */ + entry->op1 = entry->op0; + entry->op0 = X86_TYPE_None; + entry->s0 = X86_SIZE_None; + } else { + entry->special = X86_SPECIAL_HasLock; + } +} + +static void decode_group1A(DisasContext *s, CPUX86State *env, X86OpEntry *entry, uint8_t *b) +{ + int op = (get_modrm(s, env) >> 3) & 7; + if (op != 0) { + /* could be XOP prefix too */ + *entry = UNKNOWN_OPCODE; + } else { + entry->gen = gen_POP; + /* The address must use the value of ESP after the pop. */ + s->popl_esp_hack = 1 << mo_pushpop(s, s->dflag); + } +} + static const X86OpEntry opcodes_root[256] = { [0x00] = X86_OP_ENTRY2(ADD, E,b, G,b, lock), [0x01] = X86_OP_ENTRY2(ADD, E,v, G,v, lock), @@ -1163,6 +1220,60 @@ static const X86OpEntry opcodes_root[256] = { [0x56] = X86_OP_ENTRYr(PUSH, LoBits,d64), [0x57] = X86_OP_ENTRYr(PUSH, LoBits,d64), + [0x60] = X86_OP_ENTRY0(PUSHA, chk(i64)), + [0x61] = X86_OP_ENTRY0(POPA, chk(i64)), + [0x62] = X86_OP_ENTRYrr(BOUND, G,v, M,a, chk(i64)), + [0x63] = X86_OP_GROUP0(63), + [0x64] = {}, + [0x65] = {}, + [0x66] = {}, + [0x67] = {}, + + [0x70] = X86_OP_ENTRYr(Jcc, J,b), + [0x71] = X86_OP_ENTRYr(Jcc, J,b), + [0x72] = X86_OP_ENTRYr(Jcc, J,b), + [0x73] = X86_OP_ENTRYr(Jcc, J,b), + [0x74] = X86_OP_ENTRYr(Jcc, J,b), + [0x75] = X86_OP_ENTRYr(Jcc, J,b), + [0x76] = X86_OP_ENTRYr(Jcc, J,b), + [0x77] = X86_OP_ENTRYr(Jcc, J,b), + + [0x80] = X86_OP_GROUP2(group1, E,b, I,b), + [0x81] = X86_OP_GROUP2(group1, E,v, I,z), + [0x82] = X86_OP_GROUP2(group1, E,b, I,b, chk(i64)), + [0x83] = X86_OP_GROUP2(group1, E,v, I,b), + [0x84] = X86_OP_ENTRYrr(AND, E,b, G,b), + [0x85] = X86_OP_ENTRYrr(AND, E,v, G,v), + [0x86] = X86_OP_ENTRY2(XCHG, E,b, G,b, xchg), + [0x87] = X86_OP_ENTRY2(XCHG, E,v, G,v, xchg), + + [0x90] = X86_OP_ENTRY2(XCHG, 0,v, LoBits,v), + [0x91] = X86_OP_ENTRY2(XCHG, 0,v, LoBits,v), + [0x92] = X86_OP_ENTRY2(XCHG, 0,v, LoBits,v), + [0x93] = X86_OP_ENTRY2(XCHG, 0,v, LoBits,v), + [0x94] = X86_OP_ENTRY2(XCHG, 0,v, LoBits,v), + [0x95] = X86_OP_ENTRY2(XCHG, 0,v, LoBits,v), + [0x96] = X86_OP_ENTRY2(XCHG, 0,v, LoBits,v), + [0x97] = X86_OP_ENTRY2(XCHG, 0,v, LoBits,v), + + [0xA0] = X86_OP_ENTRY3(MOV, 0,b, O,b, None, None), /* AL, Ob */ + [0xA1] = X86_OP_ENTRY3(MOV, 0,v, O,v, None, None), /* rAX, Ov */ + [0xA2] = X86_OP_ENTRY3(MOV, O,b, 0,b, None, None), /* Ob, AL */ + [0xA3] = X86_OP_ENTRY3(MOV, O,v, 0,v, None, None), /* Ov, rAX */ + [0xA4] = X86_OP_ENTRYrr(MOVS, Y,b, X,b), + [0xA5] = X86_OP_ENTRYrr(MOVS, Y,v, X,v), + [0xA6] = X86_OP_ENTRYrr(CMPS, Y,b, X,b), + [0xA7] = X86_OP_ENTRYrr(CMPS, Y,v, X,v), + + [0xB0] = X86_OP_ENTRY3(MOV, LoBits,b, I,b, None, None), + [0xB1] = X86_OP_ENTRY3(MOV, LoBits,b, I,b, None, None), + [0xB2] = X86_OP_ENTRY3(MOV, LoBits,b, I,b, None, None), + [0xB3] = X86_OP_ENTRY3(MOV, LoBits,b, I,b, None, None), + [0xB4] = X86_OP_ENTRY3(MOV, LoBits,b, I,b, None, None), + [0xB5] = X86_OP_ENTRY3(MOV, LoBits,b, I,b, None, None), + [0xB6] = X86_OP_ENTRY3(MOV, LoBits,b, I,b, None, None), + [0xB7] = X86_OP_ENTRY3(MOV, LoBits,b, I,b, None, None), + [0x08] = X86_OP_ENTRY2(OR, E,b, G,b, lock), [0x09] = X86_OP_ENTRY2(OR, E,v, G,v, lock), @@ -1217,6 +1328,61 @@ static const X86OpEntry opcodes_root[256] = { [0x5D] = X86_OP_ENTRYw(POP, LoBits,d64), [0x5E] = X86_OP_ENTRYw(POP, LoBits,d64), [0x5F] = X86_OP_ENTRYw(POP, LoBits,d64), + + [0x68] = X86_OP_ENTRYr(PUSH, I,z), + [0x69] = X86_OP_ENTRY3(IMUL3, G,v, E,v, I,z), + [0x6A] = X86_OP_ENTRYr(PUSH, I,b), + [0x6B] = X86_OP_ENTRY3(IMUL3, G,v, E,v, I,b), + [0x6C] = X86_OP_ENTRYrr(INS, Y,b, 2,w), /* DX */ + [0x6D] = X86_OP_ENTRYrr(INS, Y,z, 2,w), /* DX */ + [0x6E] = X86_OP_ENTRYrr(OUTS, 2,w, X,b), /* DX */ + [0x6F] = X86_OP_ENTRYrr(OUTS, 2,w, X,b), /* DX */ + + [0x78] = X86_OP_ENTRYr(Jcc, J,b), + [0x79] = X86_OP_ENTRYr(Jcc, J,b), + [0x7A] = X86_OP_ENTRYr(Jcc, J,b), + [0x7B] = X86_OP_ENTRYr(Jcc, J,b), + [0x7C] = X86_OP_ENTRYr(Jcc, J,b), + [0x7D] = X86_OP_ENTRYr(Jcc, J,b), + [0x7E] = X86_OP_ENTRYr(Jcc, J,b), + [0x7F] = X86_OP_ENTRYr(Jcc, J,b), + + [0x88] = X86_OP_ENTRY3(MOV, E,b, G,b, None, None), + [0x89] = X86_OP_ENTRY3(MOV, E,v, G,v, None, None), + [0x8A] = X86_OP_ENTRY3(MOV, G,b, E,b, None, None), + [0x8B] = X86_OP_ENTRY3(MOV, G,v, E,v, None, None), + [0x8C] = X86_OP_ENTRY3(MOV, E,v, S,w, None, None), + [0x8D] = X86_OP_ENTRY3(LEA, G,v, M,v, None, None, noseg), + [0x8E] = X86_OP_ENTRY3(MOV, S,w, E,v, None, None), + [0x8F] = X86_OP_GROUPw(group1A, E,v), + + [0x98] = X86_OP_ENTRY1(CBW, 0,v), /* rAX */ + [0x99] = X86_OP_ENTRY3(CWD, 2,v, 0,v, None, None), /* rDX, rAX */ + [0x9A] = X86_OP_ENTRYrr(CALLF, I_unsigned,p, I_unsigned,w, chk(i64)), + [0x9B] = X86_OP_ENTRY0(WAIT), + [0x9C] = X86_OP_ENTRY0(PUSHF, chk(vm86_iopl) svm(PUSHF)), + [0x9D] = X86_OP_ENTRY0(POPF, chk(vm86_iopl) svm(POPF)), + [0x9E] = X86_OP_ENTRY0(SAHF), + [0x9F] = X86_OP_ENTRY0(LAHF), + + [0xA8] = X86_OP_ENTRYrr(AND, 0,b, I,b), /* AL, Ib */ + [0xA9] = X86_OP_ENTRYrr(AND, 0,v, I,z), /* rAX, Iz */ + [0xAA] = X86_OP_ENTRY3(STOS, Y,b, 0,b, None, None), + [0xAB] = X86_OP_ENTRY3(STOS, Y,v, 0,v, None, None), + /* Manual writeback because REP LODS (!) has to write EAX/RAX after every LODS. */ + [0xAC] = X86_OP_ENTRYr(LODS, X,b), + [0xAD] = X86_OP_ENTRYr(LODS, X,v), + [0xAE] = X86_OP_ENTRYrr(SCAS, 0,b, Y,b), + [0xAF] = X86_OP_ENTRYrr(SCAS, 0,v, Y,v), + + [0xB8] = X86_OP_ENTRY3(MOV, LoBits,v, I,v, None, None), + [0xB9] = X86_OP_ENTRY3(MOV, LoBits,v, I,v, None, None), + [0xBA] = X86_OP_ENTRY3(MOV, LoBits,v, I,v, None, None), + [0xBB] = X86_OP_ENTRY3(MOV, LoBits,v, I,v, None, None), + [0xBC] = X86_OP_ENTRY3(MOV, LoBits,v, I,v, None, None), + [0xBD] = X86_OP_ENTRY3(MOV, LoBits,v, I,v, None, None), + [0xBE] = X86_OP_ENTRY3(MOV, LoBits,v, I,v, None, None), + [0xBF] = X86_OP_ENTRY3(MOV, LoBits,v, I,v, None, None), }; #undef mmx @@ -2037,6 +2203,11 @@ static void disas_insn_new(DisasContext *s, CPUState *cpu, int b) assert(decode.op[1].unit == X86_OP_INT); break; + case X86_SPECIAL_NoSeg: + decode.mem.def_seg = -1; + s->override = -1; + break; + default: break; } diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc index a27d3040e03..cba7b61f757 100644 --- a/target/i386/tcg/emit.c.inc +++ b/target/i386/tcg/emit.c.inc @@ -1179,6 +1179,31 @@ static void gen_ANDN(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) prepare_update1_cc(decode, s, CC_OP_LOGICB + ot); } +static void gen_ARPL(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + TCGLabel *label1 = gen_new_label(); + TCGv rpl_adj = tcg_temp_new(); + TCGv flags = tcg_temp_new(); + + gen_mov_eflags(s, flags); + tcg_gen_andi_tl(flags, flags, ~CC_Z); + + /* Compute dest[rpl] - src[rpl], adjust if result <0. */ + tcg_gen_andi_tl(rpl_adj, s->T0, 3); + tcg_gen_andi_tl(s->T1, s->T1, 3); + tcg_gen_sub_tl(rpl_adj, rpl_adj, s->T1); + + tcg_gen_brcondi_tl(TCG_COND_LT, rpl_adj, 0, label1); + + /* Subtract dest[rpl] - src[rpl] to set dest[rpl] = src[rpl]. */ + tcg_gen_sub_tl(s->T0, s->T0, rpl_adj); + tcg_gen_ori_tl(flags, flags, CC_Z); + gen_set_label(label1); + + decode->cc_src = flags; + decode->cc_op = CC_OP_EFLAGS; +} + static void gen_BEXTR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { MemOp ot = decode->op[0].ot; @@ -1243,6 +1268,17 @@ static void gen_BLSR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) set_cc_op(s, CC_OP_BMILGB + ot); } +static void gen_BOUND(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + TCGv_i32 op = tcg_temp_new_i32(); + tcg_gen_trunc_tl_i32(op, s->T0); + if (decode->op[1].ot == MO_16) { + gen_helper_boundw(tcg_env, s->A0, op); + } else { + gen_helper_boundl(tcg_env, s->A0, op); + } +} + static void gen_BZHI(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { MemOp ot = decode->op[0].ot; @@ -1263,6 +1299,18 @@ static void gen_BZHI(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) prepare_update2_cc(decode, s, CC_OP_BMILGB + ot); } +static void gen_CALLF(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + gen_far_call(s); +} + +static void gen_CBW(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + MemOp src_ot = decode->op[0].ot - 1; + + tcg_gen_ext_tl(s->T0, s->T0, src_ot | MO_SIGN); +} + static void gen_CMPccXADD(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { TCGLabel *label_top = gen_new_label(); @@ -1366,6 +1414,18 @@ static void gen_CMPccXADD(DisasContext *s, CPUX86State *env, X86DecodedInsn *dec decode->cc_op = CC_OP_SUBB + ot; } +static void gen_CMPS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + MemOp ot = decode->op[2].ot; + if (s->prefix & PREFIX_REPNZ) { + gen_repz_cmps(s, ot, 1); + } else if (s->prefix & PREFIX_REPZ) { + gen_repz_cmps(s, ot, 0); + } else { + gen_cmps(s, ot); + } +} + static void gen_CRC32(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { MemOp ot = decode->op[2].ot; @@ -1404,6 +1464,13 @@ static void gen_CVTTPx2PI(DisasContext *s, CPUX86State *env, X86DecodedInsn *dec } } +static void gen_CWD(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + int shift = 8 << decode->op[0].ot; + + tcg_gen_sextract_tl(s->T0, s->T0, shift - 1, 1); +} + static void gen_DAA(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { gen_update_cc_op(s); @@ -1450,6 +1517,59 @@ static void gen_EXTRQ_r(DisasContext *s, CPUX86State *env, X86DecodedInsn *decod gen_helper_extrq_r(tcg_env, OP_PTR0, OP_PTR2); } +static void gen_IMUL3(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + MemOp ot = decode->op[0].ot; + TCGv cc_src_rhs; + + switch (ot) { + case MO_16: + tcg_gen_ext16s_tl(s->T0, s->T0); + tcg_gen_ext16s_tl(s->T1, s->T1); + /* XXX: use 32 bit mul which could be faster */ + tcg_gen_mul_tl(s->T0, s->T0, s->T1); + /* Compare the full result to the extension of the truncated result. */ + tcg_gen_ext16s_tl(s->T1, s->T0); + cc_src_rhs = s->T0; + break; + + case MO_32: +#ifdef TARGET_X86_64 + /* + * This could also use the same algorithm as MO_16. It produces fewer + * TCG ops and better code if flags are needed, but it requires a 64-bit + * multiply even if they are not (and thus the high part of the multiply + * is dead). + */ + tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); + tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1); + tcg_gen_muls2_i32(s->tmp2_i32, s->tmp3_i32, + s->tmp2_i32, s->tmp3_i32); + tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32); + + cc_src_rhs = tcg_temp_new(); + tcg_gen_extu_i32_tl(cc_src_rhs, s->tmp3_i32); + /* Compare the high part to the sign bit of the truncated result */ + tcg_gen_negsetcondi_i32(TCG_COND_LT, s->tmp2_i32, s->tmp2_i32, 0); + tcg_gen_extu_i32_tl(s->T1, s->tmp2_i32); + break; + + case MO_64: +#endif + cc_src_rhs = tcg_temp_new(); + tcg_gen_muls2_tl(s->T0, cc_src_rhs, s->T0, s->T1); + /* Compare the high part to the sign bit of the truncated result */ + tcg_gen_negsetcondi_tl(TCG_COND_LT, s->T1, s->T0, 0); + break; + + default: + g_assert_not_reached(); + } + + tcg_gen_sub_tl(s->T1, s->T1, cc_src_rhs); + prepare_update2_cc(decode, s, CC_OP_MULB + ot); +} + static void gen_INC(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { MemOp ot = decode->op[1].ot; @@ -1464,6 +1584,26 @@ static void gen_INC(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) prepare_update_cc_incdec(decode, s, CC_OP_INCB + ot); } +static void gen_INS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + MemOp ot = decode->op[0].ot; + TCGv_i32 port = tcg_temp_new_i32(); + + tcg_gen_trunc_tl_i32(port, s->T1); + tcg_gen_ext16u_i32(port, port); + if (!gen_check_io(s, ot, port, + SVM_IOIO_TYPE_MASK | SVM_IOIO_STR_MASK)) { + return; + } + + translator_io_start(&s->base); + if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) { + gen_repz_ins(s, ot); + } else { + gen_ins(s, ot); + } +} + static void gen_INSERTQ_i(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { TCGv_i32 length = tcg_constant_i32(decode->immediate & 63); @@ -1477,12 +1617,50 @@ static void gen_INSERTQ_r(DisasContext *s, CPUX86State *env, X86DecodedInsn *dec gen_helper_insertq_r(tcg_env, OP_PTR0, OP_PTR2); } +static void gen_Jcc(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + gen_bnd_jmp(s); + gen_jcc(s, decode->b & 0xf, decode->immediate); +} + +static void gen_LAHF(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM)) { + return gen_illegal_opcode(s); + } + gen_compute_eflags(s); + /* Note: gen_compute_eflags() only gives the condition codes */ + tcg_gen_ori_tl(s->T0, cpu_cc_src, 0x02); + tcg_gen_deposit_tl(cpu_regs[R_EAX], cpu_regs[R_EAX], s->T0, 8, 8); +} + static void gen_LDMXCSR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T1); gen_helper_ldmxcsr(tcg_env, s->tmp2_i32); } +static void gen_LEA(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + tcg_gen_mov_tl(s->T0, s->A0); +} + +static void gen_LODS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + MemOp ot = decode->op[2].ot; + if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) { + gen_repz_lods(s, ot); + } else { + gen_lods(s, ot); + } +} + +static void gen_MOV(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + /* nothing to do! */ +} +#define gen_NOP gen_MOV + static void gen_MASKMOV(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { gen_lea_v_seg(s, s->aflag, cpu_regs[R_EDI], R_DS, s->override); @@ -1590,6 +1768,16 @@ static void gen_MOVq_dq(DisasContext *s, CPUX86State *env, X86DecodedInsn *decod return gen_MOVQ(s, env, decode); } +static void gen_MOVS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + MemOp ot = decode->op[2].ot; + if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) { + gen_repz_movs(s, ot); + } else { + gen_movs(s, ot); + } +} + static void gen_MULX(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { MemOp ot = decode->op[0].ot; @@ -1629,6 +1817,25 @@ static void gen_OR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) prepare_update1_cc(decode, s, CC_OP_LOGICB + ot); } +static void gen_OUTS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + MemOp ot = decode->op[1].ot; + TCGv_i32 port = tcg_temp_new_i32(); + + tcg_gen_trunc_tl_i32(port, s->T0); + tcg_gen_ext16u_i32(port, port); + if (!gen_check_io(s, ot, port, SVM_IOIO_STR_MASK)) { + return; + } + + translator_io_start(&s->base); + if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) { + gen_repz_outs(s, ot); + } else { + gen_outs(s, ot); + } +} + static void gen_PALIGNR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { TCGv_i32 imm = tcg_constant8u_i32(decode->immediate); @@ -1884,6 +2091,33 @@ static void gen_POP(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) gen_pop_update(s, ot); } +static void gen_POPA(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + gen_popa(s); +} + +static void gen_POPF(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + MemOp ot; + int mask = TF_MASK | AC_MASK | ID_MASK | NT_MASK; + + if (CPL(s) == 0) { + mask |= IF_MASK | IOPL_MASK; + } else if (CPL(s) <= IOPL(s)) { + mask |= IF_MASK; + } + if (s->dflag == MO_16) { + mask &= 0xffff; + } + + ot = gen_pop_T0(s); + gen_helper_write_eflags(tcg_env, s->T0, tcg_constant_i32(mask)); + gen_pop_update(s, ot); + set_cc_op(s, CC_OP_EFLAGS); + /* abort translation because TF/AC flag may change */ + s->base.is_jmp = DISAS_EOB_NEXT; +} + static void gen_PSHUFW(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { TCGv_i32 imm = tcg_constant8u_i32(decode->immediate); @@ -2035,6 +2269,18 @@ static void gen_PUSH(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) gen_push_v(s, s->T1); } +static void gen_PUSHA(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + gen_pusha(s); +} + +static void gen_PUSHF(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + gen_update_cc_op(s); + gen_helper_read_eflags(s->T0, tcg_env); + gen_push_v(s, s->T0); +} + static void gen_RORX(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { MemOp ot = decode->op[0].ot; @@ -2059,6 +2305,18 @@ static void gen_RORX(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) } } +static void gen_SAHF(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM)) { + return gen_illegal_opcode(s); + } + tcg_gen_shri_tl(s->T0, cpu_regs[R_EAX], 8); + gen_compute_eflags(s); + tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, CC_O); + tcg_gen_andi_tl(s->T0, s->T0, CC_S | CC_Z | CC_A | CC_P | CC_C); + tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, s->T0); +} + static void gen_SARX(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { MemOp ot = decode->op[0].ot; @@ -2091,6 +2349,18 @@ static void gen_SBB(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) prepare_update3_cc(decode, s, CC_OP_SBBB + ot, c_in); } +static void gen_SCAS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + MemOp ot = decode->op[2].ot; + if (s->prefix & PREFIX_REPNZ) { + gen_repz_scas(s, ot, 1); + } else if (s->prefix & PREFIX_REPZ) { + gen_repz_scas(s, ot, 0); + } else { + gen_scas(s, ot); + } +} + static void gen_SHA1NEXTE(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { gen_helper_sha1nexte(OP_PTR0, OP_PTR1, OP_PTR2); @@ -2178,6 +2448,16 @@ static void gen_STMXCSR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decod tcg_gen_ld32u_tl(s->T0, tcg_env, offsetof(CPUX86State, mxcsr)); } +static void gen_STOS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + MemOp ot = decode->op[1].ot; + if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) { + gen_repz_stos(s, ot); + } else { + gen_stos(s, ot); + } +} + static void gen_SUB(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { MemOp ot = decode->op[1].ot; @@ -2674,6 +2954,43 @@ static void gen_VZEROUPPER(DisasContext *s, CPUX86State *env, X86DecodedInsn *de } } +static void gen_WAIT(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) == (HF_MP_MASK | HF_TS_MASK)) { + gen_NM_exception(s); + } else { + /* needs to be treated as I/O because of ferr_irq */ + translator_io_start(&s->base); + gen_helper_fwait(tcg_env); + } +} + +static void gen_XCHG(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + if (decode->b == 0x90 && !REX_B(s)) { + if (s->prefix & PREFIX_REPZ) { + gen_update_cc_op(s); + gen_update_eip_cur(s); + gen_helper_pause(tcg_env, cur_insn_len_i32(s)); + s->base.is_jmp = DISAS_NORETURN; + } + /* No writeback. */ + decode->op[0].unit = X86_OP_SKIP; + return; + } + + if (s->prefix & PREFIX_LOCK) { + tcg_gen_atomic_xchg_tl(s->T0, s->A0, s->T1, + s->mem_index, decode->op[0].ot | MO_LE); + /* now store old value into register operand */ + gen_op_mov_reg_v(s, decode->op[2].ot, decode->op[2].n, s->T0); + } else { + /* move destination value into source operand, source preserved in T1 */ + gen_op_mov_reg_v(s, decode->op[2].ot, decode->op[2].n, s->T0); + tcg_gen_mov_tl(s->T0, s->T1); + } +} + static void gen_XOR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { /* special case XOR reg, reg */ From patchwork Tue Apr 9 16:43:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 13622962 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 3FA53C67861 for ; Tue, 9 Apr 2024 16:51:12 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ruEae-00010L-HH; Tue, 09 Apr 2024 12:44:56 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ruEa0-0000aI-Gb for qemu-devel@nongnu.org; Tue, 09 Apr 2024 12:44:16 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ruEZk-00084a-Oi for qemu-devel@nongnu.org; Tue, 09 Apr 2024 12:44:14 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1712681038; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=RjS8qjTg1SFA8JebWO9k+5blG86QrHCQn7ISVPzjrfQ=; b=ejq1ScHnh+XXVpcYihUSkudosJIop6Z8GouncfmCqH8PLMBdL9DhAlG5AIrXaobCWfnfmV zs2v5QPQNyNI05a0O+Gil/El5i5k/LfOsZ4vltNqIsDZOAaQnMTn/ZOrY9ly2vGRZ+kK3/ 0t0pA72+m6MsGlUtTQGZBQnY7JnD6sc= Received: from mail-wm1-f71.google.com (mail-wm1-f71.google.com [209.85.128.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-442-wI5NRHjCPcartw_V7JAIsw-1; Tue, 09 Apr 2024 12:43:55 -0400 X-MC-Unique: wI5NRHjCPcartw_V7JAIsw-1 Received: by mail-wm1-f71.google.com with SMTP id 5b1f17b1804b1-41663448bcbso12539265e9.1 for ; Tue, 09 Apr 2024 09:43:55 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712681034; x=1713285834; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=RjS8qjTg1SFA8JebWO9k+5blG86QrHCQn7ISVPzjrfQ=; b=wBIlsiUj513ka8fcggc/0Z68zi5RPg1dEtvGlkIKZQ6CC27Vy4GJk38dShmqPkL1HO gRJbXYTGiTr98C+rxaeZ+YHfwY14gvFK4LPD3iN0fPJpDhMaH64ptlRt5u3RY9LrPgZU TzWqscSLG/awqJI7Uc5aJbSBqFAVnVtpnf2TWOGhBg1i8y4YbrFKEE+W4bt03SrxkE3S rDn646mqnr/qwYCDjH+xF4zPJhsZiTaFG5Nj4Cc5da7JMb5U5UiW1V8wqOMggxnwyJyZ akVkoRXQHYZ/zWtm4fABVv/aw7Yrb7yVn9YvsqumrB+CC3vreTQiihQDu1H+5MX0DwJa VDcQ== X-Gm-Message-State: AOJu0YzBu4WqItNopIDVgS4y+YpRhq9KG2X3e83lAUoGrslqu4GnkYBt L6tohZafity8dfDpTgl3zsYEkkPRWaJ7VUDj5wINCBor+YvRKafPzL2TbdFrgyPuftatPjI7a1e 4Sggusa1tgMlfyRSS4k/45TztnR82oFBWTdZiviOAGBz2VUptDAuHbaR13fcDFg9iFe0tPRY458 sNIc46jhk3qbflHHwIg3K24lsrvAznB1N6gHBN X-Received: by 2002:a05:6000:87:b0:343:cee1:cbc1 with SMTP id m7-20020a056000008700b00343cee1cbc1mr2705213wrx.14.1712681034192; Tue, 09 Apr 2024 09:43:54 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGBySulLEbKVZJFGsqWOcd5VtL2Wg/I9GYyHOW+XR719uOvbAY1BKqgE8VAHQ1lXHPfscknJg== X-Received: by 2002:a05:6000:87:b0:343:cee1:cbc1 with SMTP id m7-20020a056000008700b00343cee1cbc1mr2705191wrx.14.1712681033838; Tue, 09 Apr 2024 09:43:53 -0700 (PDT) Received: from avogadro.local ([151.95.152.232]) by smtp.gmail.com with ESMTPSA id bi17-20020a05600c3d9100b00416bf7b68f6sm535735wmb.31.2024.04.09.09.43.53 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 09 Apr 2024 09:43:53 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Subject: [PATCH for-9.1 10/19] target/i386: generalize gen_movl_seg_T0 Date: Tue, 9 Apr 2024 18:43:14 +0200 Message-ID: <20240409164323.776660-11-pbonzini@redhat.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240409164323.776660-1-pbonzini@redhat.com> References: <20240409164323.776660-1-pbonzini@redhat.com> MIME-Version: 1.0 Received-SPF: pass client-ip=170.10.133.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -37 X-Spam_score: -3.8 X-Spam_bar: --- X-Spam_report: (-3.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1.701, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org In the new decoder it is sometimes easier to put the segment in T1 instead of T0, usually because another operand was loaded by common code in T0. Genrealize gen_movl_seg_T0 to allow using any source. Signed-off-by: Paolo Bonzini Reviewed-by: Richard Henderson --- target/i386/tcg/translate.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index de1ccb6ea7f..8a34e50c452 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -2531,12 +2531,12 @@ static void gen_op_movl_seg_real(DisasContext *s, X86Seg seg_reg, TCGv seg) tcg_gen_shli_tl(cpu_seg_base[seg_reg], selector, 4); } -/* move T0 to seg_reg and compute if the CPU state may change. Never +/* move SRC to seg_reg and compute if the CPU state may change. Never call this function with seg_reg == R_CS */ -static void gen_movl_seg_T0(DisasContext *s, X86Seg seg_reg) +static void gen_movl_seg(DisasContext *s, X86Seg seg_reg, TCGv src) { if (PE(s) && !VM86(s)) { - tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); + tcg_gen_trunc_tl_i32(s->tmp2_i32, src); gen_helper_load_seg(tcg_env, tcg_constant_i32(seg_reg), s->tmp2_i32); /* abort translation because the addseg value may change or because ss32 may change. For R_SS, translation must always @@ -2548,7 +2548,7 @@ static void gen_movl_seg_T0(DisasContext *s, X86Seg seg_reg) s->base.is_jmp = DISAS_EOB_NEXT; } } else { - gen_op_movl_seg_real(s, seg_reg, s->T0); + gen_op_movl_seg_real(s, seg_reg, src); if (seg_reg == R_SS) { s->base.is_jmp = DISAS_EOB_INHIBIT_IRQ; } @@ -4086,13 +4086,13 @@ static bool disas_insn(DisasContext *s, CPUState *cpu) goto illegal_op; reg = b >> 3; ot = gen_pop_T0(s); - gen_movl_seg_T0(s, reg); + gen_movl_seg(s, reg, s->T0); gen_pop_update(s, ot); break; case 0x1a1: /* pop fs */ case 0x1a9: /* pop gs */ ot = gen_pop_T0(s); - gen_movl_seg_T0(s, (b >> 3) & 7); + gen_movl_seg(s, (b >> 3) & 7, s->T0); gen_pop_update(s, ot); break; @@ -4139,7 +4139,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu) if (reg >= 6 || reg == R_CS) goto illegal_op; gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0); - gen_movl_seg_T0(s, reg); + gen_movl_seg(s, reg, s->T0); break; case 0x8c: /* mov Gv, seg */ modrm = x86_ldub_code(env, s); @@ -4325,7 +4325,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu) gen_add_A0_im(s, 1 << ot); /* load the segment first to handle exceptions properly */ gen_op_ld_v(s, MO_16, s->T0, s->A0); - gen_movl_seg_T0(s, op); + gen_movl_seg(s, op, s->T0); /* then put the data */ gen_op_mov_reg_v(s, ot, reg, s->T1); break; From patchwork Tue Apr 9 16:43:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 13622949 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 5F353CD128A for ; Tue, 9 Apr 2024 16:45:12 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ruEac-0000vh-GH; Tue, 09 Apr 2024 12:44:55 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ruEaM-0000hj-FF for qemu-devel@nongnu.org; Tue, 09 Apr 2024 12:44:44 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ruEa2-00086B-A8 for qemu-devel@nongnu.org; Tue, 09 Apr 2024 12:44:37 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1712681044; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=k0brXmLxqeo5ISsuPNpwS4enHVAsgvbxa8U3qvpUVHA=; b=KE3rlzudsC3wom2uTjR1xIbOkjO2549TjinqwdNlc3nHKlQHp0JlwTTDGQFv3IDlqK8YUs mLfxPfyxI2SNbtc8IfTdQGjlZgqC7oakp+/woJURHireZmX9sgSX7Xy+VMnGrDU6c3GVyj H5m2AFHwCZoXF4LnCtp40cZBWapSdO0= Received: from mail-wr1-f70.google.com (mail-wr1-f70.google.com [209.85.221.70]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-227-LEB20f7vOJ-D-wftzRY2Ag-1; Tue, 09 Apr 2024 12:44:02 -0400 X-MC-Unique: LEB20f7vOJ-D-wftzRY2Ag-1 Received: by mail-wr1-f70.google.com with SMTP id ffacd0b85a97d-343f08542f8so2839830f8f.0 for ; Tue, 09 Apr 2024 09:44:00 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712681038; x=1713285838; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=k0brXmLxqeo5ISsuPNpwS4enHVAsgvbxa8U3qvpUVHA=; b=nissPCZQDQnfj7Vg8F5tRqcT4YhBmdbHRvM8/+nqOp74inDY8njwBmrBUbn82/H5ut PDNL1sUOLpqW0JJKdLkW4Wupn72+w13+FACtlvgnAKFF2WcTrmaXOVG6iKB0OEVyxoNs CsECCpjfqHSZZTc/g7z70Zjt4hWkXfaP5sI7zUz9kuqf5zipjEqtV93ZmQDDJsRQ3TYu juZviEDW1Jjmsg1QB+Ceuau1Ns2KcYIh5WxQfmRzBEBP+tuxQFXiw/eT3hmQ5pEdRkBr n2f45f+Hs4RGNHn2gssrmE3ICajxzZmHmQy4if2Gvk+aDGSuXyFVFmISlNesU9fMheQm s7bw== X-Gm-Message-State: AOJu0Yy9n2eimnt3g+m22nPZQ1hZjOhr2g7Ze5xVYXwT30Dz2W9gn5Nw TcikqBDThRA0Cse+Sr/Obr5+xhNd9GL+VZIl9yr6/P+uvR9AbfCBlh0de/Pk4eCvUnHSDQPtXkU 3k9S3Nc0wvyMZGSfCfRuLDvjKsz9ZgudoI2bR/r07L8U/oSRFWvN+3tZ5y+nTataqI2aHo45qMB Iz+b8wUNC5B1Ek+gImDntEFgIvz5mV5QSKLVte X-Received: by 2002:a05:6000:1743:b0:343:ba58:97c4 with SMTP id m3-20020a056000174300b00343ba5897c4mr202033wrf.10.1712681037513; Tue, 09 Apr 2024 09:43:57 -0700 (PDT) X-Google-Smtp-Source: AGHT+IF4KS7K6BQic5bJlhCBV6yLDHMw0s1E2HPP3mkr3ZLagSTzf9Qp0Df12HwHxvho80MyXigRIA== X-Received: by 2002:a05:6000:1743:b0:343:ba58:97c4 with SMTP id m3-20020a056000174300b00343ba5897c4mr202005wrf.10.1712681036592; Tue, 09 Apr 2024 09:43:56 -0700 (PDT) Received: from avogadro.local ([151.95.152.232]) by smtp.gmail.com with ESMTPSA id n6-20020a5d6606000000b0033e745b8bcfsm11842623wru.88.2024.04.09.09.43.55 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 09 Apr 2024 09:43:56 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Subject: [PATCH for-9.1 11/19] target/i386: move C0-FF opcodes to new decoder (except for x87) Date: Tue, 9 Apr 2024 18:43:15 +0200 Message-ID: <20240409164323.776660-12-pbonzini@redhat.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240409164323.776660-1-pbonzini@redhat.com> References: <20240409164323.776660-1-pbonzini@redhat.com> MIME-Version: 1.0 Received-SPF: pass client-ip=170.10.129.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -37 X-Spam_score: -3.8 X-Spam_bar: --- X-Spam_report: (-3.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1.701, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org The shift instructions are rewritten instead of reusing code from the old decoder. Rotates use CC_OP_ADCOX more extensively and generally rely more on the optimizer, so that the code generators are shared between the immediate-count and variable-count cases. In particular, this makes gen_RCL and gen_RCR pretty efficient for the count == 1 case, which becomes (apart from a few extra movs) something like: (compute_cc_all if needed) // save old value for OF calculation mov cc_src2, T0 // the bulk of RCL is just this! deposit T0, cc_src, T0, 1, TARGET_LONG_BITS - 1 // compute carry shr cc_dst, cc_src2, length - 1 and cc_dst, cc_dst, 1 // compute overflow xor cc_src2, cc_src2, T0 extract cc_src2, cc_src2, length - 1, 1 32-bit MUL and IMUL are also slightly more efficient on 64-bit hosts. Signed-off-by: Paolo Bonzini --- include/tcg/tcg.h | 6 + target/i386/tcg/decode-new.h | 2 + target/i386/tcg/translate.c | 23 +- target/i386/tcg/decode-new.c.inc | 157 ++++- target/i386/tcg/emit.c.inc | 996 ++++++++++++++++++++++++++++++- 5 files changed, 1176 insertions(+), 8 deletions(-) diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h index 05a1912f8a3..88653c4f824 100644 --- a/include/tcg/tcg.h +++ b/include/tcg/tcg.h @@ -105,6 +105,12 @@ typedef uint64_t TCGRegSet; /* Turn some undef macros into true macros. */ #define TCG_TARGET_HAS_add2_i32 1 #define TCG_TARGET_HAS_sub2_i32 1 +/* Define parameterized _tl macros. */ +#define TCG_TARGET_deposit_tl_valid TCG_TARGET_deposit_i32_valid +#define TCG_TARGET_extract_tl_valid TCG_TARGET_extract_i32_valid +#else +#define TCG_TARGET_deposit_tl_valid TCG_TARGET_deposit_i64_valid +#define TCG_TARGET_extract_tl_valid TCG_TARGET_extract_i64_valid #endif #ifndef TCG_TARGET_deposit_i32_valid diff --git a/target/i386/tcg/decode-new.h b/target/i386/tcg/decode-new.h index ca99a620ce9..77bb31eb143 100644 --- a/target/i386/tcg/decode-new.h +++ b/target/i386/tcg/decode-new.h @@ -48,6 +48,7 @@ typedef enum X86OpType { /* Custom */ X86_TYPE_WM, /* modrm byte selects an XMM/YMM memory operand */ + X86_TYPE_I_unsigned, /* Immediate, zero-extended */ X86_TYPE_2op, /* 2-operand RMW instruction */ X86_TYPE_LoBits, /* encoded in bits 0-2 of the operand + REX.B */ X86_TYPE_0, /* Hard-coded GPRs (RAX..RDI) */ @@ -88,6 +89,7 @@ typedef enum X86OpSize { X86_SIZE_x, /* 128/256-bit, based on operand size */ X86_SIZE_y, /* 32/64-bit, based on operand size */ X86_SIZE_z, /* 16-bit for 16-bit operand size, else 32-bit */ + X86_SIZE_z_f64, /* 32-bit for 32-bit operand size or 64-bit mode, else 16-bit */ /* Custom */ X86_SIZE_d64, diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 8a34e50c452..720668e023a 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -38,6 +38,9 @@ #include "exec/helper-info.c.inc" #undef HELPER_H +/* Fixes for Windows namespace pollution. */ +#undef IN +#undef OUT #define PREFIX_REPZ 0x01 #define PREFIX_REPNZ 0x02 @@ -2495,14 +2498,24 @@ static inline int insn_const_size(MemOp ot) } } +static void gen_conditional_jump_labels(DisasContext *s, target_long diff, + TCGLabel *not_taken, TCGLabel *taken) +{ + if (not_taken) { + gen_set_label(not_taken); + } + gen_jmp_rel_csize(s, 0, 1); + + gen_set_label(taken); + gen_jmp_rel(s, s->dflag, diff, 0); +} + static void gen_jcc(DisasContext *s, int b, int diff) { TCGLabel *l1 = gen_new_label(); gen_jcc1(s, b, l1); - gen_jmp_rel_csize(s, 0, 1); - gen_set_label(l1); - gen_jmp_rel(s, s->dflag, diff, 0); + gen_conditional_jump_labels(s, diff, NULL, l1); } static void gen_cmovcc1(DisasContext *s, int b, TCGv dest, TCGv src) @@ -2759,7 +2772,7 @@ static void gen_unknown_opcode(CPUX86State *env, DisasContext *s) /* an interrupt is different from an exception because of the privilege checks */ -static void gen_interrupt(DisasContext *s, int intno) +static void gen_interrupt(DisasContext *s, uint8_t intno) { gen_update_cc_op(s); gen_update_eip_cur(s); @@ -3186,7 +3199,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu) #ifndef CONFIG_USER_ONLY use_new &= b <= limit; #endif - if (use_new && b <= 0xbf) { + if (use_new && (b < 0xd8 || b >= 0xe0)) { disas_insn_new(s, cpu, b); return true; } diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc index f6d6873dd83..87ae63faf9a 100644 --- a/target/i386/tcg/decode-new.c.inc +++ b/target/i386/tcg/decode-new.c.inc @@ -40,6 +40,15 @@ * and the instructions are illegal in 64-bit mode, so the choice of "Ip" * is somewhat arbitrary; "Iv" or "Iz" would work just as well. * + * Operand types + * ------------- + * + * Immediates are almost always signed or masked away in helpers. Two + * common exceptions are IN/OUT and absolute jumps. For these, there is + * an additional custom operand type "I_unsigned". Alternatively, the + * mask could be applied (and the original sign-extended value would be + * optimized away by TCG) in the emitter function. + * * Vector operands * --------------- * @@ -126,6 +135,8 @@ ## __VA_ARGS__ \ } +#define X86_OP_GROUP1(op, op0, s0, ...) \ + X86_OP_GROUP3(op, op0, s0, 2op, s0, None, None, ## __VA_ARGS__) #define X86_OP_GROUP2(op, op0, s0, op1, s1, ...) \ X86_OP_GROUP3(op, op0, s0, 2op, s0, op1, s1, ## __VA_ARGS__) #define X86_OP_GROUPw(op, op0, s0, ...) \ @@ -1165,6 +1176,82 @@ static void decode_group1A(DisasContext *s, CPUX86State *env, X86OpEntry *entry, } } +static void decode_group2(DisasContext *s, CPUX86State *env, X86OpEntry *entry, uint8_t *b) +{ + static const X86GenFunc group2_gen[8] = { + gen_ROL, gen_ROR, gen_RCL, gen_RCR, gen_SHL, gen_SHR, gen_SHL, gen_SAR, + }; + int op = (get_modrm(s, env) >> 3) & 7; + entry->gen = group2_gen[op]; + if (op == 7) { + entry->special = X86_SPECIAL_SExtT0; + } else { + entry->special = X86_SPECIAL_ZExtT0; + } +} + +static const X86OpEntry opcodes_grp3[16] = { + /* 0xf6 */ + [0x00] = X86_OP_ENTRYrr(AND, E,b, I,b), + [0x02] = X86_OP_ENTRY1(NOT, E,b, lock), + [0x03] = X86_OP_ENTRY1(NEG, E,b, lock), + [0x04] = X86_OP_ENTRYrr(MUL, E,b, 0,b, zextT0), + [0x05] = X86_OP_ENTRYrr(IMUL,E,b, 0,b, sextT0), + [0x06] = X86_OP_ENTRYr(DIV, E,b), + [0x07] = X86_OP_ENTRYr(IDIV, E,b), + + /* 0xf7 */ + [0x08] = X86_OP_ENTRYrr(AND, E,v, I,z), + [0x0a] = X86_OP_ENTRY1(NOT, E,v, lock), + [0x0b] = X86_OP_ENTRY1(NEG, E,v, lock), + [0x0c] = X86_OP_ENTRYrr(MUL, E,v, 0,v, zextT0), + [0x0d] = X86_OP_ENTRYrr(IMUL,E,v, 0,v, sextT0), + [0x0e] = X86_OP_ENTRYr(DIV, E,v), + [0x0f] = X86_OP_ENTRYr(IDIV, E,v), +}; + +static void decode_group3(DisasContext *s, CPUX86State *env, X86OpEntry *entry, uint8_t *b) +{ + int w = (*b & 1); + int reg = (get_modrm(s, env) >> 3) & 7; + + *entry = opcodes_grp3[(w << 3) | reg]; +} + +static const X86OpEntry opcodes_grp4[16] = { + /* 0xfe */ + [0x00] = X86_OP_ENTRY1(INC, E,b, lock), + [0x01] = X86_OP_ENTRY1(DEC, E,b, lock), + + /* 0xff */ + [0x08] = X86_OP_ENTRY1(INC, E,v, lock), + [0x09] = X86_OP_ENTRY1(DEC, E,v, lock), + [0x0a] = X86_OP_ENTRY3(CALL_m, None, None, E,f64, None, None, zextT0), + [0x0b] = X86_OP_ENTRYr(CALLF_m, M,p), + [0x0c] = X86_OP_ENTRY3(JMP_m, None, None, E,f64, None, None, zextT0), + [0x0d] = X86_OP_ENTRYr(JMPF_m, M,p), + [0x0e] = X86_OP_ENTRYr(PUSH, E,f64), +}; + +static void decode_group4(DisasContext *s, CPUX86State *env, X86OpEntry *entry, uint8_t *b) +{ + int w = (*b & 1); + int reg = (get_modrm(s, env) >> 3) & 7; + + *entry = opcodes_grp4[(w << 3) | reg]; +} + + +static void decode_group11(DisasContext *s, CPUX86State *env, X86OpEntry *entry, uint8_t *b) +{ + int op = (get_modrm(s, env) >> 3) & 7; + if (op != 0) { + *entry = UNKNOWN_OPCODE; + } else { + entry->gen = gen_MOV; + } +} + static const X86OpEntry opcodes_root[256] = { [0x00] = X86_OP_ENTRY2(ADD, E,b, G,b, lock), [0x01] = X86_OP_ENTRY2(ADD, E,v, G,v, lock), @@ -1274,6 +1361,38 @@ static const X86OpEntry opcodes_root[256] = { [0xB6] = X86_OP_ENTRY3(MOV, LoBits,b, I,b, None, None), [0xB7] = X86_OP_ENTRY3(MOV, LoBits,b, I,b, None, None), + [0xC0] = X86_OP_GROUP2(group2, E,b, I,b), + [0xC1] = X86_OP_GROUP2(group2, E,v, I,b), + [0xC2] = X86_OP_ENTRYr(RET, I,w), + [0xC3] = X86_OP_ENTRY0(RET), + [0xC4] = X86_OP_ENTRY3(LES, G,z, M,p, None, None, chk(i64)), + [0xC5] = X86_OP_ENTRY3(LDS, G,z, M,p, None, None, chk(i64)), + [0xC6] = X86_OP_GROUP3(group11, E,b, I,b, None, None), /* reg=000b */ + [0xC7] = X86_OP_GROUP3(group11, E,v, I,z, None, None), /* reg=000b */ + + [0xD0] = X86_OP_GROUP1(group2, E,b), + [0xD1] = X86_OP_GROUP1(group2, E,v), + [0xD2] = X86_OP_GROUP2(group2, E,b, 1,b), /* CL */ + [0xD3] = X86_OP_GROUP2(group2, E,v, 1,b), /* CL */ + [0xD4] = X86_OP_ENTRY2(AAM, 0,w, I,b), + [0xD5] = X86_OP_ENTRY2(AAD, 0,w, I,b), + [0xD6] = X86_OP_ENTRYw(SALC, 0,b), + [0xD7] = X86_OP_ENTRY1(XLAT, 0,b, zextT0), /* AL read/written */ + + [0xE0] = X86_OP_ENTRYr(LOOPNE, J,b), /* implicit: CX with aflag size */ + [0xE1] = X86_OP_ENTRYr(LOOPE, J,b), /* implicit: CX with aflag size */ + [0xE2] = X86_OP_ENTRYr(LOOP, J,b), /* implicit: CX with aflag size */ + [0xE3] = X86_OP_ENTRYr(JCXZ, J,b), /* implicit: CX with aflag size */ + [0xE4] = X86_OP_ENTRYwr(IN, 0,b, I_unsigned,b), /* AL */ + [0xE5] = X86_OP_ENTRYwr(IN, 0,v, I_unsigned,b), /* AX/EAX */ + [0xE6] = X86_OP_ENTRYrr(OUT, 0,b, I_unsigned,b), /* AL */ + [0xE7] = X86_OP_ENTRYrr(OUT, 0,v, I_unsigned,b), /* AX/EAX */ + + [0xF1] = X86_OP_ENTRY0(INT1, svm(ICEBP)), + [0xF4] = X86_OP_ENTRY0(HLT, chk(cpl0)), + [0xF5] = X86_OP_ENTRY0(CMC), + [0xF6] = X86_OP_GROUP1(group3, E,b), + [0xF7] = X86_OP_GROUP1(group3, E,v), [0x08] = X86_OP_ENTRY2(OR, E,b, G,b, lock), [0x09] = X86_OP_ENTRY2(OR, E,v, G,v, lock), @@ -1383,6 +1502,33 @@ static const X86OpEntry opcodes_root[256] = { [0xBD] = X86_OP_ENTRY3(MOV, LoBits,v, I,v, None, None), [0xBE] = X86_OP_ENTRY3(MOV, LoBits,v, I,v, None, None), [0xBF] = X86_OP_ENTRY3(MOV, LoBits,v, I,v, None, None), + + [0xC8] = X86_OP_ENTRYrr(ENTER, I,w, I,b), + [0xC9] = X86_OP_ENTRY1(LEAVE, A,d64), + [0xCA] = X86_OP_ENTRYr(RETF, I,w), + [0xCB] = X86_OP_ENTRY0(RETF), + [0xCC] = X86_OP_ENTRY0(INT3), + [0xCD] = X86_OP_ENTRYr(INT, I,b, chk(vm86_iopl)), + [0xCE] = X86_OP_ENTRY0(INTO), + [0xCF] = X86_OP_ENTRY0(IRET, chk(vm86_iopl) svm(IRET)), + + [0xE8] = X86_OP_ENTRYr(CALL, J,z_f64), + [0xE9] = X86_OP_ENTRYr(JMP, J,z_f64), + [0xEA] = X86_OP_ENTRYrr(JMPF, I_unsigned,p, I_unsigned,w, chk(i64)), + [0xEB] = X86_OP_ENTRYr(JMP, J,b), + [0xEC] = X86_OP_ENTRYwr(IN, 0,b, 2,w), /* AL, DX */ + [0xED] = X86_OP_ENTRYwr(IN, 0,v, 2,w), /* AX/EAX, DX */ + [0xEE] = X86_OP_ENTRYrr(OUT, 0,b, 2,w), /* DX, AL */ + [0xEF] = X86_OP_ENTRYrr(OUT, 0,v, 2,w), /* DX, AX/EAX */ + + [0xF8] = X86_OP_ENTRY0(CLC), + [0xF9] = X86_OP_ENTRY0(STC), + [0xFA] = X86_OP_ENTRY0(CLI, chk(iopl)), + [0xFB] = X86_OP_ENTRY0(STI, chk(iopl)), + [0xFC] = X86_OP_ENTRY0(CLD), + [0xFD] = X86_OP_ENTRY0(STD), + [0xFE] = X86_OP_GROUP1(group4, E,b), + [0xFF] = X86_OP_GROUP1(group4, E,v), }; #undef mmx @@ -1462,6 +1608,10 @@ static bool decode_op_size(DisasContext *s, X86OpEntry *e, X86OpSize size, MemOp *ot = s->dflag == MO_16 ? MO_16 : MO_32; return true; + case X86_SIZE_z_f64: /* 32-bit for 32-bit operand size or 64-bit mode, else 16-bit */ + *ot = !CODE64(s) && s->dflag == MO_16 ? MO_16 : MO_32; + return true; + case X86_SIZE_dq: /* SSE/AVX 128-bit */ if (e->special == X86_SPECIAL_MMX && !(s->prefix & (PREFIX_DATA | PREFIX_REPZ | PREFIX_REPNZ))) { @@ -1642,6 +1792,11 @@ static bool decode_op(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode, decode->immediate = op->imm = insn_get_signed(env, s, op->ot); break; + case X86_TYPE_I_unsigned: /* Immediate */ + op->unit = X86_OP_IMM; + decode->immediate = op->imm = insn_get(env, s, op->ot); + break; + case X86_TYPE_L: /* The upper 4 bits of the immediate select a 128-bit register */ op->n = insn_get(env, s, op->ot) >> 4; break; @@ -2241,7 +2396,7 @@ static void disas_insn_new(DisasContext *s, CPUState *cpu, int b) tcg_constant_i32(decode.e.intercept)); } if (decode.e.check) { - if ((decode.e.check & X86_CHECK_vm86_iopl) && VM86(s)) { + if (decode.e.check & X86_CHECK_vm86_iopl && VM86(s)) { if (IOPL(s) < 3) { goto gp_fault; } diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc index cba7b61f757..07f9b506043 100644 --- a/target/i386/tcg/emit.c.inc +++ b/target/i386/tcg/emit.c.inc @@ -45,6 +45,9 @@ typedef void (*SSEFunc_0_eppppii)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b, TCGv_ptr reg_c, TCGv_ptr reg_d, TCGv_i32 even, TCGv_i32 odd); +static void gen_JMP_m(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode); +static void gen_JMP(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode); + static inline TCGv_i32 tcg_constant8u_i32(uint8_t val) { return tcg_constant_i32(val); @@ -306,8 +309,8 @@ static void gen_writeback(DisasContext *s, X86DecodedInsn *decode, int opn, TCGv case X86_OP_SKIP: break; case X86_OP_SEG: - /* Note that gen_movl_seg_T0 takes care of interrupt shadow and TF. */ - gen_movl_seg_T0(s, op->n); + /* Note that gen_movl_seg takes care of interrupt shadow and TF. */ + gen_movl_seg(s, op->n, s->T0); break; case X86_OP_INT: if (op->has_ea) { @@ -330,6 +333,7 @@ static void gen_writeback(DisasContext *s, X86DecodedInsn *decode, int opn, TCGv default: g_assert_not_reached(); } + op->unit = X86_OP_SKIP; } static inline int vector_len(DisasContext *s, X86DecodedInsn *decode) @@ -1063,6 +1067,22 @@ static void gen_AAA(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) set_cc_op(s, CC_OP_EFLAGS); } +static void gen_AAD(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + gen_helper_aad(tcg_env, tcg_constant_i32(decode->immediate)); + set_cc_op(s, CC_OP_LOGICB); +} + +static void gen_AAM(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + if (decode->immediate == 0) { + gen_exception(s, EXCP00_DIVZ); + } else { + gen_helper_aam(tcg_env, tcg_constant_i32(decode->immediate)); + set_cc_op(s, CC_OP_LOGICB); + } +} + static void gen_AAS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { gen_update_cc_op(s); @@ -1299,11 +1319,33 @@ static void gen_BZHI(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) prepare_update2_cc(decode, s, CC_OP_BMILGB + ot); } +static void gen_CALL(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + gen_push_v(s, eip_next_tl(s)); + gen_JMP(s, env, decode); +} + +static void gen_CALL_m(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + gen_push_v(s, eip_next_tl(s)); + gen_JMP_m(s, env, decode); +} + static void gen_CALLF(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { gen_far_call(s); } +static void gen_CALLF_m(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + MemOp ot = decode->op[2].ot; + + gen_op_ld_v(s, ot, s->T0, s->A0); + gen_add_A0_im(s, 1 << ot); + gen_op_ld_v(s, MO_16, s->T1, s->A0); + gen_far_call(s); +} + static void gen_CBW(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { MemOp src_ot = decode->op[0].ot - 1; @@ -1311,6 +1353,28 @@ static void gen_CBW(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) tcg_gen_ext_tl(s->T0, s->T0, src_ot | MO_SIGN); } +static void gen_CLC(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + gen_compute_eflags(s); + tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_C); +} + +static void gen_CLD(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + tcg_gen_st_i32(tcg_constant_i32(1), tcg_env, offsetof(CPUX86State, df)); +} + +static void gen_CLI(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + gen_reset_eflags(s, IF_MASK); +} + +static void gen_CMC(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + gen_compute_eflags(s); + tcg_gen_xori_tl(cpu_cc_src, cpu_cc_src, CC_C); +} + static void gen_CMPccXADD(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { TCGLabel *label_top = gen_new_label(); @@ -1499,11 +1563,39 @@ static void gen_DEC(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) prepare_update_cc_incdec(decode, s, CC_OP_DECB + ot); } +static void gen_DIV(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + MemOp ot = decode->op[2].ot; + + switch(ot) { + case MO_8: + gen_helper_divb_AL(tcg_env, s->T1); + break; + case MO_16: + gen_helper_divw_AX(tcg_env, s->T1); + break; + default: + case MO_32: + gen_helper_divl_EAX(tcg_env, s->T1); + break; +#ifdef TARGET_X86_64 + case MO_64: + gen_helper_divq_EAX(tcg_env, s->T1); + break; +#endif + } +} + static void gen_EMMS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { gen_helper_emms(tcg_env); } +static void gen_ENTER(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + gen_enter(s, decode->op[1].imm, decode->op[2].imm); +} + static void gen_EXTRQ_i(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { TCGv_i32 length = tcg_constant_i32(decode->immediate & 63); @@ -1517,6 +1609,39 @@ static void gen_EXTRQ_r(DisasContext *s, CPUX86State *env, X86DecodedInsn *decod gen_helper_extrq_r(tcg_env, OP_PTR0, OP_PTR2); } +static void gen_HLT(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ +#ifdef CONFIG_SYSTEM_ONLY + gen_update_cc_op(s); + gen_update_eip_cur(s); + gen_helper_hlt(tcg_env, cur_insn_len_i32(s)); + s->base.is_jmp = DISAS_NORETURN; +#endif +} + +static void gen_IDIV(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + MemOp ot = decode->op[2].ot; + + switch(ot) { + case MO_8: + gen_helper_idivb_AL(tcg_env, s->T1); + break; + case MO_16: + gen_helper_idivw_AX(tcg_env, s->T1); + break; + default: + case MO_32: + gen_helper_idivl_EAX(tcg_env, s->T1); + break; +#ifdef TARGET_X86_64 + case MO_64: + gen_helper_idivq_EAX(tcg_env, s->T1); + break; +#endif + } +} + static void gen_IMUL3(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { MemOp ot = decode->op[0].ot; @@ -1570,6 +1695,80 @@ static void gen_IMUL3(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) prepare_update2_cc(decode, s, CC_OP_MULB + ot); } +static void gen_IMUL(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + MemOp ot = decode->op[1].ot; + TCGv cc_src_rhs; + + switch (ot) { + case MO_8: + /* s->T0 already sign-extended */ + tcg_gen_ext8s_tl(s->T1, s->T1); + tcg_gen_mul_tl(s->T0, s->T0, s->T1); + gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0); + /* Compare the full result to the extension of the truncated result. */ + tcg_gen_ext8s_tl(s->T1, s->T0); + cc_src_rhs = s->T0; + break; + + case MO_16: + /* s->T0 already sign-extended */ + tcg_gen_ext16s_tl(s->T1, s->T1); + tcg_gen_mul_tl(s->T0, s->T0, s->T1); + gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0); + tcg_gen_shri_tl(s->T1, s->T0, 16); + gen_op_mov_reg_v(s, MO_16, R_EDX, s->T1); + /* Compare the full result to the extension of the truncated result. */ + tcg_gen_ext16s_tl(s->T1, s->T0); + cc_src_rhs = s->T0; + break; + + case MO_32: +#ifdef TARGET_X86_64 + /* s->T0 already sign-extended */ + tcg_gen_ext32s_tl(s->T1, s->T1); + tcg_gen_mul_tl(s->T0, s->T0, s->T1); + tcg_gen_ext32u_tl(cpu_regs[R_EAX], s->T0); + tcg_gen_shri_tl(cpu_regs[R_EDX], s->T0, 32); + /* Compare the full result to the extension of the truncated result. */ + tcg_gen_ext32s_tl(s->T1, s->T0); + cc_src_rhs = s->T0; + break; + + case MO_64: +#endif + tcg_gen_muls2_tl(s->T0, cpu_regs[R_EDX], s->T0, s->T1); + tcg_gen_mov_tl(cpu_regs[R_EAX], s->T0); + + /* Compare the high part to the sign bit of the truncated result */ + tcg_gen_negsetcondi_tl(TCG_COND_LT, s->T1, s->T0, 0); + cc_src_rhs = cpu_regs[R_EDX]; + break; + + default: + g_assert_not_reached(); + } + + tcg_gen_sub_tl(s->T1, s->T1, cc_src_rhs); + prepare_update2_cc(decode, s, CC_OP_MULB + ot); +} + +static void gen_IN(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + MemOp ot = decode->op[0].ot; + TCGv_i32 port = tcg_temp_new_i32(); + + tcg_gen_trunc_tl_i32(port, s->T1); + tcg_gen_ext16u_i32(port, port); + if (!gen_check_io(s, ot, port, SVM_IOIO_TYPE_MASK)) { + return; + } + translator_io_start(&s->base); + gen_helper_in_func(ot, s->T0, port); + gen_writeback(s, decode, 0, s->T0); + gen_bpt_io(s, port, ot); +} + static void gen_INC(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { MemOp ot = decode->op[1].ot; @@ -1617,12 +1816,81 @@ static void gen_INSERTQ_r(DisasContext *s, CPUX86State *env, X86DecodedInsn *dec gen_helper_insertq_r(tcg_env, OP_PTR0, OP_PTR2); } +static void gen_INT(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + gen_interrupt(s, decode->immediate); +} + +static void gen_INT1(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + gen_exception(s, EXCP01_DB); +} + +static void gen_INT3(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + gen_interrupt(s, EXCP03_INT3); +} + +static void gen_INTO(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + gen_update_cc_op(s); + gen_update_eip_cur(s); + gen_helper_into(tcg_env, cur_insn_len_i32(s)); +} + +static void gen_IRET(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + if (!PE(s) || VM86(s)) { + gen_helper_iret_real(tcg_env, tcg_constant_i32(s->dflag - 1)); + } else { + gen_helper_iret_protected(tcg_env, tcg_constant_i32(s->dflag - 1), + eip_next_i32(s)); + } + set_cc_op(s, CC_OP_EFLAGS); + s->base.is_jmp = DISAS_EOB_ONLY; +} + static void gen_Jcc(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { gen_bnd_jmp(s); gen_jcc(s, decode->b & 0xf, decode->immediate); } +static void gen_JCXZ(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + TCGLabel *taken = gen_new_label(); + + gen_op_jz_ecx(s, taken); + gen_conditional_jump_labels(s, decode->immediate, NULL, taken); +} + +static void gen_JMP(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + gen_jmp_rel(s, s->dflag, decode->immediate, 0); +} + +static void gen_JMP_m(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + gen_op_jmp_v(s, s->T0); + gen_bnd_jmp(s); + s->base.is_jmp = DISAS_JUMP; +} + +static void gen_JMPF(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + gen_far_jmp(s); +} + +static void gen_JMPF_m(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + MemOp ot = decode->op[2].ot; + + gen_op_ld_v(s, ot, s->T0, s->A0); + gen_add_A0_im(s, 1 << ot); + gen_op_ld_v(s, MO_16, s->T1, s->A0); + gen_far_jmp(s); +} + static void gen_LAHF(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM)) { @@ -1640,11 +1908,38 @@ static void gen_LDMXCSR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decod gen_helper_ldmxcsr(tcg_env, s->tmp2_i32); } +static void gen_lxx_seg(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode, int seg) +{ + MemOp ot = decode->op[0].ot; + + /* Offset already in s->T0. */ + gen_add_A0_im(s, 1 << ot); + gen_op_ld_v(s, MO_16, s->T1, s->A0); + + /* load the segment here to handle exceptions properly */ + gen_movl_seg(s, seg, s->T1); +} + +static void gen_LDS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + gen_lxx_seg(s, env, decode, R_DS); +} + static void gen_LEA(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { tcg_gen_mov_tl(s->T0, s->A0); } +static void gen_LEAVE(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + gen_leave(s); +} + +static void gen_LES(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + gen_lxx_seg(s, env, decode, R_ES); +} + static void gen_LODS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { MemOp ot = decode->op[2].ot; @@ -1655,6 +1950,37 @@ static void gen_LODS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) } } +static void gen_LOOP(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + TCGLabel *taken = gen_new_label(); + + gen_op_add_reg_im(s, s->aflag, R_ECX, -1); + gen_op_jnz_ecx(s, taken); + gen_conditional_jump_labels(s, decode->immediate, NULL, taken); +} + +static void gen_LOOPE(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + TCGLabel *taken = gen_new_label(); + TCGLabel *not_taken = gen_new_label(); + + gen_op_add_reg_im(s, s->aflag, R_ECX, -1); + gen_op_jz_ecx(s, not_taken); + gen_jcc1(s, (JCC_Z << 1), taken); /* jz taken */ + gen_conditional_jump_labels(s, decode->immediate, not_taken, taken); +} + +static void gen_LOOPNE(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + TCGLabel *taken = gen_new_label(); + TCGLabel *not_taken = gen_new_label(); + + gen_op_add_reg_im(s, s->aflag, R_ECX, -1); + gen_op_jz_ecx(s, not_taken); + gen_jcc1(s, (JCC_Z << 1) | 1, taken); /* jnz taken */ + gen_conditional_jump_labels(s, decode->immediate, not_taken, taken); +} + static void gen_MOV(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { /* nothing to do! */ @@ -1778,6 +2104,57 @@ static void gen_MOVS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) } } +static void gen_MUL(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + MemOp ot = decode->op[1].ot; + + switch (ot) { + case MO_8: + /* s->T0 already zero-extended */ + tcg_gen_ext8u_tl(s->T1, s->T1); + tcg_gen_mul_tl(s->T0, s->T0, s->T1); + gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0); + tcg_gen_andi_tl(s->T1, s->T0, 0xff00); + decode->cc_dst = s->T0; + decode->cc_src = s->T1; + break; + + case MO_16: + /* s->T0 already zero-extended */ + tcg_gen_ext16u_tl(s->T1, s->T1); + tcg_gen_mul_tl(s->T0, s->T0, s->T1); + gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0); + tcg_gen_shri_tl(s->T1, s->T0, 16); + gen_op_mov_reg_v(s, MO_16, R_EDX, s->T1); + decode->cc_dst = s->T0; + decode->cc_src = s->T1; + break; + + case MO_32: +#ifdef TARGET_X86_64 + /* s->T0 already zero-extended */ + tcg_gen_ext32u_tl(s->T1, s->T1); + tcg_gen_mul_tl(s->T0, s->T0, s->T1); + tcg_gen_ext32u_tl(cpu_regs[R_EAX], s->T0); + tcg_gen_shri_tl(cpu_regs[R_EDX], s->T0, 32); + decode->cc_dst = cpu_regs[R_EAX]; + decode->cc_src = cpu_regs[R_EDX]; + break; + + case MO_64: +#endif + tcg_gen_mulu2_tl(cpu_regs[R_EAX], cpu_regs[R_EDX], s->T0, s->T1); + decode->cc_dst = cpu_regs[R_EAX]; + decode->cc_src = cpu_regs[R_EDX]; + break; + + default: + g_assert_not_reached(); + } + + decode->cc_op = CC_OP_MULB + ot; +} + static void gen_MULX(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { MemOp ot = decode->op[0].ot; @@ -1804,6 +2181,46 @@ static void gen_MULX(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) } } +static void gen_NEG(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + MemOp ot = decode->op[0].ot; + TCGv oldv = tcg_temp_new(); + + if (s->prefix & PREFIX_LOCK) { + TCGv newv = tcg_temp_new(); + TCGv cmpv = tcg_temp_new(); + TCGLabel *label1 = gen_new_label(); + + gen_set_label(label1); + gen_op_ld_v(s, ot, oldv, s->A0); + tcg_gen_neg_tl(newv, oldv); + tcg_gen_atomic_cmpxchg_tl(cmpv, s->A0, oldv, newv, + s->mem_index, ot | MO_LE); + tcg_gen_brcond_tl(TCG_COND_NE, oldv, cmpv, label1); + } else { + tcg_gen_mov_tl(oldv, s->T0); + } + tcg_gen_neg_tl(s->T0, oldv); + + decode->cc_dst = s->T0; + decode->cc_src = oldv; + tcg_gen_movi_tl(s->cc_srcT, 0); + decode->cc_op = CC_OP_SUBB + ot; +} + +static void gen_NOT(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + MemOp ot = decode->op[0].ot; + + if (s->prefix & PREFIX_LOCK) { + tcg_gen_movi_tl(s->T0, ~0); + tcg_gen_atomic_xor_fetch_tl(s->T0, s->A0, s->T0, + s->mem_index, ot | MO_LE); + } else { + tcg_gen_not_tl(s->T0, s->T0); + } +} + static void gen_OR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { MemOp ot = decode->op[1].ot; @@ -1817,6 +2234,23 @@ static void gen_OR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) prepare_update1_cc(decode, s, CC_OP_LOGICB + ot); } +static void gen_OUT(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + MemOp ot = decode->op[1].ot; + TCGv_i32 port = tcg_temp_new_i32(); + TCGv_i32 value = tcg_temp_new_i32(); + + tcg_gen_trunc_tl_i32(port, s->T1); + tcg_gen_ext16u_i32(port, port); + if (!gen_check_io(s, ot, port, 0)) { + return; + } + tcg_gen_trunc_tl_i32(value, s->T0); + translator_io_start(&s->base); + gen_helper_out_func(ot, port, value); + gen_bpt_io(s, port, ot); +} + static void gen_OUTS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { MemOp ot = decode->op[1].ot; @@ -2281,6 +2715,433 @@ static void gen_PUSHF(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) gen_push_v(s, s->T0); } +static MemOp gen_shift_count(DisasContext *s, X86DecodedInsn *decode, + bool *can_be_zero, TCGv *count) +{ + MemOp ot = decode->op[0].ot; + int mask = (ot <= MO_32 ? 0x1f : 0x3f); + + *can_be_zero = false; + switch (decode->op[2].unit) { + case X86_OP_INT: + *count = tcg_temp_new(); + tcg_gen_andi_tl(*count, s->T1, mask); + *can_be_zero = true; + break; + + case X86_OP_IMM: + if ((decode->immediate & mask) == 0) { + *count = NULL; + break; + } + *count = tcg_temp_new(); + tcg_gen_movi_tl(*count, decode->immediate & mask); + break; + + case X86_OP_SKIP: + *count = tcg_temp_new(); + tcg_gen_movi_tl(*count, 1); + break; + + default: + g_assert_not_reached(); + } + + return ot; +} + +/* + * Compute existing flags in decode->cc_src, for gen_* functions that wants + * to set the cc_op set to CC_OP_ADCOX. In particular, this allows rotate + * operations to compute the carry in decode->cc_dst and the overflow in + * decode->cc_src2. + * + * If need_flags is true, decode->cc_dst and decode->cc_src2 are preloaded + * with the value of CF and OF before the instruction, so that it is possible + * to keep the flags unmodified. + * + * Return true if carry could be made available cheaply as a 1-bit value in + * decode->cc_dst (trying a bit harder if want_carry is true). If false is + * returned, decode->cc_dst is uninitialized and the carry is only available + * as bit 0 of decode->cc_src. + */ +static bool gen_eflags_adcox(DisasContext *s, X86DecodedInsn *decode, bool want_carry, bool need_flags) +{ + bool got_cf = false; + bool got_of = false; + + decode->cc_dst = tcg_temp_new(); + decode->cc_src = tcg_temp_new(); + decode->cc_src2 = tcg_temp_new(); + decode->cc_op = CC_OP_ADCOX; + + /* A lot more cc_ops could be "optimized" to avoid the extracts at + * the end (INC/DEC, BMILG, MUL), but they are all really unlikely + * to be followed by rotations within the same basic block. + */ + switch (s->cc_op) { + case CC_OP_ADCOX: + /* No need to compute the full EFLAGS, CF/OF are already isolated. */ + tcg_gen_mov_tl(decode->cc_src, cpu_cc_src); + if (need_flags) { + tcg_gen_mov_tl(decode->cc_src2, cpu_cc_src2); + got_of = true; + } + if (want_carry || need_flags) { + tcg_gen_mov_tl(decode->cc_dst, cpu_cc_dst); + got_cf = true; + } + break; + + case CC_OP_LOGICB ... CC_OP_LOGICQ: + /* CF and OF are zero, do it just because it's easy. */ + gen_mov_eflags(s, decode->cc_src); + if (need_flags) { + tcg_gen_movi_tl(decode->cc_src2, 0); + got_of = true; + } + if (want_carry || need_flags) { + tcg_gen_movi_tl(decode->cc_dst, 0); + got_cf = true; + } + break; + + case CC_OP_SARB ... CC_OP_SARQ: + /* + * SHR/RCR/SHR/RCR/... is a relatively common occurrence of RCR. + * By computing CF without using eflags, the calls to cc_compute_all + * can be eliminated as dead code (except for the last RCR). + */ + if (want_carry || need_flags) { + tcg_gen_andi_tl(decode->cc_dst, cpu_cc_src, 1); + got_cf = true; + } + gen_mov_eflags(s, decode->cc_src); + break; + + case CC_OP_SHLB ... CC_OP_SHLQ: + /* + * Likewise for SHL/RCL/SHL/RCL/... but, if CF is not in the sign + * bit, we might as well fish CF out of EFLAGS and save a shift. + */ + if (want_carry && (!need_flags || s->cc_op == CC_OP_SHLB + MO_TL)) { + tcg_gen_shri_tl(decode->cc_dst, cpu_cc_src, (8 << (s->cc_op - CC_OP_SHLB)) - 1); + got_cf = true; + } + gen_mov_eflags(s, decode->cc_src); + break; + + default: + gen_mov_eflags(s, decode->cc_src); + break; + } + + if (need_flags) { + /* If the flags could be left unmodified, always load them. */ + if (!got_of) { + tcg_gen_extract_tl(decode->cc_src2, decode->cc_src, ctz32(CC_O), 1); + got_of = true; + } + if (!got_cf) { + tcg_gen_extract_tl(decode->cc_dst, decode->cc_src, ctz32(CC_C), 1); + got_cf = true; + } + } + return got_cf; +} + +static void gen_rot_overflow(X86DecodedInsn *decode, TCGv result, TCGv old, TCGv count) +{ + MemOp ot = decode->op[0].ot; + TCGv temp = count ? tcg_temp_new() : decode->cc_src2; + + tcg_gen_xor_tl(temp, old, result); + tcg_gen_extract_tl(temp, temp, (8 << ot) - 1, 1); + if (count) { + tcg_gen_movcond_tl(TCG_COND_EQ, decode->cc_src2, count, tcg_constant_tl(0), + decode->cc_src2, temp); + } +} + +/* + * RCx operations are invariant modulo 8*operand_size+1. For 8 and 16-bit operands, + * this is less than 0x1f (the mask applied by gen_shift_count) so reduce further. + */ +static void gen_rotc_mod(MemOp ot, TCGv count) +{ + TCGv temp; + + switch (ot) { + case MO_8: + temp = tcg_temp_new(); + tcg_gen_subi_tl(temp, count, 18); + tcg_gen_movcond_tl(TCG_COND_GE, count, temp, tcg_constant_tl(0), temp, count); + tcg_gen_subi_tl(temp, count, 9); + tcg_gen_movcond_tl(TCG_COND_GE, count, temp, tcg_constant_tl(0), temp, count); + break; + + case MO_16: + temp = tcg_temp_new(); + tcg_gen_subi_tl(temp, count, 17); + tcg_gen_movcond_tl(TCG_COND_GE, count, temp, tcg_constant_tl(0), temp, count); + break; + + default: + break; + } +} + +/* + * The idea here is that the bit to the right of the new bit 0 is the + * new carry, and the bit to the right of the old bit 0 is the old carry. + * Just like a regular rotation, the result of the rotation is composed + * from a right shifted part and a left shifted part of s->T0. The new carry + * is extracted from the right-shifted portion, and the old carry is + * inserted at the end of the left-shifted portion. + * + * Because of the separate shifts involving the carry, gen_RCL and gen_RCR + * mostly operate on count-1. This also comes in handy when computing + * length - count, because (length-1) - (count-1) can be computed with + * a XOR, and that is commutative unlike subtraction. + */ +static void gen_RCL(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + bool have_1bit_cin, can_be_zero; + TCGv count; + TCGLabel *zero_label = NULL; + MemOp ot = gen_shift_count(s, decode, &can_be_zero, &count); + TCGv low = tcg_temp_new(); + TCGv high = tcg_temp_new(); + TCGv low_count = tcg_temp_new(); + + if (!count) { + return; + } + + gen_rotc_mod(ot, count); + have_1bit_cin = gen_eflags_adcox(s, decode, true, can_be_zero); + if (can_be_zero) { + zero_label = gen_new_label(); + tcg_gen_brcondi_tl(TCG_COND_EQ, count, 0, zero_label); + } + + /* Compute high part, including incoming carry. */ + if (!have_1bit_cin || TCG_TARGET_deposit_tl_valid(1, TARGET_LONG_BITS - 1)) { + /* high = (T0 << 1) | cin */ + TCGv cin = have_1bit_cin ? decode->cc_dst : decode->cc_src; + tcg_gen_deposit_tl(high, cin, s->T0, 1, TARGET_LONG_BITS - 1); + } else { + /* Same as above but without deposit; cin in cc_dst. */ + tcg_gen_add_tl(high, s->T0, decode->cc_dst); + tcg_gen_add_tl(high, high, s->T0); + } + tcg_gen_subi_tl(count, count, 1); + tcg_gen_shl_tl(high, high, count); + + /* Compute low part and outgoing carry, incoming s->T0 is zero extended */ + tcg_gen_xori_tl(low_count, count, (8 << ot) - 1); /* LENGTH - 1 - (count - 1) */ + tcg_gen_shr_tl(low, s->T0, low_count); + tcg_gen_andi_tl(decode->cc_dst, low, 1); + tcg_gen_shri_tl(low, low, 1); + + /* Compute result and outgoing overflow */ + tcg_gen_mov_tl(decode->cc_src2, s->T0); + tcg_gen_or_tl(s->T0, low, high); + gen_rot_overflow(decode, s->T0, decode->cc_src2, NULL); + + if (zero_label) { + gen_set_label(zero_label); + } +} + +static void gen_RCR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + bool have_1bit_cin, can_be_zero; + TCGv count; + TCGLabel *zero_label = NULL; + MemOp ot = gen_shift_count(s, decode, &can_be_zero, &count); + TCGv low = tcg_temp_new(); + TCGv high = tcg_temp_new(); + TCGv high_count = tcg_temp_new(); + + if (!count) { + return; + } + + gen_rotc_mod(ot, count); + have_1bit_cin = gen_eflags_adcox(s, decode, true, can_be_zero); + if (can_be_zero) { + zero_label = gen_new_label(); + tcg_gen_brcondi_tl(TCG_COND_EQ, count, 0, zero_label); + } + + /* Save incoming carry into high, it will be shifted later. */ + if (!have_1bit_cin || TCG_TARGET_deposit_tl_valid(1, TARGET_LONG_BITS - 1)) { + TCGv cin = have_1bit_cin ? decode->cc_dst : decode->cc_src; + tcg_gen_deposit_tl(high, cin, s->T0, 1, TARGET_LONG_BITS - 1); + } else { + /* Same as above but without deposit; cin in cc_dst. */ + tcg_gen_add_tl(high, s->T0, decode->cc_dst); + tcg_gen_add_tl(high, high, s->T0); + } + + /* Compute low part and outgoing carry, incoming s->T0 is zero extended */ + tcg_gen_subi_tl(count, count, 1); + tcg_gen_shr_tl(low, s->T0, count); + tcg_gen_andi_tl(decode->cc_dst, low, 1); + tcg_gen_shri_tl(low, low, 1); + + /* Move high part to the right position */ + tcg_gen_xori_tl(high_count, count, (8 << ot) - 1); /* LENGTH - 1 - (count - 1) */ + tcg_gen_shl_tl(high, high, high_count); + + /* Compute result and outgoing overflow */ + tcg_gen_mov_tl(decode->cc_src2, s->T0); + tcg_gen_or_tl(s->T0, low, high); + gen_rot_overflow(decode, s->T0, decode->cc_src2, NULL); + + if (zero_label) { + gen_set_label(zero_label); + } +} + +static void gen_RET(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + int16_t adjust = decode->e.op2 == X86_TYPE_I ? decode->immediate : 0; + + MemOp ot = gen_pop_T0(s); + gen_stack_update(s, adjust + (1 << ot)); + gen_op_jmp_v(s, s->T0); + gen_bnd_jmp(s); + s->base.is_jmp = DISAS_JUMP; +} + +static void gen_RETF(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + int16_t adjust = decode->e.op2 == X86_TYPE_I ? decode->immediate : 0; + + if (!PE(s) || VM86(s)) { + gen_stack_A0(s); + /* pop offset */ + gen_op_ld_v(s, s->dflag, s->T0, s->A0); + /* NOTE: keeping EIP updated is not a problem in case of + exception */ + gen_op_jmp_v(s, s->T0); + /* pop selector */ + gen_add_A0_im(s, 1 << s->dflag); + gen_op_ld_v(s, s->dflag, s->T0, s->A0); + gen_op_movl_seg_real(s, R_CS, s->T0); + /* add stack offset */ + gen_stack_update(s, adjust + (2 << s->dflag)); + } else { + gen_update_cc_op(s); + gen_update_eip_cur(s); + gen_helper_lret_protected(tcg_env, tcg_constant_i32(s->dflag - 1), + tcg_constant_i32(adjust)); + } + s->base.is_jmp = DISAS_EOB_ONLY; +} + +/* + * Return non-NULL if a 32-bit rotate works, after possibly replicating the input. + * The input has already been zero-extended upon operand decode. + */ +static TCGv_i32 gen_rot_replicate(MemOp ot, TCGv in) +{ + TCGv_i32 temp; + switch (ot) { + case MO_8: + temp = tcg_temp_new_i32(); + tcg_gen_trunc_tl_i32(temp, in); + tcg_gen_muli_i32(temp, temp, 0x01010101); + return temp; + + case MO_16: + temp = tcg_temp_new_i32(); + tcg_gen_trunc_tl_i32(temp, in); + tcg_gen_deposit_i32(temp, temp, temp, 16, 16); + return temp; + +#ifdef TARGET_X86_64 + case MO_32: + temp = tcg_temp_new_i32(); + tcg_gen_trunc_tl_i32(temp, in); + return temp; +#endif + + default: + return NULL; + } +} + +static void gen_rot_carry(X86DecodedInsn *decode, TCGv result, TCGv count, int bit) +{ + TCGv temp = count ? tcg_temp_new() : decode->cc_dst; + + tcg_gen_setcondi_tl(TCG_COND_TSTNE, temp, result, 1ULL << bit); + if (count) { + tcg_gen_movcond_tl(TCG_COND_EQ, decode->cc_dst, count, tcg_constant_tl(0), + decode->cc_dst, temp); + } +} + +static void gen_ROL(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + bool can_be_zero; + TCGv count; + MemOp ot = gen_shift_count(s, decode, &can_be_zero, &count); + TCGv_i32 temp32, count32; + TCGv old = tcg_temp_new(); + + if (!count) { + return; + } + + gen_eflags_adcox(s, decode, false, can_be_zero); + tcg_gen_mov_tl(old, s->T0); + temp32 = gen_rot_replicate(ot, s->T0); + if (temp32) { + count32 = tcg_temp_new_i32(); + tcg_gen_trunc_tl_i32(count32, count); + tcg_gen_rotl_i32(temp32, temp32, count32); + /* Zero extend to facilitate later optimization. */ + tcg_gen_extu_i32_tl(s->T0, temp32); + } else { + tcg_gen_rotl_tl(s->T0, s->T0, count); + } + gen_rot_carry(decode, s->T0, count, 0); + gen_rot_overflow(decode, s->T0, old, count); +} + +static void gen_ROR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + bool can_be_zero; + TCGv count; + MemOp ot = gen_shift_count(s, decode, &can_be_zero, &count); + TCGv_i32 temp32, count32; + TCGv old = tcg_temp_new(); + + if (!count) { + return; + } + + gen_eflags_adcox(s, decode, false, can_be_zero); + tcg_gen_mov_tl(old, s->T0); + temp32 = gen_rot_replicate(ot, s->T0); + if (temp32) { + count32 = tcg_temp_new_i32(); + tcg_gen_trunc_tl_i32(count32, count); + tcg_gen_rotr_i32(temp32, temp32, count32); + /* Zero extend to facilitate later optimization. */ + tcg_gen_extu_i32_tl(s->T0, temp32); + gen_rot_carry(decode, s->T0, count, 31); + } else { + tcg_gen_rotr_tl(s->T0, s->T0, count); + gen_rot_carry(decode, s->T0, count, TARGET_LONG_BITS - 1); + } + gen_rot_overflow(decode, s->T0, old, count); +} + static void gen_RORX(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { MemOp ot = decode->op[0].ot; @@ -2317,6 +3178,54 @@ static void gen_SAHF(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, s->T0); } +static void gen_SALC(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + gen_compute_eflags_c(s, s->T0); + tcg_gen_neg_tl(s->T0, s->T0); +} + +static void gen_shift_dynamic_flags(X86DecodedInsn *decode, TCGv count, TCGv old_eflags, CCOp cc_op) +{ + TCGv_i32 count32 = tcg_temp_new_i32(); + decode->cc_op = CC_OP_DYNAMIC; + decode->cc_op_dynamic = tcg_temp_new_i32(); + + tcg_gen_movcond_tl(TCG_COND_EQ, decode->cc_src, count, tcg_constant_tl(0), + old_eflags, decode->cc_src); + + tcg_gen_trunc_tl_i32(count32, count); + tcg_gen_movcond_i32(TCG_COND_EQ, decode->cc_op_dynamic, count32, tcg_constant_i32(0), + tcg_constant_i32(CC_OP_EFLAGS), tcg_constant_i32(cc_op)); +} + +static void gen_SAR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + bool can_be_zero; + TCGv count; + TCGv orig_flags = NULL; + MemOp ot = gen_shift_count(s, decode, &can_be_zero, &count); + + if (!count) { + return; + } + + if (can_be_zero) { + orig_flags = tcg_temp_new(); + gen_mov_eflags(s, orig_flags); + } + + decode->cc_dst = s->T0; + decode->cc_src = tcg_temp_new(); + tcg_gen_subi_tl(decode->cc_src, count, 1); + tcg_gen_sar_tl(decode->cc_src, s->T0, decode->cc_src); + tcg_gen_sar_tl(s->T0, s->T0, count); + if (can_be_zero) { + gen_shift_dynamic_flags(decode, count, orig_flags, CC_OP_SARB + ot); + } else { + decode->cc_op = CC_OP_SARB + ot; + } +} + static void gen_SARX(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { MemOp ot = decode->op[0].ot; @@ -2415,6 +3324,34 @@ static void gen_SHA256RNDS2(DisasContext *s, CPUX86State *env, X86DecodedInsn *d gen_helper_sha256rnds2(OP_PTR0, OP_PTR1, OP_PTR2, wk0, wk1); } +static void gen_SHL(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + bool can_be_zero; + TCGv count; + TCGv orig_flags = NULL; + MemOp ot = gen_shift_count(s, decode, &can_be_zero, &count); + + if (!count) { + return; + } + + if (can_be_zero) { + orig_flags = tcg_temp_new(); + gen_mov_eflags(s, orig_flags); + } + + decode->cc_dst = s->T0; + decode->cc_src = tcg_temp_new(); + tcg_gen_subi_tl(decode->cc_src, count, 1); + tcg_gen_shl_tl(decode->cc_src, s->T0, decode->cc_src); + tcg_gen_shl_tl(s->T0, s->T0, count); + if (can_be_zero) { + gen_shift_dynamic_flags(decode, count, orig_flags, CC_OP_SHLB + ot); + } else { + decode->cc_op = CC_OP_SHLB + ot; + } +} + static void gen_SHLX(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { MemOp ot = decode->op[0].ot; @@ -2425,6 +3362,34 @@ static void gen_SHLX(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) tcg_gen_shl_tl(s->T0, s->T0, s->T1); } +static void gen_SHR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + bool can_be_zero; + TCGv count; + TCGv orig_flags = NULL; + MemOp ot = gen_shift_count(s, decode, &can_be_zero, &count); + + if (!count) { + return; + } + + if (can_be_zero) { + orig_flags = tcg_temp_new(); + gen_mov_eflags(s, orig_flags); + } + + decode->cc_dst = s->T0; + decode->cc_src = tcg_temp_new(); + tcg_gen_subi_tl(decode->cc_src, count, 1); + tcg_gen_shr_tl(decode->cc_src, s->T0, decode->cc_src); + tcg_gen_shr_tl(s->T0, s->T0, count); + if (can_be_zero) { + gen_shift_dynamic_flags(decode, count, orig_flags, CC_OP_SARB + ot); + } else { + decode->cc_op = CC_OP_SARB + ot; + } +} + static void gen_SHRX(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { MemOp ot = decode->op[0].ot; @@ -2435,6 +3400,25 @@ static void gen_SHRX(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) tcg_gen_shr_tl(s->T0, s->T0, s->T1); } +static void gen_STC(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + gen_compute_eflags(s); + tcg_gen_ori_tl(cpu_cc_src, cpu_cc_src, CC_C); +} + +static void gen_STD(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + tcg_gen_st_i32(tcg_constant_i32(-1), tcg_env, offsetof(CPUX86State, df)); +} + +static void gen_STI(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + gen_set_eflags(s, IF_MASK); + /* interruptions are enabled only the first insn after sti */ + gen_update_eip_next(s); + gen_eob_inhibit_irq(s, true); +} + static void gen_VAESKEYGEN(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { TCGv_i32 imm = tcg_constant8u_i32(decode->immediate); @@ -2991,6 +3975,14 @@ static void gen_XCHG(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) } } +static void gen_XLAT(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + /* AL is already zero-extended into s->T0. */ + tcg_gen_add_tl(s->A0, cpu_regs[R_EBX], s->T0); + gen_add_A0_ds_seg(s); + gen_op_ld_v(s, MO_8, s->T0, s->A0); +} + static void gen_XOR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { /* special case XOR reg, reg */ From patchwork Tue Apr 9 16:43:16 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 13622963 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id ECD95CD128A for ; Tue, 9 Apr 2024 16:51:12 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ruEam-0001Kk-FJ; Tue, 09 Apr 2024 12:45:05 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ruEaB-0000eS-7K for qemu-devel@nongnu.org; Tue, 09 Apr 2024 12:44:30 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ruEZz-000866-PS for qemu-devel@nongnu.org; Tue, 09 Apr 2024 12:44:24 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1712681043; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=L2+pS5gGAJTQx3c6Aio5nN6ovM54dMMDDl89YZXL1qo=; b=J+WbW9Q90WhRXJaFPYAKhcUM6BOn5Fp7MNXDsZFcrBIRphAi2A5J9cE0LspfdTZ/+GUX57 +BXatZZF7UbTPlWQ7RtpVL2OA6T8ErEsjz99f38LYcuAL24q0ho+D9TGQxlP4PJSOahakL FAc3UyFy3zelLDqNOqe1efIMwWPajj4= Received: from mail-wm1-f69.google.com (mail-wm1-f69.google.com [209.85.128.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-394-rscPBydFM0KV37bJbhXq4g-1; Tue, 09 Apr 2024 12:44:01 -0400 X-MC-Unique: rscPBydFM0KV37bJbhXq4g-1 Received: by mail-wm1-f69.google.com with SMTP id 5b1f17b1804b1-416b3409164so2866115e9.1 for ; Tue, 09 Apr 2024 09:44:01 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712681040; x=1713285840; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=L2+pS5gGAJTQx3c6Aio5nN6ovM54dMMDDl89YZXL1qo=; b=Iz3SIClMXGX17aDo8NFG0UTHlokfzqHKVpwCku3KbrShTV+c8E8bN08EaMf/6wYsK6 blQ4hWqpK+TeuHDM59sKv+BH2ncOBUZPmdinQWlCoXT6ww1i8oIJvO8tibbe64D38V6w PXLPKNnQApB37UVfXcEKGZPUkVQpTXDJoDPX8Tp1lwYkKJAhwDgwvyTEhnWFA54qzAi3 D1o9JOYMZZaSrI4pRvwodD3DeMHXnHUOZEgHatbl9Tmg1hVHgeVNCWp0dE4pPHdmE336 T5jmtvu4KLurA+YdVFioziJm1lObkvMIdWfu8yR9BG8MFIJhR24+jLJWF4PFzSuh7k1o wU2w== X-Gm-Message-State: AOJu0YxF613MOCmgLmxKAIrq2Zts0HXzLyIe2h7Hy+OKs1yr9X6joLny mragcDTUY7+oCPMrIQOgQdwQEc20C6cSm/Jj1jpRxVDH6MWxchpu0rxUFFE4kh2FrOQ895WKU3p Ds5e6l8gDI/qR+BUUR9mwbZGneIsYLa6xqOIKejh5t+6RokAIexL46CHkkNGvPHz4OWJu/tLfbt 0eAi8KcTVonVY/oFA7rt1EVm1Pm98zkp2ZUUJ8 X-Received: by 2002:a05:600c:4f94:b0:416:9836:c33a with SMTP id n20-20020a05600c4f9400b004169836c33amr181474wmq.29.1712681040210; Tue, 09 Apr 2024 09:44:00 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHXeNgaMig3JtXnmDOkU7DLtwG5/kMlXyMtyekxLNZ6BCAub5tZqwKT7wt5zqSKqUwCH/AvIg== X-Received: by 2002:a05:600c:4f94:b0:416:9836:c33a with SMTP id n20-20020a05600c4f9400b004169836c33amr181465wmq.29.1712681039945; Tue, 09 Apr 2024 09:43:59 -0700 (PDT) Received: from avogadro.local ([151.95.152.232]) by smtp.gmail.com with ESMTPSA id jg1-20020a05600ca00100b00414688af147sm21015170wmb.20.2024.04.09.09.43.58 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 09 Apr 2024 09:43:58 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Subject: [PATCH for-9.1 12/19] target/i386: merge and enlarge a few ranges for call to disas_insn_new Date: Tue, 9 Apr 2024 18:43:16 +0200 Message-ID: <20240409164323.776660-13-pbonzini@redhat.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240409164323.776660-1-pbonzini@redhat.com> References: <20240409164323.776660-1-pbonzini@redhat.com> MIME-Version: 1.0 Received-SPF: pass client-ip=170.10.133.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -37 X-Spam_score: -3.8 X-Spam_bar: --- X-Spam_report: (-3.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1.701, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_PASS=-0.001, T_SPF_HELO_TEMPERROR=0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Since new opcodes are not going to be added in translate.c, round the case labels that call to disas_insn_new(), including whole sets of eight opcodes when possible. Signed-off-by: Paolo Bonzini Reviewed-by: Richard Henderson --- target/i386/tcg/translate.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 720668e023a..26e4c7520db 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -6866,9 +6866,8 @@ static bool disas_insn(DisasContext *s, CPUState *cpu) break; case 0x10e ... 0x117: case 0x128 ... 0x12f: - case 0x138 ... 0x13a: - case 0x150 ... 0x179: - case 0x17c ... 0x17f: + case 0x138 ... 0x13f: + case 0x150 ... 0x17f: case 0x1c2: case 0x1c4 ... 0x1c6: case 0x1d0 ... 0x1fe: From patchwork Tue Apr 9 16:43:17 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 13622961 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 6BC59CD128A for ; Tue, 9 Apr 2024 16:50:38 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ruEai-0001AF-E1; Tue, 09 Apr 2024 12:45:00 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ruEa9-0000eG-7m for qemu-devel@nongnu.org; Tue, 09 Apr 2024 12:44:27 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ruEZz-00086f-TU for qemu-devel@nongnu.org; Tue, 09 Apr 2024 12:44:22 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1712681048; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=3dBjfULU0sDr337Hpo9NybkNaRsnBMREB60wbOp5+4s=; b=KuqhP/qbDw6CH9lcVQ1RyVQpe1m7bfrEqJPdUBXSATHQ4SfCVnaIkpBnHtlvaXqZJSB3kz KygiRMClSJQ1DqZ8rW04YKq7nPMJ2W1y1SbbFHkQnAn4OcIaq+AkWiVgf2HPxKi5utPVnL foQVK9HxFbY4UHKR++XsDPdfHzMvTtQ= Received: from mail-wm1-f72.google.com (mail-wm1-f72.google.com [209.85.128.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-448-J7rRhDCjOh2rHNxbw46I4g-1; Tue, 09 Apr 2024 12:44:04 -0400 X-MC-Unique: J7rRhDCjOh2rHNxbw46I4g-1 Received: by mail-wm1-f72.google.com with SMTP id 5b1f17b1804b1-416ac21981dso4592025e9.1 for ; Tue, 09 Apr 2024 09:44:04 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712681043; x=1713285843; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=3dBjfULU0sDr337Hpo9NybkNaRsnBMREB60wbOp5+4s=; b=RPVy7H35mG68OCaBe5BXFQ48SuGAUPr5Ja+WQVIWuPE163DusUN8ejoduyUsiIhcL9 VMb2mwYxUZatOhxSOWrp652Zqo9apiR1dvOEMjnZ6APlRtaJLAclbo37lfsMs+FXSW0+ 3DEYYQrVQOcvrPYZFC9yozCDBP+mbxPXWE+6IVJ0qlQ17aBlDXSgS9XP4r7EXJ9owX1m okSZAbZAEFd/bM3PLS4XrcCpWQctw5YOjI83fvsQmRWdQzXmY7pfS0w85QOEwlRmtUKD F3FMlj6f9Vc1FRVLG0sTGZrHqFbMGqlyXB5yJXvmVQrLh9ilzJHo4pz1RvQPnAWsBBBG /5Tw== X-Gm-Message-State: AOJu0Yycu9zTm701JmDcqsJVVe4pS4cyFL4Q/CBXEhKUv+IQA0bIG8oe GsLAOSui4p4mU4CV5z4xH9VKvVPMfYeKDZnmmL02s2+Y4R/jwBKkcAtSbaOq1aUCkvY9j7doIJq uvQ8wfdqEPzUMkAYYuo7fjPJQQI44h+AWmPMgESfpqXJdggij0KlIdaPcIM8Nbci7GlDhQgppEQ E/ZchwLnf7l7h1sOnF2KGUI807YUalBhMJRsh3 X-Received: by 2002:a05:600c:4748:b0:416:2674:1938 with SMTP id w8-20020a05600c474800b0041626741938mr2857646wmo.15.1712681043056; Tue, 09 Apr 2024 09:44:03 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHZ+44dp/Q4EGhHP+Mcxv1+Zq4yiOiyKIXBr3JvlcW69FFI3hkowXBHdyu4HdBi6a1iJLd09A== X-Received: by 2002:a05:600c:4748:b0:416:2674:1938 with SMTP id w8-20020a05600c474800b0041626741938mr2857627wmo.15.1712681042637; Tue, 09 Apr 2024 09:44:02 -0700 (PDT) Received: from avogadro.local ([151.95.152.232]) by smtp.gmail.com with ESMTPSA id p14-20020a05600c358e00b0041674bf7d4csm7851084wmq.48.2024.04.09.09.44.01 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 09 Apr 2024 09:44:02 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Subject: [PATCH for-9.1 13/19] target/i386: move remaining conditional operations to new decoder Date: Tue, 9 Apr 2024 18:43:17 +0200 Message-ID: <20240409164323.776660-14-pbonzini@redhat.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240409164323.776660-1-pbonzini@redhat.com> References: <20240409164323.776660-1-pbonzini@redhat.com> MIME-Version: 1.0 Received-SPF: pass client-ip=170.10.133.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -37 X-Spam_score: -3.8 X-Spam_bar: --- X-Spam_report: (-3.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1.701, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_PASS=-0.001, T_SPF_HELO_TEMPERROR=0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Move long-displacement Jcc, SETcc and CMOVcc to the new decoder. While filling in the tables makes the code seem longer, the new emitters are all just one line of code. Signed-off-by: Paolo Bonzini Reviewed-by: Richard Henderson --- target/i386/tcg/decode-new.h | 1 + target/i386/tcg/translate.c | 2 +- target/i386/tcg/decode-new.c.inc | 56 ++++++++++++++++++++++++++++++++ target/i386/tcg/emit.c.inc | 10 ++++++ 4 files changed, 68 insertions(+), 1 deletion(-) diff --git a/target/i386/tcg/decode-new.h b/target/i386/tcg/decode-new.h index 77bb31eb143..cd7ceca21e8 100644 --- a/target/i386/tcg/decode-new.h +++ b/target/i386/tcg/decode-new.h @@ -106,6 +106,7 @@ typedef enum X86CPUIDFeature { X86_FEAT_AVX2, X86_FEAT_BMI1, X86_FEAT_BMI2, + X86_FEAT_CMOV, X86_FEAT_CMPCCXADD, X86_FEAT_F16C, X86_FEAT_FMA, diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 26e4c7520db..f3c437aee88 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -3209,7 +3209,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu) #ifndef CONFIG_USER_ONLY use_new &= b <= limit; #endif - if (use_new && 0) { + if (use_new && (b >= 0x138 && b <= 0x19f)) { disas_insn_new(s, cpu, b); return true; } diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc index 87ae63faf9a..36eb53515af 100644 --- a/target/i386/tcg/decode-new.c.inc +++ b/target/i386/tcg/decode-new.c.inc @@ -993,6 +993,15 @@ static const X86OpEntry opcodes_0F[256] = { /* Incorrectly listed as Mq,Vq in the manual */ [0x17] = X86_OP_ENTRY3(VMOVHPx_st, M,q, None,None, V,dq, vex5 p_00_66), + [0x40] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)), + [0x41] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)), + [0x42] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)), + [0x43] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)), + [0x44] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)), + [0x45] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)), + [0x46] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)), + [0x47] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)), + [0x50] = X86_OP_ENTRY3(MOVMSK, G,y, None,None, U,x, vex7 p_00_66), [0x51] = X86_OP_GROUP3(sse_unary, V,x, H,x, W,x, vex2_rep3 p_00_66_f3_f2), /* sqrtps */ [0x52] = X86_OP_GROUP3(sse_unary, V,x, H,x, W,x, vex4_rep5 p_00_f3), /* rsqrtps */ @@ -1020,6 +1029,24 @@ static const X86OpEntry opcodes_0F[256] = { [0x76] = X86_OP_ENTRY3(PCMPEQD, V,x, H,x, W,x, vex4 mmx avx2_256 p_00_66), [0x77] = X86_OP_GROUP0(0F77), + [0x80] = X86_OP_ENTRYr(Jcc, J,z_f64), + [0x81] = X86_OP_ENTRYr(Jcc, J,z_f64), + [0x82] = X86_OP_ENTRYr(Jcc, J,z_f64), + [0x83] = X86_OP_ENTRYr(Jcc, J,z_f64), + [0x84] = X86_OP_ENTRYr(Jcc, J,z_f64), + [0x85] = X86_OP_ENTRYr(Jcc, J,z_f64), + [0x86] = X86_OP_ENTRYr(Jcc, J,z_f64), + [0x87] = X86_OP_ENTRYr(Jcc, J,z_f64), + + [0x90] = X86_OP_ENTRYw(SETcc, E,b), + [0x91] = X86_OP_ENTRYw(SETcc, E,b), + [0x92] = X86_OP_ENTRYw(SETcc, E,b), + [0x93] = X86_OP_ENTRYw(SETcc, E,b), + [0x94] = X86_OP_ENTRYw(SETcc, E,b), + [0x95] = X86_OP_ENTRYw(SETcc, E,b), + [0x96] = X86_OP_ENTRYw(SETcc, E,b), + [0x97] = X86_OP_ENTRYw(SETcc, E,b), + [0x28] = X86_OP_ENTRY3(MOVDQ, V,x, None,None, W,x, vex1 p_00_66), /* MOVAPS */ [0x29] = X86_OP_ENTRY3(MOVDQ, W,x, None,None, V,x, vex1 p_00_66), /* MOVAPS */ [0x2A] = X86_OP_GROUP0(0F2A), @@ -1032,6 +1059,15 @@ static const X86OpEntry opcodes_0F[256] = { [0x38] = X86_OP_GROUP0(0F38), [0x3a] = X86_OP_GROUP0(0F3A), + [0x48] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)), + [0x49] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)), + [0x4a] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)), + [0x4b] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)), + [0x4c] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)), + [0x4d] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)), + [0x4e] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)), + [0x4f] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)), + [0x58] = X86_OP_ENTRY3(VADD, V,x, H,x, W,x, vex2_rep3 p_00_66_f3_f2), [0x59] = X86_OP_ENTRY3(VMUL, V,x, H,x, W,x, vex2_rep3 p_00_66_f3_f2), [0x5a] = X86_OP_GROUP0(0F5A), @@ -1057,6 +1093,24 @@ static const X86OpEntry opcodes_0F[256] = { [0x7e] = X86_OP_GROUP0(0F7E), [0x7f] = X86_OP_GROUP0(0F7F), + [0x88] = X86_OP_ENTRYr(Jcc, J,z_f64), + [0x89] = X86_OP_ENTRYr(Jcc, J,z_f64), + [0x8a] = X86_OP_ENTRYr(Jcc, J,z_f64), + [0x8b] = X86_OP_ENTRYr(Jcc, J,z_f64), + [0x8c] = X86_OP_ENTRYr(Jcc, J,z_f64), + [0x8d] = X86_OP_ENTRYr(Jcc, J,z_f64), + [0x8e] = X86_OP_ENTRYr(Jcc, J,z_f64), + [0x8f] = X86_OP_ENTRYr(Jcc, J,z_f64), + + [0x98] = X86_OP_ENTRYw(SETcc, E,b), + [0x99] = X86_OP_ENTRYw(SETcc, E,b), + [0x9a] = X86_OP_ENTRYw(SETcc, E,b), + [0x9b] = X86_OP_ENTRYw(SETcc, E,b), + [0x9c] = X86_OP_ENTRYw(SETcc, E,b), + [0x9d] = X86_OP_ENTRYw(SETcc, E,b), + [0x9e] = X86_OP_ENTRYw(SETcc, E,b), + [0x9f] = X86_OP_ENTRYw(SETcc, E,b), + [0xae] = X86_OP_GROUP0(group15), [0xc2] = X86_OP_ENTRY4(VCMP, V,x, H,x, W,x, vex2_rep3 p_00_66_f3_f2), @@ -1917,6 +1971,8 @@ static bool has_cpuid_feature(DisasContext *s, X86CPUIDFeature cpuid) switch (cpuid) { case X86_FEAT_None: return true; + case X86_FEAT_CMOV: + return (s->cpuid_features & CPUID_CMOV); case X86_FEAT_F16C: return (s->cpuid_ext_features & CPUID_EXT_F16C); case X86_FEAT_FMA: diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc index 07f9b506043..dc5142be51f 100644 --- a/target/i386/tcg/emit.c.inc +++ b/target/i386/tcg/emit.c.inc @@ -1375,6 +1375,11 @@ static void gen_CMC(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) tcg_gen_xori_tl(cpu_cc_src, cpu_cc_src, CC_C); } +static void gen_CMOVcc(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + gen_cmovcc1(s, decode->b & 0xf, s->T0, s->T1); +} + static void gen_CMPccXADD(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { TCGLabel *label_top = gen_new_label(); @@ -3270,6 +3275,11 @@ static void gen_SCAS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) } } +static void gen_SETcc(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + gen_setcc1(s, decode->b & 0xf, s->T0); +} + static void gen_SHA1NEXTE(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { gen_helper_sha1nexte(OP_PTR0, OP_PTR1, OP_PTR2); From patchwork Tue Apr 9 16:43:18 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 13622954 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id B2BD5CD1297 for ; Tue, 9 Apr 2024 16:47:09 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ruEaq-0001Xx-M5; Tue, 09 Apr 2024 12:45:08 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ruEaL-0000hU-WE for qemu-devel@nongnu.org; Tue, 09 Apr 2024 12:44:44 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ruEa3-00086o-85 for qemu-devel@nongnu.org; Tue, 09 Apr 2024 12:44:35 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1712681049; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=I+IkkhB9pl1S2fDACEPQ2ZBXV/CaDauOuRUxY+FYR0I=; b=LQ4ObRVVsOQgHyUQUAWXMZB5cDmYQjeTkHZAvm5oOq7TgU5mwg64a2vVIjvjbG+l8PM606 vmS9t8jZVO4PhzTC1hNMP4XR30NVCNTga1NGLERymrhzlhGC8LKpp+f//MMQT1jgN8xDe6 16Kau8Ol1U5UF84QopcpF6Jg05woj4w= Received: from mail-wr1-f70.google.com (mail-wr1-f70.google.com [209.85.221.70]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-630-0Q5D_zMZPWuCWT7FV6cYRA-1; Tue, 09 Apr 2024 12:44:07 -0400 X-MC-Unique: 0Q5D_zMZPWuCWT7FV6cYRA-1 Received: by mail-wr1-f70.google.com with SMTP id ffacd0b85a97d-343e46df264so2387999f8f.1 for ; Tue, 09 Apr 2024 09:44:07 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712681045; x=1713285845; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=I+IkkhB9pl1S2fDACEPQ2ZBXV/CaDauOuRUxY+FYR0I=; b=YqGFM6fs8kdnWkeqBZWNCtw5tRpRJHEHqiK2CI9ofH7drIHQeEM5DXJCyxrWtLRFCN TtYQu8Ie77H39Ct10N8EBj+s+WZD0nR9TDoubt/rtEkviDum3CbhPwPfkocbtgkwpB2D N8UuWVBTCrgNlFfsXIwwvhRuiHbC05sARDoKeZ+Zq/zidin12hsyBsGkVkpBzAW1psma ClpzSouMdIVkg6D2V+w6WdNM5i/Ht4g9WP95kaPwj4JX6AFEmkwZWP0lBBB3dOQIUYxn /GzNWQARmfTrYyeJDCkm+xEJGQNZfzcYB5y+vbXJV7Z+FhmmiYvM6jyBZUPdpDJ7pML5 HLnA== X-Gm-Message-State: AOJu0YwCp0gSQAQvFo1XG2vKyRqEeE+KdaTbvKPgs82aSBwzNF4P8xz6 GKSuRpugBa+pR6uo/mXQA2aaUa3Aar9/c6yu6yxdV7jLdnCCzIt3wtC/gY5HVRuF9ima0qbp77I gL7kwXz+Yxdoji6d29Xb1YlPbR9kek9CugJUFutSy4khAtlDTLtiX9JaxCToP6kIMpMP7OfzOlS y5rrzuUp+VoNG1eZtOZ75V+4N/6dQe1Gic3Sqm X-Received: by 2002:a7b:ce0a:0:b0:416:bc07:a8a6 with SMTP id m10-20020a7bce0a000000b00416bc07a8a6mr199446wmc.23.1712681045592; Tue, 09 Apr 2024 09:44:05 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFJ1HSkvs2II1d4f9kGFZY4BDpoNsVxC0VVmHDtHpZZp+Q/VuqwIvO8Ku/JuQGKa/gPCuoXNw== X-Received: by 2002:a7b:ce0a:0:b0:416:bc07:a8a6 with SMTP id m10-20020a7bce0a000000b00416bc07a8a6mr199433wmc.23.1712681045233; Tue, 09 Apr 2024 09:44:05 -0700 (PDT) Received: from avogadro.local ([151.95.152.232]) by smtp.gmail.com with ESMTPSA id v19-20020a05600c471300b004157ff88ad7sm17999812wmo.7.2024.04.09.09.44.04 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 09 Apr 2024 09:44:04 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Subject: [PATCH for-9.1 14/19] target/i386: move BSWAP to new decoder Date: Tue, 9 Apr 2024 18:43:18 +0200 Message-ID: <20240409164323.776660-15-pbonzini@redhat.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240409164323.776660-1-pbonzini@redhat.com> References: <20240409164323.776660-1-pbonzini@redhat.com> MIME-Version: 1.0 Received-SPF: pass client-ip=170.10.133.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -37 X-Spam_score: -3.8 X-Spam_bar: --- X-Spam_report: (-3.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1.701, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Signed-off-by: Paolo Bonzini Reviewed-by: Richard Henderson --- target/i386/tcg/translate.c | 4 +++- target/i386/tcg/decode-new.c.inc | 9 +++++++++ target/i386/tcg/emit.c.inc | 11 +++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index f3c437aee88..a1e6e8ec7d9 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -3209,7 +3209,9 @@ static bool disas_insn(DisasContext *s, CPUState *cpu) #ifndef CONFIG_USER_ONLY use_new &= b <= limit; #endif - if (use_new && (b >= 0x138 && b <= 0x19f)) { + if (use_new && + ((b >= 0x138 && b <= 0x19f) || + (b >= 0x1c8 && b <= 0x1cf))) { disas_insn_new(s, cpu, b); return true; } diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc index 36eb53515af..2ee949b50e2 100644 --- a/target/i386/tcg/decode-new.c.inc +++ b/target/i386/tcg/decode-new.c.inc @@ -1118,6 +1118,15 @@ static const X86OpEntry opcodes_0F[256] = { [0xc5] = X86_OP_ENTRY3(PEXTRW, G,d, U,dq,I,b, vex5 mmx p_00_66), [0xc6] = X86_OP_ENTRY4(VSHUF, V,x, H,x, W,x, vex4 p_00_66), + [0xc8] = X86_OP_ENTRY1(BSWAP, LoBits,y), + [0xc9] = X86_OP_ENTRY1(BSWAP, LoBits,y), + [0xca] = X86_OP_ENTRY1(BSWAP, LoBits,y), + [0xcb] = X86_OP_ENTRY1(BSWAP, LoBits,y), + [0xcc] = X86_OP_ENTRY1(BSWAP, LoBits,y), + [0xcd] = X86_OP_ENTRY1(BSWAP, LoBits,y), + [0xce] = X86_OP_ENTRY1(BSWAP, LoBits,y), + [0xcf] = X86_OP_ENTRY1(BSWAP, LoBits,y), + [0xd0] = X86_OP_ENTRY3(VADDSUB, V,x, H,x, W,x, vex2 cpuid(SSE3) p_66_f2), [0xd1] = X86_OP_ENTRY3(PSRLW_r, V,x, H,x, W,x, vex4 mmx avx2_256 p_00_66), [0xd2] = X86_OP_ENTRY3(PSRLD_r, V,x, H,x, W,x, vex4 mmx avx2_256 p_00_66), diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc index dc5142be51f..1dc246f8c1e 100644 --- a/target/i386/tcg/emit.c.inc +++ b/target/i386/tcg/emit.c.inc @@ -1299,6 +1299,17 @@ static void gen_BOUND(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) } } +static void gen_BSWAP(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ +#ifdef TARGET_X86_64 + if (s->dflag == MO_64) { + tcg_gen_bswap64_i64(s->T0, s->T0); + return; + } +#endif + tcg_gen_bswap32_tl(s->T0, s->T0, TCG_BSWAP_OZ); +} + static void gen_BZHI(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { MemOp ot = decode->op[0].ot; From patchwork Tue Apr 9 16:43:19 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 13622950 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id BAAA8C67861 for ; Tue, 9 Apr 2024 16:45:20 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ruEaZ-0000q6-T7; Tue, 09 Apr 2024 12:44:51 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ruEaE-0000es-L7 for qemu-devel@nongnu.org; Tue, 09 Apr 2024 12:44:33 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ruEa1-00087D-9V for qemu-devel@nongnu.org; Tue, 09 Apr 2024 12:44:30 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1712681051; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=wlu7b7TOekeVXIs0YLd//Se9WSGm5c3+rStDiPl90VM=; b=XPeu44w525Xjqry5lB+8YW4GNiYvfEiYlw0kDaL5KKTBu0vYBJZTohNAJh/qE8u3Pz/yvE qqodXXrFjRxqMhxpiPKQfyTIa+NJZTs4d9ZfouUx8ZZEeghk/YcIe9p90BhaenhpIFDUBv YJmj8giuNWaPRjFIO896aTrC/Zg7Z7U= Received: from mail-wr1-f72.google.com (mail-wr1-f72.google.com [209.85.221.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-58-g8zM3X1COuqo1dyGffnvcA-1; Tue, 09 Apr 2024 12:44:09 -0400 X-MC-Unique: g8zM3X1COuqo1dyGffnvcA-1 Received: by mail-wr1-f72.google.com with SMTP id ffacd0b85a97d-343ee8b13aeso2752388f8f.2 for ; Tue, 09 Apr 2024 09:44:09 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712681048; x=1713285848; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=wlu7b7TOekeVXIs0YLd//Se9WSGm5c3+rStDiPl90VM=; b=DhJLSNRLujPsN1SEZju5iS9b1JoKL8e+W9nvmhgnR/TAGcl1q+/CE2HR+um587hnqP W4LqhYV3qmwNXuuouRogmKcrpyDHWaV8sHgqMGg6KZTG4yULPPh9s0fGESkL8yCrAHFh 8nLX+9n0LIGebMDhGYQOEEkTZoCjzL3S1WgCccokRHFkFiU1Tv6VPBwqO5JMhCD5KFSD vSvOSfb9fqaENCmU0hJ4NnAgcZHvygjoJMmQadpruC7fyClNccxC8+5rsFYnjQt+2aku gM8Aj7cjXnCwvGzgdPScdbYK/VVX37jchwSBhsGHy/UiQOZ+z54en0UwK2Kgdiz/lFDt Mf8g== X-Gm-Message-State: AOJu0YzQcVbK2pEvQyql6Bg7+CIEmUmNskav4M+c/yY8HJZ9EDzhXJv+ 9PmGj+h1EbnRgOFOvrQ2EGJOswYdOgtKxR3bqFKy3Kz8rHB7ecFs8Lh5DhTLglmSRo+9kNTs5/A 5zJBbgR/f3bWMky9aVJj4ZDu/npouc+AVssv2Hr6pvD5F9DH+sKs4AaxRYnmDiY4MIaJ+QWmnty f3CMnQpV1GXCZDVe4JhQ5p7MJMHDnaWKBf6R3Z X-Received: by 2002:adf:f1c4:0:b0:343:a337:f380 with SMTP id z4-20020adff1c4000000b00343a337f380mr244819wro.19.1712681048397; Tue, 09 Apr 2024 09:44:08 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHoRVmUgn+2o5l4YRHNlGb6YqgiaXTUPL4H8R8dh59TvLf9NtjNoVcyUuiB9k5I8UjKAXTixQ== X-Received: by 2002:adf:f1c4:0:b0:343:a337:f380 with SMTP id z4-20020adff1c4000000b00343a337f380mr244804wro.19.1712681048059; Tue, 09 Apr 2024 09:44:08 -0700 (PDT) Received: from avogadro.local ([151.95.152.232]) by smtp.gmail.com with ESMTPSA id k2-20020a5d5242000000b00343c0c24a65sm11841262wrc.89.2024.04.09.09.44.07 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 09 Apr 2024 09:44:07 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Subject: [PATCH for-9.1 15/19] target/i386: port extensions of one-byte opcodes to new decoder Date: Tue, 9 Apr 2024 18:43:19 +0200 Message-ID: <20240409164323.776660-16-pbonzini@redhat.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240409164323.776660-1-pbonzini@redhat.com> References: <20240409164323.776660-1-pbonzini@redhat.com> MIME-Version: 1.0 Received-SPF: pass client-ip=170.10.133.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -37 X-Spam_score: -3.8 X-Spam_bar: --- X-Spam_report: (-3.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1.701, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, T_SPF_HELO_TEMPERROR=0.01, T_SPF_TEMPERROR=0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org A few two-byte opcodes are simple extensions of existing one-byte opcodes; they are easy to decode and need no change to emit.c.inc. Port them to the new decoder. Signed-off-by: Paolo Bonzini Reviewed-by: Richard Henderson --- target/i386/tcg/decode-new.h | 1 + target/i386/tcg/translate.c | 4 ++++ target/i386/tcg/decode-new.c.inc | 27 +++++++++++++++++++++++++++ target/i386/tcg/emit.c.inc | 15 +++++++++++++++ 4 files changed, 47 insertions(+) diff --git a/target/i386/tcg/decode-new.h b/target/i386/tcg/decode-new.h index cd7ceca21e8..2ea06b44787 100644 --- a/target/i386/tcg/decode-new.h +++ b/target/i386/tcg/decode-new.h @@ -47,6 +47,7 @@ typedef enum X86OpType { X86_TYPE_Y, /* string destination */ /* Custom */ + X86_TYPE_EM, /* modrm byte selects an ALU memory operand */ X86_TYPE_WM, /* modrm byte selects an XMM/YMM memory operand */ X86_TYPE_I_unsigned, /* Immediate, zero-extended */ X86_TYPE_2op, /* 2-operand RMW instruction */ diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index a1e6e8ec7d9..e8352d43678 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -3211,6 +3211,10 @@ static bool disas_insn(DisasContext *s, CPUState *cpu) #endif if (use_new && ((b >= 0x138 && b <= 0x19f) || + (b & ~9) == 0x1a0 || + b == 0x1af || b == 0x1b2 || + (b >= 0x1b4 && b <= 0x1b7) || + b == 0x1be || b == 0x1bf || b == 0x1c3 || (b >= 0x1c8 && b <= 0x1cf))) { disas_insn_new(s, cpu, b); return true; diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc index 2ee949b50e2..2e27d28dc95 100644 --- a/target/i386/tcg/decode-new.c.inc +++ b/target/i386/tcg/decode-new.c.inc @@ -43,6 +43,12 @@ * Operand types * ------------- * + * For memory-only operands, if the emitter functions wants to rely on + * generic load and writeback, the decoder needs to know the type of the + * operand. Therefore, M is often replaced by the more specific EM and WM + * (respectively selecting an ALU operand, like the operand type E, or a + * vector operand like the operand type W). + * * Immediates are almost always signed or masked away in helpers. Two * common exceptions are IN/OUT and absolute jumps. For these, there is * an additional custom operand type "I_unsigned". Alternatively, the @@ -1047,6 +1053,9 @@ static const X86OpEntry opcodes_0F[256] = { [0x96] = X86_OP_ENTRYw(SETcc, E,b), [0x97] = X86_OP_ENTRYw(SETcc, E,b), + [0xa0] = X86_OP_ENTRYr(PUSH, FS, w), + [0xa1] = X86_OP_ENTRYw(POP, FS, w), + [0x28] = X86_OP_ENTRY3(MOVDQ, V,x, None,None, W,x, vex1 p_00_66), /* MOVAPS */ [0x29] = X86_OP_ENTRY3(MOVDQ, W,x, None,None, V,x, vex1 p_00_66), /* MOVAPS */ [0x2A] = X86_OP_GROUP0(0F2A), @@ -1111,9 +1120,22 @@ static const X86OpEntry opcodes_0F[256] = { [0x9e] = X86_OP_ENTRYw(SETcc, E,b), [0x9f] = X86_OP_ENTRYw(SETcc, E,b), + [0xa8] = X86_OP_ENTRYr(PUSH, GS, w), + [0xa9] = X86_OP_ENTRYw(POP, GS, w), [0xae] = X86_OP_GROUP0(group15), + [0xaf] = X86_OP_ENTRY2(IMUL3, G,v, E,v), + + [0xb2] = X86_OP_ENTRY3(LSS, G,v, M,p, None, None), + [0xb4] = X86_OP_ENTRY3(LFS, G,v, M,p, None, None), + [0xb5] = X86_OP_ENTRY3(LGS, G,v, M,p, None, None), + [0xb6] = X86_OP_ENTRY3(MOV, G,v, E,b, None, None, zextT0), /* MOVZX */ + [0xb7] = X86_OP_ENTRY3(MOV, G,v, E,w, None, None, zextT0), /* MOVZX */ + + [0xbe] = X86_OP_ENTRY3(MOV, G,v, E,b, None, None, sextT0), /* MOVSX */ + [0xbf] = X86_OP_ENTRY3(MOV, G,v, E,w, None, None, sextT0), /* MOVSX */ [0xc2] = X86_OP_ENTRY4(VCMP, V,x, H,x, W,x, vex2_rep3 p_00_66_f3_f2), + [0xc3] = X86_OP_ENTRY3(MOV, EM,y,G,y, None,None, cpuid(SSE2)), /* MOVNTI */ [0xc4] = X86_OP_ENTRY4(PINSRW, V,dq,H,dq,E,w, vex5 mmx p_00_66), [0xc5] = X86_OP_ENTRY3(PEXTRW, G,d, U,dq,I,b, vex5 mmx p_00_66), [0xc6] = X86_OP_ENTRY4(VSHUF, V,x, H,x, W,x, vex4 p_00_66), @@ -1814,8 +1836,13 @@ static bool decode_op(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode, case X86_TYPE_WM: /* modrm byte selects an XMM/YMM memory operand */ op->unit = X86_OP_SSE; + goto get_modrm_mem; + + case X86_TYPE_EM: /* modrm byte selects an ALU memory operand */ + op->unit = X86_OP_INT; /* fall through */ case X86_TYPE_M: /* modrm byte selects a memory operand */ + get_modrm_mem: modrm = get_modrm(s, env); if ((modrm >> 6) == 3) { return false; diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc index 1dc246f8c1e..35bb56c750e 100644 --- a/target/i386/tcg/emit.c.inc +++ b/target/i386/tcg/emit.c.inc @@ -1956,6 +1956,16 @@ static void gen_LES(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) gen_lxx_seg(s, env, decode, R_ES); } +static void gen_LFS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + gen_lxx_seg(s, env, decode, R_FS); +} + +static void gen_LGS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + gen_lxx_seg(s, env, decode, R_GS); +} + static void gen_LODS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { MemOp ot = decode->op[2].ot; @@ -1997,6 +2007,11 @@ static void gen_LOOPNE(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode gen_conditional_jump_labels(s, decode->immediate, not_taken, taken); } +static void gen_LSS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ + gen_lxx_seg(s, env, decode, R_SS); +} + static void gen_MOV(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { /* nothing to do! */ From patchwork Tue Apr 9 16:43:20 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 13622968 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 99F15C67861 for ; Tue, 9 Apr 2024 16:52:41 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ruEau-0001a5-En; Tue, 09 Apr 2024 12:45:13 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ruEaT-0000kq-9Q for qemu-devel@nongnu.org; Tue, 09 Apr 2024 12:44:47 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ruEa9-00087q-3n for qemu-devel@nongnu.org; Tue, 09 Apr 2024 12:44:43 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1712681057; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=YuiSRCIWpqGQ0+PobrMN7/e84xOQCvBQuzYRNYKcgss=; b=LPQH9dxJLi5SI4iamV4krkXYQWpXRvLBGyr4hwpw9U4JXt8vertg7QUs4jWou801ktDWU7 aB9S+Oc5Ys1nGKEvGqsqRJ1YnQWLgfNjTiX3kQ8/zE3ukHPmKr3ijyEGxczOdDfuYGTIYh sndr2lp4s5FU2M/v8pG05lVB+zA06rQ= Received: from mail-wr1-f70.google.com (mail-wr1-f70.google.com [209.85.221.70]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-204-h_hziilaM_2OSdTpusDxWw-1; Tue, 09 Apr 2024 12:44:14 -0400 X-MC-Unique: h_hziilaM_2OSdTpusDxWw-1 Received: by mail-wr1-f70.google.com with SMTP id ffacd0b85a97d-343f5059c5fso2495790f8f.2 for ; Tue, 09 Apr 2024 09:44:14 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712681053; x=1713285853; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=YuiSRCIWpqGQ0+PobrMN7/e84xOQCvBQuzYRNYKcgss=; b=Ar6Bdvo0/w80eSYuFnMS5ElaBBKfDBeIv4WtiQhT5IRJYeqffiyQPCOO9GYb1+e5nE FG4LsKj1ZoI1PMjFg9L6SPe7x60V2pf1MUvMFzmpwqJYsBt1YFEE8EQwyDMc+Nte/jPM GF1qe/NHVucH8Mb37nfYJSTXNpijE0KtA9PIb7vn5cbpCezR1iQAIsYRsnCGzTjkOHWg aRlBfA4q3FGO+20e0PBqNqtkTmw7jrb1EfWG14ECVOixxn/BSXxwCT1NFtQQVljKTVwP ylvo3/1JBsAlaHwxLuVWJfCaYeRScpqhHIUoB0wv8k8Bo6Pd5dGbkoKKc5su8w0NYF7B Jukg== X-Gm-Message-State: AOJu0Yya/NcOmTvPvan5X9gSg0nUQqtIQAvc19/HACqvG556Z5oQPd3B MyFBVS8m9rkBbS0NQKT2eTssWBblHsQxnsB0RqRUZ175sXGvYDt3jX7o6meMgpqutKOy8pb/20n SQqEr8HDaz+UMWceQ6w3NxLp+sgiNoejBkfRYlQdVsxQo2qmHkmgsNRRNkxTQ7WSfWg8v+EvcJu mA6XKRfKQTj1bA5EknhD8NkCbsMlU4q8bQjbsn X-Received: by 2002:a5d:588e:0:b0:343:77d3:5ee2 with SMTP id n14-20020a5d588e000000b0034377d35ee2mr213778wrf.35.1712681052424; Tue, 09 Apr 2024 09:44:12 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFvunlgRUeV0C3UVGotEWv1SfXU9hjWdqNHw0tFngtcPfelTfPyNynRR8KvQx2jM+8L40aNbw== X-Received: by 2002:a5d:588e:0:b0:343:77d3:5ee2 with SMTP id n14-20020a5d588e000000b0034377d35ee2mr213739wrf.35.1712681050773; Tue, 09 Apr 2024 09:44:10 -0700 (PDT) Received: from avogadro.local ([151.95.152.232]) by smtp.gmail.com with ESMTPSA id n15-20020a5d4c4f000000b0034403ee44b1sm9641441wrt.14.2024.04.09.09.44.09 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 09 Apr 2024 09:44:10 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Subject: [PATCH for-9.1 16/19] target/i386: remove now-converted opcodes from old decoder Date: Tue, 9 Apr 2024 18:43:20 +0200 Message-ID: <20240409164323.776660-17-pbonzini@redhat.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240409164323.776660-1-pbonzini@redhat.com> References: <20240409164323.776660-1-pbonzini@redhat.com> MIME-Version: 1.0 Received-SPF: pass client-ip=170.10.133.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -37 X-Spam_score: -3.8 X-Spam_bar: --- X-Spam_report: (-3.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1.701, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Send all converted opcodes to disas_insn_new() directly from the big decoding switch statement; once more, the debugging/bisecting logic disappears. Signed-off-by: Paolo Bonzini Reviewed-by: Richard Henderson --- target/i386/helper.h | 11 - target/i386/tcg/shift_helper_template.h.inc | 108 - target/i386/tcg/int_helper.c | 34 - target/i386/tcg/translate.c | 2172 +------------------ target/i386/tcg/decode-new.c.inc | 3 - 5 files changed, 11 insertions(+), 2317 deletions(-) delete mode 100644 target/i386/tcg/shift_helper_template.h.inc diff --git a/target/i386/helper.h b/target/i386/helper.h index ac2b04abd63..3c207ac62d6 100644 --- a/target/i386/helper.h +++ b/target/i386/helper.h @@ -207,15 +207,4 @@ DEF_HELPER_1(emms, void, env) #define SHIFT 2 #include "tcg/ops_sse_header.h.inc" -DEF_HELPER_3(rclb, tl, env, tl, tl) -DEF_HELPER_3(rclw, tl, env, tl, tl) -DEF_HELPER_3(rcll, tl, env, tl, tl) -DEF_HELPER_3(rcrb, tl, env, tl, tl) -DEF_HELPER_3(rcrw, tl, env, tl, tl) -DEF_HELPER_3(rcrl, tl, env, tl, tl) -#ifdef TARGET_X86_64 -DEF_HELPER_3(rclq, tl, env, tl, tl) -DEF_HELPER_3(rcrq, tl, env, tl, tl) -#endif - DEF_HELPER_1(rdrand, tl, env) diff --git a/target/i386/tcg/shift_helper_template.h.inc b/target/i386/tcg/shift_helper_template.h.inc deleted file mode 100644 index 54f15d6e05c..00000000000 --- a/target/i386/tcg/shift_helper_template.h.inc +++ /dev/null @@ -1,108 +0,0 @@ -/* - * x86 shift helpers - * - * Copyright (c) 2008 Fabrice Bellard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ - -#define DATA_BITS (1 << (3 + SHIFT)) -#define SHIFT_MASK (DATA_BITS - 1) -#if DATA_BITS <= 32 -#define SHIFT1_MASK 0x1f -#else -#define SHIFT1_MASK 0x3f -#endif - -#if DATA_BITS == 8 -#define SUFFIX b -#define DATA_MASK 0xff -#elif DATA_BITS == 16 -#define SUFFIX w -#define DATA_MASK 0xffff -#elif DATA_BITS == 32 -#define SUFFIX l -#define DATA_MASK 0xffffffff -#elif DATA_BITS == 64 -#define SUFFIX q -#define DATA_MASK 0xffffffffffffffffULL -#else -#error unhandled operand size -#endif - -target_ulong glue(helper_rcl, SUFFIX)(CPUX86State *env, target_ulong t0, - target_ulong t1) -{ - int count, eflags; - target_ulong src; - target_long res; - - count = t1 & SHIFT1_MASK; -#if DATA_BITS == 16 - count = rclw_table[count]; -#elif DATA_BITS == 8 - count = rclb_table[count]; -#endif - if (count) { - eflags = env->cc_src; - t0 &= DATA_MASK; - src = t0; - res = (t0 << count) | ((target_ulong)(eflags & CC_C) << (count - 1)); - if (count > 1) { - res |= t0 >> (DATA_BITS + 1 - count); - } - t0 = res; - env->cc_src = (eflags & ~(CC_C | CC_O)) | - (lshift(src ^ t0, 11 - (DATA_BITS - 1)) & CC_O) | - ((src >> (DATA_BITS - count)) & CC_C); - } - return t0; -} - -target_ulong glue(helper_rcr, SUFFIX)(CPUX86State *env, target_ulong t0, - target_ulong t1) -{ - int count, eflags; - target_ulong src; - target_long res; - - count = t1 & SHIFT1_MASK; -#if DATA_BITS == 16 - count = rclw_table[count]; -#elif DATA_BITS == 8 - count = rclb_table[count]; -#endif - if (count) { - eflags = env->cc_src; - t0 &= DATA_MASK; - src = t0; - res = (t0 >> count) | - ((target_ulong)(eflags & CC_C) << (DATA_BITS - count)); - if (count > 1) { - res |= t0 << (DATA_BITS + 1 - count); - } - t0 = res; - env->cc_src = (eflags & ~(CC_C | CC_O)) | - (lshift(src ^ t0, 11 - (DATA_BITS - 1)) & CC_O) | - ((src >> (count - 1)) & CC_C); - } - return t0; -} - -#undef DATA_BITS -#undef SHIFT_MASK -#undef SHIFT1_MASK -#undef DATA_TYPE -#undef DATA_MASK -#undef SUFFIX diff --git a/target/i386/tcg/int_helper.c b/target/i386/tcg/int_helper.c index ab85dc55400..df16130f5df 100644 --- a/target/i386/tcg/int_helper.c +++ b/target/i386/tcg/int_helper.c @@ -29,22 +29,6 @@ //#define DEBUG_MULDIV -/* modulo 9 table */ -static const uint8_t rclb_table[32] = { - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 0, 1, 2, 3, 4, 5, 6, - 7, 8, 0, 1, 2, 3, 4, 5, - 6, 7, 8, 0, 1, 2, 3, 4, -}; - -/* modulo 17 table */ -static const uint8_t rclw_table[32] = { - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, - 16, 0, 1, 2, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, -}; - /* division, flags are undefined */ void helper_divb_AL(CPUX86State *env, target_ulong t0) @@ -447,24 +431,6 @@ target_ulong helper_pext(target_ulong src, target_ulong mask) return dest; } -#define SHIFT 0 -#include "shift_helper_template.h.inc" -#undef SHIFT - -#define SHIFT 1 -#include "shift_helper_template.h.inc" -#undef SHIFT - -#define SHIFT 2 -#include "shift_helper_template.h.inc" -#undef SHIFT - -#ifdef TARGET_X86_64 -#define SHIFT 3 -#include "shift_helper_template.h.inc" -#undef SHIFT -#endif - /* Test that BIT is enabled in CR4. If not, raise an illegal opcode exception. This reduces the requirements for rare CR4 bits being mapped into HFLAGS. */ diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index e8352d43678..81291da4132 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -215,7 +215,6 @@ typedef struct DisasContext { #ifdef CONFIG_USER_ONLY STUB_HELPER(clgi, TCGv_env env) STUB_HELPER(flush_page, TCGv_env env, TCGv addr) -STUB_HELPER(hlt, TCGv_env env, TCGv_i32 pc_ofs) STUB_HELPER(inb, TCGv ret, TCGv_env env, TCGv_i32 port) STUB_HELPER(inw, TCGv ret, TCGv_env env, TCGv_i32 port) STUB_HELPER(inl, TCGv ret, TCGv_env env, TCGv_i32 port) @@ -242,21 +241,8 @@ static void gen_eob(DisasContext *s); static void gen_jr(DisasContext *s); static void gen_jmp_rel(DisasContext *s, MemOp ot, int diff, int tb_num); static void gen_jmp_rel_csize(DisasContext *s, int diff, int tb_num); -static void gen_op(DisasContext *s1, int op, MemOp ot, int d); static void gen_exception_gpf(DisasContext *s); -/* i386 arith/logic operations */ -enum { - OP_ADDL, - OP_ORL, - OP_ADCL, - OP_SBBL, - OP_ANDL, - OP_SUBL, - OP_XORL, - OP_CMPL, -}; - /* i386 shift ops */ enum { OP_ROL, @@ -442,13 +428,6 @@ static inline MemOp mo_b_d(int b, MemOp ot) return b & 1 ? ot : MO_8; } -/* Select size 8 if lsb of B is clear, else OT capped at 32. - Used for decoding operand size of port opcodes. */ -static inline MemOp mo_b_d32(int b, MemOp ot) -{ - return b & 1 ? (ot == MO_16 ? MO_16 : MO_32) : MO_8; -} - /* Compute the result of writing t0 to the OT-sized register REG. * * If DEST is NULL, store the result into the register and return the @@ -851,25 +830,6 @@ static void gen_op_update2_cc(DisasContext *s) tcg_gen_mov_tl(cpu_cc_dst, s->T0); } -static void gen_op_update3_cc(DisasContext *s, TCGv reg) -{ - tcg_gen_mov_tl(cpu_cc_src2, reg); - tcg_gen_mov_tl(cpu_cc_src, s->T1); - tcg_gen_mov_tl(cpu_cc_dst, s->T0); -} - -static inline void gen_op_testl_T0_T1_cc(DisasContext *s) -{ - tcg_gen_and_tl(cpu_cc_dst, s->T0, s->T1); -} - -static void gen_op_update_neg_cc(DisasContext *s) -{ - tcg_gen_mov_tl(cpu_cc_dst, s->T0); - tcg_gen_neg_tl(cpu_cc_src, s->T0); - tcg_gen_movi_tl(s->cc_srcT, 0); -} - /* compute all eflags to reg */ static void gen_mov_eflags(DisasContext *s, TCGv reg) { @@ -1490,165 +1450,6 @@ static bool check_cpl0(DisasContext *s) return false; } -/* If vm86, check for iopl == 3; if not, raise #GP and return false. */ -static bool check_vm86_iopl(DisasContext *s) -{ - if (!VM86(s) || IOPL(s) == 3) { - return true; - } - gen_exception_gpf(s); - return false; -} - -/* Check for iopl allowing access; if not, raise #GP and return false. */ -static bool check_iopl(DisasContext *s) -{ - if (VM86(s) ? IOPL(s) == 3 : CPL(s) <= IOPL(s)) { - return true; - } - gen_exception_gpf(s); - return false; -} - -/* if d == OR_TMP0, it means memory operand (address in A0) */ -static void gen_op(DisasContext *s1, int op, MemOp ot, int d) -{ - /* Invalid lock prefix when destination is not memory or OP_CMPL. */ - if ((d != OR_TMP0 || op == OP_CMPL) && s1->prefix & PREFIX_LOCK) { - gen_illegal_opcode(s1); - return; - } - - if (d != OR_TMP0) { - gen_op_mov_v_reg(s1, ot, s1->T0, d); - } else if (!(s1->prefix & PREFIX_LOCK)) { - gen_op_ld_v(s1, ot, s1->T0, s1->A0); - } - switch(op) { - case OP_ADCL: - gen_compute_eflags_c(s1, s1->tmp4); - if (s1->prefix & PREFIX_LOCK) { - tcg_gen_add_tl(s1->T0, s1->tmp4, s1->T1); - tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T0, - s1->mem_index, ot | MO_LE); - } else { - tcg_gen_add_tl(s1->T0, s1->T0, s1->T1); - tcg_gen_add_tl(s1->T0, s1->T0, s1->tmp4); - gen_op_st_rm_T0_A0(s1, ot, d); - } - gen_op_update3_cc(s1, s1->tmp4); - set_cc_op(s1, CC_OP_ADCB + ot); - break; - case OP_SBBL: - gen_compute_eflags_c(s1, s1->tmp4); - if (s1->prefix & PREFIX_LOCK) { - tcg_gen_add_tl(s1->T0, s1->T1, s1->tmp4); - tcg_gen_neg_tl(s1->T0, s1->T0); - tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T0, - s1->mem_index, ot | MO_LE); - } else { - tcg_gen_sub_tl(s1->T0, s1->T0, s1->T1); - tcg_gen_sub_tl(s1->T0, s1->T0, s1->tmp4); - gen_op_st_rm_T0_A0(s1, ot, d); - } - gen_op_update3_cc(s1, s1->tmp4); - set_cc_op(s1, CC_OP_SBBB + ot); - break; - case OP_ADDL: - if (s1->prefix & PREFIX_LOCK) { - tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T1, - s1->mem_index, ot | MO_LE); - } else { - tcg_gen_add_tl(s1->T0, s1->T0, s1->T1); - gen_op_st_rm_T0_A0(s1, ot, d); - } - gen_op_update2_cc(s1); - set_cc_op(s1, CC_OP_ADDB + ot); - break; - case OP_SUBL: - if (s1->prefix & PREFIX_LOCK) { - tcg_gen_neg_tl(s1->T0, s1->T1); - tcg_gen_atomic_fetch_add_tl(s1->cc_srcT, s1->A0, s1->T0, - s1->mem_index, ot | MO_LE); - tcg_gen_sub_tl(s1->T0, s1->cc_srcT, s1->T1); - } else { - tcg_gen_mov_tl(s1->cc_srcT, s1->T0); - tcg_gen_sub_tl(s1->T0, s1->T0, s1->T1); - gen_op_st_rm_T0_A0(s1, ot, d); - } - gen_op_update2_cc(s1); - set_cc_op(s1, CC_OP_SUBB + ot); - break; - default: - case OP_ANDL: - if (s1->prefix & PREFIX_LOCK) { - tcg_gen_atomic_and_fetch_tl(s1->T0, s1->A0, s1->T1, - s1->mem_index, ot | MO_LE); - } else { - tcg_gen_and_tl(s1->T0, s1->T0, s1->T1); - gen_op_st_rm_T0_A0(s1, ot, d); - } - gen_op_update1_cc(s1); - set_cc_op(s1, CC_OP_LOGICB + ot); - break; - case OP_ORL: - if (s1->prefix & PREFIX_LOCK) { - tcg_gen_atomic_or_fetch_tl(s1->T0, s1->A0, s1->T1, - s1->mem_index, ot | MO_LE); - } else { - tcg_gen_or_tl(s1->T0, s1->T0, s1->T1); - gen_op_st_rm_T0_A0(s1, ot, d); - } - gen_op_update1_cc(s1); - set_cc_op(s1, CC_OP_LOGICB + ot); - break; - case OP_XORL: - if (s1->prefix & PREFIX_LOCK) { - tcg_gen_atomic_xor_fetch_tl(s1->T0, s1->A0, s1->T1, - s1->mem_index, ot | MO_LE); - } else { - tcg_gen_xor_tl(s1->T0, s1->T0, s1->T1); - gen_op_st_rm_T0_A0(s1, ot, d); - } - gen_op_update1_cc(s1); - set_cc_op(s1, CC_OP_LOGICB + ot); - break; - case OP_CMPL: - tcg_gen_mov_tl(cpu_cc_src, s1->T1); - tcg_gen_mov_tl(s1->cc_srcT, s1->T0); - tcg_gen_sub_tl(cpu_cc_dst, s1->T0, s1->T1); - set_cc_op(s1, CC_OP_SUBB + ot); - break; - } -} - -/* if d == OR_TMP0, it means memory operand (address in A0) */ -static void gen_inc(DisasContext *s1, MemOp ot, int d, int c) -{ - if (s1->prefix & PREFIX_LOCK) { - if (d != OR_TMP0) { - /* Lock prefix when destination is not memory */ - gen_illegal_opcode(s1); - return; - } - tcg_gen_movi_tl(s1->T0, c > 0 ? 1 : -1); - tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T0, - s1->mem_index, ot | MO_LE); - } else { - if (d != OR_TMP0) { - gen_op_mov_v_reg(s1, ot, s1->T0, d); - } else { - gen_op_ld_v(s1, ot, s1->T0, s1->A0); - } - tcg_gen_addi_tl(s1->T0, s1->T0, (c > 0 ? 1 : -1)); - gen_op_st_rm_T0_A0(s1, ot, d); - } - - gen_compute_eflags_c(s1, cpu_cc_src); - tcg_gen_mov_tl(cpu_cc_dst, s1->T0); - set_cc_op(s1, (c > 0 ? CC_OP_INCB : CC_OP_DECB) + ot); -} - static void gen_shift_flags(DisasContext *s, MemOp ot, TCGv result, TCGv shm1, TCGv count, bool is_right) { @@ -1691,298 +1492,6 @@ static void gen_shift_flags(DisasContext *s, MemOp ot, TCGv result, set_cc_op(s, CC_OP_DYNAMIC); } -static void gen_shift_rm_T1(DisasContext *s, MemOp ot, int op1, - int is_right, int is_arith) -{ - target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f); - - /* load */ - if (op1 == OR_TMP0) { - gen_op_ld_v(s, ot, s->T0, s->A0); - } else { - gen_op_mov_v_reg(s, ot, s->T0, op1); - } - - tcg_gen_andi_tl(s->T1, s->T1, mask); - tcg_gen_subi_tl(s->tmp0, s->T1, 1); - - if (is_right) { - if (is_arith) { - gen_exts(ot, s->T0); - tcg_gen_sar_tl(s->tmp0, s->T0, s->tmp0); - tcg_gen_sar_tl(s->T0, s->T0, s->T1); - } else { - gen_extu(ot, s->T0); - tcg_gen_shr_tl(s->tmp0, s->T0, s->tmp0); - tcg_gen_shr_tl(s->T0, s->T0, s->T1); - } - } else { - tcg_gen_shl_tl(s->tmp0, s->T0, s->tmp0); - tcg_gen_shl_tl(s->T0, s->T0, s->T1); - } - - /* store */ - gen_op_st_rm_T0_A0(s, ot, op1); - - gen_shift_flags(s, ot, s->T0, s->tmp0, s->T1, is_right); -} - -static void gen_shift_rm_im(DisasContext *s, MemOp ot, int op1, int op2, - int is_right, int is_arith) -{ - int mask = (ot == MO_64 ? 0x3f : 0x1f); - - /* load */ - if (op1 == OR_TMP0) - gen_op_ld_v(s, ot, s->T0, s->A0); - else - gen_op_mov_v_reg(s, ot, s->T0, op1); - - op2 &= mask; - if (op2 != 0) { - if (is_right) { - if (is_arith) { - gen_exts(ot, s->T0); - tcg_gen_sari_tl(s->tmp4, s->T0, op2 - 1); - tcg_gen_sari_tl(s->T0, s->T0, op2); - } else { - gen_extu(ot, s->T0); - tcg_gen_shri_tl(s->tmp4, s->T0, op2 - 1); - tcg_gen_shri_tl(s->T0, s->T0, op2); - } - } else { - tcg_gen_shli_tl(s->tmp4, s->T0, op2 - 1); - tcg_gen_shli_tl(s->T0, s->T0, op2); - } - } - - /* store */ - gen_op_st_rm_T0_A0(s, ot, op1); - - /* update eflags if non zero shift */ - if (op2 != 0) { - tcg_gen_mov_tl(cpu_cc_src, s->tmp4); - tcg_gen_mov_tl(cpu_cc_dst, s->T0); - set_cc_op(s, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot); - } -} - -static void gen_rot_rm_T1(DisasContext *s, MemOp ot, int op1, int is_right) -{ - target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f); - TCGv_i32 t0, t1; - - /* load */ - if (op1 == OR_TMP0) { - gen_op_ld_v(s, ot, s->T0, s->A0); - } else { - gen_op_mov_v_reg(s, ot, s->T0, op1); - } - - tcg_gen_andi_tl(s->T1, s->T1, mask); - - switch (ot) { - case MO_8: - /* Replicate the 8-bit input so that a 32-bit rotate works. */ - tcg_gen_ext8u_tl(s->T0, s->T0); - tcg_gen_muli_tl(s->T0, s->T0, 0x01010101); - goto do_long; - case MO_16: - /* Replicate the 16-bit input so that a 32-bit rotate works. */ - tcg_gen_deposit_tl(s->T0, s->T0, s->T0, 16, 16); - goto do_long; - do_long: -#ifdef TARGET_X86_64 - case MO_32: - tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); - tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1); - if (is_right) { - tcg_gen_rotr_i32(s->tmp2_i32, s->tmp2_i32, s->tmp3_i32); - } else { - tcg_gen_rotl_i32(s->tmp2_i32, s->tmp2_i32, s->tmp3_i32); - } - tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32); - break; -#endif - default: - if (is_right) { - tcg_gen_rotr_tl(s->T0, s->T0, s->T1); - } else { - tcg_gen_rotl_tl(s->T0, s->T0, s->T1); - } - break; - } - - /* store */ - gen_op_st_rm_T0_A0(s, ot, op1); - - /* We'll need the flags computed into CC_SRC. */ - gen_compute_eflags(s); - - /* The value that was "rotated out" is now present at the other end - of the word. Compute C into CC_DST and O into CC_SRC2. Note that - since we've computed the flags into CC_SRC, these variables are - currently dead. */ - if (is_right) { - tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask - 1); - tcg_gen_shri_tl(cpu_cc_dst, s->T0, mask); - tcg_gen_andi_tl(cpu_cc_dst, cpu_cc_dst, 1); - } else { - tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask); - tcg_gen_andi_tl(cpu_cc_dst, s->T0, 1); - } - tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1); - tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst); - - /* Now conditionally store the new CC_OP value. If the shift count - is 0 we keep the CC_OP_EFLAGS setting so that only CC_SRC is live. - Otherwise reuse CC_OP_ADCOX which have the C and O flags split out - exactly as we computed above. */ - t0 = tcg_constant_i32(0); - t1 = tcg_temp_new_i32(); - tcg_gen_trunc_tl_i32(t1, s->T1); - tcg_gen_movi_i32(s->tmp2_i32, CC_OP_ADCOX); - tcg_gen_movi_i32(s->tmp3_i32, CC_OP_EFLAGS); - tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, t1, t0, - s->tmp2_i32, s->tmp3_i32); - - /* The CC_OP value is no longer predictable. */ - set_cc_op(s, CC_OP_DYNAMIC); -} - -static void gen_rot_rm_im(DisasContext *s, MemOp ot, int op1, int op2, - int is_right) -{ - int mask = (ot == MO_64 ? 0x3f : 0x1f); - int shift; - - /* load */ - if (op1 == OR_TMP0) { - gen_op_ld_v(s, ot, s->T0, s->A0); - } else { - gen_op_mov_v_reg(s, ot, s->T0, op1); - } - - op2 &= mask; - if (op2 != 0) { - switch (ot) { -#ifdef TARGET_X86_64 - case MO_32: - tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); - if (is_right) { - tcg_gen_rotri_i32(s->tmp2_i32, s->tmp2_i32, op2); - } else { - tcg_gen_rotli_i32(s->tmp2_i32, s->tmp2_i32, op2); - } - tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32); - break; -#endif - default: - if (is_right) { - tcg_gen_rotri_tl(s->T0, s->T0, op2); - } else { - tcg_gen_rotli_tl(s->T0, s->T0, op2); - } - break; - case MO_8: - mask = 7; - goto do_shifts; - case MO_16: - mask = 15; - do_shifts: - shift = op2 & mask; - if (is_right) { - shift = mask + 1 - shift; - } - gen_extu(ot, s->T0); - tcg_gen_shli_tl(s->tmp0, s->T0, shift); - tcg_gen_shri_tl(s->T0, s->T0, mask + 1 - shift); - tcg_gen_or_tl(s->T0, s->T0, s->tmp0); - break; - } - } - - /* store */ - gen_op_st_rm_T0_A0(s, ot, op1); - - if (op2 != 0) { - /* Compute the flags into CC_SRC. */ - gen_compute_eflags(s); - - /* The value that was "rotated out" is now present at the other end - of the word. Compute C into CC_DST and O into CC_SRC2. Note that - since we've computed the flags into CC_SRC, these variables are - currently dead. */ - if (is_right) { - tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask - 1); - tcg_gen_shri_tl(cpu_cc_dst, s->T0, mask); - tcg_gen_andi_tl(cpu_cc_dst, cpu_cc_dst, 1); - } else { - tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask); - tcg_gen_andi_tl(cpu_cc_dst, s->T0, 1); - } - tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1); - tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst); - set_cc_op(s, CC_OP_ADCOX); - } -} - -/* XXX: add faster immediate = 1 case */ -static void gen_rotc_rm_T1(DisasContext *s, MemOp ot, int op1, - int is_right) -{ - gen_compute_eflags(s); - assert(s->cc_op == CC_OP_EFLAGS); - - /* load */ - if (op1 == OR_TMP0) - gen_op_ld_v(s, ot, s->T0, s->A0); - else - gen_op_mov_v_reg(s, ot, s->T0, op1); - - if (is_right) { - switch (ot) { - case MO_8: - gen_helper_rcrb(s->T0, tcg_env, s->T0, s->T1); - break; - case MO_16: - gen_helper_rcrw(s->T0, tcg_env, s->T0, s->T1); - break; - case MO_32: - gen_helper_rcrl(s->T0, tcg_env, s->T0, s->T1); - break; -#ifdef TARGET_X86_64 - case MO_64: - gen_helper_rcrq(s->T0, tcg_env, s->T0, s->T1); - break; -#endif - default: - g_assert_not_reached(); - } - } else { - switch (ot) { - case MO_8: - gen_helper_rclb(s->T0, tcg_env, s->T0, s->T1); - break; - case MO_16: - gen_helper_rclw(s->T0, tcg_env, s->T0, s->T1); - break; - case MO_32: - gen_helper_rcll(s->T0, tcg_env, s->T0, s->T1); - break; -#ifdef TARGET_X86_64 - case MO_64: - gen_helper_rclq(s->T0, tcg_env, s->T0, s->T1); - break; -#endif - default: - g_assert_not_reached(); - } - } - /* store */ - gen_op_st_rm_T0_A0(s, ot, op1); -} - /* XXX: add faster immediate case */ static void gen_shiftd_rm_T1(DisasContext *s, MemOp ot, int op1, bool is_right, TCGv count_in) @@ -2067,63 +1576,6 @@ static void gen_shiftd_rm_T1(DisasContext *s, MemOp ot, int op1, gen_shift_flags(s, ot, s->T0, s->tmp0, count, is_right); } -static void gen_shift(DisasContext *s1, int op, MemOp ot, int d, int s) -{ - if (s != OR_TMP1) - gen_op_mov_v_reg(s1, ot, s1->T1, s); - switch(op) { - case OP_ROL: - gen_rot_rm_T1(s1, ot, d, 0); - break; - case OP_ROR: - gen_rot_rm_T1(s1, ot, d, 1); - break; - case OP_SHL: - case OP_SHL1: - gen_shift_rm_T1(s1, ot, d, 0, 0); - break; - case OP_SHR: - gen_shift_rm_T1(s1, ot, d, 1, 0); - break; - case OP_SAR: - gen_shift_rm_T1(s1, ot, d, 1, 1); - break; - case OP_RCL: - gen_rotc_rm_T1(s1, ot, d, 0); - break; - case OP_RCR: - gen_rotc_rm_T1(s1, ot, d, 1); - break; - } -} - -static void gen_shifti(DisasContext *s1, int op, MemOp ot, int d, int c) -{ - switch(op) { - case OP_ROL: - gen_rot_rm_im(s1, ot, d, c, 0); - break; - case OP_ROR: - gen_rot_rm_im(s1, ot, d, c, 1); - break; - case OP_SHL: - case OP_SHL1: - gen_shift_rm_im(s1, ot, d, c, 0, 0); - break; - case OP_SHR: - gen_shift_rm_im(s1, ot, d, c, 1, 0); - break; - case OP_SAR: - gen_shift_rm_im(s1, ot, d, c, 1, 1); - break; - default: - /* currently not optimized */ - tcg_gen_movi_tl(s1->T1, c); - gen_shift(s1, op, ot, d, OR_TMP1); - break; - } -} - #define X86_MAX_INSN_LENGTH 15 static uint64_t advance_pc(CPUX86State *env, DisasContext *s, int num_bytes) @@ -2159,11 +1611,6 @@ static inline uint8_t x86_ldub_code(CPUX86State *env, DisasContext *s) return translator_ldub(env, &s->base, advance_pc(env, s, 1)); } -static inline int16_t x86_ldsw_code(CPUX86State *env, DisasContext *s) -{ - return translator_lduw(env, &s->base, advance_pc(env, s, 2)); -} - static inline uint16_t x86_lduw_code(CPUX86State *env, DisasContext *s) { return translator_lduw(env, &s->base, advance_pc(env, s, 2)); @@ -2489,15 +1936,6 @@ static target_long insn_get_signed(CPUX86State *env, DisasContext *s, MemOp ot) return ret; } -static inline int insn_const_size(MemOp ot) -{ - if (ot <= MO_32) { - return 1 << ot; - } else { - return 4; - } -} - static void gen_conditional_jump_labels(DisasContext *s, target_long diff, TCGLabel *not_taken, TCGLabel *taken) { @@ -2529,12 +1967,6 @@ static void gen_cmovcc1(DisasContext *s, int b, TCGv dest, TCGv src) tcg_gen_movcond_tl(cc.cond, dest, cc.reg, cc.reg2, src, dest); } -static inline void gen_op_movl_T0_seg(DisasContext *s, X86Seg seg_reg) -{ - tcg_gen_ld32u_tl(s->T0, tcg_env, - offsetof(CPUX86State,segs[seg_reg].selector)); -} - static void gen_op_movl_seg_real(DisasContext *s, X86Seg seg_reg, TCGv seg) { TCGv selector = tcg_temp_new(); @@ -3021,9 +2453,6 @@ static void gen_sty_env_A0(DisasContext *s, int offset, bool align) tcg_gen_qemu_st_i128(t, s->tmp0, mem_index, mop); } -static bool first = true; -static unsigned long limit; - #include "decode-new.h" #include "emit.c.inc" #include "decode-new.c.inc" @@ -3180,45 +2609,13 @@ static bool disas_insn(DisasContext *s, CPUState *cpu) prefixes = 0; - if (first) { - const char *limit_str = getenv("QEMU_I386_LIMIT"); - limit = limit_str ? atol(limit_str) : -1; - first = false; - } - bool use_new = true; -#ifdef CONFIG_USER_ONLY - use_new &= limit > 0; -#endif - next_byte: s->prefix = prefixes; b = x86_ldub_code(env, s); /* Collect prefixes. */ switch (b) { - default: -#ifndef CONFIG_USER_ONLY - use_new &= b <= limit; -#endif - if (use_new && (b < 0xd8 || b >= 0xe0)) { - disas_insn_new(s, cpu, b); - return true; - } - break; case 0x0f: b = x86_ldub_code(env, s) + 0x100; -#ifndef CONFIG_USER_ONLY - use_new &= b <= limit; -#endif - if (use_new && - ((b >= 0x138 && b <= 0x19f) || - (b & ~9) == 0x1a0 || - b == 0x1af || b == 0x1b2 || - (b >= 0x1b4 && b <= 0x1b7) || - b == 0x1be || b == 0x1bf || b == 0x1c3 || - (b >= 0x1c8 && b <= 0x1cf))) { - disas_insn_new(s, cpu, b); - return true; - } break; case 0xf3: prefixes |= PREFIX_REPZ; @@ -3316,558 +2713,6 @@ static bool disas_insn(DisasContext *s, CPUState *cpu) switch (b) { /**************************/ /* arith & logic */ - case 0x00 ... 0x05: - case 0x08 ... 0x0d: - case 0x10 ... 0x15: - case 0x18 ... 0x1d: - case 0x20 ... 0x25: - case 0x28 ... 0x2d: - case 0x30 ... 0x35: - case 0x38 ... 0x3d: - { - int f; - op = (b >> 3) & 7; - f = (b >> 1) & 3; - - ot = mo_b_d(b, dflag); - - switch(f) { - case 0: /* OP Ev, Gv */ - modrm = x86_ldub_code(env, s); - reg = ((modrm >> 3) & 7) | REX_R(s); - mod = (modrm >> 6) & 3; - rm = (modrm & 7) | REX_B(s); - if (mod != 3) { - gen_lea_modrm(env, s, modrm); - opreg = OR_TMP0; - } else if (op == OP_XORL && rm == reg) { - xor_zero: - /* xor reg, reg optimisation */ - set_cc_op(s, CC_OP_CLR); - tcg_gen_movi_tl(s->T0, 0); - gen_op_mov_reg_v(s, ot, reg, s->T0); - break; - } else { - opreg = rm; - } - gen_op_mov_v_reg(s, ot, s->T1, reg); - gen_op(s, op, ot, opreg); - break; - case 1: /* OP Gv, Ev */ - modrm = x86_ldub_code(env, s); - mod = (modrm >> 6) & 3; - reg = ((modrm >> 3) & 7) | REX_R(s); - rm = (modrm & 7) | REX_B(s); - if (mod != 3) { - gen_lea_modrm(env, s, modrm); - gen_op_ld_v(s, ot, s->T1, s->A0); - } else if (op == OP_XORL && rm == reg) { - goto xor_zero; - } else { - gen_op_mov_v_reg(s, ot, s->T1, rm); - } - gen_op(s, op, ot, reg); - break; - case 2: /* OP A, Iv */ - val = insn_get(env, s, ot); - tcg_gen_movi_tl(s->T1, val); - gen_op(s, op, ot, OR_EAX); - break; - } - } - break; - - case 0x82: - if (CODE64(s)) - goto illegal_op; - /* fall through */ - case 0x80: /* GRP1 */ - case 0x81: - case 0x83: - { - ot = mo_b_d(b, dflag); - - modrm = x86_ldub_code(env, s); - mod = (modrm >> 6) & 3; - rm = (modrm & 7) | REX_B(s); - op = (modrm >> 3) & 7; - - if (mod != 3) { - if (b == 0x83) - s->rip_offset = 1; - else - s->rip_offset = insn_const_size(ot); - gen_lea_modrm(env, s, modrm); - opreg = OR_TMP0; - } else { - opreg = rm; - } - - switch(b) { - default: - case 0x80: - case 0x81: - case 0x82: - val = insn_get(env, s, ot); - break; - case 0x83: - val = (int8_t)insn_get(env, s, MO_8); - break; - } - tcg_gen_movi_tl(s->T1, val); - gen_op(s, op, ot, opreg); - } - break; - - /**************************/ - /* inc, dec, and other misc arith */ - case 0x40 ... 0x47: /* inc Gv */ - ot = dflag; - gen_inc(s, ot, OR_EAX + (b & 7), 1); - break; - case 0x48 ... 0x4f: /* dec Gv */ - ot = dflag; - gen_inc(s, ot, OR_EAX + (b & 7), -1); - break; - case 0xf6: /* GRP3 */ - case 0xf7: - ot = mo_b_d(b, dflag); - - modrm = x86_ldub_code(env, s); - mod = (modrm >> 6) & 3; - rm = (modrm & 7) | REX_B(s); - op = (modrm >> 3) & 7; - if (mod != 3) { - if (op == 0) { - s->rip_offset = insn_const_size(ot); - } - gen_lea_modrm(env, s, modrm); - /* For those below that handle locked memory, don't load here. */ - if (!(s->prefix & PREFIX_LOCK) - || op != 2) { - gen_op_ld_v(s, ot, s->T0, s->A0); - } - } else { - gen_op_mov_v_reg(s, ot, s->T0, rm); - } - - switch(op) { - case 0: /* test */ - val = insn_get(env, s, ot); - tcg_gen_movi_tl(s->T1, val); - gen_op_testl_T0_T1_cc(s); - set_cc_op(s, CC_OP_LOGICB + ot); - break; - case 2: /* not */ - if (s->prefix & PREFIX_LOCK) { - if (mod == 3) { - goto illegal_op; - } - tcg_gen_movi_tl(s->T0, ~0); - tcg_gen_atomic_xor_fetch_tl(s->T0, s->A0, s->T0, - s->mem_index, ot | MO_LE); - } else { - tcg_gen_not_tl(s->T0, s->T0); - if (mod != 3) { - gen_op_st_v(s, ot, s->T0, s->A0); - } else { - gen_op_mov_reg_v(s, ot, rm, s->T0); - } - } - break; - case 3: /* neg */ - if (s->prefix & PREFIX_LOCK) { - TCGLabel *label1; - TCGv a0, t0, t1, t2; - - if (mod == 3) { - goto illegal_op; - } - a0 = s->A0; - t0 = s->T0; - label1 = gen_new_label(); - - gen_set_label(label1); - t1 = tcg_temp_new(); - t2 = tcg_temp_new(); - tcg_gen_mov_tl(t2, t0); - tcg_gen_neg_tl(t1, t0); - tcg_gen_atomic_cmpxchg_tl(t0, a0, t0, t1, - s->mem_index, ot | MO_LE); - tcg_gen_brcond_tl(TCG_COND_NE, t0, t2, label1); - - tcg_gen_neg_tl(s->T0, t0); - } else { - tcg_gen_neg_tl(s->T0, s->T0); - if (mod != 3) { - gen_op_st_v(s, ot, s->T0, s->A0); - } else { - gen_op_mov_reg_v(s, ot, rm, s->T0); - } - } - gen_op_update_neg_cc(s); - set_cc_op(s, CC_OP_SUBB + ot); - break; - case 4: /* mul */ - switch(ot) { - case MO_8: - gen_op_mov_v_reg(s, MO_8, s->T1, R_EAX); - tcg_gen_ext8u_tl(s->T0, s->T0); - tcg_gen_ext8u_tl(s->T1, s->T1); - /* XXX: use 32 bit mul which could be faster */ - tcg_gen_mul_tl(s->T0, s->T0, s->T1); - gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0); - tcg_gen_mov_tl(cpu_cc_dst, s->T0); - tcg_gen_andi_tl(cpu_cc_src, s->T0, 0xff00); - set_cc_op(s, CC_OP_MULB); - break; - case MO_16: - gen_op_mov_v_reg(s, MO_16, s->T1, R_EAX); - tcg_gen_ext16u_tl(s->T0, s->T0); - tcg_gen_ext16u_tl(s->T1, s->T1); - /* XXX: use 32 bit mul which could be faster */ - tcg_gen_mul_tl(s->T0, s->T0, s->T1); - gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0); - tcg_gen_mov_tl(cpu_cc_dst, s->T0); - tcg_gen_shri_tl(s->T0, s->T0, 16); - gen_op_mov_reg_v(s, MO_16, R_EDX, s->T0); - tcg_gen_mov_tl(cpu_cc_src, s->T0); - set_cc_op(s, CC_OP_MULW); - break; - default: - case MO_32: - tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); - tcg_gen_trunc_tl_i32(s->tmp3_i32, cpu_regs[R_EAX]); - tcg_gen_mulu2_i32(s->tmp2_i32, s->tmp3_i32, - s->tmp2_i32, s->tmp3_i32); - tcg_gen_extu_i32_tl(cpu_regs[R_EAX], s->tmp2_i32); - tcg_gen_extu_i32_tl(cpu_regs[R_EDX], s->tmp3_i32); - tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]); - tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]); - set_cc_op(s, CC_OP_MULL); - break; -#ifdef TARGET_X86_64 - case MO_64: - tcg_gen_mulu2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX], - s->T0, cpu_regs[R_EAX]); - tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]); - tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]); - set_cc_op(s, CC_OP_MULQ); - break; -#endif - } - break; - case 5: /* imul */ - switch(ot) { - case MO_8: - gen_op_mov_v_reg(s, MO_8, s->T1, R_EAX); - tcg_gen_ext8s_tl(s->T0, s->T0); - tcg_gen_ext8s_tl(s->T1, s->T1); - /* XXX: use 32 bit mul which could be faster */ - tcg_gen_mul_tl(s->T0, s->T0, s->T1); - gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0); - tcg_gen_mov_tl(cpu_cc_dst, s->T0); - tcg_gen_ext8s_tl(s->tmp0, s->T0); - tcg_gen_sub_tl(cpu_cc_src, s->T0, s->tmp0); - set_cc_op(s, CC_OP_MULB); - break; - case MO_16: - gen_op_mov_v_reg(s, MO_16, s->T1, R_EAX); - tcg_gen_ext16s_tl(s->T0, s->T0); - tcg_gen_ext16s_tl(s->T1, s->T1); - /* XXX: use 32 bit mul which could be faster */ - tcg_gen_mul_tl(s->T0, s->T0, s->T1); - gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0); - tcg_gen_mov_tl(cpu_cc_dst, s->T0); - tcg_gen_ext16s_tl(s->tmp0, s->T0); - tcg_gen_sub_tl(cpu_cc_src, s->T0, s->tmp0); - tcg_gen_shri_tl(s->T0, s->T0, 16); - gen_op_mov_reg_v(s, MO_16, R_EDX, s->T0); - set_cc_op(s, CC_OP_MULW); - break; - default: - case MO_32: - tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); - tcg_gen_trunc_tl_i32(s->tmp3_i32, cpu_regs[R_EAX]); - tcg_gen_muls2_i32(s->tmp2_i32, s->tmp3_i32, - s->tmp2_i32, s->tmp3_i32); - tcg_gen_extu_i32_tl(cpu_regs[R_EAX], s->tmp2_i32); - tcg_gen_extu_i32_tl(cpu_regs[R_EDX], s->tmp3_i32); - tcg_gen_sari_i32(s->tmp2_i32, s->tmp2_i32, 31); - tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]); - tcg_gen_sub_i32(s->tmp2_i32, s->tmp2_i32, s->tmp3_i32); - tcg_gen_extu_i32_tl(cpu_cc_src, s->tmp2_i32); - set_cc_op(s, CC_OP_MULL); - break; -#ifdef TARGET_X86_64 - case MO_64: - tcg_gen_muls2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX], - s->T0, cpu_regs[R_EAX]); - tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]); - tcg_gen_sari_tl(cpu_cc_src, cpu_regs[R_EAX], 63); - tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_regs[R_EDX]); - set_cc_op(s, CC_OP_MULQ); - break; -#endif - } - break; - case 6: /* div */ - switch(ot) { - case MO_8: - gen_helper_divb_AL(tcg_env, s->T0); - break; - case MO_16: - gen_helper_divw_AX(tcg_env, s->T0); - break; - default: - case MO_32: - gen_helper_divl_EAX(tcg_env, s->T0); - break; -#ifdef TARGET_X86_64 - case MO_64: - gen_helper_divq_EAX(tcg_env, s->T0); - break; -#endif - } - break; - case 7: /* idiv */ - switch(ot) { - case MO_8: - gen_helper_idivb_AL(tcg_env, s->T0); - break; - case MO_16: - gen_helper_idivw_AX(tcg_env, s->T0); - break; - default: - case MO_32: - gen_helper_idivl_EAX(tcg_env, s->T0); - break; -#ifdef TARGET_X86_64 - case MO_64: - gen_helper_idivq_EAX(tcg_env, s->T0); - break; -#endif - } - break; - default: - goto unknown_op; - } - break; - - case 0xfe: /* GRP4 */ - case 0xff: /* GRP5 */ - ot = mo_b_d(b, dflag); - - modrm = x86_ldub_code(env, s); - mod = (modrm >> 6) & 3; - rm = (modrm & 7) | REX_B(s); - op = (modrm >> 3) & 7; - if (op >= 2 && b == 0xfe) { - goto unknown_op; - } - if (CODE64(s)) { - if (op == 2 || op == 4) { - /* operand size for jumps is 64 bit */ - ot = MO_64; - } else if (op == 3 || op == 5) { - ot = dflag != MO_16 ? MO_32 + REX_W(s) : MO_16; - } else if (op == 6) { - /* default push size is 64 bit */ - ot = mo_pushpop(s, dflag); - } - } - if (mod != 3) { - gen_lea_modrm(env, s, modrm); - if (op >= 2 && op != 3 && op != 5) - gen_op_ld_v(s, ot, s->T0, s->A0); - } else { - gen_op_mov_v_reg(s, ot, s->T0, rm); - } - - switch(op) { - case 0: /* inc Ev */ - if (mod != 3) - opreg = OR_TMP0; - else - opreg = rm; - gen_inc(s, ot, opreg, 1); - break; - case 1: /* dec Ev */ - if (mod != 3) - opreg = OR_TMP0; - else - opreg = rm; - gen_inc(s, ot, opreg, -1); - break; - case 2: /* call Ev */ - /* XXX: optimize if memory (no 'and' is necessary) */ - if (dflag == MO_16) { - tcg_gen_ext16u_tl(s->T0, s->T0); - } - gen_push_v(s, eip_next_tl(s)); - gen_op_jmp_v(s, s->T0); - gen_bnd_jmp(s); - s->base.is_jmp = DISAS_JUMP; - break; - case 3: /* lcall Ev */ - if (mod == 3) { - goto illegal_op; - } - gen_op_ld_v(s, ot, s->T0, s->A0); - gen_add_A0_im(s, 1 << ot); - gen_op_ld_v(s, MO_16, s->T1, s->A0); - gen_far_call(s); - break; - case 4: /* jmp Ev */ - if (dflag == MO_16) { - tcg_gen_ext16u_tl(s->T0, s->T0); - } - gen_op_jmp_v(s, s->T0); - gen_bnd_jmp(s); - s->base.is_jmp = DISAS_JUMP; - break; - case 5: /* ljmp Ev */ - if (mod == 3) { - goto illegal_op; - } - gen_op_ld_v(s, ot, s->T0, s->A0); - gen_add_A0_im(s, 1 << ot); - gen_op_ld_v(s, MO_16, s->T1, s->A0); - gen_far_jmp(s); - break; - case 6: /* push Ev */ - gen_push_v(s, s->T0); - break; - default: - goto unknown_op; - } - break; - - case 0x84: /* test Ev, Gv */ - case 0x85: - ot = mo_b_d(b, dflag); - - modrm = x86_ldub_code(env, s); - reg = ((modrm >> 3) & 7) | REX_R(s); - - gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0); - gen_op_mov_v_reg(s, ot, s->T1, reg); - gen_op_testl_T0_T1_cc(s); - set_cc_op(s, CC_OP_LOGICB + ot); - break; - - case 0xa8: /* test eAX, Iv */ - case 0xa9: - ot = mo_b_d(b, dflag); - val = insn_get(env, s, ot); - - gen_op_mov_v_reg(s, ot, s->T0, OR_EAX); - tcg_gen_movi_tl(s->T1, val); - gen_op_testl_T0_T1_cc(s); - set_cc_op(s, CC_OP_LOGICB + ot); - break; - - case 0x98: /* CWDE/CBW */ - switch (dflag) { -#ifdef TARGET_X86_64 - case MO_64: - gen_op_mov_v_reg(s, MO_32, s->T0, R_EAX); - tcg_gen_ext32s_tl(s->T0, s->T0); - gen_op_mov_reg_v(s, MO_64, R_EAX, s->T0); - break; -#endif - case MO_32: - gen_op_mov_v_reg(s, MO_16, s->T0, R_EAX); - tcg_gen_ext16s_tl(s->T0, s->T0); - gen_op_mov_reg_v(s, MO_32, R_EAX, s->T0); - break; - case MO_16: - gen_op_mov_v_reg(s, MO_8, s->T0, R_EAX); - tcg_gen_ext8s_tl(s->T0, s->T0); - gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0); - break; - default: - g_assert_not_reached(); - } - break; - case 0x99: /* CDQ/CWD */ - switch (dflag) { -#ifdef TARGET_X86_64 - case MO_64: - gen_op_mov_v_reg(s, MO_64, s->T0, R_EAX); - tcg_gen_sari_tl(s->T0, s->T0, 63); - gen_op_mov_reg_v(s, MO_64, R_EDX, s->T0); - break; -#endif - case MO_32: - gen_op_mov_v_reg(s, MO_32, s->T0, R_EAX); - tcg_gen_ext32s_tl(s->T0, s->T0); - tcg_gen_sari_tl(s->T0, s->T0, 31); - gen_op_mov_reg_v(s, MO_32, R_EDX, s->T0); - break; - case MO_16: - gen_op_mov_v_reg(s, MO_16, s->T0, R_EAX); - tcg_gen_ext16s_tl(s->T0, s->T0); - tcg_gen_sari_tl(s->T0, s->T0, 15); - gen_op_mov_reg_v(s, MO_16, R_EDX, s->T0); - break; - default: - g_assert_not_reached(); - } - break; - case 0x1af: /* imul Gv, Ev */ - case 0x69: /* imul Gv, Ev, I */ - case 0x6b: - ot = dflag; - modrm = x86_ldub_code(env, s); - reg = ((modrm >> 3) & 7) | REX_R(s); - if (b == 0x69) - s->rip_offset = insn_const_size(ot); - else if (b == 0x6b) - s->rip_offset = 1; - gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0); - if (b == 0x69) { - val = insn_get(env, s, ot); - tcg_gen_movi_tl(s->T1, val); - } else if (b == 0x6b) { - val = (int8_t)insn_get(env, s, MO_8); - tcg_gen_movi_tl(s->T1, val); - } else { - gen_op_mov_v_reg(s, ot, s->T1, reg); - } - switch (ot) { -#ifdef TARGET_X86_64 - case MO_64: - tcg_gen_muls2_i64(cpu_regs[reg], s->T1, s->T0, s->T1); - tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]); - tcg_gen_sari_tl(cpu_cc_src, cpu_cc_dst, 63); - tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, s->T1); - break; -#endif - case MO_32: - tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); - tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1); - tcg_gen_muls2_i32(s->tmp2_i32, s->tmp3_i32, - s->tmp2_i32, s->tmp3_i32); - tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp2_i32); - tcg_gen_sari_i32(s->tmp2_i32, s->tmp2_i32, 31); - tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]); - tcg_gen_sub_i32(s->tmp2_i32, s->tmp2_i32, s->tmp3_i32); - tcg_gen_extu_i32_tl(cpu_cc_src, s->tmp2_i32); - break; - default: - tcg_gen_ext16s_tl(s->T0, s->T0); - tcg_gen_ext16s_tl(s->T1, s->T1); - /* XXX: use 32 bit mul which could be faster */ - tcg_gen_mul_tl(s->T0, s->T0, s->T1); - tcg_gen_mov_tl(cpu_cc_dst, s->T0); - tcg_gen_ext16s_tl(s->tmp0, s->T0); - tcg_gen_sub_tl(cpu_cc_src, s->T0, s->tmp0); - gen_op_mov_reg_v(s, ot, reg, s->T0); - break; - } - set_cc_op(s, CC_OP_MULB + ot); - break; case 0x1c0: case 0x1c1: /* xadd Ev, Gv */ ot = mo_b_d(b, dflag); @@ -4025,375 +2870,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu) break; /**************************/ - /* push/pop */ - case 0x50 ... 0x57: /* push */ - gen_op_mov_v_reg(s, MO_32, s->T0, (b & 7) | REX_B(s)); - gen_push_v(s, s->T0); - break; - case 0x58 ... 0x5f: /* pop */ - ot = gen_pop_T0(s); - /* NOTE: order is important for pop %sp */ - gen_pop_update(s, ot); - gen_op_mov_reg_v(s, ot, (b & 7) | REX_B(s), s->T0); - break; - case 0x60: /* pusha */ - if (CODE64(s)) - goto illegal_op; - gen_pusha(s); - break; - case 0x61: /* popa */ - if (CODE64(s)) - goto illegal_op; - gen_popa(s); - break; - case 0x68: /* push Iv */ - case 0x6a: - ot = mo_pushpop(s, dflag); - if (b == 0x68) - val = insn_get(env, s, ot); - else - val = (int8_t)insn_get(env, s, MO_8); - tcg_gen_movi_tl(s->T0, val); - gen_push_v(s, s->T0); - break; - case 0x8f: /* pop Ev */ - modrm = x86_ldub_code(env, s); - mod = (modrm >> 6) & 3; - ot = gen_pop_T0(s); - if (mod == 3) { - /* NOTE: order is important for pop %sp */ - gen_pop_update(s, ot); - rm = (modrm & 7) | REX_B(s); - gen_op_mov_reg_v(s, ot, rm, s->T0); - } else { - /* NOTE: order is important too for MMU exceptions */ - s->popl_esp_hack = 1 << ot; - gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1); - s->popl_esp_hack = 0; - gen_pop_update(s, ot); - } - break; - case 0xc8: /* enter */ - { - int level; - val = x86_lduw_code(env, s); - level = x86_ldub_code(env, s); - gen_enter(s, val, level); - } - break; - case 0xc9: /* leave */ - gen_leave(s); - break; - case 0x06: /* push es */ - case 0x0e: /* push cs */ - case 0x16: /* push ss */ - case 0x1e: /* push ds */ - if (CODE64(s)) - goto illegal_op; - gen_op_movl_T0_seg(s, b >> 3); - gen_push_v(s, s->T0); - break; - case 0x1a0: /* push fs */ - case 0x1a8: /* push gs */ - gen_op_movl_T0_seg(s, (b >> 3) & 7); - gen_push_v(s, s->T0); - break; - case 0x07: /* pop es */ - case 0x17: /* pop ss */ - case 0x1f: /* pop ds */ - if (CODE64(s)) - goto illegal_op; - reg = b >> 3; - ot = gen_pop_T0(s); - gen_movl_seg(s, reg, s->T0); - gen_pop_update(s, ot); - break; - case 0x1a1: /* pop fs */ - case 0x1a9: /* pop gs */ - ot = gen_pop_T0(s); - gen_movl_seg(s, (b >> 3) & 7, s->T0); - gen_pop_update(s, ot); - break; - - /**************************/ - /* mov */ - case 0x88: - case 0x89: /* mov Gv, Ev */ - ot = mo_b_d(b, dflag); - modrm = x86_ldub_code(env, s); - reg = ((modrm >> 3) & 7) | REX_R(s); - - /* generate a generic store */ - gen_ldst_modrm(env, s, modrm, ot, reg, 1); - break; - case 0xc6: - case 0xc7: /* mov Ev, Iv */ - ot = mo_b_d(b, dflag); - modrm = x86_ldub_code(env, s); - mod = (modrm >> 6) & 3; - if (mod != 3) { - s->rip_offset = insn_const_size(ot); - gen_lea_modrm(env, s, modrm); - } - val = insn_get(env, s, ot); - tcg_gen_movi_tl(s->T0, val); - if (mod != 3) { - gen_op_st_v(s, ot, s->T0, s->A0); - } else { - gen_op_mov_reg_v(s, ot, (modrm & 7) | REX_B(s), s->T0); - } - break; - case 0x8a: - case 0x8b: /* mov Ev, Gv */ - ot = mo_b_d(b, dflag); - modrm = x86_ldub_code(env, s); - reg = ((modrm >> 3) & 7) | REX_R(s); - - gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0); - gen_op_mov_reg_v(s, ot, reg, s->T0); - break; - case 0x8e: /* mov seg, Gv */ - modrm = x86_ldub_code(env, s); - reg = (modrm >> 3) & 7; - if (reg >= 6 || reg == R_CS) - goto illegal_op; - gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0); - gen_movl_seg(s, reg, s->T0); - break; - case 0x8c: /* mov Gv, seg */ - modrm = x86_ldub_code(env, s); - reg = (modrm >> 3) & 7; - mod = (modrm >> 6) & 3; - if (reg >= 6) - goto illegal_op; - gen_op_movl_T0_seg(s, reg); - ot = mod == 3 ? dflag : MO_16; - gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1); - break; - - case 0x1b6: /* movzbS Gv, Eb */ - case 0x1b7: /* movzwS Gv, Eb */ - case 0x1be: /* movsbS Gv, Eb */ - case 0x1bf: /* movswS Gv, Eb */ - { - MemOp d_ot; - MemOp s_ot; - - /* d_ot is the size of destination */ - d_ot = dflag; - /* ot is the size of source */ - ot = (b & 1) + MO_8; - /* s_ot is the sign+size of source */ - s_ot = b & 8 ? MO_SIGN | ot : ot; - - modrm = x86_ldub_code(env, s); - reg = ((modrm >> 3) & 7) | REX_R(s); - mod = (modrm >> 6) & 3; - rm = (modrm & 7) | REX_B(s); - - if (mod == 3) { - if (s_ot == MO_SB && byte_reg_is_xH(s, rm)) { - tcg_gen_sextract_tl(s->T0, cpu_regs[rm - 4], 8, 8); - } else { - gen_op_mov_v_reg(s, ot, s->T0, rm); - switch (s_ot) { - case MO_UB: - tcg_gen_ext8u_tl(s->T0, s->T0); - break; - case MO_SB: - tcg_gen_ext8s_tl(s->T0, s->T0); - break; - case MO_UW: - tcg_gen_ext16u_tl(s->T0, s->T0); - break; - default: - case MO_SW: - tcg_gen_ext16s_tl(s->T0, s->T0); - break; - } - } - gen_op_mov_reg_v(s, d_ot, reg, s->T0); - } else { - gen_lea_modrm(env, s, modrm); - gen_op_ld_v(s, s_ot, s->T0, s->A0); - gen_op_mov_reg_v(s, d_ot, reg, s->T0); - } - } - break; - - case 0x8d: /* lea */ - modrm = x86_ldub_code(env, s); - mod = (modrm >> 6) & 3; - if (mod == 3) - goto illegal_op; - reg = ((modrm >> 3) & 7) | REX_R(s); - { - AddressParts a = gen_lea_modrm_0(env, s, modrm); - TCGv ea = gen_lea_modrm_1(s, a, false); - gen_lea_v_seg(s, s->aflag, ea, -1, -1); - gen_op_mov_reg_v(s, dflag, reg, s->A0); - } - break; - - case 0xa0: /* mov EAX, Ov */ - case 0xa1: - case 0xa2: /* mov Ov, EAX */ - case 0xa3: - { - target_ulong offset_addr; - - ot = mo_b_d(b, dflag); - offset_addr = insn_get_addr(env, s, s->aflag); - tcg_gen_movi_tl(s->A0, offset_addr); - gen_add_A0_ds_seg(s); - if ((b & 2) == 0) { - gen_op_ld_v(s, ot, s->T0, s->A0); - gen_op_mov_reg_v(s, ot, R_EAX, s->T0); - } else { - gen_op_mov_v_reg(s, ot, s->T0, R_EAX); - gen_op_st_v(s, ot, s->T0, s->A0); - } - } - break; - case 0xd7: /* xlat */ - tcg_gen_mov_tl(s->A0, cpu_regs[R_EBX]); - tcg_gen_ext8u_tl(s->T0, cpu_regs[R_EAX]); - tcg_gen_add_tl(s->A0, s->A0, s->T0); - gen_add_A0_ds_seg(s); - gen_op_ld_v(s, MO_8, s->T0, s->A0); - gen_op_mov_reg_v(s, MO_8, R_EAX, s->T0); - break; - case 0xb0 ... 0xb7: /* mov R, Ib */ - val = insn_get(env, s, MO_8); - tcg_gen_movi_tl(s->T0, val); - gen_op_mov_reg_v(s, MO_8, (b & 7) | REX_B(s), s->T0); - break; - case 0xb8 ... 0xbf: /* mov R, Iv */ -#ifdef TARGET_X86_64 - if (dflag == MO_64) { - uint64_t tmp; - /* 64 bit case */ - tmp = x86_ldq_code(env, s); - reg = (b & 7) | REX_B(s); - tcg_gen_movi_tl(s->T0, tmp); - gen_op_mov_reg_v(s, MO_64, reg, s->T0); - } else -#endif - { - ot = dflag; - val = insn_get(env, s, ot); - reg = (b & 7) | REX_B(s); - tcg_gen_movi_tl(s->T0, val); - gen_op_mov_reg_v(s, ot, reg, s->T0); - } - break; - - case 0x91 ... 0x97: /* xchg R, EAX */ - do_xchg_reg_eax: - ot = dflag; - reg = (b & 7) | REX_B(s); - rm = R_EAX; - goto do_xchg_reg; - case 0x86: - case 0x87: /* xchg Ev, Gv */ - ot = mo_b_d(b, dflag); - modrm = x86_ldub_code(env, s); - reg = ((modrm >> 3) & 7) | REX_R(s); - mod = (modrm >> 6) & 3; - if (mod == 3) { - rm = (modrm & 7) | REX_B(s); - do_xchg_reg: - gen_op_mov_v_reg(s, ot, s->T0, reg); - gen_op_mov_v_reg(s, ot, s->T1, rm); - gen_op_mov_reg_v(s, ot, rm, s->T0); - gen_op_mov_reg_v(s, ot, reg, s->T1); - } else { - gen_lea_modrm(env, s, modrm); - gen_op_mov_v_reg(s, ot, s->T0, reg); - /* for xchg, lock is implicit */ - tcg_gen_atomic_xchg_tl(s->T1, s->A0, s->T0, - s->mem_index, ot | MO_LE); - gen_op_mov_reg_v(s, ot, reg, s->T1); - } - break; - case 0xc4: /* les Gv */ - /* In CODE64 this is VEX3; see above. */ - op = R_ES; - goto do_lxx; - case 0xc5: /* lds Gv */ - /* In CODE64 this is VEX2; see above. */ - op = R_DS; - goto do_lxx; - case 0x1b2: /* lss Gv */ - op = R_SS; - goto do_lxx; - case 0x1b4: /* lfs Gv */ - op = R_FS; - goto do_lxx; - case 0x1b5: /* lgs Gv */ - op = R_GS; - do_lxx: - ot = dflag != MO_16 ? MO_32 : MO_16; - modrm = x86_ldub_code(env, s); - reg = ((modrm >> 3) & 7) | REX_R(s); - mod = (modrm >> 6) & 3; - if (mod == 3) - goto illegal_op; - gen_lea_modrm(env, s, modrm); - gen_op_ld_v(s, ot, s->T1, s->A0); - gen_add_A0_im(s, 1 << ot); - /* load the segment first to handle exceptions properly */ - gen_op_ld_v(s, MO_16, s->T0, s->A0); - gen_movl_seg(s, op, s->T0); - /* then put the data */ - gen_op_mov_reg_v(s, ot, reg, s->T1); - break; - - /************************/ /* shifts */ - case 0xc0: - case 0xc1: - /* shift Ev,Ib */ - shift = 2; - grp2: - { - ot = mo_b_d(b, dflag); - modrm = x86_ldub_code(env, s); - mod = (modrm >> 6) & 3; - op = (modrm >> 3) & 7; - - if (mod != 3) { - if (shift == 2) { - s->rip_offset = 1; - } - gen_lea_modrm(env, s, modrm); - opreg = OR_TMP0; - } else { - opreg = (modrm & 7) | REX_B(s); - } - - /* simpler op */ - if (shift == 0) { - gen_shift(s, op, ot, opreg, OR_ECX); - } else { - if (shift == 2) { - shift = x86_ldub_code(env, s); - } - gen_shifti(s, op, ot, opreg, shift); - } - } - break; - case 0xd0: - case 0xd1: - /* shift Ev,1 */ - shift = 1; - goto grp2; - case 0xd2: - case 0xd3: - /* shift Ev,cl */ - shift = 0; - goto grp2; - case 0x1a4: /* shld imm */ op = 0; shift = 1; @@ -4990,371 +3467,6 @@ static bool disas_insn(DisasContext *s, CPUState *cpu) } } break; - /************************/ - /* string ops */ - - case 0xa4: /* movsS */ - case 0xa5: - ot = mo_b_d(b, dflag); - if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { - gen_repz_movs(s, ot); - } else { - gen_movs(s, ot); - } - break; - - case 0xaa: /* stosS */ - case 0xab: - ot = mo_b_d(b, dflag); - gen_op_mov_v_reg(s, MO_32, s->T0, R_EAX); - if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { - gen_repz_stos(s, ot); - } else { - gen_stos(s, ot); - } - break; - case 0xac: /* lodsS */ - case 0xad: - ot = mo_b_d(b, dflag); - if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { - gen_repz_lods(s, ot); - } else { - gen_lods(s, ot); - } - break; - case 0xae: /* scasS */ - case 0xaf: - ot = mo_b_d(b, dflag); - gen_op_mov_v_reg(s, MO_32, s->T0, R_EAX); - if (prefixes & PREFIX_REPNZ) { - gen_repz_scas(s, ot, 1); - } else if (prefixes & PREFIX_REPZ) { - gen_repz_scas(s, ot, 0); - } else { - gen_scas(s, ot); - } - break; - - case 0xa6: /* cmpsS */ - case 0xa7: - ot = mo_b_d(b, dflag); - if (prefixes & PREFIX_REPNZ) { - gen_repz_cmps(s, ot, 1); - } else if (prefixes & PREFIX_REPZ) { - gen_repz_cmps(s, ot, 0); - } else { - gen_cmps(s, ot); - } - break; - case 0x6c: /* insS */ - case 0x6d: - ot = mo_b_d32(b, dflag); - tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_EDX]); - tcg_gen_ext16u_i32(s->tmp2_i32, s->tmp2_i32); - if (!gen_check_io(s, ot, s->tmp2_i32, - SVM_IOIO_TYPE_MASK | SVM_IOIO_STR_MASK)) { - break; - } - translator_io_start(&s->base); - if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { - gen_repz_ins(s, ot); - } else { - gen_ins(s, ot); - } - break; - case 0x6e: /* outsS */ - case 0x6f: - ot = mo_b_d32(b, dflag); - tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_EDX]); - tcg_gen_ext16u_i32(s->tmp2_i32, s->tmp2_i32); - if (!gen_check_io(s, ot, s->tmp2_i32, SVM_IOIO_STR_MASK)) { - break; - } - translator_io_start(&s->base); - if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { - gen_repz_outs(s, ot); - } else { - gen_outs(s, ot); - } - break; - - /************************/ - /* port I/O */ - - case 0xe4: - case 0xe5: - ot = mo_b_d32(b, dflag); - val = x86_ldub_code(env, s); - tcg_gen_movi_i32(s->tmp2_i32, val); - if (!gen_check_io(s, ot, s->tmp2_i32, SVM_IOIO_TYPE_MASK)) { - break; - } - translator_io_start(&s->base); - gen_helper_in_func(ot, s->T1, s->tmp2_i32); - gen_op_mov_reg_v(s, ot, R_EAX, s->T1); - gen_bpt_io(s, s->tmp2_i32, ot); - break; - case 0xe6: - case 0xe7: - ot = mo_b_d32(b, dflag); - val = x86_ldub_code(env, s); - tcg_gen_movi_i32(s->tmp2_i32, val); - if (!gen_check_io(s, ot, s->tmp2_i32, 0)) { - break; - } - translator_io_start(&s->base); - gen_op_mov_v_reg(s, ot, s->T1, R_EAX); - tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1); - gen_helper_out_func(ot, s->tmp2_i32, s->tmp3_i32); - gen_bpt_io(s, s->tmp2_i32, ot); - break; - case 0xec: - case 0xed: - ot = mo_b_d32(b, dflag); - tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_EDX]); - tcg_gen_ext16u_i32(s->tmp2_i32, s->tmp2_i32); - if (!gen_check_io(s, ot, s->tmp2_i32, SVM_IOIO_TYPE_MASK)) { - break; - } - translator_io_start(&s->base); - gen_helper_in_func(ot, s->T1, s->tmp2_i32); - gen_op_mov_reg_v(s, ot, R_EAX, s->T1); - gen_bpt_io(s, s->tmp2_i32, ot); - break; - case 0xee: - case 0xef: - ot = mo_b_d32(b, dflag); - tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_EDX]); - tcg_gen_ext16u_i32(s->tmp2_i32, s->tmp2_i32); - if (!gen_check_io(s, ot, s->tmp2_i32, 0)) { - break; - } - translator_io_start(&s->base); - gen_op_mov_v_reg(s, ot, s->T1, R_EAX); - tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1); - gen_helper_out_func(ot, s->tmp2_i32, s->tmp3_i32); - gen_bpt_io(s, s->tmp2_i32, ot); - break; - - /************************/ - /* control */ - case 0xc2: /* ret im */ - val = x86_ldsw_code(env, s); - ot = gen_pop_T0(s); - gen_stack_update(s, val + (1 << ot)); - /* Note that gen_pop_T0 uses a zero-extending load. */ - gen_op_jmp_v(s, s->T0); - gen_bnd_jmp(s); - s->base.is_jmp = DISAS_JUMP; - break; - case 0xc3: /* ret */ - ot = gen_pop_T0(s); - gen_pop_update(s, ot); - /* Note that gen_pop_T0 uses a zero-extending load. */ - gen_op_jmp_v(s, s->T0); - gen_bnd_jmp(s); - s->base.is_jmp = DISAS_JUMP; - break; - case 0xca: /* lret im */ - val = x86_ldsw_code(env, s); - do_lret: - if (PE(s) && !VM86(s)) { - gen_update_cc_op(s); - gen_update_eip_cur(s); - gen_helper_lret_protected(tcg_env, tcg_constant_i32(dflag - 1), - tcg_constant_i32(val)); - } else { - gen_stack_A0(s); - /* pop offset */ - gen_op_ld_v(s, dflag, s->T0, s->A0); - /* NOTE: keeping EIP updated is not a problem in case of - exception */ - gen_op_jmp_v(s, s->T0); - /* pop selector */ - gen_add_A0_im(s, 1 << dflag); - gen_op_ld_v(s, dflag, s->T0, s->A0); - gen_op_movl_seg_real(s, R_CS, s->T0); - /* add stack offset */ - gen_stack_update(s, val + (2 << dflag)); - } - s->base.is_jmp = DISAS_EOB_ONLY; - break; - case 0xcb: /* lret */ - val = 0; - goto do_lret; - case 0xcf: /* iret */ - gen_svm_check_intercept(s, SVM_EXIT_IRET); - if (!PE(s) || VM86(s)) { - /* real mode or vm86 mode */ - if (!check_vm86_iopl(s)) { - break; - } - gen_helper_iret_real(tcg_env, tcg_constant_i32(dflag - 1)); - } else { - gen_helper_iret_protected(tcg_env, tcg_constant_i32(dflag - 1), - eip_next_i32(s)); - } - set_cc_op(s, CC_OP_EFLAGS); - s->base.is_jmp = DISAS_EOB_ONLY; - break; - case 0xe8: /* call im */ - { - int diff = (dflag != MO_16 - ? (int32_t)insn_get(env, s, MO_32) - : (int16_t)insn_get(env, s, MO_16)); - gen_push_v(s, eip_next_tl(s)); - gen_bnd_jmp(s); - gen_jmp_rel(s, dflag, diff, 0); - } - break; - case 0x9a: /* lcall im */ - { - unsigned int selector, offset; - - if (CODE64(s)) - goto illegal_op; - ot = dflag; - offset = insn_get(env, s, ot); - selector = insn_get(env, s, MO_16); - - tcg_gen_movi_tl(s->T0, offset); - tcg_gen_movi_tl(s->T1, selector); - } - gen_far_call(s); - break; - case 0xe9: /* jmp im */ - { - int diff = (dflag != MO_16 - ? (int32_t)insn_get(env, s, MO_32) - : (int16_t)insn_get(env, s, MO_16)); - gen_bnd_jmp(s); - gen_jmp_rel(s, dflag, diff, 0); - } - break; - case 0xea: /* ljmp im */ - { - unsigned int selector, offset; - - if (CODE64(s)) - goto illegal_op; - ot = dflag; - offset = insn_get(env, s, ot); - selector = insn_get(env, s, MO_16); - - tcg_gen_movi_tl(s->T0, offset); - tcg_gen_movi_tl(s->T1, selector); - } - gen_far_jmp(s); - break; - case 0xeb: /* jmp Jb */ - { - int diff = (int8_t)insn_get(env, s, MO_8); - gen_jmp_rel(s, dflag, diff, 0); - } - break; - case 0x70 ... 0x7f: /* jcc Jb */ - { - int diff = (int8_t)insn_get(env, s, MO_8); - gen_bnd_jmp(s); - gen_jcc(s, b, diff); - } - break; - case 0x180 ... 0x18f: /* jcc Jv */ - { - int diff = (dflag != MO_16 - ? (int32_t)insn_get(env, s, MO_32) - : (int16_t)insn_get(env, s, MO_16)); - gen_bnd_jmp(s); - gen_jcc(s, b, diff); - } - break; - - case 0x190 ... 0x19f: /* setcc Gv */ - modrm = x86_ldub_code(env, s); - gen_setcc1(s, b, s->T0); - gen_ldst_modrm(env, s, modrm, MO_8, OR_TMP0, 1); - break; - case 0x140 ... 0x14f: /* cmov Gv, Ev */ - if (!(s->cpuid_features & CPUID_CMOV)) { - goto illegal_op; - } - ot = dflag; - modrm = x86_ldub_code(env, s); - reg = ((modrm >> 3) & 7) | REX_R(s); - gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0); - gen_cmovcc1(s, b ^ 1, s->T0, cpu_regs[reg]); - gen_op_mov_reg_v(s, ot, reg, s->T0); - break; - - /************************/ - /* flags */ - case 0x9c: /* pushf */ - gen_svm_check_intercept(s, SVM_EXIT_PUSHF); - if (check_vm86_iopl(s)) { - gen_update_cc_op(s); - gen_helper_read_eflags(s->T0, tcg_env); - gen_push_v(s, s->T0); - } - break; - case 0x9d: /* popf */ - gen_svm_check_intercept(s, SVM_EXIT_POPF); - if (check_vm86_iopl(s)) { - int mask = TF_MASK | AC_MASK | ID_MASK | NT_MASK; - - if (CPL(s) == 0) { - mask |= IF_MASK | IOPL_MASK; - } else if (CPL(s) <= IOPL(s)) { - mask |= IF_MASK; - } - if (dflag == MO_16) { - mask &= 0xffff; - } - - ot = gen_pop_T0(s); - gen_helper_write_eflags(tcg_env, s->T0, tcg_constant_i32(mask)); - gen_pop_update(s, ot); - set_cc_op(s, CC_OP_EFLAGS); - /* abort translation because TF/AC flag may change */ - s->base.is_jmp = DISAS_EOB_NEXT; - } - break; - case 0x9e: /* sahf */ - if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM)) - goto illegal_op; - tcg_gen_shri_tl(s->T0, cpu_regs[R_EAX], 8); - gen_compute_eflags(s); - tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, CC_O); - tcg_gen_andi_tl(s->T0, s->T0, CC_S | CC_Z | CC_A | CC_P | CC_C); - tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, s->T0); - break; - case 0x9f: /* lahf */ - if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM)) - goto illegal_op; - gen_compute_eflags(s); - /* Note: gen_compute_eflags() only gives the condition codes */ - tcg_gen_ori_tl(s->T0, cpu_cc_src, 0x02); - tcg_gen_deposit_tl(cpu_regs[R_EAX], cpu_regs[R_EAX], s->T0, 8, 8); - break; - case 0xf5: /* cmc */ - gen_compute_eflags(s); - tcg_gen_xori_tl(cpu_cc_src, cpu_cc_src, CC_C); - break; - case 0xf8: /* clc */ - gen_compute_eflags(s); - tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_C); - break; - case 0xf9: /* stc */ - gen_compute_eflags(s); - tcg_gen_ori_tl(cpu_cc_src, cpu_cc_src, CC_C); - break; - case 0xfc: /* cld */ - tcg_gen_movi_i32(s->tmp2_i32, 1); - tcg_gen_st_i32(s->tmp2_i32, tcg_env, offsetof(CPUX86State, df)); - break; - case 0xfd: /* std */ - tcg_gen_movi_i32(s->tmp2_i32, -1); - tcg_gen_st_i32(s->tmp2_i32, tcg_env, offsetof(CPUX86State, df)); - break; /************************/ /* bit operations */ @@ -5545,188 +3657,6 @@ static bool disas_insn(DisasContext *s, CPUState *cpu) } gen_op_mov_reg_v(s, ot, reg, s->T0); break; - /************************/ - /* bcd */ - case 0x27: /* daa */ - if (CODE64(s)) - goto illegal_op; - gen_update_cc_op(s); - gen_helper_daa(tcg_env); - set_cc_op(s, CC_OP_EFLAGS); - break; - case 0x2f: /* das */ - if (CODE64(s)) - goto illegal_op; - gen_update_cc_op(s); - gen_helper_das(tcg_env); - set_cc_op(s, CC_OP_EFLAGS); - break; - case 0x37: /* aaa */ - if (CODE64(s)) - goto illegal_op; - gen_update_cc_op(s); - gen_helper_aaa(tcg_env); - set_cc_op(s, CC_OP_EFLAGS); - break; - case 0x3f: /* aas */ - if (CODE64(s)) - goto illegal_op; - gen_update_cc_op(s); - gen_helper_aas(tcg_env); - set_cc_op(s, CC_OP_EFLAGS); - break; - case 0xd4: /* aam */ - if (CODE64(s)) - goto illegal_op; - val = x86_ldub_code(env, s); - if (val == 0) { - gen_exception(s, EXCP00_DIVZ); - } else { - gen_helper_aam(tcg_env, tcg_constant_i32(val)); - set_cc_op(s, CC_OP_LOGICB); - } - break; - case 0xd5: /* aad */ - if (CODE64(s)) - goto illegal_op; - val = x86_ldub_code(env, s); - gen_helper_aad(tcg_env, tcg_constant_i32(val)); - set_cc_op(s, CC_OP_LOGICB); - break; - /************************/ - /* misc */ - case 0x90: /* nop */ - /* XXX: correct lock test for all insn */ - if (prefixes & PREFIX_LOCK) { - goto illegal_op; - } - /* If REX_B is set, then this is xchg eax, r8d, not a nop. */ - if (REX_B(s)) { - goto do_xchg_reg_eax; - } - if (prefixes & PREFIX_REPZ) { - gen_update_cc_op(s); - gen_update_eip_cur(s); - gen_helper_pause(tcg_env, cur_insn_len_i32(s)); - s->base.is_jmp = DISAS_NORETURN; - } - break; - case 0x9b: /* fwait */ - if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) == - (HF_MP_MASK | HF_TS_MASK)) { - gen_exception(s, EXCP07_PREX); - } else { - /* needs to be treated as I/O because of ferr_irq */ - translator_io_start(&s->base); - gen_helper_fwait(tcg_env); - } - break; - case 0xcc: /* int3 */ - gen_interrupt(s, EXCP03_INT3); - break; - case 0xcd: /* int N */ - val = x86_ldub_code(env, s); - if (check_vm86_iopl(s)) { - gen_interrupt(s, val); - } - break; - case 0xce: /* into */ - if (CODE64(s)) - goto illegal_op; - gen_update_cc_op(s); - gen_update_eip_cur(s); - gen_helper_into(tcg_env, cur_insn_len_i32(s)); - break; -#ifdef WANT_ICEBP - case 0xf1: /* icebp (undocumented, exits to external debugger) */ - gen_svm_check_intercept(s, SVM_EXIT_ICEBP); - gen_debug(s); - break; -#endif - case 0xfa: /* cli */ - if (check_iopl(s)) { - gen_reset_eflags(s, IF_MASK); - } - break; - case 0xfb: /* sti */ - if (check_iopl(s)) { - gen_set_eflags(s, IF_MASK); - /* interruptions are enabled only the first insn after sti */ - gen_update_eip_next(s); - gen_eob_inhibit_irq(s, true); - } - break; - case 0x62: /* bound */ - if (CODE64(s)) - goto illegal_op; - ot = dflag; - modrm = x86_ldub_code(env, s); - reg = (modrm >> 3) & 7; - mod = (modrm >> 6) & 3; - if (mod == 3) - goto illegal_op; - gen_op_mov_v_reg(s, ot, s->T0, reg); - gen_lea_modrm(env, s, modrm); - tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); - if (ot == MO_16) { - gen_helper_boundw(tcg_env, s->A0, s->tmp2_i32); - } else { - gen_helper_boundl(tcg_env, s->A0, s->tmp2_i32); - } - break; - case 0x1c8 ... 0x1cf: /* bswap reg */ - reg = (b & 7) | REX_B(s); -#ifdef TARGET_X86_64 - if (dflag == MO_64) { - tcg_gen_bswap64_i64(cpu_regs[reg], cpu_regs[reg]); - break; - } -#endif - tcg_gen_bswap32_tl(cpu_regs[reg], cpu_regs[reg], TCG_BSWAP_OZ); - break; - case 0xd6: /* salc */ - if (CODE64(s)) - goto illegal_op; - gen_compute_eflags_c(s, s->T0); - tcg_gen_neg_tl(s->T0, s->T0); - gen_op_mov_reg_v(s, MO_8, R_EAX, s->T0); - break; - case 0xe0: /* loopnz */ - case 0xe1: /* loopz */ - case 0xe2: /* loop */ - case 0xe3: /* jecxz */ - { - TCGLabel *l1, *l2; - int diff = (int8_t)insn_get(env, s, MO_8); - - l1 = gen_new_label(); - l2 = gen_new_label(); - gen_update_cc_op(s); - b &= 3; - switch(b) { - case 0: /* loopnz */ - case 1: /* loopz */ - gen_op_add_reg_im(s, s->aflag, R_ECX, -1); - gen_op_jz_ecx(s, l2); - gen_jcc1(s, (JCC_Z << 1) | (b ^ 1), l1); - break; - case 2: /* loop */ - gen_op_add_reg_im(s, s->aflag, R_ECX, -1); - gen_op_jnz_ecx(s, l1); - break; - default: - case 3: /* jcxz */ - gen_op_jz_ecx(s, l1); - break; - } - - gen_set_label(l2); - gen_jmp_rel_csize(s, 0, 1); - - gen_set_label(l1); - gen_jmp_rel(s, dflag, diff, 0); - } - break; case 0x130: /* wrmsr */ case 0x132: /* rdmsr */ if (check_cpl0(s)) { @@ -5814,14 +3744,6 @@ static bool disas_insn(DisasContext *s, CPUState *cpu) gen_update_eip_cur(s); gen_helper_cpuid(tcg_env); break; - case 0xf4: /* hlt */ - if (check_cpl0(s)) { - gen_update_cc_op(s); - gen_update_eip_cur(s); - gen_helper_hlt(tcg_env, cur_insn_len_i32(s)); - s->base.is_jmp = DISAS_NORETURN; - } - break; case 0x100: modrm = x86_ldub_code(env, s); mod = (modrm >> 6) & 3; @@ -6224,72 +4146,6 @@ static bool disas_insn(DisasContext *s, CPUState *cpu) /* nothing to do */ } break; - case 0x63: /* arpl or movslS (x86_64) */ -#ifdef TARGET_X86_64 - if (CODE64(s)) { - int d_ot; - /* d_ot is the size of destination */ - d_ot = dflag; - - modrm = x86_ldub_code(env, s); - reg = ((modrm >> 3) & 7) | REX_R(s); - mod = (modrm >> 6) & 3; - rm = (modrm & 7) | REX_B(s); - - if (mod == 3) { - gen_op_mov_v_reg(s, MO_32, s->T0, rm); - /* sign extend */ - if (d_ot == MO_64) { - tcg_gen_ext32s_tl(s->T0, s->T0); - } - gen_op_mov_reg_v(s, d_ot, reg, s->T0); - } else { - gen_lea_modrm(env, s, modrm); - gen_op_ld_v(s, MO_32 | MO_SIGN, s->T0, s->A0); - gen_op_mov_reg_v(s, d_ot, reg, s->T0); - } - } else -#endif - { - TCGLabel *label1; - TCGv t0, t1, t2; - - if (!PE(s) || VM86(s)) - goto illegal_op; - t0 = tcg_temp_new(); - t1 = tcg_temp_new(); - t2 = tcg_temp_new(); - ot = MO_16; - modrm = x86_ldub_code(env, s); - reg = (modrm >> 3) & 7; - mod = (modrm >> 6) & 3; - rm = modrm & 7; - if (mod != 3) { - gen_lea_modrm(env, s, modrm); - gen_op_ld_v(s, ot, t0, s->A0); - } else { - gen_op_mov_v_reg(s, ot, t0, rm); - } - gen_op_mov_v_reg(s, ot, t1, reg); - tcg_gen_andi_tl(s->tmp0, t0, 3); - tcg_gen_andi_tl(t1, t1, 3); - tcg_gen_movi_tl(t2, 0); - label1 = gen_new_label(); - tcg_gen_brcond_tl(TCG_COND_GE, s->tmp0, t1, label1); - tcg_gen_andi_tl(t0, t0, ~3); - tcg_gen_or_tl(t0, t0, t1); - tcg_gen_movi_tl(t2, CC_Z); - gen_set_label(label1); - if (mod != 3) { - gen_op_st_v(s, ot, t0, s->A0); - } else { - gen_op_mov_reg_v(s, ot, rm, t0); - } - gen_compute_eflags(s); - tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_Z); - tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t2); - } - break; case 0x102: /* lar */ case 0x103: /* lsl */ { @@ -6616,18 +4472,6 @@ static bool disas_insn(DisasContext *s, CPUState *cpu) } break; /* MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4 support */ - case 0x1c3: /* MOVNTI reg, mem */ - if (!(s->cpuid_features & CPUID_SSE2)) - goto illegal_op; - ot = mo_64_32(dflag); - modrm = x86_ldub_code(env, s); - mod = (modrm >> 6) & 3; - if (mod == 3) - goto illegal_op; - reg = ((modrm >> 3) & 7) | REX_R(s); - /* generate a generic store */ - gen_ldst_modrm(env, s, modrm, ot, reg, 1); - break; case 0x1ae: modrm = x86_ldub_code(env, s); switch (modrm) { @@ -6870,13 +4714,19 @@ static bool disas_insn(DisasContext *s, CPUState *cpu) set_cc_op(s, CC_OP_POPCNT); break; + case 0 ... 0xd7: + case 0xe0 ... 0xff: case 0x10e ... 0x117: case 0x128 ... 0x12f: - case 0x138 ... 0x13f: - case 0x150 ... 0x17f: - case 0x1c2: - case 0x1c4 ... 0x1c6: - case 0x1d0 ... 0x1fe: + case 0x138 ... 0x19f: + case 0x1a0 ... 0x1a1: + case 0x1a8 ... 0x1a9: + case 0x1af: + case 0x1b2: + case 0x1b4 ... 0x1b7: + case 0x1be ... 0x1bf: + case 0x1c2 ... 0x1c6: + case 0x1c8 ... 0x1ff: disas_insn_new(s, cpu, b); break; default: diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc index 2e27d28dc95..3fc3f6b7d29 100644 --- a/target/i386/tcg/decode-new.c.inc +++ b/target/i386/tcg/decode-new.c.inc @@ -2222,9 +2222,6 @@ static void disas_insn_new(DisasContext *s, CPUState *cpu, int b) X86DecodeFunc decode_func = decode_root; uint8_t cc_live; -#ifdef CONFIG_USER_ONLY - if (limit) { --limit; } -#endif s->has_modrm = false; next_byte: From patchwork Tue Apr 9 16:43:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 13622960 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 702ADC67861 for ; Tue, 9 Apr 2024 16:49:52 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ruEaf-00013a-2r; Tue, 09 Apr 2024 12:44:57 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ruEaJ-0000hM-Tf for qemu-devel@nongnu.org; Tue, 09 Apr 2024 12:44:43 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ruEa9-00087t-FG for qemu-devel@nongnu.org; Tue, 09 Apr 2024 12:44:34 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1712681058; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=J2xXAGP+Q/9sg2vX1M6qD/LnG1pJUoWNijXMadeFAD0=; b=Z4BjHsT+NZBXHyn0iW2NNDFC22/wXygbSa6deaOMMpSEodmXEOgp8Hr5+4gPn2jPV6mKba oXb/euWtrWYdpkgmcQhH5l7OFEIjKJVr03bVHhvqY4X2s8hrr8PQxjEfvQvtkhJc6fm6Me JvjYdqu/D7KQbaXH5NLs2yR+kuKegLw= Received: from mail-wm1-f69.google.com (mail-wm1-f69.google.com [209.85.128.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-626-P-GQLjZkOuOlTPexFzGyww-1; Tue, 09 Apr 2024 12:44:16 -0400 X-MC-Unique: P-GQLjZkOuOlTPexFzGyww-1 Received: by mail-wm1-f69.google.com with SMTP id 5b1f17b1804b1-4166b96002dso11113985e9.0 for ; Tue, 09 Apr 2024 09:44:15 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712681054; x=1713285854; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=J2xXAGP+Q/9sg2vX1M6qD/LnG1pJUoWNijXMadeFAD0=; b=PwHmUrOeaBHb5BvsWZ5YeBvuQ1I7GhbqnSe/bYFzH52SjJwXD+5HWqQL8qb9Js0qKY aFFSnqu2Y08mbx0YvCL6POOgk/z4YzUDClkKF3ij6Q8pjWyT7Ps4HUZez0Fp4ITwxOkp 3idBvxtzEL7GGzKfZ3xBvWRjBJ3sXKrTsi/KVRw76Y/HFc4kQgSDN+xi9fgKGuQBEkjO pyNEWnNAtVH59JJZ3lxfUL9kRuRYgtUG6w7MqbvXRPhRSpRYWw2UDHxt1X0xzlBwOleh 9q5OUrWM6uS9wBv06EMpcl9Wz5V4aJt/SbiCrnLxVm+vVkEamXl7whTCgt4tfsKMG654 Immw== X-Gm-Message-State: AOJu0YzbkA5oWpG1ginnJoSyy/zzrQn36VsQypo4qKjK9vaT6BuNnILj EJCUzdKAg/JC1YClddPTI7aQJu0eoe6iLo3UaGilCfYSgd2rlclQXe6TPFT/2pXDoIlXwjdGZfE g/iD92eWNWoxlfeu/xgaYs5jbDVPm1H4IbERgO4umV/BcLjaqNdQitcGwI+B7M9d8MMCel+RDko iU1qbwNCtTEHrFf/wZHAF6JNre0x5TyEvlIq+J X-Received: by 2002:a05:600c:3b0f:b0:415:f755:5a1f with SMTP id m15-20020a05600c3b0f00b00415f7555a1fmr180679wms.29.1712681054038; Tue, 09 Apr 2024 09:44:14 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFPeDP6hzbJ/Ct8GLRuxU6r09Nfi8EkaJeHdOvh3g1s3bHD835OC4SchJBpPQ0Z4oDQJ65A4w== X-Received: by 2002:a05:600c:3b0f:b0:415:f755:5a1f with SMTP id m15-20020a05600c3b0f00b00415f7555a1fmr180657wms.29.1712681053412; Tue, 09 Apr 2024 09:44:13 -0700 (PDT) Received: from avogadro.local ([151.95.152.232]) by smtp.gmail.com with ESMTPSA id c15-20020adffb0f000000b00345fb949c28sm3334773wrr.100.2024.04.09.09.44.12 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 09 Apr 2024 09:44:13 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Subject: [PATCH for-9.1 17/19] target/i386: decode x87 instructions in a separate function Date: Tue, 9 Apr 2024 18:43:21 +0200 Message-ID: <20240409164323.776660-18-pbonzini@redhat.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240409164323.776660-1-pbonzini@redhat.com> References: <20240409164323.776660-1-pbonzini@redhat.com> MIME-Version: 1.0 Received-SPF: pass client-ip=170.10.133.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -37 X-Spam_score: -3.8 X-Spam_bar: --- X-Spam_report: (-3.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1.701, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org These are unlikely to be converted to the table-based decoding soon (perhaps there could be generic ESC decoding in decode-new.c.inc for the Mod/RM byte, but not operand decoding), so keep them separate from the remaining legacy-decoded instructions. Signed-off-by: Paolo Bonzini Reviewed-by: Philippe Mathieu-Daudé Acked-by: Richard Henderson --- target/i386/tcg/translate.c | 1120 ++++++++++++++++++----------------- 1 file changed, 566 insertions(+), 554 deletions(-) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 81291da4132..e7f51685ed8 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -2555,6 +2555,570 @@ static void gen_cmpxchg16b(DisasContext *s, CPUX86State *env, int modrm) } #endif +static bool disas_insn_x87(DisasContext *s, CPUState *cpu, int b) +{ + CPUX86State *env = cpu_env(cpu); + bool update_fip = true; + int modrm, mod, rm, op; + + if (s->flags & (HF_EM_MASK | HF_TS_MASK)) { + /* if CR0.EM or CR0.TS are set, generate an FPU exception */ + /* XXX: what to do if illegal op ? */ + gen_exception(s, EXCP07_PREX); + return true; + } + modrm = x86_ldub_code(env, s); + mod = (modrm >> 6) & 3; + rm = modrm & 7; + op = ((b & 7) << 3) | ((modrm >> 3) & 7); + if (mod != 3) { + /* memory op */ + AddressParts a = gen_lea_modrm_0(env, s, modrm); + TCGv ea = gen_lea_modrm_1(s, a, false); + TCGv last_addr = tcg_temp_new(); + bool update_fdp = true; + + tcg_gen_mov_tl(last_addr, ea); + gen_lea_v_seg(s, s->aflag, ea, a.def_seg, s->override); + + switch (op) { + case 0x00 ... 0x07: /* fxxxs */ + case 0x10 ... 0x17: /* fixxxl */ + case 0x20 ... 0x27: /* fxxxl */ + case 0x30 ... 0x37: /* fixxx */ + { + int op1; + op1 = op & 7; + + switch (op >> 4) { + case 0: + tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LEUL); + gen_helper_flds_FT0(tcg_env, s->tmp2_i32); + break; + case 1: + tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LEUL); + gen_helper_fildl_FT0(tcg_env, s->tmp2_i32); + break; + case 2: + tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, + s->mem_index, MO_LEUQ); + gen_helper_fldl_FT0(tcg_env, s->tmp1_i64); + break; + case 3: + default: + tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LESW); + gen_helper_fildl_FT0(tcg_env, s->tmp2_i32); + break; + } + + gen_helper_fp_arith_ST0_FT0(op1); + if (op1 == 3) { + /* fcomp needs pop */ + gen_helper_fpop(tcg_env); + } + } + break; + case 0x08: /* flds */ + case 0x0a: /* fsts */ + case 0x0b: /* fstps */ + case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */ + case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */ + case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */ + switch (op & 7) { + case 0: + switch (op >> 4) { + case 0: + tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LEUL); + gen_helper_flds_ST0(tcg_env, s->tmp2_i32); + break; + case 1: + tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LEUL); + gen_helper_fildl_ST0(tcg_env, s->tmp2_i32); + break; + case 2: + tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, + s->mem_index, MO_LEUQ); + gen_helper_fldl_ST0(tcg_env, s->tmp1_i64); + break; + case 3: + default: + tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LESW); + gen_helper_fildl_ST0(tcg_env, s->tmp2_i32); + break; + } + break; + case 1: + /* XXX: the corresponding CPUID bit must be tested ! */ + switch (op >> 4) { + case 1: + gen_helper_fisttl_ST0(s->tmp2_i32, tcg_env); + tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LEUL); + break; + case 2: + gen_helper_fisttll_ST0(s->tmp1_i64, tcg_env); + tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, + s->mem_index, MO_LEUQ); + break; + case 3: + default: + gen_helper_fistt_ST0(s->tmp2_i32, tcg_env); + tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LEUW); + break; + } + gen_helper_fpop(tcg_env); + break; + default: + switch (op >> 4) { + case 0: + gen_helper_fsts_ST0(s->tmp2_i32, tcg_env); + tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LEUL); + break; + case 1: + gen_helper_fistl_ST0(s->tmp2_i32, tcg_env); + tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LEUL); + break; + case 2: + gen_helper_fstl_ST0(s->tmp1_i64, tcg_env); + tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, + s->mem_index, MO_LEUQ); + break; + case 3: + default: + gen_helper_fist_ST0(s->tmp2_i32, tcg_env); + tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LEUW); + break; + } + if ((op & 7) == 3) { + gen_helper_fpop(tcg_env); + } + break; + } + break; + case 0x0c: /* fldenv mem */ + gen_helper_fldenv(tcg_env, s->A0, + tcg_constant_i32(s->dflag - 1)); + update_fip = update_fdp = false; + break; + case 0x0d: /* fldcw mem */ + tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LEUW); + gen_helper_fldcw(tcg_env, s->tmp2_i32); + update_fip = update_fdp = false; + break; + case 0x0e: /* fnstenv mem */ + gen_helper_fstenv(tcg_env, s->A0, + tcg_constant_i32(s->dflag - 1)); + update_fip = update_fdp = false; + break; + case 0x0f: /* fnstcw mem */ + gen_helper_fnstcw(s->tmp2_i32, tcg_env); + tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LEUW); + update_fip = update_fdp = false; + break; + case 0x1d: /* fldt mem */ + gen_helper_fldt_ST0(tcg_env, s->A0); + break; + case 0x1f: /* fstpt mem */ + gen_helper_fstt_ST0(tcg_env, s->A0); + gen_helper_fpop(tcg_env); + break; + case 0x2c: /* frstor mem */ + gen_helper_frstor(tcg_env, s->A0, + tcg_constant_i32(s->dflag - 1)); + update_fip = update_fdp = false; + break; + case 0x2e: /* fnsave mem */ + gen_helper_fsave(tcg_env, s->A0, + tcg_constant_i32(s->dflag - 1)); + update_fip = update_fdp = false; + break; + case 0x2f: /* fnstsw mem */ + gen_helper_fnstsw(s->tmp2_i32, tcg_env); + tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LEUW); + update_fip = update_fdp = false; + break; + case 0x3c: /* fbld */ + gen_helper_fbld_ST0(tcg_env, s->A0); + break; + case 0x3e: /* fbstp */ + gen_helper_fbst_ST0(tcg_env, s->A0); + gen_helper_fpop(tcg_env); + break; + case 0x3d: /* fildll */ + tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, + s->mem_index, MO_LEUQ); + gen_helper_fildll_ST0(tcg_env, s->tmp1_i64); + break; + case 0x3f: /* fistpll */ + gen_helper_fistll_ST0(s->tmp1_i64, tcg_env); + tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, + s->mem_index, MO_LEUQ); + gen_helper_fpop(tcg_env); + break; + default: + return false; + } + + if (update_fdp) { + int last_seg = s->override >= 0 ? s->override : a.def_seg; + + tcg_gen_ld_i32(s->tmp2_i32, tcg_env, + offsetof(CPUX86State, + segs[last_seg].selector)); + tcg_gen_st16_i32(s->tmp2_i32, tcg_env, + offsetof(CPUX86State, fpds)); + tcg_gen_st_tl(last_addr, tcg_env, + offsetof(CPUX86State, fpdp)); + } + } else { + /* register float ops */ + int opreg = rm; + + switch (op) { + case 0x08: /* fld sti */ + gen_helper_fpush(tcg_env); + gen_helper_fmov_ST0_STN(tcg_env, + tcg_constant_i32((opreg + 1) & 7)); + break; + case 0x09: /* fxchg sti */ + case 0x29: /* fxchg4 sti, undocumented op */ + case 0x39: /* fxchg7 sti, undocumented op */ + gen_helper_fxchg_ST0_STN(tcg_env, tcg_constant_i32(opreg)); + break; + case 0x0a: /* grp d9/2 */ + switch (rm) { + case 0: /* fnop */ + /* + * check exceptions (FreeBSD FPU probe) + * needs to be treated as I/O because of ferr_irq + */ + translator_io_start(&s->base); + gen_helper_fwait(tcg_env); + update_fip = false; + break; + default: + return false; + } + break; + case 0x0c: /* grp d9/4 */ + switch (rm) { + case 0: /* fchs */ + gen_helper_fchs_ST0(tcg_env); + break; + case 1: /* fabs */ + gen_helper_fabs_ST0(tcg_env); + break; + case 4: /* ftst */ + gen_helper_fldz_FT0(tcg_env); + gen_helper_fcom_ST0_FT0(tcg_env); + break; + case 5: /* fxam */ + gen_helper_fxam_ST0(tcg_env); + break; + default: + return false; + } + break; + case 0x0d: /* grp d9/5 */ + { + switch (rm) { + case 0: + gen_helper_fpush(tcg_env); + gen_helper_fld1_ST0(tcg_env); + break; + case 1: + gen_helper_fpush(tcg_env); + gen_helper_fldl2t_ST0(tcg_env); + break; + case 2: + gen_helper_fpush(tcg_env); + gen_helper_fldl2e_ST0(tcg_env); + break; + case 3: + gen_helper_fpush(tcg_env); + gen_helper_fldpi_ST0(tcg_env); + break; + case 4: + gen_helper_fpush(tcg_env); + gen_helper_fldlg2_ST0(tcg_env); + break; + case 5: + gen_helper_fpush(tcg_env); + gen_helper_fldln2_ST0(tcg_env); + break; + case 6: + gen_helper_fpush(tcg_env); + gen_helper_fldz_ST0(tcg_env); + break; + default: + return false; + } + } + break; + case 0x0e: /* grp d9/6 */ + switch (rm) { + case 0: /* f2xm1 */ + gen_helper_f2xm1(tcg_env); + break; + case 1: /* fyl2x */ + gen_helper_fyl2x(tcg_env); + break; + case 2: /* fptan */ + gen_helper_fptan(tcg_env); + break; + case 3: /* fpatan */ + gen_helper_fpatan(tcg_env); + break; + case 4: /* fxtract */ + gen_helper_fxtract(tcg_env); + break; + case 5: /* fprem1 */ + gen_helper_fprem1(tcg_env); + break; + case 6: /* fdecstp */ + gen_helper_fdecstp(tcg_env); + break; + default: + case 7: /* fincstp */ + gen_helper_fincstp(tcg_env); + break; + } + break; + case 0x0f: /* grp d9/7 */ + switch (rm) { + case 0: /* fprem */ + gen_helper_fprem(tcg_env); + break; + case 1: /* fyl2xp1 */ + gen_helper_fyl2xp1(tcg_env); + break; + case 2: /* fsqrt */ + gen_helper_fsqrt(tcg_env); + break; + case 3: /* fsincos */ + gen_helper_fsincos(tcg_env); + break; + case 5: /* fscale */ + gen_helper_fscale(tcg_env); + break; + case 4: /* frndint */ + gen_helper_frndint(tcg_env); + break; + case 6: /* fsin */ + gen_helper_fsin(tcg_env); + break; + default: + case 7: /* fcos */ + gen_helper_fcos(tcg_env); + break; + } + break; + case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */ + case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */ + case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */ + { + int op1; + + op1 = op & 7; + if (op >= 0x20) { + gen_helper_fp_arith_STN_ST0(op1, opreg); + if (op >= 0x30) { + gen_helper_fpop(tcg_env); + } + } else { + gen_helper_fmov_FT0_STN(tcg_env, + tcg_constant_i32(opreg)); + gen_helper_fp_arith_ST0_FT0(op1); + } + } + break; + case 0x02: /* fcom */ + case 0x22: /* fcom2, undocumented op */ + gen_helper_fmov_FT0_STN(tcg_env, tcg_constant_i32(opreg)); + gen_helper_fcom_ST0_FT0(tcg_env); + break; + case 0x03: /* fcomp */ + case 0x23: /* fcomp3, undocumented op */ + case 0x32: /* fcomp5, undocumented op */ + gen_helper_fmov_FT0_STN(tcg_env, tcg_constant_i32(opreg)); + gen_helper_fcom_ST0_FT0(tcg_env); + gen_helper_fpop(tcg_env); + break; + case 0x15: /* da/5 */ + switch (rm) { + case 1: /* fucompp */ + gen_helper_fmov_FT0_STN(tcg_env, tcg_constant_i32(1)); + gen_helper_fucom_ST0_FT0(tcg_env); + gen_helper_fpop(tcg_env); + gen_helper_fpop(tcg_env); + break; + default: + return false; + } + break; + case 0x1c: + switch (rm) { + case 0: /* feni (287 only, just do nop here) */ + break; + case 1: /* fdisi (287 only, just do nop here) */ + break; + case 2: /* fclex */ + gen_helper_fclex(tcg_env); + update_fip = false; + break; + case 3: /* fninit */ + gen_helper_fninit(tcg_env); + update_fip = false; + break; + case 4: /* fsetpm (287 only, just do nop here) */ + break; + default: + return false; + } + break; + case 0x1d: /* fucomi */ + if (!(s->cpuid_features & CPUID_CMOV)) { + goto illegal_op; + } + gen_update_cc_op(s); + gen_helper_fmov_FT0_STN(tcg_env, tcg_constant_i32(opreg)); + gen_helper_fucomi_ST0_FT0(tcg_env); + set_cc_op(s, CC_OP_EFLAGS); + break; + case 0x1e: /* fcomi */ + if (!(s->cpuid_features & CPUID_CMOV)) { + goto illegal_op; + } + gen_update_cc_op(s); + gen_helper_fmov_FT0_STN(tcg_env, tcg_constant_i32(opreg)); + gen_helper_fcomi_ST0_FT0(tcg_env); + set_cc_op(s, CC_OP_EFLAGS); + break; + case 0x28: /* ffree sti */ + gen_helper_ffree_STN(tcg_env, tcg_constant_i32(opreg)); + break; + case 0x2a: /* fst sti */ + gen_helper_fmov_STN_ST0(tcg_env, tcg_constant_i32(opreg)); + break; + case 0x2b: /* fstp sti */ + case 0x0b: /* fstp1 sti, undocumented op */ + case 0x3a: /* fstp8 sti, undocumented op */ + case 0x3b: /* fstp9 sti, undocumented op */ + gen_helper_fmov_STN_ST0(tcg_env, tcg_constant_i32(opreg)); + gen_helper_fpop(tcg_env); + break; + case 0x2c: /* fucom st(i) */ + gen_helper_fmov_FT0_STN(tcg_env, tcg_constant_i32(opreg)); + gen_helper_fucom_ST0_FT0(tcg_env); + break; + case 0x2d: /* fucomp st(i) */ + gen_helper_fmov_FT0_STN(tcg_env, tcg_constant_i32(opreg)); + gen_helper_fucom_ST0_FT0(tcg_env); + gen_helper_fpop(tcg_env); + break; + case 0x33: /* de/3 */ + switch (rm) { + case 1: /* fcompp */ + gen_helper_fmov_FT0_STN(tcg_env, tcg_constant_i32(1)); + gen_helper_fcom_ST0_FT0(tcg_env); + gen_helper_fpop(tcg_env); + gen_helper_fpop(tcg_env); + break; + default: + return false; + } + break; + case 0x38: /* ffreep sti, undocumented op */ + gen_helper_ffree_STN(tcg_env, tcg_constant_i32(opreg)); + gen_helper_fpop(tcg_env); + break; + case 0x3c: /* df/4 */ + switch (rm) { + case 0: + gen_helper_fnstsw(s->tmp2_i32, tcg_env); + tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32); + gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0); + break; + default: + return false; + } + break; + case 0x3d: /* fucomip */ + if (!(s->cpuid_features & CPUID_CMOV)) { + goto illegal_op; + } + gen_update_cc_op(s); + gen_helper_fmov_FT0_STN(tcg_env, tcg_constant_i32(opreg)); + gen_helper_fucomi_ST0_FT0(tcg_env); + gen_helper_fpop(tcg_env); + set_cc_op(s, CC_OP_EFLAGS); + break; + case 0x3e: /* fcomip */ + if (!(s->cpuid_features & CPUID_CMOV)) { + goto illegal_op; + } + gen_update_cc_op(s); + gen_helper_fmov_FT0_STN(tcg_env, tcg_constant_i32(opreg)); + gen_helper_fcomi_ST0_FT0(tcg_env); + gen_helper_fpop(tcg_env); + set_cc_op(s, CC_OP_EFLAGS); + break; + case 0x10 ... 0x13: /* fcmovxx */ + case 0x18 ... 0x1b: + { + int op1; + TCGLabel *l1; + static const uint8_t fcmov_cc[8] = { + (JCC_B << 1), + (JCC_Z << 1), + (JCC_BE << 1), + (JCC_P << 1), + }; + + if (!(s->cpuid_features & CPUID_CMOV)) { + goto illegal_op; + } + op1 = fcmov_cc[op & 3] | (((op >> 3) & 1) ^ 1); + l1 = gen_new_label(); + gen_jcc1_noeob(s, op1, l1); + gen_helper_fmov_ST0_STN(tcg_env, + tcg_constant_i32(opreg)); + gen_set_label(l1); + } + break; + default: + return false; + } + } + + if (update_fip) { + tcg_gen_ld_i32(s->tmp2_i32, tcg_env, + offsetof(CPUX86State, segs[R_CS].selector)); + tcg_gen_st16_i32(s->tmp2_i32, tcg_env, + offsetof(CPUX86State, fpcs)); + tcg_gen_st_tl(eip_cur_tl(s), + tcg_env, offsetof(CPUX86State, fpip)); + } + return true; + + illegal_op: + gen_illegal_opcode(s); + return true; +} + /* convert one instruction. s->base.is_jmp is set if the translation must be stopped. Return the next pc value */ static bool disas_insn(DisasContext *s, CPUState *cpu) @@ -2911,560 +3475,8 @@ static bool disas_insn(DisasContext *s, CPUState *cpu) /************************/ /* floats */ case 0xd8 ... 0xdf: - { - bool update_fip = true; - - if (s->flags & (HF_EM_MASK | HF_TS_MASK)) { - /* if CR0.EM or CR0.TS are set, generate an FPU exception */ - /* XXX: what to do if illegal op ? */ - gen_exception(s, EXCP07_PREX); - break; - } - modrm = x86_ldub_code(env, s); - mod = (modrm >> 6) & 3; - rm = modrm & 7; - op = ((b & 7) << 3) | ((modrm >> 3) & 7); - if (mod != 3) { - /* memory op */ - AddressParts a = gen_lea_modrm_0(env, s, modrm); - TCGv ea = gen_lea_modrm_1(s, a, false); - TCGv last_addr = tcg_temp_new(); - bool update_fdp = true; - - tcg_gen_mov_tl(last_addr, ea); - gen_lea_v_seg(s, s->aflag, ea, a.def_seg, s->override); - - switch (op) { - case 0x00 ... 0x07: /* fxxxs */ - case 0x10 ... 0x17: /* fixxxl */ - case 0x20 ... 0x27: /* fxxxl */ - case 0x30 ... 0x37: /* fixxx */ - { - int op1; - op1 = op & 7; - - switch (op >> 4) { - case 0: - tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LEUL); - gen_helper_flds_FT0(tcg_env, s->tmp2_i32); - break; - case 1: - tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LEUL); - gen_helper_fildl_FT0(tcg_env, s->tmp2_i32); - break; - case 2: - tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, - s->mem_index, MO_LEUQ); - gen_helper_fldl_FT0(tcg_env, s->tmp1_i64); - break; - case 3: - default: - tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LESW); - gen_helper_fildl_FT0(tcg_env, s->tmp2_i32); - break; - } - - gen_helper_fp_arith_ST0_FT0(op1); - if (op1 == 3) { - /* fcomp needs pop */ - gen_helper_fpop(tcg_env); - } - } - break; - case 0x08: /* flds */ - case 0x0a: /* fsts */ - case 0x0b: /* fstps */ - case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */ - case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */ - case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */ - switch (op & 7) { - case 0: - switch (op >> 4) { - case 0: - tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LEUL); - gen_helper_flds_ST0(tcg_env, s->tmp2_i32); - break; - case 1: - tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LEUL); - gen_helper_fildl_ST0(tcg_env, s->tmp2_i32); - break; - case 2: - tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, - s->mem_index, MO_LEUQ); - gen_helper_fldl_ST0(tcg_env, s->tmp1_i64); - break; - case 3: - default: - tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LESW); - gen_helper_fildl_ST0(tcg_env, s->tmp2_i32); - break; - } - break; - case 1: - /* XXX: the corresponding CPUID bit must be tested ! */ - switch (op >> 4) { - case 1: - gen_helper_fisttl_ST0(s->tmp2_i32, tcg_env); - tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LEUL); - break; - case 2: - gen_helper_fisttll_ST0(s->tmp1_i64, tcg_env); - tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, - s->mem_index, MO_LEUQ); - break; - case 3: - default: - gen_helper_fistt_ST0(s->tmp2_i32, tcg_env); - tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LEUW); - break; - } - gen_helper_fpop(tcg_env); - break; - default: - switch (op >> 4) { - case 0: - gen_helper_fsts_ST0(s->tmp2_i32, tcg_env); - tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LEUL); - break; - case 1: - gen_helper_fistl_ST0(s->tmp2_i32, tcg_env); - tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LEUL); - break; - case 2: - gen_helper_fstl_ST0(s->tmp1_i64, tcg_env); - tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, - s->mem_index, MO_LEUQ); - break; - case 3: - default: - gen_helper_fist_ST0(s->tmp2_i32, tcg_env); - tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LEUW); - break; - } - if ((op & 7) == 3) { - gen_helper_fpop(tcg_env); - } - break; - } - break; - case 0x0c: /* fldenv mem */ - gen_helper_fldenv(tcg_env, s->A0, - tcg_constant_i32(dflag - 1)); - update_fip = update_fdp = false; - break; - case 0x0d: /* fldcw mem */ - tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LEUW); - gen_helper_fldcw(tcg_env, s->tmp2_i32); - update_fip = update_fdp = false; - break; - case 0x0e: /* fnstenv mem */ - gen_helper_fstenv(tcg_env, s->A0, - tcg_constant_i32(dflag - 1)); - update_fip = update_fdp = false; - break; - case 0x0f: /* fnstcw mem */ - gen_helper_fnstcw(s->tmp2_i32, tcg_env); - tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LEUW); - update_fip = update_fdp = false; - break; - case 0x1d: /* fldt mem */ - gen_helper_fldt_ST0(tcg_env, s->A0); - break; - case 0x1f: /* fstpt mem */ - gen_helper_fstt_ST0(tcg_env, s->A0); - gen_helper_fpop(tcg_env); - break; - case 0x2c: /* frstor mem */ - gen_helper_frstor(tcg_env, s->A0, - tcg_constant_i32(dflag - 1)); - update_fip = update_fdp = false; - break; - case 0x2e: /* fnsave mem */ - gen_helper_fsave(tcg_env, s->A0, - tcg_constant_i32(dflag - 1)); - update_fip = update_fdp = false; - break; - case 0x2f: /* fnstsw mem */ - gen_helper_fnstsw(s->tmp2_i32, tcg_env); - tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LEUW); - update_fip = update_fdp = false; - break; - case 0x3c: /* fbld */ - gen_helper_fbld_ST0(tcg_env, s->A0); - break; - case 0x3e: /* fbstp */ - gen_helper_fbst_ST0(tcg_env, s->A0); - gen_helper_fpop(tcg_env); - break; - case 0x3d: /* fildll */ - tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, - s->mem_index, MO_LEUQ); - gen_helper_fildll_ST0(tcg_env, s->tmp1_i64); - break; - case 0x3f: /* fistpll */ - gen_helper_fistll_ST0(s->tmp1_i64, tcg_env); - tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, - s->mem_index, MO_LEUQ); - gen_helper_fpop(tcg_env); - break; - default: - goto unknown_op; - } - - if (update_fdp) { - int last_seg = s->override >= 0 ? s->override : a.def_seg; - - tcg_gen_ld_i32(s->tmp2_i32, tcg_env, - offsetof(CPUX86State, - segs[last_seg].selector)); - tcg_gen_st16_i32(s->tmp2_i32, tcg_env, - offsetof(CPUX86State, fpds)); - tcg_gen_st_tl(last_addr, tcg_env, - offsetof(CPUX86State, fpdp)); - } - } else { - /* register float ops */ - opreg = rm; - - switch (op) { - case 0x08: /* fld sti */ - gen_helper_fpush(tcg_env); - gen_helper_fmov_ST0_STN(tcg_env, - tcg_constant_i32((opreg + 1) & 7)); - break; - case 0x09: /* fxchg sti */ - case 0x29: /* fxchg4 sti, undocumented op */ - case 0x39: /* fxchg7 sti, undocumented op */ - gen_helper_fxchg_ST0_STN(tcg_env, tcg_constant_i32(opreg)); - break; - case 0x0a: /* grp d9/2 */ - switch (rm) { - case 0: /* fnop */ - /* - * check exceptions (FreeBSD FPU probe) - * needs to be treated as I/O because of ferr_irq - */ - translator_io_start(&s->base); - gen_helper_fwait(tcg_env); - update_fip = false; - break; - default: - goto unknown_op; - } - break; - case 0x0c: /* grp d9/4 */ - switch (rm) { - case 0: /* fchs */ - gen_helper_fchs_ST0(tcg_env); - break; - case 1: /* fabs */ - gen_helper_fabs_ST0(tcg_env); - break; - case 4: /* ftst */ - gen_helper_fldz_FT0(tcg_env); - gen_helper_fcom_ST0_FT0(tcg_env); - break; - case 5: /* fxam */ - gen_helper_fxam_ST0(tcg_env); - break; - default: - goto unknown_op; - } - break; - case 0x0d: /* grp d9/5 */ - { - switch (rm) { - case 0: - gen_helper_fpush(tcg_env); - gen_helper_fld1_ST0(tcg_env); - break; - case 1: - gen_helper_fpush(tcg_env); - gen_helper_fldl2t_ST0(tcg_env); - break; - case 2: - gen_helper_fpush(tcg_env); - gen_helper_fldl2e_ST0(tcg_env); - break; - case 3: - gen_helper_fpush(tcg_env); - gen_helper_fldpi_ST0(tcg_env); - break; - case 4: - gen_helper_fpush(tcg_env); - gen_helper_fldlg2_ST0(tcg_env); - break; - case 5: - gen_helper_fpush(tcg_env); - gen_helper_fldln2_ST0(tcg_env); - break; - case 6: - gen_helper_fpush(tcg_env); - gen_helper_fldz_ST0(tcg_env); - break; - default: - goto unknown_op; - } - } - break; - case 0x0e: /* grp d9/6 */ - switch (rm) { - case 0: /* f2xm1 */ - gen_helper_f2xm1(tcg_env); - break; - case 1: /* fyl2x */ - gen_helper_fyl2x(tcg_env); - break; - case 2: /* fptan */ - gen_helper_fptan(tcg_env); - break; - case 3: /* fpatan */ - gen_helper_fpatan(tcg_env); - break; - case 4: /* fxtract */ - gen_helper_fxtract(tcg_env); - break; - case 5: /* fprem1 */ - gen_helper_fprem1(tcg_env); - break; - case 6: /* fdecstp */ - gen_helper_fdecstp(tcg_env); - break; - default: - case 7: /* fincstp */ - gen_helper_fincstp(tcg_env); - break; - } - break; - case 0x0f: /* grp d9/7 */ - switch (rm) { - case 0: /* fprem */ - gen_helper_fprem(tcg_env); - break; - case 1: /* fyl2xp1 */ - gen_helper_fyl2xp1(tcg_env); - break; - case 2: /* fsqrt */ - gen_helper_fsqrt(tcg_env); - break; - case 3: /* fsincos */ - gen_helper_fsincos(tcg_env); - break; - case 5: /* fscale */ - gen_helper_fscale(tcg_env); - break; - case 4: /* frndint */ - gen_helper_frndint(tcg_env); - break; - case 6: /* fsin */ - gen_helper_fsin(tcg_env); - break; - default: - case 7: /* fcos */ - gen_helper_fcos(tcg_env); - break; - } - break; - case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */ - case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */ - case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */ - { - int op1; - - op1 = op & 7; - if (op >= 0x20) { - gen_helper_fp_arith_STN_ST0(op1, opreg); - if (op >= 0x30) { - gen_helper_fpop(tcg_env); - } - } else { - gen_helper_fmov_FT0_STN(tcg_env, - tcg_constant_i32(opreg)); - gen_helper_fp_arith_ST0_FT0(op1); - } - } - break; - case 0x02: /* fcom */ - case 0x22: /* fcom2, undocumented op */ - gen_helper_fmov_FT0_STN(tcg_env, tcg_constant_i32(opreg)); - gen_helper_fcom_ST0_FT0(tcg_env); - break; - case 0x03: /* fcomp */ - case 0x23: /* fcomp3, undocumented op */ - case 0x32: /* fcomp5, undocumented op */ - gen_helper_fmov_FT0_STN(tcg_env, tcg_constant_i32(opreg)); - gen_helper_fcom_ST0_FT0(tcg_env); - gen_helper_fpop(tcg_env); - break; - case 0x15: /* da/5 */ - switch (rm) { - case 1: /* fucompp */ - gen_helper_fmov_FT0_STN(tcg_env, tcg_constant_i32(1)); - gen_helper_fucom_ST0_FT0(tcg_env); - gen_helper_fpop(tcg_env); - gen_helper_fpop(tcg_env); - break; - default: - goto unknown_op; - } - break; - case 0x1c: - switch (rm) { - case 0: /* feni (287 only, just do nop here) */ - break; - case 1: /* fdisi (287 only, just do nop here) */ - break; - case 2: /* fclex */ - gen_helper_fclex(tcg_env); - update_fip = false; - break; - case 3: /* fninit */ - gen_helper_fninit(tcg_env); - update_fip = false; - break; - case 4: /* fsetpm (287 only, just do nop here) */ - break; - default: - goto unknown_op; - } - break; - case 0x1d: /* fucomi */ - if (!(s->cpuid_features & CPUID_CMOV)) { - goto illegal_op; - } - gen_update_cc_op(s); - gen_helper_fmov_FT0_STN(tcg_env, tcg_constant_i32(opreg)); - gen_helper_fucomi_ST0_FT0(tcg_env); - set_cc_op(s, CC_OP_EFLAGS); - break; - case 0x1e: /* fcomi */ - if (!(s->cpuid_features & CPUID_CMOV)) { - goto illegal_op; - } - gen_update_cc_op(s); - gen_helper_fmov_FT0_STN(tcg_env, tcg_constant_i32(opreg)); - gen_helper_fcomi_ST0_FT0(tcg_env); - set_cc_op(s, CC_OP_EFLAGS); - break; - case 0x28: /* ffree sti */ - gen_helper_ffree_STN(tcg_env, tcg_constant_i32(opreg)); - break; - case 0x2a: /* fst sti */ - gen_helper_fmov_STN_ST0(tcg_env, tcg_constant_i32(opreg)); - break; - case 0x2b: /* fstp sti */ - case 0x0b: /* fstp1 sti, undocumented op */ - case 0x3a: /* fstp8 sti, undocumented op */ - case 0x3b: /* fstp9 sti, undocumented op */ - gen_helper_fmov_STN_ST0(tcg_env, tcg_constant_i32(opreg)); - gen_helper_fpop(tcg_env); - break; - case 0x2c: /* fucom st(i) */ - gen_helper_fmov_FT0_STN(tcg_env, tcg_constant_i32(opreg)); - gen_helper_fucom_ST0_FT0(tcg_env); - break; - case 0x2d: /* fucomp st(i) */ - gen_helper_fmov_FT0_STN(tcg_env, tcg_constant_i32(opreg)); - gen_helper_fucom_ST0_FT0(tcg_env); - gen_helper_fpop(tcg_env); - break; - case 0x33: /* de/3 */ - switch (rm) { - case 1: /* fcompp */ - gen_helper_fmov_FT0_STN(tcg_env, tcg_constant_i32(1)); - gen_helper_fcom_ST0_FT0(tcg_env); - gen_helper_fpop(tcg_env); - gen_helper_fpop(tcg_env); - break; - default: - goto unknown_op; - } - break; - case 0x38: /* ffreep sti, undocumented op */ - gen_helper_ffree_STN(tcg_env, tcg_constant_i32(opreg)); - gen_helper_fpop(tcg_env); - break; - case 0x3c: /* df/4 */ - switch (rm) { - case 0: - gen_helper_fnstsw(s->tmp2_i32, tcg_env); - tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32); - gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0); - break; - default: - goto unknown_op; - } - break; - case 0x3d: /* fucomip */ - if (!(s->cpuid_features & CPUID_CMOV)) { - goto illegal_op; - } - gen_update_cc_op(s); - gen_helper_fmov_FT0_STN(tcg_env, tcg_constant_i32(opreg)); - gen_helper_fucomi_ST0_FT0(tcg_env); - gen_helper_fpop(tcg_env); - set_cc_op(s, CC_OP_EFLAGS); - break; - case 0x3e: /* fcomip */ - if (!(s->cpuid_features & CPUID_CMOV)) { - goto illegal_op; - } - gen_update_cc_op(s); - gen_helper_fmov_FT0_STN(tcg_env, tcg_constant_i32(opreg)); - gen_helper_fcomi_ST0_FT0(tcg_env); - gen_helper_fpop(tcg_env); - set_cc_op(s, CC_OP_EFLAGS); - break; - case 0x10 ... 0x13: /* fcmovxx */ - case 0x18 ... 0x1b: - { - int op1; - TCGLabel *l1; - static const uint8_t fcmov_cc[8] = { - (JCC_B << 1), - (JCC_Z << 1), - (JCC_BE << 1), - (JCC_P << 1), - }; - - if (!(s->cpuid_features & CPUID_CMOV)) { - goto illegal_op; - } - op1 = fcmov_cc[op & 3] | (((op >> 3) & 1) ^ 1); - l1 = gen_new_label(); - gen_jcc1_noeob(s, op1, l1); - gen_helper_fmov_ST0_STN(tcg_env, - tcg_constant_i32(opreg)); - gen_set_label(l1); - } - break; - default: - goto unknown_op; - } - } - - if (update_fip) { - tcg_gen_ld_i32(s->tmp2_i32, tcg_env, - offsetof(CPUX86State, segs[R_CS].selector)); - tcg_gen_st16_i32(s->tmp2_i32, tcg_env, - offsetof(CPUX86State, fpcs)); - tcg_gen_st_tl(eip_cur_tl(s), - tcg_env, offsetof(CPUX86State, fpip)); - } + if (!disas_insn_x87(s, cpu, b)) { + goto unknown_op; } break; From patchwork Tue Apr 9 16:43:22 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 13622965 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 6AC18C67861 for ; Tue, 9 Apr 2024 16:52:20 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ruEae-00010I-Cy; Tue, 09 Apr 2024 12:44:56 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ruEaU-0000kr-Ae for qemu-devel@nongnu.org; Tue, 09 Apr 2024 12:44:47 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ruEaC-000886-4Y for qemu-devel@nongnu.org; Tue, 09 Apr 2024 12:44:43 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1712681060; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=lhATD6WlEijmtwEnMyv0XkMsx8qShTRSUQW4zG6qxBM=; b=Zr4zpMnh872+MwUSERRvPqPGsC0w3Fb30da84eUXtweOj+LMGnww25XlG1ccDi9a3NWuF0 HZP83nhW0LrpXTMdD02zpAesDsAtT6m0mIErGRRLZ9pdVgKjSV8yJl0pK83NYJnCcgOsb/ wC/lJqhfwtdkBOz+dSFOjiQ/K6TcttY= Received: from mail-wm1-f71.google.com (mail-wm1-f71.google.com [209.85.128.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-1-vdSc8MoyPPiTu6VzEXpeuw-1; Tue, 09 Apr 2024 12:44:18 -0400 X-MC-Unique: vdSc8MoyPPiTu6VzEXpeuw-1 Received: by mail-wm1-f71.google.com with SMTP id 5b1f17b1804b1-4165339d3a5so13448755e9.3 for ; Tue, 09 Apr 2024 09:44:18 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712681056; x=1713285856; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=lhATD6WlEijmtwEnMyv0XkMsx8qShTRSUQW4zG6qxBM=; b=bmYD8pBvUqqIRw779Vuaiqoj/3QOXXmjWp9rSTyLowDoQaf/xiB69E+9eUVNJMgFHD 9qjtflpzBbrIDZll7wis4cs0MaRupSKz5qF2Pc1AscBwSCRNkaNboARZwOSqLu1asnaK b6vey9x4b/FQVchhVEm4WLGyqu7M8uGpLuIBfCL/OnjUXwOB3WDp2FO8mQ4EUO3sWtMj hFq9Pam9kBXMkdNG0o10tznh0tsryrmlEdDUrebRXrsI3Sh+b98kLd1sH3FPBXE7NDgm g1yOSXaX3FBuO0f6CoK+7yKe7e9UHZk4Jcx3y0k8rYMSUR8QL4GyC153ug3Gh7tw1pvI D1Ow== X-Gm-Message-State: AOJu0YzYacYDrb6Gzkr7xDb7V0ryUJJD5i6N35WeA4c//Tou5NPkrr3x VFWxNnyzmOBBpAoKp+o0iYoo36n094xb7rMNI9sz7hiKQyhksujWZLQ635kpXPOUf9q/0l1wupP rmJMCLYz2ftUMFDY3+ZEkCCPFPOH1BLs8/wvEPqDNiu1o1Bwa74CkzXBjv9yve7CoIV0ejD3mO3 l8bV/c8JqyvzAjoprhBUWhnNxxPwNK4b5igptS X-Received: by 2002:a05:600c:3509:b0:416:1d6d:dc6d with SMTP id h9-20020a05600c350900b004161d6ddc6dmr157760wmq.40.1712681056616; Tue, 09 Apr 2024 09:44:16 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHHczaWaxVv2jwUGnInMbOrW+Q+M+/+OQaMmF+AU7sLECPPfeznq05gsce+PzbaBRMZLeouFw== X-Received: by 2002:a05:600c:3509:b0:416:1d6d:dc6d with SMTP id h9-20020a05600c350900b004161d6ddc6dmr157752wmq.40.1712681056289; Tue, 09 Apr 2024 09:44:16 -0700 (PDT) Received: from avogadro.local ([151.95.152.232]) by smtp.gmail.com with ESMTPSA id j22-20020a05600c1c1600b004165315d885sm10744816wms.11.2024.04.09.09.44.15 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 09 Apr 2024 09:44:15 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Subject: [PATCH for-9.1 18/19] target/i386: split legacy decoder into a separate function Date: Tue, 9 Apr 2024 18:43:22 +0200 Message-ID: <20240409164323.776660-19-pbonzini@redhat.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240409164323.776660-1-pbonzini@redhat.com> References: <20240409164323.776660-1-pbonzini@redhat.com> MIME-Version: 1.0 Received-SPF: pass client-ip=170.10.129.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -37 X-Spam_score: -3.8 X-Spam_bar: --- X-Spam_report: (-3.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1.701, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, T_SPF_TEMPERROR=0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Split the bits that have some duplication with disas_insn_new, from those that should be the main topic of the conversion. This is the first step towards removing duplicate decoding of prefixes between disas_insn and disas_insn_new. Signed-off-by: Paolo Bonzini Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson --- target/i386/tcg/translate.c | 58 +++++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index e7f51685ed8..d3c863c5d1d 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -3119,15 +3119,15 @@ static bool disas_insn_x87(DisasContext *s, CPUState *cpu, int b) return true; } +static void disas_insn_old(DisasContext *s, CPUState *cpu, int b); + /* convert one instruction. s->base.is_jmp is set if the translation must be stopped. Return the next pc value */ static bool disas_insn(DisasContext *s, CPUState *cpu) { CPUX86State *env = cpu_env(cpu); int b, prefixes; - int shift; - MemOp ot, aflag, dflag; - int modrm, reg, rm, mod, op, opreg, val; + MemOp aflag, dflag; bool orig_cc_op_dirty = s->cc_op_dirty; CCOp orig_cc_op = s->cc_op; target_ulong orig_pc_save = s->pc_save; @@ -3273,6 +3273,38 @@ static bool disas_insn(DisasContext *s, CPUState *cpu) s->aflag = aflag; s->dflag = dflag; + switch (b) { + case 0 ... 0xd7: + case 0xe0 ... 0xff: + case 0x10e ... 0x117: + case 0x128 ... 0x12f: + case 0x138 ... 0x19f: + case 0x1a0 ... 0x1a1: + case 0x1a8 ... 0x1a9: + case 0x1af: + case 0x1b2: + case 0x1b4 ... 0x1b7: + case 0x1be ... 0x1bf: + case 0x1c2 ... 0x1c6: + case 0x1c8 ... 0x1ff: + disas_insn_new(s, cpu, b); + break; + default: + disas_insn_old(s, cpu, b); + break; + } + return true; +} + +static void disas_insn_old(DisasContext *s, CPUState *cpu, int b) +{ + CPUX86State *env = cpu_env(cpu); + int prefixes = s->prefix; + MemOp dflag = s->dflag; + int shift; + MemOp ot; + int modrm, reg, rm, mod, op, opreg, val; + /* now check op code */ switch (b) { /**************************/ @@ -4726,31 +4758,15 @@ static bool disas_insn(DisasContext *s, CPUState *cpu) set_cc_op(s, CC_OP_POPCNT); break; - case 0 ... 0xd7: - case 0xe0 ... 0xff: - case 0x10e ... 0x117: - case 0x128 ... 0x12f: - case 0x138 ... 0x19f: - case 0x1a0 ... 0x1a1: - case 0x1a8 ... 0x1a9: - case 0x1af: - case 0x1b2: - case 0x1b4 ... 0x1b7: - case 0x1be ... 0x1bf: - case 0x1c2 ... 0x1c6: - case 0x1c8 ... 0x1ff: - disas_insn_new(s, cpu, b); - break; default: goto unknown_op; } - return true; + return; illegal_op: gen_illegal_opcode(s); - return true; + return; unknown_op: gen_unknown_opcode(env, s); - return true; } void tcg_x86_init(void) From patchwork Tue Apr 9 16:43:23 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 13622967 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id EF0F0CD1297 for ; Tue, 9 Apr 2024 16:52:42 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ruEae-00010B-9R; Tue, 09 Apr 2024 12:44:56 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ruEaT-0000ko-6k for qemu-devel@nongnu.org; Tue, 09 Apr 2024 12:44:46 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ruEaB-00088c-3Z for qemu-devel@nongnu.org; Tue, 09 Apr 2024 12:44:40 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1712681063; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=euG8iZgCt7LNEIZrhHc+yJzDlLn47jvF8xmL5QEXTyg=; b=d+3l5ij18Tm1iWAwW2LkATbFySefkhmQ1DqlussxseZxYRUy1h7+a5DMS/QkBElMkx/rft rLVNcST0vyR7nQjsUPluhjSEFEc+uA0D8wdX9XeQn1XbN+sXEKPLLafgS7UBMoNydoeXS0 ZauphlHHbS7GPkdXwblmKsiXnl73thI= Received: from mail-lj1-f198.google.com (mail-lj1-f198.google.com [209.85.208.198]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-311-P9MUf3PUNoCrhRNt5CkMhQ-1; Tue, 09 Apr 2024 12:44:21 -0400 X-MC-Unique: P9MUf3PUNoCrhRNt5CkMhQ-1 Received: by mail-lj1-f198.google.com with SMTP id 38308e7fff4ca-2d87f5937fcso24940991fa.0 for ; Tue, 09 Apr 2024 09:44:21 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712681060; x=1713285860; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=euG8iZgCt7LNEIZrhHc+yJzDlLn47jvF8xmL5QEXTyg=; b=GXuYU5GQqREAmtEXKB4xykQNszx3517FRzNTTcxHfMDmK+D9ycBfeGzSTMnMNHkUWs gVC+LHpjUM9MhiPgkzZksp5xeTquoA+5y3ke0PrB5HL0qKdamgXPGiFhgP9198dQiV8d Sz8/KZc/AlXtNXxP5U7OU8BOUOCtVJf8pRTSrjSFc1x5WVVLHzFI9J1G6xuiD11FLa5e n5Vg95MmbX4HQZODXo1kKHnFs9Wad1JwCOmCKxsZUtyLSIyujorCqeuQl5w0CeST9q4o kS+xn/IT6fOze3p3haPaRyltv1oWsbsS1B2JSuR03CIf7qUs16Qs0YF92bA7tYpjhb8X BxLQ== X-Gm-Message-State: AOJu0YzEqmWOrqtpE2GPBNNbFoiSbCztW/kRc7bUtSCJ6tTNgBEd7BEg Vx+1m+eylMEYKIxyVpsdB9SWqdtdDZrQ0hun0ykelT552a+n78Hq95CcLnurklH0TZNdFvuWILL sbdzcqsHq6UhoJyr1m5wWiXIvCqFhvktTADT4Jg4x1uto+v8S2494dPZdyxrsOOVwi2/WTG+uEN 0a2jHlKkIoQXUuTGVeK1MmQZ73TI79I+y4GyFv X-Received: by 2002:a2e:86d4:0:b0:2d8:5ca5:6eb1 with SMTP id n20-20020a2e86d4000000b002d85ca56eb1mr261653ljj.37.1712681059843; Tue, 09 Apr 2024 09:44:19 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFPETi14/UQGIMtH7ORgDt9MjbiUsgCo5gjTveb8lEoOhYSan+fsbpX4Bap9OIBFkJXrdbcMg== X-Received: by 2002:a2e:86d4:0:b0:2d8:5ca5:6eb1 with SMTP id n20-20020a2e86d4000000b002d85ca56eb1mr261622ljj.37.1712681059085; Tue, 09 Apr 2024 09:44:19 -0700 (PDT) Received: from avogadro.local ([151.95.152.232]) by smtp.gmail.com with ESMTPSA id bi8-20020a05600c3d8800b00416b92dceaesm1252645wmb.11.2024.04.09.09.44.18 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 09 Apr 2024 09:44:18 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Subject: [PATCH for-9.1 19/19] target/i386: remove duplicate prefix decoding Date: Tue, 9 Apr 2024 18:43:23 +0200 Message-ID: <20240409164323.776660-20-pbonzini@redhat.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240409164323.776660-1-pbonzini@redhat.com> References: <20240409164323.776660-1-pbonzini@redhat.com> MIME-Version: 1.0 Received-SPF: pass client-ip=170.10.129.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -37 X-Spam_score: -3.8 X-Spam_bar: --- X-Spam_report: (-3.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1.701, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, T_SPF_TEMPERROR=0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Now that a bulk of opcodes go through the new decoder, it is sensible to do some cleanup. Go immediately through disas_insn_new and only jump back after parsing the prefixes. disas_insn() now only contains the three sigsetjmp cases, and they are more easily managed if they are inlined into i386_tr_translate_insn. Signed-off-by: Paolo Bonzini Reviewed-by: Richard Henderson --- target/i386/tcg/translate.c | 259 +++++++------------------------ target/i386/tcg/decode-new.c.inc | 60 +++++-- 2 files changed, 100 insertions(+), 219 deletions(-) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index d3c863c5d1d..93601abf994 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -2453,10 +2453,6 @@ static void gen_sty_env_A0(DisasContext *s, int offset, bool align) tcg_gen_qemu_st_i128(t, s->tmp0, mem_index, mop); } -#include "decode-new.h" -#include "emit.c.inc" -#include "decode-new.c.inc" - static void gen_cmpxchg8b(DisasContext *s, CPUX86State *env, int modrm) { TCGv_i64 cmp, val, old; @@ -3119,183 +3115,6 @@ static bool disas_insn_x87(DisasContext *s, CPUState *cpu, int b) return true; } -static void disas_insn_old(DisasContext *s, CPUState *cpu, int b); - -/* convert one instruction. s->base.is_jmp is set if the translation must - be stopped. Return the next pc value */ -static bool disas_insn(DisasContext *s, CPUState *cpu) -{ - CPUX86State *env = cpu_env(cpu); - int b, prefixes; - MemOp aflag, dflag; - bool orig_cc_op_dirty = s->cc_op_dirty; - CCOp orig_cc_op = s->cc_op; - target_ulong orig_pc_save = s->pc_save; - - s->pc = s->base.pc_next; - s->override = -1; - s->popl_esp_hack = 0; -#ifdef TARGET_X86_64 - s->rex_r = 0; - s->rex_x = 0; - s->rex_b = 0; -#endif - s->rip_offset = 0; /* for relative ip address */ - s->vex_l = 0; - s->vex_v = 0; - s->vex_w = false; - switch (sigsetjmp(s->jmpbuf, 0)) { - case 0: - break; - case 1: - gen_exception_gpf(s); - return true; - case 2: - /* Restore state that may affect the next instruction. */ - s->pc = s->base.pc_next; - /* - * TODO: These save/restore can be removed after the table-based - * decoder is complete; we will be decoding the insn completely - * before any code generation that might affect these variables. - */ - s->cc_op_dirty = orig_cc_op_dirty; - s->cc_op = orig_cc_op; - s->pc_save = orig_pc_save; - /* END TODO */ - s->base.num_insns--; - tcg_remove_ops_after(s->prev_insn_end); - s->base.insn_start = s->prev_insn_start; - s->base.is_jmp = DISAS_TOO_MANY; - return false; - default: - g_assert_not_reached(); - } - - prefixes = 0; - - next_byte: - s->prefix = prefixes; - b = x86_ldub_code(env, s); - /* Collect prefixes. */ - switch (b) { - case 0x0f: - b = x86_ldub_code(env, s) + 0x100; - break; - case 0xf3: - prefixes |= PREFIX_REPZ; - prefixes &= ~PREFIX_REPNZ; - goto next_byte; - case 0xf2: - prefixes |= PREFIX_REPNZ; - prefixes &= ~PREFIX_REPZ; - goto next_byte; - case 0xf0: - prefixes |= PREFIX_LOCK; - goto next_byte; - case 0x2e: - s->override = R_CS; - goto next_byte; - case 0x36: - s->override = R_SS; - goto next_byte; - case 0x3e: - s->override = R_DS; - goto next_byte; - case 0x26: - s->override = R_ES; - goto next_byte; - case 0x64: - s->override = R_FS; - goto next_byte; - case 0x65: - s->override = R_GS; - goto next_byte; - case 0x66: - prefixes |= PREFIX_DATA; - goto next_byte; - case 0x67: - prefixes |= PREFIX_ADR; - goto next_byte; -#ifdef TARGET_X86_64 - case 0x40 ... 0x4f: - if (CODE64(s)) { - /* REX prefix */ - prefixes |= PREFIX_REX; - s->vex_w = (b >> 3) & 1; - s->rex_r = (b & 0x4) << 1; - s->rex_x = (b & 0x2) << 2; - s->rex_b = (b & 0x1) << 3; - goto next_byte; - } - break; -#endif - case 0xc5: /* 2-byte VEX */ - case 0xc4: /* 3-byte VEX */ - if (CODE32(s) && !VM86(s)) { - int vex2 = x86_ldub_code(env, s); - s->pc--; /* rewind the advance_pc() x86_ldub_code() did */ - - if (!CODE64(s) && (vex2 & 0xc0) != 0xc0) { - /* 4.1.4.6: In 32-bit mode, bits [7:6] must be 11b, - otherwise the instruction is LES or LDS. */ - break; - } - disas_insn_new(s, cpu, b); - return s->pc; - } - break; - } - - /* Post-process prefixes. */ - if (CODE64(s)) { - /* In 64-bit mode, the default data size is 32-bit. Select 64-bit - data with rex_w, and 16-bit data with 0x66; rex_w takes precedence - over 0x66 if both are present. */ - dflag = (REX_W(s) ? MO_64 : prefixes & PREFIX_DATA ? MO_16 : MO_32); - /* In 64-bit mode, 0x67 selects 32-bit addressing. */ - aflag = (prefixes & PREFIX_ADR ? MO_32 : MO_64); - } else { - /* In 16/32-bit mode, 0x66 selects the opposite data size. */ - if (CODE32(s) ^ ((prefixes & PREFIX_DATA) != 0)) { - dflag = MO_32; - } else { - dflag = MO_16; - } - /* In 16/32-bit mode, 0x67 selects the opposite addressing. */ - if (CODE32(s) ^ ((prefixes & PREFIX_ADR) != 0)) { - aflag = MO_32; - } else { - aflag = MO_16; - } - } - - s->prefix = prefixes; - s->aflag = aflag; - s->dflag = dflag; - - switch (b) { - case 0 ... 0xd7: - case 0xe0 ... 0xff: - case 0x10e ... 0x117: - case 0x128 ... 0x12f: - case 0x138 ... 0x19f: - case 0x1a0 ... 0x1a1: - case 0x1a8 ... 0x1a9: - case 0x1af: - case 0x1b2: - case 0x1b4 ... 0x1b7: - case 0x1be ... 0x1bf: - case 0x1c2 ... 0x1c6: - case 0x1c8 ... 0x1ff: - disas_insn_new(s, cpu, b); - break; - default: - disas_insn_old(s, cpu, b); - break; - } - return true; -} - static void disas_insn_old(DisasContext *s, CPUState *cpu, int b) { CPUX86State *env = cpu_env(cpu); @@ -3504,14 +3323,6 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b) } break; - /************************/ - /* floats */ - case 0xd8 ... 0xdf: - if (!disas_insn_x87(s, cpu, b)) { - goto unknown_op; - } - break; - /************************/ /* bit operations */ case 0x1ba: /* bt/bts/btr/btc Gv, im */ @@ -4759,7 +4570,7 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b) set_cc_op(s, CC_OP_POPCNT); break; default: - goto unknown_op; + g_assert_not_reached(); } return; illegal_op: @@ -4769,6 +4580,10 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b) gen_unknown_opcode(env, s); } +#include "decode-new.h" +#include "emit.c.inc" +#include "decode-new.c.inc" + void tcg_x86_init(void) { static const char reg_names[CPU_NB_REGS][4] = { @@ -4890,7 +4705,6 @@ static void i386_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu) dc->cc_op = CC_OP_DYNAMIC; dc->cc_op_dirty = false; - dc->popl_esp_hack = 0; /* select memory access functions */ dc->mem_index = cpu_mmu_index(cpu, false); dc->cpuid_features = env->features[FEAT_1_EDX]; @@ -4942,6 +4756,9 @@ static void i386_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu) static void i386_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) { DisasContext *dc = container_of(dcbase, DisasContext, base); + bool orig_cc_op_dirty = dc->cc_op_dirty; + CCOp orig_cc_op = dc->cc_op; + target_ulong orig_pc_save = dc->pc_save; #ifdef TARGET_VSYSCALL_PAGE /* @@ -4954,23 +4771,51 @@ static void i386_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) } #endif - if (disas_insn(dc, cpu)) { - target_ulong pc_next = dc->pc; - dc->base.pc_next = pc_next; + switch (sigsetjmp(dc->jmpbuf, 0)) { + case 0: + disas_insn(dc, cpu); + break; + case 1: + gen_exception_gpf(dc); + break; + case 2: + /* Restore state that may affect the next instruction. */ + dc->pc = dc->base.pc_next; + /* + * TODO: These save/restore can be removed after the table-based + * decoder is complete; we will be decoding the insn completely + * before any code generation that might affect these variables. + */ + dc->cc_op_dirty = orig_cc_op_dirty; + dc->cc_op = orig_cc_op; + dc->pc_save = orig_pc_save; + /* END TODO */ + dc->base.num_insns--; + tcg_remove_ops_after(dc->prev_insn_end); + dc->base.insn_start = dc->prev_insn_start; + dc->base.is_jmp = DISAS_TOO_MANY; + return; + default: + g_assert_not_reached(); + } - if (dc->base.is_jmp == DISAS_NEXT) { - if (dc->flags & (HF_TF_MASK | HF_INHIBIT_IRQ_MASK)) { - /* - * If single step mode, we generate only one instruction and - * generate an exception. - * If irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear - * the flag and abort the translation to give the irqs a - * chance to happen. - */ - dc->base.is_jmp = DISAS_EOB_NEXT; - } else if (!is_same_page(&dc->base, pc_next)) { - dc->base.is_jmp = DISAS_TOO_MANY; - } + /* + * Instruction decoding completed (possibly with #GP if the + * 15-byte boundary was exceeded). + */ + dc->base.pc_next = dc->pc; + if (dc->base.is_jmp == DISAS_NEXT) { + if (dc->flags & (HF_TF_MASK | HF_INHIBIT_IRQ_MASK)) { + /* + * If single step mode, we generate only one instruction and + * generate an exception. + * If irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear + * the flag and abort the translation to give the irqs a + * chance to happen. + */ + dc->base.is_jmp = DISAS_EOB_NEXT; + } else if (!is_same_page(&dc->base, dc->base.pc_next)) { + dc->base.is_jmp = DISAS_TOO_MANY; } } } diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc index 3fc3f6b7d29..74790724e3c 100644 --- a/target/i386/tcg/decode-new.c.inc +++ b/target/i386/tcg/decode-new.c.inc @@ -2214,22 +2214,31 @@ illegal: * Convert one instruction. s->base.is_jmp is set if the translation must * be stopped. */ -static void disas_insn_new(DisasContext *s, CPUState *cpu, int b) +static void disas_insn(DisasContext *s, CPUState *cpu) { CPUX86State *env = cpu_env(cpu); - bool first = true; X86DecodedInsn decode; X86DecodeFunc decode_func = decode_root; - uint8_t cc_live; + uint8_t cc_live, b; + s->pc = s->base.pc_next; + s->override = -1; + s->popl_esp_hack = 0; +#ifdef TARGET_X86_64 + s->rex_r = 0; + s->rex_x = 0; + s->rex_b = 0; +#endif + s->rip_offset = 0; /* for relative ip address */ + s->vex_l = 0; + s->vex_v = 0; + s->vex_w = false; s->has_modrm = false; + s->prefix = 0; next_byte: - if (first) { - first = false; - } else { - b = x86_ldub_code(env, s); - } + b = x86_ldub_code(env, s); + /* Collect prefixes. */ switch (b) { case 0xf3: @@ -2341,10 +2350,6 @@ static void disas_insn_new(DisasContext *s, CPUState *cpu, int b) } break; default: - if (b >= 0x100) { - b -= 0x100; - decode_func = do_decode_0F; - } break; } @@ -2373,6 +2378,37 @@ static void disas_insn_new(DisasContext *s, CPUState *cpu, int b) } } + /* Go back to old decoder for unconverted opcodes. */ + if (!(s->prefix & PREFIX_VEX)) { + if ((b & ~7) == 0xd8) { + if (!disas_insn_x87(s, cpu, b)) { + goto unknown_op; + } + return; + } + + if (b == 0x0f) { + b = x86_ldub_code(env, s); + switch (b) { + case 0x00 ... 0x0d: /* mostly privileged instructions */ + case 0x18 ... 0x27: /* prefetch, MPX, mov from/to CR and DR */ + case 0x30 ... 0x37: /* more privileged instructions */ + case 0xa2 ... 0xa7: /* CPUID, BT, SHLD */ + case 0xaa ... 0xae: /* RSM, SHRD, grp15 */ + case 0xb0 ... 0xb1: /* cmpxchg */ + case 0xb3: /* btr */ + case 0xb8 ... 0xbd: /* integer ops */ + case 0xc0 ... 0xc1: /* xadd */ + case 0xc7: /* grp9 */ + disas_insn_old(s, cpu, b + 0x100); + return; + default: + decode_func = do_decode_0F; + break; + } + } + } + memset(&decode, 0, sizeof(decode)); decode.cc_op = -1; decode.b = b;