summary refs log tree commit diff stats
path: root/target/hexagon/dectree.py
diff options
context:
space:
mode:
Diffstat (limited to 'target/hexagon/dectree.py')
-rwxr-xr-xtarget/hexagon/dectree.py396
1 files changed, 224 insertions, 172 deletions
diff --git a/target/hexagon/dectree.py b/target/hexagon/dectree.py
index 29467ec7d7..3b32948a04 100755
--- a/target/hexagon/dectree.py
+++ b/target/hexagon/dectree.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python3
 
 ##
-##  Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
+##  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved.
 ##
 ##  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
@@ -23,94 +23,109 @@ import re
 import sys
 import iset
 
-encs = {tag : ''.join(reversed(iset.iset[tag]['enc'].replace(' ', '')))
-    for tag in iset.tags if iset.iset[tag]['enc'] != 'MISSING ENCODING'}
+encs = {
+    tag: "".join(reversed(iset.iset[tag]["enc"].replace(" ", "")))
+    for tag in iset.tags
+    if iset.iset[tag]["enc"] != "MISSING ENCODING"
+}
 
-enc_classes = set([iset.iset[tag]['enc_class'] for tag in encs.keys()])
-subinsn_enc_classes = \
-    set([enc_class for enc_class in enc_classes \
-        if enc_class.startswith('SUBINSN_')])
-ext_enc_classes = \
-    set([enc_class for enc_class in enc_classes \
-        if enc_class not in ('NORMAL', '16BIT') and \
-           not enc_class.startswith('SUBINSN_')])
+enc_classes = set([iset.iset[tag]["enc_class"] for tag in encs.keys()])
+subinsn_enc_classes = set(
+    [enc_class for enc_class in enc_classes if enc_class.startswith("SUBINSN_")]
+)
+ext_enc_classes = set(
+    [
+        enc_class
+        for enc_class in enc_classes
+        if enc_class not in ("NORMAL", "16BIT") and not enc_class.startswith("SUBINSN_")
+    ]
+)
 
 try:
     subinsn_groupings = iset.subinsn_groupings
 except AttributeError:
     subinsn_groupings = {}
 
-for (tag, subinsn_grouping) in subinsn_groupings.items():
-    encs[tag] = ''.join(reversed(subinsn_grouping['enc'].replace(' ', '')))
+for tag, subinsn_grouping in subinsn_groupings.items():
+    encs[tag] = "".join(reversed(subinsn_grouping["enc"].replace(" ", "")))
 
-dectree_normal = {'leaves' : set()}
-dectree_16bit = {'leaves' : set()}
-dectree_subinsn_groupings = {'leaves' : set()}
-dectree_subinsns = {name : {'leaves' : set()} for name in subinsn_enc_classes}
-dectree_extensions = {name : {'leaves' : set()} for name in ext_enc_classes}
+dectree_normal = {"leaves": set()}
+dectree_16bit = {"leaves": set()}
+dectree_subinsn_groupings = {"leaves": set()}
+dectree_subinsns = {name: {"leaves": set()} for name in subinsn_enc_classes}
+dectree_extensions = {name: {"leaves": set()} for name in ext_enc_classes}
 
 for tag in encs.keys():
     if tag in subinsn_groupings:
-        dectree_subinsn_groupings['leaves'].add(tag)
+        dectree_subinsn_groupings["leaves"].add(tag)
         continue
-    enc_class = iset.iset[tag]['enc_class']
-    if enc_class.startswith('SUBINSN_'):
+    enc_class = iset.iset[tag]["enc_class"]
+    if enc_class.startswith("SUBINSN_"):
         if len(encs[tag]) != 32:
-            encs[tag] = encs[tag] + '0' * (32 - len(encs[tag]))
-        dectree_subinsns[enc_class]['leaves'].add(tag)
-    elif  enc_class == '16BIT':
+            encs[tag] = encs[tag] + "0" * (32 - len(encs[tag]))
+        dectree_subinsns[enc_class]["leaves"].add(tag)
+    elif enc_class == "16BIT":
         if len(encs[tag]) != 16:
