Add assembler
This commit is contained in:
parent
cc60532d74
commit
5429edd444
4
Makefile
4
Makefile
|
@ -1,7 +1,7 @@
|
||||||
FILES = *.c */*.c
|
FILES = *.c */*.c
|
||||||
LIBRARIES = -lpthread
|
LIBRARIES = -lpthread
|
||||||
INCLUDES = -I. -I./parser/ -I./compiler/ -I./vm/ -I./tokenizer/ -I./misc/
|
INCLUDES = -I. -I./parser/ -I./compiler/ -I./vm/ -I./tokenizer/ -I./misc/ -I./assembler/
|
||||||
CFLAGS = -std=c99 -Wall
|
CFLAGS = -std=c99 -Wall -o3
|
||||||
OUTFILE = jackc
|
OUTFILE = jackc
|
||||||
|
|
||||||
main: ${FILES}
|
main: ${FILES}
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
#ifndef TABLES
|
||||||
|
#define TABLES
|
||||||
|
#else
|
||||||
|
#error assembler-tables.h may only be included once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define mktable(name, strs, instructionsize) TABLE name = { .table = strs, .size = sizeof(strs) / sizeof(char*) / 2, .instsize = instructionsize * sizeof(char) }
|
||||||
|
|
||||||
|
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"
|
||||||
|
};
|
||||||
|
mktable(cmptable, cmptablestrs, 8);
|
||||||
|
|
||||||
|
const char* desttablestrs[] = {
|
||||||
|
"M", "001",
|
||||||
|
"D", "010",
|
||||||
|
"MD", "011",
|
||||||
|
"A", "100",
|
||||||
|
"AM", "101",
|
||||||
|
"AD", "110",
|
||||||
|
"AMD", "111"
|
||||||
|
};
|
||||||
|
mktable(desttable, desttablestrs, 4);
|
||||||
|
|
||||||
|
const char* jmptablestrs[] = {
|
||||||
|
"JGT", "001",
|
||||||
|
"JEQ", "010",
|
||||||
|
"JGE", "011",
|
||||||
|
"JLT", "100",
|
||||||
|
"JNE", "101",
|
||||||
|
"JLE", "110",
|
||||||
|
"JMP", "111"
|
||||||
|
};
|
||||||
|
mktable(jmptable, jmptablestrs, 4);
|
|
@ -0,0 +1,368 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "assembler-tables.h"
|
||||||
|
#include "assembler.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
void expandsymbols(SYMBOLARRAY* a, int toaddn);
|
||||||
|
void pushsymbol(SYMBOLARRAY* a, SYMBOL* s);
|
||||||
|
void freesymbol(SYMBOL* s);
|
||||||
|
SYMBOL* mksymbol(char* name, int namesize, int val);
|
||||||
|
int getsymbol(ASSEMBLER* a, char* name);
|
||||||
|
void skipln(ASSEMBLER* a);
|
||||||
|
void readrest(ASSEMBLER* a, int trueln);
|
||||||
|
int isvar(char* var);
|
||||||
|
void initsymbols(SYMBOLARRAY* s);
|
||||||
|
void populatevars(ASSEMBLER* a);
|
||||||
|
SYMBOL* readlabel(ASSEMBLER* a, STRINGLIST* ln, int count);
|
||||||
|
void replacevar(ASSEMBLER* a, STRINGLIST* ln, int val);
|
||||||
|
void preprocess(ASSEMBLER* a);
|
||||||
|
void transa(STRINGLIST* ln);
|
||||||
|
char* lookctable(TABLE* t, bool cond, char* token, const char* fieldname);
|
||||||
|
void transb(STRINGLIST* ln);
|
||||||
|
void assemble(ASSEMBLER* a);
|
||||||
|
void freeassembler(ASSEMBLER* a);
|
||||||
|
void strtogarbage(ASSEMBLER* a, char* str);
|
||||||
|
|
||||||
|
void strtogarbage(ASSEMBLER* a, char* str) {
|
||||||
|
STRINGLIST* newstr = (STRINGLIST*)malloc(sizeof(STRINGLIST));
|
||||||
|
newstr->content = str;
|
||||||
|
newstr->next = a->garbage;
|
||||||
|
a->garbage = newstr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void expandsymbols(SYMBOLARRAY* a, int toaddn) {
|
||||||
|
int sum = a->count + toaddn;
|
||||||
|
if(sizeof(SYMBOL*) * sum > a->size) {
|
||||||
|
a->size = sizeof(SYMBOL*) * sum * 3;
|
||||||
|
a->items = (SYMBOL**)realloc(a->items, a->size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void pushsymbol(SYMBOLARRAY* a, SYMBOL* s) {
|
||||||
|
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);
|
||||||
|
strcpy(heapname, name);
|
||||||
|
s->name = heapname;
|
||||||
|
s->value = val;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getsymbol(ASSEMBLER* a, char* name) {
|
||||||
|
for(int i = 0; i < a->vars->count; i++)
|
||||||
|
if(strcmp(a->vars->items[i]->name, name) == 0)
|
||||||
|
return a->vars->items[i]->value;
|
||||||
|
|
||||||
|
for(int i = 0; i < a->labels->count; i++)
|
||||||
|
if(strcmp(a->labels->items[i]->name, name) == 0)
|
||||||
|
return a->labels->items[i]->value;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int isvar(char* var) {
|
||||||
|
int i = 0;
|
||||||
|
while(1) {
|
||||||
|
if(var[i] == '\0')
|
||||||
|
break;
|
||||||
|
if(!isdigit(var[i]))
|
||||||
|
return 1;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void initsymbols(SYMBOLARRAY* s) {
|
||||||
|
s->size = 150 * sizeof(SYMBOL*);
|
||||||
|
s->items = (SYMBOL**)malloc(s->size);
|
||||||
|
s->count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSEMBLER* mkassembler(STRINGLIST* input) {
|
||||||
|
ASSEMBLER* a = (ASSEMBLER*)malloc(sizeof(ASSEMBLER));
|
||||||
|
a->labels = (SYMBOLARRAY*)malloc(sizeof(SYMBOLARRAY));
|
||||||
|
a->vars = (SYMBOLARRAY*)malloc(sizeof(SYMBOLARRAY));
|
||||||
|
a->garbage = NULL;
|
||||||
|
a->lns = input;
|
||||||
|
|
||||||
|
initsymbols(a->labels);
|
||||||
|
initsymbols(a->vars);
|
||||||
|
|
||||||
|
populatevars(a);
|
||||||
|
a->varsramind = BOTTOM_VAR;
|
||||||
|
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
void populatevars(ASSEMBLER* a) {
|
||||||
|
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" };
|
||||||
|
for(int i = 0; i < firstamnt; i++) {
|
||||||
|
a->vars->items[i] = mksymbol(labels[i], strlen(labels[i])+1, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// RAM variables (R0-R15)
|
||||||
|
const int asciioff = 48;
|
||||||
|
char ramvname[4];
|
||||||
|
ramvname[0] = 'R';
|
||||||
|
ramvname[2] = '\0';
|
||||||
|
int tmptarg = (ramvamnt/10)*10;
|
||||||
|
for(int i = 0; i < tmptarg; i++) {
|
||||||
|
ramvname[1] = (char)(i+asciioff);
|
||||||
|
a->vars->items[firstamnt+i] = mksymbol(ramvname, 3, i);
|
||||||
|
}
|
||||||
|
ramvname[1] = '1';
|
||||||
|
ramvname[3] = '\0';
|
||||||
|
for(int i = 10; i < ramvamnt; i++) {
|
||||||
|
ramvname[2] = (char)((i%10)+asciioff);
|
||||||
|
a->vars->items[firstamnt+i] = mksymbol(ramvname, 4, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// SCREEN var
|
||||||
|
a->vars->items[firstamnt+ramvamnt] = mksymbol("SCREEN", 7, 16384);
|
||||||
|
// KBD var
|
||||||
|
a->vars->items[firstamnt+ramvamnt+1] = mksymbol("KBD", 4, 24576);
|
||||||
|
}
|
||||||
|
|
||||||
|
SYMBOL* readlabel(ASSEMBLER* a, STRINGLIST* ln, int count) {
|
||||||
|
int i = 1;
|
||||||
|
char c;
|
||||||
|
while(true) {
|
||||||
|
c = ln->content[i];
|
||||||
|
if(c == ')')
|
||||||
|
break;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int size = i * sizeof(char);
|
||||||
|
char* name = (char*)malloc(size);
|
||||||
|
snprintf(name, size, "%s", ln->content+sizeof(char));
|
||||||
|
SYMBOL* l = (SYMBOL*)malloc(sizeof(SYMBOL));
|
||||||
|
l->name = name;
|
||||||
|
l->value = count;
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
void replacevar(ASSEMBLER* a, STRINGLIST* ln, int val) {
|
||||||
|
int size = sizeof(char)*(countplaces(val) + 2);
|
||||||
|
char* newln = (char *)malloc(size);
|
||||||
|
snprintf(newln, size, "@%i", val);
|
||||||
|
ln->content = newln;
|
||||||
|
strtogarbage(a, newln);
|
||||||
|
}
|
||||||
|
|
||||||
|
void handlevarsymbol(ASSEMBLER* a, STRINGLIST* ln) {
|
||||||
|
char* afterat = ln->content+sizeof(char);
|
||||||
|
if(isvar(afterat)) {
|
||||||
|
int val = getsymbol(a, afterat);
|
||||||
|
if(val == -1) {
|
||||||
|
if(a->varsramind == RAM_LIMIT) {
|
||||||
|
eprintf("Variable amount reached RAM limit (%i)\n", RAM_LIMIT);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
SYMBOL* var = mksymbol(afterat, strlen(afterat)+1, a->varsramind);
|
||||||
|
a->varsramind++;
|
||||||
|
pushsymbol(a->vars, var);
|
||||||
|
val = var->value;
|
||||||
|
}
|
||||||
|
replacevar(a, ln, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void handlelabelsymbol(ASSEMBLER* a, STRINGLIST* ln, int count) {
|
||||||
|
SYMBOL* l = readlabel(a, ln, count);
|
||||||
|
|
||||||
|
pushsymbol(a->labels, l);
|
||||||
|
}
|
||||||
|
|
||||||
|
void stripvars(ASSEMBLER* a) {
|
||||||
|
STRINGLIST* curln = a->lns;
|
||||||
|
while(curln != NULL) {
|
||||||
|
if(curln->content[0] == '@')
|
||||||
|
handlevarsymbol(a, curln);
|
||||||
|
curln = curln->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void striplabels(ASSEMBLER* a) {
|
||||||
|
STRINGLIST* curln = a->lns;
|
||||||
|
STRINGLIST* lastln;
|
||||||
|
int count = 0;
|
||||||
|
while(curln != NULL) {
|
||||||
|
if(curln->content[0] == '(') {
|
||||||
|
handlelabelsymbol(a, curln, count);
|
||||||
|
if(count > 0)
|
||||||
|
lastln->next = curln->next;
|
||||||
|
else
|
||||||
|
a->lns = curln->next;
|
||||||
|
STRINGLIST* tmp = curln;
|
||||||
|
curln = curln->next;
|
||||||
|
free(tmp);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lastln = curln;
|
||||||
|
curln = curln->next;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void preprocess(ASSEMBLER* a) {
|
||||||
|
striplabels(a);
|
||||||
|
stripvars(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
void transa(STRINGLIST* ln) {
|
||||||
|
int add = atoi(ln->content+sizeof(char));
|
||||||
|
|
||||||
|
char* out = (char*)malloc(sizeof(char) * INST_SIZE);
|
||||||
|
|
||||||
|
int lastbit = 1 << 15;
|
||||||
|
for(int i = INST_SIZE-2; i > 0; i--) {
|
||||||
|
if(add & (lastbit >> i))
|
||||||
|
out[i] = '1';
|
||||||
|
else
|
||||||
|
out[i] = '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
out[INST_SIZE-1] = '\0';
|
||||||
|
out[0] = '0';
|
||||||
|
|
||||||
|
ln->content = out;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* lookctable(TABLE* t, bool cond, char* token, const char* fieldname) {
|
||||||
|
char* out = (char*)malloc(t->instsize);
|
||||||
|
|
||||||
|
if(!cond) {
|
||||||
|
int targsize = t->instsize - 1;
|
||||||
|
for(int i = 0; i < targsize; i++)
|
||||||
|
out[i] = '0';
|
||||||
|
out[t->instsize-1] = '\0';
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
for(int i = 0; i < t->size; i++)
|
||||||
|
if(strcmp(t->table[2*i], token) == 0) {
|
||||||
|
strcpy(out, t->table[(2*i)+1]);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void transb(STRINGLIST* ln) {
|
||||||
|
bool hasjmp = false;
|
||||||
|
bool hasdest = false;
|
||||||
|
bool hascmp = false;
|
||||||
|
int i = 0;
|
||||||
|
int tmpi = 0;
|
||||||
|
char tmp[C_TOKEN_SIZE], dest[C_TOKEN_SIZE], cmp[C_TOKEN_SIZE], jmp[C_TOKEN_SIZE];
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
if(ln->content[i] == '\0') {
|
||||||
|
tmp[tmpi] = '\0';
|
||||||
|
if(hasjmp)
|
||||||
|
strcpy(jmp, tmp);
|
||||||
|
else
|
||||||
|
strcpy(cmp, tmp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ln->content[i] == '=' && !hasdest && hascmp) {
|
||||||
|
hascmp = false;
|
||||||
|
hasdest = true;
|
||||||
|
tmp[tmpi] = '\0';
|
||||||
|
strcpy(dest, tmp);
|
||||||
|
tmpi = 0;
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(ln->content[i] == ';' && !hasjmp && hascmp) {
|
||||||
|
hascmp = false;
|
||||||
|
hasjmp = true;
|
||||||
|
tmp[tmpi] = '\0';
|
||||||
|
strcpy(cmp, tmp);
|
||||||
|
tmpi = 0;
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
hascmp = 1;
|
||||||
|
tmp[tmpi] = ln->content[i];
|
||||||
|
tmpi++;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* rawdest = lookctable(&desttable, hasdest, dest, "dest");
|
||||||
|
char* rawjmp = lookctable(&jmptable, hasjmp, jmp, "jump");
|
||||||
|
char* rawcmp = lookctable(&cmptable, 1, cmp, "comp");
|
||||||
|
|
||||||
|
int sz = sizeof(char) * INST_SIZE;
|
||||||
|
char* out = (char*)malloc(sz);
|
||||||
|
snprintf(out, sz, "111%s%s%s", rawcmp, rawdest, rawjmp);
|
||||||
|
|
||||||
|
ln->content = out;
|
||||||
|
free(rawdest);
|
||||||
|
free(rawjmp);
|
||||||
|
free(rawcmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void assemble(ASSEMBLER* a) {
|
||||||
|
STRINGLIST* currln = a->lns;
|
||||||
|
while(currln != NULL) {
|
||||||
|
if(currln->content[0] == '@')
|
||||||
|
transa(currln);
|
||||||
|
else
|
||||||
|
transb(currln);
|
||||||
|
currln = currln->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void freeasmlns(STRINGLIST* lns) {
|
||||||
|
if(lns != NULL) {
|
||||||
|
free(lns->content);
|
||||||
|
STRINGLIST* next = lns->next;
|
||||||
|
free(lns);
|
||||||
|
freeasmlns(next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void freeassembler(ASSEMBLER* a) {
|
||||||
|
freesymbols(a->vars);
|
||||||
|
freesymbols(a->labels);
|
||||||
|
freeasmlns(a->lns);
|
||||||
|
freeasmlns(a->garbage);
|
||||||
|
free(a);
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
#ifndef ASSEMBLER_H
|
||||||
|
#define ASSEMBLER_H
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "parser.h"
|
||||||
|
|
||||||
|
#define RAM_LIMIT 24577
|
||||||
|
#define TOP_VAR 16383
|
||||||
|
#define BOTTOM_VAR 16
|
||||||
|
#define INST_SIZE 17
|
||||||
|
#define C_TOKEN_SIZE 4
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char* name;
|
||||||
|
int value;
|
||||||
|
} SYMBOL;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
SYMBOL** items;
|
||||||
|
int count;
|
||||||
|
int size;
|
||||||
|
} SYMBOLARRAY;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
STRINGLIST* lns;
|
||||||
|
STRINGLIST* garbage;
|
||||||
|
|
||||||
|
SYMBOLARRAY* labels;
|
||||||
|
|
||||||
|
SYMBOLARRAY* vars;
|
||||||
|
int varsramind;
|
||||||
|
} ASSEMBLER;
|
||||||
|
|
||||||
|
ASSEMBLER* mkassembler(STRINGLIST* input);
|
||||||
|
void preprocess(ASSEMBLER* a);
|
||||||
|
void assemble(ASSEMBLER* a);
|
||||||
|
void freeassembler(ASSEMBLER* a);
|
||||||
|
#endif
|
28
main.c
28
main.c
|
@ -7,6 +7,7 @@
|
||||||
#include "compiler.h"
|
#include "compiler.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
|
#include "assembler.h"
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
if(argc < 2) {
|
if(argc < 2) {
|
||||||
|
@ -53,25 +54,42 @@ int main(int argc, char* argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
actonunits(head, compileunit);
|
actonunits(head, compileunit);
|
||||||
|
|
||||||
actonunits(head, vmtranslateunit);
|
actonunits(head, vmtranslateunit);
|
||||||
|
|
||||||
currunit = head;
|
ASMBLK* asmlns = head->asmlns;
|
||||||
FILE* output = fopen("out.asm", "w");
|
currunit = head->next;
|
||||||
while(currunit != NULL) {
|
while(currunit != NULL) {
|
||||||
|
mergeasmblks(asmlns, currunit->asmlns);
|
||||||
|
currunit = currunit->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSEMBLER* assembler = mkassembler(asmlns->head);
|
||||||
|
preprocess(assembler);
|
||||||
|
assemble(assembler);
|
||||||
|
|
||||||
|
|
||||||
|
char* outname = getouthack(argv[1]);
|
||||||
|
FILE* output = fopen(outname, "w");
|
||||||
if(output == NULL) {
|
if(output == NULL) {
|
||||||
eprintf("%s", strerror(errno));
|
eprintf("%s", strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
printstrlist(currunit->asmlns, output);
|
printstrlist(asmlns->head, output);
|
||||||
|
free(asmlns);
|
||||||
|
|
||||||
|
fclose(output);
|
||||||
|
free(outname);
|
||||||
|
|
||||||
|
currunit = head;
|
||||||
|
while(currunit != NULL) {
|
||||||
COMPILEUNIT* next = currunit->next;
|
COMPILEUNIT* next = currunit->next;
|
||||||
freeunit(currunit);
|
freeunit(currunit);
|
||||||
currunit = next;
|
currunit = next;
|
||||||
}
|
}
|
||||||
fclose(output);
|
|
||||||
|
|
||||||
freecompiler(compiler);
|
freecompiler(compiler);
|
||||||
|
freeassembler(assembler);
|
||||||
freetree(headclass);
|
freetree(headclass);
|
||||||
freefilelist(files);
|
freefilelist(files);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
26
misc/io.c
26
misc/io.c
|
@ -75,9 +75,9 @@ bool isdotjack(char* f, int len) {
|
||||||
return strcmp(strtail(f, len, strlen(ext)), ext) == 0;
|
return strcmp(strtail(f, len, strlen(ext)), ext) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isdir(char* f, int len) {
|
bool isdir(char* f) {
|
||||||
bool readsmt = false;
|
bool readsmt = false;
|
||||||
for(int i = len-1; i >= 0; i--) {
|
for(int i = strlen(f)-1; i >= 0; i--) {
|
||||||
if(f[i] == '.') {
|
if(f[i] == '.') {
|
||||||
if(readsmt)
|
if(readsmt)
|
||||||
return false;
|
return false;
|
||||||
|
@ -160,10 +160,7 @@ FILELIST* getsinglefile(char* file) {
|
||||||
}
|
}
|
||||||
|
|
||||||
FILELIST* getfiles(char* input) {
|
FILELIST* getfiles(char* input) {
|
||||||
int inplen = strlen(input);
|
if(isdir(input))
|
||||||
bool isitdir = isdir(input, inplen);
|
|
||||||
|
|
||||||
if(isitdir)
|
|
||||||
return getfilesfromdir(input);
|
return getfilesfromdir(input);
|
||||||
else
|
else
|
||||||
return getsinglefile(input);
|
return getsinglefile(input);
|
||||||
|
@ -178,3 +175,20 @@ void freefilelist(FILELIST* fs) {
|
||||||
if(next != NULL)
|
if(next != NULL)
|
||||||
freefilelist(next);
|
freefilelist(next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char* getouthack(char* input) {
|
||||||
|
char* out;
|
||||||
|
int inplen = strlen(input);
|
||||||
|
if(isdir(input)) {
|
||||||
|
char* name = getname(input, inplen);
|
||||||
|
int sz = (inplen + strlen(name) + 7) * sizeof(char);
|
||||||
|
out = (char*)malloc(sz);
|
||||||
|
sprintf(out, "%s/%s.hack", input, name);
|
||||||
|
free(name);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
out = heapstr(input, inplen);
|
||||||
|
out[inplen-4] = 'h';
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
|
@ -11,4 +11,5 @@ typedef struct flist {
|
||||||
|
|
||||||
FILELIST* getfiles(char* input);
|
FILELIST* getfiles(char* input);
|
||||||
void freefilelist(FILELIST* fs);
|
void freefilelist(FILELIST* fs);
|
||||||
|
char* getouthack(char* input);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -93,7 +93,6 @@ void actonunits(COMPILEUNIT* units, void*(*fun)(void*)) {
|
||||||
void freeunit(COMPILEUNIT* u) {
|
void freeunit(COMPILEUNIT* u) {
|
||||||
freeparser(u->parser);
|
freeparser(u->parser);
|
||||||
freelnblk(u->compiled);
|
freelnblk(u->compiled);
|
||||||
freestrlist(u->asmlns);
|
|
||||||
freevmtranslator(u->vmtranslator);
|
freevmtranslator(u->vmtranslator);
|
||||||
free(u);
|
free(u);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ typedef struct unit {
|
||||||
PARSER* parser;
|
PARSER* parser;
|
||||||
CLASS* parsed;
|
CLASS* parsed;
|
||||||
COMPILER* compiler;
|
COMPILER* compiler;
|
||||||
STRINGLIST* asmlns;
|
ASMBLK* asmlns;
|
||||||
LINEBLOCK* compiled;
|
LINEBLOCK* compiled;
|
||||||
VMTRANSLATOR* vmtranslator;
|
VMTRANSLATOR* vmtranslator;
|
||||||
struct unit* next;
|
struct unit* next;
|
||||||
|
|
|
@ -17,7 +17,6 @@ char* tpushlns[] = {
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
"",
|
|
||||||
"A=D+A",
|
"A=D+A",
|
||||||
"D=M",
|
"D=M",
|
||||||
"@SP",
|
"@SP",
|
||||||
|
@ -29,7 +28,6 @@ char* tpushlns[] = {
|
||||||
mktemplate(tpush, tpushlns);
|
mktemplate(tpush, tpushlns);
|
||||||
|
|
||||||
char* tpushconslns[] = {
|
char* tpushconslns[] = {
|
||||||
"",
|
|
||||||
"",
|
"",
|
||||||
"D=A",
|
"D=A",
|
||||||
"@SP",
|
"@SP",
|
||||||
|
@ -41,7 +39,6 @@ char* tpushconslns[] = {
|
||||||
mktemplate(tpushcons, tpushconslns);
|
mktemplate(tpushcons, tpushconslns);
|
||||||
|
|
||||||
char* tpushstatlns[] = {
|
char* tpushstatlns[] = {
|
||||||
"",
|
|
||||||
"",
|
"",
|
||||||
"D=M",
|
"D=M",
|
||||||
"@SP",
|
"@SP",
|
||||||
|
@ -60,7 +57,6 @@ char* tpoplns[] = {
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
"",
|
|
||||||
"D=D+A",
|
"D=D+A",
|
||||||
"@R13",
|
"@R13",
|
||||||
"M=D",
|
"M=D",
|
||||||
|
@ -74,7 +70,6 @@ char* tpoplns[] = {
|
||||||
mktemplate(tpop, tpoplns);
|
mktemplate(tpop, tpoplns);
|
||||||
|
|
||||||
char* tpopstatlns[] = {
|
char* tpopstatlns[] = {
|
||||||
"",
|
|
||||||
"@SP",
|
"@SP",
|
||||||
"AM=M-1",
|
"AM=M-1",
|
||||||
"D=M",
|
"D=M",
|
||||||
|
@ -88,7 +83,6 @@ mktemplate(tpoptemp, tpopstatlns);
|
||||||
mktemplate(tpoppointer, tpopstatlns);
|
mktemplate(tpoppointer, tpopstatlns);
|
||||||
|
|
||||||
char* tarithlns[] = {
|
char* tarithlns[] = {
|
||||||
"",
|
|
||||||
"@SP",
|
"@SP",
|
||||||
"AM=M-1",
|
"AM=M-1",
|
||||||
"D=M",
|
"D=M",
|
||||||
|
@ -98,7 +92,6 @@ char* tarithlns[] = {
|
||||||
mktemplate(tarith, tarithlns);
|
mktemplate(tarith, tarithlns);
|
||||||
|
|
||||||
char* tneglns[] = {
|
char* tneglns[] = {
|
||||||
"",
|
|
||||||
"@SP",
|
"@SP",
|
||||||
"A=M-1",
|
"A=M-1",
|
||||||
"M=-M",
|
"M=-M",
|
||||||
|
@ -106,7 +99,6 @@ char* tneglns[] = {
|
||||||
mktemplate(tneg, tneglns);
|
mktemplate(tneg, tneglns);
|
||||||
|
|
||||||
char* tnotlns[] = {
|
char* tnotlns[] = {
|
||||||
"",
|
|
||||||
"@SP",
|
"@SP",
|
||||||
"A=M-1",
|
"A=M-1",
|
||||||
"M=!M",
|
"M=!M",
|
||||||
|
@ -114,7 +106,6 @@ char* tnotlns[] = {
|
||||||
mktemplate(tnot, tnotlns);
|
mktemplate(tnot, tnotlns);
|
||||||
|
|
||||||
char* tcomplns[] = {
|
char* tcomplns[] = {
|
||||||
"",
|
|
||||||
"@SP",
|
"@SP",
|
||||||
"AM=M-1",
|
"AM=M-1",
|
||||||
"D=M",
|
"D=M",
|
||||||
|
@ -131,20 +122,17 @@ char* tcomplns[] = {
|
||||||
mktemplate(tcomp, tcomplns);
|
mktemplate(tcomp, tcomplns);
|
||||||
|
|
||||||
char* tlabellns[] = {
|
char* tlabellns[] = {
|
||||||
"",
|
|
||||||
""
|
""
|
||||||
};
|
};
|
||||||
mktemplate(tlabel, tlabellns);
|
mktemplate(tlabel, tlabellns);
|
||||||
|
|
||||||
char* tgotolns[] = {
|
char* tgotolns[] = {
|
||||||
"",
|
|
||||||
"",
|
"",
|
||||||
"0;JMP"
|
"0;JMP"
|
||||||
};
|
};
|
||||||
mktemplate(tgoto, tgotolns);
|
mktemplate(tgoto, tgotolns);
|
||||||
|
|
||||||
char* tifgotolns[] = {
|
char* tifgotolns[] = {
|
||||||
"",
|
|
||||||
"@SP",
|
"@SP",
|
||||||
"AM=M-1",
|
"AM=M-1",
|
||||||
"D=M",
|
"D=M",
|
||||||
|
@ -154,8 +142,6 @@ char* tifgotolns[] = {
|
||||||
mktemplate(tifgoto, tifgotolns);
|
mktemplate(tifgoto, tifgotolns);
|
||||||
|
|
||||||
char* tcallstartlns[] = {
|
char* tcallstartlns[] = {
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"D=A",
|
"D=A",
|
||||||
"@SP",
|
"@SP",
|
||||||
"A=M",
|
"A=M",
|
||||||
|
@ -204,7 +190,6 @@ char* tframevarslns[] = {
|
||||||
mktemplate(tframevars, tframevarslns);
|
mktemplate(tframevars, tframevarslns);
|
||||||
|
|
||||||
char* tfunctionlns[] = {
|
char* tfunctionlns[] = {
|
||||||
"",
|
|
||||||
""
|
""
|
||||||
};
|
};
|
||||||
mktemplate(tfunction, tfunctionlns);
|
mktemplate(tfunction, tfunctionlns);
|
||||||
|
@ -219,7 +204,6 @@ char* tfunctionpushlns[] = {
|
||||||
mktemplate(tfunctionpush, tfunctionpushlns);
|
mktemplate(tfunctionpush, tfunctionpushlns);
|
||||||
|
|
||||||
char* tstartreturnlns[] = {
|
char* tstartreturnlns[] = {
|
||||||
"",
|
|
||||||
"@LCL",
|
"@LCL",
|
||||||
"D=M",
|
"D=M",
|
||||||
"@5",
|
"@5",
|
||||||
|
|
|
@ -5,11 +5,6 @@
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#define eq(translator, index, str) !strcmp(translator->currln->tokens[index], str)
|
#define eq(translator, index, str) !strcmp(translator->currln->tokens[index], str)
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
STRINGLIST* head;
|
|
||||||
STRINGLIST* tail;
|
|
||||||
} ASMBLK;
|
|
||||||
|
|
||||||
STRINGLIST* asmln(char* content) {
|
STRINGLIST* asmln(char* content) {
|
||||||
STRINGLIST* ln = (STRINGLIST*)malloc(sizeof(STRINGLIST));
|
STRINGLIST* ln = (STRINGLIST*)malloc(sizeof(STRINGLIST));
|
||||||
ln->content = content;
|
ln->content = content;
|
||||||
|
@ -68,26 +63,6 @@ char* dotat(VMTRANSLATOR* t, char* name, char* n) {
|
||||||
return atstr;
|
return atstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* comment(VMTRANSLATOR* t) {
|
|
||||||
int sz = (4 + strlen(t->currln->tokens[0])) * sizeof(char);
|
|
||||||
for(int i = 1; i < t->currln->count; i++)
|
|
||||||
sz += (1 + strlen(t->currln->tokens[i])) * sizeof(char);
|
|
||||||
|
|
||||||
char* com = (char*)malloc(sz);
|
|
||||||
if(t->currln->count == 1)
|
|
||||||
sprintf(com, "// %s", t->currln->tokens[0]);
|
|
||||||
else if(t->currln->count == 2)
|
|
||||||
sprintf(com, "// %s %s", t->currln->tokens[0],
|
|
||||||
t->currln->tokens[1]);
|
|
||||||
else if(t->currln->count == 3)
|
|
||||||
sprintf(com, "// %s %s %s", t->currln->tokens[0],
|
|
||||||
t->currln->tokens[1],
|
|
||||||
t->currln->tokens[2]);
|
|
||||||
|
|
||||||
togarbage(t, com);
|
|
||||||
return com;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* switchsegment(VMTRANSLATOR* t) {
|
char* switchsegment(VMTRANSLATOR* t) {
|
||||||
if(eq(t, 1, "local"))
|
if(eq(t, 1, "local"))
|
||||||
return mkstr(t, "@LCL");
|
return mkstr(t, "@LCL");
|
||||||
|
@ -154,13 +129,6 @@ ASMBLK* copytemplate(TEMPLATE* t) {
|
||||||
return blk;
|
return blk;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASMBLK* mkasmlns(VMTRANSLATOR* t, TEMPLATE* tp) {
|
|
||||||
// instruction comment
|
|
||||||
tp->items[0] = comment(t);
|
|
||||||
|
|
||||||
return copytemplate(tp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void mergeasmblks(ASMBLK* a, ASMBLK* b) {
|
void mergeasmblks(ASMBLK* a, ASMBLK* b) {
|
||||||
a->tail->next = b->head;
|
a->tail->next = b->head;
|
||||||
a->tail = b->tail;
|
a->tail = b->tail;
|
||||||
|
@ -173,47 +141,47 @@ void mergeasmblks(ASMBLK* a, ASMBLK* b) {
|
||||||
|
|
||||||
ASMBLK* translatepushconst(VMTRANSLATOR* t) {
|
ASMBLK* translatepushconst(VMTRANSLATOR* t) {
|
||||||
// @i
|
// @i
|
||||||
tpushcons.items[1] = at(t, t->currln->tokens[2]);
|
tpushcons.items[0] = at(t, t->currln->tokens[2]);
|
||||||
|
|
||||||
return mkasmlns(t, &tpushcons);
|
return copytemplate(&tpushcons);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASMBLK* translatepushstatic(VMTRANSLATOR* t) {
|
ASMBLK* translatepushstatic(VMTRANSLATOR* t) {
|
||||||
// @classname.i
|
// @classname.i
|
||||||
tpushstat.items[1] = dotat(t, t->classname, t->currln->tokens[2]);
|
tpushstat.items[0] = dotat(t, t->classname, t->currln->tokens[2]);
|
||||||
|
|
||||||
return mkasmlns(t, &tpushstat);
|
return copytemplate(&tpushstat);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASMBLK* translatepushpointer(VMTRANSLATOR* t) {
|
ASMBLK* translatepushpointer(VMTRANSLATOR* t) {
|
||||||
// @THIS/@THAT
|
// @THIS/@THAT
|
||||||
tpushpointer.items[1] = mkpointerind(t);
|
tpushpointer.items[0] = mkpointerind(t);
|
||||||
|
|
||||||
return mkasmlns(t, &tpushpointer);
|
return copytemplate(&tpushpointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASMBLK* translatepushtemp(VMTRANSLATOR* t) {
|
ASMBLK* translatepushtemp(VMTRANSLATOR* t) {
|
||||||
// @5+i
|
// @5+i
|
||||||
tpushtemp.items[1] = mktempind(t);
|
tpushtemp.items[0] = mktempind(t);
|
||||||
|
|
||||||
return mkasmlns(t, &tpushtemp);
|
return copytemplate(&tpushtemp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pushpopcommon(VMTRANSLATOR* t, TEMPLATE* tp) {
|
void pushpopcommon(VMTRANSLATOR* t, TEMPLATE* tp) {
|
||||||
// @segment
|
// @segment
|
||||||
tp->items[1] = switchsegment(t);
|
tp->items[0] = switchsegment(t);
|
||||||
|
|
||||||
// D=M
|
// D=M
|
||||||
tp->items[2] = mkstr(t, "D=M");
|
tp->items[1] = mkstr(t, "D=M");
|
||||||
|
|
||||||
// @i
|
// @i
|
||||||
tp->items[3] = at(t, t->currln->tokens[2]);
|
tp->items[2] = at(t, t->currln->tokens[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASMBLK* translatepushgeneric(VMTRANSLATOR* t) {
|
ASMBLK* translatepushgeneric(VMTRANSLATOR* t) {
|
||||||
pushpopcommon(t, &tpush);
|
pushpopcommon(t, &tpush);
|
||||||
|
|
||||||
return mkasmlns(t, &tpush);
|
return copytemplate(&tpush);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASMBLK* translatepush(VMTRANSLATOR* t) {
|
ASMBLK* translatepush(VMTRANSLATOR* t) {
|
||||||
|
@ -235,7 +203,7 @@ ASMBLK* translatepopstatic(VMTRANSLATOR* t) {
|
||||||
// M=D
|
// M=D
|
||||||
tpopstat.items[tpopstat.count-1] = mkstr(t, "M=D");
|
tpopstat.items[tpopstat.count-1] = mkstr(t, "M=D");
|
||||||
|
|
||||||
return mkasmlns(t, &tpopstat);
|
return copytemplate(&tpopstat);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASMBLK* translatepoppointer(VMTRANSLATOR* t) {
|
ASMBLK* translatepoppointer(VMTRANSLATOR* t) {
|
||||||
|
@ -245,7 +213,7 @@ ASMBLK* translatepoppointer(VMTRANSLATOR* t) {
|
||||||
// M=D
|
// M=D
|
||||||
tpoppointer.items[tpoppointer.count-1] = mkstr(t, "M=D");
|
tpoppointer.items[tpoppointer.count-1] = mkstr(t, "M=D");
|
||||||
|
|
||||||
return mkasmlns(t, &tpoppointer);
|
return copytemplate(&tpoppointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASMBLK* translatepoptemp(VMTRANSLATOR* t) {
|
ASMBLK* translatepoptemp(VMTRANSLATOR* t) {
|
||||||
|
@ -254,13 +222,13 @@ ASMBLK* translatepoptemp(VMTRANSLATOR* t) {
|
||||||
|
|
||||||
tpoptemp.items[tpoptemp.count-1] = mkstr(t, "M=D");
|
tpoptemp.items[tpoptemp.count-1] = mkstr(t, "M=D");
|
||||||
|
|
||||||
return mkasmlns(t, &tpoptemp);
|
return copytemplate(&tpoptemp);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASMBLK* translatepopgeneric(VMTRANSLATOR* t) {
|
ASMBLK* translatepopgeneric(VMTRANSLATOR* t) {
|
||||||
pushpopcommon(t, &tpop);
|
pushpopcommon(t, &tpop);
|
||||||
|
|
||||||
return mkasmlns(t, &tpop);
|
return copytemplate(&tpop);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASMBLK* translatepop(VMTRANSLATOR* t) {
|
ASMBLK* translatepop(VMTRANSLATOR* t) {
|
||||||
|
@ -281,7 +249,7 @@ ASMBLK* translatepop(VMTRANSLATOR* t) {
|
||||||
ASMBLK* translatearith(VMTRANSLATOR* t, char* op) {
|
ASMBLK* translatearith(VMTRANSLATOR* t, char* op) {
|
||||||
tarith.items[tarith.count-1] = mkstr(t, op);
|
tarith.items[tarith.count-1] = mkstr(t, op);
|
||||||
|
|
||||||
return mkasmlns(t, &tarith);
|
return copytemplate(&tarith);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASMBLK* translatecomp(VMTRANSLATOR* t, char* op) {
|
ASMBLK* translatecomp(VMTRANSLATOR* t, char* op) {
|
||||||
|
@ -301,7 +269,7 @@ ASMBLK* translatecomp(VMTRANSLATOR* t, char* op) {
|
||||||
// (label)
|
// (label)
|
||||||
tcomp.items[tcomp.count-1] = enclosingparenthesis(t, label, labellen);
|
tcomp.items[tcomp.count-1] = enclosingparenthesis(t, label, labellen);
|
||||||
|
|
||||||
return mkasmlns(t, &tcomp);
|
return copytemplate(&tcomp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* END OPERATIONS */
|
/* END OPERATIONS */
|
||||||
|
@ -310,25 +278,25 @@ ASMBLK* translatelabel(VMTRANSLATOR* t) {
|
||||||
// (classname$label)
|
// (classname$label)
|
||||||
tlabel.items[tlabel.count-1] = mklab(t);
|
tlabel.items[tlabel.count-1] = mklab(t);
|
||||||
|
|
||||||
return mkasmlns(t, &tlabel);
|
return copytemplate(&tlabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASMBLK* translategoto(VMTRANSLATOR* t) {
|
ASMBLK* translategoto(VMTRANSLATOR* t) {
|
||||||
// @label
|
// @label
|
||||||
tgoto.items[tgoto.count-2] = mkgotolab(t);
|
tgoto.items[tgoto.count-2] = mkgotolab(t);
|
||||||
|
|
||||||
return mkasmlns(t, &tgoto);
|
return copytemplate(&tgoto);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASMBLK* translateifgoto(VMTRANSLATOR* t) {
|
ASMBLK* translateifgoto(VMTRANSLATOR* t) {
|
||||||
// @label
|
// @label
|
||||||
tifgoto.items[tifgoto.count-2] = mkgotolab(t);
|
tifgoto.items[tifgoto.count-2] = mkgotolab(t);
|
||||||
|
|
||||||
return mkasmlns(t, &tifgoto);
|
return copytemplate(&tifgoto);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASMBLK* translatereturn(VMTRANSLATOR* t) {
|
ASMBLK* translatereturn(VMTRANSLATOR* t) {
|
||||||
ASMBLK* blk = mkasmlns(t, &tstartreturn);
|
ASMBLK* blk = copytemplate(&tstartreturn);
|
||||||
|
|
||||||
for(int i = tframevars.count-1; i >= 0; i--) {
|
for(int i = tframevars.count-1; i >= 0; i--) {
|
||||||
tretpop.items[tretpop.count-2] = tframevars.items[i];
|
tretpop.items[tretpop.count-2] = tframevars.items[i];
|
||||||
|
@ -344,8 +312,8 @@ ASMBLK* translatefunction(VMTRANSLATOR* t) {
|
||||||
t->cmpind = 0;
|
t->cmpind = 0;
|
||||||
|
|
||||||
// (funcname)
|
// (funcname)
|
||||||
tfunction.items[1] = mklab(t);
|
tfunction.items[0] = mklab(t);
|
||||||
ASMBLK* blk = mkasmlns(t, &tfunction);
|
ASMBLK* blk = copytemplate(&tfunction);
|
||||||
|
|
||||||
// repeat nVars times:
|
// repeat nVars times:
|
||||||
int nlocals = atoi(t->currln->tokens[2]);
|
int nlocals = atoi(t->currln->tokens[2]);
|
||||||
|
@ -359,7 +327,7 @@ ASMBLK* translatefunction(VMTRANSLATOR* t) {
|
||||||
ASMBLK* pushframe(VMTRANSLATOR* t, char* retlab, int retlablen, int* framesize) {
|
ASMBLK* pushframe(VMTRANSLATOR* t, char* retlab, int retlablen, int* framesize) {
|
||||||
tcallstart.items[1] = atraw(t, retlab, retlablen);
|
tcallstart.items[1] = atraw(t, retlab, retlablen);
|
||||||
|
|
||||||
ASMBLK* blk = mkasmlns(t, &tcallstart);
|
ASMBLK* blk = copytemplate(&tcallstart);
|
||||||
|
|
||||||
for(int i = 0; i < tframevars.count; i++) {
|
for(int i = 0; i < tframevars.count; i++) {
|
||||||
tcallpush.items[0] = tframevars.items[i];
|
tcallpush.items[0] = tframevars.items[i];
|
||||||
|
@ -408,9 +376,9 @@ ASMBLK* translateln(VMTRANSLATOR* t) {
|
||||||
return translatearith(t, "M=D|M");
|
return translatearith(t, "M=D|M");
|
||||||
|
|
||||||
if(eq(t, 0, "neg"))
|
if(eq(t, 0, "neg"))
|
||||||
return mkasmlns(t, &tneg);
|
return copytemplate(&tneg);
|
||||||
if(eq(t, 0, "not"))
|
if(eq(t, 0, "not"))
|
||||||
return mkasmlns(t, &tnot);
|
return copytemplate(&tnot);
|
||||||
|
|
||||||
if(eq(t, 0, "eq"))
|
if(eq(t, 0, "eq"))
|
||||||
return translatecomp(t, "EQ");
|
return translatecomp(t, "EQ");
|
||||||
|
@ -433,15 +401,13 @@ ASMBLK* translateln(VMTRANSLATOR* t) {
|
||||||
return translatecall(t);
|
return translatecall(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
STRINGLIST* translatevm(VMTRANSLATOR* t) {
|
ASMBLK* translatevm(VMTRANSLATOR* t) {
|
||||||
ASMBLK* blk = copytemplate(&tbootstrap);
|
ASMBLK* blk = copytemplate(&tbootstrap);
|
||||||
while(t->currln != NULL) {
|
while(t->currln != NULL) {
|
||||||
mergeasmblks(blk, translateln(t));
|
mergeasmblks(blk, translateln(t));
|
||||||
t->currln = t->currln->next;
|
t->currln = t->currln->next;
|
||||||
}
|
}
|
||||||
STRINGLIST* output = blk->head;
|
return blk;
|
||||||
free(blk);
|
|
||||||
return output;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VMTRANSLATOR* mkvmtranslator(char* classname, LINEBLOCK* vmlines) {
|
VMTRANSLATOR* mkvmtranslator(char* classname, LINEBLOCK* vmlines) {
|
||||||
|
|
|
@ -12,9 +12,14 @@ typedef struct {
|
||||||
int retind;
|
int retind;
|
||||||
} VMTRANSLATOR;
|
} VMTRANSLATOR;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
STRINGLIST* head;
|
||||||
|
STRINGLIST* tail;
|
||||||
|
} ASMBLK;
|
||||||
|
|
||||||
STRINGLIST* translatevm(VMTRANSLATOR* t);
|
ASMBLK* translatevm(VMTRANSLATOR* t);
|
||||||
VMTRANSLATOR* mkvmtranslator(char* classname, LINEBLOCK* vmlines);
|
VMTRANSLATOR* mkvmtranslator(char* classname, LINEBLOCK* vmlines);
|
||||||
void freevmtranslator(VMTRANSLATOR* t);
|
void freevmtranslator(VMTRANSLATOR* t);
|
||||||
|
void mergeasmblks(ASMBLK* a, ASMBLK* b);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue