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 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;
@ -46,7 +48,25 @@ void CLASS::print(uint32_t lineno)
{ {
l = b; 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) if (!checked)
{ {
nc1 = getBool("option.nocolor", false); nc1 = getBool("option.nocolor", false);
@ -57,7 +77,7 @@ void CLASS::print(uint32_t lineno)
nc = nc1; nc = nc1;
} }
if (!isatty(STDOUT_FILENO)) if ((!isatty(STDOUT_FILENO)) || (merlinstyle))
{ {
nc = true; nc = true;
} }
@ -87,7 +107,12 @@ void CLASS::print(uint32_t lineno)
} }
pcol = 0; 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); pcol += printf("%02X/%04X:", (startpc >> 16), startpc & 0xFFFF);
} }
@ -143,14 +168,17 @@ void CLASS::print(uint32_t lineno)
pcol += printf(" "); pcol += printf(" ");
} }
} }
//pcol += printf("%s", comment.c_str()); else
{
pcol += printf("%s", comment.c_str());
}
} }
} }
else else
{ {
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) if ((errorcode > 0) && (!merlinstyle))
{ {
while (pcol < commentcol) while (pcol < commentcol)
{ {
@ -233,7 +261,7 @@ void CLASS::clear()
operand_expr2 = ""; operand_expr2 = "";
addrtext = ""; addrtext = "";
linemx = 0; linemx = 0;
commentcol=40; commentcol = 40;
bytect = 0; bytect = 0;
opflags = 0; opflags = 0;
pass0bytect = 0; pass0bytect = 0;
@ -456,12 +484,12 @@ void CLASS::complete(void)
{ {
uint64_t n = GetTickCount(); uint64_t n = GetTickCount();
if (isDebug()) //if (isDebug())
{ {
//cout << "Processing Time: " << n - starttime << "ms" << endl; //cout << "Processing Time: " << n - starttime << "ms" << endl;
uint64_t x = n - starttime; uint64_t x = n - starttime;
uint32_t x1 = x & 0xFFFFFFFF; uint32_t x1 = x & 0xFFFFFFFF;
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? // is this the first file in the compilation, or a PUT/USE?
// if first, change CWD to location of file // 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 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); allowdup = getBool("asm.allowduplicate", true);
skiplist = false; skiplist = false;
generateCode = true;
PC.origin = 0x8000; PC.origin = 0x8000;
PC.currentpc = PC.origin; PC.currentpc = PC.origin;
@ -1270,14 +1299,17 @@ void CLASS::initpass(void)
{ {
LUPstack.pop(); LUPstack.pop();
} }
while (!DOstack.empty())
{
DOstack.pop();
}
curLUP.clear(); curLUP.clear();
curDO.clear();
savepath = ""; savepath = "";
} }
void CLASS::complete(void) void CLASS::complete(void)
{ {
printf("\n\n=== Assembly Complete: %d bytes %u errors.\n", PC.totalbytes, errorct);
if (savepath != "") if (savepath != "")
{ {
if (errorct == 0) 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) if (listing)
{ {
showSymbolTable(true); showSymbolTable(true);
showSymbolTable(false); showSymbolTable(false);
showVariables(); showVariables();
} }
TFileProcessor::complete();
} }
int CLASS::evaluate(MerlinLine &line, std::string expr, int64_t &value) int CLASS::evaluate(MerlinLine &line, std::string expr, int64_t &value)
@ -1548,6 +1583,18 @@ int CLASS::substituteVariables(MerlinLine & line)
return (res); return (res);
} }
bool CLASS::codeSkipped(void)
{
bool res = false;
if (curLUP.lupskip)
{
res = true;
}
return (res);
}
void CLASS::process(void) void CLASS::process(void)
{ {
uint32_t l; uint32_t l;
@ -1575,12 +1622,12 @@ void CLASS::process(void)
operand = Poco::toLower(line.operand); operand = Poco::toLower(line.operand);
line.startpc = PC.currentpc; line.startpc = PC.currentpc;
line.linemx = mx; line.linemx = mx;
uint16_t cc=tabs[2]; uint16_t cc = tabs[2];
if (cc==0) if (cc == 0)
{ {
cc=40; cc = 40;
} }
line.commentcol=cc; line.commentcol = cc;
line.bytect = 0; line.bytect = 0;
line.showmx = showmx; line.showmx = showmx;
@ -1640,6 +1687,11 @@ void CLASS::process(void)
x = callOpCode(op, line); 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 (x > 0)
{ {
if (!PCstack.empty()) // are we inside a DUM section? 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 // end of file reached here, do some final checks
#if 0
if (LUPstack.size() > 0) if (LUPstack.size() > 0)
{ {
errLine.clear(); errLine.clear();
@ -1705,6 +1758,7 @@ void CLASS::process(void)
errLine.print(lineno); errLine.print(lineno);
pass = 2; pass = 2;
} }
#endif
pass++; pass++;
} }

40
asm.h
View File

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

View File

@ -754,10 +754,10 @@ void CLASS::insertOpcodes(void)
pushopcode("ADRL",P_DATA, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("ADRL",P_DATA, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("HEX", P_HEX, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("HEX", P_HEX, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("DS", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("DS", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("DO", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("DO", P_DO, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("ELSE", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("ELSE",P_DO, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("IF", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("IF", P_DO, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("FIN", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("FIN", P_DO, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("CHK", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("CHK", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("ERR", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("ERR", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("KBD", 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) int CLASS::doLUP(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
{ {
UNUSED(opinfo); UNUSED(opinfo);
UNUSED(line);
UNUSED(a); TEvaluator eval(a);
int64_t eval_result = 0;
uint8_t shift;
int lidx, len; int lidx, len;
int res = 0; int res = 0;
int err = 0; int err = 0;
@ -26,24 +117,38 @@ int CLASS::doLUP(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
if (op == "LUP") if (op == "LUP")
{ {
line.flags |= FLAG_NOLINEPRINT;
len = line.lineno - 1; // MerlinLine line numbers are +1 from actual array idx len = line.lineno - 1; // MerlinLine line numbers are +1 from actual array idx
if (len >= 0) if (len >= 0)
{ {
shift = 0;
eval_result = 0;
int x = eval.evaluate(line.operand, eval_result, shift);
a.LUPstack.push(a.curLUP); a.LUPstack.push(a.curLUP);
a.curLUP.lupoffset = len; a.curLUP.lupoffset = len;
a.curLUP.lupct = 3; // evaluate here a.curLUP.lupct = eval_result & 0xFFFF; // evaluate here
a.curLUP.luprunning++; 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 else
{ {
printf("err 3\n");
err = errUnexpectedOp; err = errUnexpectedOp;
} }
} }
if (op == "--^") if (op == "--^")
{ {
line.flags |= FLAG_NOLINEPRINT;
if (a.curLUP.luprunning > 0) if (a.curLUP.luprunning > 0)
{ {
lidx = line.lineno - 1; lidx = line.lineno - 1;
@ -58,6 +163,10 @@ int CLASS::doLUP(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
goto out; 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); //printf("start=%d end=%d len=%d\n", a.curLUP.lupoffset, lidx, len);
if (a.LUPstack.size() > 0) if (a.LUPstack.size() > 0)
@ -67,14 +176,14 @@ int CLASS::doLUP(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
} }
else else
{ {
printf("err 2\n");
err = errUnexpectedOp; err = errUnexpectedOp;
} }
} }
else else
{ {
printf("err 1\n"); a.curLUP.lupskip = false;
err = errUnexpectedOp; // 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; uint32_t bytect = 0;
uint8_t b = 0; uint8_t b = 0;
uint8_t ct = 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 ) for ( uint32_t i = 0; i < os.length(); ++i )
{ {
char c = os[i]; char c = os[i];
@ -311,8 +428,9 @@ int CLASS::doHEX(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
} }
else else
{ {
line.setError(errBadCharacter); line.setError(errIllegalCharOperand);
return 0; bytect = 0;
goto out;
} }
// Got a good char, append to hex string and see if we've got a byte // 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 if (ct & 0x01) // we got an odd number of nibbles
{ {
line.setError(errMalformed); line.setError(errBadOperand);
bytect = 0; bytect = 0;
} }
out:
line.outbytect = bytect; line.outbytect = bytect;
return bytect; return bytect;
} }
@ -367,6 +486,8 @@ int CLASS::ProcessOpcode(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
case P_DUM: case P_DUM:
case P_DEND: case P_DEND:
res = doDUM(a, line, opinfo); res = doDUM(a, line, opinfo);
line.flags |= FLAG_FORCEADDRPRINT;
break; break;
case P_ORG: case P_ORG:
if (line.operand.length() > 0) if (line.operand.length() > 0)
@ -380,6 +501,7 @@ int CLASS::ProcessOpcode(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
a.PC.currentpc = a.PC.orgsave; a.PC.currentpc = a.PC.orgsave;
line.startpc = a.PC.orgsave; line.startpc = a.PC.orgsave;
} }
line.flags |= FLAG_FORCEADDRPRINT;
break; break;
case P_SAV: case P_SAV:
a.savepath = a.processFilename(line.operand, Poco::Path::current(), 0); a.savepath = a.processFilename(line.operand, Poco::Path::current(), 0);
@ -395,8 +517,11 @@ int CLASS::ProcessOpcode(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
break; break;
case P_LUP: case P_LUP:
res = doLUP(a, line, opinfo); res = doLUP(a, line, opinfo);
res = 0;
break; break;
case P_DO:
res = doDO(a, line, opinfo);
break;
} }
return (res); return (res);
} }

View File

@ -16,6 +16,7 @@ enum
P_HEX, P_HEX,
P_DATA, P_DATA,
P_LUP, P_LUP,
P_DO,
P_MAX P_MAX
}; };
@ -32,6 +33,8 @@ public:
int doHEX(T65816Asm &a, MerlinLine &line, TSymbol &opinfo); int doHEX(T65816Asm &a, MerlinLine &line, TSymbol &opinfo);
int doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo); int doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo);
int doLUP(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 symcolumns=3
[reformat] [reformat]
tabs=12; 18; 36 tabs=12; 18; 30;
;tabs=0;0;0 ;tabs=0;0;0

View File

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