risc5dis.c (2128B)
1 // Copyright 2020, 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 "risc5.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 const char* regname[16] = { 23 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 24 "r8", "r9", "r10", "r11", "fp", "sb", "sp", "lr", 25 }; 26 #define R(n) regname[(n) & 15] 27 28 static const char* opname[16] = { 29 "mov", "lsl", "asr", "ror", "and", "ann", "ior", "xor", 30 "add", "sub", "mul", "div", "fad", "fsb", "fml", "fdv", 31 }; 32 #define OP(n) opname[(n) & 15] 33 34 static const char* ccname[16] = { 35 "mi", "eq", "cs", "vs", "ls", "lt", "le", "", 36 "pl", "ne", "cc", "vc", "hi", "ge", "gt", "nv", 37 }; 38 #define CC(n) ccname[(n) & 15] 39 40 typedef struct { 41 uint32_t mask; 42 uint32_t bits; 43 const char* fmt; 44 } ins_t; 45 46 static ins_t instab[] = { 47 #include "../out/risc5ins.h" 48 }; 49 50 void risc5dis(uint32_t pc, uint32_t ins, char *out) { 51 unsigned n = 0; 52 while ((ins & instab[n].mask) != instab[n].bits) n++; 53 const char* fmt = instab[n].fmt; 54 char x; 55 56 unsigned mo = ins & 0xFFFFF; 57 unsigned bo = ins & 0xFFFFFF; 58 if (mo & 0x80000) mo |= 0xFFF00000; 59 if (bo & 0x800000) bo |= 0xFF000000; 60 61 while ((x = *fmt++) != 0) { 62 if (x != '%') { 63 *out++ = x; 64 continue; 65 } 66 switch (*fmt++) { 67 case 'C': out = append_str(out, CC((ins >> 24) & 15)); break; 68 case 'a': out = append_str(out, R((ins >> 24) & 15)); break; 69 case 'b': out = append_str(out, R((ins >> 20) & 15)); break; 70 case 'o': out = append_str(out, OP((ins >> 16) & 15)); break; 71 case 'c': out = append_str(out, R(ins & 15)); break; 72 case 'n': out = append_i32(out, ins & 0xFFFF); break; 73 case 's': out = append_u32(out, (ins & 0xFFFF) | 0xFFFF0000); break; 74 case 'N': out = append_u32(out, (ins & 0xFFFF) << 16); break; 75 case 'm': out = append_i32(out, mo); break; 76 case 'B': out = append_u32(out, pc + 4 + (bo << 2)); break; 77 } 78 } 79 *out = 0; 80 }