/***********************************************************************
*
*             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
*
*       ppc_defs.h
*
*   DESCRIPTION
*
*       This file contains all definitions, structures, etc for the
*       base PPC architecture.
*
*   DATA STRUCTURES
*
*       None
*
*   DEPENDENCIES
*
*       None
*
***********************************************************************/

#ifndef         PPC_DEFS_H
#define         PPC_DEFS_H

/* Define if critical interrupts are available (NU_TRUE) or not (NU_FALSE)
   for this core
   NOTE:  An assembler define for this same attribute must also be set in
          csgnu_ppc_defs.inc */
#define         ESAL_CO_CRITICAL_INTS_AVAIL             CFG_NU_OS_ARCH_PPC_COM_CRIT_INT_SUPPORT

/* Define if the OS timer is part of the architecture (NU_TRUE)
   NOTE:  The OS timer can be located at only one of the following levels of
          abstraction: the processor level or the architecture level.
          If ESAL_AR_OS_TIMER_USED is NU_TRUE, the OS timer is contained
          within the architecture.  If ESAL_AR_OS_TIMER_USED is NU_FALSE,
          the OS timer is contained within the processor component. */
#define         ESAL_AR_OS_TIMER_USED                   NU_TRUE

/* Define if architecture supports unaligned 16-bit accesses to memory. */
#define         ESAL_AR_UNALIGNED_16BIT_SPT             NU_FALSE

/* Define if architecture supports unaligned 32-bit accesses to memory. */
#define         ESAL_AR_UNALIGNED_32BIT_SPT             NU_FALSE

/* Define number of accesses required to read or write a pointer */
#define         ESAL_AR_PTR_ACCESS                      1

/* Define number of accesses required to read or write a 32-bit value */
#define         ESAL_AR_32BIT_ACCESS                    1

/* Define reverse bit ordering in PPC.  This makes many of the ESAL
   memory macros use reverse-bit ordering (bit 0 is most-significant bit) */
#define         ESAL_AR_REVERSE_BIT_ORDERING

/* Size, in bytes, of architecture system stack.  This stack will be
   utilized when servicing interrupts. */
#define         ESAL_AR_SYSTEM_STACK_SIZE               CFG_NU_OS_ARCH_PPC_COM_SYSTEM_STACK_SIZE

/* Size, in bytes, of architecture exception stack.  This stack will be
   utilized when servicing exceptions. */
#define         ESAL_AR_EXCEPTION_STACK_SIZE            0

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

/* MSR IP-Exception prefix bit */
#define         ESAL_AR_ISR_MSR_IP_BIT                  ESAL_GE_MEM_32BIT_SET(25)

/* Define default vector table address for PPC */
#define         ESAL_AR_ISR_VECT_TABLE_ADDRESS          0x00000000

#endif /* (CFG_NU_OS_ARCH_PPC_COM_PPC_VARIANT == 0) */

/* Define if interrupt servicing initialization is required at the
   architecture level. */
#define         ESAL_AR_ISR_INIT_REQUIRED               NU_TRUE

/* Define if architecture mandates that all interrupt handlers perform a
   "return from interrupt" (RTI) instruction in order for the hardware to
   correctly restore the state of execution to the pre-interrupt condition.
   NOTE:  Most architectures allow the state of execution to be restored
          without needing to perform an RTI.  In most cases, this will be set
          to NU_FALSE */
#define         ESAL_AR_ISR_RTI_MANDATORY               NU_FALSE

/* Determines where the ISR nesting counter is incremented.  
   When set to 0 the increment occurs in assembly files, when 
   set to 1 the increment will occur in c files. */
#define         ESAL_AR_ISR_INCREMENT_IN_C              NU_TRUE

/* Define bit values for the architecture's status register / machine state register /
   etc that are used to enable and disable interrupts for the given architecture. */
#define         ESAL_AR_INTERRUPTS_DISABLE_BITS         0x00000000
#if (CFG_NU_OS_ARCH_PPC_COM_PPC_VARIANT == 0)
/* PPC32 variant ONLY */
#define         ESAL_AR_INTERRUPTS_ENABLE_BITS          0x00008080
#else /* CFG_NU_OS_ARCH_PPC_COM_PPC_VARIANT == 1 */
/* BookE variant ONLY */
#define         ESAL_AR_INTERRUPTS_ENABLE_BITS          0x00029000
#endif /* (CFG_NU_OS_ARCH_PPC_COM_PPC_VARIANT == 0) */

