 #*****************************************************************************
 #
 #                                  Sf_cpu_ext
 #
 # This module contains the assemly routines for the SWORDFISH CPU driver.
 #
 # Note that comment lines must begin with a blank so cpp will not regard 
 # them.
 #
 # History:
 #   +----------+------------+------------------------------------------------+
 #   |   Date   |     by     |     Description                                |
 #   +----------+------------+------------------------------------------------+
 #   |          | Coby       | Written                                        |
 #   +----------+------------+------------------------------------------------+
 #
 #*****************************************************************************


#ifndef SIM_32K
	.file	"sf_cpu_e.s"
#endif


#include "global.h"

#define NUM_OF_CPU_REGS  22

#define DESR 0xfffff100
#define DDR  0xfffff104
 #
 # List of global functions defined in this routine
 # Note the routine are defined in C style
 #
#ifndef public
extern void		call_bpt__(/*addr*/);
extern void		begin_bpt__(/*addr*/);
extern void		get_in__(/*addr*/);
extern void		mod_in__(/*addr*/);
extern void		get_cfg__(/*addr*/);
extern void		mod_cfg__(/*addr*/);
extern void		get_dcr__(/*addr*/);
extern void		mod_dcr__(/*addr*/);
extern void		get_dsr__(/*addr*/);
extern void		mod_dsr__(/*addr*/);
extern void		get_car__(/*addr*/);
extern void		mod_car__(/*addr*/);
extern void		get_amr__(/*addr*/);
extern void		mod_amr__(/*addr*/);
extern void		get_bpc0__(/*addr*/);
extern void		mod_bpc0__(/*addr*/);
extern void		get_bpc1__(/*addr*/);
extern void		mod_bpc1__(/*addr*/);
extern void		get_desr__(/*addr*/);
extern void		mod_desr__(/*addr*/);
extern void		get_ddr__(/*addr*/);
extern void		mod_ddr__(/*addr*/);

#endif

 #
 # Define global variables
 #

	.comm	_cmon_sp__,4
#ifdef DEBUG
	.comm	_ram_intbase__,4
	.comm	_rom_intbase__,4
#endif
	.globl  _END_BSS__
	.globl  end_init_cpu__

#ifdef SIM_32K
	
	#
	#  The monitors allocates a buffer to no existent SF register on 32K
	#  The SB will be initialized to this buffer and this buffer will be 
	#  used by both the application and the monitor.
	#
	
	.comm _memory_mapped_reg__, 1100
#endif



    #
    # Define registers variable
    #
	
	.comm	_save_R0__, 4
	.comm	_save_R1__, 4
	.comm	_save_R2__, 4
	.comm	_save_R3__, 4
	.comm	_save_R4__, 4
	.comm	_save_R5__, 4
	.comm	_save_R6__, 4
	.comm	_save_R7__, 4
	.comm	_save_R8__, 4
	.comm	_save_R9__, 4
	.comm	_save_R10__, 4
	.comm	_save_R11__, 4
	.comm	_save_R12__, 4
	.comm	_save_R13__, 4
	.comm	_save_R14__, 4
	.comm	_save_R15__, 4
	.comm	_save_R16__, 4
	.comm	_save_R17__, 4
	.comm	_save_R18__, 4
	.comm	_save_R19__, 4
	.comm	_save_R20__, 4
	.comm	_save_R21__, 4
	.comm	_save_R22__, 4
	.comm	_save_R23__, 4
	.comm	_save_R24__, 4
	.comm	_save_R25__, 4
	.comm	_save_R26__, 4
	.comm	_save_R27__, 4
	.comm	_save_R28__, 4
	.comm	_save_R29__, 4
	.comm	_save_R30__, 4
	
	.comm	_save_PC__,  4
	.comm	_save_PSR__, 4
	.comm	_save_IN__, 4
	.comm	_save_CFG__, 4
	
		.text

 #----------------------------------------------------------------------------
 #                   Macro definitions 
 #----------------------------------------------------------------------------
 
 #
 # LOADIi Load immediate macros 
 # Note the macro itself prepande the "$" to the value don't add it yourself
 #
