This commit is contained in:
marketideas 2019-11-17 22:16:00 -08:00
parent 09482611cf
commit 1c7a91e5eb
3 changed files with 245 additions and 93 deletions

42
asm.cpp
View File

@ -319,9 +319,12 @@ void CLASS::set(std::string line)
int i = 0;
int x;
char c, delim;
bool isascii;
std::string opupper;
clear();
isascii = false;
delim = 0;
//printf("line: |%s|\n", line.c_str());
while (i < l)
@ -380,6 +383,39 @@ void CLASS::set(std::string line)
}
else
{
// SGQ
// this is bad, but the only way I currently know how to do this.
// the problem is, is that the ASCII generating psuedo-ops in Merlin
// use any char > space and less than apostrophe, and > apostrophe
// as delimiters.
// however, those characters also contain valid opcode expression characters
// so we see a character here, it looks like a delim, and we keep reading to EOL
// which might include a comment. All of that, then goes into the operand, and
// comments cause errors on evaluation.
// So, at this point in the code, we must determine if the opcode is one of our
// ascii psuedo-ops and treat the first char as a delim.
// otherwise, we must parse the operand as an express.
// this parser should know NOTHING about what the code does...but it needs to in
// this case.
opupper = Poco::toUpper(opcode);
if (opupper.length() > 0)
{
if (
(opupper == "STRL")
|| (opupper == "STR")
|| (opupper == "ASC")
|| (opupper == "DCI")
|| (opupper == "INV")
|| (opupper == "FLS")
|| (opupper == "REV")
)
{
isascii = true;
}
}
state = 4;
}
break;
@ -392,7 +428,7 @@ void CLASS::set(std::string line)
else if (c > ' ')
{
operand += c;
if (c <= '/')
if ((c <= '/') && (isascii))
{
delim = c;
state = 8;
@ -441,11 +477,11 @@ void CLASS::set(std::string line)
else if (c == delim)
{
operand += c;
state=5;
state = 5;
}
else
{
operand+=c;
operand += c;
}
break;
}

View File

@ -805,11 +805,12 @@ void CLASS::insertOpcodes(void)
pushopcode("SKP", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("TR", P_TR, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("ASC", P_ASC, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("DCI", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("INV", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("FLS", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("REV", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("STR", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("DCI", P_ASC, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("INV", P_ASC, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("FLS", P_ASC, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("REV", P_ASC, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("STR", P_ASC, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("STRL", P_ASC, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("DA", P_DATA, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("DW", P_DATA, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("DDB", P_DATA, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));

View File

@ -282,7 +282,7 @@ int CLASS::doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
r = eval.evaluate(expr, eval_result, shift);
if (r < 0)
{
//printf("error\n");
//printf("error %d\n",r);
if (a.pass > 0)
{
line.setError(errBadEvaluation);
@ -481,7 +481,7 @@ int CLASS::doHEX(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
continue;
}
char hv = hexVal(c);
if( hv < 0 )
if ( hv < 0 )
{
line.setError(errIllegalCharOperand);
bytect = 0;
@ -520,37 +520,51 @@ out:
return bytect;
}
// the handler for STR,STRL,REV,FLS,INV,DCI,ASC
int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
{
UNUSED(opinfo);
std::string os = line.operand;
std::string op = Poco::toUpper(line.opcode);
uint8_t lastdelimbyte = 0x00;
uint8_t firstdelim = 0xFF;
uint32_t bytect = 0;
uint8_t b = 0;
uint8_t b1;
uint8_t ct = 0;
char delimiter = 0;
uint32_t ss = 0;
std::vector<uint8_t> bytes;
for ( uint32_t i = 0; i < os.length(); ++i )
{
char c = os[i];
// are we inside a delimited string?
if( delimiter )
if ( delimiter )
{
if( c == delimiter )
if ( c == delimiter )
{
bytect += (i - ss);
if( a.pass > 0 )
if ( a.pass > 0 )
{
for( ; ss < i; ++ss )
for ( ; ss < i; ++ss )
{
c = os[ss];
if( delimiter >= '\'' )
if ( delimiter >= '\'' )
{
c &= 0x7F;
}
else
{
c |= 0x80;
line.outbytes.push_back(c);
}
lastdelimbyte = c;
bytes.push_back(c);
//line.outbytes.push_back(c);
}
}
@ -562,17 +576,25 @@ int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
else
{
// No, check for seperator characters
if( c == ',' || c == ' ' )
if ( c == ',' || c == ' ' )
{
continue;
}
// Is this a hex char?
char hv = hexVal(c);
if( hv < 0 )
if ( hv < 0 )
{
// if not a hex value, then consider the character to be the string delimiter
delimiter = c;
if (firstdelim == 0xFF)
{
firstdelim = c;
}
else if (delimiter != firstdelim)
{
line.setError(errIllegalCharOperand);
}
ss = i + 1;
continue;
}
@ -592,7 +614,8 @@ int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
{
if (a.pass > 0)
{
line.outbytes.push_back(b);
bytes.push_back(b);
//line.outbytes.push_back(b);
}
b = 0;
bytect++;
@ -600,11 +623,103 @@ int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
}
}
if( delimiter || (ct & 0x01) ) // error w/unterminated string or we got an odd number of nibbles in hex value
if ( delimiter || (ct & 0x01) ) // error w/unterminated string or we got an odd number of nibbles in hex value
{
line.setError(errBadOperand);
bytect = 0;
}
else // now figure out what psuedo op we are and transfer the data to outbytect
{
uint32_t i;
bool reverse = false;
bool dci = false;
uint8_t andval = 0xFF;
uint8_t orval = 0x00;
uint8_t addlen = 0;
uint8_t firstbyte = 0x00;
uint32_t truebytect = bytes.size();
const char *ptr = (const char *)op.c_str();
//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;
}
if (a.pass > 0)
{
for (i = 0; i < addlen; i++) // if a string, push length
{
line.outbytes.push_back((truebytect >> (i * 8)) & 0xFF);
}
for (i = 0; i < truebytect; i++)
{
if (reverse)
{
b = bytes[bytect - i - 1];
}
else
{
b = bytes[i];
}
if (!i)
{
firstbyte = b;
}
b1 = b & 0x7F;
if ((andval!=0xFF) || (orval!=0x00))
b=b1;
if ((b1 < 0x60))
{
b &= andval; // strip whatever bits needed to flash or invert
b |= orval;
}
if ((dci) && (i == (truebytect - 1)))
{
// this one might be a bug. I am going to compare the first byte in the string for
// bit seven, and invert it on this byte. The confusion arises because this text string
// could have high ASCII, but low HEX values.
if (firstbyte < 0x80)
{
b |= 0x80;
}
else
{
b &= 0x7F;
}
}
line.outbytes.push_back(b);
}
}
bytect = bytect + addlen;
}
//printf("XXX bytect=%d bytes.size()=%zu\n",bytect,bytes.size());
line.outbytect = bytect;
return bytect;