From nobody Mon Feb 9 17:36:10 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=1597767055; cv=none; d=zohomail.com; s=zohoarc; b=NOGaccyHUB8spMquVIRGOvU5YsYAZivbTOaaLILcsBA9KBEdQYWg6Hf/IUmAc7uXt0eJxoiXLmc5vSaVAdt50SNwvbfeLpUofuRvvxcu89UySgIqEaG2qrHOdfKfoZx+L+4VZCk0Ao1IOxDm9E2KY1BqpVCjB01xtgsNU1TfpQM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1597767055; 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=xxRUwtV9seQpocl47f4bhfzv96+ccLFVOhfXGSKbmKk=; b=AYInuVPICldONLWH6Qj0mPVbbkQ5rdbPcwNJyyf5uV3P3efM+KaPMQuacvn4MN+BduX3gbtnIypzRuOLksA5cT7SdnFeBb6ZXQepOAcohZH5V0tr6SwEzVY/2dfXHABOrcvJDJXg0Mau+bI/+UjP2yt6bcDCWNtfDnOKzC41e6Y= 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 1597767055026642.3190282257959; Tue, 18 Aug 2020 09:10:55 -0700 (PDT) Received: from localhost ([::1]:51096 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1k84CL-0007KM-Ir for importer@patchew.org; Tue, 18 Aug 2020 12:10:53 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:32972) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k83u1-0008FQ-KJ for qemu-devel@nongnu.org; Tue, 18 Aug 2020 11:51:57 -0400 Received: from alexa-out-sd-02.qualcomm.com ([199.106.114.39]:12947) by eggs.gnu.org with esmtps (TLS1.2:RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1k83tx-0005sa-2s for qemu-devel@nongnu.org; Tue, 18 Aug 2020 11:51:57 -0400 Received: from unknown (HELO ironmsg02-sd.qualcomm.com) ([10.53.140.142]) by alexa-out-sd-02.qualcomm.com with ESMTP; 18 Aug 2020 08:51:00 -0700 Received: from vu-tsimpson-aus.qualcomm.com (HELO vu-tsimpson1-aus.qualcomm.com) ([10.222.150.1]) by ironmsg02-sd.qualcomm.com with ESMTP; 18 Aug 2020 08:50:58 -0700 Received: by vu-tsimpson1-aus.qualcomm.com (Postfix, from userid 47164) id D444A1618; Tue, 18 Aug 2020 10:50:57 -0500 (CDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=quicinc.com; i=@quicinc.com; q=dns/txt; s=qcdkim; t=1597765913; x=1629301913; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=xxRUwtV9seQpocl47f4bhfzv96+ccLFVOhfXGSKbmKk=; b=b0Ry9doPfeIqVUdJKOnxPRZnHT8vQQValXB2Yn8R/vABdV9OwZ7GgkmK 52xGoqdH9Yypv+bshc/9MjgAOmOdetnQhqIA2sVVZK2POW6ohsJFF3uoU f8Q1vzw736hFMSVoOZ4pUkJZwyOZtl6f3PLs176hJp4W4gyxbcHJcXJXM o=; From: Taylor Simpson To: qemu-devel@nongnu.org Subject: [RFC PATCH v3 21/34] Hexagon (target/hexagon) generator phase 2 - generate header files Date: Tue, 18 Aug 2020 10:50:34 -0500 Message-Id: <1597765847-16637-22-git-send-email-tsimpson@quicinc.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1597765847-16637-1-git-send-email-tsimpson@quicinc.com> References: <1597765847-16637-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.39; envelope-from=tsimpson@qualcomm.com; helo=alexa-out-sd-02.qualcomm.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/08/18 11:50:57 X-ACL-Warn: Detected OS = FreeBSD 9.x or newer [fuzzy] X-Spam_score_int: -32 X-Spam_score: -3.3 X-Spam_bar: --- X-Spam_report: (-3.3 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, URIBL_BLOCKED=0.001, WEIRD_QUOTING=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 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 | 230 +++++++++++++++++++++++++++ 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 | 182 ++++++++++++++++++++++ target/hexagon/gen_shortcode.py | 71 +++++++++ target/hexagon/gen_tcg_funcs.py | 301 ++++++++++++++++++++++++++++++++= ++++ target/hexagon/hex_common.py | 204 ++++++++++++++++++++++++ 9 files changed, 1354 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_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..4595887 --- /dev/null +++ b/target/hexagon/gen_helper_funcs.py @@ -0,0 +1,230 @@ +#!/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("size4u_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: +## #ifndef fGEN_TCG_A2_add +## 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;} +## return RdV; +## } +## #endif +## +def gen_helper_function(f, tag, tagregs, tagimms): + regs =3D tagregs[tag] + imms =3D tagimms[tag] + + f.write('#ifndef fGEN_TCG_%s\n' % 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(semdict[tag]) + f.write("\n") + + 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") + ## End of the helper definition + f.write('#endif\n') + +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() + + 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_helper_function(f, tag, tagregs, tagimms) + + + realf =3D open('helper_funcs_generated.h','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..6d5ab07 --- /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: +## #ifndef fGEN_TCG_A2_add +## DEF_HELPER_3(A2_add, s32, env, s32, s32) +## #endif +## +def gen_helper_prototype(f, tag, tagregs, tagimms): + regs =3D tagregs[tag] + imms =3D tagimms[tag] + + f.write('#ifndef fGEN_TCG_%s\n' % 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') + f.write('#endif\n') + +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() + + 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_helper_prototype(f, tag, tagregs, tagimms) + + realf =3D open('helper_protos_generated.h','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..663296e --- /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('op_attribs_generated.h', '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..abb7441 --- /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('op_regs_generated.h','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..c34c2b1 --- /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('opcodes_def_generated.h', '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..6fb9424 --- /dev/null +++ b/target/hexagon/gen_printinsn.py @@ -0,0 +1,182 @@ +#!/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(',REGNO(%d)' % regno) + if 'S' in a: + f.write(',sreg2str(REGNO(%d))' % regno) + elif 'C' in a: + f.write(',creg2str(REGNO(%d))' % regno) + elif len(b) =3D=3D 2: + f.write(',REGNO(%d)+1,REGNO(%d)' % (regno,regno)) + elif len(b) =3D=3D 4: + f.write(',REGNO(%d)^3,REGNO(%d)^2,REGNO(%d)^1,REGNO(%d= )' % \ + (regno,regno,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(',IMMNO(%d)' % ii) + # append empty string so there is at least one more arg + f.write(',"")\n') + + realf =3D open('printinsn_generated.h','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..3255972 --- /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('shortcode_generated.h','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..1b2ef5b --- /dev/null +++ b/target/hexagon/gen_tcg_funcs.py @@ -0,0 +1,301 @@ +#!/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): + f.write("DECL_EA;\n") + +def gen_free_ea_tcg(f): + f.write("FREE_EA;\n") + +def genptr_decl(f,regtype,regid,regno): + regN=3D"%s%sN" % (regtype,regid) + macro =3D "DECL_%sREG_%s" % (regtype, regid) + f.write("%s(%s%sV, %s, %d, 0);\n" % \ + (macro, regtype, regid, regN, regno)) + +def genptr_decl_new(f,regtype,regid,regno): + regN=3D"%s%sX" % (regtype,regid) + macro =3D "DECL_NEW_%sREG_%s" % (regtype, regid) + f.write("%s(%s%sN, %s, %d, 0);\n" % \ + (macro, regtype, regid, regN, regno)) + +def genptr_decl_opn(f, tag, regtype, regid, toss, numregs, i): + if (is_pair(regid)): + genptr_decl(f,regtype,regid,i) + elif (is_single(regid)): + if is_old_val(regtype, regid, tag): + genptr_decl(f,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("DECL_IMM(%s,%d);\n" % (imm_name(immlett),i)) + +def genptr_free(f,regtype,regid,regno): + macro =3D "FREE_%sREG_%s" % (regtype, regid) + f.write("%s(%s%sV);\n" % (macro, regtype, regid)) + +def genptr_free_new(f,regtype,regid,regno): + macro =3D "FREE_NEW_%sREG_%s" % (regtype, regid) + f.write("%s(%s%sN);\n" % (macro, 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_free_imm(f,immlett): + f.write("FREE_IMM(%s);\n" % (imm_name(immlett))) + +def genptr_src_read(f,regtype,regid): + macro =3D "READ_%sREG_%s" % (regtype, regid) + f.write("%s(%s%sV, %s%sN);\n" % \ + (macro,regtype,regid,regtype,regid)) + +def genptr_src_read_new(f,regtype,regid): + macro =3D "READ_NEW_%sREG_%s" % (regtype, regid) + f.write("%s(%s%sN, %s%sX);\n" % \ + (macro,regtype,regid,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("DECL_TCG_IMM(tcgv_%s, %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("FREE_TCG_IMM(tcgv_%s);\n" % imm_name(immlett)) + +def genptr_dst_write(f,regtype, regid): + macro =3D "WRITE_%sREG_%s" % (regtype, regid) + f.write("%s(%s%sN, %s%sV);\n" % (macro, regtype, regid, regtype, regid= )) + +def genptr_dst_write_opn(f,regtype, regid, tag): + if (is_pair(regid)): + genptr_dst_write(f, regtype, regid) + elif (is_single(regid)): + genptr_dst_write(f, 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: +## { +## /* A2_add */ +## DECL_RREG_d(RdV, RdN, 0, 0); +## DECL_RREG_s(RsV, RsN, 1, 0); +## DECL_RREG_t(RtV, RtN, 2, 0); +## READ_RREG_s(RsV, RsN); +## READ_RREG_t(RtV, RtN); +## #ifdef fGEN_TCG_A2_add +## fGEN_TCG_A2_add({ RdV=3DRsV+RtV;}); +## #else +## gen_helper_A2_add(RdV, cpu_env, RsV, RtV); +## #endif +## WRITE_RREG_d(RdN, RdV); +## FREE_RREG_d(RdV); +## FREE_RREG_s(RsV); +## FREE_RREG_t(RtV); +## /* A2_add */ +## } +## +def gen_tcg_func(f, tag, regs, imms): + f.write('{\n') + f.write('/* %s */\n' % tag) + if need_ea(tag): gen_decl_ea_tcg(f) + 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) + + f.write("#ifdef fGEN_TCG_%s\n" % tag) + f.write("fGEN_TCG_%s(%s);\n" % (tag, semdict[tag])) + f.write("#else\n") + ## Generate the call to the helper + f.write("do {\n") + for immlett,bits,immshift in imms: + gen_helper_decl_imm(f,immlett) + if need_part1(tag): f.write("PART1_WRAP(") + if need_slot(tag): f.write("SLOT_WRAP(") + 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(")") + if need_slot(tag): f.write(")") + if need_part1(tag): f.write(")") + f.write(";\n") + for immlett,bits,immshift in imms: + gen_helper_free_imm(f,immlett) + f.write("} while (0);\n") + f.write("#endif\n") + + ## 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 + for immlett,bits,immshift in imms: + genptr_free_imm(f,immlett) + + f.write("/* %s */\n" % tag) + f.write("}") + +def gen_def_tcg_func(f, tag, tagregs, tagimms): + regs =3D tagregs[tag] + imms =3D tagimms[tag] + + f.write('DEF_TCG_FUNC(%s, /* %s */\n' % (tag,semdict[tag])) + gen_tcg_func(f, tag, regs, imms) + f.write(")\n" ) + +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 DEF_TCG_FUNC\n") + f.write("#define DEF_TCG_FUNC(TAG,GENFN) /* 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_def_tcg_func(f, tag, tagregs, tagimms) + + f.write("#undef DEF_TCG_FUNC\n") + + realf =3D open('tcg_funcs_generated.h','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..d45ffab --- /dev/null +++ b/target/hexagon/hex_common.py @@ -0,0 +1,204 @@ +#!/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 + +# 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 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(sys.argv[2], '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} --=20 2.7.4