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