fixed a few bugs, got more tests to pass, added some parms.json options

This commit is contained in:
Shawn Quick 2023-02-05 21:38:02 -08:00
parent 2f79abe461
commit 6e9eb6cfcc
23 changed files with 2547 additions and 2289 deletions

11
.gitignore vendored
View File

@ -1,3 +1,14 @@
**/build **/build
**/testdata1
*.bin
*.BIN
*.a
*.so
Finder.Data
test.s
disk_commands.txt
.vscode/browse*
.vscode/book*
*.xcuserstate *.xcuserstate
*.xcbkptlist *.xcbkptlist

296
asm.cpp
View File

@ -217,11 +217,13 @@ void CLASS::print(uint32_t lineno)
if (printoperand.length() > 0) if (printoperand.length() > 0)
{ {
pcol += printf("%s ", printoperand.c_str()); pcol += printf("%s ", printoperand.c_str());
//pcol += printf("%s ", orig_operand.c_str());
} }
else else
{ {
pcol += printf("%s ", operand.c_str()); pcol += printf("%s ", printoperand.c_str());
//pcol += printf("%s ", orig_operand.c_str());
} }
} }
//pcol += printf("%-12s %-8s %-10s ", printlable.c_str(), opcode.c_str(), operand.c_str()); //pcol += printf("%-12s %-8s %-10s ", printlable.c_str(), opcode.c_str(), operand.c_str());
@ -309,6 +311,7 @@ void CLASS::clear()
opcodelower = ""; opcodelower = "";
operand = ""; operand = "";
printoperand = ""; printoperand = "";
orig_operand="";
comment = ""; comment = "";
operand_expr = ""; operand_expr = "";
operand_expr2 = ""; operand_expr2 = "";
@ -494,6 +497,7 @@ void CLASS::set(std::string line)
{ {
//printf("%d regex %d match |%s|\n", ct, x, restofline.c_str()); //printf("%d regex %d match |%s|\n", ct, x, restofline.c_str());
operand = strs[0]; operand = strs[0];
orig_operand=operand;
//printf("which=%d operand=|%s|\n",ct,operand.c_str()); //printf("which=%d operand=|%s|\n",ct,operand.c_str());
i = (int)operand.length(); i = (int)operand.length();
restofline = restofline.substr(i, restofline.length()); restofline = restofline.substr(i, restofline.length());
@ -579,7 +583,9 @@ void CLASS::init(void)
filecount = 0; filecount = 0;
syntax = SYNTAX_QASM; syntax = SYNTAX_QASM;
std::string tabstr = getConfig("reformat.tabs", "8,16,32"); //std::string tabstr = getConfig("reformat.tabs", "8,16,32");
std::string tabstr = getConfig("reformat.tabs", "12,24,40,70");
tabstr = Poco::trim(tabstr); tabstr = Poco::trim(tabstr);
memset(tabs, 0x00, sizeof(tabs)); memset(tabs, 0x00, sizeof(tabs));
@ -722,7 +728,7 @@ std::string CLASS::processFilename(std::string fn, std::string curDir, int level
int CLASS::processfile(std::string p, std::string &newfilename) int CLASS::processfile(std::string p, std::string &newfilename)
{ {
//Poco::File fn(p); //Poco::File fn(p);
int c; int c,c1;
int res = -1; int res = -1;
uint32_t linect; uint32_t linect;
bool done, valid; bool done, valid;
@ -804,7 +810,7 @@ int CLASS::processfile(std::string p, std::string &newfilename)
} }
if ((fn.isDirectory()) || (!fn.canRead())) if ((fn.isDirectory()) || (!fn.canRead()))
{ {
LOG_DEBUG << "File is a directory: " << p1 << endl; LOG_DEBUG << "File is a directory or can not read: " << p1 << endl;
valid = false; valid = false;
} }
} }
@ -847,22 +853,34 @@ int CLASS::processfile(std::string p, std::string &newfilename)
{ {
//printf("file is open\n"); //printf("file is open\n");
line = ""; line = "";
while ((!done) && (f.good()) && (!f.eof())) while ((!done) && (f.good()) && (!f.eof()))
{ {
c = f.get(); c = f.get();
c1 = c & 0x7F;
if (c == 0x8D) // merlin line ending if (c == 0x8D) // merlin line ending
{ {
c = 0x0A; // convert to linux c = 0x0A; // convert to linux
} }
if (c == 0x8A) // possible merlin line ending else if (c == 0x8A) // possible merlin line ending
{ {
c = 0x00; // ignore c = 0x0D; // ignore
}
else if ((c1<0x20) || (c1==127)) // see if it might be a control character
{
if ((c1==0x0D) || (c1==0x0A) || (c1==0x09))
{
}
else
{
c=0x00;
}
} }
c &= 0x7F; c &= 0x7F;
int x; int x;
switch (c) switch (c)
{ {
case 0x00:
case 0x0D: case 0x0D:
break; break;
case 0x09: case 0x09:
@ -870,6 +888,7 @@ int CLASS::processfile(std::string p, std::string &newfilename)
break; break;
case 0x0A: case 0x0A:
linect++; linect++;
line=Poco::trimRight(line); //get rid of any space at end of line
x = doline(linect, line); x = doline(linect, line);
if (x < 0) if (x < 0)
{ {
@ -907,36 +926,11 @@ int CLASS::processfile(std::string p, std::string &newfilename)
return (res); return (res);
} }
#undef CLASS
#define CLASS TImageProcessor
CLASS::CLASS() : TFileProcessor()
{
}
CLASS::~TImageProcessor()
{
}
int CLASS::doline(int lineno, std::string line)
{
printf("%05d: %s\n",lineno,line.c_str());
return(0);
}
void CLASS::process(void)
{
}
void CLASS::complete(void)
{
}
#undef CLASS #undef CLASS
#define CLASS TMerlinConverter #define CLASS TMerlinConverter
CLASS::CLASS() : TFileProcessor() CLASS::CLASS() : TFileProcessor()
{ {
format_flags=CONVERT_TEST;
} }
CLASS::~CLASS() CLASS::~CLASS()
{ {
@ -962,72 +956,130 @@ void CLASS::process(void)
char buff[128*1024]; char buff[128*1024];
uint32_t ct = (uint32_t)lines.size(); uint32_t ct = (uint32_t)lines.size();
uint8_t orval=0x80; uint8_t orval=0x00;
uint32_t flags;
string s;
int llen,oplen,operlen,comlen;
string lable,opcode,operand,comment;
uint32_t len, tlen,t, pos,i; uint32_t len, tlen,t, pos,i;
tlen=0; tlen=0;
flags=format_flags;
for (uint32_t lineno = 0; lineno < ct; lineno++) for (uint32_t lineno = 0; lineno < ct; lineno++)
{ {
MerlinLine &line = lines.at(lineno); MerlinLine &line = lines.at(lineno);
orval=0x00;
if (flags&CONVERT_HIGH)
{
orval=0x80;
}
len=0; len=0;
pos = 0; pos = 0;
if ((line.lable.length() == 0)
&& (line.opcode.length() == 0) lable=Poco::trimRight(line.printlable);
&& (line.operand.length() == 0)) llen=lable.length();
opcode=Poco::trimRight(line.opcode);
oplen=opcode.length();
operand=Poco::trimRight(line.operand);
operlen=operand.length();
comment=Poco::trimRight(line.comment);
comlen=comment.length();
if ((llen+oplen+operlen)==0)
{ {
if (line.comment.length() > 0) if (comlen > 0)
{ {
char c = line.comment[0]; char c = comment[0];
if ((c == '*') || (c == '/')) if ((c == '*') || (c == '/'))
{ {
sprintf(&buff[len+tlen],"%s", line.comment.c_str()); len+=sprintf(&buff[len+tlen],"%s", comment.c_str());
} }
else else
{ {
t = tabs[2]; t = tabs[2];
if (flags&CONVERT_COMPRESS)
{
len += sprintf(&buff[len+tlen]," ");
}
else
{
while (len < t) while (len < t)
{ {
len += sprintf(&buff[len+tlen]," "); len += sprintf(&buff[len+tlen]," ");
} }
sprintf(&buff[len+tlen],"%s", line.comment.c_str()); }
len+=sprintf(&buff[len+tlen],"%s", comment.c_str());
} }
} }
sprintf(&buff[len+tlen],"\r");
} }
else else
{ {
t = tabs[pos++]; t = tabs[pos++];
len = sprintf(&buff[len+tlen],"%s ", line.printlable.c_str()); len += sprintf(&buff[len+tlen],"%s", lable.c_str());
while (len < t) if ((oplen+operlen+comlen)>0)
{
if (flags&CONVERT_COMPRESS)
{ {
len += sprintf(&buff[len+tlen]," "); len += sprintf(&buff[len+tlen]," ");
} }
t = tabs[pos++];
len += sprintf(&buff[len+tlen],"%s ", line.opcode.c_str());
while (len < t)
{
len += sprintf(&buff[len+tlen]," ");
}
t = tabs[pos++];
len += sprintf(&buff[len+tlen],"%s ", line.operand.c_str());
while (len < t)
{
len += sprintf(&buff[len+tlen]," ");
}
t = tabs[pos++];
len += sprintf(&buff[len+tlen],"%s", line.comment.c_str());
while (len < t)
{
len += sprintf(&buff[len+tlen]," ");
}
if (syntax ==SYNTAX_MERLIN)
len += sprintf(&buff[len+tlen],"\r");
else else
len += sprintf(&buff[len+tlen],"\n"); {
while (len < t)
{
len += sprintf(&buff[len+tlen]," ");
}
}
}
t = tabs[pos++];
len += sprintf(&buff[len+tlen],"%s", opcode.c_str());
if ((operlen+comlen)>0)
{
if (flags&CONVERT_COMPRESS)
{
len += sprintf(&buff[len+tlen]," ");
}
else
{
while (len < t)
{
len += sprintf(&buff[len+tlen]," ");
}
}
}
t = tabs[pos++];
len += sprintf(&buff[len+tlen],"%s", operand.c_str());
if ((comlen)>0)
{
if (flags&CONVERT_COMPRESS)
{
len += sprintf(&buff[len+tlen]," ");
}
else
{
while (len < t)
{
len += sprintf(&buff[len+tlen]," ");
}
}
}
len += sprintf(&buff[len+tlen],"%s", comment.c_str());
}
if (flags&CONVERT_CRLF)
{
len+=sprintf(&buff[len+tlen],"\r\n");
}
else if (flags&CONVERT_LF)
{
len+=sprintf(&buff[len+tlen],"\n");
}
else
{
len+=sprintf(&buff[len+tlen],"\r");
} }
tlen+=len; tlen+=len;
} }
@ -1035,45 +1087,58 @@ void CLASS::process(void)
if (tlen>0) if (tlen>0)
{ {
int tct=0; int tct=0;
int idx=0;
for (i=0; i<tlen; i++) for (i=0; i<tlen; i++)
{ {
char c=buff[i]; char c=buff[i];
if (c==0x20) if (c==0x20)
{ {
if (tct<3) if (tct<3)
buff[i]=0x20 | orval; {
buff[idx++]=0x20 | orval;
}
else else
{ {
buff[i]=0x20; buff[idx++]=0x20;
} }
tct++; tct++;
} }
else if (c==0x0D) else if (c==0x0D)
{ {
buff[i]=0x0D; buff[idx++]=0x0D | orval;
tct=0; tct=0;
} }
else if (c==0x0A) else if (c==0x0A)
{ {
buff[i]=0x0D; if ((flags&(CONVERT_COMPRESS|CONVERT_HIGH))==(CONVERT_COMPRESS | CONVERT_HIGH))
{
// don't allow any LFs if converting to merlin
}
else
{
buff[idx++]=0x0A;
}
tct=0; tct=0;
} }
else else
{ {
buff[i]=c|orval; buff[idx++]=c|orval;
} }
} }
FILE *f=NULL; FILE *f=NULL;
//string outfile=
f=fopen("./aout.s","w+"); f=fopen("./aout.s","w+");
if (f!=NULL) if (f!=NULL)
{ {
fwrite(buff,1,tlen,f); fwrite(buff,1,idx,f);
fclose(f); fclose(f);
printf("file ok\n"); printf("file ok\n");
} }
else else
{
printf("file error\n"); printf("file error\n");
} }
}
} }
void CLASS::complete(void) void CLASS::complete(void)
@ -1227,7 +1292,25 @@ TSymbol * CLASS::findSymbol(std::string symname)
} }
if (symname.length() > 0) if (symname.length() > 0)
{ {
if (symname[0] == ':') if (symname[0] == ']')
{
//printf("finding symbol: |%s|\n",symname.c_str());
res = findVariable(symname, variables);
if (res!=NULL)
{
//printf("symbol found: |%s| |%s|\n",symname.c_str(),res->var_text.c_str());
TEvaluator eval(*this);
int64_t er_val=0;
uint8_t shift=0;
int er;
er = eval.evaluate(res->var_text, er_val, shift);
if (er == 0)
{
res->value=er_val;
}
}
}
else if (symname[0] == ':')
{ {
if (currentsym == NULL) if (currentsym == NULL)
{ {
@ -1582,23 +1665,25 @@ const TaddrMode addrRegEx[] =
{ "^(?'expr'.+)\\,[s,S]{1}$", syn_s, "e,s"}, // expr,s { "^(?'expr'.+)\\,[s,S]{1}$", syn_s, "e,s"}, // expr,s
{"^[(]{1}(?'expr'.+)[,]{1}[(S|s)]{1}[)]{1}[,]{1}[(Y|y)]{1}$", syn_sy, "(e,s),y"}, // (expr,s),y {"^[(]{1}(?'expr'.+)[,]{1}[(S|s)]{1}[)]{1}[,]{1}[(Y|y)]{1}$", syn_sy, "(e,s),y"}, // (expr,s),y
{"^#{1}(.+)$", syn_imm, "immediate"}, //#expr,#^expr,#|expr,#<expr,#>expr {"^#{1}(.+)$", syn_imm, "immediate"}, //#expr,#^expr,#|expr,#<expr,#>expr
{"^[(]{1}(?'expr'.+)[,]{1}[x,X]{1}\\)$", syn_diix, "(e,x)"}, // (expr,x) {"^[(]{1}(?'expr'.+)[,]{1}[x,X]{1}\\)$", syn_diix, "(dp,x)"}, // (expr,x)
{"^[(]{1}(?'expr'.+)[\\)]{1}[\\,][(Y|y]{1}$", syn_diiy, "(e),y"}, //(expr),y {"^[(]{1}(?'expr'.+)[\\)]{1}[\\,][(Y|y]{1}$", syn_diiy, "(dp),y"}, //(expr),y
{"^[(]{1}(?'expr'.+)[\\)]{1}$", syn_di, "(e)"}, // (expr) {"^[(]{1}(?'expr'.+)[\\)]{1}$", syn_di, "(dp)"}, // (expr)
{"^\\[{1}(?'expr'.+)\\]{1}[,]{1}[(Y|y)]{1}$", syn_iyl, "[e],y"}, // [expr],y {"^\\[{1}(?'expr'.+)\\]{1}[,]{1}[(Y|y)]{1}$", syn_iyl, "[laddr],y"}, // [expr],y
{"^\\[(?'expr'.+)\\]$", syn_dil, "[e]"}, // [expr] {"^\\[(?'expr'.+)\\]$", syn_dil, "[e]"}, // [expr]
{"^(?'expr'.+)[,]{1}[(X|x)]{1}$", syn_absx, "e,x"}, // expr,x {"^(?'expr'.+)[,]{1}[(X|x)]{1}$", syn_absx, "addr,x"}, // expr,x
{"^(?'expr'.+)[,]{1}[(Y|y)]{1}$", syn_absy, "e,y"}, // expr,y {"^(?'expr'.+)[,]{1}[(Y|y)]{1}$", syn_absy, "addr,y"}, // expr,y
{"^(?'expr'.+)[,]{1}(?'expr2'.+)$", syn_bm, "block"}, // block move expr,expr1 {"^(?'expr'.+)[,]{1}(?'expr2'.+)$", syn_bm, "block"}, // block move expr,expr1
{"^(?'expr'.+)$", syn_abs, "absolute"}, // expr (MUST BE LAST) {"^(?'expr'.+)$", syn_abs, "absolute"}, // expr (MUST BE LAST)
{"", 0, ""} {"", 0, ""}
}; };
// one or more of any character except ][,(); // one or more of any character except ][,();
const std::string valExpression = "^([^\\]\\[,();]+)$"; //const std::string valExpression = "^([^\\]\\[,();]+)$";
const std::string valExpression = "^([^\\[,();]+)$";
// this one looks for ]variables // this one looks for ]variables
const std::string varExpression = "([]]{1}[:0-9A-Z_a-z]{1}[0-9A-Z_a-z]*)"; const std::string varExpression = "([]]{1}[:0-9A-Z_a-z]{1}[0-9A-Z_a-z]*)";
const std::string varMACExpression = "([]]{1}[:0-9]{1}[0-9]*)";
// opcode check. emitted opcodes are compared against this // opcode check. emitted opcodes are compared against this
// table, and if the XC status doesn't meet the requirements // table, and if the XC status doesn't meet the requirements
@ -1646,7 +1731,7 @@ void CLASS::initpass(void)
casesen = getBool("asm.casesen", true); casesen = getBool("asm.casesen", true);
listing = getBool("asm.lst", true); listing = getBool("asm.lst", true);
showmx = getBool("asm.showmx", false); showmx = getBool("asm.showmx", true);
merlinerrors = getBool("asm.merlinerrors", true); merlinerrors = getBool("asm.merlinerrors", true);
trackrep = getBool("asm.trackrep", false); trackrep = getBool("asm.trackrep", false);
@ -1675,15 +1760,16 @@ void CLASS::initpass(void)
PC.totalbytes = 0; PC.totalbytes = 0;
PC.orgsave = PC.origin; PC.orgsave = PC.origin;
s = getConfig("asm.cpu", "M65816"); s = getConfig("asm.cpu", "M6502");
s = Poco::trim(Poco::toUpper(s)); s = Poco::trim(Poco::toUpper(s));
cpumode = MODE_65816; cpumode = MODE_65816;
mx = 0x03;
if (s == "M65816") if (s == "M65816")
{ {
cpumode = MODE_65816; cpumode = MODE_65816;
mx = 0x00; mx = 0x03;
} }
else if (s == "M65C02") else if (s == "M65C02")
{ {
@ -1698,7 +1784,7 @@ void CLASS::initpass(void)
else else
{ {
printf("Unknown CPU type in .ini\n"); printf("Unknown CPU type in .ini\n");
mx = 0x00; mx = 0x03;
} }
mx = getInt("asm.startmx", mx);; mx = getInt("asm.startmx", mx);;
@ -1893,6 +1979,7 @@ int CLASS::getAddrMode(MerlinLine & line)
x = 0; x = 0;
try try
{ {
//printf("oper: |%s|\n",oper.c_str());
x = regex.split(oper, 0, groups, 0); x = regex.split(oper, 0, groups, 0);
} }
catch (...) catch (...)
@ -2007,7 +2094,7 @@ int CLASS::parseOperand(MerlinLine & line)
int CLASS::substituteVariables(MerlinLine & line, std::string &outop) int CLASS::substituteVariables(MerlinLine & line, std::string &outop)
{ {
int res = 0; int res = 0;
int x; int x,x1;
std::string::size_type offset, slen; std::string::size_type offset, slen;
std::string oper = line.operand; std::string oper = line.operand;
std::string s; std::string s;
@ -2018,10 +2105,12 @@ int CLASS::substituteVariables(MerlinLine & line, std::string &outop)
bool done = false; bool done = false;
operin = oper; operin = oper;
ct = 0; ct = 0;
bool mac_var;
restart: restart:
while (!done) while (!done)
{ {
mac_var=false;
slen = oper.length(); slen = oper.length();
if (slen > 0) if (slen > 0)
{ {
@ -2055,13 +2144,44 @@ restart:
sym = NULL; sym = NULL;
if (expand_macrostack.size() > 0) if (expand_macrostack.size() > 0)
{ {
mac_var=true;
sym = findVariable(s, expand_macro.variables); sym = findVariable(s, expand_macro.variables);
if (sym!=NULL)
{
RegularExpression varEx1(varMACExpression, 0, true);
Poco::RegularExpression::MatchVec mVec1;
try
{
varEx1.match(oper, 0, mVec1, 0);
x1 = (int)mVec1.size();
if (x1>0)
{
mac_var=true;
//printf("Found MACvar: |%s| |%s|\n",sym->name.c_str(),sym->var_text.c_str());
}
}
catch(...)
{
}
}
}
else
{
//mac_var=true;
} }
if (sym == NULL) if (sym == NULL)
{ {
sym = findVariable(s, variables); sym = findVariable(s, variables);
} }
if (sym != NULL)
if ((expand_macrostack.size() == 0) && (!mac_var))
{
//mac_var=true;
}
if ((sym != NULL) && (mac_var))
{ {
//printf("match |%s|\n",sym->var_text.c_str()); //printf("match |%s|\n",sym->var_text.c_str());

28
asm.h
View File

@ -15,6 +15,8 @@
#define SYNTAX_MPW 0x08 #define SYNTAX_MPW 0x08
#define SYNTAX_ORCA 0x10 #define SYNTAX_ORCA 0x10
#define SYNTAX_CC65 0x20 #define SYNTAX_CC65 0x20
#define SYNTAX_LISA 0x40
#define SYNTAX_QASM (0x80 | SYNTAX_MERLIN) #define SYNTAX_QASM (0x80 | SYNTAX_MERLIN)
#define OPTION_ALLOW_A_OPERAND 0x0100 #define OPTION_ALLOW_A_OPERAND 0x0100
#define OPTION_ALLOW_LOCAL 0x0200 #define OPTION_ALLOW_LOCAL 0x0200
@ -23,7 +25,7 @@
#define OPTION_NO_REPSEP 0x1000 #define OPTION_NO_REPSEP 0x1000
#define OPTION_CFG_REPSEP 0x2000 #define OPTION_CFG_REPSEP 0x2000
#define OPTION_M32_VARS 0x4000 #define OPTION_M32_VARS 0x4000
#define OPTION_M16_PLUS 0x8000
#define FLAG_FORCELONG 0x01 #define FLAG_FORCELONG 0x01
#define FLAG_FORCEABS 0x02 #define FLAG_FORCEABS 0x02
@ -201,6 +203,7 @@ public:
std::string printoperand; std::string printoperand;
std::string opcode; std::string opcode;
std::string opcodelower; std::string opcodelower;
std::string orig_operand;
std::string operand; std::string operand;
std::string operand_expr; std::string operand_expr;
std::string operand_expr2; std::string operand_expr2;
@ -254,6 +257,7 @@ protected:
public: public:
uint32_t errorct; uint32_t errorct;
std::string filename; std::string filename;
uint32_t format_flags;
TFileProcessor(); TFileProcessor();
virtual ~TFileProcessor(); virtual ~TFileProcessor();
@ -267,18 +271,18 @@ public:
virtual void setSyntax(uint32_t syn); virtual void setSyntax(uint32_t syn);
}; };
class TImageProcessor : public TFileProcessor
{
protected:
std::vector<MerlinLine> lines;
public: #define CONVERT_NONE 0x00
TImageProcessor(); #define CONVERT_LF 0x01
virtual ~TImageProcessor(); #define CONVERT_CRLF 0x02
virtual int doline(int lineno, std::string line); #define CONVERT_COMPRESS 0x04
virtual void process(void); #define CONVERT_HIGH 0x08
virtual void complete(void); #define CONVERT_MERLIN (CONVERT_HIGH|CONVERT_COMPRESS)
}; #define CONVERT_LINUX (CONVERT_LF)
#define CONVERT_WINDOWS (CONVERT_CRLF)
#define CONVERT_APW (CONVERT_NONE)
#define CONVERT_MPW (CONVERT_NONE)
#define CONVERT_TEST (CONVERT_COMPRESS|CONVERT_LF)
class TMerlinConverter : public TFileProcessor class TMerlinConverter : public TFileProcessor
{ {

View File

@ -1,3 +1,5 @@
#ifdef CIDERPRESS
#include "asm.h" #include "asm.h"
#include "eval.h" #include "eval.h"
#include "psuedo.h" #include "psuedo.h"
@ -7,6 +9,9 @@
#include <cider.h> #include <cider.h>
#include <DiskImg.h> #include <DiskImg.h>
#include <util.h>
#undef CLASS
#define CLASS CiderPress #define CLASS CiderPress
using namespace DiskImgLib; using namespace DiskImgLib;
@ -14,11 +19,13 @@ using DiskImgLib::DiskImg;
void dbgMessage(const char *file, int line, const char *msg) void dbgMessage(const char *file, int line, const char *msg)
{ {
if (isDebug()>0)
{
printf("DEBUG: %s\n",msg); printf("DEBUG: %s\n",msg);
}
} }
CLASS::CLASS() CLASS::CLASS() : TFileProcessor()
{ {
if (!Global::GetAppInitCalled()) if (!Global::GetAppInitCalled())
{ {
@ -27,6 +34,11 @@ CLASS::CLASS()
} }
} }
CLASS::~CLASS()
{
}
int CLASS::RunScript(string path) int CLASS::RunScript(string path)
{ {
int res=-1; int res=-1;
@ -56,7 +68,27 @@ int CLASS::CreateVolume(string OSName, string VolName, uint64_t size, CIDER_VOLF
); );
printf("create error: %d\n",err); printf("create error: %d\n",err);
if (err== kDIErrNone ) if (err== kDIErrNone )
{
interr=0; interr=0;
} }
}
return (interr); return (interr);
} }
int CLASS::doline(int lineno, std::string line)
{
printf("%05d: %s\n",lineno,line.c_str());
return(0);
}
void CLASS::process(void)
{
}
void CLASS::complete(void)
{
}
#undef CLASS
#endif

12
cider.h
View File

@ -1,3 +1,4 @@
#ifdef CIDERPRESS
#pragma once #pragma once
#include "asm.h" #include "asm.h"
@ -11,12 +12,19 @@
#define CLASS CiderPress #define CLASS CiderPress
enum CIDER_VOLFORMAT {CP_PRODOS,CP_HFS}; enum CIDER_VOLFORMAT {CP_PRODOS,CP_HFS};
class CLASS class CLASS : public TFileProcessor
{ {
public: protected:
std::vector<MerlinLine> lines;
public:
CLASS(); CLASS();
virtual ~CLASS();
int CreateVolume(string OSName, string VolName, uint64_t size, CIDER_VOLFORMAT format); int CreateVolume(string OSName, string VolName, uint64_t size, CIDER_VOLFORMAT format);
int RunScript(string path); int RunScript(string path);
virtual int doline(int lineno, std::string line);
virtual void process(void);
virtual void complete(void);
}; };
#undef CLASS #undef CLASS
#endif

View File

@ -607,7 +607,7 @@ int CLASS::evaluate(std::string & e, int64_t &res, uint8_t &_shiftmode)
std::string expr = Poco::trim(e); std::string expr = Poco::trim(e);
expr += " "; // add a space at end to make parsing easier expr += " "; // add a space at end to make parsing easier
if (isDebug() >= 4) if (isDebug() >= 1)
{ {
printf("eval: expression: |%s|\n", expr.c_str()); printf("eval: expression: |%s|\n", expr.c_str());
} }

View File

@ -22,7 +22,9 @@ for S in $SRC ; do
S1=${S1/.s/} S1=${S1/.s/}
cd ./testdata cd ./testdata
merlin32$X . $S 2>/dev/null >/dev/null #merlin32$X . $S 2>/dev/null >/dev/null
merlin32$X -V . $S
#merlin32 . $S 2>/dev/null #merlin32 . $S 2>/dev/null
R=?$ R=?$

View File

@ -12,6 +12,7 @@ void CLASS::setOpcode(MerlinLine &line, uint8_t op)
uint8_t m = opCodeCompatibility[op]; uint8_t m = opCodeCompatibility[op];
if ((m > 0) && (cpumode < MODE_65C02)) // if the instruction is non-zero, and we are in 6502 base mode, error if ((m > 0) && (cpumode < MODE_65C02)) // if the instruction is non-zero, and we are in 6502 base mode, error
{ {
//printf("incompatable: %02X %02X\n",op,m);
if (line.errorcode == 0) // don't replace other errors if (line.errorcode == 0) // don't replace other errors
{ {
line.setError(errIncompatibleOpcode); line.setError(errIncompatibleOpcode);
@ -706,7 +707,8 @@ int CLASS::doBase6502(MerlinLine & line, TSymbol & sym)
if (err) // not a 6502 address mode if (err) // not a 6502 address mode
{ {
if (cpumode >= MODE_65816) //if (cpumode >= MODE_65816)
if (cpumode >= MODE_65C02)
{ {
cc = 0x03; cc = 0x03;
err = false; err = false;
@ -950,6 +952,7 @@ void CLASS::insertOpcodes(void)
pushopcode("MVP", 0x01, 0, OPHANDLER(&CLASS::doMVN)); pushopcode("MVP", 0x01, 0, OPHANDLER(&CLASS::doMVN));
pushopcode("NOP", 0xEA, 0, OPHANDLER(&CLASS::doBYTE)); pushopcode("NOP", 0xEA, 0, OPHANDLER(&CLASS::doBYTE));
pushopcode("ORA", 0x00, OP_STD | OP_A, OPHANDLER(&CLASS::doBase6502)); pushopcode("ORA", 0x00, OP_STD | OP_A, OPHANDLER(&CLASS::doBase6502));
pushopcode("PEA", 0xF4, 2, OPHANDLER(&CLASS::doAddress)); pushopcode("PEA", 0xF4, 2, OPHANDLER(&CLASS::doAddress));
pushopcode("PEI", 0xD4, 1, OPHANDLER(&CLASS::doAddress)); pushopcode("PEI", 0xD4, 1, OPHANDLER(&CLASS::doAddress));
pushopcode("PER", 0x62, 2, OPHANDLER(&CLASS::doPER)); pushopcode("PER", 0x62, 2, OPHANDLER(&CLASS::doPER));

View File

@ -1,6 +1,7 @@
{ {
"version": "1.1", "version": "1.1",
"general": { "general": {
"color_output": true,
"prefix": [ "prefix": [
{ {
"0": "${PWD}" "0": "${PWD}"
@ -16,16 +17,27 @@
} }
] ]
}, },
"assembler": { "asm": {
"cpu_default": "6502", "syntax": "merlin16plus", //merlin8, merlin16, merlin16plus,merlin32
"syntax": "merlin", "cpu": "M6502",
"listmode": "on" "startmx": 3,
"listmode": "on",
"casesend": true,
"lst": false,
"showmx": true,
"allowduplicate": true,
"trackrep": false,
"merlinerrors": true,
"m32vars": false,
"allowA": true,
"allowLocal": true,
"allowColon": true,
"repsep": "force", //force,no,cfg
"linebytes": 4,
"line2bytes": 8
}, },
"linker": {}, "linker": {},
"format": { "format": {
"tabs": "12,18,30" "tabs": "12,18,30,48"
},
"diskimg": {
"script": "./disk_commands.txt"
} }
} }

View File

@ -944,6 +944,10 @@ int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
if (dci && (i == lastdelimidx)) if (dci && (i == lastdelimidx))
{ {
// SGQ BUG - Merlin16+ does it like Merlin32 and now does the last
// byte not the way merlin816 and earlier do it documented below.
// use OPTION_M16_PLUS when implemented.
//lr - Merlin only toggles the high bit of string chars, not hex values //lr - Merlin only toggles the high bit of string chars, not hex values
// 8D,'Hello',8D,'there',8D becomes 8D 48 65 6C 6C 6F 8D 74 68 65 72 E5 // 8D,'Hello',8D,'there',8D becomes 8D 48 65 6C 6C 6F 8D 74 68 65 72 E5
// //

View File

@ -20,7 +20,7 @@ programOption PAL::appOptions[] =
{ "debug", "d", "enable debug info (repeat for more verbosity)", "", false, true}, { "debug", "d", "enable debug info (repeat for more verbosity)", "", false, true},
#endif #endif
//{ "config", "f", "load configuration data from a <file>", "<file>", false, false}, //{ "config", "f", "load configuration data from a <file>", "<file>", false, false},
{ "exec", "x", "execute a command [asm, link, reformat, script] default=asm", "<command>", false, false}, { "exec", "x", "execute a command [asm, link, format, script] default=asm", "<command>", false, false},
{ "objfile", "o", "write output to file", "<file>", false, false}, { "objfile", "o", "write output to file", "<file>", false, false},
{ "syntax", "s", "enforce syntax of other assembler [qasm, merlin, merlin32, ORCA, APW, MPW, CC65]", "<syntax>", false, false}, { "syntax", "s", "enforce syntax of other assembler [qasm, merlin, merlin32, ORCA, APW, MPW, CC65]", "<syntax>", false, false},
@ -101,7 +101,7 @@ int CLASS::runCommandLineApp(void)
syn=Poco::toUpper(syn); syn=Poco::toUpper(syn);
syn=Poco::trim(syn); syn=Poco::trim(syn);
syntax=SYNTAX_QASM; syntax=SYNTAX_QASM;
if ((syn=="MERLIN") || (syn=="MERLIN16") || (syn=="MERLIN8") || (syn=="MERLIN16+")) if ((syn=="MERLIN") || (syn=="MERLIN16") || (syn=="MERLIN8") || (syn=="MERLIN16PLUS"))
{ {
syntax=SYNTAX_MERLIN; syntax=SYNTAX_MERLIN;
} }
@ -130,7 +130,7 @@ int CLASS::runCommandLineApp(void)
syntax=SYNTAX_CC65; syntax=SYNTAX_CC65;
} }
printf("SYNTAX: |%s|\n",syn.c_str()); //printf("SYNTAX: |%s|\n",syn.c_str());
try try
{ {
@ -148,6 +148,7 @@ int CLASS::runCommandLineApp(void)
for (ArgVec::const_iterator it = commandargs.begin(); it != commandargs.end(); ++it) for (ArgVec::const_iterator it = commandargs.begin(); it != commandargs.end(); ++it)
{ {
int32_t format_flags=CONVERT_LINUX;
Poco::File fn(*it); Poco::File fn(*it);
int x; int x;
std::string p = fn.path(); std::string p = fn.path();
@ -158,10 +159,50 @@ int CLASS::runCommandLineApp(void)
std::string cmd = Poco::toUpper(getConfig("option.exec", "asm")); std::string cmd = Poco::toUpper(getConfig("option.exec", "asm"));
//printf("DEBUG=%d\n",isDebug()); Poco::StringTokenizer toks(cmd,"-");
if (toks.count()>1)
{
if (toks[0]=="FORMAT")
{
if (toks[1]=="LINUX")
{
format_flags=CONVERT_LINUX;
}
else if (toks[1]=="WINDOWS")
{
format_flags=CONVERT_WINDOWS;
}
else if (toks[1]=="MERLIN")
{
format_flags=CONVERT_MERLIN;
}
else if (toks[1]=="APW")
{
format_flags=CONVERT_APW;
}
else if (toks[1]=="MPW")
{
format_flags=CONVERT_MPW;
}
else if (toks[1]=="MAC")
{
format_flags=CONVERT_LINUX;
}
else if (toks[1]=="CC65")
{
format_flags=CONVERT_LINUX;
}
else if (toks[1]=="COMPRESS")
{
format_flags=CONVERT_TEST;
}
cmd=toks[0];
}
}
if (cmd.length() > 0) if (cmd.length() > 0)
{ {
if (cmd == "REFORMAT") if (cmd == "FORMAT")
{ {
res = 0; res = 0;
t = new TMerlinConverter(); t = new TMerlinConverter();
@ -171,6 +212,7 @@ int CLASS::runCommandLineApp(void)
{ {
t->init(); t->init();
t->setSyntax(syntax); t->setSyntax(syntax);
t->format_flags=format_flags;
std::string f = path.toString(); std::string f = path.toString();
t->filename = f; t->filename = f;
@ -233,7 +275,7 @@ int CLASS::runCommandLineApp(void)
else if (cmd == "SCRIPT") else if (cmd == "SCRIPT")
{ {
res = 0; res = 0;
t = new TImageProcessor(); t = new CiderPress();
if (t!=NULL) if (t!=NULL)
{ {
try try

View File

@ -2,6 +2,10 @@
; See the LICENSE.txt file for distribution terms (Apache 2.0). ; See the LICENSE.txt file for distribution terms (Apache 2.0).
; ;
; Assembler: Merlin 32 ; Assembler: Merlin 32
xc off
xc
xc
mx %00
ZP EQU $FF ZP EQU $FF
ABS EQU $FEFF ABS EQU $FEFF
LONG EQU $FDFEFF LONG EQU $FDFEFF

View File

@ -3,6 +3,10 @@
; ;
; Assembler: Merlin 32 ; Assembler: Merlin 32
xc off
xc
xc
mx %00
ZP EQU $00 ZP EQU $00
ABS EQU $0000 ABS EQU $0000
LONG EQU $000000 LONG EQU $000000

View File

@ -1,11 +1,15 @@
; Copyright 2018 faddenSoft. All Rights Reserved. ; Copyright 2018 faddenSoft. All Rights Reserved.
; See the LICENSE.txt file for distribution terms (Apache 2.0). ; See the LICENSE.txt file for distribution terms (Apache 2.0).
; ;
; Assembler: Merlin 32 ; Assembler: Merlin 32
xc off
xc
xc
mx %11
org $1000 org $1000
; 65816 mode with short regs ; 65816 mode with short regs
clc clc
xce xce
sep #$30 sep #$30
@ -18,28 +22,28 @@
jsr test5 jsr test5
rts rts
; TEST #1: simple example ; TEST #1: simple example
test1 lda #$00 test1 lda #$00
dfb $2c ;BIT abs dfb $2c ;BIT abs
:inner lda #$01 :inner lda #$01
beq :inner beq :inner
rts rts
; TEST #2: embedded with break path ; TEST #2: embedded with break path
; ;
; Example inspired by incorrect analysis... ; Example inspired by incorrect analysis...
; ;
; The code analyzer sees: ; The code analyzer sees:
; beq {+03} ;jumps to the $8f ; beq {+03} ;jumps to the $8f
; lda #$00 ; lda #$00
; brk $8f ; brk $8f
; and stops, then pursues the branch. If we try to walk from top ; and stops, then pursues the branch. If we try to walk from top
; to bottom, skipping forward by the full length of an instruction, ; to bottom, skipping forward by the full length of an instruction,
; we'll appear to find ourselves in the middle of an embedded ; we'll appear to find ourselves in the middle of an embedded
; instruction. ; instruction.
; ;
; This is different from the typical embedded instruction, ; This is different from the typical embedded instruction,
; where the inner is contained entirely within the outer. ; where the inner is contained entirely within the outer.
test2 sep #$30 ;short regs test2 sep #$30 ;short regs
mx %00 ;pretend they're long mx %00 ;pretend they're long
@ -49,15 +53,15 @@ test2 sep #$30 ;short regs
:store stal $012345 :store stal $012345
rts rts
; TEST #3: embedded with non-instruction byte ; TEST #3: embedded with non-instruction byte
; ;
; The code analyzer sees two paths, involving the three bytes. ; The code analyzer sees two paths, involving the three bytes.
; The first is the three-byte JSR, the second is the one-byte ; The first is the three-byte JSR, the second is the one-byte
; RTS. The third NOP byte is never "executed" by the analyzer, ; RTS. The third NOP byte is never "executed" by the analyzer,
; but because of the way we display embedded instructions it ; but because of the way we display embedded instructions it
; gets put on its own line. Since it's not an instruction start ; gets put on its own line. Since it's not an instruction start
; or a data item, things get confused. (This is referred to as ; or a data item, things get confused. (This is referred to as
; an "embedded orphan" in the code.) ; an "embedded orphan" in the code.)
test3 dfb $20 ;JSR test3 dfb $20 ;JSR
:mid dfb $60 ;RTS :mid dfb $60 ;RTS
@ -65,10 +69,10 @@ test3 dfb $20 ;JSR
bra :mid bra :mid
; TEST #4: overlapping chain ; TEST #4: overlapping chain
; ;
; Each BIT instruction is three bytes, and each byte is a branch target, ; Each BIT instruction is three bytes, and each byte is a branch target,
; so we get a string of embedded instructions. ; so we get a string of embedded instructions.
test4 test4
:bits hex 2c2c2c2c2c2c2c2c2ceaea :bits hex 2c2c2c2c2c2c2c2c2ceaea
asl asl
@ -93,9 +97,9 @@ test4
bcc :bits+9 bcc :bits+9
rts rts
; TEST #5: another overlap ; TEST #5: another overlap
; ;
; Trying to be a little different. ; Trying to be a little different.
test5 dfb $2c test5 dfb $2c
:mid1 nop :mid1 nop
hex ad hex ad
@ -105,6 +109,6 @@ test5 dfb $2c
asl asl
bcc :mid2 bcc :mid2
; TEST #6: "embedded" off the end of the file ; TEST #6: "embedded" off the end of the file
dfb $af ;ldal dfb $af ;ldal

View File

@ -2,7 +2,9 @@
; See the LICENSE.txt file for distribution terms (Apache 2.0). ; See the LICENSE.txt file for distribution terms (Apache 2.0).
; ;
; Assembler: Merlin 32 ; Assembler: Merlin 32
xc off
xc
xc
org $1000 org $1000
clc clc
xce xce

View File

@ -1,8 +1,8 @@
; Copyright 2018 faddenSoft. All Rights Reserved. ; Copyright 2018 faddenSoft. All Rights Reserved.
; See the LICENSE.txt file for distribution terms (Apache 2.0). ; See the LICENSE.txt file for distribution terms (Apache 2.0).
; ;
; Assembler: Merlin 32 ; Assembler: Merlin 32
xc off
ZP EQU $FF ZP EQU $FF
ABS EQU $FEFF ABS EQU $FEFF

View File

@ -2,7 +2,9 @@
; See the LICENSE.txt file for distribution terms (Apache 2.0). ; See the LICENSE.txt file for distribution terms (Apache 2.0).
; ;
; Assembler: Merlin 32 ; Assembler: Merlin 32
xc off
xc
;xc
ZP EQU $FF ZP EQU $FF
ABS EQU $FEFF ABS EQU $FEFF

View File

@ -2,6 +2,8 @@
; See the LICENSE.txt file for distribution terms (Apache 2.0). ; See the LICENSE.txt file for distribution terms (Apache 2.0).
; ;
; Assembler: Merlin 32 ; Assembler: Merlin 32
xc off
xc
ZP EQU $00 ZP EQU $00
ABS EQU $0000 ABS EQU $0000

View File

@ -12,3 +12,4 @@ xx mac
xx "hello" xx "hello"
xx 'abc',00 xx 'abc',00
xx ff xx ff

View File

@ -1,7 +1,7 @@
; Copyright 2018 faddenSoft. All Rights Reserved. ; Copyright 2018 faddenSoft. All Rights Reserved.
; See the LICENSE.txt file for distribution terms (Apache 2.0). ; See the LICENSE.txt file for distribution terms (Apache 2.0).
; ;
; Assembler: Merlin 32 ; Assembler: Merlin 32
ORG $1000 ORG $1000
@ -84,7 +84,7 @@ PostH32 DFB $33,ZP
AND: ABS,Y AND: ABS,Y
DFB $3A DFB $3A
DFB $3B,#<ABS,#>ABS DFB $3B,#<ABS,#>ABS
BIT: ABS,X ;BIT: ABS,X // not available on standard 6502 (but is on 65C02)
AND: ABS,X AND: ABS,X
ROL: ABS,X ROL: ABS,X
DFB $3F,#<ABS,#>ABS DFB $3F,#<ABS,#>ABS

View File

@ -5,6 +5,7 @@
ORG $1000 ORG $1000
mx %00
SEC SEC
XCE XCE
JSR L101F JSR L101F

View File

@ -1,6 +1,5 @@
; Copyright 2018 faddenSoft. All Rights Reserved. ; Copyright 2018 faddenSoft. All Rights Reserved.
; See the LICENSE.txt file for distribution terms (Apache 2.0). ; See the LICENSE.txt file for distribution terms (Apache 2.0).
;
; Assembler: Merlin 32 ; Assembler: Merlin 32
ORG $1000 ORG $1000

View File

@ -9,3 +9,4 @@ bool isMerlin816(void)
{ {
return(true); return(true);
} }