; modified for 8008 by Mark Arnold 
;  from MCS 6502 MEMORY TEST by Mike Willegal
;
;  6502  8008
;  ----  -------------
;   Y     B
;  ADDRS  DE
;   X     -
;   A     A
;  stack  SAVEA and C
;
;  when needed, 8008 B-E saved and restored by SAVE_REGS and REST_REGS

;  first 100 bytes free for boot loader
;  emulator starts here
	ORG 000#100
	JMP MEM_TEST
;
;  data RAM on page 0 just after JMP 
;  user should initialize (jam with switches) START, END
START:	  	DATA 	026,002 
END:    	DATA 	000,060		;defualt to 12k
;  remaining data simply variables used by program
TEST_PATRN: 	DATA 	000      	;1 BYTE - CURRENT TEST PATTERN
PASSES: 	DATA	000		;NUMBER of PASSES
COUNT:		DATA	000		;NUMBER of ERRORS
SAVEA:		DATA	000
SAVEB:		DATA	000
SAVEC:		DATA	000
SAVED:		DATA	000
SAVEE:		DATA	000
	ORG 000#120
        LLI \LB\END+1			; user sets ending page in REG A before jumping to this entry point
        LHI \HB\END+1
	LMA	
	JMP MEM_TEST
;
; utility routines (used to be macros on 6502)
;
INI_ADDRS:
        LLI \LB\START
        LHI \HB\START
        LEM		;low ADDRS
        LLI \LB\START+1
        ;LHI \HB\START   ;not needed 
        LDM		;high ADDRS
	RET

; INCREMENT ADDRESS
INC_ADDRSC:
	INE		;low ADDRS
	JFZ SKIP_HI
 	IND		;high ADDRS
SKIP_HI:
   	LLI 	\LB\END
	LHI	\HB\END
	LAM
        CPE		;low ADDRS
	RFZ
   	LLI 	\LB\END+1
	;LHI	\HB\END  ;not needed
	LAM
        CPD		;high ADDRS
	RET

; SET TEST PATTERN
; only for tests 4 and 5 (address in address tests), make addres High or Low 
; equal to pattern
; test 4 is LSB of address
; test 5 is MSB of address
; 
SET_PATRN:
	LLI	\LB\TEST_PATRN
	LHI	\HB\TEST_PATRN
	LAI	004
	CPB
	JFZ	TEST5
	LME		;low ADDRS
TEST5:
	LAI	005
	CPB
	RFZ	
	LMD		;high ADDRS
	RET

;
; TESTS TYPE
;	0 = all zeros
;	1 = all ones
;	2 = floating 1s
;	3 = floating 0s
;	4 = address in address (LS 8 address bits)
;	5 = adddress in address(MS 8 address bits)
;
;


; 8008 routine to save and restore regs
;
SAVE_REGS:
	LHI \HB\SAVEB
	LLI \LB\SAVEB
	LMB
	INL
	LMC
	INL
	LMD
	INL
	LME
	RET  	

REST_REGS:
	LHI \HB\SAVEB
	LLI \LB\SAVEB
	LBM
	INL
	LCM
	INL
	LDM
	INL
	LEM
	RET  	

; entry point to memorY
;
MEM_TEST:
	LAI 000
		
	LHI \HB\PASSES		; start at pass 0
	LLI \LB\PASSES
	LMA

REPEAT:
	LAI 000
	LBA			; TEST # in REG B
	LLI \LB\TEST_PATRN   	; first pass all zeros
	LHI \HB\TEST_PATRN   	; first pass all zeros
        LMA
;
NX_PASS:
;  uncomment to print debug info
;	CAL	SAVE_REGS
;	LLI \LB\TEST_PATRN 
;	LHI \HB\TEST_PATRN
;	LAM
;	CAL	TBYT
;	CAL 	SPACE
;	CAL	REST_REGS
;
	CAL	INI_ADDRS
;
LOOP1:
	CAL	SET_PATRN
	LLI	\LB\TEST_PATRN
	LHI	\HB\TEST_PATRN
	LAM
 	LLE
	LHD
	LMA   ;STA 	(ADDRS, X) STORE PATTERN
       	LAM	;LDA                               	(ADDRS, X) READ (save result of read in case of error)
