Bläddra i källkod

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 år sedan
förälder
incheckning
f6dddaa380
3 ändrade filer med 190 tillägg och 13 borttagningar
  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 Visa fil

@@ -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 Visa fil

@@ -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 Visa fil

@@ -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)


Laddar…
Avbryt
Spara