gateware

A collection of little open source FPGA hobby projects
git clone http://frotz.net/git/gateware.git
Log | Files | Refs | README

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