1 /*
2 * Copyright (c) 2018 Lima Project
3 *
4 * Copyright (c) 2013 Codethink (http://www.codethink.co.uk)
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, sub license,
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
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the 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 NON-INFRINGEMENT. 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
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
24 *
25 */
26
27 #include "util/half_float.h"
28
29 #include "ppir.h"
30 #include "codegen.h"
31
32 typedef struct {
33 char *name;
34 unsigned srcs;
35 } asm_op;
36
37 static void
print_swizzle(uint8_t swizzle,FILE * fp)38 print_swizzle(uint8_t swizzle, FILE *fp)
39 {
40 if (swizzle == 0xE4)
41 return;
42
43 fprintf(fp, ".");
44 for (unsigned i = 0; i < 4; i++, swizzle >>= 2)
45 fprintf(fp, "%c", "xyzw"[swizzle & 3]);
46 }
47
48 static void
print_mask(uint8_t mask,FILE * fp)49 print_mask(uint8_t mask, FILE *fp)
50 {
51 if (mask == 0xF)
52 return;
53
54 fprintf(fp, ".");
55 if (mask & 1) fprintf(fp, "x");
56 if (mask & 2) fprintf(fp, "y");
57 if (mask & 4) fprintf(fp, "z");
58 if (mask & 8) fprintf(fp, "w");
59 }
60
61 static void
print_reg(ppir_codegen_vec4_reg reg,const char * special,FILE * fp)62 print_reg(ppir_codegen_vec4_reg reg, const char *special, FILE *fp)
63 {
64 if (special) {
65 fprintf(fp, "%s", special);
66 } else {
67 switch (reg)
68 {
69 case ppir_codegen_vec4_reg_constant0:
70 fprintf(fp, "^const0");
71 break;
72 case ppir_codegen_vec4_reg_constant1:
73 fprintf(fp, "^const1");
74 break;
75 case ppir_codegen_vec4_reg_texture:
76 fprintf(fp, "^texture");
77 break;
78 case ppir_codegen_vec4_reg_uniform:
79 fprintf(fp, "^uniform");
80 break;
81 default:
82 fprintf(fp, "$%u", reg);
83 break;
84 }
85 }
86 }
87
88 static void
print_vector_source(ppir_codegen_vec4_reg reg,const char * special,uint8_t swizzle,bool abs,bool neg,FILE * fp)89 print_vector_source(ppir_codegen_vec4_reg reg, const char *special,
90 uint8_t swizzle, bool abs, bool neg, FILE *fp)
91 {
92 if (neg)
93 fprintf(fp, "-");
94 if (abs)
95 fprintf(fp, "abs(");
96
97 print_reg(reg, special, fp);
98 print_swizzle(swizzle, fp);
99
100 if (abs)
101 fprintf(fp, ")");
102 }
103
104 static void
print_source_scalar(unsigned reg,const char * special,bool abs,bool neg,FILE * fp)105 print_source_scalar(unsigned reg, const char *special, bool abs, bool neg, FILE *fp)
106 {
107 if (neg)
108 fprintf(fp, "-");
109 if (abs)
110 fprintf(fp, "abs(");
111
112 print_reg(reg >> 2, special, fp);
113 if (!special)
114 fprintf(fp, ".%c", "xyzw"[reg & 3]);
115
116 if (abs)
117 fprintf(fp, ")");
118 }
119
120 static void
print_varying_source(ppir_codegen_field_varying * varying,FILE * fp)121 print_varying_source(ppir_codegen_field_varying *varying, FILE *fp)
122 {
123 switch (varying->imm.alignment) {
124 case 0:
125 fprintf(fp, "%u.%c", varying->imm.index >> 2,
126 "xyzw"[varying->imm.index & 3]);
127 break;
128 case 1: {
129 const char *c[2] = {"xy", "zw"};
130 fprintf(fp, "%u.%s", varying->imm.index >> 1, c[varying->imm.index & 1]);
131 break;
132 }
133 default:
134 fprintf(fp, "%u", varying->imm.index);
135 break;
136 }
137
138 if (varying->imm.offset_vector != 15) {
139 unsigned reg = (varying->imm.offset_vector << 2) +
140 varying->imm.offset_scalar;
141 fprintf(fp, "+");
142 print_source_scalar(reg, NULL, false, false, fp);
143 }
144 }
145
146 static void
print_outmod(ppir_codegen_outmod modifier,FILE * fp)147 print_outmod(ppir_codegen_outmod modifier, FILE *fp)
148 {
149 switch (modifier)
150 {
151 case ppir_codegen_outmod_clamp_fraction:
152 fprintf(fp, ".sat");
153 break;
154 case ppir_codegen_outmod_clamp_positive:
155 fprintf(fp, ".pos");
156 break;
157 case ppir_codegen_outmod_round:
158 fprintf(fp, ".int");
159 break;
160 default:
161 break;
162 }
163 }
164
165 static void
print_dest_scalar(unsigned reg,FILE * fp)166 print_dest_scalar(unsigned reg, FILE *fp)
167 {
168 fprintf(fp, "$%u", reg >> 2);
169 fprintf(fp, ".%c ", "xyzw"[reg & 3]);
170 }
171
172 static void
print_const(unsigned const_num,uint16_t * val,FILE * fp)173 print_const(unsigned const_num, uint16_t *val, FILE *fp)
174 {
175 fprintf(fp, "const%u", const_num);
176 for (unsigned i = 0; i < 4; i++)
177 fprintf(fp, " %f", _mesa_half_to_float(val[i]));
178 }
179
180 static void
print_const0(void * code,unsigned offset,FILE * fp)181 print_const0(void *code, unsigned offset, FILE *fp)
182 {
183 (void) offset;
184
185 print_const(0, code, fp);
186 }
187
188 static void
print_const1(void * code,unsigned offset,FILE * fp)189 print_const1(void *code, unsigned offset, FILE *fp)
190 {
191 (void) offset;
192
193 print_const(1, code, fp);
194 }
195
196 static void
print_varying(void * code,unsigned offset,FILE * fp)197 print_varying(void *code, unsigned offset, FILE *fp)
198 {
199 (void) offset;
200 ppir_codegen_field_varying *varying = code;
201
202 fprintf(fp, "load");
203
204 bool perspective = varying->imm.source_type < 2 && varying->imm.perspective;
205 if (perspective)
206 {
207 fprintf(fp, ".perspective");
208 switch (varying->imm.perspective)
209 {
210 case 2:
211 fprintf(fp, ".z");
212 break;
213 case 3:
214 fprintf(fp, ".w");
215 break;
216 default:
217 fprintf(fp, ".unknown");
218 break;
219 }
220 }
221
222 fprintf(fp, ".v ");
223
224 switch (varying->imm.dest)
225 {
226 case ppir_codegen_vec4_reg_discard:
227 fprintf(fp, "^discard");
228 break;
229 default:
230 fprintf(fp, "$%u", varying->imm.dest);
231 break;
232 }
233 print_mask(varying->imm.mask, fp);
234 fprintf(fp, " ");
235
236 switch (varying->imm.source_type) {
237 case 1:
238 print_vector_source(varying->reg.source, NULL, varying->reg.swizzle,
239 varying->reg.absolute, varying->reg.negate, fp);
240 break;
241 case 2:
242 switch (varying->imm.perspective) {
243 case 0:
244 fprintf(fp, "cube(");
245 print_varying_source(varying, fp);
246 fprintf(fp, ")");
247 break;
248 case 1:
249 fprintf(fp, "cube(");
250 print_vector_source(varying->reg.source, NULL, varying->reg.swizzle,
251 varying->reg.absolute, varying->reg.negate, fp);
252 fprintf(fp, ")");
253 break;
254 case 2:
255 fprintf(fp, "normalize(");
256 print_vector_source(varying->reg.source, NULL, varying->reg.swizzle,
257 varying->reg.absolute, varying->reg.negate, fp);
258 fprintf(fp, ")");
259 break;
260 default:
261 fprintf(fp, "gl_FragCoord");
262 break;
263 }
264 break;
265 case 3:
266 if (varying->imm.perspective)
267 fprintf(fp, "gl_FrontFacing");
268 else
269 fprintf(fp, "gl_PointCoord");
270 break;
271 default:
272 print_varying_source(varying, fp);
273 break;
274 }
275 }
276
277 static void
print_sampler(void * code,unsigned offset,FILE * fp)278 print_sampler(void *code, unsigned offset, FILE *fp)
279 {
280 (void) offset;
281 ppir_codegen_field_sampler *sampler = code;
282
283 fprintf(fp, "texld");
284 if (sampler->lod_bias_en)
285 fprintf(fp, ".b");
286
287 switch (sampler->type) {
288 case ppir_codegen_sampler_type_2d:
289 fprintf(fp, ".2d");
290 break;
291 case ppir_codegen_sampler_type_cube:
292 fprintf(fp, ".cube");
293 break;
294 default:
295 fprintf(fp, "_t%u", sampler->type);
296 break;
297 }
298
299 fprintf(fp, " %u", sampler->index);
300
301 if (sampler->offset_en)
302 {
303 fprintf(fp, "+");
304 print_source_scalar(sampler->index_offset, NULL, false, false, fp);
305 }
306
307 if (sampler->lod_bias_en)
308 {
309 fprintf(fp, " ");
310 print_source_scalar(sampler->lod_bias, NULL, false, false, fp);
311 }
312 }
313
314 static void
print_uniform(void * code,unsigned offset,FILE * fp)315 print_uniform(void *code, unsigned offset, FILE *fp)
316 {
317 (void) offset;
318 ppir_codegen_field_uniform *uniform = code;
319
320 fprintf(fp, "load.");
321
322 switch (uniform->source) {
323 case ppir_codegen_uniform_src_uniform:
324 fprintf(fp, "u");
325 break;
326 case ppir_codegen_uniform_src_temporary:
327 fprintf(fp, "t");
328 break;
329 default:
330 fprintf(fp, ".u%u", uniform->source);
331 break;
332 }
333
334 int16_t index = uniform->index;
335 switch (uniform->alignment) {
336 case 2:
337 fprintf(fp, " %d", index);
338 break;
339 case 1:
340 fprintf(fp, " %d.%s", index / 2, (index & 1) ? "zw" : "xy");
341 break;
342 default:
343 fprintf(fp, " %d.%c", index / 4, "xyzw"[index & 3]);
344 break;
345 }
346
347 if (uniform->offset_en) {
348 fprintf(fp, "+");
349 print_source_scalar(uniform->offset_reg, NULL, false, false, fp);
350 }
351 }
352
353 #define CASE(_name, _srcs) \
354 [ppir_codegen_vec4_mul_op_##_name] = { \
355 .name = #_name, \
356 .srcs = _srcs \
357 }
358
359 static const asm_op vec4_mul_ops[] = {
360 [0 ... 7] = {
361 .name = "mul",
362 .srcs = 2
363 },
364 CASE(not, 1),
365 CASE(and, 2),
366 CASE(or, 2),
367 CASE(xor, 2),
368 CASE(ne, 2),
369 CASE(gt, 2),
370 CASE(ge, 2),
371 CASE(eq, 2),
372 CASE(min, 2),
373 CASE(max, 2),
374 CASE(mov, 1),
375 };
376
377 #undef CASE
378
379 static void
print_vec4_mul(void * code,unsigned offset,FILE * fp)380 print_vec4_mul(void *code, unsigned offset, FILE *fp)
381 {
382 (void) offset;
383 ppir_codegen_field_vec4_mul *vec4_mul = code;
384
385 asm_op op = vec4_mul_ops[vec4_mul->op];
386
387 if (op.name)
388 fprintf(fp, "%s", op.name);
389 else
390 fprintf(fp, "op%u", vec4_mul->op);
391 print_outmod(vec4_mul->dest_modifier, fp);
392 fprintf(fp, ".v0 ");
393
394 if (vec4_mul->mask) {
395 fprintf(fp, "$%u", vec4_mul->dest);
396 print_mask(vec4_mul->mask, fp);
397 fprintf(fp, " ");
398 }
399
400 print_vector_source(vec4_mul->arg0_source, NULL,
401 vec4_mul->arg0_swizzle,
402 vec4_mul->arg0_absolute,
403 vec4_mul->arg0_negate, fp);
404
405 if (vec4_mul->op < 8 && vec4_mul->op != 0) {
406 fprintf(fp, "<<%u", vec4_mul->op);
407 }
408
409 fprintf(fp, " ");
410
411 if (op.srcs > 1) {
412 print_vector_source(vec4_mul->arg1_source, NULL,
413 vec4_mul->arg1_swizzle,
414 vec4_mul->arg1_absolute,
415 vec4_mul->arg1_negate, fp);
416 }
417 }
418
419 #define CASE(_name, _srcs) \
420 [ppir_codegen_vec4_acc_op_##_name] = { \
421 .name = #_name, \
422 .srcs = _srcs \
423 }
424
425 static const asm_op vec4_acc_ops[] = {
426 CASE(add, 2),
427 CASE(fract, 1),
428 CASE(ne, 2),
429 CASE(gt, 2),
430 CASE(ge, 2),
431 CASE(eq, 2),
432 CASE(floor, 1),
433 CASE(ceil, 1),
434 CASE(min, 2),
435 CASE(max, 2),
436 CASE(sum3, 1),
437 CASE(sum4, 1),
438 CASE(dFdx, 2),
439 CASE(dFdy, 2),
440 CASE(sel, 2),
441 CASE(mov, 1),
442 };
443
444 #undef CASE
445
446 static void
print_vec4_acc(void * code,unsigned offset,FILE * fp)447 print_vec4_acc(void *code, unsigned offset, FILE *fp)
448 {
449 (void) offset;
450 ppir_codegen_field_vec4_acc *vec4_acc = code;
451
452 asm_op op = vec4_acc_ops[vec4_acc->op];
453
454 if (op.name)
455 fprintf(fp, "%s", op.name);
456 else
457 fprintf(fp, "op%u", vec4_acc->op);
458 print_outmod(vec4_acc->dest_modifier, fp);
459 fprintf(fp, ".v1 ");
460
461 if (vec4_acc->mask) {
462 fprintf(fp, "$%u", vec4_acc->dest);
463 print_mask(vec4_acc->mask, fp);
464 fprintf(fp, " ");
465 }
466
467 print_vector_source(vec4_acc->arg0_source, vec4_acc->mul_in ? "^v0" : NULL,
468 vec4_acc->arg0_swizzle,
469 vec4_acc->arg0_absolute,
470 vec4_acc->arg0_negate, fp);
471
472 if (op.srcs > 1) {
473 fprintf(fp, " ");
474 print_vector_source(vec4_acc->arg1_source, NULL,
475 vec4_acc->arg1_swizzle,
476 vec4_acc->arg1_absolute,
477 vec4_acc->arg1_negate, fp);
478 }
479 }
480
481 #define CASE(_name, _srcs) \
482 [ppir_codegen_float_mul_op_##_name] = { \
483 .name = #_name, \
484 .srcs = _srcs \
485 }
486
487 static const asm_op float_mul_ops[] = {
488 [0 ... 7] = {
489 .name = "mul",
490 .srcs = 2
491 },
492 CASE(not, 1),
493 CASE(and, 2),
494 CASE(or, 2),
495 CASE(xor, 2),
496 CASE(ne, 2),
497 CASE(gt, 2),
498 CASE(ge, 2),
499 CASE(eq, 2),
500 CASE(min, 2),
501 CASE(max, 2),
502 CASE(mov, 1),
503 };
504
505 #undef CASE
506
507 static void
print_float_mul(void * code,unsigned offset,FILE * fp)508 print_float_mul(void *code, unsigned offset, FILE *fp)
509 {
510 (void) offset;
511 ppir_codegen_field_float_mul *float_mul = code;
512
513 asm_op op = float_mul_ops[float_mul->op];
514
515 if (op.name)
516 fprintf(fp, "%s", op.name);
517 else
518 fprintf(fp, "op%u", float_mul->op);
519 print_outmod(float_mul->dest_modifier, fp);
520 fprintf(fp, ".s0 ");
521
522 if (float_mul->output_en)
523 print_dest_scalar(float_mul->dest, fp);
524
525 print_source_scalar(float_mul->arg0_source, NULL,
526 float_mul->arg0_absolute,
527 float_mul->arg0_negate, fp);
528
529 if (float_mul->op < 8 && float_mul->op != 0) {
530 fprintf(fp, "<<%u", float_mul->op);
531 }
532
533 if (op.srcs > 1) {
534 fprintf(fp, " ");
535
536 print_source_scalar(float_mul->arg1_source, NULL,
537 float_mul->arg1_absolute,
538 float_mul->arg1_negate, fp);
539 }
540 }
541
542 #define CASE(_name, _srcs) \
543 [ppir_codegen_float_acc_op_##_name] = { \
544 .name = #_name, \
545 .srcs = _srcs \
546 }
547
548 static const asm_op float_acc_ops[] = {
549 CASE(add, 2),
550 CASE(fract, 1),
551 CASE(ne, 2),
552 CASE(gt, 2),
553 CASE(ge, 2),
554 CASE(eq, 2),
555 CASE(floor, 1),
556 CASE(ceil, 1),
557 CASE(min, 2),
558 CASE(max, 2),
559 CASE(dFdx, 2),
560 CASE(dFdy, 2),
561 CASE(sel, 2),
562 CASE(mov, 1),
563 };
564
565 #undef CASE
566
567 static void
print_float_acc(void * code,unsigned offset,FILE * fp)568 print_float_acc(void *code, unsigned offset, FILE *fp)
569 {
570 (void) offset;
571 ppir_codegen_field_float_acc *float_acc = code;
572
573 asm_op op = float_acc_ops[float_acc->op];
574
575 if (op.name)
576 fprintf(fp, "%s", op.name);
577 else
578 fprintf(fp, "op%u", float_acc->op);
579 print_outmod(float_acc->dest_modifier, fp);
580 fprintf(fp, ".s1 ");
581
582 if (float_acc->output_en)
583 print_dest_scalar(float_acc->dest, fp);
584
585 print_source_scalar(float_acc->arg0_source, float_acc->mul_in ? "^s0" : NULL,
586 float_acc->arg0_absolute,
587 float_acc->arg0_negate, fp);
588
589 if (op.srcs > 1) {
590 fprintf(fp, " ");
591 print_source_scalar(float_acc->arg1_source, NULL,
592 float_acc->arg1_absolute,
593 float_acc->arg1_negate, fp);
594 }
595 }
596
597 #define CASE(_name, _srcs) \
598 [ppir_codegen_combine_scalar_op_##_name] = { \
599 .name = #_name, \
600 .srcs = _srcs \
601 }
602
603 static const asm_op combine_ops[] = {
604 CASE(rcp, 1),
605 CASE(mov, 1),
606 CASE(sqrt, 1),
607 CASE(rsqrt, 1),
608 CASE(exp2, 1),
609 CASE(log2, 1),
610 CASE(sin, 1),
611 CASE(cos, 1),
612 CASE(atan, 1),
613 CASE(atan2, 1),
614 };
615
616 #undef CASE
617
618 static void
print_combine(void * code,unsigned offset,FILE * fp)619 print_combine(void *code, unsigned offset, FILE *fp)
620 {
621 (void) offset;
622 ppir_codegen_field_combine *combine = code;
623
624 if (combine->scalar.dest_vec &&
625 combine->scalar.arg1_en) {
626 /* This particular combination can only be valid for scalar * vector
627 * multiplies, and the opcode field is reused for something else.
628 */
629 fprintf(fp, "mul");
630 } else {
631 asm_op op = combine_ops[combine->scalar.op];
632
633 if (op.name)
634 fprintf(fp, "%s", op.name);
635 else
636 fprintf(fp, "op%u", combine->scalar.op);
637 }
638
639 if (!combine->scalar.dest_vec)
640 print_outmod(combine->scalar.dest_modifier, fp);
641 fprintf(fp, ".s2 ");
642
643 if (combine->scalar.dest_vec) {
644 fprintf(fp, "$%u", combine->vector.dest);
645 print_mask(combine->vector.mask, fp);
646 } else {
647 print_dest_scalar(combine->scalar.dest, fp);
648 }
649 fprintf(fp, " ");
650
651 print_source_scalar(combine->scalar.arg0_src, NULL,
652 combine->scalar.arg0_absolute,
653 combine->scalar.arg0_negate, fp);
654 fprintf(fp, " ");
655
656 if (combine->scalar.arg1_en) {
657 if (combine->scalar.dest_vec) {
658 print_vector_source(combine->vector.arg1_source, NULL,
659 combine->vector.arg1_swizzle,
660 false, false, fp);
661 } else {
662 print_source_scalar(combine->scalar.arg1_src, NULL,
663 combine->scalar.arg1_absolute,
664 combine->scalar.arg1_negate, fp);
665 }
666 }
667 }
668
669 static void
print_temp_write(void * code,unsigned offset,FILE * fp)670 print_temp_write(void *code, unsigned offset, FILE *fp)
671 {
672 (void) offset;
673 ppir_codegen_field_temp_write *temp_write = code;
674
675 if (temp_write->fb_read.unknown_0 == 0x7) {
676 if (temp_write->fb_read.source)
677 fprintf(fp, "fb_color");
678 else
679 fprintf(fp, "fb_depth");
680 fprintf(fp, " $%u", temp_write->fb_read.dest);
681
682 return;
683 }
684
685 fprintf(fp, "store.t");
686
687 int16_t index = temp_write->temp_write.index;
688 switch (temp_write->temp_write.alignment) {
689 case 2:
690 fprintf(fp, " %d", index);
691 break;
692 case 1:
693 fprintf(fp, " %d.%s", index / 2, (index & 1) ? "zw" : "xy");
694 break;
695 default:
696 fprintf(fp, " %d.%c", index / 4, "xyzw"[index & 3]);
697 break;
698 }
699
700 if (temp_write->temp_write.offset_en) {
701 fprintf(fp, "+");
702 print_source_scalar(temp_write->temp_write.offset_reg,
703 NULL, false, false, fp);
704 }
705
706 fprintf(fp, " ");
707
708 if (temp_write->temp_write.alignment) {
709 print_reg(temp_write->temp_write.source >> 2, NULL, fp);
710 } else {
711 print_source_scalar(temp_write->temp_write.source, NULL, false, false, fp);
712 }
713 }
714
715 static void
print_branch(void * code,unsigned offset,FILE * fp)716 print_branch(void *code, unsigned offset, FILE *fp)
717 {
718 ppir_codegen_field_branch *branch = code;
719
720 if (branch->discard.word0 == PPIR_CODEGEN_DISCARD_WORD0 &&
721 branch->discard.word1 == PPIR_CODEGEN_DISCARD_WORD1 &&
722 branch->discard.word2 == PPIR_CODEGEN_DISCARD_WORD2) {
723 fprintf(fp, "discard");
724 return;
725 }
726
727 const char* cond[] = {
728 "nv", "lt", "eq", "le",
729 "gt", "ne", "ge", "" ,
730 };
731
732 unsigned cond_mask = 0;
733 cond_mask |= (branch->branch.cond_lt ? 1 : 0);
734 cond_mask |= (branch->branch.cond_eq ? 2 : 0);
735 cond_mask |= (branch->branch.cond_gt ? 4 : 0);
736 fprintf(fp, "branch");
737 if (cond_mask != 0x7) {
738 fprintf(fp, ".%s ", cond[cond_mask]);
739 print_source_scalar(branch->branch.arg0_source, NULL, false, false, fp);
740 fprintf(fp, " ");
741 print_source_scalar(branch->branch.arg1_source, NULL, false, false, fp);
742 }
743
744 fprintf(fp, " %d", branch->branch.target + offset);
745 }
746
747 typedef void (*print_field_func)(void *, unsigned, FILE *);
748
749 static const print_field_func print_field[ppir_codegen_field_shift_count] = {
750 [ppir_codegen_field_shift_varying] = print_varying,
751 [ppir_codegen_field_shift_sampler] = print_sampler,
752 [ppir_codegen_field_shift_uniform] = print_uniform,
753 [ppir_codegen_field_shift_vec4_mul] = print_vec4_mul,
754 [ppir_codegen_field_shift_float_mul] = print_float_mul,
755 [ppir_codegen_field_shift_vec4_acc] = print_vec4_acc,
756 [ppir_codegen_field_shift_float_acc] = print_float_acc,
757 [ppir_codegen_field_shift_combine] = print_combine,
758 [ppir_codegen_field_shift_temp_write] = print_temp_write,
759 [ppir_codegen_field_shift_branch] = print_branch,
760 [ppir_codegen_field_shift_vec4_const_0] = print_const0,
761 [ppir_codegen_field_shift_vec4_const_1] = print_const1,
762 };
763
764 static const int ppir_codegen_field_size[] = {
765 34, 62, 41, 43, 30, 44, 31, 30, 41, 73, 64, 64
766 };
767
768 static void
bitcopy(char * src,char * dst,unsigned bits,unsigned src_offset)769 bitcopy(char *src, char *dst, unsigned bits, unsigned src_offset)
770 {
771 src += src_offset / 8;
772 src_offset %= 8;
773
774 for (int b = bits; b > 0; b -= 8, src++, dst++) {
775 unsigned char out = ((unsigned char) *src) >> src_offset;
776 if (src_offset > 0 && src_offset + b > 8)
777 out |= ((unsigned char) *(src + 1)) << (8 - src_offset);
778 *dst = (char) out;
779 }
780 }
781
782 void
ppir_disassemble_instr(uint32_t * instr,unsigned offset,FILE * fp)783 ppir_disassemble_instr(uint32_t *instr, unsigned offset, FILE *fp)
784 {
785 ppir_codegen_ctrl *ctrl = (ppir_codegen_ctrl *) instr;
786
787 char *instr_code = (char *) (instr + 1);
788 unsigned bit_offset = 0;
789 bool first = true;
790 for (unsigned i = 0; i < ppir_codegen_field_shift_count; i++) {
791 char code[12];
792
793 if (!((ctrl->fields >> i) & 1))
794 continue;
795
796 unsigned bits = ppir_codegen_field_size[i];
797 bitcopy(instr_code, code, bits, bit_offset);
798
799 if (first)
800 first = false;
801 else
802 fprintf(fp, ", ");
803
804 print_field[i](code, offset, fp);
805
806 bit_offset += bits;
807 }
808
809 if (ctrl->sync)
810 fprintf(fp, ", sync");
811 if (ctrl->stop)
812 fprintf(fp, ", stop");
813
814 fprintf(fp, "\n");
815 }
816
817