1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2022 Imagination Technologies Ltd.
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
5bf215546Sopenharmony_ci * of this software and associated documentation files (the "Software"), to deal
6bf215546Sopenharmony_ci * in the Software without restriction, including without limitation the rights
7bf215546Sopenharmony_ci * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8bf215546Sopenharmony_ci * copies of the Software, and to permit persons to whom the Software is
9bf215546Sopenharmony_ci * 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 THE
18bf215546Sopenharmony_ci * 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
24bf215546Sopenharmony_ci#include <inttypes.h>
25bf215546Sopenharmony_ci#include <stdbool.h>
26bf215546Sopenharmony_ci#include <stdint.h>
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci#include "rogue_dump.h"
29bf215546Sopenharmony_ci#include "rogue_shader.h"
30bf215546Sopenharmony_ci#include "rogue_util.h"
31bf215546Sopenharmony_ci#include "util/bitscan.h"
32bf215546Sopenharmony_ci
33bf215546Sopenharmony_ci/**
34bf215546Sopenharmony_ci * \file rogue_dump.c
35bf215546Sopenharmony_ci *
36bf215546Sopenharmony_ci * \brief Contains functions to dump Rogue data structures into a textual
37bf215546Sopenharmony_ci * format.
38bf215546Sopenharmony_ci */
39bf215546Sopenharmony_ci
40bf215546Sopenharmony_cistatic const char *const rogue_operand_string[ROGUE_OPERAND_TYPE_COUNT] = {
41bf215546Sopenharmony_ci   [ROGUE_OPERAND_TYPE_REG_TEMP] = "r",
42bf215546Sopenharmony_ci   [ROGUE_OPERAND_TYPE_REG_COEFF] = "cf",
43bf215546Sopenharmony_ci   [ROGUE_OPERAND_TYPE_REG_CONST] = "c",
44bf215546Sopenharmony_ci   [ROGUE_OPERAND_TYPE_REG_SHARED] = "sh",
45bf215546Sopenharmony_ci   [ROGUE_OPERAND_TYPE_REG_PIXEL_OUT] = "po",
46bf215546Sopenharmony_ci   [ROGUE_OPERAND_TYPE_REG_VERTEX_IN] = "vi",
47bf215546Sopenharmony_ci   [ROGUE_OPERAND_TYPE_REG_INTERNAL] = "i",
48bf215546Sopenharmony_ci   [ROGUE_OPERAND_TYPE_IMMEDIATE] = "#",
49bf215546Sopenharmony_ci   [ROGUE_OPERAND_TYPE_DRC] = "drc",
50bf215546Sopenharmony_ci   [ROGUE_OPERAND_TYPE_VREG] = "V",
51bf215546Sopenharmony_ci};
52bf215546Sopenharmony_ci
53bf215546Sopenharmony_cistatic const char *const rogue_opcode_string[ROGUE_OP_COUNT] = {
54bf215546Sopenharmony_ci   [ROGUE_OP_NOP] = "nop",
55bf215546Sopenharmony_ci   [ROGUE_OP_END_FRAG] = "end.frag",
56bf215546Sopenharmony_ci   [ROGUE_OP_END_VERT] = "end.vert",
57bf215546Sopenharmony_ci   [ROGUE_OP_WDF] = "wdf",
58bf215546Sopenharmony_ci   [ROGUE_OP_PIX_ITER_W] = "pixiter.w",
59bf215546Sopenharmony_ci   [ROGUE_OP_MAX] = "max",
60bf215546Sopenharmony_ci   [ROGUE_OP_MIN] = "min",
61bf215546Sopenharmony_ci   [ROGUE_OP_PACK_U8888] = "pack.u8888",
62bf215546Sopenharmony_ci   [ROGUE_OP_MOV] = "mov",
63bf215546Sopenharmony_ci   [ROGUE_OP_MOV_IMM] = "mov.imm",
64bf215546Sopenharmony_ci   [ROGUE_OP_FMA] = "fma",
65bf215546Sopenharmony_ci   [ROGUE_OP_MUL] = "mul",
66bf215546Sopenharmony_ci   [ROGUE_OP_VTXOUT] = "vtxout",
67bf215546Sopenharmony_ci};
68bf215546Sopenharmony_ci
69bf215546Sopenharmony_cistatic const char *const rogue_instr_flag_string[ROGUE_INSTR_FLAG_COUNT] = {
70bf215546Sopenharmony_ci   [ROGUE_INSTR_FLAG_SAT] = "sat",
71bf215546Sopenharmony_ci   [ROGUE_INSTR_FLAG_LP] = "lp",
72bf215546Sopenharmony_ci   [ROGUE_INSTR_FLAG_OLCHK] = "olchk",
73bf215546Sopenharmony_ci};
74bf215546Sopenharmony_ci
75bf215546Sopenharmony_cistatic const char rogue_vector_string[4] = {
76bf215546Sopenharmony_ci   'x',
77bf215546Sopenharmony_ci   'y',
78bf215546Sopenharmony_ci   'z',
79bf215546Sopenharmony_ci   'w',
80bf215546Sopenharmony_ci};
81bf215546Sopenharmony_ci
82bf215546Sopenharmony_ci/**
83bf215546Sopenharmony_ci * \brief Dumps an operand as text to a file pointer.
84bf215546Sopenharmony_ci *
85bf215546Sopenharmony_ci * \param[in] operand The operand.
86bf215546Sopenharmony_ci * \param[in] fp The file pointer.
87bf215546Sopenharmony_ci * \return true if successful, otherwise false.
88bf215546Sopenharmony_ci */
89bf215546Sopenharmony_cibool rogue_dump_operand(const struct rogue_operand *operand, FILE *fp)
90bf215546Sopenharmony_ci{
91bf215546Sopenharmony_ci   ASSERT_OPERAND_RANGE(operand->type);
92bf215546Sopenharmony_ci
93bf215546Sopenharmony_ci   fprintf(fp, "%s", rogue_operand_string[operand->type]);
94bf215546Sopenharmony_ci
95bf215546Sopenharmony_ci   if (operand->type == ROGUE_OPERAND_TYPE_IMMEDIATE)
96bf215546Sopenharmony_ci      fprintf(fp, "%" PRIu64, operand->immediate.value);
97bf215546Sopenharmony_ci   else if (operand->type == ROGUE_OPERAND_TYPE_DRC)
98bf215546Sopenharmony_ci      fprintf(fp, "%zu", operand->drc.number);
99bf215546Sopenharmony_ci   else if (rogue_check_bitset(rogue_onehot(operand->type), ROGUE_MASK_ANY_REG))
100bf215546Sopenharmony_ci      fprintf(fp, "%zu", operand->reg.number);
101bf215546Sopenharmony_ci   else if (operand->type == ROGUE_OPERAND_TYPE_VREG) {
102bf215546Sopenharmony_ci      fprintf(fp, "%zu", operand->vreg.number);
103bf215546Sopenharmony_ci      if (operand->vreg.is_vector)
104bf215546Sopenharmony_ci         fprintf(fp, ".%c", rogue_vector_string[operand->vreg.component]);
105bf215546Sopenharmony_ci   }
106bf215546Sopenharmony_ci
107bf215546Sopenharmony_ci   return true;
108bf215546Sopenharmony_ci}
109bf215546Sopenharmony_ci
110bf215546Sopenharmony_ci/**
111bf215546Sopenharmony_ci * \brief Dumps an instruction as text to a file pointer.
112bf215546Sopenharmony_ci *
113bf215546Sopenharmony_ci * \param[in] instr The instruction.
114bf215546Sopenharmony_ci * \param[in] fp The file pointer.
115bf215546Sopenharmony_ci * \return true if successful, otherwise false.
116bf215546Sopenharmony_ci */
117bf215546Sopenharmony_cibool rogue_dump_instr(const struct rogue_instr *instr, FILE *fp)
118bf215546Sopenharmony_ci{
119bf215546Sopenharmony_ci   uint64_t flags = 0U;
120bf215546Sopenharmony_ci
121bf215546Sopenharmony_ci   ASSERT_OPCODE_RANGE(instr->opcode);
122bf215546Sopenharmony_ci
123bf215546Sopenharmony_ci   flags = instr->flags;
124bf215546Sopenharmony_ci
125bf215546Sopenharmony_ci   fprintf(fp, "%s", rogue_opcode_string[instr->opcode]);
126bf215546Sopenharmony_ci
127bf215546Sopenharmony_ci   /* Iterate over each flag bit and print its string form. */
128bf215546Sopenharmony_ci   while (flags) {
129bf215546Sopenharmony_ci      uint64_t flag = u_bit_scan64(&flags);
130bf215546Sopenharmony_ci      ASSERT_INSTR_FLAG_RANGE(flag);
131bf215546Sopenharmony_ci      fprintf(fp, ".%s", rogue_instr_flag_string[flag]);
132bf215546Sopenharmony_ci   }
133bf215546Sopenharmony_ci
134bf215546Sopenharmony_ci   if (instr->num_operands)
135bf215546Sopenharmony_ci      fprintf(fp, " ");
136bf215546Sopenharmony_ci
137bf215546Sopenharmony_ci   /* Dump each operand. */
138bf215546Sopenharmony_ci   for (size_t u = 0U; u < instr->num_operands; ++u) {
139bf215546Sopenharmony_ci      CHECKF(rogue_dump_operand(&instr->operands[u], fp),
140bf215546Sopenharmony_ci             "Failed to dump operand.");
141bf215546Sopenharmony_ci      if (u < (instr->num_operands - 1))
142bf215546Sopenharmony_ci         fprintf(fp, ", ");
143bf215546Sopenharmony_ci   }
144bf215546Sopenharmony_ci
145bf215546Sopenharmony_ci   fprintf(fp, ";");
146bf215546Sopenharmony_ci
147bf215546Sopenharmony_ci   return true;
148bf215546Sopenharmony_ci}
149bf215546Sopenharmony_ci
150bf215546Sopenharmony_ci/**
151bf215546Sopenharmony_ci * \brief Dumps a shader as text to a file pointer.
152bf215546Sopenharmony_ci *
153bf215546Sopenharmony_ci * \param[in] shader The shader.
154bf215546Sopenharmony_ci * \param[in] fp The file pointer.
155bf215546Sopenharmony_ci * \return true if successful, otherwise false.
156bf215546Sopenharmony_ci */
157bf215546Sopenharmony_cibool rogue_dump_shader(const struct rogue_shader *shader, FILE *fp)
158bf215546Sopenharmony_ci{
159bf215546Sopenharmony_ci   /* Dump the shader stage. */
160bf215546Sopenharmony_ci   fprintf(fp, "# %s shader\n", _mesa_shader_stage_to_string(shader->stage));
161bf215546Sopenharmony_ci
162bf215546Sopenharmony_ci   /* Dump each instruction. */
163bf215546Sopenharmony_ci   foreach_instr (instr, &shader->instr_list) {
164bf215546Sopenharmony_ci      CHECKF(rogue_dump_instr(instr, fp), "Failed to dump instruction.");
165bf215546Sopenharmony_ci      fprintf(fp, "\n");
166bf215546Sopenharmony_ci   }
167bf215546Sopenharmony_ci   fprintf(fp, "\n");
168bf215546Sopenharmony_ci
169bf215546Sopenharmony_ci   return true;
170bf215546Sopenharmony_ci}
171