Merge pull request #19 from marketideas/sgq_qasm_main

Sgq qasm main
This commit is contained in:
marketideas 2019-11-19 12:08:31 -08:00 committed by GitHub
commit d30965d72d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 252 additions and 98 deletions

261
asm.cpp
View File

@ -2,6 +2,9 @@
#include "asm.h"
#include "eval.h"
#include "psuedo.h"
#include <sys/ioctl.h>
#include <unistd.h>
#define CLASS MerlinLine
@ -99,7 +102,7 @@ void CLASS::print(uint32_t lineno)
}
}
bool empty = false;
if ((printlable == "") && (opcode == "") && (operand == ""))
if ((printlable == "") && (opcode == "") && (printoperand == ""))
{
empty = true;
}
@ -174,7 +177,7 @@ void CLASS::print(uint32_t lineno)
{
pcol += printf("%c", comment[cc]);
comct++;
if ((comment[cc] <= ' ') && (pcol >= (commentcol + savpcol + 10)))
if ((comment[cc] <= ' ') && (pcol >= (commentcol + savpcol + 20)))
{
printf("\n");
pcol = 0;
@ -202,7 +205,14 @@ void CLASS::print(uint32_t lineno)
{
pcol += printf(" ");
}
pcol += printf("%s ", operand.c_str());
if (isDebug() > 2)
{
pcol += printf("%s ", operand.c_str());
}
else
{
pcol += printf("%s ", printoperand.c_str());
}
//pcol += printf("%-12s %-8s %-10s ", printlable.c_str(), opcode.c_str(), operand.c_str());
}
if ((errorcode > 0) && (!merlinerrors))
@ -287,6 +297,7 @@ void CLASS::clear()
opcode = "";
opcodelower = "";
operand = "";
printoperand = "";
comment = "";
operand_expr = "";
operand_expr2 = "";
@ -416,6 +427,11 @@ void CLASS::set(std::string line)
restofline = Poco::trim(tline.substr(i, tline.length())) + " ";
//printf("ROL: |%s|\n",restofline.c_str());
if (restofline == "")
{
i = l;
break;
}
strs.clear();
x = 0;
try
@ -478,9 +494,7 @@ void CLASS::set(std::string line)
i = l;
if (!match)
{
opcode = ":::"; // let assembler figure out this is a bad opcode
// SGQ maybe error here
//printf("---No Match %s\n", restofline.c_str());
// if you are here, there probably isn't an operand and/or comment after opcode
}
}
break;
@ -490,15 +504,16 @@ void CLASS::set(std::string line)
x = lable.length();
if (x > 1)
{
// SGQ M32 syntax
#if 0
while ((x > 1) && (lable[x - 1] == ':'))
// M32 syntax allows a colon after lable, and it is not part of the lable
if ((syntax & SYNTAX_MERLIN32) == SYNTAX_MERLIN32)
{
lable = lable.substr(0, x - 1);
x--;
while ((x > 1) && (lable[x - 1] == ':'))
{
lable = lable.substr(0, x - 1);
x--;
}
//printf("linelable: |%s|\n", lable.c_str());
}
//printf("linelable: |%s|\n", lable.c_str());
#endif
}
opcodelower = Poco::toLower(opcode);
@ -509,7 +524,20 @@ void CLASS::set(std::string line)
CLASS::CLASS()
{
int x;
errorct = 0;
win_columns = -1;
win_rows = -1;
struct winsize w;
x = ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
if (x == 0)
{
win_columns = w.ws_col;
win_rows = w.ws_row;
}
//printf("cols=%d rows=%d\n",win_columns,win_rows);
}
CLASS::~CLASS()
@ -529,9 +557,24 @@ void CLASS::init(void)
filenames.clear();
starttime = GetTickCount();
initialdir = Poco::Path::current();
syntax = 0;
syntax = SYNTAX_MERLIN;
filecount = 0;
s = getConfig("option.syntax", "merlin16");
s = Poco::toUpper(Poco::trim(s));
if ((s == "MERLIN") || (s == "MERLIN16"))
{
syntax = SYNTAX_MERLIN;
}
else if (s == "MERLIN32")
{
syntax = SYNTAX_MERLIN32;
}
else if (s == "QASM")
{
syntax = SYNTAX_QASM;
}
std::string tabstr = getConfig("reformat.tabs", "8,16,32");
tabstr = Poco::trim(tabstr);
@ -1139,7 +1182,7 @@ TSymbol * CLASS::addVariable(std::string symname, std::string val, bool replace)
if (fnd != NULL)
{
//printf("replacing symbol: %s %08X\n",sym.c_str(),val);
fnd->text = val;
fnd->var_text = val;
return (fnd);
}
@ -1149,7 +1192,7 @@ TSymbol * CLASS::addVariable(std::string symname, std::string val, bool replace)
s.namelc = Poco::toLower(sym);
s.stype = 0;
s.value = 0;
s.text = val;
s.var_text = val;
s.used = false;
s.cb = NULL;
@ -1166,7 +1209,7 @@ TSymbol * CLASS::findVariable(std::string symname)
TSymbol *res = NULL;
//printf("finding: %s\n",symname.c_str());
auto itr = variables.find(Poco::toUpper(symname));
auto itr = variables.find(symname);
if (itr != variables.end())
{
//printf("Found: %s 0x%08X\n",itr->second.name.c_str(),itr->second.value);
@ -1185,7 +1228,7 @@ void CLASS::showVariables(void)
for (auto itr = variables.begin(); itr != variables.end(); ++itr)
{
printf("%-16s %s\n", itr->first.c_str(), itr->second.text.c_str());
printf("%-16s %s\n", itr->first.c_str(), itr->second.var_text.c_str());
}
printf("\n");
}
@ -1291,12 +1334,23 @@ int CLASS::callOpCode(std::string op, MerlinLine &line)
case '>':
line.expr_value >>= 8;
line.expr_value &= 0xFFFF;
if ((line.syntax & SYNTAX_MERLIN32) == SYNTAX_MERLIN32)
{
line.flags |= FLAG_FORCEABS;
}
break;
case '^':
line.expr_value = (line.expr_value >> 16) & 0xFFFF;
if ((line.syntax & SYNTAX_MERLIN32) == SYNTAX_MERLIN32)
{
line.flags |= FLAG_FORCEABS;
}
break;
case '|':
line.flags |= FLAG_FORCELONG;
if ((line.syntax & SYNTAX_MERLIN32) != SYNTAX_MERLIN32)
{
line.flags |= FLAG_FORCELONG;
}
break;
}
if (line.expr_value >= 0x100)
@ -1419,7 +1473,22 @@ void CLASS::initpass(void)
merlinerrors = getBool("asm.merlinerrors", true);
trackrep = getBool("asm.trackrep", false);
merlincompat = getBool("asm.merlincompatible", true);
if (syntax == SYNTAX_MERLIN32)
{
trackrep = true; // can't turn this off in M32
}
else if (syntax == SYNTAX_MERLIN)
{
trackrep = false; // can't turn this ON in M16
}
else if (syntax == SYNTAX_QASM)
{
// we will allow this to be settable default off
trackrep = false;
trackrep = getBool("asm.trackrep", trackrep);
}
//merlincompat = getBool("asm.merlincompatible", true);
allowdup = getBool("asm.allowduplicate", true);
skiplist = false;
@ -1461,7 +1530,12 @@ void CLASS::initpass(void)
lastcarry = false;
relocatable = false;
currentsym = &topSymbol; // this is the default symbol for :locals without a global above;
currentsym = NULL;
if ((syntax & SYNTAX_MERLIN32) == SYNTAX_MERLIN32)
{
// M32 allows locals that don't have a global above. this is the catchall for that
currentsym = &topSymbol; // this is the default symbol for :locals without a global above;
}
currentsymstr = "";
lineno = 0;
errorct = 0;
@ -1665,18 +1739,17 @@ int CLASS::getAddrMode(MerlinLine & line)
// 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
if ((line.syntax & SYNTAX_MERLIN32) == SYNTAX_MERLIN32)
{
// 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)
if (Poco::toUpper(oper) == "A") // check the whole operand, not just the expression
{
line.flags |= FLAG_FORCEIMPLIED;
mode = syn_implied; // if the label hasn't been defined yet, assume Immediate addressing
goto out;
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;
}
}
}
}
@ -1742,63 +1815,93 @@ int CLASS::parseOperand(MerlinLine & line)
return (res);
}
int CLASS::substituteVariables(MerlinLine & line)
int CLASS::substituteVariables(MerlinLine & line, std::string &outop)
{
int res = -1;
int res = 0;
int x;
std::string::size_type offset, slen;
std::string oper = line.operand;
std::string s;
std::string operin;
TSymbol *sym;
uint32_t len, off, ct;
slen = oper.length();
if (slen > 0)
bool done = false;
operin = oper;
ct = 0;
restart:
while (!done)
{
std::vector<std::string> groups;
offset = 0;
RegularExpression varEx(varExpression, Poco::RegularExpression::RE_EXTRA, true);
Poco::RegularExpression::MatchVec mVec;
//printf("|%s|%s|\n", varExpression.c_str(), oper.c_str());
groups.clear();
ct = 0;
while (offset < slen)
slen = oper.length();
if (slen > 0)
{
try
{
varEx.match(oper, offset, mVec, 0);
}
catch (...)
{
offset = slen;
}
std::vector<std::string> groups;
x = mVec.size();
if (x > 0)
offset = 0;
RegularExpression varEx(varExpression, 0, true);
Poco::RegularExpression::MatchVec mVec;
//printf("|%s|%s|\n", varExpression.c_str(), oper.c_str());
groups.clear();
while (offset < slen)
{
res = 0;
off = mVec[0].offset;
len = mVec[0].length;
s = oper.substr(off, len);
sym = findVariable(s);
if (sym != NULL)
try
{
ct++;
if (pass > 0)
{
//printf("%d |%s|\n", ct, s.c_str());
}
varEx.match(oper, offset, mVec, 0);
}
catch (...)
{
offset = slen;
}
offset += len;
}
else
{
offset = slen;
}
}
x = mVec.size();
if (x > 0)
{
res = 0;
off = mVec[0].offset;
len = mVec[0].length;
s = oper.substr(off, len);
sym = findVariable(s);
if (sym != NULL)
{
//printf("match |%s|\n",sym->var_text.c_str());
if (sym->var_text != "")
{
oper = oper.replace(off, len, sym->var_text);
ct++;
if (pass > 0)
{
//printf("%d |%s|\n", ct, s.c_str());
}
goto restart;
}
}
else
{
done = true;
}
offset += len;
}
else
{
offset = slen;
done = true;
}
}
}
else
{
done = true;
}
}
//printf("inoper=|%s| outoper=|%s|\n",operin.c_str(),oper.c_str());
if (ct > 0)
{
outop = oper;
res = ct;
}
return (res);
}
@ -1858,6 +1961,7 @@ void CLASS::process(void)
line.linemx = mx;
line.bytect = 0;
line.showmx = showmx;
line.syntax = syntax;
line.merlinerrors = merlinerrors;
if ((line.lable != ""))
@ -1872,7 +1976,7 @@ void CLASS::process(void)
sprintf(buff, "$%X", PC.currentpc);
ls = buff;
sym = addVariable(line.lable, ls, true);
if (sym == NULL) { dupsym = true; }
//if (sym == NULL) { dupsym = true; }
break;
case ':':
@ -1898,7 +2002,16 @@ void CLASS::process(void)
line.setError(errDupSymbol);
}
}
x = substituteVariables(line);
std::string outop;
if (pass == 0)
{
line.printoperand = line.operand;
}
x = substituteVariables(line, outop);
if (x > 0)
{
line.operand = outop;
}
x = parseOperand(line);
if (x >= 0)
{

33
asm.h
View File

@ -8,8 +8,18 @@
#define MODE_65816 2
#define SYNTAX_MERLIN 0
#define SYNTAX_APW 1
#define SYNTAX_ORCA 2
#define SYNTAX_MERLIN32 0x01
#define SYNTAX_APW 0x02
#define SYNTAX_ORCA 0x04
#define SYNTAX_QASM (0x08 | SYNTAX_MERLIN32)
#define OPTION_ALLOW_A_OPERAND 0x0100
#define OPTION_ALLOW_LOCAL 0x0200
#define OPTION_ALLOW_COLON 0x0400
#define OPTION_FORCE_REPSEP 0x0800
#define OPTION_NO_REPSEP 0x1000
#define OPTION_CFG_REPSEP 0x2000
#define OPTION_M32_VARS 0x4000
#define FLAG_FORCELONG 0x01
#define FLAG_FORCEABS 0x02
@ -68,6 +78,7 @@ enum asmErrors
errBadLUPOperand,
errBadLabel,
errBadOperand,
errErrOpcode,
errMAX
};
@ -102,6 +113,7 @@ const std::string errStrings[errMAX + 1] =
"LUP value must be 0 < VAL <= $8000",
"Unknown label",
"Bad operand",
"Break",
""
};
@ -177,9 +189,10 @@ class MerlinLine
{
public:
uint8_t syntax;
uint32_t syntax;
std::string lable;
std::string printlable;
std::string printoperand;
std::string opcode;
std::string opcodelower;
std::string operand;
@ -222,9 +235,11 @@ public:
class TFileProcessor
{
protected:
int win_columns;
int win_rows;
std::string initialdir;
std::vector<std::string> filenames;
uint8_t syntax;
uint32_t syntax;
uint64_t starttime;
uint8_t tabs[16];
@ -301,7 +316,8 @@ class TSymbol
public:
std::string namelc;
std::string name;
std::string text;
//std::string text;
std::string var_text;
uint32_t value;
uint16_t stype;
uint8_t opcode;
@ -317,7 +333,8 @@ public:
{
value = 0;
used = false;
text = "";
//text = "";
var_text="";
name = "";
namelc = "";
stype = 0;
@ -335,7 +352,6 @@ public:
bool casesen;
bool showmx;
bool trackrep;
bool merlincompat;
bool merlinerrors;
bool allowdup;
uint8_t mx;
@ -398,7 +414,8 @@ public:
void showVariables(void);
int evaluate(MerlinLine &line, std::string expr, int64_t &value);
int substituteVariables(MerlinLine & line);
int substituteVariables(MerlinLine & line, std::string &outop);
bool codeSkipped(void);
int parseOperand(MerlinLine &line);

View File

@ -94,7 +94,18 @@ int CLASS::doEQU(MerlinLine &line, TSymbol &sym)
else if (isvar)
{
res = -1;
s = addVariable(line.lable, line.operand, true);
if (syntax==SYNTAX_MERLIN)
{
char buff[32];
sprintf(buff,"$%08X",line.expr_value);
std::string s1=buff;
s = addVariable(line.lable, s1, true);
}
else
{
s = addVariable(line.lable, line.operand, true);
}
if (s != NULL)
{
res = 0;
@ -849,7 +860,7 @@ void CLASS::insertOpcodes(void)
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("ERR", P_ERR, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("KBD", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("LUP", P_LUP, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("--^", P_LUP, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));

View File

@ -844,6 +844,17 @@ int CLASS::ProcessOpcode(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
case P_SAV:
a.savepath = a.processFilename(line.operand, Poco::Path::current(), 0);
break;
case P_ERR:
if (a.pass>0)
{
if ((line.expr_value!=0) || (line.eval_result<0))
{
line.setError(errErrOpcode);
//a.passcomplete=true; // terminate assembly
}
}
res=0;
break;
case P_LST:
res = doLST(a, line, opinfo);
break;

View File

@ -19,6 +19,7 @@ enum
P_DO,
P_TR,
P_ASC,
P_ERR,
P_MAX
};

View File

@ -18,9 +18,11 @@ programOption PAL::appOptions[] =
#ifdef DEBUG
{ "debug", "d", "enable debug info (repeat for more verbosity)", "", false, true},
#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},
//{ "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},
{ "syntax", "s", "enforce syntax of other assembler [merlin16, merlin32]", "<syntax>", false, false},
{ "", "", "", "", false, false}
};

View File

@ -6,6 +6,7 @@ logfile=mylog.log
[option]
debug=1
nocolor=false
;syntax=merlin32
;debug must be an integer. Code can use this as a level
[application]
@ -28,8 +29,7 @@ lst=true
cpu=M65816
trackrep=true
allowduplicate=true
merlinerrors=false
merlincompatible=true
merlinerrors=true
symcolumns=3
[reformat]

View File

@ -29,7 +29,7 @@ for S in $SRC ; do
BASE=${BASE/.s/}
#./qasm -o 0/$OUTDIR/$S1 ./testdata/$S
./qasm -o 0/$OUTDIR/$S1 ./testdata/$S >> $TMPFILE
./qasm --syntax merlin32 -o 0/$OUTDIR/$S1 ./testdata/$S >> $TMPFILE
R=?$
#echo $S " " $S1

View File

@ -307,7 +307,7 @@ myQuit
sbc ^$012345
sbc |$012345
asll $1234
;asll $1234
lda <$fff0+24 ;zp
lda >$fff0+24 ;ABS (lo word)
@ -411,8 +411,8 @@ L00BC bit L00BC
asc 02,15,?123456?
asc 02,15,>123456>
asc 02,15,<123456<
asc 02,15,5,"123456"
asc 02,15,"123456
asc 02,15,05,"123456"
asc 02,15,"123456"
asc 0215"1234"1502
@ -423,7 +423,7 @@ lup_start:
--^
lst off
;lst off
//]XCODEEND ; Keep this at the end and put your code above this
;lst off

View File

@ -155,5 +155,5 @@ LOCAL1 lda #$2c ;EDIT: format as ASCII
beq LOCAL1
LOCAL2 lda $2c ;EDIT: format as ASCII
ldx $5678 ;put empty variable table here
;beq LOCAL2
beq LOCAL2
rts

View File

@ -1,13 +1,12 @@
(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 - Note (syntax) Merlin doesn't allow 'A' implied addressing
(0) 2019-11-17 - Note (syntax): Merlin doesn't allow local labels without a previous global
(0) 2019-11-17 - Note (syntax): Merlin doesn't allow local colons after label which is ignored
(0) 2019-11-17 - Note (syntax): Merlin doesn't allow for 'rep/sep/xce' tracking
(0) 2019-11-17 - Bug (evaluation routine puts ascii bytes in reverse order (#"AB")
(0) 2019-11-17 -
(0) 2019-11-17 -
(0) 2019-11-17 - want to wrap comments based on current terminal width, and don't if printing to non-terminal
(0) 2019-11-17 - syntax options - check OPTION bits, not syntax type (OPTION_ALLOW_LOCAL)
(0) 2019-11-17 -
(0) 2019-11-17 -
(0) 2019-11-17 -