qasm/psuedo.cpp

333 lines
5.8 KiB
C++
Raw Normal View History

#include "psuedo.h"
2019-11-15 13:09:41 +00:00
#include "eval.h"
#define CLASS TPsuedoOp
CLASS::CLASS()
{
}
CLASS::~CLASS()
{
}
2019-11-15 07:35:04 +00:00
constexpr unsigned int strhash(const char *str, int h = 0)
{
return !str[h] ? 5381 : (strhash(str, h + 1) * 33) ^ str[h];
}
int CLASS::doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
{
2019-11-15 11:40:35 +00:00
UNUSED(opinfo);
2019-11-15 13:09:41 +00:00
TEvaluator eval(a);
int i;
2019-11-15 07:35:04 +00:00
int outct = 0;
int wordsize = 2;
int endian = 0;
std::string oper = line.operand;
std::string op = Poco::toUpper(Poco::trim(line.opcode));
Poco::StringTokenizer tok(oper, ",", Poco::StringTokenizer::TOK_TRIM |
Poco::StringTokenizer::TOK_IGNORE_EMPTY);
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;
2019-11-15 13:09:41 +00:00
default:
2019-11-16 00:15:58 +00:00
wordsize = 0;
2019-11-15 13:09:41 +00:00
break;
2019-11-15 07:35:04 +00:00
}
for (auto itr = tok.begin(); itr != tok.end(); ++itr)
{
//printf("%s\n",(*itr).c_str());
//evaluate each of these strings, check for errors on pass 2
2019-11-15 13:09:41 +00:00
std::string expr = *itr;
int64_t eval_result = 0;
uint8_t shift;
int r;
uint8_t b;
2019-11-16 00:15:58 +00:00
shift = 0;
2019-11-15 13:09:41 +00:00
r = eval.evaluate(expr, eval_result, shift);
if (r < 0)
{
//printf("eval error %d |%s|\n", r,expr.c_str());
if (a.pass > 0)
{
line.setError(errBadEvaluation);
}
}
2019-11-16 00:15:58 +00:00
if (shift == '>')
2019-11-15 13:09:41 +00:00
{
2019-11-16 00:15:58 +00:00
eval_result = (eval_result) & 0xFF;
2019-11-15 13:09:41 +00:00
}
2019-11-16 00:15:58 +00:00
if (shift == '<')
2019-11-15 13:09:41 +00:00
{
2019-11-16 00:15:58 +00:00
eval_result = (eval_result >> 8) & 0xFF;
2019-11-15 13:09:41 +00:00
}
2019-11-16 00:15:58 +00:00
else if ((shift == '^') || (shift == '|'))
2019-11-15 13:09:41 +00:00
{
2019-11-16 00:15:58 +00:00
eval_result = (eval_result >> 16) & 0xFF;
2019-11-15 13:09:41 +00:00
}
2019-11-15 07:35:04 +00:00
outct += wordsize;
if (a.pass > 0)
{
if (!endian) // little endian
{
2019-11-15 13:09:41 +00:00
for (i = 0; i < wordsize; i++)
{
2019-11-16 00:15:58 +00:00
b = (eval_result >> (8 * i)) & 0xFF;
2019-11-15 13:09:41 +00:00
line.outbytes.push_back(b);
//printf("%02X\n",b);
}
2019-11-15 07:35:04 +00:00
}
else
{
// big endian
2019-11-15 13:09:41 +00:00
for (i = 0; i < wordsize; i++)
{
2019-11-16 00:15:58 +00:00
b = (eval_result >> ((wordsize - 1 - i) * 8)) & 0xFF;
2019-11-15 13:09:41 +00:00
line.outbytes.push_back(b);
//printf("%02X\n",b);
}
2019-11-15 07:35:04 +00:00
}
}
}
2019-11-15 13:09:41 +00:00
#if 0
2019-11-15 07:35:04 +00:00
// SGQ - remove when complete
2019-11-15 13:09:41 +00:00
line.datafillct = outct;
line.datafillbyte = 0xCA;
2019-11-15 07:35:04 +00:00
// ===============
2019-11-15 13:09:41 +00:00
#endif
2019-11-16 00:15:58 +00:00
line.outbytect = outct;
2019-11-15 07:35:04 +00:00
return (outct);
}
int CLASS::doDS(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
{
2019-11-15 11:40:35 +00:00
UNUSED(opinfo);
int res = 0;
int32_t v = line.expr_value;
2019-11-15 01:04:35 +00:00
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;
2019-11-13 23:45:39 +00:00
2019-11-15 07:35:04 +00:00
line.datafillbyte = line.eval_result & 0xFF;
line.datafillct = v;
#if 0
2019-11-15 01:04:35 +00:00
if (a.pass > 0)
2019-11-13 23:45:39 +00:00
{
2019-11-15 01:04:35 +00:00
for (int i = 0; i < v; i++)
2019-11-13 23:45:39 +00:00
{
line.outbytes.push_back(0x00);
}
2019-11-15 01:04:35 +00:00
line.outbytect = v;
2019-11-13 23:45:39 +00:00
}
2019-11-15 07:35:04 +00:00
#endif
2019-11-13 23:45:39 +00:00
}
return (res);
}
2019-11-13 04:32:10 +00:00
int CLASS::doDUM(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
{
2019-11-15 11:40:35 +00:00
UNUSED(opinfo);
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);
2019-11-13 04:32:10 +00:00
}
int CLASS::doLST(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
{
2019-11-15 11:40:35 +00:00
UNUSED(opinfo);
std::string s;
if (a.pass > 0)
{
s = Poco::toUpper(Poco::trim(line.operand));
if ((s == "") || (s == "ON") || (line.expr_value > 0))
{
//printf("ON\n");
a.skiplist = true;
a.listing = true;
}
else if ((s == "OFF") || (line.expr_value == 0))
{
//printf("OFF\n");
a.skiplist = true;
a.listing = false;
}
}
return (0);
}
2019-11-15 01:04:35 +00:00
int CLASS::doHEX(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
{
2019-11-15 11:40:35 +00:00
UNUSED(opinfo);
2019-11-15 13:09:41 +00:00
2019-11-15 01:04:35 +00:00
std::string os = Poco::toUpper(Poco::trim(line.operand));
2019-11-15 07:35:04 +00:00
uint32_t bytect = 0;
uint8_t b = 0;
uint8_t ct = 0;
2019-11-15 01:04:35 +00:00
for ( uint32_t i = 0; i < os.length(); ++i )
{
char c = os[i];
2019-11-15 07:35:04 +00:00
if ((c >= '0') && (c <= '9'))
2019-11-15 05:21:03 +00:00
{
2019-11-15 07:35:04 +00:00
c = c - '0';
2019-11-15 05:21:03 +00:00
}
2019-11-15 07:35:04 +00:00
else if ((c >= 'a') && (c <= 'f'))
2019-11-15 05:21:03 +00:00
{
2019-11-15 07:35:04 +00:00
c = c - 'a' + 10;
2019-11-15 05:21:03 +00:00
}
2019-11-15 07:35:04 +00:00
else if ((c >= 'A') && (c <= 'F'))
2019-11-15 05:21:03 +00:00
{
2019-11-15 07:35:04 +00:00
c = c - 'A' + 10;
2019-11-15 05:21:03 +00:00
}
2019-11-15 07:35:04 +00:00
else if (c == ',')
2019-11-15 01:04:35 +00:00
{
continue;
}
2019-11-15 05:21:03 +00:00
else
2019-11-15 01:04:35 +00:00
{
2019-11-16 00:15:58 +00:00
line.setError(errBadCharacter);
2019-11-15 05:21:03 +00:00
return 0;
2019-11-15 01:04:35 +00:00
}
// Got a good char, append to hex string and see if we've got a byte
2019-11-15 07:35:04 +00:00
switch (ct)
2019-11-15 01:04:35 +00:00
{
2019-11-15 05:21:03 +00:00
case 0:
2019-11-15 07:35:04 +00:00
b = (c << 4);
2019-11-15 05:21:03 +00:00
break;
case 1:
2019-11-15 07:35:04 +00:00
b |= c;
2019-11-15 05:21:03 +00:00
break;
2019-11-15 01:04:35 +00:00
}
2019-11-15 07:35:04 +00:00
ct = (ct + 1) & 0x01;
2019-11-15 05:21:03 +00:00
if (!ct)
2019-11-15 01:04:35 +00:00
{
2019-11-15 07:35:04 +00:00
if (a.pass > 0)
2019-11-15 01:04:35 +00:00
{
2019-11-15 05:21:03 +00:00
line.outbytes.push_back(b);
2019-11-15 01:04:35 +00:00
}
2019-11-15 07:35:04 +00:00
b = 0;
2019-11-15 05:21:03 +00:00
bytect++;
2019-11-15 01:04:35 +00:00
}
2019-11-16 00:15:58 +00:00
}
if (ct & 0x01) // we got an odd number of nibbles
{
line.setError(errMalformed);
bytect = 0;
2019-11-15 01:04:35 +00:00
}
2019-11-15 07:35:04 +00:00
line.outbytect = bytect;
2019-11-15 05:21:03 +00:00
//printf("bytect=%d\n",bytect);
return bytect;
2019-11-15 01:04:35 +00:00
}
int CLASS::ProcessOpcode(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
{
int res = 0;
switch (opinfo.opcode)
{
default:
res = -1; // undefined p-op
line.setError(errUnimplemented);
break;
case P_DS:
res = doDS(a, line, opinfo);
break;
2019-11-13 23:45:39 +00:00
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;
2019-11-13 04:32:10 +00:00
case P_DUM:
case P_DEND:
res = doDUM(a, line, opinfo);
break;
case P_ORG:
2019-11-15 01:04:35 +00:00
if (line.operand.length() > 0)
{
2019-11-15 01:04:35 +00:00
a.PC.orgsave = a.PC.currentpc;
a.PC.currentpc = line.expr_value;
2019-11-15 01:04:35 +00:00
line.startpc = line.expr_value;
}
else
{
a.PC.currentpc = a.PC.orgsave;
2019-11-15 01:04:35 +00:00
line.startpc = a.PC.orgsave;
}
break;
case P_SAV:
2019-11-15 01:04:35 +00:00
a.savepath = a.processFilename(line.operand, Poco::Path::current(), 0);
break;
case P_LST:
res = doLST(a, line, opinfo);
break;
2019-11-15 01:04:35 +00:00
case P_HEX:
res = doHEX(a, line, opinfo);
break;
2019-11-15 07:35:04 +00:00
case P_DATA:
res = doDATA(a, line, opinfo);
break;
}
return (res);
}