/* Define if floating point registers will be saved during context switches
   NOTE:  The assembly define must be changed in csgnu_ppc_defs.inc to
          match this define
   NOTE:  This define will dictate what registers are contained
          within solicited (TS) and unsolicited (AR) stack frames. */
#define         ESAL_AR_STK_FPU_SUPPORT                 CFG_NU_OS_ARCH_PPC_COM_FPU_SUPPORT

/* Define is set if SPE instructions will be used during context switches
NOTE:  The assembly define must be changed in esal_ar_stk_defs.inc to
       match this define
NOTE:  This define will dictate if the GPR are 64-bits or 32-bits. */
#define         ESAL_AR_STK_SPE_SUPPORT                 CFG_NU_OS_ARCH_PPC_COM_SPE_SUPPORT

/* Define stack frame structure for minimum architecture registers required
   to be saved in order to enter a C environment during in interrupt / exception.
   These registers are the "scratch" registers that will not be preserved across
   a function call boundary and any interrupt state registers that must preserved
   to allow interrupt nesting. */
typedef struct
{
    UINT32          ctr;
    UINT32          xer;
    UINT32          cr;
    UINT32          lr;

#if (ESAL_AR_STK_SPE_SUPPORT)

    UINT64          r0;
    UINT64          r4;
    UINT64          r5;
    UINT64          r6;
    UINT64          r7;
    UINT64          r8;
    UINT64          r9;
    UINT64          r10;
    UINT64          r11;
    UINT32          msr;
    UINT32          rtn_address;
    UINT64          r3;
    UINT64          r12;

#else /* SPE not supported/set. */

    UINT32          r0;
    UINT32          r4;
    UINT32          r5;
    UINT32          r6;
    UINT32          r7;
    UINT32          r8;
    UINT32          r9;
    UINT32          r10;
    UINT32          r11;
    UINT32          msr;
    UINT32          rtn_address;
    UINT32          r3;
    UINT32          r12;

#endif /* #if (ESAL_AR_STK_SPE_SUPPORT) */

} ESAL_AR_STK_MIN;

/* Define stack frame structure for the architecture supported.
   This stack frame contains all registers that must be preserved
   across an (unsolicited) interrupt context switch.
   NOTE:  This stack frame includes the minimum stack frame
          defined above AND all other registers for the given
          architecture. */
typedef struct  ESAL_AR_STK_STRUCT
{
    UINT32          stack_type;

#if (ESAL_AR_STK_SPE_SUPPORT)

    UINT64          r14;
    UINT64          r15;
    UINT64          r16;
    UINT64          r17;
    UINT64          r18;
    UINT64          r19;
    UINT64          r20;
    UINT64          r21;
    UINT64          r22;
    UINT64          r23;
    UINT64          r24;
    UINT64          r25;
    UINT64          r26;
    UINT64          r27;
    UINT64          r28;
    UINT64          r29;
    UINT64          r30;
    UINT64          r31;


#else /* SPE not supported/set. */

    UINT32          r14;
    UINT32          r15;
    UINT32          r16;
    UINT32          r17;
    UINT32          r18;
    UINT32          r19;
    UINT32          r20;
    UINT32          r21;
    UINT32          r22;
    UINT32          r23;
    UINT32          r24;
    UINT32          r25;
    UINT32          r26;
    UINT32          r27;
    UINT32          r28;
    UINT32          r29;
    UINT32          r30;
    UINT32          r31;

#endif /* #if (ESAL_AR_STK_SPE_SUPPORT) */

#if (ESAL_AR_STK_FPU_SUPPORT == NU_TRUE)

    UINT32        fpscr;
    UINT32        f0[2];
    UINT32        f1[2];
    UINT32        f2[2];
    UINT32        f3[2];
    UINT32        f4[2];
    UINT32        f5[2];
    UINT32        f6[2];
    UINT32        f7[2];
    UINT32        f8[2];
    UINT32        f9[2];
    UINT32        f10[2];
    UINT32        f11[2];
    UINT32        f12[2];
    UINT32        f13[2];
    UINT32        f14[2];
    UINT32        f15[2];
    UINT32        f16[2];
    UINT32        f17[2];
    UINT32        f18[2];
    UINT32        f19[2];
    UINT32        f20[2];
    UINT32        f21[2];
    UINT32        f22[2];
    UINT32        f23[2];
    UINT32        f24[2];
    UINT32        f25[2];
    UINT32        f26[2];
    UINT32        f27[2];
    UINT32        f28[2];
    UINT32        f29[2];
    UINT32        f30[2];
    UINT32        f31[2];

#endif /* (ESAL_AR_STK_FPU_SUPPORT == NU_TRUE) */

    ESAL_AR_STK_MIN min_stack;
    UINT32          eabi[4];

} ESAL_AR_STK;