.macro	loadib  val, reg
	    orb	    ${val}, c0, {reg}
.endm
.macro	loadiw	val, reg
	    orw	    ${val}, c0, {reg}
.endm
.macro	loadid  val, reg
	    ord	    ${val}, c0, {reg}
.endm

 #
 # ADDR macro
 #
.macro	addr	label, reg
	    ord	    ${label}, c0, {reg}
.endm
	    

 #/*^L*/
 #-----------------------------------------------------------------------------
 #
 #                                 Init_cpu
 #
 # This routine is called as part of the reset procedure. It initializes the
 # CMON and user cpu registers.
 #
 #-----------------------------------------------------------------------------

init_cpu__::
#ifdef DEBUG
	    #
	    # Change to superviser mode
	    #
	loadid	  9,r0
	loadid	  0x55555555,r1
	excp	svc
	
#ifdef SIM_32K
	    #
	    # Change "host" monitor to direct exception
	    #
	loadid	  14,r0
	loadid	  0x55555555,r1
	loadid	  1,r2
	excp	svc
	    #
	    # initialize SB for memory mapped registers
	    #
	addr	_memory_mapped_reg__,r7 
	lprd	 sb, r7

#endif /* SIM_32K */
#endif /* DEBUG */

	    #
	    # load intbase
	    #
	addr	dispatch_table__,r7	
#ifndef DEBUG
	lpr	r7, intbase
#else
	stord	r7,_ram_intbase__	# on ram monitor don't change intbase
#endif /* DEBUG */
	stord	r7,_save_IN__		# update saved intbase



	    #
	    # Initialize the CFG
	    #
#ifndef SIM_32K
#ifndef DEBUG
	    #
	    # enable FPU, DATA CACHE & INSTRUCTION CACHE.
	    # Use 512 Byte Page size
	    #
	loadid	  0x215,r7
#else
	    # disable DATA CACHE & INSTRUCTION CACHE.
	loadid    0x1, r7
#endif
#else
	    #
	    # enable FPU, DATA CACHE & INSTRUCTION CACHE.
	    # Use direct exception mode
	    # 
	loadid	  0xb02,r7
#endif
	lpr	 r7, cfg
	stord	r7, _save_CFG__		# update saved cfg
	
	
	    #
	    # Initialize stack
	    #
	addr	_end_interrupt_stack__ ,r7
	addd    $(IS_SIZE-4) ,r7, r7
	andb	$0xf8, r7, r7			# Align isp to 8 bytes
	lpr	 r7, isp			#
	stord	r7,_save_IS__			#
	addr	_end_cmon_stack__ ,r7
	addud	$(C_IS_SIZE-4), r7, r7
	andb	$0xf8, r7, r7			# Align SP to 8 bytes
	ord	r7, c0, SP			# load SP
	stord	r7, _cmon_sp__			# 

	stord	c0, _save_PC__			# update saved pc
	spr	  psr, r7
	stord	r7, _save_PSR__			# update saved psr
	br	end_init_cpu__





 #/*^L*/
 #-----------------------------------------------------------------------------
 #
 #                           Save_user_cpu_regs
 #
 # This routine is called always before entering monitor time.
 # It saves the users cpu registers, and loads them with the values
 # needed by CMON.
 # All the regs are saved here, even though intbase for example doesn't have
 # to be, for the convenience of the CPU driver print and change functions.
 #
 # Note that R15 was saved perior to calling this routine and it holds now
 #	the return address.
 #
 #-----------------------------------------------------------------------------

save_user_cpu_regs::
#ifdef SIM_32K
	bispsrw	$0x200		# 32K simulation work with user stack