; uncomment to test with error injection 
;   CAL	INJECT_ERR
	LLI	\LB\TEST_PATRN
	LHI	\HB\TEST_PATRN
	CPM	; CHECK
	CFZ 	LOOP_ERR	; 8008Jxx notRngLimitLOOP_EER2;branch if error
	CAL	INC_ADDRSC
	JFZ	LOOP1
;
;  uncomment to print debug info
;	CAL	SAVE_REGS
;	LLI \LB\TEST_PATRN   
;	LHI \HB\TEST_PATRN 
;	LAM
;	CAL	TBYT
;	CAL 	SPACE
;	CAL	REST_REGS
;
CK_PATRN:
	CAL	INI_ADDRS 	; INITIALISE ADDRS
;
LOOP2:
	CAL 	SET_PATRN	; sets up TEST_PATRN for address in address test
 	LLE
	LHD
	LAM	;LDA 	(ADDRS, X) READ (save result of read in case of error)
	LLI	\LB\TEST_PATRN
	LHI	\HB\TEST_PATRN
	CPM	; CHECK
LOOP_ERR2:
	CFZ 	LOOP_ERR	; branch if error
	CAL	INC_ADDRSC
	JFZ 	LOOP2
;
; Pass Complete - see what is next
;
        LAB
	CPI	0		; test 0 - all zeros complete
	JFZ	CHK_TEST1
;
; move to test 1
;

	LAI	377		; 
NX_TEST:
	LLI \LB\TEST_PATRN   
	LHI \HB\TEST_PATRN  
        LMA
	INB			; move to next test 
NX_PASS3:
NX_PASS1:
NX_PASS2:
	JMP	NX_PASS
	
;
CHK_TEST1:
        LAB
	CPI	1		; all ones complete?
	JFZ	CHK_TEST2
;
; test 1 - all zeros comlete
;
	LAI	1
	JMP 	NX_TEST	; always

CHK_TEST2:
        LAB
	CPI	2		
	JFZ	CHK_TEST3 ; floating 1s in progress or done
;
; pass of test 2 complete - 8 passes in all with 1 in each bit position
;
	LLI \LB\TEST_PATRN   
	LHI \HB\TEST_PATRN  
	LAM
	NDA	;clear carry
	RAL
	LMA 	; shift left - zero to LSB- MSB to CARRY
	JFC	NX_PASS1
;
; all test 2 passes complete - prepase for test 3
;
	LAI	177
	JMP	NX_TEST		;always branch

CHK_TEST3:		;floating zeros in progress or done
        LAB
	CPI	3		
	JFZ	CHK_TEST4 
;
; pass of test 3 complete - 8 passes in all with 0 in each bit position
;
	LAI	200
	RAL	;SET CARRY
	LLI \LB\TEST_PATRN   
	LHI \HB\TEST_PATRN  
	LAM
	RAR		; rotate right - Carry to MSB, LSB to Carry
	LMA
	JTC	NX_PASS2	; keep going until zero bit reaches carry
NXTADDRTST:
	INB			; move to test 4 or 5 - address in address
	JMP	NX_PASS3	; aways
;
; ADDRESS IN ADDRESS tests - two test only make one pass each
;
CHK_TEST4:
        LAB
	CPI	4		; address in address (low done)?
	JTZ	NXTADDRTST	; if test 4 done, start test 5

; test 5 complete - we have finished a complete pass
TESTDONE:			; print done and stop
	CAL	SAVE_REGS
	LAI	320
	CAL	WRITE
	LAI	301
	CAL	WRITE
	LAI	323
	CAL	WRITE
	LAI	323
	CAL	WRITE
    	CAL	SPACE
	LHI 	\HB\PASSES		
	LLI 	\LB\PASSES
	LAM
	ADI	001
	LMA
	CAL	TBYT
	CAL	SPACE
	LAI	305
	CAL	WRITE
	CAL	SPACE
	LLI 	\LB\COUNT	; count errors  (8 bit counter)
  	LHI 	\HB\COUNT
  	LAM
	CAL	TBYT
	CAL	PRINT_CRLF
;uncomment for a single pass
; JMP FINISHED
	CAL	REST_REGS
	JMP	REPEAT