/* Define stack frame structure for the toolset / architecture supported. */
typedef struct  ESAL_TS_STK_STRUCT
{
    UINT32        stack_type;

#if (ESAL_AR_STK_SPE_SUPPORT)

    UINT64        r14;
    UINT64        r15;
    UINT64        r16;
    UINT64        r17;
    UINT64        r18;
    UINT64        r19;
    UINT64        r20;
    UINT64        r21;
    UINT64        r22;
    UINT64        r23;
    UINT64        r24;
    UINT64        r25;
    UINT64        r26;
    UINT64        r27;
    UINT64        r28;
    UINT64        r29;
    UINT64        r30;
    UINT64        r31;
    UINT32        ctr;
    UINT32        cr;
    UINT32        rtn_address;

#else /* SPE not supported/set. */

    UINT32        r14;
    UINT32        r15;
    UINT32        r16;
    UINT32        r17;
    UINT32        r18;
    UINT32        r19;
    UINT32        r20;
    UINT32        r21;
    UINT32        r22;
    UINT32        r23;
    UINT32        r24;
    UINT32        r25;
    UINT32        r26;
    UINT32        r27;
    UINT32        r28;
    UINT32        r29;
    UINT32        r30;
    UINT32        r31;
    UINT32        ctr;
    UINT32        cr;
    UINT32        rtn_address;

#endif /* #ESAL_AR_STK_SPE_SUPPORT) */

#if (ESAL_AR_STK_FPU_SUPPORT == NU_TRUE)

    UINT32      f14[2];
    UINT32      f15[2];
    UINT32      f16[2];
    UINT32      f17[2];
    UINT32      f18[2];
    UINT32      f19[2];
    UINT32      f20[2];
    UINT32      f21[2];
    UINT32      f22[2];
    UINT32      f23[2];
    UINT32      f24[2];
    UINT32      f25[2];
    UINT32      f26[2];
    UINT32      f27[2];
    UINT32      f28[2];
    UINT32      f29[2];
    UINT32      f30[2];
    UINT32      f31[2];

#endif /* (ESAL_AR_STK_FPU_SUPPORT == NU_TRUE) */

    UINT32        eabi[4];

} ESAL_TS_STK;

/* This define is used to add quotes to anything passed in */
#define         ESAL_TS_RTE_QUOTES(x)                   #x

