freedreno/a3xx/compiler: rename ir3_shader to ir3
[mesa.git] / src / gallium / drivers / freedreno / a3xx / disasm-a3xx.c
1 /*
2 * Copyright (c) 2013 Rob Clark <robdclark@gmail.com>
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
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <stdint.h>
27 #include <string.h>
28 #include <assert.h>
29
30 #include <util/u_debug.h>
31
32 #include "disasm.h"
33 #include "instr-a3xx.h"
34
35 static enum debug_t debug;
36
37 #define printf debug_printf
38
39 static const char *levels[] = {
40 "",
41 "\t",
42 "\t\t",
43 "\t\t\t",
44 "\t\t\t\t",
45 "\t\t\t\t\t",
46 "\t\t\t\t\t\t",
47 "\t\t\t\t\t\t\t",
48 "\t\t\t\t\t\t\t\t",
49 "\t\t\t\t\t\t\t\t\t",
50 "x",
51 "x",
52 "x",
53 "x",
54 "x",
55 "x",
56 };
57
58 static const char *component = "xyzw";
59
60 static const char *type[] = {
61 [TYPE_F16] = "f16",
62 [TYPE_F32] = "f32",
63 [TYPE_U16] = "u16",
64 [TYPE_U32] = "u32",
65 [TYPE_S16] = "s16",
66 [TYPE_S32] = "s32",
67 [TYPE_U8] = "u8",
68 [TYPE_S8] = "s8",
69 };
70
71 static void print_reg(reg_t reg, bool full, bool r, bool c, bool im,
72 bool neg, bool abs, bool addr_rel)
73 {
74 const char type = c ? 'c' : 'r';
75
76 // XXX I prefer - and || for neg/abs, but preserving format used
77 // by libllvm-a3xx for easy diffing..
78
79 if (abs && neg)
80 printf("(absneg)");
81 else if (neg)
82 printf("(neg)");
83 else if (abs)
84 printf("(abs)");
85
86 if (r)
87 printf("(r)");
88
89 if (im) {
90 printf("%d", reg.iim_val);
91 } else if (addr_rel) {
92 /* I would just use %+d but trying to make it diff'able with
93 * libllvm-a3xx...
94 */
95 if (reg.iim_val < 0)
96 printf("%s%c<a0.x - %d>", full ? "" : "h", type, -reg.iim_val);
97 else if (reg.iim_val > 0)
98 printf("%s%c<a0.x + %d>", full ? "" : "h", type, reg.iim_val);
99 else
100 printf("%s%c<a0.x>", full ? "" : "h", type);
101 } else if ((reg.num == REG_A0) && !c) {
102 printf("a0.%c", component[reg.comp]);
103 } else if ((reg.num == REG_P0) && !c) {
104 printf("p0.%c", component[reg.comp]);
105 } else {
106 printf("%s%c%d.%c", full ? "" : "h", type, reg.num, component[reg.comp]);
107 }
108 }
109
110
111 /* current instruction repeat flag: */
112 static unsigned repeat;
113
114 static void print_reg_dst(reg_t reg, bool full, bool addr_rel)
115 {
116 print_reg(reg, full, false, false, false, false, false, addr_rel);
117 }
118
119 static void print_reg_src(reg_t reg, bool full, bool r, bool c, bool im,
120 bool neg, bool abs, bool addr_rel)
121 {
122 print_reg(reg, full, r, c, im, neg, abs, addr_rel);
123 }
124
125 static void print_instr_cat0(instr_t *instr)
126 {
127 instr_cat0_t *cat0 = &instr->cat0;
128
129 switch (cat0->opc) {
130 case OPC_KILL:
131 printf(" %sp0.%c", cat0->inv ? "!" : "",
132 component[cat0->comp]);
133 break;
134 case OPC_BR:
135 printf(" %sp0.%c, #%d", cat0->inv ? "!" : "",
136 component[cat0->comp], cat0->immed);
137 break;
138 case OPC_JUMP:
139 case OPC_CALL:
140 printf(" #%d", cat0->immed);
141 break;
142 }
143
144 if ((debug & PRINT_VERBOSE) && (cat0->dummy1|cat0->dummy2|cat0->dummy3|cat0->dummy4))
145 printf("\t{0: %x,%x,%x,%x}", cat0->dummy1, cat0->dummy2, cat0->dummy3, cat0->dummy4);
146 }
147
148 static void print_instr_cat1(instr_t *instr)
149 {
150 instr_cat1_t *cat1 = &instr->cat1;
151
152 if (cat1->ul)
153 printf("(ul)");
154
155 if (cat1->src_type == cat1->dst_type) {
156 if ((cat1->src_type == TYPE_S16) && (((reg_t)cat1->dst).num == REG_A0)) {
157 /* special case (nmemonic?): */
158 printf("mova");
159 } else {
160 printf("mov.%s%s", type[cat1->src_type], type[cat1->dst_type]);
161 }
162 } else {
163 printf("cov.%s%s", type[cat1->src_type], type[cat1->dst_type]);
164 }
165
166 printf(" ");
167
168 if (cat1->even)
169 printf("(even)");
170
171 if (cat1->pos_inf)
172 printf("(pos_infinity)");
173
174 print_reg_dst((reg_t)(cat1->dst), type_size(cat1->dst_type) == 32,
175 cat1->dst_rel);
176
177 printf(", ");
178
179 /* ugg, have to special case this.. vs print_reg().. */
180 if (cat1->src_im) {
181 if (type_float(cat1->src_type))
182 printf("(%f)", cat1->fim_val);
183 else
184 printf("%d", cat1->iim_val);
185 } else if (cat1->src_rel && !cat1->src_c) {
186 /* I would just use %+d but trying to make it diff'able with
187 * libllvm-a3xx...
188 */
189 char type = cat1->src_rel_c ? 'c' : 'r';
190 if (cat1->off < 0)
191 printf("%c<a0.x - %d>", type, -cat1->off);
192 else if (cat1->off > 0)
193 printf("%c<a0.x + %d>", type, cat1->off);
194 else
195 printf("c<a0.x>");
196 } else {
197 print_reg_src((reg_t)(cat1->src), type_size(cat1->src_type) == 32,
198 cat1->src_r, cat1->src_c, cat1->src_im, false, false, false);
199 }
200
201 if ((debug & PRINT_VERBOSE) && (cat1->must_be_0))
202 printf("\t{1: %x}", cat1->must_be_0);
203 }
204
205 static void print_instr_cat2(instr_t *instr)
206 {
207 instr_cat2_t *cat2 = &instr->cat2;
208 static const char *cond[] = {
209 "lt",
210 "le",
211 "gt",
212 "ge",
213 "eq",
214 "ne",
215 "?6?",
216 };
217
218 switch (cat2->opc) {
219 case OPC_CMPS_F:
220 case OPC_CMPS_U:
221 case OPC_CMPS_S:
222 case OPC_CMPV_F:
223 case OPC_CMPV_U:
224 case OPC_CMPV_S:
225 printf(".%s", cond[cat2->cond]);
226 break;
227 }
228
229 printf(" ");
230 if (cat2->ei)
231 printf("(ei)");
232 print_reg_dst((reg_t)(cat2->dst), cat2->full ^ cat2->dst_half, false);
233 printf(", ");
234
235 if (cat2->c1.src1_c) {
236 print_reg_src((reg_t)(cat2->c1.src1), cat2->full, cat2->src1_r,
237 cat2->c1.src1_c, cat2->src1_im, cat2->src1_neg,
238 cat2->src1_abs, false);
239 } else if (cat2->rel1.src1_rel) {
240 print_reg_src((reg_t)(cat2->rel1.src1), cat2->full, cat2->src1_r,
241 cat2->rel1.src1_c, cat2->src1_im, cat2->src1_neg,
242 cat2->src1_abs, cat2->rel1.src1_rel);
243 } else {
244 print_reg_src((reg_t)(cat2->src1), cat2->full, cat2->src1_r,
245 false, cat2->src1_im, cat2->src1_neg,
246 cat2->src1_abs, false);
247 }
248
249 switch (cat2->opc) {
250 case OPC_ABSNEG_F:
251 case OPC_ABSNEG_S:
252 case OPC_CLZ_B:
253 case OPC_CLZ_S:
254 case OPC_SIGN_F:
255 case OPC_FLOOR_F:
256 case OPC_CEIL_F:
257 case OPC_RNDNE_F:
258 case OPC_RNDAZ_F:
259 case OPC_TRUNC_F:
260 case OPC_NOT_B:
261 case OPC_BFREV_B:
262 case OPC_SETRM:
263 case OPC_CBITS_B:
264 /* these only have one src reg */
265 break;
266 default:
267 printf(", ");
268 if (cat2->c2.src2_c) {
269 print_reg_src((reg_t)(cat2->c2.src2), cat2->full, cat2->src2_r,
270 cat2->c2.src2_c, cat2->src2_im, cat2->src2_neg,
271 cat2->src2_abs, false);
272 } else if (cat2->rel2.src2_rel) {
273 print_reg_src((reg_t)(cat2->rel2.src2), cat2->full, cat2->src2_r,
274 cat2->rel2.src2_c, cat2->src2_im, cat2->src2_neg,
275 cat2->src2_abs, cat2->rel2.src2_rel);
276 } else {
277 print_reg_src((reg_t)(cat2->src2), cat2->full, cat2->src2_r,
278 false, cat2->src2_im, cat2->src2_neg,
279 cat2->src2_abs, false);
280 }
281 break;
282 }
283 }
284
285 static void print_instr_cat3(instr_t *instr)
286 {
287 instr_cat3_t *cat3 = &instr->cat3;
288 bool full = instr_cat3_full(cat3);
289
290 printf(" ");
291 print_reg_dst((reg_t)(cat3->dst), full ^ cat3->dst_half, false);
292 printf(", ");
293 if (cat3->c1.src1_c) {
294 print_reg_src((reg_t)(cat3->c1.src1), full,
295 cat3->src1_r, cat3->c1.src1_c, false, cat3->src1_neg,
296 false, false);
297 } else if (cat3->rel1.src1_rel) {
298 print_reg_src((reg_t)(cat3->rel1.src1), full,
299 cat3->src1_r, cat3->rel1.src1_c, false, cat3->src1_neg,
300 false, cat3->rel1.src1_rel);
301 } else {
302 print_reg_src((reg_t)(cat3->src1), full,
303 cat3->src1_r, false, false, cat3->src1_neg,
304 false, false);
305 }
306 printf(", ");
307 print_reg_src((reg_t)cat3->src2, full,
308 cat3->src2_r, cat3->src2_c, false, cat3->src2_neg,
309 false, false);
310 printf(", ");
311 if (cat3->c2.src3_c) {
312 print_reg_src((reg_t)(cat3->c2.src3), full,
313 cat3->src3_r, cat3->c2.src3_c, false, cat3->src3_neg,
314 false, false);
315 } else if (cat3->rel2.src3_rel) {
316 print_reg_src((reg_t)(cat3->rel2.src3), full,
317 cat3->src3_r, cat3->rel2.src3_c, false, cat3->src3_neg,
318 false, cat3->rel2.src3_rel);
319 } else {
320 print_reg_src((reg_t)(cat3->src3), full,
321 cat3->src3_r, false, false, cat3->src3_neg,
322 false, false);
323 }
324 }
325
326 static void print_instr_cat4(instr_t *instr)
327 {
328 instr_cat4_t *cat4 = &instr->cat4;
329
330 printf(" ");
331 print_reg_dst((reg_t)(cat4->dst), cat4->full ^ cat4->dst_half, false);
332 printf(", ");
333
334 if (cat4->c.src_c) {
335 print_reg_src((reg_t)(cat4->c.src), cat4->full,
336 cat4->src_r, cat4->c.src_c, cat4->src_im,
337 cat4->src_neg, cat4->src_abs, false);
338 } else if (cat4->rel.src_rel) {
339 print_reg_src((reg_t)(cat4->rel.src), cat4->full,
340 cat4->src_r, cat4->rel.src_c, cat4->src_im,
341 cat4->src_neg, cat4->src_abs, cat4->rel.src_rel);
342 } else {
343 print_reg_src((reg_t)(cat4->src), cat4->full,
344 cat4->src_r, false, cat4->src_im,
345 cat4->src_neg, cat4->src_abs, false);
346 }
347
348 if ((debug & PRINT_VERBOSE) && (cat4->dummy1|cat4->dummy2))
349 printf("\t{4: %x,%x}", cat4->dummy1, cat4->dummy2);
350 }
351
352 static void print_instr_cat5(instr_t *instr)
353 {
354 static const struct {
355 bool src1, src2, samp, tex;
356 } info[0x1f] = {
357 [OPC_ISAM] = { true, false, true, true, },
358 [OPC_ISAML] = { true, true, true, true, },
359 [OPC_ISAMM] = { true, false, true, true, },
360 [OPC_SAM] = { true, false, true, true, },
361 [OPC_SAMB] = { true, true, true, true, },
362 [OPC_SAML] = { true, true, true, true, },
363 [OPC_SAMGQ] = { true, false, true, true, },
364 [OPC_GETLOD] = { true, false, true, true, },
365 [OPC_CONV] = { true, true, true, true, },
366 [OPC_CONVM] = { true, true, true, true, },
367 [OPC_GETSIZE] = { true, false, false, true, },
368 [OPC_GETBUF] = { false, false, false, true, },
369 [OPC_GETPOS] = { true, false, false, true, },
370 [OPC_GETINFO] = { false, false, false, true, },
371 [OPC_DSX] = { true, false, false, false, },
372 [OPC_DSY] = { true, false, false, false, },
373 [OPC_GATHER4R] = { true, false, true, true, },
374 [OPC_GATHER4G] = { true, false, true, true, },
375 [OPC_GATHER4B] = { true, false, true, true, },
376 [OPC_GATHER4A] = { true, false, true, true, },
377 [OPC_SAMGP0] = { true, false, true, true, },
378 [OPC_SAMGP1] = { true, false, true, true, },
379 [OPC_SAMGP2] = { true, false, true, true, },
380 [OPC_SAMGP3] = { true, false, true, true, },
381 [OPC_DSXPP_1] = { true, false, false, false, },
382 [OPC_DSYPP_1] = { true, false, false, false, },
383 [OPC_RGETPOS] = { false, false, false, false, },
384 [OPC_RGETINFO] = { false, false, false, false, },
385 };
386 instr_cat5_t *cat5 = &instr->cat5;
387 int i;
388
389 if (cat5->is_3d) printf(".3d");
390 if (cat5->is_a) printf(".a");
391 if (cat5->is_o) printf(".o");
392 if (cat5->is_p) printf(".p");
393 if (cat5->is_s) printf(".s");
394 if (cat5->is_s2en) printf(".s2en");
395
396 printf(" ");
397
398 switch (cat5->opc) {
399 case OPC_DSXPP_1:
400 case OPC_DSYPP_1:
401 break;
402 default:
403 printf("(%s)", type[cat5->type]);
404 break;
405 }
406
407 printf("(");
408 for (i = 0; i < 4; i++)
409 if (cat5->wrmask & (1 << i))
410 printf("%c", "xyzw"[i]);
411 printf(")");
412
413 print_reg_dst((reg_t)(cat5->dst), type_size(cat5->type) == 32, false);
414
415 if (info[cat5->opc].src1) {
416 printf(", ");
417 print_reg_src((reg_t)(cat5->src1), cat5->full, false, false, false,
418 false, false, false);
419 }
420
421 if (cat5->is_s2en) {
422 printf(", ");
423 print_reg_src((reg_t)(cat5->s2en.src2), cat5->full, false, false, false,
424 false, false, false);
425 printf(", ");
426 print_reg_src((reg_t)(cat5->s2en.src3), false, false, false, false,
427 false, false, false);
428 } else {
429 if (cat5->is_o || info[cat5->opc].src2) {
430 printf(", ");
431 print_reg_src((reg_t)(cat5->norm.src2), cat5->full,
432 false, false, false, false, false, false);
433 }
434 if (info[cat5->opc].samp)
435 printf(", s#%d", cat5->norm.samp);
436 if (info[cat5->opc].tex)
437 printf(", t#%d", cat5->norm.tex);
438 }
439
440 if (debug & PRINT_VERBOSE) {
441 if (cat5->is_s2en) {
442 if ((debug & PRINT_VERBOSE) && (cat5->s2en.dummy1|cat5->s2en.dummy2|cat5->dummy2))
443 printf("\t{5: %x,%x,%x}", cat5->s2en.dummy1, cat5->s2en.dummy2, cat5->dummy2);
444 } else {
445 if ((debug & PRINT_VERBOSE) && (cat5->norm.dummy1|cat5->dummy2))
446 printf("\t{5: %x,%x}", cat5->norm.dummy1, cat5->dummy2);
447 }
448 }
449 }
450
451 static int32_t u2i(uint32_t val, int nbits)
452 {
453 return ((val >> (nbits-1)) * ~((1 << nbits) - 1)) | val;
454 }
455
456 static void print_instr_cat6(instr_t *instr)
457 {
458 instr_cat6_t *cat6 = &instr->cat6;
459
460 printf(".%s ", type[cat6->type]);
461
462 switch (cat6->opc) {
463 case OPC_LDG:
464 case OPC_LDP:
465 case OPC_LDL:
466 case OPC_LDLW:
467 case OPC_LDLV:
468 /* load instructions: */
469 print_reg_dst((reg_t)(cat6->a.dst), type_size(cat6->type) == 32, false);
470 printf(",");
471 switch (cat6->opc) {
472 case OPC_LDG:
473 printf("g");
474 break;
475 case OPC_LDP:
476 printf("p");
477 break;
478 case OPC_LDL:
479 case OPC_LDLW:
480 case OPC_LDLV:
481 printf("l");
482 break;
483 }
484 printf("[");
485 print_reg_src((reg_t)(cat6->a.src), true,
486 false, false, false, false, false, false);
487 if (cat6->a.off)
488 printf("%+d", cat6->a.off);
489 printf("]");
490 break;
491 case OPC_PREFETCH:
492 /* similar to load instructions: */
493 printf("g[");
494 print_reg_src((reg_t)(cat6->a.src), true,
495 false, false, false, false, false, false);
496 if (cat6->a.off)
497 printf("%+d", cat6->a.off);
498 printf("]");
499 break;
500 case OPC_STG:
501 case OPC_STP:
502 case OPC_STL:
503 case OPC_STLW:
504 /* store instructions: */
505 switch (cat6->opc) {
506 case OPC_STG:
507 printf("g");
508 break;
509 case OPC_STP:
510 printf("p");
511 break;
512 case OPC_STL:
513 case OPC_STLW:
514 printf("l");
515 break;
516 }
517 printf("[");
518 print_reg_dst((reg_t)(cat6->b.dst), true, false);
519 if (cat6->b.off || cat6->b.off_hi)
520 printf("%+d", u2i((cat6->b.off_hi << 8) | cat6->b.off, 13));
521 printf("]");
522 printf(",");
523 print_reg_src((reg_t)(cat6->b.src), type_size(cat6->type) == 32,
524 false, false, false, false, false, false);
525
526 break;
527 case OPC_STI:
528 /* sti has same encoding as other store instructions, but
529 * slightly different syntax:
530 */
531 print_reg_dst((reg_t)(cat6->b.dst), false /* XXX is it always half? */, false);
532 if (cat6->b.off || cat6->b.off_hi)
533 printf("%+d", u2i((cat6->b.off_hi << 8) | cat6->b.off, 13));
534 printf(",");
535 print_reg_src((reg_t)(cat6->b.src), type_size(cat6->type) == 32,
536 false, false, false, false, false, false);
537 break;
538 }
539
540 printf(", %d", cat6->iim_val);
541
542 if (debug & PRINT_VERBOSE) {
543 switch (cat6->opc) {
544 case OPC_LDG:
545 case OPC_LDP:
546 /* load instructions: */
547 if (cat6->a.dummy1|cat6->a.dummy2|cat6->a.dummy3)
548 printf("\t{6: %x,%x,%x}", cat6->a.dummy1, cat6->a.dummy2, cat6->a.dummy3);
549 if ((cat6->a.must_be_one1 != 1) || (cat6->a.must_be_one2 != 1))
550 printf("{?? %d,%d ??}", cat6->a.must_be_one1, cat6->a.must_be_one2);
551 break;
552 case OPC_STG:
553 case OPC_STP:
554 case OPC_STI:
555 /* store instructions: */
556 if (cat6->b.dummy1|cat6->b.dummy2)
557 printf("\t{6: %x,%x}", cat6->b.dummy1, cat6->b.dummy2);
558 if ((cat6->b.must_be_one1 != 1) || (cat6->b.must_be_one2 != 1) ||
559 (cat6->b.must_be_zero1 != 0))
560 printf("{?? %d,%d,%d ??}", cat6->b.must_be_one1, cat6->b.must_be_one2,
561 cat6->b.must_be_zero1);
562 break;
563 }
564 }
565 }
566
567 /* size of largest OPC field of all the instruction categories: */
568 #define NOPC_BITS 6
569
570 struct opc_info {
571 uint16_t cat;
572 uint16_t opc;
573 const char *name;
574 void (*print)(instr_t *instr);
575 } opcs[1 << (3+NOPC_BITS)] = {
576 #define OPC(cat, opc, name) [((cat) << NOPC_BITS) | (opc)] = { (cat), (opc), #name, print_instr_cat##cat }
577 /* category 0: */
578 OPC(0, OPC_NOP, nop),
579 OPC(0, OPC_BR, br),
580 OPC(0, OPC_JUMP, jump),
581 OPC(0, OPC_CALL, call),
582 OPC(0, OPC_RET, ret),
583 OPC(0, OPC_KILL, kill),
584 OPC(0, OPC_END, end),
585 OPC(0, OPC_EMIT, emit),
586 OPC(0, OPC_CUT, cut),
587 OPC(0, OPC_CHMASK, chmask),
588 OPC(0, OPC_CHSH, chsh),
589 OPC(0, OPC_FLOW_REV, flow_rev),
590
591 /* category 1: */
592 OPC(1, 0, ),
593
594 /* category 2: */
595 OPC(2, OPC_ADD_F, add.f),
596 OPC(2, OPC_MIN_F, min.f),
597 OPC(2, OPC_MAX_F, max.f),
598 OPC(2, OPC_MUL_F, mul.f),
599 OPC(2, OPC_SIGN_F, sign.f),
600 OPC(2, OPC_CMPS_F, cmps.f),
601 OPC(2, OPC_ABSNEG_F, absneg.f),
602 OPC(2, OPC_CMPV_F, cmpv.f),
603 OPC(2, OPC_FLOOR_F, floor.f),
604 OPC(2, OPC_CEIL_F, ceil.f),
605 OPC(2, OPC_RNDNE_F, rndne.f),
606 OPC(2, OPC_RNDAZ_F, rndaz.f),
607 OPC(2, OPC_TRUNC_F, trunc.f),
608 OPC(2, OPC_ADD_U, add.u),
609 OPC(2, OPC_ADD_S, add.s),
610 OPC(2, OPC_SUB_U, sub.u),
611 OPC(2, OPC_SUB_S, sub.s),
612 OPC(2, OPC_CMPS_U, cmps.u),
613 OPC(2, OPC_CMPS_S, cmps.s),
614 OPC(2, OPC_MIN_U, min.u),
615 OPC(2, OPC_MIN_S, min.s),
616 OPC(2, OPC_MAX_U, max.u),
617 OPC(2, OPC_MAX_S, max.s),
618 OPC(2, OPC_ABSNEG_S, absneg.s),
619 OPC(2, OPC_AND_B, and.b),
620 OPC(2, OPC_OR_B, or.b),
621 OPC(2, OPC_NOT_B, not.b),
622 OPC(2, OPC_XOR_B, xor.b),
623 OPC(2, OPC_CMPV_U, cmpv.u),
624 OPC(2, OPC_CMPV_S, cmpv.s),
625 OPC(2, OPC_MUL_U, mul.u),
626 OPC(2, OPC_MUL_S, mul.s),
627 OPC(2, OPC_MULL_U, mull.u),
628 OPC(2, OPC_BFREV_B, bfrev.b),
629 OPC(2, OPC_CLZ_S, clz.s),
630 OPC(2, OPC_CLZ_B, clz.b),
631 OPC(2, OPC_SHL_B, shl.b),
632 OPC(2, OPC_SHR_B, shr.b),
633 OPC(2, OPC_ASHR_B, ashr.b),
634 OPC(2, OPC_BARY_F, bary.f),
635 OPC(2, OPC_MGEN_B, mgen.b),
636 OPC(2, OPC_GETBIT_B, getbit.b),
637 OPC(2, OPC_SETRM, setrm),
638 OPC(2, OPC_CBITS_B, cbits.b),
639 OPC(2, OPC_SHB, shb),
640 OPC(2, OPC_MSAD, msad),
641
642 /* category 3: */
643 OPC(3, OPC_MAD_U16, mad.u16),
644 OPC(3, OPC_MADSH_U16, madsh.u16),
645 OPC(3, OPC_MAD_S16, mad.s16),
646 OPC(3, OPC_MADSH_M16, madsh.m16),
647 OPC(3, OPC_MAD_U24, mad.u24),
648 OPC(3, OPC_MAD_S24, mad.s24),
649 OPC(3, OPC_MAD_F16, mad.f16),
650 OPC(3, OPC_MAD_F32, mad.f32),
651 OPC(3, OPC_SEL_B16, sel.b16),
652 OPC(3, OPC_SEL_B32, sel.b32),
653 OPC(3, OPC_SEL_S16, sel.s16),
654 OPC(3, OPC_SEL_S32, sel.s32),
655 OPC(3, OPC_SEL_F16, sel.f16),
656 OPC(3, OPC_SEL_F32, sel.f32),
657 OPC(3, OPC_SAD_S16, sad.s16),
658 OPC(3, OPC_SAD_S32, sad.s32),
659
660 /* category 4: */
661 OPC(4, OPC_RCP, rcp),
662 OPC(4, OPC_RSQ, rsq),
663 OPC(4, OPC_LOG2, log2),
664 OPC(4, OPC_EXP2, exp2),
665 OPC(4, OPC_SIN, sin),
666 OPC(4, OPC_COS, cos),
667 OPC(4, OPC_SQRT, sqrt),
668
669 /* category 5: */
670 OPC(5, OPC_ISAM, isam),
671 OPC(5, OPC_ISAML, isaml),
672 OPC(5, OPC_ISAMM, isamm),
673 OPC(5, OPC_SAM, sam),
674 OPC(5, OPC_SAMB, samb),
675 OPC(5, OPC_SAML, saml),
676 OPC(5, OPC_SAMGQ, samgq),
677 OPC(5, OPC_GETLOD, getlod),
678 OPC(5, OPC_CONV, conv),
679 OPC(5, OPC_CONVM, convm),
680 OPC(5, OPC_GETSIZE, getsize),
681 OPC(5, OPC_GETBUF, getbuf),
682 OPC(5, OPC_GETPOS, getpos),
683 OPC(5, OPC_GETINFO, getinfo),
684 OPC(5, OPC_DSX, dsx),
685 OPC(5, OPC_DSY, dsy),
686 OPC(5, OPC_GATHER4R, gather4r),
687 OPC(5, OPC_GATHER4G, gather4g),
688 OPC(5, OPC_GATHER4B, gather4b),
689 OPC(5, OPC_GATHER4A, gather4a),
690 OPC(5, OPC_SAMGP0, samgp0),
691 OPC(5, OPC_SAMGP1, samgp1),
692 OPC(5, OPC_SAMGP2, samgp2),
693 OPC(5, OPC_SAMGP3, samgp3),
694 OPC(5, OPC_DSXPP_1, dsxpp.1),
695 OPC(5, OPC_DSYPP_1, dsypp.1),
696 OPC(5, OPC_RGETPOS, rgetpos),
697 OPC(5, OPC_RGETINFO, rgetinfo),
698
699
700 /* category 6: */
701 OPC(6, OPC_LDG, ldg),
702 OPC(6, OPC_LDL, ldl),
703 OPC(6, OPC_LDP, ldp),
704 OPC(6, OPC_STG, stg),
705 OPC(6, OPC_STL, stl),
706 OPC(6, OPC_STP, stp),
707 OPC(6, OPC_STI, sti),
708 OPC(6, OPC_G2L, g2l),
709 OPC(6, OPC_L2G, l2g),
710 OPC(6, OPC_PREFETCH, prefetch),
711 OPC(6, OPC_LDLW, ldlw),
712 OPC(6, OPC_STLW, stlw),
713 OPC(6, OPC_RESFMT, resfmt),
714 OPC(6, OPC_RESINFO, resinf),
715 OPC(6, OPC_ATOMIC_ADD_L, atomic.add.l),
716 OPC(6, OPC_ATOMIC_SUB_L, atomic.sub.l),
717 OPC(6, OPC_ATOMIC_XCHG_L, atomic.xchg.l),
718 OPC(6, OPC_ATOMIC_INC_L, atomic.inc.l),
719 OPC(6, OPC_ATOMIC_DEC_L, atomic.dec.l),
720 OPC(6, OPC_ATOMIC_CMPXCHG_L, atomic.cmpxchg.l),
721 OPC(6, OPC_ATOMIC_MIN_L, atomic.min.l),
722 OPC(6, OPC_ATOMIC_MAX_L, atomic.max.l),
723 OPC(6, OPC_ATOMIC_AND_L, atomic.and.l),
724 OPC(6, OPC_ATOMIC_OR_L, atomic.or.l),
725 OPC(6, OPC_ATOMIC_XOR_L, atomic.xor.l),
726 OPC(6, OPC_LDGB_TYPED_4D, ldgb.typed.4d),
727 OPC(6, OPC_STGB_4D_4, stgb.4d.4),
728 OPC(6, OPC_STIB, stib),
729 OPC(6, OPC_LDC_4, ldc.4),
730 OPC(6, OPC_LDLV, ldlv),
731
732
733 #undef OPC
734 };
735
736 #define GETINFO(instr) (&(opcs[((instr)->opc_cat << NOPC_BITS) | instr_opc(instr)]))
737
738 // XXX hack.. probably should move this table somewhere common:
739 #include "ir3.h"
740 const char *ir3_instr_name(struct ir3_instruction *instr)
741 {
742 if (instr->category == -1) return "??meta??";
743 return opcs[(instr->category << NOPC_BITS) | instr->opc].name;
744 }
745
746 static void print_instr(uint32_t *dwords, int level, int n)
747 {
748 instr_t *instr = (instr_t *)dwords;
749 uint32_t opc = instr_opc(instr);
750 const char *name;
751
752 printf("%s%04d[%08xx_%08xx] ", levels[level], n, dwords[1], dwords[0]);
753
754 #if 0
755 /* print unknown bits: */
756 if (debug & PRINT_RAW)
757 printf("[%08xx_%08xx] ", dwords[1] & 0x001ff800, dwords[0] & 0x00000000);
758
759 if (debug & PRINT_VERBOSE)
760 printf("%d,%02d ", instr->opc_cat, opc);
761 #endif
762
763 /* NOTE: order flags are printed is a bit fugly.. but for now I
764 * try to match the order in llvm-a3xx disassembler for easy
765 * diff'ing..
766 */
767
768 if (instr->sync)
769 printf("(sy)");
770 if (instr->ss && (instr->opc_cat <= 4))
771 printf("(ss)");
772 if (instr->jmp_tgt)
773 printf("(jp)");
774 if (instr->repeat && (instr->opc_cat <= 4)) {
775 printf("(rpt%d)", instr->repeat);
776 repeat = instr->repeat;
777 } else {
778 repeat = 0;
779 }
780 if (instr->ul && ((2 <= instr->opc_cat) && (instr->opc_cat <= 4)))
781 printf("(ul)");
782
783 name = GETINFO(instr)->name;
784
785 if (name) {
786 printf("%s", name);
787 GETINFO(instr)->print(instr);
788 } else {
789 printf("unknown(%d,%d)", instr->opc_cat, opc);
790 }
791
792 printf("\n");
793 }
794
795 int disasm_a3xx(uint32_t *dwords, int sizedwords, int level, enum shader_t type)
796 {
797 int i;
798
799 assert((sizedwords % 2) == 0);
800
801 for (i = 0; i < sizedwords; i += 2)
802 print_instr(&dwords[i], level, i/2);
803
804 return 0;
805 }