mirror of
https://github.com/marketideas/qasm.git
synced 2025-01-13 20:32:14 +00:00
DUM complete, DS working/not done, work on shift operators
This commit is contained in:
parent
0af8c9765a
commit
8608bf5a94
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
||||
**/build
|
||||
*.xcuserstate
|
||||
*.xcbkptlist
|
||||
|
2
Makefile
2
Makefile
@ -33,7 +33,7 @@ install:
|
||||
-cd ./build && cmake -P cmake_install.cmake
|
||||
|
||||
reformat:
|
||||
qasm -r src/main.s
|
||||
qasm -x REFORMAT src/main.s
|
||||
|
||||
asm:
|
||||
|
||||
|
141
asm.cpp
141
asm.cpp
@ -163,6 +163,7 @@ void CLASS::clear()
|
||||
outbytes.clear();
|
||||
addressmode = 0;
|
||||
expr_value = 0;
|
||||
eval_result = 0;
|
||||
flags = 0;
|
||||
outbytes.clear();
|
||||
}
|
||||
@ -451,7 +452,7 @@ int CLASS::processfile(std::string &p)
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("file %s does not exist\n", p.c_str());
|
||||
fprintf(stderr,"File <%s> does not exist.\n\n", p.c_str());
|
||||
}
|
||||
|
||||
//printf("\n\nfile read result: %d\n", res);
|
||||
@ -499,7 +500,6 @@ void CLASS::init(void)
|
||||
|
||||
int CLASS::doline(int lineno, std::string line)
|
||||
{
|
||||
|
||||
MerlinLine l(line);
|
||||
lines.push_back(l);
|
||||
return 0;
|
||||
@ -513,7 +513,7 @@ void CLASS::process(void)
|
||||
|
||||
for (uint32_t lineno = 0; lineno < ct; lineno++)
|
||||
{
|
||||
MerlinLine &line = lines[lineno];
|
||||
MerlinLine &line = lines.at(lineno);
|
||||
|
||||
pos = 0;
|
||||
len = 0;
|
||||
@ -734,6 +734,8 @@ void CLASS::showSymbolTable(bool alpha)
|
||||
std::map<std::string, uint32_t> alphamap;
|
||||
std::map<uint32_t, std::string> nummap;
|
||||
|
||||
int columns = 4;
|
||||
int column = columns;
|
||||
|
||||
for (auto itr = symbols.begin(); itr != symbols.end(); itr++)
|
||||
{
|
||||
@ -746,19 +748,29 @@ void CLASS::showSymbolTable(bool alpha)
|
||||
|
||||
if (alpha)
|
||||
{
|
||||
printf("\nSymbol table sorted alphabetically:\n");
|
||||
printf("\n\nSymbol table sorted alphabetically:\n\n");
|
||||
|
||||
for (auto itr = alphamap.begin(); itr != alphamap.end(); ++itr)
|
||||
{
|
||||
printf("%-16s 0x%08X\n", itr->first.c_str(), itr->second);
|
||||
printf("%16s 0x%08X", itr->first.c_str(), itr->second);
|
||||
if( !--column )
|
||||
{
|
||||
printf("\n");
|
||||
column = columns;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("\nSymbol table sorted numerically:\n");
|
||||
printf("\n\nSymbol table sorted numerically:\n\n");
|
||||
for (auto itr = nummap.begin(); itr != nummap.end(); ++itr)
|
||||
{
|
||||
printf("0x%08X %-16s\n", itr->first, itr->second.c_str());
|
||||
printf("0x%08X %-16s", itr->first, itr->second.c_str());
|
||||
if( !--column )
|
||||
{
|
||||
printf("\n");
|
||||
column = columns;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -825,12 +837,11 @@ const TaddrMode addrRegEx[] =
|
||||
{
|
||||
{ "^(?'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}(?'shift'[<,>,^,|]?)(.+)$", 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}[\\,][(Y|y]{1}$", syn_diiy, "(e),y"}, //(expr),y
|
||||
{"^[(]{1}(?'expr'.+)[\\)]{1}$", syn_di, "(e)"}, // (expr)
|
||||
{"^\\[{1}(?'expr'.+)\\]{1}[,]{1}[(Y|y)]{1}$", syn_iyl, "[e],y"}, // [expr],y
|
||||
//{"^\\[{1}(?'expr'.+)\\]{1}[,]{1}[(X|x)]{1}$", syn_iyl, "[e],x"}, // [expr],x
|
||||
{"^\\[(?'expr'.+)\\]$", syn_dil, "[e]"}, // [expr]
|
||||
{"^(?'expr'.+)[,]{1}[(X|x)]{1}$", syn_absx, "e,x"}, // expr,x
|
||||
{"^(?'expr'.+)[,]{1}[(Y|y)]{1}$", syn_absy, "e,y"}, // expr,y
|
||||
@ -839,7 +850,11 @@ const TaddrMode addrRegEx[] =
|
||||
{"", 0, ""}
|
||||
};
|
||||
|
||||
const std::string valExpression = "^([$%\\+\\-:-~][^\\],()]*)$";
|
||||
// keep this next line for awhile
|
||||
// {"^#{1}(?'shift'[<,>,^,|]?)(.+)$", syn_imm, "immediate"}, //#expr,#^expr,#|expr,#<expr,#>expr
|
||||
|
||||
// one or more of any character except ][,();
|
||||
const std::string valExpression = "^([^\\]\\[,();]+)$";
|
||||
|
||||
// opcode check. emitted opcodes are compared against this
|
||||
// table, and if the XC status doesn't meet the requirements
|
||||
@ -895,6 +910,8 @@ void CLASS::initpass(void)
|
||||
|
||||
PC.origin = 0x8000;
|
||||
PC.currentpc = PC.origin;
|
||||
PC.totalbytes=0;
|
||||
PC.orgsave=PC.origin;
|
||||
|
||||
s = getConfig("asm.cpu", "M65816");
|
||||
s = Poco::trim(Poco::toUpper(s));
|
||||
@ -923,10 +940,12 @@ void CLASS::initpass(void)
|
||||
}
|
||||
relocatable = false;
|
||||
currentsym = NULL;
|
||||
PC.totalbytes = 0;
|
||||
lineno = 0;
|
||||
errorct = 0;
|
||||
passcomplete = false;
|
||||
dumstartaddr=0;
|
||||
dumstart=0;
|
||||
|
||||
|
||||
variables.clear(); // clear the variables for each pass
|
||||
while (!PCstack.empty())
|
||||
@ -944,19 +963,18 @@ void CLASS::complete(void)
|
||||
{
|
||||
if (errorct == 0)
|
||||
{
|
||||
MerlinLine *line;
|
||||
std::ofstream f(savepath);
|
||||
|
||||
uint32_t lineno = 0;
|
||||
uint32_t l = lines.size();
|
||||
while (lineno < l)
|
||||
{
|
||||
line = &lines[lineno++];
|
||||
if (line->outbytect > 0)
|
||||
MerlinLine &line=lines.at(lineno++);
|
||||
if (line.outbytect > 0)
|
||||
{
|
||||
for (uint32_t i = 0; i < line->outbytect; i++)
|
||||
for (uint32_t i = 0; i < line.outbytect; i++)
|
||||
{
|
||||
f.put(line->outbytes[i]);
|
||||
f.put(line.outbytes[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -986,7 +1004,7 @@ int CLASS::evaluate(std::string expr, int64_t &value)
|
||||
|
||||
TEvaluator eval(*this);
|
||||
|
||||
res = eval.evaluate(expr, result);
|
||||
res = eval.evaluate(expr, result, mx);
|
||||
if (res != 0)
|
||||
{
|
||||
if (isDebug() > 2)
|
||||
@ -1006,6 +1024,10 @@ int CLASS::evaluate(std::string expr, int64_t &value)
|
||||
value = 0;
|
||||
res = 0;
|
||||
}
|
||||
if (isDebug()>=3)
|
||||
{
|
||||
printf("Eval Result: %08lX (status=%d)\n",value,res);
|
||||
}
|
||||
return (res);
|
||||
}
|
||||
|
||||
@ -1127,13 +1149,13 @@ int CLASS::parseOperand(MerlinLine & line)
|
||||
void CLASS::process(void)
|
||||
{
|
||||
uint32_t l;
|
||||
int x, evalresult;
|
||||
int x;;
|
||||
char c;
|
||||
std::string op, operand;
|
||||
//uint32_t operand_eval;
|
||||
//uint16_t addrmode;
|
||||
|
||||
MerlinLine *line;
|
||||
//MerlinLine *line;
|
||||
pass = 0;
|
||||
while (pass < 2)
|
||||
{
|
||||
@ -1142,100 +1164,115 @@ void CLASS::process(void)
|
||||
l = lines.size();
|
||||
while ((lineno < l) && (!passcomplete))
|
||||
{
|
||||
evalresult = 0;
|
||||
line = &lines[lineno];
|
||||
MerlinLine &line=lines[lineno];
|
||||
|
||||
line->lineno = lineno + 1;
|
||||
//printf("lineno: %d %d |%s|\n",lineno,l,line->operand.c_str());
|
||||
line.eval_result=0;
|
||||
line.lineno = lineno + 1;
|
||||
//printf("lineno: %d %d |%s|\n",lineno,l,line.operand.c_str());
|
||||
|
||||
op = Poco::toLower(line->opcode);
|
||||
operand = Poco::toLower(line->operand);
|
||||
line->startpc = PC.currentpc;
|
||||
line->linemx = mx;
|
||||
line->bytect = 0;
|
||||
line->showmx = showmx;
|
||||
op = Poco::toLower(line.opcode);
|
||||
operand = Poco::toLower(line.operand);
|
||||
line.startpc = PC.currentpc;
|
||||
line.linemx = mx;
|
||||
line.bytect = 0;
|
||||
line.showmx = showmx;
|
||||
|
||||
if ((line->lable != "") && (pass == 0))
|
||||
if ((line.lable != "") && (pass == 0))
|
||||
{
|
||||
std::string lable = Poco::trim(line->lable);
|
||||
std::string lable = Poco::trim(line.lable);
|
||||
TSymbol *sym = NULL;
|
||||
bool dupsym = false;
|
||||
c = line->lable[0];
|
||||
c = line.lable[0];
|
||||
switch (c)
|
||||
{
|
||||
case ']':
|
||||
sym = addVariable(line->lable, "", true);
|
||||
sym = addVariable(line.lable, "", true);
|
||||
if (sym == NULL) { dupsym = true; }
|
||||
break;
|
||||
case ':':
|
||||
break;
|
||||
default:
|
||||
sym = addSymbol(line->lable, PC.currentpc, false);
|
||||
sym = addSymbol(line.lable, PC.currentpc, false);
|
||||
if (sym == NULL) { dupsym = true; }
|
||||
break;
|
||||
}
|
||||
if (dupsym)
|
||||
{
|
||||
line->setError(errDupSymbol);
|
||||
line.setError(errDupSymbol);
|
||||
}
|
||||
}
|
||||
x = parseOperand(*line);
|
||||
x = parseOperand(line);
|
||||
if (x >= 0)
|
||||
{
|
||||
line->addressmode = x;
|
||||
line.addressmode = x;
|
||||
}
|
||||
|
||||
int64_t value = -1;
|
||||
x = evaluate(line->operand_expr, value);
|
||||
evalresult = x;
|
||||
x = evaluate(line.operand_expr, value);
|
||||
line.eval_result=x;
|
||||
|
||||
if (x == 0)
|
||||
{
|
||||
value &= 0xFFFFFFFF;
|
||||
line->expr_value = value;
|
||||
line.expr_value = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
line->expr_value = 0;
|
||||
line.expr_value = 0;
|
||||
}
|
||||
|
||||
x = 0;
|
||||
if (op.length() > 0)
|
||||
{
|
||||
x = callOpCode(op, *line);
|
||||
x = callOpCode(op, line);
|
||||
}
|
||||
|
||||
if (x > 0)
|
||||
{
|
||||
if ((evalresult != 0) && (pass > 0))
|
||||
if ((line.eval_result != 0) && (pass > 0))
|
||||
{
|
||||
line->setError(errBadOperand);
|
||||
line->errorText = line->operand_expr;
|
||||
line.setError(errBadOperand);
|
||||
line.errorText = line.operand_expr;
|
||||
}
|
||||
line->bytect = x;
|
||||
line.bytect = x;
|
||||
PC.currentpc += x;
|
||||
PC.totalbytes += x;
|
||||
}
|
||||
if (pass == 0)
|
||||
{
|
||||
line->pass0bytect = line->bytect;
|
||||
line.pass0bytect = line.bytect;
|
||||
}
|
||||
|
||||
if (dumstart>0) // starting a dummy section
|
||||
{
|
||||
PCstack.push(PC);
|
||||
PC.origin=dumstartaddr;
|
||||
PC.currentpc=PC.origin;
|
||||
dumstart=0;
|
||||
dumstartaddr=0;
|
||||
}
|
||||
if (dumstart<0)
|
||||
{
|
||||
PC=PCstack.top();
|
||||
PCstack.pop();
|
||||
dumstart=0;
|
||||
dumstartaddr=0;
|
||||
}
|
||||
|
||||
if (pass == 1)
|
||||
{
|
||||
if ((line->pass0bytect != line->bytect) && (line->errorcode == 0))
|
||||
if ((line.pass0bytect != line.bytect) && (line.errorcode == 0))
|
||||
{
|
||||
line->setError(errBadByteCount);
|
||||
line.setError(errBadByteCount);
|
||||
}
|
||||
|
||||
if (line->errorcode != 0)
|
||||
if (line.errorcode != 0)
|
||||
{
|
||||
errorct++;
|
||||
}
|
||||
if (((!skiplist) && (listing) && (pass == 1)) || (line->errorcode != 0))
|
||||
if (((!skiplist) && (listing) && (pass == 1)) || (line.errorcode != 0))
|
||||
{
|
||||
line->print(lineno);
|
||||
line.print(lineno);
|
||||
}
|
||||
skiplist = false;
|
||||
}
|
||||
|
48
asm.h
48
asm.h
@ -38,10 +38,14 @@ enum asmErrors
|
||||
errBadByteCount,
|
||||
errBadBranch,
|
||||
errUnimplemented,
|
||||
errForwardReference,
|
||||
errForwardRef,
|
||||
errNoRedefinition,
|
||||
errBadOperand,
|
||||
errDupSymbol,
|
||||
errBadDUMop,
|
||||
errOverflow,
|
||||
errRecursiveOp,
|
||||
errOpcodeNotStarted,
|
||||
errMAX
|
||||
};
|
||||
|
||||
@ -62,7 +66,10 @@ const std::string errStrings[errMAX + 1] =
|
||||
"Unable to redefine symbol",
|
||||
"Unable to evaluate",
|
||||
"Duplicate Symbol",
|
||||
|
||||
"Invalid use of DUM/DEND",
|
||||
"Overflow detected",
|
||||
"Recursive Operand",
|
||||
"Opcode without start",
|
||||
""
|
||||
};
|
||||
#else
|
||||
@ -96,10 +103,42 @@ enum
|
||||
|
||||
class TOriginSection
|
||||
{
|
||||
// SGQ - if you do something unusual here, be aware of copy constructor
|
||||
// may be needed
|
||||
public:
|
||||
uint32_t origin;
|
||||
uint32_t currentpc;
|
||||
uint32_t totalbytes;
|
||||
uint32_t orgsave;
|
||||
#if 0
|
||||
TOriginSection(const TOriginSection &old)
|
||||
{
|
||||
origin = old.origin;
|
||||
currentpc = old.currentpc;
|
||||
orgsave=old.orgsave;
|
||||
totalbytes = old.totalbytes;
|
||||
};
|
||||
|
||||
TOriginSection& operator=(const TOriginSection &other)
|
||||
{
|
||||
origin = other.origin;
|
||||
currentpc = other.currentpc;
|
||||
totalbytes = other.totalbytes;
|
||||
orgsave=other.orgsave;
|
||||
return (*this);
|
||||
};
|
||||
|
||||
TOriginSection()
|
||||
{
|
||||
origin = 0;
|
||||
currentpc = 0;
|
||||
totalbytes = 0;
|
||||
orgsave=0;
|
||||
};
|
||||
~TOriginSection()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
class MerlinLine
|
||||
@ -124,6 +163,7 @@ public:
|
||||
int32_t startpc;
|
||||
uint32_t addressmode;
|
||||
int32_t expr_value;
|
||||
int32_t eval_result; // this is the error code from the evaluate routing (0 or neg)
|
||||
uint32_t errorcode;
|
||||
std::string errorText;
|
||||
|
||||
@ -223,10 +263,10 @@ public:
|
||||
|
||||
bool passcomplete;
|
||||
bool relocatable;
|
||||
int dumstart; // must be signed
|
||||
uint32_t dumstartaddr;
|
||||
bool skiplist; // used if lst is on, but LST opcode turns it off
|
||||
uint32_t lineno;
|
||||
//uint32_t origin;
|
||||
//uint32_t currentpc;
|
||||
|
||||
std::string savepath;
|
||||
TSymbol *currentsym;
|
||||
|
72
eval.cpp
72
eval.cpp
@ -118,11 +118,19 @@ std::deque<Token> CLASS::exprToTokens(const std::string& expr)
|
||||
numexpect = false;
|
||||
|
||||
}
|
||||
else if ((numexpect) && ( (c == '^') || (c == '<') || (c == '>') || (c == '|')))
|
||||
{
|
||||
ident = c;
|
||||
tokens.push_back(Token{Token::Type::Shift, ident, 1, true});
|
||||
ident = "";
|
||||
}
|
||||
else if ((c == '*') && (numexpect))
|
||||
{
|
||||
numexpect = false;
|
||||
state = 20;
|
||||
state = 0;
|
||||
ident += c;
|
||||
tokens.push_back(Token{Token::Type::Symbol, ident, 1, false});
|
||||
ident = "";
|
||||
}
|
||||
else if ((c == '%') && (numexpect))
|
||||
{
|
||||
@ -155,14 +163,7 @@ std::deque<Token> CLASS::exprToTokens(const std::string& expr)
|
||||
numexpect = false;
|
||||
|
||||
}
|
||||
else if ((c >= 'a') && (c <= 'z'))
|
||||
{
|
||||
state = 20;
|
||||
ident += c;
|
||||
numexpect = false;
|
||||
|
||||
}
|
||||
else if ((c >= 'A') && (c <= 'Z'))
|
||||
else if (c >= ':')
|
||||
{
|
||||
state = 20;
|
||||
ident += c;
|
||||
@ -229,7 +230,6 @@ std::deque<Token> CLASS::shuntingYard(const std::deque<Token>& tokens)
|
||||
if (sym != NULL)
|
||||
{
|
||||
sym->used = true;
|
||||
//printf("symbol found\n");
|
||||
sprintf(buff, "%d", sym->value);
|
||||
token.str = buff;
|
||||
}
|
||||
@ -247,6 +247,9 @@ std::deque<Token> CLASS::shuntingYard(const std::deque<Token>& tokens)
|
||||
queue.push_back(token);
|
||||
break;
|
||||
|
||||
case Token::Type::Shift:
|
||||
stack.push_back(token);
|
||||
break;
|
||||
case Token::Type::Operator:
|
||||
{
|
||||
// If the token is operator, o1, then:
|
||||
@ -317,7 +320,7 @@ std::deque<Token> CLASS::shuntingYard(const std::deque<Token>& tokens)
|
||||
{
|
||||
// If the stack runs out without finding a left parenthesis,
|
||||
// then there are mismatched parentheses.
|
||||
printf("RightParen error (%s)\n", token.str.c_str());
|
||||
//printf("RightParen error (%s)\n", token.str.c_str());
|
||||
setError(Token::operatorErr);
|
||||
return queue;
|
||||
}
|
||||
@ -327,7 +330,7 @@ std::deque<Token> CLASS::shuntingYard(const std::deque<Token>& tokens)
|
||||
default:
|
||||
setError(Token::syntaxErr);
|
||||
|
||||
printf("error (%s)\n", token.str.c_str());
|
||||
//printf("error (%s)\n", token.str.c_str());
|
||||
return queue;
|
||||
break;
|
||||
}
|
||||
@ -518,11 +521,12 @@ void CLASS::setError(int ecode)
|
||||
}
|
||||
}
|
||||
|
||||
int CLASS::evaluate(std::string & e, int64_t &res)
|
||||
int CLASS::evaluate(std::string & e, int64_t &res, uint8_t &_shiftmode)
|
||||
{
|
||||
// const std::string expr = "3+4*2/(1-5)^2^3"; // Wikipedia's example
|
||||
// const std::string expr = "20-30/3+4*2^3";
|
||||
|
||||
_shiftmode=shiftmode=0;
|
||||
res = DEF_VAL;
|
||||
setError(Token::noError);
|
||||
|
||||
@ -531,8 +535,10 @@ int CLASS::evaluate(std::string & e, int64_t &res)
|
||||
std::string expr = Poco::trim(e);
|
||||
expr += " "; // add a space at end to make parsing easier
|
||||
|
||||
//printf("expression: |%s|\n",expr.c_str());
|
||||
|
||||
if (isDebug() >= 4)
|
||||
{
|
||||
printf("eval: expression: |%s|\n", expr.c_str());
|
||||
}
|
||||
const auto tokens = exprToTokens(expr);
|
||||
auto queue = shuntingYard(tokens);
|
||||
std::vector<int64_t> stack;
|
||||
@ -565,6 +571,41 @@ int CLASS::evaluate(std::string & e, int64_t &res)
|
||||
//op = "Push " + token.str;
|
||||
break;
|
||||
|
||||
case Token::Type::Shift:
|
||||
{
|
||||
auto rhs = DEF_VAL;
|
||||
|
||||
if (stack.size() > 0)
|
||||
{
|
||||
rhs = stack.back();
|
||||
stack.pop_back();
|
||||
shiftmode=token.str[0];
|
||||
|
||||
if (token.str=="^")
|
||||
{
|
||||
//rhs = (rhs >> 16) &0xFFFF ;
|
||||
}
|
||||
else if (token.str=="|")
|
||||
{
|
||||
//rhs = (rhs >> 16) & 0xFFFF;
|
||||
}
|
||||
else if (token.str=="<")
|
||||
{
|
||||
//rhs = (rhs << 8 ) & 0xFFFF;
|
||||
}
|
||||
else if (token.str==">")
|
||||
{
|
||||
//rhs=(rhs>>8) & 0xFFFF;
|
||||
}
|
||||
|
||||
stack.push_back(rhs);
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf("nothing on stack\n");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Token::Type::Operator:
|
||||
{
|
||||
|
||||
@ -656,6 +697,7 @@ out:
|
||||
{
|
||||
setError(Token::syntaxErr);
|
||||
}
|
||||
_shiftmode=shiftmode;
|
||||
res = v;
|
||||
return (evalerror);
|
||||
}
|
||||
|
4
eval.h
4
eval.h
@ -41,6 +41,7 @@ public:
|
||||
Unknown = 0,
|
||||
Number,
|
||||
Symbol,
|
||||
Shift,
|
||||
Operator,
|
||||
LeftParen,
|
||||
RightParen,
|
||||
@ -62,6 +63,7 @@ protected:
|
||||
T65816Asm &assembler;
|
||||
int evalerror;
|
||||
void setError(int ecode);
|
||||
uint8_t shiftmode;
|
||||
public:
|
||||
CLASS(T65816Asm &_asm);
|
||||
~CLASS();
|
||||
@ -69,7 +71,7 @@ public:
|
||||
std::deque<Token> shuntingYard(const std::deque<Token>& tokens);
|
||||
std::deque<Token> exprToTokens(const std::string& expr);
|
||||
int parseNumber(std::string n, int64_t &val);
|
||||
int evaluate(std::string &expr, int64_t &res);
|
||||
int evaluate(std::string &expr, int64_t &res, uint8_t &_shiftmode);
|
||||
|
||||
};
|
||||
|
||||
|
@ -687,7 +687,7 @@ void CLASS::insertOpcodes(void)
|
||||
pushopcode("ORG", P_ORG, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
|
||||
pushopcode("DSK", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
|
||||
pushopcode("SAV", P_SAV, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
|
||||
pushopcode("DS", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
|
||||
pushopcode("DS", P_DS, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
|
||||
pushopcode("REL", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
|
||||
pushopcode("OBJ", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
|
||||
pushopcode("PUT", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
|
||||
|
60
psuedo.cpp
60
psuedo.cpp
@ -12,11 +12,47 @@ CLASS::~CLASS()
|
||||
|
||||
}
|
||||
|
||||
|
||||
int CLASS::doDS(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
||||
{
|
||||
int res = 0;
|
||||
int32_t v = line.expr_value;
|
||||
if (line.eval_result!=0)
|
||||
{
|
||||
line.setError(errForwardRef);
|
||||
}
|
||||
else if ((v < 0) || ((a.PC.currentpc + v) >= 0x10000)) // no neg, or crossing bank bound
|
||||
{
|
||||
line.setError(errOverflow);
|
||||
}
|
||||
else
|
||||
{
|
||||
res = v;
|
||||
}
|
||||
return (res);
|
||||
}
|
||||
|
||||
int CLASS::doDUM(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
||||
{
|
||||
int res=-1;
|
||||
//bool isdend=((opinfo.opcode==P_DEND)?true:false);
|
||||
return(res);
|
||||
int res = 0;
|
||||
bool isdend = ((opinfo.opcode == P_DEND) ? true : false);
|
||||
|
||||
if (!isdend)
|
||||
{
|
||||
a.dumstart = 1;
|
||||
a.dumstartaddr = line.expr_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
a.dumstart = -1;
|
||||
if (a.PCstack.size() == 0)
|
||||
{
|
||||
line.setError(errBadDUMop);
|
||||
a.dumstart = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return (res);
|
||||
}
|
||||
|
||||
int CLASS::doLST(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
||||
@ -51,11 +87,25 @@ int CLASS::ProcessOpcode(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
|
||||
res = -1; // undefined p-op
|
||||
line.setError(errUnimplemented);
|
||||
break;
|
||||
case P_DS:
|
||||
res = doDS(a, line, opinfo);
|
||||
break;
|
||||
case P_DUM:
|
||||
case P_DEND:
|
||||
res=doDUM(a,line,opinfo);
|
||||
res = doDUM(a, line, opinfo);
|
||||
break;
|
||||
case P_ORG:
|
||||
a.PC.currentpc = line.expr_value;
|
||||
if (line.operand.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_SAV:
|
||||
a.savepath = line.operand;
|
||||
|
2
psuedo.h
2
psuedo.h
@ -10,6 +10,7 @@ enum
|
||||
P_SAV,
|
||||
P_DUM,
|
||||
P_DEND,
|
||||
P_DS,
|
||||
|
||||
P_MAX
|
||||
};
|
||||
@ -22,6 +23,7 @@ public:
|
||||
int ProcessOpcode(T65816Asm &a, MerlinLine &line, TSymbol &opinfo);
|
||||
int doLST(T65816Asm &a, MerlinLine &line, TSymbol &opinfo);
|
||||
int doDUM(T65816Asm &a, MerlinLine &line, TSymbol &opinfo);
|
||||
int doDS(T65816Asm &a, MerlinLine &line, TSymbol &opinfo);
|
||||
|
||||
|
||||
|
||||
|
92
qasm.cpp
92
qasm.cpp
@ -13,9 +13,8 @@ PAL_BASEAPP *PAL::appFactory(void)
|
||||
programOption PAL::appOptions[] =
|
||||
{
|
||||
{ "debug", "d", "enable debug info (repeat for more verbosity)", "", false, true},
|
||||
{ "config-file", "f", "load configuration data from a <file>", "file", false, false},
|
||||
{ "tomerlin", "m", "convert file to merlin format ", "", false, false},
|
||||
{ "reformat", "r", "convert to readable ascii", "", false, false},
|
||||
{ "config", "f", "load configuration data from a <file>", "<file>", false, false},
|
||||
{ "exec", "x", "execute a command", "<command>", false, false},
|
||||
|
||||
{ "", "", "", "", false, false}
|
||||
};
|
||||
@ -49,6 +48,12 @@ int CLASS::runCommandLineApp(void)
|
||||
int res = -1;
|
||||
|
||||
//LOG_DEBUG << "command line mode" << endl;
|
||||
if (commandargs.size()==0)
|
||||
{
|
||||
fprintf(stderr,"No files given (--help for help)\n\n");
|
||||
return(res);
|
||||
}
|
||||
|
||||
for (ArgVec::const_iterator it = commandargs.begin(); it != commandargs.end(); ++it)
|
||||
{
|
||||
Poco::File fn(*it);
|
||||
@ -59,53 +64,60 @@ int CLASS::runCommandLineApp(void)
|
||||
|
||||
std::string e = toUpper(path.getExtension());
|
||||
|
||||
int x = getInt("option.reformat", 0);
|
||||
std::string cmd = Poco::toUpper(getConfig("option.exec", "asm"));
|
||||
|
||||
if (x != 0)
|
||||
if (cmd.length() > 0)
|
||||
{
|
||||
res=0;
|
||||
t = new TMerlinConverter();
|
||||
if (t != NULL)
|
||||
if (cmd == "REFORMAT")
|
||||
{
|
||||
res = 0;
|
||||
t = new TMerlinConverter();
|
||||
if (t != NULL)
|
||||
{
|
||||
|
||||
t->init();
|
||||
std::string f = path.toString();
|
||||
t->processfile(f);
|
||||
t->process();
|
||||
t->complete();
|
||||
res = (t->errorct > 0) ? -1 : 0;
|
||||
|
||||
delete t;
|
||||
t = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (e == "S")
|
||||
{
|
||||
//logger().information("ASM: " + path.toString());
|
||||
t->init();
|
||||
std::string f = path.toString();
|
||||
t->processfile(f);
|
||||
t->process();
|
||||
t->complete();
|
||||
res = (t->errorct > 0) ? -1 : 0;
|
||||
|
||||
t = new T65816Asm();
|
||||
delete t;
|
||||
t = NULL;
|
||||
}
|
||||
}
|
||||
if (e == "LNK")
|
||||
else if (cmd == "ASM")
|
||||
{
|
||||
//logger().information("LNK: " + path.toString());
|
||||
t = new T65816Link();
|
||||
}
|
||||
if (t != NULL)
|
||||
{
|
||||
t->init();
|
||||
std::string f = path.toString();
|
||||
t->processfile(f);
|
||||
t->process();
|
||||
t->complete();
|
||||
res = (t->errorct > 0) ? -1 : 0;
|
||||
delete t;
|
||||
t = NULL;
|
||||
if (e == "S")
|
||||
{
|
||||
//logger().information("ASM: " + path.toString());
|
||||
|
||||
t = new T65816Asm();
|
||||
}
|
||||
if (e == "LNK")
|
||||
{
|
||||
//logger().information("LNK: " + path.toString());
|
||||
t = new T65816Link();
|
||||
}
|
||||
if (t != NULL)
|
||||
{
|
||||
t->init();
|
||||
std::string f = path.toString();
|
||||
t->processfile(f);
|
||||
t->process();
|
||||
t->complete();
|
||||
res = (t->errorct > 0) ? -1 : 0;
|
||||
delete t;
|
||||
t = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("not supported type\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("not supported type\n");
|
||||
fprintf(stderr,"Invalid command: <%s>\n\n", cmd.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
;lst on
|
||||
lst off
|
||||
*
|
||||
* main.s
|
||||
* Merlin32 Test
|
||||
@ -83,6 +83,7 @@ START
|
||||
|
||||
;adc (ZP,x)
|
||||
adc (0,x)
|
||||
|
||||
adc ($80,x)
|
||||
adc (_tmp,x)
|
||||
adc (_tmp+0,x)
|
||||
@ -162,7 +163,7 @@ myQuit
|
||||
|
||||
org ;return to ongoing address
|
||||
|
||||
|
||||
lst
|
||||
;Issue #16 (fadden) - Byte reference modifiers are ignored (no way to force DP)
|
||||
lda <$fff0 ;zp
|
||||
lda >$fff0 ;ABS (lo word)
|
||||
@ -182,6 +183,8 @@ myQuit
|
||||
lda #>$fff0 ;page
|
||||
lda #^$fff0 ;bank
|
||||
|
||||
lst off
|
||||
|
||||
lda $0008 ;ZP
|
||||
lda $08 ;ZP
|
||||
lda $ffff-$fff7 ;ZP
|
||||
@ -201,3 +204,5 @@ L00BC bit L00BC
|
||||
stx L00BC,y
|
||||
|
||||
//]XCODEEND ; Keep this at the end and put your code above this
|
||||
lst off
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user