making tests pass

This commit is contained in:
marketideas 2019-11-18 04:50:02 -08:00
parent 1c7a91e5eb
commit a80ff4a35c
5 changed files with 109 additions and 37 deletions

42
asm.cpp
View File

@ -1427,8 +1427,10 @@ void CLASS::initpass(void)
} }
mx = getInt("asm.startmx", mx);; mx = getInt("asm.startmx", mx);;
savepath = getConfig("option.objfile", ""); savepath = getConfig("option.objfile", "");
lastcarry = false;
relocatable = false; relocatable = false;
currentsym = &topSymbol; // this is the default symbol for :locals without a global above; currentsym = &topSymbol; // this is the default symbol for :locals without a global above;
currentsymstr = ""; currentsymstr = "";
@ -1485,6 +1487,14 @@ void CLASS::complete(void)
f.put(line.outbytes[i]); f.put(line.outbytes[i]);
} }
} }
if ((line.datafillct > 0) && ((line.flags & FLAG_INDUM) == 0))
{
for (uint32_t i = 0; i < line.datafillct; i++)
{
f.put(line.datafillbyte & 0xFF);
}
}
} }
} }
else else
@ -1618,6 +1628,35 @@ int CLASS::getAddrMode(MerlinLine & line)
if (i > 0) if (i > 0)
{ {
v = valEx.match(s, 0, 0); v = valEx.match(s, 0, 0);
if (v)
{
if (pass == 0)
{
// can only check on pass 0, because if the A"
// symbol is defined later, we will generate different
// bytes on the next pass
if (Poco::toUpper(oper) == "A") // check the whole operand, not just the expression
{
// SGQ
// Merlin32 supports the 'A" operand for immediate
// mode for opcodes like "ROR A". Problem is, Merlin16
// does not, and 'A' could be a lable.
TSymbol *sym = findSymbol("A");
if (sym == NULL)
{
line.flags |= FLAG_FORCEIMPLIED;
mode = syn_implied; // if the label hasn't been defined yet, assume Immediate addressing
goto out;
}
}
}
else if (line.flags & FLAG_FORCEIMPLIED)
{
mode = syn_implied;
goto out;
}
}
} }
} }
if (!v) if (!v)
@ -1646,7 +1685,7 @@ int CLASS::getAddrMode(MerlinLine & line)
} }
idx++; idx++;
} }
out:
if (mode == syn_none) if (mode == syn_none)
{ {
mode = syn_err; mode = syn_err;
@ -1828,6 +1867,7 @@ void CLASS::process(void)
int64_t value = -1; int64_t value = -1;
x = evaluate(line, line.operand_expr, value); x = evaluate(line, line.operand_expr, value);
line.eval_result = x;
if (x == 0) if (x == 0)
{ {
value &= 0xFFFFFFFF; value &= 0xFFFFFFFF;

6
asm.h
View File

@ -17,9 +17,10 @@
#define FLAG_DP 0x08 #define FLAG_DP 0x08
#define FLAG_BIGNUM 0x10 #define FLAG_BIGNUM 0x10
#define FLAG_INDUM 0x20 #define FLAG_INDUM 0x20
#define FLAG_FORCEIMPLIED 0x40
#define FLAG_FORCEADDRPRINT 0x0100 #define FLAG_FORCEADDRPRINT 0x0100
#define FLAG_NOLINEPRINT 0x2000 #define FLAG_NOLINEPRINT 0x0200
#define OP_A 0x0001 #define OP_A 0x0001
#define OP_XY 0x0002 #define OP_XY 0x0002
@ -197,7 +198,7 @@ public:
uint32_t addressmode; uint32_t addressmode;
uint32_t expr_value; uint32_t expr_value;
uint8_t expr_shift; // after an eval, this byte will reflect any shift code on expr (|^<>) uint8_t expr_shift; // after an eval, this byte will reflect any shift code on expr (|^<>)
uint32_t eval_result; // this is the error code from the evaluate routing (0 or neg) int32_t eval_result; // this is the error code from the evaluate routing (0 or neg)
uint32_t errorcode; uint32_t errorcode;
std::string errorText; std::string errorText;
@ -344,6 +345,7 @@ public:
uint32_t dumstartaddr; uint32_t dumstartaddr;
bool skiplist; // used if lst is on, but LST opcode turns it off bool skiplist; // used if lst is on, but LST opcode turns it off
uint32_t lineno; uint32_t lineno;
bool lastcarry;
std::string savepath; std::string savepath;
TSymbol *currentsym; TSymbol *currentsym;

View File

@ -747,6 +747,30 @@ int CLASS::doBYTE(MerlinLine & line, TSymbol & sym)
setOpcode(line, sym.opcode); setOpcode(line, sym.opcode);
line.outbytect = res; line.outbytect = res;
} }
// SGQ merlin32 apparently tracks XCE instructions when tracking MX status
// who know how they determine this. I am assuming the NEXT instruction
// after a SEC/CLC instruction must be an XCE
if (sym.opcode == 0x38) // SEC
{
lastcarry = true;
}
else if (sym.opcode == 0x18) // CLC
{
lastcarry = false;
}
else if (sym.opcode==0xFB) // XCE
{
if (trackrep)
{
if (lastcarry)
{
mx=0x03;
}
}
}
return (res); return (res);
} }

