1*61046927SAndroid Build Coastguard Worker# 2*61046927SAndroid Build Coastguard Worker# Copyright © 2020 Google, Inc. 3*61046927SAndroid Build Coastguard Worker# 4*61046927SAndroid Build Coastguard Worker# Permission is hereby granted, free of charge, to any person obtaining a 5*61046927SAndroid Build Coastguard Worker# copy of this software and associated documentation files (the "Software"), 6*61046927SAndroid Build Coastguard Worker# to deal in the Software without restriction, including without limitation 7*61046927SAndroid Build Coastguard Worker# the rights to use, copy, modify, merge, publish, distribute, sublicense, 8*61046927SAndroid Build Coastguard Worker# and/or sell copies of the Software, and to permit persons to whom the 9*61046927SAndroid Build Coastguard Worker# Software is furnished to do so, subject to the following conditions: 10*61046927SAndroid Build Coastguard Worker# 11*61046927SAndroid Build Coastguard Worker# The above copyright notice and this permission notice (including the next 12*61046927SAndroid Build Coastguard Worker# paragraph) shall be included in all copies or substantial portions of the 13*61046927SAndroid Build Coastguard Worker# Software. 14*61046927SAndroid Build Coastguard Worker# 15*61046927SAndroid Build Coastguard Worker# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16*61046927SAndroid Build Coastguard Worker# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17*61046927SAndroid Build Coastguard Worker# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18*61046927SAndroid Build Coastguard Worker# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19*61046927SAndroid Build Coastguard Worker# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20*61046927SAndroid Build Coastguard Worker# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21*61046927SAndroid Build Coastguard Worker# IN THE SOFTWARE. 22*61046927SAndroid Build Coastguard Worker 23*61046927SAndroid Build Coastguard Workerfrom xml.etree import ElementTree 24*61046927SAndroid Build Coastguard Workerimport os 25*61046927SAndroid Build Coastguard Workerimport re 26*61046927SAndroid Build Coastguard Worker 27*61046927SAndroid Build Coastguard Workerdef dbg(str): 28*61046927SAndroid Build Coastguard Worker if False: 29*61046927SAndroid Build Coastguard Worker print(str) 30*61046927SAndroid Build Coastguard Worker 31*61046927SAndroid Build Coastguard Workerclass BitSetPattern(object): 32*61046927SAndroid Build Coastguard Worker """Class that encapsulated the pattern matching, ie. 33*61046927SAndroid Build Coastguard Worker the match/dontcare/mask bitmasks. The following 34*61046927SAndroid Build Coastguard Worker rules should hold 35*61046927SAndroid Build Coastguard Worker 36*61046927SAndroid Build Coastguard Worker (match ^ dontcare) == 0 37*61046927SAndroid Build Coastguard Worker (match || dontcare) == mask 38*61046927SAndroid Build Coastguard Worker 39*61046927SAndroid Build Coastguard Worker For a leaf node, the mask should be (1 << size) - 1 40*61046927SAndroid Build Coastguard Worker (ie. all bits set) 41*61046927SAndroid Build Coastguard Worker """ 42*61046927SAndroid Build Coastguard Worker def __init__(self, bitset): 43*61046927SAndroid Build Coastguard Worker self.match = bitset.match 44*61046927SAndroid Build Coastguard Worker self.dontcare = bitset.dontcare 45*61046927SAndroid Build Coastguard Worker self.mask = bitset.mask 46*61046927SAndroid Build Coastguard Worker self.field_mask = bitset.field_mask 47*61046927SAndroid Build Coastguard Worker 48*61046927SAndroid Build Coastguard Worker def merge(self, pattern): 49*61046927SAndroid Build Coastguard Worker p = BitSetPattern(pattern) 50*61046927SAndroid Build Coastguard Worker p.match = p.match | self.match 51*61046927SAndroid Build Coastguard Worker p.dontcare = p.dontcare | self.dontcare 52*61046927SAndroid Build Coastguard Worker p.mask = p.mask | self.mask 53*61046927SAndroid Build Coastguard Worker p.field_mask = p.field_mask | self.field_mask 54*61046927SAndroid Build Coastguard Worker return p 55*61046927SAndroid Build Coastguard Worker 56*61046927SAndroid Build Coastguard Worker def defined_bits(self): 57*61046927SAndroid Build Coastguard Worker return self.match | self.dontcare | self.mask | self.field_mask 58*61046927SAndroid Build Coastguard Worker 59*61046927SAndroid Build Coastguard Workerdef get_bitrange(field): 60*61046927SAndroid Build Coastguard Worker if 'pos' in field.attrib: 61*61046927SAndroid Build Coastguard Worker assert('low' not in field.attrib) 62*61046927SAndroid Build Coastguard Worker assert('high' not in field.attrib) 63*61046927SAndroid Build Coastguard Worker low = int(field.attrib['pos']) 64*61046927SAndroid Build Coastguard Worker high = low 65*61046927SAndroid Build Coastguard Worker else: 66*61046927SAndroid Build Coastguard Worker low = int(field.attrib['low']) 67*61046927SAndroid Build Coastguard Worker high = int(field.attrib['high']) 68*61046927SAndroid Build Coastguard Worker assert low <= high 69*61046927SAndroid Build Coastguard Worker return low, high 70*61046927SAndroid Build Coastguard Worker 71*61046927SAndroid Build Coastguard Workerdef extract_pattern(xml, name, is_defined_bits=None): 72*61046927SAndroid Build Coastguard Worker low, high = get_bitrange(xml) 73*61046927SAndroid Build Coastguard Worker mask = ((1 << (1 + high - low)) - 1) << low 74*61046927SAndroid Build Coastguard Worker 75*61046927SAndroid Build Coastguard Worker patstr = xml.text.strip() 76*61046927SAndroid Build Coastguard Worker 77*61046927SAndroid Build Coastguard Worker assert (len(patstr) == (1 + high - low)), "Invalid {} length in {}: {}..{}".format(xml.tag, name, low, high) 78*61046927SAndroid Build Coastguard Worker if is_defined_bits is not None: 79*61046927SAndroid Build Coastguard Worker assert not is_defined_bits(mask), "Redefined bits in {} {}: {}..{}".format(xml.tag, name, low, high) 80*61046927SAndroid Build Coastguard Worker 81*61046927SAndroid Build Coastguard Worker match = 0 82*61046927SAndroid Build Coastguard Worker dontcare = 0 83*61046927SAndroid Build Coastguard Worker 84*61046927SAndroid Build Coastguard Worker for n in range(0, len(patstr)): 85*61046927SAndroid Build Coastguard Worker match = match << 1 86*61046927SAndroid Build Coastguard Worker dontcare = dontcare << 1 87*61046927SAndroid Build Coastguard Worker if patstr[n] == '1': 88*61046927SAndroid Build Coastguard Worker match |= 1 89*61046927SAndroid Build Coastguard Worker elif patstr[n] == 'x': 90*61046927SAndroid Build Coastguard Worker dontcare |= 1 91*61046927SAndroid Build Coastguard Worker elif patstr[n] != '0': 92*61046927SAndroid Build Coastguard Worker assert 0, "Invalid {} character in {}: {}".format(xml.tag, name, patstr[n]) 93*61046927SAndroid Build Coastguard Worker 94*61046927SAndroid Build Coastguard Worker dbg("{}: {}.{} => {:016x} / {:016x} / {:016x}".format(xml.tag, name, patstr, match << low, dontcare << low, mask)) 95*61046927SAndroid Build Coastguard Worker 96*61046927SAndroid Build Coastguard Worker return match << low, dontcare << low, mask 97*61046927SAndroid Build Coastguard Worker 98*61046927SAndroid Build Coastguard Workerdef get_c_name(name): 99*61046927SAndroid Build Coastguard Worker return name.lower().replace('#', '__').replace('-', '_').replace('.', '_') 100*61046927SAndroid Build Coastguard Worker 101*61046927SAndroid Build Coastguard Workerclass BitSetField(object): 102*61046927SAndroid Build Coastguard Worker """Class that encapsulates a field defined in a bitset 103*61046927SAndroid Build Coastguard Worker """ 104*61046927SAndroid Build Coastguard Worker def __init__(self, isa, xml): 105*61046927SAndroid Build Coastguard Worker self.isa = isa 106*61046927SAndroid Build Coastguard Worker self.low, self.high = get_bitrange(xml) 107*61046927SAndroid Build Coastguard Worker self.name = xml.attrib['name'] 108*61046927SAndroid Build Coastguard Worker self.type = xml.attrib['type'] 109*61046927SAndroid Build Coastguard Worker self.params = [] 110*61046927SAndroid Build Coastguard Worker for param in xml.findall('param'): 111*61046927SAndroid Build Coastguard Worker aas = name = param.attrib['name'] 112*61046927SAndroid Build Coastguard Worker if 'as' in param.attrib: 113*61046927SAndroid Build Coastguard Worker aas = param.attrib['as'] 114*61046927SAndroid Build Coastguard Worker self.params.append([name, aas]) 115*61046927SAndroid Build Coastguard Worker self.expr = None 116*61046927SAndroid Build Coastguard Worker self.display = None 117*61046927SAndroid Build Coastguard Worker self.call = 'call' in xml.attrib and xml.attrib['call'] == 'true' 118*61046927SAndroid Build Coastguard Worker if 'display' in xml.attrib: 119*61046927SAndroid Build Coastguard Worker self.display = xml.attrib['display'].strip() 120*61046927SAndroid Build Coastguard Worker 121*61046927SAndroid Build Coastguard Worker def get_c_name(self): 122*61046927SAndroid Build Coastguard Worker return get_c_name(self.name) 123*61046927SAndroid Build Coastguard Worker 124*61046927SAndroid Build Coastguard Worker def get_c_typename(self): 125*61046927SAndroid Build Coastguard Worker if self.type in self.isa.enums: 126*61046927SAndroid Build Coastguard Worker return 'TYPE_ENUM' 127*61046927SAndroid Build Coastguard Worker if self.type in self.isa.bitsets: 128*61046927SAndroid Build Coastguard Worker return 'TYPE_BITSET' 129*61046927SAndroid Build Coastguard Worker return 'TYPE_' + self.type.upper() 130*61046927SAndroid Build Coastguard Worker 131*61046927SAndroid Build Coastguard Worker def mask(self): 132*61046927SAndroid Build Coastguard Worker return ((1 << self.get_size()) - 1) << self.low 133*61046927SAndroid Build Coastguard Worker 134*61046927SAndroid Build Coastguard Worker def get_size(self): 135*61046927SAndroid Build Coastguard Worker return 1 + self.high - self.low 136*61046927SAndroid Build Coastguard Worker 137*61046927SAndroid Build Coastguard Workerclass BitSetAssertField(BitSetField): 138*61046927SAndroid Build Coastguard Worker """Similar to BitSetField, but for <assert/>s, which can be 139*61046927SAndroid Build Coastguard Worker used to specify that a certain bitpattern is expected in 140*61046927SAndroid Build Coastguard Worker place of (for example) unused bitfields 141*61046927SAndroid Build Coastguard Worker """ 142*61046927SAndroid Build Coastguard Worker def __init__(self, case, xml): 143*61046927SAndroid Build Coastguard Worker self.isa = case.bitset.isa 144*61046927SAndroid Build Coastguard Worker self.low, self.high = get_bitrange(xml) 145*61046927SAndroid Build Coastguard Worker self.name = case.bitset.name + '#assert' + str(len(case.fields)) 146*61046927SAndroid Build Coastguard Worker self.type = 'uint' 147*61046927SAndroid Build Coastguard Worker self.expr = None 148*61046927SAndroid Build Coastguard Worker self.display = None 149*61046927SAndroid Build Coastguard Worker 150*61046927SAndroid Build Coastguard Worker match, dontcare, mask = extract_pattern(xml, case.bitset.name) 151*61046927SAndroid Build Coastguard Worker self.val = match >> self.low 152*61046927SAndroid Build Coastguard Worker 153*61046927SAndroid Build Coastguard Worker assert dontcare == 0, "'x' (dontcare) is not valid in an assert" 154*61046927SAndroid Build Coastguard Worker 155*61046927SAndroid Build Coastguard Worker def get_c_typename(self): 156*61046927SAndroid Build Coastguard Worker return 'TYPE_ASSERT' 157*61046927SAndroid Build Coastguard Worker 158*61046927SAndroid Build Coastguard Workerclass BitSetDerivedField(BitSetField): 159*61046927SAndroid Build Coastguard Worker """Similar to BitSetField, but for derived fields 160*61046927SAndroid Build Coastguard Worker """ 161*61046927SAndroid Build Coastguard Worker def __init__(self, isa, xml): 162*61046927SAndroid Build Coastguard Worker self.isa = isa 163*61046927SAndroid Build Coastguard Worker self.low = 0 164*61046927SAndroid Build Coastguard Worker self.high = 0 165*61046927SAndroid Build Coastguard Worker # NOTE: a width should be provided for 'int' derived fields, ie. 166*61046927SAndroid Build Coastguard Worker # where sign extension is needed. We just repurpose the 'high' 167*61046927SAndroid Build Coastguard Worker # field for that to make '1 + high - low' work out 168*61046927SAndroid Build Coastguard Worker if 'width' in xml.attrib: 169*61046927SAndroid Build Coastguard Worker self.high = int(xml.attrib['width']) - 1 170*61046927SAndroid Build Coastguard Worker self.name = xml.attrib['name'] 171*61046927SAndroid Build Coastguard Worker self.type = xml.attrib['type'] 172*61046927SAndroid Build Coastguard Worker if 'expr' in xml.attrib: 173*61046927SAndroid Build Coastguard Worker self.expr = xml.attrib['expr'] 174*61046927SAndroid Build Coastguard Worker else: 175*61046927SAndroid Build Coastguard Worker e = isa.parse_one_expression(xml, self.name) 176*61046927SAndroid Build Coastguard Worker self.expr = e.name 177*61046927SAndroid Build Coastguard Worker self.display = None 178*61046927SAndroid Build Coastguard Worker if 'display' in xml.attrib: 179*61046927SAndroid Build Coastguard Worker self.display = xml.attrib['display'].strip() 180*61046927SAndroid Build Coastguard Worker self.call = 'call' in xml.attrib and xml.attrib['call'] == 'true' 181*61046927SAndroid Build Coastguard Worker 182*61046927SAndroid Build Coastguard Workerclass BitSetCase(object): 183*61046927SAndroid Build Coastguard Worker """Class that encapsulates a single bitset case 184*61046927SAndroid Build Coastguard Worker """ 185*61046927SAndroid Build Coastguard Worker def __init__(self, bitset, xml, update_field_mask, expr=None): 186*61046927SAndroid Build Coastguard Worker self.bitset = bitset 187*61046927SAndroid Build Coastguard Worker if expr is not None: 188*61046927SAndroid Build Coastguard Worker self.name = bitset.name + '#case' + str(len(bitset.cases)) 189*61046927SAndroid Build Coastguard Worker else: 190*61046927SAndroid Build Coastguard Worker self.name = bitset.name + "#default" 191*61046927SAndroid Build Coastguard Worker self.expr = expr 192*61046927SAndroid Build Coastguard Worker self.fields = {} 193*61046927SAndroid Build Coastguard Worker 194*61046927SAndroid Build Coastguard Worker for derived in xml.findall('derived'): 195*61046927SAndroid Build Coastguard Worker f = BitSetDerivedField(bitset.isa, derived) 196*61046927SAndroid Build Coastguard Worker self.fields[f.name] = f 197*61046927SAndroid Build Coastguard Worker 198*61046927SAndroid Build Coastguard Worker for assrt in xml.findall('assert'): 199*61046927SAndroid Build Coastguard Worker f = BitSetAssertField(self, assrt) 200*61046927SAndroid Build Coastguard Worker update_field_mask(self, f) 201*61046927SAndroid Build Coastguard Worker self.fields[f.name] = f 202*61046927SAndroid Build Coastguard Worker 203*61046927SAndroid Build Coastguard Worker for field in xml.findall('field'): 204*61046927SAndroid Build Coastguard Worker dbg("{}.{}".format(self.name, field.attrib['name'])) 205*61046927SAndroid Build Coastguard Worker f = BitSetField(bitset.isa, field) 206*61046927SAndroid Build Coastguard Worker update_field_mask(self, f) 207*61046927SAndroid Build Coastguard Worker self.fields[f.name] = f 208*61046927SAndroid Build Coastguard Worker 209*61046927SAndroid Build Coastguard Worker self.display = None 210*61046927SAndroid Build Coastguard Worker for d in xml.findall('display'): 211*61046927SAndroid Build Coastguard Worker # Allow <display/> for empty display string: 212*61046927SAndroid Build Coastguard Worker if d.text is not None: 213*61046927SAndroid Build Coastguard Worker self.display = d.text.strip() 214*61046927SAndroid Build Coastguard Worker else: 215*61046927SAndroid Build Coastguard Worker self.display = '' 216*61046927SAndroid Build Coastguard Worker dbg("found display: '{}'".format(self.display)) 217*61046927SAndroid Build Coastguard Worker 218*61046927SAndroid Build Coastguard Worker def get_c_name(self): 219*61046927SAndroid Build Coastguard Worker return get_c_name(self.name) 220*61046927SAndroid Build Coastguard Worker 221*61046927SAndroid Build Coastguard Workerclass BitSetEncode(object): 222*61046927SAndroid Build Coastguard Worker """Additional data that may be associated with a root bitset node 223*61046927SAndroid Build Coastguard Worker to provide additional information needed to generate helpers 224*61046927SAndroid Build Coastguard Worker to encode the bitset, such as source data type and "opcode" 225*61046927SAndroid Build Coastguard Worker case prefix (ie. how to choose/enumerate which leaf node bitset 226*61046927SAndroid Build Coastguard Worker to use to encode the source data 227*61046927SAndroid Build Coastguard Worker """ 228*61046927SAndroid Build Coastguard Worker def __init__(self, xml): 229*61046927SAndroid Build Coastguard Worker self.type = None 230*61046927SAndroid Build Coastguard Worker if 'type' in xml.attrib: 231*61046927SAndroid Build Coastguard Worker self.type = xml.attrib['type'] 232*61046927SAndroid Build Coastguard Worker self.case_prefix = None 233*61046927SAndroid Build Coastguard Worker if 'case-prefix' in xml.attrib: 234*61046927SAndroid Build Coastguard Worker self.case_prefix = xml.attrib['case-prefix'] 235*61046927SAndroid Build Coastguard Worker # The encode element may also contain mappings from encode src 236*61046927SAndroid Build Coastguard Worker # to individual field names: 237*61046927SAndroid Build Coastguard Worker self.maps = {} 238*61046927SAndroid Build Coastguard Worker self.forced = {} 239*61046927SAndroid Build Coastguard Worker for map in xml.findall('map'): 240*61046927SAndroid Build Coastguard Worker name = map.attrib['name'] 241*61046927SAndroid Build Coastguard Worker self.maps[name] = map.text.strip() 242*61046927SAndroid Build Coastguard Worker if 'force' in map.attrib and map.attrib['force'] == 'true': 243*61046927SAndroid Build Coastguard Worker self.forced[name] = 'true' 244*61046927SAndroid Build Coastguard Worker 245*61046927SAndroid Build Coastguard Workerclass BitSetDecode(object): 246*61046927SAndroid Build Coastguard Worker """Additional data that may be associated with a root bitset node 247*61046927SAndroid Build Coastguard Worker to provide additional information needed to generate helpers 248*61046927SAndroid Build Coastguard Worker to decode the bitset. 249*61046927SAndroid Build Coastguard Worker """ 250*61046927SAndroid Build Coastguard Worker def __init__(self, xml): 251*61046927SAndroid Build Coastguard Worker pass 252*61046927SAndroid Build Coastguard Worker 253*61046927SAndroid Build Coastguard Workerclass BitSet(object): 254*61046927SAndroid Build Coastguard Worker """Class that encapsulates a single bitset rule 255*61046927SAndroid Build Coastguard Worker """ 256*61046927SAndroid Build Coastguard Worker def __init__(self, isa, xml): 257*61046927SAndroid Build Coastguard Worker self.isa = isa 258*61046927SAndroid Build Coastguard Worker self.xml = xml 259*61046927SAndroid Build Coastguard Worker self.name = xml.attrib['name'] 260*61046927SAndroid Build Coastguard Worker self.display_name = xml.attrib['displayname'] if 'displayname' in xml.attrib else self.name 261*61046927SAndroid Build Coastguard Worker self.meta = {} 262*61046927SAndroid Build Coastguard Worker 263*61046927SAndroid Build Coastguard Worker # Used for generated encoder, to de-duplicate encoding for 264*61046927SAndroid Build Coastguard Worker # similar instructions: 265*61046927SAndroid Build Coastguard Worker self.snippets = {} 266*61046927SAndroid Build Coastguard Worker 267*61046927SAndroid Build Coastguard Worker if 'size' in xml.attrib: 268*61046927SAndroid Build Coastguard Worker assert('extends' not in xml.attrib) 269*61046927SAndroid Build Coastguard Worker self.size = int(xml.attrib['size']) 270*61046927SAndroid Build Coastguard Worker self.extends = None 271*61046927SAndroid Build Coastguard Worker else: 272*61046927SAndroid Build Coastguard Worker self.size = None 273*61046927SAndroid Build Coastguard Worker self.extends = xml.attrib['extends'] 274*61046927SAndroid Build Coastguard Worker 275*61046927SAndroid Build Coastguard Worker self.encode = None 276*61046927SAndroid Build Coastguard Worker if xml.find('encode') is not None: 277*61046927SAndroid Build Coastguard Worker self.encode = BitSetEncode(xml.find('encode')) 278*61046927SAndroid Build Coastguard Worker self.decode = None 279*61046927SAndroid Build Coastguard Worker if xml.find('decode') is not None: 280*61046927SAndroid Build Coastguard Worker self.decode = BitSetDecode(xml.find('encode')) 281*61046927SAndroid Build Coastguard Worker 282*61046927SAndroid Build Coastguard Worker self.gen_min = 0 283*61046927SAndroid Build Coastguard Worker self.gen_max = (1 << 32) - 1 284*61046927SAndroid Build Coastguard Worker 285*61046927SAndroid Build Coastguard Worker for gen in xml.findall('gen'): 286*61046927SAndroid Build Coastguard Worker if 'min' in gen.attrib: 287*61046927SAndroid Build Coastguard Worker self.gen_min = int(gen.attrib['min']) 288*61046927SAndroid Build Coastguard Worker if 'max' in gen.attrib: 289*61046927SAndroid Build Coastguard Worker self.gen_max = int(gen.attrib['max']) 290*61046927SAndroid Build Coastguard Worker 291*61046927SAndroid Build Coastguard Worker for meta in xml.findall('meta'): 292*61046927SAndroid Build Coastguard Worker self.meta.update(meta.attrib) 293*61046927SAndroid Build Coastguard Worker 294*61046927SAndroid Build Coastguard Worker # Collect up the match/dontcare/mask bitmasks for 295*61046927SAndroid Build Coastguard Worker # this bitset case: 296*61046927SAndroid Build Coastguard Worker self.match = 0 297*61046927SAndroid Build Coastguard Worker self.dontcare = 0 298*61046927SAndroid Build Coastguard Worker self.mask = 0 299*61046927SAndroid Build Coastguard Worker self.field_mask = 0 300*61046927SAndroid Build Coastguard Worker 301*61046927SAndroid Build Coastguard Worker self.cases = [] 302*61046927SAndroid Build Coastguard Worker 303*61046927SAndroid Build Coastguard Worker # Helper to check for redefined bits: 304*61046927SAndroid Build Coastguard Worker def is_defined_bits(m): 305*61046927SAndroid Build Coastguard Worker return ((self.field_mask | self.mask | self.dontcare | self.match) & m) != 0 306*61046927SAndroid Build Coastguard Worker 307*61046927SAndroid Build Coastguard Worker def update_default_bitmask_field(bs, field): 308*61046927SAndroid Build Coastguard Worker m = field.mask() 309*61046927SAndroid Build Coastguard Worker dbg("field: {}.{} => {:016x}".format(self.name, field.name, m)) 310*61046927SAndroid Build Coastguard Worker # For default case, we don't expect any bits to be doubly defined: 311*61046927SAndroid Build Coastguard Worker assert not is_defined_bits(m), "Redefined bits in field {}.{}: {}..{}".format( 312*61046927SAndroid Build Coastguard Worker self.name, field.name, field.low, field.high) 313*61046927SAndroid Build Coastguard Worker self.field_mask |= m 314*61046927SAndroid Build Coastguard Worker 315*61046927SAndroid Build Coastguard Worker def update_override_bitmask_field(bs, field): 316*61046927SAndroid Build Coastguard Worker m = field.mask() 317*61046927SAndroid Build Coastguard Worker dbg("field: {}.{} => {:016x}".format(self.name, field.name, m)) 318*61046927SAndroid Build Coastguard Worker assert self.field_mask ^ ~m 319*61046927SAndroid Build Coastguard Worker 320*61046927SAndroid Build Coastguard Worker dflt = BitSetCase(self, xml, update_default_bitmask_field) 321*61046927SAndroid Build Coastguard Worker 322*61046927SAndroid Build Coastguard Worker for override in xml.findall('override'): 323*61046927SAndroid Build Coastguard Worker if 'expr' in override.attrib: 324*61046927SAndroid Build Coastguard Worker expr = override.attrib['expr'] 325*61046927SAndroid Build Coastguard Worker else: 326*61046927SAndroid Build Coastguard Worker e = isa.parse_one_expression(override, self.name) 327*61046927SAndroid Build Coastguard Worker expr = e.name 328*61046927SAndroid Build Coastguard Worker c = BitSetCase(self, override, update_override_bitmask_field, expr) 329*61046927SAndroid Build Coastguard Worker self.cases.append(c) 330*61046927SAndroid Build Coastguard Worker 331*61046927SAndroid Build Coastguard Worker # Default case is expected to be the last one: 332*61046927SAndroid Build Coastguard Worker self.cases.append(dflt) 333*61046927SAndroid Build Coastguard Worker 334*61046927SAndroid Build Coastguard Worker for pattern in xml.findall('pattern'): 335*61046927SAndroid Build Coastguard Worker match, dontcare, mask = extract_pattern(pattern, self.name, is_defined_bits) 336*61046927SAndroid Build Coastguard Worker 337*61046927SAndroid Build Coastguard Worker self.match |= match 338*61046927SAndroid Build Coastguard Worker self.dontcare |= dontcare 339*61046927SAndroid Build Coastguard Worker self.mask |= mask 340*61046927SAndroid Build Coastguard Worker 341*61046927SAndroid Build Coastguard Worker def get_pattern(self): 342*61046927SAndroid Build Coastguard Worker if self.extends is not None: 343*61046927SAndroid Build Coastguard Worker parent = self.isa.bitsets[self.extends] 344*61046927SAndroid Build Coastguard Worker ppat = parent.get_pattern() 345*61046927SAndroid Build Coastguard Worker pat = BitSetPattern(self) 346*61046927SAndroid Build Coastguard Worker 347*61046927SAndroid Build Coastguard Worker assert ((ppat.defined_bits() & pat.defined_bits()) == 0), "bitset conflict in {}: {:x}".format(self.name, (ppat.defined_bits() & pat.defined_bits())) 348*61046927SAndroid Build Coastguard Worker 349*61046927SAndroid Build Coastguard Worker return pat.merge(ppat) 350*61046927SAndroid Build Coastguard Worker 351*61046927SAndroid Build Coastguard Worker return BitSetPattern(self) 352*61046927SAndroid Build Coastguard Worker 353*61046927SAndroid Build Coastguard Worker def get_size(self): 354*61046927SAndroid Build Coastguard Worker if self.extends is not None: 355*61046927SAndroid Build Coastguard Worker parent = self.isa.bitsets[self.extends] 356*61046927SAndroid Build Coastguard Worker return parent.get_size() 357*61046927SAndroid Build Coastguard Worker return self.size 358*61046927SAndroid Build Coastguard Worker 359*61046927SAndroid Build Coastguard Worker def get_gen_min(self): 360*61046927SAndroid Build Coastguard Worker if self.extends is not None: 361*61046927SAndroid Build Coastguard Worker parent = self.isa.bitsets[self.extends] 362*61046927SAndroid Build Coastguard Worker 363*61046927SAndroid Build Coastguard Worker assert (self.gen_min == 0) or (self.gen_min >= parent.get_gen_min()), "bitset {} should not have min gen lower than the parent's one".format(self.name) 364*61046927SAndroid Build Coastguard Worker 365*61046927SAndroid Build Coastguard Worker return max(self.gen_min, parent.get_gen_min()) 366*61046927SAndroid Build Coastguard Worker return self.gen_min 367*61046927SAndroid Build Coastguard Worker 368*61046927SAndroid Build Coastguard Worker def get_gen_max(self): 369*61046927SAndroid Build Coastguard Worker if self.extends is not None: 370*61046927SAndroid Build Coastguard Worker parent = self.isa.bitsets[self.extends] 371*61046927SAndroid Build Coastguard Worker 372*61046927SAndroid Build Coastguard Worker assert (self.gen_max == (1 << 32) - 1) or (self.gen_max <= parent.get_gen_max()), "bitset {} should not have max gen higher than the parent's one".format(self.name) 373*61046927SAndroid Build Coastguard Worker 374*61046927SAndroid Build Coastguard Worker return min(self.gen_max, parent.get_gen_max()) 375*61046927SAndroid Build Coastguard Worker return self.gen_max 376*61046927SAndroid Build Coastguard Worker 377*61046927SAndroid Build Coastguard Worker def has_gen_restriction(self): 378*61046927SAndroid Build Coastguard Worker return self.gen_min != 0 or self.gen_max != (1 << 32) - 1 379*61046927SAndroid Build Coastguard Worker 380*61046927SAndroid Build Coastguard Worker def get_c_name(self): 381*61046927SAndroid Build Coastguard Worker return get_c_name(self.name) 382*61046927SAndroid Build Coastguard Worker 383*61046927SAndroid Build Coastguard Worker def get_root(self): 384*61046927SAndroid Build Coastguard Worker if self.extends is not None: 385*61046927SAndroid Build Coastguard Worker return self.isa.bitsets[self.extends].get_root() 386*61046927SAndroid Build Coastguard Worker return self 387*61046927SAndroid Build Coastguard Worker 388*61046927SAndroid Build Coastguard Worker def get_meta(self): 389*61046927SAndroid Build Coastguard Worker meta = {} 390*61046927SAndroid Build Coastguard Worker 391*61046927SAndroid Build Coastguard Worker if self.extends is not None: 392*61046927SAndroid Build Coastguard Worker meta = self.isa.bitsets[self.extends].get_meta() 393*61046927SAndroid Build Coastguard Worker 394*61046927SAndroid Build Coastguard Worker if self.meta: 395*61046927SAndroid Build Coastguard Worker meta.update(self.meta) 396*61046927SAndroid Build Coastguard Worker 397*61046927SAndroid Build Coastguard Worker return meta 398*61046927SAndroid Build Coastguard Worker 399*61046927SAndroid Build Coastguard Workerclass BitSetTemplate(object): 400*61046927SAndroid Build Coastguard Worker """Class that encapsulates a template declaration 401*61046927SAndroid Build Coastguard Worker """ 402*61046927SAndroid Build Coastguard Worker def __init__(self, isa, xml): 403*61046927SAndroid Build Coastguard Worker self.isa = isa 404*61046927SAndroid Build Coastguard Worker self.name = xml.attrib['name'] 405*61046927SAndroid Build Coastguard Worker self.display = xml.text.strip() 406*61046927SAndroid Build Coastguard Worker dbg("found template '{}: {}'".format(self.name, self.display)) 407*61046927SAndroid Build Coastguard Worker 408*61046927SAndroid Build Coastguard Workerclass BitSetEnumValue(object): 409*61046927SAndroid Build Coastguard Worker """Class that encapsulates an enum value 410*61046927SAndroid Build Coastguard Worker """ 411*61046927SAndroid Build Coastguard Worker def __init__(self, isa, xml): 412*61046927SAndroid Build Coastguard Worker self.isa = isa 413*61046927SAndroid Build Coastguard Worker self.displayname = xml.attrib['display'] 414*61046927SAndroid Build Coastguard Worker self.value = xml.attrib['val'] 415*61046927SAndroid Build Coastguard Worker self.name = xml.attrib.get('name') 416*61046927SAndroid Build Coastguard Worker 417*61046927SAndroid Build Coastguard Worker def __str__(self): 418*61046927SAndroid Build Coastguard Worker return self.displayname 419*61046927SAndroid Build Coastguard Worker 420*61046927SAndroid Build Coastguard Worker def get_name(self): 421*61046927SAndroid Build Coastguard Worker return self.name or self.displayname 422*61046927SAndroid Build Coastguard Worker 423*61046927SAndroid Build Coastguard Worker def get_displayname(self): 424*61046927SAndroid Build Coastguard Worker return self.displayname or self.name 425*61046927SAndroid Build Coastguard Worker 426*61046927SAndroid Build Coastguard Worker def get_value(self): 427*61046927SAndroid Build Coastguard Worker return self.value 428*61046927SAndroid Build Coastguard Worker 429*61046927SAndroid Build Coastguard Workerclass BitSetEnum(object): 430*61046927SAndroid Build Coastguard Worker """Class that encapsulates an enum declaration 431*61046927SAndroid Build Coastguard Worker """ 432*61046927SAndroid Build Coastguard Worker def __init__(self, isa, xml): 433*61046927SAndroid Build Coastguard Worker self.isa = isa 434*61046927SAndroid Build Coastguard Worker self.name = xml.attrib['name'] 435*61046927SAndroid Build Coastguard Worker 436*61046927SAndroid Build Coastguard Worker # Table mapping value to name 437*61046927SAndroid Build Coastguard Worker self.values = {} 438*61046927SAndroid Build Coastguard Worker for value in xml.findall('value'): 439*61046927SAndroid Build Coastguard Worker v = BitSetEnumValue(self, value) 440*61046927SAndroid Build Coastguard Worker self.values[v.get_value()] = v 441*61046927SAndroid Build Coastguard Worker 442*61046927SAndroid Build Coastguard Worker def get_c_name(self): 443*61046927SAndroid Build Coastguard Worker return 'enum_' + get_c_name(self.name) 444*61046927SAndroid Build Coastguard Worker 445*61046927SAndroid Build Coastguard Workerclass BitSetExpression(object): 446*61046927SAndroid Build Coastguard Worker """Class that encapsulates an <expr> declaration 447*61046927SAndroid Build Coastguard Worker """ 448*61046927SAndroid Build Coastguard Worker def __init__(self, isa, xml): 449*61046927SAndroid Build Coastguard Worker self.isa = isa 450*61046927SAndroid Build Coastguard Worker if 'name' in xml.attrib: 451*61046927SAndroid Build Coastguard Worker self.name = xml.attrib['name'] 452*61046927SAndroid Build Coastguard Worker else: 453*61046927SAndroid Build Coastguard Worker self.name = 'anon_' + str(isa.anon_expression_count) 454*61046927SAndroid Build Coastguard Worker isa.anon_expression_count = isa.anon_expression_count + 1 455*61046927SAndroid Build Coastguard Worker expr = xml.text.strip() 456*61046927SAndroid Build Coastguard Worker self.fieldnames = list(set(re.findall(r"{([a-zA-Z0-9_]+)}", expr))) 457*61046927SAndroid Build Coastguard Worker self.expr = re.sub(r"{([a-zA-Z0-9_]+)}", r"\1", expr) 458*61046927SAndroid Build Coastguard Worker dbg("'{}' -> '{}'".format(expr, self.expr)) 459*61046927SAndroid Build Coastguard Worker 460*61046927SAndroid Build Coastguard Worker def get_c_name(self): 461*61046927SAndroid Build Coastguard Worker return 'expr_' + get_c_name(self.name) 462*61046927SAndroid Build Coastguard Worker 463*61046927SAndroid Build Coastguard Workerclass ISA(object): 464*61046927SAndroid Build Coastguard Worker """Class that encapsulates all the parsed bitset rules 465*61046927SAndroid Build Coastguard Worker """ 466*61046927SAndroid Build Coastguard Worker def __init__(self, xmlpath): 467*61046927SAndroid Build Coastguard Worker self.base_path = os.path.dirname(xmlpath) 468*61046927SAndroid Build Coastguard Worker 469*61046927SAndroid Build Coastguard Worker # Counter used to name inline (anonymous) expressions: 470*61046927SAndroid Build Coastguard Worker self.anon_expression_count = 0 471*61046927SAndroid Build Coastguard Worker 472*61046927SAndroid Build Coastguard Worker # Table of (globally defined) expressions: 473*61046927SAndroid Build Coastguard Worker self.expressions = {} 474*61046927SAndroid Build Coastguard Worker 475*61046927SAndroid Build Coastguard Worker # Table of templates: 476*61046927SAndroid Build Coastguard Worker self.templates = {} 477*61046927SAndroid Build Coastguard Worker 478*61046927SAndroid Build Coastguard Worker # Table of enums: 479*61046927SAndroid Build Coastguard Worker self.enums = {} 480*61046927SAndroid Build Coastguard Worker 481*61046927SAndroid Build Coastguard Worker # Table of toplevel bitset hierarchies: 482*61046927SAndroid Build Coastguard Worker self.roots = {} 483*61046927SAndroid Build Coastguard Worker 484*61046927SAndroid Build Coastguard Worker # Table of leaf nodes of bitset hierarchies: 485*61046927SAndroid Build Coastguard Worker # Note that there may be multiple leaves for a particular name 486*61046927SAndroid Build Coastguard Worker # (distinguished by gen), so the values here are lists. 487*61046927SAndroid Build Coastguard Worker self.leafs = {} 488*61046927SAndroid Build Coastguard Worker 489*61046927SAndroid Build Coastguard Worker # Table of all non-ambiguous bitsets (i.e. no per-gen ambiguity): 490*61046927SAndroid Build Coastguard Worker self.bitsets = {} 491*61046927SAndroid Build Coastguard Worker 492*61046927SAndroid Build Coastguard Worker # Max needed bitsize for one instruction 493*61046927SAndroid Build Coastguard Worker self.bitsize = 0 494*61046927SAndroid Build Coastguard Worker 495*61046927SAndroid Build Coastguard Worker root = ElementTree.parse(xmlpath).getroot() 496*61046927SAndroid Build Coastguard Worker self.parse_file(root) 497*61046927SAndroid Build Coastguard Worker self.validate_isa() 498*61046927SAndroid Build Coastguard Worker 499*61046927SAndroid Build Coastguard Worker def parse_expressions(self, root): 500*61046927SAndroid Build Coastguard Worker e = None 501*61046927SAndroid Build Coastguard Worker for expr in root.findall('expr'): 502*61046927SAndroid Build Coastguard Worker e = BitSetExpression(self, expr) 503*61046927SAndroid Build Coastguard Worker self.expressions[e.name] = e 504*61046927SAndroid Build Coastguard Worker return e 505*61046927SAndroid Build Coastguard Worker 506*61046927SAndroid Build Coastguard Worker def parse_one_expression(self, root, name): 507*61046927SAndroid Build Coastguard Worker assert len(root.findall('expr')) == 1, "expected a single expression in: {}".format(name) 508*61046927SAndroid Build Coastguard Worker return self.parse_expressions(root) 509*61046927SAndroid Build Coastguard Worker 510*61046927SAndroid Build Coastguard Worker def parse_file(self, root): 511*61046927SAndroid Build Coastguard Worker # Handle imports up-front: 512*61046927SAndroid Build Coastguard Worker for imprt in root.findall('import'): 513*61046927SAndroid Build Coastguard Worker p = os.path.join(self.base_path, imprt.attrib['file']) 514*61046927SAndroid Build Coastguard Worker self.parse_file(ElementTree.parse(p)) 515*61046927SAndroid Build Coastguard Worker 516*61046927SAndroid Build Coastguard Worker # Extract expressions: 517*61046927SAndroid Build Coastguard Worker self.parse_expressions(root) 518*61046927SAndroid Build Coastguard Worker 519*61046927SAndroid Build Coastguard Worker # Extract templates: 520*61046927SAndroid Build Coastguard Worker for template in root.findall('template'): 521*61046927SAndroid Build Coastguard Worker t = BitSetTemplate(self, template) 522*61046927SAndroid Build Coastguard Worker self.templates[t.name] = t 523*61046927SAndroid Build Coastguard Worker 524*61046927SAndroid Build Coastguard Worker # Extract enums: 525*61046927SAndroid Build Coastguard Worker for enum in root.findall('enum'): 526*61046927SAndroid Build Coastguard Worker e = BitSetEnum(self, enum) 527*61046927SAndroid Build Coastguard Worker self.enums[e.name] = e 528*61046927SAndroid Build Coastguard Worker 529*61046927SAndroid Build Coastguard Worker # Extract bitsets: 530*61046927SAndroid Build Coastguard Worker for bitset in root.findall('bitset'): 531*61046927SAndroid Build Coastguard Worker b = BitSet(self, bitset) 532*61046927SAndroid Build Coastguard Worker if b.size is not None: 533*61046927SAndroid Build Coastguard Worker dbg("toplevel: " + b.name) 534*61046927SAndroid Build Coastguard Worker self.roots[b.name] = b 535*61046927SAndroid Build Coastguard Worker self.bitsize = max(self.bitsize, b.size) 536*61046927SAndroid Build Coastguard Worker else: 537*61046927SAndroid Build Coastguard Worker dbg("derived: " + b.name) 538*61046927SAndroid Build Coastguard Worker self.bitsets[b.name] = b 539*61046927SAndroid Build Coastguard Worker self.leafs.setdefault(b.name, []).append(b) 540*61046927SAndroid Build Coastguard Worker 541*61046927SAndroid Build Coastguard Worker # Resolve all templates: 542*61046927SAndroid Build Coastguard Worker for _, bitset in self.bitsets.items(): 543*61046927SAndroid Build Coastguard Worker for case in bitset.cases: 544*61046927SAndroid Build Coastguard Worker if case.display: 545*61046927SAndroid Build Coastguard Worker case.display = self.resolve_templates(case.display) 546*61046927SAndroid Build Coastguard Worker 547*61046927SAndroid Build Coastguard Worker def validate_isa(self): 548*61046927SAndroid Build Coastguard Worker # We only support multiples of 32 bits for now 549*61046927SAndroid Build Coastguard Worker assert self.bitsize % 32 == 0 550*61046927SAndroid Build Coastguard Worker 551*61046927SAndroid Build Coastguard Worker # Do one-time fixups 552*61046927SAndroid Build Coastguard Worker # Remove non-leaf nodes from the leafs table: 553*61046927SAndroid Build Coastguard Worker for name, bitsets in list(self.leafs.items()): 554*61046927SAndroid Build Coastguard Worker for bitset in bitsets: 555*61046927SAndroid Build Coastguard Worker if bitset.extends in self.leafs: 556*61046927SAndroid Build Coastguard Worker del self.leafs[bitset.extends] 557*61046927SAndroid Build Coastguard Worker 558*61046927SAndroid Build Coastguard Worker # Fix multi-gen leaves in bitsets 559*61046927SAndroid Build Coastguard Worker for name, bitsets in self.leafs.items(): 560*61046927SAndroid Build Coastguard Worker if len(bitsets) == 1: 561*61046927SAndroid Build Coastguard Worker continue 562*61046927SAndroid Build Coastguard Worker 563*61046927SAndroid Build Coastguard Worker del self.bitsets[name] 564*61046927SAndroid Build Coastguard Worker 565*61046927SAndroid Build Coastguard Worker # Validate that all bitset fields have valid types, and in 566*61046927SAndroid Build Coastguard Worker # the case of bitset type, the sizes match: 567*61046927SAndroid Build Coastguard Worker builtin_types = ['branch', 'absbranch', 'int', 'uint', 'hex', 'offset', 'uoffset', 'float', 'bool', 'bool_inv', 'enum', 'custom'] 568*61046927SAndroid Build Coastguard Worker for bitset_name, bitset in self.bitsets.items(): 569*61046927SAndroid Build Coastguard Worker if bitset.extends is not None: 570*61046927SAndroid Build Coastguard Worker assert bitset.extends in self.bitsets, "{} extends invalid type: {}".format( 571*61046927SAndroid Build Coastguard Worker bitset_name, bitset.extends) 572*61046927SAndroid Build Coastguard Worker for case in bitset.cases: 573*61046927SAndroid Build Coastguard Worker for field_name, field in case.fields.items(): 574*61046927SAndroid Build Coastguard Worker if field.type == 'float': 575*61046927SAndroid Build Coastguard Worker assert field.get_size() == 32 or field.get_size() == 16 576*61046927SAndroid Build Coastguard Worker 577*61046927SAndroid Build Coastguard Worker if not isinstance(field, BitSetDerivedField): 578*61046927SAndroid Build Coastguard Worker assert field.high < bitset.get_size(), \ 579*61046927SAndroid Build Coastguard Worker "{}.{}: invalid bit range: [{}, {}] is not in [{}, {}]".format( 580*61046927SAndroid Build Coastguard Worker bitset_name, field_name, field.low, field.high, 0, bitset.get_size() - 1) 581*61046927SAndroid Build Coastguard Worker 582*61046927SAndroid Build Coastguard Worker if field.type in builtin_types: 583*61046927SAndroid Build Coastguard Worker continue 584*61046927SAndroid Build Coastguard Worker if field.type in self.enums: 585*61046927SAndroid Build Coastguard Worker continue 586*61046927SAndroid Build Coastguard Worker assert field.type in self.bitsets, "{}.{}: invalid type: {}".format( 587*61046927SAndroid Build Coastguard Worker bitset_name, field_name, field.type) 588*61046927SAndroid Build Coastguard Worker bs = self.bitsets[field.type] 589*61046927SAndroid Build Coastguard Worker assert field.get_size() == bs.get_size(), "{}.{}: invalid size: {} vs {}".format( 590*61046927SAndroid Build Coastguard Worker bitset_name, field_name, field.get_size(), bs.get_size()) 591*61046927SAndroid Build Coastguard Worker 592*61046927SAndroid Build Coastguard Worker # Validate that all the leaf node bitsets have no remaining 593*61046927SAndroid Build Coastguard Worker # undefined bits 594*61046927SAndroid Build Coastguard Worker for name, bitsets in self.leafs.items(): 595*61046927SAndroid Build Coastguard Worker for bitset in bitsets: 596*61046927SAndroid Build Coastguard Worker pat = bitset.get_pattern() 597*61046927SAndroid Build Coastguard Worker sz = bitset.get_size() 598*61046927SAndroid Build Coastguard Worker assert ((pat.mask | pat.field_mask) == (1 << sz) - 1), "leaf bitset {} has undefined bits: {:x}".format( 599*61046927SAndroid Build Coastguard Worker bitset.name, ~(pat.mask | pat.field_mask) & ((1 << sz) - 1)) 600*61046927SAndroid Build Coastguard Worker 601*61046927SAndroid Build Coastguard Worker # TODO somehow validating that only one bitset in a hierarchy 602*61046927SAndroid Build Coastguard Worker # matches any given bit pattern would be useful. 603*61046927SAndroid Build Coastguard Worker 604*61046927SAndroid Build Coastguard Worker # TODO we should probably be able to look at the contexts where 605*61046927SAndroid Build Coastguard Worker # an expression is evaluated and verify that it doesn't have any 606*61046927SAndroid Build Coastguard Worker # {VARNAME} references that would be unresolved at evaluation time 607*61046927SAndroid Build Coastguard Worker 608*61046927SAndroid Build Coastguard Worker def format(self): 609*61046927SAndroid Build Coastguard Worker ''' Generate format string used by printf(..) and friends ''' 610*61046927SAndroid Build Coastguard Worker parts = [] 611*61046927SAndroid Build Coastguard Worker words = self.bitsize / 32 612*61046927SAndroid Build Coastguard Worker 613*61046927SAndroid Build Coastguard Worker for i in range(int(words)): 614*61046927SAndroid Build Coastguard Worker parts.append('%08x') 615*61046927SAndroid Build Coastguard Worker 616*61046927SAndroid Build Coastguard Worker fmt = ''.join(parts) 617*61046927SAndroid Build Coastguard Worker 618*61046927SAndroid Build Coastguard Worker return f"\"{fmt[1:]}\"" 619*61046927SAndroid Build Coastguard Worker 620*61046927SAndroid Build Coastguard Worker def value(self): 621*61046927SAndroid Build Coastguard Worker ''' Generate format values used by printf(..) and friends ''' 622*61046927SAndroid Build Coastguard Worker parts = [] 623*61046927SAndroid Build Coastguard Worker words = self.bitsize / 32 624*61046927SAndroid Build Coastguard Worker 625*61046927SAndroid Build Coastguard Worker for i in range(int(words) - 1, -1, -1): 626*61046927SAndroid Build Coastguard Worker parts.append('v[' + str(i) + ']') 627*61046927SAndroid Build Coastguard Worker 628*61046927SAndroid Build Coastguard Worker return ', '.join(parts) 629*61046927SAndroid Build Coastguard Worker 630*61046927SAndroid Build Coastguard Worker def split_bits(self, value, bitsize): 631*61046927SAndroid Build Coastguard Worker ''' Split `value` into a list of bitsize-bit integers ''' 632*61046927SAndroid Build Coastguard Worker mask, parts = (1 << bitsize) - 1, [] 633*61046927SAndroid Build Coastguard Worker words = self.bitsize / bitsize 634*61046927SAndroid Build Coastguard Worker 635*61046927SAndroid Build Coastguard Worker while value: 636*61046927SAndroid Build Coastguard Worker parts.append(hex(value & mask)) 637*61046927SAndroid Build Coastguard Worker value >>= bitsize 638*61046927SAndroid Build Coastguard Worker 639*61046927SAndroid Build Coastguard Worker # Add 'missing' words 640*61046927SAndroid Build Coastguard Worker while len(parts) < words: 641*61046927SAndroid Build Coastguard Worker parts.append('0x0') 642*61046927SAndroid Build Coastguard Worker 643*61046927SAndroid Build Coastguard Worker return parts 644*61046927SAndroid Build Coastguard Worker 645*61046927SAndroid Build Coastguard Worker # Returns all bitsets in the ISA, including all per-gen variants, in 646*61046927SAndroid Build Coastguard Worker # (name, bitset) pairs. 647*61046927SAndroid Build Coastguard Worker def all_bitsets(self): 648*61046927SAndroid Build Coastguard Worker for name, bitset in self.bitsets.items(): 649*61046927SAndroid Build Coastguard Worker yield name, bitset 650*61046927SAndroid Build Coastguard Worker for name, bitsets in self.leafs.items(): 651*61046927SAndroid Build Coastguard Worker if len(bitsets) == 1: 652*61046927SAndroid Build Coastguard Worker continue 653*61046927SAndroid Build Coastguard Worker for bitset in bitsets: 654*61046927SAndroid Build Coastguard Worker yield name, bitset 655*61046927SAndroid Build Coastguard Worker 656*61046927SAndroid Build Coastguard Worker def resolve_templates(self, display_string): 657*61046927SAndroid Build Coastguard Worker matches = re.findall(r'\{([^\}]+)\}', display_string) 658*61046927SAndroid Build Coastguard Worker for m in matches: 659*61046927SAndroid Build Coastguard Worker if m in self.templates: 660*61046927SAndroid Build Coastguard Worker display_string = display_string.replace("{" + m + "}", self.templates[m].display) 661*61046927SAndroid Build Coastguard Worker 662*61046927SAndroid Build Coastguard Worker return display_string 663*61046927SAndroid Build Coastguard Worker 664*61046927SAndroid Build Coastguard Worker def instructions(self): 665*61046927SAndroid Build Coastguard Worker instr = [] 666*61046927SAndroid Build Coastguard Worker 667*61046927SAndroid Build Coastguard Worker for _, root in self.roots.items(): 668*61046927SAndroid Build Coastguard Worker for _, leafs in self.leafs.items(): 669*61046927SAndroid Build Coastguard Worker for leaf in leafs: 670*61046927SAndroid Build Coastguard Worker if leaf.get_root() == root: 671*61046927SAndroid Build Coastguard Worker if not leaf.get_c_name().startswith('__'): 672*61046927SAndroid Build Coastguard Worker instr.append(leaf) 673*61046927SAndroid Build Coastguard Worker 674*61046927SAndroid Build Coastguard Worker return instr 675