2 * Copyright 2013 Vadim Girlin <vadimgirlin@gmail.com>
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:
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
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.
31 #include "sb_shader.h"
36 static const char* chans
= "xyzw01?_";
38 static const char* vec_bs
[] = {
39 "VEC_012", "VEC_021", "VEC_120", "VEC_102", "VEC_201", "VEC_210"
42 static const char* scl_bs
[] = {
43 "SCL_210", "SCL_122", "SCL_212", "SCL_221"
47 bool bc_dump::visit(cf_node
& n
, bool enter
) {
52 if ((n
.bc
.op_ptr
->flags
& CF_ALU
) && n
.bc
.is_alu_extended()) {
61 if (n
.bc
.op_ptr
->flags
& CF_CLAUSE
) {
69 bool bc_dump::visit(alu_node
& n
, bool enter
) {
75 o
<< std::setw(5) << ++group_index
<< " ";
82 new_group
= n
.bc
.last
;
86 static_cast<alu_group_node
*>(n
.get_alu_group_node());
88 for (unsigned k
= 0; k
< g
->literals
.size(); ++k
) {
102 bool bc_dump::visit(fetch_node
& n
, bool enter
) {
112 static void fill_to(std::ostringstream
&s
, int pos
) {
113 int l
= s
.str().length();
115 s
<< std::string(pos
-l
, ' ');
118 void bc_dump::dump(cf_node
& n
) {
119 std::ostringstream s
;
120 s
<< n
.bc
.op_ptr
->name
;
122 if (n
.bc
.op_ptr
->flags
& CF_EXP
) {
123 static const char *exp_type
[] = {"PIXEL", "POS ", "PARAM"};
126 s
<< " " << exp_type
[n
.bc
.type
];
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
<< ".";
135 s
<< " " << std::setw(5) << std::left
<< n
.bc
.array_base
;
136 s
<< "R" << n
.bc
.rw_gpr
<< ".";
139 for (int k
= 0; k
< 4; ++k
)
140 s
<< chans
[n
.bc
.sel
[k
]];
142 } else if (n
.bc
.op_ptr
->flags
& (CF_STRM
| CF_RAT
)) {
143 static const char *exp_type
[] = {"WRITE", "WRITE_IND", "WRITE_ACK",
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
] : '_');
152 if ((n
.bc
.op_ptr
->flags
& CF_RAT
) && (n
.bc
.type
& 1)) {
153 s
<< ", @R" << n
.bc
.index_gpr
<< ".xyz";
156 s
<< " ES:" << n
.bc
.elem_size
;
160 if (n
.bc
.op_ptr
->flags
& CF_CLAUSE
) {
161 s
<< " " << n
.bc
.count
+1;
164 s
<< " @" << (n
.bc
.addr
<< 1);
166 if (n
.bc
.op_ptr
->flags
& CF_ALU
) {
168 for (int k
= 0; k
< 4; ++k
) {
169 bc_kcache
&kc
= n
.bc
.kc
[k
];
171 s
<< " KC" << k
<< "[CB" << kc
.bank
<< ":" <<
172 (kc
.addr
<< 4) << "-" <<
173 (((kc
.addr
+ kc
.mode
) << 4) - 1) << "]";
179 s
<< " CND:" << n
.bc
.pop_count
;
182 s
<< " POP:" << n
.bc
.pop_count
;
188 if (n
.bc
.valid_pixel_mode
)
191 if (n
.bc
.whole_quad_mode
)
194 if (n
.bc
.end_of_program
)
197 o
<< s
.str() << "\n";
201 static void print_sel(std::ostream
&s
, int sel
, int rel
, int index_mode
,
203 if (rel
&& index_mode
>= 5 && sel
< 128)
205 if (rel
|| need_brackets
) {
210 if (index_mode
== 0 || index_mode
== 6)
212 else if (index_mode
== 4)
215 if (rel
|| need_brackets
) {
220 static void print_dst(std::ostream
&s
, bc_alu
&alu
)
222 unsigned sel
= alu
.dst_gpr
;
224 if (sel
>= 128 - 4) { // clause temporary gpr
229 if (alu
.write_mask
|| alu
.op_ptr
->src_count
== 3) {
231 print_sel(s
, sel
, alu
.dst_rel
, alu
.index_mode
, 0);
236 s
<< chans
[alu
.dst_chan
];
239 static void print_src(std::ostream
&s
, bc_alu
&alu
, unsigned idx
)
241 bc_alu_src
*src
= &alu
.src
[idx
];
242 unsigned sel
= src
->sel
, need_sel
= 1, need_chan
= 1, need_brackets
= 0;
251 } else if (sel
< 128) {
254 } else if (sel
< 160) {
258 } else if (sel
< 192) {
262 } else if (sel
>= 448) {
265 } else if (sel
>= 288) {
269 } else if (sel
>= 256) {
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
<< "]";
294 case ALU_SRC_M_1_INT
:
307 s
<< "??IMM_" << sel
;
313 print_sel(s
, sel
, src
->rel
, alu
.index_mode
, need_brackets
);
316 s
<< "." << chans
[src
->chan
];
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";
327 s
<< (n
.bc
.update_exec_mask
? 'M' : ' ');
328 s
<< (n
.bc
.update_pred
? 'P' : ' ');
330 s
<< (n
.bc
.pred_sel
>=2 ? (n
.bc
.pred_sel
== 2 ? '0' : '1') : ' ');
333 s
<< slots
[n
.bc
.slot
] << ": ";
335 s
<< n
.bc
.op_ptr
->name
<< omod_str
[n
.bc
.omod
] << (n
.bc
.clamp
? "_sat" : "");
340 for (int k
= 0; k
< n
.bc
.op_ptr
->src_count
; ++k
) {
341 s
<< (k
? ", " : ", ");
342 print_src(s
, n
.bc
, k
);
345 if (n
.bc
.bank_swizzle
) {
347 if (n
.bc
.slot
== SLOT_TRANS
)
348 s
<< " " << scl_bs
[n
.bc
.bank_swizzle
];
350 s
<< " " << vec_bs
[n
.bc
.bank_swizzle
];
353 o
<< s
.str() << "\n";
356 int bc_dump::init() {
357 std::ostringstream s
;
358 s
<< "===== SHADER #" << sh
.id
;
365 std::string target
= std::string(" ") +
366 sh
.get_full_target_name() + " =====";
368 while (s
.str().length() + target
.length() < 80)
373 o
<< "\n" << s
.str() << "\n";
375 s
.str(std::string());
378 s
<< "===== " << ndw
<< " dw ===== " << sh
.ngpr
379 << " gprs ===== " << sh
.nstack
<< " stack ";
382 while (s
.str().length() < 80)
385 o
<< s
.str() << "\n";
390 int bc_dump::done() {
391 std::ostringstream s
;
392 s
<< "===== SHADER_END ";
394 while (s
.str().length() < 80)
397 o
<< s
.str() << "\n\n";
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() {
407 bc_data
= bc
->data();
412 void bc_dump::dump(fetch_node
& n
) {
413 std::ostringstream s
;
414 static const char * fetch_type
[] = {"VERTEX", "INSTANCE", ""};
416 s
<< n
.bc
.op_ptr
->name
;
420 print_sel(s
, n
.bc
.dst_gpr
, n
.bc
.dst_rel
, INDEX_LOOP
, 0);
422 for (int k
= 0; k
< 4; ++k
)
423 s
<< chans
[n
.bc
.dst_sel
[k
]];
427 print_sel(s
, n
.bc
.src_gpr
, n
.bc
.src_rel
, INDEX_LOOP
, 0);
430 unsigned vtx
= n
.bc
.op_ptr
->flags
& FF_VTX
;
431 unsigned num_src_comp
= vtx
? ctx
.is_cayman() ? 2 : 1 : 4;
433 for (unsigned k
= 0; k
< num_src_comp
; ++k
)
434 s
<< chans
[n
.bc
.src_sel
[k
]];
436 if (vtx
&& n
.bc
.offset
[0]) {
437 s
<< " + " << n
.bc
.offset
[0] << "b ";
440 s
<< ", RID:" << n
.bc
.resource_id
;
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
)
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
<< ")";
454 s
<< ", SID:" << n
.bc
.sampler_id
;
456 s
<< " LB:" << n
.bc
.lod_bias
;
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
)
462 s
<< " O" << chans
[k
] << ":" << n
.bc
.offset
[k
];
465 o
<< s
.str() << "\n";
468 void bc_dump::dump_dw(unsigned dw_id
, unsigned count
) {
472 assert(dw_id
+ count
<= ndw
);
474 o
<< std::setfill('0') << std::setw(4) << dw_id
<< " ";
476 o
<< std::setw(8) << std::hex
<< bc_data
[dw_id
++] << " ";
478 o
<< std::setfill(' ') << std::dec
;
481 } // namespace r600_sb