/***********************************************************************
 *
 *             Copyright 2011 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
 *
 *      csgnu_ppc_defs.inc
 *
 *  DESCRIPTION
 *
 *      This file contains the architecture specific definitions,
 *      constants, etc, for CSGNU for PPC
 *
 *  DATA STRUCTURES
 *
 *      None
 *
 *  DEPENDENCIES
 *
 *      None
 *
 ***********************************************************************/

# Register definitions for PPC E500 MMU
 
.equ    SPR_MAS0,                       624
.equ    SPR_MAS1,                       625
.equ    SPR_MAS2,                       626
.equ    SPR_MAS3,                       627
.equ    SPR_MAS4,                       628
.equ    SPR_MAS5,                       629
.equ    SPR_MAS6,                       630
.equ    SPR_PID0,                       48
.equ    SPR_SRR0,                       26
.equ    SPR_SRR1,                       27

.equ    MAS0_TLB1_SELECT,               0x10000000
.equ    MAS0_TLB1_ESEL_SHIFT,           16
.equ    MAS1_TLB1_VALID_BIT,            0x80000000
.equ    MAS1_TLB1_IPROT_BIT,            0x40000000
.equ    MAS1_TLB1_VALID_CLEAR_MASK,     0x7FFFFFFF
.equ    MAS1_TLB1_INIT_VAL,             0x80000500
.equ    MAS2_TLB1_WIMGE_ATTR,           0x00000010
.equ    MAS3_TLB1_RPN_MASK,             0x00000FFF

.equ    MAS1_ENTRY_TS0_KERNEL_MAPPING,  0x80000500
.equ    MAS1_ENTRY_TS1_KERNEL_MAPPING,  0xC0001A00

# Define the FPSCR field mask.

#define ESAL_AR_STK_FPSCR_FM                      0xFF

# MSR FP enable

#define ESAL_AR_STK_MSR_FP                        0x2000

# Size, in bytes, of architecture startup stack

#define ESAL_AR_STK_STARTUP_SIZE                  1024

# Alignment shift value based on required stack alignment (defined in esal_ts_cfg.h)

#define ESAL_AR_STK_ALIGNMENT_SHIFT               3

# Define for conditional branch instruction to "branch always" (BO = 0b1z1zz)

#define ESAL_AR_STK_BRANCH_ALWAYS                 0x14

# Define constants required for interrupt handling

#if (CFG_NU_OS_ARCH_PPC_COM_PPC_VARIANT == 0)

/* PPC32 variant */
#define ESAL_AR_ISR_MSR_LOCKOUT_BITS              0x8080
#define ESAL_AR_ISR_MSR_PR_BIT                    0x4000
#define ESAL_AR_ISR_MSR_SE_BIT                    0x0400

#else /* CFG_NU_OS_ARCH_PPC_COM_PPC_VARIANT == 1 */

/* BookE variant */
#define ESAL_AR_ISR_MSR_LOCKOUT_BITS              0x29000

#endif /* CFG_NU_OS_ARCH_PPC_COM_PPC_VARIANT == 0 */

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

#define ESAL_AR_STK_MIN_CTR_OFFSET                0
#define ESAL_AR_STK_MIN_XER_OFFSET                4
#define ESAL_AR_STK_MIN_CR_OFFSET                 8
#define ESAL_AR_STK_MIN_LR_OFFSET                 12
#define ESAL_AR_STK_MIN_R0_OFFSET                 16
#define ESAL_AR_STK_MIN_R3_OFFSET                 20
#define ESAL_AR_STK_MIN_R4_OFFSET                 24
#define ESAL_AR_STK_MIN_R5_OFFSET                 28
#define ESAL_AR_STK_MIN_R6_OFFSET                 32
#define ESAL_AR_STK_MIN_R7_OFFSET                 36
#define ESAL_AR_STK_MIN_R8_OFFSET                 40
#define ESAL_AR_STK_MIN_R9_OFFSET                 44
#define ESAL_AR_STK_MIN_R10_OFFSET                48
#define ESAL_AR_STK_MIN_MSR_OFFSET                52
#define ESAL_AR_STK_MIN_PC_OFFSET                 56
#define ESAL_AR_STK_MIN_R11_OFFSET                60
#define ESAL_AR_STK_MIN_R12_OFFSET                64

# Define constants required for interrupt handling

#define ESAL_AR_ISR_SRR0_NUM                      26
#define ESAL_AR_ISR_SRR1_NUM                      27
#define ESAL_AR_ISR_CSRR0_NUM                     58
#define ESAL_AR_ISR_CSRR1_NUM                     59

