diff --git a/.gitignore b/.gitignore index 17ca9e0..a3d5d9d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,14 @@ **/build +**/testdata1 +*.bin +*.BIN +*.a +*.so +Finder.Data +test.s +disk_commands.txt +.vscode/browse* +.vscode/book* + *.xcuserstate *.xcbkptlist diff --git a/asm.cpp b/asm.cpp index 47b652e..79347c9 100644 --- a/asm.cpp +++ b/asm.cpp @@ -13,523 +13,527 @@ CLASS::CLASS() { - clear(); + clear(); } CLASS::CLASS(std::string line) { - clear(); - set(line); + clear(); + set(line); } void CLASS::setError(uint32_t ecode) { - errorcode = ecode; + errorcode = ecode; } void CLASS::print(uint32_t lineno) { - uint32_t l, i, savpcol, pcol; - bool commentprinted = false; - static bool checked = false; - static bool nc1 = false; - bool nc = false; - uint8_t commentcol = tabs[2]; + uint32_t l, i, savpcol, pcol; + bool commentprinted = false; + static bool checked = false; + static bool nc1 = false; + bool nc = false; + uint8_t commentcol = tabs[2]; - uint32_t b = 4; // how many bytes show on the first line + uint32_t b = 4; // how many bytes show on the first line - if (datafillct > 0) - { - l = datafillct; - } - else - { - l = outbytect; - } - if (l > b) - { - l = b; - } - if (errorcode > 0) - { - if (merlinerrors) - { - //printf("errorcode=%d\n",errorcode); - printf("\n%s in line: %d", errStrings[errorcode].c_str(), lineno + 1); - if (errorText != "") - { - printf(" (%s)", errorText.c_str()); - } - printf("\n"); - } - flags &= (~FLAG_NOLINEPRINT); - } + if (datafillct > 0) + { + l = datafillct; + } + else + { + l = outbytect; + } + if (l > b) + { + l = b; + } + if (errorcode > 0) + { + if (merlinerrors) + { + //printf("errorcode=%d\n",errorcode); + printf("\n%s in line: %d", errStrings[errorcode].c_str(), lineno + 1); + if (errorText != "") + { + printf(" (%s)", errorText.c_str()); + } + printf("\n"); + } + flags &= (~FLAG_NOLINEPRINT); + } - if (flags & FLAG_NOLINEPRINT) - { - return; - } - if (!checked) - { - nc1 = getBool("option.nocolor", false); - checked = true; - } - else - { - nc = nc1; - } + if (flags & FLAG_NOLINEPRINT) + { + return; + } + if (!checked) + { + nc1 = getBool("option.nocolor", false); + checked = true; + } + else + { + nc = nc1; + } - //if ((!isatty(STDOUT_FILENO)) || (merlinerrors)) - if ((!isatty(STDOUT_FILENO)) || (0)) - { - nc = true; - } + //if ((!isatty(STDOUT_FILENO)) || (merlinerrors)) + if ((!isatty(STDOUT_FILENO)) || (0)) + { + nc = true; + } - if (!nc) - { - if (errorcode > 0) - { - if (errorcode >= errFatal) - { - SetColor(CL_WHITE | CL_BOLD | BG_RED); - } - else - { - SetColor(CL_YELLOW | CL_BOLD | BG_NORMAL); - } - } - else - { - SetColor(CL_WHITE | CL_BOLD | BG_NORMAL); - } - } - bool empty = false; - if ((printlable == "") && (opcode == "") && (printoperand == "")) - { - empty = true; - } + if (!nc) + { + if (errorcode > 0) + { + if (errorcode >= errFatal) + { + SetColor(CL_WHITE | CL_BOLD | BG_RED); + } + else + { + SetColor(CL_YELLOW | CL_BOLD | BG_NORMAL); + } + } + else + { + SetColor(CL_WHITE | CL_BOLD | BG_NORMAL); + } + } + bool empty = false; + if ((printlable == "") && (opcode == "") && (printoperand == "")) + { + empty = true; + } - pcol = 0; + pcol = 0; - bool saddr = flags & FLAG_FORCEADDRPRINT; - saddr = (outbytect > 0) ? true : saddr; - saddr = (printlable != "") ? true : saddr; + bool saddr = flags & FLAG_FORCEADDRPRINT; + saddr = (outbytect > 0) ? true : saddr; + saddr = (printlable != "") ? true : saddr; - if (saddr) - { - pcol += printf("%02X/%04X:", (startpc >> 16), startpc & 0xFFFF); - } - else - { - pcol += printf(" "); - } + if (saddr) + { + pcol += printf("%02X/%04X:", (startpc >> 16), startpc & 0xFFFF); + } + else + { + pcol += printf(" "); + } - for (i = 0; i < l; i++) - { - uint8_t a = datafillbyte; - if (datafillct == 0) - { - a = outbytes[i]; - } + for (i = 0; i < l; i++) + { + uint8_t a = datafillbyte; + if (datafillct == 0) + { + a = outbytes[i]; + } - pcol += printf("%02X ", a); - } - for (i = l; i < b; i++) - { - pcol += printf(" "); - } + pcol += printf("%02X ", a); + } + for (i = l; i < b; i++) + { + pcol += printf(" "); + } - pcol += printf("%6d ", lineno + 1); + pcol += printf("%6d ", lineno + 1); - if (showmx) - { - if ((outbytect + datafillct) > 0) - { - pcol += printf("%%%c%c ", linemx & 02 ? '1' : '0', linemx & 01 ? '1' : '0'); - } - else - { - pcol += printf(" "); - } - } + if (showmx) + { + if ((outbytect + datafillct) > 0) + { + pcol += printf("%%%c%c ", linemx & 02 ? '1' : '0', linemx & 01 ? '1' : '0'); + } + else + { + pcol += printf(" "); + } + } - if (isDebug() > 1) - { - pcol += printf("%02X ", addressmode & 0xFF); - } + if (isDebug() > 1) + { + pcol += printf("%02X ", addressmode & 0xFF); + } - savpcol = pcol; // this is how many bytes are in the side margin - pcol = 0; // reset pcol here because this is where source code starts + savpcol = pcol; // this is how many bytes are in the side margin + pcol = 0; // reset pcol here because this is where source code starts - if (empty) - { - if (comment.length() > 0) - { - if (comment[0] == ';') - { - while (pcol < commentcol) - { - pcol += printf(" "); - } - } - //else - { - int comct = 0; - for (uint32_t cc = 0; cc < comment.length(); cc++) - { - pcol += printf("%c", comment[cc]); - comct++; - if ((comment[cc] <= ' ') && (pcol >= (commentcol + savpcol + 20))) - { - printf("\n"); - pcol = 0; - while (pcol < (commentcol + savpcol)) - { - pcol += printf(" "); - } - } - } - //pcol += printf("%s", comment.c_str()); + if (empty) + { + if (comment.length() > 0) + { + if (comment[0] == ';') + { + while (pcol < commentcol) + { + pcol += printf(" "); + } + } + //else + { + int comct = 0; + for (uint32_t cc = 0; cc < comment.length(); cc++) + { + pcol += printf("%c", comment[cc]); + comct++; + if ((comment[cc] <= ' ') && (pcol >= (commentcol + savpcol + 20))) + { + printf("\n"); + pcol = 0; + while (pcol < (commentcol + savpcol)) + { + pcol += printf(" "); + } + } + } + //pcol += printf("%s", comment.c_str()); - } - commentprinted = true; - } - } - else - { - pcol += printf("%s ", printlable.c_str()); - while (pcol < tabs[0]) - { - pcol += printf(" "); - } - pcol += printf("%s ", opcode.c_str()); - while (pcol < tabs[1]) - { - pcol += printf(" "); - } - if (isDebug() > 1) - { - pcol += printf("%s ", operand.c_str()); - } - else - { - if (printoperand.length() > 0) - { - pcol += printf("%s ", printoperand.c_str()); + } + commentprinted = true; + } + } + else + { + pcol += printf("%s ", printlable.c_str()); + while (pcol < tabs[0]) + { + pcol += printf(" "); + } + pcol += printf("%s ", opcode.c_str()); + while (pcol < tabs[1]) + { + pcol += printf(" "); + } + if (isDebug() > 1) + { + pcol += printf("%s ", operand.c_str()); + } + else + { + if (printoperand.length() > 0) + { + pcol += printf("%s ", printoperand.c_str()); + //pcol += printf("%s ", orig_operand.c_str()); - } - else - { - pcol += printf("%s ", operand.c_str()); - } - } - //pcol += printf("%-12s %-8s %-10s ", printlable.c_str(), opcode.c_str(), operand.c_str()); - } - if ((errorcode > 0) && (!merlinerrors)) - { - while (pcol < commentcol) - { - pcol += printf(" "); - } - pcol += printf(":[Error] %s", errStrings[errorcode].c_str()); - if (errorText.length() > 0) - { - pcol += printf(" (%s)", errorText.c_str()); - } - } - else if (!commentprinted) - { - while (pcol < commentcol) - { - pcol += printf(" "); - } - pcol += printf("%s", comment.c_str()); - } - //printf("\n"); + } + else + { + pcol += printf("%s ", printoperand.c_str()); + //pcol += printf("%s ", orig_operand.c_str()); + } + } + //pcol += printf("%-12s %-8s %-10s ", printlable.c_str(), opcode.c_str(), operand.c_str()); + } + if ((errorcode > 0) && (!merlinerrors)) + { + while (pcol < commentcol) + { + pcol += printf(" "); + } + pcol += printf(":[Error] %s", errStrings[errorcode].c_str()); + if (errorText.length() > 0) + { + pcol += printf(" (%s)", errorText.c_str()); + } + } + else if (!commentprinted) + { + while (pcol < commentcol) + { + pcol += printf(" "); + } + pcol += printf("%s", comment.c_str()); + } + //printf("\n"); - if ((!nc) && (errorcode > 0)) - { - SetColor(CL_NORMAL | BG_NORMAL); - } + if ((!nc) && (errorcode > 0)) + { + SetColor(CL_NORMAL | BG_NORMAL); + } - uint32_t obc = datafillct; - if (obc == 0) - { - obc = outbytect; - } + uint32_t obc = datafillct; + if (obc == 0) + { + obc = outbytect; + } - uint32_t ct = 1; - if ((obc > b) && ((truncdata & 0x01) == 0)) - { - ct = 0; - uint8_t db; - uint32_t t = b; - char *s = (char *)" "; + uint32_t ct = 1; + if ((obc > b) && ((truncdata & 0x01) == 0)) + { + ct = 0; + uint8_t db; + uint32_t t = b; + char *s = (char *)" "; - b = 8; + b = 8; - //printf("t=%d ct=%d\n",t,outbytect); - printf("\n"); - while (t < obc) - { - db = datafillbyte; - if (datafillct == 0) - { - db = outbytes[t]; - } - if (ct == 0) - { - printf("%s", s); - } + //printf("t=%d ct=%d\n",t,outbytect); + printf("\n"); + while (t < obc) + { + db = datafillbyte; + if (datafillct == 0) + { + db = outbytes[t]; + } + if (ct == 0) + { + printf("%s", s); + } - printf("%02X ", db); - t++; - ct++; - if (ct >= b) - { - printf("\n"); - ct = 0; - } - } - } - if (ct > 0) - { - printf("\n"); - } + printf("%02X ", db); + t++; + ct++; + if (ct >= b) + { + printf("\n"); + ct = 0; + } + } + } + if (ct > 0) + { + printf("\n"); + } } void CLASS::clear() { - wholetext = ""; - lable = ""; - printlable = ""; - opcode = ""; - opcodelower = ""; - operand = ""; - printoperand = ""; - comment = ""; - operand_expr = ""; - operand_expr2 = ""; - addrtext = ""; - merlinerrors = false; - linemx = 0; - bytect = 0; - opflags = 0; - pass0bytect = 0; - startpc = 0; - errorcode = 0; - errorText = ""; - outbytect = 0; - datafillct = 0; - datafillbyte = 0; - lineno = 0; - outbytes.clear(); - addressmode = 0; - expr_value = 0; - eval_result = 0; - flags = 0; - outbytes.clear(); + wholetext = ""; + lable = ""; + printlable = ""; + opcode = ""; + opcodelower = ""; + operand = ""; + printoperand = ""; + orig_operand=""; + comment = ""; + operand_expr = ""; + operand_expr2 = ""; + addrtext = ""; + merlinerrors = false; + linemx = 0; + bytect = 0; + opflags = 0; + pass0bytect = 0; + startpc = 0; + errorcode = 0; + errorText = ""; + outbytect = 0; + datafillct = 0; + datafillbyte = 0; + lineno = 0; + outbytes.clear(); + addressmode = 0; + expr_value = 0; + eval_result = 0; + flags = 0; + outbytes.clear(); } std::string operEx[] = { - "^(\\S*)(#?)([<>\\^|]?)([\"\'])(.*)(\\4)([\\S]*)", // catches the normal delims - "^(\\s*)([!-~])([!-~]*?)([^;]*)\\2(\\S*)", // catches the unusual delims - "^(\\s*)(\\S+)", // captures everything else - "" + "^(\\S*)(#?)([<>\\^|]?)([\"\'])(.*)(\\4)([\\S]*)", // catches the normal delims + "^(\\s*)([!-~])([!-~]*?)([^;]*)\\2(\\S*)", // catches the unusual delims + "^(\\s*)(\\S+)", // captures everything else + "" }; std::string commentEx = "^(\\s*)((;|\\/{2}))+(.*)"; void CLASS::set(std::string line) { - int state = 0; - int l = (int)line.length(); - int i = 0; - int x; - char c; - //char delim; - //bool isascii; - std::string opupper, s; - std::string restofline; - std::string tline = line; - clear(); + int state = 0; + int l = (int)line.length(); + int i = 0; + int x; + char c; + //char delim; + //bool isascii; + std::string opupper, s; + std::string restofline; + std::string tline = line; + clear(); - wholetext = line; - // isascii = false; - //delim = 0; - while (i < l) - { - c = tline[i++]; - switch (state) - { - case 7: - if (c >= ' ') - { - comment += c; - } - else - { - i = l; - } - break; - case 0: // start of line state - if ((c == ';') || (c == '*') || (c == '/')) - { - comment += c; - state = 7; - } - else if (c > ' ') - { - lable += c; - state = 1; - } - else - { - state = 2; - }; - break; - case 1: // read in entire lable until whitespace - if (c > ' ') - { - lable += c; - } - else - { - state = 2; - } - break; - case 2: // read whitespace between label and opcode - if (c == ';') - { - comment += c; - state = 7; - } - else if (((c == '*') || (c == '/')) && (lable.length() == 0)) - { - comment += c; - state = 7; - } - else if (c > ' ') - { - opcode += c; - state = 3; - } - break; - case 3: - { - if (c > ' ') - { - opcode += c; - } - else - { - i--; - state = 4; - } - } - break; - case 4: // read whitespace between opcode and operand - { - std::vector strs; - std::string s; + wholetext = line; + // isascii = false; + //delim = 0; + while (i < l) + { + c = tline[i++]; + switch (state) + { + case 7: + if (c >= ' ') + { + comment += c; + } + else + { + i = l; + } + break; + case 0: // start of line state + if ((c == ';') || (c == '*') || (c == '/')) + { + comment += c; + state = 7; + } + else if (c > ' ') + { + lable += c; + state = 1; + } + else + { + state = 2; + }; + break; + case 1: // read in entire lable until whitespace + if (c > ' ') + { + lable += c; + } + else + { + state = 2; + } + break; + case 2: // read whitespace between label and opcode + if (c == ';') + { + comment += c; + state = 7; + } + else if (((c == '*') || (c == '/')) && (lable.length() == 0)) + { + comment += c; + state = 7; + } + else if (c > ' ') + { + opcode += c; + state = 3; + } + break; + case 3: + { + if (c > ' ') + { + opcode += c; + } + else + { + i--; + state = 4; + } + } + break; + case 4: // read whitespace between opcode and operand + { + std::vector strs; + std::string s; - Poco::RegularExpression comEx(commentEx, 0, true); - restofline = Poco::trim(tline.substr(i, tline.length())) + " "; - //printf("ROL: |%s|\n",restofline.c_str()); + Poco::RegularExpression comEx(commentEx, 0, true); + restofline = Poco::trim(tline.substr(i, tline.length())) + " "; + //printf("ROL: |%s|\n",restofline.c_str()); - if (restofline == "") - { - i = l; - break; - } - strs.clear(); - x = 0; - try - { - x = comEx.split(restofline, strs, 0); - } - catch (Poco::Exception &e) - { - x = 0; - if (isDebug() > 3) - { - cout << e.displayText() << endl; - } - } - if (x > 0) - { - // if the comment detector above is true, then the rest of line is comment; - operand = ""; - comment = strs[0]; - //printf("comment=%s\n", comment.c_str()); - i = l; - break; - } + if (restofline == "") + { + i = l; + break; + } + strs.clear(); + x = 0; + try + { + x = comEx.split(restofline, strs, 0); + } + catch (Poco::Exception &e) + { + x = 0; + if (isDebug() > 3) + { + cout << e.displayText() << endl; + } + } + if (x > 0) + { + // if the comment detector above is true, then the rest of line is comment; + operand = ""; + comment = strs[0]; + //printf("comment=%s\n", comment.c_str()); + i = l; + break; + } - int ct = 0; - int x = 0; - bool match = false; - s = operEx[ct]; - while (s != "") - { - RegularExpression regex(s, 0, true); - strs.clear(); - x = 0; - try - { - x = regex.split(restofline, strs, 0); - } - catch (Poco::Exception &e) - { - x = 0; - if (isDebug() > 3) - { - cout << e.displayText() << endl; - } - } - if (x > 0) - { - //printf("%d regex %d match |%s|\n", ct, x, restofline.c_str()); - operand = strs[0]; - //printf("which=%d operand=|%s|\n",ct,operand.c_str()); - i = (int)operand.length(); - restofline = restofline.substr(i, restofline.length()); - comment = Poco::trim(restofline); - match = true; - break; - } - ct++; - s = operEx[ct]; - } - i = l; - if (!match) - { - // if you are here, there probably isn't an operand and/or comment after opcode - } - } - break; - } - } - printlable = lable; - x = (int)lable.length(); - if (x > 1) - { - // M32 syntax allows a colon after lable, and it is not part of the lable - if ((syntax & SYNTAX_MERLIN32) == SYNTAX_MERLIN32) - { - while ((x > 1) && (lable[x - 1] == ':')) - { - lable = lable.substr(0, x - 1); - x--; - } - //printf("linelable: |%s|\n", lable.c_str()); - } - } + int ct = 0; + int x = 0; + bool match = false; + s = operEx[ct]; + while (s != "") + { + RegularExpression regex(s, 0, true); + strs.clear(); + x = 0; + try + { + x = regex.split(restofline, strs, 0); + } + catch (Poco::Exception &e) + { + x = 0; + if (isDebug() > 3) + { + cout << e.displayText() << endl; + } + } + if (x > 0) + { + //printf("%d regex %d match |%s|\n", ct, x, restofline.c_str()); + operand = strs[0]; + orig_operand=operand; + //printf("which=%d operand=|%s|\n",ct,operand.c_str()); + i = (int)operand.length(); + restofline = restofline.substr(i, restofline.length()); + comment = Poco::trim(restofline); + match = true; + break; + } + ct++; + s = operEx[ct]; + } + i = l; + if (!match) + { + // if you are here, there probably isn't an operand and/or comment after opcode + } + } + break; + } + } + printlable = lable; + x = (int)lable.length(); + if (x > 1) + { + // M32 syntax allows a colon after lable, and it is not part of the lable + if ((syntax & SYNTAX_MERLIN32) == SYNTAX_MERLIN32) + { + while ((x > 1) && (lable[x - 1] == ':')) + { + lable = lable.substr(0, x - 1); + x--; + } + //printf("linelable: |%s|\n", lable.c_str()); + } + } - opcodelower = Poco::toLower(opcode); + opcodelower = Poco::toLower(opcode); } #undef CLASS @@ -537,20 +541,20 @@ void CLASS::set(std::string line) CLASS::CLASS() { - int x; - errorct = 0; - syntax=SYNTAX_QASM; + int x; + errorct = 0; + syntax=SYNTAX_QASM; - win_columns = -1; - win_rows = -1; - struct winsize w; - x = ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); - if (x == 0) - { - win_columns = w.ws_col; - win_rows = w.ws_row; - } - //printf("cols=%d rows=%d\n",win_columns,win_rows); + win_columns = -1; + win_rows = -1; + struct winsize w; + x = ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); + if (x == 0) + { + win_columns = w.ws_col; + win_rows = w.ws_row; + } + //printf("cols=%d rows=%d\n",win_columns,win_rows); } @@ -560,63 +564,65 @@ CLASS::~CLASS() void CLASS::setSyntax(uint32_t syn) { - syntax=syn; + syntax=syn; } void CLASS::errorOut(uint16_t code) { - printf("error: %d\n", code); + printf("error: %d\n", code); } void CLASS::init(void) { - int ts, tabpos; - std::string s; + int ts, tabpos; + std::string s; - filenames.clear(); - starttime = GetTickCount(); - initialdir = Poco::Path::current(); - filecount = 0; - syntax = SYNTAX_QASM; + filenames.clear(); + starttime = GetTickCount(); + initialdir = Poco::Path::current(); + filecount = 0; + syntax = SYNTAX_QASM; - std::string tabstr = getConfig("reformat.tabs", "8,16,32"); - tabstr = Poco::trim(tabstr); + //std::string tabstr = getConfig("reformat.tabs", "8,16,32"); + std::string tabstr = getConfig("reformat.tabs", "12,24,40,70"); - memset(tabs, 0x00, sizeof(tabs)); + tabstr = Poco::trim(tabstr); - Poco::StringTokenizer t(tabstr, ",;", 0); - tabpos = 0; - for (auto itr = t.begin(); itr != t.end(); ++itr) - { - s = Poco::trim(*itr); - try - { - ts = Poco::NumberParser::parse(s); - } - catch (...) - { - ts = 0; - } - if ((ts >= 0) && (ts < 240)) - { - tabs[tabpos++] = ts; - } - } + memset(tabs, 0x00, sizeof(tabs)); + + Poco::StringTokenizer t(tabstr, ",;", 0); + tabpos = 0; + for (auto itr = t.begin(); itr != t.end(); ++itr) + { + s = Poco::trim(*itr); + try + { + ts = Poco::NumberParser::parse(s); + } + catch (...) + { + ts = 0; + } + if ((ts >= 0) && (ts < 240)) + { + tabs[tabpos++] = ts; + } + } } void CLASS::complete(void) { - uint64_t n = GetTickCount(); - //if (isDebug()) - { - //cout << "Processing Time: " << n - starttime << "ms" << endl; - uint64_t x = n - starttime; - uint32_t x1 = x & 0xFFFFFFFF; - printf("Elapsed time: %u ms\n", x1); + uint64_t n = GetTickCount(); + //if (isDebug()) + { + //cout << "Processing Time: " << n - starttime << "ms" << endl; + uint64_t x = n - starttime; + uint32_t x1 = x & 0xFFFFFFFF; + printf("Elapsed time: %u ms\n", x1); - } + } } void CLASS::process(void) @@ -625,455 +631,514 @@ void CLASS::process(void) } int CLASS::doline(int lineno, std::string line) { - UNUSED(lineno); - UNUSED(line); + UNUSED(lineno); + UNUSED(line); - int res = -1; + int res = -1; - return (res); + return (res); } std::string CLASS::processFilename(std::string fn, std::string curDir, int level) { - std::string res = fn; - std::string s, s1; - Path p = Poco::Path(fn); + std::string res = fn; + std::string s, s1; + Path p = Poco::Path(fn); - try - { - int n = p.depth(); - //LOG_DEBUG << "n=" << n << " " << fn << endl; - if (n == 0) - { - res = curDir + fn; - } - if (n > 0) - { - std::string d1 = p[0]; - uint32_t v = 100; - try - { - v = Poco::NumberParser::parseUnsigned(d1); - } - catch (...) - { - v = 99; - } - if (v < 10) - { - Poco::Path p1 = p.popFrontDirectory(); - s = p1.toString(); - s1 = "global.path" + Poco::NumberFormatter::format(v); - switch (v) - { - case 0: - s = initialdir + s; - break; - default: - s = getConfig(s1, ".") + "/" + s; - if (level < 5) - { - s = processFilename(s, curDir, level + 1); - } - break; - } - p = s; - p.makeAbsolute(); - } - res = p.toString(); - } - } - catch (Poco::Exception &e) - { - if (isDebug() > 2) - { - cout << "exception: " << e.displayText() << endl; - } - } - catch (std::exception &e) - { - if (isDebug() > 2) - { - cout << e.what() << endl; - } - } + try + { + int n = p.depth(); + //LOG_DEBUG << "n=" << n << " " << fn << endl; + if (n == 0) + { + res = curDir + fn; + } + if (n > 0) + { + std::string d1 = p[0]; + uint32_t v = 100; + try + { + v = Poco::NumberParser::parseUnsigned(d1); + } + catch (...) + { + v = 99; + } + if (v < 10) + { + Poco::Path p1 = p.popFrontDirectory(); + s = p1.toString(); + s1 = "global.path" + Poco::NumberFormatter::format(v); + switch (v) + { + case 0: + s = initialdir + s; + break; + default: + s = getConfig(s1, ".") + "/" + s; + if (level < 5) + { + s = processFilename(s, curDir, level + 1); + } + break; + } + p = s; + p.makeAbsolute(); + } + res = p.toString(); + } + } + catch (Poco::Exception &e) + { + if (isDebug() > 2) + { + cout << "exception: " << e.displayText() << endl; + } + } + catch (std::exception &e) + { + if (isDebug() > 2) + { + cout << e.what() << endl; + } + } - p = res; - p.makeAbsolute(); - res = p.toString(); + p = res; + p.makeAbsolute(); + res = p.toString(); - char buff[PATH_MAX + 1]; - memset(buff, 0x00, sizeof(buff)); - char *rp = realpath(res.c_str(), buff); - if (rp != NULL) - { - //printf("realpath: %s\n", buff); - res = rp; - } - p = res; - p.makeAbsolute(); - res = p.toString(); + char buff[PATH_MAX + 1]; + memset(buff, 0x00, sizeof(buff)); + char *rp = realpath(res.c_str(), buff); + if (rp != NULL) + { + //printf("realpath: %s\n", buff); + res = rp; + } + p = res; + p.makeAbsolute(); + res = p.toString(); - //LOG_DEBUG << "convert: |" << res << "|" << endl; + //LOG_DEBUG << "convert: |" << res << "|" << endl; - return (res); + return (res); } int CLASS::processfile(std::string p, std::string &newfilename) { - //Poco::File fn(p); - int c; - int res = -1; - uint32_t linect; - bool done, valid; - std::string currentdir; - std::string p1; - std::string line, op; + //Poco::File fn(p); + int c,c1; + int res = -1; + uint32_t linect; + bool done, valid; + std::string currentdir; + std::string p1; + std::string line, op; - linect = 0; - done = false; + linect = 0; + done = false; - p = Poco::trim(p); - currentdir = Poco::Path::current(); + p = Poco::trim(p); + currentdir = Poco::Path::current(); - if (filecount == 0) - { - initialdir = currentdir; - //printf("initialdir=%s\n",initialdir.c_str()); - } + if (filecount == 0) + { + initialdir = currentdir; + //printf("initialdir=%s\n",initialdir.c_str()); + } - //printf("currentdir=%s initialdir=%s\n", currentdir.c_str(), initialdir.c_str()); - //LOG_DEBUG << "initial file name: " << p << endl; - p = processFilename(p, (filecount == 0) ? currentdir : currentdir, 0); + //printf("currentdir=%s initialdir=%s\n", currentdir.c_str(), initialdir.c_str()); + //LOG_DEBUG << "initial file name: " << p << endl; + p = processFilename(p, (filecount == 0) ? currentdir : currentdir, 0); - //LOG_DEBUG << "Converted filename: " << p << endl; + //LOG_DEBUG << "Converted filename: " << p << endl; - Poco::Path tp(p); - Poco::Path path = tp.makeAbsolute(); - Poco::Path parent = path.parent(); - std::string dir = parent.toString(); + Poco::Path tp(p); + Poco::Path path = tp.makeAbsolute(); + Poco::Path parent = path.parent(); + std::string dir = parent.toString(); - try - { + try + { - if (filecount == 0) - { - // is this the first file in the compilation, or a PUT/USE? - // if first, change CWD to location of file - //LOG_DEBUG << "Changing directory to: " << dir << endl; - if (chdir(dir.c_str())) {} // change directory to where the file is - } + if (filecount == 0) + { + // is this the first file in the compilation, or a PUT/USE? + // if first, change CWD to location of file + //LOG_DEBUG << "Changing directory to: " << dir << endl; + if (chdir(dir.c_str())) {} // change directory to where the file is + } - p1 = path.toString(); + p1 = path.toString(); - newfilename = p1; - //LOG_DEBUG << "initial file name: " << p1 << endl; + newfilename = p1; + //LOG_DEBUG << "initial file name: " << p1 << endl; - valid = true; - Poco::File fn(p1); - if (!fn.exists()) - { - fn = Poco::File(p1 + ".s"); - if (!fn.exists()) - { - fn = Poco::File(p1 + ".S"); - if (!fn.exists()) - { - fn = Poco::File(p1 + ".mac"); - if (!fn.exists()) - { - fn = Poco::File(p1); - valid = false; - } - } - } - } - p1 = fn.path(); - //LOG_DEBUG << "File name: " << p1 << endl; + valid = true; + Poco::File fn(p1); + if (!fn.exists()) + { + fn = Poco::File(p1 + ".s"); + if (!fn.exists()) + { + fn = Poco::File(p1 + ".S"); + if (!fn.exists()) + { + fn = Poco::File(p1 + ".mac"); + if (!fn.exists()) + { + fn = Poco::File(p1); + valid = false; + } + } + } + } + p1 = fn.path(); + //LOG_DEBUG << "File name: " << p1 << endl; - int ecode = -3; - valid = false; - if (fn.exists()) - { - ecode = -2; - valid = true; - //LOG_DEBUG << "File exists: " << p1 << endl; - if (fn.isLink()) - { - //LOG_DEBUG << "File is a link: " << p1 << endl; - } - if ((fn.isDirectory()) || (!fn.canRead())) - { - LOG_DEBUG << "File is a directory: " << p1 << endl; - valid = false; - } - } - else - { - printf("file does not exist |%s|\n", p1.c_str()); - } + int ecode = -3; + valid = false; + if (fn.exists()) + { + ecode = -2; + valid = true; + //LOG_DEBUG << "File exists: " << p1 << endl; + if (fn.isLink()) + { + //LOG_DEBUG << "File is a link: " << p1 << endl; + } + if ((fn.isDirectory()) || (!fn.canRead())) + { + LOG_DEBUG << "File is a directory or can not read: " << p1 << endl; + valid = false; + } + } + else + { + printf("file does not exist |%s|\n", p1.c_str()); + } - newfilename = p1; - if (!valid) - { - //fprintf(stderr, "Unable to access file: %s\n", p1.c_str()); + newfilename = p1; + if (!valid) + { + //fprintf(stderr, "Unable to access file: %s\n", p1.c_str()); - errorct = 1; - return (ecode); - } + errorct = 1; + return (ecode); + } - if (valid) - { + if (valid) + { - if (filecount == 0) - { - } - else - { - for (auto itr = filenames.begin(); itr != filenames.end(); ++itr) - { - if (*itr == p1) - { - return (-9); - } - } - } + if (filecount == 0) + { + } + else + { + for (auto itr = filenames.begin(); itr != filenames.end(); ++itr) + { + if (*itr == p1) + { + return (-9); + } + } + } - filecount++; - filenames.push_back(p1); + filecount++; + filenames.push_back(p1); - std::ifstream f(p1); - if (f.is_open()) - { - //printf("file is open\n"); - line = ""; + std::ifstream f(p1); + if (f.is_open()) + { + //printf("file is open\n"); + line = ""; + while ((!done) && (f.good()) && (!f.eof())) + { + c = f.get(); + c1 = c & 0x7F; + if (c == 0x8D) // merlin line ending + { + c = 0x0A; // convert to linux + } + else if (c == 0x8A) // possible merlin line ending + { + c = 0x0D; // ignore + } + else if ((c1<0x20) || (c1==127)) // see if it might be a control character + { + if ((c1==0x0D) || (c1==0x0A) || (c1==0x09)) + { - while ((!done) && (f.good()) && (!f.eof())) - { - c = f.get(); - if (c == 0x8D) // merlin line ending - { - c = 0x0A; // convert to linux - } - if (c == 0x8A) // possible merlin line ending - { - c = 0x00; // ignore - } - c &= 0x7F; - int x; - switch (c) - { - case 0x0D: - break; - case 0x09: - line += " "; - break; - case 0x0A: - linect++; - x = doline(linect, line); - if (x < 0) - { - done = true; - } - line = ""; - break; - default: - if ((c >= ' ') && (c < 0x7F)) - { - line += c; - } - else - { - //printf("garbage %08X\n",c); - } - break; - } - } - if ( (f.eof())) - { - res = 0; - } - } - } - else - { - fprintf(stderr, "File <%s> does not exist.\n\n", p.c_str()); - } - } - catch (...) - { - - } - return (res); -} - -#undef CLASS -#define CLASS TImageProcessor - -CLASS::CLASS() : TFileProcessor() -{ - -} -CLASS::~TImageProcessor() -{ - -} - -int CLASS::doline(int lineno, std::string line) -{ - printf("%05d: %s\n",lineno,line.c_str()); - return(0); -} -void CLASS::process(void) -{ - -} -void CLASS::complete(void) -{ + } + else + { + c=0x00; + } + } + c &= 0x7F; + int x; + switch (c) + { + case 0x00: + case 0x0D: + break; + case 0x09: + line += " "; + break; + case 0x0A: + linect++; + line=Poco::trimRight(line); //get rid of any space at end of line + x = doline(linect, line); + if (x < 0) + { + done = true; + } + line = ""; + break; + default: + if ((c >= ' ') && (c < 0x7F)) + { + line += c; + } + else + { + //printf("garbage %08X\n",c); + } + break; + } + } + if ( (f.eof())) + { + res = 0; + } + } + } + else + { + fprintf(stderr, "File <%s> does not exist.\n\n", p.c_str()); + } + } + catch (...) + { + } + return (res); } #undef CLASS #define CLASS TMerlinConverter CLASS::CLASS() : TFileProcessor() { + format_flags=CONVERT_TEST; } CLASS::~CLASS() { } void CLASS::init(void) { - TFileProcessor::init(); - std::string s; - lines.clear(); + TFileProcessor::init(); + std::string s; + lines.clear(); } int CLASS::doline(int lineno, std::string line) { - UNUSED(lineno); + UNUSED(lineno); - MerlinLine l(line); - lines.push_back(l); - return 0; + MerlinLine l(line); + lines.push_back(l); + return 0; } void CLASS::process(void) { - char buff[128*1024]; - uint32_t ct = (uint32_t)lines.size(); - uint8_t orval=0x80; + char buff[128*1024]; + uint32_t ct = (uint32_t)lines.size(); + uint8_t orval=0x00; + uint32_t flags; + string s; + int llen,oplen,operlen,comlen; + string lable,opcode,operand,comment; - uint32_t len, tlen,t, pos,i; + uint32_t len, tlen,t, pos,i; - tlen=0; - for (uint32_t lineno = 0; lineno < ct; lineno++) - { - MerlinLine &line = lines.at(lineno); - len=0; - pos = 0; - if ((line.lable.length() == 0) - && (line.opcode.length() == 0) - && (line.operand.length() == 0)) - { - if (line.comment.length() > 0) - { - char c = line.comment[0]; - if ((c == '*') || (c == '/')) - { - sprintf(&buff[len+tlen],"%s", line.comment.c_str()); - } - else - { - t = tabs[2]; - while (len < t) - { - len += sprintf(&buff[len+tlen]," "); - } - sprintf(&buff[len+tlen],"%s", line.comment.c_str()); - } - } - sprintf(&buff[len+tlen],"\r"); - } - else - { - t = tabs[pos++]; - len = sprintf(&buff[len+tlen],"%s ", line.printlable.c_str()); - while (len < t) - { - len += sprintf(&buff[len+tlen]," "); - } + tlen=0; + flags=format_flags; - t = tabs[pos++]; - len += sprintf(&buff[len+tlen],"%s ", line.opcode.c_str()); - while (len < t) - { - len += sprintf(&buff[len+tlen]," "); - } + for (uint32_t lineno = 0; lineno < ct; lineno++) + { + MerlinLine &line = lines.at(lineno); + orval=0x00; + if (flags&CONVERT_HIGH) + { + orval=0x80; + } + len=0; + pos = 0; - t = tabs[pos++]; - len += sprintf(&buff[len+tlen],"%s ", line.operand.c_str()); - while (len < t) - { - len += sprintf(&buff[len+tlen]," "); - } + lable=Poco::trimRight(line.printlable); + llen=lable.length(); + opcode=Poco::trimRight(line.opcode); + oplen=opcode.length(); + operand=Poco::trimRight(line.operand); + operlen=operand.length(); + comment=Poco::trimRight(line.comment); + comlen=comment.length(); - t = tabs[pos++]; - len += sprintf(&buff[len+tlen],"%s", line.comment.c_str()); - while (len < t) - { - len += sprintf(&buff[len+tlen]," "); - } - if (syntax ==SYNTAX_MERLIN) - len += sprintf(&buff[len+tlen],"\r"); - else - len += sprintf(&buff[len+tlen],"\n"); - } - tlen+=len; - } - //printf("tlen=%d\n",tlen); - if (tlen>0) - { - int tct=0; - for (i=0; i 0) + { + char c = comment[0]; + if ((c == '*') || (c == '/')) + { + len+=sprintf(&buff[len+tlen],"%s", comment.c_str()); + } + else + { + t = tabs[2]; + if (flags&CONVERT_COMPRESS) + { + len += sprintf(&buff[len+tlen]," "); + } + else + { + while (len < t) + { + len += sprintf(&buff[len+tlen]," "); + } + } + len+=sprintf(&buff[len+tlen],"%s", comment.c_str()); + } + } + } else + { + t = tabs[pos++]; + len += sprintf(&buff[len+tlen],"%s", lable.c_str()); + if ((oplen+operlen+comlen)>0) + { + if (flags&CONVERT_COMPRESS) + { + len += sprintf(&buff[len+tlen]," "); + } + else + { + while (len < t) + { + len += sprintf(&buff[len+tlen]," "); + } + } + } + + t = tabs[pos++]; + len += sprintf(&buff[len+tlen],"%s", opcode.c_str()); + if ((operlen+comlen)>0) + { + if (flags&CONVERT_COMPRESS) + { + len += sprintf(&buff[len+tlen]," "); + } + else + { + while (len < t) + { + len += sprintf(&buff[len+tlen]," "); + } + } + } + + t = tabs[pos++]; + len += sprintf(&buff[len+tlen],"%s", operand.c_str()); + if ((comlen)>0) + { + if (flags&CONVERT_COMPRESS) + { + len += sprintf(&buff[len+tlen]," "); + } + else + { + while (len < t) + { + len += sprintf(&buff[len+tlen]," "); + } + } + } + + len += sprintf(&buff[len+tlen],"%s", comment.c_str()); + } + if (flags&CONVERT_CRLF) + { + len+=sprintf(&buff[len+tlen],"\r\n"); + } + else if (flags&CONVERT_LF) + { + len+=sprintf(&buff[len+tlen],"\n"); + } + else + { + len+=sprintf(&buff[len+tlen],"\r"); + } + tlen+=len; + } + //printf("tlen=%d\n",tlen); + if (tlen>0) + { + int tct=0; + int idx=0; + for (i=0; i p(Poco::toUpper(op), sym); + sym.name = op; + sym.opcode = opcode; + sym.namelc = Poco::toLower(op); + sym.stype = flags; + sym.value = 0; + sym.cb = cb; + std::pair p(Poco::toUpper(op), sym); - opcodes.insert(p); + opcodes.insert(p); } TSymbol * CLASS::addSymbol(std::string symname, uint32_t val, bool replace) { - TSymbol *res = NULL; - TSymbol *fnd = NULL; + TSymbol *res = NULL; + TSymbol *fnd = NULL; - std::string sym = symname; - if (!casesen) - { - sym = Poco::toUpper(sym); - } + std::string sym = symname; + if (!casesen) + { + sym = Poco::toUpper(sym); + } - //printf("addSymbol: |%s|\n",sym.c_str()); - if (sym.length() > 0) - { - TSymbol s; - s.name = sym; - s.opcode = 0; - s.namelc = Poco::toLower(sym); - s.stype = 0; - s.value = val; - s.used = false; - s.cb = NULL; - std::pair p(sym, s); + //printf("addSymbol: |%s|\n",sym.c_str()); + if (sym.length() > 0) + { + TSymbol s; + s.name = sym; + s.opcode = 0; + s.namelc = Poco::toLower(sym); + s.stype = 0; + s.value = val; + s.used = false; + s.cb = NULL; + std::pair p(sym, s); - if (sym[0] == ':') - { - //local symbol - if (currentsym == NULL) - { - goto out; - } - else - { - fnd = findSymbol(sym); - if ((fnd != NULL) && (!replace)) - { - goto out; - } + if (sym[0] == ':') + { + //local symbol + if (currentsym == NULL) + { + goto out; + } + else + { + fnd = findSymbol(sym); + if ((fnd != NULL) && (!replace)) + { + goto out; + } - if (fnd != NULL) - { - fnd->value = val; - res = fnd; - goto out; - } - if (currentsym != NULL) - { - currentsym->locals.insert(p); - } - res = findSymbol(sym); - goto out; - } - } - else - { - fnd = findSymbol(sym); + if (fnd != NULL) + { + fnd->value = val; + res = fnd; + goto out; + } + if (currentsym != NULL) + { + currentsym->locals.insert(p); + } + res = findSymbol(sym); + goto out; + } + } + else + { + fnd = findSymbol(sym); - if ((fnd != NULL) && (!replace)) - { - goto out; - } + if ((fnd != NULL) && (!replace)) + { + goto out; + } - if (fnd != NULL) - { - //printf("replacing symbol: %s %08X\n",sym.c_str(),val); - fnd->value = val; - res = fnd; - goto out; - } + if (fnd != NULL) + { + //printf("replacing symbol: %s %08X\n",sym.c_str(),val); + fnd->value = val; + res = fnd; + goto out; + } - symbols.insert(p); - res = findSymbol(sym); - } - } + symbols.insert(p); + res = findSymbol(sym); + } + } out: - return (res); + return (res); } TMacro * CLASS::findMacro(std::string symname) { - TMacro *res = NULL; + TMacro *res = NULL; - std::string sym = symname; - if (!casesen) - { - sym = Poco::toUpper(sym); - } - if (symname.length() > 0) - { - //printf("finding: %s\n",symname.c_str()); - auto itr = macros.find(sym); - if (itr != macros.end()) - { - res = &itr->second; - } - } - return (res); + std::string sym = symname; + if (!casesen) + { + sym = Poco::toUpper(sym); + } + if (symname.length() > 0) + { + //printf("finding: %s\n",symname.c_str()); + auto itr = macros.find(sym); + if (itr != macros.end()) + { + res = &itr->second; + } + } + return (res); } TSymbol * CLASS::findSymbol(std::string symname) { - TSymbol *res = NULL; + TSymbol *res = NULL; - std::string sym = symname; - if (!casesen) - { - sym = Poco::toUpper(sym); - } - if (symname.length() > 0) - { - if (symname[0] == ':') - { - if (currentsym == NULL) - { - goto out; - } - else - { - auto itr = currentsym->locals.find(sym); - if (itr != currentsym->locals.end()) - { - res = &itr->second; - goto out; - } - } - } - else - { - //printf("finding: %s\n",symname.c_str()); - auto itr = symbols.find(sym); - if (itr != symbols.end()) - { - //printf("Found: %s 0x%08X\n",itr->second.name.c_str(),itr->second.value); - res = &itr->second; - goto out; - } - } - } + std::string sym = symname; + if (!casesen) + { + sym = Poco::toUpper(sym); + } + if (symname.length() > 0) + { + if (symname[0] == ']') + { + //printf("finding symbol: |%s|\n",symname.c_str()); + res = findVariable(symname, variables); + if (res!=NULL) + { + //printf("symbol found: |%s| |%s|\n",symname.c_str(),res->var_text.c_str()); + TEvaluator eval(*this); + int64_t er_val=0; + uint8_t shift=0; + int er; + er = eval.evaluate(res->var_text, er_val, shift); + if (er == 0) + { + res->value=er_val; + } + } + } + else if (symname[0] == ':') + { + if (currentsym == NULL) + { + goto out; + } + else + { + auto itr = currentsym->locals.find(sym); + if (itr != currentsym->locals.end()) + { + res = &itr->second; + goto out; + } + } + } + else + { + //printf("finding: %s\n",symname.c_str()); + auto itr = symbols.find(sym); + if (itr != symbols.end()) + { + //printf("Found: %s 0x%08X\n",itr->second.name.c_str(),itr->second.value); + res = &itr->second; + goto out; + } + } + } out: - return (res); + return (res); } TSymbol * CLASS::addVariable(std::string symname, std::string val, TVariable &vars, bool replace) { - TSymbol *res = NULL; - TSymbol *fnd = NULL; + TSymbol *res = NULL; + TSymbol *fnd = NULL; - std::string sym = symname; - if (!casesen) - { - sym = Poco::toUpper(sym); - } + std::string sym = symname; + if (!casesen) + { + sym = Poco::toUpper(sym); + } - //printf("addvariable\n"); - fnd = findVariable(sym, vars); + //printf("addvariable\n"); + fnd = findVariable(sym, vars); - if ((fnd != NULL) && (!replace)) - { - return (NULL); // it is a duplicate - } + if ((fnd != NULL) && (!replace)) + { + return (NULL); // it is a duplicate + } - if (fnd != NULL) - { - //printf("replacing symbol: %s %s\n",sym.c_str(),val.c_str()); - fnd->var_text = val; - return (fnd); - } + if (fnd != NULL) + { + //printf("replacing symbol: %s %s\n",sym.c_str(),val.c_str()); + fnd->var_text = val; + return (fnd); + } - TSymbol s; - s.name = sym; - s.opcode = 0; - s.namelc = Poco::toLower(sym); - s.stype = 0; - s.value = 0; - s.var_text = val; - s.used = false; - s.cb = NULL; + TSymbol s; + s.name = sym; + s.opcode = 0; + s.namelc = Poco::toLower(sym); + s.stype = 0; + s.value = 0; + s.var_text = val; + s.used = false; + s.cb = NULL; - //printf("addvariable: %s %s\n", s.name.c_str(), s.var_text.c_str()); + //printf("addvariable: %s %s\n", s.name.c_str(), s.var_text.c_str()); - std::pair p(sym, s); - vars.vars.insert(p); - res = findVariable(sym, vars); - return (res); + std::pair p(sym, s); + vars.vars.insert(p); + res = findVariable(sym, vars); + return (res); } TSymbol * CLASS::findVariable(std::string symname, TVariable &vars) { - TSymbol *res = NULL; + TSymbol *res = NULL; - if (!casesen) - { - symname = Poco::toUpper(symname); - } + if (!casesen) + { + symname = Poco::toUpper(symname); + } - if ((expand_macrostack.size() > 0) && (vars.id != expand_macro.variables.id)) - { - res = findVariable(symname, expand_macro.variables); - if (res != NULL) - { - return (res); - } - } + if ((expand_macrostack.size() > 0) && (vars.id != expand_macro.variables.id)) + { + res = findVariable(symname, expand_macro.variables); + if (res != NULL) + { + return (res); + } + } - //printf("finding: %s\n",symname.c_str()); - auto itr = vars.vars.find(symname); - if (itr != vars.vars.end()) - { - //printf("Found: %s 0x%08X\n",itr->second.name.c_str(),itr->second.value); - res = &itr->second; + //printf("finding: %s\n",symname.c_str()); + auto itr = vars.vars.find(symname); + if (itr != vars.vars.end()) + { + //printf("Found: %s 0x%08X\n",itr->second.name.c_str(),itr->second.value); + res = &itr->second; - return (res); - } - return (res); + return (res); + } + return (res); } void CLASS::showVariables(TVariable &vars) { - if (vars.vars.size() > 0) - { - printf("\nVariables:\n"); + if (vars.vars.size() > 0) + { + printf("\nVariables:\n"); - for (auto itr = vars.vars.begin(); itr != vars.vars.end(); ++itr) - { - printf("%-16s %s\n", itr->first.c_str(), itr->second.var_text.c_str()); - } - printf("\n"); - } + for (auto itr = vars.vars.begin(); itr != vars.vars.end(); ++itr) + { + printf("%-16s %s\n", itr->first.c_str(), itr->second.var_text.c_str()); + } + printf("\n"); + } } // set alpha to true to print table sorted by name or // false to print by value; void CLASS::showSymbolTable(bool alpha) { - if (symbols.size() > 0) - { - std::map alphamap; - std::map nummap; + if (symbols.size() > 0) + { + std::map alphamap; + std::map nummap; - int columns = getInt("asm.symcolumns", 3); - int column = columns; + int columns = getInt("asm.symcolumns", 3); + int column = columns; - for (auto itr = symbols.begin(); itr != symbols.end(); itr++) - { - TSymbol ptr = itr->second; - alphamap.insert(pair(ptr.name, ptr.value)); - nummap.insert(pair(ptr.value, ptr.name)); - } + for (auto itr = symbols.begin(); itr != symbols.end(); itr++) + { + TSymbol ptr = itr->second; + alphamap.insert(pair(ptr.name, ptr.value)); + nummap.insert(pair(ptr.value, ptr.name)); + } - if (alpha) - { - printf("\n\nSymbol table sorted alphabetically:\n\n"); + if (alpha) + { + printf("\n\nSymbol table sorted alphabetically:\n\n"); - for (auto itr = alphamap.begin(); itr != alphamap.end(); ++itr) - { - printf("%-16s 0x%08X ", itr->first.c_str(), itr->second); - if ( !--column ) - { - printf("\n"); - column = columns; - } - } - } - else - { - printf("\n\nSymbol table sorted numerically:\n\n"); - for (auto itr = nummap.begin(); itr != nummap.end(); ++itr) - { - printf("0x%08X %-16s ", itr->first, itr->second.c_str()); - if ( !--column ) - { - printf("\n"); - column = columns; - } - } - } - if (column > 0) - { - printf("\n"); - } - } + for (auto itr = alphamap.begin(); itr != alphamap.end(); ++itr) + { + printf("%-16s 0x%08X ", itr->first.c_str(), itr->second); + if ( !--column ) + { + printf("\n"); + column = columns; + } + } + } + else + { + printf("\n\nSymbol table sorted numerically:\n\n"); + for (auto itr = nummap.begin(); itr != nummap.end(); ++itr) + { + printf("0x%08X %-16s ", itr->first, itr->second.c_str()); + if ( !--column ) + { + printf("\n"); + column = columns; + } + } + } + if (column > 0) + { + printf("\n"); + } + } } // set alpha to true to print table sorted by name or // false to print by value; void CLASS::showMacros(bool alpha) { - if (macros.size() > 0) - { - std::map alphamap; + if (macros.size() > 0) + { + std::map alphamap; - int columns = getInt("asm.symcolumns", 3); - int column = columns; + int columns = getInt("asm.symcolumns", 3); + int column = columns; - for (auto itr = macros.begin(); itr != macros.end(); itr++) - { - TMacro ptr = itr->second; - alphamap.insert(pair(ptr.name, 0)); - } + for (auto itr = macros.begin(); itr != macros.end(); itr++) + { + TMacro ptr = itr->second; + alphamap.insert(pair(ptr.name, 0)); + } - if (alpha) - { - printf("\n\nmacros sorted alphabetically:\n\n"); + if (alpha) + { + printf("\n\nmacros sorted alphabetically:\n\n"); - for (auto itr = alphamap.begin(); itr != alphamap.end(); ++itr) - { - printf("%-16s 0x%08X ", itr->first.c_str(), itr->second); - if ( !--column ) - { - printf("\n"); - column = columns; - } - } - } - if (column > 0) - { - printf("\n"); - } - } + for (auto itr = alphamap.begin(); itr != alphamap.end(); ++itr) + { + printf("%-16s 0x%08X ", itr->first.c_str(), itr->second); + if ( !--column ) + { + printf("\n"); + column = columns; + } + } + } + if (column > 0) + { + printf("\n"); + } + } } int CLASS::callOpCode(std::string op, MerlinLine &line) { - int res = -1; - char c; - std::string s; + int res = -1; + char c; + std::string s; - // 'op' is always lowercase here + // 'op' is always lowercase here // during MACRO definition no opcodes are called (except for MAC, EOM, <<) - if (macrostack.size() > 0) - { - // if something on the macro stack, then a macro is being defined - if (!((op == "mac") || (op == "eom") || (op == "<<<"))) - { - return 0; - } - } + if (macrostack.size() > 0) + { + // if something on the macro stack, then a macro is being defined + if (!((op == "mac") || (op == "eom") || (op == "<<<"))) + { + return 0; + } + } - if (op.length() == 4) // check for 4 digit 'L' opcodes - { - c = op[3] & 0x7F; - if ((c >= 'a') && (c <= 'z')) - { - c = c - 0x20; - } - switch (c) - { - case 'L': - op = op.substr(0, 3); - line.flags |= FLAG_FORCELONG; // 3 byte address - break; - default: // any char but 'L' as in Merlin 16+ - s = Poco::toUpper(op); - if ((s == "ELSE") || (s == "DEND")) - { - break; - } - if (c != 'D') - { - op = op.substr(0, 3); - line.flags |= FLAG_FORCEABS; // 2 byte address - } - break; - case 'Z': - op = op.substr(0, 3); - line.flags |= FLAG_FORCEDP; // one byte address - break; - } - } + if (op.length() == 4) // check for 4 digit 'L' opcodes + { + c = op[3] & 0x7F; + if ((c >= 'a') && (c <= 'z')) + { + c = c - 0x20; + } + switch (c) + { + case 'L': + op = op.substr(0, 3); + line.flags |= FLAG_FORCELONG; // 3 byte address + break; + default: // any char but 'L' as in Merlin 16+ + s = Poco::toUpper(op); + if ((s == "ELSE") || (s == "DEND")) + { + break; + } + if (c != 'D') + { + op = op.substr(0, 3); + line.flags |= FLAG_FORCEABS; // 2 byte address + } + break; + case 'Z': + op = op.substr(0, 3); + line.flags |= FLAG_FORCEDP; // one byte address + break; + } + } - if (line.addressmode == syn_imm) - { - //printf("immediate mode\n"); - switch (line.expr_shift) - { - case '<': - //line.expr_value &= 0xFF; - break; - case '>': - line.expr_value >>= 8; - //line.expr_value &= 0xFFFF; - break; - case '^': - line.expr_value = (line.expr_value >> 16); - //line.expr_value = (line.expr_value >> 16) & 0xFFFF; - break; - case '|': - if (syntax == SYNTAX_MERLIN) - { - line.setError(errBadLabel); - line.expr_value = 0; - } - break; - } - } - else - { - switch (line.expr_shift) - { - case '<': - line.flags |= FLAG_DP; - break; - case '>': + if (line.addressmode == syn_imm) + { + //printf("immediate mode\n"); + switch (line.expr_shift) + { + case '<': + //line.expr_value &= 0xFF; + break; + case '>': + line.expr_value >>= 8; + //line.expr_value &= 0xFFFF; + break; + case '^': + line.expr_value = (line.expr_value >> 16); + //line.expr_value = (line.expr_value >> 16) & 0xFFFF; + break; + case '|': + if (syntax == SYNTAX_MERLIN) + { + line.setError(errBadLabel); + line.expr_value = 0; + } + break; + } + } + else + { + switch (line.expr_shift) + { + case '<': + line.flags |= FLAG_DP; + break; + case '>': #if 0 - if ((syntax & SYNTAX_MERLIN32) == SYNTAX_MERLIN32) - { - // bug in M32 or not, do what it does - line.flags |= FLAG_FORCEABS; - } - else + if ((syntax & SYNTAX_MERLIN32) == SYNTAX_MERLIN32) + { + // bug in M32 or not, do what it does + line.flags |= FLAG_FORCEABS; + } + else #endif - { - line.flags |= FLAG_FORCELONG; - } - break; - case '|': - line.flags |= FLAG_FORCEABS; - break; - case '^': - //line.flags |= FLAG_FORCELONG; - break; - } - } - if (line.expr_value >= 0x100) - { - line.flags |= FLAG_FORCEABS; - } + { + line.flags |= FLAG_FORCELONG; + } + break; + case '|': + line.flags |= FLAG_FORCEABS; + break; + case '^': + //line.flags |= FLAG_FORCELONG; + break; + } + } + if (line.expr_value >= 0x100) + { + line.flags |= FLAG_FORCEABS; + } - auto itr = opcodes.find(Poco::toUpper(op)); - if (itr != opcodes.end()) - { - TSymbol s = itr->second; - if (s.cb != NULL) - { - res = s.cb(line, s); - if (res == -1) - { - res = -2; - } - } - } - else - { - line.setError(errBadOpcode); - } - return (res); + auto itr = opcodes.find(Poco::toUpper(op)); + if (itr != opcodes.end()) + { + TSymbol s = itr->second; + if (s.cb != NULL) + { + res = s.cb(line, s); + if (res == -1) + { + res = -2; + } + } + } + else + { + line.setError(errBadOpcode); + } + return (res); } typedef struct { - std::string regEx; - uint16_t addrMode; - std::string text; - //std::string expression; + std::string regEx; + uint16_t addrMode; + std::string text; + //std::string expression; } TaddrMode; // these are the regular expressions that determine the addressing mode @@ -1579,26 +1662,28 @@ typedef struct const TaddrMode addrRegEx[] = { - { "^(?'expr'.+)\\,[s,S]{1}$", syn_s, "e,s"}, // expr,s - {"^[(]{1}(?'expr'.+)[,]{1}[(S|s)]{1}[)]{1}[,]{1}[(Y|y)]{1}$", syn_sy, "(e,s),y"}, // (expr,s),y - {"^#{1}(.+)$", syn_imm, "immediate"}, //#expr,#^expr,#|expr,#expr - {"^[(]{1}(?'expr'.+)[,]{1}[x,X]{1}\\)$", syn_diix, "(e,x)"}, // (expr,x) - {"^[(]{1}(?'expr'.+)[\\)]{1}[\\,][(Y|y]{1}$", syn_diiy, "(e),y"}, //(expr),y - {"^[(]{1}(?'expr'.+)[\\)]{1}$", syn_di, "(e)"}, // (expr) - {"^\\[{1}(?'expr'.+)\\]{1}[,]{1}[(Y|y)]{1}$", syn_iyl, "[e],y"}, // [expr],y - {"^\\[(?'expr'.+)\\]$", syn_dil, "[e]"}, // [expr] - {"^(?'expr'.+)[,]{1}[(X|x)]{1}$", syn_absx, "e,x"}, // expr,x - {"^(?'expr'.+)[,]{1}[(Y|y)]{1}$", syn_absy, "e,y"}, // expr,y - {"^(?'expr'.+)[,]{1}(?'expr2'.+)$", syn_bm, "block"}, // block move expr,expr1 - {"^(?'expr'.+)$", syn_abs, "absolute"}, // expr (MUST BE LAST) - {"", 0, ""} + { "^(?'expr'.+)\\,[s,S]{1}$", syn_s, "e,s"}, // expr,s + {"^[(]{1}(?'expr'.+)[,]{1}[(S|s)]{1}[)]{1}[,]{1}[(Y|y)]{1}$", syn_sy, "(e,s),y"}, // (expr,s),y + {"^#{1}(.+)$", syn_imm, "immediate"}, //#expr,#^expr,#|expr,#expr + {"^[(]{1}(?'expr'.+)[,]{1}[x,X]{1}\\)$", syn_diix, "(dp,x)"}, // (expr,x) + {"^[(]{1}(?'expr'.+)[\\)]{1}[\\,][(Y|y]{1}$", syn_diiy, "(dp),y"}, //(expr),y + {"^[(]{1}(?'expr'.+)[\\)]{1}$", syn_di, "(dp)"}, // (expr) + {"^\\[{1}(?'expr'.+)\\]{1}[,]{1}[(Y|y)]{1}$", syn_iyl, "[laddr],y"}, // [expr],y + {"^\\[(?'expr'.+)\\]$", syn_dil, "[e]"}, // [expr] + {"^(?'expr'.+)[,]{1}[(X|x)]{1}$", syn_absx, "addr,x"}, // expr,x + {"^(?'expr'.+)[,]{1}[(Y|y)]{1}$", syn_absy, "addr,y"}, // expr,y + {"^(?'expr'.+)[,]{1}(?'expr2'.+)$", syn_bm, "block"}, // block move expr,expr1 + {"^(?'expr'.+)$", syn_abs, "absolute"}, // expr (MUST BE LAST) + {"", 0, ""} }; // one or more of any character except ][,(); -const std::string valExpression = "^([^\\]\\[,();]+)$"; +//const std::string valExpression = "^([^\\]\\[,();]+)$"; +const std::string valExpression = "^([^\\[,();]+)$"; // this one looks for ]variables const std::string varExpression = "([]]{1}[:0-9A-Z_a-z]{1}[0-9A-Z_a-z]*)"; +const std::string varMACExpression = "([]]{1}[:0-9]{1}[0-9]*)"; // opcode check. emitted opcodes are compared against this // table, and if the XC status doesn't meet the requirements @@ -1609,924 +1694,959 @@ const std::string varExpression = "([]]{1}[:0-9A-Z_a-z]{1}[0-9A-Z_a-z]*)"; // 0x02 = 65816 uint8_t opCodeCompatibility[256] = { - 0x00, 0x00, 0x02, 0x02, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x01, 0x02, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x02, 0x01, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x01, 0x02, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x02, 0x01, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x02, 0x02, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x01, 0x02, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x02, 0x01, 0x00, 0x00, 0x02, - 0x01, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x01, 0x02, - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02 + 0x00, 0x00, 0x02, 0x02, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x01, 0x02, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x02, 0x01, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x01, 0x02, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x02, 0x01, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x02, 0x02, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x01, 0x02, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x02, 0x01, 0x00, 0x00, 0x02, + 0x01, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x01, 0x02, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02 }; void CLASS::init(void) { - uint8_t b = opCodeCompatibility[0]; - if (b) - { - } - TFileProcessor::init(); - lines.clear(); + uint8_t b = opCodeCompatibility[0]; + if (b) + { + } + TFileProcessor::init(); + lines.clear(); - insertOpcodes(); + insertOpcodes(); } void CLASS::initpass(void) { - std::string s; + std::string s; - casesen = getBool("asm.casesen", true); - listing = getBool("asm.lst", true); - showmx = getBool("asm.showmx", false); - merlinerrors = getBool("asm.merlinerrors", true); + casesen = getBool("asm.casesen", true); + listing = getBool("asm.lst", true); + showmx = getBool("asm.showmx", true); + merlinerrors = getBool("asm.merlinerrors", true); - trackrep = getBool("asm.trackrep", false); - if (syntax == SYNTAX_MERLIN32) - { - trackrep = true; // can't turn this off in M32 - } - else if (syntax == SYNTAX_MERLIN) - { - trackrep = false; // can't turn this ON in M16 - } - else if (syntax == SYNTAX_QASM) - { - // we will allow this to be settable default off - trackrep = false; - trackrep = getBool("asm.trackrep", trackrep); + trackrep = getBool("asm.trackrep", false); + if (syntax == SYNTAX_MERLIN32) + { + trackrep = true; // can't turn this off in M32 + } + else if (syntax == SYNTAX_MERLIN) + { + trackrep = false; // can't turn this ON in M16 + } + else if (syntax == SYNTAX_QASM) + { + // we will allow this to be settable default off + trackrep = false; + trackrep = getBool("asm.trackrep", trackrep); - } - //merlincompat = getBool("asm.merlincompatible", true); - allowdup = getBool("asm.allowduplicate", true); + } + //merlincompat = getBool("asm.merlincompatible", true); + allowdup = getBool("asm.allowduplicate", true); - skiplist = false; + skiplist = false; - PC.origin = 0x8000; - PC.currentpc = PC.origin; - PC.totalbytes = 0; - PC.orgsave = PC.origin; + PC.origin = 0x8000; + PC.currentpc = PC.origin; + PC.totalbytes = 0; + PC.orgsave = PC.origin; - s = getConfig("asm.cpu", "M65816"); - s = Poco::trim(Poco::toUpper(s)); + s = getConfig("asm.cpu", "M6502"); + s = Poco::trim(Poco::toUpper(s)); - cpumode = MODE_65816; + cpumode = MODE_65816; + mx = 0x03; - if (s == "M65816") - { - cpumode = MODE_65816; - mx = 0x00; - } - else if (s == "M65C02") - { - cpumode = MODE_65C02; - mx = 0x03; - } - else if (s == "M6502") - { - cpumode = MODE_6502; - mx = 0x03; - } - else - { - printf("Unknown CPU type in .ini\n"); - mx = 0x00; - } - mx = getInt("asm.startmx", mx);; + if (s == "M65816") + { + cpumode = MODE_65816; + mx = 0x03; + } + else if (s == "M65C02") + { + cpumode = MODE_65C02; + mx = 0x03; + } + else if (s == "M6502") + { + cpumode = MODE_6502; + mx = 0x03; + } + else + { + printf("Unknown CPU type in .ini\n"); + mx = 0x03; + } + mx = getInt("asm.startmx", mx);; - savepath = getConfig("option.objfile", ""); + savepath = getConfig("option.objfile", ""); - lastcarry = false; - relocatable = false; - currentsym = NULL; - if ((syntax & SYNTAX_MERLIN32) == SYNTAX_MERLIN32) - { - // M32 allows locals that don't have a global above. this is the catchall for that - currentsym = &topSymbol; // this is the default symbol for :locals without a global above; - } - currentsymstr = ""; - lineno = 0; - errorct = 0; - passcomplete = false; - dumstartaddr = 0; - dumstart = 0; - truncdata = 0; - variables.vars.clear(); // clear the variables for each pass + lastcarry = false; + relocatable = false; + currentsym = NULL; + if ((syntax & SYNTAX_MERLIN32) == SYNTAX_MERLIN32) + { + // M32 allows locals that don't have a global above. this is the catchall for that + currentsym = &topSymbol; // this is the default symbol for :locals without a global above; + } + currentsymstr = ""; + lineno = 0; + errorct = 0; + passcomplete = false; + dumstartaddr = 0; + dumstart = 0; + truncdata = 0; + variables.vars.clear(); // clear the variables for each pass - while (!macrostack.empty()) - { - macrostack.pop(); - } - while (!expand_macrostack.empty()) - { - expand_macrostack.pop(); - } - while (!LUPstack.empty()) - { - LUPstack.pop(); - } - while (!DOstack.empty()) - { - DOstack.pop(); - } - while (!LSTstack.empty()) - { - LSTstack.pop(); - } - while (!PCstack.empty()) - { - PCstack.pop(); - } - currentmacro.clear(); - expand_macro.clear(); - curLUP.clear(); - curDO.clear(); + while (!macrostack.empty()) + { + macrostack.pop(); + } + while (!expand_macrostack.empty()) + { + expand_macrostack.pop(); + } + while (!LUPstack.empty()) + { + LUPstack.pop(); + } + while (!DOstack.empty()) + { + DOstack.pop(); + } + while (!LSTstack.empty()) + { + LSTstack.pop(); + } + while (!PCstack.empty()) + { + PCstack.pop(); + } + currentmacro.clear(); + expand_macro.clear(); + curLUP.clear(); + curDO.clear(); } void CLASS::complete(void) { - if (savepath != "") - { - if (errorct == 0) - { - std::string currentdir = Poco::Path::current(); + if (savepath != "") + { + if (errorct == 0) + { + std::string currentdir = Poco::Path::current(); - savepath = processFilename(savepath, currentdir, 0); - printf("saving to file: %s\n", savepath.c_str()); + savepath = processFilename(savepath, currentdir, 0); + printf("saving to file: %s\n", savepath.c_str()); - std::ofstream f(savepath); + std::ofstream f(savepath); - uint32_t lineno = 0; - uint32_t l = (uint32_t)lines.size(); - while (lineno < l) - { - MerlinLine &line = lines.at(lineno++); - if ((line.outbytect > 0) && ((line.flags & FLAG_INDUM) == 0)) - { - for (uint32_t i = 0; i < line.outbytect; i++) - { - f.put(line.outbytes[i]); - } - } - if ((line.datafillct > 0) && ((line.flags & FLAG_INDUM) == 0)) - { - for (uint32_t i = 0; i < line.datafillct; i++) - { - f.put(line.datafillbyte & 0xFF); - } + uint32_t lineno = 0; + uint32_t l = (uint32_t)lines.size(); + while (lineno < l) + { + MerlinLine &line = lines.at(lineno++); + if ((line.outbytect > 0) && ((line.flags & FLAG_INDUM) == 0)) + { + for (uint32_t i = 0; i < line.outbytect; i++) + { + f.put(line.outbytes[i]); + } + } + if ((line.datafillct > 0) && ((line.flags & FLAG_INDUM) == 0)) + { + for (uint32_t i = 0; i < line.datafillct; i++) + { + f.put(line.datafillbyte & 0xFF); + } - } - } - } - else - { - printf("\nErrors in assembly. Output not SAVED.\n\n"); - } - } + } + } + } + else + { + printf("\nErrors in assembly. Output not SAVED.\n\n"); + } + } - printf("\n\nEnd qASM assembly, %d bytes, %u errors, %lu lines, %lu symbols.\n", PC.totalbytes, errorct, lines.size(), symbols.size()); + printf("\n\nEnd qASM assembly, %d bytes, %u errors, %lu lines, %lu symbols.\n", PC.totalbytes, errorct, lines.size(), symbols.size()); - TFileProcessor::complete(); + TFileProcessor::complete(); - if (listing) - { - showSymbolTable(true); - showSymbolTable(false); - showVariables(variables); - showMacros(true); - } + if (listing) + { + showSymbolTable(true); + showSymbolTable(false); + showVariables(variables); + showMacros(true); + } } int CLASS::evaluate(MerlinLine &line, std::string expr, int64_t &value) { - int res = -1; - int64_t result = 0; + int res = -1; + int64_t result = 0; - if (expr.length() > 0) - { + if (expr.length() > 0) + { - TEvaluator eval(*this); - line.eval_result = 0; + TEvaluator eval(*this); + line.eval_result = 0; - res = eval.evaluate(expr, result, line.expr_shift); - if (res != 0) - { - if (isDebug() > 2) - { - int c = SetColor(CL_RED); - uint32_t rr = result & 0xFFFFFFFF; - printf("eval Error=%d %08X |%s|\n", res, rr, eval.badsymbol.c_str()); - SetColor(c); - } - } - if (res == 0) - { - uint64_t v1 = (uint64_t) result; - value = result; - if ((listing) && (pass > 0) && (isDebug() > 2)) - { - uint32_t rr = v1 & 0xFFFFFFFF; - printf("EV1=%08X '%c'\n", rr, line.expr_shift); - } - if (v1 >= 0x10000) - { - line.flags |= FLAG_BIGNUM; - } - if (v1 < 0x100) - { - line.flags |= FLAG_DP; - } - } - } - else - { - value = 0; - res = 0; - } - if (isDebug() >= 3) - { - uint32_t rr = value & 0xFFFFFFFF; - printf("Eval Result: %08X (status=%d)\n", rr, res); - } - return (res); + res = eval.evaluate(expr, result, line.expr_shift); + if (res != 0) + { + if (isDebug() > 2) + { + int c = SetColor(CL_RED); + uint32_t rr = result & 0xFFFFFFFF; + printf("eval Error=%d %08X |%s|\n", res, rr, eval.badsymbol.c_str()); + SetColor(c); + } + } + if (res == 0) + { + uint64_t v1 = (uint64_t) result; + value = result; + if ((listing) && (pass > 0) && (isDebug() > 2)) + { + uint32_t rr = v1 & 0xFFFFFFFF; + printf("EV1=%08X '%c'\n", rr, line.expr_shift); + } + if (v1 >= 0x10000) + { + line.flags |= FLAG_BIGNUM; + } + if (v1 < 0x100) + { + line.flags |= FLAG_DP; + } + } + } + else + { + value = 0; + res = 0; + } + if (isDebug() >= 3) + { + uint32_t rr = value & 0xFFFFFFFF; + printf("Eval Result: %08X (status=%d)\n", rr, res); + } + return (res); } int CLASS::getAddrMode(MerlinLine & line) { - int res = -1; - uint16_t mode = syn_none; - int idx, x; - std::string s, oper; - std::vector groups; + int res = -1; + uint16_t mode = syn_none; + int idx, x; + std::string s, oper; + std::vector groups; - oper = line.operand; + oper = line.operand; - if ((line.opcode.length() == 0) || (line.operand.length() == 0)) - { - return (syn_implied); - } + if ((line.opcode.length() == 0) || (line.operand.length() == 0)) + { + return (syn_implied); + } - idx = 0; - RegularExpression valEx(valExpression, 0, true); + idx = 0; + RegularExpression valEx(valExpression, 0, true); - while (mode == syn_none) - { - s = addrRegEx[idx].regEx; - if (s == "") - { - mode = syn_err; - } - else - { - RegularExpression regex(s, 0, true); - groups.clear(); - x = 0; - try - { - x = regex.split(oper, 0, groups, 0); - } - catch (...) - { - x = 0; - } - if (x > 0) - { - mode = addrRegEx[idx].addrMode; - line.addrtext = addrRegEx[idx].text; - //cout << "mode: " << line.addrtext << endl; - int ct = 0; - for (uint32_t i = 0; i < groups.size(); i++) - { - s = groups[i]; - //printf("ct=%zu idx=%d group: |%s|\n", groups.size(), i, s.c_str()); + while (mode == syn_none) + { + s = addrRegEx[idx].regEx; + if (s == "") + { + mode = syn_err; + } + else + { + RegularExpression regex(s, 0, true); + groups.clear(); + x = 0; + try + { + //printf("oper: |%s|\n",oper.c_str()); + x = regex.split(oper, 0, groups, 0); + } + catch (...) + { + x = 0; + } + if (x > 0) + { + mode = addrRegEx[idx].addrMode; + line.addrtext = addrRegEx[idx].text; + //cout << "mode: " << line.addrtext << endl; + int ct = 0; + for (uint32_t i = 0; i < groups.size(); i++) + { + s = groups[i]; + //printf("ct=%zu idx=%d group: |%s|\n", groups.size(), i, s.c_str()); - if (s != "") - { - if ((s != "^") && (s != "<") && (s != ">") && (s != "|")) - { - bool v = true; - if (mode == syn_abs) - { - if (i > 0) - { - v = valEx.match(s, 0, 0); - if (v) - { - if (pass == 0) - { - // can only check on pass 0, because if the A" - // symbol is defined later, we will generate different - // bytes on the next pass + if (s != "") + { + if ((s != "^") && (s != "<") && (s != ">") && (s != "|")) + { + bool v = true; + if (mode == syn_abs) + { + if (i > 0) + { + v = valEx.match(s, 0, 0); + if (v) + { + if (pass == 0) + { + // can only check on pass 0, because if the A" + // symbol is defined later, we will generate different + // bytes on the next pass - if ((line.syntax & SYNTAX_MERLIN32) == SYNTAX_MERLIN32) - { - if (Poco::toUpper(oper) == "A") // check the whole operand, not just the expression - { - TSymbol *sym = findSymbol("A"); - if (sym == NULL) - { - line.flags |= FLAG_FORCEIMPLIED; - mode = syn_implied; // if the label hasn't been defined yet, assume Immediate addressing - goto out; - } - } - } - } - else if (line.flags & FLAG_FORCEIMPLIED) - { - mode = syn_implied; - goto out; - } - } - } - } - if (!v) - { - //printf("invalid expression |%s|\n", s.c_str()); - mode = syn_none; - } - else if (ct == 1) - { - line.operand_expr = s; - } - else if (ct == 2) - { - line.operand_expr2 = s; - } - ct++; - //printf("line expression=|%s|\n", s.c_str()); - } - else - { - // SGQ need to set a flag for a shift and process it after eval - } - } - } - } - } - idx++; - } + if ((line.syntax & SYNTAX_MERLIN32) == SYNTAX_MERLIN32) + { + if (Poco::toUpper(oper) == "A") // check the whole operand, not just the expression + { + TSymbol *sym = findSymbol("A"); + if (sym == NULL) + { + line.flags |= FLAG_FORCEIMPLIED; + mode = syn_implied; // if the label hasn't been defined yet, assume Immediate addressing + goto out; + } + } + } + } + else if (line.flags & FLAG_FORCEIMPLIED) + { + mode = syn_implied; + goto out; + } + } + } + } + if (!v) + { + //printf("invalid expression |%s|\n", s.c_str()); + mode = syn_none; + } + else if (ct == 1) + { + line.operand_expr = s; + } + else if (ct == 2) + { + line.operand_expr2 = s; + } + ct++; + //printf("line expression=|%s|\n", s.c_str()); + } + else + { + // SGQ need to set a flag for a shift and process it after eval + } + } + } + } + } + idx++; + } out: - if (mode == syn_none) - { - mode = syn_err; - } - res = mode; - //printf("syn_mode=%d\n", mode); - return (res); + if (mode == syn_none) + { + mode = syn_err; + } + res = mode; + //printf("syn_mode=%d\n", mode); + return (res); } int CLASS::parseOperand(MerlinLine & line) { - int res = -1; + int res = -1; - line.operand_expr = ""; - int m = getAddrMode(line); - if (m >= 0) - { - res = m; - } - else - { - //errorOut(errBadAddressMode); - } - return (res); + line.operand_expr = ""; + int m = getAddrMode(line); + if (m >= 0) + { + res = m; + } + else + { + //errorOut(errBadAddressMode); + } + return (res); } int CLASS::substituteVariables(MerlinLine & line, std::string &outop) { - int res = 0; - int x; - std::string::size_type offset, slen; - std::string oper = line.operand; - std::string s; - std::string operin; - TSymbol *sym; - uint32_t len, off, ct; + int res = 0; + int x,x1; + std::string::size_type offset, slen; + std::string oper = line.operand; + std::string s; + std::string operin; + TSymbol *sym; + uint32_t len, off, ct; - bool done = false; - operin = oper; - ct = 0; + bool done = false; + operin = oper; + ct = 0; + bool mac_var; restart: - while (!done) - { + while (!done) + { - slen = oper.length(); - if (slen > 0) - { - std::vector groups; + mac_var=false; + slen = oper.length(); + if (slen > 0) + { + std::vector groups; - offset = 0; - RegularExpression varEx(varExpression, 0, true); - Poco::RegularExpression::MatchVec mVec; + offset = 0; + RegularExpression varEx(varExpression, 0, true); + Poco::RegularExpression::MatchVec mVec; - //printf("|%s|%s|\n", varExpression.c_str(), oper.c_str()); - groups.clear(); - while (offset < slen) - { - try - { - varEx.match(oper, offset, mVec, 0); - } - catch (...) - { - offset = slen; - } + //printf("|%s|%s|\n", varExpression.c_str(), oper.c_str()); + groups.clear(); + while (offset < slen) + { + try + { + varEx.match(oper, offset, mVec, 0); + } + catch (...) + { + offset = slen; + } - x = (int)mVec.size(); - if (x > 0) - { - res = 0; - off = (uint32_t)mVec[0].offset; - len = (uint32_t)mVec[0].length; - s = oper.substr(off, len); - slen = s.length(); - sym = NULL; - if (expand_macrostack.size() > 0) - { - sym = findVariable(s, expand_macro.variables); - } - if (sym == NULL) - { - sym = findVariable(s, variables); - } - if (sym != NULL) - { - //printf("match |%s|\n",sym->var_text.c_str()); + x = (int)mVec.size(); + if (x > 0) + { + res = 0; + off = (uint32_t)mVec[0].offset; + len = (uint32_t)mVec[0].length; + s = oper.substr(off, len); + slen = s.length(); + sym = NULL; + if (expand_macrostack.size() > 0) + { + mac_var=true; + sym = findVariable(s, expand_macro.variables); + if (sym!=NULL) + { + RegularExpression varEx1(varMACExpression, 0, true); + Poco::RegularExpression::MatchVec mVec1; + try + { + varEx1.match(oper, 0, mVec1, 0); + x1 = (int)mVec1.size(); + if (x1>0) + { + mac_var=true; + //printf("Found MACvar: |%s| |%s|\n",sym->name.c_str(),sym->var_text.c_str()); + } + } + catch(...) + { - if (sym->var_text != "") - { - oper = oper.replace(off, len, sym->var_text); - slen = oper.length(); - ct++; - if (pass > 0) - { - //printf("%d |%s|\n", ct, s.c_str()); - } - goto restart; - } - } - else - { - done = true; - } - offset += len; - } - else - { - offset = slen; - done = true; - } - } + } - } - else - { - done = true; - } - } + } + } + else + { + //mac_var=true; + } + if (sym == NULL) + { + sym = findVariable(s, variables); + } + + if ((expand_macrostack.size() == 0) && (!mac_var)) + { + //mac_var=true; + } + + if ((sym != NULL) && (mac_var)) + { + //printf("match |%s|\n",sym->var_text.c_str()); + + if (sym->var_text != "") + { + oper = oper.replace(off, len, sym->var_text); + slen = oper.length(); + ct++; + if (pass > 0) + { + //printf("%d |%s|\n", ct, s.c_str()); + } + goto restart; + } + } + else + { + done = true; + } + offset += len; + } + else + { + offset = slen; + done = true; + } + } + + } + else + { + done = true; + } + } //printf("inoper=|%s| outoper=|%s|\n",operin.c_str(),oper.c_str()); - if (ct > 0) - { - outop = oper; - res = ct; - } - return (res); + if (ct > 0) + { + outop = oper; + res = ct; + } + return (res); } bool CLASS::doOFF(void) { - bool res = curDO.doskip; - std::stack tmpstack; - TDOstruct doitem; + bool res = curDO.doskip; + std::stack tmpstack; + TDOstruct doitem; - uint32_t ct = (uint32_t)DOstack.size(); - if (ct > 0) - { - tmpstack = DOstack; - } - while (ct > 0) - { - doitem = tmpstack.top(); - tmpstack.pop(); - if (doitem.doskip) - { - res = true; - } - ct--; - } - //printf("DOOFF: %d\n",res); - return (res); + uint32_t ct = (uint32_t)DOstack.size(); + if (ct > 0) + { + tmpstack = DOstack; + } + while (ct > 0) + { + doitem = tmpstack.top(); + tmpstack.pop(); + if (doitem.doskip) + { + res = true; + } + ct--; + } + //printf("DOOFF: %d\n",res); + return (res); } // this function determines if code generation is turned off (IF,DO,LUP,MAC, etc bool CLASS::codeSkipped(void) { - bool res = false; + bool res = false; - res = (curLUP.lupskip) ? true : res; - res = doOFF() ? true : res; - res = currentmacro.running ? true : res; + res = (curLUP.lupskip) ? true : res; + res = doOFF() ? true : res; + res = currentmacro.running ? true : res; - //printf("codeskip: %d\n",res); + //printf("codeskip: %d\n",res); - return (res); + return (res); } void CLASS::process(void) { #if 0 - uint32_t ct = lines.size(); - for (uint32_t lineno = 0; lineno < ct; lineno++) - { - //MerlinLine &line = lines.at(lineno); - //printf("|%s| |%s| |%s| |%s|\n", line.lable.c_str() - // , line.opcode.c_str(), line.operand.c_str(), line.comment.c_str()); - } + uint32_t ct = lines.size(); + for (uint32_t lineno = 0; lineno < ct; lineno++) + { + //MerlinLine &line = lines.at(lineno); + //printf("|%s| |%s| |%s| |%s|\n", line.lable.c_str() + // , line.opcode.c_str(), line.operand.c_str(), line.comment.c_str()); + } #else - uint32_t l; - int x;; - char c; - char buff[256]; - MerlinLine errLine; - std::string op, realop, operand, ls; + uint32_t l; + int x;; + char c; + char buff[256]; + MerlinLine errLine; + std::string op, realop, operand, ls; - pass = 0; - while (pass < 2) - { - initpass(); + pass = 0; + while (pass < 2) + { + initpass(); - l = (uint32_t)lines.size(); - bool passdone = false; - while ((!passdone) && (!passcomplete)) - { + l = (uint32_t)lines.size(); + bool passdone = false; + while ((!passdone) && (!passcomplete)) + { - MerlinLine *ml = NULL; - bool srcline = true; - if (expand_macro.running) - { - srcline = false; - if (expand_macro.currentline >= expand_macro.len) - { - // macro is complete - lineno = expand_macro.sourceline + 1; - if (expand_macrostack.size() > 0) - { - expand_macro = expand_macrostack.top(); - expand_macrostack.pop(); - } - else - { - expand_macro.clear(); - } - srcline = true; - } - else - { - ml = &expand_macro.lines[expand_macro.currentline]; - lineno = expand_macro.sourceline; - expand_macro.currentline++; - } - } - if (srcline) - { - if (lineno >= l) - { - passdone = true; - goto passout; - } - else - { - ml = &lines[lineno]; - } - } + MerlinLine *ml = NULL; + bool srcline = true; + if (expand_macro.running) + { + srcline = false; + if (expand_macro.currentline >= expand_macro.len) + { + // macro is complete + lineno = expand_macro.sourceline + 1; + if (expand_macrostack.size() > 0) + { + expand_macro = expand_macrostack.top(); + expand_macrostack.pop(); + } + else + { + expand_macro.clear(); + } + srcline = true; + } + else + { + ml = &expand_macro.lines[expand_macro.currentline]; + lineno = expand_macro.sourceline; + expand_macro.currentline++; + } + } + if (srcline) + { + if (lineno >= l) + { + passdone = true; + goto passout; + } + else + { + ml = &lines[lineno]; + } + } - MerlinLine &line = *ml; + MerlinLine &line = *ml; - //printf("lineno=%u %s\n", lineno, line.wholetext.c_str()); + //printf("lineno=%u %s\n", lineno, line.wholetext.c_str()); - line.eval_result = 0; - line.lineno = lineno + 1; - line.truncdata = truncdata; - memcpy(line.tabs, tabs, sizeof(tabs)); - //printf("lineno: %d %d |%s|\n",lineno,l,line.operand.c_str()); + line.eval_result = 0; + line.lineno = lineno + 1; + line.truncdata = truncdata; + memcpy(line.tabs, tabs, sizeof(tabs)); + //printf("lineno: %d %d |%s|\n",lineno,l,line.operand.c_str()); - op = Poco::toLower(line.opcode); - realop = line.opcode; - operand = Poco::toLower(line.operand); - line.startpc = PC.currentpc; - line.linemx = mx; - line.bytect = 0; - line.showmx = showmx; - line.syntax = syntax; - line.merlinerrors = merlinerrors; + op = Poco::toLower(line.opcode); + realop = line.opcode; + operand = Poco::toLower(line.operand); + line.startpc = PC.currentpc; + line.linemx = mx; + line.bytect = 0; + line.showmx = showmx; + line.syntax = syntax; + line.merlinerrors = merlinerrors; - if ((line.lable != "") && (op != "mac")) - { - std::string lable = Poco::trim(line.lable); - TSymbol *sym = NULL; - bool dupsym = false; - c = line.lable[0]; - switch (c) - { - case ']': - sprintf(buff, "$%X", PC.currentpc); - ls = buff; - sym = addVariable(line.lable, ls, variables, true); - //if (sym == NULL) { dupsym = true; } - break; + if ((line.lable != "") && (op != "mac")) + { + std::string lable = Poco::trim(line.lable); + TSymbol *sym = NULL; + bool dupsym = false; + c = line.lable[0]; + switch (c) + { + case ']': + sprintf(buff, "$%X", PC.currentpc); + ls = buff; + sym = addVariable(line.lable, ls, variables, true); + //if (sym == NULL) { dupsym = true; } + break; - case ':': - default: - if (pass == 0) - { - sym = addSymbol(line.lable, PC.currentpc, false); - if (sym == NULL) - { - dupsym = true; - line.setError(errDupSymbol); - } - } - if (c != ':') - { - currentsym = findSymbol(line.lable); - currentsymstr = line.lable; - } - break; - } - if (dupsym) - { - line.setError(errDupSymbol); - } - } - std::string outop; - line.printoperand = line.operand; - //printf("\nprintoperand: |%s|\n",line.printoperand.c_str()); - //printf("\noperand: |%s|\n",operand.c_str()); + case ':': + default: + if (pass == 0) + { + sym = addSymbol(line.lable, PC.currentpc, false); + if (sym == NULL) + { + dupsym = true; + line.setError(errDupSymbol); + } + } + if (c != ':') + { + currentsym = findSymbol(line.lable); + currentsymstr = line.lable; + } + break; + } + if (dupsym) + { + line.setError(errDupSymbol); + } + } + std::string outop; + line.printoperand = line.operand; + //printf("\nprintoperand: |%s|\n",line.printoperand.c_str()); + //printf("\noperand: |%s|\n",operand.c_str()); - x = 0; - if (macrostack.size() == 0) - { - x = substituteVariables(line, outop); - } - if (x > 0) - { - line.printoperand = outop; - line.operand = outop; - } - x = parseOperand(line); - if (x >= 0) - { - line.addressmode = x; - } + x = 0; + if (macrostack.size() == 0) + { + x = substituteVariables(line, outop); + } + if (x > 0) + { + line.printoperand = outop; + line.operand = outop; + } + x = parseOperand(line); + if (x >= 0) + { + line.addressmode = x; + } - int64_t value = -1; - x = evaluate(line, line.operand_expr, value); + int64_t value = -1; + x = evaluate(line, line.operand_expr, value); - line.eval_result = x; - if (x == 0) - { - value &= 0xFFFFFFFF; - line.expr_value = (uint32_t)value; - } - else - { - line.expr_value = 0; - } + line.eval_result = x; + if (x == 0) + { + value &= 0xFFFFFFFF; + line.expr_value = (uint32_t)value; + } + else + { + line.expr_value = 0; + } - x = 0; - if (op.length() > 0) - { - bool skipop = false; - if (doOFF()) - { - skipop = true; - if ((op == "fin") || (op == "else") || (op == "do") || (op == "if")) - { - skipop = false; - } - } - if (!skipop) - { - TMacro *mac = NULL; - bool inoperand = false; - if (macrostack.size() == 0) - { - mac = findMacro(realop); - if (mac == NULL) - { - if (op == ">>>") // specal merlin way of calling a macro - { - Poco::StringTokenizer tok(operand, ", ", Poco::StringTokenizer::TOK_TRIM | - Poco::StringTokenizer::TOK_IGNORE_EMPTY); - std::string s = ""; - if (tok.count() > 0) - { - s = tok[0]; - } - mac = findMacro(s); - inoperand = true; - } - } - } - if (mac == NULL) - { - x = callOpCode(op, line); - } - if (mac != NULL) - { - expand_macrostack.push(expand_macro); - expand_macro = *mac; + x = 0; + if (op.length() > 0) + { + bool skipop = false; + if (doOFF()) + { + skipop = true; + if ((op == "fin") || (op == "else") || (op == "do") || (op == "if")) + { + skipop = false; + } + } + if (!skipop) + { + TMacro *mac = NULL; + bool inoperand = false; + if (macrostack.size() == 0) + { + mac = findMacro(realop); + if (mac == NULL) + { + if (op == ">>>") // specal merlin way of calling a macro + { + Poco::StringTokenizer tok(operand, ", ", Poco::StringTokenizer::TOK_TRIM | + Poco::StringTokenizer::TOK_IGNORE_EMPTY); + std::string s = ""; + if (tok.count() > 0) + { + s = tok[0]; + } + mac = findMacro(s); + inoperand = true; + } + } + } + if (mac == NULL) + { + x = callOpCode(op, line); + } + if (mac != NULL) + { + expand_macrostack.push(expand_macro); + expand_macro = *mac; - expand_macro.lines.clear(); - //printf("mac start=%u end=%u\n", expand_macro.start, expand_macro.end); - for (uint32_t lc = expand_macro.start; lc < expand_macro.end; lc++) - { - //printf("pushing %s\n", lines[lc].wholetext.c_str()); - MerlinLine nl(lines[lc].wholetext); // create a new clean line (without errors,data) - expand_macro.lines.push_back(nl); - } - expand_macro.running = true; - expand_macro.sourceline = lineno; - expand_macro.variables.vars.clear(); - // set the variables for the macro here SGQ + expand_macro.lines.clear(); + //printf("mac start=%u end=%u\n", expand_macro.start, expand_macro.end); + for (uint32_t lc = expand_macro.start; lc < expand_macro.end; lc++) + { + //printf("pushing %s\n", lines[lc].wholetext.c_str()); + MerlinLine nl(lines[lc].wholetext); // create a new clean line (without errors,data) + expand_macro.lines.push_back(nl); + } + expand_macro.running = true; + expand_macro.sourceline = lineno; + expand_macro.variables.vars.clear(); + // set the variables for the macro here SGQ - std::string parms = line.operand; - if (inoperand) - { - Poco::StringTokenizer tok(parms, ", ", Poco::StringTokenizer::TOK_TRIM | - Poco::StringTokenizer::TOK_IGNORE_EMPTY); - parms = ""; - if (tok.count() > 1) - { - parms = tok[1]; - } - } - Poco::StringTokenizer tok(parms, ",;", Poco::StringTokenizer::TOK_TRIM | - Poco::StringTokenizer::TOK_IGNORE_EMPTY); + std::string parms = line.operand; + if (inoperand) + { + Poco::StringTokenizer tok(parms, ", ", Poco::StringTokenizer::TOK_TRIM | + Poco::StringTokenizer::TOK_IGNORE_EMPTY); + parms = ""; + if (tok.count() > 1) + { + parms = tok[1]; + } + } + Poco::StringTokenizer tok(parms, ",;", Poco::StringTokenizer::TOK_TRIM | + Poco::StringTokenizer::TOK_IGNORE_EMPTY); - uint32_t ct = 0; - for (auto itr = tok.begin(); itr != tok.end(); ++itr) - { - //evaluate each of these strings, check for errors on pass 2 - std::string expr = *itr; - std::string v = "]" + Poco::NumberFormatter::format(ct + 1); - //printf("var: %s %s\n", v.c_str(), expr.c_str()); - addVariable(v, expr, expand_macro.variables, true); - ct++; - } - x = 0; - expand_macro.currentline = 0; - } - } - } + uint32_t ct = 0; + for (auto itr = tok.begin(); itr != tok.end(); ++itr) + { + //evaluate each of these strings, check for errors on pass 2 + std::string expr = *itr; + std::string v = "]" + Poco::NumberFormatter::format(ct + 1); + //printf("var: %s %s\n", v.c_str(), expr.c_str()); + addVariable(v, expr, expand_macro.variables, true); + ct++; + } + x = 0; + expand_macro.currentline = 0; + } + } + } - if ((x > 0) && (codeSkipped())) // has a psuedo-op turned off code generation? (LUP, IF, etc) - { - x = 0; - line.outbytect = 0; - } + if ((x > 0) && (codeSkipped())) // has a psuedo-op turned off code generation? (LUP, IF, etc) + { + x = 0; + line.outbytect = 0; + } - if (x > 0) - { - if (!PCstack.empty()) // are we inside a DUM section? - { - line.flags |= FLAG_INDUM; - } - if ((line.eval_result != 0) && (pass > 0)) - { - line.setError(errBadOperand); - line.errorText = line.operand_expr; - } - line.bytect = x; - PC.currentpc += x; - PC.totalbytes += x; - } - if (pass == 0) - { - line.pass0bytect = line.bytect; - } + if (x > 0) + { + if (!PCstack.empty()) // are we inside a DUM section? + { + line.flags |= FLAG_INDUM; + } + if ((line.eval_result != 0) && (pass > 0)) + { + line.setError(errBadOperand); + line.errorText = line.operand_expr; + } + line.bytect = x; + PC.currentpc += x; + PC.totalbytes += x; + } + if (pass == 0) + { + line.pass0bytect = line.bytect; + } - if (dumstart > 0) // starting a dummy section - { - PCstack.push(PC); - PC.origin = dumstartaddr; - PC.currentpc = PC.origin; - dumstart = 0; - dumstartaddr = 0; - } - if (dumstart < 0) - { - PC = PCstack.top(); - PCstack.pop(); - dumstart = 0; - dumstartaddr = 0; - } + if (dumstart > 0) // starting a dummy section + { + PCstack.push(PC); + PC.origin = dumstartaddr; + PC.currentpc = PC.origin; + dumstart = 0; + dumstartaddr = 0; + } + if (dumstart < 0) + { + PC = PCstack.top(); + PCstack.pop(); + dumstart = 0; + dumstartaddr = 0; + } - if (pass == 1) - { - if ((line.pass0bytect != line.bytect) && (line.errorcode == 0)) - { - if (expand_macrostack.size() == 0) // if macro expanding, you can't make this check - { - line.setError(errBadByteCount); - } - } + if (pass == 1) + { + if ((line.pass0bytect != line.bytect) && (line.errorcode == 0)) + { + if (expand_macrostack.size() == 0) // if macro expanding, you can't make this check + { + line.setError(errBadByteCount); + } + } - if (line.errorcode != 0) - { - errorct++; - } - if (((!skiplist) && (listing) && (pass == 1)) || (line.errorcode != 0)) - { - line.print(lineno); - } - skiplist = false; - } - lineno++; - } + if (line.errorcode != 0) + { + errorct++; + } + if (((!skiplist) && (listing) && (pass == 1)) || (line.errorcode != 0)) + { + line.print(lineno); + } + skiplist = false; + } + lineno++; + } passout: - // end of file reached here, do some final checks + // end of file reached here, do some final checks #if 0 - if (LUPstack.size() > 0) - { - errLine.clear(); - errLine.setError(errUnexpectedEOF); - errLine.print(lineno); - pass = 2; - } + if (LUPstack.size() > 0) + { + errLine.clear(); + errLine.setError(errUnexpectedEOF); + errLine.print(lineno); + pass = 2; + } #endif - pass++; - } + pass++; + } #endif } int CLASS::doline(int lineno, std::string line) { - int res = 0; - int x; - std::string op; + int res = 0; + int x; + std::string op; - UNUSED(lineno); + UNUSED(lineno); - MerlinLine l(line); + MerlinLine l(line); - op = Poco::toLower(l.opcode); - if (op == "merlin") - { - syntax = SYNTAX_MERLIN; - } - else if (op == "orca") - { - syntax = SYNTAX_ORCA; - } - l.syntax = syntax; - lines.push_back(l); + op = Poco::toLower(l.opcode); + if (op == "merlin") + { + syntax = SYNTAX_MERLIN; + } + else if (op == "orca") + { + syntax = SYNTAX_ORCA; + } + l.syntax = syntax; + lines.push_back(l); - if ((op == "use") || (op == "put")) - { - std::string fn; - x = processfile(l.operand, fn); - //printf("processfile : %d\n",x); - if (x < 0) - { - switch (x) - { - case -9: - l.setError(errDuplicateFile); - break; - case -3: - l.setError(errFileNotFound); - break; - case -2: - l.setError(errFileNoAccess); - break; - default: - l.setError(errFileNotFound); - break; - } - l.operand = fn; - l.print(0); - errorct++; - res = -1; - } - } + if ((op == "use") || (op == "put")) + { + std::string fn; + x = processfile(l.operand, fn); + //printf("processfile : %d\n",x); + if (x < 0) + { + switch (x) + { + case -9: + l.setError(errDuplicateFile); + break; + case -3: + l.setError(errFileNotFound); + break; + case -2: + l.setError(errFileNoAccess); + break; + default: + l.setError(errFileNotFound); + break; + } + l.operand = fn; + l.print(0); + errorct++; + res = -1; + } + } - return (res); + return (res); } #undef CLASS @@ -2543,7 +2663,7 @@ CLASS::~CLASS() void CLASS::init(void) { - TFileProcessor::init(); + TFileProcessor::init(); } void CLASS::process(void) @@ -2556,12 +2676,12 @@ void CLASS::complete(void) int CLASS::doline(int lineno, std::string line) { - UNUSED(lineno); - UNUSED(line); + UNUSED(lineno); + UNUSED(line); - int res = 0; + int res = 0; - return (res); + return (res); } #undef CLASS diff --git a/asm.h b/asm.h index a246ea5..ea844bf 100644 --- a/asm.h +++ b/asm.h @@ -15,6 +15,8 @@ #define SYNTAX_MPW 0x08 #define SYNTAX_ORCA 0x10 #define SYNTAX_CC65 0x20 +#define SYNTAX_LISA 0x40 + #define SYNTAX_QASM (0x80 | SYNTAX_MERLIN) #define OPTION_ALLOW_A_OPERAND 0x0100 #define OPTION_ALLOW_LOCAL 0x0200 @@ -23,7 +25,7 @@ #define OPTION_NO_REPSEP 0x1000 #define OPTION_CFG_REPSEP 0x2000 #define OPTION_M32_VARS 0x4000 - +#define OPTION_M16_PLUS 0x8000 #define FLAG_FORCELONG 0x01 #define FLAG_FORCEABS 0x02 @@ -201,6 +203,7 @@ public: std::string printoperand; std::string opcode; std::string opcodelower; + std::string orig_operand; std::string operand; std::string operand_expr; std::string operand_expr2; @@ -254,6 +257,7 @@ protected: public: uint32_t errorct; std::string filename; + uint32_t format_flags; TFileProcessor(); virtual ~TFileProcessor(); @@ -267,18 +271,18 @@ public: virtual void setSyntax(uint32_t syn); }; -class TImageProcessor : public TFileProcessor -{ -protected: - std::vector lines; -public: - TImageProcessor(); - virtual ~TImageProcessor(); - virtual int doline(int lineno, std::string line); - virtual void process(void); - virtual void complete(void); -}; +#define CONVERT_NONE 0x00 +#define CONVERT_LF 0x01 +#define CONVERT_CRLF 0x02 +#define CONVERT_COMPRESS 0x04 +#define CONVERT_HIGH 0x08 +#define CONVERT_MERLIN (CONVERT_HIGH|CONVERT_COMPRESS) +#define CONVERT_LINUX (CONVERT_LF) +#define CONVERT_WINDOWS (CONVERT_CRLF) +#define CONVERT_APW (CONVERT_NONE) +#define CONVERT_MPW (CONVERT_NONE) +#define CONVERT_TEST (CONVERT_COMPRESS|CONVERT_LF) class TMerlinConverter : public TFileProcessor { diff --git a/cider.cpp b/cider.cpp index f7d6a8f..8c30468 100644 --- a/cider.cpp +++ b/cider.cpp @@ -1,3 +1,5 @@ +#ifdef CIDERPRESS + #include "asm.h" #include "eval.h" #include "psuedo.h" @@ -7,6 +9,9 @@ #include #include +#include + +#undef CLASS #define CLASS CiderPress using namespace DiskImgLib; @@ -14,49 +19,76 @@ using DiskImgLib::DiskImg; void dbgMessage(const char *file, int line, const char *msg) { - - printf("DEBUG: %s\n",msg); + if (isDebug()>0) + { + printf("DEBUG: %s\n",msg); + } } -CLASS::CLASS() +CLASS::CLASS() : TFileProcessor() { - if (!Global::GetAppInitCalled()) - { - DiskImgLib::Global::SetDebugMsgHandler(dbgMessage); + if (!Global::GetAppInitCalled()) + { + DiskImgLib::Global::SetDebugMsgHandler(dbgMessage); DiskImgLib::Global::AppInit(); - } + } +} + +CLASS::~CLASS() +{ + } int CLASS::RunScript(string path) { - int res=-1; + int res=-1; - - return(res); + + return(res); } int CLASS::CreateVolume(string OSName, string VolName, uint64_t size, CIDER_VOLFORMAT format) { - int interr=-1; - DIError err; - DiskImg *img=new DiskImg(); - if (format==CP_PRODOS) - { + int interr=-1; + DIError err; + DiskImg *img=new DiskImg(); + if (format==CP_PRODOS) + { - err=img->CreateImage(OSName.c_str(),VolName.c_str(), - DiskImg::kOuterFormatNone, - DiskImg::kFileFormat2MG, - DiskImg::kPhysicalFormatSectors, - NULL, - DiskImg::kSectorOrderProDOS, - DiskImg::kFormatGenericProDOSOrd, - size/256, - false - ); - printf("create error: %d\n",err); - if (err== kDIErrNone ) - interr=0; - } - return (interr); + err=img->CreateImage(OSName.c_str(),VolName.c_str(), + DiskImg::kOuterFormatNone, + DiskImg::kFileFormat2MG, + DiskImg::kPhysicalFormatSectors, + NULL, + DiskImg::kSectorOrderProDOS, + DiskImg::kFormatGenericProDOSOrd, + size/256, + false + ); + printf("create error: %d\n",err); + if (err== kDIErrNone ) + { + interr=0; + } + } + return (interr); } + +int CLASS::doline(int lineno, std::string line) +{ + printf("%05d: %s\n",lineno,line.c_str()); + return(0); +} +void CLASS::process(void) +{ + +} +void CLASS::complete(void) +{ + +} + +#undef CLASS + +#endif \ No newline at end of file diff --git a/cider.h b/cider.h index f006dfc..f3bd6d5 100644 --- a/cider.h +++ b/cider.h @@ -1,3 +1,4 @@ +#ifdef CIDERPRESS #pragma once #include "asm.h" @@ -10,13 +11,20 @@ #define CLASS CiderPress -enum CIDER_VOLFORMAT {CP_PRODOS,CP_HFS}; -class CLASS +enum CIDER_VOLFORMAT {CP_PRODOS,CP_HFS}; +class CLASS : public TFileProcessor { - public: - CLASS(); - int CreateVolume(string OSName, string VolName, uint64_t size, CIDER_VOLFORMAT format); - int RunScript(string path); +protected: + std::vector lines; +public: + CLASS(); + virtual ~CLASS(); + int CreateVolume(string OSName, string VolName, uint64_t size, CIDER_VOLFORMAT format); + int RunScript(string path); + virtual int doline(int lineno, std::string line); + virtual void process(void); + virtual void complete(void); }; -#undef CLASS \ No newline at end of file +#undef CLASS +#endif \ No newline at end of file diff --git a/eval.cpp b/eval.cpp index 9975379..c34beff 100644 --- a/eval.cpp +++ b/eval.cpp @@ -607,7 +607,7 @@ int CLASS::evaluate(std::string & e, int64_t &res, uint8_t &_shiftmode) std::string expr = Poco::trim(e); expr += " "; // add a space at end to make parsing easier - if (isDebug() >= 4) + if (isDebug() >= 1) { printf("eval: expression: |%s|\n", expr.c_str()); } diff --git a/merlintests.sh b/merlintests.sh index 1d3d03d..3d8c68e 100755 --- a/merlintests.sh +++ b/merlintests.sh @@ -22,7 +22,9 @@ for S in $SRC ; do S1=${S1/.s/} cd ./testdata - merlin32$X . $S 2>/dev/null >/dev/null + #merlin32$X . $S 2>/dev/null >/dev/null + merlin32$X -V . $S + #merlin32 . $S 2>/dev/null R=?$ diff --git a/opcodes.cpp b/opcodes.cpp index 3226664..4c2d760 100644 --- a/opcodes.cpp +++ b/opcodes.cpp @@ -12,6 +12,7 @@ void CLASS::setOpcode(MerlinLine &line, uint8_t op) uint8_t m = opCodeCompatibility[op]; if ((m > 0) && (cpumode < MODE_65C02)) // if the instruction is non-zero, and we are in 6502 base mode, error { + //printf("incompatable: %02X %02X\n",op,m); if (line.errorcode == 0) // don't replace other errors { line.setError(errIncompatibleOpcode); @@ -706,7 +707,8 @@ int CLASS::doBase6502(MerlinLine & line, TSymbol & sym) if (err) // not a 6502 address mode { - if (cpumode >= MODE_65816) + //if (cpumode >= MODE_65816) + if (cpumode >= MODE_65C02) { cc = 0x03; err = false; @@ -950,6 +952,7 @@ void CLASS::insertOpcodes(void) pushopcode("MVP", 0x01, 0, OPHANDLER(&CLASS::doMVN)); pushopcode("NOP", 0xEA, 0, OPHANDLER(&CLASS::doBYTE)); pushopcode("ORA", 0x00, OP_STD | OP_A, OPHANDLER(&CLASS::doBase6502)); + pushopcode("PEA", 0xF4, 2, OPHANDLER(&CLASS::doAddress)); pushopcode("PEI", 0xD4, 1, OPHANDLER(&CLASS::doAddress)); pushopcode("PER", 0x62, 2, OPHANDLER(&CLASS::doPER)); diff --git a/parms.json b/parms.json index 6da923e..df3eb64 100644 --- a/parms.json +++ b/parms.json @@ -1,6 +1,7 @@ { "version": "1.1", "general": { + "color_output": true, "prefix": [ { "0": "${PWD}" @@ -16,16 +17,27 @@ } ] }, - "assembler": { - "cpu_default": "6502", - "syntax": "merlin", - "listmode": "on" + "asm": { + "syntax": "merlin16plus", //merlin8, merlin16, merlin16plus,merlin32 + "cpu": "M6502", + "startmx": 3, + "listmode": "on", + "casesend": true, + "lst": false, + "showmx": true, + "allowduplicate": true, + "trackrep": false, + "merlinerrors": true, + "m32vars": false, + "allowA": true, + "allowLocal": true, + "allowColon": true, + "repsep": "force", //force,no,cfg + "linebytes": 4, + "line2bytes": 8 }, "linker": {}, "format": { - "tabs": "12,18,30" - }, - "diskimg": { - "script": "./disk_commands.txt" + "tabs": "12,18,30,48" } } \ No newline at end of file diff --git a/psuedo.cpp b/psuedo.cpp index 5145891..fdae7e5 100644 --- a/psuedo.cpp +++ b/psuedo.cpp @@ -944,6 +944,10 @@ int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) if (dci && (i == lastdelimidx)) { + // SGQ BUG - Merlin16+ does it like Merlin32 and now does the last + // byte not the way merlin816 and earlier do it documented below. + // use OPTION_M16_PLUS when implemented. + //lr - Merlin only toggles the high bit of string chars, not hex values // 8D,'Hello',8D,'there',8D becomes 8D 48 65 6C 6C 6F 8D 74 68 65 72 E5 // diff --git a/qasm.cpp b/qasm.cpp index a7cc4d6..32d21b7 100644 --- a/qasm.cpp +++ b/qasm.cpp @@ -20,7 +20,7 @@ programOption PAL::appOptions[] = { "debug", "d", "enable debug info (repeat for more verbosity)", "", false, true}, #endif //{ "config", "f", "load configuration data from a ", "", false, false}, - { "exec", "x", "execute a command [asm, link, reformat, script] default=asm", "", false, false}, + { "exec", "x", "execute a command [asm, link, format, script] default=asm", "", false, false}, { "objfile", "o", "write output to file", "", false, false}, { "syntax", "s", "enforce syntax of other assembler [qasm, merlin, merlin32, ORCA, APW, MPW, CC65]", "", false, false}, @@ -101,7 +101,7 @@ int CLASS::runCommandLineApp(void) syn=Poco::toUpper(syn); syn=Poco::trim(syn); syntax=SYNTAX_QASM; - if ((syn=="MERLIN") || (syn=="MERLIN16") || (syn=="MERLIN8") || (syn=="MERLIN16+")) + if ((syn=="MERLIN") || (syn=="MERLIN16") || (syn=="MERLIN8") || (syn=="MERLIN16PLUS")) { syntax=SYNTAX_MERLIN; } @@ -130,7 +130,7 @@ int CLASS::runCommandLineApp(void) syntax=SYNTAX_CC65; } - printf("SYNTAX: |%s|\n",syn.c_str()); + //printf("SYNTAX: |%s|\n",syn.c_str()); try { @@ -148,6 +148,7 @@ int CLASS::runCommandLineApp(void) for (ArgVec::const_iterator it = commandargs.begin(); it != commandargs.end(); ++it) { + int32_t format_flags=CONVERT_LINUX; Poco::File fn(*it); int x; std::string p = fn.path(); @@ -158,10 +159,50 @@ int CLASS::runCommandLineApp(void) std::string cmd = Poco::toUpper(getConfig("option.exec", "asm")); - //printf("DEBUG=%d\n",isDebug()); + Poco::StringTokenizer toks(cmd,"-"); + if (toks.count()>1) + { + if (toks[0]=="FORMAT") + { + if (toks[1]=="LINUX") + { + format_flags=CONVERT_LINUX; + } + else if (toks[1]=="WINDOWS") + { + format_flags=CONVERT_WINDOWS; + } + else if (toks[1]=="MERLIN") + { + format_flags=CONVERT_MERLIN; + } + else if (toks[1]=="APW") + { + format_flags=CONVERT_APW; + } + else if (toks[1]=="MPW") + { + format_flags=CONVERT_MPW; + } + else if (toks[1]=="MAC") + { + format_flags=CONVERT_LINUX; + } + else if (toks[1]=="CC65") + { + format_flags=CONVERT_LINUX; + } + else if (toks[1]=="COMPRESS") + { + format_flags=CONVERT_TEST; + } + + cmd=toks[0]; + } + } if (cmd.length() > 0) { - if (cmd == "REFORMAT") + if (cmd == "FORMAT") { res = 0; t = new TMerlinConverter(); @@ -171,6 +212,7 @@ int CLASS::runCommandLineApp(void) { t->init(); t->setSyntax(syntax); + t->format_flags=format_flags; std::string f = path.toString(); t->filename = f; @@ -233,7 +275,7 @@ int CLASS::runCommandLineApp(void) else if (cmd == "SCRIPT") { res = 0; - t = new TImageProcessor(); + t = new CiderPress(); if (t!=NULL) { try diff --git a/testdata/1000-allops-value-65816.S b/testdata/1000-allops-value-65816.S index dc67504..46619a3 100644 --- a/testdata/1000-allops-value-65816.S +++ b/testdata/1000-allops-value-65816.S @@ -2,6 +2,10 @@ ; See the LICENSE.txt file for distribution terms (Apache 2.0). ; ; Assembler: Merlin 32 + xc off + xc + xc + mx %00 ZP EQU $FF ABS EQU $FEFF LONG EQU $FDFEFF diff --git a/testdata/1001-allops-zero-65816.S b/testdata/1001-allops-zero-65816.S index cd67505..145d9d3 100644 --- a/testdata/1001-allops-zero-65816.S +++ b/testdata/1001-allops-zero-65816.S @@ -3,6 +3,10 @@ ; ; Assembler: Merlin 32 + xc off + xc + xc + mx %00 ZP EQU $00 ABS EQU $0000 LONG EQU $000000 diff --git a/testdata/1002-embedded-instructions.S b/testdata/1002-embedded-instructions.S index 71c596a..64abad1 100644 --- a/testdata/1002-embedded-instructions.S +++ b/testdata/1002-embedded-instructions.S @@ -1,110 +1,114 @@ -; Copyright 2018 faddenSoft. All Rights Reserved. -; See the LICENSE.txt file for distribution terms (Apache 2.0). -; -; Assembler: Merlin 32 + ; Copyright 2018 faddenSoft. All Rights Reserved. + ; See the LICENSE.txt file for distribution terms (Apache 2.0). + ; + ; Assembler: Merlin 32 - org $1000 + xc off + xc + xc + mx %11 + org $1000 -; 65816 mode with short regs - clc - xce - sep #$30 - mx %11 + ; 65816 mode with short regs + clc + xce + sep #$30 + mx %11 - jsr test1 - jsr test2 - jsr test3 - jsr test4 - jsr test5 - rts + jsr test1 + jsr test2 + jsr test3 + jsr test4 + jsr test5 + rts -; TEST #1: simple example -test1 lda #$00 - dfb $2c ;BIT abs -:inner lda #$01 - beq :inner - rts + ; TEST #1: simple example +test1 lda #$00 + dfb $2c ;BIT abs +:inner lda #$01 + beq :inner + rts -; TEST #2: embedded with break path -; -; Example inspired by incorrect analysis... -; -; The code analyzer sees: -; beq {+03} ;jumps to the $8f -; lda #$00 -; brk $8f -; and stops, then pursues the branch. If we try to walk from top -; to bottom, skipping forward by the full length of an instruction, -; we'll appear to find ourselves in the middle of an embedded -; instruction. -; -; This is different from the typical embedded instruction, -; where the inner is contained entirely within the outer. -test2 sep #$30 ;short regs - mx %00 ;pretend they're long + ; TEST #2: embedded with break path + ; + ; Example inspired by incorrect analysis... + ; + ; The code analyzer sees: + ; beq {+03} ;jumps to the $8f + ; lda #$00 + ; brk $8f + ; and stops, then pursues the branch. If we try to walk from top + ; to bottom, skipping forward by the full length of an instruction, + ; we'll appear to find ourselves in the middle of an embedded + ; instruction. + ; + ; This is different from the typical embedded instruction, + ; where the inner is contained entirely within the outer. +test2 sep #$30 ;short regs + mx %00 ;pretend they're long - lda $00 ;load something to scramble flags - beq :store - lda #$0000 -:store stal $012345 - rts + lda $00 ;load something to scramble flags + beq :store + lda #$0000 +:store stal $012345 + rts -; TEST #3: embedded with non-instruction byte -; -; The code analyzer sees two paths, involving the three bytes. -; The first is the three-byte JSR, the second is the one-byte -; RTS. The third NOP byte is never "executed" by the analyzer, -; but because of the way we display embedded instructions it -; gets put on its own line. Since it's not an instruction start -; or a data item, things get confused. (This is referred to as -; an "embedded orphan" in the code.) + ; TEST #3: embedded with non-instruction byte + ; + ; The code analyzer sees two paths, involving the three bytes. + ; The first is the three-byte JSR, the second is the one-byte + ; RTS. The third NOP byte is never "executed" by the analyzer, + ; but because of the way we display embedded instructions it + ; gets put on its own line. Since it's not an instruction start + ; or a data item, things get confused. (This is referred to as + ; an "embedded orphan" in the code.) -test3 dfb $20 ;JSR -:mid dfb $60 ;RTS - dfb $ea ;NOP - bra :mid +test3 dfb $20 ;JSR +:mid dfb $60 ;RTS + dfb $ea ;NOP + bra :mid -; TEST #4: overlapping chain -; -; Each BIT instruction is three bytes, and each byte is a branch target, -; so we get a string of embedded instructions. + ; TEST #4: overlapping chain + ; + ; Each BIT instruction is three bytes, and each byte is a branch target, + ; so we get a string of embedded instructions. test4 -:bits hex 2c2c2c2c2c2c2c2c2ceaea - asl - bcc :bits - asl - bcc :bits+1 - asl - bcc :bits+2 - asl - bcc :bits+3 - asl - bcc :bits+4 - asl - bcc :bits+5 - asl - bcc :bits+6 - asl - bcc :bits+7 - asl - bcc :bits+8 - asl - bcc :bits+9 - rts +:bits hex 2c2c2c2c2c2c2c2c2ceaea + asl + bcc :bits + asl + bcc :bits+1 + asl + bcc :bits+2 + asl + bcc :bits+3 + asl + bcc :bits+4 + asl + bcc :bits+5 + asl + bcc :bits+6 + asl + bcc :bits+7 + asl + bcc :bits+8 + asl + bcc :bits+9 + rts -; TEST #5: another overlap -; -; Trying to be a little different. -test5 dfb $2c -:mid1 nop - hex ad -:mid2 lda $00 - asl - bcc :mid1 - asl - bcc :mid2 + ; TEST #5: another overlap + ; + ; Trying to be a little different. +test5 dfb $2c +:mid1 nop + hex ad +:mid2 lda $00 + asl + bcc :mid1 + asl + bcc :mid2 -; TEST #6: "embedded" off the end of the file - dfb $af ;ldal + ; TEST #6: "embedded" off the end of the file + dfb $af ;ldal diff --git a/testdata/1003-flags-and-branches.S b/testdata/1003-flags-and-branches.S index 059510f..6495b4b 100644 --- a/testdata/1003-flags-and-branches.S +++ b/testdata/1003-flags-and-branches.S @@ -2,7 +2,9 @@ ; See the LICENSE.txt file for distribution terms (Apache 2.0). ; ; Assembler: Merlin 32 - + xc off + xc + xc org $1000 clc xce diff --git a/testdata/2000-allops-value-6502.S b/testdata/2000-allops-value-6502.S index 3fd0a81..691bd68 100644 --- a/testdata/2000-allops-value-6502.S +++ b/testdata/2000-allops-value-6502.S @@ -1,8 +1,8 @@ -; Copyright 2018 faddenSoft. All Rights Reserved. -; See the LICENSE.txt file for distribution terms (Apache 2.0). -; -; Assembler: Merlin 32 - + ; Copyright 2018 faddenSoft. All Rights Reserved. + ; See the LICENSE.txt file for distribution terms (Apache 2.0). + ; + ; Assembler: Merlin 32 + xc off ZP EQU $FF ABS EQU $FEFF diff --git a/testdata/2002-allops-value-65C02.S b/testdata/2002-allops-value-65C02.S index 563694c..44d0399 100644 --- a/testdata/2002-allops-value-65C02.S +++ b/testdata/2002-allops-value-65C02.S @@ -2,7 +2,9 @@ ; See the LICENSE.txt file for distribution terms (Apache 2.0). ; ; Assembler: Merlin 32 - + xc off + xc + ;xc ZP EQU $FF ABS EQU $FEFF diff --git a/testdata/2003-allops-zero-65C02.S b/testdata/2003-allops-zero-65C02.S index c4b330a..6736e6e 100644 --- a/testdata/2003-allops-zero-65C02.S +++ b/testdata/2003-allops-zero-65C02.S @@ -2,7 +2,9 @@ ; See the LICENSE.txt file for distribution terms (Apache 2.0). ; ; Assembler: Merlin 32 - + xc off + xc + ZP EQU $00 ABS EQU $0000 diff --git a/testdata/3008-macro-strings.S b/testdata/3008-macro-strings.S index 6bd9863..4b2f077 100644 --- a/testdata/3008-macro-strings.S +++ b/testdata/3008-macro-strings.S @@ -12,3 +12,4 @@ xx mac xx "hello" xx 'abc',00 xx ff + diff --git a/testdata/allops-common-6502.S b/testdata/allops-common-6502.S index 888a9ae..659808c 100644 --- a/testdata/allops-common-6502.S +++ b/testdata/allops-common-6502.S @@ -1,7 +1,7 @@ -; Copyright 2018 faddenSoft. All Rights Reserved. -; See the LICENSE.txt file for distribution terms (Apache 2.0). -; -; Assembler: Merlin 32 + ; Copyright 2018 faddenSoft. All Rights Reserved. + ; See the LICENSE.txt file for distribution terms (Apache 2.0). + ; + ; Assembler: Merlin 32 ORG $1000 @@ -24,7 +24,7 @@ NOP NOP NOP - BRK ZP ;$00 + BRK ZP ;$00 PostBRK ORA (ZP,X) DFB $02 PostH02 DFB $03,ZP @@ -40,7 +40,7 @@ PostH02 DFB $03,ZP ORA: ABS ASL: ABS DFB $0F,#ABS - BPL PostBPL ;$10 + BPL PostBPL ;$10 PostBPL ORA (ZP),Y DFB $12 PostH12 DFB $13,ZP @@ -56,7 +56,7 @@ PostH12 DFB $13,ZP ORA: ABS,X ASL: ABS,X DFB $1F,#ABS - JSR ABS ;$20 + JSR ABS ;$20 AND (ZP,X) DFB $22 PostH22 DFB $23,ZP @@ -72,7 +72,7 @@ PostH22 DFB $23,ZP AND: ABS ROL: ABS DFB $2F,#ABS - BMI PostBMI ;$30 + BMI PostBMI ;$30 PostBMI AND (ZP),Y DFB $32 PostH32 DFB $33,ZP @@ -84,11 +84,11 @@ PostH32 DFB $33,ZP AND: ABS,Y DFB $3A DFB $3B,#ABS - BIT: ABS,X + ;BIT: ABS,X // not available on standard 6502 (but is on 65C02) AND: ABS,X ROL: ABS,X DFB $3F,#ABS - RTI ;$40 + RTI ;$40 PostRTI EOR (ZP,X) DFB $42 PostH42 DFB $43,ZP @@ -104,7 +104,7 @@ PostH42 DFB $43,ZP PostJMP EOR: ABS LSR: ABS DFB $4f,#ABS - BVC PostBVC ;$50 + BVC PostBVC ;$50 PostBVC EOR (ZP),Y DFB $52 PostH52 DFB $53,ZP @@ -120,7 +120,7 @@ PostH52 DFB $53,ZP EOR: ABS,X LSR: ABS,X DFB $5F,#ABS - RTS ;$60 + RTS ;$60 PostRTS ADC (ZP,X) DFB $62 PostH62 DFB $63,ZP @@ -136,7 +136,7 @@ PostH62 DFB $63,ZP PostJMPI ADC: ABS ROR: ABS DFB $6F,#ABS - BVS PostBVS ;$70 + BVS PostBVS ;$70 PostBVS ADC (ZP),Y DFB $72 PostH72 DFB $73,ZP @@ -152,7 +152,7 @@ PostH72 DFB $73,ZP ADC: ABS,X ROR: ABS,X DFB $7F,#ABS - DFB $80,ZP ;$80 + DFB $80,ZP ;$80 STA (ZP,X) DFB $82,ZP DFB $83,ZP @@ -168,7 +168,7 @@ PostH72 DFB $73,ZP STA: ABS STX: ABS DFB $8F,#ABS - BCC PostBCC ;$90 + BCC PostBCC ;$90 PostBCC STA (ZP),Y DFB $92 PostH92 DFB $93,ZP @@ -184,7 +184,7 @@ PostH92 DFB $93,ZP STA: ABS,X DFB $9E,#ABS DFB $9F,#ABS - LDY #ZP ;$A0 + LDY #ZP ;$A0 LDA (ZP,X) LDX #ZP DFB $A3,ZP @@ -200,7 +200,7 @@ PostH92 DFB $93,ZP LDA: ABS LDX: ABS DFB $AF,#ABS - BCS PostBCS ;$B0 + BCS PostBCS ;$B0 PostBCS LDA (ZP),Y DFB $B2 PostHB2 DFB $B3,ZP @@ -216,7 +216,7 @@ PostHB2 DFB $B3,ZP LDA: ABS,X LDX: ABS,Y DFB $BF,#ABS - CPY #ZP ;$C0 + CPY #ZP ;$C0 CMP (ZP,X) DFB $C2,ZP DFB $C3,ZP @@ -232,7 +232,7 @@ PostHB2 DFB $B3,ZP CMP: ABS DEC: ABS DFB $CF,#ABS - BNE PostBNE ;$D0 + BNE PostBNE ;$D0 PostBNE CMP (ZP),Y DFB $D2 PostHD2 DFB $D3,ZP @@ -248,7 +248,7 @@ PostHD2 DFB $D3,ZP L11FC CMP: ABS,X DEC: ABS,X DFB $DF,#ABS - CPX #ZP ;$E0 + CPX #ZP ;$E0 SBC (ZP,X) DFB $E2,ZP DFB $E3,ZP @@ -264,7 +264,7 @@ L11FC CMP: ABS,X SBC: ABS INC: ABS DFB $EF,#ABS - BEQ PostBEQ ;$F0 + BEQ PostBEQ ;$F0 PostBEQ SBC (ZP),Y DFB $F2 PostHF2 DFB $F3,ZP diff --git a/testdata/allops-common-65816.S b/testdata/allops-common-65816.S index 1b895f8..6dae000 100644 --- a/testdata/allops-common-65816.S +++ b/testdata/allops-common-65816.S @@ -5,6 +5,7 @@ ORG $1000 + mx %00 SEC XCE JSR L101F diff --git a/testdata/allops-common-65C02.S b/testdata/allops-common-65C02.S index 40f014e..0ceed52 100644 --- a/testdata/allops-common-65C02.S +++ b/testdata/allops-common-65C02.S @@ -1,6 +1,5 @@ ; Copyright 2018 faddenSoft. All Rights Reserved. ; See the LICENSE.txt file for distribution terms (Apache 2.0). -; ; Assembler: Merlin 32 ORG $1000 diff --git a/util.cpp b/util.cpp index fd2f335..1dcd80a 100644 --- a/util.cpp +++ b/util.cpp @@ -9,3 +9,4 @@ bool isMerlin816(void) { return(true); } +