diff options
Diffstat (limited to 'main.c')
-rw-r--r-- | main.c | 68 |
1 files changed, 54 insertions, 14 deletions
@@ -69,6 +69,8 @@ #define OK 1 #define CONTINUE 2 +#define BCC_S_MAX_BACKWARDS 126 + enum token_type { TT_NONE = 0, TT_NEWLINE, @@ -412,8 +414,8 @@ struct instruction { struct directive { enum directive_type type; - size_t name_token; /// Directive self first token - size_t first_token, num_tokens; /// Directive arguments tokens span + size_t name_token; ///< Directive self first token + size_t first_token, num_tokens; ///< Directive arguments tokens span }; struct stmt { @@ -425,6 +427,7 @@ struct stmt { size_t label_token; size_t first_token, num_tokens; // Statement tokens span, may be NULL size_t comment_token; + uint32_t addr; }; struct symbol { @@ -462,15 +465,15 @@ struct token_recognition { struct { enum reg_type reg; uint8_t reg_num; - }; // For RTT_REG - int32_t number; // For TT_ID - size_t symbol_id; // For TT_ID and TT_DOT_ID, see (struct pars).symtab + }; ///< For RTT_REG + int32_t number; ///< For TT_ID + size_t symbol_id; ///< For TT_ID and TT_DOT_ID, see (struct pars).symtab }; }; struct sym { size_t stmt_id; - size_t addr; + uint32_t addr; }; struct pars { @@ -478,7 +481,10 @@ struct pars { // State size_t cur_tok_id; enum pars_error error; - bool in_sat; ///< Indicates whether inside .def ... .endef block or not + /*! + * SAT stands for Symbol Attribute Table + */ + bool in_sat; ///< Indicates whether inside `.def ... .endef` block or not // Statement table FILE *stmttab_stream; struct stmt *stmttab; @@ -1713,7 +1719,7 @@ static size_t get_instruction_size(const struct instruction *const instr) } static void pars_put_stmt( - struct pars *const self, const struct stmt *const stmt) + struct pars *const self, struct stmt *const stmt) { if (stmt->label_token) { // fflush is necessary to update stmttab_size variable @@ -1727,6 +1733,7 @@ static void pars_put_stmt( (void) res; } if (stmt->type == ST_INSTRUCTION) { + stmt->addr = self->addr_cursor; self->addr_cursor += get_instruction_size(&stmt->instruction); } fwrite_stmt(stmt, self->stmttab_stream); @@ -2084,7 +2091,7 @@ static int pars_finish_directive( return ret; } const size_t first_token = label_id ? label_id : directive.name_token; - const struct stmt stmt = { + struct stmt stmt = { .type = ST_DIRECTIVE, .directive = directive, .label_token = label_id, @@ -2734,7 +2741,7 @@ static int pars_yield_instruction( break; } const size_t first_token_id = label_id ? label_id : mnemonic_id; - const struct stmt stmt = { + struct stmt stmt = { .type = ST_INSTRUCTION, .instruction = { .mnemonic = mnemonic, @@ -3164,10 +3171,43 @@ static enum opsize assem_resolve_bcc( const size_t stmt_number) { const struct pars *const pars = self->pars; - (void) pars; - (void) stmt_number; - // TODO impl real resolving - return OPSIZE_S; + const struct stmt *const stmt = pars->stmttab + stmt_number; + const struct instruction *const instr = &stmt->instruction; + const struct arg *const arg = &instr->arg1; + // XXX I'm not sure what else it can be, so let's catch it with an assert + assert(arg->type == ARG_ADDR_UNSPEC); + // Usually it is just a label - a single token + // TODO Impl support of expressions for real + assert(arg->expr.num_tokens); + const struct token *const target_token = pars->lex->tokbuf + arg->expr.first_token; + assert(target_token->type == TT_DOT_ID || target_token->type == TT_ID); + bool found = false; + uint32_t found_addr = 0; + for (size_t i = 0; i < pars->symtab_size; i++) { + const struct sym *const sym = pars->symtab + i; + if (sym->addr >= stmt->addr) { + // Current Bcc statement address reached or surpassed. And we are + // not interested in it if it is located either somewhere after + // current Bcc statement or in another translation unit. + break; + } + const struct stmt *const target = pars->stmttab + sym->stmt_id; + const struct token *const label_token = pars->lex->tokbuf + target->label_token; + const bool matches = 0 == memcmp( + pars->lex->input + label_token->offset, + pars->lex->input + target_token->offset, + target_token->length); + if (matches) { + found = true; + found_addr = sym->addr; + } + } + if (found && ((stmt->addr + 2 - found_addr) <= BCC_S_MAX_BACKWARDS)) { + return OPSIZE_S; + } + // Label is not found, therefore current Bcc size must be as wide as + // possible (word). This is original behavior of Sierra's ASM68.EXE. + return OPSIZE_W; } static struct res { uint32_t value; bool ok; } assem_find_symbol( |