summaryrefslogtreecommitdiffstats
path: root/arch/metag/tbx/tbisoft.S
blob: 0346fe8a53b1c7f8f5e738ecec6e39ea322bf37e (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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
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
 */