Add arithmetic and boolean operations

This commit is contained in:
Augusto Gunsch 2020-11-01 18:57:56 -03:00
parent 54eb1daee6
commit 3241592364
No known key found for this signature in database
GPG Key ID: F7EEFE29825C72DC
3 changed files with 123 additions and 0 deletions

View File

@ -94,4 +94,51 @@ char* tpoppointer[TPOPPOINTERN] = {
"M=D"
};
#define TARITHN 7
char* tarith[TARITHN] = {
"",
"@SP",
"M=M-1",
"A=M",
"D=M",
"A=A-1",
""
};
#define TNEGN 5
char* tneg[TNEGN] = {
"",
"@SP",
"M=M-1",
"A=M",
"M=-M",
};
#define TNOTN 5
char* tnot[TNOTN] = {
"",
"@SP",
"M=M-1",
"A=M",
"M=!M",
};
#define TCOMPN 15
char* tcomp[TCOMPN] = {
"",
"M=D",
"@SP",
"M=M-1",
"A=M",
"D=M",
"A=A-1",
"D=D-M",
"M=1",
"",
"",
"@SP",
"A=M-1",
"M=0",
""
};
#endif

View File

@ -4,6 +4,8 @@
#include <ctype.h>
#include "translator.h"
#include "templates.h"
#define CMPLIMIT 1000
#define CMPLEN 4
void pushtoclean(struct Translator* t, char* topush) {
int nextsz = sizeof(char*)*(t->tocleanind+1);
@ -105,6 +107,19 @@ void checkind(struct line* ln, int indlen) {
}
}
char* mkcmplab(struct Translator* t, struct line* ln) {
t->compcount++;
if(t->compcount > CMPLIMIT) {
fprintf(stderr, "Reached comparison limit (%i); line %i\n", CMPLIMIT, ln->truen);
exit(1);
}
int newsz = (CMPLEN+13)*sizeof(char);
char* label = (char*)malloc(newsz);
snprintf(label, newsz, "COMPARISON-%i", t->compcount);
pushtoclean(t, label);
return label;
}
char* mkind(struct Translator* t, struct line* ln, int indlen) {
checkind(ln, indlen);
int newsz = sizeof(char) * (indlen + 2);
@ -114,6 +129,22 @@ char* mkind(struct Translator* t, struct line* ln, int indlen) {
return newind;
}
char* atlab(struct Translator* t, char* label, int labellen) {
int newsz = sizeof(char) * (labellen + 2);
char* newind = (char*)malloc(newsz);
snprintf(newind, newsz, "@%s", label);
pushtoclean(t, newind);
return newind;
}
char* mklab(struct Translator* t, char* label, int labellen) {
int newsz = sizeof(char) * (labellen + 3);
char* newind = (char*)malloc(newsz);
snprintf(newind, newsz, "(%s)", label);
pushtoclean(t, newind);
return newind;
}
char* mkstatind(struct Translator* t, struct line* ln, int indlen) {
checkind(ln, indlen);
int fnamelen = strlen(t->fname);
@ -275,6 +306,32 @@ void pop(struct Translator* t, struct line* ln, int indlen) {
addasmlns(t, ln, tpop, TPOPN);
}
void arith(struct Translator* t, struct line* ln, char* op) {
tarith[TARITHN-1] = heapstr(t, op);
addasmlns(t, ln, tarith, TARITHN);
}
void comp(struct Translator* t, struct line* ln, char* op) {
char* label = mkcmplab(t, ln);
int labellen = strlen(label);
// @label
tcomp[TCOMPN-6] = atlab(t, label, labellen);
// D;J(op)
int opsz = sizeof(char)*6;
char* trueop = (char*)malloc(opsz);
snprintf(trueop, opsz, "D;J%s", op);
tcomp[TCOMPN-5] = trueop;
// (label)
tcomp[TCOMPN-1] = mklab(t, label, labellen);
free(label);
addasmlns(t, ln, tcomp, TCOMPN);
};
void switchpush(struct Translator* t, struct line* ln) {
checkopamnt(3, ln);
char* seg = ln->tokens[1];
@ -314,6 +371,24 @@ void switchop(struct Translator* t, struct line* ln) {
switchpush(t, ln);
else if(!strcmp(op, "pop"))
switchpop(t, ln);
else if(!strcmp(op, "add"))
arith(t, ln, "M=M+D");
else if(!strcmp(op, "sub"))
arith(t, ln, "M=M-D");
else if(!strcmp(op, "neg"))
addasmlns(t, ln, tneg, TNEGN);
else if(!strcmp(op, "eq"))
comp(t, ln, "EQ");
else if(!strcmp(op, "gt"))
comp(t, ln, "GT");
else if(!strcmp(op, "lt"))
comp(t, ln, "LT");
else if(!strcmp(op, "and"))
arith(t, ln, "M=M&D");
else if(!strcmp(op, "or"))
arith(t, ln, "M=M|D");
else if(!strcmp(op, "not"))
addasmlns(t, ln, tnot, TNOTN);
else {
fprintf(stderr, "Unrecognized operation '%s'; line %i\n", op, ln->truen);
exit(1);

View File

@ -16,6 +16,7 @@ struct Translator {
int tocleanind;
struct lnarray* lns;
char* fname;
int compcount;
};
void freetranslator(struct Translator* t);