This commit is contained in:
Lane Roathe 2019-11-23 09:24:28 -08:00
commit d78c8612f9
10 changed files with 531 additions and 74 deletions

340
asm.cpp
View File

@ -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<std::string, TSymbol> 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<std::string, uint32_t> 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<std::string, uint32_t>(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<TDOstruct> 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

60
asm.h
View File

@ -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<std::string, TSymbol> variable_t;
class TVariable
{
public:
uint32_t id;
Poco::HashMap<std::string, TSymbol> 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<MerlinLine> lines;
std::vector<std::string> 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<MerlinLine> lines;
Poco::HashMap<std::string, TMacro> macros;
Poco::HashMap<std::string, TSymbol>opcodes;
Poco::HashMap<std::string, TSymbol> opcodes;
Poco::HashMap<std::string, TSymbol> symbols;
Poco::HashMap<std::string, TSymbol> 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<TLUPstruct> LUPstack;
std::stack<TDOstruct> DOstack;
std::stack<bool> LSTstack;
std::stack<TMacro> curMacro;
std::stack<TMacro> macrostack;
std::stack<TMacro> 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);

View File

@ -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<Token> CLASS::shuntingYard(const std::deque<Token>& 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);

1
eval.h
View File

@ -68,6 +68,7 @@ protected:
public:
CLASS(T65816Asm &_asm);
~CLASS();
bool allowMX;
std::string badsymbol;
std::deque<Token> shuntingYard(const std::deque<Token>& tokens);
std::deque<Token> exprToTokens(const std::string& expr);

View File

@ -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=?$

View File

@ -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));

View File

@ -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<std::string, TMacro> 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);

View File

@ -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

View File

@ -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

View File

@ -23,6 +23,6 @@ start nop
lda #<long
lda #>long
lda #^long
lda #|long
lda #long
lst off