now able to push all test scripts to a directory that can be shared with gsplus, and files directly loaded into Merlin. Also support 'CHK' p-op to compare assemblies between the two

This commit is contained in:
Shawn Quick 2023-02-09 13:26:09 -08:00
parent 6571f2de07
commit e687507a3b
13 changed files with 223 additions and 110 deletions

View File

@ -35,14 +35,14 @@ cider:
-mkdir -p ./build
-cd ./build && cmake -DCIDER=1 -DCMAKE_BUILD_TYPE=DEBUG .. && $(MAKE) $S
distclean: clean
-rm -rf ./qasmout
-rm -rf ./m32out
-rm -rf ./libhfs/build ./nufxlib/build ./diskimg/build ./libpal/build
clean:
-rm -rf ./build *.2mg test.bin
-rm -rf ./build *.2mg test.bin *_Output.txt _FileInforma*.txt testdata/*.bin testdata/Finder.Data
-rm -rf ./log_qasm ./testdata1 test
depend:
-cd ./build && $(MAKE) depend

114
asm.cpp
View File

@ -150,15 +150,21 @@ void CLASS::print(uint32_t lineno)
pcol += printf(" ");
}
string addrmode=options->addrModeEnglish(addressmode).c_str();
pcol+=printf("%s ",addrmode.c_str());
pcol+=printf("/%04X ",flags);
while(pcol<50)
{
pcol+=printf(" ");
}
pcol+=printf("|");
char sc=shiftchar;
if (sc==0)
{
sc=' ';
}
pcol+=printf("%c |",sc);
}
@ -1624,57 +1630,75 @@ int CLASS::callOpCode(std::string op, MerlinLine &line)
}
}
if (line.addressmode == syn_imm)
if (line.addressmode == syn_imm) //page 83 merlin16 manual
{
//printf("immediate mode\n");
switch (line.expr_shift)
switch (line.shiftchar)
{
case '<':
//line.expr_value &= 0xFF;
break;
case '>':
line.expr_value >>= 8;
//line.expr_value >>= 8;
//line.expr_value &= 0xFFFF;
break;
case '^':
line.expr_value = (line.expr_value >> 16);
//line.expr_value = (line.expr_value >> 16);
//line.expr_value = (line.expr_value >> 16) & 0xFFFF;
break;
case '|':
case '|': // should never get here, handled in getAddrMode
//if (syntax == SYNTAX_MERLIN)
if (options.isMerlin())
{
line.setError(errBadLabel);
line.setError(errBadOperand);
line.expr_value = 0;
}
//line.shiftchar=0;
break;
}
}
else
{
switch (line.expr_shift)
switch (line.shiftchar) // page 84 Merlin16 manual
{
case '<':
line.flags |= FLAG_DP;
if (options.isMerlin32())
{
line.flags |= FLAG_DP;
line.expr_value &= 0xFF;
}
break;
case '>':
#if 0
if (options.isMerlin32())
{
// bug in M32 or not, do what it does
line.flags |= FLAG_FORCEABS;
//line.flags |= FLAG_FORCEABS;
line.flags |= FLAG_FORCELONG;
}
else
#endif
{
line.flags |= FLAG_FORCELONG;
// Merlin16+ uses this to force long addressing
// need to check Merlin16
if (!options.isMerlin()) // not merlin8
{
line.flags |= FLAG_FORCELONG;
}
}
break;
case '|':
line.flags |= FLAG_FORCEABS;
if ((!options.isMerlin32()) && (options.isMerlinCompat()))
{
line.flags |= FLAG_FORCEABS;
//line.shiftchar=0;
}
break;
case '^':
//line.flags |= FLAG_FORCELONG;
if (options.isMerlin32())
{
line.flags |= FLAG_DP;
line.expr_value >>= 16;
}
break;
}
}
@ -1737,7 +1761,7 @@ const std::string valExpression = "^([^\\[,();]+)$";
// this one looks for ]variables
const std::string varExpression = "([]]{1}[:0-9A-Z_a-z]{1}[0-9A-Z_a-z]*)";
const std::string varMACExpression = "([]]{1}[:0-9]{1}[0-9]*)";
const std::string macExpression = "([]]{1}[:0-9]{1}[0-9]*)";
// opcode check. emitted opcodes are compared against this
// table, and if the XC status doesn't meet the requirements
@ -1798,7 +1822,7 @@ void CLASS::initpass(void)
{
trackrep = false; // can't turn this ON in M16
}
else if (options.isQASM())
else if (options.isNative())
{
// we will allow this to be settable default off
trackrep = false;
@ -1920,30 +1944,6 @@ void CLASS::complete(void)
if (f.is_open())
{
#if 0
uint32_t lineno = 0;
uint32_t l = (uint32_t)lines.size();
while (lineno < l)
{
MerlinLine &line = lines.at(lineno++);
if ((line.outbytect > 0) && ((line.flags & FLAG_INDUM) == 0))
{
for (uint32_t i = 0; i < line.outbytect; 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
for (unsigned int i=0; i<outputbytes.size(); i++)
{
f.put(outputbytes[i]);
@ -1956,8 +1956,6 @@ void CLASS::complete(void)
writeerr=true;
}
f.close();
#endif
}
else
{
@ -1980,7 +1978,7 @@ void CLASS::complete(void)
TFileProcessor::complete();
if (listing)
if ((errorct==0) && (listing) && (!options.isQuiet()))
{
showSymbolTable(true);
showSymbolTable(false);
@ -2117,10 +2115,7 @@ int CLASS::getAddrMode(MerlinLine & line)
{
modified=true;
}
if (supportbar && shiftchar=='|')
{
line.flags|=FLAG_FORCELONG;
}
if (modified)
{
line.shiftchar=shiftchar;
@ -2142,6 +2137,17 @@ int CLASS::getAddrMode(MerlinLine & line)
line.strippedoperand=oper;
}
if (supportbar && shiftchar=='|')
{
//if ((options.isMerlin32()) || (options.isNative()))
if (options.isMerlin32())
{
// regular Merlin16/16+ seems to accept this character, but does NOT force long (bank) addressing
line.flags|=FLAG_FORCELONG;
}
//shiftchar=0; // don't process this as a shift because we only needed to set a flag to force long addressing
}
idx = 0;
RegularExpression valEx(valExpression, 0, true);
@ -2150,7 +2156,7 @@ int CLASS::getAddrMode(MerlinLine & line)
s = addrRegEx[idx].regEx;
if (s == "")
{
mode = syn_err;
mode = syn_err; // no more RegX left (nothing matched)
}
else
{
@ -2179,7 +2185,7 @@ int CLASS::getAddrMode(MerlinLine & line)
if (s != "")
{
if ((s != "^") && (s != "<") && (s != ">") && (s != "|"))
//if ((s != "^") && (s != "<") && (s != ">") && (s != "|"))
{
bool v = true;
if (mode == syn_abs)
@ -2234,7 +2240,7 @@ int CLASS::getAddrMode(MerlinLine & line)
ct++;
//printf("line expression=|%s|\n", s.c_str());
}
else
//else
{
// SGQ need to set a flag for a shift and process it after eval
}
@ -2334,7 +2340,7 @@ restart:
sym = findVariable(s, expand_macro.variables);
if (sym!=NULL)
{
RegularExpression varEx1(varMACExpression, 0, true);
RegularExpression varEx1(macExpression, 0, true);
Poco::RegularExpression::MatchVec mVec1;
try
{
@ -2596,7 +2602,7 @@ void CLASS::process(void)
x = parseOperand(line);
//if (x >= 0)
//{
line.addressmode = x;
line.addressmode = x;
//}
int64_t value = -1;

3
asm.h
View File

@ -388,9 +388,10 @@ class TPsuedoOp;
class T65816Asm : public TFileProcessor
{
protected:
std::vector<uint8_t> outputbytes;
public:
std::vector<uint8_t> outputbytes;
// options
bool casesen;
bool showmx;

View File

@ -654,7 +654,7 @@ int CLASS::doBase6502(MerlinLine & line, TSymbol & sym)
}
if ((m == syn_absx) || (m == syn_abs) || (m == syn_absy))
{
if ((line.flags & FLAG_FORCEABS) || (line.expr_value >= 0x100))
if ((line.flags & FLAG_FORCEABS) || (line.expr_value >= 0x100) )
{
bytelen++;
amode += 2;
@ -725,6 +725,7 @@ int CLASS::doBase6502(MerlinLine & line, TSymbol & sym)
{
if ((((line.flags & FLAG_DP) == 0) && ((line.flags & FLAG_FORCEDP) == 0))
|| (line.flags & FLAG_FORCEABS)
|| (m==syn_absy)
)
{
bytelen++;
@ -806,26 +807,58 @@ out:
}
res += bytelen;
//if (options.isMerlin32())
{
if ((op==0xB9) || (op==0x79) || (op==0xF9) || (op==0x99))
{
// there are 4 instructions that don't have (dp),y addressing so convert to (abs),
if (bytelen<2)
{
res++;
bytelen++;
}
}
}
if ((pass > 0) && (res > 0))
{
int pidx=0;
uint8_t *ptr=(uint8_t *)&line.expr_value;
setOpcode(line, op);
if (line.shiftchar!=0)
{
if (m==syn_imm)
{
switch(line.shiftchar)
{
case '>':
pidx+=1;
break;
case '^':
pidx+=2;
break;
}
}
else
{
switch(line.shiftchar)
{
case '>':
{
if ((line.flags&FLAG_FORCELONG)!=FLAG_FORCELONG)
{
pidx+=1;
}
}
break;
case '^':
{
}
break;
}
}
}
for (i = 0; i < (res - 1); i++)
{
line.outbytes.push_back(line.expr_value >> (8 * i));
if (pidx>3) // don't over index into 32 bit int
{
line.outbytes.push_back(0x00);
}
else
{
line.outbytes.push_back(ptr[pidx]);
pidx++;
}
}
line.outbytect = res;
}
@ -941,6 +974,7 @@ void CLASS::insertOpcodes(void)
pushopcode("PAG", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("TTL", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("SKP", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("PAU", P_PAU, 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", P_ASC, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
@ -961,12 +995,11 @@ void CLASS::insertOpcodes(void)
pushopcode("ELSE", P_DO, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("IF", P_DO, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("FIN", P_DO, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("CHK", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("CHK", P_CHK, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("ERR", P_ERR, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("KBD", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("LUP", P_LUP, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("--^", P_LUP, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("PAU", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("SW", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("USR", P_USR, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));
pushopcode("MAC", P_MAC, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO));

View File

@ -10,16 +10,29 @@
"1": "${QASM_BASE}"
},
{
"2": "0/object"
"2": "0/source"
},
{
"3": "1/macros"
"3": "0/object"
},
{
"4": "1/toolmacs"
"4": "1/macros"
},
{
"5": "../backup"
"5": "1/lib"
},
{
"6": "1/commands"
},
{
"7": "1/help"
},
{
"8": "object",
"volume": "0/merlin.2mg",
"size": "800K",
"format": "prodos",
"fileformat": "2mg"
}
]
},

View File

@ -777,6 +777,32 @@ out:
}
int CLASS::doPAU(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
{
UNUSED(opinfo);
return 0;
}
int CLASS::doCHK(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
{
int res=1;
UNUSED(opinfo);
if (a.pass>0)
{
uint8_t val=0;
for (uint64_t i=0;i<a.outputbytes.size();i++)
{
val^=a.outputbytes[i];
//printf("%02X ",val);
}
line.outbytes.push_back(val);
}
line.outbytect=res;
return (res);
}
// the handler for STR,STRL,REV,FLS,INV,DCI,ASC
int CLASS::doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
{
@ -1122,6 +1148,12 @@ int CLASS::ProcessOpcode(T65816Asm &a, MerlinLine &line, TSymbol &opinfo)
case P_USR:
res = doUSR(a, line, opinfo);
break;
case P_PAU:
res = doPAU(a, line, opinfo);
break;
case P_CHK:
res = doCHK(a, line, opinfo);
break;
}
return (res);

View File

@ -23,6 +23,8 @@ enum
P_MAC,
P_CAS,
P_USR,
P_PAU,
P_CHK,
P_MAX
};
@ -46,6 +48,9 @@ public:
int doASC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo);
int doMAC(T65816Asm &a, MerlinLine &line, TSymbol &opinfo);
int doUSR(T65816Asm &a, MerlinLine &line, TSymbol &opinfo);
int doPAU(T65816Asm &a, MerlinLine &line, TSymbol &opinfo);
int doCHK(T65816Asm &a, MerlinLine &line, TSymbol &opinfo);
};

View File

@ -367,7 +367,7 @@ public:
}
return(res);
}
bool isQASM(void)
bool isNative(void) // use this as we are running in 'native/qasm' mode so we can add special options
{
bool res=false;
if (language=="QASM")

View File

@ -5,6 +5,8 @@ TMPFILE=/tmp/qasm_out.txt
rm -f $TMPFILE
rm -rf $OUTDIR
rm -rf ./testdata/*.bin
mkdir -p $OUTDIR
SRC=`ls ./testdata | grep -E '^([0-9]+)(.*)\.[Ss]'`
@ -17,6 +19,7 @@ SRC=`ls ./testdata | grep -E '^([0-9]+)(.*)\.[Ss]'`
TOTAL=0
FAILCT=0
for S in $SRC ; do
rm -f $TMPFILE

View File

@ -8,9 +8,10 @@ fi
cp testdata/$FNAME.S /tmp
cd /tmp
OUTNAME=compare.txt
OUTNAME=/tmp/compare.txt
merlin32 -V ${FNAME}.S >/dev/null
cat ${FNAME}_Output.txt >OUTNAME
cat ${FNAME}_Output.txt
qasm ${FNAME}.S -t merlin32 -i M65816 -o 0/${FNAME}.S.bin
qasm ${FNAME}.S -t qasm -i M65816 -o 0/${FNAME}.S_q.bin

68
test.s
View File

@ -10,14 +10,9 @@
xc off
xc
xc
lst
;lst OFF
ZP equ $00
org $2000
lda $04,y
adc $04,y
sbc $04,y
sta $04,y
lda <$fff0 ;zp
lda >$fff0 ;ABS (lo word)
@ -29,31 +24,35 @@ ZP equ $00
lda >$fff0+24 ;ABS (lo word)
lda ^$fff0+24 ;ABS (hi word)
lda |$fff0+24 ;ABS (long in 65816 mode)
ldal $fff0+24 ;ABS (long in 65816 mode)
lda: $fff0+24 ;ABS (long in 65816 mode)
lda: $00
mx %11
lda #<$fff0 ;zp
lda #>$fff0 ;ABS (lo word)
lda #^$fff0 ;ABS (hi word)
lda #<$FFF0+$FFFF
lda #>$FFF0+$FFFF
lda #^$FFF0+$FFFF
mx %00
lda #<$fff0 ;zp
lda #>$fff0 ;ABS (lo word)
lda #^$fff0 ;ABS (hi word)
lda #<$FFF0+$FFFF
lda #>$FFF0+$FFFF
lda #^$FFF0+$FFFF
lst off
;end
ora ($00)
lda ($00)
bit: $FFFE,X
ror: $FFFE,X
ora #ZP
begin
;]m equ *
; lda begin
; lda ]m
;lst on
;end
;]m equ *
lda begin
;lda ]m
_mymac mac
]mac1 lda ]mac1
@ -64,7 +63,6 @@ _mymac mac
_ascmac mac
asc ]1,]2,8D
eom
;lst off
;var 'one';'two';'three'
justlable ;line with just a lable
start
@ -73,23 +71,31 @@ another lda #$00 ;line with everything
nop ;line with just opcode
_mymac *;1
_mymac *;2
_ascmac 'hello';'there'
lup 2
]m equ *
nop
lda ]m
bra ]m
--^
sav 2/test.bin
end
;_ascmac 'hello';'there'
;lup 2
;]m equ *
;nop
;lda ]m
;bra ]m
;--^
]1 nop
nop
;lst
bra ]1
;bra ]1
;typ $06
db 255
;lst off
]DPNOP equ $80
lda ]DPNOP
jsr DPCODE
rts
org $0080
DPCODE nop
lda DPCODE
lda |DPCODE
lda >DPCODE
lst
chk
lst off

1
testdata/test.S vendored Symbolic link
View File

@ -0,0 +1 @@
../test.s

12
tomerlin.sh Executable file
View File

@ -0,0 +1,12 @@
#!/bin/bash
rm -rf ./testdata1/*
cp -r ./testdata/*.S testdata1/
cd ./testdata1
X=`ls *.S`
for F in $X ; do
UFNAME=`echo $F | tr '[:lower:]' '[:upper:]'`
qasm -x format-merlin $F >${UFNAME}
rm -rf $F
done
ls