diff options
Diffstat (limited to 'assemble.c')
-rw-r--r-- | assemble.c | 154 |
1 files changed, 136 insertions, 18 deletions
@@ -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) { |