mirror of
https://github.com/marketideas/qasm.git
synced 2024-06-02 08:41:27 +00:00
commit
a68c741800
|
@ -5,7 +5,7 @@ project(QAsm)
|
|||
|
||||
set(CIDER "0")
|
||||
|
||||
set(CMAKE_BUILD_TYPE DEBUG)
|
||||
#set(CMAKE_BUILD_TYPE DEBUG)
|
||||
set(APPVERSION "4.0.9")
|
||||
set(LIBRARY_NAME pal)
|
||||
set(FIND_LIBRARY_USE_LIB64_PATHS TRUE)
|
||||
|
@ -24,7 +24,10 @@ set(SOURCE
|
|||
|
||||
#find_package(OpenSSL REQUIRED)
|
||||
find_package( Poco REQUIRED Foundation Util XML JSON )
|
||||
|
||||
if ( ${CIDER} )
|
||||
find_package( ZLIB )
|
||||
endif ( ${CIDER} )
|
||||
|
||||
include_directories(BEFORE
|
||||
${PROJECT_ROOT}
|
||||
|
|
17
Makefile
17
Makefile
|
@ -18,13 +18,26 @@ endif
|
|||
|
||||
all:
|
||||
-mkdir -p ./build
|
||||
-cd ./build && cmake .. && $(MAKE) $S
|
||||
-cd ./build && cmake -DCMAKE_BUILD_TYPE=DEBUG .. && $(MAKE) $S
|
||||
|
||||
release:
|
||||
-rm -rf ./build
|
||||
-mkdir -p ./build
|
||||
-cd ./build && cmake -DCMAKE_BUILD_TYPE=RELEASE .. && $(MAKE) $S
|
||||
|
||||
debug:
|
||||
-rm -rf ./build
|
||||
-mkdir -p ./build
|
||||
-cd ./build && cmake -DCMAKE_BUILD_TYPE=DEBUG .. && $(MAKE) $S
|
||||
|
||||
|
||||
distclean:
|
||||
rm -rf ./build
|
||||
-rm -rf ./testout
|
||||
|
||||
clean:
|
||||
-rm -rf ./build
|
||||
-rm -rf ./testout
|
||||
|
||||
depend:
|
||||
-cd ./build && $(MAKE) depend
|
||||
|
@ -42,7 +55,7 @@ reformat:
|
|||
qasm -x REFORMAT src/main.s
|
||||
|
||||
compare:
|
||||
-bcompare . ../lane_hex &
|
||||
-bcompare . ../lane_qasm &
|
||||
|
||||
asm:
|
||||
|
||||
|
|
238
asm.cpp
238
asm.cpp
|
@ -30,7 +30,7 @@ void CLASS::print(uint32_t lineno)
|
|||
static bool checked = false;
|
||||
static bool nc1 = false;
|
||||
bool nc = false;
|
||||
uint8_t commentcol=tabs[2];
|
||||
uint8_t commentcol = tabs[2];
|
||||
|
||||
uint32_t b = 4; // how many bytes show on the first line
|
||||
|
||||
|
@ -56,7 +56,7 @@ void CLASS::print(uint32_t lineno)
|
|||
printf("\n%s in line: %d", errStrings[errorcode].c_str(), lineno + 1);
|
||||
if (errorText != "")
|
||||
{
|
||||
printf("%s", errorText.c_str());
|
||||
printf(" (%s)", errorText.c_str());
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
@ -194,17 +194,17 @@ void CLASS::print(uint32_t lineno)
|
|||
}
|
||||
else
|
||||
{
|
||||
pcol += printf("%s ",printlable.c_str());
|
||||
pcol += printf("%s ", printlable.c_str());
|
||||
while (pcol < tabs[0])
|
||||
{
|
||||
pcol += printf(" ");
|
||||
}
|
||||
pcol+=printf("%s ",opcode.c_str());
|
||||
pcol += printf("%s ", opcode.c_str());
|
||||
while (pcol < tabs[1])
|
||||
{
|
||||
pcol += printf(" ");
|
||||
}
|
||||
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());
|
||||
}
|
||||
if ((errorcode > 0) && (!merlinstyle))
|
||||
|
@ -213,7 +213,11 @@ void CLASS::print(uint32_t lineno)
|
|||
{
|
||||
pcol += printf(" ");
|
||||
}
|
||||
pcol += printf(":[Error] %s %s", errStrings[errorcode].c_str(), errorText.c_str());
|
||||
pcol += printf(":[Error] %s", errStrings[errorcode].c_str());
|
||||
if (errorText.length() > 0)
|
||||
{
|
||||
pcol += printf(" (%s)", errorText.c_str());
|
||||
}
|
||||
}
|
||||
else if (!commentprinted)
|
||||
{
|
||||
|
@ -315,9 +319,12 @@ void CLASS::set(std::string line)
|
|||
int i = 0;
|
||||
int x;
|
||||
char c, delim;
|
||||
bool isascii;
|
||||
std::string opupper;
|
||||
|
||||
clear();
|
||||
|
||||
isascii = false;
|
||||
delim = 0;
|
||||
//printf("line: |%s|\n", line.c_str());
|
||||
while (i < l)
|
||||
|
@ -376,6 +383,39 @@ void CLASS::set(std::string line)
|
|||
}
|
||||
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);
|
||||
if (opupper.length() > 0)
|
||||
{
|
||||
if (
|
||||
(opupper == "STRL")
|
||||
|| (opupper == "STR")
|
||||
|| (opupper == "ASC")
|
||||
|| (opupper == "DCI")
|
||||
|| (opupper == "INV")
|
||||
|| (opupper == "FLS")
|
||||
|| (opupper == "REV")
|
||||
)
|
||||
{
|
||||
isascii = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
state = 4;
|
||||
}
|
||||
break;
|
||||
|
@ -388,8 +428,9 @@ void CLASS::set(std::string line)
|
|||
else if (c > ' ')
|
||||
{
|
||||
operand += c;
|
||||
if (c == '\'')
|
||||
if ((c <= '/') && (isascii))
|
||||
{
|
||||
delim = c;
|
||||
state = 8;
|
||||
}
|
||||
else
|
||||
|
@ -399,15 +440,18 @@ void CLASS::set(std::string line)
|
|||
}
|
||||
break;
|
||||
case 5:
|
||||
if ((c == '\'') || (c == '"'))
|
||||
if (c > ' ')
|
||||
{
|
||||
delim = c;
|
||||
operand += c;
|
||||
state = 8;
|
||||
}
|
||||
else if (c > ' ')
|
||||
{
|
||||
operand += c;
|
||||
if ((c == '\'') || (c == '"'))
|
||||
{
|
||||
delim = c;
|
||||
operand += c;
|
||||
state = 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
operand += c;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -424,8 +468,13 @@ void CLASS::set(std::string line)
|
|||
case 7:
|
||||
comment += c;
|
||||
break;
|
||||
case 9:
|
||||
break;
|
||||
case 8:
|
||||
if (c == delim)
|
||||
if (c < ' ')
|
||||
{
|
||||
}
|
||||
else if (c == delim)
|
||||
{
|
||||
operand += c;
|
||||
state = 5;
|
||||
|
@ -435,8 +484,6 @@ void CLASS::set(std::string line)
|
|||
operand += c;
|
||||
}
|
||||
break;
|
||||
case 9:
|
||||
break;
|
||||
}
|
||||
}
|
||||
printlable = lable;
|
||||
|
@ -945,32 +992,69 @@ TSymbol *CLASS::addSymbol(std::string sym, uint32_t val, bool replace)
|
|||
TSymbol *res = NULL;
|
||||
TSymbol *fnd = NULL;
|
||||
|
||||
fnd = findSymbol(sym);
|
||||
|
||||
if ((fnd != NULL) && (!replace))
|
||||
if (sym.length() > 0)
|
||||
{
|
||||
return (NULL); // it is a duplicate
|
||||
}
|
||||
TSymbol s;
|
||||
s.name = sym;
|
||||
s.opcode = 0;
|
||||
s.namelc = Poco::toLower(sym);
|
||||
s.stype = 0;
|
||||
s.value = val;
|
||||
s.used = false;
|
||||
s.cb = NULL;
|
||||
std::pair<std::string, TSymbol> p(Poco::toUpper(sym), s);
|
||||
|
||||
if (fnd != NULL)
|
||||
{
|
||||
//printf("replacing symbol: %s %08X\n",sym.c_str(),val);
|
||||
fnd->value = val;
|
||||
return (fnd);
|
||||
}
|
||||
if (sym[0] == ':')
|
||||
{
|
||||
//local symbol
|
||||
if (currentsym == NULL)
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
{
|
||||
fnd = findSymbol(sym);
|
||||
if ((fnd != NULL) && (!replace))
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
|
||||
//printf("addSymbol |%s|\n",sym.c_str());
|
||||
TSymbol s;
|
||||
s.name = sym;
|
||||
s.opcode = 0;
|
||||
s.namelc = Poco::toLower(sym);
|
||||
s.stype = 0;
|
||||
s.value = val;
|
||||
s.used = false;
|
||||
s.cb = NULL;
|
||||
std::pair<std::string, TSymbol> p(Poco::toUpper(sym), s);
|
||||
symbols.insert(p);
|
||||
res = findSymbol(sym);
|
||||
if (fnd != NULL)
|
||||
{
|
||||
fnd->value = val;
|
||||
res = fnd;
|
||||
goto out;
|
||||
}
|
||||
if (currentsym != NULL)
|
||||
{
|
||||
currentsym->locals.insert(p);
|
||||
}
|
||||
res = findSymbol(sym);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fnd = findSymbol(sym);
|
||||
|
||||
if ((fnd != NULL) && (!replace))
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (fnd != NULL)
|
||||
{
|
||||
//printf("replacing symbol: %s %08X\n",sym.c_str(),val);
|
||||
fnd->value = val;
|
||||
res = fnd;
|
||||
goto out;
|
||||
}
|
||||
|
||||
symbols.insert(p);
|
||||
res = findSymbol(sym);
|
||||
}
|
||||
}
|
||||
out:
|
||||
return (res);
|
||||
}
|
||||
|
||||
|
@ -978,15 +1062,37 @@ TSymbol *CLASS::findSymbol(std::string symname)
|
|||
{
|
||||
TSymbol *res = NULL;
|
||||
|
||||
//printf("finding: %s\n",symname.c_str());
|
||||
auto itr = symbols.find(Poco::toUpper(symname));
|
||||
if (itr != symbols.end())
|
||||
if (symname.length() > 0)
|
||||
{
|
||||
//printf("Found: %s 0x%08X\n",itr->second.name.c_str(),itr->second.value);
|
||||
res = &itr->second;
|
||||
|
||||
return (res);
|
||||
if (symname[0] == ':')
|
||||
{
|
||||
if (currentsym == NULL)
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto itr = currentsym->locals.find(Poco::toUpper(symname));
|
||||
if (itr != currentsym->locals.end())
|
||||
{
|
||||
res = &itr->second;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf("finding: %s\n",symname.c_str());
|
||||
auto itr = symbols.find(Poco::toUpper(symname));
|
||||
if (itr != symbols.end())
|
||||
{
|
||||
//printf("Found: %s 0x%08X\n",itr->second.name.c_str(),itr->second.value);
|
||||
res = &itr->second;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
out:
|
||||
return (res);
|
||||
}
|
||||
|
||||
|
@ -1166,9 +1272,9 @@ int CLASS::callOpCode(std::string op, MerlinLine &line)
|
|||
line.flags |= FLAG_FORCELONG;
|
||||
break;
|
||||
}
|
||||
if (line.expr_value>=0x100)
|
||||
if (line.expr_value >= 0x100)
|
||||
{
|
||||
line.flags|=FLAG_FORCEABS;
|
||||
line.flags |= FLAG_FORCEABS;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1298,7 +1404,6 @@ void CLASS::initpass(void)
|
|||
s = Poco::trim(Poco::toUpper(s));
|
||||
|
||||
cpumode = MODE_65816;
|
||||
mx = 0x00;
|
||||
|
||||
if (s == "M65816")
|
||||
{
|
||||
|
@ -1318,9 +1423,15 @@ void CLASS::initpass(void)
|
|||
else
|
||||
{
|
||||
printf("Unknown CPU type in .ini\n");
|
||||
mx = 0x00;
|
||||
}
|
||||
mx = getInt("asm.startmx", mx);;
|
||||
|
||||
savepath = getConfig("option.objfile", "");
|
||||
|
||||
relocatable = false;
|
||||
currentsym = NULL;
|
||||
currentsym = &topSymbol; // this is the default symbol for :locals without a global above;
|
||||
currentsymstr = "";
|
||||
lineno = 0;
|
||||
errorct = 0;
|
||||
passcomplete = false;
|
||||
|
@ -1347,7 +1458,6 @@ void CLASS::initpass(void)
|
|||
}
|
||||
curLUP.clear();
|
||||
curDO.clear();
|
||||
savepath = "";
|
||||
}
|
||||
|
||||
void CLASS::complete(void)
|
||||
|
@ -1359,10 +1469,6 @@ void CLASS::complete(void)
|
|||
std::string currentdir = Poco::Path::current();
|
||||
|
||||
savepath = processFilename(savepath, currentdir, 0);
|
||||
if (isDebug()>=1)
|
||||
{
|
||||
savepath+="1"; // append this to the end to help with testing against other assemblers
|
||||
}
|
||||
printf("saving to file: %s\n", savepath.c_str());
|
||||
|
||||
std::ofstream f(savepath);
|
||||
|
@ -1664,7 +1770,7 @@ void CLASS::process(void)
|
|||
line.eval_result = 0;
|
||||
line.lineno = lineno + 1;
|
||||
line.truncdata = truncdata;
|
||||
memcpy(line.tabs,tabs,sizeof(tabs));
|
||||
memcpy(line.tabs, tabs, sizeof(tabs));
|
||||
//printf("lineno: %d %d |%s|\n",lineno,l,line.operand.c_str());
|
||||
|
||||
op = Poco::toLower(line.opcode);
|
||||
|
@ -1688,13 +1794,22 @@ void CLASS::process(void)
|
|||
sym = addVariable(line.lable, ls, true);
|
||||
if (sym == NULL) { dupsym = true; }
|
||||
break;
|
||||
|
||||
case ':':
|
||||
break;
|
||||
default:
|
||||
if (pass == 0)
|
||||
{
|
||||
sym = addSymbol(line.lable, PC.currentpc, false);
|
||||
if (sym == NULL) { dupsym = true; }
|
||||
if (sym == NULL)
|
||||
{
|
||||
dupsym = true;
|
||||
line.setError(errDupSymbol);
|
||||
}
|
||||
}
|
||||
if (c != ':')
|
||||
{
|
||||
currentsym = findSymbol(line.lable);
|
||||
currentsymstr = line.lable;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1712,12 +1827,11 @@ void CLASS::process(void)
|
|||
|
||||
int64_t value = -1;
|
||||
x = evaluate(line, line.operand_expr, value);
|
||||
//line.eval_result=x;
|
||||
|
||||
if (x == 0)
|
||||
{
|
||||
value &= 0xFFFFFFFF;
|
||||
line.expr_value = value;
|
||||
line.expr_value = (uint32_t)value;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
6
asm.h
6
asm.h
|
@ -82,7 +82,7 @@ const std::string errStrings[errMAX + 1] =
|
|||
"Bad opcode",
|
||||
"Opcode not available under CPU mode",
|
||||
"Byte output differs between passes",
|
||||
"Relative branch offset too large",
|
||||
"Bad branch",
|
||||
"Forward Reference to symbol",
|
||||
"Unable to redefine symbol",
|
||||
"Duplicate Symbol",
|
||||
|
@ -347,6 +347,9 @@ public:
|
|||
|
||||
std::string savepath;
|
||||
TSymbol *currentsym;
|
||||
TSymbol topSymbol;
|
||||
|
||||
std::string currentsymstr;
|
||||
std::vector<MerlinLine> lines;
|
||||
Poco::HashMap<std::string, TSymbol>opcodes;
|
||||
Poco::HashMap<std::string, TSymbol> macros;
|
||||
|
@ -408,6 +411,7 @@ public:
|
|||
int doNoPattern(MerlinLine &line, TSymbol &sym);
|
||||
int doMVN(MerlinLine &line, TSymbol &sym);
|
||||
int doPER(MerlinLine &line, TSymbol &sym);
|
||||
int doBRK(MerlinLine & line, TSymbol & sym);
|
||||
|
||||
int doEQU(MerlinLine &line, TSymbol &sym);
|
||||
int doXC(MerlinLine &line, TSymbol &sym);
|
||||
|
|
4
eval.cpp
4
eval.cpp
|
@ -225,9 +225,9 @@ std::deque<Token> CLASS::shuntingYard(const std::deque<Token>& tokens)
|
|||
}
|
||||
else
|
||||
{
|
||||
//printf("symbol find |%s|\n",token.str.c_str());
|
||||
|
||||
sym = assembler.findSymbol(token.str);
|
||||
//printf("symbol find |%s| %p\n",token.str.c_str(),sym);
|
||||
|
||||
if (sym != NULL)
|
||||
{
|
||||
sym->used = true;
|
||||
|
|
100
opcodes.cpp
100
opcodes.cpp
|
@ -182,7 +182,7 @@ int CLASS::doMVN(MerlinLine &line, TSymbol &sym)
|
|||
{
|
||||
value = 0xFFFFFFFF;
|
||||
line.setError(errBadOperand);
|
||||
line.errorText = line.operand_expr2;
|
||||
//line.errorText = line.operand_expr2;
|
||||
}
|
||||
|
||||
setOpcode(line, op);
|
||||
|
@ -226,7 +226,7 @@ int CLASS::doNoPattern(MerlinLine &line, TSymbol &sym)
|
|||
op = (m == syn_abs ? 0x64 : op);
|
||||
op = (m == syn_absx ? 0x74 : op);
|
||||
|
||||
if ((op != 0) && (line.expr_value >= 0x100))
|
||||
if ((op != 0) && ((line.expr_value >= 0x100) || (line.flags&FLAG_FORCEABS)))
|
||||
{
|
||||
res++;
|
||||
op = (op == 0x64) ? 0x9C : op;
|
||||
|
@ -236,7 +236,7 @@ int CLASS::doNoPattern(MerlinLine &line, TSymbol &sym)
|
|||
case 2: // TSB
|
||||
res++;
|
||||
op = (m == syn_abs ? 0x04 : op);
|
||||
if ((op != 0) && (line.expr_value >= 0x100))
|
||||
if ((op != 0) && ((line.expr_value >= 0x100) || (line.flags&FLAG_FORCEABS)))
|
||||
{
|
||||
res++;
|
||||
op = 0x0C;
|
||||
|
@ -245,7 +245,7 @@ int CLASS::doNoPattern(MerlinLine &line, TSymbol &sym)
|
|||
case 3: // TRB
|
||||
res++;
|
||||
op = (m == syn_abs ? 0x14 : op);
|
||||
if ((op != 0) && (line.expr_value >= 0x100))
|
||||
if ((op != 0) && ((line.expr_value >= 0x100) || (line.flags&FLAG_FORCEABS)))
|
||||
{
|
||||
res++;
|
||||
op = 0x1C;
|
||||
|
@ -416,15 +416,38 @@ int CLASS::doBRANCH(MerlinLine & line, TSymbol & sym)
|
|||
int32_t o32 = (int32_t)(o64 & 0xFFFFFFFF);
|
||||
int32_t offset = o32 - line.startpc - res;
|
||||
|
||||
// SGQ should check under/over flows
|
||||
|
||||
bool err = false;
|
||||
if (res == 2) // short branch
|
||||
{
|
||||
if ((offset < -128) || (offset > 127))
|
||||
{
|
||||
err = true;
|
||||
op=0x00; // merlin does this
|
||||
}
|
||||
}
|
||||
else if (res == 3) // long branch
|
||||
{
|
||||
if ((offset < -32768) || (offset > 32767))
|
||||
{
|
||||
err = true;
|
||||
// for BRL, merlin DOES NOT kill the opcode
|
||||
//op=0x00; // merlin does this
|
||||
}
|
||||
}
|
||||
//printf("offset %d\n", offset);
|
||||
|
||||
setOpcode(line, op);
|
||||
for (i = 0; i < (res - 1); i++)
|
||||
{
|
||||
line.outbytes.push_back(offset >> (i * 8));
|
||||
uint8_t v=(offset >> (i*8));
|
||||
v=err?0x00:v;
|
||||
line.outbytes.push_back(v);
|
||||
}
|
||||
line.outbytect = res;
|
||||
if (err)
|
||||
{
|
||||
line.setError(errBadBranch);
|
||||
}
|
||||
}
|
||||
return (res);
|
||||
}
|
||||
|
@ -464,14 +487,9 @@ int CLASS::doBase6502(MerlinLine & line, TSymbol & sym)
|
|||
cc = 0x01;
|
||||
op = 0x80;
|
||||
bbb = 0x02;
|
||||
//if ((mx&0x02)==0)
|
||||
//{
|
||||
// bytelen++;
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
else if ((bbb > 0) && (line.expr_value >= 0x100))
|
||||
else if ((bbb > 0) && ((line.expr_value >= 0x100) || (line.flags&FLAG_FORCEABS)))
|
||||
{
|
||||
bbb |= 0x02;
|
||||
bytelen++;
|
||||
|
@ -546,14 +564,18 @@ int CLASS::doBase6502(MerlinLine & line, TSymbol & sym)
|
|||
{
|
||||
err = true;
|
||||
}
|
||||
if (m==syn_imm)
|
||||
if (m == syn_imm)
|
||||
{
|
||||
if ((mx&0x01)==0)
|
||||
if ((mx & 0x01) == 0)
|
||||
{
|
||||
bytelen++;
|
||||
}
|
||||
}
|
||||
if ((m == syn_absx) || (m == syn_abs) || (m==syn_absy))
|
||||
if ( ((m==syn_absx) || (m==syn_diix)) && ((sym.opcode==4) || (sym.opcode==5))) // these are STX,LDX
|
||||
{
|
||||
err=true;
|
||||
}
|
||||
if ((m == syn_absx) || (m == syn_abs) || (m == syn_absy))
|
||||
{
|
||||
if ((line.flags & FLAG_FORCEABS) || (line.expr_value >= 0x100))
|
||||
{
|
||||
|
@ -589,7 +611,7 @@ int CLASS::doBase6502(MerlinLine & line, TSymbol & sym)
|
|||
}
|
||||
else
|
||||
{
|
||||
if ((m == syn_absx) || (m==syn_abs))
|
||||
if ((m == syn_absx) || (m == syn_abs))
|
||||
{
|
||||
if ((line.flags & FLAG_FORCEABS) || (line.expr_value >= 0x100))
|
||||
{
|
||||
|
@ -728,6 +750,30 @@ int CLASS::doBYTE(MerlinLine & line, TSymbol & sym)
|
|||
return (res);
|
||||
}
|
||||
|
||||
int CLASS::doBRK(MerlinLine & line, TSymbol & sym)
|
||||
{
|
||||
UNUSED(sym);
|
||||
|
||||
int res = 1;
|
||||
int bytes=0;
|
||||
|
||||
if (line.operand_expr!="")
|
||||
{
|
||||
bytes++;
|
||||
}
|
||||
if (pass > 0)
|
||||
{
|
||||
setOpcode(line, sym.opcode);
|
||||
for (int i=0;i<bytes;i++)
|
||||
{
|
||||
line.outbytes.push_back((line.expr_value>>(8*i))&0xFF);
|
||||
}
|
||||
|
||||
line.outbytect = res+bytes;
|
||||
}
|
||||
return (res+bytes);
|
||||
}
|
||||
|
||||
void CLASS::insertOpcodes(void)
|
||||
{
|
||||
pushopcode("=", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doEQU));
|
||||
|
@ -758,12 +804,13 @@ void CLASS::insertOpcodes(void)
|
|||
pushopcode("TTL", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
|
||||
pushopcode("SKP", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
|
||||
pushopcode("TR", P_TR, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
|
||||
pushopcode("ASC", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
|
||||
pushopcode("DCI", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
|
||||
pushopcode("INV", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
|
||||
pushopcode("FLS", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
|
||||
pushopcode("REV", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
|
||||
pushopcode("STR", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
|
||||
pushopcode("ASC", P_ASC, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
|
||||
pushopcode("DCI", P_ASC, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
|
||||
pushopcode("INV", P_ASC, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
|
||||
pushopcode("FLS", P_ASC, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
|
||||
pushopcode("REV", P_ASC, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
|
||||
pushopcode("STR", P_ASC, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
|
||||
pushopcode("STRL", P_ASC, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
|
||||
pushopcode("DA", P_DATA, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
|
||||
pushopcode("DW", P_DATA, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
|
||||
pushopcode("DDB", P_DATA, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
|
||||
|
@ -806,7 +853,7 @@ void CLASS::insertOpcodes(void)
|
|||
pushopcode("BNE", 0x03, 0, OPHANDLER(&CLASS::doBRANCH));
|
||||
pushopcode("BPL", 0x00, 0, OPHANDLER(&CLASS::doBRANCH));
|
||||
pushopcode("BRA", 0x40, 0, OPHANDLER(&CLASS::doBRANCH));
|
||||
pushopcode("BRK", 0x00, 0, OPHANDLER(&CLASS::doBYTE));
|
||||
pushopcode("BRK", 0x00, 1, OPHANDLER(&CLASS::doBRK));
|
||||
pushopcode("BRL", 0x20, 0, OPHANDLER(&CLASS::doBRANCH));
|
||||
pushopcode("BVC", 0x01, 0, OPHANDLER(&CLASS::doBRANCH));
|
||||
pushopcode("BVS", 0x81, 0, OPHANDLER(&CLASS::doBRANCH));
|
||||
|
@ -872,11 +919,15 @@ void CLASS::insertOpcodes(void)
|
|||
pushopcode("TAX", 0xAA, 0, OPHANDLER(&CLASS::doBYTE));
|
||||
pushopcode("TAY", 0xA8, 0, OPHANDLER(&CLASS::doBYTE));
|
||||
pushopcode("TCD", 0x5B, 0, OPHANDLER(&CLASS::doBYTE));
|
||||
pushopcode("TAD", 0x5B, 0, OPHANDLER(&CLASS::doBYTE));
|
||||
pushopcode("TCS", 0x1B, 0, OPHANDLER(&CLASS::doBYTE));
|
||||
pushopcode("TAS", 0x1B, 0, OPHANDLER(&CLASS::doBYTE));
|
||||
pushopcode("TDC", 0x7B, 0, OPHANDLER(&CLASS::doBYTE));
|
||||
pushopcode("TDA", 0x7B, 0, OPHANDLER(&CLASS::doBYTE));
|
||||
pushopcode("TRB", 0x03, OP_A, OPHANDLER(&CLASS::doNoPattern));
|
||||
pushopcode("TSB", 0x02, OP_A, OPHANDLER(&CLASS::doNoPattern));
|
||||
pushopcode("TSC", 0x3B, 0, OPHANDLER(&CLASS::doBYTE));
|
||||
pushopcode("TSA", 0x3B, 0, OPHANDLER(&CLASS::doBYTE));
|
||||
pushopcode("TSX", 0xBA, 0, OPHANDLER(&CLASS::doBYTE));
|
||||
pushopcode("TXA", 0x8A, 0, OPHANDLER(&CLASS::doBYTE));
|
||||
pushopcode("TXS", 0x9A, 0, OPHANDLER(&CLASS::doBYTE));
|
||||
|
@ -886,6 +937,7 @@ void CLASS::insertOpcodes(void)
|
|||
pushopcode("WAI", 0xCB, 0, OPHANDLER(&CLASS::doBYTE));
|
||||
pushopcode("WDM", 0x42, 1, OPHANDLER(&CLASS::doAddress));
|
||||
pushopcode("XBA", 0xEB, 0, OPHANDLER(&CLASS::doBYTE));
|
||||
pushopcode("SWA", 0xEB, 0, OPHANDLER(&CLASS::doBYTE));
|
||||
pushopcode("XCE", 0xFB, 0, OPHANDLER(&CLASS::doBYTE));
|
||||
}
|
||||
|
||||
|
|
325
psuedo.cpp
325
psuedo.cpp
|
@ -221,8 +221,11 @@ int CLASS::doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
|||
int outct = 0;
|
||||
int wordsize = 2;
|
||||
int endian = 0;
|
||||
std::string oper = line.operand_expr;
|
||||
std::string oper = line.operand;
|
||||
std::string op = Poco::toUpper(Poco::trim(line.opcode));
|
||||
|
||||
//printf("DFB TOK1 : |%s|\n", oper.c_str());
|
||||
|
||||
Poco::StringTokenizer tok(oper, ",", Poco::StringTokenizer::TOK_TRIM |
|
||||
Poco::StringTokenizer::TOK_IGNORE_EMPTY);
|
||||
|
||||
|
@ -255,38 +258,49 @@ int CLASS::doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
|||
|
||||
for (auto itr = tok.begin(); itr != tok.end(); ++itr)
|
||||
{
|
||||
//printf("%s\n",(*itr).c_str());
|
||||
//evaluate each of these strings, check for errors on pass 2
|
||||
|
||||
std::string expr = *itr;
|
||||
|
||||
//printf("DFB TOK : |%s|\n", expr.c_str());
|
||||
|
||||
int64_t eval_result = 0;
|
||||
uint8_t shift;
|
||||
int r;
|
||||
uint8_t b;
|
||||
|
||||
shift = 0;
|
||||
r = eval.evaluate(expr, eval_result, shift);
|
||||
if (r < 0)
|
||||
if (expr.length() > 0)
|
||||
{
|
||||
//printf("eval error %d |%s|\n", r,expr.c_str());
|
||||
if (a.pass > 0)
|
||||
if (expr[0] == '#')
|
||||
{
|
||||
line.setError(errBadEvaluation);
|
||||
expr[0] = ' ';
|
||||
expr = Poco::trim(expr);
|
||||
}
|
||||
shift = 0;
|
||||
eval_result = 0;
|
||||
//printf("DFB EVAL: |%s|\n", expr.c_str());
|
||||
r = eval.evaluate(expr, eval_result, shift);
|
||||
if (r < 0)
|
||||
{
|
||||
//printf("error %d\n",r);
|
||||
if (a.pass > 0)
|
||||
{
|
||||
line.setError(errBadEvaluation);
|
||||
}
|
||||
}
|
||||
if (shift == '>')
|
||||
{
|
||||
eval_result = (eval_result) & 0xFF;
|
||||
}
|
||||
if (shift == '<')
|
||||
{
|
||||
eval_result = (eval_result >> 8) & 0xFF;
|
||||
}
|
||||
else if ((shift == '^') || (shift == '|'))
|
||||
{
|
||||
eval_result = (eval_result >> 16) & 0xFF;
|
||||
}
|
||||
}
|
||||
if (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;
|
||||
if (a.pass > 0)
|
||||
|
@ -375,7 +389,12 @@ int CLASS::doLST(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
|||
if (a.pass > 0)
|
||||
{
|
||||
s = Poco::toUpper(Poco::trim(line.operand_expr));
|
||||
if (s == "RTN")
|
||||
if (s == "")
|
||||
{
|
||||
a.listing = true;
|
||||
a.skiplist = true;
|
||||
}
|
||||
else if (s == "RTN")
|
||||
{
|
||||
if (a.LSTstack.size())
|
||||
{
|
||||
|
@ -422,44 +441,47 @@ int CLASS::doTR(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
|||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
char hexVal( char c )
|
||||
{
|
||||
char v = -1;
|
||||
|
||||
if ((c >= '0') && (c <= '9'))
|
||||
{
|
||||
v = c - '0';
|
||||
}
|
||||
else if ((c >= 'a') && (c <= 'f'))
|
||||
{
|
||||
v = c - 'a' + 10;
|
||||
}
|
||||
else if ((c >= 'A') && (c <= 'F'))
|
||||
{
|
||||
v = c - 'A' + 10;
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
int CLASS::doHEX(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
||||
{
|
||||
UNUSED(opinfo);
|
||||
|
||||
std::string os = Poco::toUpper(Poco::trim(line.operand_expr));
|
||||
std::string os = Poco::trim(line.operand);
|
||||
|
||||
uint32_t bytect = 0;
|
||||
uint8_t b = 0;
|
||||
uint8_t ct = 0;
|
||||
|
||||
if (os.length() == 0)
|
||||
{
|
||||
// case where HEX has no operand, Merlin does not flag as error
|
||||
//line.setError(errIllegalCharOperand);
|
||||
bytect = 0;
|
||||
goto out;
|
||||
}
|
||||
for ( uint32_t i = 0; i < os.length(); ++i )
|
||||
{
|
||||
char c = os[i];
|
||||
|
||||
if ((c >= '0') && (c <= '9'))
|
||||
{
|
||||
c = c - '0';
|
||||
}
|
||||
else if ((c >= 'a') && (c <= 'f'))
|
||||
{
|
||||
c = c - 'a' + 10;
|
||||
}
|
||||
else if ((c >= 'A') && (c <= 'F'))
|
||||
{
|
||||
c = c - 'A' + 10;
|
||||
}
|
||||
else if (c == ',')
|
||||
if (c == ',')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
char hv = hexVal(c);
|
||||
if ( hv < 0 )
|
||||
{
|
||||
line.setError(errIllegalCharOperand);
|
||||
bytect = 0;
|
||||
|
@ -470,10 +492,10 @@ int CLASS::doHEX(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
|||
switch (ct)
|
||||
{
|
||||
case 0:
|
||||
b = (c << 4);
|
||||
b = (hv << 4);
|
||||
break;
|
||||
case 1:
|
||||
b |= c;
|
||||
b |= hv;
|
||||
break;
|
||||
}
|
||||
ct = (ct + 1) & 0x01;
|
||||
|
@ -487,6 +509,7 @@ int CLASS::doHEX(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
|||
bytect++;
|
||||
}
|
||||
}
|
||||
|
||||
if (ct & 0x01) // we got an odd number of nibbles
|
||||
{
|
||||
line.setError(errBadOperand);
|
||||
|
@ -497,6 +520,210 @@ out:
|
|||
return bytect;
|
||||
}
|
||||
|
||||
// the handler for STR,STRL,REV,FLS,INV,DCI,ASC
|
||||
int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
||||
{
|
||||
UNUSED(opinfo);
|
||||
|
||||
std::string os = line.operand;
|
||||
std::string op = Poco::toUpper(line.opcode);
|
||||
|
||||
uint8_t lastdelimbyte = 0x00;
|
||||
uint8_t firstdelim = 0xFF;
|
||||
uint32_t bytect = 0;
|
||||
uint8_t b = 0;
|
||||
uint8_t b1;
|
||||
uint8_t ct = 0;
|
||||
char delimiter = 0;
|
||||
uint32_t ss = 0;
|
||||
std::vector<uint8_t> bytes;
|
||||
|
||||
for ( uint32_t i = 0; i < os.length(); ++i )
|
||||
{
|
||||
char c = os[i];
|
||||
|
||||
// are we inside a delimited string?
|
||||
if ( delimiter )
|
||||
{
|
||||
if ( c == delimiter )
|
||||
{
|
||||
bytect += (i - ss);
|
||||
|
||||
if ( a.pass > 0 )
|
||||
{
|
||||
for ( ; ss < i; ++ss )
|
||||
{
|
||||
c = os[ss];
|
||||
if ( delimiter >= '\'' )
|
||||
{
|
||||
c &= 0x7F;
|
||||
}
|
||||
else
|
||||
{
|
||||
c |= 0x80;
|
||||
}
|
||||
lastdelimbyte = c;
|
||||
bytes.push_back(c);
|
||||
//line.outbytes.push_back(c);
|
||||
}
|
||||
}
|
||||
|
||||
delimiter = 0;
|
||||
ss = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No, check for seperator characters
|
||||
if ( c == ',' || c == ' ' )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Is this a hex char?
|
||||
char hv = hexVal(c);
|
||||
if ( hv < 0 )
|
||||
{
|
||||
// if not a hex value, then consider the character to be the string delimiter
|
||||
delimiter = c;
|
||||
if (firstdelim == 0xFF)
|
||||
{
|
||||
firstdelim = c;
|
||||
}
|
||||
else if (delimiter != firstdelim)
|
||||
{
|
||||
line.setError(errIllegalCharOperand);
|
||||
}
|
||||
ss = i + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Got a hex char, append to hex string and see if we've got a byte
|
||||
switch (ct)
|
||||
{
|
||||
case 0:
|
||||
b = (hv << 4);
|
||||
break;
|
||||
case 1:
|
||||
b |= hv;
|
||||
break;
|
||||
}
|
||||
ct = (ct + 1) & 0x01;
|
||||
if (!ct)
|
||||
{
|
||||
if (a.pass > 0)
|
||||
{
|
||||
bytes.push_back(b);
|
||||
//line.outbytes.push_back(b);
|
||||
}
|
||||
b = 0;
|
||||
bytect++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( delimiter || (ct & 0x01) ) // error w/unterminated string or we got an odd number of nibbles in hex value
|
||||
{
|
||||
line.setError(errBadOperand);
|
||||
bytect = 0;
|
||||
}
|
||||
else // now figure out what psuedo op we are and transfer the data to outbytect
|
||||
{
|
||||
uint32_t i;
|
||||
bool reverse = false;
|
||||
bool dci = false;
|
||||
uint8_t andval = 0xFF;
|
||||
uint8_t orval = 0x00;
|
||||
uint8_t addlen = 0;
|
||||
uint8_t firstbyte = 0x00;
|
||||
uint32_t truebytect = bytes.size();
|
||||
const char *ptr = (const char *)op.c_str();
|
||||
//printf("bytect=%d bytes.size()=%zu\n",bytect,bytes.size());
|
||||
switch (strhash(ptr) )
|
||||
{
|
||||
case strhash((const char *)"STRL"):
|
||||
addlen = 2;
|
||||
break;
|
||||
case strhash((const char *)"STR"):
|
||||
addlen = 1;
|
||||
break;
|
||||
case strhash((const char *)"REV"):
|
||||
reverse = true;
|
||||
break;
|
||||
case strhash((const char *)"FLS"):
|
||||
andval = (uint8_t)~0xC0;
|
||||
orval = (uint8_t)0x40;
|
||||
break;
|
||||
case strhash((const char *)"INV"):
|
||||
andval = (uint8_t)~0xC0;
|
||||
orval = 0x00;
|
||||
break;
|
||||
case strhash((const char *)"DCI"):
|
||||
dci = true;
|
||||
break;
|
||||
case strhash((const char *)"ASC"):
|
||||
break;
|
||||
default:
|
||||
line.setError(errBadOpcode);
|
||||
bytect = 0;
|
||||
addlen = 0;
|
||||
break;
|
||||
}
|
||||
if (a.pass > 0)
|
||||
{
|
||||
for (i = 0; i < addlen; i++) // if a string, push length
|
||||
{
|
||||
line.outbytes.push_back((truebytect >> (i * 8)) & 0xFF);
|
||||
}
|
||||
for (i = 0; i < truebytect; i++)
|
||||
{
|
||||
if (reverse)
|
||||
{
|
||||
b = bytes[bytect - i - 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
b = bytes[i];
|
||||
}
|
||||
if (!i)
|
||||
{
|
||||
firstbyte = b;
|
||||
}
|
||||
b1 = b & 0x7F;
|
||||
if ((andval!=0xFF) || (orval!=0x00))
|
||||
b=b1;
|
||||
if ((b1 < 0x60))
|
||||
{
|
||||
b &= andval; // strip whatever bits needed to flash or invert
|
||||
b |= orval;
|
||||
}
|
||||
if ((dci) && (i == (truebytect - 1)))
|
||||
{
|
||||
// this one might be a bug. I am going to compare the first byte in the string for
|
||||
// bit seven, and invert it on this byte. The confusion arises because this text string
|
||||
// could have high ASCII, but low HEX values.
|
||||
if (firstbyte < 0x80)
|
||||
{
|
||||
b |= 0x80;
|
||||
}
|
||||
else
|
||||
{
|
||||
b &= 0x7F;
|
||||
}
|
||||
}
|
||||
line.outbytes.push_back(b);
|
||||
}
|
||||
}
|
||||
bytect = bytect + addlen;
|
||||
|
||||
}
|
||||
//printf("XXX bytect=%d bytes.size()=%zu\n",bytect,bytes.size());
|
||||
|
||||
line.outbytect = bytect;
|
||||
return bytect;
|
||||
|
||||
}
|
||||
|
||||
int CLASS::ProcessOpcode(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
||||
{
|
||||
|
@ -555,9 +782,11 @@ int CLASS::ProcessOpcode(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
|||
res = doDO(a, line, opinfo);
|
||||
break;
|
||||
case P_TR:
|
||||
res=doTR(a,line,opinfo);
|
||||
res = doTR(a, line, opinfo);
|
||||
break;
|
||||
case P_ASC:
|
||||
res = doASC(a, line, opinfo);
|
||||
break;
|
||||
|
||||
}
|
||||
return (res);
|
||||
}
|
||||
|
|
4
psuedo.h
4
psuedo.h
|
@ -18,6 +18,7 @@ enum
|
|||
P_LUP,
|
||||
P_DO,
|
||||
P_TR,
|
||||
P_ASC,
|
||||
|
||||
P_MAX
|
||||
};
|
||||
|
@ -36,6 +37,7 @@ public:
|
|||
int doLUP(T65816Asm &a, MerlinLine &line, TSymbol &opinfo);
|
||||
int doDO(T65816Asm &a, MerlinLine &line, TSymbol &opinfo);
|
||||
int doTR(T65816Asm &a, MerlinLine &line, TSymbol &opinfo);
|
||||
int doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo);
|
||||
};
|
||||
|
||||
#undef CLASS
|
||||
#undef CLASS
|
||||
|
|
2
qasm.cpp
2
qasm.cpp
|
@ -20,6 +20,8 @@ programOption PAL::appOptions[] =
|
|||
#endif
|
||||
//{ "config", "f", "load configuration data from a <file>", " <file>", false, false},
|
||||
{ "exec", "x", "execute a command [asm, link, reformat] default=asm", " <command>", false, false},
|
||||
{ "objfile", "o", "write output to file", " <file>", false, false},
|
||||
|
||||
{ "", "", "", "", false, false}
|
||||
};
|
||||
|
||||
|
|
3
qasm.ini
3
qasm.ini
|
@ -4,7 +4,7 @@ logdir=/var/log/mylog
|
|||
logfile=mylog.log
|
||||
|
||||
[option]
|
||||
debug=2
|
||||
debug=1
|
||||
nocolor=false
|
||||
;debug must be an integer. Code can use this as a level
|
||||
|
||||
|
@ -22,6 +22,7 @@ path5=dirpath5
|
|||
[asm]
|
||||
casesen=true
|
||||
showmx=true
|
||||
startmx=3
|
||||
lst=true
|
||||
; can be M6502, M65C02, M65816
|
||||
cpu=M65816
|
||||
|
|
|
@ -544,7 +544,7 @@
|
|||
2F5E548F237BAC9A0091163D /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 1020;
|
||||
LastUpgradeCheck = 1120;
|
||||
ORGANIZATIONNAME = "Lane Roathe";
|
||||
TargetAttributes = {
|
||||
2F5E5496237BAC9A0091163D = {
|
||||
|
@ -558,6 +558,7 @@
|
|||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 2F5E548E237BAC9A0091163D;
|
||||
productRefGroup = 2F5E5498237BAC9A0091163D /* Products */;
|
||||
|
@ -716,6 +717,7 @@
|
|||
2F5E549F237BAC9A0091163D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = 32JVURPAZ7;
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
|
@ -729,6 +731,7 @@
|
|||
2F5E54A0237BAC9A0091163D /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = 32JVURPAZ7;
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1020"
|
||||
LastUpgradeVersion = "1120"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -27,8 +27,6 @@
|
|||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
|
@ -38,8 +36,8 @@
|
|||
ReferencedContainer = "container:qasm.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
<Testables>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
|
@ -67,8 +65,6 @@
|
|||
isEnabled = "YES">
|
||||
</CommandLineArgument>
|
||||
</CommandLineArguments>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
|
|
74
runtests.sh
Executable file
74
runtests.sh
Executable file
|
@ -0,0 +1,74 @@
|
|||
#!/bin/bash
|
||||
|
||||
OUTDIR=./testout
|
||||
TMPFILE=/tmp/qasm_out.txt
|
||||
|
||||
rm -f $TMPFILE
|
||||
rm -rf $OUTDIR
|
||||
mkdir -p $OUTDIR
|
||||
|
||||
SRC=`ls ./testdata | grep -E '^([0-9]+)(.*)\.[Ss]'`
|
||||
|
||||
#for S in $SRC ; do
|
||||
# echo $S
|
||||
#done
|
||||
#exit
|
||||
|
||||
TOTAL=0
|
||||
FAILCT=0
|
||||
|
||||
for S in $SRC ; do
|
||||
|
||||
rm -f $TMPFILE
|
||||
|
||||
S1=$S
|
||||
S1=${S1/.S/.bin}
|
||||
S1=${S1/.s/.bin}
|
||||
|
||||
BASE=${S/.S/}
|
||||
BASE=${BASE/.s/}
|
||||
./qasm -o 0/$OUTDIR/$S1 ./testdata/$S >> $TMPFILE
|
||||
|
||||
R=?$
|
||||
#echo $S " " $S1
|
||||
R=`cat $TMPFILE | grep "End qASM assembly"`
|
||||
E=`echo $R | awk -e '{ print $6; }'`
|
||||
ect=`echo $(($E))`
|
||||
|
||||
MSHA="Q"
|
||||
QSHA="M"
|
||||
|
||||
if [ -f ./testdata/M32_expected/$BASE ] ; then
|
||||
MSHA=`sha256sum ./testdata/M32_expected/$BASE | awk '{ print $1;}'` 2>/dev/null >/dev/null
|
||||
fi
|
||||
|
||||
if [ -f $OUTDIR/$BASE.bin ] ; then
|
||||
QSHA=`sha256sum $OUTDIR/$BASE.bin |awk '{print $1;}'` 2>/dev/null >/dev/null
|
||||
fi
|
||||
#echo "$MSHA $QSHA"
|
||||
|
||||
shapass=0;
|
||||
CX=" "
|
||||
|
||||
if [ "$MSHA""L" != "$QSHA""L" ] ; then
|
||||
shapass=1
|
||||
CX="!"
|
||||
fi
|
||||
|
||||
P="PASS: "
|
||||
TOTAL=$(($TOTAL+1))
|
||||
pct=$(($ect+$shapass))
|
||||
if [ $pct != 0 ] ; then
|
||||
printf 'FAIL: (%3s) ' $ect
|
||||
printf '%s ' $CX
|
||||
|
||||
FAILCT=$(($FAILCT+1))
|
||||
else
|
||||
printf "PASS: "
|
||||
fi
|
||||
echo " $S"
|
||||
done
|
||||
echo "Total: $TOTAL Fail: $FAILCT"
|
||||
|
||||
|
||||
|
25
src/main.s
25
src/main.s
|
@ -360,11 +360,12 @@ L00BC bit L00BC
|
|||
|
||||
* Data Storage Tests
|
||||
|
||||
hex ;no error
|
||||
hex 11,22,33,44,55,66,77,88,99
|
||||
hex 112233445566778899F
|
||||
hex 112233445I566778899FF
|
||||
|
||||
hex aabb,CC,0123456789ABCDEFabcdef,ff
|
||||
hex aabb,CC,0123456789abcdefABCDEF,ff
|
||||
|
||||
ds 36
|
||||
da $A55A
|
||||
|
@ -392,6 +393,28 @@ L00BC bit L00BC
|
|||
db ^$01A55A,^$011234
|
||||
db |$01A55A,|$011234
|
||||
|
||||
asc 02,15,"123456"
|
||||
asc 02,15,z123456z
|
||||
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,5,"123456"
|
||||
asc 02,15,"123456
|
||||
asc 0215"1234"1502
|
||||
|
||||
|
||||
lst
|
||||
lup_start:
|
||||
|
|
|
@ -14,10 +14,10 @@ lexpr = $010203
|
|||
immed = $123456
|
||||
neg equ -16
|
||||
|
||||
//]var1 = v1234
|
||||
]var1 = v1234
|
||||
|
||||
;lst off
|
||||
start00:
|
||||
start00
|
||||
brk ;$00
|
||||
ora (dp,x)
|
||||
cop $BA
|
||||
|
|
81
testdata/2009-branches-and-banks.S
vendored
81
testdata/2009-branches-and-banks.S
vendored
|
@ -1,81 +0,0 @@
|
|||
; Copyright 2018 faddenSoft. All Rights Reserved.
|
||||
; See the LICENSE.txt file for distribution terms (Apache 2.0).
|
||||
;
|
||||
; Assembler: cc65
|
||||
;
|
||||
; Both cc65 (2.17) and Merlin32 (1.0) have problems computing branches that
|
||||
; wrap around a bank (e.g. from $0010 to $ffd0). cc65 is slightly less
|
||||
; egregious in that a workaround is possible: if you specify a label that
|
||||
; is in range, and then an offset, it will generate code.
|
||||
|
||||
.setcpu "65816"
|
||||
|
||||
symlong = $123456
|
||||
|
||||
|
||||
.org $1000
|
||||
clc
|
||||
xce
|
||||
sep #$30
|
||||
.a8
|
||||
.i8
|
||||
jmp zero
|
||||
|
||||
.org $0000
|
||||
zero: bit a:zero
|
||||
low: lda zero
|
||||
lda low
|
||||
bne low-$40 ;reference symbol
|
||||
bmi low-$40 ;EDIT: format as hex
|
||||
per low-$40
|
||||
bvs more
|
||||
brl more1
|
||||
lodat: .byte $00,$01,$02 ;EDIT: set label
|
||||
more: lda more-2
|
||||
brl zero-$40 ;branch to high
|
||||
|
||||
.org $0080
|
||||
more1: bit a:more1
|
||||
jml bank44
|
||||
|
||||
.org $ffc0
|
||||
high:
|
||||
bit high
|
||||
brl high+$43 ;branch to low
|
||||
|
||||
.org $440000
|
||||
bank44: cmp f:bank44
|
||||
low44: lda bank44
|
||||
lda a:bank44 & $ffff
|
||||
lda z:bank44 & $ffff ;DP ref, should resolve to "zero"
|
||||
bmi low44
|
||||
per low44-$40
|
||||
bne low44-$40 ;branch to high44
|
||||
brl bank44-$40 ;branch to late44
|
||||
|
||||
dat44: ;EDIT: set label
|
||||
.addr dat44 ;EDIT: format as 16-bit Address
|
||||
.faraddr dat44 ;EDIT: format as 24-bit Address
|
||||
|
||||
.org $44ffc0
|
||||
late44: cmp f:late44
|
||||
high44: beq cont44 ;EDIT: set label
|
||||
bmi late44+$44 ;branch to low44
|
||||
brl late44+$44 ;branch to low44
|
||||
|
||||
cont44: jml twok
|
||||
|
||||
.org $2000
|
||||
twok: bit twok
|
||||
pea dat44 & $ffff ;EDIT: set symbol=dat44
|
||||
pea dat44 >> 16 ;EDIT: set symbol=dat44
|
||||
bne skip
|
||||
jmp [lodat]
|
||||
|
||||
skip: nop
|
||||
j1: jsr j2 ;EDIT: set symbol=j2 for all, confirm auto-labels vanish
|
||||
j2: jsr j3 ;EDIT: set label
|
||||
j3: jsr j1
|
||||
|
||||
jsl symlong
|
||||
rts
|
8
testdata/2009-branches-and-banks.cfg
vendored
8
testdata/2009-branches-and-banks.cfg
vendored
|
@ -1,8 +0,0 @@
|
|||
MEMORY {
|
||||
MAIN: file=%O, start=%S, size=65536;
|
||||
}
|
||||
SEGMENTS {
|
||||
CODE: load=MAIN, type=rw;
|
||||
}
|
||||
FEATURES {}
|
||||
SYMBOLS {}
|
153
testdata/2016-char-encoding.S
vendored
153
testdata/2016-char-encoding.S
vendored
|
@ -1,153 +0,0 @@
|
|||
; Copyright 2019 faddenSoft. All Rights Reserved.
|
||||
; See the LICENSE.txt file for distribution terms (Apache 2.0).
|
||||
;
|
||||
; Assembler: ACME (for the PETSCII/screen code support)
|
||||
|
||||
!cpu 65816
|
||||
* = $1000
|
||||
|
||||
clc
|
||||
xce
|
||||
sep #$30
|
||||
!as
|
||||
!rs
|
||||
|
||||
; Single-byte operand
|
||||
lda #'A' ;format as low ASCII
|
||||
lda #'A' | $80 ;format as high ASCII
|
||||
lda #'A' | $80 ;format as PETSCII
|
||||
lda #'A' ;format as screen code
|
||||
|
||||
ldx #'a' ;format as low ASCII
|
||||
ldx #'a' | $80 ;format as high ASCII
|
||||
ldx #'a' - $20 ;format as PETSCII
|
||||
ldx #$01 ;format as screen code
|
||||
|
||||
lda #$7f ;EDIT: force to low ASCII
|
||||
lda #$7f ;EDIT: force to high ASCII
|
||||
lda #$7f ;EDIT: force to PETSCII
|
||||
lda #$7f ;EDIT: force to screen code
|
||||
|
||||
lda #$0d ;verify the instruction operand editor only allows C64SC
|
||||
|
||||
; Single letter in a 16-bit immediate
|
||||
rep #$30
|
||||
!al
|
||||
!rl
|
||||
lda #'B'
|
||||
lda #'B' | $80
|
||||
lda #'B' | $80
|
||||
lda #'B'
|
||||
|
||||
sep #$30
|
||||
!as
|
||||
!rs
|
||||
rts
|
||||
|
||||
; Single-byte data items
|
||||
!byte 'C'
|
||||
!byte 'C' | $80
|
||||
!byte 'C' | $80
|
||||
!byte 'C'
|
||||
|
||||
; Double-byte data items
|
||||
!byte 'd', 0
|
||||
!byte 'd' | $80, 0
|
||||
!byte 'd' - $20, 0
|
||||
!byte $04, 0
|
||||
|
||||
; Double-byte big-endian data items
|
||||
!byte 0, 'E'
|
||||
!byte 0, 'E' | $80
|
||||
!byte 0, 'E' | $80
|
||||
!byte 0, 'E'
|
||||
|
||||
; Start with the basics
|
||||
!byte $80
|
||||
!text "low ASCII str"
|
||||
; !byte $80 ; let them run together to test scan / dialog behavior
|
||||
!xor $80 {
|
||||
!text "high ASCII str"
|
||||
}
|
||||
!byte $80
|
||||
!pet "PETSCII str"
|
||||
!byte $80
|
||||
!scr "Screen Code str"
|
||||
|
||||
; Get a bit fancy
|
||||
!byte $82
|
||||
!text $07,"Low ASCII CRLF",$0d,$0a
|
||||
!byte $82
|
||||
!xor $80 {
|
||||
!text $07,"High ASCII CRLF",$0d,$0a
|
||||
}
|
||||
!byte $82
|
||||
!pet $93,"PETSCII with ",$96,"control",$05," codes",$0d
|
||||
; no control chars in screen code
|
||||
|
||||
; Test the ASCII $20-7e range.
|
||||
!byte $83
|
||||
!text " !",$22,"#$%&'()*+,-./0123456789:;<=>?"
|
||||
!text "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_"
|
||||
!text "`abcdefghijklmnopqrstuvwxyz{|}~"
|
||||
!byte $83
|
||||
!xor $80 {
|
||||
!text " !",$22,"#$%&'()*+,-./0123456789:;<=>?"
|
||||
!text "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_"
|
||||
!text "`abcdefghijklmnopqrstuvwxyz{|}~"
|
||||
}
|
||||
!byte $83
|
||||
!pet " !",$22,"#$%&'()*+,-./0123456789:;<=>?"
|
||||
!pet "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_"
|
||||
!pet "`abcdefghijklmnopqrstuvwxyz{|}~"
|
||||
!byte $83
|
||||
!scr " !",$22,"#$%&'()*+,-./0123456789:;<=>?"
|
||||
!scr "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_"
|
||||
!scr "`abcdefghijklmnopqrstuvwxyz{|}~"
|
||||
|
||||
; The 2005 test exercises low/high ASCII strings, so no need to do that here.
|
||||
; Do a quick test with C64 characters. Note Screen Code can't be null-terminated
|
||||
; by definition.
|
||||
!byte $84
|
||||
!pet "IICSTEP esrever" ;format as StringReverse
|
||||
!byte $84
|
||||
!pet "null term PETSCII",0 ;format as StringNullTerm
|
||||
!byte $84
|
||||
!pet "This null-terminated string is too long to fit on a single line, and will be split.",0
|
||||
!byte $84
|
||||
!pet 19,"PETSCII with length" ;format as StringL8
|
||||
!byte $84
|
||||
!pet 20,0,"PETSCII with length2" ;format as StringL16
|
||||
!byte $84
|
||||
!pet "pet dcI" ;format as StringDCI
|
||||
|
||||
!byte $84
|
||||
!scr "edoC neercS esrever" ;format as StringReverse
|
||||
!byte $84
|
||||
!scr 23,"Screen Code with length" ;format as StringL8
|
||||
!byte $84
|
||||
!scr 24,0,"Screen Code with length2" ;format as StringL16
|
||||
!byte $84
|
||||
!scr "Screen Code DC",$c9 ;format as StringDCI
|
||||
!byte $84
|
||||
|
||||
!byte $85
|
||||
|
||||
; All bytes, from 00-ff. Handy for seeing what the auto-scanner picks up.
|
||||
allbytes
|
||||
!hex 000102030405060708090a0b0c0d0e0f
|
||||
!hex 101112131415161718191a1b1c1d1e1f
|
||||
!hex 202122232425262728292a2b2c2d2e2f
|
||||
!hex 303132333435363738393a3b3c3d3e3f
|
||||
!hex 404142434445464748494a4b4c4d4e4f
|
||||
!hex 505152535455565758595a5b5c5d5e5f
|
||||
!hex 606162636465666768696a6b6c6d6e6f
|
||||
!hex 707172737475767778797a7b7c7d7e7f
|
||||
!hex 808182838485868788898a8b8c8d8e8f
|
||||
!hex 909192939495969798999a9b9c9d9e9f
|
||||
!hex a0a1a2a3a4a5a6a7a8a9aaabacadaeaf
|
||||
!hex b0b1b2b3b4b5b6b7b8b9babbbcbdbebf
|
||||
!hex c0c1c2c3c4c5c6c7c8c9cacbcccdcecf
|
||||
!hex d0d1d2d3d4d5d6d7d8d9dadbdcdddedf
|
||||
!hex e0e1e2e3e4e5e6e7e8e9eaebecedeeef
|
||||
!hex f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
|
BIN
testdata/M32_expected/1000-allops-value-65816
vendored
Normal file
BIN
testdata/M32_expected/1000-allops-value-65816
vendored
Normal file
Binary file not shown.
BIN
testdata/M32_expected/1001-allops-zero-65816
vendored
Normal file
BIN
testdata/M32_expected/1001-allops-zero-65816
vendored
Normal file
Binary file not shown.
BIN
testdata/M32_expected/1002-embedded-instructions
vendored
Normal file
BIN
testdata/M32_expected/1002-embedded-instructions
vendored
Normal file
Binary file not shown.
BIN
testdata/M32_expected/1003-flags-and-branches
vendored
Normal file
BIN
testdata/M32_expected/1003-flags-and-branches
vendored
Normal file
Binary file not shown.
BIN
testdata/M32_expected/1004-data-recognition
vendored
Normal file
BIN
testdata/M32_expected/1004-data-recognition
vendored
Normal file
Binary file not shown.
BIN
testdata/M32_expected/2000-allops-value-6502
vendored
Normal file
BIN
testdata/M32_expected/2000-allops-value-6502
vendored
Normal file
Binary file not shown.
BIN
testdata/M32_expected/2001-allops-zero-6502
vendored
Normal file
BIN
testdata/M32_expected/2001-allops-zero-6502
vendored
Normal file
Binary file not shown.
BIN
testdata/M32_expected/2002-allops-value-65C02
vendored
Normal file
BIN
testdata/M32_expected/2002-allops-value-65C02
vendored
Normal file
Binary file not shown.
BIN
testdata/M32_expected/2003-allops-zero-65C02
vendored
Normal file
BIN
testdata/M32_expected/2003-allops-zero-65C02
vendored
Normal file
Binary file not shown.
BIN
testdata/M32_expected/2004-numeric-types
vendored
Normal file
BIN
testdata/M32_expected/2004-numeric-types
vendored
Normal file
Binary file not shown.
BIN
testdata/M32_expected/2005-string-types
vendored
Normal file
BIN
testdata/M32_expected/2005-string-types
vendored
Normal file
Binary file not shown.
BIN
testdata/M32_expected/2006-operand-formats
vendored
Normal file
BIN
testdata/M32_expected/2006-operand-formats
vendored
Normal file
Binary file not shown.
BIN
testdata/M32_expected/2007-labels-and-symbols
vendored
Normal file
BIN
testdata/M32_expected/2007-labels-and-symbols
vendored
Normal file
Binary file not shown.
BIN
testdata/M32_expected/2008-address-changes
vendored
Normal file
BIN
testdata/M32_expected/2008-address-changes
vendored
Normal file
Binary file not shown.
BIN
testdata/M32_expected/2010-target-adjustment
vendored
Normal file
BIN
testdata/M32_expected/2010-target-adjustment
vendored
Normal file
Binary file not shown.
2
testdata/M32_expected/2011-hinting
vendored
Normal file
2
testdata/M32_expected/2011-hinting
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
,,©ę,˘˙ę
|
||||
ę,˘˙ę V$©˘" ( V$©3˘D : =ęV$ E` V$©U˘f`<60>‚<EFBFBD>©™`
|
BIN
testdata/M32_expected/2012-label-localizer
vendored
Normal file
BIN
testdata/M32_expected/2012-label-localizer
vendored
Normal file
Binary file not shown.
BIN
testdata/M32_expected/2013-notes-and-comments
vendored
Normal file
BIN
testdata/M32_expected/2013-notes-and-comments
vendored
Normal file
Binary file not shown.
BIN
testdata/M32_expected/2014-label-dp
vendored
Normal file
BIN
testdata/M32_expected/2014-label-dp
vendored
Normal file
Binary file not shown.
BIN
testdata/M32_expected/2019-local-variables
vendored
Normal file
BIN
testdata/M32_expected/2019-local-variables
vendored
Normal file
Binary file not shown.
BIN
testdata/M32_expected/2020-cycle-counts-65816
vendored
Normal file
BIN
testdata/M32_expected/2020-cycle-counts-65816
vendored
Normal file
Binary file not shown.
BIN
testdata/M32_expected/2021-external-symbols
vendored
Normal file
BIN
testdata/M32_expected/2021-external-symbols
vendored
Normal file
Binary file not shown.
BIN
testdata/M32_expected/2022-extension-scripts
vendored
Normal file
BIN
testdata/M32_expected/2022-extension-scripts
vendored
Normal file
Binary file not shown.
1
testdata/qasm
vendored
1
testdata/qasm
vendored
|
@ -1 +0,0 @@
|
|||
../qasm
|
19
todo.txt
Normal file
19
todo.txt
Normal file
|
@ -0,0 +1,19 @@
|
|||
(0) 2019-11-17 - BRK does not detect a lable that can't be evaluated
|
||||
(0) 2019-11-17 - ASCII parsing in both eval and for ASC type commands
|
||||
(0) 2019-11-17 - IF processing for character compare mode
|
||||
(0) 2019-11-17 -
|
||||
(0) 2019-11-17 -
|
||||
(0) 2019-11-17 -
|
||||
(0) 2019-11-17 -
|
||||
(0) 2019-11-17 -
|
||||
(0) 2019-11-17 -
|
||||
(0) 2019-11-17 -
|
||||
(0) 2019-11-17 -
|
||||
(0) 2019-11-17 -
|
||||
(0) 2019-11-17 -
|
||||
(0) 2019-11-17 -
|
||||
(0) 2019-11-17 -
|
||||
(0) 2019-11-17 -
|
||||
(0) 2019-11-17 -
|
||||
(0) 2019-11-17 -
|
||||
|
Loading…
Reference in New Issue
Block a user