1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright (C) 2014 Rob Clark <robclark@freedesktop.org> 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21bf215546Sopenharmony_ci * SOFTWARE. 22bf215546Sopenharmony_ci * 23bf215546Sopenharmony_ci * Authors: 24bf215546Sopenharmony_ci * Rob Clark <robclark@freedesktop.org> 25bf215546Sopenharmony_ci */ 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#include <stdarg.h> 28bf215546Sopenharmony_ci#include <stdio.h> 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci#include "util/log.h" 31bf215546Sopenharmony_ci#include "ir3.h" 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_ci#define PTRID(x) ((unsigned long)(x)) 34bf215546Sopenharmony_ci 35bf215546Sopenharmony_ci/* ansi escape sequences: */ 36bf215546Sopenharmony_ci#define RESET "\x1b[0m" 37bf215546Sopenharmony_ci#define RED "\x1b[0;31m" 38bf215546Sopenharmony_ci#define GREEN "\x1b[0;32m" 39bf215546Sopenharmony_ci#define BLUE "\x1b[0;34m" 40bf215546Sopenharmony_ci#define MAGENTA "\x1b[0;35m" 41bf215546Sopenharmony_ci 42bf215546Sopenharmony_ci/* syntax coloring, mostly to make it easier to see different sorts of 43bf215546Sopenharmony_ci * srcs (immediate, constant, ssa, array, ...) 44bf215546Sopenharmony_ci */ 45bf215546Sopenharmony_ci#define SYN_REG(x) RED x RESET 46bf215546Sopenharmony_ci#define SYN_IMMED(x) GREEN x RESET 47bf215546Sopenharmony_ci#define SYN_CONST(x) GREEN x RESET 48bf215546Sopenharmony_ci#define SYN_SSA(x) BLUE x RESET 49bf215546Sopenharmony_ci#define SYN_ARRAY(x) MAGENTA x RESET 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_cistatic const char * 52bf215546Sopenharmony_citype_name(type_t type) 53bf215546Sopenharmony_ci{ 54bf215546Sopenharmony_ci static const char *type_names[] = { 55bf215546Sopenharmony_ci /* clang-format off */ 56bf215546Sopenharmony_ci [TYPE_F16] = "f16", 57bf215546Sopenharmony_ci [TYPE_F32] = "f32", 58bf215546Sopenharmony_ci [TYPE_U16] = "u16", 59bf215546Sopenharmony_ci [TYPE_U32] = "u32", 60bf215546Sopenharmony_ci [TYPE_S16] = "s16", 61bf215546Sopenharmony_ci [TYPE_S32] = "s32", 62bf215546Sopenharmony_ci [TYPE_U8] = "u8", 63bf215546Sopenharmony_ci [TYPE_S8] = "s8", 64bf215546Sopenharmony_ci /* clang-format on */ 65bf215546Sopenharmony_ci }; 66bf215546Sopenharmony_ci return type_names[type]; 67bf215546Sopenharmony_ci} 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_cistatic void 70bf215546Sopenharmony_ciprint_instr_name(struct log_stream *stream, struct ir3_instruction *instr, 71bf215546Sopenharmony_ci bool flags) 72bf215546Sopenharmony_ci{ 73bf215546Sopenharmony_ci if (!instr) 74bf215546Sopenharmony_ci return; 75bf215546Sopenharmony_ci#ifdef DEBUG 76bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "%04u:", instr->serialno); 77bf215546Sopenharmony_ci#endif 78bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "%04u:", instr->ip); 79bf215546Sopenharmony_ci if (instr->flags & IR3_INSTR_UNUSED) { 80bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "XXX: "); 81bf215546Sopenharmony_ci } else { 82bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "%03u: ", instr->use_count); 83bf215546Sopenharmony_ci } 84bf215546Sopenharmony_ci 85bf215546Sopenharmony_ci if (flags) { 86bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "\t"); 87bf215546Sopenharmony_ci if (instr->flags & IR3_INSTR_SY) 88bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "(sy)"); 89bf215546Sopenharmony_ci if (instr->flags & IR3_INSTR_SS) 90bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "(ss)"); 91bf215546Sopenharmony_ci if (instr->flags & IR3_INSTR_JP) 92bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "(jp)"); 93bf215546Sopenharmony_ci if (instr->repeat) 94bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "(rpt%d)", instr->repeat); 95bf215546Sopenharmony_ci if (instr->nop) 96bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "(nop%d)", instr->nop); 97bf215546Sopenharmony_ci if (instr->flags & IR3_INSTR_UL) 98bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "(ul)"); 99bf215546Sopenharmony_ci } else { 100bf215546Sopenharmony_ci mesa_log_stream_printf(stream, " "); 101bf215546Sopenharmony_ci } 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_ci if (is_meta(instr)) { 104bf215546Sopenharmony_ci switch (instr->opc) { 105bf215546Sopenharmony_ci case OPC_META_INPUT: 106bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "_meta:in"); 107bf215546Sopenharmony_ci break; 108bf215546Sopenharmony_ci case OPC_META_SPLIT: 109bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "_meta:split"); 110bf215546Sopenharmony_ci break; 111bf215546Sopenharmony_ci case OPC_META_COLLECT: 112bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "_meta:collect"); 113bf215546Sopenharmony_ci break; 114bf215546Sopenharmony_ci case OPC_META_TEX_PREFETCH: 115bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "_meta:tex_prefetch"); 116bf215546Sopenharmony_ci break; 117bf215546Sopenharmony_ci case OPC_META_PARALLEL_COPY: 118bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "_meta:parallel_copy"); 119bf215546Sopenharmony_ci break; 120bf215546Sopenharmony_ci case OPC_META_PHI: 121bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "_meta:phi"); 122bf215546Sopenharmony_ci break; 123bf215546Sopenharmony_ci 124bf215546Sopenharmony_ci /* shouldn't hit here.. just for debugging: */ 125bf215546Sopenharmony_ci default: 126bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "_meta:%d", instr->opc); 127bf215546Sopenharmony_ci break; 128bf215546Sopenharmony_ci } 129bf215546Sopenharmony_ci } else if (opc_cat(instr->opc) == 1) { 130bf215546Sopenharmony_ci if (instr->opc == OPC_MOV) { 131bf215546Sopenharmony_ci if (instr->cat1.src_type == instr->cat1.dst_type) 132bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "mov"); 133bf215546Sopenharmony_ci else 134bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "cov"); 135bf215546Sopenharmony_ci } else { 136bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "%s", 137bf215546Sopenharmony_ci disasm_a3xx_instr_name(instr->opc)); 138bf215546Sopenharmony_ci } 139bf215546Sopenharmony_ci 140bf215546Sopenharmony_ci if (instr->opc == OPC_SCAN_MACRO) { 141bf215546Sopenharmony_ci switch (instr->cat1.reduce_op) { 142bf215546Sopenharmony_ci case REDUCE_OP_ADD_U: 143bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ".add.u"); 144bf215546Sopenharmony_ci break; 145bf215546Sopenharmony_ci case REDUCE_OP_ADD_F: 146bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ".add.f"); 147bf215546Sopenharmony_ci break; 148bf215546Sopenharmony_ci case REDUCE_OP_MUL_U: 149bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ".mul.u"); 150bf215546Sopenharmony_ci break; 151bf215546Sopenharmony_ci case REDUCE_OP_MUL_F: 152bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ".mul.f"); 153bf215546Sopenharmony_ci break; 154bf215546Sopenharmony_ci case REDUCE_OP_MIN_U: 155bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ".min.u"); 156bf215546Sopenharmony_ci break; 157bf215546Sopenharmony_ci case REDUCE_OP_MIN_S: 158bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ".min.s"); 159bf215546Sopenharmony_ci break; 160bf215546Sopenharmony_ci case REDUCE_OP_MIN_F: 161bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ".min.f"); 162bf215546Sopenharmony_ci break; 163bf215546Sopenharmony_ci case REDUCE_OP_MAX_U: 164bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ".max.u"); 165bf215546Sopenharmony_ci break; 166bf215546Sopenharmony_ci case REDUCE_OP_MAX_S: 167bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ".max.s"); 168bf215546Sopenharmony_ci break; 169bf215546Sopenharmony_ci case REDUCE_OP_MAX_F: 170bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ".max.f"); 171bf215546Sopenharmony_ci break; 172bf215546Sopenharmony_ci case REDUCE_OP_AND_B: 173bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ".and.b"); 174bf215546Sopenharmony_ci break; 175bf215546Sopenharmony_ci case REDUCE_OP_OR_B: 176bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ".or.b"); 177bf215546Sopenharmony_ci break; 178bf215546Sopenharmony_ci case REDUCE_OP_XOR_B: 179bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ".xor.b"); 180bf215546Sopenharmony_ci break; 181bf215546Sopenharmony_ci } 182bf215546Sopenharmony_ci } 183bf215546Sopenharmony_ci 184bf215546Sopenharmony_ci if (instr->opc != OPC_MOVMSK && instr->opc != OPC_SCAN_MACRO) { 185bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ".%s%s", 186bf215546Sopenharmony_ci type_name(instr->cat1.src_type), 187bf215546Sopenharmony_ci type_name(instr->cat1.dst_type)); 188bf215546Sopenharmony_ci } 189bf215546Sopenharmony_ci } else if (instr->opc == OPC_B) { 190bf215546Sopenharmony_ci const char *name[8] = { 191bf215546Sopenharmony_ci /* clang-format off */ 192bf215546Sopenharmony_ci [BRANCH_PLAIN] = "br", 193bf215546Sopenharmony_ci [BRANCH_OR] = "brao", 194bf215546Sopenharmony_ci [BRANCH_AND] = "braa", 195bf215546Sopenharmony_ci [BRANCH_CONST] = "brac", 196bf215546Sopenharmony_ci [BRANCH_ANY] = "bany", 197bf215546Sopenharmony_ci [BRANCH_ALL] = "ball", 198bf215546Sopenharmony_ci [BRANCH_X] = "brax", 199bf215546Sopenharmony_ci /* clang-format on */ 200bf215546Sopenharmony_ci }; 201bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "%s", name[instr->cat0.brtype]); 202bf215546Sopenharmony_ci } else { 203bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "%s", disasm_a3xx_instr_name(instr->opc)); 204bf215546Sopenharmony_ci if (instr->flags & IR3_INSTR_3D) 205bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ".3d"); 206bf215546Sopenharmony_ci if (instr->flags & IR3_INSTR_A) 207bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ".a"); 208bf215546Sopenharmony_ci if (instr->flags & IR3_INSTR_O) 209bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ".o"); 210bf215546Sopenharmony_ci if (instr->flags & IR3_INSTR_P) 211bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ".p"); 212bf215546Sopenharmony_ci if (instr->flags & IR3_INSTR_S) 213bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ".s"); 214bf215546Sopenharmony_ci if (instr->flags & IR3_INSTR_A1EN) 215bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ".a1en"); 216bf215546Sopenharmony_ci if (instr->opc == OPC_LDC) 217bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ".offset%d", instr->cat6.d); 218bf215546Sopenharmony_ci if (instr->opc == OPC_LDC_K) 219bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ".%d", instr->cat6.iim_val); 220bf215546Sopenharmony_ci if (instr->flags & IR3_INSTR_B) { 221bf215546Sopenharmony_ci mesa_log_stream_printf( 222bf215546Sopenharmony_ci stream, ".base%d", 223bf215546Sopenharmony_ci is_tex(instr) ? instr->cat5.tex_base : instr->cat6.base); 224bf215546Sopenharmony_ci } 225bf215546Sopenharmony_ci if (instr->flags & IR3_INSTR_S2EN) 226bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ".s2en"); 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci static const char *cond[0x7] = { 229bf215546Sopenharmony_ci "lt", "le", "gt", "ge", "eq", "ne", 230bf215546Sopenharmony_ci }; 231bf215546Sopenharmony_ci 232bf215546Sopenharmony_ci switch (instr->opc) { 233bf215546Sopenharmony_ci case OPC_CMPS_F: 234bf215546Sopenharmony_ci case OPC_CMPS_U: 235bf215546Sopenharmony_ci case OPC_CMPS_S: 236bf215546Sopenharmony_ci case OPC_CMPV_F: 237bf215546Sopenharmony_ci case OPC_CMPV_U: 238bf215546Sopenharmony_ci case OPC_CMPV_S: 239bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ".%s", 240bf215546Sopenharmony_ci cond[instr->cat2.condition & 0x7]); 241bf215546Sopenharmony_ci break; 242bf215546Sopenharmony_ci default: 243bf215546Sopenharmony_ci break; 244bf215546Sopenharmony_ci } 245bf215546Sopenharmony_ci } 246bf215546Sopenharmony_ci} 247bf215546Sopenharmony_ci 248bf215546Sopenharmony_cistatic void 249bf215546Sopenharmony_ciprint_ssa_def_name(struct log_stream *stream, struct ir3_register *reg) 250bf215546Sopenharmony_ci{ 251bf215546Sopenharmony_ci mesa_log_stream_printf(stream, SYN_SSA("ssa_%u"), reg->instr->serialno); 252bf215546Sopenharmony_ci if (reg->name != 0) 253bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ":%u", reg->name); 254bf215546Sopenharmony_ci} 255bf215546Sopenharmony_ci 256bf215546Sopenharmony_cistatic void 257bf215546Sopenharmony_ciprint_ssa_name(struct log_stream *stream, struct ir3_register *reg, bool dst) 258bf215546Sopenharmony_ci{ 259bf215546Sopenharmony_ci if (!dst) { 260bf215546Sopenharmony_ci if (!reg->def) 261bf215546Sopenharmony_ci mesa_log_stream_printf(stream, SYN_SSA("undef")); 262bf215546Sopenharmony_ci else 263bf215546Sopenharmony_ci print_ssa_def_name(stream, reg->def); 264bf215546Sopenharmony_ci } else { 265bf215546Sopenharmony_ci print_ssa_def_name(stream, reg); 266bf215546Sopenharmony_ci } 267bf215546Sopenharmony_ci 268bf215546Sopenharmony_ci if (reg->num != INVALID_REG && !(reg->flags & IR3_REG_ARRAY)) 269bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "(" SYN_REG("r%u.%c") ")", reg_num(reg), 270bf215546Sopenharmony_ci "xyzw"[reg_comp(reg)]); 271bf215546Sopenharmony_ci} 272bf215546Sopenharmony_ci 273bf215546Sopenharmony_cistatic void 274bf215546Sopenharmony_ciprint_reg_name(struct log_stream *stream, struct ir3_instruction *instr, 275bf215546Sopenharmony_ci struct ir3_register *reg, bool dest) 276bf215546Sopenharmony_ci{ 277bf215546Sopenharmony_ci if ((reg->flags & (IR3_REG_FABS | IR3_REG_SABS)) && 278bf215546Sopenharmony_ci (reg->flags & (IR3_REG_FNEG | IR3_REG_SNEG | IR3_REG_BNOT))) 279bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "(absneg)"); 280bf215546Sopenharmony_ci else if (reg->flags & (IR3_REG_FNEG | IR3_REG_SNEG | IR3_REG_BNOT)) 281bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "(neg)"); 282bf215546Sopenharmony_ci else if (reg->flags & (IR3_REG_FABS | IR3_REG_SABS)) 283bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "(abs)"); 284bf215546Sopenharmony_ci 285bf215546Sopenharmony_ci if (reg->flags & IR3_REG_FIRST_KILL) 286bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "(kill)"); 287bf215546Sopenharmony_ci if (reg->flags & IR3_REG_UNUSED) 288bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "(unused)"); 289bf215546Sopenharmony_ci 290bf215546Sopenharmony_ci if (reg->flags & IR3_REG_R) 291bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "(r)"); 292bf215546Sopenharmony_ci 293bf215546Sopenharmony_ci if (reg->flags & IR3_REG_EARLY_CLOBBER) 294bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "(early_clobber)"); 295bf215546Sopenharmony_ci 296bf215546Sopenharmony_ci /* Right now all instructions that use tied registers only have one 297bf215546Sopenharmony_ci * destination register, so we can just print (tied) as if it's a flag, 298bf215546Sopenharmony_ci * although it's more convenient for RA if it's a pointer. 299bf215546Sopenharmony_ci */ 300bf215546Sopenharmony_ci if (reg->tied) 301bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "(tied)"); 302bf215546Sopenharmony_ci 303bf215546Sopenharmony_ci if (reg->flags & IR3_REG_SHARED) 304bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "s"); 305bf215546Sopenharmony_ci if (reg->flags & IR3_REG_HALF) 306bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "h"); 307bf215546Sopenharmony_ci 308bf215546Sopenharmony_ci if (reg->flags & IR3_REG_IMMED) { 309bf215546Sopenharmony_ci mesa_log_stream_printf(stream, SYN_IMMED("imm[%f,%d,0x%x]"), reg->fim_val, 310bf215546Sopenharmony_ci reg->iim_val, reg->iim_val); 311bf215546Sopenharmony_ci } else if (reg->flags & IR3_REG_ARRAY) { 312bf215546Sopenharmony_ci if (reg->flags & IR3_REG_SSA) { 313bf215546Sopenharmony_ci print_ssa_name(stream, reg, dest); 314bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ":"); 315bf215546Sopenharmony_ci } 316bf215546Sopenharmony_ci mesa_log_stream_printf(stream, 317bf215546Sopenharmony_ci SYN_ARRAY("arr[id=%u, offset=%d, size=%u]"), 318bf215546Sopenharmony_ci reg->array.id, reg->array.offset, reg->size); 319bf215546Sopenharmony_ci if (reg->array.base != INVALID_REG) 320bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "(" SYN_REG("r%u.%c") ")", 321bf215546Sopenharmony_ci reg->array.base >> 2, 322bf215546Sopenharmony_ci "xyzw"[reg->array.base & 0x3]); 323bf215546Sopenharmony_ci } else if (reg->flags & IR3_REG_SSA) { 324bf215546Sopenharmony_ci print_ssa_name(stream, reg, dest); 325bf215546Sopenharmony_ci } else if (reg->flags & IR3_REG_RELATIV) { 326bf215546Sopenharmony_ci if (reg->flags & IR3_REG_CONST) 327bf215546Sopenharmony_ci mesa_log_stream_printf(stream, SYN_CONST("c<a0.x + %d>"), 328bf215546Sopenharmony_ci reg->array.offset); 329bf215546Sopenharmony_ci else 330bf215546Sopenharmony_ci mesa_log_stream_printf(stream, SYN_REG("r<a0.x + %d>") " (%u)", 331bf215546Sopenharmony_ci reg->array.offset, reg->size); 332bf215546Sopenharmony_ci } else { 333bf215546Sopenharmony_ci if (reg->flags & IR3_REG_CONST) 334bf215546Sopenharmony_ci mesa_log_stream_printf(stream, SYN_CONST("c%u.%c"), reg_num(reg), 335bf215546Sopenharmony_ci "xyzw"[reg_comp(reg)]); 336bf215546Sopenharmony_ci else 337bf215546Sopenharmony_ci mesa_log_stream_printf(stream, SYN_REG("r%u.%c"), reg_num(reg), 338bf215546Sopenharmony_ci "xyzw"[reg_comp(reg)]); 339bf215546Sopenharmony_ci } 340bf215546Sopenharmony_ci 341bf215546Sopenharmony_ci if (reg->wrmask > 0x1) 342bf215546Sopenharmony_ci mesa_log_stream_printf(stream, " (wrmask=0x%x)", reg->wrmask); 343bf215546Sopenharmony_ci} 344bf215546Sopenharmony_ci 345bf215546Sopenharmony_cistatic void 346bf215546Sopenharmony_citab(struct log_stream *stream, int lvl) 347bf215546Sopenharmony_ci{ 348bf215546Sopenharmony_ci for (int i = 0; i < lvl; i++) 349bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "\t"); 350bf215546Sopenharmony_ci} 351bf215546Sopenharmony_ci 352bf215546Sopenharmony_cistatic void 353bf215546Sopenharmony_ciprint_instr(struct log_stream *stream, struct ir3_instruction *instr, int lvl) 354bf215546Sopenharmony_ci{ 355bf215546Sopenharmony_ci tab(stream, lvl); 356bf215546Sopenharmony_ci 357bf215546Sopenharmony_ci print_instr_name(stream, instr, true); 358bf215546Sopenharmony_ci 359bf215546Sopenharmony_ci if (is_tex(instr)) { 360bf215546Sopenharmony_ci mesa_log_stream_printf(stream, " (%s)(", type_name(instr->cat5.type)); 361bf215546Sopenharmony_ci for (unsigned i = 0; i < 4; i++) 362bf215546Sopenharmony_ci if (instr->dsts[0]->wrmask & (1 << i)) 363bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "%c", "xyzw"[i]); 364bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ")"); 365bf215546Sopenharmony_ci } else if ((instr->srcs_count > 0 || instr->dsts_count > 0) && 366bf215546Sopenharmony_ci (instr->opc != OPC_B)) { 367bf215546Sopenharmony_ci /* NOTE the b(ranch) instruction has a suffix, which is 368bf215546Sopenharmony_ci * handled below 369bf215546Sopenharmony_ci */ 370bf215546Sopenharmony_ci mesa_log_stream_printf(stream, " "); 371bf215546Sopenharmony_ci } 372bf215546Sopenharmony_ci 373bf215546Sopenharmony_ci if (!is_flow(instr) || instr->opc == OPC_END || instr->opc == OPC_CHMASK) { 374bf215546Sopenharmony_ci bool first = true; 375bf215546Sopenharmony_ci foreach_dst (reg, instr) { 376bf215546Sopenharmony_ci if (reg->wrmask == 0) 377bf215546Sopenharmony_ci continue; 378bf215546Sopenharmony_ci if (!first) 379bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ", "); 380bf215546Sopenharmony_ci print_reg_name(stream, instr, reg, true); 381bf215546Sopenharmony_ci first = false; 382bf215546Sopenharmony_ci } 383bf215546Sopenharmony_ci foreach_src_n (reg, n, instr) { 384bf215546Sopenharmony_ci if (!first) 385bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ", "); 386bf215546Sopenharmony_ci print_reg_name(stream, instr, reg, false); 387bf215546Sopenharmony_ci if (instr->opc == OPC_END || instr->opc == OPC_CHMASK) 388bf215546Sopenharmony_ci mesa_log_stream_printf(stream, " (%u)", instr->end.outidxs[n]); 389bf215546Sopenharmony_ci first = false; 390bf215546Sopenharmony_ci } 391bf215546Sopenharmony_ci } 392bf215546Sopenharmony_ci 393bf215546Sopenharmony_ci if (is_tex(instr) && !(instr->flags & IR3_INSTR_S2EN)) { 394bf215546Sopenharmony_ci if (!!(instr->flags & IR3_INSTR_B) && !!(instr->flags & IR3_INSTR_A1EN)) { 395bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ", s#%d", instr->cat5.samp); 396bf215546Sopenharmony_ci } else { 397bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ", s#%d, t#%d", instr->cat5.samp, 398bf215546Sopenharmony_ci instr->cat5.tex); 399bf215546Sopenharmony_ci } 400bf215546Sopenharmony_ci } 401bf215546Sopenharmony_ci 402bf215546Sopenharmony_ci if (instr->opc == OPC_META_SPLIT) { 403bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ", off=%d", instr->split.off); 404bf215546Sopenharmony_ci } else if (instr->opc == OPC_META_TEX_PREFETCH) { 405bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ", tex=%d, samp=%d, input_offset=%d", 406bf215546Sopenharmony_ci instr->prefetch.tex, instr->prefetch.samp, 407bf215546Sopenharmony_ci instr->prefetch.input_offset); 408bf215546Sopenharmony_ci } 409bf215546Sopenharmony_ci 410bf215546Sopenharmony_ci if (is_flow(instr) && instr->cat0.target) { 411bf215546Sopenharmony_ci /* the predicate register src is implied: */ 412bf215546Sopenharmony_ci if (instr->opc == OPC_B) { 413bf215546Sopenharmony_ci static const struct { 414bf215546Sopenharmony_ci int nsrc; 415bf215546Sopenharmony_ci bool idx; 416bf215546Sopenharmony_ci } brinfo[7] = { 417bf215546Sopenharmony_ci /* clang-format off */ 418bf215546Sopenharmony_ci [BRANCH_PLAIN] = {1, false}, 419bf215546Sopenharmony_ci [BRANCH_OR] = {2, false}, 420bf215546Sopenharmony_ci [BRANCH_AND] = {2, false}, 421bf215546Sopenharmony_ci [BRANCH_CONST] = {0, true}, 422bf215546Sopenharmony_ci [BRANCH_ANY] = {1, false}, 423bf215546Sopenharmony_ci [BRANCH_ALL] = {1, false}, 424bf215546Sopenharmony_ci [BRANCH_X] = {0, false}, 425bf215546Sopenharmony_ci /* clang-format on */ 426bf215546Sopenharmony_ci }; 427bf215546Sopenharmony_ci 428bf215546Sopenharmony_ci if (brinfo[instr->cat0.brtype].idx) { 429bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ".%u", instr->cat0.idx); 430bf215546Sopenharmony_ci } 431bf215546Sopenharmony_ci if (brinfo[instr->cat0.brtype].nsrc >= 1) { 432bf215546Sopenharmony_ci mesa_log_stream_printf(stream, " %sp0.%c (", 433bf215546Sopenharmony_ci instr->cat0.inv1 ? "!" : "", 434bf215546Sopenharmony_ci "xyzw"[instr->cat0.comp1 & 0x3]); 435bf215546Sopenharmony_ci print_reg_name(stream, instr, instr->srcs[0], false); 436bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "), "); 437bf215546Sopenharmony_ci } 438bf215546Sopenharmony_ci if (brinfo[instr->cat0.brtype].nsrc >= 2) { 439bf215546Sopenharmony_ci mesa_log_stream_printf(stream, " %sp0.%c (", 440bf215546Sopenharmony_ci instr->cat0.inv2 ? "!" : "", 441bf215546Sopenharmony_ci "xyzw"[instr->cat0.comp2 & 0x3]); 442bf215546Sopenharmony_ci print_reg_name(stream, instr, instr->srcs[1], false); 443bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "), "); 444bf215546Sopenharmony_ci } 445bf215546Sopenharmony_ci } 446bf215546Sopenharmony_ci mesa_log_stream_printf(stream, " target=block%u", 447bf215546Sopenharmony_ci block_id(instr->cat0.target)); 448bf215546Sopenharmony_ci } 449bf215546Sopenharmony_ci 450bf215546Sopenharmony_ci if (instr->deps_count) { 451bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ", false-deps:"); 452bf215546Sopenharmony_ci unsigned n = 0; 453bf215546Sopenharmony_ci for (unsigned i = 0; i < instr->deps_count; i++) { 454bf215546Sopenharmony_ci if (!instr->deps[i]) 455bf215546Sopenharmony_ci continue; 456bf215546Sopenharmony_ci if (n++ > 0) 457bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ", "); 458bf215546Sopenharmony_ci mesa_log_stream_printf(stream, SYN_SSA("ssa_%u"), 459bf215546Sopenharmony_ci instr->deps[i]->serialno); 460bf215546Sopenharmony_ci } 461bf215546Sopenharmony_ci } 462bf215546Sopenharmony_ci 463bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "\n"); 464bf215546Sopenharmony_ci} 465bf215546Sopenharmony_ci 466bf215546Sopenharmony_civoid 467bf215546Sopenharmony_ciir3_print_instr_stream(struct log_stream *stream, struct ir3_instruction *instr) 468bf215546Sopenharmony_ci{ 469bf215546Sopenharmony_ci print_instr(stream, instr, 0); 470bf215546Sopenharmony_ci} 471bf215546Sopenharmony_ci 472bf215546Sopenharmony_civoid 473bf215546Sopenharmony_ciir3_print_instr(struct ir3_instruction *instr) 474bf215546Sopenharmony_ci{ 475bf215546Sopenharmony_ci struct log_stream *stream = mesa_log_streami(); 476bf215546Sopenharmony_ci print_instr(stream, instr, 0); 477bf215546Sopenharmony_ci mesa_log_stream_destroy(stream); 478bf215546Sopenharmony_ci} 479bf215546Sopenharmony_ci 480bf215546Sopenharmony_cistatic void 481bf215546Sopenharmony_ciprint_block(struct ir3_block *block, int lvl) 482bf215546Sopenharmony_ci{ 483bf215546Sopenharmony_ci struct log_stream *stream = mesa_log_streami(); 484bf215546Sopenharmony_ci 485bf215546Sopenharmony_ci tab(stream, lvl); 486bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "block%u {\n", block_id(block)); 487bf215546Sopenharmony_ci 488bf215546Sopenharmony_ci if (block->predecessors_count > 0) { 489bf215546Sopenharmony_ci tab(stream, lvl + 1); 490bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "pred: "); 491bf215546Sopenharmony_ci for (unsigned i = 0; i < block->predecessors_count; i++) { 492bf215546Sopenharmony_ci struct ir3_block *pred = block->predecessors[i]; 493bf215546Sopenharmony_ci if (i != 0) 494bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ", "); 495bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "block%u", block_id(pred)); 496bf215546Sopenharmony_ci } 497bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "\n"); 498bf215546Sopenharmony_ci } 499bf215546Sopenharmony_ci 500bf215546Sopenharmony_ci if (block->physical_predecessors_count > 0) { 501bf215546Sopenharmony_ci tab(stream, lvl + 1); 502bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "physical pred: "); 503bf215546Sopenharmony_ci for (unsigned i = 0; i < block->physical_predecessors_count; i++) { 504bf215546Sopenharmony_ci struct ir3_block *pred = block->physical_predecessors[i]; 505bf215546Sopenharmony_ci if (i != 0) 506bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ", "); 507bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "block%u", block_id(pred)); 508bf215546Sopenharmony_ci } 509bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "\n"); 510bf215546Sopenharmony_ci } 511bf215546Sopenharmony_ci 512bf215546Sopenharmony_ci foreach_instr (instr, &block->instr_list) { 513bf215546Sopenharmony_ci print_instr(stream, instr, lvl + 1); 514bf215546Sopenharmony_ci } 515bf215546Sopenharmony_ci 516bf215546Sopenharmony_ci tab(stream, lvl + 1); 517bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "/* keeps:\n"); 518bf215546Sopenharmony_ci for (unsigned i = 0; i < block->keeps_count; i++) { 519bf215546Sopenharmony_ci print_instr(stream, block->keeps[i], lvl + 2); 520bf215546Sopenharmony_ci } 521bf215546Sopenharmony_ci tab(stream, lvl + 1); 522bf215546Sopenharmony_ci mesa_log_stream_printf(stream, " */\n"); 523bf215546Sopenharmony_ci 524bf215546Sopenharmony_ci if (block->successors[1]) { 525bf215546Sopenharmony_ci /* leading into if/else: */ 526bf215546Sopenharmony_ci tab(stream, lvl + 1); 527bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "/* succs: if "); 528bf215546Sopenharmony_ci switch (block->brtype) { 529bf215546Sopenharmony_ci case IR3_BRANCH_COND: 530bf215546Sopenharmony_ci break; 531bf215546Sopenharmony_ci case IR3_BRANCH_ANY: 532bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "any "); 533bf215546Sopenharmony_ci break; 534bf215546Sopenharmony_ci case IR3_BRANCH_ALL: 535bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "all "); 536bf215546Sopenharmony_ci break; 537bf215546Sopenharmony_ci case IR3_BRANCH_GETONE: 538bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "getone "); 539bf215546Sopenharmony_ci break; 540bf215546Sopenharmony_ci case IR3_BRANCH_SHPS: 541bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "shps "); 542bf215546Sopenharmony_ci break; 543bf215546Sopenharmony_ci } 544bf215546Sopenharmony_ci if (block->condition) 545bf215546Sopenharmony_ci mesa_log_stream_printf(stream, SYN_SSA("ssa_%u") " ", 546bf215546Sopenharmony_ci block->condition->serialno); 547bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "block%u; else block%u; */\n", 548bf215546Sopenharmony_ci block_id(block->successors[0]), 549bf215546Sopenharmony_ci block_id(block->successors[1])); 550bf215546Sopenharmony_ci } else if (block->successors[0]) { 551bf215546Sopenharmony_ci tab(stream, lvl + 1); 552bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "/* succs: block%u; */\n", 553bf215546Sopenharmony_ci block_id(block->successors[0])); 554bf215546Sopenharmony_ci } 555bf215546Sopenharmony_ci if (block->physical_successors[0]) { 556bf215546Sopenharmony_ci tab(stream, lvl + 1); 557bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "/* physical succs: block%u", 558bf215546Sopenharmony_ci block_id(block->physical_successors[0])); 559bf215546Sopenharmony_ci if (block->physical_successors[1]) { 560bf215546Sopenharmony_ci mesa_log_stream_printf(stream, ", block%u", 561bf215546Sopenharmony_ci block_id(block->physical_successors[1])); 562bf215546Sopenharmony_ci } 563bf215546Sopenharmony_ci mesa_log_stream_printf(stream, " */\n"); 564bf215546Sopenharmony_ci } 565bf215546Sopenharmony_ci tab(stream, lvl); 566bf215546Sopenharmony_ci mesa_log_stream_printf(stream, "}\n"); 567bf215546Sopenharmony_ci} 568bf215546Sopenharmony_ci 569bf215546Sopenharmony_civoid 570bf215546Sopenharmony_ciir3_print(struct ir3 *ir) 571bf215546Sopenharmony_ci{ 572bf215546Sopenharmony_ci foreach_block (block, &ir->block_list) 573bf215546Sopenharmony_ci print_block(block, 0); 574bf215546Sopenharmony_ci} 575