d16v5.c (5481B)
1 // Copyright 2018, Brian Swetland <swetland@frotz.net> 2 // Licensed under the Apache License, Version 2.0. 3 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <stdarg.h> 7 #include <ctype.h> 8 #include <strings.h> 9 #include <string.h> 10 11 typedef unsigned u32; 12 typedef unsigned short u16; 13 14 char *append(char *buf, const char *s) { 15 while (*s) 16 *buf++ = *s++; 17 return buf; 18 } 19 char *append_u16(char *buf, unsigned n) { 20 sprintf(buf, "%04x", n & 0xFFFF); 21 return buf + strlen(buf); 22 } 23 char *append_int(char *buf, int n) { 24 sprintf(buf, "%d", n); 25 return buf + strlen(buf); 26 } 27 28 const char *regname[] = { 29 "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", 30 }; 31 32 const char *alufunc[] = { 33 "AND", "ORR", "XOR", "NOT", "ADD", "SUB", "SLT", "SLU", 34 "SHL", "SHR", "ROL", "ROR", "MUL", "DUP", "SWP", "MHI", 35 }; 36 37 void printinst(char *buf, unsigned pc, unsigned instr, const char *fmt, unsigned verbose) { 38 char *start = buf; 39 char note[64]; 40 note[0] = 0; 41 42 unsigned c = (instr >> 3) & 7; 43 unsigned a = (instr >> 6) & 7; 44 unsigned b = (instr >> 9) & 7; 45 unsigned f = (instr >> 12) & 15; 46 47 // immediates 48 int s7 = (instr >> 9) & 0x3F; 49 int s9 = ((instr >> 9) & 0x3F) | (instr & 0xC0); 50 int s10 = ((instr >> 9) & 0x3F) | (instr & 0x1C0); 51 int s12 = ((instr >> 9) & 0x3F) | (instr & 0x1C0) | ((instr & 0x30) << 5); 52 unsigned u6 = ((instr >> 6) & 0x7) | ((instr >> 9) & 0x38); 53 54 // sign-extend 55 if (instr & 0x8000) { 56 s7 |= 0xFFFFFF80; 57 s9 |= 0xFFFFFF00; 58 s10 |= 0xFFFFFE00; 59 s12 |= 0xFFFFF800; 60 } 61 62 while (*fmt) { 63 if (*fmt != '@') { 64 *buf++ = *fmt++; 65 continue; 66 } 67 switch (*++fmt) { 68 case 'A': 69 buf = append(buf, regname[a]); 70 break; 71 case 'B': 72 buf = append(buf, regname[b]); 73 break; 74 case 'C': 75 buf = append(buf, regname[c]); 76 break; 77 case 'F': 78 buf = append(buf, alufunc[f]); 79 break; 80 case '7': // si7 81 buf = append_u16(buf, s7); 82 sprintf(note, "(%d)", s7); 83 break; 84 case '9': // si9 (pcrel) 85 buf = append_u16(buf, pc + s9 + 1); 86 sprintf(note, "(%d)", pc + s9 + 1); 87 break; 88 case '0': // si10 89 buf = append_u16(buf, s10); 90 sprintf(note, "(%d)", s10); 91 break; 92 case '2': // si12 (pcrel) 93 buf = append_u16(buf, pc + s12 + 1); 94 sprintf(note, "(%d)", pc + s12 + 1); 95 break; 96 case 'h': // only used by mhi 97 buf = append_u16(buf, s7 & 0x3F); 98 sprintf(note, "(%d)", s7 & 0x3F); 99 break; 100 case 'u': // only used by LC/SC 101 buf = append_u16(buf, u6); 102 sprintf(note, "(%d)", u6); 103 case 0: 104 goto done; 105 } 106 fmt++; 107 } 108 done: 109 if (verbose && note[0]) { 110 while ((buf - start) < 22) *buf++ = ' '; 111 strcpy(buf, note); 112 buf += strlen(note); 113 } 114 *buf = 0; 115 } 116 117 struct { 118 u16 mask; 119 u16 value; 120 const char *fmt; 121 } decode[] = { 122 { 0b1111000000000111, 0b0011000000000000, "NOT @C, @A" }, 123 { 0b1111111111000111, 0b0000000000000000, "MOV @C, @A" }, 124 { 0b1111111111000111, 0b0000001001000000, "MOV @C, @A" }, 125 { 0b1111111111000111, 0b0000010010000000, "MOV @C, @A" }, 126 { 0b1111111111000111, 0b0000011011000000, "MOV @C, @A" }, 127 { 0b1111111111000111, 0b0000100100000000, "MOV @C, @A" }, 128 { 0b1111111111000111, 0b0000101101000000, "MOV @C, @A" }, 129 { 0b1111111111000111, 0b0000110110000000, "MOV @C, @A" }, 130 { 0b1111111111000111, 0b0000111111000000, "MOV @C, @A" }, 131 { 0b0000000000000111, 0b0000000000000000, "@F @C, @A, @B" }, 132 { 0b0000000000000111, 0b0000000000000001, "ADD @C, @A, @7" }, 133 { 0b0000000000000111, 0b0000000000000010, "MOV @C, @0" }, 134 { 0b0000000000000111, 0b0000000000000011, "LW @C, [@A, @7]" }, 135 { 0b0000000100000111, 0b0000000000000100, "BNZ @C, @9" }, 136 { 0b0000000100000111, 0b0000000100000100, "BZ @C, @9" }, 137 { 0b0000000000000111, 0b0000000000000101, "SW @C, [@A, @7]" }, 138 { 0b0000000000001111, 0b0000000000000110, "B @2" }, 139 { 0b0000000000001111, 0b0000000000001110, "BL @2" }, 140 { 0b1000111000001111, 0b0000000000000111, "B @A" }, 141 { 0b1000111000001111, 0b0000000000001111, "BL @A" }, 142 { 0b1000111000000111, 0b0000001000000111, "NOP" }, 143 { 0b1000111000000111, 0b0000010000000111, "RSV0" }, 144 { 0b1000111000000111, 0b0000011000000111, "RSV1" }, 145 { 0b1000111000000111, 0b0000100000000111, "LC @c, @6" }, 146 { 0b1000111000000111, 0b0000101000000111, "SC @c, @6" }, 147 { 0b1111111000000111, 0b0000110000000111, "SHL @C, @A, 1" }, 148 { 0b1111111000000111, 0b0001110000000111, "SHR @C, @A, 1" }, 149 { 0b1111111000000111, 0b0010110000000111, "ROL @C, @A, 1" }, 150 { 0b1111111000000111, 0b0011110000000111, "ROR @C, @A, 1" }, 151 { 0b1111111000000111, 0b0000111000000111, "SHL @C, @A, 4" }, 152 { 0b1111111000000111, 0b0001111000000111, "SHR @C, @A, 4" }, 153 { 0b1111111000000111, 0b0010111000000111, "ROL @C, @A, 4" }, 154 { 0b1111111000000111, 0b0011111000000111, "ROR @C, @A, 4" }, 155 { 0b1000000000000111, 0b1000000000000111, "MHI @C, @A, @h" }, 156 { 0b0000000000000000, 0b0000000000000000, "UND" }, 157 }; 158 159 static void disassemble0(char *buf, unsigned pc, unsigned instr, unsigned verbose) { 160 int n = 0; 161 for (n = 0 ;; n++) { 162 if ((instr & decode[n].mask) == decode[n].value) { 163 printinst(buf, pc, instr, decode[n].fmt, verbose); 164 return; 165 } 166 } 167 buf[0] = 0; 168 } 169 170 void disassemble(char *buf, unsigned pc, unsigned instr) { 171 disassemble0(buf, pc, instr, 1); 172 } 173 174 #ifdef STANDALONE 175 int main(int argc, char **argv) { 176 char buf[256]; 177 char line[1024]; 178 while (fgets(line, 1024, stdin)) { 179 unsigned insn = 0xFFFF; 180 unsigned pc = 0; 181 sscanf(line, "%04x%04x", &insn, &pc); 182 disassemble0(buf, pc, insn, 0); 183 printf("%s\n", buf); 184 fflush(stdout); 185 } 186 return 0; 187 } 188 #endif