From nobody Mon Apr 29 13:24:59 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1617117299; cv=none; d=zohomail.com; s=zohoarc; b=aopZ3v/HCcqT60MJtl8YyGH+WcbGhHHYTeBSZC5+X/q5MlP32PjZbWV1oq2iM9cvWNHQvZ/gmn6eoem28CHNOFA4gWStfsSkyJxD32CI3fVpHcCIjtebPGSy3avmOSwbe1WiGuGXYw+SS9yR529BhvOo06a2oGZvmr0sbfPbSjI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1617117299; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=2RwTHTorS670vO4eCktAe3M0cB7xAsEMv6yPznJKvhs=; b=n68WOZyU8Za0wuo3JDWUdphjlNtwDSUleAAM37aNy9jKk3jrW9hh8Lbf1lBgPXva0ntAZo2q3WGzJ2PCKtrlwbC2qn1BG2EJxZ5DzHc2SOoGfbR+8XjGeiT8C8+cnNKaEUu77mzQGc//gfar0Wi3NiYjbfzrrfHkqBaZ0NaOePE= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1617117299740372.11905492012477; Tue, 30 Mar 2021 08:14:59 -0700 (PDT) Received: from localhost ([::1]:54790 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lRFXL-0004x0-0P for importer@patchew.org; Tue, 30 Mar 2021 10:40:07 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:38398) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lRFVc-000301-Ny for qemu-devel@nongnu.org; Tue, 30 Mar 2021 10:38:20 -0400 Received: from rev.ng ([5.9.113.41]:39183) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lRFVa-0004v8-FK for qemu-devel@nongnu.org; Tue, 30 Mar 2021 10:38:20 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=rev.ng; s=dkim; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=2RwTHTorS670vO4eCktAe3M0cB7xAsEMv6yPznJKvhs=; b=VV7zYk2fBwmAelF5Zeu75J0Nzn ZwZ5Am8ts6Sx9cC2j/tC92eNVqYr3yua7pchbZB9pYFB4uV7f1mSOtuG9sspcktztsorqNv16dT1t OeonK+qddbsqNP3ezr4gxFBGi+kcpoEoQwv32Frz7MDNIyORaQsfU7Em+bQf3Lv2nHrY=; To: qemu-devel@nongnu.org Cc: tsimpson@quicinc.com, bcain@quicinc.com, babush@rev.ng, nizzo@rev.ng, philmd@redhat.com, richard.henderson@linaro.org, Alessandro Di Federico Subject: [PATCH v3 01/12] tcg: expose TCGCond manipulation routines Date: Tue, 30 Mar 2021 16:37:39 +0200 Message-Id: <20210330143750.3037824-2-ale.qemu@rev.ng> In-Reply-To: <20210330143750.3037824-1-ale.qemu@rev.ng> References: <20210330143750.3037824-1-ale.qemu@rev.ng> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=5.9.113.41; envelope-from=ale@rev.ng; helo=rev.ng X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_PASS=-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.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Reply-to: Alessandro Di Federico From: Alessandro Di Federico via X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" From: Alessandro Di Federico This commit moves into a separate file routines used to manipulate TCGCond. These will be employed by the idef-parser. Signed-off-by: Alessandro Di Federico Signed-off-by: Paolo Montesel --- include/tcg/tcg-cond.h | 101 +++++++++++++++++++++++++++++++++++++++++ include/tcg/tcg.h | 70 +--------------------------- 2 files changed, 102 insertions(+), 69 deletions(-) create mode 100644 include/tcg/tcg-cond.h diff --git a/include/tcg/tcg-cond.h b/include/tcg/tcg-cond.h new file mode 100644 index 0000000000..2a38a386d4 --- /dev/null +++ b/include/tcg/tcg-cond.h @@ -0,0 +1,101 @@ +/* + * Tiny Code Generator for QEMU + * + * Copyright (c) 2008 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a= copy + * of this software and associated documentation files (the "Software"), t= o deal + * in the Software without restriction, including without limitation the r= ights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or se= ll + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included= in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS= OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OT= HER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING= FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS = IN + * THE SOFTWARE. + */ + +#ifndef TCG_COND_H +#define TCG_COND_H + +/* + * Conditions. Note that these are laid out for easy manipulation by + * the functions below: + * bit 0 is used for inverting; + * bit 1 is signed, + * bit 2 is unsigned, + * bit 3 is used with bit 0 for swapping signed/unsigned. + */ +typedef enum { + /* non-signed */ + TCG_COND_NEVER =3D 0 | 0 | 0 | 0, + TCG_COND_ALWAYS =3D 0 | 0 | 0 | 1, + TCG_COND_EQ =3D 8 | 0 | 0 | 0, + TCG_COND_NE =3D 8 | 0 | 0 | 1, + /* signed */ + TCG_COND_LT =3D 0 | 0 | 2 | 0, + TCG_COND_GE =3D 0 | 0 | 2 | 1, + TCG_COND_LE =3D 8 | 0 | 2 | 0, + TCG_COND_GT =3D 8 | 0 | 2 | 1, + /* unsigned */ + TCG_COND_LTU =3D 0 | 4 | 0 | 0, + TCG_COND_GEU =3D 0 | 4 | 0 | 1, + TCG_COND_LEU =3D 8 | 4 | 0 | 0, + TCG_COND_GTU =3D 8 | 4 | 0 | 1, +} TCGCond; + +/* Invert the sense of the comparison. */ +static inline TCGCond tcg_invert_cond(TCGCond c) +{ + return (TCGCond)(c ^ 1); +} + +/* Swap the operands in a comparison. */ +static inline TCGCond tcg_swap_cond(TCGCond c) +{ + return c & 6 ? (TCGCond)(c ^ 9) : c; +} + +/* Create an "unsigned" version of a "signed" comparison. */ +static inline TCGCond tcg_unsigned_cond(TCGCond c) +{ + return c & 2 ? (TCGCond)(c ^ 6) : c; +} + +/* Create a "signed" version of an "unsigned" comparison. */ +static inline TCGCond tcg_signed_cond(TCGCond c) +{ + return c & 4 ? (TCGCond)(c ^ 6) : c; +} + +/* Must a comparison be considered unsigned? */ +static inline bool is_unsigned_cond(TCGCond c) +{ + return (c & 4) !=3D 0; +} + +/* + * Create a "high" version of a double-word comparison. + * This removes equality from a LTE or GTE comparison. + */ +static inline TCGCond tcg_high_cond(TCGCond c) +{ + switch (c) { + case TCG_COND_GE: + case TCG_COND_LE: + case TCG_COND_GEU: + case TCG_COND_LEU: + return (TCGCond)(c ^ 8); + default: + return c; + } +} + +#endif /* TCG_COND_H */ diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h index 0f0695e90d..3dc468ebd8 100644 --- a/include/tcg/tcg.h +++ b/include/tcg/tcg.h @@ -34,6 +34,7 @@ #include "tcg/tcg-mo.h" #include "tcg-target.h" #include "qemu/int128.h" +#include "tcg/tcg-cond.h" =20 /* XXX: make safe guess about sizes */ #define MAX_OP_PER_INSTR 266 @@ -407,75 +408,6 @@ typedef TCGv_ptr TCGv_env; /* Used to align parameters. See the comment before tcgv_i32_temp. */ #define TCG_CALL_DUMMY_ARG ((TCGArg)0) =20 -/* Conditions. Note that these are laid out for easy manipulation by - the functions below: - bit 0 is used for inverting; - bit 1 is signed, - bit 2 is unsigned, - bit 3 is used with bit 0 for swapping signed/unsigned. */ -typedef enum { - /* non-signed */ - TCG_COND_NEVER =3D 0 | 0 | 0 | 0, - TCG_COND_ALWAYS =3D 0 | 0 | 0 | 1, - TCG_COND_EQ =3D 8 | 0 | 0 | 0, - TCG_COND_NE =3D 8 | 0 | 0 | 1, - /* signed */ - TCG_COND_LT =3D 0 | 0 | 2 | 0, - TCG_COND_GE =3D 0 | 0 | 2 | 1, - TCG_COND_LE =3D 8 | 0 | 2 | 0, - TCG_COND_GT =3D 8 | 0 | 2 | 1, - /* unsigned */ - TCG_COND_LTU =3D 0 | 4 | 0 | 0, - TCG_COND_GEU =3D 0 | 4 | 0 | 1, - TCG_COND_LEU =3D 8 | 4 | 0 | 0, - TCG_COND_GTU =3D 8 | 4 | 0 | 1, -} TCGCond; - -/* Invert the sense of the comparison. */ -static inline TCGCond tcg_invert_cond(TCGCond c) -{ - return (TCGCond)(c ^ 1); -} - -/* Swap the operands in a comparison. */ -static inline TCGCond tcg_swap_cond(TCGCond c) -{ - return c & 6 ? (TCGCond)(c ^ 9) : c; -} - -/* Create an "unsigned" version of a "signed" comparison. */ -static inline TCGCond tcg_unsigned_cond(TCGCond c) -{ - return c & 2 ? (TCGCond)(c ^ 6) : c; -} - -/* Create a "signed" version of an "unsigned" comparison. */ -static inline TCGCond tcg_signed_cond(TCGCond c) -{ - return c & 4 ? (TCGCond)(c ^ 6) : c; -} - -/* Must a comparison be considered unsigned? */ -static inline bool is_unsigned_cond(TCGCond c) -{ - return (c & 4) !=3D 0; -} - -/* Create a "high" version of a double-word comparison. - This removes equality from a LTE or GTE comparison. */ -static inline TCGCond tcg_high_cond(TCGCond c) -{ - switch (c) { - case TCG_COND_GE: - case TCG_COND_LE: - case TCG_COND_GEU: - case TCG_COND_LEU: - return (TCGCond)(c ^ 8); - default: - return c; - } -} - typedef enum TCGTempVal { TEMP_VAL_DEAD, TEMP_VAL_REG, --=20 2.31.1 From nobody Mon Apr 29 13:24:59 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1617116139; cv=none; d=zohomail.com; s=zohoarc; b=OxKXE1UMENjylz2kzYktROKK3pWdr4N1Ta0o0nVB9GDzvimRrhHnPxRBj1qkHwpkeYs0xK+3a/GHlKkTzFrwAyn1nkimEGu9cI8byRBe7lOoTQKWP3qqjbqudsXOfhKnqRiw2YLNo5ewcAA5iX9CJt2RJu50QQ4pPBL3t0Ch1xg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1617116139; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=9Rmu20NMWFw1ZiJmJP9RMJRKCvAPOYy9SSJV4pKvtAM=; b=Sf/maW4lf+C2RSmAH5DnUubXLj++osbURQOodjy48x4dQqEBcnbS8ecE3wiIcJPLhp+uLW+Zom/iZ73wA1nwP4wdvh/8C3Ffu470xJFKarIh+IWrX06HHfYg9PJ5VZZVW1hmCF+5PDqYTsNPLS2efu2Pap72WxarzHpCsi/3e5U= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1617116139309427.58975369934376; Tue, 30 Mar 2021 07:55:39 -0700 (PDT) Received: from localhost ([::1]:43462 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lRFcy-0003XY-Rq for importer@patchew.org; Tue, 30 Mar 2021 10:45:56 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:38420) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lRFVd-00032Q-N6 for qemu-devel@nongnu.org; Tue, 30 Mar 2021 10:38:21 -0400 Received: from rev.ng ([5.9.113.41]:45577) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lRFVa-0004vi-FV for qemu-devel@nongnu.org; Tue, 30 Mar 2021 10:38:21 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=rev.ng; s=dkim; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=9Rmu20NMWFw1ZiJmJP9RMJRKCvAPOYy9SSJV4pKvtAM=; b=AjnooJ/gyr6KJEYl98dNLwYezk 11cn4yGAhp28VI2Fcbtgjr9Ohz4FlKNTS7OhMfuAQVAgfNMI3hjyuiccH+jacZ7XE4VlsJO7eSAno 5XnESt+DPrdd3BzaEU0FTl3GLg0eCVJM/6jBTmKTQCQ6vLbCCRtLgmUPsRtSL5WQVXjQ=; To: qemu-devel@nongnu.org Cc: tsimpson@quicinc.com, bcain@quicinc.com, babush@rev.ng, nizzo@rev.ng, philmd@redhat.com, richard.henderson@linaro.org, Alessandro Di Federico Subject: [PATCH v3 02/12] target/hexagon: update MAINTAINERS for idef-parser Date: Tue, 30 Mar 2021 16:37:40 +0200 Message-Id: <20210330143750.3037824-3-ale.qemu@rev.ng> In-Reply-To: <20210330143750.3037824-1-ale.qemu@rev.ng> References: <20210330143750.3037824-1-ale.qemu@rev.ng> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=5.9.113.41; envelope-from=ale@rev.ng; helo=rev.ng X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_PASS=-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.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Reply-to: Alessandro Di Federico From: Alessandro Di Federico via X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" From: Alessandro Di Federico Signed-off-by: Alessandro Di Federico --- MAINTAINERS | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 554be84b32..13de7ecc36 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -194,11 +194,19 @@ Hexagon TCG CPUs M: Taylor Simpson S: Supported F: target/hexagon/ +X: target/hexagon/idef-parser/ +X: target/hexagon/gen_idef_parser_funcs.py F: linux-user/hexagon/ F: tests/tcg/hexagon/ F: disas/hexagon.c F: default-configs/targets/hexagon-linux-user.mak =20 +Hexagon idef-parser +M: Alessandro Di Federico +S: Supported +F: target/hexagon/idef-parser/ +F: target/hexagon/gen_idef_parser_funcs.py + HPPA (PA-RISC) TCG CPUs M: Richard Henderson S: Maintained --=20 2.31.1 From nobody Mon Apr 29 13:24:59 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1617117312; cv=none; d=zohomail.com; s=zohoarc; b=Nflb1jqCqahr2bCnUBL+ozB+PmkWnZu7nRHi/Mli0X1mmEJPYSH9VLDAOlgszt+EWQpeeGYSfyKWgZXXEANmV7jX/m9/P+ld9IzemtfIp0durqukioYE+AHzRWg8hm19TB9JR9n2TuyX1B0r8I5g6CBJ+u5j5/7RRrMPsQOOtiM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1617117312; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=nnMa6nyW3qh00VjA+XvsAuyxMfPHoTfD0lPP+OlMkB0=; b=d4UIdQS9h3r1G+04fMDL9zUcY4JyV4JPb2Kae5O7rHbBrA26SUZHbdsvnOvIBz8pWtuTY/3sutSi1IdiqC+IDsUpnf8uy8bYDLXqJG5HdTCzQJWIcFb+hRpNMPyHtKu7IW81EhFXioXbdXVaTldRIDNAREJPJ1IPbaA4fx5HipQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1617117312526352.8380970973262; Tue, 30 Mar 2021 08:15:12 -0700 (PDT) Received: from localhost ([::1]:34810 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lRFaQ-0008Qc-9L for importer@patchew.org; Tue, 30 Mar 2021 10:43:18 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:38476) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lRFVj-00036H-1J for qemu-devel@nongnu.org; Tue, 30 Mar 2021 10:38:27 -0400 Received: from rev.ng ([5.9.113.41]:56795) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lRFVa-0004wB-FU for qemu-devel@nongnu.org; Tue, 30 Mar 2021 10:38:26 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=rev.ng; s=dkim; h=Content-Transfer-Encoding:Content-Type:MIME-Version:References: In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=nnMa6nyW3qh00VjA+XvsAuyxMfPHoTfD0lPP+OlMkB0=; b=b2qeSHNnhgvv7wG/ZRpbXvF7CI v1y+GP41xGL/41PZd69TXNNSWhLtraEiWBhbdv6b/fenY7cyL9dvTaLH1YTi/oGDpKQci4DBIXYQr 2jp+0TLozIFkkj7Ey1VK5NGOnFfBlKGHFN+xI/vOVerMAUSX65ldbvfdhWfQSyhqDW9A=; To: qemu-devel@nongnu.org Cc: tsimpson@quicinc.com, bcain@quicinc.com, babush@rev.ng, nizzo@rev.ng, philmd@redhat.com, richard.henderson@linaro.org, Alessandro Di Federico Subject: [PATCH v3 03/12] target/hexagon: import README for idef-parser Date: Tue, 30 Mar 2021 16:37:41 +0200 Message-Id: <20210330143750.3037824-4-ale.qemu@rev.ng> In-Reply-To: <20210330143750.3037824-1-ale.qemu@rev.ng> References: <20210330143750.3037824-1-ale.qemu@rev.ng> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=5.9.113.41; envelope-from=ale@rev.ng; helo=rev.ng X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_PASS=-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.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Reply-to: Alessandro Di Federico From: Alessandro Di Federico via X-ZohoMail-DKIM: fail (Header signature does not verify) From: Alessandro Di Federico Signed-off-by: Alessandro Di Federico --- target/hexagon/README | 5 + target/hexagon/idef-parser/README.rst | 447 ++++++++++++++++++++++++++ 2 files changed, 452 insertions(+) create mode 100644 target/hexagon/idef-parser/README.rst diff --git a/target/hexagon/README b/target/hexagon/README index b0b2435070..2f2814380c 100644 --- a/target/hexagon/README +++ b/target/hexagon/README @@ -23,6 +23,10 @@ Hexagon-specific code are encode*.def Encoding patterns for each instruction iclass.def Instruction class definitions used to dete= rmine legal VLIW slots for each instruction + qemu/target/hexagon/idef-parser + Parser that, given the high-level definitions of an instruction, + produces a C function generating equivalent tiny code instructions. + See README.rst. qemu/linux-user/hexagon Helpers for loading the ELF file and making Linux system calls, signals, etc @@ -43,6 +47,7 @@ header files in /target/hexagon gen_tcg_funcs.py -> tcg_funcs_generated.c.inc gen_tcg_func_table.py -> tcg_func_table_generated.c.inc gen_helper_funcs.py -> helper_funcs_generated.c.inc + gen_idef_parser_funcs.py -> idef_parser_input.h =20 Qemu helper functions have 3 parts DEF_HELPER declaration indicates the signature of the helper diff --git a/target/hexagon/idef-parser/README.rst b/target/hexagon/idef-pa= rser/README.rst new file mode 100644 index 0000000000..f4cb416e8b --- /dev/null +++ b/target/hexagon/idef-parser/README.rst @@ -0,0 +1,447 @@ +Hexagon ISA instruction definitions to tinycode generator compiler +------------------------------------------------------------------ + +idef-parser is a small compiler able to translate the Hexagon ISA descript= ion +language into tinycode generator code, that can be easily integrated into = QEMU. + +Compilation Example +------------------- + +To better understand the scope of the idef-parser, we'll explore an applic= ative +example. Let's start by one of the simplest Hexagon instruction: the ``add= ``. + +The ISA description language represents the ``add`` instruction as +follows: + +.. code:: c + + A2_add(RdV, in RsV, in RtV) { + { RdV=3DRsV+RtV;} + } + +idef-parser will compile the above code into the following code: + +.. code:: c + + /* A2_add */ + void emit_A2_add(DisasContext *ctx, Insn *insn, Packet *pkt, TCGv_i32 R= dV, + TCGv_i32 RsV, TCGv_i32 RtV) + /* { RdV=3DRsV+RtV;} */ + { + tcg_gen_movi_i32(RdV, 0); + TCGv_i32 tmp_0 =3D tcg_temp_new_i32(); + tcg_gen_add_i32(tmp_0, RsV, RtV); + tcg_gen_mov_i32(RdV, tmp_0); + tcg_temp_free_i32(tmp_0); + } + +The output of the compilation process will be a function, containing the +tinycode generator code, implementing the correct semantics. That function= will +not access any global variable, because all the accessed data structures w= ill be +passed explicitly as function parameters. Among the passed parameters we w= ill +have TCGv (tinycode variables) representing the input and output registers= of +the architecture, integers representing the immediates that come from the = code, +and other data structures which hold information about the disassemblation +context (``DisasContext`` struct). + +Let's begin by describing the input code. The ``add`` instruction is assoc= iated +with a unique identifier, in this case ``A2_add``, which allows to disting= uish +variants of the same instruction, and expresses the class to which the +instruction belongs, in this case ``A2`` corresponds to the Hexagon +``ALU32/ALU`` instruction subclass. + +After the instruction identifier, we have a series of parameters that repr= esents +TCG variables that will be passed to the generated function. Parameters ma= rked +with ``in`` are already initialized, while the others are output parameter= s. + +We will leverage this information to infer several information: + +- Fill in the output function signature with the correct TCGv registers +- Fill in the output function signature with the immediate integers +- Keep track of which registers, among the declared one, have been + initialized + +Let's now observe the actual instruction description code, in this case: + +.. code:: c + + { RdV=3DRsV+RtV;} + +This code is composed by a subset of the C syntax, and is the result of the +application of some macro definitions contained in the ``macros.h`` file. + +This file is used to reduce the complexity of the input language where com= plex +variants of similar constructs can be mapped to a unique primitive, so tha= t the +idef-parser has to handle a lower number of computation primitives. + +As you may notice, the description code modifies the registers which have = been +declared by the declaration statements. In this case all the three registe= rs +will be declared, ``RsV`` and ``RtV`` will also be read and ``RdV`` will be +written. + +Now let's have a quick look at the generated code, line by line. + +:: + + tcg_gen_movi_i32(RdV, 0); + +This code starts by zero-initializing ``RdV``, since reading from that reg= ister +without initialization will cause a segmentation fault by QEMU. This is e= mitted +since a declaration of the ``RdV`` register was parsed, but we got no indi= cation +that the variable has been initialized by the caller. + +:: + + TCGv_i32 tmp_0 =3D tcg_temp_new_i32(); + +Then we are declaring a temporary TCGv to hold the result from the sum +operation. + +:: + + tcg_gen_add_i32(tmp_0, RsV, RtV); + +Now we are actually generating the sum tinycode operator between the selec= ted +registers, storing the result in the just declared temporary. + +:: + + tcg_gen_mov_i32(RdV, tmp_0); + +The result of the addition is now stored in the temporary, we move it into= the +correct destination register. This might not seem an efficient code, but Q= EMU +will perform some tinycode optimization, reducing the unnecessary copy. + +:: + + tcg_temp_free_i32(tmp_0); + +Finally, we free the temporary we used to hold the addition result. + +Parser Structure +---------------- + +The idef-parser is built using the ``flex`` and ``bison``. + +``flex`` is used to split the input string into tokens, each described usi= ng a +regular expression. The token description is contained in the +``idef-parser.lex`` source file. The flex-generated scanner takes care als= o to +extract from the input text other meaningful information, e.g.,=C2=A0the n= umerical +value in case of an immediate constant, and decorates the token with the +extracted information. + +``bison`` is used to generate the actual parser, starting from the parsing +description contained in the ``idef-parser.y`` file. The generated parser +executes the ``main`` function at the end of the ``idef-parser.y`` file, w= hich +opens input and output files, creates the parsing context, and eventually = calls +the ``yyparse()`` function, which starts the execution of the LALR(1) pars= er +(see `Wikipedia `__ for more +information about LALR parsing techniques). The LALR(1) parser, whenever i= t has +to shift a token, calls the ``yylex()`` function, which is defined by the +flex-generated code, and reads the input file returning the next scanned t= oken. + +The tokens are mapped on the source language grammar, defined in the +``idef-parser.y`` file to build a unique syntactic tree, according to the +specified operator precedences and associativity rules. + +The grammar describes the whole file which contains the Hexagon instruction +descriptions, therefore it starts from the ``input`` nonterminal, which is= a +list of instructions, each instruction is represented by the following gra= mmar +rule, representing the structure of the input file shown above: + +:: + + instruction : INAME code + + code : LBR decls statements decls RBR + + statements : statements statement + | statement + + statement : control_statement + | rvalue SEMI + | code_block + | SEMI + + code_block : LBR statements RBR + | LBR RBR + +With this initial portion of the grammar we are defining the instruction +statements, which are enclosed by the declarations. Each statement can be a +``control_statement``, a code block, which is just a bracket-enclosed list= of +statements, a ``SEMI``, which is a ``nop`` instruction, and an ``rvalue SE= MI``. + +Expressions +~~~~~~~~~~~ + +``rvalue`` is the nonterminal representing expressions, which are everythi= ng +that could be assigned to a variable. ``rvalue SEMI`` can be a statement o= n its +own because the assign statement, just as in the C language, is itself an +expression. + +``rvalue``\ s can be registers, immediates, predicates, control registers, +variables, or any combination of other ``rvalue``\ s through operators. An +``rvalue`` can be either an immediate or a TCGv, the actual type is determ= ined +by the ``t_hex_value.type`` field. In case it is an immediate, its combina= tion +with other immediates can be performed at compile-time (constant folding),= only +the result will be written into the code. If the ``rvalue`` instead is a T= CGv, +the operations performed on it will have to be emitted as tinycode instruc= tions, +therefore their result will be known only at runtime. An immediate can be = copied +into a TCGv through the ``rvalue_materialize`` function, which allocates a +temporary TCGv and copies the value of the immediate in it. Each temporary +should be freed after that it is no more used, we usually free both operan= ds of +each operator, in an SSA fashion. + +``lvalue``\ s instead represents all the variables which can be assigned t= o a +value, and are specialized into registers and variables: + +:: + + lvalue : REG + | VAR + +The effective assignment of ``lvalue``\ s is handled by the ``gen_assign()= `` +function. + +Automatic Variables +~~~~~~~~~~~~~~~~~~~ + +The input code can contain implicitly declared automatic variables, which = are +initialized with a value and then used. We performed a dedicated handling = of +such variables, because they will be matched by a generic ``VARID`` token,= which +will feature the variable name as a decoration. Each time that the variabl= e is +found, we have to check if that's the first variable use, in that case we +declare a new automatic variable in the tinycode, which can be considered = at all +effects as an immediate. Special care is taken to make sure that each vari= able +is declared only the first time it is seen. Furthermore the variable might +inherit some characteristics like the signedness and the bit width, which = must +be propagated from the initialization of the variable to all the further u= ses of +the variable. + +The combination of ``rvalue``\ s are handled through the use of the +``gen_bin_op`` and ``gen_bin_cmp`` helper functions. These two functions h= andle +the appropriate compile-time or run-time emission of operations to perform= the +required computation. + +Type System +~~~~~~~~~~~ + +idef-parser features a simple type system which is used to correctly imple= ment +the signedness and bit width of the operations. + +The type of each ``rvalue`` is determined by two attributes: its bit width +(``unsigned bit_width``) and its signedness (``bool is_unsigned``). + +For each operation, the type of ``rvalue``\ s influence the way in which t= he +operands are handled and emitted. For example a right shift between signed +operators will be an algebraic shift, while one between unsigned operators= will +be a logical shift. If one of the two operands is signed, and the other is +unsigned, the operation will be signed. + +The bit width also influences the outcome of the operations, in particular= while +the input languages features a fine granularity type system, with types of= 8, +16, 32, 64 (and more for vectorial instructions) bits, the tinycode only +features 32 and 64 bit widths. We propagate as much as possible the fine +granularity type, until the value has to be used inside an operation betwe= en +``rvalue``\ s; in that case if one of the two operands is greater than 32 = bits +we promote the whole operation to 64 bit, taking care of properly extendin= g the +two operands. Fortunately, the most critical instructions already feature +explicit casts and zero/sign extensions which are properly propagated down= to +our parser. + +Control Statements +~~~~~~~~~~~~~~~~~~ + +``control_statement``\ s are all the statements which modify the order of +execution of the generated code according to input parameters. They are ex= panded +by the following grammar rule: + +:: + + control_statement : frame_check + | cancel_statement + | if_statement + | for_statement + | fpart1_statement + +``if_statement``\ s require the emission of labels and branch instructions= which +effectively perform conditional jumps (``tcg_gen_brcondi``) according to t= he +value of an expression. All the predicated instructions, and in general al= l the +instructions where there could be alternative values assigned to an ``lval= ue``, +like C-style ternary expressions: + +:: + + rvalue : rvalue QMARK rvalue COLON rvalue + +Are handled using the conditional move tinycode instruction +(``tcg_gen_movcond``), which avoids the additional complexity of managing = labels +and jumps. + +Instead, regarding the ``for`` loops, exploiting the fact that they always +iterate on immediate values, therefore their iteration ranges are always k= nown +at compile time, we implemented those emitting plain C ``for`` loops. This= is +possible because the loops will be executed in the QEMU code, leading to t= he +consequential unrolling of the for loop, since the tinycode generator +instructions will be executed multiple times, and the respective generated +tinycode will represent the unrolled execution of the loop. + +Parsing Context +~~~~~~~~~~~~~~~ + +All the helper functions in ``idef-parser.y`` carry two fixed parameters, = which +are the parsing context ``c`` and the ``YYLLOC`` location information. The +context is explicitly passed to all the functions because the parser we ge= nerate +is a reentrant one, meaning that it does not have any global variable, and +therefore the instruction compilation could easily be parallelized in the +future. Finally for each rule we propagate information about the location = of the +involved tokens to generate a pretty error reporting, able to highlight the +portion of the input code which generated each error. + +Debugging +--------- + +Developing the idef-parser can lead to two types of errors: compile-time e= rrors +and parsing errors. + +Compile-time errors in Bison-generated parsers are usually due to conflict= s in +the described grammar. Conflicts forbid the grammar to produce a unique +derivation tree, thus must be solved (except for the dangling else problem, +which is marked as expected through the ``%expect 1`` Bison option). + +For solving conflicts you need a basic understanding of `shift-reduce conf= licts +`__ +and `reduce-reduce conflicts +`__, +then, if you are using a Bison version > 3.7.1 you can ask Bison to genera= te +some counterexamples which highlight ambiguous derivations, passing the +``-Wcex`` option to Bison. In general shift/reduce conflicts are solved by +redesigning the grammar in an unambiguous way or by setting the token prio= rity +correctly, while reduce/reduce conflicts are solved by redesigning the +interested part of the grammar. + +Run-time errors can be divided between lexing and parsing errors, lexing e= rrors +are hard to detect, since the ``VAR`` token will catch everything which is= not +catched by other tokens, but easy to fix, because most of the time a simple +regex editing will be enough. + +idef-parser features a fancy parsing error reporting scheme, which for each +parsing error reports the fragment of the input text which was involved in= the +parsing rule that generated an error. + +Implementing an instruction goes through several sequential steps, here ar= e some +suggestions to make each instruction proceed to the next step. + +- not-emitted + + Means that the parsing of the input code relative to that instruction f= ailed, + this could be due to a lexical error or to some mismatch between the or= der of + valid tokens and a parser rule. You should check that tokens are correc= tly + identified and mapped, and that there is a rule matching the token sequ= ence + that you need to parse. + +- emitted + + This instruction class contains all the instruction which are emitted b= ut + fail to compile when included in QEMU. The compilation errors are shown= by + the QEMU building process and will lead to fixing the bug. Most common + errors regard the mismatch of parameters for tinycode generator functio= ns, + which boil down to errors in the idef-parser type system. + +- compiled + + These instruction generate valid tinycode generator code, which however= fail + the QEMU or the harness tests, these cases must be handled manually by + looking into the failing tests and looking at the generated tinycode + generator instruction and at the generated tinycode itself. Tip: handle= the + failing harness tests first, because they usually feature only a single + instruction, thus will require less execution trace navigation. If a + multi-threaded test fail, fixing all the other tests will be the easier + option, hoping that the multi-threaded one will be indirectly fixed. + +- tests-passed + + This is the final goal for each instruction, meaning that the instructi= on + passes the test suite. + +Another approach to fix QEMU system test, where many instructions might fa= il, is +to compare the execution trace of your implementation with the reference +implementations already present in QEMU. To do so you should obtain a QEMU= build +where the instruction pass the test, and run it with the following command: + +:: + + sudo unshare -p sudo -u bash -c \ + 'env -i -d cpu ' + +And do the same for your implementation, the generated execution traces wi= ll be +inherently aligned and can be inspected for behavioral differences using t= he +``diff`` tool. + +Limitations and Future Development +---------------------------------- + +The main limitation of the current parser is given by the syntax-driven na= ture +of the Bison-generated parsers. This has the severe implication of only be= ing +able to generate code in the order of evaluation of the various rules, wit= hout, +in any case, being able to backtrack and alter the generated code. + +An example limitation is highlighted by this statement of the input langua= ge: + +:: + + { (PsV=3D=3D0xff) ? (PdV=3D0xff) : (PdV=3D0x00); } + +This ternary assignment, when written in this form requires us to emit some +proper control flow statements, which emit a jump to the first or to the s= econd +code block, whose implementation is extremely convoluted, because when mat= ching +the ternary assignment, the code evaluating the two assignments will be al= ready +generated. + +Instead we pre-process that statement, making it become: + +:: + + { PdV =3D ((PsV=3D=3D0xff)) ? 0xff : 0x00; } + +Which can be easily matched by the following parser rules: + +:: + + statement | rvalue SEMI + + rvalue : rvalue QMARK rvalue COLON rvalue + | rvalue EQ rvalue + | LPAR rvalue RPAR + | assign_statement + | IMM + + assign_statement : pre ASSIGN rvalue + +Another example that highlight the limitation of the flex/bison parser can= be +found even in the add operation we already saw: + +:: + + TCGv_i32 tmp_0 =3D tcg_temp_new_i32(); + tcg_gen_add_i32(tmp_0, RsV, RtV); + tcg_gen_mov_i32(RdV, tmp_0); + +The fact that we cannot directly use ``RdV`` as the destination of the sum= is a +consequence of the syntax-driven nature of the parser. In fact when we par= se the +assignment, the ``rvalue`` token, representing the sum has already been re= duced, +and thus its code emitted and unchangeable. We rely on the fact that QEMU = will +optimize our code reducing the useless move operations and the relative +temporaries. + +A possible improvement of the parser regards the support for vectorial +instructions and floating point instructions, which will require the exten= sion +of the scanner, the parser, and a partial re-design of the type system, al= lowing +to build the vectorial semantics over the available vectorial tinycode gen= erator +primitives. + +A more radical improvement will use the parser, not to generate directly t= he +tinycode generator code, but to generate an intermediate representation li= ke the +LLVM IR, which in turn could be compiled using the clang TCG backend. That= code +could be furtherly optimized, overcoming the limitations of the syntax-dri= ven +parsing and could lead to a more optimized generated code. --=20 2.31.1 From nobody Mon Apr 29 13:24:59 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1617116157; cv=none; d=zohomail.com; s=zohoarc; b=e/l25BQ6babditsnEnDl2zyb6S/CrzDER5GNTm0/YKZgjP+x524OZpT1a4dbdFvAYmVp3l4csoSb3bf4nyNuRnbyJ0JbDd2FWlPJQSjSQ4fWOZE0Y1Wx+dDpFwLUrGOVwRbZINHORrWV0Qs7Fr24YwHPb9cAARo4WTBHsh03jV4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1617116157; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=m2yRXnIbNbZIWeyfV8xdgvOS2RzdG35bJ8KtiwrTQJs=; b=CH8pnw70HXGXLk+5rUI3EIhW42fZftArDQ4vAUVp9KlEpQ6fjklulbyj6qlPTYU4wN11meqQX/zS7PoiKdurYimTSaWnaFEiQFQJPWNcQ9T4ORHmkNKYQb8qiGyvlbuU804keB5ezMHsu1vGA99247R1HI9iWT471aYGuNVeAQ4= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1617116157396510.28497969520936; Tue, 30 Mar 2021 07:55:57 -0700 (PDT) Received: from localhost ([::1]:39318 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lRFbh-0001px-AJ for importer@patchew.org; Tue, 30 Mar 2021 10:44:37 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:38408) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lRFVd-000314-5M for qemu-devel@nongnu.org; Tue, 30 Mar 2021 10:38:21 -0400 Received: from rev.ng ([5.9.113.41]:32873) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lRFVa-0004wb-FK for qemu-devel@nongnu.org; Tue, 30 Mar 2021 10:38:20 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=rev.ng; s=dkim; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=m2yRXnIbNbZIWeyfV8xdgvOS2RzdG35bJ8KtiwrTQJs=; b=WK06t6bjsOtxbS1owui18VJpng OM2Bu11jiSPVl/XnKJORymrp//TxoOGPilDJ0D7ddJkE4Tpa67UkoBxoJCfpO6fghV1TeaCxbjl15 nwLVPG86aBq5M1NoFFXtcGA5+E3DolKaf234Wsp6erpoTJy0PrdU6X7FPtODaI9ABpB0=; To: qemu-devel@nongnu.org Cc: tsimpson@quicinc.com, bcain@quicinc.com, babush@rev.ng, nizzo@rev.ng, philmd@redhat.com, richard.henderson@linaro.org, Alessandro Di Federico Subject: [PATCH v3 04/12] target/hexagon: make slot number an unsigned Date: Tue, 30 Mar 2021 16:37:42 +0200 Message-Id: <20210330143750.3037824-5-ale.qemu@rev.ng> In-Reply-To: <20210330143750.3037824-1-ale.qemu@rev.ng> References: <20210330143750.3037824-1-ale.qemu@rev.ng> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=5.9.113.41; envelope-from=ale@rev.ng; helo=rev.ng X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_PASS=-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.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Reply-to: Alessandro Di Federico From: Alessandro Di Federico via X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" From: Paolo Montesel Signed-off-by: Alessandro Di Federico Signed-off-by: Paolo Montesel --- target/hexagon/genptr.c | 6 ++++-- target/hexagon/macros.h | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c index 7481f4c1dd..fd18aabe8d 100644 --- a/target/hexagon/genptr.c +++ b/target/hexagon/genptr.c @@ -33,7 +33,8 @@ static inline TCGv gen_read_preg(TCGv pred, uint8_t num) return pred; } =20 -static inline void gen_log_predicated_reg_write(int rnum, TCGv val, int sl= ot) +static inline void gen_log_predicated_reg_write(int rnum, TCGv val, + unsigned slot) { TCGv one =3D tcg_const_tl(1); TCGv zero =3D tcg_const_tl(0); @@ -62,7 +63,8 @@ static inline void gen_log_reg_write(int rnum, TCGv val) #endif } =20 -static void gen_log_predicated_reg_write_pair(int rnum, TCGv_i64 val, int = slot) +static void gen_log_predicated_reg_write_pair(int rnum, TCGv_i64 val, + unsigned slot) { TCGv val32 =3D tcg_temp_new(); TCGv one =3D tcg_const_tl(1); diff --git a/target/hexagon/macros.h b/target/hexagon/macros.h index cfcb8173ba..d9473c8823 100644 --- a/target/hexagon/macros.h +++ b/target/hexagon/macros.h @@ -154,7 +154,7 @@ #define LOAD_CANCEL(EA) do { CANCEL; } while (0) =20 #ifdef QEMU_GENERATE -static inline void gen_pred_cancel(TCGv pred, int slot_num) +static inline void gen_pred_cancel(TCGv pred, unsigned slot_num) { TCGv slot_mask =3D tcg_const_tl(1 << slot_num); TCGv tmp =3D tcg_temp_new(); --=20 2.31.1 From nobody Mon Apr 29 13:24:59 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1617117250; cv=none; d=zohomail.com; s=zohoarc; b=Q+fUoHesOyJdBQipBPfK6GKBQode7rBVJ/vD5KPFDtD3f9+M9damgA//hgMX+/SVqZo+I3NkVKM2Kd2PSrabiz8YUw7OTPFUKgJKHhZ62dJsDZrAVO8yBnMfXyOAL+If5Vzn7JM2OMeG+4S6HNDWoyKKZ/jD8RjwqiKNIn/bIGM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1617117250; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=8kkGbIESYw21aMYRMMd2RPq99rDaSprGzjF3+F+2fVc=; b=IWwv0wAfZjAQS1Okxgs440dFNs5C/mhjUK7AOeul/jVhs1SijCvWPblBu38QWwPuziBQV00+6rWnSvBPW/lOPqoI0XT2dU12Aidgj6z7L2mf7eGQwuTzJl3n0cV9JevKzo1NS9c5cxiNhOKT0oYJIlhz5TvaYo84SeZ5t0fk3fw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1617117250965348.73208847489013; Tue, 30 Mar 2021 08:14:10 -0700 (PDT) Received: from localhost ([::1]:54460 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lRFXH-0004nM-Cf for importer@patchew.org; Tue, 30 Mar 2021 10:40:03 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:38432) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lRFVe-00033r-9a for qemu-devel@nongnu.org; Tue, 30 Mar 2021 10:38:22 -0400 Received: from rev.ng ([5.9.113.41]:60549) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lRFVa-0004wl-FL for qemu-devel@nongnu.org; Tue, 30 Mar 2021 10:38:21 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=rev.ng; s=dkim; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=8kkGbIESYw21aMYRMMd2RPq99rDaSprGzjF3+F+2fVc=; b=JPlZ93DTpEbYQjkwnKRL7V+gsG AsLhcyXMRTw3U7zcB79WXgEZ4S3r3MR4FbKtTQbkk10sTBcoRfc9ECCaZzBhBFrm7kDtQa5jObHiQ aTaKs7/8pP1uLO4IbPK5nt92/L+tCeXJKRPBaEBWiLnC19KDX2m1PUYK4yCqjsVD8bEc=; To: qemu-devel@nongnu.org Cc: tsimpson@quicinc.com, bcain@quicinc.com, babush@rev.ng, nizzo@rev.ng, philmd@redhat.com, richard.henderson@linaro.org, Alessandro Di Federico Subject: [PATCH v3 05/12] target/hexagon: make helper functions non-static Date: Tue, 30 Mar 2021 16:37:43 +0200 Message-Id: <20210330143750.3037824-6-ale.qemu@rev.ng> In-Reply-To: <20210330143750.3037824-1-ale.qemu@rev.ng> References: <20210330143750.3037824-1-ale.qemu@rev.ng> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=5.9.113.41; envelope-from=ale@rev.ng; helo=rev.ng X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_PASS=-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.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Reply-to: Alessandro Di Federico From: Alessandro Di Federico via X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" From: Paolo Montesel Make certain helper functions non-static, making them available outside genptr.c. These functions are required by code generated by the idef-parser. Signed-off-by: Alessandro Di Federico Signed-off-by: Paolo Montesel --- target/hexagon/genptr.c | 7 ++++--- target/hexagon/genptr.h | 6 ++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c index fd18aabe8d..1ddb4360f1 100644 --- a/target/hexagon/genptr.c +++ b/target/hexagon/genptr.c @@ -26,8 +26,9 @@ #include "translate.h" #include "macros.h" #include "gen_tcg.h" +#include "genptr.h" =20 -static inline TCGv gen_read_preg(TCGv pred, uint8_t num) +TCGv gen_read_preg(TCGv pred, uint8_t num) { tcg_gen_mov_tl(pred, hex_pred[num]); return pred; @@ -54,7 +55,7 @@ static inline void gen_log_predicated_reg_write(int rnum,= TCGv val, tcg_temp_free(slot_mask); } =20 -static inline void gen_log_reg_write(int rnum, TCGv val) +void gen_log_reg_write(int rnum, TCGv val) { tcg_gen_mov_tl(hex_new_value[rnum], val); #if HEX_DEBUG @@ -118,7 +119,7 @@ static void gen_log_reg_write_pair(int rnum, TCGv_i64 v= al) #endif } =20 -static inline void gen_log_pred_write(int pnum, TCGv val) +void gen_log_pred_write(int pnum, TCGv val) { TCGv zero =3D tcg_const_tl(0); TCGv base_val =3D tcg_temp_new(); diff --git a/target/hexagon/genptr.h b/target/hexagon/genptr.h index c158005d2a..e1dcd24b0e 100644 --- a/target/hexagon/genptr.h +++ b/target/hexagon/genptr.h @@ -19,7 +19,13 @@ #define HEXAGON_GENPTR_H =20 #include "insn.h" +#include "tcg/tcg.h" +#include "translate.h" =20 extern const SemanticInsn opcode_genptr[]; =20 +TCGv gen_read_preg(TCGv pred, uint8_t num); +void gen_log_reg_write(int rnum, TCGv val); +void gen_log_pred_write(int pnum, TCGv val); + #endif --=20 2.31.1 From nobody Mon Apr 29 13:24:59 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1617115790; cv=none; d=zohomail.com; s=zohoarc; b=EKh9XnKDWxEg+E0J1LoOeqyEhv/KmzslbvIcNgYghye5BpTcZRgHCBTfA+xK2oIsZK8O6bkLsvIeKsMFUg3SiPk4iMeigutLsJ9IocJayb6WDOeoR5L0UgNiU1CFJkdzyUHedtBVntndN/SenUtTtre6K0B73LXRzIyKupn5IrY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1617115790; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=TgVzR+MVQGw9qLCEKsreHw5xl12aOmQPStr1EZ48rWM=; b=VhYrYqvM+rZETM/imI90dG+SX53SvhojcQPGAtNAW+Uker1dxEH74WezMwVEb3jX1XQ4MOm1pv2p8cP36Kcy4FjMCliarhReAgp9yEDw6Dc3j7LqRiVKd3lRn2Qjnn2hQtf9eUTlfP2npowKjOo9LW2fT0Bpkpz0Tywsgb/U7og= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1617115790444274.20983865563187; Tue, 30 Mar 2021 07:49:50 -0700 (PDT) Received: from localhost ([::1]:55000 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lRFgj-0008LU-9g for importer@patchew.org; Tue, 30 Mar 2021 10:49:49 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:38512) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lRFVm-0003Ev-IQ for qemu-devel@nongnu.org; Tue, 30 Mar 2021 10:38:30 -0400 Received: from rev.ng ([5.9.113.41]:45053) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lRFVa-0004wr-FV for qemu-devel@nongnu.org; Tue, 30 Mar 2021 10:38:30 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=rev.ng; s=dkim; h=Content-Transfer-Encoding:Content-Type:MIME-Version:References: In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=TgVzR+MVQGw9qLCEKsreHw5xl12aOmQPStr1EZ48rWM=; b=H3CHTxNbnav3N8/OYIZMbcBQSD P+XCRZGqNaqxPaAFhPONKRV1jPoJpqGmtuUtgCmwdUg3ojeT85gMqzF78gHv287+qYWlolMRh0tJV 9tcQfUYpjEQLEuHrgckBH4zz0alxr7llmMDuu1FQJ/W40jeIZaHGBCOt+IzsQYKvz82k=; To: qemu-devel@nongnu.org Cc: tsimpson@quicinc.com, bcain@quicinc.com, babush@rev.ng, nizzo@rev.ng, philmd@redhat.com, richard.henderson@linaro.org, Alessandro Di Federico Subject: [PATCH v3 06/12] target/hexagon: introduce new helper functions Date: Tue, 30 Mar 2021 16:37:44 +0200 Message-Id: <20210330143750.3037824-7-ale.qemu@rev.ng> In-Reply-To: <20210330143750.3037824-1-ale.qemu@rev.ng> References: <20210330143750.3037824-1-ale.qemu@rev.ng> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=5.9.113.41; envelope-from=ale@rev.ng; helo=rev.ng X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_PASS=-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.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Reply-to: Alessandro Di Federico From: Alessandro Di Federico via X-ZohoMail-DKIM: fail (Header signature does not verify) From: Niccol=C3=B2 Izzo These helpers will be employed by the idef-parser generated code. Signed-off-by: Alessandro Di Federico Signed-off-by: Niccol=C3=B2 Izzo --- target/hexagon/genptr.c | 173 ++++++++++++++++++++++++++++++++++++++++ target/hexagon/genptr.h | 17 ++++ target/hexagon/macros.h | 9 +++ 3 files changed, 199 insertions(+) diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c index 1ddb4360f1..adab1d395c 100644 --- a/target/hexagon/genptr.c +++ b/target/hexagon/genptr.c @@ -28,6 +28,12 @@ #include "gen_tcg.h" #include "genptr.h" =20 +TCGv gen_read_reg(TCGv result, int num) +{ + tcg_gen_mov_tl(result, hex_gpr[num]); + return result; +} + TCGv gen_read_preg(TCGv pred, uint8_t num) { tcg_gen_mov_tl(pred, hex_pred[num]); @@ -330,5 +336,172 @@ static inline void gen_store_conditional8(CPUHexagonS= tate *env, tcg_gen_movi_tl(hex_llsc_addr, ~0); } =20 +void gen_store32(TCGv vaddr, TCGv src, tcg_target_long width, unsigned slo= t) +{ + tcg_gen_mov_tl(hex_store_addr[slot], vaddr); + tcg_gen_movi_tl(hex_store_width[slot], width); + tcg_gen_mov_tl(hex_store_val32[slot], src); +} + +void gen_store1(TCGv_env cpu_env, TCGv vaddr, TCGv src, DisasContext *ctx, + unsigned slot) +{ + gen_store32(vaddr, src, 1, slot); + ctx->store_width[slot] =3D 1; +} + +void gen_store2(TCGv_env cpu_env, TCGv vaddr, TCGv src, DisasContext *ctx, + unsigned slot) +{ + gen_store32(vaddr, src, 2, slot); + ctx->store_width[slot] =3D 2; +} + +void gen_store4(TCGv_env cpu_env, TCGv vaddr, TCGv src, DisasContext *ctx, + unsigned slot) +{ + gen_store32(vaddr, src, 4, slot); + ctx->store_width[slot] =3D 4; +} + + +void gen_store8(TCGv_env cpu_env, TCGv vaddr, TCGv_i64 src, DisasContext *= ctx, + unsigned slot) +{ + tcg_gen_mov_tl(hex_store_addr[slot], vaddr); + tcg_gen_movi_tl(hex_store_width[slot], 8); + tcg_gen_mov_i64(hex_store_val64[slot], src); + ctx->store_width[slot] =3D 8; +} + +void gen_set_usr_field(int field, TCGv val) +{ + tcg_gen_deposit_tl(hex_gpr[HEX_REG_USR], hex_gpr[HEX_REG_USR], val, + reg_field_info[field].offset, + reg_field_info[field].width); +} + +void gen_set_usr_fieldi(int field, int x) +{ + TCGv val =3D tcg_const_tl(x); + gen_set_usr_field(field, val); + tcg_temp_free(val); +} + +void gen_write_new_pc(TCGv addr) +{ + /* If there are multiple branches in a packet, ignore the second one */ + TCGv zero =3D tcg_const_tl(0); + tcg_gen_movcond_tl(TCG_COND_NE, hex_next_PC, hex_branch_taken, zero, + hex_next_PC, addr); + tcg_gen_movi_tl(hex_branch_taken, 1); + tcg_temp_free(zero); +} + +void gen_sat_i32(TCGv dest, TCGv source, int width, bool set_overflow) +{ + TCGv max_val =3D tcg_const_i32((1 << (width - 1)) - 1); + TCGv min_val =3D tcg_const_i32(-(1 << (width - 1))); + tcg_gen_movcond_i32(TCG_COND_GT, dest, source, max_val, max_val, sourc= e); + tcg_gen_movcond_i32(TCG_COND_LT, dest, source, min_val, min_val, dest); + /* Set Overflow Bit */ + if (set_overflow) { + TCGv ovf =3D tcg_temp_new(); + TCGv one =3D tcg_const_i32(1); + GET_USR_FIELD(USR_OVF, ovf); + tcg_gen_movcond_i32(TCG_COND_GT, ovf, source, max_val, one, ovf); + tcg_gen_movcond_i32(TCG_COND_LT, ovf, source, min_val, one, ovf); + SET_USR_FIELD(USR_OVF, ovf); + tcg_temp_free_i32(ovf); + tcg_temp_free_i32(one); + } + tcg_temp_free_i32(max_val); + tcg_temp_free_i32(min_val); +} + +void gen_satu_i32(TCGv dest, TCGv source, int width, bool set_overflow) +{ + TCGv max_val =3D tcg_const_i32((1 << width) - 1); + tcg_gen_movcond_i32(TCG_COND_GTU, dest, source, max_val, max_val, sour= ce); + TCGv_i32 zero =3D tcg_const_i32(0); + tcg_gen_movcond_i32(TCG_COND_LT, dest, source, zero, zero, dest); + /* Set Overflow Bit */ + if (set_overflow) { + TCGv ovf =3D tcg_temp_new(); + TCGv one =3D tcg_const_i32(1); + GET_USR_FIELD(USR_OVF, ovf); + tcg_gen_movcond_i32(TCG_COND_GTU, ovf, source, max_val, one, ovf); + SET_USR_FIELD(USR_OVF, ovf); + tcg_temp_free_i32(ovf); + tcg_temp_free_i32(one); + } + tcg_temp_free_i32(max_val); + tcg_temp_free_i32(zero); +} + +void gen_sat_i64(TCGv_i64 dest, TCGv_i64 source, int width, bool set_overf= low) +{ + TCGv_i64 max_val =3D tcg_const_i64((1 << (width - 1)) - 1); + TCGv_i64 min_val =3D tcg_const_i64(-(1 << (width - 1))); + tcg_gen_movcond_i64(TCG_COND_GT, dest, source, max_val, max_val, sourc= e); + tcg_gen_movcond_i64(TCG_COND_LT, dest, source, min_val, min_val, dest); + /* Set Overflow Bit */ + if (set_overflow) { + TCGv ovf =3D tcg_temp_new(); + TCGv_i64 ovf_ext =3D tcg_temp_new_i64(); + TCGv_i64 one =3D tcg_const_i64(1); + GET_USR_FIELD(USR_OVF, ovf); + tcg_gen_ext_i32_i64(ovf_ext, ovf); + tcg_gen_movcond_i64(TCG_COND_GT, + ovf_ext, + source, + max_val, + one, + ovf_ext); + tcg_gen_movcond_i64(TCG_COND_LT, + ovf_ext, + source, + min_val, + one, + ovf_ext); + tcg_gen_trunc_i64_tl(ovf, ovf_ext); + SET_USR_FIELD(USR_OVF, ovf); + tcg_temp_free_i32(ovf); + tcg_temp_free_i64(ovf_ext); + tcg_temp_free_i64(one); + } + tcg_temp_free_i64(max_val); + tcg_temp_free_i64(min_val); +} + +void gen_satu_i64(TCGv_i64 dest, TCGv_i64 source, int width, bool set_over= flow) +{ + TCGv_i64 max_val =3D tcg_const_i64((1 << width) - 1); + tcg_gen_movcond_i64(TCG_COND_GTU, dest, source, max_val, max_val, sour= ce); + TCGv_i64 zero =3D tcg_const_i64(0); + tcg_gen_movcond_i64(TCG_COND_LT, dest, source, zero, zero, dest); + /* Set Overflow Bit */ + if (set_overflow) { + TCGv ovf =3D tcg_temp_new(); + TCGv_i64 ovf_ext =3D tcg_temp_new_i64(); + TCGv_i64 one =3D tcg_const_i64(1); + GET_USR_FIELD(USR_OVF, ovf); + tcg_gen_ext_i32_i64(ovf_ext, ovf); + tcg_gen_movcond_i64(TCG_COND_GTU, + ovf_ext, + source, + max_val, + one, + ovf_ext); + tcg_gen_trunc_i64_tl(ovf, ovf_ext); + SET_USR_FIELD(USR_OVF, ovf); + tcg_temp_free_i32(ovf); + tcg_temp_free_i64(ovf_ext); + tcg_temp_free_i64(one); + } + tcg_temp_free_i64(max_val); + tcg_temp_free_i64(zero); +} + #include "tcg_funcs_generated.c.inc" #include "tcg_func_table_generated.c.inc" diff --git a/target/hexagon/genptr.h b/target/hexagon/genptr.h index e1dcd24b0e..c36ad76c42 100644 --- a/target/hexagon/genptr.h +++ b/target/hexagon/genptr.h @@ -24,8 +24,25 @@ =20 extern const SemanticInsn opcode_genptr[]; =20 +TCGv gen_read_reg(TCGv result, int num); TCGv gen_read_preg(TCGv pred, uint8_t num); void gen_log_reg_write(int rnum, TCGv val); void gen_log_pred_write(int pnum, TCGv val); +void gen_store32(TCGv vaddr, TCGv src, tcg_target_long width, unsigned slo= t); +void gen_store1(TCGv_env cpu_env, TCGv vaddr, TCGv src, DisasContext *ctx, + unsigned slot); +void gen_store2(TCGv_env cpu_env, TCGv vaddr, TCGv src, DisasContext *ctx, + unsigned slot); +void gen_store4(TCGv_env cpu_env, TCGv vaddr, TCGv src, DisasContext *ctx, + unsigned slot); +void gen_store8(TCGv_env cpu_env, TCGv vaddr, TCGv_i64 src, DisasContext *= ctx, + unsigned slot); +void gen_write_new_pc(TCGv addr); +void gen_set_usr_field(int field, TCGv val); +void gen_set_usr_fieldi(int field, int x); +void gen_sat_i32(TCGv dest, TCGv source, int width, bool set_overflow); +void gen_satu_i32(TCGv dest, TCGv source, int width, bool set_overflow); +void gen_sat_i64(TCGv_i64 dest, TCGv_i64 source, int width, bool set_overf= low); +void gen_satu_i64(TCGv_i64 dest, TCGv_i64 source, int width, bool set_over= flow); =20 #endif diff --git a/target/hexagon/macros.h b/target/hexagon/macros.h index d9473c8823..94357c3e42 100644 --- a/target/hexagon/macros.h +++ b/target/hexagon/macros.h @@ -149,7 +149,16 @@ #define MEM_STORE8(VA, DATA, SLOT) log_store64(env, VA, DATA, 8, SLOT) #endif =20 +#ifdef QEMU_GENERATE +static inline void gen_cancel(unsigned slot) +{ + tcg_gen_ori_tl(hex_slot_cancelled, hex_slot_cancelled, 1 << slot); +} + +#define CANCEL gen_cancel(slot); +#else #define CANCEL cancel_slot(env, slot) +#endif =20 #define LOAD_CANCEL(EA) do { CANCEL; } while (0) =20 --=20 2.31.1 From nobody Mon Apr 29 13:24:59 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1617118177; cv=none; d=zohomail.com; s=zohoarc; b=izoTD2wOH1XtuZPdvgiDWT90q5UGDmP9gn1T6wU2AYbyk8xCcUJzg+ilfAS34rHnf3ir+/MKj0CN/TWdEZUDCd8DvFCUsznC5NlzDUzzrajCLqZbHsMwO4PdGqnJHaaQ2pyNDo8LThF8t2CKyoftwzyogNojsnPH4qdoMDtpvJM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1617118177; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=dKS566l2tmz6OK9atm1kzL5ZHx1yC4keQWD0Ja+UupI=; b=Q65/FChf0qdObvMrGzX8TWt7kW8048EF+L0xrZsVWu2aZMCDJy437Axq3eUSL3lrXQpu9qjUAlNWo4PmdxvEVKhxqK1UM1Uq6/L9rHkBpG4EamOZCoVx6jcMsKK0V/JJ+dJ7hJo9MrvZ9Uq3fLKaMbxsvfZQIQkW6sJyqVUI6K4= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1617118177554857.1719204699498; Tue, 30 Mar 2021 08:29:37 -0700 (PDT) Received: from localhost ([::1]:35078 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lRFaR-00005Z-KP for importer@patchew.org; Tue, 30 Mar 2021 10:43:19 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:38406) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lRFVd-00030v-4x for qemu-devel@nongnu.org; Tue, 30 Mar 2021 10:38:21 -0400 Received: from rev.ng ([5.9.113.41]:50999) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lRFVa-0004ww-FC for qemu-devel@nongnu.org; Tue, 30 Mar 2021 10:38:20 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=rev.ng; s=dkim; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=dKS566l2tmz6OK9atm1kzL5ZHx1yC4keQWD0Ja+UupI=; b=dgftM278F88qUlr9fk2f7u2SiW WliUVkX3EtkECiIm6ChpjNWXIOugsCRT/JV2jgqLAem2eo/1x9x2gHqWgDd0yiWeydT5zgW2Q3qMj FJK3dfeCM0hJJPdLcpuvRN2+PwjepQ9oLIec0pS4cLr4TtRP90X3ESE/nxuNqLGh/JeE=; To: qemu-devel@nongnu.org Cc: tsimpson@quicinc.com, bcain@quicinc.com, babush@rev.ng, nizzo@rev.ng, philmd@redhat.com, richard.henderson@linaro.org, Alessandro Di Federico Subject: [PATCH v3 07/12] target/hexagon: expose next PC in DisasContext Date: Tue, 30 Mar 2021 16:37:45 +0200 Message-Id: <20210330143750.3037824-8-ale.qemu@rev.ng> In-Reply-To: <20210330143750.3037824-1-ale.qemu@rev.ng> References: <20210330143750.3037824-1-ale.qemu@rev.ng> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=5.9.113.41; envelope-from=ale@rev.ng; helo=rev.ng X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_PASS=-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.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Reply-to: Alessandro Di Federico From: Alessandro Di Federico via X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" From: Paolo Montesel Signed-off-by: Alessandro Di Federico Signed-off-by: Paolo Montesel --- target/hexagon/translate.c | 3 ++- target/hexagon/translate.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c index eeaad5f8ba..30ff3c5d51 100644 --- a/target/hexagon/translate.c +++ b/target/hexagon/translate.c @@ -503,11 +503,12 @@ static void decode_and_translate_packet(CPUHexagonSta= te *env, DisasContext *ctx) if (decode_packet(nwords, words, &pkt, false) > 0) { HEX_DEBUG_PRINT_PKT(&pkt); gen_start_packet(ctx, &pkt); + ctx->npc =3D ctx->base.pc_next + pkt.encod_pkt_size_in_bytes; for (i =3D 0; i < pkt.num_insns; i++) { gen_insn(env, ctx, &pkt.insn[i], &pkt); } gen_commit_packet(ctx, &pkt); - ctx->base.pc_next +=3D pkt.encod_pkt_size_in_bytes; + ctx->base.pc_next =3D ctx->npc; } else { gen_exception(HEX_EXCP_INVALID_PACKET); ctx->base.is_jmp =3D DISAS_NORETURN; diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h index 938f7fbb9f..2195e20f4b 100644 --- a/target/hexagon/translate.h +++ b/target/hexagon/translate.h @@ -36,6 +36,7 @@ typedef struct DisasContext { int preg_log_idx; uint8_t store_width[STORES_MAX]; uint8_t s1_store_processed; + uint32_t npc; } DisasContext; =20 static inline void ctx_log_reg_write(DisasContext *ctx, int rnum) --=20 2.31.1 From nobody Mon Apr 29 13:24:59 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1617117302; cv=none; d=zohomail.com; s=zohoarc; b=RECUQx0mtRHUMI5NF6gx3a7waGuZJ/7mnsCsq3NA202cvz6cfhhlstijEeUIuzWmGPTELD61+wz1/olSpkJwBlkOU4WL+/5kUkJOAdC6v9LKtRQPJtuiavR+4VEQjDkHeQxblbkFjHyGqrrAopR3YOMHZ1VvVVZc4905QXJu11g= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1617117302; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=v3Mp4qE6QPfGMYfFwmbFg8cv/3Gpp8SNoSLu/UaNH9U=; b=V8omTDtbjVhtKH5wFl7t2Upc+m3WtzjzNp6yJx54oA5p3aCdrEnpQNd6O4l802WvsWeSnHjOIHYvTlok1R5b25yUDxP2kflax2imSC4KUtii32Kn/hbWvC1FwzfYdS/+3DTHa+4OCjCIzQ7wWokDbS2No65TMHT+orhGXoW5rlQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1617117302738454.71627889983426; Tue, 30 Mar 2021 08:15:02 -0700 (PDT) Received: from localhost ([::1]:47658 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lRFeL-0005MG-Ph for importer@patchew.org; Tue, 30 Mar 2021 10:47:21 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:38488) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lRFVk-000391-Ak for qemu-devel@nongnu.org; Tue, 30 Mar 2021 10:38:28 -0400 Received: from rev.ng ([5.9.113.41]:45239) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lRFVa-0004x0-F4 for qemu-devel@nongnu.org; Tue, 30 Mar 2021 10:38:28 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=rev.ng; s=dkim; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=v3Mp4qE6QPfGMYfFwmbFg8cv/3Gpp8SNoSLu/UaNH9U=; b=UmZTx1dwRkREFWYJTBzI/v9ja6 x+WjRDJddUgT+ZJJnMU6+zq7r935qxdPyGOoKRLLZWm2YQ+eiSfyGI2ALbBMNNug51Zg81gY3bdKe ORCVe9RykVeGDjcmQRumvWO6How0cKgXiMFoKDUFMotXLOwDp7XezewXGiPL2bAaBMwY=; To: qemu-devel@nongnu.org Cc: tsimpson@quicinc.com, bcain@quicinc.com, babush@rev.ng, nizzo@rev.ng, philmd@redhat.com, richard.henderson@linaro.org, Alessandro Di Federico Subject: [PATCH v3 08/12] target/hexagon: prepare input for the idef-parser Date: Tue, 30 Mar 2021 16:37:46 +0200 Message-Id: <20210330143750.3037824-9-ale.qemu@rev.ng> In-Reply-To: <20210330143750.3037824-1-ale.qemu@rev.ng> References: <20210330143750.3037824-1-ale.qemu@rev.ng> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=5.9.113.41; envelope-from=ale@rev.ng; helo=rev.ng X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_PASS=-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.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Reply-to: Alessandro Di Federico From: Alessandro Di Federico via X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" From: Alessandro Di Federico Introduce infrastructure necessary to produce a file suitable for being parsed by the idef-parser. Signed-off-by: Alessandro Di Federico --- target/hexagon/gen_idef_parser_funcs.py | 114 ++++++++++++++++++ target/hexagon/idef-parser/macros.inc | 150 ++++++++++++++++++++++++ target/hexagon/idef-parser/prepare | 24 ++++ target/hexagon/meson.build | 18 +++ 4 files changed, 306 insertions(+) create mode 100644 target/hexagon/gen_idef_parser_funcs.py create mode 100644 target/hexagon/idef-parser/macros.inc create mode 100755 target/hexagon/idef-parser/prepare diff --git a/target/hexagon/gen_idef_parser_funcs.py b/target/hexagon/gen_i= def_parser_funcs.py new file mode 100644 index 0000000000..7b8e0f6981 --- /dev/null +++ b/target/hexagon/gen_idef_parser_funcs.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python3 + +## +## Copyright(c) 2019-2021 rev.ng Srls. All Rights Reserved. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program 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 General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, see . +## + +import sys +import re +import string +from io import StringIO + +import hex_common + +## +## Generate code to be fed to the idef_parser +## +## Consider A2_add: +## +## Rd32=3Dadd(Rs32,Rt32), { RdV=3DRsV+RtV;} +## +## We produce: +## +## A2_add(RdV, in RsV, in RtV) { +## { RdV=3DRsV+RtV;} +## } +## +## A2_add represents the instruction tag. Then we have a list of TCGv +## that the code generated by the parser can expect in input. Some of +## them are inputs ("in" prefix), while some others are outputs. +## +def main(): + hex_common.read_semantics_file(sys.argv[1]) + hex_common.read_attribs_file(sys.argv[2]) + hex_common.read_overrides_file(sys.argv[3]) + hex_common.calculate_attribs() + tagregs =3D hex_common.get_tagregs() + tagimms =3D hex_common.get_tagimms() + + with open(sys.argv[4], 'w') as f: + f.write('#include "macros.inc"\n\n') + + for tag in hex_common.tags: + ## Skip the priv instructions + if ( "A_PRIV" in hex_common.attribdict[tag] ) : + continue + ## Skip the guest instructions + if ( "A_GUEST" in hex_common.attribdict[tag] ) : + continue + ## Skip instructions using switch + if ( tag in {'S4_vrcrotate_acc', 'S4_vrcrotate'} ) : + continue + ## Skip trap instructions + if ( tag in {'J2_trap0', 'J2_trap1'} ) : + continue + ## Skip 128-bit instructions + if ( tag in {'A7_croundd_ri', 'A7_croundd_rr'} ) : + continue + ## Skip other unsupported instructions + if ( tag.startswith('S2_cabacdecbin') ) : + continue + if ( tag.startswith('Y') ) : + continue + if ( tag.startswith('V6_') ) : + continue + if ( tag.startswith('F') ) : + continue + if ( tag.endswith('_locked') ) : + continue + + regs =3D tagregs[tag] + imms =3D tagimms[tag] + + arguments =3D [] + if hex_common.need_ea(tag): + arguments.append("EA") + + for regtype,regid,toss,numregs in regs: + prefix =3D "in " if hex_common.is_read(regid) else "" + + is_pair =3D hex_common.is_pair(regid) + is_single_old =3D (hex_common.is_single(regid) + and hex_common.is_old_val(regtype, regid,= tag)) + is_single_new =3D (hex_common.is_single(regid) + and hex_common.is_new_val(regtype, regid,= tag)) + + if is_pair or is_single_old: + arguments.append("%s%s%sV" % (prefix, regtype, regid)) + elif is_single_new: + arguments.append("%s%s%sN" % (prefix, regtype, regid)) + else: + print("Bad register parse: ",regtype,regid,toss,numreg= s) + + for immlett,bits,immshift in imms: + arguments.append(hex_common.imm_name(immlett)) + + f.write("%s(%s) {\n" % (tag, ", ".join(arguments))) + f.write(" %s\n" % hex_common.semdict[tag]) + f.write("}\n\n") + +if __name__ =3D=3D "__main__": + main() diff --git a/target/hexagon/idef-parser/macros.inc b/target/hexagon/idef-pa= rser/macros.inc new file mode 100644 index 0000000000..a0e16180c9 --- /dev/null +++ b/target/hexagon/idef-parser/macros.inc @@ -0,0 +1,150 @@ +/* + * Copyright(c) 2019-2021 rev.ng Srls. All Rights Reserved. + * + * 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 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 . + */ + +/* Copy rules */ +#define fLSBOLD(VAL) (fGETBIT(0, VAL)) +#define fSATH(VAL) fSATN(16, VAL) +#define fSATUH(VAL) fSATUN(16, VAL) +#define fVSATH(VAL) fVSATN(16, VAL) +#define fVSATUH(VAL) fVSATUN(16, VAL) +#define fSATUB(VAL) fSATUN(8, VAL) +#define fSATB(VAL) fSATN(8, VAL) +#define fVSATUB(VAL) fVSATUN(8, VAL) +#define fVSATB(VAL) fVSATN(8, VAL) +#define fCALL(A) fWRITE_LR(fREAD_NPC()); fWRITE_NPC(A); +#define fCALLR(A) fWRITE_LR(fREAD_NPC()); fWRITE_NPC(A); +#define fCAST2_8s(A) fSXTN(16, 64, A) +#define fCAST2_8u(A) fZXTN(16, 64, A) +#define fCAST8S_16S(A) (fSXTN(64, 128, A)) +#define fCAST16S_8S(A) (fSXTN(128, 64, A)) +#define fVSATW(A) fVSATN(32, fCAST8_8s(A)) +#define fSATW(A) fSATN(32, fCAST8_8s(A)) +#define fVSAT(A) fVSATN(32, A) +#define fSAT(A) fSATN(32, A) + +/* Ease parsing */ +#define f8BITSOF(VAL) ((VAL) ? 0xff : 0x00) +#define fREAD_GP() (Constant_extended ? (0) : GP) +#define fCLIP(DST, SRC, U) (DST =3D fMIN((1 << U) - 1, fMAX(SRC, -(1 << U)= ))) +#define fBIDIR_ASHIFTL(SRC, SHAMT, REGSTYPE) \ + ((SHAMT > 0) ? \ + (fCAST##REGSTYPE##s(SRC) << SHAMT) : \ + (fCAST##REGSTYPE##s(SRC) >> -SHAMT)) + +#define fBIDIR_LSHIFTL(SRC, SHAMT, REGSTYPE) \ + ((SHAMT > 0) ? \ + (fCAST##REGSTYPE##u(SRC) << SHAMT) : \ + (fCAST##REGSTYPE##u(SRC) >>> -SHAMT)) + +#define fBIDIR_ASHIFTR(SRC, SHAMT, REGSTYPE) \ + ((SHAMT > 0) ? \ + (fCAST##REGSTYPE##s(SRC) >> SHAMT) : \ + (fCAST##REGSTYPE##s(SRC) << -SHAMT)) + +#define fBIDIR_SHIFTR(SRC, SHAMT, REGSTYPE) \ + (((SHAMT) < 0) ? ((fCAST##REGSTYPE(SRC) << ((-(SHAMT)) - 1)) << 1) \ + : (fCAST##REGSTYPE(SRC) >> (SHAMT))) + +#define fBIDIR_LSHIFTR(SRC, SHAMT, REGSTYPE) \ + fBIDIR_SHIFTR(SRC, SHAMT, REGSTYPE##u) + +#define fSATVALN(N, VAL) \ + fSET_OVERFLOW( \ + ((VAL) < 0) ? (-(1LL << ((N) - 1))) : ((1LL << ((N) - 1)) - 1) \ + ) + +#define fSAT_ORIG_SHL(A, ORIG_REG) \ + (((fCAST4s((fSAT(A)) ^ (fCAST4s(ORIG_REG)))) < 0) \ + ? fSATVALN(32, (fCAST4s(ORIG_REG))) \ + : ((((ORIG_REG) > 0) && ((A) =3D=3D 0)) ? fSATVALN(32, (ORIG_REG))= \ + : fSAT(A))) + +#define fBIDIR_ASHIFTR_SAT(SRC, SHAMT, REGSTYPE) \ + (((SHAMT) < 0) ? fSAT_ORIG_SHL((fCAST##REGSTYPE##s(SRC) \ + << ((-(SHAMT)) - 1)) << 1, (SRC)) \ + : (fCAST##REGSTYPE##s(SRC) >> (SHAMT))) + +#define fBIDIR_ASHIFTL_SAT(SRC, SHAMT, REGSTYPE) \ + (((SHAMT) < 0) \ + ? ((fCAST##REGSTYPE##s(SRC) >> ((-(SHAMT)) - 1)) >> 1) \ + : fSAT_ORIG_SHL(fCAST##REGSTYPE##s(SRC) << (SHAMT), (SRC))) + +#define fEXTRACTU_BIDIR(INREG, WIDTH, OFFSET) \ + (fZXTN(WIDTH, 32, fBIDIR_LSHIFTR((INREG), (OFFSET), 4_8))) + +#define fADDSAT64(DST, A, B) \ + __a =3D fCAST8u(A); \ + __b =3D fCAST8u(B); \ + __sum =3D __a + __b; \ + __xor =3D __a ^ __b; \ + __mask =3D fCAST8s(0x8000000000000000ULL); \ + if (((__a ^ __b) | ~(__a ^ __sum)) & __mask) { \ + DST =3D __sum; \ + } else { \ + DST =3D ((__sum & __mask) >> 63) + __mask; \ + fSET_OVERFLOW(); \ + } + +/* Negation operator */ +#define fLSBOLDNOT(VAL) fGETBIT(0, ~VAL) +#define fLSBNEWNOT(PNUM) (!fLSBNEW(PNUM)) +#define fLSBNEW0NOT (!fLSBNEW0) + +/* Assignments */ +#define fPCALIGN(IMM) (IMM =3D IMM & ~3) +#define fWRITE_LR(A) (LR =3D A) +#define fWRITE_FP(A) (FP =3D A) +#define fWRITE_SP(A) (SP =3D A) +#define fBRANCH(LOC, TYPE) (PC =3D LOC) +#define fJUMPR(REGNO, TARGET, TYPE) (PC =3D TARGET) +#define fWRITE_LOOP_REGS0(START, COUNT) SA0 =3D START; (LC0 =3D COUNT) +#define fWRITE_LOOP_REGS1(START, COUNT) SA1 =3D START; (LC1 =3D COUNT) +#define fWRITE_LC0(VAL) (LC0 =3D VAL) +#define fWRITE_LC1(VAL) (LC1 =3D VAL) +#define fSET_LPCFG(VAL) (USR.LPCFG =3D VAL) +#define fWRITE_P0(VAL) P0 =3D VAL; +#define fWRITE_P1(VAL) P1 =3D VAL; +#define fWRITE_P3(VAL) P3 =3D VAL; +#define fEA_RI(REG, IMM) (EA =3D REG + IMM) +#define fEA_RRs(REG, REG2, SCALE) (EA =3D REG + (REG2 << SCALE)) +#define fEA_IRs(IMM, REG, SCALE) (EA =3D IMM + (REG << SCALE)) +#define fEA_IMM(IMM) (EA =3D IMM) +#define fEA_REG(REG) (EA =3D REG) +#define fEA_BREVR(REG) (EA =3D fbrev(REG)) +#define fEA_GPI(IMM) (EA =3D fREAD_GP() + IMM) +#define fPM_I(REG, IMM) (REG =3D REG + IMM) +#define fPM_M(REG, MVAL) (REG =3D REG + MVAL) +#define fWRITE_NPC(VAL) (PC =3D VAL) + +/* Unary operators */ +#define fROUND(A) (A + 0x8000) + +/* Binary operators */ +#define fADD128(A, B) (A + B) +#define fSUB128(A, B) (A - B) +#define fSHIFTR128(A, B) (size8s_t) (A >> B) +#define fSHIFTL128(A, B) (A << B) +#define fAND128(A, B) (A & B) +#define fSCALE(N, A) (A << N) +#define fASHIFTR(SRC, SHAMT, REGSTYPE) (SRC >> SHAMT) +#define fLSHIFTR(SRC, SHAMT, REGSTYPE) (SRC >>> SHAMT) +#define fROTL(SRC, SHAMT, REGSTYPE) fROTL(SRC, SHAMT) +#define fASHIFTL(SRC, SHAMT, REGSTYPE) (fCAST##REGSTYPE##s(SRC) << SHAMT) + +/* Purge non-relavant parts */ +#define fHIDE(A) +#define fBRANCH_SPECULATE_STALL(A, B, C, D, E) diff --git a/target/hexagon/idef-parser/prepare b/target/hexagon/idef-parse= r/prepare new file mode 100755 index 0000000000..9b662dea18 --- /dev/null +++ b/target/hexagon/idef-parser/prepare @@ -0,0 +1,24 @@ +#!/bin/bash + +# +# Copyright(c) 2019-2021 rev.ng Srls. All Rights Reserved. +# +# 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 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 . +# + +set -e +set -o pipefail + +# Run the preprocessor and drop comments +cpp "$@" | grep -v '^#' diff --git a/target/hexagon/meson.build b/target/hexagon/meson.build index 15318a6fa7..2c18edf67a 100644 --- a/target/hexagon/meson.build +++ b/target/hexagon/meson.build @@ -20,6 +20,7 @@ hexagon_ss =3D ss.source_set() hex_common_py =3D 'hex_common.py' attribs_def =3D meson.current_source_dir() / 'attribs_def.h.inc' gen_tcg_h =3D meson.current_source_dir() / 'gen_tcg.h' +idef_parser_dir =3D meson.current_source_dir() / 'idef-parser' =20 # # Step 1 @@ -188,4 +189,21 @@ hexagon_ss.add(files( 'conv_emu.c', )) =20 +idef_parser_input_generated =3D custom_target( + 'idef_parser_input.h.inc', + output: 'idef_parser_input.h.inc', + input: 'gen_idef_parser_funcs.py', + depend_files: [hex_common_py], + command: [python, '@INPUT@', semantics_generated, attribs_def, gen_tcg= _h, '@OUTPUT@'], +) + +idef_parser_input_generated_prep =3D custom_target( + 'idef_parser_input.preprocessed.h.inc', + output: 'idef_parser_input.preprocessed.h.inc', + input: idef_parser_input_generated, + capture: true, + depend_files: [hex_common_py], + command: [idef_parser_dir / 'prepare', '@INPUT@', '-I' + idef_parser_d= ir], +) + target_arch +=3D {'hexagon': hexagon_ss} --=20 2.31.1 From nobody Mon Apr 29 13:24:59 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1617117127; cv=none; d=zohomail.com; s=zohoarc; b=bgAp+CROOMUbSQ+YzbqQ+R63VRJ9OD39ek8YyY7bzjaVFTHMwl2y6D9VYoxzIOIFjznhfxtLymA9NVNy7bBk36+P3PzQE25sPXoW5lFl7mVu1kPfIbxaQmSe2a6glym4GjVWtX1bawwsIwpbepIm7rk/H2FI0+28MMKG4hp+FvE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1617117127; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=z5uH72O4kN211iKfztZ7evlqZ3MCU0PqebyXX7A1wOs=; b=L5cMNAxJBYwSw6PBhJLud3BlKhQJHfD6YI4e2CD8YpcmOo9pF3MCYn/YsCowL0HENy0QzaK5CEaJeiWyHYYLpi8VjoEHQoFrRWl1DGAgaIIbVwBk+ksQmes7iRhDZewvUqDTvle7SuNKF1apeuVoptXaFn5J9jnHzMlCU5QmZzs= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1617117126880825.9150642541024; Tue, 30 Mar 2021 08:12:06 -0700 (PDT) Received: from localhost ([::1]:39524 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lRFbl-0001v4-J7 for importer@patchew.org; Tue, 30 Mar 2021 10:44:41 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:38508) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lRFVm-0003Dq-4k for qemu-devel@nongnu.org; Tue, 30 Mar 2021 10:38:30 -0400 Received: from rev.ng ([5.9.113.41]:55541) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lRFVa-0004x4-FN for qemu-devel@nongnu.org; Tue, 30 Mar 2021 10:38:29 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=rev.ng; s=dkim; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=z5uH72O4kN211iKfztZ7evlqZ3MCU0PqebyXX7A1wOs=; b=mMSXNkHl2T9/9G6N5srtmcmIXS 55TbaWxJcU4KVl8oWHoQ9Wt/2yCxq9q6Yv6WMOB/oulXhZ8LYQxELfBRP+9RQ55hQ1bbKz1H0zZAl enD85NwvgRA8Pn4JC+ZWr/+vKmuqBT/47ft2h7ERUE6V9YuqaeeUG3oscJLKq011ja6Y=; To: qemu-devel@nongnu.org Cc: tsimpson@quicinc.com, bcain@quicinc.com, babush@rev.ng, nizzo@rev.ng, philmd@redhat.com, richard.henderson@linaro.org, Alessandro Di Federico Subject: [PATCH v3 09/12] target/hexagon: import lexer for idef-parser Date: Tue, 30 Mar 2021 16:37:47 +0200 Message-Id: <20210330143750.3037824-10-ale.qemu@rev.ng> In-Reply-To: <20210330143750.3037824-1-ale.qemu@rev.ng> References: <20210330143750.3037824-1-ale.qemu@rev.ng> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=5.9.113.41; envelope-from=ale@rev.ng; helo=rev.ng X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_PASS=-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.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Reply-to: Alessandro Di Federico From: Alessandro Di Federico via X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" From: Paolo Montesel Signed-off-by: Alessandro Di Federico Signed-off-by: Paolo Montesel --- target/hexagon/idef-parser/idef-parser.h | 240 +++++++ target/hexagon/idef-parser/idef-parser.lex | 611 ++++++++++++++++++ target/hexagon/meson.build | 4 + tests/docker/dockerfiles/alpine.docker | 1 + tests/docker/dockerfiles/centos7.docker | 1 + tests/docker/dockerfiles/centos8.docker | 1 + tests/docker/dockerfiles/debian10.docker | 1 + .../dockerfiles/fedora-i386-cross.docker | 1 + .../dockerfiles/fedora-win32-cross.docker | 1 + .../dockerfiles/fedora-win64-cross.docker | 1 + tests/docker/dockerfiles/fedora.docker | 1 + tests/docker/dockerfiles/opensuse-leap.docker | 1 + tests/docker/dockerfiles/ubuntu.docker | 1 + tests/docker/dockerfiles/ubuntu1804.docker | 1 + tests/docker/dockerfiles/ubuntu2004.docker | 3 +- 15 files changed, 868 insertions(+), 1 deletion(-) create mode 100644 target/hexagon/idef-parser/idef-parser.h create mode 100644 target/hexagon/idef-parser/idef-parser.lex diff --git a/target/hexagon/idef-parser/idef-parser.h b/target/hexagon/idef= -parser/idef-parser.h new file mode 100644 index 0000000000..ecfa0174e2 --- /dev/null +++ b/target/hexagon/idef-parser/idef-parser.h @@ -0,0 +1,240 @@ +/* + * Copyright(c) 2019-2021 rev.ng Srls. All Rights Reserved. + * + * 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 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 + * 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 . + */ + +#ifndef IDEF_PARSER_H +#define IDEF_PARSER_H + +#include +#include +#include +#include + +#define TCGV_NAME_SIZE 7 +#define MAX_WRITTEN_REGS 32 +#define OFFSET_STR_LEN 32 +#define ALLOC_LIST_LEN 32 +#define ALLOC_NAME_SIZE 32 +#define INIT_LIST_LEN 32 +#define OUT_BUF_LEN (1024 * 1024) +#define SIGNATURE_BUF_LEN (128 * 1024) +#define HEADER_BUF_LEN (128 * 1024) + +/* Variadic macros to wrap the buffer printing functions */ +#define EMIT(c, ...) \ + do { \ + g_string_append_printf((c)->out_str, __VA_ARGS__); \ + } while (0) + +#define EMIT_SIG(c, ...) = \ + do { = \ + g_string_append_printf((c)->signature_str, __VA_ARGS__); = \ + } while (0) + +#define EMIT_HEAD(c, ...) = \ + do { = \ + g_string_append_printf((c)->header_str, __VA_ARGS__); = \ + } while (0) + +/** + * Type of register, assigned to the HexReg.type field + */ +typedef enum {GENERAL_PURPOSE, CONTROL, MODIFIER, DOTNEW} RegType; + +/** + * Types of control registers, assigned to the HexReg.id field + */ +typedef enum {SP, FP, LR, GP, LC0, LC1, SA0, SA1} CregType; + +/** + * Identifier string of the control registers, indexed by the CregType enum + */ +extern const char *creg_str[]; + +/** + * Semantic record of the REG tokens, identifying registers + */ +typedef struct HexReg { + CregType id; /**< Identifier of the register = */ + RegType type; /**< Type of the register = */ + unsigned bit_width; /**< Bit width of the reg, 32 or 64 bits = */ +} HexReg; + +/** + * Data structure, identifying a TCGv temporary value + */ +typedef struct HexTmp { + int index; /**< Index of the TCGv temporary value */ +} HexTmp; + +/** + * Enum of the possible immediated, an immediate is a value which is known + * at tinycode generation time, e.g. an integer value, not a TCGv + */ +enum ImmUnionTag {I, VARIABLE, VALUE, QEMU_TMP, IMM_PC, IMM_CONSTEXT}; + +/** + * Semantic record of the IMM token, identifying an immediate constant + */ +typedef struct HexImm { + union { + char id; /**< Identifier of the immediate = */ + uint64_t value; /**< Immediate value (for VALUE type immediate= s) */ + uint64_t index; /**< Index of the immediate (for int temp vars= ) */ + }; + enum ImmUnionTag type; /**< Type of the immediate = */ +} HexImm; + +/** + * Semantic record of the PRE token, identifying a predicate + */ +typedef struct HexPre { + char id; /**< Identifier of the predicate = */ +} HexPre; + +/** + * Semantic record of the SAT token, identifying the saturate operator + */ +typedef struct HexSat { + bool set_overflow; /**< Set-overflow feature for the sat operator= */ + bool is_unsigned; /**< Unsigned flag for the saturate operator = */ +} HexSat; + +/** + * Semantic record of the CAST token, identifying the cast operator + */ +typedef struct HexCast { + int bit_width; /**< Bit width of the cast operator = */ + bool is_unsigned; /**< Unsigned flag for the cast operator = */ +} HexCast; + +/** + * Semantic record of the EXTRACT token, identifying the cast operator + */ +typedef struct HexExtract { + int bit_width; /**< Bit width of the extract operator = */ + int storage_bit_width; /**< Actual bit width of the extract operator = */ + bool is_unsigned; /**< Unsigned flag for the extract operator = */ +} HexExtract; + +/** + * Semantic record of the MPY token, identifying the fMPY multiplication + * operator + */ +typedef struct HexMpy { + int first_bit_width; /**< Bit width of the first operand of fMPY op= */ + int second_bit_width; /**< Bit width of the second operand of fMPY = */ + bool first_unsigned; /**< Unsigned flag for the first operand of fM= PY */ + bool second_unsigned; /**< Unsigned flag for second operand of fMPY = */ +} HexMpy; + +/** + * Semantic record of the VARID token, identifying automatic variables + * of the input language + */ +typedef struct HexVar { + GString *name; /**< Name of the VARID automatic variable = */ +} HexVar; + +/** + * Data structure uniquely identifying an automatic VARID variable, used f= or + * keeping track of declared variable, so that any variable is declared on= ly + * once, and its properties are propagated through all the subsequent inst= ances + * of that variable + */ +typedef struct Var { + GString *name; /**< Name of the VARID automatic variable = */ + uint8_t bit_width; /**< Bit width of the VARID automatic variable= */ + bool is_unsigned; /**< Unsigned flag for the VARID automatic var= */ +} Var; + +/** + * Enum of the possible rvalue types, used in the HexValue.type field + */ +typedef enum RvalueUnionTag { + REGISTER, TEMP, IMMEDIATE, PREDICATE, VARID +} RvalueUnionTag; + +/** + * Semantic record of the rvalue token, identifying any numeric value, + * immediate or register based. The rvalue tokens are combined together + * through the use of several operators, to encode expressions + */ +typedef struct HexValue { + union { + HexReg reg; /**< rvalue of register type = */ + HexTmp tmp; /**< rvalue of temporary type = */ + HexImm imm; /**< rvalue of immediate type = */ + HexPre pre; /**< rvalue of predicate type = */ + HexVar var; /**< rvalue of automatic variable type = */ + }; + RvalueUnionTag type; /**< Type of the rvalue = */ + unsigned bit_width; /**< Bit width of the rvalue = */ + bool is_unsigned; /**< Unsigned flag for the rvalue = */ + bool is_dotnew; /**< rvalue of predicate type is dotnew? = */ + bool is_manual; /**< Opt out of automatic freeing of params = */ +} HexValue; + +/** + * Operator type, used for referencing the correct operator when calling t= he + * gen_bin_op() function, which in turn will generate the correct code to + * execute the operation between the two rvalues + */ +typedef enum OpType { + ADD_OP, SUB_OP, MUL_OP, ASL_OP, ASR_OP, LSR_OP, ANDB_OP, ORB_OP, + XORB_OP, ANDL_OP, MINI_OP, MAXI_OP, MOD_OP +} OpType; + +/** + * Data structure including instruction specific information, to be cleared + * out after the compilation of each instruction + */ +typedef struct Inst { + GString *name; /**< Name of the compiled instruction = */ + char *code_begin; /**< Beginning of instruction input code= */ + char *code_end; /**< End of instruction input code = */ + int tmp_count; /**< Index of the last declared TCGv tem= p */ + int qemu_tmp_count; /**< Index of the last declared int temp= */ + int if_count; /**< Index of the last declared if label= */ + int error_count; /**< Number of generated errors = */ + GArray *allocated; /**< Allocated VARID automatic vars = */ + GArray *init_list; /**< List of initialized registers = */ + GArray *strings; /**< Strings allocated by the instructio= n */ +} Inst; + +/** + * Data structure representing the whole translation context, which in a + * reentrant flex/bison parser just like ours is passed between the scanner + * and the parser, holding all the necessary information to perform the + * parsing, this data structure survives between the compilation of differ= ent + * instructions + * + */ +typedef struct Context { + void *scanner; /**< Reentrant parser state pointer = */ + char *input_buffer; /**< Buffer containing the input code = */ + GString *out_str; /**< String containing the output code = */ + GString *signature_str; /**< String containing the signatures co= de */ + GString *header_str; /**< String containing the output code = */ + FILE *defines_file; /**< FILE * of the generated header = */ + FILE *output_file; /**< FILE * of the C output file = */ + FILE *enabled_file; /**< FILE * of the list of enabled inst = */ + int total_insn; /**< Number of instructions in input fil= e */ + int implemented_insn; /**< Instruction compiled without errors= */ + Inst inst; /**< Parsing data of the current inst = */ +} Context; + +#endif /* IDEF_PARSER_H */ diff --git a/target/hexagon/idef-parser/idef-parser.lex b/target/hexagon/id= ef-parser/idef-parser.lex new file mode 100644 index 0000000000..7593c9392b --- /dev/null +++ b/target/hexagon/idef-parser/idef-parser.lex @@ -0,0 +1,611 @@ +%option noyywrap noinput nounput +%option 8bit reentrant bison-bridge +%option warn nodefault +%option bison-locations + +%{ +/* + * Copyright(c) 2019-2021 rev.ng Srls. All Rights Reserved. + * + * 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 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 . + */ + +#include +#include + +#include "idef-parser.h" +#include "idef-parser.tab.h" + +/* Keep track of scanner position for error message printout */ +#define YY_USER_ACTION yylloc->first_column =3D yylloc->last_column; \ + for (int i =3D 0; yytext[i] !=3D '\0'; i++) { \ + yylloc->last_column++; \ + } + +/* Global Error Counter */ +int error_count; + +%} + +/* Definitions */ +DIGIT [0-9] +LOWER_ID [a-z] +UPPER_ID [A-Z] +ID LOWER_ID|UPPER_ID +INST_NAME [A-Z]+[0-9]_([A-Za-z]|[0-9]|_)+ +HEX_DIGIT [0-9a-fA-F] +REG_ID_32 e|s|d|t|u|v|x|y +REG_ID_64 ee|ss|dd|tt|uu|vv|xx|yy +SYS_ID_32 s|d +SYS_ID_64 ss|dd +LOWER_PRE d|s|t|u|v|e|x|x +IMM_ID r|s|S|u|U +VAR_ID [a-zA-Z_][a-zA-Z0-9_]* +SIGN_ID s|u + +/* Tokens */ +%% + +[ \t\f\v]+ { /* Ignore whitespaces. */ } +[\n\r]+ { /* Ignore newlines. */ } + +{INST_NAME} { yylval->string =3D g_string_new(yytext); + return INAME; } +"fFLOAT" | +"fUNFLOAT" | +"fDOUBLE" | +"fUNDOUBLE" | +"0.0" | +"0x1.0p52" | +"0x1.0p-52" { return FAIL; } +"R"{REG_ID_32}"V" { + yylval->rvalue.type =3D REGISTER; + yylval->rvalue.reg.type =3D GENERAL_PURPOSE; + yylval->rvalue.reg.id =3D yytext[1]; + yylval->rvalue.reg.bit_width =3D 32; + yylval->rvalue.bit_width =3D 32; + yylval->rvalue.is_dotnew =3D false; + return REG; } +"R"{REG_ID_32}"N" { + yylval->rvalue.type =3D REGISTER; + yylval->rvalue.reg.type =3D DOTNEW; + yylval->rvalue.reg.id =3D yytext[1]; + yylval->rvalue.reg.bit_width =3D 32; + yylval->rvalue.bit_width =3D 32; + yylval->rvalue.is_dotnew =3D true; + return REG; } +"R"{REG_ID_64}"V" { + yylval->rvalue.type =3D REGISTER; + yylval->rvalue.reg.type =3D GENERAL_PURPOSE; + yylval->rvalue.reg.id =3D yytext[1]; + yylval->rvalue.reg.bit_width =3D 64; + yylval->rvalue.bit_width =3D 64; + yylval->rvalue.is_dotnew =3D false; + return REG; } +"R"{REG_ID_64}"N" { + yylval->rvalue.type =3D REGISTER; + yylval->rvalue.reg.type =3D DOTNEW; + yylval->rvalue.reg.id =3D yytext[1]; + yylval->rvalue.reg.bit_width =3D 64; + yylval->rvalue.bit_width =3D 64; + yylval->rvalue.is_dotnew =3D true; + return REG; } +"MuV" { + yylval->rvalue.type =3D REGISTER; + yylval->rvalue.reg.type =3D MODIFIER; + yylval->rvalue.reg.id =3D 'u'; + yylval->rvalue.reg.bit_width =3D 32; + yylval->rvalue.bit_width =3D 32; + return REG; } +"C"{REG_ID_32}"V" { + yylval->rvalue.type =3D REGISTER; + yylval->rvalue.reg.type =3D CONTROL; + yylval->rvalue.reg.id =3D yytext[1]; + yylval->rvalue.reg.bit_width =3D 32; + yylval->rvalue.bit_width =3D 32; + yylval->rvalue.is_dotnew =3D false; + return REG; } +"C"{REG_ID_64}"V" { + yylval->rvalue.type =3D REGISTER; + yylval->rvalue.reg.type =3D CONTROL; + yylval->rvalue.reg.id =3D yytext[1]; + yylval->rvalue.reg.bit_width =3D 64; + yylval->rvalue.bit_width =3D 64; + yylval->rvalue.is_dotnew =3D false; + return REG; } +{IMM_ID}"iV" { + yylval->rvalue.type =3D IMMEDIATE; + yylval->rvalue.is_unsigned =3D false; + yylval->rvalue.imm.type =3D VARIABLE; + yylval->rvalue.imm.id =3D yytext[0]; + yylval->rvalue.is_dotnew =3D false; + return IMM; } +"P"{LOWER_PRE}"V" { + yylval->rvalue.type =3D PREDICATE; + yylval->rvalue.pre.id =3D yytext[1]; + yylval->rvalue.bit_width =3D 32; + yylval->rvalue.is_dotnew =3D false; + return PRE; } +"P"{LOWER_PRE}"N" { + yylval->rvalue.type =3D PREDICATE; + yylval->rvalue.pre.id =3D yytext[1]; + yylval->rvalue.bit_width =3D 32; + yylval->rvalue.is_dotnew =3D true; + return PRE; } +"in R"{REG_ID_32}"V" { + yylval->rvalue.type =3D REGISTER; + yylval->rvalue.reg.type =3D GENERAL_PURPOSE; + yylval->rvalue.reg.id =3D yytext[4]; + yylval->rvalue.reg.bit_width =3D 32; + yylval->rvalue.bit_width =3D 32; + yylval->rvalue.is_dotnew =3D false; + return RREG; } +"in R"{REG_ID_64}"V" { + yylval->rvalue.type =3D REGISTER; + yylval->rvalue.reg.type =3D GENERAL_PURPOSE; + yylval->rvalue.reg.id =3D yytext[4]; + yylval->rvalue.reg.bit_width =3D 64; + yylval->rvalue.bit_width =3D 64; + yylval->rvalue.is_dotnew =3D false; + return RREG; } +"in N"{REG_ID_32}"N" { + yylval->rvalue.type =3D REGISTER; + yylval->rvalue.reg.type =3D DOTNEW; + yylval->rvalue.reg.id =3D yytext[4]; + yylval->rvalue.reg.bit_width =3D 32; + yylval->rvalue.bit_width =3D 32; + yylval->rvalue.is_dotnew =3D true; + return RREG; } +"in N"{REG_ID_64}"N" { + yylval->rvalue.type =3D REGISTER; + yylval->rvalue.reg.type =3D DOTNEW; + yylval->rvalue.reg.id =3D yytext[4]; + yylval->rvalue.reg.bit_width =3D 64; + yylval->rvalue.bit_width =3D 64; + yylval->rvalue.is_dotnew =3D true; + return RREG; } +"in P"{LOWER_PRE}"V" { + yylval->rvalue.type =3D PREDICATE; + yylval->rvalue.pre.id =3D yytext[4]; + yylval->rvalue.bit_width =3D 32; + yylval->rvalue.is_dotnew =3D false; + return RPRE; } +"in P"{LOWER_PRE}"N" { + yylval->rvalue.type =3D PREDICATE; + yylval->rvalue.pre.id =3D yytext[4]; + yylval->rvalue.bit_width =3D 32; + yylval->rvalue.is_dotnew =3D true; + return RPRE; } +"in MuV" { + yylval->rvalue.type =3D REGISTER; + yylval->rvalue.reg.type =3D MODIFIER; + yylval->rvalue.reg.id =3D 'u'; + yylval->rvalue.reg.bit_width =3D 32; + yylval->rvalue.bit_width =3D 32; + return RREG; } +"in C"{REG_ID_32}"V" { + yylval->rvalue.type =3D REGISTER; + yylval->rvalue.reg.type =3D CONTROL; + yylval->rvalue.reg.id =3D yytext[4]; + yylval->rvalue.reg.bit_width =3D 32; + yylval->rvalue.bit_width =3D 32; + yylval->rvalue.is_dotnew =3D false; + return RREG; } +"in C"{REG_ID_64}"V" { + yylval->rvalue.type =3D REGISTER; + yylval->rvalue.reg.type =3D CONTROL; + yylval->rvalue.reg.id =3D yytext[4]; + yylval->rvalue.reg.bit_width =3D 64; + yylval->rvalue.bit_width =3D 64; + yylval->rvalue.is_dotnew =3D false; + return RREG; } +"fGEN_TCG_"{INST_NAME}"(" { return FWRAP; } +"IV1DEAD()" | +"fPAUSE(uiV);" { return ';'; } +"**" { return POW; } +"+=3D" { return INC; } +"-=3D" { return DEC; } +"++" { return PLUSPLUS; } +"&=3D" { return ANDA; } +"|=3D" { return ORA; } +"^=3D" { return XORA; } +"<<" { return ASL; } +">>" { return ASR; } +">>>" { return LSR; } +"=3D=3D" { return EQ; } +"!=3D" { return NEQ; } +"<=3D" { return LTE; } +">=3D" { return GTE; } +"&&" { return ANDL; } +"||" { return ORL; } +"else" { return ELSE; } +"for" { return FOR; } +"fREAD_IREG" { return ICIRC; } +"fPART1" { return PART1; } +"if" { return IF; } +"fFRAME_SCRAMBLE" { return FSCR; } +"fFRAME_UNSCRAMBLE" { return FSCR; } +"fFRAMECHECK" { return FCHK; } +"Constant_extended" { return CONSTEXT; } +"fCL1_"{DIGIT} { return LOCNT; } +"fBREV_8" { return BREV_8; } +"fBREV_4" { return BREV_4; } +"fbrev" { return BREV; } +"fSXTN" { return SXT; } +"fZXTN" { return ZXT; } +"fDF_MAX" | +"fSF_MAX" | +"fMAX" { return MAX; } +"fDF_MIN" | +"fSF_MIN" | +"fMIN" { return MIN; } +"fABS" { return ABS; } +"fRNDN" { return ROUND; } +"fCRND" { return CROUND; } +"fCRNDN" { return CROUND; } +"fPM_CIRI" { return CIRCADD; } +"fPM_CIRR" { return CIRCADD; } +"fCOUNTONES_"{DIGIT} { return COUNTONES; } +"fSATN" { yylval->sat.set_overflow =3D false; + yylval->sat.is_unsigned =3D false; + return SAT; } +"fVSATN" { yylval->sat.set_overflow =3D true; + yylval->sat.is_unsigned =3D false; + return SAT; } +"fSATUN" { yylval->sat.set_overflow =3D false; + yylval->sat.is_unsigned =3D true; + return SAT; } +"fSE32_64" { yylval->cast.bit_width =3D 64; + yylval->cast.is_unsigned =3D false; + return CAST; } +"fCAST4_4u" { yylval->cast.bit_width =3D 32; + yylval->cast.is_unsigned =3D true; + return CAST; } +"fCAST4_8s" { yylval->cast.bit_width =3D 64; + yylval->cast.is_unsigned =3D false; + return CAST; } +"fCAST4_8u" { return CAST4_8U; } +"fCAST4u" { yylval->cast.bit_width =3D 32; + yylval->cast.is_unsigned =3D true; + return CAST; } +"fCAST4s" { yylval->cast.bit_width =3D 32; + yylval->cast.is_unsigned =3D false; + return CAST; } +"fCAST8_8u" { yylval->cast.bit_width =3D 64; + yylval->cast.is_unsigned =3D true; + return CAST; } +"fCAST8u" { yylval->cast.bit_width =3D 64; + yylval->cast.is_unsigned =3D true; + return CAST; } +"fCAST8s" { yylval->cast.bit_width =3D 64; + yylval->cast.is_unsigned =3D false; + return CAST; } +"fGETBIT" { yylval->extract.bit_width =3D 1; + yylval->extract.storage_bit_width =3D 1; + yylval->extract.is_unsigned =3D true; + return EXTRACT; } +"fGETBYTE" { yylval->extract.bit_width =3D 8; + yylval->extract.storage_bit_width =3D 8; + yylval->extract.is_unsigned =3D false; + return EXTRACT; } +"fGETUBYTE" { yylval->extract.bit_width =3D 8; + yylval->extract.storage_bit_width =3D 8; + yylval->extract.is_unsigned =3D true; + return EXTRACT; } +"fGETHALF" { yylval->extract.bit_width =3D 16; + yylval->extract.storage_bit_width =3D 16; + yylval->extract.is_unsigned =3D false; + return EXTRACT; } +"fGETUHALF" { yylval->extract.bit_width =3D 16; + yylval->extract.storage_bit_width =3D 16; + yylval->extract.is_unsigned =3D true; + return EXTRACT; } +"fGETWORD" { yylval->extract.bit_width =3D 32; + yylval->extract.storage_bit_width =3D 64; + yylval->extract.is_unsigned =3D false; + return EXTRACT; } +"fGETUWORD" { yylval->extract.bit_width =3D 32; + yylval->extract.storage_bit_width =3D 64; + yylval->extract.is_unsigned =3D true; + return EXTRACT; } +"fEXTRACTU_BITS" { return EXTBITS; } +"fEXTRACTU_RANGE" { return EXTRANGE; } +"fSETBIT" { yylval->cast.bit_width =3D 1; + yylval->cast.is_unsigned =3D false; + return DEPOSIT; } +"fSETBYTE" { yylval->cast.bit_width =3D 8; + yylval->cast.is_unsigned =3D false; + return DEPOSIT; } +"fSETHALF" { yylval->cast.bit_width =3D 16; + yylval->cast.is_unsigned =3D false; + return SETHALF; } +"fSETWORD" { yylval->cast.bit_width =3D 32; + yylval->cast.is_unsigned =3D false; + return DEPOSIT; } +"fINSERT_BITS" { return INSBITS; } +"fSETBITS" { return SETBITS; } +"fMPY8UU" { yylval->mpy.first_bit_width =3D 8; + yylval->mpy.second_bit_width =3D 8; + yylval->mpy.first_unsigned =3D true; + yylval->mpy.second_unsigned =3D true; + return MPY; } +"fMPY8US" { yylval->mpy.first_bit_width =3D 8; + yylval->mpy.second_bit_width =3D 8; + yylval->mpy.first_unsigned =3D true; + yylval->mpy.second_unsigned =3D false; + return MPY; } +"fMPY8SU" { yylval->mpy.first_bit_width =3D 8; + yylval->mpy.second_bit_width =3D 8; + yylval->mpy.first_unsigned =3D false; + yylval->mpy.second_unsigned =3D true; + return MPY; } +"fMPY8SS" { yylval->mpy.first_bit_width =3D 8; + yylval->mpy.second_bit_width =3D 8; + yylval->mpy.first_unsigned =3D false; + yylval->mpy.second_unsigned =3D false; + return MPY; } +"fMPY16UU" { yylval->mpy.first_bit_width =3D 16; + yylval->mpy.second_bit_width =3D 16; + yylval->mpy.first_unsigned =3D true; + yylval->mpy.second_unsigned =3D true; + return MPY; } +"fMPY16US" { yylval->mpy.first_bit_width =3D 16; + yylval->mpy.second_bit_width =3D 16; + yylval->mpy.first_unsigned =3D true; + yylval->mpy.second_unsigned =3D false; + return MPY; } +"fMPY16SU" { yylval->mpy.first_bit_width =3D 16; + yylval->mpy.second_bit_width =3D 16; + yylval->mpy.first_unsigned =3D false; + yylval->mpy.second_unsigned =3D true; + return MPY; } +"fMPY16SS" { yylval->mpy.first_bit_width =3D 16; + yylval->mpy.second_bit_width =3D 16; + yylval->mpy.first_unsigned =3D false; + yylval->mpy.second_unsigned =3D false; + return MPY; } +"fMPY32UU" { yylval->mpy.first_bit_width =3D 32; + yylval->mpy.second_bit_width =3D 32; + yylval->mpy.first_unsigned =3D true; + yylval->mpy.second_unsigned =3D true; + return MPY; } +"fMPY32US" { yylval->mpy.first_bit_width =3D 32; + yylval->mpy.second_bit_width =3D 32; + yylval->mpy.first_unsigned =3D true; + yylval->mpy.second_unsigned =3D false; + return MPY; } +"fMPY32SU" { yylval->mpy.first_bit_width =3D 32; + yylval->mpy.second_bit_width =3D 32; + yylval->mpy.first_unsigned =3D false; + yylval->mpy.second_unsigned =3D true; + return MPY; } +"fSFMPY" | +"fMPY32SS" { yylval->mpy.first_bit_width =3D 32; + yylval->mpy.second_bit_width =3D 32; + yylval->mpy.first_unsigned =3D false; + yylval->mpy.second_unsigned =3D false; + return MPY; } +"fMPY3216SS" { yylval->mpy.first_bit_width =3D 32; + yylval->mpy.second_bit_width =3D 16; + yylval->mpy.first_unsigned =3D false; + yylval->mpy.second_unsigned =3D false; + return MPY; } +"fMPY3216SU" { yylval->mpy.first_bit_width =3D 32; + yylval->mpy.second_bit_width =3D 16; + yylval->mpy.first_unsigned =3D false; + yylval->mpy.second_unsigned =3D true; + return MPY; } +"fNEWREG" | +"fNEWREG_ST" | +"fIMMEXT" | +"fMUST_IMMEXT" | +"fCAST2_2s" | +"fCAST2_2u" | +"fCAST4_4s" | +"fCAST8_8s" | +"fZE8_16" | +"fSE8_16" | +"fZE16_32" | +"fSE16_32" | +"fZE32_64" | +"fPASS" | +"fECHO" { return IDENTITY; } +"(size8"[us]"_t)" { yylval->cast.bit_width =3D 8; + yylval->cast.is_unsigned =3D ((yytext[6]) =3D= =3D 'u'); + return CAST; } +"(size16"[us]"_t)" { yylval->cast.bit_width =3D 16; + yylval->cast.is_unsigned =3D ((yytext[7]) =3D= =3D 'u'); + return CAST; } +"(int)" { yylval->cast.bit_width =3D 32; + yylval->cast.is_unsigned =3D false; + return CAST; } +"(unsigned int)" { yylval->cast.bit_width =3D 32; + yylval->cast.is_unsigned =3D true; + return CAST; } +"fREAD_PC()" | +"PC" { return PC; } +"fREAD_NPC()" | +"NPC" { return NPC; } +"fGET_LPCFG" | +"USR.LPCFG" { return LPCFG; } +"LOAD_CANCEL(EA)" | +"STORE_CANCEL(EA)" | +"CANCEL" { return CANCEL; } +"N"{LOWER_ID} { yylval->rvalue.type =3D REGISTER; + yylval->rvalue.reg.type =3D GENERAL_PURPOSE; + yylval->rvalue.reg.id =3D yytext[1]; + yylval->rvalue.reg.bit_width =3D 32; + yylval->rvalue.bit_width =3D 32; + return REG; } +"N"{LOWER_ID}"N" { yylval->rvalue.type =3D REGISTER; + yylval->rvalue.reg.type =3D DOTNEW; + yylval->rvalue.reg.id =3D yytext[1]; + yylval->rvalue.reg.bit_width =3D 32; + yylval->rvalue.bit_width =3D 32; + return REG; } +[rR]{DIGIT}+ { yylval->rvalue.type =3D REGISTER; + yylval->rvalue.reg.type =3D GENERAL_PURPOSE; + yylval->rvalue.reg.id =3D atoi(yytext + 1); + yylval->rvalue.reg.bit_width =3D 32; + yylval->rvalue.bit_width =3D 32; + return REG; } +"fREAD_SP()" | +"SP" { yylval->rvalue.type =3D REGISTER; + yylval->rvalue.reg.type =3D CONTROL; + yylval->rvalue.reg.id =3D SP; + yylval->rvalue.reg.bit_width =3D 32; + yylval->rvalue.bit_width =3D 32; + return REG; } +"fREAD_FP()" | +"FP" { yylval->rvalue.type =3D REGISTER; + yylval->rvalue.reg.type =3D CONTROL; + yylval->rvalue.reg.id =3D FP; + yylval->rvalue.reg.bit_width =3D 32; + yylval->rvalue.bit_width =3D 32; + return REG; } +"fREAD_LR()" | +"LR" { yylval->rvalue.type =3D REGISTER; + yylval->rvalue.reg.type =3D CONTROL; + yylval->rvalue.reg.id =3D LR; + yylval->rvalue.reg.bit_width =3D 32; + yylval->rvalue.bit_width =3D 32; + return REG; } +"GP" { yylval->rvalue.type =3D REGISTER; + yylval->rvalue.reg.type =3D CONTROL; + yylval->rvalue.reg.id =3D GP; + yylval->rvalue.reg.bit_width =3D 32; + yylval->rvalue.bit_width =3D 32; + return REG; } +"fREAD_LC"[01] { yylval->rvalue.type =3D REGISTER; + yylval->rvalue.reg.type =3D CONTROL; + yylval->rvalue.reg.id =3D LC0 + (yytext[8] - '0= '); + yylval->rvalue.reg.bit_width =3D 32; + yylval->rvalue.bit_width =3D 32; + return REG; } +"LC"[01] { yylval->rvalue.type =3D REGISTER; + yylval->rvalue.reg.type =3D CONTROL; + yylval->rvalue.reg.id =3D LC0 + (yytext[2] - '0= '); + yylval->rvalue.reg.bit_width =3D 32; + yylval->rvalue.bit_width =3D 32; + return REG; } +"fREAD_SA"[01] { yylval->rvalue.type =3D REGISTER; + yylval->rvalue.reg.type =3D CONTROL; + yylval->rvalue.reg.id =3D SA0 + (yytext[8] - '0= '); + yylval->rvalue.reg.bit_width =3D 32; + yylval->rvalue.bit_width =3D 32; + return REG; } +"SA"[01] { yylval->rvalue.type =3D REGISTER; + yylval->rvalue.reg.type =3D CONTROL; + yylval->rvalue.reg.id =3D SA0 + (yytext[2] - '0= '); + yylval->rvalue.reg.bit_width =3D 32; + yylval->rvalue.bit_width =3D 32; + return REG; } +"MuN" { return MUN; } +"fREAD_P0()" { yylval->rvalue.type =3D PREDICATE; + yylval->rvalue.pre.id =3D '0'; + yylval->rvalue.bit_width =3D 32; + return PRE; } +[pP]{DIGIT} { yylval->rvalue.type =3D PREDICATE; + yylval->rvalue.pre.id =3D yytext[1]; + yylval->rvalue.bit_width =3D 32; + return PRE; } +"fLSBNEW(P"{LOWER_PRE}"N)" { yylval->rvalue.type =3D PREDICATE; + yylval->rvalue.pre.id =3D yytext[9]; + yylval->rvalue.bit_width =3D 32; + yylval->rvalue.is_dotnew =3D true; + return PRE; } +"fLSBNEW0" { yylval->rvalue.type =3D PREDICATE; + yylval->rvalue.pre.id =3D '0'; + yylval->rvalue.bit_width =3D 32; + yylval->rvalue.is_dotnew =3D true; + return PRE; } +"fLSBNEW1" { yylval->rvalue.type =3D PREDICATE; + yylval->rvalue.pre.id =3D '1'; + yylval->rvalue.bit_width =3D 32; + yylval->rvalue.is_dotnew =3D true; + return PRE; } +"fLSBNEW1NOT" { yylval->rvalue.type =3D PREDICATE; + yylval->rvalue.pre.id =3D '1'; + yylval->rvalue.bit_width =3D 32; + yylval->rvalue.is_dotnew =3D true; + return PRE; } +"N" { yylval->rvalue.type =3D IMMEDIATE; + yylval->rvalue.bit_width =3D 32; + yylval->rvalue.imm.type =3D VARIABLE; + yylval->rvalue.imm.id =3D 'N'; + return IMM; } +"i" { yylval->rvalue.type =3D IMMEDIATE; + yylval->rvalue.bit_width =3D 32; + yylval->rvalue.imm.type =3D I; + return IMM; } +{SIGN_ID} { yylval->is_unsigned =3D (yytext[0] =3D=3D 'u'); + return SIGN; + } +"fSF_BIAS()" { yylval->rvalue.type =3D IMMEDIATE; + yylval->rvalue.bit_width =3D 32; + yylval->rvalue.is_unsigned =3D false; + yylval->rvalue.imm.type =3D VALUE; + yylval->rvalue.imm.value =3D 127; + return IMM; } +{DIGIT}+ { yylval->rvalue.type =3D IMMEDIATE; + yylval->rvalue.bit_width =3D 64; + yylval->rvalue.is_unsigned =3D false; + yylval->rvalue.imm.type =3D VALUE; + yylval->rvalue.imm.value =3D atoi(yytext); + return IMM; } +{DIGIT}+"LL" { yylval->rvalue.type =3D IMMEDIATE; + yylval->rvalue.bit_width =3D 64; + yylval->rvalue.is_unsigned =3D false; + yylval->rvalue.imm.type =3D VALUE; + yylval->rvalue.imm.value =3D strtoll(yytext, NU= LL, 10); + return IMM; } +"0x"{HEX_DIGIT}+ { yylval->rvalue.type =3D IMMEDIATE; + yylval->rvalue.bit_width =3D 32; + yylval->rvalue.is_unsigned =3D false; + yylval->rvalue.imm.type =3D VALUE; + yylval->rvalue.imm.value =3D strtoul(yytext, NU= LL, 16); + return IMM; } +"0x"{HEX_DIGIT}+"LL" { yylval->rvalue.type =3D IMMEDIATE; + yylval->rvalue.bit_width =3D 64; + yylval->rvalue.is_unsigned =3D false; + yylval->rvalue.imm.type =3D VALUE; + yylval->rvalue.imm.value =3D strtoll(yytext, NU= LL, 16); + return IMM; } +"0x"{HEX_DIGIT}+"ULL" { yylval->rvalue.type =3D IMMEDIATE; + yylval->rvalue.bit_width =3D 64; + yylval->rvalue.is_unsigned =3D true; + yylval->rvalue.imm.type =3D VALUE; + yylval->rvalue.imm.value =3D strtoull(yytext, + NULL, + 16); + return IMM; } +"fCONSTLL" { return CONSTLL; } +"fCONSTULL" { return CONSTULL; } +"fLOAD" { return LOAD; } +"fSTORE" { return STORE; } +"fROTL" { return ROTL; } +"fSET_OVERFLOW" { return SETOVF; } +"fDEINTERLEAVE" { return DEINTERLEAVE; } +"fINTERLEAVE" { return INTERLEAVE; } +"fCARRY_FROM_ADD" { return CARRY_FROM_ADD; } +{VAR_ID} { /* Variable name, we adopt the C names conventi= on */ + yylval->rvalue.type =3D VARID; + yylval->rvalue.var.name =3D g_string_new(yytext= ); + /* Default types are int */ + yylval->rvalue.bit_width =3D 32; + return VAR; } +"fHINTJR(RsV)" { /* Emit no token */ } +. { return yytext[0]; } + +%% diff --git a/target/hexagon/meson.build b/target/hexagon/meson.build index 2c18edf67a..5dda04dc29 100644 --- a/target/hexagon/meson.build +++ b/target/hexagon/meson.build @@ -206,4 +206,8 @@ idef_parser_input_generated_prep =3D custom_target( command: [idef_parser_dir / 'prepare', '@INPUT@', '-I' + idef_parser_d= ir], ) =20 +flex =3D generator(find_program('flex'), + output: ['@BASENAME@.yy.c', '@BASENAME@.yy.h'], + arguments: ['-o', '@OUTPUT0@', '--header-file=3D@OUTPUT1@= ', '@INPUT@']) + target_arch +=3D {'hexagon': hexagon_ss} diff --git a/tests/docker/dockerfiles/alpine.docker b/tests/docker/dockerfi= les/alpine.docker index d63a269aef..1120e8555d 100644 --- a/tests/docker/dockerfiles/alpine.docker +++ b/tests/docker/dockerfiles/alpine.docker @@ -11,6 +11,7 @@ ENV PACKAGES \ binutils \ coreutils \ curl-dev \ + flex \ g++ \ gcc \ git \ diff --git a/tests/docker/dockerfiles/centos7.docker b/tests/docker/dockerf= iles/centos7.docker index 75fdb53c7c..95966ea7e6 100644 --- a/tests/docker/dockerfiles/centos7.docker +++ b/tests/docker/dockerfiles/centos7.docker @@ -10,6 +10,7 @@ ENV PACKAGES \ ccache \ csnappy-devel \ dbus-daemon \ + flex \ gcc-c++ \ gcc \ gettext \ diff --git a/tests/docker/dockerfiles/centos8.docker b/tests/docker/dockerf= iles/centos8.docker index a763d55730..5919aa0697 100644 --- a/tests/docker/dockerfiles/centos8.docker +++ b/tests/docker/dockerfiles/centos8.docker @@ -7,6 +7,7 @@ ENV PACKAGES \ bzip2-devel \ dbus-daemon \ diffutils \ + flex \ gcc \ gcc-c++ \ genisoimage \ diff --git a/tests/docker/dockerfiles/debian10.docker b/tests/docker/docker= files/debian10.docker index d034acbd25..97ec6d5637 100644 --- a/tests/docker/dockerfiles/debian10.docker +++ b/tests/docker/dockerfiles/debian10.docker @@ -23,6 +23,7 @@ RUN apt update && \ ccache \ clang \ dbus \ + flex \ gdb-multiarch \ gettext \ git \ diff --git a/tests/docker/dockerfiles/fedora-i386-cross.docker b/tests/dock= er/dockerfiles/fedora-i386-cross.docker index 966072c08e..9703b7ec78 100644 --- a/tests/docker/dockerfiles/fedora-i386-cross.docker +++ b/tests/docker/dockerfiles/fedora-i386-cross.docker @@ -3,6 +3,7 @@ ENV PACKAGES \ bzip2 \ diffutils \ findutils \ + flex \ gcc \ git \ libtasn1-devel.i686 \ diff --git a/tests/docker/dockerfiles/fedora-win32-cross.docker b/tests/doc= ker/dockerfiles/fedora-win32-cross.docker index 81b5659e9c..2018dcabe5 100644 --- a/tests/docker/dockerfiles/fedora-win32-cross.docker +++ b/tests/docker/dockerfiles/fedora-win32-cross.docker @@ -6,6 +6,7 @@ ENV PACKAGES \ bzip2 \ diffutils \ findutils \ + flex \ gcc \ gettext \ git \ diff --git a/tests/docker/dockerfiles/fedora-win64-cross.docker b/tests/doc= ker/dockerfiles/fedora-win64-cross.docker index bcb428e724..b05e4cbcc6 100644 --- a/tests/docker/dockerfiles/fedora-win64-cross.docker +++ b/tests/docker/dockerfiles/fedora-win64-cross.docker @@ -6,6 +6,7 @@ ENV PACKAGES \ bzip2 \ diffutils \ findutils \ + flex \ gcc \ gettext \ git \ diff --git a/tests/docker/dockerfiles/fedora.docker b/tests/docker/dockerfi= les/fedora.docker index 915fdc1845..5d3f49936b 100644 --- a/tests/docker/dockerfiles/fedora.docker +++ b/tests/docker/dockerfiles/fedora.docker @@ -14,6 +14,7 @@ ENV PACKAGES \ device-mapper-multipath-devel \ diffutils \ findutils \ + flex \ gcc \ gcc-c++ \ genisoimage \ diff --git a/tests/docker/dockerfiles/opensuse-leap.docker b/tests/docker/d= ockerfiles/opensuse-leap.docker index 0e64893e4a..ce1db959a2 100644 --- a/tests/docker/dockerfiles/opensuse-leap.docker +++ b/tests/docker/dockerfiles/opensuse-leap.docker @@ -6,6 +6,7 @@ ENV PACKAGES \ brlapi-devel \ bzip2 \ cyrus-sasl-devel \ + flex \ gcc \ gcc-c++ \ mkisofs \ diff --git a/tests/docker/dockerfiles/ubuntu.docker b/tests/docker/dockerfi= les/ubuntu.docker index b5ef7a8198..e2f55eb892 100644 --- a/tests/docker/dockerfiles/ubuntu.docker +++ b/tests/docker/dockerfiles/ubuntu.docker @@ -14,6 +14,7 @@ ENV PACKAGES \ ccache \ clang \ dbus \ + flex \ gcc \ gettext \ git \ diff --git a/tests/docker/dockerfiles/ubuntu1804.docker b/tests/docker/dock= erfiles/ubuntu1804.docker index 9b0a19ba5e..2068118180 100644 --- a/tests/docker/dockerfiles/ubuntu1804.docker +++ b/tests/docker/dockerfiles/ubuntu1804.docker @@ -2,6 +2,7 @@ FROM ubuntu:18.04 ENV PACKAGES \ ccache \ clang \ + flex \ gcc \ gettext \ git \ diff --git a/tests/docker/dockerfiles/ubuntu2004.docker b/tests/docker/dock= erfiles/ubuntu2004.docker index 9750016e51..13d43a7b90 100644 --- a/tests/docker/dockerfiles/ubuntu2004.docker +++ b/tests/docker/dockerfiles/ubuntu2004.docker @@ -1,8 +1,9 @@ FROM ubuntu:20.04 -ENV PACKAGES flex bison \ +ENV PACKAGES bison \ bsdmainutils \ ccache \ clang-10\ + flex \ gcc \ gcovr \ genisoimage \ --=20 2.31.1 From nobody Mon Apr 29 13:24:59 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1617118198; cv=none; d=zohomail.com; s=zohoarc; b=Hj8+OCPh5b1xQxlobYeLitFeRtmbrtnMi11lDojEGviTy7E0Setpv6YG7r5v5cNfXDD4fB1FrCH3+6CnhhLOMqa73HG0+34GRBxGWjxYLx/Uev/MDITt4kb/DKZ82RgG3PSJm+p7jAoBc4CJx5gQ6I60W9dcoO4WCqZbfAdtlro= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1617118198; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=qQSKDTMx7Ayf0+fx40LBYGduvBs84fR2cXgf8peB/VU=; b=XTKfXdTmSF1q6+SiidzDKwgl7NQFUe0SZPCWe+GkOoE+TZeN9yj2PXrcZxSOK8KTEQdWM1/l5zc1z1xXc0XsbzFcTpKfb9E9kX2d6fQru2jViqwMZNrBEww8dNEVJGrkgUVFOpZwYwB/kNFK8ujMgsWqoFpE+LIwlBoD4Yn0TzA= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1617118198441575.4987983297618; Tue, 30 Mar 2021 08:29:58 -0700 (PDT) Received: from localhost ([::1]:36008 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lRFjw-0003oK-GG for importer@patchew.org; Tue, 30 Mar 2021 10:53:08 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:38564) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lRFVp-0003Mx-KK for qemu-devel@nongnu.org; Tue, 30 Mar 2021 10:38:33 -0400 Received: from rev.ng ([5.9.113.41]:51543) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lRFVe-0004x8-0i for qemu-devel@nongnu.org; Tue, 30 Mar 2021 10:38:33 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=rev.ng; s=dkim; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=qQSKDTMx7Ayf0+fx40LBYGduvBs84fR2cXgf8peB/VU=; b=ROLC1cnECaZhv9waPNaLT+b1yv jCT17dIGa7U2XR8k19BEAnestBP7rFYQJ9LzgfMoozuD/ReouYAWNx6NUq5rbsAszFrHsUfV1bJ/l 6DL9nQudoykEsDYDviLepdFm49jXf9JHxTjdm2rp1HSOABVHOGbkv2/yo5A9nSCITPZA=; To: qemu-devel@nongnu.org Cc: tsimpson@quicinc.com, bcain@quicinc.com, babush@rev.ng, nizzo@rev.ng, philmd@redhat.com, richard.henderson@linaro.org, Alessandro Di Federico Subject: [PATCH v3 10/12] target/hexagon: import parser for idef-parser Date: Tue, 30 Mar 2021 16:37:48 +0200 Message-Id: <20210330143750.3037824-11-ale.qemu@rev.ng> In-Reply-To: <20210330143750.3037824-1-ale.qemu@rev.ng> References: <20210330143750.3037824-1-ale.qemu@rev.ng> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=5.9.113.41; envelope-from=ale@rev.ng; helo=rev.ng X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_PASS=-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.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Reply-to: Alessandro Di Federico From: Alessandro Di Federico via X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" From: Paolo Montesel Signed-off-by: Alessandro Di Federico Signed-off-by: Paolo Montesel --- target/hexagon/idef-parser/idef-parser.y | 940 +++++++ target/hexagon/idef-parser/parser-helpers.c | 2230 +++++++++++++++++ target/hexagon/idef-parser/parser-helpers.h | 344 +++ target/hexagon/meson.build | 26 +- tests/docker/dockerfiles/alpine.docker | 1 + tests/docker/dockerfiles/centos7.docker | 1 + tests/docker/dockerfiles/centos8.docker | 1 + tests/docker/dockerfiles/debian10.docker | 2 + .../dockerfiles/fedora-i386-cross.docker | 2 + .../dockerfiles/fedora-win32-cross.docker | 2 + .../dockerfiles/fedora-win64-cross.docker | 2 + tests/docker/dockerfiles/fedora.docker | 1 + tests/docker/dockerfiles/opensuse-leap.docker | 1 + tests/docker/dockerfiles/ubuntu.docker | 2 + tests/docker/dockerfiles/ubuntu1804.docker | 2 + tests/docker/dockerfiles/ubuntu2004.docker | 4 +- 16 files changed, 3559 insertions(+), 2 deletions(-) create mode 100644 target/hexagon/idef-parser/idef-parser.y create mode 100644 target/hexagon/idef-parser/parser-helpers.c create mode 100644 target/hexagon/idef-parser/parser-helpers.h diff --git a/target/hexagon/idef-parser/idef-parser.y b/target/hexagon/idef= -parser/idef-parser.y new file mode 100644 index 0000000000..5d96c9262a --- /dev/null +++ b/target/hexagon/idef-parser/idef-parser.y @@ -0,0 +1,940 @@ +%{ +/* + * Copyright(c) 2019-2021 rev.ng Srls. All Rights Reserved. + * + * 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 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 . + */ + +#include "idef-parser.h" +#include "parser-helpers.h" +#include "idef-parser.tab.h" +#include "idef-parser.yy.h" + +/* Uncomment this to disable yyasserts */ +/* #define NDEBUG */ + +#define ERR_LINE_CONTEXT 40 + +%} + +%lex-param {void *scanner} +%parse-param {void *scanner} +%parse-param {Context *c} + +%define parse.error verbose +%define parse.lac full +%define api.pure full + +%locations + +%union { + GString *string; + HexValue rvalue; + HexSat sat; + HexCast cast; + HexExtract extract; + HexMpy mpy; + bool is_unsigned; + int index; +} + +/* Tokens */ +%start input + +%expect 1 + +%token INAME DREG DIMM DPRE DEA RREG WREG FREG FIMM RPRE WPRE FPRE FWRAP F= EA VAR +%token POW ABS CROUND ROUND CIRCADD COUNTONES INC DEC ANDA ORA XORA PLUSPL= US ASL +%token ASR LSR EQ NEQ LTE GTE MIN MAX ANDL ORL FOR ICIRC IF MUN FSCR FCHK = SXT +%token ZXT CONSTEXT LOCNT BREV SIGN LOAD STORE CONSTLL CONSTULL PC NPC LPC= FG +%token CANCEL IDENTITY PART1 BREV_4 BREV_8 ROTL INSBITS SETBITS EXTBITS EX= TRANGE +%token CAST4_8U SETOVF FAIL DEINTERLEAVE INTERLEAVE CARRY_FROM_ADD + +%token REG IMM PRE +%token ELSE +%token MPY +%token SAT +%token CAST DEPOSIT SETHALF +%token EXTRACT +%type INAME +%type rvalue lvalue VAR assign_statement var +%type DREG DIMM DPRE RREG RPRE FAIL +%type if_stmt IF ':' '?' +%type SIGN + +/* Operator Precedences */ +%left MIN MAX +%left '(' +%left ',' +%left '=3D' +%right CIRCADD +%right INC DEC ANDA ORA XORA +%left '?' ':' +%left ORL +%left ANDL +%left '|' +%left '^' ANDOR +%left '&' +%left EQ NEQ +%left '<' '>' LTE GTE +%left ASL ASR LSR +%right ABS +%left '-' '+' +%left POW +%left '*' '/' '%' MPY +%right '~' '!' +%left '[' +%right CAST +%right LOCNT BREV + +/* Bison Grammar */ +%% + +/* Input file containing the description of each hexagon instruction */ +input : instructions + { + YYACCEPT; + } + ; + +instructions : instruction instructions + | %empty + ; + +instruction : INAME + { + gen_inst(c, $1); + } + arguments + { + gen_inst_args(c, &@1); + } + code + { + gen_inst_code(c, &@1); + } + | error /* Recover gracefully after instruction compilation er= ror */ + { + free_instruction(c); + } + ; + +arguments : '(' ')' + | '(' argument_list ')'; + +argument_list : decl ',' argument_list + | decl + ; + +var : VAR + { + track_string(c, $1.var.name); + $$ =3D $1; + } + ; + +/* Return the modified registers list */ +code : '{' statements '}' + { + c->inst.code_begin =3D c->input_buffer + @2.first_column; + c->inst.code_end =3D c->input_buffer + @2.last_column - 1; + } + | '{' + { + /* Nop */ + } + '}' + ; + +decl : REG + { + emit_arg(c, &@1, &$1); + /* Enqueue register into initialization list */ + g_array_append_val(c->inst.init_list, $1); + } + | IMM + { + EMIT_SIG(c, ", int %ciV", $1.imm.id); + } + | PRE + { + emit_arg(c, &@1, &$1); + /* Enqueue predicate into initialization list */ + g_array_append_val(c->inst.init_list, $1); + } + | var + { + yyassert(c, &@1, !strcmp($1.var.name->str, "EA"), + "Unknown argument variable!"); + } + | RREG + { + emit_arg(c, &@1, &$1); + } + | WREG + | FREG + | FIMM + | RPRE + { + emit_arg(c, &@1, &$1); + } + | WPRE + | FPRE + | FEA + ; + +code_block : '{' statements '}' + | '{' '}' + ; + +/* A list of one or more statements */ +statements : statements statement + | statement + ; + +/* Statements can be assignment (rvalue ';'), control or memory statements= */ +statement : control_statement + | rvalue ';' + | code_block + | ';' + ; + +assign_statement : lvalue '=3D' rvalue + { + @1.last_column =3D @3.last_column; + gen_assign(c, &@1, &$1, &$3); + $$ =3D $1; + } + | lvalue INC rvalue + { + @1.last_column =3D @3.last_column; + HexValue tmp =3D gen_bin_op(c, &@1, ADD_OP, &$1, &$= 3); + gen_assign(c, &@1, &$1, &tmp); + $$ =3D $1; + } + | lvalue DEC rvalue + { + @1.last_column =3D @3.last_column; + HexValue tmp =3D gen_bin_op(c, &@1, SUB_OP, &$1, &$= 3); + gen_assign(c, &@1, &$1, &tmp); + $$ =3D $1; + } + | lvalue ANDA rvalue + { + @1.last_column =3D @3.last_column; + HexValue tmp =3D gen_bin_op(c, &@1, ANDB_OP, &$1, &= $3); + gen_assign(c, &@1, &$1, &tmp); + $$ =3D $1; + } + | lvalue ORA rvalue + { + @1.last_column =3D @3.last_column; + HexValue tmp =3D gen_bin_op(c, &@1, ORB_OP, &$1, &$= 3); + gen_assign(c, &@1, &$1, &tmp); + $$ =3D $1; + } + | lvalue XORA rvalue + { + @1.last_column =3D @3.last_column; + HexValue tmp =3D gen_bin_op(c, &@1, XORB_OP, &$1, &= $3); + gen_assign(c, &@1, &$1, &tmp); + $$ =3D $1; + } + | PRE '=3D' rvalue + { + @1.last_column =3D @3.last_column; + gen_pre_assign(c, &@1, &$1, &$3); + } + | IMM '=3D' rvalue + { + @1.last_column =3D @3.last_column; + yyassert(c, &@1, $3.type =3D=3D IMMEDIATE, + "Cannot assign non-immediate to immediate!= "); + yyassert(c, &@1, $1.imm.type =3D=3D VARIABLE, + "Cannot assign to non-variable!"); + /* Assign to the function argument */ + OUT(c, &@1, &$1, " =3D ", &$3, ";\n"); + $$ =3D $1; + } + | PC '=3D' rvalue + { + @1.last_column =3D @3.last_column; + $3 =3D rvalue_truncate(c, &@1, &$3); + $3 =3D rvalue_materialize(c, &@1, &$3); + OUT(c, &@1, "gen_write_new_pc(", &$3, ");\n"); + rvalue_free(c, &@1, &$3); /* Free temporary value */ + } + | LOAD '(' IMM ',' IMM ',' SIGN ',' var ',' lvalue ')' + { + @1.last_column =3D @12.last_column; + gen_load(c, &@1, &$3, &$5, $7, &$9, &$11); + } + | STORE '(' IMM ',' IMM ',' var ',' rvalue ')' + /* Store primitive */ + { + @1.last_column =3D @10.last_column; + gen_store(c, &@1, &$3, &$5, &$7, &$9); + } + | LPCFG '=3D' rvalue + { + @1.last_column =3D @3.last_column; + $3 =3D rvalue_truncate(c, &@1, &$3); + $3 =3D rvalue_materialize(c, &@1, &$3); + OUT(c, &@1, "SET_USR_FIELD(USR_LPCFG, ", &$3, ");\n= "); + rvalue_free(c, &@1, &$3); + } + | DEPOSIT '(' rvalue ',' rvalue ',' rvalue ')' + { + @1.last_column =3D @8.last_column; + gen_deposit_op(c, &@1, &$5, &$7, &$3, &$1); + } + | SETHALF '(' rvalue ',' lvalue ',' rvalue ')' + { + @1.last_column =3D @8.last_column; + gen_sethalf(c, &@1, &$1, &$3, &$5, &$7); + } + | SETBITS '(' rvalue ',' rvalue ',' rvalue ',' rvalue ')' + { + @1.last_column =3D @10.last_column; + gen_setbits(c, &@1, &$3, &$5, &$7, &$9); + } + | INSBITS '(' lvalue ',' rvalue ',' rvalue ',' rvalue ')' + { + @1.last_column =3D @10.last_column; + gen_rdeposit_op(c, &@1, &$3, &$9, &$7, &$5); + } + | IDENTITY '(' rvalue ')' + { + @1.last_column =3D @4.last_column; + $$ =3D $3; + } + ; + +control_statement : frame_check + | cancel_statement + | if_statement + | for_statement + | fpart1_statement + ; + +frame_check : FCHK '(' rvalue ',' rvalue ')' ';' + { + rvalue_free(c, &@1, &$3); + rvalue_free(c, &@1, &$5); + } + ; + +cancel_statement : CANCEL + { + OUT(c, &@1, "gen_cancel(insn->slot);\n"); + } + ; + +if_statement : if_stmt + { + /* Fix else label */ + OUT(c, &@1, "gen_set_label(if_label_", &$1, ");\n"); + } + | if_stmt ELSE + { + @1.last_column =3D @2.last_column; + $2 =3D gen_if_else(c, &@1, $1); + } + statement + { + OUT(c, &@1, "gen_set_label(if_label_", &$2, ");\n"); + } + ; + +for_statement : FOR '(' IMM '=3D' IMM ';' IMM '<' IMM ';' IMM PLUSPLUS ')' + { + @1.last_column =3D @13.last_column; + OUT(c, &@1, "for (int ", &$3, " =3D ", &$5, "; ", + &$7, " < ", &$9); + OUT(c, &@1, "; ", &$11, "++) {\n"); + } + code_block + { + OUT(c, &@1, "}\n"); + } + | FOR '(' IMM '=3D' IMM ';' IMM '<' IMM ';' IMM INC IMM ')' + { + @1.last_column =3D @14.last_column; + OUT(c, &@1, "for (int ", &$3, " =3D ", &$5, "; ", + &$7, " < ", &$9); + OUT(c, &@1, "; ", &$11, " +=3D ", &$13, ") {\n"); + } + code_block + { + OUT(c, &@1, "}\n"); + } + ; + +fpart1_statement : PART1 + { + OUT(c, &@1, "if (insn->part1) {\n"); + } + '(' statements ')' + { + @1.last_column =3D @3.last_column; + OUT(c, &@1, "return; }\n"); + } + ; + +if_stmt : IF '(' rvalue ')' + { + @1.last_column =3D @3.last_column; + $1 =3D gen_if_cond(c, &@1, &$3); + } + statement + { + $$ =3D $1; + } + ; + +rvalue : FAIL + { + yyassert(c, &@1, false, "Encountered a FAIL token as rvalue.\= n"); + } + | assign_statement + | REG + { + if ($1.reg.type =3D=3D CONTROL) { + $$ =3D gen_read_creg(c, &@1, &$1); + } else { + $$ =3D $1; + } + } + | IMM + { + $$ =3D $1; + } + | CONSTLL '(' IMM ')' + { + $3.is_unsigned =3D false; + $3.bit_width =3D 64; + $$ =3D $3; + } + | CONSTULL '(' IMM ')' + { + $3.is_unsigned =3D true; + $3.bit_width =3D 64; + $$ =3D $3; + } + | PRE + { + $$ =3D gen_rvalue_pre(c, &@1, &$1); + } + | PC + { + /* Read PC from the CR */ + $$ =3D gen_tmp(c, &@1, 32); + OUT(c, &@1, "tcg_gen_movi_i32(", &$$, ", ctx->base.pc_next);\= n"); + } + | NPC + { + /* NPC is only read from CALLs, so we can hardcode it + at translation time */ + $$ =3D gen_tmp(c, &@1, 32); + OUT(c, &@1, "tcg_gen_movi_i32(", &$$, ", ctx->npc);\n"); + } + | CONSTEXT + { + HexValue rvalue; + rvalue.type =3D IMMEDIATE; + rvalue.imm.type =3D IMM_CONSTEXT; + rvalue.is_unsigned =3D true; + rvalue.is_dotnew =3D false; + rvalue.is_manual =3D false; + $$ =3D rvalue; + } + | var + { + $$ =3D gen_rvalue_var(c, &@1, &$1); + } + | MPY '(' rvalue ',' rvalue ')' + { + @1.last_column =3D @6.last_column; + $$ =3D gen_rvalue_mpy(c, &@1, &$1, &$3, &$5); + } + | rvalue '+' rvalue + { + @1.last_column =3D @3.last_column; + $$ =3D gen_bin_op(c, &@1, ADD_OP, &$1, &$3); + } + | rvalue '-' rvalue + { + @1.last_column =3D @3.last_column; + $$ =3D gen_bin_op(c, &@1, SUB_OP, &$1, &$3); + } + | rvalue '*' rvalue + { + @1.last_column =3D @3.last_column; + $$ =3D gen_bin_op(c, &@1, MUL_OP, &$1, &$3); + } + | rvalue POW rvalue + { + @1.last_column =3D @3.last_column; + $$ =3D gen_rvalue_pow(c, &@1, &$1, &$3); + } + | rvalue '%' rvalue + { + @1.last_column =3D @3.last_column; + $$ =3D gen_bin_op(c, &@1, MOD_OP, &$1, &$3); + } + | rvalue ASL rvalue + { + @1.last_column =3D @3.last_column; + $$ =3D gen_bin_op(c, &@1, ASL_OP, &$1, &$3); + } + | rvalue ASR rvalue + { + @1.last_column =3D @3.last_column; + if ($1.is_unsigned) { + $$ =3D gen_bin_op(c, &@1, LSR_OP, &$1, &$3); + } else { + $$ =3D gen_bin_op(c, &@1, ASR_OP, &$1, &$3); + } + } + | rvalue LSR rvalue + { + @1.last_column =3D @3.last_column; + $$ =3D gen_bin_op(c, &@1, LSR_OP, &$1, &$3); + } + | rvalue '&' rvalue + { + @1.last_column =3D @3.last_column; + $$ =3D gen_bin_op(c, &@1, ANDB_OP, &$1, &$3); + } + | rvalue '|' rvalue + { + @1.last_column =3D @3.last_column; + $$ =3D gen_bin_op(c, &@1, ORB_OP, &$1, &$3); + } + | rvalue '^' rvalue + { + @1.last_column =3D @3.last_column; + $$ =3D gen_bin_op(c, &@1, XORB_OP, &$1, &$3); + } + | rvalue ANDL rvalue + { + @1.last_column =3D @3.last_column; + $$ =3D gen_bin_op(c, &@1, ANDL_OP, &$1, &$3); + } + | MIN '(' rvalue ',' rvalue ')' + { + @1.last_column =3D @3.last_column; + $$ =3D gen_bin_op(c, &@1, MINI_OP, &$3, &$5); + } + | MAX '(' rvalue ',' rvalue ')' + { + @1.last_column =3D @3.last_column; + $$ =3D gen_bin_op(c, &@1, MAXI_OP, &$3, &$5); + } + | '~' rvalue + { + @1.last_column =3D @2.last_column; + $$ =3D gen_rvalue_not(c, &@1, &$2); + } + | '!' rvalue + { + @1.last_column =3D @2.last_column; + $$ =3D gen_rvalue_notl(c, &@1, &$2); + } + | SAT '(' IMM ',' rvalue ')' + { + @1.last_column =3D @6.last_column; + $$ =3D gen_rvalue_sat(c, &@1, &$1, &$3, &$5); + } + | CAST rvalue + { + @1.last_column =3D @2.last_column; + /* Assign target signedness */ + $2.is_unsigned =3D $1.is_unsigned; + $$ =3D gen_cast_op(c, &@1, &$2, $1.bit_width); + $$.is_unsigned =3D $1.is_unsigned; + } + | rvalue '[' rvalue ']' + { + @1.last_column =3D @4.last_column; + if ($3.type =3D=3D IMMEDIATE) { + $$ =3D gen_tmp(c, &@1, $1.bit_width); + OUT(c, &@1, "tcg_gen_extract_i", &$$.bit_width, "("); + OUT(c, &@1, &$$, ", ", &$1, ", ", &$3, ", 1);\n"); + } else { + HexValue one =3D gen_imm_value(c, &@1, 1, $3.bit_width); + HexValue tmp =3D gen_bin_op(c, &@1, ASR_OP, &$1, &$3); + $$ =3D gen_bin_op(c, &@1, ANDB_OP, &tmp, &one); + } + } + | rvalue EQ rvalue + { + @1.last_column =3D @3.last_column; + $$ =3D gen_bin_cmp(c, &@1, TCG_COND_EQ, &$1, &$3); + } + | rvalue NEQ rvalue + { + @1.last_column =3D @3.last_column; + $$ =3D gen_bin_cmp(c, &@1, TCG_COND_NE, &$1, &$3); + } + | rvalue '<' rvalue + { + @1.last_column =3D @3.last_column; + if ($1.is_unsigned || $3.is_unsigned) { + $$ =3D gen_bin_cmp(c, &@1, TCG_COND_LTU, &$1, &$3); + } else { + $$ =3D gen_bin_cmp(c, &@1, TCG_COND_LT, &$1, &$3); + } + } + | rvalue '>' rvalue + { + @1.last_column =3D @3.last_column; + if ($1.is_unsigned || $3.is_unsigned) { + $$ =3D gen_bin_cmp(c, &@1, TCG_COND_GTU, &$1, &$3); + } else { + $$ =3D gen_bin_cmp(c, &@1, TCG_COND_GT, &$1, &$3); + } + } + | rvalue LTE rvalue + { + @1.last_column =3D @3.last_column; + if ($1.is_unsigned || $3.is_unsigned) { + $$ =3D gen_bin_cmp(c, &@1, TCG_COND_LEU, &$1, &$3); + } else { + $$ =3D gen_bin_cmp(c, &@1, TCG_COND_LE, &$1, &$3); + } + } + | rvalue GTE rvalue + { + @1.last_column =3D @3.last_column; + if ($1.is_unsigned || $3.is_unsigned) { + $$ =3D gen_bin_cmp(c, &@1, TCG_COND_GEU, &$1, &$3); + } else { + $$ =3D gen_bin_cmp(c, &@1, TCG_COND_GE, &$1, &$3); + } + } + | rvalue '?' + { + $2 =3D gen_if_cond(c, &@1, &$1); + $1 =3D gen_tmp(c, &@1, 64); + } + rvalue ':' + { + $4 =3D rvalue_materialize(c, &@1, &$4); + HexValue tmp =3D $4; + if ($4.bit_width < 64) { + tmp =3D rvalue_extend(c, &@1, &tmp); + } + OUT(c, &@1, "tcg_gen_mov_i64(", &$1, ", ", &tmp, ");\n"); + rvalue_free(c, &@1, &tmp); + $5 =3D gen_if_else(c, &@1, $2); + } + rvalue + { + /* Note: $4 was already rvalue_free'd */ + unsigned final_width =3D ($4.bit_width =3D=3D $7.bit_width) + ? $4.bit_width : 64; + $7 =3D rvalue_materialize(c, &@1, &$7); + $7 =3D rvalue_extend(c, &@1, &$7); + OUT(c, &@1, "tcg_gen_mov_i64(", &$1, ", ", &$7, ");\n"); + rvalue_free(c, &@1, &$7); + + $1.is_unsigned =3D $4.is_unsigned || $7.is_unsigned; + + OUT(c, &@1, "gen_set_label(if_label_", &$5, ");\n"); + if (final_width < 64) { + $$ =3D rvalue_truncate(c, &@1, &$1); + } else { + $$ =3D $1; + } + } + | FSCR '(' rvalue ')' + { + @1.last_column =3D @4.last_column; + $$ =3D gen_rvalue_fscr(c, &@1, &$3); + } + | SXT '(' rvalue ',' IMM ',' rvalue ')' + { + @1.last_column =3D @8.last_column; + yyassert(c, &@1, $5.type =3D=3D IMMEDIATE && + $5.imm.type =3D=3D VALUE, + "SXT expects immediate values\n"); + $5.imm.value =3D 64; + $$ =3D gen_extend_op(c, &@1, &$3, &$5, &$7, false); + } + | ZXT '(' rvalue ',' IMM ',' rvalue ')' + { + @1.last_column =3D @8.last_column; + yyassert(c, &@1, $5.type =3D=3D IMMEDIATE && + $5.imm.type =3D=3D VALUE, + "ZXT expects immediate values\n"); + $$ =3D gen_extend_op(c, &@1, &$3, &$5, &$7, true); + } + | '(' rvalue ')' + { + $$ =3D $2; + } + | ABS rvalue + { + @1.last_column =3D @2.last_column; + $$ =3D gen_rvalue_abs(c, &@1, &$2); + } + | CROUND '(' rvalue ',' rvalue ')' + { + @1.last_column =3D @6.last_column; + $$ =3D gen_convround_n(c, &@1, &$3, &$5); + } + | CROUND '(' rvalue ')' + { + @1.last_column =3D @4.last_column; + $$ =3D gen_convround(c, &@1, &$3); + } + | ROUND '(' rvalue ',' rvalue ')' + { + @1.last_column =3D @6.last_column; + $$ =3D gen_round(c, &@1, &$3, &$5); + } + | '-' rvalue + { + @1.last_column =3D @2.last_column; + $$ =3D gen_rvalue_neg(c, &@1, &$2); + } + | ICIRC '(' rvalue ')' ASL IMM + { + @1.last_column =3D @6.last_column; + $$ =3D gen_tmp(c, &@1, 32); + OUT(c, &@1, "gen_read_ireg(", &$$, ", ", &$3, ", ", &$6, ");\= n"); + rvalue_free(c, &@1, &$3); + } + | CIRCADD '(' rvalue ',' rvalue ',' rvalue ')' + { + @1.last_column =3D @8.last_column; + gen_circ_op(c, &@1, &$3, &$5, &$7); + } + | LOCNT '(' rvalue ')' + { + @1.last_column =3D @4.last_column; + /* Leading ones count */ + $$ =3D gen_locnt_op(c, &@1, &$3); + } + | COUNTONES '(' rvalue ')' + { + @1.last_column =3D @4.last_column; + /* Ones count */ + $$ =3D gen_ctpop_op(c, &@1, &$3); + } + | LPCFG + { + $$ =3D gen_tmp_value(c, &@1, "0", 32); + OUT(c, &@1, "tcg_gen_extract_tl(", &$$, + ", hex_gpr[HEX_REG_USR], "); + OUT(c, &@1, "reg_field_info[USR_LPCFG].offset, "); + OUT(c, &@1, "reg_field_info[USR_LPCFG].width);\n"); + } + | EXTRACT '(' rvalue ',' rvalue ')' + { + @1.last_column =3D @6.last_column; + $$ =3D gen_extract_op(c, &@1, &$5, &$3, &$1); + } + | EXTBITS '(' rvalue ',' rvalue ',' rvalue ')' + { + @1.last_column =3D @8.last_column; + yyassert(c, &@1, $5.type =3D=3D IMMEDIATE && + $5.imm.type =3D=3D VALUE && + $7.type =3D=3D IMMEDIATE && + $7.imm.type =3D=3D VALUE, + "Range extract needs immediate values!\n"); + $$ =3D gen_rextract_op(c, &@1, &$3, $7.imm.value, $5.imm.valu= e); + } + | EXTRANGE '(' rvalue ',' rvalue ',' rvalue ')' + { + @1.last_column =3D @8.last_column; + yyassert(c, &@1, $5.type =3D=3D IMMEDIATE && + $5.imm.type =3D=3D VALUE && + $7.type =3D=3D IMMEDIATE && + $7.imm.type =3D=3D VALUE, + "Range extract needs immediate values!\n"); + $$ =3D gen_rextract_op(c, + &@1, + &$3, + $7.imm.value, + $5.imm.value - $7.imm.value + 1); + } + | CAST4_8U '(' rvalue ')' + { + @1.last_column =3D @4.last_column; + $$ =3D rvalue_truncate(c, &@1, &$3); + $$.is_unsigned =3D true; + $$ =3D rvalue_materialize(c, &@1, &$$); + $$ =3D rvalue_extend(c, &@1, &$$); + } + | BREV '(' rvalue ')' + { + @1.last_column =3D @4.last_column; + $$ =3D gen_rvalue_brev(c, &@1, &$3); + } + | BREV_4 '(' rvalue ')' + { + @1.last_column =3D @4.last_column; + $$ =3D gen_fbrev_4(c, &@1, &$3); + } + | BREV_8 '(' rvalue ')' + { + @1.last_column =3D @4.last_column; + $$ =3D gen_fbrev_8(c, &@1, &$3); + } + | ROTL '(' rvalue ',' rvalue ')' + { + @1.last_column =3D @6.last_column; + $$ =3D gen_rotl(c, &@1, &$3, &$5); + } + | SETOVF '(' ')' + { + @1.last_column =3D @3.last_column; + OUT(c, &@1, "gen_set_usr_fieldi(USR_OVF, 1);\n"); + } + | SETOVF '(' rvalue ')' + { + /* Convenience fSET_OVERFLOW with pass-through */ + @1.last_column =3D @3.last_column; + OUT(c, &@1, "gen_set_usr_fieldi(USR_OVF, 1);\n"); + $$ =3D $3; + } + | DEINTERLEAVE '(' rvalue ')' + { + @1.last_column =3D @4.last_column; + $$ =3D gen_deinterleave(c, &@1, &$3); + } + | INTERLEAVE '(' rvalue ',' rvalue ')' + { + @1.last_column =3D @6.last_column; + $$ =3D gen_interleave(c, &@1, &$3, &$5); + } + | CARRY_FROM_ADD '(' rvalue ',' rvalue ',' rvalue ')' + { + @1.last_column =3D @8.last_column; + $$ =3D gen_carry_from_add(c, &@1, &$3, &$5, &$7); + } + ; + +lvalue : FAIL + { + @1.last_column =3D @1.last_column; + yyassert(c, &@1, false, "Encountered a FAIL token as lvalue.\= n"); + } + | REG + { + $$ =3D $1; + } + | var + { + $$ =3D $1; + } + ; + +%% + +int main(int argc, char **argv) +{ + if (argc !=3D 5) { + fprintf(stderr, + "Semantics: Hexagon ISA to tinycode generator compiler\n\n= "); + fprintf(stderr, + "Usage: ./semantics IDEFS EMITTER_C EMITTER_H " + "ENABLED_INSTRUCTIONS_LIST\n"); + return 1; + } + + enum { + ARG_INDEX_ARGV0 =3D 0, + ARG_INDEX_IDEFS, + ARG_INDEX_EMITTER_C, + ARG_INDEX_EMITTER_H, + ARG_INDEX_ENABLED_INSTRUCTIONS_LIST + }; + + FILE *enabled_file =3D fopen(argv[ARG_INDEX_ENABLED_INSTRUCTIONS_LIST]= , "w"); + + FILE *output_file =3D fopen(argv[ARG_INDEX_EMITTER_C], "w"); + fputs("#include \"qemu/osdep.h\"\n", output_file); + fputs("#include \"qemu/log.h\"\n", output_file); + fputs("#include \"cpu.h\"\n", output_file); + fputs("#include \"internal.h\"\n", output_file); + fputs("#include \"tcg/tcg-op.h\"\n", output_file); + fputs("#include \"insn.h\"\n", output_file); + fputs("#include \"opcodes.h\"\n", output_file); + fputs("#include \"translate.h\"\n", output_file); + fputs("#define QEMU_GENERATE\n", output_file); + fputs("#include \"genptr.h\"\n", output_file); + fputs("#include \"tcg/tcg.h\"\n", output_file); + fputs("#include \"macros.h\"\n", output_file); + fprintf(output_file, "#include \"%s\"\n", argv[ARG_INDEX_EMITTER_H]); + + FILE *defines_file =3D fopen(argv[ARG_INDEX_EMITTER_H], "w"); + assert(defines_file !=3D NULL); + fputs("#ifndef HEX_EMITTER_H\n", defines_file); + fputs("#define HEX_EMITTER_H\n", defines_file); + fputs("\n", defines_file); + fputs("#include \"insn.h\"\n\n", defines_file); + + /* Parser input file */ + Context context =3D { 0 }; + context.defines_file =3D defines_file; + context.output_file =3D output_file; + context.enabled_file =3D enabled_file; + /* Initialize buffers */ + context.out_str =3D g_string_new(NULL); + context.signature_str =3D g_string_new(NULL); + context.header_str =3D g_string_new(NULL); + /* Read input file */ + FILE *input_file =3D fopen(argv[ARG_INDEX_IDEFS], "r"); + fseek(input_file, 0L, SEEK_END); + long input_size =3D ftell(input_file); + context.input_buffer =3D (char *) calloc(input_size + 1, sizeof(char)); + fseek(input_file, 0L, SEEK_SET); + size_t read_chars =3D fread(context.input_buffer, + sizeof(char), + input_size, + input_file); + if (read_chars !=3D input_size) { + fprintf(stderr, "Error: an error occurred while reading input file= !\n"); + return -1; + } + yylex_init(&context.scanner); + YY_BUFFER_STATE buffer; + buffer =3D yy_scan_string(context.input_buffer, context.scanner); + /* Start the parsing procedure */ + yyparse(context.scanner, &context); + if (context.implemented_insn !=3D context.total_insn) { + fprintf(stderr, + "Warning: %d/%d meta instructions have been implemented!\n= ", + context.implemented_insn, + context.total_insn); + } + fputs("#endif " START_COMMENT " HEX_EMITTER_h " END_COMMENT "\n", + defines_file); + /* Cleanup */ + yy_delete_buffer(buffer, context.scanner); + yylex_destroy(context.scanner); + free(context.input_buffer); + g_string_free(context.out_str, TRUE); + g_string_free(context.signature_str, TRUE); + g_string_free(context.header_str, TRUE); + fclose(output_file); + fclose(input_file); + fclose(defines_file); + fclose(enabled_file); + + return 0; +} diff --git a/target/hexagon/idef-parser/parser-helpers.c b/target/hexagon/i= def-parser/parser-helpers.c new file mode 100644 index 0000000000..2b024f494f --- /dev/null +++ b/target/hexagon/idef-parser/parser-helpers.c @@ -0,0 +1,2230 @@ +/* + * Copyright(c) 2019-2021 rev.ng Srls. All Rights Reserved. + * + * 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 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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "idef-parser.h" +#include "parser-helpers.h" +#include "idef-parser.tab.h" +#include "idef-parser.yy.h" + +const char *creg_str[] =3D {"HEX_REG_SP", "HEX_REG_FP", "HEX_REG_LR", + "HEX_REG_GP", "HEX_REG_LC0", "HEX_REG_LC1", + "HEX_REG_SA0", "HEX_REG_SA1"}; + +void yyerror(YYLTYPE *locp, + yyscan_t scanner __attribute__((unused)), + Context *c, + const char *s) +{ + const char *code_ptr =3D c->input_buffer; + + fprintf(stderr, "WARNING (%s): '%s'\n", c->inst.name->str, s); + + fprintf(stderr, "Problematic range: "); + for (int i =3D locp->first_column; i < locp->last_column; i++) { + if (code_ptr[i] !=3D '\n') { + fprintf(stderr, "%c", code_ptr[i]); + } + } + fprintf(stderr, "\n"); + + for (int i =3D 0; + i < 80 && + code_ptr[locp->first_column - 10 + i] !=3D '\0' && + code_ptr[locp->first_column - 10 + i] !=3D '\n'; + i++) { + fprintf(stderr, "%c", code_ptr[locp->first_column - 10 + i]); + } + fprintf(stderr, "\n"); + for (int i =3D 0; i < 9; i++) { + fprintf(stderr, " "); + } + fprintf(stderr, "^"); + for (int i =3D 0; i < (locp->last_column - locp->first_column) - 1; i+= +) { + fprintf(stderr, "~"); + } + fprintf(stderr, "\n"); + c->inst.error_count++; +} + +bool is_direct_predicate(HexValue *value) +{ + return value->pre.id >=3D '0' && value->pre.id <=3D '3'; +} + +/* Print functions */ +void str_print(Context *c, YYLTYPE *locp, const char *string) +{ + EMIT(c, "%s", string); +} + + +void uint64_print(Context *c, YYLTYPE *locp, uint64_t *num) +{ + EMIT(c, "%" PRIu64, *num); +} + +void int_print(Context *c, YYLTYPE *locp, int *num) +{ + EMIT(c, "%d", *num); +} + +void uint_print(Context *c, YYLTYPE *locp, unsigned *num) +{ + EMIT(c, "%u", *num); +} + +void tmp_print(Context *c, YYLTYPE *locp, HexTmp *tmp) +{ + EMIT(c, "tmp_%d", tmp->index); +} + +void pre_print(Context *c, YYLTYPE *locp, HexPre *pre, bool is_dotnew) +{ + char suffix =3D is_dotnew ? 'N' : 'V'; + EMIT(c, "P%c%c", pre->id, suffix); +} + +void reg_compose(Context *c, YYLTYPE *locp, HexReg *reg, char reg_id[5]) +{ + switch (reg->type) { + case GENERAL_PURPOSE: + reg_id[0] =3D 'R'; + break; + case CONTROL: + reg_id[0] =3D 'C'; + break; + case MODIFIER: + reg_id[0] =3D 'M'; + break; + case DOTNEW: + /* The DOTNEW case is managed by the upper level function */ + break; + } + switch (reg->bit_width) { + case 32: + reg_id[1] =3D reg->id; + reg_id[2] =3D 'V'; + break; + case 64: + reg_id[1] =3D reg->id; + reg_id[2] =3D reg->id; + reg_id[3] =3D 'V'; + break; + default: + yyassert(c, locp, false, "Unhandled register bit width!\n"); + } +} + +void reg_print(Context *c, YYLTYPE *locp, HexReg *reg) +{ + if (reg->type =3D=3D DOTNEW) { + EMIT(c, "N%cN", reg->id); + } else { + char reg_id[5] =3D { 0 }; + reg_compose(c, locp, reg, reg_id); + EMIT(c, "%s", reg_id); + } +} + +void imm_print(Context *c, YYLTYPE *locp, HexImm *imm) +{ + switch (imm->type) { + case I: + EMIT(c, "i"); + break; + case VARIABLE: + EMIT(c, "%ciV", imm->id); + break; + case VALUE: + EMIT(c, "((int64_t)%" PRIu64 "ULL)", (int64_t)imm->value); + break; + case QEMU_TMP: + EMIT(c, "qemu_tmp_%" PRIu64, imm->index); + break; + case IMM_PC: + EMIT(c, "dc->pc"); + break; + case IMM_CONSTEXT: + EMIT(c, "insn->extension_valid"); + break; + default: + yyassert(c, locp, false, "Cannot print this expression!"); + } +} + +void var_print(Context *c, YYLTYPE *locp, HexVar *var) +{ + EMIT(c, "%s", var->name->str); +} + +void rvalue_out(Context *c, YYLTYPE *locp, void *pointer) +{ + HexValue *rvalue =3D (HexValue *) pointer; + switch (rvalue->type) { + case REGISTER: + reg_print(c, locp, &rvalue->reg); + break; + case TEMP: + tmp_print(c, locp, &rvalue->tmp); + break; + case IMMEDIATE: + imm_print(c, locp, &rvalue->imm); + break; + case VARID: + var_print(c, locp, &rvalue->var); + break; + case PREDICATE: + pre_print(c, locp, &rvalue->pre, rvalue->is_dotnew); + break; + default: + yyassert(c, locp, false, "Cannot print this expression!"); + } +} + +void out_assert(Context *c, YYLTYPE *locp, + void *dummy __attribute__((unused))) { + abort(); + yyassert(c, locp, false, "Unhandled print type!"); +} + +/* Copy output code buffer */ +void commit(Context *c) +{ + /* Emit instruction pseudocode */ + EMIT_SIG(c, "\n" START_COMMENT " "); + for (char *x =3D c->inst.code_begin; x < c->inst.code_end; x++) { + EMIT_SIG(c, "%c", *x); + } + EMIT_SIG(c, " " END_COMMENT "\n"); + + /* Commit instruction code to output file */ + fwrite(c->signature_str->str, sizeof(char), c->signature_str->len, + c->output_file); + fwrite(c->header_str->str, sizeof(char), c->header_str->len, + c->output_file); + fwrite(c->out_str->str, sizeof(char), c->out_str->len, + c->output_file); + + fwrite(c->signature_str->str, sizeof(char), c->signature_str->len, + c->defines_file); + fprintf(c->defines_file, ";\n"); +} + +/* Temporary values creation */ +HexValue gen_tmp(Context *c, YYLTYPE *locp, int bit_width) +{ + HexValue rvalue; + rvalue.type =3D TEMP; + bit_width =3D (bit_width =3D=3D 64) ? 64 : 32; + rvalue.bit_width =3D bit_width; + rvalue.is_unsigned =3D false; + rvalue.is_dotnew =3D false; + rvalue.is_manual =3D false; + rvalue.tmp.index =3D c->inst.tmp_count; + OUT(c, locp, "TCGv_i", &bit_width, " tmp_", &c->inst.tmp_count, + " =3D tcg_temp_local_new_i", &bit_width, "();\n"); + c->inst.tmp_count++; + return rvalue; +} + +HexValue gen_tmp_value(Context *c, + YYLTYPE *locp, + const char *value, + int bit_width) +{ + HexValue rvalue; + rvalue.type =3D TEMP; + rvalue.bit_width =3D bit_width; + rvalue.is_unsigned =3D false; + rvalue.is_dotnew =3D false; + rvalue.is_manual =3D false; + rvalue.tmp.index =3D c->inst.tmp_count; + OUT(c, locp, "TCGv_i", &bit_width, " tmp_", &c->inst.tmp_count, + " =3D tcg_const_i", &bit_width, "(", value, ");\n"); + c->inst.tmp_count++; + return rvalue; +} + +HexValue gen_imm_value(Context *c __attribute__((unused)), + YYLTYPE *locp, + int value, + int bit_width) +{ + HexValue rvalue; + rvalue.type =3D IMMEDIATE; + rvalue.bit_width =3D bit_width; + rvalue.is_unsigned =3D false; + rvalue.is_dotnew =3D false; + rvalue.is_manual =3D false; + rvalue.imm.type =3D VALUE; + rvalue.imm.value =3D value; + return rvalue; +} + +void rvalue_free(Context *c, YYLTYPE *locp, HexValue *rvalue) +{ + if (rvalue->type =3D=3D TEMP && !rvalue->is_manual) { + const char *bit_suffix =3D (rvalue->bit_width =3D=3D 64) ? "i64" := "i32"; + OUT(c, locp, "tcg_temp_free_", bit_suffix, "(", rvalue, ");\n"); + } +} + +static void rvalue_free_manual(Context *c, YYLTYPE *locp, HexValue *rvalue) +{ + rvalue->is_manual =3D false; + rvalue_free(c, locp, rvalue); +} + +HexValue rvalue_materialize(Context *c, YYLTYPE *locp, HexValue *rvalue) +{ + if (rvalue->type =3D=3D IMMEDIATE) { + HexValue tmp =3D gen_tmp(c, locp, rvalue->bit_width); + tmp.is_unsigned =3D rvalue->is_unsigned; + const char *bit_suffix =3D (rvalue->bit_width =3D=3D 64) ? "i64" := "i32"; + OUT(c, locp, "tcg_gen_movi_", bit_suffix, + "(", &tmp, ", ", rvalue, ");\n"); + rvalue_free(c, locp, rvalue); + return tmp; + } + return *rvalue; +} + +HexValue rvalue_extend(Context *c, YYLTYPE *locp, HexValue *rvalue) +{ + if (rvalue->type =3D=3D IMMEDIATE) { + HexValue res =3D *rvalue; + res.bit_width =3D 64; + return res; + } else { + if (rvalue->bit_width =3D=3D 32) { + HexValue res =3D gen_tmp(c, locp, 64); + const char *sign_suffix =3D (rvalue->is_unsigned) ? "u" : ""; + OUT(c, locp, "tcg_gen_ext", sign_suffix, + "_i32_i64(", &res, ", ", rvalue, ");\n"); + rvalue_free(c, locp, rvalue); + return res; + } + } + return *rvalue; +} + +HexValue rvalue_truncate(Context *c, YYLTYPE *locp, HexValue *rvalue) +{ + if (rvalue->type =3D=3D IMMEDIATE) { + HexValue res =3D *rvalue; + res.bit_width =3D 32; + return res; + } else { + if (rvalue->bit_width =3D=3D 64) { + HexValue res =3D gen_tmp(c, locp, 32); + OUT(c, locp, "tcg_gen_trunc_i64_tl(", &res, ", ", rvalue, ");\= n"); + rvalue_free(c, locp, rvalue); + return res; + } + } + return *rvalue; +} + +int find_variable(Context *c, YYLTYPE *locp, HexValue *varid) +{ + for (int i =3D 0; i < c->inst.allocated->len; i++) { + Var *curr =3D &g_array_index(c->inst.allocated, Var, i); + if (g_string_equal(varid->var.name, curr->name)) { + return i; + } + } + return -1; +} + +void varid_allocate(Context *c, + YYLTYPE *locp, + HexValue *varid, + int width, + bool is_unsigned) +{ + varid->bit_width =3D width; + const char *bit_suffix =3D width =3D=3D 64 ? "64" : "32"; + int index =3D find_variable(c, locp, varid); + bool found =3D index !=3D -1; + if (found) { + Var *other =3D &g_array_index(c->inst.allocated, Var, index); + varid->var.name =3D other->name; + varid->bit_width =3D other->bit_width; + varid->is_unsigned =3D other->is_unsigned; + } else { + EMIT_HEAD(c, "TCGv_i%s %s", bit_suffix, varid->var.name->str); + EMIT_HEAD(c, " =3D tcg_temp_local_new_i%s();\n", bit_suffix); + Var new_var =3D { + .name =3D varid->var.name, + .bit_width =3D width, + .is_unsigned =3D is_unsigned, + }; + g_array_append_val(c->inst.allocated, new_var); + } +} + +void ea_free(Context *c, YYLTYPE *locp) +{ + OUT(c, locp, "tcg_temp_free(EA);\n"); +} + +enum OpTypes { + IMM_IMM =3D 0, + IMM_REG =3D 1, + REG_IMM =3D 2, + REG_REG =3D 3, +}; + +HexValue gen_bin_cmp(Context *c, + YYLTYPE *locp, + TCGCond type, + HexValue *op1_ptr, + HexValue *op2_ptr) +{ + HexValue op1 =3D *op1_ptr; + HexValue op2 =3D *op2_ptr; + enum OpTypes op_types =3D (op1.type !=3D IMMEDIATE) << 1 + | (op2.type !=3D IMMEDIATE); + + /* Find bit width of the two operands, if at least one is 64 bit use a= */ + /* 64bit operation, eventually extend 32bit operands. */ + bool op_is64bit =3D op1.bit_width =3D=3D 64 || op2.bit_width =3D=3D 64; + const char *bit_suffix =3D op_is64bit ? "i64" : "i32"; + int bit_width =3D (op_is64bit) ? 64 : 32; + if (op_is64bit) { + switch (op_types) { + case IMM_IMM: + break; + case IMM_REG: + op2 =3D rvalue_extend(c, locp, &op2); + break; + case REG_IMM: + op1 =3D rvalue_extend(c, locp, &op1); + break; + case REG_REG: + op1 =3D rvalue_extend(c, locp, &op1); + op2 =3D rvalue_extend(c, locp, &op2); + break; + } + } + + HexValue res =3D gen_tmp(c, locp, bit_width); + + switch (op_types) { + case IMM_IMM: + OUT(c, locp, "tcg_gen_movi_", bit_suffix, + "(", &res, ", ", &op1, " =3D=3D ", &op2, ");\n"); + break; + case IMM_REG: + { + HexValue swp =3D op2; + op2 =3D op1; + op1 =3D swp; + /* Swap comparison direction */ + type =3D tcg_swap_cond(type); + } + /* fallthrough */ + case REG_IMM: + OUT(c, locp, "tcg_gen_setcondi_", bit_suffix, "("); + OUT(c, locp, cond_to_str(type), ", ", &res, ", ", &op1, ", ", &op2, + ");\n"); + break; + case REG_REG: + OUT(c, locp, "tcg_gen_setcond_", bit_suffix, "("); + OUT(c, locp, cond_to_str(type), ", ", &res, ", ", &op1, ", ", &op2, + ");\n"); + break; + default: + fprintf(stderr, "Error in evalutating immediateness!"); + abort(); + } + + /* Free operands */ + rvalue_free(c, locp, &op1); + rvalue_free(c, locp, &op2); + + return res; +} + +static void gen_simple_op(Context *c, YYLTYPE *locp, unsigned bit_width, + const char *bit_suffix, HexValue *res, + enum OpTypes op_types, HexValue *op1, + HexValue *op2, + const char *imm_imm, + const char *imm_reg, + const char *reg_imm, + const char *reg_reg + ) { + switch (op_types) { + case IMM_IMM: + OUT(c, locp, "int", &bit_width, "_t ", res, + " =3D ", op1, imm_imm, op2, ";\n"); + break; + case IMM_REG: + OUT(c, locp, imm_reg, bit_suffix, + "(", res, ", ", op2, ", (int64_t)", op1, ");\n"); + break; + case REG_IMM: + OUT(c, locp, reg_imm, bit_suffix, + "(", res, ", ", op1, ", (int64_t)", op2, ");\n"); + break; + case REG_REG: + OUT(c, locp, reg_reg, bit_suffix, + "(", res, ", ", op1, ", ", op2, ");\n"); + break; + } + rvalue_free(c, locp, op1); + rvalue_free(c, locp, op2); +} + +static void gen_sub_op(Context *c, YYLTYPE *locp, unsigned bit_width, + const char *bit_suffix, HexValue *res, + enum OpTypes op_types, HexValue *op1, HexValue *op2) +{ + switch (op_types) { + case IMM_IMM: + OUT(c, locp, "int", &bit_width, "_t ", res, + " =3D ", op1, " - ", op2, ";\n"); + break; + case IMM_REG: + OUT(c, locp, "tcg_gen_subfi_", bit_suffix, + "(", res, ", ", op1, ", ", op2, ");\n"); + break; + case REG_IMM: + OUT(c, locp, "tcg_gen_subi_", bit_suffix, + "(", res, ", ", op1, ", ", op2, ");\n"); + break; + case REG_REG: + OUT(c, locp, "tcg_gen_sub_", bit_suffix, + "(", res, ", ", op1, ", ", op2, ");\n"); + break; + } + rvalue_free(c, locp, op1); + rvalue_free(c, locp, op2); +} + +static void gen_asl_op(Context *c, YYLTYPE *locp, unsigned bit_width, + bool op_is64bit, const char *bit_suffix, HexValue *= res, + enum OpTypes op_types, HexValue *op1_ptr, + HexValue *op2_ptr) +{ + HexValue op1 =3D *op1_ptr; + HexValue op2 =3D *op2_ptr; + switch (op_types) { + case IMM_IMM: + OUT(c, locp, "int", &bit_width, "_t ", res, + " =3D ", &op1, " << ", &op2, ";\n"); + break; + case REG_IMM: + { + OUT(c, locp, "if (", &op2, " >=3D ", &bit_width, ") {\n"); + OUT(c, locp, "tcg_gen_movi_", bit_suffix, "(", res, ", 0);\n"); + OUT(c, locp, "} else {\n"); + OUT(c, locp, "tcg_gen_shli_", bit_suffix, + "(", res, ", ", &op1, ", ", &op2, ");\n"); + OUT(c, locp, "}\n"); + } + break; + case IMM_REG: + op1.bit_width =3D bit_width; + op1 =3D rvalue_materialize(c, locp, &op1); + /* Fallthrough */ + case REG_REG: + OUT(c, locp, "tcg_gen_shl_", bit_suffix, + "(", res, ", ", &op1, ", ", &op2, ");\n"); + break; + } + if (op_types =3D=3D IMM_REG || op_types =3D=3D REG_REG) { + /* Handle left shift by 64/32 which hexagon-sim expects to clear o= ut */ + /* register */ + HexValue edge =3D gen_imm_value(c, locp, bit_width, bit_width); + edge =3D rvalue_materialize(c, locp, &edge); + HexValue zero =3D gen_tmp_value(c, locp, "0", bit_width); + if (op_is64bit) { + op2 =3D rvalue_extend(c, locp, &op2); + } + op1 =3D rvalue_materialize(c, locp, &op1); + op2 =3D rvalue_materialize(c, locp, &op2); + OUT(c, locp, "tcg_gen_movcond_i", &bit_width); + OUT(c, locp, "(TCG_COND_GEU, ", res, ", ", &op2, ", ", &edge); + OUT(c, locp, ", ", &zero, ", ", res, ");\n"); + rvalue_free(c, locp, &edge); + rvalue_free(c, locp, &zero); + } + rvalue_free(c, locp, &op1); + rvalue_free(c, locp, &op2); +} + +static void gen_asr_op(Context *c, YYLTYPE *locp, unsigned bit_width, + bool op_is64bit, const char *bit_suffix, HexValue *= res, + enum OpTypes op_types, HexValue *op1_ptr, + HexValue *op2_ptr) +{ + HexValue op1 =3D *op1_ptr; + HexValue op2 =3D *op2_ptr; + switch (op_types) { + case IMM_IMM: + OUT(c, locp, "int", &bit_width, "_t ", res, + " =3D ", &op1, " >> ", &op2, ";\n"); + break; + case REG_IMM: + OUT(c, locp, "{\nint", &bit_width, "_t shift =3D ", &op2, ";\n"); + OUT(c, locp, "if (", &op2, " >=3D ", &bit_width, ") {\n"); + OUT(c, locp, " shift =3D ", &bit_width, " - 1;\n"); + OUT(c, locp, "}\n"); + OUT(c, locp, "tcg_gen_sari_", bit_suffix, + "(", res, ", ", &op1, ", shift);\n}\n"); + break; + case IMM_REG: + op1 =3D rvalue_materialize(c, locp, &op1); + /* Fallthrough */ + case REG_REG: + OUT(c, locp, "tcg_gen_sar_", bit_suffix, + "(", res, ", ", &op1, ", ", &op2, ");\n"); + break; + } + if (op_types =3D=3D IMM_REG || op_types =3D=3D REG_REG) { + /* Handle right shift by values >=3D bit_width */ + HexValue edge =3D gen_imm_value(c, locp, bit_width, bit_width); + edge =3D rvalue_materialize(c, locp, &edge); + HexValue tmp =3D gen_tmp(c, locp, bit_width); + HexValue zero =3D gen_tmp_value(c, locp, "0", bit_width); + if (op_is64bit) { + op2 =3D rvalue_extend(c, locp, &op2); + } + op1 =3D rvalue_materialize(c, locp, &op1); + op2 =3D rvalue_materialize(c, locp, &op2); + + const char *offset =3D op_is64bit ? "63" : "31"; + OUT(c, locp, "tcg_gen_extract_", bit_suffix, "(", + &tmp, ", ", &op1, ", ", offset, ", 1);\n"); + OUT(c, locp, "tcg_gen_sub_", bit_suffix, "(", + &tmp, ", ", &zero, ", ", &tmp, ");\n"); + OUT(c, locp, "tcg_gen_movcond_i", &bit_width); + OUT(c, locp, "(TCG_COND_GEU, ", res, ", ", &op2, ", ", &edge); + OUT(c, locp, ", ", &tmp, ", ", res, ");\n"); + rvalue_free(c, locp, &edge); + rvalue_free(c, locp, &tmp); + rvalue_free(c, locp, &zero); + } + rvalue_free(c, locp, &op1); + rvalue_free(c, locp, &op2); +} + +static void gen_lsr_op(Context *c, YYLTYPE *locp, unsigned bit_width, + bool op_is64bit, const char *bit_suffix, HexValue *= res, + enum OpTypes op_types, HexValue *op1_ptr, + HexValue *op2_ptr) +{ + HexValue op1 =3D *op1_ptr; + HexValue op2 =3D *op2_ptr; + switch (op_types) { + case IMM_IMM: + OUT(c, locp, "int", &bit_width, "_t ", + res, " =3D ", &op1, " >> ", &op2, ";\n"); + break; + case REG_IMM: + OUT(c, locp, "if (", &op2, " >=3D ", &bit_width, ") {\n"); + OUT(c, locp, "tcg_gen_movi_", bit_suffix, "(", res, ", 0);\n"); + OUT(c, locp, "} else {\n"); + OUT(c, locp, "tcg_gen_shri_", bit_suffix, + "(", res, ", ", &op1, ", ", &op2, ");\n"); + OUT(c, locp, "}\n"); + break; + case IMM_REG: + op1 =3D rvalue_materialize(c, locp, &op1); + /* Fallthrough */ + case REG_REG: + OUT(c, locp, "tcg_gen_shr_", bit_suffix, + "(", res, ", ", &op1, ", ", &op2, ");\n"); + break; + } + if (op_types =3D=3D IMM_REG || op_types =3D=3D REG_REG) { + /* Handle right shift by values >=3D bit_width */ + HexValue edge =3D gen_imm_value(c, locp, bit_width, bit_width); + edge =3D rvalue_materialize(c, locp, &edge); + HexValue zero =3D gen_tmp_value(c, locp, "0", bit_width); + if (op_is64bit) { + op2 =3D rvalue_extend(c, locp, &op2); + } + op1 =3D rvalue_materialize(c, locp, &op1); + op2 =3D rvalue_materialize(c, locp, &op2); + OUT(c, locp, "tcg_gen_movcond_i", &bit_width); + OUT(c, locp, "(TCG_COND_GEU, ", res, ", ", &op2, ", ", &edge); + OUT(c, locp, ", ", &zero, ", ", res, ");\n"); + rvalue_free(c, locp, &edge); + rvalue_free(c, locp, &zero); + } + rvalue_free(c, locp, &op1); + rvalue_free(c, locp, &op2); +} + +static void gen_andl_op(Context *c, YYLTYPE *locp, unsigned bit_width, + const char *bit_suffix, HexValue *res, + enum OpTypes op_types, HexValue *op1, HexValue *op= 2) +{ + HexValue zero, tmp1, tmp2; + switch (op_types) { + case IMM_IMM: + OUT(c, locp, "int", &bit_width, "_t ", + res, " =3D ", op1, " && ", op2, ";\n"); + break; + case IMM_REG: + zero =3D gen_tmp_value(c, locp, "0", 32); + tmp2 =3D gen_bin_cmp(c, locp, TCG_COND_NE, op2, &zero); + OUT(c, locp, "tcg_gen_andi_", bit_suffix, + "(", res, ", ", op1, " !=3D 0 , ", &tmp2, ");\n"); + rvalue_free(c, locp, &tmp2); + break; + case REG_IMM: + zero =3D gen_tmp_value(c, locp, "0", 32); + tmp1 =3D gen_bin_cmp(c, locp, TCG_COND_NE, op1, &zero); + OUT(c, locp, "tcg_gen_andi_", bit_suffix, + "(", res, ", ", &tmp1, ", ", op2, " !=3D 0);\n"); + rvalue_free(c, locp, &tmp1); + break; + case REG_REG: + zero =3D gen_tmp_value(c, locp, "0", 32); + zero.is_manual =3D true; + tmp1 =3D gen_bin_cmp(c, locp, TCG_COND_NE, op1, &zero); + tmp2 =3D gen_bin_cmp(c, locp, TCG_COND_NE, op2, &zero); + OUT(c, locp, "tcg_gen_and_", bit_suffix, + "(", res, ", ", &tmp1, ", ", &tmp2, ");\n"); + rvalue_free_manual(c, locp, &zero); + rvalue_free(c, locp, &tmp1); + rvalue_free(c, locp, &tmp2); + break; + } +} + +static void gen_mini_op(Context *c, YYLTYPE *locp, unsigned bit_width, + HexValue *res, enum OpTypes op_types, + HexValue *op1_ptr, HexValue *op2_ptr) +{ + HexValue op1 =3D *op1_ptr; + HexValue op2 =3D *op2_ptr; + const char *min =3D res->is_unsigned ? "tcg_gen_umin" : "tcg_gen_smin"; + switch (op_types) { + case IMM_IMM: + OUT(c, locp, "int", &bit_width, "_t ", res, " =3D (", &op1, " <=3D= "); + OUT(c, locp, &op2, ") ? ", &op1, " : ", &op2, ";\n"); + break; + case IMM_REG: + op1.bit_width =3D bit_width; + op1 =3D rvalue_materialize(c, locp, &op1); + OUT(c, locp, min, "_i", &bit_width, "("); + OUT(c, locp, res, ", ", &op1, ", ", &op2, ");\n"); + break; + case REG_IMM: + op2.bit_width =3D bit_width; + op2 =3D rvalue_materialize(c, locp, &op2); + /* Fallthrough */ + case REG_REG: + OUT(c, locp, min, "_i", &bit_width, "("); + OUT(c, locp, res, ", ", &op1, ", ", &op2, ");\n"); + break; + } + rvalue_free(c, locp, &op1); + rvalue_free(c, locp, &op2); +} + +static void gen_maxi_op(Context *c, YYLTYPE *locp, unsigned bit_width, + HexValue *res, enum OpTypes op_types, + HexValue *op1_ptr, HexValue *op2_ptr) +{ + HexValue op1 =3D *op1_ptr; + HexValue op2 =3D *op2_ptr; + const char *min =3D res->is_unsigned ? "tcg_gen_umax" : "tcg_gen_smax"; + switch (op_types) { + case IMM_IMM: + OUT(c, locp, "int", &bit_width, "_t ", res, " =3D (", &op1, " <=3D= "); + OUT(c, locp, &op2, ") ? ", &op2, " : ", &op1, ";\n"); + break; + case IMM_REG: + op1.bit_width =3D bit_width; + op1 =3D rvalue_materialize(c, locp, &op1); + OUT(c, locp, min, "_i", &bit_width, "("); + OUT(c, locp, res, ", ", &op1, ", ", &op2, ");\n"); + break; + case REG_IMM: + op2.bit_width =3D bit_width; + op2 =3D rvalue_materialize(c, locp, &op2); + /* Fallthrough */ + case REG_REG: + OUT(c, locp, min, "_i", &bit_width, "("); + OUT(c, locp, res, ", ", &op1, ", ", &op2, ");\n"); + break; + } + rvalue_free(c, locp, &op1); + rvalue_free(c, locp, &op2); +} + +static void gen_mod_op(Context *c, YYLTYPE *locp, HexValue *res, + enum OpTypes op_types, HexValue *op1, HexValue *op2) +{ + switch (op_types) { + case IMM_IMM: + OUT(c, locp, "int64_t ", res, " =3D ", op1, " % ", op2, ";\n"); + break; + case IMM_REG: + case REG_IMM: + case REG_REG: + OUT(c, locp, "gen_helper_mod(", + res, ", ", op1, ", ", op2, ");\n"); + break; + } + rvalue_free(c, locp, op1); + rvalue_free(c, locp, op2); +} + +/* Code generation functions */ +HexValue gen_bin_op(Context *c, + YYLTYPE *locp, + OpType type, + HexValue *operand1, + HexValue *operand2) +{ + /* Replicate operands to avoid side effects */ + HexValue op1 =3D *operand1; + HexValue op2 =3D *operand2; + + /* Enforce variables' size */ + if (op1.type =3D=3D VARID) { + int index =3D find_variable(c, locp, &op1); + yyassert(c, locp, c->inst.allocated->len > 0, + "Variable in bin_op must exist!\n"); + op1.bit_width =3D g_array_index(c->inst.allocated, Var, index).bit= _width; + } + if (op2.type =3D=3D VARID) { + int index =3D find_variable(c, locp, &op2); + yyassert(c, locp, c->inst.allocated->len > 0, + "Variable in bin_op must exist!\n"); + op2.bit_width =3D g_array_index(c->inst.allocated, Var, index).bit= _width; + } + + enum OpTypes op_types =3D (op1.type !=3D IMMEDIATE) << 1 + | (op2.type !=3D IMMEDIATE); + + /* Find bit width of the two operands, if at least one is 64 bit use a= */ + /* 64bit operation, eventually extend 32bit operands. */ + bool op_is64bit =3D op1.bit_width =3D=3D 64 || op2.bit_width =3D=3D 64; + /* Shift greater than 32 are 64 bits wide */ + if (type =3D=3D ASL_OP && op2.type =3D=3D IMMEDIATE && + op2.imm.type =3D=3D VALUE && op2.imm.value >=3D 32) + op_is64bit =3D true; + const char *bit_suffix =3D op_is64bit ? "i64" : "i32"; + int bit_width =3D (op_is64bit) ? 64 : 32; + /* Handle bit width */ + if (op_is64bit) { + switch (op_types) { + case IMM_IMM: + break; + case IMM_REG: + op2 =3D rvalue_extend(c, locp, &op2); + break; + case REG_IMM: + op1 =3D rvalue_extend(c, locp, &op1); + break; + case REG_REG: + op1 =3D rvalue_extend(c, locp, &op1); + op2 =3D rvalue_extend(c, locp, &op2); + break; + } + } + HexValue res; + if (op_types !=3D IMM_IMM) { + res =3D gen_tmp(c, locp, bit_width); + } else { + res.type =3D IMMEDIATE; + res.is_dotnew =3D false; + res.is_manual =3D false; + res.imm.type =3D QEMU_TMP; + res.imm.index =3D c->inst.qemu_tmp_count; + res.bit_width =3D bit_width; + } + /* Handle signedness, if both unsigned -> result is unsigned, else sig= ned */ + res.is_unsigned =3D op1.is_unsigned && op2.is_unsigned; + + switch (type) { + case ADD_OP: + gen_simple_op(c, locp, bit_width, bit_suffix, &res, + op_types, &op1, &op2, + " + ", + "tcg_gen_addi_", + "tcg_gen_addi_", + "tcg_gen_add_"); + break; + case SUB_OP: + gen_sub_op(c, locp, bit_width, bit_suffix, &res, op_types, &op1, &= op2); + break; + case MUL_OP: + gen_simple_op(c, locp, bit_width, bit_suffix, &res, + op_types, &op1, &op2, + " * ", + "tcg_gen_muli_", + "tcg_gen_muli_", + "tcg_gen_mul_"); + break; + case ASL_OP: + gen_asl_op(c, locp, bit_width, op_is64bit, bit_suffix, &res, op_ty= pes, + &op1, &op2); + break; + case ASR_OP: + gen_asr_op(c, locp, bit_width, op_is64bit, bit_suffix, &res, op_ty= pes, + &op1, &op2); + break; + case LSR_OP: + gen_lsr_op(c, locp, bit_width, op_is64bit, bit_suffix, &res, op_ty= pes, + &op1, &op2); + break; + case ANDB_OP: + gen_simple_op(c, locp, bit_width, bit_suffix, &res, + op_types, &op1, &op2, + " & ", + "tcg_gen_andi_", + "tcg_gen_andi_", + "tcg_gen_and_"); + break; + case ORB_OP: + gen_simple_op(c, locp, bit_width, bit_suffix, &res, + op_types, &op1, &op2, + " | ", + "tcg_gen_ori_", + "tcg_gen_ori_", + "tcg_gen_or_"); + break; + case XORB_OP: + gen_simple_op(c, locp, bit_width, bit_suffix, &res, + op_types, &op1, &op2, + " ^ ", + "tcg_gen_xori_", + "tcg_gen_xori_", + "tcg_gen_xor_"); + break; + case ANDL_OP: + gen_andl_op(c, locp, bit_width, bit_suffix, &res, op_types, &op1, = &op2); + break; + case MINI_OP: + gen_mini_op(c, locp, bit_width, &res, op_types, &op1, &op2); + break; + case MAXI_OP: + gen_maxi_op(c, locp, bit_width, &res, op_types, &op1, &op2); + break; + case MOD_OP: + gen_mod_op(c, locp, &res, op_types, &op1, &op2); + break; + } + if (op_types =3D=3D IMM_IMM) { + c->inst.qemu_tmp_count++; + } + return res; +} + +HexValue gen_cast_op(Context *c, + YYLTYPE *locp, + HexValue *source, + unsigned target_width) { + if (source->bit_width =3D=3D target_width) { + return *source; + } else if (source->type =3D=3D IMMEDIATE) { + HexValue res =3D *source; + res.bit_width =3D target_width; + return res; + } else { + HexValue res =3D gen_tmp(c, locp, target_width); + /* Truncate */ + if (source->bit_width > target_width) { + OUT(c, locp, "tcg_gen_trunc_i64_tl(", &res, ", ", source, ");\= n"); + } else { + if (source->is_unsigned) { + /* Extend unsigned */ + OUT(c, locp, "tcg_gen_extu_i32_i64(", + &res, ", ", source, ");\n"); + } else { + /* Extend signed */ + OUT(c, locp, "tcg_gen_ext_i32_i64(", + &res, ", ", source, ");\n"); + } + } + rvalue_free(c, locp, source); + return res; + } +} + +HexValue gen_extend_op(Context *c, + YYLTYPE *locp, + HexValue *src_width_ptr, + HexValue *dst_width_ptr, + HexValue *value_ptr, + bool is_unsigned) { + HexValue src_width =3D *src_width_ptr; + HexValue dst_width =3D *dst_width_ptr; + HexValue value =3D *value_ptr; + src_width =3D rvalue_extend(c, locp, &src_width); + value =3D rvalue_extend(c, locp, &value); + src_width =3D rvalue_materialize(c, locp, &src_width); + value =3D rvalue_materialize(c, locp, &value); + + HexValue res =3D gen_tmp(c, locp, 64); + HexValue shift =3D gen_tmp_value(c, locp, "64", 64); + HexValue zero =3D gen_tmp_value(c, locp, "0", 64); + OUT(c, locp, "tcg_gen_sub_i64(", + &shift, ", ", &shift, ", ", &src_width, ");\n"); + if (is_unsigned) { + HexValue mask =3D gen_tmp_value(c, locp, "0xffffffffffffffff", 64); + OUT(c, locp, "tcg_gen_shr_i64(", + &mask, ", ", &mask, ", ", &shift, ");\n"); + OUT(c, locp, "tcg_gen_and_i64(", + &res, ", ", &value, ", ", &mask, ");\n"); + rvalue_free(c, locp, &mask); + } else { + OUT(c, locp, "tcg_gen_shl_i64(", + &res, ", ", &value, ", ", &shift, ");\n"); + OUT(c, locp, "tcg_gen_sar_i64(", + &res, ", ", &res, ", ", &shift, ");\n"); + } + OUT(c, locp, "tcg_gen_movcond_i64(TCG_COND_EQ, ", &res, ", "); + OUT(c, locp, &src_width, ", ", &zero, ", ", &zero, ", ", &res, ");\n"); + + rvalue_free(c, locp, &src_width); + rvalue_free(c, locp, &dst_width); + rvalue_free(c, locp, &value); + rvalue_free(c, locp, &shift); + rvalue_free(c, locp, &zero); + + res.is_unsigned =3D is_unsigned; + return res; +} + +void gen_rdeposit_op(Context *c, + YYLTYPE *locp, + HexValue *dest, + HexValue *value, + HexValue *begin, + HexValue *width) +{ + HexValue dest_m =3D *dest; + dest_m.is_manual =3D true; + + HexValue value_m =3D rvalue_extend(c, locp, value); + HexValue begin_m =3D rvalue_extend(c, locp, begin); + HexValue width_orig =3D *width; + width_orig.is_manual =3D true; + HexValue width_m =3D rvalue_extend(c, locp, &width_orig); + width_m =3D rvalue_materialize(c, locp, &width_m); + + HexValue mask =3D gen_tmp_value(c, locp, "0xffffffffffffffffUL", 64); + mask.is_unsigned =3D true; + HexValue k64 =3D gen_tmp_value(c, locp, "64", 64); + k64 =3D gen_bin_op(c, locp, SUB_OP, &k64, &width_m); + mask =3D gen_bin_op(c, locp, LSR_OP, &mask, &k64); + begin_m.is_manual =3D true; + mask =3D gen_bin_op(c, locp, ASL_OP, &mask, &begin_m); + mask.is_manual =3D true; + value_m =3D gen_bin_op(c, locp, ASL_OP, &value_m, &begin_m); + value_m =3D gen_bin_op(c, locp, ANDB_OP, &value_m, &mask); + + OUT(c, locp, "tcg_gen_not_i64(", &mask, ", ", &mask, ");\n"); + mask.is_manual =3D false; + HexValue res =3D gen_bin_op(c, locp, ANDB_OP, &dest_m, &mask); + res =3D gen_bin_op(c, locp, ORB_OP, &res, &value_m); + + if (dest->bit_width !=3D res.bit_width) { + res =3D rvalue_truncate(c, locp, &res); + } + + HexValue zero =3D gen_tmp_value(c, locp, "0", res.bit_width); + OUT(c, locp, "tcg_gen_movcond_i", &res.bit_width, "(TCG_COND_NE, ", de= st); + OUT(c, locp, ", ", &width_orig, ", ", &zero, ", ", &res, ", ", dest, + ");\n"); + + rvalue_free(c, locp, &zero); + rvalue_free(c, locp, width); + rvalue_free(c, locp, &res); +} + +void gen_deposit_op(Context *c, + YYLTYPE *locp, + HexValue *dest, + HexValue *value, + HexValue *index, + HexCast *cast) +{ + yyassert(c, locp, index->type =3D=3D IMMEDIATE, + "Deposit index must be immediate!\n"); + HexValue value_m =3D *value; + int bit_width =3D (dest->bit_width =3D=3D 64) ? 64 : 32; + int width =3D cast->bit_width; + /* If the destination value is 32, truncate the value, otherwise exten= d */ + if (dest->bit_width !=3D value->bit_width) { + if (bit_width =3D=3D 32) { + value_m =3D rvalue_truncate(c, locp, &value_m); + } else { + value_m =3D rvalue_extend(c, locp, &value_m); + } + } + value_m =3D rvalue_materialize(c, locp, &value_m); + OUT(c, locp, "tcg_gen_deposit_i", &bit_width, "(", dest, ", ", dest, "= , "); + OUT(c, locp, &value_m, ", ", index, " * ", &width, ", ", &width, ");\n= "); + rvalue_free(c, locp, index); + rvalue_free(c, locp, &value_m); +} + +HexValue gen_rextract_op(Context *c, + YYLTYPE *locp, + HexValue *source, + int begin, + int width) { + int bit_width =3D (source->bit_width =3D=3D 64) ? 64 : 32; + HexValue res =3D gen_tmp(c, locp, bit_width); + OUT(c, locp, "tcg_gen_extract_i", &bit_width, "(", &res); + OUT(c, locp, ", ", source, ", ", &begin, ", ", &width, ");\n"); + rvalue_free(c, locp, source); + return res; +} + +HexValue gen_extract_op(Context *c, + YYLTYPE *locp, + HexValue *source, + HexValue *index, + HexExtract *extract) { + yyassert(c, locp, index->type =3D=3D IMMEDIATE, + "Extract index must be immediate!\n"); + int bit_width =3D (source->bit_width =3D=3D 64) ? 64 : 32; + const char *sign_prefix =3D (extract->is_unsigned) ? "" : "s"; + int width =3D extract->bit_width; + HexValue res =3D gen_tmp(c, locp, bit_width); + res.is_unsigned =3D extract->is_unsigned; + OUT(c, locp, "tcg_gen_", sign_prefix, "extract_i", &bit_width, + "(", &res, ", ", source); + OUT(c, locp, ", ", index, " * ", &width, ", ", &width, ");\n"); + + /* Some extract operations have bit_width !=3D storage_bit_width */ + if (extract->storage_bit_width > bit_width) { + HexValue tmp =3D gen_tmp(c, locp, extract->storage_bit_width); + tmp.is_unsigned =3D extract->is_unsigned; + if (extract->is_unsigned) { + /* Extend unsigned */ + OUT(c, locp, "tcg_gen_extu_i32_i64(", + &tmp, ", ", &res, ");\n"); + } else { + /* Extend signed */ + OUT(c, locp, "tcg_gen_ext_i32_i64(", + &tmp, ", ", &res, ");\n"); + } + rvalue_free(c, locp, &res); + res =3D tmp; + } + + rvalue_free(c, locp, source); + rvalue_free(c, locp, index); + return res; +} + +HexValue gen_read_creg(Context *c, YYLTYPE *locp, HexValue *reg) +{ + yyassert(c, locp, reg->type =3D=3D REGISTER, "reg must be a register!"= ); + if (reg->reg.id < 'a') { + HexValue tmp =3D gen_tmp_value(c, locp, "0", 32); + const char *id =3D creg_str[(uint8_t)reg->reg.id]; + OUT(c, locp, "READ_REG(", &tmp, ", ", id, ");\n"); + rvalue_free(c, locp, reg); + return tmp; + } + return *reg; +} + +void gen_write_creg(Context *c, + YYLTYPE *locp, + HexValue *reg, + HexValue *value) +{ + yyassert(c, locp, reg->type =3D=3D REGISTER, "reg must be a register!"= ); + HexValue value_m =3D *value; + value_m =3D rvalue_truncate(c, locp, &value_m); + value_m =3D rvalue_materialize(c, locp, &value_m); + OUT(c, + locp, + "gen_log_reg_write(", creg_str[(uint8_t)reg->reg.id], ", ", + &value_m, ");\n"); + OUT(c, + locp, + "ctx_log_reg_write(ctx, ", creg_str[(uint8_t)reg->reg.id], ");\n"); + rvalue_free(c, locp, reg); + rvalue_free(c, locp, &value_m); +} + +void gen_assign(Context *c, + YYLTYPE *locp, + HexValue *dest, + HexValue *value) +{ + HexValue value_m =3D *value; + if (dest->type =3D=3D REGISTER && + dest->reg.type =3D=3D CONTROL && dest->reg.id < 'a') { + gen_write_creg(c, locp, dest, &value_m); + return; + } + /* Create (if not present) and assign to temporary variable */ + if (dest->type =3D=3D VARID) { + varid_allocate(c, locp, dest, value_m.bit_width, value_m.is_unsign= ed); + } + int bit_width =3D dest->bit_width =3D=3D 64 ? 64 : 32; + if (bit_width !=3D value_m.bit_width) { + if (bit_width =3D=3D 64) { + value_m =3D rvalue_extend(c, locp, &value_m); + } else { + value_m =3D rvalue_truncate(c, locp, &value_m); + } + } + value_m =3D rvalue_materialize(c, locp, &value_m); + if (value_m.type =3D=3D IMMEDIATE) { + OUT(c, locp, "tcg_gen_movi_i", &bit_width, + "(", dest, ", ", &value_m, ");\n"); + } else { + OUT(c, locp, "tcg_gen_mov_i", &bit_width, + "(", dest, ", ", &value_m, ");\n"); + } + rvalue_free(c, locp, &value_m); +} + +HexValue gen_convround(Context *c, + YYLTYPE *locp, + HexValue *source) +{ + HexValue src =3D *source; + src.is_manual =3D true; + + unsigned bit_width =3D src.bit_width; + const char *size =3D (bit_width =3D=3D 32) ? "32" : "64"; + HexValue res =3D gen_tmp(c, locp, bit_width); + HexValue mask =3D gen_tmp_value(c, locp, "0x3", bit_width); + mask.is_manual =3D true; + HexValue and =3D gen_bin_op(c, locp, ANDB_OP, &src, &mask); + HexValue one =3D gen_tmp_value(c, locp, "1", bit_width); + HexValue src_p1 =3D gen_bin_op(c, locp, ADD_OP, &src, &one); + + OUT(c, locp, "tcg_gen_movcond_i", size, "(TCG_COND_EQ, ", &res); + OUT(c, locp, ", ", &and, ", ", &mask, ", "); + OUT(c, locp, &src_p1, ", ", &src, ");\n"); + + /* Free src but use the original `is_manual` value */ + rvalue_free(c, locp, source); + + /* Free the rest of the values */ + rvalue_free_manual(c, locp, &mask); + rvalue_free(c, locp, &and); + rvalue_free(c, locp, &src_p1); + + return res; +} + +static HexValue gen_convround_n_a(Context *c, + YYLTYPE *locp, + HexValue *a, + HexValue *n) +{ + HexValue res =3D gen_tmp(c, locp, 64); + OUT(c, locp, "tcg_gen_ext_i32_i64(", &res, ", ", a, ");\n"); + return res; +} + +static HexValue gen_convround_n_b(Context *c, + YYLTYPE *locp, + HexValue *a, + HexValue *n) +{ + HexValue res =3D gen_tmp(c, locp, 64); + OUT(c, locp, "tcg_gen_ext_i32_i64(", &res, ", ", a, ");\n"); + + HexValue one =3D gen_tmp_value(c, locp, "1", 32); + HexValue tmp =3D gen_tmp(c, locp, 32); + HexValue tmp_64 =3D gen_tmp(c, locp, 64); + + OUT(c, locp, "tcg_gen_shl_i32(", &tmp); + OUT(c, locp, ", ", &one, ", ", n, ");\n"); + OUT(c, locp, "tcg_gen_and_i32(", &tmp); + OUT(c, locp, ", ", &tmp, ", ", a, ");\n"); + OUT(c, locp, "tcg_gen_shri_i32(", &tmp); + OUT(c, locp, ", ", &tmp, ", 1);\n"); + OUT(c, locp, "tcg_gen_ext_i32_i64(", &tmp_64, ", ", &tmp, ");\n"); + OUT(c, locp, "tcg_gen_add_i64(", &res); + OUT(c, locp, ", ", &res, ", ", &tmp_64, ");\n"); + + rvalue_free(c, locp, &one); + rvalue_free(c, locp, &tmp); + rvalue_free(c, locp, &tmp_64); + + return res; +} + +static HexValue gen_convround_n_c(Context *c, + YYLTYPE *locp, + HexValue *a, + HexValue *n) +{ + HexValue res =3D gen_tmp(c, locp, 64); + OUT(c, locp, "tcg_gen_ext_i32_i64(", &res, ", ", a, ");\n"); + + HexValue one =3D gen_tmp_value(c, locp, "1", 32); + HexValue tmp =3D gen_tmp(c, locp, 32); + HexValue tmp_64 =3D gen_tmp(c, locp, 64); + + OUT(c, locp, "tcg_gen_subi_i32(", &tmp); + OUT(c, locp, ", ", n, ", 1);\n"); + OUT(c, locp, "tcg_gen_shl_i32(", &tmp); + OUT(c, locp, ", ", &one, ", ", &tmp, ");\n"); + OUT(c, locp, "tcg_gen_ext_i32_i64(", &tmp_64, ", ", &tmp, ");\n"); + OUT(c, locp, "tcg_gen_add_i64(", &res); + OUT(c, locp, ", ", &res, ", ", &tmp_64, ");\n"); + + rvalue_free(c, locp, &one); + rvalue_free(c, locp, &tmp); + rvalue_free(c, locp, &tmp_64); + + return res; +} + +HexValue gen_convround_n(Context *c, + YYLTYPE *locp, + HexValue *source_ptr, + HexValue *bit_pos_ptr) +{ + /* If input is 64 bit cast it to 32 */ + HexValue source =3D gen_cast_op(c, locp, source_ptr, 32); + HexValue bit_pos =3D gen_cast_op(c, locp, bit_pos_ptr, 32); + + source =3D rvalue_materialize(c, locp, &source); + bit_pos =3D rvalue_materialize(c, locp, &bit_pos); + + HexValue r1 =3D gen_convround_n_a(c, locp, &source, &bit_pos); + HexValue r2 =3D gen_convround_n_b(c, locp, &source, &bit_pos); + HexValue r3 =3D gen_convround_n_c(c, locp, &source, &bit_pos); + + HexValue l_32 =3D gen_tmp_value(c, locp, "1", 32); + + HexValue cond =3D gen_tmp(c, locp, 32); + HexValue cond_64 =3D gen_tmp(c, locp, 64); + HexValue mask =3D gen_tmp(c, locp, 32); + HexValue n_64 =3D gen_tmp(c, locp, 64); + HexValue res =3D gen_tmp(c, locp, 64); + HexValue zero =3D gen_tmp_value(c, locp, "0", 64); + + OUT(c, locp, "tcg_gen_sub_i32(", &mask); + OUT(c, locp, ", ", &bit_pos, ", ", &l_32, ");\n"); + OUT(c, locp, "tcg_gen_shl_i32(", &mask); + OUT(c, locp, ", ", &l_32, ", ", &mask, ");\n"); + OUT(c, locp, "tcg_gen_sub_i32(", &mask); + OUT(c, locp, ", ", &mask, ", ", &l_32, ");\n"); + OUT(c, locp, "tcg_gen_and_i32(", &cond); + OUT(c, locp, ", ", &source, ", ", &mask, ");\n"); + OUT(c, locp, "tcg_gen_extu_i32_i64(", &cond_64, ", ", &cond, ");\n"); + OUT(c, locp, "tcg_gen_ext_i32_i64(", &n_64, ", ", &bit_pos, ");\n"); + + OUT(c, locp, "tcg_gen_movcond_i64"); + OUT(c, locp, "(TCG_COND_EQ, ", &res, ", ", &cond_64, ", ", &zero); + OUT(c, locp, ", ", &r2, ", ", &r3, ");\n"); + + OUT(c, locp, "tcg_gen_movcond_i64"); + OUT(c, locp, "(TCG_COND_EQ, ", &res, ", ", &n_64, ", ", &zero); + OUT(c, locp, ", ", &r1, ", ", &res, ");\n"); + + OUT(c, locp, "tcg_gen_shr_i64(", &res); + OUT(c, locp, ", ", &res, ", ", &n_64, ");\n"); + + rvalue_free(c, locp, &source); + rvalue_free(c, locp, &bit_pos); + + rvalue_free(c, locp, &r1); + rvalue_free(c, locp, &r2); + rvalue_free(c, locp, &r3); + + rvalue_free(c, locp, &cond); + rvalue_free(c, locp, &cond_64); + rvalue_free(c, locp, &l_32); + rvalue_free(c, locp, &mask); + rvalue_free(c, locp, &n_64); + rvalue_free(c, locp, &zero); + + res =3D rvalue_truncate(c, locp, &res); + return res; +} + +HexValue gen_round(Context *c, + YYLTYPE *locp, + HexValue *source, + HexValue *position) { + yyassert(c, locp, source->bit_width <=3D 32, + "fRNDN not implemented for bit widths > 32!"); + + HexValue src =3D *source; + HexValue pos =3D *position; + + HexValue src_width =3D gen_imm_value(c, locp, src.bit_width, 32); + HexValue dst_width =3D gen_imm_value(c, locp, 64, 32); + HexValue a =3D gen_extend_op(c, locp, &src_width, &dst_width, &src, fa= lse); + + src_width =3D gen_imm_value(c, locp, 5, 32); + dst_width =3D gen_imm_value(c, locp, 64, 32); + HexValue b =3D gen_extend_op(c, locp, &src_width, &dst_width, &pos, tr= ue); + + /* Disable auto-free of values used more than once */ + a.is_manual =3D true; + b.is_manual =3D true; + + HexValue res =3D gen_tmp(c, locp, 64); + + HexValue one =3D gen_tmp_value(c, locp, "1", 64); + HexValue n_m1 =3D gen_bin_op(c, locp, SUB_OP, &b, &one); + one =3D gen_tmp_value(c, locp, "1", 64); + HexValue shifted =3D gen_bin_op(c, locp, ASL_OP, &one, &n_m1); + HexValue sum =3D gen_bin_op(c, locp, ADD_OP, &shifted, &a); + + HexValue zero =3D gen_tmp_value(c, locp, "0", 64); + OUT(c, locp, "tcg_gen_movcond_i64"); + OUT(c, locp, "(TCG_COND_EQ, ", &res, ", ", &b, ", ", &zero); + OUT(c, locp, ", ", &a, ", ", &sum, ");\n"); + + rvalue_free_manual(c, locp, &a); + rvalue_free_manual(c, locp, &b); + rvalue_free(c, locp, &zero); + rvalue_free(c, locp, &sum); + + return res; +} + +/* Circular addressing mode with auto-increment */ +void gen_circ_op(Context *c, + YYLTYPE *locp, + HexValue *addr, + HexValue *increment, + HexValue *modifier) { + HexValue increment_m =3D *increment; + HexValue cs =3D gen_tmp(c, locp, 32); + increment_m =3D rvalue_materialize(c, locp, &increment_m); + OUT(c, locp, "READ_REG(", &cs, ", HEX_REG_CS0 + MuN);\n"); + OUT(c, + locp, + "gen_helper_fcircadd(", + addr, + ", ", + addr, + ", ", + &increment_m, + ", ", + modifier); + OUT(c, locp, ", ", &cs, ");\n"); + rvalue_free(c, locp, &increment_m); + rvalue_free(c, locp, modifier); + rvalue_free(c, locp, &cs); +} + +HexValue gen_locnt_op(Context *c, YYLTYPE *locp, HexValue *source) +{ + HexValue source_m =3D *source; + const char *bit_suffix =3D source->bit_width =3D=3D 64 ? "64" : "32"; + HexValue res =3D gen_tmp(c, locp, source->bit_width =3D=3D 64 ? 64 : 3= 2); + res.type =3D TEMP; + source_m =3D rvalue_materialize(c, locp, &source_m); + OUT(c, locp, "tcg_gen_not_i", bit_suffix, "(", + &res, ", ", &source_m, ");\n"); + OUT(c, locp, "tcg_gen_clzi_i", bit_suffix, "(", &res, ", ", &res, ", "= ); + OUT(c, locp, bit_suffix, ");\n"); + rvalue_free(c, locp, &source_m); + return res; +} + +HexValue gen_ctpop_op(Context *c, YYLTYPE *locp, HexValue *source) +{ + HexValue source_m =3D *source; + const char *bit_suffix =3D source_m.bit_width =3D=3D 64 ? "64" : "32"; + HexValue res =3D gen_tmp(c, locp, source_m.bit_width =3D=3D 64 ? 64 : = 32); + res.type =3D TEMP; + source_m =3D rvalue_materialize(c, locp, &source_m); + OUT(c, locp, "tcg_gen_ctpop_i", bit_suffix, + "(", &res, ", ", &source_m, ");\n"); + rvalue_free(c, locp, &source_m); + return res; +} + +HexValue gen_fbrev_4(Context *c, YYLTYPE *locp, HexValue *source) +{ + HexValue source_m =3D *source; + + HexValue res =3D gen_tmp(c, locp, 32); + HexValue tmp1 =3D gen_tmp(c, locp, 32); + HexValue tmp2 =3D gen_tmp(c, locp, 32); + + source_m =3D rvalue_materialize(c, locp, &source_m); + source_m =3D rvalue_truncate(c, locp, &source_m); + + OUT(c, locp, "tcg_gen_mov_tl(", &res, ", ", &source_m, ");\n"); + OUT(c, locp, "tcg_gen_andi_tl(", &tmp1, ", ", &res, ", 0xaaaaaaaa);\n"= ); + OUT(c, locp, "tcg_gen_shri_tl(", &tmp1, ", ", &tmp1, ", 1);\n"); + OUT(c, locp, "tcg_gen_andi_tl(", &tmp2, ", ", &res, ", 0x55555555);\n"= ); + OUT(c, locp, "tcg_gen_shli_tl(", &tmp2, ", ", &tmp2, ", 1);\n"); + OUT(c, locp, "tcg_gen_or_tl(", &res, ", ", &tmp1, ", ", &tmp2, ");\n"); + OUT(c, locp, "tcg_gen_andi_tl(", &tmp1, ", ", &res, ", 0xcccccccc);\n"= ); + OUT(c, locp, "tcg_gen_shri_tl(", &tmp1, ", ", &tmp1, ", 2);\n"); + OUT(c, locp, "tcg_gen_andi_tl(", &tmp2, ", ", &res, ", 0x33333333);\n"= ); + OUT(c, locp, "tcg_gen_shli_tl(", &tmp2, ", ", &tmp2, ", 2);\n"); + OUT(c, locp, "tcg_gen_or_tl(", &res, ", ", &tmp1, ", ", &tmp2, ");\n"); + OUT(c, locp, "tcg_gen_andi_tl(", &tmp1, ", ", &res, ", 0xf0f0f0f0);\n"= ); + OUT(c, locp, "tcg_gen_shri_tl(", &tmp1, ", ", &tmp1, ", 4);\n"); + OUT(c, locp, "tcg_gen_andi_tl(", &tmp2, ", ", &res, ", 0x0f0f0f0f);\n"= ); + OUT(c, locp, "tcg_gen_shli_tl(", &tmp2, ", ", &tmp2, ", 4);\n"); + OUT(c, locp, "tcg_gen_or_tl(", &res, ", ", &tmp1, ", ", &tmp2, ");\n"); + OUT(c, locp, "tcg_gen_bswap32_tl(", &res, ", ", &res, ");\n"); + + rvalue_free(c, locp, &tmp1); + rvalue_free(c, locp, &tmp2); + rvalue_free(c, locp, &source_m); + + return res; +} + +HexValue gen_fbrev_8(Context *c, YYLTYPE *locp, HexValue *source) +{ + HexValue source_m =3D *source; + + source_m =3D rvalue_extend(c, locp, &source_m); + source_m =3D rvalue_materialize(c, locp, &source_m); + + HexValue res =3D gen_tmp(c, locp, 64); + HexValue tmp1 =3D gen_tmp(c, locp, 64); + HexValue tmp2 =3D gen_tmp(c, locp, 64); + + OUT(c, locp, "tcg_gen_mov_i64(", + &res, ", ", &source_m, ");\n"); + OUT(c, locp, "tcg_gen_andi_i64(", + &tmp1, ", ", &res, ", 0xaaaaaaaaaaaaaaaa);\n"); + OUT(c, locp, "tcg_gen_shri_i64(", + &tmp1, ", ", &tmp1, ", 1);\n"); + OUT(c, locp, "tcg_gen_andi_i64(", + &tmp2, ", ", &res, ", 0x5555555555555555);\n"); + OUT(c, locp, "tcg_gen_shli_i64(", + &tmp2, ", ", &tmp2, ", 1);\n"); + OUT(c, locp, "tcg_gen_or_i64(", &res, ", ", &tmp1, ", ", &tmp2, ");\n"= ); + OUT(c, locp, "tcg_gen_andi_i64(", + &tmp1, ", ", &res, ", 0xcccccccccccccccc);\n"); + OUT(c, locp, "tcg_gen_shri_i64(", + &tmp1, ", ", &tmp1, ", 2);\n"); + OUT(c, locp, "tcg_gen_andi_i64(", + &tmp2, ", ", &res, ", 0x3333333333333333);\n"); + OUT(c, locp, "tcg_gen_shli_i64(", + &tmp2, ", ", &tmp2, ", 2);\n"); + OUT(c, locp, "tcg_gen_or_i64(", &res, ", ", &tmp1, ", ", &tmp2, ");\n"= ); + OUT(c, locp, "tcg_gen_andi_i64(", + &tmp1, ", ", &res, ", 0xf0f0f0f0f0f0f0f0);\n"); + OUT(c, locp, "tcg_gen_shri_i64(", + &tmp1, ", ", &tmp1, ", 4);\n"); + OUT(c, locp, "tcg_gen_andi_i64(", + &tmp2, ", ", &res, ", 0x0f0f0f0f0f0f0f0f);\n"); + OUT(c, locp, "tcg_gen_shli_i64(", + &tmp2, ", ", &tmp2, ", 4);\n"); + OUT(c, locp, "tcg_gen_or_i64(", &res, ", ", &tmp1, ", ", &tmp2, ");\n"= ); + OUT(c, locp, "tcg_gen_andi_i64(", + &tmp1, ", ", &res, ", 0xff00ff00ff00ff00);\n"); + OUT(c, locp, "tcg_gen_shri_i64(", + &tmp1, ", ", &tmp1, ", 8);\n"); + OUT(c, locp, "tcg_gen_andi_i64(", + &tmp2, ", ", &res, ", 0x00ff00ff00ff00ff);\n"); + OUT(c, locp, "tcg_gen_shli_i64(", + &tmp2, ", ", &tmp2, ", 8);\n"); + OUT(c, locp, "tcg_gen_or_i64(", &res, ", ", &tmp1, ", ", &tmp2, ");\n"= ); + OUT(c, locp, "tcg_gen_andi_i64(", + &tmp1, ", ", &res, ", 0xffff0000ffff0000);\n"); + OUT(c, locp, "tcg_gen_shri_i64(", + &tmp1, ", ", &tmp1, ", 16);\n"); + OUT(c, locp, "tcg_gen_andi_i64(", + &tmp2, ", ", &res, ", 0x0000ffff0000ffff);\n"); + OUT(c, locp, "tcg_gen_shli_i64(", + &tmp2, ", ", &tmp2, ", 16);\n"); + OUT(c, locp, "tcg_gen_or_i64(", &res, ", ", &tmp1, ", ", &tmp2, ");\n"= ); + OUT(c, locp, "tcg_gen_shri_i64(", &tmp1, ", ", &res, ", 32);\n"); + OUT(c, locp, "tcg_gen_shli_i64(", &tmp2, ", ", &res, ", 32);\n"); + OUT(c, locp, "tcg_gen_or_i64(", &res, ", ", &tmp1, ", ", &tmp2, ");\n"= ); + + rvalue_free(c, locp, &tmp1); + rvalue_free(c, locp, &tmp2); + rvalue_free(c, locp, &source_m); + + return res; +} + +HexValue gen_rotl(Context *c, YYLTYPE *locp, HexValue *source, HexValue *n) +{ + HexValue amount =3D *n; + amount =3D rvalue_materialize(c, locp, &amount); + const char *suffix =3D source->bit_width =3D=3D 64 ? "i64" : "i32"; + + HexValue res =3D gen_tmp(c, locp, source->bit_width); + res.is_unsigned =3D source->is_unsigned; + OUT(c, locp, "tcg_gen_rotl_", suffix, "(", + &res, ", ", source, ", ", &amount, ");\n"); + rvalue_free(c, locp, source); + rvalue_free(c, locp, &amount); + + return res; +} + +const char *INTERLEAVE_MASKS[6] =3D { + "0x5555555555555555ULL", + "0x3333333333333333ULL", + "0x0f0f0f0f0f0f0f0fULL", + "0x00ff00ff00ff00ffULL", + "0x0000ffff0000ffffULL", + "0x00000000ffffffffULL", +}; + +HexValue gen_deinterleave(Context *c, YYLTYPE *locp, HexValue *mixed) +{ + HexValue src =3D rvalue_extend(c, locp, mixed); + + HexValue a =3D gen_tmp(c, locp, 64); + a.is_unsigned =3D true; + HexValue b =3D gen_tmp(c, locp, 64); + b.is_unsigned =3D true; + + const char **masks =3D INTERLEAVE_MASKS; + + OUT(c, locp, "tcg_gen_shri_i64(", &a, ", ", &src, ", 1);\n"); + OUT(c, locp, "tcg_gen_andi_i64(", &a, ", ", &a, ", ", masks[0], ");\n"= ); + OUT(c, locp, "tcg_gen_andi_i64(", &b, ", ", &src, ", ", masks[0], ");\= n"); + + HexValue res =3D gen_tmp(c, locp, 64); + res.is_unsigned =3D true; + + unsigned shift =3D 1; + for (unsigned i =3D 1; i < 6; ++i) { + OUT(c, locp, "tcg_gen_shri_i64(", &res, ", ", &b, ", ", &shift, ")= ;\n"); + OUT(c, locp, "tcg_gen_or_i64(", &b, ", ", &res, ", ", &b, ");\n"); + OUT(c, locp, "tcg_gen_andi_i64(", &b, ", ", &b, ", ", masks[i], ")= ;\n"); + OUT(c, locp, "tcg_gen_shri_i64(", &res, ", ", &a, ", ", &shift, ")= ;\n"); + OUT(c, locp, "tcg_gen_or_i64(", &a, ", ", &res, ", ", &a, ");\n"); + OUT(c, locp, "tcg_gen_andi_i64(", &a, ", ", &a, ", ", masks[i], ")= ;\n"); + shift <<=3D 1; + } + + OUT(c, locp, "tcg_gen_shli_i64(", &a, ", ", &a, ", 32);\n"); + OUT(c, locp, "tcg_gen_or_i64(", &res, ", ", &a, ", ", &b, ");\n"); + + rvalue_free(c, locp, &a); + rvalue_free(c, locp, &b); + + return res; +} + +HexValue gen_interleave(Context *c, + YYLTYPE *locp, + HexValue *odd, + HexValue *even) +{ + HexValue a =3D rvalue_truncate(c, locp, odd); + a.is_unsigned =3D true; + HexValue b =3D rvalue_truncate(c, locp, even); + a.is_unsigned =3D true; + + a =3D rvalue_extend(c, locp, &a); + b =3D rvalue_extend(c, locp, &b); + + HexValue res =3D gen_tmp(c, locp, 64); + res.is_unsigned =3D true; + + const char **masks =3D INTERLEAVE_MASKS; + + unsigned shift =3D 16; + for (int i =3D 4; i >=3D 0; --i) { + OUT(c, locp, "tcg_gen_shli_i64(", &res, ", ", &a, ", ", &shift, ")= ;\n"); + OUT(c, locp, "tcg_gen_or_i64(", &a, ", ", &res, ", ", &a, ");\n"); + OUT(c, locp, "tcg_gen_andi_i64(", &a, ", ", &a, ", ", masks[i], ")= ;\n"); + OUT(c, locp, "tcg_gen_shli_i64(", &res, ", ", &b, ", ", &shift, ")= ;\n"); + OUT(c, locp, "tcg_gen_or_i64(", &b, ", ", &res, ", ", &b, ");\n"); + OUT(c, locp, "tcg_gen_andi_i64(", &b, ", ", &b, ", ", masks[i], ")= ;\n"); + shift >>=3D 1; + } + + OUT(c, locp, "tcg_gen_shli_i64(", &a, ", ", &a, ", 1);\n"); + OUT(c, locp, "tcg_gen_or_i64(", &res, ", ", &a, ", ", &b, ");\n"); + + rvalue_free(c, locp, &a); + rvalue_free(c, locp, &b); + + return res; +} + +HexValue gen_carry_from_add(Context *c, + YYLTYPE *locp, + HexValue *op1, + HexValue *op2, + HexValue *op3) +{ + HexValue opa =3D rvalue_materialize(c, locp, op1); + HexValue opb =3D rvalue_materialize(c, locp, op2); + HexValue opc =3D rvalue_materialize(c, locp, op3); + opc =3D rvalue_extend(c, locp, &opc); + + HexValue zero =3D gen_tmp_value(c, locp, "0", 64); + HexValue res =3D gen_tmp(c, locp, 64); + HexValue cf =3D gen_tmp(c, locp, 64); + OUT(c, locp, "tcg_gen_add2_i64(", &res, ", ", &cf, ", ", &opa, ", ", &= zero); + OUT(c, locp, ", ", &opc, ", ", &zero, ");\n"); + OUT(c, locp, "tcg_gen_add2_i64(", &res, ", ", &cf, ", ", &res, ", ", &= cf); + OUT(c, locp, ", ", &opb, ", ", &zero, ");\n"); + + rvalue_free(c, locp, &opa); + rvalue_free(c, locp, &opb); + rvalue_free(c, locp, &opc); + rvalue_free(c, locp, &zero); + rvalue_free(c, locp, &res); + return cf; +} + +void gen_inst(Context *c, GString *iname) +{ + c->total_insn++; + c->inst.name =3D iname; + c->inst.allocated =3D g_array_new(FALSE, FALSE, sizeof(Var)); + c->inst.init_list =3D g_array_new(FALSE, FALSE, sizeof(HexValue)); + c->inst.strings =3D g_array_new(FALSE, FALSE, sizeof(GString *)); + EMIT_SIG(c, "void emit_%s(DisasContext *ctx, Insn *insn, Packet *pkt", + c->inst.name->str); +} + +void gen_inst_args(Context *c, YYLTYPE *locp) +{ + EMIT_SIG(c, ")"); + EMIT_HEAD(c, "{\n"); + + /* Initialize declared but uninitialized registers, but only for */ + /* non-conditional instructions */ + for (int i =3D 0; i < c->inst.init_list->len; i++) { + HexValue *reg =3D &g_array_index(c->inst.init_list, HexValue, i); + if (reg->type =3D=3D REGISTER || reg->type =3D=3D PREDICATE) { + OUT(c, locp, "tcg_gen_movi_i", ®->bit_width, "(", + reg, ", 0);\n"); + } + } +} + +void gen_inst_code(Context *c, YYLTYPE *locp) +{ + if (c->inst.error_count !=3D 0) { + fprintf(stderr, + "Parsing of instruction %s generated %d errors!\n", + c->inst.name->str, + c->inst.error_count); + } else { + free_variables(c, locp); + c->implemented_insn++; + fprintf(c->enabled_file, "%s\n", c->inst.name->str); + emit_footer(c); + commit(c); + } + free_instruction(c); +} + +void gen_pre_assign(Context *c, YYLTYPE *locp, HexValue *l, HexValue *r) +{ + bool is_direct =3D is_direct_predicate(l); + char pre_id[2] =3D " "; + pre_id[0] =3D l->pre.id; + /* Extract predicate TCGv */ + if (is_direct) { + *l =3D gen_tmp_value(c, locp, "0", 32); + } + *r =3D rvalue_materialize(c, locp, r); + *r =3D rvalue_truncate(c, locp, r); + /* Extract first 8 bits, and store new predicate value */ + if (r->type =3D=3D IMMEDIATE) { + OUT(c, locp, &r, " =3D (", r, " & 0xff) << i;\n"); + OUT(c, locp, "tcg_gen_ori_i32(", l, ", ", l, ", ", r, ");\n"); + } else { + OUT(c, locp, "tcg_gen_mov_i32(", l, ", ", r, ");\n"); + OUT(c, locp, "tcg_gen_andi_i32(", l, ", ", l, ", 0xff);\n"); + } + if (is_direct) { + OUT(c, locp, "gen_log_pred_write(", pre_id, ", ", l, ");\n"); + OUT(c, locp, "ctx_log_pred_write(ctx, ", pre_id, ");\n"); + rvalue_free(c, locp, l); + } + rvalue_free(c, locp, r); /* Free temporary value */ +} + +void gen_load(Context *c, YYLTYPE *locp, HexValue *num, HexValue *size, + bool is_unsigned, HexValue *ea, HexValue *dst) +{ + /* Memop width is specified in the load macro */ + int bit_width =3D (size->imm.value > 4) ? 64 : 32; + const char *sign_suffix =3D (size->imm.value > 4) + ? "" + : ((is_unsigned) ? "u" : "s"); + char size_suffix[4] =3D { 0 }; + /* Create temporary variable (if not present) */ + if (dst->type =3D=3D VARID) { + /* TODO: this is a common pattern, the parser should be varid-awar= e. */ + varid_allocate(c, locp, dst, bit_width, is_unsigned); + } + snprintf(size_suffix, 4, "%" PRIu64, size->imm.value * 8); + if (bit_width =3D=3D 32) { + *dst =3D rvalue_truncate(c, locp, dst); + } else { + *dst =3D rvalue_extend(c, locp, dst); + } + int var_id =3D find_variable(c, locp, ea); + yyassert(c, locp, var_id !=3D -1, "Load variable must exist!\n"); + /* We need to enforce the variable size */ + ea->bit_width =3D g_array_index(c->inst.allocated, Var, var_id).bit_wi= dth; + if (ea->bit_width !=3D 32) { + *ea =3D rvalue_truncate(c, locp, ea); + } + OUT(c, locp, "if (insn->slot =3D=3D 0 && pkt->pkt_has_store_s1) {\n"); + OUT(c, locp, "process_store(ctx, pkt, 1);\n"); + OUT(c, locp, "}\n"); + OUT(c, locp, "tcg_gen_qemu_ld", size_suffix, sign_suffix); + OUT(c, locp, "(", dst, ", ", ea, ", 0);\n"); + /* If the var in EA was truncated it is now a tmp HexValue, so free it= . */ + rvalue_free(c, locp, ea); +} + +void gen_store(Context *c, YYLTYPE *locp, HexValue *num, HexValue *size, + HexValue *ea, HexValue *src) +{ + /* Memop width is specified in the store macro */ + int mem_width =3D size->imm.value; + /* Adjust operand bit width to memop bit width */ + if (mem_width < 8) { + *src =3D rvalue_truncate(c, locp, src); + } else { + *src =3D rvalue_extend(c, locp, src); + } + assert(ea->type =3D=3D VARID); + int var_id =3D find_variable(c, locp, ea); + yyassert(c, locp, var_id !=3D -1, "Load variable must exist!\n"); + /* We need to enforce the variable size */ + ea->bit_width =3D g_array_index(c->inst.allocated, Var, var_id).bit_wi= dth; + if (ea->bit_width !=3D 32) { + *ea =3D rvalue_truncate(c, locp, ea); + } + *src =3D rvalue_materialize(c, locp, src); + OUT(c, locp, "gen_store", &mem_width, "(cpu_env, ", ea, ", ", src); + OUT(c, locp, ", ctx, insn->slot);\n"); + rvalue_free(c, locp, src); + /* If the var in ea was truncated it is now a tmp HexValue, so free it= . */ + rvalue_free(c, locp, ea); +} + +void gen_sethalf(Context *c, YYLTYPE *locp, HexCast *sh, HexValue *n, + HexValue *dst, HexValue *val) +{ + yyassert(c, locp, n->type =3D=3D IMMEDIATE, + "Deposit index must be immediate!\n"); + if (dst->type =3D=3D VARID) { + int var_id =3D find_variable(c, locp, dst); + if (var_id =3D=3D -1) { + HexValue zero =3D gen_imm_value(c, locp, 0, 64); + zero.is_unsigned =3D true; + dst->bit_width =3D 64; + gen_assign(c, locp, dst, &zero); + } else { + /* We need to enforce the variable size (default is 32) */ + dst->bit_width =3D g_array_index(c->inst.allocated, + Var, + var_id).bit_width; + } + } + gen_deposit_op(c, locp, dst, val, n, sh); +} + +void gen_setbits(Context *c, YYLTYPE *locp, HexValue *hi, HexValue *lo, + HexValue *dst, HexValue *val) +{ + yyassert(c, locp, hi->type =3D=3D IMMEDIATE && + hi->imm.type =3D=3D VALUE && + lo->type =3D=3D IMMEDIATE && + lo->imm.type =3D=3D VALUE, + "Range deposit needs immediate values!\n"); + + *val =3D rvalue_truncate(c, locp, val); + unsigned len =3D hi->imm.value + 1 - lo->imm.value; + HexValue tmp =3D gen_tmp(c, locp, 32); + OUT(c, locp, "tcg_gen_neg_i32(", &tmp, ", ", val, ");\n"); + OUT(c, locp, "tcg_gen_deposit_i32(", dst, ", ", dst, ", ", &tmp, ", "); + OUT(c, locp, lo, ", ", &len, ");\n"); + + rvalue_free(c, locp, &tmp); + rvalue_free(c, locp, hi); + rvalue_free(c, locp, lo); + rvalue_free(c, locp, val); +} + +int gen_if_cond(Context *c, YYLTYPE *locp, HexValue *cond) +{ + /* Generate an end label, if false branch to that label */ + OUT(c, locp, "TCGLabel *if_label_", &c->inst.if_count, + " =3D gen_new_label();\n"); + *cond =3D rvalue_materialize(c, locp, cond); + const char *bit_suffix =3D (cond->bit_width =3D=3D 64) ? "i64" : "i32"; + OUT(c, locp, "tcg_gen_brcondi_", bit_suffix, "(TCG_COND_EQ, ", cond, + ", 0, if_label_", &c->inst.if_count, ");\n"); + rvalue_free(c, locp, cond); + return c->inst.if_count++; +} + +int gen_if_else(Context *c, YYLTYPE *locp, int index) +{ + /* Generate label to jump if else is not verified */ + OUT(c, locp, "TCGLabel *if_label_", &c->inst.if_count, + " =3D gen_new_label();\n"); + int if_index =3D c->inst.if_count; + c->inst.if_count++; + /* Jump out of the else statement */ + OUT(c, locp, "tcg_gen_br(if_label_", &if_index, ");\n"); + /* Fix the else label */ + OUT(c, locp, "gen_set_label(if_label_", &index, ");\n"); + return if_index; +} + +HexValue gen_rvalue_pre(Context *c, YYLTYPE *locp, HexValue *pre) +{ + if (is_direct_predicate(pre)) { + bool is_dotnew =3D pre->is_dotnew; + char predicate_id[2] =3D { pre->pre.id, '\0' }; + char *pre_str =3D (char *) &predicate_id; + *pre =3D gen_tmp_value(c, locp, "0", 32); + if (is_dotnew) { + OUT(c, locp, "tcg_gen_mov_i32(", pre, ", hex_new_pred_value["); + OUT(c, locp, pre_str, "]);\n"); + } else { + OUT(c, locp, "gen_read_preg(", pre, ", ", pre_str, ");\n"); + } + } + return *pre; +} + +HexValue gen_rvalue_var(Context *c, YYLTYPE *locp, HexValue *var) +{ + /* Assign correct bit width and signedness */ + bool found =3D false; + for (int i =3D 0; i < c->inst.allocated->len; i++) { + Var *other =3D &g_array_index(c->inst.allocated, Var, i); + if (g_string_equal(var->var.name, other->name)) { + found =3D true; + other->name =3D var->var.name; + var->bit_width =3D other->bit_width; + var->is_unsigned =3D other->is_unsigned; + break; + } + } + yyassert(c, locp, found, "Undefined symbol!\n"); + return *var; +} + +HexValue gen_rvalue_mpy(Context *c, YYLTYPE *locp, HexMpy *mpy, HexValue *= a, + HexValue *b) +{ + a->is_unsigned =3D mpy->first_unsigned; + b->is_unsigned =3D mpy->second_unsigned; + *a =3D gen_cast_op(c, locp, a, mpy->first_bit_width * 2); + /* Handle fMPTY3216.. */ + if (mpy->first_bit_width =3D=3D 32) { + *b =3D gen_cast_op(c, locp, b, 64); + } else { + *b =3D gen_cast_op(c, locp, b, mpy->second_bit_width * 2); + } + HexValue ret =3D gen_bin_op(c, locp, MUL_OP, a, b); + /* Handle special cases required by the language */ + if (mpy->first_bit_width =3D=3D 16 && mpy->second_bit_width =3D=3D 16)= { + HexValue src_width =3D gen_imm_value(c, locp, 32, 32); + HexValue dst_width =3D gen_imm_value(c, locp, 64, 32); + ret =3D gen_extend_op(c, locp, &src_width, &dst_width, &ret, + mpy->first_unsigned && mpy->second_unsigned); + } + return ret; +} + +HexValue gen_rvalue_pow(Context *c, YYLTYPE *locp, HexValue *l, HexValue *= r) +{ + /* We assume that this is a shorthand for a shift */ + yyassert(c, locp, l->type =3D=3D IMMEDIATE && r->imm.value =3D=3D 2, + "Exponentiation is not a left shift!\n"); + HexValue one =3D gen_imm_value(c, locp, 1, 32); + HexValue shift =3D gen_bin_op(c, locp, SUB_OP, r, &one); + HexValue res =3D gen_bin_op(c, locp, ASL_OP, l, &shift); + rvalue_free(c, locp, &one); + rvalue_free(c, locp, &shift); + return res; +} + +HexValue gen_rvalue_not(Context *c, YYLTYPE *locp, HexValue *v) +{ + const char *bit_suffix =3D (v->bit_width =3D=3D 64) ? "i64" : "i32"; + int bit_width =3D (v->bit_width =3D=3D 64) ? 64 : 32; + HexValue res; + res.is_unsigned =3D v->is_unsigned; + res.is_dotnew =3D false; + res.is_manual =3D false; + if (v->type =3D=3D IMMEDIATE) { + res.type =3D IMMEDIATE; + res.imm.type =3D QEMU_TMP; + res.imm.index =3D c->inst.qemu_tmp_count; + OUT(c, locp, "int", &bit_width, "_t ", &res, " =3D ~", v, ";\n"); + c->inst.qemu_tmp_count++; + } else { + res =3D gen_tmp(c, locp, bit_width); + OUT(c, locp, "tcg_gen_not_", bit_suffix, "(", &res, + ", ", v, ");\n"); + rvalue_free(c, locp, v); + } + return res; +} + +HexValue gen_rvalue_notl(Context *c, YYLTYPE *locp, HexValue *v) +{ + const char *bit_suffix =3D (v->bit_width =3D=3D 64) ? "i64" : "i32"; + int bit_width =3D (v->bit_width =3D=3D 64) ? 64 : 32; + HexValue res; + res.is_unsigned =3D v->is_unsigned; + res.is_dotnew =3D false; + res.is_manual =3D false; + if (v->type =3D=3D IMMEDIATE) { + res.type =3D IMMEDIATE; + res.imm.type =3D QEMU_TMP; + res.imm.index =3D c->inst.qemu_tmp_count; + OUT(c, locp, "int", &bit_width, "_t ", &res, " =3D !", v, ";\n"); + c->inst.qemu_tmp_count++; + } else { + res =3D gen_tmp(c, locp, bit_width); + HexValue zero =3D gen_tmp_value(c, locp, "0", bit_width); + HexValue one =3D gen_tmp_value(c, locp, "0xff", bit_width); + OUT(c, locp, "tcg_gen_movcond_", bit_suffix); + OUT(c, locp, "(TCG_COND_EQ, ", &res, ", ", v, ", ", &zero); + OUT(c, locp, ", ", &one, ", ", &zero, ");\n"); + rvalue_free(c, locp, v); + rvalue_free(c, locp, &zero); + rvalue_free(c, locp, &one); + } + return res; +} + +HexValue gen_rvalue_sat(Context *c, YYLTYPE *locp, HexSat *sat, HexValue *= n, + HexValue *v) +{ + if (sat->set_overflow) { + yyassert(c, locp, n->imm.value < v->bit_width, "To compute overflo= w, " + "source width must be greater than saturation width!"); + } + HexValue res =3D gen_tmp(c, locp, v->bit_width); + const char *bit_suffix =3D (v->bit_width =3D=3D 64) ? "i64" : "i32"; + const char *overflow_str =3D (sat->set_overflow) ? "true" : "false"; + const char *unsigned_str =3D (sat->is_unsigned) ? "u" : ""; + OUT(c, locp, "gen_sat", unsigned_str, "_", bit_suffix, "(", &res, ", "= ); + OUT(c, locp, v, ", ", &n->imm.value, ", ", overflow_str, ");\n"); + res.is_unsigned =3D sat->is_unsigned; + rvalue_free(c, locp, v); + return res; +} + +HexValue gen_rvalue_fscr(Context *c, YYLTYPE *locp, HexValue *v) +{ + HexValue key =3D gen_tmp(c, locp, 64); + HexValue res =3D gen_tmp(c, locp, 64); + *v =3D rvalue_extend(c, locp, v); + HexValue frame_key =3D gen_tmp(c, locp, 32); + OUT(c, locp, "READ_REG(", &frame_key, ", HEX_REG_FRAMEKEY);\n"); + OUT(c, locp, "tcg_gen_concat_i32_i64(", + &key, ", ", &frame_key, ", ", &frame_key, ");\n"); + OUT(c, locp, "tcg_gen_xor_i64(", &res, ", ", v, ", ", &key, ");\n"); + rvalue_free(c, locp, &key); + rvalue_free(c, locp, &frame_key); + rvalue_free(c, locp, v); + return res; +} + +HexValue gen_rvalue_abs(Context *c, YYLTYPE *locp, HexValue *v) +{ + const char *bit_suffix =3D (v->bit_width =3D=3D 64) ? "i64" : "i32"; + int bit_width =3D (v->bit_width =3D=3D 64) ? 64 : 32; + HexValue res; + res.is_unsigned =3D v->is_unsigned; + res.is_dotnew =3D false; + res.is_manual =3D false; + if (v->type =3D=3D IMMEDIATE) { + res.type =3D IMMEDIATE; + res.imm.type =3D QEMU_TMP; + res.imm.index =3D c->inst.qemu_tmp_count; + OUT(c, locp, "int", &bit_width, "_t ", &res, " =3D abs(", v, ");\n= "); + c->inst.qemu_tmp_count++; + } else { + res =3D gen_tmp(c, locp, bit_width); + HexValue zero =3D gen_tmp_value(c, locp, "0", bit_width); + OUT(c, locp, "tcg_gen_neg_", bit_suffix, "(", &res, ", ", v, ");\n= "); + OUT(c, locp, "tcg_gen_movcond_i", &bit_width); + OUT(c, locp, "(TCG_COND_GT, ", &res, ", ", v, ", ", &zero); + OUT(c, locp, ", ", v, ", ", &res, ");\n"); + rvalue_free(c, locp, &zero); + rvalue_free(c, locp, v); + } + return res; +} + +HexValue gen_rvalue_neg(Context *c, YYLTYPE *locp, HexValue *v) +{ + const char *bit_suffix =3D (v->bit_width =3D=3D 64) ? "i64" : "i32"; + int bit_width =3D (v->bit_width =3D=3D 64) ? 64 : 32; + HexValue res; + res.is_unsigned =3D v->is_unsigned; + res.is_dotnew =3D false; + res.is_manual =3D false; + if (v->type =3D=3D IMMEDIATE) { + res.type =3D IMMEDIATE; + res.imm.type =3D QEMU_TMP; + res.imm.index =3D c->inst.qemu_tmp_count; + OUT(c, locp, "int", &bit_width, "_t ", &res, " =3D -", v, ";\n"); + c->inst.qemu_tmp_count++; + } else { + res =3D gen_tmp(c, locp, bit_width); + OUT(c, locp, "tcg_gen_neg_", bit_suffix, "(", &res, ", ", v, ");\n= "); + rvalue_free(c, locp, v); + } + return res; +} + +HexValue gen_rvalue_brev(Context *c, YYLTYPE *locp, HexValue *v) +{ + yyassert(c, locp, v->bit_width <=3D 32, + "fbrev not implemented for 64-bit integers!"); + HexValue res =3D gen_tmp(c, locp, v->bit_width); + *v =3D rvalue_materialize(c, locp, v); + OUT(c, locp, "gen_fbrev(", &res, ", ", v, ");\n"); + rvalue_free(c, locp, v); + return res; +} + +const char *cond_to_str(TCGCond cond) +{ + switch (cond) { + case TCG_COND_NEVER: + return "TCG_COND_NEVER"; + case TCG_COND_ALWAYS: + return "TCG_COND_ALWAYS"; + case TCG_COND_EQ: + return "TCG_COND_EQ"; + case TCG_COND_NE: + return "TCG_COND_NE"; + case TCG_COND_LT: + return "TCG_COND_LT"; + case TCG_COND_GE: + return "TCG_COND_GE"; + case TCG_COND_LE: + return "TCG_COND_LE"; + case TCG_COND_GT: + return "TCG_COND_GT"; + case TCG_COND_LTU: + return "TCG_COND_LTU"; + case TCG_COND_GEU: + return "TCG_COND_GEU"; + case TCG_COND_LEU: + return "TCG_COND_LEU"; + case TCG_COND_GTU: + return "TCG_COND_GTU"; + default: + abort(); + } +} + +void emit_arg(Context *c, YYLTYPE *locp, HexValue *arg) +{ + switch (arg->type) { + case REGISTER: + if (arg->reg.type =3D=3D DOTNEW) { + EMIT_SIG(c, ", TCGv N%cN", arg->reg.id); + } else { + bool is64 =3D (arg->bit_width =3D=3D 64); + const char *type =3D is64 ? "TCGv_i64" : "TCGv_i32"; + char reg_id[5] =3D { 0 }; + reg_compose(c, locp, &(arg->reg), reg_id); + EMIT_SIG(c, ", %s %s", type, reg_id); + /* MuV register requires also MuN to provide its index */ + if (arg->reg.type =3D=3D MODIFIER) { + EMIT_SIG(c, ", int MuN"); + } + } + break; + case PREDICATE: + { + char suffix =3D arg->is_dotnew ? 'N' : 'V'; + EMIT_SIG(c, ", TCGv P%c%c", arg->pre.id, suffix); + } + break; + default: + { + fprintf(stderr, "emit_arg got unsupported argument!"); + abort(); + } + } +} + +void emit_footer(Context *c) +{ + EMIT(c, "}\n"); + EMIT(c, "\n"); +} + +void track_string(Context *c, GString *s) +{ + g_array_append_val(c->inst.strings, s); +} + +void free_variables(Context *c, YYLTYPE *locp) +{ + for (unsigned i =3D 0; i < c->inst.allocated->len; ++i) { + Var *var =3D &g_array_index(c->inst.allocated, Var, i); + const char *suffix =3D var->bit_width =3D=3D 64 ? "i64" : "i32"; + OUT(c, locp, "tcg_temp_free_", suffix, "(", var->name->str, ");\n"= ); + } +} + +void free_instruction(Context *c) +{ + /* Free the strings */ + g_string_truncate(c->signature_str, 0); + g_string_truncate(c->out_str, 0); + g_string_truncate(c->header_str, 0); + /* Free strings allocated by the instruction */ + for (int i =3D 0; i < c->inst.strings->len; i++) { + g_string_free(g_array_index(c->inst.strings, GString*, i), TRUE); + } + g_array_free(c->inst.strings, TRUE); + /* Free INAME token value */ + g_string_free(c->inst.name, TRUE); + /* Free variables and registers */ + g_array_free(c->inst.allocated, TRUE); + g_array_free(c->inst.init_list, TRUE); + /* Initialize instruction-specific portion of the context */ + memset(&(c->inst), 0, sizeof(Inst)); +} diff --git a/target/hexagon/idef-parser/parser-helpers.h b/target/hexagon/i= def-parser/parser-helpers.h new file mode 100644 index 0000000000..59b66f3943 --- /dev/null +++ b/target/hexagon/idef-parser/parser-helpers.h @@ -0,0 +1,344 @@ +/* + * Copyright(c) 2019-2021 rev.ng Srls. All Rights Reserved. + * + * 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 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 . + */ + +#ifndef PARSER_HELPERS_H +#define PARSER_HELPERS_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "qemu/compiler.h" +#include "tcg/tcg-cond.h" + +#include "idef-parser.tab.h" +#include "idef-parser.yy.h" +#include "idef-parser.h" + +/* Decomment this to disable yyasserts */ +/* #define NDEBUG */ + +#define ERR_LINE_CONTEXT 40 + +#define START_COMMENT "/" "*" +#define END_COMMENT "*" "/" + +void yyerror(YYLTYPE *locp, + yyscan_t scanner __attribute__((unused)), + Context *c, + const char *s); + +#ifndef NDEBUG +#define yyassert(context, locp, condition, msg) \ + if (!(condition)) { \ + yyerror(locp, (context)->scanner, (context), (msg)); \ + } +#endif + +bool is_direct_predicate(HexValue *value); + +/* Print functions */ +void str_print(Context *c, YYLTYPE *locp, const char *string); + +void uint64_print(Context *c, YYLTYPE *locp, uint64_t *num); + +void int_print(Context *c, YYLTYPE *locp, int *num); + +void uint_print(Context *c, YYLTYPE *locp, unsigned *num); + +void tmp_print(Context *c, YYLTYPE *locp, HexTmp *tmp); + +void pre_print(Context *c, YYLTYPE *locp, HexPre *pre, bool is_dotnew); + +void reg_compose(Context *c, YYLTYPE *locp, HexReg *reg, char reg_id[5]); + +void reg_print(Context *c, YYLTYPE *locp, HexReg *reg); + +void imm_print(Context *c, YYLTYPE *locp, HexImm *imm); + +void var_print(Context *c, YYLTYPE *locp, HexVar *var); + +void rvalue_out(Context *c, YYLTYPE *locp, void *pointer); + +void out_assert(Context *c, YYLTYPE *locp, void *dummy); + +/* Copy output code buffer into stdout */ +void commit(Context *c); + +#define OUT_IMPL(c, locp, x) \ + do { \ + QEMU_GENERIC(typeof(*x), \ + (char, str_print), \ + (uint64_t, uint64_print), \ + (int, int_print), \ + (unsigned, uint_print), \ + (HexValue, rvalue_out), \ + out_assert \ + )(c, locp, x); \ + } while (0); + +/* Make a FOREACH macro */ +#define FE_1(c, locp, WHAT, X) WHAT(c, locp, X) +#define FE_2(c, locp, WHAT, X, ...) \ + WHAT(c, locp, X)FE_1(c, locp, WHAT, __VA_ARGS__) +#define FE_3(c, locp, WHAT, X, ...) \ + WHAT(c, locp, X)FE_2(c, locp, WHAT, __VA_ARGS__) +#define FE_4(c, locp, WHAT, X, ...) \ + WHAT(c, locp, X)FE_3(c, locp, WHAT, __VA_ARGS__) +#define FE_5(c, locp, WHAT, X, ...) \ + WHAT(c, locp, X)FE_4(c, locp, WHAT, __VA_ARGS__) +#define FE_6(c, locp, WHAT, X, ...) \ + WHAT(c, locp, X)FE_5(c, locp, WHAT, __VA_ARGS__) +#define FE_7(c, locp, WHAT, X, ...) \ + WHAT(c, locp, X)FE_6(c, locp, WHAT, __VA_ARGS__) +#define FE_8(c, locp, WHAT, X, ...) \ + WHAT(c, locp, X)FE_7(c, locp, WHAT, __VA_ARGS__) +#define FE_9(c, locp, WHAT, X, ...) \ + WHAT(c, locp, X)FE_8(c, locp, WHAT, __VA_ARGS__) +/* repeat as needed */ + +#define GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, NAME, ...) NAME + +#define FOR_EACH(c, locp, action, ...) \ + do { \ + GET_MACRO(__VA_ARGS__, \ + FE_9, \ + FE_8, \ + FE_7, \ + FE_6, \ + FE_5, \ + FE_4, \ + FE_3, \ + FE_2, \ + FE_1)(c, locp, action, \ + __VA_ARGS__) \ + } while (0) + +#define OUT(c, locp, ...) FOR_EACH((c), (locp), OUT_IMPL, __VA_ARGS__) + +const char *cmp_swap(Context *c, YYLTYPE *locp, const char *type); + +/* Temporary values creation */ +HexValue gen_tmp(Context *c, YYLTYPE *locp, int bit_width); + +HexValue gen_tmp_value(Context *c, + YYLTYPE *locp, + const char *value, + int bit_width); + +HexValue gen_imm_value(Context *c __attribute__((unused)), + YYLTYPE *locp, + int value, + int bit_width); + +void rvalue_free(Context *c, YYLTYPE *locp, HexValue *rvalue); + +HexValue rvalue_materialize(Context *c, YYLTYPE *locp, HexValue *rvalue); + +HexValue rvalue_extend(Context *c, YYLTYPE *locp, HexValue *rvalue); + +HexValue rvalue_truncate(Context *c, YYLTYPE *locp, HexValue *rvalue); + +int find_variable(Context *c, YYLTYPE *locp, HexValue *varid); + +void varid_allocate(Context *c, + YYLTYPE *locp, + HexValue *varid, + int width, + bool is_unsigned); + +void ea_free(Context *c, YYLTYPE *locp); + +HexValue gen_bin_cmp(Context *c, + YYLTYPE *locp, + TCGCond type, + HexValue *op1_ptr, + HexValue *op2_ptr); + +/* Code generation functions */ +HexValue gen_bin_op(Context *c, + YYLTYPE *locp, + OpType type, + HexValue *operand1, + HexValue *operand2); + +HexValue gen_cast_op(Context *c, + YYLTYPE *locp, + HexValue *source, + unsigned target_width); + +HexValue gen_extend_op(Context *c, + YYLTYPE *locp, + HexValue *src_width_ptr, + HexValue *dst_width_ptr, + HexValue *value_ptr, + bool is_unsigned); + +void gen_rdeposit_op(Context *c, + YYLTYPE *locp, + HexValue *dest, + HexValue *value, + HexValue *begin, + HexValue *width); + +void gen_deposit_op(Context *c, + YYLTYPE *locp, + HexValue *dest, + HexValue *value, + HexValue *index, + HexCast *cast); + +HexValue gen_rextract_op(Context *c, + YYLTYPE *locp, + HexValue *source, + int begin, + int width); + +HexValue gen_extract_op(Context *c, + YYLTYPE *locp, + HexValue *source, + HexValue *index, + HexExtract *extract); + +HexValue gen_read_creg(Context *c, YYLTYPE *locp, HexValue *reg); + +void gen_write_creg(Context *c, + YYLTYPE *locp, + HexValue *reg, + HexValue *value); + +void gen_assign(Context *c, + YYLTYPE *locp, + HexValue *dest, + HexValue *value); + +HexValue gen_convround(Context *c, + YYLTYPE *locp, + HexValue *source); + +HexValue gen_round(Context *c, + YYLTYPE *locp, + HexValue *source, + HexValue *position); + +HexValue gen_convround_n(Context *c, + YYLTYPE *locp, + HexValue *source_ptr, + HexValue *bit_pos_ptr); + +/* Circular addressing mode with auto-increment */ +void gen_circ_op(Context *c, + YYLTYPE *locp, + HexValue *addr, + HexValue *increment, + HexValue *modifier); + +HexValue gen_locnt_op(Context *c, YYLTYPE *locp, HexValue *source); + +HexValue gen_ctpop_op(Context *c, YYLTYPE *locp, HexValue *source); + +HexValue gen_fbrev_4(Context *c, YYLTYPE *locp, HexValue *source); + +HexValue gen_fbrev_8(Context *c, YYLTYPE *locp, HexValue *source); + +HexValue gen_rotl(Context *c, YYLTYPE *locp, HexValue *source, HexValue *n= ); + +HexValue gen_deinterleave(Context *c, YYLTYPE *locp, HexValue *mixed); + +HexValue gen_interleave(Context *c, + YYLTYPE *locp, + HexValue *odd, + HexValue *even); + +HexValue gen_carry_from_add(Context *c, + YYLTYPE *locp, + HexValue *op1, + HexValue *op2, + HexValue *op3); + +void gen_inst(Context *c, GString *iname); + +void gen_inst_args(Context *c, YYLTYPE *locp); + +void gen_inst_code(Context *c, YYLTYPE *locp); + +void gen_pre_assign(Context *c, YYLTYPE *locp, HexValue *l, HexValue *r); + +void gen_load(Context *c, YYLTYPE *locp, HexValue *num, HexValue *size, + bool is_unsigned, HexValue *ea, HexValue *dst); + +void gen_store(Context *c, YYLTYPE *locp, HexValue *num, HexValue *size, + HexValue *ea, HexValue *src); + +void gen_sethalf(Context *c, YYLTYPE *locp, HexCast *sh, HexValue *n, + HexValue *dst, HexValue *val); + +void gen_setbits(Context *c, YYLTYPE *locp, HexValue *hi, HexValue *lo, + HexValue *dst, HexValue *val); + +int gen_if_cond(Context *c, YYLTYPE *locp, HexValue *cond); + +int gen_if_else(Context *c, YYLTYPE *locp, int index); + +HexValue gen_rvalue_pre(Context *c, YYLTYPE *locp, HexValue *pre); + +HexValue gen_rvalue_var(Context *c, YYLTYPE *locp, HexValue *var); + +HexValue gen_rvalue_mpy(Context *c, YYLTYPE *locp, HexMpy *mpy, HexValue *= a, + HexValue *b); + +HexValue gen_rvalue_pow(Context *c, YYLTYPE *locp, HexValue *l, HexValue *= r); + +HexValue gen_rvalue_not(Context *c, YYLTYPE *locp, HexValue *v); + +HexValue gen_rvalue_notl(Context *c, YYLTYPE *locp, HexValue *v); + +HexValue gen_rvalue_sat(Context *c, YYLTYPE *locp, HexSat *sat, HexValue *= n, + HexValue *v); + +HexValue gen_rvalue_ternary(Context *c, YYLTYPE *locp, HexValue *cond, + HexValue *t, HexValue *e); + +HexValue gen_rvalue_fscr(Context *c, YYLTYPE *locp, HexValue *v); + +HexValue gen_rvalue_abs(Context *c, YYLTYPE *locp, HexValue *v); + +HexValue gen_rvalue_neg(Context *c, YYLTYPE *locp, HexValue *v); + +HexValue gen_rvalue_brev(Context *c, YYLTYPE *locp, HexValue *v); + +const char *cond_to_str(TCGCond cond); + +void emit_header(Context *c); + +void emit_arg(Context *c, YYLTYPE *locp, HexValue *arg); + +void emit_footer(Context *c); + +void track_string(Context *c, GString *s); + +void free_variables(Context *c, YYLTYPE *locp); + +void free_instruction(Context *c); + +#endif /* PARSER_HELPERS_h */ diff --git a/target/hexagon/meson.build b/target/hexagon/meson.build index 5dda04dc29..2b7d6c8c62 100644 --- a/target/hexagon/meson.build +++ b/target/hexagon/meson.build @@ -197,7 +197,7 @@ idef_parser_input_generated =3D custom_target( command: [python, '@INPUT@', semantics_generated, attribs_def, gen_tcg= _h, '@OUTPUT@'], ) =20 -idef_parser_input_generated_prep =3D custom_target( +preprocessed_idef_parser_input_generated =3D custom_target( 'idef_parser_input.preprocessed.h.inc', output: 'idef_parser_input.preprocessed.h.inc', input: idef_parser_input_generated, @@ -210,4 +210,28 @@ flex =3D generator(find_program('flex'), output: ['@BASENAME@.yy.c', '@BASENAME@.yy.h'], arguments: ['-o', '@OUTPUT0@', '--header-file=3D@OUTPUT1@= ', '@INPUT@']) =20 +bison =3D generator(find_program('bison'), + output: ['@BASENAME@.tab.c', '@BASENAME@.tab.h'], + arguments: ['@INPUT@', '--defines=3D@OUTPUT1@', '--outpu= t=3D@OUTPUT0@']) + +glib_dep =3D dependency('glib-2.0', native: true) + +idef_parser =3D executable('idef-parser', + [flex.process(idef_parser_dir / 'idef-parser.lex'= ), + bison.process(idef_parser_dir / 'idef-parser.y'), + idef_parser_dir / 'parser-helpers.c'], + include_directories: ['idef-parser', '../../inclu= de/'], + dependencies: [glib_dep], + native: true) + +idef_generated_tcg =3D custom_target( + 'idef-generated-tcg', + output: ['idef-generated-emitter.c', + 'idef-generated-emitter.h.inc', + 'idef-generated-enabled-instructions'], + input: preprocessed_idef_parser_input_generated, + depend_files: [hex_common_py], + command: [idef_parser, '@INPUT@', '@OUTPUT0@', '@OUTPUT1@', '@OUTPUT2@= '], +) + target_arch +=3D {'hexagon': hexagon_ss} diff --git a/tests/docker/dockerfiles/alpine.docker b/tests/docker/dockerfi= les/alpine.docker index 1120e8555d..04a85afe3b 100644 --- a/tests/docker/dockerfiles/alpine.docker +++ b/tests/docker/dockerfiles/alpine.docker @@ -9,6 +9,7 @@ ENV PACKAGES \ alsa-lib-dev \ bash \ binutils \ + bison \ coreutils \ curl-dev \ flex \ diff --git a/tests/docker/dockerfiles/centos7.docker b/tests/docker/dockerf= iles/centos7.docker index 95966ea7e6..33c38dc35b 100644 --- a/tests/docker/dockerfiles/centos7.docker +++ b/tests/docker/dockerfiles/centos7.docker @@ -5,6 +5,7 @@ RUN yum -y update =20 # Please keep this list sorted alphabetically ENV PACKAGES \ + bison \ bzip2 \ bzip2-devel \ ccache \ diff --git a/tests/docker/dockerfiles/centos8.docker b/tests/docker/dockerf= iles/centos8.docker index 5919aa0697..0d4e07ae29 100644 --- a/tests/docker/dockerfiles/centos8.docker +++ b/tests/docker/dockerfiles/centos8.docker @@ -3,6 +3,7 @@ FROM centos:8.3.2011 RUN dnf -y update ENV PACKAGES \ SDL2-devel \ + bison \ bzip2 \ bzip2-devel \ dbus-daemon \ diff --git a/tests/docker/dockerfiles/debian10.docker b/tests/docker/docker= files/debian10.docker index 97ec6d5637..bb04ea9f6e 100644 --- a/tests/docker/dockerfiles/debian10.docker +++ b/tests/docker/dockerfiles/debian10.docker @@ -17,6 +17,7 @@ RUN apt update && \ DEBIAN_FRONTEND=3Dnoninteractive apt install -yy eatmydata && \ DEBIAN_FRONTEND=3Dnoninteractive eatmydata \ apt install -y --no-install-recommends \ + bison \ bc \ build-essential \ ca-certificates \ @@ -27,6 +28,7 @@ RUN apt update && \ gdb-multiarch \ gettext \ git \ + libglib2.0-dev \ libncurses5-dev \ ninja-build \ pkg-config \ diff --git a/tests/docker/dockerfiles/fedora-i386-cross.docker b/tests/dock= er/dockerfiles/fedora-i386-cross.docker index 9703b7ec78..ba8165dc0d 100644 --- a/tests/docker/dockerfiles/fedora-i386-cross.docker +++ b/tests/docker/dockerfiles/fedora-i386-cross.docker @@ -1,11 +1,13 @@ FROM fedora:33 ENV PACKAGES \ + bison \ bzip2 \ diffutils \ findutils \ flex \ gcc \ git \ + glib2-devel \ libtasn1-devel.i686 \ libzstd-devel.i686 \ make \ diff --git a/tests/docker/dockerfiles/fedora-win32-cross.docker b/tests/doc= ker/dockerfiles/fedora-win32-cross.docker index 2018dcabe5..98b525258b 100644 --- a/tests/docker/dockerfiles/fedora-win32-cross.docker +++ b/tests/docker/dockerfiles/fedora-win32-cross.docker @@ -2,6 +2,7 @@ FROM fedora:33 =20 # Please keep this list sorted alphabetically ENV PACKAGES \ + bison \ bc \ bzip2 \ diffutils \ @@ -10,6 +11,7 @@ ENV PACKAGES \ gcc \ gettext \ git \ + glib2-devel \ hostname \ make \ meson \ diff --git a/tests/docker/dockerfiles/fedora-win64-cross.docker b/tests/doc= ker/dockerfiles/fedora-win64-cross.docker index b05e4cbcc6..f28cc3d02f 100644 --- a/tests/docker/dockerfiles/fedora-win64-cross.docker +++ b/tests/docker/dockerfiles/fedora-win64-cross.docker @@ -2,6 +2,7 @@ FROM fedora:33 =20 # Please keep this list sorted alphabetically ENV PACKAGES \ + bison \ bc \ bzip2 \ diffutils \ @@ -9,6 +10,7 @@ ENV PACKAGES \ flex \ gcc \ gettext \ + glib2-devel \ git \ hostname \ make \ diff --git a/tests/docker/dockerfiles/fedora.docker b/tests/docker/dockerfi= les/fedora.docker index 5d3f49936b..a6714ec2e2 100644 --- a/tests/docker/dockerfiles/fedora.docker +++ b/tests/docker/dockerfiles/fedora.docker @@ -2,6 +2,7 @@ FROM fedora:33 =20 # Please keep this list sorted alphabetically ENV PACKAGES \ + bison \ bc \ brlapi-devel \ bzip2 \ diff --git a/tests/docker/dockerfiles/opensuse-leap.docker b/tests/docker/d= ockerfiles/opensuse-leap.docker index ce1db959a2..debdb029c1 100644 --- a/tests/docker/dockerfiles/opensuse-leap.docker +++ b/tests/docker/dockerfiles/opensuse-leap.docker @@ -3,6 +3,7 @@ FROM opensuse/leap:15.2 # Please keep this list sorted alphabetically ENV PACKAGES \ bc \ + bison \ brlapi-devel \ bzip2 \ cyrus-sasl-devel \ diff --git a/tests/docker/dockerfiles/ubuntu.docker b/tests/docker/dockerfi= les/ubuntu.docker index e2f55eb892..1609af3c4f 100644 --- a/tests/docker/dockerfiles/ubuntu.docker +++ b/tests/docker/dockerfiles/ubuntu.docker @@ -11,6 +11,7 @@ =20 FROM ubuntu:20.04 ENV PACKAGES \ + bison \ ccache \ clang \ dbus \ @@ -30,6 +31,7 @@ ENV PACKAGES \ libepoxy-dev \ libfdt-dev \ libgbm-dev \ + libglib2.0-dev \ libgnutls28-dev \ libgtk-3-dev \ libibverbs-dev \ diff --git a/tests/docker/dockerfiles/ubuntu1804.docker b/tests/docker/dock= erfiles/ubuntu1804.docker index 2068118180..18f9261ad5 100644 --- a/tests/docker/dockerfiles/ubuntu1804.docker +++ b/tests/docker/dockerfiles/ubuntu1804.docker @@ -1,5 +1,6 @@ FROM ubuntu:18.04 ENV PACKAGES \ + bison \ ccache \ clang \ flex \ @@ -18,6 +19,7 @@ ENV PACKAGES \ libepoxy-dev \ libfdt-dev \ libgbm-dev \ + libglib2.0-dev \ libgtk-3-dev \ libibverbs-dev \ libiscsi-dev \ diff --git a/tests/docker/dockerfiles/ubuntu2004.docker b/tests/docker/dock= erfiles/ubuntu2004.docker index 13d43a7b90..4c01e0cbef 100644 --- a/tests/docker/dockerfiles/ubuntu2004.docker +++ b/tests/docker/dockerfiles/ubuntu2004.docker @@ -1,5 +1,6 @@ FROM ubuntu:20.04 -ENV PACKAGES bison \ +ENV PACKAGES \ + bison \ bsdmainutils \ ccache \ clang-10\ @@ -21,6 +22,7 @@ ENV PACKAGES bison \ libepoxy-dev \ libfdt-dev \ libgbm-dev \ + libglib2.0-dev \ libgtk-3-dev \ libibverbs-dev \ libiscsi-dev \ --=20 2.31.1 From nobody Mon Apr 29 13:24:59 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1617115817; cv=none; d=zohomail.com; s=zohoarc; b=ABfEXFsz3Gpc6xCv4cRTFMM0sjhWfmAvdloVvGfSubXhoOLNyoxVrBf4F0BOPIHRSFZmEH5AmguA5MdZUXaSA4bFBuxpUfDowd4f6ssYRelgi/Necx00lnqECKfwbM1cokfu0rHCsVamdZDY7qzRu2BRMpUa2Jtm9AU0zVE9nrU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1617115817; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=QA7pKJPo5gsYV4WzI+RKKPhDfhbkegEXiBWbsgpnV1o=; b=aIlkupEJYx7gzNQJkzji52Zv+/pDlwzzAKJdStszp3OXHWi7+EgqOsAjMIjSB9HWs5Q+kcuMr/31/+rsd00bnZqWkgDGoXu4jY5hear6ZPnBUEiJ0iyqm6JQecnNTTbDYDXzn3EJHqIedvYehEZuMhKZ4UZZiOgi4lB/S2pF4VM= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1617115817929111.15067361303079; Tue, 30 Mar 2021 07:50:17 -0700 (PDT) Received: from localhost ([::1]:56168 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lRFhA-0000RL-P5 for importer@patchew.org; Tue, 30 Mar 2021 10:50:16 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:38490) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lRFVk-00039y-NX for qemu-devel@nongnu.org; Tue, 30 Mar 2021 10:38:28 -0400 Received: from rev.ng ([5.9.113.41]:48431) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lRFVe-0004xC-71 for qemu-devel@nongnu.org; Tue, 30 Mar 2021 10:38:28 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=rev.ng; s=dkim; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=QA7pKJPo5gsYV4WzI+RKKPhDfhbkegEXiBWbsgpnV1o=; b=fbFTj/Abts1h/AwiwUTh1+QmrU i6y8CgU68vmKTaDntwE2XuQLv3nq/WwOcw2zdA8XEeqpVDwiT02QzNvvrd3iKQ9eTVPDs57KJAJxQ IqtfaWgnk/1Z9LLiSed9tCOOZZgbjCz0m3DEo1qnq1/pl61s3KQhhno3KAOhVLfYVuP8=; To: qemu-devel@nongnu.org Cc: tsimpson@quicinc.com, bcain@quicinc.com, babush@rev.ng, nizzo@rev.ng, philmd@redhat.com, richard.henderson@linaro.org, Alessandro Di Federico Subject: [PATCH v3 11/12] target/hexagon: call idef-parser functions Date: Tue, 30 Mar 2021 16:37:49 +0200 Message-Id: <20210330143750.3037824-12-ale.qemu@rev.ng> In-Reply-To: <20210330143750.3037824-1-ale.qemu@rev.ng> References: <20210330143750.3037824-1-ale.qemu@rev.ng> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=5.9.113.41; envelope-from=ale@rev.ng; helo=rev.ng X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_PASS=-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.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Reply-to: Alessandro Di Federico From: Alessandro Di Federico via X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" From: Alessandro Di Federico Extend gen_tcg_funcs.py in order to emit calls to the functions emitted by the idef-parser, if available. Signed-off-by: Alessandro Di Federico --- target/hexagon/gen_tcg_funcs.py | 28 ++++++++++++++++++++++++++-- target/hexagon/hex_common.py | 10 ++++++++++ target/hexagon/meson.build | 24 ++++++++++++++---------- 3 files changed, 50 insertions(+), 12 deletions(-) diff --git a/target/hexagon/gen_tcg_funcs.py b/target/hexagon/gen_tcg_funcs= .py index db9f663a77..5980dab8ee 100755 --- a/target/hexagon/gen_tcg_funcs.py +++ b/target/hexagon/gen_tcg_funcs.py @@ -394,7 +394,29 @@ def gen_tcg_func(f, tag, regs, imms): if (hex_common.is_read(regid)): genptr_src_read_opn(f,regtype,regid,tag) =20 - if ( hex_common.skip_qemu_helper(tag) ): + if hex_common.is_idef_parser_enabled(tag): + declared =3D [] + ## Handle registers + for regtype,regid,toss,numregs in regs: + if (hex_common.is_pair(regid) + or (hex_common.is_single(regid) + and hex_common.is_old_val(regtype, regid, tag))): + declared.append("%s%sV" % (regtype, regid)) + if regtype =3D=3D "M": + declared.append("%s%sN" % (regtype, regid)) + elif hex_common.is_new_val(regtype, regid, tag): + declared.append("%s%sN" % (regtype,regid)) + else: + print("Bad register parse: ",regtype,regid,toss,numregs) + + ## Handle immediates + for immlett,bits,immshift in imms: + declared.append(hex_common.imm_name(immlett)) + + arguments =3D ", ".join(["ctx", "insn", "pkt"] + declared) + f.write(" emit_%s(%s);\n" % (tag, arguments)) + + elif ( hex_common.skip_qemu_helper(tag) ): f.write(" fGEN_TCG_%s(%s);\n" % (tag, hex_common.semdict[tag])) else: ## Generate the call to the helper @@ -455,12 +477,14 @@ def main(): hex_common.read_attribs_file(sys.argv[2]) hex_common.read_overrides_file(sys.argv[3]) hex_common.calculate_attribs() + hex_common.read_idef_parser_enabled_file(sys.argv[4]) tagregs =3D hex_common.get_tagregs() tagimms =3D hex_common.get_tagimms() =20 - with open(sys.argv[4], 'w') as f: + with open(sys.argv[5], 'w') as f: f.write("#ifndef HEXAGON_TCG_FUNCS_H\n") f.write("#define HEXAGON_TCG_FUNCS_H\n\n") + f.write("#include \"idef-generated-emitter.h.inc\"\n\n") =20 for tag in hex_common.tags: ## Skip the priv instructions diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py index b3b534057d..648ad29e94 100755 --- a/target/hexagon/hex_common.py +++ b/target/hexagon/hex_common.py @@ -28,6 +28,7 @@ attribinfo =3D {} # Register information and misc tags =3D [] # list of all tags overrides =3D {} # tags with helper overrides +idef_parser_enabled =3D {} # tags enabled for idef-parser =20 # We should do this as a hash for performance, # but to keep order let's keep it as a list. @@ -201,6 +202,9 @@ def need_ea(tag): def skip_qemu_helper(tag): return tag in overrides.keys() =20 +def is_idef_parser_enabled(tag): + return tag in idef_parser_enabled + def imm_name(immlett): return "%siV" % immlett =20 @@ -232,3 +236,9 @@ def read_overrides_file(name): continue tag =3D overridere.findall(line)[0] overrides[tag] =3D True + +def read_idef_parser_enabled_file(name): + global idef_parser_enabled + with open(name, "r") as idef_parser_enabled_file: + lines =3D idef_parser_enabled_file.read().strip().split("\n") + idef_parser_enabled =3D set(lines) diff --git a/target/hexagon/meson.build b/target/hexagon/meson.build index 2b7d6c8c62..6adfe0468d 100644 --- a/target/hexagon/meson.build +++ b/target/hexagon/meson.build @@ -72,16 +72,6 @@ helper_protos_generated =3D custom_target( ) hexagon_ss.add(helper_protos_generated) =20 -tcg_funcs_generated =3D custom_target( - 'tcg_funcs_generated.c.inc', - output: 'tcg_funcs_generated.c.inc', - input: 'gen_tcg_funcs.py', - depends: [semantics_generated], - depend_files: [hex_common_py, attribs_def, gen_tcg_h], - command: [python, '@INPUT@', semantics_generated, attribs_def, gen_tcg= _h, '@OUTPUT@'], -) -hexagon_ss.add(tcg_funcs_generated) - tcg_func_table_generated =3D custom_target( 'tcg_func_table_generated.c.inc', output: 'tcg_func_table_generated.c.inc', @@ -234,4 +224,18 @@ idef_generated_tcg =3D custom_target( command: [idef_parser, '@INPUT@', '@OUTPUT0@', '@OUTPUT1@', '@OUTPUT2@= '], ) =20 +idef_generated_list =3D idef_generated_tcg[2].full_path() + +hexagon_ss.add(idef_generated_tcg) + +tcg_funcs_generated =3D custom_target( + 'tcg_funcs_generated.c.inc', + output: 'tcg_funcs_generated.c.inc', + input: 'gen_tcg_funcs.py', + depends: [semantics_generated, idef_generated_tcg], + depend_files: [hex_common_py, attribs_def, gen_tcg_h], + command: [python, '@INPUT@', semantics_generated, attribs_def, gen_tcg= _h, idef_generated_list, '@OUTPUT@'], +) +hexagon_ss.add(tcg_funcs_generated) + target_arch +=3D {'hexagon': hexagon_ss} --=20 2.31.1 From nobody Mon Apr 29 13:24:59 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1617119575; cv=none; d=zohomail.com; s=zohoarc; b=QEBJSIDvfeDx3zA4OP3GVedHBcT8M4PDS8kYy5WsbLImHGh92ORhtoPhEo27oNvYoNz2VtoGYfCZ8n0hwlbrNwlWAhbzRVpttpPZ1zG0IPT4hso4VujHj006U1IgwdsvrK64AycXraLay0uneTOi8Nfz4SgQ29hX1Z/9wqM2/c8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1617119575; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=aSKaCqMnhUcYcEz1piF/JXOLWAn79usG/6R6/yR7kBM=; b=JprB7BRE8G7QiWcSmOkiwYz4gcmrvL+W+TbXym0L1t3iYylaZsmCGVDdPGvQWVStweSSlxxhWyzalrnGPml63bBvv+iNxjRWo1/fC0d7MwcdtxKZTulP19CwrMs1suEj86Tf8xWkh5QASr83QRYSEut3wotq6ypthp5XR/gxEiA= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1617119575563663.1759451526241; Tue, 30 Mar 2021 08:52:55 -0700 (PDT) Received: from localhost ([::1]:48624 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lRFeZ-0005kw-I8 for importer@patchew.org; Tue, 30 Mar 2021 10:47:35 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:38542) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lRFVo-0003KR-I1 for qemu-devel@nongnu.org; Tue, 30 Mar 2021 10:38:32 -0400 Received: from rev.ng ([5.9.113.41]:57397) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lRFVe-0004xE-NJ for qemu-devel@nongnu.org; Tue, 30 Mar 2021 10:38:32 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=rev.ng; s=dkim; h=Content-Transfer-Encoding:Content-Type:MIME-Version:References: In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=aSKaCqMnhUcYcEz1piF/JXOLWAn79usG/6R6/yR7kBM=; b=b5WjUXvJo6og8h4EA5jfCTUDU6 72eE4C3IKJm1Vk4BjJusOnTh6vwDGagtO+RrTJhTsir8eER4HTvlGwVsF20byePRxZpbgvWJqkFI8 yGPyxDuQj7kiXQLAi4Qb65wjUfTS0Z4woI1KJ1gPmaekW3sd1V6va2mR+BwUC6BXEW+4=; To: qemu-devel@nongnu.org Cc: tsimpson@quicinc.com, bcain@quicinc.com, babush@rev.ng, nizzo@rev.ng, philmd@redhat.com, richard.henderson@linaro.org, Alessandro Di Federico Subject: [PATCH v3 12/12] target/hexagon: import additional tests Date: Tue, 30 Mar 2021 16:37:50 +0200 Message-Id: <20210330143750.3037824-13-ale.qemu@rev.ng> In-Reply-To: <20210330143750.3037824-1-ale.qemu@rev.ng> References: <20210330143750.3037824-1-ale.qemu@rev.ng> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=5.9.113.41; envelope-from=ale@rev.ng; helo=rev.ng X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_PASS=-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.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Reply-to: Alessandro Di Federico From: Alessandro Di Federico via X-ZohoMail-DKIM: fail (Header signature does not verify) From: Niccol=C3=B2 Izzo Signed-off-by: Alessandro Di Federico Signed-off-by: Niccol=C3=B2 Izzo --- tests/tcg/hexagon/Makefile.target | 35 ++++++++++++++++- tests/tcg/hexagon/crt.S | 28 +++++++++++++ tests/tcg/hexagon/test_abs.S | 20 ++++++++++ tests/tcg/hexagon/test_add.S | 20 ++++++++++ tests/tcg/hexagon/test_andp.S | 23 +++++++++++ tests/tcg/hexagon/test_bitcnt.S | 42 ++++++++++++++++++++ tests/tcg/hexagon/test_bitsplit.S | 25 ++++++++++++ tests/tcg/hexagon/test_call.S | 63 ++++++++++++++++++++++++++++++ tests/tcg/hexagon/test_clobber.S | 35 +++++++++++++++++ tests/tcg/hexagon/test_cmp.S | 34 ++++++++++++++++ tests/tcg/hexagon/test_cmpy.S | 31 +++++++++++++++ tests/tcg/hexagon/test_djump.S | 24 ++++++++++++ tests/tcg/hexagon/test_dotnew.S | 39 ++++++++++++++++++ tests/tcg/hexagon/test_dstore.S | 29 ++++++++++++++ tests/tcg/hexagon/test_ext.S | 18 +++++++++ tests/tcg/hexagon/test_fibonacci.S | 33 ++++++++++++++++ tests/tcg/hexagon/test_hello.S | 21 ++++++++++ tests/tcg/hexagon/test_hl.S | 19 +++++++++ tests/tcg/hexagon/test_hwloops.S | 25 ++++++++++++ tests/tcg/hexagon/test_jmp.S | 25 ++++++++++++ tests/tcg/hexagon/test_lsr.S | 39 ++++++++++++++++++ tests/tcg/hexagon/test_mpyi.S | 20 ++++++++++ tests/tcg/hexagon/test_packet.S | 26 ++++++++++++ tests/tcg/hexagon/test_reorder.S | 31 +++++++++++++++ tests/tcg/hexagon/test_round.S | 31 +++++++++++++++ tests/tcg/hexagon/test_vavgw.S | 33 ++++++++++++++++ tests/tcg/hexagon/test_vcmpb.S | 32 +++++++++++++++ tests/tcg/hexagon/test_vcmpw.S | 29 ++++++++++++++ tests/tcg/hexagon/test_vcmpy.S | 50 ++++++++++++++++++++++++ tests/tcg/hexagon/test_vlsrw.S | 23 +++++++++++ tests/tcg/hexagon/test_vmaxh.S | 37 ++++++++++++++++++ tests/tcg/hexagon/test_vminh.S | 37 ++++++++++++++++++ tests/tcg/hexagon/test_vpmpyh.S | 30 ++++++++++++++ tests/tcg/hexagon/test_vspliceb.S | 33 ++++++++++++++++ 34 files changed, 1039 insertions(+), 1 deletion(-) create mode 100644 tests/tcg/hexagon/crt.S create mode 100644 tests/tcg/hexagon/test_abs.S create mode 100644 tests/tcg/hexagon/test_add.S create mode 100644 tests/tcg/hexagon/test_andp.S create mode 100644 tests/tcg/hexagon/test_bitcnt.S create mode 100644 tests/tcg/hexagon/test_bitsplit.S create mode 100644 tests/tcg/hexagon/test_call.S create mode 100644 tests/tcg/hexagon/test_clobber.S create mode 100644 tests/tcg/hexagon/test_cmp.S create mode 100644 tests/tcg/hexagon/test_cmpy.S create mode 100644 tests/tcg/hexagon/test_djump.S create mode 100644 tests/tcg/hexagon/test_dotnew.S create mode 100644 tests/tcg/hexagon/test_dstore.S create mode 100644 tests/tcg/hexagon/test_ext.S create mode 100644 tests/tcg/hexagon/test_fibonacci.S create mode 100644 tests/tcg/hexagon/test_hello.S create mode 100644 tests/tcg/hexagon/test_hl.S create mode 100644 tests/tcg/hexagon/test_hwloops.S create mode 100644 tests/tcg/hexagon/test_jmp.S create mode 100644 tests/tcg/hexagon/test_lsr.S create mode 100644 tests/tcg/hexagon/test_mpyi.S create mode 100644 tests/tcg/hexagon/test_packet.S create mode 100644 tests/tcg/hexagon/test_reorder.S create mode 100644 tests/tcg/hexagon/test_round.S create mode 100644 tests/tcg/hexagon/test_vavgw.S create mode 100644 tests/tcg/hexagon/test_vcmpb.S create mode 100644 tests/tcg/hexagon/test_vcmpw.S create mode 100644 tests/tcg/hexagon/test_vcmpy.S create mode 100644 tests/tcg/hexagon/test_vlsrw.S create mode 100644 tests/tcg/hexagon/test_vmaxh.S create mode 100644 tests/tcg/hexagon/test_vminh.S create mode 100644 tests/tcg/hexagon/test_vpmpyh.S create mode 100644 tests/tcg/hexagon/test_vspliceb.S diff --git a/tests/tcg/hexagon/Makefile.target b/tests/tcg/hexagon/Makefile= .target index 616af697fe..f4a774cda1 100644 --- a/tests/tcg/hexagon/Makefile.target +++ b/tests/tcg/hexagon/Makefile.target @@ -32,7 +32,7 @@ CFLAGS +=3D -Wno-incompatible-pointer-types -Wno-undefine= d-internal HEX_SRC=3D$(SRC_PATH)/tests/tcg/hexagon VPATH +=3D $(HEX_SRC) =20 -first: $(HEX_SRC)/first.S +%: $(HEX_SRC)/%.S $(HEX_SRC)/crt.S $(CC) -static -mv67 -nostdlib $^ -o $@ =20 HEX_TESTS =3D first @@ -43,4 +43,37 @@ HEX_TESTS +=3D mem_noshuf HEX_TESTS +=3D atomics HEX_TESTS +=3D fpstuff =20 +HEX_TESTS +=3D test_abs +HEX_TESTS +=3D test_add +HEX_TESTS +=3D test_andp +HEX_TESTS +=3D test_bitcnt +HEX_TESTS +=3D test_bitsplit +HEX_TESTS +=3D test_call +HEX_TESTS +=3D test_clobber +HEX_TESTS +=3D test_cmp +HEX_TESTS +=3D test_cmpy +HEX_TESTS +=3D test_djump +HEX_TESTS +=3D test_dotnew +HEX_TESTS +=3D test_dstore +HEX_TESTS +=3D test_ext +HEX_TESTS +=3D test_fibonacci +HEX_TESTS +=3D test_hello +HEX_TESTS +=3D test_hl +HEX_TESTS +=3D test_hwloops +HEX_TESTS +=3D test_jmp +HEX_TESTS +=3D test_lsr +HEX_TESTS +=3D test_mpyi +HEX_TESTS +=3D test_packet +HEX_TESTS +=3D test_reorder +HEX_TESTS +=3D test_round +HEX_TESTS +=3D test_vavgw +HEX_TESTS +=3D test_vcmpb +HEX_TESTS +=3D test_vcmpw +HEX_TESTS +=3D test_vcmpy +HEX_TESTS +=3D test_vlsrw +HEX_TESTS +=3D test_vmaxh +HEX_TESTS +=3D test_vminh +HEX_TESTS +=3D test_vpmpyh +HEX_TESTS +=3D test_vspliceb + TESTS +=3D $(HEX_TESTS) diff --git a/tests/tcg/hexagon/crt.S b/tests/tcg/hexagon/crt.S new file mode 100644 index 0000000000..2c10577470 --- /dev/null +++ b/tests/tcg/hexagon/crt.S @@ -0,0 +1,28 @@ +#define SYS_exit_group 94 + + .text + .globl init +init: + { + allocframe(r29,#0):raw + } + { + r0=3D#256 + } + { + dealloc_return + } + + .space 240 + + .globl pass +pass: + r0 =3D #0 + r6 =3D #SYS_exit_group + trap0(#1) + + .globl fail +fail: + r0 =3D #1 + r6 =3D #SYS_exit_group + trap0(#1) diff --git a/tests/tcg/hexagon/test_abs.S b/tests/tcg/hexagon/test_abs.S new file mode 100644 index 0000000000..880b2886b5 --- /dev/null +++ b/tests/tcg/hexagon/test_abs.S @@ -0,0 +1,20 @@ +/* Purpose: test example, verify the soundness of the abs operation */ + + .text + .globl _start + +_start: + { + call init + } + { + r1=3D#-2 + r2=3D#2 + } + { + r3=3Dabs(r1) + } + { + p0 =3D cmp.eq(r3, r2); if (p0.new) jump:t pass + jump fail + } diff --git a/tests/tcg/hexagon/test_add.S b/tests/tcg/hexagon/test_add.S new file mode 100644 index 0000000000..e8de34520f --- /dev/null +++ b/tests/tcg/hexagon/test_add.S @@ -0,0 +1,20 @@ +/* Purpose: test example, verify the soundness of the add operation */ + + .text + .globl _start + +_start: + { + call init + } + { + r1=3D#0 + r2=3D#0 + } + { + r3=3Dadd(r1,r2) + } + { + p0 =3D cmp.eq(r3, #0); if (p0.new) jump:t pass + jump fail + } diff --git a/tests/tcg/hexagon/test_andp.S b/tests/tcg/hexagon/test_andp.S new file mode 100644 index 0000000000..3c4aa8b2ae --- /dev/null +++ b/tests/tcg/hexagon/test_andp.S @@ -0,0 +1,23 @@ +/* Purpose: test a multiple predicate AND combination */ + + .text + .globl _start + +_start: + { + r1+=3Dsub(r2,r3) + call init + } + { + r0=3D#0 + r1=3D#1 + } + { + p0=3Dcmp.gt(r0,r1) + p0=3Dcmp.gt(r0,r1) + p0=3Dcmp.gt(r1,r0) + } + { + if (!p0) jump:t pass + jump fail + } diff --git a/tests/tcg/hexagon/test_bitcnt.S b/tests/tcg/hexagon/test_bitcn= t.S new file mode 100644 index 0000000000..df77fe61e2 --- /dev/null +++ b/tests/tcg/hexagon/test_bitcnt.S @@ -0,0 +1,42 @@ +/* Purpose: test example, verify the soundness of the cl[01] operations + * + * the number 0x000001aa has 23 leading zeroes + * they become 55 when considered as 64 bit register + * and it has 1 trailing zero + */ + .text + .globl _start + +_start: + { + call init + } + { + r0=3D#426 + r1=3D#0 + } + { + r2=3Dcl0(r0) + } + { + p0 =3D cmp.eq(r2, #23); if (p0.new) jump:t test2 + jump fail + } + +test2: + { + r2=3Dcl0(r1:0) + } + { + p0 =3D cmp.eq(r2, #55); if (p0.new) jump:t test3 + jump fail + } + +test3: + { + r2=3Dct0(r0) + } + { + p0 =3D cmp.eq(r2, #1); if (p0.new) jump:t pass + jump fail + } diff --git a/tests/tcg/hexagon/test_bitsplit.S b/tests/tcg/hexagon/test_bit= split.S new file mode 100644 index 0000000000..787cce72e4 --- /dev/null +++ b/tests/tcg/hexagon/test_bitsplit.S @@ -0,0 +1,25 @@ +/* Purpose: test example, verify the soundness of the bitsplit operation */ + + .text + .globl _start + +_start: + { + call init + } + { + r1=3D#187 + } + { + r3:2=3Dbitsplit(r1, #3) + } + { + p0 =3D cmp.eq(r2, #3); if (p0.new) jump:t test2 + jump fail + } + +test2: + { + p0 =3D cmp.eq(r3, #23); if (p0.new) jump:t pass + jump fail + } diff --git a/tests/tcg/hexagon/test_call.S b/tests/tcg/hexagon/test_call.S new file mode 100644 index 0000000000..53a2450522 --- /dev/null +++ b/tests/tcg/hexagon/test_call.S @@ -0,0 +1,63 @@ +/* Purpose: test function calls and duplex instructions. + * The string "Hello there, I'm a test string!" with the first letter repl= aced + * with a capital L should be printed out. + */ + + .text + .globl test +test: + { + jumpr r31 + memb(r0+#0)=3D#76 + } +.Lfunc_end0: +.Ltmp0: + .size test, .Ltmp0-test + + .globl _start +_start: + { + call init + } + { + call test + r0=3D##dummy_buffer + allocframe(#0) + } + { + call write + } + { + jump pass + } + { + r31:30=3Ddeallocframe(r30):raw + } +.Lfunc_end1: +.Ltmp1: + .size _start, .Ltmp1-_start +write: + { + r2=3D##dummy_buffer + } + { r0=3Dr2; } + { + r2=3D#256 + } + { r1=3Dr2; } + { trap0(#7); } + { + jumpr r31 + } +.Lfunc_end2: +.Ltmp2: + .size write, .Ltmp2-write + + .type dummy_buffer,@object + .data + .globl dummy_buffer + .p2align 3 +dummy_buffer: + .string "Hello there, I'm a test string!\n" + .space 223 + .size dummy_buffer, 256 diff --git a/tests/tcg/hexagon/test_clobber.S b/tests/tcg/hexagon/test_clob= ber.S new file mode 100644 index 0000000000..198817ebd5 --- /dev/null +++ b/tests/tcg/hexagon/test_clobber.S @@ -0,0 +1,35 @@ +/* Purpose: demonstrate the succesful operation of the register save mecha= nism, + * in which the caller saves the registers that will be clobbered, and res= tores + * them after the call. + */ + + .text + .globl _start + +_start: + { + call init + } + { + r16=3D#47 + r17=3D#155 + } + { + memd(r29+#-16)=3Dr17:16; allocframe(#8) + } + { + r16=3D#255 + r17=3D#42 + } + { + r17:16=3Dmemd(r29+#0); deallocframe + } + { + r3=3Dadd(r16,r17) + } + { + p0 =3D cmp.eq(r3, #202); if (p0.new) jump:t pass + } + { + jump fail + } diff --git a/tests/tcg/hexagon/test_cmp.S b/tests/tcg/hexagon/test_cmp.S new file mode 100644 index 0000000000..31ee9565fe --- /dev/null +++ b/tests/tcg/hexagon/test_cmp.S @@ -0,0 +1,34 @@ +/* Purpose: test a signed and unsigned comparison */ + + .text + .globl _start + +_start: + { + call init + } + { + jump signed + } + + .globl signed +signed: + { + r0=3D#-2 + r1=3D#0 + } + { + p0 =3D cmp.lt(r0, r1); if (p0.new) jump:t unsigned + jump fail + } + + .globl unsigned +unsigned: + { + r0=3D#-2 + r1=3D#0 + } + { + p0 =3D cmp.gtu(r0, r1); if (p0.new) jump:t pass + jump fail + } diff --git a/tests/tcg/hexagon/test_cmpy.S b/tests/tcg/hexagon/test_cmpy.S new file mode 100644 index 0000000000..0b3dfb95de --- /dev/null +++ b/tests/tcg/hexagon/test_cmpy.S @@ -0,0 +1,31 @@ +/* Purpose: test example, verify the soundness of the cmpy operation + * + * 3j+5 * 2j+4 =3D 22j+14 + * + * the complex multiply between 0x00030005 and 0x00020004 is 0x00000016000= 0000e + */ + + .text + .globl _start + +_start: + { + call init + } + { + r0=3D#196613 + r1=3D#131076 + } + { + r3:2=3Dcmpy(r0, r1):sat + } + { + p0 =3D cmp.eq(r2, #14); if (p0.new) jump:t test2 + jump fail + } + +test2: + { + p0 =3D cmp.eq(r3, #22); if (p0.new) jump:t pass + jump fail + } diff --git a/tests/tcg/hexagon/test_djump.S b/tests/tcg/hexagon/test_djump.S new file mode 100644 index 0000000000..dbad7eb0a1 --- /dev/null +++ b/tests/tcg/hexagon/test_djump.S @@ -0,0 +1,24 @@ +/* Purpose: show dual jumps actually work. This program features a packet = where + * two jumps should (in theory) be performed if !P0. However, we correctly + * handle the situation by performing only the first one and ignoring the = second + * one. This can be verified by checking that the CPU dump contains 0xDEAD= BEEF + * in R2. + */ + + .text + .globl _start + +_start: + { + call init + } + { + r1 =3D #255; + } + { + p0 =3D r1; + } + { + if (p0) jump:t pass + jump fail + } diff --git a/tests/tcg/hexagon/test_dotnew.S b/tests/tcg/hexagon/test_dotne= w.S new file mode 100644 index 0000000000..3897c6bc96 --- /dev/null +++ b/tests/tcg/hexagon/test_dotnew.S @@ -0,0 +1,39 @@ +/* Purpose: test the .new operator while performing memory stores. + * In the final CPU dump R0 should contain 3, R1 should contain 2 and R2 s= hould + * contain 1. + */ + .text + .globl _start + +_start: + { + call init + } + { + r0=3D#1 + memw(sp+#0)=3Dr0.new + } + { + r1=3D#2 + memw(sp+#4)=3Dr1.new + } + { + r2=3D#3 + memw(sp+#8)=3Dr2.new + } + { + r0=3Dmemw(sp+#8) + } + { + r1=3Dmemw(sp+#4) + } + { + r2=3Dmemw(sp+#0) + } + { + r3=3Dmpyi(r1,r2) + } + { + p0 =3D cmp.eq(r3, #2); if (p0.new) jump:t pass + jump fail + } diff --git a/tests/tcg/hexagon/test_dstore.S b/tests/tcg/hexagon/test_dstor= e.S new file mode 100644 index 0000000000..62c4301eb1 --- /dev/null +++ b/tests/tcg/hexagon/test_dstore.S @@ -0,0 +1,29 @@ +/* Purpose: test dual stores correctness. + * In this example the values 1 and 2 are both written on the top of the s= tack + * in a single packet. + * The value is then read back in R3, which should contain only the latest= value + * written (2). + */ + + .text + .globl _start + +_start: + { + call init + } + { + r0=3D#1 + r1=3D#2 + } + { + memw(sp+#0)=3Dr0 + memw(sp+#0)=3Dr1 + } + { + r3=3Dmemw(sp+#0) + } + { + p0 =3D cmp.eq(r3, #2); if (p0.new) jump:t pass + jump fail + } diff --git a/tests/tcg/hexagon/test_ext.S b/tests/tcg/hexagon/test_ext.S new file mode 100644 index 0000000000..0f6e21593a --- /dev/null +++ b/tests/tcg/hexagon/test_ext.S @@ -0,0 +1,18 @@ +/* Purpose: test immediate extender instructions. + * In the CPU dump R0 should contain 0xDEADBEEF. + */ + + .text + .globl _start + +_start: + { + call init + } + { + r2=3D##-559038737 + } + { + p0 =3D cmp.eq(r2, ##-559038737); if (p0.new) jump:t pass + jump fail + } diff --git a/tests/tcg/hexagon/test_fibonacci.S b/tests/tcg/hexagon/test_fi= bonacci.S new file mode 100644 index 0000000000..41cb1517cb --- /dev/null +++ b/tests/tcg/hexagon/test_fibonacci.S @@ -0,0 +1,33 @@ +/* Purpose: computes the Fibonacci series up to a constant number. */ + + .text + .globl _start + +_start: + { + call init + } + { + r2=3D#100 + } + { + p0=3Dcmp.gt(r2,#0); if (!p0.new) jump:nt .LBB0_3 + } + { + r3=3D#0 + r4=3D#1 + } +.LBB0_2: + { + r5=3Dr4 + } + { + p0=3Dcmp.gt(r2,r5); if (p0.new) jump:nt .LBB0_2 + r4=3Dadd(r3,r4) + r3=3Dr5 + } +.LBB0_3: + { + p0 =3D cmp.eq(r3, #144); if (p0.new) jump:t pass + jump fail + } diff --git a/tests/tcg/hexagon/test_hello.S b/tests/tcg/hexagon/test_hello.S new file mode 100644 index 0000000000..89c7da677f --- /dev/null +++ b/tests/tcg/hexagon/test_hello.S @@ -0,0 +1,21 @@ +/* Purpose: simple hello world program. */ + + .text + .globl _start + +_start: + { + call init + } + { r0=3D#4; } + { + r1=3D##.L.str + } + { trap0(#0); } + { + jump pass + } + +.L.str: + .string "Hello world!\n" + .size .L.str, 14 diff --git a/tests/tcg/hexagon/test_hl.S b/tests/tcg/hexagon/test_hl.S new file mode 100644 index 0000000000..217b3143e2 --- /dev/null +++ b/tests/tcg/hexagon/test_hl.S @@ -0,0 +1,19 @@ +/* Purpose: test example, verify the soundness of the high/low assignment = */ + + .text + .globl _start + +_start: + { + call init + } + { + r0.H=3D#42 + } + { + r0.L=3D#69 + } + { + p0 =3D cmp.eq(r0, #2752581); if (p0.new) jump:t pass + jump fail + } diff --git a/tests/tcg/hexagon/test_hwloops.S b/tests/tcg/hexagon/test_hwlo= ops.S new file mode 100644 index 0000000000..8337083d8e --- /dev/null +++ b/tests/tcg/hexagon/test_hwloops.S @@ -0,0 +1,25 @@ +/* Purpose: simple C Program to test hardware loops. + * It should print numbersfrom 0 to 9. + */ + + .text + .globl _start + +_start: + { + call init + } + { + loop0(.LBB0_1,#10) + r2=3D#0 + } +.Ltmp0: +.LBB0_1: + { + r2=3Dadd(r2,#1) + nop + }:endloop0 + { + p0 =3D cmp.eq(r2, #10); if (p0.new) jump:t pass + jump fail + } diff --git a/tests/tcg/hexagon/test_jmp.S b/tests/tcg/hexagon/test_jmp.S new file mode 100644 index 0000000000..9bf6ea34e5 --- /dev/null +++ b/tests/tcg/hexagon/test_jmp.S @@ -0,0 +1,25 @@ +/* Purpose: test example, verify the soundness of the add operation */ + + .text + .globl _start + +_start: + { + call init + } + { + r1=3D#0 + r2=3D#0 + } + { + r3=3Dadd(r1,r2) + } + { + p0 =3D cmp.eq(r3, #0) + } + { + if (p0) jump:t pass + } + { + jump fail + } diff --git a/tests/tcg/hexagon/test_lsr.S b/tests/tcg/hexagon/test_lsr.S new file mode 100644 index 0000000000..202eb4aec7 --- /dev/null +++ b/tests/tcg/hexagon/test_lsr.S @@ -0,0 +1,39 @@ +/* Purpose: test the soundness of the lsr operation */ + + .text + .globl _start + +_start: + { + call init + } + { + r0=3D#-56984 + r1=3D#2147483647 + } + { + r2=3D#0x19 + } + { + r0&=3Dlsr(r1, r2) + } + { + p0 =3D cmp.eq(r0, #0x28); if (p0.new) jump:t test2 + jump fail + } + +test2: + { + r0=3D#0x0000000a + r1=3D#0x00000000 + } + { + r2=3D#-1 + } + { + r1:0=3Dlsl(r1:0, r2) + } + { + p0 =3D cmp.eq(r0, #0x5); if (p0.new) jump:t pass + jump fail + } diff --git a/tests/tcg/hexagon/test_mpyi.S b/tests/tcg/hexagon/test_mpyi.S new file mode 100644 index 0000000000..b8e0d50b68 --- /dev/null +++ b/tests/tcg/hexagon/test_mpyi.S @@ -0,0 +1,20 @@ +/* Purpose: test a simple multiplication operation */ + + .text + .globl _start + +_start: + { + call init + } + { + r1=3D#4 + r2=3D#6 + } + { + r3=3Dmpyi(r1,r2) + } + { + p0 =3D cmp.eq(r3, #24); if (p0.new) jump:t pass + jump fail + } diff --git a/tests/tcg/hexagon/test_packet.S b/tests/tcg/hexagon/test_packe= t.S new file mode 100644 index 0000000000..d26e284be9 --- /dev/null +++ b/tests/tcg/hexagon/test_packet.S @@ -0,0 +1,26 @@ +/* Purpose: test that writes of a register in a packet are performed only = after + * that packet has finished its execution. + */ + + .text + .globl _start + +_start: + { + call init + } + { + r2=3D#4 + r3=3D#6 + } + { + memw(sp+#0)=3Dr2 + } + { + r3=3Dmemw(sp+#0) + r0=3Dadd(r2,r3) + } + { + p0 =3D cmp.eq(r0, #10); if (p0.new) jump:t pass + jump fail + } diff --git a/tests/tcg/hexagon/test_reorder.S b/tests/tcg/hexagon/test_reor= der.S new file mode 100644 index 0000000000..508d5302f9 --- /dev/null +++ b/tests/tcg/hexagon/test_reorder.S @@ -0,0 +1,31 @@ +/* Purpose: demonstrate handling of .new uses appearing before the associa= ted + * definition. + * Here we perform a jump that skips the code resetting R2 from 0xDEADBEEF= to 0, + * only if P0.new is true, but P0 is assigned to 1 (R4) in the next instru= ction + * in the packet. + * A successful run of the program will show R2 retaining the 0xDEADBEEF v= alue + * in the CPU dump. + */ + + .text + .globl _start + +_start: + { + call init + } + { r2=3D#-559038737 } + { r4=3D#1 } + { + if (p0.new) jump:nt skip + p0=3Dr4; + } + +fallthrough: + { r2=3D#0 } + +skip: + { + p0 =3D cmp.eq(r2, #-559038737); if (p0.new) jump:t pass + jump fail + } diff --git a/tests/tcg/hexagon/test_round.S b/tests/tcg/hexagon/test_round.S new file mode 100644 index 0000000000..2becd62c4c --- /dev/null +++ b/tests/tcg/hexagon/test_round.S @@ -0,0 +1,31 @@ +/* Purpose: test example, verify the soundness of the cround operation + * 106 =3D 0b1101010 with the comma at third digit is 12.5 which is cround= ed to 12 + * but rounded to 13 + */ + + .text + .globl _start + +_start: + { + call init + } + { + r1=3D#200 + } + { + r2=3Dround(r1, #4) + } + { + p0 =3D cmp.eq(r2, #13); if (p0.new) jump:t test2 + jump fail + } + +test2: + { + r2=3Dcround(r1, #4) + } + { + p0 =3D cmp.eq(r2, #12); if (p0.new) jump:t pass + jump fail + } diff --git a/tests/tcg/hexagon/test_vavgw.S b/tests/tcg/hexagon/test_vavgw.S new file mode 100644 index 0000000000..8f67238900 --- /dev/null +++ b/tests/tcg/hexagon/test_vavgw.S @@ -0,0 +1,33 @@ +/* Purpose: test example, verify the soundness of the vavgw operation + * + * 0x00030001 averaged with 0x00010003 results 0x00020002 + */ + + .text + .globl _start + +_start: + { + call init + } + { + r0=3D#3 + r1=3D#1 + } + { + r2=3D#1 + r3=3D#3 + } + { + r1:0=3Dvavgw(r1:0, r3:2):crnd + } + { + p0 =3D cmp.eq(r0, #2); if (p0.new) jump:t test2 + jump fail + } + +test2: + { + p0 =3D cmp.eq(r1, #2); if (p0.new) jump:t pass + jump fail + } diff --git a/tests/tcg/hexagon/test_vcmpb.S b/tests/tcg/hexagon/test_vcmpb.S new file mode 100644 index 0000000000..3c6700a63a --- /dev/null +++ b/tests/tcg/hexagon/test_vcmpb.S @@ -0,0 +1,32 @@ +/* Purpose: test example, verify the soundness of the vector compare bytes + * operation + * + * Vector word comparison between 0x1234567887654321 and 0x1234567800000000 + * should result in 0x11110000 + */ + + .text + .globl _start + +_start: + { + call init + } + { + r0=3D#305419896 + r1=3D#-2023406815 + } + { + r2=3D#305419896 + r3=3D#0 + } + { + p2=3Dvcmpb.eq(r1:0, r3:2) + } + { + r4=3Dp2 + } + { + p0 =3D cmp.eq(r4, #15); if (p0.new) jump:t pass + jump fail + } diff --git a/tests/tcg/hexagon/test_vcmpw.S b/tests/tcg/hexagon/test_vcmpw.S new file mode 100644 index 0000000000..112f08c92f --- /dev/null +++ b/tests/tcg/hexagon/test_vcmpw.S @@ -0,0 +1,29 @@ +/* Purpose: test example, verify the soundness of the vector compare words + * operation + * + * Vector word comparison between 0x1234567887654321 and 0x1234567800000000 + * should result in 0x11110000 + */ + + .text + .globl _start + +_start: + { + call init + } + { + r0=3D#305419896 + r1=3D#-2023406815 + } + { + r2=3D#305419896 + r3=3D#0 + } + { + p2=3Dvcmpw.eq(r1:0, r3:2) + } + { + if (p2) jump:t pass + jump fail + } diff --git a/tests/tcg/hexagon/test_vcmpy.S b/tests/tcg/hexagon/test_vcmpy.S new file mode 100644 index 0000000000..df379f9186 --- /dev/null +++ b/tests/tcg/hexagon/test_vcmpy.S @@ -0,0 +1,50 @@ +/* Purpose: test example, verify the soundness of the vcmpy operation + * this operation is a complex multiply and accumulate on vectors of two v= alues + * + * (3j+5 * 2j+4) + (4j+6 * 5j+2) =3D 22j+14 + * + * the complex multiply between 0x00030005 and 0x00020004 is 0x0000001600= 00000e + * the complex multiply between 0x00040006 and 0x00050002 is 0x0000001600= 00000e + */ + + .text + .globl _start + +_start: + { + call init + } + { + r0=3D#196613 + r1=3D#131076 + } + { + r2=3D#262150 + r3=3D#327682 + } + { + r5:4=3Dvcmpyr(r1:0, r3:2):sat + r7:6=3Dvcmpyi(r1:0, r3:2):sat + } + { + p0 =3D cmp.eq(r4, #18); if (p0.new) jump:t test2 + jump fail + } + +test2: + { + p0 =3D cmp.eq(r5, #-2); if (p0.new) jump:t test3 + jump fail + } + +test3: + { + p0 =3D cmp.eq(r6, #38); if (p0.new) jump:t test4 + jump fail + } + +test4: + { + p0 =3D cmp.eq(r7, #24); if (p0.new) jump:t pass + jump fail + } diff --git a/tests/tcg/hexagon/test_vlsrw.S b/tests/tcg/hexagon/test_vlsrw.S new file mode 100644 index 0000000000..962ec99543 --- /dev/null +++ b/tests/tcg/hexagon/test_vlsrw.S @@ -0,0 +1,23 @@ +/* Purpose: test the soundness of the vlsrw operation */ + + .text + .globl _start + +_start: + { + call init + } + { + r0=3D#0x00000001 + r1=3D#0x00000001 + } + { + r1:0=3Dvlsrw(r1:0, #1) + } + { + r0 =3D add(r0, r1) + } + { + p0 =3D cmp.eq(r0, #0); if (p0.new) jump:t pass + jump fail + } diff --git a/tests/tcg/hexagon/test_vmaxh.S b/tests/tcg/hexagon/test_vmaxh.S new file mode 100644 index 0000000000..1fce935e35 --- /dev/null +++ b/tests/tcg/hexagon/test_vmaxh.S @@ -0,0 +1,37 @@ +/* Purpose: test example, verify the soundness of the vrmaxh operation + * + * the maximum between 0x0002000300010005 and 0x0003000200020007 is + * 0x0003000300020007. + * + * r1=3D0x00010003 r0=3D0x00010005 r3=3D0x00030002 r2= =3D0x00020007 + * result: r1=3D0x00030003 r0=3D0x00020007 + */ + + .text + .globl _start + +_start: + { + call init + } + { + r0=3D#65541 + r1=3D#65539 + } + { + r2=3D#131079 + r3=3D#196610 + } + { + r1:0=3Dvmaxh(r1:0, r3:2) + } + { + p0 =3D cmp.eq(r0, #131079); if (p0.new) jump:t test2 + jump fail + } + +test2: + { + p0 =3D cmp.eq(r1, #196611); if (p0.new) jump:t pass + jump fail + } diff --git a/tests/tcg/hexagon/test_vminh.S b/tests/tcg/hexagon/test_vminh.S new file mode 100644 index 0000000000..6c6d18c673 --- /dev/null +++ b/tests/tcg/hexagon/test_vminh.S @@ -0,0 +1,37 @@ +/* Purpose: test example, verify the soundness of the vrmaxh operation + * + * the minimum between 0x0002000300010005 and 0x0003000200020007 is + * 0x0003000300020007 + * + * r1=3D0x00010003 r0=3D0x00010005 r3=3D0x00030002 r2= =3D0x00020007 + * result: r1=3D0x00010002 r0=3D0x00010005 + */ + + .text + .globl _start + +_start: + { + call init + } + { + r0=3D#65541 + r1=3D#65539 + } + { + r2=3D#131079 + r3=3D#196610 + } + { + r1:0=3Dvminh(r1:0, r3:2) + } + { + p0 =3D cmp.eq(r0, #65541); if (p0.new) jump:t test2 + jump fail + } + +test2: + { + p0 =3D cmp.eq(r1, #65538); if (p0.new) jump:t pass + jump fail + } diff --git a/tests/tcg/hexagon/test_vpmpyh.S b/tests/tcg/hexagon/test_vpmpy= h.S new file mode 100644 index 0000000000..942d691da4 --- /dev/null +++ b/tests/tcg/hexagon/test_vpmpyh.S @@ -0,0 +1,30 @@ +/* Purpose: test example, verify the soundness of the vpmpyh operator + * + * 0x01020304 vector polynomial multiplied with 0x04030201 results + * 0x000400060b060b04 + */ + + .text + .globl _start + +_start: + { + call init + } + { + r0=3D#16909060 + r1=3D#67305985 + } + { + r1:0=3Dvpmpyh(r0, r1) + } + { + p0 =3D cmp.eq(r0, #184945412); if (p0.new) jump:t test2 + jump fail + } + +test2: + { + p0 =3D cmp.eq(r1, #262150); if (p0.new) jump:t pass + jump fail + } diff --git a/tests/tcg/hexagon/test_vspliceb.S b/tests/tcg/hexagon/test_vsp= liceb.S new file mode 100644 index 0000000000..bae2a9c163 --- /dev/null +++ b/tests/tcg/hexagon/test_vspliceb.S @@ -0,0 +1,33 @@ +/* Purpose: test example, verify the soundness of the vspliceb operation + * the operation is a binary splice of two 64bit operators + * + * vspliceb(0xffffffffffffffff,0x0000000000000000,5) =3D 0x00000000000000= 1f + */ + .text + .globl _start + +_start: + { + call init + } + { + r0=3D#-1 + r1=3D#-1 + } + { + r2=3D#0 + r3=3D#0 + } + { + r5:4=3Dvspliceb(r1:0, r3:2, #5) + } + { + p0 =3D cmp.eq(r4, #-1); if (p0.new) jump:t test2 + jump fail + } + +test2: + { + p0 =3D cmp.eq(r5, #255); if (p0.new) jump:t pass + jump fail + } --=20 2.31.1