1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
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
*/
|