;******************************************************************************
;            TEXAS INSTRUMENTS INCORPORATED PROPRIETARY INFORMATION           
;                                                                             
;   Property of Texas Instruments -- For  Unrestricted  Internal  Use  Only 
;   Unauthorized reproduction and/or distribution is strictly prohibited.  This 
;   product  is  protected  under  copyright  law  and  trade  secret law as an 
;   unpublished work.  Created 1987, (C) Copyright 1997 Texas Instruments.  All 
;   rights reserved.                                                            
;                  
;                                                           
;   Filename       	: int.s
;
;   Description    	: Nucleus initialization
;
;   Project        	: Drivers
;
;   Author         	: proussel@ti.com  Patrick Roussel.
;
;   Version number	: 1.3
;
;   Date and time	: 07/23/98 15:36:07
;
;   Previous delta 	: 07/23/98 15:36:06
;
;   SCCS file      	: /db/gsm_asp/db_ht96/dsp_0/gsw/rel_0/mcu_l1/release1.5/mod/emu/EMU_MCMP/eva3_drivers/source/SCCS/s.int.s
;
;   Sccs Id  (SID)      : '@(#) int.s 1.3 07/23/98 15:36:07 '
;/*************************************************************************/
;/*                                                                       */
;/*     Copyright (c) 1993 - 1996 Accelerated Technology, Inc.            */
;/*                                                                       */
;/* PROPRIETARY RIGHTS of Accelerated Technology are involved in the      */
;/* subject matter of this material.  All manufacturing, reproduction,    */
;/* use, and sales rights pertaining to this subject matter are governed  */
;/* by the license agreement.  The recipient of this software implicitly  */
;/* accepts the terms of the license.                                     */
;/*                                                                       */
;/*************************************************************************/
;
;/*************************************************************************/
;/*                                                                       */
;/* FILE NAME                                            VERSION          */
;/*                                                                       */
;/*      int.s                                       PLUS/THUMB/T 1.3     */
;/*                                                                       */
;/* COMPONENT                                                             */
;/*                                                                       */
;/*      IN - Initialization                                              */
;/*                                                                       */
;/* DESCRIPTION                                                           */
;/*                                                                       */
;/*      This file contains the target processor dependent initialization */
;/*      routines and data.                                               */
;/*                                                                       */
;/* AUTHOR                                                                */
;/*                                                                       */
;/*      Barry Sellew, Accelerated Technology, Inc.                       */
;/*                                                                       */
;/* DATA STRUCTURES                                                       */
;/*                                                                       */
;/*      INT_Vectors                         Interrupt vector table       */
;/*                                                                       */
;/* FUNCTIONS                                                             */
;/*                                                                       */
;/*      INT_Initialize                      Target initialization        */
;/*      INT_Vectors_Loaded                  Returns a NU_TRUE if all the */
;/*                                            default vectors are loaded */
;/*      INT_Setup_Vector                    Sets up an actual vector     */
;/*                                                                       */
;/* DEPENDENCIES                                                          */
;/*                                                                       */
;/*      nucleus.h                           System constants             */ 
;/*                                                                       */ 
;/* HISTORY                                                               */
;/*                                                                       */
;/*         NAME            DATE                    REMARKS               */
;/*                                                                       */
;/*      B. Sellew       01-19-1996      Created initial version 1.0      */
;/*	     B. Sellew	     01-22-1996	     Verified version 1.0	  	      */
;/*	     B. Sellew	     03-14-1996	     Modified to use the ROM          */
;/*				                          initialization method,          */
;/*	                                      resulting in version 1.1        */
;/*      B. Sellew       03-14-1996      Verified version 1.1             */
;/*      B. Sellew       02-06-1997      Created version 1.3              */
;/*	     B. Sellew	     02-06-1997	     Verified version 1.3	  	      */
;/*      M. Manning      06-02-1997      Added support for FIQ            */
;/*                                       interrupts. Bumped to 1.4       */
;/*      M. Manning      06-03-1997      Verified version 1.4             */
;/*                                                                       */
;/*************************************************************************/
;#define         NU_SOURCE_FILE
;
;#include        "nucleus.h"                 /* System constants          */
;
;
;/* Define constants used in low-level initialization.  */
;
;


  .if LONG_JUMP >= 3
        .global IND_CALL
        .global _f_load_int_mem
        .global _ResetVector
        
; Initialization for variable S_D_Mem
      	.sect	".cinit"
      	.align	4

; S_D_Mem is a UWORD32, See mem_load.c
;
      	.field  	4,32
      	.field  	_S_D_Mem+0,32
      	.field  	0,32		; _S_D_Mem @ 0

      	.sect	".text"
        .global _S_D_Mem
_S_D_Mem: .usect  "S_D_Mem",4,4
        .sym    _S_D_Mem,_S_D_Mem,14,2,32        ; For debug only


; Initialization for variable E_D_Mem

      	.sect	".cinit"
      	.align	4


; E_D_Mem is a UWORD32, See mem_load.c
;
      	.field  	4,32
      	.field  	_E_D_Mem+0,32
      	.field  	0,32		; _E_D_Mem @ 0

      	.sect	".text"
        .global _E_D_Mem
_E_D_Mem: .usect  "E_D_Mem",4,4
        .sym    _E_D_Mem,_E_D_Mem,14,2,32        ; For debug only

  .endif      ; (LONG_JUMP >= 3)
  
  .if CHIPSET == 12
        .global _f_load_int_mem
        .global _ResetVector
        .global _ResetVectorTestMode ; CALYPSO PLUS TEST MODE - TO BE ERASED
  .endif
  
LOCKOUT         .equ     00C0h              ; Interrupt lockout value
LOCK_MSK        .equ     00C0h              ; Interrupt lockout mask value
MODE_MASK       .equ     001Fh              ; Processor Mode Mask
SUP_MODE        .equ     0013h              ; Supervisor Mode (SVC)
IRQ_MODE        .equ     0012h              ; Interrupt Mode (IRQ)
FIQ_MODE        .equ     0011h              ; Fast Interrupt Mode (FIQ)
ABORT_MODE      .equ     0017h				; Abort Interrupt Mode
UNDEF_MODE      .equ     001Bh				; Undefined Interrupt Mode (should not happen)

IRQ_STACK_SIZE  .equ     128                ; Number of bytes in IRQ stack (must be align(8))
                                            ;   Note that the IRQ interrupt,
                                            ;   by default, is managed by 
                                            ;   Nucleus PLUS.  Only several
                                            ;   words are actually used.  The 
                                            ;   system stack is what will 
                                            ;   actually be used for Nuclues
                                            ;   PLUS managed IRQ interrupts.
FIQ_STACK_SIZE  .equ     512                ; Number of bytes in FIQ stack. (must be align(8))
                                            ;   This value is application 
                                            ;   specific.  By default, Nucleus
                                            ;   does not manage FIQ interrupts
                                            ;   and furthermore, leaves them
                                            ;   enabled virtually all the time.
SYSTEM_SIZE     .equ     1024               ; Define the system stack size (must be align(8))
TIMER_SIZE      .equ     1024               ; Define timer HISR stack size (must be align(8))
TIMER_PRIORITY  .equ     2                  ; Timer HISR priority (values from
    
  .if BOARD = 34
; Name                   value     offset   type      W/E W/S D/Cycles
CS0_CONFIG      .short   0x044F    ; 0     Flash 32    N   F   2
CS1_CONFIG      .short   0x02CF    ; 2     RAM   32    Y   F   1
CS2_CONFIG      .short   0x02CF    ; 4
CS3_CONFIG      .short   0x02CF    ; 6
CS7_CONFIG      .short   0x02C0    ; 8    Int-RAM 32   Y   0   1
CS5_CONFIG      .short   0x02CF    ; A                          
CS6_CONFIG      .short   0x02C0    ; C    Int-RAM 32   Y   0   1
RHEA_CONFIG     .short   0x002A    ; E   ARM -> RHEA/API adaptation
NUM_CS_REGS     .equ     8            ; number of Chip Select Config regs to program
  .endif
	                                        ;   0 to 2, where 0 is highest)

;
;/* End of low-level initialization constants.  */
;
;
;/* Define the initialization flag that indicates whether or not all of the
;   default vectors have been loaded during initialization.  */
;
;INT    INT_Loaded_Flag;

        .def    _INT_Loaded_Flag
        .bss    _INT_Loaded_Flag, 4, 4
;
;/* Define the vector table  */
;

  .if CHIPSET = 12
	        .sect ".start"

             .ref    _INT_Bootloader_Start

_ResetVector:
              B	_INT_Bootloader_Start

         .sect ".indint"
         
            .def  _IndirectVectorTable
