4 * Copyright (C) 2001, 2002, 2007, 2012 Imagination Technologies.
6 * This program is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU General Public License version 2 as published by the
8 * Free Software Foundation.
10 * Support for soft threads and soft context switches
18 /* Ax.4 is saved in TBICTX */
22 /* Ax.4 is NOT saved in TBICTX */
27 /* Size of the TBICTX structure */
28 #define TBICTX_BYTES ((TBICTX_AX_REGS*8)+TBICTX_AX)
32 .global ___TBISwitchTail
33 .type ___TBISwitchTail,function
36 .size ___TBISwitchTail,.-___TBISwitchTail
39 * TBIRES __TBIJumpX( TBIX64 ArgsA, PTBICTX *rpSaveCtx, int TrigsMask,
40 * void (*fnMain)(), void *pStack );
42 * This is a combination of __TBISwitch and __TBIJump with the context of
43 * the calling thread being saved in the rpSaveCtx location with a drop-thru
44 * effect into the __TBIJump logic. ArgsB passes via __TBIJump to the
45 * routine eventually invoked will reflect the rpSaveCtx value specified.
50 .type ___TBIJumpX,function
54 .size ___TBIJumpX,.-___TBIJumpX
57 * TBIRES __TBISwitch( TBIRES Switch, PTBICTX *rpSaveCtx )
59 * Software synchronous context switch between soft threads, save only the
60 * registers which are actually valid on call entry.
62 * A0FrP, D0RtP, D0.5, D0.6, D0.7 - Saved on stack
63 * A1GbP is global to all soft threads so not virtualised
64 * A0StP is then saved as the base of the TBICTX of the thread
70 .type ___TBISwitch,function
72 XORS D0Re0,D0Re0,D0Re0 /* Set ZERO flag */
74 MOV D0FrT,A0FrP /* Boing entry sequence */
76 SETL [A0StP+#8++],D0FrT,D1RtP
78 * Save current frame state - we save all regs because we don't want
79 * uninitialised crap in the TBICTX structure that the asynchronous resumption
80 * of a thread will restore.
82 MOVT D1Re0,#HI($LSwitchExit) /* ASync resume point here */
83 ADD D1Re0,D1Re0,#LO($LSwitchExit)
84 SETD [D1Ar3],A0StP /* Record pCtx of this thread */
85 MOVT D0Re0,#TBICTX_SOFT_BIT /* Only soft thread state */
86 SETL [A0StP++],D0Re0,D1Re0 /* Push header fields */
87 ADD D0FrT,A0StP,#TBICTX_AX-TBICTX_DX /* Address AX save area */
88 MOV D0Re0,#0 /* Setup 0:0 result for ASync */
89 MOV D1Re0,#0 /* resume of the thread */
90 MSETL [A0StP],D0Re0,D0Ar6,D0Ar4,D0Ar2,D0FrT,D0.5,D0.6,D0.7
91 SETL [A0StP++],D0Re0,D1Re0 /* Zero CurrRPT, CurrBPOBITS, */
92 SETL [A0StP++],D0Re0,D1Re0 /* Zero CurrMODE, CurrDIVTIME */
93 ADD A0StP,A0StP,#(TBICTX_AX_REGS*8) /* Reserve AX save space */
94 MSETL [D0FrT],A0StP,A0FrP,A0.2,A0.3 A0_4 /* Save AX regs */
97 * NextThread MUST be in TBICTX_SOFT_BIT state!
100 MOV D0Re0,D0Ar2 /* Result from args */
102 ADD D1RtP,D1Ar1,#TBICTX_AX
103 MGETL A0StP,A0FrP,[D1RtP] /* Get frame values */
105 ADD A0.2,D1Ar1,#TBICTX_DX+(8*5)
106 MGETL D0.5,D0.6,D0.7,[A0.2] /* Get caller-saved DX regs */
108 GETL D0FrT,D1RtP,[A0FrP++] /* Restore state from frame */
109 SUB A0StP,A0FrP,#8 /* Unwind stack */
110 MOV A0FrP,D0FrT /* Last memory read completes */
111 MOV PC,D1RtP /* Return to caller */
112 .size ___TBISwitch,.-___TBISwitch
115 * void __TBISyncResume( TBIRES State, int TrigMask );
117 * This routine causes the TBICTX structure specified in State.Sig.pCtx to
118 * be restored. This implies that execution will not return to the caller.
119 * The State.Sig.TrigMask field will be ored into TXMASKI during the
120 * context switch such that any immediately occurring interrupts occur in
121 * the context of the newly specified task. The State.Sig.SaveMask parameter
126 .global ___TBISyncResume
127 .type ___TBISyncResume,function
129 MOV D0Re0,D0Ar2 /* Result from args */
131 XOR D1Ar5,D1Ar5,D1Ar5 /* D1Ar5 = 0 */
132 ADD D1RtP,D1Ar1,#TBICTX_AX
133 SWAP D1Ar5,TXMASKI /* D1Ar5 <-> TXMASKI */
134 MGETL A0StP,A0FrP,[D1RtP] /* Get frame values */
135 OR TXMASKI,D1Ar5,D1Ar3 /* New TXMASKI */
137 .size ___TBISyncResume,.-___TBISyncResume
140 * void __TBIJump( TBIX64 ArgsA, TBIX32 ArgsB, int TrigsMask,
141 * void (*fnMain)(), void *pStack );
143 * Jump directly to a new routine on an arbitrary stack with arbitrary args
144 * oring bits back into TXMASKI on route.
149 .type ___TBIJump,function
151 XOR D0Re0,D0Re0,D0Re0 /* D0Re0 = 0 */
152 MOV A0StP,D0Ar6 /* Stack = Frame */
153 SWAP D0Re0,TXMASKI /* D0Re0 <-> TXMASKI */
155 MOVT A1LbP,#HI(__exit)
156 ADD A1LbP,A1LbP,#LO(__exit)
157 MOV D1RtP,A1LbP /* D1RtP = __exit */
158 OR TXMASKI,D0Re0,D0Ar4 /* New TXMASKI */
159 MOV PC,D1Ar5 /* Jump to fnMain */
160 .size ___TBIJump,.-___TBIJump
163 * PTBICTX __TBISwitchInit( void *pStack, int (*fnMain)(),
164 * .... 4 extra 32-bit args .... );
166 * Generate a new soft thread context ready for it's first outing.
168 * D1Ar1 - Region of memory to be used as the new soft thread stack
169 * D0Ar2 - Main line routine for new soft thread
170 * D1Ar3, D0Ar4, D1Ar5, D0Ar6 - arguments to be passed on stack
171 * The routine returns the initial PTBICTX value for the new thread
175 .global ___TBISwitchInit
176 .type ___TBISwitchInit,function
178 MOV D0FrT,A0FrP /* Need save return point */
180 SETL [A0StP++],D0FrT,D1RtP /* Save return to caller */
181 MOVT A1LbP,#HI(__exit)
182 ADD A1LbP,A1LbP,#LO(__exit)
183 MOV D1RtP,A1LbP /* Get address of __exit */
184 ADD D1Ar1,D1Ar1,#7 /* Align stack to 64-bits */
185 ANDMB D1Ar1,D1Ar1,#0xfff8 /* by rounding base up */
186 MOV A0.2,D1Ar1 /* A0.2 is new stack */
187 MOV D0FrT,D1Ar1 /* Initial puesdo-frame pointer */
188 SETL [A0.2++],D0FrT,D1RtP /* Save return to __exit */
190 SETL [A0.2++],D0FrT,D1RtP /* Save return to fnMain */
191 ADD D0FrT,D0FrT,#8 /* Advance puesdo-frame pointer */
192 MSETL [A0.2],D0Ar6,D0Ar4 /* Save extra initial args */
193 MOVT D1RtP,#HI(___TBIStart) /* Start up code for new stack */
194 ADD D1RtP,D1RtP,#LO(___TBIStart)
195 SETL [A0.2++],D0FrT,D1RtP /* Save return to ___TBIStart */
196 ADD D0FrT,D0FrT,#(8*3) /* Advance puesdo-frame pointer */
197 MOV D0Re0,A0.2 /* Return pCtx for new thread */
198 MOV D1Re0,#0 /* pCtx:0 is default Arg1:Arg2 */
200 * Generate initial TBICTX state
202 MOVT D1Ar1,#HI($LSwitchExit) /* Async restore code */
203 ADD D1Ar1,D1Ar1,#LO($LSwitchExit)
204 MOVT D0Ar2,#TBICTX_SOFT_BIT /* Only soft thread state */
205 ADD D0Ar6,A0.2,#TBICTX_BYTES /* New A0StP */
206 MOV D1Ar5,A1GbP /* Same A1GbP */
207 MOV D0Ar4,D0FrT /* Initial A0FrP */
208 MOV D1Ar3,A1LbP /* Same A1LbP */
209 SETL [A0.2++],D0Ar2,D1Ar1 /* Set header fields */
210 MSETL [A0.2],D0Re0,D0Ar6,D0Ar4,D0Ar2,D0FrT,D0.5,D0.6,D0.7
211 MOV D0Ar2,#0 /* Zero values */
213 SETL [A0.2++],D0Ar2,D1Ar1 /* Zero CurrRPT, CurrBPOBITS, */
214 SETL [A0.2++],D0Ar2,D1Ar1 /* CurrMODE, and pCurrCBuf */
215 MSETL [A0.2],D0Ar6,D0Ar4,D0Ar2,D0FrT D0_5 /* Set DX and then AX regs */
216 B $LSwitchExit /* All done! */
217 .size ___TBISwitchInit,.-___TBISwitchInit
222 .type ___TBIStart,function
224 MOV D1Ar1,D1Re0 /* Pass TBIRES args to call */
226 MGETL D0Re0,D0Ar6,D0Ar4,[A0FrP] /* Get hidden args */
227 SUB A0StP,A0FrP,#(8*3) /* Entry stack pointer */
228 MOV A0FrP,D0Re0 /* Entry frame pointer */
229 MOVT A1LbP,#HI(__exit)
230 ADD A1LbP,A1LbP,#LO(__exit)
231 MOV D1RtP,A1LbP /* D1RtP = __exit */
232 MOV PC,D1Re0 /* Jump into fnMain */
233 .size ___TBIStart,.-___TBIStart