; Memory Test
; Two kind of tests are executed
; 1. Pattern test using bit-patterns defined in mempatt where memory is filled
;    with this patterns and tested for correctness
; 2. Pseudo-random test where memory is filled with pseudo-random content and
;    tested for correctness afterwards
; Test-result is stored to storage variable (view with memory view)
; 1. Word is Error-count
; For Pattern-test only faulty address is written to storage,
; for Memory-test #2 (pseudo-random) two long words (32 bit) are written
;  - faulty address (long),
;  - expected value (16bit) and value read from memory (16 bit) is written
; To test different memory regions adopt MEM_START and MEM_LEN below.
; TAKE CARE!!! ORG address below needs to be outside of tested Memory area!!!


;       org $400    ; Needs to be outside of MEM_START:MEM_LEN
;MEM_START equ $400   ; Start-address of memory range to be tested
;MEM_LEN equ $80000   ; number of bytes to be tested

start:
        moveq #62,d7            ; ramtop
        trap #6
        lea memtop(pc),a1
        subq.l #4,a0           ; safety margin
        move.l a0,(a1)         ; store memtop
        lea msg3(pc),a0
        moveq #7,d7     ; Write
        trap #6
        lea memstart(pc),a0
        move.l a0,d0
        bsr print4
        move.b #'-',d0
        moveq #!co2,d7
        trap #1
        move.b #' ',d0
        moveq #!co2,d7
        trap #1
        move.l memtop(pc),d0
        bsr print4

        lea mempatt(pc),a2    ; A2 points to Memory pattern list
        lea patt_buf(pc),a3   ;
        lea storage(pc),a1
        clr.l d3                ; Fehler-counter
        move.l d3,(a1)+         ; First word is error-count
        clr.l (a1)
;        bra memt2            ; uncomment to skip test #1

; Memory-test #1 -> Patter test
loop1:
        move.b (a2)+,d0        ; Get Pattern
        tst.b d0
        beq.s memt2             ; done with pattern testing
        move.w d0,-(a7)         ; backup D0
        bsr print1

;       lea MEM_START,a0
;       move.l #MEM_LEN,d1
        move.l memtop(pc),d1
        lea memstart(pc),a0
        sub.l a0,d1

        move.w (a7)+,d0         ; Restore D0
        movem.l d1/a0,-(a7)
        bsr memset              ; Fill memory with pattern

        movem.l (a7)+,d6/a0
;        lea MEM_START,a0
;        move.l #MEM_LEN,d6
        bsr dupl                 ; create 32bit word from pattern (duplicate 4x)
        move.l d0,(a3)+          ; write to pattern buffer - for debug
        lsr.l #2,d6     ; div by 4
        subq.l #1,d6    ; prepare for dbra
        move.l d6,d7    ; low word of MEM_LEN in d6
        swap d7         ; high word of MEM_LEN in d7

m1:     move.l (a0)+,d1 ; Read memory content
        cmp.l d0,d1     ; And compare it with pattern
        beq.s equal

        move.l a0,d2    ; Memory error detected!
        subq.l #4,d2
        move.l d2,(a1)+ ; Store erroneous address
        addq.w #1,d3    ; Increment Fehler counter
        cmp.w #10,d3    ; Abort after 10 errors
        bhs.s stop
equal:  dbra d6,m1
        dbra d7,m1
;        move.l a0,debug2       ; For debug
        bra.s loop1

memt2:  ; Memory-test #2 -> fill with ascending numbers
;        lea MEM_START,a0
;        move.l #MEM_LEN,d6

        move.l memtop(pc),d6
        lea memstart(pc),a0
        sub.l a0,d6
        clr.w d0
        move.w #$cf31,d4        ; xor value
        lsr.l #1,d6     ; div by 2
        subq.l #1,d6    ; prepare for dbra
        move.l d6,d7
        swap d7
        movem.l d4/d6-d7/a0,-(a7)

mt1:    move.w d0,d1
        eor.w d4,d1

        move.w d1,(a0)+
        addq.w #1,d0
        add.w #4232,d4  ; Make values pseudo-random
        rol.w #1,d4
        dbra d6,mt1
        dbra d7,mt1

; Now test memory content
        movem.l (a7)+,d4/d6-d7/a0
        clr.w d0
mt2:
        move.w d0,d2
        eor.w d4,d2

        move.w (a0)+,d1
        cmp.w d2,d1     ; Memory content correct?
        beq.s mt3
        move.l a0,d5
        subq.l #2,d5
        move.l d5,(a1)+ ; 1. Store address
;        move.w d2,(a1)+ ; 2. store soll - optional for debugging
;        move.w d1,(a1)+ ; 3. store ist - optional for debugging
        addq.w #1,d3    ; Increment Fehler counter

        cmp.w #10,d3    ; Abort after 10 errors
        bhs.s stop
mt3:
        addq.w #1,d0
        add.w #4232,d4
        rol.w #1,d4
        dbra d6,mt2
        dbra d7,mt2

stop:   lea storage(pc),a1
        move.l d3,(a1)+
        moveq #!CRLF,d7
        trap #1
        tst.l d3
        beq.s no_err

; there were Errors. Print amount
        move.l d3,d0
        bsr print1
        lea msg2(pc),a0
        moveq #7,d7    ; Write
        trap #6
        moveq #!CRLF,d7
        trap #1

        subq.l #1,d3    ; correct for dbra
sp1:    move.l (a1)+,d0
        bsr print4
        dbra d3,sp1
        bra.s done
no_err: lea msg1(pc),a0
        moveq #7,d7     ; Write
        trap #6
done:
        rts
; Addresse in A0 - nees to be align(4)
; value in d0.b
; len d1.l
memset: bsr.s dupl
        lsr.l #2,d1     ; div by 4
        subq.l #1,d1    ; prepare for dbra
        move.l d1,d2
        swap d2
mset1:  move.l d0,(a0)+
        dbra d1, mset1
        dbra d2, mset1
;        move.l a0,debug1       ; For debug
        rts

;duplicate byte in d0.b to 32bit
dupl:   movem.l d2/d7,-(a7)   ;
        clr.l d2
        move.b d0,d2
        and.l #$ff,d0
        moveq #3-1,d7
l1:
        lsl.l #8,d2
        or.l d2,d0
        dbra d7,l1
        movem.l (a7)+,d2/d7
        rts

print1: lea buffer(pc),a0
        moveq #!PRINT2X,d7
        trap #1
p_c:    clr.b (a0)
        lea buffer(pc),a0
p1:     move.b (a0)+,d0
        tst.b d0
        beq.s p2
        moveq #!CO2,d7
        trap #1
        bra.s p1
 p2:    move.b #' ',d0
        moveq #!CO2,d7
        trap #1
        rts


; Zahl in d0.l
print4: lea buffer(pc),a0
        moveq #!PRINT8X,d7
        trap #1
        bra.s p_c

mempatt: dc.b $55,$aa,$01,$02,$04,$08,$10,$20,$40,$80,0
msg1: dc.b 'Done - No errors',0
msg2: dc.b ' Errors',0
msg3: dc.b 'Testing ',0
ds 0
memtop: ds.l 1
;debug1: ds.l 1
;debug2: ds.l 1
buffer: ds.b 16
patt_buf: ds.l 10
storage: ds.l 20
; 1. Word is Error-count
; For Pattern-test only faulty address is written to storage,
; for Memory-test #2 (pseudo-random) two long words (32 bit) are written
;  - faulty address (long),
;  - expected value (16bit) and value read from memory (16 bit) is written
memstart:
