Commit | Line | Data |
---|---|---|
027f891f JH |
1 | /* |
2 | * tbipcx.S | |
3 | * | |
4 | * Copyright (C) 2001, 2002, 2007, 2009, 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 | * Asyncronous trigger handling including exceptions | |
11 | */ | |
12 | ||
13 | .file "tbipcx.S" | |
14 | #include <asm/metag_regs.h> | |
15 | #include <asm/tbx.h> | |
16 | ||
17 | /* BEGIN HACK */ | |
18 | /* define these for now while doing inital conversion to GAS | |
19 | will fix properly later */ | |
20 | ||
21 | /* Signal identifiers always have the TBID_SIGNAL_BIT set and contain the | |
22 | following related bit-fields */ | |
23 | #define TBID_SIGNUM_S 2 | |
24 | ||
25 | /* END HACK */ | |
26 | ||
27 | #ifdef METAC_1_0 | |
28 | /* Ax.4 is saved in TBICTX */ | |
29 | #define A0_4 ,A0.4 | |
30 | #else | |
31 | /* Ax.4 is NOT saved in TBICTX */ | |
32 | #define A0_4 | |
33 | #endif | |
34 | ||
35 | /* Size of the TBICTX structure */ | |
36 | #define TBICTX_BYTES ((TBICTX_AX_REGS*8)+TBICTX_AX) | |
37 | ||
38 | #ifdef METAC_1_1 | |
39 | #ifndef BOOTROM | |
40 | #ifndef SPECIAL_BUILD | |
41 | /* Jump straight into the boot ROM version of this code */ | |
42 | #define CODE_USES_BOOTROM | |
43 | #endif | |
44 | #endif | |
45 | #endif | |
46 | ||
47 | /* Define space needed for CATCH buffer state in traditional units */ | |
48 | #define CATCH_ENTRIES 5 | |
49 | #define CATCH_ENTRY_BYTES 16 | |
50 | ||
51 | #ifndef CODE_USES_BOOTROM | |
52 | #define A0GblIStP A0.15 /* PTBICTX for current thread in PRIV system */ | |
53 | #define A1GblIGbP A1.15 /* Interrupt A1GbP value in PRIV system */ | |
54 | #endif | |
55 | ||
56 | /* | |
57 | * TBIRES __TBIASyncTrigger( TBIRES State ) | |
58 | */ | |
59 | .text | |
60 | .balign 4 | |
61 | .global ___TBIASyncTrigger | |
62 | .type ___TBIASyncTrigger,function | |
63 | ___TBIASyncTrigger: | |
64 | #ifdef CODE_USES_BOOTROM | |
65 | MOVT D0Re0,#HI(LINCORE_BASE) | |
66 | JUMP D0Re0,#0xA0 | |
67 | #else | |
68 | MOV D0FrT,A0FrP /* Boing entry sequence */ | |
69 | ADD A0FrP,A0StP,#0 | |
70 | SETL [A0StP++],D0FrT,D1RtP | |
71 | MOV D0Re0,PCX /* Check for repeat call */ | |
72 | MOVT D0FrT,#HI(___TBIBoingRTI+4) | |
73 | ADD D0FrT,D0FrT,#LO(___TBIBoingRTI+4) | |
74 | CMP D0Re0,D0FrT | |
75 | BEQ ___TBIBoingExit /* Already set up - come out */ | |
76 | ADD D1Ar1,D1Ar1,#7 /* PRIV system stack here */ | |
77 | MOV A0.2,A0StP /* else push context here */ | |
78 | MOVS D0Re0,D0Ar2 /* Return in user mode? */ | |
79 | ANDMB D1Ar1,D1Ar1,#0xfff8 /* align priv stack to 64-bit */ | |
80 | MOV D1Re0,D1Ar1 /* and set result to arg */ | |
81 | MOVMI A0.2,D1Ar1 /* use priv stack if PRIV set */ | |
82 | /* | |
83 | * Generate an initial TBICTX to return to our own current call context | |
84 | */ | |
85 | MOVT D1Ar5,#HI(___TBIBoingExit) /* Go here to return */ | |
86 | ADD D1Ar5,D1Ar5,#LO(___TBIBoingExit) | |
87 | ADD A0.3,A0.2,#TBICTX_DX /* DX Save area */ | |
88 | ANDT D0Ar2,D0Ar2,#TBICTX_PRIV_BIT /* Extract PRIV bit */ | |
89 | MOVT D0Ar6,#TBICTX_SOFT_BIT /* Only soft thread state */ | |
90 | ADD D0Ar6,D0Ar6,D0Ar2 /* Add in PRIV bit if requested */ | |
91 | SETL [A0.2],D0Ar6,D1Ar5 /* Push header fields */ | |
92 | ADD D0FrT,A0.2,#TBICTX_AX /* Address AX save area */ | |
93 | MSETL [A0.3],D0Re0,D0Ar6,D0Ar4,D0Ar2,D0FrT,D0.5,D0.6,D0.7 | |
94 | MOV D0Ar6,#0 | |
95 | MOV D1Ar5,#0 | |
96 | SETL [A0.3++],D0Ar6,D1Ar5 /* Zero CT register states */ | |
97 | SETL [A0.3++],D0Ar6,D1Ar5 | |
98 | MSETL [D0FrT],A0StP,A0FrP,A0.2,A0.3 A0_4 /* Save AX regs */ | |
99 | MOV A0FrP,A0.2 /* Restore me! */ | |
100 | B ___TBIResume | |
101 | .size ___TBIASyncTrigger,.-___TBIASyncTrigger | |
102 | ||
103 | /* | |
104 | * Optimised return to handler for META Core | |
105 | */ | |
106 | ___TBIBoingRTH: | |
107 | RTH /* Go to background level */ | |
108 | MOVT A0.2, #HI($Lpcx_target) | |
109 | ADD A0.2,A0.2,#LO($Lpcx_target) | |
110 | MOV PCX,A0.2 /* Setup PCX for interrupts */ | |
111 | MOV PC,D1Re0 /* Jump to handler */ | |
112 | /* | |
113 | * This is where the code below needs to jump to wait for outermost interrupt | |
114 | * event in a non-privilege mode system (single shared interrupt stack). | |
115 | */ | |
116 | ___TBIBoingPCX: | |
117 | MGETL A0StP,A0FrP,A0.2,A0.3 A0_4,[D1Re0] /* Restore AX regs */ | |
118 | MOV TXSTATUS,D0Re0 /* Restore flags */ | |
119 | GETL D0Re0,D1Re0,[D1Re0+#TBICTX_DX-TBICTX_BYTES] | |
120 | ___TBIBoingRTI: | |
121 | RTI /* Wait for interrupt */ | |
122 | $Lpcx_target: | |
123 | /* | |
124 | * Save initial interrupt state on current stack | |
125 | */ | |
126 | SETL [A0StP+#TBICTX_DX],D0Re0,D1Re0 /* Save key registers */ | |
127 | ADD D1Re0,A0StP,#TBICTX_AX /* Address AX save area */ | |
128 | MOV D0Re0,TXSTATUS /* Read TXSTATUS into D0Re0 */ | |
129 | MOV TXSTATUS,#0 /* Clear TXSTATUS */ | |
130 | MSETL [D1Re0],A0StP,A0FrP,A0.2,A0.3 A0_4 /* Save AX critical regs */ | |
131 | /* | |
132 | * Register state at this point is- | |
133 | * | |
134 | * D0Re0 - Old TXSTATUS with PRIV and CBUF bits set if appropriate | |
135 | * A0StP - Is call stack frame and base of TBICTX being generated | |
136 | * A1GbP - Is valid static access link | |
137 | */ | |
138 | ___TBIBoing: | |
139 | LOCK0 /* Make sure we have no locks! */ | |
140 | ADD A1.2,A0StP,#TBICTX_DX+(8*1) /* Address DX.1 save area */ | |
141 | MOV A0FrP,A0StP /* Setup frame pointer */ | |
142 | MSETL [A1.2],D0Ar6,D0Ar4,D0Ar2,D0FrT,D0.5,D0.6,D0.7 | |
143 | MOV D0Ar4,TXRPT /* Save critical CT regs */ | |
144 | MOV D1Ar3,TXBPOBITS | |
145 | MOV D1Ar1,TXDIVTIME /* Calc catch buffer pSrc */ | |
146 | MOV D0Ar2,TXMODE | |
147 | MOV TXMODE,#0 /* Clear TXMODE */ | |
148 | #ifdef TXDIVTIME_RPDIRTY_BIT | |
149 | TSTT D1Ar1,#HI(TXDIVTIME_RPDIRTY_BIT)/* NZ = RPDIRTY */ | |
150 | MOVT D0Ar6,#TBICTX_CBRP_BIT | |
151 | ORNZ D0Re0,D0Re0,D0Ar6 /* Set CBRP if RPDIRTY set */ | |
152 | #endif | |
153 | MSETL [A1.2],D0Ar4,D0Ar2 /* Save CT regs state */ | |
154 | MOV D0Ar2,D0Re0 /* Copy TXSTATUS */ | |
155 | ANDMT D0Ar2,D0Ar2,#TBICTX_CBUF_BIT+TBICTX_CBRP_BIT | |
156 | #ifdef TBI_1_4 | |
157 | MOVT D1Ar1,#TBICTX_FPAC_BIT /* Copy FPActive into FPAC */ | |
158 | TSTT D0Re0,#HI(TXSTATUS_FPACTIVE_BIT) | |
159 | ORNZ D0Ar2,D0Ar2,D1Ar1 | |
160 | #endif | |
161 | MOV D1Ar1,PCX /* Read CurrPC */ | |
162 | ORT D0Ar2,D0Ar2,#TBICTX_CRIT_BIT /* SaveMask + CRIT bit */ | |
163 | SETL [A0FrP+#TBICTX_Flags],D0Ar2,D1Ar1 /* Set pCtx header fields */ | |
164 | /* | |
165 | * Completed context save, now we need to make a call to an interrupt handler | |
166 | * | |
167 | * D0Re0 - holds PRIV, WAIT, CBUF flags, HALT reason if appropriate | |
168 | * A0FrP - interrupt stack frame and base of TBICTX being generated | |
169 | * A0StP - same as A0FrP | |
170 | */ | |
171 | ___TBIBoingWait: | |
172 | /* Reserve space for TBICTX and CBUF */ | |
173 | ADD A0StP,A0StP,#TBICTX_BYTES+(CATCH_ENTRY_BYTES*CATCH_ENTRIES) | |
174 | MOV D0Ar4,TXSTATI /* Read the Triggers data */ | |
175 | MOV D1Ar3,TXDIVTIME /* Read IRQEnc bits */ | |
176 | MOV D0Ar2,D0Re0 /* Copy PRIV and WAIT flags */ | |
177 | ANDT D0Ar2,D0Ar2,#TBICTX_PRIV_BIT+TBICTX_WAIT_BIT+TBICTX_CBUF_BIT | |
178 | #ifdef TBI_1_4 | |
179 | MOVT D1Ar5,#TBICTX_FPAC_BIT /* Copy FPActive into FPAC */ | |
180 | TSTT D0Re0,#HI(TXSTATUS_FPACTIVE_BIT) | |
181 | ORNZ D0Ar2,D0Ar2,D1Ar5 | |
182 | #endif | |
183 | ANDT D1Ar3,D1Ar3,#HI(TXDIVTIME_IRQENC_BITS) | |
184 | LSR D1Ar3,D1Ar3,#TXDIVTIME_IRQENC_S | |
185 | AND TXSTATI,D0Ar4,#TXSTATI_BGNDHALT_BIT/* Ack any HALT seen */ | |
186 | ANDS D0Ar4,D0Ar4,#0xFFFF-TXSTATI_BGNDHALT_BIT /* Only seen HALT? */ | |
187 | ORT D0Ar2,D0Ar2,#TBICTX_CRIT_BIT /* Set CRIT */ | |
188 | #ifndef BOOTROM | |
189 | MOVT A1LbP,#HI(___pTBIs) | |
190 | ADD A1LbP,A1LbP,#LO(___pTBIs) | |
191 | GETL D1Ar5,D0Ar6,[A1LbP] /* D0Ar6 = ___pTBIs[1] */ | |
192 | #else | |
193 | /* | |
194 | * For BOOTROM support ___pTBIs must be allocated at offset 0 vs A1GbP | |
195 | */ | |
196 | GETL D1Ar5,D0Ar6,[A1GbP] /* D0Ar6 = ___pTBIs[1] */ | |
197 | #endif | |
198 | BZ ___TBIBoingHalt /* Yes: Service HALT */ | |
199 | /* | |
200 | * Encode interrupt as signal vector, strip away same/lower TXMASKI bits | |
201 | */ | |
202 | MOV D1Ar1,#1 /* Generate mask for this bit */ | |
203 | MOV D0Re0,TXMASKI /* Get interrupt mask */ | |
204 | LSL TXSTATI,D1Ar1,D1Ar3 /* Acknowledge trigger */ | |
205 | AND TXMASKI,D0Re0,#TXSTATI_BGNDHALT_BIT /* Only allow HALTs */ | |
206 | OR D0Ar2,D0Ar2,D0Re0 /* Set TBIRES.Sig.TrigMask */ | |
207 | ADD D1Ar3,D1Ar3,#TBID_SIGNUM_TRT /* Offset into interrupt sigs */ | |
208 | LSL D0Re0,D1Ar3,#TBID_SIGNUM_S /* Generate offset from SigNum */ | |
209 | /* | |
210 | * This is a key moment we are about to call the handler, register state is | |
211 | * as follows- | |
212 | * | |
213 | * D0Re0 - Handler vector (SigNum<<TBID_SIGNUM_S) | |
214 | * D0Ar2 - TXMASKI:TBICTX_CRIT_BIT with optional CBUF and PRIV bits | |
215 | * D1Ar3 - SigNum | |
216 | * D0Ar4 - State read from TXSTATI | |
217 | * D1Ar5 - Inst for SWITCH trigger case only, otherwise undefined | |
218 | * D0Ar6 - pTBI | |
219 | */ | |
220 | ___TBIBoingVec: | |
221 | ADD D0Re0,D0Re0,#TBI_fnSigs /* Offset into signal table */ | |
222 | GETD D1Re0,[D0Ar6+D0Re0] /* Get address for Handler */ | |
223 | /* | |
224 | * Call handler at interrupt level, when it returns simply resume execution | |
225 | * of state indicated by D1Re0. | |
226 | */ | |
227 | MOV D1Ar1,A0FrP /* Pass in pCtx */ | |
228 | CALLR D1RtP,___TBIBoingRTH /* Use RTH to invoke handler */ | |
229 | ||
230 | /* | |
231 | * Perform critical state restore and execute background thread. | |
232 | * | |
233 | * A0FrP - is pointer to TBICTX structure to resume | |
234 | * D0Re0 - contains additional TXMASKI triggers | |
235 | */ | |
236 | .text | |
237 | .balign 4 | |
238 | #ifdef BOOTROM | |
239 | .global ___TBIResume | |
240 | #endif | |
241 | ___TBIResume: | |
242 | /* | |
243 | * New META IP method | |
244 | */ | |
245 | RTH /* Go to interrupt level */ | |
246 | MOV D0Ar4,TXMASKI /* Read TXMASKI */ | |
247 | OR TXMASKI,D0Ar4,D0Re0 /* -Write-Modify TXMASKI */ | |
248 | GETL D0Re0,D1Re0,[A0FrP+#TBICTX_Flags]/* Get Flags:SaveMask, CurrPC */ | |
249 | MOV A0StP,A0FrP /* Position stack pointer */ | |
250 | MOV D0Ar2,TXPOLLI /* Read pending triggers */ | |
251 | MOV PCX,D1Re0 /* Set resumption PC */ | |
252 | TST D0Ar2,#0xFFFF /* Any pending triggers? */ | |
253 | BNZ ___TBIBoingWait /* Yes: Go for triggers */ | |
254 | TSTT D0Re0,#TBICTX_WAIT_BIT /* Do we WAIT anyway? */ | |
255 | BNZ ___TBIBoingWait /* Yes: Go for triggers */ | |
256 | LSLS D1Ar5,D0Re0,#1 /* Test XCBF (MI) & PRIV (CS)? */ | |
257 | ADD D1Re0,A0FrP,#TBICTX_CurrRPT /* Address CT save area */ | |
258 | ADD A0StP,A0FrP,#TBICTX_DX+(8*1) /* Address DX.1 save area */ | |
259 | MGETL A0.2,A0.3,[D1Re0] /* Get CT reg states */ | |
260 | MOV D1Ar3,A1.3 /* Copy old TXDIVTIME */ | |
261 | BPL ___TBIResCrit /* No: Skip logic */ | |
262 | ADD D0Ar4,A0FrP,#TBICTX_BYTES /* Source is after TBICTX */ | |
263 | ANDST D1Ar3,D1Ar3,#HI(TXDIVTIME_RPMASK_BITS)/* !Z if RPDIRTY */ | |
264 | MGETL D0.5,D0.6,[D0Ar4] /* Read Catch state */ | |
265 | MOV TXCATCH0,D0.5 /* Restore TXCATCHn */ | |
266 | MOV TXCATCH1,D1.5 | |
267 | MOV TXCATCH2,D0.6 | |
268 | MOV TXCATCH3,D1.6 | |
269 | BZ ___TBIResCrit | |
270 | MOV D0Ar2,#(1*8) | |
271 | LSRS D1Ar3,D1Ar3,#TXDIVTIME_RPMASK_S+1 /* 2nd RPMASK bit -> bit 0 */ | |
272 | ADD RA,D0Ar4,#(0*8) /* Re-read read pipeline */ | |
273 | ADDNZ RA,D0Ar4,D0Ar2 /* If Bit 0 set issue RA */ | |
274 | LSRS D1Ar3,D1Ar3,#2 /* Bit 1 -> C, Bit 2 -> Bit 0 */ | |
275 | ADD D0Ar2,D0Ar2,#8 | |
276 | ADDCS RA,D0Ar4,D0Ar2 /* If C issue RA */ | |
277 | ADD D0Ar2,D0Ar2,#8 | |
278 | ADDNZ RA,D0Ar4,D0Ar2 /* If Bit 0 set issue RA */ | |
279 | LSRS D1Ar3,D1Ar3,#2 /* Bit 1 -> C, Bit 2 -> Bit 0 */ | |
280 | ADD D0Ar2,D0Ar2,#8 | |
281 | ADDCS RA,D0Ar4,D0Ar2 /* If C issue RA */ | |
282 | ADD D0Ar2,D0Ar2,#8 | |
283 | ADDNZ RA,D0Ar4,D0Ar2 /* If Bit 0 set issue RA */ | |
284 | MOV TXDIVTIME,A1.3 /* Set RPDIRTY again */ | |
285 | ___TBIResCrit: | |
286 | LSLS D1Ar5,D0Re0,#1 /* Test XCBF (MI) & PRIV (CS)? */ | |
287 | #ifdef TBI_1_4 | |
288 | ANDT D1Ar5,D1Ar5,#(TBICTX_FPAC_BIT*2) | |
289 | LSL D0Ar6,D1Ar5,#3 /* Convert FPAC into FPACTIVE */ | |
290 | #endif | |
291 | ANDMT D0Re0,D0Re0,#TBICTX_CBUF_BIT /* Keep CBUF bit from SaveMask */ | |
292 | #ifdef TBI_1_4 | |
293 | OR D0Re0,D0Re0,D0Ar6 /* Combine FPACTIVE with others */ | |
294 | #endif | |
295 | MGETL D0Ar6,D0Ar4,D0Ar2,D0FrT,D0.5,D0.6,D0.7,[A0StP] /* Restore DX */ | |
296 | MOV TXRPT,A0.2 /* Restore CT regs */ | |
297 | MOV TXBPOBITS,A1.2 | |
298 | MOV TXMODE,A0.3 | |
299 | BCC ___TBIBoingPCX /* Do non-PRIV wait! */ | |
300 | MOV A1GblIGbP,A1GbP /* Save A1GbP too */ | |
301 | MGETL A0StP,A0FrP,A0.2,A0.3 A0_4,[D1Re0] /* Restore AX regs */ | |
302 | /* | |
303 | * Wait for the first interrupt/exception trigger in a privilege mode system | |
304 | * (interrupt stack area for current TASK to be pointed to by A0GblIStP | |
305 | * or per_cpu__stack_save[hwthread_id]). | |
306 | */ | |
307 | MOV TXSTATUS,D0Re0 /* Restore flags */ | |
308 | MOV D0Re0,TXPRIVEXT /* Set TXPRIVEXT_TXTOGGLEI_BIT */ | |
309 | SUB D1Re0,D1Re0,#TBICTX_BYTES /* TBICTX is top of int stack */ | |
310 | #ifdef TBX_PERCPU_SP_SAVE | |
311 | SWAP D1Ar3,A1GbP | |
312 | MOV D1Ar3,TXENABLE /* Which thread are we? */ | |
313 | AND D1Ar3,D1Ar3,#TXENABLE_THREAD_BITS | |
314 | LSR D1Ar3,D1Ar3,#TXENABLE_THREAD_S-2 | |
315 | ADDT D1Ar3,D1Ar3,#HI(_per_cpu__stack_save) | |
316 | ADD D1Ar3,D1Ar3,#LO(_per_cpu__stack_save) | |
317 | SETD [D1Ar3],D1Re0 | |
318 | SWAP D1Ar3,A1GbP | |
319 | #else | |
320 | MOV A0GblIStP, D1Re0 | |
321 | #endif | |
322 | OR D0Re0,D0Re0,#TXPRIVEXT_TXTOGGLEI_BIT | |
323 | MOV TXPRIVEXT,D0Re0 /* Cannot set TXPRIVEXT if !priv */ | |
324 | GETL D0Re0,D1Re0,[D1Re0+#TBICTX_DX] | |
325 | RTI /* Wait for interrupt */ | |
326 | /* | |
327 | * Save initial interrupt state on A0GblIStP, switch to A0GblIStP if | |
328 | * BOOTROM code, save and switch to [A1GbP] otherwise. | |
329 | */ | |
330 | ___TBIBoingPCXP: | |
331 | #ifdef TBX_PERCPU_SP_SAVE | |
332 | SWAP D1Ar3,A1GbP /* Get PRIV stack base */ | |
333 | MOV D1Ar3,TXENABLE /* Which thread are we? */ | |
334 | AND D1Ar3,D1Ar3,#TXENABLE_THREAD_BITS | |
335 | LSR D1Ar3,D1Ar3,#TXENABLE_THREAD_S-2 | |
336 | ADDT D1Ar3,D1Ar3,#HI(_per_cpu__stack_save) | |
337 | ADD D1Ar3,D1Ar3,#LO(_per_cpu__stack_save) | |
338 | GETD D1Ar3,[D1Ar3] | |
339 | #else | |
340 | SWAP D1Ar3,A0GblIStP /* Get PRIV stack base */ | |
341 | #endif | |
342 | SETL [D1Ar3+#TBICTX_DX],D0Re0,D1Re0 /* Save key registers */ | |
343 | MOV D0Re0,TXPRIVEXT /* Clear TXPRIVEXT_TXTOGGLEI_BIT */ | |
344 | ADD D1Re0,D1Ar3,#TBICTX_AX /* Address AX save area */ | |
345 | ANDMB D0Re0,D0Re0,#0xFFFF-TXPRIVEXT_TXTOGGLEI_BIT | |
346 | MOV TXPRIVEXT,D0Re0 /* Cannot set TXPRIVEXT if !priv */ | |
347 | MOV D0Re0,TXSTATUS /* Read TXSTATUS into D0Re0 */ | |
348 | MOV TXSTATUS,#0 /* Clear TXSTATUS */ | |
349 | MSETL [D1Re0],A0StP,A0FrP,A0.2,A0.3 A0_4 /* Save AX critical regs */ | |
350 | MOV A0StP,D1Ar3 /* Switch stacks */ | |
351 | #ifdef TBX_PERCPU_SP_SAVE | |
352 | MOV D1Ar3,A1GbP /* Get D1Ar2 back */ | |
353 | #else | |
354 | MOV D1Ar3,A0GblIStP /* Get D1Ar2 back */ | |
355 | #endif | |
356 | ORT D0Re0,D0Re0,#TBICTX_PRIV_BIT /* Add PRIV to TXSTATUS */ | |
357 | MOV A1GbP,A1GblIGbP /* Restore A1GbP */ | |
358 | B ___TBIBoing /* Enter common handler code */ | |
359 | /* | |
360 | * At this point we know it's a background HALT case we are handling. | |
361 | * The restored TXSTATUS always needs to have zero in the reason bits. | |
362 | */ | |
363 | ___TBIBoingHalt: | |
364 | MOV D0Ar4,TXMASKI /* Get interrupt mask */ | |
365 | ANDST D0Re0,D0Re0,#HI(TXSTATUS_MAJOR_HALT_BITS+TXSTATUS_MEM_FAULT_BITS) | |
366 | AND TXMASKI,D0Ar4,#TXSTATI_BGNDHALT_BIT /* Only allow HALTs */ | |
367 | AND D0Ar4,D0Ar4,#0xFFFF-TXSTATI_BGNDHALT_BIT /* What ints are off? */ | |
368 | OR D0Ar2,D0Ar2,D0Ar4 /* Set TBIRES.Sig.TrigMask */ | |
369 | MOV D0Ar4,#TXSTATI_BGNDHALT_BIT /* This was the trigger state */ | |
370 | LSR D1Ar3,D0Re0,#TXSTATUS_MAJOR_HALT_S | |
371 | MOV D0Re0,#TBID_SIGNUM_XXF<<TBID_SIGNUM_S | |
372 | BNZ ___TBIBoingVec /* Jump to XXF exception handler */ | |
373 | /* | |
374 | * Only the SWITCH cases are left, PCX must be valid | |
375 | */ | |
376 | #ifdef TBI_1_4 | |
377 | MOV D1Ar5,TXPRIVEXT | |
378 | TST D1Ar5,#TXPRIVEXT_MINIMON_BIT | |
379 | LSR D1Ar3,D1Ar1,#1 /* Shift needed for MINIM paths (fill stall) */ | |
380 | BZ $Lmeta /* If META only, skip */ | |
381 | TSTT D1Ar1,#HI(0x00800000) | |
382 | ANDMT D1Ar3,D1Ar3,#HI(0x007FFFFF >> 1)/* Shifted mask for large MINIM */ | |
383 | ANDT D1Ar1,D1Ar1,#HI(0xFFE00000) /* Static mask for small MINIM */ | |
384 | BZ $Llarge_minim /* If large MINIM */ | |
385 | $Lsmall_minim: | |
386 | TSTT D1Ar3,#HI(0x00100000 >> 1) | |
387 | ANDMT D1Ar3,D1Ar3,#HI(0x001FFFFF >> 1)/* Correct shifted mask for large MINIM */ | |
388 | ADDZ D1Ar1,D1Ar1,D1Ar3 /* If META rgn, add twice to undo LSR #1 */ | |
389 | B $Lrecombine | |
390 | $Llarge_minim: | |
391 | ANDST D1Ar1,D1Ar1,#HI(0xFF800000) /* Correct static mask for small MINIM */ | |
392 | /* Z=0 (Cannot place code at NULL) */ | |
393 | $Lrecombine: | |
394 | ADD D1Ar1,D1Ar1,D1Ar3 /* Combine static and shifted parts */ | |
395 | $Lmeta: | |
396 | GETW D1Ar5,[D1Ar1++] /* META: lo-16, MINIM: lo-16 (all-16 if short) */ | |
397 | GETW D1Ar3,[D1Ar1] /* META: hi-16, MINIM: hi-16 (only if long) */ | |
398 | MOV D1Re0,D1Ar5 | |
399 | XOR D1Re0,D1Re0,#0x4000 | |
400 | LSLSNZ D1Re0,D1Re0,#(32-14) /* MINIM: If long C=0, if short C=1 */ | |
401 | LSLCC D1Ar3,D1Ar3,#16 /* META/MINIM long: Move hi-16 up */ | |
402 | LSLCS D1Ar3,D1Ar5,#16 /* MINIM short: Dup all-16 */ | |
403 | ADD D1Ar5,D1Ar5,D1Ar3 /* ALL: Combine both 16-bit parts */ | |
404 | #else | |
405 | GETD D1Ar5,[D1Ar1] /* Read instruction for switch */ | |
406 | #endif | |
407 | LSR D1Ar3,D1Ar5,#22 /* Convert into signal number */ | |
408 | AND D1Ar3,D1Ar3,#TBID_SIGNUM_SW3-TBID_SIGNUM_SW0 | |
409 | LSL D0Re0,D1Ar3,#TBID_SIGNUM_S /* Generate offset from SigNum */ | |
410 | B ___TBIBoingVec /* Jump to switch handler */ | |
411 | /* | |
412 | * Exit from TBIASyncTrigger call | |
413 | */ | |
414 | ___TBIBoingExit: | |
415 | GETL D0FrT,D1RtP,[A0FrP++] /* Restore state from frame */ | |
416 | SUB A0StP,A0FrP,#8 /* Unwind stack */ | |
417 | MOV A0FrP,D0FrT /* Last memory read completes */ | |
418 | MOV PC,D1RtP /* Return to caller */ | |
419 | #endif /* ifdef CODE_USES_BOOTROM */ | |
420 | .size ___TBIResume,.-___TBIResume | |
421 | ||
422 | #ifndef BOOTROM | |
423 | /* | |
424 | * void __TBIASyncResume( TBIRES State ) | |
425 | */ | |
426 | .text | |
427 | .balign 4 | |
428 | .global ___TBIASyncResume | |
429 | .type ___TBIASyncResume,function | |
430 | ___TBIASyncResume: | |
431 | /* | |
432 | * Perform CRIT|SOFT state restore and execute background thread. | |
433 | */ | |
434 | MOV D1Ar3,D1Ar1 /* Restore this context */ | |
435 | MOV D0Re0,D0Ar2 /* Carry in additional triggers */ | |
436 | /* Reserve space for TBICTX */ | |
437 | ADD D1Ar3,D1Ar3,#TBICTX_BYTES+(CATCH_ENTRY_BYTES*CATCH_ENTRIES) | |
438 | MOV A0StP,D1Ar3 /* Enter with protection of */ | |
439 | MOV A0FrP,D1Ar1 /* TBICTX on our stack */ | |
440 | #ifdef CODE_USES_BOOTROM | |
441 | MOVT D1Ar1,#HI(LINCORE_BASE) | |
442 | JUMP D1Ar1,#0xA4 | |
443 | #else | |
444 | B ___TBIResume | |
445 | #endif | |
446 | .size ___TBIASyncResume,.-___TBIASyncResume | |
447 | #endif /* ifndef BOOTROM */ | |
448 | ||
449 | /* | |
450 | * End of tbipcx.S | |
451 | */ |