diff --git a/asm.cpp b/asm.cpp index 19ccbaa..1045272 100644 --- a/asm.cpp +++ b/asm.cpp @@ -211,7 +211,14 @@ void CLASS::print(uint32_t lineno) } else { - pcol += printf("%s ", printoperand.c_str()); + if (printoperand.length() > 0) + { + pcol += printf("%s ", printoperand.c_str()); + } + else + { + pcol += printf("%s ", operand.c_str()); + } } //pcol += printf("%-12s %-8s %-10s ", printlable.c_str(), opcode.c_str(), operand.c_str()); } @@ -292,6 +299,7 @@ void CLASS::print(uint32_t lineno) void CLASS::clear() { syntax = SYNTAX_MERLIN; + wholetext = ""; lable = ""; printlable = ""; opcode = ""; @@ -345,6 +353,7 @@ void CLASS::set(std::string line) std::string tline = line; clear(); + wholetext = line; isascii = false; delim = 0; while (i < l) @@ -1117,6 +1126,28 @@ out: return (res); } + +TMacro * CLASS::findMacro(std::string symname) +{ + TMacro *res = NULL; + + std::string sym = symname; + if (!casesen) + { + sym = Poco::toUpper(sym); + } + if (symname.length() > 0) + { + //printf("finding: %s\n",symname.c_str()); + auto itr = macros.find(sym); + if (itr != macros.end()) + { + res = &itr->second; + } + } + return (res); +} + TSymbol * CLASS::findSymbol(std::string symname) { TSymbol *res = NULL; @@ -1160,7 +1191,7 @@ out: return (res); } -TSymbol * CLASS::addVariable(std::string symname, std::string val, bool replace) +TSymbol * CLASS::addVariable(std::string symname, std::string val, TVariable &vars, bool replace) { TSymbol *res = NULL; TSymbol *fnd = NULL; @@ -1172,7 +1203,7 @@ TSymbol * CLASS::addVariable(std::string symname, std::string val, bool replace) } //printf("addvariable\n"); - fnd = findVariable(sym); + fnd = findVariable(sym, vars); if ((fnd != NULL) && (!replace)) { @@ -1199,18 +1230,32 @@ TSymbol * CLASS::addVariable(std::string symname, std::string val, bool replace) //printf("addvariable: %s %s\n", s.name.c_str(), s.text.c_str()); std::pair p(sym, s); - variables.insert(p); - res = findVariable(sym); + vars.vars.insert(p); + res = findVariable(sym, vars); return (res); } -TSymbol * CLASS::findVariable(std::string symname) +TSymbol * CLASS::findVariable(std::string symname, TVariable &vars) { TSymbol *res = NULL; + if (!casesen) + { + symname = Poco::toUpper(symname); + } + + if ((expand_macrostack.size() > 0) && (vars.id != expand_macro.variables.id)) + { + res = findVariable(symname, expand_macro.variables); + if (res != NULL) + { + return (res); + } + } + //printf("finding: %s\n",symname.c_str()); - auto itr = variables.find(symname); - if (itr != variables.end()) + auto itr = vars.vars.find(symname); + if (itr != vars.vars.end()) { //printf("Found: %s 0x%08X\n",itr->second.name.c_str(),itr->second.value); res = &itr->second; @@ -1220,13 +1265,13 @@ TSymbol * CLASS::findVariable(std::string symname) return (res); } -void CLASS::showVariables(void) +void CLASS::showVariables(TVariable &vars) { - if (variables.size() > 0) + if (vars.vars.size() > 0) { printf("\nVariables:\n"); - for (auto itr = variables.begin(); itr != variables.end(); ++itr) + for (auto itr = vars.vars.begin(); itr != vars.vars.end(); ++itr) { printf("%-16s %s\n", itr->first.c_str(), itr->second.var_text.c_str()); } @@ -1287,12 +1332,62 @@ void CLASS::showSymbolTable(bool alpha) } } +// set alpha to true to print table sorted by name or +// false to print by value; +void CLASS::showMacros(bool alpha) +{ + if (macros.size() > 0) + { + std::map alphamap; + + int columns = getInt("asm.symcolumns", 3); + int column = columns; + + for (auto itr = macros.begin(); itr != macros.end(); itr++) + { + TMacro ptr = itr->second; + alphamap.insert(pair(ptr.name, 0)); + } + + if (alpha) + { + printf("\n\nmacros sorted alphabetically:\n\n"); + + for (auto itr = alphamap.begin(); itr != alphamap.end(); ++itr) + { + printf("%-16s 0x%08X ", itr->first.c_str(), itr->second); + if ( !--column ) + { + printf("\n"); + column = columns; + } + } + } + if (column > 0) + { + printf("\n"); + } + } +} + int CLASS::callOpCode(std::string op, MerlinLine &line) { int res = -1; char c; std::string s; + // 'op' is always lowercase here + +// during MACRO definition no opcodes are called (except for MAC, EOM, <<) + if (macrostack.size() > 0) + { + // if something on the macro stack, then a macro is being defined + if (!((op == "mac") || (op == "eom") || (op == "<<<"))) + { + return 0; + } + } + if (op.length() == 4) // check for 4 digit 'L' opcodes { c = op[3] & 0x7F; @@ -1342,10 +1437,10 @@ int CLASS::callOpCode(std::string op, MerlinLine &line) //line.expr_value = (line.expr_value >> 16) & 0xFFFF; break; case '|': - if (syntax==SYNTAX_MERLIN) - { + if (syntax == SYNTAX_MERLIN) + { line.setError(errBadLabel); - line.expr_value=0; + line.expr_value = 0; } break; } @@ -1557,12 +1652,15 @@ void CLASS::initpass(void) dumstartaddr = 0; dumstart = 0; truncdata = 0; - variables.clear(); // clear the variables for each pass + variables.vars.clear(); // clear the variables for each pass - macros.clear(); - while (!PCstack.empty()) + while (!macrostack.empty()) { - PCstack.pop(); + macrostack.pop(); + } + while (!expand_macrostack.empty()) + { + expand_macrostack.pop(); } while (!LUPstack.empty()) { @@ -1576,6 +1674,12 @@ void CLASS::initpass(void) { LSTstack.pop(); } + while (!PCstack.empty()) + { + PCstack.pop(); + } + currentmacro.clear(); + expand_macro.clear(); curLUP.clear(); curDO.clear(); } @@ -1629,8 +1733,10 @@ void CLASS::complete(void) { showSymbolTable(true); showSymbolTable(false); - showVariables(); + showVariables(variables); + showMacros(true); } + } int CLASS::evaluate(MerlinLine &line, std::string expr, int64_t &value) @@ -1877,7 +1983,16 @@ restart: off = mVec[0].offset; len = mVec[0].length; s = oper.substr(off, len); - sym = findVariable(s); + slen = s.length(); + sym = NULL; + if (expand_macrostack.size() > 0) + { + sym = findVariable(s, expand_macro.variables); + } + if (sym == NULL) + { + sym = findVariable(s, variables); + } if (sym != NULL) { //printf("match |%s|\n",sym->var_text.c_str()); @@ -1885,6 +2000,7 @@ restart: if (sym->var_text != "") { oper = oper.replace(off, len, sym->var_text); + slen = oper.length(); ct++; if (pass > 0) { @@ -1912,7 +2028,7 @@ restart: done = true; } } - //printf("inoper=|%s| outoper=|%s|\n",operin.c_str(),oper.c_str()); +//printf("inoper=|%s| outoper=|%s|\n",operin.c_str(),oper.c_str()); if (ct > 0) { outop = oper; @@ -1921,13 +2037,39 @@ restart: return (res); } +bool CLASS::doOFF(void) +{ + bool res = curDO.doskip; + std::stack tmpstack; + TDOstruct doitem; + + uint32_t ct = DOstack.size(); + if (ct > 0) + { + tmpstack = DOstack; + } + while (ct > 0) + { + doitem = tmpstack.top(); + tmpstack.pop(); + if (doitem.doskip) + { + res = true; + } + ct--; + } + //printf("DOOFF: %d\n",res); + return (res); +} + // this function determines if code generation is turned off (IF,DO,LUP,MAC, etc bool CLASS::codeSkipped(void) { bool res = false; res = (curLUP.lupskip) ? true : res; - res = (curDO.doskip) ? true : res; + res = doOFF() ? true : res; + res = currentmacro.running ? true : res; //printf("codeskip: %d\n",res); @@ -1952,7 +2094,7 @@ void CLASS::process(void) char c; char buff[256]; MerlinLine errLine; - std::string op, operand, ls; + std::string op, realop, operand, ls; pass = 0; while (pass < 2) @@ -1960,9 +2102,53 @@ void CLASS::process(void) initpass(); l = lines.size(); - while ((lineno < l) && (!passcomplete)) + bool passdone = false; + while ((!passdone) && (!passcomplete)) { - MerlinLine &line = lines[lineno]; + + MerlinLine *ml = NULL; + bool srcline = true; + if (expand_macro.running) + { + srcline = false; + if (expand_macro.currentline >= expand_macro.len) + { + // macro is complete + lineno = expand_macro.sourceline + 1; + if (expand_macrostack.size() > 0) + { + expand_macro = expand_macrostack.top(); + expand_macrostack.pop(); + } + else + { + expand_macro.clear(); + } + srcline = true; + } + else + { + ml = &expand_macro.lines[expand_macro.currentline]; + lineno = expand_macro.sourceline; + expand_macro.currentline++; + } + } + if (srcline) + { + if (lineno >= l) + { + passdone = true; + goto passout; + } + else + { + ml = &lines[lineno]; + } + } + + MerlinLine &line = *ml; + + //printf("lineno=%u %s\n", lineno, line.wholetext.c_str()); line.eval_result = 0; line.lineno = lineno + 1; @@ -1971,6 +2157,7 @@ void CLASS::process(void) //printf("lineno: %d %d |%s|\n",lineno,l,line.operand.c_str()); op = Poco::toLower(line.opcode); + realop = line.opcode; operand = Poco::toLower(line.operand); line.startpc = PC.currentpc; line.linemx = mx; @@ -1979,7 +2166,7 @@ void CLASS::process(void) line.syntax = syntax; line.merlinerrors = merlinerrors; - if ((line.lable != "")) + if ((line.lable != "") && (op != "mac")) { std::string lable = Poco::trim(line.lable); TSymbol *sym = NULL; @@ -1990,7 +2177,7 @@ void CLASS::process(void) case ']': sprintf(buff, "$%X", PC.currentpc); ls = buff; - sym = addVariable(line.lable, ls, true); + sym = addVariable(line.lable, ls, variables, true); //if (sym == NULL) { dupsym = true; } break; @@ -2018,13 +2205,16 @@ void CLASS::process(void) } } std::string outop; - if (pass == 0) + line.printoperand = line.operand; + + x = 0; + if (macrostack.size() == 0) { - line.printoperand = line.operand; + x = substituteVariables(line, outop); } - x = substituteVariables(line, outop); if (x > 0) { + line.printoperand = outop; line.operand = outop; } x = parseOperand(line); @@ -2050,7 +2240,88 @@ void CLASS::process(void) x = 0; if (op.length() > 0) { - x = callOpCode(op, line); + bool skipop = false; + if (doOFF()) + { + skipop = true; + if ((op == "fin") || (op == "else") || (op == "do") || (op == "if")) + { + skipop = false; + } + } + if (!skipop) + { + TMacro *mac = NULL; + bool inoperand = false; + if (macrostack.size() == 0) + { + mac = findMacro(realop); + if (mac == NULL) + { + if (op == ">>>") // specal merlin way of calling a macro + { + Poco::StringTokenizer tok(operand, ", ", Poco::StringTokenizer::TOK_TRIM | + Poco::StringTokenizer::TOK_IGNORE_EMPTY); + std::string s = ""; + if (tok.count() > 0) + { + s = tok[0]; + } + mac = findMacro(s); + inoperand = true; + } + } + } + if (mac == NULL) + { + x = callOpCode(op, line); + } + if (mac != NULL) + { + expand_macrostack.push(expand_macro); + expand_macro = *mac; + + expand_macro.lines.clear(); + //printf("mac start=%u end=%u\n", expand_macro.start, expand_macro.end); + for (uint32_t lc = expand_macro.start; lc < expand_macro.end; lc++) + { + //printf("pushing %s\n", lines[lc].wholetext.c_str()); + MerlinLine nl(lines[lc].wholetext); // create a new clean line (without errors,data) + expand_macro.lines.push_back(nl); + } + expand_macro.running = true; + expand_macro.sourceline = lineno; + expand_macro.variables.vars.clear(); + // set the variables for the macro here SGQ + + std::string parms = line.operand; + if (inoperand) + { + Poco::StringTokenizer tok(parms, ", ", Poco::StringTokenizer::TOK_TRIM | + Poco::StringTokenizer::TOK_IGNORE_EMPTY); + parms = ""; + if (tok.count() > 1) + { + parms = tok[1]; + } + } + Poco::StringTokenizer tok(parms, ",;", Poco::StringTokenizer::TOK_TRIM | + Poco::StringTokenizer::TOK_IGNORE_EMPTY); + + uint32_t ct = 0; + for (auto itr = tok.begin(); itr != tok.end(); ++itr) + { + //evaluate each of these strings, check for errors on pass 2 + std::string expr = *itr; + std::string v = "]" + Poco::NumberFormatter::format(ct + 1); + //printf("var: %s %s\n", v.c_str(), expr.c_str()); + addVariable(v, expr, expand_macro.variables, true); + ct++; + } + x = 0; + expand_macro.currentline = 0; + } + } } if ((x > 0) && (codeSkipped())) // has a psuedo-op turned off code generation? (LUP, IF, etc) @@ -2099,7 +2370,10 @@ void CLASS::process(void) { if ((line.pass0bytect != line.bytect) && (line.errorcode == 0)) { - line.setError(errBadByteCount); + if (expand_macrostack.size() == 0) // if macro expanding, you can't make this check + { + line.setError(errBadByteCount); + } } if (line.errorcode != 0) @@ -2114,7 +2388,7 @@ void CLASS::process(void) } lineno++; } - +passout: // end of file reached here, do some final checks #if 0 diff --git a/asm.h b/asm.h index 5a9573c..9f47d2e 100644 --- a/asm.h +++ b/asm.h @@ -144,6 +144,7 @@ enum syn_MAX }; + class TOriginSection { // SGQ - if you do something unusual here, be aware of copy constructor @@ -190,6 +191,7 @@ class MerlinLine public: uint32_t syntax; + std::string wholetext; std::string lable; std::string printlable; std::string printoperand; @@ -345,15 +347,48 @@ public: } }; +//typedef Poco::HashMap variable_t; + +class TVariable +{ +public: + uint32_t id; + Poco::HashMap vars; + TVariable() + { + // SGQ - must fix this so it is guaranteed unique for each one + id=rand(); + } +}; class TMacro { public: std::string name; std::string lcname; - uint32_t currentline; + TVariable variables; std::vector lines; - std::vector variables; + uint32_t start, end, currentline, len; + uint32_t sourceline; + bool running; + + TMacro() + { + clear(); + } + void clear(void) + { + name = ""; + lcname = ""; + variables.vars.clear(); + lines.clear(); + sourceline = 0; + currentline = 0; + len = 0; + start = 0; + end = 0; + running = false; + } }; class TPsuedoOp; @@ -385,13 +420,15 @@ public: std::string currentsymstr; std::vector lines; Poco::HashMap macros; - Poco::HashMapopcodes; + Poco::HashMap opcodes; Poco::HashMap symbols; - Poco::HashMap variables; + TVariable variables; TOriginSection PC; TLUPstruct curLUP; TDOstruct curDO; + TMacro currentmacro; + TMacro expand_macro; bool listing; uint8_t truncdata; // for the TR opcode @@ -399,7 +436,8 @@ public: std::stack LUPstack; std::stack DOstack; std::stack LSTstack; - std::stack curMacro; + std::stack macrostack; + std::stack expand_macrostack; TPsuedoOp *psuedoops; @@ -417,20 +455,26 @@ public: void pushopcode(std::string op, uint8_t opcode, uint16_t flags, TOpCallback cb); int callOpCode(std::string op, MerlinLine &line); + TMacro *findMacro(std::string sym); + TSymbol *findSymbol(std::string sym); TSymbol *addSymbol(std::string sym, uint32_t val, bool replace); - TSymbol *findVariable(std::string sym); - TSymbol *addVariable(std::string sym, std::string val, bool replace); + TSymbol *findVariable(std::string sym, TVariable &vars); + TSymbol *addVariable(std::string sym, std::string val, TVariable &vars, bool replace); void initpass(void); void showSymbolTable(bool alpha); - void showVariables(void); + void showMacros(bool alpha); + + void showVariables(TVariable &vars); int evaluate(MerlinLine &line, std::string expr, int64_t &value); int substituteVariables(MerlinLine & line, std::string &outop); bool codeSkipped(void); + bool doOFF(void); + int parseOperand(MerlinLine &line); int getAddrMode(MerlinLine &line); diff --git a/eval.cpp b/eval.cpp index 713ce9d..7dce58b 100644 --- a/eval.cpp +++ b/eval.cpp @@ -15,6 +15,7 @@ std::ostream& operator<<(std::ostream& os, const Token& token) CLASS::CLASS(T65816Asm &_asm) : assembler(_asm) { + allowMX = false; } CLASS::~CLASS() @@ -232,20 +233,30 @@ std::deque CLASS::shuntingYard(const std::deque& tokens) } else { - sym = assembler.findSymbol(token.str); - //printf("symbol find |%s| %p\n",token.str.c_str(),sym); - - if (sym != NULL) + std::string tok = Poco::toUpper(token.str); + if ((tok == "MX") && (allowMX)) { - sym->used = true; - sprintf(buff, "$%X", sym->value); - token.str = buff; + //printf("MX EVAL\n"); + sprintf(buff,"$%02X",assembler.mx&0x03); + token.str=buff;; } else { - setError(Token::unknownSymbolErr); - badsymbol = token.str; - token.str = "0"; + sym = assembler.findSymbol(token.str); + //printf("symbol find |%s| %p\n",token.str.c_str(),sym); + + if (sym != NULL) + { + sym->used = true; + sprintf(buff, "$%X", sym->value); + token.str = buff; + } + else + { + setError(Token::unknownSymbolErr); + badsymbol = token.str; + token.str = "0"; + } } } queue.push_back(token); diff --git a/eval.h b/eval.h index 73b6c54..f0ed9a2 100644 --- a/eval.h +++ b/eval.h @@ -68,6 +68,7 @@ protected: public: CLASS(T65816Asm &_asm); ~CLASS(); + bool allowMX; std::string badsymbol; std::deque shuntingYard(const std::deque& tokens); std::deque exprToTokens(const std::string& expr); diff --git a/merlintests.sh b/merlintests.sh index 9e89e71..ad97e50 100755 --- a/merlintests.sh +++ b/merlintests.sh @@ -1,5 +1,10 @@ #!/bin/bash +X= +if [ "$1""L" != "L" ] ; then + X=_$1 +fi + OUTDIR=./m32out rm -rf $OUTDIR @@ -18,7 +23,7 @@ for S in $SRC ; do BASE=${S/.S/} BASE=${BASE/.s/} cd ./testdata - merlin32 . $S 2>/dev/null >/dev/null + merlin32$X . $S 2>/dev/null >/dev/null #merlin32 . $S 2>/dev/null R=?$ diff --git a/opcodes.cpp b/opcodes.cpp index 72a8cb1..3ec3c6a 100644 --- a/opcodes.cpp +++ b/opcodes.cpp @@ -99,10 +99,10 @@ int CLASS::doEQU(MerlinLine &line, TSymbol &sym) char buff[32]; sprintf(buff, "$%08X", line.expr_value); std::string s1 = buff; - s = addVariable(line.lable, s1, true); + s = addVariable(line.lable, s1, variables,true); #else // do this if you want to do this more as a #define - s = addVariable(line.lable, line.operand, true); + s = addVariable(line.lable, line.operand, variables,true); #endif if (s != NULL) { @@ -846,6 +846,7 @@ void CLASS::insertOpcodes(void) pushopcode("DUM", P_DUM, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("DEND", P_DEND, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("AST", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); + pushopcode("CAS", P_CAS, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("CYC", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("DAT", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("EXP", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); @@ -885,9 +886,10 @@ void CLASS::insertOpcodes(void) pushopcode("SW", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("USR", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("XC", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doXC)); - pushopcode("MAC", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); - pushopcode("EOM", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); - pushopcode("<<<", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); + pushopcode("MAC", P_MAC, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); + pushopcode("EOM", P_MAC, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); + pushopcode("<<<", P_MAC, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); + pushopcode(">>>", P_MAC, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("ADC", 0x03, OP_STD | OP_A, OPHANDLER(&CLASS::doBase6502)); diff --git a/psuedo.cpp b/psuedo.cpp index ad9c43b..36b512e 100644 --- a/psuedo.cpp +++ b/psuedo.cpp @@ -36,6 +36,7 @@ int CLASS::doDO(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) UNUSED(opinfo); TEvaluator eval(a); + eval.allowMX = true; // allow the built in MX symbol int64_t eval_value = 0; uint8_t shift; @@ -130,6 +131,88 @@ out: return (res); } +int CLASS::doMAC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) +{ + UNUSED(opinfo); + + int res = 0; + int err = 0; + + std::string op = Poco::toUpper(line.opcode); + if (op == "MAC") + { + if (a.expand_macrostack.size() > 0) + { + line.flags |= FLAG_NOLINEPRINT; + goto out; + } + if (line.lable.length() == 0) + { + err = errBadLabel; + goto out; + } + a.macrostack.push(a.currentmacro); + a.currentmacro.clear(); + + a.currentmacro.name = line.lable; + a.currentmacro.lcname = Poco::toLower(line.lable); + a.currentmacro.start = line.lineno; + a.currentmacro.running = true; + + if (!a.casesen) + { + a.currentmacro.name = Poco::toUpper(a.currentmacro.name); + } + + if (a.pass == 0) + { + } + else + { + // don't need to do anything on pass > 0 + } + //printf("macro stack size=%zu\n",a.macrostack.size()); + } + else if (op == ">>>") + { + // don't do anything here, let the macro call handler stuff do ths (asm.cpp) + } + else // it is EOM or <<< + { + while (a.macrostack.size() > 0) + { + a.currentmacro.end = line.lineno - 1; + a.currentmacro.len = 0; + if (a.currentmacro.end >= a.currentmacro.start) + { + a.currentmacro.len = a.currentmacro.end - a.currentmacro.start; + //printf("macro len=%d\n",a.currentmacro.len); + } + a.currentmacro.running = false; + + std::pair p(a.currentmacro.name, a.currentmacro); + //printf("macro insert %s\n",a.currentmacro.name.c_str()); + a.macros.insert(p); + + a.currentmacro = a.macrostack.top(); + a.macrostack.pop(); + } +#if 0 + else + { + err = errUnexpectedOp; + goto out; + } +#endif + } +out: + if (err) + { + line.setError(err); + } + return (res); +} + int CLASS::doLUP(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) { UNUSED(opinfo); @@ -157,7 +240,14 @@ int CLASS::doLUP(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) a.LUPstack.push(a.curLUP); - a.curLUP.lupoffset = len; + if (a.expand_macrostack.size() > 0) + { + a.curLUP.lupoffset = a.expand_macro.currentline; + } + else + { + a.curLUP.lupoffset = len; + } a.curLUP.lupct = eval_value & 0xFFFF; // evaluate here a.curLUP.luprunning++; @@ -180,6 +270,8 @@ int CLASS::doLUP(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) if (a.curLUP.luprunning > 0) { + + lidx = line.lineno - 1; len = lidx - a.curLUP.lupoffset - 1; @@ -188,7 +280,14 @@ int CLASS::doLUP(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) a.curLUP.lupct--; if (a.curLUP.lupct != 0) { - a.lineno = a.curLUP.lupoffset; + if (a.expand_macrostack.size() > 0) + { + a.expand_macro.currentline = a.curLUP.lupoffset; + } + else + { + a.lineno = a.curLUP.lupoffset; + } goto out; } } @@ -215,7 +314,6 @@ int CLASS::doLUP(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) //err = errUnexpectedOp; } } - out: if (err > 0) { @@ -340,6 +438,8 @@ int CLASS::doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) return (outct); } + + int CLASS::doDS(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) { UNUSED(opinfo); @@ -352,7 +452,7 @@ int CLASS::doDS(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) uint8_t shift; line.eval_result = 0; // since this is an data p-op, clear the global 'bad operand' flag - line.flags|=FLAG_FORCEADDRPRINT; + line.flags |= FLAG_FORCEADDRPRINT; std::string s; Poco::StringTokenizer tok(line.operand, ",", Poco::StringTokenizer::TOK_TRIM | Poco::StringTokenizer::TOK_IGNORE_EMPTY); @@ -418,11 +518,11 @@ int CLASS::doDS(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) v = datact; if (pagefill) { - v=line.startpc&0xFF; - v=0x100-v; + v = line.startpc & 0xFF; + v = 0x100 - v; } line.datafillct = (uint16_t)v & 0xFFFF; - res=line.datafillct; + res = line.datafillct; out: //printf("res=%d %04X\n",res,res); @@ -810,6 +910,7 @@ int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) int CLASS::ProcessOpcode(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) { int res = 0; + std::string s; switch (opinfo.opcode) { @@ -846,12 +947,12 @@ int CLASS::ProcessOpcode(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) #if 0 // Merlin32 seems to have a bug where ORG seems like it can only be 16 bits - if ((line.syntax&SYNTAX_MERLIN32)==SYNTAX_MERLIN32) + if ((line.syntax & SYNTAX_MERLIN32) == SYNTAX_MERLIN32) { // so clear the bank word in all variables a.PC.orgsave &= 0xFFFF; - a.PC.currentpc&=0xFFFF; - line.startpc &=0xFFFF; + a.PC.currentpc &= 0xFFFF; + line.startpc &= 0xFFFF; } #endif @@ -860,16 +961,31 @@ int CLASS::ProcessOpcode(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) case P_SAV: a.savepath = a.processFilename(line.operand, Poco::Path::current(), 0); break; - case P_ERR: - if (a.pass>0) + case P_CAS: + s = Poco::toUpper(line.operand); + if (s == "SE") { - if ((line.expr_value!=0) || (line.eval_result<0)) + a.casesen = true; + } + if (s=="IN") + { + a.casesen=false; + } + res = 0; + break; + case P_MAC: + res = doMAC(a, line, opinfo); + break; + case P_ERR: + if (a.pass > 0) + { + if ((line.expr_value != 0) || (line.eval_result < 0)) { line.setError(errErrOpcode); //a.passcomplete=true; // terminate assembly } } - res=0; + res = 0; break; case P_LST: res = doLST(a, line, opinfo); diff --git a/psuedo.h b/psuedo.h index 5d86908..809cb54 100644 --- a/psuedo.h +++ b/psuedo.h @@ -20,6 +20,8 @@ enum P_TR, P_ASC, P_ERR, + P_MAC, + P_CAS, P_MAX }; @@ -41,6 +43,8 @@ public: int doDO(T65816Asm &a, MerlinLine &line, TSymbol &opinfo); int doTR(T65816Asm &a, MerlinLine &line, TSymbol &opinfo); int doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo); + int doMAC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo); + }; #undef CLASS diff --git a/testdata/1000-allops-value-65816.S b/testdata/1000-allops-value-65816.S index 2439293..dc67504 100644 --- a/testdata/1000-allops-value-65816.S +++ b/testdata/1000-allops-value-65816.S @@ -5,7 +5,7 @@ ZP EQU $FF ABS EQU $FEFF LONG EQU $FDFEFF -MV0 EQU ZP ;Merlin 32 bug -- must use 8-bit constant, or -MV1 EQU ZP-1 ; '^' modifier is implicitly applied +MV0 EQU LONG ;Merlin 32 bug -- must use 8-bit constant, or +MV1 EQU LONG-$10000 ; '^' modifier is implicitly applied PUT allops-common-65816.S diff --git a/testdata/3000-addresses.S b/testdata/3000-addresses.S index 5b29154..d99592b 100644 --- a/testdata/3000-addresses.S +++ b/testdata/3000-addresses.S @@ -23,6 +23,6 @@ start nop lda #long lda #^long - lda #|long + lda #long lst off