diff options
author | Oxore <oxore@protonmail.com> | 2023-08-13 13:46:32 +0300 |
---|---|---|
committer | Oxore <oxore@protonmail.com> | 2023-08-13 13:46:32 +0300 |
commit | 3d02eab027120b9cc1416a22dab0defbc90c5a3b (patch) | |
tree | edeb15ee23e1d7b8d2201d9ad3772cf48c61c7c3 | |
parent | bac14a58c850e4b3b7fad4e145952c6fd0725015 (diff) |
Begin impl Bcc resolution (impl symbol table)
-rw-r--r-- | main.c | 103 |
1 files changed, 98 insertions, 5 deletions
@@ -468,12 +468,17 @@ struct token_recognition { }; }; +struct sym { + size_t stmt_id; + size_t addr; +}; + struct pars { const struct lex *lex; // State size_t cur_tok_id; enum pars_error error; - bool in_sat; /// Indicates whether inside .def ... .endef block or not + bool in_sat; ///< Indicates whether inside .def ... .endef block or not // Statement table FILE *stmttab_stream; struct stmt *stmttab; @@ -482,6 +487,7 @@ struct pars { FILE *symtab_stream; struct sym *symtab; size_t symtab_size; + uint32_t addr_cursor; ///< Current address relative to parsed instructions // Symbol buffer for symbol table FILE *symbuf_stream; char *symbuf; @@ -1660,6 +1666,72 @@ static int fwrite_stmt(const struct stmt *const stmt, FILE *const stream) return res; } +static size_t get_arg_size( + const struct arg *const arg, const enum opsize opsize) +{ + switch (arg->type) { + case ARG_NONE: return 0; + case ARG_DN: return 0; + case ARG_AN: return 0; + case ARG_AN_ADDR: return 0; + case ARG_AN_ADDR_INCR: return 0; + case ARG_AN_ADDR_DECR: return 0; + case ARG_AN_ADDR_16: return 2; + case ARG_AN_ADDR_8_XI: + return arg->briefext_size == OPSIZE_W ? 2 : 4; // FIXME I'm not sure how it works + case ARG_ADDR_WORD: return 2; + case ARG_ADDR_LONG: return 4; + case ARG_ADDR_UNSPEC: return 2; // FIXME I'm not sure how it works + case ARG_PC_ADDR_16: return 2; + case ARG_PC_ADDR_8_XI: + return arg->briefext_size == OPSIZE_W ? 2 : 4; // FIXME I'm not sure how it works + case ARG_IMMEDIATE: + switch (opsize) { + case OPSIZE_S: + case OPSIZE_B: + return 1; + case OPSIZE_W: + return 2; + case OPSIZE_NONE: // FIXME it should depend on the value, I guess + case OPSIZE_L: + return 4; + } + break; + case ARG_REGMASK: return 2; + case ARG_SR: return 0; + case ARG_CCR: return 0; + case ARG_USP: return 0; + } + UNREACHABLE(); + return 0; +} + +static size_t get_instruction_size(const struct instruction *const instr) +{ + return 2 + get_arg_size(&instr->arg1, instr->opsize) + + get_arg_size(&instr->arg2, instr->opsize); +} + +static void pars_put_stmt( + struct pars *const self, const struct stmt *const stmt) +{ + if (stmt->label_token) { + // fflush is necessary to update stmttab_size variable + fflush(self->stmttab_stream); + const struct sym sym = { + .stmt_id = self->stmttab_size / (sizeof *self->stmttab), + .addr = self->addr_cursor, + }; + const int res = fwrite(&sym, sizeof sym, 1, self->symtab_stream); + assert(res == 1); + (void) res; + } + if (stmt->type == ST_INSTRUCTION) { + self->addr_cursor += get_instruction_size(&stmt->instruction); + } + fwrite_stmt(stmt, self->stmttab_stream); +} + static struct token pars_peek(const struct pars *const self) { return self->lex->tokbuf[self->cur_tok_id]; @@ -2020,7 +2092,7 @@ static int pars_finish_directive( .first_token = first_token, .num_tokens = self->cur_tok_id - first_token, }; - fwrite_stmt(&stmt, self->stmttab_stream); + pars_put_stmt(self, &stmt); return OK; } @@ -2675,7 +2747,7 @@ static int pars_yield_instruction( .first_token = first_token_id, .num_tokens = self->cur_tok_id - first_token_id, }; - fwrite_stmt(&stmt, self->stmttab_stream); + pars_put_stmt(self, &stmt); return OK; } @@ -2769,7 +2841,7 @@ static int pars_yield_label_comment( .first_token = first_token, .num_tokens = self->cur_tok_id - first_token, }; - fwrite_stmt(&stmt, self->stmttab_stream); + pars_put_stmt(self, &stmt); } return OK; } @@ -2819,7 +2891,7 @@ static int pars_run(struct pars *const self) // Skip dummy token at position 0 self->cur_tok_id = 1; // Leave dummy statement at position 0 - fwrite_stmt(&(struct stmt){0}, self->stmttab_stream); + pars_put_stmt(self, &(struct stmt){0}); int ret = OK; while (self->cur_tok_id < self->lex->tokens_count) { ret = pars_parse_statement(self); @@ -3098,6 +3170,21 @@ static enum opsize assem_resolve_bcc( return OPSIZE_S; } +static struct res { uint32_t value; bool ok; } assem_find_symbol( + const struct assem *const self, + const size_t stmt_id) +{ + for (size_t i = 0; i < self->pars->symtab_size / (sizeof *self->pars->symtab); i++) { + if ((self->pars->symtab + i)->stmt_id == stmt_id) { + return (struct res){ + .value = (self->pars->symtab + i)->addr, + .ok = true, + }; + } + } + return (struct res){ .ok = false }; +} + static int assem_emit(struct assem *const self, FILE *const stream) { const struct lex *const lex = self->pars->lex; @@ -3170,6 +3257,12 @@ static int assem_emit(struct assem *const self, FILE *const stream) const struct token token = lex->tokbuf[stmt->comment_token]; fprintf(stream, " |%.*s", (int)token.length - 1, lex->input + token.offset + 1); } + if (stmt->label_token) { + struct res res = assem_find_symbol(self, i); + if (res.ok) { + fprintf(stream, " | @%08x", res.value); + } + } fprintf(stream, "\n"); } return OK; |