From 4380f4e8cab001df5b08ac31a9f49f00eaa34b36 Mon Sep 17 00:00:00 2001 From: Shawn Quick Date: Wed, 8 Feb 2023 10:14:55 -0800 Subject: [PATCH] might be broken, work on addressing modes and shift operators < > | ^ --- .vscode/launch.json | 4 +- asm.cpp | 270 +++++++++--- asm.h | 12 +- eval.cpp | 2 +- opcodes.cpp | 289 ++++++++----- parms.json | 16 +- psuedo.cpp | 58 ++- qasm.cpp | 16 +- qoptions.h | 385 +++++++++++++++--- runtests.sh | 10 +- test.s | 33 +- testdata/2001-allops-zero-6502.S | 9 +- testdata/2006-operand-formats.S | 4 +- testdata/2007-labels-and-symbols.S | 4 +- testdata/3001-runfile.S | 634 +++++++++++++++-------------- testdata/3015-amacc.S | 4 + 16 files changed, 1154 insertions(+), 596 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 71c4a0e..216d036 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -9,8 +9,8 @@ "program": "${workspaceFolder}/build/qasm", "args": [ "${workspaceFolder}/test.s", - "-s", - "-d" + "-d", + "-l" ], "stopAtEntry": false, "cwd": "${workspaceFolder}", diff --git a/asm.cpp b/asm.cpp index 15068a9..0f1a985 100644 --- a/asm.cpp +++ b/asm.cpp @@ -11,12 +11,12 @@ #define CLASS MerlinLine -CLASS::CLASS(ConfigOptions &opt) //: options(opt) +CLASS::CLASS(ConfigOptions &opt) : options(&opt) { clear(); } -CLASS::CLASS(std::string line, ConfigOptions &opt) //: options(opt) +CLASS::CLASS(std::string line, ConfigOptions &opt) : options(&opt) { clear(); set(line); @@ -68,11 +68,17 @@ void CLASS::print(uint32_t lineno) bool np=(flags & FLAG_NOLINEPRINT)?true:false; if (options->isQuiet()) + { np=true; + } if (options->isList()) - np=false; - if (force) + { np=false; + } + if (force) + { + np=false; + } if (np) { return; @@ -221,6 +227,8 @@ void CLASS::print(uint32_t lineno) } //pcol += printf("%-12s %-8s %-10s ", printlable.c_str(), opcode.c_str(), operand.c_str()); } + //printf("merlinerrors=%d\n",merlinerrors); + //merlinerrors=false; if ((errorcode > 0) && (!merlinerrors)) { while (pcol < commentcol) @@ -245,7 +253,7 @@ void CLASS::print(uint32_t lineno) if ((options->useColor()) && (errorcode > 0)) { - SetColor(CL_NORMAL | BG_NORMAL); + SetColor(CL_NORMAL); } uint32_t obc = datafillct; @@ -297,6 +305,7 @@ void CLASS::print(uint32_t lineno) void CLASS::clear() { + shiftchar=0; wholetext = ""; lable = ""; printlable = ""; @@ -305,6 +314,7 @@ void CLASS::clear() operand = ""; printoperand = ""; orig_operand=""; + strippedoperand=""; comment = ""; operand_expr = ""; operand_expr2 = ""; @@ -317,16 +327,15 @@ void CLASS::clear() startpc = 0; errorcode = 0; errorText = ""; - outbytect = 0; datafillct = 0; datafillbyte = 0; lineno = 0; - outbytes.clear(); addressmode = 0; expr_value = 0; eval_result = 0; flags = 0; outbytes.clear(); + outbytect = 0; } std::string operEx[] = @@ -556,9 +565,9 @@ CLASS::~CLASS() { } -void CLASS::setLanguage(string lang) +void CLASS::setLanguage(string lang,bool force) { - options.setLanguage(lang); + options.setLanguage(lang,force); } void CLASS::errorOut(uint16_t code) @@ -614,7 +623,7 @@ void CLASS::complete(void) //cout << "Processing Time: " << n - starttime << "ms" << endl; uint64_t x = n - starttime; uint32_t x1 = x & 0xFFFFFFFF; - if ((!getBool("option.quiet",false)) && (isDebug()>0)) + //if ((!getBool("option.quiet",false)) && (isDebug()>0)) { printf("Elapsed time: %u ms\n", x1); } @@ -1639,7 +1648,7 @@ int CLASS::callOpCode(std::string op, MerlinLine &line) break; case '>': #if 0 - if ((syntax & SYNTAX_MERLIN32) == SYNTAX_MERLIN32) + if (options.isMerlin32()) { // bug in M32 or not, do what it does line.flags |= FLAG_FORCEABS; @@ -1768,16 +1777,17 @@ void CLASS::initpass(void) showmx = getBool("asm.showmx", true); merlinerrors = getBool("asm.merlinerrors", true); + outputbytes.clear(); trackrep = getBool("asm.trackrep", false); - if (syntax == SYNTAX_MERLIN32) + if (options.isMerlin32()) { trackrep = true; // can't turn this off in M32 } - else if (syntax == SYNTAX_MERLIN) + else if (options.isMerlin()) { trackrep = false; // can't turn this ON in M16 } - else if (syntax == SYNTAX_QASM) + else if (options.isQASM()) { // we will allow this to be settable default off trackrep = false; @@ -1797,28 +1807,33 @@ void CLASS::initpass(void) s = getConfig("asm.cpu", "M6502"); s = Poco::trim(Poco::toUpper(s)); - cpumode = MODE_65816; - mx = 0x03; - - if (s == "M65816") + s=PAL::getString("option.instruction",""); + if (s!="") { + printf("CPU command line %s\n",s.c_str()); cpumode = MODE_65816; mx = 0x03; - } - else if (s == "M65C02") - { - cpumode = MODE_65C02; - mx = 0x03; - } - else if (s == "M6502") - { - cpumode = MODE_6502; - mx = 0x03; - } - else - { - printf("Unknown CPU type in .ini\n"); - mx = 0x03; + + if (s == "M65816") + { + cpumode = MODE_65816; + mx = 0x03; + } + else if (s == "M65C02") + { + cpumode = MODE_65C02; + mx = 0x03; + } + else if (s == "M6502") + { + cpumode = MODE_6502; + mx = 0x03; + } + else + { + printf("Unknown CPU type in .ini\n"); + mx = 0x03; + } } mx = getInt("asm.startmx", mx);; @@ -1829,7 +1844,7 @@ void CLASS::initpass(void) lastcarry = false; relocatable = false; currentsym = NULL; - if ((syntax & SYNTAX_MERLIN32) == SYNTAX_MERLIN32) + if (options.isMerlin32()) { // 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; @@ -1875,46 +1890,76 @@ void CLASS::initpass(void) void CLASS::complete(void) { + bool writeerr=false; if (savepath != "") { if (errorct == 0) { std::string currentdir = Poco::Path::current(); - savepath = processFilename(savepath, currentdir, 0); + //savepath = processFilename(savepath, currentdir, 0); + savepath=options.formatPath(savepath); if (!options.isQuiet()) { printf("saving to file: %s\n", savepath.c_str()); } - std::ofstream f(savepath); + std::ofstream f(savepath, std::ios::out|std::ios::trunc); - uint32_t lineno = 0; - uint32_t l = (uint32_t)lines.size(); - while (lineno < l) + if (f.is_open()) { - MerlinLine &line = lines.at(lineno++); - if ((line.outbytect > 0) && ((line.flags & FLAG_INDUM) == 0)) +#if 0 + uint32_t lineno = 0; + uint32_t l = (uint32_t)lines.size(); + while (lineno < l) { - for (uint32_t i = 0; i < line.outbytect; i++) + MerlinLine &line = lines.at(lineno++); + if ((line.outbytect > 0) && ((line.flags & FLAG_INDUM) == 0)) { - f.put(line.outbytes[i]); + for (uint32_t i = 0; i < line.outbytect; i++) + { + f.put(line.outbytes[i]); + } } - } - if ((line.datafillct > 0) && ((line.flags & FLAG_INDUM) == 0)) - { - for (uint32_t i = 0; i < line.datafillct; i++) + if ((line.datafillct > 0) && ((line.flags & FLAG_INDUM) == 0)) { - f.put(line.datafillbyte & 0xFF); - } + for (uint32_t i = 0; i < line.datafillct; i++) + { + f.put(line.datafillbyte & 0xFF); + } + } } +#else + + for (unsigned int i=0; i groups; + char shiftchar; oper = line.operand; - - if ((line.opcode.length() == 0) || (line.operand.length() == 0)) + int l=oper.length(); + if ((line.opcode.length() == 0) || (l <= 0)) { - return (syn_implied); + return (syn_none); + } + + bool supportbar=false; + bool modified=false; + + shiftchar=oper[0]; + if (shiftchar=='#') + { + shiftchar=0; + if (l>1) + { + shiftchar=oper[1]; + + //oper=oper.substr(1); + //oper="#"+oper; + } + } + if (shiftchar=='^') + { + if (options.isMerlin()) + { + return(syn_err); + //shiftchar=0x00; // merlin8 does not support the bank addr + } + } + if (shiftchar=='|') + { + if (options.isMerlinCompat()) + { + if ((options.isMerlin() || options.isMerlin16())) // merlin8 and merlin16 do not support the bar + { + return(syn_err); + } + else + { + supportbar=true; + } + } + } + + if ((shiftchar=='^') || (shiftchar=='<') || (shiftchar=='>') || (supportbar && shiftchar=='|')) + { + modified=true; + } + if (supportbar) + { + + } + if (modified) + { + line.shiftchar=shiftchar; + if (oper[0]=='#') + { + oper=oper.substr(2); + oper="#"+oper; + l=oper.length(); + } + else if (shiftchar!=0) + { + oper=oper.substr(1); + l=oper.length(); + } + printf("old: |%s| new: |%s|\n",line.operand.c_str(),oper.c_str()); + line.strippedoperand=oper; } idx = 0; @@ -2136,9 +2246,35 @@ int CLASS::parseOperand(MerlinLine & line) { //errorOut(errBadAddressMode); } + printf("addressmode=%d %s\n",res,addrModeEnglish(res).c_str()); return (res); } +string CLASS::addrModeEnglish(int mode) +{ + string res=""; + switch(mode) + { + case syn_err: res="addrmode_error";break; + case syn_none: res="addrmode_none";break; + case syn_implied: res="implied";break; + case syn_s: res="dp,s";break; + case syn_sy: res="(dp,s),y";break; + case syn_imm: res="#immediate";break; + case syn_diix: res="(dp,x)";break; + case syn_diiy: res="(dp),y";break; + case syn_di: res="(dp)";break; + case syn_iyl: res="[expr],y";break; + case syn_dil: res="[expr]";break; + case syn_absx: res="abs,x";break; + case syn_absy: res="abs,y";break; + case syn_bm: res="block move";break; + case syn_abs: res="absolute";break; + default: res="addr_mode bad";break; + } + return(res); +} + int CLASS::substituteVariables(MerlinLine & line, std::string &outop) { int res = 0; @@ -2580,6 +2716,24 @@ void CLASS::process(void) line.errorText = line.operand_expr; } line.bytect = x; + if (pass>0) + { + if ((line.flags & FLAG_INDUM) == 0) // don't write bytes if inside DUM section + { + for (unsigned int i=0; i0) + { + for (int i=0; i filenames; - uint32_t syntax; + //uint32_t syntax; uint64_t starttime; uint8_t tabs[16]; @@ -249,7 +253,7 @@ public: virtual void process(void); virtual void complete(void); virtual void errorOut(uint16_t code); - virtual void setLanguage(string lang); + virtual void setLanguage(string lang,bool force); }; @@ -403,6 +407,9 @@ class TPsuedoOp; class T65816Asm : public TFileProcessor { +protected: + std::vector outputbytes; + public: // options bool casesen; @@ -486,6 +493,7 @@ public: int parseOperand(MerlinLine &line); int getAddrMode(MerlinLine &line); + string addrModeEnglish(int mode); void setOpcode(MerlinLine &line, uint8_t op); diff --git a/eval.cpp b/eval.cpp index c34beff..214f99e 100644 --- a/eval.cpp +++ b/eval.cpp @@ -607,7 +607,7 @@ int CLASS::evaluate(std::string & e, int64_t &res, uint8_t &_shiftmode) std::string expr = Poco::trim(e); expr += " "; // add a space at end to make parsing easier - if (isDebug() >= 1) + if (isDebug() >= 3) { printf("eval: expression: |%s|\n", expr.c_str()); } diff --git a/opcodes.cpp b/opcodes.cpp index b8486ab..79aac88 100644 --- a/opcodes.cpp +++ b/opcodes.cpp @@ -7,6 +7,7 @@ void CLASS::setOpcode(MerlinLine &line, uint8_t op) { if (pass > 0) { + //printf("cpumode=%d\n",cpumode); if (cpumode < MODE_65816) // instructions are valid if we are in 65816 { uint8_t m = opCodeCompatibility[op]; @@ -40,6 +41,15 @@ int CLASS::doXC(MerlinLine &line, TSymbol &sym) std::string s; int res = 0; + if (options.isMerlin()) // in merlin8 mode we don't support XC psuedoop + { + if (line.errorcode == 0) // don't replace other errors + { + line.setError(errIncompatibleOpcode); + } + return(res); + } + if (cpumode < MODE_65816) { cpumode++; @@ -203,7 +213,7 @@ int CLASS::doMVN(MerlinLine &line, TSymbol &sym) // these bytes are the two bank registers if (options.isMerlin32() && (v<256)) - //if (((line.syntax & SYNTAX_MERLIN32) == SYNTAX_MERLIN32) && (v<256)) + //if (((line.syntax & SYNTAX_MERLIN32) == SYNTAX_MERLIN32) && (v<256)) { // merlin32 uses the low byte of the two operands line.outbytes.push_back((v) & 0xFF); @@ -248,40 +258,40 @@ int CLASS::doNoPattern(MerlinLine &line, TSymbol &sym) switch (sym.opcode) { - case 1: // STZ - res++; - op = (m == syn_abs ? 0x64 : op); - op = (m == syn_absx ? 0x74 : op); + case 1: // STZ + res++; + op = (m == syn_abs ? 0x64 : op); + op = (m == syn_absx ? 0x74 : op); - if ((op != 0) && ((line.expr_value >= 0x100) || (line.flags & FLAG_FORCEABS))) - { - res++; - op = (op == 0x64) ? 0x9C : op; - op = (op == 0x74) ? 0x9E : op; - } - break; - case 2: // TSB + if ((op != 0) && ((line.expr_value >= 0x100) || (line.flags & FLAG_FORCEABS))) + { res++; - op = (m == syn_abs ? 0x04 : op); - if ((op != 0) && ((line.expr_value >= 0x100) || (line.flags & FLAG_FORCEABS))) - { - res++; - op = 0x0C; - } - break; - case 3: // TRB + op = (op == 0x64) ? 0x9C : op; + op = (op == 0x74) ? 0x9E : op; + } + break; + case 2: // TSB + res++; + op = (m == syn_abs ? 0x04 : op); + if ((op != 0) && ((line.expr_value >= 0x100) || (line.flags & FLAG_FORCEABS))) + { res++; - op = (m == syn_abs ? 0x14 : op); - if ((op != 0) && ((line.expr_value >= 0x100) || (line.flags & FLAG_FORCEABS))) - { - res++; - op = 0x1C; - } - break; - default: - op = 0; - err = errBadOpcode; - break; + op = 0x0C; + } + break; + case 3: // TRB + res++; + op = (m == syn_abs ? 0x14 : op); + if ((op != 0) && ((line.expr_value >= 0x100) || (line.flags & FLAG_FORCEABS))) + { + res++; + op = 0x1C; + } + break; + default: + op = 0; + err = errBadOpcode; + break; } if (op == 0x00) @@ -316,15 +326,15 @@ int CLASS::doAddress(MerlinLine &line, TSymbol &sym) //} 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; + 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); @@ -347,12 +357,12 @@ int CLASS::doAddress(MerlinLine &line, TSymbol &sym) uint8_t newmx = (line.expr_value & 0x30) >> 4; switch (sym.opcode) { - case 0xC2: // REP - mx &= ~newmx; - break; - case 0xE2: // SEP - mx |= newmx; - break; + case 0xC2: // REP + mx &= ~newmx; + break; + case 0xE2: // SEP + mx |= newmx; + break; } line.linemx = mx; } @@ -544,21 +554,21 @@ int CLASS::doBase6502(MerlinLine & line, TSymbol & sym) int add = 0; switch (sym.opcode) { - case 7: // CPX - case 6: // CPY - case 5: // LDY - case 4: // STY - if ((mx & 0x01) == 0) - { - add = 1; - } - break; - case 1: // BIT - if ((mx & 0x02) == 0) - { - add = 1; - } - break; + case 7: // CPX + case 6: // CPY + case 5: // LDY + case 4: // STY + if ((mx & 0x01) == 0) + { + add = 1; + } + break; + case 1: // BIT + if ((mx & 0x02) == 0) + { + add = 1; + } + break; } bytelen += add; @@ -571,34 +581,55 @@ int CLASS::doBase6502(MerlinLine & line, TSymbol & sym) { switch (m) { - case syn_diix: amode = 0; break; - case syn_abs: amode = 1; break; - case syn_imm: amode = 2; break; - case syn_diiy: amode = 4; break; - case syn_absx: amode = 5; break; - case syn_absy: amode = 6; break; - default: - err = true; - break; + case syn_diix: + amode = 0; + break; + case syn_abs: + amode = 1; + break; + case syn_imm: + amode = 2; + break; + case syn_diiy: + amode = 4; + break; + case syn_absx: + amode = 5; + break; + case syn_absy: + amode = 6; + break; + default: + err = true; + break; } } else if (cc == 0x02) { switch (m) { - case syn_imm: amode = 0; break; - case syn_abs: amode = 1; break; - case syn_implied: amode = 2; bytelen = 0; break; - case syn_absy: - if ((opflags & OP_STX) == OP_STX) - { - amode = 5; - } - break; - case syn_absx: amode = 5; break; // this is actually Y addressing because X register is used - default: - err = true; - break; + case syn_imm: + amode = 0; + break; + case syn_abs: + amode = 1; + break; + case syn_implied: + amode = 2; + bytelen = 0; + break; + case syn_absy: + if ((opflags & OP_STX) == OP_STX) + { + amode = 5; + } + break; + case syn_absx: + amode = 5; + break; // this is actually Y addressing because X register is used + default: + err = true; + break; } if ((opflags & OP_STX) == OP_STX) @@ -715,17 +746,32 @@ int CLASS::doBase6502(MerlinLine & line, TSymbol & sym) err = false; switch (m) { - case syn_s: amode = 0; break; - case syn_sy: amode = 4; break; - case syn_di: cc = 0x02; amode = 4; break; - case syn_iyl: amode = 5; break; - case syn_dil: amode = 1; break; - case syn_absx: amode = 7; break; - case syn_abs: amode = 3; break; - default: - //printf("bad syn_mode=%d\n", m); - err = true; - break; + case syn_s: + amode = 0; + break; + case syn_sy: + amode = 4; + break; + case syn_di: + cc = 0x02; + amode = 4; + break; + case syn_iyl: + amode = 5; + break; + case syn_dil: + amode = 1; + break; + case syn_absx: + amode = 7; + break; + case syn_abs: + amode = 3; + break; + default: + //printf("bad syn_mode=%d\n", m); + err = true; + break; } if (!err) { @@ -750,15 +796,29 @@ out: if (err) { line.setError(errBadAddressMode); - //printf("bad address mode %d\n",line.addressmode); + printf("bad address mode %d\n",line.addressmode); op = 0x00; res = 0; bytelen = 0; } res += bytelen; + //if (options.isMerlin32()) + { + if ((op==0xB9) || (op==0x79) || (op==0xF9) || (op==0x99)) + { + // there are 4 instructions that don't have (dp),y addressing so convert to (abs), + if (bytelen<2) + { + res++; + bytelen++; + } + } + } + if ((pass > 0) && (res > 0)) { + setOpcode(line, op); for (i = 0; i < (res - 1); i++) { @@ -794,23 +854,26 @@ int CLASS::doBYTE(MerlinLine & line, TSymbol & sym) } // SGQ merlin32 apparently tracks XCE instructions when tracking MX status - // who know how they determine this. I am assuming the NEXT instruction + // who knows how they determine this. I am assuming the NEXT instruction // after a SEC/CLC instruction must be an XCE - if (sym.opcode == 0x38) // SEC + if (options.isMerlin32()) { - lastcarry = true; - } - else if (sym.opcode == 0x18) // CLC - { - lastcarry = false; - } - else if (sym.opcode == 0xFB) // XCE - { - if (trackrep) + if (sym.opcode == 0x38) // SEC { - if (lastcarry) + lastcarry = true; + } + else if (sym.opcode == 0x18) // CLC + { + lastcarry = false; + } + else if (sym.opcode == 0xFB) // XCE + { + if (trackrep) { - mx = 0x03; + if (lastcarry) + { + mx = 0x03; + } } } } @@ -847,11 +910,11 @@ void CLASS::insertOpcodes(void) { pushopcode("=", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doEQU)); pushopcode("EQU", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doEQU)); - 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("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("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)); diff --git a/parms.json b/parms.json index 5cb1877..035dd16 100644 --- a/parms.json +++ b/parms.json @@ -7,20 +7,26 @@ "0": "${PWD}" }, { - "1": "0/source" + "1": "${QASM_BASE}" }, { "2": "0/object" }, { - "3": "0/macros" + "3": "1/macros" + }, + { + "4": "1/toolmacs" + }, + { + "5": "../backup" } ] }, + "language": "qasm", "asm": { - "language": "merlin16plus", - "cpu": "M6502", - "start_mx": 2, + "cpu": "M65816", + "start_mx": 0, "listmode": "on", "casesen": true, "start_lst": false, diff --git a/psuedo.cpp b/psuedo.cpp index 60750fd..22f7cfe 100644 --- a/psuedo.cpp +++ b/psuedo.cpp @@ -793,6 +793,7 @@ int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) uint8_t delimiter = 0; uint32_t ss = 0; uint32_t lastdelimidx = 0; + bool dci = false; std::vector bytes; @@ -890,7 +891,6 @@ int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) { uint32_t i; bool reverse = false; - bool dci = false; uint8_t andval = 0xFF; uint8_t orval = 0x00; uint8_t addlen = 0; @@ -956,28 +956,42 @@ int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) b |= orval; } - if (dci && (i == lastdelimidx)) + if ((line.options->isMerlin32()) || (line.options->isMerlin16plus())) { - // SGQ BUG - Merlin16+ does it like Merlin32 and now does the last - // byte not the way merlin816 and earlier do it documented below. - // use OPTION_M16_PLUS when implemented. + // invert last byte of total bytes out - //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 >= '\'' ) + if ((dci) && ((i+1)>=truebytect)) { - b |= 0x80; + b^=0x80; } - else + } + else + { + printf("bug\n"); + // invert last byte of last string (old merlin way (pre-merlin16+)) + if (dci && (i == lastdelimidx)) { - b &= 0x7F; + // SGQ BUG - Merlin16+ does it like Merlin32 and now does the last + // byte not the way merlin816 and earlier do it documented below. + // use OPTION_M16_PLUS when implemented. + + //lr - Merlin only toggles the high bit of string chars, not hex values + // 8D,'Hello',8D,'there',8D becomes 8D 48 65 6C 6C 6F 8D 74 68 65 72 E5 + // + // 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; + } + else + { + b &= 0x7F; + } } } line.outbytes.push_back(b); @@ -986,7 +1000,7 @@ int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) bytect = bytect + addlen; } - //printf("XXX bytect=%d bytes.size()=%zu\n",bytect,bytes.size()); +//printf("XXX bytect=%d bytes.size()=%zu\n",bytect,bytes.size()); line.outbytect = bytect; return bytect; @@ -1033,7 +1047,8 @@ 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) + if (options.isMerlin32()) { // so clear the bank word in all variables a.PC.orgsave &= 0xFFFF; @@ -1048,7 +1063,8 @@ int CLASS::ProcessOpcode(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) sp = getConfig("option.objfile", ""); if (sp=="") { - a.savepath = a.processFilename(line.operand, Poco::Path::current(), 0); + //a.savepath = a.processFilename(line.operand, Poco::Path::current(), 0); + a.savepath=line.operand; } else // if they specified an output name on the command line, use it. { diff --git a/qasm.cpp b/qasm.cpp index ba84677..e3a619d 100644 --- a/qasm.cpp +++ b/qasm.cpp @@ -115,10 +115,11 @@ int CLASS::runCommandLineApp(void) return (res); } - options.ReadFile(Poco::Path::config()+"/parms.json"); - options.ReadFile(appPath+"/parms.json"); - options.ReadFile(Poco::Path::configHome()+"/parms.json"); - options.ReadFile(Poco::Path::current()+"/parms.json"); + //printf("apppath: |%s|\n",appPath.c_str()); + options.ReadFile(Poco::Path::config()+"/parms.json",false); + options.ReadFile(appPath+"/parms.json",true); + options.ReadFile(Poco::Path::configHome()+"/parms.json",false); + options.ReadFile(Poco::Path::current()+"/parms.json",false); syn="QASM"; @@ -145,6 +146,7 @@ int CLASS::runCommandLineApp(void) } language=syn; + options.setLanguage(syn,true); if (isDebug()>0) { @@ -237,7 +239,7 @@ int CLASS::runCommandLineApp(void) try { t->init(); - t->setLanguage(language); + t->setLanguage(language,true); t->format_flags=format_flags; std::string f = path.toString(); @@ -271,7 +273,7 @@ int CLASS::runCommandLineApp(void) try { t->init(); - t->setLanguage(language); + t->setLanguage(language,true); std::string f = path.toString(); @@ -308,7 +310,7 @@ int CLASS::runCommandLineApp(void) try { t->init(); - t->setLanguage(language); + t->setLanguage(language,true); std::string f = path.toString(); t->filename = f; diff --git a/qoptions.h b/qoptions.h index 0ed1a50..e4528ae 100644 --- a/qoptions.h +++ b/qoptions.h @@ -3,6 +3,8 @@ using namespace Poco; +#define ENV_QASM "QASM_BASE" + #define MAX_PREFIX 32 #define MODE_6502 0 @@ -10,13 +12,15 @@ using namespace Poco; #define MODE_65816 2 #define SYNTAX_MERLIN 0x01 -#define SYNTAX_MERLIN32 0x02 -#define SYNTAX_APW 0x04 -#define SYNTAX_MPW 0x08 -#define SYNTAX_ORCA 0x10 -#define SYNTAX_CC65 0x20 -#define SYNTAX_LISA 0x40 -#define SYNTAX_QASM (0x80 | SYNTAX_MERLIN) +#define SYNTAX_MERLIN16 0x02 +#define SYNTAX_MERLIN16PLUS 0x04 +#define SYNTAX_MERLIN32 0x08 +#define SYNTAX_APW 0x10 +#define SYNTAX_MPW 0x20 +#define SYNTAX_ORCA 0x40 +#define SYNTAX_CC65 0x80 +#define SYNTAX_LISA 0x100 +#define SYNTAX_QASM (0x200 | SYNTAX_MERLIN) #define OPTION_ALLOW_A_OPERAND 0x0100 #define OPTION_ALLOW_LOCAL 0x0200 @@ -41,11 +45,11 @@ class CLASS { protected: //vector> configs; - + vector valid_files; public: - Poco::JSON::Parser parser; - string jsonin; - Dynamic::Var jsonobj=NULL; + //Poco::JSON::Parser parser; + //string jsonin; + //Dynamic::Var jsonobj=NULL; uint16_t format_flags; uint16_t cpu_mode; @@ -70,23 +74,34 @@ public: int16_t linebytes; int16_t overflowbytes; - myLayeredConfiguration config; + myLayeredConfiguration *config=NULL; bool usecolor; CLASS() { + language=""; + setEnvironment(); + clear(); setDefaults(); - setLanguage("QASM"); + setLanguage("QASM",true); + setCurrent(); } ~CLASS() { - + clear(); } void clear() { - //configs.clear(); + if (config!=NULL) + { + delete config; + config=NULL; + } + config=new myLayeredConfiguration(); + valid_files.clear(); + } bool useColor(void) @@ -125,6 +140,8 @@ public: int printDefaults(string lang) { int res=-1; + string s; + int i; string l=Poco::toUpper(lang); if (l=="") { @@ -132,24 +149,46 @@ public: } if (l!="") { - setLanguage(l); + setLanguage(l,false); setCurrent(); printf("Defaults for language (%s)\n",language.c_str()); - printf("\tLanguage:\t\t\t\t\t%s\n",language.c_str()); - printf("\t\tlanguageLevel:\t\t\t\t%d\n",langlevel); - printf("\t\tcpu_mode:\t\t\t\t%d\n",cpu_mode); - printf("\t\tstart_mx:\t\t\t\t%d\n",start_mx); + printf("\t\tLanguage:\t\t\t%s\n",language.c_str()); + printf("\t\tlanguageLevel:\t\t\t%d\n",langlevel); + s=""; + switch(cpu_mode) + { + case 0: + s="M6502"; + break; + case 1: + s="M65C02"; + break; + case 2: + s="M65816"; + break; + } + printf("\t\tcpu_mode:\t\t\t%s\n",s.c_str()); + printf("\t\tstart_mx:\t\t\t%%%d%d\n",start_mx&0x02?1:0,start_mx&0x01?1:0); + //printf("\t\tstart_mx:\t\t\t%d\n",start_mx); printf("\t\tPrefixes:\n"); - for (int i=0; i0) { - printf("\t\t\t%02d:\t\t\t%s\n",i,prefixes[i].c_str()); + printf("\t\t\t%2d:\t%s\n",i,prefixes[i].c_str()); } } + printf("\n"); + for (unsigned long ii=0; ii0) + { + printf("\t\tSettings files read: \t%s\n",valid_files[ii].c_str()); + } + } //uint16_t format_flags; @@ -160,68 +199,292 @@ public: return(res); } - int ReadFile(string path) + string getAppPath() { + char buff[PATH_MAX+1]; + char *x; + + string res=""; + res=Poco::Util::Application::instance().commandPath(); + x=realpath(res.c_str(),buff); + if (x!=NULL) + { + res=buff; + } + else + { + res=""; + } + return(res); + } + int ReadFile(string path, bool backtrack) + { + //int levels=0; + bool done=false; int ret=-1; + unsigned long ii; Poco::Util::JSONConfiguration *jc; - Poco::Path pp(path); - //pp=pp.expand(); - Poco::File pf(pp); - if (isDebug()>1) + while(!done) { - printf("parmsfile: %s\n",pp.toString().c_str()); - } - if ((pf.exists()) && (pf.canRead()) && ((pf.isFile()) || (pf.isLink()))) - { - //printf("OK: %s\n",pp.toString().c_str()); + Poco::Path pp(path); + //pp=pp.absolute(Poco::Path("/")); + pp=pp.absolute(); - jc=new Poco::Util::JSONConfiguration(); - //Poco::FileInputStream fs(path); - //Poco::StreamCopier::copyToString(fs,jsonin); - //parser.reset(); - //parser.setAllowComments(true); - //jsonobj=parser.parse(jsonin); - if (jc!=NULL) + std::string basename=pp.getFileName(); + + Poco::File pf(pp); + if (isDebug()>1) { - bool success=false; - try + //pf. + printf(" %d parmsfile: %s ",backtrack,pf.path().c_str()); + } + if ((pf.exists()) && (pf.canRead()) && ((pf.isFile()) || (pf.isLink()))) + { + if (isDebug()>1) { - jc->load(pp.toString()); - success=true; + printf("...found!\n"); } - catch(...) + //printf("OK: %s\n",pp.toString().c_str()); + done=false; + for (ii=0; ii(jc)); - config.add(jc); - ret=0; + done=true; // we found a valid file + + jc=new Poco::Util::JSONConfiguration(); + //Poco::FileInputStream fs(path); + //Poco::StreamCopier::copyToString(fs,jsonin); + //parser.reset(); + //parser.setAllowComments(true); + //jsonobj=parser.parse(jsonin); + if (jc!=NULL) + { + bool success=false; + try + { + jc->load(pp.toString()); + success=true; + } + catch(...) + { + success=false; + } + if (success) + { + //configs.push_back(shared_ptr(jc)); + config->add(jc); + valid_files.push_back(pp.toString()); + ret=0; + } + else + { + delete jc; + jc=NULL; + printf("...unable to load/parts file: %s\n",pp.toString().c_str()); + } + + } } - else + + } + else + { + if (isDebug()>1) { - printf("unable to load/parts file: %s\n",pp.toString().c_str()); + printf("...not found\n"); } } + if (!backtrack) + { + done=true; + } + + if (!done) + { + //string ss=pp.current(); + string ss=pp.toString(); + pp=pp.popDirectory(); + string ss1=pp.toString(); + + //printf("|%s| |%s|\n",ss.c_str(),ss1.c_str()); + //assert(0); + path=ss1; + pp=Path(path); + if (path=="/") + { + done=true; + } + //path=path+"/"+basename; + } } return(ret); } bool isMerlin32(void) { - return(true); + bool res=false; + if (language=="MERLIN32") + { + res=true; + } + return(res); } bool isMerlin(void) { - return(false); + bool res=false; + if (language=="MERLIN") + { + res=true; + } + return(res); + } + bool isQASM(void) + { + bool res=false; + if (language=="QASM") + { + res=true; + } + return(res); + } + + bool isMerlinCompat() + { + bool res=false; + string s=language; + if (s=="QASM") + { + return(true); + } + bool b=s.find("MERLIN"); // any of the merlin varieties + if (b) + { + res=true; + return(res); + } + return(res); + } + + bool isMerlin16(void) + { + bool res=false; + if (language=="MERLIN16") + { + res=true; + } + return(res); + } + + bool isMerlin16plus(void) + { + bool res=false; + if (language=="MERLIN16PLUS") + { + res=true; + } + return(res); + } + + void setEnvironment() + { + string s=""; + //s=Poco::Environment::get("QASM"); + if (!Poco::Environment::has(ENV_QASM)) + { + s=Poco::Util::Application::instance().commandPath(); + Poco::Path pp(getAppPath()); + pp=pp.absolute(Poco::Path()); + //pp=pp.absolute(Poco::Path("/")); + s=pp.toString(); + //printf("program: %s\n",s.c_str()); + Poco::Environment::set(ENV_QASM,s); + } + } + string formatPath(string p) + { + string res=p; + string s; + Poco::Path pp(p); + s=pp.expand(pp.toString()); // replace environment variable references + pp=Poco::Path(s); + if (s!="") + { + + Poco::StringTokenizer toks(s,"/"); + if (toks.count()>0) + { + uint32_t n; + bool success=false; + try + { + n=Poco::NumberParser::parseUnsigned(toks[0]); + if (ngetBool(name); + //Dynamic::Var jresult=GetObject(name); //if (!jresult.isEmpty()) //{ @@ -358,7 +623,7 @@ public: string res=def; try { - //config + res=config->getString(name); } catch(...) { @@ -373,8 +638,8 @@ public: #if 0 std::vector keys; - config.keys(keys); - for (unsigned int i=0;ikeys(keys); + for (unsigned int i=0; igetInt(name); } catch(...) { diff --git a/runtests.sh b/runtests.sh index fdc5cd0..5d9c6c7 100755 --- a/runtests.sh +++ b/runtests.sh @@ -29,10 +29,14 @@ for S in $SRC ; do BASE=${BASE/.s/} #./qasm -o 0/$OUTDIR/$S1 ./testdata/$S - ./qasm --syntax merlin32 -o 0/$OUTDIR/$S1 ./testdata/$S >> $TMPFILE + ./qasm -l -t merlin32 -i M65816 -o 0/$OUTDIR/$S1 ./testdata/$S >> $TMPFILE + + X="./qasm -l -t merlin32 -i M65816 -o 0/$OUTDIR/$S1 ./testdata/$S" + #echo $X R=?$ #echo $S " " $S1 + #cat $TMPFILE R=`cat $TMPFILE | grep "End qASM assembly"` E=`echo $R | awk -e '{ print $6; }'` ect=`echo $(($E))` @@ -64,8 +68,12 @@ for S in $SRC ; do if [ $pct != 0 ] ; then printf 'FAIL: (%3s) ' $ect printf '%s ' $CX + echo " $S" FAILCT=$(($FAILCT+1)) + cat $TMPFILE + echo $X + exit 255 else printf "PASS: " fi diff --git a/test.s b/test.s index e8ceb18..e672f37 100644 --- a/test.s +++ b/test.s @@ -10,9 +10,36 @@ xc off xc xc + lst ;lst OFF ZP equ $00 org $2000 + lda $04,y + adc $04,y + sbc $04,y + sta $04,y + + lda <$fff0 ;zp + lda >$fff0 ;ABS (lo word) + lda ^$fff0 ;ABS (hi word) + lda |$fff0 ;ABS (long in 65816 mode) + lda <$FFF0+$FFFF + + lda <$fff0+24 ;zp + lda >$fff0+24 ;ABS (lo word) + lda ^$fff0+24 ;ABS (hi word) + lda |$fff0+24 ;ABS (long in 65816 mode) + + lda #<$fff0 ;zp + lda #>$fff0 ;ABS (lo word) + lda #^$fff0 ;ABS (hi word) + lda #<$FFF0+$FFFF + lda #>$FFF0+$FFFF + + + + lst off + end ora ($00) lda ($00) bit: $FFFE,X @@ -51,11 +78,15 @@ another lda #$00 ;line with everything lda ]m bra ]m --^ + sav 2/test.bin + end + + ]1 nop nop ;lst bra ]1 ;typ $06 - sav 0/test.bin + db 255 ;lst off diff --git a/testdata/2001-allops-zero-6502.S b/testdata/2001-allops-zero-6502.S index d35e34a..f583a9d 100644 --- a/testdata/2001-allops-zero-6502.S +++ b/testdata/2001-allops-zero-6502.S @@ -1,8 +1,9 @@ -; Copyright 2018 faddenSoft. All Rights Reserved. -; See the LICENSE.txt file for distribution terms (Apache 2.0). -; -; Assembler: Merlin 32 + ; Copyright 2018 faddenSoft. All Rights Reserved. + ; See the LICENSE.txt file for distribution terms (Apache 2.0). + ; + ; Assembler: Merlin 32 + xc off ZP EQU $00 ABS EQU $0000 diff --git a/testdata/2006-operand-formats.S b/testdata/2006-operand-formats.S index 9a027bd..056528b 100644 --- a/testdata/2006-operand-formats.S +++ b/testdata/2006-operand-formats.S @@ -4,7 +4,9 @@ ; Assembler: Merlin 32 org $1000 - + xc off + xc + xc ; 65816 with short regs clc xce diff --git a/testdata/2007-labels-and-symbols.S b/testdata/2007-labels-and-symbols.S index aca00e4..89247db 100644 --- a/testdata/2007-labels-and-symbols.S +++ b/testdata/2007-labels-and-symbols.S @@ -2,7 +2,9 @@ ; See the LICENSE.txt file for distribution terms (Apache 2.0). ; ; Assembler: Merlin 32 - + xc off + xc + xc absl equ $1029 absh equ $feed zip equ $cd diff --git a/testdata/3001-runfile.S b/testdata/3001-runfile.S index bfa0b61..bac8562 100644 --- a/testdata/3001-runfile.S +++ b/testdata/3001-runfile.S @@ -1,4 +1,4 @@ - ;lst off + lst off * * main.s * Merlin32 Test @@ -6,401 +6,403 @@ * Created by Lane Roathe on 8/26/19. * Copyright B) 2019 Ideas From the Deep. All rights reserved. * -//]XCODESTART ; Keep this at the start and put your code after this +//]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 - 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 START - 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,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 + adc 0 + adc $80 + adc _tmp + adc #0 + adc #$1111 + adc $1111 - sta TSTADDR+dum0 - sta TSTADDR+_num1+dum0 - sta TSTADDR+_num1+dum0,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 + 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,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 + lst + lda _num1+dum0,y ;these assemble to abs accesses: lda $00C0,y + adc _num1+dum0,y + sbc _num1+dum0,y + sta _num1+dum0,y + lst off - ; Label & branching tests -GetKey ldx $C000 - bpl GetKey -]loop - dex - bne ]loop + ; Label & branching tests +GetKey ldx $C000 + bpl GetKey +]loop + dex + bne ]loop - tya - and #1 - beq :err + 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 + tya + and #1 + bne :good +:err + lda #0 +:good + bne myQuit + nop + hex 2C ;bit + lda #1 +myQuit + jmp DOSWARM - org $2000 + org $2000 - lda _LFT - ldx #_LFT - cpx #$20 + lda _LFT + ldx #_LFT + cpx #$20 - org ;return to ongoing address + 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 $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 + 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 $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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + ;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) + 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 + mx %11 - lda #<$fff0+24 ;byte - lda #>$fff0+24 ;page - lda #^$fff0+24 ;bank + lda #<$fff0+24 ;byte + lda #>$fff0+24 ;page + lda #^$fff0+24 ;bank - lda #<$1234 ;byte - lda #>$1234 ;page - lda #^$1234 ;bank - lda #^$A51234 ;bank + lda #<$1234 ;byte + lda #>$1234 ;page + lda #^$1234 ;bank + lda #^$A51234 ;bank - mx %00 + mx %00 - lda #<$fff0+24 ;byte - lda #>$fff0+24 ;page - lda #^$fff0+24 ;bank + lda #<$fff0+24 ;byte + lda #>$fff0+24 ;page + lda #^$fff0+24 ;bank - lda #<$1234 ;byte - lda #>$1234 ;page - lda #^$1234 ;bank - lda #^$A51234 ;bank + lda #<$1234 ;byte + lda #>$1234 ;page + lda #^$1234 ;bank + lda #^$A51234 ;bank - lda $0008 ;ZP - lda $08 ;ZP - lda $ffff-$fff7 ;ZP - lda $fff0+24 ;ABS (long in 65816 mode) + 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 + ;Issue #8 fadden) - STX zp,y fails to assemble + org $bc -L00BC bit L00BC +L00BC bit L00BC - org + org - stx $bc,y + stx $bc,y - ldx L00BC,y - stx L00BC,y + ldx L00BC,y + stx L00BC,y * Data Storage Tests - hex ;no error - hex 11,22,33,44,55,66,77,88,99 - ;hex 112233445566778899F - ;hex 112233445I566778899FF + hex ;no error + hex 11,22,33,44,55,66,77,88,99 + ;hex 112233445566778899F + ;hex 112233445I566778899FF - hex aabb,CC,0123456789abcdefABCDEF,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 + 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 + dw >$01A55A,>$011234 + dw <$01A55A,<$011234 + dw ^$01A55A,^$011234 + dw |$01A55A,|$011234 - db >$01A55A,>$011234 - db <$01A55A,<$011234 - db ^$01A55A,^$011234 - db |$01A55A,|$011234 + db >$01A55A,>$011234 + db <$01A55A,<$011234 + db ^$01A55A,^$011234 + db |$01A55A,|$011234 - asc 02,15,"123456" - asc 02,15,z123456z - asc 0215,"123456" - asc 02,15,'123456' - asc 02,15,!123456! - asc 02,15,@123456@ - asc 02,15,#123456# - asc 02,15,$123456$ - asc 02,15,%123456% - asc 02,15,^123456^ - asc 02,15,&123456& - asc 02,15,*123456* - asc 02,15,(123456( - asc 02,15,)123456) - asc 02,15,/123456/ - asc 02,15,?123456? - asc 02,15,>123456> - asc 02,15,<123456< - asc 02,15,05,"123456" - asc 02,15,"123456" - asc 0215"1234"1502 + asc 02,15,"123456" + asc 02,15,z123456z + asc 0215,"123456" + asc 02,15,'123456' + asc 02,15,!123456! + asc 02,15,@123456@ + asc 02,15,#123456# + asc 02,15,$123456$ + asc 02,15,%123456% + asc 02,15,^123456^ + asc 02,15,&123456& + asc 02,15,*123456* + asc 02,15,(123456( + asc 02,15,)123456) + asc 02,15,/123456/ + asc 02,15,?123456? + asc 02,15,>123456> + asc 02,15,<123456< + asc 02,15,05,"123456" + asc 02,15,"123456" + asc 0215"1234"1502 - dci 8D,'Hello',8D,'there',8D - dci 8D,"Hello",8D,"there",8D + dci 8D,'Hello',8D,'there',8D + dci 8D,"Hello",8D,"there",8D - lst + lst lup_start: - lup 0 - db 0 ; outside - --^ + lup 0 + db 0 ; outside + --^ - ;lst off -//]XCODEEND ; Keep this at the end and put your code above this - ;lst off + ;lst off +//]XCODEEND ; Keep this at the end and put your code above this + lst off diff --git a/testdata/3015-amacc.S b/testdata/3015-amacc.S index d38e59e..bc034da 100644 --- a/testdata/3015-amacc.S +++ b/testdata/3015-amacc.S @@ -1,6 +1,10 @@ * * explicit a operand (inc a, etc) is dropped. * + xc OFF + xc + xc + mx %11 inc a dec a