1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
import sys, re, json
from xml.etree import ElementTree
def insert_n(s, nb):
sout = ""
def sub(g):
if g.group(2):
a, b = int(g.group(1)), int(g.group(2)[1:])
return nb[-a - 1:-b or None]
else:
a = int(g.group(1))
return nb[-a - 1]
s = re.sub(r'n\[(\d+)(:\d+)?\]', sub, s)
s = "".join(s.split(":"))
return int(s.replace("0b", ""), 2)
def parse_one(regs, xml):
t = ElementTree.parse(xml)
for reg in t.findall('registers/register'):
data = {}
name = reg.find('reg_short_name').text
fullname = reg.find('reg_long_name').text
if name.startswith("S3_") or name.startswith("SYS S1_"):
continue
array = reg.find('reg_array')
start = end = 0
if array:
start = int(array.find("reg_array_start").text)
end = int(array.find("reg_array_end").text)
encs = {}
accessors = {}
for am in reg.findall('access_mechanisms/access_mechanism'):
accessor = am.attrib["accessor"]
if accessor.startswith("MSRimmediate"):
continue
ins = am.find("encoding/access_instruction").text.split(" ")[0]
regname = accessor.split(" ", 1)[1]
enc = {}
for e in am.findall("encoding/enc"):
enc[e.attrib["n"]] = e.attrib["v"]
enc = enc["op0"], enc["op1"], enc["CRn"], enc["CRm"], enc["op2"]
if regname in encs:
assert encs[regname] == enc
encs[regname] = enc
accessors.setdefault(regname, set()).add(ins)
if not encs:
continue
fieldsets = []
width = None
for fields_elem in reg.findall('reg_fieldsets/fields'):
fieldset = {}
if (instance_elem := fields_elem.find('fields_instance')) is not None:
fieldset["instance"] = instance_elem.text
fields = []
set_width = int(fields_elem.attrib["length"])
if width is None:
width = set_width
else:
assert width == set_width
single_field = False
for f in fields_elem.findall('field'):
if f.attrib.get("rwtype", None) in ("RES0", "RES1", "RAZ", "RAZ/WI", "RAO/WI", "UNKNOWN"):
continue
msb, lsb = int(f.find('field_msb').text), int(f.find('field_lsb').text)
assert not single_field
if msb == width - 1 and lsb == 0:
continue
if (name_elem := f.find('field_name')) is not None:
name = name_elem.text
else:
assert not fields
continue
field = {
"name": name,
"msb": msb,
"lsb": lsb,
}
fields.append(field)
fields.sort(key=lambda x: x["lsb"], reverse=True)
fieldset["fields"] = fields
fieldsets.append(fieldset)
for idx, n in enumerate(range(start, end + 1)):
nb = "{0:064b}".format(n)[::-1]
for name, enc in sorted(encs.items()):
enc = tuple(insert_n(i, nb) for i in enc)
data = {
"index": idx,
"name": name.replace("<n>", "%d" % n),
"fullname": fullname,
"enc": enc,
"accessors": sorted(list(accessors[name])),
"fieldsets": fieldsets,
}
if width is not None:
data["width"] = width
yield data
if __name__ == "__main__":
regs = []
for i in sys.argv[1:]:
regs.extend(parse_one(regs, i))
json.dump(regs, sys.stdout)
|