rvdis.c (2424B)
1 // Copyright 2019, Brian Swetland <swetland@frotz.net> 2 // Licensed under the Apache License, Version 2.0. 3 4 #include <string.h> 5 #include <stdio.h> 6 7 #include "riscv.h" 8 9 static char *append_str(char *buf, const char *s) { 10 while (*s) *buf++ = *s++; 11 return buf; 12 } 13 14 static char *append_i32(char *buf, int32_t n) { 15 return buf + sprintf(buf, "%d", n); 16 } 17 18 static char *append_u32(char *buf, int32_t n) { 19 return buf + sprintf(buf, "0x%x", n); 20 } 21 22 static char *append_csr(char *buf, int32_t n) { 23 return buf + sprintf(buf, "0x%03x", n & 0xFFF); 24 } 25 26 static const char* regname_plain[32] = { 27 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", 28 "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", 29 "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", 30 "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31", 31 }; 32 static const char* regname_fancy[32] = { 33 "zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", 34 "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", 35 "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", 36 "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", 37 }; 38 39 static const char** regname = regname_plain; 40 41 const char* rvregname(uint32_t n) { 42 if (n < 32) { 43 return regname[n]; 44 } else { 45 return "??"; 46 } 47 } 48 49 50 typedef struct { 51 uint32_t mask; 52 uint32_t bits; 53 const char* fmt; 54 } rvins_t; 55 56 static rvins_t instab[] = { 57 #include "gen/instab.h" 58 }; 59 60 void rvdis(uint32_t pc, uint32_t ins, char *out) { 61 unsigned n = 0; 62 while ((ins & instab[n].mask) != instab[n].bits) n++; 63 const char* fmt = instab[n].fmt; 64 char c; 65 while ((c = *fmt++) != 0) { 66 if (c != '%') { 67 *out++ = c; 68 continue; 69 } 70 switch (*fmt++) { 71 case '1': out = append_str(out, regname[get_r1(ins)]); break; 72 case '2': out = append_str(out, regname[get_r2(ins)]); break; 73 case 'd': out = append_str(out, regname[get_rd(ins)]); break; 74 case 'i': out = append_i32(out, get_ii(ins)); break; 75 case 'j': out = append_i32(out, get_ij(ins)); break; 76 case 'J': out = append_u32(out, pc + get_ij(ins)); break; 77 case 'b': out = append_i32(out, get_ib(ins)); break; 78 case 'B': out = append_u32(out, pc + get_ib(ins)); break; 79 case 's': out = append_i32(out, get_is(ins)); break; 80 case 'u': out = append_i32(out, get_iu(ins)); break; 81 case 'U': out = append_u32(out, get_iu(ins)); break; 82 case 'c': out = append_i32(out, get_ic(ins)); break; 83 case 'x': out = append_i32(out, get_r2(ins)); break; 84 case 'C': out = append_csr(out, get_ii(ins)); break; 85 } 86 } 87 *out = 0; 88 }