/***********************************************************************
*
*             Copyright 2012 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
*
*       tensilica_defs.h
*
*   DESCRIPTION
*
*       This file contains all definitions, structures, etc for the
*       Tensilica toolset
*
*   DATA STRUCTURES
*
*       None
*
*   DEPENDENCIES
*
*       None
*
***********************************************************************/

#ifndef         TENSILICA_DEFS_H
#define         TENSILICA_DEFS_H

#include <xtensa/config/core.h>

/* Define required for RTL support. */
#ifndef         ESAL_TS_RTL_SUPPORT
#define         ESAL_TS_RTL_SUPPORT                     NU_TRUE
#endif

/* Define required stack pointer alignment for the given toolset.*/
#define         ESAL_TS_REQ_STK_ALIGNMENT               16

/* Defines if toolset supports 64-bit data types (long long) */
#define         ESAL_TS_64BIT_SUPPORT                   NU_TRUE

/* Defines, in bytes, toolset minimum required alignment for structures */
#define         ESAL_TS_STRUCT_ALIGNMENT                4

/* Size, in bits, of integers for the given toolset / architecture */
#define         ESAL_TS_INTEGER_SIZE                    32

/* Size, in bits, of code pointer for the given toolset / architecture */
#define         ESAL_TS_CODE_PTR_SIZE                   32

/* Size, in bits, of data pointer for the given toolset / architecture */
#define         ESAL_TS_DATA_PTR_SIZE                   32

/* Defines used to enforce alignment of data structure members (if necessary). */


/* Define tool specific type for HUGE and FAR data pointers - these will usually
   be defined to nothing.  Some 16-bit architectures may require these
   to be defined differently to access data across memory pages */
#define         ESAL_TS_HUGE_PTR_TYPE
#define         ESAL_TS_FAR_PTR_TYPE

/* Define if position-independent code / data (PIC/PID) support (if available)
   is enabled.
   NOTE:  This may be required to be set to NU_TRUE when utilizing any
          OS components requiring position-independent code / data */
#define         ESAL_TS_PIC_PID_SUPPORT                 NU_FALSE

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

/* Xtensa HAL cache manipulation defines. */
#define ESAL_TS_RTE_DCACHE_ALL_UNLOCK               xthal_dcache_all_unlock
#define ESAL_TS_RTE_ICACHE_ALL_UNLOCK               xthal_icache_all_unlock
#define ESAL_TS_RTE_DCACHE_ALL_INVALIDATE           xthal_dcache_all_invalidate
#define ESAL_TS_RTE_ICACHE_ALL_INVALIDATE           xthal_icache_all_invalidate



/* This macro returns the highest set bit. */
#define         ESAL_TS_RTE_HIGHEST_SET_BIT(VALUE, BITNUM)                                \
{                                                                                         \
    __asm__ __volatile__                                                                  \
    (                                                                                     \
        "nsau    %0, %1 \n\t"                                                             \
        "neg     %0, %0 \n\t"                                                             \
        "addi    %0, %0, 31 \n\t"                                                         \
        : "=a" (BITNUM): "a" (VALUE)                                                      \
    );                                                                                    \
}

/* This macro reads the stack pointer. */
#define         ESAL_TS_RTE_SP_READ()                                                     \
({                                                                                        \
    UINT32 * stack_ptr;                                                                   \
    __asm__ __volatile__                                                                  \
    (                                                                                     \
        "or    %0, a1,a1 "                                                                \
        : "=a" (stack_ptr)                                                                \
    );                                                                                    \
    stack_ptr;                                                                            \
})

/* This macro sets the stack pointer. */
#if XCHAL_HAVE_WINDOW
#define         ESAL_TS_RTE_SP_WRITE(stack_ptr)                                           \
{                                                                                         \
    __asm__ __volatile__                                                                  \
    (                                                                                     \
        "movi    a10, xthal_window_spill \n\t"                                            \
        "callx4  a10    \n\t"                                                             \
        "movsp sp, %0    \n\t"                                                            \
        :: "a" (stack_ptr)   :"a10"                                                       \
    );                                                                                    \
}
#else
#define         ESAL_TS_RTE_SP_WRITE(stack_ptr)                                           \
{                                                                                         \
    __asm__ __volatile__                                                                  \
    (                                                                                     \
        "mov   sp, %0    \n\t"                                                            \
        :: "a" (stack_ptr)   :"a10"                                                       \
    );                                                                                    \
}
#endif

/* This macro sets region protection TLB entries */
#define         ESAL_TS_RTE_ADD_TLB_ENTRY(x,y)                                            \
{                                                                                         \
    __asm__ __volatile__                                                                  \
    (                                                                                     \
        "wdtlb    %0, %1   \n\t"                                                          \
        "witlb    %0, %1   \n\t"                                                          \
        "isync   \n\t"                                                                    \
        :: "a" (x) ,"a" (y)                                                               \
    );                                                                                    \
}

/* This macro reads CCOUNT register. */
#define         ESAL_TS_RTE_READ_CCOUNT(REG_CCOUNT)                                       \
{                                                                                         \
    __asm__ __volatile__                                                                  \
    (                                                                                     \
        "rsr    %0, 234"                                                                  \
        : "=a" (REG_CCOUNT)                                                               \
    );                                                                                    \
}

/* This macro reads CCOMPARE register. */
#define         ESAL_TS_RTE_READ_CCOMPARE(REG_CCOMPARE)                                   \
{                                                                                         \
    __asm__ __volatile__                                                                  \
    (                                                                                     \
        "rsr    %0, %1"                                                                   \
        : "=a" (REG_CCOMPARE): "i" (240 + ESAL_XCHAL_SELECTED_TIMER)                      \
    );                                                                                    \
}

