diff --git a/src/tools/aindump/macros.c b/src/tools/aindump/macros.c index 601c065..94fb7d3 100644 --- a/src/tools/aindump/macros.c +++ b/src/tools/aindump/macros.c @@ -34,7 +34,149 @@ static bool check_opcode(struct dasm_state *dasm, enum opcode opcode) return dasm->instr->opcode == opcode && can_elide(dasm); } -static bool print_localref(struct dasm_state *dasm) +static bool check_next_opcode(struct dasm_state *dasm, enum opcode opcode) +{ + dasm_next(dasm); + return check_opcode(dasm, opcode); +} + +/* Macro List + +.GLOBALREF : + PUSHGLOBALPAGE + PUSH + REF + +.GLOBALREFREF : + PUSHGLOBALPAGE + PUSH + REFREF + +.LOCALREF : + PUSHLOCALPAGE + PUSH + REF + +.LOCALREFREF : + PUSHLOCALPAGE + PUSH + REFREF + +.LOCALINC: + PUSHLOCALPAGE + PUSH + INC + +.LOCALDEC: + PUSHLOCALPAGE + PUSH + DEC + +.LOCALASSIGN : + PUSHLOCALPAGE + PUSH + PUSH + ASSIGN + +.LOCALDELETE: + PUSHLOCALPAGE + PUSH + DUP2 + REF + DELETE + PUSH -1 + ASSIGN + POP + +.LOCALCREATE: + PUSHLOCALPAGE + PUSH + DUP2 + REF + DELETE + DUP2 + NEW -1 + ASSIGN + POP + POP + POP + + */ + +static void print_local(struct dasm_state *dasm, int32_t no) +{ + dasm_print_local_variable(dasm, &dasm->ain->functions[dasm->func], no); +} + +static bool local_create_or_delete_macro(struct dasm_state *dasm, int32_t varno) +{ + if (!check_next_opcode(dasm, REF)) + return false; + + if (!check_next_opcode(dasm, DELETE)) + return false; + + dasm_next(dasm); + if (check_opcode(dasm, PUSH)) { + // localdelete + if (dasm_arg(dasm, 0) != -1) + return false; + + if (!check_next_opcode(dasm, ASSIGN)) + return false; + + if (!check_next_opcode(dasm, POP)) + return false; + + fprintf(dasm->out, ".LOCALDELETE "); + dasm_print_local_variable(dasm, &dasm->ain->functions[dasm->func], varno); + fputc('\n', dasm->out); + return true; + } else if (check_opcode(dasm, DUP2)) { + // localcreate + if (!check_next_opcode(dasm, NEW)) + return false; + + int32_t structno = dasm_arg(dasm, 0); + if (structno < 0 || structno >= dasm->ain->nr_structures) + return false; + if (dasm_arg(dasm, 1) != -1) + return false; + + if (!check_next_opcode(dasm, ASSIGN)) + return false; + if (!check_next_opcode(dasm, POP)) + return false; + if (!check_next_opcode(dasm, POP)) + return false; + if (!check_next_opcode(dasm, POP)) + return false; + + fprintf(dasm->out, ".LOCALCREATE "); + print_local(dasm, varno); + fputc(' ', dasm->out); + dasm_print_identifier(dasm, dasm->ain->structures[structno].name); + fputc('\n', dasm->out); + return true; + } + + return false; +} + +static bool localassign_macro(struct dasm_state *dasm, int32_t no) +{ + int32_t val = dasm_arg(dasm, 0); + if (!check_next_opcode(dasm, ASSIGN)) + return false; + + fprintf(dasm->out, ".LOCALASSIGN "); + print_local(dasm, no); + fputc(' ', dasm->out); + fprintf(dasm->out, "%d\n", val); + return true; +} + +static bool localpage_macro(struct dasm_state *dasm) { dasm_next(dasm); if (!check_opcode(dasm, PUSH)) @@ -49,18 +191,39 @@ static bool print_localref(struct dasm_state *dasm) fprintf(dasm->out, ".LOCALREF "); } else if (check_opcode(dasm, REFREF)) { fprintf(dasm->out, ".LOCALREFREF "); + } else if (check_opcode(dasm, INC)) { + fprintf(dasm->out, ".LOCALINC "); + } else if (check_opcode(dasm, DEC)) { + fprintf(dasm->out, ".LOCALDEC "); + } else if (check_opcode(dasm, PUSH)) { + return localassign_macro(dasm, no); + } else if (check_opcode(dasm, DUP2)) { + return local_create_or_delete_macro(dasm, no); } else { return false; } - //dasm_print_identifier(dasm, dasm->ain->functions[dasm->func].vars[no].name); - dasm_print_local_variable(dasm, &dasm->ain->functions[dasm->func], no); + print_local(dasm, no); fputc('\n', dasm->out); return true; } -static bool print_globalref(struct dasm_state *dasm) +static bool globalassign_macro(struct dasm_state *dasm, int32_t no) +{ + int32_t val = dasm_arg(dasm, 0); + if (!check_next_opcode(dasm, ASSIGN)) + return false; + + fprintf(dasm->out, ".GLOBALASSIGN "); + dasm_print_identifier(dasm, dasm->ain->globals[no].name); + fputc(' ', dasm->out); + fprintf(dasm->out, "%d\n", val); + return true; + +} + +static bool globalpage_macro(struct dasm_state *dasm) { dasm_next(dasm); if (!check_opcode(dasm, PUSH)) @@ -75,6 +238,12 @@ static bool print_globalref(struct dasm_state *dasm) fprintf(dasm->out, ".GLOBALREF "); } else if (check_opcode(dasm, REFREF)) { fprintf(dasm->out, ".GLOBALREFREF "); + } else if (check_opcode(dasm, INC)) { + fprintf(dasm->out, ".GLOBALINC "); + } else if (check_opcode(dasm, DEC)) { + fprintf(dasm->out, ".GLOBALDEC "); + } else if (check_opcode(dasm, PUSH)) { + return globalassign_macro(dasm, no); } else { return false; } @@ -89,9 +258,9 @@ static bool _dasm_print_macro(struct dasm_state *dasm) { switch (dasm->instr->opcode) { case PUSHLOCALPAGE: - return print_localref(dasm); + return localpage_macro(dasm); case PUSHGLOBALPAGE: - return print_globalref(dasm); + return globalpage_macro(dasm); default: return false; } diff --git a/src/tools/ainedit/ainedit.h b/src/tools/ainedit/ainedit.h index 58faba6..cf27a49 100644 --- a/src/tools/ainedit/ainedit.h +++ b/src/tools/ainedit/ainedit.h @@ -36,6 +36,14 @@ enum asm_pseudo_opcode { PO_GLOBALREF, PO_LOCALREFREF, PO_GLOBALREFREF, + PO_LOCALINC, + PO_LOCALDEC, + PO_LOCALASSIGN, + PO_LOCALDELETE, + PO_LOCALCREATE, + PO_GLOBALINC, + PO_GLOBALDEC, + PO_GLOBALASSIGN, NR_PSEUDO_OPS }; diff --git a/src/tools/ainedit/asm.c b/src/tools/ainedit/asm.c index 0c6b1c1..95c5cb1 100644 --- a/src/tools/ainedit/asm.c +++ b/src/tools/ainedit/asm.c @@ -34,7 +34,7 @@ KHASH_MAP_INIT_STR(string_ht, size_t); // TODO: better error messages #define ASM_ERROR(state, ...) ERROR(__VA_ARGS__) -#define _PSEUDO_OP(code, _name, nargs, _ip_inc, ...) \ +#define MACRO(code, _name, nargs, _ip_inc, ...) \ [code - PSEUDO_OP_OFFSET] = { \ .opcode = code, \ .name = _name, \ @@ -55,14 +55,22 @@ KHASH_MAP_INIT_STR(string_ht, size_t); } const struct instruction asm_pseudo_ops[NR_PSEUDO_OPS - PSEUDO_OP_OFFSET] = { - PSEUDO_OP(PO_CASE, ".CASE", 2), - PSEUDO_OP(PO_DEFAULT, ".DEFAULT", 1), - PSEUDO_OP(PO_STR, ".STR", 2), - PSEUDO_OP(PO_MSG, ".MSG", 2), - _PSEUDO_OP(PO_LOCALREF, ".LOCALREF", 1, 10), - _PSEUDO_OP(PO_GLOBALREF, ".GLOBALREF", 1, 10), - _PSEUDO_OP(PO_LOCALREFREF, ".LOCALREFREF", 1, 10), - _PSEUDO_OP(PO_GLOBALREFREF, ".GLOBALREFREF", 1, 10), + PSEUDO_OP(PO_CASE, ".CASE", 2), + PSEUDO_OP(PO_DEFAULT, ".DEFAULT", 1), + PSEUDO_OP(PO_STR, ".STR", 2), + PSEUDO_OP(PO_MSG, ".MSG", 2), + MACRO(PO_LOCALREF, ".LOCALREF", 1, 10), + MACRO(PO_GLOBALREF, ".GLOBALREF", 1, 10), + MACRO(PO_LOCALREFREF, ".LOCALREFREF", 1, 10), + MACRO(PO_GLOBALREFREF, ".GLOBALREFREF", 1, 10), + MACRO(PO_LOCALINC, ".LOCALINC", 1, 10), + MACRO(PO_LOCALDEC, ".LOCALDEC", 1, 10), + MACRO(PO_LOCALASSIGN, ".LOCALASSIGN", 2, 16), + MACRO(PO_LOCALDELETE, ".LOCALDELETE", 1, 24), + MACRO(PO_LOCALCREATE, ".LOCALCREATE", 2, 34), + MACRO(PO_GLOBALINC, ".GLOBALINC", 1, 10), + MACRO(PO_GLOBALDEC, ".GLOBALDEC", 1, 10), + MACRO(PO_GLOBALASSIGN, ".GLOBALASSIGN", 2, 16), }; struct string_table { @@ -513,6 +521,82 @@ void handle_pseudo_op(struct asm_state *state, struct parse_instruction *instr) asm_write_opcode(state, REFREF); break; } + case PO_LOCALINC: { + asm_write_opcode(state, PUSHLOCALPAGE); + asm_write_opcode(state, PUSH); + asm_write_argument(state, asm_resolve_arg(state, PUSH, T_LOCAL, kv_A(*instr->args, 0)->text)); + asm_write_opcode(state, INC); + break; + } + case PO_LOCALDEC: { + asm_write_opcode(state, PUSHLOCALPAGE); + asm_write_opcode(state, PUSH); + asm_write_argument(state, asm_resolve_arg(state, PUSH, T_LOCAL, kv_A(*instr->args, 0)->text)); + asm_write_opcode(state, DEC); + break; + } + case PO_LOCALASSIGN: { + asm_write_opcode(state, PUSHLOCALPAGE); + asm_write_opcode(state, PUSH); + asm_write_argument(state, asm_resolve_arg(state, PUSH, T_LOCAL, kv_A(*instr->args, 0)->text)); + asm_write_opcode(state, PUSH); + asm_write_argument(state, asm_resolve_arg(state, PUSH, T_INT, kv_A(*instr->args, 1)->text)); + asm_write_opcode(state, ASSIGN); + break; + } + case PO_LOCALDELETE: { + asm_write_opcode(state, PUSHLOCALPAGE); + asm_write_opcode(state, PUSH); + asm_write_argument(state, asm_resolve_arg(state, PUSH, T_LOCAL, kv_A(*instr->args, 0)->text)); + asm_write_opcode(state, DUP2); + asm_write_opcode(state, REF); + asm_write_opcode(state, DELETE); + asm_write_opcode(state, PUSH); + asm_write_argument(state, -1); + asm_write_opcode(state, ASSIGN); + asm_write_opcode(state, POP); + break; + } + case PO_LOCALCREATE: { + asm_write_opcode(state, PUSHLOCALPAGE); + asm_write_opcode(state, PUSH); + asm_write_argument(state, asm_resolve_arg(state, PUSH, T_LOCAL, kv_A(*instr->args, 0)->text)); + asm_write_opcode(state, DUP2); + asm_write_opcode(state, REF); + asm_write_opcode(state, DELETE); + asm_write_opcode(state, DUP2); + asm_write_opcode(state, NEW); + asm_write_argument(state, asm_resolve_arg(state, NEW, T_STRUCT, kv_A(*instr->args, 1)->text)); + asm_write_argument(state, -1); + asm_write_opcode(state, ASSIGN); + asm_write_opcode(state, POP); + asm_write_opcode(state, POP); + asm_write_opcode(state, POP); + break; + } + case PO_GLOBALINC: { + asm_write_opcode(state, PUSHGLOBALPAGE); + asm_write_opcode(state, PUSH); + asm_write_argument(state, asm_resolve_arg(state, PUSH, T_GLOBAL, kv_A(*instr->args, 0)->text)); + asm_write_opcode(state, INC); + break; + } + case PO_GLOBALDEC: { + asm_write_opcode(state, PUSHGLOBALPAGE); + asm_write_opcode(state, PUSH); + asm_write_argument(state, asm_resolve_arg(state, PUSH, T_GLOBAL, kv_A(*instr->args, 0)->text)); + asm_write_opcode(state, DEC); + break; + } + case PO_GLOBALASSIGN: { + asm_write_opcode(state, PUSHGLOBALPAGE); + asm_write_opcode(state, PUSH); + asm_write_argument(state, asm_resolve_arg(state, PUSH, T_GLOBAL, kv_A(*instr->args, 0)->text)); + asm_write_opcode(state, PUSH); + asm_write_argument(state, asm_resolve_arg(state, PUSH, T_INT, kv_A(*instr->args, 1)->text)); + asm_write_opcode(state, ASSIGN); + break; + } } }