r600g/sb: fix kcache handling on r6xx
[mesa.git] / src / gallium / drivers / r600 / sb / sb_bc_dump.cpp
1 /*
2 * Copyright 2013 Vadim Girlin <vadimgirlin@gmail.com>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE.
22 *
23 * Authors:
24 * Vadim Girlin
25 */
26
27 #include <sstream>
28 #include <iomanip>
29
30 #include "sb_bc.h"
31 #include "sb_shader.h"
32 #include "sb_pass.h"
33
34 namespace r600_sb {
35
36 static const char* chans = "xyzw01?_";
37
38 static const char* vec_bs[] = {
39 "VEC_012", "VEC_021", "VEC_120", "VEC_102", "VEC_201", "VEC_210"
40 };
41
42 static const char* scl_bs[] = {
43 "SCL_210", "SCL_122", "SCL_212", "SCL_221"
44 };
45
46
47 bool bc_dump::visit(cf_node& n, bool enter) {
48 if (enter) {
49
50 id = n.bc.id << 1;
51
52 if ((n.bc.op_ptr->flags & CF_ALU) && n.bc.is_alu_extended()) {
53 dump_dw(id, 2);
54 id += 2;
55 o << "\n";
56 }
57
58 dump_dw(id, 2);
59 dump(n);
60
61 if (n.bc.op_ptr->flags & CF_CLAUSE) {
62 id = n.bc.addr << 1;
63 new_group = 1;
64 }
65 }
66 return true;
67 }
68
69 bool bc_dump::visit(alu_node& n, bool enter) {
70 if (enter) {
71 o << " ";
72 dump_dw(id, 2);
73
74 if (new_group)
75 o << std::setw(5) << ++group_index << " ";
76 else
77 o << " ";
78
79 dump(n);
80 id += 2;
81
82 new_group = n.bc.last;
83 } else {
84 if (n.bc.last) {
85 alu_group_node *g =
86 static_cast<alu_group_node*>(n.get_alu_group_node());
87 assert(g);
88 for (unsigned k = 0; k < g->literals.size(); ++k) {
89 o << " ";
90 dump_dw(id, 1);
91 id += 1;
92 o << "\n";
93 }
94
95 id = (id + 1) & ~1u;
96 }
97 }
98
99 return false;
100 }
101
102 bool bc_dump::visit(fetch_node& n, bool enter) {
103 if (enter) {
104 o << " ";
105 dump_dw(id, 3);
106 dump(n);
107 id += 4;
108 }
109 return false;
110 }
111
112 static void fill_to(std::ostringstream &s, int pos) {
113 int l = s.str().length();
114 if (l < pos)
115 s << std::string(pos-l, ' ');
116 }
117
118 void bc_dump::dump(cf_node& n) {
119 std::ostringstream s;
120 s << n.bc.op_ptr->name;
121
122 if (n.bc.op_ptr->flags & CF_EXP) {
123 static const char *exp_type[] = {"PIXEL", "POS ", "PARAM"};
124
125 fill_to(s, 18);
126 s << " " << exp_type[n.bc.type];
127
128 if (n.bc.burst_count) {
129 std::ostringstream s2;
130 s2 << n.bc.array_base << "-" << n.bc.array_base + n.bc.burst_count;
131 s << " " << std::setw(5) << std::left << s2.str();
132 s << "R" << n.bc.rw_gpr << "-" <<
133 n.bc.rw_gpr + n.bc.burst_count << ".";
134 } else {
135 s << " " << std::setw(5) << std::left << n.bc.array_base;
136 s << "R" << n.bc.rw_gpr << ".";
137 }
138
139 for (int k = 0; k < 4; ++k)
140 s << chans[n.bc.sel[k]];
141
142 } else if (n.bc.op_ptr->flags & (CF_STRM | CF_RAT)) {
143 static const char *exp_type[] = {"WRITE", "WRITE_IND", "WRITE_ACK",
144 "WRITE_IND_ACK"};
145 fill_to(s, 18);
146 s << " " << exp_type[n.bc.type];
147 s << " " << std::setw(5) << std::left << n.bc.array_base;
148 s << "R" << n.bc.rw_gpr << ".";
149 for (int k = 0; k < 4; ++k)
150 s << ((n.bc.comp_mask & (1 << k)) ? chans[k] : '_');
151
152 if ((n.bc.op_ptr->flags & CF_RAT) && (n.bc.type & 1)) {
153 s << ", @R" << n.bc.index_gpr << ".xyz";
154 }
155
156 s << " ES:" << n.bc.elem_size;
157
158 } else {
159
160 if (n.bc.op_ptr->flags & CF_CLAUSE) {
161 s << " " << n.bc.count+1;
162 }
163
164 s << " @" << (n.bc.addr << 1);
165
166 if (n.bc.op_ptr->flags & CF_ALU) {
167
168 for (int k = 0; k < 4; ++k) {
169 bc_kcache &kc = n.bc.kc[k];
170 if (kc.mode) {
171 s << " KC" << k << "[CB" << kc.bank << ":" <<
172 (kc.addr << 4) << "-" <<
173 (((kc.addr + kc.mode) << 4) - 1) << "]";
174 }
175 }
176 }
177
178 if (n.bc.cond)
179 s << " CND:" << n.bc.pop_count;
180
181 if (n.bc.pop_count)
182 s << " POP:" << n.bc.pop_count;
183 }
184
185 if (!n.bc.barrier)
186 s << " NO_BARRIER";
187
188 if (n.bc.valid_pixel_mode)
189 s << " VPM";
190
191 if (n.bc.whole_quad_mode)
192 s << " WQM";
193
194 if (n.bc.end_of_program)
195 s << " EOP";
196
197 o << s.str() << "\n";
198 }
199
200
201 static void print_sel(std::ostream &s, int sel, int rel, int index_mode,
202 int need_brackets) {
203 if (rel && index_mode >= 5 && sel < 128)
204 s << "G";
205 if (rel || need_brackets) {
206 s << "[";
207 }
208 s << sel;
209 if (rel) {
210 if (index_mode == 0 || index_mode == 6)
211 s << "+AR";
212 else if (index_mode == 4)
213 s << "+AL";
214 }
215 if (rel || need_brackets) {
216 s << "]";
217 }
218 }
219
220 static void print_dst(std::ostream &s, bc_alu &alu)
221 {
222 unsigned sel = alu.dst_gpr;
223 char reg_char = 'R';
224 if (sel >= 128 - 4) { // clause temporary gpr
225 sel -= 128 - 4;
226 reg_char = 'T';
227 }
228
229 if (alu.write_mask || alu.op_ptr->src_count == 3) {
230 s << reg_char;
231 print_sel(s, sel, alu.dst_rel, alu.index_mode, 0);
232 } else {
233 s << "__";
234 }
235 s << ".";
236 s << chans[alu.dst_chan];
237 }
238
239 static void print_src(std::ostream &s, bc_alu &alu, unsigned idx)
240 {
241 bc_alu_src *src = &alu.src[idx];
242 unsigned sel = src->sel, need_sel = 1, need_chan = 1, need_brackets = 0;
243
244 if (src->neg)
245 s <<"-";
246 if (src->abs)
247 s <<"|";
248
249 if (sel < 128 - 4) {
250 s << "R";
251 } else if (sel < 128) {
252 s << "T";
253 sel -= 128 - 4;
254 } else if (sel < 160) {
255 s << "KC0";
256 need_brackets = 1;
257 sel -= 128;
258 } else if (sel < 192) {
259 s << "KC1";
260 need_brackets = 1;
261 sel -= 160;
262 } else if (sel >= 448) {
263 s << "Param";
264 sel -= 448;
265 } else if (sel >= 288) {
266 s << "KC3";
267 need_brackets = 1;
268 sel -= 288;
269 } else if (sel >= 256) {
270 s << "KC2";
271 need_brackets = 1;
272 sel -= 256;
273 } else {
274 need_sel = 0;
275 need_chan = 0;
276 switch (sel) {
277 case ALU_SRC_PS:
278 s << "PS";
279 break;
280 case ALU_SRC_PV:
281 s << "PV";
282 need_chan = 1;
283 break;
284 case ALU_SRC_LITERAL:
285 s << "[" << std::hex << std::setfill('0') << std::setw(8)
286 << std::showbase << src->value.u << " "
287 << std::noshowbase << std::setfill(' ') << std::dec
288 << src->value.f << "]";
289 need_chan = 1;
290 break;
291 case ALU_SRC_0_5:
292 s << "0.5";
293 break;
294 case ALU_SRC_M_1_INT:
295 s << "-1";
296 break;
297 case ALU_SRC_1_INT:
298 s << "1";
299 break;
300 case ALU_SRC_1:
301 s << "1.0";
302 break;
303 case ALU_SRC_0:
304 s << "0";
305 break;
306 default:
307 s << "??IMM_" << sel;
308 break;
309 }
310 }
311
312 if (need_sel)
313 print_sel(s, sel, src->rel, alu.index_mode, need_brackets);
314
315 if (need_chan) {
316 s << "." << chans[src->chan];
317 }
318
319 if (src->abs)
320 s << "|";
321 }
322 void bc_dump::dump(alu_node& n) {
323 std::ostringstream s;
324 static const char *omod_str[] = {"","*2","*4","/2"};
325 static const char *slots = "xyzwt";
326
327 s << (n.bc.update_exec_mask ? 'M' : ' ');
328 s << (n.bc.update_pred ? 'P' : ' ');
329 s << " ";
330 s << (n.bc.pred_sel>=2 ? (n.bc.pred_sel == 2 ? '0' : '1') : ' ');
331 s << " ";
332
333 s << slots[n.bc.slot] << ": ";
334
335 s << n.bc.op_ptr->name << omod_str[n.bc.omod] << (n.bc.clamp ? "_sat" : "");
336 fill_to(s, 26);
337 s << " ";
338
339 print_dst(s, n.bc);
340 for (int k = 0; k < n.bc.op_ptr->src_count; ++k) {
341 s << (k ? ", " : ", ");
342 print_src(s, n.bc, k);
343 }
344
345 if (n.bc.bank_swizzle) {
346 fill_to(s, 55);
347 if (n.bc.slot == SLOT_TRANS)
348 s << " " << scl_bs[n.bc.bank_swizzle];
349 else
350 s << " " << vec_bs[n.bc.bank_swizzle];
351 }
352
353 o << s.str() << "\n";
354 }
355
356 int bc_dump::init() {
357 std::ostringstream s;
358 s << "===== SHADER #" << sh.id;
359
360 if (sh.optimized)
361 s << " OPT";
362
363 s << " ";
364
365 std::string target = std::string(" ") +
366 sh.get_full_target_name() + " =====";
367
368 while (s.str().length() + target.length() < 80)
369 s << "=";
370
371 s << target;
372
373 o << "\n" << s.str() << "\n";
374
375 s.str(std::string());
376
377 if (bc_data) {
378 s << "===== " << ndw << " dw ===== " << sh.ngpr
379 << " gprs ===== " << sh.nstack << " stack ";
380 }
381
382 while (s.str().length() < 80)
383 s << "=";
384
385 o << s.str() << "\n";
386
387 return 0;
388 }
389
390 int bc_dump::done() {
391 std::ostringstream s;
392 s << "===== SHADER_END ";
393
394 while (s.str().length() < 80)
395 s << "=";
396
397 o << s.str() << "\n\n";
398
399 return 0;
400 }
401
402 bc_dump::bc_dump(shader& s, std::ostream& o, bytecode* bc) :
403 vpass(s), o(o), bc_data(), ndw(), id(),
404 new_group(), group_index() {
405
406 if (bc) {
407 bc_data = bc->data();
408 ndw = bc->ndw();
409 }
410 }
411
412 void bc_dump::dump(fetch_node& n) {
413 std::ostringstream s;
414 static const char * fetch_type[] = {"VERTEX", "INSTANCE", ""};
415
416 s << n.bc.op_ptr->name;
417 fill_to(s, 20);
418
419 s << "R";
420 print_sel(s, n.bc.dst_gpr, n.bc.dst_rel, INDEX_LOOP, 0);
421 s << ".";
422 for (int k = 0; k < 4; ++k)
423 s << chans[n.bc.dst_sel[k]];
424 s << ", ";
425
426 s << "R";
427 print_sel(s, n.bc.src_gpr, n.bc.src_rel, INDEX_LOOP, 0);
428 s << ".";
429
430 unsigned vtx = n.bc.op_ptr->flags & FF_VTX;
431 unsigned num_src_comp = vtx ? ctx.is_cayman() ? 2 : 1 : 4;
432
433 for (unsigned k = 0; k < num_src_comp; ++k)
434 s << chans[n.bc.src_sel[k]];
435
436 if (vtx && n.bc.offset[0]) {
437 s << " + " << n.bc.offset[0] << "b ";
438 }
439
440 s << ", RID:" << n.bc.resource_id;
441
442 if (vtx) {
443 s << " " << fetch_type[n.bc.fetch_type];
444 if (!ctx.is_cayman() && n.bc.mega_fetch_count)
445 s << " MFC:" << n.bc.mega_fetch_count;
446 if (n.bc.fetch_whole_quad)
447 s << " FWQ";
448 s << " UCF:" << n.bc.use_const_fields
449 << " FMT(DTA:" << n.bc.data_format
450 << " NUM:" << n.bc.num_format_all
451 << " COMP:" << n.bc.format_comp_all
452 << " MODE:" << n.bc.srf_mode_all << ")";
453 } else {
454 s << ", SID:" << n.bc.sampler_id;
455 if (n.bc.lod_bias)
456 s << " LB:" << n.bc.lod_bias;
457 s << " CT:";
458 for (unsigned k = 0; k < 4; ++k)
459 s << (n.bc.coord_type[k] ? "N" : "U");
460 for (unsigned k = 0; k < 3; ++k)
461 if (n.bc.offset[k])
462 s << " O" << chans[k] << ":" << n.bc.offset[k];
463 }
464
465 o << s.str() << "\n";
466 }
467
468 void bc_dump::dump_dw(unsigned dw_id, unsigned count) {
469 if (!bc_data)
470 return;
471
472 assert(dw_id + count <= ndw);
473
474 o << std::setfill('0') << std::setw(4) << dw_id << " ";
475 while (count--) {
476 o << std::setw(8) << std::hex << bc_data[dw_id++] << " ";
477 }
478 o << std::setfill(' ') << std::dec;
479 }
480
481 } // namespace r600_sb