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