diff --git a/README b/README index 0d6b762..9bb593a 100644 --- a/README +++ b/README @@ -46,3 +46,9 @@ make To test: ./qasm src/testfile.s + + +Some notes on compatibility: + +ERR does not support the ($300)-$4C style of checking, because we are not running on Apple // hardware, so there is no need to check for a USR vector having been setup in this manner. + diff --git a/asm.cpp b/asm.cpp index 3bbec9f..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; @@ -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); @@ -1693,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++); @@ -1971,14 +1976,14 @@ 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; 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) { @@ -2037,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; @@ -2095,7 +2101,7 @@ void CLASS::process(void) { initpass(); - l = lines.size(); + l = (uint32_t)lines.size(); bool passdone = false; while ((!passdone) && (!passcomplete)) { @@ -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/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++) { diff --git a/merlintests.sh b/merlintests.sh index ad97e50..dcf3146 100755 --- a/merlintests.sh +++ b/merlintests.sh @@ -20,17 +20,14 @@ for S in $SRC ; do S1=${S1/.S/} S1=${S1/.s/} - BASE=${S/.S/} - BASE=${BASE/.s/} cd ./testdata merlin32$X . $S 2>/dev/null >/dev/null #merlin32 . $S 2>/dev/null R=?$ - cd - >/dev/null - cp ./testdata/$S1 $OUTDIR/$S1.bin 2>/dev/null + cd .. >/dev/null + mv ./testdata/$S1 $OUTDIR/$S1.bin 2>/dev/null rm -f ./testdata/*.txt 2>/dev/null - rm -f ./testdata/$S1 2>/dev/null R=?$ done diff --git a/opcodes.cpp b/opcodes.cpp index e77cea7..26c5c03 100644 --- a/opcodes.cpp +++ b/opcodes.cpp @@ -829,7 +829,11 @@ void CLASS::insertOpcodes(void) { pushopcode("=", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doEQU)); pushopcode("EQU", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doEQU)); - pushopcode("EXT", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); + pushopcode("END", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doEND)); + pushopcode("MX", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doMX)); + pushopcode("XC", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doXC)); + + 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", P_SAV, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); @@ -840,12 +844,11 @@ void CLASS::insertOpcodes(void) pushopcode("PUT", P_PUT, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("USE", P_USE, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("VAR", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); - pushopcode("SAV", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("TYP", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); - pushopcode("END", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doEND)); 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)); @@ -870,7 +873,6 @@ void CLASS::insertOpcodes(void) 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", 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)); @@ -880,11 +882,9 @@ void CLASS::insertOpcodes(void) 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)); - pushopcode("MX", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doMX)); pushopcode("PAU", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); 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", P_MAC, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("EOM", P_MAC, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("<<<", P_MAC, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); @@ -898,7 +898,6 @@ void CLASS::insertOpcodes(void) pushopcode("BLT", 0x02, 0, OPHANDLER(&CLASS::doBRANCH)); pushopcode("BCS", 0x82, 0, OPHANDLER(&CLASS::doBRANCH)); pushopcode("BGE", 0x82, 0, OPHANDLER(&CLASS::doBRANCH)); - pushopcode("BEQ", 0x83, 0, OPHANDLER(&CLASS::doBRANCH)); pushopcode("BIT", 0x01, OP_C0, OPHANDLER(&CLASS::doBase6502)); pushopcode("BMI", 0x80, 0, OPHANDLER(&CLASS::doBRANCH)); diff --git a/psuedo.cpp b/psuedo.cpp index 51c34d4..36b512e 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) { } @@ -399,7 +406,7 @@ int CLASS::doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) line.setError(errBadEvaluation); } } - eval_value = doShift(eval_value, shift); + eval_value = (uint64_t)doShift((uint32_t)eval_value, shift); } outct += wordsize; @@ -477,7 +484,7 @@ int CLASS::doDS(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) line.setError(errBadOperand); goto out; } - eval_value = doShift(eval_value, shift); + eval_value = (uint64_t)doShift((uint32_t)eval_value, shift); datact = eval_value & 0xFFFF; if (datact < 0) { @@ -497,7 +504,7 @@ int CLASS::doDS(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) line.setError(errBadOperand); goto out; } - eval_value = doShift(eval_value, shift); + eval_value = (uint64_t)doShift((uint32_t)eval_value, shift); fill = eval_value & 0xFF; } else if (ct > 1) @@ -696,20 +703,21 @@ int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) std::string os = line.operand; std::string op = Poco::toUpper(line.opcode); - uint8_t lastdelimbyte = 0x00; - uint8_t firstdelim = 0xFF; + uint8_t firstdelim = 0; uint32_t bytect = 0; uint8_t b = 0; uint8_t b1; uint8_t ct = 0; - char delimiter = 0; + uint8_t delimiter = 0; uint32_t ss = 0; + uint32_t lastdelimidx = 0; + std::vector bytes; line.eval_result = 0; // since this is an ASCII p-op, clear the global 'bad operand' flag for ( uint32_t i = 0; i < os.length(); ++i ) { - char c = os[i]; + uint8_t c = os[i]; // are we inside a delimited string? if ( delimiter ) @@ -731,9 +739,9 @@ int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) { c |= 0x80; } - lastdelimbyte = c; + bytes.push_back(c); - //line.outbytes.push_back(c); + lastdelimidx = (uint32_t)(bytes.size() - 1); } } @@ -756,7 +764,7 @@ int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) { // if not a hex value, then consider the character to be the string delimiter delimiter = c; - if (firstdelim == 0xFF) + if( ! firstdelim ) { firstdelim = c; } @@ -784,7 +792,6 @@ int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) if (a.pass > 0) { bytes.push_back(b); - //line.outbytes.push_back(b); } b = 0; bytect++; @@ -805,8 +812,7 @@ int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) uint8_t andval = 0xFF; uint8_t orval = 0x00; uint8_t addlen = 0; - uint8_t firstbyte = 0x00; - uint32_t truebytect = bytes.size(); + uint32_t truebytect = (uint32_t)bytes.size(); const char *ptr = (const char *)op.c_str(); //printf("bytect=%d bytes.size()=%zu\n",bytect,bytes.size()); switch (strhash(ptr) ) @@ -855,26 +861,31 @@ int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) { b = bytes[i]; } - if (!i) - { - firstbyte = b; - } - b1 = b & 0x7F; + + b1 = b & 0x7F; if ((andval != 0xFF) || (orval != 0x00)) { b = b1; } + if ((b1 < 0x60)) { b &= andval; // strip whatever bits needed to flash or invert b |= orval; } - if ((dci) && (i == (truebytect - 1))) + + if (dci && (i == lastdelimidx)) { - // this one might be a bug. I am going to compare the first byte in the string for - // bit seven, and invert it on this byte. The confusion arises because this text string - // could have high ASCII, but low HEX values. - if (firstbyte < 0x80) + //lr - Merlin only toggles the high bit of string chars, not hex values + // 8D,'Hello',8D,'there',8D becomes 8D 48 65 6C 6C 6F 8D 74 68 65 72 E5 + // + // The DCI instruction is documented to work like this on page 108 + // (regardless of how this effects the desired lda, (bpl/bmi) functionality) + // + // I am now checking the delimiter character to determine hi/lo toggle (reversed) + // and am tracking the index to the last delimited character put into 'bytes'. + // This produces the same results as Merlin 16+ in my testing. + if ( firstdelim >= '\'' ) { b |= 0x80; } @@ -899,6 +910,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 +961,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 fe6454a..809cb54 100644 --- a/psuedo.h +++ b/psuedo.h @@ -21,6 +21,7 @@ enum P_ASC, P_ERR, P_MAC, + P_CAS, P_MAX }; diff --git a/testdata/3001-lroathe.S b/testdata/3001-lroathe.S index 13f9832..bfd0932 100644 --- a/testdata/3001-lroathe.S +++ b/testdata/3001-lroathe.S @@ -413,6 +413,8 @@ L00BC bit L00BC asc 02,15,"123456" asc 0215"1234"1502 + dci 8D,'Hello',8D,'there',8D + dci 8D,"Hello",8D,"there",8D lst lup_start: