xref: /aosp_15_r20/external/mesa3d/src/compiler/isaspec/encode.py (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker#!/usr/bin/env python3
2*61046927SAndroid Build Coastguard Worker#
3*61046927SAndroid Build Coastguard Worker# Copyright © 2020 Google, Inc.
4*61046927SAndroid Build Coastguard Worker#
5*61046927SAndroid Build Coastguard Worker# Permission is hereby granted, free of charge, to any person obtaining a
6*61046927SAndroid Build Coastguard Worker# copy of this software and associated documentation files (the "Software"),
7*61046927SAndroid Build Coastguard Worker# to deal in the Software without restriction, including without limitation
8*61046927SAndroid Build Coastguard Worker# the rights to use, copy, modify, merge, publish, distribute, sublicense,
9*61046927SAndroid Build Coastguard Worker# and/or sell copies of the Software, and to permit persons to whom the
10*61046927SAndroid Build Coastguard Worker# Software is furnished to do so, subject to the following conditions:
11*61046927SAndroid Build Coastguard Worker#
12*61046927SAndroid Build Coastguard Worker# The above copyright notice and this permission notice (including the next
13*61046927SAndroid Build Coastguard Worker# paragraph) shall be included in all copies or substantial portions of the
14*61046927SAndroid Build Coastguard Worker# Software.
15*61046927SAndroid Build Coastguard Worker#
16*61046927SAndroid Build Coastguard Worker# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*61046927SAndroid Build Coastguard Worker# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*61046927SAndroid Build Coastguard Worker# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19*61046927SAndroid Build Coastguard Worker# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*61046927SAndroid Build Coastguard Worker# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21*61046927SAndroid Build Coastguard Worker# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22*61046927SAndroid Build Coastguard Worker# IN THE SOFTWARE.
23*61046927SAndroid Build Coastguard Worker
24*61046927SAndroid Build Coastguard Workerfrom mako.template import Template
25*61046927SAndroid Build Coastguard Workerfrom isa import ISA, BitSetDerivedField, BitSetAssertField
26*61046927SAndroid Build Coastguard Workerimport argparse
27*61046927SAndroid Build Coastguard Workerimport sys
28*61046927SAndroid Build Coastguard Workerimport re
29*61046927SAndroid Build Coastguard Worker
30*61046927SAndroid Build Coastguard Worker# Encoding is driven by the display template that would be used
31*61046927SAndroid Build Coastguard Worker# to decode any given instruction, essentially working backwards
32*61046927SAndroid Build Coastguard Worker# from the decode case.  (Or put another way, the decoded bitset
33*61046927SAndroid Build Coastguard Worker# should contain enough information to re-encode it again.)
34*61046927SAndroid Build Coastguard Worker#
35*61046927SAndroid Build Coastguard Worker# In the xml, we can have multiple override cases per bitset,
36*61046927SAndroid Build Coastguard Worker# which can override display template and/or fields.  Iterating
37*61046927SAndroid Build Coastguard Worker# all this from within the template is messy, so use helpers
38*61046927SAndroid Build Coastguard Worker# outside of the template for this.
39*61046927SAndroid Build Coastguard Worker#
40*61046927SAndroid Build Coastguard Worker# The hierarchy of iterators for encoding is:
41*61046927SAndroid Build Coastguard Worker#
42*61046927SAndroid Build Coastguard Worker#   // First level - Case()  (s.bitset_cases() iterator)
43*61046927SAndroid Build Coastguard Worker#   if (caseA.expression()) {  // maps to <override/> in xml
44*61046927SAndroid Build Coastguard Worker#      // Second level - DisplayField()  (case.display_fields() iterator)
45*61046927SAndroid Build Coastguard Worker#      ... encode field A ...
46*61046927SAndroid Build Coastguard Worker#      ... encode field B ...
47*61046927SAndroid Build Coastguard Worker#
48*61046927SAndroid Build Coastguard Worker#      // Third level - each display field can be potentially resolved
49*61046927SAndroid Build Coastguard Worker#      // by multiple different overrides, you can end up with
50*61046927SAndroid Build Coastguard Worker#      // an if/else ladder for an individual display field
51*61046927SAndroid Build Coastguard Worker#      if (field_c_case1.expression()) {
52*61046927SAndroid Build Coastguard Worker#         ... encode field C ...
53*61046927SAndroid Build Coastguard Worker#      } else if (field_c_case2.expression() {
54*61046927SAndroid Build Coastguard Worker#         ... encode field C ...
55*61046927SAndroid Build Coastguard Worker#      } else {
56*61046927SAndroid Build Coastguard Worker#      }
57*61046927SAndroid Build Coastguard Worker#
58*61046927SAndroid Build Coastguard Worker#   } else if (caseB.expression())(
59*61046927SAndroid Build Coastguard Worker#   } else {  // maps to the default case in bitset, ie. outside <override/>
60*61046927SAndroid Build Coastguard Worker#   }
61*61046927SAndroid Build Coastguard Worker
62*61046927SAndroid Build Coastguard Worker
63*61046927SAndroid Build Coastguard Worker# Represents a concrete field, ie. a field can be overriden
64*61046927SAndroid Build Coastguard Worker# by an override, so the exact choice to encode a given field
65*61046927SAndroid Build Coastguard Worker# in a bitset may be conditional
66*61046927SAndroid Build Coastguard Workerclass FieldCase(object):
67*61046927SAndroid Build Coastguard Worker    def __init__(self, bitset, field, case):
68*61046927SAndroid Build Coastguard Worker        self.field = field
69*61046927SAndroid Build Coastguard Worker        self.expr  = None
70*61046927SAndroid Build Coastguard Worker        if case.expr is not None:
71*61046927SAndroid Build Coastguard Worker            self.expr = bitset.isa.expressions[case.expr]
72*61046927SAndroid Build Coastguard Worker
73*61046927SAndroid Build Coastguard Worker    def signed(self):
74*61046927SAndroid Build Coastguard Worker        if self.field.type in ['int', 'offset', 'branch']:
75*61046927SAndroid Build Coastguard Worker            return 'true'
76*61046927SAndroid Build Coastguard Worker        return 'false'
77*61046927SAndroid Build Coastguard Worker
78*61046927SAndroid Build Coastguard Workerclass AssertField(object):
79*61046927SAndroid Build Coastguard Worker    def __init__(self, bitset, field, case):
80*61046927SAndroid Build Coastguard Worker        self.field = field
81*61046927SAndroid Build Coastguard Worker        self.expr  = None
82*61046927SAndroid Build Coastguard Worker        if case.expr is not None:
83*61046927SAndroid Build Coastguard Worker            self.expr = bitset.isa.expressions[case.expr]
84*61046927SAndroid Build Coastguard Worker
85*61046927SAndroid Build Coastguard Worker    def signed(self):
86*61046927SAndroid Build Coastguard Worker        return 'false'
87*61046927SAndroid Build Coastguard Worker
88*61046927SAndroid Build Coastguard Worker# Represents a field to be encoded:
89*61046927SAndroid Build Coastguard Workerclass DisplayField(object):
90*61046927SAndroid Build Coastguard Worker    def __init__(self, bitset, case, name):
91*61046927SAndroid Build Coastguard Worker        self.bitset = bitset   # leaf bitset
92*61046927SAndroid Build Coastguard Worker        self.case = case
93*61046927SAndroid Build Coastguard Worker        self.name = name
94*61046927SAndroid Build Coastguard Worker
95*61046927SAndroid Build Coastguard Worker    def fields(self, bitset=None):
96*61046927SAndroid Build Coastguard Worker        if bitset is None:
97*61046927SAndroid Build Coastguard Worker            bitset = self.bitset
98*61046927SAndroid Build Coastguard Worker        # resolving the various cases for encoding a given
99*61046927SAndroid Build Coastguard Worker        # field is similar to resolving the display template
100*61046927SAndroid Build Coastguard Worker        # string
101*61046927SAndroid Build Coastguard Worker        for case in bitset.cases:
102*61046927SAndroid Build Coastguard Worker            if case.expr is not None:
103*61046927SAndroid Build Coastguard Worker                expr = bitset.isa.expressions[case.expr]
104*61046927SAndroid Build Coastguard Worker                self.case.append_expr_fields(expr)
105*61046927SAndroid Build Coastguard Worker            if self.name in case.fields:
106*61046927SAndroid Build Coastguard Worker                field = case.fields[self.name]
107*61046927SAndroid Build Coastguard Worker                # For bitset fields, the bitset type could reference
108*61046927SAndroid Build Coastguard Worker                # fields in this (the containing) bitset, in addition
109*61046927SAndroid Build Coastguard Worker                # to the ones which are directly used to encode the
110*61046927SAndroid Build Coastguard Worker                # field itself.
111*61046927SAndroid Build Coastguard Worker                if field.get_c_typename() == 'TYPE_BITSET':
112*61046927SAndroid Build Coastguard Worker                    for param in field.params:
113*61046927SAndroid Build Coastguard Worker                        self.case.append_field(param[0])
114*61046927SAndroid Build Coastguard Worker                # For derived fields, we want to consider any other
115*61046927SAndroid Build Coastguard Worker                # fields that are referenced by the expr
116*61046927SAndroid Build Coastguard Worker                if isinstance(field, BitSetDerivedField):
117*61046927SAndroid Build Coastguard Worker                    expr = bitset.isa.expressions[field.expr]
118*61046927SAndroid Build Coastguard Worker                    self.case.append_expr_fields(expr)
119*61046927SAndroid Build Coastguard Worker                elif not isinstance(field, BitSetAssertField):
120*61046927SAndroid Build Coastguard Worker                    yield FieldCase(bitset, field, case)
121*61046927SAndroid Build Coastguard Worker                # if we've found an unconditional case specifying
122*61046927SAndroid Build Coastguard Worker                # the named field, we are done
123*61046927SAndroid Build Coastguard Worker                if case.expr is None:
124*61046927SAndroid Build Coastguard Worker                    return
125*61046927SAndroid Build Coastguard Worker        if bitset.extends is not None:
126*61046927SAndroid Build Coastguard Worker            yield from self.fields(bitset.isa.bitsets[bitset.extends])
127*61046927SAndroid Build Coastguard Worker
128*61046927SAndroid Build Coastguard Worker# Represents an if/else case in bitset encoding which has a display
129*61046927SAndroid Build Coastguard Worker# template string:
130*61046927SAndroid Build Coastguard Workerclass Case(object):
131*61046927SAndroid Build Coastguard Worker    def __init__(self, bitset, case):
132*61046927SAndroid Build Coastguard Worker        self.bitset = bitset   # leaf bitset
133*61046927SAndroid Build Coastguard Worker        self.case = case
134*61046927SAndroid Build Coastguard Worker        self.expr = None
135*61046927SAndroid Build Coastguard Worker        if case.expr is not None:
136*61046927SAndroid Build Coastguard Worker            self.expr = bitset.isa.expressions[case.expr]
137*61046927SAndroid Build Coastguard Worker        self.fieldnames = re.findall(r"{([a-zA-Z0-9_:=]+)}", case.display)
138*61046927SAndroid Build Coastguard Worker        self.append_forced(bitset)
139*61046927SAndroid Build Coastguard Worker
140*61046927SAndroid Build Coastguard Worker        # remove special fieldname properties e.g. :align=
141*61046927SAndroid Build Coastguard Worker        self.fieldnames = list(map(lambda name: name.split(':')[0], self.fieldnames))
142*61046927SAndroid Build Coastguard Worker
143*61046927SAndroid Build Coastguard Worker    # Handle fields which don't appear in display template but have
144*61046927SAndroid Build Coastguard Worker    # force="true"
145*61046927SAndroid Build Coastguard Worker    def append_forced(self, bitset):
146*61046927SAndroid Build Coastguard Worker        if bitset.encode is not None:
147*61046927SAndroid Build Coastguard Worker            for name, val in bitset.encode.forced.items():
148*61046927SAndroid Build Coastguard Worker                self.append_field(name)
149*61046927SAndroid Build Coastguard Worker        if bitset.extends is not None:
150*61046927SAndroid Build Coastguard Worker            self.append_forced(bitset.isa.bitsets[bitset.extends])
151*61046927SAndroid Build Coastguard Worker
152*61046927SAndroid Build Coastguard Worker    # In the process of resolving a field, we might discover additional
153*61046927SAndroid Build Coastguard Worker    # fields that need resolving:
154*61046927SAndroid Build Coastguard Worker    #
155*61046927SAndroid Build Coastguard Worker    # a) a derived field which maps to one or more other concrete fields
156*61046927SAndroid Build Coastguard Worker    # b) a bitset field, which may be "parameterized".. for example a
157*61046927SAndroid Build Coastguard Worker    #    #multisrc field which refers back to SRC1_R/SRC2_R outside of
158*61046927SAndroid Build Coastguard Worker    #    the range of bits covered by the #multisrc field itself
159*61046927SAndroid Build Coastguard Worker    def append_field(self, fieldname):
160*61046927SAndroid Build Coastguard Worker        if fieldname not in self.fieldnames:
161*61046927SAndroid Build Coastguard Worker            self.fieldnames.append(fieldname)
162*61046927SAndroid Build Coastguard Worker
163*61046927SAndroid Build Coastguard Worker    def append_expr_fields(self, expr):
164*61046927SAndroid Build Coastguard Worker        for fieldname in expr.fieldnames:
165*61046927SAndroid Build Coastguard Worker            self.append_field(fieldname)
166*61046927SAndroid Build Coastguard Worker
167*61046927SAndroid Build Coastguard Worker    def display_fields(self):
168*61046927SAndroid Build Coastguard Worker        for fieldname in self.fieldnames:
169*61046927SAndroid Build Coastguard Worker            yield DisplayField(self.bitset, self, fieldname)
170*61046927SAndroid Build Coastguard Worker
171*61046927SAndroid Build Coastguard Worker    def assert_cases(self, bitset=None):
172*61046927SAndroid Build Coastguard Worker        if bitset is None:
173*61046927SAndroid Build Coastguard Worker            bitset = self.bitset
174*61046927SAndroid Build Coastguard Worker        for case in bitset.cases:
175*61046927SAndroid Build Coastguard Worker            for name, field in case.fields.items():
176*61046927SAndroid Build Coastguard Worker                if field.get_c_typename() == 'TYPE_ASSERT':
177*61046927SAndroid Build Coastguard Worker                    yield AssertField(bitset, field, case)
178*61046927SAndroid Build Coastguard Worker        if bitset.extends is not None:
179*61046927SAndroid Build Coastguard Worker            yield from self.assert_cases(bitset.isa.bitsets[bitset.extends])
180*61046927SAndroid Build Coastguard Worker
181*61046927SAndroid Build Coastguard Worker# State and helpers used by the template:
182*61046927SAndroid Build Coastguard Workerclass State(object):
183*61046927SAndroid Build Coastguard Worker    def __init__(self, isa):
184*61046927SAndroid Build Coastguard Worker        self.isa = isa
185*61046927SAndroid Build Coastguard Worker        self.warned_missing_extractors = []
186*61046927SAndroid Build Coastguard Worker
187*61046927SAndroid Build Coastguard Worker    def bitset_cases(self, bitset, leaf_bitset=None):
188*61046927SAndroid Build Coastguard Worker        if leaf_bitset is None:
189*61046927SAndroid Build Coastguard Worker            leaf_bitset = bitset
190*61046927SAndroid Build Coastguard Worker        for case in bitset.cases:
191*61046927SAndroid Build Coastguard Worker            if case.display is None:
192*61046927SAndroid Build Coastguard Worker                # if this is the last case (ie. case.expr is None)
193*61046927SAndroid Build Coastguard Worker                # then we need to go up the inheritance chain:
194*61046927SAndroid Build Coastguard Worker                if case.expr is None and bitset.extends is not None:
195*61046927SAndroid Build Coastguard Worker                    parent_bitset = bitset.isa.bitsets[bitset.extends]
196*61046927SAndroid Build Coastguard Worker                    yield from self.bitset_cases(parent_bitset, leaf_bitset)
197*61046927SAndroid Build Coastguard Worker                continue
198*61046927SAndroid Build Coastguard Worker            yield Case(leaf_bitset, case)
199*61046927SAndroid Build Coastguard Worker
200*61046927SAndroid Build Coastguard Worker    # Find unique bitset remap/parameter names, to generate a struct
201*61046927SAndroid Build Coastguard Worker    # used to pass "parameters" to bitset fields:
202*61046927SAndroid Build Coastguard Worker    def unique_param_names(self):
203*61046927SAndroid Build Coastguard Worker        unique_names = []
204*61046927SAndroid Build Coastguard Worker        for root in self.encode_roots():
205*61046927SAndroid Build Coastguard Worker            for leaf in self.encode_leafs(root):
206*61046927SAndroid Build Coastguard Worker                for case in self.bitset_cases(leaf):
207*61046927SAndroid Build Coastguard Worker                    for df in case.display_fields():
208*61046927SAndroid Build Coastguard Worker                        for f in df.fields():
209*61046927SAndroid Build Coastguard Worker                            if f.field.get_c_typename() == 'TYPE_BITSET':
210*61046927SAndroid Build Coastguard Worker                                for param in f.field.params:
211*61046927SAndroid Build Coastguard Worker                                    target_name = param[1]
212*61046927SAndroid Build Coastguard Worker                                    if target_name not in unique_names:
213*61046927SAndroid Build Coastguard Worker                                        yield target_name
214*61046927SAndroid Build Coastguard Worker                                        unique_names.append(target_name)
215*61046927SAndroid Build Coastguard Worker
216*61046927SAndroid Build Coastguard Worker    def case_name(self, bitset, name):
217*61046927SAndroid Build Coastguard Worker       return bitset.encode.case_prefix + name.upper().replace('.', '_').replace('-', '_').replace('#', '')
218*61046927SAndroid Build Coastguard Worker
219*61046927SAndroid Build Coastguard Worker    def encode_roots(self):
220*61046927SAndroid Build Coastguard Worker       for name, root in self.isa.roots.items():
221*61046927SAndroid Build Coastguard Worker          if root.encode is None:
222*61046927SAndroid Build Coastguard Worker             continue
223*61046927SAndroid Build Coastguard Worker          yield root
224*61046927SAndroid Build Coastguard Worker
225*61046927SAndroid Build Coastguard Worker    def encode_leafs(self, root):
226*61046927SAndroid Build Coastguard Worker        for name, leafs in self.isa.leafs.items():
227*61046927SAndroid Build Coastguard Worker            for leaf in leafs:
228*61046927SAndroid Build Coastguard Worker                if leaf.get_root() != root:
229*61046927SAndroid Build Coastguard Worker                    continue
230*61046927SAndroid Build Coastguard Worker                yield leaf
231*61046927SAndroid Build Coastguard Worker
232*61046927SAndroid Build Coastguard Worker    def encode_leaf_groups(self, root):
233*61046927SAndroid Build Coastguard Worker        for name, leafs in self.isa.leafs.items():
234*61046927SAndroid Build Coastguard Worker            if leafs[0].get_root() != root:
235*61046927SAndroid Build Coastguard Worker                continue
236*61046927SAndroid Build Coastguard Worker            yield leafs
237*61046927SAndroid Build Coastguard Worker
238*61046927SAndroid Build Coastguard Worker    # expressions used in a bitset (case or field or recursively parent bitsets)
239*61046927SAndroid Build Coastguard Worker    def bitset_used_exprs(self, bitset):
240*61046927SAndroid Build Coastguard Worker       for case in bitset.cases:
241*61046927SAndroid Build Coastguard Worker          if case.expr:
242*61046927SAndroid Build Coastguard Worker             yield self.isa.expressions[case.expr]
243*61046927SAndroid Build Coastguard Worker          for name, field in case.fields.items():
244*61046927SAndroid Build Coastguard Worker             if isinstance(field, BitSetDerivedField):
245*61046927SAndroid Build Coastguard Worker                yield self.isa.expressions[field.expr]
246*61046927SAndroid Build Coastguard Worker       if bitset.extends is not None:
247*61046927SAndroid Build Coastguard Worker          yield from self.bitset_used_exprs(self.isa.bitsets[bitset.extends])
248*61046927SAndroid Build Coastguard Worker
249*61046927SAndroid Build Coastguard Worker    def extractor_impl(self, bitset, name):
250*61046927SAndroid Build Coastguard Worker        if bitset.encode is not None:
251*61046927SAndroid Build Coastguard Worker            if name in bitset.encode.maps:
252*61046927SAndroid Build Coastguard Worker                return bitset.encode.maps[name]
253*61046927SAndroid Build Coastguard Worker        if bitset.extends is not None:
254*61046927SAndroid Build Coastguard Worker            return self.extractor_impl(self.isa.bitsets[bitset.extends], name)
255*61046927SAndroid Build Coastguard Worker        return None
256*61046927SAndroid Build Coastguard Worker
257*61046927SAndroid Build Coastguard Worker    # Default fallback when no mapping is defined, simply to avoid
258*61046927SAndroid Build Coastguard Worker    # having to deal with encoding at the same time as r/e new
259*61046927SAndroid Build Coastguard Worker    # instruction decoding.. but we can at least print warnings:
260*61046927SAndroid Build Coastguard Worker    def extractor_fallback(self, bitset, name):
261*61046927SAndroid Build Coastguard Worker        extr_name = bitset.name + '.' + name
262*61046927SAndroid Build Coastguard Worker        if extr_name not in self.warned_missing_extractors:
263*61046927SAndroid Build Coastguard Worker            print('WARNING: no encode mapping for {}.{}'.format(bitset.name, name))
264*61046927SAndroid Build Coastguard Worker            self.warned_missing_extractors.append(extr_name)
265*61046927SAndroid Build Coastguard Worker        return '0 /* XXX */'
266*61046927SAndroid Build Coastguard Worker
267*61046927SAndroid Build Coastguard Worker    def extractor(self, bitset, name):
268*61046927SAndroid Build Coastguard Worker        extr = self.extractor_impl(bitset, name)
269*61046927SAndroid Build Coastguard Worker        if extr is not None:
270*61046927SAndroid Build Coastguard Worker            return extr
271*61046927SAndroid Build Coastguard Worker        return self.extractor_fallback(bitset, name)
272*61046927SAndroid Build Coastguard Worker
273*61046927SAndroid Build Coastguard Worker    # In the special case of needing to access a field with bitset type
274*61046927SAndroid Build Coastguard Worker    # for an expr, we need to encode the field so we end up with an
275*61046927SAndroid Build Coastguard Worker    # integer, and not some pointer to a thing that will be encoded to
276*61046927SAndroid Build Coastguard Worker    # an integer
277*61046927SAndroid Build Coastguard Worker    def expr_extractor(self, bitset, name, p):
278*61046927SAndroid Build Coastguard Worker        extr = self.extractor_impl(bitset, name)
279*61046927SAndroid Build Coastguard Worker        field = self.resolve_simple_field(bitset, name)
280*61046927SAndroid Build Coastguard Worker        if isinstance(field, BitSetDerivedField):
281*61046927SAndroid Build Coastguard Worker            expr = self.isa.expressions[field.expr]
282*61046927SAndroid Build Coastguard Worker            return self.expr_name(bitset.get_root(), expr) + '(s, p, src)'
283*61046927SAndroid Build Coastguard Worker        if extr is None:
284*61046927SAndroid Build Coastguard Worker            if name in self.unique_param_names():
285*61046927SAndroid Build Coastguard Worker                extr = 'p->' + name
286*61046927SAndroid Build Coastguard Worker            else:
287*61046927SAndroid Build Coastguard Worker                extr = self.extractor_fallback(bitset, name)
288*61046927SAndroid Build Coastguard Worker        if field and field.get_c_typename() == 'TYPE_BITSET':
289*61046927SAndroid Build Coastguard Worker            extr = 'encode' + self.isa.roots[field.type].get_c_name() + '(s, ' + p + ', ' + extr + ')'
290*61046927SAndroid Build Coastguard Worker        return extr
291*61046927SAndroid Build Coastguard Worker
292*61046927SAndroid Build Coastguard Worker    # A limited resolver for field type which doesn't properly account for
293*61046927SAndroid Build Coastguard Worker    # overrides.  In particular, if a field is defined differently in multiple
294*61046927SAndroid Build Coastguard Worker    # different cases, this just blindly picks the last one.
295*61046927SAndroid Build Coastguard Worker    #
296*61046927SAndroid Build Coastguard Worker    # TODO to do this properly, I don't think there is an alternative than
297*61046927SAndroid Build Coastguard Worker    # to emit code which evaluates the case.expr
298*61046927SAndroid Build Coastguard Worker    def resolve_simple_field(self, bitset, name):
299*61046927SAndroid Build Coastguard Worker        field = None
300*61046927SAndroid Build Coastguard Worker        for case in bitset.cases:
301*61046927SAndroid Build Coastguard Worker            if name in case.fields:
302*61046927SAndroid Build Coastguard Worker                field = case.fields[name]
303*61046927SAndroid Build Coastguard Worker        if field is not None:
304*61046927SAndroid Build Coastguard Worker            return field
305*61046927SAndroid Build Coastguard Worker        if bitset.extends is not None:
306*61046927SAndroid Build Coastguard Worker            return self.resolve_simple_field(bitset.isa.bitsets[bitset.extends], name)
307*61046927SAndroid Build Coastguard Worker        return None
308*61046927SAndroid Build Coastguard Worker
309*61046927SAndroid Build Coastguard Worker    def encode_type(self, bitset):
310*61046927SAndroid Build Coastguard Worker        if bitset.encode is not None:
311*61046927SAndroid Build Coastguard Worker            if bitset.encode.type is not None:
312*61046927SAndroid Build Coastguard Worker                return bitset.encode.type
313*61046927SAndroid Build Coastguard Worker        if bitset.extends is not None:
314*61046927SAndroid Build Coastguard Worker            return self.encode_type(bitset.isa.bitsets[bitset.extends])
315*61046927SAndroid Build Coastguard Worker        return None
316*61046927SAndroid Build Coastguard Worker
317*61046927SAndroid Build Coastguard Worker    def expr_name(self, root, expr):
318*61046927SAndroid Build Coastguard Worker       return root.get_c_name() + '_' + expr.get_c_name()
319*61046927SAndroid Build Coastguard Worker
320*61046927SAndroid Build Coastguard Workertemplate = """\
321*61046927SAndroid Build Coastguard Worker/* Copyright (C) 2020 Google, Inc.
322*61046927SAndroid Build Coastguard Worker *
323*61046927SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a
324*61046927SAndroid Build Coastguard Worker * copy of this software and associated documentation files (the "Software"),
325*61046927SAndroid Build Coastguard Worker * to deal in the Software without restriction, including without limitation
326*61046927SAndroid Build Coastguard Worker * the rights to use, copy, modify, merge, publish, distribute, sublicense,
327*61046927SAndroid Build Coastguard Worker * and/or sell copies of the Software, and to permit persons to whom the
328*61046927SAndroid Build Coastguard Worker * Software is furnished to do so, subject to the following conditions:
329*61046927SAndroid Build Coastguard Worker *
330*61046927SAndroid Build Coastguard Worker * The above copyright notice and this permission notice (including the next
331*61046927SAndroid Build Coastguard Worker * paragraph) shall be included in all copies or substantial portions of the
332*61046927SAndroid Build Coastguard Worker * Software.
333*61046927SAndroid Build Coastguard Worker *
334*61046927SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
335*61046927SAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
336*61046927SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
337*61046927SAndroid Build Coastguard Worker * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
338*61046927SAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
339*61046927SAndroid Build Coastguard Worker * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
340*61046927SAndroid Build Coastguard Worker * IN THE SOFTWARE.
341*61046927SAndroid Build Coastguard Worker */
342*61046927SAndroid Build Coastguard Worker
343*61046927SAndroid Build Coastguard Worker#include <assert.h>
344*61046927SAndroid Build Coastguard Worker#include <stdbool.h>
345*61046927SAndroid Build Coastguard Worker#include <stdint.h>
346*61046927SAndroid Build Coastguard Worker#include <util/bitset.h>
347*61046927SAndroid Build Coastguard Worker#include <util/log.h>
348*61046927SAndroid Build Coastguard Worker
349*61046927SAndroid Build Coastguard Worker<%
350*61046927SAndroid Build Coastguard Workerisa = s.isa
351*61046927SAndroid Build Coastguard Worker%>
352*61046927SAndroid Build Coastguard Worker
353*61046927SAndroid Build Coastguard Worker#define BITMASK_WORDS BITSET_WORDS(${isa.bitsize})
354*61046927SAndroid Build Coastguard Worker
355*61046927SAndroid Build Coastguard Workertypedef struct {
356*61046927SAndroid Build Coastguard Worker    BITSET_WORD bitset[BITMASK_WORDS];
357*61046927SAndroid Build Coastguard Worker} bitmask_t;
358*61046927SAndroid Build Coastguard Worker
359*61046927SAndroid Build Coastguard Workerstatic inline uint64_t
360*61046927SAndroid Build Coastguard Workerbitmask_to_uint64_t(bitmask_t mask)
361*61046927SAndroid Build Coastguard Worker{
362*61046927SAndroid Build Coastguard Worker%   if isa.bitsize <= 32:
363*61046927SAndroid Build Coastguard Worker    return mask.bitset[0];
364*61046927SAndroid Build Coastguard Worker%   else:
365*61046927SAndroid Build Coastguard Worker    return ((uint64_t)mask.bitset[1] << 32) | mask.bitset[0];
366*61046927SAndroid Build Coastguard Worker%   endif
367*61046927SAndroid Build Coastguard Worker}
368*61046927SAndroid Build Coastguard Worker
369*61046927SAndroid Build Coastguard Workerstatic inline bitmask_t
370*61046927SAndroid Build Coastguard Workeruint64_t_to_bitmask(uint64_t val)
371*61046927SAndroid Build Coastguard Worker{
372*61046927SAndroid Build Coastguard Worker    bitmask_t mask = {
373*61046927SAndroid Build Coastguard Worker        .bitset[0] = val & 0xffffffff,
374*61046927SAndroid Build Coastguard Worker%   if isa.bitsize > 32:
375*61046927SAndroid Build Coastguard Worker        .bitset[1] = (val >> 32) & 0xffffffff,
376*61046927SAndroid Build Coastguard Worker%   endif
377*61046927SAndroid Build Coastguard Worker    };
378*61046927SAndroid Build Coastguard Worker
379*61046927SAndroid Build Coastguard Worker    return mask;
380*61046927SAndroid Build Coastguard Worker}
381*61046927SAndroid Build Coastguard Worker
382*61046927SAndroid Build Coastguard Workerstatic inline void
383*61046927SAndroid Build Coastguard Workerstore_instruction(BITSET_WORD *dst, bitmask_t instr)
384*61046927SAndroid Build Coastguard Worker{
385*61046927SAndroid Build Coastguard Worker%   for i in range(0, int(isa.bitsize / 32)):
386*61046927SAndroid Build Coastguard Worker    *(dst + ${i}) = instr.bitset[${i}];
387*61046927SAndroid Build Coastguard Worker%   endfor
388*61046927SAndroid Build Coastguard Worker}
389*61046927SAndroid Build Coastguard Worker
390*61046927SAndroid Build Coastguard Worker/**
391*61046927SAndroid Build Coastguard Worker * Opaque type from the PoV of generated code, but allows state to be passed
392*61046927SAndroid Build Coastguard Worker * thru to the hand written helpers used by the generated code.
393*61046927SAndroid Build Coastguard Worker */
394*61046927SAndroid Build Coastguard Workerstruct encode_state;
395*61046927SAndroid Build Coastguard Worker
396*61046927SAndroid Build Coastguard Worker/**
397*61046927SAndroid Build Coastguard Worker * Allows to use gpu_id in expr functions
398*61046927SAndroid Build Coastguard Worker */
399*61046927SAndroid Build Coastguard Worker#define ISA_GPU_ID() s->gen
400*61046927SAndroid Build Coastguard Worker
401*61046927SAndroid Build Coastguard Workerstruct bitset_params;
402*61046927SAndroid Build Coastguard Worker
403*61046927SAndroid Build Coastguard Workerstatic bitmask_t
404*61046927SAndroid Build Coastguard Workerpack_field(unsigned low, unsigned high, int64_t val, bool is_signed)
405*61046927SAndroid Build Coastguard Worker{
406*61046927SAndroid Build Coastguard Worker   bitmask_t field, mask;
407*61046927SAndroid Build Coastguard Worker
408*61046927SAndroid Build Coastguard Worker   if (is_signed) {
409*61046927SAndroid Build Coastguard Worker      /* NOTE: Don't assume val is already sign-extended to 64b,
410*61046927SAndroid Build Coastguard Worker       * just check that the bits above the valid range are either
411*61046927SAndroid Build Coastguard Worker       * all zero or all one:
412*61046927SAndroid Build Coastguard Worker       */
413*61046927SAndroid Build Coastguard Worker      assert(!(( val & ~BITFIELD64_MASK(1 + high - low)) &&
414*61046927SAndroid Build Coastguard Worker               (~val & ~BITFIELD64_MASK(1 + high - low))));
415*61046927SAndroid Build Coastguard Worker   } else {
416*61046927SAndroid Build Coastguard Worker      assert(!(val & ~BITFIELD64_MASK(1 + high - low)));
417*61046927SAndroid Build Coastguard Worker   }
418*61046927SAndroid Build Coastguard Worker
419*61046927SAndroid Build Coastguard Worker   BITSET_ZERO(field.bitset);
420*61046927SAndroid Build Coastguard Worker
421*61046927SAndroid Build Coastguard Worker   if (!val)
422*61046927SAndroid Build Coastguard Worker      return field;
423*61046927SAndroid Build Coastguard Worker
424*61046927SAndroid Build Coastguard Worker   BITSET_ZERO(mask.bitset);
425*61046927SAndroid Build Coastguard Worker   BITSET_SET_RANGE(mask.bitset, 0, high - low);
426*61046927SAndroid Build Coastguard Worker
427*61046927SAndroid Build Coastguard Worker   field = uint64_t_to_bitmask(val);
428*61046927SAndroid Build Coastguard Worker   BITSET_AND(field.bitset, field.bitset, mask.bitset);
429*61046927SAndroid Build Coastguard Worker   BITSET_SHL(field.bitset, low);
430*61046927SAndroid Build Coastguard Worker
431*61046927SAndroid Build Coastguard Worker   return field;
432*61046927SAndroid Build Coastguard Worker}
433*61046927SAndroid Build Coastguard Worker
434*61046927SAndroid Build Coastguard Worker/*
435*61046927SAndroid Build Coastguard Worker * Forward-declarations (so we don't have to figure out which order to
436*61046927SAndroid Build Coastguard Worker * emit various encoders when they have reference each other)
437*61046927SAndroid Build Coastguard Worker */
438*61046927SAndroid Build Coastguard Worker
439*61046927SAndroid Build Coastguard Worker%for root in s.encode_roots():
440*61046927SAndroid Build Coastguard Workerstatic bitmask_t encode${root.get_c_name()}(struct encode_state *s, const struct bitset_params *p, const ${root.encode.type} src);
441*61046927SAndroid Build Coastguard Worker%endfor
442*61046927SAndroid Build Coastguard Worker
443*61046927SAndroid Build Coastguard Worker## TODO before the expr evaluators, we should generate extract_FOO() for
444*61046927SAndroid Build Coastguard Worker## derived fields.. which probably also need to be in the context of the
445*61046927SAndroid Build Coastguard Worker## respective root so they take the correct src arg??
446*61046927SAndroid Build Coastguard Worker
447*61046927SAndroid Build Coastguard Worker/*
448*61046927SAndroid Build Coastguard Worker * Expression evaluators:
449*61046927SAndroid Build Coastguard Worker */
450*61046927SAndroid Build Coastguard Worker
451*61046927SAndroid Build Coastguard Workerstruct bitset_params {
452*61046927SAndroid Build Coastguard Worker%for name in s.unique_param_names():
453*61046927SAndroid Build Coastguard Worker   int64_t ${name};
454*61046927SAndroid Build Coastguard Worker%endfor
455*61046927SAndroid Build Coastguard Worker};
456*61046927SAndroid Build Coastguard Worker
457*61046927SAndroid Build Coastguard Worker## TODO can we share this def between the two templates somehow?
458*61046927SAndroid Build Coastguard Worker<%def name="encode_params(leaf, field)">
459*61046927SAndroid Build Coastguard Worker struct bitset_params bp = {
460*61046927SAndroid Build Coastguard Worker%for param in field.params:
461*61046927SAndroid Build Coastguard Worker    .${param[1]} = ${s.expr_extractor(leaf, param[0], 'p')},  /* ${param[0]} */
462*61046927SAndroid Build Coastguard Worker%endfor
463*61046927SAndroid Build Coastguard Worker };
464*61046927SAndroid Build Coastguard Worker</%def>
465*61046927SAndroid Build Coastguard Worker
466*61046927SAndroid Build Coastguard Worker<%def name="render_expr(leaf, expr)">
467*61046927SAndroid Build Coastguard Workerstatic inline int64_t
468*61046927SAndroid Build Coastguard Worker${s.expr_name(leaf.get_root(), expr)}(struct encode_state *s, const struct bitset_params *p, const ${leaf.get_root().encode.type} src)
469*61046927SAndroid Build Coastguard Worker{
470*61046927SAndroid Build Coastguard Worker%   for fieldname in expr.fieldnames:
471*61046927SAndroid Build Coastguard Worker    int64_t ${fieldname};
472*61046927SAndroid Build Coastguard Worker%   endfor
473*61046927SAndroid Build Coastguard Worker%   for fieldname in expr.fieldnames:
474*61046927SAndroid Build Coastguard Worker<% field = s.resolve_simple_field(leaf, fieldname) %>
475*61046927SAndroid Build Coastguard Worker%      if field is not None and field.get_c_typename() == 'TYPE_BITSET':
476*61046927SAndroid Build Coastguard Worker          { ${encode_params(leaf, field)}
477*61046927SAndroid Build Coastguard Worker          const bitmask_t tmp = ${s.expr_extractor(leaf, fieldname, '&bp')};
478*61046927SAndroid Build Coastguard Worker          ${fieldname} = bitmask_to_uint64_t(tmp);
479*61046927SAndroid Build Coastguard Worker          }
480*61046927SAndroid Build Coastguard Worker%      else:
481*61046927SAndroid Build Coastguard Worker          ${fieldname} = ${s.expr_extractor(leaf, fieldname, 'p')};
482*61046927SAndroid Build Coastguard Worker%      endif
483*61046927SAndroid Build Coastguard Worker%   endfor
484*61046927SAndroid Build Coastguard Worker    return ${expr.expr};
485*61046927SAndroid Build Coastguard Worker}
486*61046927SAndroid Build Coastguard Worker</%def>
487*61046927SAndroid Build Coastguard Worker
488*61046927SAndroid Build Coastguard Worker## note, we can't just iterate all the expressions, but we need to find
489*61046927SAndroid Build Coastguard Worker## the context in which they are used to know the correct src type
490*61046927SAndroid Build Coastguard Worker
491*61046927SAndroid Build Coastguard Worker%for root in s.encode_roots():
492*61046927SAndroid Build Coastguard Worker%   for leaf in s.encode_leafs(root):
493*61046927SAndroid Build Coastguard Worker%      for expr in s.bitset_used_exprs(leaf):
494*61046927SAndroid Build Coastguard Workerstatic inline int64_t ${s.expr_name(leaf.get_root(), expr)}(struct encode_state *s, const struct bitset_params *p, const ${leaf.get_root().encode.type} src);
495*61046927SAndroid Build Coastguard Worker%      endfor
496*61046927SAndroid Build Coastguard Worker%   endfor
497*61046927SAndroid Build Coastguard Worker%endfor
498*61046927SAndroid Build Coastguard Worker
499*61046927SAndroid Build Coastguard Worker%for root in s.encode_roots():
500*61046927SAndroid Build Coastguard Worker<%
501*61046927SAndroid Build Coastguard Worker    rendered_exprs = []
502*61046927SAndroid Build Coastguard Worker%>
503*61046927SAndroid Build Coastguard Worker%   for leaf in s.encode_leafs(root):
504*61046927SAndroid Build Coastguard Worker%      for expr in s.bitset_used_exprs(leaf):
505*61046927SAndroid Build Coastguard Worker<%
506*61046927SAndroid Build Coastguard Worker          if expr in rendered_exprs:
507*61046927SAndroid Build Coastguard Worker             continue
508*61046927SAndroid Build Coastguard Worker          rendered_exprs.append(expr)
509*61046927SAndroid Build Coastguard Worker%>
510*61046927SAndroid Build Coastguard Worker          ${render_expr(leaf, expr)}
511*61046927SAndroid Build Coastguard Worker%      endfor
512*61046927SAndroid Build Coastguard Worker%   endfor
513*61046927SAndroid Build Coastguard Worker%endfor
514*61046927SAndroid Build Coastguard Worker
515*61046927SAndroid Build Coastguard Worker
516*61046927SAndroid Build Coastguard Worker/*
517*61046927SAndroid Build Coastguard Worker * The actual encoder definitions
518*61046927SAndroid Build Coastguard Worker */
519*61046927SAndroid Build Coastguard Worker
520*61046927SAndroid Build Coastguard Worker%for root in s.encode_roots():
521*61046927SAndroid Build Coastguard Worker%   for leaf in s.encode_leafs(root):
522*61046927SAndroid Build Coastguard Worker<% snippet = encode_bitset.render(s=s, root=root, leaf=leaf) %>
523*61046927SAndroid Build Coastguard Worker%      if snippet not in root.snippets.keys():
524*61046927SAndroid Build Coastguard Worker<% snippet_name = "snippet" + root.get_c_name() + "_" + str(len(root.snippets)) %>
525*61046927SAndroid Build Coastguard Workerstatic bitmask_t
526*61046927SAndroid Build Coastguard Worker${snippet_name}(struct encode_state *s, const struct bitset_params *p, const ${root.encode.type} src)
527*61046927SAndroid Build Coastguard Worker{
528*61046927SAndroid Build Coastguard Worker   bitmask_t val = uint64_t_to_bitmask(0);
529*61046927SAndroid Build Coastguard Worker${snippet}
530*61046927SAndroid Build Coastguard Worker   return val;
531*61046927SAndroid Build Coastguard Worker}
532*61046927SAndroid Build Coastguard Worker<% root.snippets[snippet] = snippet_name %>
533*61046927SAndroid Build Coastguard Worker%      endif
534*61046927SAndroid Build Coastguard Worker%   endfor
535*61046927SAndroid Build Coastguard Worker
536*61046927SAndroid Build Coastguard Workerstatic bitmask_t
537*61046927SAndroid Build Coastguard Workerencode${root.get_c_name()}(struct encode_state *s, const struct bitset_params *p, const ${root.encode.type} src)
538*61046927SAndroid Build Coastguard Worker{
539*61046927SAndroid Build Coastguard Worker%   if root.encode.case_prefix is not None:
540*61046927SAndroid Build Coastguard Worker   switch (${root.get_c_name()}_case(s, src)) {
541*61046927SAndroid Build Coastguard Worker%      for leafs in s.encode_leaf_groups(root):
542*61046927SAndroid Build Coastguard Worker   case ${s.case_name(root, leafs[0].name)}: {
543*61046927SAndroid Build Coastguard Worker%         for leaf in leafs:
544*61046927SAndroid Build Coastguard Worker%           if leaf.has_gen_restriction():
545*61046927SAndroid Build Coastguard Worker      if (s->gen >= ${leaf.gen_min} && s->gen <= ${leaf.gen_max}) {
546*61046927SAndroid Build Coastguard Worker%           endif
547*61046927SAndroid Build Coastguard Worker<% snippet = encode_bitset.render(s=s, root=root, leaf=leaf) %>
548*61046927SAndroid Build Coastguard Worker<%    words = isa.split_bits((leaf.get_pattern().match), 64) %>
549*61046927SAndroid Build Coastguard Worker      bitmask_t val = uint64_t_to_bitmask(${words[-1]});
550*61046927SAndroid Build Coastguard Worker
551*61046927SAndroid Build Coastguard Worker<%    words.pop() %>
552*61046927SAndroid Build Coastguard Worker
553*61046927SAndroid Build Coastguard Worker%     for x in reversed(range(len(words))):
554*61046927SAndroid Build Coastguard Worker      {
555*61046927SAndroid Build Coastguard Worker         bitmask_t word = uint64_t_to_bitmask(${words[x]});
556*61046927SAndroid Build Coastguard Worker         BITSET_SHL(val.bitset, 64);
557*61046927SAndroid Build Coastguard Worker         BITSET_OR(val.bitset, val.bitset, word.bitset);
558*61046927SAndroid Build Coastguard Worker      }
559*61046927SAndroid Build Coastguard Worker%     endfor
560*61046927SAndroid Build Coastguard Worker
561*61046927SAndroid Build Coastguard Worker      BITSET_OR(val.bitset, val.bitset, ${root.snippets[snippet]}(s, p, src).bitset);
562*61046927SAndroid Build Coastguard Worker      return val;
563*61046927SAndroid Build Coastguard Worker%           if leaf.has_gen_restriction():
564*61046927SAndroid Build Coastguard Worker      }
565*61046927SAndroid Build Coastguard Worker%           endif
566*61046927SAndroid Build Coastguard Worker%         endfor
567*61046927SAndroid Build Coastguard Worker%         if leaf.has_gen_restriction():
568*61046927SAndroid Build Coastguard Worker      break;
569*61046927SAndroid Build Coastguard Worker%         endif
570*61046927SAndroid Build Coastguard Worker    }
571*61046927SAndroid Build Coastguard Worker%      endfor
572*61046927SAndroid Build Coastguard Worker   default:
573*61046927SAndroid Build Coastguard Worker      /* Note that we need the default case, because there are
574*61046927SAndroid Build Coastguard Worker       * instructions which we never expect to be encoded, (ie.
575*61046927SAndroid Build Coastguard Worker       * meta/macro instructions) as they are removed/replace
576*61046927SAndroid Build Coastguard Worker       * in earlier stages of the compiler.
577*61046927SAndroid Build Coastguard Worker       */
578*61046927SAndroid Build Coastguard Worker      break;
579*61046927SAndroid Build Coastguard Worker   }
580*61046927SAndroid Build Coastguard Worker   mesa_loge("Unhandled ${root.name} encode case: 0x%x\\n", ${root.get_c_name()}_case(s, src));
581*61046927SAndroid Build Coastguard Worker   return uint64_t_to_bitmask(0);
582*61046927SAndroid Build Coastguard Worker%   else: # single case bitset, no switch
583*61046927SAndroid Build Coastguard Worker%      for leaf in s.encode_leafs(root):
584*61046927SAndroid Build Coastguard Worker<% snippet = encode_bitset.render(s=s, root=root, leaf=leaf) %>
585*61046927SAndroid Build Coastguard Worker      bitmask_t val = uint64_t_to_bitmask(${hex(leaf.get_pattern().match)});
586*61046927SAndroid Build Coastguard Worker      BITSET_OR(val.bitset, val.bitset, ${root.snippets[snippet]}(s, p, src).bitset);
587*61046927SAndroid Build Coastguard Worker      return val;
588*61046927SAndroid Build Coastguard Worker%      endfor
589*61046927SAndroid Build Coastguard Worker%   endif
590*61046927SAndroid Build Coastguard Worker}
591*61046927SAndroid Build Coastguard Worker%endfor
592*61046927SAndroid Build Coastguard Worker"""
593*61046927SAndroid Build Coastguard Worker
594*61046927SAndroid Build Coastguard Workerencode_bitset_template = """
595*61046927SAndroid Build Coastguard Worker<%
596*61046927SAndroid Build Coastguard Workerisa = s.isa
597*61046927SAndroid Build Coastguard Worker%>
598*61046927SAndroid Build Coastguard Worker
599*61046927SAndroid Build Coastguard Worker<%def name="case_pre(root, expr)">
600*61046927SAndroid Build Coastguard Worker%if expr is not None:
601*61046927SAndroid Build Coastguard Worker    if (${s.expr_name(root, expr)}(s, p, src)) {
602*61046927SAndroid Build Coastguard Worker%else:
603*61046927SAndroid Build Coastguard Worker    {
604*61046927SAndroid Build Coastguard Worker%endif
605*61046927SAndroid Build Coastguard Worker</%def>
606*61046927SAndroid Build Coastguard Worker
607*61046927SAndroid Build Coastguard Worker<%def name="case_post(root, expr)">
608*61046927SAndroid Build Coastguard Worker%if expr is not None:
609*61046927SAndroid Build Coastguard Worker    } else
610*61046927SAndroid Build Coastguard Worker%else:
611*61046927SAndroid Build Coastguard Worker    }
612*61046927SAndroid Build Coastguard Worker%endif
613*61046927SAndroid Build Coastguard Worker</%def>
614*61046927SAndroid Build Coastguard Worker
615*61046927SAndroid Build Coastguard Worker<%def name="encode_params(leaf, field)">
616*61046927SAndroid Build Coastguard Worker struct bitset_params bp = {
617*61046927SAndroid Build Coastguard Worker%for param in field.params:
618*61046927SAndroid Build Coastguard Worker    .${param[1]} = ${s.expr_extractor(leaf, param[0], 'p')},  /* ${param[0]} */
619*61046927SAndroid Build Coastguard Worker%endfor
620*61046927SAndroid Build Coastguard Worker };
621*61046927SAndroid Build Coastguard Worker</%def>
622*61046927SAndroid Build Coastguard Worker
623*61046927SAndroid Build Coastguard Worker      uint64_t fld;
624*61046927SAndroid Build Coastguard Worker
625*61046927SAndroid Build Coastguard Worker      (void)fld;
626*61046927SAndroid Build Coastguard Worker<% visited_exprs = [] %>
627*61046927SAndroid Build Coastguard Worker%for case in s.bitset_cases(leaf):
628*61046927SAndroid Build Coastguard Worker<%
629*61046927SAndroid Build Coastguard Worker    if case.expr is not None:
630*61046927SAndroid Build Coastguard Worker        visited_exprs.append(case.expr)
631*61046927SAndroid Build Coastguard Worker
632*61046927SAndroid Build Coastguard Worker    # per-expression-case track display-field-names that we have
633*61046927SAndroid Build Coastguard Worker    # already emitted encoding for.  It is possible that an
634*61046927SAndroid Build Coastguard Worker    # <override> case overrides a given field (for ex. #cat5-src3)
635*61046927SAndroid Build Coastguard Worker    # and we don't want to emit encoding for both the override and
636*61046927SAndroid Build Coastguard Worker    # the fallback
637*61046927SAndroid Build Coastguard Worker    seen_fields = {}
638*61046927SAndroid Build Coastguard Worker%>
639*61046927SAndroid Build Coastguard Worker    ${case_pre(root, case.expr)}
640*61046927SAndroid Build Coastguard Worker%   for df in case.display_fields():
641*61046927SAndroid Build Coastguard Worker%       for f in df.fields():
642*61046927SAndroid Build Coastguard Worker<%
643*61046927SAndroid Build Coastguard Worker          # simplify the control flow a bit to give the compiler a bit
644*61046927SAndroid Build Coastguard Worker          # less to clean up
645*61046927SAndroid Build Coastguard Worker          expr = f.expr
646*61046927SAndroid Build Coastguard Worker          if expr == case.expr:
647*61046927SAndroid Build Coastguard Worker              # Don't need to evaluate the same condition twice:
648*61046927SAndroid Build Coastguard Worker              expr = None
649*61046927SAndroid Build Coastguard Worker          elif expr in visited_exprs:
650*61046927SAndroid Build Coastguard Worker              # We are in an 'else'/'else-if' leg that we wouldn't
651*61046927SAndroid Build Coastguard Worker              # go down due to passing an earlier if()
652*61046927SAndroid Build Coastguard Worker              continue
653*61046927SAndroid Build Coastguard Worker
654*61046927SAndroid Build Coastguard Worker          if not expr in seen_fields.keys():
655*61046927SAndroid Build Coastguard Worker              seen_fields[expr] = []
656*61046927SAndroid Build Coastguard Worker
657*61046927SAndroid Build Coastguard Worker          if f.field.name in seen_fields[expr]:
658*61046927SAndroid Build Coastguard Worker              continue
659*61046927SAndroid Build Coastguard Worker          seen_fields[expr].append(f.field.name)
660*61046927SAndroid Build Coastguard Worker%>
661*61046927SAndroid Build Coastguard Worker           ${case_pre(root, expr)}
662*61046927SAndroid Build Coastguard Worker%         if f.field.get_c_typename() == 'TYPE_BITSET':
663*61046927SAndroid Build Coastguard Worker             { ${encode_params(leaf, f.field)}
664*61046927SAndroid Build Coastguard Worker               bitmask_t tmp = encode${isa.roots[f.field.type].get_c_name()}(s, &bp, ${s.extractor(leaf, f.field.name)});
665*61046927SAndroid Build Coastguard Worker               fld = bitmask_to_uint64_t(tmp);
666*61046927SAndroid Build Coastguard Worker             }
667*61046927SAndroid Build Coastguard Worker%         else:
668*61046927SAndroid Build Coastguard Worker             fld = ${s.extractor(leaf, f.field.name)};
669*61046927SAndroid Build Coastguard Worker%         endif
670*61046927SAndroid Build Coastguard Worker             const bitmask_t packed = pack_field(${f.field.low}, ${f.field.high}, fld, ${f.signed()});  /* ${f.field.name} */
671*61046927SAndroid Build Coastguard Worker             BITSET_OR(val.bitset, val.bitset, packed.bitset);
672*61046927SAndroid Build Coastguard Worker             ${case_post(root, expr)}
673*61046927SAndroid Build Coastguard Worker%       endfor
674*61046927SAndroid Build Coastguard Worker%   endfor
675*61046927SAndroid Build Coastguard Worker
676*61046927SAndroid Build Coastguard Worker%   for f in case.assert_cases():
677*61046927SAndroid Build Coastguard Worker<%
678*61046927SAndroid Build Coastguard Worker      # simplify the control flow a bit to give the compiler a bit
679*61046927SAndroid Build Coastguard Worker      # less to clean up
680*61046927SAndroid Build Coastguard Worker      expr = f.expr
681*61046927SAndroid Build Coastguard Worker      if expr == case.expr:
682*61046927SAndroid Build Coastguard Worker          # Don't need to evaluate the same condition twice:
683*61046927SAndroid Build Coastguard Worker          expr = None
684*61046927SAndroid Build Coastguard Worker      elif expr in visited_exprs:
685*61046927SAndroid Build Coastguard Worker          # We are in an 'else'/'else-if' leg that we wouldn't
686*61046927SAndroid Build Coastguard Worker          # go down due to passing an earlier if()
687*61046927SAndroid Build Coastguard Worker          continue
688*61046927SAndroid Build Coastguard Worker%>
689*61046927SAndroid Build Coastguard Worker       ${case_pre(root, expr)}
690*61046927SAndroid Build Coastguard Worker       const bitmask_t packed = pack_field(${f.field.low}, ${f.field.high}, ${f.field.val}, ${f.signed()});
691*61046927SAndroid Build Coastguard Worker       BITSET_OR(val.bitset, val.bitset, packed.bitset);
692*61046927SAndroid Build Coastguard Worker       ${case_post(root, None)}
693*61046927SAndroid Build Coastguard Worker%   endfor
694*61046927SAndroid Build Coastguard Worker      {}  /* in case no unconditional field to close out last '} else' */
695*61046927SAndroid Build Coastguard Worker    ${case_post(root, case.expr)}
696*61046927SAndroid Build Coastguard Worker%endfor
697*61046927SAndroid Build Coastguard Worker"""
698*61046927SAndroid Build Coastguard Worker
699*61046927SAndroid Build Coastguard Workerdef main():
700*61046927SAndroid Build Coastguard Worker    parser = argparse.ArgumentParser()
701*61046927SAndroid Build Coastguard Worker    parser.add_argument('--xml', required=True, help='isaspec XML file.')
702*61046927SAndroid Build Coastguard Worker    parser.add_argument('--out-h', required=True, help='Output H file.')
703*61046927SAndroid Build Coastguard Worker    args = parser.parse_args()
704*61046927SAndroid Build Coastguard Worker
705*61046927SAndroid Build Coastguard Worker    isa = ISA(args.xml)
706*61046927SAndroid Build Coastguard Worker    s = State(isa)
707*61046927SAndroid Build Coastguard Worker
708*61046927SAndroid Build Coastguard Worker    try:
709*61046927SAndroid Build Coastguard Worker        with open(args.out_h, 'w', encoding='utf-8') as f:
710*61046927SAndroid Build Coastguard Worker            encode_bitset = Template(encode_bitset_template)
711*61046927SAndroid Build Coastguard Worker            f.write(Template(template).render(s=s, encode_bitset=encode_bitset))
712*61046927SAndroid Build Coastguard Worker
713*61046927SAndroid Build Coastguard Worker    except Exception:
714*61046927SAndroid Build Coastguard Worker        # In the event there's an error, this imports some helpers from mako
715*61046927SAndroid Build Coastguard Worker        # to print a useful stack trace and prints it, then exits with
716*61046927SAndroid Build Coastguard Worker        # status 1, if python is run with debug; otherwise it just raises
717*61046927SAndroid Build Coastguard Worker        # the exception
718*61046927SAndroid Build Coastguard Worker        import sys
719*61046927SAndroid Build Coastguard Worker        from mako import exceptions
720*61046927SAndroid Build Coastguard Worker        print(exceptions.text_error_template().render(), file=sys.stderr)
721*61046927SAndroid Build Coastguard Worker        sys.exit(1)
722*61046927SAndroid Build Coastguard Worker
723*61046927SAndroid Build Coastguard Workerif __name__ == '__main__':
724*61046927SAndroid Build Coastguard Worker    main()
725