1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker * Copyright 2021 Alyssa Rosenzweig
3*61046927SAndroid Build Coastguard Worker * Copyright 2019-2020 Collabora, Ltd.
4*61046927SAndroid Build Coastguard Worker * SPDX-License-Identifier: MIT
5*61046927SAndroid Build Coastguard Worker */
6*61046927SAndroid Build Coastguard Worker
7*61046927SAndroid Build Coastguard Worker #include "agx_builder.h"
8*61046927SAndroid Build Coastguard Worker #include "agx_compiler.h"
9*61046927SAndroid Build Coastguard Worker
10*61046927SAndroid Build Coastguard Worker static void
agx_print_sized(char prefix,unsigned value,enum agx_size size,FILE * fp)11*61046927SAndroid Build Coastguard Worker agx_print_sized(char prefix, unsigned value, enum agx_size size, FILE *fp)
12*61046927SAndroid Build Coastguard Worker {
13*61046927SAndroid Build Coastguard Worker switch (size) {
14*61046927SAndroid Build Coastguard Worker case AGX_SIZE_16:
15*61046927SAndroid Build Coastguard Worker fprintf(fp, "%c%u%c", prefix, value >> 1, (value & 1) ? 'h' : 'l');
16*61046927SAndroid Build Coastguard Worker return;
17*61046927SAndroid Build Coastguard Worker case AGX_SIZE_32:
18*61046927SAndroid Build Coastguard Worker assert((value & 1) == 0);
19*61046927SAndroid Build Coastguard Worker fprintf(fp, "%c%u", prefix, value >> 1);
20*61046927SAndroid Build Coastguard Worker return;
21*61046927SAndroid Build Coastguard Worker case AGX_SIZE_64:
22*61046927SAndroid Build Coastguard Worker assert((value & 1) == 0);
23*61046927SAndroid Build Coastguard Worker fprintf(fp, "%c%u:%c%u", prefix, value >> 1, prefix, (value >> 1) + 1);
24*61046927SAndroid Build Coastguard Worker return;
25*61046927SAndroid Build Coastguard Worker }
26*61046927SAndroid Build Coastguard Worker
27*61046927SAndroid Build Coastguard Worker unreachable("Invalid size");
28*61046927SAndroid Build Coastguard Worker }
29*61046927SAndroid Build Coastguard Worker
30*61046927SAndroid Build Coastguard Worker void
agx_print_index(agx_index index,bool is_float,FILE * fp)31*61046927SAndroid Build Coastguard Worker agx_print_index(agx_index index, bool is_float, FILE *fp)
32*61046927SAndroid Build Coastguard Worker {
33*61046927SAndroid Build Coastguard Worker if (index.memory)
34*61046927SAndroid Build Coastguard Worker fprintf(fp, "m");
35*61046927SAndroid Build Coastguard Worker
36*61046927SAndroid Build Coastguard Worker switch (index.type) {
37*61046927SAndroid Build Coastguard Worker case AGX_INDEX_NULL:
38*61046927SAndroid Build Coastguard Worker fprintf(fp, "_");
39*61046927SAndroid Build Coastguard Worker return;
40*61046927SAndroid Build Coastguard Worker
41*61046927SAndroid Build Coastguard Worker case AGX_INDEX_NORMAL:
42*61046927SAndroid Build Coastguard Worker if (index.cache)
43*61046927SAndroid Build Coastguard Worker fprintf(fp, "$");
44*61046927SAndroid Build Coastguard Worker
45*61046927SAndroid Build Coastguard Worker if (index.discard)
46*61046927SAndroid Build Coastguard Worker fprintf(fp, "`");
47*61046927SAndroid Build Coastguard Worker
48*61046927SAndroid Build Coastguard Worker if (index.kill)
49*61046927SAndroid Build Coastguard Worker fprintf(fp, "*");
50*61046927SAndroid Build Coastguard Worker
51*61046927SAndroid Build Coastguard Worker fprintf(fp, "%u", index.value);
52*61046927SAndroid Build Coastguard Worker break;
53*61046927SAndroid Build Coastguard Worker
54*61046927SAndroid Build Coastguard Worker case AGX_INDEX_IMMEDIATE:
55*61046927SAndroid Build Coastguard Worker if (is_float) {
56*61046927SAndroid Build Coastguard Worker assert(index.value < 0x100);
57*61046927SAndroid Build Coastguard Worker fprintf(fp, "#%f", agx_minifloat_decode(index.value));
58*61046927SAndroid Build Coastguard Worker } else {
59*61046927SAndroid Build Coastguard Worker fprintf(fp, "#%u", index.value);
60*61046927SAndroid Build Coastguard Worker }
61*61046927SAndroid Build Coastguard Worker
62*61046927SAndroid Build Coastguard Worker break;
63*61046927SAndroid Build Coastguard Worker
64*61046927SAndroid Build Coastguard Worker case AGX_INDEX_UNDEF:
65*61046927SAndroid Build Coastguard Worker fprintf(fp, "undef");
66*61046927SAndroid Build Coastguard Worker break;
67*61046927SAndroid Build Coastguard Worker
68*61046927SAndroid Build Coastguard Worker case AGX_INDEX_UNIFORM:
69*61046927SAndroid Build Coastguard Worker agx_print_sized('u', index.value, index.size, fp);
70*61046927SAndroid Build Coastguard Worker break;
71*61046927SAndroid Build Coastguard Worker
72*61046927SAndroid Build Coastguard Worker case AGX_INDEX_REGISTER:
73*61046927SAndroid Build Coastguard Worker agx_print_sized('r', index.value, index.size, fp);
74*61046927SAndroid Build Coastguard Worker
75*61046927SAndroid Build Coastguard Worker if (agx_channels(index) > 1) {
76*61046927SAndroid Build Coastguard Worker unsigned last = index.value + agx_size_align_16(index.size) *
77*61046927SAndroid Build Coastguard Worker (agx_channels(index) - 1);
78*61046927SAndroid Build Coastguard Worker
79*61046927SAndroid Build Coastguard Worker fprintf(fp, "...");
80*61046927SAndroid Build Coastguard Worker
81*61046927SAndroid Build Coastguard Worker if (index.memory)
82*61046927SAndroid Build Coastguard Worker fprintf(fp, "m");
83*61046927SAndroid Build Coastguard Worker agx_print_sized('r', last, index.size, fp);
84*61046927SAndroid Build Coastguard Worker }
85*61046927SAndroid Build Coastguard Worker break;
86*61046927SAndroid Build Coastguard Worker
87*61046927SAndroid Build Coastguard Worker default:
88*61046927SAndroid Build Coastguard Worker unreachable("Invalid index type");
89*61046927SAndroid Build Coastguard Worker }
90*61046927SAndroid Build Coastguard Worker
91*61046927SAndroid Build Coastguard Worker /* Print length suffixes if not implied */
92*61046927SAndroid Build Coastguard Worker if (index.type == AGX_INDEX_NORMAL) {
93*61046927SAndroid Build Coastguard Worker if (index.size == AGX_SIZE_16)
94*61046927SAndroid Build Coastguard Worker fprintf(fp, "h");
95*61046927SAndroid Build Coastguard Worker else if (index.size == AGX_SIZE_64)
96*61046927SAndroid Build Coastguard Worker fprintf(fp, "d");
97*61046927SAndroid Build Coastguard Worker }
98*61046927SAndroid Build Coastguard Worker
99*61046927SAndroid Build Coastguard Worker if (index.abs)
100*61046927SAndroid Build Coastguard Worker fprintf(fp, ".abs");
101*61046927SAndroid Build Coastguard Worker
102*61046927SAndroid Build Coastguard Worker if (index.neg)
103*61046927SAndroid Build Coastguard Worker fprintf(fp, ".neg");
104*61046927SAndroid Build Coastguard Worker }
105*61046927SAndroid Build Coastguard Worker
106*61046927SAndroid Build Coastguard Worker static struct agx_opcode_info
agx_get_opcode_info_for_print(const agx_instr * I)107*61046927SAndroid Build Coastguard Worker agx_get_opcode_info_for_print(const agx_instr *I)
108*61046927SAndroid Build Coastguard Worker {
109*61046927SAndroid Build Coastguard Worker struct agx_opcode_info info = agx_opcodes_info[I->op];
110*61046927SAndroid Build Coastguard Worker
111*61046927SAndroid Build Coastguard Worker if (I->op == AGX_OPCODE_BITOP) {
112*61046927SAndroid Build Coastguard Worker const char *bitops[16] = {
113*61046927SAndroid Build Coastguard Worker [AGX_BITOP_NOR] = "nor", [AGX_BITOP_ANDN2] = "andn2",
114*61046927SAndroid Build Coastguard Worker [AGX_BITOP_ANDN1] = "andn1", [AGX_BITOP_XOR] = "xor",
115*61046927SAndroid Build Coastguard Worker [AGX_BITOP_NAND] = "nand", [AGX_BITOP_AND] = "and",
116*61046927SAndroid Build Coastguard Worker [AGX_BITOP_XNOR] = "xnor", [AGX_BITOP_ORN2] = "orn2",
117*61046927SAndroid Build Coastguard Worker [AGX_BITOP_ORN1] = "orn1", [AGX_BITOP_OR] = "or",
118*61046927SAndroid Build Coastguard Worker };
119*61046927SAndroid Build Coastguard Worker
120*61046927SAndroid Build Coastguard Worker if (bitops[I->truth_table] != NULL) {
121*61046927SAndroid Build Coastguard Worker info.name = bitops[I->truth_table];
122*61046927SAndroid Build Coastguard Worker info.immediates &= ~AGX_IMMEDIATE_TRUTH_TABLE;
123*61046927SAndroid Build Coastguard Worker }
124*61046927SAndroid Build Coastguard Worker }
125*61046927SAndroid Build Coastguard Worker
126*61046927SAndroid Build Coastguard Worker return info;
127*61046927SAndroid Build Coastguard Worker }
128*61046927SAndroid Build Coastguard Worker
129*61046927SAndroid Build Coastguard Worker void
agx_print_instr(const agx_instr * I,FILE * fp)130*61046927SAndroid Build Coastguard Worker agx_print_instr(const agx_instr *I, FILE *fp)
131*61046927SAndroid Build Coastguard Worker {
132*61046927SAndroid Build Coastguard Worker assert(I->op < AGX_NUM_OPCODES);
133*61046927SAndroid Build Coastguard Worker struct agx_opcode_info info = agx_get_opcode_info_for_print(I);
134*61046927SAndroid Build Coastguard Worker bool print_comma = false;
135*61046927SAndroid Build Coastguard Worker
136*61046927SAndroid Build Coastguard Worker fprintf(fp, " ");
137*61046927SAndroid Build Coastguard Worker
138*61046927SAndroid Build Coastguard Worker agx_foreach_dest(I, d) {
139*61046927SAndroid Build Coastguard Worker if (print_comma)
140*61046927SAndroid Build Coastguard Worker fprintf(fp, ", ");
141*61046927SAndroid Build Coastguard Worker else
142*61046927SAndroid Build Coastguard Worker print_comma = true;
143*61046927SAndroid Build Coastguard Worker
144*61046927SAndroid Build Coastguard Worker agx_print_index(I->dest[d], false, fp);
145*61046927SAndroid Build Coastguard Worker }
146*61046927SAndroid Build Coastguard Worker
147*61046927SAndroid Build Coastguard Worker if (I->nr_dests) {
148*61046927SAndroid Build Coastguard Worker fprintf(fp, " = ");
149*61046927SAndroid Build Coastguard Worker print_comma = false;
150*61046927SAndroid Build Coastguard Worker }
151*61046927SAndroid Build Coastguard Worker
152*61046927SAndroid Build Coastguard Worker fprintf(fp, "%s", info.name);
153*61046927SAndroid Build Coastguard Worker
154*61046927SAndroid Build Coastguard Worker if (I->saturate)
155*61046927SAndroid Build Coastguard Worker fprintf(fp, ".sat");
156*61046927SAndroid Build Coastguard Worker
157*61046927SAndroid Build Coastguard Worker if (I->last)
158*61046927SAndroid Build Coastguard Worker fprintf(fp, ".last");
159*61046927SAndroid Build Coastguard Worker
160*61046927SAndroid Build Coastguard Worker fprintf(fp, " ");
161*61046927SAndroid Build Coastguard Worker
162*61046927SAndroid Build Coastguard Worker agx_foreach_src(I, s) {
163*61046927SAndroid Build Coastguard Worker if (print_comma)
164*61046927SAndroid Build Coastguard Worker fprintf(fp, ", ");
165*61046927SAndroid Build Coastguard Worker else
166*61046927SAndroid Build Coastguard Worker print_comma = true;
167*61046927SAndroid Build Coastguard Worker
168*61046927SAndroid Build Coastguard Worker agx_print_index(I->src[s],
169*61046927SAndroid Build Coastguard Worker agx_opcodes_info[I->op].is_float &&
170*61046927SAndroid Build Coastguard Worker !(s >= 2 && I->op == AGX_OPCODE_FCMPSEL),
171*61046927SAndroid Build Coastguard Worker fp);
172*61046927SAndroid Build Coastguard Worker }
173*61046927SAndroid Build Coastguard Worker
174*61046927SAndroid Build Coastguard Worker if (I->mask) {
175*61046927SAndroid Build Coastguard Worker fprintf(fp, ", ");
176*61046927SAndroid Build Coastguard Worker
177*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < 4; ++i) {
178*61046927SAndroid Build Coastguard Worker if (I->mask & (1 << i))
179*61046927SAndroid Build Coastguard Worker fprintf(fp, "%c", "xyzw"[i]);
180*61046927SAndroid Build Coastguard Worker }
181*61046927SAndroid Build Coastguard Worker }
182*61046927SAndroid Build Coastguard Worker
183*61046927SAndroid Build Coastguard Worker /* TODO: Do better for enums, truth tables, etc */
184*61046927SAndroid Build Coastguard Worker if (info.immediates) {
185*61046927SAndroid Build Coastguard Worker if (print_comma)
186*61046927SAndroid Build Coastguard Worker fprintf(fp, ", ");
187*61046927SAndroid Build Coastguard Worker else
188*61046927SAndroid Build Coastguard Worker print_comma = true;
189*61046927SAndroid Build Coastguard Worker
190*61046927SAndroid Build Coastguard Worker fprintf(fp, "#%" PRIx64, I->imm);
191*61046927SAndroid Build Coastguard Worker }
192*61046927SAndroid Build Coastguard Worker
193*61046927SAndroid Build Coastguard Worker if (info.immediates & AGX_IMMEDIATE_DIM) {
194*61046927SAndroid Build Coastguard Worker if (print_comma)
195*61046927SAndroid Build Coastguard Worker fprintf(fp, ", ");
196*61046927SAndroid Build Coastguard Worker else
197*61046927SAndroid Build Coastguard Worker print_comma = true;
198*61046927SAndroid Build Coastguard Worker
199*61046927SAndroid Build Coastguard Worker fputs(agx_dim_as_str(I->dim), fp);
200*61046927SAndroid Build Coastguard Worker }
201*61046927SAndroid Build Coastguard Worker
202*61046927SAndroid Build Coastguard Worker if (info.immediates & AGX_IMMEDIATE_SCOREBOARD) {
203*61046927SAndroid Build Coastguard Worker if (print_comma)
204*61046927SAndroid Build Coastguard Worker fprintf(fp, ", ");
205*61046927SAndroid Build Coastguard Worker else
206*61046927SAndroid Build Coastguard Worker print_comma = true;
207*61046927SAndroid Build Coastguard Worker
208*61046927SAndroid Build Coastguard Worker fprintf(fp, "slot %u", I->scoreboard);
209*61046927SAndroid Build Coastguard Worker }
210*61046927SAndroid Build Coastguard Worker
211*61046927SAndroid Build Coastguard Worker if (info.immediates & AGX_IMMEDIATE_NEST) {
212*61046927SAndroid Build Coastguard Worker if (print_comma)
213*61046927SAndroid Build Coastguard Worker fprintf(fp, ", ");
214*61046927SAndroid Build Coastguard Worker else
215*61046927SAndroid Build Coastguard Worker print_comma = true;
216*61046927SAndroid Build Coastguard Worker
217*61046927SAndroid Build Coastguard Worker fprintf(fp, "n=%u", I->nest);
218*61046927SAndroid Build Coastguard Worker }
219*61046927SAndroid Build Coastguard Worker
220*61046927SAndroid Build Coastguard Worker if ((info.immediates & AGX_IMMEDIATE_INVERT_COND) && I->invert_cond) {
221*61046927SAndroid Build Coastguard Worker if (print_comma)
222*61046927SAndroid Build Coastguard Worker fprintf(fp, ", ");
223*61046927SAndroid Build Coastguard Worker else
224*61046927SAndroid Build Coastguard Worker print_comma = true;
225*61046927SAndroid Build Coastguard Worker
226*61046927SAndroid Build Coastguard Worker fprintf(fp, "inv");
227*61046927SAndroid Build Coastguard Worker }
228*61046927SAndroid Build Coastguard Worker
229*61046927SAndroid Build Coastguard Worker fprintf(fp, "\n");
230*61046927SAndroid Build Coastguard Worker }
231*61046927SAndroid Build Coastguard Worker
232*61046927SAndroid Build Coastguard Worker void
agx_print_block(const agx_block * block,FILE * fp)233*61046927SAndroid Build Coastguard Worker agx_print_block(const agx_block *block, FILE *fp)
234*61046927SAndroid Build Coastguard Worker {
235*61046927SAndroid Build Coastguard Worker fprintf(fp, "block%u {\n", block->index);
236*61046927SAndroid Build Coastguard Worker
237*61046927SAndroid Build Coastguard Worker agx_foreach_instr_in_block(block, ins)
238*61046927SAndroid Build Coastguard Worker agx_print_instr(ins, fp);
239*61046927SAndroid Build Coastguard Worker
240*61046927SAndroid Build Coastguard Worker fprintf(fp, "}");
241*61046927SAndroid Build Coastguard Worker
242*61046927SAndroid Build Coastguard Worker if (block->successors[0]) {
243*61046927SAndroid Build Coastguard Worker fprintf(fp, " -> ");
244*61046927SAndroid Build Coastguard Worker
245*61046927SAndroid Build Coastguard Worker agx_foreach_successor(block, succ)
246*61046927SAndroid Build Coastguard Worker fprintf(fp, "block%u ", succ->index);
247*61046927SAndroid Build Coastguard Worker }
248*61046927SAndroid Build Coastguard Worker
249*61046927SAndroid Build Coastguard Worker if (block->predecessors.size) {
250*61046927SAndroid Build Coastguard Worker fprintf(fp, " from");
251*61046927SAndroid Build Coastguard Worker
252*61046927SAndroid Build Coastguard Worker agx_foreach_predecessor(block, pred)
253*61046927SAndroid Build Coastguard Worker fprintf(fp, " block%u", (*pred)->index);
254*61046927SAndroid Build Coastguard Worker }
255*61046927SAndroid Build Coastguard Worker
256*61046927SAndroid Build Coastguard Worker fprintf(fp, "\n\n");
257*61046927SAndroid Build Coastguard Worker }
258*61046927SAndroid Build Coastguard Worker
259*61046927SAndroid Build Coastguard Worker void
agx_print_shader(const agx_context * ctx,FILE * fp)260*61046927SAndroid Build Coastguard Worker agx_print_shader(const agx_context *ctx, FILE *fp)
261*61046927SAndroid Build Coastguard Worker {
262*61046927SAndroid Build Coastguard Worker agx_foreach_block(ctx, block)
263*61046927SAndroid Build Coastguard Worker agx_print_block(block, fp);
264*61046927SAndroid Build Coastguard Worker }
265