Major code overhaul
This commit is contained in:
parent
92f5fc88e5
commit
8e490746d1
|
@ -1 +1,2 @@
|
||||||
assembler
|
assembler
|
||||||
|
tags
|
||||||
|
|
9
Makefile
9
Makefile
|
@ -1,2 +1,7 @@
|
||||||
main: assembler.c
|
FILES = assembler.c main.c util.c
|
||||||
${CC} -std=c99 assembler.c -o assembler
|
INCLUDES = -I.
|
||||||
|
CFLAGS = -std=c99
|
||||||
|
OUTFILE = assembler
|
||||||
|
|
||||||
|
main: ${FILES}
|
||||||
|
${CC} ${CFLAGS} ${FILES} -o ${OUTFILE}
|
||||||
|
|
599
assembler.c
599
assembler.c
|
@ -3,103 +3,61 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "tables.h"
|
||||||
|
#include "assembler.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
#define RAM_LIMIT 24577
|
void expandsymbols(SYMBOLARRAY* a, int toaddn);
|
||||||
#define TOP_VAR 16383
|
void pushsymbol(SYMBOLARRAY* a, SYMBOL* s);
|
||||||
#define BOT_VAR 16
|
void freesymbol(SYMBOL* s);
|
||||||
#define ADD_STR_SIZE 7
|
SYMBOL* mksymbol(char* name, int namesize, int val);
|
||||||
#define INST_SIZE 17
|
int getsymbol(ASSEMBLER* a, char* name);
|
||||||
#define C_TOKEN_SIZE 4
|
void skipln(ASSEMBLER* a);
|
||||||
#define INST_LIMIT 32768
|
void readrest(ASSEMBLER* a, int trueln);
|
||||||
|
int isvar(char* var);
|
||||||
|
void initsymbols(SYMBOLARRAY* s);
|
||||||
|
ASSEMBLER* mkassembler(FILE* input);
|
||||||
|
void populatevars(ASSEMBLER* a);
|
||||||
|
SYMBOL* readlabel(ASSEMBLER* a, int trueln);
|
||||||
|
void chop(ASSEMBLER* a);
|
||||||
|
void replacevar(SYMBOL* ln, int val);
|
||||||
|
void preprocess(ASSEMBLER* a);
|
||||||
|
void transa(SYMBOL* ln);
|
||||||
|
char* lookctable(TABLE* t, bool cond, char* token, const char* fieldname, int trueln);
|
||||||
|
void transb(SYMBOL* ln);
|
||||||
|
void translate(ASSEMBLER* a);
|
||||||
|
void gatherinfo(ASSEMBLER* a);
|
||||||
|
void freeassembler(ASSEMBLER* a);
|
||||||
|
|
||||||
#define CMP_SIZE 8
|
void expandsymbols(SYMBOLARRAY* a, int toaddn) {
|
||||||
#define CMP_TABLE_SIZE 37
|
int sum = a->count + toaddn;
|
||||||
const char* cmptable[CMP_TABLE_SIZE] =
|
if(sizeof(SYMBOL*) * sum > a->size) {
|
||||||
{
|
a->size = sizeof(SYMBOL*) * sum * 3;
|
||||||
"0", "0101010",
|
a->items = (SYMBOL**)realloc(a->items, a->size);
|
||||||
"1", "0111111",
|
|
||||||
"-1", "0111010",
|
|
||||||
"D", "0001100",
|
|
||||||
"A", "0110000",
|
|
||||||
"!D", "0001101",
|
|
||||||
"!A", "0110001",
|
|
||||||
"-D", "0001111",
|
|
||||||
"-A", "0110011",
|
|
||||||
"D+1", "0011111",
|
|
||||||
"1+D", "0011111",
|
|
||||||
"A+1", "0110111",
|
|
||||||
"1+A", "0110111",
|
|
||||||
"D-1", "0001110",
|
|
||||||
"A-1", "0110010",
|
|
||||||
"D+A", "0000010",
|
|
||||||
"A+D", "0000010",
|
|
||||||
"D-A", "0010011",
|
|
||||||
"A-D", "0000111",
|
|
||||||
"D&A", "0000000",
|
|
||||||
"A&D", "0000000",
|
|
||||||
"D|A", "0010101",
|
|
||||||
"A|D", "0010101",
|
|
||||||
"M", "1110000",
|
|
||||||
"!M", "1110001",
|
|
||||||
"-M", "1110011",
|
|
||||||
"M+1", "1110111",
|
|
||||||
"1+M", "1110111",
|
|
||||||
"M-1", "1110010",
|
|
||||||
"D+M", "1000010",
|
|
||||||
"M+D", "1000010",
|
|
||||||
"D-M", "1010011",
|
|
||||||
"M-D", "1000111",
|
|
||||||
"D&M", "1000000",
|
|
||||||
"M&D", "1000000",
|
|
||||||
"D|M", "1010101"
|
|
||||||
"M|D", "1010101"
|
|
||||||
};
|
|
||||||
|
|
||||||
#define DEST_SIZE 4
|
|
||||||
#define DEST_TABLE_SIZE 7
|
|
||||||
const char* desttable[] =
|
|
||||||
{
|
|
||||||
"M", "001",
|
|
||||||
"D", "010",
|
|
||||||
"MD", "011",
|
|
||||||
"A", "100",
|
|
||||||
"AM", "101",
|
|
||||||
"AD", "110",
|
|
||||||
"AMD", "111"
|
|
||||||
};
|
|
||||||
|
|
||||||
#define JMP_SIZE 4
|
|
||||||
#define JMP_TABLE_SIZE 7
|
|
||||||
const char* jmptable[] =
|
|
||||||
{
|
|
||||||
"JGT", "001",
|
|
||||||
"JEQ", "010",
|
|
||||||
"JGE", "011",
|
|
||||||
"JLT", "100",
|
|
||||||
"JNE", "101",
|
|
||||||
"JLE", "110",
|
|
||||||
"JMP", "111"
|
|
||||||
};
|
|
||||||
|
|
||||||
struct symbol {
|
|
||||||
char* name;
|
|
||||||
int value;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct line {
|
|
||||||
char* ln;
|
|
||||||
int truen;
|
|
||||||
};
|
|
||||||
|
|
||||||
void freesymbols(struct symbol** symbols, int symbolsind) {
|
|
||||||
for(int i = 0; i < symbolsind; i++) {
|
|
||||||
free(symbols[i]->name);
|
|
||||||
free(symbols[i]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct symbol* mksymb(char* name, int namesize, int val) {
|
void pushsymbol(SYMBOLARRAY* a, SYMBOL* s) {
|
||||||
struct symbol* s = (struct symbol*)malloc(sizeof(struct symbol));
|
expandsymbols(a, 1);
|
||||||
|
a->items[a->count] = s;
|
||||||
|
a->count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void freesymbol(SYMBOL* s) {
|
||||||
|
free(s->name);
|
||||||
|
free(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void freesymbols(SYMBOLARRAY* a) {
|
||||||
|
for(int i = 0; i < a->count; i++)
|
||||||
|
freesymbol(a->items[i]);
|
||||||
|
free(a->items);
|
||||||
|
free(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
SYMBOL* mksymbol(char* name, int namesize, int val) {
|
||||||
|
SYMBOL* s = (SYMBOL*)malloc(sizeof(SYMBOL));
|
||||||
char* heapname = (char*)malloc(namesize);
|
char* heapname = (char*)malloc(namesize);
|
||||||
strcpy(heapname, name);
|
strcpy(heapname, name);
|
||||||
s->name = heapname;
|
s->name = heapname;
|
||||||
|
@ -107,39 +65,39 @@ struct symbol* mksymb(char* name, int namesize, int val) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getsymb(char* symb, struct symbol** vars, int varscount, struct symbol** labels, int labelscount) {
|
int getsymbol(ASSEMBLER* a, char* name) {
|
||||||
for(int i = 0; i < varscount; i++)
|
for(int i = 0; i < a->vars->count; i++)
|
||||||
if(strcmp(vars[i]->name, symb) == 0)
|
if(strcmp(a->vars->items[i]->name, name) == 0)
|
||||||
return vars[i]->value;
|
return a->vars->items[i]->value;
|
||||||
|
|
||||||
for(int i = 0; i < labelscount; i++)
|
for(int i = 0; i < a->labels->count; i++)
|
||||||
if(strcmp(labels[i]->name, symb) == 0)
|
if(strcmp(a->labels->items[i]->name, name) == 0)
|
||||||
return labels[i]->value;
|
return a->labels->items[i]->value;
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void skipln(FILE* input) {
|
void skipln(ASSEMBLER* a) {
|
||||||
char c;
|
char c;
|
||||||
while(c = fgetc(input), c != -1)
|
while(c = fgetc(a->input), c != -1)
|
||||||
if(c == '\n')
|
if(c == '\n')
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
void readrest(FILE* input, int trueln) {
|
void readrest(ASSEMBLER* a, int trueln) {
|
||||||
char c;
|
char c;
|
||||||
while(c = fgetc(input), c != -1) {
|
while(c = fgetc(a->input), c != -1) {
|
||||||
if(c == '\n')
|
if(c == '\n')
|
||||||
break;
|
break;
|
||||||
if(isspace(c))
|
if(isspace(c))
|
||||||
continue;
|
continue;
|
||||||
if(c == '/') {
|
if(c == '/') {
|
||||||
char nc = fgetc(input);
|
char nc = fgetc(a->input);
|
||||||
if(nc == '/') {
|
if(nc == '/') {
|
||||||
skipln(input);
|
skipln(a);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ungetc(nc, input);
|
ungetc(nc, a->input);
|
||||||
}
|
}
|
||||||
fprintf(stderr, "Unexpected '%c' at line '%i'\n", c, trueln);
|
fprintf(stderr, "Unexpected '%c' at line '%i'\n", c, trueln);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -158,96 +116,84 @@ int isvar(char* var) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void populatevars(struct symbol** vars, int* varscount) {
|
void initsymbols(SYMBOLARRAY* s) {
|
||||||
// First five
|
s->size = s->count * sizeof(SYMBOL*);
|
||||||
|
s->items = (SYMBOL**)malloc(s->size);
|
||||||
|
s->count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSEMBLER* mkassembler(FILE* input) {
|
||||||
|
ASSEMBLER* a = (ASSEMBLER*)malloc(sizeof(ASSEMBLER));
|
||||||
|
a->lns = (SYMBOLARRAY*)malloc(sizeof(SYMBOLARRAY));
|
||||||
|
a->labels = (SYMBOLARRAY*)malloc(sizeof(SYMBOLARRAY));
|
||||||
|
a->vars = (SYMBOLARRAY*)malloc(sizeof(SYMBOLARRAY));
|
||||||
|
a->input = input;
|
||||||
|
|
||||||
|
gatherinfo(a);
|
||||||
|
|
||||||
|
initsymbols(a->lns);
|
||||||
|
initsymbols(a->labels);
|
||||||
|
a->vars->count = 80; // arbitrary number for initial size
|
||||||
|
initsymbols(a->vars);
|
||||||
|
|
||||||
|
populatevars(a);
|
||||||
|
chop(a);
|
||||||
|
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
void populatevars(ASSEMBLER* a) {
|
||||||
const int firstamnt = 5;
|
const int firstamnt = 5;
|
||||||
|
const int ramvamnt = 16; //max: 19
|
||||||
|
const int specialamt = 2;
|
||||||
|
const int sum = firstamnt + ramvamnt + specialamt;
|
||||||
|
|
||||||
|
// realloc if necessary
|
||||||
|
expandsymbols(a->vars, sum);
|
||||||
|
|
||||||
|
// update varscount to new index
|
||||||
|
a->vars->count = sum;
|
||||||
|
|
||||||
|
// first five
|
||||||
char* labels[] = { "SP", "LCL", "ARG", "THIS", "THAT" };
|
char* labels[] = { "SP", "LCL", "ARG", "THIS", "THAT" };
|
||||||
for(int i = 0; i < firstamnt; i++) {
|
for(int i = 0; i < firstamnt; i++) {
|
||||||
vars[i] = mksymb(labels[i], strlen(labels[i])+1, i);
|
a->vars->items[i] = mksymbol(labels[i], strlen(labels[i])+1, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
// RAM variables (R0-R15)
|
// RAM variables (R0-R15)
|
||||||
const int ramvamnt = 16; //max: 19
|
|
||||||
const int asciioff = 48;
|
const int asciioff = 48;
|
||||||
char ramvname[4];
|
char ramvname[4];
|
||||||
ramvname[0] = 'R';
|
ramvname[0] = 'R';
|
||||||
ramvname[2] = '\0';
|
ramvname[2] = '\0';
|
||||||
for(int i = 0; i < (ramvamnt/10)*10; i++) {
|
int tmptarg = (ramvamnt/10)*10;
|
||||||
|
for(int i = 0; i < tmptarg; i++) {
|
||||||
ramvname[1] = (char)(i+asciioff);
|
ramvname[1] = (char)(i+asciioff);
|
||||||
vars[firstamnt+i] = mksymb(ramvname, 3, i);
|
a->vars->items[firstamnt+i] = mksymbol(ramvname, 3, i);
|
||||||
}
|
}
|
||||||
ramvname[1] = '1';
|
ramvname[1] = '1';
|
||||||
ramvname[3] = '\0';
|
ramvname[3] = '\0';
|
||||||
for(int i = 10; i < ramvamnt; i++) {
|
for(int i = 10; i < ramvamnt; i++) {
|
||||||
ramvname[2] = (char)((i%10)+asciioff);
|
ramvname[2] = (char)((i%10)+asciioff);
|
||||||
vars[firstamnt+i] = mksymb(ramvname, 4, i);
|
a->vars->items[firstamnt+i] = mksymbol(ramvname, 4, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
// SCREEN var
|
// SCREEN var
|
||||||
vars[firstamnt+ramvamnt] = mksymb("SCREEN", 7, 16384);
|
a->vars->items[firstamnt+ramvamnt] = mksymbol("SCREEN", 7, 16384);
|
||||||
// KBD var
|
// KBD var
|
||||||
vars[firstamnt+ramvamnt+1] = mksymb("KBD", 4, 24576);
|
a->vars->items[firstamnt+ramvamnt+1] = mksymbol("KBD", 4, 24576);
|
||||||
// update varscount to new index
|
|
||||||
*varscount = firstamnt+ramvamnt+2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void gatherinfo(FILE* input, int* lnscount, int* labelscount, int* maxwidth) {
|
SYMBOL* readlabel(ASSEMBLER* a, int trueln) {
|
||||||
char c;
|
char* name = (char*)malloc(sizeof(char)*(a->maxwidth-1));
|
||||||
unsigned char readsmt = 0;
|
|
||||||
unsigned char comment = 0;
|
|
||||||
int truelnscount = 1;
|
|
||||||
int lnwidth = 1;
|
|
||||||
while(c = fgetc(input), c != -1) {
|
|
||||||
if(c == '\n') {
|
|
||||||
truelnscount++;
|
|
||||||
comment = 0;
|
|
||||||
if(lnwidth > *maxwidth)
|
|
||||||
*maxwidth = lnwidth;
|
|
||||||
if(readsmt) {
|
|
||||||
if(*lnscount == INST_LIMIT) {
|
|
||||||
fprintf(stderr, "Reached instruction limit (%i); line %i\n", INST_LIMIT, truelnscount);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
(*lnscount)++;
|
|
||||||
}
|
|
||||||
readsmt = 0;
|
|
||||||
lnwidth = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if(comment)
|
|
||||||
continue;
|
|
||||||
if(c == '(') {
|
|
||||||
(*labelscount)++;
|
|
||||||
comment = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if(c == '/') {
|
|
||||||
char nc = fgetc(input);
|
|
||||||
if(nc == '/') {
|
|
||||||
comment = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ungetc(nc, input);
|
|
||||||
}
|
|
||||||
if(isspace(c)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
readsmt = 1;
|
|
||||||
lnwidth++;
|
|
||||||
}
|
|
||||||
rewind(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct symbol* readlabel(FILE* input, int ln, int trueln, int lnwidth) {
|
|
||||||
char* name = (char*)malloc(sizeof(char)*(lnwidth-1));
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
char c;
|
char c;
|
||||||
while(c = fgetc(input), c != -1) {
|
int maxind = a->maxwidth-2;
|
||||||
|
while(c = fgetc(a->input), c != -1) {
|
||||||
if(c == ')')
|
if(c == ')')
|
||||||
break;
|
break;
|
||||||
if(i == lnwidth-2) {
|
if(i == maxind) {
|
||||||
fprintf(stderr, "Label width bigger than the maximum (%i characters); line %i\n",
|
fprintf(stderr, "Label width bigger than the maximum (%i characters); line %i\n",
|
||||||
lnwidth-2, trueln+1);
|
maxind, trueln+1);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if(c == '\n') {
|
if(c == '\n') {
|
||||||
|
@ -262,28 +208,29 @@ struct symbol* readlabel(FILE* input, int ln, int trueln, int lnwidth) {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
name[i] = '\0';
|
name[i] = '\0';
|
||||||
readrest(input, trueln);
|
readrest(a, trueln);
|
||||||
struct symbol* l = (struct symbol*)malloc(sizeof(struct symbol));
|
SYMBOL* l = (SYMBOL*)malloc(sizeof(SYMBOL));
|
||||||
l->name = name;
|
l->name = name;
|
||||||
l->value = ln;
|
l->value = a->lns->count;
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Splits the stream into an array of strings, stripping comments, white spaces and labels
|
// Splits the stream into an array of strings, stripping comments, white spaces and labels
|
||||||
// Requires vars array to check for duplicate symbols, but doesn't modify it
|
// Requires vars array to check for duplicate symbols, but doesn't modify it
|
||||||
int chop(FILE* input, struct symbol** vars, int varscount, struct symbol** labels, int* labelscount, struct line** lns, int lnwidth) {
|
void chop(ASSEMBLER* a) {
|
||||||
char c;
|
char c;
|
||||||
char tmpln[lnwidth];
|
char tmpln[a->maxwidth];
|
||||||
|
int lnind = 0;
|
||||||
int lnscount = 0;
|
int lnscount = 0;
|
||||||
int truelnscount = 1;
|
int truelnscount = 1;
|
||||||
int lnind = 0;
|
|
||||||
int comment = 0;
|
bool comment = false;
|
||||||
int spacedln = 0;
|
bool spacedln = false;
|
||||||
while(c = fgetc(input), c != -1) {
|
while(c = fgetc(a->input), c != -1) {
|
||||||
if(c == '\n') {
|
if(c == '\n') {
|
||||||
if(comment) {
|
if(comment) {
|
||||||
comment = 0;
|
comment = false;
|
||||||
ungetc(c, input);
|
ungetc(c, a->input);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
truelnscount++;
|
truelnscount++;
|
||||||
|
@ -292,16 +239,11 @@ int chop(FILE* input, struct symbol** vars, int varscount, struct symbol** label
|
||||||
|
|
||||||
tmpln[lnind] = '\0';
|
tmpln[lnind] = '\0';
|
||||||
|
|
||||||
char* newln = (char*)malloc(sizeof(char)*(lnind+1));
|
pushsymbol(a->lns, mksymbol(tmpln, lnind+1, truelnscount));
|
||||||
strcpy(newln, tmpln);
|
|
||||||
struct line* s = (struct line*)malloc(sizeof(struct line));
|
|
||||||
s->ln = newln;
|
|
||||||
s->truen = truelnscount;
|
|
||||||
lns[lnscount] = s;
|
|
||||||
|
|
||||||
lnscount++;
|
|
||||||
lnind = 0;
|
lnind = 0;
|
||||||
spacedln = 0;
|
spacedln = false;
|
||||||
|
lnscount++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,35 +252,34 @@ int chop(FILE* input, struct symbol** vars, int varscount, struct symbol** label
|
||||||
|
|
||||||
if(isspace(c)) {
|
if(isspace(c)) {
|
||||||
if(lnind)
|
if(lnind)
|
||||||
spacedln = 1;
|
spacedln = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(c == '(') {
|
if(c == '(') {
|
||||||
if(lnind != 0) {
|
if(lnind) {
|
||||||
fprintf(stderr, "Unexpected char '%c'; line %i:%i\n", c, truelnscount, lnind+1);
|
fprintf(stderr, "Unexpected char '%c'; line %i:%i\n", c, truelnscount, lnind+1);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct symbol* l = readlabel(input, lnscount, truelnscount, lnwidth);
|
SYMBOL* l = readlabel(a, truelnscount);
|
||||||
if(getsymb(l->name, vars, varscount, labels, *labelscount) != -1) {
|
if(getsymbol(a, l->name) != -1) {
|
||||||
fprintf(stderr, "Already defined symbol '%s'; line %i\n", l->name, truelnscount);
|
fprintf(stderr, "Already defined symbol '%s'; line %i\n", l->name, truelnscount);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
labels[*labelscount] = l;
|
pushsymbol(a->labels, l);
|
||||||
(*labelscount)++;
|
|
||||||
truelnscount++;
|
truelnscount++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(c == '/') {
|
if(c == '/') {
|
||||||
char nc = fgetc(input);
|
char nc = fgetc(a->input);
|
||||||
if(nc == '/') {
|
if(nc == '/') {
|
||||||
comment = 1;
|
comment = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ungetc(nc, input);
|
ungetc(nc, a->input);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(spacedln) {
|
if(spacedln) {
|
||||||
|
@ -346,91 +287,98 @@ int chop(FILE* input, struct symbol** vars, int varscount, struct symbol** label
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(lnwidth-1 == lnind) {
|
|
||||||
fprintf(stderr, "Reached line width limit (%i); line %i\n", lnwidth, lnscount+1);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpln[lnind] = c;
|
tmpln[lnind] = c;
|
||||||
lnind++;
|
lnind++;
|
||||||
}
|
}
|
||||||
return lnscount;
|
fclose(a->input);
|
||||||
}
|
}
|
||||||
|
|
||||||
void replacevar(struct line* ln, int val) {
|
void replacevar(SYMBOL* ln, int val) {
|
||||||
free(ln->ln);
|
free(ln->content);
|
||||||
char* newln = (char *)malloc(sizeof(char)*ADD_STR_SIZE);
|
int size = sizeof(char)*(countplaces(val) + 2);
|
||||||
snprintf(newln, ADD_STR_SIZE, "@%i", val);
|
char* newln = (char *)malloc(size);
|
||||||
ln->ln = newln;
|
snprintf(newln, size, "@%i", val);
|
||||||
|
ln->content = newln;
|
||||||
}
|
}
|
||||||
|
|
||||||
void stripvars(struct symbol** vars, int* varscount, struct symbol** labels, int* labelscount, struct line** lns, int lnscount) {
|
void preprocess(ASSEMBLER* a) {
|
||||||
int varsramind = BOT_VAR;
|
int varsramind = BOTTOM_VAR;
|
||||||
for(int i = 0; i < lnscount; i++) {
|
for(int i = 0; i < a->lncount; i++) {
|
||||||
if(lns[i]->ln[0] == '@') {
|
if(a->lns->items[i]->content[0] == '@') {
|
||||||
char* afterat = lns[i]->ln+sizeof(char);
|
char* afterat = a->lns->items[i]->content+sizeof(char);
|
||||||
if(isvar(afterat)) {
|
if(isvar(afterat)) {
|
||||||
int val = getsymb(afterat, vars, *varscount, labels, *labelscount);
|
int val = getsymbol(a, afterat);
|
||||||
if(val == -1) {
|
if(val == -1) {
|
||||||
if(varsramind == RAM_LIMIT) {
|
if(varsramind == RAM_LIMIT) {
|
||||||
fprintf(stderr, "Variable amount reached RAM limit (%i); line %i\n", RAM_LIMIT, lns[i]->truen);
|
fprintf(stderr, "Variable amount reached RAM limit (%i); line %i\n", RAM_LIMIT, a->lns->items[i]->truen);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
struct symbol* var = mksymb(afterat, strlen(afterat)+1, varsramind);
|
SYMBOL* var = mksymbol(afterat, strlen(afterat)+1, varsramind);
|
||||||
vars[*varscount] = var;
|
|
||||||
(*varscount)++;
|
|
||||||
varsramind++;
|
varsramind++;
|
||||||
|
pushsymbol(a->vars, var);
|
||||||
val = var->value;
|
val = var->value;
|
||||||
}
|
}
|
||||||
replacevar(lns[i], val);
|
replacevar(a->lns->items[i], val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void transa(char* in, char* out, int trueln) {
|
void transa(SYMBOL* ln) {
|
||||||
int add = atoi(in+sizeof(char));
|
int add = atoi(ln->content+sizeof(char));
|
||||||
|
|
||||||
if(add >= INST_LIMIT) {
|
if(add >= INST_LIMIT) {
|
||||||
fprintf(stderr, "'A' instruction cannot reference addresses bigger than %i; line %i\n", INST_LIMIT-1, trueln);
|
fprintf(stderr, "'A' instruction cannot reference addresses bigger than %i; line %i\n", INST_LIMIT-1, ln->truen);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char* out = (char*)malloc(sizeof(char) * INST_SIZE);
|
||||||
|
|
||||||
int lastbit = 1 << 15;
|
int lastbit = 1 << 15;
|
||||||
for(int i = INST_SIZE-2;i > 0; i--) {
|
for(int i = INST_SIZE-2; i > 0; i--) {
|
||||||
if(add & (lastbit >> i))
|
if(add & (lastbit >> i))
|
||||||
out[i] = '1';
|
out[i] = '1';
|
||||||
else
|
else
|
||||||
out[i] = '0';
|
out[i] = '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
out[INST_SIZE-1] = '\0';
|
out[INST_SIZE-1] = '\0';
|
||||||
out[0] = '0';
|
out[0] = '0';
|
||||||
|
|
||||||
|
free(ln->content);
|
||||||
|
ln->content = out;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lookctable(char* out, int outsize, const char** table, int tablesize, int cond, char* token, const char* fieldname, int trueln) {
|
char* lookctable(TABLE* t, bool cond, char* token, const char* fieldname, int trueln) {
|
||||||
|
char* out = (char*)malloc(t->instsize);
|
||||||
|
|
||||||
if(!cond) {
|
if(!cond) {
|
||||||
for(int i = 0; i < outsize-1; i++)
|
int targsize = t->instsize - 1;
|
||||||
|
for(int i = 0; i < targsize; i++)
|
||||||
out[i] = '0';
|
out[i] = '0';
|
||||||
out[outsize-1] = '\0';
|
out[t->instsize-1] = '\0';
|
||||||
return;
|
return out;
|
||||||
}
|
}
|
||||||
for(int i = 0; i < tablesize; i++)
|
for(int i = 0; i < t->size; i++)
|
||||||
if(strcmp(table[2*i], token) == 0) {
|
if(strcmp(t->table[2*i], token) == 0) {
|
||||||
strcpy(out, table[(2*i)+1]);
|
strcpy(out, t->table[(2*i)+1]);
|
||||||
return;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "Unexpected token '%s' for %s field; line %i\n", token, fieldname, trueln);
|
fprintf(stderr, "Unexpected token '%s' for %s field; line %i\n", token, fieldname, trueln);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void transb(char* in, char* out, int trueln) {
|
void transb(SYMBOL* ln) {
|
||||||
int hasjmp = 0;
|
bool hasjmp = false;
|
||||||
int hasdest = 0;
|
bool hasdest = false;
|
||||||
int hascmp = 0;
|
bool hascmp = false;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int tmpi = 0;
|
int tmpi = 0;
|
||||||
char tmp[C_TOKEN_SIZE], dest[C_TOKEN_SIZE], cmp[C_TOKEN_SIZE], jmp[C_TOKEN_SIZE];
|
char tmp[C_TOKEN_SIZE], dest[C_TOKEN_SIZE], cmp[C_TOKEN_SIZE], jmp[C_TOKEN_SIZE];
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
if(in[i] == '\0') {
|
if(ln->content[i] == '\0') {
|
||||||
tmp[tmpi] = '\0';
|
tmp[tmpi] = '\0';
|
||||||
if(hasjmp)
|
if(hasjmp)
|
||||||
strcpy(jmp, tmp);
|
strcpy(jmp, tmp);
|
||||||
|
@ -440,22 +388,22 @@ void transb(char* in, char* out, int trueln) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(tmpi == C_TOKEN_SIZE-1) {
|
if(tmpi == C_TOKEN_SIZE-1) {
|
||||||
fprintf(stderr, "Unexpected char '%c'; line %i:%i;\n", in[i], trueln, i+1);
|
fprintf(stderr, "Unexpected char '%c'; line %i:%i;\n", ln->content[i], ln->truen, i+1);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(in[i] == '=' && !hasdest && hascmp) {
|
if(ln->content[i] == '=' && !hasdest && hascmp) {
|
||||||
hascmp = 0;
|
hascmp = false;
|
||||||
hasdest = 1;
|
hasdest = true;
|
||||||
tmp[tmpi] = '\0';
|
tmp[tmpi] = '\0';
|
||||||
strcpy(dest, tmp);
|
strcpy(dest, tmp);
|
||||||
tmpi = 0;
|
tmpi = 0;
|
||||||
i++;
|
i++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(in[i] == ';' && !hasjmp && hascmp) {
|
if(ln->content[i] == ';' && !hasjmp && hascmp) {
|
||||||
hascmp = 0;
|
hascmp = false;
|
||||||
hasjmp = 1;
|
hasjmp = true;
|
||||||
tmp[tmpi] = '\0';
|
tmp[tmpi] = '\0';
|
||||||
strcpy(cmp, tmp);
|
strcpy(cmp, tmp);
|
||||||
tmpi = 0;
|
tmpi = 0;
|
||||||
|
@ -464,105 +412,90 @@ void transb(char* in, char* out, int trueln) {
|
||||||
}
|
}
|
||||||
|
|
||||||
hascmp = 1;
|
hascmp = 1;
|
||||||
tmp[tmpi] = in[i];
|
tmp[tmpi] = ln->content[i];
|
||||||
tmpi++;
|
tmpi++;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
char rawdest[DEST_SIZE];
|
char* rawdest = lookctable(&desttable, hasdest, dest, "dest", ln->truen);
|
||||||
lookctable(rawdest, DEST_SIZE, desttable, DEST_TABLE_SIZE, hasdest, dest, "dest", trueln);
|
char* rawjmp = lookctable(&jmptable, hasjmp, jmp, "jump", ln->truen);
|
||||||
char rawjmp[JMP_SIZE];
|
char* rawcmp = lookctable(&cmptable, 1, cmp, "comp", ln->truen);
|
||||||
lookctable(rawjmp, JMP_SIZE, jmptable, JMP_TABLE_SIZE, hasjmp, jmp, "jump", trueln);
|
|
||||||
char rawcmp[CMP_SIZE];
|
int sz = sizeof(char) * INST_SIZE;
|
||||||
lookctable(rawcmp, CMP_SIZE, cmptable, CMP_TABLE_SIZE, 1, cmp, "comp", trueln);
|
char* out = (char*)malloc(sz);
|
||||||
sprintf(out, "111%s%s%s", rawcmp, rawdest, rawjmp);
|
snprintf(out, sz, "111%s%s%s", rawcmp, rawdest, rawjmp);
|
||||||
|
|
||||||
|
free(ln->content);
|
||||||
|
ln->content = out;
|
||||||
|
free(rawdest);
|
||||||
|
free(rawjmp);
|
||||||
|
free(rawcmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
char** translate(struct line** lns, int lnscount) {
|
void translate(ASSEMBLER* a) {
|
||||||
char** assembled = (char**)malloc(sizeof(char*)*lnscount);
|
for(int i = 0; i < a->lns->count; i++)
|
||||||
for(int i = 0; i < lnscount; i++)
|
if(a->lns->items[i]->content[0] == '@')
|
||||||
assembled[i] = (char*)malloc(sizeof(char)*INST_SIZE);
|
transa(a->lns->items[i]);
|
||||||
|
|
||||||
for(int i = 0; i < lnscount; i++)
|
|
||||||
if(lns[i]->ln[0] == '@')
|
|
||||||
transa(lns[i]->ln, assembled[i], lns[i]->truen);
|
|
||||||
else
|
else
|
||||||
transb(lns[i]->ln, assembled[i], lns[i]->truen);
|
transb(a->lns->items[i]);
|
||||||
return assembled;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void getoutname(char* fname, int fnamelen, char* outf) {
|
void gatherinfo(ASSEMBLER* a) {
|
||||||
strcpy(outf, fname);
|
char c;
|
||||||
strcpy(outf+(fnamelen*sizeof(char))-(3*sizeof(char)), "hack");
|
bool readsmt = false;
|
||||||
|
bool comment = false;
|
||||||
|
int lnwidth = 1;
|
||||||
|
|
||||||
|
a->truelnscount = 1;
|
||||||
|
a->maxwidth = 0;
|
||||||
|
a->labels->count = 0;
|
||||||
|
a->lns->count = 0;
|
||||||
|
|
||||||
|
while(c = fgetc(a->input), c != -1) {
|
||||||
|
if(c == '\n') {
|
||||||
|
a->truelnscount++;
|
||||||
|
comment = false;
|
||||||
|
if(lnwidth > a->maxwidth)
|
||||||
|
a->maxwidth = lnwidth;
|
||||||
|
if(readsmt) {
|
||||||
|
if(a->lns->count == INST_LIMIT) {
|
||||||
|
fprintf(stderr, "Reached instruction limit (%i); line %i\n", INST_LIMIT, a->truelnscount);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
a->lns->count++;
|
||||||
|
}
|
||||||
|
readsmt = false;
|
||||||
|
lnwidth = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(comment)
|
||||||
|
continue;
|
||||||
|
if(c == '(') {
|
||||||
|
a->labels->count++;
|
||||||
|
comment = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(c == '/') {
|
||||||
|
char nc = fgetc(a->input);
|
||||||
|
if(nc == '/') {
|
||||||
|
comment = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ungetc(nc, a->input);
|
||||||
|
}
|
||||||
|
if(isspace(c)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
readsmt = true;
|
||||||
|
lnwidth++;
|
||||||
|
}
|
||||||
|
rewind(a->input);
|
||||||
|
a->lncount = a->lns->count;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
void freeassembler(ASSEMBLER* a) {
|
||||||
if(argc < 2) {
|
freesymbols(a->lns);
|
||||||
printf("Usage: %s {input}\n", argv[0]);
|
freesymbols(a->vars);
|
||||||
return 1;
|
freesymbols(a->labels);
|
||||||
}
|
free(a);
|
||||||
|
|
||||||
int fnamelen = strlen(argv[1]);
|
|
||||||
int invalidext = strcmp(argv[1]+(fnamelen*sizeof(char)-(4*sizeof(char))), ".asm");
|
|
||||||
if(invalidext) {
|
|
||||||
fprintf(stderr, "Invalid extension (must be *.asm)\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
FILE* input = fopen(argv[1], "r");
|
|
||||||
|
|
||||||
if(input == NULL) {
|
|
||||||
fprintf(stderr, "%s\n", strerror(errno));
|
|
||||||
return errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
// info gathering
|
|
||||||
int lnscount = 0;
|
|
||||||
int labelscount = 0;
|
|
||||||
int lnwidth = 0;
|
|
||||||
gatherinfo(input, &lnscount, &labelscount, &lnwidth);
|
|
||||||
struct line** lns = (struct line**)malloc(sizeof(struct line*)*lnscount); // has to be on the heap; can be huge and cause a stack overflow
|
|
||||||
|
|
||||||
// line chopping
|
|
||||||
struct symbol** labels = (struct symbol**)malloc(sizeof(struct symbol*)*labelscount); // same for this one
|
|
||||||
labelscount = 0;
|
|
||||||
|
|
||||||
struct symbol* vars[TOP_VAR - BOT_VAR];
|
|
||||||
int varscount = 0;
|
|
||||||
populatevars(vars, &varscount);
|
|
||||||
|
|
||||||
lnscount = chop(input, vars, varscount, labels, &labelscount, lns, lnwidth);
|
|
||||||
fclose(input);
|
|
||||||
|
|
||||||
// variable substitution
|
|
||||||
stripvars(vars, &varscount, labels, &labelscount, lns, lnscount);
|
|
||||||
freesymbols(vars, varscount);
|
|
||||||
freesymbols(labels, labelscount);
|
|
||||||
free(labels);
|
|
||||||
|
|
||||||
// actual translation
|
|
||||||
char** bin = translate(lns, lnscount);
|
|
||||||
for(int i = 0; i < lnscount; i++) {
|
|
||||||
free(lns[i]->ln);
|
|
||||||
free(lns[i]);
|
|
||||||
}
|
|
||||||
free(lns);
|
|
||||||
|
|
||||||
// file output
|
|
||||||
char outf[fnamelen+2];
|
|
||||||
getoutname(argv[1], fnamelen, outf);
|
|
||||||
|
|
||||||
FILE* output = fopen(outf, "w");
|
|
||||||
|
|
||||||
if(output == NULL) {
|
|
||||||
fprintf(stderr, "%s\n", strerror(errno));
|
|
||||||
return errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int i = 0; i < lnscount; i++) {
|
|
||||||
fprintf(output, "%s\n", bin[i]);
|
|
||||||
free(bin[i]);
|
|
||||||
}
|
|
||||||
free(bin);
|
|
||||||
fclose(output);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
#ifndef ASSEMBLER_H
|
||||||
|
#define ASSEMBLER_H
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define RAM_LIMIT 24577
|
||||||
|
#define TOP_VAR 16383
|
||||||
|
#define BOTTOM_VAR 16
|
||||||
|
#define INST_SIZE 17
|
||||||
|
#define C_TOKEN_SIZE 4
|
||||||
|
#define INST_LIMIT 1<<15
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
union {
|
||||||
|
char* name;
|
||||||
|
char* content;
|
||||||
|
};
|
||||||
|
union {
|
||||||
|
int value;
|
||||||
|
int truen;
|
||||||
|
};
|
||||||
|
} SYMBOL;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
SYMBOL** items;
|
||||||
|
int count;
|
||||||
|
int size;
|
||||||
|
} SYMBOLARRAY;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
FILE* input;
|
||||||
|
|
||||||
|
int maxwidth;
|
||||||
|
int truelnscount;
|
||||||
|
int lncount;
|
||||||
|
|
||||||
|
SYMBOLARRAY* lns;
|
||||||
|
|
||||||
|
SYMBOLARRAY* labels;
|
||||||
|
|
||||||
|
SYMBOLARRAY* vars;
|
||||||
|
} ASSEMBLER;
|
||||||
|
|
||||||
|
ASSEMBLER* mkassembler(FILE* input);
|
||||||
|
void preprocess(ASSEMBLER* a);
|
||||||
|
void translate(ASSEMBLER* a);
|
||||||
|
void freeassembler(ASSEMBLER* a);
|
||||||
|
#endif
|
|
@ -0,0 +1,59 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "assembler.h"
|
||||||
|
|
||||||
|
char* getoutname(char* fname, int fnamelen) {
|
||||||
|
char* outf = (char*)malloc(sizeof(char) * fnamelen + 2);
|
||||||
|
strcpy(outf, fname);
|
||||||
|
// .hack
|
||||||
|
strcpy( (outf + ((fnamelen * sizeof(char)) - (3 * sizeof(char)))), "hack");
|
||||||
|
return outf;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
if(argc < 2) {
|
||||||
|
printf("Usage: %s {input}\n", argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fnamelen = strlen(argv[1]);
|
||||||
|
int invalidext = strcmp(argv[1]+(fnamelen*sizeof(char)-(4*sizeof(char))), ".asm");
|
||||||
|
if(invalidext) {
|
||||||
|
fprintf(stderr, "Invalid extension (must be named lide Xxx.asm)\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
FILE* input = fopen(argv[1], "r");
|
||||||
|
|
||||||
|
if(input == NULL) {
|
||||||
|
fprintf(stderr, "%s\n", strerror(errno));
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSEMBLER* a = mkassembler(input);
|
||||||
|
|
||||||
|
// variable substitution
|
||||||
|
preprocess(a);
|
||||||
|
|
||||||
|
// actual translation
|
||||||
|
translate(a);
|
||||||
|
|
||||||
|
// file output
|
||||||
|
char* outf = getoutname(argv[1], fnamelen);
|
||||||
|
FILE* output = fopen(outf, "w");
|
||||||
|
|
||||||
|
if(output == NULL) {
|
||||||
|
fprintf(stderr, "%s\n", strerror(errno));
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < a->lns->count; i++) {
|
||||||
|
fprintf(output, "%s\n", a->lns->items[i]->content);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(outf);
|
||||||
|
freeassembler(a);
|
||||||
|
fclose(output);
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,88 @@
|
||||||
|
#ifndef TABLES
|
||||||
|
#define TABLES
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char** table;
|
||||||
|
const int size;
|
||||||
|
const int instsize;
|
||||||
|
} TABLE;
|
||||||
|
|
||||||
|
const char* cmptablestrs[] = {
|
||||||
|
"0", "0101010",
|
||||||
|
"1", "0111111",
|
||||||
|
"-1", "0111010",
|
||||||
|
"D", "0001100",
|
||||||
|
"A", "0110000",
|
||||||
|
"!D", "0001101",
|
||||||
|
"!A", "0110001",
|
||||||
|
"-D", "0001111",
|
||||||
|
"-A", "0110011",
|
||||||
|
"D+1", "0011111",
|
||||||
|
"1+D", "0011111",
|
||||||
|
"A+1", "0110111",
|
||||||
|
"1+A", "0110111",
|
||||||
|
"D-1", "0001110",
|
||||||
|
"A-1", "0110010",
|
||||||
|
"D+A", "0000010",
|
||||||
|
"A+D", "0000010",
|
||||||
|
"D-A", "0010011",
|
||||||
|
"A-D", "0000111",
|
||||||
|
"D&A", "0000000",
|
||||||
|
"A&D", "0000000",
|
||||||
|
"D|A", "0010101",
|
||||||
|
"A|D", "0010101",
|
||||||
|
"M", "1110000",
|
||||||
|
"!M", "1110001",
|
||||||
|
"-M", "1110011",
|
||||||
|
"M+1", "1110111",
|
||||||
|
"1+M", "1110111",
|
||||||
|
"M-1", "1110010",
|
||||||
|
"D+M", "1000010",
|
||||||
|
"M+D", "1000010",
|
||||||
|
"D-M", "1010011",
|
||||||
|
"M-D", "1000111",
|
||||||
|
"D&M", "1000000",
|
||||||
|
"M&D", "1000000",
|
||||||
|
"D|M", "1010101",
|
||||||
|
"M|D", "1010101"
|
||||||
|
};
|
||||||
|
TABLE cmptable =
|
||||||
|
{
|
||||||
|
.table = cmptablestrs,
|
||||||
|
.size = sizeof(cmptablestrs) / sizeof(char*) / 2,
|
||||||
|
.instsize = 8 * sizeof(char)
|
||||||
|
};
|
||||||
|
|
||||||
|
const char* desttablestrs[] = {
|
||||||
|
"M", "001",
|
||||||
|
"D", "010",
|
||||||
|
"MD", "011",
|
||||||
|
"A", "100",
|
||||||
|
"AM", "101",
|
||||||
|
"AD", "110",
|
||||||
|
"AMD", "111"
|
||||||
|
};
|
||||||
|
TABLE desttable =
|
||||||
|
{
|
||||||
|
.table = desttablestrs,
|
||||||
|
.size = sizeof(desttablestrs) / sizeof(char*) / 2,
|
||||||
|
.instsize = 4 * sizeof(char)
|
||||||
|
};
|
||||||
|
|
||||||
|
const char* jmptablestrs[] = {
|
||||||
|
"JGT", "001",
|
||||||
|
"JEQ", "010",
|
||||||
|
"JGE", "011",
|
||||||
|
"JLT", "100",
|
||||||
|
"JNE", "101",
|
||||||
|
"JLE", "110",
|
||||||
|
"JMP", "111"
|
||||||
|
};
|
||||||
|
TABLE jmptable =
|
||||||
|
{
|
||||||
|
.table = jmptablestrs,
|
||||||
|
.size = sizeof(jmptablestrs) / sizeof(char*) / 2,
|
||||||
|
.instsize = 4 * sizeof(char)
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,24 @@
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
char* heapstr(const char* str, int len) {
|
||||||
|
int sz = sizeof(char) * (len + 1);
|
||||||
|
char* outstr = (char*)malloc(sz);
|
||||||
|
strcpy(outstr, str);
|
||||||
|
return outstr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int countplaces(int n) {
|
||||||
|
int places = 1;
|
||||||
|
int divisor = 1;
|
||||||
|
if(n < 0) {
|
||||||
|
n = -n;
|
||||||
|
places++;
|
||||||
|
}
|
||||||
|
while(n / divisor >= 10) {
|
||||||
|
places++;
|
||||||
|
divisor *= 10;
|
||||||
|
}
|
||||||
|
return places;
|
||||||
|
}
|
Loading…
Reference in New Issue