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