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