From nobody Thu Nov 13 22:06:43 2025 Delivered-To: importer@patchew.org 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; 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=1582909764; cv=none; d=zohomail.com; s=zohoarc; b=VDMRVs7jegrVNFdHzoyfTKDaWe4WVz72U3Htz4ltTHCYbBEAXS9ye2/nfYChSEK/5J6FH/BSB+P952NwfMv5gsYplcQ5hKAGNYXegI9lLLpRHiETxOqK4K2n7gsK+MrswPovHLnAz8jM1wxSExVz0v6pvmd69y3vXaZPlS3WigA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1582909764; 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=yGYxHfH+spxucmBWiu25yYVocsuwWLSqiw6dypnmJC4=; b=Boi7iItEzfhWaXbUXsoFTnWLOPOCUwlW9s8YQfSm8cQVv+WoPd2jGQ9T77cqf41/3++0hjDbc1L2glINOGzc2I1/dD1cWnRTg8S4UKkmtalrLkO1TAijiYE7z68kR12zrBzdVeAskYtA+d/C3V9SEXZjicwgICTON7z4YhAT/WY= 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 1582909764348735.9798897515462; Fri, 28 Feb 2020 09:09:24 -0800 (PST) Received: from localhost ([::1]:50984 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j7j8c-0000KV-UB for importer@patchew.org; Fri, 28 Feb 2020 12:09:22 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:58221) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j7ilS-0004YS-Ux for qemu-devel@nongnu.org; Fri, 28 Feb 2020 11:45:30 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1j7ilP-0006Wr-6O for qemu-devel@nongnu.org; Fri, 28 Feb 2020 11:45:26 -0500 Received: from alexa-out-sd-01.qualcomm.com ([199.106.114.38]:13301) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1j7iks-0005cG-6t for qemu-devel@nongnu.org; Fri, 28 Feb 2020 11:45:23 -0500 Received: from unknown (HELO ironmsg03-sd.qualcomm.com) ([10.53.140.143]) by alexa-out-sd-01.qualcomm.com with ESMTP; 28 Feb 2020 08:44:30 -0800 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 Feb 2020 08:44:29 -0800 Received: by vu-tsimpson1-aus.qualcomm.com (Postfix, from userid 47164) id B55B7FCD; Fri, 28 Feb 2020 10:44:29 -0600 (CST) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=quicinc.com; i=@quicinc.com; q=dns/txt; s=qcdkim; t=1582908290; x=1614444290; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=yGYxHfH+spxucmBWiu25yYVocsuwWLSqiw6dypnmJC4=; b=zb6pRbYRjlvtnUwHrByNFCxo26uwh4OIN4A2bNwhk6s9o17QPMnVD+ot tDoRGHogBCDNe80p+iPj2SC3AVB/fH8WOEWdQbmeFV1nLXAzwuNc4oDfP ZN2Q6JmNwtRABirqsdWlJUPJWL0ka6sLl3hdIr7tFRrlcAjFEnvpin+SZ I=; From: Taylor Simpson To: qemu-devel@nongnu.org Subject: [RFC PATCH v2 22/67] Hexagon generator phase 2 - qemu_def_generated.h Date: Fri, 28 Feb 2020 10:43:18 -0600 Message-Id: <1582908244-304-23-git-send-email-tsimpson@quicinc.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1582908244-304-1-git-send-email-tsimpson@quicinc.com> References: <1582908244-304-1-git-send-email-tsimpson@quicinc.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: FreeBSD 9.x [fuzzy] X-Received-From: 199.106.114.38 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: riku.voipio@iki.fi, richard.henderson@linaro.org, laurent@vivier.eu, Taylor Simpson , 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) For each instruction we create DEF_HELPER function prototype TCG code to generate call to helper Helper definition Signed-off-by: Taylor Simpson --- target/hexagon/do_qemu.py | 769 ++++++++++++++++++++++++++++++++++++++++++= ++++ 1 file changed, 769 insertions(+) create mode 100755 target/hexagon/do_qemu.py diff --git a/target/hexagon/do_qemu.py b/target/hexagon/do_qemu.py new file mode 100755 index 0000000..6f0e376 --- /dev/null +++ b/target/hexagon/do_qemu.py @@ -0,0 +1,769 @@ +#!/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 + + +import operator +from itertools import chain + + + +behdict =3D {} # tag ->behavior +semdict =3D {} # tag -> semantics +extdict =3D {} # tag -> What extension an instruction belongs to = (or "") +extnames =3D {} # ext name -> True +attribdict =3D {} # tag -> attributes +macros =3D {} # macro -> macro information... +attribinfo =3D {} # Register information and misc +tags =3D [] # list of all tags + +def get_macro(macname,ext=3D""): + mackey =3D macname + ":" + ext + if ext and mackey not in macros: + return get_macro(macname,"") + return macros[mackey] + +# 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( + get_macro(submacro,macro.ext), 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 get_macro(macname,extdict[tag]) + attribdict[tag] |=3D set(macro.attribs) + m =3D immextre.search(semdict[tag]) + if m: + if m.group(2).isupper(): + attrib =3D 'A_EXT_UPPER_IMMED' + elif m.group(2).islower(): + attrib =3D 'A_EXT_LOWER_IMMED' + else: + raise "Not a letter: %s (%s)" % (m.group(1),tag) + if not attrib in attribdict[tag]: + attribdict[tag].add(attrib) + +def SEMANTICS(tag, beh, sem): + #print tag,beh,sem + extdict[tag] =3D "" + 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','ext'] + def __init__(self,key, name, beh, attribs,ext): + self.key =3D key + self.name =3D name + self.beh =3D beh + self.attribs =3D set(attribs) + self.ext =3D ext + self.re =3D re.compile("\\b" + name + "\\b") + +def MACROATTRIB(macname,beh,attribstring,ext=3D""): + attribstring =3D attribstring.replace("(","").replace(")","") + mackey =3D macname + ":" + ext + if attribstring: + attribs =3D attribstring.split(",") + else: + attribs =3D [] + macros[mackey] =3D Macro(mackey,macname,beh,attribs,ext) + +# read in file. Evaluate each line: each line calls a function above + +for line in open(sys.argv[1], 'rt').readlines(): + if not line.startswith("#"): + eval(line.strip()) + + +calculate_attribs() + + +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':descr} + +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 +## +tagregs =3D dict(zip(tags, list(map(compute_tag_regs, 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] + +tagimms =3D dict(zip(tags, list(map(compute_tag_immediates, tags)))) + +def need_slot(tag): + if ('A_CONDEXEC' in attribdict[tag] or + 'A_STORE' 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 + +## +## 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 fWRAP_A2_add +## DEF_HELPER_3(A2_add, s32, env, s32, s32) +## #endif +## +def gen_helper_prototype(f, tag, regs, imms): + f.write('#ifndef fWRAP_%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') + +## +## 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): + 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): + 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); +## fWRAP_A2_add( +## do { +## gen_helper_A2_add(RdV, cpu_env, RsV, RtV); +## while (0), +## { RdV=3DRsV+RtV;}); +## 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) + + ## Generate the call to the helper + f.write("fWRAP_%s(\n" % tag) + 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)") + f.write(",\n%s);\n" % semdict[tag] ) + + ## 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) + i +=3D 1 + for immlett,bits,immshift in imms: + genptr_free_imm(f,immlett) + + f.write("/* %s */\n" % tag) + f.write("}") + +## +## Helpers for gen_helper_definition +## +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): + 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 fWRAP_A2_add +## int32_t HELPER(A2_add)(CPUHexagonState *env, int32_t RsV, int32_t= RtV) +## { +## uint32_t slot =3D 4; slot =3D slot; +## int32_t RdV =3D 0; +## { RdV=3DRsV+RtV;} +## COUNT_HELPER(A2_add); +## return RdV; +## } +## #endif +## +def gen_helper_definition(f, tag, regs, imms): + f.write('#ifndef fWRAP_%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) + 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 =3D 4; slot =3D sl= ot;\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") + f.write("COUNT_HELPER(%s);\n" % 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") + ## End of the helper definition + f.write('#endif\n') + +## +## Bring it all together in the DEF_QEMU macro +## +def gen_qemu(f, tag): + regs =3D tagregs[tag] + imms =3D tagimms[tag] + + f.write('DEF_QEMU(%s,%s,\n' % (tag,semdict[tag])) + gen_helper_prototype(f, tag, regs, imms) + f.write(",\n" ) + gen_tcg_func(f, tag, regs, imms) + f.write(",\n" ) + gen_helper_definition(f, tag, regs, imms) + f.write(")\n") + +## +## Generate the qemu_def_generated.h file +## +f =3D StringIO() + +f.write("#ifndef DEF_QEMU\n") +f.write("#define DEF_QEMU(TAG,SHORTCODE,HELPER,GENFN,HELPFN) /* Nothing = */\n") +f.write("#endif\n\n") + + +for tag in tags: + ## Skip assembler mapped instructions + if "A_MAPPING" in attribdict[tag]: + continue + ## Skip the fake instructions + if ( "A_FAKEINSN" in attribdict[tag] ) : + continue + ## 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_qemu(f, tag) + +realf =3D open('qemu_def_generated.h','w') +realf.write(f.getvalue()) +realf.close() +f.close() + --=20 2.7.4