From 59eb85245f45331fbf739fdbc54370d07a09148d Mon Sep 17 00:00:00 2001 From: Nunuhara Cabbage Date: Fri, 29 May 2020 18:54:32 -0700 Subject: [PATCH] aindump/ainedit: various macros .LOCALINC2/.LOCALDEC2 are semantically identical to .LOCALINC/.LOCALDEC except that they represent an uglier instruction sequence which is frequently used in Rance 10. .LOCALPLUSA/.LOCALMINUSA and .STRING_LOCALASSIGN do what you would expect. --- src/tools/aindump/dasm.c | 16 ++++---- src/tools/aindump/dasm.h | 1 + src/tools/aindump/macros.c | 32 +++++++++++++++- src/tools/ainedit/ainedit.h | 5 +++ src/tools/ainedit/asm.c | 70 +++++++++++++++++++++++++++++++--- src/tools/ainedit/asm_lexer.l | 17 +++++---- src/tools/ainedit/asm_parser.y | 6 ++- 7 files changed, 123 insertions(+), 24 deletions(-) diff --git a/src/tools/aindump/dasm.c b/src/tools/aindump/dasm.c index 9de59fb..072dd45 100644 --- a/src/tools/aindump/dasm.c +++ b/src/tools/aindump/dasm.c @@ -219,7 +219,7 @@ char *escape_string(const char *str) return _escape_string(str, escape_chars, replace_chars); } -static void print_string(struct dasm_state *dasm, const char *str) +void dasm_print_string(struct dasm_state *dasm, const char *str) { char *u = escape_string(str); fprintf(dasm->out, "\"%s\"", u); @@ -230,7 +230,7 @@ void dasm_print_identifier(struct dasm_state *dasm, const char *str) { char *u = encode_text_utf8(str); if (strchr(u, ' ')) - print_string(dasm, str); + dasm_print_string(dasm, str); else print_sjis(dasm, str); free(u); @@ -335,7 +335,7 @@ static void print_argument(struct dasm_state *dasm, int32_t arg, enum instructio fprintf(dasm->out, "0x%x ", arg); *comment = ain->strings[arg]->text; } else { - print_string(dasm, ain->strings[arg]->text); + dasm_print_string(dasm, ain->strings[arg]->text); } break; case T_MSG: @@ -345,14 +345,14 @@ static void print_argument(struct dasm_state *dasm, int32_t arg, enum instructio fprintf(dasm->out, "0x%x ", arg); *comment = ain->messages[arg]->text; } else { - print_string(dasm, ain->messages[arg]->text); + dasm_print_string(dasm, ain->messages[arg]->text); } break; case T_LOCAL: if (dasm->func < 0) { DASM_ERROR(dasm, "Attempt to access local variable outside of function"); //WARNING("Attempt to access local variable outside of function"); - //print_string(dasm, "???"); + //dasm_print_string(dasm, "???"); break; } if (arg < 0 || arg >= ain->functions[dasm->func].nr_vars) @@ -423,7 +423,7 @@ static void print_arguments(struct dasm_state *dasm, const struct instruction *i } if (comment) { fprintf(dasm->out, "; "); - print_string(dasm, comment); + dasm_print_string(dasm, comment); } } @@ -489,9 +489,9 @@ static void print_switch_case(struct dasm_state *dasm, struct ain_switch_case *c case AIN_SWITCH_STRING: if (dasm->flags & DASM_NO_STRINGS) { fprintf(dasm->out, "%d ; ", c->value); - print_string(dasm, dasm->ain->strings[c->value]->text); + dasm_print_string(dasm, dasm->ain->strings[c->value]->text); } else { - print_string(dasm, dasm->ain->strings[c->value]->text); + dasm_print_string(dasm, dasm->ain->strings[c->value]->text); } break; default: diff --git a/src/tools/aindump/dasm.h b/src/tools/aindump/dasm.h index 1e8026d..3a9fd8b 100644 --- a/src/tools/aindump/dasm.h +++ b/src/tools/aindump/dasm.h @@ -28,5 +28,6 @@ bool dasm_is_jump_target(struct dasm_state *dasm); bool dasm_print_macro(struct dasm_state *dasm); void dasm_print_identifier(struct dasm_state *dasm, const char *str); void dasm_print_local_variable(struct dasm_state *dasm, struct ain_function *func, int varno); +void dasm_print_string(struct dasm_state *dasm, const char *str); #endif /* AINDUMP_DASM_H */ diff --git a/src/tools/aindump/macros.c b/src/tools/aindump/macros.c index a3fd0c8..ad14ebd 100644 --- a/src/tools/aindump/macros.c +++ b/src/tools/aindump/macros.c @@ -20,6 +20,8 @@ #include #include "system4/ain.h" #include "system4/instructions.h" +#include "system4/string.h" +#include "system4/utfsjis.h" #include "aindump.h" #include "dasm.h" @@ -67,10 +69,15 @@ static bool local_check(struct dasm_state *dasm, int32_t *args) #define LOCALREF_check local_check #define LOCALREFREF_check local_check #define LOCALINC_check local_check +#define LOCALINC2_check local_check #define LOCALDEC_check local_check +#define LOCALDEC2_check local_check +#define LOCALPLUSA_check local_check +#define LOCALMINUSA_check local_check #define LOCALASSIGN_check local_check #define LOCALASSIGN2_check local_check #define F_LOCALASSIGN_check local_check +#define STRING_LOCALASSIGN_check local_check static bool S_LOCALASSIGN_check(struct dasm_state *dasm, int32_t *args) { @@ -94,16 +101,21 @@ static void local_emit(struct dasm_state *dasm, int32_t *args) #define LOCALREF_emit local_emit #define LOCALREFREF_emit local_emit #define LOCALINC_emit local_emit +#define LOCALINC2_emit local_emit #define LOCALDEC_emit local_emit +#define LOCALDEC2_emit local_emit #define LOCALDELETE_emit local_emit #define LOCALASSIGN2_emit local_emit #define S_LOCALASSIGN_emit local_emit -static void LOCALASSIGN_emit(struct dasm_state *dasm, int32_t *args) +static void localassign_emit(struct dasm_state *dasm, int32_t *args) { print_local(dasm, args[0]); fprintf(dasm->out, " %d", args[1]); } +#define LOCALASSIGN_emit localassign_emit +#define LOCALPLUSA_emit localassign_emit +#define LOCALMINUSA_emit localassign_emit static void F_LOCALASSIGN_emit(struct dasm_state *dasm, int32_t *args) { @@ -112,6 +124,19 @@ static void F_LOCALASSIGN_emit(struct dasm_state *dasm, int32_t *args) fprintf(dasm->out, " %f", v.f); } +static void STRING_LOCALASSIGN_emit(struct dasm_state *dasm, int32_t *args) +{ + print_local(dasm, args[0]); + fprintf(dasm->out, " 0x%x ; ", args[1]); + dasm_print_string(dasm, dasm->ain->strings[args[1]]->text); + /* + char *u = sjis2utf(dasm->ain->strings[args[1]]->text, 0); + print_local(dasm, args[0]); + fprintf(dasm->out, " 0x%x ; \"%s\"", args[1], u); + free(u); + */ +} + static void LOCALCREATE_emit(struct dasm_state *dasm, int32_t *args) { print_local(dasm, args[0]); @@ -224,11 +249,16 @@ struct macrodef macrodefs[] = { DEFMACRO(LOCALREF, PUSHLOCALPAGE, PUSH, REF), DEFMACRO(LOCALREFREF, PUSHLOCALPAGE, PUSH, REFREF), DEFMACRO(LOCALINC, PUSHLOCALPAGE, PUSH, INC), + DEFMACRO(LOCALINC2, PUSHLOCALPAGE, PUSH, DUP2, REF, DUP_X2, POP, INC, POP), DEFMACRO(LOCALDEC, PUSHLOCALPAGE, PUSH, DEC), + DEFMACRO(LOCALDEC2, PUSHLOCALPAGE, PUSH, DUP2, REF, DUP_X2, POP, DEC, POP), + DEFMACRO(LOCALPLUSA, PUSHLOCALPAGE, PUSH, PUSH, PLUSA, POP), + DEFMACRO(LOCALMINUSA, PUSHLOCALPAGE, PUSH, PUSH, MINUSA, POP), DEFMACRO(LOCALASSIGN, PUSHLOCALPAGE, PUSH, PUSH, ASSIGN, POP), DEFMACRO(LOCALASSIGN2, PUSHLOCALPAGE, SWAP, PUSH, SWAP, ASSIGN), DEFMACRO(F_LOCALASSIGN, PUSHLOCALPAGE, PUSH, F_PUSH, F_ASSIGN, POP), DEFMACRO(S_LOCALASSIGN, PUSHLOCALPAGE, PUSH, REF, DELETE, PUSHLOCALPAGE, SWAP, PUSH, SWAP, ASSIGN), + DEFMACRO(STRING_LOCALASSIGN, PUSHLOCALPAGE, PUSH, REF, S_PUSH, S_ASSIGN, DELETE), DEFMACRO(LOCALCREATE, PUSHLOCALPAGE, PUSH, DUP2, REF, DELETE, DUP2, NEW, ASSIGN, POP, POP, POP), DEFMACRO(LOCALDELETE, PUSHLOCALPAGE, PUSH, DUP2, REF, DELETE, PUSH, ASSIGN, POP), DEFMACRO(GLOBALREF, PUSHGLOBALPAGE, PUSH, REF), diff --git a/src/tools/ainedit/ainedit.h b/src/tools/ainedit/ainedit.h index 08cf371..4bd05dd 100644 --- a/src/tools/ainedit/ainedit.h +++ b/src/tools/ainedit/ainedit.h @@ -39,11 +39,16 @@ enum asm_pseudo_opcode { PO_LOCALREFREF, PO_GLOBALREFREF, PO_LOCALINC, + PO_LOCALINC2, PO_LOCALDEC, + PO_LOCALDEC2, + PO_LOCALPLUSA, + PO_LOCALMINUSA, PO_LOCALASSIGN, PO_LOCALASSIGN2, PO_F_LOCALASSIGN, PO_S_LOCALASSIGN, + PO_STRING_LOCALASSIGN, PO_LOCALDELETE, PO_LOCALCREATE, PO_GLOBALINC, diff --git a/src/tools/ainedit/asm.c b/src/tools/ainedit/asm.c index 342ce6b..922f3bc 100644 --- a/src/tools/ainedit/asm.c +++ b/src/tools/ainedit/asm.c @@ -27,7 +27,7 @@ #include "system4/string.h" #include "asm_parser.tab.h" -extern FILE *yyin; +extern FILE *asm_in; KHASH_MAP_INIT_STR(string_ht, size_t); @@ -64,11 +64,16 @@ const struct instruction asm_pseudo_ops[NR_PSEUDO_OPS - PSEUDO_OP_OFFSET] = { MACRO(PO_LOCALREF, ".LOCALREF", 1, 10), MACRO(PO_LOCALREFREF, ".LOCALREFREF", 1, 10), MACRO(PO_LOCALINC, ".LOCALINC", 1, 10), + MACRO(PO_LOCALINC2, ".LOCALINC2", 1, 20), MACRO(PO_LOCALDEC, ".LOCALDEC", 1, 10), + MACRO(PO_LOCALDEC2, ".LOCALDEC2", 1, 20), + MACRO(PO_LOCALPLUSA, ".LOCALPLUSA", 2, 18), + MACRO(PO_LOCALMINUSA, ".LOCALMINUSA", 2, 18), MACRO(PO_LOCALASSIGN, ".LOCALASSIGN", 2, 18), MACRO(PO_LOCALASSIGN2, ".LOCALASSIGN2", 1, 14), MACRO(PO_F_LOCALASSIGN, ".F_LOCALASSIGN", 2, 18), MACRO(PO_S_LOCALASSIGN, ".S_LOCALASSIGN", 1, 26), + MACRO(PO_STRING_LOCALASSIGN, ".STRING_LOCALASSIGN", 2, 20), MACRO(PO_LOCALDELETE, ".LOCALDELETE", 1, 24), MACRO(PO_LOCALCREATE, ".LOCALCREATE", 2, 34), MACRO(PO_GLOBALREF, ".GLOBALREF", 1, 10), @@ -607,6 +612,18 @@ void handle_pseudo_op(struct asm_state *state, struct parse_instruction *instr) asm_write_opcode(state, INC); break; } + case PO_LOCALINC2: { + 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, DUP_X2); + asm_write_opcode(state, POP); + asm_write_opcode(state, INC); + asm_write_opcode(state, POP); + break; + } case PO_LOCALDEC: { asm_write_opcode(state, PUSHLOCALPAGE); asm_write_opcode(state, PUSH); @@ -614,6 +631,38 @@ void handle_pseudo_op(struct asm_state *state, struct parse_instruction *instr) asm_write_opcode(state, DEC); break; } + case PO_LOCALDEC2: { + 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, DUP_X2); + asm_write_opcode(state, POP); + asm_write_opcode(state, DEC); + asm_write_opcode(state, POP); + break; + } + case PO_LOCALPLUSA: { + 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, PLUSA); + asm_write_opcode(state, POP); + break; + } + case PO_LOCALMINUSA: { + 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, MINUSA); + asm_write_opcode(state, POP); + break; + } case PO_LOCALASSIGN: { asm_write_opcode(state, PUSHLOCALPAGE); asm_write_opcode(state, PUSH); @@ -657,6 +706,17 @@ void handle_pseudo_op(struct asm_state *state, struct parse_instruction *instr) asm_write_opcode(state, ASSIGN); break; } + case PO_STRING_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, REF); + asm_write_opcode(state, S_PUSH); + asm_write_argument(state, asm_resolve_arg(state, PUSH, T_INT, kv_A(*instr->args, 1)->text)); + asm_write_opcode(state, S_ASSIGN); + asm_write_opcode(state, DELETE); + break; + } case PO_LOCALDELETE: { asm_write_opcode(state, PUSHLOCALPAGE); asm_write_opcode(state, PUSH); @@ -852,15 +912,15 @@ void asm_assemble_jam(const char *filename, struct ain *ain, uint32_t flags) if (filename) { if (!strcmp(filename, "-")) - yyin = stdin; + asm_in = stdin; else - yyin = fopen(filename, "r"); - if (!yyin) + asm_in = fopen(filename, "r"); + if (!asm_in) ERROR("Opening input file '%s': %s", filename, strerror(errno)); } label_table = kh_init(label_table); NOTICE("Parsing..."); - yyparse(); + asm_parse(); NOTICE("Encoding..."); for (size_t i = 0; i < kv_size(*parsed_code); i++) { diff --git a/src/tools/ainedit/asm_lexer.l b/src/tools/ainedit/asm_lexer.l index a22ca41..1267a51 100644 --- a/src/tools/ainedit/asm_lexer.l +++ b/src/tools/ainedit/asm_lexer.l @@ -23,17 +23,18 @@ #include "system4.h" #include "system4/string.h" -#define SAVE_TOKEN yylval.string = makes_string(yytext, yyleng) +#define SAVE_TOKEN asm_lval.string = makes_string(asm_text, asm_leng) char string_buf[65536]; char *string_buf_ptr; unsigned long asm_line = 1; -extern void yyerror(const char *s); +extern void asm_error(const char *s); %} %option noyywrap +%option prefix="asm_" %x str @@ -44,8 +45,8 @@ id_char [^ \t\r\n:;\"] [ \t] ; ;[^\n]*\n asm_line++; return NEWLINE; \n asm_line++; return NEWLINE; -[a-zA-Z0-9_-]+: yylval.string = make_string(yytext, yyleng-1); return LABEL; -({id_char}|:)*{id_char}+ yylval.string = make_string(yytext, yyleng); return IDENTIFIER; +[a-zA-Z0-9_-]+: asm_lval.string = make_string(asm_text, asm_leng-1); return LABEL; +({id_char}|:)*{id_char}+ asm_lval.string = make_string(asm_text, asm_leng); return IDENTIFIER; \" string_buf_ptr = string_buf; BEGIN(str); @@ -54,11 +55,11 @@ id_char [^ \t\r\n:;\"] \" { BEGIN(INITIAL); *string_buf_ptr = '\0'; - yylval.string = make_string(string_buf, strlen(string_buf)); + asm_lval.string = make_string(string_buf, strlen(string_buf)); return IDENTIFIER; } - \n yyerror("Unterminated string literal"); + \n asm_error("Unterminated string literal"); \\n *string_buf_ptr++ = '\n'; \\t *string_buf_ptr++ = '\t'; @@ -66,10 +67,10 @@ id_char [^ \t\r\n:;\"] \\b *string_buf_ptr++ = '\b'; \\f *string_buf_ptr++ = '\f'; - \\(.|\n) *string_buf_ptr++ = yytext[1]; + \\(.|\n) *string_buf_ptr++ = asm_text[1]; [^\\\n\"]+ { - char *yptr = yytext; + char *yptr = asm_text; while (*yptr) *string_buf_ptr++ = *yptr++; } diff --git a/src/tools/ainedit/asm_parser.y b/src/tools/ainedit/asm_parser.y index 43bb94a..ae11f81 100644 --- a/src/tools/ainedit/asm_parser.y +++ b/src/tools/ainedit/asm_parser.y @@ -1,3 +1,5 @@ +%define api.prefix {asm_} + %union { int token; struct string *string; @@ -36,13 +38,13 @@ #include "system4/instructions.h" #include "system4/string.h" -extern int yylex(); +extern int asm_lex(); extern unsigned long asm_line; #define PARSE_ERROR(fmt, ...) \ sys_error("ERROR: At line %d: " fmt "\n", asm_line-1, ##__VA_ARGS__) -void yyerror(const char *s) +void asm_error(const char *s) { sys_error("ERROR: At line %d: %s\n", asm_line, s); }