17ec681f3Smrg/* 27ec681f3Smrg * Copyright (C) 2021 Alyssa Rosenzweig <alyssa@rosenzweig.io> 37ec681f3Smrg * Copyright (C) 2019-2020 Collabora, Ltd. 47ec681f3Smrg * 57ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 67ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 77ec681f3Smrg * to deal in the Software without restriction, including without limitation 87ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 97ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the 107ec681f3Smrg * Software is furnished to do so, subject to the following conditions: 117ec681f3Smrg * 127ec681f3Smrg * The above copyright notice and this permission notice (including the next 137ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the 147ec681f3Smrg * Software. 157ec681f3Smrg * 167ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 177ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 187ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 197ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 207ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 217ec681f3Smrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 227ec681f3Smrg * SOFTWARE. 237ec681f3Smrg */ 247ec681f3Smrg 257ec681f3Smrg#include "agx_compiler.h" 267ec681f3Smrg 277ec681f3Smrgstatic void 287ec681f3Smrgagx_print_sized(char prefix, unsigned value, enum agx_size size, FILE *fp) 297ec681f3Smrg{ 307ec681f3Smrg switch (size) { 317ec681f3Smrg case AGX_SIZE_16: 327ec681f3Smrg fprintf(fp, "%c%u%c", prefix, value >> 1, (value & 1) ? 'h' : 'l'); 337ec681f3Smrg return; 347ec681f3Smrg case AGX_SIZE_32: 357ec681f3Smrg assert((value & 1) == 0); 367ec681f3Smrg fprintf(fp, "%c%u", prefix, value >> 1); 377ec681f3Smrg return; 387ec681f3Smrg case AGX_SIZE_64: 397ec681f3Smrg assert((value & 1) == 0); 407ec681f3Smrg fprintf(fp, "%c%u:%c%u", prefix, value >> 1, 417ec681f3Smrg prefix, (value >> 1) + 1); 427ec681f3Smrg return; 437ec681f3Smrg } 447ec681f3Smrg 457ec681f3Smrg unreachable("Invalid size"); 467ec681f3Smrg} 477ec681f3Smrg 487ec681f3Smrgstatic void 497ec681f3Smrgagx_print_index(agx_index index, FILE *fp) 507ec681f3Smrg{ 517ec681f3Smrg switch (index.type) { 527ec681f3Smrg case AGX_INDEX_NULL: 537ec681f3Smrg fprintf(fp, "_"); 547ec681f3Smrg return; 557ec681f3Smrg 567ec681f3Smrg case AGX_INDEX_NORMAL: 577ec681f3Smrg if (index.cache) 587ec681f3Smrg fprintf(fp, "$"); 597ec681f3Smrg 607ec681f3Smrg if (index.discard) 617ec681f3Smrg fprintf(fp, "`"); 627ec681f3Smrg 637ec681f3Smrg if (index.kill) 647ec681f3Smrg fprintf(fp, "*"); 657ec681f3Smrg 667ec681f3Smrg fprintf(fp, "%u", index.value); 677ec681f3Smrg break; 687ec681f3Smrg 697ec681f3Smrg case AGX_INDEX_IMMEDIATE: 707ec681f3Smrg fprintf(fp, "#%u", index.value); 717ec681f3Smrg break; 727ec681f3Smrg 737ec681f3Smrg case AGX_INDEX_UNIFORM: 747ec681f3Smrg agx_print_sized('u', index.value, index.size, fp); 757ec681f3Smrg break; 767ec681f3Smrg 777ec681f3Smrg case AGX_INDEX_REGISTER: 787ec681f3Smrg agx_print_sized('r', index.value, index.size, fp); 797ec681f3Smrg break; 807ec681f3Smrg 817ec681f3Smrg default: 827ec681f3Smrg unreachable("Invalid index type"); 837ec681f3Smrg } 847ec681f3Smrg 857ec681f3Smrg /* Print length suffixes if not implied */ 867ec681f3Smrg if (index.type == AGX_INDEX_NORMAL || index.type == AGX_INDEX_IMMEDIATE) { 877ec681f3Smrg if (index.size == AGX_SIZE_16) 887ec681f3Smrg fprintf(fp, "h"); 897ec681f3Smrg else if (index.size == AGX_SIZE_64) 907ec681f3Smrg fprintf(fp, "d"); 917ec681f3Smrg } 927ec681f3Smrg 937ec681f3Smrg if (index.abs) 947ec681f3Smrg fprintf(fp, ".abs"); 957ec681f3Smrg 967ec681f3Smrg if (index.neg) 977ec681f3Smrg fprintf(fp, ".neg"); 987ec681f3Smrg} 997ec681f3Smrg 1007ec681f3Smrgvoid 1017ec681f3Smrgagx_print_instr(agx_instr *I, FILE *fp) 1027ec681f3Smrg{ 1037ec681f3Smrg assert(I->op < AGX_NUM_OPCODES); 1047ec681f3Smrg struct agx_opcode_info info = agx_opcodes_info[I->op]; 1057ec681f3Smrg 1067ec681f3Smrg fprintf(fp, " %s", info.name); 1077ec681f3Smrg 1087ec681f3Smrg if (I->saturate) 1097ec681f3Smrg fprintf(fp, ".sat"); 1107ec681f3Smrg 1117ec681f3Smrg if (I->last) 1127ec681f3Smrg fprintf(fp, ".last"); 1137ec681f3Smrg 1147ec681f3Smrg fprintf(fp, " "); 1157ec681f3Smrg 1167ec681f3Smrg bool print_comma = false; 1177ec681f3Smrg 1187ec681f3Smrg for (unsigned d = 0; d < info.nr_dests; ++d) { 1197ec681f3Smrg if (print_comma) 1207ec681f3Smrg fprintf(fp, ", "); 1217ec681f3Smrg else 1227ec681f3Smrg print_comma = true; 1237ec681f3Smrg 1247ec681f3Smrg agx_print_index(I->dest[d], fp); 1257ec681f3Smrg } 1267ec681f3Smrg 1277ec681f3Smrg for (unsigned s = 0; s < info.nr_srcs; ++s) { 1287ec681f3Smrg if (print_comma) 1297ec681f3Smrg fprintf(fp, ", "); 1307ec681f3Smrg else 1317ec681f3Smrg print_comma = true; 1327ec681f3Smrg 1337ec681f3Smrg agx_print_index(I->src[s], fp); 1347ec681f3Smrg } 1357ec681f3Smrg 1367ec681f3Smrg if (I->mask) { 1377ec681f3Smrg fprintf(fp, ", "); 1387ec681f3Smrg 1397ec681f3Smrg for (unsigned i = 0; i < 4; ++i) { 1407ec681f3Smrg if (I->mask & (1 << i)) 1417ec681f3Smrg fprintf(fp, "%c", "xyzw"[i]); 1427ec681f3Smrg } 1437ec681f3Smrg } 1447ec681f3Smrg 1457ec681f3Smrg /* TODO: Do better for enums, truth tables, etc */ 1467ec681f3Smrg if (info.immediates) { 1477ec681f3Smrg if (print_comma) 1487ec681f3Smrg fprintf(fp, ", "); 1497ec681f3Smrg else 1507ec681f3Smrg print_comma = true; 1517ec681f3Smrg 1527ec681f3Smrg fprintf(fp, "#%X", I->imm); 1537ec681f3Smrg } 1547ec681f3Smrg 1557ec681f3Smrg if (info.immediates & AGX_IMMEDIATE_DIM) { 1567ec681f3Smrg if (print_comma) 1577ec681f3Smrg fprintf(fp, ", "); 1587ec681f3Smrg else 1597ec681f3Smrg print_comma = true; 1607ec681f3Smrg 1617ec681f3Smrg fprintf(fp, "dim %u", I->dim); // TODO enumify 1627ec681f3Smrg } 1637ec681f3Smrg 1647ec681f3Smrg if (info.immediates & AGX_IMMEDIATE_SCOREBOARD) { 1657ec681f3Smrg if (print_comma) 1667ec681f3Smrg fprintf(fp, ", "); 1677ec681f3Smrg else 1687ec681f3Smrg print_comma = true; 1697ec681f3Smrg 1707ec681f3Smrg fprintf(fp, "slot %u", I->scoreboard); 1717ec681f3Smrg } 1727ec681f3Smrg 1737ec681f3Smrg if (info.immediates & AGX_IMMEDIATE_NEST) { 1747ec681f3Smrg if (print_comma) 1757ec681f3Smrg fprintf(fp, ", "); 1767ec681f3Smrg else 1777ec681f3Smrg print_comma = true; 1787ec681f3Smrg 1797ec681f3Smrg fprintf(fp, "n=%u", I->nest); 1807ec681f3Smrg } 1817ec681f3Smrg 1827ec681f3Smrg if ((info.immediates & AGX_IMMEDIATE_INVERT_COND) && I->invert_cond) { 1837ec681f3Smrg if (print_comma) 1847ec681f3Smrg fprintf(fp, ", "); 1857ec681f3Smrg else 1867ec681f3Smrg print_comma = true; 1877ec681f3Smrg 1887ec681f3Smrg fprintf(fp, "inv"); 1897ec681f3Smrg } 1907ec681f3Smrg 1917ec681f3Smrg fprintf(fp, "\n"); 1927ec681f3Smrg} 1937ec681f3Smrg 1947ec681f3Smrgvoid 1957ec681f3Smrgagx_print_block(agx_block *block, FILE *fp) 1967ec681f3Smrg{ 1977ec681f3Smrg fprintf(fp, "block%u {\n", block->name); 1987ec681f3Smrg 1997ec681f3Smrg agx_foreach_instr_in_block(block, ins) 2007ec681f3Smrg agx_print_instr(ins, fp); 2017ec681f3Smrg 2027ec681f3Smrg fprintf(fp, "}"); 2037ec681f3Smrg 2047ec681f3Smrg if (block->successors[0]) { 2057ec681f3Smrg fprintf(fp, " -> "); 2067ec681f3Smrg 2077ec681f3Smrg agx_foreach_successor(block, succ) 2087ec681f3Smrg fprintf(fp, "block%u ", succ->name); 2097ec681f3Smrg } 2107ec681f3Smrg 2117ec681f3Smrg if (block->predecessors->entries) { 2127ec681f3Smrg fprintf(fp, " from"); 2137ec681f3Smrg 2147ec681f3Smrg agx_foreach_predecessor(block, pred) 2157ec681f3Smrg fprintf(fp, " block%u", pred->name); 2167ec681f3Smrg } 2177ec681f3Smrg 2187ec681f3Smrg fprintf(fp, "\n\n"); 2197ec681f3Smrg} 2207ec681f3Smrg 2217ec681f3Smrgvoid 2227ec681f3Smrgagx_print_shader(agx_context *ctx, FILE *fp) 2237ec681f3Smrg{ 2247ec681f3Smrg agx_foreach_block(ctx, block) 2257ec681f3Smrg agx_print_block(block, fp); 2267ec681f3Smrg} 227