summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOxore <oxore@protonmail.com>2023-08-12 00:50:22 +0300
committerOxore <oxore@protonmail.com>2023-08-12 00:50:22 +0300
commit3e584a3df6bede3ae545ae530c619ba6eecc97c9 (patch)
treec3fc9afbf17f0e79d81c044f3e85be63f8c2986e
parent5a724adfc7cfbdd015c38e8627d491e8c297964d (diff)
Impl basic kind of instruction emission
-rw-r--r--main.c150
1 files changed, 143 insertions, 7 deletions
diff --git a/main.c b/main.c
index a6897ae..f6b9560 100644
--- a/main.c
+++ b/main.c
@@ -379,7 +379,6 @@ enum arg_type {
ARG_SR,
ARG_CCR,
ARG_USP,
- ARG_EXPR,
};
enum args_count {
@@ -1422,7 +1421,6 @@ static const char *arg_type_to_string(const enum arg_type type)
case ARG_SR: return "SR";
case ARG_CCR: return "CCR";
case ARG_USP: return "USP";
- case ARG_EXPR: return "EXPR";
}
UNREACHABLE();
return "_UNKNOWN";
@@ -1497,14 +1495,13 @@ static void fprint_expr(
fputc(']', s);
}
-static void fprint_arg(
+static void fprint_arg_debug(
const struct lex *const lex,
const struct arg *const arg,
FILE *const s)
{
fprintf(s, "(%s", arg_type_to_string(arg->type));
switch (arg->type) {
- case ARG_NONE:
case ARG_DN:
fprintf(s, " reg [d%d]", arg->xn);
break;
@@ -1562,10 +1559,17 @@ static void fprint_arg(
}
}
fprintf(s, "]");
+ break;
case ARG_SR:
+ fprintf(s, "reg [sr]");
+ break;
case ARG_CCR:
+ fprintf(s, "reg [ccr]");
+ break;
case ARG_USP:
- case ARG_EXPR:
+ fprintf(s, "reg [usp]");
+ break;
+ case ARG_NONE:
break;
}
fprintf(s, " raw-tokens [");
@@ -1596,13 +1600,13 @@ static int fprint_stmt_debug(
fprintf(s, "\n\t(size %s)", opsize_to_string(stmt->instruction.opsize));
if (stmt->instruction.arg1.type != ARG_NONE) {
fprintf(s, "\n\t(arg1 ");
- fprint_arg(lex, &stmt->instruction.arg1, s);
+ fprint_arg_debug(lex, &stmt->instruction.arg1, s);
fprintf(s, ")");
}
if (stmt->instruction.arg2.type != ARG_NONE) {
assert(stmt->instruction.arg1.type != ARG_NONE);
fprintf(s, "\n\t(arg2 ");
- fprint_arg(lex, &stmt->instruction.arg2, s);
+ fprint_arg_debug(lex, &stmt->instruction.arg2, s);
fprintf(s, ")");
}
} else if (stmt->type == ST_DIRECTIVE) {
@@ -2729,6 +2733,7 @@ static int pars_parse_instruction(
static int pars_parse_assignment(
struct pars *const self, const size_t label_id, const size_t symbol_id)
{
+ // TODO
(void) label_id;
(void) symbol_id;
return pars_yield_error_msg(self, self->cur_tok_id, E_NIMPL);
@@ -2835,6 +2840,113 @@ static int assem_resolve(struct assem *const self)
return OK;
}
+static void emit_expr(
+ const struct lex *const lex,
+ const struct expr_tokens_span *const expr,
+ FILE *const s)
+{
+ for (size_t i = 0; i < expr->num_tokens; i++) {
+ const struct token token = lex->tokbuf[expr->first_token + i];
+ if (token.type == TT_NEWLINE) {
+ break;
+ }
+ fprintf(s, "%.*s", (int)token.length, lex->input + token.offset);
+ }
+}
+
+static void emit_arg(
+ const struct lex *const lex,
+ const struct arg *const arg,
+ FILE *const s)
+{
+ switch (arg->type) {
+ case ARG_DN:
+ fprintf(s, "%%d%d", arg->xn);
+ break;
+ case ARG_AN:
+ fprintf(s, "%%a%d", arg->xn);
+ break;
+ case ARG_AN_ADDR:
+ fprintf(s, "%%a%d@", arg->xn);
+ break;
+ case ARG_AN_ADDR_INCR:
+ fprintf(s, "%%a%d@+", arg->xn);
+ break;
+ case ARG_AN_ADDR_DECR:
+ fprintf(s, "%%a%d@-", arg->xn);
+ break;
+ case ARG_AN_ADDR_16:
+ fprintf(s, "%%a%d@(", arg->xn);
+ emit_expr(lex, &arg->expr, s);
+ fprintf(s, ")");
+ break;
+ case ARG_AN_ADDR_8_XI:
+ fprintf(s, "%%a%d@(", arg->xn);
+ emit_expr(lex, &arg->expr, s);
+ {
+ const char reg_type = arg->xi & 0x8 ? 'a' : 'd';
+ const char size = arg->briefext_size == OPSIZE_L ? 'l' : 'w';
+ fprintf(s, ",%c%d:%c)", reg_type, arg->xi & 0x7, size);
+ }
+ break;
+ case ARG_ADDR_WORD:
+ emit_expr(lex, &arg->expr, s), fprintf(s, ".w");
+ break;
+ case ARG_ADDR_LONG:
+ emit_expr(lex, &arg->expr, s), fprintf(s, ".l");
+ break;
+ case ARG_ADDR_UNSPEC:
+ emit_expr(lex, &arg->expr, s);
+ break;
+ case ARG_PC_ADDR_16:
+ fprintf(s, "%%pc@(");
+ emit_expr(lex, &arg->expr, s);
+ fprintf(s, ")");
+ break;
+ case ARG_PC_ADDR_8_XI:
+ fprintf(s, "%%pc@(");
+ emit_expr(lex, &arg->expr, s);
+ {
+ const char reg_type = arg->xi & 0x8 ? 'a' : 'd';
+ const char size = arg->briefext_size == OPSIZE_L ? 'l' : 'w';
+ fprintf(s, ",%c%d:%c)", reg_type, arg->xi & 0x7, size);
+ }
+ break;
+ case ARG_IMMEDIATE:
+ fprintf(s, "#"), emit_expr(lex, &arg->expr, s);
+ break;
+ case ARG_REGMASK:
+ {
+ // TODO make it concise
+ bool leading_space = false;
+ for (unsigned i = 0; i < 8; i++) {
+ if (arg->regmask & (1 << i)) {
+ fprintf(s, "%s%%d%d", leading_space ? "/" : "", i);
+ leading_space = true;
+ }
+ }
+ for (unsigned i = 0; i < 8; i++) {
+ if (arg->regmask & (1 << (i + 8))) {
+ fprintf(s, "%s%%a%d", leading_space ? "/" : "", i);
+ leading_space = true;
+ }
+ }
+ }
+ break;
+ case ARG_SR:
+ fprintf(s, "%%sr");
+ break;
+ case ARG_CCR:
+ fprintf(s, "%%ccr");
+ break;
+ case ARG_USP:
+ fprintf(s, "%%usp");
+ break;
+ case ARG_NONE:
+ break;
+ }
+}
+
static int assem_emit(struct assem *const self, FILE *const stream)
{
const struct lex *const lex = self->pars->lex;
@@ -2849,6 +2961,30 @@ static int assem_emit(struct assem *const self, FILE *const stream)
fprint_stmt_debug(lex, pars->stmttab + i, stream);
}
}
+ for (size_t i = 1; i < pars->stmttab_size / (sizeof *pars->stmttab); i++) {
+ const struct stmt *stmt = pars->stmttab + i;
+ if (stmt->label_token) {
+ const struct token token = lex->tokbuf[stmt->label_token];
+ fprintf(stream, "%.*s:", (int)token.length, lex->input + token.offset);
+ }
+ if (stmt->type == ST_INSTRUCTION) {
+ const struct instruction instr = stmt->instruction;
+ fprintf(stream, "\t%s", mnemonic_to_string(instr.mnemonic));
+ if (instr.arg1.type != ARG_NONE) {
+ fprintf(stream, " ");
+ emit_arg(lex, &instr.arg1, stream);
+ if (instr.arg2.type != ARG_NONE) {
+ fprintf(stream, ", ");
+ emit_arg(lex, &instr.arg2, stream);
+ }
+ }
+ }
+ if (stmt->comment_token) {
+ const struct token token = lex->tokbuf[stmt->comment_token];
+ fprintf(stream, " %.*s", (int)token.length, lex->input + token.offset);
+ }
+ fprintf(stream, "\n");
+ }
return OK;
}