Browse Source

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!
pull/10/head
Virgil Dupras 5 years ago
parent
commit
f6dddaa380
3 changed files with 190 additions and 13 deletions
  1. +152
    -0
      apps/zasm/tests/geninstrs.py
  2. +23
    -0
      apps/zasm/tests/runtests.sh
  3. +15
    -13
      apps/zasm/zasm.asm

+ 152
- 0
apps/zasm/tests/geninstrs.py View 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
- 0
apps/zasm/tests/runtests.sh View 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

+ 15
- 13
apps/zasm/zasm.asm View File

@@ -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…
Cancel
Save