1/* 2 * Copyright (C) 2014 Rob Clark <robclark@freedesktop.org> 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 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * 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 NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 * SOFTWARE. 22 * 23 * Authors: 24 * Rob Clark <robclark@freedesktop.org> 25 */ 26 27#include <stdarg.h> 28#include <stdio.h> 29 30#include "ir3.h" 31 32#define PTRID(x) ((unsigned long)(x)) 33 34static void print_instr_name(struct ir3_instruction *instr) 35{ 36 if (!instr) 37 return; 38#ifdef DEBUG 39 printf("%04u:", instr->serialno); 40#endif 41 printf("%04u:", instr->name); 42 printf("%04u:", instr->ip); 43 printf("%03u:", instr->depth); 44 printf("%03u: ", instr->sun); 45 46 if (instr->flags & IR3_INSTR_SY) 47 printf("(sy)"); 48 if (instr->flags & IR3_INSTR_SS) 49 printf("(ss)"); 50 51 if (is_meta(instr)) { 52 switch (instr->opc) { 53 case OPC_META_INPUT: printf("_meta:in"); break; 54 case OPC_META_FO: printf("_meta:fo"); break; 55 case OPC_META_FI: printf("_meta:fi"); break; 56 57 /* shouldn't hit here.. just for debugging: */ 58 default: printf("_meta:%d", instr->opc); break; 59 } 60 } else if (instr->opc == OPC_MOV) { 61 static const char *type[] = { 62 [TYPE_F16] = "f16", 63 [TYPE_F32] = "f32", 64 [TYPE_U16] = "u16", 65 [TYPE_U32] = "u32", 66 [TYPE_S16] = "s16", 67 [TYPE_S32] = "s32", 68 [TYPE_U8] = "u8", 69 [TYPE_S8] = "s8", 70 }; 71 if (instr->cat1.src_type == instr->cat1.dst_type) 72 printf("mov"); 73 else 74 printf("cov"); 75 printf(".%s%s", type[instr->cat1.src_type], type[instr->cat1.dst_type]); 76 } else { 77 printf("%s", ir3_instr_name(instr)); 78 if (instr->flags & IR3_INSTR_3D) 79 printf(".3d"); 80 if (instr->flags & IR3_INSTR_A) 81 printf(".a"); 82 if (instr->flags & IR3_INSTR_O) 83 printf(".o"); 84 if (instr->flags & IR3_INSTR_P) 85 printf(".p"); 86 if (instr->flags & IR3_INSTR_S) 87 printf(".s"); 88 if (instr->flags & IR3_INSTR_S2EN) 89 printf(".s2en"); 90 } 91} 92 93static void print_reg_name(struct ir3_register *reg) 94{ 95 if ((reg->flags & (IR3_REG_FABS | IR3_REG_SABS)) && 96 (reg->flags & (IR3_REG_FNEG | IR3_REG_SNEG | IR3_REG_BNOT))) 97 printf("(absneg)"); 98 else if (reg->flags & (IR3_REG_FNEG | IR3_REG_SNEG | IR3_REG_BNOT)) 99 printf("(neg)"); 100 else if (reg->flags & (IR3_REG_FABS | IR3_REG_SABS)) 101 printf("(abs)"); 102 103 if (reg->flags & IR3_REG_IMMED) { 104 printf("imm[%f,%d,0x%x]", reg->fim_val, reg->iim_val, reg->iim_val); 105 } else if (reg->flags & IR3_REG_ARRAY) { 106 printf("arr[id=%u, offset=%d, size=%u", reg->array.id, 107 reg->array.offset, reg->size); 108 /* for ARRAY we could have null src, for example first write 109 * instruction.. 110 */ 111 if (reg->instr) { 112 printf(", _["); 113 print_instr_name(reg->instr); 114 printf("]"); 115 } 116 printf("]"); 117 } else if (reg->flags & IR3_REG_SSA) { 118 printf("_["); 119 print_instr_name(reg->instr); 120 printf("]"); 121 } else if (reg->flags & IR3_REG_RELATIV) { 122 if (reg->flags & IR3_REG_HALF) 123 printf("h"); 124 if (reg->flags & IR3_REG_CONST) 125 printf("c<a0.x + %d>", reg->array.offset); 126 else 127 printf("\x1b[0;31mr<a0.x + %d>\x1b[0m (%u)", reg->array.offset, reg->size); 128 } else { 129 if (reg->flags & IR3_REG_HIGH) 130 printf("H"); 131 if (reg->flags & IR3_REG_HALF) 132 printf("h"); 133 if (reg->flags & IR3_REG_CONST) 134 printf("c%u.%c", reg_num(reg), "xyzw"[reg_comp(reg)]); 135 else 136 printf("\x1b[0;31mr%u.%c\x1b[0m", reg_num(reg), "xyzw"[reg_comp(reg)]); 137 } 138} 139 140static void 141tab(int lvl) 142{ 143 for (int i = 0; i < lvl; i++) 144 printf("\t"); 145} 146 147static void 148print_instr(struct ir3_instruction *instr, int lvl) 149{ 150 unsigned i; 151 152 tab(lvl); 153 154 print_instr_name(instr); 155 for (i = 0; i < instr->regs_count; i++) { 156 struct ir3_register *reg = instr->regs[i]; 157 printf(i ? ", " : " "); 158 print_reg_name(reg); 159 } 160 161 if (instr->address) { 162 printf(", address=_"); 163 printf("["); 164 print_instr_name(instr->address); 165 printf("]"); 166 } 167 168 if (instr->cp.left) { 169 printf(", left=_"); 170 printf("["); 171 print_instr_name(instr->cp.left); 172 printf("]"); 173 } 174 175 if (instr->cp.right) { 176 printf(", right=_"); 177 printf("["); 178 print_instr_name(instr->cp.right); 179 printf("]"); 180 } 181 182 if (instr->opc == OPC_META_FO) { 183 printf(", off=%d", instr->fo.off); 184 } 185 186 if (is_flow(instr) && instr->cat0.target) { 187 /* the predicate register src is implied: */ 188 if (instr->opc == OPC_BR) { 189 printf(" %sp0.x", instr->cat0.inv ? "!" : ""); 190 } 191 printf(", target=block%u", block_id(instr->cat0.target)); 192 } 193 194 if (instr->deps_count) { 195 printf(", false-deps:"); 196 for (unsigned i = 0; i < instr->deps_count; i++) { 197 if (i > 0) 198 printf(", "); 199 printf("_["); 200 print_instr_name(instr->deps[i]); 201 printf("]"); 202 } 203 } 204 205 printf("\n"); 206} 207 208void ir3_print_instr(struct ir3_instruction *instr) 209{ 210 print_instr(instr, 0); 211} 212 213static void 214print_block(struct ir3_block *block, int lvl) 215{ 216 tab(lvl); printf("block%u {\n", block_id(block)); 217 218 if (block->predecessors_count > 0) { 219 tab(lvl+1); 220 printf("pred: "); 221 for (unsigned i = 0; i < block->predecessors_count; i++) { 222 if (i) 223 printf(", "); 224 printf("block%u", block_id(block->predecessors[i])); 225 } 226 printf("\n"); 227 } 228 229 list_for_each_entry (struct ir3_instruction, instr, &block->instr_list, node) { 230 print_instr(instr, lvl+1); 231 } 232 233 tab(lvl+1); printf("/* keeps:\n"); 234 for (unsigned i = 0; i < block->keeps_count; i++) { 235 print_instr(block->keeps[i], lvl+2); 236 } 237 tab(lvl+1); printf(" */\n"); 238 239 if (block->successors[1]) { 240 /* leading into if/else: */ 241 tab(lvl+1); 242 printf("/* succs: if _["); 243 print_instr_name(block->condition); 244 printf("] block%u; else block%u; */\n", 245 block_id(block->successors[0]), 246 block_id(block->successors[1])); 247 } else if (block->successors[0]) { 248 tab(lvl+1); 249 printf("/* succs: block%u; */\n", 250 block_id(block->successors[0])); 251 } 252 tab(lvl); printf("}\n"); 253} 254 255void 256ir3_print(struct ir3 *ir) 257{ 258 list_for_each_entry (struct ir3_block, block, &ir->block_list, node) 259 print_block(block, 0); 260 261 for (unsigned i = 0; i < ir->noutputs; i++) { 262 if (!ir->outputs[i]) 263 continue; 264 printf("out%d: ", i); 265 print_instr(ir->outputs[i], 0); 266 } 267} 268