1 /* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */ 2 3 /* 4 * Copyright (C) 2014 Rob Clark <robclark (at) freedesktop.org> 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the next 14 * paragraph) shall be included in all copies or substantial portions of the 15 * Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 * SOFTWARE. 24 * 25 * Authors: 26 * Rob Clark <robclark (at) freedesktop.org> 27 */ 28 29 #include <stdarg.h> 30 #include <stdio.h> 31 32 #include "ir3.h" 33 34 #define PTRID(x) ((unsigned long)(x)) 35 36 static void print_instr_name(struct ir3_instruction *instr) 37 { 38 if (!instr) 39 return; 40 #ifdef DEBUG 41 printf("%04u:", instr->serialno); 42 #endif 43 printf("%04u:", instr->name); 44 printf("%03u: ", instr->depth); 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_PHI: 54 printf("Φ"); 55 break; 56 default: 57 /* shouldn't hit here.. just for debugging: */ 58 switch (instr->opc) { 59 case OPC_META_INPUT: printf("_meta:in"); break; 60 case OPC_META_FO: printf("_meta:fo"); break; 61 case OPC_META_FI: printf("_meta:fi"); break; 62 63 default: printf("_meta:%d", instr->opc); break; 64 } 65 break; 66 } 67 } else if (instr->opc == OPC_MOV) { 68 static const char *type[] = { 69 [TYPE_F16] = "f16", 70 [TYPE_F32] = "f32", 71 [TYPE_U16] = "u16", 72 [TYPE_U32] = "u32", 73 [TYPE_S16] = "s16", 74 [TYPE_S32] = "s32", 75 [TYPE_U8] = "u8", 76 [TYPE_S8] = "s8", 77 }; 78 if (instr->cat1.src_type == instr->cat1.dst_type) 79 printf("mov"); 80 else 81 printf("cov"); 82 printf(".%s%s", type[instr->cat1.src_type], type[instr->cat1.dst_type]); 83 } else { 84 printf("%s", ir3_instr_name(instr)); 85 if (instr->flags & IR3_INSTR_3D) 86 printf(".3d"); 87 if (instr->flags & IR3_INSTR_A) 88 printf(".a"); 89 if (instr->flags & IR3_INSTR_O) 90 printf(".o"); 91 if (instr->flags & IR3_INSTR_P) 92 printf(".p"); 93 if (instr->flags & IR3_INSTR_S) 94 printf(".s"); 95 if (instr->flags & IR3_INSTR_S2EN) 96 printf(".s2en"); 97 } 98 } 99 100 static void print_reg_name(struct ir3_register *reg) 101 { 102 if ((reg->flags & (IR3_REG_FABS | IR3_REG_SABS)) && 103 (reg->flags & (IR3_REG_FNEG | IR3_REG_SNEG | IR3_REG_BNOT))) 104 printf("(absneg)"); 105 else if (reg->flags & (IR3_REG_FNEG | IR3_REG_SNEG | IR3_REG_BNOT)) 106 printf("(neg)"); 107 else if (reg->flags & (IR3_REG_FABS | IR3_REG_SABS)) 108 printf("(abs)"); 109 110 if (reg->flags & IR3_REG_IMMED) { 111 printf("imm[%f,%d,0x%x]", reg->fim_val, reg->iim_val, reg->iim_val); 112 } else if (reg->flags & IR3_REG_ARRAY) { 113 printf("arr[id=%u, offset=%d, size=%u", reg->array.id, 114 reg->array.offset, reg->size); 115 /* for ARRAY we could have null src, for example first write 116 * instruction.. 117 */ 118 if (reg->instr) { 119 printf(", _["); 120 print_instr_name(reg->instr); 121 printf("]"); 122 } 123 printf("]"); 124 } else if (reg->flags & IR3_REG_SSA) { 125 printf("_["); 126 print_instr_name(reg->instr); 127 printf("]"); 128 } else if (reg->flags & IR3_REG_RELATIV) { 129 if (reg->flags & IR3_REG_HALF) 130 printf("h"); 131 if (reg->flags & IR3_REG_CONST) 132 printf("c<a0.x + %d>", reg->array.offset); 133 else 134 printf("\x1b[0;31mr<a0.x + %d>\x1b[0m (%u)", reg->array.offset, reg->size); 135 } else { 136 if (reg->flags & IR3_REG_HALF) 137 printf("h"); 138 if (reg->flags & IR3_REG_CONST) 139 printf("c%u.%c", reg_num(reg), "xyzw"[reg_comp(reg)]); 140 else 141 printf("\x1b[0;31mr%u.%c\x1b[0m", reg_num(reg), "xyzw"[reg_comp(reg)]); 142 } 143 } 144 145 static void 146 tab(int lvl) 147 { 148 for (int i = 0; i < lvl; i++) 149 printf("\t"); 150 } 151 152 static void 153 print_instr(struct ir3_instruction *instr, int lvl) 154 { 155 unsigned i; 156 157 tab(lvl); 158 159 print_instr_name(instr); 160 for (i = 0; i < instr->regs_count; i++) { 161 struct ir3_register *reg = instr->regs[i]; 162 printf(i ? ", " : " "); 163 print_reg_name(reg); 164 } 165 166 if (instr->address) { 167 printf(", address=_"); 168 printf("["); 169 print_instr_name(instr->address); 170 printf("]"); 171 } 172 173 if (instr->cp.left) { 174 printf(", left=_"); 175 printf("["); 176 print_instr_name(instr->cp.left); 177 printf("]"); 178 } 179 180 if (instr->cp.right) { 181 printf(", right=_"); 182 printf("["); 183 print_instr_name(instr->cp.right); 184 printf("]"); 185 } 186 187 if (instr->opc == OPC_META_FO) { 188 printf(", off=%d", instr->fo.off); 189 } 190 191 if (is_flow(instr) && instr->cat0.target) { 192 /* the predicate register src is implied: */ 193 if (instr->opc == OPC_BR) { 194 printf(" %sp0.x", instr->cat0.inv ? "!" : ""); 195 } 196 printf(", target=block%u", block_id(instr->cat0.target)); 197 } 198 199 printf("\n"); 200 } 201 202 void ir3_print_instr(struct ir3_instruction *instr) 203 { 204 print_instr(instr, 0); 205 } 206 207 static void 208 print_block(struct ir3_block *block, int lvl) 209 { 210 tab(lvl); printf("block%u {\n", block_id(block)); 211 list_for_each_entry (struct ir3_instruction, instr, &block->instr_list, node) { 212 print_instr(instr, lvl+1); 213 } 214 if (block->successors[1]) { 215 /* leading into if/else: */ 216 tab(lvl+1); 217 printf("/* succs: if _["); 218 print_instr_name(block->condition); 219 printf("] block%u; else block%u; */\n", 220 block_id(block->successors[0]), 221 block_id(block->successors[1])); 222 } else if (block->successors[0]) { 223 tab(lvl+1); 224 printf("/* succs: block%u; */\n", 225 block_id(block->successors[0])); 226 } 227 tab(lvl); printf("}\n"); 228 } 229 230 void 231 ir3_print(struct ir3 *ir) 232 { 233 list_for_each_entry (struct ir3_block, block, &ir->block_list, node) 234 print_block(block, 0); 235 236 for (unsigned i = 0; i < ir->noutputs; i++) { 237 if (!ir->outputs[i]) 238 continue; 239 printf("out%d: ", i); 240 print_instr(ir->outputs[i], 0); 241 } 242 } 243