xref: /aosp_15_r20/external/mesa3d/src/compiler/isaspec/isa.py (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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