-            raise Exception('Tag "{}" has enc_class "{}" and not an encoding ' +
-                            'width of 16 bits!'.format(tag, enc_class))
-        dectree_16bit['leaves'].add(tag)
+            raise Exception(
+                'Tag "{}" has enc_class "{}" and not an encoding '
+                + "width of 16 bits!".format(tag, enc_class)
+            )
+        dectree_16bit["leaves"].add(tag)
     else:
         if len(encs[tag]) != 32:
-            raise Exception('Tag "{}" has enc_class "{}" and not an encoding ' +
-                            'width of 32 bits!'.format(tag, enc_class))
-        if enc_class == 'NORMAL':
-            dectree_normal['leaves'].add(tag)
+            raise Exception(
+                'Tag "{}" has enc_class "{}" and not an encoding '
+                + "width of 32 bits!".format(tag, enc_class)
+            )
+        if enc_class == "NORMAL":
+            dectree_normal["leaves"].add(tag)
         else:
-            dectree_extensions[enc_class]['leaves'].add(tag)
+            dectree_extensions[enc_class]["leaves"].add(tag)
 
 faketags = set()
-for (tag, enc) in iset.enc_ext_spaces.items():
+for tag, enc in iset.enc_ext_spaces.items():
     faketags.add(tag)
-    encs[tag] = ''.join(reversed(enc.replace(' ', '')))
-    dectree_normal['leaves'].add(tag)
+    encs[tag] = "".join(reversed(enc.replace(" ", "")))
+    dectree_normal["leaves"].add(tag)
 
 faketags |= set(subinsn_groupings.keys())
 
+
 def every_bit_counts(bitset):
     for i in range(1, len(next(iter(bitset)))):
-        if len(set([bits[:i] + bits[i+1:] for bits in bitset])) == len(bitset):
+        if len(set([bits[:i] + bits[i + 1 :] for bits in bitset])) == len(bitset):
             return False
     return True
 
+
 def auto_separate(node):
-    tags = node['leaves']
+    tags = node["leaves"]
     if len(tags) <= 1:
         return
     enc_width = len(encs[next(iter(tags))])
-    opcode_bit_for_all = \
-        [all([encs[tag][i] in '01' \
-            for tag in tags]) for i in range(enc_width)]
-    opcode_bit_is_0_for_all = \
-        [opcode_bit_for_all[i] and all([encs[tag][i] == '0' \
-            for tag in tags]) for i in range(enc_width)]
-    opcode_bit_is_1_for_all = \
-        [opcode_bit_for_all[i] and all([encs[tag][i] == '1' \
-            for tag in tags]) for i in range(enc_width)]
-    differentiator_opcode_bit = \
-        [opcode_bit_for_all[i] and \
-         not (opcode_bit_is_0_for_all[i] or \
-         opcode_bit_is_1_for_all[i]) \
-            for i in range(enc_width)]
+    opcode_bit_for_all = [
+        all([encs[tag][i] in "01" for tag in tags]) for i in range(enc_width)
+    ]
+    opcode_bit_is_0_for_all = [
+        opcode_bit_for_all[i] and all([encs[tag][i] == "0" for tag in tags])
+        for i in range(enc_width)
+    ]
+    opcode_bit_is_1_for_all = [
+        opcode_bit_for_all[i] and all([encs[tag][i] == "1" for tag in tags])
+        for i in range(enc_width)
+    ]
+    differentiator_opcode_bit = [
+        opcode_bit_for_all[i]
+        and not (opcode_bit_is_0_for_all[i] or opcode_bit_is_1_for_all[i])
+        for i in range(enc_width)
+    ]
     best_width = 0
     for width in range(4, 0, -1):
         for lsb in range(enc_width - width, -1, -1):
-            bitset = set([encs[tag][lsb:lsb+width] for tag in tags])
-            if all(differentiator_opcode_bit[lsb:lsb+width]) and \
-                (len(bitset) == len(tags) or every_bit_counts(bitset)):
+            bitset = set([encs[tag][lsb : lsb + width] for tag in tags])
+            if all(differentiator_opcode_bit[lsb : lsb + width]) and (
+                len(bitset) == len(tags) or every_bit_counts(bitset)
+            ):
                 best_width = width
                 best_lsb = lsb
                 caught_all_tags = len(bitset) == len(tags)
