;***********************************************************************
;*
;*             Copyright 2006 Mentor Graphics Corporation
;*                         All Rights Reserved.
;*
;* THIS WORK CONTAINS TRADE SECRET AND PROPRIETARY INFORMATION WHICH IS
;* THE PROPERTY OF MENTOR GRAPHICS CORPORATION OR ITS LICENSORS AND IS
;* SUBJECT TO LICENSE TERMS.
;*
;***********************************************************************

;***********************************************************************
;*
;*  FILE NAME
;*
;*      rvct_arm_defs.inc
;*
;*  DESCRIPTION
;*
;*      This file contains the architecture specific definitions,
;*      constants, etc, for RVCT
;*
;*  DATA STRUCTURES
;*
;*      None
;*
;*  DEPENDENCIES
;*
;*      None
;*
;***********************************************************************


; Define to allow conditional compilation for ARM7TDMI processor. Setting this
; will include necessary low-level interrupt handling code specific to
; the ARM7TDMI and its pipeline architecture.

    GBLL ESAL_AR_ISR_CPU7TDMI
ESAL_AR_ISR_CPU7TDMI                SETL       {CPU} = "ARM7TDMI"

; Define to allow conditional assembling of lowlevel ISR hook.
; Setting this to TRUE will allow a low-level hook to be executed in the
; interrupt handlers

    GBLL ESAL_AR_ISR_HOOK_ENABLED
ESAL_AR_ISR_HOOK_ENABLED            SETL       {FALSE}

; Define to allow conditional assembling of reset vector type (branch versus load).
; Setting this to TRUE will force the reset vector to utilize a branch instruction.
; This is necessary for certain processors that re-map memory and require a PC
; relative jump to the entry point versus a full 32-bit address (before remapping memory).

    GBLL ESAL_AR_ISR_RESET_BRANCH
ESAL_AR_ISR_RESET_BRANCH            SETL       {FALSE}

; Startup / initialization stack size in bytes

ESAL_AR_STK_STARTUP_STACK_SIZE     EQU          1024

#if (CFG_NU_OS_ARCH_ARM_COM_FPU_SUPPORT > 0)

#if (CFG_NU_OS_ARCH_ARM_COM_FPU_SUPPORT == 2)

; Size, in bytes, of max architecture stack frames (with floating point)

ESAL_AR_STK_MAX_FRAME_SIZE         EQU          328

#else

; Size, in bytes, of max architecture stack frames (with floating point)

ESAL_AR_STK_MAX_FRAME_SIZE         EQU          200

#endif /* CFG_NU_OS_ARCH_ARM_COM_FPU_SUPPORT == 2 */

#else

; Size, in bytes, of max architecture stack frames (without floating point)

ESAL_AR_STK_MAX_FRAME_SIZE         EQU          68

#endif  /* CFG_NU_OS_ARCH_ARM_COM_FPU_SUPPORT > 0 */

; Offset, in bytes, of LR in full stack frame

ESAL_AR_STK_PC_OFFSET              EQU          (ESAL_AR_STK_MAX_FRAME_SIZE-4)
ESAL_AR_STK_LR_OFFSET              EQU          (ESAL_AR_STK_MAX_FRAME_SIZE-8)
ESAL_AR_STK_SPSR_OFFSET            EQU          (ESAL_AR_STK_MAX_FRAME_SIZE-12)
ESAL_AR_STK_R12_OFFSET             EQU          (ESAL_AR_STK_MAX_FRAME_SIZE-16)

; Size, in bytes, of min architecture stack frames

ESAL_AR_STK_MIN_FRAME_SIZE         EQU          32

; Based on ESAL_TS_REQ_STK_ALIGNMENT in esal_ts_cfg.h

ESAL_AR_STK_ALIGNMENT_MASK         EQU          0x00000007

; Offsets, in bytes, of registers on temp stack

ESAL_AR_STK_TMP_R0_OFFSET          EQU          0
ESAL_AR_STK_TMP_SPSR_OFFSET        EQU          4
ESAL_AR_STK_TMP_LR_OFFSET          EQU          8

; Offsets, in bytes, of registers in minimum stack frame

ESAL_AR_STK_MIN_PC_OFFSET          EQU          28
ESAL_AR_STK_MIN_LR_OFFSET          EQU          24
ESAL_AR_STK_MIN_SPSR_OFFSET        EQU          20
ESAL_AR_STK_MIN_R12_OFFSET         EQU          16

; VFP enable value

ESAL_AR_STK_VFP_ENABLE             EQU          0x40000000