_IndirectVectorTable:
                LDR   PC, [PC, #0x14]
                LDR   PC, [PC, #0x14]
                LDR   PC, [PC, #0x14]
                LDR   PC, [PC, #0x14]
                LDR   PC, [PC, #0x14]
                LDR   PC, [PC, #0x14]
                LDR   PC, [PC, #0x14]

                .word    INT_Undef_Inst
                .word    INT_Swi
                .word    INT_Abort_Prefetch
                .word    INT_Abort_Data
                .word    INT_Reserved
                .word    INT_IRQ
                .word    INT_FIQ

; CALYPSO PLUS TEST MODE - TO BE ERASED
	.sect ".intvecs"

_ResetVectorTestMode:
	B	_INT_Bootloader_Start
	B	INT_Undef_Inst
	B	INT_Swi
	B	INT_Abort_Prefetch
	B	INT_Abort_Data
	B	INT_Reserved
	B	INT_IRQ
	B	INT_FIQ

  .else ; CHIPSET = 12

	.sect ".intvecs"

  .if BOARD = 34
        B       _INT_Initialize
  .elseif BOARD = 35
        B       _INT_Initialize
  .else
        .ref    _INT_Bootloader_Start

	B	_INT_Bootloader_Start
  .endif
	B	INT_Undef_Inst
	B	INT_Swi
	B	INT_Abort_Prefetch
	B	INT_Abort_Data
	B	INT_Reserved
	B	Vect_IRQ
    .if WCP_PROF = 1
        .global    _PR_StoreMonteCarloSample

; Timing profiler using FIQ - Handle FIQ directly here

        STMFD    sp!,{R0-R4, LR}            ; Save R0-R4 and LR on FIQ stack

        MOV     R0, LR                      ; Retrieve link register in R0
        BL      _PR_StoreMonteCarloSample   ; Store into ring buffer
        BL      _IQ_FIQ_isr                 ; Ack FIQ

        LDMFD   sp!,{R0-R4, LR}             ; Restore R0-R4 and LR from FIQ stack
        SUBS    PC, LR, #4                  ; return from FIQ
    .else
	B	Vect_FIQ
    .endif
  .endif ; CHIPSET = 12

;
;	.text
;
;	.ref	cinit

	.sect       ".inttext"
	.global     cinit       ; Linker symbol for C variable init.


; Address definitions in the section where they are used.

;
;/* Define the global system stack variable.  This is setup by the 
;   initialization routine.  */
;
;extern VOID            *TCD_System_Stack;
;
        .ref  	_TCD_System_Stack
        .ref    _TCT_System_Limit
;
;
;/* Define the global data structures that need to be initialized by this
;   routine.  These structures are used to define the system timer management
;   HISR.  */
;   
;extern VOID     *TMD_HISR_Stack_Ptr;
;extern UNSIGNED  TMD_HISR_Stack_Size;
;extern INT       TMD_HISR_Priority;
;
        .ref  	_TMD_HISR_Stack_Ptr
        .ref  	_TMD_HISR_Stack_Size
        .ref  	_TMD_HISR_Priority
;
;
;/* Define extern function references.  */
;
;VOID   INC_Initialize(VOID *first_available_memory);
;VOID   TCT_Interrupt_Context_Save(VOID);
;VOID   TCT_Interrupt_Context_Restore(VOID);
;VOID   TCC_Dispatch_LISR(INT vector_number);
;VOID   TMT_Timer_Interrupt(void);
;
        .ref  	_INC_Initialize
        .ref  	_TCT_Interrupt_Context_Save
        .ref  	_TCT_Interrupt_Context_Restore
        .ref  	_TCC_Dispatch_LISR
        .ref  	_TMT_Timer_Interrupt

;/* Application ISR */
        .ref  	_IQ_IRQ_isr
        .ref  	_IQ_FIQ_isr
;
; /* Reference pointers defined by the linker */
;
	.ref	.bss
	.ref	end

;
;/* Define indirect branching labels for the vector table  */
;

        .def    INT_Undef_Inst
INT_Undef_Inst
        B       arm_undefined               ; Undefined
;
        .def    INT_Swi
INT_Swi
        B       arm_swi                     ; Software Generated
;
        .def    INT_Abort_Prefetch
INT_Abort_Prefetch
        B		arm_abort_prefetch          ; Abort Prefetch
;
        .def    INT_Abort_Data
INT_Abort_Data
        B       arm_abort_data              ; Abort Data
;
        .def    INT_Reserved
INT_Reserved
        B       arm_reserved                ; Reserved
;
        .def    Vect_IRQ
Vect_IRQ
		.if TI_NUC_MONITOR = 1
        B       _INT_IRQ
        .else
        B       INT_IRQ
		.endif
;
        .def    Vect_FIQ
Vect_FIQ
		.if TI_PROFILER = 1
        B       _INT_FIQ
        .else
        B       INT_FIQ
		.endif
;

;
;/*************************************************************************/
;/*                                                                       */
;/* FUNCTION                                                              */
;/*                                                                       */
;/*      INT_Initialize                                                   */
;/*                                                                       */
;/* DESCRIPTION                                                           */
;/*                                                                       */
;/*      This function sets up the global system stack variable and       */
;/*      transfers control to the target independent initialization       */
;/*      function INC_Initialize.  Responsibilities of this function      */
;/*      include the following:                                           */
;/*                                                                       */
;/*             - Setup necessary processor/system control registers      */
;/*             - Initialize the vector table                             */
;/*             - Setup the system stack pointers                         */
;/*             - Setup the timer interrupt                               */
;/*             - Calculate the timer HISR stack and priority             */
;/*             - Calculate the first available memory address            */
;/*             - Transfer control to INC_Initialize to initialize all of */
;/*               the system components.                                  */
;/*                                                                       */
;/* AUTHOR                                                                */
;/*                                                                       */
;/*      Barry Sellew, Accelerated Technology, Inc.                       */
;/*                                                                       */
;/* CALLED BY                                                             */
;/*                                                                       */
;/*      none  					 			  */
;/*                                                                       */
;/* CALLS                                                                 */
;/*                                                                       */
;/*      INC_Initialize                      Common initialization        */
;/*                                                                       */
;/* INPUTS                                                                */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* OUTPUTS                                                               */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* HISTORY                                                               */
;/*                                                                       */
;/*         NAME            DATE                    REMARKS               */
;/*                                                                       */
;/*      B. Sellew       01-19-1996      Created initial version 1.0      */
;/*	 B. Sellew	 01-22-1996	 Verified version 1.0	  	  */
;/*                                                                       */
;/*************************************************************************/
;VOID    INT_Initialize(void)
;{
	.def	_c_int00
_c_int00

	.include "init.asm"

addrCS0	      	.word	 0xfffffb00		    ; CS0 address space

    .if BOARD = 34
CSConfigTable   .long    CS0_CONFIG	
CS7_SIZE        .equ     0x2000       ; 8 kB
CS7_ADDR        .equ     0x03800000   ; initial address before toggling nIBOOT
SRAM_ADDR       .equ     0x03000000   ; Internal SRAM start address
SRAM_SIZE       .equ     0x00040000   ; 256kB 
EXTRA_CONF      .short   0x013E    ;     Boot configuration
DEF_EXTRA_CONF  .short   0x063E    ;     Default configuration
addrCS7         .word    0xFFFFFB08   ; CS7 configuration
addrExtraConf   .word    0xFFFFFB10   ; Extra configuration
armio_in        .word    0xFFFE4800   ; ARMIO_IN register address
armio_out       .word    0xFFFE4802   ; ARMIO_OUT register address
    .endif

    .if BOARD = 40 | 41
EX_MPU_CONF_REG .word    0xFFFEF006   ; Extended MPU configuration register address
EX_FLASH_VALUE  .short   0x0008       ; set bit to enable A22
    .endif

    .if CHIPSET = 4
CNTL_ARM_CLK_REG .word   0xFFFFFD00   ; CNTL_ARM_CLK register address
DPLL_CNTRL_REG   .word   0xFFFF9800   ; DPLL control register address
RHEA_CNTL_REG    .word   0xFFFFF900   ; RHEA control register address


CNTL_ARM_CLK_RST .short  0x1081	  ; Initialization of CNTL_ARM_CLK register
                                  ; Use DPLL, Divide by 1
DPLL_CONTROL_RST .short  0x2002   ; Configure DPLL in default state
RHEA_CONTROL_RST .short  0xFF22   ; Set access factor in order to access the DPLL register
                                  ; independently of the ARM clock
    .elseif CHIPSET = 6
CNTL_ARM_CLK_REG        .word  0xFFFFFD00   ; CNTL_ARM_CLK register address
CNTLCLK_26MHZ_SELECTOR  .short 0x0040       ; VTCXO_26 selector

    .elseif CHIPSET = 7
CNTL_ARM_CLK_REG  .word   0xFFFFFD00   ; CNTL_ARM_CLK register address
DPLL_CNTRL_REG    .word   0xFFFF9800   ; DPLL control register address
EXTRA_CONTROL_REG .word   0xFFFFFB10   ; Extra Control register CONF address
MPU_CTL_REG       .word   0xFFFFFF08   ; MPU_CTL register address

CNTL_ARM_CLK_RST  .short  0x1081       ; Initialization of CNTL_ARM_CLK register
                                       ; Use DPLL, Divide by 1
DPLL_CONTROL_RST  .short  0x2002       ; Configure DPLL in default state
DISABLE_DU_MASK   .short  0x0800       ; Mask to Disable the DU module
ENABLE_DU_MASK	  .short  0xF7FF       ; Mask to Enable the DU module
MPU_CTL_RST       .short  0x0000       ; Reset value of MPU_CTL register - All protections disabled

    .elseif CHIPSET = 8
CNTL_ARM_CLK_REG  .word   0xFFFFFD00   ; CNTL_ARM_CLK register address
DPLL_CNTRL_REG    .word   0xFFFF9800   ; DPLL control register address
EXTRA_CONTROL_REG .word   0xFFFFFB10   ; Extra Control register CONF address
MPU_CTL_REG       .word   0xFFFFFF08   ; MPU_CTL register address

CNTL_ARM_CLK_RST  .short  0x1081       ; Initialization of CNTL_ARM_CLK register
                                       ; Use DPLL, Divide by 1
DPLL_CONTROL_RST  .short  0x2002       ; Configure DPLL in default state
DISABLE_DU_MASK   .short  0x0800       ; Mask to Disable the DU module
ENABLE_DU_MASK	  .short  0xF7FF       ; Mask to Enable the DU module
MPU_CTL_RST       .short  0x0000       ; Reset value of MPU_CTL register - All protections disabled

    .elseif CHIPSET = 10
CNTL_ARM_CLK_REG  .word   0xFFFFFD00   ; CNTL_ARM_CLK register address
DPLL_CNTRL_REG    .word   0xFFFF9800   ; DPLL control register address
EXTRA_CONTROL_REG .word   0xFFFFFB10   ; Extra Control register CONF address
MPU_CTL_REG       .word   0xFFFFFF08   ; MPU_CTL register address

CNTL_ARM_CLK_RST  .short  0x1081       ; Initialization of CNTL_ARM_CLK register
                                       ; Use DPLL, Divide by 1
DPLL_CONTROL_RST  .short  0x2002       ; Configure DPLL in default state
DISABLE_DU_MASK   .short  0x0800       ; Mask to Disable the DU module
ENABLE_DU_MASK	  .short  0xF7FF       ; Mask to Enable the DU module
MPU_CTL_RST       .short  0x0000       ; Reset value of MPU_CTL register - All protections disabled

    .elseif CHIPSET = 11
CNTL_ARM_CLK_REG  .word   0xFFFFFD00   ; CNTL_ARM_CLK register address
DPLL_CNTRL_REG    .word   0xFFFF9800   ; DPLL control register address
EXTRA_CONTROL_REG .word   0xFFFFFB10   ; Extra Control register CONF address
MPU_CTL_REG       .word   0xFFFFFF08   ; MPU_CTL register address

CNTL_ARM_CLK_RST  .short  0x1081       ; Initialization of CNTL_ARM_CLK register
                                       ; Use DPLL, Divide by 1
DPLL_CONTROL_RST  .short  0x2002       ; Configure DPLL in default state
DISABLE_DU_MASK   .short  0x0800       ; Mask to Disable the DU module
ENABLE_DU_MASK	  .short  0xF7FF       ; Mask to Enable the DU module
MPU_CTL_RST       .short  0x0000       ; Reset value of MPU_CTL register - All protections disabled

    .elseif CHIPSET = 12
DBG_DMA_P2        .word   0xFFFEF02C   ; DBG_DMA_P2 register address    
CNTL_ARM_CLK_REG  .word   0xFFFFFD00   ; CNTL_ARM_CLK register address
DPLL_CNTRL_REG    .word   0xFFFF9800   ; DPLL control register address
EXTRA_CONTROL_REG .word   0xFFFFFB10   ; Extra Control register CONF address
MPU_CTL_REG       .word   0xFFFFFF08   ; MPU_CTL register address

CNTL_ARM_CLK_RST  .short  0x1081	     ; Initialization of CNTL_ARM_CLK register
                                       ; Use DPLL, Divide by 1
DPLL_CONTROL_RST  .short  0x2006       ; Configure DPLL in default state
DISABLE_DU_MASK   .short  0x0800       ; Mask to Disable the DU module
MPU_CTL_RST       .short  0x0000       ; Reset value of MPU_CTL register - All protections disabled
DBG_DMA_P2_RST    .short  0x0002       ; DBG_DMA_P2 register reset value
    .endif ; CHIPSET = 4 or 6 or 7 or 8 or 10 or 11 or 12


c_cinit	.long	cinit

        .def  	_INT_Initialize
_INT_Initialize

;
;  Configuration of ARM clock and DPLL frequency
;
    .if CHIPSET = 4
;
;  Configure RHEA access factor in order to allow the access of DPLL register
;
       ldr     r1,RHEA_CNTL_REG      ; Load address of RHEA control register in R1
       ldrh    r2,RHEA_CONTROL_RST   ; Load RHEA configuration value in R2
       strh    r2,[r1]               ; Store DPLL reset value in RHEA control register
  
;
;  Configure DPLL register with reset value
;
       ldr     r1,DPLL_CNTRL_REG     ; Load address of DPLL register in R1
       ldrh    r2,DPLL_CONTROL_RST   ; Load DPLL reset value in R2
       strh    r2,[r1]               ; Store DPLL reset value in DPLL register

;
; Wait that DPLL goes in BYPASS mode
;
Wait_DPLL_Bypass
       ldr     r2,[r1]               ; Load DPLL register
       and     r2,r2,#1              ; Perform a mask on bit 0
       cmp     r2,#1                 ; Compare DPLL lock bit
       beq     Wait_DPLL_Bypass      ; Wait Bypass mode (i.e. bit[0]='0')

;
;  Configure CNTL_ARM_CLK register with reset value: DPLL is used to
;  generate ARM clock with division factor of 1.
;
       ldr     r1,CNTL_ARM_CLK_REG  ; Load address of CNTL_ARM_CLK register in R1
       ldrh    r2,CNTL_ARM_CLK_RST  ; Load CNTL_ARM_CLK reset value in R2
       strh    r2,[r1]              ; Store CNTL_ARM_CLK reset value in CNTL_ARM_CLK register

    .elseif CHIPSET = 6

;
;  Set VTCXO_26MHZ bit to '1' in case of the VTCXO clock is 26MHz instead
;  of 13MHz.
;
       ldr     r1, CNTL_ARM_CLK_REG       ; Load CLKM base register address in R1
       ldrh    r2, [r1,#2]                ; Load contents of CNTL_CLK register in R2
       ldr     r0, CNTLCLK_26MHZ_SELECTOR ; Load configuration of 26MHz selector
       orr     r0, r0, r2;
       strh    r0, [r1,#2];

; Wait a while until clock is stable (required for AvengerII)
        mov     r0,#0x100
WaitAWhile1:
        sub     r0, r0, #1
        cmp     r0, #0
        bne     WaitAWhile1

    .elseif CHIPSET = 7
;
;  Configure DPLL register with reset value
;
       ldr     r1,DPLL_CNTRL_REG     ; Load address of DPLL register in R1
       ldrh    r2,DPLL_CONTROL_RST   ; Load DPLL reset value in R2
       strh    r2,[r1]               ; Store DPLL reset value in DPLL register

;
;  Wait that DPLL goes in BYPASS mode
;
Wait_DPLL_Bypass
       ldr     r2,[r1]               ; Load DPLL register
       and     r2,r2,#1              ; Perform a mask on bit 0
       cmp     r2,#1                 ; Compare DPLL lock bit
       beq     Wait_DPLL_Bypass      ; Wait Bypass mode (i.e. bit[0]='0')

;
;  Configure CNTL_ARM_CLK register with reset value: DPLL is used to
;  generate ARM clock with division factor of 1.
;
       ldr     r1,CNTL_ARM_CLK_REG  ; Load address of CNTL_ARM_CLK register in R1
       ldrh    r2,CNTL_ARM_CLK_RST  ; Load CNTL_ARM_CLK reset value in R2
       strh    r2,[r1]              ; Store CNTL_ARM_CLK reset value in CNTL_ARM_CLK register
  
;
;  Disable/Enable the DU module by setting/resetting bit 11 to '1'/'0'
;
       ldr     r1,EXTRA_CONTROL_REG ; Load address of Extra Control register CONF
       ;ldrh    r2,DISABLE_DU_MASK   ; Load mask to write in Extra Control register CONF
       ldrh    r2,ENABLE_DU_MASK    ; Load mask to write in Extra Control register CONF
       ldrh    r0,[r1]              ; Load Extra Control register CONF in r0
       ;orr     r0,r0,r2             ; Disable DU module
       and     r0,r0,r2             ; Enable DU module
       strh    r0,[r1]              ; Store configuration in Extra Control register CONF
  
;
;  Disable all MPU protections
;
       ldr     r1,MPU_CTL_REG       ; Load address of MPU_CTL register
       ldrh    r2,MPU_CTL_RST       ; Load reset value of MPU_CTL register
       strh    r2,[r1]              ; Store reset value of MPU_CTL register

    .elseif CHIPSET = 8
;
;  Configure DPLL register with reset value
;
       ldr     r1,DPLL_CNTRL_REG     ; Load address of DPLL register in R1
       ldrh    r2,DPLL_CONTROL_RST   ; Load DPLL reset value in R2
       strh    r2,[r1]               ; Store DPLL reset value in DPLL register

;
;  Wait that DPLL goes in BYPASS mode
;
Wait_DPLL_Bypass
       ldr     r2,[r1]               ; Load DPLL register
       and     r2,r2,#1              ; Perform a mask on bit 0
       cmp     r2,#1                 ; Compare DPLL lock bit
       beq     Wait_DPLL_Bypass      ; Wait Bypass mode (i.e. bit[0]='0')

;
;  Configure CNTL_ARM_CLK register with reset value: DPLL is used to
;  generate ARM clock with division factor of 1.
;
       ldr     r1,CNTL_ARM_CLK_REG  ; Load address of CNTL_ARM_CLK register in R1
       ldrh    r2,CNTL_ARM_CLK_RST  ; Load CNTL_ARM_CLK reset value in R2
       strh    r2,[r1]              ; Store CNTL_ARM_CLK reset value in CNTL_ARM_CLK register
  
;
;  Disable/Enable the DU module by setting/resetting bit 11 to '1'/'0'
;
       ldr     r1,EXTRA_CONTROL_REG ; Load address of Extra Control register CONF
       ;ldrh    r2,DISABLE_DU_MASK   ; Load mask to write in Extra Control register CONF
       ldrh    r2,ENABLE_DU_MASK    ; Load mask to write in Extra Control register CONF
       ldrh    r0,[r1]              ; Load Extra Control register CONF in r0
       ;orr     r0,r0,r2             ; Disable DU module
       and     r0,r0,r2             ; Enable DU module
       strh    r0,[r1]              ; Store configuration in Extra Control register CONF
  
;
;  Disable all MPU protections
;
       ldr     r1,MPU_CTL_REG       ; Load address of MPU_CTL register
       ldrh    r2,MPU_CTL_RST       ; Load reset value of MPU_CTL register
       strh    r2,[r1]              ; Store reset value of MPU_CTL register

    .elseif CHIPSET = 10
;
;  Configure DPLL register with reset value
;
       ldr     r1,DPLL_CNTRL_REG     ; Load address of DPLL register in R1
       ldrh    r2,DPLL_CONTROL_RST   ; Load DPLL reset value in R2
       strh    r2,[r1]               ; Store DPLL reset value in DPLL register

;
;  Wait that DPLL goes in BYPASS mode
;
Wait_DPLL_Bypass
       ldr     r2,[r1]               ; Load DPLL register
       and     r2,r2,#1              ; Perform a mask on bit 0
       cmp     r2,#1                 ; Compare DPLL lock bit
       beq     Wait_DPLL_Bypass      ; Wait Bypass mode (i.e. bit[0]='0')

;
;  Configure CNTL_ARM_CLK register with reset value: DPLL is used to
;  generate ARM clock with division factor of 1.
;
       ldr     r1,CNTL_ARM_CLK_REG  ; Load address of CNTL_ARM_CLK register in R1
       ldrh    r2,CNTL_ARM_CLK_RST  ; Load CNTL_ARM_CLK reset value in R2
       strh    r2,[r1]              ; Store CNTL_ARM_CLK reset value in CNTL_ARM_CLK register
  
;
;  Disable/Enable the DU module by setting/resetting bit 11 to '1'/'0'
;
       ldr     r1,EXTRA_CONTROL_REG ; Load address of Extra Control register CONF
       ;ldrh    r2,DISABLE_DU_MASK   ; Load mask to write in Extra Control register CONF
       ldrh    r2,ENABLE_DU_MASK    ; Load mask to write in Extra Control register CONF
       ldrh    r0,[r1]              ; Load Extra Control register CONF in r0
       ;orr     r0,r0,r2             ; Disable DU module
       and     r0,r0,r2             ; Enable DU module
       strh    r0,[r1]              ; Store configuration in Extra Control register CONF
  
;
;  Disable all MPU protections
;
       ldr     r1,MPU_CTL_REG       ; Load address of MPU_CTL register
       ldrh    r2,MPU_CTL_RST       ; Load reset value of MPU_CTL register
       strh    r2,[r1]              ; Store reset value of MPU_CTL register

    .elseif CHIPSET = 11
;
;  Configure DPLL register with reset value
;
       ldr     r1,DPLL_CNTRL_REG     ; Load address of DPLL register in R1
       ldrh    r2,DPLL_CONTROL_RST   ; Load DPLL reset value in R2
       strh    r2,[r1]               ; Store DPLL reset value in DPLL register

;
;  Wait that DPLL goes in BYPASS mode
;
Wait_DPLL_Bypass
       ldr     r2,[r1]               ; Load DPLL register
       and     r2,r2,#1              ; Perform a mask on bit 0
       cmp     r2,#1                 ; Compare DPLL lock bit
       beq     Wait_DPLL_Bypass      ; Wait Bypass mode (i.e. bit[0]='0')

;
;  Configure CNTL_ARM_CLK register with reset value: DPLL is used to
;  generate ARM clock with division factor of 1.
;
       ldr     r1,CNTL_ARM_CLK_REG  ; Load address of CNTL_ARM_CLK register in R1
       ldrh    r2,CNTL_ARM_CLK_RST  ; Load CNTL_ARM_CLK reset value in R2
       strh    r2,[r1]              ; Store CNTL_ARM_CLK reset value in CNTL_ARM_CLK register
  
;
;  Disable/Enable the DU module by setting/resetting bit 11 to '1'/'0'
;
       ldr     r1,EXTRA_CONTROL_REG ; Load address of Extra Control register CONF
       ;ldrh    r2,DISABLE_DU_MASK   ; Load mask to write in Extra Control register CONF
       ldrh    r2,ENABLE_DU_MASK    ; Load mask to write in Extra Control register CONF
       ldrh    r0,[r1]              ; Load Extra Control register CONF in r0
       ;orr     r0,r0,r2             ; Disable DU module
       and     r0,r0,r2             ; Enable DU module
       strh    r0,[r1]              ; Store configuration in Extra Control register CONF
  
;
;  Disable all MPU protections
;
       ldr     r1,MPU_CTL_REG       ; Load address of MPU_CTL register
       ldrh    r2,MPU_CTL_RST       ; Load reset value of MPU_CTL register
       strh    r2,[r1]              ; Store reset value of MPU_CTL register

    .elseif CHIPSET = 12
  
  .if BOARD = 6
  ; Configure DBG_DMA_P2 reg => GPO_2 output pin for EVA4
  ldr	r1,DBG_DMA_P2         ; Load address of DBG_DMA_P2 register in R1
  ldrh	r2,DBG_DMA_P2_RST     ; Load DBG_DMA_P2 reset value in R2
  strh	r2,[r1]               ; Store reset value in register
  ;
  .endif ; BOARD = 6

  ;
  ;  Configure DPLL register with reset value
  ;
	ldr	  r1,DPLL_CNTRL_REG     ; Load address of DPLL register in R1
	ldrh	r2,DPLL_CONTROL_RST   ; Load DPLL reset value in R2
	strh	r2,[r1]               ; Store DPLL reset value in DPLL register

;
;  Wait that DPLL goes in BYPASS mode
;
Wait_DPLL_Bypass
  ldr   r2,[r1]               ; Load DPLL register
  and   r2,r2,#1              ; Perform a mask on bit 0
  cmp   r2,#1                 ; Compare DPLL lock bit
  beq   Wait_DPLL_Bypass      ; Wait Bypass mode (i.e. bit[0]='0')

  ;
  ;  Configure CNTL_ARM_CLK register with reset value: DPLL is used to
  ;  generate ARM clock with division factor of 1.
  ;
	ldr	  r1,CNTL_ARM_CLK_REG  ; Load address of CNTL_ARM_CLK register in R1
	ldrh	r2,CNTL_ARM_CLK_RST  ; Load CNTL_ARM_CLK reset value in R2
	strh	r2,[r1]              ; Store CNTL_ARM_CLK reset value in CNTL_ARM_CLK register
  
;
;  Disable the DU module by setting bit 11 to '1'
;
;  ldr   r1,EXTRA_CONTROL_REG ; Load address of Extra Control register CONF
;  ldrh  r2,DISABLE_DU_MASK   ; Load mask to write in Extra Control register CONF
;  ldrh  r0,[r1]              ; Load Extra Control register CONF in r0
;  orr   r0,r0,r2             ; Disable DU module
;  strh  r0,[r1]              ; Store configuration in Extra Control register CONF
  
  ;
  ;  Disable all MPU protections
  ;
  ldr   r1,MPU_CTL_REG       ; Load address of MPU_CTL register
  ldrh  r2,MPU_CTL_RST       ; Load reset value of MPU_CTL register
  strh  r2,[r1]              ; Store reset value of MPU_CTL register

    .endif ; CHIPSET = 4 or 6 or 7 or 8 or 10 or 11 or 12

;
;  Wait-state configuration of external and internal memories
;
    .if BOARD = 34
;
;       Wait states for Perseus - see IQ_InitWaitStates for details
;


        mov     r0, #NUM_CS_REGS        ; number of chip selects to configure
        ldr     r1, addrCS0             ; first CS register
        ldr     r2, CSConfigTable       ; table of values to program
        
ConfigCS:          
        ldrh    r3,[r2]
        strh    r3,[r1]
        add     r1, r1, #2
        add     r2, r2, #2
        sub     r0, r0, #1
        cmp     r0, #0
        bne     ConfigCS

        bl    Ensure_external_access
        bl    Copy_code_into_CS7
        bl    Toggle_nIBoot

; Wait a while - not quite sure why, but it is required for Avenger II
        mov     r0,#0x100
WaitAWhile2:
        sub     r0, r0, #1
        cmp     r0, #0
        bne     WaitAWhile2

        bl    Clear_Internal_SRAM       ; This is required if the BSS is not in SRAM

    .elseif BOARD = 35

        ldr    r1,addrCS0
        ldrh   r2,CS0_MEM_REG           ; CS0 initialization
        strh   r2,[r1]
        ldrh   r2,CS1_MEM_REG           ; CS1 initialization
        strh   r2,[r1,#0x2]
        ldrh   r2,CS2_MEM_REG           ; CS2 initialization
        strh   r2,[r1,#0x4]
        ldrh   r2,CS7_MEM_REG           ; CS7 initialization
        strh   r2,[r1,#0x8]
        ldrh   r2,CS6_MEM_REG           ; CS6 initialization
        strh   r2,[r1,#0xC]
        mov    r2,#API_ADAPT            ; API-RHEA configuration
        strh   r2,[r1,#0xE]

        bl    Ensure_external_access
        bl    Copy_code_into_CS7
        bl    Toggle_nIBoot
        bl    Clear_Internal_SRAM       ; This is required if the BSS is not in SRAM

    .else

       ldr     r1,addrCS0
  .if CHIPSET != 12
       ldrh    r2,CS0_MEM_REG			    ; ROM initialization
       strh    r2,[r1]                      ; CS0

       ldrh    r2,CS1_MEM_REG               ; RAM Initialization
       strh    r2,[r1,#2]		            ; CS1

       ldrh    r2,CS2_MEM_REG               ; RAM Initialization
       strh    r2,[r1,#4]		            ; CS2

       ldrh    r2,CS3_MEM_REG               ; Parallel I/O on B-Sample
       strh    r2,[r1,#6]                   ; CS3 (unused on EVA4?)

       ldrh    r2,CS4_MEM_REG               ; Latch on B-Sample
       strh    r2,[r1,#0xa]                 ; CS4 (unused on EVA4)

  .else

  ldrh  r2,CS0_MEM_REG  ; CALYPSO PLUS TEST MODE - TO BE ERASED - FLASH Initialization
  strh  r2,[r1,#0x0]    ; CS0

  ldrh  r2,CS5_MEM_REG  ; FLASH Initialization
  strh  r2,[r1,#0xA]    ; CS5

  ldrh  r2,CS4_MEM_REG  ; RAM Initialization
  strh  r2,[r1,#0x8]    ; CS4

  .endif

    .if CHIPSET = 3
       ldrh    r2,CS6_MEM_REG               ; Internal SRAM initialization
       strh    r2,[r1,#0xc]		            ; CS6 Internal RAM

    .elseif CHIPSET = 4
       ldrh    r2,CS6_MEM_REG               ; Internal SRAM initialization
       strh    r2,[r1,#0xc]	               	; CS6 Internal RAM
        
       ldrh    r2,CS7_MEM_REG               ; Internal SRAM initialization
       strh    r2,[r1,#0x8]	               	; CS7 Internal Boot RAM

    .elseif CHIPSET = 5
       ldrh    r2,CS6_MEM_REG               ; Internal SRAM initialization
       strh    r2,[r1,#0xc]		            ; CS6 Internal RAM

    .elseif CHIPSET = 6
       ldrh    r2,CS6_MEM_REG               ; Internal SRAM initialization
       strh    r2,[r1,#0xc]		            ; CS6 Internal RAM

    .elseif CHIPSET = 7
       ldrh    r2,CS6_MEM_REG               ; Internal SRAM initialization
       strh    r2,[r1,#0xc]		            ; CS6 Internal RAM
  
       ldrh    r2,CS7_MEM_REG               ; Internal SRAM initialization
       strh    r2,[r1,#0x8]		            ; CS7 Internal Boot ROM

    .elseif CHIPSET = 8
       ldrh    r2,CS6_MEM_REG               ; Internal SRAM initialization
       strh    r2,[r1,#0xc]		            ; CS6 Internal RAM
  
       ldrh    r2,CS7_MEM_REG               ; Internal SRAM initialization
       strh    r2,[r1,#0x8]		            ; CS7 Internal Boot ROM

    .elseif CHIPSET = 10
       ldrh    r2,CS6_MEM_REG               ; Internal SRAM initialization
       strh    r2,[r1,#0xc]		            ; CS6 Internal RAM
  
       ldrh    r2,CS7_MEM_REG               ; Internal SRAM initialization
       strh    r2,[r1,#0x8]		            ; CS7 Internal Boot ROM

    .elseif CHIPSET = 11
       ldrh    r2,CS6_MEM_REG               ; Internal SRAM initialization
       strh    r2,[r1,#0xc]		            ; CS6 Internal RAM
  
       ldrh    r2,CS7_MEM_REG               ; Internal SRAM initialization
       strh    r2,[r1,#0x8]		            ; CS7 Internal Boot ROM
    .endif ; CHIPSET = 3 or 4 or 5 or 6 or 7 or 8 or 10 or 11

       ldrh    r2,CTL_MEM_REG               ; API-RHEA configuration
       strh    r2,[r1,#0xe]

    .endif ; BOARD = 34 | 35

    .if BOARD = 40 | 41
;    /* On D-Sample Board, use A22 mode (ADD(22) instead of CS4) to be able to
;       address 8 Mbytes especially with CS0 (Flash) & CS3 (External Peripherals) */
       ldr     r1,EX_MPU_CONF_REG
       ldrh    r2,[r1]
       ldr     r0,EX_FLASH_VALUE
       orr     r0, r0, r2
       strh    r0,[r1]
    .endif

;
;    /* Insure that the processor is in supervisor mode.  */
;
        MRS     a1,CPSR                     ; Pickup current CPSR
        BIC     a1,a1,#MODE_MASK            ; Clear the mode bits
        ORR     a1,a1,#SUP_MODE             ; Set the supervisor mode bits
        ORR     a1,a1,#LOCKOUT              ; Insure IRQ and FIQ interrupts are
                                            ;   locked out
        MSR     CPSR,a1                     ; Setup the new CPSR
;

;
;
; REWORK OF .bss INITIALIZATION - start
; Creation of INT_memset and INT_memcpy, respectively identical to memset and 
; memcpy from the rts library of compiler V2.51/2.54.
; They are used to make the initialization of the .bss section and the load 
; of the internal ram code not dependent to the 32-bit alignment.
; The old code used for the initialization and the load used a loop with
; 4-byte increment, assuming the 32-bit alignment of the .bss section.
; This alignment is not necessary true.
;
;    /* Clear the un-initialized global and static C data areas.  */
;       Initialize the system stack pointer a first time to allow use of memset function
;       which needs stack.
;       The system stack pointers will be fully initialized after having cleared
;       the BSS area.  */
;        
        LDR     a1,StackSegment             ; Pickup the begining address from .cmd file
                                            ;   (is aligned on 8 byte boundary)

        MOV     a2,#SYSTEM_SIZE             ; Pickup system stack size
        SUB     a2,a2,#4                    ; Subtract one word for first addr
        ADD     a3,a1,a2                    ; Build start of system stack area

        MOV     sp,a3                       ; Setup initial stack pointer

        STMFD   sp!,{a1-a4}               ; Save a1-a4 registers to stack

        LDR     a1,BSS_Start              ; Pickup the start of the BSS area
        LDR     a3,BSS_End                ; Pickup the end of the BSS area
        SUB     a3,a3,a1                  ; Calculate size of the BSS area
        MOV     a2,#0                     ; Clear value in a2

        BL      _INT_memset                   ; Clear the BSS area using memset function

  .if LONG_JUMP >= 3                      ;
        LDR     a1,BSS_IntMem_Start       ; Pickup the start of the BSS area
        LDR     a3,BSS_IntMem_End         ; Pickup the end of the BSS area
        SUB     a3,a3,a1                  ; Calculate size of the BSS area
        MOV     a2,#0                     ; Clear value in a2

        BL      _INT_memset               ; Clear the BSS area using memset function

  .endif

        LDMFD   sp!,{a1-a4}               ; Restore a1-a4 registers from stack

; REWORK OF .bss INITIALIZATION - end  

;
;    /* Setup the vectors loaded flag to indicate to other routines in the 
;       system whether or not all of the default vectors have been loaded. 
;       If INT_Loaded_Flag is 1, all of the default vectors have been loaded.
;       Otherwise, if INT_Loaded_Flag is 0, registering an LISR cause the
;       default vector to be loaded.  In the THUMB this variable is always
;       set to 1.  All vectors must be setup by this function.  */
;    INT_Loaded_Flag =  0;
;
        MOV     a1,#1                       ; All vectors are assumed loaded
        LDR     a2,Loaded_Flag   	        ; Build address of loaded flag  
        STR     a1,[a2,#0]                  ; Initialize loaded flag
;
;    /* Initialize the system stack pointers.  This is done after the BSS is
;       cleared because the TCD_System_Stack pointer is a BSS variable!  It is
;       assumed that the .cmd file is written to direct where these stacks should
;       be allocated and to align them on double word boundaries.
;
        LDR     a1,StackSegment             ; Pickup the begining address from .cmd file
                                            ;   (is aligned on 8 byte boundary)
        MOV     a2,#SYSTEM_SIZE             ; Pickup system stack size
        SUB     a2,a2,#4                    ; Subtract one word for first addr
        ADD     a3,a1,a2                    ; Build start of system stack area
        MOV     v7,a1                       ; Setup initial stack limit
        LDR     a4,System_Limit             ; Pickup system stack limit address
        STR     v7,[a4, #0]                 ; Save stack limit
        MOV     sp,a3                       ; Setup initial stack pointer
        LDR     a4,System_Stack             ; Pickup system stack address
        STR     sp,[a4, #0]                 ; Save stack pointer
        MOV     a2,#IRQ_STACK_SIZE          ; Pickup IRQ stack size in bytes
        ADD     a3,a3,a2                    ; Allocate IRQ stack area
        MRS     a1,CPSR                     ; Pickup current CPSR
        BIC     a1,a1,#MODE_MASK            ; Clear the mode bits
        ORR     a1,a1,#IRQ_MODE             ; Set the IRQ mode bits
        MSR     CPSR,a1                     ; Move to IRQ mode
        MOV     sp,a3                       ; Setup IRQ stack pointer
        MOV     a2,#FIQ_STACK_SIZE          ; Pickup FIQ stack size in bytes
        ADD     a3,a3,a2                    ; Allocate FIQ stack area
        MRS     a1,CPSR                     ; Pickup current CPSR
        BIC     a1,a1,#MODE_MASK            ; Clear the mode bits
        ORR     a1,a1,#FIQ_MODE             ; Set the FIQ mode bits
        MSR     CPSR,a1                     ; Move to the FIQ mode
        MOV     sp,a3                       ; Setup FIQ stack pointer

        MRS     a1,CPSR                     ; Pickup current CPSR
        BIC     a1,a1,#MODE_MASK            ; Clear the mode bits
        ORR     a1,a1,#ABORT_MODE           ; Set the Abort mode bits
        MSR     CPSR,a1                     ; Move to the Abort mode
        LDR     sp,Exception_Stack          ; Setup Abort stack pointer

        MRS     a1,CPSR                     ; Pickup current CPSR
        BIC     a1,a1,#MODE_MASK            ; Clear the mode bits
        ORR     a1,a1,#UNDEF_MODE           ; Set the Undefined mode bits
        MSR     CPSR,a1                     ; Move to the Undefined mode
        LDR     sp,Exception_Stack          ; Setup Undefined stack pointer
                                            ;   (should never be used)

; go to Supervisor Mode
        MRS     a1,CPSR                     ; Pickup current CPSR
        BIC     a1,a1,#MODE_MASK            ; Clear mode bits
        ORR     a1,a1,#SUP_MODE             ; Set the supervisor mode bits
        MSR     CPSR,a1                     ; All interrupt stacks are setup,
                                            ;   return to supervisor mode
;
;    /* Define the global data structures that need to be initialized by this
;       routine.  These structures are used to define the system timer 
;       management HISR.  */
;    TMD_HISR_Stack_Ptr =        (VOID *) a3;
;    TMD_HISR_Stack_Size =       TIMER_SIZE;
;    TMD_HISR_Priority =         TIMER_PRIORITY;
;
; TMD_HISR_Stack_Ptr points at the top (the lowest address) of the allocated
; area. The Timer HISR (called "SYSTEM H") and its related stack will be created
; in TMI_Initialize(). The current stack pointer will be set at the bottom (the
; lowest address) of the expected area.

        LDR     a4,HISR_Stack_Ptr  	        ; Pickup variable's address
        ADD     a3,a3,#4                    ; Increment to next available word
        STR     a3,[a4, #0]                 ; Setup timer HISR stack pointer
        MOV     a2,#TIMER_SIZE              ; Pickup the timer HISR stack size
        BIC     a2,a2,#3                    ; Insure word alignment
        ADD     a3,a3,a2                    ; Allocate the timer HISR stack 
                                            ;   from available memory
        LDR     a4,HISR_Stack_Size    	    ; Pickup variable's address
        STR     a2,[a4, #0]                 ; Setup timer HISR stack size
        MOV     a2,#TIMER_PRIORITY          ; Pickup timer HISR priority (0-2)
        LDR     a4,HISR_Priority            ; Pickup variable's address
        STR     a2,[a4, #0]                 ; Setup timer HISR priority

  .if CHIPSET = 12
      ; This sequence must be always done in order to download the interrupt
      ; vector remapping
        MOV     V1, a3                      ; Save a3 register
        BL      _f_load_int_mem             ; Download FLASH to Internal RAM
        MOV     a3, V1                      ; Restore a3 register
  .else

  .if LONG_JUMP >= 3
        MOV     V1, a3                      ; Save a3 register
        BL      _f_load_int_mem             ; Download FLASH to Internal RAM
        MOV     a3, V1                      ; Restore a3 register
  .endif

  .endif ; CHIPSET != 12

; We now fill up the System, IRQ, FIQ and System Timer HISR stacks with 0xFE for
; checking the status of the stacks later. 
; inputs:
;     a3 still has the bottom of all four stacks and is aligned. 
; algorithm:
;     We start from the top of all four stacks (*System_Limit), which is
;     necessarily aligned.  We store 0xFEFEFEFE until we have filled the
;     bottom of the fourth stack
; outputs:
;     memory has 0xFE on all four stacks: System, FIQ, IRQ and System Timer HISR
;     a3 still has the bottom of all four stacks

        LDR     a2,System_Limit             ; pickup system stack limit address
        LDR     a1,[a2]                     ; a1 = StackSegment
        MOV     a4,#0FEh                    ; use this and the next 7 instructons to set a4 = 0xFEFEFEFE
        STRB    a4,[a1, #0]
        STRB    a4,[a1, #1]
        STRB    a4,[a1, #2]
        STRB    a4,[a1, #3]
        LDR     a4,[a1],#4                  ; stored first word, move to second

fill_stack:
        STR     a4,[a1],#4                  ; store a word and increment by four
        CMP     a1,a3                       ; is this the last address?
        BLT     fill_stack                  ; if not, loop back

;
;       Perform auto-initialization.  if cinit is -1, then there is none.
;
        LDR     r0, c_cinit
        CMN     r0, #1
        BLNE    _auto_init
;
;     /* Call INC_Initialize with a pointer to the first available memory 
;        address after the compiler's global data.  This memory may be used
;        by the application.  */
;     INC_Initialize(first_available_memory);
;
        MOV     a1,a3                       ; Pass the first available memory
	B       _INC_Initialize		        ; to high-level initialization
;}
;


  .if  BOARD=35 | BOARD=34

;/*
; * FUNCTION
; *
; *      Ensure_external_access
; */
Ensure_external_access: 
        ;AI_ResetBit(4);             // request shared mem clock
        ldr    r1, armio_out
        ldrh   r2, [r1]
        bic    r2, r2, #0x10
        strh   r2, [r1]

        ;while(AI_ReadBit(5)!=1);    // wait for acknowledge
ack:
        ldr     r1, armio_in
        ldrh    r2, [r1]
        and     r2, r2, #0x20
        cmp     r2, #0x20
        bne     ack  
        bx      lr                      ; Return to caller

;/*
; * FUNCTION
; *
; *      Copy_code_into_CS7
; */
Copy_code_into_CS7:
        ldr     r1, addrExtraConf
        ldr     r3, DEF_EXTRA_CONF
        strh    r3, [r1]                ; ensure CS7 selects internal memory

        mov     r0, #CS7_SIZE           ; size of CS7 memory in bytes
        mov     r1, #CS7_ADDR           ; destination
        mov     r2, #0                  ; source
CopyIntCode:          
        ldr     r3,[r2]
        str     r3,[r1]
        add     r1, r1, #4
        add     r2, r2, #4
        sub     r0, r0, #4
        cmp     r0, #0
        bne     CopyIntCode

        ldr     r1, addrCS7
        ldr     r2, [r1]
        bic     r2, r2, #0x80           ; Write Enable OFF on CS7
        strh    r2, [r1]
        bx      lr                      ; Return to caller

;/*
; * FUNCTION
; *
; *      Toggle_nIBoot
; */
Toggle_nIBoot:                                                                       
        ldr     r1, addrExtraConf       ; Address of Extra Conf Register
        ldr     r3, EXTRA_CONF          ; set CS7 at address zero
        strh    r3, [r1]
        bx      lr                      ; Return to caller

;/*
; * FUNCTION
; *
; *      Clear_Internal_SRAM
; */
Clear_Internal_SRAM:
        mov     r0, #SRAM_ADDR          ; r0 points to SRAM start
        mov     r1, #SRAM_SIZE
        add     r1, r0, r1              ; r1 points to SRAM end
        mov     r2, #0

ClearSram:
        str     r2,[r0], #4
        cmp     r0, r1                  ; done?
        bne     ClearSram               ; no - loop
        bx      lr                      ; Return to caller

  .endif ; BOARD=34 | BOARD=35

;
;/*************************************************************************/
;/*                                                                       */
;/* FUNCTION                                                              */
;/*                                                                       */
;/*      INT_Vectors_Loaded                                               */
;/*                                                                       */
;/* DESCRIPTION                                                           */
;/*                                                                       */
;/*      This function returns the flag that indicates whether or not     */
;/*      all the default vectors have been loaded.  If it is false,       */
;/*      each LISR register also loads the ISR shell into the actual      */
;/*      vector table.                                                    */
;/*                                                                       */
;/* AUTHOR                                                                */
;/*                                                                       */
;/*      Barry Sellew, Accelerated Technology, Inc.                       */
;/*                                                                       */
;/* CALLED BY                                                             */
;/*                                                                       */
;/*      TCC_Register_LISR                   Register LISR for vector     */
;/*                                                                       */
;/* CALLS                                                                 */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* INPUTS                                                                */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* OUTPUTS                                                               */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* HISTORY                                                               */
;/*                                                                       */
;/*         NAME            DATE                    REMARKS               */
;/*                                                                       */
;/*      B. Sellew       01-19-1996      Created initial version 1.0      */
;/*	 B. Sellew	 01-22-1996	 Verified version 1.0	  	  */
;/*                                                                       */
;/*************************************************************************/
;INT    INT_Vectors_Loaded(void)
;{
	.def	$INT_Vectors_Loaded
$INT_Vectors_Loaded			    ; Dual-state interworking veneer
	.state16
	BX	pc
	NOP
	.state32
	B	_INT_Vectors_Loaded
;
        .def    _INT_Vectors_Loaded
_INT_Vectors_Loaded
;
;    /* Just return the loaded vectors flag.  */
;    return(INT_Loaded_Flag);
;
        MOV     a1,#1                       ; Always return TRUE since there 
                                            ;   are really only two normal 
                                            ;   vectors IRQ & FIQ
        BX      lr                          ; Return to caller
;}
;
;
;/*************************************************************************/
;/*                                                                       */
;/* FUNCTION                                                              */
;/*                                                                       */
;/*      INT_Setup_Vector                                                 */
;/*                                                                       */
;/* DESCRIPTION                                                           */
;/*                                                                       */
;/*      This function sets up the specified vector with the new vector   */
;/*      value.  The previous vector value is returned to the caller.     */
;/*                                                                       */
;/* AUTHOR                                                                */
;/*                                                                       */
;/*      Barry Sellew, Accelerated Technology, Inc.                       */
;/*                                                                       */
;/* CALLED BY                                                             */
;/*                                                                       */
;/*      Application                                                      */
;/*      TCC_Register_LISR                   Register LISR for vector     */
;/*                                                                       */
;/* CALLS                                                                 */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* INPUTS                                                                */
;/*                                                                       */
;/*      vector                              Vector number to setup       */
;/*      new                                 Pointer to new assembly      */
;/*                                            language ISR               */
;/*                                                                       */
;/* OUTPUTS                                                               */
;/*                                                                       */
;/*      old vector contents                                              */
;/*                                                                       */
;/* HISTORY                                                               */
;/*                                                                       */
;/*         NAME            DATE                    REMARKS               */
;/*                                                                       */
;/*      B. Sellew       01-19-1996      Created initial version 1.0      */
;/*	 B. Sellew	 01-22-1996	 Verified version 1.0	  	  */
;/*                                                                       */
;/*************************************************************************/
;VOID  *INT_Setup_Vector(INT vector, VOID *new)
;{
	.def	$INT_Setup_Vector
$INT_Setup_Vector			    ; Dual-state interworking veneer
	.state16
	BX	pc
	NOP
	.state32
	B	_INT_Setup_Vector
;
        .def    _INT_Setup_Vector
_INT_Setup_Vector
;
;VOID    *old_vector;                        /* Old interrupt vector      */
;VOID   **vector_table;                      /* Pointer to vector table   */
;
;    /* Calculate the starting address of the actual vector table.  */
;    vector_table =  (VOID **) 0;
;
;    /* Pickup the old interrupt vector.  */
;    old_vector =  vector_table[vector];
;    
;    /* Setup the new interrupt vector.  */
;    vector_table[vector] =  new;
;    
;    /* Return the old interrupt vector.  */
;    return(old_vector);
;
        MOV     a1,#0                       ; This routine is not applicable to
                                            ;   THUMB, return a NULL pointer
        BX      lr                          ; Return to caller
;}
;
;
;
;
;/*************************************************************************/
;/*                                                                       */
;/* FUNCTIONS                                                             */
;/*                                                                       */
;/*      INT_EnableIRQ, INT_DisableIRQ                                    */
;/*                                                                       */
;/* DESCRIPTION                                                           */
;/*                                                                       */
;/*      This function enable/disable IRQ/FIQ in current mode             */
;/*                                                                       */
;/*************************************************************************/
;
        .global $INT_EnableIRQ
$INT_EnableIRQ:
	.state16
        BX      pc
	nop

	.state32
        MRS     a1, CPSR                ; read current PSR
        BIC     a1,a1,#MODE_MASK        ; remove all mode bits
        ORR     a1,a1,#IRQ_MODE         ; retrieve desired mode
        MSR     CPSR,a1                 ; IRQ mode

        MRS     a1, CPSR                ; read current PSR
        BIC     a1,a1,#LOCKOUT          ; interrupt lockout value
        MSR     CPSR,a1                 ; Lockout interrupts

        BIC     a1,a1,#MODE_MASK        ; remove all mode bits
        ORR     a1,a1,#SUP_MODE         
        MSR     CPSR,a1                 ; Lockout interrupts

	add	a1, pc, #1		; back to Thumb mode 
	bx	a1

	.state16
        BX      lr                      ; Return to caller

;
;
        .global $INT_DisableIRQ
$INT_DisableIRQ:
	.state16
        BX      pc
	nop

	.state32
        MRS     a1, CPSR                ; read current PSR
        BIC     a1,a1,#MODE_MASK        ; remove all mode bits
        ORR     a1,a1,#IRQ_MODE         ; retrieve desired mode
        MSR     CPSR,a1                 ; IRQ mode

        MRS     a1, CPSR                ; read current PSR
        ORR     a1,a1,#LOCKOUT          ; Build interrupt lockout value
        MSR     CPSR,a1                 ; Lockout interrupts

        BIC     a1,a1,#MODE_MASK        ; remove all mode bits
        ORR     a1,a1,#SUP_MODE         
        MSR     CPSR,a1                 ; Lockout interrupts

	add	a1, pc, #1		; back to Thumb mode 
	bx	a1

	.state16
         BX      lr                      ; Return to caller
;
;
;/*************************************************************************/
;/*                                                                       */
;/* FUNCTION                                                              */
;/*                                                                       */
;/*      INT_Retrieve_Shell                                               */
;/*                                                                       */
;/* DESCRIPTION                                                           */
;/*                                                                       */
;/*      This function retrieves the pointer to the shell interrupt       */
;/*      service routine.  The shell interrupt service routine calls      */
;/*      the LISR dispatch routine.                                       */
;/*                                                                       */
;/* AUTHOR                                                                */
;/*                                                                       */
;/*      Barry Sellew, Accelerated Technology, Inc.                       */
;/*                                                                       */
;/* CALLED BY                                                             */
;/*                                                                       */
;/*      TCC_Register_LISR                   Register LISR for vector     */
;/*                                                                       */
;/* CALLS                                                                 */
;/*                                                                       */
;/*      None                                                             */
;/*                                                                       */
;/* INPUTS                                                                */
;/*                                                                       */
;/*      vector                              Vector number to setup       */
;/*                                                                       */
;/* OUTPUTS                                                               */
;/*                                                                       */
;/*      shell pointer                                                    */
;/*                                                                       */
;/* HISTORY                                                               */
;/*                                                                       */
;/*         NAME            DATE                    REMARKS               */
;/*                                                                       */
;/*      B. Sellew       01-19-1996      Created initial version 1.0      */
;/*	 B. Sellew	 01-22-1996	 Verified version 1.0	  	  */
;/*                                                                       */
;/*************************************************************************/
;VOID  *INT_Retrieve_Shell(INT vector)
;{
	.def	$INT_Retrieve_Shell
$INT_Retrieve_Shell			    ; Dual-state interworking veneer
	.state16
	BX	pc
	NOP
	.state32
	B	_INT_Retrieve_Shell
;
        .def    _INT_Retrieve_Shell
_INT_Retrieve_Shell
;
;    /* Return the LISR Shell interrupt routine.  */
;    return(INT_Vectors[vector]);
;
        MOV     a1,#0                       ; This routine is not applicable to
                                            ;   THUMB, return a NULL pointer
        BX      lr                          ; Return to caller
;}
;
;
;
;/* The following section contains default interrupt handlers.  */
;
     .if TI_NUC_MONITOR = 1
; define a new section to be mapped independently
        .sect ".irqtext"
             
        .def    _INT_IRQ
		.global _INT_IRQ
_INT_IRQ
     .else
        .def    INT_IRQ
INT_IRQ
	 .endif

;
;    /* Call Prepare for IRQ interrupt processing by calling 
;       TCT_Interrupt_Context_Save.  */
        STMDB   sp!,{a1-a4}                 ; Save a1-a4 on temporary IRQ stack

;BUG correction 1st part -------------------
;It looks like there is an issue with ARM7 IRQ masking in the CPSR register
;which leads to crashes in Nucleus+ scheduler.
;Basically the code below  (correct as LOCKOUT = 0xC0) is used in many places by N+ but do not 
;prevent from having an interrupt after the execution of the third line (I mean execution, not 
;fetch).
;        MRS     a1,CPSR                     ; Pickup current CPSR
;        ORR     a1,a1,#LOCKOUT              ; Build interrupt lockout value
;        MSR     CPSR,a1                     ; Lockout interrupts
;       * IRQ INTERRUPT ! *
;       Next instructions...
;
;SW workaround:
;When a task is interrupted at this point an interrupted context is stored on its task and will 
;be resumed later on at the next instruction but to make a long story short it leads to some 
;problem as the OS does not expect to be interrupted there.
;Further testing tends to show that the CPSR *seems* to be loaded with the proper masking value 
;but that the IRQ is still triggered (has been hardwarewise requested during the instruction 
;exectution by the ARM7 core?)
        MRS     a1,spsr                     ; check for the IRQ bug:
        TST     a1,#080h                    ; if the I - flag is set,
        BNE     IRQBUG                      ; then postpone execution of this IRQ
;Bug correction 1st part end ---------------
    
        SUB     a4,lr,#4                    ; Save IRQ's lr (return address)
        BL      _TCT_Interrupt_Context_Save ; Call context save routine

  .if TI_NUC_MONITOR = 1
; Log the IRQ call entry
  		.global _ti_nuc_monitor_LISR_log
		BL		_ti_nuc_monitor_LISR_log		; Call the LISR Log function.
  .endif

;
;    /* On actuall hardware, a register must be examined to see what the 
;       IRQ interrupt was caused from.   For default processing, the 
;       timer is the only IRQ interrupt source.  It is assumed that further
;       timer interrupts are disabled upon this call.  */
;
        BL      _IQ_IRQ_isr 			; Call  int. service routine

  .if TI_NUC_MONITOR = 1
; Log the IRQ exit
  		.global _ti_nuc_monitor_LISR_log_end
		BL		_ti_nuc_monitor_LISR_log_end		; Call the LISR end function.
  .endif

;
;    /* IRQ interrupt processing is complete.  Restore context- Never 
;       returns!  */
        B       _TCT_Interrupt_Context_Restore

;BUG correction 2nd part  ------------------
IRQBUG: LDMFD  sp!,{a1-a4}                  ; return from interrupt
        SUBS   pc,r14,#4
;BUG correction 2nd part end  --------------

;
  .if TI_NUC_MONITOR = 1
      .sect ".inttext"
  .endif
;
     .if TI_PROFILER = 1
; define a new section to be mapped independently
        .sect ".fiqtext"
             
        .def    _INT_FIQ
		.global _INT_FIQ
_INT_FIQ
     .else
        .def    INT_FIQ
INT_FIQ
	 .endif

   .if TI_PROFILER = 1
; Warning : 
; This code has been added for profiliing purpose.
; It removes all other FIQ. 
        .global    _ti_profiler_handler
; Timing profiler using FIQ - Handle FIQ directly here
        STMFD    sp!,{R0-R4, LR}            ; Save R0-R4 and LR on FIQ stack

        MOV     R0, LR                      ; Retrieve link register in R0
        BL      _ti_profiler_handler        ; Store into buffer
        BL      _IQ_FIQ_isr                 ; Call the FIQ ISR
        LDMFD   sp!,{R0-R4, LR}            ; Restore R0-R4 and LR from FIQ stack
        SUBS    PC, LR, #4                 ; return from FIQ
    .else

;
;    /* Call Prepare for FIQ interrupt processing by calling 
;       TCT_Interrupt_Context_Save.  */
        STMDB   sp!,{a1-a4}                 ; Save a1-a4 on temporary FIQ stack
        SUB     a4,lr,#4                    ; Save FIQ's lr (return address)
        BL      _TCT_Interrupt_Context_Save ; Call context save routine
;
;    /* On actuall hardware, a register must be examined to see what the 
;       FIQ interrupt was caused from.   For default processing, the 
;       test is the only FIQ interrupt source.  */
;
;    /* Replace this with a call to your own ISR */
        BL      _IQ_FIQ_isr              ; Call the FIQ ISR

;
;    /* FIQ interrupt processing is complete.  Restore context- Never 
;       returns!  */
        B       _TCT_Interrupt_Context_Restore

  .endif

  .if TI_PROFILER = 1
      .sect ".inttext"
  .endif

;***************************************************************
;* CONSTANT TABLE                                              *
;***************************************************************

;
;    /* Define all the global addresses used in this section */
;

; internal/external RAM
    .if CHIPSET = 3	| CHIPSET = 5 | CHIPSET = 6
RAM_SIZE       .equ    0x40000          ; size (in bytes) of internal RAM 
RAM_LOW        .equ    0x3000000        ; first address of internal RAM
    .elseif CHIPSET = 4
RAM_SIZE       .equ    0x40000          ; size (in bytes) of internal RAM 
RAM_LOW        .equ    0x800000         ; first address of internal RAM
    .elseif CHIPSET = 7	| CHIPSET = 8 | CHIPSET = 10 | CHIPSET = 11 | CHIPSET = 12
	.if L1_GPRS = 1
RAM_SIZE       .equ    0x200000         ; size (in bytes) of external RAM 
RAM_LOW        .equ    0x1000000        ; first address of external RAM
		.else	; GSM ONLY
RAM_SIZE       .equ    0x80000          ; size (in bytes) of internal RAM 
RAM_LOW        .equ    0x800000         ; first address of internal RAM
		.endif
	.endif

RAM_HIGH       .equ    RAM_LOW + RAM_SIZE ; first address after internal/external RAM
               

	.global exception_stack        ; top address of SVC mode stack

	.global _xdump_buffer          ; first address of state data

	.global stack_segment		   ; address of the top of the system stack

;
; /* Define exception functions */
;
    .ref    _dar_exception

XDUMP_STACK_SIZE .equ   20

; layout of xdump buffer:
; struct xdump_s {
;     long registers[16] // svc mode registers
;     long cpsr          // svc mode CPSR
;     long exception     // magic word + index of vector taken
;     long stack[20]     // bottom 20 words of usr mode stack
; }

arm_undefined:
        stmfd   r13!,{r11,r12}		; store r12 for Xdump_buffer pointer, r11 for index
		mov     r11,#1
		b       save_regs
		
arm_swi:
        stmfd   r13!,{r11,r12}		; store r12 for Xdump_buffer pointer, r11 for index
		mov     r11,#2
		b       save_regs
        
arm_abort_prefetch:
        stmfd   r13!,{r11,r12}		; store r12 for Xdump_buffer pointer, r11 for index
		mov     r11,#3
		b       save_regs
		
        
arm_abort_data:
        stmfd   r13!,{r11,r12}		; store r12 for Xdump_buffer pointer, r11 for index
		mov     r11,#4
		b       save_regs

arm_reserved:
        ldr     r13,Exception_Stack     ; should never happen, but mode is unknown at this point
        stmfd   r13!,{r11,r12}		; store r12 for Xdump_buffer pointer, r11 for index
		mov     r11,#5
		b       save_regs
        
save_regs:
        ldr     r12,Xdump_buffer
        str     r14,[r12,#4*15] ; save r14_abt (original PC) into r15 slot

        stmia   r12,{r0-r10}    ; save unbanked registers (except r11 and r12)
        ldmfd   r13!,{r0,r1}    ; get original r11 and r12
        str     r0,[r12,#4*11]  ; save original r11
        str     r1,[r12,#4*12]  ; save original r12
        mrs     r0,spsr         ; get original psr
        str     r0,[r12,#4*16]  ; save original cpsr

        mrs     r1,cpsr         ; save mode psr
        bic     r2,r1,#0x1f     ; psr with mode bits cleared
        and     r0,r0,#0x1f     ; get original mode bits
        add     r0,r0,r2

        msr     cpsr,r0		  ; move to pre-exception mode
        str     r13,[r12,#4*13] ; save original SP
        str     r14,[r12,#4*14] ; save original LR
        msr     cpsr,r1 	  ; restore mode psr

        ; r11 has original index
        orr     r10,r11,#0xDE<<24; r10 = 0xDEAD0000 + index of vector taken
        orr     r10,r10,#0xAD<<16
        str     r10,[r12,#4*17] ; save magic + index

        mov     r0,r11          ; put index into 1st argument
        b       _dar_exception
        
	.global $exception		       ; export function

$exception: ; Veneer function
        .ref    _exception
		.state16
		adr     r0,_exception
		bx      r0
		.align
		.state32
		.def    _exception
_exception:
        ldr     r12,Xdump_buffer ; redundant unless _exception is called
        ldr     r11,[r12,#4*13]  ; get svc mode r13
        add     r12,r12,#4*18    ; base of stack buffer

        ; check if svc r13(sp) is within internal/external RAM. It *could* be invalid.
        ; we boldly assume stack is only within internal RAM except for GPRS build on 
		; Calypso chipset : stack is within external RAM
    .if CHIPSET = 7	| CHIPSET = 8 | CHIPSET = 10 | CHIPSET = 11
         .if L1_GPRS = 1
              ; if GPRS, check for internal RAM as well as 2Mbytes of external RAM
              cmp     r11,#0x800000			 ; INTERNAL RAM_LOW
              blt     nostack
              mov     r0, #0x880000			 ; INTERNAL RAM_HIGH
              sub     r0,r0,#XDUMP_STACK_SIZE
              cmp     r11,r0
              blt     stack_range
              ; was not less than 0x880000, so check for external RAM
              cmp     r11,#RAM_LOW
              blt     nostack
              mov     r0,#RAM_HIGH
              sub     r0,r0,#XDUMP_STACK_SIZE
              cmp     r11,r0
              bge     nostack
		.else	; GSM ONLY
              cmp     r11,#RAM_LOW
              blt     nostack
              mov     r0,#RAM_HIGH
              sub     r0,r0,#XDUMP_STACK_SIZE
              cmp     r11,r0
              bge     nostack
		.endif
	.endif
              
stack_range:              
        ldmfd   r11!,{r0-r9}    ; copy ten stack words..
        stmia   r12!,{r0-r9}
        ldmfd   r11!,{r0-r9}    ; copy ten stack words..
        stmia   r12!,{r0-r9}

nostack:
STACKS       .equ    SYSTEM_SIZE + IRQ_STACK_SIZE +	FIQ_STACK_SIZE + TIMER_SIZE
	.ref _dar_reset
        ; we're finished saving all state. Now execute C code for more flexibility.
        ; set up a stack for this C call
        LDR     a1,StackSegment             ; Pickup the begining address from .cmd file
                                            ;    (is aligned on 8 byte boundary)
        MOV     a2,#STACKS					; Pickup all stacks size
        ADD     a2,a2,#0x80                 ; Add 128 to get past all used data
        ADD     a3,a1,a2                    
        MOV     sp,a3                       ; Setup exception stack pointer
        b _dar_reset


BSS_Start
	.word	.bss
;
BSS_End
	.word	end
;
  .if LONG_JUMP >= 3
  .align 4
BSS_IntMem_Start: .field  _S_D_Mem,32
  .align 4
BSS_IntMem_End:   .field  _E_D_Mem,32
  .endif

StackSegment
	.word	stack_segment
;
Loaded_Flag
	.word	_INT_Loaded_Flag
;
System_Limit
	.word	_TCT_System_Limit
;
System_Stack
	.word	_TCD_System_Stack
;
HISR_Stack_Ptr
	.word	_TMD_HISR_Stack_Ptr
;
HISR_Stack_Size	
	.word	_TMD_HISR_Stack_Size
;
HISR_Priority
	.word	_TMD_HISR_Priority
;
Exception_Stack
    .word   exception_stack
;
Xdump_buffer
    .word   _xdump_buffer
;
;   The following code is pulled from rts.src, which is part of the
;   TI tools installation.
;
;***************************************************************************
;*  PROCESS INITIALIZATION TABLE.
;*
;*  THE TABLE CONSISTS OF A SEQUENCE OF RECORDS OF THE FOLLOWING FORMAT:
;*                                                                          
;*       .word  <length of data (bytes)>
;*       .word  <address of variable to initialize>                         
;*       .word  <data>
;*                                                                          
;*  THE INITIALIZATION TABLE IS TERMINATED WITH A ZERO LENGTH RECORD.
;*                                                                          
;***************************************************************************
;****auto_init(register int *table)
;****{
;****   register int length;
;****   register int *addr;
;****
;****   while (length = *table++)
;****   {
;****      addr = (int *)*table++;
;****      while (length)
;****      {
;****         if (length > 3)
;****	      {
;****	         *addr++ = *table++;
;****	         length -= 4;
;****	      }
;****	      else
;****	      {
;****	         *(char *)addr++ = *(char *)table++;
;****	         length--;
;****	      }
;****      }
;****   }
;****}

tbl_addr: .set    R0
var_addr: .set    R1
length:   .set    R3
data:     .set    R4

_auto_init:
	B	rec_chk

record:
        ;*------------------------------------------------------
	;* PROCESS AN INITIALIZATION RECORD
        ;*------------------------------------------------------
	LDR	var_addr, [tbl_addr], #4

copy:
        ;*------------------------------------------------------
	;* COPY THE INITIALIZATION DATA
        ;*------------------------------------------------------
	CMP	length, #3

	LDRHI	data, [tbl_addr], #4  
	STRHI	data, [var_addr], #4	   ; COPY A WORD OF DATA
	SUBHI	length, length, #4	   ; OR ...
	LDRLSB	data, [tbl_addr], #1       ;
	STRLSB	data, [var_addr], #1       ; COPY A BYTE OF DATA
	SUBLS	length, length, #1

	CMP     length, #0		   ; CONTINUE TO COPY IF
	BNE	copy                       ; LENGTH IS NONZERO

	ANDS	length, tbl_addr, #0x3     ; MAKE SURE THE ADDRESS
	RSBNE	length, length, #0x4       ; IS WORD ALIGNED
	ADDNE	tbl_addr, tbl_addr, length ;

rec_chk:LDR	length, [tbl_addr], #4     ; PROCESS NEXT
	CMP	length, #0                 ; RECORD IF LENGTH IS
	BNE	record                     ; NONZERO

	MOV	PC, LR
;

;
; Creation of INT_memset and INT_memcpy, respectively identical to memset and 
; memcpy from the rts library of compiler 2.51/2.54.
; They are used to make the initialization of the .bss section and the load 
; of the internal ram code not dependent to the 32-bit alignment.
; The old code used for the initialization and the load used a loop with
; 4-byte increment, assuming the 32-bit alignment of the .bss section.
; This alignment is not necessary true.
;  
;******************************************************************************
;* INT_memset - INITIALIZE MEMORY WITH VALUE                                  *
;******************************************************************************
;* MEMSET32.ASM  - 32 BIT STATE -  v2.51                                      *
;* Copyright (c) 1996-2003 Texas Instruments Incorporated                     *
;******************************************************************************

;****************************************************************************
;* INT_memset - INITIALIZE MEMORY WITH VALUE.
;*
;*  Same memset defined in rts.src.
;*  Used in INT_Initialize to clear bss area.
;*  Used in f_load_int_mem() function to clear internal memory space used
;*  for data and code.
;*  The memset function defined in rts library is loaded into internal memory,
;*  then, it can not be used in either INT_Initialize, or f_load_int_mem().
;*
;*  C Prototype   : void *INT_memset(void *s, int c, size_t n);
;*  C++ Prototype : void *std::INT_memset(void *s, int c, std::size_t n);
;*
;****************************************************************************
;*
;*   o DESTINATION LOCATION IS IN r0
;*   o INITIALIZATION VALUE IS IN r1
;*   o NUMBER OF BYTES TO INITIALIZE IS IN r2
;*
;*   o ORIGINAL DESTINATION LOCATION RETURNED IN r0
;****************************************************************************
	.state32
  .def _INT_memset

_INT_memset:
	STMFD	SP!, {R0, LR}		      ; save R0 also since original dst
					                    ; address is returned.

	TST	R0, #3			            ; check for word alignment
	BEQ	_word_aligned

	CMP	R2, #0			            ; set bytes until there are no more
					                    ; to set or until address is aligned
_unaligned_loop:
	STRHIB	R1, [R0], #1
	SUBHIS	R2, R2, #1
	TSTHI	R0, #3
	BNE	_unaligned_loop
          
	CMP	R2, #0			            ; return early if no more bytes
	LDMEQFD	SP!, {R0, PC}		    ; to set.

_word_aligned:
	AND	R1, R1, #255		        ; be safe since prototype has value as
					                    ; as an int rather than unsigned char

	ORR	R1, R1, R1, LSL	#8      ; replicate byte in 2nd byte of
					                    ; register

	CMP	R2,#4			              ; are at least 4 bytes being set
	BCC	_INT_memset3

	ORR	R1, R1, R1, LSL	#16	    ; replicate byte in upper 2 bytes
					                    ; of register. note that each of
					                    ; the bottom 2 bytes already contain 
					                    ; the byte value from above.

	CMP	R2,#8	              		; are at least 8 bytes being set
	BCC	_INT_memset7
        
	MOV	LR,R1		              	; copy bits into another register so
					                    ; 8 bytes at a time can be copied.
				                    	; use LR since it is already being
				                    	; saved/restored.

	CMP	R2,#16		            	; are at least 16 bytes being set
	BCC	_INT_memset15

	STMFD	SP!, {R4}		          ; save regs needed by 16 byte copies

	MOV	R4, R1		            	; copy bits into 2 other registers so
	MOV	R12, R1		            	; 16 bytes at a time can be copied

	SUB	R3, R2, #15	          	; set up loop count
	AND	R2, R2, #15		          ; determine number of bytes to set
					                    ; after setting 16 byte blocks

_INT_memset16_loop:			    	; set blocks of 16 bytes
	STMIA	R0!, {R1, R4, R12, LR}
	SUBS	R3, R3, #16
	BHI	_INT_memset16_loop

	LDMFD	SP!, {R4}	          	; resotre regs used by 16 byte copies

_INT_memset15:			         	; may still be as many as 15 bytes to 
					                    ; set. the address in R0 is guaranteed
					                    ; to be word aligned here.

	TST	R2, #8		            	; are at least 8 bytes being set
	STMNEIA	R0!, {R1, LR}


_INT_memset7:		          		; may still be as many as 7 bytes to 
					                    ; set. the address in R0 is guaranteed
					                    ; to be word aligned here.

	TST	R2, #4			            ; are at least 4 bytes being set
	STRNE	R1, [R0], #4

_INT_memset3:	          			; may still be as many as 3 bytes to 
				                    	; set. the address in R0 is guaranteed
				                    	; to be word aligned here.

	TST	R2, #2		            	; are there at least 2 more bytes to 
	STRNEH	R1, [R0], #2	     	; set.  the address in R0 is guaranteed
				                    	; to be half-word aligned here.
	
	TST	R2, #1		            	; is there one remaining byte to set
	STRNEB	R1, [R0]


	LDMFD     SP!, {R0, PC}		  ; restore regs and return


;******************************************************************************
;* INT_memcpy - COPY CHARACTERS FROM SOURCE TO DEST                           *
;******************************************************************************
;* MEMCPY32.ASM  - 32 BIT STATE -  v2.51                                      *
;* Copyright (c) 1996-2003 Texas Instruments Incorporated                     *
;******************************************************************************
 
;****************************************************************************
;* INT_memcpy - COPY CHARACTERS FROM SOURCE TO DEST
;*
;*  Same as C_MEMCPY defined in rts.src.
;*  Used in INT_Initialize to download code into internal memory space.
;*  The memcpy function defined in rts library is loaded into internal memory.
;*  then, it can not be used in f_load_int_mem().
;*
;****************************************************************************
;*
;*   o DESTINATION LOCATION IS IN r0
;*   o SOURCE LOCATION IS IN r1
;*   o NUMBER OF CHARACTERS TO BE COPIED IS IN r2
;****************************************************************************
 	.state32
  .def _INT_memcpy

_INT_memcpy: 
	CMP	r2, #0			                    ; CHECK FOR n == 0
	BXEQ	lr			;

	STMFD	sp!, {r0, lr}		              ; SAVE RETURN VALUE AND ADDRESS

	TST	r1, #0x3		                    ; CHECK ADDRESS ALIGNMENT
	BNE	_unaln			                    ; IF NOT WORD ALIGNED, HANDLE SPECIALLY
	TST	r0, #0x3		                    ;
	BNE	_saln			;

_aln:	CMP	r2, #16			                ; CHECK FOR n >= 16
	BCC	_l16			;

	STMFD	sp!, {r4}		;
	SUB	r2, r2, #16		;
_c16:	LDMIA	r1!, {r3, r4, r12, lr}	  ; COPY 16 BYTES
	STMIA	r0!, {r3, r4, r12, lr}	;
	SUBS	r2, r2, #16		;
	BCS	_c16			;
	LDMFD	sp!, {r4}		;
	ADDS	r2, r2, #16		                ; RETURN IF DONE
	LDMEQFD	sp!, {r0, pc}		;
	
_l16:	ANDS	r3, r2, #0xC		;
	BEQ	_cp1			;
	BICS	r2, r2, #0xC		;
	ADR	r12, _4line - 16	;
	ADD	pc, r12, r3, LSL #2	;

_4line:	LDR	r3, [r1], #4		          ; COPY 4 BYTES
	STR	r3, [r0], #4		;
	LDMEQFD	sp!, {r0, pc} 	          	; CHECK FOR n == 0
	B	_cp1			;

	LDMIA	r1!, {r3, r12}		            ; COPY 8 BYTES
	STMIA	r0!, {r3, r12}		;
	LDMEQFD	sp!, {r0, pc} 		          ; CHECK FOR n == 0
	B	_cp1			;

	LDMIA	r1!, {r3, r12, lr}	          ; COPY 12 BYTES
	STMIA	r0!, {r3, r12, lr}	;
	LDMEQFD	sp!, {r0, pc} 		          ; CHECK FOR n == 0

_cp1:	SUBS	r2, r2, #1		;
	ADRNE	r3, _1line - 4		            ; SETUP TO COPY 1 - 3 BYTES...
	ADDNE	pc, r3, r2, LSL #4	;

_1line:	LDRB	r3, [r1], #1		        ; COPY 1 BYTE
	STRB	r3, [r0], #1		;
	LDMFD	sp!, {r0, pc}		;

	LDRH	r3, [r1], #2		              ; COPY 2 BYTES
	STRH	r3, [r0], #2		;
	LDMFD	sp!, {r0, pc}		;
	NOP				;

	LDRH	r3, [r1], #2		              ; COPY 3 BYTES
	STRH	r3, [r0], #2		;
	LDRB	r3, [r1], #1		;
	STRB	r3, [r0], #1		;
	LDMFD	sp!, {r0, pc}		;

_unaln:	LDRB	r3, [r1], #1		        ; THE ADDRESSES ARE NOT WORD ALIGNED.
	STRB	r3, [r0], #1		              ; COPY BYTES UNTIL THE SOURCE IS
	SUBS	r2, r2, #1		                ; WORD ALIGNED OR THE COPY SIZE
	LDMEQFD	sp!, {r0, pc}		            ; BECOMES ZERO
	TST	r1, #0x3		;
	BNE	_unaln			;

_saln:	TST	r0, #0x1		              ; IF THE ADDRESSES ARE OFF BY 1 BYTE
	BNE	_off1			                      ; JUST BYTE COPY

	TST	r0, #0x2	                    	; IF THE ADDRESSES ARE NOW WORD ALIGNED
	BEQ	_aln			                      ; GO COPY.  ELSE THEY ARE OFF BY 2, SO
					                            ; GO SHORT WORD COPY

_off2:	SUBS	r2, r2, #4		          ; COPY 2 BYTES AT A TIME...
	BCC	_c1h			;
_c2:	LDR	r3, [r1], #4		            ; START BY COPYING CHUNKS OF 4,
	.if	.TMS470_BIG
	STRH	r3, [r0, #2]		;
	MOV	r3, r3, LSR #16		;
	STRH	r3, [r0], #4		;
	.else
	STRH	r3, [r0], #4		;
	MOV	r3, r3, LSR #16		;
	STRH	r3, [r0, #-2]		;
	.endif
	SUBS	r2, r2, #4		;
	BCS	_c2			;
	CMN	r2, #4			;
	LDMEQFD	sp!, {r0, pc}		;

_c1h:	ADDS	r2, r2, #2		            ; THEN COPY THE ODD BYTES.
	LDRCSH	r3, [r1], #2		;
	STRCSH	r3, [r0], #2		;
	SUBCS	r2, r2, #2		;
	ADDS	r2, r2, #1		;
	LDRCSB	r3, [r1], #1		;
	STRCSB	r3, [r0], #1		;
	LDMFD	sp!, {r0, pc}		;

_off1:	SUBS	r2, r2, #4		          ; COPY 1 BYTE AT A TIME...
	BCC	_c1b			;
_c1:	LDR	r3, [r1], #4		            ; START BY COPYING CHUNKS OF 4,
	.if	.TMS470_BIG
	STRB	r3, [r0, #3]		              ;
	MOV	r3, r3, LSR #8		              ;
	STRB	r3, [r0, #2]		              ;
	MOV	r3, r3, LSR #8		              ;
	STRB	r3, [r0, #1]		              ;
	MOV	r3, r3, LSR #8		              ;
	STRB	r3, [r0], #4		              ;
	.else
	STRB	r3, [r0], #4		              ;
	MOV	r3, r3, LSR #8		              ;
	STRB	r3, [r0, #-3]		              ;
	MOV	r3, r3, LSR #8		              ;
	STRB	r3, [r0, #-2]		              ;
	MOV	r3, r3, LSR #8		              ;
	STRB	r3, [r0, #-1]		              ;
	.endif
	SUBS	r2, r2, #4		;
	BCS	_c1			;

_c1b:	ADDS	r2, r2, #4	            	; THEN COPY THE ODD BYTES.
	LDMEQFD	sp!, {r0, pc}		;
_lp1:	LDRB	r3, [r1], #1		;
	STRB	r3, [r0], #1		;
	SUBS	r2, r2, #1		;
	BNE	_lp1			; 
	LDMFD	sp!, {r0, pc}		;

        .end

