This commit is contained in:
Lane Roathe 2019-11-17 11:18:23 -08:00
commit df8c9ef7d3
7 changed files with 252 additions and 44 deletions

84
asm.cpp
View File

@ -34,6 +34,8 @@ void CLASS::print(uint32_t lineno)
uint32_t b = 4; // how many bytes show on the first line
bool merlinstyle=true;
if (datafillct > 0)
{
l = datafillct;
@ -46,7 +48,25 @@ void CLASS::print(uint32_t lineno)
{
l = b;
}
if (errorcode > 0)
{
if (merlinstyle)
{
//printf("errorcode=%d\n",errorcode);
printf("%s in line: %d", errStrings[errorcode].c_str(), lineno+1);
if (errorText != "")
{
printf("%s", errorText.c_str());
}
printf("\n");
}
flags &= (~FLAG_NOLINEPRINT);
}
if (flags & FLAG_NOLINEPRINT)
{
return;
}
if (!checked)
{
nc1 = getBool("option.nocolor", false);
@ -57,7 +77,7 @@ void CLASS::print(uint32_t lineno)
nc = nc1;
}
if (!isatty(STDOUT_FILENO))
if ((!isatty(STDOUT_FILENO)) || (merlinstyle))
{
nc = true;
}
@ -87,7 +107,12 @@ void CLASS::print(uint32_t lineno)
}
pcol = 0;
if (!empty)
bool saddr = flags & FLAG_FORCEADDRPRINT;
saddr = (outbytect > 0) ? true : saddr;
saddr = (printlable != "") ? true : saddr;
if (saddr)
{
pcol += printf("%02X/%04X:", (startpc >> 16), startpc & 0xFFFF);
}
@ -143,14 +168,17 @@ void CLASS::print(uint32_t lineno)
pcol += printf(" ");
}
}
//pcol += printf("%s", comment.c_str());
else
{
pcol += printf("%s", comment.c_str());
}
}
}
else
{
pcol += printf("%-12s %-8s %-10s ", printlable.c_str(), opcode.c_str(), operand.c_str());
}
if (errorcode > 0)
if ((errorcode > 0) && (!merlinstyle))
{
while (pcol < commentcol)
{
@ -233,7 +261,7 @@ void CLASS::clear()
operand_expr2 = "";
addrtext = "";
linemx = 0;
commentcol=40;
commentcol = 40;
bytect = 0;
opflags = 0;
pass0bytect = 0;
@ -456,12 +484,12 @@ void CLASS::complete(void)
{
uint64_t n = GetTickCount();
if (isDebug())
//if (isDebug())
{
//cout << "Processing Time: " << n - starttime << "ms" << endl;
uint64_t x = n - starttime;
uint32_t x1 = x & 0xFFFFFFFF;
printf("Processing Time: %u ms\n", x1);
printf("Elapsed time: %u ms\n", x1);
}
}
@ -606,7 +634,7 @@ int CLASS::processfile(std::string p, std::string &newfilename)
{
// is this the first file in the compilation, or a PUT/USE?
// if first, change CWD to location of file
LOG_DEBUG << "Changing directory to: " << dir << endl;
//LOG_DEBUG << "Changing directory to: " << dir << endl;
if (chdir(dir.c_str())) {} // change directory to where the file is
}
@ -1221,6 +1249,7 @@ void CLASS::initpass(void)
allowdup = getBool("asm.allowduplicate", true);
skiplist = false;
generateCode = true;
PC.origin = 0x8000;
PC.currentpc = PC.origin;
@ -1270,14 +1299,17 @@ void CLASS::initpass(void)
{
LUPstack.pop();
}
while (!DOstack.empty())
{
DOstack.pop();
}
curLUP.clear();
curDO.clear();
savepath = "";
}
void CLASS::complete(void)
{
printf("\n\n=== Assembly Complete: %d bytes %u errors.\n", PC.totalbytes, errorct);
if (savepath != "")
{
if (errorct == 0)
@ -1309,13 +1341,16 @@ void CLASS::complete(void)
}
}
printf("\n\nEnd qASM assembly, %d bytes, %u errors, %lu lines, %lu symbols.\n", PC.totalbytes, errorct, lines.size(), symbols.size());
TFileProcessor::complete();
if (listing)
{
showSymbolTable(true);
showSymbolTable(false);
showVariables();
}
TFileProcessor::complete();
}
int CLASS::evaluate(MerlinLine &line, std::string expr, int64_t &value)
@ -1548,6 +1583,18 @@ int CLASS::substituteVariables(MerlinLine & line)
return (res);
}
bool CLASS::codeSkipped(void)
{
bool res = false;
if (curLUP.lupskip)
{
res = true;
}
return (res);
}
void CLASS::process(void)
{
uint32_t l;
@ -1575,12 +1622,12 @@ void CLASS::process(void)
operand = Poco::toLower(line.operand);
line.startpc = PC.currentpc;
line.linemx = mx;
uint16_t cc=tabs[2];
if (cc==0)
uint16_t cc = tabs[2];
if (cc == 0)
{
cc=40;
cc = 40;
}
line.commentcol=cc;
line.commentcol = cc;
line.bytect = 0;
line.showmx = showmx;
@ -1640,6 +1687,11 @@ void CLASS::process(void)
x = callOpCode(op, line);
}
if ((x > 0) && (codeSkipped())) // has a psuedo-op turned off code generation? (LUP, IF, etc)
{
x = 0;
}
if (x > 0)
{
if (!PCstack.empty()) // are we inside a DUM section?
@ -1698,6 +1750,7 @@ void CLASS::process(void)
// end of file reached here, do some final checks
#if 0
if (LUPstack.size() > 0)
{
errLine.clear();
@ -1705,6 +1758,7 @@ void CLASS::process(void)
errLine.print(lineno);
pass = 2;
}
#endif
pass++;
}