/* Define PPC Architecture SPR register numbers */
#define         ESAL_TS_RTE_DEC                         22
#define         ESAL_TS_RTE_TBL_READ                    268
#define         ESAL_TS_RTE_TBU_READ                    269
#define         ESAL_TS_RTE_SPRG0                       272
#define         ESAL_TS_RTE_SPRG1                       273
#define         ESAL_TS_RTE_SPRG2                       274
#define         ESAL_TS_RTE_SPRG3                       275
#define         ESAL_TS_RTE_TBL_WRITE                   284
#define         ESAL_TS_RTE_TBU_WRITE                   285
#define         ESAL_TS_RTE_PIR                         286
#define         ESAL_TS_RTE_IBAT0U                      528
#define         ESAL_TS_RTE_IBAT0L                      529
#define         ESAL_TS_RTE_IBAT1U                      530
#define         ESAL_TS_RTE_IBAT1L                      531
#define         ESAL_TS_RTE_IBAT2U                      532
#define         ESAL_TS_RTE_IBAT2L                      533
#define         ESAL_TS_RTE_IBAT3U                      534
#define         ESAL_TS_RTE_IBAT3L                      535
#define         ESAL_TS_RTE_DBAT0U                      536
#define         ESAL_TS_RTE_DBAT0L                      537
#define         ESAL_TS_RTE_DBAT1U                      538
#define         ESAL_TS_RTE_DBAT1L                      539
#define         ESAL_TS_RTE_DBAT2U                      540
#define         ESAL_TS_RTE_DBAT2L                      541
#define         ESAL_TS_RTE_DBAT3U                      542
#define         ESAL_TS_RTE_DBAT3L                      543
#define         ESAL_TS_RTE_IVPR                        63
#define         ESAL_TS_RTE_IVOR0                       400
#define         ESAL_TS_RTE_IVOR1                       401
#define         ESAL_TS_RTE_IVOR2                       402
#define         ESAL_TS_RTE_IVOR3                       403
#define         ESAL_TS_RTE_IVOR4                       404
#define         ESAL_TS_RTE_IVOR5                       405
#define         ESAL_TS_RTE_IVOR6                       406
#define         ESAL_TS_RTE_IVOR7                       407
#define         ESAL_TS_RTE_IVOR8                       408
#define         ESAL_TS_RTE_IVOR9                       409
#define         ESAL_TS_RTE_IVOR10                      410
#define         ESAL_TS_RTE_IVOR11                      411
#define         ESAL_TS_RTE_IVOR12                      412
#define         ESAL_TS_RTE_IVOR13                      413
#define         ESAL_TS_RTE_IVOR14                      414
#define         ESAL_TS_RTE_IVOR15                      415

/* IVOR16 to IVOR31 are Reserved for future architectural in the e500 core      */
#define         ESAL_TS_RTE_IVOR32                      528     /* SPE Not Avail    */
#define         ESAL_TS_RTE_IVOR33                      529     /* EFP Data Excpt   */
#define         ESAL_TS_RTE_IVOR34                      530     /* EFP Round Excpt  */
#define         ESAL_TS_RTE_IVOR35                      531     /* Perform Monitor  */

/* Defines used to specify an interrupt source type as a normal External Interrupt
   or Critical Interrupt (for PPC variants that support Critical Interrupts).
   This value can be bitwise OR'd with the priority field when enabling an interrupt
   source via the ESAL_GE_INT_Enable API to specify if an interrupt will be routed
   as an External or Critical Interrupt.  The default for all interrupt sources is
   External routed (interrupt will be External routed if not specified when enabling
   an interrupt source via ESAL_GE_INT_Enable).
   NOTE:  This operation is not supported by all PPC processor implementations - some
          processors allow any interrupt source to be either External or Critical while other
          do not allow this functionality.  Additionally, some PPC processors do not
          support Critical interrupts at all. */
#define         ESAL_AR_INT_EXTERNAL_ROUTED                 (INT)0x00001000
#define         ESAL_AR_INT_CRITICAL_ROUTED                 (INT)0x00002000

/* Defines the enable bits for the interrupts enable through the MSR */
#define         ESAL_AR_INT_MACHINE_CHECK_BIT               ESAL_GE_MEM_32BIT_SET(19)
#define         ESAL_AR_INT_EXTERNAL_DECREMENTER_BIT        ESAL_GE_MEM_32BIT_SET(16)
#if (CFG_NU_OS_ARCH_PPC_COM_PPC_VARIANT == 0)
/* PPC32 variant ONLY */
#define         ESAL_AR_INT_CRITICAL_BIT                    ESAL_GE_MEM_32BIT_SET(24)
#else /* CFG_NU_OS_ARCH_PPC_COM_PPC_VARIANT == 1 */
/* BookE variant ONLY */
#define         ESAL_AR_INT_CRITICAL_BIT                    ESAL_GE_MEM_32BIT_SET(14)
#define         ESAL_AR_INT_DEBUG_BIT                       ESAL_GE_MEM_32BIT_SET(22)
#endif /* (CFG_NU_OS_ARCH_PPC_COM_PPC_VARIANT == 0) */

/* Define ESAL interrupt vector IDs for this 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 <Name> comes
   directly from the hardware documentation */
#if (CFG_NU_OS_ARCH_PPC_COM_PPC_VARIANT == 0)
/* PPC32 variant ONLY */
#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

