• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 */
452