#endif
	stord	r0, _save_R0__
	stord	r1, _save_R1__
	stord	r2, _save_R2__
	stord	r3, _save_R3__
	stord	r4, _save_R4__
	stord	r5, _save_R5__
	stord	r6, _save_R6__
	stord	r7, _save_R7__
	stord	r8, _save_R8__
	stord	r9, _save_R9__
	stord	r10, _save_R10__
	stord	r11, _save_R11__
	stord	r12, _save_R12__
	stord	r13, _save_R13__
	stord	r14, _save_R14__
	    #
	    # Don't  stord	r15, _save_R15__
	    #  
	stord	r16, _save_R16__
	stord	r17, _save_R17__
	stord	r18, _save_R18__
	stord	r19, _save_R19__
	stord	r20, _save_R20__
	stord	r21, _save_R21__
	stord	r22, _save_R22__
	stord	r23, _save_R23__
	stord	r24, _save_R24__
	stord	r25, _save_R25__
	stord	r26, _save_R26__
	stord	r27, _save_R27__
	stord	r28, _save_R28__
	stord	r29, _save_R29__
	stord	r30, _save_R30__
	
	    #
	    # get SP 
	    #
	spr	  isp, r0
	
	    #
	    # get PC into R1  & PSR into R2  from the stack
	    #
	loadd	0(r0),r1
#ifndef	SIM_32K
	loadd	4(r0),r2
#else
	loadw	6(r0), r2
	andd	$(0xffff), r2, r2
#endif
	    #
	    # Clean SP  from  PC & PSR .
	    # Store users special registers
	    #
	addd	$(8), r0, r0
	stord	r0, _save_IS__
	stord	r1, _save_PC__
	stord	r2, _save_PSR__
#ifdef DEBUG
	loadd	_ram_intbase__, r3	# save cmon intbase
#else
	spr	  intbase, r3		# save intbase
#endif
	stord	r3, _save_IN__
	loadd   _cmon_sp__, SP		# load CMON Stack
	jump	r15




 #/*^L*/
 #-----------------------------------------------------------------------------
 #
 #                           Load_user_cpu_regs
 #
 # This routine is called always just before exiting monitor time.
 # It loads the cpu registers with the values they contained at user time.
 # The US CFG and INTBASE registers are not loaded since they have the same 
 # value as in monitor time.
 # R15 is not loaded since it contain the return address it is the caller 
 # responsabilty to load R15.
 #
 #-----------------------------------------------------------------------------

load_user_cpu_regs::
	loadd	 _save_IS__,r0
	loadd	 _save_PC__,r1
	loadd	 _save_PSR__,r2
	addd	$(-8), r0, r0
	stord	r1, 0(r0)
#ifndef	SIM_32K
	stord	r2, 4(r0)
#else
	storw	r2, 6(r0)
#endif
	lpr	 r0, isp
	
	loadd	 _save_R0__,r0
	loadd	 _save_R1__,r1
	loadd	 _save_R2__,r2
	loadd	 _save_R3__,r3
	loadd	 _save_R4__,r4
	loadd	 _save_R5__,r5
	loadd	 _save_R6__,r6
	loadd	 _save_R7__,r7
	loadd	 _save_R8__,r8
	loadd	 _save_R9__,r9
	loadd	 _save_R10__,r10
	loadd	 _save_R11__,r11
	loadd	 _save_R12__,r12
	loadd	 _save_R13__,r13
	loadd	 _save_R14__,r14
	    #
	    # DONT loadd	 _save_R15__,r15
	    #
	loadd	 _save_R16__,r16
	loadd	 _save_R17__,r17
	loadd	 _save_R18__,r18
	loadd	 _save_R19__,r19
	loadd	 _save_R20__,r20
	loadd	 _save_R21__,r21
	loadd	 _save_R22__,r22
	loadd	 _save_R23__,r23
	loadd	 _save_R24__,r24
	loadd	 _save_R25__,r25
	loadd	 _save_R26__,r26
	loadd	 _save_R27__,r27
	loadd	 _save_R28__,r28
	loadd	 _save_R29__,r29
	loadd	 _save_R30__,r30
	
	jump	r15

 #----------------------------------------------------------------------------
 #
 #    Two globaly defined labels on BPT instruction.
 #    They are used to implement the BEGIN and two CALLs command.
 #    The return address pushed onto the stack are those labels.
 #
 #    NOTE this implementation of the above command differs from the old 
 #         monitor implementation and will not work in MMU environment,
 #         nevertheless it is cleaner and will work no mater which stack is
 #         chosen.
 #
 #----------------------------------------------------------------------------

_call_bpt__::
	excp	bpt