; OUTPUT THE ERROR INFO and STOP	
; TEST#, ADDRESS, PATTERN, ERROR
LOOP_ERR:
	CAL	SAVE_REGS
	LLI	\LB\SAVEA
	LHI	\HB\SAVEA
	LMA
	LAB			; test # is in B
	CAL	TBYT 		; test #
    	CAL	SPACE
	LAD			;LDA ADDRS + $01
	CAL	TBYT 		; OUTPUT ADDRS HI
	CAL 	SPACE
	LAE			;LDA ADDRS
	CAL	TBYT 		; OUTPUT ADDRS LO
      	CAL	SPACE
      	LLI 	\LB\TEST_PATRN
      	LHI 	\HB\TEST_PATRN
        LAM
      	CAL	TBYT 		; OUTPUT EXPECTED
	CAL	SPACE
	LLI	\LB\SAVEA
	LHI	\HB\SAVEA
	LAM
      	CAL	TBYT 		; OUTPUT ACTUAL
      	CAL	PRINT_CRLF
 	LLI 	\LB\COUNT	; count errors  (8 bit counter)
  	LHI 	\HB\COUNT
  	LAM
  	ADI 	001
  	LMA
 	CAL	REST_REGS
	
FINISHED:
	RET
;	HLT



; PRINT OCTAL (rather than HEX) BYTE
TBYT:
   	LCA	;save byte in C	
	RRC
	RRC
	RRC
	RRC
	RRC
	RRC
	NDI	003
	ORI	260
	CAL 	WRITE
	LAC
	RRC
	RRC
	RRC
	NDI	007
	ORI	260
	CAL 	WRITE
	LAC
	NDI	007
	ORI	260
	JMP 	WRITE

; ROUTINE TO OUTPUT CRLF
PRINT_CRLF:
	LAI 	215 
	CAL	WRITE
	LAI 	212
      	JMP	WRITE


; SPACE = OUTPUT 1 SPACE
SPACE:
	LAI 	240
	JMP	WRITE 

; ROUTINE TO WRITE AN ASCII CHAR.
; change to character out routine for your platform
;;; HERE IS THE USER DEFINED PRINT ROUTINE FOR A SERIAL PORT
OUTPORT: EQU 016
	
WRITE:
ECHO:			         ;ASCII Output routine

        NDI    177		; mask MSbit
	RAL
	OUT OUTPORT
	RAR
	LAA			; delay to make timing work
	LAA
	LBI	2		; delay counter
	CAL 	MORE2		
	CAL 	BITOUT		; LSB
	CAL 	BITOUT		; 1
	CAL 	BITOUT		; 2
	CAL 	BITOUT		; 3
	CAL 	BITOUT		; 4
	CAL 	BITOUT		; 5
	CAL 	BITOUT		; 6
	CAL 	BITOUT		; MSB
	LBA			; timing delay
	LAI 	001
	OUT 	OUTPORT		; stop bit
	LBI 	5
	JMP 	MORE2

BITOUT:	
	OUT 	OUTPORT
	RRC			; shift to get next bit
	LBI 	3
MORE2:
	LAA			; nop to delay 5 states to make timing work
	DCB
	JFZ 	MORE2
	LBI	0		; delay 8 states
	RET

;
; testing by injection of errors for particular test type
; uncomment appropriate lines
INJECT_ERR:
;	LLI	\LB\SAVEA
;	LHI	\HB\SAVEA
;	LMA		;save A
;     uncomment for test 0
;	LAI	0	;if test==0 return 1
;	CPB
;	LAI	1
;	RTZ
;     uncomment for test 1
;	LAI	1 	;if test==1 return 0
;	CPB
;	LAI	0
;	RTZ
;     uncomment for test 2
;	LAI	2 	;if test==2 return 377
;	CPB
;	LAI	377
;	RTZ
;     uncomment for test 3
;	LAI	3 	;if test==3 return 177
;	CPB
;	LAI	177
;	RTZ
;     uncomment for test 4
;	LAI	4 	;if test==4 return 0 
;	CPB
;	LAI	376	;low 8 of first test loc
;	RTZ
;     uncomment for test 5
;	LAI	5 	;if test==4 return 0 
;	CPB
;	LAI	3	;page where test starts
;	RTZ
;	LAM		;restore A
;	RET

;
; code for testing eror message
;	ORG 000#100
;	LBI 176
;	LDI 245
;	LEI 376
;	LAI 034
;	JMP LOOP_ERR


