From nobody Mon Feb 9 11:51:20 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail header.i=@quicinc.com; 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=fail(p=none dis=none) header.from=quicinc.com ARC-Seal: i=1; a=rsa-sha256; t=1601315509; cv=none; d=zohomail.com; s=zohoarc; b=nNpoZUDdfyVG22BzzttCgQZqd5x21Le3io8TBPtMHxR/lLvQBUe8P6HQ2BfeP4nXww2k+g+CXcWfn5bibXUrkMiNp7B/GHgNQDfP8X7U8L6D+JKI1G8KMqhVqwbVijus1bZ7XK455xLSOsPDfrErZQE1/xAk7XLseysIKmXeEq4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1601315509; 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:References:Sender:Subject:To; bh=jeBD+kFB84F5G7GFluKLnMsR3PQQ7/SknDkEd0Xw1ww=; b=ghRNjtWu3wohlE4rzvUXHFJnPfJLhOsguMr8rY0Q9sRoA2UdkBH2mkLUm/w1vWryrMDwX0ixCQLkrg1aXyMGv3yEXWbwL5+HcCNimhXg3iBy5k8VFzLYGSACVHeu/xoMO0ARBVUoKu5eh/VJ3XsrzAuJzfhHyen3fCU+5BnVuig= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail header.i=@quicinc.com; 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=fail 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 1601315509316199.92813932974047; Mon, 28 Sep 2020 10:51:49 -0700 (PDT) Received: from localhost ([::1]:36320 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kMxJT-00041w-Hs for importer@patchew.org; Mon, 28 Sep 2020 13:51:47 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:48948) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kMwy2-00032X-WA for qemu-devel@nongnu.org; Mon, 28 Sep 2020 13:29:40 -0400 Received: from alexa-out-sd-01.qualcomm.com ([199.106.114.38]:53863) by eggs.gnu.org with esmtps (TLS1.2:RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kMwxv-0007v8-9Z for qemu-devel@nongnu.org; Mon, 28 Sep 2020 13:29:38 -0400 Received: from unknown (HELO ironmsg03-sd.qualcomm.com) ([10.53.140.143]) by alexa-out-sd-01.qualcomm.com with ESMTP; 28 Sep 2020 10:29:04 -0700 Received: from vu-tsimpson-aus.qualcomm.com (HELO vu-tsimpson1-aus.qualcomm.com) ([10.222.150.1]) by ironmsg03-sd.qualcomm.com with ESMTP; 28 Sep 2020 10:29:04 -0700 Received: by vu-tsimpson1-aus.qualcomm.com (Postfix, from userid 47164) id 2FF261184; Mon, 28 Sep 2020 12:29:04 -0500 (CDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=quicinc.com; i=@quicinc.com; q=dns/txt; s=qcdkim; t=1601314171; x=1632850171; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=jeBD+kFB84F5G7GFluKLnMsR3PQQ7/SknDkEd0Xw1ww=; b=nOe4VxuEJFSYw8/Pkz4fSVL2zkGNdHTDCsYkQz9v6AeqwmQk++gf4dln 7yLxP+t0bE5BHcgCr2X6Y5HrlOBSxTP3uf/UaClIdDd75NnGW2NOgnFB5 6xY8V6RQ/FkmmF+7Sv0tspGS4hKWx+miRSxMEgMjt6gJ+fk9yYTTbpDk5 U=; X-QCInternal: smtphost From: Taylor Simpson To: qemu-devel@nongnu.org Subject: [RFC PATCH v4 18/29] Hexagon (target/hexagon) generator phase 2 - generate header files Date: Mon, 28 Sep 2020 12:28:47 -0500 Message-Id: <1601314138-9930-19-git-send-email-tsimpson@quicinc.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1601314138-9930-1-git-send-email-tsimpson@quicinc.com> References: <1601314138-9930-1-git-send-email-tsimpson@quicinc.com> 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=199.106.114.38; envelope-from=tsimpson@qualcomm.com; helo=alexa-out-sd-01.qualcomm.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/09/28 13:29:03 X-ACL-Warn: Detected OS = FreeBSD 9.x or newer [fuzzy] X-Spam_score_int: -40 X-Spam_score: -4.1 X-Spam_bar: ---- X-Spam_report: (-4.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.199, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: ale@rev.ng, riku.voipio@iki.fi, richard.henderson@linaro.org, laurent@vivier.eu, tsimpson@quicinc.com, philmd@redhat.com, aleksandar.m.mail@gmail.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Python scripts generate the following files helper_protos_generated.h For each instruction we create DEF_HELPER function prototype helper_funcs_generated.h For each instruction we create the helper function definition tcg_funcs_generated.h For each instruction we create TCG code to generate call to helper tcg_func_table_generated.h Table of function pointers indexed by opcode shortcode_generated.h Generate a table of instruction "shortcode" semantics opcodes_def_generated.h Gives a list of all the opcodes op_attribs_generated.h Lists all the attributes associated with each instruction op_regs_generated.h Lists the register and immediate operands for each instruction printinsn_generated.h Data for printing (disassembling) each instruction (format string + operands) Signed-off-by: Taylor Simpson --- target/hexagon/gen_helper_funcs.py | 229 +++++++++++++++ target/hexagon/gen_helper_protos.py | 158 ++++++++++ target/hexagon/gen_op_attribs.py | 46 +++ target/hexagon/gen_op_regs.py | 119 ++++++++ target/hexagon/gen_opcodes_def.py | 43 +++ target/hexagon/gen_printinsn.py | 185 ++++++++++++ target/hexagon/gen_shortcode.py | 71 +++++ target/hexagon/gen_tcg_func_table.py | 66 +++++ target/hexagon/gen_tcg_funcs.py | 543 +++++++++++++++++++++++++++++++= ++++ target/hexagon/hex_common.py | 216 ++++++++++++++ 10 files changed, 1676 insertions(+) create mode 100755 target/hexagon/gen_helper_funcs.py create mode 100755 target/hexagon/gen_helper_protos.py create mode 100755 target/hexagon/gen_op_attribs.py create mode 100755 target/hexagon/gen_op_regs.py create mode 100755 target/hexagon/gen_opcodes_def.py create mode 100755 target/hexagon/gen_printinsn.py create mode 100755 target/hexagon/gen_shortcode.py create mode 100755 target/hexagon/gen_tcg_func_table.py create mode 100755 target/hexagon/gen_tcg_funcs.py create mode 100755 target/hexagon/hex_common.py diff --git a/target/hexagon/gen_helper_funcs.py b/target/hexagon/gen_helper= _funcs.py new file mode 100755 index 0000000..089818c --- /dev/null +++ b/target/hexagon/gen_helper_funcs.py @@ -0,0 +1,229 @@ +#!/usr/bin/env python3 + +## +## Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Res= erved. +## +## 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 + +from hex_common import * + +## +## Helpers for gen_helper_function +## +def gen_decl_ea(f): + f.write(" uint32_t EA;\n") + +def gen_helper_return_type(f,regtype,regid,regno): + if regno > 1 : f.write(", ") + f.write("int32_t") + +def gen_helper_return_type_pair(f,regtype,regid,regno): + if regno > 1 : f.write(", ") + f.write("int64_t") + +def gen_helper_arg(f,regtype,regid,regno): + if regno > 0 : f.write(", " ) + f.write("int32_t %s%sV" % (regtype,regid)) + +def gen_helper_arg_new(f,regtype,regid,regno): + if regno >=3D 0 : f.write(", " ) + f.write("int32_t %s%sN" % (regtype,regid)) + +def gen_helper_arg_pair(f,regtype,regid,regno): + if regno >=3D 0 : f.write(", ") + f.write("int64_t %s%sV" % (regtype,regid)) + +def gen_helper_arg_opn(f,regtype,regid,i,tag): + if (is_pair(regid)): + gen_helper_arg_pair(f,regtype,regid,i) + elif (is_single(regid)): + if is_old_val(regtype, regid, tag): + gen_helper_arg(f,regtype,regid,i) + elif is_new_val(regtype, regid, tag): + gen_helper_arg_new(f,regtype,regid,i) + else: + print("Bad register parse: ",regtype,regid,toss,numregs) + else: + print("Bad register parse: ",regtype,regid,toss,numregs) + +def gen_helper_arg_imm(f,immlett): + f.write(", int32_t %s" % (imm_name(immlett))) + +def gen_helper_dest_decl(f,regtype,regid,regno,subfield=3D""): + f.write(" int32_t %s%sV%s =3D 0;\n" % \ + (regtype,regid,subfield)) + +def gen_helper_dest_decl_pair(f,regtype,regid,regno,subfield=3D""): + f.write(" int64_t %s%sV%s =3D 0;\n" % \ + (regtype,regid,subfield)) + +def gen_helper_dest_decl_opn(f,regtype,regid,i): + if (is_pair(regid)): + gen_helper_dest_decl_pair(f,regtype,regid,i) + elif (is_single(regid)): + gen_helper_dest_decl(f,regtype,regid,i) + else: + print("Bad register parse: ",regtype,regid,toss,numregs) + +def gen_helper_return(f,regtype,regid,regno): + f.write(" return %s%sV;\n" % (regtype,regid)) + +def gen_helper_return_pair(f,regtype,regid,regno): + f.write(" return %s%sV;\n" % (regtype,regid)) + +def gen_helper_return_opn(f, regtype, regid, i): + if (is_pair(regid)): + gen_helper_return_pair(f,regtype,regid,i) + elif (is_single(regid)): + gen_helper_return(f,regtype,regid,i) + else: + print("Bad register parse: ",regtype,regid,toss,numregs) + +## +## Generate the TCG code to call the helper +## For A2_add: Rd32=3Dadd(Rs32,Rt32), { RdV=3DRsV+RtV;} +## We produce: +## int32_t HELPER(A2_add)(CPUHexagonState *env, int32_t RsV, int32_t= RtV) +## { +## uint32_t slot __attribute__(unused)) =3D 4; +## int32_t RdV =3D 0; +## { RdV=3DRsV+RtV;} +## COUNT_HELPER(A2_add); +## return RdV; +## } +## +def gen_helper_function(f, tag, tagregs, tagimms): + regs =3D tagregs[tag] + imms =3D tagimms[tag] + + numresults =3D 0 + numscalarresults =3D 0 + numscalarreadwrite =3D 0 + for regtype,regid,toss,numregs in regs: + if (is_written(regid)): + numresults +=3D 1 + if (is_scalar_reg(regtype)): + numscalarresults +=3D 1 + if (is_readwrite(regid)): + if (is_scalar_reg(regtype)): + numscalarreadwrite +=3D 1 + + if (numscalarresults > 1): + ## The helper is bogus when there is more than one result + f.write("void HELPER(%s)(CPUHexagonState *env) { BOGUS_HELPER(%s);= }\n" + % (tag, tag)) + else: + ## The return type of the function is the type of the destination + ## register + i=3D0 + for regtype,regid,toss,numregs in regs: + if (is_written(regid)): + if (is_pair(regid)): + gen_helper_return_type_pair(f,regtype,regid,i) + elif (is_single(regid)): + gen_helper_return_type(f,regtype,regid,i) + else: + print("Bad register parse: ",regtype,regid,toss,numreg= s) + i +=3D 1 + + if (numscalarresults =3D=3D 0): + f.write("void") + f.write(" HELPER(%s)(CPUHexagonState *env" % tag) + + i =3D 1 + + ## Arguments to the helper function are the source regs and immedi= ates + for regtype,regid,toss,numregs in regs: + if (is_read(regid)): + gen_helper_arg_opn(f,regtype,regid,i,tag) + i +=3D 1 + for immlett,bits,immshift in imms: + gen_helper_arg_imm(f,immlett) + i +=3D 1 + if need_slot(tag): + if i > 0: f.write(", ") + f.write("uint32_t slot") + i +=3D 1 + if need_part1(tag): + if i > 0: f.write(", ") + f.write("uint32_t part1") + f.write(")\n{\n") + if (not need_slot(tag)): + f.write(" uint32_t slot __attribute__((unused)) =3D 4;\n" ) + if need_ea(tag): gen_decl_ea(f) + ## Declare the return variable + i=3D0 + for regtype,regid,toss,numregs in regs: + if (is_writeonly(regid)): + gen_helper_dest_decl_opn(f,regtype,regid,i) + i +=3D 1 + + if 'A_FPOP' in attribdict[tag]: + f.write(' fFPOP_START();\n'); + + f.write(" %s\n" % semdict[tag]) + + if 'A_FPOP' in attribdict[tag]: + f.write(' fFPOP_END();\n'); + + ## Save/return the return variable + for regtype,regid,toss,numregs in regs: + if (is_written(regid)): + gen_helper_return_opn(f, regtype, regid, i) + f.write("}\n\n") + ## End of the helper definition + +def main(): + read_semantics_file(sys.argv[1]) + read_attribs_file(sys.argv[2]) + read_overrides_file(sys.argv[3]) + calculate_attribs() + tagregs =3D get_tagregs() + tagimms =3D get_tagimms() + + f =3D StringIO() + + for tag in tags: + ## Skip the priv instructions + if ( "A_PRIV" in attribdict[tag] ) : + continue + ## Skip the guest instructions + if ( "A_GUEST" in attribdict[tag] ) : + continue + ## Skip the diag instructions + if ( tag =3D=3D "Y6_diag" ) : + continue + if ( tag =3D=3D "Y6_diag0" ) : + continue + if ( tag =3D=3D "Y6_diag1" ) : + continue + if ( skip_qemu_helper(tag) ): + continue + + gen_helper_function(f, tag, tagregs, tagimms) + + + realf =3D open(sys.argv[4], 'w') + realf.write(f.getvalue()) + realf.close() + f.close() + +if __name__ =3D=3D "__main__": + main() diff --git a/target/hexagon/gen_helper_protos.py b/target/hexagon/gen_helpe= r_protos.py new file mode 100755 index 0000000..40e00e7 --- /dev/null +++ b/target/hexagon/gen_helper_protos.py @@ -0,0 +1,158 @@ +#!/usr/bin/env python3 + +## +## Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Res= erved. +## +## 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 + +from hex_common import * + +## +## Helpers for gen_helper_prototype +## +def_helper_types =3D { + 'N' : 's32', + 'O' : 's32', + 'P' : 's32', + 'M' : 's32', + 'C' : 's32', + 'R' : 's32', + 'V' : 'ptr', + 'Q' : 'ptr' +} + +def_helper_types_pair =3D { + 'R' : 's64', + 'C' : 's64', + 'S' : 's64', + 'G' : 's64', + 'V' : 'ptr', + 'Q' : 'ptr' +} + +def gen_def_helper_opn(f, tag, regtype, regid, toss, numregs, i): + if (is_pair(regid)): + f.write(", %s" % (def_helper_types_pair[regtype])) + elif (is_single(regid)): + f.write(", %s" % (def_helper_types[regtype])) + else: + print("Bad register parse: ",regtype,regid,toss,numregs) + +## +## Generate the DEF_HELPER prototype for an instruction +## For A2_add: Rd32=3Dadd(Rs32,Rt32) +## We produce: +## DEF_HELPER_3(A2_add, s32, env, s32, s32) +## +def gen_helper_prototype(f, tag, tagregs, tagimms): + regs =3D tagregs[tag] + imms =3D tagimms[tag] + + numresults =3D 0 + numscalarresults =3D 0 + numscalarreadwrite =3D 0 + for regtype,regid,toss,numregs in regs: + if (is_written(regid)): + numresults +=3D 1 + if (is_scalar_reg(regtype)): + numscalarresults +=3D 1 + if (is_readwrite(regid)): + if (is_scalar_reg(regtype)): + numscalarreadwrite +=3D 1 + + if (numscalarresults > 1): + ## The helper is bogus when there is more than one result + f.write('DEF_HELPER_1(%s, void, env)\n' % tag) + else: + ## Figure out how many arguments the helper will take + if (numscalarresults =3D=3D 0): + def_helper_size =3D len(regs)+len(imms)+numscalarreadwrite+1 + if need_part1(tag): def_helper_size +=3D 1 + if need_slot(tag): def_helper_size +=3D 1 + f.write('DEF_HELPER_%s(%s' % (def_helper_size, tag)) + ## The return type is void + f.write(', void' ) + else: + def_helper_size =3D len(regs)+len(imms)+numscalarreadwrite + if need_part1(tag): def_helper_size +=3D 1 + if need_slot(tag): def_helper_size +=3D 1 + f.write('DEF_HELPER_%s(%s' % (def_helper_size, tag)) + + ## Generate the qemu DEF_HELPER type for each result + i=3D0 + for regtype,regid,toss,numregs in regs: + if (is_written(regid)): + gen_def_helper_opn(f, tag, regtype, regid, toss, numregs, = i) + i +=3D 1 + + ## Put the env between the outputs and inputs + f.write(', env' ) + i +=3D 1 + + ## Generate the qemu type for each input operand (regs and immedia= tes) + for regtype,regid,toss,numregs in regs: + if (is_read(regid)): + gen_def_helper_opn(f, tag, regtype, regid, toss, numregs, = i) + i +=3D 1 + for immlett,bits,immshift in imms: + f.write(", s32") + + ## Add the arguments for the instruction slot and part1 (if needed) + if need_slot(tag): f.write(', i32' ) + if need_part1(tag): f.write(' , i32' ) + f.write(')\n') + +def main(): + read_semantics_file(sys.argv[1]) + read_attribs_file(sys.argv[2]) + read_overrides_file(sys.argv[3]) + calculate_attribs() + tagregs =3D get_tagregs() + tagimms =3D get_tagimms() + + f =3D StringIO() + + for tag in tags: + ## Skip the priv instructions + if ( "A_PRIV" in attribdict[tag] ) : + continue + ## Skip the guest instructions + if ( "A_GUEST" in attribdict[tag] ) : + continue + ## Skip the diag instructions + if ( tag =3D=3D "Y6_diag" ) : + continue + if ( tag =3D=3D "Y6_diag0" ) : + continue + if ( tag =3D=3D "Y6_diag1" ) : + continue + + if ( skip_qemu_helper(tag) ): + continue + + gen_helper_prototype(f, tag, tagregs, tagimms) + + realf =3D open(sys.argv[4], 'w') + realf.write(f.getvalue()) + realf.close() + f.close() + +if __name__ =3D=3D "__main__": + main() diff --git a/target/hexagon/gen_op_attribs.py b/target/hexagon/gen_op_attri= bs.py new file mode 100755 index 0000000..aef3f19 --- /dev/null +++ b/target/hexagon/gen_op_attribs.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 + +## +## Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Res= erved. +## +## 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 + +from hex_common import * + +def main(): + read_semantics_file(sys.argv[1]) + read_attribs_file(sys.argv[2]) + calculate_attribs() + + ## + ## Generate the op_attribs_generated.h file + ## Lists all the attributes associated with each instruction + ## + f =3D StringIO() + for tag in tags: + f.write('OP_ATTRIB(%s,ATTRIBS(%s))\n' % \ + (tag, ','.join(sorted(attribdict[tag])))) + realf =3D open(sys.argv[3], 'wt') + realf.write(f.getvalue()) + realf.close() + f.close() + +if __name__ =3D=3D "__main__": + main() diff --git a/target/hexagon/gen_op_regs.py b/target/hexagon/gen_op_regs.py new file mode 100755 index 0000000..0ce3ddf --- /dev/null +++ b/target/hexagon/gen_op_regs.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python3 + +## +## Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Res= erved. +## +## 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 + +from hex_common import * + +## +## Generate the op_regs_generated.h file +## Lists the register and immediate operands for each instruction +## +def calculate_regid_reg(tag): + def letter_inc(x): return chr(ord(x)+1) + ordered_implregs =3D [ 'SP','FP','LR' ] + srcdst_lett =3D 'X' + src_lett =3D 'S' + dst_lett =3D 'D' + retstr =3D "" + mapdict =3D {} + for reg in ordered_implregs: + reg_rd =3D 0 + reg_wr =3D 0 + if ('A_IMPLICIT_WRITES_'+reg) in attribdict[tag]: reg_wr =3D 1 + if reg_rd and reg_wr: + retstr +=3D srcdst_lett + mapdict[srcdst_lett] =3D reg + srcdst_lett =3D letter_inc(srcdst_lett) + elif reg_rd: + retstr +=3D src_lett + mapdict[src_lett] =3D reg + src_lett =3D letter_inc(src_lett) + elif reg_wr: + retstr +=3D dst_lett + mapdict[dst_lett] =3D reg + dst_lett =3D letter_inc(dst_lett) + return retstr,mapdict + +def calculate_regid_letters(tag): + retstr,mapdict =3D calculate_regid_reg(tag) + return retstr + +def strip_reg_prefix(x): + y=3Dx.replace('UREG.','') + y=3Dy.replace('MREG.','') + return y.replace('GREG.','') + +def main(): + read_semantics_file(sys.argv[1]) + read_attribs_file(sys.argv[2]) + tagregs =3D get_tagregs() + tagimms =3D get_tagimms() + + f =3D StringIO() + + for tag in tags: + regs =3D tagregs[tag] + rregs =3D [] + wregs =3D [] + regids =3D "" + for regtype,regid,toss,numregs in regs: + if is_read(regid): + if regid[0] not in regids: regids +=3D regid[0] + rregs.append(regtype+regid+numregs) + if is_written(regid): + wregs.append(regtype+regid+numregs) + if regid[0] not in regids: regids +=3D regid[0] + for attrib in attribdict[tag]: + if attribinfo[attrib]['rreg']: + rregs.append(strip_reg_prefix(attribinfo[attrib]['rreg'])) + if attribinfo[attrib]['wreg']: + wregs.append(strip_reg_prefix(attribinfo[attrib]['wreg'])) + regids +=3D calculate_regid_letters(tag) + f.write('REGINFO(%s,"%s",\t/*RD:*/\t"%s",\t/*WR:*/\t"%s")\n' % \ + (tag,regids,",".join(rregs),",".join(wregs))) + + for tag in tags: + imms =3D tagimms[tag] + f.write( 'IMMINFO(%s' % tag) + if not imms: + f.write(''','u',0,0,'U',0,0''') + for sign,size,shamt in imms: + if sign =3D=3D 'r': sign =3D 's' + if not shamt: + shamt =3D "0" + f.write(''','%s',%s,%s''' % (sign,size,shamt)) + if len(imms) =3D=3D 1: + if sign.isupper(): + myu =3D 'u' + else: + myu =3D 'U' + f.write(''','%s',0,0''' % myu) + f.write(')\n') + + realf =3D open(sys.argv[3], 'w') + realf.write(f.getvalue()) + realf.close() + f.close() + +if __name__ =3D=3D "__main__": + main() diff --git a/target/hexagon/gen_opcodes_def.py b/target/hexagon/gen_opcodes= _def.py new file mode 100755 index 0000000..3c47285 --- /dev/null +++ b/target/hexagon/gen_opcodes_def.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 + +## +## Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Res= erved. +## +## 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 + +from hex_common import * + +def main(): + read_semantics_file(sys.argv[1]) + + ## + ## Generate the opcodes_def_generated.h file + ## Gives a list of all the opcodes + ## + f =3D StringIO() + for tag in tags: + f.write ( "OPCODE(%s),\n" % (tag) ) + realf =3D open(sys.argv[3], 'wt') + realf.write(f.getvalue()) + realf.close() + f.close() + +if __name__ =3D=3D "__main__": + main() diff --git a/target/hexagon/gen_printinsn.py b/target/hexagon/gen_printinsn= .py new file mode 100755 index 0000000..149ffb4 --- /dev/null +++ b/target/hexagon/gen_printinsn.py @@ -0,0 +1,185 @@ +#!/usr/bin/env python3 + +## +## Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Res= erved. +## +## 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 + +from hex_common import * + +## +## Generate the printinsn_generated.h file +## Data for printing each instruction (format string + operands) +## +def regprinter(m): + str =3D m.group(1) + str +=3D ":".join(["%d"]*len(m.group(2))) + str +=3D m.group(3) + if ('S' in m.group(1)) and (len(m.group(2)) =3D=3D 1): + str +=3D "/%s" + elif ('C' in m.group(1)) and (len(m.group(2)) =3D=3D 1): + str +=3D "/%s" + return str + +def spacify(s): + # Regular expression that matches any operator that contains '=3D' cha= racter: + opswithequal_re =3D '[-+^&|!<>=3D]?=3D' + # Regular expression that matches any assignment operator. + assignment_re =3D '[-+^&|]?=3D' + + # Out of the operators that contain the =3D sign, if the operator is a= lso an + # assignment, spaces will be added around it, unless it's enclosed wit= hin + # parentheses, or spaces are already present. + + equals =3D re.compile(opswithequal_re) + assign =3D re.compile(assignment_re) + + slen =3D len(s) + paren_count =3D {} + i =3D 0 + pc =3D 0 + while i < slen: + c =3D s[i] + if c =3D=3D '(': + pc +=3D 1 + elif c =3D=3D ')': + pc -=3D 1 + paren_count[i] =3D pc + i +=3D 1 + + # Iterate over all operators that contain the equal sign. If any + # match is also an assignment operator, add spaces around it if + # the parenthesis count is 0. + pos =3D 0 + out =3D [] + for m in equals.finditer(s): + ms =3D m.start() + me =3D m.end() + # t is the string that matched opswithequal_re. + t =3D m.string[ms:me] + out +=3D s[pos:ms] + pos =3D me + if paren_count[ms] =3D=3D 0: + # Check if the entire string t is an assignment. + am =3D assign.match(t) + if am and len(am.group(0)) =3D=3D me-ms: + # Don't add spaces if they are already there. + if ms > 0 and s[ms-1] !=3D ' ': + out.append(' ') + out +=3D t + if me < slen and s[me] !=3D ' ': + out.append(' ') + continue + # If this is not an assignment, just append it to the output + # string. + out +=3D t + + # Append the remaining part of the string. + out +=3D s[pos:len(s)] + return ''.join(out) + +def main(): + read_semantics_file(sys.argv[1]) + read_attribs_file(sys.argv[2]) + + immext_casere =3D re.compile(r'IMMEXT\(([A-Za-z])') + + f =3D StringIO() + + for tag in tags: + if not behdict[tag]: continue + extendable_upper_imm =3D False + extendable_lower_imm =3D False + m =3D immext_casere.search(semdict[tag]) + if m: + if m.group(1).isupper(): + extendable_upper_imm =3D True + else: + extendable_lower_imm =3D True + beh =3D behdict[tag] + beh =3D regre.sub(regprinter,beh) + beh =3D absimmre.sub(r"#%s0x%x",beh) + beh =3D relimmre.sub(r"PC+%s%d",beh) + beh =3D spacify(beh) + # Print out a literal "%s" at the end, used to match empty string + # so C won't complain at us + if ("A_VECX" in attribdict[tag]): macname =3D "DEF_VECX_PRINTINFO" + else: macname =3D "DEF_PRINTINFO" + f.write('%s(%s,"%s%%s"' % (macname,tag,beh)) + regs_or_imms =3D reg_or_immre.findall(behdict[tag]) + ri =3D 0 + seenregs =3D {} + for allregs,a,b,c,d,allimm,immlett,bits,immshift in regs_or_imms: + if a: + #register + if b in seenregs: + regno =3D seenregs[b] + else: + regno =3D ri + if len(b) =3D=3D 1: + f.write(', insn->regno[%d]' % regno) + if 'S' in a: + f.write(', sreg2str(insn->regno[%d])' % regno) + elif 'C' in a: + f.write(', creg2str(insn->regno[%d])' % regno) + elif len(b) =3D=3D 2: + f.write(', insn->regno[%d] + 1, insn->regno[%d]' % \ + (regno,regno)) + elif len(b) =3D=3D 4: + f.write(', insn->regno[%d] ^ 3, insn->regno[%d] ^ 2, '= % \ + (regno, regno)) + f.write('insn->regno[%d] ^ 1, insn->regno[%d]' % \ + (regno, regno)) + else: + print("Put some stuff to handle quads here") + if b not in seenregs: + seenregs[b] =3D ri + ri +=3D 1 + else: + #immediate + if (immlett.isupper()): + if extendable_upper_imm: + if immlett in 'rR': + f.write(',insn->extension_valid?"##":""') + else: + f.write(',insn->extension_valid?"#":""') + else: + f.write(',""') + ii =3D 1 + else: + if extendable_lower_imm: + if immlett in 'rR': + f.write(',insn->extension_valid?"##":""') + else: + f.write(',insn->extension_valid?"#":""') + else: + f.write(',""') + ii =3D 0 + f.write(', insn->immed[%d]' % ii) + # append empty string so there is at least one more arg + f.write(',"")\n') + + realf =3D open(sys.argv[3], 'w') + realf.write(f.getvalue()) + realf.close() + f.close() + +if __name__ =3D=3D "__main__": + main() diff --git a/target/hexagon/gen_shortcode.py b/target/hexagon/gen_shortcode= .py new file mode 100755 index 0000000..1c7b611 --- /dev/null +++ b/target/hexagon/gen_shortcode.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 + +## +## Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Res= erved. +## +## 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 + +from hex_common import * + +def gen_shortcode(f, tag): + f.write('DEF_SHORTCODE(%s, %s)\n' % (tag,semdict[tag])) + +def main(): + read_semantics_file(sys.argv[1]) + read_attribs_file(sys.argv[2]) + calculate_attribs() + tagregs =3D get_tagregs() + tagimms =3D get_tagimms() + + ## + ## Generate the shortcode_generated.h file + ## + f =3D StringIO() + + f.write("#ifndef DEF_SHORTCODE\n") + f.write("#define DEF_SHORTCODE(TAG,SHORTCODE) /* Nothing */\n") + f.write("#endif\n") + + for tag in tags: + ## Skip the priv instructions + if ( "A_PRIV" in attribdict[tag] ) : + continue + ## Skip the guest instructions + if ( "A_GUEST" in attribdict[tag] ) : + continue + ## Skip the diag instructions + if ( tag =3D=3D "Y6_diag" ) : + continue + if ( tag =3D=3D "Y6_diag0" ) : + continue + if ( tag =3D=3D "Y6_diag1" ) : + continue + + gen_shortcode(f, tag) + + f.write("#undef DEF_SHORTCODE\n") + + realf =3D open(sys.argv[3], 'w') + realf.write(f.getvalue()) + realf.close() + f.close() + +if __name__ =3D=3D "__main__": + main() diff --git a/target/hexagon/gen_tcg_func_table.py b/target/hexagon/gen_tcg_= func_table.py new file mode 100755 index 0000000..c371aa8 --- /dev/null +++ b/target/hexagon/gen_tcg_func_table.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python3 + +## +## Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Res= erved. +## +## 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 + +from hex_common import * + +def main(): + read_semantics_file(sys.argv[1]) + read_attribs_file(sys.argv[2]) + calculate_attribs() + tagregs =3D get_tagregs() + tagimms =3D get_tagimms() + + f =3D StringIO() + + f.write("#ifndef HEXAGON_FUNC_TABLE_H\n") + f.write("#define HEXAGON_FUNC_TABLE_H\n\n") + + f.write("const semantic_insn_t opcode_genptr[XX_LAST_OPCODE] =3D {\n") + for tag in tags: + ## Skip the priv instructions + if ( "A_PRIV" in attribdict[tag] ) : + continue + ## Skip the guest instructions + if ( "A_GUEST" in attribdict[tag] ) : + continue + ## Skip the diag instructions + if ( tag =3D=3D "Y6_diag" ) : + continue + if ( tag =3D=3D "Y6_diag0" ) : + continue + if ( tag =3D=3D "Y6_diag1" ) : + continue + + f.write(" [%s] =3D generate_%s,\n" % (tag, tag)) + f.write("};\n\n") + + f.write("#endif /* HEXAGON_FUNC_TABLE_H */\n") + + realf =3D open(sys.argv[3], 'w') + realf.write(f.getvalue()) + realf.close() + f.close() + +if __name__ =3D=3D "__main__": + main() diff --git a/target/hexagon/gen_tcg_funcs.py b/target/hexagon/gen_tcg_funcs= .py new file mode 100755 index 0000000..1c3543e --- /dev/null +++ b/target/hexagon/gen_tcg_funcs.py @@ -0,0 +1,543 @@ +#!/usr/bin/env python3 + +## +## Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Res= erved. +## +## 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 + +from hex_common import * + +## +## Helpers for gen_tcg_func +## +def gen_decl_ea_tcg(f, tag): + if ('A_CONDEXEC' in attribdict[tag]): + f.write(" TCGv EA =3D tcg_temp_local_new();\n") + else: + f.write(" TCGv EA =3D tcg_temp_new();\n") + +def gen_free_ea_tcg(f): + f.write(" tcg_temp_free(EA);\n") + +def genptr_decl_pair_writeble(f, tag, regtype, regid, regno): + regN=3D"%s%sN" % (regtype,regid) + f.write(" TCGv_i64 %s%sV =3D tcg_temp_local_new_i64();\n" % \ + (regtype, regid)) + f.write(" const int %s =3D insn->regno[%d];\n" % (regN, regno)) + if ('A_CONDEXEC' in attribdict[tag]): + f.write(" if (!is_preloaded(ctx, %s)) {\n" % regN) + f.write(" tcg_gen_mov_tl(hex_new_value[%s], hex_gpr[%s]);\n= " % \ + (regN, regN)) + f.write(" }\n") + f.write(" if (!is_preloaded(ctx, %s + 1)) {\n" % regN) + f.write(" tcg_gen_mov_tl(hex_new_value[%s + 1], hex_gpr[%s = + 1]);\n" % \ + (regN, regN)) + f.write(" }\n") + +def genptr_decl_writeble(f, tag, regtype, regid, regno): + regN=3D"%s%sN" % (regtype,regid) + f.write(" TCGv %s%sV =3D tcg_temp_local_new();\n" % \ + (regtype, regid)) + f.write(" const int %s =3D insn->regno[%d];\n" % (regN, regno)) + if ('A_CONDEXEC' in attribdict[tag]): + f.write(" if (!is_preloaded(ctx, %s)) {\n" % regN) + f.write(" tcg_gen_mov_tl(hex_new_value[%s], hex_gpr[%s]);\n= " % \ + (regN, regN)) + f.write(" }\n") + +def genptr_decl(f, tag, regtype, regid, regno): + regN=3D"%s%sN" % (regtype,regid) + if (regtype =3D=3D "R"): + if (regid in {"ss", "tt"}): + f.write(" TCGv_i64 %s%sV =3D tcg_temp_local_new_i64();\n" %= \ + (regtype, regid)) + f.write(" const int %s =3D insn->regno[%d];\n" % \ + (regN, regno)) + elif (regid in {"dd", "ee", "xx", "yy"}): + genptr_decl_pair_writeble(f, tag, regtype, regid, regno) + elif (regid in {"s", "t", "u", "v"}): + f.write(" TCGv %s%sV =3D hex_gpr[insn->regno[%d]];\n" % \ + (regtype, regid, regno)) + elif (regid in {"d", "e", "x", "y"}): + genptr_decl_writeble(f, tag, regtype, regid, regno) + else: + print("Bad register parse: ", regtype, regid) + elif (regtype =3D=3D "P"): + if (regid in {"s", "t", "u", "v"}): + f.write(" TCGv %s%sV =3D hex_pred[insn->regno[%d]];\n" % \ + (regtype, regid, regno)) + elif (regid in {"d", "e", "x"}): + genptr_decl_writeble(f, tag, regtype, regid, regno) + else: + print("Bad register parse: ", regtype, regid) + elif (regtype =3D=3D "C"): + if (regid =3D=3D "ss"): + f.write(" TCGv_i64 %s%sV =3D tcg_temp_local_new_i64();\n" %= \ + (regtype, regid)) + f.write(" const int %s =3D insn->regno[%d];\n" % \ + (regN, regno)) + elif (regid =3D=3D "dd"): + genptr_decl_pair_writeble(f, tag, regtype, regid, regno) + elif (regid =3D=3D "s"): + f.write(" TCGv %s%sV =3D tcg_temp_local_new();\n" % \ + (regtype, regid)) + f.write(" const int %s%sN =3D insn->regno[%d];\n" % \ + (regtype, regid, regno)) + elif (regid =3D=3D "d"): + genptr_decl_writeble(f, tag, regtype, regid, regno) + else: + print("Bad register parse: ", regtype, regid) + elif (regtype =3D=3D "M"): + if (regid =3D=3D "u"): + f.write(" const int %s%sN =3D insn->regno[%d];\n"% \ + (regtype, regid, regno)) + f.write(" TCGv %s%sV =3D hex_gpr[%s%sN + HEX_REG_M0];\n" % \ + (regtype, regid, regtype, regid)) + else: + print("Bad register parse: ", regtype, regid) + else: + print("Bad register parse: ", regtype, regid) + +def genptr_decl_new(f,regtype,regid,regno): + if (regtype =3D=3D "N"): + if (regid in {"s", "t"}): + f.write(" const int %s%sX =3D insn->regno[%d];\n" % \ + (regtype, regid, regno)) + f.write(" TCGv %s%sN =3D tcg_const_tl(%s%sX);\n" % \ + (regtype, regid, regtype, regid)) + else: + print("Bad register parse: ", regtype, regid) + elif (regtype =3D=3D "P"): + if (regid in {"t", "u", "v"}): + f.write(" TCGv %s%sN =3D hex_new_pred_value[insn->regno[%d]= ];\n" % \ + (regtype, regid, regno)) + else: + print("Bad register parse: ", regtype, regid) + else: + print("Bad register parse: ", regtype, regid) + +def genptr_decl_opn(f, tag, regtype, regid, toss, numregs, i): + if (is_pair(regid)): + genptr_decl(f, tag, regtype, regid, i) + elif (is_single(regid)): + if is_old_val(regtype, regid, tag): + genptr_decl(f,tag, regtype, regid, i) + elif is_new_val(regtype, regid, tag): + genptr_decl_new(f,regtype,regid,i) + else: + print("Bad register parse: ",regtype,regid,toss,numregs) + else: + print("Bad register parse: ",regtype,regid,toss,numregs) + +def genptr_decl_imm(f,immlett): + if (immlett.isupper()): + i =3D 1 + else: + i =3D 0 + f.write(" int %s =3D insn->immed[%d];\n" % \ + (imm_name(immlett), i)) + +def genptr_free(f,regtype,regid,regno): + if (regtype =3D=3D "R"): + if (regid in {"dd", "ss", "tt", "xx", "yy"}): + f.write(" tcg_temp_free_i64(%s%sV);\n" % (regtype, regid)) + elif (regid in {"d", "e", "x", "y"}): + f.write(" tcg_temp_free(%s%sV);\n" % (regtype, regid)) + elif (regid not in {"s", "t", "u", "v"}): + print("Bad register parse: ",regtype,regid) + elif (regtype =3D=3D "P"): + if (regid in {"d", "e", "x"}): + f.write(" tcg_temp_free(%s%sV);\n" % (regtype, regid)) + elif (regid not in {"s", "t", "u", "v"}): + print("Bad register parse: ",regtype,regid) + elif (regtype =3D=3D "C"): + if (regid in {"dd", "ss"}): + f.write(" tcg_temp_free_i64(%s%sV);\n" % (regtype, regid)) + elif (regid in {"d", "s"}): + f.write(" tcg_temp_free(%s%sV);\n" % (regtype, regid)) + else: + print("Bad register parse: ",regtype,regid) + elif (regtype =3D=3D "M"): + if (regid !=3D "u"): + print("Bad register parse: ", regtype, regid) + else: + print("Bad register parse: ", regtype, regid) + +def genptr_free_new(f,regtype,regid,regno): + if (regtype =3D=3D "N"): + if (regid in {"s", "t"}): + f.write(" tcg_temp_free(%s%sN);\n" % \ + (regtype, regid)) + else: + print("Bad register parse: ", regtype, regid) + elif (regtype =3D=3D "P"): + if (regid not in {"t", "u", "v"}): + print("Bad register parse: ", regtype, regid) + else: + print("Bad register parse: ", regtype, regid) + +def genptr_free_opn(f,regtype,regid,i,tag): + if (is_pair(regid)): + genptr_free(f,regtype,regid,i) + elif (is_single(regid)): + if is_old_val(regtype, regid, tag): + genptr_free(f,regtype,regid,i) + elif is_new_val(regtype, regid, tag): + genptr_free_new(f,regtype,regid,i) + else: + print("Bad register parse: ",regtype,regid,toss,numregs) + else: + print("Bad register parse: ",regtype,regid,toss,numregs) + +def genptr_src_read(f,regtype,regid): + if (regtype =3D=3D "R"): + if (regid in {"ss", "tt", "xx", "yy"}): + f.write(" tcg_gen_concat_i32_i64(%s%sV, hex_gpr[%s%sN],\n" = % \ + (regtype, regid, regtype, regid)) + f.write(" hex_gpr[%s%sN + 1]);= \n" % \ + (regtype, regid)) + elif (regid in {"x", "y"}): + f.write(" tcg_gen_mov_tl(%s%sV, hex_gpr[%s%sN]);\n" % \ + (regtype,regid,regtype,regid)) + elif (regid not in {"s", "t", "u", "v"}): + print("Bad register parse: ", regtype, regid) + elif (regtype =3D=3D "P"): + if (regid =3D=3D "x"): + f.write(" tcg_gen_mov_tl(%s%sV, hex_pred[%s%sN]);\n" % \ + (regtype, regid, regtype, regid)) + elif (regid not in {"s", "t", "u", "v"}): + print("Bad register parse: ", regtype, regid) + elif (regtype =3D=3D "C"): + if (regid =3D=3D "ss"): + f.write(" if (%s%sN + HEX_REG_SA0 =3D=3D HEX_REG_P3_0) {\n"= % \ + (regtype, regid)) + f.write(" TCGv p3_0 =3D tcg_temp_new();\n") + f.write(" gen_read_p3_0(p3_0);\n") + f.write(" tcg_gen_concat_i32_i64(%s%sV, p3_0,\n" % \ + (regtype, regid)) + f.write(" hex_gpr[%s%sN + = 1]);\n" % \ + (regtype, regid)) + f.write(" tcg_temp_free(p3_0);\n") + f.write(" } else {\n") + f.write(" tcg_gen_concat_i32_i64(%s%sV, hex_gpr[%s%sN],= \n" % \ + (regtype, regid, regtype, regid)) + f.write(" hex_gpr[%s%sN + = 1]);\n" % \ + (regtype, regid)) + f.write(" }\n") + elif (regid =3D=3D "s"): + f.write(" if (%s%sN + HEX_REG_SA0 =3D=3D HEX_REG_P3_0) {\n"= % \ + (regtype, regid)) + f.write(" gen_read_p3_0(%s%sV);\n" % \ + (regtype, regid)) + f.write(" } else {\n") + f.write(" tcg_gen_mov_tl(%s%sV, hex_gpr[%s%sN + HEX_REG= _SA0]);\n" % \ + (regtype, regid, regtype, regid)) + f.write(" }\n") + else: + print("Bad register parse: ", regtype, regid) + elif (regtype =3D=3D "M"): + if (regid !=3D "u"): + print("Bad register parse: ", regtype, regid) + else: + print("Bad register parse: ", regtype, regid) + +def genptr_src_read_new(f,regtype,regid): + if (regtype =3D=3D "N"): + if (regid not in {"s", "t"}): + print("Bad register parse: ", regtype, regid) + elif (regtype =3D=3D "P"): + if (regid not in {"t", "u", "v"}): + print("Bad register parse: ", regtype, regid) + else: + print("Bad register parse: ", regtype, regid) + +def genptr_src_read_opn(f,regtype,regid,tag): + if (is_pair(regid)): + genptr_src_read(f,regtype,regid) + elif (is_single(regid)): + if is_old_val(regtype, regid, tag): + genptr_src_read(f,regtype,regid) + elif is_new_val(regtype, regid, tag): + genptr_src_read_new(f,regtype,regid) + else: + print("Bad register parse: ",regtype,regid,toss,numregs) + else: + print("Bad register parse: ",regtype,regid,toss,numregs) + +def gen_helper_call_opn(f, tag, regtype, regid, toss, numregs, i): + if (i > 0): f.write(", ") + if (is_pair(regid)): + f.write("%s%sV" % (regtype,regid)) + elif (is_single(regid)): + if is_old_val(regtype, regid, tag): + f.write("%s%sV" % (regtype,regid)) + elif is_new_val(regtype, regid, tag): + f.write("%s%sN" % (regtype,regid)) + else: + print("Bad register parse: ",regtype,regid,toss,numregs) + else: + print("Bad register parse: ",regtype,regid,toss,numregs) + +def gen_helper_decl_imm(f,immlett): + f.write(" TCGv tcgv_%s =3D tcg_const_tl(%s);\n" % \ + (imm_name(immlett), imm_name(immlett))) + +def gen_helper_call_imm(f,immlett): + f.write(", tcgv_%s" % imm_name(immlett)) + +def gen_helper_free_imm(f,immlett): + f.write(" tcg_temp_free(tcgv_%s);\n" % imm_name(immlett)) + +def genptr_dst_write_pair(f, tag, regtype, regid): + if ('A_CONDEXEC' in attribdict[tag]): + f.write(" gen_log_predicated_reg_write_pair(%s%sN, %s%sV, insn-= >slot);\n" % \ + (regtype, regid, regtype, regid)) + else: + f.write(" gen_log_reg_write_pair(%s%sN, %s%sV);\n" % \ + (regtype, regid, regtype, regid)) + f.write(" ctx_log_reg_write(ctx, %s%sN);\n" % \ + (regtype, regid)) + f.write(" ctx_log_reg_write(ctx, %s%sN + 1);\n" % \ + (regtype, regid)) + +def genptr_dst_write(f, tag, regtype, regid): + if (regtype =3D=3D "R"): + if (regid in {"dd", "xx", "yy"}): + genptr_dst_write_pair(f, tag, regtype, regid) + elif (regid in {"d", "e", "x", "y"}): + if ('A_CONDEXEC' in attribdict[tag]): + f.write(" gen_log_predicated_reg_write(%s%sN, %s%sV,\n"= % \ + (regtype, regid, regtype, regid)) + f.write(" insn->slot);\n") + else: + f.write(" gen_log_reg_write(%s%sN, %s%sV);\n" % \ + (regtype, regid, regtype, regid)) + f.write(" ctx_log_reg_write(ctx, %s%sN);\n" % \ + (regtype, regid)) + else: + print("Bad register parse: ", regtype, regid) + elif (regtype =3D=3D "P"): + if (regid in {"d", "e", "x"}): + f.write(" gen_log_pred_write(%s%sN, %s%sV);\n" % \ + (regtype, regid, regtype, regid)) + f.write(" ctx_log_pred_write(ctx, %s%sN);\n" % \ + (regtype, regid)) + else: + print("Bad register parse: ", regtype, regid) + elif (regtype =3D=3D "C"): + if (regid =3D=3D "dd"): + f.write(" if (%s%sN + HEX_REG_SA0 =3D=3D HEX_REG_P3_0) {\n"= % \ + (regtype, regid)) + f.write(" TCGv val32 =3D tcg_temp_new();\n") + f.write(" tcg_gen_extrl_i64_i32(val32, %s%sV);\n" % \ + (regtype, regid)) + f.write(" gen_write_p3_0(val32);\n") + f.write(" tcg_gen_extrh_i64_i32(val32, %s%sV);\n" % \ + (regtype, regid)) + f.write(" gen_log_reg_write(%s%sN + HEX_REG_SA0 + 1, va= l32);\n" % \ + (regtype, regid)) + f.write(" tcg_temp_free(val32);\n") + f.write(" ctx_log_reg_write(ctx, %s%sN + HEX_REG_SA0 + = 1);\n" % \ + (regtype, regid)) + f.write(" } else {\n") + f.write(" gen_log_reg_write_pair(%s%sN + HEX_REG_SA0, %= s%sV);\n" % \ + (regtype, regid, regtype, regid)) + f.write(" ctx_log_reg_write(ctx, %s%sN + HEX_REG_SA0);\= n" % \ + (regtype, regid)) + f.write(" ctx_log_reg_write(ctx, %s%sN + HEX_REG_SA0 + = 1);\n" % \ + (regtype, regid)) + f.write(" }\n") + elif (regid =3D=3D "d"): + f.write(" if (%s%sN + HEX_REG_SA0 =3D=3D HEX_REG_P3_0) {\n"= % \ + (regtype, regid)) + f.write(" gen_write_p3_0(%s%sV);\n" % \ + (regtype, regid)) + f.write(" } else {\n") + f.write(" gen_log_reg_write(%s%sN + HEX_REG_SA0, %s%sV)= ;\n" % \ + (regtype, regid, regtype, regid)) + f.write(" ctx_log_reg_write(ctx, %s%sN + HEX_REG_SA0);\= n" % \ + (regtype, regid)) + f.write(" }\n") + else: + print("Bad register parse: ", regtype, regid) + else: + print("Bad register parse: ", regtype, regid) + +def genptr_dst_write_opn(f,regtype, regid, tag): + if (is_pair(regid)): + genptr_dst_write(f, tag, regtype, regid) + elif (is_single(regid)): + genptr_dst_write(f, tag, regtype, regid) + else: + print("Bad register parse: ",regtype,regid,toss,numregs) + +## +## Generate the TCG code to call the helper +## For A2_add: Rd32=3Dadd(Rs32,Rt32), { RdV=3DRsV+RtV;} +## We produce: +## static void generate_A2_add() +## CPUHexagonState *env +## DisasContext *ctx, +## insn_t *insn, +## packet_t *pkt) +## { +## TCGv RdV =3D tcg_temp_local_new(); +## const int RdN =3D insn->regno[0]; +## TCGv RsV =3D hex_gpr[insn->regno[1]]; +## TCGv RtV =3D hex_gpr[insn->regno[2]]; +## +## gen_log_reg_write(RdN, RdV); +## ctx_log_reg_write(ctx, RdN); +## tcg_temp_free(RdV); +## } +## +## where depends on skip_qemu_helper(tag) +## if skip_qemu_helper(tag) is True +## is fGEN_TCG_A2_add({ RdV=3DRsV+RtV;}); +## if skip_qemu_helper(tag) is False +## is gen_helper_A2_add(RdV, cpu_env, RsV, RtV); +## +def gen_tcg_func(f, tag, regs, imms): + f.write("static void generate_%s(\n" %tag) + f.write(" CPUHexagonState *env,\n") + f.write(" DisasContext *ctx,\n") + f.write(" insn_t *insn,\n") + f.write(" packet_t *pkt)\n") + f.write('{\n') + if need_ea(tag): gen_decl_ea_tcg(f, tag) + i=3D0 + ## Declare all the operands (regs and immediates) + for regtype,regid,toss,numregs in regs: + genptr_decl_opn(f, tag, regtype, regid, toss, numregs, i) + i +=3D 1 + for immlett,bits,immshift in imms: + genptr_decl_imm(f,immlett) + + if 'A_PRIV' in attribdict[tag]: + f.write(' fCHECKFORPRIV();\n') + if 'A_GUEST' in attribdict[tag]: + f.write(' fCHECKFORGUEST();\n') + if 'A_FPOP' in attribdict[tag]: + f.write(' fFPOP_START();\n'); + + ## Read all the inputs + for regtype,regid,toss,numregs in regs: + if (is_read(regid)): + genptr_src_read_opn(f,regtype,regid,tag) + + if ( skip_qemu_helper(tag) ): + f.write(" fGEN_TCG_%s(%s);\n" % (tag, semdict[tag])) + else: + ## Generate the call to the helper + for immlett,bits,immshift in imms: + gen_helper_decl_imm(f,immlett) + if need_part1(tag): + f.write(" TCGv part1 =3D tcg_const_tl(insn->part1);\n") + if need_slot(tag): + f.write(" TCGv slot =3D tcg_const_tl(insn->slot);\n") + f.write(" gen_helper_%s(" % (tag)) + i=3D0 + ## If there is a scalar result, it is the return type + for regtype,regid,toss,numregs in regs: + if (is_written(regid)): + gen_helper_call_opn(f, tag, regtype, regid, toss, numregs,= i) + i +=3D 1 + if (i > 0): f.write(", ") + f.write("cpu_env") + i=3D1 + for regtype,regid,toss,numregs in regs: + if (is_read(regid)): + gen_helper_call_opn(f, tag, regtype, regid, toss, numregs,= i) + i +=3D 1 + for immlett,bits,immshift in imms: + gen_helper_call_imm(f,immlett) + + if need_slot(tag): f.write(", slot") + if need_part1(tag): f.write(", part1" ) + f.write(");\n") + if need_slot(tag): + f.write(" tcg_temp_free(slot);\n") + if need_part1(tag): + f.write(" tcg_temp_free(part1);\n") + for immlett,bits,immshift in imms: + gen_helper_free_imm(f,immlett) + + ## Write all the outputs + for regtype,regid,toss,numregs in regs: + if (is_written(regid)): + genptr_dst_write_opn(f,regtype, regid, tag) + + if 'A_FPOP' in attribdict[tag]: + f.write(' fFPOP_END();\n'); + + + ## Free all the operands (regs and immediates) + if need_ea(tag): gen_free_ea_tcg(f) + for regtype,regid,toss,numregs in regs: + genptr_free_opn(f,regtype,regid,i,tag) + i +=3D 1 + + f.write("}\n\n") + +def gen_def_tcg_func(f, tag, tagregs, tagimms): + regs =3D tagregs[tag] + imms =3D tagimms[tag] + + gen_tcg_func(f, tag, regs, imms) + +def main(): + read_semantics_file(sys.argv[1]) + read_attribs_file(sys.argv[2]) + read_overrides_file(sys.argv[3]) + calculate_attribs() + tagregs =3D get_tagregs() + tagimms =3D get_tagimms() + + f =3D StringIO() + + f.write("#ifndef HEXAGON_TCG_FUNCS_H\n") + f.write("#define HEXAGON_TCG_FUNCS_H\n\n") + + for tag in tags: + ## Skip the priv instructions + if ( "A_PRIV" in attribdict[tag] ) : + continue + ## Skip the guest instructions + if ( "A_GUEST" in attribdict[tag] ) : + continue + ## Skip the diag instructions + if ( tag =3D=3D "Y6_diag" ) : + continue + if ( tag =3D=3D "Y6_diag0" ) : + continue + if ( tag =3D=3D "Y6_diag1" ) : + continue + + gen_def_tcg_func(f, tag, tagregs, tagimms) + + f.write("#endif /* HEXAGON_TCG_FUNCS_H */\n") + + realf =3D open(sys.argv[4], 'w') + realf.write(f.getvalue()) + realf.close() + f.close() + +if __name__ =3D=3D "__main__": + main() diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py new file mode 100755 index 0000000..26f9624 --- /dev/null +++ b/target/hexagon/hex_common.py @@ -0,0 +1,216 @@ +#!/usr/bin/env python3 + +## +## Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Res= erved. +## +## 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 + +behdict =3D {} # tag ->behavior +semdict =3D {} # tag -> semantics +attribdict =3D {} # tag -> attributes +macros =3D {} # macro -> macro information... +attribinfo =3D {} # Register information and misc +tags =3D [] # list of all tags +overrides =3D {} # tags with helper overrides + +# We should do this as a hash for performance, +# but to keep order let's keep it as a list. +def uniquify(seq): + seen =3D set() + seen_add =3D seen.add + return [x for x in seq if x not in seen and not seen_add(x)] + +regre =3D re.compile( + r"((?" % l) + macro.attribs |=3D expand_macro_attribs( + macros[submacro], allmac_re) + finished_macros.add(macro.key) + return macro.attribs + +immextre =3D re.compile(r'f(MUST_)?IMMEXT[(]([UuSsRr])') +def calculate_attribs(): + # Recurse down macros, find attributes from sub-macros + macroValues =3D list(macros.values()) + allmacros_restr =3D "|".join(set([ m.re.pattern for m in macroValues ]= )) + allmacros_re =3D re.compile(allmacros_restr) + for macro in macroValues: + expand_macro_attribs(macro,allmacros_re) + # Append attributes to all instructions + for tag in tags: + for macname in allmacros_re.findall(semdict[tag]): + if not macname: continue + macro =3D macros[macname] + attribdict[tag] |=3D set(macro.attribs) + +def SEMANTICS(tag, beh, sem): + #print tag,beh,sem + behdict[tag] =3D beh + semdict[tag] =3D sem + attribdict[tag] =3D set() + tags.append(tag) # dicts have no order, this is for order + +def ATTRIBUTES(tag, attribstring): + attribstring =3D \ + attribstring.replace("ATTRIBS","").replace("(","").replace(")","") + if not attribstring: + return + attribs =3D attribstring.split(",") + for attrib in attribs: + attribdict[tag].add(attrib.strip()) + +class Macro(object): + __slots__ =3D ['key','name', 'beh', 'attribs', 're'] + def __init__(self, name, beh, attribs): + self.key =3D name + self.name =3D name + self.beh =3D beh + self.attribs =3D set(attribs) + self.re =3D re.compile("\\b" + name + "\\b") + +def MACROATTRIB(macname,beh,attribstring): + attribstring =3D attribstring.replace("(","").replace(")","") + if attribstring: + attribs =3D attribstring.split(",") + else: + attribs =3D [] + macros[macname] =3D Macro(macname,beh,attribs) + +def compute_tag_regs(tag): + return uniquify(regre.findall(behdict[tag])) + +def compute_tag_immediates(tag): + return uniquify(immre.findall(behdict[tag])) + +## +## tagregs is the main data structure we'll use +## tagregs[tag] will contain the registers used by an instruction +## Within each entry, we'll use the regtype and regid fields +## regtype can be one of the following +## C control register +## N new register value +## P predicate register +## R GPR register +## M modifier register +## regid can be one of the following +## d, e destination register +## dd destination register pair +## s, t, u, v, w source register +## ss, tt, uu, vv source register pair +## x, y read-write register +## xx, yy read-write register pair +## +def get_tagregs(): + return dict(zip(tags, list(map(compute_tag_regs, tags)))) + +def get_tagimms(): + return dict(zip(tags, list(map(compute_tag_immediates, tags)))) + +def is_pair(regid): + return len(regid) =3D=3D 2 + +def is_single(regid): + return len(regid) =3D=3D 1 + +def is_written(regid): + return regid[0] in "dexy" + +def is_writeonly(regid): + return regid[0] in "de" + +def is_read(regid): + return regid[0] in "stuvwxy" + +def is_readwrite(regid): + return regid[0] in "xy" + +def is_scalar_reg(regtype): + return regtype in "RPC" + +def is_old_val(regtype, regid, tag): + return regtype+regid+'V' in semdict[tag] + +def is_new_val(regtype, regid, tag): + return regtype+regid+'N' in semdict[tag] + +def need_slot(tag): + if ('A_CONDEXEC' in attribdict[tag] or + 'A_STORE' in attribdict[tag] or + 'A_LOAD' in attribdict[tag]): + return 1 + else: + return 0 + +def need_part1(tag): + return re.compile(r"fPART1").search(semdict[tag]) + +def need_ea(tag): + return re.compile(r"\bEA\b").search(semdict[tag]) + +def skip_qemu_helper(tag): + return tag in overrides.keys() + +def imm_name(immlett): + return "%siV" % immlett + +def read_semantics_file(name): + eval_line =3D "" + for line in open(name, 'rt').readlines(): + if not line.startswith("#"): + eval_line +=3D line + if line.endswith("\\\n"): + eval_line.rstrip("\\\n") + else: + eval(eval_line.strip()) + eval_line =3D "" + +def read_attribs_file(name): + attribre =3D re.compile(r'DEF_ATTRIB\(([A-Za-z0-9_]+), ([^,]*), ' + + r'"([A-Za-z0-9_\.]*)", "([A-Za-z0-9_\.]*)"\)') + for line in open(name, 'rt').readlines(): + if not attribre.match(line): + continue + (attrib_base,descr,rreg,wreg) =3D attribre.findall(line)[0] + attrib_base =3D 'A_' + attrib_base + attribinfo[attrib_base] =3D {'rreg':rreg, 'wreg':wreg, 'descr':des= cr} + +def read_overrides_file(name): + overridere =3D re.compile("#define fGEN_TCG_([A-Za-z0-9_]+)\(.*") + for line in open(name, 'rt').readlines(): + if not overridere.match(line): + continue + tag =3D overridere.findall(line)[0] + overrides[tag] =3D True --=20 2.7.4