encode.py revision 7ec681f3
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