• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#encoding=utf-8
2
3# Copyright (C) 2021 Collabora, Ltd.
4#
5# Permission is hereby granted, free of charge, to any person obtaining a
6# copy of this software and associated documentation files (the "Software"),
7# to deal in the Software without restriction, including without limitation
8# the rights to use, copy, modify, merge, publish, distribute, sublicense,
9# and/or sell copies of the Software, and to permit persons to whom the
10# Software is furnished to do so, subject to the following conditions:
11#
12# The above copyright notice and this permission notice (including the next
13# paragraph) shall be included in all copies or substantial portions of the
14# Software.
15#
16# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22# IN THE SOFTWARE.
23
24from valhall import instructions, immediates, enums, typesize, safe_name
25from mako.template import Template
26from mako import exceptions
27
28template = """
29#include "disassemble.h"
30
31% for name, en in ENUMS.items():
32UNUSED static const char *valhall_${name}[] = {
33% for v in en.values:
34    "${"" if v.default else "." + v.value}",
35% endfor
36};
37
38% endfor
39static const uint32_t va_immediates[32] = {
40% for imm in IMMEDIATES:
41    ${hex(imm)},
42% endfor
43};
44
45static inline void
46va_print_src(FILE *fp, uint8_t src, unsigned fau_page)
47{
48	unsigned type = (src >> 6);
49	unsigned value = (src & 0x3F);
50
51	if (type == VA_SRC_IMM_TYPE) {
52        if (value >= 32) {
53            if (fau_page == 0)
54                fputs(valhall_fau_special_page_0[(value - 0x20) >> 1] + 1, fp);
55            else if (fau_page == 1)
56                fputs(valhall_fau_special_page_1[(value - 0x20) >> 1] + 1, fp);
57            else if (fau_page == 3)
58                fputs(valhall_fau_special_page_3[(value - 0x20) >> 1] + 1, fp);
59            else
60                fprintf(fp, "reserved_page2");
61
62            fprintf(fp, ".w%u", value & 1);
63        } else {
64            fprintf(fp, "0x%X", va_immediates[value]);
65        }
66	} else if (type == VA_SRC_UNIFORM_TYPE) {
67		fprintf(fp, "u%u", value | (fau_page << 6));
68	} else {
69		bool discard = (type & 1);
70		fprintf(fp, "%sr%u", discard ? "^" : "", value);
71	}
72}
73
74static inline void
75va_print_float_src(FILE *fp, uint8_t src, unsigned fau_page, bool neg, bool abs)
76{
77	unsigned type = (src >> 6);
78	unsigned value = (src & 0x3F);
79
80	if (type == VA_SRC_IMM_TYPE) {
81        assert(value < 32 && "overflow in LUT");
82        fprintf(fp, "0x%X", va_immediates[value]);
83	} else {
84        va_print_src(fp, src, fau_page);
85    }
86
87	if (neg)
88		fprintf(fp, ".neg");
89
90	if (abs)
91		fprintf(fp, ".abs");
92}
93
94void
95va_disasm_instr(FILE *fp, uint64_t instr)
96{
97   unsigned primary_opc = (instr >> 48) & MASK(9);
98   unsigned fau_page = (instr >> 57) & MASK(2);
99   unsigned secondary_opc = 0;
100
101   switch (primary_opc) {
102% for bucket in OPCODES:
103    <%
104        ops = OPCODES[bucket]
105        ambiguous = (len(ops) > 1)
106    %>
107% if len(ops) > 0:
108   case ${hex(bucket)}:
109% if ambiguous:
110	secondary_opc = (instr >> ${ops[0].secondary_shift}) & ${hex(ops[0].secondary_mask)};
111% endif
112% for op in ops:
113<% no_comma = True %>
114% if ambiguous:
115
116        if (secondary_opc == ${op.opcode2}) {
117% endif
118            fputs("${op.name}", fp);
119% for mod in op.modifiers:
120% if mod.name not in ["left", "memory_width", "descriptor_type", "staging_register_count", "staging_register_write_count"]:
121% if mod.is_enum:
122            fputs(valhall_${safe_name(mod.enum)}[(instr >> ${mod.start}) & ${hex((1 << mod.size) - 1)}], fp);
123% else:
124            if (instr & BIT(${mod.start})) fputs(".${mod.name}", fp);
125% endif
126% endif
127% endfor
128            assert((instr & (1ull << 63)) == 0 /* reserved */);
129            fprintf(fp, "%s ", valhall_flow[instr >> 59]);
130% if len(op.dests) > 0:
131<% no_comma = False %>
132            va_print_dest(fp, (instr >> 40), true);
133% endif
134% for index, sr in enumerate(op.staging):
135% if not no_comma:
136            fputs(", ", fp);
137% endif
138<%
139    no_comma = False
140
141    if sr.count != 0:
142        sr_count = sr.count
143    elif "staging_register_write_count" in [x.name for x in op.modifiers] and sr.write:
144        sr_count = "(((instr >> 36) & MASK(3)) + 1)"
145    elif "staging_register_count" in [x.name for x in op.modifiers]:
146        sr_count = "((instr >> 33) & MASK(3))"
147    else:
148        assert(0)
149%>
150//            assert(((instr >> ${sr.start}) & 0xC0) == ${sr.encoded_flags});
151            fprintf(fp, "@");
152            for (unsigned i = 0; i < ${sr_count}; ++i) {
153                fprintf(fp, "%sr%u", (i == 0) ? "" : ":",
154                        (uint32_t) (((instr >> ${sr.start}) & 0x3F) + i));
155            }
156% endfor
157% for i, src in enumerate(op.srcs):
158% if not no_comma:
159            fputs(", ", fp);
160% endif
161<% no_comma = False %>
162% if src.absneg:
163            va_print_float_src(fp, instr >> ${src.start}, fau_page,
164                    instr & BIT(${src.offset['neg']}),
165                    instr & BIT(${src.offset['abs']}));
166% elif src.is_float:
167            va_print_float_src(fp, instr >> ${src.start}, fau_page, false, false);
168% else:
169            va_print_src(fp, instr >> ${src.start}, fau_page);
170% endif
171% if src.swizzle:
172% if src.size == 32:
173            fputs(valhall_widen[(instr >> ${src.offset['swizzle']}) & 3], fp);
174% else:
175            fputs(valhall_swizzles_16_bit[(instr >> ${src.offset['swizzle']}) & 3], fp);
176% endif
177% endif
178% if src.lanes:
179            fputs(valhall_lanes_8_bit[(instr >> ${src.offset['widen']}) & 0xF], fp);
180% elif src.halfswizzle:
181            fputs(valhall_half_swizzles_8_bit[(instr >> ${src.offset['widen']}) & 0xF], fp);
182% elif src.widen:
183		    fputs(valhall_swizzles_${src.size}_bit[(instr >> ${src.offset['widen']}) & 0xF], fp);
184% elif src.combine:
185            fputs(valhall_combine[(instr >> ${src.offset['combine']}) & 0x7], fp);
186% endif
187% if src.lane:
188            fputs(valhall_lane_${src.size}_bit[(instr >> ${src.lane}) & 0x3], fp);
189% endif
190% if 'not' in src.offset:
191            if (instr & BIT(${src.offset['not']})) fputs(".not", fp);
192% endif
193% endfor
194% for imm in op.immediates:
195<%
196    prefix = "#" if imm.name == "constant" else imm.name + ":"
197    fmt = "%d" if imm.signed else "0x%X"
198%>
199            fprintf(fp, ", ${prefix}${fmt}", (uint32_t) ${"SEXT(" if imm.signed else ""}
200                    ((instr >> ${imm.start}) & MASK(${imm.size})) ${f", {imm.size})" if imm.signed else ""});
201% endfor
202% if ambiguous:
203        }
204% endif
205% endfor
206     break;
207
208% endif
209% endfor
210   }
211}
212"""
213
214# Bucket by opcode for hierarchical disassembly
215OPCODE_BUCKETS = {}
216for ins in instructions:
217    opc = ins.opcode
218    OPCODE_BUCKETS[opc] = OPCODE_BUCKETS.get(opc, []) + [ins]
219
220# Check that each bucket may be disambiguated
221for op in OPCODE_BUCKETS:
222    bucket = OPCODE_BUCKETS[op]
223
224    # Nothing to disambiguate
225    if len(bucket) < 2:
226        continue
227
228    SECONDARY = {}
229    for ins in bucket:
230        # Number of sources determines opcode2 placement, must be consistent
231        assert(len(ins.srcs) == len(bucket[0].srcs))
232
233        # Must not repeat, else we're ambiguous
234        assert(ins.opcode2 not in SECONDARY)
235        SECONDARY[ins.opcode2] = ins
236
237try:
238    print(Template(template).render(OPCODES = OPCODE_BUCKETS, IMMEDIATES = immediates, ENUMS = enums, typesize = typesize, safe_name = safe_name))
239except:
240    print(exceptions.text_error_template().render())
241