xref: /aosp_15_r20/external/mesa3d/src/nouveau/mme/mme_fermi.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2022 Mary Guillemard
3  * SPDX-License-Identifier: MIT
4  */
5 #include "mme_fermi.h"
6 
7 #include "mme_bitpack_helpers.h"
8 
9 #define OP_TO_STR(OP) [MME_FERMI_OP_##OP] = #OP
10 static const char *op_to_str[] = {
11    OP_TO_STR(ALU_REG),
12    OP_TO_STR(ADD_IMM),
13    OP_TO_STR(MERGE),
14    OP_TO_STR(BFE_LSL_IMM),
15    OP_TO_STR(BFE_LSL_REG),
16    OP_TO_STR(STATE),
17    OP_TO_STR(UNK6),
18    OP_TO_STR(BRANCH),
19 };
20 #undef OP_TO_STR
21 
22 const char *
mme_fermi_op_to_str(enum mme_fermi_op op)23 mme_fermi_op_to_str(enum mme_fermi_op op)
24 {
25    assert(op < ARRAY_SIZE(op_to_str));
26    return op_to_str[op];
27 }
28 
29 #define ALU_OP_TO_STR(OP) [MME_FERMI_ALU_OP_##OP] = #OP
30 static const char *alu_op_to_str[] = {
31     ALU_OP_TO_STR(ADD),
32     ALU_OP_TO_STR(ADDC),
33     ALU_OP_TO_STR(SUB),
34     ALU_OP_TO_STR(SUBB),
35     ALU_OP_TO_STR(RESERVED4),
36     ALU_OP_TO_STR(RESERVED5),
37     ALU_OP_TO_STR(RESERVED6),
38     ALU_OP_TO_STR(RESERVED7),
39     ALU_OP_TO_STR(XOR),
40     ALU_OP_TO_STR(OR),
41     ALU_OP_TO_STR(AND),
42     ALU_OP_TO_STR(AND_NOT),
43     ALU_OP_TO_STR(NAND),
44     ALU_OP_TO_STR(RESERVED13),
45     ALU_OP_TO_STR(RESERVED14),
46     ALU_OP_TO_STR(RESERVED15),
47     ALU_OP_TO_STR(RESERVED16),
48     ALU_OP_TO_STR(RESERVED17),
49     ALU_OP_TO_STR(RESERVED18),
50     ALU_OP_TO_STR(RESERVED19),
51     ALU_OP_TO_STR(RESERVED20),
52     ALU_OP_TO_STR(RESERVED21),
53     ALU_OP_TO_STR(RESERVED22),
54     ALU_OP_TO_STR(RESERVED23),
55     ALU_OP_TO_STR(RESERVED24),
56     ALU_OP_TO_STR(RESERVED25),
57     ALU_OP_TO_STR(RESERVED26),
58     ALU_OP_TO_STR(RESERVED27),
59     ALU_OP_TO_STR(RESERVED28),
60     ALU_OP_TO_STR(RESERVED29),
61     ALU_OP_TO_STR(RESERVED30),
62     ALU_OP_TO_STR(RESERVED31),
63 };
64 #undef ALU_OP_TO_STR
65 
66 const char *
mme_fermi_alu_op_to_str(enum mme_fermi_alu_op op)67 mme_fermi_alu_op_to_str(enum mme_fermi_alu_op op)
68 {
69    assert(op < ARRAY_SIZE(alu_op_to_str));
70    return alu_op_to_str[op];
71 }
72 
73 #define ASSIGN_OP_TO_STR(OP) [MME_FERMI_ASSIGN_OP_##OP] = #OP
74 static const char *assign_op_to_str[] = {
75     ASSIGN_OP_TO_STR(LOAD),
76     ASSIGN_OP_TO_STR(MOVE),
77     ASSIGN_OP_TO_STR(MOVE_SET_MADDR),
78     ASSIGN_OP_TO_STR(LOAD_EMIT),
79     ASSIGN_OP_TO_STR(MOVE_EMIT),
80     ASSIGN_OP_TO_STR(LOAD_SET_MADDR),
81     ASSIGN_OP_TO_STR(MOVE_SET_MADDR_LOAD_EMIT),
82     ASSIGN_OP_TO_STR(MOVE_SET_MADDR_LOAD_EMIT_HIGH),
83 };
84 #undef ASSIGN_OP_TO_STR
85 
86 const char *
mme_fermi_assign_op_to_str(enum mme_fermi_assign_op op)87 mme_fermi_assign_op_to_str(enum mme_fermi_assign_op op)
88 {
89    assert(op < ARRAY_SIZE(assign_op_to_str));
90    return assign_op_to_str[op];
91 }
92 
mme_fermi_encode(uint32_t * out,uint32_t inst_count,const struct mme_fermi_inst * insts)93 void mme_fermi_encode(uint32_t *out, uint32_t inst_count,
94                       const struct mme_fermi_inst *insts)
95 {
96    for (uint32_t i = 0; i < inst_count; i++) {
97       uint32_t *b = &out[i];
98       *b = 0;
99 
100       pack_uint(b, 0,  3, insts[i].op);
101       pack_uint(b, 7,  7, insts[i].end_next);
102       pack_uint(b, 8, 10, insts[i].dst);
103 
104       if (insts[i].op != MME_FERMI_OP_BRANCH) {
105          pack_uint(b, 4, 6, insts[i].assign_op);
106       }
107 
108       if (insts[i].op == MME_FERMI_OP_ALU_REG) {
109          pack_uint(b, 11, 13, insts[i].src[0]);
110          pack_uint(b, 14, 16, insts[i].src[1]);
111          pack_uint(b, 17, 21, insts[i].alu_op);
112       } else if (insts[i].op == MME_FERMI_OP_ADD_IMM ||
113                  insts[i].op == MME_FERMI_OP_STATE) {
114          pack_uint(b, 11, 13, insts[i].src[0]);
115          pack_sint(b, 14, 31, insts[i].imm);
116       } else if (insts[i].op == MME_FERMI_OP_MERGE ||
117                  insts[i].op == MME_FERMI_OP_BFE_LSL_IMM ||
118                  insts[i].op == MME_FERMI_OP_BFE_LSL_REG) {
119          pack_uint(b, 11, 13, insts[i].src[0]);
120          pack_uint(b, 14, 16, insts[i].src[1]);
121          pack_uint(b, 17, 21, insts[i].bitfield.src_bit);
122          pack_uint(b, 22, 26, insts[i].bitfield.size);
123          pack_uint(b, 27, 31, insts[i].bitfield.dst_bit);
124       } else if (insts[i].op == MME_FERMI_OP_BRANCH) {
125          pack_uint(b,  4,  4, insts[i].branch.not_zero);
126          pack_uint(b,  5,  5, insts[i].branch.no_delay);
127          pack_uint(b, 11, 13, insts[i].src[0]);
128          pack_sint(b, 14, 31, insts[i].imm);
129       }
130    }
131 }
132 
mme_fermi_decode(struct mme_fermi_inst * insts,const uint32_t * in,uint32_t inst_count)133 void mme_fermi_decode(struct mme_fermi_inst *insts,
134                       const uint32_t *in, uint32_t inst_count)
135 {
136    for (uint32_t i = 0; i < inst_count; i++) {
137       const uint32_t *b = &in[i];
138 
139       insts[i] = (struct mme_fermi_inst) {
140          .op       = unpack_uint(b, 0, 3),
141          .end_next = unpack_uint(b, 7, 7),
142          .dst      = unpack_uint(b, 8, 10),
143       };
144 
145       if (insts[i].op != MME_FERMI_OP_BRANCH) {
146          insts[i].assign_op = unpack_uint(b, 4, 6);
147       }
148 
149       if (insts[i].op == MME_FERMI_OP_ALU_REG) {
150          insts[i].src[0] = unpack_uint(b, 11, 13);
151          insts[i].src[1] = unpack_uint(b, 14, 16);
152          insts[i].alu_op = unpack_uint(b, 17, 21);
153       } else if (insts[i].op == MME_FERMI_OP_ADD_IMM ||
154                  insts[i].op == MME_FERMI_OP_STATE) {
155          insts[i].src[0] = unpack_uint(b, 11, 13);
156          insts[i].imm    = unpack_sint(b, 14, 31);
157       } else if (insts[i].op == MME_FERMI_OP_MERGE ||
158                  insts[i].op == MME_FERMI_OP_BFE_LSL_IMM ||
159                  insts[i].op == MME_FERMI_OP_BFE_LSL_REG) {
160          insts[i].src[0] = unpack_uint(b, 11, 13);
161          insts[i].src[1] = unpack_uint(b, 14, 16);
162          insts[i].bitfield.src_bit  = unpack_uint(b, 17, 21);
163          insts[i].bitfield.size     = unpack_uint(b, 22, 26);
164          insts[i].bitfield.dst_bit  = unpack_uint(b, 27, 31);
165       } else if (insts[i].op == MME_FERMI_OP_BRANCH) {
166          insts[i].branch.not_zero   = unpack_uint(b, 4, 4);
167          insts[i].branch.no_delay   = unpack_uint(b, 5, 5);
168          insts[i].src[0]            = unpack_uint(b, 11, 13);
169          insts[i].imm               = unpack_sint(b, 14, 31);
170       }
171    }
172 }
173 
174 static void
print_indent(FILE * fp,unsigned depth)175 print_indent(FILE *fp, unsigned depth)
176 {
177    for (unsigned i = 0; i < depth; i++)
178       fprintf(fp, "    ");
179 }
180 
181 static void
print_reg(FILE * fp,enum mme_fermi_reg reg)182 print_reg(FILE *fp, enum mme_fermi_reg reg)
183 {
184    if (reg == MME_FERMI_REG_ZERO) {
185       fprintf(fp, " $zero");
186    } else {
187       fprintf(fp, " $r%u", (unsigned)reg);
188    }
189 }
190 
191 static void
print_imm(FILE * fp,const struct mme_fermi_inst * inst)192 print_imm(FILE *fp, const struct mme_fermi_inst *inst)
193 {
194    int32_t imm = util_mask_sign_extend(inst->imm, 18);
195 
196    fprintf(fp, " %d /* 0x%04x */", (int)imm, (unsigned)imm);
197 }
198 
199 void
mme_fermi_print_inst(FILE * fp,unsigned indent,const struct mme_fermi_inst * inst)200 mme_fermi_print_inst(FILE *fp, unsigned indent,
201                      const struct mme_fermi_inst *inst)
202 {
203    print_indent(fp, indent);
204 
205    switch (inst->op) {
206       case MME_FERMI_OP_ALU_REG:
207          fprintf(fp, "%s", mme_fermi_alu_op_to_str(inst->alu_op));
208          print_reg(fp, inst->src[0]);
209          print_reg(fp, inst->src[1]);
210 
211          if (inst->alu_op == MME_FERMI_ALU_OP_ADDC) {
212             fprintf(fp, " $carry");
213          } else if (inst->alu_op == MME_FERMI_ALU_OP_SUBB) {
214             fprintf(fp, " $borrow");
215          }
216          break;
217       case MME_FERMI_OP_ADD_IMM:
218       case MME_FERMI_OP_STATE:
219          fprintf(fp, "%s", mme_fermi_op_to_str(inst->op));
220          print_reg(fp, inst->src[0]);
221          print_imm(fp, inst);
222          break;
223       case MME_FERMI_OP_MERGE:
224          fprintf(fp, "%s", mme_fermi_op_to_str(inst->op));
225          print_reg(fp, inst->src[0]);
226          print_reg(fp, inst->src[1]);
227          fprintf(fp, " (%u, %u, %u)", inst->bitfield.dst_bit,
228                                       inst->bitfield.size,
229                                       inst->bitfield.src_bit);
230          break;
231       case MME_FERMI_OP_BFE_LSL_IMM:
232          fprintf(fp, "%s", mme_fermi_op_to_str(inst->op));
233          print_reg(fp, inst->src[0]);
234          print_reg(fp, inst->src[1]);
235          fprintf(fp, " (%u, %u)", inst->bitfield.dst_bit,
236                                   inst->bitfield.size);
237          break;
238       case MME_FERMI_OP_BFE_LSL_REG:
239          fprintf(fp, "%s", mme_fermi_op_to_str(inst->op));
240          print_reg(fp, inst->src[0]);
241          print_reg(fp, inst->src[1]);
242          fprintf(fp, " (%u, %u)", inst->bitfield.src_bit,
243                                   inst->bitfield.size);
244          break;
245       case MME_FERMI_OP_BRANCH:
246          if (inst->branch.not_zero) {
247             fprintf(fp, "BNZ");
248          } else {
249             fprintf(fp, "BZ");
250          }
251          print_reg(fp, inst->src[0]);
252          print_imm(fp, inst);
253 
254          if (inst->branch.no_delay) {
255             fprintf(fp, " NO_DELAY");
256          }
257 
258          break;
259       default:
260          fprintf(fp, "%s", mme_fermi_op_to_str(inst->op));
261          break;
262    }
263 
264    if (inst->op != MME_FERMI_OP_BRANCH) {
265       fprintf(fp, "\n");
266       print_indent(fp, indent);
267 
268       fprintf(fp, "%s", mme_fermi_assign_op_to_str(inst->assign_op));
269       print_reg(fp, inst->dst);
270 
271       if (inst->assign_op != MME_FERMI_ASSIGN_OP_LOAD) {
272          fprintf(fp, " $scratch");
273       }
274    }
275 
276    if (inst->end_next) {
277       fprintf(fp, "\n");
278       print_indent(fp, indent);
279       fprintf(fp, "END_NEXT");
280    }
281 
282    fprintf(fp, "\n");
283 
284 }
285 
286 void
mme_fermi_print(FILE * fp,const struct mme_fermi_inst * insts,uint32_t inst_count)287 mme_fermi_print(FILE *fp, const struct mme_fermi_inst *insts,
288                 uint32_t inst_count)
289 {
290    for (uint32_t i = 0; i < inst_count; i++) {
291       fprintf(fp, "%u:\n", i);
292       mme_fermi_print_inst(fp, 1, &insts[i]);
293    }
294 }
295 
296 void
mme_fermi_dump(FILE * fp,uint32_t * encoded,size_t encoded_size)297 mme_fermi_dump(FILE *fp, uint32_t *encoded, size_t encoded_size)
298 {
299    uint32_t inst_count = encoded_size / 4;
300    for (uint32_t i = 0; i < inst_count; i++) {
301       struct mme_fermi_inst inst;
302       mme_fermi_decode(&inst, &encoded[i], 1);
303       mme_fermi_print_inst(fp, 1, &inst);
304    }
305 }
306