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.
28 #include "sb_shader.h"
30 #include "eg_sq.h" // V_SQ_CF_INDEX_0/1
34 static const char* chans
= "xyzw01?_";
36 static const char* vec_bs
[] = {
37 "VEC_012", "VEC_021", "VEC_120", "VEC_102", "VEC_201", "VEC_210"
40 static const char* scl_bs
[] = {
41 "SCL_210", "SCL_122", "SCL_212", "SCL_221"
45 bool bc_dump::visit(cf_node
& n
, bool enter
) {
50 if ((n
.bc
.op_ptr
->flags
& CF_ALU
) && n
.bc
.is_alu_extended()) {
59 if (n
.bc
.op_ptr
->flags
& CF_CLAUSE
) {
67 bool bc_dump::visit(alu_node
& n
, bool enter
) {
73 sblog
.print_w(++group_index
, 5);
81 new_group
= n
.bc
.last
;
85 static_cast<alu_group_node
*>(n
.get_alu_group_node());
87 for (unsigned k
= 0; k
< g
->literals
.size(); ++k
) {
101 bool bc_dump::visit(fetch_node
& n
, bool enter
) {
111 static void fill_to(sb_ostringstream
&s
, int pos
) {
112 int l
= s
.str().length();
114 s
<< std::string(pos
-l
, ' ');
117 void bc_dump::dump(cf_node
& n
) {
119 s
<< n
.bc
.op_ptr
->name
;
121 if (n
.bc
.op_ptr
->flags
& CF_EXP
) {
122 static const char *exp_type
[] = {"PIXEL", "POS ", "PARAM"};
125 s
<< " " << exp_type
[n
.bc
.type
] << " ";
127 if (n
.bc
.burst_count
) {
129 s2
<< n
.bc
.array_base
<< "-" << n
.bc
.array_base
+ n
.bc
.burst_count
;
130 s
.print_wl(s2
.str(), 5);
131 s
<< " R" << n
.bc
.rw_gpr
<< "-" <<
132 n
.bc
.rw_gpr
+ n
.bc
.burst_count
<< ".";
134 s
.print_wl(n
.bc
.array_base
, 5);
135 s
<< " R" << n
.bc
.rw_gpr
<< ".";
138 for (int k
= 0; k
< 4; ++k
)
139 s
<< chans
[n
.bc
.sel
[k
]];
141 } else if (n
.bc
.op_ptr
->flags
& CF_MEM
) {
142 static const char *exp_type
[] = {"WRITE", "WRITE_IND", "WRITE_ACK",
145 s
<< " " << exp_type
[n
.bc
.type
] << " ";
146 s
.print_wl(n
.bc
.array_base
, 5);
147 s
<< " R" << n
.bc
.rw_gpr
<< ".";
148 for (int k
= 0; k
< 4; ++k
)
149 s
<< ((n
.bc
.comp_mask
& (1 << k
)) ? chans
[k
] : '_');
151 if ((n
.bc
.op_ptr
->flags
& CF_RAT
) && (n
.bc
.type
& 1)) {
152 s
<< ", @R" << n
.bc
.index_gpr
<< ".xyz";
154 if ((n
.bc
.op_ptr
->flags
& CF_MEM
) && (n
.bc
.type
& 1)) {
155 s
<< ", @R" << n
.bc
.index_gpr
<< ".x";
158 s
<< " ES:" << n
.bc
.elem_size
;
162 if (n
.bc
.op_ptr
->flags
& CF_CLAUSE
) {
163 s
<< " " << n
.bc
.count
+1;
166 s
<< " @" << (n
.bc
.addr
<< 1);
168 if (n
.bc
.op_ptr
->flags
& CF_ALU
) {
169 static const char *index_mode
[] = {"", " CF_INDEX_0", " CF_INDEX_1"};
171 for (int k
= 0; k
< 4; ++k
) {
172 bc_kcache
&kc
= n
.bc
.kc
[k
];
174 s
<< " KC" << k
<< "[CB" << kc
.bank
<< ":" <<
175 (kc
.addr
<< 4) << "-" <<
176 (((kc
.addr
+ kc
.mode
) << 4) - 1) << index_mode
[kc
.index_mode
] << "]";
182 s
<< " CND:" << n
.bc
.cond
;
185 s
<< " POP:" << n
.bc
.pop_count
;
187 if (n
.bc
.count
&& (n
.bc
.op_ptr
->flags
& CF_EMIT
))
188 s
<< " STREAM" << n
.bc
.count
;
194 if (n
.bc
.valid_pixel_mode
)
197 if (n
.bc
.whole_quad_mode
)
200 if (n
.bc
.end_of_program
)
203 sblog
<< s
.str() << "\n";
207 static void print_sel(sb_ostream
&s
, int sel
, int rel
, int index_mode
,
209 if (rel
&& index_mode
>= 5 && sel
< 128)
211 if (rel
|| need_brackets
) {
216 if (index_mode
== 0 || index_mode
== 6)
218 else if (index_mode
== 4)
221 if (rel
|| need_brackets
) {
226 static void print_dst(sb_ostream
&s
, bc_alu
&alu
)
228 unsigned sel
= alu
.dst_gpr
;
230 if (sel
>= 128 - 4) { // clause temporary gpr
235 if (alu
.write_mask
|| alu
.op_ptr
->src_count
== 3) {
237 print_sel(s
, sel
, alu
.dst_rel
, alu
.index_mode
, 0);
242 s
<< chans
[alu
.dst_chan
];
245 static void print_src(sb_ostream
&s
, bc_alu
&alu
, unsigned idx
)
247 bc_alu_src
*src
= &alu
.src
[idx
];
248 unsigned sel
= src
->sel
, need_sel
= 1, need_chan
= 1, need_brackets
= 0;
257 } else if (sel
< 128) {
260 } else if (sel
< 160) {
264 } else if (sel
< 192) {
268 } else if (sel
>= 448) {
271 } else if (sel
>= 288) {
275 } else if (sel
>= 256) {
283 case ALU_SRC_LDS_OQ_A
:
287 case ALU_SRC_LDS_OQ_B
:
291 case ALU_SRC_LDS_OQ_A_POP
:
295 case ALU_SRC_LDS_OQ_B_POP
:
299 case ALU_SRC_LDS_DIRECT_A
:
300 s
<< "LDS_A["; s
.print_zw_hex(src
->value
.u
, 8); s
<< "]";
302 case ALU_SRC_LDS_DIRECT_B
:
303 s
<< "LDS_B["; s
.print_zw_hex(src
->value
.u
, 8); s
<< "]";
312 case ALU_SRC_LITERAL
:
314 s
.print_zw_hex(src
->value
.u
, 8);
315 s
<< " " << src
->value
.f
<< "]";
321 case ALU_SRC_M_1_INT
:
334 s
<< "??IMM_" << sel
;
340 print_sel(s
, sel
, src
->rel
, alu
.index_mode
, need_brackets
);
343 s
<< "." << chans
[src
->chan
];
349 void bc_dump::dump(alu_node
& n
) {
351 static const char *omod_str
[] = {"","*2","*4","/2"};
352 static const char *slots
= "xyzwt";
354 s
<< (n
.bc
.update_exec_mask
? "M" : " ");
355 s
<< (n
.bc
.update_pred
? "P" : " ");
357 s
<< (n
.bc
.pred_sel
>=2 ? (n
.bc
.pred_sel
== 2 ? "0" : "1") : " ");
360 s
<< slots
[n
.bc
.slot
] << ": ";
362 s
<< n
.bc
.op_ptr
->name
<< omod_str
[n
.bc
.omod
] << (n
.bc
.clamp
? "_sat" : "");
367 for (int k
= 0; k
< n
.bc
.op_ptr
->src_count
; ++k
) {
368 s
<< (k
? ", " : ", ");
369 print_src(s
, n
.bc
, k
);
372 if (n
.bc
.bank_swizzle
) {
374 if (n
.bc
.slot
== SLOT_TRANS
)
375 s
<< " " << scl_bs
[n
.bc
.bank_swizzle
];
377 s
<< " " << vec_bs
[n
.bc
.bank_swizzle
];
380 if (ctx
.is_cayman()) {
381 if (n
.bc
.op
== ALU_OP1_MOVA_INT
) {
382 static const char *mova_str
[] = { " AR_X", " PC", " CF_IDX0", " CF_IDX1",
383 " Unknown MOVA_INT dest" };
384 s
<< mova_str
[std::min(n
.bc
.dst_gpr
, 4u)]; // CM_V_SQ_MOVA_DST_AR_*
388 if (n
.bc
.lds_idx_offset
) {
389 s
<< " IDX_OFFSET:" << n
.bc
.lds_idx_offset
;
392 sblog
<< s
.str() << "\n";
395 int bc_dump::init() {
397 s
<< "===== SHADER #" << sh
.id
;
404 std::string target
= std::string(" ") +
405 sh
.get_full_target_name() + " =====";
407 while (s
.str().length() + target
.length() < 80)
412 sblog
<< "\n" << s
.str() << "\n";
417 s
<< "===== " << ndw
<< " dw ===== " << sh
.ngpr
418 << " gprs ===== " << sh
.nstack
<< " stack ";
421 while (s
.str().length() < 80)
424 sblog
<< s
.str() << "\n";
429 int bc_dump::done() {
431 s
<< "===== SHADER_END ";
433 while (s
.str().length() < 80)
436 sblog
<< s
.str() << "\n\n";
441 bc_dump::bc_dump(shader
& s
, bytecode
* bc
) :
442 vpass(s
), bc_data(), ndw(), id(),
443 new_group(), group_index() {
446 bc_data
= bc
->data();
451 void bc_dump::dump(fetch_node
& n
) {
453 static const char * fetch_type
[] = {"VERTEX", "INSTANCE", ""};
454 unsigned gds
= n
.bc
.op_ptr
->flags
& FF_GDS
;
456 s
<< n
.bc
.op_ptr
->name
;
461 print_sel(s
, n
.bc
.dst_gpr
, n
.bc
.dst_rel
, INDEX_LOOP
, 0);
463 for (int k
= 0; k
< 4; ++k
)
464 s
<< chans
[n
.bc
.dst_sel
[k
]];
469 print_sel(s
, n
.bc
.src_gpr
, n
.bc
.src_rel
, INDEX_LOOP
, 0);
472 unsigned vtx
= n
.bc
.op_ptr
->flags
& FF_VTX
;
473 unsigned num_src_comp
= gds
? 3 : vtx
? ctx
.is_cayman() ? 2 : 1 : 4;
475 for (unsigned k
= 0; k
< num_src_comp
; ++k
)
476 s
<< chans
[n
.bc
.src_sel
[k
]];
478 if (vtx
&& n
.bc
.offset
[0]) {
479 s
<< " + " << n
.bc
.offset
[0] << "b ";
483 s
<< ", RID:" << n
.bc
.resource_id
;
488 s
<< " " << fetch_type
[n
.bc
.fetch_type
];
489 if (!ctx
.is_cayman() && n
.bc
.mega_fetch_count
)
490 s
<< " MFC:" << n
.bc
.mega_fetch_count
;
491 if (n
.bc
.fetch_whole_quad
)
493 if (ctx
.is_egcm() && n
.bc
.resource_index_mode
)
494 s
<< " RIM:SQ_CF_INDEX_" << (n
.bc
.resource_index_mode
- V_SQ_CF_INDEX_0
);
495 if (ctx
.is_egcm() && n
.bc
.sampler_index_mode
)
496 s
<< " SID:SQ_CF_INDEX_" << (n
.bc
.sampler_index_mode
- V_SQ_CF_INDEX_0
);
498 s
<< " UCF:" << n
.bc
.use_const_fields
499 << " FMT(DTA:" << n
.bc
.data_format
500 << " NUM:" << n
.bc
.num_format_all
501 << " COMP:" << n
.bc
.format_comp_all
502 << " MODE:" << n
.bc
.srf_mode_all
<< ")";
504 s
<< ", SID:" << n
.bc
.sampler_id
;
506 s
<< " LB:" << n
.bc
.lod_bias
;
508 for (unsigned k
= 0; k
< 4; ++k
)
509 s
<< (n
.bc
.coord_type
[k
] ? "N" : "U");
510 for (unsigned k
= 0; k
< 3; ++k
)
512 s
<< " O" << chans
[k
] << ":" << n
.bc
.offset
[k
];
513 if (ctx
.is_egcm() && n
.bc
.resource_index_mode
)
514 s
<< " RIM:SQ_CF_INDEX_" << (n
.bc
.resource_index_mode
- V_SQ_CF_INDEX_0
);
515 if (ctx
.is_egcm() && n
.bc
.sampler_index_mode
)
516 s
<< " SID:SQ_CF_INDEX_" << (n
.bc
.sampler_index_mode
- V_SQ_CF_INDEX_0
);
519 sblog
<< s
.str() << "\n";
522 void bc_dump::dump_dw(unsigned dw_id
, unsigned count
) {
526 assert(dw_id
+ count
<= ndw
);
528 sblog
.print_zw(dw_id
, 4);
531 sblog
.print_zw_hex(bc_data
[dw_id
++], 8);
536 } // namespace r600_sb