From a80ff4a35cf6c2ee17c5833e77cdfaa9c0db5c0d Mon Sep 17 00:00:00 2001 From: marketideas Date: Mon, 18 Nov 2019 04:50:02 -0800 Subject: [PATCH 1/5] making tests pass --- asm.cpp | 42 ++++++++++++++++++++++++++++++++++++++++- asm.h | 6 ++++-- opcodes.cpp | 54 ++++++++++++++++++++++++++++++++++++++--------------- psuedo.cpp | 42 +++++++++++++++++++++++------------------ qasm.ini | 2 +- 5 files changed, 109 insertions(+), 37 deletions(-) diff --git a/asm.cpp b/asm.cpp index ef1afe0..6fe7b09 100644 --- a/asm.cpp +++ b/asm.cpp @@ -1427,8 +1427,10 @@ void CLASS::initpass(void) } mx = getInt("asm.startmx", mx);; + savepath = getConfig("option.objfile", ""); + lastcarry = false; relocatable = false; currentsym = &topSymbol; // this is the default symbol for :locals without a global above; currentsymstr = ""; @@ -1485,6 +1487,14 @@ void CLASS::complete(void) f.put(line.outbytes[i]); } } + if ((line.datafillct > 0) && ((line.flags & FLAG_INDUM) == 0)) + { + for (uint32_t i = 0; i < line.datafillct; i++) + { + f.put(line.datafillbyte & 0xFF); + } + + } } } else @@ -1618,6 +1628,35 @@ int CLASS::getAddrMode(MerlinLine & line) if (i > 0) { v = valEx.match(s, 0, 0); + if (v) + { + if (pass == 0) + { + // can only check on pass 0, because if the A" + // symbol is defined later, we will generate different + // bytes on the next pass + + if (Poco::toUpper(oper) == "A") // check the whole operand, not just the expression + { + // 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) + { + line.flags |= FLAG_FORCEIMPLIED; + mode = syn_implied; // if the label hasn't been defined yet, assume Immediate addressing + goto out; + } + } + } + else if (line.flags & FLAG_FORCEIMPLIED) + { + mode = syn_implied; + goto out; + } + } } } if (!v) @@ -1646,7 +1685,7 @@ int CLASS::getAddrMode(MerlinLine & line) } idx++; } - +out: if (mode == syn_none) { mode = syn_err; @@ -1828,6 +1867,7 @@ void CLASS::process(void) int64_t value = -1; x = evaluate(line, line.operand_expr, value); + line.eval_result = x; if (x == 0) { value &= 0xFFFFFFFF; diff --git a/asm.h b/asm.h index 27f9de8..ae95374 100644 --- a/asm.h +++ b/asm.h @@ -17,9 +17,10 @@ #define FLAG_DP 0x08 #define FLAG_BIGNUM 0x10 #define FLAG_INDUM 0x20 +#define FLAG_FORCEIMPLIED 0x40 #define FLAG_FORCEADDRPRINT 0x0100 -#define FLAG_NOLINEPRINT 0x2000 +#define FLAG_NOLINEPRINT 0x0200 #define OP_A 0x0001 #define OP_XY 0x0002 @@ -197,7 +198,7 @@ public: uint32_t addressmode; uint32_t expr_value; uint8_t expr_shift; // after an eval, this byte will reflect any shift code on expr (|^<>) - uint32_t eval_result; // this is the error code from the evaluate routing (0 or neg) + int32_t eval_result; // this is the error code from the evaluate routing (0 or neg) uint32_t errorcode; std::string errorText; @@ -344,6 +345,7 @@ public: uint32_t dumstartaddr; bool skiplist; // used if lst is on, but LST opcode turns it off uint32_t lineno; + bool lastcarry; std::string savepath; TSymbol *currentsym; diff --git a/opcodes.cpp b/opcodes.cpp index f852835..58afdbd 100644 --- a/opcodes.cpp +++ b/opcodes.cpp @@ -226,7 +226,7 @@ int CLASS::doNoPattern(MerlinLine &line, TSymbol &sym) op = (m == syn_abs ? 0x64 : op); op = (m == syn_absx ? 0x74 : op); - if ((op != 0) && ((line.expr_value >= 0x100) || (line.flags&FLAG_FORCEABS))) + if ((op != 0) && ((line.expr_value >= 0x100) || (line.flags & FLAG_FORCEABS))) { res++; op = (op == 0x64) ? 0x9C : op; @@ -236,7 +236,7 @@ int CLASS::doNoPattern(MerlinLine &line, TSymbol &sym) case 2: // TSB res++; op = (m == syn_abs ? 0x04 : op); - if ((op != 0) && ((line.expr_value >= 0x100) || (line.flags&FLAG_FORCEABS))) + if ((op != 0) && ((line.expr_value >= 0x100) || (line.flags & FLAG_FORCEABS))) { res++; op = 0x0C; @@ -245,7 +245,7 @@ int CLASS::doNoPattern(MerlinLine &line, TSymbol &sym) case 3: // TRB res++; op = (m == syn_abs ? 0x14 : op); - if ((op != 0) && ((line.expr_value >= 0x100) || (line.flags&FLAG_FORCEABS))) + if ((op != 0) && ((line.expr_value >= 0x100) || (line.flags & FLAG_FORCEABS))) { res++; op = 0x1C; @@ -422,7 +422,7 @@ int CLASS::doBRANCH(MerlinLine & line, TSymbol & sym) if ((offset < -128) || (offset > 127)) { err = true; - op=0x00; // merlin does this + op = 0x00; // merlin does this } } else if (res == 3) // long branch @@ -439,8 +439,8 @@ int CLASS::doBRANCH(MerlinLine & line, TSymbol & sym) setOpcode(line, op); for (i = 0; i < (res - 1); i++) { - uint8_t v=(offset >> (i*8)); - v=err?0x00:v; + uint8_t v = (offset >> (i * 8)); + v = err ? 0x00 : v; line.outbytes.push_back(v); } line.outbytect = res; @@ -489,7 +489,7 @@ int CLASS::doBase6502(MerlinLine & line, TSymbol & sym) bbb = 0x02; } - else if ((bbb > 0) && ((line.expr_value >= 0x100) || (line.flags&FLAG_FORCEABS))) + else if ((bbb > 0) && ((line.expr_value >= 0x100) || (line.flags & FLAG_FORCEABS))) { bbb |= 0x02; bytelen++; @@ -571,9 +571,9 @@ int CLASS::doBase6502(MerlinLine & line, TSymbol & sym) bytelen++; } } - if ( ((m==syn_absx) || (m==syn_diix)) && ((sym.opcode==4) || (sym.opcode==5))) // these are STX,LDX + if ( ((m == syn_absx) || (m == syn_diix)) && ((sym.opcode == 4) || (sym.opcode == 5))) // these are STX,LDX { - err=true; + err = true; } if ((m == syn_absx) || (m == syn_abs) || (m == syn_absy)) { @@ -747,6 +747,30 @@ int CLASS::doBYTE(MerlinLine & line, TSymbol & sym) setOpcode(line, sym.opcode); line.outbytect = res; } + + // SGQ merlin32 apparently tracks XCE instructions when tracking MX status + // who know how they determine this. I am assuming the NEXT instruction + // after a SEC/CLC instruction must be an XCE + if (sym.opcode == 0x38) // SEC + { + lastcarry = true; + } + else if (sym.opcode == 0x18) // CLC + { + lastcarry = false; + } + else if (sym.opcode==0xFB) // XCE + { + if (trackrep) + { + if (lastcarry) + { + mx=0x03; + } + } + } + + return (res); } @@ -755,23 +779,23 @@ int CLASS::doBRK(MerlinLine & line, TSymbol & sym) UNUSED(sym); int res = 1; - int bytes=0; + int bytes = 0; - if (line.operand_expr!="") + if (line.operand_expr != "") { bytes++; } if (pass > 0) { setOpcode(line, sym.opcode); - for (int i=0;i>(8*i))&0xFF); + line.outbytes.push_back((line.expr_value >> (8 * i)) & 0xFF); } - line.outbytect = res+bytes; + line.outbytect = res + bytes; } - return (res+bytes); + return (res + bytes); } void CLASS::insertOpcodes(void) diff --git a/psuedo.cpp b/psuedo.cpp index 7b598f1..93db837 100644 --- a/psuedo.cpp +++ b/psuedo.cpp @@ -119,7 +119,7 @@ int CLASS::doLUP(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) TEvaluator eval(a); - int64_t eval_result = 0; + int64_t eval_value = 0; uint8_t shift; int lidx, len; int res = 0; @@ -135,16 +135,16 @@ int CLASS::doLUP(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) { shift = 0; - eval_result = 0; - int x = eval.evaluate(line.operand_expr, eval_result, shift); + 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_result & 0xFFFF; // evaluate here + a.curLUP.lupct = eval_value & 0xFFFF; // evaluate here a.curLUP.luprunning++; - if ((x < 0) || (eval_result <= 0) || (eval_result > 0x8000)) + if ((x < 0) || (eval_value <= 0) || (eval_value > 0x8000)) { // merlin just ignores LUP if the value is out of range a.curLUP.lupct = 0; @@ -226,6 +226,9 @@ int CLASS::doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) //printf("DFB TOK1 : |%s|\n", oper.c_str()); + + line.eval_result=0; // since this is an data p-op, clear the global 'bad operand' flag + Poco::StringTokenizer tok(oper, ",", Poco::StringTokenizer::TOK_TRIM | Poco::StringTokenizer::TOK_IGNORE_EMPTY); @@ -264,7 +267,7 @@ int CLASS::doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) //printf("DFB TOK : |%s|\n", expr.c_str()); - int64_t eval_result = 0; + int64_t eval_value = 0; uint8_t shift; int r; uint8_t b; @@ -277,9 +280,9 @@ int CLASS::doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) expr = Poco::trim(expr); } shift = 0; - eval_result = 0; + eval_value = 0; //printf("DFB EVAL: |%s|\n", expr.c_str()); - r = eval.evaluate(expr, eval_result, shift); + r = eval.evaluate(expr, eval_value, shift); if (r < 0) { //printf("error %d\n",r); @@ -288,17 +291,17 @@ int CLASS::doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) line.setError(errBadEvaluation); } } - if (shift == '>') - { - eval_result = (eval_result) & 0xFF; - } if (shift == '<') { - eval_result = (eval_result >> 8) & 0xFF; + eval_value = (eval_value) & 0xFF; + } + if (shift == '>') + { + eval_value = (eval_value >> 8) & 0xFF; } else if ((shift == '^') || (shift == '|')) { - eval_result = (eval_result >> 16) & 0xFF; + eval_value = (eval_value >> 16) & 0xFF; } } @@ -309,7 +312,7 @@ int CLASS::doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) { for (i = 0; i < wordsize; i++) { - b = (eval_result >> (8 * i)) & 0xFF; + b = (eval_value >> (8 * i)) & 0xFF; line.outbytes.push_back(b); //printf("%02X\n",b); } @@ -319,7 +322,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_value >> ((wordsize - 1 - i) * 8)) & 0xFF; line.outbytes.push_back(b); //printf("%02X\n",b); } @@ -341,7 +344,7 @@ int CLASS::doDS(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) { line.setError(errForwardRef); } - else if ((v < 0) || ((a.PC.currentpc + v) >= 0x10000)) // no neg, or crossing bank bound + else if ((v < 0) || (((a.PC.currentpc&0xFFFF) + v) >= 0x10000)) // no neg, or crossing bank bound { line.setError(errOverflow); } @@ -349,7 +352,7 @@ int CLASS::doDS(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) { res = v; - line.datafillbyte = line.eval_result & 0xFF; + line.datafillbyte = 0x00; line.datafillct = v; } @@ -468,6 +471,8 @@ int CLASS::doHEX(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) std::string os = Poco::trim(line.operand); + line.eval_result=0; // since this is an data p-op, clear the global 'bad operand' flag + uint32_t bytect = 0; uint8_t b = 0; uint8_t ct = 0; @@ -538,6 +543,7 @@ int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) uint32_t ss = 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]; diff --git a/qasm.ini b/qasm.ini index 78c0ba2..31aaf04 100644 --- a/qasm.ini +++ b/qasm.ini @@ -26,7 +26,7 @@ startmx=3 lst=true ; can be M6502, M65C02, M65816 cpu=M65816 -trackrep=false +trackrep=true allowduplicate=true merlincompatible=true symcolumns=3 From 3fd0c7bcb519d21a40d8635e4f1c4980ad7c6262 Mon Sep 17 00:00:00 2001 From: marketideas Date: Mon, 18 Nov 2019 06:07:44 -0800 Subject: [PATCH 2/5] test --- asm.cpp | 31 +++++-- asm.h | 2 + psuedo.cpp | 142 ++++++++++++++++++++++------- psuedo.h | 2 + qasm.ini | 3 +- testdata/2007-labels-and-symbols.S | 4 +- 6 files changed, 137 insertions(+), 47 deletions(-) diff --git a/asm.cpp b/asm.cpp index 6fe7b09..2d247b7 100644 --- a/asm.cpp +++ b/asm.cpp @@ -34,8 +34,6 @@ void CLASS::print(uint32_t lineno) uint32_t b = 4; // how many bytes show on the first line - bool merlinstyle = true; - if (datafillct > 0) { l = datafillct; @@ -50,7 +48,7 @@ void CLASS::print(uint32_t lineno) } if (errorcode > 0) { - if (merlinstyle) + if (merlinerrors) { //printf("errorcode=%d\n",errorcode); printf("\n%s in line: %d", errStrings[errorcode].c_str(), lineno + 1); @@ -77,7 +75,7 @@ void CLASS::print(uint32_t lineno) nc = nc1; } - if ((!isatty(STDOUT_FILENO)) || (merlinstyle)) + if ((!isatty(STDOUT_FILENO)) || (merlinerrors)) { nc = true; } @@ -207,7 +205,7 @@ void CLASS::print(uint32_t lineno) pcol += printf("%s ", operand.c_str()); //pcol += printf("%-12s %-8s %-10s ", printlable.c_str(), opcode.c_str(), operand.c_str()); } - if ((errorcode > 0) && (!merlinstyle)) + if ((errorcode > 0) && (!merlinerrors)) { while (pcol < commentcol) { @@ -293,6 +291,7 @@ void CLASS::clear() operand_expr = ""; operand_expr2 = ""; addrtext = ""; + merlinerrors=false; linemx = 0; bytect = 0; opflags = 0; @@ -1062,6 +1061,11 @@ TSymbol *CLASS::findSymbol(std::string symname) { TSymbol *res = NULL; + std::string sym=symname; + if (!casesen) + { + sym=Poco::toUpper(sym); + } if (symname.length() > 0) { if (symname[0] == ':') @@ -1072,7 +1076,7 @@ TSymbol *CLASS::findSymbol(std::string symname) } else { - auto itr = currentsym->locals.find(Poco::toUpper(symname)); + auto itr = currentsym->locals.find(sym); if (itr != currentsym->locals.end()) { res = &itr->second; @@ -1083,7 +1087,7 @@ TSymbol *CLASS::findSymbol(std::string symname) else { //printf("finding: %s\n",symname.c_str()); - auto itr = symbols.find(Poco::toUpper(symname)); + auto itr = symbols.find(sym); if (itr != symbols.end()) { //printf("Found: %s 0x%08X\n",itr->second.name.c_str(),itr->second.value); @@ -1096,11 +1100,17 @@ out: return (res); } -TSymbol *CLASS::addVariable(std::string sym, std::string val, bool replace) +TSymbol *CLASS::addVariable(std::string symname, std::string val, bool replace) { TSymbol *res = NULL; TSymbol *fnd = NULL; + std::string sym=symname; + if (!casesen) + { + sym=Poco::toUpper(sym); + } + //printf("addvariable\n"); fnd = findVariable(sym); @@ -1128,7 +1138,7 @@ TSymbol *CLASS::addVariable(std::string sym, std::string val, bool replace) //printf("addvariable: %s %s\n", s.name.c_str(), s.text.c_str()); - std::pair p(Poco::toUpper(sym), s); + std::pair p(sym, s); variables.insert(p); res = findVariable(sym); return (res); @@ -1389,6 +1399,8 @@ void CLASS::initpass(void) casesen = getBool("asm.casesen", true); listing = getBool("asm.lst", true); showmx = getBool("asm.showmx", false); + merlinerrors = getBool("asm.merlinerrors", true); + trackrep = getBool("asm.trackrep", false); merlincompat = getBool("asm.merlincompatible", true); allowdup = getBool("asm.allowduplicate", true); @@ -1818,6 +1830,7 @@ void CLASS::process(void) line.linemx = mx; line.bytect = 0; line.showmx = showmx; + line.merlinerrors = merlinerrors; if ((line.lable != "")) { diff --git a/asm.h b/asm.h index ae95374..cae8a1e 100644 --- a/asm.h +++ b/asm.h @@ -190,6 +190,7 @@ public: uint8_t linemx; uint8_t tabs[16]; bool showmx; + bool merlinerrors; uint8_t truncdata; uint32_t lineno; uint32_t flags; @@ -335,6 +336,7 @@ public: bool showmx; bool trackrep; bool merlincompat; + bool merlinerrors; bool allowdup; uint8_t mx; uint8_t cpumode; // 0=6502, 1=65C02, 2=65816 diff --git a/psuedo.cpp b/psuedo.cpp index 93db837..fdfa6a8 100644 --- a/psuedo.cpp +++ b/psuedo.cpp @@ -14,13 +14,30 @@ CLASS::~CLASS() } +uint32_t CLASS::doShift(uint32_t value, uint8_t shift) +{ + if (shift == '<') + { + value = (value) & 0xFF; + } + if (shift == '>') + { + value = (value >> 8) & 0xFF; + } + else if ((shift == '^') || (shift == '|')) + { + value = (value >> 16) & 0xFF; + } + return (value); +} + int CLASS::doDO(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) { UNUSED(opinfo); TEvaluator eval(a); - int64_t eval_result = 0; + int64_t eval_value = 0; uint8_t shift; uint32_t result32; int res = 0; @@ -51,8 +68,8 @@ int CLASS::doDO(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) } shift = 0; - eval_result = 0; - int x = eval.evaluate(line.operand_expr, eval_result, shift); + eval_value = 0; + int x = eval.evaluate(line.operand_expr, eval_value, shift); if (x < 0) { @@ -65,7 +82,7 @@ int CLASS::doDO(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) goto out; } - result32 = eval_result & 0xFFFFFFFF; + result32 = eval_value & 0xFFFFFFFF; a.curDO.doskip = (result32 != 0) ? false : true; goto out; @@ -227,7 +244,7 @@ int CLASS::doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) //printf("DFB TOK1 : |%s|\n", oper.c_str()); - line.eval_result=0; // since this is an data p-op, clear the global 'bad operand' flag + line.eval_result = 0; // since this is an data p-op, clear the global 'bad operand' flag Poco::StringTokenizer tok(oper, ",", Poco::StringTokenizer::TOK_TRIM | Poco::StringTokenizer::TOK_IGNORE_EMPTY); @@ -291,18 +308,7 @@ int CLASS::doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) line.setError(errBadEvaluation); } } - if (shift == '<') - { - eval_value = (eval_value) & 0xFF; - } - if (shift == '>') - { - eval_value = (eval_value >> 8) & 0xFF; - } - else if ((shift == '^') || (shift == '|')) - { - eval_value = (eval_value >> 16) & 0xFF; - } + eval_value = doShift(eval_value, shift); } outct += wordsize; @@ -339,23 +345,87 @@ 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) - { - line.setError(errForwardRef); - } - else if ((v < 0) || (((a.PC.currentpc&0xFFFF) + v) >= 0x10000)) // no neg, or crossing bank bound - { - line.setError(errOverflow); - } - else - { - res = v; - line.datafillbyte = 0x00; - line.datafillct = v; + TEvaluator eval(a); + int64_t eval_value = 0; + uint8_t shift; + + line.eval_result = 0; // since this is an data p-op, clear the global 'bad operand' flag + line.flags|=FLAG_FORCEADDRPRINT; + std::string s; + Poco::StringTokenizer tok(line.operand, ",", Poco::StringTokenizer::TOK_TRIM | + Poco::StringTokenizer::TOK_IGNORE_EMPTY); + + int32_t datact = 0; + uint8_t fill = 0x0; + bool pagefill = false; + int32_t v = 0; + + + int ct = 0; + for (auto itr = tok.begin(); itr != tok.end(); ++itr) + { + s = *itr; + if (ct == 0) + { + if (s == "\\") + { + pagefill = true; + } + else + { + + shift = 0; + eval_value = 0; + int x = eval.evaluate(s, eval_value, shift); + if (x < 0) + { + line.setError(errBadOperand); + goto out; + } + eval_value = doShift(eval_value, shift); + datact = eval_value & 0xFFFF; + if (datact < 0) + { + line.setError(errBadOperand); + goto out; + } + } + } + else if (ct == 1) + { + + shift = 0; + eval_value = 0; + int x = eval.evaluate(s, eval_value, shift); + if (x < 0) + { + line.setError(errBadOperand); + goto out; + } + eval_value = doShift(eval_value, shift); + fill = eval_value & 0xFF; + } + else if (ct > 1) + { + line.setError(errBadOperand); + } + ct++; } + + line.datafillbyte = fill; + v = datact; + if (pagefill) + { + v=line.startpc&0xFF; + v=0x100-v; + } + line.datafillct = (uint16_t)v & 0xFFFF; + res=line.datafillct; + +out: + //printf("res=%d %04X\n",res,res); return (res); } @@ -471,7 +541,7 @@ int CLASS::doHEX(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) std::string os = Poco::trim(line.operand); - line.eval_result=0; // since this is an data p-op, clear the global 'bad operand' flag + line.eval_result = 0; // since this is an data p-op, clear the global 'bad operand' flag uint32_t bytect = 0; uint8_t b = 0; @@ -543,7 +613,7 @@ int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) uint32_t ss = 0; std::vector bytes; - line.eval_result=0; // since this is an ASCII p-op, clear the global 'bad operand' flag + 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]; @@ -697,8 +767,10 @@ int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) firstbyte = b; } b1 = b & 0x7F; - if ((andval!=0xFF) || (orval!=0x00)) - b=b1; + if ((andval != 0xFF) || (orval != 0x00)) + { + b = b1; + } if ((b1 < 0x60)) { b &= andval; // strip whatever bits needed to flash or invert diff --git a/psuedo.h b/psuedo.h index 3d1699b..7251ca9 100644 --- a/psuedo.h +++ b/psuedo.h @@ -28,6 +28,8 @@ class CLASS public: CLASS(); ~CLASS(); + uint32_t doShift(uint32_t value, uint8_t shift); + int ProcessOpcode(T65816Asm &a, MerlinLine &line, TSymbol &opinfo); int doLST(T65816Asm &a, MerlinLine &line, TSymbol &opinfo); int doDUM(T65816Asm &a, MerlinLine &line, TSymbol &opinfo); diff --git a/qasm.ini b/qasm.ini index 31aaf04..69af3c1 100644 --- a/qasm.ini +++ b/qasm.ini @@ -20,7 +20,7 @@ path4= path5=dirpath5 [asm] -casesen=true +casesen=false showmx=true startmx=3 lst=true @@ -28,6 +28,7 @@ lst=true cpu=M65816 trackrep=true allowduplicate=true +merlinerrors=false merlincompatible=true symcolumns=3 diff --git a/testdata/2007-labels-and-symbols.S b/testdata/2007-labels-and-symbols.S index 2c3b071..e5400cf 100644 --- a/testdata/2007-labels-and-symbols.S +++ b/testdata/2007-labels-and-symbols.S @@ -160,7 +160,7 @@ nosym equ $3300 ;should not match anything lda projalso lda nosym - bra :next + bra next target0 nop target1 nop ;point everything here @@ -186,7 +186,7 @@ t4a jml target0 t4b jml target1 t4c jml target2 -:next +next jsr t0 jsr t1a jsr t1b From 0a5f52a2d0d6e13b5472fd76a2ebedb22f186809 Mon Sep 17 00:00:00 2001 From: marketideas Date: Mon, 18 Nov 2019 11:34:20 -0800 Subject: [PATCH 3/5] test --- asm.cpp | 59 ++++++++++++++++++++++++---- eval.cpp | 115 +++++++++++++++++++++++++++++++++++++++++++++---------- eval.h | 3 ++ qasm.ini | 2 +- 4 files changed, 149 insertions(+), 30 deletions(-) diff --git a/asm.cpp b/asm.cpp index 2d247b7..b480bcb 100644 --- a/asm.cpp +++ b/asm.cpp @@ -291,7 +291,7 @@ void CLASS::clear() operand_expr = ""; operand_expr2 = ""; addrtext = ""; - merlinerrors=false; + merlinerrors = false; linemx = 0; bytect = 0; opflags = 0; @@ -376,10 +376,12 @@ void CLASS::set(std::string line) } break; case 3: + { if (c > ' ') { opcode += c; } +#if 1 else { // SGQ @@ -417,7 +419,41 @@ void CLASS::set(std::string line) state = 4; } - break; +#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()) + { + TSymbol s = itr->second; + if (1) + { + isascii = true; + } + } + + state = 4; + } +#endif + } + break; case 4: // read whitespace between opcode and operand if (c == ';') { @@ -986,11 +1022,18 @@ void CLASS::pushopcode(std::string op, uint8_t opcode, uint16_t flags, TOpCallba opcodes.insert(p); } -TSymbol *CLASS::addSymbol(std::string sym, uint32_t val, bool replace) +TSymbol *CLASS::addSymbol(std::string symname, uint32_t val, bool replace) { TSymbol *res = NULL; TSymbol *fnd = NULL; + std::string sym = symname; + if (!casesen) + { + sym = Poco::toUpper(sym); + } + + //printf("addSymbol: |%s|\n",sym.c_str()); if (sym.length() > 0) { TSymbol s; @@ -1001,7 +1044,7 @@ TSymbol *CLASS::addSymbol(std::string sym, uint32_t val, bool replace) s.value = val; s.used = false; s.cb = NULL; - std::pair p(Poco::toUpper(sym), s); + std::pair p(sym, s); if (sym[0] == ':') { @@ -1061,10 +1104,10 @@ TSymbol *CLASS::findSymbol(std::string symname) { TSymbol *res = NULL; - std::string sym=symname; + std::string sym = symname; if (!casesen) { - sym=Poco::toUpper(sym); + sym = Poco::toUpper(sym); } if (symname.length() > 0) { @@ -1105,10 +1148,10 @@ TSymbol *CLASS::addVariable(std::string symname, std::string val, bool replace) TSymbol *res = NULL; TSymbol *fnd = NULL; - std::string sym=symname; + std::string sym = symname; if (!casesen) { - sym=Poco::toUpper(sym); + sym = Poco::toUpper(sym); } //printf("addvariable\n"); diff --git a/eval.cpp b/eval.cpp index 8b1d461..ff7be25 100644 --- a/eval.cpp +++ b/eval.cpp @@ -27,16 +27,18 @@ std::deque CLASS::exprToTokens(const std::string& expr) int state = 0; char c; char delim; - std::string ident, asc; + std::string ident; + //, asc; std::string ops = "+-*//^!.&()"; std::string c1; char *tokptr; char *tptr; bool numexpect; + bool highascii = false; Token::Type t; - delim=0; + delim = 0; numexpect = true; for (const auto* p = expr.c_str(); *p; ++p) { @@ -56,18 +58,20 @@ std::deque CLASS::exprToTokens(const std::string& expr) if ((c < ' ') || (c == delim)) { // SGQ - convert ascii to a number here - asc = "0"; - //printf("ident=|%s|\n",ident.c_str()); + //asc = "0"; + //printf("ascii ident=|%s|\n", ident.c_str()); if (ident.length() > 0) { // SGQ - convert ascii to a number here } - t = Token::Type::Number; + ident = delim + ident + delim; + + t = Token::Type::Ascii; int pr = 1; // precedence - bool ra = false; // rightAssociative + bool ra = false; tokens.push_back(Token { - t, asc, pr, ra + t, ident, pr, ra }); ident = ""; state = 0; @@ -75,6 +79,8 @@ std::deque CLASS::exprToTokens(const std::string& expr) { p--; } + highascii = false; + delim = 0; } else { @@ -150,6 +156,7 @@ std::deque CLASS::exprToTokens(const std::string& expr) { delim = c; state = 11; + highascii = true; numexpect = false; } else if (((c == '-') || (c == '+')) && (numexpect)) @@ -220,7 +227,7 @@ std::deque CLASS::shuntingYard(const std::deque& tokens) token.type = Token::Type::Number; if (token.str == "*") { - sprintf(buff, "%u", assembler.PC.currentpc); + sprintf(buff, "$%X", assembler.PC.currentpc); token.str = buff; } else @@ -231,7 +238,7 @@ std::deque CLASS::shuntingYard(const std::deque& tokens) if (sym != NULL) { sym->used = true; - sprintf(buff, "%d", sym->value); + sprintf(buff, "$%X", sym->value); token.str = buff; } else @@ -243,6 +250,7 @@ std::deque CLASS::shuntingYard(const std::deque& tokens) } queue.push_back(token); break; + case Token::Type::Ascii: case Token::Type::Number: // If the token is a number, then add it to the output queue queue.push_back(token); @@ -363,9 +371,54 @@ std::deque CLASS::shuntingYard(const std::deque& tokens) return queue; } +int CLASS::parseAscii(std::string n, int64_t &val) +{ + int res = -1; + val = 0; + bool err = false; + uint64_t tval = 0; + bool high = false; + uint8_t c; + + uint32_t l = n.length(); + for (uint32_t i = 0; i < l - 1; i++) + { + c = n[i]; + if (i == 0) + { + if (c == '"') + { + high = true; + } + } + else + { + tval <<= 8; + if (high) + { + c |= 0x80; + } + else + { + c &= 0x7F; + } + tval = ((tval & 0xFFFFFF00) | c); + } + } + + if (!err) + { + val = (uint32_t)(tval & 0xFFFFFFFF); + res = 0; + } + + //printf("parseASCII |%s| %d %016lX\n", n.c_str(), res, val); + return (res); +} + int CLASS::parseNumber(std::string n, int64_t &val) { - int res = DEF_VAL; + int res = -1; int state = 0; char c; std::string s; @@ -376,8 +429,7 @@ int CLASS::parseNumber(std::string n, int64_t &val) int64_t tval = 0; val = 0; - - + //printf("parseNumber |%s|\n",n.c_str()); i = 0; l = n.length(); s = ""; @@ -483,12 +535,13 @@ int CLASS::parseNumber(std::string n, int64_t &val) } } - if (tval > (int64_t)0xFFFFFFFF) + uint32_t tv = (uint32_t)tval; + uint64_t tv1 = tv; + if (tv1 > (int64_t)0xFFFFFFFF) { setError(Token::overflowErr); } - //printf("parsenumber: |%s|\n",s.c_str()); if ((state == 99) || (err)) { @@ -507,6 +560,13 @@ int CLASS::parseNumber(std::string n, int64_t &val) //printf("value=%08lX\n", val); res = 0; } + if (res != 0) + { + if (isDebug() > 2) + { + printf("parsenumber error result: %d\n", res); + } + } return (res); } @@ -527,7 +587,7 @@ int CLASS::evaluate(std::string & e, int64_t &res, uint8_t &_shiftmode) // const std::string expr = "3+4*2/(1-5)^2^3"; // Wikipedia's example // const std::string expr = "20-30/3+4*2^3"; - _shiftmode=shiftmode=0; + _shiftmode = shiftmode = 0; res = DEF_VAL; setError(Token::noError); @@ -560,6 +620,19 @@ int CLASS::evaluate(std::string & e, int64_t &res, uint8_t &_shiftmode) //op = "Push " + token.str; //printf("shouldn't get this kind of token\n"); break; + case Token::Type::Ascii: + + val = 0; + u = parseAscii(token.str, val); + if (u < 0) + { + setError(Token::numberErr); + val = DEF_VAL; + } + stack.push_back(val); + //op = "Push " + token.str; + break; + case Token::Type::Number: val = 0; u = parseNumber(token.str, val); @@ -580,21 +653,21 @@ int CLASS::evaluate(std::string & e, int64_t &res, uint8_t &_shiftmode) { rhs = stack.back(); stack.pop_back(); - shiftmode=token.str[0]; + shiftmode = token.str[0]; - if (token.str=="^") + if (token.str == "^") { //rhs = (rhs >> 16) &0xFFFF ; } - else if (token.str=="|") + else if (token.str == "|") { //rhs = (rhs >> 16) & 0xFFFF; } - else if (token.str=="<") + else if (token.str == "<") { //rhs = (rhs << 8 ) & 0xFFFF; } - else if (token.str==">") + else if (token.str == ">") { //rhs=(rhs>>8) & 0xFFFF; } @@ -698,7 +771,7 @@ out: { setError(Token::syntaxErr); } - _shiftmode=shiftmode; + _shiftmode = shiftmode; res = v; return (evalerror); } diff --git a/eval.h b/eval.h index e9cf182..73b6c54 100644 --- a/eval.h +++ b/eval.h @@ -41,6 +41,7 @@ public: Unknown = 0, Number, Symbol, + Ascii, Shift, Operator, LeftParen, @@ -71,6 +72,8 @@ public: std::deque shuntingYard(const std::deque& tokens); std::deque exprToTokens(const std::string& expr); int parseNumber(std::string n, int64_t &val); + int parseAscii(std::string n, int64_t &val); + int evaluate(std::string &expr, int64_t &res, uint8_t &_shiftmode); }; diff --git a/qasm.ini b/qasm.ini index 69af3c1..2aad0ca 100644 --- a/qasm.ini +++ b/qasm.ini @@ -20,7 +20,7 @@ path4= path5=dirpath5 [asm] -casesen=false +casesen=true showmx=true startmx=3 lst=true From dd7dcb40821eda4a8529815c4b2b29d16d5d9920 Mon Sep 17 00:00:00 2001 From: marketideas Date: Mon, 18 Nov 2019 22:29:06 -0800 Subject: [PATCH 4/5] 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 5/5] 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 -