# Define ESAL interrupt vector IDs for the architecture.
# 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 the Name comes
# directly from the hardware documentation

#if (CFG_NU_OS_ARCH_PPC_COM_PPC_VARIANT == 0)

/* PPC32 variant */
#define ESAL_AR_MACHINE_CHECK_INT_VECTOR_ID       0
#define ESAL_AR_EXTERNAL_INT_VECTOR_ID            1
#define ESAL_AR_DECREMENTER_INT_VECTOR_ID         2
#define ESAL_AR_CRITICAL_INT_VECTOR_ID            3

#else /* CFG_NU_OS_ARCH_PPC_COM_PPC_VARIANT == 1 */

/* BookE variant */
#define ESAL_AR_CRITICAL_INT_VECTOR_ID            0
#define ESAL_AR_MACHINE_CHECK_INT_VECTOR_ID       1
#define ESAL_AR_EXTERNAL_INT_VECTOR_ID            2
#define ESAL_AR_DECREMENTER_INT_VECTOR_ID         3
#define ESAL_AR_FIT_INT_VECTOR_ID                 4
#define ESAL_AR_WATCHDOG_INT_VECTOR_ID            5
#define ESAL_AR_DEBUG_INT_VECTOR_ID               6

#endif /* CFG_NU_OS_ARCH_PPC_COM_PPC_VARIANT == 0 */

# Define ESAL exception vector IDs for the architecture.
# 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 the Name comes
# directly from the hardware documentation

#define ESAL_AR_DSI_EXCEPT_VECTOR_ID              0
#define ESAL_AR_ISI_EXCEPT_VECTOR_ID              1
#define ESAL_AR_ALIGNMENT_EXCEPT_VECTOR_ID        2
#define ESAL_AR_PROGRAM_EXCEPT_VECTOR_ID          3
#define ESAL_AR_FLTPT_UNAVAIL_EXCEPT_VECTOR_ID    4

#if (CFG_NU_OS_ARCH_PPC_COM_PPC_VARIANT == 0)

/* PPC32 variant */
#define ESAL_AR_RSRVD_0B00_EXCEPT_VECTOR_ID       5
#define ESAL_AR_SYSCALL_EXCEPT_VECTOR_ID          6
#define ESAL_AR_TRACE_EXCEPT_VECTOR_ID            7
#define ESAL_AR_FLTPT_ASSIST_EXCEPT_VECTOR_ID     8
#define ESAL_AR_RSRVD_0F00_EXCEPT_VECTOR_ID       9
#define ESAL_AR_RSRVD_1000_EXCEPT_VECTOR_ID       10
#define ESAL_AR_RSRVD_1100_EXCEPT_VECTOR_ID       11
#define ESAL_AR_RSRVD_1200_EXCEPT_VECTOR_ID       12
#define ESAL_AR_RSRVD_1300_EXCEPT_VECTOR_ID       13
#define ESAL_AR_RSRVD_1400_EXCEPT_VECTOR_ID       14
#define ESAL_AR_RSRVD_1500_EXCEPT_VECTOR_ID       15
#define ESAL_AR_RSRVD_1600_EXCEPT_VECTOR_ID       16
#define ESAL_AR_RSRVD_1700_EXCEPT_VECTOR_ID       17
#define ESAL_AR_RSRVD_1800_EXCEPT_VECTOR_ID       18
#define ESAL_AR_RSRVD_1900_EXCEPT_VECTOR_ID       19
#define ESAL_AR_RSRVD_1A00_EXCEPT_VECTOR_ID       20
#define ESAL_AR_RSRVD_1B00_EXCEPT_VECTOR_ID       21
#define ESAL_AR_RSRVD_1C00_EXCEPT_VECTOR_ID       22
#define ESAL_AR_RSRVD_1D00_EXCEPT_VECTOR_ID       23
#define ESAL_AR_RSRVD_1E00_EXCEPT_VECTOR_ID       24
#define ESAL_AR_RSRVD_1F00_EXCEPT_VECTOR_ID       25

#else /* CFG_NU_OS_ARCH_PPC_COM_PPC_VARIANT == 1 */

/* BookE variant */
#define ESAL_AR_SYSCALL_EXCEPT_VECTOR_ID          5
#define ESAL_AR_AP_UNAVAIL_EXCEPT_VECTOR_ID       6
#define ESAL_AR_DTLB_ERR_EXCEPT_VECTOR_ID         7
#define ESAL_AR_ITLB_ERR_EXCEPT_VECTOR_ID         8
#define ESAL_AR_IVOR16_EXCEPT_VECTOR_ID           9
#define ESAL_AR_IVOR17_EXCEPT_VECTOR_ID           10
#define ESAL_AR_IVOR18_EXCEPT_VECTOR_ID           11
#define ESAL_AR_IVOR19_EXCEPT_VECTOR_ID           12
#define ESAL_AR_IVOR20_EXCEPT_VECTOR_ID           13
#define ESAL_AR_IVOR21_EXCEPT_VECTOR_ID           14
#define ESAL_AR_IVOR22_EXCEPT_VECTOR_ID           15
#define ESAL_AR_IVOR23_EXCEPT_VECTOR_ID           16
#define ESAL_AR_IVOR24_EXCEPT_VECTOR_ID           17
#define ESAL_AR_IVOR25_EXCEPT_VECTOR_ID           18
#define ESAL_AR_IVOR26_EXCEPT_VECTOR_ID           19
#define ESAL_AR_IVOR27_EXCEPT_VECTOR_ID           20
#define ESAL_AR_IVOR28_EXCEPT_VECTOR_ID           21
#define ESAL_AR_IVOR29_EXCEPT_VECTOR_ID           22
#define ESAL_AR_IVOR30_EXCEPT_VECTOR_ID           23
#define ESAL_AR_IVOR31_EXCEPT_VECTOR_ID           24
#define ESAL_AR_IVOR32_EXCEPT_VECTOR_ID           25
#define ESAL_AR_IVOR33_EXCEPT_VECTOR_ID           26
#define ESAL_AR_IVOR34_EXCEPT_VECTOR_ID           27
#define ESAL_AR_IVOR35_EXCEPT_VECTOR_ID           28
#define ESAL_AR_IVOR36_EXCEPT_VECTOR_ID           29
#define ESAL_AR_IVOR37_EXCEPT_VECTOR_ID           30
#define ESAL_AR_IVOR38_EXCEPT_VECTOR_ID           31
#define ESAL_AR_IVOR39_EXCEPT_VECTOR_ID           32
#define ESAL_AR_IVOR40_EXCEPT_VECTOR_ID           33
#define ESAL_AR_IVOR41_EXCEPT_VECTOR_ID           34
#define ESAL_AR_IVOR42_EXCEPT_VECTOR_ID           35
#define ESAL_AR_IVOR43_EXCEPT_VECTOR_ID           36
#define ESAL_AR_IVOR44_EXCEPT_VECTOR_ID           37
#define ESAL_AR_IVOR45_EXCEPT_VECTOR_ID           38
#define ESAL_AR_IVOR46_EXCEPT_VECTOR_ID           39
#define ESAL_AR_IVOR47_EXCEPT_VECTOR_ID           40
#define ESAL_AR_IVOR48_EXCEPT_VECTOR_ID           41
#define ESAL_AR_IVOR49_EXCEPT_VECTOR_ID           42
#define ESAL_AR_IVOR50_EXCEPT_VECTOR_ID           43
#define ESAL_AR_IVOR51_EXCEPT_VECTOR_ID           44
#define ESAL_AR_IVOR52_EXCEPT_VECTOR_ID           45
#define ESAL_AR_IVOR53_EXCEPT_VECTOR_ID           46
#define ESAL_AR_IVOR54_EXCEPT_VECTOR_ID           47
#define ESAL_AR_IVOR55_EXCEPT_VECTOR_ID           48
#define ESAL_AR_IVOR56_EXCEPT_VECTOR_ID           49
#define ESAL_AR_IVOR57_EXCEPT_VECTOR_ID           50
#define ESAL_AR_IVOR58_EXCEPT_VECTOR_ID           51
#define ESAL_AR_IVOR59_EXCEPT_VECTOR_ID           52
#define ESAL_AR_IVOR60_EXCEPT_VECTOR_ID           53
#define ESAL_AR_IVOR61_EXCEPT_VECTOR_ID           54
#define ESAL_AR_IVOR62_EXCEPT_VECTOR_ID           55
#define ESAL_AR_IVOR63_EXCEPT_VECTOR_ID           56

#endif /* CFG_NU_OS_ARCH_PPC_COM_PPC_VARIANT == 0 */

#***********************************************************************
#* ESAL_AR_SAVE_REGISTER
#*
#* Handles both SPE and non-SPE single register save
#***********************************************************************
    .macro  ESAL_AR_SAVE_REGISTER register
	
#if (CFG_NU_OS_ARCH_PPC_COM_SPE_SUPPORT == 0)
    stwu    \register,-4(r1)
#else
    addi    r1,r1,-8
    evstdd  \register,0(r1)
#endif

    .endm

#***********************************************************************
#* ESAL_AR_RESTORE_REGISTER
#*
#* Handles both SPE and non-SPE single register restore
#***********************************************************************
    .macro  ESAL_AR_RESTORE_REGISTER register
	
#if (CFG_NU_OS_ARCH_PPC_COM_SPE_SUPPORT == 0)
    lwzu    \register,4(r1)
#else
    addi    r1,r1,8
    evldd   \register,0(r1)
#endif

    .endm

#***********************************************************************
#* ESAL_AR_ISR_HOOK_EXECUTE
#*
#* Save minimal registers and execute low-level ISR hook
#***********************************************************************

    .macro ESAL_AR_ISR_HOOK_EXECUTE

#if (CFG_NU_OS_ARCH_PPC_COM_ISR_HOOK_ENABLED == 1)

    # Adjust stack to save minimal registers to call C function

    addi    r1,r1,-32

    # Save minimal registers

    stw     r12,28(r1)
    mfspr   r12,LR
    stw     r12,24(r1)
    mfspr   r12,CTR
    stw     r12,20(r1)

    # Call low-level ISR hook

    bl      ESAL_AR_ISR_HOOK

    # Restore minimal registers

    lwz     r12,20(r1)
    mtspr   CTR,r12
    lwz     r12,24(r1)
    mtspr   LR,r12
    lwz     r12,28(r1)

    # Reset stack pointer

    addi    r1,r1,32

#endif /* (CFG_NU_OS_ARCH_PPC_COM_ISR_HOOK_ENABLED == 1) */

    .endm
	
#if (CFG_NU_OS_ARCH_PPC_COM_SPE_SUPPORT == 0)

#define ESAL_AR_STK_ALIGNMENT                           4

#define ESAL_AR_STK_ADJUSTMENT                          4

#else /* CFG_NU_OS_ARCH_PPC_COM_SPE_SUPPORT == 1 */

#define ESAL_AR_STK_ALIGNMENT                           16

#define ESAL_AR_STK_ADJUSTMENT                          8

#endif /* CFG_NU_OS_ARCH_PPC_COM_SPE_SUPPORT == 0 */

#***********************************************************************
#* ESAL_AR_STK_MIN_SAVE
#*
#* Save minimal amount of registers required for handling interrupts.
#***********************************************************************

    .macro ESAL_AR_STK_MIN_SAVE REG0=ESAL_AR_ISR_SRR0_NUM, REG1=ESAL_AR_ISR_SRR1_NUM

#if (CFG_NU_OS_ARCH_PPC_COM_SPE_SUPPORT == 1) || (CFG_NU_OS_ARCH_PPC_COM_PPC_VARIANT == 1)

    # Re-enable SPE support if user requires or if this is a BookE variant

    stwu    r12,-4(r1)
    mfmsr   r12
    oris    r12,r12,0x200
    mtmsr   r12
    lwz     r12,0(r1)
    addi    r1,r1,4

#endif

    ESAL_AR_SAVE_REGISTER r12
    ESAL_AR_SAVE_REGISTER r3

    # Save return PC on stack (SRR0 or CSRR0)

    mfspr   r12,\REG0
    stwu    r12,-4(r1)

    # Save return MSR on stack (SRR1 or CSRR1)

    mfspr   r12,\REG1
    stwu    r12,-4(r1)

#if (CFG_NU_OS_ARCH_PPC_COM_PPC_VARIANT == 0)
# PPC32 variant ONLY

    # Disable interrupts, re-enable address translation (if enabled) and
    # clear single-stepping (if enabled)

    li      r3,0
    ori     r3,r3,(ESAL_AR_ISR_MSR_LOCKOUT_BITS | ESAL_AR_ISR_MSR_PR_BIT | ESAL_AR_ISR_MSR_SE_BIT)
    andc    r12,r12,r3
    mtmsr   r12
    isync
    eieio	

#endif    

    # Save r0,r4-r11 (C scratch registers) on stack

    ESAL_AR_SAVE_REGISTER r11
    ESAL_AR_SAVE_REGISTER r10
    ESAL_AR_SAVE_REGISTER r9
    ESAL_AR_SAVE_REGISTER r8
    ESAL_AR_SAVE_REGISTER r7
    ESAL_AR_SAVE_REGISTER r6
    ESAL_AR_SAVE_REGISTER r5
    ESAL_AR_SAVE_REGISTER r4
    ESAL_AR_SAVE_REGISTER r0

    # Save LR on stack

    mfspr   r12,LR
    stwu    r12,-4(r1)

    # Save CR on stack

    mfcr    r12
    stwu    r12,-4(r1)

    # Save XER on stack

    mfspr   r12,XER
    stwu    r12,-4(r1)

    # Save CTR on stack

    mfspr   r12,CTR
    stwu    r12,-4(r1)

    .endm


