blob: a0838ebcb4334c106caa58fb8a9ea24366a39418 [file] [log] [blame]
/*
* 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
*/