Commit | Line | Data |
---|---|---|
027f891f JH |
1 | /* |
2 | * tbisoft.S | |
3 | * | |
4 | * Copyright (C) 2001, 2002, 2007, 2012 Imagination Technologies. | |
5 | * | |
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. | |
9 | * | |
10 | * Support for soft threads and soft context switches | |
11 | */ | |
12 | ||
13 | .file "tbisoft.S" | |
14 | ||
15 | #include <asm/tbx.h> | |
16 | ||
17 | #ifdef METAC_1_0 | |
18 | /* Ax.4 is saved in TBICTX */ | |
19 | #define A0_4 ,A0.4 | |
20 | #define D0_5 ,D0.5 | |
21 | #else | |
22 | /* Ax.4 is NOT saved in TBICTX */ | |
23 | #define A0_4 | |
24 | #define D0_5 | |
25 | #endif | |
26 | ||
27 | /* Size of the TBICTX structure */ | |
28 | #define TBICTX_BYTES ((TBICTX_AX_REGS*8)+TBICTX_AX) | |
29 | ||
30 | .text | |
31 | .balign 4 | |
32 | .global ___TBISwitchTail | |
33 | .type ___TBISwitchTail,function | |
34 | ___TBISwitchTail: | |
35 | B $LSwitchTail | |
36 | .size ___TBISwitchTail,.-___TBISwitchTail | |
37 | ||
38 | /* | |
39 | * TBIRES __TBIJumpX( TBIX64 ArgsA, PTBICTX *rpSaveCtx, int TrigsMask, | |
40 | * void (*fnMain)(), void *pStack ); | |
41 | * | |
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. | |
46 | */ | |
47 | .text | |
48 | .balign 4 | |
49 | .global ___TBIJumpX | |
50 | .type ___TBIJumpX,function | |
51 | ___TBIJumpX: | |
52 | CMP D1RtP,#-1 | |
53 | B $LSwitchStart | |
54 | .size ___TBIJumpX,.-___TBIJumpX | |
55 | ||
56 | /* | |
57 | * TBIRES __TBISwitch( TBIRES Switch, PTBICTX *rpSaveCtx ) | |
58 | * | |
cacd2c41 | 59 | * Software synchronous context switch between soft threads, save only the |
027f891f JH |
60 | * registers which are actually valid on call entry. |
61 | * | |
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 | |
65 | * | |
66 | */ | |
67 | .text | |
68 | .balign 4 | |
69 | .global ___TBISwitch | |
70 | .type ___TBISwitch,function | |
71 | ___TBISwitch: | |
72 | XORS D0Re0,D0Re0,D0Re0 /* Set ZERO flag */ | |
73 | $LSwitchStart: | |
74 | MOV D0FrT,A0FrP /* Boing entry sequence */ | |
75 | ADD A0FrP,A0StP,#0 | |
76 | SETL [A0StP+#8++],D0FrT,D1RtP | |
77 | /* | |
78 | * Save current frame state - we save all regs because we don't want | |
cacd2c41 | 79 | * uninitialised crap in the TBICTX structure that the asynchronous resumption |
027f891f JH |
80 | * of a thread will restore. |
81 | */ | |
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 */ | |
95 | BNZ ___TBIJump | |
96 | /* | |
97 | * NextThread MUST be in TBICTX_SOFT_BIT state! | |
98 | */ | |
99 | $LSwitchTail: | |
100 | MOV D0Re0,D0Ar2 /* Result from args */ | |
101 | MOV D1Re0,D1Ar1 | |
102 | ADD D1RtP,D1Ar1,#TBICTX_AX | |
103 | MGETL A0StP,A0FrP,[D1RtP] /* Get frame values */ | |
104 | $LSwitchCmn: | |
105 | ADD A0.2,D1Ar1,#TBICTX_DX+(8*5) | |
106 | MGETL D0.5,D0.6,D0.7,[A0.2] /* Get caller-saved DX regs */ | |
107 | $LSwitchExit: | |
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 | |
113 | ||
114 | /* | |
115 | * void __TBISyncResume( TBIRES State, int TrigMask ); | |
116 | * | |
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 | |
cacd2c41 | 120 | * context switch such that any immediately occurring interrupts occur in |
027f891f JH |
121 | * the context of the newly specified task. The State.Sig.SaveMask parameter |
122 | * is ignored. | |
123 | */ | |
124 | .text | |
125 | .balign 4 | |
126 | .global ___TBISyncResume | |
127 | .type ___TBISyncResume,function | |
128 | ___TBISyncResume: | |
129 | MOV D0Re0,D0Ar2 /* Result from args */ | |
130 | MOV D1Re0,D1Ar1 | |
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 */ | |
136 | B $LSwitchCmn | |
137 | .size ___TBISyncResume,.-___TBISyncResume | |
138 | ||
139 | /* | |
140 | * void __TBIJump( TBIX64 ArgsA, TBIX32 ArgsB, int TrigsMask, | |
141 | * void (*fnMain)(), void *pStack ); | |
142 | * | |
143 | * Jump directly to a new routine on an arbitrary stack with arbitrary args | |
144 | * oring bits back into TXMASKI on route. | |
145 | */ | |
146 | .text | |
147 | .balign 4 | |
148 | .global ___TBIJump | |
149 | .type ___TBIJump,function | |
150 | ___TBIJump: | |
151 | XOR D0Re0,D0Re0,D0Re0 /* D0Re0 = 0 */ | |
152 | MOV A0StP,D0Ar6 /* Stack = Frame */ | |
153 | SWAP D0Re0,TXMASKI /* D0Re0 <-> TXMASKI */ | |
154 | MOV A0FrP,D0Ar6 | |
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 | |
161 | ||
162 | /* | |
163 | * PTBICTX __TBISwitchInit( void *pStack, int (*fnMain)(), | |
164 | * .... 4 extra 32-bit args .... ); | |
165 | * | |
166 | * Generate a new soft thread context ready for it's first outing. | |
167 | * | |
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 | |
172 | */ | |
173 | .text | |
174 | .balign 4 | |
175 | .global ___TBISwitchInit | |
176 | .type ___TBISwitchInit,function | |
177 | ___TBISwitchInit: | |
178 | MOV D0FrT,A0FrP /* Need save return point */ | |
179 | ADD A0FrP,A0StP,#0 | |
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 */ | |
189 | MOV D1RtP,D0Ar2 | |
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 */ | |
199 | /* | |
200 | * Generate initial TBICTX state | |
201 | */ | |
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 */ | |
212 | MOV D1Ar1,#0 | |
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 | |
218 | ||
219 | .text | |
220 | .balign 4 | |
221 | .global ___TBIStart | |
222 | .type ___TBIStart,function | |
223 | ___TBIStart: | |
224 | MOV D1Ar1,D1Re0 /* Pass TBIRES args to call */ | |
225 | MOV D0Ar2,D0Re0 | |
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 | |
234 | ||
235 | /* | |
236 | * End of tbisoft.S | |
237 | */ |