qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

gen_helper_funcs.py (11478B)


      1 #!/usr/bin/env python3
      2 
      3 ##
      4 ##  Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
      5 ##
      6 ##  This program is free software; you can redistribute it and/or modify
      7 ##  it under the terms of the GNU General Public License as published by
      8 ##  the Free Software Foundation; either version 2 of the License, or
      9 ##  (at your option) any later version.
     10 ##
     11 ##  This program is distributed in the hope that it will be useful,
     12 ##  but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 ##  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14 ##  GNU General Public License for more details.
     15 ##
     16 ##  You should have received a copy of the GNU General Public License
     17 ##  along with this program; if not, see <http://www.gnu.org/licenses/>.
     18 ##
     19 
     20 import sys
     21 import re
     22 import string
     23 import hex_common
     24 
     25 ##
     26 ## Helpers for gen_helper_function
     27 ##
     28 def gen_decl_ea(f):
     29     f.write("    uint32_t EA;\n")
     30 
     31 def gen_helper_return_type(f,regtype,regid,regno):
     32     if regno > 1 : f.write(", ")
     33     f.write("int32_t")
     34 
     35 def gen_helper_return_type_pair(f,regtype,regid,regno):
     36     if regno > 1 : f.write(", ")
     37     f.write("int64_t")
     38 
     39 def gen_helper_arg(f,regtype,regid,regno):
     40     if regno > 0 : f.write(", " )
     41     f.write("int32_t %s%sV" % (regtype,regid))
     42 
     43 def gen_helper_arg_new(f,regtype,regid,regno):
     44     if regno >= 0 : f.write(", " )
     45     f.write("int32_t %s%sN" % (regtype,regid))
     46 
     47 def gen_helper_arg_pair(f,regtype,regid,regno):
     48     if regno >= 0 : f.write(", ")
     49     f.write("int64_t %s%sV" % (regtype,regid))
     50 
     51 def gen_helper_arg_ext(f,regtype,regid,regno):
     52     if regno > 0 : f.write(", ")
     53     f.write("void *%s%sV_void" % (regtype,regid))
     54 
     55 def gen_helper_arg_ext_pair(f,regtype,regid,regno):
     56     if regno > 0 : f.write(", ")
     57     f.write("void *%s%sV_void" % (regtype,regid))
     58 
     59 def gen_helper_arg_opn(f,regtype,regid,i,tag):
     60     if (hex_common.is_pair(regid)):
     61         if (hex_common.is_hvx_reg(regtype)):
     62             gen_helper_arg_ext_pair(f,regtype,regid,i)
     63         else:
     64             gen_helper_arg_pair(f,regtype,regid,i)
     65     elif (hex_common.is_single(regid)):
     66         if hex_common.is_old_val(regtype, regid, tag):
     67             if (hex_common.is_hvx_reg(regtype)):
     68                 gen_helper_arg_ext(f,regtype,regid,i)
     69             else:
     70                 gen_helper_arg(f,regtype,regid,i)
     71         elif hex_common.is_new_val(regtype, regid, tag):
     72             gen_helper_arg_new(f,regtype,regid,i)
     73         else:
     74             print("Bad register parse: ",regtype,regid,toss,numregs)
     75     else:
     76         print("Bad register parse: ",regtype,regid,toss,numregs)
     77 
     78 def gen_helper_arg_imm(f,immlett):
     79     f.write(", int32_t %s" % (hex_common.imm_name(immlett)))
     80 
     81 def gen_helper_dest_decl(f,regtype,regid,regno,subfield=""):
     82     f.write("    int32_t %s%sV%s = 0;\n" % \
     83         (regtype,regid,subfield))
     84 
     85 def gen_helper_dest_decl_pair(f,regtype,regid,regno,subfield=""):
     86     f.write("    int64_t %s%sV%s = 0;\n" % \
     87         (regtype,regid,subfield))
     88 
     89 def gen_helper_dest_decl_ext(f,regtype,regid):
     90     if (regtype == "Q"):
     91         f.write("    /* %s%sV is *(MMQReg *)(%s%sV_void) */\n" % \
     92             (regtype,regid,regtype,regid))
     93     else:
     94         f.write("    /* %s%sV is *(MMVector *)(%s%sV_void) */\n" % \
     95             (regtype,regid,regtype,regid))
     96 
     97 def gen_helper_dest_decl_ext_pair(f,regtype,regid,regno):
     98     f.write("    /* %s%sV is *(MMVectorPair *))%s%sV_void) */\n" % \
     99         (regtype,regid,regtype, regid))
    100 
    101 def gen_helper_dest_decl_opn(f,regtype,regid,i):
    102     if (hex_common.is_pair(regid)):
    103         if (hex_common.is_hvx_reg(regtype)):
    104             gen_helper_dest_decl_ext_pair(f,regtype,regid, i)
    105         else:
    106             gen_helper_dest_decl_pair(f,regtype,regid,i)
    107     elif (hex_common.is_single(regid)):
    108         if (hex_common.is_hvx_reg(regtype)):
    109             gen_helper_dest_decl_ext(f,regtype,regid)
    110         else:
    111             gen_helper_dest_decl(f,regtype,regid,i)
    112     else:
    113         print("Bad register parse: ",regtype,regid,toss,numregs)
    114 
    115 def gen_helper_src_var_ext(f,regtype,regid):
    116     if (regtype == "Q"):
    117        f.write("    /* %s%sV is *(MMQReg *)(%s%sV_void) */\n" % \
    118            (regtype,regid,regtype,regid))
    119     else:
    120        f.write("    /* %s%sV is *(MMVector *)(%s%sV_void) */\n" % \
    121            (regtype,regid,regtype,regid))
    122 
    123 def gen_helper_src_var_ext_pair(f,regtype,regid,regno):
    124     f.write("    /* %s%sV%s is *(MMVectorPair *)(%s%sV%s_void) */\n" % \
    125         (regtype,regid,regno,regtype,regid,regno))
    126 
    127 def gen_helper_return(f,regtype,regid,regno):
    128     f.write("    return %s%sV;\n" % (regtype,regid))
    129 
    130 def gen_helper_return_pair(f,regtype,regid,regno):
    131     f.write("    return %s%sV;\n" % (regtype,regid))
    132 
    133 def gen_helper_dst_write_ext(f,regtype,regid):
    134     return
    135 
    136 def gen_helper_dst_write_ext_pair(f,regtype,regid):
    137     return
    138 
    139 def gen_helper_return_opn(f, regtype, regid, i):
    140     if (hex_common.is_pair(regid)):
    141         if (hex_common.is_hvx_reg(regtype)):
    142             gen_helper_dst_write_ext_pair(f,regtype,regid)
    143         else:
    144             gen_helper_return_pair(f,regtype,regid,i)
    145     elif (hex_common.is_single(regid)):
    146         if (hex_common.is_hvx_reg(regtype)):
    147             gen_helper_dst_write_ext(f,regtype,regid)
    148         else:
    149             gen_helper_return(f,regtype,regid,i)
    150     else:
    151         print("Bad register parse: ",regtype,regid,toss,numregs)
    152 
    153 ##
    154 ## Generate the TCG code to call the helper
    155 ##     For A2_add: Rd32=add(Rs32,Rt32), { RdV=RsV+RtV;}
    156 ##     We produce:
    157 ##       int32_t HELPER(A2_add)(CPUHexagonState *env, int32_t RsV, int32_t RtV)
    158 ##       {
    159 ##           uint32_t slot __attribute__(unused)) = 4;
    160 ##           int32_t RdV = 0;
    161 ##           { RdV=RsV+RtV;}
    162 ##           COUNT_HELPER(A2_add);
    163 ##           return RdV;
    164 ##       }
    165 ##
    166 def gen_helper_function(f, tag, tagregs, tagimms):
    167     regs = tagregs[tag]
    168     imms = tagimms[tag]
    169 
    170     numresults = 0
    171     numscalarresults = 0
    172     numscalarreadwrite = 0
    173     for regtype,regid,toss,numregs in regs:
    174         if (hex_common.is_written(regid)):
    175             numresults += 1
    176             if (hex_common.is_scalar_reg(regtype)):
    177                 numscalarresults += 1
    178         if (hex_common.is_readwrite(regid)):
    179             if (hex_common.is_scalar_reg(regtype)):
    180                 numscalarreadwrite += 1
    181 
    182     if (numscalarresults > 1):
    183         ## The helper is bogus when there is more than one result
    184         f.write("void HELPER(%s)(CPUHexagonState *env) { BOGUS_HELPER(%s); }\n"
    185                 % (tag, tag))
    186     else:
    187         ## The return type of the function is the type of the destination
    188         ## register (if scalar)
    189         i=0
    190         for regtype,regid,toss,numregs in regs:
    191             if (hex_common.is_written(regid)):
    192                 if (hex_common.is_pair(regid)):
    193                     if (hex_common.is_hvx_reg(regtype)):
    194                         continue
    195                     else:
    196                         gen_helper_return_type_pair(f,regtype,regid,i)
    197                 elif (hex_common.is_single(regid)):
    198                     if (hex_common.is_hvx_reg(regtype)):
    199                             continue
    200                     else:
    201                         gen_helper_return_type(f,regtype,regid,i)
    202                 else:
    203                     print("Bad register parse: ",regtype,regid,toss,numregs)
    204             i += 1
    205 
    206         if (numscalarresults == 0):
    207             f.write("void")
    208         f.write(" HELPER(%s)(CPUHexagonState *env" % tag)
    209 
    210         ## Arguments include the vector destination operands
    211         i = 1
    212         for regtype,regid,toss,numregs in regs:
    213             if (hex_common.is_written(regid)):
    214                 if (hex_common.is_pair(regid)):
    215                     if (hex_common.is_hvx_reg(regtype)):
    216                         gen_helper_arg_ext_pair(f,regtype,regid,i)
    217                     else:
    218                         continue
    219                 elif (hex_common.is_single(regid)):
    220                     if (hex_common.is_hvx_reg(regtype)):
    221                         gen_helper_arg_ext(f,regtype,regid,i)
    222                     else:
    223                         # This is the return value of the function
    224                         continue
    225                 else:
    226                     print("Bad register parse: ",regtype,regid,toss,numregs)
    227                 i += 1
    228 
    229         ## Arguments to the helper function are the source regs and immediates
    230         for regtype,regid,toss,numregs in regs:
    231             if (hex_common.is_read(regid)):
    232                 if (hex_common.is_hvx_reg(regtype) and
    233                     hex_common.is_readwrite(regid)):
    234                     continue
    235                 gen_helper_arg_opn(f,regtype,regid,i,tag)
    236                 i += 1
    237         for immlett,bits,immshift in imms:
    238             gen_helper_arg_imm(f,immlett)
    239             i += 1
    240 
    241         if hex_common.need_slot(tag):
    242             if i > 0: f.write(", ")
    243             f.write("uint32_t slot")
    244             i += 1
    245         if hex_common.need_part1(tag):
    246             if i > 0: f.write(", ")
    247             f.write("uint32_t part1")
    248         f.write(")\n{\n")
    249         if (not hex_common.need_slot(tag)):
    250             f.write("    uint32_t slot __attribute__((unused)) = 4;\n" )
    251         if hex_common.need_ea(tag): gen_decl_ea(f)
    252         ## Declare the return variable
    253         i=0
    254         for regtype,regid,toss,numregs in regs:
    255             if (hex_common.is_writeonly(regid)):
    256                 gen_helper_dest_decl_opn(f,regtype,regid,i)
    257             i += 1
    258 
    259         for regtype,regid,toss,numregs in regs:
    260             if (hex_common.is_read(regid)):
    261                 if (hex_common.is_pair(regid)):
    262                     if (hex_common.is_hvx_reg(regtype)):
    263                         gen_helper_src_var_ext_pair(f,regtype,regid,i)
    264                 elif (hex_common.is_single(regid)):
    265                     if (hex_common.is_hvx_reg(regtype)):
    266                         gen_helper_src_var_ext(f,regtype,regid)
    267                 else:
    268                     print("Bad register parse: ",regtype,regid,toss,numregs)
    269 
    270         if 'A_FPOP' in hex_common.attribdict[tag]:
    271             f.write('    arch_fpop_start(env);\n');
    272 
    273         f.write("    %s\n" % hex_common.semdict[tag])
    274 
    275         if 'A_FPOP' in hex_common.attribdict[tag]:
    276             f.write('    arch_fpop_end(env);\n');
    277 
    278         ## Save/return the return variable
    279         for regtype,regid,toss,numregs in regs:
    280             if (hex_common.is_written(regid)):
    281                 gen_helper_return_opn(f, regtype, regid, i)
    282         f.write("}\n\n")
    283         ## End of the helper definition
    284 
    285 def main():
    286     hex_common.read_semantics_file(sys.argv[1])
    287     hex_common.read_attribs_file(sys.argv[2])
    288     hex_common.read_overrides_file(sys.argv[3])
    289     hex_common.read_overrides_file(sys.argv[4])
    290     hex_common.calculate_attribs()
    291     tagregs = hex_common.get_tagregs()
    292     tagimms = hex_common.get_tagimms()
    293 
    294     with open(sys.argv[5], 'w') as f:
    295         for tag in hex_common.tags:
    296             ## Skip the priv instructions
    297             if ( "A_PRIV" in hex_common.attribdict[tag] ) :
    298                 continue
    299             ## Skip the guest instructions
    300             if ( "A_GUEST" in hex_common.attribdict[tag] ) :
    301                 continue
    302             ## Skip the diag instructions
    303             if ( tag == "Y6_diag" ) :
    304                 continue
    305             if ( tag == "Y6_diag0" ) :
    306                 continue
    307             if ( tag == "Y6_diag1" ) :
    308                 continue
    309             if ( hex_common.skip_qemu_helper(tag) ):
    310                 continue
    311 
    312             gen_helper_function(f, tag, tagregs, tagimms)
    313 
    314 if __name__ == "__main__":
    315     main()