/* Define the last ESAL interrupt vector ID for this architecture + 1 */
#define         ESAL_AR_INT_VECTOR_ID_DELIMITER             (ESAL_AR_CRITICAL_INT_VECTOR_ID + 1)

#else /* CFG_NU_OS_ARCH_PPC_COM_PPC_VARIANT == 1 */
/* BookE variant ONLY */

#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

/* Define the last ESAL interrupt vector ID for this architecture + 1 */
#define         ESAL_AR_INT_VECTOR_ID_DELIMITER             (ESAL_AR_DEBUG_INT_VECTOR_ID + 1)

#endif /* (CFG_NU_OS_ARCH_PPC_COM_PPC_VARIANT == 0) */

/* Define ESAL exception vector IDs for this 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 <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 ONLY */
#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

/* Define the last ESAL exception vector ID for this architecture + 1 */
#define         ESAL_AR_EXCEPT_VECTOR_ID_DELIMITER          (ESAL_AR_RSRVD_1F00_EXCEPT_VECTOR_ID + 1)

#else /* CFG_NU_OS_ARCH_PPC_COM_PPC_VARIANT == 1 */
/* BookE variant ONLY */

#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

/* Define the last ESAL exception vector ID for this architecture + 1 */
#define         ESAL_AR_EXCEPT_VECTOR_ID_DELIMITER          (ESAL_AR_IVOR63_EXCEPT_VECTOR_ID + 1)

#endif /* (CFG_NU_OS_ARCH_PPC_COM_PPC_VARIANT == 0) */

/* Define variable(s) required to save / restore architecture interrupt state.
   These variable(s) are used in conjunction with the ESAL_AR_INT_ALL_DISABLE() and
   ESAL_AR_INT_ALL_RESTORE() macros to hold any data that must be preserved in
   order to allow these macros to function correctly. */
#define         ESAL_AR_INT_CONTROL_VARS                    UINT32 esal_tmp_val;

/* This macro locks out interrupts and saves the current
   architecture status register / state register to the specified
   address.  This function does not attempt to mask any bits in
   the return register value and can be used as a quick method
   to guard a critical section.
   NOTE:  This macro is used in conjunction with ESAL_AR_INT_ALL_RESTORE
          defined below and ESAL_AR_INT_CONTROL_VARS defined above. */
#define         ESAL_AR_INT_ALL_DISABLE()                                           \
                {                                                                   \
                    NU_REG UINT32 temp;                                           \
                                                                                    \
                    /* Read-modify-write MSR to disable all interrupts */           \
                    ESAL_TS_RTE_MSR_READ(&esal_tmp_val);                            \
                    temp = esal_tmp_val & ~ESAL_AR_INTERRUPTS_ENABLE_BITS;          \
                    ESAL_TS_RTE_MSR_WRITE(temp);                                    \
                }

/* This macro restores the architecture status / state register
   used to lockout interrupts to the value provided.  The
   intent of this function is to be a fast mechanism to restore the
   interrupt level at the end of a critical section to its
   original level.
   NOTE:  This macro is used in conjunction with ESAL_AR_INT_ALL_DISABLE
          and ESAL_AR_INT_CONTROL_VARS defined above. */
#define         ESAL_AR_INT_ALL_RESTORE()                                           \
                {                                                                   \
                    /* Restore MSR to pre-disable value */                          \
                    ESAL_TS_RTE_MSR_WRITE(esal_tmp_val);                            \
                }

/* This macro locks-out interrupts but doesn't save the status
   register / control register value. */
#define         ESAL_AR_INT_FAST_ALL_DISABLE()                                      \
                {                                                                   \
                    UINT32 temp;                                                    \
                                                                                    \
                    /* Read-modify-write MSR to disable all interrupts */           \
                    ESAL_TS_RTE_MSR_READ(&temp);                                    \
                    temp &= ~ESAL_AR_INTERRUPTS_ENABLE_BITS;                        \
                    ESAL_TS_RTE_MSR_WRITE(temp);                                    \
                }

/* This macro unlocks interrupts but doesn't save the status
   register / control register value. */
