• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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