commit 6c71f9a1d984b525595dce8ef3b2f7372e2a9e58
parent ab5cc9ce5f7b503cbe762a15c3e71729c917fa18
Author: Brian Swetland <swetland@frotz.net>
Date: Sun, 2 Dec 2018 23:25:23 -0800
cleanup: remove obsolete assemblers
Diffstat:
D | src/a16.c | | | 682 | ------------------------------------------------------------------------------- |
D | src/a16v4.c | | | 688 | ------------------------------------------------------------------------------- |
D | src/d16.c | | | 143 | ------------------------------------------------------------------------------- |
D | src/d16v4.c | | | 211 | ------------------------------------------------------------------------------- |
4 files changed, 0 insertions(+), 1724 deletions(-)
diff --git a/src/a16.c b/src/a16.c
@@ -1,682 +0,0 @@
-// Copyright 2015, Brian Swetland <swetland@frotz.net>
-// Licensed under the Apache License, Version 2.0.
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include <strings.h>
-#include <string.h>
-
-typedef unsigned u32;
-typedef unsigned short u16;
-
-static unsigned linenumber = 0;
-static char linestring[256];
-static char *filename;
-
-FILE *ofp = 0;
-
-void die(const char *fmt, ...) {
- va_list ap;
- fprintf(stderr,"%s:%d: ", filename, linenumber);
- va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
- fprintf(stderr,"\n");
- if (linestring[0])
- fprintf(stderr,"%s:%d: >> %s <<\n", filename, linenumber, linestring);
- exit(1);
-}
-
-int is_signed4(unsigned n) {
- if (n & 0x8000) n |= 0xFFFF0000;
- if (n <= 0x7) return 1;
- if ((n & 0xFFFFFFF8) == 0xFFFFFFF8) return 1;
- return 0;
-}
-int is_signed8(unsigned n) {
- if (n & 0x8000) n |= 0xFFFF0000;
- if (n <= 0xFF) return 1;
- if ((n & 0xFFFFFF80) == 0xFFFFFF80) return 1;
- return 0;
-}
-int is_signed12(unsigned n) {
- if (n & 0x8000) n |= 0xFFFF0000;
- if (n <= 0x7FF) return 1;
- if ((n & 0xFFFFF800) == 0xFFFFF800) return 1;
- return 0;
-}
-int is_signed16(unsigned n) {
- if (n < 0xFFFF) return 1;
- if ((n & 0xFFF8000) == 0xFFFF8000) return 1;
- return 0;
-}
-
-u16 rom[65535];
-u16 PC = 0;
-
-#define TYPE_PCREL_S8 1
-#define TYPE_PCREL_S12 2
-#define TYPE_ABS_U16 3
-
-struct fixup {
- struct fixup *next;
- unsigned pc;
- unsigned type;
-};
-
-struct label {
- struct label *next;
- struct fixup *fixups;
- const char *name;
- unsigned pc;
- unsigned defined;
-};
-
-struct label *labels;
-struct fixup *fixups;
-
-void fixup_branch(const char *name, int addr, int btarget, int type) {
- unsigned n;
-
- switch(type) {
- case TYPE_PCREL_S8:
- n = btarget - addr - 1;
- if (!is_signed8(n)) break;
- rom[addr] = (rom[addr] & 0x00FF) | ((n & 0x00FF) << 8);
- return;
- case TYPE_PCREL_S12:
- n = btarget - addr - 1;
- if (!is_signed12(n)) break;
- rom[addr] = (rom[addr] & 0x000F) | ((n & 0x0FFF) << 4);
- return;
- case TYPE_ABS_U16:
- rom[addr] = btarget;
- return;
- default:
- die("unknown branch type %d\n",type);
- }
- die("label '%s' at %08x is out of range of %08x\n", name, btarget, addr);
-}
-
-void setlabel(const char *name, unsigned pc) {
- struct label *l;
- struct fixup *f;
-
- for (l = labels; l; l = l->next) {
- if (!strcasecmp(l->name, name)) {
- if (l->defined) die("cannot redefine '%s'", name);
- l->pc = pc;
- l->defined = 1;
- for (f = l->fixups; f; f = f->next) {
- fixup_branch(name, f->pc, l->pc, f->type);
- }
- return;
- }
- }
- l = malloc(sizeof(*l));
- l->name = strdup(name);
- l->pc = pc;
- l->fixups = 0;
- l->defined = 1;
- l->next = labels;
- labels = l;
-}
-
-const char *getlabel(unsigned pc) {
- struct label *l;
- for (l = labels; l; l = l->next)
- if (l->pc == pc)
- return l->name;
- return 0;
-}
-
-void uselabel(const char *name, unsigned pc, unsigned type) {
- struct label *l;
- struct fixup *f;
-
- for (l = labels; l; l = l->next) {
- if (!strcasecmp(l->name, name)) {
- if (l->defined) {
- fixup_branch(name, pc, l->pc, type);
- return;
- } else {
- goto add_fixup;
- }
- }
- }
- l = malloc(sizeof(*l));
- l->name = strdup(name);
- l->pc = 0;
- l->fixups = 0;
- l->defined = 0;
- l->next = labels;
- labels = l;
-add_fixup:
- f = malloc(sizeof(*f));
- f->pc = pc;
- f->type = type;
- f->next = l->fixups;
- l->fixups = f;
-}
-
-void checklabels(void) {
- struct label *l;
- for (l = labels; l; l = l->next) {
- if (!l->defined) {
- die("undefined label '%s'", l->name);
- }
- }
-}
-
-void disassemble(char *buf, unsigned pc, unsigned instr);
-
-void emit(unsigned instr) {
- rom[PC++] = instr;
-}
-
-void save(const char *fn) {
- const char *name;
- unsigned n;
- char dis[128];
-
- FILE *fp = fopen(fn, "w");
- if (!fp) die("cannot write to '%s'", fn);
- for (n = 0; n < PC; n++) {
- disassemble(dis, n, rom[n]);
- name = getlabel(n);
- if (name) {
- fprintf(fp, "%04x // %04x: %-25s <- %s\n", rom[n], n, dis, name);
- } else {
- fprintf(fp, "%04x // %04x: %s\n", rom[n], n, dis);
- }
- }
- fclose(fp);
-}
-
-#define MAXTOKEN 32
-
-enum tokens {
- tEOL,
- tCOMMA, tCOLON, tOBRACK, tCBRACK, tDOT, tHASH, tSTRING, tNUMBER,
- tMOV, tAND, tORR, tXOR, tADD, tSUB, tMUL, tMHI,
- tSLT, tSLE, tSHR, tSHL, tBIS, tBIC, tTBS, tBIT,
- tLW, tSW, tNOP, tNOT, tB, tBL, tBZ, tBNZ,
- tDEBUG,
- tR0, tR1, tR2, tR3, tR4, tR5, tR6, tR7,
- rR8, rR9, rR10, rR11, rR12, tR13, tR14, tR15,
- tSP, tLR,
- tEQU, tWORD, tASCII, tASCIIZ,
- NUMTOKENS,
-};
-
-char *tnames[] = {
- "<EOL>",
- ",", ":", "[", "]", ".", "#", "<STRING>", "<NUMBER>",
- "MOV", "AND", "ORR", "XOR", "ADD", "SUB", "MUL", "MHI",
- "SLT", "SLE", "SHR", "SHL", "BIS", "BIC", "TBS", "BIT",
- "LW", "SW", "NOP", "NOT", "B", "BL", "BZ", "BNZ",
- "DEBUG",
- "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7",
- "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15",
- "SP", "LR",
- "EQU", "WORD", "STRING", "ASCIIZ"
-};
-
-#define FIRST_ALU_OP tMOV
-#define LAST_ALU_OP tBIT
-#define FIRST_REGISTER tR0
-#define LAST_REGISTER tLR
-
-int is_reg(unsigned tok) {
- return ((tok >= FIRST_REGISTER) && (tok <= LAST_REGISTER));
-}
-
-int is_alu_op(unsigned tok) {
- return ((tok >= FIRST_ALU_OP) && (tok <= LAST_ALU_OP));
-}
-
-unsigned to_func(unsigned tok) {
- return tok - FIRST_ALU_OP;
-}
-
-unsigned to_reg(unsigned tok) {
- if (tok == tLR) return 14;
- if (tok == tSP) return 13;
- return tok - FIRST_REGISTER;
-}
-
-int is_stopchar(unsigned x) {
- switch (x) {
- case 0:
- case ' ':
- case '\t':
- case '\r':
- case '\n':
- case ',':
- case ':':
- case '[':
- case ']':
- case '.':
- case '"':
- case '#':
- return 1;
- default:
- return 0;
- }
-}
-int is_eoschar(unsigned x) {
- switch (x) {
- case 0:
- case '\t':
- case '\r':
- case '"':
- return 1;
- default:
- return 0;
- }
-}
-
-int tokenize(char *line, unsigned *tok, unsigned *num, char **str) {
- char *s;
- int count = 0;
- unsigned x, n, neg;
- linenumber++;
-
- for (;;) {
- x = *line;
- again:
- if (count == 31) die("line too complex");
-
- switch (x) {
- case 0:
- goto alldone;
- case ' ':
- case '\t':
- case '\r':
- case '\n':
- line++;
- continue;
- case '/':
- if (line[1] == '/')
- goto alldone;
- case ';':
- goto alldone;
- case ',':
- str[count] = ",";
- num[count] = 0;
- tok[count++] = tCOMMA;
- line++;
- continue;
- case ':':
- str[count] = ":";
- num[count] = 0;
- tok[count++] = tCOLON;
- line++;
- continue;
- case '[':
- str[count] = "[";
- num[count] = 0;
- tok[count++] = tOBRACK;
- line++;
- continue;
- case ']':
- str[count] = "]";
- num[count] = 0;
- tok[count++] = tCBRACK;
- line++;
- continue;
- case '.':
- str[count] = ".";
- num[count] = 0;
- tok[count++] = tDOT;
- line++;
- continue;
- case '#':
- str[count] = "#";
- num[count] = 0;
- tok[count++] = tHASH;
- line++;
- continue;
- case '"':
- str[count] = ++line;
- num[count] = 0;
- tok[count++] = tSTRING;
- while (!is_eoschar(*line)) line++;
- if (*line != '"')
- die("unterminated string");
- *line++ = 0;
- continue;
- }
-
- s = line++;
- while (!is_stopchar(*line)) line++;
-
- /* save the stopchar */
- x = *line;
- *line = 0;
-
- neg = (s[0] == '-');
- if (neg && isdigit(s[1])) s++;
-
- str[count] = s;
- if (isdigit(s[0])) {
- num[count] = strtoul(s, 0, 0);
- if(neg) num[count] = -num[count];
- tok[count++] = tNUMBER;
- goto again;
- }
- if (isalpha(s[0])) {
- num[count] = 0;
- for (n = tNUMBER + 1; n < NUMTOKENS; n++) {
- if (!strcasecmp(s, tnames[n])) {
- str[count] = tnames[n];
- tok[count++] = n;
- goto again;
- }
- }
-
- while (*s) {
- if (!isalnum(*s) && (*s != '_'))
- die("invalid character '%c' in identifier", *s);
- s++;
- }
- tok[count++] = tSTRING;
- goto again;
- }
- die("invalid character '%c'", s[0]);
- }
-
-alldone:
- str[count] = "";
- num[count] = 0;
- tok[count++] = tEOL;
- return count;
-}
-
-void expect(unsigned expected, unsigned got) {
- if (expected != got)
- die("expected %s, got %s", tnames[expected], tnames[got]);
-}
-
-void expect_register(unsigned got) {
- if (!is_reg(got))
- die("expected register, got %s", tnames[got]);
-}
-
-#define REG(n) (tnames[FIRST_REGISTER + (n)])
-
-// various fields
-#define _OP(n) (((n) & 15) << 0)
-#define _A(n) (((n) & 15) << 4)
-#define _B(n) (((n) & 15) << 8)
-#define _FHI(n) (((n) & 15) << 12)
-#define _FLO(n) (((n) & 15) << 8)
-#define _I4(n) (((n) & 15) << 12)
-#define _I8(n) (((n) & 0xFF) << 8)
-#define _I12(n) (((n) & 0xFFF) << 4)
-
-#define OP_MOV_RA_S8 0x0000
-#define OP_MHI_RA_S8 0x0001
-#define OP_ALU_RA_RA_RB 0x0002
-#define OP_ALU_RA_RA_S4 0x0003
-#define OP_ALU_R0_RA_RB 0x0004
-#define OP_ALU_R1_RA_RB 0x0005
-#define OP_ALU_R2_RA_RB 0x0006
-#define OP_ALU_R3_RA_RB 0x0007
-#define OP_LW_RB_S4 0x0008
-#define OP_SW_RB_S4 0x0009
-#define OP_BNZ_RA_S8 0x000A
-#define OP_BZ_RA_S8 0x000B
-#define OP_B_S12 0x000C
-#define OP_BL_S12 0x000D
-#define OP_B_RB 0x000E
-#define OP_BL_RB 0x100E
-#define OP_NOP 0x200E
-
-#define ALU_MOV 0
-#define ALU_AND 1
-#define ALU_ORR 2
-#define ALU_XOR 3
-#define ALU_ADD 4
-#define ALU_SUB 5
-#define ALU_SHR 6
-#define ALU_SHL 7
-
-#define T0 tok[0]
-#define T1 tok[1]
-#define T2 tok[2]
-#define T3 tok[3]
-#define T4 tok[4]
-#define T5 tok[5]
-#define T6 tok[6]
-#define T7 tok[7]
-
-void assemble_line(int n, unsigned *tok, unsigned *num, char **str) {
- unsigned instr = 0;
- unsigned tmp;
- if (T0 == tSTRING) {
- if (T1 == tCOLON) {
- setlabel(str[0], PC);
- tok += 2;
- num += 2;
- str += 2;
- n -= 2;
- } else {
- die("unexpected identifier '%s'", str[0]);
- }
- }
-
- switch(T0) {
- case tEOL:
- /* blank lines are fine */
- return;
- case tNOP:
- emit(OP_NOP);
- return;
- case tNOT:
- /* XOR rX, rX, -1 */
- expect_register(T1);
- emit(OP_ALU_RA_RA_S4 | _A(to_reg(T1)) | _I4(-1) | ALU_XOR);
- return;
- case tMOV:
- expect_register(T1);
- expect(tCOMMA, T2);
- if (is_reg(T3)) {
- emit(OP_ALU_RA_RA_RB | _A(to_reg(T1)) | _B(to_reg(T3)) | ALU_MOV);
- return;
- }
- expect(tNUMBER, T3);
- if (is_signed8(num[3])) {
- emit(OP_MOV_RA_S8 | _A(to_reg(T1)) | _I8(num[3]));
- return;
- } else {
- emit(OP_MOV_RA_S8 | _A(to_reg(T1)) | _I8(num[3]));
- emit(OP_MHI_RA_S8 | _A(to_reg(T1)) | _I8((num[3] >> 8)));
- }
- return;
- case tMHI:
- expect_register(T1);
- expect(tCOMMA, T2);
- expect(tNUMBER, T3);
- // range
- emit(OP_MHI_RA_S8 | _A(to_reg(T1)) | _I8(num[3]));
- return;
- case tLW:
- case tSW:
- instr = (T0 == tLW ? OP_LW_RB_S4 : OP_SW_RB_S4);
- expect_register(T1);
- expect(tCOMMA, T2);
- expect(tOBRACK, T3);
- expect_register(T4);
- if (T5 == tCOMMA) {
- expect(tNUMBER, T6);
- expect(tCBRACK, T7);
- tmp = num[6];
- } else {
- expect(tCBRACK, T5);
- tmp = 0;
- }
- if (!is_signed4(tmp)) die("index too large");
- emit(instr | _A(to_reg(T1)) | _B(to_reg(T4)) | _I4(tmp));
- return;
- case tB:
- case tBL:
- if (is_reg(T1)) {
- instr = (T0 == tB) ? OP_B_RB : OP_BL_RB;
- emit(instr | _B(to_reg(T1)));
- } else {
- instr = (T0 == tB) ? OP_B_S12 : OP_BL_S12;
- if (T1 == tSTRING) {
- emit(instr);
- uselabel(str[1], PC - 1, TYPE_PCREL_S12);
- } else if (T1 == tDOT) {
- emit(instr | _I12(-1));
- } else {
- die("expected register or address");
- }
- }
- return;
- case tBZ:
- case tBNZ:
- instr = (T0 == tBZ) ? OP_BZ_RA_S8 : OP_BNZ_RA_S8;
- expect_register(T1);
- expect(tCOMMA, T2);
- if (T3 == tSTRING) {
- emit(instr | _A(to_reg(T1)));
- uselabel(str[3], PC - 1, TYPE_PCREL_S8);
- } else if (T3 == tDOT) {
- emit(instr | _A(to_reg(T1)) | _I12(-1));
- } else {
- die("expected register or address");
- }
- return;
- case tDEBUG:
- expect_register(T1);
- expect(tCOMMA, T2);
- expect(tNUMBER, T3);
- emit(OP_NOP | _FLO(num[3]) | _A(to_reg(T1)));
- return;
- case tWORD:
- tmp = 1;
- for (;;) {
- if (tok[tmp] == tSTRING) {
- emit(0);
- uselabel(str[tmp++], PC - 1, TYPE_ABS_U16);
- } else {
- expect(tNUMBER, tok[tmp]);
- emit(num[tmp++]);
- }
- if (tok[tmp] != tCOMMA)
- break;
- tmp++;
- }
- return;
- case tASCII:
- case tASCIIZ: {
- unsigned n = 0, c = 0;
- const unsigned char *s = (void*) str[1];
- expect(tSTRING, tok[1]);
- while (*s) {
- n |= ((*s) << (c++ * 8));
- if (c == 2) {
- emit(n);
- n = 0;
- c = 0;
- }
- s++;
- }
- emit(n);
- return;
- }
- }
- if (is_alu_op(T0)) {
- expect_register(T1);
- expect(T2, tCOMMA);
- expect_register(T3);
- expect(T4, tCOMMA);
- if (T5 == tNUMBER) {
- if (T1 != T3) {
- die("both registers must be the same in this form");
- }
- if (is_signed4(num[5])) {
- emit(OP_ALU_RA_RA_S4 | _A(to_reg(T1)) | _FLO(to_func(T0)) | _I4(num[5]));
- return;
- } else {
- // auto use R15 as scratch?
- die("immediate out of range (s4)");
- }
- } else if (is_reg(T5)) {
- if (T1 == T3) {
- emit(OP_ALU_RA_RA_RB | _A(to_reg(T1)) | _B(to_reg(T5)) | _FHI(to_func(T0)));
- return;
- }
- switch (T1) {
- case tR0: instr = OP_ALU_R0_RA_RB; break;
- case tR1: instr = OP_ALU_R1_RA_RB; break;
- case tR2: instr = OP_ALU_R2_RA_RB; break;
- case tR3: instr = OP_ALU_R3_RA_RB; break;
- default:
- die("three-reg ALU ops require R0-R3 for the first register");
- }
- emit(instr | _A(to_reg(T3)) | _B(to_reg(T5)) | _FHI(to_func(T0)));
- } else {
- die("expected register or #, got %s", tnames[tok[5]]);
- }
- return;
- }
-
- die("HUH");
-}
-
-void assemble(const char *fn) {
- FILE *fp;
- char line[256];
- int n;
-
- unsigned tok[MAXTOKEN];
- unsigned num[MAXTOKEN];
- char *str[MAXTOKEN];
- char *s;
-
- fp = fopen(fn, "r");
- if (!fp) die("cannot open '%s'", fn);
-
- while (fgets(line, sizeof(line)-1, fp)) {
- strcpy(linestring, line);
- s = linestring;
- while (*s) {
- if ((*s == '\r') || (*s == '\n')) *s = 0;
- else s++;
- }
- n = tokenize(line, tok, num, str);
-#if DEBUG
- {
- int i
- printf("%04d: (%02d) ", linenumber, n);
- for (i = 0; i < n; i++)
- printf("%s ", tnames[tok[i]]);
- printf("\n");
- }
-#endif
- assemble_line(n, tok, num, str);
- }
-}
-
-int main(int argc, char **argv) {
- const char *outname = "out.hex";
- filename = argv[1];
-
- if (argc < 2)
- die("no file specified");
- if (argc == 3)
- outname = argv[2];
-
- assemble(filename);
- linestring[0] = 0;
- checklabels();
- save(outname);
-
- return 0;
-}
diff --git a/src/a16v4.c b/src/a16v4.c
@@ -1,688 +0,0 @@
-// Copyright 2015, Brian Swetland <swetland@frotz.net>
-// Licensed under the Apache License, Version 2.0.
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include <strings.h>
-#include <string.h>
-
-typedef unsigned u32;
-typedef unsigned short u16;
-
-static unsigned linenumber = 0;
-static char linestring[256];
-static char *filename;
-
-FILE *ofp = 0;
-
-void die(const char *fmt, ...) {
- va_list ap;
- fprintf(stderr,"%s:%d: ", filename, linenumber);
- va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
- fprintf(stderr,"\n");
- if (linestring[0])
- fprintf(stderr,"%s:%d: >> %s <<\n", filename, linenumber, linestring);
- exit(1);
-}
-
-// various fields
-#define _OP(n) (((n) & 15) << 0)
-#define _A(n) (((n) & 7) << 7)
-#define _B(n) (((n) & 7) << 10)
-#define _C(n) (((n) & 7) << 4)
-#define _FHI(n) (((n) & 7) << 13)
-#define _FLO(n) (((n) & 7) << 0)
-#define _I6(n) (((n) & 0x3F) << 10)
-
-// smiiiii
-// siiiiiaaamxx0ooo
-static inline unsigned _I7(unsigned n) {
- return ((n & 0x1F) << 10) |
- ((n & 0x20) << 1) |
- ((n & 0x40) << 9);
-}
-// skkkiiiii
-// siiiiikkkccc0ooo
-static inline unsigned _I9(unsigned n) {
- return ((n & 0x1F) << 10) |
- ((n & 0xE0) << 2) |
- ((n & 0x100) << 7);
-}
-// sjjjjjiiiii
-// siiiiixjjjjj0ooo
-static inline unsigned _I11(unsigned n) {
- return ((n & 0x1F) << 10) |
- ((n & 0x3E0) >> 1) |
- ((n & 0x400) << 5);
-}
-// sjjjjjjiiiii
-// siiiiijjjjjj0ooo
-static inline unsigned _I12(unsigned n) {
- return ((n & 0x1F) << 10) |
- ((n & 0x7E0) >> 1) |
- ((n & 0x800) << 4);
-}
-
-int is_signed6(unsigned n) {
- n &= 0xFFFFFFE0;
- return ((n == 0) || (n == 0xFFFFFFE0));
-}
-int is_signed7(unsigned n) {
- n &= 0xFFFFFFC0;
- return ((n == 0) || (n == 0xFFFFFFC0));
-}
-int is_signed9(unsigned n) {
- n &= 0xFFFFFF00;
- return ((n == 0) || (n == 0xFFFFFF00));
-}
-int is_signed11(unsigned n) {
- n &= 0xFFFFFC00;
- return ((n == 0) || (n == 0xFFFFFC00));
-}
-int is_signed12(unsigned n) {
- n &= 0xFFFFF800;
- return ((n == 0) || (n == 0xFFFFF800));
-}
-
-u16 rom[65535];
-u16 PC = 0;
-
-#define TYPE_PCREL_S7 1
-#define TYPE_PCREL_S11 2
-#define TYPE_ABS_U16 3
-
-struct fixup {
- struct fixup *next;
- unsigned pc;
- unsigned type;
-};
-
-struct label {
- struct label *next;
- struct fixup *fixups;
- const char *name;
- unsigned pc;
- unsigned defined;
-};
-
-struct label *labels;
-struct fixup *fixups;
-
-void fixup_branch(const char *name, int addr, int btarget, int type) {
- unsigned n;
-
- switch(type) {
- case TYPE_PCREL_S7:
- n = btarget - addr - 1;
- if (!is_signed7(n)) break;
- rom[addr] |= _I7(n);
- return;
- case TYPE_PCREL_S11:
- n = btarget - addr - 1;
- if (!is_signed11(n)) break;
- rom[addr] |= _I11(n);
- return;
- case TYPE_ABS_U16:
- rom[addr] = btarget;
- return;
- default:
- die("unknown branch type %d\n",type);
- }
- die("label '%s' at %08x is out of range of %08x\n", name, btarget, addr);
-}
-
-void setlabel(const char *name, unsigned pc) {
- struct label *l;
- struct fixup *f;
-
- for (l = labels; l; l = l->next) {
- if (!strcasecmp(l->name, name)) {
- if (l->defined) die("cannot redefine '%s'", name);
- l->pc = pc;
- l->defined = 1;
- for (f = l->fixups; f; f = f->next) {
- fixup_branch(name, f->pc, l->pc, f->type);
- }
- return;
- }
- }
- l = malloc(sizeof(*l));
- l->name = strdup(name);
- l->pc = pc;
- l->fixups = 0;
- l->defined = 1;
- l->next = labels;
- labels = l;
-}
-
-const char *getlabel(unsigned pc) {
- struct label *l;
- for (l = labels; l; l = l->next)
- if (l->pc == pc)
- return l->name;
- return 0;
-}
-
-void uselabel(const char *name, unsigned pc, unsigned type) {
- struct label *l;
- struct fixup *f;
-
- for (l = labels; l; l = l->next) {
- if (!strcasecmp(l->name, name)) {
- if (l->defined) {
- fixup_branch(name, pc, l->pc, type);
- return;
- } else {
- goto add_fixup;
- }
- }
- }
- l = malloc(sizeof(*l));
- l->name = strdup(name);
- l->pc = 0;
- l->fixups = 0;
- l->defined = 0;
- l->next = labels;
- labels = l;
-add_fixup:
- f = malloc(sizeof(*f));
- f->pc = pc;
- f->type = type;
- f->next = l->fixups;
- l->fixups = f;
-}
-
-void checklabels(void) {
- struct label *l;
- for (l = labels; l; l = l->next) {
- if (!l->defined) {
- die("undefined label '%s'", l->name);
- }
- }
-}
-
-void disassemble(char *buf, unsigned pc, unsigned instr);
-
-void emit(unsigned instr) {
- rom[PC++] = instr;
-}
-
-void save(const char *fn) {
- const char *name;
- unsigned n;
- char dis[128];
-
- FILE *fp = fopen(fn, "w");
- if (!fp) die("cannot write to '%s'", fn);
- for (n = 0; n < PC; n++) {
- disassemble(dis, n, rom[n]);
- name = getlabel(n);
- if (name) {
- fprintf(fp, "%04x // %04x: %-25s <- %s\n", rom[n], n, dis, name);
- } else {
- fprintf(fp, "%04x // %04x: %s\n", rom[n], n, dis);
- }
- }
- fclose(fp);
-}
-
-#define MAXTOKEN 32
-
-enum tokens {
- tEOL,
- tCOMMA, tCOLON, tOBRACK, tCBRACK, tDOT, tHASH, tSTRING, tNUMBER,
- tADD, tSUB, tAND, tORR, tXOR, tSLT, tSGE, tMUL,
- tLW, tSW, tNOP, tNOT, tB, tBL, tBZ, tBNZ,
- tMOV, tEXT, tDEBUG, tHALT,
- tR0, tR1, tR2, tR3, tR4, tR5, tR6, tR7,
- tSP, tLR,
- tEQU, tWORD, tASCII, tASCIIZ,
- NUMTOKENS,
-};
-
-char *tnames[] = {
- "<EOL>",
- ",", ":", "[", "]", ".", "#", "<STRING>", "<NUMBER>",
- "ADD", "SUB", "AND", "ORR", "XOR", "SLT", "SGE", "MUL",
- "LW", "SW", "NOP", "NOT", "B", "BL", "BZ", "BNZ",
- "MOV", "EXT", "DEBUG", "HALT",
- "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7",
- "SP", "LR",
- "EQU", "WORD", "STRING", "ASCIIZ"
-};
-
-#define FIRST_ALU_OP tADD
-#define LAST_ALU_OP tMUL
-#define FIRST_REGISTER tR0
-#define LAST_REGISTER tLR
-
-int is_reg(unsigned tok) {
- return ((tok >= FIRST_REGISTER) && (tok <= LAST_REGISTER));
-}
-
-int is_alu_op(unsigned tok) {
- return ((tok >= FIRST_ALU_OP) && (tok <= LAST_ALU_OP));
-}
-
-unsigned to_func(unsigned tok) {
- return tok - FIRST_ALU_OP;
-}
-
-unsigned to_reg(unsigned tok) {
- if (tok == tLR) return 7;
- if (tok == tSP) return 6;
- return tok - FIRST_REGISTER;
-}
-
-int is_stopchar(unsigned x) {
- switch (x) {
- case 0:
- case ' ':
- case '\t':
- case '\r':
- case '\n':
- case ',':
- case ':':
- case '[':
- case ']':
- case '.':
- case '"':
- case '#':
- return 1;
- default:
- return 0;
- }
-}
-int is_eoschar(unsigned x) {
- switch (x) {
- case 0:
- case '\t':
- case '\r':
- case '"':
- return 1;
- default:
- return 0;
- }
-}
-
-int tokenize(char *line, unsigned *tok, unsigned *num, char **str) {
- char *s;
- int count = 0;
- unsigned x, n, neg;
- linenumber++;
-
- for (;;) {
- x = *line;
- again:
- if (count == 31) die("line too complex");
-
- switch (x) {
- case 0:
- goto alldone;
- case ' ':
- case '\t':
- case '\r':
- case '\n':
- line++;
- continue;
- case '/':
- if (line[1] == '/')
- goto alldone;
- case ';':
- goto alldone;
- case ',':
- str[count] = ",";
- num[count] = 0;
- tok[count++] = tCOMMA;
- line++;
- continue;
- case ':':
- str[count] = ":";
- num[count] = 0;
- tok[count++] = tCOLON;
- line++;
- continue;
- case '[':
- str[count] = "[";
- num[count] = 0;
- tok[count++] = tOBRACK;
- line++;
- continue;
- case ']':
- str[count] = "]";
- num[count] = 0;
- tok[count++] = tCBRACK;
- line++;
- continue;
- case '.':
- str[count] = ".";
- num[count] = 0;
- tok[count++] = tDOT;
- line++;
- continue;
- case '#':
- str[count] = "#";
- num[count] = 0;
- tok[count++] = tHASH;
- line++;
- continue;
- case '"':
- str[count] = ++line;
- num[count] = 0;
- tok[count++] = tSTRING;
- while (!is_eoschar(*line)) line++;
- if (*line != '"')
- die("unterminated string");
- *line++ = 0;
- continue;
- }
-
- s = line++;
- while (!is_stopchar(*line)) line++;
-
- /* save the stopchar */
- x = *line;
- *line = 0;
-
- neg = (s[0] == '-');
- if (neg && isdigit(s[1])) s++;
-
- str[count] = s;
- if (isdigit(s[0])) {
- num[count] = strtoul(s, 0, 0);
- if(neg) num[count] = -num[count];
- tok[count++] = tNUMBER;
- goto again;
- }
- if (isalpha(s[0])) {
- num[count] = 0;
- for (n = tNUMBER + 1; n < NUMTOKENS; n++) {
- if (!strcasecmp(s, tnames[n])) {
- str[count] = tnames[n];
- tok[count++] = n;
- goto again;
- }
- }
-
- while (*s) {
- if (!isalnum(*s) && (*s != '_'))
- die("invalid character '%c' in identifier", *s);
- s++;
- }
- tok[count++] = tSTRING;
- goto again;
- }
- die("invalid character '%c'", s[0]);
- }
-
-alldone:
- str[count] = "";
- num[count] = 0;
- tok[count++] = tEOL;
- return count;
-}
-
-void expect(unsigned expected, unsigned got) {
- if (expected != got)
- die("expected %s, got %s", tnames[expected], tnames[got]);
-}
-
-void expect_register(unsigned got) {
- if (!is_reg(got))
- die("expected register, got %s", tnames[got]);
-}
-
-#define REG(n) (tnames[FIRST_REGISTER + (n)])
-
-
-#define OP_ALU_RC_RA_RB 0x0000
-#define OP_EXPANSION 0x0001
-#define OP_EXT 0x0002
-#define OP_MOV_RC_S9 0x0003
-#define OP_LW_RC_RA_S6 0x0004
-#define OP_SW_RC_RA_S6 0x0005
-#define OP_B_S11 0x0006
-#define OP_BL_S11 0x0206
-#define OP_BZ_RA_S7 0x0007
-#define OP_BNZ_RA_S7 0x0017
-#define OP_B_RA 0x0027
-#define OP_BL_RA 0x0037
-#define OP_ALU_RC_RA_S6 0x0008
-#define OP_NOP_EXP 0x0001
-#define OP_NOP_ALU 0x0008
-
-#define ALU_ADD 0
-#define ALU_SUB 1
-#define ALU_AND 2
-#define ALU_ORR 3
-#define ALU_XOR 4
-#define ALU_SLT 5
-#define ALU_SGE 6
-#define ALU_MUL 7
-
-#define T0 tok[0]
-#define T1 tok[1]
-#define T2 tok[2]
-#define T3 tok[3]
-#define T4 tok[4]
-#define T5 tok[5]
-#define T6 tok[6]
-#define T7 tok[7]
-
-void assemble_line(int n, unsigned *tok, unsigned *num, char **str) {
- unsigned instr = 0;
- unsigned tmp;
- if (T0 == tSTRING) {
- if (T1 == tCOLON) {
- setlabel(str[0], PC);
- tok += 2;
- num += 2;
- str += 2;
- n -= 2;
- } else {
- die("unexpected identifier '%s'", str[0]);
- }
- }
-
- switch(T0) {
- case tEOL:
- /* blank lines are fine */
- return;
- case tNOP:
- emit(OP_NOP_EXP);
- return;
- case tNOT:
- /* XOR rX, rX, -1 */
- expect_register(T1);
- emit(OP_ALU_RC_RA_S6 | _A(to_reg(T1)) | _C(to_reg(T1)) | _I6(-1) | ALU_XOR);
- return;
- case tMOV:
- expect_register(T1);
- expect(tCOMMA, T2);
- if (is_reg(T3)) {
- emit(OP_ALU_RC_RA_S6 | _C(to_reg(T1)) | _A(to_reg(T3)) | ALU_ADD);
- return;
- }
- expect(tNUMBER, T3);
- if (is_signed9(num[3])) {
- emit(OP_MOV_RC_S9 | _C(to_reg(T1)) | _I9(num[3]));
- return;
- } else {
- emit(OP_EXT | _I12((num[3] >> 4)));
- emit(OP_MOV_RC_S9 | _C(to_reg(T1)) | _I9((num[3] & 15)));
- }
- return;
- case tEXT:
- expect_register(T1);
- expect(tNUMBER, T2);
- // range
- emit(OP_EXT | _I12(num[3]));
- return;
- case tLW:
- case tSW:
- instr = (T0 == tLW ? OP_LW_RC_RA_S6 : OP_SW_RC_RA_S6);
- expect_register(T1);
- expect(tCOMMA, T2);
- expect(tOBRACK, T3);
- expect_register(T4);
- if (T5 == tCOMMA) {
- expect(tNUMBER, T6);
- expect(tCBRACK, T7);
- tmp = num[6];
- } else {
- expect(tCBRACK, T5);
- tmp = 0;
- }
- if (!is_signed6(tmp)) die("index too large");
- emit(instr | _C(to_reg(T1)) | _A(to_reg(T4)) | _I6(tmp));
- return;
- case tB:
- case tBL:
- if (is_reg(T1)) {
- instr = (T0 == tB) ? OP_B_RA : OP_BL_RA;
- emit(instr | _A(to_reg(T1)));
- } else {
- instr = (T0 == tB) ? OP_B_S11 : OP_BL_S11;
- if (T1 == tSTRING) {
- emit(instr);
- uselabel(str[1], PC - 1, TYPE_PCREL_S11);
- } else if (T1 == tDOT) {
- emit(instr | _I11(-1));
- } else {
- die("expected register or address");
- }
- }
- return;
- case tBZ:
- case tBNZ:
- instr = (T0 == tBZ) ? OP_BZ_RA_S7 : OP_BNZ_RA_S7;
- expect_register(T1);
- expect(tCOMMA, T2);
- if (T3 == tSTRING) {
- emit(instr | _A(to_reg(T1)));
- uselabel(str[3], PC - 1, TYPE_PCREL_S7);
- } else if (T3 == tDOT) {
- emit(instr | _A(to_reg(T1)) | _I11(-1));
- } else {
- die("expected register or address");
- }
- return;
- case tDEBUG:
- expect_register(T1);
- expect(tCOMMA, T2);
- expect(tNUMBER, T3);
- emit(OP_NOP_EXP); //TODO
- return;
- case tHALT:
- emit(0xFFFF);
- return;
- case tWORD:
- tmp = 1;
- for (;;) {
- if (tok[tmp] == tSTRING) {
- emit(0);
- uselabel(str[tmp++], PC - 1, TYPE_ABS_U16);
- } else {
- expect(tNUMBER, tok[tmp]);
- emit(num[tmp++]);
- }
- if (tok[tmp] != tCOMMA)
- break;
- tmp++;
- }
- return;
- case tASCII:
- case tASCIIZ: {
- unsigned n = 0, c = 0;
- const unsigned char *s = (void*) str[1];
- expect(tSTRING, tok[1]);
- while (*s) {
- n |= ((*s) << (c++ * 8));
- if (c == 2) {
- emit(n);
- n = 0;
- c = 0;
- }
- s++;
- }
- emit(n);
- return;
- }
- }
- if (is_alu_op(T0)) {
- expect_register(T1);
- expect(T2, tCOMMA);
- expect_register(T3);
- expect(T4, tCOMMA);
- if (T5 == tNUMBER) {
- if (is_signed6(num[5])) {
- emit(OP_ALU_RC_RA_S6 | _C(to_reg(T1)) | _A(to_reg(T3)) | _FLO(to_func(T0)) | _I6(num[5]));
- } else {
- emit(OP_EXT | _I12((num[5] >> 4)));
- emit(OP_ALU_RC_RA_S6 | _C(to_reg(T1)) | _A(to_reg(T3)) | _FLO(to_func(T0)) | _I6((num[5] & 15)));
- }
- } else if (is_reg(T5)) {
- emit(OP_ALU_RC_RA_RB | _C(to_reg(T1)) | _A(to_reg(T3)) | _B(to_reg(T5)) | _FHI(to_func(T0)));
- } else {
- die("expected register or #, got %s", tnames[tok[5]]);
- }
- return;
- }
-
- die("HUH");
-}
-
-void assemble(const char *fn) {
- FILE *fp;
- char line[256];
- int n;
-
- unsigned tok[MAXTOKEN];
- unsigned num[MAXTOKEN];
- char *str[MAXTOKEN];
- char *s;
-
- fp = fopen(fn, "r");
- if (!fp) die("cannot open '%s'", fn);
-
- while (fgets(line, sizeof(line)-1, fp)) {
- strcpy(linestring, line);
- s = linestring;
- while (*s) {
- if ((*s == '\r') || (*s == '\n')) *s = 0;
- else s++;
- }
- n = tokenize(line, tok, num, str);
-#if DEBUG
- {
- int i
- printf("%04d: (%02d) ", linenumber, n);
- for (i = 0; i < n; i++)
- printf("%s ", tnames[tok[i]]);
- printf("\n");
- }
-#endif
- assemble_line(n, tok, num, str);
- }
-}
-
-int main(int argc, char **argv) {
- const char *outname = "out.hex";
- filename = argv[1];
-
- if (argc < 2)
- die("no file specified");
- if (argc == 3)
- outname = argv[2];
-
- assemble(filename);
- linestring[0] = 0;
- checklabels();
- save(outname);
-
- return 0;
-}
diff --git a/src/d16.c b/src/d16.c
@@ -1,143 +0,0 @@
-// Copyright 2015, Brian Swetland <swetland@frotz.net>
-// Licensed under the Apache License, Version 2.0.
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include <strings.h>
-#include <string.h>
-
-typedef unsigned u32;
-typedef unsigned short u16;
-
-char *append(char *buf, const char *s) {
- while (*s)
- *buf++ = *s++;
- return buf;
-}
-char *append_u16(char *buf, unsigned n) {
- sprintf(buf, "%04x", n & 0xFFFF);
- return buf + strlen(buf);
-}
-char *append_int(char *buf, int n) {
- sprintf(buf, "%d", n);
- return buf + strlen(buf);
-}
-
-const char *regname[] = {
- "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7",
- "R8", "R9", "R10", "R11", "R12", "SP", "LR", "R15",
-};
-
-const char *alufunc[] = {
- "MOV", "AND", "ORR", "XOR", "ADD", "SUB", "MUL", "MHI",
- "SLT", "SLE", "SHR", "SHL", "BIS", "BIC", "TBS", "BIT",
-};
-
-void printinst(char *buf, unsigned pc, unsigned instr, const char *fmt) {
- unsigned a = (instr >> 4) & 15;
- unsigned b = (instr >> 8) & 15;
- unsigned fhi = (instr >> 12) & 15;
- unsigned flo = (instr >> 8) & 15;
- unsigned i8 = (instr >> 8);
- unsigned i4 = (instr >> 12);
- unsigned i12 = (instr >> 4);
- int s4 = (i4 & 0x8) ? (i4 | 0xFFFFFFF0) : (i4 & 0xF);
- int s8 = (i8 & 0x80) ? (i8 | 0xFFFFFF00) : (i8 & 0xFF);
- int s12 = (i12 & 0x800) ? (i12 | 0xFFFFF800) : (i12 & 0xFFF);
-
- while (*fmt) {
- if (*fmt != '@') {
- *buf++ = *fmt++;
- continue;
- }
- switch (*++fmt) {
- case 'A':
- buf = append(buf, regname[a]);
- break;
- case 'B':
- buf = append(buf, regname[b]);
- break;
- case 'C':
- buf = append(buf, regname[instr & 3]);
- break;
- case 'F':
- buf = append(buf, alufunc[fhi]);
- break;
- case 'f': // alt alu func
- buf = append(buf, alufunc[flo]);
- break;
- case '4':
- buf = append_int(buf, s4);
- break;
- case '8':
- buf = append_int(buf, s8);
- break;
- case 's':
- buf = append_int(buf, s12);
- break;
- case 'n':
- buf = append_int(buf, flo);
- break;
- case 0:
- goto done;
- }
- fmt++;
- }
-done:
- *buf = 0;
-}
-
-struct {
- u16 mask;
- u16 value;
- const char *fmt;
-} decode[] = {
- { 0b0000000000001111, 0b0000000000000000, "MOV @A, @8" },
- { 0b0000000000001111, 0b0000000000000001, "MHI @A, @8" },
- { 0b1111000000001111, 0b0000000000000010, "MOV @A, @B" },
- { 0b0000000000001111, 0b0000000000000010, "@F @A, @B" },
- { 0b0000111100001111, 0b0000000000000011, "MOV @A, @4" },
- { 0b1111111100001111, 0b1111001100000011, "NOT @A" },
- { 0b0000000000001111, 0b0000000000000011, "@f @A, @4" },
- { 0b1111000000001100, 0b0000000000000100, "MOV @C, @B" },
- { 0b0000000000001100, 0b0000000000000100, "@F @C, @B, @A" },
- { 0b0000000000001111, 0b0000000000001000, "LW @A, [@B, @4]" },
- { 0b0000000000001111, 0b0000000000001001, "SW @A, [@B, @4]" },
- { 0b0000000000001111, 0b0000000000001010, "BNZ @A, @8" },
- { 0b0000000000001111, 0b0000000000001011, "BZ @A, @8" },
- { 0b0000000000001111, 0b0000000000001100, "B @s" },
- { 0b0000000000001111, 0b0000000000001101, "BL @s" },
- { 0b1111000000001111, 0b0000000000001110, "B @B" },
- { 0b1111000000001111, 0b0001000000001110, "BL @B" },
- { 0b1111111111111111, 0b0010000000001110, "NOP" },
- { 0b1111000000001111, 0b0010000000001110, "DEBUG @A, @n" },
- { 0b0000000000000000, 0b0000000000000000, "UNDEFINED" },
-};
-
-void disassemble(char *buf, unsigned pc, unsigned instr) {
- int n = 0;
- for (n = 0 ;; n++) {
- if ((instr & decode[n].mask) == decode[n].value) {
- printinst(buf, pc, instr, decode[n].fmt);
- return;
- }
- }
- buf[0] = 0;
-}
-
-#ifdef STANDALONE
-int main(int argc, char **argv) {
- char buf[256];
- char line[1024];
- while (fgets(line, 1024, stdin)) {
- unsigned insn = 0xFFFF;
- sscanf(line, "%x", &insn);
- disassemble(buf, 0, insn);
- printf("%s\n", buf);
- fflush(stdout);
- }
- return 0;
-}
-#endif
diff --git a/src/d16v4.c b/src/d16v4.c
@@ -1,211 +0,0 @@
-// Copyright 2018, Brian Swetland <swetland@frotz.net>
-// Licensed under the Apache License, Version 2.0.
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include <strings.h>
-#include <string.h>
-
-typedef unsigned u32;
-typedef unsigned short u16;
-
-char *append(char *buf, const char *s) {
- while (*s)
- *buf++ = *s++;
- return buf;
-}
-char *append_u16(char *buf, unsigned n) {
- sprintf(buf, "%04x", n & 0xFFFF);
- return buf + strlen(buf);
-}
-char *append_int(char *buf, int n) {
- sprintf(buf, "%d", n);
- return buf + strlen(buf);
-}
-
-const char *regname[] = {
- "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7",
-};
-
-const char *alufunc[] = {
- "ADD", "SUB", "AND", "ORR", "XOR", "SLT", "SGE", "MUL",
-};
-
-void printinst(char *buf, unsigned pc, unsigned instr, const char *fmt,
- unsigned _ex, unsigned ev, unsigned verbose) {
- unsigned tmp;
- char *start = buf;
- char note[64];
- note[0] = 0;
-
- unsigned a = (instr >> 7) & 7;
- unsigned b = (instr >> 10) & 7;
- unsigned c = (instr >> 4) & 7;
- unsigned fhi = (instr >> 13) & 7;
- unsigned flo = instr & 7;
-
- // immediate sub-fields
- unsigned s = (instr >> 15);
- unsigned i = (instr >> 10) & 0x1F;
- unsigned j = (instr >> 4) & 0x3F;
- unsigned k = (instr >> 7) & 7;
- unsigned m = (instr >> 6) & 1;
-
- // immediates
- int s6 = i;
- int s7 = i | (m << 5);
- int s9 = i | (k << 5);
- int s11 = i | ((j & 0x1F) << 5);
- int s12 = i | (j << 5);
-
- // sign-extend
- if (s) {
- s6 |= 0xFFFFFFE0;
- s7 |= 0xFFFFFFC0;
- s9 |= 0xFFFFFF00;
- s11 |= 0xFFFFFC00;
- s12 |= 0xFFFFF800;
- }
-
- while (*fmt) {
- unsigned ex;
- if (*fmt == '+') {
- ex = _ex;
- fmt++;
- } else {
- ex = 0;
- }
- if (*fmt != '@') {
- *buf++ = *fmt++;
- continue;
- }
- switch (*++fmt) {
- case 'A':
- buf = append(buf, regname[a]);
- break;
- case 'B':
- buf = append(buf, regname[b]);
- break;
- case 'C':
- buf = append(buf, regname[c]);
- break;
- case 'F':
- buf = append(buf, alufunc[fhi]);
- break;
- case 'f': // alt alu func
- buf = append(buf, alufunc[flo]);
- break;
- case '6':
- if (ex) {
- tmp = (ev << 4) | (s6 & 15);
- if (tmp & 0x8000) tmp |= 0xFFFF0000;
- } else {
- tmp = s6;
- }
- buf = append_u16(buf, tmp);
- sprintf(note, "(%d)", tmp);
- break;
- case '7':
- buf = append_u16(buf, pc + s7 + 1);
- sprintf(note, "(%d)", pc + s7 + 1);
- break;
- case '9':
- if (ex) {
- tmp = (ev << 4) | (s9 & 15);
- if (tmp & 0x8000) tmp |= 0xFFFF0000;
- } else {
- tmp = s9;
- }
- buf = append_u16(buf, tmp);
- sprintf(note, "(%d)", tmp);
- break;
- case 'b':
- buf = append_u16(buf, pc + s11 + 1);
- sprintf(note, "(%d)", pc + s11 + 1);
- break;
- case 'c':
- buf = append_int(buf, s12);
- break;
- case 'e':
- buf = append_u16(buf, (s12 << 4) & 0xffff);
- break;
- case 0:
- goto done;
- }
- fmt++;
- }
-done:
- if (verbose && note[0]) {
- while ((buf - start) < 22) *buf++ = ' ';
- strcpy(buf, note);
- buf += strlen(note);
- }
- *buf = 0;
-}
-
-struct {
- u16 mask;
- u16 value;
- const char *fmt;
-} decode[] = {
- { 0b0000000000001111, 0b0000000000000000, "@F @C, @A, @B" },
- { 0b0000000000001111, 0b0000000000000001, "NOP (EXT)" },
- { 0b0000000000001111, 0b0000000000000010, "EXT @e" },
- { 0b0000000000001111, 0b0000000000000011, "MOV @C, +@9" },
- { 0b0000000000001111, 0b0000000000000100, "LW @C, [@A, @6]" },
- { 0b0000000000001111, 0b0000000000000101, "SW @C, [@A, @6]" },
- { 0b0000001000001111, 0b0000000000000110, "B @b" },
- { 0b0000001000001111, 0b0000001000000110, "BL @b" },
- { 0b0000000000111111, 0b0000000000000111, "BZ @A, @7" },
- { 0b0000000000111111, 0b0000000000010111, "BNZ @A, @7" },
- { 0b1111110001111111, 0b0000000000100111, "B @A" },
- { 0b1111110001111111, 0b0000000000110111, "BL @A" },
- { 0b1111111111111111, 0b0000000000001000, "NOP (ALU)" }, // ADD R0, R0, 0
- { 0b1111110000001111, 0b0000000000001000, "MOV @C, @A" }, // ADD Rc, Ra, 0
- { 0b1111110000001111, 0b1111110000001100, "NOT @C, @A" }, // XOR Rc, Ra, -1
- { 0b0000000000001000, 0b0000000000001000, "@f @C, @A, +@6" },
- { 0b0000000000000000, 0b0000000000000000, "UND" },
-};
-
-static void disassemble0(char *buf, unsigned pc, unsigned instr,
- unsigned ex, unsigned ev, unsigned verbose) {
- int n = 0;
- for (n = 0 ;; n++) {
- if ((instr & decode[n].mask) == decode[n].value) {
- printinst(buf, pc, instr, decode[n].fmt, ex, ev, verbose);
- return;
- }
- }
- buf[0] = 0;
-}
-
-void disassemble(char *buf, unsigned pc, unsigned instr) {
- static unsigned ex = 0;
- static unsigned ev = 0;
- disassemble0(buf, pc, instr, ex, ev, 1);
- if ((instr & 0xF) == 0x2) {
- ex = 1;
- ev = ((instr >> 10) & 0x1F) | ((instr & 0x3F0) << 1) | ((instr >> 4) & 0x800);
- } else {
- ex = 0;
- }
-}
-
-#ifdef STANDALONE
-int main(int argc, char **argv) {
- char buf[256];
- char line[1024];
- while (fgets(line, 1024, stdin)) {
- unsigned insn = 0xFFFF;
- unsigned ext = 0;
- unsigned pc = 0;
- sscanf(line, "%04x%04x%04x", &insn, &ext, &pc);
- disassemble0(buf, pc, insn, ext >> 12, ext & 0xFFF, 0);
- printf("%s\n", buf);
- fflush(stdout);
- }
- return 0;
-}
-#endif