summaryrefslogtreecommitdiff
path: root/assemble.c
diff options
context:
space:
mode:
authormrb0nk500 <b0nk@b0nk.xyz>2020-09-18 14:49:07 -0400
committermrb0nk500 <b0nk@b0nk.xyz>2020-09-18 14:49:07 -0400
commiteea04e3327972f052dcfb8ae0854b77f87d3d52f (patch)
treee6c65aad43cb65eb152dc55fba1eb13efffdf7f2 /assemble.c
parent385a621b9487456c3167f204b02cb0ea0752191d (diff)
- Added support for structs, and unions to the
emulator's assembler. - Make the symbol table a doublely linked list, in both ways. - Optimized the memcopy() function. - Changed the benchmark timing, to now use a timer, and stops once the timer reaches zero. When the timer hits zero, it sends SIGALRM to the main function, which tells the emulator that the benchmark is done.
Diffstat (limited to 'assemble.c')
-rw-r--r--assemble.c154
1 files changed, 136 insertions, 18 deletions
diff --git a/assemble.c b/assemble.c
index 0dad97c..2114456 100644
--- a/assemble.c
+++ b/assemble.c
@@ -74,7 +74,11 @@ uint64_t get_val(token *t, uint64_t addr, uint8_t size, uint8_t dbg) {
case TOK_BIN:
case TOK_CHAR: tmp_val = t->qword; t = t->next; break;
case TOK_SYM:
- case TOK_LABEL: tmp_val = (t->sym) ? t->sym->val : addr; t = t-> next; break;
+ case TOK_LABEL:
+ for (; t->sym && t->sym->isstruct && t->next && t->next->id == TOK_SYM; t = t->next);
+ tmp_val = (t->sym) ? t->sym->val : addr;
+ t = t->next;
+ break;
}
switch (type) {
case EXPR_PLUS : (isstart) ? (value = tmp_val) : (value += tmp_val); break;
@@ -139,6 +143,79 @@ uint8_t get_directivesize(uint8_t type, uint8_t dbg) {
return 0;
}
+uint16_t handle_struct(line **ln, uint64_t address, uint16_t offset, uint8_t dbg) {
+ uint8_t type = 0;
+ uint8_t done = 0;
+ uint8_t ismember = 0;
+ uint16_t size = 0;
+ uint16_t member_size = 0;
+ line *l = *ln;
+ symbol *strct = NULL;
+ token *tok = l->tok;
+
+ for (uint8_t found = 0; tok && !found; tok = tok->next) {
+ switch (tok->id) {
+ case TOK_DIR:
+ type = (tok->type == DIR_UNION);
+ found = (tok->type == DIR_STRUCT || tok->type == DIR_UNION);
+ break;
+ case TOK_STRUCT:
+ case TOK_UNION : type = (tok->id == TOK_UNION); found = 1; break;
+ }
+ }
+ if (tok != NULL) {
+ strct = tok->sym;
+ }
+
+ if (l && l->next) {
+ l = l->next;
+ }
+
+ for (; l && !done; l = l->next) {
+ token *t = l->tok;
+ token *start = t;
+ symbol *member;
+ for (; t && !done; t = t->next) {
+ switch (t->id) {
+ case TOK_MEMBER: ismember = 1; member = t->sym; break;
+ case TOK_DIR :
+ ismember = (t->type == DIR_STRUCT || t->type == DIR_UNION) ? 1 : ismember;
+ done = ((!type && t->type == DIR_ENDSTRUCT) || (type && t->type == DIR_ENDUNION));
+ if (!done && ismember) {
+ switch (t->type) {
+ case DIR_BYTE : member_size = 1; break;
+ case DIR_WORD : member_size = 2; break;
+ case DIR_DWORD : member_size = 4; break;
+ case DIR_QWORD : member_size = 8; break;
+ case DIR_UNION :
+ case DIR_STRUCT: member_size = handle_struct(&l, address, offset, dbg); break;
+ case DIR_RES : member_size = get_val(t, address, 3, dbg); t = skip_expr(t, dbg); break;
+ }
+ if (member && t->type != DIR_UNION && t->type != DIR_STRUCT) {
+ member->val = offset;
+ }
+ if (size < member_size) {
+ size = member_size;
+ }
+ if (!type) {
+ offset += size;
+ }
+ }
+ ismember = 0;
+ break;
+ }
+ }
+ if (done) {
+ break;
+ }
+ }
+ *ln = l;
+ if (strct != NULL) {
+ strct->val = offset;
+ }
+ return (!type) ? offset : size;
+}
+
uint64_t handle_directive(token *t, bytecount *bc, uint8_t isasm, uint64_t address, uint8_t dbg) {
union reg val;
uint8_t c = 0;
@@ -464,11 +541,13 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address,
return address;
}
-uint64_t parse_tokens(token *t, bytecount *bc, uint8_t isasm, uint64_t address, uint8_t dbg) {
+uint64_t parse_tokens(token *t, line **l, bytecount *bc, uint8_t isasm, uint64_t address, uint8_t dbg) {
for (; t; t = t->next) {
switch (t->id) {
case TOK_DIR:
switch (t->type) {
+ case DIR_STRUCT:
+ case DIR_UNION : handle_struct(l, address, 0, dbg); break;
case DIR_RES: t = t->next; address += get_val(t, address, 3, dbg); break;
case DIR_ORG: t = t->next; address = get_val(t, address, 3, dbg); break;
case DIR_BYTE:
@@ -519,7 +598,7 @@ void assemble(line *ln, bytecount *bc, uint8_t dbg) {
for (; l; l = l->next) {
l->addr = address;
token *t = l->tok;
- address = parse_tokens(t, bc, 0, address, dbg);
+ address = parse_tokens(t, &l, bc, 0, address, dbg);
}
l = ln;
for (; l; l = l->next) {
@@ -536,67 +615,106 @@ void assemble(line *ln, bytecount *bc, uint8_t dbg) {
bc->progsize = 0;
bc->datasize = 0;
for (; l; l = l->next) {
- address = parse_tokens(l->tok, bc, 1, address, dbg);
+ address = parse_tokens(l->tok, &l, bc, 1, address, dbg);
}
}
static inline void free_tokens(token *t) {
token *tok;
- while (t != NULL) {
+ if (t != NULL) {
tok = t;
t = t->next;
free(tok);
+ free_tokens(t);
}
}
-void free_lines() {
- line *l = lines;
+void free_lines(line *l) {
line *ln;
- while (l != NULL) {
+ if (l != NULL) {
free_tokens(l->tok);
ln = l;
l = l->next;
free(ln);
+ free_lines(l);
+ }
+}
+
+void print_symtree(symbol *s) {
+ int depth = 0;
+ int lol = 0;
+ while (s) {
+ for (int i = depth; i; i--) {
+ putchar('|');
+ if (i > 1) {
+ printf(" ");
+ }
+ }
+ if (depth) {
+ printf("--");
+ }
+ if (s->name != NULL) {
+ if (!strcmp(s->name, "printc")) {
+ lol = 1;
+ }
+ printf("%s\n", s->name);
+ }
+ if (s->down != NULL) {
+ s = s->down;
+ depth++;
+ continue;
+ }
+ if (s->next == NULL) {
+ if (s->up != NULL) {
+ for (; !s->next && s->up; s = s->up, depth--);
+ }
+ }
+ s = s->next;
}
}
void free_symbols(symbol *s) {
symbol *sym;
- while (s != NULL) {
- if (s->local) {
- free_symbols(s->local);
+ sym = s;
+ if (sym != NULL) {
+ if (s->down) {
+ free_symbols(s->down);
}
- sym = s;
- s = s->next;
if (sym->name != NULL) {
free(sym->name);
+ sym->name = NULL;
}
+ s = s->next;
free(sym);
+ sym = NULL;
+ free_symbols(s);
}
}
-static inline void free_fixups() {
- fixup *f = fixups;
+static inline void free_fixups(fixup *f) {
fixup *fix;
- while (f != NULL) {
+ if (f != NULL) {
fix = f;
f = f->next;
free(fix);
+ fix = NULL;
+ free_fixups(f);
}
}
void cleanup() {
uint16_t i;
if (lines) {
- free_lines();
+ free_lines(lines);
lines = NULL;
}
if (symbols) {
+ /*print_symtree(symbols);*/
free_symbols(symbols);
symbols = NULL;
}
if (fixups) {
- free_fixups();
+ free_fixups(fixups);
fixups = NULL;
}
while (i < stridx || i < comidx) {