42
asm.h
View File

@ -18,6 +18,8 @@
#define FLAG_BIGNUM 0x10
#define FLAG_INDUM 0x20
#define FLAG_FORCEADDRPRINT 0x0100
#define FLAG_NOLINEPRINT 0x2000
#define OP_A 0x0001
#define OP_XY 0x0002
@ -49,7 +51,6 @@ enum asmErrors
errBadBranch,
errForwardRef,
errNoRedefinition,
errBadOperand,
errDupSymbol,
errBadDUMop,
errOverflow,
@ -59,10 +60,13 @@ enum asmErrors
errFileNotFound,
errFileNoAccess,
errBadEvaluation,
errMalformed,
errIllegalCharOperand,
errBadCharacter,
errUnexpectedOp,
errUnexpectedEOF,
errBadLUPOperand,
errBadLabel,
errBadOperand,
errMAX
};
@ -81,7 +85,6 @@ const std::string errStrings[errMAX + 1] =
"Relative branch offset too large",
"Forward Reference to symbol",
"Unable to redefine symbol",
"Error in expression",
"Duplicate Symbol",
"Invalid use of DUM/DEND",
"Overflow detected",
@ -91,10 +94,13 @@ const std::string errStrings[errMAX + 1] =
"File not found",
"File no access",
"Unable to evaluate",
"Malformed Operand",
"Illegal char in operand",
"Unexpected character in input",
"Unexpected opcode",
"Unexpected End of File",
"LUP value must be 0 < VAL <= $8000",
"Unknown label",
"Bad operand",
""
};
@ -260,12 +266,29 @@ public:
lupct=0;
lupoffset=0;
luprunning=0;
lupskip=false;
}
uint16_t lupct;
bool lupskip;
uint32_t lupoffset;
uint16_t luprunning;
};
class TDOstruct
{
public:
TDOstruct()
{
clear();
}
void clear(void) {
dooff=false;
value=0;
}
uint32_t value;
bool dooff;
};
class TSymbol;
typedef int (*TOpCB)(MerlinLine &line, TSymbol &sym);
typedef std::function<int (MerlinLine &line, TSymbol &sym)> TOpCallback;
@ -322,6 +345,8 @@ public:
bool skiplist; // used if lst is on, but LST opcode turns it off
uint32_t lineno;
bool generateCode;
std::string savepath;
TSymbol *currentsym;
std::vector<MerlinLine> lines;
@ -331,9 +356,12 @@ public:
Poco::HashMap<std::string, TSymbol> variables;
TOriginSection PC;
TLUPstruct curLUP;
TDOstruct curDO;
std::stack<TOriginSection> PCstack;
std::stack<TLUPstruct> LUPstack;
TLUPstruct curLUP;
std::stack<TDOstruct> DOstack;
TPsuedoOp *psuedoops;
@ -363,6 +391,8 @@ public:
int evaluate(MerlinLine &line, std::string expr, int64_t &value);
int substituteVariables(MerlinLine & line);
bool codeSkipped(void);
int parseOperand(MerlinLine &line);
int getAddrMode(MerlinLine &line);
void setOpcode(MerlinLine &line, uint8_t op);
@ -397,4 +427,4 @@ public:
virtual void process(void);
virtual void complete(void);
};
};

