summaryrefslogtreecommitdiff
path: root/assemble.c
diff options
context:
space:
mode:
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) {