From a80ff4a35cf6c2ee17c5833e77cdfaa9c0db5c0d Mon Sep 17 00:00:00 2001 From: marketideas Date: Mon, 18 Nov 2019 04:50:02 -0800 Subject: [PATCH] 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