View File

@ -754,10 +754,10 @@ void CLASS::insertOpcodes(void)
pushopcode("ADRL",P_DATA, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("HEX", P_HEX, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("DS", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("DO", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("ELSE", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("IF", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("FIN", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("DO", P_DO, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("ELSE",P_DO, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("IF", P_DO, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("FIN", P_DO, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("CHK", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("ERR", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("KBD", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));

View File

@ -13,11 +13,102 @@ CLASS::~CLASS()
}
int CLASS::doDO(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
{
UNUSED(opinfo);
TEvaluator eval(a);
int64_t eval_result = 0;
uint8_t shift;
int res = 0;
int err = 0;
std::string op = Poco::toUpper(line.opcode);
std::string oper = Poco::toUpper(line.operand);
if (op == "IF")
{
if (oper == "")
{
err = errIllegalCharOperand;
}
goto out;
}
if (op == "DO")
{
if (oper == "")
{
err = errIllegalCharOperand;
goto out;
}
//line.flags |= FLAG_NOLINEPRINT;
shift = 0;
eval_result = 0;
int x = eval.evaluate(line.operand, eval_result, shift);
a.curDO.dooff = (eval_result & 0xFFFFFF); // evaluate here
if (x < 0)
{
a.curDO.dooff = false;
err = errBadLabel;
if (a.pass == 0)
{
err = errForwardRef;
}
}
a.DOstack.push(a.curDO);
goto out;
}
if (op == "ELSE")
{
//line.flags |= FLAG_NOLINEPRINT;
a.curDO.dooff = !a.curDO.dooff;
goto out;
}
if (op == "FIN")
{
//line.flags |= FLAG_NOLINEPRINT;
if (a.DOstack.size() > 0)
{
// kind of a silent error here, just make sure we reinitialize
a.curDO.dooff = false;
a.curDO = a.DOstack.top();
a.DOstack.pop();
}
else
{
// kind of a silent error here, just make sure we reinitialize
a.curDO.dooff = false;
}
goto out;
}
out:
if (err > 0)
{
line.setError(err);
}
return (res);
}
int CLASS::doLUP(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
{
UNUSED(opinfo);
UNUSED(line);
UNUSED(a);
TEvaluator eval(a);
int64_t eval_result = 0;
uint8_t shift;
int lidx, len;
int res = 0;
int err = 0;
@ -26,24 +117,38 @@ int CLASS::doLUP(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
if (op == "LUP")
{
line.flags |= FLAG_NOLINEPRINT;
len = line.lineno - 1; // MerlinLine line numbers are +1 from actual array idx
if (len >= 0)
{
shift = 0;
eval_result = 0;
int x = eval.evaluate(line.operand, eval_result, shift);
a.LUPstack.push(a.curLUP);
a.curLUP.lupoffset = len;
a.curLUP.lupct = 3; // evaluate here
a.curLUP.lupct = eval_result & 0xFFFF; // evaluate here
a.curLUP.luprunning++;
if ((x < 0) || (eval_result <= 0) || (eval_result > 0x8000))
{
// merlin just ignores LUP if the value is out of range
a.curLUP.lupct = 0;
a.curLUP.lupskip = true;
}
}
else
{
printf("err 3\n");
err = errUnexpectedOp;
}
}
if (op == "--^")
{
line.flags |= FLAG_NOLINEPRINT;
if (a.curLUP.luprunning > 0)
{
lidx = line.lineno - 1;
@ -58,6 +163,10 @@ int CLASS::doLUP(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
goto out;
}
}
// kind of a silent error here, just make sure we reinitialize
a.curLUP.luprunning = 0;
a.curLUP.lupct = 0;
a.curLUP.lupskip = false;
//printf("start=%d end=%d len=%d\n", a.curLUP.lupoffset, lidx, len);
if (a.LUPstack.size() > 0)
@ -67,14 +176,14 @@ int CLASS::doLUP(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
}
else
{
printf("err 2\n");
err = errUnexpectedOp;
}
}
else
{
printf("err 1\n");
err = errUnexpectedOp;
a.curLUP.lupskip = false;
// SGQ - found a '--^' without a LUP, should we just ignore?
//err = errUnexpectedOp;
}
}
@ -289,6 +398,14 @@ int CLASS::doHEX(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
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];
@ -311,8 +428,9 @@ int CLASS::doHEX(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
}
else
{
line.setError(errBadCharacter);
return 0;
line.setError(errIllegalCharOperand);
bytect = 0;
goto out;
}
// Got a good char, append to hex string and see if we've got a byte
@ -338,9 +456,10 @@ int CLASS::doHEX(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
}
if (ct & 0x01) // we got an odd number of nibbles
{
line.setError(errMalformed);
line.setError(errBadOperand);
bytect = 0;
}
out:
line.outbytect = bytect;
return bytect;
}
@ -367,6 +486,8 @@ int CLASS::ProcessOpcode(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
case P_DUM:
case P_DEND:
res = doDUM(a, line, opinfo);
line.flags |= FLAG_FORCEADDRPRINT;
break;
case P_ORG:
if (line.operand.length() > 0)
@ -380,6 +501,7 @@ int CLASS::ProcessOpcode(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
a.PC.currentpc = a.PC.orgsave;
line.startpc = a.PC.orgsave;
}
line.flags |= FLAG_FORCEADDRPRINT;
break;
case P_SAV:
a.savepath = a.processFilename(line.operand, Poco::Path::current(), 0);
@ -395,8 +517,11 @@ int CLASS::ProcessOpcode(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
break;
case P_LUP:
res = doLUP(a, line, opinfo);
res = 0;
break;
case P_DO:
res = doDO(a, line, opinfo);
break;
}
return (res);
}

View File

@ -16,6 +16,7 @@ enum
P_HEX,
P_DATA,
P_LUP,
P_DO,
P_MAX
};
@ -32,6 +33,8 @@ public:
int doHEX(T65816Asm &a, MerlinLine &line, TSymbol &opinfo);
int doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo);
int doLUP(T65816Asm &a, MerlinLine &line, TSymbol &opinfo);
int doDO(T65816Asm &a, MerlinLine &line, TSymbol &opinfo);;
};

View File

@ -31,7 +31,7 @@ merlincompatible=true
symcolumns=3
[reformat]
tabs=12; 18; 36
tabs=12; 18; 30;
;tabs=0;0;0

View File

@ -1,4 +1,4 @@
lst off
;lst off
*
* main.s
* Merlin32 Test
@ -40,7 +40,6 @@ TSTADDR = $1000 ;absolute address for testing
*==========================================================
* Data Index DUM section test
lst off
DUM 0
dum0 ds 1 ;fractional byte
dum1 ds 1
@ -396,11 +395,8 @@ L00BC bit L00BC
lst
lup_start:
lup 3
;db 0 ; outside
;lup 3
;db 1 ; inside
;--^
lup 0
db 0 ; outside
--^