#***********************************************************************
#* ESAL_AR_STK_MIN_RESTORE
#*
#* Restore minimal amount of registers required for handling interrupts.
#***********************************************************************

    .macro ESAL_AR_STK_MIN_RESTORE REG0=ESAL_AR_ISR_SRR0_NUM, REG1=ESAL_AR_ISR_SRR1_NUM

    # Restore CTR from stack

    lwz     r12,0(r1)
    mtspr   CTR,r12

    # Restore XER from stack

    lwzu    r12,4(r1)
    mtspr   XER,r12

    # Restore CR from stack

    lwzu    r12,4(r1)
    mtcr    r12

    # Restore LR from stack

    lwzu    r12,4(r1)
    mtspr   LR,r12

#if (CFG_NU_OS_ARCH_PPC_COM_SPE_SUPPORT == 1)

    addi    r1,r1,-4 # Adjust stack so restore macro aligns for SPE mode

#endif

    # Restore r0, r4-r11 (C scratch registers) from stack

    ESAL_AR_RESTORE_REGISTER r0
    ESAL_AR_RESTORE_REGISTER r4
    ESAL_AR_RESTORE_REGISTER r5
    ESAL_AR_RESTORE_REGISTER r6
    ESAL_AR_RESTORE_REGISTER r7
    ESAL_AR_RESTORE_REGISTER r8
    ESAL_AR_RESTORE_REGISTER r9
    ESAL_AR_RESTORE_REGISTER r10
    ESAL_AR_RESTORE_REGISTER r11

#if (CFG_NU_OS_ARCH_PPC_COM_SPE_SUPPORT == 1)

    addi    r1,r1,4 # Adjust stack for SPE mode

#endif

    # Restore return MSR from stack

    lwzu    r12,4(r1)
    mtspr   \REG1,r12

    # Restore return PC from stack

    lwzu    r12,4(r1)
    mtspr   \REG0,r12

#if (CFG_NU_OS_ARCH_PPC_COM_SPE_SUPPORT == 1)

    addi    r1,r1,-4 # Adjust stack so restore macro aligns for SPE mode

#endif

    # Restore r3 and r12 from stack

    ESAL_AR_RESTORE_REGISTER r3
    ESAL_AR_RESTORE_REGISTER r12

    # Adjust stack for last "pop"

    addi    r1,r1,ESAL_AR_STK_ADJUSTMENT

    .endm

#***********************************************************************
#* ESAL_AR_ISR_EXCEPTION_HANDLER
#*
#* Default Handler code for exceptions/interrupts
#***********************************************************************
    .macro  ESAL_AR_ISR_EXCEPTION_HANDLER label, vector_id, address
	
#if (CFG_NU_OS_ARCH_PPC_COM_PPC_VARIANT == 0)
    .org \address+ESAL_AR_ISR_Vector_Table
#else
    .align  4
#endif

    .global  \label
\label:

    # Execute low-level ISR hook (if enabled)

    ESAL_AR_ISR_HOOK_EXECUTE

    # Save minimal registers

    ESAL_AR_STK_MIN_SAVE

    # Get vector number in r3

    li      r3,\vector_id

    # Load address of exception handler into CTR

    lis     r9,ESAL_AR_ISR_Exception_Handler@h
    ori     r9,r9,ESAL_AR_ISR_Exception_Handler@l
    mtspr   CTR,r9

    # Jump to exception handler

    bctr

    .endm

#***********************************************************************
#* ESAL_AR_ISR_EXTERNAL_HANDLER
#*
#* Default Handler code for exceptions/interrupts
#***********************************************************************
    .macro  ESAL_AR_ISR_EXTERNAL_HANDLER label, vector_id, address
	
#if (CFG_NU_OS_ARCH_PPC_COM_PPC_VARIANT == 0)
    .org \address+ESAL_AR_ISR_Vector_Table
#else
    .align  4
#endif

    .global  \label
\label:

    # Execute low-level ISR hook (if enabled)

    ESAL_AR_ISR_HOOK_EXECUTE

    # Save minimal registers

    ESAL_AR_STK_MIN_SAVE

    # Get vector number in r3

    li      r3,\vector_id

    # Load address of interrupt handler into CTR

    lis     r9,ESAL_AR_ISR_External_Handler@h
    ori     r9,r9,ESAL_AR_ISR_External_Handler@l
    mtspr   CTR,r9

    # Jump to interrupt handler

    bctr

    .endm

