working on parameters and options

This commit is contained in:
Shawn Quick 2023-02-06 22:27:19 -08:00
parent 6e9eb6cfcc
commit 107598bb02
19 changed files with 740 additions and 343 deletions

2
.gitignore vendored
View File

@ -5,8 +5,6 @@
*.a
*.so
Finder.Data
test.s
disk_commands.txt
.vscode/browse*
.vscode/book*

1
.vscode/launch.json vendored
View File

@ -8,6 +8,7 @@
// Resolved by CMake Tools:
"program": "${command:cmake.launchTargetPath}",
"args": [
" -d -d -d",
"${workspaceFolder}/test.s"
],
"stopAtEntry": false,

View File

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.0)
set(CIDER "1")
#set(CIDER "1")
#set (CMAKE_C_COMPILER /usr/bin/clang)
#set (CMAKE_CXX_COMPILER /usr/bin/clang++)
@ -45,6 +45,8 @@ set(SOURCE
${PROJECT_ROOT}/psuedo.cpp
${PROJECT_ROOT}/qoptions.cpp
${PROJECT_ROOT}/cider.cpp
${PROJECT_ROOT}/util.cpp
)
#find_package(OpenSSL REQUIRED)
@ -67,7 +69,6 @@ include_directories(BEFORE
set (CIDERLIBS "" )
if ( ${CIDER} )
add_definitions(-DCIDERPRESS)
add_definitions(-DAPPVERSION=${APPVERSION})
include_directories(AFTER ${PROJECT_ROOT}/diskimg)
add_subdirectory(${PROJECT_ROOT}/libhfs)
@ -81,6 +82,8 @@ find_library(NUFX_LIB libnufx_static.a ${PROJECT_ROOT}/build )
set (CIDERLIBS diskimg_static hfs_static nufx_static ${ZLIB_LIBRARIES})
endif ( ${CIDER} )
add_definitions(-DAPPVERSION=${APPVERSION})
add_subdirectory(${PROJECT_ROOT}/libpal)
add_executable( ${PROJECT_NAME} ${SOURCE})

View File

@ -30,6 +30,12 @@ debug:
-mkdir -p ./build
-cd ./build && cmake -DCMAKE_BUILD_TYPE=DEBUG .. && $(MAKE) $S
cider:
-rm -rf ./build
-mkdir -p ./build
-cd ./build && cmake -DCIDER=1 -DCMAKE_BUILD_TYPE=DEBUG .. && $(MAKE) $S
distclean: clean
-rm -rf ./qasmout
-rm -rf ./m32out
@ -38,7 +44,6 @@ distclean: clean
clean:
-rm -rf ./build *.2mg test.bin
depend:
-cd ./build && $(MAKE) depend

153
asm.cpp
View File

@ -11,12 +11,12 @@
#define CLASS MerlinLine
CLASS::CLASS()
CLASS::CLASS(ConfigOptions &opt) //: options(opt)
{
clear();
}
CLASS::CLASS(std::string line)
CLASS::CLASS(std::string line, ConfigOptions &opt) //: options(opt)
{
clear();
set(line);
@ -28,13 +28,11 @@ void CLASS::setError(uint32_t ecode)
errorcode = ecode;
}
void CLASS::print(uint32_t lineno)
{
uint32_t l, i, savpcol, pcol;
bool commentprinted = false;
static bool checked = false;
static bool nc1 = false;
bool nc = false;
uint8_t commentcol = tabs[2];
uint32_t b = 4; // how many bytes show on the first line
@ -66,27 +64,17 @@ void CLASS::print(uint32_t lineno)
flags &= (~FLAG_NOLINEPRINT);
}
if (flags & FLAG_NOLINEPRINT)
bool np=(flags & FLAG_NOLINEPRINT);
if (options->isQuiet())
np=true;
if (options->isList())
np=false;
if (np)
{
return;
}
if (!checked)
{
nc1 = getBool("option.nocolor", false);
checked = true;
}
else
{
nc = nc1;
}
//if ((!isatty(STDOUT_FILENO)) || (merlinerrors))
if ((!isatty(STDOUT_FILENO)) || (0))
{
nc = true;
}
if (!nc)
if (options->useColor())
{
if (errorcode > 0)
{
@ -156,7 +144,9 @@ void CLASS::print(uint32_t lineno)
if (isDebug() > 1)
{
pcol += printf("%02X ", addressmode & 0xFF);
//pcol += printf("%02X ", addressmode & 0xFF);
pcol += printf(" %s ", addrtext.c_str());
}
savpcol = pcol; // this is how many bytes are in the side margin
@ -250,7 +240,7 @@ void CLASS::print(uint32_t lineno)
}
//printf("\n");
if ((!nc) && (errorcode > 0))
if ((options->useColor()) && (errorcode > 0))
{
SetColor(CL_NORMAL | BG_NORMAL);
}
@ -522,7 +512,8 @@ void CLASS::set(std::string line)
if (x > 1)
{
// M32 syntax allows a colon after lable, and it is not part of the lable
if ((syntax & SYNTAX_MERLIN32) == SYNTAX_MERLIN32)
//if ((syntax & SYNTAX_MERLIN32) == SYNTAX_MERLIN32)
if (options->isMerlin32())
{
while ((x > 1) && (lable[x - 1] == ':'))
{
@ -539,11 +530,11 @@ void CLASS::set(std::string line)
#undef CLASS
#define CLASS TFileProcessor
CLASS::CLASS()
CLASS::CLASS(ConfigOptions &opt) : options(opt)
{
int x;
errorct = 0;
syntax=SYNTAX_QASM;
//syntax=SYNTAX_QASM;
win_columns = -1;
win_rows = -1;
@ -562,9 +553,9 @@ CLASS::~CLASS()
{
}
void CLASS::setSyntax(uint32_t syn)
void CLASS::setProduct(string product)
{
syntax=syn;
options.setProduct(product);
}
void CLASS::errorOut(uint16_t code)
@ -581,7 +572,7 @@ void CLASS::init(void)
starttime = GetTickCount();
initialdir = Poco::Path::current();
filecount = 0;
syntax = SYNTAX_QASM;
//syntax = SYNTAX_QASM;
//std::string tabstr = getConfig("reformat.tabs", "8,16,32");
std::string tabstr = getConfig("reformat.tabs", "12,24,40,70");
@ -620,7 +611,10 @@ void CLASS::complete(void)
//cout << "Processing Time: " << n - starttime << "ms" << endl;
uint64_t x = n - starttime;
uint32_t x1 = x & 0xFFFFFFFF;
printf("Elapsed time: %u ms\n", x1);
if ((!getBool("option.quiet",false)) && (isDebug()>0))
{
printf("Elapsed time: %u ms\n", x1);
}
}
}
@ -926,11 +920,13 @@ int CLASS::processfile(std::string p, std::string &newfilename)
return (res);
}
#if 1
#undef CLASS
#define CLASS TMerlinConverter
CLASS::CLASS() : TFileProcessor()
CLASS::CLASS(ConfigOptions &opt) : TFileProcessor(opt)
{
format_flags=CONVERT_TEST;
//options=new ConfigOptions();
}
CLASS::~CLASS()
{
@ -946,7 +942,7 @@ int CLASS::doline(int lineno, std::string line)
{
UNUSED(lineno);
MerlinLine l(line);
MerlinLine l(line, options);
lines.push_back(l);
return 0;
}
@ -969,7 +965,8 @@ void CLASS::process(void)
for (uint32_t lineno = 0; lineno < ct; lineno++)
{
MerlinLine &line = lines.at(lineno);
MerlinLine line = lines.at(lineno);
//printf("line: |%s|\n",line.wholetext.c_str());
orval=0x00;
if (flags&CONVERT_HIGH)
{
@ -1001,7 +998,14 @@ void CLASS::process(void)
t = tabs[2];
if (flags&CONVERT_COMPRESS)
{
len += sprintf(&buff[len+tlen]," ");
if (flags&CONVERT_TABS)
{
len += sprintf(&buff[len+tlen],"\t\t\t\t");
}
else
{
len += sprintf(&buff[len+tlen]," ");
}
}
else
{
@ -1022,7 +1026,14 @@ void CLASS::process(void)
{
if (flags&CONVERT_COMPRESS)
{
len += sprintf(&buff[len+tlen]," ");
if (flags&CONVERT_TABS)
{
len += sprintf(&buff[len+tlen],"\t\t\t");
}
else
{
len += sprintf(&buff[len+tlen]," ");
}
}
else
{
@ -1039,7 +1050,14 @@ void CLASS::process(void)
{
if (flags&CONVERT_COMPRESS)
{
len += sprintf(&buff[len+tlen]," ");
if (flags&CONVERT_TABS)
{
len += sprintf(&buff[len+tlen],"\t\t\t");
}
else
{
len += sprintf(&buff[len+tlen]," ");
}
}
else
{
@ -1056,7 +1074,14 @@ void CLASS::process(void)
{
if (flags&CONVERT_COMPRESS)
{
len += sprintf(&buff[len+tlen]," ");
if (flags&CONVERT_TABS)
{
len += sprintf(&buff[len+tlen],"\t\t\t");
}
else
{
len += sprintf(&buff[len+tlen]," ");
}
}
else
{
@ -1125,8 +1150,11 @@ void CLASS::process(void)
buff[idx++]=c|orval;
}
}
buff[idx]=0;
fprintf(stdout,"%s",buff);
#if 0
FILE *f=NULL;
//string outfile=
f=fopen("./aout.s","w+");
if (f!=NULL)
{
@ -1138,18 +1166,20 @@ void CLASS::process(void)
{
printf("file error\n");
}
#endif
}
}
void CLASS::complete(void)
{
}
#endif
#undef CLASS
#define CLASS T65816Asm
CLASS::CLASS() : TFileProcessor()
CLASS::CLASS(ConfigOptions &opt) : TFileProcessor(opt)
{
lines.clear();
psuedoops = new TPsuedoOp();
@ -1588,7 +1618,8 @@ int CLASS::callOpCode(std::string op, MerlinLine &line)
//line.expr_value = (line.expr_value >> 16) & 0xFFFF;
break;
case '|':
if (syntax == SYNTAX_MERLIN)
//if (syntax == SYNTAX_MERLIN)
if (options.isMerlin())
{
line.setError(errBadLabel);
line.expr_value = 0;
@ -1790,6 +1821,7 @@ void CLASS::initpass(void)
savepath = getConfig("option.objfile", "");
//printf("savepath: %s\n",savepath.c_str());
lastcarry = false;
relocatable = false;
@ -1847,7 +1879,10 @@ void CLASS::complete(void)
std::string currentdir = Poco::Path::current();
savepath = processFilename(savepath, currentdir, 0);
printf("saving to file: %s\n", savepath.c_str());
if (!options.isQuiet())
{
printf("saving to file: %s\n", savepath.c_str());
}
std::ofstream f(savepath);
@ -1878,8 +1913,10 @@ void CLASS::complete(void)
printf("\nErrors in assembly. Output not SAVED.\n\n");
}
}
printf("\n\nEnd qASM assembly, %d bytes, %u errors, %lu lines, %lu symbols.\n", PC.totalbytes, errorct, lines.size(), symbols.size());
if ((!options.isQuiet()) || (options.isList()))
{
printf("\n\nEnd qASM assembly, %d bytes, %u errors, %lu lines, %lu symbols.\n", PC.totalbytes, errorct, lines.size(), symbols.size());
}
TFileProcessor::complete();
@ -1909,10 +1946,17 @@ int CLASS::evaluate(MerlinLine &line, std::string expr, int64_t &value)
{
if (isDebug() > 2)
{
int c = SetColor(CL_RED);
int c;
if (options.useColor())
{
c = SetColor(CL_RED);
}
uint32_t rr = result & 0xFFFFFFFF;
printf("eval Error=%d %08X |%s|\n", res, rr, eval.badsymbol.c_str());
SetColor(c);
if (options.useColor())
{
SetColor(c);
}
}
}
if (res == 0)
@ -2015,7 +2059,8 @@ int CLASS::getAddrMode(MerlinLine & line)
// symbol is defined later, we will generate different
// bytes on the next pass
if ((line.syntax & SYNTAX_MERLIN32) == SYNTAX_MERLIN32)
if (options.isMerlin32())
//if ((line.syntax & SYNTAX_MERLIN32) == SYNTAX_MERLIN32)
{
if (Poco::toUpper(oper) == "A") // check the whole operand, not just the expression
{
@ -2281,7 +2326,7 @@ void CLASS::process(void)
int x;;
char c;
char buff[256];
MerlinLine errLine;
MerlinLine errLine(options);
std::string op, realop, operand, ls;
pass = 0;
@ -2351,7 +2396,7 @@ void CLASS::process(void)
line.linemx = mx;
line.bytect = 0;
line.showmx = showmx;
line.syntax = syntax;
//line.syntax = syntax;
line.merlinerrors = merlinerrors;
if ((line.lable != "") && (op != "mac"))
@ -2476,7 +2521,7 @@ void CLASS::process(void)
for (uint32_t lc = expand_macro.start; lc < expand_macro.end; lc++)
{
//printf("pushing %s\n", lines[lc].wholetext.c_str());
MerlinLine nl(lines[lc].wholetext); // create a new clean line (without errors,data)
MerlinLine nl(lines[lc].wholetext,options); // create a new clean line (without errors,data)
expand_macro.lines.push_back(nl);
}
expand_macro.running = true;
@ -2603,7 +2648,7 @@ int CLASS::doline(int lineno, std::string line)
UNUSED(lineno);
MerlinLine l(line);
MerlinLine l(line,options);
op = Poco::toLower(l.opcode);
if (op == "merlin")
@ -2614,7 +2659,7 @@ int CLASS::doline(int lineno, std::string line)
{
syntax = SYNTAX_ORCA;
}
l.syntax = syntax;
//l.syntax = syntax;
lines.push_back(l);
if ((op == "use") || (op == "put"))
@ -2653,7 +2698,7 @@ int CLASS::doline(int lineno, std::string line)
#define CLASS T65816Link
CLASS::CLASS() : TFileProcessor()
CLASS::CLASS(ConfigOptions &opt) : TFileProcessor(opt)
{
}

43
asm.h
View File

@ -5,27 +5,6 @@
//
#define OPHANDLER(ACB) std::bind(ACB, this, std::placeholders::_1, std::placeholders::_2)
#define MODE_6502 0
#define MODE_65C02 1
#define MODE_65816 2
#define SYNTAX_MERLIN 0x01
#define SYNTAX_MERLIN32 0x02
#define SYNTAX_APW 0x04
#define SYNTAX_MPW 0x08
#define SYNTAX_ORCA 0x10
#define SYNTAX_CC65 0x20
#define SYNTAX_LISA 0x40
#define SYNTAX_QASM (0x80 | SYNTAX_MERLIN)
#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 OPTION_M16_PLUS 0x8000
#define FLAG_FORCELONG 0x01
#define FLAG_FORCEABS 0x02
@ -196,7 +175,8 @@ class MerlinLine
{
public:
uint32_t syntax;
//uint32_t syntax;
ConfigOptions *options;
std::string wholetext;
std::string lable;
std::string printlable;
@ -233,8 +213,8 @@ public:
std::vector<uint8_t> outbytes;
public:
MerlinLine();
MerlinLine(std::string line);
MerlinLine(ConfigOptions &opt);
MerlinLine(std::string line, ConfigOptions &opt);
void clear();
void set(std::string line);
void print(uint32_t lineno);
@ -255,11 +235,12 @@ protected:
uint32_t filecount; // how many files have been read in (because of included files from source
public:
ConfigOptions &options;
uint32_t errorct;
std::string filename;
uint32_t format_flags;
TFileProcessor();
TFileProcessor(ConfigOptions &opt);
virtual ~TFileProcessor();
virtual std::string processFilename(std::string p, std::string currentdir, int level);
virtual int processfile(std::string p, std::string &newfilename);
@ -268,7 +249,7 @@ public:
virtual void process(void);
virtual void complete(void);
virtual void errorOut(uint16_t code);
virtual void setSyntax(uint32_t syn);
virtual void setProduct(string product);
};
@ -277,6 +258,7 @@ public:
#define CONVERT_CRLF 0x02
#define CONVERT_COMPRESS 0x04
#define CONVERT_HIGH 0x08
#define CONVERT_TABS 0x10
#define CONVERT_MERLIN (CONVERT_HIGH|CONVERT_COMPRESS)
#define CONVERT_LINUX (CONVERT_LF)
#define CONVERT_WINDOWS (CONVERT_CRLF)
@ -284,19 +266,22 @@ public:
#define CONVERT_MPW (CONVERT_NONE)
#define CONVERT_TEST (CONVERT_COMPRESS|CONVERT_LF)
#if 1
class TMerlinConverter : public TFileProcessor
{
protected:
std::vector<MerlinLine> lines;
public:
TMerlinConverter();
TMerlinConverter(ConfigOptions &opt);
virtual ~TMerlinConverter();
virtual void init(void);
virtual int doline(int lineno, std::string line);
virtual void process(void);
virtual void complete(void);
};
#endif
class TLUPstruct
{
@ -466,7 +451,7 @@ public:
uint16_t pass;
T65816Asm();
T65816Asm(ConfigOptions &opt);
virtual ~T65816Asm();
virtual void init(void);
@ -527,7 +512,7 @@ public:
class T65816Link : public TFileProcessor
{
public:
T65816Link();
T65816Link(ConfigOptions &opt);
virtual ~T65816Link();
virtual void init(void);
virtual int doline(int lineno, std::string line);

View File

@ -17,7 +17,7 @@ class CLASS : public TFileProcessor
protected:
std::vector<MerlinLine> lines;
public:
CLASS();
CLASS(ConfigOptions &opt);
virtual ~CLASS();
int CreateVolume(string OSName, string VolName, uint64_t size, CIDER_VOLFORMAT format);
int RunScript(string path);

View File

@ -15,7 +15,7 @@
#define NO_TTY_SETUP
// help text
#define HELP_USAGE "<options> <list of files>"
#define HELP_USAGE "<options> file1 <file2 file3 ...>"
#define HELP_PURPOSE "\nMerlin 8/16(+)/32 Compatible 65816 Development Tool"

View File

@ -202,7 +202,8 @@ int CLASS::doMVN(MerlinLine &line, TSymbol &sym)
setOpcode(line, op);
// these bytes are the two bank registers
if (((line.syntax & SYNTAX_MERLIN32) == SYNTAX_MERLIN32) && (v<256))
if (options.isMerlin32() && (v<256))
//if (((line.syntax & SYNTAX_MERLIN32) == SYNTAX_MERLIN32) && (v<256))
{
// merlin32 uses the low byte of the two operands
line.outbytes.push_back((v) & 0xFF);

View File

@ -1,7 +1,7 @@
{
"version": "1.1",
"general": {
"color_output": true,
"nocolor": false,
"prefix": [
{
"0": "${PWD}"
@ -18,12 +18,12 @@
]
},
"asm": {
"syntax": "merlin16plus", //merlin8, merlin16, merlin16plus,merlin32
"syntax": "merlin16plus",
"cpu": "M6502",
"startmx": 3,
"listmode": "on",
"casesend": true,
"lst": false,
"casesen": true,
"start_lst": false,
"showmx": true,
"allowduplicate": true,
"trackrep": false,
@ -32,7 +32,7 @@
"allowA": true,
"allowLocal": true,
"allowColon": true,
"repsep": "force", //force,no,cfg
"repsep": "force",
"linebytes": 4,
"line2bytes": 8
},

View File

@ -179,31 +179,32 @@ int CLASS::doMAC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
}
else // it is EOM or <<<
{
while (a.macrostack.size() > 0)
if (a.macrostack.size()>0)
{
a.currentmacro.end = line.lineno - 1;
a.currentmacro.len = 0;
if (a.currentmacro.end >= a.currentmacro.start)
while (a.macrostack.size() > 0)
{
a.currentmacro.len = a.currentmacro.end - a.currentmacro.start;
//printf("macro len=%d\n",a.currentmacro.len);
a.currentmacro.end = line.lineno - 1;
a.currentmacro.len = 0;
if (a.currentmacro.end >= a.currentmacro.start)
{
a.currentmacro.len = a.currentmacro.end - a.currentmacro.start;
//printf("macro len=%d\n",a.currentmacro.len);
}
a.currentmacro.running = false;
std::pair<std::string, TMacro> p(a.currentmacro.name, a.currentmacro);
//printf("macro insert %s\n",a.currentmacro.name.c_str());
a.macros.insert(p);
a.currentmacro = a.macrostack.top();
a.macrostack.pop();
}
a.currentmacro.running = false;
std::pair<std::string, TMacro> p(a.currentmacro.name, a.currentmacro);
//printf("macro insert %s\n",a.currentmacro.name.c_str());
a.macros.insert(p);
a.currentmacro = a.macrostack.top();
a.macrostack.pop();
}
#if 0
else
{
err = errUnexpectedOp;
goto out;
}
#endif
}
out:
if (err)
@ -351,27 +352,27 @@ int CLASS::doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
const char *ptr = (const char *)op.c_str();
switch (strhash(ptr) )
{
case strhash((const char *)"DA"):
case strhash((const char *)"DW"):
wordsize = 2;
break;
case strhash((const char *)"DDB"):
wordsize = 2;
endian = 1;
break;
case strhash((const char *)"DFB"):
case strhash((const char *)"DB"):
wordsize = 1;
break;
case strhash((const char *)"ADR"):
wordsize = 3;
break;
case strhash((const char *)"ADRL"):
wordsize = 4;
break;
default:
wordsize = 0;
break;
case strhash((const char *)"DA"):
case strhash((const char *)"DW"):
wordsize = 2;
break;
case strhash((const char *)"DDB"):
wordsize = 2;
endian = 1;
break;
case strhash((const char *)"DFB"):
case strhash((const char *)"DB"):
wordsize = 1;
break;
case strhash((const char *)"ADR"):
wordsize = 3;
break;
case strhash((const char *)"ADRL"):
wordsize = 4;
break;
default:
wordsize = 0;
break;
}
for (auto itr = tok.begin(); itr != tok.end(); ++itr)
@ -666,12 +667,12 @@ int CLASS::doHEX(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
// Got a good 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;
case 0:
b = (hv << 4);
break;
case 1:
b |= hv;
break;
}
ct = (ct + 1) & 0x01;
if (!ct)
@ -695,7 +696,8 @@ out:
return bytect;
}
static int usr_hash(std::string os) {
static int usr_hash(std::string os)
{
int hash = 0;
os.resize(4, ' ');
@ -704,7 +706,10 @@ static int usr_hash(std::string os) {
hash = (os[0] & 0x1f) << 11;
hash |= (os[1] & 0x1f) << 6;
hash |= (os[2] & 0x1f) << 1;
if (os[3] == 'L') hash |= 0x01;
if (os[3] == 'L')
{
hash |= 0x01;
}
return hash;
}
@ -727,34 +732,43 @@ int CLASS::doUSR(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
char c = os.empty() ? 0 : os.front();
if (c == '$' && os.length() > 1) {
if (c == '$' && os.length() > 1)
{
for (uint32_t i = 1; i < os.length(); ++i)
{
char hv = hexVal(os[i]);
if (hv < 0) {
if (hv < 0)
{
line.setError(errIllegalCharOperand);
bytect = 0;
goto out;
goto out;
}
hash <<= 4;
hash |= hv;
}
} else if ((c == '\'' || c == '\"') && os.front() == os.back() && os.length() == 6) {
}
else if ((c == '\'' || c == '\"') && os.front() == os.back() && os.length() == 6)
{
hash = usr_hash(os.substr(1, 4));
} else if (os.length() > 0 && os.length() <= 4) {
}
else if (os.length() > 0 && os.length() <= 4)
{
hash = usr_hash(os);
} else {
}
else
{
printf("line.setError(errBadOperand);\n");
line.setError(errBadOperand);
bytect = 0;
goto out;
goto out;
}
if (a.pass > 0) {
line.outbytes.push_back(hash & 0xff);
line.outbytes.push_back(hash >> 8);
if (a.pass > 0)
{
line.outbytes.push_back(hash & 0xff);
line.outbytes.push_back(hash >> 8);
}
out:
@ -778,7 +792,7 @@ int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
uint8_t ct = 0;
uint8_t delimiter = 0;
uint32_t ss = 0;
uint32_t lastdelimidx = 0;
uint32_t lastdelimidx = 0;
std::vector<uint8_t> bytes;
@ -809,7 +823,7 @@ int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
}
bytes.push_back(c);
lastdelimidx = (uint32_t)(bytes.size() - 1);
lastdelimidx = (uint32_t)(bytes.size() - 1);
}
}
@ -847,12 +861,12 @@ int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
// 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;
case 0:
b = (hv << 4);
break;
case 1:
b |= hv;
break;
}
ct = (ct + 1) & 0x01;
if (!ct)
@ -885,33 +899,33 @@ int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
//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;
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)
{
@ -930,7 +944,7 @@ int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
b = bytes[i];
}
b1 = b & 0x7F;
b1 = b & 0x7F;
if ((andval != 0xFF) || (orval != 0x00))
{
b = b1;
@ -947,17 +961,17 @@ int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
// 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
// 8D,'Hello',8D,'there',8D becomes 8D 48 65 6C 6C 6F 8D 74 68 65 72 E5
//
// The DCI instruction is documented to work like this on page 108
// (regardless of how this effects the desired lda, (bpl/bmi) functionality)
//
// I am now checking the delimiter character to determine hi/lo toggle (reversed)
// and am tracking the index to the last delimited character put into 'bytes'.
// This produces the same results as Merlin 16+ in my testing.
if ( firstdelim >= '\'' )
//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
//
// The DCI instruction is documented to work like this on page 108
// (regardless of how this effects the desired lda, (bpl/bmi) functionality)
//
// I am now checking the delimiter character to determine hi/lo toggle (reversed)
// and am tracking the index to the last delimited character put into 'bytes'.
// This produces the same results as Merlin 16+ in my testing.
if ( firstdelim >= '\'' )
{
b |= 0x80;
}
@ -982,108 +996,116 @@ int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
int CLASS::ProcessOpcode(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
{
int res = 0;
std::string s;
std::string s,sp;
switch (opinfo.opcode)
{
default:
res = -1; // undefined p-op
line.setError(errUnimplemented);
break;
case P_DS:
res = doDS(a, line, opinfo);
break;
case P_PUT:
case P_USE:
// both of these are handled by the input file processor, just allow them to be
// processed with no errors here
break;
case P_DUM:
case P_DEND:
res = doDUM(a, line, opinfo);
line.flags |= FLAG_FORCEADDRPRINT;
default:
res = -1; // undefined p-op
line.setError(errUnimplemented);
break;
case P_DS:
res = doDS(a, line, opinfo);
break;
case P_PUT:
case P_USE:
// both of these are handled by the input file processor, just allow them to be
// processed with no errors here
break;
case P_DUM:
case P_DEND:
res = doDUM(a, line, opinfo);
line.flags |= FLAG_FORCEADDRPRINT;
break;
case P_ORG:
if (line.operand_expr.length() > 0)
{
a.PC.orgsave = a.PC.currentpc;
a.PC.currentpc = line.expr_value;
line.startpc = line.expr_value;
}
else
{
a.PC.currentpc = a.PC.orgsave;
line.startpc = a.PC.orgsave;
}
break;
case P_ORG:
if (line.operand_expr.length() > 0)
{
a.PC.orgsave = a.PC.currentpc;
a.PC.currentpc = line.expr_value;
line.startpc = line.expr_value;
}
else
{
a.PC.currentpc = a.PC.orgsave;
line.startpc = a.PC.orgsave;
}
#if 0
// Merlin32 seems to have a bug where ORG seems like it can only be 16 bits
if ((line.syntax & SYNTAX_MERLIN32) == SYNTAX_MERLIN32)
{
// so clear the bank word in all variables
a.PC.orgsave &= 0xFFFF;
a.PC.currentpc &= 0xFFFF;
line.startpc &= 0xFFFF;
}
// Merlin32 seems to have a bug where ORG seems like it can only be 16 bits
if ((line.syntax & SYNTAX_MERLIN32) == SYNTAX_MERLIN32)
{
// so clear the bank word in all variables
a.PC.orgsave &= 0xFFFF;
a.PC.currentpc &= 0xFFFF;
line.startpc &= 0xFFFF;
}
#endif
line.flags |= FLAG_FORCEADDRPRINT;
break;
case P_SAV:
line.flags |= FLAG_FORCEADDRPRINT;
break;
case P_SAV:
sp = getConfig("option.objfile", "");
if (sp=="")
{
a.savepath = a.processFilename(line.operand, Poco::Path::current(), 0);
break;
case P_CAS:
s = Poco::toUpper(line.operand);
if (s == "SE")
}
else // if they specified an output name on the command line, use it.
{
a.savepath = sp;
}
break;
case P_CAS:
s = Poco::toUpper(line.operand);
if (s == "SE")
{
a.casesen = true;
}
if (s=="IN")
{
a.casesen=false;
}
res = 0;
break;
case P_MAC:
res = doMAC(a, line, opinfo);
break;
case P_ERR:
if (a.pass > 0)
{
if ((line.expr_value != 0) || (line.eval_result < 0))
{
a.casesen = true;
line.setError(errErrOpcode);
//a.passcomplete=true; // terminate assembly
}
if (s=="IN")
{
a.casesen=false;
}
res = 0;
break;
case P_MAC:
res = doMAC(a, line, opinfo);
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;
case P_HEX:
res = doHEX(a, line, opinfo);
break;
case P_DATA:
res = doDATA(a, line, opinfo);
break;
case P_LUP:
res = doLUP(a, line, opinfo);
break;
case P_DO:
res = doDO(a, line, opinfo);
break;
case P_TR:
res = doTR(a, line, opinfo);
break;
case P_ASC:
res = doASC(a, line, opinfo);
break;
}
res = 0;
break;
case P_LST:
res = doLST(a, line, opinfo);
break;
case P_HEX:
res = doHEX(a, line, opinfo);
break;
case P_DATA:
res = doDATA(a, line, opinfo);
break;
case P_LUP:
res = doLUP(a, line, opinfo);
break;
case P_DO:
res = doDO(a, line, opinfo);
break;
case P_TR:
res = doTR(a, line, opinfo);
break;
case P_ASC:
res = doASC(a, line, opinfo);
break;
case P_USR:
res = doUSR(a, line, opinfo);
break;
case P_USR:
res = doUSR(a, line, opinfo);
break;
}
return (res);

View File

@ -6,7 +6,6 @@
#define CLASS PAL_APPCLASS
// return a pointer to the actual Application class
PAL_BASEAPP *PAL::appFactory(void)
{
@ -21,8 +20,16 @@ programOption PAL::appOptions[] =
#endif
//{ "config", "f", "load configuration data from a <file>", "<file>", 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},
{ "syntax", "s", "enforce syntax of other assembler [qasm, merlin, merlin32, ORCA, APW, MPW, CC65]", "<syntax>", false, false},
{ "objfile", "o", "write output to <objfile>", "<objfile>", false, false},
{ "instruction", "i", "force the CPU instruction set ('xc' ingored) [6502, 65C02, 65816]", "<cpu>", false, false},
{ "type", "t", "enforce syntax/features/bugs of other assembler [qasm, merlin8, merlin16, merlin16plus, merlin32, orca, apw, mpw, lisa, ca65]", "<type>", false, false},
{ "quiet", "q", "print as little as possible, equivalent to lst off in the assembler ('lst' opcodes will be ignored)", "", false, true},
{ "list", "l", "force assembly listing ('lst' opcodes will be ignored)", "", false, true},
{ "color", "c", "colorize the output", "", false, true},
{ "parms", "p", "show the working parameters/options", "", false, true},
{ "", "", "", "", false, false}
@ -75,62 +82,49 @@ int CLASS::runCommandLineApp(void)
TFileProcessor *t = NULL;
std::string line;
std::string startdirectory;
std::string appPath;
std::string fname;
uint32_t syntax;
//uint32_t syntax;
string product="";
string syn;
int res = -1;
ConfigOptions options;
//Poco::Util::Application::instance().config()
utils=new QUtils();
//LOG_NOTE << "this is it!" << endl;
startdirectory = Poco::Path::current();
appPath=utils->getAppPath();
if (commandargs.size() == 0)
{
displayHelp();
return (res);
}
options.ReadFile(startdirectory+"/parms.json");
options.ReadFile(Poco::Path::config()+"/parms.json");
options.ReadFile(appPath+"/parms.json");
options.ReadFile(Poco::Path::configHome()+"/parms.json");
options.ReadFile(Poco::Path::current()+"/parms.json");
string syn=options.GetString("assembler.syntax","QASM");
syn="QASM";
//syn=options.GetString("assembler.syntax","QASM");
string cmdsyn = Poco::toUpper(getConfig("option.syntax", ""));
string cmdsyn = Poco::toUpper(getConfig("option.type", ""));
if (cmdsyn!="")
{
syn=cmdsyn; // if they overrode the syntax on the command line, use it
}
syn=Poco::toUpper(syn);
syn=Poco::trim(syn);
syntax=SYNTAX_QASM;
if ((syn=="MERLIN") || (syn=="MERLIN16") || (syn=="MERLIN8") || (syn=="MERLIN16PLUS"))
{
syntax=SYNTAX_MERLIN;
}
else if (syn=="MERLIN32")
{
syntax=SYNTAX_MERLIN32;
}
else if (syn=="QASM")
{
syntax=SYNTAX_QASM;
}
else if (syn=="APW")
{
syntax=SYNTAX_APW;
}
else if (syn=="ORCA")
{
syntax=SYNTAX_ORCA;
}
else if (syn=="MPW")
{
syntax=SYNTAX_MPW;
}
else if (syn=="CC65")
{
syntax=SYNTAX_CC65;
}
product=Poco::trim(syn);
//printf("SYNTAX: |%s|\n",syn.c_str());
if (isDebug()>0)
{
printf("SYNTAX: |%s|\n",syn.c_str());
}
try
{
@ -196,7 +190,7 @@ int CLASS::runCommandLineApp(void)
{
format_flags=CONVERT_TEST;
}
options.format_flags=format_flags;
cmd=toks[0];
}
}
@ -205,13 +199,14 @@ int CLASS::runCommandLineApp(void)
if (cmd == "FORMAT")
{
res = 0;
t = new TMerlinConverter();
t = new TMerlinConverter(options);
//t=NULL;
if (t != NULL)
{
try
{
t->init();
t->setSyntax(syntax);
t->setProduct(product);
t->format_flags=format_flags;
std::string f = path.toString();
@ -239,13 +234,14 @@ int CLASS::runCommandLineApp(void)
else if (cmd == "ASM")
{
int x;
t = new T65816Asm();
t = new T65816Asm(options);
if (t != NULL)
{
try
{
t->init();
t->setSyntax(syntax);
t->setProduct(product);
std::string f = path.toString();
t->filename = f;
@ -275,13 +271,13 @@ int CLASS::runCommandLineApp(void)
else if (cmd == "SCRIPT")
{
res = 0;
t = new CiderPress();
t = new CiderPress(options);
if (t!=NULL)
{
try
{
t->init();
t->setSyntax(syntax);
t->setProduct(product);
std::string f = path.toString();
t->filename = f;

6
qasm.h
View File

@ -5,6 +5,7 @@
#include <pallogger.h>
#include <eventtask.h>
#include <baseapp.h>
#include "app.h"
#include "qoptions.h"
#include "util.h"
//#include <httpserver.h>
@ -27,7 +28,10 @@ protected:
virtual void displayVersion();
public:
QOptions options;
QOptions options;
};
extern PAL_LOGGER logger;
#undef CLASS

View File

@ -9,6 +9,7 @@ CLASS::CLASS()
jsonin="";
jsonobj=NULL;
parser.reset();
parser.setAllowComments(true);
}
int CLASS::ReadFile(string path)
@ -17,6 +18,8 @@ int CLASS::ReadFile(string path)
Poco::FileInputStream fs(path);
Poco::StreamCopier::copyToString(fs,jsonin);
parser.reset();
parser.setAllowComments(true);
jsonobj=parser.parse(jsonin);
config.load(path);

View File

@ -1,12 +1,237 @@
#pragma once
#include "app.h"
#include "qasm.h"
#define MAX_PREFIX 32
#define MODE_6502 0
#define MODE_65C02 1
#define MODE_65816 2
#define SYNTAX_MERLIN 0x01
#define SYNTAX_MERLIN32 0x02
#define SYNTAX_APW 0x04
#define SYNTAX_MPW 0x08
#define SYNTAX_ORCA 0x10
#define SYNTAX_CC65 0x20
#define SYNTAX_LISA 0x40
#define SYNTAX_QASM (0x80 | SYNTAX_MERLIN)
#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 OPTION_M16_PLUS 0x8000
#undef CLASS
#define CLASS ConfigOptions
class CLASS
{
protected:
vector<shared_ptr<JSONConfiguration>> configs;
public:
Poco::JSON::Parser parser;
string jsonin;
Dynamic::Var jsonobj=NULL;
uint16_t format_flags;
uint16_t cpu_mode;
string product;
uint16_t productlevel;
string prefixes[MAX_PREFIX];
uint8_t start_mx;
bool start_listmode;
bool listmode;
bool casesen;
bool showmx;
bool allowDuplicate;
bool trackrep;
bool merlinerrors;
bool m32vars;
bool allowA;
bool allowLocal;
bool allowColon;
bool oldevaluation;
int16_t linebytes;
int16_t overflowbytes;
//Poco::Util::LayeredConfiguration config;
bool usecolor;
CLASS()
{
setDefaults();
setProduct("QASM");
}
~CLASS()
{
}
void clear()
{
//configs.clear();
}
bool useColor(void)
{
bool res=false;
if (getBool("option.color",false))
{
res=true;
}
if ((!isatty(STDOUT_FILENO)) || (0))
{
res=false;
}
return(res);
}
bool isQuiet(void)
{
bool res;
res=getBool("option.quiet",false);
if (isDebug()>0)
{
res=false;
}
return(res);
}
bool isList(void)
{
bool res;
res=getBool("option.list",false);
return(res);
}
int ReadFile(string path)
{
int ret=-1;
Poco::Util::JSONConfiguration *jc;
Poco::Path pp(path);
//pp=pp.expand();
Poco::File pf(pp);
if (isDebug()>1)
{
printf("parmsfile: %s\n",pp.toString().c_str());
}
if ((pf.exists()) && (pf.canRead()) && ((pf.isFile()) || (pf.isLink())))
{
//printf("OK: %s\n",pp.toString().c_str());
jc=new Poco::Util::JSONConfiguration();
//Poco::FileInputStream fs(path);
//Poco::StreamCopier::copyToString(fs,jsonin);
//parser.reset();
//parser.setAllowComments(true);
//jsonobj=parser.parse(jsonin);
if (jc!=NULL)
{
bool success=false;
try
{
jc->load(pp.toString());
success=true;
}
catch(...)
{
success=false;
}
if (success)
{
//configs.push_back(shared_ptr<JSONConfiguration>(jc));
ret=0;
}
else
{
printf("unable to load/parts file: %s\n",pp.toString().c_str());
}
}
}
return(ret);
}
void printCurrentOptions(void)
{
printf("Current Options:");
printf(" product: %s\n",product.c_str());
//printf(" start_mx: \%%02d\n",start_mx);
}
bool isMerlin32(void)
{
return(true);
}
bool isMerlin(void)
{
return(false);
}
void setDefaults(void)
{
cpu_mode=MODE_6502;
product="QASM";
productlevel=0;
for (int i=0; i<MAX_PREFIX; i++)
{
prefixes[i]="";
}
start_mx=0x03;
start_listmode=true;
listmode=start_listmode;
casesen=true;
showmx=true;
allowDuplicate=false;
trackrep=false;
merlinerrors=true;
m32vars=false;
allowA=true;
allowLocal=false;
allowColon=false;
oldevaluation=true;
linebytes=4;
overflowbytes=6;
usecolor=true;
}
void setProduct(string productName)
{
string old=productName;
string pn=Poco::toUpper(productName);
if (old!=pn)
{
printf("setting product options to %s\n",pn.c_str());
productName=pn;
if (pn=="QASM")
{
setQASM();
}
}
}
void setQASM()
{
}
};
#undef CLASS
#define CLASS QOptions
class CLASS
{
public:
Poco::Util::JSONConfiguration config;
Poco::Util::JSONConfiguration config;
Poco::JSON::Parser parser;
string jsonin;
Dynamic::Var jsonobj=NULL;

10
test.link Normal file
View File

@ -0,0 +1,10 @@
product QASM
nolist
asm test.s -o test.o
asm test1.s -o test1.o
asm test2.s -o test2.o
link test.o test1.o test2.o
volume TESTASM test.2mg 800K prodos .2mg
copyto TESTASM test.o :SOURCE: 0x06 0x2000
copyto TESTASM test.s :SOURCE: 0x04 0x0000 FORMAT-MERLIN

59
test.s Normal file
View File

@ -0,0 +1,59 @@
* [QASM] SYNTAX MERLIN16
* [QASM] Filetype $06
* [QASM] AuxType $2000
* [QASM] Volume TESTASM test.2mg 800K prodos 2mg
* [QASM] save TESTASM :SOURCE:${FILE}.bin
xc off
xc
xc
;lst OFF
ZP equ $00
org $2000
ora ($00)
lda ($00)
bit: $FFFE,X
ror: $FFFE,X
ora #ZP
begin
;]m equ *
; lda begin
; lda ]m
lst on
;end
_mymac mac
]mac1 lda ]mac1
ldal ]1
ldal ]2
eom
_ascmac mac
asc ]1,]2,8D
eom
lst off
;var 'one';'two';'three'
justlable ;line with just a lable
start
another lda #$00 ;line with everything
lda #$00 ;line with opcode, operand comment
nop ;line with just opcode
_mymac *;1
_mymac *;2
_ascmac 'hello';'there'
lup 2
]m equ *
nop
lda ]m
bra ]m
--^
]1 nop
nop
lst
bra ]1
;typ $06
sav 0/test.bin
lst off

View File

@ -1,12 +1,38 @@
#include <util.h>
#define UTIL_CPP
#include <app.h>
bool isMerlin32(void)
#undef CLASS
#define CLASS QUtils
CLASS::CLASS() : appInstance(Poco::Util::Application::instance())
{
}
bool CLASS::isMerlin32(void)
{
return(false);
}
bool isMerlin816(void)
bool CLASS::isMerlin816(void)
{
return(true);
}
string CLASS::getAppPath()
{
char buff[PATH_MAX+1];
char *x;
string res="";
res=appInstance.commandPath();
x=realpath(res.c_str(),buff);
if (x!=NULL)
{
res=buff;
}
else
res="";
return(res);
}

20
util.h
View File

@ -1,5 +1,19 @@
#pragma once
#include <app.h>
#include <palPoco.h>
bool isMerlin32(void);
bool isMerlin816(void);
class QUtils
{
protected:
Poco::Util::Application &appInstance;
public:
QUtils();
bool isMerlin32(void);
bool isMerlin816(void);
string getAppPath();
};
#ifdef UTIL_CPP
QUtils *utils=NULL;
#else
extern QUtils *utils;
#endif