diff options
author | James Hogan <james.hogan@imgtec.com> | 2012-09-21 17:40:06 +0100 |
---|---|---|
committer | James Hogan <james.hogan@imgtec.com> | 2013-03-02 20:09:18 +0000 |
commit | 027f891f7640144d4b7b15113f3ae9af2c8b095d (patch) | |
tree | cee318450f4782ca3a471f83ef3fd3557e8c3a9d /arch | |
parent | 4ca151b20803eb2e31bb6d840d01eec461158e14 (diff) |
metag: TBX source
Add source files from the Thread Binary Interface (TBI) library which
provides useful low level operations and traps/context management.
Among other things it handles interrupt/exception/syscall entry (in
tbipcx.S).
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/metag/tbx/tbicore.S | 136 | ||||
-rw-r--r-- | arch/metag/tbx/tbictx.S | 366 | ||||
-rw-r--r-- | arch/metag/tbx/tbictxfpu.S | 190 | ||||
-rw-r--r-- | arch/metag/tbx/tbidefr.S | 175 | ||||
-rw-r--r-- | arch/metag/tbx/tbidspram.S | 161 | ||||
-rw-r--r-- | arch/metag/tbx/tbilogf.S | 48 | ||||
-rw-r--r-- | arch/metag/tbx/tbipcx.S | 451 | ||||
-rw-r--r-- | arch/metag/tbx/tbiroot.S | 87 | ||||
-rw-r--r-- | arch/metag/tbx/tbisoft.S | 237 | ||||
-rw-r--r-- | arch/metag/tbx/tbistring.c | 114 | ||||
-rw-r--r-- | arch/metag/tbx/tbitimer.S | 207 |
11 files changed, 2172 insertions, 0 deletions
diff --git a/arch/metag/tbx/tbicore.S b/arch/metag/tbx/tbicore.S new file mode 100644 index 000000000000..a0838ebcb433 --- /dev/null +++ b/arch/metag/tbx/tbicore.S @@ -0,0 +1,136 @@ +/* + * tbicore.S + * + * Copyright (C) 2001, 2002, 2007, 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. + * + * Core functions needed to support use of the thread binary interface for META + * processors + */ + + .file "tbicore.S" +/* Get data structures and defines from the TBI C header */ +#include <asm/metag_mem.h> +#include <asm/metag_regs.h> +#include <asm/tbx.h> + + .data + .balign 8 + .global ___pTBISegs + .type ___pTBISegs,object +___pTBISegs: + .quad 0 /* Segment list pointer with it's */ + .size ___pTBISegs,.-___pTBISegs + /* own id or spin-lock location */ +/* + * Return ___pTBISegs value specific to privilege level - not very complicated + * at the moment + * + * Register Usage: D0Re0 is the result, D1Re0 is used as a scratch + */ + .text + .balign 4 + .global ___TBISegList + .type ___TBISegList,function +___TBISegList: + MOVT A1LbP,#HI(___pTBISegs) + ADD A1LbP,A1LbP,#LO(___pTBISegs) + GETL D0Re0,D1Re0,[A1LbP] + MOV PC,D1RtP + .size ___TBISegList,.-___TBISegList + +/* + * Search the segment list for a match given Id, pStart can be NULL + * + * Register Usage: D1Ar1 is pSeg, D0Ar2 is Id, D0Re0 is the result + * D0Ar4, D1Ar3 are used as a scratch + * NB: The PSTAT bit if Id in D0Ar2 may be toggled + */ + .text + .balign 4 + .global ___TBIFindSeg + .type ___TBIFindSeg,function +___TBIFindSeg: + MOVT A1LbP,#HI(___pTBISegs) + ADD A1LbP,A1LbP,#LO(___pTBISegs) + GETL D1Ar3,D0Ar4,[A1LbP] /* Read segment list head */ + MOV D0Re0,TXSTATUS /* What priv level are we at? */ + CMP D1Ar1,#0 /* Is pStart provided? */ +/* Disable privilege adaption for now */ + ANDT D0Re0,D0Re0,#0 /*HI(TXSTATUS_PSTAT_BIT) ; Is PSTAT set? Zero if not */ + LSL D0Re0,D0Re0,#(TBID_PSTAT_S-TXSTATUS_PSTAT_S) + XOR D0Ar2,D0Ar2,D0Re0 /* Toggle Id PSTAT if privileged */ + MOVNZ D1Ar3,D1Ar1 /* Use pStart if provided */ +$LFindSegLoop: + ADDS D0Re0,D1Ar3,#0 /* End of list? Load result into D0Re0 */ + MOVZ PC,D1RtP /* If result is NULL we leave */ + GETL D1Ar3,D0Ar4,[D1Ar3] /* Read pLink and Id */ + CMP D0Ar4,D0Ar2 /* Does it match? */ + BNZ $LFindSegLoop /* Loop if there is no match */ + TST D0Re0,D0Re0 /* Clear zero flag - we found it! */ + MOV PC,D1RtP /* Return */ + .size ___TBIFindSeg,.-___TBIFindSeg + +/* Useful offsets to encode the lower bits of the lock/unlock addresses */ +#define UON (LINSYSEVENT_WR_ATOMIC_LOCK & 0xFFF8) +#define UOFF (LINSYSEVENT_WR_ATOMIC_UNLOCK & 0xFFF8) + +/* + * Perform a whole spin-lock sequence as used by the TBISignal routine + * + * Register Usage: D1Ar1 is pLock, D0Ar2 is Mask, D0Re0 is the result + * (All other usage due to ___TBIPoll - D0Ar6, D1Re0) + */ + .text + .balign 4 + .global ___TBISpin + .type ___TBISpin,function +___TBISpin: + SETL [A0StP++],D0FrT,D1RtP /* Save our return address */ + ORS D0Re0,D0Re0,#1 /* Clear zero flag */ + MOV D1RtP,PC /* Setup return address to form loop */ +$LSpinLoop: + BNZ ___TBIPoll /* Keep repeating if fail to set */ + GETL D0FrT,D1RtP,[--A0StP] /* Restore return address */ + MOV PC,D1RtP /* Return */ + .size ___TBISpin,.-___TBISpin + +/* + * Perform an attempt to gain access to a spin-lock and set some bits + * + * Register Usage: D1Ar1 is pLock, D0Ar2 is Mask, D0Re0 is the result + * !!On return Zero flag is SET if we are sucessfull!! + * A0.3 is used to hold base address of system event region + * D1Re0 use to hold TXMASKI while interrupts are off + */ + .text + .balign 4 + .global ___TBIPoll + .type ___TBIPoll,function +___TBIPoll: + MOV D1Re0,#0 /* Prepare to disable ints */ + MOVT A0.3,#HI(LINSYSEVENT_WR_ATOMIC_LOCK) + SWAP D1Re0,TXMASKI /* Really stop ints */ + LOCK2 /* Gain all locks */ + SET [A0.3+#UON],D1RtP /* Stop shared memory access too */ + DCACHE [D1Ar1],A0.3 /* Flush Cache line */ + GETD D0Re0,[D1Ar1] /* Get new state from memory or hit */ + DCACHE [D1Ar1],A0.3 /* Flush Cache line */ + GETD D0Re0,[D1Ar1] /* Get current state */ + TST D0Re0,D0Ar2 /* Are we clear to send? */ + ORZ D0Re0,D0Re0,D0Ar2 /* Yes: So set bits and */ + SETDZ [D1Ar1],D0Re0 /* transmit new state */ + SET [A0.3+#UOFF],D1RtP /* Allow shared memory access */ + LOCK0 /* Release all locks */ + MOV TXMASKI,D1Re0 /* Allow ints */ +$LPollEnd: + XORNZ D0Re0,D0Re0,D0Re0 /* No: Generate zero result */ + MOV PC,D1RtP /* Return (NZ indicates failure) */ + .size ___TBIPoll,.-___TBIPoll + +/* + * End of tbicore.S + */ diff --git a/arch/metag/tbx/tbictx.S b/arch/metag/tbx/tbictx.S new file mode 100644 index 000000000000..19af983a13ae --- /dev/null +++ b/arch/metag/tbx/tbictx.S @@ -0,0 +1,366 @@ +/* + * tbictx.S + * + * Copyright (C) 2001, 2002, 2007, 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. + * + * Explicit state save and restore routines forming part of the thread binary + * interface for META processors + */ + + .file "tbictx.S" +#include <asm/metag_regs.h> +#include <asm/tbx.h> + +#ifdef METAC_1_0 +/* Ax.4 is NOT saved in XAX3 */ +#define A0_4 +#else +/* Ax.4 is saved in XAX4 */ +#define A0_4 A0.4, +#endif + + +/* Size of the TBICTX structure */ +#define TBICTX_BYTES ((TBICTX_AX_REGS*8)+TBICTX_AX) + +/* + * TBIRES __TBINestInts( TBIRES State, void *pExt, int NoNestMask ) + */ + .text + .balign 4 + .global ___TBINestInts + .type ___TBINestInts,function +___TBINestInts: + XOR D0Ar4,D0Ar4,#-1 /* D0Ar4 = ~TrigBit */ + AND D0Ar4,D0Ar4,#0xFFFF /* D0Ar4 &= 0xFFFF */ + MOV D0Ar6,TXMASKI /* BGNDHALT currently enabled? */ + TSTT D0Ar2,#TBICTX_XDX8_BIT+TBICTX_XAXX_BIT+TBICTX_XHL2_BIT+TBICTX_XTDP_BIT+TBICTX_XCBF_BIT + AND D0Ar4,D0Ar2,D0Ar4 /* D0Ar4 = Ints to allow */ + XOR D0Ar2,D0Ar2,D0Ar4 /* Less Ints in TrigMask */ + BNZ ___TBINestInts2 /* Jump if ctx save required! */ + TSTT D0Ar2,#TBICTX_CBUF_BIT+TBICTX_CBRP_BIT /* Is catch state dirty? */ + OR D0Ar4,D0Ar4,D0Ar6 /* Or in TXMASKI BGNDHALT if set */ + TSTNZ D0Ar4,D0Ar4 /* Yes: AND triggers enabled */ + MOV D0Re0,D0Ar2 /* Update State argument */ + MOV D1Re0,D1Ar1 /* with less Ints in TrigMask */ + MOVZ TXMASKI,D0Ar4 /* Early return: Enable Ints */ + MOVZ PC,D1RtP /* Early return */ + .size ___TBINestInts,.-___TBINestInts +/* + * Drop thru into sub-function- + */ + .global ___TBINestInts2 + .type ___TBINestInts2,function +___TBINestInts2: + MOV D0FrT,A0FrP /* Full entry sequence so we */ + ADD A0FrP,A0StP,#0 /* can make sub-calls */ + MSETL [A0StP],D0FrT,D0.5,D0.6 /* and preserve our result */ + ORT D0Ar2,D0Ar2,#TBICTX_XCBF_BIT /* Add in XCBF save request */ + MOV D0.5,D0Ar2 /* Save State in DX.5 */ + MOV D1.5,D1Ar1 + OR D0.6,D0Ar4,D0Ar6 /* Save TrigMask in D0.6 */ + MOVT D1RtP,#HI(___TBICtxSave) /* Save catch buffer */ + CALL D1RtP,#LO(___TBICtxSave) + MOV TXMASKI,D0.6 /* Allow Ints */ + MOV D0Re0,D0.5 /* Return State */ + MOV D1Re0,D1.5 + MGETL D0FrT,D0.5,D0.6,[A0FrP] /* Full exit sequence */ + SUB A0StP,A0FrP,#(8*3) + MOV A0FrP,D0FrT + MOV PC,D1RtP + .size ___TBINestInts2,.-___TBINestInts2 + +/* + * void *__TBICtxSave( TBIRES State, void *pExt ) + * + * D0Ar2 contains TBICTX_*_BIT values that control what + * extended data is to be saved beyond the end of D1Ar1. + * These bits must be ored into the SaveMask of this structure. + * + * Virtually all possible scratch registers are used. + * + * The D1Ar1 parameter is only used as the basis for saving + * CBUF state. + */ +/* + * If TBICTX_XEXT_BIT is specified in State. then State.pCtx->Ext is + * utilised to save the base address of the context save area and + * the extended states saved. The XEXT flag then indicates that the + * original state of the A0.2 and A1.2 registers from TBICTX.Ext.AX2 + * are stored as the first part of the extended state structure. + */ + .balign 4 + .global ___TBICtxSave + .type ___TBICtxSave,function +___TBICtxSave: + GETD D0Re0,[D1Ar1+#TBICTX_SaveMask-2] /* Get SaveMask */ + TSTT D0Ar2,#TBICTX_XDX8_BIT+TBICTX_XAXX_BIT+TBICTX_XHL2_BIT+TBICTX_XTDP_BIT+TBICTX_XEXT_BIT + /* Just XCBF to save? */ + MOV A0.2,D1Ar3 /* Save pointer into A0.2 */ + MOV A1.2,D1RtP /* Free off D0FrT:D1RtP pair */ + BZ $LCtxSaveCBUF /* Yes: Only XCBF may be saved */ + TSTT D0Ar2,#TBICTX_XEXT_BIT /* Extended base-state model? */ + BZ $LCtxSaveXDX8 + GETL D0Ar6,D1Ar5,[D1Ar1+#TBICTX_Ext_AX2] /* Get A0.2, A1.2 state */ + MOV D0Ar4,D0Ar2 /* Extract Ctx.SaveFlags value */ + ANDMT D0Ar4,D0Ar4,#TBICTX_XDX8_BIT+TBICTX_XAXX_BIT+TBICTX_XHL2_BIT+TBICTX_XTDP_BIT+TBICTX_XEXT_BIT + SETD [D1Ar1+#TBICTX_Ext_Ctx_pExt],A0.2 + SETD [D1Ar1+#TBICTX_Ext_Ctx_SaveMask-2],D0Ar4 + SETL [A0.2++],D0Ar6,D1Ar5 /* Save A0.2, A1.2 state */ +$LCtxSaveXDX8: + TSTT D0Ar2,#TBICTX_XDX8_BIT /* Save extended DX regs? */ + BZ $LCtxSaveXAXX +/* + * Save 8 extra DX registers + */ + MSETL [A0.2],D0.8,D0.9,D0.10,D0.11,D0.12,D0.13,D0.14,D0.15 +$LCtxSaveXAXX: + TSTT D0Ar2,#TBICTX_XAXX_BIT /* Save extended AX regs? */ + SWAP D0Re0,A0.2 /* pDst into D0Re0 */ + BZ $LCtxSaveXHL2 +/* + * Save 4 extra AX registers + */ + MSETL [D0Re0], A0_4 A0.5,A0.6,A0.7 /* Save 8*3 bytes */ +$LCtxSaveXHL2: + TSTT D0Ar2,#TBICTX_XHL2_BIT /* Save hardware-loop regs? */ + SWAP D0Re0,A0.2 /* pDst back into A0.2 */ + MOV D0Ar6,TXL1START + MOV D1Ar5,TXL2START + BZ $LCtxSaveXTDP +/* + * Save hardware loop registers + */ + SETL [A0.2++],D0Ar6,D1Ar5 /* Save 8*1 bytes */ + MOV D0Ar6,TXL1END + MOV D1Ar5,TXL2END + MOV D0FrT,TXL1COUNT + MOV D1RtP,TXL2COUNT + MSETL [A0.2],D0Ar6,D0FrT /* Save 8*2 bytes */ +/* + * Clear loop counters to disable any current loops + */ + XOR TXL1COUNT,D0FrT,D0FrT + XOR TXL2COUNT,D1RtP,D1RtP +$LCtxSaveXTDP: + TSTT D0Ar2,#TBICTX_XTDP_BIT /* Save per-thread DSP regs? */ + BZ $LCtxSaveCBUF +/* + * Save per-thread DSP registers; ACC.0, PR.0, PI.1-3 (PI.0 is zero) + */ +#ifndef CTX_NO_DSP +D SETL [A0.2++],AC0.0,AC1.0 /* Save ACx.0 lower 32-bits */ +DH SETL [A0.2++],AC0.0,AC1.0 /* Save ACx.0 upper 32-bits */ +D SETL [A0.2++],D0AR.0,D1AR.0 /* Save DSP RAM registers */ +D SETL [A0.2++],D0AR.1,D1AR.1 +D SETL [A0.2++],D0AW.0,D1AW.0 +D SETL [A0.2++],D0AW.1,D1AW.1 +D SETL [A0.2++],D0BR.0,D1BR.0 +D SETL [A0.2++],D0BR.1,D1BR.1 +D SETL [A0.2++],D0BW.0,D1BW.0 +D SETL [A0.2++],D0BW.1,D1BW.1 +D SETL [A0.2++],D0ARI.0,D1ARI.0 +D SETL [A0.2++],D0ARI.1,D1ARI.1 +D SETL [A0.2++],D0AWI.0,D1AWI.0 +D SETL [A0.2++],D0AWI.1,D1AWI.1 +D SETL [A0.2++],D0BRI.0,D1BRI.0 +D SETL [A0.2++],D0BRI.1,D1BRI.1 +D SETL [A0.2++],D0BWI.0,D1BWI.0 +D SETL [A0.2++],D0BWI.1,D1BWI.1 +D SETD [A0.2++],T0 +D SETD [A0.2++],T1 +D SETD [A0.2++],T2 +D SETD [A0.2++],T3 +D SETD [A0.2++],T4 +D SETD [A0.2++],T5 +D SETD [A0.2++],T6 +D SETD [A0.2++],T7 +D SETD [A0.2++],T8 +D SETD [A0.2++],T9 +D SETD [A0.2++],TA +D SETD [A0.2++],TB +D SETD [A0.2++],TC +D SETD [A0.2++],TD +D SETD [A0.2++],TE +D SETD [A0.2++],TF +#else + ADD A0.2,A0.2,#(8*18+4*16) +#endif + MOV D0Ar6,TXMRSIZE + MOV D1Ar5,TXDRSIZE + SETL [A0.2++],D0Ar6,D1Ar5 /* Save 8*1 bytes */ + +$LCtxSaveCBUF: +#ifdef TBI_1_3 + MOV D0Ar4,D0Re0 /* Copy Ctx Flags */ + ANDT D0Ar4,D0Ar4,#TBICTX_XCBF_BIT /* mask XCBF if already set */ + XOR D0Ar4,D0Ar4,#-1 + AND D0Ar2,D0Ar2,D0Ar4 /* remove XCBF if already set */ +#endif + TSTT D0Ar2,#TBICTX_XCBF_BIT /* Want to save CBUF? */ + ANDT D0Ar2,D0Ar2,#TBICTX_XDX8_BIT+TBICTX_XAXX_BIT+TBICTX_XHL2_BIT+TBICTX_XTDP_BIT+TBICTX_XEXT_BIT + OR D0Ar2,D0Ar2,D0Re0 /* Generate new SaveMask */ + SETD [D1Ar1+#TBICTX_SaveMask-2],D0Ar2/* Add in bits saved to TBICTX */ + MOV D0Re0,A0.2 /* Return end of save area */ + MOV D0Ar4,TXDIVTIME /* Get TXDIVTIME */ + MOVZ PC,A1.2 /* No: Early return */ + TSTT D0Ar2,#TBICTX_CBUF_BIT+TBICTX_CBRP_BIT /* Need to save CBUF? */ + MOVZ PC,A1.2 /* No: Early return */ + ORT D0Ar2,D0Ar2,#TBICTX_XCBF_BIT + SETD [D1Ar1+#TBICTX_SaveMask-2],D0Ar2/* Add in XCBF bit to TBICTX */ + ADD A0.2,D1Ar1,#TBICTX_BYTES /* Dump CBUF state after TBICTX */ +/* + * Save CBUF + */ + SETD [A0.2+# 0],TXCATCH0 /* Restore TXCATCHn */ + SETD [A0.2+# 4],TXCATCH1 + TSTT D0Ar2,#TBICTX_CBRP_BIT /* ... RDDIRTY was/is set */ + SETD [A0.2+# 8],TXCATCH2 + SETD [A0.2+#12],TXCATCH3 + BZ $LCtxSaveComplete + SETL [A0.2+#(2*8)],RD /* Save read pipeline */ + SETL [A0.2+#(3*8)],RD /* Save read pipeline */ + SETL [A0.2+#(4*8)],RD /* Save read pipeline */ + SETL [A0.2+#(5*8)],RD /* Save read pipeline */ + SETL [A0.2+#(6*8)],RD /* Save read pipeline */ + SETL [A0.2+#(7*8)],RD /* Save read pipeline */ + AND TXDIVTIME,D0Ar4,#TXDIVTIME_DIV_BITS /* Clear RPDIRTY */ +$LCtxSaveComplete: + MOV PC,A1.2 /* Return */ + .size ___TBICtxSave,.-___TBICtxSave + +/* + * void *__TBICtxRestore( TBIRES State, void *pExt ) + * + * D0Ar2 contains TBICTX_*_BIT values that control what + * extended data is to be recovered from D1Ar3 (pExt). + * + * Virtually all possible scratch registers are used. + */ +/* + * If TBICTX_XEXT_BIT is specified in State. Then the saved state of + * the orginal A0.2 and A1.2 is restored from pExt and the XEXT + * related flags are removed from State.pCtx->SaveMask. + * + */ + .balign 4 + .global ___TBICtxRestore + .type ___TBICtxRestore,function +___TBICtxRestore: + GETD D0Ar6,[D1Ar1+#TBICTX_CurrMODE] /* Get TXMODE Value */ + ANDST D0Ar2,D0Ar2,#TBICTX_XDX8_BIT+TBICTX_XAXX_BIT+TBICTX_XHL2_BIT+TBICTX_XTDP_BIT+TBICTX_XEXT_BIT + MOV D1Re0,D0Ar2 /* Keep flags in D1Re0 */ + MOV D0Re0,D1Ar3 /* D1Ar3 is default result */ + MOVZ PC,D1RtP /* Early return, nothing to do */ + ANDT D0Ar6,D0Ar6,#0xE000 /* Top bits of TXMODE required */ + MOV A0.3,D0Ar6 /* Save TXMODE for later */ + TSTT D1Re0,#TBICTX_XEXT_BIT /* Check for XEXT bit */ + BZ $LCtxRestXDX8 + GETD D0Ar4,[D1Ar1+#TBICTX_SaveMask-2]/* Get current SaveMask */ + GETL D0Ar6,D1Ar5,[D0Re0++] /* Restore A0.2, A1.2 state */ + ANDMT D0Ar4,D0Ar4,#(0xFFFF-(TBICTX_XDX8_BIT+TBICTX_XAXX_BIT+TBICTX_XHL2_BIT+TBICTX_XTDP_BIT+TBICTX_XEXT_BIT)) + SETD [D1Ar1+#TBICTX_SaveMask-2],D0Ar4/* New SaveMask */ +#ifdef METAC_1_0 + SETD [D1Ar1+#TBICTX_Ext_AX2_U0],D0Ar6 + MOV D0Ar6,D1Ar1 + SETD [D0Ar6+#TBICTX_Ext_AX2_U1],D1Ar5 +#else + SETL [D1Ar1+#TBICTX_Ext_AX2],D0Ar6,D1Ar5 +#endif +$LCtxRestXDX8: + TSTT D1Re0,#TBICTX_XDX8_BIT /* Get extended DX regs? */ + MOV A1.2,D1RtP /* Free off D1RtP register */ + BZ $LCtxRestXAXX +/* + * Restore 8 extra DX registers + */ + MGETL D0.8,D0.9,D0.10,D0.11,D0.12,D0.13,D0.14,D0.15,[D0Re0] +$LCtxRestXAXX: + TSTT D1Re0,#TBICTX_XAXX_BIT /* Get extended AX regs? */ + BZ $LCtxRestXHL2 +/* + * Restore 3 extra AX registers + */ + MGETL A0_4 A0.5,A0.6,A0.7,[D0Re0] /* Get 8*3 bytes */ +$LCtxRestXHL2: + TSTT D1Re0,#TBICTX_XHL2_BIT /* Get hardware-loop regs? */ + BZ $LCtxRestXTDP +/* + * Get hardware loop registers + */ + MGETL D0Ar6,D0Ar4,D0Ar2,[D0Re0] /* Get 8*3 bytes */ + MOV TXL1START,D0Ar6 + MOV TXL2START,D1Ar5 + MOV TXL1END,D0Ar4 + MOV TXL2END,D1Ar3 + MOV TXL1COUNT,D0Ar2 + MOV TXL2COUNT,D1Ar1 +$LCtxRestXTDP: + TSTT D1Re0,#TBICTX_XTDP_BIT /* Get per-thread DSP regs? */ + MOVZ PC,A1.2 /* No: Early return */ +/* + * Get per-thread DSP registers; ACC.0, PR.0, PI.1-3 (PI.0 is zero) + */ + MOV A0.2,D0Re0 + GETL D0Ar6,D1Ar5,[D0Re0++#((16*4)+(18*8))] +#ifndef CTX_NO_DSP +D GETL AC0.0,AC1.0,[A0.2++] /* Restore ACx.0 lower 32-bits */ +DH GETL AC0.0,AC1.0,[A0.2++] /* Restore ACx.0 upper 32-bits */ +#else + ADD A0.2,A0.2,#(2*8) +#endif + ADD D0Re0,D0Re0,#(2*4) + MOV TXMODE,A0.3 /* Some TXMODE bits needed */ + MOV TXMRSIZE,D0Ar6 + MOV TXDRSIZE,D1Ar5 +#ifndef CTX_NO_DSP +D GETL D0AR.0,D1AR.0,[A0.2++] /* Restore DSP RAM registers */ +D GETL D0AR.1,D1AR.1,[A0.2++] +D GETL D0AW.0,D1AW.0,[A0.2++] +D GETL D0AW.1,D1AW.1,[A0.2++] +D GETL D0BR.0,D1BR.0,[A0.2++] +D GETL D0BR.1,D1BR.1,[A0.2++] +D GETL D0BW.0,D1BW.0,[A0.2++] +D GETL D0BW.1,D1BW.1,[A0.2++] +#else + ADD A0.2,A0.2,#(8*8) +#endif + MOV TXMODE,#0 /* Restore TXMODE */ +#ifndef CTX_NO_DSP +D GETL D0ARI.0,D1ARI.0,[A0.2++] +D GETL D0ARI.1,D1ARI.1,[A0.2++] +D GETL D0AWI.0,D1AWI.0,[A0.2++] +D GETL D0AWI.1,D1AWI.1,[A0.2++] +D GETL D0BRI.0,D1BRI.0,[A0.2++] +D GETL D0BRI.1,D1BRI.1,[A0.2++] +D GETL D0BWI.0,D1BWI.0,[A0.2++] +D GETL D0BWI.1,D1BWI.1,[A0.2++] +D GETD T0,[A0.2++] +D GETD T1,[A0.2++] +D GETD T2,[A0.2++] +D GETD T3,[A0.2++] +D GETD T4,[A0.2++] +D GETD T5,[A0.2++] +D GETD T6,[A0.2++] +D GETD T7,[A0.2++] +D GETD T8,[A0.2++] +D GETD T9,[A0.2++] +D GETD TA,[A0.2++] +D GETD TB,[A0.2++] +D GETD TC,[A0.2++] +D GETD TD,[A0.2++] +D GETD TE,[A0.2++] +D GETD TF,[A0.2++] +#else + ADD A0.2,A0.2,#(8*8+4*16) +#endif + MOV PC,A1.2 /* Return */ + .size ___TBICtxRestore,.-___TBICtxRestore + +/* + * End of tbictx.S + */ diff --git a/arch/metag/tbx/tbictxfpu.S b/arch/metag/tbx/tbictxfpu.S new file mode 100644 index 000000000000..e773bea3e7bd --- /dev/null +++ b/arch/metag/tbx/tbictxfpu.S @@ -0,0 +1,190 @@ +/* + * tbictxfpu.S + * + * Copyright (C) 2009, 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. + * + * Explicit state save and restore routines forming part of the thread binary + * interface for META processors + */ + + .file "tbifpuctx.S" + +#include <asm/metag_regs.h> +#include <asm/tbx.h> + +#ifdef TBI_1_4 +/* + * void *__TBICtxFPUSave( TBIRES State, void *pExt ) + * + * D0Ar2 contains TBICTX_*_BIT values that control what + * extended data is to be saved. + * These bits must be ored into the SaveMask of this structure. + * + * Virtually all possible scratch registers are used. + */ + .text + .balign 4 + .global ___TBICtxFPUSave + .type ___TBICtxFPUSave,function +___TBICtxFPUSave: + + /* D1Ar1:D0Ar2 - State + * D1Ar3 - pExt + * D0Ar4 - Value of METAC_CORE_ID + * D1Ar5 - Scratch + * D0Ar6 - Scratch + */ + + /* If the FPAC bit isnt set then there is nothing to do */ + TSTT D0Ar2,#TBICTX_FPAC_BIT + MOVZ PC, D1RtP + + /* Obtain the Core config */ + MOVT D0Ar4, #HI(METAC_CORE_ID) + ADD D0Ar4, D0Ar4, #LO(METAC_CORE_ID) + GETD D0Ar4, [D0Ar4] + + /* Detect FX.8 - FX.15 and add to core config */ + MOV D0Ar6, TXENABLE + AND D0Ar6, D0Ar6, #(TXENABLE_CLASSALT_FPUR8 << TXENABLE_CLASS_S) + AND D0Ar4, D0Ar4, #LO(0x0000FFFF) + ORT D0Ar4, D0Ar4, #HI(TBICTX_CFGFPU_FX16_BIT) + XOR D0Ar4, D0Ar4, D0Ar6 + + /* Save the relevant bits to the buffer */ + SETD [D1Ar3++], D0Ar4 + + /* Save the relevant bits of TXDEFR (Assumes TXDEFR is coherent) ... */ + MOV D0Ar6, TXDEFR + LSR D0Re0, D0Ar6, #8 + AND D0Re0, D0Re0, #LO(TXDEFR_FPE_FE_BITS>>8) + AND D0Ar6, D0Ar6, #LO(TXDEFR_FPE_ICTRL_BITS) + OR D0Re0, D0Re0, D0Ar6 + + /* ... along with relevant bits of TXMODE to buffer */ + MOV D0Ar6, TXMODE + ANDT D0Ar6, D0Ar6, #HI(TXMODE_FPURMODE_BITS) + ORT D0Ar6, D0Ar6, #HI(TXMODE_FPURMODEWRITE_BIT) + OR D0Ar6, D0Ar6, D0Re0 + SETD [D1Ar3++], D0Ar6 + + GETD D0Ar6,[D1Ar1+#TBICTX_SaveMask-2] /* Get the current SaveMask */ + /* D0Ar6 - pCtx->SaveMask */ + + TSTT D0Ar4, #HI(TBICTX_CFGFPU_FX16_BIT) /* Perform test here for extended FPU registers + * to avoid stalls + */ + /* Save the standard FPU registers */ +F MSETL [D1Ar3++], FX.0, FX.2, FX.4, FX.6 + + /* Save the extended FPU registers if they are present */ + BZ $Lskip_save_fx8_fx16 +F MSETL [D1Ar3++], FX.8, FX.10, FX.12, FX.14 +$Lskip_save_fx8_fx16: + + /* Save the FPU Accumulator if it is present */ + TST D0Ar4, #METAC_COREID_NOFPACC_BIT + BNZ $Lskip_save_fpacc +F SETL [D1Ar3++], ACF.0 +F SETL [D1Ar3++], ACF.1 +F SETL [D1Ar3++], ACF.2 +$Lskip_save_fpacc: + + /* Update pCtx->SaveMask */ + ANDT D0Ar2, D0Ar2, #TBICTX_FPAC_BIT + OR D0Ar6, D0Ar6, D0Ar2 + SETD [D1Ar1+#TBICTX_SaveMask-2],D0Ar6/* Add in XCBF bit to TBICTX */ + + MOV D0Re0, D1Ar3 /* Return end of save area */ + MOV PC, D1RtP + + .size ___TBICtxFPUSave,.-___TBICtxFPUSave + +/* + * void *__TBICtxFPURestore( TBIRES State, void *pExt ) + * + * D0Ar2 contains TBICTX_*_BIT values that control what + * extended data is to be recovered from D1Ar3 (pExt). + * + * Virtually all possible scratch registers are used. + */ +/* + * If TBICTX_XEXT_BIT is specified in State. Then the saved state of + * the orginal A0.2 and A1.2 is restored from pExt and the XEXT + * related flags are removed from State.pCtx->SaveMask. + * + */ + .balign 4 + .global ___TBICtxFPURestore + .type ___TBICtxFPURestore,function +___TBICtxFPURestore: + + /* D1Ar1:D0Ar2 - State + * D1Ar3 - pExt + * D0Ar4 - Value of METAC_CORE_ID + * D1Ar5 - Scratch + * D0Ar6 - Scratch + * D1Re0 - Scratch + */ + + /* If the FPAC bit isnt set then there is nothing to do */ + TSTT D0Ar2,#TBICTX_FPAC_BIT + MOVZ PC, D1RtP + + /* Obtain the relevant bits of the Core config */ + GETD D0Ar4, [D1Ar3++] + + /* Restore FPU related parts of TXDEFR. Assumes TXDEFR is coherent */ + GETD D1Ar5, [D1Ar3++] + MOV D0Ar6, D1Ar5 + LSL D1Re0, D1Ar5, #8 + ANDT D1Re0, D1Re0, #HI(TXDEFR_FPE_FE_BITS|TXDEFR_FPE_ICTRL_BITS) + AND D1Ar5, D1Ar5, #LO(TXDEFR_FPE_FE_BITS|TXDEFR_FPE_ICTRL_BITS) + OR D1Re0, D1Re0, D1Ar5 + + MOV D1Ar5, TXDEFR + ANDMT D1Ar5, D1Ar5, #HI(~(TXDEFR_FPE_FE_BITS|TXDEFR_FPE_ICTRL_BITS)) + ANDMB D1Ar5, D1Ar5, #LO(~(TXDEFR_FPE_FE_BITS|TXDEFR_FPE_ICTRL_BITS)) + OR D1Re0, D1Re0, D1Ar5 + MOV TXDEFR, D1Re0 + + /* Restore relevant bits of TXMODE */ + MOV D1Ar5, TXMODE + ANDMT D1Ar5, D1Ar5, #HI(~TXMODE_FPURMODE_BITS) + ANDT D0Ar6, D0Ar6, #HI(TXMODE_FPURMODE_BITS|TXMODE_FPURMODEWRITE_BIT) + OR D0Ar6, D0Ar6, D1Ar5 + MOV TXMODE, D0Ar6 + + TSTT D0Ar4, #HI(TBICTX_CFGFPU_FX16_BIT) /* Perform test here for extended FPU registers + * to avoid stalls + */ + /* Save the standard FPU registers */ +F MGETL FX.0, FX.2, FX.4, FX.6, [D1Ar3++] + + /* Save the extended FPU registers if they are present */ + BZ $Lskip_restore_fx8_fx16 +F MGETL FX.8, FX.10, FX.12, FX.14, [D1Ar3++] +$Lskip_restore_fx8_fx16: + + /* Save the FPU Accumulator if it is present */ + TST D0Ar4, #METAC_COREID_NOFPACC_BIT + BNZ $Lskip_restore_fpacc +F GETL ACF.0, [D1Ar3++] +F GETL ACF.1, [D1Ar3++] +F GETL ACF.2, [D1Ar3++] +$Lskip_restore_fpacc: + + MOV D0Re0, D1Ar3 /* Return end of save area */ + MOV PC, D1RtP + + .size ___TBICtxFPURestore,.-___TBICtxFPURestore + +#endif /* TBI_1_4 */ + +/* + * End of tbictx.S + */ diff --git a/arch/metag/tbx/tbidefr.S b/arch/metag/tbx/tbidefr.S new file mode 100644 index 000000000000..3eb165ebf540 --- /dev/null +++ b/arch/metag/tbx/tbidefr.S @@ -0,0 +1,175 @@ +/* + * tbidefr.S + * + * Copyright (C) 2009, 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. + * + * Routing deferred exceptions + */ + +#include <asm/metag_regs.h> +#include <asm/tbx.h> + + .text + .balign 4 + .global ___TBIHandleDFR + .type ___TBIHandleDFR,function +/* D1Ar1:D0Ar2 -- State + * D0Ar3 -- SigNum + * D0Ar4 -- Triggers + * D1Ar5 -- InstOrSWSId + * D0Ar6 -- pTBI (volatile) + */ +___TBIHandleDFR: +#ifdef META_BUG_MBN100212 + MSETL [A0StP++], D0FrT, D0.5 + + /* D1Ar1,D0Ar2,D1Ar5,D0Ar6 -- Arguments to handler, must be preserved + * D0Ar4 -- The deferred exceptions + * D1Ar3 -- As per D0Ar4 but just the trigger bits + * D0.5 -- The bgnd deferred exceptions + * D1.5 -- TXDEFR with bgnd re-added + */ + + /* - Collect the pending deferred exceptions using TXSTAT, + * (ack's the bgnd exceptions as a side-effect) + * - Manually collect remaining (interrupt) deferred exceptions + * using TXDEFR + * - Replace the triggers (from TXSTATI) with the int deferred + * exceptions DEFR ..., TXSTATI would have returned if it was valid + * from bgnd code + * - Reconstruct TXDEFR by or'ing bgnd deferred exceptions (except + * the DEFER bit) and the int deferred exceptions. This will be + * restored later + */ + DEFR D0.5, TXSTAT + MOV D1.5, TXDEFR + ANDT D0.5, D0.5, #HI(0xFFFF0000) + MOV D1Ar3, D1.5 + ANDT D1Ar3, D1Ar3, #HI(0xFFFF0000) + OR D0Ar4, D1Ar3, #TXSTAT_DEFER_BIT + OR D1.5, D1.5, D0.5 + + /* Mask off anything unrelated to the deferred exception triggers */ + ANDT D1Ar3, D1Ar3, #HI(TXSTAT_BUSERR_BIT | TXSTAT_FPE_BITS) + + /* Can assume that at least one exception happened since this + * handler wouldnt have been called otherwise. + * + * Replace the signal number and at the same time, prepare + * the mask to acknowledge the exception + * + * D1Re0 -- The bits to acknowledge + * D1Ar3 -- The signal number + * D1RtP -- Scratch to deal with non-conditional insns + */ + MOVT D1Re0, #HI(TXSTAT_FPE_BITS & ~TXSTAT_FPE_DENORMAL_BIT) + MOV D1RtP, #TXSTAT_FPE_INVALID_S + FFB D1Ar3, D1Ar3 + CMP D1Ar3, #TXSTAT_FPE_INVALID_S + MOVLE D1Ar3, D1RtP /* Collapse FPE triggers to a single signal */ + MOV D1RtP, #1 + LSLGT D1Re0, D1RtP, D1Ar3 + + /* Get the handler using the signal number + * + * D1Ar3 -- The signal number + * D0Re0 -- Offset into TBI struct containing handler address + * D1Re0 -- Mask of triggers to keep + * D1RtP -- Address of handler + */ + SUB D1Ar3, D1Ar3, #(TXSTAT_FPE_INVALID_S - TBID_SIGNUM_FPE) + LSL D0Re0, D1Ar3, #2 + XOR D1Re0, D1Re0, #-1 /* Prepare mask for acknowledge (avoids stall) */ + ADD D0Re0,D0Re0,#TBI_fnSigs + GETD D1RtP, [D0Ar6+D0Re0] + + /* Acknowledge triggers */ + AND D1.5, D1.5, D1Re0 + + /* Restore remaining exceptions + * Do this here in case the handler enables nested interrupts + * + * D1.5 -- TXDEFR with this exception ack'd + */ + MOV TXDEFR, D1.5 + + /* Call the handler */ + SWAP D1RtP, PC + + GETL D0.5, D1.5, [--A0StP] + GETL D0FrT, D1RtP, [--A0StP] + MOV PC,D1RtP +#else /* META_BUG_MBN100212 */ + + /* D1Ar1,D0Ar2,D1Ar5,D0Ar6 -- Arguments to handler, must be preserved + * D0Ar4 -- The deferred exceptions + * D1Ar3 -- As per D0Ar4 but just the trigger bits + */ + + /* - Collect the pending deferred exceptions using TXSTAT, + * (ack's the interrupt exceptions as a side-effect) + */ + DEFR D0Ar4, TXSTATI + + /* Mask off anything unrelated to the deferred exception triggers */ + MOV D1Ar3, D0Ar4 + ANDT D1Ar3, D1Ar3, #HI(TXSTAT_BUSERR_BIT | TXSTAT_FPE_BITS) + + /* Can assume that at least one exception happened since this + * handler wouldnt have been called otherwise. + * + * Replace the signal number and at the same time, prepare + * the mask to acknowledge the exception + * + * The unusual code for 1<<D1Ar3 may need explanation. + * Normally this would be done using 'MOV rs,#1' and 'LSL rd,rs,D1Ar3' + * but only D1Re0 is available in D1 and no crossunit insns are available + * Even worse, there is no conditional 'MOV r,#uimm8'. + * Since the CMP proves that D1Ar3 >= 20, we can reuse the bottom 12-bits + * of D1Re0 (using 'ORGT r,#1') in the knowledge that the top 20-bits will + * be discarded without affecting the result. + * + * D1Re0 -- The bits to acknowledge + * D1Ar3 -- The signal number + */ + MOVT D1Re0, #HI(TXSTAT_FPE_BITS & ~TXSTAT_FPE_DENORMAL_BIT) + MOV D0Re0, #TXSTAT_FPE_INVALID_S + FFB D1Ar3, D1Ar3 + CMP D1Ar3, #TXSTAT_FPE_INVALID_S + MOVLE D1Ar3, D0Re0 /* Collapse FPE triggers to a single signal */ + ORGT D1Re0, D1Re0, #1 + LSLGT D1Re0, D1Re0, D1Ar3 + + SUB D1Ar3, D1Ar3, #(TXSTAT_FPE_INVALID_S - TBID_SIGNUM_FPE) + + /* Acknowledge triggers and restore remaining exceptions + * Do this here in case the handler enables nested interrupts + * + * (x | y) ^ y == x & ~y. It avoids the restrictive XOR ...,#-1 insn + * and is the same length + */ + MOV D0Re0, TXDEFR + OR D0Re0, D0Re0, D1Re0 + XOR TXDEFR, D0Re0, D1Re0 + + /* Get the handler using the signal number + * + * D1Ar3 -- The signal number + * D0Re0 -- Address of handler + */ + LSL D0Re0, D1Ar3, #2 + ADD D0Re0,D0Re0,#TBI_fnSigs + GETD D0Re0, [D0Ar6+D0Re0] + + /* Tailcall the handler */ + MOV PC,D0Re0 + +#endif /* META_BUG_MBN100212 */ + .size ___TBIHandleDFR,.-___TBIHandleDFR +/* + * End of tbidefr.S + */ diff --git a/arch/metag/tbx/tbidspram.S b/arch/metag/tbx/tbidspram.S new file mode 100644 index 000000000000..2f27c0372212 --- /dev/null +++ b/arch/metag/tbx/tbidspram.S @@ -0,0 +1,161 @@ +/* + * tbidspram.S + * + * Copyright (C) 2009, 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. + * + * Explicit state save and restore routines forming part of the thread binary + * interface for META processors + */ + + .file "tbidspram.S" + +/* These aren't generally useful to a user so for now, they arent publically available */ +#define _TBIECH_DSPRAM_DUA_S 8 +#define _TBIECH_DSPRAM_DUA_BITS 0x7f00 +#define _TBIECH_DSPRAM_DUB_S 0 +#define _TBIECH_DSPRAM_DUB_BITS 0x007f + +/* + * void *__TBIDspramSaveA( short DspramSizes, void *pExt ) + */ + .text + .balign 4 + .global ___TBIDspramSaveA + .type ___TBIDspramSaveA,function +___TBIDspramSaveA: + + SETL [A0StP++], D0.5, D1.5 + MOV A0.3, D0Ar2 + + /* D1Ar1 - Dspram Sizes + * A0.4 - Pointer to buffer + */ + + /* Save the specified amount of dspram DUA */ +DL MOV D0AR.0, #0 + LSR D1Ar1, D1Ar1, #_TBIECH_DSPRAM_DUA_S + AND D1Ar1, D1Ar1, #(_TBIECH_DSPRAM_DUA_BITS >> _TBIECH_DSPRAM_DUA_S) + SUB TXRPT, D1Ar1, #1 +$L1: +DL MOV D0Re0, [D0AR.0++] +DL MOV D0Ar6, [D0AR.0++] +DL MOV D0Ar4, [D0AR.0++] +DL MOV D0.5, [D0AR.0++] + MSETL [A0.3++], D0Re0, D0Ar6, D0Ar4, D0.5 + + BR $L1 + + GETL D0.5, D1.5, [--A0StP] + MOV PC, D1RtP + + .size ___TBIDspramSaveA,.-___TBIDspramSaveA + +/* + * void *__TBIDspramSaveB( short DspramSizes, void *pExt ) + */ + .balign 4 + .global ___TBIDspramSaveB + .type ___TBIDspramSaveB,function +___TBIDspramSaveB: + + SETL [A0StP++], D0.5, D1.5 + MOV A0.3, D0Ar2 + + /* D1Ar1 - Dspram Sizes + * A0.3 - Pointer to buffer + */ + + /* Save the specified amount of dspram DUA */ +DL MOV D0BR.0, #0 + LSR D1Ar1, D1Ar1, #_TBIECH_DSPRAM_DUB_S + AND D1Ar1, D1Ar1, #(_TBIECH_DSPRAM_DUB_BITS >> _TBIECH_DSPRAM_DUB_S) + SUB TXRPT, D1Ar1, #1 +$L2: +DL MOV D0Re0, [D0BR.0++] +DL MOV D0Ar6, [D0BR.0++] +DL MOV D0Ar4, [D0BR.0++] +DL MOV D0.5, [D0BR.0++] + MSETL [A0.3++], D0Re0, D0Ar6, D0Ar4, D0.5 + + BR $L2 + + GETL D0.5, D1.5, [--A0StP] + MOV PC, D1RtP + + .size ___TBIDspramSaveB,.-___TBIDspramSaveB + +/* + * void *__TBIDspramRestoreA( short DspramSizes, void *pExt ) + */ + .balign 4 + .global ___TBIDspramRestoreA + .type ___TBIDspramRestoreA,function +___TBIDspramRestoreA: + + SETL [A0StP++], D0.5, D1.5 + MOV A0.3, D0Ar2 + + /* D1Ar1 - Dspram Sizes + * A0.3 - Pointer to buffer + */ + + /* Restore the specified amount of dspram DUA */ +DL MOV D0AW.0, #0 + LSR D1Ar1, D1Ar1, #_TBIECH_DSPRAM_DUA_S + AND D1Ar1, D1Ar1, #(_TBIECH_DSPRAM_DUA_BITS >> _TBIECH_DSPRAM_DUA_S) + SUB TXRPT, D1Ar1, #1 +$L3: + MGETL D0Re0, D0Ar6, D0Ar4, D0.5, [A0.3++] +DL MOV [D0AW.0++], D0Re0 +DL MOV [D0AW.0++], D0Ar6 +DL MOV [D0AW.0++], D0Ar4 +DL MOV [D0AW.0++], D0.5 + + BR $L3 + |