; The Z80 tester.
 
;
 
; Copyright (C) 2012 Patrik Rak (patrik@raxoft.cz)
 
;
 
; This source code is released under the MIT license, see included license.txt.
 
 
 
opsize      equ     4+postccf       ; Size of the tested instruction sequence.
 
datasize    equ     16              ; Size of the tested registers and data.
 
vecsize     equ     opsize+datasize ; Size of entire test vector.
 
 
 
test:       ld      (.spptr+1),sp
 
 
 
            if      maskflags       ; Keep mask for official flags.
 
            ld      a,(hl)          
 
            ld      (.flagptr+1),a
 
            endif
 
 
 
            inc     hl
 
 
 
            ld      de,vector       ; Init the test vector, counter and shifter.
 
            ld      bc,vecsize
 
            call    .copy
 
 
 
            add     hl,bc
 
 
 
            call    .copy
 
 
 
            call    .copy
 
            
 
            add     hl,bc
 
 
 
            ld      (.valptr+1),de
 
 
 
            inc     de
 
 
 
            call    .clear
 
 
 
            ld      (.maskptr+1),de
 
 
 
            xor     a
 
            ld      (de),a
 
            inc     de
 
 
 
            call    .copy
 
            
 
            ld      a,0x07          ; Make sure we get 0
 
            out     (0xfe),a        ; on MIC bit when doing IN.
 
 
 
            ld      a,0xa9          ; Set I,R,AF' to known values.
 
            ld      i,a
 
            ld      r,a
 
            or      a
 
            ex      af,af
 
 
 
            ld      bc,65535        ; Init CRC.
 
            ld      d,b
 
            ld      e,c
 
            exx
 
 
 
            ld      sp,data.regs
 
 
 
            ; Test vector sequence combinator.
 
 
 
.loop       ld      hl,counter
 
            ld      de,shifter+1
 
            ld      bc,vector
 
            
 
            macro   combine base,count,offset:0,last:1
 
            repeat  count
 
            ld      a,(bc)
 
            xor     (hl)
 
            ex      de,hl
 
            xor     (hl)
 
            ld      (base+offset+@#),a
 
            if      ( @# < count-1 ) | ! last
 
            inc     c
 
            inc     e
 
            inc     l
 
            endif
 
            endrepeat
 
            endm
 
 
 
            ld      a,(bc)
 
            xor     (hl)
 
            ex      de,hl
 
            xor     (hl)
 
            cp      0x76        ; Skip halt.
 
            jp      z,.next
 
            ld      (.opcode),a
 
            inc     c
 
            inc     e
 
            inc     l
 
 
 
            ld      a,(bc)
 
            xor     (hl)
 
            ex      de,hl
 
            xor     (hl)
 
            ld      (.opcode+1),a
 
            cp      0x76        ; Skip halt...
 
            jp      nz,.ok
 
            ld      a,(.opcode)
 
            and     0xdf        ; ... with IX/IY prefix.
 
            cp      0xdd
 
            jp      z,.next
 
.ok         inc     c
 
            inc     e
 
            inc     l
 
 
 
            combine .opcode,opsize-2,2,0
 
            combine data,datasize
 
 
 
            ; The test itself.
 
 
 
            pop     af
 
            pop     bc
 
            pop     de
 
            pop     hl
 
            pop     ix
 
            pop     iy
 
            ld      sp,(data.sp)
 
 
 
.opcode     ds      opsize
 
.continue
 
            if      memptr
 
            ld      hl,data
 
            bit     0,(hl)
 
            endif
 
 
 
            ld      (data.sp),sp
 
            ld      sp,data.regstop
 
            push    iy
 
            push    ix
 
            push    hl
 
            push    de
 
            push    bc
 
            push    af
 
            
 
            ld      hl,data
 
 
 
            if      maskflags
 
            ld      a,(hl)
 
.flagptr    and     0xff
 
 
 
            if      ! onlyflags
 
            ld      (hl),a
 
            endif
 
 
 
            endif
 
 
 
            ; CRC update.
 
 
 
            if      ! onlyflags
 
            ld      b,datasize
 
            endif
 
 
 
            if      ! ( onlyflags & maskflags )
 
.crcloop    ld      a,(hl)
 
            endif
 
 
 
            exx
 
            xor     e
 
 
 
            ld      l,a
 
            ld      h,crctable/256
 
            
 
            ld      a,(hl)
 
            xor     d
 
            ld      e,a
 
            inc     h
 
 
 
            ld      a,(hl)
 
            xor     c
 
            ld      d,a
 
            inc     h
 
 
 
            ld      a,(hl)
 
            xor     b
 
            ld      c,a
 
            inc     h
 
 
 
            ld      b,(hl)
 
 
 
            exx
 
 
 
            if      ! onlyflags
 
            inc     hl
 
            djnz    .crcloop
 
            endif
 
 
 
            ; Multibyte counter with arbitrary bit mask.
 
 
 
.next       ld      hl,countmask
 
            ld      de,counter
 
            ld      b,vecsize
 
.countloop  ld      a,(de)
 
            or      a
 
            jr      z,.countnext
 
            dec     a
 
            and     (hl)
 
            ld      (de),a
 
            jp      .loop
 
.countnext  ld      a,(hl)
 
            ld      (de),a
 
            inc     l
 
            inc     e
 
            djnz    .countloop
 
 
 
            ; Multibyte shifter with arbitrary bit mask.
 
 
 
.maskptr    ld      hl,shiftmask
 
.valptr     ld      de,shifter
 
            ld      a,(de)
 
            add     a,a
 
            neg
 
            add     (hl)
 
            xor     (hl)
 
            and     (hl)
 
            ld      (de),a
 
            jp      nz,.loop
 
.shiftloop  inc     l
 
            inc     e
 
            ld      a,e
 
            cp      shiftend % 256
 
            jr      z,.exit
 
            ld      a,(hl)
 
            dec     a
 
            xor     (hl)
 
            and     (hl)
 
            jr      z,.shiftloop
 
            ld      (de),a
 
            ld      (.maskptr+1),hl
 
            ld      (.valptr+1),de
 
            jp      .loop
 
 
 
.exit       exx
 
.spptr      ld      sp,0
 
            ret
 
 
 
            ; Misc helper routines.
 
 
 
.copy       push    hl
 
            push    bc
 
            ldir
 
            pop     bc
 
            pop     hl
 
            ret
 
 
 
.clear      push    hl
 
            push    bc
 
            ld      h,d
 
            ld      l,e
 
            ld      (hl),0
 
            inc     de
 
            dec     bc
 
            ldir
 
            pop     bc
 
            pop     hl
 
            ret
 
 
 
            align   256
 
 
 
            include crctab.asm
 
 
 
; If this moves from 0x8800, all tests which use this address
 
; will need to have their CRCs updated, so don't move it.
 
 
 
            align   256
 
data
 
.regs       ds      datasize-4
 
.regstop
 
.mem        ds      2
 
.sp         ds      2
 
 
 
.jump
 
            if      postccf
 
            ccf
 
            else
 
            inc     bc
 
            endif
 
            jp      test.continue
 
 
 
; This entire workspace must be kept within single 256 byte page.
 
 
 
vector      ds      vecsize
 
counter     ds      vecsize
 
countmask   ds      vecsize
 
shifter     ds      1+vecsize
 
shiftend
 
shiftmask   ds      1+vecsize
 
 
 
; EOF ;