qemu

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

dectree.py (13570B)


      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 io
     21 import re
     22 
     23 import sys
     24 import iset
     25 
     26 encs = {tag : ''.join(reversed(iset.iset[tag]['enc'].replace(' ', '')))
     27     for tag in iset.tags if iset.iset[tag]['enc'] != 'MISSING ENCODING'}
     28 
     29 enc_classes = set([iset.iset[tag]['enc_class'] for tag in encs.keys()])
     30 subinsn_enc_classes = \
     31     set([enc_class for enc_class in enc_classes \
     32         if enc_class.startswith('SUBINSN_')])
     33 ext_enc_classes = \
     34     set([enc_class for enc_class in enc_classes \
     35         if enc_class not in ('NORMAL', '16BIT') and \
     36            not enc_class.startswith('SUBINSN_')])
     37 
     38 try:
     39     subinsn_groupings = iset.subinsn_groupings
     40 except AttributeError:
     41     subinsn_groupings = {}
     42 
     43 for (tag, subinsn_grouping) in subinsn_groupings.items():
     44     encs[tag] = ''.join(reversed(subinsn_grouping['enc'].replace(' ', '')))
     45 
     46 dectree_normal = {'leaves' : set()}
     47 dectree_16bit = {'leaves' : set()}
     48 dectree_subinsn_groupings = {'leaves' : set()}
     49 dectree_subinsns = {name : {'leaves' : set()} for name in subinsn_enc_classes}
     50 dectree_extensions = {name : {'leaves' : set()} for name in ext_enc_classes}
     51 
     52 for tag in encs.keys():
     53     if tag in subinsn_groupings:
     54         dectree_subinsn_groupings['leaves'].add(tag)
     55         continue
     56     enc_class = iset.iset[tag]['enc_class']
     57     if enc_class.startswith('SUBINSN_'):
     58         if len(encs[tag]) != 32:
     59             encs[tag] = encs[tag] + '0' * (32 - len(encs[tag]))
     60         dectree_subinsns[enc_class]['leaves'].add(tag)
     61     elif  enc_class == '16BIT':
     62         if len(encs[tag]) != 16:
     63             raise Exception('Tag "{}" has enc_class "{}" and not an encoding ' +
     64                             'width of 16 bits!'.format(tag, enc_class))
     65         dectree_16bit['leaves'].add(tag)
     66     else:
     67         if len(encs[tag]) != 32:
     68             raise Exception('Tag "{}" has enc_class "{}" and not an encoding ' +
     69                             'width of 32 bits!'.format(tag, enc_class))
     70         if enc_class == 'NORMAL':
     71             dectree_normal['leaves'].add(tag)
     72         else:
     73             dectree_extensions[enc_class]['leaves'].add(tag)
     74 
     75 faketags = set()
     76 for (tag, enc) in iset.enc_ext_spaces.items():
     77     faketags.add(tag)
     78     encs[tag] = ''.join(reversed(enc.replace(' ', '')))
     79     dectree_normal['leaves'].add(tag)
     80 
     81 faketags |= set(subinsn_groupings.keys())
     82 
     83 def every_bit_counts(bitset):
     84     for i in range(1, len(next(iter(bitset)))):
     85         if len(set([bits[:i] + bits[i+1:] for bits in bitset])) == len(bitset):
     86             return False
     87     return True
     88 
     89 def auto_separate(node):
     90     tags = node['leaves']
     91     if len(tags) <= 1:
     92         return
     93     enc_width = len(encs[next(iter(tags))])
     94     opcode_bit_for_all = \
     95         [all([encs[tag][i] in '01' \
     96             for tag in tags]) for i in range(enc_width)]
     97     opcode_bit_is_0_for_all = \
     98         [opcode_bit_for_all[i] and all([encs[tag][i] == '0' \
     99             for tag in tags]) for i in range(enc_width)]
    100     opcode_bit_is_1_for_all = \
    101         [opcode_bit_for_all[i] and all([encs[tag][i] == '1' \
    102             for tag in tags]) for i in range(enc_width)]
    103     differentiator_opcode_bit = \
    104         [opcode_bit_for_all[i] and \
    105          not (opcode_bit_is_0_for_all[i] or \
    106          opcode_bit_is_1_for_all[i]) \
    107             for i in range(enc_width)]
    108     best_width = 0
    109     for width in range(4, 0, -1):
    110         for lsb in range(enc_width - width, -1, -1):
    111             bitset = set([encs[tag][lsb:lsb+width] for tag in tags])
    112             if all(differentiator_opcode_bit[lsb:lsb+width]) and \
    113                 (len(bitset) == len(tags) or every_bit_counts(bitset)):
    114                 best_width = width
    115                 best_lsb = lsb
    116                 caught_all_tags = len(bitset) == len(tags)
    117                 break
    118         if best_width != 0:
    119             break
    120     if best_width == 0:
    121         raise Exception('Could not find a way to differentiate the encodings ' +
    122                          'of the following tags:\n{}'.format('\n'.join(tags)))
    123     if caught_all_tags:
    124         for width in range(1, best_width):
    125             for lsb in range(enc_width - width, -1, -1):
    126                 bitset = set([encs[tag][lsb:lsb+width] for tag in tags])
    127                 if all(differentiator_opcode_bit[lsb:lsb+width]) and \
    128                     len(bitset) == len(tags):
    129                     best_width = width
    130                     best_lsb = lsb
    131                     break
    132             else:
    133                 continue
    134             break
    135     node['separator_lsb'] = best_lsb
    136     node['separator_width'] = best_width
    137     node['children'] = []
    138     for value in range(2 ** best_width):
    139         child = {}
    140         bits = ''.join(reversed('{:0{}b}'.format(value, best_width)))
    141         child['leaves'] = \
    142             set([tag for tag in tags \
    143                 if encs[tag][best_lsb:best_lsb+best_width] == bits])
    144         node['children'].append(child)
    145     for child in node['children']:
    146         auto_separate(child)
    147 
    148 auto_separate(dectree_normal)
    149 auto_separate(dectree_16bit)
    150 if subinsn_groupings:
    151     auto_separate(dectree_subinsn_groupings)
    152 for dectree_subinsn in dectree_subinsns.values():
    153     auto_separate(dectree_subinsn)
    154 for dectree_ext in dectree_extensions.values():
    155     auto_separate(dectree_ext)
    156 
    157 for tag in faketags:
    158     del encs[tag]
    159 
    160 def table_name(parents, node):
    161     path = parents + [node]
    162     root = path[0]
    163     tag = next(iter(node['leaves']))
    164     if tag in subinsn_groupings:
    165         enc_width = len(subinsn_groupings[tag]['enc'].replace(' ', ''))
    166     else:
    167         tag = next(iter(node['leaves'] - faketags))
    168         enc_width = len(encs[tag])
    169     determining_bits = ['_'] * enc_width
    170     for (parent, child) in zip(path[:-1], path[1:]):
    171         lsb = parent['separator_lsb']
    172         width = parent['separator_width']
    173         value = parent['children'].index(child)
    174         determining_bits[lsb:lsb+width] = \
    175             list(reversed('{:0{}b}'.format(value, width)))
    176     if tag in subinsn_groupings:
    177         name = 'DECODE_ROOT_EE'
    178     else:
    179         enc_class = iset.iset[tag]['enc_class']
    180         if enc_class in ext_enc_classes:
    181             name = 'DECODE_EXT_{}'.format(enc_class)
    182         elif enc_class in subinsn_enc_classes:
    183             name = 'DECODE_SUBINSN_{}'.format(enc_class)
    184         else:
    185             name = 'DECODE_ROOT_{}'.format(enc_width)
    186     if node != root:
    187         name += '_' + ''.join(reversed(determining_bits))
    188     return name
    189 
    190 def print_node(f, node, parents):
    191     if len(node['leaves']) <= 1:
    192         return
    193     name = table_name(parents, node)
    194     lsb = node['separator_lsb']
    195     width = node['separator_width']
    196     print('DECODE_NEW_TABLE({},{},DECODE_SEPARATOR_BITS({},{}))'.\
    197         format(name, 2 ** width, lsb, width), file=f)
    198     for child in node['children']:
    199         if len(child['leaves']) == 0:
    200             print('INVALID()', file=f)
    201         elif len(child['leaves']) == 1:
    202             (tag,) = child['leaves']
    203             if tag in subinsn_groupings:
    204                 class_a = subinsn_groupings[tag]['class_a']
    205                 class_b = subinsn_groupings[tag]['class_b']
    206                 enc = subinsn_groupings[tag]['enc'].replace(' ', '')
    207                 if 'RESERVED' in tag:
    208                     print('INVALID()', file=f)
    209                 else:
    210                     print('SUBINSNS({},{},{},"{}")'.\
    211                         format(tag, class_a, class_b, enc), file=f)
    212             elif tag in iset.enc_ext_spaces:
    213                 enc = iset.enc_ext_spaces[tag].replace(' ', '')
    214                 print('EXTSPACE({},"{}")'.format(tag, enc), file=f)
    215             else:
    216                 enc = ''.join(reversed(encs[tag]))
    217                 print('TERMINAL({},"{}")'.format(tag, enc), file=f)
    218         else:
    219             print('TABLE_LINK({})'.format(table_name(parents + [node], child)),
    220                   file=f)
    221     print('DECODE_END_TABLE({},{},DECODE_SEPARATOR_BITS({},{}))'.\
    222         format(name, 2 ** width, lsb, width), file=f)
    223     print(file=f)
    224     parents.append(node)
    225     for child in node['children']:
    226         print_node(f, child, parents)
    227     parents.pop()
    228 
    229 def print_tree(f, tree):
    230     print_node(f, tree, [])
    231 
    232 def print_match_info(f):
    233     for tag in sorted(encs.keys(), key=iset.tags.index):
    234         enc = ''.join(reversed(encs[tag]))
    235         mask = int(re.sub(r'[^1]', r'0', enc.replace('0', '1')), 2)
    236         match = int(re.sub(r'[^01]', r'0', enc), 2)
    237         suffix = ''
    238         print('DECODE{}_MATCH_INFO({},0x{:x}U,0x{:x}U)'.\
    239             format(suffix, tag, mask, match), file=f)
    240 
    241 regre = re.compile(
    242     r'((?<!DUP)[MNORCPQXSGVZA])([stuvwxyzdefg]+)([.]?[LlHh]?)(\d+S?)')
    243 immre = re.compile(r'[#]([rRsSuUm])(\d+)(?:[:](\d+))?')
    244 
    245 def ordered_unique(l):
    246     return sorted(set(l), key=l.index)
    247 
    248 implicit_registers = {
    249     'SP' : 29,
    250     'FP' : 30,
    251     'LR' : 31
    252 }
    253 
    254 num_registers = {
    255     'R' : 32,
    256     'V' : 32
    257 }
    258 
    259 def print_op_info(f):
    260     for tag in sorted(encs.keys(), key=iset.tags.index):
    261         enc = encs[tag]
    262         print(file=f)
    263         print('DECODE_OPINFO({},'.format(tag), file=f)
    264         regs = ordered_unique(regre.findall(iset.iset[tag]['syntax']))
    265         imms = ordered_unique(immre.findall(iset.iset[tag]['syntax']))
    266         regno = 0
    267         for reg in regs:
    268             reg_type = reg[0]
    269             reg_letter = reg[1][0]
    270             reg_num_choices = int(reg[3].rstrip('S'))
    271             reg_mapping = reg[0] + ''.join(['_' for letter in reg[1]]) + reg[3]
    272             reg_enc_fields = re.findall(reg_letter + '+', enc)
    273             if len(reg_enc_fields) == 0:
    274                 raise Exception('Tag "{}" missing register field!'.format(tag))
    275             if len(reg_enc_fields) > 1:
    276                 raise Exception('Tag "{}" has split register field!'.\
    277                     format(tag))
    278             reg_enc_field = reg_enc_fields[0]
    279             if 2 ** len(reg_enc_field) != reg_num_choices:
    280                 raise Exception('Tag "{}" has incorrect register field width!'.\
    281                     format(tag))
    282             print('        DECODE_REG({},{},{})'.\
    283                 format(regno, len(reg_enc_field), enc.index(reg_enc_field)),
    284                        file=f)
    285             if reg_type in num_registers and \
    286                 reg_num_choices != num_registers[reg_type]:
    287                 print('        DECODE_MAPPED_REG({},{})'.\
    288                     format(regno, reg_mapping), file=f)
    289             regno += 1
    290         def implicit_register_key(reg):
    291             return implicit_registers[reg]
    292         for reg in sorted(
    293             set([r for r in (iset.iset[tag]['rregs'].split(',') + \
    294                 iset.iset[tag]['wregs'].split(',')) \
    295                     if r in implicit_registers]), key=implicit_register_key):
    296             print('        DECODE_IMPL_REG({},{})'.\
    297                 format(regno, implicit_registers[reg]), file=f)
    298             regno += 1
    299         if imms and imms[0][0].isupper():
    300             imms = reversed(imms)
    301         for imm in imms:
    302             if imm[0].isupper():
    303                 immno = 1
    304             else:
    305                 immno = 0
    306             imm_type = imm[0]
    307             imm_width = int(imm[1])
    308             imm_shift = imm[2]
    309             if imm_shift:
    310                 imm_shift = int(imm_shift)
    311             else:
    312                 imm_shift = 0
    313             if imm_type.islower():
    314                 imm_letter = 'i'
    315             else:
    316                 imm_letter = 'I'
    317             remainder = imm_width
    318             for m in reversed(list(re.finditer(imm_letter + '+', enc))):
    319                 remainder -= m.end() - m.start()
    320                 print('        DECODE_IMM({},{},{},{})'.\
    321                     format(immno, m.end() - m.start(), m.start(), remainder),
    322                         file=f)
    323             if remainder != 0:
    324                 if imm[2]:
    325                     imm[2] = ':' + imm[2]
    326                 raise Exception('Tag "{}" has an incorrect number of ' + \
    327                     'encoding bits for immediate "{}"'.\
    328                     format(tag, ''.join(imm)))
    329             if imm_type.lower() in 'sr':
    330                 print('        DECODE_IMM_SXT({},{})'.\
    331                     format(immno, imm_width), file=f)
    332             if imm_type.lower() == 'n':
    333                 print('        DECODE_IMM_NEG({},{})'.\
    334                     format(immno, imm_width), file=f)
    335             if imm_shift:
    336                 print('        DECODE_IMM_SHIFT({},{})'.\
    337                     format(immno, imm_shift), file=f)
    338         print(')', file=f)
    339 
    340 if __name__ == '__main__':
    341     with open(sys.argv[1], 'w') as f:
    342         print_tree(f, dectree_normal)
    343         print_tree(f, dectree_16bit)
    344         if subinsn_groupings:
    345             print_tree(f, dectree_subinsn_groupings)
    346         for (name, dectree_subinsn) in sorted(dectree_subinsns.items()):
    347             print_tree(f, dectree_subinsn)
    348         for (name, dectree_ext) in sorted(dectree_extensions.items()):
    349             print_tree(f, dectree_ext)
    350         print_match_info(f)
    351         print_op_info(f)