@@ -118,33 +133,37 @@ def auto_separate(node):
         if best_width != 0:
             break
     if best_width == 0:
-        raise Exception('Could not find a way to differentiate the encodings ' +
-                         'of the following tags:\n{}'.format('\n'.join(tags)))
+        raise Exception(
+            "Could not find a way to differentiate the encodings "
+            + "of the following tags:\n{}".format("\n".join(tags))
+        )
     if caught_all_tags:
         for width in range(1, best_width):
             for lsb in range(enc_width - width, -1, -1):
-                bitset = set([encs[tag][lsb:lsb+width] for tag in tags])
-                if all(differentiator_opcode_bit[lsb:lsb+width]) and \
-                    len(bitset) == len(tags):
+                bitset = set([encs[tag][lsb : lsb + width] for tag in tags])
+                if all(differentiator_opcode_bit[lsb : lsb + width]) and len(
+                    bitset
+                ) == len(tags):
                     best_width = width
                     best_lsb = lsb
                     break
             else:
                 continue
             break
-    node['separator_lsb'] = best_lsb
-    node['separator_width'] = best_width
-    node['children'] = []
-    for value in range(2 ** best_width):
+    node["separator_lsb"] = best_lsb
+    node["separator_width"] = best_width
+    node["children"] = []
+    for value in range(2**best_width):
         child = {}
-        bits = ''.join(reversed('{:0{}b}'.format(value, best_width)))
-        child['leaves'] = \
-            set([tag for tag in tags \
-                if encs[tag][best_lsb:best_lsb+best_width] == bits])
-        node['children'].append(child)
-    for child in node['children']:
+        bits = "".join(reversed("{:0{}b}".format(value, best_width)))
+        child["leaves"] = set(
+            [tag for tag in tags if encs[tag][best_lsb : best_lsb + best_width] == bits]
+        )
+        node["children"].append(child)
+    for child in node["children"]:
         auto_separate(child)
 
+
 auto_separate(dectree_normal)
 auto_separate(dectree_16bit)
 if subinsn_groupings:
@@ -157,144 +176,173 @@ for dectree_ext in dectree_extensions.values():
 for tag in faketags:
     del encs[tag]
 
+
 def table_name(parents, node):
     path = parents + [node]
     root = path[0]
-    tag = next(iter(node['leaves']))
+    tag = next(iter(node["leaves"]))
     if tag in subinsn_groupings:
-        enc_width = len(subinsn_groupings[tag]['enc'].replace(' ', ''))
+        enc_width = len(subinsn_groupings[tag]["enc"].replace(" ", ""))
     else:
-        tag = next(iter(node['leaves'] - faketags))
+        tag = next(iter(node["leaves"] - faketags))
         enc_width = len(encs[tag])
-    determining_bits = ['_'] * enc_width
-    for (parent, child) in zip(path[:-1], path[1:]):
-        lsb = parent['separator_lsb']
-        width = parent['separator_width']
-        value = parent['children'].index(child)
-        determining_bits[lsb:lsb+width] = \
-            list(reversed('{:0{}b}'.format(value, width)))
+    determining_bits = ["_"] * enc_width
+    for parent, child in zip(path[:-1], path[1:]):
+        lsb = parent["separator_lsb"]
+        width = parent["separator_width"]
+        value = parent["children"].index(child)
+        determining_bits[lsb : lsb + width] = list(
+            reversed("{:0{}b}".format(value, width))
+        )
     if tag in subinsn_groupings:
-        name = 'DECODE_ROOT_EE'
+        name = "DECODE_ROOT_EE"
     else:
-        enc_class = iset.iset[tag]['enc_class']
+        enc_class = iset.iset[tag]["enc_class"]
         if enc_class in ext_enc_classes:
-            name = 'DECODE_EXT_{}'.format(enc_class)
+            name = "DECODE_EXT_{}".format(enc_class)
         elif enc_class in subinsn_enc_classes:
-            name = 'DECODE_SUBINSN_{}'.format(enc_class)
+            name = "DECODE_SUBINSN_{}".format(enc_class)
         else:
-            name = 'DECODE_ROOT_{}'.format(enc_width)
+            name = "DECODE_ROOT_{}".format(enc_width)
     if node != root:
-        name += '_' + ''.join(reversed(determining_bits))
+        name += "_" + "".join(reversed(determining_bits))
     return name
 
+
 def print_node(f, node, parents):
-    if len(node['leaves']) <= 1:
+    if len(node["leaves"]) <= 1:
         return
     name = table_name(parents, node)
-    lsb = node['separator_lsb']
-    width = node['separator_width']
-    print('DECODE_NEW_TABLE({},{},DECODE_SEPARATOR_BITS({},{}))'.\
-        format(name, 2 ** width, lsb, width), file=f)
-    for child in node['children']:
-        if len(child['leaves']) == 0:
-            print('INVALID()', file=f)
-        elif len(child['leaves']) == 1:
-            (tag,) = child['leaves']
+    lsb = node["separator_lsb"]
+    width = node["separator_width"]
+    print(
+        "DECODE_NEW_TABLE({},{},DECODE_SEPARATOR_BITS({},{}))".format(
+            name, 2**width, lsb, width
+        ),
+        file=f,
+    )
+    for child in node["children"]:
+        if len(child["leaves"]) == 0:
+            print("INVALID()", file=f)
+        elif len(child["leaves"]) == 1:
+            (tag,) = child["leaves"]
             if tag in subinsn_groupings:
-                class_a = subinsn_groupings[tag]['class_a']
-                class_b = subinsn_groupings[tag]['class_b']
-                enc = subinsn_groupings[tag]['enc'].replace(' ', '')
-                if 'RESERVED' in tag:
-                    print('INVALID()', file=f)
+                class_a = subinsn_groupings[tag]["class_a"]
+                class_b = subinsn_groupings[tag]["class_b"]
+                enc = subinsn_groupings[tag]["enc"].replace(" ", "")
+                if "RESERVED" in tag:
+                    print("INVALID()", file=f)
                 else:
-                    print('SUBINSNS({},{},{},"{}")'.\
-                        format(tag, class_a, class_b, enc), file=f)
+                    print(
+                        'SUBINSNS({},{},{},"{}")'.format(tag, class_a, class_b, enc),
+                        file=f,
+                    )
             elif tag in iset.enc_ext_spaces:
-                enc = iset.enc_ext_spaces[tag].replace(' ', '')
+                enc = iset.enc_ext_spaces[tag].replace(" ", "")
                 print('EXTSPACE({},"{}")'.format(tag, enc), file=f)
             else:
-                enc = ''.join(reversed(encs[tag]))
+                enc = "".join(reversed(encs[tag]))
                 print('TERMINAL({},"{}")'.format(tag, enc), file=f)
         else:
-            print('TABLE_LINK({})'.format(table_name(parents + [node], child)),
-                  file=f)
-    print('DECODE_END_TABLE({},{},DECODE_SEPARATOR_BITS({},{}))'.\
-        format(name, 2 ** width, lsb, width), file=f)
+            print("TABLE_LINK({})".format(table_name(parents + [node], child)), file=f)
+    print(
+        "DECODE_END_TABLE({},{},DECODE_SEPARATOR_BITS({},{}))".format(
+            name, 2**width, lsb, width
+        ),
+        file=f,
+    )
     print(file=f)
     parents.append(node)
-    for child in node['children']:
+    for child in node["children"]:
         print_node(f, child, parents)
     parents.pop()
 
+
 def print_tree(f, tree):
     print_node(f, tree, [])
 
+
 def print_match_info(f):
     for tag in sorted(encs.keys(), key=iset.tags.index):