#define         ESAL_AR_INT_FAST_ALL_ENABLE()                                       \
                {                                                                   \
                    UINT32   temp;                                                  \
                                                                                    \
                    /* Read-modify-write MSR to enable all interrupts */            \
                    ESAL_TS_RTE_MSR_READ(&temp);                                    \
                    temp |= ESAL_AR_INTERRUPTS_ENABLE_BITS;                         \
                    ESAL_TS_RTE_MSR_WRITE(temp);                                    \
                }

/* This macro sets the interrupt related bits in the status register / control
   register to the specified value. */
#define         ESAL_AR_INT_BITS_SET(set_bits)                                      \
                {                                                                   \
                    UINT32 temp;                                                    \
                                                                                    \
                    /* Read MSR into temp */                                        \
                    ESAL_TS_RTE_MSR_READ(&temp);                                    \
                                                                                    \
                    /* Clear current interrupt bits and set new ones */             \
                    temp &= ~ESAL_AR_INTERRUPTS_ENABLE_BITS;                        \
                    temp |= set_bits;                                               \
                                                                                    \
                    /* Write new MSR */                                             \
                    ESAL_TS_RTE_MSR_WRITE(temp);                                    \
                }

/* This macro gets the interrupt related bits from the status register / control
   register. */
#define         ESAL_AR_INT_BITS_GET(get_bits_ptr)                                  \
                {                                                                   \
                    UINT32 temp;                                                    \
                                                                                    \
                    /* Read MSR into temp */                                        \
                    ESAL_TS_RTE_MSR_READ(&temp);                                    \
                                                                                    \
                    /* Return just interrupt bits */                                \
                    *get_bits_ptr = (temp & (UINT16)ESAL_AR_INTERRUPTS_ENABLE_BITS);\
                }
                


/* Define any architecture specific, OS timer initialization constants,
   register addresses, etc here */
   
#if (ESAL_AR_OS_TIMER_USED == NU_TRUE)

/* Decrementer Register (SPR22) */
#define         ESAL_AR_TMR_DEC_REG                     22

/* Decrementer Auto-reload Register (SPR54) */
#define         ESAL_AR_TMR_DECAR_REG                   54

/* Timer Status Register (SPR336) */
#define         ESAL_AR_TMR_TSR_REG                     336

/* Decrementer Interrupt Status bit */
#define         ESAL_AR_TMR_TSR_DIS_BIT                 ESAL_GE_MEM_32BIT_SET(4)

/* Define the architecture OS timer type (count-down or count-up) */
#define         ESAL_AR_TMR_OS_COUNT_DIR                ESAL_COUNT_DOWN

/* Define for the architecture OS timer interrupt vector */
#define         ESAL_AR_TMR_OS_VECTOR                   ESAL_AR_DECREMENTER_INT_VECTOR_ID

/* Define a macro to read the architecture OS timer hardware count.  The
   resultant size of the count must be 32-bits, regardless of the actual
   size of the timer used (8-bit, 16-bit, 32-bit, etc). */
#define         ESAL_AR_TMR_OS_COUNT_READ()             ESAL_TS_RTE_DEC_READ()

/* Define the EOI logic for the architecture OS timer */
#if (CFG_NU_OS_ARCH_PPC_COM_PPC_VARIANT == 0)
/* PPC32 variant ONLY */
#define         ESAL_AR_TMR_OS_TIMER_EOI(vector)                                                \
                {                                                                               \
                    UINT32  timer_count;                                                        \
                                                                                                \
                    /* Get the timer count from the vector ID data structure */                 \
                    timer_count = (UINT32)ESAL_GE_EXCEPT_VECTOR_DATA_GET(vector);               \
                                                                                                \
                    /* Resetting the decrementer count clears the interrupt */                  \
                    ESAL_TS_RTE_SPR_WRITE(ESAL_TS_RTE_DEC, timer_count);                        \
                }

#else /* CFG_NU_OS_ARCH_PPC_COM_PPC_VARIANT == 1 */
/* BookE variant ONLY */
#define         ESAL_AR_TMR_OS_TIMER_EOI(vector)                                                \
                {                                                                               \
                    ESAL_TS_RTE_SPR_WRITE(ESAL_AR_TMR_TSR_REG, ESAL_AR_TMR_TSR_DIS_BIT);        \
                }
#endif /* (CFG_NU_OS_ARCH_PPC_COM_PPC_VARIANT == 0) */

