diff options
| -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; | 