;***********************************************************************
;* ESAL_AR_STK_MIN_INT_SAVE
;*
;* Save minimal amount of registers required for handling interrupts.
;* ESAL_AR_STK_Unsolicited_Switch() will save the rest.
;***********************************************************************

    MACRO
    ESAL_AR_STK_MIN_INT_SAVE 
    ; Save lr on temporary stack

    STR     lr, [sp,#ESAL_AR_STK_TMP_LR_OFFSET]

    ; Get SPSR and save on temporary stack

    MRS     r14, SPSR
    STR     r14, [sp,#ESAL_AR_STK_TMP_SPSR_OFFSET]

    ; Save r0 on temporary stack

    STR     r0, [sp,#ESAL_AR_STK_TMP_R0_OFFSET]

    ; Save address of temporary stack into r0

    MOV     r0, sp

    ; Switch to system mode and keep all interrupts disabled

    MSR     CPSR_c,#(ESAL_AR_ISR_CPSR_SYS_MODE :OR: ESAL_AR_ISR_CPSR_IRQ_BIT :OR: ESAL_AR_ISR_CPSR_FIQ_BIT)

    ; Now in system mode, save the system mode lr
    ; on the current stack and save room for return pc

    STR     lr, [sp,#-8]!

    ; Get lr from temporary stack and save on
    ; system mode stack (in space provided by operation above)

    LDR     r14, [r0,#ESAL_AR_STK_TMP_LR_OFFSET]
    STR     r14, [sp,#4]

    ; Get SPSR and R0 from temporary stack

    LDR     r14, [r0,#ESAL_AR_STK_TMP_SPSR_OFFSET]
    LDR     r0, [r0,#ESAL_AR_STK_TMP_R0_OFFSET]

    ; Now save minimal context required to enter C (save only
    ; toolset scratch registers and necessary registers for
    ; interrupt nesting)

    STMDB   sp!,{r0-r3, r12, r14}

    MEND


;***********************************************************************
;* ESAL_AR_STK_MIN_INT_RESTORE
;*
;* Restore minimal amount of registers required for handling interrupts.
;***********************************************************************

    MACRO
    ESAL_AR_STK_MIN_INT_RESTORE 

    ; Update system stack pointer to end-state

    ADD     r1,r0,#ESAL_AR_STK_MIN_FRAME_SIZE
    MOV     sp,r1

    ; Update system link register and r12 to end-state (banked registers)

    LDR     lr,[r0,#ESAL_AR_STK_MIN_LR_OFFSET]
    LDR     r12,[r0,#ESAL_AR_STK_MIN_R12_OFFSET]

    ; Switch to FIQ mode and keep interrupts disabled (required to have access to SPSR register)
    ; NOTE:  The code following this point cannot result in a change to the FIQ mode SP

    MSR     CPSR_c,#(ESAL_AR_ISR_CPSR_FIQ_MODE :OR: ESAL_AR_ISR_CPSR_IRQ_BIT :OR: ESAL_AR_ISR_CPSR_FIQ_BIT)

    ; Get return address and SPSR from stack
    
    LDR     lr,[r0,#ESAL_AR_STK_MIN_PC_OFFSET]
    LDR     r1,[r0,#ESAL_AR_STK_MIN_SPSR_OFFSET]    
    
    ; Update SPSR

    MSR     SPSR_cxsf, r1    
    
    ; Restore minimal registers

    LDMIA   r0,{r0-r3}

    ; Return to point of interrupt

    MOVS    pc,lr

    MEND


;***********************************************************************
;* ESAL_AR_STK_MIN_EXCEPT_SAVE
;*
;* Save minimal amount of registers required for handling exceptions.
;***********************************************************************

    MACRO
    ESAL_AR_STK_MIN_EXCEPT_SAVE 

    ; Save exception return address on stack

    STR     lr,[sp,#-4]!

    ; No lr to save, so skip it on stack

    SUB     sp,sp,#4

    ; Put spsr in r14 and save remaining
    ; minimal context on stack

    MRS     r14,spsr
    STMDB   sp!,{r0-r3,r12,r14}

    MEND


;***********************************************************************
;* ESAL_AR_STK_MIN_EXCEPT_RESTORE
;*
;* Restore minimal amount of registers required for handling exceptions.
;***********************************************************************

    MACRO
    ESAL_AR_STK_MIN_EXCEPT_RESTORE 

    ; Restore min stack registers

    LDMIA   sp!,{r0-r3, r12, r14}

    ; Restore SPSR

    MSR     SPSR_cxsf,r14

    ; Skip lr on stack

    ADD     sp,sp,#4

    ; Return to point of interrupt
    ; NOTE: {pc}^ also restores the CPSR from the SPSR

    LDMIA   sp!,{pc}^

    MEND

; Define architecture interrupt handling constants,
; register addresses, initialization values, structures, etc.

; Define constants for CPSR interrupt / mode bits

ESAL_AR_ISR_CPSR_MODE_MASK         EQU          0x0000001F
ESAL_AR_ISR_CPSR_SYS_MODE          EQU          0x0000001F
ESAL_AR_ISR_CPSR_IRQ_MODE          EQU          0x00000012
ESAL_AR_ISR_CPSR_FIQ_MODE          EQU          0x00000011
ESAL_AR_ISR_CPSR_UND_MODE          EQU          0x0000001B
ESAL_AR_ISR_CPSR_ABT_MODE          EQU          0x00000017
ESAL_AR_ISR_CPSR_IRQ_BIT           EQU          0x00000080
ESAL_AR_ISR_CPSR_FIQ_BIT           EQU          0x00000040

; Define architecture ESAL interrupt vector IDs
; These IDs match up with architecture interrupts.
; Values correspond to the index of entries in ESAL_GE_ISR_Interrupt_Handler[].
; Names are of the form ESAL_AR_<Name>_INT_VECTOR_ID, where <Name> comes
; directly from the hardware documentation.

ESAL_AR_IRQ_INT_VECTOR_ID          EQU          0
ESAL_AR_FIQ_INT_VECTOR_ID          EQU          1

; Define architecture ESAL exception vector IDs
; These IDs match up with architecture exceptions.
; Values correspond to the index of entries in ESAL_GE_ISR_Exception_Handler[].
; Names are of the form ESAL_AR_<Name>_EXCEPT_VECTOR_ID, where <Name> comes
; directly from the hardware documentation.

ESAL_AR_UNDEF_EXCEPT_VECTOR_ID     EQU          0
ESAL_AR_SWI_EXCEPT_VECTOR_ID       EQU          1
ESAL_AR_PREFETCH_EXCEPT_VECTOR_ID  EQU          2
ESAL_AR_DATA_EXCEPT_VECTOR_ID      EQU          3    
