1#ifndef __DISASM_H
2#define __DISASM_H
3
4#include <stdio.h>
5#include <stdint.h>
6#include <inttypes.h>
7#include <assert.h>
8#include <stdbool.h>
9#include <stdlib.h>
10#include <string.h>
11
12#define BIT(b) (1ull << (b))
13#define MASK(count) ((1ull << (count)) - 1)
14#define SEXT(b, count) ((b ^ BIT(count - 1)) - BIT(count - 1))
15#define UNUSED __attribute__((unused))
16
17#define VA_SRC_UNIFORM_TYPE 0x2
18#define VA_SRC_IMM_TYPE 0x3
19
20static inline void
21va_print_dest(FILE *fp, uint8_t dest, bool can_mask)
22{
23   unsigned mask = (dest >> 6);
24   unsigned value = (dest & 0x3F);
25   fprintf(fp, "r%u", value);
26
27   /* Should write at least one component */
28   //	assert(mask != 0);
29   //	assert(mask == 0x3 || can_mask);
30
31   if (mask != 0x3)
32      fprintf(fp, ".h%u", (mask == 1) ? 0 : 1);
33}
34
35void va_disasm_instr(FILE *fp, uint64_t instr);
36
37static inline void
38disassemble_valhall(FILE *fp, const uint64_t *code, unsigned size, bool verbose)
39{
40   assert((size & 7) == 0);
41
42   /* Segment into 8-byte instructions */
43   for (unsigned i = 0; i < (size / 8); ++i) {
44      uint64_t instr = code[i];
45
46      if (instr == 0) {
47         fprintf(fp, "\n");
48         return;
49      }
50
51      if (verbose) {
52         /* Print byte pattern */
53         for (unsigned j = 0; j < 8; ++j)
54            fprintf(fp, "%02x ", (uint8_t) (instr >> (j * 8)));
55
56         fprintf(fp, "   ");
57      } else {
58         /* Print whitespace */
59         fprintf(fp, "   ");
60      }
61
62      va_disasm_instr(fp, instr);
63      fprintf(fp, "\n");
64
65      /* Detect branches */
66      uint64_t opcode = (instr >> 48) & MASK(9);
67      bool branchz = (opcode == 0x1F);
68      bool branchzi = (opcode == 0x2F);
69
70      /* Separate blocks visually by inserting whitespace after branches */
71      if (branchz || branchzi)
72         fprintf(fp, "\n");
73   }
74
75   fprintf(fp, "\n");
76}
77
78#endif
79