mirror of
https://github.com/marketideas/qasm.git
synced 2024-12-28 06:29:58 +00:00
commit
e4548bf453
120
asm.cpp
120
asm.cpp
@ -34,8 +34,6 @@ void CLASS::print(uint32_t lineno)
|
|||||||
|
|
||||||
uint32_t b = 4; // how many bytes show on the first line
|
uint32_t b = 4; // how many bytes show on the first line
|
||||||
|
|
||||||
bool merlinstyle = true;
|
|
||||||
|
|
||||||
if (datafillct > 0)
|
if (datafillct > 0)
|
||||||
{
|
{
|
||||||
l = datafillct;
|
l = datafillct;
|
||||||
@ -50,7 +48,7 @@ void CLASS::print(uint32_t lineno)
|
|||||||
}
|
}
|
||||||
if (errorcode > 0)
|
if (errorcode > 0)
|
||||||
{
|
{
|
||||||
if (merlinstyle)
|
if (merlinerrors)
|
||||||
{
|
{
|
||||||
//printf("errorcode=%d\n",errorcode);
|
//printf("errorcode=%d\n",errorcode);
|
||||||
printf("\n%s in line: %d", errStrings[errorcode].c_str(), lineno + 1);
|
printf("\n%s in line: %d", errStrings[errorcode].c_str(), lineno + 1);
|
||||||
@ -77,7 +75,7 @@ void CLASS::print(uint32_t lineno)
|
|||||||
nc = nc1;
|
nc = nc1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((!isatty(STDOUT_FILENO)) || (merlinstyle))
|
if ((!isatty(STDOUT_FILENO)) || (merlinerrors))
|
||||||
{
|
{
|
||||||
nc = true;
|
nc = true;
|
||||||
}
|
}
|
||||||
@ -207,7 +205,7 @@ void CLASS::print(uint32_t lineno)
|
|||||||
pcol += printf("%s ", operand.c_str());
|
pcol += printf("%s ", operand.c_str());
|
||||||
//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());
|
||||||
}
|
}
|
||||||
if ((errorcode > 0) && (!merlinstyle))
|
if ((errorcode > 0) && (!merlinerrors))
|
||||||
{
|
{
|
||||||
while (pcol < commentcol)
|
while (pcol < commentcol)
|
||||||
{
|
{
|
||||||
@ -293,6 +291,7 @@ void CLASS::clear()
|
|||||||
operand_expr = "";
|
operand_expr = "";
|
||||||
operand_expr2 = "";
|
operand_expr2 = "";
|
||||||
addrtext = "";
|
addrtext = "";
|
||||||
|
merlinerrors = false;
|
||||||
linemx = 0;
|
linemx = 0;
|
||||||
bytect = 0;
|
bytect = 0;
|
||||||
opflags = 0;
|
opflags = 0;
|
||||||
@ -377,10 +376,12 @@ void CLASS::set(std::string line)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
|
{
|
||||||
if (c > ' ')
|
if (c > ' ')
|
||||||
{
|
{
|
||||||
opcode += c;
|
opcode += c;
|
||||||
}
|
}
|
||||||
|
#if 1
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// SGQ
|
// SGQ
|
||||||
@ -418,6 +419,40 @@ void CLASS::set(std::string line)
|
|||||||
|
|
||||||
state = 4;
|
state = 4;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// SGQ
|
||||||
|
// this is bad, but the only way I currently know how to do this.
|
||||||
|
// the problem is, is that the ASCII generating psuedo-ops in Merlin
|
||||||
|
// use any char > space and less than apostrophe, and > apostrophe
|
||||||
|
// as delimiters.
|
||||||
|
// however, those characters also contain valid opcode expression characters
|
||||||
|
// so we see a character here, it looks like a delim, and we keep reading to EOL
|
||||||
|
// which might include a comment. All of that, then goes into the operand, and
|
||||||
|
// comments cause errors on evaluation.
|
||||||
|
// So, at this point in the code, we must determine if the opcode is one of our
|
||||||
|
// ascii psuedo-ops and treat the first char as a delim.
|
||||||
|
// otherwise, we must parse the operand as an express.
|
||||||
|
// this parser should know NOTHING about what the code does...but it needs to in
|
||||||
|
// this case.
|
||||||
|
|
||||||
|
opupper = Poco::toUpper(opcode);
|
||||||
|
|
||||||
|
auto itr = a.opcodes.find(op);
|
||||||
|
if (itr != a.opcodes.end())
|
||||||
|
{
|
||||||
|
TSymbol s = itr->second;
|
||||||
|
if (1)
|
||||||
|
{
|
||||||
|
isascii = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
state = 4;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 4: // read whitespace between opcode and operand
|
case 4: // read whitespace between opcode and operand
|
||||||
if (c == ';')
|
if (c == ';')
|
||||||
@ -987,11 +1022,18 @@ void CLASS::pushopcode(std::string op, uint8_t opcode, uint16_t flags, TOpCallba
|
|||||||
opcodes.insert(p);
|
opcodes.insert(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
TSymbol *CLASS::addSymbol(std::string sym, uint32_t val, bool replace)
|
TSymbol *CLASS::addSymbol(std::string symname, uint32_t val, bool replace)
|
||||||
{
|
{
|
||||||
TSymbol *res = NULL;
|
TSymbol *res = NULL;
|
||||||
TSymbol *fnd = NULL;
|
TSymbol *fnd = NULL;
|
||||||
|
|
||||||
|
std::string sym = symname;
|
||||||
|
if (!casesen)
|
||||||
|
{
|
||||||
|
sym = Poco::toUpper(sym);
|
||||||
|
}
|
||||||
|
|
||||||
|
//printf("addSymbol: |%s|\n",sym.c_str());
|
||||||
if (sym.length() > 0)
|
if (sym.length() > 0)
|
||||||
{
|
{
|
||||||
TSymbol s;
|
TSymbol s;
|
||||||
@ -1002,7 +1044,7 @@ TSymbol *CLASS::addSymbol(std::string sym, uint32_t val, bool replace)
|
|||||||
s.value = val;
|
s.value = val;
|
||||||
s.used = false;
|
s.used = false;
|
||||||
s.cb = NULL;
|
s.cb = NULL;
|
||||||
std::pair<std::string, TSymbol> p(Poco::toUpper(sym), s);
|
std::pair<std::string, TSymbol> p(sym, s);
|
||||||
|
|
||||||
if (sym[0] == ':')
|
if (sym[0] == ':')
|
||||||
{
|
{
|
||||||
@ -1062,6 +1104,11 @@ TSymbol *CLASS::findSymbol(std::string symname)
|
|||||||
{
|
{
|
||||||
TSymbol *res = NULL;
|
TSymbol *res = NULL;
|
||||||
|
|
||||||
|
std::string sym = symname;
|
||||||
|
if (!casesen)
|
||||||
|
{
|
||||||
|
sym = Poco::toUpper(sym);
|
||||||
|
}
|
||||||
if (symname.length() > 0)
|
if (symname.length() > 0)
|
||||||
{
|
{
|
||||||
if (symname[0] == ':')
|
if (symname[0] == ':')
|
||||||
@ -1072,7 +1119,7 @@ TSymbol *CLASS::findSymbol(std::string symname)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto itr = currentsym->locals.find(Poco::toUpper(symname));
|
auto itr = currentsym->locals.find(sym);
|
||||||
if (itr != currentsym->locals.end())
|
if (itr != currentsym->locals.end())
|
||||||
{
|
{
|
||||||
res = &itr->second;
|
res = &itr->second;
|
||||||
@ -1083,7 +1130,7 @@ TSymbol *CLASS::findSymbol(std::string symname)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
//printf("finding: %s\n",symname.c_str());
|
//printf("finding: %s\n",symname.c_str());
|
||||||
auto itr = symbols.find(Poco::toUpper(symname));
|
auto itr = symbols.find(sym);
|
||||||
if (itr != symbols.end())
|
if (itr != symbols.end())
|
||||||
{
|
{
|
||||||
//printf("Found: %s 0x%08X\n",itr->second.name.c_str(),itr->second.value);
|
//printf("Found: %s 0x%08X\n",itr->second.name.c_str(),itr->second.value);
|
||||||
@ -1096,11 +1143,17 @@ out:
|
|||||||
return (res);
|
return (res);
|
||||||
}
|
}
|
||||||
|
|
||||||
TSymbol *CLASS::addVariable(std::string sym, std::string val, bool replace)
|
TSymbol *CLASS::addVariable(std::string symname, std::string val, bool replace)
|
||||||
{
|
{
|
||||||
TSymbol *res = NULL;
|
TSymbol *res = NULL;
|
||||||
TSymbol *fnd = NULL;
|
TSymbol *fnd = NULL;
|
||||||
|
|
||||||
|
std::string sym = symname;
|
||||||
|
if (!casesen)
|
||||||
|
{
|
||||||
|
sym = Poco::toUpper(sym);
|
||||||
|
}
|
||||||
|
|
||||||
//printf("addvariable\n");
|
//printf("addvariable\n");
|
||||||
fnd = findVariable(sym);
|
fnd = findVariable(sym);
|
||||||
|
|
||||||
@ -1128,7 +1181,7 @@ TSymbol *CLASS::addVariable(std::string sym, std::string val, bool replace)
|
|||||||
|
|
||||||
//printf("addvariable: %s %s\n", s.name.c_str(), s.text.c_str());
|
//printf("addvariable: %s %s\n", s.name.c_str(), s.text.c_str());
|
||||||
|
|
||||||
std::pair<std::string, TSymbol> p(Poco::toUpper(sym), s);
|
std::pair<std::string, TSymbol> p(sym, s);
|
||||||
variables.insert(p);
|
variables.insert(p);
|
||||||
res = findVariable(sym);
|
res = findVariable(sym);
|
||||||
return (res);
|
return (res);
|
||||||
@ -1389,6 +1442,8 @@ void CLASS::initpass(void)
|
|||||||
casesen = getBool("asm.casesen", true);
|
casesen = getBool("asm.casesen", true);
|
||||||
listing = getBool("asm.lst", true);
|
listing = getBool("asm.lst", true);
|
||||||
showmx = getBool("asm.showmx", false);
|
showmx = getBool("asm.showmx", false);
|
||||||
|
merlinerrors = getBool("asm.merlinerrors", true);
|
||||||
|
|
||||||
trackrep = getBool("asm.trackrep", false);
|
trackrep = getBool("asm.trackrep", false);
|
||||||
merlincompat = getBool("asm.merlincompatible", true);
|
merlincompat = getBool("asm.merlincompatible", true);
|
||||||
allowdup = getBool("asm.allowduplicate", true);
|
allowdup = getBool("asm.allowduplicate", true);
|
||||||
@ -1427,8 +1482,10 @@ void CLASS::initpass(void)
|
|||||||
}
|
}
|
||||||
mx = getInt("asm.startmx", mx);;
|
mx = getInt("asm.startmx", mx);;
|
||||||
|
|
||||||
|
|
||||||
savepath = getConfig("option.objfile", "");
|
savepath = getConfig("option.objfile", "");
|
||||||
|
|
||||||
|
lastcarry = false;
|
||||||
relocatable = false;
|
relocatable = false;
|
||||||
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;
|
||||||
currentsymstr = "";
|
currentsymstr = "";
|
||||||
@ -1485,6 +1542,14 @@ void CLASS::complete(void)
|
|||||||
f.put(line.outbytes[i]);
|
f.put(line.outbytes[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ((line.datafillct > 0) && ((line.flags & FLAG_INDUM) == 0))
|
||||||
|
{
|
||||||
|
for (uint32_t i = 0; i < line.datafillct; i++)
|
||||||
|
{
|
||||||
|
f.put(line.datafillbyte & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1618,6 +1683,35 @@ int CLASS::getAddrMode(MerlinLine & line)
|
|||||||
if (i > 0)
|
if (i > 0)
|
||||||
{
|
{
|
||||||
v = valEx.match(s, 0, 0);
|
v = valEx.match(s, 0, 0);
|
||||||
|
if (v)
|
||||||
|
{
|
||||||
|
if (pass == 0)
|
||||||
|
{
|
||||||
|
// can only check on pass 0, because if the A"
|
||||||
|
// symbol is defined later, we will generate different
|
||||||
|
// bytes on the next pass
|
||||||
|
|
||||||
|
if (Poco::toUpper(oper) == "A") // check the whole operand, not just the expression
|
||||||
|
{
|
||||||
|
// SGQ
|
||||||
|
// Merlin32 supports the 'A" operand for immediate
|
||||||
|
// mode for opcodes like "ROR A". Problem is, Merlin16
|
||||||
|
// does not, and 'A' could be a lable.
|
||||||
|
TSymbol *sym = findSymbol("A");
|
||||||
|
if (sym == NULL)
|
||||||
|
{
|
||||||
|
line.flags |= FLAG_FORCEIMPLIED;
|
||||||
|
mode = syn_implied; // if the label hasn't been defined yet, assume Immediate addressing
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (line.flags & FLAG_FORCEIMPLIED)
|
||||||
|
{
|
||||||
|
mode = syn_implied;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!v)
|
if (!v)
|
||||||
@ -1646,7 +1740,7 @@ int CLASS::getAddrMode(MerlinLine & line)
|
|||||||
}
|
}
|
||||||
idx++;
|
idx++;
|
||||||
}
|
}
|
||||||
|
out:
|
||||||
if (mode == syn_none)
|
if (mode == syn_none)
|
||||||
{
|
{
|
||||||
mode = syn_err;
|
mode = syn_err;
|
||||||
@ -1779,6 +1873,7 @@ void CLASS::process(void)
|
|||||||
line.linemx = mx;
|
line.linemx = mx;
|
||||||
line.bytect = 0;
|
line.bytect = 0;
|
||||||
line.showmx = showmx;
|
line.showmx = showmx;
|
||||||
|
line.merlinerrors = merlinerrors;
|
||||||
|
|
||||||
if ((line.lable != ""))
|
if ((line.lable != ""))
|
||||||
{
|
{
|
||||||
@ -1828,6 +1923,7 @@ void CLASS::process(void)
|
|||||||
int64_t value = -1;
|
int64_t value = -1;
|
||||||
x = evaluate(line, line.operand_expr, value);
|
x = evaluate(line, line.operand_expr, value);
|
||||||
|
|
||||||
|
line.eval_result = x;
|
||||||
if (x == 0)
|
if (x == 0)
|
||||||
{
|
{
|
||||||
value &= 0xFFFFFFFF;
|
value &= 0xFFFFFFFF;
|
||||||
|
8
asm.h
8
asm.h
@ -17,9 +17,10 @@
|
|||||||
#define FLAG_DP 0x08
|
#define FLAG_DP 0x08
|
||||||
#define FLAG_BIGNUM 0x10
|
#define FLAG_BIGNUM 0x10
|
||||||
#define FLAG_INDUM 0x20
|
#define FLAG_INDUM 0x20
|
||||||
|
#define FLAG_FORCEIMPLIED 0x40
|
||||||
|
|
||||||
#define FLAG_FORCEADDRPRINT 0x0100
|
#define FLAG_FORCEADDRPRINT 0x0100
|
||||||
#define FLAG_NOLINEPRINT 0x2000
|
#define FLAG_NOLINEPRINT 0x0200
|
||||||
|
|
||||||
#define OP_A 0x0001
|
#define OP_A 0x0001
|
||||||
#define OP_XY 0x0002
|
#define OP_XY 0x0002
|
||||||
@ -189,6 +190,7 @@ public:
|
|||||||
uint8_t linemx;
|
uint8_t linemx;
|
||||||
uint8_t tabs[16];
|
uint8_t tabs[16];
|
||||||
bool showmx;
|
bool showmx;
|
||||||
|
bool merlinerrors;
|
||||||
uint8_t truncdata;
|
uint8_t truncdata;
|
||||||
uint32_t lineno;
|
uint32_t lineno;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
@ -197,7 +199,7 @@ public:
|
|||||||
uint32_t addressmode;
|
uint32_t addressmode;
|
||||||
uint32_t expr_value;
|
uint32_t expr_value;
|
||||||
uint8_t expr_shift; // after an eval, this byte will reflect any shift code on expr (|^<>)
|
uint8_t expr_shift; // after an eval, this byte will reflect any shift code on expr (|^<>)
|
||||||
uint32_t eval_result; // this is the error code from the evaluate routing (0 or neg)
|
int32_t eval_result; // this is the error code from the evaluate routing (0 or neg)
|
||||||
uint32_t errorcode;
|
uint32_t errorcode;
|
||||||
std::string errorText;
|
std::string errorText;
|
||||||
|
|
||||||
@ -334,6 +336,7 @@ public:
|
|||||||
bool showmx;
|
bool showmx;
|
||||||
bool trackrep;
|
bool trackrep;
|
||||||
bool merlincompat;
|
bool merlincompat;
|
||||||
|
bool merlinerrors;
|
||||||
bool allowdup;
|
bool allowdup;
|
||||||
uint8_t mx;
|
uint8_t mx;
|
||||||
uint8_t cpumode; // 0=6502, 1=65C02, 2=65816
|
uint8_t cpumode; // 0=6502, 1=65C02, 2=65816
|
||||||
@ -344,6 +347,7 @@ public:
|
|||||||
uint32_t dumstartaddr;
|
uint32_t dumstartaddr;
|
||||||
bool skiplist; // used if lst is on, but LST opcode turns it off
|
bool skiplist; // used if lst is on, but LST opcode turns it off
|
||||||
uint32_t lineno;
|
uint32_t lineno;
|
||||||
|
bool lastcarry;
|
||||||
|
|
||||||
std::string savepath;
|
std::string savepath;
|
||||||
TSymbol *currentsym;
|
TSymbol *currentsym;
|
||||||
|
115
eval.cpp
115
eval.cpp
@ -27,16 +27,18 @@ std::deque<Token> CLASS::exprToTokens(const std::string& expr)
|
|||||||
int state = 0;
|
int state = 0;
|
||||||
char c;
|
char c;
|
||||||
char delim;
|
char delim;
|
||||||
std::string ident, asc;
|
std::string ident;
|
||||||
|
//, asc;
|
||||||
|
|
||||||
std::string ops = "+-*//^!.&()";
|
std::string ops = "+-*//^!.&()";
|
||||||
std::string c1;
|
std::string c1;
|
||||||
char *tokptr;
|
char *tokptr;
|
||||||
char *tptr;
|
char *tptr;
|
||||||
bool numexpect;
|
bool numexpect;
|
||||||
|
bool highascii = false;
|
||||||
Token::Type t;
|
Token::Type t;
|
||||||
|
|
||||||
delim=0;
|
delim = 0;
|
||||||
numexpect = true;
|
numexpect = true;
|
||||||
for (const auto* p = expr.c_str(); *p; ++p)
|
for (const auto* p = expr.c_str(); *p; ++p)
|
||||||
{
|
{
|
||||||
@ -56,18 +58,20 @@ std::deque<Token> CLASS::exprToTokens(const std::string& expr)
|
|||||||
if ((c < ' ') || (c == delim))
|
if ((c < ' ') || (c == delim))
|
||||||
{
|
{
|
||||||
// SGQ - convert ascii to a number here
|
// SGQ - convert ascii to a number here
|
||||||
asc = "0";
|
//asc = "0";
|
||||||
//printf("ident=|%s|\n",ident.c_str());
|
//printf("ascii ident=|%s|\n", ident.c_str());
|
||||||
if (ident.length() > 0)
|
if (ident.length() > 0)
|
||||||
{
|
{
|
||||||
// SGQ - convert ascii to a number here
|
// SGQ - convert ascii to a number here
|
||||||
}
|
}
|
||||||
t = Token::Type::Number;
|
ident = delim + ident + delim;
|
||||||
|
|
||||||
|
t = Token::Type::Ascii;
|
||||||
int pr = 1; // precedence
|
int pr = 1; // precedence
|
||||||
bool ra = false; // rightAssociative
|
bool ra = false;
|
||||||
tokens.push_back(Token
|
tokens.push_back(Token
|
||||||
{
|
{
|
||||||
t, asc, pr, ra
|
t, ident, pr, ra
|
||||||
});
|
});
|
||||||
ident = "";
|
ident = "";
|
||||||
state = 0;
|
state = 0;
|
||||||
@ -75,6 +79,8 @@ std::deque<Token> CLASS::exprToTokens(const std::string& expr)
|
|||||||
{
|
{
|
||||||
p--;
|
p--;
|
||||||
}
|
}
|
||||||
|
highascii = false;
|
||||||
|
delim = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -150,6 +156,7 @@ std::deque<Token> CLASS::exprToTokens(const std::string& expr)
|
|||||||
{
|
{
|
||||||
delim = c;
|
delim = c;
|
||||||
state = 11;
|
state = 11;
|
||||||
|
highascii = true;
|
||||||
numexpect = false;
|
numexpect = false;
|
||||||
}
|
}
|
||||||
else if (((c == '-') || (c == '+')) && (numexpect))
|
else if (((c == '-') || (c == '+')) && (numexpect))
|
||||||
@ -220,7 +227,7 @@ std::deque<Token> CLASS::shuntingYard(const std::deque<Token>& tokens)
|
|||||||
token.type = Token::Type::Number;
|
token.type = Token::Type::Number;
|
||||||
if (token.str == "*")
|
if (token.str == "*")
|
||||||
{
|
{
|
||||||
sprintf(buff, "%u", assembler.PC.currentpc);
|
sprintf(buff, "$%X", assembler.PC.currentpc);
|
||||||
token.str = buff;
|
token.str = buff;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -231,7 +238,7 @@ std::deque<Token> CLASS::shuntingYard(const std::deque<Token>& tokens)
|
|||||||
if (sym != NULL)
|
if (sym != NULL)
|
||||||
{
|
{
|
||||||
sym->used = true;
|
sym->used = true;
|
||||||
sprintf(buff, "%d", sym->value);
|
sprintf(buff, "$%X", sym->value);
|
||||||
token.str = buff;
|
token.str = buff;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -243,6 +250,7 @@ std::deque<Token> CLASS::shuntingYard(const std::deque<Token>& tokens)
|
|||||||
}
|
}
|
||||||
queue.push_back(token);
|
queue.push_back(token);
|
||||||
break;
|
break;
|
||||||
|
case Token::Type::Ascii:
|
||||||
case Token::Type::Number:
|
case Token::Type::Number:
|
||||||
// If the token is a number, then add it to the output queue
|
// If the token is a number, then add it to the output queue
|
||||||
queue.push_back(token);
|
queue.push_back(token);
|
||||||
@ -363,9 +371,54 @@ std::deque<Token> CLASS::shuntingYard(const std::deque<Token>& tokens)
|
|||||||
return queue;
|
return queue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CLASS::parseAscii(std::string n, int64_t &val)
|
||||||
|
{
|
||||||
|
int res = -1;
|
||||||
|
val = 0;
|
||||||
|
bool err = false;
|
||||||
|
uint64_t tval = 0;
|
||||||
|
bool high = false;
|
||||||
|
uint8_t c;
|
||||||
|
|
||||||
|
uint32_t l = n.length();
|
||||||
|
for (uint32_t i = 0; i < l - 1; i++)
|
||||||
|
{
|
||||||
|
c = n[i];
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
if (c == '"')
|
||||||
|
{
|
||||||
|
high = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tval <<= 8;
|
||||||
|
if (high)
|
||||||
|
{
|
||||||
|
c |= 0x80;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c &= 0x7F;
|
||||||
|
}
|
||||||
|
tval = ((tval & 0xFFFFFF00) | c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!err)
|
||||||
|
{
|
||||||
|
val = (uint32_t)(tval & 0xFFFFFFFF);
|
||||||
|
res = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//printf("parseASCII |%s| %d %016lX\n", n.c_str(), res, val);
|
||||||
|
return (res);
|
||||||
|
}
|
||||||
|
|
||||||
int CLASS::parseNumber(std::string n, int64_t &val)
|
int CLASS::parseNumber(std::string n, int64_t &val)
|
||||||
{
|
{
|
||||||
int res = DEF_VAL;
|
int res = -1;
|
||||||
int state = 0;
|
int state = 0;
|
||||||
char c;
|
char c;
|
||||||
std::string s;
|
std::string s;
|
||||||
@ -376,8 +429,7 @@ int CLASS::parseNumber(std::string n, int64_t &val)
|
|||||||
int64_t tval = 0;
|
int64_t tval = 0;
|
||||||
val = 0;
|
val = 0;
|
||||||
|
|
||||||
|
//printf("parseNumber |%s|\n",n.c_str());
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
l = n.length();
|
l = n.length();
|
||||||
s = "";
|
s = "";
|
||||||
@ -483,12 +535,13 @@ int CLASS::parseNumber(std::string n, int64_t &val)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tval > (int64_t)0xFFFFFFFF)
|
uint32_t tv = (uint32_t)tval;
|
||||||
|
uint64_t tv1 = tv;
|
||||||
|
if (tv1 > (int64_t)0xFFFFFFFF)
|
||||||
{
|
{
|
||||||
setError(Token::overflowErr);
|
setError(Token::overflowErr);
|
||||||
}
|
}
|
||||||
|
|
||||||
//printf("parsenumber: |%s|\n",s.c_str());
|
|
||||||
|
|
||||||
if ((state == 99) || (err))
|
if ((state == 99) || (err))
|
||||||
{
|
{
|
||||||
@ -507,6 +560,13 @@ int CLASS::parseNumber(std::string n, int64_t &val)
|
|||||||
//printf("value=%08lX\n", val);
|
//printf("value=%08lX\n", val);
|
||||||
res = 0;
|
res = 0;
|
||||||
}
|
}
|
||||||
|
if (res != 0)
|
||||||
|
{
|
||||||
|
if (isDebug() > 2)
|
||||||
|
{
|
||||||
|
printf("parsenumber error result: %d\n", res);
|
||||||
|
}
|
||||||
|
}
|
||||||
return (res);
|
return (res);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -527,7 +587,7 @@ int CLASS::evaluate(std::string & e, int64_t &res, uint8_t &_shiftmode)
|
|||||||
// const std::string expr = "3+4*2/(1-5)^2^3"; // Wikipedia's example
|
// const std::string expr = "3+4*2/(1-5)^2^3"; // Wikipedia's example
|
||||||
// const std::string expr = "20-30/3+4*2^3";
|
// const std::string expr = "20-30/3+4*2^3";
|
||||||
|
|
||||||
_shiftmode=shiftmode=0;
|
_shiftmode = shiftmode = 0;
|
||||||
res = DEF_VAL;
|
res = DEF_VAL;
|
||||||
setError(Token::noError);
|
setError(Token::noError);
|
||||||
|
|
||||||
@ -560,6 +620,19 @@ int CLASS::evaluate(std::string & e, int64_t &res, uint8_t &_shiftmode)
|
|||||||
//op = "Push " + token.str;
|
//op = "Push " + token.str;
|
||||||
//printf("shouldn't get this kind of token\n");
|
//printf("shouldn't get this kind of token\n");
|
||||||
break;
|
break;
|
||||||
|
case Token::Type::Ascii:
|
||||||
|
|
||||||
|
val = 0;
|
||||||
|
u = parseAscii(token.str, val);
|
||||||
|
if (u < 0)
|
||||||
|
{
|
||||||
|
setError(Token::numberErr);
|
||||||
|
val = DEF_VAL;
|
||||||
|
}
|
||||||
|
stack.push_back(val);
|
||||||
|
//op = "Push " + token.str;
|
||||||
|
break;
|
||||||
|
|
||||||
case Token::Type::Number:
|
case Token::Type::Number:
|
||||||
val = 0;
|
val = 0;
|
||||||
u = parseNumber(token.str, val);
|
u = parseNumber(token.str, val);
|
||||||
@ -580,21 +653,21 @@ int CLASS::evaluate(std::string & e, int64_t &res, uint8_t &_shiftmode)
|
|||||||
{
|
{
|
||||||
rhs = stack.back();
|
rhs = stack.back();
|
||||||
stack.pop_back();
|
stack.pop_back();
|
||||||
shiftmode=token.str[0];
|
shiftmode = token.str[0];
|
||||||
|
|
||||||
if (token.str=="^")
|
if (token.str == "^")
|
||||||
{
|
{
|
||||||
//rhs = (rhs >> 16) &0xFFFF ;
|
//rhs = (rhs >> 16) &0xFFFF ;
|
||||||
}
|
}
|
||||||
else if (token.str=="|")
|
else if (token.str == "|")
|
||||||
{
|
{
|
||||||
//rhs = (rhs >> 16) & 0xFFFF;
|
//rhs = (rhs >> 16) & 0xFFFF;
|
||||||
}
|
}
|
||||||
else if (token.str=="<")
|
else if (token.str == "<")
|
||||||
{
|
{
|
||||||
//rhs = (rhs << 8 ) & 0xFFFF;
|
//rhs = (rhs << 8 ) & 0xFFFF;
|
||||||
}
|
}
|
||||||
else if (token.str==">")
|
else if (token.str == ">")
|
||||||
{
|
{
|
||||||
//rhs=(rhs>>8) & 0xFFFF;
|
//rhs=(rhs>>8) & 0xFFFF;
|
||||||
}
|
}
|
||||||
@ -698,7 +771,7 @@ out:
|
|||||||
{
|
{
|
||||||
setError(Token::syntaxErr);
|
setError(Token::syntaxErr);
|
||||||
}
|
}
|
||||||
_shiftmode=shiftmode;
|
_shiftmode = shiftmode;
|
||||||
res = v;
|
res = v;
|
||||||
return (evalerror);
|
return (evalerror);
|
||||||
}
|
}
|
||||||
|
3
eval.h
3
eval.h
@ -41,6 +41,7 @@ public:
|
|||||||
Unknown = 0,
|
Unknown = 0,
|
||||||
Number,
|
Number,
|
||||||
Symbol,
|
Symbol,
|
||||||
|
Ascii,
|
||||||
Shift,
|
Shift,
|
||||||
Operator,
|
Operator,
|
||||||
LeftParen,
|
LeftParen,
|
||||||
@ -71,6 +72,8 @@ public:
|
|||||||
std::deque<Token> shuntingYard(const std::deque<Token>& tokens);
|
std::deque<Token> shuntingYard(const std::deque<Token>& tokens);
|
||||||
std::deque<Token> exprToTokens(const std::string& expr);
|
std::deque<Token> exprToTokens(const std::string& expr);
|
||||||
int parseNumber(std::string n, int64_t &val);
|
int parseNumber(std::string n, int64_t &val);
|
||||||
|
int parseAscii(std::string n, int64_t &val);
|
||||||
|
|
||||||
int evaluate(std::string &expr, int64_t &res, uint8_t &_shiftmode);
|
int evaluate(std::string &expr, int64_t &res, uint8_t &_shiftmode);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
54
opcodes.cpp
54
opcodes.cpp
@ -226,7 +226,7 @@ int CLASS::doNoPattern(MerlinLine &line, TSymbol &sym)
|
|||||||
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++;
|
res++;
|
||||||
op = (op == 0x64) ? 0x9C : op;
|
op = (op == 0x64) ? 0x9C : op;
|
||||||
@ -236,7 +236,7 @@ int CLASS::doNoPattern(MerlinLine &line, TSymbol &sym)
|
|||||||
case 2: // TSB
|
case 2: // TSB
|
||||||
res++;
|
res++;
|
||||||
op = (m == syn_abs ? 0x04 : op);
|
op = (m == syn_abs ? 0x04 : op);
|
||||||
if ((op != 0) && ((line.expr_value >= 0x100) || (line.flags&FLAG_FORCEABS)))
|
if ((op != 0) && ((line.expr_value >= 0x100) || (line.flags & FLAG_FORCEABS)))
|
||||||
{
|
{
|
||||||
res++;
|
res++;
|
||||||
op = 0x0C;
|
op = 0x0C;
|
||||||
@ -245,7 +245,7 @@ int CLASS::doNoPattern(MerlinLine &line, TSymbol &sym)
|
|||||||
case 3: // TRB
|
case 3: // TRB
|
||||||
res++;
|
res++;
|
||||||
op = (m == syn_abs ? 0x14 : op);
|
op = (m == syn_abs ? 0x14 : op);
|
||||||
if ((op != 0) && ((line.expr_value >= 0x100) || (line.flags&FLAG_FORCEABS)))
|
if ((op != 0) && ((line.expr_value >= 0x100) || (line.flags & FLAG_FORCEABS)))
|
||||||
{
|
{
|
||||||
res++;
|
res++;
|
||||||
op = 0x1C;
|
op = 0x1C;
|
||||||
@ -422,7 +422,7 @@ int CLASS::doBRANCH(MerlinLine & line, TSymbol & sym)
|
|||||||
if ((offset < -128) || (offset > 127))
|
if ((offset < -128) || (offset > 127))
|
||||||
{
|
{
|
||||||
err = true;
|
err = true;
|
||||||
op=0x00; // merlin does this
|
op = 0x00; // merlin does this
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (res == 3) // long branch
|
else if (res == 3) // long branch
|
||||||
@ -439,8 +439,8 @@ int CLASS::doBRANCH(MerlinLine & line, TSymbol & sym)
|
|||||||
setOpcode(line, op);
|
setOpcode(line, op);
|
||||||
for (i = 0; i < (res - 1); i++)
|
for (i = 0; i < (res - 1); i++)
|
||||||
{
|
{
|
||||||
uint8_t v=(offset >> (i*8));
|
uint8_t v = (offset >> (i * 8));
|
||||||
v=err?0x00:v;
|
v = err ? 0x00 : v;
|
||||||
line.outbytes.push_back(v);
|
line.outbytes.push_back(v);
|
||||||
}
|
}
|
||||||
line.outbytect = res;
|
line.outbytect = res;
|
||||||
@ -489,7 +489,7 @@ int CLASS::doBase6502(MerlinLine & line, TSymbol & sym)
|
|||||||
bbb = 0x02;
|
bbb = 0x02;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if ((bbb > 0) && ((line.expr_value >= 0x100) || (line.flags&FLAG_FORCEABS)))
|
else if ((bbb > 0) && ((line.expr_value >= 0x100) || (line.flags & FLAG_FORCEABS)))
|
||||||
{
|
{
|
||||||
bbb |= 0x02;
|
bbb |= 0x02;
|
||||||
bytelen++;
|
bytelen++;
|
||||||
@ -571,9 +571,9 @@ int CLASS::doBase6502(MerlinLine & line, TSymbol & sym)
|
|||||||
bytelen++;
|
bytelen++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( ((m==syn_absx) || (m==syn_diix)) && ((sym.opcode==4) || (sym.opcode==5))) // these are STX,LDX
|
if ( ((m == syn_absx) || (m == syn_diix)) && ((sym.opcode == 4) || (sym.opcode == 5))) // these are STX,LDX
|
||||||
{
|
{
|
||||||
err=true;
|
err = true;
|
||||||
}
|
}
|
||||||
if ((m == syn_absx) || (m == syn_abs) || (m == syn_absy))
|
if ((m == syn_absx) || (m == syn_abs) || (m == syn_absy))
|
||||||
{
|
{
|
||||||
@ -747,6 +747,30 @@ int CLASS::doBYTE(MerlinLine & line, TSymbol & sym)
|
|||||||
setOpcode(line, sym.opcode);
|
setOpcode(line, sym.opcode);
|
||||||
line.outbytect = res;
|
line.outbytect = res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SGQ merlin32 apparently tracks XCE instructions when tracking MX status
|
||||||
|
// who know how they determine this. I am assuming the NEXT instruction
|
||||||
|
// after a SEC/CLC instruction must be an XCE
|
||||||
|
if (sym.opcode == 0x38) // SEC
|
||||||
|
{
|
||||||
|
lastcarry = true;
|
||||||
|
}
|
||||||
|
else if (sym.opcode == 0x18) // CLC
|
||||||
|
{
|
||||||
|
lastcarry = false;
|
||||||
|
}
|
||||||
|
else if (sym.opcode==0xFB) // XCE
|
||||||
|
{
|
||||||
|
if (trackrep)
|
||||||
|
{
|
||||||
|
if (lastcarry)
|
||||||
|
{
|
||||||
|
mx=0x03;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return (res);
|
return (res);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -755,23 +779,23 @@ int CLASS::doBRK(MerlinLine & line, TSymbol & sym)
|
|||||||
UNUSED(sym);
|
UNUSED(sym);
|
||||||
|
|
||||||
int res = 1;
|
int res = 1;
|
||||||
int bytes=0;
|
int bytes = 0;
|
||||||
|
|
||||||
if (line.operand_expr!="")
|
if (line.operand_expr != "")
|
||||||
{
|
{
|
||||||
bytes++;
|
bytes++;
|
||||||
}
|
}
|
||||||
if (pass > 0)
|
if (pass > 0)
|
||||||
{
|
{
|
||||||
setOpcode(line, sym.opcode);
|
setOpcode(line, sym.opcode);
|
||||||
for (int i=0;i<bytes;i++)
|
for (int i = 0; i < bytes; i++)
|
||||||
{
|
{
|
||||||
line.outbytes.push_back((line.expr_value>>(8*i))&0xFF);
|
line.outbytes.push_back((line.expr_value >> (8 * i)) & 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
line.outbytect = res+bytes;
|
line.outbytect = res + bytes;
|
||||||
}
|
}
|
||||||
return (res+bytes);
|
return (res + bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CLASS::insertOpcodes(void)
|
void CLASS::insertOpcodes(void)
|
||||||
|
196
psuedo.cpp
196
psuedo.cpp
@ -14,13 +14,30 @@ CLASS::~CLASS()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t CLASS::doShift(uint32_t value, uint8_t shift)
|
||||||
|
{
|
||||||
|
if (shift == '<')
|
||||||
|
{
|
||||||
|
value = (value) & 0xFF;
|
||||||
|
}
|
||||||
|
if (shift == '>')
|
||||||
|
{
|
||||||
|
value = (value >> 8) & 0xFF;
|
||||||
|
}
|
||||||
|
else if ((shift == '^') || (shift == '|'))
|
||||||
|
{
|
||||||
|
value = (value >> 16) & 0xFF;
|
||||||
|
}
|
||||||
|
return (value);
|
||||||
|
}
|
||||||
|
|
||||||
int CLASS::doDO(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
int CLASS::doDO(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
||||||
{
|
{
|
||||||
UNUSED(opinfo);
|
UNUSED(opinfo);
|
||||||
|
|
||||||
TEvaluator eval(a);
|
TEvaluator eval(a);
|
||||||
|
|
||||||
int64_t eval_result = 0;
|
int64_t eval_value = 0;
|
||||||
uint8_t shift;
|
uint8_t shift;
|
||||||
uint32_t result32;
|
uint32_t result32;
|
||||||
int res = 0;
|
int res = 0;
|
||||||
@ -51,8 +68,8 @@ int CLASS::doDO(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
shift = 0;
|
shift = 0;
|
||||||
eval_result = 0;
|
eval_value = 0;
|
||||||
int x = eval.evaluate(line.operand_expr, eval_result, shift);
|
int x = eval.evaluate(line.operand_expr, eval_value, shift);
|
||||||
|
|
||||||
if (x < 0)
|
if (x < 0)
|
||||||
{
|
{
|
||||||
@ -65,7 +82,7 @@ int CLASS::doDO(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
result32 = eval_result & 0xFFFFFFFF;
|
result32 = eval_value & 0xFFFFFFFF;
|
||||||
a.curDO.doskip = (result32 != 0) ? false : true;
|
a.curDO.doskip = (result32 != 0) ? false : true;
|
||||||
|
|
||||||
goto out;
|
goto out;
|
||||||
@ -119,7 +136,7 @@ int CLASS::doLUP(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
|||||||
|
|
||||||
TEvaluator eval(a);
|
TEvaluator eval(a);
|
||||||
|
|
||||||
int64_t eval_result = 0;
|
int64_t eval_value = 0;
|
||||||
uint8_t shift;
|
uint8_t shift;
|
||||||
int lidx, len;
|
int lidx, len;
|
||||||
int res = 0;
|
int res = 0;
|
||||||
@ -135,16 +152,16 @@ int CLASS::doLUP(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
|||||||
{
|
{
|
||||||
|
|
||||||
shift = 0;
|
shift = 0;
|
||||||
eval_result = 0;
|
eval_value = 0;
|
||||||
int x = eval.evaluate(line.operand_expr, eval_result, shift);
|
int x = eval.evaluate(line.operand_expr, eval_value, shift);
|
||||||
|
|
||||||
a.LUPstack.push(a.curLUP);
|
a.LUPstack.push(a.curLUP);
|
||||||
|
|
||||||
a.curLUP.lupoffset = len;
|
a.curLUP.lupoffset = len;
|
||||||
a.curLUP.lupct = eval_result & 0xFFFF; // evaluate here
|
a.curLUP.lupct = eval_value & 0xFFFF; // evaluate here
|
||||||
a.curLUP.luprunning++;
|
a.curLUP.luprunning++;
|
||||||
|
|
||||||
if ((x < 0) || (eval_result <= 0) || (eval_result > 0x8000))
|
if ((x < 0) || (eval_value <= 0) || (eval_value > 0x8000))
|
||||||
{
|
{
|
||||||
// merlin just ignores LUP if the value is out of range
|
// merlin just ignores LUP if the value is out of range
|
||||||
a.curLUP.lupct = 0;
|
a.curLUP.lupct = 0;
|
||||||
@ -226,6 +243,9 @@ int CLASS::doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
|||||||
|
|
||||||
//printf("DFB TOK1 : |%s|\n", oper.c_str());
|
//printf("DFB TOK1 : |%s|\n", oper.c_str());
|
||||||
|
|
||||||
|
|
||||||
|
line.eval_result = 0; // since this is an data p-op, clear the global 'bad operand' flag
|
||||||
|
|
||||||
Poco::StringTokenizer tok(oper, ",", Poco::StringTokenizer::TOK_TRIM |
|
Poco::StringTokenizer tok(oper, ",", Poco::StringTokenizer::TOK_TRIM |
|
||||||
Poco::StringTokenizer::TOK_IGNORE_EMPTY);
|
Poco::StringTokenizer::TOK_IGNORE_EMPTY);
|
||||||
|
|
||||||
@ -264,7 +284,7 @@ int CLASS::doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
|||||||
|
|
||||||
//printf("DFB TOK : |%s|\n", expr.c_str());
|
//printf("DFB TOK : |%s|\n", expr.c_str());
|
||||||
|
|
||||||
int64_t eval_result = 0;
|
int64_t eval_value = 0;
|
||||||
uint8_t shift;
|
uint8_t shift;
|
||||||
int r;
|
int r;
|
||||||
uint8_t b;
|
uint8_t b;
|
||||||
@ -277,9 +297,9 @@ int CLASS::doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
|||||||
expr = Poco::trim(expr);
|
expr = Poco::trim(expr);
|
||||||
}
|
}
|
||||||
shift = 0;
|
shift = 0;
|
||||||
eval_result = 0;
|
eval_value = 0;
|
||||||
//printf("DFB EVAL: |%s|\n", expr.c_str());
|
//printf("DFB EVAL: |%s|\n", expr.c_str());
|
||||||
r = eval.evaluate(expr, eval_result, shift);
|
r = eval.evaluate(expr, eval_value, shift);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
{
|
{
|
||||||
//printf("error %d\n",r);
|
//printf("error %d\n",r);
|
||||||
@ -288,18 +308,7 @@ int CLASS::doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
|||||||
line.setError(errBadEvaluation);
|
line.setError(errBadEvaluation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (shift == '>')
|
eval_value = (uint64_t)doShift((uint32_t)eval_value, shift);
|
||||||
{
|
|
||||||
eval_result = (eval_result) & 0xFF;
|
|
||||||
}
|
|
||||||
if (shift == '<')
|
|
||||||
{
|
|
||||||
eval_result = (eval_result >> 8) & 0xFF;
|
|
||||||
}
|
|
||||||
else if ((shift == '^') || (shift == '|'))
|
|
||||||
{
|
|
||||||
eval_result = (eval_result >> 16) & 0xFF;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
outct += wordsize;
|
outct += wordsize;
|
||||||
@ -309,7 +318,7 @@ int CLASS::doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
|||||||
{
|
{
|
||||||
for (i = 0; i < wordsize; i++)
|
for (i = 0; i < wordsize; i++)
|
||||||
{
|
{
|
||||||
b = (eval_result >> (8 * i)) & 0xFF;
|
b = (eval_value >> (8 * i)) & 0xFF;
|
||||||
line.outbytes.push_back(b);
|
line.outbytes.push_back(b);
|
||||||
//printf("%02X\n",b);
|
//printf("%02X\n",b);
|
||||||
}
|
}
|
||||||
@ -319,7 +328,7 @@ int CLASS::doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
|||||||
// big endian
|
// big endian
|
||||||
for (i = 0; i < wordsize; i++)
|
for (i = 0; i < wordsize; i++)
|
||||||
{
|
{
|
||||||
b = (eval_result >> ((wordsize - 1 - i) * 8)) & 0xFF;
|
b = (eval_value >> ((wordsize - 1 - i) * 8)) & 0xFF;
|
||||||
line.outbytes.push_back(b);
|
line.outbytes.push_back(b);
|
||||||
//printf("%02X\n",b);
|
//printf("%02X\n",b);
|
||||||
}
|
}
|
||||||
@ -336,23 +345,87 @@ int CLASS::doDS(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
|||||||
UNUSED(opinfo);
|
UNUSED(opinfo);
|
||||||
|
|
||||||
int res = 0;
|
int res = 0;
|
||||||
int32_t v = line.expr_value;
|
|
||||||
if (line.eval_result != 0)
|
TEvaluator eval(a);
|
||||||
|
|
||||||
|
int64_t eval_value = 0;
|
||||||
|
uint8_t shift;
|
||||||
|
|
||||||
|
line.eval_result = 0; // since this is an data p-op, clear the global 'bad operand' flag
|
||||||
|
line.flags|=FLAG_FORCEADDRPRINT;
|
||||||
|
std::string s;
|
||||||
|
Poco::StringTokenizer tok(line.operand, ",", Poco::StringTokenizer::TOK_TRIM |
|
||||||
|
Poco::StringTokenizer::TOK_IGNORE_EMPTY);
|
||||||
|
|
||||||
|
int32_t datact = 0;
|
||||||
|
uint8_t fill = 0x0;
|
||||||
|
bool pagefill = false;
|
||||||
|
int32_t v = 0;
|
||||||
|
|
||||||
|
|
||||||
|
int ct = 0;
|
||||||
|
for (auto itr = tok.begin(); itr != tok.end(); ++itr)
|
||||||
{
|
{
|
||||||
line.setError(errForwardRef);
|
s = *itr;
|
||||||
}
|
if (ct == 0)
|
||||||
else if ((v < 0) || ((a.PC.currentpc + v) >= 0x10000)) // no neg, or crossing bank bound
|
|
||||||
{
|
{
|
||||||
line.setError(errOverflow);
|
if (s == "\\")
|
||||||
|
{
|
||||||
|
pagefill = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
res = v;
|
|
||||||
|
|
||||||
line.datafillbyte = line.eval_result & 0xFF;
|
|
||||||
line.datafillct = v;
|
|
||||||
|
|
||||||
|
shift = 0;
|
||||||
|
eval_value = 0;
|
||||||
|
int x = eval.evaluate(s, eval_value, shift);
|
||||||
|
if (x < 0)
|
||||||
|
{
|
||||||
|
line.setError(errBadOperand);
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
eval_value = (uint64_t)doShift((uint32_t)eval_value, shift);
|
||||||
|
datact = eval_value & 0xFFFF;
|
||||||
|
if (datact < 0)
|
||||||
|
{
|
||||||
|
line.setError(errBadOperand);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ct == 1)
|
||||||
|
{
|
||||||
|
|
||||||
|
shift = 0;
|
||||||
|
eval_value = 0;
|
||||||
|
int x = eval.evaluate(s, eval_value, shift);
|
||||||
|
if (x < 0)
|
||||||
|
{
|
||||||
|
line.setError(errBadOperand);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
eval_value = (uint64_t)doShift((uint32_t)eval_value, shift);
|
||||||
|
fill = eval_value & 0xFF;
|
||||||
|
}
|
||||||
|
else if (ct > 1)
|
||||||
|
{
|
||||||
|
line.setError(errBadOperand);
|
||||||
|
}
|
||||||
|
ct++;
|
||||||
|
}
|
||||||
|
|
||||||
|
line.datafillbyte = fill;
|
||||||
|
v = datact;
|
||||||
|
if (pagefill)
|
||||||
|
{
|
||||||
|
v=line.startpc&0xFF;
|
||||||
|
v=0x100-v;
|
||||||
|
}
|
||||||
|
line.datafillct = (uint16_t)v & 0xFFFF;
|
||||||
|
res=line.datafillct;
|
||||||
|
|
||||||
|
out:
|
||||||
|
//printf("res=%d %04X\n",res,res);
|
||||||
return (res);
|
return (res);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -468,6 +541,8 @@ int CLASS::doHEX(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
|||||||
|
|
||||||
std::string os = Poco::trim(line.operand);
|
std::string os = Poco::trim(line.operand);
|
||||||
|
|
||||||
|
line.eval_result = 0; // since this is an data p-op, clear the global 'bad operand' flag
|
||||||
|
|
||||||
uint32_t bytect = 0;
|
uint32_t bytect = 0;
|
||||||
uint8_t b = 0;
|
uint8_t b = 0;
|
||||||
uint8_t ct = 0;
|
uint8_t ct = 0;
|
||||||
@ -528,19 +603,21 @@ int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
|||||||
std::string os = line.operand;
|
std::string os = line.operand;
|
||||||
std::string op = Poco::toUpper(line.opcode);
|
std::string op = Poco::toUpper(line.opcode);
|
||||||
|
|
||||||
uint8_t lastdelimbyte = 0x00;
|
uint8_t firstdelim = 0;
|
||||||
uint8_t firstdelim = 0xFF;
|
|
||||||
uint32_t bytect = 0;
|
uint32_t bytect = 0;
|
||||||
uint8_t b = 0;
|
uint8_t b = 0;
|
||||||
uint8_t b1;
|
uint8_t b1;
|
||||||
uint8_t ct = 0;
|
uint8_t ct = 0;
|
||||||
char delimiter = 0;
|
uint8_t delimiter = 0;
|
||||||
uint32_t ss = 0;
|
uint32_t ss = 0;
|
||||||
|
uint32_t lastdelimidx = 0;
|
||||||
|
|
||||||
std::vector<uint8_t> bytes;
|
std::vector<uint8_t> bytes;
|
||||||
|
|
||||||
|
line.eval_result = 0; // since this is an ASCII p-op, clear the global 'bad operand' flag
|
||||||
for ( uint32_t i = 0; i < os.length(); ++i )
|
for ( uint32_t i = 0; i < os.length(); ++i )
|
||||||
{
|
{
|
||||||
char c = os[i];
|
uint8_t c = os[i];
|
||||||
|
|
||||||
// are we inside a delimited string?
|
// are we inside a delimited string?
|
||||||
if ( delimiter )
|
if ( delimiter )
|
||||||
@ -562,9 +639,9 @@ int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
|||||||
{
|
{
|
||||||
c |= 0x80;
|
c |= 0x80;
|
||||||
}
|
}
|
||||||
lastdelimbyte = c;
|
|
||||||
bytes.push_back(c);
|
bytes.push_back(c);
|
||||||
//line.outbytes.push_back(c);
|
lastdelimidx = (uint32_t)(bytes.size() - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -587,7 +664,7 @@ int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
|||||||
{
|
{
|
||||||
// if not a hex value, then consider the character to be the string delimiter
|
// if not a hex value, then consider the character to be the string delimiter
|
||||||
delimiter = c;
|
delimiter = c;
|
||||||
if (firstdelim == 0xFF)
|
if( ! firstdelim )
|
||||||
{
|
{
|
||||||
firstdelim = c;
|
firstdelim = c;
|
||||||
}
|
}
|
||||||
@ -615,7 +692,6 @@ int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
|||||||
if (a.pass > 0)
|
if (a.pass > 0)
|
||||||
{
|
{
|
||||||
bytes.push_back(b);
|
bytes.push_back(b);
|
||||||
//line.outbytes.push_back(b);
|
|
||||||
}
|
}
|
||||||
b = 0;
|
b = 0;
|
||||||
bytect++;
|
bytect++;
|
||||||
@ -636,8 +712,7 @@ int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
|||||||
uint8_t andval = 0xFF;
|
uint8_t andval = 0xFF;
|
||||||
uint8_t orval = 0x00;
|
uint8_t orval = 0x00;
|
||||||
uint8_t addlen = 0;
|
uint8_t addlen = 0;
|
||||||
uint8_t firstbyte = 0x00;
|
uint32_t truebytect = (uint32_t)bytes.size();
|
||||||
uint32_t truebytect = bytes.size();
|
|
||||||
const char *ptr = (const char *)op.c_str();
|
const char *ptr = (const char *)op.c_str();
|
||||||
//printf("bytect=%d bytes.size()=%zu\n",bytect,bytes.size());
|
//printf("bytect=%d bytes.size()=%zu\n",bytect,bytes.size());
|
||||||
switch (strhash(ptr) )
|
switch (strhash(ptr) )
|
||||||
@ -686,24 +761,31 @@ int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
|||||||
{
|
{
|
||||||
b = bytes[i];
|
b = bytes[i];
|
||||||
}
|
}
|
||||||
if (!i)
|
|
||||||
{
|
|
||||||
firstbyte = b;
|
|
||||||
}
|
|
||||||
b1 = b & 0x7F;
|
b1 = b & 0x7F;
|
||||||
if ((andval!=0xFF) || (orval!=0x00))
|
if ((andval != 0xFF) || (orval != 0x00))
|
||||||
b=b1;
|
{
|
||||||
|
b = b1;
|
||||||
|
}
|
||||||
|
|
||||||
if ((b1 < 0x60))
|
if ((b1 < 0x60))
|
||||||
{
|
{
|
||||||
b &= andval; // strip whatever bits needed to flash or invert
|
b &= andval; // strip whatever bits needed to flash or invert
|
||||||
b |= orval;
|
b |= orval;
|
||||||
}
|
}
|
||||||
if ((dci) && (i == (truebytect - 1)))
|
|
||||||
|
if (dci && (i == lastdelimidx))
|
||||||
{
|
{
|
||||||
// this one might be a bug. I am going to compare the first byte in the string for
|
//lr - Merlin only toggles the high bit of string chars, not hex values
|
||||||
// bit seven, and invert it on this byte. The confusion arises because this text string
|
// 8D,'Hello',8D,'there',8D becomes 8D 48 65 6C 6C 6F 8D 74 68 65 72 E5
|
||||||
// could have high ASCII, but low HEX values.
|
//
|
||||||
if (firstbyte < 0x80)
|
// 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;
|
||||||
}
|
}
|
||||||
|
2
psuedo.h
2
psuedo.h
@ -28,6 +28,8 @@ class CLASS
|
|||||||
public:
|
public:
|
||||||
CLASS();
|
CLASS();
|
||||||
~CLASS();
|
~CLASS();
|
||||||
|
uint32_t doShift(uint32_t value, uint8_t shift);
|
||||||
|
|
||||||
int ProcessOpcode(T65816Asm &a, MerlinLine &line, TSymbol &opinfo);
|
int ProcessOpcode(T65816Asm &a, MerlinLine &line, TSymbol &opinfo);
|
||||||
int doLST(T65816Asm &a, MerlinLine &line, TSymbol &opinfo);
|
int doLST(T65816Asm &a, MerlinLine &line, TSymbol &opinfo);
|
||||||
int doDUM(T65816Asm &a, MerlinLine &line, TSymbol &opinfo);
|
int doDUM(T65816Asm &a, MerlinLine &line, TSymbol &opinfo);
|
||||||
|
3
qasm.ini
3
qasm.ini
@ -26,8 +26,9 @@ startmx=3
|
|||||||
lst=true
|
lst=true
|
||||||
; can be M6502, M65C02, M65816
|
; can be M6502, M65C02, M65816
|
||||||
cpu=M65816
|
cpu=M65816
|
||||||
trackrep=false
|
trackrep=true
|
||||||
allowduplicate=true
|
allowduplicate=true
|
||||||
|
merlinerrors=false
|
||||||
merlincompatible=true
|
merlincompatible=true
|
||||||
symcolumns=3
|
symcolumns=3
|
||||||
|
|
||||||
|
@ -415,6 +415,8 @@ L00BC bit L00BC
|
|||||||
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
|
||||||
|
|
||||||
lst
|
lst
|
||||||
lup_start:
|
lup_start:
|
||||||
|
4
testdata/2007-labels-and-symbols.S
vendored
4
testdata/2007-labels-and-symbols.S
vendored
@ -160,7 +160,7 @@ nosym equ $3300 ;should not match anything
|
|||||||
lda projalso
|
lda projalso
|
||||||
lda nosym
|
lda nosym
|
||||||
|
|
||||||
bra :next
|
bra next
|
||||||
|
|
||||||
target0 nop
|
target0 nop
|
||||||
target1 nop ;point everything here
|
target1 nop ;point everything here
|
||||||
@ -186,7 +186,7 @@ t4a jml target0
|
|||||||
t4b jml target1
|
t4b jml target1
|
||||||
t4c jml target2
|
t4c jml target2
|
||||||
|
|
||||||
:next
|
next
|
||||||
jsr t0
|
jsr t0
|
||||||
jsr t1a
|
jsr t1a
|
||||||
jsr t1b
|
jsr t1b
|
||||||
|
Loading…
Reference in New Issue
Block a user