This source file includes following definitions.
- decode_fpu
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 #include <linux/kernel.h>
31 #include "float.h"
32 #include "sgl_float.h"
33 #include "dbl_float.h"
34 #include "cnv_float.h"
35
36 #include <asm/signal.h>
37 #include <asm/siginfo.h>
38
39
40 #undef Fpustatus_register
41 #define Fpustatus_register Fpu_register[0]
42
43
44 #define DOESTRAP 1
45 #define NOTRAP 0
46 #define SIGNALCODE(signal, code) ((signal) << 24 | (code))
47 #define copropbit 1<<31-2
48 #define opclass 9
49 #define fmt 11
50 #define df 13
51 #define twobits 3
52 #define fivebits 31
53 #define MAX_EXCP_REG 7
54
55
56 #define Excp_type(index) Exceptiontype(Fpu_register[index])
57 #define Excp_instr(index) Instructionfield(Fpu_register[index])
58 #define Clear_excp_register(index) Allexception(Fpu_register[index]) = 0
59 #define Excp_format() \
60 (current_ir >> ((current_ir>>opclass & twobits)==1 ? df : fmt) & twobits)
61
62
63 #define Fpu_sgl(index) Fpu_register[index*2]
64
65 #define Fpu_dblp1(index) Fpu_register[index*2]
66 #define Fpu_dblp2(index) Fpu_register[(index*2)+1]
67
68 #define Fpu_quadp1(index) Fpu_register[index*2]
69 #define Fpu_quadp2(index) Fpu_register[(index*2)+1]
70 #define Fpu_quadp3(index) Fpu_register[(index*2)+2]
71 #define Fpu_quadp4(index) Fpu_register[(index*2)+3]
72
73
74 #ifndef Sgl_decrement
75 # define Sgl_decrement(sgl_value) Sall(sgl_value)--
76 #endif
77
78
79 #ifndef Dbl_decrement
80 # define Dbl_decrement(dbl_valuep1,dbl_valuep2) \
81 if ((Dallp2(dbl_valuep2)--) == 0) Dallp1(dbl_valuep1)--
82 #endif
83
84
85 #define update_trap_counts(Fpu_register, aflags, bflags, trap_counts) { \
86 aflags=(Fpu_register[0])>>27; \
87 Fpu_register[0] |= bflags; \
88 }
89
90 u_int
91 decode_fpu(unsigned int Fpu_register[], unsigned int trap_counts[])
92 {
93 unsigned int current_ir, excp;
94 int target, exception_index = 1;
95 boolean inexact;
96 unsigned int aflags;
97 unsigned int bflags;
98 unsigned int excptype;
99
100
101
102
103
104
105
106
107 bflags=(Fpu_register[0] & 0xf8000000);
108 Fpu_register[0] &= 0x07ffffff;
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125 if (!Is_tbit_set()) {
126 update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
127 return SIGNALCODE(SIGILL, ILL_COPROC);
128 }
129
130
131
132
133
134
135 for (exception_index=1; exception_index<=MAX_EXCP_REG; exception_index++) {
136 current_ir = Excp_instr(exception_index);
137
138
139
140
141
142 excptype = Excp_type(exception_index);
143 if (excptype & UNIMPLEMENTEDEXCEPTION) {
144
145
146
147
148
149 Clear_tbit();
150 Clear_excp_register(exception_index);
151
152
153
154
155 excp = fpudispatch(current_ir,excptype,0,Fpu_register);
156
157 if (excp) {
158
159
160
161
162
163
164
165
166
167 Set_tbit();
168
169
170 Set_exceptiontype_and_instr_field(excp,current_ir,
171 Fpu_register[exception_index]);
172 if (excp == UNIMPLEMENTEDEXCEPTION) {
173
174
175
176
177 excp = excptype;
178 update_trap_counts(Fpu_register, aflags, bflags,
179 trap_counts);
180 return SIGNALCODE(SIGILL, ILL_COPROC);
181 }
182
183
184 excptype = excp;
185 }
186
187
188 if (excp == NOEXCEPTION)
189
190 break;
191 }
192
193
194
195
196
197
198
199 if (excptype & UNDERFLOWEXCEPTION) {
200
201 if (Is_underflowtrap_enabled()) {
202 update_trap_counts(Fpu_register, aflags, bflags,
203 trap_counts);
204 return SIGNALCODE(SIGFPE, FPE_FLTUND);
205 } else {
206
207
208
209
210 target = current_ir & fivebits;
211 #ifndef lint
212 if (Ibit(Fpu_register[exception_index])) inexact = TRUE;
213 else inexact = FALSE;
214 #endif
215 switch (Excp_format()) {
216 case SGL:
217
218
219
220
221
222 if (Rabit(Fpu_register[exception_index]))
223 Sgl_decrement(Fpu_sgl(target));
224
225
226 sgl_denormalize(&Fpu_sgl(target),&inexact,Rounding_mode());
227 break;
228 case DBL:
229
230
231
232
233
234 if (Rabit(Fpu_register[exception_index]))
235 Dbl_decrement(Fpu_dblp1(target),Fpu_dblp2(target));
236
237
238 dbl_denormalize(&Fpu_dblp1(target),&Fpu_dblp2(target),
239 &inexact,Rounding_mode());
240 break;
241 }
242 if (inexact) Set_underflowflag();
243
244
245
246
247
248
249 if (inexact && Is_inexacttrap_enabled()) {
250
251
252
253
254
255 Set_exceptiontype(Fpu_register[exception_index],
256 INEXACTEXCEPTION);
257 Set_parmfield(Fpu_register[exception_index],0);
258 update_trap_counts(Fpu_register, aflags, bflags,
259 trap_counts);
260 return SIGNALCODE(SIGFPE, FPE_FLTRES);
261 }
262 else {
263
264
265
266
267 Clear_excp_register(exception_index);
268 if (inexact) Set_inexactflag();
269 }
270 }
271 continue;
272 }
273 switch(Excp_type(exception_index)) {
274 case OVERFLOWEXCEPTION:
275 case OVERFLOWEXCEPTION | INEXACTEXCEPTION:
276
277 update_trap_counts(Fpu_register, aflags, bflags,
278 trap_counts);
279 if (Is_overflowtrap_enabled()) {
280 update_trap_counts(Fpu_register, aflags, bflags,
281 trap_counts);
282 return SIGNALCODE(SIGFPE, FPE_FLTOVF);
283 } else {
284
285
286
287
288 target = current_ir & fivebits;
289 switch (Excp_format()) {
290 case SGL:
291 Sgl_setoverflow(Fpu_sgl(target));
292 break;
293 case DBL:
294 Dbl_setoverflow(Fpu_dblp1(target),Fpu_dblp2(target));
295 break;
296 }
297 Set_overflowflag();
298
299
300
301
302
303
304 if (Is_inexacttrap_enabled()) {
305
306
307
308
309
310 Set_exceptiontype(Fpu_register[exception_index],
311 INEXACTEXCEPTION);
312 update_trap_counts(Fpu_register, aflags, bflags,
313 trap_counts);
314 return SIGNALCODE(SIGFPE, FPE_FLTRES);
315 }
316 else {
317
318
319
320
321 Clear_excp_register(exception_index);
322 Set_inexactflag();
323 }
324 }
325 break;
326 case INVALIDEXCEPTION:
327 case OPC_2E_INVALIDEXCEPTION:
328 update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
329 return SIGNALCODE(SIGFPE, FPE_FLTINV);
330 case DIVISIONBYZEROEXCEPTION:
331 update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
332 Clear_excp_register(exception_index);
333 return SIGNALCODE(SIGFPE, FPE_FLTDIV);
334 case INEXACTEXCEPTION:
335 update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
336 return SIGNALCODE(SIGFPE, FPE_FLTRES);
337 default:
338 update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
339 printk("%s(%d) Unknown FPU exception 0x%x\n", __FILE__,
340 __LINE__, Excp_type(exception_index));
341 return SIGNALCODE(SIGILL, ILL_COPROC);
342 case NOEXCEPTION:
343
344
345
346
347 Clear_excp_register(exception_index);
348 break;
349 }
350 }
351
352
353
354 Clear_tbit();
355 update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
356 return(NOTRAP);
357 }