Browse Source
Now that we are using QEMU decodetree.py, remove the old decoder Signed-off-by: Taylor Simpson <ltaylorsimpson@gmail.com> Reviewed-by: Brian Cain <bcain@quicinc.com> Message-Id: <20240115221443.365287-4-ltaylorsimpson@gmail.com> Signed-off-by: Brian Cain <bcain@quicinc.com>coverity
committed by
Brian Cain
6 changed files with 0 additions and 839 deletions
@ -1,403 +0,0 @@ |
|||
#!/usr/bin/env python3 |
|||
|
|||
## |
|||
## 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 |
|||
## 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 <http://www.gnu.org/licenses/>. |
|||
## |
|||
|
|||
import io |
|||
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" |
|||
} |
|||
|
|||
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(" ", ""))) |
|||
|
|||
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) |
|||
continue |
|||
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": |
|||
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) |
|||
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) |
|||
else: |
|||
dectree_extensions[enc_class]["leaves"].add(tag) |
|||
|
|||
faketags = set() |
|||
for tag, enc in iset.enc_ext_spaces.items(): |
|||
faketags.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): |
|||
return False |
|||
return True |
|||
|
|||
|
|||
def auto_separate(node): |
|||
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) |
|||
] |
|||
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) |
|||
): |
|||
best_width = width |
|||
best_lsb = lsb |
|||
caught_all_tags = len(bitset) == len(tags) |
|||
break |
|||
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)) |
|||
) |
|||
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): |
|||
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): |
|||
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"]: |
|||
auto_separate(child) |
|||
|
|||
|
|||
auto_separate(dectree_normal) |
|||
auto_separate(dectree_16bit) |
|||
if subinsn_groupings: |
|||
auto_separate(dectree_subinsn_groupings) |
|||
for dectree_subinsn in dectree_subinsns.values(): |
|||
auto_separate(dectree_subinsn) |
|||
for dectree_ext in dectree_extensions.values(): |
|||
auto_separate(dectree_ext) |
|||
|
|||
for tag in faketags: |
|||
del encs[tag] |
|||
|
|||
|
|||
def table_name(parents, node): |
|||
path = parents + [node] |
|||
root = path[0] |
|||
tag = next(iter(node["leaves"])) |
|||
if tag in subinsn_groupings: |
|||
enc_width = len(subinsn_groupings[tag]["enc"].replace(" ", "")) |
|||
else: |
|||
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)) |
|||
) |
|||
if tag in subinsn_groupings: |
|||
name = "DECODE_ROOT_EE" |
|||
else: |
|||
enc_class = iset.iset[tag]["enc_class"] |
|||
if enc_class in ext_enc_classes: |
|||
name = "DECODE_EXT_{}".format(enc_class) |
|||
elif enc_class in subinsn_enc_classes: |
|||
name = "DECODE_SUBINSN_{}".format(enc_class) |
|||
else: |
|||
name = "DECODE_ROOT_{}".format(enc_width) |
|||
if node != root: |
|||
name += "_" + "".join(reversed(determining_bits)) |
|||
return name |
|||
|
|||
|
|||
def print_node(f, node, parents): |
|||
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"] |
|||
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) |
|||
else: |
|||
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(" ", "") |
|||
print('EXTSPACE({},"{}")'.format(tag, enc), file=f) |
|||
else: |
|||
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(file=f) |
|||
parents.append(node) |
|||
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, |
|||
) |
|||
|
|||
|
|||
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} |
|||
|
|||
|
|||
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"])) |
|||
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) |
|||
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)) |
|||
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, |
|||
) |
|||
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, |
|||
) |
|||
regno += 1 |
|||
if imms and imms[0][0].isupper(): |
|||
imms = reversed(imms) |
|||
for imm in imms: |
|||
if imm[0].isupper(): |
|||
immno = 1 |
|||
else: |
|||
immno = 0 |
|||
imm_type = imm[0] |
|||
imm_width = int(imm[1]) |
|||
imm_shift = imm[2] |
|||
if imm_shift: |
|||
imm_shift = int(imm_shift) |
|||
else: |
|||
imm_shift = 0 |
|||
if imm_type.islower(): |
|||
imm_letter = "i" |
|||
else: |
|||
imm_letter = "I" |
|||
remainder = imm_width |
|||
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, |
|||
) |
|||
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) |
|||
if imm_shift: |
|||
print( |
|||
" DECODE_IMM_SHIFT({},{})".format(immno, imm_shift), file=f |
|||
) |
|||
print(")", file=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()): |
|||
print_tree(f, dectree_subinsn) |
|||
for name, dectree_ext in sorted(dectree_extensions.items()): |
|||
print_tree(f, dectree_ext) |
|||
print_match_info(f) |
|||
print_op_info(f) |
|||
Loading…
Reference in new issue