summaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'main.c')
-rw-r--r--main.c103
1 files changed, 98 insertions, 5 deletions
diff --git a/main.c b/main.c
index f718149..2471e96 100644
--- a/main.c
+++ b/main.c
@@ -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;