_begin_bpt__::
	excp	bpt






 ##----------------------------------------------------------------------------
 ## 
 ## The following functions implements some of the table driven get/mod 
 ## commands for the CPU register that dose not simply use their copy
 ##
 ## The standart format in C languege for this commands are:
 ##	    get_<reg>__(addr)   Will copy into addr reg contents
 ##	    mod_<reg>__(addr)	Will copy into reg addr contents
 ##---------------------------------------------------------------------------
 
 
 #-----------------------------------------------------------------------------
 #
 #                           _get_in__
 #
 # This routine is used to read the current value of the intbase register.
 #
 #-----------------------------------------------------------------------------

_get_in__::

#ifdef DEBUG
	loadd	_ram_intbase__, r0
#else
	spr	  intbase, r0
#endif
	stord	r0, 0(r4)
	jump	r15

 #-----------------------------------------------------------------------------
 #
 #                           _mod_in__
 #
 # This routine is used to modify the value of the intbase register.
 #
 #-----------------------------------------------------------------------------

_mod_in__::
	loadd	0(r4), r0
#ifdef DEBUG
	stord	r0, _ram_intbase__
#else
	lpr	 r0, intbase
#endif
	jump	r15

 #----------------------------------------------------------------------------
 #			    _get_cfg__
 #
 # This routine is used to read the value of the cfg register.
 # NOTE: If the sprd cfg is supported then this instruction is simply executed
 #	 other wise the cfg internal copy is read
 #
 #-----------------------------------------------------------------------------

_get_cfg__::
	spr	cfg, r0
	stord	r0, 0(r4)
	jump	r15


 #-----------------------------------------------------------------------------
 #
 #                           _mod_cfg__
 #
 # This routine is used to modify the value of the cfg register.
 # NOTE: If the lprd cfg is supported then this instruction is simply executed
 #	 other wise it is emulated
 #
 #-----------------------------------------------------------------------------

_mod_cfg__::
	loadd	0(r4), r0

#ifdef DEBUG
	andb	$0xef, r0, r0	    # Disable Instruction Cache
#endif

#ifdef	SIM_32K
	    #
	    # Force DE bit to 1
	    #
	ord	$0x100, r0, r0
#endif
	lpr	r0, cfg
	jump	r15


 #
 #-----------------------------------------------------------------------------
 #
 # The Following routines get and put SF CORE Hardware breakpoint registers
 #
 #-----------------------------------------------------------------------------

#ifndef SIM_32K
_get_dcr__::
	spr	  dcr, r0
	stord	r0, 0(r4)
	jump	r15

_mod_dcr__::
	loadd	0(r4), r0
	lpr	 r0, dcr
	jump	r15


_get_dsr__::
	spr	  dsr, r0
	stord	r0, 0(r4)
	jump	r15

_mod_dsr__::
	loadd	0(r4), r0
	lpr	 r0, dsr
	jump	r15


_get_car__::
	spr	  car, r0
	stord	r0, 0(r4)
	jump	r15

_mod_car__::
	loadd	0(r4), r0
	lpr	 r0, car
	jump	r15


_get_amr__::
	spr	  amr, r0
	stord	r0, 0(r4)
	jump	r15

_mod_amr__::
	loadd	0(r4), r0
	lpr	 r0, amr
	jump	r15


_get_bpc0__::
	spr	  bpc0, r0
	stord	r0, 0(r4)
	jump	r15

_mod_bpc0__::
	loadd	0(r4), r0
	lpr	 r0, bpc0
	jump	r15


_get_bpc1__::
	spr	  bpc1, r0
	stord	r0, 0(r4)
	jump	r15

_mod_bpc1__::
	loadd	0(r4), r0
	lpr	 r0, bpc1
	jump	r15

_get_desr__::
	loadd	DESR, r0
	stord	r0, 0(r4)
	jump	r15

_mod_desr__::
	loadd	0(r4), r0
	stord	r0, DESR
	jump	r15


_get_ddr__::
	loadd	DDR, r0
	stord	r0, 0(r4)
	jump	r15

_mod_ddr__::
	loadd	0(r4), r0
	stord	r0, DDR
	jump	r15

#endif /* SIM_32K */


	.align 8
