xref: /aosp_15_r20/external/mesa3d/src/panfrost/compiler/valhall/disasm.py (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker#encoding=utf-8
2*61046927SAndroid Build Coastguard Worker
3*61046927SAndroid Build Coastguard Worker# Copyright (C) 2021 Collabora, Ltd.
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 Workerimport sys
25*61046927SAndroid Build Coastguard Workerfrom valhall import valhall_parse_isa
26*61046927SAndroid Build Coastguard Workerfrom mako.template import Template
27*61046927SAndroid Build Coastguard Workerfrom mako import exceptions
28*61046927SAndroid Build Coastguard Worker
29*61046927SAndroid Build Coastguard Worker(instructions, immediates, enums, typesize, safe_name) = valhall_parse_isa()
30*61046927SAndroid Build Coastguard Worker
31*61046927SAndroid Build Coastguard Workertemplate = """
32*61046927SAndroid Build Coastguard Worker#include "disassemble.h"
33*61046927SAndroid Build Coastguard Worker
34*61046927SAndroid Build Coastguard Worker#define BIT(b)         (1ull << (b))
35*61046927SAndroid Build Coastguard Worker#define MASK(count)    ((1ull << (count)) - 1)
36*61046927SAndroid Build Coastguard Worker#define SEXT(b, count) ((b ^ BIT(count - 1)) - BIT(count - 1))
37*61046927SAndroid Build Coastguard Worker#define UNUSED         __attribute__((unused))
38*61046927SAndroid Build Coastguard Worker
39*61046927SAndroid Build Coastguard Worker#define VA_SRC_UNIFORM_TYPE 0x2
40*61046927SAndroid Build Coastguard Worker#define VA_SRC_IMM_TYPE     0x3
41*61046927SAndroid Build Coastguard Worker
42*61046927SAndroid Build Coastguard Worker% for name, en in ENUMS.items():
43*61046927SAndroid Build Coastguard WorkerUNUSED static const char *valhall_${name}[] = {
44*61046927SAndroid Build Coastguard Worker% for v in en.values:
45*61046927SAndroid Build Coastguard Worker    "${"" if v.default else "." + v.value}",
46*61046927SAndroid Build Coastguard Worker% endfor
47*61046927SAndroid Build Coastguard Worker};
48*61046927SAndroid Build Coastguard Worker
49*61046927SAndroid Build Coastguard Worker% endfor
50*61046927SAndroid Build Coastguard Workerstatic const uint32_t va_immediates[32] = {
51*61046927SAndroid Build Coastguard Worker% for imm in IMMEDIATES:
52*61046927SAndroid Build Coastguard Worker    ${hex(imm)},
53*61046927SAndroid Build Coastguard Worker% endfor
54*61046927SAndroid Build Coastguard Worker};
55*61046927SAndroid Build Coastguard Worker
56*61046927SAndroid Build Coastguard Workerstatic inline void
57*61046927SAndroid Build Coastguard Workerva_print_src(FILE *fp, uint8_t src, unsigned fau_page)
58*61046927SAndroid Build Coastguard Worker{
59*61046927SAndroid Build Coastguard Worker	unsigned type = (src >> 6);
60*61046927SAndroid Build Coastguard Worker	unsigned value = (src & 0x3F);
61*61046927SAndroid Build Coastguard Worker
62*61046927SAndroid Build Coastguard Worker	if (type == VA_SRC_IMM_TYPE) {
63*61046927SAndroid Build Coastguard Worker        if (value >= 32) {
64*61046927SAndroid Build Coastguard Worker            if (fau_page == 0)
65*61046927SAndroid Build Coastguard Worker                fputs(valhall_fau_special_page_0[(value - 0x20) >> 1] + 1, fp);
66*61046927SAndroid Build Coastguard Worker            else if (fau_page == 1)
67*61046927SAndroid Build Coastguard Worker                fputs(valhall_fau_special_page_1[(value - 0x20) >> 1] + 1, fp);
68*61046927SAndroid Build Coastguard Worker            else if (fau_page == 3)
69*61046927SAndroid Build Coastguard Worker                fputs(valhall_fau_special_page_3[(value - 0x20) >> 1] + 1, fp);
70*61046927SAndroid Build Coastguard Worker            else
71*61046927SAndroid Build Coastguard Worker                fprintf(fp, "reserved_page2");
72*61046927SAndroid Build Coastguard Worker
73*61046927SAndroid Build Coastguard Worker            fprintf(fp, ".w%u", value & 1);
74*61046927SAndroid Build Coastguard Worker        } else {
75*61046927SAndroid Build Coastguard Worker            fprintf(fp, "0x%X", va_immediates[value]);
76*61046927SAndroid Build Coastguard Worker        }
77*61046927SAndroid Build Coastguard Worker	} else if (type == VA_SRC_UNIFORM_TYPE) {
78*61046927SAndroid Build Coastguard Worker		fprintf(fp, "u%u", value | (fau_page << 6));
79*61046927SAndroid Build Coastguard Worker	} else {
80*61046927SAndroid Build Coastguard Worker		bool discard = (type & 1);
81*61046927SAndroid Build Coastguard Worker		fprintf(fp, "%sr%u", discard ? "^" : "", value);
82*61046927SAndroid Build Coastguard Worker	}
83*61046927SAndroid Build Coastguard Worker}
84*61046927SAndroid Build Coastguard Worker
85*61046927SAndroid Build Coastguard Workerstatic inline void
86*61046927SAndroid Build Coastguard Workerva_print_float_src(FILE *fp, uint8_t src, unsigned fau_page, bool neg, bool abs)
87*61046927SAndroid Build Coastguard Worker{
88*61046927SAndroid Build Coastguard Worker	unsigned type = (src >> 6);
89*61046927SAndroid Build Coastguard Worker	unsigned value = (src & 0x3F);
90*61046927SAndroid Build Coastguard Worker
91*61046927SAndroid Build Coastguard Worker	if (type == VA_SRC_IMM_TYPE) {
92*61046927SAndroid Build Coastguard Worker        assert(value < 32 && "overflow in LUT");
93*61046927SAndroid Build Coastguard Worker        fprintf(fp, "0x%X", va_immediates[value]);
94*61046927SAndroid Build Coastguard Worker	} else {
95*61046927SAndroid Build Coastguard Worker        va_print_src(fp, src, fau_page);
96*61046927SAndroid Build Coastguard Worker    }
97*61046927SAndroid Build Coastguard Worker
98*61046927SAndroid Build Coastguard Worker	if (neg)
99*61046927SAndroid Build Coastguard Worker		fprintf(fp, ".neg");
100*61046927SAndroid Build Coastguard Worker
101*61046927SAndroid Build Coastguard Worker	if (abs)
102*61046927SAndroid Build Coastguard Worker		fprintf(fp, ".abs");
103*61046927SAndroid Build Coastguard Worker}
104*61046927SAndroid Build Coastguard Worker
105*61046927SAndroid Build Coastguard Workerstatic inline void
106*61046927SAndroid Build Coastguard Workerva_print_dest(FILE *fp, uint8_t dest, bool can_mask)
107*61046927SAndroid Build Coastguard Worker{
108*61046927SAndroid Build Coastguard Worker   unsigned mask = (dest >> 6);
109*61046927SAndroid Build Coastguard Worker   unsigned value = (dest & 0x3F);
110*61046927SAndroid Build Coastguard Worker   fprintf(fp, "r%u", value);
111*61046927SAndroid Build Coastguard Worker
112*61046927SAndroid Build Coastguard Worker   /* Should write at least one component */
113*61046927SAndroid Build Coastguard Worker   //	assert(mask != 0);
114*61046927SAndroid Build Coastguard Worker   //	assert(mask == 0x3 || can_mask);
115*61046927SAndroid Build Coastguard Worker
116*61046927SAndroid Build Coastguard Worker   if (mask != 0x3)
117*61046927SAndroid Build Coastguard Worker      fprintf(fp, ".h%u", (mask == 1) ? 0 : 1);
118*61046927SAndroid Build Coastguard Worker}
119*61046927SAndroid Build Coastguard Worker
120*61046927SAndroid Build Coastguard Workervoid
121*61046927SAndroid Build Coastguard Workerva_disasm_instr(FILE *fp, uint64_t instr)
122*61046927SAndroid Build Coastguard Worker{
123*61046927SAndroid Build Coastguard Worker   unsigned primary_opc = (instr >> 48) & MASK(9);
124*61046927SAndroid Build Coastguard Worker   unsigned fau_page = (instr >> 57) & MASK(2);
125*61046927SAndroid Build Coastguard Worker   unsigned secondary_opc = 0;
126*61046927SAndroid Build Coastguard Worker
127*61046927SAndroid Build Coastguard Worker   switch (primary_opc) {
128*61046927SAndroid Build Coastguard Worker% for bucket in OPCODES:
129*61046927SAndroid Build Coastguard Worker    <%
130*61046927SAndroid Build Coastguard Worker        ops = OPCODES[bucket]
131*61046927SAndroid Build Coastguard Worker        ambiguous = (len(ops) > 1)
132*61046927SAndroid Build Coastguard Worker    %>
133*61046927SAndroid Build Coastguard Worker% if len(ops) > 0:
134*61046927SAndroid Build Coastguard Worker   case ${hex(bucket)}:
135*61046927SAndroid Build Coastguard Worker% if ambiguous:
136*61046927SAndroid Build Coastguard Worker	secondary_opc = (instr >> ${ops[0].secondary_shift}) & ${hex(ops[0].secondary_mask)};
137*61046927SAndroid Build Coastguard Worker% endif
138*61046927SAndroid Build Coastguard Worker% for op in ops:
139*61046927SAndroid Build Coastguard Worker<% no_comma = True %>
140*61046927SAndroid Build Coastguard Worker% if ambiguous:
141*61046927SAndroid Build Coastguard Worker
142*61046927SAndroid Build Coastguard Worker        if (secondary_opc == ${op.opcode2}) {
143*61046927SAndroid Build Coastguard Worker% endif
144*61046927SAndroid Build Coastguard Worker            fputs("${op.name}", fp);
145*61046927SAndroid Build Coastguard Worker% for mod in op.modifiers:
146*61046927SAndroid Build Coastguard Worker% if mod.name not in ["left", "memory_width", "descriptor_type", "staging_register_count", "staging_register_write_count"]:
147*61046927SAndroid Build Coastguard Worker% if mod.is_enum:
148*61046927SAndroid Build Coastguard Worker            fputs(valhall_${safe_name(mod.enum)}[(instr >> ${mod.start}) & ${hex((1 << mod.size) - 1)}], fp);
149*61046927SAndroid Build Coastguard Worker% else:
150*61046927SAndroid Build Coastguard Worker            if (instr & BIT(${mod.start})) fputs(".${mod.name}", fp);
151*61046927SAndroid Build Coastguard Worker% endif
152*61046927SAndroid Build Coastguard Worker% endif
153*61046927SAndroid Build Coastguard Worker% endfor
154*61046927SAndroid Build Coastguard Worker            assert((instr & (1ull << 63)) == 0 /* reserved */);
155*61046927SAndroid Build Coastguard Worker            fprintf(fp, "%s ", valhall_flow[instr >> 59]);
156*61046927SAndroid Build Coastguard Worker% if len(op.dests) > 0:
157*61046927SAndroid Build Coastguard Worker<% no_comma = False %>
158*61046927SAndroid Build Coastguard Worker            va_print_dest(fp, (instr >> 40), true);
159*61046927SAndroid Build Coastguard Worker% endif
160*61046927SAndroid Build Coastguard Worker% for index, sr in enumerate(op.staging):
161*61046927SAndroid Build Coastguard Worker% if not no_comma:
162*61046927SAndroid Build Coastguard Worker            fputs(", ", fp);
163*61046927SAndroid Build Coastguard Worker% endif
164*61046927SAndroid Build Coastguard Worker<%
165*61046927SAndroid Build Coastguard Worker    no_comma = False
166*61046927SAndroid Build Coastguard Worker
167*61046927SAndroid Build Coastguard Worker    if sr.count != 0:
168*61046927SAndroid Build Coastguard Worker        sr_count = sr.count
169*61046927SAndroid Build Coastguard Worker    elif "staging_register_write_count" in [x.name for x in op.modifiers] and sr.write:
170*61046927SAndroid Build Coastguard Worker        sr_count = "(((instr >> 36) & MASK(3)) + 1)"
171*61046927SAndroid Build Coastguard Worker    elif "staging_register_count" in [x.name for x in op.modifiers]:
172*61046927SAndroid Build Coastguard Worker        sr_count = "((instr >> 33) & MASK(3))"
173*61046927SAndroid Build Coastguard Worker    else:
174*61046927SAndroid Build Coastguard Worker        assert(0)
175*61046927SAndroid Build Coastguard Worker%>
176*61046927SAndroid Build Coastguard Worker//            assert(((instr >> ${sr.start}) & 0xC0) == ${sr.encoded_flags});
177*61046927SAndroid Build Coastguard Worker            fprintf(fp, "@");
178*61046927SAndroid Build Coastguard Worker            for (unsigned i = 0; i < ${sr_count}; ++i) {
179*61046927SAndroid Build Coastguard Worker                fprintf(fp, "%sr%u", (i == 0) ? "" : ":",
180*61046927SAndroid Build Coastguard Worker                        (uint32_t) (((instr >> ${sr.start}) & 0x3F) + i));
181*61046927SAndroid Build Coastguard Worker            }
182*61046927SAndroid Build Coastguard Worker% endfor
183*61046927SAndroid Build Coastguard Worker% for i, src in enumerate(op.srcs):
184*61046927SAndroid Build Coastguard Worker% if not no_comma:
185*61046927SAndroid Build Coastguard Worker            fputs(", ", fp);
186*61046927SAndroid Build Coastguard Worker% endif
187*61046927SAndroid Build Coastguard Worker<% no_comma = False %>
188*61046927SAndroid Build Coastguard Worker% if src.absneg:
189*61046927SAndroid Build Coastguard Worker            va_print_float_src(fp, instr >> ${src.start}, fau_page,
190*61046927SAndroid Build Coastguard Worker                    instr & BIT(${src.offset['neg']}),
191*61046927SAndroid Build Coastguard Worker                    instr & BIT(${src.offset['abs']}));
192*61046927SAndroid Build Coastguard Worker% elif src.is_float:
193*61046927SAndroid Build Coastguard Worker            va_print_float_src(fp, instr >> ${src.start}, fau_page, false, false);
194*61046927SAndroid Build Coastguard Worker% else:
195*61046927SAndroid Build Coastguard Worker            va_print_src(fp, instr >> ${src.start}, fau_page);
196*61046927SAndroid Build Coastguard Worker% endif
197*61046927SAndroid Build Coastguard Worker% if src.swizzle:
198*61046927SAndroid Build Coastguard Worker% if src.size == 32:
199*61046927SAndroid Build Coastguard Worker            fputs(valhall_widen[(instr >> ${src.offset['swizzle']}) & 3], fp);
200*61046927SAndroid Build Coastguard Worker% else:
201*61046927SAndroid Build Coastguard Worker            fputs(valhall_swizzles_16_bit[(instr >> ${src.offset['swizzle']}) & 3], fp);
202*61046927SAndroid Build Coastguard Worker% endif
203*61046927SAndroid Build Coastguard Worker% endif
204*61046927SAndroid Build Coastguard Worker% if src.lanes:
205*61046927SAndroid Build Coastguard Worker            fputs(valhall_lanes_8_bit[(instr >> ${src.offset['widen']}) & 0xF], fp);
206*61046927SAndroid Build Coastguard Worker% elif src.halfswizzle:
207*61046927SAndroid Build Coastguard Worker            fputs(valhall_half_swizzles_8_bit[(instr >> ${src.offset['widen']}) & 0xF], fp);
208*61046927SAndroid Build Coastguard Worker% elif src.widen:
209*61046927SAndroid Build Coastguard Worker		    fputs(valhall_swizzles_${src.size}_bit[(instr >> ${src.offset['widen']}) & 0xF], fp);
210*61046927SAndroid Build Coastguard Worker% elif src.combine:
211*61046927SAndroid Build Coastguard Worker            fputs(valhall_combine[(instr >> ${src.offset['combine']}) & 0x7], fp);
212*61046927SAndroid Build Coastguard Worker% endif
213*61046927SAndroid Build Coastguard Worker% if src.lane:
214*61046927SAndroid Build Coastguard Worker            fputs(valhall_lane_${src.size}_bit[(instr >> ${src.lane}) & 0x3], fp);
215*61046927SAndroid Build Coastguard Worker% endif
216*61046927SAndroid Build Coastguard Worker% if 'not' in src.offset:
217*61046927SAndroid Build Coastguard Worker            if (instr & BIT(${src.offset['not']})) fputs(".not", fp);
218*61046927SAndroid Build Coastguard Worker% endif
219*61046927SAndroid Build Coastguard Worker% endfor
220*61046927SAndroid Build Coastguard Worker% for imm in op.immediates:
221*61046927SAndroid Build Coastguard Worker<%
222*61046927SAndroid Build Coastguard Worker    prefix = "#" if imm.name == "constant" else imm.name + ":"
223*61046927SAndroid Build Coastguard Worker    fmt = "%d" if imm.signed else "0x%X"
224*61046927SAndroid Build Coastguard Worker%>
225*61046927SAndroid Build Coastguard Worker            fprintf(fp, ", ${prefix}${fmt}", (uint32_t) ${"SEXT(" if imm.signed else ""}
226*61046927SAndroid Build Coastguard Worker                    ((instr >> ${imm.start}) & MASK(${imm.size})) ${f", {imm.size})" if imm.signed else ""});
227*61046927SAndroid Build Coastguard Worker% endfor
228*61046927SAndroid Build Coastguard Worker% if ambiguous:
229*61046927SAndroid Build Coastguard Worker        }
230*61046927SAndroid Build Coastguard Worker% endif
231*61046927SAndroid Build Coastguard Worker% endfor
232*61046927SAndroid Build Coastguard Worker     break;
233*61046927SAndroid Build Coastguard Worker
234*61046927SAndroid Build Coastguard Worker% endif
235*61046927SAndroid Build Coastguard Worker% endfor
236*61046927SAndroid Build Coastguard Worker   }
237*61046927SAndroid Build Coastguard Worker}
238*61046927SAndroid Build Coastguard Worker
239*61046927SAndroid Build Coastguard Workervoid
240*61046927SAndroid Build Coastguard Workerdisassemble_valhall(FILE *fp, const void *code, size_t size, bool verbose)
241*61046927SAndroid Build Coastguard Worker{
242*61046927SAndroid Build Coastguard Worker   assert((size & 7) == 0);
243*61046927SAndroid Build Coastguard Worker
244*61046927SAndroid Build Coastguard Worker   const uint64_t *words = (const uint64_t *)code;
245*61046927SAndroid Build Coastguard Worker
246*61046927SAndroid Build Coastguard Worker   /* Segment into 8-byte instructions */
247*61046927SAndroid Build Coastguard Worker   for (unsigned i = 0; i < (size / 8); ++i) {
248*61046927SAndroid Build Coastguard Worker      uint64_t instr = words[i];
249*61046927SAndroid Build Coastguard Worker
250*61046927SAndroid Build Coastguard Worker      if (instr == 0) {
251*61046927SAndroid Build Coastguard Worker         fprintf(fp, "\\n");
252*61046927SAndroid Build Coastguard Worker         return;
253*61046927SAndroid Build Coastguard Worker      }
254*61046927SAndroid Build Coastguard Worker
255*61046927SAndroid Build Coastguard Worker      if (verbose) {
256*61046927SAndroid Build Coastguard Worker         /* Print byte pattern */
257*61046927SAndroid Build Coastguard Worker         for (unsigned j = 0; j < 8; ++j)
258*61046927SAndroid Build Coastguard Worker            fprintf(fp, "%02x ", (uint8_t)(instr >> (j * 8)));
259*61046927SAndroid Build Coastguard Worker
260*61046927SAndroid Build Coastguard Worker         fprintf(fp, "   ");
261*61046927SAndroid Build Coastguard Worker      } else {
262*61046927SAndroid Build Coastguard Worker         /* Print whitespace */
263*61046927SAndroid Build Coastguard Worker         fprintf(fp, "   ");
264*61046927SAndroid Build Coastguard Worker      }
265*61046927SAndroid Build Coastguard Worker
266*61046927SAndroid Build Coastguard Worker      va_disasm_instr(fp, instr);
267*61046927SAndroid Build Coastguard Worker      fprintf(fp, "\\n");
268*61046927SAndroid Build Coastguard Worker
269*61046927SAndroid Build Coastguard Worker      /* Detect branches */
270*61046927SAndroid Build Coastguard Worker      uint64_t opcode = (instr >> 48) & MASK(9);
271*61046927SAndroid Build Coastguard Worker      bool branchz = (opcode == 0x1F);
272*61046927SAndroid Build Coastguard Worker      bool branchzi = (opcode == 0x2F);
273*61046927SAndroid Build Coastguard Worker
274*61046927SAndroid Build Coastguard Worker      /* Separate blocks visually by inserting whitespace after branches */
275*61046927SAndroid Build Coastguard Worker      if (branchz || branchzi)
276*61046927SAndroid Build Coastguard Worker         fprintf(fp, "\\n");
277*61046927SAndroid Build Coastguard Worker   }
278*61046927SAndroid Build Coastguard Worker
279*61046927SAndroid Build Coastguard Worker   fprintf(fp, "\\n");
280*61046927SAndroid Build Coastguard Worker}
281*61046927SAndroid Build Coastguard Worker"""
282*61046927SAndroid Build Coastguard Worker
283*61046927SAndroid Build Coastguard Worker# Bucket by opcode for hierarchical disassembly
284*61046927SAndroid Build Coastguard WorkerOPCODE_BUCKETS = {}
285*61046927SAndroid Build Coastguard Workerfor ins in instructions:
286*61046927SAndroid Build Coastguard Worker    opc = ins.opcode
287*61046927SAndroid Build Coastguard Worker    OPCODE_BUCKETS[opc] = OPCODE_BUCKETS.get(opc, []) + [ins]
288*61046927SAndroid Build Coastguard Worker
289*61046927SAndroid Build Coastguard Worker# Check that each bucket may be disambiguated
290*61046927SAndroid Build Coastguard Workerfor op in OPCODE_BUCKETS:
291*61046927SAndroid Build Coastguard Worker    bucket = OPCODE_BUCKETS[op]
292*61046927SAndroid Build Coastguard Worker
293*61046927SAndroid Build Coastguard Worker    # Nothing to disambiguate
294*61046927SAndroid Build Coastguard Worker    if len(bucket) < 2:
295*61046927SAndroid Build Coastguard Worker        continue
296*61046927SAndroid Build Coastguard Worker
297*61046927SAndroid Build Coastguard Worker    SECONDARY = {}
298*61046927SAndroid Build Coastguard Worker    for ins in bucket:
299*61046927SAndroid Build Coastguard Worker        # Number of sources determines opcode2 placement, must be consistent
300*61046927SAndroid Build Coastguard Worker        assert(len(ins.srcs) == len(bucket[0].srcs))
301*61046927SAndroid Build Coastguard Worker
302*61046927SAndroid Build Coastguard Worker        # Must not repeat, else we're ambiguous
303*61046927SAndroid Build Coastguard Worker        assert(ins.opcode2 not in SECONDARY)
304*61046927SAndroid Build Coastguard Worker        SECONDARY[ins.opcode2] = ins
305*61046927SAndroid Build Coastguard Worker
306*61046927SAndroid Build Coastguard Workertry:
307*61046927SAndroid Build Coastguard Worker    print(Template(template).render(OPCODES = OPCODE_BUCKETS, IMMEDIATES = immediates, ENUMS = enums, typesize = typesize, safe_name = safe_name))
308*61046927SAndroid Build Coastguard Workerexcept:
309*61046927SAndroid Build Coastguard Worker    print(exceptions.text_error_template().render())
310