1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#include "fpa11.h"
24#include "fpopcode.h"
25#include "fpa11.inl"
26#include "fpmodule.h"
27#include "fpmodule.inl"
28#include "softfloat.h"
29
30unsigned int PerformFLT(const unsigned int opcode);
31unsigned int PerformFIX(const unsigned int opcode);
32
33static unsigned int PerformComparison(const unsigned int opcode);
34
35unsigned int EmulateCPRT(const unsigned int opcode)
36{
37
38 if (opcode & 0x800000) {
39
40
41
42
43 return PerformComparison(opcode);
44 }
45
46
47 switch ((opcode & 0x700000) >> 20) {
48 case FLT_CODE >> 20:
49 return PerformFLT(opcode);
50 break;
51 case FIX_CODE >> 20:
52 return PerformFIX(opcode);
53 break;
54
55 case WFS_CODE >> 20:
56 writeFPSR(readRegister(getRd(opcode)));
57 break;
58 case RFS_CODE >> 20:
59 writeRegister(getRd(opcode), readFPSR());
60 break;
61
62 default:
63 return 0;
64 }
65
66 return 1;
67}
68
69unsigned int PerformFLT(const unsigned int opcode)
70{
71 FPA11 *fpa11 = GET_FPA11();
72 struct roundingData roundData;
73
74 roundData.mode = SetRoundingMode(opcode);
75 roundData.precision = SetRoundingPrecision(opcode);
76 roundData.exception = 0;
77
78 switch (opcode & MASK_ROUNDING_PRECISION) {
79 case ROUND_SINGLE:
80 {
81 fpa11->fType[getFn(opcode)] = typeSingle;
82 fpa11->fpreg[getFn(opcode)].fSingle = int32_to_float32(&roundData, readRegister(getRd(opcode)));
83 }
84 break;
85
86 case ROUND_DOUBLE:
87 {
88 fpa11->fType[getFn(opcode)] = typeDouble;
89 fpa11->fpreg[getFn(opcode)].fDouble = int32_to_float64(readRegister(getRd(opcode)));
90 }
91 break;
92
93#ifdef CONFIG_FPE_NWFPE_XP
94 case ROUND_EXTENDED:
95 {
96 fpa11->fType[getFn(opcode)] = typeExtended;
97 fpa11->fpreg[getFn(opcode)].fExtended = int32_to_floatx80(readRegister(getRd(opcode)));
98 }
99 break;
100#endif
101
102 default:
103 return 0;
104 }
105
106 if (roundData.exception)
107 float_raise(roundData.exception);
108
109 return 1;
110}
111
112unsigned int PerformFIX(const unsigned int opcode)
113{
114 FPA11 *fpa11 = GET_FPA11();
115 unsigned int Fn = getFm(opcode);
116 struct roundingData roundData;
117
118 roundData.mode = SetRoundingMode(opcode);
119 roundData.precision = SetRoundingPrecision(opcode);
120 roundData.exception = 0;
121
122 switch (fpa11->fType[Fn]) {
123 case typeSingle:
124 {
125 writeRegister(getRd(opcode), float32_to_int32(&roundData, fpa11->fpreg[Fn].fSingle));
126 }
127 break;
128
129 case typeDouble:
130 {
131 writeRegister(getRd(opcode), float64_to_int32(&roundData, fpa11->fpreg[Fn].fDouble));
132 }
133 break;
134
135#ifdef CONFIG_FPE_NWFPE_XP
136 case typeExtended:
137 {
138 writeRegister(getRd(opcode), floatx80_to_int32(&roundData, fpa11->fpreg[Fn].fExtended));
139 }
140 break;
141#endif
142
143 default:
144 return 0;
145 }
146
147 if (roundData.exception)
148 float_raise(roundData.exception);
149
150 return 1;
151}
152
153
154static unsigned int PerformComparison(const unsigned int opcode)
155{
156 FPA11 *fpa11 = GET_FPA11();
157 unsigned int Fn = getFn(opcode), Fm = getFm(opcode);
158 int e_flag = opcode & 0x400000;
159 int n_flag = opcode & 0x200000;
160 unsigned int flags = 0;
161
162#ifdef CONFIG_FPE_NWFPE_XP
163 floatx80 rFn, rFm;
164
165
166
167
168
169
170 switch (fpa11->fType[Fn]) {
171 case typeSingle:
172
173 if (float32_is_nan(fpa11->fpreg[Fn].fSingle))
174 goto unordered;
175 rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
176 break;
177
178 case typeDouble:
179
180 if (float64_is_nan(fpa11->fpreg[Fn].fDouble))
181 goto unordered;
182 rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble);
183 break;
184
185 case typeExtended:
186
187 if (floatx80_is_nan(fpa11->fpreg[Fn].fExtended))
188 goto unordered;
189 rFn = fpa11->fpreg[Fn].fExtended;
190 break;
191
192 default:
193 return 0;
194 }
195
196 if (CONSTANT_FM(opcode)) {
197
198 rFm = getExtendedConstant(Fm);
199 if (floatx80_is_nan(rFm))
200 goto unordered;
201 } else {
202
203 switch (fpa11->fType[Fm]) {
204 case typeSingle:
205
206 if (float32_is_nan(fpa11->fpreg[Fm].fSingle))
207 goto unordered;
208 rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle);
209 break;
210
211 case typeDouble:
212
213 if (float64_is_nan(fpa11->fpreg[Fm].fDouble))
214 goto unordered;
215 rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble);
216 break;
217
218 case typeExtended:
219
220 if (floatx80_is_nan(fpa11->fpreg[Fm].fExtended))
221 goto unordered;
222 rFm = fpa11->fpreg[Fm].fExtended;
223 break;
224
225 default:
226 return 0;
227 }
228 }
229
230 if (n_flag)
231 rFm.high ^= 0x8000;
232
233
234 if (floatx80_lt(rFn, rFm))
235 flags |= CC_NEGATIVE;
236
237
238 if (floatx80_eq(rFn, rFm))
239 flags |= CC_ZERO;
240
241
242 if (floatx80_lt(rFm, rFn))
243 flags |= CC_CARRY;
244
245#else
246 if (CONSTANT_FM(opcode)) {
247
248
249 if (fpa11->fType[Fn] == typeSingle) {
250 float32 rFm = getSingleConstant(Fm);
251 float32 rFn = fpa11->fpreg[Fn].fSingle;
252
253 if (float32_is_nan(rFn))
254 goto unordered;
255
256 if (n_flag)
257 rFm ^= 0x80000000;
258
259
260 if (float32_lt_nocheck(rFn, rFm))
261 flags |= CC_NEGATIVE;
262
263
264 if (float32_eq_nocheck(rFn, rFm))
265 flags |= CC_ZERO;
266
267
268 if (float32_lt_nocheck(rFm, rFn))
269 flags |= CC_CARRY;
270 } else {
271 float64 rFm = getDoubleConstant(Fm);
272 float64 rFn = fpa11->fpreg[Fn].fDouble;
273
274 if (float64_is_nan(rFn))
275 goto unordered;
276
277 if (n_flag)
278 rFm ^= 0x8000000000000000ULL;
279
280
281 if (float64_lt_nocheck(rFn, rFm))
282 flags |= CC_NEGATIVE;
283
284
285 if (float64_eq_nocheck(rFn, rFm))
286 flags |= CC_ZERO;
287
288
289 if (float64_lt_nocheck(rFm, rFn))
290 flags |= CC_CARRY;
291 }
292 } else {
293
294 if (fpa11->fType[Fn] == typeSingle
295 && fpa11->fType[Fm] == typeSingle) {
296 float32 rFm = fpa11->fpreg[Fm].fSingle;
297 float32 rFn = fpa11->fpreg[Fn].fSingle;
298
299 if (float32_is_nan(rFn)
300 || float32_is_nan(rFm))
301 goto unordered;
302
303 if (n_flag)
304 rFm ^= 0x80000000;
305
306
307 if (float32_lt_nocheck(rFn, rFm))
308 flags |= CC_NEGATIVE;
309
310
311 if (float32_eq_nocheck(rFn, rFm))
312 flags |= CC_ZERO;
313
314
315 if (float32_lt_nocheck(rFm, rFn))
316 flags |= CC_CARRY;
317 } else {
318
319 float64 rFm, rFn;
320
321 rFm = (fpa11->fType[Fm] == typeSingle) ?
322 float32_to_float64(fpa11->fpreg[Fm].fSingle)
323 : fpa11->fpreg[Fm].fDouble;
324
325 rFn = (fpa11->fType[Fn] == typeSingle) ?
326 float32_to_float64(fpa11->fpreg[Fn].fSingle)
327 : fpa11->fpreg[Fn].fDouble;
328
329 if (float64_is_nan(rFn)
330 || float64_is_nan(rFm))
331 goto unordered;
332
333 if (n_flag)
334 rFm ^= 0x8000000000000000ULL;
335
336
337 if (float64_lt_nocheck(rFn, rFm))
338 flags |= CC_NEGATIVE;
339
340
341 if (float64_eq_nocheck(rFn, rFm))
342 flags |= CC_ZERO;
343
344
345 if (float64_lt_nocheck(rFm, rFn))
346 flags |= CC_CARRY;
347 }
348 }
349
350#endif
351
352 writeConditionCodes(flags);
353
354 return 1;
355
356 unordered:
357
358
359
360
361
362 flags |= CC_OVERFLOW;
363 flags &= ~(CC_ZERO | CC_NEGATIVE);
364
365 if (BIT_AC & readFPSR())
366 flags |= CC_CARRY;
367
368 if (e_flag)
369 float_raise(float_flag_invalid);
370
371 writeConditionCodes(flags);
372 return 1;
373}
374