View File

@ -119,7 +119,7 @@ int CLASS::doLUP(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
TEvaluator eval(a); TEvaluator eval(a);
int64_t eval_result = 0; int64_t eval_value = 0;
uint8_t shift; uint8_t shift;
int lidx, len; int lidx, len;
int res = 0; int res = 0;
@ -135,16 +135,16 @@ int CLASS::doLUP(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
{ {
shift = 0; shift = 0;
eval_result = 0; eval_value = 0;
int x = eval.evaluate(line.operand_expr, eval_result, shift); int x = eval.evaluate(line.operand_expr, eval_value, shift);
a.LUPstack.push(a.curLUP); a.LUPstack.push(a.curLUP);
a.curLUP.lupoffset = len; a.curLUP.lupoffset = len;
a.curLUP.lupct = eval_result & 0xFFFF; // evaluate here a.curLUP.lupct = eval_value & 0xFFFF; // evaluate here
a.curLUP.luprunning++; a.curLUP.luprunning++;
if ((x < 0) || (eval_result <= 0) || (eval_result > 0x8000)) if ((x < 0) || (eval_value <= 0) || (eval_value > 0x8000))
{ {
// merlin just ignores LUP if the value is out of range // merlin just ignores LUP if the value is out of range
a.curLUP.lupct = 0; a.curLUP.lupct = 0;
@ -226,6 +226,9 @@ int CLASS::doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
//printf("DFB TOK1 : |%s|\n", oper.c_str()); //printf("DFB TOK1 : |%s|\n", oper.c_str());
line.eval_result=0; // since this is an data p-op, clear the global 'bad operand' flag
Poco::StringTokenizer tok(oper, ",", Poco::StringTokenizer::TOK_TRIM | Poco::StringTokenizer tok(oper, ",", Poco::StringTokenizer::TOK_TRIM |
Poco::StringTokenizer::TOK_IGNORE_EMPTY); Poco::StringTokenizer::TOK_IGNORE_EMPTY);
@ -264,7 +267,7 @@ int CLASS::doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
//printf("DFB TOK : |%s|\n", expr.c_str()); //printf("DFB TOK : |%s|\n", expr.c_str());
int64_t eval_result = 0; int64_t eval_value = 0;
uint8_t shift; uint8_t shift;
int r; int r;
uint8_t b; uint8_t b;
@ -277,9 +280,9 @@ int CLASS::doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
expr = Poco::trim(expr); expr = Poco::trim(expr);
} }
shift = 0; shift = 0;
eval_result = 0; eval_value = 0;
//printf("DFB EVAL: |%s|\n", expr.c_str()); //printf("DFB EVAL: |%s|\n", expr.c_str());
r = eval.evaluate(expr, eval_result, shift); r = eval.evaluate(expr, eval_value, shift);
if (r < 0) if (r < 0)
{ {
//printf("error %d\n",r); //printf("error %d\n",r);
@ -288,17 +291,17 @@ int CLASS::doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
line.setError(errBadEvaluation); line.setError(errBadEvaluation);
} }
} }
if (shift == '>')
{
eval_result = (eval_result) & 0xFF;
}
if (shift == '<') if (shift == '<')
{ {
eval_result = (eval_result >> 8) & 0xFF; eval_value = (eval_value) & 0xFF;
}
if (shift == '>')
{
eval_value = (eval_value >> 8) & 0xFF;
} }
else if ((shift == '^') || (shift == '|')) else if ((shift == '^') || (shift == '|'))
{ {
eval_result = (eval_result >> 16) & 0xFF; eval_value = (eval_value >> 16) & 0xFF;
} }
} }
@ -309,7 +312,7 @@ int CLASS::doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
{ {
for (i = 0; i < wordsize; i++) for (i = 0; i < wordsize; i++)
{ {
b = (eval_result >> (8 * i)) & 0xFF; b = (eval_value >> (8 * i)) & 0xFF;
line.outbytes.push_back(b); line.outbytes.push_back(b);
//printf("%02X\n",b); //printf("%02X\n",b);
} }
@ -319,7 +322,7 @@ int CLASS::doDATA(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
// big endian // big endian
for (i = 0; i < wordsize; i++) for (i = 0; i < wordsize; i++)
{ {
b = (eval_result >> ((wordsize - 1 - i) * 8)) & 0xFF; b = (eval_value >> ((wordsize - 1 - i) * 8)) & 0xFF;
line.outbytes.push_back(b); line.outbytes.push_back(b);
//printf("%02X\n",b); //printf("%02X\n",b);
} }
@ -341,7 +344,7 @@ int CLASS::doDS(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
{ {
line.setError(errForwardRef); line.setError(errForwardRef);
} }
else if ((v < 0) || ((a.PC.currentpc + v) >= 0x10000)) // no neg, or crossing bank bound else if ((v < 0) || (((a.PC.currentpc&0xFFFF) + v) >= 0x10000)) // no neg, or crossing bank bound
{ {
line.setError(errOverflow); line.setError(errOverflow);
} }
@ -349,7 +352,7 @@ int CLASS::doDS(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
{ {
res = v; res = v;
line.datafillbyte = line.eval_result & 0xFF; line.datafillbyte = 0x00;
line.datafillct = v; line.datafillct = v;
} }
@ -468,6 +471,8 @@ int CLASS::doHEX(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
std::string os = Poco::trim(line.operand); std::string os = Poco::trim(line.operand);
line.eval_result=0; // since this is an data p-op, clear the global 'bad operand' flag
uint32_t bytect = 0; uint32_t bytect = 0;
uint8_t b = 0; uint8_t b = 0;
uint8_t ct = 0; uint8_t ct = 0;
@ -538,6 +543,7 @@ int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
uint32_t ss = 0; uint32_t ss = 0;
std::vector<uint8_t> bytes; std::vector<uint8_t> bytes;
line.eval_result=0; // since this is an ASCII p-op, clear the global 'bad operand' flag
for ( uint32_t i = 0; i < os.length(); ++i ) for ( uint32_t i = 0; i < os.length(); ++i )
{ {
char c = os[i]; char c = os[i];

View File

@ -26,7 +26,7 @@ startmx=3
lst=true lst=true
; can be M6502, M65C02, M65816 ; can be M6502, M65C02, M65816
cpu=M65816 cpu=M65816
trackrep=false trackrep=true
allowduplicate=true allowduplicate=true
merlincompatible=true merlincompatible=true
symcolumns=3 symcolumns=3