hmp: Ignore Error objects where the return value suffices
[qemu.git] / target / mips / fpu_helper.c
1 /*
2 * Helpers for emulation of FPU-related MIPS instructions.
3 *
4 * Copyright (C) 2004-2005 Jocelyn Mayer
5 * Copyright (C) 2020 Wave Computing, Inc.
6 * Copyright (C) 2020 Aleksandar Markovic <amarkovic@wavecomp.com>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23 #include "qemu/osdep.h"
24 #include "qemu/main-loop.h"
25 #include "cpu.h"
26 #include "internal.h"
27 #include "qemu/host-utils.h"
28 #include "exec/helper-proto.h"
29 #include "exec/exec-all.h"
30 #include "exec/cpu_ldst.h"
31 #include "exec/memop.h"
32 #include "sysemu/kvm.h"
33 #include "fpu/softfloat.h"
34
35
36 /* Complex FPU operations which may need stack space. */
37
38 #define FLOAT_TWO32 make_float32(1 << 30)
39 #define FLOAT_TWO64 make_float64(1ULL << 62)
40
41 #define FP_TO_INT32_OVERFLOW 0x7fffffff
42 #define FP_TO_INT64_OVERFLOW 0x7fffffffffffffffULL
43
44 /* convert MIPS rounding mode in FCR31 to IEEE library */
45 unsigned int ieee_rm[] = {
46 float_round_nearest_even,
47 float_round_to_zero,
48 float_round_up,
49 float_round_down
50 };
51
52 target_ulong helper_cfc1(CPUMIPSState *env, uint32_t reg)
53 {
54 target_ulong arg1 = 0;
55
56 switch (reg) {
57 case 0:
58 arg1 = (int32_t)env->active_fpu.fcr0;
59 break;
60 case 1:
61 /* UFR Support - Read Status FR */
62 if (env->active_fpu.fcr0 & (1 << FCR0_UFRP)) {
63 if (env->CP0_Config5 & (1 << CP0C5_UFR)) {
64 arg1 = (int32_t)
65 ((env->CP0_Status & (1 << CP0St_FR)) >> CP0St_FR);
66 } else {
67 do_raise_exception(env, EXCP_RI, GETPC());
68 }
69 }
70 break;
71 case 5:
72 /* FRE Support - read Config5.FRE bit */
73 if (env->active_fpu.fcr0 & (1 << FCR0_FREP)) {
74 if (env->CP0_Config5 & (1 << CP0C5_UFE)) {
75 arg1 = (env->CP0_Config5 >> CP0C5_FRE) & 1;
76 } else {
77 helper_raise_exception(env, EXCP_RI);
78 }
79 }
80 break;
81 case 25:
82 arg1 = ((env->active_fpu.fcr31 >> 24) & 0xfe) |
83 ((env->active_fpu.fcr31 >> 23) & 0x1);
84 break;
85 case 26:
86 arg1 = env->active_fpu.fcr31 & 0x0003f07c;
87 break;
88 case 28:
89 arg1 = (env->active_fpu.fcr31 & 0x00000f83) |
90 ((env->active_fpu.fcr31 >> 22) & 0x4);
91 break;
92 default:
93 arg1 = (int32_t)env->active_fpu.fcr31;
94 break;
95 }
96
97 return arg1;
98 }
99
100 void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t fs, uint32_t rt)
101 {
102 switch (fs) {
103 case 1:
104 /* UFR Alias - Reset Status FR */
105 if (!((env->active_fpu.fcr0 & (1 << FCR0_UFRP)) && (rt == 0))) {
106 return;
107 }
108 if (env->CP0_Config5 & (1 << CP0C5_UFR)) {
109 env->CP0_Status &= ~(1 << CP0St_FR);
110 compute_hflags(env);
111 } else {
112 do_raise_exception(env, EXCP_RI, GETPC());
113 }
114 break;
115 case 4:
116 /* UNFR Alias - Set Status FR */
117 if (!((env->active_fpu.fcr0 & (1 << FCR0_UFRP)) && (rt == 0))) {
118 return;
119 }
120 if (env->CP0_Config5 & (1 << CP0C5_UFR)) {
121 env->CP0_Status |= (1 << CP0St_FR);
122 compute_hflags(env);
123 } else {
124 do_raise_exception(env, EXCP_RI, GETPC());
125 }
126 break;
127 case 5:
128 /* FRE Support - clear Config5.FRE bit */
129 if (!((env->active_fpu.fcr0 & (1 << FCR0_FREP)) && (rt == 0))) {
130 return;
131 }
132 if (env->CP0_Config5 & (1 << CP0C5_UFE)) {
133 env->CP0_Config5 &= ~(1 << CP0C5_FRE);
134 compute_hflags(env);
135 } else {
136 helper_raise_exception(env, EXCP_RI);
137 }
138 break;
139 case 6:
140 /* FRE Support - set Config5.FRE bit */
141 if (!((env->active_fpu.fcr0 & (1 << FCR0_FREP)) && (rt == 0))) {
142 return;
143 }
144 if (env->CP0_Config5 & (1 << CP0C5_UFE)) {
145 env->CP0_Config5 |= (1 << CP0C5_FRE);
146 compute_hflags(env);
147 } else {
148 helper_raise_exception(env, EXCP_RI);
149 }
150 break;
151 case 25:
152 if ((env->insn_flags & ISA_MIPS32R6) || (arg1 & 0xffffff00)) {
153 return;
154 }
155 env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0x017fffff) |
156 ((arg1 & 0xfe) << 24) |
157 ((arg1 & 0x1) << 23);
158 break;
159 case 26:
160 if (arg1 & 0x007c0000) {
161 return;
162 }
163 env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0xfffc0f83) |
164 (arg1 & 0x0003f07c);
165 break;
166 case 28:
167 if (arg1 & 0x007c0000) {
168 return;
169 }
170 env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0xfefff07c) |
171 (arg1 & 0x00000f83) |
172 ((arg1 & 0x4) << 22);
173 break;
174 case 31:
175 env->active_fpu.fcr31 = (arg1 & env->active_fpu.fcr31_rw_bitmask) |
176 (env->active_fpu.fcr31 & ~(env->active_fpu.fcr31_rw_bitmask));
177 break;
178 default:
179 if (env->insn_flags & ISA_MIPS32R6) {
180 do_raise_exception(env, EXCP_RI, GETPC());
181 }
182 return;
183 }
184 restore_fp_status(env);
185 set_float_exception_flags(0, &env->active_fpu.fp_status);
186 if ((GET_FP_ENABLE(env->active_fpu.fcr31) | 0x20) &
187 GET_FP_CAUSE(env->active_fpu.fcr31)) {
188 do_raise_exception(env, EXCP_FPE, GETPC());
189 }
190 }
191
192 static inline int ieee_to_mips_xcpt(int ieee_xcpt)
193 {
194 int mips_xcpt = 0;
195
196 if (ieee_xcpt & float_flag_invalid) {
197 mips_xcpt |= FP_INVALID;
198 }
199 if (ieee_xcpt & float_flag_overflow) {
200 mips_xcpt |= FP_OVERFLOW;
201 }
202 if (ieee_xcpt & float_flag_underflow) {
203 mips_xcpt |= FP_UNDERFLOW;
204 }
205 if (ieee_xcpt & float_flag_divbyzero) {
206 mips_xcpt |= FP_DIV0;
207 }
208 if (ieee_xcpt & float_flag_inexact) {
209 mips_xcpt |= FP_INEXACT;
210 }
211
212 return mips_xcpt;
213 }
214
215 static inline void update_fcr31(CPUMIPSState *env, uintptr_t pc)
216 {
217 int ieee_exception_flags = get_float_exception_flags(
218 &env->active_fpu.fp_status);
219 int mips_exception_flags = 0;
220
221 if (ieee_exception_flags) {
222 mips_exception_flags = ieee_to_mips_xcpt(ieee_exception_flags);
223 }
224
225 SET_FP_CAUSE(env->active_fpu.fcr31, mips_exception_flags);
226
227 if (mips_exception_flags) {
228 set_float_exception_flags(0, &env->active_fpu.fp_status);
229
230 if (GET_FP_ENABLE(env->active_fpu.fcr31) & mips_exception_flags) {
231 do_raise_exception(env, EXCP_FPE, pc);
232 } else {
233 UPDATE_FP_FLAGS(env->active_fpu.fcr31, mips_exception_flags);
234 }
235 }
236 }
237
238 /*
239 * Float support.
240 * Single precition routines have a "s" suffix, double precision a
241 * "d" suffix, 32bit integer "w", 64bit integer "l", paired single "ps",
242 * paired single lower "pl", paired single upper "pu".
243 */
244
245 /* unary operations, modifying fp status */
246 uint64_t helper_float_sqrt_d(CPUMIPSState *env, uint64_t fdt0)
247 {
248 fdt0 = float64_sqrt(fdt0, &env->active_fpu.fp_status);
249 update_fcr31(env, GETPC());
250 return fdt0;
251 }
252
253 uint32_t helper_float_sqrt_s(CPUMIPSState *env, uint32_t fst0)
254 {
255 fst0 = float32_sqrt(fst0, &env->active_fpu.fp_status);
256 update_fcr31(env, GETPC());
257 return fst0;
258 }
259
260 uint64_t helper_float_cvtd_s(CPUMIPSState *env, uint32_t fst0)
261 {
262 uint64_t fdt2;
263
264 fdt2 = float32_to_float64(fst0, &env->active_fpu.fp_status);
265 update_fcr31(env, GETPC());
266 return fdt2;
267 }
268
269 uint64_t helper_float_cvtd_w(CPUMIPSState *env, uint32_t wt0)
270 {
271 uint64_t fdt2;
272
273 fdt2 = int32_to_float64(wt0, &env->active_fpu.fp_status);
274 update_fcr31(env, GETPC());
275 return fdt2;
276 }
277
278 uint64_t helper_float_cvtd_l(CPUMIPSState *env, uint64_t dt0)
279 {
280 uint64_t fdt2;
281
282 fdt2 = int64_to_float64(dt0, &env->active_fpu.fp_status);
283 update_fcr31(env, GETPC());
284 return fdt2;
285 }
286
287 uint64_t helper_float_cvt_l_d(CPUMIPSState *env, uint64_t fdt0)
288 {
289 uint64_t dt2;
290
291 dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
292 if (get_float_exception_flags(&env->active_fpu.fp_status)
293 & (float_flag_invalid | float_flag_overflow)) {
294 dt2 = FP_TO_INT64_OVERFLOW;
295 }
296 update_fcr31(env, GETPC());
297 return dt2;
298 }
299
300 uint64_t helper_float_cvt_l_s(CPUMIPSState *env, uint32_t fst0)
301 {
302 uint64_t dt2;
303
304 dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
305 if (get_float_exception_flags(&env->active_fpu.fp_status)
306 & (float_flag_invalid | float_flag_overflow)) {
307 dt2 = FP_TO_INT64_OVERFLOW;
308 }
309 update_fcr31(env, GETPC());
310 return dt2;
311 }
312
313 uint64_t helper_float_cvtps_pw(CPUMIPSState *env, uint64_t dt0)
314 {
315 uint32_t fst2;
316 uint32_t fsth2;
317
318 fst2 = int32_to_float32(dt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
319 fsth2 = int32_to_float32(dt0 >> 32, &env->active_fpu.fp_status);
320 update_fcr31(env, GETPC());
321 return ((uint64_t)fsth2 << 32) | fst2;
322 }
323
324 uint64_t helper_float_cvtpw_ps(CPUMIPSState *env, uint64_t fdt0)
325 {
326 uint32_t wt2;
327 uint32_t wth2;
328 int excp, excph;
329
330 wt2 = float32_to_int32(fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
331 excp = get_float_exception_flags(&env->active_fpu.fp_status);
332 if (excp & (float_flag_overflow | float_flag_invalid)) {
333 wt2 = FP_TO_INT32_OVERFLOW;
334 }
335
336 set_float_exception_flags(0, &env->active_fpu.fp_status);
337 wth2 = float32_to_int32(fdt0 >> 32, &env->active_fpu.fp_status);
338 excph = get_float_exception_flags(&env->active_fpu.fp_status);
339 if (excph & (float_flag_overflow | float_flag_invalid)) {
340 wth2 = FP_TO_INT32_OVERFLOW;
341 }
342
343 set_float_exception_flags(excp | excph, &env->active_fpu.fp_status);
344 update_fcr31(env, GETPC());
345
346 return ((uint64_t)wth2 << 32) | wt2;
347 }
348
349 uint32_t helper_float_cvts_d(CPUMIPSState *env, uint64_t fdt0)
350 {
351 uint32_t fst2;
352
353 fst2 = float64_to_float32(fdt0, &env->active_fpu.fp_status);
354 update_fcr31(env, GETPC());
355 return fst2;
356 }
357
358 uint32_t helper_float_cvts_w(CPUMIPSState *env, uint32_t wt0)
359 {
360 uint32_t fst2;
361
362 fst2 = int32_to_float32(wt0, &env->active_fpu.fp_status);
363 update_fcr31(env, GETPC());
364 return fst2;
365 }
366
367 uint32_t helper_float_cvts_l(CPUMIPSState *env, uint64_t dt0)
368 {
369 uint32_t fst2;
370
371 fst2 = int64_to_float32(dt0, &env->active_fpu.fp_status);
372 update_fcr31(env, GETPC());
373 return fst2;
374 }
375
376 uint32_t helper_float_cvts_pl(CPUMIPSState *env, uint32_t wt0)
377 {
378 uint32_t wt2;
379
380 wt2 = wt0;
381 update_fcr31(env, GETPC());
382 return wt2;
383 }
384
385 uint32_t helper_float_cvts_pu(CPUMIPSState *env, uint32_t wth0)
386 {
387 uint32_t wt2;
388
389 wt2 = wth0;
390 update_fcr31(env, GETPC());
391 return wt2;
392 }
393
394 uint32_t helper_float_cvt_w_s(CPUMIPSState *env, uint32_t fst0)
395 {
396 uint32_t wt2;
397
398 wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
399 if (get_float_exception_flags(&env->active_fpu.fp_status)
400 & (float_flag_invalid | float_flag_overflow)) {
401 wt2 = FP_TO_INT32_OVERFLOW;
402 }
403 update_fcr31(env, GETPC());
404 return wt2;
405 }
406
407 uint32_t helper_float_cvt_w_d(CPUMIPSState *env, uint64_t fdt0)
408 {
409 uint32_t wt2;
410
411 wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
412 if (get_float_exception_flags(&env->active_fpu.fp_status)
413 & (float_flag_invalid | float_flag_overflow)) {
414 wt2 = FP_TO_INT32_OVERFLOW;
415 }
416 update_fcr31(env, GETPC());
417 return wt2;
418 }
419
420 uint64_t helper_float_round_l_d(CPUMIPSState *env, uint64_t fdt0)
421 {
422 uint64_t dt2;
423
424 set_float_rounding_mode(float_round_nearest_even,
425 &env->active_fpu.fp_status);
426 dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
427 restore_rounding_mode(env);
428 if (get_float_exception_flags(&env->active_fpu.fp_status)
429 & (float_flag_invalid | float_flag_overflow)) {
430 dt2 = FP_TO_INT64_OVERFLOW;
431 }
432 update_fcr31(env, GETPC());
433 return dt2;
434 }
435
436 uint64_t helper_float_round_l_s(CPUMIPSState *env, uint32_t fst0)
437 {
438 uint64_t dt2;
439
440 set_float_rounding_mode(float_round_nearest_even,
441 &env->active_fpu.fp_status);
442 dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
443 restore_rounding_mode(env);
444 if (get_float_exception_flags(&env->active_fpu.fp_status)
445 & (float_flag_invalid | float_flag_overflow)) {
446 dt2 = FP_TO_INT64_OVERFLOW;
447 }
448 update_fcr31(env, GETPC());
449 return dt2;
450 }
451
452 uint32_t helper_float_round_w_d(CPUMIPSState *env, uint64_t fdt0)
453 {
454 uint32_t wt2;
455
456 set_float_rounding_mode(float_round_nearest_even,
457 &env->active_fpu.fp_status);
458 wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
459 restore_rounding_mode(env);
460 if (get_float_exception_flags(&env->active_fpu.fp_status)
461 & (float_flag_invalid | float_flag_overflow)) {
462 wt2 = FP_TO_INT32_OVERFLOW;
463 }
464 update_fcr31(env, GETPC());
465 return wt2;
466 }
467
468 uint32_t helper_float_round_w_s(CPUMIPSState *env, uint32_t fst0)
469 {
470 uint32_t wt2;
471
472 set_float_rounding_mode(float_round_nearest_even,
473 &env->active_fpu.fp_status);
474 wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
475 restore_rounding_mode(env);
476 if (get_float_exception_flags(&env->active_fpu.fp_status)
477 & (float_flag_invalid | float_flag_overflow)) {
478 wt2 = FP_TO_INT32_OVERFLOW;
479 }
480 update_fcr31(env, GETPC());
481 return wt2;
482 }
483
484 uint64_t helper_float_trunc_l_d(CPUMIPSState *env, uint64_t fdt0)
485 {
486 uint64_t dt2;
487
488 dt2 = float64_to_int64_round_to_zero(fdt0,
489 &env->active_fpu.fp_status);
490 if (get_float_exception_flags(&env->active_fpu.fp_status)
491 & (float_flag_invalid | float_flag_overflow)) {
492 dt2 = FP_TO_INT64_OVERFLOW;
493 }
494 update_fcr31(env, GETPC());
495 return dt2;
496 }
497
498 uint64_t helper_float_trunc_l_s(CPUMIPSState *env, uint32_t fst0)
499 {
500 uint64_t dt2;
501
502 dt2 = float32_to_int64_round_to_zero(fst0, &env->active_fpu.fp_status);
503 if (get_float_exception_flags(&env->active_fpu.fp_status)
504 & (float_flag_invalid | float_flag_overflow)) {
505 dt2 = FP_TO_INT64_OVERFLOW;
506 }
507 update_fcr31(env, GETPC());
508 return dt2;
509 }
510
511 uint32_t helper_float_trunc_w_d(CPUMIPSState *env, uint64_t fdt0)
512 {
513 uint32_t wt2;
514
515 wt2 = float64_to_int32_round_to_zero(fdt0, &env->active_fpu.fp_status);
516 if (get_float_exception_flags(&env->active_fpu.fp_status)
517 & (float_flag_invalid | float_flag_overflow)) {
518 wt2 = FP_TO_INT32_OVERFLOW;
519 }
520 update_fcr31(env, GETPC());
521 return wt2;
522 }
523
524 uint32_t helper_float_trunc_w_s(CPUMIPSState *env, uint32_t fst0)
525 {
526 uint32_t wt2;
527
528 wt2 = float32_to_int32_round_to_zero(fst0, &env->active_fpu.fp_status);
529 if (get_float_exception_flags(&env->active_fpu.fp_status)
530 & (float_flag_invalid | float_flag_overflow)) {
531 wt2 = FP_TO_INT32_OVERFLOW;
532 }
533 update_fcr31(env, GETPC());
534 return wt2;
535 }
536
537 uint64_t helper_float_ceil_l_d(CPUMIPSState *env, uint64_t fdt0)
538 {
539 uint64_t dt2;
540
541 set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
542 dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
543 restore_rounding_mode(env);
544 if (get_float_exception_flags(&env->active_fpu.fp_status)
545 & (float_flag_invalid | float_flag_overflow)) {
546 dt2 = FP_TO_INT64_OVERFLOW;
547 }
548 update_fcr31(env, GETPC());
549 return dt2;
550 }
551
552 uint64_t helper_float_ceil_l_s(CPUMIPSState *env, uint32_t fst0)
553 {
554 uint64_t dt2;
555
556 set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
557 dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
558 restore_rounding_mode(env);
559 if (get_float_exception_flags(&env->active_fpu.fp_status)
560 & (float_flag_invalid | float_flag_overflow)) {
561 dt2 = FP_TO_INT64_OVERFLOW;
562 }
563 update_fcr31(env, GETPC());
564 return dt2;
565 }
566
567 uint32_t helper_float_ceil_w_d(CPUMIPSState *env, uint64_t fdt0)
568 {
569 uint32_t wt2;
570
571 set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
572 wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
573 restore_rounding_mode(env);
574 if (get_float_exception_flags(&env->active_fpu.fp_status)
575 & (float_flag_invalid | float_flag_overflow)) {
576 wt2 = FP_TO_INT32_OVERFLOW;
577 }
578 update_fcr31(env, GETPC());
579 return wt2;
580 }
581
582 uint32_t helper_float_ceil_w_s(CPUMIPSState *env, uint32_t fst0)
583 {
584 uint32_t wt2;
585
586 set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
587 wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
588 restore_rounding_mode(env);
589 if (get_float_exception_flags(&env->active_fpu.fp_status)
590 & (float_flag_invalid | float_flag_overflow)) {
591 wt2 = FP_TO_INT32_OVERFLOW;
592 }
593 update_fcr31(env, GETPC());
594 return wt2;
595 }
596
597 uint64_t helper_float_floor_l_d(CPUMIPSState *env, uint64_t fdt0)
598 {
599 uint64_t dt2;
600
601 set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
602 dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
603 restore_rounding_mode(env);
604 if (get_float_exception_flags(&env->active_fpu.fp_status)
605 & (float_flag_invalid | float_flag_overflow)) {
606 dt2 = FP_TO_INT64_OVERFLOW;
607 }
608 update_fcr31(env, GETPC());
609 return dt2;
610 }
611
612 uint64_t helper_float_floor_l_s(CPUMIPSState *env, uint32_t fst0)
613 {
614 uint64_t dt2;
615
616 set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
617 dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
618 restore_rounding_mode(env);
619 if (get_float_exception_flags(&env->active_fpu.fp_status)
620 & (float_flag_invalid | float_flag_overflow)) {
621 dt2 = FP_TO_INT64_OVERFLOW;
622 }
623 update_fcr31(env, GETPC());
624 return dt2;
625 }
626
627 uint32_t helper_float_floor_w_d(CPUMIPSState *env, uint64_t fdt0)
628 {
629 uint32_t wt2;
630
631 set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
632 wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
633 restore_rounding_mode(env);
634 if (get_float_exception_flags(&env->active_fpu.fp_status)
635 & (float_flag_invalid | float_flag_overflow)) {
636 wt2 = FP_TO_INT32_OVERFLOW;
637 }
638 update_fcr31(env, GETPC());
639 return wt2;
640 }
641
642 uint32_t helper_float_floor_w_s(CPUMIPSState *env, uint32_t fst0)
643 {
644 uint32_t wt2;
645
646 set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
647 wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
648 restore_rounding_mode(env);
649 if (get_float_exception_flags(&env->active_fpu.fp_status)
650 & (float_flag_invalid | float_flag_overflow)) {
651 wt2 = FP_TO_INT32_OVERFLOW;
652 }
653 update_fcr31(env, GETPC());
654 return wt2;
655 }
656
657 uint64_t helper_float_cvt_2008_l_d(CPUMIPSState *env, uint64_t fdt0)
658 {
659 uint64_t dt2;
660
661 dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
662 if (get_float_exception_flags(&env->active_fpu.fp_status)
663 & float_flag_invalid) {
664 if (float64_is_any_nan(fdt0)) {
665 dt2 = 0;
666 }
667 }
668 update_fcr31(env, GETPC());
669 return dt2;
670 }
671
672 uint64_t helper_float_cvt_2008_l_s(CPUMIPSState *env, uint32_t fst0)
673 {
674 uint64_t dt2;
675
676 dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
677 if (get_float_exception_flags(&env->active_fpu.fp_status)
678 & float_flag_invalid) {
679 if (float32_is_any_nan(fst0)) {
680 dt2 = 0;
681 }
682 }
683 update_fcr31(env, GETPC());
684 return dt2;
685 }
686
687 uint32_t helper_float_cvt_2008_w_d(CPUMIPSState *env, uint64_t fdt0)
688 {
689 uint32_t wt2;
690
691 wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
692 if (get_float_exception_flags(&env->active_fpu.fp_status)
693 & float_flag_invalid) {
694 if (float64_is_any_nan(fdt0)) {
695 wt2 = 0;
696 }
697 }
698 update_fcr31(env, GETPC());
699 return wt2;
700 }
701
702 uint32_t helper_float_cvt_2008_w_s(CPUMIPSState *env, uint32_t fst0)
703 {
704 uint32_t wt2;
705
706 wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
707 if (get_float_exception_flags(&env->active_fpu.fp_status)
708 & float_flag_invalid) {
709 if (float32_is_any_nan(fst0)) {
710 wt2 = 0;
711 }
712 }
713 update_fcr31(env, GETPC());
714 return wt2;
715 }
716
717 uint64_t helper_float_round_2008_l_d(CPUMIPSState *env, uint64_t fdt0)
718 {
719 uint64_t dt2;
720
721 set_float_rounding_mode(float_round_nearest_even,
722 &env->active_fpu.fp_status);
723 dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
724 restore_rounding_mode(env);
725 if (get_float_exception_flags(&env->active_fpu.fp_status)
726 & float_flag_invalid) {
727 if (float64_is_any_nan(fdt0)) {
728 dt2 = 0;
729 }
730 }
731 update_fcr31(env, GETPC());
732 return dt2;
733 }
734
735 uint64_t helper_float_round_2008_l_s(CPUMIPSState *env, uint32_t fst0)
736 {
737 uint64_t dt2;
738
739 set_float_rounding_mode(float_round_nearest_even,
740 &env->active_fpu.fp_status);
741 dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
742 restore_rounding_mode(env);
743 if (get_float_exception_flags(&env->active_fpu.fp_status)
744 & float_flag_invalid) {
745 if (float32_is_any_nan(fst0)) {
746 dt2 = 0;
747 }
748 }
749 update_fcr31(env, GETPC());
750 return dt2;
751 }
752
753 uint32_t helper_float_round_2008_w_d(CPUMIPSState *env, uint64_t fdt0)
754 {
755 uint32_t wt2;
756
757 set_float_rounding_mode(float_round_nearest_even,
758 &env->active_fpu.fp_status);
759 wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
760 restore_rounding_mode(env);
761 if (get_float_exception_flags(&env->active_fpu.fp_status)
762 & float_flag_invalid) {
763 if (float64_is_any_nan(fdt0)) {
764 wt2 = 0;
765 }
766 }
767 update_fcr31(env, GETPC());
768 return wt2;
769 }
770
771 uint32_t helper_float_round_2008_w_s(CPUMIPSState *env, uint32_t fst0)
772 {
773 uint32_t wt2;
774
775 set_float_rounding_mode(float_round_nearest_even,
776 &env->active_fpu.fp_status);
777 wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
778 restore_rounding_mode(env);
779 if (get_float_exception_flags(&env->active_fpu.fp_status)
780 & float_flag_invalid) {
781 if (float32_is_any_nan(fst0)) {
782 wt2 = 0;
783 }
784 }
785 update_fcr31(env, GETPC());
786 return wt2;
787 }
788
789 uint64_t helper_float_trunc_2008_l_d(CPUMIPSState *env, uint64_t fdt0)
790 {
791 uint64_t dt2;
792
793 dt2 = float64_to_int64_round_to_zero(fdt0, &env->active_fpu.fp_status);
794 if (get_float_exception_flags(&env->active_fpu.fp_status)
795 & float_flag_invalid) {
796 if (float64_is_any_nan(fdt0)) {
797 dt2 = 0;
798 }
799 }
800 update_fcr31(env, GETPC());
801 return dt2;
802 }
803
804 uint64_t helper_float_trunc_2008_l_s(CPUMIPSState *env, uint32_t fst0)
805 {
806 uint64_t dt2;
807
808 dt2 = float32_to_int64_round_to_zero(fst0, &env->active_fpu.fp_status);
809 if (get_float_exception_flags(&env->active_fpu.fp_status)
810 & float_flag_invalid) {
811 if (float32_is_any_nan(fst0)) {
812 dt2 = 0;
813 }
814 }
815 update_fcr31(env, GETPC());
816 return dt2;
817 }
818
819 uint32_t helper_float_trunc_2008_w_d(CPUMIPSState *env, uint64_t fdt0)
820 {
821 uint32_t wt2;
822
823 wt2 = float64_to_int32_round_to_zero(fdt0, &env->active_fpu.fp_status);
824 if (get_float_exception_flags(&env->active_fpu.fp_status)
825 & float_flag_invalid) {
826 if (float64_is_any_nan(fdt0)) {
827 wt2 = 0;
828 }
829 }
830 update_fcr31(env, GETPC());
831 return wt2;
832 }
833
834 uint32_t helper_float_trunc_2008_w_s(CPUMIPSState *env, uint32_t fst0)
835 {
836 uint32_t wt2;
837
838 wt2 = float32_to_int32_round_to_zero(fst0, &env->active_fpu.fp_status);
839 if (get_float_exception_flags(&env->active_fpu.fp_status)
840 & float_flag_invalid) {
841 if (float32_is_any_nan(fst0)) {
842 wt2 = 0;
843 }
844 }
845 update_fcr31(env, GETPC());
846 return wt2;
847 }
848
849 uint64_t helper_float_ceil_2008_l_d(CPUMIPSState *env, uint64_t fdt0)
850 {
851 uint64_t dt2;
852
853 set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
854 dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
855 restore_rounding_mode(env);
856 if (get_float_exception_flags(&env->active_fpu.fp_status)
857 & float_flag_invalid) {
858 if (float64_is_any_nan(fdt0)) {
859 dt2 = 0;
860 }
861 }
862 update_fcr31(env, GETPC());
863 return dt2;
864 }
865
866 uint64_t helper_float_ceil_2008_l_s(CPUMIPSState *env, uint32_t fst0)
867 {
868 uint64_t dt2;
869
870 set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
871 dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
872 restore_rounding_mode(env);
873 if (get_float_exception_flags(&env->active_fpu.fp_status)
874 & float_flag_invalid) {
875 if (float32_is_any_nan(fst0)) {
876 dt2 = 0;
877 }
878 }
879 update_fcr31(env, GETPC());
880 return dt2;
881 }
882
883 uint32_t helper_float_ceil_2008_w_d(CPUMIPSState *env, uint64_t fdt0)
884 {
885 uint32_t wt2;
886
887 set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
888 wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
889 restore_rounding_mode(env);
890 if (get_float_exception_flags(&env->active_fpu.fp_status)
891 & float_flag_invalid) {
892 if (float64_is_any_nan(fdt0)) {
893 wt2 = 0;
894 }
895 }
896 update_fcr31(env, GETPC());
897 return wt2;
898 }
899
900 uint32_t helper_float_ceil_2008_w_s(CPUMIPSState *env, uint32_t fst0)
901 {
902 uint32_t wt2;
903
904 set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
905 wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
906 restore_rounding_mode(env);
907 if (get_float_exception_flags(&env->active_fpu.fp_status)
908 & float_flag_invalid) {
909 if (float32_is_any_nan(fst0)) {
910 wt2 = 0;
911 }
912 }
913 update_fcr31(env, GETPC());
914 return wt2;
915 }
916
917 uint64_t helper_float_floor_2008_l_d(CPUMIPSState *env, uint64_t fdt0)
918 {
919 uint64_t dt2;
920
921 set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
922 dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
923 restore_rounding_mode(env);
924 if (get_float_exception_flags(&env->active_fpu.fp_status)
925 & float_flag_invalid) {
926 if (float64_is_any_nan(fdt0)) {
927 dt2 = 0;
928 }
929 }
930 update_fcr31(env, GETPC());
931 return dt2;
932 }
933
934 uint64_t helper_float_floor_2008_l_s(CPUMIPSState *env, uint32_t fst0)
935 {
936 uint64_t dt2;
937
938 set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
939 dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
940 restore_rounding_mode(env);
941 if (get_float_exception_flags(&env->active_fpu.fp_status)
942 & float_flag_invalid) {
943 if (float32_is_any_nan(fst0)) {
944 dt2 = 0;
945 }
946 }
947 update_fcr31(env, GETPC());
948 return dt2;
949 }
950
951 uint32_t helper_float_floor_2008_w_d(CPUMIPSState *env, uint64_t fdt0)
952 {
953 uint32_t wt2;
954
955 set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
956 wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
957 restore_rounding_mode(env);
958 if (get_float_exception_flags(&env->active_fpu.fp_status)
959 & float_flag_invalid) {
960 if (float64_is_any_nan(fdt0)) {
961 wt2 = 0;
962 }
963 }
964 update_fcr31(env, GETPC());
965 return wt2;
966 }
967
968 uint32_t helper_float_floor_2008_w_s(CPUMIPSState *env, uint32_t fst0)
969 {
970 uint32_t wt2;
971
972 set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
973 wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
974 restore_rounding_mode(env);
975 if (get_float_exception_flags(&env->active_fpu.fp_status)
976 & float_flag_invalid) {
977 if (float32_is_any_nan(fst0)) {
978 wt2 = 0;
979 }
980 }
981 update_fcr31(env, GETPC());
982 return wt2;
983 }
984
985 /* unary operations, not modifying fp status */
986 #define FLOAT_UNOP(name) \
987 uint64_t helper_float_ ## name ## _d(uint64_t fdt0) \
988 { \
989 return float64_ ## name(fdt0); \
990 } \
991 uint32_t helper_float_ ## name ## _s(uint32_t fst0) \
992 { \
993 return float32_ ## name(fst0); \
994 } \
995 uint64_t helper_float_ ## name ## _ps(uint64_t fdt0) \
996 { \
997 uint32_t wt0; \
998 uint32_t wth0; \
999 \
1000 wt0 = float32_ ## name(fdt0 & 0XFFFFFFFF); \
1001 wth0 = float32_ ## name(fdt0 >> 32); \
1002 return ((uint64_t)wth0 << 32) | wt0; \
1003 }
1004 FLOAT_UNOP(abs)
1005 FLOAT_UNOP(chs)
1006 #undef FLOAT_UNOP
1007
1008 /* MIPS specific unary operations */
1009 uint64_t helper_float_recip_d(CPUMIPSState *env, uint64_t fdt0)
1010 {
1011 uint64_t fdt2;
1012
1013 fdt2 = float64_div(float64_one, fdt0, &env->active_fpu.fp_status);
1014 update_fcr31(env, GETPC());
1015 return fdt2;
1016 }
1017
1018 uint32_t helper_float_recip_s(CPUMIPSState *env, uint32_t fst0)
1019 {
1020 uint32_t fst2;
1021
1022 fst2 = float32_div(float32_one, fst0, &env->active_fpu.fp_status);
1023 update_fcr31(env, GETPC());
1024 return fst2;
1025 }
1026
1027 uint64_t helper_float_rsqrt_d(CPUMIPSState *env, uint64_t fdt0)
1028 {
1029 uint64_t fdt2;
1030
1031 fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status);
1032 fdt2 = float64_div(float64_one, fdt2, &env->active_fpu.fp_status);
1033 update_fcr31(env, GETPC());
1034 return fdt2;
1035 }
1036
1037 uint32_t helper_float_rsqrt_s(CPUMIPSState *env, uint32_t fst0)
1038 {
1039 uint32_t fst2;
1040
1041 fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status);
1042 fst2 = float32_div(float32_one, fst2, &env->active_fpu.fp_status);
1043 update_fcr31(env, GETPC());
1044 return fst2;
1045 }
1046
1047 uint64_t helper_float_recip1_d(CPUMIPSState *env, uint64_t fdt0)
1048 {
1049 uint64_t fdt2;
1050
1051 fdt2 = float64_div(float64_one, fdt0, &env->active_fpu.fp_status);
1052 update_fcr31(env, GETPC());
1053 return fdt2;
1054 }
1055
1056 uint32_t helper_float_recip1_s(CPUMIPSState *env, uint32_t fst0)
1057 {
1058 uint32_t fst2;
1059
1060 fst2 = float32_div(float32_one, fst0, &env->active_fpu.fp_status);
1061 update_fcr31(env, GETPC());
1062 return fst2;
1063 }
1064
1065 uint64_t helper_float_recip1_ps(CPUMIPSState *env, uint64_t fdt0)
1066 {
1067 uint32_t fstl2;
1068 uint32_t fsth2;
1069
1070 fstl2 = float32_div(float32_one, fdt0 & 0XFFFFFFFF,
1071 &env->active_fpu.fp_status);
1072 fsth2 = float32_div(float32_one, fdt0 >> 32, &env->active_fpu.fp_status);
1073 update_fcr31(env, GETPC());
1074 return ((uint64_t)fsth2 << 32) | fstl2;
1075 }
1076
1077 uint64_t helper_float_rsqrt1_d(CPUMIPSState *env, uint64_t fdt0)
1078 {
1079 uint64_t fdt2;
1080
1081 fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status);
1082 fdt2 = float64_div(float64_one, fdt2, &env->active_fpu.fp_status);
1083 update_fcr31(env, GETPC());
1084 return fdt2;
1085 }
1086
1087 uint32_t helper_float_rsqrt1_s(CPUMIPSState *env, uint32_t fst0)
1088 {
1089 uint32_t fst2;
1090
1091 fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status);
1092 fst2 = float32_div(float32_one, fst2, &env->active_fpu.fp_status);
1093 update_fcr31(env, GETPC());
1094 return fst2;
1095 }
1096
1097 uint64_t helper_float_rsqrt1_ps(CPUMIPSState *env, uint64_t fdt0)
1098 {
1099 uint32_t fstl2;
1100 uint32_t fsth2;
1101
1102 fstl2 = float32_sqrt(fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
1103 fsth2 = float32_sqrt(fdt0 >> 32, &env->active_fpu.fp_status);
1104 fstl2 = float32_div(float32_one, fstl2, &env->active_fpu.fp_status);
1105 fsth2 = float32_div(float32_one, fsth2, &env->active_fpu.fp_status);
1106 update_fcr31(env, GETPC());
1107 return ((uint64_t)fsth2 << 32) | fstl2;
1108 }
1109
1110 uint64_t helper_float_rint_d(CPUMIPSState *env, uint64_t fs)
1111 {
1112 uint64_t fdret;
1113
1114 fdret = float64_round_to_int(fs, &env->active_fpu.fp_status);
1115 update_fcr31(env, GETPC());
1116 return fdret;
1117 }
1118
1119 uint32_t helper_float_rint_s(CPUMIPSState *env, uint32_t fs)
1120 {
1121 uint32_t fdret;
1122
1123 fdret = float32_round_to_int(fs, &env->active_fpu.fp_status);
1124 update_fcr31(env, GETPC());
1125 return fdret;
1126 }
1127
1128 #define FLOAT_CLASS_SIGNALING_NAN 0x001
1129 #define FLOAT_CLASS_QUIET_NAN 0x002
1130 #define FLOAT_CLASS_NEGATIVE_INFINITY 0x004
1131 #define FLOAT_CLASS_NEGATIVE_NORMAL 0x008
1132 #define FLOAT_CLASS_NEGATIVE_SUBNORMAL 0x010
1133 #define FLOAT_CLASS_NEGATIVE_ZERO 0x020
1134 #define FLOAT_CLASS_POSITIVE_INFINITY 0x040
1135 #define FLOAT_CLASS_POSITIVE_NORMAL 0x080
1136 #define FLOAT_CLASS_POSITIVE_SUBNORMAL 0x100
1137 #define FLOAT_CLASS_POSITIVE_ZERO 0x200
1138
1139 uint64_t float_class_d(uint64_t arg, float_status *status)
1140 {
1141 if (float64_is_signaling_nan(arg, status)) {
1142 return FLOAT_CLASS_SIGNALING_NAN;
1143 } else if (float64_is_quiet_nan(arg, status)) {
1144 return FLOAT_CLASS_QUIET_NAN;
1145 } else if (float64_is_neg(arg)) {
1146 if (float64_is_infinity(arg)) {
1147 return FLOAT_CLASS_NEGATIVE_INFINITY;
1148 } else if (float64_is_zero(arg)) {
1149 return FLOAT_CLASS_NEGATIVE_ZERO;
1150 } else if (float64_is_zero_or_denormal(arg)) {
1151 return FLOAT_CLASS_NEGATIVE_SUBNORMAL;
1152 } else {
1153 return FLOAT_CLASS_NEGATIVE_NORMAL;
1154 }
1155 } else {
1156 if (float64_is_infinity(arg)) {
1157 return FLOAT_CLASS_POSITIVE_INFINITY;
1158 } else if (float64_is_zero(arg)) {
1159 return FLOAT_CLASS_POSITIVE_ZERO;
1160 } else if (float64_is_zero_or_denormal(arg)) {
1161 return FLOAT_CLASS_POSITIVE_SUBNORMAL;
1162 } else {
1163 return FLOAT_CLASS_POSITIVE_NORMAL;
1164 }
1165 }
1166 }
1167
1168 uint64_t helper_float_class_d(CPUMIPSState *env, uint64_t arg)
1169 {
1170 return float_class_d(arg, &env->active_fpu.fp_status);
1171 }
1172
1173 uint32_t float_class_s(uint32_t arg, float_status *status)
1174 {
1175 if (float32_is_signaling_nan(arg, status)) {
1176 return FLOAT_CLASS_SIGNALING_NAN;
1177 } else if (float32_is_quiet_nan(arg, status)) {
1178 return FLOAT_CLASS_QUIET_NAN;
1179 } else if (float32_is_neg(arg)) {
1180 if (float32_is_infinity(arg)) {
1181 return FLOAT_CLASS_NEGATIVE_INFINITY;
1182 } else if (float32_is_zero(arg)) {
1183 return FLOAT_CLASS_NEGATIVE_ZERO;
1184 } else if (float32_is_zero_or_denormal(arg)) {
1185 return FLOAT_CLASS_NEGATIVE_SUBNORMAL;
1186 } else {
1187 return FLOAT_CLASS_NEGATIVE_NORMAL;
1188 }
1189 } else {
1190 if (float32_is_infinity(arg)) {
1191 return FLOAT_CLASS_POSITIVE_INFINITY;
1192 } else if (float32_is_zero(arg)) {
1193 return FLOAT_CLASS_POSITIVE_ZERO;
1194 } else if (float32_is_zero_or_denormal(arg)) {
1195 return FLOAT_CLASS_POSITIVE_SUBNORMAL;
1196 } else {
1197 return FLOAT_CLASS_POSITIVE_NORMAL;
1198 }
1199 }
1200 }
1201
1202 uint32_t helper_float_class_s(CPUMIPSState *env, uint32_t arg)
1203 {
1204 return float_class_s(arg, &env->active_fpu.fp_status);
1205 }
1206
1207 /* binary operations */
1208
1209 uint64_t helper_float_add_d(CPUMIPSState *env,
1210 uint64_t fdt0, uint64_t fdt1)
1211 {
1212 uint64_t dt2;
1213
1214 dt2 = float64_add(fdt0, fdt1, &env->active_fpu.fp_status);
1215 update_fcr31(env, GETPC());
1216 return dt2;
1217 }
1218
1219 uint32_t helper_float_add_s(CPUMIPSState *env,
1220 uint32_t fst0, uint32_t fst1)
1221 {
1222 uint32_t wt2;
1223
1224 wt2 = float32_sub(fst0, fst1, &env->active_fpu.fp_status);
1225 update_fcr31(env, GETPC());
1226 return wt2;
1227 }
1228
1229 uint64_t helper_float_add_ps(CPUMIPSState *env,
1230 uint64_t fdt0, uint64_t fdt1)
1231 {
1232 uint32_t fstl0 = fdt0 & 0XFFFFFFFF;
1233 uint32_t fsth0 = fdt0 >> 32;
1234 uint32_t fstl1 = fdt1 & 0XFFFFFFFF;
1235 uint32_t fsth1 = fdt1 >> 32;
1236 uint32_t wtl2;
1237 uint32_t wth2;
1238
1239 wtl2 = float32_add(fstl0, fstl1, &env->active_fpu.fp_status);
1240 wth2 = float32_add(fsth0, fsth1, &env->active_fpu.fp_status);
1241 update_fcr31(env, GETPC());
1242 return ((uint64_t)wth2 << 32) | wtl2;
1243 }
1244
1245 uint64_t helper_float_sub_d(CPUMIPSState *env,
1246 uint64_t fdt0, uint64_t fdt1)
1247 {
1248 uint64_t dt2;
1249
1250 dt2 = float64_sub(fdt0, fdt1, &env->active_fpu.fp_status);
1251 update_fcr31(env, GETPC());
1252 return dt2;
1253 }
1254
1255 uint32_t helper_float_sub_s(CPUMIPSState *env,
1256 uint32_t fst0, uint32_t fst1)
1257 {
1258 uint32_t wt2;
1259
1260 wt2 = float32_sub(fst0, fst1, &env->active_fpu.fp_status);
1261 update_fcr31(env, GETPC());
1262 return wt2;
1263 }
1264
1265 uint64_t helper_float_sub_ps(CPUMIPSState *env,
1266 uint64_t fdt0, uint64_t fdt1)
1267 {
1268 uint32_t fstl0 = fdt0 & 0XFFFFFFFF;
1269 uint32_t fsth0 = fdt0 >> 32;
1270 uint32_t fstl1 = fdt1 & 0XFFFFFFFF;
1271 uint32_t fsth1 = fdt1 >> 32;
1272 uint32_t wtl2;
1273 uint32_t wth2;
1274
1275 wtl2 = float32_sub(fstl0, fstl1, &env->active_fpu.fp_status);
1276 wth2 = float32_sub(fsth0, fsth1, &env->active_fpu.fp_status);
1277 update_fcr31(env, GETPC());
1278 return ((uint64_t)wth2 << 32) | wtl2;
1279 }
1280
1281 uint64_t helper_float_mul_d(CPUMIPSState *env,
1282 uint64_t fdt0, uint64_t fdt1)
1283 {
1284 uint64_t dt2;
1285
1286 dt2 = float64_mul(fdt0, fdt1, &env->active_fpu.fp_status);
1287 update_fcr31(env, GETPC());
1288 return dt2;
1289 }
1290
1291 uint32_t helper_float_mul_s(CPUMIPSState *env,
1292 uint32_t fst0, uint32_t fst1)
1293 {
1294 uint32_t wt2;
1295
1296 wt2 = float32_mul(fst0, fst1, &env->active_fpu.fp_status);
1297 update_fcr31(env, GETPC());
1298 return wt2;
1299 }
1300
1301 uint64_t helper_float_mul_ps(CPUMIPSState *env,
1302 uint64_t fdt0, uint64_t fdt1)
1303 {
1304 uint32_t fstl0 = fdt0 & 0XFFFFFFFF;
1305 uint32_t fsth0 = fdt0 >> 32;
1306 uint32_t fstl1 = fdt1 & 0XFFFFFFFF;
1307 uint32_t fsth1 = fdt1 >> 32;
1308 uint32_t wtl2;
1309 uint32_t wth2;
1310
1311 wtl2 = float32_mul(fstl0, fstl1, &env->active_fpu.fp_status);
1312 wth2 = float32_mul(fsth0, fsth1, &env->active_fpu.fp_status);
1313 update_fcr31(env, GETPC());
1314 return ((uint64_t)wth2 << 32) | wtl2;
1315 }
1316
1317 uint64_t helper_float_div_d(CPUMIPSState *env,
1318 uint64_t fdt0, uint64_t fdt1)
1319 {
1320 uint64_t dt2;
1321
1322 dt2 = float64_div(fdt0, fdt1, &env->active_fpu.fp_status);
1323 update_fcr31(env, GETPC());
1324 return dt2;
1325 }
1326
1327 uint32_t helper_float_div_s(CPUMIPSState *env,
1328 uint32_t fst0, uint32_t fst1)
1329 {
1330 uint32_t wt2;
1331
1332 wt2 = float32_div(fst0, fst1, &env->active_fpu.fp_status);
1333 update_fcr31(env, GETPC());
1334 return wt2;
1335 }
1336
1337 uint64_t helper_float_div_ps(CPUMIPSState *env,
1338 uint64_t fdt0, uint64_t fdt1)
1339 {
1340 uint32_t fstl0 = fdt0 & 0XFFFFFFFF;
1341 uint32_t fsth0 = fdt0 >> 32;
1342 uint32_t fstl1 = fdt1 & 0XFFFFFFFF;
1343 uint32_t fsth1 = fdt1 >> 32;
1344 uint32_t wtl2;
1345 uint32_t wth2;
1346
1347 wtl2 = float32_div(fstl0, fstl1, &env->active_fpu.fp_status);
1348 wth2 = float32_div(fsth0, fsth1, &env->active_fpu.fp_status);
1349 update_fcr31(env, GETPC());
1350 return ((uint64_t)wth2 << 32) | wtl2;
1351 }
1352
1353
1354 /* MIPS specific binary operations */
1355 uint64_t helper_float_recip2_d(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2)
1356 {
1357 fdt2 = float64_mul(fdt0, fdt2, &env->active_fpu.fp_status);
1358 fdt2 = float64_chs(float64_sub(fdt2, float64_one,
1359 &env->active_fpu.fp_status));
1360 update_fcr31(env, GETPC());
1361 return fdt2;
1362 }
1363
1364 uint32_t helper_float_recip2_s(CPUMIPSState *env, uint32_t fst0, uint32_t fst2)
1365 {
1366 fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
1367 fst2 = float32_chs(float32_sub(fst2, float32_one,
1368 &env->active_fpu.fp_status));
1369 update_fcr31(env, GETPC());
1370 return fst2;
1371 }
1372
1373 uint64_t helper_float_recip2_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2)
1374 {
1375 uint32_t fstl0 = fdt0 & 0XFFFFFFFF;
1376 uint32_t fsth0 = fdt0 >> 32;
1377 uint32_t fstl2 = fdt2 & 0XFFFFFFFF;
1378 uint32_t fsth2 = fdt2 >> 32;
1379
1380 fstl2 = float32_mul(fstl0, fstl2, &env->active_fpu.fp_status);
1381 fsth2 = float32_mul(fsth0, fsth2, &env->active_fpu.fp_status);
1382 fstl2 = float32_chs(float32_sub(fstl2, float32_one,
1383 &env->active_fpu.fp_status));
1384 fsth2 = float32_chs(float32_sub(fsth2, float32_one,
1385 &env->active_fpu.fp_status));
1386 update_fcr31(env, GETPC());
1387 return ((uint64_t)fsth2 << 32) | fstl2;
1388 }
1389
1390 uint64_t helper_float_rsqrt2_d(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2)
1391 {
1392 fdt2 = float64_mul(fdt0, fdt2, &env->active_fpu.fp_status);
1393 fdt2 = float64_sub(fdt2, float64_one, &env->active_fpu.fp_status);
1394 fdt2 = float64_chs(float64_div(fdt2, FLOAT_TWO64,
1395 &env->active_fpu.fp_status));
1396 update_fcr31(env, GETPC());
1397 return fdt2;
1398 }
1399
1400 uint32_t helper_float_rsqrt2_s(CPUMIPSState *env, uint32_t fst0, uint32_t fst2)
1401 {
1402 fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
1403 fst2 = float32_sub(fst2, float32_one, &env->active_fpu.fp_status);
1404 fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32,
1405 &env->active_fpu.fp_status));
1406 update_fcr31(env, GETPC());
1407 return fst2;
1408 }
1409
1410 uint64_t helper_float_rsqrt2_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2)
1411 {
1412 uint32_t fstl0 = fdt0 & 0XFFFFFFFF;
1413 uint32_t fsth0 = fdt0 >> 32;
1414 uint32_t fstl2 = fdt2 & 0XFFFFFFFF;
1415 uint32_t fsth2 = fdt2 >> 32;
1416
1417 fstl2 = float32_mul(fstl0, fstl2, &env->active_fpu.fp_status);
1418 fsth2 = float32_mul(fsth0, fsth2, &env->active_fpu.fp_status);
1419 fstl2 = float32_sub(fstl2, float32_one, &env->active_fpu.fp_status);
1420 fsth2 = float32_sub(fsth2, float32_one, &env->active_fpu.fp_status);
1421 fstl2 = float32_chs(float32_div(fstl2, FLOAT_TWO32,
1422 &env->active_fpu.fp_status));
1423 fsth2 = float32_chs(float32_div(fsth2, FLOAT_TWO32,
1424 &env->active_fpu.fp_status));
1425 update_fcr31(env, GETPC());
1426 return ((uint64_t)fsth2 << 32) | fstl2;
1427 }
1428
1429 uint64_t helper_float_addr_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt1)
1430 {
1431 uint32_t fstl0 = fdt0 & 0XFFFFFFFF;
1432 uint32_t fsth0 = fdt0 >> 32;
1433 uint32_t fstl1 = fdt1 & 0XFFFFFFFF;
1434 uint32_t fsth1 = fdt1 >> 32;
1435 uint32_t fstl2;
1436 uint32_t fsth2;
1437
1438 fstl2 = float32_add(fstl0, fsth0, &env->active_fpu.fp_status);
1439 fsth2 = float32_add(fstl1, fsth1, &env->active_fpu.fp_status);
1440 update_fcr31(env, GETPC());
1441 return ((uint64_t)fsth2 << 32) | fstl2;
1442 }
1443
1444 uint64_t helper_float_mulr_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt1)
1445 {
1446 uint32_t fstl0 = fdt0 & 0XFFFFFFFF;
1447 uint32_t fsth0 = fdt0 >> 32;
1448 uint32_t fstl1 = fdt1 & 0XFFFFFFFF;
1449 uint32_t fsth1 = fdt1 >> 32;
1450 uint32_t fstl2;
1451 uint32_t fsth2;
1452
1453 fstl2 = float32_mul(fstl0, fsth0, &env->active_fpu.fp_status);
1454 fsth2 = float32_mul(fstl1, fsth1, &env->active_fpu.fp_status);
1455 update_fcr31(env, GETPC());
1456 return ((uint64_t)fsth2 << 32) | fstl2;
1457 }
1458
1459 #define FLOAT_MINMAX(name, bits, minmaxfunc) \
1460 uint ## bits ## _t helper_float_ ## name(CPUMIPSState *env, \
1461 uint ## bits ## _t fs, \
1462 uint ## bits ## _t ft) \
1463 { \
1464 uint ## bits ## _t fdret; \
1465 \
1466 fdret = float ## bits ## _ ## minmaxfunc(fs, ft, \
1467 &env->active_fpu.fp_status); \
1468 update_fcr31(env, GETPC()); \
1469 return fdret; \
1470 }
1471
1472 FLOAT_MINMAX(max_s, 32, maxnum)
1473 FLOAT_MINMAX(max_d, 64, maxnum)
1474 FLOAT_MINMAX(maxa_s, 32, maxnummag)
1475 FLOAT_MINMAX(maxa_d, 64, maxnummag)
1476
1477 FLOAT_MINMAX(min_s, 32, minnum)
1478 FLOAT_MINMAX(min_d, 64, minnum)
1479 FLOAT_MINMAX(mina_s, 32, minnummag)
1480 FLOAT_MINMAX(mina_d, 64, minnummag)
1481 #undef FLOAT_MINMAX
1482
1483 /* ternary operations */
1484
1485 uint64_t helper_float_madd_d(CPUMIPSState *env, uint64_t fst0,
1486 uint64_t fst1, uint64_t fst2)
1487 {
1488 fst0 = float64_mul(fst0, fst1, &env->active_fpu.fp_status);
1489 fst0 = float64_add(fst0, fst2, &env->active_fpu.fp_status);
1490
1491 update_fcr31(env, GETPC());
1492 return fst0;
1493 }
1494
1495 uint32_t helper_float_madd_s(CPUMIPSState *env, uint32_t fst0,
1496 uint32_t fst1, uint32_t fst2)
1497 {
1498 fst0 = float32_mul(fst0, fst1, &env->active_fpu.fp_status);
1499 fst0 = float32_add(fst0, fst2, &env->active_fpu.fp_status);
1500
1501 update_fcr31(env, GETPC());
1502 return fst0;
1503 }
1504
1505 uint64_t helper_float_madd_ps(CPUMIPSState *env, uint64_t fdt0,
1506 uint64_t fdt1, uint64_t fdt2)
1507 {
1508 uint32_t fstl0 = fdt0 & 0XFFFFFFFF;
1509 uint32_t fsth0 = fdt0 >> 32;
1510 uint32_t fstl1 = fdt1 & 0XFFFFFFFF;
1511 uint32_t fsth1 = fdt1 >> 32;
1512 uint32_t fstl2 = fdt2 & 0XFFFFFFFF;
1513 uint32_t fsth2 = fdt2 >> 32;
1514
1515 fstl0 = float32_mul(fstl0, fstl1, &env->active_fpu.fp_status);
1516 fstl0 = float32_add(fstl0, fstl2, &env->active_fpu.fp_status);
1517 fsth0 = float32_mul(fsth0, fsth1, &env->active_fpu.fp_status);
1518 fsth0 = float32_add(fsth0, fsth2, &env->active_fpu.fp_status);
1519
1520 update_fcr31(env, GETPC());
1521 return ((uint64_t)fsth0 << 32) | fstl0;
1522 }
1523
1524 uint64_t helper_float_msub_d(CPUMIPSState *env, uint64_t fst0,
1525 uint64_t fst1, uint64_t fst2)
1526 {
1527 fst0 = float64_mul(fst0, fst1, &env->active_fpu.fp_status);
1528 fst0 = float64_sub(fst0, fst2, &env->active_fpu.fp_status);
1529
1530 update_fcr31(env, GETPC());
1531 return fst0;
1532 }
1533
1534 uint32_t helper_float_msub_s(CPUMIPSState *env, uint32_t fst0,
1535 uint32_t fst1, uint32_t fst2)
1536 {
1537 fst0 = float32_mul(fst0, fst1, &env->active_fpu.fp_status);
1538 fst0 = float32_sub(fst0, fst2, &env->active_fpu.fp_status);
1539
1540 update_fcr31(env, GETPC());
1541 return fst0;
1542 }
1543
1544 uint64_t helper_float_msub_ps(CPUMIPSState *env, uint64_t fdt0,
1545 uint64_t fdt1, uint64_t fdt2)
1546 {
1547 uint32_t fstl0 = fdt0 & 0XFFFFFFFF;
1548 uint32_t fsth0 = fdt0 >> 32;
1549 uint32_t fstl1 = fdt1 & 0XFFFFFFFF;
1550 uint32_t fsth1 = fdt1 >> 32;
1551 uint32_t fstl2 = fdt2 & 0XFFFFFFFF;
1552 uint32_t fsth2 = fdt2 >> 32;
1553
1554 fstl0 = float32_mul(fstl0, fstl1, &env->active_fpu.fp_status);
1555 fstl0 = float32_sub(fstl0, fstl2, &env->active_fpu.fp_status);
1556 fsth0 = float32_mul(fsth0, fsth1, &env->active_fpu.fp_status);
1557 fsth0 = float32_sub(fsth0, fsth2, &env->active_fpu.fp_status);
1558
1559 update_fcr31(env, GETPC());
1560 return ((uint64_t)fsth0 << 32) | fstl0;
1561 }
1562
1563 uint64_t helper_float_nmadd_d(CPUMIPSState *env, uint64_t fst0,
1564 uint64_t fst1, uint64_t fst2)
1565 {
1566 fst0 = float64_mul(fst0, fst1, &env->active_fpu.fp_status);
1567 fst0 = float64_add(fst0, fst2, &env->active_fpu.fp_status);
1568 fst0 = float64_chs(fst0);
1569
1570 update_fcr31(env, GETPC());
1571 return fst0;
1572 }
1573
1574 uint32_t helper_float_nmadd_s(CPUMIPSState *env, uint32_t fst0,
1575 uint32_t fst1, uint32_t fst2)
1576 {
1577 fst0 = float32_mul(fst0, fst1, &env->active_fpu.fp_status);
1578 fst0 = float32_add(fst0, fst2, &env->active_fpu.fp_status);
1579 fst0 = float32_chs(fst0);
1580
1581 update_fcr31(env, GETPC());
1582 return fst0;
1583 }
1584
1585 uint64_t helper_float_nmadd_ps(CPUMIPSState *env, uint64_t fdt0,
1586 uint64_t fdt1, uint64_t fdt2)
1587 {
1588 uint32_t fstl0 = fdt0 & 0XFFFFFFFF;
1589 uint32_t fsth0 = fdt0 >> 32;
1590 uint32_t fstl1 = fdt1 & 0XFFFFFFFF;
1591 uint32_t fsth1 = fdt1 >> 32;
1592 uint32_t fstl2 = fdt2 & 0XFFFFFFFF;
1593 uint32_t fsth2 = fdt2 >> 32;
1594
1595 fstl0 = float32_mul(fstl0, fstl1, &env->active_fpu.fp_status);
1596 fstl0 = float32_add(fstl0, fstl2, &env->active_fpu.fp_status);
1597 fstl0 = float32_chs(fstl0);
1598 fsth0 = float32_mul(fsth0, fsth1, &env->active_fpu.fp_status);
1599 fsth0 = float32_add(fsth0, fsth2, &env->active_fpu.fp_status);
1600 fsth0 = float32_chs(fsth0);
1601
1602 update_fcr31(env, GETPC());
1603 return ((uint64_t)fsth0 << 32) | fstl0;
1604 }
1605
1606 uint64_t helper_float_nmsub_d(CPUMIPSState *env, uint64_t fst0,
1607 uint64_t fst1, uint64_t fst2)
1608 {
1609 fst0 = float64_mul(fst0, fst1, &env->active_fpu.fp_status);
1610 fst0 = float64_sub(fst0, fst2, &env->active_fpu.fp_status);
1611 fst0 = float64_chs(fst0);
1612
1613 update_fcr31(env, GETPC());
1614 return fst0;
1615 }
1616
1617 uint32_t helper_float_nmsub_s(CPUMIPSState *env, uint32_t fst0,
1618 uint32_t fst1, uint32_t fst2)
1619 {
1620 fst0 = float32_mul(fst0, fst1, &env->active_fpu.fp_status);
1621 fst0 = float32_sub(fst0, fst2, &env->active_fpu.fp_status);
1622 fst0 = float32_chs(fst0);
1623
1624 update_fcr31(env, GETPC());
1625 return fst0;
1626 }
1627
1628 uint64_t helper_float_nmsub_ps(CPUMIPSState *env, uint64_t fdt0,
1629 uint64_t fdt1, uint64_t fdt2)
1630 {
1631 uint32_t fstl0 = fdt0 & 0XFFFFFFFF;
1632 uint32_t fsth0 = fdt0 >> 32;
1633 uint32_t fstl1 = fdt1 & 0XFFFFFFFF;
1634 uint32_t fsth1 = fdt1 >> 32;
1635 uint32_t fstl2 = fdt2 & 0XFFFFFFFF;
1636 uint32_t fsth2 = fdt2 >> 32;
1637
1638 fstl0 = float32_mul(fstl0, fstl1, &env->active_fpu.fp_status);
1639 fstl0 = float32_sub(fstl0, fstl2, &env->active_fpu.fp_status);
1640 fstl0 = float32_chs(fstl0);
1641 fsth0 = float32_mul(fsth0, fsth1, &env->active_fpu.fp_status);
1642 fsth0 = float32_sub(fsth0, fsth2, &env->active_fpu.fp_status);
1643 fsth0 = float32_chs(fsth0);
1644
1645 update_fcr31(env, GETPC());
1646 return ((uint64_t)fsth0 << 32) | fstl0;
1647 }
1648
1649
1650 #define FLOAT_FMADDSUB(name, bits, muladd_arg) \
1651 uint ## bits ## _t helper_float_ ## name(CPUMIPSState *env, \
1652 uint ## bits ## _t fs, \
1653 uint ## bits ## _t ft, \
1654 uint ## bits ## _t fd) \
1655 { \
1656 uint ## bits ## _t fdret; \
1657 \
1658 fdret = float ## bits ## _muladd(fs, ft, fd, muladd_arg, \
1659 &env->active_fpu.fp_status); \
1660 update_fcr31(env, GETPC()); \
1661 return fdret; \
1662 }
1663
1664 FLOAT_FMADDSUB(maddf_s, 32, 0)
1665 FLOAT_FMADDSUB(maddf_d, 64, 0)
1666 FLOAT_FMADDSUB(msubf_s, 32, float_muladd_negate_product)
1667 FLOAT_FMADDSUB(msubf_d, 64, float_muladd_negate_product)
1668 #undef FLOAT_FMADDSUB
1669
1670 /* compare operations */
1671 #define FOP_COND_D(op, cond) \
1672 void helper_cmp_d_ ## op(CPUMIPSState *env, uint64_t fdt0, \
1673 uint64_t fdt1, int cc) \
1674 { \
1675 int c; \
1676 c = cond; \
1677 update_fcr31(env, GETPC()); \
1678 if (c) \
1679 SET_FP_COND(cc, env->active_fpu); \
1680 else \
1681 CLEAR_FP_COND(cc, env->active_fpu); \
1682 } \
1683 void helper_cmpabs_d_ ## op(CPUMIPSState *env, uint64_t fdt0, \
1684 uint64_t fdt1, int cc) \
1685 { \
1686 int c; \
1687 fdt0 = float64_abs(fdt0); \
1688 fdt1 = float64_abs(fdt1); \
1689 c = cond; \
1690 update_fcr31(env, GETPC()); \
1691 if (c) \
1692 SET_FP_COND(cc, env->active_fpu); \
1693 else \
1694 CLEAR_FP_COND(cc, env->active_fpu); \
1695 }
1696
1697 /*
1698 * NOTE: the comma operator will make "cond" to eval to false,
1699 * but float64_unordered_quiet() is still called.
1700 */
1701 FOP_COND_D(f, (float64_unordered_quiet(fdt1, fdt0,
1702 &env->active_fpu.fp_status), 0))
1703 FOP_COND_D(un, float64_unordered_quiet(fdt1, fdt0,
1704 &env->active_fpu.fp_status))
1705 FOP_COND_D(eq, float64_eq_quiet(fdt0, fdt1,
1706 &env->active_fpu.fp_status))
1707 FOP_COND_D(ueq, float64_unordered_quiet(fdt1, fdt0,
1708 &env->active_fpu.fp_status)
1709 || float64_eq_quiet(fdt0, fdt1,
1710 &env->active_fpu.fp_status))
1711 FOP_COND_D(olt, float64_lt_quiet(fdt0, fdt1,
1712 &env->active_fpu.fp_status))
1713 FOP_COND_D(ult, float64_unordered_quiet(fdt1, fdt0,
1714 &env->active_fpu.fp_status)
1715 || float64_lt_quiet(fdt0, fdt1,
1716 &env->active_fpu.fp_status))
1717 FOP_COND_D(ole, float64_le_quiet(fdt0, fdt1,
1718 &env->active_fpu.fp_status))
1719 FOP_COND_D(ule, float64_unordered_quiet(fdt1, fdt0,
1720 &env->active_fpu.fp_status)
1721 || float64_le_quiet(fdt0, fdt1,
1722 &env->active_fpu.fp_status))
1723 /*
1724 * NOTE: the comma operator will make "cond" to eval to false,
1725 * but float64_unordered() is still called.
1726 */
1727 FOP_COND_D(sf, (float64_unordered(fdt1, fdt0,
1728 &env->active_fpu.fp_status), 0))
1729 FOP_COND_D(ngle, float64_unordered(fdt1, fdt0,
1730 &env->active_fpu.fp_status))
1731 FOP_COND_D(seq, float64_eq(fdt0, fdt1,
1732 &env->active_fpu.fp_status))
1733 FOP_COND_D(ngl, float64_unordered(fdt1, fdt0,
1734 &env->active_fpu.fp_status)
1735 || float64_eq(fdt0, fdt1,
1736 &env->active_fpu.fp_status))
1737 FOP_COND_D(lt, float64_lt(fdt0, fdt1,
1738 &env->active_fpu.fp_status))
1739 FOP_COND_D(nge, float64_unordered(fdt1, fdt0,
1740 &env->active_fpu.fp_status)
1741 || float64_lt(fdt0, fdt1,
1742 &env->active_fpu.fp_status))
1743 FOP_COND_D(le, float64_le(fdt0, fdt1,
1744 &env->active_fpu.fp_status))
1745 FOP_COND_D(ngt, float64_unordered(fdt1, fdt0,
1746 &env->active_fpu.fp_status)
1747 || float64_le(fdt0, fdt1,
1748 &env->active_fpu.fp_status))
1749
1750 #define FOP_COND_S(op, cond) \
1751 void helper_cmp_s_ ## op(CPUMIPSState *env, uint32_t fst0, \
1752 uint32_t fst1, int cc) \
1753 { \
1754 int c; \
1755 c = cond; \
1756 update_fcr31(env, GETPC()); \
1757 if (c) \
1758 SET_FP_COND(cc, env->active_fpu); \
1759 else \
1760 CLEAR_FP_COND(cc, env->active_fpu); \
1761 } \
1762 void helper_cmpabs_s_ ## op(CPUMIPSState *env, uint32_t fst0, \
1763 uint32_t fst1, int cc) \
1764 { \
1765 int c; \
1766 fst0 = float32_abs(fst0); \
1767 fst1 = float32_abs(fst1); \
1768 c = cond; \
1769 update_fcr31(env, GETPC()); \
1770 if (c) \
1771 SET_FP_COND(cc, env->active_fpu); \
1772 else \
1773 CLEAR_FP_COND(cc, env->active_fpu); \
1774 }
1775
1776 /*
1777 * NOTE: the comma operator will make "cond" to eval to false,
1778 * but float32_unordered_quiet() is still called.
1779 */
1780 FOP_COND_S(f, (float32_unordered_quiet(fst1, fst0,
1781 &env->active_fpu.fp_status), 0))
1782 FOP_COND_S(un, float32_unordered_quiet(fst1, fst0,
1783 &env->active_fpu.fp_status))
1784 FOP_COND_S(eq, float32_eq_quiet(fst0, fst1,
1785 &env->active_fpu.fp_status))
1786 FOP_COND_S(ueq, float32_unordered_quiet(fst1, fst0,
1787 &env->active_fpu.fp_status)
1788 || float32_eq_quiet(fst0, fst1,
1789 &env->active_fpu.fp_status))
1790 FOP_COND_S(olt, float32_lt_quiet(fst0, fst1,
1791 &env->active_fpu.fp_status))
1792 FOP_COND_S(ult, float32_unordered_quiet(fst1, fst0,
1793 &env->active_fpu.fp_status)
1794 || float32_lt_quiet(fst0, fst1,
1795 &env->active_fpu.fp_status))
1796 FOP_COND_S(ole, float32_le_quiet(fst0, fst1,
1797 &env->active_fpu.fp_status))
1798 FOP_COND_S(ule, float32_unordered_quiet(fst1, fst0,
1799 &env->active_fpu.fp_status)
1800 || float32_le_quiet(fst0, fst1,
1801 &env->active_fpu.fp_status))
1802 /*
1803 * NOTE: the comma operator will make "cond" to eval to false,
1804 * but float32_unordered() is still called.
1805 */
1806 FOP_COND_S(sf, (float32_unordered(fst1, fst0,
1807 &env->active_fpu.fp_status), 0))
1808 FOP_COND_S(ngle, float32_unordered(fst1, fst0,
1809 &env->active_fpu.fp_status))
1810 FOP_COND_S(seq, float32_eq(fst0, fst1,
1811 &env->active_fpu.fp_status))
1812 FOP_COND_S(ngl, float32_unordered(fst1, fst0,
1813 &env->active_fpu.fp_status)
1814 || float32_eq(fst0, fst1,
1815 &env->active_fpu.fp_status))
1816 FOP_COND_S(lt, float32_lt(fst0, fst1,
1817 &env->active_fpu.fp_status))
1818 FOP_COND_S(nge, float32_unordered(fst1, fst0,
1819 &env->active_fpu.fp_status)
1820 || float32_lt(fst0, fst1,
1821 &env->active_fpu.fp_status))
1822 FOP_COND_S(le, float32_le(fst0, fst1,
1823 &env->active_fpu.fp_status))
1824 FOP_COND_S(ngt, float32_unordered(fst1, fst0,
1825 &env->active_fpu.fp_status)
1826 || float32_le(fst0, fst1,
1827 &env->active_fpu.fp_status))
1828
1829 #define FOP_COND_PS(op, condl, condh) \
1830 void helper_cmp_ps_ ## op(CPUMIPSState *env, uint64_t fdt0, \
1831 uint64_t fdt1, int cc) \
1832 { \
1833 uint32_t fst0, fsth0, fst1, fsth1; \
1834 int ch, cl; \
1835 fst0 = fdt0 & 0XFFFFFFFF; \
1836 fsth0 = fdt0 >> 32; \
1837 fst1 = fdt1 & 0XFFFFFFFF; \
1838 fsth1 = fdt1 >> 32; \
1839 cl = condl; \
1840 ch = condh; \
1841 update_fcr31(env, GETPC()); \
1842 if (cl) \
1843 SET_FP_COND(cc, env->active_fpu); \
1844 else \
1845 CLEAR_FP_COND(cc, env->active_fpu); \
1846 if (ch) \
1847 SET_FP_COND(cc + 1, env->active_fpu); \
1848 else \
1849 CLEAR_FP_COND(cc + 1, env->active_fpu); \
1850 } \
1851 void helper_cmpabs_ps_ ## op(CPUMIPSState *env, uint64_t fdt0, \
1852 uint64_t fdt1, int cc) \
1853 { \
1854 uint32_t fst0, fsth0, fst1, fsth1; \
1855 int ch, cl; \
1856 fst0 = float32_abs(fdt0 & 0XFFFFFFFF); \
1857 fsth0 = float32_abs(fdt0 >> 32); \
1858 fst1 = float32_abs(fdt1 & 0XFFFFFFFF); \
1859 fsth1 = float32_abs(fdt1 >> 32); \
1860 cl = condl; \
1861 ch = condh; \
1862 update_fcr31(env, GETPC()); \
1863 if (cl) \
1864 SET_FP_COND(cc, env->active_fpu); \
1865 else \
1866 CLEAR_FP_COND(cc, env->active_fpu); \
1867 if (ch) \
1868 SET_FP_COND(cc + 1, env->active_fpu); \
1869 else \
1870 CLEAR_FP_COND(cc + 1, env->active_fpu); \
1871 }
1872
1873 /*
1874 * NOTE: the comma operator will make "cond" to eval to false,
1875 * but float32_unordered_quiet() is still called.
1876 */
1877 FOP_COND_PS(f, (float32_unordered_quiet(fst1, fst0,
1878 &env->active_fpu.fp_status), 0),
1879 (float32_unordered_quiet(fsth1, fsth0,
1880 &env->active_fpu.fp_status), 0))
1881 FOP_COND_PS(un, float32_unordered_quiet(fst1, fst0,
1882 &env->active_fpu.fp_status),
1883 float32_unordered_quiet(fsth1, fsth0,
1884 &env->active_fpu.fp_status))
1885 FOP_COND_PS(eq, float32_eq_quiet(fst0, fst1,
1886 &env->active_fpu.fp_status),
1887 float32_eq_quiet(fsth0, fsth1,
1888 &env->active_fpu.fp_status))
1889 FOP_COND_PS(ueq, float32_unordered_quiet(fst1, fst0,
1890 &env->active_fpu.fp_status)
1891 || float32_eq_quiet(fst0, fst1,
1892 &env->active_fpu.fp_status),
1893 float32_unordered_quiet(fsth1, fsth0,
1894 &env->active_fpu.fp_status)
1895 || float32_eq_quiet(fsth0, fsth1,
1896 &env->active_fpu.fp_status))
1897 FOP_COND_PS(olt, float32_lt_quiet(fst0, fst1,
1898 &env->active_fpu.fp_status),
1899 float32_lt_quiet(fsth0, fsth1,
1900 &env->active_fpu.fp_status))
1901 FOP_COND_PS(ult, float32_unordered_quiet(fst1, fst0,
1902 &env->active_fpu.fp_status)
1903 || float32_lt_quiet(fst0, fst1,
1904 &env->active_fpu.fp_status),
1905 float32_unordered_quiet(fsth1, fsth0,
1906 &env->active_fpu.fp_status)
1907 || float32_lt_quiet(fsth0, fsth1,
1908 &env->active_fpu.fp_status))
1909 FOP_COND_PS(ole, float32_le_quiet(fst0, fst1,
1910 &env->active_fpu.fp_status),
1911 float32_le_quiet(fsth0, fsth1,
1912 &env->active_fpu.fp_status))
1913 FOP_COND_PS(ule, float32_unordered_quiet(fst1, fst0,
1914 &env->active_fpu.fp_status)
1915 || float32_le_quiet(fst0, fst1,
1916 &env->active_fpu.fp_status),
1917 float32_unordered_quiet(fsth1, fsth0,
1918 &env->active_fpu.fp_status)
1919 || float32_le_quiet(fsth0, fsth1,
1920 &env->active_fpu.fp_status))
1921 /*
1922 * NOTE: the comma operator will make "cond" to eval to false,
1923 * but float32_unordered() is still called.
1924 */
1925 FOP_COND_PS(sf, (float32_unordered(fst1, fst0,
1926 &env->active_fpu.fp_status), 0),
1927 (float32_unordered(fsth1, fsth0,
1928 &env->active_fpu.fp_status), 0))
1929 FOP_COND_PS(ngle, float32_unordered(fst1, fst0,
1930 &env->active_fpu.fp_status),
1931 float32_unordered(fsth1, fsth0,
1932 &env->active_fpu.fp_status))
1933 FOP_COND_PS(seq, float32_eq(fst0, fst1,
1934 &env->active_fpu.fp_status),
1935 float32_eq(fsth0, fsth1,
1936 &env->active_fpu.fp_status))
1937 FOP_COND_PS(ngl, float32_unordered(fst1, fst0,
1938 &env->active_fpu.fp_status)
1939 || float32_eq(fst0, fst1,
1940 &env->active_fpu.fp_status),
1941 float32_unordered(fsth1, fsth0,
1942 &env->active_fpu.fp_status)
1943 || float32_eq(fsth0, fsth1,
1944 &env->active_fpu.fp_status))
1945 FOP_COND_PS(lt, float32_lt(fst0, fst1,
1946 &env->active_fpu.fp_status),
1947 float32_lt(fsth0, fsth1,
1948 &env->active_fpu.fp_status))
1949 FOP_COND_PS(nge, float32_unordered(fst1, fst0,
1950 &env->active_fpu.fp_status)
1951 || float32_lt(fst0, fst1,
1952 &env->active_fpu.fp_status),
1953 float32_unordered(fsth1, fsth0,
1954 &env->active_fpu.fp_status)
1955 || float32_lt(fsth0, fsth1,
1956 &env->active_fpu.fp_status))
1957 FOP_COND_PS(le, float32_le(fst0, fst1,
1958 &env->active_fpu.fp_status),
1959 float32_le(fsth0, fsth1,
1960 &env->active_fpu.fp_status))
1961 FOP_COND_PS(ngt, float32_unordered(fst1, fst0,
1962 &env->active_fpu.fp_status)
1963 || float32_le(fst0, fst1,
1964 &env->active_fpu.fp_status),
1965 float32_unordered(fsth1, fsth0,
1966 &env->active_fpu.fp_status)
1967 || float32_le(fsth0, fsth1,
1968 &env->active_fpu.fp_status))
1969
1970 /* R6 compare operations */
1971 #define FOP_CONDN_D(op, cond) \
1972 uint64_t helper_r6_cmp_d_ ## op(CPUMIPSState *env, uint64_t fdt0, \
1973 uint64_t fdt1) \
1974 { \
1975 uint64_t c; \
1976 c = cond; \
1977 update_fcr31(env, GETPC()); \
1978 if (c) { \
1979 return -1; \
1980 } else { \
1981 return 0; \
1982 } \
1983 }
1984
1985 /*
1986 * NOTE: the comma operator will make "cond" to eval to false,
1987 * but float64_unordered_quiet() is still called.
1988 */
1989 FOP_CONDN_D(af, (float64_unordered_quiet(fdt1, fdt0,
1990 &env->active_fpu.fp_status), 0))
1991 FOP_CONDN_D(un, (float64_unordered_quiet(fdt1, fdt0,
1992 &env->active_fpu.fp_status)))
1993 FOP_CONDN_D(eq, (float64_eq_quiet(fdt0, fdt1,
1994 &env->active_fpu.fp_status)))
1995 FOP_CONDN_D(ueq, (float64_unordered_quiet(fdt1, fdt0,
1996 &env->active_fpu.fp_status)
1997 || float64_eq_quiet(fdt0, fdt1,
1998 &env->active_fpu.fp_status)))
1999 FOP_CONDN_D(lt, (float64_lt_quiet(fdt0, fdt1,
2000 &env->active_fpu.fp_status)))
2001 FOP_CONDN_D(ult, (float64_unordered_quiet(fdt1, fdt0,
2002 &env->active_fpu.fp_status)
2003 || float64_lt_quiet(fdt0, fdt1,
2004 &env->active_fpu.fp_status)))
2005 FOP_CONDN_D(le, (float64_le_quiet(fdt0, fdt1,
2006 &env->active_fpu.fp_status)))
2007 FOP_CONDN_D(ule, (float64_unordered_quiet(fdt1, fdt0,
2008 &env->active_fpu.fp_status)
2009 || float64_le_quiet(fdt0, fdt1,
2010 &env->active_fpu.fp_status)))
2011 /*
2012 * NOTE: the comma operator will make "cond" to eval to false,
2013 * but float64_unordered() is still called.\
2014 */
2015 FOP_CONDN_D(saf, (float64_unordered(fdt1, fdt0,
2016 &env->active_fpu.fp_status), 0))
2017 FOP_CONDN_D(sun, (float64_unordered(fdt1, fdt0,
2018 &env->active_fpu.fp_status)))
2019 FOP_CONDN_D(seq, (float64_eq(fdt0, fdt1,
2020 &env->active_fpu.fp_status)))
2021 FOP_CONDN_D(sueq, (float64_unordered(fdt1, fdt0,
2022 &env->active_fpu.fp_status)
2023 || float64_eq(fdt0, fdt1,
2024 &env->active_fpu.fp_status)))
2025 FOP_CONDN_D(slt, (float64_lt(fdt0, fdt1,
2026 &env->active_fpu.fp_status)))
2027 FOP_CONDN_D(sult, (float64_unordered(fdt1, fdt0,
2028 &env->active_fpu.fp_status)
2029 || float64_lt(fdt0, fdt1,
2030 &env->active_fpu.fp_status)))
2031 FOP_CONDN_D(sle, (float64_le(fdt0, fdt1,
2032 &env->active_fpu.fp_status)))
2033 FOP_CONDN_D(sule, (float64_unordered(fdt1, fdt0,
2034 &env->active_fpu.fp_status)
2035 || float64_le(fdt0, fdt1,
2036 &env->active_fpu.fp_status)))
2037 FOP_CONDN_D(or, (float64_le_quiet(fdt1, fdt0,
2038 &env->active_fpu.fp_status)
2039 || float64_le_quiet(fdt0, fdt1,
2040 &env->active_fpu.fp_status)))
2041 FOP_CONDN_D(une, (float64_unordered_quiet(fdt1, fdt0,
2042 &env->active_fpu.fp_status)
2043 || float64_lt_quiet(fdt1, fdt0,
2044 &env->active_fpu.fp_status)
2045 || float64_lt_quiet(fdt0, fdt1,
2046 &env->active_fpu.fp_status)))
2047 FOP_CONDN_D(ne, (float64_lt_quiet(fdt1, fdt0,
2048 &env->active_fpu.fp_status)
2049 || float64_lt_quiet(fdt0, fdt1,
2050 &env->active_fpu.fp_status)))
2051 FOP_CONDN_D(sor, (float64_le(fdt1, fdt0,
2052 &env->active_fpu.fp_status)
2053 || float64_le(fdt0, fdt1,
2054 &env->active_fpu.fp_status)))
2055 FOP_CONDN_D(sune, (float64_unordered(fdt1, fdt0,
2056 &env->active_fpu.fp_status)
2057 || float64_lt(fdt1, fdt0,
2058 &env->active_fpu.fp_status)
2059 || float64_lt(fdt0, fdt1,
2060 &env->active_fpu.fp_status)))
2061 FOP_CONDN_D(sne, (float64_lt(fdt1, fdt0,
2062 &env->active_fpu.fp_status)
2063 || float64_lt(fdt0, fdt1,
2064 &env->active_fpu.fp_status)))
2065
2066 #define FOP_CONDN_S(op, cond) \
2067 uint32_t helper_r6_cmp_s_ ## op(CPUMIPSState *env, uint32_t fst0, \
2068 uint32_t fst1) \
2069 { \
2070 uint64_t c; \
2071 c = cond; \
2072 update_fcr31(env, GETPC()); \
2073 if (c) { \
2074 return -1; \
2075 } else { \
2076 return 0; \
2077 } \
2078 }
2079
2080 /*
2081 * NOTE: the comma operator will make "cond" to eval to false,
2082 * but float32_unordered_quiet() is still called.
2083 */
2084 FOP_CONDN_S(af, (float32_unordered_quiet(fst1, fst0,
2085 &env->active_fpu.fp_status), 0))
2086 FOP_CONDN_S(un, (float32_unordered_quiet(fst1, fst0,
2087 &env->active_fpu.fp_status)))
2088 FOP_CONDN_S(eq, (float32_eq_quiet(fst0, fst1,
2089 &env->active_fpu.fp_status)))
2090 FOP_CONDN_S(ueq, (float32_unordered_quiet(fst1, fst0,
2091 &env->active_fpu.fp_status)
2092 || float32_eq_quiet(fst0, fst1,
2093 &env->active_fpu.fp_status)))
2094 FOP_CONDN_S(lt, (float32_lt_quiet(fst0, fst1,
2095 &env->active_fpu.fp_status)))
2096 FOP_CONDN_S(ult, (float32_unordered_quiet(fst1, fst0,
2097 &env->active_fpu.fp_status)
2098 || float32_lt_quiet(fst0, fst1,
2099 &env->active_fpu.fp_status)))
2100 FOP_CONDN_S(le, (float32_le_quiet(fst0, fst1,
2101 &env->active_fpu.fp_status)))
2102 FOP_CONDN_S(ule, (float32_unordered_quiet(fst1, fst0,
2103 &env->active_fpu.fp_status)
2104 || float32_le_quiet(fst0, fst1,
2105 &env->active_fpu.fp_status)))
2106 /*
2107 * NOTE: the comma operator will make "cond" to eval to false,
2108 * but float32_unordered() is still called.
2109 */
2110 FOP_CONDN_S(saf, (float32_unordered(fst1, fst0,
2111 &env->active_fpu.fp_status), 0))
2112 FOP_CONDN_S(sun, (float32_unordered(fst1, fst0,
2113 &env->active_fpu.fp_status)))
2114 FOP_CONDN_S(seq, (float32_eq(fst0, fst1,
2115 &env->active_fpu.fp_status)))
2116 FOP_CONDN_S(sueq, (float32_unordered(fst1, fst0,
2117 &env->active_fpu.fp_status)
2118 || float32_eq(fst0, fst1,
2119 &env->active_fpu.fp_status)))
2120 FOP_CONDN_S(slt, (float32_lt(fst0, fst1,
2121 &env->active_fpu.fp_status)))
2122 FOP_CONDN_S(sult, (float32_unordered(fst1, fst0,
2123 &env->active_fpu.fp_status)
2124 || float32_lt(fst0, fst1,
2125 &env->active_fpu.fp_status)))
2126 FOP_CONDN_S(sle, (float32_le(fst0, fst1,
2127 &env->active_fpu.fp_status)))
2128 FOP_CONDN_S(sule, (float32_unordered(fst1, fst0,
2129 &env->active_fpu.fp_status)
2130 || float32_le(fst0, fst1,
2131 &env->active_fpu.fp_status)))
2132 FOP_CONDN_S(or, (float32_le_quiet(fst1, fst0,
2133 &env->active_fpu.fp_status)
2134 || float32_le_quiet(fst0, fst1,
2135 &env->active_fpu.fp_status)))
2136 FOP_CONDN_S(une, (float32_unordered_quiet(fst1, fst0,
2137 &env->active_fpu.fp_status)
2138 || float32_lt_quiet(fst1, fst0,
2139 &env->active_fpu.fp_status)
2140 || float32_lt_quiet(fst0, fst1,
2141 &env->active_fpu.fp_status)))
2142 FOP_CONDN_S(ne, (float32_lt_quiet(fst1, fst0,
2143 &env->active_fpu.fp_status)
2144 || float32_lt_quiet(fst0, fst1,
2145 &env->active_fpu.fp_status)))
2146 FOP_CONDN_S(sor, (float32_le(fst1, fst0,
2147 &env->active_fpu.fp_status)
2148 || float32_le(fst0, fst1,
2149 &env->active_fpu.fp_status)))
2150 FOP_CONDN_S(sune, (float32_unordered(fst1, fst0,
2151 &env->active_fpu.fp_status)
2152 || float32_lt(fst1, fst0,
2153 &env->active_fpu.fp_status)
2154 || float32_lt(fst0, fst1,
2155 &env->active_fpu.fp_status)))
2156 FOP_CONDN_S(sne, (float32_lt(fst1, fst0,
2157 &env->active_fpu.fp_status)
2158 || float32_lt(fst0, fst1,
2159 &env->active_fpu.fp_status)))