xref: /qemu/target/mips/tcg/op_helper.c (revision 256eb7ee587ce4b0ae8d5b9ce76b746a29897e30)
1 /*
2  *  MIPS emulation helpers for qemu.
3  *
4  *  Copyright (c) 2004-2005 Jocelyn Mayer
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 #include "qemu/osdep.h"
22 #include "qemu/main-loop.h"
23 #include "cpu.h"
24 #include "internal.h"
25 #include "qemu/host-utils.h"
26 #include "exec/helper-proto.h"
27 #include "exec/exec-all.h"
28 #include "exec/cpu_ldst.h"
29 #include "exec/memop.h"
30 #include "sysemu/kvm.h"
31 #include "fpu/softfloat.h"
32 
33 
34 /*****************************************************************************/
35 /* Exceptions processing helpers */
36 
37 void helper_raise_exception_err(CPUMIPSState *env, uint32_t exception,
38                                 int error_code)
39 {
40     do_raise_exception_err(env, exception, error_code, 0);
41 }
42 
43 void helper_raise_exception(CPUMIPSState *env, uint32_t exception)
44 {
45     do_raise_exception(env, exception, GETPC());
46 }
47 
48 void helper_raise_exception_debug(CPUMIPSState *env)
49 {
50     do_raise_exception(env, EXCP_DEBUG, 0);
51 }
52 
53 static void raise_exception(CPUMIPSState *env, uint32_t exception)
54 {
55     do_raise_exception(env, exception, 0);
56 }
57 
58 /* 64 bits arithmetic for 32 bits hosts */
59 static inline uint64_t get_HILO(CPUMIPSState *env)
60 {
61     return ((uint64_t)(env->active_tc.HI[0]) << 32) |
62            (uint32_t)env->active_tc.LO[0];
63 }
64 
65 static inline target_ulong set_HIT0_LO(CPUMIPSState *env, uint64_t HILO)
66 {
67     env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF);
68     return env->active_tc.HI[0] = (int32_t)(HILO >> 32);
69 }
70 
71 static inline target_ulong set_HI_LOT0(CPUMIPSState *env, uint64_t HILO)
72 {
73     target_ulong tmp = env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF);
74     env->active_tc.HI[0] = (int32_t)(HILO >> 32);
75     return tmp;
76 }
77 
78 /* Multiplication variants of the vr54xx. */
79 target_ulong helper_muls(CPUMIPSState *env, target_ulong arg1,
80                          target_ulong arg2)
81 {
82     return set_HI_LOT0(env, 0 - ((int64_t)(int32_t)arg1 *
83                                  (int64_t)(int32_t)arg2));
84 }
85 
86 target_ulong helper_mulsu(CPUMIPSState *env, target_ulong arg1,
87                           target_ulong arg2)
88 {
89     return set_HI_LOT0(env, 0 - (uint64_t)(uint32_t)arg1 *
90                        (uint64_t)(uint32_t)arg2);
91 }
92 
93 target_ulong helper_macc(CPUMIPSState *env, target_ulong arg1,
94                          target_ulong arg2)
95 {
96     return set_HI_LOT0(env, (int64_t)get_HILO(env) + (int64_t)(int32_t)arg1 *
97                        (int64_t)(int32_t)arg2);
98 }
99 
100 target_ulong helper_macchi(CPUMIPSState *env, target_ulong arg1,
101                            target_ulong arg2)
102 {
103     return set_HIT0_LO(env, (int64_t)get_HILO(env) + (int64_t)(int32_t)arg1 *
104                        (int64_t)(int32_t)arg2);
105 }
106 
107 target_ulong helper_maccu(CPUMIPSState *env, target_ulong arg1,
108                           target_ulong arg2)
109 {
110     return set_HI_LOT0(env, (uint64_t)get_HILO(env) +
111                        (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2);
112 }
113 
114 target_ulong helper_macchiu(CPUMIPSState *env, target_ulong arg1,
115                             target_ulong arg2)
116 {
117     return set_HIT0_LO(env, (uint64_t)get_HILO(env) +
118                        (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2);
119 }
120 
121 target_ulong helper_msac(CPUMIPSState *env, target_ulong arg1,
122                          target_ulong arg2)
123 {
124     return set_HI_LOT0(env, (int64_t)get_HILO(env) - (int64_t)(int32_t)arg1 *
125                        (int64_t)(int32_t)arg2);
126 }
127 
128 target_ulong helper_msachi(CPUMIPSState *env, target_ulong arg1,
129                            target_ulong arg2)
130 {
131     return set_HIT0_LO(env, (int64_t)get_HILO(env) - (int64_t)(int32_t)arg1 *
132                        (int64_t)(int32_t)arg2);
133 }
134 
135 target_ulong helper_msacu(CPUMIPSState *env, target_ulong arg1,
136                           target_ulong arg2)
137 {
138     return set_HI_LOT0(env, (uint64_t)get_HILO(env) -
139                        (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2);
140 }
141 
142 target_ulong helper_msachiu(CPUMIPSState *env, target_ulong arg1,
143                             target_ulong arg2)
144 {
145     return set_HIT0_LO(env, (uint64_t)get_HILO(env) -
146                        (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2);
147 }
148 
149 target_ulong helper_mulhi(CPUMIPSState *env, target_ulong arg1,
150                           target_ulong arg2)
151 {
152     return set_HIT0_LO(env, (int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2);
153 }
154 
155 target_ulong helper_mulhiu(CPUMIPSState *env, target_ulong arg1,
156                            target_ulong arg2)
157 {
158     return set_HIT0_LO(env, (uint64_t)(uint32_t)arg1 *
159                        (uint64_t)(uint32_t)arg2);
160 }
161 
162 target_ulong helper_mulshi(CPUMIPSState *env, target_ulong arg1,
163                            target_ulong arg2)
164 {
165     return set_HIT0_LO(env, 0 - (int64_t)(int32_t)arg1 *
166                        (int64_t)(int32_t)arg2);
167 }
168 
169 target_ulong helper_mulshiu(CPUMIPSState *env, target_ulong arg1,
170                             target_ulong arg2)
171 {
172     return set_HIT0_LO(env, 0 - (uint64_t)(uint32_t)arg1 *
173                        (uint64_t)(uint32_t)arg2);
174 }
175 
176 static inline target_ulong bitswap(target_ulong v)
177 {
178     v = ((v >> 1) & (target_ulong)0x5555555555555555ULL) |
179               ((v & (target_ulong)0x5555555555555555ULL) << 1);
180     v = ((v >> 2) & (target_ulong)0x3333333333333333ULL) |
181               ((v & (target_ulong)0x3333333333333333ULL) << 2);
182     v = ((v >> 4) & (target_ulong)0x0F0F0F0F0F0F0F0FULL) |
183               ((v & (target_ulong)0x0F0F0F0F0F0F0F0FULL) << 4);
184     return v;
185 }
186 
187 #ifdef TARGET_MIPS64
188 target_ulong helper_dbitswap(target_ulong rt)
189 {
190     return bitswap(rt);
191 }
192 #endif
193 
194 target_ulong helper_bitswap(target_ulong rt)
195 {
196     return (int32_t)bitswap(rt);
197 }
198 
199 target_ulong helper_rotx(target_ulong rs, uint32_t shift, uint32_t shiftx,
200                         uint32_t stripe)
201 {
202     int i;
203     uint64_t tmp0 = ((uint64_t)rs) << 32 | ((uint64_t)rs & 0xffffffff);
204     uint64_t tmp1 = tmp0;
205     for (i = 0; i <= 46; i++) {
206         int s;
207         if (i & 0x8) {
208             s = shift;
209         } else {
210             s = shiftx;
211         }
212 
213         if (stripe != 0 && !(i & 0x4)) {
214             s = ~s;
215         }
216         if (s & 0x10) {
217             if (tmp0 & (1LL << (i + 16))) {
218                 tmp1 |= 1LL << i;
219             } else {
220                 tmp1 &= ~(1LL << i);
221             }
222         }
223     }
224 
225     uint64_t tmp2 = tmp1;
226     for (i = 0; i <= 38; i++) {
227         int s;
228         if (i & 0x4) {
229             s = shift;
230         } else {
231             s = shiftx;
232         }
233 
234         if (s & 0x8) {
235             if (tmp1 & (1LL << (i + 8))) {
236                 tmp2 |= 1LL << i;
237             } else {
238                 tmp2 &= ~(1LL << i);
239             }
240         }
241     }
242 
243     uint64_t tmp3 = tmp2;
244     for (i = 0; i <= 34; i++) {
245         int s;
246         if (i & 0x2) {
247             s = shift;
248         } else {
249             s = shiftx;
250         }
251         if (s & 0x4) {
252             if (tmp2 & (1LL << (i + 4))) {
253                 tmp3 |= 1LL << i;
254             } else {
255                 tmp3 &= ~(1LL << i);
256             }
257         }
258     }
259 
260     uint64_t tmp4 = tmp3;
261     for (i = 0; i <= 32; i++) {
262         int s;
263         if (i & 0x1) {
264             s = shift;
265         } else {
266             s = shiftx;
267         }
268         if (s & 0x2) {
269             if (tmp3 & (1LL << (i + 2))) {
270                 tmp4 |= 1LL << i;
271             } else {
272                 tmp4 &= ~(1LL << i);
273             }
274         }
275     }
276 
277     uint64_t tmp5 = tmp4;
278     for (i = 0; i <= 31; i++) {
279         int s;
280         s = shift;
281         if (s & 0x1) {
282             if (tmp4 & (1LL << (i + 1))) {
283                 tmp5 |= 1LL << i;
284             } else {
285                 tmp5 &= ~(1LL << i);
286             }
287         }
288     }
289 
290     return (int64_t)(int32_t)(uint32_t)tmp5;
291 }
292 
293 #ifndef CONFIG_USER_ONLY
294 
295 static inline hwaddr do_translate_address(CPUMIPSState *env,
296                                                       target_ulong address,
297                                                       int rw, uintptr_t retaddr)
298 {
299     hwaddr paddr;
300     CPUState *cs = env_cpu(env);
301 
302     paddr = cpu_mips_translate_address(env, address, rw);
303 
304     if (paddr == -1LL) {
305         cpu_loop_exit_restore(cs, retaddr);
306     } else {
307         return paddr;
308     }
309 }
310 
311 #define HELPER_LD_ATOMIC(name, insn, almask, do_cast)                         \
312 target_ulong helper_##name(CPUMIPSState *env, target_ulong arg, int mem_idx)  \
313 {                                                                             \
314     if (arg & almask) {                                                       \
315         if (!(env->hflags & MIPS_HFLAG_DM)) {                                 \
316             env->CP0_BadVAddr = arg;                                          \
317         }                                                                     \
318         do_raise_exception(env, EXCP_AdEL, GETPC());                          \
319     }                                                                         \
320     env->CP0_LLAddr = do_translate_address(env, arg, 0, GETPC());             \
321     env->lladdr = arg;                                                        \
322     env->llval = do_cast cpu_##insn##_mmuidx_ra(env, arg, mem_idx, GETPC());  \
323     return env->llval;                                                        \
324 }
325 HELPER_LD_ATOMIC(ll, ldl, 0x3, (target_long)(int32_t))
326 #ifdef TARGET_MIPS64
327 HELPER_LD_ATOMIC(lld, ldq, 0x7, (target_ulong))
328 #endif
329 #undef HELPER_LD_ATOMIC
330 #endif
331 
332 #ifdef TARGET_WORDS_BIGENDIAN
333 #define GET_LMASK(v) ((v) & 3)
334 #define GET_OFFSET(addr, offset) (addr + (offset))
335 #else
336 #define GET_LMASK(v) (((v) & 3) ^ 3)
337 #define GET_OFFSET(addr, offset) (addr - (offset))
338 #endif
339 
340 void helper_swl(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
341                 int mem_idx)
342 {
343     cpu_stb_mmuidx_ra(env, arg2, (uint8_t)(arg1 >> 24), mem_idx, GETPC());
344 
345     if (GET_LMASK(arg2) <= 2) {
346         cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, 1), (uint8_t)(arg1 >> 16),
347                           mem_idx, GETPC());
348     }
349 
350     if (GET_LMASK(arg2) <= 1) {
351         cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, 2), (uint8_t)(arg1 >> 8),
352                           mem_idx, GETPC());
353     }
354 
355     if (GET_LMASK(arg2) == 0) {
356         cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, 3), (uint8_t)arg1,
357                           mem_idx, GETPC());
358     }
359 }
360 
361 void helper_swr(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
362                 int mem_idx)
363 {
364     cpu_stb_mmuidx_ra(env, arg2, (uint8_t)arg1, mem_idx, GETPC());
365 
366     if (GET_LMASK(arg2) >= 1) {
367         cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, -1), (uint8_t)(arg1 >> 8),
368                           mem_idx, GETPC());
369     }
370 
371     if (GET_LMASK(arg2) >= 2) {
372         cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, -2), (uint8_t)(arg1 >> 16),
373                           mem_idx, GETPC());
374     }
375 
376     if (GET_LMASK(arg2) == 3) {
377         cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, -3), (uint8_t)(arg1 >> 24),
378                           mem_idx, GETPC());
379     }
380 }
381 
382 #if defined(TARGET_MIPS64)
383 /*
384  * "half" load and stores.  We must do the memory access inline,
385  * or fault handling won't work.
386  */
387 #ifdef TARGET_WORDS_BIGENDIAN
388 #define GET_LMASK64(v) ((v) & 7)
389 #else
390 #define GET_LMASK64(v) (((v) & 7) ^ 7)
391 #endif
392 
393 void helper_sdl(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
394                 int mem_idx)
395 {
396     cpu_stb_mmuidx_ra(env, arg2, (uint8_t)(arg1 >> 56), mem_idx, GETPC());
397 
398     if (GET_LMASK64(arg2) <= 6) {
399         cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, 1), (uint8_t)(arg1 >> 48),
400                           mem_idx, GETPC());
401     }
402 
403     if (GET_LMASK64(arg2) <= 5) {
404         cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, 2), (uint8_t)(arg1 >> 40),
405                           mem_idx, GETPC());
406     }
407 
408     if (GET_LMASK64(arg2) <= 4) {
409         cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, 3), (uint8_t)(arg1 >> 32),
410                           mem_idx, GETPC());
411     }
412 
413     if (GET_LMASK64(arg2) <= 3) {
414         cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, 4), (uint8_t)(arg1 >> 24),
415                           mem_idx, GETPC());
416     }
417 
418     if (GET_LMASK64(arg2) <= 2) {
419         cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, 5), (uint8_t)(arg1 >> 16),
420                           mem_idx, GETPC());
421     }
422 
423     if (GET_LMASK64(arg2) <= 1) {
424         cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, 6), (uint8_t)(arg1 >> 8),
425                           mem_idx, GETPC());
426     }
427 
428     if (GET_LMASK64(arg2) <= 0) {
429         cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, 7), (uint8_t)arg1,
430                           mem_idx, GETPC());
431     }
432 }
433 
434 void helper_sdr(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
435                 int mem_idx)
436 {
437     cpu_stb_mmuidx_ra(env, arg2, (uint8_t)arg1, mem_idx, GETPC());
438 
439     if (GET_LMASK64(arg2) >= 1) {
440         cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, -1), (uint8_t)(arg1 >> 8),
441                           mem_idx, GETPC());
442     }
443 
444     if (GET_LMASK64(arg2) >= 2) {
445         cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, -2), (uint8_t)(arg1 >> 16),
446                           mem_idx, GETPC());
447     }
448 
449     if (GET_LMASK64(arg2) >= 3) {
450         cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, -3), (uint8_t)(arg1 >> 24),
451                           mem_idx, GETPC());
452     }
453 
454     if (GET_LMASK64(arg2) >= 4) {
455         cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, -4), (uint8_t)(arg1 >> 32),
456                           mem_idx, GETPC());
457     }
458 
459     if (GET_LMASK64(arg2) >= 5) {
460         cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, -5), (uint8_t)(arg1 >> 40),
461                           mem_idx, GETPC());
462     }
463 
464     if (GET_LMASK64(arg2) >= 6) {
465         cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, -6), (uint8_t)(arg1 >> 48),
466                           mem_idx, GETPC());
467     }
468 
469     if (GET_LMASK64(arg2) == 7) {
470         cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, -7), (uint8_t)(arg1 >> 56),
471                           mem_idx, GETPC());
472     }
473 }
474 #endif /* TARGET_MIPS64 */
475 
476 static const int multiple_regs[] = { 16, 17, 18, 19, 20, 21, 22, 23, 30 };
477 
478 void helper_lwm(CPUMIPSState *env, target_ulong addr, target_ulong reglist,
479                 uint32_t mem_idx)
480 {
481     target_ulong base_reglist = reglist & 0xf;
482     target_ulong do_r31 = reglist & 0x10;
483 
484     if (base_reglist > 0 && base_reglist <= ARRAY_SIZE(multiple_regs)) {
485         target_ulong i;
486 
487         for (i = 0; i < base_reglist; i++) {
488             env->active_tc.gpr[multiple_regs[i]] =
489                 (target_long)cpu_ldl_mmuidx_ra(env, addr, mem_idx, GETPC());
490             addr += 4;
491         }
492     }
493 
494     if (do_r31) {
495         env->active_tc.gpr[31] =
496             (target_long)cpu_ldl_mmuidx_ra(env, addr, mem_idx, GETPC());
497     }
498 }
499 
500 void helper_swm(CPUMIPSState *env, target_ulong addr, target_ulong reglist,
501                 uint32_t mem_idx)
502 {
503     target_ulong base_reglist = reglist & 0xf;
504     target_ulong do_r31 = reglist & 0x10;
505 
506     if (base_reglist > 0 && base_reglist <= ARRAY_SIZE(multiple_regs)) {
507         target_ulong i;
508 
509         for (i = 0; i < base_reglist; i++) {
510             cpu_stw_mmuidx_ra(env, addr, env->active_tc.gpr[multiple_regs[i]],
511                               mem_idx, GETPC());
512             addr += 4;
513         }
514     }
515 
516     if (do_r31) {
517         cpu_stw_mmuidx_ra(env, addr, env->active_tc.gpr[31], mem_idx, GETPC());
518     }
519 }
520 
521 #if defined(TARGET_MIPS64)
522 void helper_ldm(CPUMIPSState *env, target_ulong addr, target_ulong reglist,
523                 uint32_t mem_idx)
524 {
525     target_ulong base_reglist = reglist & 0xf;
526     target_ulong do_r31 = reglist & 0x10;
527 
528     if (base_reglist > 0 && base_reglist <= ARRAY_SIZE(multiple_regs)) {
529         target_ulong i;
530 
531         for (i = 0; i < base_reglist; i++) {
532             env->active_tc.gpr[multiple_regs[i]] =
533                 cpu_ldq_mmuidx_ra(env, addr, mem_idx, GETPC());
534             addr += 8;
535         }
536     }
537 
538     if (do_r31) {
539         env->active_tc.gpr[31] =
540             cpu_ldq_mmuidx_ra(env, addr, mem_idx, GETPC());
541     }
542 }
543 
544 void helper_sdm(CPUMIPSState *env, target_ulong addr, target_ulong reglist,
545                 uint32_t mem_idx)
546 {
547     target_ulong base_reglist = reglist & 0xf;
548     target_ulong do_r31 = reglist & 0x10;
549 
550     if (base_reglist > 0 && base_reglist <= ARRAY_SIZE(multiple_regs)) {
551         target_ulong i;
552 
553         for (i = 0; i < base_reglist; i++) {
554             cpu_stq_mmuidx_ra(env, addr, env->active_tc.gpr[multiple_regs[i]],
555                               mem_idx, GETPC());
556             addr += 8;
557         }
558     }
559 
560     if (do_r31) {
561         cpu_stq_mmuidx_ra(env, addr, env->active_tc.gpr[31], mem_idx, GETPC());
562     }
563 }
564 #endif
565 
566 
567 void helper_fork(target_ulong arg1, target_ulong arg2)
568 {
569     /*
570      * arg1 = rt, arg2 = rs
571      * TODO: store to TC register
572      */
573 }
574 
575 target_ulong helper_yield(CPUMIPSState *env, target_ulong arg)
576 {
577     target_long arg1 = arg;
578 
579     if (arg1 < 0) {
580         /* No scheduling policy implemented. */
581         if (arg1 != -2) {
582             if (env->CP0_VPEControl & (1 << CP0VPECo_YSI) &&
583                 env->active_tc.CP0_TCStatus & (1 << CP0TCSt_DT)) {
584                 env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
585                 env->CP0_VPEControl |= 4 << CP0VPECo_EXCPT;
586                 do_raise_exception(env, EXCP_THREAD, GETPC());
587             }
588         }
589     } else if (arg1 == 0) {
590         if (0) {
591             /* TODO: TC underflow */
592             env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
593             do_raise_exception(env, EXCP_THREAD, GETPC());
594         } else {
595             /* TODO: Deallocate TC */
596         }
597     } else if (arg1 > 0) {
598         /* Yield qualifier inputs not implemented. */
599         env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
600         env->CP0_VPEControl |= 2 << CP0VPECo_EXCPT;
601         do_raise_exception(env, EXCP_THREAD, GETPC());
602     }
603     return env->CP0_YQMask;
604 }
605 
606 #ifndef CONFIG_USER_ONLY
607 /* TLB management */
608 static void r4k_mips_tlb_flush_extra(CPUMIPSState *env, int first)
609 {
610     /* Discard entries from env->tlb[first] onwards.  */
611     while (env->tlb->tlb_in_use > first) {
612         r4k_invalidate_tlb(env, --env->tlb->tlb_in_use, 0);
613     }
614 }
615 
616 static inline uint64_t get_tlb_pfn_from_entrylo(uint64_t entrylo)
617 {
618 #if defined(TARGET_MIPS64)
619     return extract64(entrylo, 6, 54);
620 #else
621     return extract64(entrylo, 6, 24) | /* PFN */
622            (extract64(entrylo, 32, 32) << 24); /* PFNX */
623 #endif
624 }
625 
626 static void r4k_fill_tlb(CPUMIPSState *env, int idx)
627 {
628     r4k_tlb_t *tlb;
629     uint64_t mask = env->CP0_PageMask >> (TARGET_PAGE_BITS + 1);
630 
631     /* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */
632     tlb = &env->tlb->mmu.r4k.tlb[idx];
633     if (env->CP0_EntryHi & (1 << CP0EnHi_EHINV)) {
634         tlb->EHINV = 1;
635         return;
636     }
637     tlb->EHINV = 0;
638     tlb->VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1);
639 #if defined(TARGET_MIPS64)
640     tlb->VPN &= env->SEGMask;
641 #endif
642     tlb->ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
643     tlb->MMID = env->CP0_MemoryMapID;
644     tlb->PageMask = env->CP0_PageMask;
645     tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
646     tlb->V0 = (env->CP0_EntryLo0 & 2) != 0;
647     tlb->D0 = (env->CP0_EntryLo0 & 4) != 0;
648     tlb->C0 = (env->CP0_EntryLo0 >> 3) & 0x7;
649     tlb->XI0 = (env->CP0_EntryLo0 >> CP0EnLo_XI) & 1;
650     tlb->RI0 = (env->CP0_EntryLo0 >> CP0EnLo_RI) & 1;
651     tlb->PFN[0] = (get_tlb_pfn_from_entrylo(env->CP0_EntryLo0) & ~mask) << 12;
652     tlb->V1 = (env->CP0_EntryLo1 & 2) != 0;
653     tlb->D1 = (env->CP0_EntryLo1 & 4) != 0;
654     tlb->C1 = (env->CP0_EntryLo1 >> 3) & 0x7;
655     tlb->XI1 = (env->CP0_EntryLo1 >> CP0EnLo_XI) & 1;
656     tlb->RI1 = (env->CP0_EntryLo1 >> CP0EnLo_RI) & 1;
657     tlb->PFN[1] = (get_tlb_pfn_from_entrylo(env->CP0_EntryLo1) & ~mask) << 12;
658 }
659 
660 void r4k_helper_tlbinv(CPUMIPSState *env)
661 {
662     bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1);
663     uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
664     uint32_t MMID = env->CP0_MemoryMapID;
665     uint32_t tlb_mmid;
666     r4k_tlb_t *tlb;
667     int idx;
668 
669     MMID = mi ? MMID : (uint32_t) ASID;
670     for (idx = 0; idx < env->tlb->nb_tlb; idx++) {
671         tlb = &env->tlb->mmu.r4k.tlb[idx];
672         tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID;
673         if (!tlb->G && tlb_mmid == MMID) {
674             tlb->EHINV = 1;
675         }
676     }
677     cpu_mips_tlb_flush(env);
678 }
679 
680 void r4k_helper_tlbinvf(CPUMIPSState *env)
681 {
682     int idx;
683 
684     for (idx = 0; idx < env->tlb->nb_tlb; idx++) {
685         env->tlb->mmu.r4k.tlb[idx].EHINV = 1;
686     }
687     cpu_mips_tlb_flush(env);
688 }
689 
690 void r4k_helper_tlbwi(CPUMIPSState *env)
691 {
692     bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1);
693     target_ulong VPN;
694     uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
695     uint32_t MMID = env->CP0_MemoryMapID;
696     uint32_t tlb_mmid;
697     bool EHINV, G, V0, D0, V1, D1, XI0, XI1, RI0, RI1;
698     r4k_tlb_t *tlb;
699     int idx;
700 
701     MMID = mi ? MMID : (uint32_t) ASID;
702 
703     idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb;
704     tlb = &env->tlb->mmu.r4k.tlb[idx];
705     VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1);
706 #if defined(TARGET_MIPS64)
707     VPN &= env->SEGMask;
708 #endif
709     EHINV = (env->CP0_EntryHi & (1 << CP0EnHi_EHINV)) != 0;
710     G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
711     V0 = (env->CP0_EntryLo0 & 2) != 0;
712     D0 = (env->CP0_EntryLo0 & 4) != 0;
713     XI0 = (env->CP0_EntryLo0 >> CP0EnLo_XI) &1;
714     RI0 = (env->CP0_EntryLo0 >> CP0EnLo_RI) &1;
715     V1 = (env->CP0_EntryLo1 & 2) != 0;
716     D1 = (env->CP0_EntryLo1 & 4) != 0;
717     XI1 = (env->CP0_EntryLo1 >> CP0EnLo_XI) &1;
718     RI1 = (env->CP0_EntryLo1 >> CP0EnLo_RI) &1;
719 
720     tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID;
721     /*
722      * Discard cached TLB entries, unless tlbwi is just upgrading access
723      * permissions on the current entry.
724      */
725     if (tlb->VPN != VPN || tlb_mmid != MMID || tlb->G != G ||
726         (!tlb->EHINV && EHINV) ||
727         (tlb->V0 && !V0) || (tlb->D0 && !D0) ||
728         (!tlb->XI0 && XI0) || (!tlb->RI0 && RI0) ||
729         (tlb->V1 && !V1) || (tlb->D1 && !D1) ||
730         (!tlb->XI1 && XI1) || (!tlb->RI1 && RI1)) {
731         r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb);
732     }
733 
734     r4k_invalidate_tlb(env, idx, 0);
735     r4k_fill_tlb(env, idx);
736 }
737 
738 void r4k_helper_tlbwr(CPUMIPSState *env)
739 {
740     int r = cpu_mips_get_random(env);
741 
742     r4k_invalidate_tlb(env, r, 1);
743     r4k_fill_tlb(env, r);
744 }
745 
746 void r4k_helper_tlbp(CPUMIPSState *env)
747 {
748     bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1);
749     r4k_tlb_t *tlb;
750     target_ulong mask;
751     target_ulong tag;
752     target_ulong VPN;
753     uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
754     uint32_t MMID = env->CP0_MemoryMapID;
755     uint32_t tlb_mmid;
756     int i;
757 
758     MMID = mi ? MMID : (uint32_t) ASID;
759     for (i = 0; i < env->tlb->nb_tlb; i++) {
760         tlb = &env->tlb->mmu.r4k.tlb[i];
761         /* 1k pages are not supported. */
762         mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
763         tag = env->CP0_EntryHi & ~mask;
764         VPN = tlb->VPN & ~mask;
765 #if defined(TARGET_MIPS64)
766         tag &= env->SEGMask;
767 #endif
768         tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID;
769         /* Check ASID/MMID, virtual page number & size */
770         if ((tlb->G == 1 || tlb_mmid == MMID) && VPN == tag && !tlb->EHINV) {
771             /* TLB match */
772             env->CP0_Index = i;
773             break;
774         }
775     }
776     if (i == env->tlb->nb_tlb) {
777         /* No match.  Discard any shadow entries, if any of them match.  */
778         for (i = env->tlb->nb_tlb; i < env->tlb->tlb_in_use; i++) {
779             tlb = &env->tlb->mmu.r4k.tlb[i];
780             /* 1k pages are not supported. */
781             mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
782             tag = env->CP0_EntryHi & ~mask;
783             VPN = tlb->VPN & ~mask;
784 #if defined(TARGET_MIPS64)
785             tag &= env->SEGMask;
786 #endif
787             tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID;
788             /* Check ASID/MMID, virtual page number & size */
789             if ((tlb->G == 1 || tlb_mmid == MMID) && VPN == tag) {
790                 r4k_mips_tlb_flush_extra(env, i);
791                 break;
792             }
793         }
794 
795         env->CP0_Index |= 0x80000000;
796     }
797 }
798 
799 static inline uint64_t get_entrylo_pfn_from_tlb(uint64_t tlb_pfn)
800 {
801 #if defined(TARGET_MIPS64)
802     return tlb_pfn << 6;
803 #else
804     return (extract64(tlb_pfn, 0, 24) << 6) | /* PFN */
805            (extract64(tlb_pfn, 24, 32) << 32); /* PFNX */
806 #endif
807 }
808 
809 void r4k_helper_tlbr(CPUMIPSState *env)
810 {
811     bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1);
812     uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
813     uint32_t MMID = env->CP0_MemoryMapID;
814     uint32_t tlb_mmid;
815     r4k_tlb_t *tlb;
816     int idx;
817 
818     MMID = mi ? MMID : (uint32_t) ASID;
819     idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb;
820     tlb = &env->tlb->mmu.r4k.tlb[idx];
821 
822     tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID;
823     /* If this will change the current ASID/MMID, flush qemu's TLB.  */
824     if (MMID != tlb_mmid) {
825         cpu_mips_tlb_flush(env);
826     }
827 
828     r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb);
829 
830     if (tlb->EHINV) {
831         env->CP0_EntryHi = 1 << CP0EnHi_EHINV;
832         env->CP0_PageMask = 0;
833         env->CP0_EntryLo0 = 0;
834         env->CP0_EntryLo1 = 0;
835     } else {
836         env->CP0_EntryHi = mi ? tlb->VPN : tlb->VPN | tlb->ASID;
837         env->CP0_MemoryMapID = tlb->MMID;
838         env->CP0_PageMask = tlb->PageMask;
839         env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) |
840                         ((uint64_t)tlb->RI0 << CP0EnLo_RI) |
841                         ((uint64_t)tlb->XI0 << CP0EnLo_XI) | (tlb->C0 << 3) |
842                         get_entrylo_pfn_from_tlb(tlb->PFN[0] >> 12);
843         env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) |
844                         ((uint64_t)tlb->RI1 << CP0EnLo_RI) |
845                         ((uint64_t)tlb->XI1 << CP0EnLo_XI) | (tlb->C1 << 3) |
846                         get_entrylo_pfn_from_tlb(tlb->PFN[1] >> 12);
847     }
848 }
849 
850 void helper_tlbwi(CPUMIPSState *env)
851 {
852     env->tlb->helper_tlbwi(env);
853 }
854 
855 void helper_tlbwr(CPUMIPSState *env)
856 {
857     env->tlb->helper_tlbwr(env);
858 }
859 
860 void helper_tlbp(CPUMIPSState *env)
861 {
862     env->tlb->helper_tlbp(env);
863 }
864 
865 void helper_tlbr(CPUMIPSState *env)
866 {
867     env->tlb->helper_tlbr(env);
868 }
869 
870 void helper_tlbinv(CPUMIPSState *env)
871 {
872     env->tlb->helper_tlbinv(env);
873 }
874 
875 void helper_tlbinvf(CPUMIPSState *env)
876 {
877     env->tlb->helper_tlbinvf(env);
878 }
879 
880 static void global_invalidate_tlb(CPUMIPSState *env,
881                            uint32_t invMsgVPN2,
882                            uint8_t invMsgR,
883                            uint32_t invMsgMMid,
884                            bool invAll,
885                            bool invVAMMid,
886                            bool invMMid,
887                            bool invVA)
888 {
889 
890     int idx;
891     r4k_tlb_t *tlb;
892     bool VAMatch;
893     bool MMidMatch;
894 
895     for (idx = 0; idx < env->tlb->nb_tlb; idx++) {
896         tlb = &env->tlb->mmu.r4k.tlb[idx];
897         VAMatch =
898             (((tlb->VPN & ~tlb->PageMask) == (invMsgVPN2 & ~tlb->PageMask))
899 #ifdef TARGET_MIPS64
900             &&
901             (extract64(env->CP0_EntryHi, 62, 2) == invMsgR)
902 #endif
903             );
904         MMidMatch = tlb->MMID == invMsgMMid;
905         if ((invAll && (idx > env->CP0_Wired)) ||
906             (VAMatch && invVAMMid && (tlb->G || MMidMatch)) ||
907             (VAMatch && invVA) ||
908             (MMidMatch && !(tlb->G) && invMMid)) {
909             tlb->EHINV = 1;
910         }
911     }
912     cpu_mips_tlb_flush(env);
913 }
914 
915 void helper_ginvt(CPUMIPSState *env, target_ulong arg, uint32_t type)
916 {
917     bool invAll = type == 0;
918     bool invVA = type == 1;
919     bool invMMid = type == 2;
920     bool invVAMMid = type == 3;
921     uint32_t invMsgVPN2 = arg & (TARGET_PAGE_MASK << 1);
922     uint8_t invMsgR = 0;
923     uint32_t invMsgMMid = env->CP0_MemoryMapID;
924     CPUState *other_cs = first_cpu;
925 
926 #ifdef TARGET_MIPS64
927     invMsgR = extract64(arg, 62, 2);
928 #endif
929 
930     CPU_FOREACH(other_cs) {
931         MIPSCPU *other_cpu = MIPS_CPU(other_cs);
932         global_invalidate_tlb(&other_cpu->env, invMsgVPN2, invMsgR, invMsgMMid,
933                               invAll, invVAMMid, invMMid, invVA);
934     }
935 }
936 
937 /* Specials */
938 target_ulong helper_di(CPUMIPSState *env)
939 {
940     target_ulong t0 = env->CP0_Status;
941 
942     env->CP0_Status = t0 & ~(1 << CP0St_IE);
943     return t0;
944 }
945 
946 target_ulong helper_ei(CPUMIPSState *env)
947 {
948     target_ulong t0 = env->CP0_Status;
949 
950     env->CP0_Status = t0 | (1 << CP0St_IE);
951     return t0;
952 }
953 
954 static void debug_pre_eret(CPUMIPSState *env)
955 {
956     if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
957         qemu_log("ERET: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
958                 env->active_tc.PC, env->CP0_EPC);
959         if (env->CP0_Status & (1 << CP0St_ERL)) {
960             qemu_log(" ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
961         }
962         if (env->hflags & MIPS_HFLAG_DM) {
963             qemu_log(" DEPC " TARGET_FMT_lx, env->CP0_DEPC);
964         }
965         qemu_log("\n");
966     }
967 }
968 
969 static void debug_post_eret(CPUMIPSState *env)
970 {
971     if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
972         qemu_log("  =>  PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
973                 env->active_tc.PC, env->CP0_EPC);
974         if (env->CP0_Status & (1 << CP0St_ERL)) {
975             qemu_log(" ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
976         }
977         if (env->hflags & MIPS_HFLAG_DM) {
978             qemu_log(" DEPC " TARGET_FMT_lx, env->CP0_DEPC);
979         }
980         switch (cpu_mmu_index(env, false)) {
981         case 3:
982             qemu_log(", ERL\n");
983             break;
984         case MIPS_HFLAG_UM:
985             qemu_log(", UM\n");
986             break;
987         case MIPS_HFLAG_SM:
988             qemu_log(", SM\n");
989             break;
990         case MIPS_HFLAG_KM:
991             qemu_log("\n");
992             break;
993         default:
994             cpu_abort(env_cpu(env), "Invalid MMU mode!\n");
995             break;
996         }
997     }
998 }
999 
1000 static void set_pc(CPUMIPSState *env, target_ulong error_pc)
1001 {
1002     env->active_tc.PC = error_pc & ~(target_ulong)1;
1003     if (error_pc & 1) {
1004         env->hflags |= MIPS_HFLAG_M16;
1005     } else {
1006         env->hflags &= ~(MIPS_HFLAG_M16);
1007     }
1008 }
1009 
1010 static inline void exception_return(CPUMIPSState *env)
1011 {
1012     debug_pre_eret(env);
1013     if (env->CP0_Status & (1 << CP0St_ERL)) {
1014         set_pc(env, env->CP0_ErrorEPC);
1015         env->CP0_Status &= ~(1 << CP0St_ERL);
1016     } else {
1017         set_pc(env, env->CP0_EPC);
1018         env->CP0_Status &= ~(1 << CP0St_EXL);
1019     }
1020     compute_hflags(env);
1021     debug_post_eret(env);
1022 }
1023 
1024 void helper_eret(CPUMIPSState *env)
1025 {
1026     exception_return(env);
1027     env->CP0_LLAddr = 1;
1028     env->lladdr = 1;
1029 }
1030 
1031 void helper_eretnc(CPUMIPSState *env)
1032 {
1033     exception_return(env);
1034 }
1035 
1036 void helper_deret(CPUMIPSState *env)
1037 {
1038     debug_pre_eret(env);
1039 
1040     env->hflags &= ~MIPS_HFLAG_DM;
1041     compute_hflags(env);
1042 
1043     set_pc(env, env->CP0_DEPC);
1044 
1045     debug_post_eret(env);
1046 }
1047 #endif /* !CONFIG_USER_ONLY */
1048 
1049 static inline void check_hwrena(CPUMIPSState *env, int reg, uintptr_t pc)
1050 {
1051     if ((env->hflags & MIPS_HFLAG_CP0) || (env->CP0_HWREna & (1 << reg))) {
1052         return;
1053     }
1054     do_raise_exception(env, EXCP_RI, pc);
1055 }
1056 
1057 target_ulong helper_rdhwr_cpunum(CPUMIPSState *env)
1058 {
1059     check_hwrena(env, 0, GETPC());
1060     return env->CP0_EBase & 0x3ff;
1061 }
1062 
1063 target_ulong helper_rdhwr_synci_step(CPUMIPSState *env)
1064 {
1065     check_hwrena(env, 1, GETPC());
1066     return env->SYNCI_Step;
1067 }
1068 
1069 target_ulong helper_rdhwr_cc(CPUMIPSState *env)
1070 {
1071     check_hwrena(env, 2, GETPC());
1072 #ifdef CONFIG_USER_ONLY
1073     return env->CP0_Count;
1074 #else
1075     return (int32_t)cpu_mips_get_count(env);
1076 #endif
1077 }
1078 
1079 target_ulong helper_rdhwr_ccres(CPUMIPSState *env)
1080 {
1081     check_hwrena(env, 3, GETPC());
1082     return env->CCRes;
1083 }
1084 
1085 target_ulong helper_rdhwr_performance(CPUMIPSState *env)
1086 {
1087     check_hwrena(env, 4, GETPC());
1088     return env->CP0_Performance0;
1089 }
1090 
1091 target_ulong helper_rdhwr_xnp(CPUMIPSState *env)
1092 {
1093     check_hwrena(env, 5, GETPC());
1094     return (env->CP0_Config5 >> CP0C5_XNP) & 1;
1095 }
1096 
1097 void helper_pmon(CPUMIPSState *env, int function)
1098 {
1099     function /= 2;
1100     switch (function) {
1101     case 2: /* TODO: char inbyte(int waitflag); */
1102         if (env->active_tc.gpr[4] == 0) {
1103             env->active_tc.gpr[2] = -1;
1104         }
1105         /* Fall through */
1106     case 11: /* TODO: char inbyte (void); */
1107         env->active_tc.gpr[2] = -1;
1108         break;
1109     case 3:
1110     case 12:
1111         printf("%c", (char)(env->active_tc.gpr[4] & 0xFF));
1112         break;
1113     case 17:
1114         break;
1115     case 158:
1116         {
1117             unsigned char *fmt = (void *)(uintptr_t)env->active_tc.gpr[4];
1118             printf("%s", fmt);
1119         }
1120         break;
1121     }
1122 }
1123 
1124 void helper_wait(CPUMIPSState *env)
1125 {
1126     CPUState *cs = env_cpu(env);
1127 
1128     cs->halted = 1;
1129     cpu_reset_interrupt(cs, CPU_INTERRUPT_WAKE);
1130     /*
1131      * Last instruction in the block, PC was updated before
1132      * - no need to recover PC and icount.
1133      */
1134     raise_exception(env, EXCP_HLT);
1135 }
1136 
1137 #if !defined(CONFIG_USER_ONLY)
1138 
1139 void mips_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
1140                                   MMUAccessType access_type,
1141                                   int mmu_idx, uintptr_t retaddr)
1142 {
1143     MIPSCPU *cpu = MIPS_CPU(cs);
1144     CPUMIPSState *env = &cpu->env;
1145     int error_code = 0;
1146     int excp;
1147 
1148     if (!(env->hflags & MIPS_HFLAG_DM)) {
1149         env->CP0_BadVAddr = addr;
1150     }
1151 
1152     if (access_type == MMU_DATA_STORE) {
1153         excp = EXCP_AdES;
1154     } else {
1155         excp = EXCP_AdEL;
1156         if (access_type == MMU_INST_FETCH) {
1157             error_code |= EXCP_INST_NOTAVAIL;
1158         }
1159     }
1160 
1161     do_raise_exception_err(env, excp, error_code, retaddr);
1162 }
1163 
1164 void mips_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
1165                                     vaddr addr, unsigned size,
1166                                     MMUAccessType access_type,
1167                                     int mmu_idx, MemTxAttrs attrs,
1168                                     MemTxResult response, uintptr_t retaddr)
1169 {
1170     MIPSCPU *cpu = MIPS_CPU(cs);
1171     CPUMIPSState *env = &cpu->env;
1172 
1173     if (access_type == MMU_INST_FETCH) {
1174         do_raise_exception(env, EXCP_IBE, retaddr);
1175     } else {
1176         do_raise_exception(env, EXCP_DBE, retaddr);
1177     }
1178 }
1179 #endif /* !CONFIG_USER_ONLY */
1180 
1181 /* Complex FPU operations which may need stack space. */
1182 
1183 #define FLOAT_TWO32 make_float32(1 << 30)
1184 #define FLOAT_TWO64 make_float64(1ULL << 62)
1185 
1186 #define FP_TO_INT32_OVERFLOW 0x7fffffff
1187 #define FP_TO_INT64_OVERFLOW 0x7fffffffffffffffULL
1188 
1189 /* convert MIPS rounding mode in FCR31 to IEEE library */
1190 unsigned int ieee_rm[] = {
1191     float_round_nearest_even,
1192     float_round_to_zero,
1193     float_round_up,
1194     float_round_down
1195 };
1196 
1197 target_ulong helper_cfc1(CPUMIPSState *env, uint32_t reg)
1198 {
1199     target_ulong arg1 = 0;
1200 
1201     switch (reg) {
1202     case 0:
1203         arg1 = (int32_t)env->active_fpu.fcr0;
1204         break;
1205     case 1:
1206         /* UFR Support - Read Status FR */
1207         if (env->active_fpu.fcr0 & (1 << FCR0_UFRP)) {
1208             if (env->CP0_Config5 & (1 << CP0C5_UFR)) {
1209                 arg1 = (int32_t)
1210                        ((env->CP0_Status & (1  << CP0St_FR)) >> CP0St_FR);
1211             } else {
1212                 do_raise_exception(env, EXCP_RI, GETPC());
1213             }
1214         }
1215         break;
1216     case 5:
1217         /* FRE Support - read Config5.FRE bit */
1218         if (env->active_fpu.fcr0 & (1 << FCR0_FREP)) {
1219             if (env->CP0_Config5 & (1 << CP0C5_UFE)) {
1220                 arg1 = (env->CP0_Config5 >> CP0C5_FRE) & 1;
1221             } else {
1222                 helper_raise_exception(env, EXCP_RI);
1223             }
1224         }
1225         break;
1226     case 25:
1227         arg1 = ((env->active_fpu.fcr31 >> 24) & 0xfe) |
1228                ((env->active_fpu.fcr31 >> 23) & 0x1);
1229         break;
1230     case 26:
1231         arg1 = env->active_fpu.fcr31 & 0x0003f07c;
1232         break;
1233     case 28:
1234         arg1 = (env->active_fpu.fcr31 & 0x00000f83) |
1235                ((env->active_fpu.fcr31 >> 22) & 0x4);
1236         break;
1237     default:
1238         arg1 = (int32_t)env->active_fpu.fcr31;
1239         break;
1240     }
1241 
1242     return arg1;
1243 }
1244 
1245 void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t fs, uint32_t rt)
1246 {
1247     switch (fs) {
1248     case 1:
1249         /* UFR Alias - Reset Status FR */
1250         if (!((env->active_fpu.fcr0 & (1 << FCR0_UFRP)) && (rt == 0))) {
1251             return;
1252         }
1253         if (env->CP0_Config5 & (1 << CP0C5_UFR)) {
1254             env->CP0_Status &= ~(1 << CP0St_FR);
1255             compute_hflags(env);
1256         } else {
1257             do_raise_exception(env, EXCP_RI, GETPC());
1258         }
1259         break;
1260     case 4:
1261         /* UNFR Alias - Set Status FR */
1262         if (!((env->active_fpu.fcr0 & (1 << FCR0_UFRP)) && (rt == 0))) {
1263             return;
1264         }
1265         if (env->CP0_Config5 & (1 << CP0C5_UFR)) {
1266             env->CP0_Status |= (1 << CP0St_FR);
1267             compute_hflags(env);
1268         } else {
1269             do_raise_exception(env, EXCP_RI, GETPC());
1270         }
1271         break;
1272     case 5:
1273         /* FRE Support - clear Config5.FRE bit */
1274         if (!((env->active_fpu.fcr0 & (1 << FCR0_FREP)) && (rt == 0))) {
1275             return;
1276         }
1277         if (env->CP0_Config5 & (1 << CP0C5_UFE)) {
1278             env->CP0_Config5 &= ~(1 << CP0C5_FRE);
1279             compute_hflags(env);
1280         } else {
1281             helper_raise_exception(env, EXCP_RI);
1282         }
1283         break;
1284     case 6:
1285         /* FRE Support - set Config5.FRE bit */
1286         if (!((env->active_fpu.fcr0 & (1 << FCR0_FREP)) && (rt == 0))) {
1287             return;
1288         }
1289         if (env->CP0_Config5 & (1 << CP0C5_UFE)) {
1290             env->CP0_Config5 |= (1 << CP0C5_FRE);
1291             compute_hflags(env);
1292         } else {
1293             helper_raise_exception(env, EXCP_RI);
1294         }
1295         break;
1296     case 25:
1297         if ((env->insn_flags & ISA_MIPS32R6) || (arg1 & 0xffffff00)) {
1298             return;
1299         }
1300         env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0x017fffff) |
1301                                 ((arg1 & 0xfe) << 24) |
1302                                 ((arg1 & 0x1) << 23);
1303         break;
1304     case 26:
1305         if (arg1 & 0x007c0000) {
1306             return;
1307         }
1308         env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0xfffc0f83) |
1309                                 (arg1 & 0x0003f07c);
1310         break;
1311     case 28:
1312         if (arg1 & 0x007c0000) {
1313             return;
1314         }
1315         env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0xfefff07c) |
1316                                 (arg1 & 0x00000f83) |
1317                                 ((arg1 & 0x4) << 22);
1318         break;
1319     case 31:
1320         env->active_fpu.fcr31 = (arg1 & env->active_fpu.fcr31_rw_bitmask) |
1321                (env->active_fpu.fcr31 & ~(env->active_fpu.fcr31_rw_bitmask));
1322         break;
1323     default:
1324         if (env->insn_flags & ISA_MIPS32R6) {
1325             do_raise_exception(env, EXCP_RI, GETPC());
1326         }
1327         return;
1328     }
1329     restore_fp_status(env);
1330     set_float_exception_flags(0, &env->active_fpu.fp_status);
1331     if ((GET_FP_ENABLE(env->active_fpu.fcr31) | 0x20) &
1332         GET_FP_CAUSE(env->active_fpu.fcr31)) {
1333         do_raise_exception(env, EXCP_FPE, GETPC());
1334     }
1335 }
1336 
1337 int ieee_ex_to_mips(int xcpt)
1338 {
1339     int ret = 0;
1340     if (xcpt) {
1341         if (xcpt & float_flag_invalid) {
1342             ret |= FP_INVALID;
1343         }
1344         if (xcpt & float_flag_overflow) {
1345             ret |= FP_OVERFLOW;
1346         }
1347         if (xcpt & float_flag_underflow) {
1348             ret |= FP_UNDERFLOW;
1349         }
1350         if (xcpt & float_flag_divbyzero) {
1351             ret |= FP_DIV0;
1352         }
1353         if (xcpt & float_flag_inexact) {
1354             ret |= FP_INEXACT;
1355         }
1356     }
1357     return ret;
1358 }
1359 
1360 static inline void update_fcr31(CPUMIPSState *env, uintptr_t pc)
1361 {
1362     int tmp = ieee_ex_to_mips(get_float_exception_flags(
1363                                   &env->active_fpu.fp_status));
1364 
1365     SET_FP_CAUSE(env->active_fpu.fcr31, tmp);
1366 
1367     if (tmp) {
1368         set_float_exception_flags(0, &env->active_fpu.fp_status);
1369 
1370         if (GET_FP_ENABLE(env->active_fpu.fcr31) & tmp) {
1371             do_raise_exception(env, EXCP_FPE, pc);
1372         } else {
1373             UPDATE_FP_FLAGS(env->active_fpu.fcr31, tmp);
1374         }
1375     }
1376 }
1377 
1378 /*
1379  * Float support.
1380  * Single precition routines have a "s" suffix, double precision a
1381  * "d" suffix, 32bit integer "w", 64bit integer "l", paired single "ps",
1382  * paired single lower "pl", paired single upper "pu".
1383  */
1384 
1385 /* unary operations, modifying fp status  */
1386 uint64_t helper_float_sqrt_d(CPUMIPSState *env, uint64_t fdt0)
1387 {
1388     fdt0 = float64_sqrt(fdt0, &env->active_fpu.fp_status);
1389     update_fcr31(env, GETPC());
1390     return fdt0;
1391 }
1392 
1393 uint32_t helper_float_sqrt_s(CPUMIPSState *env, uint32_t fst0)
1394 {
1395     fst0 = float32_sqrt(fst0, &env->active_fpu.fp_status);
1396     update_fcr31(env, GETPC());
1397     return fst0;
1398 }
1399 
1400 uint64_t helper_float_cvtd_s(CPUMIPSState *env, uint32_t fst0)
1401 {
1402     uint64_t fdt2;
1403 
1404     fdt2 = float32_to_float64(fst0, &env->active_fpu.fp_status);
1405     update_fcr31(env, GETPC());
1406     return fdt2;
1407 }
1408 
1409 uint64_t helper_float_cvtd_w(CPUMIPSState *env, uint32_t wt0)
1410 {
1411     uint64_t fdt2;
1412 
1413     fdt2 = int32_to_float64(wt0, &env->active_fpu.fp_status);
1414     update_fcr31(env, GETPC());
1415     return fdt2;
1416 }
1417 
1418 uint64_t helper_float_cvtd_l(CPUMIPSState *env, uint64_t dt0)
1419 {
1420     uint64_t fdt2;
1421 
1422     fdt2 = int64_to_float64(dt0, &env->active_fpu.fp_status);
1423     update_fcr31(env, GETPC());
1424     return fdt2;
1425 }
1426 
1427 uint64_t helper_float_cvt_l_d(CPUMIPSState *env, uint64_t fdt0)
1428 {
1429     uint64_t dt2;
1430 
1431     dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
1432     if (get_float_exception_flags(&env->active_fpu.fp_status)
1433         & (float_flag_invalid | float_flag_overflow)) {
1434         dt2 = FP_TO_INT64_OVERFLOW;
1435     }
1436     update_fcr31(env, GETPC());
1437     return dt2;
1438 }
1439 
1440 uint64_t helper_float_cvt_l_s(CPUMIPSState *env, uint32_t fst0)
1441 {
1442     uint64_t dt2;
1443 
1444     dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
1445     if (get_float_exception_flags(&env->active_fpu.fp_status)
1446         & (float_flag_invalid | float_flag_overflow)) {
1447         dt2 = FP_TO_INT64_OVERFLOW;
1448     }
1449     update_fcr31(env, GETPC());
1450     return dt2;
1451 }
1452 
1453 uint64_t helper_float_cvtps_pw(CPUMIPSState *env, uint64_t dt0)
1454 {
1455     uint32_t fst2;
1456     uint32_t fsth2;
1457 
1458     fst2 = int32_to_float32(dt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
1459     fsth2 = int32_to_float32(dt0 >> 32, &env->active_fpu.fp_status);
1460     update_fcr31(env, GETPC());
1461     return ((uint64_t)fsth2 << 32) | fst2;
1462 }
1463 
1464 uint64_t helper_float_cvtpw_ps(CPUMIPSState *env, uint64_t fdt0)
1465 {
1466     uint32_t wt2;
1467     uint32_t wth2;
1468     int excp, excph;
1469 
1470     wt2 = float32_to_int32(fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
1471     excp = get_float_exception_flags(&env->active_fpu.fp_status);
1472     if (excp & (float_flag_overflow | float_flag_invalid)) {
1473         wt2 = FP_TO_INT32_OVERFLOW;
1474     }
1475 
1476     set_float_exception_flags(0, &env->active_fpu.fp_status);
1477     wth2 = float32_to_int32(fdt0 >> 32, &env->active_fpu.fp_status);
1478     excph = get_float_exception_flags(&env->active_fpu.fp_status);
1479     if (excph & (float_flag_overflow | float_flag_invalid)) {
1480         wth2 = FP_TO_INT32_OVERFLOW;
1481     }
1482 
1483     set_float_exception_flags(excp | excph, &env->active_fpu.fp_status);
1484     update_fcr31(env, GETPC());
1485 
1486     return ((uint64_t)wth2 << 32) | wt2;
1487 }
1488 
1489 uint32_t helper_float_cvts_d(CPUMIPSState *env, uint64_t fdt0)
1490 {
1491     uint32_t fst2;
1492 
1493     fst2 = float64_to_float32(fdt0, &env->active_fpu.fp_status);
1494     update_fcr31(env, GETPC());
1495     return fst2;
1496 }
1497 
1498 uint32_t helper_float_cvts_w(CPUMIPSState *env, uint32_t wt0)
1499 {
1500     uint32_t fst2;
1501 
1502     fst2 = int32_to_float32(wt0, &env->active_fpu.fp_status);
1503     update_fcr31(env, GETPC());
1504     return fst2;
1505 }
1506 
1507 uint32_t helper_float_cvts_l(CPUMIPSState *env, uint64_t dt0)
1508 {
1509     uint32_t fst2;
1510 
1511     fst2 = int64_to_float32(dt0, &env->active_fpu.fp_status);
1512     update_fcr31(env, GETPC());
1513     return fst2;
1514 }
1515 
1516 uint32_t helper_float_cvts_pl(CPUMIPSState *env, uint32_t wt0)
1517 {
1518     uint32_t wt2;
1519 
1520     wt2 = wt0;
1521     update_fcr31(env, GETPC());
1522     return wt2;
1523 }
1524 
1525 uint32_t helper_float_cvts_pu(CPUMIPSState *env, uint32_t wth0)
1526 {
1527     uint32_t wt2;
1528 
1529     wt2 = wth0;
1530     update_fcr31(env, GETPC());
1531     return wt2;
1532 }
1533 
1534 uint32_t helper_float_cvt_w_s(CPUMIPSState *env, uint32_t fst0)
1535 {
1536     uint32_t wt2;
1537 
1538     wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
1539     if (get_float_exception_flags(&env->active_fpu.fp_status)
1540         & (float_flag_invalid | float_flag_overflow)) {
1541         wt2 = FP_TO_INT32_OVERFLOW;
1542     }
1543     update_fcr31(env, GETPC());
1544     return wt2;
1545 }
1546 
1547 uint32_t helper_float_cvt_w_d(CPUMIPSState *env, uint64_t fdt0)
1548 {
1549     uint32_t wt2;
1550 
1551     wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
1552     if (get_float_exception_flags(&env->active_fpu.fp_status)
1553         & (float_flag_invalid | float_flag_overflow)) {
1554         wt2 = FP_TO_INT32_OVERFLOW;
1555     }
1556     update_fcr31(env, GETPC());
1557     return wt2;
1558 }
1559 
1560 uint64_t helper_float_round_l_d(CPUMIPSState *env, uint64_t fdt0)
1561 {
1562     uint64_t dt2;
1563 
1564     set_float_rounding_mode(float_round_nearest_even,
1565                             &env->active_fpu.fp_status);
1566     dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
1567     restore_rounding_mode(env);
1568     if (get_float_exception_flags(&env->active_fpu.fp_status)
1569         & (float_flag_invalid | float_flag_overflow)) {
1570         dt2 = FP_TO_INT64_OVERFLOW;
1571     }
1572     update_fcr31(env, GETPC());
1573     return dt2;
1574 }
1575 
1576 uint64_t helper_float_round_l_s(CPUMIPSState *env, uint32_t fst0)
1577 {
1578     uint64_t dt2;
1579 
1580     set_float_rounding_mode(float_round_nearest_even,
1581                             &env->active_fpu.fp_status);
1582     dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
1583     restore_rounding_mode(env);
1584     if (get_float_exception_flags(&env->active_fpu.fp_status)
1585         & (float_flag_invalid | float_flag_overflow)) {
1586         dt2 = FP_TO_INT64_OVERFLOW;
1587     }
1588     update_fcr31(env, GETPC());
1589     return dt2;
1590 }
1591 
1592 uint32_t helper_float_round_w_d(CPUMIPSState *env, uint64_t fdt0)
1593 {
1594     uint32_t wt2;
1595 
1596     set_float_rounding_mode(float_round_nearest_even,
1597                             &env->active_fpu.fp_status);
1598     wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
1599     restore_rounding_mode(env);
1600     if (get_float_exception_flags(&env->active_fpu.fp_status)
1601         & (float_flag_invalid | float_flag_overflow)) {
1602         wt2 = FP_TO_INT32_OVERFLOW;
1603     }
1604     update_fcr31(env, GETPC());
1605     return wt2;
1606 }
1607 
1608 uint32_t helper_float_round_w_s(CPUMIPSState *env, uint32_t fst0)
1609 {
1610     uint32_t wt2;
1611 
1612     set_float_rounding_mode(float_round_nearest_even,
1613                             &env->active_fpu.fp_status);
1614     wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
1615     restore_rounding_mode(env);
1616     if (get_float_exception_flags(&env->active_fpu.fp_status)
1617         & (float_flag_invalid | float_flag_overflow)) {
1618         wt2 = FP_TO_INT32_OVERFLOW;
1619     }
1620     update_fcr31(env, GETPC());
1621     return wt2;
1622 }
1623 
1624 uint64_t helper_float_trunc_l_d(CPUMIPSState *env, uint64_t fdt0)
1625 {
1626     uint64_t dt2;
1627 
1628     dt2 = float64_to_int64_round_to_zero(fdt0,
1629                                          &env->active_fpu.fp_status);
1630     if (get_float_exception_flags(&env->active_fpu.fp_status)
1631         & (float_flag_invalid | float_flag_overflow)) {
1632         dt2 = FP_TO_INT64_OVERFLOW;
1633     }
1634     update_fcr31(env, GETPC());
1635     return dt2;
1636 }
1637 
1638 uint64_t helper_float_trunc_l_s(CPUMIPSState *env, uint32_t fst0)
1639 {
1640     uint64_t dt2;
1641 
1642     dt2 = float32_to_int64_round_to_zero(fst0, &env->active_fpu.fp_status);
1643     if (get_float_exception_flags(&env->active_fpu.fp_status)
1644         & (float_flag_invalid | float_flag_overflow)) {
1645         dt2 = FP_TO_INT64_OVERFLOW;
1646     }
1647     update_fcr31(env, GETPC());
1648     return dt2;
1649 }
1650 
1651 uint32_t helper_float_trunc_w_d(CPUMIPSState *env, uint64_t fdt0)
1652 {
1653     uint32_t wt2;
1654 
1655     wt2 = float64_to_int32_round_to_zero(fdt0, &env->active_fpu.fp_status);
1656     if (get_float_exception_flags(&env->active_fpu.fp_status)
1657         & (float_flag_invalid | float_flag_overflow)) {
1658         wt2 = FP_TO_INT32_OVERFLOW;
1659     }
1660     update_fcr31(env, GETPC());
1661     return wt2;
1662 }
1663 
1664 uint32_t helper_float_trunc_w_s(CPUMIPSState *env, uint32_t fst0)
1665 {
1666     uint32_t wt2;
1667 
1668     wt2 = float32_to_int32_round_to_zero(fst0, &env->active_fpu.fp_status);
1669     if (get_float_exception_flags(&env->active_fpu.fp_status)
1670         & (float_flag_invalid | float_flag_overflow)) {
1671         wt2 = FP_TO_INT32_OVERFLOW;
1672     }
1673     update_fcr31(env, GETPC());
1674     return wt2;
1675 }
1676 
1677 uint64_t helper_float_ceil_l_d(CPUMIPSState *env, uint64_t fdt0)
1678 {
1679     uint64_t dt2;
1680 
1681     set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
1682     dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
1683     restore_rounding_mode(env);
1684     if (get_float_exception_flags(&env->active_fpu.fp_status)
1685         & (float_flag_invalid | float_flag_overflow)) {
1686         dt2 = FP_TO_INT64_OVERFLOW;
1687     }
1688     update_fcr31(env, GETPC());
1689     return dt2;
1690 }
1691 
1692 uint64_t helper_float_ceil_l_s(CPUMIPSState *env, uint32_t fst0)
1693 {
1694     uint64_t dt2;
1695 
1696     set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
1697     dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
1698     restore_rounding_mode(env);
1699     if (get_float_exception_flags(&env->active_fpu.fp_status)
1700         & (float_flag_invalid | float_flag_overflow)) {
1701         dt2 = FP_TO_INT64_OVERFLOW;
1702     }
1703     update_fcr31(env, GETPC());
1704     return dt2;
1705 }
1706 
1707 uint32_t helper_float_ceil_w_d(CPUMIPSState *env, uint64_t fdt0)
1708 {
1709     uint32_t wt2;
1710 
1711     set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
1712     wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
1713     restore_rounding_mode(env);
1714     if (get_float_exception_flags(&env->active_fpu.fp_status)
1715         & (float_flag_invalid | float_flag_overflow)) {
1716         wt2 = FP_TO_INT32_OVERFLOW;
1717     }
1718     update_fcr31(env, GETPC());
1719     return wt2;
1720 }
1721 
1722 uint32_t helper_float_ceil_w_s(CPUMIPSState *env, uint32_t fst0)
1723 {
1724     uint32_t wt2;
1725 
1726     set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
1727     wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
1728     restore_rounding_mode(env);
1729     if (get_float_exception_flags(&env->active_fpu.fp_status)
1730         & (float_flag_invalid | float_flag_overflow)) {
1731         wt2 = FP_TO_INT32_OVERFLOW;
1732     }
1733     update_fcr31(env, GETPC());
1734     return wt2;
1735 }
1736 
1737 uint64_t helper_float_floor_l_d(CPUMIPSState *env, uint64_t fdt0)
1738 {
1739     uint64_t dt2;
1740 
1741     set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
1742     dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
1743     restore_rounding_mode(env);
1744     if (get_float_exception_flags(&env->active_fpu.fp_status)
1745         & (float_flag_invalid | float_flag_overflow)) {
1746         dt2 = FP_TO_INT64_OVERFLOW;
1747     }
1748     update_fcr31(env, GETPC());
1749     return dt2;
1750 }
1751 
1752 uint64_t helper_float_floor_l_s(CPUMIPSState *env, uint32_t fst0)
1753 {
1754     uint64_t dt2;
1755 
1756     set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
1757     dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
1758     restore_rounding_mode(env);
1759     if (get_float_exception_flags(&env->active_fpu.fp_status)
1760         & (float_flag_invalid | float_flag_overflow)) {
1761         dt2 = FP_TO_INT64_OVERFLOW;
1762     }
1763     update_fcr31(env, GETPC());
1764     return dt2;
1765 }
1766 
1767 uint32_t helper_float_floor_w_d(CPUMIPSState *env, uint64_t fdt0)
1768 {
1769     uint32_t wt2;
1770 
1771     set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
1772     wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
1773     restore_rounding_mode(env);
1774     if (get_float_exception_flags(&env->active_fpu.fp_status)
1775         & (float_flag_invalid | float_flag_overflow)) {
1776         wt2 = FP_TO_INT32_OVERFLOW;
1777     }
1778     update_fcr31(env, GETPC());
1779     return wt2;
1780 }
1781 
1782 uint32_t helper_float_floor_w_s(CPUMIPSState *env, uint32_t fst0)
1783 {
1784     uint32_t wt2;
1785 
1786     set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
1787     wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
1788     restore_rounding_mode(env);
1789     if (get_float_exception_flags(&env->active_fpu.fp_status)
1790         & (float_flag_invalid | float_flag_overflow)) {
1791         wt2 = FP_TO_INT32_OVERFLOW;
1792     }
1793     update_fcr31(env, GETPC());
1794     return wt2;
1795 }
1796 
1797 uint64_t helper_float_cvt_2008_l_d(CPUMIPSState *env, uint64_t fdt0)
1798 {
1799     uint64_t dt2;
1800 
1801     dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
1802     if (get_float_exception_flags(&env->active_fpu.fp_status)
1803             & float_flag_invalid) {
1804         if (float64_is_any_nan(fdt0)) {
1805             dt2 = 0;
1806         }
1807     }
1808     update_fcr31(env, GETPC());
1809     return dt2;
1810 }
1811 
1812 uint64_t helper_float_cvt_2008_l_s(CPUMIPSState *env, uint32_t fst0)
1813 {
1814     uint64_t dt2;
1815 
1816     dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
1817     if (get_float_exception_flags(&env->active_fpu.fp_status)
1818             & float_flag_invalid) {
1819         if (float32_is_any_nan(fst0)) {
1820             dt2 = 0;
1821         }
1822     }
1823     update_fcr31(env, GETPC());
1824     return dt2;
1825 }
1826 
1827 uint32_t helper_float_cvt_2008_w_d(CPUMIPSState *env, uint64_t fdt0)
1828 {
1829     uint32_t wt2;
1830 
1831     wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
1832     if (get_float_exception_flags(&env->active_fpu.fp_status)
1833             & float_flag_invalid) {
1834         if (float64_is_any_nan(fdt0)) {
1835             wt2 = 0;
1836         }
1837     }
1838     update_fcr31(env, GETPC());
1839     return wt2;
1840 }
1841 
1842 uint32_t helper_float_cvt_2008_w_s(CPUMIPSState *env, uint32_t fst0)
1843 {
1844     uint32_t wt2;
1845 
1846     wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
1847     if (get_float_exception_flags(&env->active_fpu.fp_status)
1848             & float_flag_invalid) {
1849         if (float32_is_any_nan(fst0)) {
1850             wt2 = 0;
1851         }
1852     }
1853     update_fcr31(env, GETPC());
1854     return wt2;
1855 }
1856 
1857 uint64_t helper_float_round_2008_l_d(CPUMIPSState *env, uint64_t fdt0)
1858 {
1859     uint64_t dt2;
1860 
1861     set_float_rounding_mode(float_round_nearest_even,
1862             &env->active_fpu.fp_status);
1863     dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
1864     restore_rounding_mode(env);
1865     if (get_float_exception_flags(&env->active_fpu.fp_status)
1866             & float_flag_invalid) {
1867         if (float64_is_any_nan(fdt0)) {
1868             dt2 = 0;
1869         }
1870     }
1871     update_fcr31(env, GETPC());
1872     return dt2;
1873 }
1874 
1875 uint64_t helper_float_round_2008_l_s(CPUMIPSState *env, uint32_t fst0)
1876 {
1877     uint64_t dt2;
1878 
1879     set_float_rounding_mode(float_round_nearest_even,
1880             &env->active_fpu.fp_status);
1881     dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
1882     restore_rounding_mode(env);
1883     if (get_float_exception_flags(&env->active_fpu.fp_status)
1884             & float_flag_invalid) {
1885         if (float32_is_any_nan(fst0)) {
1886             dt2 = 0;
1887         }
1888     }
1889     update_fcr31(env, GETPC());
1890     return dt2;
1891 }
1892 
1893 uint32_t helper_float_round_2008_w_d(CPUMIPSState *env, uint64_t fdt0)
1894 {
1895     uint32_t wt2;
1896 
1897     set_float_rounding_mode(float_round_nearest_even,
1898             &env->active_fpu.fp_status);
1899     wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
1900     restore_rounding_mode(env);
1901     if (get_float_exception_flags(&env->active_fpu.fp_status)
1902             & float_flag_invalid) {
1903         if (float64_is_any_nan(fdt0)) {
1904             wt2 = 0;
1905         }
1906     }
1907     update_fcr31(env, GETPC());
1908     return wt2;
1909 }
1910 
1911 uint32_t helper_float_round_2008_w_s(CPUMIPSState *env, uint32_t fst0)
1912 {
1913     uint32_t wt2;
1914 
1915     set_float_rounding_mode(float_round_nearest_even,
1916             &env->active_fpu.fp_status);
1917     wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
1918     restore_rounding_mode(env);
1919     if (get_float_exception_flags(&env->active_fpu.fp_status)
1920             & float_flag_invalid) {
1921         if (float32_is_any_nan(fst0)) {
1922             wt2 = 0;
1923         }
1924     }
1925     update_fcr31(env, GETPC());
1926     return wt2;
1927 }
1928 
1929 uint64_t helper_float_trunc_2008_l_d(CPUMIPSState *env, uint64_t fdt0)
1930 {
1931     uint64_t dt2;
1932 
1933     dt2 = float64_to_int64_round_to_zero(fdt0, &env->active_fpu.fp_status);
1934     if (get_float_exception_flags(&env->active_fpu.fp_status)
1935             & float_flag_invalid) {
1936         if (float64_is_any_nan(fdt0)) {
1937             dt2 = 0;
1938         }
1939     }
1940     update_fcr31(env, GETPC());
1941     return dt2;
1942 }
1943 
1944 uint64_t helper_float_trunc_2008_l_s(CPUMIPSState *env, uint32_t fst0)
1945 {
1946     uint64_t dt2;
1947 
1948     dt2 = float32_to_int64_round_to_zero(fst0, &env->active_fpu.fp_status);
1949     if (get_float_exception_flags(&env->active_fpu.fp_status)
1950             & float_flag_invalid) {
1951         if (float32_is_any_nan(fst0)) {
1952             dt2 = 0;
1953         }
1954     }
1955     update_fcr31(env, GETPC());
1956     return dt2;
1957 }
1958 
1959 uint32_t helper_float_trunc_2008_w_d(CPUMIPSState *env, uint64_t fdt0)
1960 {
1961     uint32_t wt2;
1962 
1963     wt2 = float64_to_int32_round_to_zero(fdt0, &env->active_fpu.fp_status);
1964     if (get_float_exception_flags(&env->active_fpu.fp_status)
1965             & float_flag_invalid) {
1966         if (float64_is_any_nan(fdt0)) {
1967             wt2 = 0;
1968         }
1969     }
1970     update_fcr31(env, GETPC());
1971     return wt2;
1972 }
1973 
1974 uint32_t helper_float_trunc_2008_w_s(CPUMIPSState *env, uint32_t fst0)
1975 {
1976     uint32_t wt2;
1977 
1978     wt2 = float32_to_int32_round_to_zero(fst0, &env->active_fpu.fp_status);
1979     if (get_float_exception_flags(&env->active_fpu.fp_status)
1980             & float_flag_invalid) {
1981         if (float32_is_any_nan(fst0)) {
1982             wt2 = 0;
1983         }
1984     }
1985     update_fcr31(env, GETPC());
1986     return wt2;
1987 }
1988 
1989 uint64_t helper_float_ceil_2008_l_d(CPUMIPSState *env, uint64_t fdt0)
1990 {
1991     uint64_t dt2;
1992 
1993     set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
1994     dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
1995     restore_rounding_mode(env);
1996     if (get_float_exception_flags(&env->active_fpu.fp_status)
1997             & float_flag_invalid) {
1998         if (float64_is_any_nan(fdt0)) {
1999             dt2 = 0;
2000         }
2001     }
2002     update_fcr31(env, GETPC());
2003     return dt2;
2004 }
2005 
2006 uint64_t helper_float_ceil_2008_l_s(CPUMIPSState *env, uint32_t fst0)
2007 {
2008     uint64_t dt2;
2009 
2010     set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
2011     dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
2012     restore_rounding_mode(env);
2013     if (get_float_exception_flags(&env->active_fpu.fp_status)
2014             & float_flag_invalid) {
2015         if (float32_is_any_nan(fst0)) {
2016             dt2 = 0;
2017         }
2018     }
2019     update_fcr31(env, GETPC());
2020     return dt2;
2021 }
2022 
2023 uint32_t helper_float_ceil_2008_w_d(CPUMIPSState *env, uint64_t fdt0)
2024 {
2025     uint32_t wt2;
2026 
2027     set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
2028     wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
2029     restore_rounding_mode(env);
2030     if (get_float_exception_flags(&env->active_fpu.fp_status)
2031             & float_flag_invalid) {
2032         if (float64_is_any_nan(fdt0)) {
2033             wt2 = 0;
2034         }
2035     }
2036     update_fcr31(env, GETPC());
2037     return wt2;
2038 }
2039 
2040 uint32_t helper_float_ceil_2008_w_s(CPUMIPSState *env, uint32_t fst0)
2041 {
2042     uint32_t wt2;
2043 
2044     set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
2045     wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
2046     restore_rounding_mode(env);
2047     if (get_float_exception_flags(&env->active_fpu.fp_status)
2048             & float_flag_invalid) {
2049         if (float32_is_any_nan(fst0)) {
2050             wt2 = 0;
2051         }
2052     }
2053     update_fcr31(env, GETPC());
2054     return wt2;
2055 }
2056 
2057 uint64_t helper_float_floor_2008_l_d(CPUMIPSState *env, uint64_t fdt0)
2058 {
2059     uint64_t dt2;
2060 
2061     set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
2062     dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
2063     restore_rounding_mode(env);
2064     if (get_float_exception_flags(&env->active_fpu.fp_status)
2065             & float_flag_invalid) {
2066         if (float64_is_any_nan(fdt0)) {
2067             dt2 = 0;
2068         }
2069     }
2070     update_fcr31(env, GETPC());
2071     return dt2;
2072 }
2073 
2074 uint64_t helper_float_floor_2008_l_s(CPUMIPSState *env, uint32_t fst0)
2075 {
2076     uint64_t dt2;
2077 
2078     set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
2079     dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
2080     restore_rounding_mode(env);
2081     if (get_float_exception_flags(&env->active_fpu.fp_status)
2082             & float_flag_invalid) {
2083         if (float32_is_any_nan(fst0)) {
2084             dt2 = 0;
2085         }
2086     }
2087     update_fcr31(env, GETPC());
2088     return dt2;
2089 }
2090 
2091 uint32_t helper_float_floor_2008_w_d(CPUMIPSState *env, uint64_t fdt0)
2092 {
2093     uint32_t wt2;
2094 
2095     set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
2096     wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
2097     restore_rounding_mode(env);
2098     if (get_float_exception_flags(&env->active_fpu.fp_status)
2099             & float_flag_invalid) {
2100         if (float64_is_any_nan(fdt0)) {
2101             wt2 = 0;
2102         }
2103     }
2104     update_fcr31(env, GETPC());
2105     return wt2;
2106 }
2107 
2108 uint32_t helper_float_floor_2008_w_s(CPUMIPSState *env, uint32_t fst0)
2109 {
2110     uint32_t wt2;
2111 
2112     set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
2113     wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
2114     restore_rounding_mode(env);
2115     if (get_float_exception_flags(&env->active_fpu.fp_status)
2116             & float_flag_invalid) {
2117         if (float32_is_any_nan(fst0)) {
2118             wt2 = 0;
2119         }
2120     }
2121     update_fcr31(env, GETPC());
2122     return wt2;
2123 }
2124 
2125 /* unary operations, not modifying fp status  */
2126 #define FLOAT_UNOP(name)                                       \
2127 uint64_t helper_float_ ## name ## _d(uint64_t fdt0)                \
2128 {                                                              \
2129     return float64_ ## name(fdt0);                             \
2130 }                                                              \
2131 uint32_t helper_float_ ## name ## _s(uint32_t fst0)                \
2132 {                                                              \
2133     return float32_ ## name(fst0);                             \
2134 }                                                              \
2135 uint64_t helper_float_ ## name ## _ps(uint64_t fdt0)               \
2136 {                                                              \
2137     uint32_t wt0;                                              \
2138     uint32_t wth0;                                             \
2139                                                                \
2140     wt0 = float32_ ## name(fdt0 & 0XFFFFFFFF);                 \
2141     wth0 = float32_ ## name(fdt0 >> 32);                       \
2142     return ((uint64_t)wth0 << 32) | wt0;                       \
2143 }
2144 FLOAT_UNOP(abs)
2145 FLOAT_UNOP(chs)
2146 #undef FLOAT_UNOP
2147 
2148 /* MIPS specific unary operations */
2149 uint64_t helper_float_recip_d(CPUMIPSState *env, uint64_t fdt0)
2150 {
2151     uint64_t fdt2;
2152 
2153     fdt2 = float64_div(float64_one, fdt0, &env->active_fpu.fp_status);
2154     update_fcr31(env, GETPC());
2155     return fdt2;
2156 }
2157 
2158 uint32_t helper_float_recip_s(CPUMIPSState *env, uint32_t fst0)
2159 {
2160     uint32_t fst2;
2161 
2162     fst2 = float32_div(float32_one, fst0, &env->active_fpu.fp_status);
2163     update_fcr31(env, GETPC());
2164     return fst2;
2165 }
2166 
2167 uint64_t helper_float_rsqrt_d(CPUMIPSState *env, uint64_t fdt0)
2168 {
2169     uint64_t fdt2;
2170 
2171     fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status);
2172     fdt2 = float64_div(float64_one, fdt2, &env->active_fpu.fp_status);
2173     update_fcr31(env, GETPC());
2174     return fdt2;
2175 }
2176 
2177 uint32_t helper_float_rsqrt_s(CPUMIPSState *env, uint32_t fst0)
2178 {
2179     uint32_t fst2;
2180 
2181     fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status);
2182     fst2 = float32_div(float32_one, fst2, &env->active_fpu.fp_status);
2183     update_fcr31(env, GETPC());
2184     return fst2;
2185 }
2186 
2187 uint64_t helper_float_recip1_d(CPUMIPSState *env, uint64_t fdt0)
2188 {
2189     uint64_t fdt2;
2190 
2191     fdt2 = float64_div(float64_one, fdt0, &env->active_fpu.fp_status);
2192     update_fcr31(env, GETPC());
2193     return fdt2;
2194 }
2195 
2196 uint32_t helper_float_recip1_s(CPUMIPSState *env, uint32_t fst0)
2197 {
2198     uint32_t fst2;
2199 
2200     fst2 = float32_div(float32_one, fst0, &env->active_fpu.fp_status);
2201     update_fcr31(env, GETPC());
2202     return fst2;
2203 }
2204 
2205 uint64_t helper_float_recip1_ps(CPUMIPSState *env, uint64_t fdt0)
2206 {
2207     uint32_t fst2;
2208     uint32_t fsth2;
2209 
2210     fst2 = float32_div(float32_one, fdt0 & 0XFFFFFFFF,
2211                        &env->active_fpu.fp_status);
2212     fsth2 = float32_div(float32_one, fdt0 >> 32, &env->active_fpu.fp_status);
2213     update_fcr31(env, GETPC());
2214     return ((uint64_t)fsth2 << 32) | fst2;
2215 }
2216 
2217 uint64_t helper_float_rsqrt1_d(CPUMIPSState *env, uint64_t fdt0)
2218 {
2219     uint64_t fdt2;
2220 
2221     fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status);
2222     fdt2 = float64_div(float64_one, fdt2, &env->active_fpu.fp_status);
2223     update_fcr31(env, GETPC());
2224     return fdt2;
2225 }
2226 
2227 uint32_t helper_float_rsqrt1_s(CPUMIPSState *env, uint32_t fst0)
2228 {
2229     uint32_t fst2;
2230 
2231     fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status);
2232     fst2 = float32_div(float32_one, fst2, &env->active_fpu.fp_status);
2233     update_fcr31(env, GETPC());
2234     return fst2;
2235 }
2236 
2237 uint64_t helper_float_rsqrt1_ps(CPUMIPSState *env, uint64_t fdt0)
2238 {
2239     uint32_t fst2;
2240     uint32_t fsth2;
2241 
2242     fst2 = float32_sqrt(fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
2243     fsth2 = float32_sqrt(fdt0 >> 32, &env->active_fpu.fp_status);
2244     fst2 = float32_div(float32_one, fst2, &env->active_fpu.fp_status);
2245     fsth2 = float32_div(float32_one, fsth2, &env->active_fpu.fp_status);
2246     update_fcr31(env, GETPC());
2247     return ((uint64_t)fsth2 << 32) | fst2;
2248 }
2249 
2250 #define FLOAT_RINT(name, bits)                                              \
2251 uint ## bits ## _t helper_float_ ## name(CPUMIPSState *env,                 \
2252                                          uint ## bits ## _t fs)             \
2253 {                                                                           \
2254     uint ## bits ## _t fdret;                                               \
2255                                                                             \
2256     fdret = float ## bits ## _round_to_int(fs, &env->active_fpu.fp_status); \
2257     update_fcr31(env, GETPC());                                             \
2258     return fdret;                                                           \
2259 }
2260 
2261 FLOAT_RINT(rint_s, 32)
2262 FLOAT_RINT(rint_d, 64)
2263 #undef FLOAT_RINT
2264 
2265 #define FLOAT_CLASS_SIGNALING_NAN      0x001
2266 #define FLOAT_CLASS_QUIET_NAN          0x002
2267 #define FLOAT_CLASS_NEGATIVE_INFINITY  0x004
2268 #define FLOAT_CLASS_NEGATIVE_NORMAL    0x008
2269 #define FLOAT_CLASS_NEGATIVE_SUBNORMAL 0x010
2270 #define FLOAT_CLASS_NEGATIVE_ZERO      0x020
2271 #define FLOAT_CLASS_POSITIVE_INFINITY  0x040
2272 #define FLOAT_CLASS_POSITIVE_NORMAL    0x080
2273 #define FLOAT_CLASS_POSITIVE_SUBNORMAL 0x100
2274 #define FLOAT_CLASS_POSITIVE_ZERO      0x200
2275 
2276 #define FLOAT_CLASS(name, bits)                                      \
2277 uint ## bits ## _t float_ ## name(uint ## bits ## _t arg,            \
2278                                   float_status *status)              \
2279 {                                                                    \
2280     if (float ## bits ## _is_signaling_nan(arg, status)) {           \
2281         return FLOAT_CLASS_SIGNALING_NAN;                            \
2282     } else if (float ## bits ## _is_quiet_nan(arg, status)) {        \
2283         return FLOAT_CLASS_QUIET_NAN;                                \
2284     } else if (float ## bits ## _is_neg(arg)) {                      \
2285         if (float ## bits ## _is_infinity(arg)) {                    \
2286             return FLOAT_CLASS_NEGATIVE_INFINITY;                    \
2287         } else if (float ## bits ## _is_zero(arg)) {                 \
2288             return FLOAT_CLASS_NEGATIVE_ZERO;                        \
2289         } else if (float ## bits ## _is_zero_or_denormal(arg)) {     \
2290             return FLOAT_CLASS_NEGATIVE_SUBNORMAL;                   \
2291         } else {                                                     \
2292             return FLOAT_CLASS_NEGATIVE_NORMAL;                      \
2293         }                                                            \
2294     } else {                                                         \
2295         if (float ## bits ## _is_infinity(arg)) {                    \
2296             return FLOAT_CLASS_POSITIVE_INFINITY;                    \
2297         } else if (float ## bits ## _is_zero(arg)) {                 \
2298             return FLOAT_CLASS_POSITIVE_ZERO;                        \
2299         } else if (float ## bits ## _is_zero_or_denormal(arg)) {     \
2300             return FLOAT_CLASS_POSITIVE_SUBNORMAL;                   \
2301         } else {                                                     \
2302             return FLOAT_CLASS_POSITIVE_NORMAL;                      \
2303         }                                                            \
2304     }                                                                \
2305 }                                                                    \
2306                                                                      \
2307 uint ## bits ## _t helper_float_ ## name(CPUMIPSState *env,          \
2308                                          uint ## bits ## _t arg)     \
2309 {                                                                    \
2310     return float_ ## name(arg, &env->active_fpu.fp_status);          \
2311 }
2312 
2313 FLOAT_CLASS(class_s, 32)
2314 FLOAT_CLASS(class_d, 64)
2315 #undef FLOAT_CLASS
2316 
2317 /* binary operations */
2318 #define FLOAT_BINOP(name)                                          \
2319 uint64_t helper_float_ ## name ## _d(CPUMIPSState *env,            \
2320                                      uint64_t fdt0, uint64_t fdt1) \
2321 {                                                                  \
2322     uint64_t dt2;                                                  \
2323                                                                    \
2324     dt2 = float64_ ## name(fdt0, fdt1, &env->active_fpu.fp_status);\
2325     update_fcr31(env, GETPC());                                    \
2326     return dt2;                                                    \
2327 }                                                                  \
2328                                                                    \
2329 uint32_t helper_float_ ## name ## _s(CPUMIPSState *env,            \
2330                                      uint32_t fst0, uint32_t fst1) \
2331 {                                                                  \
2332     uint32_t wt2;                                                  \
2333                                                                    \
2334     wt2 = float32_ ## name(fst0, fst1, &env->active_fpu.fp_status);\
2335     update_fcr31(env, GETPC());                                    \
2336     return wt2;                                                    \
2337 }                                                                  \
2338                                                                    \
2339 uint64_t helper_float_ ## name ## _ps(CPUMIPSState *env,           \
2340                                       uint64_t fdt0,               \
2341                                       uint64_t fdt1)               \
2342 {                                                                  \
2343     uint32_t fst0 = fdt0 & 0XFFFFFFFF;                             \
2344     uint32_t fsth0 = fdt0 >> 32;                                   \
2345     uint32_t fst1 = fdt1 & 0XFFFFFFFF;                             \
2346     uint32_t fsth1 = fdt1 >> 32;                                   \
2347     uint32_t wt2;                                                  \
2348     uint32_t wth2;                                                 \
2349                                                                    \
2350     wt2 = float32_ ## name(fst0, fst1, &env->active_fpu.fp_status);     \
2351     wth2 = float32_ ## name(fsth0, fsth1, &env->active_fpu.fp_status);  \
2352     update_fcr31(env, GETPC());                                    \
2353     return ((uint64_t)wth2 << 32) | wt2;                           \
2354 }
2355 
2356 FLOAT_BINOP(add)
2357 FLOAT_BINOP(sub)
2358 FLOAT_BINOP(mul)
2359 FLOAT_BINOP(div)
2360 #undef FLOAT_BINOP
2361 
2362 /* MIPS specific binary operations */
2363 uint64_t helper_float_recip2_d(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2)
2364 {
2365     fdt2 = float64_mul(fdt0, fdt2, &env->active_fpu.fp_status);
2366     fdt2 = float64_chs(float64_sub(fdt2, float64_one,
2367                                    &env->active_fpu.fp_status));
2368     update_fcr31(env, GETPC());
2369     return fdt2;
2370 }
2371 
2372 uint32_t helper_float_recip2_s(CPUMIPSState *env, uint32_t fst0, uint32_t fst2)
2373 {
2374     fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
2375     fst2 = float32_chs(float32_sub(fst2, float32_one,
2376                                        &env->active_fpu.fp_status));
2377     update_fcr31(env, GETPC());
2378     return fst2;
2379 }
2380 
2381 uint64_t helper_float_recip2_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2)
2382 {
2383     uint32_t fst0 = fdt0 & 0XFFFFFFFF;
2384     uint32_t fsth0 = fdt0 >> 32;
2385     uint32_t fst2 = fdt2 & 0XFFFFFFFF;
2386     uint32_t fsth2 = fdt2 >> 32;
2387 
2388     fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
2389     fsth2 = float32_mul(fsth0, fsth2, &env->active_fpu.fp_status);
2390     fst2 = float32_chs(float32_sub(fst2, float32_one,
2391                                        &env->active_fpu.fp_status));
2392     fsth2 = float32_chs(float32_sub(fsth2, float32_one,
2393                                        &env->active_fpu.fp_status));
2394     update_fcr31(env, GETPC());
2395     return ((uint64_t)fsth2 << 32) | fst2;
2396 }
2397 
2398 uint64_t helper_float_rsqrt2_d(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2)
2399 {
2400     fdt2 = float64_mul(fdt0, fdt2, &env->active_fpu.fp_status);
2401     fdt2 = float64_sub(fdt2, float64_one, &env->active_fpu.fp_status);
2402     fdt2 = float64_chs(float64_div(fdt2, FLOAT_TWO64,
2403                                        &env->active_fpu.fp_status));
2404     update_fcr31(env, GETPC());
2405     return fdt2;
2406 }
2407 
2408 uint32_t helper_float_rsqrt2_s(CPUMIPSState *env, uint32_t fst0, uint32_t fst2)
2409 {
2410     fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
2411     fst2 = float32_sub(fst2, float32_one, &env->active_fpu.fp_status);
2412     fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32,
2413                                        &env->active_fpu.fp_status));
2414     update_fcr31(env, GETPC());
2415     return fst2;
2416 }
2417 
2418 uint64_t helper_float_rsqrt2_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2)
2419 {
2420     uint32_t fst0 = fdt0 & 0XFFFFFFFF;
2421     uint32_t fsth0 = fdt0 >> 32;
2422     uint32_t fst2 = fdt2 & 0XFFFFFFFF;
2423     uint32_t fsth2 = fdt2 >> 32;
2424 
2425     fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
2426     fsth2 = float32_mul(fsth0, fsth2, &env->active_fpu.fp_status);
2427     fst2 = float32_sub(fst2, float32_one, &env->active_fpu.fp_status);
2428     fsth2 = float32_sub(fsth2, float32_one, &env->active_fpu.fp_status);
2429     fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32,
2430                                        &env->active_fpu.fp_status));
2431     fsth2 = float32_chs(float32_div(fsth2, FLOAT_TWO32,
2432                                        &env->active_fpu.fp_status));
2433     update_fcr31(env, GETPC());
2434     return ((uint64_t)fsth2 << 32) | fst2;
2435 }
2436 
2437 uint64_t helper_float_addr_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt1)
2438 {
2439     uint32_t fst0 = fdt0 & 0XFFFFFFFF;
2440     uint32_t fsth0 = fdt0 >> 32;
2441     uint32_t fst1 = fdt1 & 0XFFFFFFFF;
2442     uint32_t fsth1 = fdt1 >> 32;
2443     uint32_t fst2;
2444     uint32_t fsth2;
2445 
2446     fst2 = float32_add(fst0, fsth0, &env->active_fpu.fp_status);
2447     fsth2 = float32_add(fst1, fsth1, &env->active_fpu.fp_status);
2448     update_fcr31(env, GETPC());
2449     return ((uint64_t)fsth2 << 32) | fst2;
2450 }
2451 
2452 uint64_t helper_float_mulr_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt1)
2453 {
2454     uint32_t fst0 = fdt0 & 0XFFFFFFFF;
2455     uint32_t fsth0 = fdt0 >> 32;
2456     uint32_t fst1 = fdt1 & 0XFFFFFFFF;
2457     uint32_t fsth1 = fdt1 >> 32;
2458     uint32_t fst2;
2459     uint32_t fsth2;
2460 
2461     fst2 = float32_mul(fst0, fsth0, &env->active_fpu.fp_status);
2462     fsth2 = float32_mul(fst1, fsth1, &env->active_fpu.fp_status);
2463     update_fcr31(env, GETPC());
2464     return ((uint64_t)fsth2 << 32) | fst2;
2465 }
2466 
2467 #define FLOAT_MINMAX(name, bits, minmaxfunc)                            \
2468 uint ## bits ## _t helper_float_ ## name(CPUMIPSState *env,             \
2469                                          uint ## bits ## _t fs,         \
2470                                          uint ## bits ## _t ft)         \
2471 {                                                                       \
2472     uint ## bits ## _t fdret;                                           \
2473                                                                         \
2474     fdret = float ## bits ## _ ## minmaxfunc(fs, ft,                    \
2475                                            &env->active_fpu.fp_status); \
2476     update_fcr31(env, GETPC());                                         \
2477     return fdret;                                                       \
2478 }
2479 
2480 FLOAT_MINMAX(max_s, 32, maxnum)
2481 FLOAT_MINMAX(max_d, 64, maxnum)
2482 FLOAT_MINMAX(maxa_s, 32, maxnummag)
2483 FLOAT_MINMAX(maxa_d, 64, maxnummag)
2484 
2485 FLOAT_MINMAX(min_s, 32, minnum)
2486 FLOAT_MINMAX(min_d, 64, minnum)
2487 FLOAT_MINMAX(mina_s, 32, minnummag)
2488 FLOAT_MINMAX(mina_d, 64, minnummag)
2489 #undef FLOAT_MINMAX
2490 
2491 /* ternary operations */
2492 #define UNFUSED_FMA(prefix, a, b, c, flags)                          \
2493 {                                                                    \
2494     a = prefix##_mul(a, b, &env->active_fpu.fp_status);              \
2495     if ((flags) & float_muladd_negate_c) {                           \
2496         a = prefix##_sub(a, c, &env->active_fpu.fp_status);          \
2497     } else {                                                         \
2498         a = prefix##_add(a, c, &env->active_fpu.fp_status);          \
2499     }                                                                \
2500     if ((flags) & float_muladd_negate_result) {                      \
2501         a = prefix##_chs(a);                                         \
2502     }                                                                \
2503 }
2504 
2505 /* FMA based operations */
2506 #define FLOAT_FMA(name, type)                                        \
2507 uint64_t helper_float_ ## name ## _d(CPUMIPSState *env,              \
2508                                      uint64_t fdt0, uint64_t fdt1,   \
2509                                      uint64_t fdt2)                  \
2510 {                                                                    \
2511     UNFUSED_FMA(float64, fdt0, fdt1, fdt2, type);                    \
2512     update_fcr31(env, GETPC());                                      \
2513     return fdt0;                                                     \
2514 }                                                                    \
2515                                                                      \
2516 uint32_t helper_float_ ## name ## _s(CPUMIPSState *env,              \
2517                                      uint32_t fst0, uint32_t fst1,   \
2518                                      uint32_t fst2)                  \
2519 {                                                                    \
2520     UNFUSED_FMA(float32, fst0, fst1, fst2, type);                    \
2521     update_fcr31(env, GETPC());                                      \
2522     return fst0;                                                     \
2523 }                                                                    \
2524                                                                      \
2525 uint64_t helper_float_ ## name ## _ps(CPUMIPSState *env,             \
2526                                       uint64_t fdt0, uint64_t fdt1,  \
2527                                       uint64_t fdt2)                 \
2528 {                                                                    \
2529     uint32_t fst0 = fdt0 & 0XFFFFFFFF;                               \
2530     uint32_t fsth0 = fdt0 >> 32;                                     \
2531     uint32_t fst1 = fdt1 & 0XFFFFFFFF;                               \
2532     uint32_t fsth1 = fdt1 >> 32;                                     \
2533     uint32_t fst2 = fdt2 & 0XFFFFFFFF;                               \
2534     uint32_t fsth2 = fdt2 >> 32;                                     \
2535                                                                      \
2536     UNFUSED_FMA(float32, fst0, fst1, fst2, type);                    \
2537     UNFUSED_FMA(float32, fsth0, fsth1, fsth2, type);                 \
2538     update_fcr31(env, GETPC());                                      \
2539     return ((uint64_t)fsth0 << 32) | fst0;                           \
2540 }
2541 FLOAT_FMA(madd, 0)
2542 FLOAT_FMA(msub, float_muladd_negate_c)
2543 FLOAT_FMA(nmadd, float_muladd_negate_result)
2544 FLOAT_FMA(nmsub, float_muladd_negate_result | float_muladd_negate_c)
2545 #undef FLOAT_FMA
2546 
2547 #define FLOAT_FMADDSUB(name, bits, muladd_arg)                          \
2548 uint ## bits ## _t helper_float_ ## name(CPUMIPSState *env,             \
2549                                          uint ## bits ## _t fs,         \
2550                                          uint ## bits ## _t ft,         \
2551                                          uint ## bits ## _t fd)         \
2552 {                                                                       \
2553     uint ## bits ## _t fdret;                                           \
2554                                                                         \
2555     fdret = float ## bits ## _muladd(fs, ft, fd, muladd_arg,            \
2556                                      &env->active_fpu.fp_status);       \
2557     update_fcr31(env, GETPC());                                         \
2558     return fdret;                                                       \
2559 }
2560 
2561 FLOAT_FMADDSUB(maddf_s, 32, 0)
2562 FLOAT_FMADDSUB(maddf_d, 64, 0)
2563 FLOAT_FMADDSUB(msubf_s, 32, float_muladd_negate_product)
2564 FLOAT_FMADDSUB(msubf_d, 64, float_muladd_negate_product)
2565 #undef FLOAT_FMADDSUB
2566 
2567 /* compare operations */
2568 #define FOP_COND_D(op, cond)                                   \
2569 void helper_cmp_d_ ## op(CPUMIPSState *env, uint64_t fdt0,     \
2570                          uint64_t fdt1, int cc)                \
2571 {                                                              \
2572     int c;                                                     \
2573     c = cond;                                                  \
2574     update_fcr31(env, GETPC());                                \
2575     if (c)                                                     \
2576         SET_FP_COND(cc, env->active_fpu);                      \
2577     else                                                       \
2578         CLEAR_FP_COND(cc, env->active_fpu);                    \
2579 }                                                              \
2580 void helper_cmpabs_d_ ## op(CPUMIPSState *env, uint64_t fdt0,  \
2581                             uint64_t fdt1, int cc)             \
2582 {                                                              \
2583     int c;                                                     \
2584     fdt0 = float64_abs(fdt0);                                  \
2585     fdt1 = float64_abs(fdt1);                                  \
2586     c = cond;                                                  \
2587     update_fcr31(env, GETPC());                                \
2588     if (c)                                                     \
2589         SET_FP_COND(cc, env->active_fpu);                      \
2590     else                                                       \
2591         CLEAR_FP_COND(cc, env->active_fpu);                    \
2592 }
2593 
2594 /*
2595  * NOTE: the comma operator will make "cond" to eval to false,
2596  * but float64_unordered_quiet() is still called.
2597  */
2598 FOP_COND_D(f,    (float64_unordered_quiet(fdt1, fdt0,
2599                                        &env->active_fpu.fp_status), 0))
2600 FOP_COND_D(un,   float64_unordered_quiet(fdt1, fdt0,
2601                                        &env->active_fpu.fp_status))
2602 FOP_COND_D(eq,   float64_eq_quiet(fdt0, fdt1,
2603                                        &env->active_fpu.fp_status))
2604 FOP_COND_D(ueq,  float64_unordered_quiet(fdt1, fdt0,
2605                                        &env->active_fpu.fp_status)
2606                  || float64_eq_quiet(fdt0, fdt1,
2607                                        &env->active_fpu.fp_status))
2608 FOP_COND_D(olt,  float64_lt_quiet(fdt0, fdt1,
2609                                        &env->active_fpu.fp_status))
2610 FOP_COND_D(ult,  float64_unordered_quiet(fdt1, fdt0,
2611                                        &env->active_fpu.fp_status)
2612                  || float64_lt_quiet(fdt0, fdt1,
2613                                        &env->active_fpu.fp_status))
2614 FOP_COND_D(ole,  float64_le_quiet(fdt0, fdt1,
2615                                        &env->active_fpu.fp_status))
2616 FOP_COND_D(ule,  float64_unordered_quiet(fdt1, fdt0,
2617                                        &env->active_fpu.fp_status)
2618                  || float64_le_quiet(fdt0, fdt1,
2619                                        &env->active_fpu.fp_status))
2620 /*
2621  * NOTE: the comma operator will make "cond" to eval to false,
2622  * but float64_unordered() is still called.
2623  */
2624 FOP_COND_D(sf,   (float64_unordered(fdt1, fdt0,
2625                                        &env->active_fpu.fp_status), 0))
2626 FOP_COND_D(ngle, float64_unordered(fdt1, fdt0,
2627                                        &env->active_fpu.fp_status))
2628 FOP_COND_D(seq,  float64_eq(fdt0, fdt1,
2629                                        &env->active_fpu.fp_status))
2630 FOP_COND_D(ngl,  float64_unordered(fdt1, fdt0,
2631                                        &env->active_fpu.fp_status)
2632                  || float64_eq(fdt0, fdt1,
2633                                        &env->active_fpu.fp_status))
2634 FOP_COND_D(lt,   float64_lt(fdt0, fdt1,
2635                                        &env->active_fpu.fp_status))
2636 FOP_COND_D(nge,  float64_unordered(fdt1, fdt0,
2637                                        &env->active_fpu.fp_status)
2638                  || float64_lt(fdt0, fdt1,
2639                                        &env->active_fpu.fp_status))
2640 FOP_COND_D(le,   float64_le(fdt0, fdt1,
2641                                        &env->active_fpu.fp_status))
2642 FOP_COND_D(ngt,  float64_unordered(fdt1, fdt0,
2643                                        &env->active_fpu.fp_status)
2644                  || float64_le(fdt0, fdt1,
2645                                        &env->active_fpu.fp_status))
2646 
2647 #define FOP_COND_S(op, cond)                                   \
2648 void helper_cmp_s_ ## op(CPUMIPSState *env, uint32_t fst0,     \
2649                          uint32_t fst1, int cc)                \
2650 {                                                              \
2651     int c;                                                     \
2652     c = cond;                                                  \
2653     update_fcr31(env, GETPC());                                \
2654     if (c)                                                     \
2655         SET_FP_COND(cc, env->active_fpu);                      \
2656     else                                                       \
2657         CLEAR_FP_COND(cc, env->active_fpu);                    \
2658 }                                                              \
2659 void helper_cmpabs_s_ ## op(CPUMIPSState *env, uint32_t fst0,  \
2660                             uint32_t fst1, int cc)             \
2661 {                                                              \
2662     int c;                                                     \
2663     fst0 = float32_abs(fst0);                                  \
2664     fst1 = float32_abs(fst1);                                  \
2665     c = cond;                                                  \
2666     update_fcr31(env, GETPC());                                \
2667     if (c)                                                     \
2668         SET_FP_COND(cc, env->active_fpu);                      \
2669     else                                                       \
2670         CLEAR_FP_COND(cc, env->active_fpu);                    \
2671 }
2672 
2673 /*
2674  * NOTE: the comma operator will make "cond" to eval to false,
2675  * but float32_unordered_quiet() is still called.
2676  */
2677 FOP_COND_S(f,    (float32_unordered_quiet(fst1, fst0,
2678                                        &env->active_fpu.fp_status), 0))
2679 FOP_COND_S(un,   float32_unordered_quiet(fst1, fst0,
2680                                        &env->active_fpu.fp_status))
2681 FOP_COND_S(eq,   float32_eq_quiet(fst0, fst1,
2682                                        &env->active_fpu.fp_status))
2683 FOP_COND_S(ueq,  float32_unordered_quiet(fst1, fst0,
2684                                        &env->active_fpu.fp_status)
2685                  || float32_eq_quiet(fst0, fst1,
2686                                        &env->active_fpu.fp_status))
2687 FOP_COND_S(olt,  float32_lt_quiet(fst0, fst1,
2688                                        &env->active_fpu.fp_status))
2689 FOP_COND_S(ult,  float32_unordered_quiet(fst1, fst0,
2690                                        &env->active_fpu.fp_status)
2691                  || float32_lt_quiet(fst0, fst1,
2692                                        &env->active_fpu.fp_status))
2693 FOP_COND_S(ole,  float32_le_quiet(fst0, fst1,
2694                                        &env->active_fpu.fp_status))
2695 FOP_COND_S(ule,  float32_unordered_quiet(fst1, fst0,
2696                                        &env->active_fpu.fp_status)
2697                  || float32_le_quiet(fst0, fst1,
2698                                        &env->active_fpu.fp_status))
2699 /*
2700  * NOTE: the comma operator will make "cond" to eval to false,
2701  * but float32_unordered() is still called.
2702  */
2703 FOP_COND_S(sf,   (float32_unordered(fst1, fst0,
2704                                        &env->active_fpu.fp_status), 0))
2705 FOP_COND_S(ngle, float32_unordered(fst1, fst0,
2706                                        &env->active_fpu.fp_status))
2707 FOP_COND_S(seq,  float32_eq(fst0, fst1,
2708                                        &env->active_fpu.fp_status))
2709 FOP_COND_S(ngl,  float32_unordered(fst1, fst0,
2710                                        &env->active_fpu.fp_status)
2711                  || float32_eq(fst0, fst1,
2712                                        &env->active_fpu.fp_status))
2713 FOP_COND_S(lt,   float32_lt(fst0, fst1,
2714                                        &env->active_fpu.fp_status))
2715 FOP_COND_S(nge,  float32_unordered(fst1, fst0,
2716                                        &env->active_fpu.fp_status)
2717                  || float32_lt(fst0, fst1,
2718                                        &env->active_fpu.fp_status))
2719 FOP_COND_S(le,   float32_le(fst0, fst1,
2720                                        &env->active_fpu.fp_status))
2721 FOP_COND_S(ngt,  float32_unordered(fst1, fst0,
2722                                        &env->active_fpu.fp_status)
2723                  || float32_le(fst0, fst1,
2724                                        &env->active_fpu.fp_status))
2725 
2726 #define FOP_COND_PS(op, condl, condh)                           \
2727 void helper_cmp_ps_ ## op(CPUMIPSState *env, uint64_t fdt0,     \
2728                           uint64_t fdt1, int cc)                \
2729 {                                                               \
2730     uint32_t fst0, fsth0, fst1, fsth1;                          \
2731     int ch, cl;                                                 \
2732     fst0 = fdt0 & 0XFFFFFFFF;                                   \
2733     fsth0 = fdt0 >> 32;                                         \
2734     fst1 = fdt1 & 0XFFFFFFFF;                                   \
2735     fsth1 = fdt1 >> 32;                                         \
2736     cl = condl;                                                 \
2737     ch = condh;                                                 \
2738     update_fcr31(env, GETPC());                                 \
2739     if (cl)                                                     \
2740         SET_FP_COND(cc, env->active_fpu);                       \
2741     else                                                        \
2742         CLEAR_FP_COND(cc, env->active_fpu);                     \
2743     if (ch)                                                     \
2744         SET_FP_COND(cc + 1, env->active_fpu);                   \
2745     else                                                        \
2746         CLEAR_FP_COND(cc + 1, env->active_fpu);                 \
2747 }                                                               \
2748 void helper_cmpabs_ps_ ## op(CPUMIPSState *env, uint64_t fdt0,  \
2749                              uint64_t fdt1, int cc)             \
2750 {                                                               \
2751     uint32_t fst0, fsth0, fst1, fsth1;                          \
2752     int ch, cl;                                                 \
2753     fst0 = float32_abs(fdt0 & 0XFFFFFFFF);                      \
2754     fsth0 = float32_abs(fdt0 >> 32);                            \
2755     fst1 = float32_abs(fdt1 & 0XFFFFFFFF);                      \
2756     fsth1 = float32_abs(fdt1 >> 32);                            \
2757     cl = condl;                                                 \
2758     ch = condh;                                                 \
2759     update_fcr31(env, GETPC());                                 \
2760     if (cl)                                                     \
2761         SET_FP_COND(cc, env->active_fpu);                       \
2762     else                                                        \
2763         CLEAR_FP_COND(cc, env->active_fpu);                     \
2764     if (ch)                                                     \
2765         SET_FP_COND(cc + 1, env->active_fpu);                   \
2766     else                                                        \
2767         CLEAR_FP_COND(cc + 1, env->active_fpu);                 \
2768 }
2769 
2770 /*
2771  * NOTE: the comma operator will make "cond" to eval to false,
2772  * but float32_unordered_quiet() is still called.
2773  */
2774 FOP_COND_PS(f,    (float32_unordered_quiet(fst1, fst0,
2775                                        &env->active_fpu.fp_status), 0),
2776                   (float32_unordered_quiet(fsth1, fsth0,
2777                                        &env->active_fpu.fp_status), 0))
2778 FOP_COND_PS(un,   float32_unordered_quiet(fst1, fst0,
2779                                        &env->active_fpu.fp_status),
2780                   float32_unordered_quiet(fsth1, fsth0,
2781                                        &env->active_fpu.fp_status))
2782 FOP_COND_PS(eq,   float32_eq_quiet(fst0, fst1,
2783                                        &env->active_fpu.fp_status),
2784                   float32_eq_quiet(fsth0, fsth1,
2785                                        &env->active_fpu.fp_status))
2786 FOP_COND_PS(ueq,  float32_unordered_quiet(fst1, fst0,
2787                                        &env->active_fpu.fp_status)
2788                   || float32_eq_quiet(fst0, fst1,
2789                                        &env->active_fpu.fp_status),
2790                   float32_unordered_quiet(fsth1, fsth0,
2791                                        &env->active_fpu.fp_status)
2792                   || float32_eq_quiet(fsth0, fsth1,
2793                                        &env->active_fpu.fp_status))
2794 FOP_COND_PS(olt,  float32_lt_quiet(fst0, fst1,
2795                                        &env->active_fpu.fp_status),
2796                   float32_lt_quiet(fsth0, fsth1,
2797                                        &env->active_fpu.fp_status))
2798 FOP_COND_PS(ult,  float32_unordered_quiet(fst1, fst0,
2799                                        &env->active_fpu.fp_status)
2800                   || float32_lt_quiet(fst0, fst1,
2801                                        &env->active_fpu.fp_status),
2802                   float32_unordered_quiet(fsth1, fsth0,
2803                                        &env->active_fpu.fp_status)
2804                   || float32_lt_quiet(fsth0, fsth1,
2805                                        &env->active_fpu.fp_status))
2806 FOP_COND_PS(ole,  float32_le_quiet(fst0, fst1,
2807                                        &env->active_fpu.fp_status),
2808                   float32_le_quiet(fsth0, fsth1,
2809                                        &env->active_fpu.fp_status))
2810 FOP_COND_PS(ule,  float32_unordered_quiet(fst1, fst0,
2811                                        &env->active_fpu.fp_status)
2812                   || float32_le_quiet(fst0, fst1,
2813                                        &env->active_fpu.fp_status),
2814                   float32_unordered_quiet(fsth1, fsth0,
2815                                        &env->active_fpu.fp_status)
2816                   || float32_le_quiet(fsth0, fsth1,
2817                                        &env->active_fpu.fp_status))
2818 /*
2819  * NOTE: the comma operator will make "cond" to eval to false,
2820  * but float32_unordered() is still called.
2821  */
2822 FOP_COND_PS(sf,   (float32_unordered(fst1, fst0,
2823                                        &env->active_fpu.fp_status), 0),
2824                   (float32_unordered(fsth1, fsth0,
2825                                        &env->active_fpu.fp_status), 0))
2826 FOP_COND_PS(ngle, float32_unordered(fst1, fst0,
2827                                        &env->active_fpu.fp_status),
2828                   float32_unordered(fsth1, fsth0,
2829                                        &env->active_fpu.fp_status))
2830 FOP_COND_PS(seq,  float32_eq(fst0, fst1,
2831                                        &env->active_fpu.fp_status),
2832                   float32_eq(fsth0, fsth1,
2833                                        &env->active_fpu.fp_status))
2834 FOP_COND_PS(ngl,  float32_unordered(fst1, fst0,
2835                                        &env->active_fpu.fp_status)
2836                   || float32_eq(fst0, fst1,
2837                                        &env->active_fpu.fp_status),
2838                   float32_unordered(fsth1, fsth0,
2839                                        &env->active_fpu.fp_status)
2840                   || float32_eq(fsth0, fsth1,
2841                                        &env->active_fpu.fp_status))
2842 FOP_COND_PS(lt,   float32_lt(fst0, fst1,
2843                                        &env->active_fpu.fp_status),
2844                   float32_lt(fsth0, fsth1,
2845                                        &env->active_fpu.fp_status))
2846 FOP_COND_PS(nge,  float32_unordered(fst1, fst0,
2847                                        &env->active_fpu.fp_status)
2848                   || float32_lt(fst0, fst1,
2849                                        &env->active_fpu.fp_status),
2850                   float32_unordered(fsth1, fsth0,
2851                                        &env->active_fpu.fp_status)
2852                   || float32_lt(fsth0, fsth1,
2853                                        &env->active_fpu.fp_status))
2854 FOP_COND_PS(le,   float32_le(fst0, fst1,
2855                                        &env->active_fpu.fp_status),
2856                   float32_le(fsth0, fsth1,
2857                                        &env->active_fpu.fp_status))
2858 FOP_COND_PS(ngt,  float32_unordered(fst1, fst0,
2859                                        &env->active_fpu.fp_status)
2860                   || float32_le(fst0, fst1,
2861                                        &env->active_fpu.fp_status),
2862                   float32_unordered(fsth1, fsth0,
2863                                        &env->active_fpu.fp_status)
2864                   || float32_le(fsth0, fsth1,
2865                                        &env->active_fpu.fp_status))
2866 
2867 /* R6 compare operations */
2868 #define FOP_CONDN_D(op, cond)                                       \
2869 uint64_t helper_r6_cmp_d_ ## op(CPUMIPSState *env, uint64_t fdt0,   \
2870                                 uint64_t fdt1)                      \
2871 {                                                                   \
2872     uint64_t c;                                                     \
2873     c = cond;                                                       \
2874     update_fcr31(env, GETPC());                                     \
2875     if (c) {                                                        \
2876         return -1;                                                  \
2877     } else {                                                        \
2878         return 0;                                                   \
2879     }                                                               \
2880 }
2881 
2882 /*
2883  * NOTE: the comma operator will make "cond" to eval to false,
2884  * but float64_unordered_quiet() is still called.
2885  */
2886 FOP_CONDN_D(af,  (float64_unordered_quiet(fdt1, fdt0,
2887                                        &env->active_fpu.fp_status), 0))
2888 FOP_CONDN_D(un,  (float64_unordered_quiet(fdt1, fdt0,
2889                                        &env->active_fpu.fp_status)))
2890 FOP_CONDN_D(eq,  (float64_eq_quiet(fdt0, fdt1,
2891                                        &env->active_fpu.fp_status)))
2892 FOP_CONDN_D(ueq, (float64_unordered_quiet(fdt1, fdt0,
2893                                        &env->active_fpu.fp_status)
2894                  || float64_eq_quiet(fdt0, fdt1,
2895                                        &env->active_fpu.fp_status)))
2896 FOP_CONDN_D(lt,  (float64_lt_quiet(fdt0, fdt1,
2897                                        &env->active_fpu.fp_status)))
2898 FOP_CONDN_D(ult, (float64_unordered_quiet(fdt1, fdt0,
2899                                        &env->active_fpu.fp_status)
2900                  || float64_lt_quiet(fdt0, fdt1,
2901                                        &env->active_fpu.fp_status)))
2902 FOP_CONDN_D(le,  (float64_le_quiet(fdt0, fdt1,
2903                                        &env->active_fpu.fp_status)))
2904 FOP_CONDN_D(ule, (float64_unordered_quiet(fdt1, fdt0,
2905                                        &env->active_fpu.fp_status)
2906                  || float64_le_quiet(fdt0, fdt1,
2907                                        &env->active_fpu.fp_status)))
2908 /*
2909  * NOTE: the comma operator will make "cond" to eval to false,
2910  * but float64_unordered() is still called.\
2911  */
2912 FOP_CONDN_D(saf,  (float64_unordered(fdt1, fdt0,
2913                                        &env->active_fpu.fp_status), 0))
2914 FOP_CONDN_D(sun,  (float64_unordered(fdt1, fdt0,
2915                                        &env->active_fpu.fp_status)))
2916 FOP_CONDN_D(seq,  (float64_eq(fdt0, fdt1,
2917                                        &env->active_fpu.fp_status)))
2918 FOP_CONDN_D(sueq, (float64_unordered(fdt1, fdt0,
2919                                        &env->active_fpu.fp_status)
2920                    || float64_eq(fdt0, fdt1,
2921                                        &env->active_fpu.fp_status)))
2922 FOP_CONDN_D(slt,  (float64_lt(fdt0, fdt1,
2923                                        &env->active_fpu.fp_status)))
2924 FOP_CONDN_D(sult, (float64_unordered(fdt1, fdt0,
2925                                        &env->active_fpu.fp_status)
2926                    || float64_lt(fdt0, fdt1,
2927                                        &env->active_fpu.fp_status)))
2928 FOP_CONDN_D(sle,  (float64_le(fdt0, fdt1,
2929                                        &env->active_fpu.fp_status)))
2930 FOP_CONDN_D(sule, (float64_unordered(fdt1, fdt0,
2931                                        &env->active_fpu.fp_status)
2932                    || float64_le(fdt0, fdt1,
2933                                        &env->active_fpu.fp_status)))
2934 FOP_CONDN_D(or,   (float64_le_quiet(fdt1, fdt0,
2935                                        &env->active_fpu.fp_status)
2936                    || float64_le_quiet(fdt0, fdt1,
2937                                        &env->active_fpu.fp_status)))
2938 FOP_CONDN_D(une,  (float64_unordered_quiet(fdt1, fdt0,
2939                                        &env->active_fpu.fp_status)
2940                    || float64_lt_quiet(fdt1, fdt0,
2941                                        &env->active_fpu.fp_status)
2942                    || float64_lt_quiet(fdt0, fdt1,
2943                                        &env->active_fpu.fp_status)))
2944 FOP_CONDN_D(ne,   (float64_lt_quiet(fdt1, fdt0,
2945                                        &env->active_fpu.fp_status)
2946                    || float64_lt_quiet(fdt0, fdt1,
2947                                        &env->active_fpu.fp_status)))
2948 FOP_CONDN_D(sor,  (float64_le(fdt1, fdt0,
2949                                        &env->active_fpu.fp_status)
2950                    || float64_le(fdt0, fdt1,
2951                                        &env->active_fpu.fp_status)))
2952 FOP_CONDN_D(sune, (float64_unordered(fdt1, fdt0,
2953                                        &env->active_fpu.fp_status)
2954                    || float64_lt(fdt1, fdt0,
2955                                        &env->active_fpu.fp_status)
2956                    || float64_lt(fdt0, fdt1,
2957                                        &env->active_fpu.fp_status)))
2958 FOP_CONDN_D(sne,  (float64_lt(fdt1, fdt0,
2959                                        &env->active_fpu.fp_status)
2960                    || float64_lt(fdt0, fdt1,
2961                                        &env->active_fpu.fp_status)))
2962 
2963 #define FOP_CONDN_S(op, cond)                                       \
2964 uint32_t helper_r6_cmp_s_ ## op(CPUMIPSState *env, uint32_t fst0,   \
2965                                 uint32_t fst1)                      \
2966 {                                                                   \
2967     uint64_t c;                                                     \
2968     c = cond;                                                       \
2969     update_fcr31(env, GETPC());                                     \
2970     if (c) {                                                        \
2971         return -1;                                                  \
2972     } else {                                                        \
2973         return 0;                                                   \
2974     }                                                               \
2975 }
2976 
2977 /*
2978  * NOTE: the comma operator will make "cond" to eval to false,
2979  * but float32_unordered_quiet() is still called.
2980  */
2981 FOP_CONDN_S(af,   (float32_unordered_quiet(fst1, fst0,
2982                                        &env->active_fpu.fp_status), 0))
2983 FOP_CONDN_S(un,   (float32_unordered_quiet(fst1, fst0,
2984                                        &env->active_fpu.fp_status)))
2985 FOP_CONDN_S(eq,   (float32_eq_quiet(fst0, fst1,
2986                                        &env->active_fpu.fp_status)))
2987 FOP_CONDN_S(ueq,  (float32_unordered_quiet(fst1, fst0,
2988                                        &env->active_fpu.fp_status)
2989                    || float32_eq_quiet(fst0, fst1,
2990                                        &env->active_fpu.fp_status)))
2991 FOP_CONDN_S(lt,   (float32_lt_quiet(fst0, fst1,
2992                                        &env->active_fpu.fp_status)))
2993 FOP_CONDN_S(ult,  (float32_unordered_quiet(fst1, fst0,
2994                                        &env->active_fpu.fp_status)
2995                    || float32_lt_quiet(fst0, fst1,
2996                                        &env->active_fpu.fp_status)))
2997 FOP_CONDN_S(le,   (float32_le_quiet(fst0, fst1,
2998                                        &env->active_fpu.fp_status)))
2999 FOP_CONDN_S(ule,  (float32_unordered_quiet(fst1, fst0,
3000                                        &env->active_fpu.fp_status)
3001                    || float32_le_quiet(fst0, fst1,
3002                                        &env->active_fpu.fp_status)))
3003 /*
3004  * NOTE: the comma operator will make "cond" to eval to false,
3005  * but float32_unordered() is still called.
3006  */
3007 FOP_CONDN_S(saf,  (float32_unordered(fst1, fst0,
3008                                        &env->active_fpu.fp_status), 0))
3009 FOP_CONDN_S(sun,  (float32_unordered(fst1, fst0,
3010                                        &env->active_fpu.fp_status)))
3011 FOP_CONDN_S(seq,  (float32_eq(fst0, fst1,
3012                                        &env->active_fpu.fp_status)))
3013 FOP_CONDN_S(sueq, (float32_unordered(fst1, fst0,
3014                                        &env->active_fpu.fp_status)
3015                    || float32_eq(fst0, fst1,
3016                                        &env->active_fpu.fp_status)))
3017 FOP_CONDN_S(slt,  (float32_lt(fst0, fst1,
3018                                        &env->active_fpu.fp_status)))
3019 FOP_CONDN_S(sult, (float32_unordered(fst1, fst0,
3020                                        &env->active_fpu.fp_status)
3021                    || float32_lt(fst0, fst1,
3022                                        &env->active_fpu.fp_status)))
3023 FOP_CONDN_S(sle,  (float32_le(fst0, fst1,
3024                                        &env->active_fpu.fp_status)))
3025 FOP_CONDN_S(sule, (float32_unordered(fst1, fst0,
3026                                        &env->active_fpu.fp_status)
3027                    || float32_le(fst0, fst1,
3028                                        &env->active_fpu.fp_status)))
3029 FOP_CONDN_S(or,   (float32_le_quiet(fst1, fst0,
3030                                        &env->active_fpu.fp_status)
3031                    || float32_le_quiet(fst0, fst1,
3032                                        &env->active_fpu.fp_status)))
3033 FOP_CONDN_S(une,  (float32_unordered_quiet(fst1, fst0,
3034                                        &env->active_fpu.fp_status)
3035                    || float32_lt_quiet(fst1, fst0,
3036                                        &env->active_fpu.fp_status)
3037                    || float32_lt_quiet(fst0, fst1,
3038                                        &env->active_fpu.fp_status)))
3039 FOP_CONDN_S(ne,   (float32_lt_quiet(fst1, fst0,
3040                                        &env->active_fpu.fp_status)
3041                    || float32_lt_quiet(fst0, fst1,
3042                                        &env->active_fpu.fp_status)))
3043 FOP_CONDN_S(sor,  (float32_le(fst1, fst0,
3044                                        &env->active_fpu.fp_status)
3045                    || float32_le(fst0, fst1,
3046                                        &env->active_fpu.fp_status)))
3047 FOP_CONDN_S(sune, (float32_unordered(fst1, fst0,
3048                                        &env->active_fpu.fp_status)
3049                    || float32_lt(fst1, fst0,
3050                                        &env->active_fpu.fp_status)
3051                    || float32_lt(fst0, fst1,
3052                                        &env->active_fpu.fp_status)))
3053 FOP_CONDN_S(sne,  (float32_lt(fst1, fst0,
3054                                        &env->active_fpu.fp_status)
3055                    || float32_lt(fst0, fst1,
3056                                        &env->active_fpu.fp_status)))
3057 
3058 /* MSA */
3059 /* Data format min and max values */
3060 #define DF_BITS(df) (1 << ((df) + 3))
3061 
3062 /* Element-by-element access macros */
3063 #define DF_ELEMENTS(df) (MSA_WRLEN / DF_BITS(df))
3064 
3065 #if !defined(CONFIG_USER_ONLY)
3066 #define MEMOP_IDX(DF)                                           \
3067         TCGMemOpIdx oi = make_memop_idx(MO_TE | DF | MO_UNALN,  \
3068                                         cpu_mmu_index(env, false));
3069 #else
3070 #define MEMOP_IDX(DF)
3071 #endif
3072 
3073 void helper_msa_ld_b(CPUMIPSState *env, uint32_t wd,
3074                      target_ulong addr)
3075 {
3076     wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3077     MEMOP_IDX(DF_BYTE)
3078 #if !defined(CONFIG_USER_ONLY)
3079 #if !defined(HOST_WORDS_BIGENDIAN)
3080     pwd->b[0]  = helper_ret_ldub_mmu(env, addr + (0  << DF_BYTE), oi, GETPC());
3081     pwd->b[1]  = helper_ret_ldub_mmu(env, addr + (1  << DF_BYTE), oi, GETPC());
3082     pwd->b[2]  = helper_ret_ldub_mmu(env, addr + (2  << DF_BYTE), oi, GETPC());
3083     pwd->b[3]  = helper_ret_ldub_mmu(env, addr + (3  << DF_BYTE), oi, GETPC());
3084     pwd->b[4]  = helper_ret_ldub_mmu(env, addr + (4  << DF_BYTE), oi, GETPC());
3085     pwd->b[5]  = helper_ret_ldub_mmu(env, addr + (5  << DF_BYTE), oi, GETPC());
3086     pwd->b[6]  = helper_ret_ldub_mmu(env, addr + (6  << DF_BYTE), oi, GETPC());
3087     pwd->b[7]  = helper_ret_ldub_mmu(env, addr + (7  << DF_BYTE), oi, GETPC());
3088     pwd->b[8]  = helper_ret_ldub_mmu(env, addr + (8  << DF_BYTE), oi, GETPC());
3089     pwd->b[9]  = helper_ret_ldub_mmu(env, addr + (9  << DF_BYTE), oi, GETPC());
3090     pwd->b[10] = helper_ret_ldub_mmu(env, addr + (10 << DF_BYTE), oi, GETPC());
3091     pwd->b[11] = helper_ret_ldub_mmu(env, addr + (11 << DF_BYTE), oi, GETPC());
3092     pwd->b[12] = helper_ret_ldub_mmu(env, addr + (12 << DF_BYTE), oi, GETPC());
3093     pwd->b[13] = helper_ret_ldub_mmu(env, addr + (13 << DF_BYTE), oi, GETPC());
3094     pwd->b[14] = helper_ret_ldub_mmu(env, addr + (14 << DF_BYTE), oi, GETPC());
3095     pwd->b[15] = helper_ret_ldub_mmu(env, addr + (15 << DF_BYTE), oi, GETPC());
3096 #else
3097     pwd->b[0]  = helper_ret_ldub_mmu(env, addr + (7  << DF_BYTE), oi, GETPC());
3098     pwd->b[1]  = helper_ret_ldub_mmu(env, addr + (6  << DF_BYTE), oi, GETPC());
3099     pwd->b[2]  = helper_ret_ldub_mmu(env, addr + (5  << DF_BYTE), oi, GETPC());
3100     pwd->b[3]  = helper_ret_ldub_mmu(env, addr + (4  << DF_BYTE), oi, GETPC());
3101     pwd->b[4]  = helper_ret_ldub_mmu(env, addr + (3  << DF_BYTE), oi, GETPC());
3102     pwd->b[5]  = helper_ret_ldub_mmu(env, addr + (2  << DF_BYTE), oi, GETPC());
3103     pwd->b[6]  = helper_ret_ldub_mmu(env, addr + (1  << DF_BYTE), oi, GETPC());
3104     pwd->b[7]  = helper_ret_ldub_mmu(env, addr + (0  << DF_BYTE), oi, GETPC());
3105     pwd->b[8]  = helper_ret_ldub_mmu(env, addr + (15 << DF_BYTE), oi, GETPC());
3106     pwd->b[9]  = helper_ret_ldub_mmu(env, addr + (14 << DF_BYTE), oi, GETPC());
3107     pwd->b[10] = helper_ret_ldub_mmu(env, addr + (13 << DF_BYTE), oi, GETPC());
3108     pwd->b[11] = helper_ret_ldub_mmu(env, addr + (12 << DF_BYTE), oi, GETPC());
3109     pwd->b[12] = helper_ret_ldub_mmu(env, addr + (11 << DF_BYTE), oi, GETPC());
3110     pwd->b[13] = helper_ret_ldub_mmu(env, addr + (10 << DF_BYTE), oi, GETPC());
3111     pwd->b[14] = helper_ret_ldub_mmu(env, addr + (9  << DF_BYTE), oi, GETPC());
3112     pwd->b[15] = helper_ret_ldub_mmu(env, addr + (8  << DF_BYTE), oi, GETPC());
3113 #endif
3114 #else
3115 #if !defined(HOST_WORDS_BIGENDIAN)
3116     pwd->b[0]  = cpu_ldub_data(env, addr + (0  << DF_BYTE));
3117     pwd->b[1]  = cpu_ldub_data(env, addr + (1  << DF_BYTE));
3118     pwd->b[2]  = cpu_ldub_data(env, addr + (2  << DF_BYTE));
3119     pwd->b[3]  = cpu_ldub_data(env, addr + (3  << DF_BYTE));
3120     pwd->b[4]  = cpu_ldub_data(env, addr + (4  << DF_BYTE));
3121     pwd->b[5]  = cpu_ldub_data(env, addr + (5  << DF_BYTE));
3122     pwd->b[6]  = cpu_ldub_data(env, addr + (6  << DF_BYTE));
3123     pwd->b[7]  = cpu_ldub_data(env, addr + (7  << DF_BYTE));
3124     pwd->b[8]  = cpu_ldub_data(env, addr + (8  << DF_BYTE));
3125     pwd->b[9]  = cpu_ldub_data(env, addr + (9  << DF_BYTE));
3126     pwd->b[10] = cpu_ldub_data(env, addr + (10 << DF_BYTE));
3127     pwd->b[11] = cpu_ldub_data(env, addr + (11 << DF_BYTE));
3128     pwd->b[12] = cpu_ldub_data(env, addr + (12 << DF_BYTE));
3129     pwd->b[13] = cpu_ldub_data(env, addr + (13 << DF_BYTE));
3130     pwd->b[14] = cpu_ldub_data(env, addr + (14 << DF_BYTE));
3131     pwd->b[15] = cpu_ldub_data(env, addr + (15 << DF_BYTE));
3132 #else
3133     pwd->b[0]  = cpu_ldub_data(env, addr + (7  << DF_BYTE));
3134     pwd->b[1]  = cpu_ldub_data(env, addr + (6  << DF_BYTE));
3135     pwd->b[2]  = cpu_ldub_data(env, addr + (5  << DF_BYTE));
3136     pwd->b[3]  = cpu_ldub_data(env, addr + (4  << DF_BYTE));
3137     pwd->b[4]  = cpu_ldub_data(env, addr + (3  << DF_BYTE));
3138     pwd->b[5]  = cpu_ldub_data(env, addr + (2  << DF_BYTE));
3139     pwd->b[6]  = cpu_ldub_data(env, addr + (1  << DF_BYTE));
3140     pwd->b[7]  = cpu_ldub_data(env, addr + (0  << DF_BYTE));
3141     pwd->b[8]  = cpu_ldub_data(env, addr + (15 << DF_BYTE));
3142     pwd->b[9]  = cpu_ldub_data(env, addr + (14 << DF_BYTE));
3143     pwd->b[10] = cpu_ldub_data(env, addr + (13 << DF_BYTE));
3144     pwd->b[11] = cpu_ldub_data(env, addr + (12 << DF_BYTE));
3145     pwd->b[12] = cpu_ldub_data(env, addr + (11 << DF_BYTE));
3146     pwd->b[13] = cpu_ldub_data(env, addr + (10 << DF_BYTE));
3147     pwd->b[14] = cpu_ldub_data(env, addr + (9 << DF_BYTE));
3148     pwd->b[15] = cpu_ldub_data(env, addr + (8 << DF_BYTE));
3149 #endif
3150 #endif
3151 }
3152 
3153 void helper_msa_ld_h(CPUMIPSState *env, uint32_t wd,
3154                      target_ulong addr)
3155 {
3156     wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3157     MEMOP_IDX(DF_HALF)
3158 #if !defined(CONFIG_USER_ONLY)
3159 #if !defined(HOST_WORDS_BIGENDIAN)
3160     pwd->h[0] = helper_ret_lduw_mmu(env, addr + (0 << DF_HALF), oi, GETPC());
3161     pwd->h[1] = helper_ret_lduw_mmu(env, addr + (1 << DF_HALF), oi, GETPC());
3162     pwd->h[2] = helper_ret_lduw_mmu(env, addr + (2 << DF_HALF), oi, GETPC());
3163     pwd->h[3] = helper_ret_lduw_mmu(env, addr + (3 << DF_HALF), oi, GETPC());
3164     pwd->h[4] = helper_ret_lduw_mmu(env, addr + (4 << DF_HALF), oi, GETPC());
3165     pwd->h[5] = helper_ret_lduw_mmu(env, addr + (5 << DF_HALF), oi, GETPC());
3166     pwd->h[6] = helper_ret_lduw_mmu(env, addr + (6 << DF_HALF), oi, GETPC());
3167     pwd->h[7] = helper_ret_lduw_mmu(env, addr + (7 << DF_HALF), oi, GETPC());
3168 #else
3169     pwd->h[0] = helper_ret_lduw_mmu(env, addr + (3 << DF_HALF), oi, GETPC());
3170     pwd->h[1] = helper_ret_lduw_mmu(env, addr + (2 << DF_HALF), oi, GETPC());
3171     pwd->h[2] = helper_ret_lduw_mmu(env, addr + (1 << DF_HALF), oi, GETPC());
3172     pwd->h[3] = helper_ret_lduw_mmu(env, addr + (0 << DF_HALF), oi, GETPC());
3173     pwd->h[4] = helper_ret_lduw_mmu(env, addr + (7 << DF_HALF), oi, GETPC());
3174     pwd->h[5] = helper_ret_lduw_mmu(env, addr + (6 << DF_HALF), oi, GETPC());
3175     pwd->h[6] = helper_ret_lduw_mmu(env, addr + (5 << DF_HALF), oi, GETPC());
3176     pwd->h[7] = helper_ret_lduw_mmu(env, addr + (4 << DF_HALF), oi, GETPC());
3177 #endif
3178 #else
3179 #if !defined(HOST_WORDS_BIGENDIAN)
3180     pwd->h[0] = cpu_lduw_data(env, addr + (0 << DF_HALF));
3181     pwd->h[1] = cpu_lduw_data(env, addr + (1 << DF_HALF));
3182     pwd->h[2] = cpu_lduw_data(env, addr + (2 << DF_HALF));
3183     pwd->h[3] = cpu_lduw_data(env, addr + (3 << DF_HALF));
3184     pwd->h[4] = cpu_lduw_data(env, addr + (4 << DF_HALF));
3185     pwd->h[5] = cpu_lduw_data(env, addr + (5 << DF_HALF));
3186     pwd->h[6] = cpu_lduw_data(env, addr + (6 << DF_HALF));
3187     pwd->h[7] = cpu_lduw_data(env, addr + (7 << DF_HALF));
3188 #else
3189     pwd->h[0] = cpu_lduw_data(env, addr + (3 << DF_HALF));
3190     pwd->h[1] = cpu_lduw_data(env, addr + (2 << DF_HALF));
3191     pwd->h[2] = cpu_lduw_data(env, addr + (1 << DF_HALF));
3192     pwd->h[3] = cpu_lduw_data(env, addr + (0 << DF_HALF));
3193     pwd->h[4] = cpu_lduw_data(env, addr + (7 << DF_HALF));
3194     pwd->h[5] = cpu_lduw_data(env, addr + (6 << DF_HALF));
3195     pwd->h[6] = cpu_lduw_data(env, addr + (5 << DF_HALF));
3196     pwd->h[7] = cpu_lduw_data(env, addr + (4 << DF_HALF));
3197 #endif
3198 #endif
3199 }
3200 
3201 void helper_msa_ld_w(CPUMIPSState *env, uint32_t wd,
3202                      target_ulong addr)
3203 {
3204     wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3205     MEMOP_IDX(DF_WORD)
3206 #if !defined(CONFIG_USER_ONLY)
3207 #if !defined(HOST_WORDS_BIGENDIAN)
3208     pwd->w[0] = helper_ret_ldul_mmu(env, addr + (0 << DF_WORD), oi, GETPC());
3209     pwd->w[1] = helper_ret_ldul_mmu(env, addr + (1 << DF_WORD), oi, GETPC());
3210     pwd->w[2] = helper_ret_ldul_mmu(env, addr + (2 << DF_WORD), oi, GETPC());
3211     pwd->w[3] = helper_ret_ldul_mmu(env, addr + (3 << DF_WORD), oi, GETPC());
3212 #else
3213     pwd->w[0] = helper_ret_ldul_mmu(env, addr + (1 << DF_WORD), oi, GETPC());
3214     pwd->w[1] = helper_ret_ldul_mmu(env, addr + (0 << DF_WORD), oi, GETPC());
3215     pwd->w[2] = helper_ret_ldul_mmu(env, addr + (3 << DF_WORD), oi, GETPC());
3216     pwd->w[3] = helper_ret_ldul_mmu(env, addr + (2 << DF_WORD), oi, GETPC());
3217 #endif
3218 #else
3219 #if !defined(HOST_WORDS_BIGENDIAN)
3220     pwd->w[0] = cpu_ldl_data(env, addr + (0 << DF_WORD));
3221     pwd->w[1] = cpu_ldl_data(env, addr + (1 << DF_WORD));
3222     pwd->w[2] = cpu_ldl_data(env, addr + (2 << DF_WORD));
3223     pwd->w[3] = cpu_ldl_data(env, addr + (3 << DF_WORD));
3224 #else
3225     pwd->w[0] = cpu_ldl_data(env, addr + (1 << DF_WORD));
3226     pwd->w[1] = cpu_ldl_data(env, addr + (0 << DF_WORD));
3227     pwd->w[2] = cpu_ldl_data(env, addr + (3 << DF_WORD));
3228     pwd->w[3] = cpu_ldl_data(env, addr + (2 << DF_WORD));
3229 #endif
3230 #endif
3231 }
3232 
3233 void helper_msa_ld_d(CPUMIPSState *env, uint32_t wd,
3234                      target_ulong addr)
3235 {
3236     wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3237     MEMOP_IDX(DF_DOUBLE)
3238 #if !defined(CONFIG_USER_ONLY)
3239     pwd->d[0] = helper_ret_ldq_mmu(env, addr + (0 << DF_DOUBLE), oi, GETPC());
3240     pwd->d[1] = helper_ret_ldq_mmu(env, addr + (1 << DF_DOUBLE), oi, GETPC());
3241 #else
3242     pwd->d[0] = cpu_ldq_data(env, addr + (0 << DF_DOUBLE));
3243     pwd->d[1] = cpu_ldq_data(env, addr + (1 << DF_DOUBLE));
3244 #endif
3245 }
3246 
3247 #define MSA_PAGESPAN(x) \
3248         ((((x) & ~TARGET_PAGE_MASK) + MSA_WRLEN / 8 - 1) >= TARGET_PAGE_SIZE)
3249 
3250 static inline void ensure_writable_pages(CPUMIPSState *env,
3251                                          target_ulong addr,
3252                                          int mmu_idx,
3253                                          uintptr_t retaddr)
3254 {
3255     /* FIXME: Probe the actual accesses (pass and use a size) */
3256     if (unlikely(MSA_PAGESPAN(addr))) {
3257         /* first page */
3258         probe_write(env, addr, 0, mmu_idx, retaddr);
3259         /* second page */
3260         addr = (addr & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
3261         probe_write(env, addr, 0, mmu_idx, retaddr);
3262     }
3263 }
3264 
3265 void helper_msa_st_b(CPUMIPSState *env, uint32_t wd,
3266                      target_ulong addr)
3267 {
3268     wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3269     int mmu_idx = cpu_mmu_index(env, false);
3270 
3271     MEMOP_IDX(DF_BYTE)
3272     ensure_writable_pages(env, addr, mmu_idx, GETPC());
3273 #if !defined(CONFIG_USER_ONLY)
3274 #if !defined(HOST_WORDS_BIGENDIAN)
3275     helper_ret_stb_mmu(env, addr + (0  << DF_BYTE), pwd->b[0],  oi, GETPC());
3276     helper_ret_stb_mmu(env, addr + (1  << DF_BYTE), pwd->b[1],  oi, GETPC());
3277     helper_ret_stb_mmu(env, addr + (2  << DF_BYTE), pwd->b[2],  oi, GETPC());
3278     helper_ret_stb_mmu(env, addr + (3  << DF_BYTE), pwd->b[3],  oi, GETPC());
3279     helper_ret_stb_mmu(env, addr + (4  << DF_BYTE), pwd->b[4],  oi, GETPC());
3280     helper_ret_stb_mmu(env, addr + (5  << DF_BYTE), pwd->b[5],  oi, GETPC());
3281     helper_ret_stb_mmu(env, addr + (6  << DF_BYTE), pwd->b[6],  oi, GETPC());
3282     helper_ret_stb_mmu(env, addr + (7  << DF_BYTE), pwd->b[7],  oi, GETPC());
3283     helper_ret_stb_mmu(env, addr + (8  << DF_BYTE), pwd->b[8],  oi, GETPC());
3284     helper_ret_stb_mmu(env, addr + (9  << DF_BYTE), pwd->b[9],  oi, GETPC());
3285     helper_ret_stb_mmu(env, addr + (10 << DF_BYTE), pwd->b[10], oi, GETPC());
3286     helper_ret_stb_mmu(env, addr + (11 << DF_BYTE), pwd->b[11], oi, GETPC());
3287     helper_ret_stb_mmu(env, addr + (12 << DF_BYTE), pwd->b[12], oi, GETPC());
3288     helper_ret_stb_mmu(env, addr + (13 << DF_BYTE), pwd->b[13], oi, GETPC());
3289     helper_ret_stb_mmu(env, addr + (14 << DF_BYTE), pwd->b[14], oi, GETPC());
3290     helper_ret_stb_mmu(env, addr + (15 << DF_BYTE), pwd->b[15], oi, GETPC());
3291 #else
3292     helper_ret_stb_mmu(env, addr + (7  << DF_BYTE), pwd->b[0],  oi, GETPC());
3293     helper_ret_stb_mmu(env, addr + (6  << DF_BYTE), pwd->b[1],  oi, GETPC());
3294     helper_ret_stb_mmu(env, addr + (5  << DF_BYTE), pwd->b[2],  oi, GETPC());
3295     helper_ret_stb_mmu(env, addr + (4  << DF_BYTE), pwd->b[3],  oi, GETPC());
3296     helper_ret_stb_mmu(env, addr + (3  << DF_BYTE), pwd->b[4],  oi, GETPC());
3297     helper_ret_stb_mmu(env, addr + (2  << DF_BYTE), pwd->b[5],  oi, GETPC());
3298     helper_ret_stb_mmu(env, addr + (1  << DF_BYTE), pwd->b[6],  oi, GETPC());
3299     helper_ret_stb_mmu(env, addr + (0  << DF_BYTE), pwd->b[7],  oi, GETPC());
3300     helper_ret_stb_mmu(env, addr + (15 << DF_BYTE), pwd->b[8],  oi, GETPC());
3301     helper_ret_stb_mmu(env, addr + (14 << DF_BYTE), pwd->b[9],  oi, GETPC());
3302     helper_ret_stb_mmu(env, addr + (13 << DF_BYTE), pwd->b[10], oi, GETPC());
3303     helper_ret_stb_mmu(env, addr + (12 << DF_BYTE), pwd->b[11], oi, GETPC());
3304     helper_ret_stb_mmu(env, addr + (11 << DF_BYTE), pwd->b[12], oi, GETPC());
3305     helper_ret_stb_mmu(env, addr + (10 << DF_BYTE), pwd->b[13], oi, GETPC());
3306     helper_ret_stb_mmu(env, addr + (9  << DF_BYTE), pwd->b[14], oi, GETPC());
3307     helper_ret_stb_mmu(env, addr + (8  << DF_BYTE), pwd->b[15], oi, GETPC());
3308 #endif
3309 #else
3310 #if !defined(HOST_WORDS_BIGENDIAN)
3311     cpu_stb_data(env, addr + (0  << DF_BYTE), pwd->b[0]);
3312     cpu_stb_data(env, addr + (1  << DF_BYTE), pwd->b[1]);
3313     cpu_stb_data(env, addr + (2  << DF_BYTE), pwd->b[2]);
3314     cpu_stb_data(env, addr + (3  << DF_BYTE), pwd->b[3]);
3315     cpu_stb_data(env, addr + (4  << DF_BYTE), pwd->b[4]);
3316     cpu_stb_data(env, addr + (5  << DF_BYTE), pwd->b[5]);
3317     cpu_stb_data(env, addr + (6  << DF_BYTE), pwd->b[6]);
3318     cpu_stb_data(env, addr + (7  << DF_BYTE), pwd->b[7]);
3319     cpu_stb_data(env, addr + (8  << DF_BYTE), pwd->b[8]);
3320     cpu_stb_data(env, addr + (9  << DF_BYTE), pwd->b[9]);
3321     cpu_stb_data(env, addr + (10 << DF_BYTE), pwd->b[10]);
3322     cpu_stb_data(env, addr + (11 << DF_BYTE), pwd->b[11]);
3323     cpu_stb_data(env, addr + (12 << DF_BYTE), pwd->b[12]);
3324     cpu_stb_data(env, addr + (13 << DF_BYTE), pwd->b[13]);
3325     cpu_stb_data(env, addr + (14 << DF_BYTE), pwd->b[14]);
3326     cpu_stb_data(env, addr + (15 << DF_BYTE), pwd->b[15]);
3327 #else
3328     cpu_stb_data(env, addr + (7  << DF_BYTE), pwd->b[0]);
3329     cpu_stb_data(env, addr + (6  << DF_BYTE), pwd->b[1]);
3330     cpu_stb_data(env, addr + (5  << DF_BYTE), pwd->b[2]);
3331     cpu_stb_data(env, addr + (4  << DF_BYTE), pwd->b[3]);
3332     cpu_stb_data(env, addr + (3  << DF_BYTE), pwd->b[4]);
3333     cpu_stb_data(env, addr + (2  << DF_BYTE), pwd->b[5]);
3334     cpu_stb_data(env, addr + (1  << DF_BYTE), pwd->b[6]);
3335     cpu_stb_data(env, addr + (0  << DF_BYTE), pwd->b[7]);
3336     cpu_stb_data(env, addr + (15 << DF_BYTE), pwd->b[8]);
3337     cpu_stb_data(env, addr + (14 << DF_BYTE), pwd->b[9]);
3338     cpu_stb_data(env, addr + (13 << DF_BYTE), pwd->b[10]);
3339     cpu_stb_data(env, addr + (12 << DF_BYTE), pwd->b[11]);
3340     cpu_stb_data(env, addr + (11 << DF_BYTE), pwd->b[12]);
3341     cpu_stb_data(env, addr + (10 << DF_BYTE), pwd->b[13]);
3342     cpu_stb_data(env, addr + (9  << DF_BYTE), pwd->b[14]);
3343     cpu_stb_data(env, addr + (8  << DF_BYTE), pwd->b[15]);
3344 #endif
3345 #endif
3346 }
3347 
3348 void helper_msa_st_h(CPUMIPSState *env, uint32_t wd,
3349                      target_ulong addr)
3350 {
3351     wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3352     int mmu_idx = cpu_mmu_index(env, false);
3353 
3354     MEMOP_IDX(DF_HALF)
3355     ensure_writable_pages(env, addr, mmu_idx, GETPC());
3356 #if !defined(CONFIG_USER_ONLY)
3357 #if !defined(HOST_WORDS_BIGENDIAN)
3358     helper_ret_stw_mmu(env, addr + (0 << DF_HALF), pwd->h[0], oi, GETPC());
3359     helper_ret_stw_mmu(env, addr + (1 << DF_HALF), pwd->h[1], oi, GETPC());
3360     helper_ret_stw_mmu(env, addr + (2 << DF_HALF), pwd->h[2], oi, GETPC());
3361     helper_ret_stw_mmu(env, addr + (3 << DF_HALF), pwd->h[3], oi, GETPC());
3362     helper_ret_stw_mmu(env, addr + (4 << DF_HALF), pwd->h[4], oi, GETPC());
3363     helper_ret_stw_mmu(env, addr + (5 << DF_HALF), pwd->h[5], oi, GETPC());
3364     helper_ret_stw_mmu(env, addr + (6 << DF_HALF), pwd->h[6], oi, GETPC());
3365     helper_ret_stw_mmu(env, addr + (7 << DF_HALF), pwd->h[7], oi, GETPC());
3366 #else
3367     helper_ret_stw_mmu(env, addr + (3 << DF_HALF), pwd->h[0], oi, GETPC());
3368     helper_ret_stw_mmu(env, addr + (2 << DF_HALF), pwd->h[1], oi, GETPC());
3369     helper_ret_stw_mmu(env, addr + (1 << DF_HALF), pwd->h[2], oi, GETPC());
3370     helper_ret_stw_mmu(env, addr + (0 << DF_HALF), pwd->h[3], oi, GETPC());
3371     helper_ret_stw_mmu(env, addr + (7 << DF_HALF), pwd->h[4], oi, GETPC());
3372     helper_ret_stw_mmu(env, addr + (6 << DF_HALF), pwd->h[5], oi, GETPC());
3373     helper_ret_stw_mmu(env, addr + (5 << DF_HALF), pwd->h[6], oi, GETPC());
3374     helper_ret_stw_mmu(env, addr + (4 << DF_HALF), pwd->h[7], oi, GETPC());
3375 #endif
3376 #else
3377 #if !defined(HOST_WORDS_BIGENDIAN)
3378     cpu_stw_data(env, addr + (0 << DF_HALF), pwd->h[0]);
3379     cpu_stw_data(env, addr + (1 << DF_HALF), pwd->h[1]);
3380     cpu_stw_data(env, addr + (2 << DF_HALF), pwd->h[2]);
3381     cpu_stw_data(env, addr + (3 << DF_HALF), pwd->h[3]);
3382     cpu_stw_data(env, addr + (4 << DF_HALF), pwd->h[4]);
3383     cpu_stw_data(env, addr + (5 << DF_HALF), pwd->h[5]);
3384     cpu_stw_data(env, addr + (6 << DF_HALF), pwd->h[6]);
3385     cpu_stw_data(env, addr + (7 << DF_HALF), pwd->h[7]);
3386 #else
3387     cpu_stw_data(env, addr + (3 << DF_HALF), pwd->h[0]);
3388     cpu_stw_data(env, addr + (2 << DF_HALF), pwd->h[1]);
3389     cpu_stw_data(env, addr + (1 << DF_HALF), pwd->h[2]);
3390     cpu_stw_data(env, addr + (0 << DF_HALF), pwd->h[3]);
3391     cpu_stw_data(env, addr + (7 << DF_HALF), pwd->h[4]);
3392     cpu_stw_data(env, addr + (6 << DF_HALF), pwd->h[5]);
3393     cpu_stw_data(env, addr + (5 << DF_HALF), pwd->h[6]);
3394     cpu_stw_data(env, addr + (4 << DF_HALF), pwd->h[7]);
3395 #endif
3396 #endif
3397 }
3398 
3399 void helper_msa_st_w(CPUMIPSState *env, uint32_t wd,
3400                      target_ulong addr)
3401 {
3402     wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3403     int mmu_idx = cpu_mmu_index(env, false);
3404 
3405     MEMOP_IDX(DF_WORD)
3406     ensure_writable_pages(env, addr, mmu_idx, GETPC());
3407 #if !defined(CONFIG_USER_ONLY)
3408 #if !defined(HOST_WORDS_BIGENDIAN)
3409     helper_ret_stl_mmu(env, addr + (0 << DF_WORD), pwd->w[0], oi, GETPC());
3410     helper_ret_stl_mmu(env, addr + (1 << DF_WORD), pwd->w[1], oi, GETPC());
3411     helper_ret_stl_mmu(env, addr + (2 << DF_WORD), pwd->w[2], oi, GETPC());
3412     helper_ret_stl_mmu(env, addr + (3 << DF_WORD), pwd->w[3], oi, GETPC());
3413 #else
3414     helper_ret_stl_mmu(env, addr + (1 << DF_WORD), pwd->w[0], oi, GETPC());
3415     helper_ret_stl_mmu(env, addr + (0 << DF_WORD), pwd->w[1], oi, GETPC());
3416     helper_ret_stl_mmu(env, addr + (3 << DF_WORD), pwd->w[2], oi, GETPC());
3417     helper_ret_stl_mmu(env, addr + (2 << DF_WORD), pwd->w[3], oi, GETPC());
3418 #endif
3419 #else
3420 #if !defined(HOST_WORDS_BIGENDIAN)
3421     cpu_stl_data(env, addr + (0 << DF_WORD), pwd->w[0]);
3422     cpu_stl_data(env, addr + (1 << DF_WORD), pwd->w[1]);
3423     cpu_stl_data(env, addr + (2 << DF_WORD), pwd->w[2]);
3424     cpu_stl_data(env, addr + (3 << DF_WORD), pwd->w[3]);
3425 #else
3426     cpu_stl_data(env, addr + (1 << DF_WORD), pwd->w[0]);
3427     cpu_stl_data(env, addr + (0 << DF_WORD), pwd->w[1]);
3428     cpu_stl_data(env, addr + (3 << DF_WORD), pwd->w[2]);
3429     cpu_stl_data(env, addr + (2 << DF_WORD), pwd->w[3]);
3430 #endif
3431 #endif
3432 }
3433 
3434 void helper_msa_st_d(CPUMIPSState *env, uint32_t wd,
3435                      target_ulong addr)
3436 {
3437     wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
3438     int mmu_idx = cpu_mmu_index(env, false);
3439 
3440     MEMOP_IDX(DF_DOUBLE)
3441     ensure_writable_pages(env, addr, mmu_idx, GETPC());
3442 #if !defined(CONFIG_USER_ONLY)
3443     helper_ret_stq_mmu(env, addr + (0 << DF_DOUBLE), pwd->d[0], oi, GETPC());
3444     helper_ret_stq_mmu(env, addr + (1 << DF_DOUBLE), pwd->d[1], oi, GETPC());
3445 #else
3446     cpu_stq_data(env, addr + (0 << DF_DOUBLE), pwd->d[0]);
3447     cpu_stq_data(env, addr + (1 << DF_DOUBLE), pwd->d[1]);
3448 #endif
3449 }
3450 
3451 void helper_cache(CPUMIPSState *env, target_ulong addr, uint32_t op)
3452 {
3453 #ifndef CONFIG_USER_ONLY
3454     target_ulong index = addr & 0x1fffffff;
3455     if (op == 9) {
3456         /* Index Store Tag */
3457         memory_region_dispatch_write(env->itc_tag, index, env->CP0_TagLo,
3458                                      MO_64, MEMTXATTRS_UNSPECIFIED);
3459     } else if (op == 5) {
3460         /* Index Load Tag */
3461         memory_region_dispatch_read(env->itc_tag, index, &env->CP0_TagLo,
3462                                     MO_64, MEMTXATTRS_UNSPECIFIED);
3463     }
3464 #endif
3465 }
3466