101e04c3fSmrg/*
201e04c3fSmrg * Copyright (c) 2016 Etnaviv Project
301e04c3fSmrg *
401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
501e04c3fSmrg * copy of this software and associated documentation files (the "Software"),
601e04c3fSmrg * to deal in the Software without restriction, including without limitation
701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sub license,
801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the
901e04c3fSmrg * Software is furnished to do so, subject to the following conditions:
1001e04c3fSmrg *
1101e04c3fSmrg * The above copyright notice and this permission notice (including the
1201e04c3fSmrg * next paragraph) shall be included in all copies or substantial portions
1301e04c3fSmrg * of the Software.
1401e04c3fSmrg *
1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2101e04c3fSmrg * DEALINGS IN THE SOFTWARE.
2201e04c3fSmrg *
2301e04c3fSmrg * Authors:
2401e04c3fSmrg *    Christian Gmeiner <christian.gmeiner@gmail.com>
2501e04c3fSmrg */
2601e04c3fSmrg
2701e04c3fSmrg#include "etnaviv_disasm.h"
287ec681f3Smrg#include "etnaviv_asm.h"
2901e04c3fSmrg
3001e04c3fSmrg#include <assert.h>
3101e04c3fSmrg#include <stdbool.h>
3201e04c3fSmrg#include <stdio.h>
3301e04c3fSmrg#include <stdlib.h>
3401e04c3fSmrg
3501e04c3fSmrg#include "hw/isa.xml.h"
367ec681f3Smrg#include "util/u_math.h"
377ec681f3Smrg#include "util/half_float.h"
3801e04c3fSmrg
3901e04c3fSmrgstruct instr {
4001e04c3fSmrg   /* dword0: */
4101e04c3fSmrg   uint32_t opc         : 6;
4201e04c3fSmrg   uint32_t cond        : 5;
4301e04c3fSmrg   uint32_t sat         : 1;
4401e04c3fSmrg   uint32_t dst_use     : 1;
4501e04c3fSmrg   uint32_t dst_amode   : 3;
4601e04c3fSmrg   uint32_t dst_reg     : 7;
4701e04c3fSmrg   uint32_t dst_comps   : 4;
4801e04c3fSmrg   uint32_t tex_id      : 5;
4901e04c3fSmrg
5001e04c3fSmrg   /* dword1: */
5101e04c3fSmrg   uint32_t tex_amode   : 3;
5201e04c3fSmrg   uint32_t tex_swiz    : 8;
5301e04c3fSmrg   uint32_t src0_use    : 1;
5401e04c3fSmrg   uint32_t src0_reg    : 9;
5501e04c3fSmrg   uint32_t type_bit2   : 1;
5601e04c3fSmrg   uint32_t src0_swiz   : 8;
5701e04c3fSmrg   uint32_t src0_neg    : 1;
5801e04c3fSmrg   uint32_t src0_abs    : 1;
5901e04c3fSmrg
6001e04c3fSmrg   /* dword2: */
6101e04c3fSmrg   uint32_t src0_amode  : 3;
6201e04c3fSmrg   uint32_t src0_rgroup : 3;
6301e04c3fSmrg   uint32_t src1_use    : 1;
6401e04c3fSmrg   uint32_t src1_reg    : 9;
6501e04c3fSmrg   uint32_t opcode_bit6 : 1;
6601e04c3fSmrg   uint32_t src1_swiz   : 8;
6701e04c3fSmrg   uint32_t src1_neg    : 1;
6801e04c3fSmrg   uint32_t src1_abs    : 1;
6901e04c3fSmrg   uint32_t src1_amode  : 3;
7001e04c3fSmrg   uint32_t type_bit01  : 2;
7101e04c3fSmrg
7201e04c3fSmrg   /* dword3: */
7301e04c3fSmrg   union {
7401e04c3fSmrg      struct {
7501e04c3fSmrg         uint32_t src1_rgroup : 3;
7601e04c3fSmrg         uint32_t src2_use    : 1;
7701e04c3fSmrg         uint32_t src2_reg    : 9;
787ec681f3Smrg         uint32_t sel_0       : 1;
7901e04c3fSmrg         uint32_t src2_swiz   : 8;
8001e04c3fSmrg         uint32_t src2_neg    : 1;
8101e04c3fSmrg         uint32_t src2_abs    : 1;
827ec681f3Smrg         uint32_t sel_1       : 1;
8301e04c3fSmrg         uint32_t src2_amode  : 3;
8401e04c3fSmrg         uint32_t src2_rgroup : 3;
857ec681f3Smrg         uint32_t dst_full    : 1;
8601e04c3fSmrg      };
8701e04c3fSmrg      uint32_t dword3;
8801e04c3fSmrg   };
8901e04c3fSmrg};
9001e04c3fSmrgstruct opc_operands {
917ec681f3Smrg   struct etna_inst_dst *dst;
927ec681f3Smrg   struct etna_inst_tex *tex;
937ec681f3Smrg   struct etna_inst_src *src0;
947ec681f3Smrg   struct etna_inst_src *src1;
957ec681f3Smrg   struct etna_inst_src *src2;
9601e04c3fSmrg
9701e04c3fSmrg   int imm;
9801e04c3fSmrg};
9901e04c3fSmrg
10001e04c3fSmrgstatic void
10101e04c3fSmrgprintf_type(uint8_t type)
10201e04c3fSmrg{
10301e04c3fSmrg   switch(type) {
10401e04c3fSmrg   case INST_TYPE_F32:
10501e04c3fSmrg      /* as f32 is the default print nothing */
10601e04c3fSmrg      break;
10701e04c3fSmrg
10801e04c3fSmrg   case INST_TYPE_S32:
10901e04c3fSmrg      printf(".s32");
11001e04c3fSmrg      break;
11101e04c3fSmrg
11201e04c3fSmrg   case INST_TYPE_S8:
11301e04c3fSmrg      printf(".s8");
11401e04c3fSmrg      break;
11501e04c3fSmrg
11601e04c3fSmrg   case INST_TYPE_U16:
11701e04c3fSmrg      printf(".u16");
11801e04c3fSmrg      break;
11901e04c3fSmrg
12001e04c3fSmrg   case INST_TYPE_F16:
12101e04c3fSmrg      printf(".f16");
12201e04c3fSmrg      break;
12301e04c3fSmrg
12401e04c3fSmrg   case INST_TYPE_S16:
12501e04c3fSmrg      printf(".s16");
12601e04c3fSmrg      break;
12701e04c3fSmrg
12801e04c3fSmrg   case INST_TYPE_U32:
12901e04c3fSmrg      printf(".u32");
13001e04c3fSmrg      break;
13101e04c3fSmrg
13201e04c3fSmrg   case INST_TYPE_U8:
13301e04c3fSmrg      printf(".u8");
13401e04c3fSmrg      break;
13501e04c3fSmrg
13601e04c3fSmrg   default:
13701e04c3fSmrg      abort();
13801e04c3fSmrg      break;
13901e04c3fSmrg   }
14001e04c3fSmrg}
14101e04c3fSmrg
14201e04c3fSmrgstatic void
14301e04c3fSmrgprint_condition(uint8_t condition)
14401e04c3fSmrg{
14501e04c3fSmrg   switch (condition) {
14601e04c3fSmrg   case INST_CONDITION_TRUE:
14701e04c3fSmrg      break;
14801e04c3fSmrg
14901e04c3fSmrg   case INST_CONDITION_GT:
15001e04c3fSmrg      printf(".GT");
15101e04c3fSmrg      break;
15201e04c3fSmrg
15301e04c3fSmrg   case INST_CONDITION_LT:
15401e04c3fSmrg      printf(".LT");
15501e04c3fSmrg      break;
15601e04c3fSmrg
15701e04c3fSmrg   case INST_CONDITION_GE:
15801e04c3fSmrg      printf(".GE");
15901e04c3fSmrg      break;
16001e04c3fSmrg
16101e04c3fSmrg   case INST_CONDITION_LE:
16201e04c3fSmrg      printf(".LE");
16301e04c3fSmrg      break;
16401e04c3fSmrg
16501e04c3fSmrg   case INST_CONDITION_EQ:
16601e04c3fSmrg      printf(".EQ");
16701e04c3fSmrg      break;
16801e04c3fSmrg
16901e04c3fSmrg   case INST_CONDITION_NE:
17001e04c3fSmrg      printf(".NE");
17101e04c3fSmrg      break;
17201e04c3fSmrg
17301e04c3fSmrg   case INST_CONDITION_AND:
17401e04c3fSmrg      printf(".AND");
17501e04c3fSmrg      break;
17601e04c3fSmrg
17701e04c3fSmrg   case INST_CONDITION_OR:
17801e04c3fSmrg      printf(".OR");
17901e04c3fSmrg      break;
18001e04c3fSmrg
18101e04c3fSmrg   case INST_CONDITION_XOR:
18201e04c3fSmrg      printf(".XOR");
18301e04c3fSmrg      break;
18401e04c3fSmrg
18501e04c3fSmrg   case INST_CONDITION_NOT:
18601e04c3fSmrg      printf(".NOT");
18701e04c3fSmrg      break;
18801e04c3fSmrg
18901e04c3fSmrg   case INST_CONDITION_NZ:
19001e04c3fSmrg      printf(".NZ");
19101e04c3fSmrg      break;
19201e04c3fSmrg
19301e04c3fSmrg   case INST_CONDITION_GEZ:
19401e04c3fSmrg      printf(".GEZ");
19501e04c3fSmrg      break;
19601e04c3fSmrg
19701e04c3fSmrg   case INST_CONDITION_GZ:
19801e04c3fSmrg      printf(".GZ");
19901e04c3fSmrg      break;
20001e04c3fSmrg
20101e04c3fSmrg   case INST_CONDITION_LEZ:
20201e04c3fSmrg      printf(".LEZ");
20301e04c3fSmrg      break;
20401e04c3fSmrg
20501e04c3fSmrg   case INST_CONDITION_LZ:
20601e04c3fSmrg      printf(".LZ");
20701e04c3fSmrg      break;
20801e04c3fSmrg
20901e04c3fSmrg   default:
21001e04c3fSmrg      abort();
21101e04c3fSmrg      break;
21201e04c3fSmrg   }
21301e04c3fSmrg}
21401e04c3fSmrg
21501e04c3fSmrgstatic void
21601e04c3fSmrgprint_rgroup(uint8_t rgoup)
21701e04c3fSmrg{
21801e04c3fSmrg   switch (rgoup) {
21901e04c3fSmrg   case INST_RGROUP_TEMP:
22001e04c3fSmrg      printf("t");
22101e04c3fSmrg      break;
22201e04c3fSmrg
22301e04c3fSmrg   case INST_RGROUP_INTERNAL:
22401e04c3fSmrg      printf("i");
22501e04c3fSmrg      break;
22601e04c3fSmrg
22701e04c3fSmrg   case INST_RGROUP_UNIFORM_0:
22801e04c3fSmrg   case INST_RGROUP_UNIFORM_1:
22901e04c3fSmrg      printf("u");
23001e04c3fSmrg      break;
2317ec681f3Smrg   case 4:
2327ec681f3Smrg      printf("th");
2337ec681f3Smrg      break;
23401e04c3fSmrg   }
23501e04c3fSmrg}
23601e04c3fSmrg
23701e04c3fSmrgstatic void
23801e04c3fSmrgprint_components(uint8_t components)
23901e04c3fSmrg{
24001e04c3fSmrg   if (components == 15)
24101e04c3fSmrg      return;
24201e04c3fSmrg
24301e04c3fSmrg   printf(".");
24401e04c3fSmrg   if (components & INST_COMPS_X)
24501e04c3fSmrg      printf("x");
24601e04c3fSmrg   else
24701e04c3fSmrg      printf("_");
24801e04c3fSmrg
24901e04c3fSmrg   if (components & INST_COMPS_Y)
25001e04c3fSmrg      printf("y");
25101e04c3fSmrg   else
25201e04c3fSmrg      printf("_");
25301e04c3fSmrg
25401e04c3fSmrg   if (components & INST_COMPS_Z)
25501e04c3fSmrg      printf("z");
25601e04c3fSmrg   else
25701e04c3fSmrg      printf("_");
25801e04c3fSmrg
25901e04c3fSmrg   if (components & INST_COMPS_W)
26001e04c3fSmrg      printf("w");
26101e04c3fSmrg   else
26201e04c3fSmrg      printf("_");
26301e04c3fSmrg}
26401e04c3fSmrg
26501e04c3fSmrgstatic inline void
26601e04c3fSmrgprint_swiz_comp(uint8_t swiz_comp)
26701e04c3fSmrg{
26801e04c3fSmrg   switch (swiz_comp) {
26901e04c3fSmrg   case INST_SWIZ_COMP_X:
27001e04c3fSmrg      printf("x");
27101e04c3fSmrg      break;
27201e04c3fSmrg
27301e04c3fSmrg   case INST_SWIZ_COMP_Y:
27401e04c3fSmrg      printf("y");
27501e04c3fSmrg      break;
27601e04c3fSmrg
27701e04c3fSmrg   case INST_SWIZ_COMP_Z:
27801e04c3fSmrg      printf("z");
27901e04c3fSmrg      break;
28001e04c3fSmrg
28101e04c3fSmrg   case INST_SWIZ_COMP_W:
28201e04c3fSmrg      printf("w");
28301e04c3fSmrg      break;
28401e04c3fSmrg
28501e04c3fSmrg   default:
28601e04c3fSmrg      abort();
28701e04c3fSmrg      break;
28801e04c3fSmrg   }
28901e04c3fSmrg}
29001e04c3fSmrg
29101e04c3fSmrgstatic void
29201e04c3fSmrgprint_swiz(uint8_t swiz)
29301e04c3fSmrg{
29401e04c3fSmrg   // if a null swizzle
29501e04c3fSmrg   if (swiz == 0xe4)
29601e04c3fSmrg      return;
29701e04c3fSmrg
29801e04c3fSmrg   const unsigned x = swiz & 0x3;
29901e04c3fSmrg   const unsigned y = (swiz & 0x0C) >> 2;
30001e04c3fSmrg   const unsigned z = (swiz & 0x30) >> 4;
30101e04c3fSmrg   const unsigned w = (swiz & 0xc0) >> 6;
30201e04c3fSmrg
30301e04c3fSmrg   printf(".");
30401e04c3fSmrg   print_swiz_comp(x);
30501e04c3fSmrg   print_swiz_comp(y);
30601e04c3fSmrg   print_swiz_comp(z);
30701e04c3fSmrg   print_swiz_comp(w);
30801e04c3fSmrg}
30901e04c3fSmrg
31001e04c3fSmrgstatic void
31101e04c3fSmrgprint_amode(uint8_t amode)
31201e04c3fSmrg{
31301e04c3fSmrg   switch (amode) {
31401e04c3fSmrg   case INST_AMODE_DIRECT:
31501e04c3fSmrg      /* nothing to output */
31601e04c3fSmrg      break;
31701e04c3fSmrg
31801e04c3fSmrg   case INST_AMODE_ADD_A_X:
31901e04c3fSmrg      printf("[a.x]");
32001e04c3fSmrg      break;
32101e04c3fSmrg
32201e04c3fSmrg   case INST_AMODE_ADD_A_Y:
32301e04c3fSmrg      printf("[a.y]");
32401e04c3fSmrg      break;
32501e04c3fSmrg
32601e04c3fSmrg   case INST_AMODE_ADD_A_Z:
32701e04c3fSmrg      printf("[a.z]");
32801e04c3fSmrg      break;
32901e04c3fSmrg
33001e04c3fSmrg   case INST_AMODE_ADD_A_W:
33101e04c3fSmrg      printf("[a.w]");
33201e04c3fSmrg      break;
33301e04c3fSmrg
33401e04c3fSmrg   default:
33501e04c3fSmrg      abort();
33601e04c3fSmrg      break;
33701e04c3fSmrg   }
33801e04c3fSmrg}
33901e04c3fSmrg
34001e04c3fSmrgstatic void
3417ec681f3Smrgprint_dst(struct etna_inst_dst *dst, bool sep)
34201e04c3fSmrg{
34301e04c3fSmrg   if (dst->use) {
34401e04c3fSmrg      printf("t%u", dst->reg);
34501e04c3fSmrg      print_amode(dst->amode);
3467ec681f3Smrg      print_components(dst->write_mask);
34701e04c3fSmrg   } else {
34801e04c3fSmrg      printf("void");
34901e04c3fSmrg   }
35001e04c3fSmrg
35101e04c3fSmrg   if (sep)
35201e04c3fSmrg      printf(", ");
35301e04c3fSmrg}
35401e04c3fSmrg
35501e04c3fSmrgstatic void
3567ec681f3Smrgprint_tex(struct etna_inst_tex *tex, bool sep)
35701e04c3fSmrg{
35801e04c3fSmrg   printf("tex%u", tex->id);
35901e04c3fSmrg   print_amode(tex->amode);
36001e04c3fSmrg   print_swiz(tex->swiz);
36101e04c3fSmrg
36201e04c3fSmrg   if (sep)
36301e04c3fSmrg      printf(", ");
36401e04c3fSmrg}
36501e04c3fSmrg
36601e04c3fSmrgstatic void
3677ec681f3Smrgprint_src(struct etna_inst_src *src, bool sep)
36801e04c3fSmrg{
36901e04c3fSmrg   if (src->use) {
3707ec681f3Smrg      if (src->rgroup == INST_RGROUP_IMMEDIATE) {
3717ec681f3Smrg         switch (src->imm_type) {
3727ec681f3Smrg         case 0: /* float */
3737ec681f3Smrg            printf("%f", uif(src->imm_val << 12));
3747ec681f3Smrg            break;
3757ec681f3Smrg         case 1: /* signed */
3767ec681f3Smrg            printf("%d", ((int) src->imm_val << 12) >> 12);
3777ec681f3Smrg            break;
3787ec681f3Smrg         case 2: /* unsigned */
3797ec681f3Smrg            printf("%d", src->imm_val);
3807ec681f3Smrg            break;
3817ec681f3Smrg         case 3: /* 16-bit */
3827ec681f3Smrg            printf("%f/%.5X", _mesa_half_to_float(src->imm_val), src->imm_val);
3837ec681f3Smrg            break;
3847ec681f3Smrg         }
3857ec681f3Smrg      } else {
3867ec681f3Smrg         if (src->neg)
3877ec681f3Smrg            printf("-");
3887ec681f3Smrg
3897ec681f3Smrg         if (src->abs)
3907ec681f3Smrg            printf("|");
3917ec681f3Smrg
3927ec681f3Smrg         if (src->rgroup == INST_RGROUP_UNIFORM_1)
3937ec681f3Smrg            src->reg += 128;
3947ec681f3Smrg
3957ec681f3Smrg         print_rgroup(src->rgroup);
3967ec681f3Smrg         printf("%u", src->reg);
3977ec681f3Smrg         print_amode(src->amode);
3987ec681f3Smrg         print_swiz(src->swiz);
3997ec681f3Smrg
4007ec681f3Smrg         if (src->abs)
4017ec681f3Smrg            printf("|");
4027ec681f3Smrg      }
40301e04c3fSmrg   } else {
40401e04c3fSmrg      printf("void");
40501e04c3fSmrg   }
40601e04c3fSmrg
40701e04c3fSmrg   if (sep)
40801e04c3fSmrg      printf(", ");
40901e04c3fSmrg}
41001e04c3fSmrg
41101e04c3fSmrgstatic void
41201e04c3fSmrgprint_opc_default(struct opc_operands *operands)
41301e04c3fSmrg{
41401e04c3fSmrg   print_dst(operands->dst, true);
41501e04c3fSmrg   print_src(operands->src0, true);
41601e04c3fSmrg   print_src(operands->src1, true);
41701e04c3fSmrg   print_src(operands->src2, false);
41801e04c3fSmrg}
41901e04c3fSmrg
42001e04c3fSmrgstatic void
42101e04c3fSmrgprint_opc_mov(struct opc_operands *operands)
42201e04c3fSmrg{
42301e04c3fSmrg   // dst (areg)
42401e04c3fSmrg   printf("a%u", operands->dst->reg);
4257ec681f3Smrg   print_components(operands->dst->write_mask);
42601e04c3fSmrg   printf(", ");
42701e04c3fSmrg
42801e04c3fSmrg   print_src(operands->src0, true);
42901e04c3fSmrg   print_src(operands->src1, true);
43001e04c3fSmrg   print_src(operands->src2, false);
43101e04c3fSmrg}
43201e04c3fSmrg
43301e04c3fSmrgstatic void
43401e04c3fSmrgprint_opc_tex(struct opc_operands *operands)
43501e04c3fSmrg{
43601e04c3fSmrg   print_dst(operands->dst, true);
43701e04c3fSmrg   print_tex(operands->tex, true);
43801e04c3fSmrg   print_src(operands->src0, true);
43901e04c3fSmrg   print_src(operands->src1, true);
44001e04c3fSmrg   print_src(operands->src2, false);
44101e04c3fSmrg}
44201e04c3fSmrg
44301e04c3fSmrgstatic void
44401e04c3fSmrgprint_opc_imm(struct opc_operands *operands)
44501e04c3fSmrg{
44601e04c3fSmrg   print_dst(operands->dst, true);
44701e04c3fSmrg   print_src(operands->src0, true);
44801e04c3fSmrg   print_src(operands->src1, true);
44901e04c3fSmrg   printf("label_%04d", operands->imm);
45001e04c3fSmrg}
45101e04c3fSmrg
45201e04c3fSmrg#define OPC_BITS 7
45301e04c3fSmrg
45401e04c3fSmrgstatic const struct opc_info {
45501e04c3fSmrg   const char *name;
45601e04c3fSmrg   void (*print)(struct opc_operands *operands);
45701e04c3fSmrg} opcs[1 << OPC_BITS] = {
45801e04c3fSmrg#define OPC(opc) [INST_OPCODE_##opc] = {#opc, print_opc_default}
45901e04c3fSmrg#define OPC_MOV(opc) [INST_OPCODE_##opc] = {#opc, print_opc_mov}
46001e04c3fSmrg#define OPC_TEX(opc) [INST_OPCODE_##opc] = {#opc, print_opc_tex}
46101e04c3fSmrg#define OPC_IMM(opc) [INST_OPCODE_##opc] = {#opc, print_opc_imm}
46201e04c3fSmrg   OPC(NOP),
46301e04c3fSmrg   OPC(ADD),
46401e04c3fSmrg   OPC(MAD),
46501e04c3fSmrg   OPC(MUL),
46601e04c3fSmrg   OPC(DST),
46701e04c3fSmrg   OPC(DP3),
46801e04c3fSmrg   OPC(DP4),
46901e04c3fSmrg   OPC(DSX),
47001e04c3fSmrg   OPC(DSY),
47101e04c3fSmrg   OPC(MOV),
47201e04c3fSmrg   OPC_MOV(MOVAR),
47301e04c3fSmrg   OPC_MOV(MOVAF),
4747ec681f3Smrg   OPC_MOV(MOVAI),
47501e04c3fSmrg   OPC(RCP),
47601e04c3fSmrg   OPC(RSQ),
47701e04c3fSmrg   OPC(LITP),
47801e04c3fSmrg   OPC(SELECT),
47901e04c3fSmrg   OPC(SET),
48001e04c3fSmrg   OPC(EXP),
48101e04c3fSmrg   OPC(LOG),
48201e04c3fSmrg   OPC(FRC),
48301e04c3fSmrg   OPC_IMM(CALL),
48401e04c3fSmrg   OPC(RET),
48501e04c3fSmrg   OPC_IMM(BRANCH),
48601e04c3fSmrg   OPC_TEX(TEXKILL),
48701e04c3fSmrg   OPC_TEX(TEXLD),
48801e04c3fSmrg   OPC_TEX(TEXLDB),
48901e04c3fSmrg   OPC_TEX(TEXLDD),
49001e04c3fSmrg   OPC_TEX(TEXLDL),
49101e04c3fSmrg   OPC_TEX(TEXLDPCF),
4927ec681f3Smrg   OPC_TEX(TEXLDLPCF),
4937ec681f3Smrg   OPC_TEX(TEXLDGPCF),
49401e04c3fSmrg   OPC(REP),
49501e04c3fSmrg   OPC(ENDREP),
49601e04c3fSmrg   OPC(LOOP),
49701e04c3fSmrg   OPC(ENDLOOP),
49801e04c3fSmrg   OPC(SQRT),
49901e04c3fSmrg   OPC(SIN),
50001e04c3fSmrg   OPC(COS),
50101e04c3fSmrg   OPC(FLOOR),
50201e04c3fSmrg   OPC(CEIL),
50301e04c3fSmrg   OPC(SIGN),
50401e04c3fSmrg   OPC(I2F),
5057ec681f3Smrg   OPC(F2I),
50601e04c3fSmrg   OPC(CMP),
50701e04c3fSmrg   OPC(LOAD),
50801e04c3fSmrg   OPC(STORE),
50901e04c3fSmrg   OPC(IMULLO0),
51001e04c3fSmrg   OPC(IMULHI0),
5117ec681f3Smrg   OPC(IMADLO0),
5127ec681f3Smrg   OPC(IMADHI0),
51301e04c3fSmrg   OPC(LEADZERO),
51401e04c3fSmrg   OPC(LSHIFT),
51501e04c3fSmrg   OPC(RSHIFT),
51601e04c3fSmrg   OPC(ROTATE),
51701e04c3fSmrg   OPC(OR),
51801e04c3fSmrg   OPC(AND),
51901e04c3fSmrg   OPC(XOR),
52001e04c3fSmrg   OPC(NOT),
52101e04c3fSmrg   OPC(DP2),
5227ec681f3Smrg   OPC(DIV),
5237ec681f3Smrg   OPC(IABS),
52401e04c3fSmrg};
52501e04c3fSmrg
52601e04c3fSmrgstatic void
52701e04c3fSmrgprint_instr(uint32_t *dwords, int n, enum debug_t debug)
52801e04c3fSmrg{
52901e04c3fSmrg   struct instr *instr = (struct instr *)dwords;
53001e04c3fSmrg   const unsigned opc = instr->opc | (instr->opcode_bit6 << 6);
53101e04c3fSmrg   const char *name = opcs[opc].name;
53201e04c3fSmrg
53301e04c3fSmrg   printf("%04d: ", n);
53401e04c3fSmrg   if (debug & PRINT_RAW)
53501e04c3fSmrg      printf("%08x %08x %08x %08x  ", dwords[0], dwords[1], dwords[2],
53601e04c3fSmrg             dwords[3]);
53701e04c3fSmrg
53801e04c3fSmrg   if (name) {
53901e04c3fSmrg
5407ec681f3Smrg      struct etna_inst_dst dst = {
54101e04c3fSmrg         .use = instr->dst_use,
54201e04c3fSmrg         .amode = instr->dst_amode,
54301e04c3fSmrg         .reg = instr->dst_reg,
5447ec681f3Smrg         .write_mask = instr->dst_comps
54501e04c3fSmrg      };
54601e04c3fSmrg
5477ec681f3Smrg      struct etna_inst_tex tex = {
54801e04c3fSmrg         .id = instr->tex_id,
54901e04c3fSmrg         .amode = instr->tex_amode,
55001e04c3fSmrg         .swiz = instr->tex_swiz,
55101e04c3fSmrg      };
55201e04c3fSmrg
5537ec681f3Smrg      struct etna_inst_src src0 = {
55401e04c3fSmrg         .use = instr->src0_use,
55501e04c3fSmrg         .neg = instr->src0_neg,
55601e04c3fSmrg         .abs = instr->src0_abs,
55701e04c3fSmrg         .rgroup = instr->src0_rgroup,
55801e04c3fSmrg         .reg = instr->src0_reg,
55901e04c3fSmrg         .swiz = instr->src0_swiz,
56001e04c3fSmrg         .amode = instr->src0_amode,
56101e04c3fSmrg      };
56201e04c3fSmrg
5637ec681f3Smrg      struct etna_inst_src src1 = {
56401e04c3fSmrg         .use = instr->src1_use,
56501e04c3fSmrg         .neg = instr->src1_neg,
56601e04c3fSmrg         .abs = instr->src1_abs,
56701e04c3fSmrg         .rgroup = instr->src1_rgroup,
56801e04c3fSmrg         .reg = instr->src1_reg,
56901e04c3fSmrg         .swiz = instr->src1_swiz,
57001e04c3fSmrg         .amode = instr->src1_amode,
57101e04c3fSmrg      };
57201e04c3fSmrg
5737ec681f3Smrg      struct etna_inst_src src2 = {
57401e04c3fSmrg         .use = instr->src2_use,
57501e04c3fSmrg         .neg = instr->src2_neg,
57601e04c3fSmrg         .abs = instr->src2_abs,
57701e04c3fSmrg         .rgroup = instr->src2_rgroup,
57801e04c3fSmrg         .reg = instr->src2_reg,
57901e04c3fSmrg         .swiz = instr->src2_swiz,
58001e04c3fSmrg         .amode = instr->src2_amode,
58101e04c3fSmrg      };
58201e04c3fSmrg
58301e04c3fSmrg      int imm = (instr->dword3 & VIV_ISA_WORD_3_SRC2_IMM__MASK)
58401e04c3fSmrg                >> VIV_ISA_WORD_3_SRC2_IMM__SHIFT;
58501e04c3fSmrg
58601e04c3fSmrg      struct opc_operands operands = {
58701e04c3fSmrg         .dst = &dst,
58801e04c3fSmrg         .tex = &tex,
58901e04c3fSmrg         .src0 = &src0,
59001e04c3fSmrg         .src1 = &src1,
59101e04c3fSmrg         .src2 = &src2,
59201e04c3fSmrg         .imm = imm,
59301e04c3fSmrg      };
59401e04c3fSmrg
59501e04c3fSmrg      uint8_t type = instr->type_bit01 | (instr->type_bit2 << 2);
59601e04c3fSmrg
59701e04c3fSmrg      printf("%s", name);
59801e04c3fSmrg      printf_type(type);
59901e04c3fSmrg      if (instr->sat)
60001e04c3fSmrg         printf(".SAT");
60101e04c3fSmrg      print_condition(instr->cond);
60201e04c3fSmrg      printf(" ");
6037ec681f3Smrg      if (instr->sel_0)
6047ec681f3Smrg         printf("SEL_0 ");
6057ec681f3Smrg      if (instr->sel_1)
6067ec681f3Smrg         printf("SEL_1 ");
6077ec681f3Smrg      if (instr->dst_full)
6087ec681f3Smrg         printf("DST_FULL ");
60901e04c3fSmrg      opcs[opc].print(&operands);
61001e04c3fSmrg   } else {
61101e04c3fSmrg      printf("unknown (%d)", instr->opc);
61201e04c3fSmrg   }
61301e04c3fSmrg
61401e04c3fSmrg   printf("\n");
61501e04c3fSmrg}
61601e04c3fSmrg
61701e04c3fSmrgvoid
61801e04c3fSmrgetna_disasm(uint32_t *dwords, int sizedwords, enum debug_t debug)
61901e04c3fSmrg{
62001e04c3fSmrg   unsigned i;
62101e04c3fSmrg
62201e04c3fSmrg   assert((sizedwords % 2) == 0);
62301e04c3fSmrg
62401e04c3fSmrg   for (i = 0; i < sizedwords; i += 4)
62501e04c3fSmrg      print_instr(&dwords[i], i / 4, debug);
62601e04c3fSmrg}
627