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