/* Define generic macro for OS timer pending */
#define         ESAL_AR_TMR_PENDING()                               \
({                                                                  \
    UINT32  _ret_val;                                               \
    ESAL_TS_RTE_SPR_READ(ESAL_AR_TMR_TSR_REG, &_ret_val);           \
    _ret_val &= ESAL_AR_TMR_TSR_DIS_BIT;                            \
    _ret_val;                                                       \
})

/* Define for setting the processor tick value */
#define         ESAL_AR_TMR_TICK_VALUE_SET(value)       ESAL_TS_RTE_DEC_WRITE(value)

/* Define for adjusting the processor tick value */
#define         ESAL_AR_TMR_TICK_ADJUST_SET(adjustment)              \
({                                                                   \
    UINT32 _temp_ticks = ESAL_TS_RTE_DEC_READ();                     \
    ESAL_TS_RTE_DEC_WRITE((_temp_ticks + adjustment));               \
})

/* Define method for which PMS will work with the counter.  In most cases this will
   match the OS timer direction.  On some rarer cases it may be needed to differ, such
   cases include timers that don't start at 0 but count up. */
#define ESAL_AR_TMR_PMS_COUNT_METHOD        ESAL_AR_TMR_OS_COUNT_DIR

/*
 * ESAL_AR_TMR_PMS_IS_TIMER_INT_PENDING() checks whether a hardware tick timer interrupt is
 * pending at this time.
 * It is used to check if a race condition occurred, CPU woke up due to
 * other HW interrupt but a tick occurred between the interrupt and any
 * hardware tick counter sampling.
 */
#define ESAL_AR_TMR_PMS_IS_TIMER_INT_PENDING()  ESAL_GE_TMR_OS_PENDING()

/*
 * ESAL_AR_TMR_PMS_SET_HW_TICK_INTERVAL(interval) sets the hardware tick timer interval
 * It is used and required only for UP counting hardware timer counters.
 */
#if(ESAL_AR_TMR_PMS_COUNT_METHOD == ESAL_COUNT_UP)
#define ESAL_AR_TMR_PMS_SET_HW_TICK_INTERVAL(interval)
#endif

/*
 * ESAL_AR_TMR_PMS_GET_HW_TICK_CNT_VALUE() reads the current hardware tick timer counter value
 * This typically can be left mapped to ESAL_GE_TMR_OS_COUNT_READ
 */
#define ESAL_AR_TMR_PMS_GET_HW_TICK_CNT_VALUE()         ESAL_GE_TMR_OS_COUNT_READ()

/*
 * ESAL_AR_TMR_PMS_ADJUST_HW_TICK_VALUE(adjustment) adjust the current hardware tick timer value
 * by the adjustment value. POSITIVE OR NEGATIVE adjustments must be handled.
 * ESAL_AR_TMR_PMS_ADJUST_HW_TICK_VALUE is used only with DOWN counting hardware timer counters
 * and is the preferred method for tick suppression (vs. ESAL_PMS_SET_HW_TICK_VALUE)
 */
#if(ESAL_AR_TMR_PMS_COUNT_METHOD == ESAL_COUNT_DOWN)
#define ESAL_AR_TMR_PMS_ADJUST_HW_TICK_VALUE(adjustment) ESAL_AR_TMR_TICK_ADJUST_SET(adjustment)
#endif

/* This macro sets the current hardware tick timer counter value
 * It is used and required only for DOWN counting hardware timer counters
 * and only if ESAL_PR_TMR_PMS_ADJUST_HW_TICK_VALUE is not defined.
 * ESAL_PR_TMR_PMS_SET_HW_TICK_VALUE should only be used if ESAL_PMS_ADJUST_HW_TICK function
 * in unachievable because it potentially introduces small tick drift
 * when the software does read-modify-write adjustments to the counter value.
 */
#if(ESAL_AR_TMR_PMS_COUNT_METHOD == ESAL_COUNT_DOWN)
#ifndef ESAL_AR_TMR_PMS_ADJUST_HW_TICK_VALUE
#define ESAL_AR_TMR_PMS_SET_HW_TICK_VALUE(value)        ESAL_AR_TMR_TICK_VALUE_SET(value)
#endif
#endif

#endif  /* ESAL_AR_OS_TIMER_USED == NU_TRUE */

#endif  /* PPC_DEFS_H */

