 #*****************************************************************************
 #
 #   DIAGNOSTIC DRIVER ASSEMBLER FILE  Diag_ext
 #
 # This module contains the Start_diag entry routine of the diagnostic.
 # It does what has to be done in assembly, and then calls the appropriate 
 # function in diag.c .
 # 
 # Note that comment lines must begin with a blank so cpp will not regard 
 # them.
 #
 # History:
 #   +----------+------------+------------------------------------------------+
 #   |   Date   |     by     |     Description                                |
 #   +----------+------------+------------------------------------------------+
 #   |          | Amir       | Written                                        |
 #   +----------+------------+------------------------------------------------+
 #
 #*****************************************************************************



    .file   "diag_ext.s"


#include    "global.h"



    count := 0

    .macro  bal	    link_reg, dest
		movd    $bal..{count}, {link_reg}
		br	{dest}
	    bal..{count}:
	    count := {{count} + 1}
    .endm

    .globl	_block_start__

    #***********************************************************************
    # Diagnostic usable meory definition.
    # This memory is checked in the start_diag routine and later will 
    # be used by the diagnostics.
    #
    #***********************************************************************
    .bss    _block_start__,   1, 4
#define    block_end	   _block_start__ + 0x1000 
#define    PU_test    	   0x7	    # Run first three tests

	.text

_start_diag__::
	#movd	r4, r5		    # Hold parameter in r5

	movd	$_block_start__, r1	
	movd	$15,r4
write1_mem:			    # for (r1 = _block_start__; r1 < block_end; 
				    #				     r1 += 4) {
	bal	r7, random	    #	r0 = random (r4);
	movd	r0, 0(r1)	    #	*r1 =  r0;
	addqd	4, r1		    # }
	cmpd	r1, $(block_end)
	blt	write1_mem


	movd	$15,r4
	movd	$_block_start__, r1	
write2_mem:			    # for (r1 = _block_start__; r1 < block_end; 
				    #				     r1 += 4) {
	bal	r7, random	    #	r0 = random (r4);
	comd	r0, r0		    #	r0 = com (r0);
	movd	r0, 0(r1)	    #	*r1 =  r0;
	addqd	4, r1		    # }
	cmpd	r1, $(block_end)
	blt	write2_mem



	movd	$0x10000, r1
delay1:
	acbd	-1, r1, delay1	    # Wait a while

	movd	$_block_start__, r1	
	movd	$15,r4
read1_mem:			    # for (r1 = _block_start__; r1 < block_end;
				    #				     r1 += 4) {
	bal	r7, random	    #	r0 = random (r4);
	comd	r0, r0		    #	r0 = com (r0);
	cmpd	r0, 0(r1)	    #	if (*r1  !=  r0)
	bne	start_error	    #	    goto start_error
	addqd	4, r1		    # }
	cmpd	r1, $(block_end)
	blt	read1_mem



	movd	$15,r4
	movd	$_block_start__, r1	
write3_mem:			    # for (r1 = _block_start__; r1 < block_end; 
				    #				     r1 += 4) {
	bal	r7, random	    #	r0 = random (r4);
	movd	r0, 0(r1)	    #	*r1 =  r0;
	addqd	4, r1		    # }
	cmpd	r1, $(block_end)
	blt	write3_mem

	movd	$0x10000, r1
delay2:
	acbd	-1, r1, delay2	    # Wait a while

	movd	$_block_start__, r1	
	movd	$15,r4
read2_mem:			    # for (r1 = _block_start__; r1 < block_end;
				    #				     r1 += 4) {
	bal	r7, random	    #	r0 = random (r4);
	cmpd	r0, 0(r1)	    #	if (*r1  !=  r0)
	bne	start_error	    #	    goto start_error
	addqd	4, r1		    # }
	cmpd	r1, $(block_end)
	blt	read2_mem

	movd	$_block_start__, r1	
write4_mem:			    # for (r1 = _block_start__; r1 < block_end; 
				    #				     r1 += 4) {
	movqd	0, 0(r1)	    #	*r1 =  0;
	addqd	4, r1		    # }
	cmpd	r1, $(block_end)
	blt	write4_mem


	LED(LED_5)
	
	    #
	    # Initialize registers before call to HLL
	    #****************************************
#ifdef DEBUG	    
        movd    $9,r0
        movd    $0x55555555, r1
        svc                         # change to supervisor mode
	lprd	psr, $0x00	    # SP0 interrupt disable Supervisor mode

	#
	#	Default Exception mode is non-direct
	#
#if (DE_AVAILABLE && NON_DE_AVAILABLE)
	movd	$14, r0
	movd    $0x55555555,  r1
	movd	$0, r2		    # Change to non-direct exception
	svc
#endif

        movd    $12,r0
        movd    $0x55555555, r1
        addr    _diag_dispatch__,r2  #new int base address
        movd    $16,r3
        svc			    # copy monitor int_tab to int_table.
#else
	addr _diag_dispatch__,  r5
	lprd intbase,  r5

#endif /* DEBUG */

	LED(LED_6)

#if (NON_DE_AVAILABLE)
# if (FPU_TYPE != NOFPU)
	setcfg	[f,i]		    # Initialize CFG 
