mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 10:49:33 +00:00
![Adam Buchbinder](/assets/img/avatar_default.png)
Signed-off-by: Adam Buchbinder <adam.buchbinder@gmail.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
1420 lines
62 KiB
C
1420 lines
62 KiB
C
/*
|
|
* asm/tbx.h
|
|
*
|
|
* Copyright (C) 2000-2012 Imagination Technologies.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it under
|
|
* the terms of the GNU General Public License version 2 as published by the
|
|
* Free Software Foundation.
|
|
*
|
|
* Thread binary interface header
|
|
*/
|
|
|
|
#ifndef _ASM_METAG_TBX_H_
|
|
#define _ASM_METAG_TBX_H_
|
|
|
|
/* for CACHEW_* values */
|
|
#include <asm/metag_isa.h>
|
|
/* for LINSYSEVENT_* addresses */
|
|
#include <asm/metag_mem.h>
|
|
|
|
#ifdef TBI_1_4
|
|
#ifndef TBI_MUTEXES_1_4
|
|
#define TBI_MUTEXES_1_4
|
|
#endif
|
|
#ifndef TBI_SEMAPHORES_1_4
|
|
#define TBI_SEMAPHORES_1_4
|
|
#endif
|
|
#ifndef TBI_ASYNC_SWITCH_1_4
|
|
#define TBI_ASYNC_SWITCH_1_4
|
|
#endif
|
|
#ifndef TBI_FASTINT_1_4
|
|
#define TBI_FASTINT_1_4
|
|
#endif
|
|
#endif
|
|
|
|
|
|
/* Id values in the TBI system describe a segment using an arbitrary
|
|
integer value and flags in the bottom 8 bits, the SIGPOLL value is
|
|
used in cases where control over blocking or polling behaviour is
|
|
needed. */
|
|
#define TBID_SIGPOLL_BIT 0x02 /* Set bit in an Id value to poll vs block */
|
|
/* Extended segment identifiers use strings in the string table */
|
|
#define TBID_IS_SEGSTR( Id ) (((Id) & (TBID_SEGTYPE_BITS>>1)) == 0)
|
|
|
|
/* Segment identifiers contain the following related bit-fields */
|
|
#define TBID_SEGTYPE_BITS 0x0F /* One of the predefined segment types */
|
|
#define TBID_SEGTYPE_S 0
|
|
#define TBID_SEGSCOPE_BITS 0x30 /* Indicates the scope of the segment */
|
|
#define TBID_SEGSCOPE_S 4
|
|
#define TBID_SEGGADDR_BITS 0xC0 /* Indicates access possible via pGAddr */
|
|
#define TBID_SEGGADDR_S 6
|
|
|
|
/* Segments of memory can only really contain a few types of data */
|
|
#define TBID_SEGTYPE_TEXT 0x02 /* Code segment */
|
|
#define TBID_SEGTYPE_DATA 0x04 /* Data segment */
|
|
#define TBID_SEGTYPE_STACK 0x06 /* Stack segment */
|
|
#define TBID_SEGTYPE_HEAP 0x0A /* Heap segment */
|
|
#define TBID_SEGTYPE_ROOT 0x0C /* Root block segments */
|
|
#define TBID_SEGTYPE_STRING 0x0E /* String table segment */
|
|
|
|
/* Segments have one of three possible scopes */
|
|
#define TBID_SEGSCOPE_INIT 0 /* Temporary area for initialisation phase */
|
|
#define TBID_SEGSCOPE_LOCAL 1 /* Private to this thread */
|
|
#define TBID_SEGSCOPE_GLOBAL 2 /* Shared globally throughout the system */
|
|
#define TBID_SEGSCOPE_SHARED 3 /* Limited sharing between local/global */
|
|
|
|
/* For segment specifier a further field in two of the remaining bits
|
|
indicates the usefulness of the pGAddr field in the segment descriptor
|
|
descriptor. */
|
|
#define TBID_SEGGADDR_NULL 0 /* pGAddr is NULL -> SEGSCOPE_(LOCAL|INIT) */
|
|
#define TBID_SEGGADDR_READ 1 /* Only read via pGAddr */
|
|
#define TBID_SEGGADDR_WRITE 2 /* Full access via pGAddr */
|
|
#define TBID_SEGGADDR_EXEC 3 /* Only execute via pGAddr */
|
|
|
|
/* The following values are common to both segment and signal Id value and
|
|
live in the top 8 bits of the Id values. */
|
|
|
|
/* The ISTAT bit indicates if segments are related to interrupt vs
|
|
background level interfaces a thread can still handle all triggers at
|
|
either level, but can also split these up if it wants to. */
|
|
#define TBID_ISTAT_BIT 0x01000000
|
|
#define TBID_ISTAT_S 24
|
|
|
|
/* Privilege needed to access a segment is indicated by the next bit.
|
|
|
|
This bit is set to mirror the current privilege level when starting a
|
|
search for a segment - setting it yourself toggles the automatically
|
|
generated state which is only useful to emulate unprivileged behaviour
|
|
or access unprivileged areas of memory while at privileged level. */
|
|
#define TBID_PSTAT_BIT 0x02000000
|
|
#define TBID_PSTAT_S 25
|
|
|
|
/* The top six bits of a signal/segment specifier identifies a thread within
|
|
the system. This represents a segments owner. */
|
|
#define TBID_THREAD_BITS 0xFC000000
|
|
#define TBID_THREAD_S 26
|
|
|
|
/* Special thread id values */
|
|
#define TBID_THREAD_NULL (-32) /* Never matches any thread/segment id used */
|
|
#define TBID_THREAD_GLOBAL (-31) /* Things global to all threads */
|
|
#define TBID_THREAD_HOST ( -1) /* Host interface */
|
|
#define TBID_THREAD_EXTIO (TBID_THREAD_HOST) /* Host based ExtIO i/f */
|
|
|
|
/* Virtual Id's are used for external thread interface structures or the
|
|
above special Id's */
|
|
#define TBID_IS_VIRTTHREAD( Id ) ((Id) < 0)
|
|
|
|
/* Real Id's are used for actual hardware threads that are local */
|
|
#define TBID_IS_REALTHREAD( Id ) ((Id) >= 0)
|
|
|
|
/* Generate a segment Id given Thread, Scope, and Type */
|
|
#define TBID_SEG( Thread, Scope, Type ) (\
|
|
((Thread)<<TBID_THREAD_S) + ((Scope)<<TBID_SEGSCOPE_S) + (Type))
|
|
|
|
/* Generate a signal Id given Thread and SigNum */
|
|
#define TBID_SIG( Thread, SigNum ) (\
|
|
((Thread)<<TBID_THREAD_S) + ((SigNum)<<TBID_SIGNUM_S) + TBID_SIGNAL_BIT)
|
|
|
|
/* Generate an Id that solely represents a thread - useful for cache ops */
|
|
#define TBID_THD( Thread ) ((Thread)<<TBID_THREAD_S)
|
|
#define TBID_THD_NULL ((TBID_THREAD_NULL) <<TBID_THREAD_S)
|
|
#define TBID_THD_GLOBAL ((TBID_THREAD_GLOBAL)<<TBID_THREAD_S)
|
|
|
|
/* Common exception handler (see TBID_SIGNUM_XXF below) receives hardware
|
|
generated fault codes TBIXXF_SIGNUM_xxF in it's SigNum parameter */
|
|
#define TBIXXF_SIGNUM_IIF 0x01 /* General instruction fault */
|
|
#define TBIXXF_SIGNUM_PGF 0x02 /* Privilege general fault */
|
|
#define TBIXXF_SIGNUM_DHF 0x03 /* Data access watchpoint HIT */
|
|
#define TBIXXF_SIGNUM_IGF 0x05 /* Code fetch general read failure */
|
|
#define TBIXXF_SIGNUM_DGF 0x07 /* Data access general read/write fault */
|
|
#define TBIXXF_SIGNUM_IPF 0x09 /* Code fetch page fault */
|
|
#define TBIXXF_SIGNUM_DPF 0x0B /* Data access page fault */
|
|
#define TBIXXF_SIGNUM_IHF 0x0D /* Instruction breakpoint HIT */
|
|
#define TBIXXF_SIGNUM_DWF 0x0F /* Data access read-only fault */
|
|
|
|
/* Hardware signals communicate events between processing levels within a
|
|
single thread all the _xxF cases are exceptions and are routed via a
|
|
common exception handler, _SWx are software trap events and kicks including
|
|
__TBISignal generated kicks, and finally _TRx are hardware triggers */
|
|
#define TBID_SIGNUM_SW0 0x00 /* SWITCH GROUP 0 - Per thread user */
|
|
#define TBID_SIGNUM_SW1 0x01 /* SWITCH GROUP 1 - Per thread system */
|
|
#define TBID_SIGNUM_SW2 0x02 /* SWITCH GROUP 2 - Internal global request */
|
|
#define TBID_SIGNUM_SW3 0x03 /* SWITCH GROUP 3 - External global request */
|
|
#ifdef TBI_1_4
|
|
#define TBID_SIGNUM_FPE 0x04 /* Deferred exception - Any IEEE 754 exception */
|
|
#define TBID_SIGNUM_FPD 0x05 /* Deferred exception - Denormal exception */
|
|
/* Reserved 0x6 for a reserved deferred exception */
|
|
#define TBID_SIGNUM_BUS 0x07 /* Deferred exception - Bus Error */
|
|
/* Reserved 0x08-0x09 */
|
|
#else
|
|
/* Reserved 0x04-0x09 */
|
|
#endif
|
|
/* Reserved 0x0A-0x0F */
|
|
#define TBID_SIGNUM_TRT 0x10 /* Timer trigger */
|
|
#define TBID_SIGNUM_LWK 0x11 /* Low level kick */
|
|
#define TBID_SIGNUM_XXF 0x12 /* Fault handler - receives ALL _xxF sigs */
|
|
#ifdef TBI_1_4
|
|
#define TBID_SIGNUM_DFR 0x13 /* Deferred Exception handler */
|
|
#else
|
|
#define TBID_SIGNUM_FPE 0x13 /* FPE Exception handler */
|
|
#endif
|
|
/* External trigger one group 0x14 to 0x17 - per thread */
|
|
#define TBID_SIGNUM_TR1(Thread) (0x14+(Thread))
|
|
#define TBID_SIGNUM_T10 0x14
|
|
#define TBID_SIGNUM_T11 0x15
|
|
#define TBID_SIGNUM_T12 0x16
|
|
#define TBID_SIGNUM_T13 0x17
|
|
/* External trigger two group 0x18 to 0x1b - per thread */
|
|
#define TBID_SIGNUM_TR2(Thread) (0x18+(Thread))
|
|
#define TBID_SIGNUM_T20 0x18
|
|
#define TBID_SIGNUM_T21 0x19
|
|
#define TBID_SIGNUM_T22 0x1A
|
|
#define TBID_SIGNUM_T23 0x1B
|
|
#define TBID_SIGNUM_TR3 0x1C /* External trigger N-4 (global) */
|
|
#define TBID_SIGNUM_TR4 0x1D /* External trigger N-3 (global) */
|
|
#define TBID_SIGNUM_TR5 0x1E /* External trigger N-2 (global) */
|
|
#define TBID_SIGNUM_TR6 0x1F /* External trigger N-1 (global) */
|
|
#define TBID_SIGNUM_MAX 0x1F
|
|
|
|
/* Return the trigger register(TXMASK[I]/TXSTAT[I]) bits related to
|
|
each hardware signal, sometimes this is a many-to-one relationship. */
|
|
#define TBI_TRIG_BIT(SigNum) (\
|
|
((SigNum) >= TBID_SIGNUM_TRT) ? 1<<((SigNum)-TBID_SIGNUM_TRT) :\
|
|
((SigNum) == TBID_SIGNUM_LWK) ? \
|
|
TXSTAT_KICK_BIT : TXSTATI_BGNDHALT_BIT )
|
|
|
|
/* Return the hardware trigger vector number for entries in the
|
|
HWVEC0EXT table that will generate the required internal trigger. */
|
|
#define TBI_TRIG_VEC(SigNum) (\
|
|
((SigNum) >= TBID_SIGNUM_T10) ? ((SigNum)-TBID_SIGNUM_TRT) : -1)
|
|
|
|
/* Default trigger masks for each thread at background/interrupt level */
|
|
#define TBI_TRIGS_INIT( Thread ) (\
|
|
TXSTAT_KICK_BIT + TBI_TRIG_BIT(TBID_SIGNUM_TR1(Thread)) )
|
|
#define TBI_INTS_INIT( Thread ) (\
|
|
TXSTAT_KICK_BIT + TXSTATI_BGNDHALT_BIT \
|
|
+ TBI_TRIG_BIT(TBID_SIGNUM_TR2(Thread)) )
|
|
|
|
#ifndef __ASSEMBLY__
|
|
/* A spin-lock location is a zero-initialised location in memory */
|
|
typedef volatile int TBISPIN, *PTBISPIN;
|
|
|
|
/* A kick location is a hardware location you can write to
|
|
* in order to cause a kick
|
|
*/
|
|
typedef volatile int *PTBIKICK;
|
|
|
|
#if defined(METAC_1_0) || defined(METAC_1_1)
|
|
/* Macro to perform a kick */
|
|
#define TBI_KICK( pKick ) do { pKick[0] = 1; } while (0)
|
|
#else
|
|
/* #define METAG_LIN_VALUES before including machine.h if required */
|
|
#ifdef LINSYSEVENT_WR_COMBINE_FLUSH
|
|
/* Macro to perform a kick - write combiners must be flushed */
|
|
#define TBI_KICK( pKick ) do {\
|
|
volatile int *pFlush = (volatile int *) LINSYSEVENT_WR_COMBINE_FLUSH; \
|
|
pFlush[0] = 0; \
|
|
pKick[0] = 1; } while (0)
|
|
#endif
|
|
#endif /* if defined(METAC_1_0) || defined(METAC_1_1) */
|
|
#endif /* ifndef __ASSEMBLY__ */
|
|
|
|
#ifndef __ASSEMBLY__
|
|
/* 64-bit dual unit state value */
|
|
typedef struct _tbidual_tag_ {
|
|
/* 32-bit value from a pair of registers in data or address units */
|
|
int U0, U1;
|
|
} TBIDUAL, *PTBIDUAL;
|
|
#endif /* ifndef __ASSEMBLY__ */
|
|
|
|
/* Byte offsets of fields within TBIDUAL */
|
|
#define TBIDUAL_U0 (0)
|
|
#define TBIDUAL_U1 (4)
|
|
|
|
#define TBIDUAL_BYTES (8)
|
|
|
|
#define TBICTX_CRIT_BIT 0x0001 /* ASync state saved in TBICTX */
|
|
#define TBICTX_SOFT_BIT 0x0002 /* Sync state saved in TBICTX (other bits 0) */
|
|
#ifdef TBI_FASTINT_1_4
|
|
#define TBICTX_FINT_BIT 0x0004 /* Using Fast Interrupts */
|
|
#endif
|
|
#define TBICTX_FPAC_BIT 0x0010 /* FPU state in TBICTX, FPU active on entry */
|
|
#define TBICTX_XMCC_BIT 0x0020 /* Bit to identify a MECC task */
|
|
#define TBICTX_CBUF_BIT 0x0040 /* Hardware catch buffer flag from TXSTATUS */
|
|
#define TBICTX_CBRP_BIT 0x0080 /* Read pipeline dirty from TXDIVTIME */
|
|
#define TBICTX_XDX8_BIT 0x0100 /* Saved DX.8 to DX.15 too */
|
|
#define TBICTX_XAXX_BIT 0x0200 /* Save remaining AX registers to AX.7 */
|
|
#define TBICTX_XHL2_BIT 0x0400 /* Saved hardware loop registers too */
|
|
#define TBICTX_XTDP_BIT 0x0800 /* Saved DSP registers too */
|
|
#define TBICTX_XEXT_BIT 0x1000 /* Set if TBICTX.Ext.Ctx contains extended
|
|
state save area, otherwise TBICTX.Ext.AX2
|
|
just holds normal A0.2 and A1.2 states */
|
|
#define TBICTX_WAIT_BIT 0x2000 /* Causes wait for trigger - sticky toggle */
|
|
#define TBICTX_XCBF_BIT 0x4000 /* Catch buffer or RD extracted into TBICTX */
|
|
#define TBICTX_PRIV_BIT 0x8000 /* Set if system uses 'privileged' model */
|
|
|
|
#ifdef METAC_1_0
|
|
#define TBICTX_XAX3_BIT 0x0200 /* Saved AX.5 to AX.7 for XAXX */
|
|
#define TBICTX_AX_REGS 5 /* Ax.0 to Ax.4 are core GP regs on CHORUS */
|
|
#else
|
|
#define TBICTX_XAX4_BIT 0x0200 /* Saved AX.4 to AX.7 for XAXX */
|
|
#define TBICTX_AX_REGS 4 /* Default is Ax.0 to Ax.3 */
|
|
#endif
|
|
|
|
#ifdef TBI_1_4
|
|
#define TBICTX_CFGFPU_FX16_BIT 0x00010000 /* Save FX.8 to FX.15 too */
|
|
|
|
/* The METAC_CORE_ID_CONFIG field indicates omitted DSP resources */
|
|
#define METAC_COREID_CFGXCTX_MASK( Value ) (\
|
|
( (((Value & METAC_COREID_CFGDSP_BITS)>> \
|
|
METAC_COREID_CFGDSP_S ) == METAC_COREID_CFGDSP_MIN) ? \
|
|
~(TBICTX_XHL2_BIT+TBICTX_XTDP_BIT+ \
|
|
TBICTX_XAXX_BIT+TBICTX_XDX8_BIT ) : ~0U ) )
|
|
#endif
|
|
|
|
/* Extended context state provides a standardised method for registering the
|
|
arguments required by __TBICtxSave to save the additional register states
|
|
currently in use by non general purpose code. The state of the __TBIExtCtx
|
|
variable in the static space of the thread forms an extension of the base
|
|
context of the thread.
|
|
|
|
If ( __TBIExtCtx.Ctx.SaveMask == 0 ) then pExt is assumed to be NULL and
|
|
the empty state of __TBIExtCtx is represented by the fact that
|
|
TBICTX.SaveMask does not have the bit TBICTX_XEXT_BIT set.
|
|
|
|
If ( __TBIExtCtx.Ctx.SaveMask != 0 ) then pExt should point at a suitably
|
|
sized extended context save area (usually at the end of the stack space
|
|
allocated by the current routine). This space should allow for the
|
|
displaced state of A0.2 and A1.2 to be saved along with the other extended
|
|
states indicated via __TBIExtCtx.Ctx.SaveMask. */
|
|
#ifndef __ASSEMBLY__
|
|
typedef union _tbiextctx_tag_ {
|
|
long long Val;
|
|
TBIDUAL AX2;
|
|
struct _tbiextctxext_tag {
|
|
#ifdef TBI_1_4
|
|
short DspramSizes; /* DSPRAM sizes. Encoding varies between
|
|
TBICtxAlloc and the ECH scheme. */
|
|
#else
|
|
short Reserved0;
|
|
#endif
|
|
short SaveMask; /* Flag bits for state saved */
|
|
PTBIDUAL pExt; /* AX[2] state saved first plus Xxxx state */
|
|
|
|
} Ctx;
|
|
|
|
} TBIEXTCTX, *PTBIEXTCTX;
|
|
|
|
/* Automatic registration of extended context save for __TBINestInts */
|
|
extern TBIEXTCTX __TBIExtCtx;
|
|
#endif /* ifndef __ASSEMBLY__ */
|
|
|
|
/* Byte offsets of fields within TBIEXTCTX */
|
|
#define TBIEXTCTX_AX2 (0)
|
|
#define TBIEXTCTX_Ctx (0)
|
|
#define TBIEXTCTX_Ctx_SaveMask (TBIEXTCTX_Ctx + 2)
|
|
#define TBIEXTCTX_Ctx_pExt (TBIEXTCTX_Ctx + 2 + 2)
|
|
|
|
/* Extended context data size calculation constants */
|
|
#define TBICTXEXT_BYTES (8)
|
|
#define TBICTXEXTBB8_BYTES (8*8)
|
|
#define TBICTXEXTAX3_BYTES (3*8)
|
|
#define TBICTXEXTAX4_BYTES (4*8)
|
|
#ifdef METAC_1_0
|
|
#define TBICTXEXTAXX_BYTES TBICTXEXTAX3_BYTES
|
|
#else
|
|
#define TBICTXEXTAXX_BYTES TBICTXEXTAX4_BYTES
|
|
#endif
|
|
#define TBICTXEXTHL2_BYTES (3*8)
|
|
#define TBICTXEXTTDR_BYTES (27*8)
|
|
#define TBICTXEXTTDP_BYTES TBICTXEXTTDR_BYTES
|
|
|
|
#ifdef TBI_1_4
|
|
#define TBICTXEXTFX8_BYTES (4*8)
|
|
#define TBICTXEXTFPAC_BYTES (1*4 + 2*2 + 4*8)
|
|
#define TBICTXEXTFACF_BYTES (3*8)
|
|
#endif
|
|
|
|
/* Maximum flag bits to be set via the TBICTX_EXTSET macro */
|
|
#define TBICTXEXT_MAXBITS (TBICTX_XEXT_BIT| \
|
|
TBICTX_XDX8_BIT|TBICTX_XAXX_BIT|\
|
|
TBICTX_XHL2_BIT|TBICTX_XTDP_BIT )
|
|
|
|
/* Maximum size of the extended context save area for current variant */
|
|
#define TBICTXEXT_MAXBYTES (TBICTXEXT_BYTES+TBICTXEXTBB8_BYTES+\
|
|
TBICTXEXTAXX_BYTES+TBICTXEXTHL2_BYTES+\
|
|
TBICTXEXTTDP_BYTES )
|
|
|
|
#ifdef TBI_FASTINT_1_4
|
|
/* Maximum flag bits to be set via the TBICTX_EXTSET macro */
|
|
#define TBICTX2EXT_MAXBITS (TBICTX_XDX8_BIT|TBICTX_XAXX_BIT|\
|
|
TBICTX_XHL2_BIT|TBICTX_XTDP_BIT )
|
|
|
|
/* Maximum size of the extended context save area for current variant */
|
|
#define TBICTX2EXT_MAXBYTES (TBICTXEXTBB8_BYTES+TBICTXEXTAXX_BYTES\
|
|
+TBICTXEXTHL2_BYTES+TBICTXEXTTDP_BYTES )
|
|
#endif
|
|
|
|
/* Specify extended resources being used by current routine, code must be
|
|
assembler generated to utilise extended resources-
|
|
|
|
MOV D0xxx,A0StP ; Perform alloca - routine should
|
|
ADD A0StP,A0StP,#SaveSize ; setup/use A0FrP to access locals
|
|
MOVT D1xxx,#SaveMask ; TBICTX_XEXT_BIT MUST be set
|
|
SETL [A1GbP+#OG(___TBIExtCtx)],D0xxx,D1xxx
|
|
|
|
NB: OG(___TBIExtCtx) is a special case supported for SETL/GETL operations
|
|
on 64-bit sizes structures only, other accesses must be based on use
|
|
of OGA(___TBIExtCtx).
|
|
|
|
At exit of routine-
|
|
|
|
MOV D0xxx,#0 ; Clear extended context save state
|
|
MOV D1xxx,#0
|
|
SETL [A1GbP+#OG(___TBIExtCtx)],D0xxx,D1xxx
|
|
SUB A0StP,A0StP,#SaveSize ; If original A0StP required
|
|
|
|
NB: Both the setting and clearing of the whole __TBIExtCtx MUST be done
|
|
atomically in one 64-bit write operation.
|
|
|
|
For simple interrupt handling only via __TBINestInts there should be no
|
|
impact of the __TBIExtCtx system. If pre-emptive scheduling is being
|
|
performed however (assuming __TBINestInts has already been called earlier
|
|
on) then the following logic will correctly call __TBICtxSave if required
|
|
and clear out the currently selected background task-
|
|
|
|
if ( __TBIExtCtx.Ctx.SaveMask & TBICTX_XEXT_BIT )
|
|
{
|
|
/ * Store extended states in pCtx * /
|
|
State.Sig.SaveMask |= __TBIExtCtx.Ctx.SaveMask;
|
|
|
|
(void) __TBICtxSave( State, (void *) __TBIExtCtx.Ctx.pExt );
|
|
__TBIExtCtx.Val = 0;
|
|
}
|
|
|
|
and when restoring task states call __TBICtxRestore-
|
|
|
|
/ * Restore state from pCtx * /
|
|
State.Sig.pCtx = pCtx;
|
|
State.Sig.SaveMask = pCtx->SaveMask;
|
|
|
|
if ( State.Sig.SaveMask & TBICTX_XEXT_BIT )
|
|
{
|
|
/ * Restore extended states from pCtx * /
|
|
__TBIExtCtx.Val = pCtx->Ext.Val;
|
|
|
|
(void) __TBICtxRestore( State, (void *) __TBIExtCtx.Ctx.pExt );
|
|
}
|
|
|
|
*/
|
|
|
|
/* Critical thread state save area */
|
|
#ifndef __ASSEMBLY__
|
|
typedef struct _tbictx_tag_ {
|
|
/* TXSTATUS_FLAG_BITS and TXSTATUS_LSM_STEP_BITS from TXSTATUS */
|
|
short Flags;
|
|
/* Mask indicates any extended context state saved; 0 -> Never run */
|
|
short SaveMask;
|
|
/* Saved PC value */
|
|
int CurrPC;
|
|
/* Saved critical register states */
|
|
TBIDUAL DX[8];
|
|
/* Background control register states - for cores without catch buffer
|
|
base in DIVTIME the TXSTATUS bits RPVALID and RPMASK are stored with
|
|
the real state TXDIVTIME in CurrDIVTIME */
|
|
int CurrRPT, CurrBPOBITS, CurrMODE, CurrDIVTIME;
|
|
/* Saved AX register states */
|
|
TBIDUAL AX[2];
|
|
TBIEXTCTX Ext;
|
|
TBIDUAL AX3[TBICTX_AX_REGS-3];
|
|
|
|
/* Any CBUF state to be restored by a handler return must be stored here.
|
|
Other extended state can be stored anywhere - see __TBICtxSave and
|
|
__TBICtxRestore. */
|
|
|
|
} TBICTX, *PTBICTX;
|
|
|
|
#ifdef TBI_FASTINT_1_4
|
|
typedef struct _tbictx2_tag_ {
|
|
TBIDUAL AX[2]; /* AU.0, AU.1 */
|
|
TBIDUAL DX[2]; /* DU.0, DU.4 */
|
|
int CurrMODE;
|
|
int CurrRPT;
|
|
int CurrSTATUS;
|
|
void *CurrPC; /* PC in PC address space */
|
|
} TBICTX2, *PTBICTX2;
|
|
/* TBICTX2 is followed by:
|
|
* TBICTXEXTCB0 if TXSTATUS.CBMarker
|
|
* TBIDUAL * TXSTATUS.IRPCount if TXSTATUS.IRPCount > 0
|
|
* TBICTXGP if using __TBIStdRootIntHandler or __TBIStdCtxSwitchRootIntHandler
|
|
*/
|
|
|
|
typedef struct _tbictxgp_tag_ {
|
|
short DspramSizes;
|
|
short SaveMask;
|
|
void *pExt;
|
|
TBIDUAL DX[6]; /* DU.1-DU.3, DU.5-DU.7 */
|
|
TBIDUAL AX[2]; /* AU.2-AU.3 */
|
|
} TBICTXGP, *PTBICTXGP;
|
|
|
|
#define TBICTXGP_DspramSizes (0)
|
|
#define TBICTXGP_SaveMask (TBICTXGP_DspramSizes + 2)
|
|
#define TBICTXGP_MAX_BYTES (2 + 2 + 4 + 8*(6+2))
|
|
|
|
#endif
|
|
#endif /* ifndef __ASSEMBLY__ */
|
|
|
|
/* Byte offsets of fields within TBICTX */
|
|
#define TBICTX_Flags (0)
|
|
#define TBICTX_SaveMask (2)
|
|
#define TBICTX_CurrPC (4)
|
|
#define TBICTX_DX (2 + 2 + 4)
|
|
#define TBICTX_CurrRPT (2 + 2 + 4 + 8 * 8)
|
|
#define TBICTX_CurrMODE (2 + 2 + 4 + 8 * 8 + 4 + 4)
|
|
#define TBICTX_AX (2 + 2 + 4 + 8 * 8 + 4 + 4 + 4 + 4)
|
|
#define TBICTX_Ext (2 + 2 + 4 + 8 * 8 + 4 + 4 + 4 + 4 + 2 * 8)
|
|
#define TBICTX_Ext_AX2 (TBICTX_Ext + TBIEXTCTX_AX2)
|
|
#define TBICTX_Ext_AX2_U0 (TBICTX_Ext + TBIEXTCTX_AX2 + TBIDUAL_U0)
|
|
#define TBICTX_Ext_AX2_U1 (TBICTX_Ext + TBIEXTCTX_AX2 + TBIDUAL_U1)
|
|
#define TBICTX_Ext_Ctx_pExt (TBICTX_Ext + TBIEXTCTX_Ctx_pExt)
|
|
#define TBICTX_Ext_Ctx_SaveMask (TBICTX_Ext + TBIEXTCTX_Ctx_SaveMask)
|
|
|
|
#ifdef TBI_FASTINT_1_4
|
|
#define TBICTX2_BYTES (8 * 2 + 8 * 2 + 4 + 4 + 4 + 4)
|
|
#define TBICTXEXTCB0_BYTES (4 + 4 + 8)
|
|
|
|
#define TBICTX2_CRIT_MAX_BYTES (TBICTX2_BYTES + TBICTXEXTCB0_BYTES + 6 * TBIDUAL_BYTES)
|
|
#define TBI_SWITCH_NEXT_PC(PC, EXTRA) ((PC) + (EXTRA & 1) ? 8 : 4)
|
|
#endif
|
|
|
|
#ifndef __ASSEMBLY__
|
|
/* Extended thread state save areas - catch buffer state element */
|
|
typedef struct _tbictxextcb0_tag_ {
|
|
/* Flags data and address value - see METAC_CATCH_VALUES in machine.h */
|
|
unsigned long CBFlags, CBAddr;
|
|
/* 64-bit data */
|
|
TBIDUAL CBData;
|
|
|
|
} TBICTXEXTCB0, *PTBICTXEXTCB0;
|
|
|
|
/* Read pipeline state saved on later cores after single catch buffer slot */
|
|
typedef struct _tbictxextrp6_tag_ {
|
|
/* RPMask is TXSTATUS_RPMASK_BITS only, reserved is undefined */
|
|
unsigned long RPMask, Reserved0;
|
|
TBIDUAL CBData[6];
|
|
|
|
} TBICTXEXTRP6, *PTBICTXEXTRP6;
|
|
|
|
/* Extended thread state save areas - 8 DU register pairs */
|
|
typedef struct _tbictxextbb8_tag_ {
|
|
/* Remaining Data unit registers in 64-bit pairs */
|
|
TBIDUAL UX[8];
|
|
|
|
} TBICTXEXTBB8, *PTBICTXEXTBB8;
|
|
|
|
/* Extended thread state save areas - 3 AU register pairs */
|
|
typedef struct _tbictxextbb3_tag_ {
|
|
/* Remaining Address unit registers in 64-bit pairs */
|
|
TBIDUAL UX[3];
|
|
|
|
} TBICTXEXTBB3, *PTBICTXEXTBB3;
|
|
|
|
/* Extended thread state save areas - 4 AU register pairs or 4 FX pairs */
|
|
typedef struct _tbictxextbb4_tag_ {
|
|
/* Remaining Address unit or FPU registers in 64-bit pairs */
|
|
TBIDUAL UX[4];
|
|
|
|
} TBICTXEXTBB4, *PTBICTXEXTBB4;
|
|
|
|
/* Extended thread state save areas - Hardware loop states (max 2) */
|
|
typedef struct _tbictxexthl2_tag_ {
|
|
/* Hardware looping register states */
|
|
TBIDUAL Start, End, Count;
|
|
|
|
} TBICTXEXTHL2, *PTBICTXEXTHL2;
|
|
|
|
/* Extended thread state save areas - DSP register states */
|
|
typedef struct _tbictxexttdp_tag_ {
|
|
/* DSP 32-bit accumulator register state (Bits 31:0 of ACX.0) */
|
|
TBIDUAL Acc32[1];
|
|
/* DSP > 32-bit accumulator bits 63:32 of ACX.0 (zero-extended) */
|
|
TBIDUAL Acc64[1];
|
|
/* Twiddle register state, and three phase increment states */
|
|
TBIDUAL PReg[4];
|
|
/* Modulo region size, padded to 64-bits */
|
|
int CurrMRSIZE, Reserved0;
|
|
|
|
} TBICTXEXTTDP, *PTBICTXEXTTDP;
|
|
|
|
/* Extended thread state save areas - DSP register states including DSP RAM */
|
|
typedef struct _tbictxexttdpr_tag_ {
|
|
/* DSP 32-bit accumulator register state (Bits 31:0 of ACX.0) */
|
|
TBIDUAL Acc32[1];
|
|
/* DSP 40-bit accumulator register state (Bits 39:8 of ACX.0) */
|
|
TBIDUAL Acc40[1];
|
|
/* DSP RAM Pointers */
|
|
TBIDUAL RP0[2], WP0[2], RP1[2], WP1[2];
|
|
/* DSP RAM Increments */
|
|
TBIDUAL RPI0[2], WPI0[2], RPI1[2], WPI1[2];
|
|
/* Template registers */
|
|
unsigned long Tmplt[16];
|
|
/* Modulo address region size and DSP RAM module region sizes */
|
|
int CurrMRSIZE, CurrDRSIZE;
|
|
|
|
} TBICTXEXTTDPR, *PTBICTXEXTTDPR;
|
|
|
|
#ifdef TBI_1_4
|
|
/* The METAC_ID_CORE register state is a marker for the FPU
|
|
state that is then stored after this core header structure. */
|
|
#define TBICTXEXTFPU_CONFIG_MASK ( (METAC_COREID_NOFPACC_BIT+ \
|
|
METAC_COREID_CFGFPU_BITS ) << \
|
|
METAC_COREID_CONFIG_BITS )
|
|
|
|
/* Recorded FPU exception state from TXDEFR in DefrFpu */
|
|
#define TBICTXEXTFPU_DEFRFPU_MASK (TXDEFR_FPU_FE_BITS)
|
|
|
|
/* Extended thread state save areas - FPU register states */
|
|
typedef struct _tbictxextfpu_tag_ {
|
|
/* Stored METAC_CORE_ID CONFIG */
|
|
int CfgFpu;
|
|
/* Stored deferred TXDEFR bits related to FPU
|
|
*
|
|
* This is encoded as follows in order to fit into 16-bits:
|
|
* DefrFPU:15 - 14 <= 0
|
|
* :13 - 8 <= TXDEFR:21-16
|
|
* : 7 - 6 <= 0
|
|
* : 5 - 0 <= TXDEFR:5-0
|
|
*/
|
|
short DefrFpu;
|
|
|
|
/* TXMODE bits related to FPU */
|
|
short ModeFpu;
|
|
|
|
/* FPU Even/Odd register states */
|
|
TBIDUAL FX[4];
|
|
|
|
/* if CfgFpu & TBICTX_CFGFPU_FX16_BIT -> 1 then TBICTXEXTBB4 holds FX.8-15 */
|
|
/* if CfgFpu & TBICTX_CFGFPU_NOACF_BIT -> 0 then TBICTXEXTFPACC holds state */
|
|
} TBICTXEXTFPU, *PTBICTXEXTFPU;
|
|
|
|
/* Extended thread state save areas - FPU accumulator state */
|
|
typedef struct _tbictxextfpacc_tag_ {
|
|
/* FPU accumulator register state - three 64-bit parts */
|
|
TBIDUAL FAcc32[3];
|
|
|
|
} TBICTXEXTFPACC, *PTBICTXEXTFPACC;
|
|
#endif
|
|
|
|
/* Prototype TBI structure */
|
|
struct _tbi_tag_ ;
|
|
|
|
/* A 64-bit return value used commonly in the TBI APIs */
|
|
typedef union _tbires_tag_ {
|
|
/* Save and load this value to get/set the whole result quickly */
|
|
long long Val;
|
|
|
|
/* Parameter of a fnSigs or __TBICtx* call */
|
|
struct _tbires_sig_tag_ {
|
|
/* TXMASK[I] bits zeroed upto and including current trigger level */
|
|
unsigned short TrigMask;
|
|
/* Control bits for handlers - see PTBIAPIFN documentation below */
|
|
unsigned short SaveMask;
|
|
/* Pointer to the base register context save area of the thread */
|
|
PTBICTX pCtx;
|
|
} Sig;
|
|
|
|
/* Result of TBIThrdPrivId call */
|
|
struct _tbires_thrdprivid_tag_ {
|
|
/* Basic thread identifier; just TBID_THREAD_BITS */
|
|
int Id;
|
|
/* None thread number bits; TBID_ISTAT_BIT+TBID_PSTAT_BIT */
|
|
int Priv;
|
|
} Thrd;
|
|
|
|
/* Parameter and Result of a __TBISwitch call */
|
|
struct _tbires_switch_tag_ {
|
|
/* Parameter passed across context switch */
|
|
void *pPara;
|
|
/* Thread context of other Thread includng restore flags */
|
|
PTBICTX pCtx;
|
|
} Switch;
|
|
|
|
/* For extended S/W events only */
|
|
struct _tbires_ccb_tag_ {
|
|
void *pCCB;
|
|
int COff;
|
|
} CCB;
|
|
|
|
struct _tbires_tlb_tag_ {
|
|
int Leaf; /* TLB Leaf data */
|
|
int Flags; /* TLB Flags */
|
|
} Tlb;
|
|
|
|
#ifdef TBI_FASTINT_1_4
|
|
struct _tbires_intr_tag_ {
|
|
short TrigMask;
|
|
short SaveMask;
|
|
PTBICTX2 pCtx;
|
|
} Intr;
|
|
#endif
|
|
|
|
} TBIRES, *PTBIRES;
|
|
#endif /* ifndef __ASSEMBLY__ */
|
|
|
|
#ifndef __ASSEMBLY__
|
|
/* Prototype for all signal handler functions, called via ___TBISyncTrigger or
|
|
___TBIASyncTrigger.
|
|
|
|
State.Sig.TrigMask will indicate the bits set within TXMASKI at
|
|
the time of the handler call that have all been cleared to prevent
|
|
nested interrupt occurring immediately.
|
|
|
|
State.Sig.SaveMask is a bit-mask which will be set to Zero when a trigger
|
|
occurs at background level and TBICTX_CRIT_BIT and optionally
|
|
TBICTX_CBUF_BIT when a trigger occurs at interrupt level.
|
|
|
|
TBICTX_CBUF_BIT reflects the state of TXSTATUS_CBMARKER_BIT for
|
|
the interrupted background thread.
|
|
|
|
State.Sig.pCtx will point at a TBICTX structure generated to hold the
|
|
critical state of the interrupted thread at interrupt level and
|
|
should be set to NULL when called at background level.
|
|
|
|
Triggers will indicate the status of TXSTAT or TXSTATI sampled by the
|
|
code that called the handler.
|
|
|
|
Inst is defined as 'Inst' if the SigNum is TBID_SIGNUM_SWx and holds the
|
|
actual SWITCH instruction detected, in other cases the value of this
|
|
parameter is undefined.
|
|
|
|
pTBI points at the PTBI structure related to the thread and processing
|
|
level involved.
|
|
|
|
TBIRES return value at both processing levels is similar in terms of any
|
|
changes that the handler makes. By default the State argument value
|
|
passed in should be returned.
|
|
|
|
Sig.TrigMask value is bits to OR back into TXMASKI when the handler
|
|
completes to enable currently disabled interrupts.
|
|
|
|
Sig.SaveMask value is ignored.
|
|
|
|
Sig.pCtx is ignored.
|
|
|
|
*/
|
|
typedef TBIRES (*PTBIAPIFN)( TBIRES State, int SigNum,
|
|
int Triggers, int Inst,
|
|
volatile struct _tbi_tag_ *pTBI );
|
|
#endif /* ifndef __ASSEMBLY__ */
|
|
|
|
#ifndef __ASSEMBLY__
|
|
/* The global memory map is described by a list of segment descriptors */
|
|
typedef volatile struct _tbiseg_tag_ {
|
|
volatile struct _tbiseg_tag_ *pLink;
|
|
int Id; /* Id of the segment */
|
|
TBISPIN Lock; /* Spin-lock for struct (normally 0) */
|
|
unsigned int Bytes; /* Size of region in bytes */
|
|
void *pGAddr; /* Base addr of region in global space */
|
|
void *pLAddr; /* Base addr of region in local space */
|
|
int Data[2]; /* Segment specific data (may be extended) */
|
|
|
|
} TBISEG, *PTBISEG;
|
|
#endif /* ifndef __ASSEMBLY__ */
|
|
|
|
/* Offsets of fields in TBISEG structure */
|
|
#define TBISEG_pLink ( 0)
|
|
#define TBISEG_Id ( 4)
|
|
#define TBISEG_Lock ( 8)
|
|
#define TBISEG_Bytes (12)
|
|
#define TBISEG_pGAddr (16)
|
|
#define TBISEG_pLAddr (20)
|
|
#define TBISEG_Data (24)
|
|
|
|
#ifndef __ASSEMBLY__
|
|
typedef volatile struct _tbi_tag_ {
|
|
int SigMask; /* Bits set to represent S/W events */
|
|
PTBIKICK pKick; /* Kick addr for S/W events */
|
|
void *pCCB; /* Extended S/W events */
|
|
PTBISEG pSeg; /* Related segment structure */
|
|
PTBIAPIFN fnSigs[TBID_SIGNUM_MAX+1];/* Signal handler API table */
|
|
} *PTBI, TBI;
|
|
#endif /* ifndef __ASSEMBLY__ */
|
|
|
|
/* Byte offsets of fields within TBI */
|
|
#define TBI_SigMask (0)
|
|
#define TBI_pKick (4)
|
|
#define TBI_pCCB (8)
|
|
#define TBI_pSeg (12)
|
|
#define TBI_fnSigs (16)
|
|
|
|
#ifdef TBI_1_4
|
|
#ifndef __ASSEMBLY__
|
|
/* This handler should be used for TBID_SIGNUM_DFR */
|
|
extern TBIRES __TBIHandleDFR ( TBIRES State, int SigNum,
|
|
int Triggers, int Inst,
|
|
volatile struct _tbi_tag_ *pTBI );
|
|
#endif
|
|
#endif
|
|
|
|
/* String table entry - special values */
|
|
#define METAG_TBI_STRS (0x5300) /* Tag : If entry is valid */
|
|
#define METAG_TBI_STRE (0x4500) /* Tag : If entry is end of table */
|
|
#define METAG_TBI_STRG (0x4700) /* Tag : If entry is a gap */
|
|
#define METAG_TBI_STRX (0x5A00) /* TransLen : If no translation present */
|
|
|
|
#ifndef __ASSEMBLY__
|
|
typedef volatile struct _tbistr_tag_ {
|
|
short Bytes; /* Length of entry in Bytes */
|
|
short Tag; /* Normally METAG_TBI_STRS(0x5300) */
|
|
short Len; /* Length of the string entry (incl null) */
|
|
short TransLen; /* Normally METAG_TBI_STRX(0x5A00) */
|
|
char String[8]; /* Zero terminated (may-be bigger) */
|
|
|
|
} TBISTR, *PTBISTR;
|
|
#endif /* ifndef __ASSEMBLY__ */
|
|
|
|
/* Cache size information - available as fields of Data[1] of global heap
|
|
segment */
|
|
#define METAG_TBI_ICACHE_SIZE_S 0 /* see comments below */
|
|
#define METAG_TBI_ICACHE_SIZE_BITS 0x0000000F
|
|
#define METAG_TBI_ICACHE_FILL_S 4
|
|
#define METAG_TBI_ICACHE_FILL_BITS 0x000000F0
|
|
#define METAG_TBI_DCACHE_SIZE_S 8
|
|
#define METAG_TBI_DCACHE_SIZE_BITS 0x00000F00
|
|
#define METAG_TBI_DCACHE_FILL_S 12
|
|
#define METAG_TBI_DCACHE_FILL_BITS 0x0000F000
|
|
|
|
/* METAG_TBI_xCACHE_SIZE
|
|
Describes the physical cache size rounded up to the next power of 2
|
|
relative to a 16K (2^14) cache. These sizes are encoded as a signed addend
|
|
to this base power of 2, for example
|
|
4K -> 2^12 -> -2 (i.e. 12-14)
|
|
8K -> 2^13 -> -1
|
|
16K -> 2^14 -> 0
|
|
32K -> 2^15 -> +1
|
|
64K -> 2^16 -> +2
|
|
128K -> 2^17 -> +3
|
|
|
|
METAG_TBI_xCACHE_FILL
|
|
Describes the physical cache size within the power of 2 area given by
|
|
the value above. For example a 10K cache may be represented as having
|
|
nearest size 16K with a fill of 10 sixteenths. This is encoded as the
|
|
number of unused 1/16ths, for example
|
|
0000 -> 0 -> 16/16
|
|
0001 -> 1 -> 15/16
|
|
0010 -> 2 -> 14/16
|
|
...
|
|
1111 -> 15 -> 1/16
|
|
*/
|
|
|
|
#define METAG_TBI_CACHE_SIZE_BASE_LOG2 14
|
|
|
|
/* Each declaration made by this macro generates a TBISTR entry */
|
|
#ifndef __ASSEMBLY__
|
|
#define TBISTR_DECL( Name, Str ) \
|
|
__attribute__ ((__section__ (".tbistr") )) const char Name[] = #Str
|
|
#endif
|
|
|
|
/* META timer values - see below for Timer support routines */
|
|
#define TBI_TIMERWAIT_MIN (-16) /* Minimum 'recommended' period */
|
|
#define TBI_TIMERWAIT_MAX (-0x7FFFFFFF) /* Maximum 'recommended' period */
|
|
|
|
#ifndef __ASSEMBLY__
|
|
/* These macros allow direct access from C to any register known to the
|
|
assembler or defined in machine.h. Example candidates are TXTACTCYC,
|
|
TXIDLECYC, and TXPRIVEXT. Note that when higher level macros and routines
|
|
like the timer and trigger handling features below these should be used in
|
|
preference to this direct low-level access mechanism. */
|
|
#define TBI_GETREG( Reg ) __extension__ ({\
|
|
int __GRValue; \
|
|
__asm__ volatile ("MOV\t%0," #Reg "\t/* (*TBI_GETREG OK) */" : \
|
|
"=r" (__GRValue) ); \
|
|
__GRValue; })
|
|
|
|
#define TBI_SETREG( Reg, Value ) do {\
|
|
int __SRValue = Value; \
|
|
__asm__ volatile ("MOV\t" #Reg ",%0\t/* (*TBI_SETREG OK) */" : \
|
|
: "r" (__SRValue) ); } while (0)
|
|
|
|
#define TBI_SWAPREG( Reg, Value ) do {\
|
|
int __XRValue = (Value); \
|
|
__asm__ volatile ("SWAP\t" #Reg ",%0\t/* (*TBI_SWAPREG OK) */" : \
|
|
"=r" (__XRValue) : "0" (__XRValue) ); \
|
|
Value = __XRValue; } while (0)
|
|
|
|
/* Obtain and/or release global critical section lock given that interrupts
|
|
are already disabled and/or should remain disabled. */
|
|
#define TBI_NOINTSCRITON do {\
|
|
__asm__ volatile ("LOCK1\t\t/* (*TBI_NOINTSCRITON OK) */");} while (0)
|
|
#define TBI_NOINTSCRITOFF do {\
|
|
__asm__ volatile ("LOCK0\t\t/* (*TBI_NOINTSCRITOFF OK) */");} while (0)
|
|
/* Optimised in-lining versions of the above macros */
|
|
|
|
#define TBI_LOCK( TrigState ) do {\
|
|
int __TRValue; \
|
|
int __ALOCKHI = LINSYSEVENT_WR_ATOMIC_LOCK & 0xFFFF0000; \
|
|
__asm__ volatile ("MOV %0,#0\t\t/* (*TBI_LOCK ... */\n\t" \
|
|
"SWAP\t%0,TXMASKI\t/* ... */\n\t" \
|
|
"LOCK2\t\t/* ... */\n\t" \
|
|
"SETD\t[%1+#0x40],D1RtP /* ... OK) */" : \
|
|
"=r&" (__TRValue) : "u" (__ALOCKHI) ); \
|
|
TrigState = __TRValue; } while (0)
|
|
#define TBI_CRITON( TrigState ) do {\
|
|
int __TRValue; \
|
|
__asm__ volatile ("MOV %0,#0\t\t/* (*TBI_CRITON ... */\n\t" \
|
|
"SWAP\t%0,TXMASKI\t/* ... */\n\t" \
|
|
"LOCK1\t\t/* ... OK) */" : \
|
|
"=r" (__TRValue) ); \
|
|
TrigState = __TRValue; } while (0)
|
|
|
|
#define TBI_INTSX( TrigState ) do {\
|
|
int __TRValue = TrigState; \
|
|
__asm__ volatile ("SWAP\t%0,TXMASKI\t/* (*TBI_INTSX OK) */" : \
|
|
"=r" (__TRValue) : "0" (__TRValue) ); \
|
|
TrigState = __TRValue; } while (0)
|
|
|
|
#define TBI_UNLOCK( TrigState ) do {\
|
|
int __TRValue = TrigState; \
|
|
int __ALOCKHI = LINSYSEVENT_WR_ATOMIC_LOCK & 0xFFFF0000; \
|
|
__asm__ volatile ("SETD\t[%1+#0x00],D1RtP\t/* (*TBI_UNLOCK ... */\n\t" \
|
|
"LOCK0\t\t/* ... */\n\t" \
|
|
"MOV\tTXMASKI,%0\t/* ... OK) */" : \
|
|
: "r" (__TRValue), "u" (__ALOCKHI) ); } while (0)
|
|
|
|
#define TBI_CRITOFF( TrigState ) do {\
|
|
int __TRValue = TrigState; \
|
|
__asm__ volatile ("LOCK0\t\t/* (*TBI_CRITOFF ... */\n\t" \
|
|
"MOV\tTXMASKI,%0\t/* ... OK) */" : \
|
|
: "r" (__TRValue) ); } while (0)
|
|
|
|
#define TBI_TRIGSX( SrcDst ) do { TBI_SWAPREG( TXMASK, SrcDst );} while (0)
|
|
|
|
/* Composite macros to perform logic ops on INTS or TRIGS masks */
|
|
#define TBI_INTSOR( Bits ) do {\
|
|
int __TT = 0; TBI_INTSX(__TT); \
|
|
__TT |= (Bits); TBI_INTSX(__TT); } while (0)
|
|
|
|
#define TBI_INTSAND( Bits ) do {\
|
|
int __TT = 0; TBI_INTSX(__TT); \
|
|
__TT &= (Bits); TBI_INTSX(__TT); } while (0)
|
|
|
|
#ifdef TBI_1_4
|
|
#define TBI_DEFRICTRLSOR( Bits ) do {\
|
|
int __TT = TBI_GETREG( CT.20 ); \
|
|
__TT |= (Bits); TBI_SETREG( CT.20, __TT); } while (0)
|
|
|
|
#define TBI_DEFRICTRLSAND( Bits ) do {\
|
|
int __TT = TBI_GETREG( TXDEFR ); \
|
|
__TT &= (Bits); TBI_SETREG( CT.20, __TT); } while (0)
|
|
#endif
|
|
|
|
#define TBI_TRIGSOR( Bits ) do {\
|
|
int __TT = TBI_GETREG( TXMASK ); \
|
|
__TT |= (Bits); TBI_SETREG( TXMASK, __TT); } while (0)
|
|
|
|
#define TBI_TRIGSAND( Bits ) do {\
|
|
int __TT = TBI_GETREG( TXMASK ); \
|
|
__TT &= (Bits); TBI_SETREG( TXMASK, __TT); } while (0)
|
|
|
|
/* Macros to disable and re-enable interrupts using TBI_INTSX, deliberate
|
|
traps and exceptions can still be handled within the critical section. */
|
|
#define TBI_STOPINTS( Value ) do {\
|
|
int __TT = TBI_GETREG( TXMASKI ); \
|
|
__TT &= TXSTATI_BGNDHALT_BIT; TBI_INTSX( __TT ); \
|
|
Value = __TT; } while (0)
|
|
#define TBI_RESTINTS( Value ) do {\
|
|
int __TT = Value; TBI_INTSX( __TT ); } while (0)
|
|
|
|
/* Return pointer to segment list at current privilege level */
|
|
PTBISEG __TBISegList( void );
|
|
|
|
/* Search the segment list for a match given Id, pStart can be NULL */
|
|
PTBISEG __TBIFindSeg( PTBISEG pStart, int Id );
|
|
|
|
/* Prepare a new segment structure using space from within another */
|
|
PTBISEG __TBINewSeg( PTBISEG pFromSeg, int Id, unsigned int Bytes );
|
|
|
|
/* Prepare a new segment using any global or local heap segments available */
|
|
PTBISEG __TBIMakeNewSeg( int Id, unsigned int Bytes );
|
|
|
|
/* Insert a new segment into the segment list so __TBIFindSeg can locate it */
|
|
void __TBIAddSeg( PTBISEG pSeg );
|
|
#define __TBIADDSEG_DEF /* Some versions failed to define this */
|
|
|
|
/* Return Id of current thread; TBID_ISTAT_BIT+TBID_THREAD_BITS */
|
|
int __TBIThreadId( void );
|
|
|
|
/* Return TBIRES.Thrd data for current thread */
|
|
TBIRES __TBIThrdPrivId( void );
|
|
|
|
/* Return pointer to current threads TBI root block.
|
|
Id implies whether Int or Background root block is required */
|
|
PTBI __TBI( int Id );
|
|
|
|
/* Try to set Mask bit using the spin-lock protocol, return 0 if fails and
|
|
new state if succeeds */
|
|
int __TBIPoll( PTBISPIN pLock, int Mask );
|
|
|
|
/* Set Mask bits via the spin-lock protocol in *pLock, return new state */
|
|
int __TBISpin( PTBISPIN pLock, int Mask );
|
|
|
|
/* Default handler set up for all TBI.fnSigs entries during initialisation */
|
|
TBIRES __TBIUnExpXXX( TBIRES State, int SigNum,
|
|
int Triggers, int Inst, PTBI pTBI );
|
|
|
|
/* Call this routine to service triggers at background processing level. The
|
|
TBID_POLL_BIT of the Id parameter value will be used to indicate that the
|
|
routine should return if no triggers need to be serviced initially. If this
|
|
bit is not set the routine will block until one trigger handler is serviced
|
|
and then behave like the poll case servicing any remaining triggers
|
|
actually outstanding before returning. Normally the State parameter should
|
|
be simply initialised to zero and the result should be ignored, other
|
|
values/options are for internal use only. */
|
|
TBIRES __TBISyncTrigger( TBIRES State, int Id );
|
|
|
|
/* Call this routine to enable processing of triggers by signal handlers at
|
|
interrupt level. The State parameter value passed is returned by this
|
|
routine. The State.Sig.TrigMask field also specifies the initial
|
|
state of the interrupt mask register TXMASKI to be setup by the call.
|
|
The other parts of the State parameter are ignored unless the PRIV bit is
|
|
set in the SaveMask field. In this case the State.Sig.pCtx field specifies
|
|
the base of the stack to which the interrupt system should switch into
|
|
as it saves the state of the previously executing code. In the case the
|
|
thread will be unprivileged as it continues execution at the return
|
|
point of this routine and it's future state will be effectively never
|
|
trusted to be valid. */
|
|
TBIRES __TBIASyncTrigger( TBIRES State );
|
|
|
|
/* Call this to swap soft threads executing at the background processing level.
|
|
The TBIRES returned to the new thread will be the same as the NextThread
|
|
value specified to the call. The NextThread.Switch.pCtx value specifies
|
|
which thread context to restore and the NextThread.Switch.Para value can
|
|
hold an arbitrary expression to be passed between the threads. The saved
|
|
state of the previous thread will be stored in a TBICTX descriptor created
|
|
on it's stack and the address of this will be stored into the *rpSaveCtx
|
|
location specified. */
|
|
TBIRES __TBISwitch( TBIRES NextThread, PTBICTX *rpSaveCtx );
|
|
|
|
/* Call this to initialise a stack frame ready for further use, up to four
|
|
32-bit arguments may be specified after the fixed args to be passed via
|
|
the new stack pStack to the routine specified via fnMain. If the
|
|
main-line routine ever returns the thread will operate as if main itself
|
|
had returned and terminate with the return code given. */
|
|
typedef int (*PTBIMAINFN)( TBIRES Arg /*, <= 4 additional 32-bit args */ );
|
|
PTBICTX __TBISwitchInit( void *pStack, PTBIMAINFN fnMain, ... );
|
|
|
|
/* Call this to resume a thread from a saved synchronous TBICTX state.
|
|
The TBIRES returned to the new thread will be the same as the NextThread
|
|
value specified to the call. The NextThread.Switch.pCtx value specifies
|
|
which thread context to restore and the NextThread.Switch.Para value can
|
|
hold an arbitrary expression to be passed between the threads. The context
|
|
of the calling thread is lost and this routine never returns to the
|
|
caller. The TrigsMask value supplied is ored into TXMASKI to enable
|
|
interrupts after the context of the new thread is established. */
|
|
void __TBISyncResume( TBIRES NextThread, int TrigsMask );
|
|
|
|
/* Call these routines to save and restore the extended states of
|
|
scheduled tasks. */
|
|
void *__TBICtxSave( TBIRES State, void *pExt );
|
|
void *__TBICtxRestore( TBIRES State, void *pExt );
|
|
|
|
#ifdef TBI_1_4
|
|
#ifdef TBI_FASTINT_1_4
|
|
/* Call these routines to copy the GP state to a separate buffer
|
|
* Only necessary for context switching.
|
|
*/
|
|
PTBICTXGP __TBICtx2SaveCrit( PTBICTX2 pCurrentCtx, PTBICTX2 pSaveCtx );
|
|
void *__TBICtx2SaveGP( PTBICTXGP pCurrentCtxGP, PTBICTXGP pSaveCtxGP );
|
|
|
|
/* Call these routines to save and restore the extended states of
|
|
scheduled tasks. */
|
|
void *__TBICtx2Save( PTBICTXGP pCtxGP, short SaveMask, void *pExt );
|
|
void *__TBICtx2Restore( PTBICTX2 pCtx, short SaveMask, void *pExt );
|
|
#endif
|
|
|
|
/* If FPAC flag is set then significant FPU context exists. Call these routine
|
|
to save and restore it */
|
|
void *__TBICtxFPUSave( TBIRES State, void *pExt );
|
|
void *__TBICtxFPURestore( TBIRES State, void *pExt );
|
|
|
|
#ifdef TBI_FASTINT_1_4
|
|
extern void *__TBICtx2FPUSave (PTBICTXGP, short, void*);
|
|
extern void *__TBICtx2FPURestore (PTBICTXGP, short, void*);
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef TBI_1_4
|
|
/* Call these routines to save and restore DSPRAM. */
|
|
void *__TBIDspramSaveA (short DspramSizes, void *pExt);
|
|
void *__TBIDspramSaveB (short DspramSizes, void *pExt);
|
|
void *__TBIDspramRestoreA (short DspramSizes, void *pExt);
|
|
void *__TBIDspramRestoreB (short DspramSizes, void *pExt);
|
|
#endif
|
|
|
|
/* This routine should be used at the entrypoint of interrupt handlers to
|
|
re-enable higher priority interrupts and/or save state from the previously
|
|
executing background code. State is a TBIRES.Sig parameter with NoNestMask
|
|
indicating the triggers (if any) that should remain disabled and SaveMask
|
|
CBUF bit indicating the if the hardware catch buffer is dirty. Optionally
|
|
any number of extended state bits X??? including XCBF can be specified to
|
|
force a nested state save call to __TBICtxSave before the current routine
|
|
continues. (In the latter case __TBICtxRestore should be called to restore
|
|
any extended states before the background thread of execution is resumed)
|
|
|
|
By default (no X??? bits specified in SaveMask) this routine performs a
|
|
sub-call to __TBICtxSave with the pExt and State parameters specified IF
|
|
some triggers could be serviced while the current interrupt handler
|
|
executes and the hardware catch buffer is actually dirty. In this case
|
|
this routine provides the XCBF bit in State.Sig.SaveMask to force the
|
|
__TBICtxSave to extract the current catch state.
|
|
|
|
The NoNestMask parameter should normally indicate that the same or lower
|
|
triggers than those provoking the current handler call should not be
|
|
serviced in nested calls, zero may be specified if all possible interrupts
|
|
are to be allowed.
|
|
|
|
The TBIRES.Sig value returned will be similar to the State parameter
|
|
specified with the XCBF bit ORed into it's SaveMask if a context save was
|
|
required and fewer bits set in it's TrigMask corresponding to the same/lower
|
|
priority interrupt triggers still not enabled. */
|
|
TBIRES __TBINestInts( TBIRES State, void *pExt, int NoNestMask );
|
|
|
|
/* This routine causes the TBICTX structure specified in State.Sig.pCtx to
|
|
be restored. This implies that execution will not return to the caller.
|
|
The State.Sig.TrigMask field will be restored during the context switch
|
|
such that any immediately occurring interrupts occur in the context of the
|
|
newly specified task. The State.Sig.SaveMask parameter is ignored. */
|
|
void __TBIASyncResume( TBIRES State );
|
|
|
|
/* Call this routine to enable fastest possible processing of one or more
|
|
interrupt triggers via a unified signal handler. The handler concerned
|
|
must simple return after servicing the related hardware.
|
|
The State.Sig.TrigMask parameter indicates the interrupt triggers to be
|
|
enabled and the Thin.Thin.fnHandler specifies the routine to call and
|
|
the whole Thin parameter value will be passed to this routine unaltered as
|
|
it's first parameter. */
|
|
void __TBIASyncThin( TBIRES State, TBIRES Thin );
|
|
|
|
/* Do this before performing your own direct spin-lock access - use TBI_LOCK */
|
|
int __TBILock( void );
|
|
|
|
/* Do this after performing your own direct spin-lock access - use TBI_UNLOCK */
|
|
void __TBIUnlock( int TrigState );
|
|
|
|
/* Obtain and release global critical section lock - only stops execution
|
|
of interrupts on this thread and similar critical section code on other
|
|
local threads - use TBI_CRITON or TBI_CRITOFF */
|
|
int __TBICritOn( void );
|
|
void __TBICritOff( int TrigState );
|
|
|
|
/* Change INTS (TXMASKI) - return old state - use TBI_INTSX */
|
|
int __TBIIntsX( int NewMask );
|
|
|
|
/* Change TRIGS (TXMASK) - return old state - use TBI_TRIGSX */
|
|
int __TBITrigsX( int NewMask );
|
|
|
|
/* This function initialises a timer for first use, only the TBID_ISTAT_BIT
|
|
of the Id parameter is used to indicate which timer is to be modified. The
|
|
Wait value should either be zero to disable the timer concerned or be in
|
|
the recommended TBI_TIMERWAIT_* range to specify the delay required before
|
|
the first timer trigger occurs.
|
|
|
|
The TBID_ISTAT_BIT of the Id parameter similar effects all other timer
|
|
support functions (see below). */
|
|
void __TBITimerCtrl( int Id, int Wait );
|
|
|
|
/* This routine returns a 64-bit time stamp value that is initialised to zero
|
|
via a __TBITimerCtrl timer enabling call. */
|
|
long long __TBITimeStamp( int Id );
|
|
|
|
/* To manage a periodic timer each period elapsed should be subracted from
|
|
the current timer value to attempt to set up the next timer trigger. The
|
|
Wait parameter should be a value in the recommended TBI_TIMERWAIT_* range.
|
|
The return value is the new aggregate value that the timer was updated to,
|
|
if this is less than zero then a timer trigger is guaranteed to be
|
|
generated after the number of ticks implied, if a positive result is
|
|
returned either itterative or step-wise corrective action must be taken to
|
|
resynchronise the timer and hence provoke a future timer trigger. */
|
|
int __TBITimerAdd( int Id, int Wait );
|
|
|
|
/* String table search function, pStart is first entry to check or NULL,
|
|
pStr is string data to search for and MatchLen is either length of string
|
|
to compare for an exact match or negative length to compare for partial
|
|
match. */
|
|
const TBISTR *__TBIFindStr( const TBISTR *pStart,
|
|
const char *pStr, int MatchLen );
|
|
|
|
/* String table translate function, pStr is text to translate and Len is
|
|
it's length. Value returned may not be a string pointer if the
|
|
translation value is really some other type, 64-bit alignment of the return
|
|
pointer is guaranteed so almost any type including a structure could be
|
|
located with this routine. */
|
|
const void *__TBITransStr( const char *pStr, int Len );
|
|
|
|
|
|
|
|
/* Arbitrary physical memory access windows, use different Channels to avoid
|
|
conflict/thrashing within a single piece of code. */
|
|
void *__TBIPhysAccess( int Channel, int PhysAddr, int Bytes );
|
|
void __TBIPhysRelease( int Channel, void *pLinAddr );
|
|
|
|
#ifdef METAC_1_0
|
|
/* Data cache function nullified because data cache is off */
|
|
#define TBIDCACHE_FLUSH( pAddr )
|
|
#define TBIDCACHE_PRELOAD( Type, pAddr ) ((Type) (pAddr))
|
|
#define TBIDCACHE_REFRESH( Type, pAddr ) ((Type) (pAddr))
|
|
#endif
|
|
#ifdef METAC_1_1
|
|
/* To flush a single cache line from the data cache using a linear address */
|
|
#define TBIDCACHE_FLUSH( pAddr ) ((volatile char *) \
|
|
(((unsigned int) (pAddr))>>LINSYSLFLUSH_S))[0] = 0
|
|
|
|
extern void * __builtin_dcache_preload (void *);
|
|
|
|
/* Try to ensure that the data at the address concerned is in the cache */
|
|
#define TBIDCACHE_PRELOAD( Type, Addr ) \
|
|
((Type) __builtin_dcache_preload ((void *)(Addr)))
|
|
|
|
extern void * __builtin_dcache_refresh (void *);
|
|
|
|
/* Flush any old version of data from address and re-load a new copy */
|
|
#define TBIDCACHE_REFRESH( Type, Addr ) __extension__ ({ \
|
|
Type __addr = (Type)(Addr); \
|
|
(void)__builtin_dcache_refresh ((void *)(((unsigned int)(__addr))>>6)); \
|
|
__addr; })
|
|
|
|
#endif
|
|
#ifndef METAC_1_0
|
|
#ifndef METAC_1_1
|
|
/* Support for DCACHE builtin */
|
|
extern void __builtin_dcache_flush (void *);
|
|
|
|
/* To flush a single cache line from the data cache using a linear address */
|
|
#define TBIDCACHE_FLUSH( Addr ) \
|
|
__builtin_dcache_flush ((void *)(Addr))
|
|
|
|
extern void * __builtin_dcache_preload (void *);
|
|
|
|
/* Try to ensure that the data at the address concerned is in the cache */
|
|
#define TBIDCACHE_PRELOAD( Type, Addr ) \
|
|
((Type) __builtin_dcache_preload ((void *)(Addr)))
|
|
|
|
extern void * __builtin_dcache_refresh (void *);
|
|
|
|
/* Flush any old version of data from address and re-load a new copy */
|
|
#define TBIDCACHE_REFRESH( Type, Addr ) \
|
|
((Type) __builtin_dcache_refresh ((void *)(Addr)))
|
|
|
|
#endif
|
|
#endif
|
|
|
|
/* Flush the MMCU cache */
|
|
#define TBIMCACHE_FLUSH() { ((volatile int *) LINSYSCFLUSH_MMCU)[0] = 0; }
|
|
|
|
#ifdef METAC_2_1
|
|
/* Obtain the MMU table entry for the specified address */
|
|
#define TBIMTABLE_LEAFDATA(ADDR) TBIXCACHE_RD((int)(ADDR) & (-1<<6))
|
|
|
|
#ifndef __ASSEMBLY__
|
|
/* Obtain the full MMU table entry for the specified address */
|
|
#define TBIMTABLE_DATA(ADDR) __extension__ ({ TBIRES __p; \
|
|
__p.Val = TBIXCACHE_RL((int)(ADDR) & (-1<<6)); \
|
|
__p; })
|
|
#endif
|
|
#endif
|
|
|
|
/* Combine a physical base address, and a linear address
|
|
* Internal use only
|
|
*/
|
|
#define _TBIMTABLE_LIN2PHYS(PHYS, LIN, LMASK) (void*)(((int)(PHYS)&0xFFFFF000)\
|
|
+((int)(LIN)&(LMASK)))
|
|
|
|
/* Convert a linear to a physical address */
|
|
#define TBIMTABLE_LIN2PHYS(LEAFDATA, ADDR) \
|
|
(((LEAFDATA) & CRLINPHY0_VAL_BIT) \
|
|
? _TBIMTABLE_LIN2PHYS(LEAFDATA, ADDR, 0x00000FFF) \
|
|
: 0)
|
|
|
|
/* Debug support - using external debugger or host */
|
|
void __TBIDumpSegListEntries( void );
|
|
void __TBILogF( const char *pFmt, ... );
|
|
void __TBIAssert( const char *pFile, int LineNum, const char *pExp );
|
|
void __TBICont( const char *pMsg, ... ); /* TBIAssert -> 'wait for continue' */
|
|
|
|
/* Array of signal name data for debug messages */
|
|
extern const char __TBISigNames[];
|
|
#endif /* ifndef __ASSEMBLY__ */
|
|
|
|
|
|
|
|
/* Scale of sub-strings in the __TBISigNames string list */
|
|
#define TBI_SIGNAME_SCALE 4
|
|
#define TBI_SIGNAME_SCALE_S 2
|
|
|
|
#define TBI_1_3
|
|
|
|
#ifdef TBI_1_3
|
|
|
|
#ifndef __ASSEMBLY__
|
|
#define TBIXCACHE_RD(ADDR) __extension__ ({\
|
|
void * __Addr = (void *)(ADDR); \
|
|
int __Data; \
|
|
__asm__ volatile ( "CACHERD\t%0,[%1+#0]" : \
|
|
"=r" (__Data) : "r" (__Addr) ); \
|
|
__Data; })
|
|
|
|
#define TBIXCACHE_RL(ADDR) __extension__ ({\
|
|
void * __Addr = (void *)(ADDR); \
|
|
long long __Data; \
|
|
__asm__ volatile ( "CACHERL\t%0,%t0,[%1+#0]" : \
|
|
"=d" (__Data) : "r" (__Addr) ); \
|
|
__Data; })
|
|
|
|
#define TBIXCACHE_WD(ADDR, DATA) do {\
|
|
void * __Addr = (void *)(ADDR); \
|
|
int __Data = DATA; \
|
|
__asm__ volatile ( "CACHEWD\t[%0+#0],%1" : \
|
|
: "r" (__Addr), "r" (__Data) ); } while(0)
|
|
|
|
#define TBIXCACHE_WL(ADDR, DATA) do {\
|
|
void * __Addr = (void *)(ADDR); \
|
|
long long __Data = DATA; \
|
|
__asm__ volatile ( "CACHEWL\t[%0+#0],%1,%t1" : \
|
|
: "r" (__Addr), "r" (__Data) ); } while(0)
|
|
|
|
#ifdef TBI_4_0
|
|
|
|
#define TBICACHE_FLUSH_L1D_L2(ADDR) \
|
|
TBIXCACHE_WD(ADDR, CACHEW_FLUSH_L1D_L2)
|
|
#define TBICACHE_WRITEBACK_L1D_L2(ADDR) \
|
|
TBIXCACHE_WD(ADDR, CACHEW_WRITEBACK_L1D_L2)
|
|
#define TBICACHE_INVALIDATE_L1D(ADDR) \
|
|
TBIXCACHE_WD(ADDR, CACHEW_INVALIDATE_L1D)
|
|
#define TBICACHE_INVALIDATE_L1D_L2(ADDR) \
|
|
TBIXCACHE_WD(ADDR, CACHEW_INVALIDATE_L1D_L2)
|
|
#define TBICACHE_INVALIDATE_L1DTLB(ADDR) \
|
|
TBIXCACHE_WD(ADDR, CACHEW_INVALIDATE_L1DTLB)
|
|
#define TBICACHE_INVALIDATE_L1I(ADDR) \
|
|
TBIXCACHE_WD(ADDR, CACHEW_INVALIDATE_L1I)
|
|
#define TBICACHE_INVALIDATE_L1ITLB(ADDR) \
|
|
TBIXCACHE_WD(ADDR, CACHEW_INVALIDATE_L1ITLB)
|
|
|
|
#endif /* TBI_4_0 */
|
|
#endif /* ifndef __ASSEMBLY__ */
|
|
|
|
/*
|
|
* Calculate linear PC value from real PC and Minim mode control, the LSB of
|
|
* the result returned indicates if address compression has occurred.
|
|
*/
|
|
#ifndef __ASSEMBLY__
|
|
#define METAG_LINPC( PCVal ) (\
|
|
( (TBI_GETREG(TXPRIVEXT) & TXPRIVEXT_MINIMON_BIT) != 0 ) ? ( \
|
|
( ((PCVal) & 0x00900000) == 0x00900000 ) ? \
|
|
(((PCVal) & 0xFFE00000) + (((PCVal) & 0x001FFFFC)>>1) + 1) : \
|
|
( ((PCVal) & 0x00800000) == 0x00000000 ) ? \
|
|
(((PCVal) & 0xFF800000) + (((PCVal) & 0x007FFFFC)>>1) + 1) : \
|
|
(PCVal) ) \
|
|
: (PCVal) )
|
|
#define METAG_LINPC_X2BIT 0x00000001 /* Make (Size>>1) if compressed */
|
|
|
|
/* Convert an arbitrary Linear address into a valid Minim PC or return 0 */
|
|
#define METAG_PCMINIM( LinVal ) (\
|
|
(((LinVal) & 0x00980000) == 0x00880000) ? \
|
|
(((LinVal) & 0xFFE00000) + (((LinVal) & 0x000FFFFE)<<1)) : \
|
|
(((LinVal) & 0x00C00000) == 0x00000000) ? \
|
|
(((LinVal) & 0xFF800000) + (((LinVal) & 0x003FFFFE)<<1)) : 0 )
|
|
|
|
/* Reverse a METAG_LINPC conversion step to return the original PCVal */
|
|
#define METAG_PCLIN( LinVal ) ( 0xFFFFFFFC & (\
|
|
( (LinVal & METAG_LINPC_X2BIT) != 0 ) ? METAG_PCMINIM( LinVal ) : \
|
|
(LinVal) ))
|
|
|
|
/*
|
|
* Flush the MMCU Table cache privately for each thread. On cores that do not
|
|
* support per-thread flushing it will flush all threads mapping data.
|
|
*/
|
|
#define TBIMCACHE_TFLUSH(Thread) do {\
|
|
((volatile int *)( LINSYSCFLUSH_TxMMCU_BASE + \
|
|
(LINSYSCFLUSH_TxMMCU_STRIDE*(Thread)) ))[0] = 0; \
|
|
} while(0)
|
|
|
|
/*
|
|
* To flush a single linear-matched cache line from the code cache. In
|
|
* cases where Minim is possible the METAC_LINPC operation must be used
|
|
* to pre-process the address being flushed.
|
|
*/
|
|
#define TBIICACHE_FLUSH( pAddr ) TBIXCACHE_WD (pAddr, CACHEW_ICACHE_BIT)
|
|
|
|
/* To flush a single linear-matched mapping from code/data MMU table cache */
|
|
#define TBIMCACHE_AFLUSH( pAddr, SegType ) \
|
|
TBIXCACHE_WD(pAddr, CACHEW_TLBFLUSH_BIT + ( \
|
|
((SegType) == TBID_SEGTYPE_TEXT) ? CACHEW_ICACHE_BIT : 0 ))
|
|
|
|
/*
|
|
* To flush translation data corresponding to a range of addresses without
|
|
* using TBITCACHE_FLUSH to flush all of this threads translation data. It
|
|
* is necessary to know what stride (>= 4K) must be used to flush a specific
|
|
* region.
|
|
*
|
|
* For example direct mapped regions use the maximum page size (512K) which may
|
|
* mean that only one flush is needed to cover the sub-set of the direct
|
|
* mapped area used since it was setup.
|
|
*
|
|
* The function returns the stride on which flushes should be performed.
|
|
*
|
|
* If 0 is returned then the region is not subject to MMU caching, if -1 is
|
|
* returned then this indicates that only TBIMCACHE_TFLUSH can be used to
|
|
* flush the region concerned rather than TBIMCACHE_AFLUSH which this
|
|
* function is designed to support.
|
|
*/
|
|
int __TBIMMUCacheStride( const void *pStart, int Bytes );
|
|
|
|
/*
|
|
* This function will use the above lower level functions to achieve a MMU
|
|
* table data flush in an optimal a fashion as possible. On a system that
|
|
* supports linear address based caching this function will also call the
|
|
* code or data cache flush functions to maintain address/data coherency.
|
|
*
|
|
* SegType should be TBID_SEGTYPE_TEXT if the address range is for code or
|
|
* any other value such as TBID_SEGTYPE_DATA for data. If an area is
|
|
* used in both ways then call this function twice; once for each.
|
|
*/
|
|
void __TBIMMUCacheFlush( const void *pStart, int Bytes, int SegType );
|
|
|
|
/*
|
|
* Cached Core mode setup and flush functions allow one code and one data
|
|
* region of the corresponding global or local cache partion size to be
|
|
* locked into the corresponding cache memory. This prevents normal LRU
|
|
* logic discarding the code or data and avoids write-thru bandwidth in
|
|
* data areas. Code mappings are selected by specifying TBID_SEGTYPE_TEXT
|
|
* for SegType, otherwise data mappings are created.
|
|
*
|
|
* Mode supplied should always contain the VALID bit and WINx selection data.
|
|
* Data areas will be mapped read-only if the WRITE bit is not added.
|
|
*
|
|
* The address returned by the Opt function will either be the same as that
|
|
* passed in (if optimisation cannot be supported) or the base of the new core
|
|
* cached region in linear address space. The returned address must be passed
|
|
* into the End function to remove the mapping when required. If a non-core
|
|
* cached memory address is passed into it the End function has no effect.
|
|
* Note that the region accessed MUST be flushed from the appropriate cache
|
|
* before the End function is called to deliver correct operation.
|
|
*/
|
|
void *__TBICoreCacheOpt( const void *pStart, int Bytes, int SegType, int Mode );
|
|
void __TBICoreCacheEnd( const void *pOpt, int Bytes, int SegType );
|
|
|
|
/*
|
|
* Optimise physical access channel and flush side effects before releasing
|
|
* the channel. If pStart is NULL the whole region must be flushed and this is
|
|
* done automatically by the channel release function if optimisation is
|
|
* enabled. Flushing the specific region that may have been accessed before
|
|
* release should optimises this process. On physically cached systems we do
|
|
* not flush the code/data caches only the MMU table data needs flushing.
|
|
*/
|
|
void __TBIPhysOptim( int Channel, int IMode, int DMode );
|
|
void __TBIPhysFlush( int Channel, const void *pStart, int Bytes );
|
|
#endif
|
|
#endif /* ifdef TBI_1_3 */
|
|
|
|
#endif /* _ASM_METAG_TBX_H_ */
|