2 * Copyright (c) 2018 Lima Project
4 * Copyright (c) 2013 Codethink (http://www.codethink.co.uk)
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:
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
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.
27 #include "util/u_half.h"
38 print_swizzle(uint8_t swizzle
)
44 for (unsigned i
= 0; i
< 4; i
++, swizzle
>>= 2)
45 printf("%c", "xyzw"[swizzle
& 3]);
49 print_mask(uint8_t mask
)
55 if (mask
& 1) printf("x");
56 if (mask
& 2) printf("y");
57 if (mask
& 4) printf("z");
58 if (mask
& 8) printf("w");
62 print_reg(ppir_codegen_vec4_reg reg
, const char *special
)
65 printf("%s", special
);
69 case ppir_codegen_vec4_reg_constant0
:
72 case ppir_codegen_vec4_reg_constant1
:
75 case ppir_codegen_vec4_reg_texture
:
78 case ppir_codegen_vec4_reg_uniform
:
89 print_vector_source(ppir_codegen_vec4_reg reg
, const char *special
,
90 uint8_t swizzle
, bool abs
, bool neg
)
97 print_reg(reg
, special
);
98 print_swizzle(swizzle
);
105 print_source_scalar(unsigned reg
, const char *special
, bool abs
, bool neg
)
112 print_reg(reg
>> 2, special
);
114 printf(".%c", "xyzw"[reg
& 3]);
121 print_varying_source(ppir_codegen_field_varying
*varying
)
123 switch (varying
->imm
.alignment
) {
125 printf("%u.%c", varying
->imm
.index
>> 2,
126 "xyzw"[varying
->imm
.index
& 3]);
129 const char *c
[2] = {"xy", "zw"};
130 printf("%u.%s", varying
->imm
.index
>> 1, c
[varying
->imm
.index
& 1]);
134 printf("%u", varying
->imm
.index
);
138 if (varying
->imm
.offset_vector
!= 15) {
139 unsigned reg
= (varying
->imm
.offset_vector
<< 2) +
140 varying
->imm
.offset_scalar
;
142 print_source_scalar(reg
, NULL
, false, false);
147 print_outmod(ppir_codegen_outmod modifier
)
151 case ppir_codegen_outmod_clamp_fraction
:
154 case ppir_codegen_outmod_clamp_positive
:
157 case ppir_codegen_outmod_round
:
166 print_dest_scalar(unsigned reg
)
168 printf("$%u", reg
>> 2);
169 printf(".%c ", "xyzw"[reg
& 3]);
173 print_const(unsigned const_num
, uint16_t *val
)
175 printf("const%u", const_num
);
176 for (unsigned i
= 0; i
< 4; i
++)
177 printf(" %f", util_half_to_float(val
[i
]));
181 print_const0(void *code
, unsigned offset
)
185 print_const(0, code
);
189 print_const1(void *code
, unsigned offset
)
193 print_const(1, code
);
197 print_varying(void *code
, unsigned offset
)
200 ppir_codegen_field_varying
*varying
= code
;
204 bool perspective
= varying
->imm
.source_type
< 2 && varying
->imm
.perspective
;
207 printf(".perspective");
208 switch (varying
->imm
.perspective
)
224 switch (varying
->imm
.dest
)
226 case ppir_codegen_vec4_reg_discard
:
230 printf("$%u", varying
->imm
.dest
);
233 print_mask(varying
->imm
.mask
);
236 switch (varying
->imm
.source_type
) {
238 print_vector_source(varying
->reg
.source
, NULL
, varying
->reg
.swizzle
,
239 varying
->reg
.absolute
, varying
->reg
.negate
);
242 switch (varying
->imm
.perspective
) {
245 print_varying_source(varying
);
250 print_vector_source(varying
->reg
.source
, NULL
, varying
->reg
.swizzle
,
251 varying
->reg
.absolute
, varying
->reg
.negate
);
255 printf("normalize(");
256 print_vector_source(varying
->reg
.source
, NULL
, varying
->reg
.swizzle
,
257 varying
->reg
.absolute
, varying
->reg
.negate
);
261 printf("gl_FragCoord");
266 if (varying
->imm
.perspective
)
267 printf("gl_FrontFacing");
269 printf("gl_PointCoord");
272 print_varying_source(varying
);
278 print_sampler(void *code
, unsigned offset
)
281 ppir_codegen_field_sampler
*sampler
= code
;
284 if (sampler
->lod_bias_en
)
287 switch (sampler
->type
) {
288 case ppir_codegen_sampler_type_2d
:
291 case ppir_codegen_sampler_type_cube
:
295 printf("_t%u", sampler
->type
);
299 printf(" %u", sampler
->index
);
301 if (sampler
->offset_en
)
304 print_source_scalar(sampler
->index_offset
, NULL
, false, false);
307 if (sampler
->lod_bias_en
)
310 print_source_scalar(sampler
->lod_bias
, NULL
, false, false);
315 print_uniform(void *code
, unsigned offset
)
318 ppir_codegen_field_uniform
*uniform
= code
;
322 switch (uniform
->source
) {
323 case ppir_codegen_uniform_src_uniform
:
326 case ppir_codegen_uniform_src_temporary
:
330 printf(".u%u", uniform
->source
);
334 int16_t index
= uniform
->index
;
335 switch (uniform
->alignment
) {
337 printf(" %d", index
);
340 printf(" %d.%s", index
/ 2, (index
& 1) ? "zw" : "xy");
343 printf(" %d.%c", index
/ 4, "xyzw"[index
& 3]);
347 if (uniform
->offset_en
) {
349 print_source_scalar(uniform
->offset_reg
, NULL
, false, false);
353 #define CASE(_name, _srcs) \
354 [ppir_codegen_vec4_mul_op_##_name] = { \
359 static const asm_op vec4_mul_ops
[] = {
380 print_vec4_mul(void *code
, unsigned offset
)
383 ppir_codegen_field_vec4_mul
*vec4_mul
= code
;
385 asm_op op
= vec4_mul_ops
[vec4_mul
->op
];
388 printf("%s", op
.name
);
390 printf("op%u", vec4_mul
->op
);
391 print_outmod(vec4_mul
->dest_modifier
);
394 if (vec4_mul
->mask
) {
395 printf("$%u", vec4_mul
->dest
);
396 print_mask(vec4_mul
->mask
);
400 print_vector_source(vec4_mul
->arg0_source
, NULL
,
401 vec4_mul
->arg0_swizzle
,
402 vec4_mul
->arg0_absolute
,
403 vec4_mul
->arg0_negate
);
405 if (vec4_mul
->op
< 8 && vec4_mul
->op
!= 0) {
406 printf("<<%u", vec4_mul
->op
);
412 print_vector_source(vec4_mul
->arg1_source
, NULL
,
413 vec4_mul
->arg1_swizzle
,
414 vec4_mul
->arg1_absolute
,
415 vec4_mul
->arg1_negate
);
419 #define CASE(_name, _srcs) \
420 [ppir_codegen_vec4_acc_op_##_name] = { \
425 static const asm_op vec4_acc_ops
[] = {
447 print_vec4_acc(void *code
, unsigned offset
)
450 ppir_codegen_field_vec4_acc
*vec4_acc
= code
;
452 asm_op op
= vec4_acc_ops
[vec4_acc
->op
];
455 printf("%s", op
.name
);
457 printf("op%u", vec4_acc
->op
);
458 print_outmod(vec4_acc
->dest_modifier
);
461 if (vec4_acc
->mask
) {
462 printf("$%u", vec4_acc
->dest
);
463 print_mask(vec4_acc
->mask
);
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
);
474 print_vector_source(vec4_acc
->arg1_source
, NULL
,
475 vec4_acc
->arg1_swizzle
,
476 vec4_acc
->arg1_absolute
,
477 vec4_acc
->arg1_negate
);
481 #define CASE(_name, _srcs) \
482 [ppir_codegen_float_mul_op_##_name] = { \
487 static const asm_op float_mul_ops
[] = {
508 print_float_mul(void *code
, unsigned offset
)
511 ppir_codegen_field_float_mul
*float_mul
= code
;
513 asm_op op
= float_mul_ops
[float_mul
->op
];
516 printf("%s", op
.name
);
518 printf("op%u", float_mul
->op
);
519 print_outmod(float_mul
->dest_modifier
);
522 if (float_mul
->output_en
)
523 print_dest_scalar(float_mul
->dest
);
525 print_source_scalar(float_mul
->arg0_source
, NULL
,
526 float_mul
->arg0_absolute
,
527 float_mul
->arg0_negate
);
529 if (float_mul
->op
< 8 && float_mul
->op
!= 0) {
530 printf("<<%u", float_mul
->op
);
536 print_source_scalar(float_mul
->arg1_source
, NULL
,
537 float_mul
->arg1_absolute
,
538 float_mul
->arg1_negate
);
542 #define CASE(_name, _srcs) \
543 [ppir_codegen_float_acc_op_##_name] = { \
548 static const asm_op float_acc_ops
[] = {
568 print_float_acc(void *code
, unsigned offset
)
571 ppir_codegen_field_float_acc
*float_acc
= code
;
573 asm_op op
= float_acc_ops
[float_acc
->op
];
576 printf("%s", op
.name
);
578 printf("op%u", float_acc
->op
);
579 print_outmod(float_acc
->dest_modifier
);
582 if (float_acc
->output_en
)
583 print_dest_scalar(float_acc
->dest
);
585 print_source_scalar(float_acc
->arg0_source
, float_acc
->mul_in
? "^s0" : NULL
,
586 float_acc
->arg0_absolute
,
587 float_acc
->arg0_negate
);
591 print_source_scalar(float_acc
->arg1_source
, NULL
,
592 float_acc
->arg1_absolute
,
593 float_acc
->arg1_negate
);
597 #define CASE(_name, _srcs) \
598 [ppir_codegen_combine_scalar_op_##_name] = { \
603 static const asm_op combine_ops
[] = {
619 print_combine(void *code
, unsigned offset
)
622 ppir_codegen_field_combine
*combine
= code
;
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.
631 asm_op op
= combine_ops
[combine
->scalar
.op
];
634 printf("%s", op
.name
);
636 printf("op%u", combine
->scalar
.op
);
639 if (!combine
->scalar
.dest_vec
)
640 print_outmod(combine
->scalar
.dest_modifier
);
643 if (combine
->scalar
.dest_vec
) {
644 printf("$%u", combine
->vector
.dest
);
645 print_mask(combine
->vector
.mask
);
647 print_dest_scalar(combine
->scalar
.dest
);
651 print_source_scalar(combine
->scalar
.arg0_src
, NULL
,
652 combine
->scalar
.arg0_absolute
,
653 combine
->scalar
.arg0_negate
);
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
,
662 print_source_scalar(combine
->scalar
.arg1_src
, NULL
,
663 combine
->scalar
.arg1_absolute
,
664 combine
->scalar
.arg1_negate
);
670 print_temp_write(void *code
, unsigned offset
)
673 ppir_codegen_field_temp_write
*temp_write
= code
;
675 if (temp_write
->fb_read
.unknown_0
== 0x7) {
676 if (temp_write
->fb_read
.source
)
680 printf(" $%u", temp_write
->fb_read
.dest
);
687 int16_t index
= temp_write
->temp_write
.index
;
688 switch (temp_write
->temp_write
.alignment
) {
690 printf(" %d", index
);
693 printf(" %d.%s", index
/ 2, (index
& 1) ? "zw" : "xy");
696 printf(" %d.%c", index
/ 4, "xyzw"[index
& 3]);
700 if (temp_write
->temp_write
.offset_en
) {
702 print_source_scalar(temp_write
->temp_write
.offset_reg
,
708 if (temp_write
->temp_write
.alignment
) {
709 print_reg(temp_write
->temp_write
.source
>> 2, NULL
);
711 print_source_scalar(temp_write
->temp_write
.source
, NULL
, false, false);
716 print_branch(void *code
, unsigned offset
)
718 ppir_codegen_field_branch
*branch
= code
;
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
) {
728 const char* cond
[] = {
729 "nv", "lt", "eq", "le",
730 "gt", "ne", "ge", "" ,
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);
738 if (cond_mask
!= 0x7) {
739 printf(".%s ", cond
[cond_mask
]);
740 print_source_scalar(branch
->branch
.arg0_source
, NULL
, false, false);
742 print_source_scalar(branch
->branch
.arg1_source
, NULL
, false, false);
745 printf(" %d", branch
->branch
.target
+ offset
);
748 typedef void (*print_field_func
)(void *, unsigned);
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
,
765 static const int ppir_codegen_field_size
[] = {
766 34, 62, 41, 43, 30, 44, 31, 30, 41, 73, 64, 64
770 bitcopy(char *src
, char *dst
, unsigned bits
, unsigned src_offset
)
772 src
+= src_offset
/ 8;
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
);
784 ppir_disassemble_instr(uint32_t *instr
, unsigned offset
)
786 ppir_codegen_ctrl
*ctrl
= (ppir_codegen_ctrl
*) instr
;
788 char *instr_code
= (char *) (instr
+ 1);
789 unsigned bit_offset
= 0;
791 for (unsigned i
= 0; i
< ppir_codegen_field_shift_count
; i
++) {
794 if (!((ctrl
->fields
>> i
) & 1))
797 unsigned bits
= ppir_codegen_field_size
[i
];
798 bitcopy(instr_code
, code
, bits
, bit_offset
);
805 print_field
[i
](code
, offset
);