1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright (c) 2016 Etnaviv Project
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sub license,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the
12bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
13bf215546Sopenharmony_ci * of the Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21bf215546Sopenharmony_ci * DEALINGS IN THE SOFTWARE.
22bf215546Sopenharmony_ci *
23bf215546Sopenharmony_ci * Authors:
24bf215546Sopenharmony_ci *    Christian Gmeiner <christian.gmeiner@gmail.com>
25bf215546Sopenharmony_ci */
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_ci#include "etnaviv_disasm.h"
28bf215546Sopenharmony_ci#include "etnaviv_asm.h"
29bf215546Sopenharmony_ci
30bf215546Sopenharmony_ci#include <assert.h>
31bf215546Sopenharmony_ci#include <stdbool.h>
32bf215546Sopenharmony_ci#include <stdio.h>
33bf215546Sopenharmony_ci#include <stdlib.h>
34bf215546Sopenharmony_ci
35bf215546Sopenharmony_ci#include "hw/isa.xml.h"
36bf215546Sopenharmony_ci#include "util/u_math.h"
37bf215546Sopenharmony_ci#include "util/half_float.h"
38bf215546Sopenharmony_ci
39bf215546Sopenharmony_cistruct instr {
40bf215546Sopenharmony_ci   /* dword0: */
41bf215546Sopenharmony_ci   uint32_t opc         : 6;
42bf215546Sopenharmony_ci   uint32_t cond        : 5;
43bf215546Sopenharmony_ci   uint32_t sat         : 1;
44bf215546Sopenharmony_ci   uint32_t dst_use     : 1;
45bf215546Sopenharmony_ci   uint32_t dst_amode   : 3;
46bf215546Sopenharmony_ci   uint32_t dst_reg     : 7;
47bf215546Sopenharmony_ci   uint32_t dst_comps   : 4;
48bf215546Sopenharmony_ci   uint32_t tex_id      : 5;
49bf215546Sopenharmony_ci
50bf215546Sopenharmony_ci   /* dword1: */
51bf215546Sopenharmony_ci   uint32_t tex_amode   : 3;
52bf215546Sopenharmony_ci   uint32_t tex_swiz    : 8;
53bf215546Sopenharmony_ci   uint32_t src0_use    : 1;
54bf215546Sopenharmony_ci   uint32_t src0_reg    : 9;
55bf215546Sopenharmony_ci   uint32_t type_bit2   : 1;
56bf215546Sopenharmony_ci   uint32_t src0_swiz   : 8;
57bf215546Sopenharmony_ci   uint32_t src0_neg    : 1;
58bf215546Sopenharmony_ci   uint32_t src0_abs    : 1;
59bf215546Sopenharmony_ci
60bf215546Sopenharmony_ci   /* dword2: */
61bf215546Sopenharmony_ci   uint32_t src0_amode  : 3;
62bf215546Sopenharmony_ci   uint32_t src0_rgroup : 3;
63bf215546Sopenharmony_ci   uint32_t src1_use    : 1;
64bf215546Sopenharmony_ci   uint32_t src1_reg    : 9;
65bf215546Sopenharmony_ci   uint32_t opcode_bit6 : 1;
66bf215546Sopenharmony_ci   uint32_t src1_swiz   : 8;
67bf215546Sopenharmony_ci   uint32_t src1_neg    : 1;
68bf215546Sopenharmony_ci   uint32_t src1_abs    : 1;
69bf215546Sopenharmony_ci   uint32_t src1_amode  : 3;
70bf215546Sopenharmony_ci   uint32_t type_bit01  : 2;
71bf215546Sopenharmony_ci
72bf215546Sopenharmony_ci   /* dword3: */
73bf215546Sopenharmony_ci   union {
74bf215546Sopenharmony_ci      struct {
75bf215546Sopenharmony_ci         uint32_t src1_rgroup : 3;
76bf215546Sopenharmony_ci         uint32_t src2_use    : 1;
77bf215546Sopenharmony_ci         uint32_t src2_reg    : 9;
78bf215546Sopenharmony_ci         uint32_t sel_0       : 1;
79bf215546Sopenharmony_ci         uint32_t src2_swiz   : 8;
80bf215546Sopenharmony_ci         uint32_t src2_neg    : 1;
81bf215546Sopenharmony_ci         uint32_t src2_abs    : 1;
82bf215546Sopenharmony_ci         uint32_t sel_1       : 1;
83bf215546Sopenharmony_ci         uint32_t src2_amode  : 3;
84bf215546Sopenharmony_ci         uint32_t src2_rgroup : 3;
85bf215546Sopenharmony_ci         uint32_t dst_full    : 1;
86bf215546Sopenharmony_ci      };
87bf215546Sopenharmony_ci      uint32_t dword3;
88bf215546Sopenharmony_ci   };
89bf215546Sopenharmony_ci};
90bf215546Sopenharmony_cistruct opc_operands {
91bf215546Sopenharmony_ci   struct etna_inst_dst *dst;
92bf215546Sopenharmony_ci   struct etna_inst_tex *tex;
93bf215546Sopenharmony_ci   struct etna_inst_src *src0;
94bf215546Sopenharmony_ci   struct etna_inst_src *src1;
95bf215546Sopenharmony_ci   struct etna_inst_src *src2;
96bf215546Sopenharmony_ci
97bf215546Sopenharmony_ci   int imm;
98bf215546Sopenharmony_ci};
99bf215546Sopenharmony_ci
100bf215546Sopenharmony_cistatic void
101bf215546Sopenharmony_ciprintf_type(uint8_t type)
102bf215546Sopenharmony_ci{
103bf215546Sopenharmony_ci   switch(type) {
104bf215546Sopenharmony_ci   case INST_TYPE_F32:
105bf215546Sopenharmony_ci      /* as f32 is the default print nothing */
106bf215546Sopenharmony_ci      break;
107bf215546Sopenharmony_ci
108bf215546Sopenharmony_ci   case INST_TYPE_S32:
109bf215546Sopenharmony_ci      printf(".s32");
110bf215546Sopenharmony_ci      break;
111bf215546Sopenharmony_ci
112bf215546Sopenharmony_ci   case INST_TYPE_S8:
113bf215546Sopenharmony_ci      printf(".s8");
114bf215546Sopenharmony_ci      break;
115bf215546Sopenharmony_ci
116bf215546Sopenharmony_ci   case INST_TYPE_U16:
117bf215546Sopenharmony_ci      printf(".u16");
118bf215546Sopenharmony_ci      break;
119bf215546Sopenharmony_ci
120bf215546Sopenharmony_ci   case INST_TYPE_F16:
121bf215546Sopenharmony_ci      printf(".f16");
122bf215546Sopenharmony_ci      break;
123bf215546Sopenharmony_ci
124bf215546Sopenharmony_ci   case INST_TYPE_S16:
125bf215546Sopenharmony_ci      printf(".s16");
126bf215546Sopenharmony_ci      break;
127bf215546Sopenharmony_ci
128bf215546Sopenharmony_ci   case INST_TYPE_U32:
129bf215546Sopenharmony_ci      printf(".u32");
130bf215546Sopenharmony_ci      break;
131bf215546Sopenharmony_ci
132bf215546Sopenharmony_ci   case INST_TYPE_U8:
133bf215546Sopenharmony_ci      printf(".u8");
134bf215546Sopenharmony_ci      break;
135bf215546Sopenharmony_ci
136bf215546Sopenharmony_ci   default:
137bf215546Sopenharmony_ci      abort();
138bf215546Sopenharmony_ci      break;
139bf215546Sopenharmony_ci   }
140bf215546Sopenharmony_ci}
141bf215546Sopenharmony_ci
142bf215546Sopenharmony_cistatic void
143bf215546Sopenharmony_ciprint_condition(uint8_t condition)
144bf215546Sopenharmony_ci{
145bf215546Sopenharmony_ci   switch (condition) {
146bf215546Sopenharmony_ci   case INST_CONDITION_TRUE:
147bf215546Sopenharmony_ci      break;
148bf215546Sopenharmony_ci
149bf215546Sopenharmony_ci   case INST_CONDITION_GT:
150bf215546Sopenharmony_ci      printf(".GT");
151bf215546Sopenharmony_ci      break;
152bf215546Sopenharmony_ci
153bf215546Sopenharmony_ci   case INST_CONDITION_LT:
154bf215546Sopenharmony_ci      printf(".LT");
155bf215546Sopenharmony_ci      break;
156bf215546Sopenharmony_ci
157bf215546Sopenharmony_ci   case INST_CONDITION_GE:
158bf215546Sopenharmony_ci      printf(".GE");
159bf215546Sopenharmony_ci      break;
160bf215546Sopenharmony_ci
161bf215546Sopenharmony_ci   case INST_CONDITION_LE:
162bf215546Sopenharmony_ci      printf(".LE");
163bf215546Sopenharmony_ci      break;
164bf215546Sopenharmony_ci
165bf215546Sopenharmony_ci   case INST_CONDITION_EQ:
166bf215546Sopenharmony_ci      printf(".EQ");
167bf215546Sopenharmony_ci      break;
168bf215546Sopenharmony_ci
169bf215546Sopenharmony_ci   case INST_CONDITION_NE:
170bf215546Sopenharmony_ci      printf(".NE");
171bf215546Sopenharmony_ci      break;
172bf215546Sopenharmony_ci
173bf215546Sopenharmony_ci   case INST_CONDITION_AND:
174bf215546Sopenharmony_ci      printf(".AND");
175bf215546Sopenharmony_ci      break;
176bf215546Sopenharmony_ci
177bf215546Sopenharmony_ci   case INST_CONDITION_OR:
178bf215546Sopenharmony_ci      printf(".OR");
179bf215546Sopenharmony_ci      break;
180bf215546Sopenharmony_ci
181bf215546Sopenharmony_ci   case INST_CONDITION_XOR:
182bf215546Sopenharmony_ci      printf(".XOR");
183bf215546Sopenharmony_ci      break;
184bf215546Sopenharmony_ci
185bf215546Sopenharmony_ci   case INST_CONDITION_NOT:
186bf215546Sopenharmony_ci      printf(".NOT");
187bf215546Sopenharmony_ci      break;
188bf215546Sopenharmony_ci
189bf215546Sopenharmony_ci   case INST_CONDITION_NZ:
190bf215546Sopenharmony_ci      printf(".NZ");
191bf215546Sopenharmony_ci      break;
192bf215546Sopenharmony_ci
193bf215546Sopenharmony_ci   case INST_CONDITION_GEZ:
194bf215546Sopenharmony_ci      printf(".GEZ");
195bf215546Sopenharmony_ci      break;
196bf215546Sopenharmony_ci
197bf215546Sopenharmony_ci   case INST_CONDITION_GZ:
198bf215546Sopenharmony_ci      printf(".GZ");
199bf215546Sopenharmony_ci      break;
200bf215546Sopenharmony_ci
201bf215546Sopenharmony_ci   case INST_CONDITION_LEZ:
202bf215546Sopenharmony_ci      printf(".LEZ");
203bf215546Sopenharmony_ci      break;
204bf215546Sopenharmony_ci
205bf215546Sopenharmony_ci   case INST_CONDITION_LZ:
206bf215546Sopenharmony_ci      printf(".LZ");
207bf215546Sopenharmony_ci      break;
208bf215546Sopenharmony_ci
209bf215546Sopenharmony_ci   default:
210bf215546Sopenharmony_ci      abort();
211bf215546Sopenharmony_ci      break;
212bf215546Sopenharmony_ci   }
213bf215546Sopenharmony_ci}
214bf215546Sopenharmony_ci
215bf215546Sopenharmony_cistatic void
216bf215546Sopenharmony_ciprint_rgroup(uint8_t rgoup)
217bf215546Sopenharmony_ci{
218bf215546Sopenharmony_ci   switch (rgoup) {
219bf215546Sopenharmony_ci   case INST_RGROUP_TEMP:
220bf215546Sopenharmony_ci      printf("t");
221bf215546Sopenharmony_ci      break;
222bf215546Sopenharmony_ci
223bf215546Sopenharmony_ci   case INST_RGROUP_INTERNAL:
224bf215546Sopenharmony_ci      printf("i");
225bf215546Sopenharmony_ci      break;
226bf215546Sopenharmony_ci
227bf215546Sopenharmony_ci   case INST_RGROUP_UNIFORM_0:
228bf215546Sopenharmony_ci   case INST_RGROUP_UNIFORM_1:
229bf215546Sopenharmony_ci      printf("u");
230bf215546Sopenharmony_ci      break;
231bf215546Sopenharmony_ci   case 4:
232bf215546Sopenharmony_ci      printf("th");
233bf215546Sopenharmony_ci      break;
234bf215546Sopenharmony_ci   }
235bf215546Sopenharmony_ci}
236bf215546Sopenharmony_ci
237bf215546Sopenharmony_cistatic void
238bf215546Sopenharmony_ciprint_components(uint8_t components)
239bf215546Sopenharmony_ci{
240bf215546Sopenharmony_ci   if (components == 15)
241bf215546Sopenharmony_ci      return;
242bf215546Sopenharmony_ci
243bf215546Sopenharmony_ci   printf(".");
244bf215546Sopenharmony_ci   if (components & INST_COMPS_X)
245bf215546Sopenharmony_ci      printf("x");
246bf215546Sopenharmony_ci   else
247bf215546Sopenharmony_ci      printf("_");
248bf215546Sopenharmony_ci
249bf215546Sopenharmony_ci   if (components & INST_COMPS_Y)
250bf215546Sopenharmony_ci      printf("y");
251bf215546Sopenharmony_ci   else
252bf215546Sopenharmony_ci      printf("_");
253bf215546Sopenharmony_ci
254bf215546Sopenharmony_ci   if (components & INST_COMPS_Z)
255bf215546Sopenharmony_ci      printf("z");
256bf215546Sopenharmony_ci   else
257bf215546Sopenharmony_ci      printf("_");
258bf215546Sopenharmony_ci
259bf215546Sopenharmony_ci   if (components & INST_COMPS_W)
260bf215546Sopenharmony_ci      printf("w");
261bf215546Sopenharmony_ci   else
262bf215546Sopenharmony_ci      printf("_");
263bf215546Sopenharmony_ci}
264bf215546Sopenharmony_ci
265bf215546Sopenharmony_cistatic inline void
266bf215546Sopenharmony_ciprint_swiz_comp(uint8_t swiz_comp)
267bf215546Sopenharmony_ci{
268bf215546Sopenharmony_ci   switch (swiz_comp) {
269bf215546Sopenharmony_ci   case INST_SWIZ_COMP_X:
270bf215546Sopenharmony_ci      printf("x");
271bf215546Sopenharmony_ci      break;
272bf215546Sopenharmony_ci
273bf215546Sopenharmony_ci   case INST_SWIZ_COMP_Y:
274bf215546Sopenharmony_ci      printf("y");
275bf215546Sopenharmony_ci      break;
276bf215546Sopenharmony_ci
277bf215546Sopenharmony_ci   case INST_SWIZ_COMP_Z:
278bf215546Sopenharmony_ci      printf("z");
279bf215546Sopenharmony_ci      break;
280bf215546Sopenharmony_ci
281bf215546Sopenharmony_ci   case INST_SWIZ_COMP_W:
282bf215546Sopenharmony_ci      printf("w");
283bf215546Sopenharmony_ci      break;
284bf215546Sopenharmony_ci
285bf215546Sopenharmony_ci   default:
286bf215546Sopenharmony_ci      abort();
287bf215546Sopenharmony_ci      break;
288bf215546Sopenharmony_ci   }
289bf215546Sopenharmony_ci}
290bf215546Sopenharmony_ci
291bf215546Sopenharmony_cistatic void
292bf215546Sopenharmony_ciprint_swiz(uint8_t swiz)
293bf215546Sopenharmony_ci{
294bf215546Sopenharmony_ci   // if a null swizzle
295bf215546Sopenharmony_ci   if (swiz == 0xe4)
296bf215546Sopenharmony_ci      return;
297bf215546Sopenharmony_ci
298bf215546Sopenharmony_ci   const unsigned x = swiz & 0x3;
299bf215546Sopenharmony_ci   const unsigned y = (swiz & 0x0C) >> 2;
300bf215546Sopenharmony_ci   const unsigned z = (swiz & 0x30) >> 4;
301bf215546Sopenharmony_ci   const unsigned w = (swiz & 0xc0) >> 6;
302bf215546Sopenharmony_ci
303bf215546Sopenharmony_ci   printf(".");
304bf215546Sopenharmony_ci   print_swiz_comp(x);
305bf215546Sopenharmony_ci   print_swiz_comp(y);
306bf215546Sopenharmony_ci   print_swiz_comp(z);
307bf215546Sopenharmony_ci   print_swiz_comp(w);
308bf215546Sopenharmony_ci}
309bf215546Sopenharmony_ci
310bf215546Sopenharmony_cistatic void
311bf215546Sopenharmony_ciprint_amode(uint8_t amode)
312bf215546Sopenharmony_ci{
313bf215546Sopenharmony_ci   switch (amode) {
314bf215546Sopenharmony_ci   case INST_AMODE_DIRECT:
315bf215546Sopenharmony_ci      /* nothing to output */
316bf215546Sopenharmony_ci      break;
317bf215546Sopenharmony_ci
318bf215546Sopenharmony_ci   case INST_AMODE_ADD_A_X:
319bf215546Sopenharmony_ci      printf("[a.x]");
320bf215546Sopenharmony_ci      break;
321bf215546Sopenharmony_ci
322bf215546Sopenharmony_ci   case INST_AMODE_ADD_A_Y:
323bf215546Sopenharmony_ci      printf("[a.y]");
324bf215546Sopenharmony_ci      break;
325bf215546Sopenharmony_ci
326bf215546Sopenharmony_ci   case INST_AMODE_ADD_A_Z:
327bf215546Sopenharmony_ci      printf("[a.z]");
328bf215546Sopenharmony_ci      break;
329bf215546Sopenharmony_ci
330bf215546Sopenharmony_ci   case INST_AMODE_ADD_A_W:
331bf215546Sopenharmony_ci      printf("[a.w]");
332bf215546Sopenharmony_ci      break;
333bf215546Sopenharmony_ci
334bf215546Sopenharmony_ci   default:
335bf215546Sopenharmony_ci      abort();
336bf215546Sopenharmony_ci      break;
337bf215546Sopenharmony_ci   }
338bf215546Sopenharmony_ci}
339bf215546Sopenharmony_ci
340bf215546Sopenharmony_cistatic void
341bf215546Sopenharmony_ciprint_dst(struct etna_inst_dst *dst, bool sep)
342bf215546Sopenharmony_ci{
343bf215546Sopenharmony_ci   if (dst->use) {
344bf215546Sopenharmony_ci      printf("t%u", dst->reg);
345bf215546Sopenharmony_ci      print_amode(dst->amode);
346bf215546Sopenharmony_ci      print_components(dst->write_mask);
347bf215546Sopenharmony_ci   } else {
348bf215546Sopenharmony_ci      printf("void");
349bf215546Sopenharmony_ci   }
350bf215546Sopenharmony_ci
351bf215546Sopenharmony_ci   if (sep)
352bf215546Sopenharmony_ci      printf(", ");
353bf215546Sopenharmony_ci}
354bf215546Sopenharmony_ci
355bf215546Sopenharmony_cistatic void
356bf215546Sopenharmony_ciprint_tex(struct etna_inst_tex *tex, bool sep)
357bf215546Sopenharmony_ci{
358bf215546Sopenharmony_ci   printf("tex%u", tex->id);
359bf215546Sopenharmony_ci   print_amode(tex->amode);
360bf215546Sopenharmony_ci   print_swiz(tex->swiz);
361bf215546Sopenharmony_ci
362bf215546Sopenharmony_ci   if (sep)
363bf215546Sopenharmony_ci      printf(", ");
364bf215546Sopenharmony_ci}
365bf215546Sopenharmony_ci
366bf215546Sopenharmony_cistatic void
367bf215546Sopenharmony_ciprint_src(struct etna_inst_src *src, bool sep)
368bf215546Sopenharmony_ci{
369bf215546Sopenharmony_ci   if (src->use) {
370bf215546Sopenharmony_ci      if (src->rgroup == INST_RGROUP_IMMEDIATE) {
371bf215546Sopenharmony_ci         switch (src->imm_type) {
372bf215546Sopenharmony_ci         case 0: /* float */
373bf215546Sopenharmony_ci            printf("%f", uif(src->imm_val << 12));
374bf215546Sopenharmony_ci            break;
375bf215546Sopenharmony_ci         case 1: /* signed */
376bf215546Sopenharmony_ci            printf("%d", ((int) src->imm_val << 12) >> 12);
377bf215546Sopenharmony_ci            break;
378bf215546Sopenharmony_ci         case 2: /* unsigned */
379bf215546Sopenharmony_ci            printf("%d", src->imm_val);
380bf215546Sopenharmony_ci            break;
381bf215546Sopenharmony_ci         case 3: /* 16-bit */
382bf215546Sopenharmony_ci            printf("%f/%.5X", _mesa_half_to_float(src->imm_val), src->imm_val);
383bf215546Sopenharmony_ci            break;
384bf215546Sopenharmony_ci         }
385bf215546Sopenharmony_ci      } else {
386bf215546Sopenharmony_ci         if (src->neg)
387bf215546Sopenharmony_ci            printf("-");
388bf215546Sopenharmony_ci
389bf215546Sopenharmony_ci         if (src->abs)
390bf215546Sopenharmony_ci            printf("|");
391bf215546Sopenharmony_ci
392bf215546Sopenharmony_ci         if (src->rgroup == INST_RGROUP_UNIFORM_1)
393bf215546Sopenharmony_ci            src->reg += 128;
394bf215546Sopenharmony_ci
395bf215546Sopenharmony_ci         print_rgroup(src->rgroup);
396bf215546Sopenharmony_ci         printf("%u", src->reg);
397bf215546Sopenharmony_ci         print_amode(src->amode);
398bf215546Sopenharmony_ci         print_swiz(src->swiz);
399bf215546Sopenharmony_ci
400bf215546Sopenharmony_ci         if (src->abs)
401bf215546Sopenharmony_ci            printf("|");
402bf215546Sopenharmony_ci      }
403bf215546Sopenharmony_ci   } else {
404bf215546Sopenharmony_ci      printf("void");
405bf215546Sopenharmony_ci   }
406bf215546Sopenharmony_ci
407bf215546Sopenharmony_ci   if (sep)
408bf215546Sopenharmony_ci      printf(", ");
409bf215546Sopenharmony_ci}
410bf215546Sopenharmony_ci
411bf215546Sopenharmony_cistatic void
412bf215546Sopenharmony_ciprint_opc_default(struct opc_operands *operands)
413bf215546Sopenharmony_ci{
414bf215546Sopenharmony_ci   print_dst(operands->dst, true);
415bf215546Sopenharmony_ci   print_src(operands->src0, true);
416bf215546Sopenharmony_ci   print_src(operands->src1, true);
417bf215546Sopenharmony_ci   print_src(operands->src2, false);
418bf215546Sopenharmony_ci}
419bf215546Sopenharmony_ci
420bf215546Sopenharmony_cistatic void
421bf215546Sopenharmony_ciprint_opc_mov(struct opc_operands *operands)
422bf215546Sopenharmony_ci{
423bf215546Sopenharmony_ci   // dst (areg)
424bf215546Sopenharmony_ci   printf("a%u", operands->dst->reg);
425bf215546Sopenharmony_ci   print_components(operands->dst->write_mask);
426bf215546Sopenharmony_ci   printf(", ");
427bf215546Sopenharmony_ci
428bf215546Sopenharmony_ci   print_src(operands->src0, true);
429bf215546Sopenharmony_ci   print_src(operands->src1, true);
430bf215546Sopenharmony_ci   print_src(operands->src2, false);
431bf215546Sopenharmony_ci}
432bf215546Sopenharmony_ci
433bf215546Sopenharmony_cistatic void
434bf215546Sopenharmony_ciprint_opc_tex(struct opc_operands *operands)
435bf215546Sopenharmony_ci{
436bf215546Sopenharmony_ci   print_dst(operands->dst, true);
437bf215546Sopenharmony_ci   print_tex(operands->tex, true);
438bf215546Sopenharmony_ci   print_src(operands->src0, true);
439bf215546Sopenharmony_ci   print_src(operands->src1, true);
440bf215546Sopenharmony_ci   print_src(operands->src2, false);
441bf215546Sopenharmony_ci}
442bf215546Sopenharmony_ci
443bf215546Sopenharmony_cistatic void
444bf215546Sopenharmony_ciprint_opc_imm(struct opc_operands *operands)
445bf215546Sopenharmony_ci{
446bf215546Sopenharmony_ci   print_dst(operands->dst, true);
447bf215546Sopenharmony_ci   print_src(operands->src0, true);
448bf215546Sopenharmony_ci   print_src(operands->src1, true);
449bf215546Sopenharmony_ci   printf("label_%04d", operands->imm);
450bf215546Sopenharmony_ci}
451bf215546Sopenharmony_ci
452bf215546Sopenharmony_ci#define OPC_BITS 7
453bf215546Sopenharmony_ci
454bf215546Sopenharmony_cistatic const struct opc_info {
455bf215546Sopenharmony_ci   const char *name;
456bf215546Sopenharmony_ci   void (*print)(struct opc_operands *operands);
457bf215546Sopenharmony_ci} opcs[1 << OPC_BITS] = {
458bf215546Sopenharmony_ci#define OPC(opc) [INST_OPCODE_##opc] = {#opc, print_opc_default}
459bf215546Sopenharmony_ci#define OPC_MOV(opc) [INST_OPCODE_##opc] = {#opc, print_opc_mov}
460bf215546Sopenharmony_ci#define OPC_TEX(opc) [INST_OPCODE_##opc] = {#opc, print_opc_tex}
461bf215546Sopenharmony_ci#define OPC_IMM(opc) [INST_OPCODE_##opc] = {#opc, print_opc_imm}
462bf215546Sopenharmony_ci   OPC(NOP),
463bf215546Sopenharmony_ci   OPC(ADD),
464bf215546Sopenharmony_ci   OPC(MAD),
465bf215546Sopenharmony_ci   OPC(MUL),
466bf215546Sopenharmony_ci   OPC(DST),
467bf215546Sopenharmony_ci   OPC(DP3),
468bf215546Sopenharmony_ci   OPC(DP4),
469bf215546Sopenharmony_ci   OPC(DSX),
470bf215546Sopenharmony_ci   OPC(DSY),
471bf215546Sopenharmony_ci   OPC(MOV),
472bf215546Sopenharmony_ci   OPC_MOV(MOVAR),
473bf215546Sopenharmony_ci   OPC_MOV(MOVAF),
474bf215546Sopenharmony_ci   OPC_MOV(MOVAI),
475bf215546Sopenharmony_ci   OPC(RCP),
476bf215546Sopenharmony_ci   OPC(RSQ),
477bf215546Sopenharmony_ci   OPC(LITP),
478bf215546Sopenharmony_ci   OPC(SELECT),
479bf215546Sopenharmony_ci   OPC(SET),
480bf215546Sopenharmony_ci   OPC(EXP),
481bf215546Sopenharmony_ci   OPC(LOG),
482bf215546Sopenharmony_ci   OPC(FRC),
483bf215546Sopenharmony_ci   OPC_IMM(CALL),
484bf215546Sopenharmony_ci   OPC(RET),
485bf215546Sopenharmony_ci   OPC_IMM(BRANCH),
486bf215546Sopenharmony_ci   OPC_TEX(TEXKILL),
487bf215546Sopenharmony_ci   OPC_TEX(TEXLD),
488bf215546Sopenharmony_ci   OPC_TEX(TEXLDB),
489bf215546Sopenharmony_ci   OPC_TEX(TEXLDD),
490bf215546Sopenharmony_ci   OPC_TEX(TEXLDL),
491bf215546Sopenharmony_ci   OPC_TEX(TEXLDPCF),
492bf215546Sopenharmony_ci   OPC_TEX(TEXLDLPCF),
493bf215546Sopenharmony_ci   OPC_TEX(TEXLDGPCF),
494bf215546Sopenharmony_ci   OPC(REP),
495bf215546Sopenharmony_ci   OPC(ENDREP),
496bf215546Sopenharmony_ci   OPC(LOOP),
497bf215546Sopenharmony_ci   OPC(ENDLOOP),
498bf215546Sopenharmony_ci   OPC(SQRT),
499bf215546Sopenharmony_ci   OPC(SIN),
500bf215546Sopenharmony_ci   OPC(COS),
501bf215546Sopenharmony_ci   OPC(FLOOR),
502bf215546Sopenharmony_ci   OPC(CEIL),
503bf215546Sopenharmony_ci   OPC(SIGN),
504bf215546Sopenharmony_ci   OPC(I2F),
505bf215546Sopenharmony_ci   OPC(F2I),
506bf215546Sopenharmony_ci   OPC(CMP),
507bf215546Sopenharmony_ci   OPC(LOAD),
508bf215546Sopenharmony_ci   OPC(STORE),
509bf215546Sopenharmony_ci   OPC(IMULLO0),
510bf215546Sopenharmony_ci   OPC(IMULHI0),
511bf215546Sopenharmony_ci   OPC(IMADLO0),
512bf215546Sopenharmony_ci   OPC(IMADHI0),
513bf215546Sopenharmony_ci   OPC(LEADZERO),
514bf215546Sopenharmony_ci   OPC(LSHIFT),
515bf215546Sopenharmony_ci   OPC(RSHIFT),
516bf215546Sopenharmony_ci   OPC(ROTATE),
517bf215546Sopenharmony_ci   OPC(OR),
518bf215546Sopenharmony_ci   OPC(AND),
519bf215546Sopenharmony_ci   OPC(XOR),
520bf215546Sopenharmony_ci   OPC(NOT),
521bf215546Sopenharmony_ci   OPC(DP2),
522bf215546Sopenharmony_ci   OPC(DIV),
523bf215546Sopenharmony_ci   OPC(IABS),
524bf215546Sopenharmony_ci};
525bf215546Sopenharmony_ci
526bf215546Sopenharmony_cistatic void
527bf215546Sopenharmony_ciprint_instr(uint32_t *dwords, int n, enum debug_t debug)
528bf215546Sopenharmony_ci{
529bf215546Sopenharmony_ci   struct instr *instr = (struct instr *)dwords;
530bf215546Sopenharmony_ci   const unsigned opc = instr->opc | (instr->opcode_bit6 << 6);
531bf215546Sopenharmony_ci   const char *name = opcs[opc].name;
532bf215546Sopenharmony_ci
533bf215546Sopenharmony_ci   printf("%04d: ", n);
534bf215546Sopenharmony_ci   if (debug & PRINT_RAW)
535bf215546Sopenharmony_ci      printf("%08x %08x %08x %08x  ", dwords[0], dwords[1], dwords[2],
536bf215546Sopenharmony_ci             dwords[3]);
537bf215546Sopenharmony_ci
538bf215546Sopenharmony_ci   if (name) {
539bf215546Sopenharmony_ci
540bf215546Sopenharmony_ci      struct etna_inst_dst dst = {
541bf215546Sopenharmony_ci         .use = instr->dst_use,
542bf215546Sopenharmony_ci         .amode = instr->dst_amode,
543bf215546Sopenharmony_ci         .reg = instr->dst_reg,
544bf215546Sopenharmony_ci         .write_mask = instr->dst_comps
545bf215546Sopenharmony_ci      };
546bf215546Sopenharmony_ci
547bf215546Sopenharmony_ci      struct etna_inst_tex tex = {
548bf215546Sopenharmony_ci         .id = instr->tex_id,
549bf215546Sopenharmony_ci         .amode = instr->tex_amode,
550bf215546Sopenharmony_ci         .swiz = instr->tex_swiz,
551bf215546Sopenharmony_ci      };
552bf215546Sopenharmony_ci
553bf215546Sopenharmony_ci      struct etna_inst_src src0 = {
554bf215546Sopenharmony_ci         .use = instr->src0_use,
555bf215546Sopenharmony_ci         .neg = instr->src0_neg,
556bf215546Sopenharmony_ci         .abs = instr->src0_abs,
557bf215546Sopenharmony_ci         .rgroup = instr->src0_rgroup,
558bf215546Sopenharmony_ci         .reg = instr->src0_reg,
559bf215546Sopenharmony_ci         .swiz = instr->src0_swiz,
560bf215546Sopenharmony_ci         .amode = instr->src0_amode,
561bf215546Sopenharmony_ci      };
562bf215546Sopenharmony_ci
563bf215546Sopenharmony_ci      struct etna_inst_src src1 = {
564bf215546Sopenharmony_ci         .use = instr->src1_use,
565bf215546Sopenharmony_ci         .neg = instr->src1_neg,
566bf215546Sopenharmony_ci         .abs = instr->src1_abs,
567bf215546Sopenharmony_ci         .rgroup = instr->src1_rgroup,
568bf215546Sopenharmony_ci         .reg = instr->src1_reg,
569bf215546Sopenharmony_ci         .swiz = instr->src1_swiz,
570bf215546Sopenharmony_ci         .amode = instr->src1_amode,
571bf215546Sopenharmony_ci      };
572bf215546Sopenharmony_ci
573bf215546Sopenharmony_ci      struct etna_inst_src src2 = {
574bf215546Sopenharmony_ci         .use = instr->src2_use,
575bf215546Sopenharmony_ci         .neg = instr->src2_neg,
576bf215546Sopenharmony_ci         .abs = instr->src2_abs,
577bf215546Sopenharmony_ci         .rgroup = instr->src2_rgroup,
578bf215546Sopenharmony_ci         .reg = instr->src2_reg,
579bf215546Sopenharmony_ci         .swiz = instr->src2_swiz,
580bf215546Sopenharmony_ci         .amode = instr->src2_amode,
581bf215546Sopenharmony_ci      };
582bf215546Sopenharmony_ci
583bf215546Sopenharmony_ci      int imm = (instr->dword3 & VIV_ISA_WORD_3_SRC2_IMM__MASK)
584bf215546Sopenharmony_ci                >> VIV_ISA_WORD_3_SRC2_IMM__SHIFT;
585bf215546Sopenharmony_ci
586bf215546Sopenharmony_ci      struct opc_operands operands = {
587bf215546Sopenharmony_ci         .dst = &dst,
588bf215546Sopenharmony_ci         .tex = &tex,
589bf215546Sopenharmony_ci         .src0 = &src0,
590bf215546Sopenharmony_ci         .src1 = &src1,
591bf215546Sopenharmony_ci         .src2 = &src2,
592bf215546Sopenharmony_ci         .imm = imm,
593bf215546Sopenharmony_ci      };
594bf215546Sopenharmony_ci
595bf215546Sopenharmony_ci      uint8_t type = instr->type_bit01 | (instr->type_bit2 << 2);
596bf215546Sopenharmony_ci
597bf215546Sopenharmony_ci      printf("%s", name);
598bf215546Sopenharmony_ci      printf_type(type);
599bf215546Sopenharmony_ci      if (instr->sat)
600bf215546Sopenharmony_ci         printf(".SAT");
601bf215546Sopenharmony_ci      print_condition(instr->cond);
602bf215546Sopenharmony_ci      printf(" ");
603bf215546Sopenharmony_ci      if (instr->sel_0)
604bf215546Sopenharmony_ci         printf("SEL_0 ");
605bf215546Sopenharmony_ci      if (instr->sel_1)
606bf215546Sopenharmony_ci         printf("SEL_1 ");
607bf215546Sopenharmony_ci      if (instr->dst_full)
608bf215546Sopenharmony_ci         printf("DST_FULL ");
609bf215546Sopenharmony_ci      opcs[opc].print(&operands);
610bf215546Sopenharmony_ci   } else {
611bf215546Sopenharmony_ci      printf("unknown (%d)", instr->opc);
612bf215546Sopenharmony_ci   }
613bf215546Sopenharmony_ci
614bf215546Sopenharmony_ci   printf("\n");
615bf215546Sopenharmony_ci}
616bf215546Sopenharmony_ci
617bf215546Sopenharmony_civoid
618bf215546Sopenharmony_cietna_disasm(uint32_t *dwords, int sizedwords, enum debug_t debug)
619bf215546Sopenharmony_ci{
620bf215546Sopenharmony_ci   unsigned i;
621bf215546Sopenharmony_ci
622bf215546Sopenharmony_ci   assert((sizedwords % 2) == 0);
623bf215546Sopenharmony_ci
624bf215546Sopenharmony_ci   for (i = 0; i < sizedwords; i += 4)
625bf215546Sopenharmony_ci      print_instr(&dwords[i], i / 4, debug);
626bf215546Sopenharmony_ci}
627