/* This macro writes to CCOMPARE register. */
#define         ESAL_TS_RTE_WRITE_CCOMPARE(REG_CCOMPARE)                                  \
{                                                                                         \
    __asm__ __volatile__                                                                  \
    (                                                                                     \
        "wsr    %0, %1 \n\t"                                                              \
        "isync\n\t"                                                                       \
        :: "a" (REG_CCOMPARE), "i" (240 + ESAL_XCHAL_SELECTED_TIMER)                      \
    );                                                                                    \
}

/* This macro reads INTENABLE register. */
#define         ESAL_TS_RTE_READ_INTENABLE(REG_INTENABLE)                                 \
{                                                                                         \
    __asm__ __volatile__                                                                  \
    (                                                                                     \
        "rsr    %0, 228 "                                                                 \
        :"=a" (REG_INTENABLE)                                                             \
    );                                                                                    \
}

/* This macro writes to INTENABLE register. */
#define         ESAL_TS_RTE_WRITE_INTENABLE(REG_INTENABLE)                                \
{                                                                                         \
    __asm__ __volatile__                                                                  \
    (                                                                                     \
        "wsr    %0, 228"                                                                  \
        :: "a" (REG_INTENABLE)                                                            \
    );                                                                                    \
}

/* This macro reads INTERRUPT register. */
#define         ESAL_TS_RTE_READ_INTERRUPT(VALUE)                                         \
{                                                                                         \
    __asm__ __volatile__                                                                  \
    (                                                                                     \
        "rsr %0, 226": "=a" (VALUE)                                                       \
    );                                                                                    \
}

/* This macro writes to INTCLEAR register. */
#define         ESAL_TS_RTE_WRITE_INTCLEAR(VALUE)                                         \
{                                                                                         \
    __asm__ __volatile__                                                                  \
    (                                                                                     \
       "wsr %0, 227"                                                                      \
       :: "a" (VALUE)                                                                     \
    );                                                                                    \
}

/* This macro reads from PS register. */
#define         ESAL_TS_RTE_READ_PS(VALUE)                                                \
{                                                                                         \
    __asm__ __volatile__                                                                  \
    (                                                                                     \
        "rsr %0, 230": "=a" (VALUE)                                                       \
    );                                                                                    \
}

/* This macro writes to PS register. */
#define         ESAL_TS_RTE_WRITE_PS(VALUE)                                               \
{                                                                                         \
    __asm__ __volatile__                                                                  \
    (                                                                                     \
        "wsr %0, 230":: "a" (VALUE)                                                       \
    );                                                                                    \
}

/* This macro sets interrupt level to the specified value. */
#define         ESAL_TS_RTE_SET_INT_LEVEL(VALUE)                                          \
{                                                                                         \
    __asm__ __volatile__                                                                  \
    (                                                                                     \
        "rsil a15, " ESAL_TS_RTE_QUOTES(VALUE)                                            \
         :: :"a15"                                                                        \
    );                                                                                    \
}

#define         ESAL_TS_RTE_SYNC()                                                        \
{                                                                                         \
    __asm__ __volatile__                                                                  \
    (                                                                                     \
        "rsync"                                                                       \
    );                                                                                    \
}

/* Define stack frame size for the toolset / architecture supported. 
 * NOTE : Size must be a 16-byte multiple to keep stacks 16-byte aligned */
#define         ESAL_TS_STK_SIZE            (((0x20 + XCHAL_NCP_SA_SIZE) + 15) & (~0xF))

/* Define xtensa stack frame offsets */
#define         ESAL_TS_STK_OFFSET_TYPE           0x0
#define         ESAL_TS_STK_OFFSET_A0             0x4
#define         ESAL_TS_STK_OFFSET_A12            0x8
#define         ESAL_TS_STK_OFFSET_A13            0xC
#define         ESAL_TS_STK_OFFSET_A14            0x10
#define         ESAL_TS_STK_OFFSET_A15            0x14
#define         ESAL_TS_STK_OFFSET_EXTRA          0x20    /* Extra register save base offset */

#define ESAL_TS_STK_SAVE_AREA_SIZE   16
#define ESAL_TS_STK_CALL4_HEADER_SIZE   16

/* Define stack frame structure for the toolset / architecture supported. */
typedef struct  ESAL_TS_STK_STRUCT
{
    UINT32        stack_type;
    UINT32        rtn_address;
    UINT32        a12;
    UINT32        a13;
    UINT32        a14;
    UINT32        a15;
                  /* To force 16-byte alignment of xthal_extra field */
    UINT32        alignment_padding_1[2];
    UINT8         xthal_extra[XCHAL_NCP_SA_SIZE];
#if ((XCHAL_NCP_SA_SIZE % 16) > 0)
                  /* To force 16-byte alignment of the stack frame */
    UINT8         alignment_padding_2[(16-(XCHAL_NCP_SA_SIZE % 16))];
    UINT32        align_offset[4];
#endif

} ESAL_TS_STK;

/* This macro marks a symbol declaration as weakly linked */
#define         ESAL_TS_WEAK_REF(decl) decl __attribute((weak))

/* This macro marks a symbol definition as weakly linked */
#define         ESAL_TS_WEAK_DEF(decl) decl

/* This macro returns the passed value */
#define         ESAL_TS_NO_RETURN(return_val) return(return_val)

/* This macro generates deprecation warnings */
#define         ESAL_TS_RTE_DEPRECATED __attribute__((deprecated))

/* This macro places a compiler memory barrier to ensure read / write commands
 * cannot be re-ordered around it */
#define         ESAL_TS_RTE_COMPILE_MEM_BARRIER()   asm volatile("" ::: "memory")

#endif  /* TENSILICA_DEFS_H */

