zasm: add automated tests and fix a bunch of bugs
A python script generates all possibilities for all supported instructions and compare zasm output with scas. After having fixed a couple of bugs, all tests pass!
This commit is contained in:
parent
8ce528c752
commit
f6dddaa380
152
apps/zasm/tests/geninstrs.py
Executable file
152
apps/zasm/tests/geninstrs.py
Executable file
@ -0,0 +1,152 @@
|
||||
#!/usr/bin/python
|
||||
# Generate almost all possible combination for instructions from instruction
|
||||
# tables
|
||||
|
||||
argspecTbl = {
|
||||
'A': "A",
|
||||
'B': "B",
|
||||
'C': "C",
|
||||
'D': "D",
|
||||
'E': "E",
|
||||
'H': "H",
|
||||
'L': "L",
|
||||
'h': "HL",
|
||||
'l': "(HL)",
|
||||
'd': "DE",
|
||||
'e': "(DE)",
|
||||
'b': "BC",
|
||||
'c': "(BC)",
|
||||
'a': "AF",
|
||||
'f': "AF'",
|
||||
'x': "(IX)",
|
||||
'y': "(IY)",
|
||||
's': "SP",
|
||||
'p': "(SP)",
|
||||
'Z': "Z",
|
||||
'z': "NZ",
|
||||
'=': "NC",
|
||||
'+': "P",
|
||||
'-': "M",
|
||||
'1': "PO",
|
||||
'2': "PE",
|
||||
}
|
||||
|
||||
argGrpTbl = {
|
||||
chr(0x01): "bdha",
|
||||
chr(0x02): "ZzC=",
|
||||
chr(0x03): "bdhs",
|
||||
chr(0x0a): "ZzC=+-12",
|
||||
chr(0x0b): "BCDEHLA",
|
||||
}
|
||||
|
||||
instrTBlPrimary = [
|
||||
("ADC", 'A', 'l', 0, 0x8e),
|
||||
("ADC", 'A', 0xb, 0, 0b10001000),
|
||||
("ADC", 'A', 'n', 0, 0xce ),
|
||||
("ADD", 'A', 'l', 0, 0x86 ),
|
||||
("ADD", 'A', 0xb, 0, 0b10000000),
|
||||
("ADD", 'A', 'n', 0, 0xc6 ),
|
||||
("ADD", 'h', 0x3, 4, 0b00001001 ),
|
||||
("AND", 'l', 0, 0, 0xa6 ),
|
||||
("AND", 0xb, 0, 0, 0b10100000),
|
||||
("AND", 'n', 0, 0, 0xe6 ),
|
||||
("CALL", 0xa, 'N', 3, 0b11000100),
|
||||
("CALL", 'N', 0, 0, 0xcd ),
|
||||
("CCF", 0, 0, 0, 0x3f ),
|
||||
("CP", 'l', 0, 0, 0xbe ),
|
||||
("CP", 0xb, 0, 0, 0b10111000),
|
||||
("CP", 'n', 0, 0, 0xfe ),
|
||||
("CPL", 0, 0, 0, 0x2f ),
|
||||
("DAA", 0, 0, 0, 0x27 ),
|
||||
("DI", 0, 0, 0, 0xf3 ),
|
||||
("DEC", 'l', 0, 0, 0x35 ),
|
||||
("DEC", 0xb, 0, 3, 0b00000101),
|
||||
("DEC", 0x3, 0, 4, 0b00001011),
|
||||
("DJNZ", 'n', 0,0x80, 0x10 ),
|
||||
("EI", 0, 0, 0, 0xfb ),
|
||||
("EX", 'p', 'h', 0, 0xe3 ),
|
||||
("EX", 'a', 'f', 0, 0x08 ),
|
||||
("EX", 'd', 'h', 0, 0xeb ),
|
||||
("EXX", 0, 0, 0, 0xd9 ),
|
||||
("HALT", 0, 0, 0, 0x76 ),
|
||||
("IN", 'A', 'm', 0, 0xdb ),
|
||||
("INC", 'l', 0, 0, 0x34 ),
|
||||
("INC", 0xb, 0, 3, 0b00000100),
|
||||
("INC", 0x3, 0, 4, 0b00000011),
|
||||
("JP", 'l', 0, 0, 0xe9 ),
|
||||
("JP", 'N', 0, 0, 0xc3 ),
|
||||
("JR", 'n', 0,0x80, 0x18 ),
|
||||
("JR",'C','n',0x80, 0x38 ),
|
||||
("JR",'=','n',0x80, 0x30 ),
|
||||
("JR",'Z','n',0x80, 0x28 ),
|
||||
("JR",'z','n',0x80, 0x20 ),
|
||||
("LD", 'c', 'A', 0, 0x02 ),
|
||||
("LD", 'e', 'A', 0, 0x12 ),
|
||||
("LD", 'A', 'c', 0, 0x0a ),
|
||||
("LD", 'A', 'e', 0, 0x0a ),
|
||||
("LD", 's', 'h', 0, 0x0a ),
|
||||
("LD", 'l', 0xb, 0, 0b01110000),
|
||||
("LD", 0xb, 'l', 3, 0b01000110),
|
||||
("LD", 'l', 'n', 0, 0x36 ),
|
||||
("LD", 0xb, 'n', 3, 0b00000110),
|
||||
("LD", 0x3, 'N', 4, 0b00000001),
|
||||
("LD", 'M', 'A', 0, 0x32 ),
|
||||
("LD", 'A', 'M', 0, 0x3a ),
|
||||
("LD", 'M', 'h', 0, 0x22 ),
|
||||
("LD", 'h', 'M', 0, 0x2a ),
|
||||
("NOP", 0, 0, 0, 0x00 ),
|
||||
("OR", 'l', 0, 0, 0xb6 ),
|
||||
("OR", 0xb, 0, 0, 0b10110000),
|
||||
("OUT", 'm', 'A', 0, 0xd3 ),
|
||||
("POP", 0x1, 0, 4, 0b11000001),
|
||||
("PUSH", 0x1, 0, 4, 0b11000101),
|
||||
("RET", 0xa, 0, 3, 0b11000000),
|
||||
("RET", 0, 0, 0, 0xc9 ),
|
||||
("RLA", 0, 0, 0, 0x17 ),
|
||||
("RLCA", 0, 0, 0, 0x07 ),
|
||||
("RRA", 0, 0, 0, 0x1f ),
|
||||
("RRCA", 0, 0, 0, 0x0f ),
|
||||
("SBC", 'A', 'l', 0, 0x9e ),
|
||||
("SBC", 'A', 0xb, 0, 0b10011000),
|
||||
("SCF", 0, 0, 0, 0x37 ),
|
||||
("SUB", 'A', 'l', 0, 0x96 ),
|
||||
("SUB", 'A', 0xb, 0, 0b10010000),
|
||||
("SUB", 'n', 0, 0, 0xd6 ),
|
||||
("XOR", 'l', 0, 0, 0xae ),
|
||||
("XOR", 0xb, 0, 0, 0b10101000),
|
||||
]
|
||||
|
||||
def genargs(argspec):
|
||||
if not argspec:
|
||||
return ''
|
||||
if not isinstance(argspec, str):
|
||||
argspec = chr(argspec)
|
||||
if argspec in 'nmNM':
|
||||
bits = 16 if argspec in 'NM' else 8
|
||||
nbs = [str(1 << i) for i in range(bits)]
|
||||
if argspec in 'mM':
|
||||
nbs = [f"({n})" for n in nbs]
|
||||
return nbs
|
||||
if argspec in argspecTbl:
|
||||
return [argspecTbl[argspec]]
|
||||
grp = argGrpTbl[argspec]
|
||||
return [argspecTbl[a] for a in grp]
|
||||
|
||||
|
||||
def main():
|
||||
for n, a1, a2, f, op in instrTBlPrimary:
|
||||
args1 = genargs(a1)
|
||||
if args1:
|
||||
for arg1 in args1:
|
||||
args2 = genargs(a2)
|
||||
if args2:
|
||||
for arg2 in args2:
|
||||
print(f"{n} {arg1}, {arg2}")
|
||||
else:
|
||||
print(f"{n} {arg1}")
|
||||
else:
|
||||
print(n)
|
||||
pass
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
23
apps/zasm/tests/runtests.sh
Executable file
23
apps/zasm/tests/runtests.sh
Executable file
@ -0,0 +1,23 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
TMPFILE=$(mktemp)
|
||||
SCAS=scas
|
||||
ZASM=../emul/zasm
|
||||
|
||||
./geninstrs.py | \
|
||||
while read line; do
|
||||
echo $line | tee "${TMPFILE}"
|
||||
EXPECTED=$($SCAS -o - "${TMPFILE}" | xxd)
|
||||
ACTUAL=$(echo $line | $ZASM | xxd)
|
||||
if [ "$ACTUAL" == "$EXPECTED" ]; then
|
||||
echo ok
|
||||
else
|
||||
echo actual
|
||||
echo $ACTUAL
|
||||
echo expected
|
||||
echo $EXPECTED
|
||||
exit 1
|
||||
fi
|
||||
done
|
@ -223,7 +223,7 @@ toWord:
|
||||
readArg:
|
||||
push de
|
||||
ld de, tmpBuf
|
||||
ld a, 6
|
||||
ld a, 8
|
||||
call readWord
|
||||
push hl
|
||||
ld hl, tmpBuf
|
||||
@ -363,6 +363,7 @@ findInGroup:
|
||||
jr z, .specialGroupCC
|
||||
cp 0xb
|
||||
jr z, .specialGroupABCDEHL
|
||||
jr nc, .notfound ; > 0xb? not a group
|
||||
pop af
|
||||
; regular group
|
||||
push de
|
||||
@ -660,7 +661,8 @@ argspecTbl:
|
||||
; we also need argspecs for the condition flags
|
||||
.db 'Z', "Z", 0, 0, 0
|
||||
.db 'z', "NZ", 0, 0
|
||||
.db '^', "C", 0, 0, 0
|
||||
; C is in conflict with the C register. The situation is ambiguous, but
|
||||
; doesn't cause actual problems.
|
||||
.db '=', "NC", 0, 0
|
||||
.db '+', "P", 0, 0, 0
|
||||
.db '-', "M", 0, 0, 0
|
||||
@ -682,11 +684,11 @@ argspecTbl:
|
||||
; The table below is in order, starting with group 0x01
|
||||
argGrpTbl:
|
||||
.db "bdha" ; 0x01
|
||||
.db "Zz^=" ; 0x02
|
||||
.db "ZzC=" ; 0x02
|
||||
.db "bdhs" ; 0x03
|
||||
|
||||
argGrpCC:
|
||||
.db "Zz^=+-12" ; 0xa
|
||||
.db "zZ=C12+-" ; 0xa
|
||||
argGrpABCDEHL:
|
||||
.db "BCDEHL_A" ; 0xb
|
||||
|
||||
@ -705,15 +707,15 @@ argGrpABCDEHL:
|
||||
; decreased by 2 (djnz, jr).
|
||||
|
||||
instrTBlPrimary:
|
||||
.db "ADC", 0, 'A', 'h', 0, 0x8e ; ADC A, HL
|
||||
.db "ADC", 0, 'A', 'l', 0, 0x8e ; ADC A, (HL)
|
||||
.db "ADC", 0, 'A', 0xb, 0, 0b10001000 ; ADC A, r
|
||||
.db "ADC", 0, 'A', 'n', 0, 0xce ; ADC A, n
|
||||
.db "ADD", 0, 'A', 'h', 0, 0x86 ; ADD A, HL
|
||||
.db "ADD", 0, 'A', 'l', 0, 0x86 ; ADD A, (HL)
|
||||
.db "ADD", 0, 'A', 0xb, 0, 0b10000000 ; ADD A, r
|
||||
.db "ADD", 0, 'A', 'n', 0, 0xc6 ; ADD A, n
|
||||
.db "ADD", 0, 'h', 0x3, 4, 0b00001001 ; ADD HL, ss
|
||||
.db "AND", 0, 'l', 0, 0, 0xa6 ; AND (HL)
|
||||
.db "AND", 0, 0xa, 0, 0, 0b10100000 ; AND r
|
||||
.db "AND", 0, 0xb, 0, 0, 0b10100000 ; AND r
|
||||
.db "AND", 0, 'n', 0, 0, 0xe6 ; AND n
|
||||
.db "CALL", 0xa, 'N', 3, 0b11000100 ; CALL cc, NN
|
||||
.db "CALL", 'N', 0, 0, 0xcd ; CALL NN
|
||||
@ -741,15 +743,15 @@ instrTBlPrimary:
|
||||
.db "JP",0,0, 'l', 0, 0, 0xe9 ; JP (HL)
|
||||
.db "JP",0,0, 'N', 0, 0, 0xc3 ; JP NN
|
||||
.db "JR",0,0, 'n', 0,0x80, 0x18 ; JR e
|
||||
.db "JR",0,0,'^','n',0x80, 0x38 ; JR C, e
|
||||
.db "JR",0,0,'C','n',0x80, 0x38 ; JR C, e
|
||||
.db "JR",0,0,'=','n',0x80, 0x30 ; JR NC, e
|
||||
.db "JR",0,0,'Z','n',0x80, 0x28 ; JR Z, e
|
||||
.db "JR",0,0,'z','n',0x80, 0x20 ; JR NZ, e
|
||||
.db "LD",0,0, 'c', 'A', 0, 0x02 ; LD (BC), A
|
||||
.db "LD",0,0, 'e', 'A', 0, 0x12 ; LD (DE), A
|
||||
.db "LD",0,0, 'A', 'c', 0, 0x0a ; LD A, (BC)
|
||||
.db "LD",0,0, 'A', 'e', 0, 0x0a ; LD A, (DE)
|
||||
.db "LD",0,0, 's', 'h', 0, 0x0a ; LD SP, HL
|
||||
.db "LD",0,0, 'A', 'e', 0, 0x1a ; LD A, (DE)
|
||||
.db "LD",0,0, 's', 'h', 0, 0xf9 ; LD SP, HL
|
||||
.db "LD",0,0, 'l', 0xb, 0, 0b01110000 ; LD (HL), r
|
||||
.db "LD",0,0, 0xb, 'l', 3, 0b01000110 ; LD r, (HL)
|
||||
.db "LD",0,0, 'l', 'n', 0, 0x36 ; LD (HL), n
|
||||
@ -765,16 +767,16 @@ instrTBlPrimary:
|
||||
.db "OUT", 0, 'm', 'A', 0, 0xd3 ; OUT (n), A
|
||||
.db "POP", 0, 0x1, 0, 4, 0b11000001 ; POP qq
|
||||
.db "PUSH", 0x1, 0, 4, 0b11000101 ; PUSH qq
|
||||
.db "RET", 0, 0xa, 0, 3, 0b11000000 ; RET cc
|
||||
.db "RET", 0, 0, 0, 0, 0xc9 ; RET
|
||||
.db "RET", 0, 0xa, 0, 3, 0b11000000 ; RET cc
|
||||
.db "RLA", 0, 0, 0, 0, 0x17 ; RLA
|
||||
.db "RLCA", 0, 0, 0, 0x07 ; RLCA
|
||||
.db "RRA", 0, 0, 0, 0, 0x1f ; RRA
|
||||
.db "RRCA", 0, 0, 0, 0x0f ; RRCA
|
||||
.db "SBC", 0, 'A', 'h', 0, 0x9e ; SBC A, HL
|
||||
.db "SBC", 0, 'A', 'l', 0, 0x9e ; SBC A, (HL)
|
||||
.db "SBC", 0, 'A', 0xb, 0, 0b10011000 ; SBC A, r
|
||||
.db "SCF", 0, 0, 0, 0, 0x37 ; SCF
|
||||
.db "SUB", 0, 'A', 'h', 0, 0x96 ; SUB A, HL
|
||||
.db "SUB", 0, 'A', 'l', 0, 0x96 ; SUB A, (HL)
|
||||
.db "SUB", 0, 'A', 0xb, 0, 0b10010000 ; SUB A, r
|
||||
.db "SUB", 0, 'n', 0, 0, 0xd6 ; SUB n
|
||||
.db "XOR", 0, 'l', 0, 0, 0xae ; XOR (HL)
|
||||
|
Loading…
Reference in New Issue
Block a user