17ec681f3Smrg#!/usr/bin/env python3 27ec681f3Smrg# 37ec681f3Smrg# Copyright © 2020 Google, Inc. 47ec681f3Smrg# 57ec681f3Smrg# Permission is hereby granted, free of charge, to any person obtaining a 67ec681f3Smrg# copy of this software and associated documentation files (the "Software"), 77ec681f3Smrg# to deal in the Software without restriction, including without limitation 87ec681f3Smrg# the rights to use, copy, modify, merge, publish, distribute, sublicense, 97ec681f3Smrg# and/or sell copies of the Software, and to permit persons to whom the 107ec681f3Smrg# Software is furnished to do so, subject to the following conditions: 117ec681f3Smrg# 127ec681f3Smrg# The above copyright notice and this permission notice (including the next 137ec681f3Smrg# paragraph) shall be included in all copies or substantial portions of the 147ec681f3Smrg# Software. 157ec681f3Smrg# 167ec681f3Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 177ec681f3Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 187ec681f3Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 197ec681f3Smrg# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 207ec681f3Smrg# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 217ec681f3Smrg# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 227ec681f3Smrg# IN THE SOFTWARE. 237ec681f3Smrg 247ec681f3Smrgfrom mako.template import Template 257ec681f3Smrgfrom isa import ISA, BitSetDerivedField, BitSetAssertField 267ec681f3Smrgimport sys 277ec681f3Smrgimport re 287ec681f3Smrg 297ec681f3Smrg# Encoding is driven by the display template that would be used 307ec681f3Smrg# to decode any given instruction, essentially working backwards 317ec681f3Smrg# from the decode case. (Or put another way, the decoded bitset 327ec681f3Smrg# should contain enough information to re-encode it again.) 337ec681f3Smrg# 347ec681f3Smrg# In the xml, we can have multiple override cases per bitset, 357ec681f3Smrg# which can override display template and/or fields. Iterating 367ec681f3Smrg# all this from within the template is messy, so use helpers 377ec681f3Smrg# outside of the template for this. 387ec681f3Smrg# 397ec681f3Smrg# The hierarchy of iterators for encoding is: 407ec681f3Smrg# 417ec681f3Smrg# // First level - Case() (s.bitset_cases() iterator) 427ec681f3Smrg# if (caseA.expression()) { // maps to <override/> in xml 437ec681f3Smrg# // Second level - DisplayField() (case.display_fields() iterator) 447ec681f3Smrg# ... encode field A ... 457ec681f3Smrg# ... encode field B ... 467ec681f3Smrg# 477ec681f3Smrg# // Third level - each display field can be potentially resolved 487ec681f3Smrg# // by multiple different overrides, you can end up with 497ec681f3Smrg# // an if/else ladder for an individual display field 507ec681f3Smrg# if (field_c_case1.expression()) { 517ec681f3Smrg# ... encode field C ... 527ec681f3Smrg# } else if (field_c_case2.expression() { 537ec681f3Smrg# ... encode field C ... 547ec681f3Smrg# } else { 557ec681f3Smrg# } 567ec681f3Smrg# 577ec681f3Smrg# } else if (caseB.expression())( 587ec681f3Smrg# } else { // maps to the default case in bitset, ie. outside <override/> 597ec681f3Smrg# } 607ec681f3Smrg 617ec681f3Smrg 627ec681f3Smrg# Represents a concrete field, ie. a field can be overriden 637ec681f3Smrg# by an override, so the exact choice to encode a given field 647ec681f3Smrg# in a bitset may be conditional 657ec681f3Smrgclass FieldCase(object): 667ec681f3Smrg def __init__(self, field, case): 677ec681f3Smrg self.field = field 687ec681f3Smrg self.expr = None 697ec681f3Smrg if case.expr is not None: 707ec681f3Smrg self.expr = isa.expressions[case.expr] 717ec681f3Smrg 727ec681f3Smrgclass AssertField(object): 737ec681f3Smrg def __init__(self, field, case): 747ec681f3Smrg self.field = field 757ec681f3Smrg self.expr = None 767ec681f3Smrg if case.expr is not None: 777ec681f3Smrg self.expr = isa.expressions[case.expr] 787ec681f3Smrg 797ec681f3Smrg# Represents a field to be encoded: 807ec681f3Smrgclass DisplayField(object): 817ec681f3Smrg def __init__(self, bitset, case, name): 827ec681f3Smrg self.bitset = bitset # leaf bitset 837ec681f3Smrg self.case = case 847ec681f3Smrg self.name = name 857ec681f3Smrg 867ec681f3Smrg def fields(self, bitset=None): 877ec681f3Smrg if bitset is None: 887ec681f3Smrg bitset = self.bitset 897ec681f3Smrg # resolving the various cases for encoding a given 907ec681f3Smrg # field is similar to resolving the display template 917ec681f3Smrg # string 927ec681f3Smrg for case in bitset.cases: 937ec681f3Smrg if case.expr is not None: 947ec681f3Smrg expr = bitset.isa.expressions[case.expr] 957ec681f3Smrg self.case.append_expr_fields(expr) 967ec681f3Smrg if self.name in case.fields: 977ec681f3Smrg field = case.fields[self.name] 987ec681f3Smrg # For bitset fields, the bitset type could reference 997ec681f3Smrg # fields in this (the containing) bitset, in addition 1007ec681f3Smrg # to the ones which are directly used to encode the 1017ec681f3Smrg # field itself. 1027ec681f3Smrg if field.get_c_typename() == 'TYPE_BITSET': 1037ec681f3Smrg for param in field.params: 1047ec681f3Smrg self.case.append_field(param[0]) 1057ec681f3Smrg # For derived fields, we want to consider any other 1067ec681f3Smrg # fields that are referenced by the expr 1077ec681f3Smrg if isinstance(field, BitSetDerivedField): 1087ec681f3Smrg expr = bitset.isa.expressions[field.expr] 1097ec681f3Smrg self.case.append_expr_fields(expr) 1107ec681f3Smrg elif not isinstance(field, BitSetAssertField): 1117ec681f3Smrg yield FieldCase(field, case) 1127ec681f3Smrg # if we've found an unconditional case specifying 1137ec681f3Smrg # the named field, we are done 1147ec681f3Smrg if case.expr is None: 1157ec681f3Smrg return 1167ec681f3Smrg if bitset.extends is not None: 1177ec681f3Smrg yield from self.fields(isa.bitsets[bitset.extends]) 1187ec681f3Smrg 1197ec681f3Smrg# Represents an if/else case in bitset encoding which has a display 1207ec681f3Smrg# template string: 1217ec681f3Smrgclass Case(object): 1227ec681f3Smrg def __init__(self, bitset, case): 1237ec681f3Smrg self.bitset = bitset # leaf bitset 1247ec681f3Smrg self.case = case 1257ec681f3Smrg self.expr = None 1267ec681f3Smrg if case.expr is not None: 1277ec681f3Smrg self.expr = isa.expressions[case.expr] 1287ec681f3Smrg self.fieldnames = re.findall(r"{([a-zA-Z0-9_]+)}", case.display) 1297ec681f3Smrg self.append_forced(bitset) 1307ec681f3Smrg 1317ec681f3Smrg # Handle fields which don't appear in display template but have 1327ec681f3Smrg # force="true" 1337ec681f3Smrg def append_forced(self, bitset): 1347ec681f3Smrg if bitset.encode is not None: 1357ec681f3Smrg for name, val in bitset.encode.forced.items(): 1367ec681f3Smrg self.append_field(name) 1377ec681f3Smrg if bitset.extends is not None: 1387ec681f3Smrg self.append_forced(isa.bitsets[bitset.extends]) 1397ec681f3Smrg 1407ec681f3Smrg # In the process of resolving a field, we might discover additional 1417ec681f3Smrg # fields that need resolving: 1427ec681f3Smrg # 1437ec681f3Smrg # a) a derived field which maps to one or more other concrete fields 1447ec681f3Smrg # b) a bitset field, which may be "parameterized".. for example a 1457ec681f3Smrg # #multisrc field which refers back to SRC1_R/SRC2_R outside of 1467ec681f3Smrg # the range of bits covered by the #multisrc field itself 1477ec681f3Smrg def append_field(self, fieldname): 1487ec681f3Smrg if fieldname not in self.fieldnames: 1497ec681f3Smrg self.fieldnames.append(fieldname) 1507ec681f3Smrg 1517ec681f3Smrg def append_expr_fields(self, expr): 1527ec681f3Smrg for fieldname in expr.fieldnames: 1537ec681f3Smrg self.append_field(fieldname) 1547ec681f3Smrg 1557ec681f3Smrg def display_fields(self): 1567ec681f3Smrg for fieldname in self.fieldnames: 1577ec681f3Smrg yield DisplayField(self.bitset, self, fieldname) 1587ec681f3Smrg 1597ec681f3Smrg def assert_cases(self, bitset=None): 1607ec681f3Smrg if bitset is None: 1617ec681f3Smrg bitset = self.bitset 1627ec681f3Smrg for case in bitset.cases: 1637ec681f3Smrg for name, field in case.fields.items(): 1647ec681f3Smrg if field.get_c_typename() == 'TYPE_ASSERT': 1657ec681f3Smrg yield AssertField(field, case) 1667ec681f3Smrg if bitset.extends is not None: 1677ec681f3Smrg yield from self.assert_cases(isa.bitsets[bitset.extends]) 1687ec681f3Smrg 1697ec681f3Smrg# State and helpers used by the template: 1707ec681f3Smrgclass State(object): 1717ec681f3Smrg def __init__(self, isa): 1727ec681f3Smrg self.isa = isa 1737ec681f3Smrg self.warned_missing_extractors = [] 1747ec681f3Smrg 1757ec681f3Smrg def bitset_cases(self, bitset, leaf_bitset=None): 1767ec681f3Smrg if leaf_bitset is None: 1777ec681f3Smrg leaf_bitset = bitset; 1787ec681f3Smrg for case in bitset.cases: 1797ec681f3Smrg if case.display is None: 1807ec681f3Smrg # if this is the last case (ie. case.expr is None) 1817ec681f3Smrg # then we need to go up the inheritance chain: 1827ec681f3Smrg if case.expr is None and bitset.extends is not None: 1837ec681f3Smrg parent_bitset = isa.bitsets[bitset.extends] 1847ec681f3Smrg yield from self.bitset_cases(parent_bitset, leaf_bitset) 1857ec681f3Smrg continue; 1867ec681f3Smrg yield Case(leaf_bitset, case) 1877ec681f3Smrg 1887ec681f3Smrg # Find unique bitset remap/parameter names, to generate a struct 1897ec681f3Smrg # used to pass "parameters" to bitset fields: 1907ec681f3Smrg def unique_param_names(self): 1917ec681f3Smrg unique_names = [] 1927ec681f3Smrg for root in self.encode_roots(): 1937ec681f3Smrg for leaf in self.encode_leafs(root): 1947ec681f3Smrg for case in s.bitset_cases(leaf): 1957ec681f3Smrg for df in case.display_fields(): 1967ec681f3Smrg for f in df.fields(): 1977ec681f3Smrg if f.field.get_c_typename() == 'TYPE_BITSET': 1987ec681f3Smrg for param in f.field.params: 1997ec681f3Smrg target_name = param[1] 2007ec681f3Smrg if target_name not in unique_names: 2017ec681f3Smrg yield target_name 2027ec681f3Smrg unique_names.append(target_name) 2037ec681f3Smrg 2047ec681f3Smrg def case_name(self, bitset, name): 2057ec681f3Smrg return bitset.encode.case_prefix + name.upper().replace('.', '_').replace('-', '_').replace('#', '') 2067ec681f3Smrg 2077ec681f3Smrg def encode_roots(self): 2087ec681f3Smrg for name, root in self.isa.roots.items(): 2097ec681f3Smrg if root.encode is None: 2107ec681f3Smrg continue 2117ec681f3Smrg yield root 2127ec681f3Smrg 2137ec681f3Smrg def encode_leafs(self, root): 2147ec681f3Smrg for name, leaf in self.isa.leafs.items(): 2157ec681f3Smrg if leaf.get_root() != root: 2167ec681f3Smrg continue 2177ec681f3Smrg yield leaf 2187ec681f3Smrg 2197ec681f3Smrg # expressions used in a bitset (case or field or recursively parent bitsets) 2207ec681f3Smrg def bitset_used_exprs(self, bitset): 2217ec681f3Smrg for case in bitset.cases: 2227ec681f3Smrg if case.expr: 2237ec681f3Smrg yield self.isa.expressions[case.expr] 2247ec681f3Smrg for name, field in case.fields.items(): 2257ec681f3Smrg if isinstance(field, BitSetDerivedField): 2267ec681f3Smrg yield self.isa.expressions[field.expr] 2277ec681f3Smrg if bitset.extends is not None: 2287ec681f3Smrg yield from self.bitset_used_exprs(self.isa.bitsets[bitset.extends]) 2297ec681f3Smrg 2307ec681f3Smrg def extractor_impl(self, bitset, name): 2317ec681f3Smrg if bitset.encode is not None: 2327ec681f3Smrg if name in bitset.encode.maps: 2337ec681f3Smrg return bitset.encode.maps[name] 2347ec681f3Smrg if bitset.extends is not None: 2357ec681f3Smrg return self.extractor_impl(self.isa.bitsets[bitset.extends], name) 2367ec681f3Smrg return None 2377ec681f3Smrg 2387ec681f3Smrg # Default fallback when no mapping is defined, simply to avoid 2397ec681f3Smrg # having to deal with encoding at the same time as r/e new 2407ec681f3Smrg # instruction decoding.. but we can at least print warnings: 2417ec681f3Smrg def extractor_fallback(self, bitset, name): 2427ec681f3Smrg extr_name = bitset.name + '.' + name 2437ec681f3Smrg if extr_name not in self.warned_missing_extractors: 2447ec681f3Smrg print('WARNING: no encode mapping for {}.{}'.format(bitset.name, name)) 2457ec681f3Smrg self.warned_missing_extractors.append(extr_name) 2467ec681f3Smrg return '0 /* XXX */' 2477ec681f3Smrg 2487ec681f3Smrg def extractor(self, bitset, name): 2497ec681f3Smrg extr = self.extractor_impl(bitset, name) 2507ec681f3Smrg if extr is not None: 2517ec681f3Smrg return extr 2527ec681f3Smrg return self.extractor_fallback(bitset, name) 2537ec681f3Smrg 2547ec681f3Smrg # In the special case of needing to access a field with bitset type 2557ec681f3Smrg # for an expr, we need to encode the field so we end up with an 2567ec681f3Smrg # integer, and not some pointer to a thing that will be encoded to 2577ec681f3Smrg # an integer 2587ec681f3Smrg def expr_extractor(self, bitset, name, p): 2597ec681f3Smrg extr = self.extractor_impl(bitset, name) 2607ec681f3Smrg field = self.resolve_simple_field(bitset, name) 2617ec681f3Smrg if isinstance(field, BitSetDerivedField): 2627ec681f3Smrg expr = self.isa.expressions[field.expr] 2637ec681f3Smrg return self.expr_name(bitset.get_root(), expr) + '(s, p, src)' 2647ec681f3Smrg if extr is None: 2657ec681f3Smrg if name in self.unique_param_names(): 2667ec681f3Smrg extr = 'p->' + name 2677ec681f3Smrg else: 2687ec681f3Smrg extr = self.extractor_fallback(bitset, name) 2697ec681f3Smrg if field and field.get_c_typename() == 'TYPE_BITSET': 2707ec681f3Smrg extr = 'encode' + isa.roots[field.type].get_c_name() + '(s, ' + p + ', ' + extr + ')' 2717ec681f3Smrg return extr 2727ec681f3Smrg 2737ec681f3Smrg # A limited resolver for field type which doesn't properly account for 2747ec681f3Smrg # overrides. In particular, if a field is defined differently in multiple 2757ec681f3Smrg # different cases, this just blindly picks the last one. 2767ec681f3Smrg # 2777ec681f3Smrg # TODO to do this properly, I don't think there is an alternative than 2787ec681f3Smrg # to emit code which evaluates the case.expr 2797ec681f3Smrg def resolve_simple_field(self, bitset, name): 2807ec681f3Smrg field = None 2817ec681f3Smrg for case in bitset.cases: 2827ec681f3Smrg if name in case.fields: 2837ec681f3Smrg field = case.fields[name] 2847ec681f3Smrg if field is not None: 2857ec681f3Smrg return field 2867ec681f3Smrg if bitset.extends is not None: 2877ec681f3Smrg return self.resolve_simple_field(isa.bitsets[bitset.extends], name) 2887ec681f3Smrg return None 2897ec681f3Smrg 2907ec681f3Smrg def encode_type(self, bitset): 2917ec681f3Smrg if bitset.encode is not None: 2927ec681f3Smrg if bitset.encode.type is not None: 2937ec681f3Smrg return bitset.encode.type 2947ec681f3Smrg if bitset.extends is not None: 2957ec681f3Smrg return self.encode_type(isa.bitsets[bitset.extends]) 2967ec681f3Smrg return None 2977ec681f3Smrg 2987ec681f3Smrg def expr_name(self, root, expr): 2997ec681f3Smrg return root.get_c_name() + '_' + expr.get_c_name() 3007ec681f3Smrg 3017ec681f3Smrgtemplate = """\ 3027ec681f3Smrg/* Copyright (C) 2020 Google, Inc. 3037ec681f3Smrg * 3047ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 3057ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 3067ec681f3Smrg * to deal in the Software without restriction, including without limitation 3077ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 3087ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the 3097ec681f3Smrg * Software is furnished to do so, subject to the following conditions: 3107ec681f3Smrg * 3117ec681f3Smrg * The above copyright notice and this permission notice (including the next 3127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the 3137ec681f3Smrg * Software. 3147ec681f3Smrg * 3157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 3167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 3177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 3187ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 3197ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 3207ec681f3Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 3217ec681f3Smrg * IN THE SOFTWARE. 3227ec681f3Smrg */ 3237ec681f3Smrg 3247ec681f3Smrg#include <stdbool.h> 3257ec681f3Smrg#include <stdint.h> 3267ec681f3Smrg#include <util/bitset.h> 3277ec681f3Smrg 3287ec681f3Smrg<% 3297ec681f3Smrgisa = s.isa 3307ec681f3Smrg%> 3317ec681f3Smrg 3327ec681f3Smrg#define BITMASK_WORDS BITSET_WORDS(${isa.bitsize}) 3337ec681f3Smrg 3347ec681f3Smrgtypedef struct { 3357ec681f3Smrg BITSET_WORD bitset[BITMASK_WORDS]; 3367ec681f3Smrg} bitmask_t; 3377ec681f3Smrg 3387ec681f3Smrgstatic inline uint64_t 3397ec681f3Smrgbitmask_to_uint64_t(bitmask_t mask) 3407ec681f3Smrg{ 3417ec681f3Smrg return ((uint64_t)mask.bitset[1] << 32) | mask.bitset[0]; 3427ec681f3Smrg} 3437ec681f3Smrg 3447ec681f3Smrgstatic inline bitmask_t 3457ec681f3Smrguint64_t_to_bitmask(uint64_t val) 3467ec681f3Smrg{ 3477ec681f3Smrg bitmask_t mask = { 3487ec681f3Smrg .bitset[0] = val & 0xffffffff, 3497ec681f3Smrg .bitset[1] = (val >> 32) & 0xffffffff, 3507ec681f3Smrg }; 3517ec681f3Smrg 3527ec681f3Smrg return mask; 3537ec681f3Smrg} 3547ec681f3Smrg 3557ec681f3Smrgstatic inline void 3567ec681f3Smrgstore_instruction(BITSET_WORD *dst, bitmask_t instr) 3577ec681f3Smrg{ 3587ec681f3Smrg% for i in range(0, int(isa.bitsize / 32)): 3597ec681f3Smrg *(dst + ${i}) = instr.bitset[${i}]; 3607ec681f3Smrg% endfor 3617ec681f3Smrg} 3627ec681f3Smrg 3637ec681f3Smrg/** 3647ec681f3Smrg * Opaque type from the PoV of generated code, but allows state to be passed 3657ec681f3Smrg * thru to the hand written helpers used by the generated code. 3667ec681f3Smrg */ 3677ec681f3Smrgstruct encode_state; 3687ec681f3Smrg 3697ec681f3Smrgstruct bitset_params; 3707ec681f3Smrg 3717ec681f3Smrgstatic bitmask_t 3727ec681f3Smrgpack_field(unsigned low, unsigned high, uint64_t val) 3737ec681f3Smrg{ 3747ec681f3Smrg bitmask_t field, mask; 3757ec681f3Smrg 3767ec681f3Smrg BITSET_ZERO(field.bitset); 3777ec681f3Smrg 3787ec681f3Smrg if (!val) 3797ec681f3Smrg return field; 3807ec681f3Smrg 3817ec681f3Smrg BITSET_ZERO(mask.bitset); 3827ec681f3Smrg BITSET_SET_RANGE(mask.bitset, 0, high - low); 3837ec681f3Smrg 3847ec681f3Smrg field = uint64_t_to_bitmask(val); 3857ec681f3Smrg BITSET_AND(field.bitset, field.bitset, mask.bitset); 3867ec681f3Smrg BITSET_SHL(field.bitset, low); 3877ec681f3Smrg 3887ec681f3Smrg return field; 3897ec681f3Smrg} 3907ec681f3Smrg 3917ec681f3Smrg/* 3927ec681f3Smrg * Forward-declarations (so we don't have to figure out which order to 3937ec681f3Smrg * emit various encoders when they have reference each other) 3947ec681f3Smrg */ 3957ec681f3Smrg 3967ec681f3Smrg%for root in s.encode_roots(): 3977ec681f3Smrgstatic bitmask_t encode${root.get_c_name()}(struct encode_state *s, struct bitset_params *p, ${root.encode.type} src); 3987ec681f3Smrg%endfor 3997ec681f3Smrg 4007ec681f3Smrg## TODO before the expr evaluators, we should generate extract_FOO() for 4017ec681f3Smrg## derived fields.. which probably also need to be in the context of the 4027ec681f3Smrg## respective root so they take the correct src arg?? 4037ec681f3Smrg 4047ec681f3Smrg/* 4057ec681f3Smrg * Expression evaluators: 4067ec681f3Smrg */ 4077ec681f3Smrg 4087ec681f3Smrgstruct bitset_params { 4097ec681f3Smrg%for name in s.unique_param_names(): 4107ec681f3Smrg int64_t ${name}; 4117ec681f3Smrg%endfor 4127ec681f3Smrg}; 4137ec681f3Smrg 4147ec681f3Smrg## TODO can we share this def between the two templates somehow? 4157ec681f3Smrg<%def name="encode_params(leaf, field)"> 4167ec681f3Smrg struct bitset_params bp = { 4177ec681f3Smrg%for param in field.params: 4187ec681f3Smrg .${param[1]} = ${s.expr_extractor(leaf, param[0], 'p')}, /* ${param[0]} */ 4197ec681f3Smrg%endfor 4207ec681f3Smrg }; 4217ec681f3Smrg</%def> 4227ec681f3Smrg 4237ec681f3Smrg<%def name="render_expr(leaf, expr)"> 4247ec681f3Smrgstatic inline int64_t 4257ec681f3Smrg${s.expr_name(leaf.get_root(), expr)}(struct encode_state *s, struct bitset_params *p, ${leaf.get_root().encode.type} src) 4267ec681f3Smrg{ 4277ec681f3Smrg% for fieldname in expr.fieldnames: 4287ec681f3Smrg int64_t ${fieldname}; 4297ec681f3Smrg% endfor 4307ec681f3Smrg% for fieldname in expr.fieldnames: 4317ec681f3Smrg<% field = s.resolve_simple_field(leaf, fieldname) %> 4327ec681f3Smrg% if field is not None and field.get_c_typename() == 'TYPE_BITSET': 4337ec681f3Smrg { ${encode_params(leaf, field)} 4347ec681f3Smrg const bitmask_t tmp = ${s.expr_extractor(leaf, fieldname, '&bp')}; 4357ec681f3Smrg ${fieldname} = bitmask_to_uint64_t(tmp); 4367ec681f3Smrg } 4377ec681f3Smrg% else: 4387ec681f3Smrg ${fieldname} = ${s.expr_extractor(leaf, fieldname, 'p')}; 4397ec681f3Smrg% endif 4407ec681f3Smrg% endfor 4417ec681f3Smrg return ${expr.expr}; 4427ec681f3Smrg} 4437ec681f3Smrg</%def> 4447ec681f3Smrg 4457ec681f3Smrg## note, we can't just iterate all the expressions, but we need to find 4467ec681f3Smrg## the context in which they are used to know the correct src type 4477ec681f3Smrg 4487ec681f3Smrg%for root in s.encode_roots(): 4497ec681f3Smrg<% 4507ec681f3Smrg rendered_exprs = [] 4517ec681f3Smrg%> 4527ec681f3Smrg% for leaf in s.encode_leafs(root): 4537ec681f3Smrg% for expr in s.bitset_used_exprs(leaf): 4547ec681f3Smrg<% 4557ec681f3Smrg if expr in rendered_exprs: 4567ec681f3Smrg continue 4577ec681f3Smrg rendered_exprs.append(expr) 4587ec681f3Smrg%> 4597ec681f3Smrg ${render_expr(leaf, expr)} 4607ec681f3Smrg% endfor 4617ec681f3Smrg% endfor 4627ec681f3Smrg%endfor 4637ec681f3Smrg 4647ec681f3Smrg 4657ec681f3Smrg/* 4667ec681f3Smrg * The actual encoder definitions 4677ec681f3Smrg */ 4687ec681f3Smrg 4697ec681f3Smrg%for root in s.encode_roots(): 4707ec681f3Smrg% for leaf in s.encode_leafs(root): 4717ec681f3Smrg<% snippet = encode_bitset.render(s=s, root=root, leaf=leaf) %> 4727ec681f3Smrg% if snippet not in root.snippets.keys(): 4737ec681f3Smrg<% snippet_name = "snippet" + root.get_c_name() + "_" + str(len(root.snippets)) %> 4747ec681f3Smrgstatic bitmask_t 4757ec681f3Smrg${snippet_name}(struct encode_state *s, struct bitset_params *p, ${root.encode.type} src) 4767ec681f3Smrg{ 4777ec681f3Smrg bitmask_t val = uint64_t_to_bitmask(0); 4787ec681f3Smrg${snippet} 4797ec681f3Smrg return val; 4807ec681f3Smrg} 4817ec681f3Smrg<% root.snippets[snippet] = snippet_name %> 4827ec681f3Smrg% endif 4837ec681f3Smrg% endfor 4847ec681f3Smrg 4857ec681f3Smrgstatic bitmask_t 4867ec681f3Smrgencode${root.get_c_name()}(struct encode_state *s, struct bitset_params *p, ${root.encode.type} src) 4877ec681f3Smrg{ 4887ec681f3Smrg% if root.encode.case_prefix is not None: 4897ec681f3Smrg switch (${root.get_c_name()}_case(s, src)) { 4907ec681f3Smrg% for leaf in s.encode_leafs(root): 4917ec681f3Smrg case ${s.case_name(root, leaf.name)}: { 4927ec681f3Smrg<% snippet = encode_bitset.render(s=s, root=root, leaf=leaf) %> 4937ec681f3Smrg bitmask_t val = uint64_t_to_bitmask(${hex(leaf.get_pattern().match)}); 4947ec681f3Smrg BITSET_OR(val.bitset, val.bitset, ${root.snippets[snippet]}(s, p, src).bitset); 4957ec681f3Smrg return val; 4967ec681f3Smrg } 4977ec681f3Smrg% endfor 4987ec681f3Smrg default: 4997ec681f3Smrg /* Note that we need the default case, because there are 5007ec681f3Smrg * instructions which we never expect to be encoded, (ie. 5017ec681f3Smrg * meta/macro instructions) as they are removed/replace 5027ec681f3Smrg * in earlier stages of the compiler. 5037ec681f3Smrg */ 5047ec681f3Smrg break; 5057ec681f3Smrg } 5067ec681f3Smrg mesa_loge("Unhandled ${root.name} encode case: 0x%x\\n", ${root.get_c_name()}_case(s, src)); 5077ec681f3Smrg return uint64_t_to_bitmask(0); 5087ec681f3Smrg% else: # single case bitset, no switch 5097ec681f3Smrg% for leaf in s.encode_leafs(root): 5107ec681f3Smrg<% snippet = encode_bitset.render(s=s, root=root, leaf=leaf) %> 5117ec681f3Smrg bitmask_t val = uint64_t_to_bitmask(${hex(leaf.get_pattern().match)}); 5127ec681f3Smrg BITSET_OR(val.bitset, val.bitset, ${root.snippets[snippet]}(s, p, src).bitset); 5137ec681f3Smrg return val; 5147ec681f3Smrg% endfor 5157ec681f3Smrg% endif 5167ec681f3Smrg} 5177ec681f3Smrg%endfor 5187ec681f3Smrg""" 5197ec681f3Smrg 5207ec681f3Smrgencode_bitset_template = """ 5217ec681f3Smrg<% 5227ec681f3Smrgisa = s.isa 5237ec681f3Smrg%> 5247ec681f3Smrg 5257ec681f3Smrg<%def name="case_pre(root, expr)"> 5267ec681f3Smrg%if expr is not None: 5277ec681f3Smrg if (${s.expr_name(root, expr)}(s, p, src)) { 5287ec681f3Smrg%else: 5297ec681f3Smrg { 5307ec681f3Smrg%endif 5317ec681f3Smrg</%def> 5327ec681f3Smrg 5337ec681f3Smrg<%def name="case_post(root, expr)"> 5347ec681f3Smrg%if expr is not None: 5357ec681f3Smrg } else 5367ec681f3Smrg%else: 5377ec681f3Smrg } 5387ec681f3Smrg%endif 5397ec681f3Smrg</%def> 5407ec681f3Smrg 5417ec681f3Smrg<%def name="encode_params(leaf, field)"> 5427ec681f3Smrg struct bitset_params bp = { 5437ec681f3Smrg%for param in field.params: 5447ec681f3Smrg .${param[1]} = ${s.expr_extractor(leaf, param[0], 'p')}, /* ${param[0]} */ 5457ec681f3Smrg%endfor 5467ec681f3Smrg }; 5477ec681f3Smrg</%def> 5487ec681f3Smrg 5497ec681f3Smrg uint64_t fld; 5507ec681f3Smrg 5517ec681f3Smrg (void)fld; 5527ec681f3Smrg<% visited_exprs = [] %> 5537ec681f3Smrg%for case in s.bitset_cases(leaf): 5547ec681f3Smrg<% 5557ec681f3Smrg if case.expr is not None: 5567ec681f3Smrg visited_exprs.append(case.expr) 5577ec681f3Smrg%> 5587ec681f3Smrg ${case_pre(root, case.expr)} 5597ec681f3Smrg% for df in case.display_fields(): 5607ec681f3Smrg% for f in df.fields(): 5617ec681f3Smrg<% 5627ec681f3Smrg # simplify the control flow a bit to give the compiler a bit 5637ec681f3Smrg # less to clean up 5647ec681f3Smrg expr = f.expr 5657ec681f3Smrg if expr == case.expr: 5667ec681f3Smrg # Don't need to evaluate the same condition twice: 5677ec681f3Smrg expr = None 5687ec681f3Smrg elif expr in visited_exprs: 5697ec681f3Smrg # We are in an 'else'/'else-if' leg that we wouldn't 5707ec681f3Smrg # go down due to passing an earlier if() 5717ec681f3Smrg continue 5727ec681f3Smrg%> 5737ec681f3Smrg ${case_pre(root, expr)} 5747ec681f3Smrg% if f.field.get_c_typename() == 'TYPE_BITSET': 5757ec681f3Smrg { ${encode_params(leaf, f.field)} 5767ec681f3Smrg bitmask_t tmp = encode${isa.roots[f.field.type].get_c_name()}(s, &bp, ${s.extractor(leaf, f.field.name)}); 5777ec681f3Smrg fld = bitmask_to_uint64_t(tmp); 5787ec681f3Smrg } 5797ec681f3Smrg% else: 5807ec681f3Smrg fld = ${s.extractor(leaf, f.field.name)}; 5817ec681f3Smrg% endif 5827ec681f3Smrg const bitmask_t packed = pack_field(${f.field.low}, ${f.field.high}, fld); /* ${f.field.name} */ 5837ec681f3Smrg BITSET_OR(val.bitset, val.bitset, packed.bitset); 5847ec681f3Smrg ${case_post(root, expr)} 5857ec681f3Smrg% endfor 5867ec681f3Smrg% endfor 5877ec681f3Smrg 5887ec681f3Smrg% for f in case.assert_cases(): 5897ec681f3Smrg<% 5907ec681f3Smrg # simplify the control flow a bit to give the compiler a bit 5917ec681f3Smrg # less to clean up 5927ec681f3Smrg expr = f.expr 5937ec681f3Smrg if expr == case.expr: 5947ec681f3Smrg # Don't need to evaluate the same condition twice: 5957ec681f3Smrg expr = None 5967ec681f3Smrg elif expr in visited_exprs: 5977ec681f3Smrg # We are in an 'else'/'else-if' leg that we wouldn't 5987ec681f3Smrg # go down due to passing an earlier if() 5997ec681f3Smrg continue 6007ec681f3Smrg%> 6017ec681f3Smrg ${case_pre(root, expr)} 6027ec681f3Smrg const bitmask_t packed = pack_field(${f.field.low}, ${f.field.high}, ${f.field.val}); 6037ec681f3Smrg BITSET_OR(val.bitset, val.bitset, packed.bitset); 6047ec681f3Smrg ${case_post(root, None)} 6057ec681f3Smrg% endfor 6067ec681f3Smrg {} /* in case no unconditional field to close out last '} else' */ 6077ec681f3Smrg ${case_post(root, case.expr)} 6087ec681f3Smrg%endfor 6097ec681f3Smrg return val; 6107ec681f3Smrg""" 6117ec681f3Smrg 6127ec681f3Smrgxml = sys.argv[1] 6137ec681f3Smrgdst = sys.argv[2] 6147ec681f3Smrg 6157ec681f3Smrgisa = ISA(xml) 6167ec681f3Smrgs = State(isa) 6177ec681f3Smrg 6187ec681f3Smrgwith open(dst, 'w') as f: 6197ec681f3Smrg f.write(Template(template).render(s=s, encode_bitset=Template(encode_bitset_template))) 620