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