From d074e54ffee2d61b8bedc1d9be046a26fc6c9d0b Mon Sep 17 00:00:00 2001 From: org Date: Sat, 9 Sep 2023 13:26:27 +0300 Subject: [PATCH] addressing mode fixes --- Tools/Breakasm/asm.cpp | 2 +- Tools/Breakasm/asmexpr.cpp | 53 +++++--- Tools/Breakasm/asmexpr.h | 3 +- Tools/Breakasm/asmops.cpp | 248 +++++++++++++++++++++++++++++-------- Tools/Breakasm/main.cpp | 2 +- 5 files changed, 232 insertions(+), 76 deletions(-) diff --git a/Tools/Breakasm/asm.cpp b/Tools/Breakasm/asm.cpp index f6575b3..3f98cf7 100644 --- a/Tools/Breakasm/asm.cpp +++ b/Tools/Breakasm/asm.cpp @@ -124,7 +124,7 @@ static void do_expr_labels() for (auto it = labels.begin(); it != labels.end(); ++it) { label_s* label = *it; if (label->composite) { - label->orig = eval_expr(label->name, false); + label->orig = eval_expr(label->name, false, false); } } } diff --git a/Tools/Breakasm/asmexpr.cpp b/Tools/Breakasm/asmexpr.cpp index 53f0ba9..ad1b9a8 100644 --- a/Tools/Breakasm/asmexpr.cpp +++ b/Tools/Breakasm/asmexpr.cpp @@ -26,7 +26,7 @@ static token_t* create_op_token(OPS optype) return token; } -static token_t* next_token(char** pp) +static token_t* next_token(char** pp, bool quiet) { token_t* token = nullptr; char buf[0x100]{}, *ptr; @@ -122,7 +122,7 @@ static token_t* next_token(char** pp) } } *ptr++ = 0; - printf("string: %s\n", buf); + //printf("string: %s\n", buf); token = new token_t; token->type = TOKEN_STRING; token->op = OPS::NOP; @@ -251,20 +251,22 @@ static token_t* next_token(char** pp) } } - printf("ERROR(%s,%i): unknown character in string: %c\n", get_source_name().c_str(), get_linenum(), ch); - errors++; + if (!quiet) { + printf("ERROR(%s,%i): unknown character in string: %c\n", get_source_name().c_str(), get_linenum(), ch); + errors++; + } break; } return token; } -static void tokenize(char* text, std::list& tokens) +static void tokenize(char* text, std::list& tokens, bool quiet) { token_t* next = nullptr; char* pp = text; do { - next = next_token(&pp); + next = next_token(&pp, quiet); if (next != nullptr) tokens.push_back(next); } while (next != nullptr); @@ -357,7 +359,7 @@ static node_t* addnode(std::list& tree, token_t* token, int depth) } // executing the tree (semantic analysis) -static node_t * evaluate (std::list& tree, node_t * expr, long *lvalue) +static node_t * evaluate (std::list& tree, node_t * expr, long *lvalue, bool quiet) { node_t * curr; long rvalue = 0, mvalue; @@ -377,8 +379,10 @@ static node_t * evaluate (std::list& tree, node_t * expr, long *lvalue) token = curr->token; if ( token->type == TOKEN_OP && isunary(token->op) ) { if (curr->rvalue == NULL) { - printf("Missing identifier\n"); - errors++; + if (!quiet) { + printf("Missing identifier\n"); + errors++; + } } else { curr = curr->rvalue; @@ -397,7 +401,7 @@ static node_t * evaluate (std::list& tree, node_t * expr, long *lvalue) if ( curr->depth > expr->depth ) { // nested expression if (debug) printf ( "SUBEVAL " ); - curr = evaluate (tree, curr, &mvalue); + curr = evaluate (tree, curr, &mvalue, quiet); //printf ( "SUB LVALUE : %i\n", mvalue.num.value ); } else if ( token->type == TOKEN_IDENT) { @@ -405,7 +409,7 @@ static node_t * evaluate (std::list& tree, node_t * expr, long *lvalue) define_s* def = define_lookup(token->string); if (def) { - mvalue = eval_expr(def->replace, debug); + mvalue = eval_expr(def->replace, debug, quiet); } else { label_s* label = label_lookup(token->string); @@ -413,7 +417,10 @@ static node_t * evaluate (std::list& tree, node_t * expr, long *lvalue) mvalue = label->orig; } else { - printf("Undefined identifier: %s", token->string); + if (!quiet) { + printf("Undefined identifier: %s", token->string); + errors++; + } } } if (debug) printf ( "SYMBOL: %s", token->string ); @@ -461,8 +468,10 @@ static node_t * evaluate (std::list& tree, node_t * expr, long *lvalue) else rvalue = mvalue; } else { - printf ("Identifier required\n"); - errors++; + if (!quiet) { + printf("Identifier required\n"); + errors++; + } } // optional binary operation @@ -485,7 +494,7 @@ static node_t * evaluate (std::list& tree, node_t * expr, long *lvalue) } // grow a syntax tree -static void grow (tree_t& tree, node_t **expr, token_t * token) +static void grow (tree_t& tree, node_t **expr, token_t * token, bool quiet) { node_t *node = addnode (tree.nodes, token, tree.depth ); @@ -508,7 +517,11 @@ static void grow (tree_t& tree, node_t **expr, token_t * token) else if (token->op == OPS::RPAREN) { tree.prio--; if (tree.depth > 0) tree.depth--; - else printf("Unmatched parenthesis"); + else { + if (!quiet) { + printf("Unmatched parenthesis"); + } + } return; } else if (opprio[(int)token->op] > tree.prio_stack[tree.prio]) { // priority increase. for binary operations, the priority of the previous token is also increased. @@ -545,7 +558,7 @@ static void dump_tree(tree_t& tree, node_t* root) printf("\n"); } -long eval_expr(char* text, bool debug) +long eval_expr(char* text, bool debug, bool quiet) { char expr[0x100]; sprintf(expr, "res=%s", text); @@ -553,7 +566,7 @@ long eval_expr(char* text, bool debug) // Obtain token stream std::list tokens; - tokenize(expr, tokens); + tokenize(expr, tokens, quiet); if (debug) dump_tokens(tokens); @@ -562,7 +575,7 @@ long eval_expr(char* text, bool debug) tree_t tree{}; node_t* root = nullptr; for (auto it = tokens.begin(); it != tokens.end(); ++it) { - grow(tree, &root, *it); + grow(tree, &root, *it, quiet); } if (debug) dump_tree(tree, root); @@ -570,7 +583,7 @@ long eval_expr(char* text, bool debug) // Execute the tree long result = 0; - evaluate(tree.nodes, root->rvalue->rvalue, &result); + evaluate(tree.nodes, root->rvalue->rvalue, &result, quiet); if (debug) printf("Source expression: %s, result: %d (0x%08X)\n", text, result, result); diff --git a/Tools/Breakasm/asmexpr.h b/Tools/Breakasm/asmexpr.h index 3fae1b5..718416c 100644 --- a/Tools/Breakasm/asmexpr.h +++ b/Tools/Breakasm/asmexpr.h @@ -62,5 +62,6 @@ struct tree_t /// /// The text of the expression, for example: MyData + 32 * entry_size + 12. Other labels and defines can be identifiers /// Output debugging states during operation +/// Quiet mode, no error generation. Just trying to resolve the expression. /// -long eval_expr(char* text, bool debug); +long eval_expr(char* text, bool debug, bool quiet); diff --git a/Tools/Breakasm/asmops.cpp b/Tools/Breakasm/asmops.cpp index 7481609..ae15ea8 100644 --- a/Tools/Breakasm/asmops.cpp +++ b/Tools/Breakasm/asmops.cpp @@ -28,6 +28,8 @@ */ +// TODO: Simplify addressing modes. + // Typical errors #include "pch.h" @@ -110,11 +112,27 @@ void opLDST (char *cmd, char *ops) } } else if ( type[0] == EVAL_LABEL ) { // Absolute - if ( !_stricmp (cmd, "LDA") ) emit (0xAD); - if ( !_stricmp (cmd, "STA") ) emit (0x8D); - label = add_label (val[0].label->name, UNDEF); - add_patch (label, org, 0 ); - emit (0); emit (0); + long addr = eval_expr(val[0].label->name, false, true); + if (addr != 0) { + if (addr >= 0x100) { + if (!_stricmp(cmd, "LDA")) emit(0xAD); + if (!_stricmp(cmd, "STA")) emit(0x8D); + emit(addr & 0xff); + emit((addr >> 8) & 0xff); + } + else { // Zero Page + if (!_stricmp(cmd, "LDA")) emit(0xA5); + if (!_stricmp(cmd, "STA")) emit(0x85); + emit(addr & 0xff); + } + } + else { + if (!_stricmp(cmd, "LDA")) emit(0xAD); + if (!_stricmp(cmd, "STA")) emit(0x8D); + label = add_label(val[0].label->name, UNDEF); + add_patch(label, org, 0); + emit(0); emit(0); + } } else WrongParameters (cmd, ops); } @@ -150,17 +168,18 @@ void opLDST (char *cmd, char *ops) } else WrongParameters (cmd, ops); } - else if ( type[0] == EVAL_ADDRESS ) { - if ( val[0].address < 0x100 ) { // Zero page, X + else if ( type[0] == EVAL_ADDRESS || type[0] == EVAL_NUMBER ) { + long addr = type[0] == EVAL_ADDRESS ? val[0].address : val[0].number; + if (addr < 0x100 ) { // Zero page, X if (val[1].label->orig == KEYWORD && !_stricmp(val[1].label->name, "X")) { if ( !_stricmp ( cmd, "LDA" ) ) emit ( 0xB5 ); if ( !_stricmp ( cmd, "STA" ) ) emit ( 0x95 ); - emit ( val[0].address & 0xff ); + emit (addr & 0xff ); } else if (val[1].label->orig == KEYWORD && !_stricmp(val[1].label->name, "Y")) { // Indirect, Y if ( !_stricmp ( cmd, "LDA" ) ) emit ( 0xB1 ); if ( !_stricmp ( cmd, "STA" ) ) emit ( 0x91 ); - emit ( val[0].address & 0xff ); + emit (addr & 0xff ); } else WrongParameters (cmd, ops); } @@ -168,18 +187,19 @@ void opLDST (char *cmd, char *ops) if (val[1].label->orig == KEYWORD && !_stricmp(val[1].label->name, "X")) { if ( !_stricmp ( cmd, "LDA" ) ) emit ( 0xBD ); if ( !_stricmp ( cmd, "STA" ) ) emit ( 0x9D ); - emit ( val[0].address & 0xff ); - emit ( (val[0].address >> 8) & 0xff ); + emit (addr & 0xff ); + emit ( (addr >> 8) & 0xff ); } else if (val[1].label->orig == KEYWORD && !_stricmp(val[1].label->name, "Y")) { if ( !_stricmp ( cmd, "LDA" ) ) emit ( 0xB9 ); if ( !_stricmp ( cmd, "STA" ) ) emit ( 0x99 ); - emit ( val[0].address & 0xff ); - emit ( (val[0].address >> 8) & 0xff ); + emit (addr & 0xff ); + emit ( (addr >> 8) & 0xff ); } else WrongParameters (cmd, ops); } } + else WrongParameters(cmd, ops); } else NotEnoughParameters (cmd); } @@ -208,11 +228,27 @@ void opLDSTX (char *cmd, char *ops) } } else if ( type[0] == EVAL_LABEL ) { // Absolute by label - if ( !_stricmp ( cmd, "LDX" ) ) emit ( 0xAE ); - if ( !_stricmp ( cmd, "STX" ) ) emit ( 0x8E ); - label = add_label (val[0].label->name, UNDEF); - add_patch (label, org, 0 ); - emit (0); emit (0); + long addr = eval_expr(val[0].label->name, false, true); + if (addr != 0) { + if (addr < 0x100) { // Zero page + if (!_stricmp(cmd, "LDX")) emit(0xA6); + if (!_stricmp(cmd, "STX")) emit(0x86); + emit(addr & 0xff); + } + else { // Absolute + if (!_stricmp(cmd, "LDX")) emit(0xAE); + if (!_stricmp(cmd, "STX")) emit(0x8E); + emit(addr & 0xff); + emit((addr >> 8) & 0xff); + } + } + else { + if (!_stricmp(cmd, "LDX")) emit(0xAE); + if (!_stricmp(cmd, "STX")) emit(0x8E); + label = add_label(val[0].label->name, UNDEF); + add_patch(label, org, 0); + emit(0); emit(0); + } } else if ( type[0] == EVAL_NUMBER ) { // # if ( !_stricmp ( cmd, "LDX" ) ) { @@ -291,11 +327,27 @@ void opLDSTY (char *cmd, char *ops) } } else if ( type[0] == EVAL_LABEL ) { // Absolute by label - if ( !_stricmp ( cmd, "LDY" ) ) emit ( 0xAC ); - if ( !_stricmp ( cmd, "STY" ) ) emit ( 0x8C ); - label = add_label (val[0].label->name, UNDEF); - add_patch (label, org, 0 ); - emit (0); emit (0); + long addr = eval_expr(val[0].label->name, false, true); + if (addr != 0) { + if (addr < 0x100) { // Zero page + if (!_stricmp(cmd, "LDY")) emit(0xA4); + if (!_stricmp(cmd, "STY")) emit(0x84); + emit(addr & 0xff); + } + else { // Absolute + if (!_stricmp(cmd, "LDY")) emit(0xAC); + if (!_stricmp(cmd, "STY")) emit(0x8C); + emit(addr & 0xff); + emit((addr >> 8) & 0xff); + } + } + else { + if (!_stricmp(cmd, "LDY")) emit(0xAC); + if (!_stricmp(cmd, "STY")) emit(0x8C); + label = add_label(val[0].label->name, UNDEF); + add_patch(label, org, 0); + emit(0); emit(0); + } } else if ( type[0] == EVAL_NUMBER ) { // # if ( !_stricmp ( cmd, "LDY" ) ) { @@ -474,15 +526,39 @@ void opALU1 (char *cmd, char *ops) emit ( val[0].number & 0xff ); } else if ( type[0] == EVAL_LABEL ) { // Absolute by label - if ( !_stricmp ( cmd, "ORA" ) ) emit ( 0x0D ); - if ( !_stricmp ( cmd, "AND" ) ) emit ( 0x2D ); - if ( !_stricmp ( cmd, "EOR" ) ) emit ( 0x4D ); - if ( !_stricmp ( cmd, "ADC" ) ) emit ( 0x6D ); - if ( !_stricmp ( cmd, "CMP" ) ) emit ( 0xCD ); - if ( !_stricmp ( cmd, "SBC" ) ) emit ( 0xED ); - label = add_label (val[0].label->name, UNDEF); - add_patch (label, org, 0 ); - emit (0); emit (0); + long addr = eval_expr(val[0].label->name, false, true); + if (addr != 0) { + if (addr < 0x100) { // Zero page + if (!_stricmp(cmd, "ORA")) emit(0x05); + if (!_stricmp(cmd, "AND")) emit(0x25); + if (!_stricmp(cmd, "EOR")) emit(0x45); + if (!_stricmp(cmd, "ADC")) emit(0x65); + if (!_stricmp(cmd, "CMP")) emit(0xC5); + if (!_stricmp(cmd, "SBC")) emit(0xE5); + emit(addr & 0xff); + } + else { // Absolute + if (!_stricmp(cmd, "ORA")) emit(0x0D); + if (!_stricmp(cmd, "AND")) emit(0x2D); + if (!_stricmp(cmd, "EOR")) emit(0x4D); + if (!_stricmp(cmd, "ADC")) emit(0x6D); + if (!_stricmp(cmd, "CMP")) emit(0xCD); + if (!_stricmp(cmd, "SBC")) emit(0xED); + emit(addr & 0xff); + emit((addr >> 8) & 0xff); + } + } + else { + if (!_stricmp(cmd, "ORA")) emit(0x0D); + if (!_stricmp(cmd, "AND")) emit(0x2D); + if (!_stricmp(cmd, "EOR")) emit(0x4D); + if (!_stricmp(cmd, "ADC")) emit(0x6D); + if (!_stricmp(cmd, "CMP")) emit(0xCD); + if (!_stricmp(cmd, "SBC")) emit(0xED); + label = add_label(val[0].label->name, UNDEF); + add_patch(label, org, 0); + emit(0); emit(0); + } } else WrongParameters (cmd, ops); } @@ -622,13 +698,33 @@ void opSHIFT (char *cmd, char *ops) if ( !_stricmp ( cmd, "ROR" ) ) emit ( 0x6A ); } else { // Absolute by label - if ( !_stricmp ( cmd, "ASL" ) ) emit ( 0x0E ); - if ( !_stricmp ( cmd, "ROL" ) ) emit ( 0x2E ); - if ( !_stricmp ( cmd, "LSR" ) ) emit ( 0x4E ); - if ( !_stricmp ( cmd, "ROR" ) ) emit ( 0x6E ); - label = add_label (val[0].label->name, UNDEF); - add_patch (label, org, 0 ); - emit (0); emit (0); + long addr = eval_expr(val[0].label->name, false, true); + if (addr != 0) { + if (addr < 0x100) { // Zero page + if (!_stricmp(cmd, "ASL")) emit(0x06); + if (!_stricmp(cmd, "ROL")) emit(0x26); + if (!_stricmp(cmd, "LSR")) emit(0x46); + if (!_stricmp(cmd, "ROR")) emit(0x66); + emit(addr & 0xff); + } + else { // Absolute + if (!_stricmp(cmd, "ASL")) emit(0x0E); + if (!_stricmp(cmd, "ROL")) emit(0x2E); + if (!_stricmp(cmd, "LSR")) emit(0x4E); + if (!_stricmp(cmd, "ROR")) emit(0x6E); + emit(addr & 0xff); + emit((addr >> 8) & 0xff); + } + } + else { + if (!_stricmp(cmd, "ASL")) emit(0x0E); + if (!_stricmp(cmd, "ROL")) emit(0x2E); + if (!_stricmp(cmd, "LSR")) emit(0x4E); + if (!_stricmp(cmd, "ROR")) emit(0x6E); + label = add_label(val[0].label->name, UNDEF); + add_patch(label, org, 0); + emit(0); emit(0); + } } } else WrongParameters (cmd, ops); @@ -701,10 +797,24 @@ void opBIT (char *cmd, char *ops) } } else if (type == EVAL_LABEL) { - emit (0x2C); - label = add_label (val.label->name, UNDEF); - add_patch (label, org, 0 ); - emit (0); emit (0); + long addr = eval_expr(val.label->name, false, true); + if (addr != 0) { + if (addr < 0x100) { // Zero page + emit(0x24); + emit(addr & 0xff); + } + else { // Absoulte + emit(0x2C); + emit(addr & 0xff); + emit((addr >> 8) & 0xff); + } + } + else { + emit(0x2C); + label = add_label(val.label->name, UNDEF); + add_patch(label, org, 0); + emit(0); emit(0); + } } else WrongParameters (cmd, ops); } @@ -736,11 +846,27 @@ void opINCDEC (char *cmd, char *ops) } } else if ( type[0] == EVAL_LABEL ) { // Absolute by label - if ( !_stricmp ( cmd, "INC" ) ) emit ( 0xEE ); - if ( !_stricmp ( cmd, "DEC" ) ) emit ( 0xCE ); - label = add_label (val[0].label->name, UNDEF); - add_patch (label, org, 0 ); - emit (0); emit (0); + long addr = eval_expr(val[0].label->name, false, true); + if (addr != 0) { + if (addr < 0x100) { // Zero page + if (!_stricmp(cmd, "INC")) emit(0xE6); + if (!_stricmp(cmd, "DEC")) emit(0xC6); + emit(addr & 0xff); + } + else { // Absolute + if (!_stricmp(cmd, "INC")) emit(0xEE); + if (!_stricmp(cmd, "DEC")) emit(0xCE); + emit(addr & 0xff); + emit((addr >> 8) & 0xff); + } + } + else { + if (!_stricmp(cmd, "INC")) emit(0xEE); + if (!_stricmp(cmd, "DEC")) emit(0xCE); + label = add_label(val[0].label->name, UNDEF); + add_patch(label, org, 0); + emit(0); emit(0); + } } else WrongParameters (cmd, ops); } @@ -813,11 +939,27 @@ void opCPXY (char *cmd, char *ops) } } else if (type == EVAL_LABEL) { - if ( !_stricmp ( cmd, "CPX" ) ) emit ( 0xEC ); - if ( !_stricmp ( cmd, "CPY" ) ) emit ( 0xCC ); - label = add_label (val.label->name, UNDEF); - add_patch (label, org, 0 ); - emit (0); emit (0); + long addr = eval_expr(val.label->name, false, true); + if (addr != 0) { + if (addr < 0x100) { // Zero page + if (!_stricmp(cmd, "CPX")) emit(0xE4); + if (!_stricmp(cmd, "CPY")) emit(0xC4); + emit(addr & 0xff); + } + else { // Absoulte + if (!_stricmp(cmd, "CPX")) emit(0xEC); + if (!_stricmp(cmd, "CPY")) emit(0xCC); + emit(addr & 0xff); + emit((addr >> 8) & 0xff); + } + } + else { + if (!_stricmp(cmd, "CPX")) emit(0xEC); + if (!_stricmp(cmd, "CPY")) emit(0xCC); + label = add_label(val.label->name, UNDEF); + add_patch(label, org, 0); + emit(0); emit(0); + } } else WrongParameters (cmd, ops); } diff --git a/Tools/Breakasm/main.cpp b/Tools/Breakasm/main.cpp index 0783685..71c4dab 100644 --- a/Tools/Breakasm/main.cpp +++ b/Tools/Breakasm/main.cpp @@ -17,7 +17,7 @@ void test_expr_eval() //const char* text = " $700"; add_define((char *)"SPR_TAB", (char*)"$700"); //add_label("ItemID", 5); - auto res = eval_expr((char*)text, true); + auto res = eval_expr((char*)text, true, false); } int main(int argc, char** argv)