From 5302a2c5148bdc2ad7b1d85f66153c2f508a34a9 Mon Sep 17 00:00:00 2001 From: marketideas Date: Fri, 15 Nov 2019 05:31:42 -0800 Subject: [PATCH 01/26] merge from SGQ branch --- CMakeLists.txt | 10 +- Makefile | 16 +- asm.cpp | 634 ++++++++++++++++++++++++++++++++++++++----------- asm.h | 27 ++- config.h | 15 +- eval.cpp | 5 +- opcodes.cpp | 37 ++- psuedo.cpp | 218 +++++++++++++---- psuedo.h | 8 +- qasm.cpp | 134 ++++++++--- qasm.h | 3 + qasm.ini | 13 +- src/main.s | 30 ++- src/var.s | 25 ++ 14 files changed, 917 insertions(+), 258 deletions(-) create mode 100644 src/var.s diff --git a/CMakeLists.txt b/CMakeLists.txt index 657e258..9cbb532 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,8 +3,8 @@ set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/") project(QAsm) -set(CMAKE_BUILD_TYPE Debug) -set(APPVERSION "1.0.1") +set(CMAKE_BUILD_TYPE DEBUG) +set(APPVERSION "4.0.9") set(LIBRARY_NAME pal) set(FIND_LIBRARY_USE_LIB64_PATHS TRUE) @@ -19,13 +19,13 @@ set(SOURCE ${PROJECT_ROOT}/psuedo.cpp ) -find_package(OpenSSL REQUIRED) -find_package(Poco REQUIRED Foundation Util XML JSON NetSSL) +#find_package(OpenSSL REQUIRED) +find_package(Poco REQUIRED Foundation Util XML JSON ) include_directories(BEFORE ${PROJECT_ROOT} ${PROJECT_ROOT}/lib${LIBRARY_NAME}/include/${LIBRARY_NAME} - ${OPENSSL_INCLUDE_DIR} + #${OPENSSL_INCLUDE_DIR} ${Poco_INCLUDE_DIRS} ) diff --git a/Makefile b/Makefile index af0c3b8..26eaecd 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,12 @@ -#export CC=/usr/bin/clang -#export CXX=/usr/bin/clang++ +export USE_CLANG=1 +ifeq ($(USE_CLANG),1) +export CXX=/usr/bin/clang++ +export CC=/usr/bin/clang +else +export CXX=g++ +export CC=gcc +endif V?= S= @@ -35,6 +41,9 @@ install: reformat: qasm -x REFORMAT src/main.s +compare: + -bcompare . ../lane_hex & + asm: test1: @@ -42,6 +51,9 @@ test1: test2: -qasm src/testfile.s + +test3: + -qasm src/var.s diff --git a/asm.cpp b/asm.cpp index 7758092..f5ab12e 100644 --- a/asm.cpp +++ b/asm.cpp @@ -25,18 +25,43 @@ void CLASS::setError(uint32_t ecode) void CLASS::print(uint32_t lineno) { - int i, l, pcol; + int pcol; + uint32_t l, i; int commentcol = 40; + static bool checked = false; + static bool nc1 = false; bool nc = false; + uint32_t b = 4; // how many bytes show on the first line - l = outbytect; - if (l > 4) + if (datafillct > 0) { - l = 4; + l = datafillct; + } + else + { + l = outbytect; + } + if (l > b) + { + l = b; + } + + if (!checked) + { + nc1 = getBool("option.nocolor", false); + checked = true; + } + else + { + nc = nc1; + } + + if (!isatty(STDOUT_FILENO)) + { + nc = true; } - nc = getBool("option.nocolor", false); if (!nc) { if (errorcode > 0) @@ -60,7 +85,6 @@ void CLASS::print(uint32_t lineno) { empty = true; } - int b = 4; pcol = 0; if (!empty) @@ -74,16 +98,24 @@ void CLASS::print(uint32_t lineno) for (i = 0; i < l; i++) { - pcol += printf("%02X ", outbytes[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("%6d ", lineno + 1); + if (showmx) { - if (outbytect > 0) + if ((outbytect + datafillct) > 0) { pcol += printf("%%%c%c ", linemx & 02 ? '1' : '0', linemx & 01 ? '1' : '0'); } @@ -97,7 +129,6 @@ void CLASS::print(uint32_t lineno) { pcol += printf("%02X ", addressmode & 0xFF); } - pcol += printf("%6d ", lineno + 1); pcol = 0; // reset pcol here because this is where source code starts @@ -140,7 +171,51 @@ void CLASS::print(uint32_t lineno) { SetColor(CL_NORMAL | BG_NORMAL); } - printf("\n"); + + uint32_t obc = datafillct; + if (obc == 0) + { + obc = outbytect; + } + + uint32_t ct = 1; + if (obc > b) + { + ct = 0; + uint8_t db; + uint32_t t = b; + char *s = (char *)" "; + + 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("%02X ", db); + t++; + ct++; + if (ct >= b) + { + printf("\n"); + ct = 0; + } + } + } + if (ct > 0) + { + printf("\n"); + } } @@ -164,6 +239,8 @@ void CLASS::clear() errorcode = 0; errorText = ""; outbytect = 0; + datafillct = 0; + datafillbyte = 0; lineno = 0; outbytes.clear(); addressmode = 0; @@ -176,13 +253,14 @@ void CLASS::clear() void CLASS::set(std::string line) { int state = 0; - int l = (int)line.length(); + int l = line.length(); int i = 0; int x; - char c, delim = 0; + char c, delim; clear(); + delim=0; //printf("line: |%s|\n", line.c_str()); while (i < l) { @@ -304,7 +382,7 @@ void CLASS::set(std::string line) } } printlable = lable; - x = (int)lable.length(); + x = lable.length(); if (x > 1) { while ((x > 1) && (lable[x - 1] == ':')) @@ -337,9 +415,11 @@ void CLASS::errorOut(uint16_t code) void CLASS::init(void) { + filenames.clear(); starttime = GetTickCount(); - - syntax = SYNTAX_MERLIN; + initialdir = Poco::Path::current(); + syntax = 0; + filecount = 0; } void CLASS::complete(void) @@ -348,9 +428,11 @@ void CLASS::complete(void) uint64_t n = GetTickCount(); if (isDebug()) { - //cout << "Processing Time: " << n-starttime << " ms" << endl; - printf("Processing Time: %" PRIu64 " ms\n",n-starttime); - //printf("Processing Time: %llu ms\n", n - starttime); + //cout << "Processing Time: " << n - starttime << "ms" << endl; + uint64_t x = n - starttime; + uint32_t x1 = x & 0xFFFFFFFF; + printf("Processing Time: %u ms\n", x1); + } } @@ -360,109 +442,280 @@ void CLASS::process(void) } int CLASS::doline(int lineno, std::string line) { + UNUSED(lineno); + UNUSED(line); + int res = -1; return (res); } -int CLASS::processfile(std::string &p) +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); + + 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(); + + 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; + + 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; linect = 0; done = false; + currentdir = Poco::Path::current(); + + 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); + + //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(); - valid = true; - p1 = tp.toString(); - Poco::File fn(p1); - if (!fn.exists()) + try { - fn = Poco::File(p1 + ".s"); + + 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(); + + newfilename = p1; + //LOG_DEBUG << "initial file name: " << p1 << endl; + + valid = true; + Poco::File fn(p1); if (!fn.exists()) { - fn = Poco::File(p1 + ".S"); + fn = Poco::File(p1 + ".s"); if (!fn.exists()) { - fn = Poco::File(p1 + ".mac"); + fn = Poco::File(p1 + ".S"); if (!fn.exists()) { - valid = false; + fn = Poco::File(p1 + ".mac"); + if (!fn.exists()) + { + fn = Poco::File(p1); + valid = false; + } } } } - } - p1 = fn.path(); + p1 = fn.path(); + //LOG_DEBUG << "File name: " << p1 << endl; - if (valid) - { - std::ifstream f(p1); - if (f.is_open()) + int ecode = -3; + valid = false; + if (fn.exists()) { - //printf("file is open\n"); - line = ""; - - while ((!done) && (f.good()) && (!f.eof())) + ecode = -2; + valid = true; + //LOG_DEBUG << "File exists: " << p1 << endl; + if (fn.isLink()) { - 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; - } + //LOG_DEBUG << "File is a link: " << p1 << endl; } - if ( (f.eof())) + if ((fn.isDirectory()) || (!fn.canRead())) { - res = 0; + //LOG_DEBUG << "File is a directory: " << p1 << endl; + valid = false; } } - } - else - { - fprintf(stderr, "File <%s> does not exist.\n\n", p.c_str()); - } - //printf("\n\nfile read result: %d\n", res); + newfilename = p1; + if (!valid) + { + //fprintf(stderr, "Unable to access file: %s\n", p1.c_str()); + + errorct = 1; + return (ecode); + } + + if (valid) + { + + if (filecount == 0) + { + } + else + { + for (auto itr = filenames.begin(); itr != filenames.end(); ++itr) + { + if (*itr == p1) + { + return (-9); + } + } + } + + filecount++; + filenames.push_back(p1); + + std::ifstream f(p1); + if (f.is_open()) + { + //printf("file is open\n"); + line = ""; + + 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); } @@ -480,6 +733,8 @@ void CLASS::init(void) int ts, tabpos; lines.clear(); + syntax = SYNTAX_MERLIN; + std::string tabstr = getConfig("reformat.tabs", "8,16,32"); tabstr = Poco::trim(tabstr); @@ -507,6 +762,8 @@ void CLASS::init(void) int CLASS::doline(int lineno, std::string line) { + UNUSED(lineno); + MerlinLine l(line); lines.push_back(l); return 0; @@ -516,7 +773,7 @@ void CLASS::process(void) { uint32_t len, t, pos; - uint32_t ct = (uint32_t)lines.size(); + uint32_t ct = lines.size(); for (uint32_t lineno = 0; lineno < ct; lineno++) { @@ -592,7 +849,6 @@ void CLASS::complete(void) CLASS::CLASS() : TFileProcessor() { lines.clear(); - inDUMSection = false; psuedoops = new TPsuedoOp(); } @@ -701,6 +957,9 @@ TSymbol *CLASS::addVariable(std::string sym, std::string val, bool replace) s.text = val; s.used = false; s.cb = NULL; + + //printf("addvariable: %s %s\n", s.name.c_str(), s.text.c_str()); + std::pair p(Poco::toUpper(sym), s); variables.insert(p); res = findVariable(sym); @@ -733,6 +992,7 @@ void CLASS::showVariables(void) { printf("%-16s %s\n", itr->first.c_str(), itr->second.text.c_str()); } + printf("\n"); } } @@ -740,45 +1000,52 @@ void CLASS::showVariables(void) // false to print by value; void CLASS::showSymbolTable(bool alpha) { - std::map alphamap; - std::map nummap; - - int columns = 4; - int column = columns; - - for (auto itr = symbols.begin(); itr != symbols.end(); itr++) + if (symbols.size() > 0) { - TSymbol ptr = itr->second; - alphamap.insert(pair(ptr.name, ptr.value)); - nummap.insert(pair(ptr.value, ptr.name)); - } + std::map alphamap; + std::map nummap; - if (alpha) - { - printf("\n\nSymbol table sorted alphabetically:\n\n"); + int columns = getInt("asm.symcolumns", 3); + int column = columns; - for (auto itr = alphamap.begin(); itr != alphamap.end(); ++itr) + for (auto itr = symbols.begin(); itr != symbols.end(); itr++) { - printf("%-16s 0x%08X ", itr->first.c_str(), itr->second); - if ( !--column ) + 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"); + + for (auto itr = alphamap.begin(); itr != alphamap.end(); ++itr) { - printf("\n"); - column = columns; + 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) + else { - printf("0x%08X %-16s ", itr->first, itr->second.c_str()); - if ( !--column ) + printf("\n\nSymbol table sorted numerically:\n\n"); + for (auto itr = nummap.begin(); itr != nummap.end(); ++itr) { - printf("\n"); - column = columns; + printf("0x%08X %-16s ", itr->first, itr->second.c_str()); + if ( !--column ) + { + printf("\n"); + column = columns; + } } } + if (column > 0) + { + printf("\n"); + } } } @@ -858,7 +1125,7 @@ typedef struct std::string regEx; uint16_t addrMode; std::string text; - std::string expression; + //std::string expression; } TaddrMode; // these are the regular expressions that determine the addressing mode @@ -894,6 +1161,9 @@ const TaddrMode addrRegEx[] = // one or more of any character except ][,(); 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]*)"; + // opcode check. emitted opcodes are compared against this // table, and if the XC status doesn't meet the requirements // an error is thrown @@ -1002,10 +1272,15 @@ void CLASS::complete(void) { if (errorct == 0) { + std::string currentdir = Poco::Path::current(); + + savepath = processFilename(savepath, currentdir, 0); + printf("saving to file: %s\n", savepath.c_str()); + std::ofstream f(savepath); uint32_t lineno = 0; - uint32_t l = (uint32_t)lines.size(); + uint32_t l = lines.size(); while (lineno < l) { MerlinLine &line = lines.at(lineno++); @@ -1050,8 +1325,8 @@ int CLASS::evaluate(MerlinLine &line, std::string expr, int64_t &value) if (isDebug() > 2) { int c = SetColor(CL_RED); - cout << "eval Error=" << res << "0x" << std::hex << result << std::dec << eval.badsymbol << endl; - //printf("eval Error=%d %08llX |%s|\n", res, result, eval.badsymbol.c_str()); + uint32_t rr = result & 0xFFFFFFFF; + printf("eval Error=%d %08X |%s|\n", res, rr, eval.badsymbol.c_str()); SetColor(c); } } @@ -1061,8 +1336,8 @@ int CLASS::evaluate(MerlinLine &line, std::string expr, int64_t &value) value = result; if ((listing) && (pass > 0) && (isDebug() > 2)) { - cout << "EV1=0x" << std::hex << v1 << " '" << std::dec << line.expr_shift << ";" << endl; - //printf("EV1=%08llX '%c'\n", v1, line.expr_shift); + uint32_t rr = v1 & 0xFFFFFFFF; + printf("EV1=%08X '%c'\n", rr, line.expr_shift); } if (v1 >= 0x10000) { @@ -1081,8 +1356,8 @@ int CLASS::evaluate(MerlinLine &line, std::string expr, int64_t &value) } if (isDebug() >= 3) { - cout << "Eval Result: 0x" << std::hex << value << std::dec << "(status=" << res << ")" << endl; - //printf("Eval Result: %08llX (status=%d)\n", value, res); + uint32_t rr = value & 0xFFFFFFFF; + printf("Eval Result: %08X (status=%d)\n", rr, res); } return (res); } @@ -1202,22 +1477,81 @@ int CLASS::parseOperand(MerlinLine & line) return (res); } +int CLASS::substituteVariables(MerlinLine & line) +{ + int res = -1; + int x; + std::string::size_type offset, slen; + std::string oper = line.operand; + std::string s; + TSymbol *sym; + uint32_t len, off, ct; + + slen = oper.length(); + if (slen > 0) + { + std::vector groups; + + offset = 0; + RegularExpression varEx(varExpression, Poco::RegularExpression::RE_EXTRA, true); + Poco::RegularExpression::MatchVec mVec; + + //printf("|%s|%s|\n", varExpression.c_str(), oper.c_str()); + groups.clear(); + ct = 0; + while (offset < slen) + { + try + { + varEx.match(oper, offset, mVec, 0); + } + catch (...) + { + offset = slen; + } + + x = mVec.size(); + if (x > 0) + { + res = 0; + off = mVec[0].offset; + len = mVec[0].length; + s = oper.substr(off, len); + sym = findVariable(s); + if (sym != NULL) + { + ct++; + if (pass > 0) + { + //printf("%d |%s|\n", ct, s.c_str()); + } + } + offset += len; + } + else + { + offset = slen; + } + } + + } + return (res); +} + void CLASS::process(void) { uint32_t l; int x;; char c; - std::string op, operand; - //uint32_t operand_eval; - //uint16_t addrmode; + char buff[256]; + std::string op, operand, ls; - //MerlinLine *line; pass = 0; while (pass < 2) { initpass(); - l = (uint32_t)lines.size(); + l = lines.size(); while ((lineno < l) && (!passcomplete)) { MerlinLine &line = lines[lineno]; @@ -1233,7 +1567,7 @@ void CLASS::process(void) line.bytect = 0; line.showmx = showmx; - if ((line.lable != "") && (pass == 0)) + if ((line.lable != "")) { std::string lable = Poco::trim(line.lable); TSymbol *sym = NULL; @@ -1242,14 +1576,19 @@ void CLASS::process(void) switch (c) { case ']': - sym = addVariable(line.lable, "", true); + sprintf(buff, "$%X", PC.currentpc); + ls = buff; + sym = addVariable(line.lable, ls, true); if (sym == NULL) { dupsym = true; } break; case ':': break; default: - sym = addSymbol(line.lable, PC.currentpc, false); - if (sym == NULL) { dupsym = true; } + if (pass == 0) + { + sym = addSymbol(line.lable, PC.currentpc, false); + if (sym == NULL) { dupsym = true; } + } break; } if (dupsym) @@ -1257,6 +1596,7 @@ void CLASS::process(void) line.setError(errDupSymbol); } } + x = substituteVariables(line); x = parseOperand(line); if (x >= 0) { @@ -1270,7 +1610,7 @@ void CLASS::process(void) if (x == 0) { value &= 0xFFFFFFFF; - line.expr_value = (int32_t)value; + line.expr_value = value; } else { @@ -1346,8 +1686,11 @@ void CLASS::process(void) int CLASS::doline(int lineno, std::string line) { int res = 0; + int x; std::string op; + UNUSED(lineno); + MerlinLine l(line); op = Poco::toLower(l.opcode); @@ -1364,8 +1707,30 @@ int CLASS::doline(int lineno, std::string line) if ((op == "use") || (op == "put")) { - //printf("processing % s\n",l.operand.c_str()); - processfile(l.operand); + std::string fn; + x = processfile(l.operand, fn); + 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); @@ -1398,6 +1763,9 @@ void CLASS::complete(void) int CLASS::doline(int lineno, std::string line) { + UNUSED(lineno); + UNUSED(line); + int res = 0; return (res); diff --git a/asm.h b/asm.h index 191185c..7c36ed2 100644 --- a/asm.h +++ b/asm.h @@ -40,13 +40,13 @@ enum asmErrors errNone, errWarn, errIncomplete, + errUnimplemented, errFatal, errBadAddressMode, errBadOpcode, errIncompatibleOpcode, errBadByteCount, errBadBranch, - errUnimplemented, errForwardRef, errNoRedefinition, errBadOperand, @@ -55,6 +55,10 @@ enum asmErrors errOverflow, errRecursiveOp, errOpcodeNotStarted, + errDuplicateFile, + errFileNotFound, + errFileNoAccess, + errBadEvaluation, errMAX }; @@ -64,13 +68,13 @@ const std::string errStrings[errMAX + 1] = "No Error", "Warning", "Unfinished Opcode", + "Unimplemented Instruction", "Fatal", "Unsupported Addressing Mode", "Unknown Opcode", "Opcode not available under CPU mode", "Byte output differs between passes", "Relative branch offset too large", - "Unimplemented Instruction", "Forward Reference to symbol", "Unable to redefine symbol", "Unable to evaluate", @@ -79,6 +83,11 @@ const std::string errStrings[errMAX + 1] = "Overflow detected", "Recursive Operand", "Opcode without start", + "File already included", + "File not found", + "File no access", + "Unable to evaluate", + "" }; #else @@ -178,6 +187,8 @@ public: uint16_t pass0bytect; uint16_t bytect; + uint16_t datafillct; + uint8_t datafillbyte; uint16_t outbytect; std::vector outbytes; @@ -193,14 +204,19 @@ public: class TFileProcessor { protected: + std::string initialdir; + std::vector filenames; uint8_t syntax; uint64_t starttime; + uint32_t filecount; // how many files have been read in (because of included files from source public: uint32_t errorct; + std::string filename; TFileProcessor(); virtual ~TFileProcessor(); - virtual int processfile(std::string &p); + virtual std::string processFilename(std::string p,std::string currentdir,int level); + virtual int processfile(std::string p,std::string &newfilename); virtual void init(void); virtual int doline(int lineno, std::string line); virtual void process(void); @@ -293,8 +309,6 @@ public: uint16_t pass; - bool inDUMSection; // yes if we are in a DUM/DEND section - T65816Asm(); virtual ~T65816Asm(); @@ -318,6 +332,7 @@ public: void showVariables(void); int evaluate(MerlinLine &line,std::string expr, int64_t &value); + int substituteVariables(MerlinLine & line); int parseOperand(MerlinLine &line); int getAddrMode(MerlinLine &line); void setOpcode(MerlinLine &line, uint8_t op); @@ -352,4 +367,4 @@ public: virtual void process(void); virtual void complete(void); -}; +}; \ No newline at end of file diff --git a/config.h b/config.h index 3db2eb2..f1f9a01 100644 --- a/config.h +++ b/config.h @@ -1,16 +1,21 @@ #pragma once // define application options here -#define PAL_APPCLASS TMyCustomApp +#define PAL_APPCLASS TQAsmApp #define NO_SIGNAL_HANDLING //#define SERVERAPP -#define ENABLE_SSL -#define USE_LOGGER + +//#define ENABLE_SSL +//#define USE_LOGGER +//#define USE_NET +//#define USE_SSL +//#define USE_JSON +//#define USE_XML // help text -#define HELP_USAGE " filename" -#define HELP_PURPOSE "a program that does something" +#define HELP_USAGE " " +#define HELP_PURPOSE "\nMerlin 16+ Compatible 65816 Development Tool" diff --git a/eval.cpp b/eval.cpp index a8b9dda..2f9fd69 100644 --- a/eval.cpp +++ b/eval.cpp @@ -26,7 +26,7 @@ std::deque CLASS::exprToTokens(const std::string& expr) std::deque tokens; int state = 0; char c; - char delim = 0; + char delim; std::string ident, asc; std::string ops = "+-*//^!.&()"; @@ -36,6 +36,7 @@ std::deque CLASS::exprToTokens(const std::string& expr) bool numexpect; Token::Type t; + delim=0; numexpect = true; for (const auto* p = expr.c_str(); *p; ++p) { @@ -378,7 +379,7 @@ int CLASS::parseNumber(std::string n, int64_t &val) i = 0; - l = (int)n.length(); + l = n.length(); s = ""; for (i = 0; i < l; i++) { diff --git a/opcodes.cpp b/opcodes.cpp index 3aa2ae0..2aacfa6 100644 --- a/opcodes.cpp +++ b/opcodes.cpp @@ -24,6 +24,8 @@ void CLASS::setOpcode(MerlinLine &line, uint8_t op) int CLASS::doPSEUDO(MerlinLine &line, TSymbol &sym) { + UNUSED(sym); + int res; res = psuedoops->ProcessOpcode(*this, line, sym); @@ -32,6 +34,8 @@ int CLASS::doPSEUDO(MerlinLine &line, TSymbol &sym) int CLASS::doXC(MerlinLine &line, TSymbol &sym) { + UNUSED(sym); + std::string s; int res = 0; @@ -53,6 +57,8 @@ int CLASS::doXC(MerlinLine &line, TSymbol &sym) int CLASS::doMX(MerlinLine &line, TSymbol &sym) { + UNUSED(sym); + if (cpumode < MODE_65816) { line.setError(errIncompatibleOpcode); @@ -67,6 +73,7 @@ int CLASS::doMX(MerlinLine &line, TSymbol &sym) int CLASS::doEQU(MerlinLine &line, TSymbol &sym) { + UNUSED(sym); int res = 0; TSymbol *s; if (line.lable.length() > 0) @@ -100,6 +107,7 @@ int CLASS::doEQU(MerlinLine &line, TSymbol &sym) int CLASS::doUNK(MerlinLine &line, TSymbol &sym) { int res = -1; + UNUSED(sym); res = 0; if (pass > 0) @@ -117,6 +125,7 @@ int CLASS::doPER(MerlinLine &line, TSymbol &sym) { int res; int32_t value = 0;; + UNUSED(sym); res = 0; if ((line.addressmode == syn_abs) || (line.addressmode == syn_imm)) @@ -147,6 +156,7 @@ int CLASS::doMVN(MerlinLine &line, TSymbol &sym) { int res; uint8_t op; + UNUSED(sym); if (line.addressmode == syn_bm) { @@ -197,6 +207,7 @@ int CLASS::doNoPattern(MerlinLine &line, TSymbol &sym) // STZ = 1 // TSB = 2 // TRB = 3 + UNUSED(sym); int res, i; uint8_t err; @@ -565,6 +576,11 @@ int CLASS::doBase6502(MerlinLine & line, TSymbol & sym) } } } + if (line.flags&FLAG_FORCELONG) + { + line.setError(errBadAddressMode); + } + goto out; } if (m == syn_imm) @@ -670,6 +686,9 @@ out: int CLASS::doEND(MerlinLine & line, TSymbol & sym) { + UNUSED(sym); + UNUSED(line); + int res = 0; passcomplete = true; @@ -678,6 +697,8 @@ int CLASS::doEND(MerlinLine & line, TSymbol & sym) int CLASS::doBYTE(MerlinLine & line, TSymbol & sym) { + UNUSED(sym); + int res = 1; if (pass > 0) @@ -695,7 +716,7 @@ void CLASS::insertOpcodes(void) pushopcode("EXT", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("ENT", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("ORG", P_ORG, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); - pushopcode("DSK", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); + pushopcode("DSK", P_SAV, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("SAV", P_SAV, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("DS", P_DS, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("REL", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); @@ -724,13 +745,13 @@ void CLASS::insertOpcodes(void) pushopcode("FLS", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("REV", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("STR", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); - pushopcode("DA", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); - pushopcode("DW", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); - pushopcode("DDB", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); - pushopcode("DFB", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); - pushopcode("DB", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); - pushopcode("ADR", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); - pushopcode("ADRL", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); + pushopcode("DA", P_DATA, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); + pushopcode("DW", P_DATA, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); + pushopcode("DDB", P_DATA, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); + pushopcode("DFB", P_DATA, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); + pushopcode("DB", P_DATA, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); + pushopcode("ADR", P_DATA, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); + pushopcode("ADRL",P_DATA, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("HEX", P_HEX, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("DS", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("DO", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); diff --git a/psuedo.cpp b/psuedo.cpp index ed180e4..a93ba13 100644 --- a/psuedo.cpp +++ b/psuedo.cpp @@ -1,4 +1,5 @@ #include "psuedo.h" +#include "eval.h" #define CLASS TPsuedoOp @@ -12,9 +13,126 @@ CLASS::~CLASS() } +constexpr unsigned int strhash(const char *str, int h = 0) +{ + return !str[h] ? 5381 : (strhash(str, h + 1) * 33) ^ str[h]; +} + +int CLASS::doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) +{ + UNUSED(opinfo); + TEvaluator eval(a); + + int i; + int outct = 0; + int wordsize = 2; + int endian = 0; + std::string oper = line.operand; + std::string op = Poco::toUpper(Poco::trim(line.opcode)); + Poco::StringTokenizer tok(oper, ",", Poco::StringTokenizer::TOK_TRIM | + Poco::StringTokenizer::TOK_IGNORE_EMPTY); + + + const char *ptr = (const char *)op.c_str(); + switch (strhash(ptr) ) + { + case strhash((const char *)"DA"): + case strhash((const char *)"DW"): + wordsize = 2; + break; + case strhash((const char *)"DDB"): + wordsize = 2; + endian = 1; + break; + case strhash((const char *)"DFB"): + case strhash((const char *)"DB"): + wordsize = 1; + break; + case strhash((const char *)"ADR"): + wordsize = 3; + break; + case strhash((const char *)"ADRL"): + wordsize = 4; + break; + default: + wordsize=0; + break; + } + + for (auto itr = tok.begin(); itr != tok.end(); ++itr) + { + //printf("%s\n",(*itr).c_str()); + //evaluate each of these strings, check for errors on pass 2 + + std::string expr = *itr; + int64_t eval_result = 0; + uint8_t shift; + int r; + uint8_t b; + + shift=0; + r = eval.evaluate(expr, eval_result, shift); + if (r < 0) + { + //printf("eval error %d |%s|\n", r,expr.c_str()); + if (a.pass > 0) + { + line.setError(errBadEvaluation); + } + } + if (shift=='>') + { + eval_result=(eval_result) & 0xFF; + } + if (shift=='<') + { + eval_result=(eval_result>>8) & 0xFF; + } + else if ((shift=='^') || (shift=='|')) + { + eval_result=(eval_result>>16)&0xFF; + } + + + outct += wordsize; + if (a.pass > 0) + { + if (!endian) // little endian + { + for (i = 0; i < wordsize; i++) + { + b=(eval_result >> (8 * i))&0xFF; + line.outbytes.push_back(b); + //printf("%02X\n",b); + } + } + else + { + // big endian + for (i = 0; i < wordsize; i++) + { + b=(eval_result >> ((wordsize-1-i) * 8))&0xFF; + line.outbytes.push_back(b); + //printf("%02X\n",b); + } + + } + } + } +#if 0 + // SGQ - remove when complete + line.datafillct = outct; + line.datafillbyte = 0xCA; + // =============== +#endif + line.outbytect=outct; + return (outct); +} int CLASS::doDS(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) { + UNUSED(opinfo); + int res = 0; int32_t v = line.expr_value; if (line.eval_result != 0) @@ -29,14 +147,18 @@ int CLASS::doDS(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) { res = v; + line.datafillbyte = line.eval_result & 0xFF; + line.datafillct = v; +#if 0 if (a.pass > 0) { - for (int32_t i = 0; i < v; i++) + for (int i = 0; i < v; i++) { line.outbytes.push_back(0x00); } line.outbytect = v; } +#endif } return (res); @@ -44,6 +166,8 @@ int CLASS::doDS(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) int CLASS::doDUM(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) { + UNUSED(opinfo); + int res = 0; bool isdend = ((opinfo.opcode == P_DEND) ? true : false); @@ -67,9 +191,12 @@ int CLASS::doDUM(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) int CLASS::doLST(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) { + UNUSED(opinfo); + + std::string s; if (a.pass > 0) { - std::string s = Poco::toUpper(Poco::trim(line.operand)); + s = Poco::toUpper(Poco::trim(line.operand)); if ((s == "") || (s == "ON") || (line.expr_value > 0)) { //printf("ON\n"); @@ -88,71 +215,67 @@ int CLASS::doLST(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) int CLASS::doHEX(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) { - int res = 0; - std::vector values; - values.clear(); + UNUSED(opinfo); std::string os = Poco::toUpper(Poco::trim(line.operand)); - std::string vs = "0123456789ABCDEF"; - std::string hex = ""; + uint32_t bytect = 0; + uint8_t b = 0; + uint8_t ct = 0; for ( uint32_t i = 0; i < os.length(); ++i ) { char c = os[i]; - // Check for a comma if needed, and continue to next char if found - if ( hex.length() == 0 && c == ',' ) + if ((c >= '0') && (c <= '9')) + { + c = c - '0'; + } + else if ((c >= 'a') && (c <= 'f')) + { + c = c - 'a' + 10; + } + else if ((c >= 'A') && (c <= 'F')) + { + c = c - 'A' + 10; + } + else if (c == ',') { continue; } - - if ( vs.find(c) == std::string::npos ) + else { line.setError(errBadOperand); - return -1; + return 0; } // Got a good char, append to hex string and see if we've got a byte - hex.append(1, c); - if ( hex.length() == 2 ) + switch (ct) { - // Got 2 chars (1 byte), so store in values array - values.push_back(hex); - hex.clear(); + case 0: + b = (c << 4); + break; + case 1: + b |= c; + break; } - } - - // We can't have an odd character dangling around! - if ( hex.size() != 0 ) - { - line.setError(errOverflow); - return -1; - } - - int byteCnt = (int)values.size(); - a.PC.currentpc += byteCnt; - - if (a.pass > 0) - { - for ( uint32_t i = 0; i < values.size(); ++i ) + ct = (ct + 1) & 0x01; + if (!ct) { - std::string s = "$"; - s.append(values[i]); - int64_t v; - if ( 0 == a.evaluate(line, s, v) ) + if (a.pass > 0) { - line.outbytes.push_back((uint8_t)v); + line.outbytes.push_back(b); } + b = 0; + bytect++; } - line.outbytect = byteCnt; + } - else - { - line.pass0bytect = byteCnt; - } - return res; + line.outbytect = bytect; + //printf("bytect=%d\n",bytect); + return bytect; } + int CLASS::ProcessOpcode(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) { int res = 0; @@ -163,7 +286,6 @@ int CLASS::ProcessOpcode(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) res = -1; // undefined p-op line.setError(errUnimplemented); break; - case P_DS: res = doDS(a, line, opinfo); break; @@ -189,18 +311,18 @@ int CLASS::ProcessOpcode(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) line.startpc = a.PC.orgsave; } break; - case P_SAV: - a.savepath = line.operand; + a.savepath = a.processFilename(line.operand, Poco::Path::current(), 0); break; - case P_LST: res = doLST(a, line, opinfo); break; - case P_HEX: res = doHEX(a, line, opinfo); break; + case P_DATA: + res = doDATA(a, line, opinfo); + break; } return (res); } diff --git a/psuedo.h b/psuedo.h index 99eb226..3845232 100644 --- a/psuedo.h +++ b/psuedo.h @@ -13,7 +13,8 @@ enum P_DS, P_PUT, P_USE, - P_HEX, + P_HEX, + P_DATA, P_MAX }; @@ -27,7 +28,8 @@ public: int doLST(T65816Asm &a, MerlinLine &line, TSymbol &opinfo); int doDUM(T65816Asm &a, MerlinLine &line, TSymbol &opinfo); int doDS(T65816Asm &a, MerlinLine &line, TSymbol &opinfo); - int doHEX(T65816Asm &a, MerlinLine &line, TSymbol &opinfo); + int doHEX(T65816Asm &a, MerlinLine &line, TSymbol &opinfo); + int doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo); }; -#undef CLASS +#undef CLASS \ No newline at end of file diff --git a/qasm.cpp b/qasm.cpp index 018405e..22e034d 100644 --- a/qasm.cpp +++ b/qasm.cpp @@ -12,14 +12,24 @@ PAL_BASEAPP *PAL::appFactory(void) // you MUST supply this array 'appOptions'. NULL line and end. programOption PAL::appOptions[] = { +#ifdef DEBUG { "debug", "d", "enable debug info (repeat for more verbosity)", "", false, true}, - { "config", "f", "load configuration data from a ", "", false, false}, - { "exec", "x", "execute a command", "", false, false}, - +#endif + //{ "config", "f", "load configuration data from a ", " ", false, false}, + { "exec", "x", "execute a command [asm, link, reformat] default=asm", " ", false, false}, { "", "", "", "", false, false} }; +void CLASS::displayVersion() +{ + std::string s = ""; +#ifdef DEBUG + s = "-debug"; +#endif + cerr << "quickASM 16++ v" << (std::string)STRINGIFY(APPVERSION) << s << endl; +} + int CLASS::runServerApp(PAL_EVENTMANAGER *em) { int res = -1; @@ -39,25 +49,50 @@ int CLASS::runServerApp(PAL_EVENTMANAGER *em) return (res); } +void CLASS::showerror(int ecode, std::string fname) +{ + std::string s; + switch (ecode) + { + case -2: + s = "Permission Denied"; + break; + case -3: + s = "File not found"; + break; + default: + s = "Unknown Error"; + break; + } + if (ecode < -1) + { + std::string a = Poco::Util::Application::instance().config().getString("application.name", ""); + fprintf(stderr, "%s: %s: %s\n", a.c_str(), fname.c_str(), s.c_str()); + } +} + int CLASS::runCommandLineApp(void) { TFileProcessor *t = NULL; std::string line; + std::string startdirectory; + std::string fname; - // only called if SERVERAPP not defined int res = -1; - //LOG_DEBUG << "command line mode" << endl; - if (commandargs.size()==0) + + startdirectory = Poco::Path::current(); + + if (commandargs.size() == 0) { - fprintf(stderr,"No files given (--help for help)\n\n"); - return(res); + displayHelp(); + return (res); } for (ArgVec::const_iterator it = commandargs.begin(); it != commandargs.end(); ++it) { Poco::File fn(*it); - + int x; std::string p = fn.path(); Poco::Path path(p); //logger().information(path.toString()); @@ -74,41 +109,62 @@ int CLASS::runCommandLineApp(void) t = new TMerlinConverter(); if (t != NULL) { - - t->init(); - std::string f = path.toString(); - t->processfile(f); - t->process(); - t->complete(); - res = (t->errorct > 0) ? -1 : 0; - - delete t; - t = NULL; + try + { + t->init(); + std::string f = path.toString(); + t->filename = f; + x = t->processfile(f, fname); + if (x == 0) + { + t->process(); + t->complete(); + } + else + { + showerror(x, fname); + t->errorct = 1; + } + res = (t->errorct > 0) ? -1 : 0; + } + catch (...) + { + delete t; + t = NULL; + } } } else if (cmd == "ASM") { - if (e == "S") - { - //logger().information("ASM: " + path.toString()); - - t = new T65816Asm(); - } - if (e == "LNK") - { - //logger().information("LNK: " + path.toString()); - t = new T65816Link(); - } + int x; + t = new T65816Asm(); if (t != NULL) { - t->init(); - std::string f = path.toString(); - t->processfile(f); - t->process(); - t->complete(); - res = (t->errorct > 0) ? -1 : 0; - delete t; - t = NULL; + try + { + t->init(); + std::string f = path.toString(); + t->filename = f; + x = t->processfile(f, fname); + f = t->filename; + if (x == 0) + { + t->process(); + t->complete(); + } + else + { + showerror(x, fname); + t->errorct = 1; + } + res = (t->errorct > 0) ? -1 : 0; + } + catch (...) + { + delete t; + t = NULL; + } + if (chdir(startdirectory.c_str())) {}; // return us back to where we were } else { @@ -117,7 +173,7 @@ int CLASS::runCommandLineApp(void) } else { - fprintf(stderr,"Invalid command: <%s>\n\n", cmd.c_str()); + fprintf(stderr, "Invalid command: <%s>\n\n", cmd.c_str()); } } } diff --git a/qasm.h b/qasm.h index 01074cd..1cc8b2d 100644 --- a/qasm.h +++ b/qasm.h @@ -12,8 +12,11 @@ using namespace PAL_NAMESPACE; class CLASS : public PAL_BASEAPP { protected: + void showerror(int ecode,std::string fname); virtual int runCommandLineApp(void); virtual int runServerApp(PAL_EVENTMANAGER *em); + virtual void displayVersion(); + public: }; diff --git a/qasm.ini b/qasm.ini index 409b355..4e41bc8 100644 --- a/qasm.ini +++ b/qasm.ini @@ -5,19 +5,19 @@ logfile=mylog.log [option] debug=1 -nocolor=true -;must be an integer. Code can use this as a level +nocolor=false +;debug must be an integer. Code can use this as a level [application] timezone=America/Los_Angeles [global] -; path0 can not be set. It will always be the linux 'pwd' +; path0 can not be set. It will always be the linux 'pwd' at the time of launch path1=0/macros path2=0/output -path3= +path3=0/src path4= -path5= +path5=dirpath5 [asm] casesen=true @@ -27,7 +27,8 @@ lst=true cpu=M65816 trackrep=false allowduplicate=true -merlincompatible=true; +merlincompatible=true +symcolumns=3 [reformat] tabs=12; 18; 36 diff --git a/src/main.s b/src/main.s index 2640247..560694e 100644 --- a/src/main.s +++ b/src/main.s @@ -364,7 +364,35 @@ L00BC bit L00BC hex 11,22,33,44,55,66,77,88,99 hex 112233445566778899 - hex aabb,cc,ddee,ff + hex aabb,CC,0123456789ABCDEFabcdef,ff + + ds 36 + da $A55A + da $A55A,$1234 + dw $A55A + dw $A55A,$1234 + ddb $A55A + ddb $A55A,$1234 + dfb $A55A + dfb $A55A,$1234 + db $A55A + db $A55A,$1234 + adr $01A55A + adr $01A55A,$011234 + adrl $01A55A + adrl $01A55A,$011234 + + dw >$01A55A,>$011234 + dw <$01A55A,<$011234 + dw ^$01A55A,^$011234 + dw |$01A55A,|$011234 + + db >$01A55A,>$011234 + db <$01A55A,<$011234 + db ^$01A55A,^$011234 + db |$01A55A,|$011234 + + //]XCODEEND ; Keep this at the end and put your code above this ;lst off diff --git a/src/var.s b/src/var.s new file mode 100644 index 0000000..b54c676 --- /dev/null +++ b/src/var.s @@ -0,0 +1,25 @@ + lst + xc + xc + + mx %00 + org $4000 + +getkey = $FF00 + +]myvar = getkey + +start nop + ldy #$00 +]loop sta $800,y + dey + bne ]loop;]loop2 + bne ]myvar; + + bcs ]loop + bpl ]loop + rts + + use var + lst on + From b1eeb0a648619d16bc1764aa36eea05a35a6eece Mon Sep 17 00:00:00 2001 From: marketideas Date: Sat, 16 Nov 2019 20:48:25 -0800 Subject: [PATCH 02/26] DUP/IF/OPCODES/LST --- CMakeLists.txt | 24 +- asm.cpp | 236 ++++++-- asm.h | 107 +++- ciderpress/diskimg/CMakeLists.txt | 2 + ciderpress/diskimg/DDD.cpp | 2 +- ciderpress/diskimg/DOS33.cpp | 2 +- ciderpress/diskimg/Gutenberg.cpp | 12 +- ciderpress/diskimg/HFS.cpp | 4 +- ciderpress/diskimg/Nibble35.cpp | 2 +- ciderpress/diskimg/OzDOS.cpp | 8 +- ciderpress/diskimg/Pascal.cpp | 4 +- ciderpress/diskimg/ProDOS.cpp | 4 +- ciderpress/diskimg/UNIDOS.cpp | 10 +- ciderpress/diskimg/libhfs/CMakeLists.txt | 2 +- ciderpress/nufxlib/Archive.c | 7 + opcodes.cpp | 101 ++-- psuedo.cpp | 307 +++++++++-- psuedo.h | 6 + qasm.cpp | 11 + qasm.h | 7 +- qasm.ini | 4 +- src/main.s | 675 ++++++++++++----------- src/testfile.s | 9 +- 23 files changed, 1022 insertions(+), 524 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9cbb532..20ee519 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,12 +3,15 @@ set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/") project(QAsm) +set(CIDER "0") + set(CMAKE_BUILD_TYPE DEBUG) set(APPVERSION "4.0.9") set(LIBRARY_NAME pal) set(FIND_LIBRARY_USE_LIB64_PATHS TRUE) include(./lib${LIBRARY_NAME}/cmake/CMakeHeader.txt) + set ( PROJECT_NAME "qasm" ) set(SOURCE @@ -20,7 +23,8 @@ set(SOURCE ) #find_package(OpenSSL REQUIRED) -find_package(Poco REQUIRED Foundation Util XML JSON ) +find_package( Poco REQUIRED Foundation Util XML JSON ) +find_package( ZLIB ) include_directories(BEFORE ${PROJECT_ROOT} @@ -29,16 +33,30 @@ include_directories(BEFORE ${Poco_INCLUDE_DIRS} ) -add_subdirectory(${PROJECT_ROOT}/lib${LIBRARY_NAME}) - include(${PROJECT_ROOT}/lib${LIBRARY_NAME}/cmake/CMakeApp.txt) +set (CIDERLIBS "" ) +if ( ${CIDER} ) +add_definitions(-DCIDERPRESS) +include_directories(AFTER ${PROJECT_ROOT}/ciderpress/diskimg) +add_subdirectory(${PROJECT_ROOT}/ciderpress/nufxlib) +add_subdirectory(${PROJECT_ROOT}/ciderpress/diskimg) + +find_library(DISKIMG_LIB libnufx_static.a ${PROJECT_ROOT}/build ) +find_library(HFS_LIB libnufx_static.a ${PROJECT_ROOT}/build ) +find_library(NUFX_LIB libnufx_static.a ${PROJECT_ROOT}/build ) +set (CIDERLIBS diskimg_static hfs_static nufx_static ${ZLIB_LIBRARIES}) +endif ( ${CIDER} ) + +add_subdirectory(${PROJECT_ROOT}/lib${LIBRARY_NAME}) + add_executable( ${PROJECT_NAME} ${SOURCE}) target_link_libraries ( ${PROJECT_NAME} ${LIBRARY_NAME} pthread +${CIDERLIBS} ${Poco_LIBRARIES} ) diff --git a/asm.cpp b/asm.cpp index f5ab12e..e6db75c 100644 --- a/asm.cpp +++ b/asm.cpp @@ -25,15 +25,17 @@ void CLASS::setError(uint32_t ecode) void CLASS::print(uint32_t lineno) { - int pcol; - uint32_t l, i; - int commentcol = 40; + 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 + bool merlinstyle = true; + if (datafillct > 0) { l = datafillct; @@ -46,7 +48,25 @@ void CLASS::print(uint32_t lineno) { l = b; } + if (errorcode > 0) + { + if (merlinstyle) + { + //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); @@ -57,7 +77,7 @@ void CLASS::print(uint32_t lineno) nc = nc1; } - if (!isatty(STDOUT_FILENO)) + if ((!isatty(STDOUT_FILENO)) || (merlinstyle)) { nc = true; } @@ -87,7 +107,12 @@ void CLASS::print(uint32_t lineno) } pcol = 0; - if (!empty) + + bool saddr = flags & FLAG_FORCEADDRPRINT; + saddr = (outbytect > 0) ? true : saddr; + saddr = (printlable != "") ? true : saddr; + + if (saddr) { pcol += printf("%02X/%04X:", (startpc >> 16), startpc & 0xFFFF); } @@ -130,6 +155,7 @@ void CLASS::print(uint32_t lineno) 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 if (empty) @@ -143,30 +169,62 @@ void CLASS::print(uint32_t lineno) pcol += printf(" "); } } - pcol += printf("%s", comment.c_str()); + //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 + 10))) + { + printf("\n"); + pcol = 0; + while (pcol < (commentcol + savpcol)) + { + pcol += printf(" "); + } + } + } + //pcol += printf("%s", comment.c_str()); + + } + commentprinted = true; } } else { - pcol += printf("%-12s %-8s %-10s ", printlable.c_str(), opcode.c_str(), operand.c_str()); - if (errorcode > 0) + pcol += printf("%s ",printlable.c_str()); + while (pcol < tabs[0]) { - - while (pcol < commentcol) - { - pcol += printf(" "); - } - pcol += printf(":[Error] %s %s", errStrings[errorcode].c_str(), errorText.c_str()); + pcol += printf(" "); } - else + pcol+=printf("%s ",opcode.c_str()); + while (pcol < tabs[1]) { - while (pcol < commentcol) - { - pcol += printf(" "); - } - pcol += printf("%s", comment.c_str()); + pcol += printf(" "); } + pcol+=printf("%s ",operand.c_str()); + //pcol += printf("%-12s %-8s %-10s ", printlable.c_str(), opcode.c_str(), operand.c_str()); } + if ((errorcode > 0) && (!merlinstyle)) + { + while (pcol < commentcol) + { + pcol += printf(" "); + } + pcol += printf(":[Error] %s %s", errStrings[errorcode].c_str(), 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); @@ -179,7 +237,7 @@ void CLASS::print(uint32_t lineno) } uint32_t ct = 1; - if (obc > b) + if ((obc > b) && ((truncdata & 0x01) == 0)) { ct = 0; uint8_t db; @@ -260,7 +318,7 @@ void CLASS::set(std::string line) clear(); - delim=0; + delim = 0; //printf("line: |%s|\n", line.c_str()); while (i < l) { @@ -415,23 +473,51 @@ void CLASS::errorOut(uint16_t code) void CLASS::init(void) { + int ts, tabpos; + std::string s; + filenames.clear(); starttime = GetTickCount(); initialdir = Poco::Path::current(); syntax = 0; filecount = 0; + + std::string tabstr = getConfig("reformat.tabs", "8,16,32"); + tabstr = Poco::trim(tabstr); + + 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()) + //if (isDebug()) { //cout << "Processing Time: " << n - starttime << "ms" << endl; uint64_t x = n - starttime; uint32_t x1 = x & 0xFFFFFFFF; - printf("Processing Time: %u ms\n", x1); + printf("Elapsed time: %u ms\n", x1); } } @@ -576,7 +662,7 @@ int CLASS::processfile(std::string p, std::string &newfilename) { // 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; + //LOG_DEBUG << "Changing directory to: " << dir << endl; if (chdir(dir.c_str())) {} // change directory to where the file is } @@ -730,34 +816,9 @@ CLASS::~CLASS() void CLASS::init(void) { std::string s; - int ts, tabpos; lines.clear(); syntax = SYNTAX_MERLIN; - - std::string tabstr = getConfig("reformat.tabs", "8,16,32"); - tabstr = Poco::trim(tabstr); - - 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; - } - } } int CLASS::doline(int lineno, std::string line) @@ -1053,6 +1114,7 @@ int CLASS::callOpCode(std::string op, MerlinLine &line) { int res = -1; char c; + std::string s; if (op.length() == 4) // check for 4 digit 'L' opcodes { @@ -1068,7 +1130,12 @@ int CLASS::callOpCode(std::string op, MerlinLine &line) line.flags |= FLAG_FORCELONG; // 3 byte address break; default: // any char but 'L' as in Merlin 16+ - if ((c != 'D') || (Poco::toUpper(op) != "DEND")) + 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 @@ -1098,6 +1165,10 @@ int CLASS::callOpCode(std::string op, MerlinLine &line) line.flags |= FLAG_FORCELONG; break; } + if (line.expr_value>=0x100) + { + line.flags|=FLAG_FORCEABS; + } auto itr = opcodes.find(Poco::toUpper(op)); @@ -1254,20 +1325,32 @@ void CLASS::initpass(void) passcomplete = false; dumstartaddr = 0; dumstart = 0; - - + truncdata = 0; variables.clear(); // clear the variables for each pass + while (!PCstack.empty()) { PCstack.pop(); } + while (!LUPstack.empty()) + { + LUPstack.pop(); + } + while (!DOstack.empty()) + { + DOstack.pop(); + } + while (!LSTstack.empty()) + { + LSTstack.pop(); + } + curLUP.clear(); + curDO.clear(); savepath = ""; } void CLASS::complete(void) { - printf("\n\n=== Assembly Complete: %d bytes %u errors.\n", PC.totalbytes, errorct); - if (savepath != "") { if (errorct == 0) @@ -1275,6 +1358,10 @@ void CLASS::complete(void) std::string currentdir = Poco::Path::current(); savepath = processFilename(savepath, currentdir, 0); + if (isDebug()>=1) + { + savepath+="1"; // append this to the end to help with testing against other assemblers + } printf("saving to file: %s\n", savepath.c_str()); std::ofstream f(savepath); @@ -1299,13 +1386,16 @@ void CLASS::complete(void) } } + printf("\n\nEnd qASM assembly, %d bytes, %u errors, %lu lines, %lu symbols.\n", PC.totalbytes, errorct, lines.size(), symbols.size()); + + TFileProcessor::complete(); + if (listing) { showSymbolTable(true); showSymbolTable(false); showVariables(); } - TFileProcessor::complete(); } int CLASS::evaluate(MerlinLine &line, std::string expr, int64_t &value) @@ -1538,12 +1628,26 @@ int CLASS::substituteVariables(MerlinLine & line) return (res); } +// this function determines if code generation is turned off (IF,DO,LUP,MAC, etc +bool CLASS::codeSkipped(void) +{ + bool res = false; + + res = (curLUP.lupskip) ? true : res; + res = (curDO.doskip) ? true : res; + + //printf("codeskip: %d\n",res); + + return (res); +} + void CLASS::process(void) { uint32_t l; int x;; char c; char buff[256]; + MerlinLine errLine; std::string op, operand, ls; pass = 0; @@ -1558,6 +1662,8 @@ void CLASS::process(void) 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); @@ -1623,6 +1729,12 @@ void CLASS::process(void) x = callOpCode(op, line); } + 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? @@ -1678,6 +1790,18 @@ void CLASS::process(void) } lineno++; } + + // 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; + } +#endif pass++; } diff --git a/asm.h b/asm.h index 7c36ed2..53d1ded 100644 --- a/asm.h +++ b/asm.h @@ -18,6 +18,8 @@ #define FLAG_BIGNUM 0x10 #define FLAG_INDUM 0x20 +#define FLAG_FORCEADDRPRINT 0x0100 +#define FLAG_NOLINEPRINT 0x2000 #define OP_A 0x0001 #define OP_XY 0x0002 @@ -25,15 +27,15 @@ #define OP_SPECIAL 0x0008 // these bits are actually the CC (last 2 bits) of opcode addressing -#define OP_CLASS0 0x0000 +#define OP_CLASS0 0x0000 #define OP_CLASS1 0x0100 #define OP_CLASS2 0x0200 #define OP_CLASS3 0x0300 // these ORd bits specify specific classes of opcodes and subgroups #define OP_STD (0x1000 | OP_CLASS1) #define OP_ASL (0x2000 | OP_CLASS2) -#define OP_STX (0x3000 | OP_CLASS2) #define OP_C0 (0x4000 | OP_CLASS0) +#define OP_STX (0x8000 | OP_ASL|OP_CLASS2) enum asmErrors { @@ -49,16 +51,22 @@ enum asmErrors errBadBranch, errForwardRef, errNoRedefinition, - errBadOperand, errDupSymbol, errBadDUMop, errOverflow, errRecursiveOp, - errOpcodeNotStarted, - errDuplicateFile, - errFileNotFound, - errFileNoAccess, - errBadEvaluation, + errOpcodeNotStarted, + errDuplicateFile, + errFileNotFound, + errFileNoAccess, + errBadEvaluation, + errIllegalCharOperand, + errBadCharacter, + errUnexpectedOp, + errUnexpectedEOF, + errBadLUPOperand, + errBadLabel, + errBadOperand, errMAX }; @@ -71,22 +79,28 @@ const std::string errStrings[errMAX + 1] = "Unimplemented Instruction", "Fatal", "Unsupported Addressing Mode", - "Unknown Opcode", + "Bad opcode", "Opcode not available under CPU mode", "Byte output differs between passes", "Relative branch offset too large", "Forward Reference to symbol", "Unable to redefine symbol", - "Unable to evaluate", "Duplicate Symbol", "Invalid use of DUM/DEND", "Overflow detected", "Recursive Operand", - "Opcode without start", - "File already included", - "File not found", - "File no access", - "Unable to evaluate", + "Opcode without start", + "File already included", + "File not found", + "File no access", + "Unable to evaluate", + "Illegal char in operand", + "Unexpected character in input", + "Unexpected opcode", + "Unexpected End of File", + "LUP value must be 0 < VAL <= $8000", + "Unknown label", + "Bad operand", "" }; @@ -132,7 +146,7 @@ public: { origin = old.origin; currentpc = old.currentpc; - orgsave=old.orgsave; + orgsave = old.orgsave; totalbytes = old.totalbytes; }; @@ -141,7 +155,7 @@ public: origin = other.origin; currentpc = other.currentpc; totalbytes = other.totalbytes; - orgsave=other.orgsave; + orgsave = other.orgsave; return (*this); }; @@ -150,7 +164,7 @@ public: origin = 0; currentpc = 0; totalbytes = 0; - orgsave=0; + orgsave = 0; }; ~TOriginSection() { @@ -173,7 +187,9 @@ public: std::string comment; std::string addrtext; uint8_t linemx; + uint8_t tabs[16]; bool showmx; + uint8_t truncdata; uint32_t lineno; uint32_t flags; uint16_t opflags; @@ -208,6 +224,8 @@ protected: std::vector filenames; uint8_t syntax; uint64_t starttime; + uint8_t tabs[16]; + uint32_t filecount; // how many files have been read in (because of included files from source public: uint32_t errorct; @@ -215,8 +233,8 @@ public: TFileProcessor(); virtual ~TFileProcessor(); - virtual std::string processFilename(std::string p,std::string currentdir,int level); - virtual int processfile(std::string p,std::string &newfilename); + virtual std::string processFilename(std::string p, std::string currentdir, int level); + virtual int processfile(std::string p, std::string &newfilename); virtual void init(void); virtual int doline(int lineno, std::string line); virtual void process(void); @@ -227,7 +245,6 @@ public: class TMerlinConverter : public TFileProcessor { protected: - uint8_t tabs[10]; std::vector lines; public: @@ -239,6 +256,40 @@ public: virtual void complete(void); }; +class TLUPstruct +{ +public: + TLUPstruct() + { + clear(); + } + void clear(void) { + lupct=0; + lupoffset=0; + luprunning=0; + lupskip=false; + } + uint16_t lupct; + bool lupskip; + uint32_t lupoffset; + uint16_t luprunning; +}; + +class TDOstruct +{ +public: + TDOstruct() + { + clear(); + } + void clear(void) { + doskip=false; + value=0; + } + uint32_t value; + bool doskip; +}; + class TSymbol; typedef int (*TOpCB)(MerlinLine &line, TSymbol &sym); typedef std::function TOpCallback; @@ -280,7 +331,6 @@ class T65816Asm : public TFileProcessor public: // options bool casesen; - bool listing; bool showmx; bool trackrep; bool merlincompat; @@ -304,7 +354,16 @@ public: Poco::HashMap variables; TOriginSection PC; + TLUPstruct curLUP; + TDOstruct curDO; + bool listing; + uint8_t truncdata; // for the TR opcode + std::stack PCstack; + std::stack LUPstack; + std::stack DOstack; + std::stack LSTstack; + TPsuedoOp *psuedoops; uint16_t pass; @@ -330,9 +389,11 @@ public: void initpass(void); void showSymbolTable(bool alpha); void showVariables(void); - int evaluate(MerlinLine &line,std::string expr, int64_t &value); + int evaluate(MerlinLine &line, std::string expr, int64_t &value); int substituteVariables(MerlinLine & line); + bool codeSkipped(void); + int parseOperand(MerlinLine &line); int getAddrMode(MerlinLine &line); void setOpcode(MerlinLine &line, uint8_t op); diff --git a/ciderpress/diskimg/CMakeLists.txt b/ciderpress/diskimg/CMakeLists.txt index eeca5b6..7b4f0d5 100644 --- a/ciderpress/diskimg/CMakeLists.txt +++ b/ciderpress/diskimg/CMakeLists.txt @@ -22,6 +22,8 @@ set(CMAKE_C_FLAGS_RELEASE "${RELEASE_OPT}") set(FIND_LIBRARY_USE_LIB64_PATHS TRUE) +add_subdirectory( ${CMAKE_CURRENT_SOURCE_DIR}/libhfs) + set (SOURCE ASPI.cpp DiskFS.cpp diff --git a/ciderpress/diskimg/DDD.cpp b/ciderpress/diskimg/DDD.cpp index b0c7cb7..c600211 100644 --- a/ciderpress/diskimg/DDD.cpp +++ b/ciderpress/diskimg/DDD.cpp @@ -80,7 +80,7 @@ SST disk. const int kNumSymbols = 256; const int kNumFavorites = 20; const int kRLEDelim = 0x97; // value MUST have high bit set -const int kMaxExcessByteCount = WrapperDDD::kMaxDDDZeroCount + 1; +//const int kMaxExcessByteCount = WrapperDDD::kMaxDDDZeroCount + 1; //const int kTrackLen = 4096; //const int kNumTracks = 35; diff --git a/ciderpress/diskimg/DOS33.cpp b/ciderpress/diskimg/DOS33.cpp index af71f9c..0b61083 100644 --- a/ciderpress/diskimg/DOS33.cpp +++ b/ciderpress/diskimg/DOS33.cpp @@ -20,7 +20,7 @@ * =========================================================================== */ -const int kMaxSectors = 32; +//const int kMaxSectors = 32; const int kSctSize = 256; /* do we need a way to override these? */ diff --git a/ciderpress/diskimg/Gutenberg.cpp b/ciderpress/diskimg/Gutenberg.cpp index 7cc5a5d..7225e66 100644 --- a/ciderpress/diskimg/Gutenberg.cpp +++ b/ciderpress/diskimg/Gutenberg.cpp @@ -64,7 +64,7 @@ header followed by 6502 instructions). There's no apparent link between the value and the type of data in the file. */ -const int kMaxSectors = 32; +//const int kMaxSectors = 32; const int kMaxVolNameLen = 9; const int kSctSize = 256; const int kVTOCTrack = 17; @@ -73,20 +73,22 @@ const int kCatalogEntryOffset = 0x10; // first entry in cat sect starts here const int kCatalogEntrySize = 16; // length in bytes of catalog entries const int kCatalogEntriesPerSect = 15; // #of entries per catalog sector const int kEntryDeleted = 0x40; // this is used to designate deleted files -const int kEntryUnused = 0x00; // this is track# in never-used entries -const int kMaxTSPairs = 0x7a; // 122 entries for 256-byte sectors -const int kTSOffset = 0x0c; // first T/S entry in a T/S list +//const int kEntryUnused = 0x00; // this is track# in never-used entries +//const int kMaxTSPairs = 0x7a; // 122 entries for 256-byte sectors +//const int kTSOffset = 0x0c; // first T/S entry in a T/S list -const int kMaxTSIterations = 32; +//const int kMaxTSIterations = 32; /* * Get a pointer to the Nth entry in a catalog sector. */ +#if 0 static inline uint8_t* GetCatalogEntryPtr(uint8_t* basePtr, int entryNum) { assert(entryNum >= 0 && entryNum < kCatalogEntriesPerSect); return basePtr + kCatalogEntryOffset + entryNum * kCatalogEntrySize; } +#endif /* diff --git a/ciderpress/diskimg/HFS.cpp b/ciderpress/diskimg/HFS.cpp index fb8a7f9..dfd1536 100644 --- a/ciderpress/diskimg/HFS.cpp +++ b/ciderpress/diskimg/HFS.cpp @@ -1771,8 +1771,8 @@ char* A2FileHFS::GetLibHFSPathName(void) const } else if (fileType == 0x04 && auxType == 0x0000) { strcpy(pCreator, "pdos"); strcpy(pType, "TEXT"); - } else if (fileType >= 0 && fileType <= 0xff && - auxType >= 0 && auxType <= 0xffff) + } else if (fileType <= 0xff && + auxType <= 0xffff) { pType[0] = 'p'; pType[1] = (uint8_t) fileType; diff --git a/ciderpress/diskimg/Nibble35.cpp b/ciderpress/diskimg/Nibble35.cpp index a0efeef..67e213d 100644 --- a/ciderpress/diskimg/Nibble35.cpp +++ b/ciderpress/diskimg/Nibble35.cpp @@ -53,7 +53,7 @@ const int kDataChecksumLen = 3; const int kChunkSize35 = 175; // ceil(524 / 3) const int kOffsetToChecksum = 699; const int kNibblizedOutputLen = (kOffsetToChecksum + 4); -const int kMaxDataReach = 48; // should only be 6 bytes */ +//const int kMaxDataReach = 48; // should only be 6 bytes */ enum { kAddrProlog0 = 0xd5, diff --git a/ciderpress/diskimg/OzDOS.cpp b/ciderpress/diskimg/OzDOS.cpp index 9167a40..0bac55d 100644 --- a/ciderpress/diskimg/OzDOS.cpp +++ b/ciderpress/diskimg/OzDOS.cpp @@ -27,12 +27,12 @@ const int kVTOCTrack = 17; const int kVTOCSector = 0; const int kSctSize = 256; -const int kCatalogEntrySize = 0x23; // length in bytes of catalog entries -const int kCatalogEntriesPerSect = 7; // #of entries per catalog sector +//const int kCatalogEntrySize = 0x23; // length in bytes of catalog entries +//const int kCatalogEntriesPerSect = 7; // #of entries per catalog sector const int kMaxTSPairs = 0x7a; // 122 entries for 256-byte sectors -const int kTSOffset = 0x0c; // first T/S entry in a T/S list +//const int kTSOffset = 0x0c; // first T/S entry in a T/S list -const int kMaxTSIterations = 32; +//const int kMaxTSIterations = 32; const int kMaxCatalogIterations = 64; diff --git a/ciderpress/diskimg/Pascal.cpp b/ciderpress/diskimg/Pascal.cpp index 1ebc080..4d615e7 100644 --- a/ciderpress/diskimg/Pascal.cpp +++ b/ciderpress/diskimg/Pascal.cpp @@ -20,7 +20,7 @@ const int kBlkSize = 512; const int kVolHeaderBlock = 2; // first directory block -const int kMaxCatalogIterations = 64; // should be short, linear catalog +//const int kMaxCatalogIterations = 64; // should be short, linear catalog const int kHugeDir = 32; static const char* kInvalidNameChars = "$=?,[#:"; @@ -1506,7 +1506,7 @@ uint32_t A2FilePascal::GetFileType(void) const year = ptm->tm_year; // years since 1900 if (year >= 100) year -= 100; - if (year < 0 || year >= 100) { + if (year >= 100) { LOGW("WHOOPS: got year %u from %d", year, ptm->tm_year); year = 70; } diff --git a/ciderpress/diskimg/ProDOS.cpp b/ciderpress/diskimg/ProDOS.cpp index 2a60d10..02b78d6 100644 --- a/ciderpress/diskimg/ProDOS.cpp +++ b/ciderpress/diskimg/ProDOS.cpp @@ -1975,7 +1975,7 @@ DIError DiskFSProDOS::CreateFile(const CreateParms* pParms, A2File** ppNewFile) */ dirEntryPtr[0x00] = (pParms->storageType << 4) | strlen(upperName); strncpy((char*) &dirEntryPtr[0x01], upperName, A2FileProDOS::kMaxFileName); - if (pParms->fileType >= 0 && pParms->fileType <= 0xff) + if (pParms->fileType <= 0xff) dirEntryPtr[0x10] = (uint8_t) pParms->fileType; else dirEntryPtr[0x10] = 0; // HFS long type? @@ -1996,7 +1996,7 @@ DIError DiskFSProDOS::CreateFile(const CreateParms* pParms, A2File** ppNewFile) PutShortLE(&dirEntryPtr[0x1c], 0); // version, min_version } dirEntryPtr[0x1e] = pParms->access; - if (pParms->auxType >= 0 && pParms->auxType <= 0xffff) + if (pParms->auxType <= 0xffff) PutShortLE(&dirEntryPtr[0x1f], (uint16_t) pParms->auxType); else PutShortLE(&dirEntryPtr[0x1f], 0); diff --git a/ciderpress/diskimg/UNIDOS.cpp b/ciderpress/diskimg/UNIDOS.cpp index f47dd7a..f33144e 100644 --- a/ciderpress/diskimg/UNIDOS.cpp +++ b/ciderpress/diskimg/UNIDOS.cpp @@ -31,13 +31,13 @@ const int kVTOCTrack = 17; const int kVTOCSector = 0; const int kSctSize = 256; -const int kCatalogEntrySize = 0x23; // length in bytes of catalog entries -const int kCatalogEntriesPerSect = 7; // #of entries per catalog sector +//const int kCatalogEntrySize = 0x23; // length in bytes of catalog entries +//const int kCatalogEntriesPerSect = 7; // #of entries per catalog sector const int kMaxTSPairs = 0x7a; // 122 entries for 256-byte sectors -const int kTSOffset = 0x0c; // first T/S entry in a T/S list +//const int kTSOffset = 0x0c; // first T/S entry in a T/S list -const int kMaxTSIterations = 32; -const int kMaxCatalogIterations = 64; +//const int kMaxTSIterations = 32; +//const int kMaxCatalogIterations = 64; /* diff --git a/ciderpress/diskimg/libhfs/CMakeLists.txt b/ciderpress/diskimg/libhfs/CMakeLists.txt index 5a5c63c..185b3e3 100644 --- a/ciderpress/diskimg/libhfs/CMakeLists.txt +++ b/ciderpress/diskimg/libhfs/CMakeLists.txt @@ -3,7 +3,7 @@ set(CMAKE_BUILD_TYPE DEBUG) set(BASE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) -set(PROJECT_NAME diskimg) +set(PROJECT_NAME hfs) set(PROJECT_ROOT ${CMAKE_CURRENT_SOURCE_DIR}) project(${PROJECT_NAME}) diff --git a/ciderpress/nufxlib/Archive.c b/ciderpress/nufxlib/Archive.c index 7c97cb3..616573f 100644 --- a/ciderpress/nufxlib/Archive.c +++ b/ciderpress/nufxlib/Archive.c @@ -862,8 +862,15 @@ static NuError Nu_OpenTempFile(UNICHAR* fileNameUNI, FILE** pFp) #else char* result; +#if 1 DBUG(("+++ Using mktemp\n")); result = mktemp(fileNameUNI); +#else + char fbuff[256]; + sprintf(fbuff,"%s%s",fileNameUNI,"XXXXXX"); + result=mkstemp(); +#endif + if (result == NULL) { Nu_ReportError(NU_BLOB, kNuErrNone, "mktemp failed on '%s'", fileNameUNI); diff --git a/opcodes.cpp b/opcodes.cpp index 2aacfa6..ba86a8a 100644 --- a/opcodes.cpp +++ b/opcodes.cpp @@ -449,6 +449,7 @@ int CLASS::doBase6502(MerlinLine & line, TSymbol & sym) cc = (sym.stype >> 8) & 0x03; amode = 0xFF; + if ((sym.stype & OP_C0) == OP_C0) { uint8_t cc = 0; @@ -540,15 +541,25 @@ int CLASS::doBase6502(MerlinLine & line, TSymbol & sym) } if ((opflags & OP_STX) == OP_STX) - //if ((opcode == "STX") || (opcode == "LDX") || (opcode == "DEC") || (opcode == "INC")) { if (m == syn_implied) { err = true; } - if (m == syn_absx) + if (m==syn_imm) { - //err = true; + if ((mx&0x01)==0) + { + bytelen++; + } + } + if ((m == syn_absx) || (m == syn_abs) || (m==syn_absy)) + { + if ((line.flags & FLAG_FORCEABS) || (line.expr_value >= 0x100)) + { + bytelen++; + amode += 2; + } } if (cpumode >= MODE_65C02) { @@ -576,11 +587,25 @@ int CLASS::doBase6502(MerlinLine & line, TSymbol & sym) } } } - if (line.flags&FLAG_FORCELONG) + else { - line.setError(errBadAddressMode); + if ((m == syn_absx) || (m==syn_abs)) + { + if ((line.flags & FLAG_FORCEABS) || (line.expr_value >= 0x100)) + { + bytelen++; + amode += 2; + } + } + } - goto out; + + if (line.flags & FLAG_FORCELONG) + { + err = errBadAddressMode; + //line.setError(errBadAddressMode); + } + goto outop; } if (m == syn_imm) @@ -598,16 +623,9 @@ int CLASS::doBase6502(MerlinLine & line, TSymbol & sym) else if ((m == syn_abs) || (m == syn_absx) || (m == syn_absy)) { - if (isDebug() > 2) - { - printf("flgs=%08X\n", line.flags); - } - - - if ((((line.flags & FLAG_DP) == 0) && ((line.flags & FLAG_FORCEDP) == 0)) - || (line.flags & FLAG_FORCEABS) - ) + || (line.flags & FLAG_FORCEABS) + ) { bytelen++; if (amode != 6) @@ -648,7 +666,7 @@ int CLASS::doBase6502(MerlinLine & line, TSymbol & sym) { if (line.flags & FLAG_FORCELONG) { - bytelen=3; + bytelen = 3; } } @@ -657,6 +675,7 @@ int CLASS::doBase6502(MerlinLine & line, TSymbol & sym) } +outop: op |= (amode & 0x07) << 2; op |= cc; @@ -738,7 +757,7 @@ void CLASS::insertOpcodes(void) pushopcode("PAG", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("TTL", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("SKP", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); - pushopcode("TR", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); + pushopcode("TR", P_TR, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("ASC", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("DCI", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("INV", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); @@ -751,18 +770,18 @@ void CLASS::insertOpcodes(void) pushopcode("DFB", P_DATA, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("DB", P_DATA, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("ADR", P_DATA, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); - pushopcode("ADRL",P_DATA, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); + pushopcode("ADRL", P_DATA, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("HEX", P_HEX, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("DS", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); - pushopcode("DO", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); - pushopcode("ELSE", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); - pushopcode("IF", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); - pushopcode("FIN", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); + pushopcode("DO", P_DO, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); + pushopcode("ELSE", P_DO, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); + pushopcode("IF", P_DO, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); + pushopcode("FIN", P_DO, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("CHK", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("ERR", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("KBD", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); - pushopcode("LUP", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); - pushopcode("--^", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); + pushopcode("LUP", P_LUP, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); + pushopcode("--^", P_LUP, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("MX", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doMX)); pushopcode("PAU", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("SW", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); @@ -773,9 +792,9 @@ void CLASS::insertOpcodes(void) pushopcode("<<<", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); - pushopcode("ADC", 0x03, OP_STD|OP_A, OPHANDLER(&CLASS::doBase6502)); - pushopcode("AND", 0x01, OP_STD|OP_A, OPHANDLER(&CLASS::doBase6502)); - pushopcode("ASL", 0x00, OP_ASL|OP_A, OPHANDLER(&CLASS::doBase6502)); + pushopcode("ADC", 0x03, OP_STD | OP_A, OPHANDLER(&CLASS::doBase6502)); + pushopcode("AND", 0x01, OP_STD | OP_A, OPHANDLER(&CLASS::doBase6502)); + pushopcode("ASL", 0x00, OP_ASL | OP_A, OPHANDLER(&CLASS::doBase6502)); pushopcode("BCC", 0x02, 0, OPHANDLER(&CLASS::doBRANCH)); pushopcode("BLT", 0x02, 0, OPHANDLER(&CLASS::doBRANCH)); pushopcode("BCS", 0x82, 0, OPHANDLER(&CLASS::doBRANCH)); @@ -799,25 +818,25 @@ void CLASS::insertOpcodes(void) pushopcode("COP", 0x02, 1, OPHANDLER(&CLASS::doAddress)); pushopcode("CPX", 0x07, OP_C0 | OP_XY, OPHANDLER(&CLASS::doBase6502)); pushopcode("CPY", 0x06, OP_C0 | OP_XY, OPHANDLER(&CLASS::doBase6502)); - pushopcode("DEC", 0x06, OP_STX | OP_SPECIAL |OP_A, OPHANDLER(&CLASS::doBase6502)); + pushopcode("DEC", 0x06, OP_STX | OP_SPECIAL | OP_A, OPHANDLER(&CLASS::doBase6502)); pushopcode("DEX", 0xCA, OP_XY, OPHANDLER(&CLASS::doBYTE)); pushopcode("DEY", 0x88, OP_XY, OPHANDLER(&CLASS::doBYTE)); - pushopcode("EOR", 0x02, OP_STD|OP_A, OPHANDLER(&CLASS::doBase6502)); - pushopcode("INC", 0x07, OP_STX|OP_A | OP_SPECIAL, OPHANDLER(&CLASS::doBase6502)); + pushopcode("EOR", 0x02, OP_STD | OP_A, OPHANDLER(&CLASS::doBase6502)); + pushopcode("INC", 0x07, OP_STX | OP_A | OP_SPECIAL, OPHANDLER(&CLASS::doBase6502)); pushopcode("INX", 0xE8, 0, OPHANDLER(&CLASS::doBYTE)); pushopcode("INY", 0xC8, 0, OPHANDLER(&CLASS::doBYTE)); pushopcode("JML", 0x00, 0, OPHANDLER(&CLASS::doJMP)); pushopcode("JMP", 0x01, 0, OPHANDLER(&CLASS::doJMP)); pushopcode("JSL", 0x02, 0, OPHANDLER(&CLASS::doJMP)); pushopcode("JSR", 0x03, 0, OPHANDLER(&CLASS::doJMP)); - pushopcode("LDA", 0x05, OP_STD|OP_A, OPHANDLER(&CLASS::doBase6502)); - pushopcode("LDX", 0x05, OP_STX|OP_XY, OPHANDLER(&CLASS::doBase6502)); - pushopcode("LDY", 0x05, OP_C0|OP_XY, OPHANDLER(&CLASS::doBase6502)); - pushopcode("LSR", 0x02, OP_ASL|OP_A, OPHANDLER(&CLASS::doBase6502)); + pushopcode("LDA", 0x05, OP_STD | OP_A, OPHANDLER(&CLASS::doBase6502)); + pushopcode("LDX", 0x05, OP_STX | OP_XY, OPHANDLER(&CLASS::doBase6502)); + pushopcode("LDY", 0x05, OP_C0 | OP_XY, OPHANDLER(&CLASS::doBase6502)); + pushopcode("LSR", 0x02, OP_ASL | OP_A, OPHANDLER(&CLASS::doBase6502)); pushopcode("MVN", 0x00, 0, OPHANDLER(&CLASS::doMVN)); 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("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)); @@ -835,20 +854,20 @@ void CLASS::insertOpcodes(void) pushopcode("PLX", 0xFA, 0, OPHANDLER(&CLASS::doBYTE)); pushopcode("PLY", 0x7A, 0, OPHANDLER(&CLASS::doBYTE)); pushopcode("REP", 0xC2, 1, OPHANDLER(&CLASS::doAddress)); - pushopcode("ROL", 0x01, OP_ASL|OP_A, OPHANDLER(&CLASS::doBase6502)); - pushopcode("ROR", 0x03, OP_ASL|OP_A, OPHANDLER(&CLASS::doBase6502)); + pushopcode("ROL", 0x01, OP_ASL | OP_A, OPHANDLER(&CLASS::doBase6502)); + pushopcode("ROR", 0x03, OP_ASL | OP_A, OPHANDLER(&CLASS::doBase6502)); pushopcode("RTI", 0x40, 0, OPHANDLER(&CLASS::doBYTE)); pushopcode("RTL", 0x6B, 0, OPHANDLER(&CLASS::doBYTE)); pushopcode("RTS", 0x60, 0, OPHANDLER(&CLASS::doBYTE)); - pushopcode("SBC", 0x07, OP_STD|OP_A, OPHANDLER(&CLASS::doBase6502)); + pushopcode("SBC", 0x07, OP_STD | OP_A, OPHANDLER(&CLASS::doBase6502)); pushopcode("SEC", 0x38, 0, OPHANDLER(&CLASS::doBYTE)); pushopcode("SED", 0xF8, 0, OPHANDLER(&CLASS::doBYTE)); pushopcode("SEI", 0x78, 0, OPHANDLER(&CLASS::doBYTE)); pushopcode("SEP", 0xE2, 1, OPHANDLER(&CLASS::doAddress)); pushopcode("STP", 0xDB, 0, OPHANDLER(&CLASS::doBYTE)); - pushopcode("STA", 0x04, OP_STD|OP_A, OPHANDLER(&CLASS::doBase6502)); - pushopcode("STX", 0x04, OP_STX|OP_XY, OPHANDLER(&CLASS::doBase6502)); - pushopcode("STY", 0x04, OP_C0|OP_XY, OPHANDLER(&CLASS::doBase6502)); + pushopcode("STA", 0x04, OP_STD | OP_A, OPHANDLER(&CLASS::doBase6502)); + pushopcode("STX", 0x04, OP_STX | OP_XY, OPHANDLER(&CLASS::doBase6502)); + pushopcode("STY", 0x04, OP_C0 | OP_XY, OPHANDLER(&CLASS::doBase6502)); pushopcode("STZ", 0x01, OP_A, OPHANDLER(&CLASS::doNoPattern)); pushopcode("TAX", 0xAA, 0, OPHANDLER(&CLASS::doBYTE)); pushopcode("TAY", 0xA8, 0, OPHANDLER(&CLASS::doBYTE)); diff --git a/psuedo.cpp b/psuedo.cpp index a93ba13..ff7f736 100644 --- a/psuedo.cpp +++ b/psuedo.cpp @@ -13,6 +13,200 @@ CLASS::~CLASS() } + +int CLASS::doDO(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) +{ + UNUSED(opinfo); + + TEvaluator eval(a); + + int64_t eval_result = 0; + uint8_t shift; + uint32_t result32; + int res = 0; + int err = 0; + + std::string op = Poco::toUpper(line.opcode); + std::string oper = line.operand_expr; + result32 = 0xFFFFFFFF; + + if (op == "IF") + { + if (oper == "") + { + err = errIllegalCharOperand; + } + goto out; + } + if (op == "DO") + { + + a.DOstack.push(a.curDO); + + if (oper == "") + { + err = errIllegalCharOperand; + a.curDO.doskip = false; + goto out; + } + + shift = 0; + eval_result = 0; + int x = eval.evaluate(line.operand_expr, eval_result, shift); + + if (x < 0) + { + a.curDO.doskip = false; + err = errBadLabel; + if (a.pass == 0) + { + err = errForwardRef; + } + goto out; + } + + result32 = eval_result & 0xFFFFFFFF; + a.curDO.doskip = (result32 != 0) ? false : true; + + goto out; + } + + if (op == "ELSE") + { + if (a.DOstack.size() > 0) + { + //line.flags |= FLAG_NOLINEPRINT; + a.curDO.doskip = !a.curDO.doskip; + } + else + { + err = errUnexpectedOp; + } + goto out; + } + + if (op == "FIN") + { + //line.flags |= FLAG_NOLINEPRINT; + + if (a.DOstack.size() > 0) + { + a.curDO = a.DOstack.top(); + a.DOstack.pop(); + } + else + { + // kind of a silent error here, just make sure we reinitialize + err = errUnexpectedOp; + a.curDO.doskip = false; + } + goto out; + } + +out: + //printf("DO eval: %08X %s\n", result32, a.curDO.doskip ? "true" : "false"); + + if (err > 0) + { + line.setError(err); + } + return (res); +} + +int CLASS::doLUP(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) +{ + UNUSED(opinfo); + + TEvaluator eval(a); + + int64_t eval_result = 0; + uint8_t shift; + int lidx, len; + int res = 0; + int err = 0; + + std::string op = Poco::toUpper(line.opcode); + + if (op == "LUP") + { + line.flags |= FLAG_NOLINEPRINT; + len = line.lineno - 1; // MerlinLine line numbers are +1 from actual array idx + if (len >= 0) + { + + shift = 0; + eval_result = 0; + int x = eval.evaluate(line.operand_expr, eval_result, shift); + + a.LUPstack.push(a.curLUP); + + a.curLUP.lupoffset = len; + a.curLUP.lupct = eval_result & 0xFFFF; // evaluate here + a.curLUP.luprunning++; + + if ((x < 0) || (eval_result <= 0) || (eval_result > 0x8000)) + { + // merlin just ignores LUP if the value is out of range + a.curLUP.lupct = 0; + a.curLUP.lupskip = true; + } + } + else + { + err = errUnexpectedOp; + } + } + + if (op == "--^") + { + line.flags |= FLAG_NOLINEPRINT; + + if (a.curLUP.luprunning > 0) + { + lidx = line.lineno - 1; + len = lidx - a.curLUP.lupoffset - 1; + + if (a.curLUP.lupct > 0) + { + a.curLUP.lupct--; + if (a.curLUP.lupct != 0) + { + a.lineno = a.curLUP.lupoffset; + goto out; + } + } + // kind of a silent error here, just make sure we reinitialize + a.curLUP.luprunning = 0; + a.curLUP.lupct = 0; + a.curLUP.lupskip = false; + + //printf("start=%d end=%d len=%d\n", a.curLUP.lupoffset, lidx, len); + if (a.LUPstack.size() > 0) + { + a.curLUP = a.LUPstack.top(); + a.LUPstack.pop(); + } + else + { + err = errUnexpectedOp; + } + } + else + { + a.curLUP.lupskip = false; + // SGQ - found a '--^' without a LUP, should we just ignore? + //err = errUnexpectedOp; + } + } + +out: + if (err > 0) + { + line.setError(err); + } + return (res); +} + constexpr unsigned int strhash(const char *str, int h = 0) { return !str[h] ? 5381 : (strhash(str, h + 1) * 33) ^ str[h]; @@ -27,7 +221,7 @@ int CLASS::doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) int outct = 0; int wordsize = 2; int endian = 0; - std::string oper = line.operand; + std::string oper = line.operand_expr; std::string op = Poco::toUpper(Poco::trim(line.opcode)); Poco::StringTokenizer tok(oper, ",", Poco::StringTokenizer::TOK_TRIM | Poco::StringTokenizer::TOK_IGNORE_EMPTY); @@ -55,7 +249,7 @@ int CLASS::doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) wordsize = 4; break; default: - wordsize=0; + wordsize = 0; break; } @@ -70,7 +264,7 @@ int CLASS::doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) int r; uint8_t b; - shift=0; + shift = 0; r = eval.evaluate(expr, eval_result, shift); if (r < 0) { @@ -80,17 +274,17 @@ int CLASS::doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) line.setError(errBadEvaluation); } } - if (shift=='>') + if (shift == '>') { - eval_result=(eval_result) & 0xFF; + eval_result = (eval_result) & 0xFF; } - if (shift=='<') + if (shift == '<') { - eval_result=(eval_result>>8) & 0xFF; + eval_result = (eval_result >> 8) & 0xFF; } - else if ((shift=='^') || (shift=='|')) + else if ((shift == '^') || (shift == '|')) { - eval_result=(eval_result>>16)&0xFF; + eval_result = (eval_result >> 16) & 0xFF; } @@ -101,7 +295,7 @@ int CLASS::doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) { for (i = 0; i < wordsize; i++) { - b=(eval_result >> (8 * i))&0xFF; + b = (eval_result >> (8 * i)) & 0xFF; line.outbytes.push_back(b); //printf("%02X\n",b); } @@ -111,7 +305,7 @@ int CLASS::doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) // big endian for (i = 0; i < wordsize; i++) { - b=(eval_result >> ((wordsize-1-i) * 8))&0xFF; + b = (eval_result >> ((wordsize - 1 - i) * 8)) & 0xFF; line.outbytes.push_back(b); //printf("%02X\n",b); } @@ -119,13 +313,7 @@ int CLASS::doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) } } } -#if 0 - // SGQ - remove when complete - line.datafillct = outct; - line.datafillbyte = 0xCA; - // =============== -#endif - line.outbytect=outct; + line.outbytect = outct; return (outct); } @@ -149,16 +337,6 @@ int CLASS::doDS(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) line.datafillbyte = line.eval_result & 0xFF; line.datafillct = v; -#if 0 - if (a.pass > 0) - { - for (int i = 0; i < v; i++) - { - line.outbytes.push_back(0x00); - } - line.outbytect = v; - } -#endif } return (res); @@ -196,8 +374,16 @@ int CLASS::doLST(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) std::string s; if (a.pass > 0) { - s = Poco::toUpper(Poco::trim(line.operand)); - if ((s == "") || (s == "ON") || (line.expr_value > 0)) + s = Poco::toUpper(Poco::trim(line.operand_expr)); + if (s == "RTN") + { + if (a.LSTstack.size()) + { + a.listing = a.LSTstack.top(); + a.LSTstack.pop(); + } + } + else if ((s == "ON") || (line.expr_value > 0)) { //printf("ON\n"); a.skiplist = true; @@ -213,15 +399,46 @@ int CLASS::doLST(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) return (0); } +int CLASS::doTR(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) +{ + UNUSED(opinfo); + + std::string s; + if (a.pass > 0) + { + s = Poco::toUpper(Poco::trim(line.operand_expr)); + if (s == "ADR") + { + a.truncdata |= 0x03; + } + else if ((s == "ON") || (line.expr_value > 0)) + { + a.truncdata |= 0x01;; + } + else if ((s == "OFF") || (line.expr_value == 0)) + { + a.truncdata = 0x00; + } + } + return (0); +} int CLASS::doHEX(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) { UNUSED(opinfo); - std::string os = Poco::toUpper(Poco::trim(line.operand)); + std::string os = Poco::toUpper(Poco::trim(line.operand_expr)); uint32_t bytect = 0; uint8_t b = 0; uint8_t ct = 0; + + if (os.length() == 0) + { + // case where HEX has no operand, Merlin does not flag as error + //line.setError(errIllegalCharOperand); + bytect = 0; + goto out; + } for ( uint32_t i = 0; i < os.length(); ++i ) { char c = os[i]; @@ -244,8 +461,9 @@ int CLASS::doHEX(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) } else { - line.setError(errBadOperand); - return 0; + line.setError(errIllegalCharOperand); + bytect = 0; + goto out; } // Got a good char, append to hex string and see if we've got a byte @@ -268,10 +486,14 @@ int CLASS::doHEX(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) b = 0; bytect++; } - } + if (ct & 0x01) // we got an odd number of nibbles + { + line.setError(errBadOperand); + bytect = 0; + } +out: line.outbytect = bytect; - //printf("bytect=%d\n",bytect); return bytect; } @@ -297,9 +519,11 @@ int CLASS::ProcessOpcode(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) case P_DUM: case P_DEND: res = doDUM(a, line, opinfo); + line.flags |= FLAG_FORCEADDRPRINT; + break; case P_ORG: - if (line.operand.length() > 0) + if (line.operand_expr.length() > 0) { a.PC.orgsave = a.PC.currentpc; a.PC.currentpc = line.expr_value; @@ -310,6 +534,7 @@ int CLASS::ProcessOpcode(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) a.PC.currentpc = a.PC.orgsave; line.startpc = a.PC.orgsave; } + line.flags |= FLAG_FORCEADDRPRINT; break; case P_SAV: a.savepath = a.processFilename(line.operand, Poco::Path::current(), 0); @@ -323,6 +548,16 @@ int CLASS::ProcessOpcode(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) case P_DATA: res = doDATA(a, line, opinfo); break; + case P_LUP: + res = doLUP(a, line, opinfo); + break; + case P_DO: + res = doDO(a, line, opinfo); + break; + case P_TR: + res=doTR(a,line,opinfo); + break; + } return (res); } diff --git a/psuedo.h b/psuedo.h index 3845232..d59a38f 100644 --- a/psuedo.h +++ b/psuedo.h @@ -15,6 +15,9 @@ enum P_USE, P_HEX, P_DATA, + P_LUP, + P_DO, + P_TR, P_MAX }; @@ -30,6 +33,9 @@ public: int doDS(T65816Asm &a, MerlinLine &line, TSymbol &opinfo); int doHEX(T65816Asm &a, MerlinLine &line, TSymbol &opinfo); int doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo); + int doLUP(T65816Asm &a, MerlinLine &line, TSymbol &opinfo); + int doDO(T65816Asm &a, MerlinLine &line, TSymbol &opinfo); + int doTR(T65816Asm &a, MerlinLine &line, TSymbol &opinfo); }; #undef CLASS \ No newline at end of file diff --git a/qasm.cpp b/qasm.cpp index 22e034d..958c157 100644 --- a/qasm.cpp +++ b/qasm.cpp @@ -1,5 +1,8 @@ #include "app.h" #include "asm.h" +#ifdef CIDERPRESS +#include "DiskImg.h" +#endif #define CLASS PAL_APPCLASS @@ -28,6 +31,14 @@ void CLASS::displayVersion() s = "-debug"; #endif cerr << "quickASM 16++ v" << (std::string)STRINGIFY(APPVERSION) << s << endl; + +#ifdef CIDERPRESS + DiskImgLib::Global::AppInit(); + DiskImgLib::DiskImg prodos; + + DiskImgLib::Global::AppCleanup(); +#endif + } int CLASS::runServerApp(PAL_EVENTMANAGER *em) diff --git a/qasm.h b/qasm.h index 1cc8b2d..a9e0002 100644 --- a/qasm.h +++ b/qasm.h @@ -1,11 +1,16 @@ #pragma once -#include "inttypes.h" +#include + #include "palPoco.h" #include "pallogger.h" #include "eventtask.h" #include "baseapp.h" #include "httpserver.h" +#ifndef UNUSED +#define UNUSED (void) +#endif + #define CLASS PAL_APPCLASS using namespace PAL_NAMESPACE; diff --git a/qasm.ini b/qasm.ini index 4e41bc8..8e64e5e 100644 --- a/qasm.ini +++ b/qasm.ini @@ -4,7 +4,7 @@ logdir=/var/log/mylog logfile=mylog.log [option] -debug=1 +debug=2 nocolor=false ;debug must be an integer. Code can use this as a level @@ -31,7 +31,7 @@ merlincompatible=true symcolumns=3 [reformat] -tabs=12; 18; 36 +tabs=12; 18; 30 ;tabs=0;0;0 diff --git a/src/main.s b/src/main.s index 560694e..ce2e595 100644 --- a/src/main.s +++ b/src/main.s @@ -1,399 +1,406 @@ - lst off + ;lst off * * main.s * Merlin32 Test * * Created by Lane Roathe on 8/26/19. -* Copyright © 2019 Ideas From the Deep. All rights reserved. +* Copyright B) 2019 Ideas From the Deep. All rights reserved. * //]XCODESTART ; Keep this at the start and put your code after this - xc off - xc - xc - mx %00 + xc off + xc + xc + mx %00 + *========================================================== * monitor addresses - -TEXT = $FB39 ;Reset text window -TABV = $FB5B ;Complete vtab, using contents of 'A' -MONBELL = $FBE4 ;random bell noise! -HOME = $FC58 ;Clear text window -WAIT = $FCA8 ;delay routine -CROUT = $FD8E ;Print a CR -PRBYTE = $FDDA ;Print 'A' as a hex number -PRHEX = $FDE3 ;as above, but bits 0-3 only -COUT = $FDED ;Monitor char out -MOVE = $FE2C ;memory move routine -INVERSE = $FE80 ;Print in inverse -NORMAL = $FE84 ;Normal print +TEXT = $FB39 ;Reset text window +TABV = $FB5B ;Complete vtab, using contents of 'A' +MONBELL = $FBE4 ;random bell noise! +HOME = $FC58 ;Clear text window +WAIT = $FCA8 ;delay routine +CROUT = $FD8E ;Print a CR +PRBYTE = $FDDA ;Print 'A' as a hex number +PRHEX = $FDE3 ;as above, but bits 0-3 only +COUT = $FDED ;Monitor char out +MOVE = $FE2C ;memory move routine +INVERSE = $FE80 ;Print in inverse +NORMAL = $FE84 ;Normal print * Jump Vectors -CONNECT = $3EA ;Connect DOS -DOSWARM = $3D0 ;exit to DOS prompt -RSTVEC = $3F2 ;reset vector +CONNECT = $3EA ;Connect DOS +DOSWARM = $3D0 ;exit to DOS prompt +RSTVEC = $3F2 ;reset vector -TSTADDR = $1000 ;absolute address for testing +TSTADDR = $1000 ;absolute address for testing *========================================================== * Data Index DUM section test - lst - DUM 0 -dum0 ds 1 ;fractional byte -dum1 ds 1 -dumSize = * - DEND - ;lst off + DUM 0 +dum0 ds 1 ;fractional byte +dum1 ds 1 +dumSize = * + DEND + ;lst off *========================================================== * zero page (all zp var names are prefixed with _) - DUM 0 + DUM 0 -_ptr ds 2 -_tmp ds 2 +_ptr ds 2 +_tmp ds 2 -_num1 ds dumSize ;first and second operand values +_num1 ds dumSize ;first and second operand values -; test ORG with DUM section + ; test ORG with DUM section - ORG $20 + ORG $20 -_LFT ds 1 ;Window edge 0..39 +_LFT ds 1 ;Window edge 0..39 - DEND + DEND *========================================================== * Program Entry -;Issue #26 - This should start at the ORG in the linkscript, not at the last ORG in the DUM sections. -START + ;Issue #26 - This should start at the ORG in the linkscript, not at the last ORG in the DUM sections. +START -; PUT current issue here, so it's the first thing assembled. -; The rest below are unit tests to make sure future changes don't break existing code! + ; PUT current issue here, so it's the first thing assembled. + ; The rest below are unit tests to make sure future changes don't break existing code! -; START OF TESTS KNOWN TO HAVE PASSED IN PREVIOUS BUILDS + ; START OF TESTS KNOWN TO HAVE PASSED IN PREVIOUS BUILDS -; --- Test all instructions in all their modes, with as many variants as possible --- + ; --- Test all instructions in all their modes, with as many variants as possible --- - - -;adc (ZP,x) - adc (0,x) - adc ($80,x) - adc (_tmp,x) - adc (_tmp+0,x) - adc (_tmp+$10,x) - adc ($10+_tmp,x) - adc (_tmp+dum0,x) - adc (_tmp+dum1,x) - adc (_tmp+dum1+1,x) - adc (_tmp+dum0+dum1,x) - - adc 0 - adc $80 - adc _tmp - adc #0 - adc #$1111 - adc $1111 - -; --- Other tests that have proven helpful --- - -; Tests regarding issues with math and zp,x - sta TSTADDR+dum0 - sta TSTADDR+_num1+dum0 - sta TSTADDR+_num1+dum0,x - - lda _num1+dum0 - adc _num1+dum1 - sbc _num1+dum1 - bit _num1+dum0 - sta _num1+dum0 ;(FIXED): can't use sta _num1+dum0 - stz _num1+dum0 - - lda _num1+dum0,x - adc _num1+dum0,x - sbc _num1+dum0,x - bit _num1+dum0,x - sta _num1+dum0,x - stz _num1+dum0,x - - lda _num1+dum0,y ;these assemble to abs accesses: lda $00C0,y - adc _num1+dum0,y - sbc _num1+dum0,y - sta _num1+dum0,y - -; Label & branching tests -GetKey ldx $C000 - bpl GetKey -]loop - dex - bne ]loop - - tya - and #1 - beq :err - - tya - and #1 - bne :good -:err - lda #0 -:good - bne myQuit - nop - hex 2C ;bit - lda #1 -myQuit - jmp DOSWARM - -; --- Tests used when addressing issues opened against Merlin32 --- - -;Issue #26 (lroathe) - ORG in DUM section is ignored, but can't mess up code ORG - - org $2000 - - lda _LFT - ldx #_LFT - cpx #$20 - - org ;return to ongoing address - - lst - lda $FF -;Issue #16 (fadden) - Byte reference modifiers are ignored (no way to force DP) - lda <$fff0 ;zp - lda >$fff0 ;ABS (lo word) - lda ^$fff0 ;ABS (hi word) - lda |$fff0 ;ABS (long in 65816 mode) - - lda $08 - lda $0008 - lda $FFFF-$FFF7 - lda $FFF0+24 - ldaz $FFF0+24 ; forced DP - - - ldaz $FFFF ; forced DP - lda: $FFFF ; forced ABS (any char but 'L', 'D', and 'Z" - ldal $FFFF ; forced long abs (3 byte address) - - ldaz $05 - lda: $05 - ldal $05 - - lda $45 - lda $2345 - lda $012345 - ldaz $2345 - lda: $45 - ldal $012345 - ldal $2345 - ldal $45 - lda <$2345 - lda >$2345 - lda <$012345 - lda >$012345 - lda ^$012345 - lda |$012345 - - ora $45 - ora $2345 - ora $012345 - oraz $2345 - ora: $45 - oral $012345 - oral $2345 - oral $45 - ora <$2345 - ora >$2345 - ora <$012345 - ora >$012345 - ora ^$012345 - ora |$012345 - - and $45 - and $2345 - and $012345 - andz $2345 - and: $45 - andl $012345 - andl $2345 - andl $45 - and <$2345 - and >$2345 - and <$012345 - and >$012345 - and ^$012345 - and |$012345 - - eor $45 - eor $2345 - eor $012345 - eorz $2345 - eor: $45 - eorl $012345 - eorl $2345 - eorl $45 - eor <$2345 - eor >$2345 - eor <$012345 - eor >$012345 - eor ^$012345 - eor |$012345 - - adc $45 - adc $2345 - adc $012345 - adcz $2345 - adc: $45 - adcl $012345 - adcl $2345 - adcl $45 - adc <$2345 - adc >$2345 - adc <$012345 - adc >$012345 - adc ^$012345 - adc |$012345 - - sta $45 - sta $2345 - sta $012345 - staz $2345 - sta: $45 - stal $012345 - stal $2345 - stal $45 - sta <$2345 - sta >$2345 - sta <$012345 - sta >$012345 - sta ^$012345 - sta |$012345 - - cmp $45 - cmp $2345 - cmp $012345 - cmpz $2345 - cmp: $45 - cmpl $012345 - cmpl $2345 - cmpl $45 - cmp <$2345 - cmp >$2345 - cmp <$012345 - cmp >$012345 - cmp ^$012345 - cmp |$012345 - - sbc $45 - sbc $2345 - sbc $012345 - sbcz $2345 - sbc: $45 - sbcl $012345 - sbcl $2345 - sbcl $45 - sbc <$2345 - sbc >$2345 - sbc <$012345 - sbc >$012345 - sbc ^$012345 - sbc |$012345 - - asll $1234 - - lda <$fff0+24 ;zp - lda >$fff0+24 ;ABS (lo word) - lda ^$fff0+24 ;ABS (hi word) - lda |$fff0+24 ;ABS (long in 65816 mode) - - mx %11 - - lda #<$fff0+24 ;byte - lda #>$fff0+24 ;page - lda #^$fff0+24 ;bank - - lda #<$1234 ;byte - lda #>$1234 ;page - lda #^$1234 ;bank - lda #^$A51234 ;bank + ;adc (ZP,x) + adc (0,x) - mx %00 + adc ($80,x) + adc (_tmp,x) + adc (_tmp+0,x) + adc (_tmp+$10,x) + adc ($10+_tmp,x) + adc (_tmp+dum0,x) + adc (_tmp+dum1,x) + adc (_tmp+dum1+1,x) + adc (_tmp+dum0+dum1,x) - lda #<$fff0+24 ;byte - lda #>$fff0+24 ;page - lda #^$fff0+24 ;bank + adc 0 + adc $80 + adc _tmp + adc #0 + adc #$1111 + adc $1111 - lda #<$1234 ;byte - lda #>$1234 ;page - lda #^$1234 ;bank - lda #^$A51234 ;bank + ; --- Other tests that have proven helpful --- + + ; Tests regarding issues with math and zp,x + sta TSTADDR+dum0 + sta TSTADDR+_num1+dum0 + sta TSTADDR+_num1+dum0,x + + lda _num1+dum0 + adc _num1+dum1 + sbc _num1+dum1 + bit _num1+dum0 + sta _num1+dum0 ;(FIXED): can't use sta _num1+dum0 + stz _num1+dum0 + + lda _num1+dum0,x + adc _num1+dum0,x + sbc _num1+dum0,x + bit _num1+dum0,x + sta _num1+dum0,x + stz _num1+dum0,x + + lda _num1+dum0,y ;these assemble to abs accesses: lda $00C0,y + adc _num1+dum0,y + sbc _num1+dum0,y + sta _num1+dum0,y + + ; Label & branching tests +GetKey ldx $C000 + bpl GetKey +]loop + dex + bne ]loop + + tya + and #1 + beq :err + + tya + and #1 + bne :good +:err + lda #0 +:good + bne myQuit + nop + hex 2C ;bit + lda #1 +myQuit + jmp DOSWARM + + ; --- Tests used when addressing issues opened against Merlin32 --- + + ;Issue #26 (lroathe) - ORG in DUM section is ignored, but can't mess up code ORG + + org $2000 + + lda _LFT + ldx #_LFT + cpx #$20 + + org ;return to ongoing address + + lda $FF + ;Issue #16 (fadden) - Byte reference modifiers are ignored (no way to force DP) + lda <$fff0 ;zp + lda >$fff0 ;ABS (lo word) + lda ^$fff0 ;ABS (hi word) + lda |$fff0 ;ABS (long in 65816 mode) + + lda $08 + lda $0008 + lda $FFFF-$FFF7 + lda $FFF0+24 + ldaz $FFF0+24 ; forced DP - mx MX + ldaz $FFFF ; forced DP + lda: $FFFF ; forced ABS (any char but 'L', 'D', and 'Z" + ldal $FFFF ; forced long abs (3 byte address) - lda $0008 ;ZP - lda $08 ;ZP - lda $ffff-$fff7 ;ZP - lda $fff0+24 ;ABS (long in 65816 mode) + ldaz $05 + lda: $05 + ldal $05 + + lda $45 + lda $2345 + lda $012345 + ldaz $2345 + lda: $45 + ldal $012345 + ldal $2345 + ldal $45 + lda <$2345 + lda >$2345 + lda <$012345 + lda >$012345 + lda ^$012345 + lda |$012345 + + ora $45 + ora $2345 + ora $012345 + oraz $2345 + ora: $45 + oral $012345 + oral $2345 + oral $45 + ora <$2345 + ora >$2345 + ora <$012345 + ora >$012345 + ora ^$012345 + ora |$012345 + + and $45 + and $2345 + and $012345 + andz $2345 + and: $45 + andl $012345 + andl $2345 + andl $45 + and <$2345 + and >$2345 + and <$012345 + and >$012345 + and ^$012345 + and |$012345 + + eor $45 + eor $2345 + eor $012345 + eorz $2345 + eor: $45 + eorl $012345 + eorl $2345 + eorl $45 + eor <$2345 + eor >$2345 + eor <$012345 + eor >$012345 + eor ^$012345 + eor |$012345 + + adc $45 + adc $2345 + adc $012345 + adcz $2345 + adc: $45 + adcl $012345 + adcl $2345 + adcl $45 + adc <$2345 + adc >$2345 + adc <$012345 + adc >$012345 + adc ^$012345 + adc |$012345 + + sta $45 + sta $2345 + sta $012345 + staz $2345 + sta: $45 + stal $012345 + stal $2345 + stal $45 + sta <$2345 + sta >$2345 + sta <$012345 + sta >$012345 + sta ^$012345 + sta |$012345 + + cmp $45 + cmp $2345 + cmp $012345 + cmpz $2345 + cmp: $45 + cmpl $012345 + cmpl $2345 + cmpl $45 + cmp <$2345 + cmp >$2345 + cmp <$012345 + cmp >$012345 + cmp ^$012345 + cmp |$012345 + + sbc $45 + sbc $2345 + sbc $012345 + sbcz $2345 + sbc: $45 + sbcl $012345 + sbcl $2345 + sbcl $45 + sbc <$2345 + sbc >$2345 + sbc <$012345 + sbc >$012345 + sbc ^$012345 + sbc |$012345 + + asll $1234 + + lda <$fff0+24 ;zp + lda >$fff0+24 ;ABS (lo word) + lda ^$fff0+24 ;ABS (hi word) + lda |$fff0+24 ;ABS (long in 65816 mode) + + mx %11 + + lda #<$fff0+24 ;byte + lda #>$fff0+24 ;page + lda #^$fff0+24 ;bank + + lda #<$1234 ;byte + lda #>$1234 ;page + lda #^$1234 ;bank + lda #^$A51234 ;bank -;Issue #8 fadden) - STX zp,y fails to assemble - org $bc + mx %00 -L00BC bit L00BC + lda #<$fff0+24 ;byte + lda #>$fff0+24 ;page + lda #^$fff0+24 ;bank - org + lda #<$1234 ;byte + lda #>$1234 ;page + lda #^$1234 ;bank + lda #^$A51234 ;bank - stx $bc,y - ldx L00BC,y - stx L00BC,y + mx MX + + lda $0008 ;ZP + lda $08 ;ZP + lda $ffff-$fff7 ;ZP + lda $fff0+24 ;ABS (long in 65816 mode) + + + ;Issue #8 fadden) - STX zp,y fails to assemble + org $bc + +L00BC bit L00BC + + org + + stx $bc,y + + ldx L00BC,y + stx L00BC,y * Data Storage Tests - hex 11,22,33,44,55,66,77,88,99 - hex 112233445566778899 - hex aabb,CC,0123456789ABCDEFabcdef,ff + hex 11,22,33,44,55,66,77,88,99 + hex 112233445566778899F + hex 112233445I566778899FF - ds 36 - da $A55A - da $A55A,$1234 - dw $A55A - dw $A55A,$1234 - ddb $A55A - ddb $A55A,$1234 - dfb $A55A - dfb $A55A,$1234 - db $A55A - db $A55A,$1234 - adr $01A55A - adr $01A55A,$011234 - adrl $01A55A - adrl $01A55A,$011234 + hex aabb,CC,0123456789ABCDEFabcdef,ff - dw >$01A55A,>$011234 - dw <$01A55A,<$011234 - dw ^$01A55A,^$011234 - dw |$01A55A,|$011234 + ds 36 + da $A55A + da $A55A,$1234 + dw $A55A + dw $A55A,$1234 + ddb $A55A + ddb $A55A,$1234 + dfb $A55A + dfb $A55A,$1234 + db $A55A + db $A55A,$1234 + adr $01A55A + adr $01A55A,$011234 + adrl $01A55A + adrl $01A55A,$011234 - db >$01A55A,>$011234 - db <$01A55A,<$011234 - db ^$01A55A,^$011234 - db |$01A55A,|$011234 + dw >$01A55A,>$011234 + dw <$01A55A,<$011234 + dw ^$01A55A,^$011234 + dw |$01A55A,|$011234 + + db >$01A55A,>$011234 + db <$01A55A,<$011234 + db ^$01A55A,^$011234 + db |$01A55A,|$011234 + lst +lup_start: + lup 0 + db 0 ; outside + --^ + + lst off //]XCODEEND ; Keep this at the end and put your code above this - ;lst off + ;lst off diff --git a/src/testfile.s b/src/testfile.s index 4fdb318..3bb6669 100644 --- a/src/testfile.s +++ b/src/testfile.s @@ -8,16 +8,16 @@ MXX = %00 mx MXX org $4000 -dp: = $A5 +dp = $A5 expr = $0405 lexpr = $010203 immed = $123456 neg equ -16 -]var1 = v1234 +//]var1 = v1234 ;lst off -start00: +:start00: brk ;$00 ora (dp,x) cop $BA @@ -219,7 +219,7 @@ startA0 startB0 bcs startB0 lda (dp),y - lda dp,s + lda (dp) lda (dp,s),y ldy dp,x lda dp,x @@ -233,6 +233,7 @@ startB0 lda expr,x ldx expr,y ldal lexpr,x + lst off startC0 cpy #immed From 3b92d28f189c010d2571712515abe507fe5a5b7f Mon Sep 17 00:00:00 2001 From: marketideas Date: Sat, 16 Nov 2019 21:06:29 -0800 Subject: [PATCH 03/26] fixed formatter --- asm.cpp | 1 + src/testfile.s | 585 ++++++++++++++++++++++++------------------------- 2 files changed, 293 insertions(+), 293 deletions(-) diff --git a/asm.cpp b/asm.cpp index e6db75c..c4c65e0 100644 --- a/asm.cpp +++ b/asm.cpp @@ -815,6 +815,7 @@ CLASS::~CLASS() } void CLASS::init(void) { + TFileProcessor::init(); std::string s; lines.clear(); diff --git a/src/testfile.s b/src/testfile.s index 3bb6669..5491052 100644 --- a/src/testfile.s +++ b/src/testfile.s @@ -1,313 +1,312 @@ - ;lst off - xc off - xc - xc + ;lst off + xc off + xc + xc -MXX = %00 +MXX = %00 - mx MXX - org $4000 + mx MXX + org $4000 -dp = $A5 -expr = $0405 -lexpr = $010203 -immed = $123456 -neg equ -16 +dp = $A5 +expr = $0405 +lexpr = $010203 +immed = $123456 +neg equ -16 -//]var1 = v1234 +//]var1 = v1234 - ;lst off -:start00: - brk ;$00 - ora (dp,x) - cop $BA - ora $BC,S - tsb dp - ora dp - asl dp - ora [dp] - php - ora #immed - asl - phd - tsb expr - ora expr - asl expr - oral lexpr - ;end + ;lst off +start00: + brk ;$00 + ora (dp,x) + cop $BA + ora $BC,S + tsb dp + ora dp + asl dp + ora [dp] + php + ora #immed + asl + phd + tsb expr + ora expr + asl expr + oral lexpr + ;end -start10 - bpl start10 - ora (dp),y - ora (dp) - ora (dp,s),y - trb dp - ora dp,x - asl dp,x - ora [dp],y - clc - ora expr,y - inc - tcs - trb expr - ora expr,x - asl expr,x - oral lexpr,x +start10 + bpl start10 + ora (dp),y + ora (dp) + ora (dp,s),y + trb dp + ora dp,x + asl dp,x + ora [dp],y + clc + ora expr,y + inc + tcs + trb expr + ora expr,x + asl expr,x + oral lexpr,x -start20 - jsr expr - and (dp,x) - jsl lexpr - and dp,s - bit dp - and dp - rol dp - and [dp] - plp - and #immed - rol - pld - bit expr - and expr - rol expr - andl lexpr +start20 + jsr expr + and (dp,x) + jsl lexpr + and dp,s + bit dp + and dp + rol dp + and [dp] + plp + and #immed + rol + pld + bit expr + and expr + rol expr + andl lexpr -start30 - bmi start30 - and (dp),y - and (dp) - and (dp,s),y - bit dp,x - and dp,x - rol dp,x - and [dp],y - sec - and expr,y - dec - tsc - bit expr,x - and expr,x - rol expr,x - andl lexpr,x +start30 + bmi start30 + and (dp),y + and (dp) + and (dp,s),y + bit dp,x + and dp,x + rol dp,x + and [dp],y + sec + and expr,y + dec + tsc + bit expr,x + and expr,x + rol expr,x + andl lexpr,x -start40 - rti - eor (dp,x) - wdm $01 - eor dp,s - mvp dp,dp+1 - eor dp - lsr dp - eor [dp] - pha - eor #immed - lsr - phk - jmp expr - eor expr - lsr expr - eorl lexpr +start40 + rti + eor (dp,x) + wdm $01 + eor dp,s + mvp dp,dp+1 + eor dp + lsr dp + eor [dp] + pha + eor #immed + lsr + phk + jmp expr + eor expr + lsr expr + eorl lexpr -start50 - bvc start50 - eor (dp),y - eor (dp) - eor (dp,s),y - mvn dp,dp+1 - eor dp,x - lsr dp,x - eor [dp],y - cli - eor expr,y - phy - tcd - jml lexpr - eor expr,x - lsr expr,x - eorl lexpr,x +start50 + bvc start50 + eor (dp),y + eor (dp) + eor (dp,s),y + mvn dp,dp+1 + eor dp,x + lsr dp,x + eor [dp],y + cli + eor expr,y + phy + tcd + jml lexpr + eor expr,x + lsr expr,x + eorl lexpr,x -start60 - rts - adc (dp,x) - per start60 - adc dp,s - stz dp - adc dp - ror dp - adc [dp] - pla - adc #immed - ror - rtl - jmp (expr) - adc expr - ror expr - adcl lexpr +start60 + rts + adc (dp,x) + per start60 + adc dp,s + stz dp + adc dp + ror dp + adc [dp] + pla + adc #immed + ror + rtl + jmp (expr) + adc expr + ror expr + adcl lexpr -start70 - bvs start70 - adc (dp),y - adc (dp) - adc (dp,s),y - stz dp,x - adc dp,x - ror dp,x - adc [dp],y - sei - adc expr,y - ply - tdc - jmp (expr,x) - adc expr,x - ror expr,x - adcl expr,x +start70 + bvs start70 + adc (dp),y + adc (dp) + adc (dp,s),y + stz dp,x + adc dp,x + ror dp,x + adc [dp],y + sei + adc expr,y + ply + tdc + jmp (expr,x) + adc expr,x + ror expr,x + adcl expr,x -start80 - bra start80 - sta (dp,x) - brl start80 - sta dp,s - sty dp - sta dp - stx dp - sta [dp] - dey - bit #immed - txa - phb - sty expr - sta expr - stx expr - stal lexpr +start80 + bra start80 + sta (dp,x) + brl start80 + sta dp,s + sty dp + sta dp + stx dp + sta [dp] + dey + bit #immed + txa + phb + sty expr + sta expr + stx expr + stal lexpr -start90 - bcc start90 - sta (dp),y - sta (dp) - sta (dp,s),y - sty dp,x - sta dp,x - stx dp,y - sta [dp],y - tya - sta expr,y - txs - txy - stz expr - sta expr,x - stz expr,x - stal lexpr,x +start90 + bcc start90 + sta (dp),y + sta (dp) + sta (dp,s),y + sty dp,x + sta dp,x + stx dp,y + sta [dp],y + tya + sta expr,y + txs + txy + stz expr + sta expr,x + stz expr,x + stal lexpr,x -startA0 - ldy #immed - lda (dp,x) - ldx #immed - lda dp,s - ldy dp - lda dp - ldx dp - lda [dp] - tay - lda #immed - tax - plb - ldy expr - lda expr - ldx expr - ldal lexpr +startA0 + ldy #immed + lda (dp,x) + ldx #immed + lda dp,s + ldy dp + lda dp + ldx dp + lda [dp] + tay + lda #immed + tax + plb + ldy expr + lda expr + ldx expr + ldal lexpr -startB0 - bcs startB0 - lda (dp),y - lda (dp) - lda (dp,s),y - ldy dp,x - lda dp,x - ldx dp,y - lda [dp],y - clv - lda expr,y - tsx - tyx - ldy expr,x - lda expr,x - ldx expr,y - ldal lexpr,x - lst off +startB0 + bcs startB0 + lda (dp),y + lda (dp) + lda (dp,s),y + ldy dp,x + lda dp,x + ldx dp,y + lda [dp],y + clv + lda expr,y + tsx + tyx + ldy expr,x + lda expr,x + ldx expr,y + ldal lexpr,x -startC0 - cpy #immed - cmp (dp,x) - rep #$FF - mx MXX - cmp dp,s - cpy dp - cmp dp - dec dp - cmp [dp] - iny - cmp #immed - dex - wai - cpy expr - cmp expr - dec expr - cmpl lexpr +startC0 + cpy #immed + cmp (dp,x) + rep #$FF + mx MXX + cmp dp,s + cpy dp + cmp dp + dec dp + cmp [dp] + iny + cmp #immed + dex + wai + cpy expr + cmp expr + dec expr + cmpl lexpr -startD0 - bne startD0 - cmp (dp),y - cmp (dp) - cmp (dp,s),y - pei dp - cmp dp,x - dec dp,x - cmp [dp],y - cld - cmp expr,y - phx - stp - jml [lexpr] - cmp expr,x - dec expr,x - cmpl lexpr,x +startD0 + bne startD0 + cmp (dp),y + cmp (dp) + cmp (dp,s),y + pei dp + cmp dp,x + dec dp,x + cmp [dp],y + cld + cmp expr,y + phx + stp + jml [lexpr] + cmp expr,x + dec expr,x + cmpl lexpr,x -startE0 - cpx #immed - sbc (dp,x) - sep #$FF - mx MXX - sbc dp,s - cpx dp - sbc dp - inc dp - sbc [dp] - inx - sbc #immed - nop - xba - cpx expr - sbc expr - inc expr - sbcl lexpr +startE0 + cpx #immed + sbc (dp,x) + sep #$FF + mx MXX + sbc dp,s + cpx dp + sbc dp + inc dp + sbc [dp] + inx + sbc #immed + nop + xba + cpx expr + sbc expr + inc expr + sbcl lexpr + +startF0 + beq startF0 + sbc (dp),y + sbc (dp) + sbc (dp,s),y + pea startF0 + sbc dp,x + inc dp,x + sbc [dp],y + sed + sbc expr,y + plx + xce + jsr (expr,x) + sbc expr,x + inc expr,x + sbcl lexpr,x + lst off + sav ./test.bin -startF0 - beq startF0 - sbc (dp),y - sbc (dp) - sbc (dp,s),y - pea startF0 - sbc dp,x - inc dp,x - sbc [dp],y - sed - sbc expr,y - plx - xce - jsr (expr,x) - sbc expr,x - inc expr,x - sbcl lexpr,x - lst off - sav ./test.bin - From dd7dcb40821eda4a8529815c4b2b29d16d5d9920 Mon Sep 17 00:00:00 2001 From: marketideas Date: Mon, 18 Nov 2019 22:29:06 -0800 Subject: [PATCH 04/26] use regEx in parser to better handle strings --- asm.cpp | 238 +++++++++++++++++++++++++------------------------------- 1 file changed, 104 insertions(+), 134 deletions(-) diff --git a/asm.cpp b/asm.cpp index b480bcb..c673b09 100644 --- a/asm.cpp +++ b/asm.cpp @@ -311,6 +311,16 @@ void CLASS::clear() outbytes.clear(); } +std::string operEx[] = +{ + "^(#?)([<>\\^|]?)([\"\'])(.*)(\\3)([\\S]*)", // catches the normal delims + "^([!$%&()*+,\\-.\\/])(.\\S*)[\\1](\\S*)", + "^(\\s*)(\\S*)", + "" +}; +std::string commentEx = "^(\\s*)((;|\\/{2}))+(.*)"; + +// ^(\s*)(;?)(([\/]{2})?)(.*) void CLASS::set(std::string line) { int state = 0; @@ -319,8 +329,9 @@ void CLASS::set(std::string line) int x; char c, delim; bool isascii; - std::string opupper; - + std::string opupper, s; + std::string restofline; + std::string tline = line; clear(); isascii = false; @@ -328,7 +339,7 @@ void CLASS::set(std::string line) //printf("line: |%s|\n", line.c_str()); while (i < l) { - c = line[i++]; + c = tline[i++]; //printf("state: %d\n",state); switch (state) { @@ -376,147 +387,92 @@ void CLASS::set(std::string line) } break; case 3: - { - if (c > ' ') { - opcode += c; - } -#if 1 - else - { - // SGQ - // this is bad, but the only way I currently know how to do this. - // the problem is, is that the ASCII generating psuedo-ops in Merlin - // use any char > space and less than apostrophe, and > apostrophe - // as delimiters. - // however, those characters also contain valid opcode expression characters - // so we see a character here, it looks like a delim, and we keep reading to EOL - // which might include a comment. All of that, then goes into the operand, and - // comments cause errors on evaluation. - // So, at this point in the code, we must determine if the opcode is one of our - // ascii psuedo-ops and treat the first char as a delim. - // otherwise, we must parse the operand as an express. - // this parser should know NOTHING about what the code does...but it needs to in - // this case. - - opupper = Poco::toUpper(opcode); - if (opupper.length() > 0) + if (c > ' ') { - if ( - (opupper == "STRL") - || (opupper == "STR") - || (opupper == "ASC") - || (opupper == "DCI") - || (opupper == "INV") - || (opupper == "FLS") - || (opupper == "REV") - ) - { - isascii = true; - } - + opcode += c; } - - state = 4; - } -#else - else - { - // SGQ - // this is bad, but the only way I currently know how to do this. - // the problem is, is that the ASCII generating psuedo-ops in Merlin - // use any char > space and less than apostrophe, and > apostrophe - // as delimiters. - // however, those characters also contain valid opcode expression characters - // so we see a character here, it looks like a delim, and we keep reading to EOL - // which might include a comment. All of that, then goes into the operand, and - // comments cause errors on evaluation. - // So, at this point in the code, we must determine if the opcode is one of our - // ascii psuedo-ops and treat the first char as a delim. - // otherwise, we must parse the operand as an express. - // this parser should know NOTHING about what the code does...but it needs to in - // this case. - - opupper = Poco::toUpper(opcode); - - auto itr = a.opcodes.find(op); - if (itr != a.opcodes.end()) + else { - TSymbol s = itr->second; - if (1) - { - isascii = true; - } + i--; + state = 4; } - - state = 4; } -#endif - } - break; + break; case 4: // read whitespace between opcode and operand - if (c == ';') { - comment += c; - state = 7; - } - else if (c > ' ') - { - operand += c; - if ((c <= '/') && (isascii)) + 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()); + + strs.clear(); + x = 0; + try { - delim = c; - state = 8; + x = comEx.split(restofline, strs, 0); } - else + catch (Poco::Exception &e) { - state = 5; + x = 0; + if (isDebug() > 3) + { + cout << e.displayText() << endl; + } } - } - break; - case 5: - if (c > ' ') - { - if ((c == '\'') || (c == '"')) + if (x > 0) { - delim = c; - operand += c; - state = 8; + // 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; } - else + + int ct = 0; + int x = 0; + bool match = false; + s = operEx[ct]; + while (s != "") { - operand += c; + 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 = operand.length(); + restofline=restofline.substr(i,restofline.length()); + match = true; + break; + } + ct++; + s = operEx[ct]; + } + i=l; + if (!match) + { + opcode="BAD"; // let assembler figure out this is a bad opcode + // SGQ maybe error here + //printf("---No Match %s\n", restofline.c_str()); } - } - else - { - state = 6; - } - break; - case 6: - if (c > ' ') - { - comment += c; - state = 7; - } - break; - case 7: - comment += c; - break; - case 9: - break; - case 8: - if (c < ' ') - { - } - else if (c == delim) - { - operand += c; - state = 5; - } - else - { - operand += c; } break; } @@ -525,12 +481,14 @@ void CLASS::set(std::string line) x = lable.length(); if (x > 1) { +#if 0 while ((x > 1) && (lable[x - 1] == ':')) { lable = lable.substr(0, x - 1); x--; } //printf("linelable: |%s|\n", lable.c_str()); +#endif } opcodelower = Poco::toLower(opcode); @@ -915,10 +873,11 @@ int CLASS::doline(int lineno, std::string line) void CLASS::process(void) { - uint32_t len, t, pos; uint32_t ct = lines.size(); + uint32_t len, t, pos; + for (uint32_t lineno = 0; lineno < ct; lineno++) { MerlinLine &line = lines.at(lineno); @@ -1022,7 +981,7 @@ void CLASS::pushopcode(std::string op, uint8_t opcode, uint16_t flags, TOpCallba opcodes.insert(p); } -TSymbol *CLASS::addSymbol(std::string symname, uint32_t val, bool replace) +TSymbol * CLASS::addSymbol(std::string symname, uint32_t val, bool replace) { TSymbol *res = NULL; TSymbol *fnd = NULL; @@ -1100,7 +1059,7 @@ out: return (res); } -TSymbol *CLASS::findSymbol(std::string symname) +TSymbol * CLASS::findSymbol(std::string symname) { TSymbol *res = NULL; @@ -1143,7 +1102,7 @@ out: return (res); } -TSymbol *CLASS::addVariable(std::string symname, std::string val, bool replace) +TSymbol * CLASS::addVariable(std::string symname, std::string val, bool replace) { TSymbol *res = NULL; TSymbol *fnd = NULL; @@ -1187,7 +1146,7 @@ TSymbol *CLASS::addVariable(std::string symname, std::string val, bool replace) return (res); } -TSymbol *CLASS::findVariable(std::string symname) +TSymbol * CLASS::findVariable(std::string symname) { TSymbol *res = NULL; @@ -1844,6 +1803,17 @@ bool CLASS::codeSkipped(void) 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()); + } +#else + uint32_t l; int x;; char c; @@ -2015,7 +1985,7 @@ void CLASS::process(void) #endif pass++; } - +#endif } int CLASS::doline(int lineno, std::string line) From b391c9b729766a36c4fba69e3cc1af42627c9a3b Mon Sep 17 00:00:00 2001 From: marketideas Date: Tue, 19 Nov 2019 08:38:49 -0800 Subject: [PATCH 05/26] parser regex complete --- asm.cpp | 156 ++++++++++++++++++-------------- config.h | 1 + runtests.sh | 2 + testdata/2019-local-variables.S | 2 +- todo.txt | 8 +- 5 files changed, 95 insertions(+), 74 deletions(-) diff --git a/asm.cpp b/asm.cpp index c673b09..2930ba8 100644 --- a/asm.cpp +++ b/asm.cpp @@ -313,14 +313,14 @@ void CLASS::clear() std::string operEx[] = { - "^(#?)([<>\\^|]?)([\"\'])(.*)(\\3)([\\S]*)", // catches the normal delims - "^([!$%&()*+,\\-.\\/])(.\\S*)[\\1](\\S*)", - "^(\\s*)(\\S*)", + "^(\\S*)(#?)([<>\\^|]?)([\"\'])(.*)(\\4)([\\S]*)", // catches the normal delims + "^(\\s*)([!-~])([!-~]*?)([^;]*)\\2(\\S*)", // catches the unusual delims + "^(\\s*)(\\S+)", // captures everything else "" }; + std::string commentEx = "^(\\s*)((;|\\/{2}))+(.*)"; -// ^(\s*)(;?)(([\/]{2})?)(.*) void CLASS::set(std::string line) { int state = 0; @@ -336,13 +336,21 @@ void CLASS::set(std::string line) isascii = false; delim = 0; - //printf("line: |%s|\n", line.c_str()); while (i < l) { c = tline[i++]; - //printf("state: %d\n",state); switch (state) { + case 7: + if (c >= ' ') + { + comment += c; + } + else + { + i = l; + } + break; case 0: // start of line state if ((c == ';') || (c == '*') || (c == '/')) { @@ -387,32 +395,63 @@ void CLASS::set(std::string line) } break; case 3: + { + if (c > ' ') { - 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()); + + strs.clear(); + x = 0; + try + { + x = comEx.split(restofline, strs, 0); + } + catch (Poco::Exception &e) + { + x = 0; + if (isDebug() > 3) { - opcode += c; - } - else - { - i--; - state = 4; + cout << e.displayText() << endl; } } - break; - case 4: // read whitespace between opcode and operand + if (x > 0) { - 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()); + // 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 = comEx.split(restofline, strs, 0); + x = regex.split(restofline, strs, 0); } catch (Poco::Exception &e) { @@ -424,63 +463,34 @@ void CLASS::set(std::string line) } 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; + //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 = operand.length(); + restofline = restofline.substr(i, restofline.length()); + comment = Poco::trim(restofline); + match = true; break; } - - int ct = 0; - int x = 0; - bool match = false; + ct++; 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 = operand.length(); - restofline=restofline.substr(i,restofline.length()); - match = true; - break; - } - ct++; - s = operEx[ct]; - } - i=l; - if (!match) - { - opcode="BAD"; // let assembler figure out this is a bad opcode - // SGQ maybe error here - //printf("---No Match %s\n", restofline.c_str()); - } } - break; + i = l; + if (!match) + { + opcode = ":::"; // let assembler figure out this is a bad opcode + // SGQ maybe error here + //printf("---No Match %s\n", restofline.c_str()); + } + } + break; } } printlable = lable; x = lable.length(); if (x > 1) { + // SGQ M32 syntax #if 0 while ((x > 1) && (lable[x - 1] == ':')) { @@ -676,6 +686,7 @@ int CLASS::processfile(std::string p, std::string &newfilename) linect = 0; done = false; + p = Poco::trim(p); currentdir = Poco::Path::current(); if (filecount == 0) @@ -746,10 +757,14 @@ int CLASS::processfile(std::string p, std::string &newfilename) } if ((fn.isDirectory()) || (!fn.canRead())) { - //LOG_DEBUG << "File is a directory: " << p1 << endl; + LOG_DEBUG << "File is a directory: " << p1 << endl; valid = false; } } + else + { + printf("file does not exist |%s|\n", p1.c_str()); + } newfilename = p1; if (!valid) @@ -2014,6 +2029,7 @@ int CLASS::doline(int lineno, std::string line) { std::string fn; x = processfile(l.operand, fn); + //printf("processfile : %d\n",x); if (x < 0) { switch (x) diff --git a/config.h b/config.h index f1f9a01..7d8623b 100644 --- a/config.h +++ b/config.h @@ -14,6 +14,7 @@ //#define USE_JSON //#define USE_XML +#define NO_TTY_SETUP // help text #define HELP_USAGE " " #define HELP_PURPOSE "\nMerlin 16+ Compatible 65816 Development Tool" diff --git a/runtests.sh b/runtests.sh index 0c22973..8cbb574 100755 --- a/runtests.sh +++ b/runtests.sh @@ -27,6 +27,8 @@ for S in $SRC ; do BASE=${S/.S/} BASE=${BASE/.s/} + #./qasm -o 0/$OUTDIR/$S1 ./testdata/$S + ./qasm -o 0/$OUTDIR/$S1 ./testdata/$S >> $TMPFILE R=?$ diff --git a/testdata/2019-local-variables.S b/testdata/2019-local-variables.S index db1922b..1687a46 100644 --- a/testdata/2019-local-variables.S +++ b/testdata/2019-local-variables.S @@ -155,5 +155,5 @@ LOCAL1 lda #$2c ;EDIT: format as ASCII beq LOCAL1 LOCAL2 lda $2c ;EDIT: format as ASCII ldx $5678 ;put empty variable table here - beq LOCAL2 + ;beq LOCAL2 rts diff --git a/todo.txt b/todo.txt index a5106a3..51a6fe3 100644 --- a/todo.txt +++ b/todo.txt @@ -1,9 +1,11 @@ (0) 2019-11-17 - BRK does not detect a lable that can't be evaluated (0) 2019-11-17 - ASCII parsing in both eval and for ASC type commands (0) 2019-11-17 - IF processing for character compare mode - (0) 2019-11-17 - - (0) 2019-11-17 - - (0) 2019-11-17 - + (0) 2019-11-17 - Note (syntax) Merlin doesn't allow 'A' implied addressing + (0) 2019-11-17 - Note (syntax): Merlin doesn't allow local labels without a previous global + (0) 2019-11-17 - Note (syntax): Merlin doesn't allow local colons after label which is ignored + (0) 2019-11-17 - Note (syntax): Merlin doesn't allow for 'rep/sep/xce' tracking + (0) 2019-11-17 - Bug (evaluation routine puts ascii bytes in reverse order (#"AB") (0) 2019-11-17 - (0) 2019-11-17 - (0) 2019-11-17 - From 572bdd587928ee12cd217a3c0a41f97f3d129be9 Mon Sep 17 00:00:00 2001 From: marketideas Date: Tue, 19 Nov 2019 09:22:27 -0800 Subject: [PATCH 06/26] just a few more parser fixes --- asm.cpp | 15 +++++++++------ asm.h | 2 +- qasm.ini | 6 +++--- src/main.s | 6 +++--- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/asm.cpp b/asm.cpp index 2930ba8..307cf1c 100644 --- a/asm.cpp +++ b/asm.cpp @@ -174,7 +174,7 @@ void CLASS::print(uint32_t lineno) { pcol += printf("%c", comment[cc]); comct++; - if ((comment[cc] <= ' ') && (pcol >= (commentcol + savpcol + 10))) + if ((comment[cc] <= ' ') && (pcol >= (commentcol + savpcol + 20))) { printf("\n"); pcol = 0; @@ -416,6 +416,11 @@ void CLASS::set(std::string line) 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 @@ -478,9 +483,7 @@ void CLASS::set(std::string line) i = l; if (!match) { - opcode = ":::"; // let assembler figure out this is a bad opcode - // SGQ maybe error here - //printf("---No Match %s\n", restofline.c_str()); + // if you are here, there probably isn't an operand and/or comment after opcode } } break; @@ -491,7 +494,7 @@ void CLASS::set(std::string line) if (x > 1) { // SGQ M32 syntax -#if 0 +#if 1 while ((x > 1) && (lable[x - 1] == ':')) { lable = lable.substr(0, x - 1); @@ -1419,7 +1422,7 @@ void CLASS::initpass(void) merlinerrors = getBool("asm.merlinerrors", true); trackrep = getBool("asm.trackrep", false); - merlincompat = getBool("asm.merlincompatible", true); + //merlincompat = getBool("asm.merlincompatible", true); allowdup = getBool("asm.allowduplicate", true); skiplist = false; diff --git a/asm.h b/asm.h index cae8a1e..d4ffb6c 100644 --- a/asm.h +++ b/asm.h @@ -335,7 +335,7 @@ public: bool casesen; bool showmx; bool trackrep; - bool merlincompat; + //bool merlincompat; bool merlinerrors; bool allowdup; uint8_t mx; diff --git a/qasm.ini b/qasm.ini index 2aad0ca..9ba320a 100644 --- a/qasm.ini +++ b/qasm.ini @@ -6,6 +6,7 @@ logfile=mylog.log [option] debug=1 nocolor=false +syntax=merlin ;debug must be an integer. Code can use this as a level [application] @@ -26,10 +27,9 @@ startmx=3 lst=true ; can be M6502, M65C02, M65816 cpu=M65816 -trackrep=true +trackrep=false allowduplicate=true -merlinerrors=false -merlincompatible=true +merlinerrors=true symcolumns=3 [reformat] diff --git a/src/main.s b/src/main.s index b64d017..8a60dae 100644 --- a/src/main.s +++ b/src/main.s @@ -307,7 +307,7 @@ myQuit sbc ^$012345 sbc |$012345 - asll $1234 + ;asll $1234 lda <$fff0+24 ;zp lda >$fff0+24 ;ABS (lo word) @@ -411,8 +411,8 @@ L00BC bit L00BC asc 02,15,?123456? asc 02,15,>123456> asc 02,15,<123456< - asc 02,15,5,"123456" - asc 02,15,"123456 + asc 02,15,05,"123456" + asc 02,15,"123456" asc 0215"1234"1502 From 4fa1c515495633e7b7a5ee2ba4a7be3232db2b5d Mon Sep 17 00:00:00 2001 From: marketideas Date: Tue, 19 Nov 2019 09:59:03 -0800 Subject: [PATCH 07/26] added --syntax option --- asm.cpp | 78 ++++++++++++++++++++++++++++++++++++++--------------- asm.h | 18 +++++++++---- qasm.cpp | 8 +++--- qasm.ini | 4 +-- runtests.sh | 2 +- 5 files changed, 78 insertions(+), 32 deletions(-) diff --git a/asm.cpp b/asm.cpp index 307cf1c..71b7c50 100644 --- a/asm.cpp +++ b/asm.cpp @@ -416,9 +416,9 @@ void CLASS::set(std::string line) restofline = Poco::trim(tline.substr(i, tline.length())) + " "; //printf("ROL: |%s|\n",restofline.c_str()); - if (restofline=="") + if (restofline == "") { - i=l; + i = l; break; } strs.clear(); @@ -493,15 +493,16 @@ void CLASS::set(std::string line) x = lable.length(); if (x > 1) { - // SGQ M32 syntax -#if 1 - while ((x > 1) && (lable[x - 1] == ':')) + // M32 syntax allows a colon after lable, and it is not part of the lable + if ((syntax & SYNTAX_MERLIN32)==SYNTAX_MERLIN32) { - lable = lable.substr(0, x - 1); - x--; + while ((x > 1) && (lable[x - 1] == ':')) + { + lable = lable.substr(0, x - 1); + x--; + } + //printf("linelable: |%s|\n", lable.c_str()); } - //printf("linelable: |%s|\n", lable.c_str()); -#endif } opcodelower = Poco::toLower(opcode); @@ -532,9 +533,24 @@ void CLASS::init(void) filenames.clear(); starttime = GetTickCount(); initialdir = Poco::Path::current(); - syntax = 0; + syntax = SYNTAX_MERLIN; filecount = 0; + s = getConfig("option.syntax", "merlin16"); + s = Poco::toUpper(Poco::trim(s)); + if ((s == "MERLIN") || (s == "MERLIN16")) + { + syntax = SYNTAX_MERLIN; + } + else if (s == "MERLIN32") + { + syntax = SYNTAX_MERLIN32; + } + else if (s == "QASM") + { + syntax = SYNTAX_QASM; + } + std::string tabstr = getConfig("reformat.tabs", "8,16,32"); tabstr = Poco::trim(tabstr); @@ -1422,6 +1438,21 @@ void CLASS::initpass(void) 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); + + } //merlincompat = getBool("asm.merlincompatible", true); allowdup = getBool("asm.allowduplicate", true); @@ -1464,7 +1495,12 @@ void CLASS::initpass(void) lastcarry = false; relocatable = false; - currentsym = &topSymbol; // this is the default symbol for :locals without a global above; + 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; @@ -1668,18 +1704,17 @@ int CLASS::getAddrMode(MerlinLine & line) // symbol is defined later, we will generate different // bytes on the next pass - if (Poco::toUpper(oper) == "A") // check the whole operand, not just the expression + if ((line.syntax&SYNTAX_MERLIN32) == SYNTAX_MERLIN32) { - // SGQ - // Merlin32 supports the 'A" operand for immediate - // mode for opcodes like "ROR A". Problem is, Merlin16 - // does not, and 'A' could be a lable. - TSymbol *sym = findSymbol("A"); - if (sym == NULL) + if (Poco::toUpper(oper) == "A") // check the whole operand, not just the expression { - line.flags |= FLAG_FORCEIMPLIED; - mode = syn_implied; // if the label hasn't been defined yet, assume Immediate addressing - goto out; + 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; + } } } } @@ -1861,6 +1896,7 @@ void CLASS::process(void) line.linemx = mx; line.bytect = 0; line.showmx = showmx; + line.syntax = syntax; line.merlinerrors = merlinerrors; if ((line.lable != "")) diff --git a/asm.h b/asm.h index d4ffb6c..b6ed183 100644 --- a/asm.h +++ b/asm.h @@ -8,8 +8,17 @@ #define MODE_65816 2 #define SYNTAX_MERLIN 0 -#define SYNTAX_APW 1 -#define SYNTAX_ORCA 2 +#define SYNTAX_MERLIN32 0x01 +#define SYNTAX_APW 0x02 +#define SYNTAX_ORCA 0x04 +#define SYNTAX_QASM (0x08 | SYNTAX_MERLIN32) +#define OPTION_ALLOW_A_OPERAND 0x0100 +#define OPTION_ALLOW_LOCAL 0x0200 +#define OPTION_ALLOW_COLON 0x0400 +#define OPTION_FORCE_REPSEP 0x0800 +#define OPTION_NO_REPSEP 0x1000 +#define OPTION_CFG_REPSEP 0x2000 + #define FLAG_FORCELONG 0x01 #define FLAG_FORCEABS 0x02 @@ -177,7 +186,7 @@ class MerlinLine { public: - uint8_t syntax; + uint32_t syntax; std::string lable; std::string printlable; std::string opcode; @@ -224,7 +233,7 @@ class TFileProcessor protected: std::string initialdir; std::vector filenames; - uint8_t syntax; + uint32_t syntax; uint64_t starttime; uint8_t tabs[16]; @@ -335,7 +344,6 @@ public: bool casesen; bool showmx; bool trackrep; - //bool merlincompat; bool merlinerrors; bool allowdup; uint8_t mx; diff --git a/qasm.cpp b/qasm.cpp index 8c06b3f..c065ecd 100644 --- a/qasm.cpp +++ b/qasm.cpp @@ -18,9 +18,11 @@ programOption PAL::appOptions[] = #ifdef DEBUG { "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] default=asm", " ", false, false}, - { "objfile", "o", "write output to file", " ", false, false}, + //{ "config", "f", "load configuration data from a ", "", false, false}, + { "exec", "x", "execute a command [asm, link, reformat] default=asm", "", false, false}, + { "objfile", "o", "write output to file", "", false, false}, + { "syntax", "s", "enforce syntax of other assembler [merlin16, merlin32]", "", false, false}, + { "", "", "", "", false, false} }; diff --git a/qasm.ini b/qasm.ini index 9ba320a..9769696 100644 --- a/qasm.ini +++ b/qasm.ini @@ -6,7 +6,7 @@ logfile=mylog.log [option] debug=1 nocolor=false -syntax=merlin +;syntax=merlin32 ;debug must be an integer. Code can use this as a level [application] @@ -27,7 +27,7 @@ startmx=3 lst=true ; can be M6502, M65C02, M65816 cpu=M65816 -trackrep=false +trackrep=true allowduplicate=true merlinerrors=true symcolumns=3 diff --git a/runtests.sh b/runtests.sh index 8cbb574..6e4ae83 100755 --- a/runtests.sh +++ b/runtests.sh @@ -29,7 +29,7 @@ for S in $SRC ; do BASE=${BASE/.s/} #./qasm -o 0/$OUTDIR/$S1 ./testdata/$S - ./qasm -o 0/$OUTDIR/$S1 ./testdata/$S >> $TMPFILE + ./qasm --syntax merlin32 -o 0/$OUTDIR/$S1 ./testdata/$S >> $TMPFILE R=?$ #echo $S " " $S1 From 2e6f8af54ea87c44bbac15c1065c43b9f8845756 Mon Sep 17 00:00:00 2001 From: marketideas Date: Tue, 19 Nov 2019 11:27:17 -0800 Subject: [PATCH 08/26] all tests assemble, ]vars seem to be working --- asm.cpp | 173 ++++++++++++++++++++++---------- asm.h | 13 ++- src/main.s | 2 +- testdata/2019-local-variables.S | 2 +- todo.txt | 5 +- 5 files changed, 134 insertions(+), 61 deletions(-) diff --git a/asm.cpp b/asm.cpp index 71b7c50..71e0bf9 100644 --- a/asm.cpp +++ b/asm.cpp @@ -2,6 +2,9 @@ #include "asm.h" #include "eval.h" #include "psuedo.h" +#include +#include + #define CLASS MerlinLine @@ -99,7 +102,7 @@ void CLASS::print(uint32_t lineno) } } bool empty = false; - if ((printlable == "") && (opcode == "") && (operand == "")) + if ((printlable == "") && (opcode == "") && (printoperand == "")) { empty = true; } @@ -202,7 +205,7 @@ void CLASS::print(uint32_t lineno) { pcol += printf(" "); } - pcol += printf("%s ", operand.c_str()); + pcol += printf("%s ", printoperand.c_str()); //pcol += printf("%-12s %-8s %-10s ", printlable.c_str(), opcode.c_str(), operand.c_str()); } if ((errorcode > 0) && (!merlinerrors)) @@ -287,6 +290,7 @@ void CLASS::clear() opcode = ""; opcodelower = ""; operand = ""; + printoperand=""; comment = ""; operand_expr = ""; operand_expr2 = ""; @@ -494,7 +498,7 @@ void CLASS::set(std::string line) if (x > 1) { // M32 syntax allows a colon after lable, and it is not part of the lable - if ((syntax & SYNTAX_MERLIN32)==SYNTAX_MERLIN32) + if ((syntax & SYNTAX_MERLIN32) == SYNTAX_MERLIN32) { while ((x > 1) && (lable[x - 1] == ':')) { @@ -513,7 +517,20 @@ void CLASS::set(std::string line) CLASS::CLASS() { + int x; errorct = 0; + + 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); + } CLASS::~CLASS() @@ -1158,7 +1175,7 @@ TSymbol * CLASS::addVariable(std::string symname, std::string val, bool replace) if (fnd != NULL) { //printf("replacing symbol: %s %08X\n",sym.c_str(),val); - fnd->text = val; + fnd->var_text = val; return (fnd); } @@ -1168,7 +1185,7 @@ TSymbol * CLASS::addVariable(std::string symname, std::string val, bool replace) s.namelc = Poco::toLower(sym); s.stype = 0; s.value = 0; - s.text = val; + s.var_text = val; s.used = false; s.cb = NULL; @@ -1185,7 +1202,7 @@ TSymbol * CLASS::findVariable(std::string symname) TSymbol *res = NULL; //printf("finding: %s\n",symname.c_str()); - auto itr = variables.find(Poco::toUpper(symname)); + auto itr = variables.find(symname); if (itr != variables.end()) { //printf("Found: %s 0x%08X\n",itr->second.name.c_str(),itr->second.value); @@ -1204,7 +1221,7 @@ void CLASS::showVariables(void) for (auto itr = variables.begin(); itr != variables.end(); ++itr) { - printf("%-16s %s\n", itr->first.c_str(), itr->second.text.c_str()); + printf("%-16s %s\n", itr->first.c_str(), itr->second.var_text.c_str()); } printf("\n"); } @@ -1310,12 +1327,23 @@ int CLASS::callOpCode(std::string op, MerlinLine &line) case '>': line.expr_value >>= 8; line.expr_value &= 0xFFFF; + if ((line.syntax&SYNTAX_MERLIN32)==SYNTAX_MERLIN32) + { + line.flags |= FLAG_FORCEABS; + } break; case '^': line.expr_value = (line.expr_value >> 16) & 0xFFFF; + if ((line.syntax&SYNTAX_MERLIN32)==SYNTAX_MERLIN32) + { + line.flags |= FLAG_FORCEABS; + } break; case '|': - line.flags |= FLAG_FORCELONG; + if ((line.syntax&SYNTAX_MERLIN32)!=SYNTAX_MERLIN32) + { + line.flags |= FLAG_FORCELONG; + } break; } if (line.expr_value >= 0x100) @@ -1496,7 +1524,7 @@ void CLASS::initpass(void) lastcarry = false; relocatable = false; currentsym = NULL; - if ((syntax & SYNTAX_MERLIN32)==SYNTAX_MERLIN32) + 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; @@ -1704,7 +1732,7 @@ int CLASS::getAddrMode(MerlinLine & line) // symbol is defined later, we will generate different // bytes on the next pass - if ((line.syntax&SYNTAX_MERLIN32) == SYNTAX_MERLIN32) + if ((line.syntax & SYNTAX_MERLIN32) == SYNTAX_MERLIN32) { if (Poco::toUpper(oper) == "A") // check the whole operand, not just the expression { @@ -1780,63 +1808,93 @@ int CLASS::parseOperand(MerlinLine & line) return (res); } -int CLASS::substituteVariables(MerlinLine & line) +int CLASS::substituteVariables(MerlinLine & line, std::string &outop) { - int res = -1; + 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; - slen = oper.length(); - if (slen > 0) + bool done = false; + operin=oper; + ct=0; +restart: + while (!done) { - std::vector groups; - offset = 0; - RegularExpression varEx(varExpression, Poco::RegularExpression::RE_EXTRA, true); - Poco::RegularExpression::MatchVec mVec; - - //printf("|%s|%s|\n", varExpression.c_str(), oper.c_str()); - groups.clear(); - ct = 0; - while (offset < slen) + slen = oper.length(); + if (slen > 0) { - try - { - varEx.match(oper, offset, mVec, 0); - } - catch (...) - { - offset = slen; - } + std::vector groups; - x = mVec.size(); - if (x > 0) + 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) { - res = 0; - off = mVec[0].offset; - len = mVec[0].length; - s = oper.substr(off, len); - sym = findVariable(s); - if (sym != NULL) + try { - ct++; - if (pass > 0) - { - //printf("%d |%s|\n", ct, s.c_str()); - } + varEx.match(oper, offset, mVec, 0); + } + catch (...) + { + offset = slen; } - offset += len; - } - else - { - offset = slen; - } - } + x = mVec.size(); + if (x > 0) + { + res = 0; + off = mVec[0].offset; + len = mVec[0].length; + s = oper.substr(off, len); + sym = findVariable(s); + if (sym != NULL) + { + //printf("match |%s|\n",sym->var_text.c_str()); + + if (sym->var_text != "") + { + oper = oper.replace(off, len, sym->var_text); + 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); } @@ -1911,7 +1969,7 @@ void CLASS::process(void) sprintf(buff, "$%X", PC.currentpc); ls = buff; sym = addVariable(line.lable, ls, true); - if (sym == NULL) { dupsym = true; } + //if (sym == NULL) { dupsym = true; } break; case ':': @@ -1937,7 +1995,16 @@ void CLASS::process(void) line.setError(errDupSymbol); } } - x = substituteVariables(line); + std::string outop; + if (pass==0) + { + line.printoperand=line.operand; + } + x = substituteVariables(line,outop); + if (x>0) + { + line.operand=outop; + } x = parseOperand(line); if (x >= 0) { diff --git a/asm.h b/asm.h index b6ed183..842ffa4 100644 --- a/asm.h +++ b/asm.h @@ -18,6 +18,7 @@ #define OPTION_FORCE_REPSEP 0x0800 #define OPTION_NO_REPSEP 0x1000 #define OPTION_CFG_REPSEP 0x2000 +#define OPTION_M32_VARS 0x4000 #define FLAG_FORCELONG 0x01 @@ -189,6 +190,7 @@ public: uint32_t syntax; std::string lable; std::string printlable; + std::string printoperand; std::string opcode; std::string opcodelower; std::string operand; @@ -231,6 +233,8 @@ public: class TFileProcessor { protected: + int win_columns; + int win_rows; std::string initialdir; std::vector filenames; uint32_t syntax; @@ -310,7 +314,8 @@ class TSymbol public: std::string namelc; std::string name; - std::string text; + //std::string text; + std::string var_text; uint32_t value; uint16_t stype; uint8_t opcode; @@ -326,7 +331,8 @@ public: { value = 0; used = false; - text = ""; + //text = ""; + var_text=""; name = ""; namelc = ""; stype = 0; @@ -406,7 +412,8 @@ public: void showVariables(void); int evaluate(MerlinLine &line, std::string expr, int64_t &value); - int substituteVariables(MerlinLine & line); + int substituteVariables(MerlinLine & line, std::string &outop); + bool codeSkipped(void); int parseOperand(MerlinLine &line); diff --git a/src/main.s b/src/main.s index 8a60dae..b27f9ab 100644 --- a/src/main.s +++ b/src/main.s @@ -423,7 +423,7 @@ lup_start: --^ - lst off + ;lst off //]XCODEEND ; Keep this at the end and put your code above this ;lst off diff --git a/testdata/2019-local-variables.S b/testdata/2019-local-variables.S index 1687a46..db1922b 100644 --- a/testdata/2019-local-variables.S +++ b/testdata/2019-local-variables.S @@ -155,5 +155,5 @@ LOCAL1 lda #$2c ;EDIT: format as ASCII beq LOCAL1 LOCAL2 lda $2c ;EDIT: format as ASCII ldx $5678 ;put empty variable table here - ;beq LOCAL2 + beq LOCAL2 rts diff --git a/todo.txt b/todo.txt index 51a6fe3..7752725 100644 --- a/todo.txt +++ b/todo.txt @@ -1,13 +1,12 @@ (0) 2019-11-17 - BRK does not detect a lable that can't be evaluated (0) 2019-11-17 - ASCII parsing in both eval and for ASC type commands (0) 2019-11-17 - IF processing for character compare mode - (0) 2019-11-17 - Note (syntax) Merlin doesn't allow 'A' implied addressing (0) 2019-11-17 - Note (syntax): Merlin doesn't allow local labels without a previous global (0) 2019-11-17 - Note (syntax): Merlin doesn't allow local colons after label which is ignored (0) 2019-11-17 - Note (syntax): Merlin doesn't allow for 'rep/sep/xce' tracking (0) 2019-11-17 - Bug (evaluation routine puts ascii bytes in reverse order (#"AB") - (0) 2019-11-17 - - (0) 2019-11-17 - + (0) 2019-11-17 - want to wrap comments based on current terminal width, and don't if printing to non-terminal + (0) 2019-11-17 - syntax options - check OPTION bits, not syntax type (OPTION_ALLOW_LOCAL) (0) 2019-11-17 - (0) 2019-11-17 - (0) 2019-11-17 - From 7534c45defa84ad29076d10af997e6c34ec42aa5 Mon Sep 17 00:00:00 2001 From: marketideas Date: Tue, 19 Nov 2019 12:06:08 -0800 Subject: [PATCH 09/26] ]var EQU does an eval first and updates the variable to the resulting hex value --- asm.cpp | 43 +++++++++++++++++++++++++------------------ asm.h | 2 ++ opcodes.cpp | 15 +++++++++++++-- psuedo.cpp | 11 +++++++++++ psuedo.h | 1 + 5 files changed, 52 insertions(+), 20 deletions(-) diff --git a/asm.cpp b/asm.cpp index 71e0bf9..9a010b5 100644 --- a/asm.cpp +++ b/asm.cpp @@ -205,7 +205,14 @@ void CLASS::print(uint32_t lineno) { pcol += printf(" "); } - pcol += printf("%s ", printoperand.c_str()); + if (isDebug() > 2) + { + pcol += printf("%s ", operand.c_str()); + } + else + { + pcol += printf("%s ", printoperand.c_str()); + } //pcol += printf("%-12s %-8s %-10s ", printlable.c_str(), opcode.c_str(), operand.c_str()); } if ((errorcode > 0) && (!merlinerrors)) @@ -290,7 +297,7 @@ void CLASS::clear() opcode = ""; opcodelower = ""; operand = ""; - printoperand=""; + printoperand = ""; comment = ""; operand_expr = ""; operand_expr2 = ""; @@ -1327,20 +1334,20 @@ int CLASS::callOpCode(std::string op, MerlinLine &line) case '>': line.expr_value >>= 8; line.expr_value &= 0xFFFF; - if ((line.syntax&SYNTAX_MERLIN32)==SYNTAX_MERLIN32) + if ((line.syntax & SYNTAX_MERLIN32) == SYNTAX_MERLIN32) { line.flags |= FLAG_FORCEABS; } break; case '^': line.expr_value = (line.expr_value >> 16) & 0xFFFF; - if ((line.syntax&SYNTAX_MERLIN32)==SYNTAX_MERLIN32) + if ((line.syntax & SYNTAX_MERLIN32) == SYNTAX_MERLIN32) { line.flags |= FLAG_FORCEABS; } break; case '|': - if ((line.syntax&SYNTAX_MERLIN32)!=SYNTAX_MERLIN32) + if ((line.syntax & SYNTAX_MERLIN32) != SYNTAX_MERLIN32) { line.flags |= FLAG_FORCELONG; } @@ -1820,8 +1827,8 @@ int CLASS::substituteVariables(MerlinLine & line, std::string &outop) uint32_t len, off, ct; bool done = false; - operin=oper; - ct=0; + operin = oper; + ct = 0; restart: while (!done) { @@ -1873,28 +1880,28 @@ restart: } else { - done=true; + done = true; } offset += len; } else { offset = slen; - done=true; + done = true; } } } else { - done=true; + done = true; } } //printf("inoper=|%s| outoper=|%s|\n",operin.c_str(),oper.c_str()); - if (ct>0) + if (ct > 0) { - outop=oper; - res=ct; + outop = oper; + res = ct; } return (res); } @@ -1996,14 +2003,14 @@ void CLASS::process(void) } } std::string outop; - if (pass==0) + if (pass == 0) { - line.printoperand=line.operand; + line.printoperand = line.operand; } - x = substituteVariables(line,outop); - if (x>0) + x = substituteVariables(line, outop); + if (x > 0) { - line.operand=outop; + line.operand = outop; } x = parseOperand(line); if (x >= 0) diff --git a/asm.h b/asm.h index 842ffa4..aa0e88e 100644 --- a/asm.h +++ b/asm.h @@ -78,6 +78,7 @@ enum asmErrors errBadLUPOperand, errBadLabel, errBadOperand, + errErrOpcode, errMAX }; @@ -112,6 +113,7 @@ const std::string errStrings[errMAX + 1] = "LUP value must be 0 < VAL <= $8000", "Unknown label", "Bad operand", + "Break", "" }; diff --git a/opcodes.cpp b/opcodes.cpp index 58afdbd..d603a99 100644 --- a/opcodes.cpp +++ b/opcodes.cpp @@ -94,7 +94,18 @@ int CLASS::doEQU(MerlinLine &line, TSymbol &sym) else if (isvar) { res = -1; - s = addVariable(line.lable, line.operand, true); + + if (syntax==SYNTAX_MERLIN) + { + char buff[32]; + sprintf(buff,"$%08X",line.expr_value); + std::string s1=buff; + s = addVariable(line.lable, s1, true); + } + else + { + s = addVariable(line.lable, line.operand, true); + } if (s != NULL) { res = 0; @@ -849,7 +860,7 @@ void CLASS::insertOpcodes(void) pushopcode("IF", P_DO, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("FIN", P_DO, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("CHK", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); - pushopcode("ERR", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); + pushopcode("ERR", P_ERR, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("KBD", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("LUP", P_LUP, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("--^", P_LUP, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); diff --git a/psuedo.cpp b/psuedo.cpp index fdfa6a8..d42e7a8 100644 --- a/psuedo.cpp +++ b/psuedo.cpp @@ -844,6 +844,17 @@ int CLASS::ProcessOpcode(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) case P_SAV: a.savepath = a.processFilename(line.operand, Poco::Path::current(), 0); break; + case P_ERR: + if (a.pass>0) + { + if ((line.expr_value!=0) || (line.eval_result<0)) + { + line.setError(errErrOpcode); + //a.passcomplete=true; // terminate assembly + } + } + res=0; + break; case P_LST: res = doLST(a, line, opinfo); break; diff --git a/psuedo.h b/psuedo.h index 7251ca9..94edb92 100644 --- a/psuedo.h +++ b/psuedo.h @@ -19,6 +19,7 @@ enum P_DO, P_TR, P_ASC, + P_ERR, P_MAX }; From 2ebeb0914cfd18749d2b93d5770d3b4bd78d4a12 Mon Sep 17 00:00:00 2001 From: marketideas Date: Tue, 19 Nov 2019 13:41:27 -0800 Subject: [PATCH 10/26] work on <>|^ operators to match M32 --- asm.cpp | 70 ++++++++++++++++++++++++++++++++--------------------- opcodes.cpp | 37 ++++++++++++++++++---------- psuedo.cpp | 12 +++++++++ qasm.ini | 7 +++--- 4 files changed, 82 insertions(+), 44 deletions(-) diff --git a/asm.cpp b/asm.cpp index 9a010b5..5bb348d 100644 --- a/asm.cpp +++ b/asm.cpp @@ -205,7 +205,7 @@ void CLASS::print(uint32_t lineno) { pcol += printf(" "); } - if (isDebug() > 2) + if (isDebug() > 1) { pcol += printf("%s ", operand.c_str()); } @@ -1325,40 +1325,56 @@ int CLASS::callOpCode(std::string op, MerlinLine &line) } } - switch (line.expr_shift) + if (line.addressmode == syn_imm) { - case '<': - line.expr_value &= 0xFF; - line.flags |= FLAG_DP; - break; - case '>': - line.expr_value >>= 8; - line.expr_value &= 0xFFFF; - if ((line.syntax & SYNTAX_MERLIN32) == SYNTAX_MERLIN32) - { + //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) & 0xFFFF; + break; + case '|': + break; + } + } + else + { + switch (line.expr_shift) + { + case '<': + line.flags |= FLAG_DP; + break; + case '>': + if ((syntax & SYNTAX_MERLIN32) == SYNTAX_MERLIN32) + { + // bug in M32 or not, do what it does + line.flags |= FLAG_FORCEABS; + } + else + { + line.flags |= FLAG_FORCELONG; + } + break; + case '|': line.flags |= FLAG_FORCEABS; - } - break; - case '^': - line.expr_value = (line.expr_value >> 16) & 0xFFFF; - if ((line.syntax & SYNTAX_MERLIN32) == SYNTAX_MERLIN32) - { - line.flags |= FLAG_FORCEABS; - } - break; - case '|': - if ((line.syntax & SYNTAX_MERLIN32) != SYNTAX_MERLIN32) - { - line.flags |= FLAG_FORCELONG; - } - break; + 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()) { diff --git a/opcodes.cpp b/opcodes.cpp index d603a99..39e51c4 100644 --- a/opcodes.cpp +++ b/opcodes.cpp @@ -95,17 +95,15 @@ int CLASS::doEQU(MerlinLine &line, TSymbol &sym) { res = -1; - if (syntax==SYNTAX_MERLIN) - { - char buff[32]; - sprintf(buff,"$%08X",line.expr_value); - std::string s1=buff; - s = addVariable(line.lable, s1, true); - } - else - { - s = addVariable(line.lable, line.operand, true); - } +#if 1 + char buff[32]; + sprintf(buff, "$%08X", line.expr_value); + std::string s1 = buff; + s = addVariable(line.lable, s1, true); +#else + // do this if you want to do this more as a #define + s = addVariable(line.lable, line.operand, true); +#endif if (s != NULL) { res = 0; @@ -295,6 +293,19 @@ int CLASS::doAddress(MerlinLine &line, TSymbol &sym) res = 1 + sym.stype; if (pass > 0) { + switch(line.expr_shift) + { + case '^': + line.expr_value=(line.expr_value>>16)&0xFFFF; + break; + case '<': + line.expr_value=(line.expr_value)&0xFF; + break; + case '>': + line.expr_value=(line.expr_value>>8)&0xFFFF; + break; + } + //line.setError(errIncomplete); setOpcode(line, sym.opcode); for (i = 0; i < (res - 1); i++) @@ -770,13 +781,13 @@ int CLASS::doBYTE(MerlinLine & line, TSymbol & sym) { lastcarry = false; } - else if (sym.opcode==0xFB) // XCE + else if (sym.opcode == 0xFB) // XCE { if (trackrep) { if (lastcarry) { - mx=0x03; + mx = 0x03; } } } diff --git a/psuedo.cpp b/psuedo.cpp index d42e7a8..32c3c6a 100644 --- a/psuedo.cpp +++ b/psuedo.cpp @@ -839,6 +839,18 @@ int CLASS::ProcessOpcode(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) a.PC.currentpc = a.PC.orgsave; line.startpc = a.PC.orgsave; } + +#if 0 + // Merlin32 seems to have a bug where ORG seems like it can only be 16 bits + if ((line.syntax&SYNTAX_MERLIN32)==SYNTAX_MERLIN32) + { + // so clear the bank word in all variables + a.PC.orgsave &= 0xFFFF; + a.PC.currentpc&=0xFFFF; + line.startpc &=0xFFFF; + } +#endif + line.flags |= FLAG_FORCEADDRPRINT; break; case P_SAV: diff --git a/qasm.ini b/qasm.ini index 9769696..5cd67fa 100644 --- a/qasm.ini +++ b/qasm.ini @@ -4,10 +4,10 @@ logdir=/var/log/mylog logfile=mylog.log [option] -debug=1 +;==debug must be an integer. Code can use this as a level +;debug=0 nocolor=false ;syntax=merlin32 -;debug must be an integer. Code can use this as a level [application] timezone=America/Los_Angeles @@ -33,8 +33,7 @@ merlinerrors=true symcolumns=3 [reformat] -tabs=12; 18; 30 -;tabs=0;0;0 +tabs=12;18;30 From 4781b693aa58260735dd0510cfa681b5dfbe2b70 Mon Sep 17 00:00:00 2001 From: marketideas Date: Tue, 19 Nov 2019 13:45:12 -0800 Subject: [PATCH 11/26] update README --- README | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/README b/README index 5e4a78c..0d6b762 100644 --- a/README +++ b/README @@ -1,29 +1,38 @@ Merlin Compatible assembler/linker (and more) for linux This project is FAR from complete...as I have just gotten it to compile all 256 65816 opcodes. -The program will read/compile linux based Merlin syntax files (.s), as well as original Merlin 8/16/16+ files in Merlin format -(high bit set), compressed spaces, and only a to end lines. I plan on adding a mode that will process and convert to linux style so -files can be converted for easy editing under linux. -Merlin32 is great, but there are aspects of it that I don't like (always outputting assembly status and creating .txt file listings, etc) +Update (11/19/2019) - All code generating opcodes/psuedo-ops complete. -Along time ago, in the mid 1980's I wrote a Merlin compatible assembler and programming shell (with the help of Lane Roathe) for the Apple //GS -Recently, Lane sent me the source code to that assembler. Unfortunately, because of some of the features we added to the assembler, it will not -compile under Merlin or Merlin32. (We actually used qasm to build qasm). +The program will read/compile linux based Merlin syntax files (.s), as well as original Merlin +8/16/16+ files in Merlin format +(high bit set), compressed spaces, and only a to end lines. I plan on adding a mode that +will process and convert to linux style so files can be converted for easy editing under linux. -This project will be a linux compatible version, that will compile/link the original source. However, due to speed and everything 'linux' -I doubt the original will be used much. +Merlin32 is great, but there are aspects of it that I don't like (always outputting assembly +status and creating .txt file listings, etc) -I also would like to interface with the CiderPress library to allow output from the assembler/linker to write files directly to Prodos -based .2MG (or other) images. That way, after a compile, the code under test can be immediately run from a GS emulator. +Along time ago, in the mid 1980's I wrote a Merlin compatible assembler and programming shell +(with the help of Lane Roathe) for the Apple //GS +Recently, Lane sent me the source code to that assembler. Unfortunately, because of some of the +features we added to the assembler, it will not compile under Merlin or Merlin32. (We actually used +qasm to build qasm). + +This project will be a linux compatible version, that will compile/link the original source. +However, due to speed and everything 'linux' I doubt the original will be used much. + +I also would like to interface with the CiderPress library to allow output from the assembler/linker +to write files directly to Prodos based .2MG (or other) images. That way, after a compile, the code +under test can be immediately run from a GS emulator. This early version relies on the Poco Foundation libraries. You must have these installed. -Additionally, this repo relies on another repo here called 'libpal'. Both repositories must be cloned at the same level. +Additionally, this repo relies on another repo here called 'libpal'. Both repositories must +be cloned at the same level. libpal does not have to be built. The 'qasm' compile will build all of those source files. -'cmake' is used to build the Makefiles. There is a generic Makefile in the base directory that does all of the 'cmake' stuff for you. -(in a 'build' directory) +'cmake' is used to build the Makefiles. There is a generic Makefile in the base directory that does +all of the 'cmake' stuff for you. (in a 'build' directory) For example: mkdir workdir From d3bc1455fad264b91bcde5b598d5972f3886eecd Mon Sep 17 00:00:00 2001 From: marketideas Date: Tue, 19 Nov 2019 15:55:38 -0800 Subject: [PATCH 12/26] removed operand with spaces --- testdata/2007-labels-and-symbols.S | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/testdata/2007-labels-and-symbols.S b/testdata/2007-labels-and-symbols.S index e5400cf..aca00e4 100644 --- a/testdata/2007-labels-and-symbols.S +++ b/testdata/2007-labels-and-symbols.S @@ -219,13 +219,13 @@ next :skiphex ; extract bytes from 32-bit value with short regs - lda #thirty2 + 768 + lda #thirty2+768 lda #^thirty2 rep #$30 mx %00 - lda #thirty2 + 1024 + lda #thirty2+1024 lda #^thirty2 rts From e2dd7ab6457ebd177268f549c809074b0b56542d Mon Sep 17 00:00:00 2001 From: marketideas Date: Tue, 19 Nov 2019 17:09:58 -0800 Subject: [PATCH 13/26] test --- asm.cpp | 19 ++++++------------ eval.cpp | 2 +- opcodes.cpp | 9 +++++++-- psuedo.cpp | 6 +++--- src/var.s | 6 +++--- testdata/M32_expected/2007-labels-and-symbols | Bin 695 -> 695 bytes testdata/M32_expected/2019-local-variables | Bin 150 -> 151 bytes 7 files changed, 20 insertions(+), 22 deletions(-) diff --git a/asm.cpp b/asm.cpp index 5bb348d..9324727 100644 --- a/asm.cpp +++ b/asm.cpp @@ -1331,14 +1331,15 @@ int CLASS::callOpCode(std::string op, MerlinLine &line) switch (line.expr_shift) { case '<': - line.expr_value &= 0xFF; + //line.expr_value &= 0xFF; break; case '>': line.expr_value >>= 8; - line.expr_value &= 0xFFFF; + //line.expr_value &= 0xFFFF; break; case '^': - line.expr_value = (line.expr_value >> 16) & 0xFFFF; + line.expr_value = (line.expr_value >> 16); + //line.expr_value = (line.expr_value >> 16) & 0xFFFF; break; case '|': break; @@ -1352,12 +1353,14 @@ int CLASS::callOpCode(std::string op, MerlinLine &line) 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 +#endif { line.flags |= FLAG_FORCELONG; } @@ -1406,13 +1409,6 @@ typedef struct // these are the regular expressions that determine the addressing mode // and extract the 'expr' part of the addr-mode -// ^([_,a-z,A-Z,0-9:\]].+)\,[s,S]{1}$ // might be a better syn_s - -// "^([:-~][0-Z_-~]*)$" // this is a valid identifier -// "^([$][0-9A-Fa-f]+)$" // hex digit -// "^([%][0-1][0-1_]+[0-1])$" - binary numbera -// "^([0-9]+)$" - decimal number -// "^([:-~][^\],()]*)$" - valid expression const TaddrMode addrRegEx[] = { { "^(?'expr'.+)\\,[s,S]{1}$", syn_s, "e,s"}, // expr,s @@ -1430,9 +1426,6 @@ const TaddrMode addrRegEx[] = {"", 0, ""} }; -// keep this next line for awhile -// {"^#{1}(?'shift'[<,>,^,|]?)(.+)$", syn_imm, "immediate"}, //#expr,#^expr,#|expr,#expr - // one or more of any character except ][,(); const std::string valExpression = "^([^\\]\\[,();]+)$"; diff --git a/eval.cpp b/eval.cpp index ff7be25..713ce9d 100644 --- a/eval.cpp +++ b/eval.cpp @@ -665,7 +665,7 @@ int CLASS::evaluate(std::string & e, int64_t &res, uint8_t &_shiftmode) } else if (token.str == "<") { - //rhs = (rhs << 8 ) & 0xFFFF; + //rhs = (rhs) & 0xFFFF; } else if (token.str == ">") { diff --git a/opcodes.cpp b/opcodes.cpp index 39e51c4..72a8cb1 100644 --- a/opcodes.cpp +++ b/opcodes.cpp @@ -194,9 +194,14 @@ int CLASS::doMVN(MerlinLine &line, TSymbol &sym) //line.errorText = line.operand_expr2; } + uint32_t v=(value & 0xFFFFFFFF); + //printf("val1 %08X\n",v); + //printf("val1 %08X\n",line.expr_value); + setOpcode(line, op); - line.outbytes.push_back(value & 0xFF); - line.outbytes.push_back(line.expr_value & 0xFF); + // these bytes are the two bank registers + line.outbytes.push_back((v>>16) & 0xFF); + line.outbytes.push_back((line.expr_value>>16) & 0xFF); line.outbytect = res; } diff --git a/psuedo.cpp b/psuedo.cpp index 32c3c6a..bd6c4fa 100644 --- a/psuedo.cpp +++ b/psuedo.cpp @@ -18,15 +18,15 @@ uint32_t CLASS::doShift(uint32_t value, uint8_t shift) { if (shift == '<') { - value = (value) & 0xFF; + value = (value) & 0xFFFFFF; } if (shift == '>') { - value = (value >> 8) & 0xFF; + value = (value >> 8) & 0xFFFFFF; } else if ((shift == '^') || (shift == '|')) { - value = (value >> 16) & 0xFF; + value = (value >> 16) & 0xFFFFFF; } return (value); } diff --git a/src/var.s b/src/var.s index b54c676..7702c95 100644 --- a/src/var.s +++ b/src/var.s @@ -13,13 +13,13 @@ start nop ldy #$00 ]loop sta $800,y dey - bne ]loop;]loop2 - bne ]myvar; + ;dw ]loop;]loop2 + ;bne ]myvar; bcs ]loop bpl ]loop rts - use var + ;use var lst on diff --git a/testdata/M32_expected/2007-labels-and-symbols b/testdata/M32_expected/2007-labels-and-symbols index 55ff1f395ee67dcd5a9900727d8174c849d97a21..a200c62e91cd8a28de3ff5baa42ff17824d08e13 100644 GIT binary patch delta 33 kcmdnax}9}`x)>wFmoSqrLJVKt{`=yp`~}M0Xj{bu0OjEg=>Px# delta 33 kcmdnax}9}`x)=k)moSqrj0|7i{`=yp`~}M0Xj{bu0OS)5#Q*>R diff --git a/testdata/M32_expected/2019-local-variables b/testdata/M32_expected/2019-local-variables index 64d9d5b0c8dde12d99e879b22596f55326266721..2e009386ec607b6ea99ad0184bfa3d057906fa57 100644 GIT binary patch delta 26 icmbQnIGu4qi}3me28NY7>r8|`{9LNDt|IKi&jbL984Jz; delta 25 hcmbQvIE`^ai_qEzhLt+&OoTrCT&lCKBJ9J@1OSF!3(Eii From 630ea6662368d0e09f1e82d7b9131905ea29f1fa Mon Sep 17 00:00:00 2001 From: marketideas Date: Wed, 20 Nov 2019 07:59:02 -0800 Subject: [PATCH 14/26] adding script to create M32 output files --- Makefile | 1 + asm.cpp | 1 + asm.h | 34 ++++++++++++----- merlintests.sh | 35 ++++++++++++++++++ runtests.sh | 4 +- testdata/M32_expected/1000-allops-value-65816 | Bin 588 -> 0 bytes testdata/M32_expected/1001-allops-zero-65816 | Bin 588 -> 0 bytes .../M32_expected/1002-embedded-instructions | Bin 101 -> 0 bytes testdata/M32_expected/1003-flags-and-branches | Bin 311 -> 0 bytes testdata/M32_expected/1004-data-recognition | Bin 196 -> 0 bytes testdata/M32_expected/2000-allops-value-6502 | Bin 598 -> 0 bytes testdata/M32_expected/2001-allops-zero-6502 | Bin 598 -> 0 bytes testdata/M32_expected/2002-allops-value-65C02 | Bin 489 -> 0 bytes testdata/M32_expected/2003-allops-zero-65C02 | Bin 489 -> 0 bytes testdata/M32_expected/2004-numeric-types | Bin 1024 -> 0 bytes testdata/M32_expected/2005-string-types | Bin 3132 -> 0 bytes testdata/M32_expected/2006-operand-formats | Bin 133 -> 0 bytes testdata/M32_expected/2007-labels-and-symbols | Bin 695 -> 0 bytes testdata/M32_expected/2008-address-changes | Bin 203 -> 0 bytes testdata/M32_expected/2010-target-adjustment | Bin 191 -> 0 bytes testdata/M32_expected/2011-hinting | 2 - testdata/M32_expected/2012-label-localizer | Bin 103 -> 0 bytes testdata/M32_expected/2013-notes-and-comments | Bin 98 -> 0 bytes testdata/M32_expected/2014-label-dp | Bin 601 -> 0 bytes testdata/M32_expected/2019-local-variables | Bin 151 -> 0 bytes testdata/M32_expected/2020-cycle-counts-65816 | Bin 126 -> 0 bytes testdata/M32_expected/2021-external-symbols | Bin 329 -> 0 bytes testdata/M32_expected/2022-extension-scripts | Bin 213 -> 0 bytes 28 files changed, 63 insertions(+), 14 deletions(-) create mode 100755 merlintests.sh delete mode 100644 testdata/M32_expected/1000-allops-value-65816 delete mode 100644 testdata/M32_expected/1001-allops-zero-65816 delete mode 100644 testdata/M32_expected/1002-embedded-instructions delete mode 100644 testdata/M32_expected/1003-flags-and-branches delete mode 100644 testdata/M32_expected/1004-data-recognition delete mode 100644 testdata/M32_expected/2000-allops-value-6502 delete mode 100644 testdata/M32_expected/2001-allops-zero-6502 delete mode 100644 testdata/M32_expected/2002-allops-value-65C02 delete mode 100644 testdata/M32_expected/2003-allops-zero-65C02 delete mode 100644 testdata/M32_expected/2004-numeric-types delete mode 100644 testdata/M32_expected/2005-string-types delete mode 100644 testdata/M32_expected/2006-operand-formats delete mode 100644 testdata/M32_expected/2007-labels-and-symbols delete mode 100644 testdata/M32_expected/2008-address-changes delete mode 100644 testdata/M32_expected/2010-target-adjustment delete mode 100644 testdata/M32_expected/2011-hinting delete mode 100644 testdata/M32_expected/2012-label-localizer delete mode 100644 testdata/M32_expected/2013-notes-and-comments delete mode 100644 testdata/M32_expected/2014-label-dp delete mode 100644 testdata/M32_expected/2019-local-variables delete mode 100644 testdata/M32_expected/2020-cycle-counts-65816 delete mode 100644 testdata/M32_expected/2021-external-symbols delete mode 100644 testdata/M32_expected/2022-extension-scripts diff --git a/Makefile b/Makefile index 75353fe..98d38ea 100644 --- a/Makefile +++ b/Makefile @@ -34,6 +34,7 @@ debug: distclean: rm -rf ./build -rm -rf ./testout + -rm -rf ./m32out clean: -rm -rf ./build diff --git a/asm.cpp b/asm.cpp index 9324727..b57ae41 100644 --- a/asm.cpp +++ b/asm.cpp @@ -1554,6 +1554,7 @@ void CLASS::initpass(void) truncdata = 0; variables.clear(); // clear the variables for each pass + macros.clear(); while (!PCstack.empty()) { PCstack.pop(); diff --git a/asm.h b/asm.h index aa0e88e..5a9573c 100644 --- a/asm.h +++ b/asm.h @@ -280,11 +280,12 @@ public: { clear(); } - void clear(void) { - lupct=0; - lupoffset=0; - luprunning=0; - lupskip=false; + void clear(void) + { + lupct = 0; + lupoffset = 0; + luprunning = 0; + lupskip = false; } uint16_t lupct; bool lupskip; @@ -299,9 +300,10 @@ public: { clear(); } - void clear(void) { - doskip=false; - value=0; + void clear(void) + { + doskip = false; + value = 0; } uint32_t value; bool doskip; @@ -334,7 +336,7 @@ public: value = 0; used = false; //text = ""; - var_text=""; + var_text = ""; name = ""; namelc = ""; stype = 0; @@ -343,6 +345,17 @@ public: } }; + +class TMacro +{ +public: + std::string name; + std::string lcname; + uint32_t currentline; + std::vector lines; + std::vector variables; +}; + class TPsuedoOp; class T65816Asm : public TFileProcessor @@ -371,8 +384,8 @@ public: std::string currentsymstr; std::vector lines; + Poco::HashMap macros; Poco::HashMapopcodes; - Poco::HashMap macros; Poco::HashMap symbols; Poco::HashMap variables; @@ -386,6 +399,7 @@ public: std::stack LUPstack; std::stack DOstack; std::stack LSTstack; + std::stack curMacro; TPsuedoOp *psuedoops; diff --git a/merlintests.sh b/merlintests.sh new file mode 100755 index 0000000..6f39cd2 --- /dev/null +++ b/merlintests.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +OUTDIR=./m32out + +rm -rf $OUTDIR +mkdir -p $OUTDIR + +SRC=`ls ./testdata | grep -E '^([0-9]+)(.*)\.[Ss]'` + +#SRC=`ls ./testdata | grep -E '^([0-9]+)(.*)\.[Ss]' | grep -i 2007` + +for S in $SRC ; do + + S1=$S + S1=${S1/.S/} + S1=${S1/.s/} + + BASE=${S/.S/} + BASE=${BASE/.s/} + cd ./testdata + #merlin32 $S 2>/dev/null >/dev/null + merlin32 . $S 2>/dev/null + + R=?$ + cd - >/dev/null + cp ./testdata/$S1 $OUTDIR/$S1.bin 2>/dev/null + rm -f ./testdata/*.txt 2>/dev/null + rm -f ./testdata/$S1 2>/dev/null + R=?$ + +done +ls $OUTDIR + + + diff --git a/runtests.sh b/runtests.sh index 6e4ae83..044b44b 100755 --- a/runtests.sh +++ b/runtests.sh @@ -40,8 +40,8 @@ for S in $SRC ; do MSHA="Q" QSHA="M" - if [ -f ./testdata/M32_expected/$BASE ] ; then - MSHA=`sha256sum ./testdata/M32_expected/$BASE | awk '{ print $1;}'` 2>/dev/null >/dev/null + if [ -f ./m32out/$BASE.bin ] ; then + MSHA=`sha256sum ./m32out/$BASE.bin | awk '{ print $1;}'` 2>/dev/null >/dev/null fi if [ -f $OUTDIR/$BASE.bin ] ; then diff --git a/testdata/M32_expected/1000-allops-value-65816 b/testdata/M32_expected/1000-allops-value-65816 deleted file mode 100644 index 204a57bf01c9a3ffe9401651388e6a830e531aec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 588 zcmWN{b9k0v07mgAtrp)edvDgVmTlX%ZMS9HcFQ)FZJVnvFRrco^!#_O>-+*DTtCMR zcHA(>_3^mA9@pRFhI`ydkJsxpL?J5Ch)xWAh)FD8V#kS#;-UB`0s7|{4+%*`Vv>-Q zWF$|4Ql?6c(x9}+&k`4sZeQHf~~b@D{WcZA06w*kN|Ei{0#DFZquA3X&3%`0B> qhPQ2??ni?7(I8PY$Q2D9MT4i&n3x!1i7k$};)ySTgo(WJYGRU*lw^pA zN-l+zUh}$C-bhWFH`DSK=|~@vfDAH*k;&UK%Ob06+2zQYi+9LPp77pcY( zQn(237yW=@d`R(-lqji`(#lX)IptNT=%bG-ZH-i>3ROcd|JQ3 zjfjRcqH&0tG}Y|I^X6J;sg>5+wDsBNU+^XEXdj9WI{Hc{oqg>aU3Be6_Z~gz#kceh zNgsXnqrU+L8f35`Lk$}~f{~13bV$Y+Yn<^Wm}rv8rhLcLY15g(OlE~-wmIgSXTAl# z_k$l7TC{ixOIgP9P^_@hDyyxr);jBL*vO`zHuE#T@M}nZv&B~1Y`4QsyX@X$@4o#U z;2?)Wao7<@9dq0XC!O;9Y0jKI#~+;MLP##Usw|nmU W$G<%A(0~4a#N#JVdB$^Igytpk*^H?G diff --git a/testdata/M32_expected/1002-embedded-instructions b/testdata/M32_expected/1002-embedded-instructions deleted file mode 100644 index cffff3c6b4f59ff3aca169f2ed3cbfc821ddd335..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 101 zcmb36{m4K;L_k4CKtW4DL0>>2QXpX^gU(9E4}TIK87yV^z`T-yq2E=RF+m~WRl^@0 z7D%K4E3D`8g?Bz7}yk@)PjQn1A~Kup)DF5Yd)c$5Jf65m=rkdFDRVUjNI6y zO@);r)wR=>Jiqt+Y|DN~{Q33ju|{)xkH{-XOf{91lcNbekR_AU17iF;#{roFve%j? zhXAc>dsJjJq7De64o+De6uB53 zgo3prdb7VLxVUB@8#CE$L$=ZRZ0vpfxVV-@yHPm;nh(<*BPY2~Zj=Y*MfpsA z3KXOe0TiYPo}#E&aa018M5Rz^RHiKD%2R=gRH8Cfs#2{wH6omvs1~Y?>X^FJt4{+O z(ul@12}Dhsq2{OsYKdB*)@^9pj`nn*Bc13RM3=5~L)}pi)D!hGz3J1Je)MMm0~s_J z4H=4tpELd)deS1L)u(bQp!9Bj_j! z=NQL1!AVYWnlqd|$N39fM3>NIbOl{C*SH?R4Q_Ia+uXT}?%hWZ&_nbHJw{K6b$vd1S+RSt1D9nq(<|u55!kH+Dg~YLtHWuPypKU79u5qNP^e(^?yC+iBmy`*freo#~>hZr%0pfu4Hl-G{y((vSWO zU?77GHpEcF3^&3^qdqcvjIoSkJQMiXM3W|)VybDTn=zAFvzfzO<}sfIKC#dui!HI# zGRs$3xyowRu$E8x%;&yX=SyE%?`z*|VB;pfWi#LLJzH$G%@2OG-3~kL+HKEXKk+la zu#f!?IC#imM;vv`@e`c|w_Qw3UQ?43)6Hy5&2&%qbjS2;YHE6z+;rPC({01lbp5)f-^V$& zvt@@^cC2M5Say=-a5xOfNKT5Bq#`wG(xxMQhKwi^%8Z;WlZC8gb0#}E$eGIp<<65A zl|qFnLQ#sj6{keWQm8a4gWSuSa+Ifn2NkJAfep-^yo=1def(G zKl%?Chz6kmGunKqpn%p_=5Fd?(&pt)!s znjdNwu#iQISwa{~mn}ytR<1&;Q8-$&mUTq1eghlX#O5uLL~Y%Mwxb!cF&Yi!&#Y>mb6?7F{yKZi9lelq(1VaMB1A*Y> zK=6GaG&Gbj!U`8&1QA7w97WV<(TPD!Vg1D{6N#-B2kd}a>ILTyFOr2)B8D`F!&78UOn9l+hF0$AX zOP5)0g_WyTTeEf@>)F6>zuRb&KmN4Y7F)Od#oya^u#;Wv-ea$Q_8)N2A%~9~b?o>F zPI8LVXPkA;`3o+(Ee-FxnP;NhdkLZ3Y48P9p~(krjMdF!3` Q{`>y}A3uHO3t##69j_CI4FCWD diff --git a/testdata/M32_expected/2004-numeric-types b/testdata/M32_expected/2004-numeric-types deleted file mode 100644 index 47e2524502e99c91732705abac5d18b216389e39..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1024 zcmYcgR1!2+5_AD#K_FAf7>HaL7#bKL7|eh&fkGn|G@KdfK(GOnGD6eJJ7xkC1)RNV z_nEuz{uAQ=e|PuH?o~58%F{wYDUG3F)nEaQ6ej7$)%XF_c*aHnD68@AT?(zFs&)XH C3~EpS diff --git a/testdata/M32_expected/2005-string-types b/testdata/M32_expected/2005-string-types deleted file mode 100644 index df57058d0d0483766bc909c5897bfe0d18f3f4fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3132 zcmeHJyG|QH6y5wlkjM{Qxp8AznDDYFA`4NtL6P`@jCb#9N1mN=X2#xZs&$e7u-qV} zh?I1ch{`pe00^j}5GRUK<<5c=9Ja7niWH$hqnUHg+;iD`hF3x*(AwW=x4~GQU0z*W zj*d=_CzH|F>2+46)9UNKvKUmVRf}(IHg=Hlmv5h^=Vu4w@$~%1G+Sw`K3`kk*xYJ9 z&Z>l9wOTE~-YQ9NmgTRM7HB+FVPmsWsXVB6^oK7&ZI-=YLNG!o3zoz7%}NODfIEy;l;ns+$u1Bk zkZ3^T03{$XQ9D#18Po#FyOPBqIRrQmYCwyaK^xHYnNNB(jKN@Jxa2VpAhHYtFpiSS z7C@b}5|D`kl$=CEMHhpi3%L#NTyH7lt^y33y(ppV?0kb3UN zH3+stfrffYMAQUF*CQr!%nYgahF&(8qHn#wa`dNHkfdHwlzI;uz*+jz=$8{Hif@nX zJ)QH{$d=~ciI3TG!AtS1=&5*7bj6~3F4|r$3SJa9^vIt#XK*!J^5z|W%9gz%i(a8e zZ_&GpaJk7+3Pq~fyC-{!hFJnPkpC7;1~nQ~%QXT82)8s~;Wp5BuhZX1=y941cWxsD zUlE)p$JS_4dQ98dLCmga{0=CEB_xdSee1F@&v=mjEsbghK!5`djWd^1_Ap50T5&mC;$M| C947n# diff --git a/testdata/M32_expected/2007-labels-and-symbols b/testdata/M32_expected/2007-labels-and-symbols deleted file mode 100644 index a200c62e91cd8a28de3ff5baa42ff17824d08e13..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 695 zcmcJN&2G~`5XWa9pkZ(l)Z<9L5Cl;RmJmot9FmAb4n3r)KsjKyZemF6kT`|57uS4$ zKLv+5SbhiY$r}`*T%b{%Q-lymYu14i;)?X&nVsMMXLk>?`g6L*V?O2;PFV6KPPxR$ zCwzvhtg~1oa#7V60v1hUp}}9}heOKlN{#+3*f5G`f}4W*w9#mU}K!fsxHP*LWB|k zBvL|>%ZaM43jwudl*u?d012SHx&Q&7NQN>7>PMiIVc@gS5L!hOzoRuzLx2__%x1Ic zS_De#5nPVoN^ngf>qlyRPpxk$<&g?VMGQ`Yufdmanued#@KajPW4(a&BDV4ft%6!b z1UiRw9_a$oMWiy)I+B5O73n(C4Wye$6{K4ju8QC&eEj6;v*#~fzIy%U?YsB?yKZ!x zAt{;E_1rcM{ek1Q%d|1_Gh|wJmrQquw!L1@c75_(a(wbV1>9X{&?CQNs=8zU)7#xA zv){MPLDrXGqN{wFmf~k+uuV#q#G+wD=#a^ K+#>{y4ABoowLAO( diff --git a/testdata/M32_expected/2010-target-adjustment b/testdata/M32_expected/2010-target-adjustment deleted file mode 100644 index 5b3cfa680579537c525423eb7ff4a911d8b49142..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 191 zcmZ1}xJYS%@k*Bl3uVT1*VUcx&k8aaD>Z~YI0`rm zFra~kwOj&g9R>J!1oZd>@&p8Qg#>s-1lAe~^qLB+wG`;J6;NOjSj#5xB|{+T=l``? z0&BAcR=(;j7wD}P=&cuMs^@QLY--kFQdrv}u$DogfxD)*t{x=R(%QC`S79xm!diZX ewE_xj1r^o`DXbM%SSzBiR#aiFn8I3dg#-ZOnK|JA diff --git a/testdata/M32_expected/2011-hinting b/testdata/M32_expected/2011-hinting deleted file mode 100644 index 07cb179..0000000 --- a/testdata/M32_expected/2011-hinting +++ /dev/null @@ -1,2 +0,0 @@ -,,©ê,¢ÿê -ê,¢ÿê  V$©¢"  ( V$©3¢D : =ê­V$ E` V$©U¢f`‚ƒ©™` \ No newline at end of file diff --git a/testdata/M32_expected/2012-label-localizer b/testdata/M32_expected/2012-label-localizer deleted file mode 100644 index 7a2358e88df2fbc5c448750d19ab52d2b81b1313..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 103 zcmaF0mRDdczrb1nfwg=BuYh2!h`>t0S8K%u*2;tUYh?wNGJIfDkQY#36j-UW)=c2l pT63VpO5?STK&CTD%}N&qFR)$(AAtsjS8F>uKnAU3xbP1K697C=GxPue diff --git a/testdata/M32_expected/2013-notes-and-comments b/testdata/M32_expected/2013-notes-and-comments deleted file mode 100644 index 233ba0563752d1a6f2f771284ebfcdd42b2476ac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 98 zcmb8i$pHWm3;;nP#H|qzC24QFRD<~qf+wIv5=N#_X>-P`M CBMkfi diff --git a/testdata/M32_expected/2014-label-dp b/testdata/M32_expected/2014-label-dp deleted file mode 100644 index 5c8e85e8d3da44f1b76ebca6fcf24b1f2dc23ec0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 601 zcmXBOV|14R9L4dQTm1jCd$N{o+qP|6-?sJ3w#{YRwr#DJm)pYA>D)K>ocnok3xql; zJx-v<3Gq0Qy^fF9@%1`CyiS-mI5=2@BRmm^NF*W?g{VG6iyp%i(-g}TdyM3fmpH^F z9`Q*)LJ}o5B}tmhl-!iUl+q=RDHW;Rl7_UTBRv_&n2F3;d`($R*-Y8pEr)WFi`?WP zFZsw%fr6$&g^QSqnu?iQ3J{sCnvM|mn#q*CQ7M?6(c)lAi0QA0JUMQ!T% z2h^n=^=Z)1)TnWjAdi}wnwgrrs6|U!{rTORHngQ3?di~wPMy1$x|+I~y1Sx>deV#D z^r0{P=+A(Gra^;;n1-5$nTERrjlfUxCxDR{qZmDgvE#;@CYUCgCb?v?rZAOhOlJl& znZ@imrn&Rxn--WBnijcaF-us=GM2M~m8@d*8rBA`Gp#pmFl}_jCT(U5TiM2TcCeFO zyG?uc?lbK-9WWhq$srDNL`ONsaZYfOQ>Qs|_MGXw>4NE^D=z6WSGdYGu5*K%+`4VL zbN8O5 z4|BF!Ui0ZCv+v1f5DW@flyImJmDFev`mc}}`R9}0Qxlw4Qa{~gpa+<7qsPFXLr=9p4i333JAt`JI32KmOE1aLH&kL!U=(4%B4eb)V8H0&>AGPM4Gl>h`vg2pbPY2_U=JId42jyW83I_z@P?KsfvRRRrb1sV>%d2{sT f^A}%$PD?7v&rZ!#V1zm>0ptKKh6JEYYF-Ke=88um From eba951f00fe37fc3c95f8233dd5af10059648a72 Mon Sep 17 00:00:00 2001 From: marketideas Date: Wed, 20 Nov 2019 10:20:43 -0800 Subject: [PATCH 15/26] moving some test scripts around --- Makefile | 6 ++--- asm.cpp | 5 ++++ merlintests.sh | 4 ++-- testdata/3000-addresses.S | 28 ++++++++++++++++++++++ src/main.s => testdata/3001-lroathe.S | 0 src/testfile.s => testdata/3002-testfile.S | 0 src/var.s => testdata/3003-var.S | 0 7 files changed, 38 insertions(+), 5 deletions(-) create mode 100644 testdata/3000-addresses.S rename src/main.s => testdata/3001-lroathe.S (100%) rename src/testfile.s => testdata/3002-testfile.S (100%) rename src/var.s => testdata/3003-var.S (100%) diff --git a/Makefile b/Makefile index 98d38ea..57fc20a 100644 --- a/Makefile +++ b/Makefile @@ -61,13 +61,13 @@ compare: asm: test1: - -qasm src/main.s + -qasm testdata/3001-lroathe.S test2: - -qasm src/testfile.s + -qasm testdata/3002-testfile.S test3: - -qasm src/var.s + -qasm testdata/3003-var.S diff --git a/asm.cpp b/asm.cpp index b57ae41..19ccbaa 100644 --- a/asm.cpp +++ b/asm.cpp @@ -1342,6 +1342,11 @@ int CLASS::callOpCode(std::string op, MerlinLine &line) //line.expr_value = (line.expr_value >> 16) & 0xFFFF; break; case '|': + if (syntax==SYNTAX_MERLIN) + { + line.setError(errBadLabel); + line.expr_value=0; + } break; } } diff --git a/merlintests.sh b/merlintests.sh index 6f39cd2..f645689 100755 --- a/merlintests.sh +++ b/merlintests.sh @@ -18,8 +18,8 @@ for S in $SRC ; do BASE=${S/.S/} BASE=${BASE/.s/} cd ./testdata - #merlin32 $S 2>/dev/null >/dev/null - merlin32 . $S 2>/dev/null + merlin32 $S 2>/dev/null >/dev/null + #merlin32 . $S 2>/dev/null R=?$ cd - >/dev/null diff --git a/testdata/3000-addresses.S b/testdata/3000-addresses.S new file mode 100644 index 0000000..5b29154 --- /dev/null +++ b/testdata/3000-addresses.S @@ -0,0 +1,28 @@ + lst + xc + xc + org $018200 + +bank02 equ $020000 +bank03 equ $030000 +dp equ $A5 +long equ $020304 + + mx %00 +start nop + pea ^start + pea start + mvn bank02,bank03 + mvp bank03,bank02 + lda dp + lda dp + lda ^dp + lda |dp + lda #long + lda #long + lda #^long + lda #|long + + lst off diff --git a/src/main.s b/testdata/3001-lroathe.S similarity index 100% rename from src/main.s rename to testdata/3001-lroathe.S diff --git a/src/testfile.s b/testdata/3002-testfile.S similarity index 100% rename from src/testfile.s rename to testdata/3002-testfile.S diff --git a/src/var.s b/testdata/3003-var.S similarity index 100% rename from src/var.s rename to testdata/3003-var.S From 37ba8aaf40e86dc04d3432f3d6c274504188732a Mon Sep 17 00:00:00 2001 From: marketideas Date: Wed, 20 Nov 2019 10:38:23 -0800 Subject: [PATCH 16/26] more mods for testruns --- merlintests.sh | 2 +- runtests.sh | 5 +++-- testdata/3001-lroathe.S | 10 ++++------ testdata/3002-testfile.S | 4 ++-- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/merlintests.sh b/merlintests.sh index f645689..9e89e71 100755 --- a/merlintests.sh +++ b/merlintests.sh @@ -18,7 +18,7 @@ for S in $SRC ; do BASE=${S/.S/} BASE=${BASE/.s/} cd ./testdata - merlin32 $S 2>/dev/null >/dev/null + merlin32 . $S 2>/dev/null >/dev/null #merlin32 . $S 2>/dev/null R=?$ diff --git a/runtests.sh b/runtests.sh index 044b44b..fdc5cd0 100755 --- a/runtests.sh +++ b/runtests.sh @@ -1,6 +1,6 @@ #!/bin/bash -OUTDIR=./testout +OUTDIR=./qasmout TMPFILE=/tmp/qasm_out.txt rm -f $TMPFILE @@ -40,6 +40,7 @@ for S in $SRC ; do MSHA="Q" QSHA="M" + if [ -f ./m32out/$BASE.bin ] ; then MSHA=`sha256sum ./m32out/$BASE.bin | awk '{ print $1;}'` 2>/dev/null >/dev/null fi @@ -47,7 +48,7 @@ for S in $SRC ; do if [ -f $OUTDIR/$BASE.bin ] ; then QSHA=`sha256sum $OUTDIR/$BASE.bin |awk '{print $1;}'` 2>/dev/null >/dev/null fi - #echo "$MSHA $QSHA" + #echo "MSHA=$MSHA QSHA=$QSHA" shapass=0; CX=" " diff --git a/testdata/3001-lroathe.S b/testdata/3001-lroathe.S index b27f9ab..13f9832 100644 --- a/testdata/3001-lroathe.S +++ b/testdata/3001-lroathe.S @@ -114,7 +114,7 @@ START adc _num1+dum1 sbc _num1+dum1 bit _num1+dum0 - sta _num1+dum0 ;(FIXED): can't use sta _num1+dum0 + sta _num1+dum0 ;(FIXED): can't use sta _num1+dum0 ' stz _num1+dum0 lda _num1+dum0,x @@ -180,7 +180,7 @@ myQuit ldaz $FFFF ; forced DP - lda: $FFFF ; forced ABS (any char but 'L', 'D', and 'Z" + lda: $FFFF ; forced ABS (any char but 'L', 'D', and 'Z' ldal $FFFF ; forced long abs (3 byte address) ldaz $05 @@ -338,8 +338,6 @@ myQuit lda #^$A51234 ;bank - mx MX - lda $0008 ;ZP lda $08 ;ZP lda $ffff-$fff7 ;ZP @@ -362,8 +360,8 @@ L00BC bit L00BC hex ;no error hex 11,22,33,44,55,66,77,88,99 - hex 112233445566778899F - hex 112233445I566778899FF + ;hex 112233445566778899F + ;hex 112233445I566778899FF hex aabb,CC,0123456789abcdefABCDEF,ff diff --git a/testdata/3002-testfile.S b/testdata/3002-testfile.S index c120a8d..725dbbf 100644 --- a/testdata/3002-testfile.S +++ b/testdata/3002-testfile.S @@ -14,7 +14,7 @@ lexpr = $010203 immed = $123456 neg equ -16 -]var1 = v1234 +*]var1 = v1234 ;lst off start00 @@ -308,5 +308,5 @@ startF0 inc expr,x sbcl lexpr,x lst off - sav ./test.bin + ;sav ./test.bin From d65b01a882230e001db5fe8f4b0b0a4128fd1de3 Mon Sep 17 00:00:00 2001 From: marketideas Date: Wed, 20 Nov 2019 10:39:28 -0800 Subject: [PATCH 17/26] more mods for testruns --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 57fc20a..992c873 100644 --- a/Makefile +++ b/Makefile @@ -32,8 +32,8 @@ debug: distclean: - rm -rf ./build - -rm -rf ./testout + -rm -rf ./build + -rm -rf ./qasmout -rm -rf ./m32out clean: From 0b8a9dfae40d409e70ba67040424a94924ed8189 Mon Sep 17 00:00:00 2001 From: marketideas Date: Wed, 20 Nov 2019 18:36:29 -0800 Subject: [PATCH 18/26] more m32 compatibility tests --- merlintests.sh | 7 ++++++- testdata/1000-allops-value-65816.S | 4 ++-- testdata/3000-addresses.S | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/merlintests.sh b/merlintests.sh index 9e89e71..ad97e50 100755 --- a/merlintests.sh +++ b/merlintests.sh @@ -1,5 +1,10 @@ #!/bin/bash +X= +if [ "$1""L" != "L" ] ; then + X=_$1 +fi + OUTDIR=./m32out rm -rf $OUTDIR @@ -18,7 +23,7 @@ for S in $SRC ; do BASE=${S/.S/} BASE=${BASE/.s/} cd ./testdata - merlin32 . $S 2>/dev/null >/dev/null + merlin32$X . $S 2>/dev/null >/dev/null #merlin32 . $S 2>/dev/null R=?$ diff --git a/testdata/1000-allops-value-65816.S b/testdata/1000-allops-value-65816.S index 2439293..dc67504 100644 --- a/testdata/1000-allops-value-65816.S +++ b/testdata/1000-allops-value-65816.S @@ -5,7 +5,7 @@ ZP EQU $FF ABS EQU $FEFF LONG EQU $FDFEFF -MV0 EQU ZP ;Merlin 32 bug -- must use 8-bit constant, or -MV1 EQU ZP-1 ; '^' modifier is implicitly applied +MV0 EQU LONG ;Merlin 32 bug -- must use 8-bit constant, or +MV1 EQU LONG-$10000 ; '^' modifier is implicitly applied PUT allops-common-65816.S diff --git a/testdata/3000-addresses.S b/testdata/3000-addresses.S index 5b29154..d99592b 100644 --- a/testdata/3000-addresses.S +++ b/testdata/3000-addresses.S @@ -23,6 +23,6 @@ start nop lda #long lda #^long - lda #|long + lda #long lst off From e2203ca1d3697e29974f681028cb20659e389f4e Mon Sep 17 00:00:00 2001 From: marketideas Date: Wed, 20 Nov 2019 21:50:00 -0800 Subject: [PATCH 19/26] start of macro code --- asm.cpp | 49 +++++++++++++++++++++++++----- asm.h | 27 +++++++++++++++-- opcodes.cpp | 6 ++-- psuedo.cpp | 87 +++++++++++++++++++++++++++++++++++++++++++++++------ psuedo.h | 3 ++ 5 files changed, 149 insertions(+), 23 deletions(-) diff --git a/asm.cpp b/asm.cpp index 19ccbaa..e2c3671 100644 --- a/asm.cpp +++ b/asm.cpp @@ -1117,6 +1117,28 @@ out: return (res); } + +TMacro * CLASS::findMacro(std::string symname) +{ + 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); +} + TSymbol * CLASS::findSymbol(std::string symname) { TSymbol *res = NULL; @@ -1342,10 +1364,10 @@ int CLASS::callOpCode(std::string op, MerlinLine &line) //line.expr_value = (line.expr_value >> 16) & 0xFFFF; break; case '|': - if (syntax==SYNTAX_MERLIN) - { + if (syntax == SYNTAX_MERLIN) + { line.setError(errBadLabel); - line.expr_value=0; + line.expr_value = 0; } break; } @@ -1559,10 +1581,9 @@ void CLASS::initpass(void) truncdata = 0; variables.clear(); // clear the variables for each pass - macros.clear(); - while (!PCstack.empty()) + while (!macrostack.empty()) { - PCstack.pop(); + macrostack.pop(); } while (!LUPstack.empty()) { @@ -1576,6 +1597,11 @@ void CLASS::initpass(void) { LSTstack.pop(); } + while (!PCstack.empty()) + { + PCstack.pop(); + } + currentmacro.clear(); curLUP.clear(); curDO.clear(); } @@ -1928,6 +1954,7 @@ bool CLASS::codeSkipped(void) res = (curLUP.lupskip) ? true : res; res = (curDO.doskip) ? true : res; + res = currentmacro.running ? true : res; //printf("codeskip: %d\n",res); @@ -2050,7 +2077,15 @@ void CLASS::process(void) x = 0; if (op.length() > 0) { - x = callOpCode(op, line); + TMacro *mac=findMacro(op); + if (mac==NULL) + { + x = callOpCode(op, line); + } + else + { + x=0; + } } if ((x > 0) && (codeSkipped())) // has a psuedo-op turned off code generation? (LUP, IF, etc) diff --git a/asm.h b/asm.h index 5a9573c..3a4003d 100644 --- a/asm.h +++ b/asm.h @@ -352,8 +352,26 @@ public: std::string name; std::string lcname; uint32_t currentline; - std::vector lines; std::vector variables; + std::vector lines; + int32_t start,end; + bool running; + + TMacro() + { + clear(); + } + void clear(void) + { + name=""; + lcname=""; + variables.clear(); + lines.clear(); + currentline=0; + start = -1; + end=-1; + running = false; + } }; class TPsuedoOp; @@ -385,13 +403,14 @@ public: std::string currentsymstr; std::vector lines; Poco::HashMap macros; - Poco::HashMapopcodes; + Poco::HashMap opcodes; Poco::HashMap symbols; Poco::HashMap variables; TOriginSection PC; TLUPstruct curLUP; TDOstruct curDO; + TMacro currentmacro; bool listing; uint8_t truncdata; // for the TR opcode @@ -399,7 +418,7 @@ public: std::stack LUPstack; std::stack DOstack; std::stack LSTstack; - std::stack curMacro; + std::stack macrostack; TPsuedoOp *psuedoops; @@ -417,6 +436,8 @@ public: void pushopcode(std::string op, uint8_t opcode, uint16_t flags, TOpCallback cb); int callOpCode(std::string op, MerlinLine &line); + TMacro *findMacro(std::string sym); + TSymbol *findSymbol(std::string sym); TSymbol *addSymbol(std::string sym, uint32_t val, bool replace); TSymbol *findVariable(std::string sym); diff --git a/opcodes.cpp b/opcodes.cpp index 72a8cb1..8c22620 100644 --- a/opcodes.cpp +++ b/opcodes.cpp @@ -885,9 +885,9 @@ void CLASS::insertOpcodes(void) pushopcode("SW", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("USR", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("XC", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doXC)); - pushopcode("MAC", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); - pushopcode("EOM", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); - pushopcode("<<<", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); + pushopcode("MAC", P_MAC, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); + pushopcode("EOM", P_MAC, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); + pushopcode("<<<", P_MAC, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("ADC", 0x03, OP_STD | OP_A, OPHANDLER(&CLASS::doBase6502)); diff --git a/psuedo.cpp b/psuedo.cpp index bd6c4fa..0dd5f2f 100644 --- a/psuedo.cpp +++ b/psuedo.cpp @@ -130,6 +130,68 @@ out: return (res); } +int CLASS::doMAC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) +{ + UNUSED(opinfo); + + int res = 0; + int err = 0; + + std::string op = Poco::toUpper(line.opcode); + if (op == "MAC") + { + if (a.currentmacro.running) + { + err=errUnexpectedOp; + goto out; + } + if (line.lable.length()==0) + { + err=errBadLabel; + goto out; + } + a.macrostack.push(a.currentmacro); + a.currentmacro.clear(); + + a.currentmacro.name=line.lable; + a.currentmacro.lcname=Poco::toLower(line.lable); + a.currentmacro.start=line.lineno+1; + a.currentmacro.running=true; + if (a.pass == 0) + { + } + else + { + // don't need to do anything on pass > 0 + } + } + else // it is EOM or <<< + { + if (a.macrostack.size() > 0) + { + a.currentmacro.end=line.lineno; + a.currentmacro.running=false; + + std::pair p(a.currentmacro.name, a.currentmacro); + a.macros.insert(p); + + a.currentmacro = a.macrostack.top(); + a.macrostack.pop(); + } + else + { + err = errUnexpectedOp; + goto out; + } + } +out: + if (err) + { + line.setError(err); + } + return (res); +} + int CLASS::doLUP(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) { UNUSED(opinfo); @@ -340,6 +402,8 @@ int CLASS::doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) return (outct); } + + int CLASS::doDS(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) { UNUSED(opinfo); @@ -352,7 +416,7 @@ int CLASS::doDS(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) uint8_t shift; line.eval_result = 0; // since this is an data p-op, clear the global 'bad operand' flag - line.flags|=FLAG_FORCEADDRPRINT; + line.flags |= FLAG_FORCEADDRPRINT; std::string s; Poco::StringTokenizer tok(line.operand, ",", Poco::StringTokenizer::TOK_TRIM | Poco::StringTokenizer::TOK_IGNORE_EMPTY); @@ -418,11 +482,11 @@ int CLASS::doDS(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) v = datact; if (pagefill) { - v=line.startpc&0xFF; - v=0x100-v; + v = line.startpc & 0xFF; + v = 0x100 - v; } line.datafillct = (uint16_t)v & 0xFFFF; - res=line.datafillct; + res = line.datafillct; out: //printf("res=%d %04X\n",res,res); @@ -842,12 +906,12 @@ int CLASS::ProcessOpcode(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) #if 0 // Merlin32 seems to have a bug where ORG seems like it can only be 16 bits - if ((line.syntax&SYNTAX_MERLIN32)==SYNTAX_MERLIN32) + if ((line.syntax & SYNTAX_MERLIN32) == SYNTAX_MERLIN32) { // so clear the bank word in all variables a.PC.orgsave &= 0xFFFF; - a.PC.currentpc&=0xFFFF; - line.startpc &=0xFFFF; + a.PC.currentpc &= 0xFFFF; + line.startpc &= 0xFFFF; } #endif @@ -856,16 +920,19 @@ int CLASS::ProcessOpcode(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) case P_SAV: a.savepath = a.processFilename(line.operand, Poco::Path::current(), 0); break; + case P_MAC: + res = doMAC(a, line, opinfo); + break; case P_ERR: - if (a.pass>0) + if (a.pass > 0) { - if ((line.expr_value!=0) || (line.eval_result<0)) + if ((line.expr_value != 0) || (line.eval_result < 0)) { line.setError(errErrOpcode); //a.passcomplete=true; // terminate assembly } } - res=0; + res = 0; break; case P_LST: res = doLST(a, line, opinfo); diff --git a/psuedo.h b/psuedo.h index 94edb92..bf86c28 100644 --- a/psuedo.h +++ b/psuedo.h @@ -20,6 +20,7 @@ enum P_TR, P_ASC, P_ERR, + P_MAC, P_MAX }; @@ -41,6 +42,8 @@ public: int doDO(T65816Asm &a, MerlinLine &line, TSymbol &opinfo); int doTR(T65816Asm &a, MerlinLine &line, TSymbol &opinfo); int doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo); + int doMAC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo); + }; #undef CLASS \ No newline at end of file From c9febb19bdd9dbbb8709124f39345523f338f3ca Mon Sep 17 00:00:00 2001 From: marketideas Date: Thu, 21 Nov 2019 04:53:10 -0800 Subject: [PATCH 20/26] macros are defining/expanding - no ]vars --- asm.cpp | 150 ++++++++++++++++++++++++++++++++++++++++++++-------- asm.h | 27 ++++++---- opcodes.cpp | 4 +- psuedo.cpp | 25 +++++---- 4 files changed, 163 insertions(+), 43 deletions(-) diff --git a/asm.cpp b/asm.cpp index e2c3671..2bbe76f 100644 --- a/asm.cpp +++ b/asm.cpp @@ -211,7 +211,14 @@ void CLASS::print(uint32_t lineno) } else { - pcol += printf("%s ", printoperand.c_str()); + if (printoperand.length() > 0) + { + pcol += printf("%s ", printoperand.c_str()); + } + else + { + pcol += printf("%s ", operand.c_str()); + } } //pcol += printf("%-12s %-8s %-10s ", printlable.c_str(), opcode.c_str(), operand.c_str()); } @@ -292,6 +299,7 @@ void CLASS::print(uint32_t lineno) void CLASS::clear() { syntax = SYNTAX_MERLIN; + wholetext = ""; lable = ""; printlable = ""; opcode = ""; @@ -345,6 +353,7 @@ void CLASS::set(std::string line) std::string tline = line; clear(); + wholetext = line; isascii = false; delim = 0; while (i < l) @@ -1182,7 +1191,7 @@ out: return (res); } -TSymbol * CLASS::addVariable(std::string symname, std::string val, bool replace) +TSymbol * CLASS::addVariable(std::string symname, std::string val, variable_t &vars, bool replace) { TSymbol *res = NULL; TSymbol *fnd = NULL; @@ -1194,7 +1203,7 @@ TSymbol * CLASS::addVariable(std::string symname, std::string val, bool replace) } //printf("addvariable\n"); - fnd = findVariable(sym); + fnd = findVariable(sym, vars); if ((fnd != NULL) && (!replace)) { @@ -1221,18 +1230,18 @@ TSymbol * CLASS::addVariable(std::string symname, std::string val, bool replace) //printf("addvariable: %s %s\n", s.name.c_str(), s.text.c_str()); std::pair p(sym, s); - variables.insert(p); - res = findVariable(sym); + vars.insert(p); + res = findVariable(sym, vars); return (res); } -TSymbol * CLASS::findVariable(std::string symname) +TSymbol * CLASS::findVariable(std::string symname, variable_t &vars) { TSymbol *res = NULL; //printf("finding: %s\n",symname.c_str()); - auto itr = variables.find(symname); - if (itr != variables.end()) + auto itr = vars.find(symname); + if (itr != vars.end()) { //printf("Found: %s 0x%08X\n",itr->second.name.c_str(),itr->second.value); res = &itr->second; @@ -1242,13 +1251,13 @@ TSymbol * CLASS::findVariable(std::string symname) return (res); } -void CLASS::showVariables(void) +void CLASS::showVariables(variable_t &vars) { if (variables.size() > 0) { printf("\nVariables:\n"); - for (auto itr = variables.begin(); itr != variables.end(); ++itr) + for (auto itr = vars.begin(); itr != vars.end(); ++itr) { printf("%-16s %s\n", itr->first.c_str(), itr->second.var_text.c_str()); } @@ -1309,6 +1318,44 @@ void CLASS::showSymbolTable(bool alpha) } } +// 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; + + 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)); + } + + 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"); + } + } +} + int CLASS::callOpCode(std::string op, MerlinLine &line) { int res = -1; @@ -1585,6 +1632,10 @@ void CLASS::initpass(void) { macrostack.pop(); } + while (!expand_macrostack.empty()) + { + expand_macrostack.pop(); + } while (!LUPstack.empty()) { LUPstack.pop(); @@ -1602,6 +1653,7 @@ void CLASS::initpass(void) PCstack.pop(); } currentmacro.clear(); + expand_macro.clear(); curLUP.clear(); curDO.clear(); } @@ -1655,8 +1707,10 @@ void CLASS::complete(void) { showSymbolTable(true); showSymbolTable(false); - showVariables(); + showVariables(variables); + showMacros(false); } + } int CLASS::evaluate(MerlinLine &line, std::string expr, int64_t &value) @@ -1903,7 +1957,7 @@ restart: off = mVec[0].offset; len = mVec[0].length; s = oper.substr(off, len); - sym = findVariable(s); + sym = findVariable(s, variables); if (sym != NULL) { //printf("match |%s|\n",sym->var_text.c_str()); @@ -1989,7 +2043,42 @@ void CLASS::process(void) l = lines.size(); while ((lineno < l) && (!passcomplete)) { - MerlinLine &line = 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) + { + ml = &lines[lineno]; + } + + MerlinLine &line = *ml; + + //printf("lineno=%u %s\n", lineno, line.wholetext.c_str()); line.eval_result = 0; line.lineno = lineno + 1; @@ -2017,7 +2106,7 @@ void CLASS::process(void) case ']': sprintf(buff, "$%X", PC.currentpc); ls = buff; - sym = addVariable(line.lable, ls, true); + sym = addVariable(line.lable, ls, variables, true); //if (sym == NULL) { dupsym = true; } break; @@ -2045,10 +2134,8 @@ void CLASS::process(void) } } std::string outop; - if (pass == 0) - { - line.printoperand = line.operand; - } + line.printoperand = line.operand; + x = substituteVariables(line, outop); if (x > 0) { @@ -2077,14 +2164,30 @@ void CLASS::process(void) x = 0; if (op.length() > 0) { - TMacro *mac=findMacro(op); - if (mac==NULL) + TMacro *mac = findMacro(op); + if (mac == NULL) { x = callOpCode(op, line); } else { - x=0; + 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.clear(); + // set the variables for the macro here SGQ + expand_macro.currentline = 0; + x = 0; } } @@ -2134,7 +2237,10 @@ void CLASS::process(void) { if ((line.pass0bytect != line.bytect) && (line.errorcode == 0)) { - line.setError(errBadByteCount); + if (expand_macrostack.size() == 0) // if macro expanding, you can't make this check + { + line.setError(errBadByteCount); + } } if (line.errorcode != 0) diff --git a/asm.h b/asm.h index 3a4003d..6565c8e 100644 --- a/asm.h +++ b/asm.h @@ -144,6 +144,7 @@ enum syn_MAX }; + class TOriginSection { // SGQ - if you do something unusual here, be aware of copy constructor @@ -190,6 +191,7 @@ class MerlinLine public: uint32_t syntax; + std::string wholetext; std::string lable; std::string printlable; std::string printoperand; @@ -345,16 +347,17 @@ public: } }; +typedef Poco::HashMap variable_t; class TMacro { public: std::string name; std::string lcname; - uint32_t currentline; - std::vector variables; + variable_t variables; std::vector lines; - int32_t start,end; + uint32_t start,end,currentline,len; + uint32_t sourceline; bool running; TMacro() @@ -367,9 +370,11 @@ public: lcname=""; variables.clear(); lines.clear(); + sourceline=0; currentline=0; - start = -1; - end=-1; + len=0; + start = 0; + end=0; running = false; } }; @@ -405,12 +410,13 @@ public: Poco::HashMap macros; Poco::HashMap opcodes; Poco::HashMap symbols; - Poco::HashMap variables; + variable_t variables; TOriginSection PC; TLUPstruct curLUP; TDOstruct curDO; TMacro currentmacro; + TMacro expand_macro; bool listing; uint8_t truncdata; // for the TR opcode @@ -419,6 +425,7 @@ public: std::stack DOstack; std::stack LSTstack; std::stack macrostack; + std::stack expand_macrostack; TPsuedoOp *psuedoops; @@ -440,13 +447,15 @@ public: TSymbol *findSymbol(std::string sym); TSymbol *addSymbol(std::string sym, uint32_t val, bool replace); - TSymbol *findVariable(std::string sym); - TSymbol *addVariable(std::string sym, std::string val, bool replace); + TSymbol *findVariable(std::string sym, variable_t &vars); + TSymbol *addVariable(std::string sym, std::string val, variable_t &vars,bool replace); void initpass(void); void showSymbolTable(bool alpha); - void showVariables(void); + void showMacros(bool alpha); + + void showVariables(variable_t &vars); int evaluate(MerlinLine &line, std::string expr, int64_t &value); int substituteVariables(MerlinLine & line, std::string &outop); diff --git a/opcodes.cpp b/opcodes.cpp index 8c22620..6909fb2 100644 --- a/opcodes.cpp +++ b/opcodes.cpp @@ -99,10 +99,10 @@ int CLASS::doEQU(MerlinLine &line, TSymbol &sym) char buff[32]; sprintf(buff, "$%08X", line.expr_value); std::string s1 = buff; - s = addVariable(line.lable, s1, true); + s = addVariable(line.lable, s1, variables,true); #else // do this if you want to do this more as a #define - s = addVariable(line.lable, line.operand, true); + s = addVariable(line.lable, line.operand, variables,true); #endif if (s != NULL) { diff --git a/psuedo.cpp b/psuedo.cpp index 0dd5f2f..e8d4a45 100644 --- a/psuedo.cpp +++ b/psuedo.cpp @@ -142,21 +142,21 @@ int CLASS::doMAC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) { if (a.currentmacro.running) { - err=errUnexpectedOp; + err = errUnexpectedOp; goto out; } - if (line.lable.length()==0) + if (line.lable.length() == 0) { - err=errBadLabel; + err = errBadLabel; goto out; } a.macrostack.push(a.currentmacro); a.currentmacro.clear(); - a.currentmacro.name=line.lable; - a.currentmacro.lcname=Poco::toLower(line.lable); - a.currentmacro.start=line.lineno+1; - a.currentmacro.running=true; + a.currentmacro.name = line.lable; + a.currentmacro.lcname = Poco::toLower(line.lable); + a.currentmacro.start = line.lineno; + a.currentmacro.running = true; if (a.pass == 0) { } @@ -169,9 +169,14 @@ int CLASS::doMAC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) { if (a.macrostack.size() > 0) { - a.currentmacro.end=line.lineno; - a.currentmacro.running=false; - + a.currentmacro.end = line.lineno - 1; + a.currentmacro.len = 0; + if (a.currentmacro.end >= a.currentmacro.start) + { + a.currentmacro.len = a.currentmacro.end - a.currentmacro.start; + } + a.currentmacro.running = false; + std::pair p(a.currentmacro.name, a.currentmacro); a.macros.insert(p); From 21da3e7536582a95a4be0f00e3931579dac41bcf Mon Sep 17 00:00:00 2001 From: marketideas Date: Thu, 21 Nov 2019 08:47:03 -0800 Subject: [PATCH 21/26] more macros and vars --- asm.cpp | 80 ++++++++++++++++++------------ asm.h | 40 +++++++++------ opcodes.cpp | 1 + psuedo.cpp | 138 ++++++++++++++++++++++++++++++++-------------------- 4 files changed, 161 insertions(+), 98 deletions(-) diff --git a/asm.cpp b/asm.cpp index 2bbe76f..cfce539 100644 --- a/asm.cpp +++ b/asm.cpp @@ -1191,7 +1191,7 @@ out: return (res); } -TSymbol * CLASS::addVariable(std::string symname, std::string val, variable_t &vars, bool replace) +TSymbol * CLASS::addVariable(std::string symname, std::string val, TVariable &vars, bool replace) { TSymbol *res = NULL; TSymbol *fnd = NULL; @@ -1230,18 +1230,27 @@ TSymbol * CLASS::addVariable(std::string symname, std::string val, variable_t &v //printf("addvariable: %s %s\n", s.name.c_str(), s.text.c_str()); std::pair p(sym, s); - vars.insert(p); + vars.vars.insert(p); res = findVariable(sym, vars); return (res); } -TSymbol * CLASS::findVariable(std::string symname, variable_t &vars) +TSymbol * CLASS::findVariable(std::string symname, TVariable &vars) { TSymbol *res = NULL; + 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.find(symname); - if (itr != vars.end()) + 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; @@ -1251,13 +1260,13 @@ TSymbol * CLASS::findVariable(std::string symname, variable_t &vars) return (res); } -void CLASS::showVariables(variable_t &vars) +void CLASS::showVariables(TVariable &vars) { - if (variables.size() > 0) + if (vars.vars.size() > 0) { printf("\nVariables:\n"); - for (auto itr = vars.begin(); itr != vars.end(); ++itr) + 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()); } @@ -1626,7 +1635,7 @@ void CLASS::initpass(void) dumstartaddr = 0; dumstart = 0; truncdata = 0; - variables.clear(); // clear the variables for each pass + variables.vars.clear(); // clear the variables for each pass while (!macrostack.empty()) { @@ -2164,30 +2173,41 @@ void CLASS::process(void) x = 0; if (op.length() > 0) { - TMacro *mac = findMacro(op); - if (mac == NULL) + TMacro *mac = NULL; + if (macrostack.size() == 0) { - x = callOpCode(op, line); - } - else - { - 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++) + mac = findMacro(op); + if (mac == NULL) { - //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); + + if (op == ">>>") // specal merlin way of calling a macro + { + mac = findMacro(operand); + } + else + { + 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.currentline = 0; } - expand_macro.running = true; - expand_macro.sourceline = lineno; - expand_macro.variables.clear(); - // set the variables for the macro here SGQ - expand_macro.currentline = 0; - x = 0; } } diff --git a/asm.h b/asm.h index 6565c8e..338d5c2 100644 --- a/asm.h +++ b/asm.h @@ -347,16 +347,28 @@ public: } }; -typedef Poco::HashMap variable_t; +//typedef Poco::HashMap variable_t; + +class TVariable +{ +public: + uint32_t id; + Poco::HashMap vars; + TVariable() + { + // SGQ - must fix this so it is guaranteed unique for each one + id=rand(); + } +}; class TMacro { public: std::string name; std::string lcname; - variable_t variables; + TVariable variables; std::vector lines; - uint32_t start,end,currentline,len; + uint32_t start, end, currentline, len; uint32_t sourceline; bool running; @@ -366,15 +378,15 @@ public: } void clear(void) { - name=""; - lcname=""; - variables.clear(); + name = ""; + lcname = ""; + variables.vars.clear(); lines.clear(); - sourceline=0; - currentline=0; - len=0; + sourceline = 0; + currentline = 0; + len = 0; start = 0; - end=0; + end = 0; running = false; } }; @@ -410,7 +422,7 @@ public: Poco::HashMap macros; Poco::HashMap opcodes; Poco::HashMap symbols; - variable_t variables; + TVariable variables; TOriginSection PC; TLUPstruct curLUP; @@ -447,15 +459,15 @@ public: TSymbol *findSymbol(std::string sym); TSymbol *addSymbol(std::string sym, uint32_t val, bool replace); - TSymbol *findVariable(std::string sym, variable_t &vars); - TSymbol *addVariable(std::string sym, std::string val, variable_t &vars,bool replace); + TSymbol *findVariable(std::string sym, TVariable &vars); + TSymbol *addVariable(std::string sym, std::string val, TVariable &vars, bool replace); void initpass(void); void showSymbolTable(bool alpha); void showMacros(bool alpha); - void showVariables(variable_t &vars); + void showVariables(TVariable &vars); int evaluate(MerlinLine &line, std::string expr, int64_t &value); int substituteVariables(MerlinLine & line, std::string &outop); diff --git a/opcodes.cpp b/opcodes.cpp index 6909fb2..e77cea7 100644 --- a/opcodes.cpp +++ b/opcodes.cpp @@ -888,6 +888,7 @@ void CLASS::insertOpcodes(void) pushopcode("MAC", P_MAC, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("EOM", P_MAC, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("<<<", P_MAC, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); + pushopcode(">>>", P_MAC, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("ADC", 0x03, OP_STD | OP_A, OPHANDLER(&CLASS::doBase6502)); diff --git a/psuedo.cpp b/psuedo.cpp index e8d4a45..d8eb9e5 100644 --- a/psuedo.cpp +++ b/psuedo.cpp @@ -35,6 +35,14 @@ int CLASS::doDO(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) { UNUSED(opinfo); + + if (a.macrostack.size()>0) + { + // if defining a macro, do nothing with this + return(0); + } + + TEvaluator eval(a); int64_t eval_value = 0; @@ -165,6 +173,10 @@ int CLASS::doMAC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) // don't need to do anything on pass > 0 } } + else if (op==">>>") + { + // don't do anything here, let the macro call handler stuff do ths (asm.cpp) + } else // it is EOM or <<< { if (a.macrostack.size() > 0) @@ -211,78 +223,96 @@ int CLASS::doLUP(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) std::string op = Poco::toUpper(line.opcode); - if (op == "LUP") + if (a.macrostack.size() == 0) // if defining a macro (size>0), don't process here { - line.flags |= FLAG_NOLINEPRINT; - len = line.lineno - 1; // MerlinLine line numbers are +1 from actual array idx - if (len >= 0) + if (op == "LUP") { - - shift = 0; - eval_value = 0; - int x = eval.evaluate(line.operand_expr, eval_value, shift); - - a.LUPstack.push(a.curLUP); - - a.curLUP.lupoffset = len; - a.curLUP.lupct = eval_value & 0xFFFF; // evaluate here - a.curLUP.luprunning++; - - if ((x < 0) || (eval_value <= 0) || (eval_value > 0x8000)) + line.flags |= FLAG_NOLINEPRINT; + len = line.lineno - 1; // MerlinLine line numbers are +1 from actual array idx + if (len >= 0) { - // merlin just ignores LUP if the value is out of range - a.curLUP.lupct = 0; - a.curLUP.lupskip = true; - } - } - else - { - err = errUnexpectedOp; - } - } - if (op == "--^") - { - line.flags |= FLAG_NOLINEPRINT; + shift = 0; + eval_value = 0; + int x = eval.evaluate(line.operand_expr, eval_value, shift); - if (a.curLUP.luprunning > 0) - { - lidx = line.lineno - 1; - len = lidx - a.curLUP.lupoffset - 1; + a.LUPstack.push(a.curLUP); - if (a.curLUP.lupct > 0) - { - a.curLUP.lupct--; - if (a.curLUP.lupct != 0) + if (a.expand_macrostack.size() > 0) { - a.lineno = a.curLUP.lupoffset; - goto out; + a.curLUP.lupoffset = a.expand_macro.currentline; } - } - // kind of a silent error here, just make sure we reinitialize - a.curLUP.luprunning = 0; - a.curLUP.lupct = 0; - a.curLUP.lupskip = false; + else + { + a.curLUP.lupoffset = len; + } + a.curLUP.lupct = eval_value & 0xFFFF; // evaluate here + a.curLUP.luprunning++; - //printf("start=%d end=%d len=%d\n", a.curLUP.lupoffset, lidx, len); - if (a.LUPstack.size() > 0) - { - a.curLUP = a.LUPstack.top(); - a.LUPstack.pop(); + if ((x < 0) || (eval_value <= 0) || (eval_value > 0x8000)) + { + // merlin just ignores LUP if the value is out of range + a.curLUP.lupct = 0; + a.curLUP.lupskip = true; + } } else { err = errUnexpectedOp; } } - else + + if (op == "--^") { - a.curLUP.lupskip = false; - // SGQ - found a '--^' without a LUP, should we just ignore? - //err = errUnexpectedOp; + line.flags |= FLAG_NOLINEPRINT; + + if (a.curLUP.luprunning > 0) + { + + + lidx = line.lineno - 1; + len = lidx - a.curLUP.lupoffset - 1; + + if (a.curLUP.lupct > 0) + { + a.curLUP.lupct--; + if (a.curLUP.lupct != 0) + { + if (a.expand_macrostack.size() > 0) + { + a.expand_macro.currentline=a.curLUP.lupoffset; + } + else + { + a.lineno = a.curLUP.lupoffset; + } + goto out; + } + } + // kind of a silent error here, just make sure we reinitialize + a.curLUP.luprunning = 0; + a.curLUP.lupct = 0; + a.curLUP.lupskip = false; + + //printf("start=%d end=%d len=%d\n", a.curLUP.lupoffset, lidx, len); + if (a.LUPstack.size() > 0) + { + a.curLUP = a.LUPstack.top(); + a.LUPstack.pop(); + } + else + { + err = errUnexpectedOp; + } + } + else + { + a.curLUP.lupskip = false; + // SGQ - found a '--^' without a LUP, should we just ignore? + //err = errUnexpectedOp; + } } } - out: if (err > 0) { From d86bd06e8e2c8f83d27c34f57b3fcec26a37f018 Mon Sep 17 00:00:00 2001 From: marketideas Date: Thu, 21 Nov 2019 18:14:30 -0800 Subject: [PATCH 22/26] macros with vars now working --- asm.cpp | 115 +++++++++++++++++++++++++++++----------- psuedo.cpp | 151 +++++++++++++++++++++++++---------------------------- 2 files changed, 154 insertions(+), 112 deletions(-) diff --git a/asm.cpp b/asm.cpp index cfce539..85cc331 100644 --- a/asm.cpp +++ b/asm.cpp @@ -1371,6 +1371,17 @@ int CLASS::callOpCode(std::string op, MerlinLine &line) char c; std::string s; +// 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 + std::string upop = Poco::toUpper(op); + if (!((upop == "MAC") || (upop == "EOM") || (upop == "<<<"))) + { + return 0; + } + } + if (op.length() == 4) // check for 4 digit 'L' opcodes { c = op[3] & 0x7F; @@ -1966,7 +1977,16 @@ restart: off = mVec[0].offset; len = mVec[0].length; s = oper.substr(off, len); - sym = findVariable(s, variables); + + 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()); @@ -2001,7 +2021,7 @@ restart: done = true; } } - //printf("inoper=|%s| outoper=|%s|\n",operin.c_str(),oper.c_str()); +//printf("inoper=|%s| outoper=|%s|\n",operin.c_str(),oper.c_str()); if (ct > 0) { outop = oper; @@ -2148,6 +2168,7 @@ void CLASS::process(void) x = substituteVariables(line, outop); if (x > 0) { + line.printoperand = outop; line.operand = outop; } x = parseOperand(line); @@ -2174,41 +2195,73 @@ void CLASS::process(void) if (op.length() > 0) { TMacro *mac = NULL; - if (macrostack.size() == 0) + bool inoperand = false; + mac = findMacro(op); + if (mac == NULL) { - mac = findMacro(op); - if (mac == NULL) + if (op == ">>>") // specal merlin way of calling a macro { - - 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) { - mac = findMacro(operand); + s=tok[0]; } - else - { - 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.currentline = 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 + + 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; + } + //} } if ((x > 0) && (codeSkipped())) // has a psuedo-op turned off code generation? (LUP, IF, etc) diff --git a/psuedo.cpp b/psuedo.cpp index d8eb9e5..9f17d6d 100644 --- a/psuedo.cpp +++ b/psuedo.cpp @@ -35,14 +35,6 @@ int CLASS::doDO(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) { UNUSED(opinfo); - - if (a.macrostack.size()>0) - { - // if defining a macro, do nothing with this - return(0); - } - - TEvaluator eval(a); int64_t eval_value = 0; @@ -173,7 +165,7 @@ int CLASS::doMAC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) // don't need to do anything on pass > 0 } } - else if (op==">>>") + else if (op == ">>>") { // don't do anything here, let the macro call handler stuff do ths (asm.cpp) } @@ -223,94 +215,91 @@ int CLASS::doLUP(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) std::string op = Poco::toUpper(line.opcode); - if (a.macrostack.size() == 0) // if defining a macro (size>0), don't process here + if (op == "LUP") { - if (op == "LUP") + line.flags |= FLAG_NOLINEPRINT; + len = line.lineno - 1; // MerlinLine line numbers are +1 from actual array idx + if (len >= 0) { - line.flags |= FLAG_NOLINEPRINT; - len = line.lineno - 1; // MerlinLine line numbers are +1 from actual array idx - if (len >= 0) + + shift = 0; + eval_value = 0; + int x = eval.evaluate(line.operand_expr, eval_value, shift); + + a.LUPstack.push(a.curLUP); + + if (a.expand_macrostack.size() > 0) { + a.curLUP.lupoffset = a.expand_macro.currentline; + } + else + { + a.curLUP.lupoffset = len; + } + a.curLUP.lupct = eval_value & 0xFFFF; // evaluate here + a.curLUP.luprunning++; - shift = 0; - eval_value = 0; - int x = eval.evaluate(line.operand_expr, eval_value, shift); + if ((x < 0) || (eval_value <= 0) || (eval_value > 0x8000)) + { + // merlin just ignores LUP if the value is out of range + a.curLUP.lupct = 0; + a.curLUP.lupskip = true; + } + } + else + { + err = errUnexpectedOp; + } + } - a.LUPstack.push(a.curLUP); + if (op == "--^") + { + line.flags |= FLAG_NOLINEPRINT; - if (a.expand_macrostack.size() > 0) + if (a.curLUP.luprunning > 0) + { + + + lidx = line.lineno - 1; + len = lidx - a.curLUP.lupoffset - 1; + + if (a.curLUP.lupct > 0) + { + a.curLUP.lupct--; + if (a.curLUP.lupct != 0) { - a.curLUP.lupoffset = a.expand_macro.currentline; + if (a.expand_macrostack.size() > 0) + { + a.expand_macro.currentline = a.curLUP.lupoffset; + } + else + { + a.lineno = a.curLUP.lupoffset; + } + goto out; } - else - { - a.curLUP.lupoffset = len; - } - a.curLUP.lupct = eval_value & 0xFFFF; // evaluate here - a.curLUP.luprunning++; + } + // kind of a silent error here, just make sure we reinitialize + a.curLUP.luprunning = 0; + a.curLUP.lupct = 0; + a.curLUP.lupskip = false; - if ((x < 0) || (eval_value <= 0) || (eval_value > 0x8000)) - { - // merlin just ignores LUP if the value is out of range - a.curLUP.lupct = 0; - a.curLUP.lupskip = true; - } + //printf("start=%d end=%d len=%d\n", a.curLUP.lupoffset, lidx, len); + if (a.LUPstack.size() > 0) + { + a.curLUP = a.LUPstack.top(); + a.LUPstack.pop(); } else { err = errUnexpectedOp; } } - - if (op == "--^") + else { - line.flags |= FLAG_NOLINEPRINT; - - if (a.curLUP.luprunning > 0) - { - - - lidx = line.lineno - 1; - len = lidx - a.curLUP.lupoffset - 1; - - if (a.curLUP.lupct > 0) - { - a.curLUP.lupct--; - if (a.curLUP.lupct != 0) - { - if (a.expand_macrostack.size() > 0) - { - a.expand_macro.currentline=a.curLUP.lupoffset; - } - else - { - a.lineno = a.curLUP.lupoffset; - } - goto out; - } - } - // kind of a silent error here, just make sure we reinitialize - a.curLUP.luprunning = 0; - a.curLUP.lupct = 0; - a.curLUP.lupskip = false; - - //printf("start=%d end=%d len=%d\n", a.curLUP.lupoffset, lidx, len); - if (a.LUPstack.size() > 0) - { - a.curLUP = a.LUPstack.top(); - a.LUPstack.pop(); - } - else - { - err = errUnexpectedOp; - } - } - else - { - a.curLUP.lupskip = false; - // SGQ - found a '--^' without a LUP, should we just ignore? - //err = errUnexpectedOp; - } + a.curLUP.lupskip = false; + // SGQ - found a '--^' without a LUP, should we just ignore? + //err = errUnexpectedOp; } } out: From b154efff36e6ddcd6483a7367208ed1b2052e973 Mon Sep 17 00:00:00 2001 From: marketideas Date: Thu, 21 Nov 2019 19:20:59 -0800 Subject: [PATCH 23/26] fixes for nested DO/IF/ELSE/FIN --- asm.cpp | 153 +++++++++++++++++++++++++++++++++-------------------- asm.h | 2 + eval.cpp | 31 +++++++---- eval.h | 1 + psuedo.cpp | 1 + 5 files changed, 120 insertions(+), 68 deletions(-) diff --git a/asm.cpp b/asm.cpp index 85cc331..1eb5ac7 100644 --- a/asm.cpp +++ b/asm.cpp @@ -2030,13 +2030,38 @@ restart: return (res); } +bool CLASS::doOFF(void) +{ + bool res=curDO.doskip; + std::stack tmpstack; + TDOstruct doitem; + + uint32_t ct=DOstack.size(); + if (ct>0) + { + tmpstack=DOstack; + } + while(ct>0) + { + doitem=tmpstack.top(); + tmpstack.pop(); + if (doitem.doskip) + { + res=true; + } + ct--; + } + + return(res); +} + // this function determines if code generation is turned off (IF,DO,LUP,MAC, etc bool CLASS::codeSkipped(void) { bool res = false; res = (curLUP.lupskip) ? true : res; - res = (curDO.doskip) ? true : res; + res = doOFF() ? true : res; res = currentmacro.running ? true : res; //printf("codeskip: %d\n",res); @@ -2062,7 +2087,7 @@ void CLASS::process(void) char c; char buff[256]; MerlinLine errLine; - std::string op, operand, ls; + std::string op, realop, operand, ls; pass = 0; while (pass < 2) @@ -2116,6 +2141,7 @@ void CLASS::process(void) //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; @@ -2194,74 +2220,85 @@ void CLASS::process(void) x = 0; if (op.length() > 0) { - TMacro *mac = NULL; - bool inoperand = false; - mac = findMacro(op); - if (mac == NULL) + bool skipop = false; + if (doOFF()) { - if (op == ">>>") // specal merlin way of calling a macro + skipop = true; + if ((op == "fin") || (op == "else") || (op == "do") || (op == "if")) { - 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; + skipop = false; } } - if (mac == NULL) + if (!skipop) { - 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++) + TMacro *mac = NULL; + bool inoperand = false; + mac = findMacro(realop); + if (mac == NULL) { - //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) + if (op == ">>>") // specal merlin way of calling a macro { - parms = tok[1]; + 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; } } - 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) + if (mac == NULL) { - //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 = 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 + + 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; } - x = 0; - expand_macro.currentline = 0; } - //} } if ((x > 0) && (codeSkipped())) // has a psuedo-op turned off code generation? (LUP, IF, etc) diff --git a/asm.h b/asm.h index 338d5c2..9f47d2e 100644 --- a/asm.h +++ b/asm.h @@ -473,6 +473,8 @@ public: int substituteVariables(MerlinLine & line, std::string &outop); bool codeSkipped(void); + bool doOFF(void); + int parseOperand(MerlinLine &line); int getAddrMode(MerlinLine &line); diff --git a/eval.cpp b/eval.cpp index 713ce9d..7dce58b 100644 --- a/eval.cpp +++ b/eval.cpp @@ -15,6 +15,7 @@ std::ostream& operator<<(std::ostream& os, const Token& token) CLASS::CLASS(T65816Asm &_asm) : assembler(_asm) { + allowMX = false; } CLASS::~CLASS() @@ -232,20 +233,30 @@ std::deque CLASS::shuntingYard(const std::deque& tokens) } else { - sym = assembler.findSymbol(token.str); - //printf("symbol find |%s| %p\n",token.str.c_str(),sym); - - if (sym != NULL) + std::string tok = Poco::toUpper(token.str); + if ((tok == "MX") && (allowMX)) { - sym->used = true; - sprintf(buff, "$%X", sym->value); - token.str = buff; + //printf("MX EVAL\n"); + sprintf(buff,"$%02X",assembler.mx&0x03); + token.str=buff;; } else { - setError(Token::unknownSymbolErr); - badsymbol = token.str; - token.str = "0"; + sym = assembler.findSymbol(token.str); + //printf("symbol find |%s| %p\n",token.str.c_str(),sym); + + if (sym != NULL) + { + sym->used = true; + sprintf(buff, "$%X", sym->value); + token.str = buff; + } + else + { + setError(Token::unknownSymbolErr); + badsymbol = token.str; + token.str = "0"; + } } } queue.push_back(token); diff --git a/eval.h b/eval.h index 73b6c54..f0ed9a2 100644 --- a/eval.h +++ b/eval.h @@ -68,6 +68,7 @@ protected: public: CLASS(T65816Asm &_asm); ~CLASS(); + bool allowMX; std::string badsymbol; std::deque shuntingYard(const std::deque& tokens); std::deque exprToTokens(const std::string& expr); diff --git a/psuedo.cpp b/psuedo.cpp index 9f17d6d..ba90566 100644 --- a/psuedo.cpp +++ b/psuedo.cpp @@ -36,6 +36,7 @@ int CLASS::doDO(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) UNUSED(opinfo); TEvaluator eval(a); + eval.allowMX=true; // allow the built in MX symbol int64_t eval_value = 0; uint8_t shift; From 279de5caa5d62e8af9d0ca4cb354f4822a2a63ce Mon Sep 17 00:00:00 2001 From: marketideas Date: Thu, 21 Nov 2019 21:00:26 -0800 Subject: [PATCH 24/26] macro on last line bug fixed, nested macro defs --- asm.cpp | 42 ++++++++++++++++++++++++++---------------- psuedo.cpp | 10 +++++++--- 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/asm.cpp b/asm.cpp index 1eb5ac7..3bbec9f 100644 --- a/asm.cpp +++ b/asm.cpp @@ -1371,12 +1371,13 @@ int CLASS::callOpCode(std::string op, MerlinLine &line) char c; std::string s; + // '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 - std::string upop = Poco::toUpper(op); - if (!((upop == "MAC") || (upop == "EOM") || (upop == "<<<"))) + if (!((op == "mac") || (op == "eom") || (op == "<<<"))) { return 0; } @@ -1728,7 +1729,7 @@ void CLASS::complete(void) showSymbolTable(true); showSymbolTable(false); showVariables(variables); - showMacros(false); + showMacros(true); } } @@ -2032,27 +2033,27 @@ restart: bool CLASS::doOFF(void) { - bool res=curDO.doskip; + bool res = curDO.doskip; std::stack tmpstack; TDOstruct doitem; - uint32_t ct=DOstack.size(); - if (ct>0) + uint32_t ct = DOstack.size(); + if (ct > 0) { - tmpstack=DOstack; + tmpstack = DOstack; } - while(ct>0) + while (ct > 0) { - doitem=tmpstack.top(); + doitem = tmpstack.top(); tmpstack.pop(); if (doitem.doskip) { - res=true; + res = true; } ct--; } - - return(res); + //printf("DOOFF: %d\n",res); + return (res); } // this function determines if code generation is turned off (IF,DO,LUP,MAC, etc @@ -2095,7 +2096,8 @@ void CLASS::process(void) initpass(); l = lines.size(); - while ((lineno < l) && (!passcomplete)) + bool passdone = false; + while ((!passdone) && (!passcomplete)) { MerlinLine *ml = NULL; @@ -2127,7 +2129,15 @@ void CLASS::process(void) } if (srcline) { - ml = &lines[lineno]; + if (lineno >= l) + { + passdone = true; + goto passout; + } + else + { + ml = &lines[lineno]; + } } MerlinLine &line = *ml; @@ -2150,7 +2160,7 @@ void CLASS::process(void) line.syntax = syntax; line.merlinerrors = merlinerrors; - if ((line.lable != "")) + if ((line.lable != "") && (op != "mac")) { std::string lable = Poco::trim(line.lable); TSymbol *sym = NULL; @@ -2365,7 +2375,7 @@ void CLASS::process(void) } lineno++; } - +passout: // end of file reached here, do some final checks #if 0 diff --git a/psuedo.cpp b/psuedo.cpp index ba90566..51c34d4 100644 --- a/psuedo.cpp +++ b/psuedo.cpp @@ -141,9 +141,8 @@ int CLASS::doMAC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) std::string op = Poco::toUpper(line.opcode); if (op == "MAC") { - if (a.currentmacro.running) + if (a.expand_macrostack.size()>0) { - err = errUnexpectedOp; goto out; } if (line.lable.length() == 0) @@ -165,6 +164,7 @@ int CLASS::doMAC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) { // don't need to do anything on pass > 0 } + //printf("macro stack size=%zu\n",a.macrostack.size()); } else if (op == ">>>") { @@ -172,27 +172,31 @@ int CLASS::doMAC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) } else // it is EOM or <<< { - if (a.macrostack.size() > 0) + while (a.macrostack.size() > 0) { a.currentmacro.end = line.lineno - 1; a.currentmacro.len = 0; if (a.currentmacro.end >= a.currentmacro.start) { a.currentmacro.len = a.currentmacro.end - a.currentmacro.start; + //printf("macro len=%d\n",a.currentmacro.len); } a.currentmacro.running = false; std::pair p(a.currentmacro.name, a.currentmacro); + //printf("macro insert %s\n",a.currentmacro.name.c_str()); a.macros.insert(p); a.currentmacro = a.macrostack.top(); a.macrostack.pop(); } +#if 0 else { err = errUnexpectedOp; goto out; } +#endif } out: if (err) From 476a46d7dbdba9dc886185b8d562facd8c255584 Mon Sep 17 00:00:00 2001 From: marketideas Date: Fri, 22 Nov 2019 09:33:24 -0800 Subject: [PATCH 25/26] test --- asm.cpp | 37 +++++++++++++++++++++++++------------ opcodes.cpp | 1 + psuedo.cpp | 24 ++++++++++++++++++++++-- psuedo.h | 1 + 4 files changed, 49 insertions(+), 14 deletions(-) diff --git a/asm.cpp b/asm.cpp index 3bbec9f..1045272 100644 --- a/asm.cpp +++ b/asm.cpp @@ -1239,6 +1239,11 @@ TSymbol * CLASS::findVariable(std::string symname, TVariable &vars) { TSymbol *res = NULL; + if (!casesen) + { + symname = Poco::toUpper(symname); + } + if ((expand_macrostack.size() > 0) && (vars.id != expand_macro.variables.id)) { res = findVariable(symname, expand_macro.variables); @@ -1978,7 +1983,7 @@ restart: off = mVec[0].offset; len = mVec[0].length; s = oper.substr(off, len); - + slen = s.length(); sym = NULL; if (expand_macrostack.size() > 0) { @@ -1995,6 +2000,7 @@ restart: if (sym->var_text != "") { oper = oper.replace(off, len, sym->var_text); + slen = oper.length(); ct++; if (pass > 0) { @@ -2201,7 +2207,11 @@ void CLASS::process(void) std::string outop; line.printoperand = line.operand; - x = substituteVariables(line, outop); + x = 0; + if (macrostack.size() == 0) + { + x = substituteVariables(line, outop); + } if (x > 0) { line.printoperand = outop; @@ -2243,20 +2253,23 @@ void CLASS::process(void) { TMacro *mac = NULL; bool inoperand = false; - mac = findMacro(realop); - if (mac == NULL) + if (macrostack.size() == 0) { - if (op == ">>>") // specal merlin way of calling a macro + mac = findMacro(realop); + if (mac == NULL) { - Poco::StringTokenizer tok(operand, ", ", Poco::StringTokenizer::TOK_TRIM | - Poco::StringTokenizer::TOK_IGNORE_EMPTY); - std::string s = ""; - if (tok.count() > 0) + if (op == ">>>") // specal merlin way of calling a macro { - s = tok[0]; + 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; } - mac = findMacro(s); - inoperand = true; } } if (mac == NULL) diff --git a/opcodes.cpp b/opcodes.cpp index e77cea7..3ec3c6a 100644 --- a/opcodes.cpp +++ b/opcodes.cpp @@ -846,6 +846,7 @@ void CLASS::insertOpcodes(void) pushopcode("DUM", P_DUM, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("DEND", P_DEND, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("AST", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); + pushopcode("CAS", P_CAS, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("CYC", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("DAT", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("EXP", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); diff --git a/psuedo.cpp b/psuedo.cpp index 51c34d4..ce1418e 100644 --- a/psuedo.cpp +++ b/psuedo.cpp @@ -36,7 +36,7 @@ int CLASS::doDO(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) UNUSED(opinfo); TEvaluator eval(a); - eval.allowMX=true; // allow the built in MX symbol + eval.allowMX = true; // allow the built in MX symbol int64_t eval_value = 0; uint8_t shift; @@ -141,8 +141,9 @@ int CLASS::doMAC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) std::string op = Poco::toUpper(line.opcode); if (op == "MAC") { - if (a.expand_macrostack.size()>0) + if (a.expand_macrostack.size() > 0) { + line.flags |= FLAG_NOLINEPRINT; goto out; } if (line.lable.length() == 0) @@ -157,6 +158,12 @@ int CLASS::doMAC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) a.currentmacro.lcname = Poco::toLower(line.lable); a.currentmacro.start = line.lineno; a.currentmacro.running = true; + + if (!a.casesen) + { + a.currentmacro.name = Poco::toUpper(a.currentmacro.name); + } + if (a.pass == 0) { } @@ -899,6 +906,7 @@ int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) int CLASS::ProcessOpcode(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) { int res = 0; + std::string s; switch (opinfo.opcode) { @@ -949,6 +957,18 @@ int CLASS::ProcessOpcode(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) case P_SAV: a.savepath = a.processFilename(line.operand, Poco::Path::current(), 0); break; + case P_CAS: + s = Poco::toUpper(line.operand); + if (s == "SE") + { + a.casesen = true; + } + if (s=="IN") + { + a.casesen=false; + } + res = 0; + break; case P_MAC: res = doMAC(a, line, opinfo); break; diff --git a/psuedo.h b/psuedo.h index bf86c28..3f27476 100644 --- a/psuedo.h +++ b/psuedo.h @@ -21,6 +21,7 @@ enum P_ASC, P_ERR, P_MAC, + P_CAS, P_MAX }; From aa5069780cc77c466cdb215acdc562f6cbed4cc6 Mon Sep 17 00:00:00 2001 From: Lane Roathe Date: Tue, 3 Dec 2019 09:44:50 -0700 Subject: [PATCH 26/26] Fix some type conversion warnings --- asm.cpp | 20 ++++++++++---------- eval.cpp | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/asm.cpp b/asm.cpp index 1045272..6dc0de5 100644 --- a/asm.cpp +++ b/asm.cpp @@ -343,7 +343,7 @@ std::string commentEx = "^(\\s*)((;|\\/{2}))+(.*)"; void CLASS::set(std::string line) { int state = 0; - int l = line.length(); + int l = (int)line.length(); int i = 0; int x; char c, delim; @@ -491,7 +491,7 @@ void CLASS::set(std::string line) //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 = operand.length(); + i = (int)operand.length(); restofline = restofline.substr(i, restofline.length()); comment = Poco::trim(restofline); match = true; @@ -510,7 +510,7 @@ void CLASS::set(std::string line) } } printlable = lable; - x = lable.length(); + x = (int)lable.length(); if (x > 1) { // M32 syntax allows a colon after lable, and it is not part of the lable @@ -941,7 +941,7 @@ int CLASS::doline(int lineno, std::string line) void CLASS::process(void) { - uint32_t ct = lines.size(); + uint32_t ct = (uint32_t)lines.size(); uint32_t len, t, pos; @@ -1698,7 +1698,7 @@ void CLASS::complete(void) std::ofstream f(savepath); uint32_t lineno = 0; - uint32_t l = lines.size(); + uint32_t l = (uint32_t)lines.size(); while (lineno < l) { MerlinLine &line = lines.at(lineno++); @@ -1976,12 +1976,12 @@ restart: offset = slen; } - x = mVec.size(); + x = (int)mVec.size(); if (x > 0) { res = 0; - off = mVec[0].offset; - len = mVec[0].length; + off = (uint32_t)mVec[0].offset; + len = (uint32_t)mVec[0].length; s = oper.substr(off, len); slen = s.length(); sym = NULL; @@ -2043,7 +2043,7 @@ bool CLASS::doOFF(void) std::stack tmpstack; TDOstruct doitem; - uint32_t ct = DOstack.size(); + uint32_t ct = (uint32_t)DOstack.size(); if (ct > 0) { tmpstack = DOstack; @@ -2101,7 +2101,7 @@ void CLASS::process(void) { initpass(); - l = lines.size(); + l = (uint32_t)lines.size(); bool passdone = false; while ((!passdone) && (!passcomplete)) { diff --git a/eval.cpp b/eval.cpp index 7dce58b..086e379 100644 --- a/eval.cpp +++ b/eval.cpp @@ -391,7 +391,7 @@ int CLASS::parseAscii(std::string n, int64_t &val) bool high = false; uint8_t c; - uint32_t l = n.length(); + uint32_t l = (uint32_t)n.length(); for (uint32_t i = 0; i < l - 1; i++) { c = n[i]; @@ -442,7 +442,7 @@ int CLASS::parseNumber(std::string n, int64_t &val) //printf("parseNumber |%s|\n",n.c_str()); i = 0; - l = n.length(); + l = (uint32_t)n.length(); s = ""; for (i = 0; i < l; i++) {