-        enc = ''.join(reversed(encs[tag]))
-        mask = int(re.sub(r'[^1]', r'0', enc.replace('0', '1')), 2)
-        match = int(re.sub(r'[^01]', r'0', enc), 2)
-        suffix = ''
-        print('DECODE{}_MATCH_INFO({},0x{:x}U,0x{:x}U)'.\
-            format(suffix, tag, mask, match), file=f)
+        enc = "".join(reversed(encs[tag]))
+        mask = int(re.sub(r"[^1]", r"0", enc.replace("0", "1")), 2)
+        match = int(re.sub(r"[^01]", r"0", enc), 2)
+        suffix = ""
+        print(
+            "DECODE{}_MATCH_INFO({},0x{:x}U,0x{:x}U)".format(suffix, tag, mask, match),
+            file=f,
+        )
+
+
+regre = re.compile(r"((?<!DUP)[MNORCPQXSGVZA])([stuvwxyzdefg]+)([.]?[LlHh]?)(\d+S?)")
+immre = re.compile(r"[#]([rRsSuUm])(\d+)(?:[:](\d+))?")
 
-regre = re.compile(
-    r'((?<!DUP)[MNORCPQXSGVZA])([stuvwxyzdefg]+)([.]?[LlHh]?)(\d+S?)')
-immre = re.compile(r'[#]([rRsSuUm])(\d+)(?:[:](\d+))?')
 
 def ordered_unique(l):
     return sorted(set(l), key=l.index)
 
-implicit_registers = {
-    'SP' : 29,
-    'FP' : 30,
-    'LR' : 31
-}
 
-num_registers = {
-    'R' : 32,
-    'V' : 32
-}
+implicit_registers = {"SP": 29, "FP": 30, "LR": 31}
+
+num_registers = {"R": 32, "V": 32}
+
 
 def print_op_info(f):
     for tag in sorted(encs.keys(), key=iset.tags.index):
         enc = encs[tag]
         print(file=f)
-        print('DECODE_OPINFO({},'.format(tag), file=f)
-        regs = ordered_unique(regre.findall(iset.iset[tag]['syntax']))
-        imms = ordered_unique(immre.findall(iset.iset[tag]['syntax']))
+        print("DECODE_OPINFO({},".format(tag), file=f)
+        regs = ordered_unique(regre.findall(iset.iset[tag]["syntax"]))
+        imms = ordered_unique(immre.findall(iset.iset[tag]["syntax"]))
         regno = 0
         for reg in regs:
             reg_type = reg[0]
             reg_letter = reg[1][0]
-            reg_num_choices = int(reg[3].rstrip('S'))
-            reg_mapping = reg[0] + ''.join(['_' for letter in reg[1]]) + reg[3]
-            reg_enc_fields = re.findall(reg_letter + '+', enc)
+            reg_num_choices = int(reg[3].rstrip("S"))
+            reg_mapping = reg[0] + "".join(["_" for letter in reg[1]]) + reg[3]
+            reg_enc_fields = re.findall(reg_letter + "+", enc)
             if len(reg_enc_fields) == 0:
                 raise Exception('Tag "{}" missing register field!'.format(tag))
             if len(reg_enc_fields) > 1:
-                raise Exception('Tag "{}" has split register field!'.\
-                    format(tag))
+                raise Exception('Tag "{}" has split register field!'.format(tag))
             reg_enc_field = reg_enc_fields[0]
             if 2 ** len(reg_enc_field) != reg_num_choices:
-                raise Exception('Tag "{}" has incorrect register field width!'.\
-                    format(tag))
-            print('        DECODE_REG({},{},{})'.\
-                format(regno, len(reg_enc_field), enc.index(reg_enc_field)),
-                       file=f)
-            if reg_type in num_registers and \
-                reg_num_choices != num_registers[reg_type]:
-                print('        DECODE_MAPPED_REG({},{})'.\
-                    format(regno, reg_mapping), file=f)
+                raise Exception(
+                    'Tag "{}" has incorrect register field width!'.format(tag)
+                )
+            print(
+                "        DECODE_REG({},{},{})".format(
+                    regno, len(reg_enc_field), enc.index(reg_enc_field)
+                ),
+                file=f,
+            )
+            if reg_type in num_registers and reg_num_choices != num_registers[reg_type]:
+                print(
+                    "        DECODE_MAPPED_REG({},{})".format(regno, reg_mapping),
+                    file=f,
+                )
             regno += 1
