summaryrefslogtreecommitdiff
path: root/assemble.c
diff options
context:
space:
mode:
Diffstat (limited to 'assemble.c')
-rw-r--r--assemble.c239
1 files changed, 189 insertions, 50 deletions
diff --git a/assemble.c b/assemble.c
index 2114456..24037d9 100644
--- a/assemble.c
+++ b/assemble.c
@@ -115,8 +115,6 @@ uint64_t get_val(token *t, uint64_t addr, uint8_t size, uint8_t dbg) {
}
token *skip_expr(token *t, uint8_t dbg) {
- /*if (t->next && t->next->id == TOK_EXPR && isexpr(t->next->type, dbg)) {
- }*/
do {
t = (t->id == TOK_EXPR) ? t->next : t;
switch (t->id) {
@@ -144,7 +142,7 @@ uint8_t get_directivesize(uint8_t type, uint8_t dbg) {
}
uint16_t handle_struct(line **ln, uint64_t address, uint16_t offset, uint8_t dbg) {
- uint8_t type = 0;
+ uint8_t is_struct = 0;
uint8_t done = 0;
uint8_t ismember = 0;
uint16_t size = 0;
@@ -156,11 +154,11 @@ uint16_t handle_struct(line **ln, uint64_t address, uint16_t offset, uint8_t dbg
for (uint8_t found = 0; tok && !found; tok = tok->next) {
switch (tok->id) {
case TOK_DIR:
- type = (tok->type == DIR_UNION);
+ is_struct = (tok->type == DIR_STRUCT);
found = (tok->type == DIR_STRUCT || tok->type == DIR_UNION);
break;
- case TOK_STRUCT:
- case TOK_UNION : type = (tok->id == TOK_UNION); found = 1; break;
+ case TOK_STRUCT: is_struct = 1;
+ case TOK_UNION : found = 1; break;
}
}
if (tok != NULL) {
@@ -180,7 +178,7 @@ uint16_t handle_struct(line **ln, uint64_t address, uint16_t offset, uint8_t dbg
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));
+ done = ((is_struct && t->type == DIR_ENDSTRUCT) || (!is_struct && t->type == DIR_ENDUNION));
if (!done && ismember) {
switch (t->type) {
case DIR_BYTE : member_size = 1; break;
@@ -194,11 +192,9 @@ uint16_t handle_struct(line **ln, uint64_t address, uint16_t offset, uint8_t dbg
if (member && t->type != DIR_UNION && t->type != DIR_STRUCT) {
member->val = offset;
}
- if (size < member_size) {
- size = member_size;
- }
- if (!type) {
- offset += size;
+ size += member_size;
+ if (is_struct) {
+ offset += member_size;
}
}
ismember = 0;
@@ -211,9 +207,9 @@ uint16_t handle_struct(line **ln, uint64_t address, uint16_t offset, uint8_t dbg
}
*ln = l;
if (strct != NULL) {
- strct->val = offset;
+ strct->val = size;
}
- return (!type) ? offset : size;
+ return size;
}
uint64_t handle_directive(token *t, bytecount *bc, uint8_t isasm, uint64_t address, uint8_t dbg) {
@@ -619,6 +615,167 @@ void assemble(line *ln, bytecount *bc, uint8_t dbg) {
}
}
+static void find_dupsym() {
+ symbol *root = symbols;
+ symbol *s = symbols;
+ for (; s; s = s->next) {
+ root = symbols;
+ for (int i = 0; root; root = root->next) {
+ if (root == s) {
+ i++;
+ }
+ if (i > 1) {
+ printf("Found duplicate symbol, s->name: %s, root->name: %s\n", s->name, root->name);
+ i = 0;
+ }
+ }
+ }
+}
+
+static symbol *find_fixup(token *t) {
+ fixup* f = fixups;
+ for (; f && t != f->t; f = f->next);
+ return (f && t == f->t) ? f->s : NULL;
+}
+
+
+static void print_symval(symbol *s) {
+ if (s) {
+ if (s->down) {
+ print_symval(s->down);
+ }
+ if (s->name) {
+ printf("s->name: %s, s->val: $%"PRIX64"\n", s->name, s->val);
+ }
+ print_symval(s->next);
+ }
+}
+
+static void print_symtree(symbol *s, int depth) {
+ if (s) {
+ if (s->name != NULL) {
+ for (int i = depth; i; i--) {
+ printf("|%s", (i > 1) ? " " : "--");
+ }
+ printf("%s: $%"PRIX64"\n", s->name, s->val);
+ }
+ if (s->down != NULL) {
+ print_symtree(s->down, depth+1);
+ }
+ print_symtree(s->next, depth);
+ }
+}
+
+static void fix_symtree(line *l) {
+ symbol *s = symbols;
+ symbol *cur_sym = NULL;
+ symbol *sym_struct = NULL;
+ symbols = NULL;
+ last_sym = NULL;
+ int islocal = 0;
+ int isanon = 0;
+ int is_struct = 0;
+ int is_structsym = 0;
+ for (; l; l = l->next) {
+ token *t = l->tok;
+ token *lt = NULL;
+ for (; t; t = t->next) {
+ int ismember = (t->id == TOK_MEMBER);
+ switch (t->id) {
+ case TOK_STRUCT:
+ case TOK_UNION : islocal = !(is_struct == 1 && lt && lt->id == TOK_DIR);
+ case TOK_SYM :
+ if (t->id == TOK_SYM && t != l->tok) {
+ break;
+ }
+ case TOK_MEMBER:
+ case TOK_LABEL :
+ if (symbols) {
+ (!islocal && s && !s->up) ? (last_sym = s) : (last_loc = s);
+ }
+ if (((t->type == 1 || ismember) && !islocal) || (islocal && ismember && is_structsym)) {
+ is_structsym = 0;
+ last_loc = NULL;
+ islocal = 1;
+ cur_sym = s;
+ s->down = t->sym;
+ s->down->up = s;
+ s = s->down;
+ if (s) {
+ s->next = NULL;
+ s->prev = NULL;
+ s->down = NULL;
+ }
+ locals = s;
+ } else if ((islocal || t->type == 0)) {
+ if (t->type == 0 && !is_struct && islocal && !ismember) {
+ islocal = 0;
+ if (s) {
+ s->up->down = locals;
+ s = s->up;
+ }
+ }
+ symbol *tmp = s;
+ s = t->sym;
+ if (s) {
+ s->prev = (tmp && tmp != s) ? tmp : NULL;
+ s->up = (s->prev) ? s->prev->up : s->up;
+ }
+ if (s && s->next) {
+ s->next = NULL;
+ }
+ }
+ if (!islocal) {
+ last_loc = NULL;
+ (last_sym) ? (last_sym->next = s) : (symbols = s);
+ cur_sym = s;
+ if (last_sym) {
+ last_sym->next->prev = last_sym;
+ last_sym->next->up = last_sym->up;
+ last_sym->next->down = NULL;
+ }
+ } else {
+ (last_loc) ? (last_loc->next = s) : (locals = s);
+ if (last_loc) {
+ last_loc->next->prev = last_loc;
+ last_loc->next->up = last_loc->up;
+ last_loc->next->down = NULL;
+ } else {
+ locals->prev = NULL;
+ locals->down = NULL;
+ }
+ }
+ break;
+ case TOK_DIR:
+ if (t->type == DIR_STRUCT || t->type == DIR_UNION) {
+ is_struct++;
+ is_structsym = (t->next && (t->next->id == TOK_STRUCT || t->next->id == TOK_UNION));
+ if ((!is_structsym) || (isanon && is_structsym)) {
+ isanon++;
+ }
+ } else if (t->type == DIR_ENDSTRUCT || t->type == DIR_ENDUNION) {
+ is_struct--;
+ int skip = 0;
+ if (isanon > 0) {
+ if ((cur_sym->up && !cur_sym->up->isanon) || (sym_struct && sym_struct->isanon)) {
+ isanon--;
+ }
+ skip = (!isanon);
+ }
+ if ((int)(is_struct-isanon) > 0 && !skip && cur_sym->up) {
+ for (sym_struct = s->up; sym_struct->prev && !sym_struct->isanon; sym_struct = sym_struct->prev);
+ s = s->up;
+ cur_sym = (cur_sym->up != NULL) ? cur_sym->up : s;
+ }
+ }
+ break;
+ }
+ lt = t;
+ }
+ }
+}
+
+
static inline void free_tokens(token *t) {
token *tok;
if (t != NULL) {
@@ -640,44 +797,11 @@ void free_lines(line *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) {
+static void free_symbols(symbol *s) {
symbol *sym;
sym = s;
if (sym != NULL) {
- if (s->down) {
+ if (s && s->down) {
free_symbols(s->down);
}
if (sym->name != NULL) {
@@ -702,14 +826,29 @@ static inline void free_fixups(fixup *f) {
}
}
+uint64_t get_tokmem(token *t) {
+ uint64_t i = 0;
+ for (; t; t = t->next, i++);
+ return i*sizeof(token);
+}
+
+void get_linemem(line *l) {
+ uint64_t i = 0;
+ uint64_t j = 0;
+ for (; l; j += get_tokmem(l->tok), l = l->next, i++);
+ printf("Bytes per line: %"PRIu64", Bytes per token: %"PRIu64", Total size of line table in bytes: %"PRIu64"\n", sizeof(line), sizeof(token), j+(i*sizeof(line)));
+}
+
void cleanup() {
uint16_t i;
if (lines) {
+ /*get_linemem(lines);*/
+ /*fix_symtree(lines);*/
free_lines(lines);
lines = NULL;
}
if (symbols) {
- /*print_symtree(symbols);*/
+ /*print_symtree(symbols, 0);*/
free_symbols(symbols);
symbols = NULL;
}