#else
	setcfg	[i]		    # Initialize CFG 
#endif
#else
# if (FPU_TYPE != NOFPU)
        setcfg  [f,i, de]           # Initialize CFG with dircet exception
#else
        setcfg  [i, de]           # Initialize CFG with dircet exception
#endif
#endif

	lprd	fp, $(0)
	lprd	sp, $(block_end) - 4
	#cmpqd	1, r5	
	#bne	run_batch_diag
	.call	_diag_interface__
	br	diag_end
run_batch_diag:
	.call	_test_dispatch__, $PU_test, $0, $0	# Run test list No loop
							# No halt
	

				    #
				    # End diagnostic clean up register
				    # and return to absolute address end_diag__
				    #
diag_end:
	lprd	psr, $0x0
	setcfg	[]
	#br	end_diag__
	movqd	6, r0
	movd	$100, r1
	svc
	ret	0



				    #
				    # Fault block of memory handling
				    #
				    
start_error:
	LED(LED_F)
	br	.


    #
    #	arguments: R4 seed number 
    #	returns r0 new number 
    #
random:
	muld	$1103515245, r4
	addd	$12345,	r4
	movd	r4, r0
	andd	$0x7fffffff, r4
	jump	0(r7)



    #########################################################################
    #
    # This section containes some handling routine to be used in the 
    # diagnostic package.
    #
    ##########################################################################
    

 #_int_enable__::
 #	bispsrw	$0x800
 #	ret	0
	

 #_int_disable__::
 #	bicpsrw	$0x800
 #	ret	0


 ############################################################################
 #
 #  isetjmp__ and ilongjmp__  
 #
 ###########################################################################


    #
    # ienv typedef struct definition
    #


    .dsect  ienv_type,   0
_r3:	    .blkd		    # Save register R3
_r4:	    .blkd		    # Save register R4
_r5:	    .blkd		    # Save register R5
_r6:	    .blkd		    # Save register R6
_r7:	    .blkd		    # Save register R7
_sp0:	    .blkd		    # Save register sp0
_sp1:	    .blkd		    # Save register sp1
_fp:	    .blkd		    # Save register fp
_mod_psr:   .blkd		    # Save register psr
_ret:	    .blkd		    # Save return address
ienv_size:

    .bss    ienv, ienv_size, 4
    .text
_isetjmp__::
	addr	    ienv, r0
	movd	    r3, _r3(r0)		    # Store Non volatile register
	movd	    r4, _r4(r0)
	movd	    r5, _r5(r0)
	movd	    r6, _r6(r0)
	movd	    r7, _r7(r0)
	movd	    0(sp), _ret(r0)	    # Store return address
        sprw        mod, _mod_psr(r0)
	sprw	    psr, 2 + _mod_psr(r0)   
        tbitd	    $9, 2 + _mod_psr(r0)    # test used stack
        bfs	    use_sp1
	sprd	    sp, _sp0(r0)            # Store first sp0
	addqd	    4, _sp0(r0)             # diconsider return address
	bispsrw	    $0x200
	sprd	    sp, _sp1(r0)
	bicpsrw	    $0x200
	br	    isetjmp1
use_sp1:
	sprd	    sp, _sp1(r0)            # Store first sp1
	addqd	    4, _sp1(r0)             # diconsider return address
	bicpsrw	    $0x200
	sprd	    sp, _sp0(r0)
	bispsrw	    $0x200
isetjmp1:
	sprd	    fp, _fp(r0)
	movqd	    0,r0
	ret	    0



_ilongjmp__::
	addr	    ienv, r0
	movd	    _r3(r0), r3
	movd	    _r4(r0), r4
	movd	    _r5(r0), r5
	movd	    _r6(r0), r6
	movd	    _r7(r0), r7
	movd	    _sp0(r0), r1
	addd	    $(-0x8),r1		    # Prepare sp0 for reti execution
	movd	    _ret(r0), 0(r1)
	movw	    _mod_psr(r0), 4(r1)
	lprd	    sp, r1		    # Load sp0
	bispsrw	    $0x200
	lprd	    sp, _sp1(r0)	    # Load sp1
	bicpsrw	    $0x200
	lprd	    fp, _fp(r0)
	movqd	    1, r0
	reti

#ifndef DEBUG
#ifdef  CMON

	    # Initialize registers before call to pu_diag__ in HLL
	    #*****************************************************
_start_pu__::	    

	addr _diag_dispatch__, r5
	lprd intbase, r5

#if (NON_DE_AVAILABLE)
#if (FPU_TYPE != NOFPU)
	setcfg	[f,i]		    # Initialize CFG 
#else
	setcfg	[i]		    # Initialize CFG 
#endif
#else
#if (FPU_TYPE != NOFPU)
        setcfg  [f,i, de]           # Initialize CFG with dircet exception
#else
        setcfg  [i, de]           # Initialize CFG with dircet exception
#endif
#endif

	lprd	fp, $(0)
	lprd	sp, $(block_end) - 4
	.call	_pu_diag__
	br end_pu__

#endif  /* CMON */
#endif	/* DEBUG */
