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