1/*
2 * tbidefr.S
3 *
4 * Copyright (C) 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 * Routing deferred exceptions
11 */
12
13#include <asm/metag_regs.h>
14#include <asm/tbx.h>
15
16	.text
17	.balign	4
18	.global	___TBIHandleDFR
19	.type	___TBIHandleDFR,function
20/* D1Ar1:D0Ar2 -- State
21 * D0Ar3       -- SigNum
22 * D0Ar4       -- Triggers
23 * D1Ar5       -- Inst
24 * D0Ar6       -- pTBI (volatile)
25 */
26___TBIHandleDFR:
27#ifdef META_BUG_MBN100212
28	MSETL	[A0StP++], D0FrT, D0.5
29
30	/* D1Ar1,D0Ar2,D1Ar5,D0Ar6 -- Arguments to handler, must be preserved
31	 * D0Ar4       -- The deferred exceptions
32	 * D1Ar3       -- As per D0Ar4 but just the trigger bits
33	 * D0.5        -- The bgnd deferred exceptions
34	 * D1.5        -- TXDEFR with bgnd re-added
35	 */
36
37	/* - Collect the pending deferred exceptions using TXSTAT,
38	 *   (ack's the bgnd exceptions as a side-effect)
39	 * - Manually collect remaining (interrupt) deferred exceptions
40	 *   using TXDEFR
41	 * - Replace the triggers (from TXSTATI) with the int deferred
42	 *   exceptions DEFR ..., TXSTATI would have returned if it was valid
43	 *   from bgnd code
44	 * - Reconstruct TXDEFR by or'ing bgnd deferred exceptions (except
45	 *   the DEFER bit) and the int deferred exceptions. This will be
46	 *   restored later
47	 */
48	DEFR	D0.5,  TXSTAT
49	MOV	D1.5,  TXDEFR
50	ANDT	D0.5,  D0.5, #HI(0xFFFF0000)
51	MOV	D1Ar3, D1.5
52	ANDT	D1Ar3, D1Ar3, #HI(0xFFFF0000)
53	OR	D0Ar4, D1Ar3, #TXSTAT_DEFER_BIT
54	OR	D1.5, D1.5, D0.5
55
56	/* Mask off anything unrelated to the deferred exception triggers */
57	ANDT	D1Ar3, D1Ar3, #HI(TXSTAT_BUSERR_BIT | TXSTAT_FPE_BITS)
58
59	/* Can assume that at least one exception happened since this
60	 * handler wouldnt have been called otherwise.
61	 *
62	 * Replace the signal number and at the same time, prepare
63	 * the mask to acknowledge the exception
64	 *
65	 * D1Re0 -- The bits to acknowledge
66	 * D1Ar3 -- The signal number
67	 * D1RtP -- Scratch to deal with non-conditional insns
68	 */
69	MOVT	D1Re0, #HI(TXSTAT_FPE_BITS & ~TXSTAT_FPE_DENORMAL_BIT)
70	MOV	D1RtP, #TXSTAT_FPE_INVALID_S
71	FFB	D1Ar3, D1Ar3
72	CMP	D1Ar3, #TXSTAT_FPE_INVALID_S
73	MOVLE	D1Ar3, D1RtP /* Collapse FPE triggers to a single signal */
74	MOV	D1RtP, #1
75	LSLGT	D1Re0, D1RtP, D1Ar3
76
77	/* Get the handler using the signal number
78	 *
79	 * D1Ar3 -- The signal number
80	 * D0Re0 -- Offset into TBI struct containing handler address
81	 * D1Re0 -- Mask of triggers to keep
82	 * D1RtP -- Address of handler
83	 */
84	SUB	D1Ar3, D1Ar3, #(TXSTAT_FPE_INVALID_S - TBID_SIGNUM_FPE)
85	LSL	D0Re0, D1Ar3, #2
86	XOR	D1Re0, D1Re0, #-1   /* Prepare mask for acknowledge (avoids stall) */
87	ADD	D0Re0,D0Re0,#TBI_fnSigs
88	GETD	D1RtP, [D0Ar6+D0Re0]
89
90	/* Acknowledge triggers */
91	AND	D1.5, D1.5, D1Re0
92
93	/* Restore remaining exceptions
94	 * Do this here in case the handler enables nested interrupts
95	 *
96	 * D1.5 -- TXDEFR with this exception ack'd
97	 */
98	MOV	TXDEFR, D1.5
99
100	/* Call the handler */
101	SWAP	D1RtP, PC
102
103	GETL	D0.5,  D1.5,  [--A0StP]
104	GETL	D0FrT, D1RtP, [--A0StP]
105	MOV	PC,D1RtP
106#else  /* META_BUG_MBN100212 */
107
108	/* D1Ar1,D0Ar2,D1Ar5,D0Ar6 -- Arguments to handler, must be preserved
109	 * D0Ar4       -- The deferred exceptions
110	 * D1Ar3       -- As per D0Ar4 but just the trigger bits
111	 */
112
113	/* - Collect the pending deferred exceptions using TXSTAT,
114	 *   (ack's the interrupt exceptions as a side-effect)
115	 */
116	DEFR	D0Ar4, TXSTATI
117
118	/* Mask off anything unrelated to the deferred exception triggers */
119	MOV	D1Ar3, D0Ar4
120	ANDT	D1Ar3, D1Ar3, #HI(TXSTAT_BUSERR_BIT | TXSTAT_FPE_BITS)
121
122	/* Can assume that at least one exception happened since this
123	 * handler wouldnt have been called otherwise.
124	 *
125	 * Replace the signal number and at the same time, prepare
126	 * the mask to acknowledge the exception
127	 *
128	 * The unusual code for 1<<D1Ar3 may need explanation.
129	 * Normally this would be done using 'MOV rs,#1' and 'LSL rd,rs,D1Ar3'
130	 * but only D1Re0 is available in D1 and no crossunit insns are available
131	 * Even worse, there is no conditional 'MOV r,#uimm8'.
132	 * Since the CMP proves that D1Ar3 >= 20, we can reuse the bottom 12-bits
133	 * of D1Re0 (using 'ORGT r,#1') in the knowledge that the top 20-bits will
134	 * be discarded without affecting the result.
135	 *
136	 * D1Re0 -- The bits to acknowledge
137	 * D1Ar3 -- The signal number
138	 */
139	MOVT	D1Re0, #HI(TXSTAT_FPE_BITS & ~TXSTAT_FPE_DENORMAL_BIT)
140	MOV	D0Re0, #TXSTAT_FPE_INVALID_S
141	FFB	D1Ar3, D1Ar3
142	CMP	D1Ar3, #TXSTAT_FPE_INVALID_S
143	MOVLE	D1Ar3, D0Re0 /* Collapse FPE triggers to a single signal */
144	ORGT	D1Re0, D1Re0, #1
145	LSLGT	D1Re0, D1Re0, D1Ar3
146
147	SUB	D1Ar3, D1Ar3, #(TXSTAT_FPE_INVALID_S - TBID_SIGNUM_FPE)
148
149	/* Acknowledge triggers and restore remaining exceptions
150	 * Do this here in case the handler enables nested interrupts
151	 *
152	 * (x | y) ^ y == x & ~y. It avoids the restrictive XOR ...,#-1 insn
153	 * and is the same length
154	 */
155	MOV	D0Re0, TXDEFR
156	OR	D0Re0, D0Re0, D1Re0
157	XOR	TXDEFR, D0Re0, D1Re0
158
159	/* Get the handler using the signal number
160	 *
161	 * D1Ar3 -- The signal number
162	 * D0Re0 -- Address of handler
163	 */
164	LSL	D0Re0, D1Ar3, #2
165	ADD	D0Re0,D0Re0,#TBI_fnSigs
166	GETD	D0Re0, [D0Ar6+D0Re0]
167
168	/* Tailcall the handler */
169	MOV	PC,D0Re0
170
171#endif /* META_BUG_MBN100212 */
172	.size	___TBIHandleDFR,.-___TBIHandleDFR
173/*
174 * End of tbidefr.S
175 */
176