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>
This commit is contained in:
parent
4ca151b208
commit
027f891f76
136
arch/metag/tbx/tbicore.S
Normal file
136
arch/metag/tbx/tbicore.S
Normal file
@ -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
|
||||
*/
|
366
arch/metag/tbx/tbictx.S
Normal file
366
arch/metag/tbx/tbictx.S
Normal file
@ -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
|
||||
*/
|
190
arch/metag/tbx/tbictxfpu.S
Normal file
190
arch/metag/tbx/tbictxfpu.S
Normal file
@ -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
|
||||
*/
|
175
arch/metag/tbx/tbidefr.S
Normal file
175
arch/metag/tbx/tbidefr.S
Normal file
@ -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
|
||||
*/
|
161
arch/metag/tbx/tbidspram.S
Normal file
161
arch/metag/tbx/tbidspram.S
Normal file
@ -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
|
||||
|
||||
GETL D0.5, D1.5, [--A0StP]
|
||||
MOV PC, D1RtP
|
||||
|
||||
.size ___TBIDspramRestoreA,.-___TBIDspramRestoreA
|
||||
|
||||
/*
|
||||
* void *__TBIDspramRestoreB( short DspramSizes, void *pExt )
|
||||
*/
|
||||
.balign 4
|
||||
.global ___TBIDspramRestoreB
|
||||
.type ___TBIDspramRestoreB,function
|
||||
___TBIDspramRestoreB:
|
||||
|
||||
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 D0BW.0, #0
|
||||
LSR D1Ar1, D1Ar1, #_TBIECH_DSPRAM_DUB_S
|
||||
AND D1Ar1, D1Ar1, #(_TBIECH_DSPRAM_DUB_BITS >> _TBIECH_DSPRAM_DUB_S)
|
||||
SUB TXRPT, D1Ar1, #1
|
||||
$L4:
|
||||
MGETL D0Re0, D0Ar6, D0Ar4, D0.5, [A0.3++]
|
||||
DL MOV [D0BW.0++], D0Re0
|
||||
DL MOV [D0BW.0++], D0Ar6
|
||||
DL MOV [D0BW.0++], D0Ar4
|
||||
DL MOV [D0BW.0++], D0.5
|
||||
|
||||
BR $L4
|
||||
|
||||
GETL D0.5, D1.5, [--A0StP]
|
||||
MOV PC, D1RtP
|
||||
|
||||
.size ___TBIDspramRestoreB,.-___TBIDspramRestoreB
|
||||
|
||||
/*
|
||||
* End of tbidspram.S
|
||||
*/
|
48
arch/metag/tbx/tbilogf.S
Normal file
48
arch/metag/tbx/tbilogf.S
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* tbilogf.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.
|
||||
*
|
||||
* Defines __TBILogF trap code for debugging messages and __TBICont for debug
|
||||
* assert to be implemented on.
|
||||
*/
|
||||
|
||||
.file "tbilogf.S"
|
||||
|
||||
/*
|
||||
* Perform console printf using external debugger or host support
|
||||
*/
|
||||
.text
|
||||
.balign 4
|
||||
.global ___TBILogF
|
||||
.type ___TBILogF,function
|
||||
___TBILogF:
|
||||
MSETL [A0StP],D0Ar6,D0Ar4,D0Ar2
|
||||
SWITCH #0xC10020
|
||||
MOV D0Re0,#0
|
||||
SUB A0StP,A0StP,#24
|
||||
MOV PC,D1RtP
|
||||
.size ___TBILogF,.-___TBILogF
|
||||
|
||||
/*
|
||||
* Perform wait for continue under control of the debugger
|
||||
*/
|
||||
.text
|
||||
.balign 4
|
||||
.global ___TBICont
|
||||
.type ___TBICont,function
|
||||
___TBICont:
|
||||
MOV D0Ar6,#1
|
||||
MSETL [A0StP],D0Ar6,D0Ar4,D0Ar2
|
||||
SWITCH #0xC30006 /* Returns if we are to continue */
|
||||
SUB A0StP,A0StP,#(8*3)
|
||||
MOV PC,D1RtP /* Return */
|
||||
.size ___TBICont,.-___TBICont
|
||||
|
||||
/*
|
||||
* End of tbilogf.S
|
||||
*/
|
451
arch/metag/tbx/tbipcx.S
Normal file
451
arch/metag/tbx/tbipcx.S
Normal file
@ -0,0 +1,451 @@
|
||||
/*
|
||||
* tbipcx.S
|
||||
*
|
||||
* Copyright (C) 2001, 2002, 2007, 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.
|
||||
*
|
||||
* Asyncronous trigger handling including exceptions
|
||||
*/
|
||||
|
||||
.file "tbipcx.S"
|
||||
#include <asm/metag_regs.h>
|
||||
#include <asm/tbx.h>
|
||||
|
||||
/* BEGIN HACK */
|
||||
/* define these for now while doing inital conversion to GAS
|
||||
will fix properly later */
|
||||
|
||||
/* Signal identifiers always have the TBID_SIGNAL_BIT set and contain the
|
||||
following related bit-fields */
|
||||
#define TBID_SIGNUM_S 2
|
||||
|
||||
/* END HACK */
|
||||
|
||||
#ifdef METAC_1_0
|
||||
/* Ax.4 is saved in TBICTX */
|
||||
#define A0_4 ,A0.4
|
||||
#else
|
||||
/* Ax.4 is NOT saved in TBICTX */
|
||||
#define A0_4
|
||||
#endif
|
||||
|
||||
/* Size of the TBICTX structure */
|
||||
#define TBICTX_BYTES ((TBICTX_AX_REGS*8)+TBICTX_AX)
|
||||
|
||||
#ifdef METAC_1_1
|
||||
#ifndef BOOTROM
|
||||
#ifndef SPECIAL_BUILD
|
||||
/* Jump straight into the boot ROM version of this code */
|
||||
#define CODE_USES_BOOTROM
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Define space needed for CATCH buffer state in traditional units */
|
||||
#define CATCH_ENTRIES 5
|
||||
#define CATCH_ENTRY_BYTES 16
|
||||
|
||||
#ifndef CODE_USES_BOOTROM
|
||||
#define A0GblIStP A0.15 /* PTBICTX for current thread in PRIV system */
|
||||
#define A1GblIGbP A1.15 /* Interrupt A1GbP value in PRIV system */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* TBIRES __TBIASyncTrigger( TBIRES State )
|
||||
*/
|
||||
.text
|
||||
.balign 4
|
||||
.global ___TBIASyncTrigger
|
||||
.type ___TBIASyncTrigger,function
|
||||
___TBIASyncTrigger:
|
||||
#ifdef CODE_USES_BOOTROM
|
||||
MOVT D0Re0,#HI(LINCORE_BASE)
|
||||
JUMP D0Re0,#0xA0
|
||||
#else
|
||||
MOV D0FrT,A0FrP /* Boing entry sequence */
|
||||
ADD A0FrP,A0StP,#0
|
||||
SETL [A0StP++],D0FrT,D1RtP
|
||||
MOV D0Re0,PCX /* Check for repeat call */
|
||||
MOVT D0FrT,#HI(___TBIBoingRTI+4)
|
||||
ADD D0FrT,D0FrT,#LO(___TBIBoingRTI+4)
|
||||
CMP D0Re0,D0FrT
|
||||
BEQ ___TBIBoingExit /* Already set up - come out */
|
||||
ADD D1Ar1,D1Ar1,#7 /* PRIV system stack here */
|
||||
MOV A0.2,A0StP /* else push context here */
|
||||
MOVS D0Re0,D0Ar2 /* Return in user mode? */
|
||||
ANDMB D1Ar1,D1Ar1,#0xfff8 /* align priv stack to 64-bit */
|
||||
MOV D1Re0,D1Ar1 /* and set result to arg */
|
||||
MOVMI A0.2,D1Ar1 /* use priv stack if PRIV set */
|
||||
/*
|
||||
* Generate an initial TBICTX to return to our own current call context
|
||||
*/
|
||||
MOVT D1Ar5,#HI(___TBIBoingExit) /* Go here to return */
|
||||
ADD D1Ar5,D1Ar5,#LO(___TBIBoingExit)
|
||||
ADD A0.3,A0.2,#TBICTX_DX /* DX Save area */
|
||||
ANDT D0Ar2,D0Ar2,#TBICTX_PRIV_BIT /* Extract PRIV bit */
|
||||
MOVT D0Ar6,#TBICTX_SOFT_BIT /* Only soft thread state */
|
||||
ADD D0Ar6,D0Ar6,D0Ar2 /* Add in PRIV bit if requested */
|
||||
SETL [A0.2],D0Ar6,D1Ar5 /* Push header fields */
|
||||
ADD D0FrT,A0.2,#TBICTX_AX /* Address AX save area */
|
||||
MSETL [A0.3],D0Re0,D0Ar6,D0Ar4,D0Ar2,D0FrT,D0.5,D0.6,D0.7
|
||||
MOV D0Ar6,#0
|
||||
MOV D1Ar5,#0
|
||||
SETL [A0.3++],D0Ar6,D1Ar5 /* Zero CT register states */
|
||||
SETL [A0.3++],D0Ar6,D1Ar5
|
||||
MSETL [D0FrT],A0StP,A0FrP,A0.2,A0.3 A0_4 /* Save AX regs */
|
||||
MOV A0FrP,A0.2 /* Restore me! */
|
||||
B ___TBIResume
|
||||
.size ___TBIASyncTrigger,.-___TBIASyncTrigger
|
||||
|
||||
/*
|
||||
* Optimised return to handler for META Core
|
||||
*/
|
||||
___TBIBoingRTH:
|
||||
RTH /* Go to background level */
|
||||
MOVT A0.2, #HI($Lpcx_target)
|
||||
ADD A0.2,A0.2,#LO($Lpcx_target)
|
||||
MOV PCX,A0.2 /* Setup PCX for interrupts */
|
||||
MOV PC,D1Re0 /* Jump to handler */
|
||||
/*
|
||||
* This is where the code below needs to jump to wait for outermost interrupt
|
||||
* event in a non-privilege mode system (single shared interrupt stack).
|
||||
*/
|
||||
___TBIBoingPCX:
|
||||
MGETL A0StP,A0FrP,A0.2,A0.3 A0_4,[D1Re0] /* Restore AX regs */
|
||||
MOV TXSTATUS,D0Re0 /* Restore flags */
|
||||
GETL D0Re0,D1Re0,[D1Re0+#TBICTX_DX-TBICTX_BYTES]
|
||||
___TBIBoingRTI:
|
||||
RTI /* Wait for interrupt */
|
||||
$Lpcx_target:
|
||||
/*
|
||||
* Save initial interrupt state on current stack
|
||||
*/
|
||||
SETL [A0StP+#TBICTX_DX],D0Re0,D1Re0 /* Save key registers */
|
||||
ADD D1Re0,A0StP,#TBICTX_AX /* Address AX save area */
|
||||
MOV D0Re0,TXSTATUS /* Read TXSTATUS into D0Re0 */
|
||||
MOV TXSTATUS,#0 /* Clear TXSTATUS */
|
||||
MSETL [D1Re0],A0StP,A0FrP,A0.2,A0.3 A0_4 /* Save AX critical regs */
|
||||
/*
|
||||
* Register state at this point is-
|
||||
*
|
||||
* D0Re0 - Old TXSTATUS with PRIV and CBUF bits set if appropriate
|
||||
* A0StP - Is call stack frame and base of TBICTX being generated
|
||||
* A1GbP - Is valid static access link
|
||||
*/
|
||||
___TBIBoing:
|
||||
LOCK0 /* Make sure we have no locks! */
|
||||
ADD A1.2,A0StP,#TBICTX_DX+(8*1) /* Address DX.1 save area */
|
||||
MOV A0FrP,A0StP /* Setup frame pointer */
|
||||
MSETL [A1.2],D0Ar6,D0Ar4,D0Ar2,D0FrT,D0.5,D0.6,D0.7
|
||||
MOV D0Ar4,TXRPT /* Save critical CT regs */
|
||||
MOV D1Ar3,TXBPOBITS
|
||||
MOV D1Ar1,TXDIVTIME /* Calc catch buffer pSrc */
|
||||
MOV D0Ar2,TXMODE
|
||||
MOV TXMODE,#0 /* Clear TXMODE */
|
||||
#ifdef TXDIVTIME_RPDIRTY_BIT
|
||||
TSTT D1Ar1,#HI(TXDIVTIME_RPDIRTY_BIT)/* NZ = RPDIRTY */
|
||||
MOVT D0Ar6,#TBICTX_CBRP_BIT
|
||||
ORNZ D0Re0,D0Re0,D0Ar6 /* Set CBRP if RPDIRTY set */
|
||||
#endif
|
||||
MSETL [A1.2],D0Ar4,D0Ar2 /* Save CT regs state */
|
||||
MOV D0Ar2,D0Re0 /* Copy TXSTATUS */
|
||||
ANDMT D0Ar2,D0Ar2,#TBICTX_CBUF_BIT+TBICTX_CBRP_BIT
|
||||
#ifdef TBI_1_4
|
||||
MOVT D1Ar1,#TBICTX_FPAC_BIT /* Copy FPActive into FPAC */
|
||||
TSTT D0Re0,#HI(TXSTATUS_FPACTIVE_BIT)
|
||||
ORNZ D0Ar2,D0Ar2,D1Ar1
|
||||
#endif
|
||||
MOV D1Ar1,PCX /* Read CurrPC */
|
||||
ORT D0Ar2,D0Ar2,#TBICTX_CRIT_BIT /* SaveMask + CRIT bit */
|
||||
SETL [A0FrP+#TBICTX_Flags],D0Ar2,D1Ar1 /* Set pCtx header fields */
|
||||
/*
|
||||
* Completed context save, now we need to make a call to an interrupt handler
|
||||
*
|
||||
* D0Re0 - holds PRIV, WAIT, CBUF flags, HALT reason if appropriate
|
||||
* A0FrP - interrupt stack frame and base of TBICTX being generated
|
||||
* A0StP - same as A0FrP
|
||||
*/
|
||||
___TBIBoingWait:
|
||||
/* Reserve space for TBICTX and CBUF */
|
||||
ADD A0StP,A0StP,#TBICTX_BYTES+(CATCH_ENTRY_BYTES*CATCH_ENTRIES)
|
||||
MOV D0Ar4,TXSTATI /* Read the Triggers data */
|
||||
MOV D1Ar3,TXDIVTIME /* Read IRQEnc bits */
|
||||
MOV D0Ar2,D0Re0 /* Copy PRIV and WAIT flags */
|
||||
ANDT D0Ar2,D0Ar2,#TBICTX_PRIV_BIT+TBICTX_WAIT_BIT+TBICTX_CBUF_BIT
|
||||
#ifdef TBI_1_4
|
||||
MOVT D1Ar5,#TBICTX_FPAC_BIT /* Copy FPActive into FPAC */
|
||||
TSTT D0Re0,#HI(TXSTATUS_FPACTIVE_BIT)
|
||||
ORNZ D0Ar2,D0Ar2,D1Ar5
|
||||
#endif
|
||||
ANDT D1Ar3,D1Ar3,#HI(TXDIVTIME_IRQENC_BITS)
|
||||
LSR D1Ar3,D1Ar3,#TXDIVTIME_IRQENC_S
|
||||
AND TXSTATI,D0Ar4,#TXSTATI_BGNDHALT_BIT/* Ack any HALT seen */
|
||||
ANDS D0Ar4,D0Ar4,#0xFFFF-TXSTATI_BGNDHALT_BIT /* Only seen HALT? */
|
||||
ORT D0Ar2,D0Ar2,#TBICTX_CRIT_BIT /* Set CRIT */
|
||||
#ifndef BOOTROM
|
||||
MOVT A1LbP,#HI(___pTBIs)
|
||||
ADD A1LbP,A1LbP,#LO(___pTBIs)
|
||||
GETL D1Ar5,D0Ar6,[A1LbP] /* D0Ar6 = ___pTBIs[1] */
|
||||
#else
|
||||
/*
|
||||
* For BOOTROM support ___pTBIs must be allocated at offset 0 vs A1GbP
|
||||
*/
|
||||
GETL D1Ar5,D0Ar6,[A1GbP] /* D0Ar6 = ___pTBIs[1] */
|
||||
#endif
|
||||
BZ ___TBIBoingHalt /* Yes: Service HALT */
|
||||
/*
|
||||
* Encode interrupt as signal vector, strip away same/lower TXMASKI bits
|
||||
*/
|
||||
MOV D1Ar1,#1 /* Generate mask for this bit */
|
||||
MOV D0Re0,TXMASKI /* Get interrupt mask */
|
||||
LSL TXSTATI,D1Ar1,D1Ar3 /* Acknowledge trigger */
|
||||
AND TXMASKI,D0Re0,#TXSTATI_BGNDHALT_BIT /* Only allow HALTs */
|
||||
OR D0Ar2,D0Ar2,D0Re0 /* Set TBIRES.Sig.TrigMask */
|
||||
ADD D1Ar3,D1Ar3,#TBID_SIGNUM_TRT /* Offset into interrupt sigs */
|
||||
LSL D0Re0,D1Ar3,#TBID_SIGNUM_S /* Generate offset from SigNum */
|
||||
/*
|
||||
* This is a key moment we are about to call the handler, register state is
|
||||
* as follows-
|
||||
*
|
||||
* D0Re0 - Handler vector (SigNum<<TBID_SIGNUM_S)
|
||||
* D0Ar2 - TXMASKI:TBICTX_CRIT_BIT with optional CBUF and PRIV bits
|
||||
* D1Ar3 - SigNum
|
||||
* D0Ar4 - State read from TXSTATI
|
||||
* D1Ar5 - Inst for SWITCH trigger case only, otherwise undefined
|
||||
* D0Ar6 - pTBI
|
||||
*/
|
||||
___TBIBoingVec:
|
||||
ADD D0Re0,D0Re0,#TBI_fnSigs /* Offset into signal table */
|
||||
GETD D1Re0,[D0Ar6+D0Re0] /* Get address for Handler */
|
||||
/*
|
||||
* Call handler at interrupt level, when it returns simply resume execution
|
||||
* of state indicated by D1Re0.
|
||||
*/
|
||||
MOV D1Ar1,A0FrP /* Pass in pCtx */
|
||||
CALLR D1RtP,___TBIBoingRTH /* Use RTH to invoke handler */
|
||||
|
||||
/*
|
||||
* Perform critical state restore and execute background thread.
|
||||
*
|
||||
* A0FrP - is pointer to TBICTX structure to resume
|
||||
* D0Re0 - contains additional TXMASKI triggers
|
||||
*/
|
||||
.text
|
||||
.balign 4
|
||||
#ifdef BOOTROM
|
||||
.global ___TBIResume
|
||||
#endif
|
||||
___TBIResume:
|
||||
/*
|
||||
* New META IP method
|
||||
*/
|
||||
RTH /* Go to interrupt level */
|
||||
MOV D0Ar4,TXMASKI /* Read TXMASKI */
|
||||
OR TXMASKI,D0Ar4,D0Re0 /* -Write-Modify TXMASKI */
|
||||
GETL D0Re0,D1Re0,[A0FrP+#TBICTX_Flags]/* Get Flags:SaveMask, CurrPC */
|
||||
MOV A0StP,A0FrP /* Position stack pointer */
|
||||
MOV D0Ar2,TXPOLLI /* Read pending triggers */
|
||||
MOV PCX,D1Re0 /* Set resumption PC */
|
||||
TST D0Ar2,#0xFFFF /* Any pending triggers? */
|
||||
BNZ ___TBIBoingWait /* Yes: Go for triggers */
|
||||
TSTT D0Re0,#TBICTX_WAIT_BIT /* Do we WAIT anyway? */
|
||||
BNZ ___TBIBoingWait /* Yes: Go for triggers */
|
||||
LSLS D1Ar5,D0Re0,#1 /* Test XCBF (MI) & PRIV (CS)? */
|
||||
ADD D1Re0,A0FrP,#TBICTX_CurrRPT /* Address CT save area */
|
||||
ADD A0StP,A0FrP,#TBICTX_DX+(8*1) /* Address DX.1 save area */
|
||||
MGETL A0.2,A0.3,[D1Re0] /* Get CT reg states */
|
||||
MOV D1Ar3,A1.3 /* Copy old TXDIVTIME */
|
||||
BPL ___TBIResCrit /* No: Skip logic */
|
||||
ADD D0Ar4,A0FrP,#TBICTX_BYTES /* Source is after TBICTX */
|
||||
ANDST D1Ar3,D1Ar3,#HI(TXDIVTIME_RPMASK_BITS)/* !Z if RPDIRTY */
|
||||
MGETL D0.5,D0.6,[D0Ar4] /* Read Catch state */
|
||||
MOV TXCATCH0,D0.5 /* Restore TXCATCHn */
|
||||
MOV TXCATCH1,D1.5
|
||||
MOV TXCATCH2,D0.6
|
||||
MOV TXCATCH3,D1.6
|
||||
BZ ___TBIResCrit
|
||||
MOV D0Ar2,#(1*8)
|
||||
LSRS D1Ar3,D1Ar3,#TXDIVTIME_RPMASK_S+1 /* 2nd RPMASK bit -> bit 0 */
|
||||
ADD RA,D0Ar4,#(0*8) /* Re-read read pipeline */
|
||||
ADDNZ RA,D0Ar4,D0Ar2 /* If Bit 0 set issue RA */
|
||||
LSRS D1Ar3,D1Ar3,#2 /* Bit 1 -> C, Bit 2 -> Bit 0 */
|
||||
ADD D0Ar2,D0Ar2,#8
|
||||
ADDCS RA,D0Ar4,D0Ar2 /* If C issue RA */
|
||||
ADD D0Ar2,D0Ar2,#8
|
||||
ADDNZ RA,D0Ar4,D0Ar2 /* If Bit 0 set issue RA */
|
||||
LSRS D1Ar3,D1Ar3,#2 /* Bit 1 -> C, Bit 2 -> Bit 0 */
|
||||
ADD D0Ar2,D0Ar2,#8
|
||||
ADDCS RA,D0Ar4,D0Ar2 /* If C issue RA */
|
||||
ADD D0Ar2,D0Ar2,#8
|
||||
ADDNZ RA,D0Ar4,D0Ar2 /* If Bit 0 set issue RA */
|
||||
MOV TXDIVTIME,A1.3 /* Set RPDIRTY again */
|
||||
___TBIResCrit:
|
||||
LSLS D1Ar5,D0Re0,#1 /* Test XCBF (MI) & PRIV (CS)? */
|
||||
#ifdef TBI_1_4
|
||||
ANDT D1Ar5,D1Ar5,#(TBICTX_FPAC_BIT*2)
|
||||
LSL D0Ar6,D1Ar5,#3 /* Convert FPAC into FPACTIVE */
|
||||
#endif
|
||||
ANDMT D0Re0,D0Re0,#TBICTX_CBUF_BIT /* Keep CBUF bit from SaveMask */
|
||||
#ifdef TBI_1_4
|
||||
OR D0Re0,D0Re0,D0Ar6 /* Combine FPACTIVE with others */
|
||||
#endif
|
||||
MGETL D0Ar6,D0Ar4,D0Ar2,D0FrT,D0.5,D0.6,D0.7,[A0StP] /* Restore DX */
|
||||
MOV TXRPT,A0.2 /* Restore CT regs */
|
||||
MOV TXBPOBITS,A1.2
|
||||
MOV TXMODE,A0.3
|
||||
BCC ___TBIBoingPCX /* Do non-PRIV wait! */
|
||||
MOV A1GblIGbP,A1GbP /* Save A1GbP too */
|
||||
MGETL A0StP,A0FrP,A0.2,A0.3 A0_4,[D1Re0] /* Restore AX regs */
|
||||
/*
|
||||
* Wait for the first interrupt/exception trigger in a privilege mode system
|
||||
* (interrupt stack area for current TASK to be pointed to by A0GblIStP
|
||||
* or per_cpu__stack_save[hwthread_id]).
|
||||
*/
|
||||
MOV TXSTATUS,D0Re0 /* Restore flags */
|
||||
MOV D0Re0,TXPRIVEXT /* Set TXPRIVEXT_TXTOGGLEI_BIT */
|
||||
SUB D1Re0,D1Re0,#TBICTX_BYTES /* TBICTX is top of int stack */
|
||||
#ifdef TBX_PERCPU_SP_SAVE
|
||||
SWAP D1Ar3,A1GbP
|
||||
MOV D1Ar3,TXENABLE /* Which thread are we? */
|
||||
AND D1Ar3,D1Ar3,#TXENABLE_THREAD_BITS
|
||||
LSR D1Ar3,D1Ar3,#TXENABLE_THREAD_S-2
|
||||
ADDT D1Ar3,D1Ar3,#HI(_per_cpu__stack_save)
|
||||
ADD D1Ar3,D1Ar3,#LO(_per_cpu__stack_save)
|
||||
SETD [D1Ar3],D1Re0
|
||||
SWAP D1Ar3,A1GbP
|
||||
#else
|
||||
MOV A0GblIStP, D1Re0
|
||||
#endif
|
||||
OR D0Re0,D0Re0,#TXPRIVEXT_TXTOGGLEI_BIT
|
||||
MOV TXPRIVEXT,D0Re0 /* Cannot set TXPRIVEXT if !priv */
|
||||
GETL D0Re0,D1Re0,[D1Re0+#TBICTX_DX]
|
||||
RTI /* Wait for interrupt */
|
||||
/*
|
||||
* Save initial interrupt state on A0GblIStP, switch to A0GblIStP if
|
||||
* BOOTROM code, save and switch to [A1GbP] otherwise.
|
||||
*/
|
||||
___TBIBoingPCXP:
|
||||
#ifdef TBX_PERCPU_SP_SAVE
|
||||
SWAP D1Ar3,A1GbP /* Get PRIV stack base */
|
||||
MOV D1Ar3,TXENABLE /* Which thread are we? */
|
||||
AND D1Ar3,D1Ar3,#TXENABLE_THREAD_BITS
|
||||
LSR D1Ar3,D1Ar3,#TXENABLE_THREAD_S-2
|
||||
ADDT D1Ar3,D1Ar3,#HI(_per_cpu__stack_save)
|
||||
ADD D1Ar3,D1Ar3,#LO(_per_cpu__stack_save)
|
||||
GETD D1Ar3,[D1Ar3]
|
||||
#else
|
||||
SWAP D1Ar3,A0GblIStP /* Get PRIV stack base */
|
||||
#endif
|
||||
SETL [D1Ar3+#TBICTX_DX],D0Re0,D1Re0 /* Save key registers */
|
||||
MOV D0Re0,TXPRIVEXT /* Clear TXPRIVEXT_TXTOGGLEI_BIT */
|
||||
ADD D1Re0,D1Ar3,#TBICTX_AX /* Address AX save area */
|
||||
ANDMB D0Re0,D0Re0,#0xFFFF-TXPRIVEXT_TXTOGGLEI_BIT
|
||||
MOV TXPRIVEXT,D0Re0 /* Cannot set TXPRIVEXT if !priv */
|
||||
MOV D0Re0,TXSTATUS /* Read TXSTATUS into D0Re0 */
|
||||
MOV TXSTATUS,#0 /* Clear TXSTATUS */
|
||||
MSETL [D1Re0],A0StP,A0FrP,A0.2,A0.3 A0_4 /* Save AX critical regs */
|
||||
MOV A0StP,D1Ar3 /* Switch stacks */
|
||||
#ifdef TBX_PERCPU_SP_SAVE
|
||||
MOV D1Ar3,A1GbP /* Get D1Ar2 back */
|
||||
#else
|
||||
MOV D1Ar3,A0GblIStP /* Get D1Ar2 back */
|
||||
#endif
|
||||
ORT D0Re0,D0Re0,#TBICTX_PRIV_BIT /* Add PRIV to TXSTATUS */
|
||||
MOV A1GbP,A1GblIGbP /* Restore A1GbP */
|
||||
B ___TBIBoing /* Enter common handler code */
|
||||
/*
|
||||
* At this point we know it's a background HALT case we are handling.
|
||||
* The restored TXSTATUS always needs to have zero in the reason bits.
|
||||
*/
|
||||
___TBIBoingHalt:
|
||||
MOV D0Ar4,TXMASKI /* Get interrupt mask */
|
||||
ANDST D0Re0,D0Re0,#HI(TXSTATUS_MAJOR_HALT_BITS+TXSTATUS_MEM_FAULT_BITS)
|
||||
AND TXMASKI,D0Ar4,#TXSTATI_BGNDHALT_BIT /* Only allow HALTs */
|
||||
AND D0Ar4,D0Ar4,#0xFFFF-TXSTATI_BGNDHALT_BIT /* What ints are off? */
|
||||
OR D0Ar2,D0Ar2,D0Ar4 /* Set TBIRES.Sig.TrigMask */
|
||||
MOV D0Ar4,#TXSTATI_BGNDHALT_BIT /* This was the trigger state */
|
||||
LSR D1Ar3,D0Re0,#TXSTATUS_MAJOR_HALT_S
|
||||
MOV D0Re0,#TBID_SIGNUM_XXF<<TBID_SIGNUM_S
|
||||
BNZ ___TBIBoingVec /* Jump to XXF exception handler */
|
||||
/*
|
||||
* Only the SWITCH cases are left, PCX must be valid
|
||||
*/
|
||||
#ifdef TBI_1_4
|
||||
MOV D1Ar5,TXPRIVEXT
|
||||
TST D1Ar5,#TXPRIVEXT_MINIMON_BIT
|
||||
LSR D1Ar3,D1Ar1,#1 /* Shift needed for MINIM paths (fill stall) */
|
||||
BZ $Lmeta /* If META only, skip */
|
||||
TSTT D1Ar1,#HI(0x00800000)
|
||||
ANDMT D1Ar3,D1Ar3,#HI(0x007FFFFF >> 1)/* Shifted mask for large MINIM */
|
||||
ANDT D1Ar1,D1Ar1,#HI(0xFFE00000) /* Static mask for small MINIM */
|
||||
BZ $Llarge_minim /* If large MINIM */
|
||||
$Lsmall_minim:
|
||||
TSTT D1Ar3,#HI(0x00100000 >> 1)
|
||||
ANDMT D1Ar3,D1Ar3,#HI(0x001FFFFF >> 1)/* Correct shifted mask for large MINIM */
|
||||
ADDZ D1Ar1,D1Ar1,D1Ar3 /* If META rgn, add twice to undo LSR #1 */
|
||||
B $Lrecombine
|
||||
$Llarge_minim:
|
||||
ANDST D1Ar1,D1Ar1,#HI(0xFF800000) /* Correct static mask for small MINIM */
|
||||
/* Z=0 (Cannot place code at NULL) */
|
||||
$Lrecombine:
|
||||
ADD D1Ar1,D1Ar1,D1Ar3 /* Combine static and shifted parts */
|
||||
$Lmeta:
|
||||
GETW D1Ar5,[D1Ar1++] /* META: lo-16, MINIM: lo-16 (all-16 if short) */
|
||||
GETW D1Ar3,[D1Ar1] /* META: hi-16, MINIM: hi-16 (only if long) */
|
||||
MOV D1Re0,D1Ar5
|
||||
XOR D1Re0,D1Re0,#0x4000
|
||||
LSLSNZ D1Re0,D1Re0,#(32-14) /* MINIM: If long C=0, if short C=1 */
|
||||
LSLCC D1Ar3,D1Ar3,#16 /* META/MINIM long: Move hi-16 up */
|
||||
LSLCS D1Ar3,D1Ar5,#16 /* MINIM short: Dup all-16 */
|
||||
ADD D1Ar5,D1Ar5,D1Ar3 /* ALL: Combine both 16-bit parts */
|
||||
#else
|
||||
GETD D1Ar5,[D1Ar1] /* Read instruction for switch */
|
||||
#endif
|
||||
LSR D1Ar3,D1Ar5,#22 /* Convert into signal number */
|
||||
AND D1Ar3,D1Ar3,#TBID_SIGNUM_SW3-TBID_SIGNUM_SW0
|
||||
LSL D0Re0,D1Ar3,#TBID_SIGNUM_S /* Generate offset from SigNum */
|
||||
B ___TBIBoingVec /* Jump to switch handler */
|
||||
/*
|
||||
* Exit from TBIASyncTrigger call
|
||||
*/
|
||||
___TBIBoingExit:
|
||||
GETL D0FrT,D1RtP,[A0FrP++] /* Restore state from frame */
|
||||
SUB A0StP,A0FrP,#8 /* Unwind stack */
|
||||
MOV A0FrP,D0FrT /* Last memory read completes */
|
||||
MOV PC,D1RtP /* Return to caller */
|
||||
#endif /* ifdef CODE_USES_BOOTROM */
|
||||
.size ___TBIResume,.-___TBIResume
|
||||
|
||||
#ifndef BOOTROM
|
||||
/*
|
||||
* void __TBIASyncResume( TBIRES State )
|
||||
*/
|
||||
.text
|
||||
.balign 4
|
||||
.global ___TBIASyncResume
|
||||
.type ___TBIASyncResume,function
|
||||
___TBIASyncResume:
|
||||
/*
|
||||
* Perform CRIT|SOFT state restore and execute background thread.
|
||||
*/
|
||||
MOV D1Ar3,D1Ar1 /* Restore this context */
|
||||
MOV D0Re0,D0Ar2 /* Carry in additional triggers */
|
||||
/* Reserve space for TBICTX */
|
||||
ADD D1Ar3,D1Ar3,#TBICTX_BYTES+(CATCH_ENTRY_BYTES*CATCH_ENTRIES)
|
||||
MOV A0StP,D1Ar3 /* Enter with protection of */
|
||||
MOV A0FrP,D1Ar1 /* TBICTX on our stack */
|
||||
#ifdef CODE_USES_BOOTROM
|
||||
MOVT D1Ar1,#HI(LINCORE_BASE)
|
||||
JUMP D1Ar1,#0xA4
|
||||
#else
|
||||
B ___TBIResume
|
||||
#endif
|
||||
.size ___TBIASyncResume,.-___TBIASyncResume
|
||||
#endif /* ifndef BOOTROM */
|
||||
|
||||
/*
|
||||
* End of tbipcx.S
|
||||
*/
|
87
arch/metag/tbx/tbiroot.S
Normal file
87
arch/metag/tbx/tbiroot.S
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* tbiroot.S
|
||||
*
|
||||
* Copyright (C) 2001, 2002, 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.
|
||||
*
|
||||
* Module that creates and via ___TBI function returns a TBI Root Block for
|
||||
* interrupt and background processing on the current thread.
|
||||
*/
|
||||
|
||||
.file "tbiroot.S"
|
||||
#include <asm/metag_regs.h>
|
||||
|
||||
/*
|
||||
* Get data structures and defines from the TBI C header
|
||||
*/
|
||||
#include <asm/tbx.h>
|
||||
|
||||
|
||||
/* If signals need to be exchanged we must create a TBI Root Block */
|
||||
|
||||
.data
|
||||
.balign 8
|
||||
.global ___pTBIs
|
||||
.type ___pTBIs,object
|
||||
___pTBIs:
|
||||
.long 0 /* Bgnd+Int root block ptrs */
|
||||
.long 0
|
||||
.size ___pTBIs,.-___pTBIs
|
||||
|
||||
|
||||
/*
|
||||
* Return ___pTBIs value specific to execution level with promotion/demotion
|
||||
*
|
||||
* Register Usage: D1Ar1 is Id, D0Re0 is the primary result
|
||||
* D1Re0 is secondary result (___pTBIs for other exec level)
|
||||
*/
|
||||
.text
|
||||
.balign 4
|
||||
.global ___TBI
|
||||
.type ___TBI,function
|
||||
___TBI:
|
||||
TSTT D1Ar1,#HI(TBID_ISTAT_BIT) /* Bgnd or Int level? */
|
||||
MOVT A1LbP,#HI(___pTBIs)
|
||||
ADD A1LbP,A1LbP,#LO(___pTBIs)
|
||||
GETL D0Re0,D1Re0,[A1LbP] /* Base of root block table */
|
||||
SWAPNZ D0Re0,D1Re0 /* Swap if asked */
|
||||
MOV PC,D1RtP
|
||||
.size ___TBI,.-___TBI
|
||||
|
||||
|
||||
/*
|
||||
* Return identifier of the current thread in TBI segment or signal format with
|
||||
* secondary mask to indicate privilege and interrupt level of thread
|
||||
*/
|
||||
.text
|
||||
.balign 4
|
||||
.global ___TBIThrdPrivId
|
||||
.type ___TBIThrdPrivId,function
|
||||
___TBIThrdPrivId:
|
||||
.global ___TBIThreadId
|
||||
.type ___TBIThreadId,function
|
||||
___TBIThreadId:
|
||||
#ifndef METAC_0_1
|
||||
MOV D1Re0,TXSTATUS /* Are we privileged or int? */
|
||||
MOV D0Re0,TXENABLE /* Which thread are we? */
|
||||
/* Disable privilege adaption for now */
|
||||
ANDT D1Re0,D1Re0,#HI(TXSTATUS_ISTAT_BIT) /* +TXSTATUS_PSTAT_BIT) */
|
||||
LSL D1Re0,D1Re0,#TBID_ISTAT_S-TXSTATUS_ISTAT_S
|
||||
AND D0Re0,D0Re0,#TXENABLE_THREAD_BITS
|
||||
LSL D0Re0,D0Re0,#TBID_THREAD_S-TXENABLE_THREAD_S
|
||||
#else
|
||||
/* Thread 0 only */
|
||||
XOR D0Re0,D0Re0,D0Re0
|
||||
XOR D1Re0,D1Re0,D1Re0
|
||||
#endif
|
||||
MOV PC,D1RtP /* Return */
|
||||
.size ___TBIThrdPrivId,.-___TBIThrdPrivId
|
||||
.size ___TBIThreadId,.-___TBIThreadId
|
||||
|
||||
|
||||
/*
|
||||
* End of tbiroot.S
|
||||
*/
|
237
arch/metag/tbx/tbisoft.S
Normal file
237
arch/metag/tbx/tbisoft.S
Normal file
@ -0,0 +1,237 @@
|
||||
/*
|
||||
* tbisoft.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.
|
||||
*
|
||||
* Support for soft threads and soft context switches
|
||||
*/
|
||||
|
||||
.file "tbisoft.S"
|
||||
|
||||
#include <asm/tbx.h>
|
||||
|
||||
#ifdef METAC_1_0
|
||||
/* Ax.4 is saved in TBICTX */
|
||||
#define A0_4 ,A0.4
|
||||
#define D0_5 ,D0.5
|
||||
#else
|
||||
/* Ax.4 is NOT saved in TBICTX */
|
||||
#define A0_4
|
||||
#define D0_5
|
||||
#endif
|
||||
|
||||
/* Size of the TBICTX structure */
|
||||
#define TBICTX_BYTES ((TBICTX_AX_REGS*8)+TBICTX_AX)
|
||||
|
||||
.text
|
||||
.balign 4
|
||||
.global ___TBISwitchTail
|
||||
.type ___TBISwitchTail,function
|
||||
___TBISwitchTail:
|
||||
B $LSwitchTail
|
||||
.size ___TBISwitchTail,.-___TBISwitchTail
|
||||
|
||||
/*
|
||||
* TBIRES __TBIJumpX( TBIX64 ArgsA, PTBICTX *rpSaveCtx, int TrigsMask,
|
||||
* void (*fnMain)(), void *pStack );
|
||||
*
|
||||
* This is a combination of __TBISwitch and __TBIJump with the context of
|
||||
* the calling thread being saved in the rpSaveCtx location with a drop-thru
|
||||
* effect into the __TBIJump logic. ArgsB passes via __TBIJump to the
|
||||
* routine eventually invoked will reflect the rpSaveCtx value specified.
|
||||
*/
|
||||
.text
|
||||
.balign 4
|
||||
.global ___TBIJumpX
|
||||
.type ___TBIJumpX,function
|
||||
___TBIJumpX:
|
||||
CMP D1RtP,#-1
|
||||
B $LSwitchStart
|
||||
.size ___TBIJumpX,.-___TBIJumpX
|
||||
|
||||
/*
|
||||
* TBIRES __TBISwitch( TBIRES Switch, PTBICTX *rpSaveCtx )
|
||||
*
|
||||
* Software syncronous context switch between soft threads, save only the
|
||||
* registers which are actually valid on call entry.
|
||||
*
|
||||
* A0FrP, D0RtP, D0.5, D0.6, D0.7 - Saved on stack
|
||||
* A1GbP is global to all soft threads so not virtualised
|
||||
* A0StP is then saved as the base of the TBICTX of the thread
|
||||
*
|
||||
*/
|
||||
.text
|
||||
.balign 4
|
||||
.global ___TBISwitch
|
||||
.type ___TBISwitch,function
|
||||
___TBISwitch:
|
||||
XORS D0Re0,D0Re0,D0Re0 /* Set ZERO flag */
|
||||
$LSwitchStart:
|
||||
MOV D0FrT,A0FrP /* Boing entry sequence */
|
||||
ADD A0FrP,A0StP,#0
|
||||
SETL [A0StP+#8++],D0FrT,D1RtP
|
||||
/*
|
||||
* Save current frame state - we save all regs because we don't want
|
||||
* uninitialised crap in the TBICTX structure that the asyncronous resumption
|
||||
* of a thread will restore.
|
||||
*/
|
||||
MOVT D1Re0,#HI($LSwitchExit) /* ASync resume point here */
|
||||
ADD D1Re0,D1Re0,#LO($LSwitchExit)
|
||||
SETD [D1Ar3],A0StP /* Record pCtx of this thread */
|
||||
MOVT D0Re0,#TBICTX_SOFT_BIT /* Only soft thread state */
|
||||
SETL [A0StP++],D0Re0,D1Re0 /* Push header fields */
|
||||
ADD D0FrT,A0StP,#TBICTX_AX-TBICTX_DX /* Address AX save area */
|
||||
MOV D0Re0,#0 /* Setup 0:0 result for ASync */
|
||||
MOV D1Re0,#0 /* resume of the thread */
|
||||
MSETL [A0StP],D0Re0,D0Ar6,D0Ar4,D0Ar2,D0FrT,D0.5,D0.6,D0.7
|
||||
SETL [A0StP++],D0Re0,D1Re0 /* Zero CurrRPT, CurrBPOBITS, */
|
||||
SETL [A0StP++],D0Re0,D1Re0 /* Zero CurrMODE, CurrDIVTIME */
|
||||
ADD A0StP,A0StP,#(TBICTX_AX_REGS*8) /* Reserve AX save space */
|
||||
MSETL [D0FrT],A0StP,A0FrP,A0.2,A0.3 A0_4 /* Save AX regs */
|
||||
BNZ ___TBIJump
|
||||
/*
|
||||
* NextThread MUST be in TBICTX_SOFT_BIT state!
|
||||
*/
|
||||
$LSwitchTail:
|
||||
MOV D0Re0,D0Ar2 /* Result from args */
|
||||
MOV D1Re0,D1Ar1
|
||||
ADD D1RtP,D1Ar1,#TBICTX_AX
|
||||
MGETL A0StP,A0FrP,[D1RtP] /* Get frame values */
|
||||
$LSwitchCmn:
|
||||
ADD A0.2,D1Ar1,#TBICTX_DX+(8*5)
|
||||
MGETL D0.5,D0.6,D0.7,[A0.2] /* Get caller-saved DX regs */
|
||||
$LSwitchExit:
|
||||
GETL D0FrT,D1RtP,[A0FrP++] /* Restore state from frame */
|
||||
SUB A0StP,A0FrP,#8 /* Unwind stack */
|
||||
MOV A0FrP,D0FrT /* Last memory read completes */
|
||||
MOV PC,D1RtP /* Return to caller */
|
||||
.size ___TBISwitch,.-___TBISwitch
|
||||
|
||||
/*
|
||||
* void __TBISyncResume( TBIRES State, int TrigMask );
|
||||
*
|
||||
* 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 ored into TXMASKI during the
|
||||
* context switch such that any immediately occuring interrupts occur in
|
||||
* the context of the newly specified task. The State.Sig.SaveMask parameter
|
||||
* is ignored.
|
||||
*/
|
||||
.text
|
||||
.balign 4
|
||||
.global ___TBISyncResume
|
||||
.type ___TBISyncResume,function
|
||||
___TBISyncResume:
|
||||
MOV D0Re0,D0Ar2 /* Result from args */
|
||||
MOV D1Re0,D1Ar1
|
||||
XOR D1Ar5,D1Ar5,D1Ar5 /* D1Ar5 = 0 */
|
||||
ADD D1RtP,D1Ar1,#TBICTX_AX
|
||||
SWAP D1Ar5,TXMASKI /* D1Ar5 <-> TXMASKI */
|
||||
MGETL A0StP,A0FrP,[D1RtP] /* Get frame values */
|
||||
OR TXMASKI,D1Ar5,D1Ar3 /* New TXMASKI */
|
||||
B $LSwitchCmn
|
||||
.size ___TBISyncResume,.-___TBISyncResume
|
||||
|
||||
/*
|
||||
* void __TBIJump( TBIX64 ArgsA, TBIX32 ArgsB, int TrigsMask,
|
||||
* void (*fnMain)(), void *pStack );
|
||||
*
|
||||
* Jump directly to a new routine on an arbitrary stack with arbitrary args
|
||||
* oring bits back into TXMASKI on route.
|
||||
*/
|
||||
.text
|
||||
.balign 4
|
||||
.global ___TBIJump
|
||||
.type ___TBIJump,function
|
||||
___TBIJump:
|
||||
XOR D0Re0,D0Re0,D0Re0 /* D0Re0 = 0 */
|
||||
MOV A0StP,D0Ar6 /* Stack = Frame */
|
||||
SWAP D0Re0,TXMASKI /* D0Re0 <-> TXMASKI */
|
||||
MOV A0FrP,D0Ar6
|
||||
MOVT A1LbP,#HI(__exit)
|
||||
ADD A1LbP,A1LbP,#LO(__exit)
|
||||
MOV D1RtP,A1LbP /* D1RtP = __exit */
|
||||
OR TXMASKI,D0Re0,D0Ar4 /* New TXMASKI */
|
||||
MOV PC,D1Ar5 /* Jump to fnMain */
|
||||
.size ___TBIJump,.-___TBIJump
|
||||
|
||||
/*
|
||||
* PTBICTX __TBISwitchInit( void *pStack, int (*fnMain)(),
|
||||
* .... 4 extra 32-bit args .... );
|
||||
*
|
||||
* Generate a new soft thread context ready for it's first outing.
|
||||
*
|
||||
* D1Ar1 - Region of memory to be used as the new soft thread stack
|
||||
* D0Ar2 - Main line routine for new soft thread
|
||||
* D1Ar3, D0Ar4, D1Ar5, D0Ar6 - arguments to be passed on stack
|
||||
* The routine returns the initial PTBICTX value for the new thread
|
||||
*/
|
||||
.text
|
||||
.balign 4
|
||||
.global ___TBISwitchInit
|
||||
.type ___TBISwitchInit,function
|
||||
___TBISwitchInit:
|
||||
MOV D0FrT,A0FrP /* Need save return point */
|
||||
ADD A0FrP,A0StP,#0
|
||||
SETL [A0StP++],D0FrT,D1RtP /* Save return to caller */
|
||||
MOVT A1LbP,#HI(__exit)
|
||||
ADD A1LbP,A1LbP,#LO(__exit)
|
||||
MOV D1RtP,A1LbP /* Get address of __exit */
|
||||
ADD D1Ar1,D1Ar1,#7 /* Align stack to 64-bits */
|
||||
ANDMB D1Ar1,D1Ar1,#0xfff8 /* by rounding base up */
|
||||
MOV A0.2,D1Ar1 /* A0.2 is new stack */
|
||||
MOV D0FrT,D1Ar1 /* Initial puesdo-frame pointer */
|
||||
SETL [A0.2++],D0FrT,D1RtP /* Save return to __exit */
|
||||
MOV D1RtP,D0Ar2
|
||||
SETL [A0.2++],D0FrT,D1RtP /* Save return to fnMain */
|
||||
ADD D0FrT,D0FrT,#8 /* Advance puesdo-frame pointer */
|
||||
MSETL [A0.2],D0Ar6,D0Ar4 /* Save extra initial args */
|
||||
MOVT D1RtP,#HI(___TBIStart) /* Start up code for new stack */
|
||||
ADD D1RtP,D1RtP,#LO(___TBIStart)
|
||||
SETL [A0.2++],D0FrT,D1RtP /* Save return to ___TBIStart */
|
||||
ADD D0FrT,D0FrT,#(8*3) /* Advance puesdo-frame pointer */
|
||||
MOV D0Re0,A0.2 /* Return pCtx for new thread */
|
||||
MOV D1Re0,#0 /* pCtx:0 is default Arg1:Arg2 */
|
||||
/*
|
||||
* Generate initial TBICTX state
|
||||
*/
|
||||
MOVT D1Ar1,#HI($LSwitchExit) /* Async restore code */
|
||||
ADD D1Ar1,D1Ar1,#LO($LSwitchExit)
|
||||
MOVT D0Ar2,#TBICTX_SOFT_BIT /* Only soft thread state */
|
||||
ADD D0Ar6,A0.2,#TBICTX_BYTES /* New A0StP */
|
||||
MOV D1Ar5,A1GbP /* Same A1GbP */
|
||||
MOV D0Ar4,D0FrT /* Initial A0FrP */
|
||||
MOV D1Ar3,A1LbP /* Same A1LbP */
|
||||
SETL [A0.2++],D0Ar2,D1Ar1 /* Set header fields */
|
||||
MSETL [A0.2],D0Re0,D0Ar6,D0Ar4,D0Ar2,D0FrT,D0.5,D0.6,D0.7
|
||||
MOV D0Ar2,#0 /* Zero values */
|
||||
MOV D1Ar1,#0
|
||||
SETL [A0.2++],D0Ar2,D1Ar1 /* Zero CurrRPT, CurrBPOBITS, */
|
||||
SETL [A0.2++],D0Ar2,D1Ar1 /* CurrMODE, and pCurrCBuf */
|
||||
MSETL [A0.2],D0Ar6,D0Ar4,D0Ar2,D0FrT D0_5 /* Set DX and then AX regs */
|
||||
B $LSwitchExit /* All done! */
|
||||
.size ___TBISwitchInit,.-___TBISwitchInit
|
||||
|
||||
.text
|
||||
.balign 4
|
||||
.global ___TBIStart
|
||||
.type ___TBIStart,function
|
||||
___TBIStart:
|
||||
MOV D1Ar1,D1Re0 /* Pass TBIRES args to call */
|
||||
MOV D0Ar2,D0Re0
|
||||
MGETL D0Re0,D0Ar6,D0Ar4,[A0FrP] /* Get hidden args */
|
||||
SUB A0StP,A0FrP,#(8*3) /* Entry stack pointer */
|
||||
MOV A0FrP,D0Re0 /* Entry frame pointer */
|
||||
MOVT A1LbP,#HI(__exit)
|
||||
ADD A1LbP,A1LbP,#LO(__exit)
|
||||
MOV D1RtP,A1LbP /* D1RtP = __exit */
|
||||
MOV PC,D1Re0 /* Jump into fnMain */
|
||||
.size ___TBIStart,.-___TBIStart
|
||||
|
||||
/*
|
||||
* End of tbisoft.S
|
||||
*/
|
114
arch/metag/tbx/tbistring.c
Normal file
114
arch/metag/tbx/tbistring.c
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* tbistring.c
|
||||
*
|
||||
* Copyright (C) 2001, 2002, 2003, 2005, 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.
|
||||
*
|
||||
* String table functions provided as part of the thread binary interface for
|
||||
* Meta processors
|
||||
*/
|
||||
|
||||
#include <linux/export.h>
|
||||
#include <linux/string.h>
|
||||
#include <asm/tbx.h>
|
||||
|
||||
/*
|
||||
* There are not any functions to modify the string table currently, if these
|
||||
* are required at some later point I suggest having a seperate module and
|
||||
* ensuring that creating new entries does not interfere with reading old
|
||||
* entries in any way.
|
||||
*/
|
||||
|
||||
const TBISTR *__TBIFindStr(const TBISTR *start,
|
||||
const char *str, int match_len)
|
||||
{
|
||||
const TBISTR *search = start;
|
||||
bool exact = true;
|
||||
const TBISEG *seg;
|
||||
|
||||
if (match_len < 0) {
|
||||
/* Make match_len always positive for the inner loop */
|
||||
match_len = -match_len;
|
||||
exact = false;
|
||||
} else {
|
||||
/*
|
||||
* Also support historic behaviour, which expected match_len to
|
||||
* include null terminator
|
||||
*/
|
||||
if (match_len && str[match_len-1] == '\0')
|
||||
match_len--;
|
||||
}
|
||||
|
||||
if (!search) {
|
||||
/* Find global string table segment */
|
||||
seg = __TBIFindSeg(NULL, TBID_SEG(TBID_THREAD_GLOBAL,
|
||||
TBID_SEGSCOPE_GLOBAL,
|
||||
TBID_SEGTYPE_STRING));
|
||||
|
||||
if (!seg || seg->Bytes < sizeof(TBISTR))
|
||||
/* No string table! */
|
||||
return NULL;
|
||||
|
||||
/* Start of string table */
|
||||
search = seg->pGAddr;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
while (!search->Tag)
|
||||
/* Allow simple gaps which are just zero initialised */
|
||||
search = (const TBISTR *)((const char *)search + 8);
|
||||
|
||||
if (search->Tag == METAG_TBI_STRE) {
|
||||
/* Reached the end of the table */
|
||||
search = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((search->Len >= match_len) &&
|
||||
(!exact || (search->Len == match_len + 1)) &&
|
||||
(search->Tag != METAG_TBI_STRG)) {
|
||||
/* Worth searching */
|
||||
if (!strncmp(str, (const char *)search->String,
|
||||
match_len))
|
||||
break;
|
||||
}
|
||||
|
||||
/* Next entry */
|
||||
search = (const TBISTR *)((const char *)search + search->Bytes);
|
||||
}
|
||||
|
||||
return search;
|
||||
}
|
||||
|
||||
const void *__TBITransStr(const char *str, int len)
|
||||
{
|
||||
const TBISTR *search = NULL;
|
||||
const void *res = NULL;
|
||||
|
||||
for (;;) {
|
||||
/* Search onwards */
|
||||
search = __TBIFindStr(search, str, len);
|
||||
|
||||
/* No translation returns NULL */
|
||||
if (!search)
|
||||
break;
|
||||
|
||||
/* Skip matching entries with no translation data */
|
||||
if (search->TransLen != METAG_TBI_STRX) {
|
||||
/* Calculate base of translation string */
|
||||
res = (const char *)search->String +
|
||||
((search->Len + 7) & ~7);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Next entry */
|
||||
search = (const TBISTR *)((const char *)search + search->Bytes);
|
||||
}
|
||||
|
||||
/* Return base address of translation data or NULL */
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL(__TBITransStr);
|
207
arch/metag/tbx/tbitimer.S
Normal file
207
arch/metag/tbx/tbitimer.S
Normal file
@ -0,0 +1,207 @@
|
||||
/*
|
||||
* tbitimer.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.
|
||||
*
|
||||
* TBI timer support routines and data values
|
||||
*/
|
||||
|
||||
.file "tbitimer.S"
|
||||
/*
|
||||
* Get data structures and defines from the main C header
|
||||
*/
|
||||
#include <asm/tbx.h>
|
||||
|
||||
.data
|
||||
.balign 8
|
||||
.global ___TBITimeB
|
||||
.type ___TBITimeB,object
|
||||
___TBITimeB:
|
||||
.quad 0 /* Background 'lost' ticks */
|
||||
.size ___TBITimeB,.-___TBITimeB
|
||||
|
||||
.data
|
||||
.balign 8
|
||||
.global ___TBITimeI
|
||||
.type ___TBITimeI,object
|
||||
___TBITimeI:
|
||||
.quad 0 /* Interrupt 'lost' ticks */
|
||||
.size ___TBITimeI,.-___TBITimeI
|
||||
|
||||
.data
|
||||
.balign 8
|
||||
.global ___TBITimes
|
||||
.type ___TBITimes,object
|
||||
___TBITimes:
|
||||
.long ___TBITimeB /* Table of 'lost' tick values */
|
||||
.long ___TBITimeI
|
||||
.size ___TBITimes,.-___TBITimes
|
||||
|
||||
/*
|
||||
* Flag bits for control of ___TBITimeCore
|
||||
*/
|
||||
#define TIMER_SET_BIT 1
|
||||
#define TIMER_ADD_BIT 2
|
||||
|
||||
/*
|
||||
* Initialise or stop timer support
|
||||
*
|
||||
* Register Usage: D1Ar1 holds Id, D1Ar2 is initial delay or 0
|
||||
* D0FrT is used to call ___TBITimeCore
|
||||
* D0Re0 is used for the result which is TXSTAT_TIMER_BIT
|
||||
* D0Ar4, D1Ar5, D0Ar6 are all used as scratch
|
||||
* Other registers are those set by ___TBITimeCore
|
||||
* A0.3 is assumed to point at ___TBITime(I/B)
|
||||
*/
|
||||
.text
|
||||
.balign 4
|
||||
.global ___TBITimerCtrl
|
||||
.type ___TBITimerCtrl,function
|
||||
___TBITimerCtrl:
|
||||
MOV D1Ar5,#TIMER_SET_BIT /* Timer SET request */
|
||||
MOVT D0FrT,#HI(___TBITimeCore) /* Get timer core reg values */
|
||||
CALL D0FrT,#LO(___TBITimeCore) /* and perform register update */
|
||||
NEGS D0Ar6,D0Ar2 /* Set flags from time-stamp */
|
||||
ASR D1Ar5,D0Ar6,#31 /* Sign extend D0Ar6 into D1Ar5 */
|
||||
SETLNZ [A0.3],D0Ar6,D1Ar5 /* ___TBITime(B/I)=-Start if enable */
|
||||
MOV PC,D1RtP /* Return */
|
||||
.size ___TBITimerCtrl,.-___TBITimerCtrl
|
||||
|
||||
/*
|
||||
* Return ___TBITimeStamp value
|
||||
*
|
||||
* Register Usage: D1Ar1 holds Id
|
||||
* D0FrT is used to call ___TBITimeCore
|
||||
* D0Re0, D1Re0 is used for the result
|
||||
* D1Ar3, D0Ar4, D1Ar5
|
||||
* Other registers are those set by ___TBITimeCore
|
||||
* D0Ar6 is assumed to be the timer value read
|
||||
* A0.3 is assumed to point at ___TBITime(I/B)
|
||||
*/
|
||||
.text
|
||||
.balign 4
|
||||
.global ___TBITimeStamp
|
||||
.type ___TBITimeStamp,function
|
||||
___TBITimeStamp:
|
||||
MOV D1Ar5,#0 /* Timer GET request */
|
||||
MOVT D0FrT,#HI(___TBITimeCore) /* Get timer core reg values */
|
||||
CALL D0FrT,#LO(___TBITimeCore) /* with no register update */
|
||||
ADDS D0Re0,D0Ar4,D0Ar6 /* Add current time value */
|
||||
ADD D1Re0,D1Ar3,D1Ar5 /* to 64-bit signed extend time */
|
||||
ADDCS D1Re0,D1Re0,#1 /* Support borrow too */
|
||||
MOV PC,D1RtP /* Return */
|
||||
.size ___TBITimeStamp,.-___TBITimeStamp
|
||||
|
||||
/*
|
||||
* Perform ___TBITimerAdd logic
|
||||
*
|
||||
* Register Usage: D1Ar1 holds Id, D0Ar2 holds value to be added to the timer
|
||||
* D0Re0 is used for the result - new TIMER value
|
||||
* D1Ar5, D0Ar6 are used as scratch
|
||||
* Other registers are those set by ___TBITimeCore
|
||||
* D0Ar6 is assumed to be the timer value read
|
||||
* D0Ar4, D1Ar3 is the current value of ___TBITime(B/I)
|
||||
*/
|
||||
.text
|
||||
.balign 4
|
||||
.global ___TBITimerAdd
|
||||
.type ___TBITimerAdd,function
|
||||
___TBITimerAdd:
|
||||
MOV D1Ar5,#TIMER_ADD_BIT /* Timer ADD request */
|
||||
MOVT D0FrT,#HI(___TBITimeCore) /* Get timer core reg values */
|
||||
CALL D0FrT,#LO(___TBITimeCore) /* with no register update */
|
||||
ADD D0Re0,D0Ar2,D0Ar6 /* Regenerate new value = result */
|
||||
NEG D0Ar2,D0Ar2 /* Negate delta */
|
||||
ASR D1Re0,D0Ar2,#31 /* Sign extend negated delta */
|
||||
ADDS D0Ar4,D0Ar4,D0Ar2 /* Add time added to ... */
|
||||
ADD D1Ar3,D1Ar3,D1Re0 /* ... real timer ... */
|
||||
ADDCS D1Ar3,D1Ar3,#1 /* ... with carry */
|
||||
SETL [A0.3],D0Ar4,D1Ar3 /* Update ___TBITime(B/I) */
|
||||
MOV PC,D1RtP /* Return */
|
||||
.size ___TBITimerAdd,.-___TBITimerAdd
|
||||
|
||||
#ifdef TBI_1_4
|
||||
/*
|
||||
* Perform ___TBITimerDeadline logic
|
||||
* NB: Delays are positive compared to the Wait values which are -ive
|
||||
*
|
||||
* Register Usage: D1Ar1 holds Id
|
||||
* D0Ar2 holds Delay requested
|
||||
* D0Re0 is used for the result - old TIMER Delay value
|
||||
* D1Ar5, D0Ar6 are used as scratch
|
||||
* Other registers are those set by ___TBITimeCore
|
||||
* D0Ar6 is assumed to be the timer value read
|
||||
* D0Ar4, D1Ar3 is the current value of ___TBITime(B/I)
|
||||
*
|
||||
*/
|
||||
.text
|
||||
.type ___TBITimerDeadline,function
|
||||
.global ___TBITimerDeadline
|
||||
.align 2
|
||||
___TBITimerDeadline:
|
||||
MOV D1Ar5,#TIMER_SET_BIT /* Timer SET request */
|
||||
MOVT D0FrT,#HI(___TBITimeCore) /* Get timer core reg values */
|
||||
CALL D0FrT,#LO(___TBITimeCore) /* with no register update */
|
||||
MOV D0Re0,D0Ar6 /* Old value read = result */
|
||||
SUB D0Ar2,D0Ar6,D0Ar2 /* Delta from (old - new) */
|
||||
ASR D1Re0,D0Ar2,#31 /* Sign extend delta */
|
||||
ADDS D0Ar4,D0Ar4,D0Ar2 /* Add time added to ... */
|
||||
ADD D1Ar3,D1Ar3,D1Re0 /* ... real timer ... */
|
||||
ADDCS D1Ar3,D1Ar3,#1 /* ... with carry */
|
||||
SETL [A0.3],D0Ar4,D1Ar3 /* Update ___TBITime(B/I) */
|
||||
MOV PC,D1RtP /* Return */
|
||||
.size ___TBITimerDeadline,.-___TBITimerDeadline
|
||||
#endif /* TBI_1_4 */
|
||||
|
||||
/*
|
||||
* Perform core timer access logic
|
||||
*
|
||||
* Register Usage: D1Ar1 holds Id, D0Ar2 holds input value for SET and
|
||||
* input value for ADD
|
||||
* D1Ar5 controls op as SET or ADD as bit values
|
||||
* On return D0Ar6, D1Ar5 holds the old 64-bit timer value
|
||||
* A0.3 is setup to point at ___TBITime(I/B)
|
||||
* A1.3 is setup to point at ___TBITimes
|
||||
* D0Ar4, D1Ar3 is setup to value of ___TBITime(I/B)
|
||||
*/
|
||||
.text
|
||||
.balign 4
|
||||
.global ___TBITimeCore
|
||||
.type ___TBITimeCore,function
|
||||
___TBITimeCore:
|
||||
#ifndef METAC_0_1
|
||||
TSTT D1Ar1,#HI(TBID_ISTAT_BIT) /* Interrupt level timer? */
|
||||
#endif
|
||||
MOVT A1LbP,#HI(___TBITimes)
|
||||
ADD A1LbP,A1LbP,#LO(___TBITimes)
|
||||
MOV A1.3,A1LbP /* Get ___TBITimes address */
|
||||
#ifndef METAC_0_1
|
||||
BNZ $LTimeCoreI /* Yes: Service TXTIMERI! */
|
||||
#endif
|
||||
LSRS D1Ar5,D1Ar5,#1 /* Carry = SET, Zero = !ADD */
|
||||
GETD A0.3,[A1.3+#0] /* A0.3 == &___TBITimeB */
|
||||
MOV D0Ar6,TXTIMER /* Always GET old value */
|
||||
MOVCS TXTIMER,D0Ar2 /* Conditional SET operation */
|
||||
ADDNZ TXTIMER,D0Ar2,D0Ar6 /* Conditional ADD operation */
|
||||
#ifndef METAC_0_1
|
||||
B $LTimeCoreEnd
|
||||
$LTimeCoreI:
|
||||
LSRS D1Ar5,D1Ar5,#1 /* Carry = SET, Zero = !ADD */
|
||||
GETD A0.3,[A1.3+#4] /* A0.3 == &___TBITimeI */
|
||||
MOV D0Ar6,TXTIMERI /* Always GET old value */
|
||||
MOVCS TXTIMERI,D0Ar2 /* Conditional SET operation */
|
||||
ADDNZ TXTIMERI,D0Ar2,D0Ar6 /* Conditional ADD operation */
|
||||
$LTimeCoreEnd:
|
||||
#endif
|
||||
ASR D1Ar5,D0Ar6,#31 /* Sign extend D0Ar6 into D1Ar5 */
|
||||
GETL D0Ar4,D1Ar3,[A0.3] /* Read ___TBITime(B/I) */
|
||||
MOV PC,D0FrT /* Return quickly */
|
||||
.size ___TBITimeCore,.-___TBITimeCore
|
||||
|
||||
/*
|
||||
* End of tbitimer.S
|
||||
*/
|
Loading…
Reference in New Issue
Block a user