+
         def implicit_register_key(reg):
             return implicit_registers[reg]
+
         for reg in sorted(
-            set([r for r in (iset.iset[tag]['rregs'].split(',') + \
-                iset.iset[tag]['wregs'].split(',')) \
-                    if r in implicit_registers]), key=implicit_register_key):
-            print('        DECODE_IMPL_REG({},{})'.\
-                format(regno, implicit_registers[reg]), file=f)
+            set(
+                [
+                    r
+                    for r in (
+                        iset.iset[tag]["rregs"].split(",")
+                        + iset.iset[tag]["wregs"].split(",")
+                    )
+                    if r in implicit_registers
+                ]
+            ),
+            key=implicit_register_key,
+        ):
+            print(
+                "        DECODE_IMPL_REG({},{})".format(regno, implicit_registers[reg]),
+                file=f,
+            )
             regno += 1
         if imms and imms[0][0].isupper():
             imms = reversed(imms)
@@ -311,41 +359,45 @@ def print_op_info(f):
             else:
                 imm_shift = 0
             if imm_type.islower():
-                imm_letter = 'i'
+                imm_letter = "i"
             else:
-                imm_letter = 'I'
+                imm_letter = "I"
             remainder = imm_width
-            for m in reversed(list(re.finditer(imm_letter + '+', enc))):
+            for m in reversed(list(re.finditer(imm_letter + "+", enc))):
                 remainder -= m.end() - m.start()
-                print('        DECODE_IMM({},{},{},{})'.\
-                    format(immno, m.end() - m.start(), m.start(), remainder),
-                        file=f)
+                print(
+                    "        DECODE_IMM({},{},{},{})".format(
+                        immno, m.end() - m.start(), m.start(), remainder
+                    ),
+                    file=f,
+                )
             if remainder != 0:
                 if imm[2]:
-                    imm[2] = ':' + imm[2]
-                raise Exception('Tag "{}" has an incorrect number of ' + \
-                    'encoding bits for immediate "{}"'.\
-                    format(tag, ''.join(imm)))
-            if imm_type.lower() in 'sr':
-                print('        DECODE_IMM_SXT({},{})'.\
-                    format(immno, imm_width), file=f)
-            if imm_type.lower() == 'n':
-                print('        DECODE_IMM_NEG({},{})'.\
-                    format(immno, imm_width), file=f)
+                    imm[2] = ":" + imm[2]
+                raise Exception(
+                    'Tag "{}" has an incorrect number of '
+                    + 'encoding bits for immediate "{}"'.format(tag, "".join(imm))
+                )
+            if imm_type.lower() in "sr":
+                print("        DECODE_IMM_SXT({},{})".format(immno, imm_width), file=f)
+            if imm_type.lower() == "n":
+                print("        DECODE_IMM_NEG({},{})".format(immno, imm_width), file=f)
             if imm_shift:
-                print('        DECODE_IMM_SHIFT({},{})'.\
-                    format(immno, imm_shift), file=f)
-        print(')', file=f)
+                print(
+                    "        DECODE_IMM_SHIFT({},{})".format(immno, imm_shift), file=f
+                )
+        print(")", file=f)
+
 
-if __name__ == '__main__':
-    with open(sys.argv[1], 'w') as f:
+if __name__ == "__main__":
+    with open(sys.argv[1], "w") as f:
         print_tree(f, dectree_normal)
         print_tree(f, dectree_16bit)
         if subinsn_groupings:
             print_tree(f, dectree_subinsn_groupings)
-        for (name, dectree_subinsn) in sorted(dectree_subinsns.items()):
+        for name, dectree_subinsn in sorted(dectree_subinsns.items()):
             print_tree(f, dectree_subinsn)
-        for (name, dectree_ext) in sorted(dectree_extensions.items()):
+        for name, dectree_ext in sorted(dectree_extensions.items()):
             print_tree(f, dectree_ext)
         print_match_info(f)
         print_op_info(f)