mirror of https://github.com/marketideas/qasm.git
might be broken, work on addressing modes and shift operators < > | ^
This commit is contained in:
parent
88e0251a16
commit
4380f4e8ca
|
@ -9,8 +9,8 @@
|
||||||
"program": "${workspaceFolder}/build/qasm",
|
"program": "${workspaceFolder}/build/qasm",
|
||||||
"args": [
|
"args": [
|
||||||
"${workspaceFolder}/test.s",
|
"${workspaceFolder}/test.s",
|
||||||
"-s",
|
"-d",
|
||||||
"-d"
|
"-l"
|
||||||
],
|
],
|
||||||
"stopAtEntry": false,
|
"stopAtEntry": false,
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}",
|
||||||
|
|
270
asm.cpp
270
asm.cpp
|
@ -11,12 +11,12 @@
|
||||||
#define CLASS MerlinLine
|
#define CLASS MerlinLine
|
||||||
|
|
||||||
|
|
||||||
CLASS::CLASS(ConfigOptions &opt) //: options(opt)
|
CLASS::CLASS(ConfigOptions &opt) : options(&opt)
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
CLASS::CLASS(std::string line, ConfigOptions &opt) //: options(opt)
|
CLASS::CLASS(std::string line, ConfigOptions &opt) : options(&opt)
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
set(line);
|
set(line);
|
||||||
|
@ -68,11 +68,17 @@ void CLASS::print(uint32_t lineno)
|
||||||
|
|
||||||
bool np=(flags & FLAG_NOLINEPRINT)?true:false;
|
bool np=(flags & FLAG_NOLINEPRINT)?true:false;
|
||||||
if (options->isQuiet())
|
if (options->isQuiet())
|
||||||
|
{
|
||||||
np=true;
|
np=true;
|
||||||
|
}
|
||||||
if (options->isList())
|
if (options->isList())
|
||||||
np=false;
|
{
|
||||||
if (force)
|
|
||||||
np=false;
|
np=false;
|
||||||
|
}
|
||||||
|
if (force)
|
||||||
|
{
|
||||||
|
np=false;
|
||||||
|
}
|
||||||
if (np)
|
if (np)
|
||||||
{
|
{
|
||||||
return;
|
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());
|
//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))
|
if ((errorcode > 0) && (!merlinerrors))
|
||||||
{
|
{
|
||||||
while (pcol < commentcol)
|
while (pcol < commentcol)
|
||||||
|
@ -245,7 +253,7 @@ void CLASS::print(uint32_t lineno)
|
||||||
|
|
||||||
if ((options->useColor()) && (errorcode > 0))
|
if ((options->useColor()) && (errorcode > 0))
|
||||||
{
|
{
|
||||||
SetColor(CL_NORMAL | BG_NORMAL);
|
SetColor(CL_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t obc = datafillct;
|
uint32_t obc = datafillct;
|
||||||
|
@ -297,6 +305,7 @@ void CLASS::print(uint32_t lineno)
|
||||||
|
|
||||||
void CLASS::clear()
|
void CLASS::clear()
|
||||||
{
|
{
|
||||||
|
shiftchar=0;
|
||||||
wholetext = "";
|
wholetext = "";
|
||||||
lable = "";
|
lable = "";
|
||||||
printlable = "";
|
printlable = "";
|
||||||
|
@ -305,6 +314,7 @@ void CLASS::clear()
|
||||||
operand = "";
|
operand = "";
|
||||||
printoperand = "";
|
printoperand = "";
|
||||||
orig_operand="";
|
orig_operand="";
|
||||||
|
strippedoperand="";
|
||||||
comment = "";
|
comment = "";
|
||||||
operand_expr = "";
|
operand_expr = "";
|
||||||
operand_expr2 = "";
|
operand_expr2 = "";
|
||||||
|
@ -317,16 +327,15 @@ void CLASS::clear()
|
||||||
startpc = 0;
|
startpc = 0;
|
||||||
errorcode = 0;
|
errorcode = 0;
|
||||||
errorText = "";
|
errorText = "";
|
||||||
outbytect = 0;
|
|
||||||
datafillct = 0;
|
datafillct = 0;
|
||||||
datafillbyte = 0;
|
datafillbyte = 0;
|
||||||
lineno = 0;
|
lineno = 0;
|
||||||
outbytes.clear();
|
|
||||||
addressmode = 0;
|
addressmode = 0;
|
||||||
expr_value = 0;
|
expr_value = 0;
|
||||||
eval_result = 0;
|
eval_result = 0;
|
||||||
flags = 0;
|
flags = 0;
|
||||||
outbytes.clear();
|
outbytes.clear();
|
||||||
|
outbytect = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string operEx[] =
|
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)
|
void CLASS::errorOut(uint16_t code)
|
||||||
|
@ -614,7 +623,7 @@ void CLASS::complete(void)
|
||||||
//cout << "Processing Time: " << n - starttime << "ms" << endl;
|
//cout << "Processing Time: " << n - starttime << "ms" << endl;
|
||||||
uint64_t x = n - starttime;
|
uint64_t x = n - starttime;
|
||||||
uint32_t x1 = x & 0xFFFFFFFF;
|
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);
|
printf("Elapsed time: %u ms\n", x1);
|
||||||
}
|
}
|
||||||
|
@ -1639,7 +1648,7 @@ int CLASS::callOpCode(std::string op, MerlinLine &line)
|
||||||
break;
|
break;
|
||||||
case '>':
|
case '>':
|
||||||
#if 0
|
#if 0
|
||||||
if ((syntax & SYNTAX_MERLIN32) == SYNTAX_MERLIN32)
|
if (options.isMerlin32())
|
||||||
{
|
{
|
||||||
// bug in M32 or not, do what it does
|
// bug in M32 or not, do what it does
|
||||||
line.flags |= FLAG_FORCEABS;
|
line.flags |= FLAG_FORCEABS;
|
||||||
|
@ -1768,16 +1777,17 @@ void CLASS::initpass(void)
|
||||||
showmx = getBool("asm.showmx", true);
|
showmx = getBool("asm.showmx", true);
|
||||||
merlinerrors = getBool("asm.merlinerrors", true);
|
merlinerrors = getBool("asm.merlinerrors", true);
|
||||||
|
|
||||||
|
outputbytes.clear();
|
||||||
trackrep = getBool("asm.trackrep", false);
|
trackrep = getBool("asm.trackrep", false);
|
||||||
if (syntax == SYNTAX_MERLIN32)
|
if (options.isMerlin32())
|
||||||
{
|
{
|
||||||
trackrep = true; // can't turn this off in M32
|
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
|
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
|
// we will allow this to be settable default off
|
||||||
trackrep = false;
|
trackrep = false;
|
||||||
|
@ -1797,28 +1807,33 @@ void CLASS::initpass(void)
|
||||||
s = getConfig("asm.cpu", "M6502");
|
s = getConfig("asm.cpu", "M6502");
|
||||||
s = Poco::trim(Poco::toUpper(s));
|
s = Poco::trim(Poco::toUpper(s));
|
||||||
|
|
||||||
cpumode = MODE_65816;
|
s=PAL::getString("option.instruction","");
|
||||||
mx = 0x03;
|
if (s!="")
|
||||||
|
|
||||||
if (s == "M65816")
|
|
||||||
{
|
{
|
||||||
|
printf("CPU command line %s\n",s.c_str());
|
||||||
cpumode = MODE_65816;
|
cpumode = MODE_65816;
|
||||||
mx = 0x03;
|
mx = 0x03;
|
||||||
}
|
|
||||||
else if (s == "M65C02")
|
if (s == "M65816")
|
||||||
{
|
{
|
||||||
cpumode = MODE_65C02;
|
cpumode = MODE_65816;
|
||||||
mx = 0x03;
|
mx = 0x03;
|
||||||
}
|
}
|
||||||
else if (s == "M6502")
|
else if (s == "M65C02")
|
||||||
{
|
{
|
||||||
cpumode = MODE_6502;
|
cpumode = MODE_65C02;
|
||||||
mx = 0x03;
|
mx = 0x03;
|
||||||
}
|
}
|
||||||
else
|
else if (s == "M6502")
|
||||||
{
|
{
|
||||||
printf("Unknown CPU type in .ini\n");
|
cpumode = MODE_6502;
|
||||||
mx = 0x03;
|
mx = 0x03;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Unknown CPU type in .ini\n");
|
||||||
|
mx = 0x03;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mx = getInt("asm.startmx", mx);;
|
mx = getInt("asm.startmx", mx);;
|
||||||
|
|
||||||
|
@ -1829,7 +1844,7 @@ void CLASS::initpass(void)
|
||||||
lastcarry = false;
|
lastcarry = false;
|
||||||
relocatable = false;
|
relocatable = false;
|
||||||
currentsym = NULL;
|
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
|
// 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;
|
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)
|
void CLASS::complete(void)
|
||||||
{
|
{
|
||||||
|
bool writeerr=false;
|
||||||
if (savepath != "")
|
if (savepath != "")
|
||||||
{
|
{
|
||||||
if (errorct == 0)
|
if (errorct == 0)
|
||||||
{
|
{
|
||||||
std::string currentdir = Poco::Path::current();
|
std::string currentdir = Poco::Path::current();
|
||||||
|
|
||||||
savepath = processFilename(savepath, currentdir, 0);
|
//savepath = processFilename(savepath, currentdir, 0);
|
||||||
|
savepath=options.formatPath(savepath);
|
||||||
if (!options.isQuiet())
|
if (!options.isQuiet())
|
||||||
{
|
{
|
||||||
printf("saving to file: %s\n", savepath.c_str());
|
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;
|
if (f.is_open())
|
||||||
uint32_t l = (uint32_t)lines.size();
|
|
||||||
while (lineno < l)
|
|
||||||
{
|
{
|
||||||
MerlinLine &line = lines.at(lineno++);
|
#if 0
|
||||||
if ((line.outbytect > 0) && ((line.flags & FLAG_INDUM) == 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))
|
||||||
if ((line.datafillct > 0) && ((line.flags & FLAG_INDUM) == 0))
|
|
||||||
{
|
|
||||||
for (uint32_t i = 0; i < line.datafillct; i++)
|
|
||||||
{
|
{
|
||||||
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<outputbytes.size(); i++)
|
||||||
|
{
|
||||||
|
f.put(outputbytes[i]);
|
||||||
|
}
|
||||||
|
f.flush();
|
||||||
|
//printf("outbytect=%ld\n",outputbytes.size());
|
||||||
|
|
||||||
|
if (f.fail())
|
||||||
|
{
|
||||||
|
writeerr=true;
|
||||||
|
}
|
||||||
|
f.close();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
writeerr=true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf("\nErrors in assembly. Output not SAVED.\n\n");
|
printf("\nErrors in assembly. Output not SAVED.\n\n");
|
||||||
}
|
}
|
||||||
|
if (writeerr)
|
||||||
|
{
|
||||||
|
printf("unable to save file.\n"); // TODO SGQ need to push error up the so exit code is non-zero
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ((!options.isQuiet()) || (options.isList()))
|
if ((!options.isQuiet()) || (options.isList()))
|
||||||
{
|
{
|
||||||
|
@ -2001,12 +2046,77 @@ int CLASS::getAddrMode(MerlinLine & line)
|
||||||
int idx, x;
|
int idx, x;
|
||||||
std::string s, oper;
|
std::string s, oper;
|
||||||
std::vector<std::string> groups;
|
std::vector<std::string> groups;
|
||||||
|
char shiftchar;
|
||||||
|
|
||||||
oper = line.operand;
|
oper = line.operand;
|
||||||
|
int l=oper.length();
|
||||||
if ((line.opcode.length() == 0) || (line.operand.length() == 0))
|
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;
|
idx = 0;
|
||||||
|
@ -2136,9 +2246,35 @@ int CLASS::parseOperand(MerlinLine & line)
|
||||||
{
|
{
|
||||||
//errorOut(errBadAddressMode);
|
//errorOut(errBadAddressMode);
|
||||||
}
|
}
|
||||||
|
printf("addressmode=%d %s\n",res,addrModeEnglish(res).c_str());
|
||||||
return (res);
|
return (res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string CLASS::addrModeEnglish(int mode)
|
||||||
|
{
|
||||||
|
string res="<none>";
|
||||||
|
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 CLASS::substituteVariables(MerlinLine & line, std::string &outop)
|
||||||
{
|
{
|
||||||
int res = 0;
|
int res = 0;
|
||||||
|
@ -2580,6 +2716,24 @@ void CLASS::process(void)
|
||||||
line.errorText = line.operand_expr;
|
line.errorText = line.operand_expr;
|
||||||
}
|
}
|
||||||
line.bytect = x;
|
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; i<line.outbytes.size(); i++)
|
||||||
|
{
|
||||||
|
outputbytes.push_back(line.outbytes[i]);
|
||||||
|
}
|
||||||
|
if (line.datafillct>0)
|
||||||
|
{
|
||||||
|
for (int i=0; i<line.datafillct; i++)
|
||||||
|
{
|
||||||
|
outputbytes.push_back(line.datafillbyte);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PC.currentpc += x;
|
PC.currentpc += x;
|
||||||
PC.totalbytes += x;
|
PC.totalbytes += x;
|
||||||
}
|
}
|
||||||
|
@ -2623,6 +2777,9 @@ void CLASS::process(void)
|
||||||
line.print(lineno);
|
line.print(lineno);
|
||||||
}
|
}
|
||||||
skiplist = false;
|
skiplist = false;
|
||||||
|
line.outbytes.clear(); // clear the outbytes on the line so LUP works correctly
|
||||||
|
line.outbytect=0;
|
||||||
|
|
||||||
}
|
}
|
||||||
lineno++;
|
lineno++;
|
||||||
}
|
}
|
||||||
|
@ -2654,15 +2811,6 @@ int CLASS::doline(int lineno, std::string line)
|
||||||
MerlinLine l(line,options);
|
MerlinLine l(line,options);
|
||||||
|
|
||||||
op = Poco::toLower(l.opcode);
|
op = Poco::toLower(l.opcode);
|
||||||
if (op == "merlin")
|
|
||||||
{
|
|
||||||
syntax = SYNTAX_MERLIN;
|
|
||||||
}
|
|
||||||
else if (op == "orca")
|
|
||||||
{
|
|
||||||
syntax = SYNTAX_ORCA;
|
|
||||||
}
|
|
||||||
//l.syntax = syntax;
|
|
||||||
lines.push_back(l);
|
lines.push_back(l);
|
||||||
|
|
||||||
if ((op == "use") || (op == "put"))
|
if ((op == "use") || (op == "put"))
|
||||||
|
|
12
asm.h
12
asm.h
|
@ -37,6 +37,7 @@ enum asmErrors
|
||||||
{
|
{
|
||||||
errNone,
|
errNone,
|
||||||
errWarn,
|
errWarn,
|
||||||
|
errDebug,
|
||||||
errIncomplete,
|
errIncomplete,
|
||||||
errUnimplemented,
|
errUnimplemented,
|
||||||
errFatal,
|
errFatal,
|
||||||
|
@ -72,6 +73,7 @@ const std::string errStrings[errMAX + 1] =
|
||||||
{
|
{
|
||||||
"No Error",
|
"No Error",
|
||||||
"Warning",
|
"Warning",
|
||||||
|
"Debug Error",
|
||||||
"Unfinished Opcode",
|
"Unfinished Opcode",
|
||||||
"Unimplemented Instruction",
|
"Unimplemented Instruction",
|
||||||
"Fatal",
|
"Fatal",
|
||||||
|
@ -181,6 +183,7 @@ public:
|
||||||
std::string lable;
|
std::string lable;
|
||||||
std::string printlable;
|
std::string printlable;
|
||||||
std::string printoperand;
|
std::string printoperand;
|
||||||
|
std::string strippedoperand;
|
||||||
std::string opcode;
|
std::string opcode;
|
||||||
std::string opcodelower;
|
std::string opcodelower;
|
||||||
std::string orig_operand;
|
std::string orig_operand;
|
||||||
|
@ -189,6 +192,7 @@ public:
|
||||||
std::string operand_expr2;
|
std::string operand_expr2;
|
||||||
std::string comment;
|
std::string comment;
|
||||||
std::string addrtext;
|
std::string addrtext;
|
||||||
|
char shiftchar;
|
||||||
uint8_t linemx;
|
uint8_t linemx;
|
||||||
uint8_t tabs[16];
|
uint8_t tabs[16];
|
||||||
bool showmx;
|
bool showmx;
|
||||||
|
@ -228,7 +232,7 @@ protected:
|
||||||
int win_rows;
|
int win_rows;
|
||||||
std::string initialdir;
|
std::string initialdir;
|
||||||
std::vector<std::string> filenames;
|
std::vector<std::string> filenames;
|
||||||
uint32_t syntax;
|
//uint32_t syntax;
|
||||||
uint64_t starttime;
|
uint64_t starttime;
|
||||||
uint8_t tabs[16];
|
uint8_t tabs[16];
|
||||||
|
|
||||||
|
@ -249,7 +253,7 @@ public:
|
||||||
virtual void process(void);
|
virtual void process(void);
|
||||||
virtual void complete(void);
|
virtual void complete(void);
|
||||||
virtual void errorOut(uint16_t code);
|
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
|
class T65816Asm : public TFileProcessor
|
||||||
{
|
{
|
||||||
|
protected:
|
||||||
|
std::vector<uint8_t> outputbytes;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// options
|
// options
|
||||||
bool casesen;
|
bool casesen;
|
||||||
|
@ -486,6 +493,7 @@ public:
|
||||||
|
|
||||||
int parseOperand(MerlinLine &line);
|
int parseOperand(MerlinLine &line);
|
||||||
int getAddrMode(MerlinLine &line);
|
int getAddrMode(MerlinLine &line);
|
||||||
|
string addrModeEnglish(int mode);
|
||||||
void setOpcode(MerlinLine &line, uint8_t op);
|
void setOpcode(MerlinLine &line, uint8_t op);
|
||||||
|
|
||||||
|
|
||||||
|
|
2
eval.cpp
2
eval.cpp
|
@ -607,7 +607,7 @@ int CLASS::evaluate(std::string & e, int64_t &res, uint8_t &_shiftmode)
|
||||||
std::string expr = Poco::trim(e);
|
std::string expr = Poco::trim(e);
|
||||||
expr += " "; // add a space at end to make parsing easier
|
expr += " "; // add a space at end to make parsing easier
|
||||||
|
|
||||||
if (isDebug() >= 1)
|
if (isDebug() >= 3)
|
||||||
{
|
{
|
||||||
printf("eval: expression: |%s|\n", expr.c_str());
|
printf("eval: expression: |%s|\n", expr.c_str());
|
||||||
}
|
}
|
||||||
|
|
289
opcodes.cpp
289
opcodes.cpp
|
@ -7,6 +7,7 @@ void CLASS::setOpcode(MerlinLine &line, uint8_t op)
|
||||||
{
|
{
|
||||||
if (pass > 0)
|
if (pass > 0)
|
||||||
{
|
{
|
||||||
|
//printf("cpumode=%d\n",cpumode);
|
||||||
if (cpumode < MODE_65816) // instructions are valid if we are in 65816
|
if (cpumode < MODE_65816) // instructions are valid if we are in 65816
|
||||||
{
|
{
|
||||||
uint8_t m = opCodeCompatibility[op];
|
uint8_t m = opCodeCompatibility[op];
|
||||||
|
@ -40,6 +41,15 @@ int CLASS::doXC(MerlinLine &line, TSymbol &sym)
|
||||||
std::string s;
|
std::string s;
|
||||||
int res = 0;
|
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)
|
if (cpumode < MODE_65816)
|
||||||
{
|
{
|
||||||
cpumode++;
|
cpumode++;
|
||||||
|
@ -203,7 +213,7 @@ int CLASS::doMVN(MerlinLine &line, TSymbol &sym)
|
||||||
// these bytes are the two bank registers
|
// these bytes are the two bank registers
|
||||||
|
|
||||||
if (options.isMerlin32() && (v<256))
|
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
|
// merlin32 uses the low byte of the two operands
|
||||||
line.outbytes.push_back((v) & 0xFF);
|
line.outbytes.push_back((v) & 0xFF);
|
||||||
|
@ -248,40 +258,40 @@ int CLASS::doNoPattern(MerlinLine &line, TSymbol &sym)
|
||||||
|
|
||||||
switch (sym.opcode)
|
switch (sym.opcode)
|
||||||
{
|
{
|
||||||
case 1: // STZ
|
case 1: // STZ
|
||||||
res++;
|
res++;
|
||||||
op = (m == syn_abs ? 0x64 : op);
|
op = (m == syn_abs ? 0x64 : op);
|
||||||
op = (m == syn_absx ? 0x74 : 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;
|
|
||||||
op = (op == 0x74) ? 0x9E : op;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 2: // TSB
|
|
||||||
res++;
|
res++;
|
||||||
op = (m == syn_abs ? 0x04 : op);
|
op = (op == 0x64) ? 0x9C : op;
|
||||||
if ((op != 0) && ((line.expr_value >= 0x100) || (line.flags & FLAG_FORCEABS)))
|
op = (op == 0x74) ? 0x9E : op;
|
||||||
{
|
}
|
||||||
res++;
|
break;
|
||||||
op = 0x0C;
|
case 2: // TSB
|
||||||
}
|
res++;
|
||||||
break;
|
op = (m == syn_abs ? 0x04 : op);
|
||||||
case 3: // TRB
|
if ((op != 0) && ((line.expr_value >= 0x100) || (line.flags & FLAG_FORCEABS)))
|
||||||
|
{
|
||||||
res++;
|
res++;
|
||||||
op = (m == syn_abs ? 0x14 : op);
|
op = 0x0C;
|
||||||
if ((op != 0) && ((line.expr_value >= 0x100) || (line.flags & FLAG_FORCEABS)))
|
}
|
||||||
{
|
break;
|
||||||
res++;
|
case 3: // TRB
|
||||||
op = 0x1C;
|
res++;
|
||||||
}
|
op = (m == syn_abs ? 0x14 : op);
|
||||||
break;
|
if ((op != 0) && ((line.expr_value >= 0x100) || (line.flags & FLAG_FORCEABS)))
|
||||||
default:
|
{
|
||||||
op = 0;
|
res++;
|
||||||
err = errBadOpcode;
|
op = 0x1C;
|
||||||
break;
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
op = 0;
|
||||||
|
err = errBadOpcode;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (op == 0x00)
|
if (op == 0x00)
|
||||||
|
@ -316,15 +326,15 @@ int CLASS::doAddress(MerlinLine &line, TSymbol &sym)
|
||||||
//}
|
//}
|
||||||
switch(line.expr_shift)
|
switch(line.expr_shift)
|
||||||
{
|
{
|
||||||
case '^':
|
case '^':
|
||||||
line.expr_value=(line.expr_value>>16)&0xFFFF;
|
line.expr_value=(line.expr_value>>16)&0xFFFF;
|
||||||
break;
|
break;
|
||||||
case '<':
|
case '<':
|
||||||
line.expr_value=(line.expr_value)&0xFF;
|
line.expr_value=(line.expr_value)&0xFF;
|
||||||
break;
|
break;
|
||||||
case '>':
|
case '>':
|
||||||
line.expr_value=(line.expr_value>>8)&0xFFFF;
|
line.expr_value=(line.expr_value>>8)&0xFFFF;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//line.setError(errIncomplete);
|
//line.setError(errIncomplete);
|
||||||
|
@ -347,12 +357,12 @@ int CLASS::doAddress(MerlinLine &line, TSymbol &sym)
|
||||||
uint8_t newmx = (line.expr_value & 0x30) >> 4;
|
uint8_t newmx = (line.expr_value & 0x30) >> 4;
|
||||||
switch (sym.opcode)
|
switch (sym.opcode)
|
||||||
{
|
{
|
||||||
case 0xC2: // REP
|
case 0xC2: // REP
|
||||||
mx &= ~newmx;
|
mx &= ~newmx;
|
||||||
break;
|
break;
|
||||||
case 0xE2: // SEP
|
case 0xE2: // SEP
|
||||||
mx |= newmx;
|
mx |= newmx;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
line.linemx = mx;
|
line.linemx = mx;
|
||||||
}
|
}
|
||||||
|
@ -544,21 +554,21 @@ int CLASS::doBase6502(MerlinLine & line, TSymbol & sym)
|
||||||
int add = 0;
|
int add = 0;
|
||||||
switch (sym.opcode)
|
switch (sym.opcode)
|
||||||
{
|
{
|
||||||
case 7: // CPX
|
case 7: // CPX
|
||||||
case 6: // CPY
|
case 6: // CPY
|
||||||
case 5: // LDY
|
case 5: // LDY
|
||||||
case 4: // STY
|
case 4: // STY
|
||||||
if ((mx & 0x01) == 0)
|
if ((mx & 0x01) == 0)
|
||||||
{
|
{
|
||||||
add = 1;
|
add = 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1: // BIT
|
case 1: // BIT
|
||||||
if ((mx & 0x02) == 0)
|
if ((mx & 0x02) == 0)
|
||||||
{
|
{
|
||||||
add = 1;
|
add = 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
bytelen += add;
|
bytelen += add;
|
||||||
|
@ -571,34 +581,55 @@ int CLASS::doBase6502(MerlinLine & line, TSymbol & sym)
|
||||||
{
|
{
|
||||||
switch (m)
|
switch (m)
|
||||||
{
|
{
|
||||||
case syn_diix: amode = 0; break;
|
case syn_diix:
|
||||||
case syn_abs: amode = 1; break;
|
amode = 0;
|
||||||
case syn_imm: amode = 2; break;
|
break;
|
||||||
case syn_diiy: amode = 4; break;
|
case syn_abs:
|
||||||
case syn_absx: amode = 5; break;
|
amode = 1;
|
||||||
case syn_absy: amode = 6; break;
|
break;
|
||||||
default:
|
case syn_imm:
|
||||||
err = true;
|
amode = 2;
|
||||||
break;
|
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)
|
else if (cc == 0x02)
|
||||||
{
|
{
|
||||||
switch (m)
|
switch (m)
|
||||||
{
|
{
|
||||||
case syn_imm: amode = 0; break;
|
case syn_imm:
|
||||||
case syn_abs: amode = 1; break;
|
amode = 0;
|
||||||
case syn_implied: amode = 2; bytelen = 0; break;
|
break;
|
||||||
case syn_absy:
|
case syn_abs:
|
||||||
if ((opflags & OP_STX) == OP_STX)
|
amode = 1;
|
||||||
{
|
break;
|
||||||
amode = 5;
|
case syn_implied:
|
||||||
}
|
amode = 2;
|
||||||
break;
|
bytelen = 0;
|
||||||
case syn_absx: amode = 5; break; // this is actually Y addressing because X register is used
|
break;
|
||||||
default:
|
case syn_absy:
|
||||||
err = true;
|
if ((opflags & OP_STX) == OP_STX)
|
||||||
break;
|
{
|
||||||
|
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)
|
if ((opflags & OP_STX) == OP_STX)
|
||||||
|
@ -715,17 +746,32 @@ int CLASS::doBase6502(MerlinLine & line, TSymbol & sym)
|
||||||
err = false;
|
err = false;
|
||||||
switch (m)
|
switch (m)
|
||||||
{
|
{
|
||||||
case syn_s: amode = 0; break;
|
case syn_s:
|
||||||
case syn_sy: amode = 4; break;
|
amode = 0;
|
||||||
case syn_di: cc = 0x02; amode = 4; break;
|
break;
|
||||||
case syn_iyl: amode = 5; break;
|
case syn_sy:
|
||||||
case syn_dil: amode = 1; break;
|
amode = 4;
|
||||||
case syn_absx: amode = 7; break;
|
break;
|
||||||
case syn_abs: amode = 3; break;
|
case syn_di:
|
||||||
default:
|
cc = 0x02;
|
||||||
//printf("bad syn_mode=%d\n", m);
|
amode = 4;
|
||||||
err = true;
|
break;
|
||||||
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)
|
if (!err)
|
||||||
{
|
{
|
||||||
|
@ -750,15 +796,29 @@ out:
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
line.setError(errBadAddressMode);
|
line.setError(errBadAddressMode);
|
||||||
//printf("bad address mode %d\n",line.addressmode);
|
printf("bad address mode %d\n",line.addressmode);
|
||||||
op = 0x00;
|
op = 0x00;
|
||||||
res = 0;
|
res = 0;
|
||||||
bytelen = 0;
|
bytelen = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
res += bytelen;
|
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))
|
if ((pass > 0) && (res > 0))
|
||||||
{
|
{
|
||||||
|
|
||||||
setOpcode(line, op);
|
setOpcode(line, op);
|
||||||
for (i = 0; i < (res - 1); i++)
|
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
|
// 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
|
// after a SEC/CLC instruction must be an XCE
|
||||||
if (sym.opcode == 0x38) // SEC
|
if (options.isMerlin32())
|
||||||
{
|
{
|
||||||
lastcarry = true;
|
if (sym.opcode == 0x38) // SEC
|
||||||
}
|
|
||||||
else if (sym.opcode == 0x18) // CLC
|
|
||||||
{
|
|
||||||
lastcarry = false;
|
|
||||||
}
|
|
||||||
else if (sym.opcode == 0xFB) // XCE
|
|
||||||
{
|
|
||||||
if (trackrep)
|
|
||||||
{
|
{
|
||||||
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("=", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doEQU));
|
||||||
pushopcode("EQU", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doEQU));
|
pushopcode("EQU", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doEQU));
|
||||||
pushopcode("END", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doEND));
|
pushopcode("END", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doEND));
|
||||||
pushopcode("MX", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doMX));
|
pushopcode("MX", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doMX));
|
||||||
pushopcode("XC", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doXC));
|
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("ENT", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
|
||||||
pushopcode("ORG", P_ORG, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
|
pushopcode("ORG", P_ORG, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
|
||||||
pushopcode("DSK", P_SAV, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
|
pushopcode("DSK", P_SAV, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
|
||||||
|
|
16
parms.json
16
parms.json
|
@ -7,20 +7,26 @@
|
||||||
"0": "${PWD}"
|
"0": "${PWD}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"1": "0/source"
|
"1": "${QASM_BASE}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"2": "0/object"
|
"2": "0/object"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"3": "0/macros"
|
"3": "1/macros"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"4": "1/toolmacs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"5": "../backup"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"language": "qasm",
|
||||||
"asm": {
|
"asm": {
|
||||||
"language": "merlin16plus",
|
"cpu": "M65816",
|
||||||
"cpu": "M6502",
|
"start_mx": 0,
|
||||||
"start_mx": 2,
|
|
||||||
"listmode": "on",
|
"listmode": "on",
|
||||||
"casesen": true,
|
"casesen": true,
|
||||||
"start_lst": false,
|
"start_lst": false,
|
||||||
|
|
58
psuedo.cpp
58
psuedo.cpp
|
@ -793,6 +793,7 @@ int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
||||||
uint8_t delimiter = 0;
|
uint8_t delimiter = 0;
|
||||||
uint32_t ss = 0;
|
uint32_t ss = 0;
|
||||||
uint32_t lastdelimidx = 0;
|
uint32_t lastdelimidx = 0;
|
||||||
|
bool dci = false;
|
||||||
|
|
||||||
std::vector<uint8_t> bytes;
|
std::vector<uint8_t> bytes;
|
||||||
|
|
||||||
|
@ -890,7 +891,6 @@ int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
||||||
{
|
{
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
bool reverse = false;
|
bool reverse = false;
|
||||||
bool dci = false;
|
|
||||||
uint8_t andval = 0xFF;
|
uint8_t andval = 0xFF;
|
||||||
uint8_t orval = 0x00;
|
uint8_t orval = 0x00;
|
||||||
uint8_t addlen = 0;
|
uint8_t addlen = 0;
|
||||||
|
@ -956,28 +956,42 @@ int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
||||||
b |= orval;
|
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
|
// invert last byte of total bytes out
|
||||||
// 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
|
if ((dci) && ((i+1)>=truebytect))
|
||||||
// 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;
|
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);
|
line.outbytes.push_back(b);
|
||||||
|
@ -986,7 +1000,7 @@ int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
||||||
bytect = bytect + addlen;
|
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;
|
line.outbytect = bytect;
|
||||||
return bytect;
|
return bytect;
|
||||||
|
@ -1033,7 +1047,8 @@ int CLASS::ProcessOpcode(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// Merlin32 seems to have a bug where ORG seems like it can only be 16 bits
|
// 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
|
// so clear the bank word in all variables
|
||||||
a.PC.orgsave &= 0xFFFF;
|
a.PC.orgsave &= 0xFFFF;
|
||||||
|
@ -1048,7 +1063,8 @@ int CLASS::ProcessOpcode(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
||||||
sp = getConfig("option.objfile", "");
|
sp = getConfig("option.objfile", "");
|
||||||
if (sp=="")
|
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.
|
else // if they specified an output name on the command line, use it.
|
||||||
{
|
{
|
||||||
|
|
16
qasm.cpp
16
qasm.cpp
|
@ -115,10 +115,11 @@ int CLASS::runCommandLineApp(void)
|
||||||
return (res);
|
return (res);
|
||||||
}
|
}
|
||||||
|
|
||||||
options.ReadFile(Poco::Path::config()+"/parms.json");
|
//printf("apppath: |%s|\n",appPath.c_str());
|
||||||
options.ReadFile(appPath+"/parms.json");
|
options.ReadFile(Poco::Path::config()+"/parms.json",false);
|
||||||
options.ReadFile(Poco::Path::configHome()+"/parms.json");
|
options.ReadFile(appPath+"/parms.json",true);
|
||||||
options.ReadFile(Poco::Path::current()+"/parms.json");
|
options.ReadFile(Poco::Path::configHome()+"/parms.json",false);
|
||||||
|
options.ReadFile(Poco::Path::current()+"/parms.json",false);
|
||||||
|
|
||||||
syn="QASM";
|
syn="QASM";
|
||||||
|
|
||||||
|
@ -145,6 +146,7 @@ int CLASS::runCommandLineApp(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
language=syn;
|
language=syn;
|
||||||
|
options.setLanguage(syn,true);
|
||||||
|
|
||||||
if (isDebug()>0)
|
if (isDebug()>0)
|
||||||
{
|
{
|
||||||
|
@ -237,7 +239,7 @@ int CLASS::runCommandLineApp(void)
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
t->init();
|
t->init();
|
||||||
t->setLanguage(language);
|
t->setLanguage(language,true);
|
||||||
t->format_flags=format_flags;
|
t->format_flags=format_flags;
|
||||||
|
|
||||||
std::string f = path.toString();
|
std::string f = path.toString();
|
||||||
|
@ -271,7 +273,7 @@ int CLASS::runCommandLineApp(void)
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
t->init();
|
t->init();
|
||||||
t->setLanguage(language);
|
t->setLanguage(language,true);
|
||||||
|
|
||||||
|
|
||||||
std::string f = path.toString();
|
std::string f = path.toString();
|
||||||
|
@ -308,7 +310,7 @@ int CLASS::runCommandLineApp(void)
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
t->init();
|
t->init();
|
||||||
t->setLanguage(language);
|
t->setLanguage(language,true);
|
||||||
|
|
||||||
std::string f = path.toString();
|
std::string f = path.toString();
|
||||||
t->filename = f;
|
t->filename = f;
|
||||||
|
|
385
qoptions.h
385
qoptions.h
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
using namespace Poco;
|
using namespace Poco;
|
||||||
|
|
||||||
|
#define ENV_QASM "QASM_BASE"
|
||||||
|
|
||||||
#define MAX_PREFIX 32
|
#define MAX_PREFIX 32
|
||||||
|
|
||||||
#define MODE_6502 0
|
#define MODE_6502 0
|
||||||
|
@ -10,13 +12,15 @@ using namespace Poco;
|
||||||
#define MODE_65816 2
|
#define MODE_65816 2
|
||||||
|
|
||||||
#define SYNTAX_MERLIN 0x01
|
#define SYNTAX_MERLIN 0x01
|
||||||
#define SYNTAX_MERLIN32 0x02
|
#define SYNTAX_MERLIN16 0x02
|
||||||
#define SYNTAX_APW 0x04
|
#define SYNTAX_MERLIN16PLUS 0x04
|
||||||
#define SYNTAX_MPW 0x08
|
#define SYNTAX_MERLIN32 0x08
|
||||||
#define SYNTAX_ORCA 0x10
|
#define SYNTAX_APW 0x10
|
||||||
#define SYNTAX_CC65 0x20
|
#define SYNTAX_MPW 0x20
|
||||||
#define SYNTAX_LISA 0x40
|
#define SYNTAX_ORCA 0x40
|
||||||
#define SYNTAX_QASM (0x80 | SYNTAX_MERLIN)
|
#define SYNTAX_CC65 0x80
|
||||||
|
#define SYNTAX_LISA 0x100
|
||||||
|
#define SYNTAX_QASM (0x200 | SYNTAX_MERLIN)
|
||||||
|
|
||||||
#define OPTION_ALLOW_A_OPERAND 0x0100
|
#define OPTION_ALLOW_A_OPERAND 0x0100
|
||||||
#define OPTION_ALLOW_LOCAL 0x0200
|
#define OPTION_ALLOW_LOCAL 0x0200
|
||||||
|
@ -41,11 +45,11 @@ class CLASS
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
//vector<shared_ptr<JSONConfiguration>> configs;
|
//vector<shared_ptr<JSONConfiguration>> configs;
|
||||||
|
vector<std::string> valid_files;
|
||||||
public:
|
public:
|
||||||
Poco::JSON::Parser parser;
|
//Poco::JSON::Parser parser;
|
||||||
string jsonin;
|
//string jsonin;
|
||||||
Dynamic::Var jsonobj=NULL;
|
//Dynamic::Var jsonobj=NULL;
|
||||||
uint16_t format_flags;
|
uint16_t format_flags;
|
||||||
|
|
||||||
uint16_t cpu_mode;
|
uint16_t cpu_mode;
|
||||||
|
@ -70,23 +74,34 @@ public:
|
||||||
int16_t linebytes;
|
int16_t linebytes;
|
||||||
int16_t overflowbytes;
|
int16_t overflowbytes;
|
||||||
|
|
||||||
myLayeredConfiguration config;
|
myLayeredConfiguration *config=NULL;
|
||||||
|
|
||||||
bool usecolor;
|
bool usecolor;
|
||||||
|
|
||||||
CLASS()
|
CLASS()
|
||||||
{
|
{
|
||||||
|
language="";
|
||||||
|
setEnvironment();
|
||||||
|
clear();
|
||||||
setDefaults();
|
setDefaults();
|
||||||
setLanguage("QASM");
|
setLanguage("QASM",true);
|
||||||
|
setCurrent();
|
||||||
}
|
}
|
||||||
~CLASS()
|
~CLASS()
|
||||||
{
|
{
|
||||||
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear()
|
void clear()
|
||||||
{
|
{
|
||||||
//configs.clear();
|
if (config!=NULL)
|
||||||
|
{
|
||||||
|
delete config;
|
||||||
|
config=NULL;
|
||||||
|
}
|
||||||
|
config=new myLayeredConfiguration();
|
||||||
|
valid_files.clear();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool useColor(void)
|
bool useColor(void)
|
||||||
|
@ -125,6 +140,8 @@ public:
|
||||||
int printDefaults(string lang)
|
int printDefaults(string lang)
|
||||||
{
|
{
|
||||||
int res=-1;
|
int res=-1;
|
||||||
|
string s;
|
||||||
|
int i;
|
||||||
string l=Poco::toUpper(lang);
|
string l=Poco::toUpper(lang);
|
||||||
if (l=="")
|
if (l=="")
|
||||||
{
|
{
|
||||||
|
@ -132,24 +149,46 @@ public:
|
||||||
}
|
}
|
||||||
if (l!="")
|
if (l!="")
|
||||||
{
|
{
|
||||||
setLanguage(l);
|
setLanguage(l,false);
|
||||||
setCurrent();
|
setCurrent();
|
||||||
printf("Defaults for language (%s)\n",language.c_str());
|
printf("Defaults for language (%s)\n",language.c_str());
|
||||||
printf("\tLanguage:\t\t\t\t\t%s\n",language.c_str());
|
printf("\t\tLanguage:\t\t\t%s\n",language.c_str());
|
||||||
printf("\t\tlanguageLevel:\t\t\t\t%d\n",langlevel);
|
printf("\t\tlanguageLevel:\t\t\t%d\n",langlevel);
|
||||||
printf("\t\tcpu_mode:\t\t\t\t%d\n",cpu_mode);
|
s="<unknown>";
|
||||||
printf("\t\tstart_mx:\t\t\t\t%d\n",start_mx);
|
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");
|
printf("\t\tPrefixes:\n");
|
||||||
|
|
||||||
for (int i=0; i<MAX_PREFIX; i++)
|
for (i=0; i<MAX_PREFIX; i++)
|
||||||
{
|
{
|
||||||
if (prefixes[i].length()>0)
|
if (prefixes[i].length()>0)
|
||||||
{
|
{
|
||||||
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; ii<valid_files.size(); ii++)
|
||||||
|
{
|
||||||
|
if (prefixes[ii].length()>0)
|
||||||
|
{
|
||||||
|
printf("\t\tSettings files read: \t%s\n",valid_files[ii].c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
//uint16_t format_flags;
|
//uint16_t format_flags;
|
||||||
|
|
||||||
|
|
||||||
|
@ -160,68 +199,292 @@ public:
|
||||||
return(res);
|
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;
|
int ret=-1;
|
||||||
|
unsigned long ii;
|
||||||
Poco::Util::JSONConfiguration *jc;
|
Poco::Util::JSONConfiguration *jc;
|
||||||
|
|
||||||
Poco::Path pp(path);
|
while(!done)
|
||||||
//pp=pp.expand();
|
|
||||||
Poco::File pf(pp);
|
|
||||||
if (isDebug()>1)
|
|
||||||
{
|
{
|
||||||
printf("parmsfile: %s\n",pp.toString().c_str());
|
Poco::Path pp(path);
|
||||||
}
|
//pp=pp.absolute(Poco::Path("/"));
|
||||||
if ((pf.exists()) && (pf.canRead()) && ((pf.isFile()) || (pf.isLink())))
|
pp=pp.absolute();
|
||||||
{
|
|
||||||
//printf("OK: %s\n",pp.toString().c_str());
|
|
||||||
|
|
||||||
jc=new Poco::Util::JSONConfiguration();
|
std::string basename=pp.getFileName();
|
||||||
//Poco::FileInputStream fs(path);
|
|
||||||
//Poco::StreamCopier::copyToString(fs,jsonin);
|
Poco::File pf(pp);
|
||||||
//parser.reset();
|
if (isDebug()>1)
|
||||||
//parser.setAllowComments(true);
|
|
||||||
//jsonobj=parser.parse(jsonin);
|
|
||||||
if (jc!=NULL)
|
|
||||||
{
|
{
|
||||||
bool success=false;
|
//pf.
|
||||||
try
|
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());
|
printf("...found!\n");
|
||||||
success=true;
|
|
||||||
}
|
}
|
||||||
catch(...)
|
//printf("OK: %s\n",pp.toString().c_str());
|
||||||
|
done=false;
|
||||||
|
for (ii=0; ii<valid_files.size(); ii++)
|
||||||
{
|
{
|
||||||
success=false;
|
if (pf.path()==valid_files[ii])
|
||||||
|
{
|
||||||
|
done=true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (success)
|
if (!done)
|
||||||
{
|
{
|
||||||
//configs.push_back(shared_ptr<JSONConfiguration>(jc));
|
done=true; // we found a valid file
|
||||||
config.add(jc);
|
|
||||||
ret=0;
|
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<JSONConfiguration>(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);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isMerlin32(void)
|
bool isMerlin32(void)
|
||||||
{
|
{
|
||||||
return(true);
|
bool res=false;
|
||||||
|
if (language=="MERLIN32")
|
||||||
|
{
|
||||||
|
res=true;
|
||||||
|
}
|
||||||
|
return(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isMerlin(void)
|
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 (n<MAX_PREFIX)
|
||||||
|
{
|
||||||
|
success=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(const std::exception& e)
|
||||||
|
{
|
||||||
|
success=false;
|
||||||
|
}
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
s=s.substr(toks[0].length(),s.length());
|
||||||
|
s=prefixes[n]+s;
|
||||||
|
pp=Poco::Path(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//pp=pp.absolute(Poco::Path("/"));
|
||||||
|
pp=pp.absolute();
|
||||||
|
res=pp.toString();
|
||||||
|
}
|
||||||
|
return(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setCurrent(void)
|
void setCurrent(void)
|
||||||
{
|
{
|
||||||
|
char buff[1024];
|
||||||
|
string s,n;
|
||||||
|
int i;
|
||||||
|
|
||||||
start_mx=GetInteger("asm.start_mx",3);
|
start_mx=GetInteger("asm.start_mx",3);
|
||||||
|
for (i=0; i<MAX_PREFIX; i++)
|
||||||
|
{
|
||||||
|
sprintf(buff,"general.prefix[%d].%d",i,i);
|
||||||
|
n=buff;
|
||||||
|
n=GetString(n,"");
|
||||||
|
n=formatPath(n);
|
||||||
|
prefixes[i]=n;
|
||||||
|
}
|
||||||
|
s=GetString("asm.cpu","M6502");
|
||||||
|
if (s=="M6502")
|
||||||
|
{
|
||||||
|
cpu_mode=MODE_6502;
|
||||||
|
}
|
||||||
|
else if (s=="M65C02")
|
||||||
|
{
|
||||||
|
cpu_mode=MODE_65C02;
|
||||||
|
}
|
||||||
|
else if (s=="M65816")
|
||||||
|
{
|
||||||
|
cpu_mode=MODE_65816;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("unknown cpu_mode in settings (%s) [M6502, M65C02, M65816]\n",s.c_str());
|
||||||
|
cpu_mode=MODE_6502;
|
||||||
|
}
|
||||||
|
|
||||||
|
allowDuplicate=GetBool("asm.allowduplicate",false);
|
||||||
}
|
}
|
||||||
void setDefaults(void)
|
void setDefaults(void)
|
||||||
{
|
{
|
||||||
|
@ -251,15 +514,15 @@ public:
|
||||||
usecolor=true;
|
usecolor=true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setLanguage(string lang)
|
void setLanguage(string lang, bool force)
|
||||||
{
|
{
|
||||||
//printf("request language options to %s from %s\n",lang.c_str(),language.c_str());
|
//printf("request language options to %s from %s\n",lang.c_str(),language.c_str());
|
||||||
|
|
||||||
string old=language;
|
string old=language;
|
||||||
string pn=Poco::toUpper(lang);
|
string pn=Poco::toUpper(lang);
|
||||||
if (old!=pn)
|
if ((old!=pn) || (force))
|
||||||
{
|
{
|
||||||
//printf("setting language options to %s\n",pn.c_str());
|
printf("setting language options to %s\n",pn.c_str());
|
||||||
language=pn;
|
language=pn;
|
||||||
setCurrent();
|
setCurrent();
|
||||||
if (pn=="QASM")
|
if (pn=="QASM")
|
||||||
|
@ -333,6 +596,8 @@ public:
|
||||||
bool res=def;
|
bool res=def;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
res=config->getBool(name);
|
||||||
|
|
||||||
//Dynamic::Var jresult=GetObject(name);
|
//Dynamic::Var jresult=GetObject(name);
|
||||||
//if (!jresult.isEmpty())
|
//if (!jresult.isEmpty())
|
||||||
//{
|
//{
|
||||||
|
@ -358,7 +623,7 @@ public:
|
||||||
string res=def;
|
string res=def;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
//config
|
res=config->getString(name);
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
|
@ -373,8 +638,8 @@ public:
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
std::vector<std::string> keys;
|
std::vector<std::string> keys;
|
||||||
config.keys(keys);
|
config->keys(keys);
|
||||||
for (unsigned int i=0;i<keys.size();i++)
|
for (unsigned int i=0; i<keys.size(); i++)
|
||||||
{
|
{
|
||||||
printf("key[%d]: %s\n",i,keys[i].c_str());
|
printf("key[%d]: %s\n",i,keys[i].c_str());
|
||||||
}
|
}
|
||||||
|
@ -382,7 +647,7 @@ public:
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
res=config.getInt(name);
|
res=config->getInt(name);
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
|
|
10
runtests.sh
10
runtests.sh
|
@ -29,10 +29,14 @@ for S in $SRC ; do
|
||||||
BASE=${BASE/.s/}
|
BASE=${BASE/.s/}
|
||||||
#./qasm -o 0/$OUTDIR/$S1 ./testdata/$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=?$
|
R=?$
|
||||||
#echo $S " " $S1
|
#echo $S " " $S1
|
||||||
|
#cat $TMPFILE
|
||||||
R=`cat $TMPFILE | grep "End qASM assembly"`
|
R=`cat $TMPFILE | grep "End qASM assembly"`
|
||||||
E=`echo $R | awk -e '{ print $6; }'`
|
E=`echo $R | awk -e '{ print $6; }'`
|
||||||
ect=`echo $(($E))`
|
ect=`echo $(($E))`
|
||||||
|
@ -64,8 +68,12 @@ for S in $SRC ; do
|
||||||
if [ $pct != 0 ] ; then
|
if [ $pct != 0 ] ; then
|
||||||
printf 'FAIL: (%3s) ' $ect
|
printf 'FAIL: (%3s) ' $ect
|
||||||
printf '%s ' $CX
|
printf '%s ' $CX
|
||||||
|
echo " $S"
|
||||||
|
|
||||||
FAILCT=$(($FAILCT+1))
|
FAILCT=$(($FAILCT+1))
|
||||||
|
cat $TMPFILE
|
||||||
|
echo $X
|
||||||
|
exit 255
|
||||||
else
|
else
|
||||||
printf "PASS: "
|
printf "PASS: "
|
||||||
fi
|
fi
|
||||||
|
|
33
test.s
33
test.s
|
@ -10,9 +10,36 @@
|
||||||
xc off
|
xc off
|
||||||
xc
|
xc
|
||||||
xc
|
xc
|
||||||
|
lst
|
||||||
;lst OFF
|
;lst OFF
|
||||||
ZP equ $00
|
ZP equ $00
|
||||||
org $2000
|
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)
|
ora ($00)
|
||||||
lda ($00)
|
lda ($00)
|
||||||
bit: $FFFE,X
|
bit: $FFFE,X
|
||||||
|
@ -51,11 +78,15 @@ another lda #$00 ;line with everything
|
||||||
lda ]m
|
lda ]m
|
||||||
bra ]m
|
bra ]m
|
||||||
--^
|
--^
|
||||||
|
sav 2/test.bin
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
]1 nop
|
]1 nop
|
||||||
nop
|
nop
|
||||||
;lst
|
;lst
|
||||||
bra ]1
|
bra ]1
|
||||||
|
|
||||||
;typ $06
|
;typ $06
|
||||||
sav 0/test.bin
|
db 255
|
||||||
;lst off
|
;lst off
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
; Copyright 2018 faddenSoft. All Rights Reserved.
|
; Copyright 2018 faddenSoft. All Rights Reserved.
|
||||||
; See the LICENSE.txt file for distribution terms (Apache 2.0).
|
; See the LICENSE.txt file for distribution terms (Apache 2.0).
|
||||||
;
|
;
|
||||||
; Assembler: Merlin 32
|
; Assembler: Merlin 32
|
||||||
|
|
||||||
|
xc off
|
||||||
ZP EQU $00
|
ZP EQU $00
|
||||||
ABS EQU $0000
|
ABS EQU $0000
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,9 @@
|
||||||
; Assembler: Merlin 32
|
; Assembler: Merlin 32
|
||||||
|
|
||||||
org $1000
|
org $1000
|
||||||
|
xc off
|
||||||
|
xc
|
||||||
|
xc
|
||||||
; 65816 with short regs
|
; 65816 with short regs
|
||||||
clc
|
clc
|
||||||
xce
|
xce
|
||||||
|
|
|
@ -2,7 +2,9 @@
|
||||||
; See the LICENSE.txt file for distribution terms (Apache 2.0).
|
; See the LICENSE.txt file for distribution terms (Apache 2.0).
|
||||||
;
|
;
|
||||||
; Assembler: Merlin 32
|
; Assembler: Merlin 32
|
||||||
|
xc off
|
||||||
|
xc
|
||||||
|
xc
|
||||||
absl equ $1029
|
absl equ $1029
|
||||||
absh equ $feed
|
absh equ $feed
|
||||||
zip equ $cd
|
zip equ $cd
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
;lst off
|
lst off
|
||||||
*
|
*
|
||||||
* main.s
|
* main.s
|
||||||
* Merlin32 Test
|
* Merlin32 Test
|
||||||
|
@ -6,401 +6,403 @@
|
||||||
* Created by Lane Roathe on 8/26/19.
|
* Created by Lane Roathe on 8/26/19.
|
||||||
* Copyright B) 2019 Ideas From the Deep. All rights reserved.
|
* 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 off
|
||||||
xc
|
xc
|
||||||
xc
|
xc
|
||||||
mx %00
|
mx %00
|
||||||
|
|
||||||
|
|
||||||
*==========================================================
|
*==========================================================
|
||||||
* monitor addresses
|
* monitor addresses
|
||||||
|
|
||||||
TEXT = $FB39 ;Reset text window
|
TEXT = $FB39 ;Reset text window
|
||||||
TABV = $FB5B ;Complete vtab, using contents of 'A'
|
TABV = $FB5B ;Complete vtab, using contents of 'A'
|
||||||
MONBELL = $FBE4 ;random bell noise!
|
MONBELL = $FBE4 ;random bell noise!
|
||||||
HOME = $FC58 ;Clear text window
|
HOME = $FC58 ;Clear text window
|
||||||
WAIT = $FCA8 ;delay routine
|
WAIT = $FCA8 ;delay routine
|
||||||
CROUT = $FD8E ;Print a CR
|
CROUT = $FD8E ;Print a CR
|
||||||
PRBYTE = $FDDA ;Print 'A' as a hex number
|
PRBYTE = $FDDA ;Print 'A' as a hex number
|
||||||
PRHEX = $FDE3 ;as above, but bits 0-3 only
|
PRHEX = $FDE3 ;as above, but bits 0-3 only
|
||||||
COUT = $FDED ;Monitor char out
|
COUT = $FDED ;Monitor char out
|
||||||
MOVE = $FE2C ;memory move routine
|
MOVE = $FE2C ;memory move routine
|
||||||
INVERSE = $FE80 ;Print in inverse
|
INVERSE = $FE80 ;Print in inverse
|
||||||
NORMAL = $FE84 ;Normal print
|
NORMAL = $FE84 ;Normal print
|
||||||
|
|
||||||
* Jump Vectors
|
* Jump Vectors
|
||||||
CONNECT = $3EA ;Connect DOS
|
CONNECT = $3EA ;Connect DOS
|
||||||
DOSWARM = $3D0 ;exit to DOS prompt
|
DOSWARM = $3D0 ;exit to DOS prompt
|
||||||
RSTVEC = $3F2 ;reset vector
|
RSTVEC = $3F2 ;reset vector
|
||||||
|
|
||||||
TSTADDR = $1000 ;absolute address for testing
|
TSTADDR = $1000 ;absolute address for testing
|
||||||
|
|
||||||
*==========================================================
|
*==========================================================
|
||||||
* Data Index DUM section test
|
* Data Index DUM section test
|
||||||
|
|
||||||
DUM 0
|
DUM 0
|
||||||
dum0 ds 1 ;fractional byte
|
dum0 ds 1 ;fractional byte
|
||||||
dum1 ds 1
|
dum1 ds 1
|
||||||
dumSize = *
|
dumSize = *
|
||||||
DEND
|
DEND
|
||||||
;lst off
|
;lst off
|
||||||
|
|
||||||
*==========================================================
|
*==========================================================
|
||||||
* zero page (all zp var names are prefixed with _)
|
* zero page (all zp var names are prefixed with _)
|
||||||
|
|
||||||
DUM 0
|
DUM 0
|
||||||
|
|
||||||
_ptr ds 2
|
_ptr ds 2
|
||||||
_tmp 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
|
* Program Entry
|
||||||
|
|
||||||
START
|
START
|
||||||
adc (0,x)
|
adc (0,x)
|
||||||
adc ($80,x)
|
adc ($80,x)
|
||||||
adc (_tmp,x)
|
adc (_tmp,x)
|
||||||
adc (_tmp+0,x)
|
adc (_tmp+0,x)
|
||||||
adc (_tmp+$10,x)
|
adc (_tmp+$10,x)
|
||||||
adc ($10+_tmp,x)
|
adc ($10+_tmp,x)
|
||||||
adc (_tmp+dum0,x)
|
adc (_tmp+dum0,x)
|
||||||
adc (_tmp+dum1,x)
|
adc (_tmp+dum1,x)
|
||||||
adc (_tmp+dum1+1,x)
|
adc (_tmp+dum1+1,x)
|
||||||
adc (_tmp+dum0+dum1,x)
|
adc (_tmp+dum0+dum1,x)
|
||||||
|
|
||||||
adc 0
|
adc 0
|
||||||
adc $80
|
adc $80
|
||||||
adc _tmp
|
adc _tmp
|
||||||
adc #0
|
adc #0
|
||||||
adc #$1111
|
adc #$1111
|
||||||
adc $1111
|
adc $1111
|
||||||
|
|
||||||
sta TSTADDR+dum0
|
sta TSTADDR+dum0
|
||||||
sta TSTADDR+_num1+dum0
|
sta TSTADDR+_num1+dum0
|
||||||
sta TSTADDR+_num1+dum0,x
|
sta TSTADDR+_num1+dum0,x
|
||||||
|
|
||||||
lda _num1+dum0
|
lda _num1+dum0
|
||||||
adc _num1+dum1
|
adc _num1+dum1
|
||||||
sbc _num1+dum1
|
sbc _num1+dum1
|
||||||
bit _num1+dum0
|
bit _num1+dum0
|
||||||
sta _num1+dum0 ;(FIXED): can't use sta _num1+dum0 '
|
sta _num1+dum0 ;(FIXED): can't use sta _num1+dum0 '
|
||||||
stz _num1+dum0
|
stz _num1+dum0
|
||||||
|
|
||||||
lda _num1+dum0,x
|
lda _num1+dum0,x
|
||||||
adc _num1+dum0,x
|
adc _num1+dum0,x
|
||||||
sbc _num1+dum0,x
|
sbc _num1+dum0,x
|
||||||
bit _num1+dum0,x
|
bit _num1+dum0,x
|
||||||
sta _num1+dum0,x
|
sta _num1+dum0,x
|
||||||
stz _num1+dum0,x
|
stz _num1+dum0,x
|
||||||
|
|
||||||
lda _num1+dum0,y ;these assemble to abs accesses: lda $00C0,y
|
lst
|
||||||
adc _num1+dum0,y
|
lda _num1+dum0,y ;these assemble to abs accesses: lda $00C0,y
|
||||||
sbc _num1+dum0,y
|
adc _num1+dum0,y
|
||||||
sta _num1+dum0,y
|
sbc _num1+dum0,y
|
||||||
|
sta _num1+dum0,y
|
||||||
|
lst off
|
||||||
|
|
||||||
; Label & branching tests
|
; Label & branching tests
|
||||||
GetKey ldx $C000
|
GetKey ldx $C000
|
||||||
bpl GetKey
|
bpl GetKey
|
||||||
]loop
|
]loop
|
||||||
dex
|
dex
|
||||||
bne ]loop
|
bne ]loop
|
||||||
|
|
||||||
tya
|
tya
|
||||||
and #1
|
and #1
|
||||||
beq :err
|
beq :err
|
||||||
|
|
||||||
tya
|
tya
|
||||||
and #1
|
and #1
|
||||||
bne :good
|
bne :good
|
||||||
:err
|
:err
|
||||||
lda #0
|
lda #0
|
||||||
:good
|
:good
|
||||||
bne myQuit
|
bne myQuit
|
||||||
nop
|
nop
|
||||||
hex 2C ;bit
|
hex 2C ;bit
|
||||||
lda #1
|
lda #1
|
||||||
myQuit
|
myQuit
|
||||||
jmp DOSWARM
|
jmp DOSWARM
|
||||||
|
|
||||||
org $2000
|
org $2000
|
||||||
|
|
||||||
lda _LFT
|
lda _LFT
|
||||||
ldx #_LFT
|
ldx #_LFT
|
||||||
cpx #$20
|
cpx #$20
|
||||||
|
|
||||||
org ;return to ongoing address
|
org ;return to ongoing address
|
||||||
|
|
||||||
lda $FF
|
lda $FF
|
||||||
;Issue #16 (fadden) - Byte reference modifiers are ignored (no way to force DP)
|
;Issue #16 (fadden) - Byte reference modifiers are ignored (no way to force DP)
|
||||||
lda <$fff0 ;zp
|
lda <$fff0 ;zp
|
||||||
lda >$fff0 ;ABS (lo word)
|
lda >$fff0 ;ABS (lo word)
|
||||||
lda ^$fff0 ;ABS (hi word)
|
lda ^$fff0 ;ABS (hi word)
|
||||||
lda |$fff0 ;ABS (long in 65816 mode)
|
lda |$fff0 ;ABS (long in 65816 mode)
|
||||||
|
|
||||||
lda $08
|
lda $08
|
||||||
lda $0008
|
lda $0008
|
||||||
lda $FFFF-$FFF7
|
lda $FFFF-$FFF7
|
||||||
lda $FFF0+24
|
lda $FFF0+24
|
||||||
ldaz $FFF0+24 ; forced DP
|
ldaz $FFF0+24 ; forced DP
|
||||||
|
|
||||||
|
|
||||||
ldaz $FFFF ; forced DP
|
ldaz $FFFF ; forced DP
|
||||||
lda: $FFFF ; forced ABS (any char but 'L', 'D', and 'Z'
|
lda: $FFFF ; forced ABS (any char but 'L', 'D', and 'Z'
|
||||||
ldal $FFFF ; forced long abs (3 byte address)
|
ldal $FFFF ; forced long abs (3 byte address)
|
||||||
|
|
||||||
ldaz $05
|
ldaz $05
|
||||||
lda: $05
|
lda: $05
|
||||||
ldal $05
|
ldal $05
|
||||||
|
|
||||||
lda $45
|
lda $45
|
||||||
lda $2345
|
lda $2345
|
||||||
lda $012345
|
lda $012345
|
||||||
ldaz $2345
|
ldaz $2345
|
||||||
lda: $45
|
lda: $45
|
||||||
ldal $012345
|
ldal $012345
|
||||||
ldal $2345
|
ldal $2345
|
||||||
ldal $45
|
ldal $45
|
||||||
lda <$2345
|
lda <$2345
|
||||||
lda >$2345
|
lda >$2345
|
||||||
lda <$012345
|
lda <$012345
|
||||||
lda >$012345
|
lda >$012345
|
||||||
lda ^$012345
|
lda ^$012345
|
||||||
lda |$012345
|
lda |$012345
|
||||||
|
|
||||||
ora $45
|
ora $45
|
||||||
ora $2345
|
ora $2345
|
||||||
ora $012345
|
ora $012345
|
||||||
oraz $2345
|
oraz $2345
|
||||||
ora: $45
|
ora: $45
|
||||||
oral $012345
|
oral $012345
|
||||||
oral $2345
|
oral $2345
|
||||||
oral $45
|
oral $45
|
||||||
ora <$2345
|
ora <$2345
|
||||||
ora >$2345
|
ora >$2345
|
||||||
ora <$012345
|
ora <$012345
|
||||||
ora >$012345
|
ora >$012345
|
||||||
ora ^$012345
|
ora ^$012345
|
||||||
ora |$012345
|
ora |$012345
|
||||||
|
|
||||||
and $45
|
and $45
|
||||||
and $2345
|
and $2345
|
||||||
and $012345
|
and $012345
|
||||||
andz $2345
|
andz $2345
|
||||||
and: $45
|
and: $45
|
||||||
andl $012345
|
andl $012345
|
||||||
andl $2345
|
andl $2345
|
||||||
andl $45
|
andl $45
|
||||||
and <$2345
|
and <$2345
|
||||||
and >$2345
|
and >$2345
|
||||||
and <$012345
|
and <$012345
|
||||||
and >$012345
|
and >$012345
|
||||||
and ^$012345
|
and ^$012345
|
||||||
and |$012345
|
and |$012345
|
||||||
|
|
||||||
eor $45
|
eor $45
|
||||||
eor $2345
|
eor $2345
|
||||||
eor $012345
|
eor $012345
|
||||||
eorz $2345
|
eorz $2345
|
||||||
eor: $45
|
eor: $45
|
||||||
eorl $012345
|
eorl $012345
|
||||||
eorl $2345
|
eorl $2345
|
||||||
eorl $45
|
eorl $45
|
||||||
eor <$2345
|
eor <$2345
|
||||||
eor >$2345
|
eor >$2345
|
||||||
eor <$012345
|
eor <$012345
|
||||||
eor >$012345
|
eor >$012345
|
||||||
eor ^$012345
|
eor ^$012345
|
||||||
eor |$012345
|
eor |$012345
|
||||||
|
|
||||||
adc $45
|
adc $45
|
||||||
adc $2345
|
adc $2345
|
||||||
adc $012345
|
adc $012345
|
||||||
adcz $2345
|
adcz $2345
|
||||||
adc: $45
|
adc: $45
|
||||||
adcl $012345
|
adcl $012345
|
||||||
adcl $2345
|
adcl $2345
|
||||||
adcl $45
|
adcl $45
|
||||||
adc <$2345
|
adc <$2345
|
||||||
adc >$2345
|
adc >$2345
|
||||||
adc <$012345
|
adc <$012345
|
||||||
adc >$012345
|
adc >$012345
|
||||||
adc ^$012345
|
adc ^$012345
|
||||||
adc |$012345
|
adc |$012345
|
||||||
|
|
||||||
sta $45
|
sta $45
|
||||||
sta $2345
|
sta $2345
|
||||||
sta $012345
|
sta $012345
|
||||||
staz $2345
|
staz $2345
|
||||||
sta: $45
|
sta: $45
|
||||||
stal $012345
|
stal $012345
|
||||||
stal $2345
|
stal $2345
|
||||||
stal $45
|
stal $45
|
||||||
sta <$2345
|
sta <$2345
|
||||||
sta >$2345
|
sta >$2345
|
||||||
sta <$012345
|
sta <$012345
|
||||||
sta >$012345
|
sta >$012345
|
||||||
sta ^$012345
|
sta ^$012345
|
||||||
sta |$012345
|
sta |$012345
|
||||||
|
|
||||||
cmp $45
|
cmp $45
|
||||||
cmp $2345
|
cmp $2345
|
||||||
cmp $012345
|
cmp $012345
|
||||||
cmpz $2345
|
cmpz $2345
|
||||||
cmp: $45
|
cmp: $45
|
||||||
cmpl $012345
|
cmpl $012345
|
||||||
cmpl $2345
|
cmpl $2345
|
||||||
cmpl $45
|
cmpl $45
|
||||||
cmp <$2345
|
cmp <$2345
|
||||||
cmp >$2345
|
cmp >$2345
|
||||||
cmp <$012345
|
cmp <$012345
|
||||||
cmp >$012345
|
cmp >$012345
|
||||||
cmp ^$012345
|
cmp ^$012345
|
||||||
cmp |$012345
|
cmp |$012345
|
||||||
|
|
||||||
sbc $45
|
sbc $45
|
||||||
sbc $2345
|
sbc $2345
|
||||||
sbc $012345
|
sbc $012345
|
||||||
sbcz $2345
|
sbcz $2345
|
||||||
sbc: $45
|
sbc: $45
|
||||||
sbcl $012345
|
sbcl $012345
|
||||||
sbcl $2345
|
sbcl $2345
|
||||||
sbcl $45
|
sbcl $45
|
||||||
sbc <$2345
|
sbc <$2345
|
||||||
sbc >$2345
|
sbc >$2345
|
||||||
sbc <$012345
|
sbc <$012345
|
||||||
sbc >$012345
|
sbc >$012345
|
||||||
sbc ^$012345
|
sbc ^$012345
|
||||||
sbc |$012345
|
sbc |$012345
|
||||||
|
|
||||||
;asll $1234
|
;asll $1234
|
||||||
|
|
||||||
lda <$fff0+24 ;zp
|
lda <$fff0+24 ;zp
|
||||||
lda >$fff0+24 ;ABS (lo word)
|
lda >$fff0+24 ;ABS (lo word)
|
||||||
lda ^$fff0+24 ;ABS (hi word)
|
lda ^$fff0+24 ;ABS (hi word)
|
||||||
lda |$fff0+24 ;ABS (long in 65816 mode)
|
lda |$fff0+24 ;ABS (long in 65816 mode)
|
||||||
|
|
||||||
mx %11
|
mx %11
|
||||||
|
|
||||||
lda #<$fff0+24 ;byte
|
lda #<$fff0+24 ;byte
|
||||||
lda #>$fff0+24 ;page
|
lda #>$fff0+24 ;page
|
||||||
lda #^$fff0+24 ;bank
|
lda #^$fff0+24 ;bank
|
||||||
|
|
||||||
lda #<$1234 ;byte
|
lda #<$1234 ;byte
|
||||||
lda #>$1234 ;page
|
lda #>$1234 ;page
|
||||||
lda #^$1234 ;bank
|
lda #^$1234 ;bank
|
||||||
lda #^$A51234 ;bank
|
lda #^$A51234 ;bank
|
||||||
|
|
||||||
|
|
||||||
mx %00
|
mx %00
|
||||||
|
|
||||||
lda #<$fff0+24 ;byte
|
lda #<$fff0+24 ;byte
|
||||||
lda #>$fff0+24 ;page
|
lda #>$fff0+24 ;page
|
||||||
lda #^$fff0+24 ;bank
|
lda #^$fff0+24 ;bank
|
||||||
|
|
||||||
lda #<$1234 ;byte
|
lda #<$1234 ;byte
|
||||||
lda #>$1234 ;page
|
lda #>$1234 ;page
|
||||||
lda #^$1234 ;bank
|
lda #^$1234 ;bank
|
||||||
lda #^$A51234 ;bank
|
lda #^$A51234 ;bank
|
||||||
|
|
||||||
|
|
||||||
lda $0008 ;ZP
|
lda $0008 ;ZP
|
||||||
lda $08 ;ZP
|
lda $08 ;ZP
|
||||||
lda $ffff-$fff7 ;ZP
|
lda $ffff-$fff7 ;ZP
|
||||||
lda $fff0+24 ;ABS (long in 65816 mode)
|
lda $fff0+24 ;ABS (long in 65816 mode)
|
||||||
|
|
||||||
|
|
||||||
;Issue #8 fadden) - STX zp,y fails to assemble
|
;Issue #8 fadden) - STX zp,y fails to assemble
|
||||||
org $bc
|
org $bc
|
||||||
|
|
||||||
L00BC bit L00BC
|
L00BC bit L00BC
|
||||||
|
|
||||||
org
|
org
|
||||||
|
|
||||||
stx $bc,y
|
stx $bc,y
|
||||||
|
|
||||||
ldx L00BC,y
|
ldx L00BC,y
|
||||||
stx L00BC,y
|
stx L00BC,y
|
||||||
|
|
||||||
* Data Storage Tests
|
* Data Storage Tests
|
||||||
|
|
||||||
hex ;no error
|
hex ;no error
|
||||||
hex 11,22,33,44,55,66,77,88,99
|
hex 11,22,33,44,55,66,77,88,99
|
||||||
;hex 112233445566778899F
|
;hex 112233445566778899F
|
||||||
;hex 112233445I566778899FF
|
;hex 112233445I566778899FF
|
||||||
|
|
||||||
hex aabb,CC,0123456789abcdefABCDEF,ff
|
hex aabb,CC,0123456789abcdefABCDEF,ff
|
||||||
|
|
||||||
ds 36
|
ds 36
|
||||||
da $A55A
|
da $A55A
|
||||||
da $A55A,$1234
|
da $A55A,$1234
|
||||||
dw $A55A
|
dw $A55A
|
||||||
dw $A55A,$1234
|
dw $A55A,$1234
|
||||||
ddb $A55A
|
ddb $A55A
|
||||||
ddb $A55A,$1234
|
ddb $A55A,$1234
|
||||||
dfb $A55A
|
dfb $A55A
|
||||||
dfb $A55A,$1234
|
dfb $A55A,$1234
|
||||||
db $A55A
|
db $A55A
|
||||||
db $A55A,$1234
|
db $A55A,$1234
|
||||||
adr $01A55A
|
adr $01A55A
|
||||||
adr $01A55A,$011234
|
adr $01A55A,$011234
|
||||||
adrl $01A55A
|
adrl $01A55A
|
||||||
adrl $01A55A,$011234
|
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,"123456"
|
||||||
asc 02,15,z123456z
|
asc 02,15,z123456z
|
||||||
asc 0215,"123456"
|
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,&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,05,"123456"
|
||||||
asc 02,15,"123456"
|
asc 02,15,"123456"
|
||||||
asc 0215"1234"1502
|
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_start:
|
||||||
lup 0
|
lup 0
|
||||||
db 0 ; outside
|
db 0 ; outside
|
||||||
--^
|
--^
|
||||||
|
|
||||||
|
|
||||||
;lst off
|
;lst off
|
||||||
//]XCODEEND ; Keep this at the end and put your code above this
|
//]XCODEEND ; Keep this at the end and put your code above this
|
||||||
;lst off
|
lst off
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
*
|
*
|
||||||
* explicit a operand (inc a, etc) is dropped.
|
* explicit a operand (inc a, etc) is dropped.
|
||||||
*
|
*
|
||||||
|
xc OFF
|
||||||
|
xc
|
||||||
|
xc
|
||||||
|
mx %11
|
||||||
|
|
||||||
inc a
|
inc a
|
||||||
dec a
|
dec a
|
||||||
|
|
Loading…
Reference in New Issue