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_generic:
289 break;
290 case ppir_codegen_sampler_type_cube:
291 fprintf(fp, ".cube");
292 break;
293 default:
294 fprintf(fp, "_t%u", sampler->type);
295 break;
296 }
297
298 fprintf(fp, " %u", sampler->index);
299
300 if (sampler->offset_en)
301 {
302 fprintf(fp, "+");
303 print_source_scalar(sampler->index_offset, NULL, false, false, fp);
304 }
305
306 if (sampler->lod_bias_en)
307 {
308 fprintf(fp, " ");
309 print_source_scalar(sampler->lod_bias, NULL, false, false, fp);
310 }
311 }
312
313 static void
print_uniform(void * code,unsigned offset,FILE * fp)314 print_uniform(void *code, unsigned offset, FILE *fp)
315 {
316 (void) offset;
317 ppir_codegen_field_uniform *uniform = code;
318
319 fprintf(fp, "load.");
320
321 switch (uniform->source) {
322 case ppir_codegen_uniform_src_uniform:
323 fprintf(fp, "u");
324 break;
325 case ppir_codegen_uniform_src_temporary:
326 fprintf(fp, "t");
327 break;
328 default:
329 fprintf(fp, ".u%u", uniform->source);
330 break;
331 }
332
333 int16_t index = uniform->index;
334 switch (uniform->alignment) {
335 case 2:
336 fprintf(fp, " %d", index);
337 break;
338 case 1:
339 fprintf(fp, " %d.%s", index / 2, (index & 1) ? "zw" : "xy");
340 break;
341 default:
342 fprintf(fp, " %d.%c", index / 4, "xyzw"[index & 3]);
343 break;
344 }
345
346 if (uniform->offset_en) {
347 fprintf(fp, "+");
348 print_source_scalar(uniform->offset_reg, NULL, false, false, fp);
349 }
350 }
351
352 #define CASE(_name, _srcs) \
353 [ppir_codegen_vec4_mul_op_##_name] = { \
354 .name = #_name, \
355 .srcs = _srcs \
356 }
357
358 static const asm_op vec4_mul_ops[] = {
359 [0 ... 7] = {
360 .name = "mul",
361 .srcs = 2
362 },
363 CASE(not, 1),
364 CASE(and, 2),
365 CASE(or, 2),
366 CASE(xor, 2),
367 CASE(ne, 2),
368 CASE(gt, 2),
369 CASE(ge, 2),
370 CASE(eq, 2),
371 CASE(min, 2),
372 CASE(max, 2),
373 CASE(mov, 1),
374 };
375
376 #undef CASE
377
378 static void
print_vec4_mul(void * code,unsigned offset,FILE * fp)379 print_vec4_mul(void *code, unsigned offset, FILE *fp)
380 {
381 (void) offset;
382 ppir_codegen_field_vec4_mul *vec4_mul = code;
383
384 asm_op op = vec4_mul_ops[vec4_mul->op];
385
386 if (op.name)
387 fprintf(fp, "%s", op.name);
388 else
389 fprintf(fp, "op%u", vec4_mul->op);
390 print_outmod(vec4_mul->dest_modifier, fp);
391 fprintf(fp, ".v0 ");
392
393 if (vec4_mul->mask) {
394 fprintf(fp, "$%u", vec4_mul->dest);
395 print_mask(vec4_mul->mask, fp);
396 fprintf(fp, " ");
397 }
398
399 print_vector_source(vec4_mul->arg0_source, NULL,
400 vec4_mul->arg0_swizzle,
401 vec4_mul->arg0_absolute,
402 vec4_mul->arg0_negate, fp);
403
404 if (vec4_mul->op < 8 && vec4_mul->op != 0) {
405 fprintf(fp, "<<%u", vec4_mul->op);
406 }
407
408 fprintf(fp, " ");
409
410 if (op.srcs > 1) {
411 print_vector_source(vec4_mul->arg1_source, NULL,
412 vec4_mul->arg1_swizzle,
413 vec4_mul->arg1_absolute,
414 vec4_mul->arg1_negate, fp);
415 }
416 }
417
418 #define CASE(_name, _srcs) \
419 [ppir_codegen_vec4_acc_op_##_name] = { \
420 .name = #_name, \
421 .srcs = _srcs \
422 }
423
424 static const asm_op vec4_acc_ops[] = {
425 CASE(add, 2),
426 CASE(fract, 1),
427 CASE(ne, 2),
428 CASE(gt, 2),
429 CASE(ge, 2),
430 CASE(eq, 2),
431 CASE(floor, 1),
432 CASE(ceil, 1),
433 CASE(min, 2),
434 CASE(max, 2),
435 CASE(sum3, 1),
436 CASE(sum4, 1),
437 CASE(dFdx, 2),
438 CASE(dFdy, 2),
439 CASE(sel, 2),
440 CASE(mov, 1),
441 };
442
443 #undef CASE
444
445 static void
print_vec4_acc(void * code,unsigned offset,FILE * fp)446 print_vec4_acc(void *code, unsigned offset, FILE *fp)
447 {
448 (void) offset;
449 ppir_codegen_field_vec4_acc *vec4_acc = code;
450
451 asm_op op = vec4_acc_ops[vec4_acc->op];
452
453 if (op.name)
454 fprintf(fp, "%s", op.name);
455 else
456 fprintf(fp, "op%u", vec4_acc->op);
457 print_outmod(vec4_acc->dest_modifier, fp);
458 fprintf(fp, ".v1 ");
459
460 if (vec4_acc->mask) {
461 fprintf(fp, "$%u", vec4_acc->dest);
462 print_mask(vec4_acc->mask, fp);
463 fprintf(fp, " ");
464 }
465
466 print_vector_source(vec4_acc->arg0_source, vec4_acc->mul_in ? "^v0" : NULL,
467 vec4_acc->arg0_swizzle,
468 vec4_acc->arg0_absolute,
469 vec4_acc->arg0_negate, fp);
470
471 if (op.srcs > 1) {
472 fprintf(fp, " ");
473 print_vector_source(vec4_acc->arg1_source, NULL,
474 vec4_acc->arg1_swizzle,
475 vec4_acc->arg1_absolute,
476 vec4_acc->arg1_negate, fp);
477 }
478 }
479
480 #define CASE(_name, _srcs) \
481 [ppir_codegen_float_mul_op_##_name] = { \
482 .name = #_name, \
483 .srcs = _srcs \
484 }
485
486 static const asm_op float_mul_ops[] = {
487 [0 ... 7] = {
488 .name = "mul",
489 .srcs = 2
490 },
491 CASE(not, 1),
492 CASE(and, 2),
493 CASE(or, 2),
494 CASE(xor, 2),
495 CASE(ne, 2),
496 CASE(gt, 2),
497 CASE(ge, 2),
498 CASE(eq, 2),
499 CASE(min, 2),
500 CASE(max, 2),
501 CASE(mov, 1),
502 };
503
504 #undef CASE
505
506 static void
print_float_mul(void * code,unsigned offset,FILE * fp)507 print_float_mul(void *code, unsigned offset, FILE *fp)
508 {
509 (void) offset;
510 ppir_codegen_field_float_mul *float_mul = code;
511
512 asm_op op = float_mul_ops[float_mul->op];
513
514 if (op.name)
515 fprintf(fp, "%s", op.name);
516 else
517 fprintf(fp, "op%u", float_mul->op);
518 print_outmod(float_mul->dest_modifier, fp);
519 fprintf(fp, ".s0 ");
520
521 if (float_mul->output_en)
522 print_dest_scalar(float_mul->dest, fp);
523
524 print_source_scalar(float_mul->arg0_source, NULL,
525 float_mul->arg0_absolute,
526 float_mul->arg0_negate, fp);
527
528 if (float_mul->op < 8 && float_mul->op != 0) {
529 fprintf(fp, "<<%u", float_mul->op);
530 }
531
532 if (op.srcs > 1) {
533 fprintf(fp, " ");
534
535 print_source_scalar(float_mul->arg1_source, NULL,
536 float_mul->arg1_absolute,
537 float_mul->arg1_negate, fp);
538 }
539 }
540
541 #define CASE(_name, _srcs) \
542 [ppir_codegen_float_acc_op_##_name] = { \
543 .name = #_name, \
544 .srcs = _srcs \
545 }
546
547 static const asm_op float_acc_ops[] = {
548 CASE(add, 2),
549 CASE(fract, 1),
550 CASE(ne, 2),
551 CASE(gt, 2),
552 CASE(ge, 2),
553 CASE(eq, 2),
554 CASE(floor, 1),
555 CASE(ceil, 1),
556 CASE(min, 2),
557 CASE(max, 2),
558 CASE(dFdx, 2),
559 CASE(dFdy, 2),
560 CASE(sel, 2),
561 CASE(mov, 1),
562 };
563
564 #undef CASE
565
566 static void
print_float_acc(void * code,unsigned offset,FILE * fp)567 print_float_acc(void *code, unsigned offset, FILE *fp)
568 {
569 (void) offset;
570 ppir_codegen_field_float_acc *float_acc = code;
571
572 asm_op op = float_acc_ops[float_acc->op];
573
574 if (op.name)
575 fprintf(fp, "%s", op.name);
576 else
577 fprintf(fp, "op%u", float_acc->op);
578 print_outmod(float_acc->dest_modifier, fp);
579 fprintf(fp, ".s1 ");
580
581 if (float_acc->output_en)
582 print_dest_scalar(float_acc->dest, fp);
583
584 print_source_scalar(float_acc->arg0_source, float_acc->mul_in ? "^s0" : NULL,
585 float_acc->arg0_absolute,
586 float_acc->arg0_negate, fp);
587
588 if (op.srcs > 1) {
589 fprintf(fp, " ");
590 print_source_scalar(float_acc->arg1_source, NULL,
591 float_acc->arg1_absolute,
592 float_acc->arg1_negate, fp);
593 }
594 }
595
596 #define CASE(_name, _srcs) \
597 [ppir_codegen_combine_scalar_op_##_name] = { \
598 .name = #_name, \
599 .srcs = _srcs \
600 }
601
602 static const asm_op combine_ops[] = {
603 CASE(rcp, 1),
604 CASE(mov, 1),
605 CASE(sqrt, 1),
606 CASE(rsqrt, 1),
607 CASE(exp2, 1),
608 CASE(log2, 1),
609 CASE(sin, 1),
610 CASE(cos, 1),
611 CASE(atan, 1),
612 CASE(atan2, 1),
613 };
614
615 #undef CASE
616
617 static void
print_combine(void * code,unsigned offset,FILE * fp)618 print_combine(void *code, unsigned offset, FILE *fp)
619 {
620 (void) offset;
621 ppir_codegen_field_combine *combine = code;
622
623 if (combine->scalar.dest_vec &&
624 combine->scalar.arg1_en) {
625 /* This particular combination can only be valid for scalar * vector
626 * multiplies, and the opcode field is reused for something else.
627 */
628 fprintf(fp, "mul");
629 } else {
630 asm_op op = combine_ops[combine->scalar.op];
631
632 if (op.name)
633 fprintf(fp, "%s", op.name);
634 else
635 fprintf(fp, "op%u", combine->scalar.op);
636 }
637
638 if (!combine->scalar.dest_vec)
639 print_outmod(combine->scalar.dest_modifier, fp);
640 fprintf(fp, ".s2 ");
641
642 if (combine->scalar.dest_vec) {
643 fprintf(fp, "$%u", combine->vector.dest);
644 print_mask(combine->vector.mask, fp);
645 } else {
646 print_dest_scalar(combine->scalar.dest, fp);
647 }
648 fprintf(fp, " ");
649
650 print_source_scalar(combine->scalar.arg0_src, NULL,
651 combine->scalar.arg0_absolute,
652 combine->scalar.arg0_negate, fp);
653 fprintf(fp, " ");
654
655 if (combine->scalar.arg1_en) {
656 if (combine->scalar.dest_vec) {
657 print_vector_source(combine->vector.arg1_source, NULL,
658 combine->vector.arg1_swizzle,
659 false, false, fp);
660 } else {
661 print_source_scalar(combine->scalar.arg1_src, NULL,
662 combine->scalar.arg1_absolute,
663 combine->scalar.arg1_negate, fp);
664 }
665 }
666 }
667
668 static void
print_temp_write(void * code,unsigned offset,FILE * fp)669 print_temp_write(void *code, unsigned offset, FILE *fp)
670 {
671 (void) offset;
672 ppir_codegen_field_temp_write *temp_write = code;
673
674 if (temp_write->fb_read.unknown_0 == 0x7) {
675 if (temp_write->fb_read.source)
676 fprintf(fp, "fb_color");
677 else
678 fprintf(fp, "fb_depth");
679 fprintf(fp, " $%u", temp_write->fb_read.dest);
680
681 return;
682 }
683
684 fprintf(fp, "store.t");
685
686 int16_t index = temp_write->temp_write.index;
687 switch (temp_write->temp_write.alignment) {
688 case 2:
689 fprintf(fp, " %d", index);
690 break;
691 case 1:
692 fprintf(fp, " %d.%s", index / 2, (index & 1) ? "zw" : "xy");
693 break;
694 default:
695 fprintf(fp, " %d.%c", index / 4, "xyzw"[index & 3]);
696 break;
697 }
698
699 if (temp_write->temp_write.offset_en) {
700 fprintf(fp, "+");
701 print_source_scalar(temp_write->temp_write.offset_reg,
702 NULL, false, false, fp);
703 }
704
705 fprintf(fp, " ");
706
707 if (temp_write->temp_write.alignment) {
708 print_reg(temp_write->temp_write.source >> 2, NULL, fp);
709 } else {
710 print_source_scalar(temp_write->temp_write.source, NULL, false, false, fp);
711 }
712 }
713
714 static void
print_branch(void * code,unsigned offset,FILE * fp)715 print_branch(void *code, unsigned offset, FILE *fp)
716 {
717 ppir_codegen_field_branch *branch = code;
718
719 if (branch->discard.word0 == PPIR_CODEGEN_DISCARD_WORD0 &&
720 branch->discard.word1 == PPIR_CODEGEN_DISCARD_WORD1 &&
721 branch->discard.word2 == PPIR_CODEGEN_DISCARD_WORD2) {
722 fprintf(fp, "discard");
723 return;
724 }
725
726 const char* cond[] = {
727 "nv", "lt", "eq", "le",
728 "gt", "ne", "ge", "" ,
729 };
730
731 unsigned cond_mask = 0;
732 cond_mask |= (branch->branch.cond_lt ? 1 : 0);
733 cond_mask |= (branch->branch.cond_eq ? 2 : 0);
734 cond_mask |= (branch->branch.cond_gt ? 4 : 0);
735 fprintf(fp, "branch");
736 if (cond_mask != 0x7) {
737 fprintf(fp, ".%s ", cond[cond_mask]);
738 print_source_scalar(branch->branch.arg0_source, NULL, false, false, fp);
739 fprintf(fp, " ");
740 print_source_scalar(branch->branch.arg1_source, NULL, false, false, fp);
741 }
742
743 fprintf(fp, " %d", branch->branch.target + offset);
744 }
745
746 typedef void (*print_field_func)(void *, unsigned, FILE *);
747
748 static const print_field_func print_field[ppir_codegen_field_shift_count] = {
749 [ppir_codegen_field_shift_varying] = print_varying,
750 [ppir_codegen_field_shift_sampler] = print_sampler,
751 [ppir_codegen_field_shift_uniform] = print_uniform,
752 [ppir_codegen_field_shift_vec4_mul] = print_vec4_mul,
753 [ppir_codegen_field_shift_float_mul] = print_float_mul,
754 [ppir_codegen_field_shift_vec4_acc] = print_vec4_acc,
755 [ppir_codegen_field_shift_float_acc] = print_float_acc,
756 [ppir_codegen_field_shift_combine] = print_combine,
757 [ppir_codegen_field_shift_temp_write] = print_temp_write,
758 [ppir_codegen_field_shift_branch] = print_branch,
759 [ppir_codegen_field_shift_vec4_const_0] = print_const0,
760 [ppir_codegen_field_shift_vec4_const_1] = print_const1,
761 };
762
763 static const int ppir_codegen_field_size[] = {
764 34, 62, 41, 43, 30, 44, 31, 30, 41, 73, 64, 64
765 };
766
767 static void
bitcopy(char * src,char * dst,unsigned bits,unsigned src_offset)768 bitcopy(char *src, char *dst, unsigned bits, unsigned src_offset)
769 {
770 src += src_offset / 8;
771 src_offset %= 8;
772
773 for (int b = bits; b > 0; b -= 8, src++, dst++) {
774 unsigned char out = ((unsigned char) *src) >> src_offset;
775 if (src_offset > 0 && src_offset + b > 8)
776 out |= ((unsigned char) *(src + 1)) << (8 - src_offset);
777 *dst = (char) out;
778 }
779 }
780
781 void
ppir_disassemble_instr(uint32_t * instr,unsigned offset,FILE * fp)782 ppir_disassemble_instr(uint32_t *instr, unsigned offset, FILE *fp)
783 {
784 ppir_codegen_ctrl *ctrl = (ppir_codegen_ctrl *) instr;
785
786 char *instr_code = (char *) (instr + 1);
787 unsigned bit_offset = 0;
788 bool first = true;
789 for (unsigned i = 0; i < ppir_codegen_field_shift_count; i++) {
790 char code[12];
791
792 if (!((ctrl->fields >> i) & 1))
793 continue;
794
795 unsigned bits = ppir_codegen_field_size[i];
796 bitcopy(instr_code, code, bits, bit_offset);
797
798 if (first)
799 first = false;
800 else
801 fprintf(fp, ", ");
802
803 print_field[i](code, offset, fp);
804
805 bit_offset += bits;
806 }
807
808 if (ctrl->sync)
809 fprintf(fp, ", sync");
810 if (ctrl->stop)
811 fprintf(fp, ", stop");
812
813 fprintf(fp, "\n");
814 }
815
816