Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/lima/ir/pp/disasm.c
4574 views
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
38
print_swizzle(uint8_t swizzle)
39
{
40
if (swizzle == 0xE4)
41
return;
42
43
printf(".");
44
for (unsigned i = 0; i < 4; i++, swizzle >>= 2)
45
printf("%c", "xyzw"[swizzle & 3]);
46
}
47
48
static void
49
print_mask(uint8_t mask)
50
{
51
if (mask == 0xF)
52
return;
53
54
printf(".");
55
if (mask & 1) printf("x");
56
if (mask & 2) printf("y");
57
if (mask & 4) printf("z");
58
if (mask & 8) printf("w");
59
}
60
61
static void
62
print_reg(ppir_codegen_vec4_reg reg, const char *special)
63
{
64
if (special) {
65
printf("%s", special);
66
} else {
67
switch (reg)
68
{
69
case ppir_codegen_vec4_reg_constant0:
70
printf("^const0");
71
break;
72
case ppir_codegen_vec4_reg_constant1:
73
printf("^const1");
74
break;
75
case ppir_codegen_vec4_reg_texture:
76
printf("^texture");
77
break;
78
case ppir_codegen_vec4_reg_uniform:
79
printf("^uniform");
80
break;
81
default:
82
printf("$%u", reg);
83
break;
84
}
85
}
86
}
87
88
static void
89
print_vector_source(ppir_codegen_vec4_reg reg, const char *special,
90
uint8_t swizzle, bool abs, bool neg)
91
{
92
if (neg)
93
printf("-");
94
if (abs)
95
printf("abs(");
96
97
print_reg(reg, special);
98
print_swizzle(swizzle);
99
100
if (abs)
101
printf(")");
102
}
103
104
static void
105
print_source_scalar(unsigned reg, const char *special, bool abs, bool neg)
106
{
107
if (neg)
108
printf("-");
109
if (abs)
110
printf("abs(");
111
112
print_reg(reg >> 2, special);
113
if (!special)
114
printf(".%c", "xyzw"[reg & 3]);
115
116
if (abs)
117
printf(")");
118
}
119
120
static void
121
print_varying_source(ppir_codegen_field_varying *varying)
122
{
123
switch (varying->imm.alignment) {
124
case 0:
125
printf("%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
printf("%u.%s", varying->imm.index >> 1, c[varying->imm.index & 1]);
131
break;
132
}
133
default:
134
printf("%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
printf("+");
142
print_source_scalar(reg, NULL, false, false);
143
}
144
}
145
146
static void
147
print_outmod(ppir_codegen_outmod modifier)
148
{
149
switch (modifier)
150
{
151
case ppir_codegen_outmod_clamp_fraction:
152
printf(".sat");
153
break;
154
case ppir_codegen_outmod_clamp_positive:
155
printf(".pos");
156
break;
157
case ppir_codegen_outmod_round:
158
printf(".int");
159
break;
160
default:
161
break;
162
}
163
}
164
165
static void
166
print_dest_scalar(unsigned reg)
167
{
168
printf("$%u", reg >> 2);
169
printf(".%c ", "xyzw"[reg & 3]);
170
}
171
172
static void
173
print_const(unsigned const_num, uint16_t *val)
174
{
175
printf("const%u", const_num);
176
for (unsigned i = 0; i < 4; i++)
177
printf(" %f", _mesa_half_to_float(val[i]));
178
}
179
180
static void
181
print_const0(void *code, unsigned offset)
182
{
183
(void) offset;
184
185
print_const(0, code);
186
}
187
188
static void
189
print_const1(void *code, unsigned offset)
190
{
191
(void) offset;
192
193
print_const(1, code);
194
}
195
196
static void
197
print_varying(void *code, unsigned offset)
198
{
199
(void) offset;
200
ppir_codegen_field_varying *varying = code;
201
202
printf("load");
203
204
bool perspective = varying->imm.source_type < 2 && varying->imm.perspective;
205
if (perspective)
206
{
207
printf(".perspective");
208
switch (varying->imm.perspective)
209
{
210
case 2:
211
printf(".z");
212
break;
213
case 3:
214
printf(".w");
215
break;
216
default:
217
printf(".unknown");
218
break;
219
}
220
}
221
222
printf(".v ");
223
224
switch (varying->imm.dest)
225
{
226
case ppir_codegen_vec4_reg_discard:
227
printf("^discard");
228
break;
229
default:
230
printf("$%u", varying->imm.dest);
231
break;
232
}
233
print_mask(varying->imm.mask);
234
printf(" ");
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);
240
break;
241
case 2:
242
switch (varying->imm.perspective) {
243
case 0:
244
printf("cube(");
245
print_varying_source(varying);
246
printf(")");
247
break;
248
case 1:
249
printf("cube(");
250
print_vector_source(varying->reg.source, NULL, varying->reg.swizzle,
251
varying->reg.absolute, varying->reg.negate);
252
printf(")");
253
break;
254
case 2:
255
printf("normalize(");
256
print_vector_source(varying->reg.source, NULL, varying->reg.swizzle,
257
varying->reg.absolute, varying->reg.negate);
258
printf(")");
259
break;
260
default:
261
printf("gl_FragCoord");
262
break;
263
}
264
break;
265
case 3:
266
if (varying->imm.perspective)
267
printf("gl_FrontFacing");
268
else
269
printf("gl_PointCoord");
270
break;
271
default:
272
print_varying_source(varying);
273
break;
274
}
275
}
276
277
static void
278
print_sampler(void *code, unsigned offset)
279
{
280
(void) offset;
281
ppir_codegen_field_sampler *sampler = code;
282
283
printf("texld");
284
if (sampler->lod_bias_en)
285
printf(".b");
286
287
switch (sampler->type) {
288
case ppir_codegen_sampler_type_2d:
289
printf(".2d");
290
break;
291
case ppir_codegen_sampler_type_cube:
292
printf(".cube");
293
break;
294
default:
295
printf("_t%u", sampler->type);
296
break;
297
}
298
299
printf(" %u", sampler->index);
300
301
if (sampler->offset_en)
302
{
303
printf("+");
304
print_source_scalar(sampler->index_offset, NULL, false, false);
305
}
306
307
if (sampler->lod_bias_en)
308
{
309
printf(" ");
310
print_source_scalar(sampler->lod_bias, NULL, false, false);
311
}
312
}
313
314
static void
315
print_uniform(void *code, unsigned offset)
316
{
317
(void) offset;
318
ppir_codegen_field_uniform *uniform = code;
319
320
printf("load.");
321
322
switch (uniform->source) {
323
case ppir_codegen_uniform_src_uniform:
324
printf("u");
325
break;
326
case ppir_codegen_uniform_src_temporary:
327
printf("t");
328
break;
329
default:
330
printf(".u%u", uniform->source);
331
break;
332
}
333
334
int16_t index = uniform->index;
335
switch (uniform->alignment) {
336
case 2:
337
printf(" %d", index);
338
break;
339
case 1:
340
printf(" %d.%s", index / 2, (index & 1) ? "zw" : "xy");
341
break;
342
default:
343
printf(" %d.%c", index / 4, "xyzw"[index & 3]);
344
break;
345
}
346
347
if (uniform->offset_en) {
348
printf("+");
349
print_source_scalar(uniform->offset_reg, NULL, false, false);
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
380
print_vec4_mul(void *code, unsigned offset)
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
printf("%s", op.name);
389
else
390
printf("op%u", vec4_mul->op);
391
print_outmod(vec4_mul->dest_modifier);
392
printf(".v0 ");
393
394
if (vec4_mul->mask) {
395
printf("$%u", vec4_mul->dest);
396
print_mask(vec4_mul->mask);
397
printf(" ");
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);
404
405
if (vec4_mul->op < 8 && vec4_mul->op != 0) {
406
printf("<<%u", vec4_mul->op);
407
}
408
409
printf(" ");
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);
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
447
print_vec4_acc(void *code, unsigned offset)
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
printf("%s", op.name);
456
else
457
printf("op%u", vec4_acc->op);
458
print_outmod(vec4_acc->dest_modifier);
459
printf(".v1 ");
460
461
if (vec4_acc->mask) {
462
printf("$%u", vec4_acc->dest);
463
print_mask(vec4_acc->mask);
464
printf(" ");
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);
471
472
if (op.srcs > 1) {
473
printf(" ");
474
print_vector_source(vec4_acc->arg1_source, NULL,
475
vec4_acc->arg1_swizzle,
476
vec4_acc->arg1_absolute,
477
vec4_acc->arg1_negate);
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
508
print_float_mul(void *code, unsigned offset)
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
printf("%s", op.name);
517
else
518
printf("op%u", float_mul->op);
519
print_outmod(float_mul->dest_modifier);
520
printf(".s0 ");
521
522
if (float_mul->output_en)
523
print_dest_scalar(float_mul->dest);
524
525
print_source_scalar(float_mul->arg0_source, NULL,
526
float_mul->arg0_absolute,
527
float_mul->arg0_negate);
528
529
if (float_mul->op < 8 && float_mul->op != 0) {
530
printf("<<%u", float_mul->op);
531
}
532
533
if (op.srcs > 1) {
534
printf(" ");
535
536
print_source_scalar(float_mul->arg1_source, NULL,
537
float_mul->arg1_absolute,
538
float_mul->arg1_negate);
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
568
print_float_acc(void *code, unsigned offset)
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
printf("%s", op.name);
577
else
578
printf("op%u", float_acc->op);
579
print_outmod(float_acc->dest_modifier);
580
printf(".s1 ");
581
582
if (float_acc->output_en)
583
print_dest_scalar(float_acc->dest);
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);
588
589
if (op.srcs > 1) {
590
printf(" ");
591
print_source_scalar(float_acc->arg1_source, NULL,
592
float_acc->arg1_absolute,
593
float_acc->arg1_negate);
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
619
print_combine(void *code, unsigned offset)
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
printf("mul");
630
} else {
631
asm_op op = combine_ops[combine->scalar.op];
632
633
if (op.name)
634
printf("%s", op.name);
635
else
636
printf("op%u", combine->scalar.op);
637
}
638
639
if (!combine->scalar.dest_vec)
640
print_outmod(combine->scalar.dest_modifier);
641
printf(".s2 ");
642
643
if (combine->scalar.dest_vec) {
644
printf("$%u", combine->vector.dest);
645
print_mask(combine->vector.mask);
646
} else {
647
print_dest_scalar(combine->scalar.dest);
648
}
649
printf(" ");
650
651
print_source_scalar(combine->scalar.arg0_src, NULL,
652
combine->scalar.arg0_absolute,
653
combine->scalar.arg0_negate);
654
printf(" ");
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);
661
} else {
662
print_source_scalar(combine->scalar.arg1_src, NULL,
663
combine->scalar.arg1_absolute,
664
combine->scalar.arg1_negate);
665
}
666
}
667
}
668
669
static void
670
print_temp_write(void *code, unsigned offset)
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
printf("fb_color");
678
else
679
printf("fb_depth");
680
printf(" $%u", temp_write->fb_read.dest);
681
682
return;
683
}
684
685
printf("store.t");
686
687
int16_t index = temp_write->temp_write.index;
688
switch (temp_write->temp_write.alignment) {
689
case 2:
690
printf(" %d", index);
691
break;
692
case 1:
693
printf(" %d.%s", index / 2, (index & 1) ? "zw" : "xy");
694
break;
695
default:
696
printf(" %d.%c", index / 4, "xyzw"[index & 3]);
697
break;
698
}
699
700
if (temp_write->temp_write.offset_en) {
701
printf("+");
702
print_source_scalar(temp_write->temp_write.offset_reg,
703
NULL, false, false);
704
}
705
706
printf(" ");
707
708
if (temp_write->temp_write.alignment) {
709
print_reg(temp_write->temp_write.source >> 2, NULL);
710
} else {
711
print_source_scalar(temp_write->temp_write.source, NULL, false, false);
712
}
713
}
714
715
static void
716
print_branch(void *code, unsigned offset)
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
printf("discard");
724
return;
725
}
726
727
728
const char* cond[] = {
729
"nv", "lt", "eq", "le",
730
"gt", "ne", "ge", "" ,
731
};
732
733
unsigned cond_mask = 0;
734
cond_mask |= (branch->branch.cond_lt ? 1 : 0);
735
cond_mask |= (branch->branch.cond_eq ? 2 : 0);
736
cond_mask |= (branch->branch.cond_gt ? 4 : 0);
737
printf("branch");
738
if (cond_mask != 0x7) {
739
printf(".%s ", cond[cond_mask]);
740
print_source_scalar(branch->branch.arg0_source, NULL, false, false);
741
printf(" ");
742
print_source_scalar(branch->branch.arg1_source, NULL, false, false);
743
}
744
745
printf(" %d", branch->branch.target + offset);
746
}
747
748
typedef void (*print_field_func)(void *, unsigned);
749
750
static const print_field_func print_field[ppir_codegen_field_shift_count] = {
751
[ppir_codegen_field_shift_varying] = print_varying,
752
[ppir_codegen_field_shift_sampler] = print_sampler,
753
[ppir_codegen_field_shift_uniform] = print_uniform,
754
[ppir_codegen_field_shift_vec4_mul] = print_vec4_mul,
755
[ppir_codegen_field_shift_float_mul] = print_float_mul,
756
[ppir_codegen_field_shift_vec4_acc] = print_vec4_acc,
757
[ppir_codegen_field_shift_float_acc] = print_float_acc,
758
[ppir_codegen_field_shift_combine] = print_combine,
759
[ppir_codegen_field_shift_temp_write] = print_temp_write,
760
[ppir_codegen_field_shift_branch] = print_branch,
761
[ppir_codegen_field_shift_vec4_const_0] = print_const0,
762
[ppir_codegen_field_shift_vec4_const_1] = print_const1,
763
};
764
765
static const int ppir_codegen_field_size[] = {
766
34, 62, 41, 43, 30, 44, 31, 30, 41, 73, 64, 64
767
};
768
769
static void
770
bitcopy(char *src, char *dst, unsigned bits, unsigned src_offset)
771
{
772
src += src_offset / 8;
773
src_offset %= 8;
774
775
for (int b = bits; b > 0; b -= 8, src++, dst++) {
776
unsigned char out = ((unsigned char) *src) >> src_offset;
777
if (src_offset > 0 && src_offset + b > 8)
778
out |= ((unsigned char) *(src + 1)) << (8 - src_offset);
779
*dst = (char) out;
780
}
781
}
782
783
void
784
ppir_disassemble_instr(uint32_t *instr, unsigned offset)
785
{
786
ppir_codegen_ctrl *ctrl = (ppir_codegen_ctrl *) instr;
787
788
char *instr_code = (char *) (instr + 1);
789
unsigned bit_offset = 0;
790
bool first = true;
791
for (unsigned i = 0; i < ppir_codegen_field_shift_count; i++) {
792
char code[12];
793
794
if (!((ctrl->fields >> i) & 1))
795
continue;
796
797
unsigned bits = ppir_codegen_field_size[i];
798
bitcopy(instr_code, code, bits, bit_offset);
799
800
if (first)
801
first = false;
802
else
803
printf(", ");
804
805
print_field[i](code, offset);
806
807
bit_offset += bits;
808
}
809
810
if (ctrl->sync)
811
printf(", sync");
812
if (ctrl->stop)
813
printf(", stop");
814
815
printf("\n");
816
}
817
818
819