aboutsummaryrefslogtreecommitdiff
path: root/arch/metag/tbx/tbicore.S
blob: a0838ebcb4334c106caa58fb8a9ea24366a39418 (plain)
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
 */