Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/lima/ir/gp/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 "gpir.h"
28
#include "codegen.h"
29
30
typedef enum {
31
unit_acc_0,
32
unit_acc_1,
33
unit_mul_0,
34
unit_mul_1,
35
unit_pass,
36
unit_complex,
37
num_units
38
} gp_unit;
39
40
static const gpir_codegen_store_src gp_unit_to_store_src[num_units] = {
41
[unit_acc_0] = gpir_codegen_store_src_acc_0,
42
[unit_acc_1] = gpir_codegen_store_src_acc_1,
43
[unit_mul_0] = gpir_codegen_store_src_mul_0,
44
[unit_mul_1] = gpir_codegen_store_src_mul_1,
45
[unit_pass] = gpir_codegen_store_src_pass,
46
[unit_complex] = gpir_codegen_store_src_complex,
47
};
48
49
static void
50
print_dest(gpir_codegen_instr *instr, gp_unit unit, unsigned cur_dest_index)
51
{
52
printf("^%u", cur_dest_index + unit);
53
54
gpir_codegen_store_src src = gp_unit_to_store_src[unit];
55
56
if (instr->store0_src_x == src ||
57
instr->store0_src_y == src) {
58
if (instr->store0_temporary) {
59
/* Temporary stores ignore the address, and always use whatever's
60
* stored in address register 0.
61
*/
62
printf("/t[addr0]");
63
} else {
64
if (instr->store0_varying)
65
printf("/v");
66
else
67
printf("/$");
68
printf("%u", instr->store0_addr);
69
}
70
71
printf(".");
72
if (instr->store0_src_x == src)
73
printf("x");
74
if (instr->store0_src_y == src)
75
printf("y");
76
}
77
78
if (instr->store1_src_z == src ||
79
instr->store1_src_w == src) {
80
if (instr->store1_temporary) {
81
printf("/t[addr0]");
82
} else {
83
if (instr->store1_varying)
84
printf("/v");
85
else
86
printf("/$");
87
printf("%u", instr->store1_addr);
88
}
89
90
printf(".");
91
if (instr->store1_src_z == src)
92
printf("z");
93
if (instr->store1_src_w == src)
94
printf("w");
95
}
96
97
if (unit == unit_complex) {
98
switch (instr->complex_op) {
99
case gpir_codegen_complex_op_temp_store_addr:
100
printf("/addr0");
101
break;
102
case gpir_codegen_complex_op_temp_load_addr_0:
103
printf("/addr1");
104
break;
105
case gpir_codegen_complex_op_temp_load_addr_1:
106
printf("/addr2");
107
break;
108
case gpir_codegen_complex_op_temp_load_addr_2:
109
printf("/addr3");
110
break;
111
default:
112
break;
113
}
114
}
115
}
116
117
static void
118
print_src(gpir_codegen_src src, gp_unit unit, unsigned unit_src_num,
119
gpir_codegen_instr *instr, gpir_codegen_instr *prev_instr,
120
unsigned cur_dest_index)
121
{
122
switch (src) {
123
case gpir_codegen_src_attrib_x:
124
case gpir_codegen_src_attrib_y:
125
case gpir_codegen_src_attrib_z:
126
case gpir_codegen_src_attrib_w:
127
printf("%c%d.%c", instr->register0_attribute ? 'a' : '$',
128
instr->register0_addr, "xyzw"[src - gpir_codegen_src_attrib_x]);
129
break;
130
131
case gpir_codegen_src_register_x:
132
case gpir_codegen_src_register_y:
133
case gpir_codegen_src_register_z:
134
case gpir_codegen_src_register_w:
135
printf("$%d.%c", instr->register1_addr,
136
"xyzw"[src - gpir_codegen_src_register_x]);
137
break;
138
139
case gpir_codegen_src_unknown_0:
140
case gpir_codegen_src_unknown_1:
141
case gpir_codegen_src_unknown_2:
142
case gpir_codegen_src_unknown_3:
143
printf("unknown%d", src - gpir_codegen_src_unknown_0);
144
break;
145
146
case gpir_codegen_src_load_x:
147
case gpir_codegen_src_load_y:
148
case gpir_codegen_src_load_z:
149
case gpir_codegen_src_load_w:
150
printf("t[%d", instr->load_addr);
151
switch (instr->load_offset) {
152
case gpir_codegen_load_off_ld_addr_0:
153
printf("+addr1");
154
break;
155
case gpir_codegen_load_off_ld_addr_1:
156
printf("+addr2");
157
break;
158
case gpir_codegen_load_off_ld_addr_2:
159
printf("+addr3");
160
break;
161
case gpir_codegen_load_off_none:
162
break;
163
default:
164
printf("+unk%d", instr->load_offset);
165
}
166
printf("].%c", "xyzw"[src - gpir_codegen_src_load_x]);
167
break;
168
169
case gpir_codegen_src_p1_acc_0:
170
printf("^%d", cur_dest_index - 1 * num_units + unit_acc_0);
171
break;
172
173
case gpir_codegen_src_p1_acc_1:
174
printf("^%d", cur_dest_index - 1 * num_units + unit_acc_1);
175
break;
176
177
case gpir_codegen_src_p1_mul_0:
178
printf("^%d", cur_dest_index - 1 * num_units + unit_mul_0);
179
break;
180
181
case gpir_codegen_src_p1_mul_1:
182
printf("^%d", cur_dest_index - 1 * num_units + unit_mul_1);
183
break;
184
185
case gpir_codegen_src_p1_pass:
186
printf("^%d", cur_dest_index - 1 * num_units + unit_pass);
187
break;
188
189
case gpir_codegen_src_unused:
190
printf("unused");
191
break;
192
193
case gpir_codegen_src_p1_complex: /* Also ident */
194
switch (unit) {
195
case unit_acc_0:
196
case unit_acc_1:
197
if (unit_src_num == 1) {
198
printf("0");
199
return;
200
}
201
break;
202
case unit_mul_0:
203
case unit_mul_1:
204
if (unit_src_num == 1) {
205
printf("1");
206
return;
207
}
208
break;
209
default:
210
break;
211
}
212
printf("^%d", cur_dest_index - 1 * num_units + unit_complex);
213
break;
214
215
case gpir_codegen_src_p2_pass:
216
printf("^%d", cur_dest_index - 2 * num_units + unit_pass);
217
break;
218
219
case gpir_codegen_src_p2_acc_0:
220
printf("^%d", cur_dest_index - 2 * num_units + unit_acc_0);
221
break;
222
223
case gpir_codegen_src_p2_acc_1:
224
printf("^%d", cur_dest_index - 2 * num_units + unit_acc_1);
225
break;
226
227
case gpir_codegen_src_p2_mul_0:
228
printf("^%d", cur_dest_index - 2 * num_units + unit_mul_0);
229
break;
230
231
case gpir_codegen_src_p2_mul_1:
232
printf("^%d", cur_dest_index - 2 * num_units + unit_mul_1);
233
break;
234
235
case gpir_codegen_src_p1_attrib_x:
236
case gpir_codegen_src_p1_attrib_y:
237
case gpir_codegen_src_p1_attrib_z:
238
case gpir_codegen_src_p1_attrib_w:
239
printf("%c%d.%c", prev_instr->register0_attribute ? 'a' : '$',
240
prev_instr->register0_addr,
241
"xyzw"[src - gpir_codegen_src_p1_attrib_x]);
242
break;
243
}
244
}
245
246
static bool
247
print_mul(gpir_codegen_instr *instr, gpir_codegen_instr *prev_instr,
248
unsigned cur_dest_index)
249
{
250
bool printed = false;
251
252
switch (instr->mul_op) {
253
case gpir_codegen_mul_op_mul:
254
case gpir_codegen_mul_op_complex2:
255
if (instr->mul0_src0 != gpir_codegen_src_unused &&
256
instr->mul0_src1 != gpir_codegen_src_unused) {
257
printed = true;
258
printf("\t");
259
if (instr->mul0_src1 == gpir_codegen_src_ident &&
260
!instr->mul0_neg) {
261
printf("mov.m0 ");
262
print_dest(instr, unit_mul_0, cur_dest_index);
263
printf(" ");
264
print_src(instr->mul0_src0, unit_mul_0, 0, instr, prev_instr,
265
cur_dest_index);
266
} else {
267
if (instr->mul_op == gpir_codegen_mul_op_complex2)
268
printf("complex2.m0 ");
269
else
270
printf("mul.m0 ");
271
272
print_dest(instr, unit_mul_0, cur_dest_index);
273
printf(" ");
274
print_src(instr->mul0_src0, unit_mul_0, 0, instr, prev_instr,
275
cur_dest_index);
276
printf(" ");
277
if (instr->mul0_neg)
278
printf("-");
279
print_src(instr->mul0_src1, unit_mul_0, 1, instr, prev_instr,
280
cur_dest_index);
281
}
282
283
printf("\n");
284
}
285
286
if (instr->mul1_src0 != gpir_codegen_src_unused &&
287
instr->mul1_src1 != gpir_codegen_src_unused) {
288
printed = true;
289
printf("\t");
290
if (instr->mul1_src1 == gpir_codegen_src_ident &&
291
!instr->mul1_neg) {
292
printf("mov.m1 ");
293
print_dest(instr, unit_mul_1, cur_dest_index);
294
printf(" ");
295
print_src(instr->mul1_src0, unit_mul_1, 0, instr, prev_instr,
296
cur_dest_index);
297
} else {
298
printf("mul.m1 ");
299
print_dest(instr, unit_mul_1, cur_dest_index);
300
printf(" ");
301
print_src(instr->mul1_src0, unit_mul_1, 0, instr, prev_instr,
302
cur_dest_index);
303
printf(" ");
304
if (instr->mul1_neg)
305
printf("-");
306
print_src(instr->mul1_src1, unit_mul_0, 1, instr, prev_instr,
307
cur_dest_index);
308
}
309
printf("\n");
310
}
311
312
break;
313
case gpir_codegen_mul_op_complex1:
314
printed = true;
315
printf("\tcomplex1.m01 ");
316
print_dest(instr, unit_mul_0, cur_dest_index);
317
printf(" ");
318
print_src(instr->mul0_src0, unit_mul_0, 0, instr, prev_instr,
319
cur_dest_index);
320
printf(" ");
321
print_src(instr->mul0_src1, unit_mul_0, 1, instr, prev_instr,
322
cur_dest_index);
323
printf(" ");
324
print_src(instr->mul1_src0, unit_mul_1, 0, instr, prev_instr,
325
cur_dest_index);
326
printf(" ");
327
print_src(instr->mul1_src1, unit_mul_1, 1, instr, prev_instr,
328
cur_dest_index);
329
printf("\n");
330
break;
331
332
case gpir_codegen_mul_op_select:
333
printed = true;
334
printf("\tsel.m01 ");
335
print_dest(instr, unit_mul_0, cur_dest_index);
336
printf(" ");
337
print_src(instr->mul0_src1, unit_mul_0, 1, instr, prev_instr,
338
cur_dest_index);
339
printf(" ");
340
print_src(instr->mul0_src0, unit_mul_0, 0, instr, prev_instr,
341
cur_dest_index);
342
printf(" ");
343
print_src(instr->mul1_src0, unit_mul_1, 0, instr, prev_instr,
344
cur_dest_index);
345
printf("\n");
346
break;
347
348
default:
349
printed = true;
350
printf("\tunknown%u.m01 ", instr->mul_op);
351
print_dest(instr, unit_mul_0, cur_dest_index);
352
printf(" ");
353
print_src(instr->mul0_src0, unit_mul_0, 0, instr, prev_instr,
354
cur_dest_index);
355
printf(" ");
356
print_src(instr->mul0_src1, unit_mul_0, 1, instr, prev_instr,
357
cur_dest_index);
358
printf(" ");
359
print_src(instr->mul1_src0, unit_mul_1, 0, instr, prev_instr,
360
cur_dest_index);
361
printf(" ");
362
print_src(instr->mul1_src1, unit_mul_1, 1, instr, prev_instr,
363
cur_dest_index);
364
printf("\n");
365
break;
366
}
367
368
return printed;
369
}
370
371
typedef struct {
372
const char *name;
373
unsigned srcs;
374
} acc_op_info;
375
376
#define CASE(_name, _srcs) \
377
[gpir_codegen_acc_op_##_name] = { \
378
.name = #_name, \
379
.srcs = _srcs \
380
}
381
382
static const acc_op_info acc_op_infos[8] = {
383
CASE(add, 2),
384
CASE(floor, 1),
385
CASE(sign, 1),
386
CASE(ge, 2),
387
CASE(lt, 2),
388
CASE(min, 2),
389
CASE(max, 2),
390
};
391
392
#undef CASE
393
394
static bool
395
print_acc(gpir_codegen_instr *instr, gpir_codegen_instr *prev_instr,
396
unsigned cur_dest_index)
397
{
398
bool printed = false;
399
const acc_op_info op = acc_op_infos[instr->acc_op];
400
401
if (instr->acc0_src0 != gpir_codegen_src_unused) {
402
printed = true;
403
printf("\t");
404
acc_op_info acc0_op = op;
405
if (instr->acc0_src1 == gpir_codegen_src_ident &&
406
instr->acc0_src1_neg) {
407
/* add x, -0 -> mov x */
408
acc0_op.name = "mov";
409
acc0_op.srcs = 1;
410
}
411
412
if (acc0_op.name)
413
printf("%s.a0 ", acc0_op.name);
414
else
415
printf("op%u.a0 ", instr->acc_op);
416
417
print_dest(instr, unit_acc_0, cur_dest_index);
418
printf(" ");
419
if (instr->acc0_src0_neg)
420
printf("-");
421
print_src(instr->acc0_src0, unit_acc_0, 0, instr, prev_instr,
422
cur_dest_index);
423
if (acc0_op.srcs > 1) {
424
printf(" ");
425
if (instr->acc0_src1_neg)
426
printf("-");
427
print_src(instr->acc0_src1, unit_acc_0, 1, instr, prev_instr,
428
cur_dest_index);
429
}
430
431
printf("\n");
432
}
433
434
if (instr->acc1_src0 != gpir_codegen_src_unused) {
435
printed = true;
436
printf("\t");
437
acc_op_info acc1_op = op;
438
if (instr->acc1_src1 == gpir_codegen_src_ident &&
439
instr->acc1_src1_neg) {
440
/* add x, -0 -> mov x */
441
acc1_op.name = "mov";
442
acc1_op.srcs = 1;
443
}
444
445
if (acc1_op.name)
446
printf("%s.a1 ", acc1_op.name);
447
else
448
printf("op%u.a1 ", instr->acc_op);
449
450
print_dest(instr, unit_acc_1, cur_dest_index);
451
printf(" ");
452
if (instr->acc1_src0_neg)
453
printf("-");
454
print_src(instr->acc1_src0, unit_acc_1, 0, instr, prev_instr,
455
cur_dest_index);
456
if (acc1_op.srcs > 1) {
457
printf(" ");
458
if (instr->acc1_src1_neg)
459
printf("-");
460
print_src(instr->acc1_src1, unit_acc_1, 1, instr, prev_instr,
461
cur_dest_index);
462
}
463
464
printf("\n");
465
}
466
467
return printed;
468
}
469
470
static bool
471
print_pass(gpir_codegen_instr *instr, gpir_codegen_instr *prev_instr,
472
unsigned cur_dest_index)
473
{
474
if (instr->pass_src == gpir_codegen_src_unused)
475
return false;
476
477
printf("\t");
478
479
switch (instr->pass_op) {
480
case gpir_codegen_pass_op_pass:
481
printf("mov.p ");
482
break;
483
case gpir_codegen_pass_op_preexp2:
484
printf("preexp2.p ");
485
break;
486
case gpir_codegen_pass_op_postlog2:
487
printf("postlog2.p ");
488
break;
489
case gpir_codegen_pass_op_clamp:
490
printf("clamp.p ");
491
break;
492
default:
493
printf("unk%u.p ", instr->pass_op);
494
}
495
496
print_dest(instr, unit_pass, cur_dest_index);
497
printf(" ");
498
print_src(instr->pass_src, unit_pass, 0, instr, prev_instr,
499
cur_dest_index);
500
501
if (instr->pass_op == gpir_codegen_pass_op_clamp) {
502
printf(" ");
503
print_src(gpir_codegen_src_load_x, unit_pass, 1, instr, prev_instr,
504
cur_dest_index);
505
printf(" ");
506
print_src(gpir_codegen_src_load_y, unit_pass, 2, instr, prev_instr,
507
cur_dest_index);
508
}
509
510
printf("\n");
511
512
return true;
513
}
514
515
static bool
516
print_complex(gpir_codegen_instr *instr, gpir_codegen_instr *prev_instr,
517
unsigned cur_dest_index)
518
{
519
if (instr->complex_src == gpir_codegen_src_unused)
520
return false;
521
522
printf("\t");
523
524
switch (instr->complex_op) {
525
case gpir_codegen_complex_op_nop:
526
return false;
527
528
case gpir_codegen_complex_op_exp2:
529
printf("exp2.c ");
530
break;
531
case gpir_codegen_complex_op_log2:
532
printf("log2.c ");
533
break;
534
case gpir_codegen_complex_op_rsqrt:
535
printf("rsqrt.c ");
536
break;
537
case gpir_codegen_complex_op_rcp:
538
printf("rcp.c ");
539
break;
540
case gpir_codegen_complex_op_pass:
541
case gpir_codegen_complex_op_temp_store_addr:
542
case gpir_codegen_complex_op_temp_load_addr_0:
543
case gpir_codegen_complex_op_temp_load_addr_1:
544
case gpir_codegen_complex_op_temp_load_addr_2:
545
printf("mov.c ");
546
break;
547
default:
548
printf("unk%u.c ", instr->complex_op);
549
}
550
551
print_dest(instr, unit_complex, cur_dest_index);
552
printf(" ");
553
print_src(instr->complex_src, unit_complex, 0, instr, prev_instr,
554
cur_dest_index);
555
printf("\n");
556
557
return true;
558
}
559
560
static void
561
print_instr(gpir_codegen_instr *instr, gpir_codegen_instr *prev_instr,
562
unsigned instr_number, unsigned cur_dest_index)
563
{
564
bool printed = false;
565
printf("%03d:", instr_number);
566
printed |= print_acc(instr, prev_instr, cur_dest_index);
567
printed |= print_mul(instr, prev_instr, cur_dest_index);
568
printed |= print_complex(instr, prev_instr, cur_dest_index);
569
printed |= print_pass(instr, prev_instr, cur_dest_index);
570
571
if (instr->branch) {
572
printed = true;
573
/* The branch condition is taken from the current pass unit result */
574
printf("\tbranch ^%d %03d\n", cur_dest_index + unit_pass,
575
instr->branch_target + (instr->branch_target_lo ? 0 : 0x100));
576
}
577
578
if (instr->unknown_1 != 0) {
579
printed = true;
580
printf("\tunknown_1 %u\n", instr->unknown_1);
581
}
582
583
if (!printed)
584
printf("\tnop\n");
585
}
586
587
void
588
gpir_disassemble_program(gpir_codegen_instr *code, unsigned num_instr)
589
{
590
printf("=======disassembly:=======\n");
591
592
unsigned cur_dest_index = 0;
593
unsigned cur_instr = 0;
594
for (gpir_codegen_instr *instr = code; cur_instr < num_instr;
595
instr++, cur_instr++, cur_dest_index += num_units) {
596
print_instr(instr, instr - 1, cur_instr, cur_dest_index);
597
}
598
}
599
600
601