1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#include "fpa11.h"
23#include "softfloat.h"
24#include "fpopcode.h"
25#include "fpa11.inl"
26
27
28
29unsigned int PerformFLT(const unsigned int opcode);
30unsigned int PerformFIX(const unsigned int opcode);
31
32static unsigned int
33PerformComparison(const unsigned int opcode);
34
35unsigned int EmulateCPRT(const unsigned int opcode)
36{
37 unsigned int nRc = 1;
38
39
40
41 if (opcode & 0x800000)
42 {
43
44
45
46
47 return PerformComparison(opcode);
48 }
49
50
51 switch ((opcode & 0x700000) >> 20)
52 {
53 case FLT_CODE >> 20: nRc = PerformFLT(opcode); break;
54 case FIX_CODE >> 20: nRc = PerformFIX(opcode); break;
55
56 case WFS_CODE >> 20: writeFPSR(readRegister(getRd(opcode))); break;
57 case RFS_CODE >> 20: writeRegister(getRd(opcode),readFPSR()); break;
58
59#if 0
60
61 case WFC_CODE >> 20: writeFPCR(readRegister(getRd(opcode)));
62 case RFC_CODE >> 20: writeRegister(getRd(opcode),readFPCR()); break;
63#endif
64
65 default: nRc = 0;
66 }
67
68 return nRc;
69}
70
71unsigned int PerformFLT(const unsigned int opcode)
72{
73 FPA11 *fpa11 = GET_FPA11();
74
75 unsigned int nRc = 1;
76 SetRoundingMode(opcode);
77
78 switch (opcode & MASK_ROUNDING_PRECISION)
79 {
80 case ROUND_SINGLE:
81 {
82 fpa11->fType[getFn(opcode)] = typeSingle;
83 fpa11->fpreg[getFn(opcode)].fSingle =
84 int32_to_float32(readRegister(getRd(opcode)), &fpa11->fp_status);
85 }
86 break;
87
88 case ROUND_DOUBLE:
89 {
90 fpa11->fType[getFn(opcode)] = typeDouble;
91 fpa11->fpreg[getFn(opcode)].fDouble =
92 int32_to_float64(readRegister(getRd(opcode)), &fpa11->fp_status);
93 }
94 break;
95
96 case ROUND_EXTENDED:
97 {
98 fpa11->fType[getFn(opcode)] = typeExtended;
99 fpa11->fpreg[getFn(opcode)].fExtended =
100 int32_to_floatx80(readRegister(getRd(opcode)), &fpa11->fp_status);
101 }
102 break;
103
104 default: nRc = 0;
105 }
106
107 return nRc;
108}
109
110unsigned int PerformFIX(const unsigned int opcode)
111{
112 FPA11 *fpa11 = GET_FPA11();
113 unsigned int nRc = 1;
114 unsigned int Fn = getFm(opcode);
115
116 SetRoundingMode(opcode);
117
118 switch (fpa11->fType[Fn])
119 {
120 case typeSingle:
121 {
122 writeRegister(getRd(opcode),
123 float32_to_int32(fpa11->fpreg[Fn].fSingle, &fpa11->fp_status));
124 }
125 break;
126
127 case typeDouble:
128 {
129
130 writeRegister(getRd(opcode),
131 float64_to_int32(fpa11->fpreg[Fn].fDouble, &fpa11->fp_status));
132 }
133 break;
134
135 case typeExtended:
136 {
137 writeRegister(getRd(opcode),
138 floatx80_to_int32(fpa11->fpreg[Fn].fExtended, &fpa11->fp_status));
139 }
140 break;
141
142 default: nRc = 0;
143 }
144
145 return nRc;
146}
147
148
149static __inline unsigned int
150PerformComparisonOperation(floatx80 Fn, floatx80 Fm)
151{
152 FPA11 *fpa11 = GET_FPA11();
153 unsigned int flags = 0;
154
155
156 if (floatx80_lt(Fn,Fm, &fpa11->fp_status))
157 {
158 flags |= CC_NEGATIVE;
159 }
160
161
162 if (floatx80_eq_quiet(Fn,Fm, &fpa11->fp_status))
163 {
164 flags |= CC_ZERO;
165 }
166
167
168 if (floatx80_lt(Fm,Fn, &fpa11->fp_status))
169 {
170 flags |= CC_CARRY;
171 }
172
173 writeConditionCodes(flags);
174 return 1;
175}
176
177
178
179static unsigned int PerformComparison(const unsigned int opcode)
180{
181 FPA11 *fpa11 = GET_FPA11();
182 unsigned int Fn, Fm;
183 floatx80 rFn, rFm;
184 int e_flag = opcode & 0x400000;
185 int n_flag = opcode & 0x200000;
186 unsigned int flags = 0;
187
188
189
190 Fn = getFn(opcode);
191 Fm = getFm(opcode);
192
193
194
195
196
197
198 switch (fpa11->fType[Fn])
199 {
200 case typeSingle:
201
202 if (float32_is_any_nan(fpa11->fpreg[Fn].fSingle))
203 goto unordered;
204 rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle, &fpa11->fp_status);
205 break;
206
207 case typeDouble:
208
209 if (float64_is_any_nan(fpa11->fpreg[Fn].fDouble))
210 goto unordered;
211 rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble, &fpa11->fp_status);
212 break;
213
214 case typeExtended:
215
216 if (floatx80_is_any_nan(fpa11->fpreg[Fn].fExtended))
217 goto unordered;
218 rFn = fpa11->fpreg[Fn].fExtended;
219 break;
220
221 default: return 0;
222 }
223
224 if (CONSTANT_FM(opcode))
225 {
226
227 rFm = getExtendedConstant(Fm);
228 if (floatx80_is_any_nan(rFm))
229 goto unordered;
230 }
231 else
232 {
233
234 switch (fpa11->fType[Fm])
235 {
236 case typeSingle:
237
238 if (float32_is_any_nan(fpa11->fpreg[Fm].fSingle))
239 goto unordered;
240 rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle, &fpa11->fp_status);
241 break;
242
243 case typeDouble:
244
245 if (float64_is_any_nan(fpa11->fpreg[Fm].fDouble))
246 goto unordered;
247 rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble, &fpa11->fp_status);
248 break;
249
250 case typeExtended:
251
252 if (floatx80_is_any_nan(fpa11->fpreg[Fm].fExtended))
253 goto unordered;
254 rFm = fpa11->fpreg[Fm].fExtended;
255 break;
256
257 default: return 0;
258 }
259 }
260
261 if (n_flag)
262 {
263 rFm.high ^= 0x8000;
264 }
265
266 return PerformComparisonOperation(rFn,rFm);
267
268 unordered:
269
270
271
272
273
274 flags |= CC_OVERFLOW;
275 flags &= ~(CC_ZERO | CC_NEGATIVE);
276
277 if (BIT_AC & readFPSR()) flags |= CC_CARRY;
278
279 if (e_flag) float_raise(float_flag_invalid, &fpa11->fp_status);
280
281 writeConditionCodes(flags);
282 return 1;
283}
284