]> Git Repo - qemu.git/blame - target/mips/op_helper.c
target/mips: Fix block-comment-related issues in msa_helper.c
[qemu.git] / target / mips / op_helper.c
CommitLineData
6af0bf9c
FB
1/*
2 * MIPS emulation helpers for qemu.
5fafdf24 3 *
6af0bf9c
FB
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
8167ee88 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
6af0bf9c 18 */
c684822a 19#include "qemu/osdep.h"
41931c01 20#include "qemu/main-loop.h"
3e457172 21#include "cpu.h"
26aa3d9a 22#include "internal.h"
1de7afc9 23#include "qemu/host-utils.h"
2ef6175a 24#include "exec/helper-proto.h"
63c91552 25#include "exec/exec-all.h"
f08b6170 26#include "exec/cpu_ldst.h"
eddedd54 27#include "sysemu/kvm.h"
3e457172 28
6af0bf9c
FB
29/*****************************************************************************/
30/* Exceptions processing helpers */
6af0bf9c 31
9c708c7f
PD
32void helper_raise_exception_err(CPUMIPSState *env, uint32_t exception,
33 int error_code)
6af0bf9c 34{
9c708c7f 35 do_raise_exception_err(env, exception, error_code, 0);
6af0bf9c
FB
36}
37
9c708c7f 38void helper_raise_exception(CPUMIPSState *env, uint32_t exception)
6af0bf9c 39{
9c708c7f 40 do_raise_exception(env, exception, GETPC());
6af0bf9c
FB
41}
42
9c708c7f 43void helper_raise_exception_debug(CPUMIPSState *env)
4ad40f36 44{
9c708c7f 45 do_raise_exception(env, EXCP_DEBUG, 0);
5f7319cd 46}
20503968 47
9c708c7f 48static void raise_exception(CPUMIPSState *env, uint32_t exception)
5f7319cd
AJ
49{
50 do_raise_exception(env, exception, 0);
4ad40f36
FB
51}
52
0ae43045
AJ
53#if defined(CONFIG_USER_ONLY)
54#define HELPER_LD(name, insn, type) \
895c2d04 55static inline type do_##name(CPUMIPSState *env, target_ulong addr, \
9c708c7f 56 int mem_idx, uintptr_t retaddr) \
0ae43045 57{ \
9c708c7f 58 return (type) cpu_##insn##_data_ra(env, addr, retaddr); \
0ae43045
AJ
59}
60#else
61#define HELPER_LD(name, insn, type) \
895c2d04 62static inline type do_##name(CPUMIPSState *env, target_ulong addr, \
9c708c7f 63 int mem_idx, uintptr_t retaddr) \
0ae43045
AJ
64{ \
65 switch (mem_idx) \
66 { \
9c708c7f
PD
67 case 0: return (type) cpu_##insn##_kernel_ra(env, addr, retaddr); \
68 case 1: return (type) cpu_##insn##_super_ra(env, addr, retaddr); \
0ae43045 69 default: \
9c708c7f 70 case 2: return (type) cpu_##insn##_user_ra(env, addr, retaddr); \
42c86612 71 case 3: return (type) cpu_##insn##_error_ra(env, addr, retaddr); \
0ae43045
AJ
72 } \
73}
74#endif
0ae43045 75HELPER_LD(lw, ldl, int32_t)
adc370a4 76#if defined(TARGET_MIPS64)
0ae43045 77HELPER_LD(ld, ldq, int64_t)
adc370a4 78#endif
0ae43045
AJ
79#undef HELPER_LD
80
81#if defined(CONFIG_USER_ONLY)
82#define HELPER_ST(name, insn, type) \
895c2d04 83static inline void do_##name(CPUMIPSState *env, target_ulong addr, \
9c708c7f 84 type val, int mem_idx, uintptr_t retaddr) \
0ae43045 85{ \
9c708c7f 86 cpu_##insn##_data_ra(env, addr, val, retaddr); \
0ae43045
AJ
87}
88#else
89#define HELPER_ST(name, insn, type) \
895c2d04 90static inline void do_##name(CPUMIPSState *env, target_ulong addr, \
9c708c7f 91 type val, int mem_idx, uintptr_t retaddr) \
0ae43045
AJ
92{ \
93 switch (mem_idx) \
94 { \
9c708c7f
PD
95 case 0: cpu_##insn##_kernel_ra(env, addr, val, retaddr); break; \
96 case 1: cpu_##insn##_super_ra(env, addr, val, retaddr); break; \
0ae43045 97 default: \
9c708c7f 98 case 2: cpu_##insn##_user_ra(env, addr, val, retaddr); break; \
42c86612
JH
99 case 3: \
100 cpu_##insn##_error_ra(env, addr, val, retaddr); \
101 break; \
0ae43045
AJ
102 } \
103}
104#endif
105HELPER_ST(sb, stb, uint8_t)
106HELPER_ST(sw, stl, uint32_t)
adc370a4 107#if defined(TARGET_MIPS64)
0ae43045 108HELPER_ST(sd, stq, uint64_t)
adc370a4 109#endif
0ae43045
AJ
110#undef HELPER_ST
111
6af0bf9c 112/* 64 bits arithmetic for 32 bits hosts */
895c2d04 113static inline uint64_t get_HILO(CPUMIPSState *env)
6af0bf9c 114{
b5dc7732 115 return ((uint64_t)(env->active_tc.HI[0]) << 32) | (uint32_t)env->active_tc.LO[0];
6af0bf9c
FB
116}
117
895c2d04 118static inline target_ulong set_HIT0_LO(CPUMIPSState *env, uint64_t HILO)
e9c71dd1 119{
b5dc7732 120 env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF);
9be38598 121 return env->active_tc.HI[0] = (int32_t)(HILO >> 32);
e9c71dd1
TS
122}
123
895c2d04 124static inline target_ulong set_HI_LOT0(CPUMIPSState *env, uint64_t HILO)
e9c71dd1 125{
6fc97faf 126 target_ulong tmp = env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF);
b5dc7732 127 env->active_tc.HI[0] = (int32_t)(HILO >> 32);
6fc97faf 128 return tmp;
e9c71dd1
TS
129}
130
e9c71dd1 131/* Multiplication variants of the vr54xx. */
895c2d04
BS
132target_ulong helper_muls(CPUMIPSState *env, target_ulong arg1,
133 target_ulong arg2)
e9c71dd1 134{
895c2d04
BS
135 return set_HI_LOT0(env, 0 - ((int64_t)(int32_t)arg1 *
136 (int64_t)(int32_t)arg2));
e9c71dd1
TS
137}
138
895c2d04
BS
139target_ulong helper_mulsu(CPUMIPSState *env, target_ulong arg1,
140 target_ulong arg2)
e9c71dd1 141{
895c2d04
BS
142 return set_HI_LOT0(env, 0 - (uint64_t)(uint32_t)arg1 *
143 (uint64_t)(uint32_t)arg2);
e9c71dd1
TS
144}
145
895c2d04
BS
146target_ulong helper_macc(CPUMIPSState *env, target_ulong arg1,
147 target_ulong arg2)
e9c71dd1 148{
895c2d04
BS
149 return set_HI_LOT0(env, (int64_t)get_HILO(env) + (int64_t)(int32_t)arg1 *
150 (int64_t)(int32_t)arg2);
e9c71dd1
TS
151}
152
895c2d04
BS
153target_ulong helper_macchi(CPUMIPSState *env, target_ulong arg1,
154 target_ulong arg2)
e9c71dd1 155{
895c2d04
BS
156 return set_HIT0_LO(env, (int64_t)get_HILO(env) + (int64_t)(int32_t)arg1 *
157 (int64_t)(int32_t)arg2);
e9c71dd1
TS
158}
159
895c2d04
BS
160target_ulong helper_maccu(CPUMIPSState *env, target_ulong arg1,
161 target_ulong arg2)
e9c71dd1 162{
895c2d04
BS
163 return set_HI_LOT0(env, (uint64_t)get_HILO(env) +
164 (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2);
e9c71dd1
TS
165}
166
895c2d04
BS
167target_ulong helper_macchiu(CPUMIPSState *env, target_ulong arg1,
168 target_ulong arg2)
e9c71dd1 169{
895c2d04
BS
170 return set_HIT0_LO(env, (uint64_t)get_HILO(env) +
171 (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2);
e9c71dd1
TS
172}
173
895c2d04
BS
174target_ulong helper_msac(CPUMIPSState *env, target_ulong arg1,
175 target_ulong arg2)
e9c71dd1 176{
895c2d04
BS
177 return set_HI_LOT0(env, (int64_t)get_HILO(env) - (int64_t)(int32_t)arg1 *
178 (int64_t)(int32_t)arg2);
e9c71dd1
TS
179}
180
895c2d04
BS
181target_ulong helper_msachi(CPUMIPSState *env, target_ulong arg1,
182 target_ulong arg2)
e9c71dd1 183{
895c2d04
BS
184 return set_HIT0_LO(env, (int64_t)get_HILO(env) - (int64_t)(int32_t)arg1 *
185 (int64_t)(int32_t)arg2);
e9c71dd1
TS
186}
187
895c2d04
BS
188target_ulong helper_msacu(CPUMIPSState *env, target_ulong arg1,
189 target_ulong arg2)
e9c71dd1 190{
895c2d04
BS
191 return set_HI_LOT0(env, (uint64_t)get_HILO(env) -
192 (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2);
e9c71dd1
TS
193}
194
895c2d04
BS
195target_ulong helper_msachiu(CPUMIPSState *env, target_ulong arg1,
196 target_ulong arg2)
e9c71dd1 197{
895c2d04
BS
198 return set_HIT0_LO(env, (uint64_t)get_HILO(env) -
199 (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2);
e9c71dd1
TS
200}
201
895c2d04
BS
202target_ulong helper_mulhi(CPUMIPSState *env, target_ulong arg1,
203 target_ulong arg2)
e9c71dd1 204{
895c2d04 205 return set_HIT0_LO(env, (int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2);
e9c71dd1
TS
206}
207
895c2d04
BS
208target_ulong helper_mulhiu(CPUMIPSState *env, target_ulong arg1,
209 target_ulong arg2)
e9c71dd1 210{
895c2d04
BS
211 return set_HIT0_LO(env, (uint64_t)(uint32_t)arg1 *
212 (uint64_t)(uint32_t)arg2);
e9c71dd1
TS
213}
214
895c2d04
BS
215target_ulong helper_mulshi(CPUMIPSState *env, target_ulong arg1,
216 target_ulong arg2)
e9c71dd1 217{
895c2d04
BS
218 return set_HIT0_LO(env, 0 - (int64_t)(int32_t)arg1 *
219 (int64_t)(int32_t)arg2);
e9c71dd1
TS
220}
221
895c2d04
BS
222target_ulong helper_mulshiu(CPUMIPSState *env, target_ulong arg1,
223 target_ulong arg2)
e9c71dd1 224{
895c2d04
BS
225 return set_HIT0_LO(env, 0 - (uint64_t)(uint32_t)arg1 *
226 (uint64_t)(uint32_t)arg2);
e9c71dd1 227}
6af0bf9c 228
15eacb9b
YK
229static inline target_ulong bitswap(target_ulong v)
230{
74dda987
LA
231 v = ((v >> 1) & (target_ulong)0x5555555555555555ULL) |
232 ((v & (target_ulong)0x5555555555555555ULL) << 1);
233 v = ((v >> 2) & (target_ulong)0x3333333333333333ULL) |
234 ((v & (target_ulong)0x3333333333333333ULL) << 2);
235 v = ((v >> 4) & (target_ulong)0x0F0F0F0F0F0F0F0FULL) |
236 ((v & (target_ulong)0x0F0F0F0F0F0F0F0FULL) << 4);
15eacb9b
YK
237 return v;
238}
239
240#ifdef TARGET_MIPS64
241target_ulong helper_dbitswap(target_ulong rt)
242{
243 return bitswap(rt);
244}
245#endif
246
247target_ulong helper_bitswap(target_ulong rt)
248{
249 return (int32_t)bitswap(rt);
250}
251
e222f506
MF
252target_ulong helper_rotx(target_ulong rs, uint32_t shift, uint32_t shiftx,
253 uint32_t stripe)
254{
255 int i;
256 uint64_t tmp0 = ((uint64_t)rs) << 32 | ((uint64_t)rs & 0xffffffff);
257 uint64_t tmp1 = tmp0;
258 for (i = 0; i <= 46; i++) {
259 int s;
260 if (i & 0x8) {
261 s = shift;
262 } else {
263 s = shiftx;
264 }
265
266 if (stripe != 0 && !(i & 0x4)) {
267 s = ~s;
268 }
269 if (s & 0x10) {
270 if (tmp0 & (1LL << (i + 16))) {
271 tmp1 |= 1LL << i;
272 } else {
273 tmp1 &= ~(1LL << i);
274 }
275 }
276 }
277
278 uint64_t tmp2 = tmp1;
279 for (i = 0; i <= 38; i++) {
280 int s;
281 if (i & 0x4) {
282 s = shift;
283 } else {
284 s = shiftx;
285 }
286
287 if (s & 0x8) {
288 if (tmp1 & (1LL << (i + 8))) {
289 tmp2 |= 1LL << i;
290 } else {
291 tmp2 &= ~(1LL << i);
292 }
293 }
294 }
295
296 uint64_t tmp3 = tmp2;
297 for (i = 0; i <= 34; i++) {
298 int s;
299 if (i & 0x2) {
300 s = shift;
301 } else {
302 s = shiftx;
303 }
304 if (s & 0x4) {
305 if (tmp2 & (1LL << (i + 4))) {
306 tmp3 |= 1LL << i;
307 } else {
308 tmp3 &= ~(1LL << i);
309 }
310 }
311 }
312
313 uint64_t tmp4 = tmp3;
314 for (i = 0; i <= 32; i++) {
315 int s;
316 if (i & 0x1) {
317 s = shift;
318 } else {
319 s = shiftx;
320 }
321 if (s & 0x2) {
322 if (tmp3 & (1LL << (i + 2))) {
323 tmp4 |= 1LL << i;
324 } else {
325 tmp4 &= ~(1LL << i);
326 }
327 }
328 }
329
330 uint64_t tmp5 = tmp4;
331 for (i = 0; i <= 31; i++) {
332 int s;
333 s = shift;
334 if (s & 0x1) {
335 if (tmp4 & (1LL << (i + 1))) {
336 tmp5 |= 1LL << i;
337 } else {
338 tmp5 &= ~(1LL << i);
339 }
340 }
341 }
342
343 return (int64_t)(int32_t)(uint32_t)tmp5;
344}
345
e7139c44 346#ifndef CONFIG_USER_ONLY
c36bbb28 347
a8170e5e 348static inline hwaddr do_translate_address(CPUMIPSState *env,
895c2d04 349 target_ulong address,
9c708c7f 350 int rw, uintptr_t retaddr)
c36bbb28 351{
c7c7e1e9 352 hwaddr paddr;
9c708c7f 353 CPUState *cs = CPU(mips_env_get_cpu(env));
c36bbb28 354
c7c7e1e9 355 paddr = cpu_mips_translate_address(env, address, rw);
c36bbb28 356
c7c7e1e9 357 if (paddr == -1LL) {
9c708c7f 358 cpu_loop_exit_restore(cs, retaddr);
c36bbb28 359 } else {
c7c7e1e9 360 return paddr;
c36bbb28
AJ
361 }
362}
363
6489dd25 364#define HELPER_LD_ATOMIC(name, insn, almask) \
895c2d04 365target_ulong helper_##name(CPUMIPSState *env, target_ulong arg, int mem_idx) \
e7139c44 366{ \
6489dd25 367 if (arg & almask) { \
e807bcc1
YK
368 if (!(env->hflags & MIPS_HFLAG_DM)) { \
369 env->CP0_BadVAddr = arg; \
370 } \
9c708c7f 371 do_raise_exception(env, EXCP_AdEL, GETPC()); \
6489dd25 372 } \
c7c7e1e9
LA
373 env->CP0_LLAddr = do_translate_address(env, arg, 0, GETPC()); \
374 env->lladdr = arg; \
9c708c7f 375 env->llval = do_##insn(env, arg, mem_idx, GETPC()); \
e7139c44
AJ
376 return env->llval; \
377}
6489dd25 378HELPER_LD_ATOMIC(ll, lw, 0x3)
e7139c44 379#ifdef TARGET_MIPS64
6489dd25 380HELPER_LD_ATOMIC(lld, ld, 0x7)
e7139c44
AJ
381#endif
382#undef HELPER_LD_ATOMIC
e7139c44
AJ
383#endif
384
c8c2227e
TS
385#ifdef TARGET_WORDS_BIGENDIAN
386#define GET_LMASK(v) ((v) & 3)
387#define GET_OFFSET(addr, offset) (addr + (offset))
388#else
389#define GET_LMASK(v) (((v) & 3) ^ 3)
390#define GET_OFFSET(addr, offset) (addr - (offset))
391#endif
392
895c2d04
BS
393void helper_swl(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
394 int mem_idx)
c8c2227e 395{
9c708c7f 396 do_sb(env, arg2, (uint8_t)(arg1 >> 24), mem_idx, GETPC());
c8c2227e 397
9c708c7f
PD
398 if (GET_LMASK(arg2) <= 2) {
399 do_sb(env, GET_OFFSET(arg2, 1), (uint8_t)(arg1 >> 16), mem_idx,
400 GETPC());
401 }
c8c2227e 402
9c708c7f
PD
403 if (GET_LMASK(arg2) <= 1) {
404 do_sb(env, GET_OFFSET(arg2, 2), (uint8_t)(arg1 >> 8), mem_idx,
405 GETPC());
406 }
c8c2227e 407
9c708c7f
PD
408 if (GET_LMASK(arg2) == 0) {
409 do_sb(env, GET_OFFSET(arg2, 3), (uint8_t)arg1, mem_idx,
410 GETPC());
411 }
c8c2227e
TS
412}
413
895c2d04
BS
414void helper_swr(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
415 int mem_idx)
c8c2227e 416{
9c708c7f 417 do_sb(env, arg2, (uint8_t)arg1, mem_idx, GETPC());
c8c2227e 418
9c708c7f
PD
419 if (GET_LMASK(arg2) >= 1) {
420 do_sb(env, GET_OFFSET(arg2, -1), (uint8_t)(arg1 >> 8), mem_idx,
421 GETPC());
422 }
c8c2227e 423
9c708c7f
PD
424 if (GET_LMASK(arg2) >= 2) {
425 do_sb(env, GET_OFFSET(arg2, -2), (uint8_t)(arg1 >> 16), mem_idx,
426 GETPC());
427 }
c8c2227e 428
9c708c7f
PD
429 if (GET_LMASK(arg2) == 3) {
430 do_sb(env, GET_OFFSET(arg2, -3), (uint8_t)(arg1 >> 24), mem_idx,
431 GETPC());
432 }
c8c2227e
TS
433}
434
435#if defined(TARGET_MIPS64)
436/* "half" load and stores. We must do the memory access inline,
437 or fault handling won't work. */
438
439#ifdef TARGET_WORDS_BIGENDIAN
440#define GET_LMASK64(v) ((v) & 7)
441#else
442#define GET_LMASK64(v) (((v) & 7) ^ 7)
443#endif
444
895c2d04
BS
445void helper_sdl(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
446 int mem_idx)
c8c2227e 447{
9c708c7f 448 do_sb(env, arg2, (uint8_t)(arg1 >> 56), mem_idx, GETPC());
c8c2227e 449
9c708c7f
PD
450 if (GET_LMASK64(arg2) <= 6) {
451 do_sb(env, GET_OFFSET(arg2, 1), (uint8_t)(arg1 >> 48), mem_idx,
452 GETPC());
453 }
c8c2227e 454
9c708c7f
PD
455 if (GET_LMASK64(arg2) <= 5) {
456 do_sb(env, GET_OFFSET(arg2, 2), (uint8_t)(arg1 >> 40), mem_idx,
457 GETPC());
458 }
c8c2227e 459
9c708c7f
PD
460 if (GET_LMASK64(arg2) <= 4) {
461 do_sb(env, GET_OFFSET(arg2, 3), (uint8_t)(arg1 >> 32), mem_idx,
462 GETPC());
463 }
c8c2227e 464
9c708c7f
PD
465 if (GET_LMASK64(arg2) <= 3) {
466 do_sb(env, GET_OFFSET(arg2, 4), (uint8_t)(arg1 >> 24), mem_idx,
467 GETPC());
468 }
c8c2227e 469
9c708c7f
PD
470 if (GET_LMASK64(arg2) <= 2) {
471 do_sb(env, GET_OFFSET(arg2, 5), (uint8_t)(arg1 >> 16), mem_idx,
472 GETPC());
473 }
c8c2227e 474
9c708c7f
PD
475 if (GET_LMASK64(arg2) <= 1) {
476 do_sb(env, GET_OFFSET(arg2, 6), (uint8_t)(arg1 >> 8), mem_idx,
477 GETPC());
478 }
c8c2227e 479
9c708c7f
PD
480 if (GET_LMASK64(arg2) <= 0) {
481 do_sb(env, GET_OFFSET(arg2, 7), (uint8_t)arg1, mem_idx,
482 GETPC());
483 }
c8c2227e
TS
484}
485
895c2d04
BS
486void helper_sdr(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
487 int mem_idx)
c8c2227e 488{
9c708c7f 489 do_sb(env, arg2, (uint8_t)arg1, mem_idx, GETPC());
c8c2227e 490
9c708c7f
PD
491 if (GET_LMASK64(arg2) >= 1) {
492 do_sb(env, GET_OFFSET(arg2, -1), (uint8_t)(arg1 >> 8), mem_idx,
493 GETPC());
494 }
c8c2227e 495
9c708c7f
PD
496 if (GET_LMASK64(arg2) >= 2) {
497 do_sb(env, GET_OFFSET(arg2, -2), (uint8_t)(arg1 >> 16), mem_idx,
498 GETPC());
499 }
c8c2227e 500
9c708c7f
PD
501 if (GET_LMASK64(arg2) >= 3) {
502 do_sb(env, GET_OFFSET(arg2, -3), (uint8_t)(arg1 >> 24), mem_idx,
503 GETPC());
504 }
c8c2227e 505
9c708c7f
PD
506 if (GET_LMASK64(arg2) >= 4) {
507 do_sb(env, GET_OFFSET(arg2, -4), (uint8_t)(arg1 >> 32), mem_idx,
508 GETPC());
509 }
c8c2227e 510
9c708c7f
PD
511 if (GET_LMASK64(arg2) >= 5) {
512 do_sb(env, GET_OFFSET(arg2, -5), (uint8_t)(arg1 >> 40), mem_idx,
513 GETPC());
514 }
c8c2227e 515
9c708c7f
PD
516 if (GET_LMASK64(arg2) >= 6) {
517 do_sb(env, GET_OFFSET(arg2, -6), (uint8_t)(arg1 >> 48), mem_idx,
518 GETPC());
519 }
c8c2227e 520
9c708c7f
PD
521 if (GET_LMASK64(arg2) == 7) {
522 do_sb(env, GET_OFFSET(arg2, -7), (uint8_t)(arg1 >> 56), mem_idx,
523 GETPC());
524 }
c8c2227e
TS
525}
526#endif /* TARGET_MIPS64 */
527
3c824109
NF
528static const int multiple_regs[] = { 16, 17, 18, 19, 20, 21, 22, 23, 30 };
529
895c2d04
BS
530void helper_lwm(CPUMIPSState *env, target_ulong addr, target_ulong reglist,
531 uint32_t mem_idx)
3c824109
NF
532{
533 target_ulong base_reglist = reglist & 0xf;
534 target_ulong do_r31 = reglist & 0x10;
3c824109
NF
535
536 if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) {
537 target_ulong i;
538
539 for (i = 0; i < base_reglist; i++) {
18bba4dc 540 env->active_tc.gpr[multiple_regs[i]] =
9c708c7f 541 (target_long)do_lw(env, addr, mem_idx, GETPC());
3c824109
NF
542 addr += 4;
543 }
544 }
545
546 if (do_r31) {
9c708c7f
PD
547 env->active_tc.gpr[31] = (target_long)do_lw(env, addr, mem_idx,
548 GETPC());
3c824109
NF
549 }
550}
551
895c2d04
BS
552void helper_swm(CPUMIPSState *env, target_ulong addr, target_ulong reglist,
553 uint32_t mem_idx)
3c824109
NF
554{
555 target_ulong base_reglist = reglist & 0xf;
556 target_ulong do_r31 = reglist & 0x10;
3c824109
NF
557
558 if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) {
559 target_ulong i;
560
561 for (i = 0; i < base_reglist; i++) {
9c708c7f
PD
562 do_sw(env, addr, env->active_tc.gpr[multiple_regs[i]], mem_idx,
563 GETPC());
3c824109
NF
564 addr += 4;
565 }
566 }
567
568 if (do_r31) {
9c708c7f 569 do_sw(env, addr, env->active_tc.gpr[31], mem_idx, GETPC());
3c824109
NF
570 }
571}
572
573#if defined(TARGET_MIPS64)
895c2d04
BS
574void helper_ldm(CPUMIPSState *env, target_ulong addr, target_ulong reglist,
575 uint32_t mem_idx)
3c824109
NF
576{
577 target_ulong base_reglist = reglist & 0xf;
578 target_ulong do_r31 = reglist & 0x10;
3c824109
NF
579
580 if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) {
581 target_ulong i;
582
583 for (i = 0; i < base_reglist; i++) {
9c708c7f
PD
584 env->active_tc.gpr[multiple_regs[i]] = do_ld(env, addr, mem_idx,
585 GETPC());
3c824109
NF
586 addr += 8;
587 }
588 }
589
590 if (do_r31) {
9c708c7f 591 env->active_tc.gpr[31] = do_ld(env, addr, mem_idx, GETPC());
3c824109
NF
592 }
593}
594
895c2d04
BS
595void helper_sdm(CPUMIPSState *env, target_ulong addr, target_ulong reglist,
596 uint32_t mem_idx)
3c824109
NF
597{
598 target_ulong base_reglist = reglist & 0xf;
599 target_ulong do_r31 = reglist & 0x10;
3c824109
NF
600
601 if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) {
602 target_ulong i;
603
604 for (i = 0; i < base_reglist; i++) {
9c708c7f
PD
605 do_sd(env, addr, env->active_tc.gpr[multiple_regs[i]], mem_idx,
606 GETPC());
3c824109
NF
607 addr += 8;
608 }
609 }
610
611 if (do_r31) {
9c708c7f 612 do_sd(env, addr, env->active_tc.gpr[31], mem_idx, GETPC());
3c824109
NF
613 }
614}
615#endif
616
0eaef5aa 617#ifndef CONFIG_USER_ONLY
f249412c 618/* SMP helpers. */
b35d77d7 619static bool mips_vpe_is_wfi(MIPSCPU *c)
f249412c 620{
259186a7 621 CPUState *cpu = CPU(c);
b35d77d7
AF
622 CPUMIPSState *env = &c->env;
623
f249412c
EI
624 /* If the VPE is halted but otherwise active, it means it's waiting for
625 an interrupt. */
259186a7 626 return cpu->halted && mips_vpe_active(env);
f249412c
EI
627}
628
01bc435b
YK
629static bool mips_vp_is_wfi(MIPSCPU *c)
630{
631 CPUState *cpu = CPU(c);
632 CPUMIPSState *env = &c->env;
633
634 return cpu->halted && mips_vp_active(env);
635}
636
c3affe56 637static inline void mips_vpe_wake(MIPSCPU *c)
f249412c 638{
cb8d4c8f 639 /* Don't set ->halted = 0 directly, let it be done via cpu_has_work
f249412c
EI
640 because there might be other conditions that state that c should
641 be sleeping. */
41931c01 642 qemu_mutex_lock_iothread();
c3affe56 643 cpu_interrupt(CPU(c), CPU_INTERRUPT_WAKE);
41931c01 644 qemu_mutex_unlock_iothread();
f249412c
EI
645}
646
6f4d6b09 647static inline void mips_vpe_sleep(MIPSCPU *cpu)
f249412c 648{
259186a7 649 CPUState *cs = CPU(cpu);
6f4d6b09 650
f249412c
EI
651 /* The VPE was shut off, really go to bed.
652 Reset any old _WAKE requests. */
259186a7 653 cs->halted = 1;
d8ed887b 654 cpu_reset_interrupt(cs, CPU_INTERRUPT_WAKE);
f249412c
EI
655}
656
135dd63a 657static inline void mips_tc_wake(MIPSCPU *cpu, int tc)
f249412c 658{
135dd63a
AF
659 CPUMIPSState *c = &cpu->env;
660
f249412c 661 /* FIXME: TC reschedule. */
b35d77d7 662 if (mips_vpe_active(c) && !mips_vpe_is_wfi(cpu)) {
c3affe56 663 mips_vpe_wake(cpu);
f249412c
EI
664 }
665}
666
c6679e90 667static inline void mips_tc_sleep(MIPSCPU *cpu, int tc)
f249412c 668{
c6679e90
AF
669 CPUMIPSState *c = &cpu->env;
670
f249412c
EI
671 /* FIXME: TC reschedule. */
672 if (!mips_vpe_active(c)) {
6f4d6b09 673 mips_vpe_sleep(cpu);
f249412c
EI
674 }
675}
676
66afd1ad
AF
677/**
678 * mips_cpu_map_tc:
679 * @env: CPU from which mapping is performed.
680 * @tc: Should point to an int with the value of the global TC index.
681 *
682 * This function will transform @tc into a local index within the
683 * returned #CPUMIPSState.
684 */
685/* FIXME: This code assumes that all VPEs have the same number of TCs,
b93bbdcd 686 which depends on runtime setup. Can probably be fixed by
7db13fae 687 walking the list of CPUMIPSStates. */
895c2d04 688static CPUMIPSState *mips_cpu_map_tc(CPUMIPSState *env, int *tc)
b93bbdcd 689{
38d8f5c8 690 MIPSCPU *cpu;
ce3960eb 691 CPUState *cs;
38d8f5c8 692 CPUState *other_cs;
ce3960eb 693 int vpe_idx;
b93bbdcd
EI
694 int tc_idx = *tc;
695
696 if (!(env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP))) {
697 /* Not allowed to address other CPUs. */
698 *tc = env->current_tc;
699 return env;
700 }
701
ce3960eb
AF
702 cs = CPU(mips_env_get_cpu(env));
703 vpe_idx = tc_idx / cs->nr_threads;
704 *tc = tc_idx % cs->nr_threads;
38d8f5c8
AF
705 other_cs = qemu_get_cpu(vpe_idx);
706 if (other_cs == NULL) {
707 return env;
708 }
709 cpu = MIPS_CPU(other_cs);
710 return &cpu->env;
b93bbdcd
EI
711}
712
fe8dca8c
EI
713/* The per VPE CP0_Status register shares some fields with the per TC
714 CP0_TCStatus registers. These fields are wired to the same registers,
715 so changes to either of them should be reflected on both registers.
716
717 Also, EntryHi shares the bottom 8 bit ASID with TCStauts.
718
719 These helper call synchronizes the regs for a given cpu. */
720
81a423e6
MR
721/* Called for updates to CP0_Status. Defined in "cpu.h" for gdbstub.c. */
722/* static inline void sync_c0_status(CPUMIPSState *env, CPUMIPSState *cpu,
723 int tc); */
fe8dca8c
EI
724
725/* Called for updates to CP0_TCStatus. */
895c2d04
BS
726static void sync_c0_tcstatus(CPUMIPSState *cpu, int tc,
727 target_ulong v)
fe8dca8c
EI
728{
729 uint32_t status;
730 uint32_t tcu, tmx, tasid, tksu;
f45cb2f4 731 uint32_t mask = ((1U << CP0St_CU3)
fe8dca8c
EI
732 | (1 << CP0St_CU2)
733 | (1 << CP0St_CU1)
734 | (1 << CP0St_CU0)
735 | (1 << CP0St_MX)
736 | (3 << CP0St_KSU));
737
738 tcu = (v >> CP0TCSt_TCU0) & 0xf;
739 tmx = (v >> CP0TCSt_TMX) & 0x1;
6ec98bd7 740 tasid = v & cpu->CP0_EntryHi_ASID_mask;
fe8dca8c
EI
741 tksu = (v >> CP0TCSt_TKSU) & 0x3;
742
743 status = tcu << CP0St_CU0;
744 status |= tmx << CP0St_MX;
745 status |= tksu << CP0St_KSU;
746
747 cpu->CP0_Status &= ~mask;
748 cpu->CP0_Status |= status;
749
750 /* Sync the TASID with EntryHi. */
6ec98bd7 751 cpu->CP0_EntryHi &= ~cpu->CP0_EntryHi_ASID_mask;
6a973e6b 752 cpu->CP0_EntryHi |= tasid;
fe8dca8c
EI
753
754 compute_hflags(cpu);
755}
756
757/* Called for updates to CP0_EntryHi. */
7db13fae 758static void sync_c0_entryhi(CPUMIPSState *cpu, int tc)
fe8dca8c
EI
759{
760 int32_t *tcst;
761 uint32_t asid, v = cpu->CP0_EntryHi;
762
6ec98bd7 763 asid = v & cpu->CP0_EntryHi_ASID_mask;
fe8dca8c
EI
764
765 if (tc == cpu->current_tc) {
766 tcst = &cpu->active_tc.CP0_TCStatus;
767 } else {
768 tcst = &cpu->tcs[tc].CP0_TCStatus;
769 }
770
6ec98bd7 771 *tcst &= ~cpu->CP0_EntryHi_ASID_mask;
fe8dca8c
EI
772 *tcst |= asid;
773}
774
6af0bf9c 775/* CP0 helpers */
895c2d04 776target_ulong helper_mfc0_mvpcontrol(CPUMIPSState *env)
f1aa6320 777{
be24bb4f 778 return env->mvp->CP0_MVPControl;
f1aa6320
TS
779}
780
895c2d04 781target_ulong helper_mfc0_mvpconf0(CPUMIPSState *env)
f1aa6320 782{
be24bb4f 783 return env->mvp->CP0_MVPConf0;
f1aa6320
TS
784}
785
895c2d04 786target_ulong helper_mfc0_mvpconf1(CPUMIPSState *env)
f1aa6320 787{
be24bb4f 788 return env->mvp->CP0_MVPConf1;
f1aa6320
TS
789}
790
895c2d04 791target_ulong helper_mfc0_random(CPUMIPSState *env)
6af0bf9c 792{
be24bb4f 793 return (int32_t)cpu_mips_get_random(env);
873eb012 794}
6af0bf9c 795
895c2d04 796target_ulong helper_mfc0_tcstatus(CPUMIPSState *env)
f1aa6320 797{
b5dc7732 798 return env->active_tc.CP0_TCStatus;
f1aa6320
TS
799}
800
895c2d04 801target_ulong helper_mftc0_tcstatus(CPUMIPSState *env)
f1aa6320
TS
802{
803 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
895c2d04 804 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
f1aa6320 805
b93bbdcd
EI
806 if (other_tc == other->current_tc)
807 return other->active_tc.CP0_TCStatus;
b5dc7732 808 else
b93bbdcd 809 return other->tcs[other_tc].CP0_TCStatus;
f1aa6320
TS
810}
811
895c2d04 812target_ulong helper_mfc0_tcbind(CPUMIPSState *env)
f1aa6320 813{
b5dc7732 814 return env->active_tc.CP0_TCBind;
f1aa6320
TS
815}
816
895c2d04 817target_ulong helper_mftc0_tcbind(CPUMIPSState *env)
f1aa6320
TS
818{
819 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
895c2d04 820 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
f1aa6320 821
b93bbdcd
EI
822 if (other_tc == other->current_tc)
823 return other->active_tc.CP0_TCBind;
b5dc7732 824 else
b93bbdcd 825 return other->tcs[other_tc].CP0_TCBind;
f1aa6320
TS
826}
827
895c2d04 828target_ulong helper_mfc0_tcrestart(CPUMIPSState *env)
f1aa6320 829{
b5dc7732 830 return env->active_tc.PC;
f1aa6320
TS
831}
832
895c2d04 833target_ulong helper_mftc0_tcrestart(CPUMIPSState *env)
f1aa6320
TS
834{
835 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
895c2d04 836 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
f1aa6320 837
b93bbdcd
EI
838 if (other_tc == other->current_tc)
839 return other->active_tc.PC;
b5dc7732 840 else
b93bbdcd 841 return other->tcs[other_tc].PC;
f1aa6320
TS
842}
843
895c2d04 844target_ulong helper_mfc0_tchalt(CPUMIPSState *env)
f1aa6320 845{
b5dc7732 846 return env->active_tc.CP0_TCHalt;
f1aa6320
TS
847}
848
895c2d04 849target_ulong helper_mftc0_tchalt(CPUMIPSState *env)
f1aa6320
TS
850{
851 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
895c2d04 852 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
f1aa6320 853
b93bbdcd
EI
854 if (other_tc == other->current_tc)
855 return other->active_tc.CP0_TCHalt;
b5dc7732 856 else
b93bbdcd 857 return other->tcs[other_tc].CP0_TCHalt;
f1aa6320
TS
858}
859
895c2d04 860target_ulong helper_mfc0_tccontext(CPUMIPSState *env)
f1aa6320 861{
b5dc7732 862 return env->active_tc.CP0_TCContext;
f1aa6320
TS
863}
864
895c2d04 865target_ulong helper_mftc0_tccontext(CPUMIPSState *env)
f1aa6320
TS
866{
867 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
895c2d04 868 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
f1aa6320 869
b93bbdcd
EI
870 if (other_tc == other->current_tc)
871 return other->active_tc.CP0_TCContext;
b5dc7732 872 else
b93bbdcd 873 return other->tcs[other_tc].CP0_TCContext;
f1aa6320
TS
874}
875
895c2d04 876target_ulong helper_mfc0_tcschedule(CPUMIPSState *env)
f1aa6320 877{
b5dc7732 878 return env->active_tc.CP0_TCSchedule;
f1aa6320
TS
879}
880
895c2d04 881target_ulong helper_mftc0_tcschedule(CPUMIPSState *env)
f1aa6320
TS
882{
883 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
895c2d04 884 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
f1aa6320 885
b93bbdcd
EI
886 if (other_tc == other->current_tc)
887 return other->active_tc.CP0_TCSchedule;
b5dc7732 888 else
b93bbdcd 889 return other->tcs[other_tc].CP0_TCSchedule;
f1aa6320
TS
890}
891
895c2d04 892target_ulong helper_mfc0_tcschefback(CPUMIPSState *env)
f1aa6320 893{
b5dc7732 894 return env->active_tc.CP0_TCScheFBack;
f1aa6320
TS
895}
896
895c2d04 897target_ulong helper_mftc0_tcschefback(CPUMIPSState *env)
f1aa6320
TS
898{
899 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
895c2d04 900 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
f1aa6320 901
b93bbdcd
EI
902 if (other_tc == other->current_tc)
903 return other->active_tc.CP0_TCScheFBack;
b5dc7732 904 else
b93bbdcd 905 return other->tcs[other_tc].CP0_TCScheFBack;
f1aa6320
TS
906}
907
895c2d04 908target_ulong helper_mfc0_count(CPUMIPSState *env)
873eb012 909{
215581bd 910 return (int32_t)cpu_mips_get_count(env);
6af0bf9c
FB
911}
912
5fb2dcd1
YK
913target_ulong helper_mfc0_saar(CPUMIPSState *env)
914{
915 if ((env->CP0_SAARI & 0x3f) < 2) {
916 return (int32_t) env->CP0_SAAR[env->CP0_SAARI & 0x3f];
917 }
918 return 0;
919}
920
921target_ulong helper_mfhc0_saar(CPUMIPSState *env)
922{
923 if ((env->CP0_SAARI & 0x3f) < 2) {
924 return env->CP0_SAAR[env->CP0_SAARI & 0x3f] >> 32;
925 }
926 return 0;
927}
928
895c2d04 929target_ulong helper_mftc0_entryhi(CPUMIPSState *env)
f1aa6320
TS
930{
931 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
895c2d04 932 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
f1aa6320 933
fe8dca8c 934 return other->CP0_EntryHi;
f1aa6320
TS
935}
936
895c2d04 937target_ulong helper_mftc0_cause(CPUMIPSState *env)
5a25ce94
EI
938{
939 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
940 int32_t tccause;
895c2d04 941 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
5a25ce94
EI
942
943 if (other_tc == other->current_tc) {
944 tccause = other->CP0_Cause;
945 } else {
946 tccause = other->CP0_Cause;
947 }
948
949 return tccause;
950}
951
895c2d04 952target_ulong helper_mftc0_status(CPUMIPSState *env)
f1aa6320
TS
953{
954 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
895c2d04 955 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
b5dc7732 956
fe8dca8c 957 return other->CP0_Status;
f1aa6320
TS
958}
959
895c2d04 960target_ulong helper_mfc0_lladdr(CPUMIPSState *env)
f1aa6320 961{
c7c7e1e9 962 return (int32_t)(env->CP0_LLAddr >> env->CP0_LLAddr_shift);
f1aa6320
TS
963}
964
f6d4dd81
YK
965target_ulong helper_mfc0_maar(CPUMIPSState *env)
966{
967 return (int32_t) env->CP0_MAAR[env->CP0_MAARI];
968}
969
970target_ulong helper_mfhc0_maar(CPUMIPSState *env)
971{
972 return env->CP0_MAAR[env->CP0_MAARI] >> 32;
973}
974
895c2d04 975target_ulong helper_mfc0_watchlo(CPUMIPSState *env, uint32_t sel)
f1aa6320 976{
be24bb4f 977 return (int32_t)env->CP0_WatchLo[sel];
f1aa6320
TS
978}
979
895c2d04 980target_ulong helper_mfc0_watchhi(CPUMIPSState *env, uint32_t sel)
f1aa6320 981{
be24bb4f 982 return env->CP0_WatchHi[sel];
f1aa6320
TS
983}
984
895c2d04 985target_ulong helper_mfc0_debug(CPUMIPSState *env)
f1aa6320 986{
1a3fd9c3 987 target_ulong t0 = env->CP0_Debug;
f1aa6320 988 if (env->hflags & MIPS_HFLAG_DM)
be24bb4f
TS
989 t0 |= 1 << CP0DB_DM;
990
991 return t0;
f1aa6320
TS
992}
993
895c2d04 994target_ulong helper_mftc0_debug(CPUMIPSState *env)
f1aa6320
TS
995{
996 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
b5dc7732 997 int32_t tcstatus;
895c2d04 998 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
b5dc7732 999
b93bbdcd
EI
1000 if (other_tc == other->current_tc)
1001 tcstatus = other->active_tc.CP0_Debug_tcstatus;
b5dc7732 1002 else
b93bbdcd 1003 tcstatus = other->tcs[other_tc].CP0_Debug_tcstatus;
f1aa6320
TS
1004
1005 /* XXX: Might be wrong, check with EJTAG spec. */
b93bbdcd 1006 return (other->CP0_Debug & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
b5dc7732 1007 (tcstatus & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
f1aa6320
TS
1008}
1009
1010#if defined(TARGET_MIPS64)
895c2d04 1011target_ulong helper_dmfc0_tcrestart(CPUMIPSState *env)
f1aa6320 1012{
b5dc7732 1013 return env->active_tc.PC;
f1aa6320
TS
1014}
1015
895c2d04 1016target_ulong helper_dmfc0_tchalt(CPUMIPSState *env)
f1aa6320 1017{
b5dc7732 1018 return env->active_tc.CP0_TCHalt;
f1aa6320
TS
1019}
1020
895c2d04 1021target_ulong helper_dmfc0_tccontext(CPUMIPSState *env)
f1aa6320 1022{
b5dc7732 1023 return env->active_tc.CP0_TCContext;
f1aa6320
TS
1024}
1025
895c2d04 1026target_ulong helper_dmfc0_tcschedule(CPUMIPSState *env)
f1aa6320 1027{
b5dc7732 1028 return env->active_tc.CP0_TCSchedule;
f1aa6320
TS
1029}
1030
895c2d04 1031target_ulong helper_dmfc0_tcschefback(CPUMIPSState *env)
f1aa6320 1032{
b5dc7732 1033 return env->active_tc.CP0_TCScheFBack;
f1aa6320
TS
1034}
1035
895c2d04 1036target_ulong helper_dmfc0_lladdr(CPUMIPSState *env)
f1aa6320 1037{
c7c7e1e9 1038 return env->CP0_LLAddr >> env->CP0_LLAddr_shift;
f1aa6320
TS
1039}
1040
f6d4dd81
YK
1041target_ulong helper_dmfc0_maar(CPUMIPSState *env)
1042{
1043 return env->CP0_MAAR[env->CP0_MAARI];
1044}
1045
895c2d04 1046target_ulong helper_dmfc0_watchlo(CPUMIPSState *env, uint32_t sel)
f1aa6320 1047{
be24bb4f 1048 return env->CP0_WatchLo[sel];
f1aa6320 1049}
5fb2dcd1
YK
1050
1051target_ulong helper_dmfc0_saar(CPUMIPSState *env)
1052{
1053 if ((env->CP0_SAARI & 0x3f) < 2) {
1054 return env->CP0_SAAR[env->CP0_SAARI & 0x3f];
1055 }
1056 return 0;
1057}
f1aa6320
TS
1058#endif /* TARGET_MIPS64 */
1059
895c2d04 1060void helper_mtc0_index(CPUMIPSState *env, target_ulong arg1)
f1aa6320 1061{
ba801af4
LA
1062 uint32_t index_p = env->CP0_Index & 0x80000000;
1063 uint32_t tlb_index = arg1 & 0x7fffffff;
1064 if (tlb_index < env->tlb->nb_tlb) {
1065 if (env->insn_flags & ISA_MIPS32R6) {
1066 index_p |= arg1 & 0x80000000;
1067 }
1068 env->CP0_Index = index_p | tlb_index;
1069 }
f1aa6320
TS
1070}
1071
895c2d04 1072void helper_mtc0_mvpcontrol(CPUMIPSState *env, target_ulong arg1)
f1aa6320
TS
1073{
1074 uint32_t mask = 0;
1075 uint32_t newval;
1076
1077 if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP))
1078 mask |= (1 << CP0MVPCo_CPA) | (1 << CP0MVPCo_VPC) |
1079 (1 << CP0MVPCo_EVP);
1080 if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1081 mask |= (1 << CP0MVPCo_STLB);
d9bea114 1082 newval = (env->mvp->CP0_MVPControl & ~mask) | (arg1 & mask);
f1aa6320
TS
1083
1084 // TODO: Enable/disable shared TLB, enable/disable VPEs.
1085
1086 env->mvp->CP0_MVPControl = newval;
1087}
1088
895c2d04 1089void helper_mtc0_vpecontrol(CPUMIPSState *env, target_ulong arg1)
f1aa6320
TS
1090{
1091 uint32_t mask;
1092 uint32_t newval;
1093
1094 mask = (1 << CP0VPECo_YSI) | (1 << CP0VPECo_GSI) |
1095 (1 << CP0VPECo_TE) | (0xff << CP0VPECo_TargTC);
d9bea114 1096 newval = (env->CP0_VPEControl & ~mask) | (arg1 & mask);
f1aa6320
TS
1097
1098 /* Yield scheduler intercept not implemented. */
1099 /* Gating storage scheduler intercept not implemented. */
1100
1101 // TODO: Enable/disable TCs.
1102
1103 env->CP0_VPEControl = newval;
1104}
1105
895c2d04 1106void helper_mttc0_vpecontrol(CPUMIPSState *env, target_ulong arg1)
5a25ce94
EI
1107{
1108 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
895c2d04 1109 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
5a25ce94
EI
1110 uint32_t mask;
1111 uint32_t newval;
1112
1113 mask = (1 << CP0VPECo_YSI) | (1 << CP0VPECo_GSI) |
1114 (1 << CP0VPECo_TE) | (0xff << CP0VPECo_TargTC);
1115 newval = (other->CP0_VPEControl & ~mask) | (arg1 & mask);
1116
1117 /* TODO: Enable/disable TCs. */
1118
1119 other->CP0_VPEControl = newval;
1120}
1121
895c2d04 1122target_ulong helper_mftc0_vpecontrol(CPUMIPSState *env)
5a25ce94
EI
1123{
1124 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
895c2d04 1125 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
5a25ce94
EI
1126 /* FIXME: Mask away return zero on read bits. */
1127 return other->CP0_VPEControl;
1128}
1129
895c2d04 1130target_ulong helper_mftc0_vpeconf0(CPUMIPSState *env)
5a25ce94
EI
1131{
1132 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
895c2d04 1133 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
5a25ce94
EI
1134
1135 return other->CP0_VPEConf0;
1136}
1137
895c2d04 1138void helper_mtc0_vpeconf0(CPUMIPSState *env, target_ulong arg1)
f1aa6320
TS
1139{
1140 uint32_t mask = 0;
1141 uint32_t newval;
1142
1143 if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) {
1144 if (env->CP0_VPEConf0 & (1 << CP0VPEC0_VPA))
1145 mask |= (0xff << CP0VPEC0_XTC);
1146 mask |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
1147 }
d9bea114 1148 newval = (env->CP0_VPEConf0 & ~mask) | (arg1 & mask);
f1aa6320
TS
1149
1150 // TODO: TC exclusive handling due to ERL/EXL.
1151
1152 env->CP0_VPEConf0 = newval;
1153}
1154
895c2d04 1155void helper_mttc0_vpeconf0(CPUMIPSState *env, target_ulong arg1)
5a25ce94
EI
1156{
1157 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
895c2d04 1158 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
5a25ce94
EI
1159 uint32_t mask = 0;
1160 uint32_t newval;
1161
1162 mask |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
1163 newval = (other->CP0_VPEConf0 & ~mask) | (arg1 & mask);
1164
1165 /* TODO: TC exclusive handling due to ERL/EXL. */
1166 other->CP0_VPEConf0 = newval;
1167}
1168
895c2d04 1169void helper_mtc0_vpeconf1(CPUMIPSState *env, target_ulong arg1)
f1aa6320
TS
1170{
1171 uint32_t mask = 0;
1172 uint32_t newval;
1173
1174 if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1175 mask |= (0xff << CP0VPEC1_NCX) | (0xff << CP0VPEC1_NCP2) |
1176 (0xff << CP0VPEC1_NCP1);
d9bea114 1177 newval = (env->CP0_VPEConf1 & ~mask) | (arg1 & mask);
f1aa6320
TS
1178
1179 /* UDI not implemented. */
1180 /* CP2 not implemented. */
1181
1182 // TODO: Handle FPU (CP1) binding.
1183
1184 env->CP0_VPEConf1 = newval;
1185}
1186
895c2d04 1187void helper_mtc0_yqmask(CPUMIPSState *env, target_ulong arg1)
f1aa6320
TS
1188{
1189 /* Yield qualifier inputs not implemented. */
1190 env->CP0_YQMask = 0x00000000;
1191}
1192
895c2d04 1193void helper_mtc0_vpeopt(CPUMIPSState *env, target_ulong arg1)
f1aa6320 1194{
d9bea114 1195 env->CP0_VPEOpt = arg1 & 0x0000ffff;
f1aa6320
TS
1196}
1197
e117f526
LA
1198#define MTC0_ENTRYLO_MASK(env) ((env->PAMask >> 6) & 0x3FFFFFFF)
1199
895c2d04 1200void helper_mtc0_entrylo0(CPUMIPSState *env, target_ulong arg1)
f1aa6320 1201{
f1aa6320 1202 /* 1k pages not implemented */
7207c7f9 1203 target_ulong rxi = arg1 & (env->CP0_PageGrain & (3u << CP0PG_XIE));
e117f526
LA
1204 env->CP0_EntryLo0 = (arg1 & MTC0_ENTRYLO_MASK(env))
1205 | (rxi << (CP0EnLo_XI - 30));
f1aa6320
TS
1206}
1207
7207c7f9 1208#if defined(TARGET_MIPS64)
e117f526
LA
1209#define DMTC0_ENTRYLO_MASK(env) (env->PAMask >> 6)
1210
7207c7f9
LA
1211void helper_dmtc0_entrylo0(CPUMIPSState *env, uint64_t arg1)
1212{
1213 uint64_t rxi = arg1 & ((env->CP0_PageGrain & (3ull << CP0PG_XIE)) << 32);
e117f526 1214 env->CP0_EntryLo0 = (arg1 & DMTC0_ENTRYLO_MASK(env)) | rxi;
7207c7f9
LA
1215}
1216#endif
1217
895c2d04 1218void helper_mtc0_tcstatus(CPUMIPSState *env, target_ulong arg1)
f1aa6320
TS
1219{
1220 uint32_t mask = env->CP0_TCStatus_rw_bitmask;
1221 uint32_t newval;
1222
d9bea114 1223 newval = (env->active_tc.CP0_TCStatus & ~mask) | (arg1 & mask);
f1aa6320 1224
b5dc7732 1225 env->active_tc.CP0_TCStatus = newval;
fe8dca8c 1226 sync_c0_tcstatus(env, env->current_tc, newval);
f1aa6320
TS
1227}
1228
895c2d04 1229void helper_mttc0_tcstatus(CPUMIPSState *env, target_ulong arg1)
f1aa6320
TS
1230{
1231 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
895c2d04 1232 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
f1aa6320 1233
b93bbdcd
EI
1234 if (other_tc == other->current_tc)
1235 other->active_tc.CP0_TCStatus = arg1;
b5dc7732 1236 else
b93bbdcd 1237 other->tcs[other_tc].CP0_TCStatus = arg1;
fe8dca8c 1238 sync_c0_tcstatus(other, other_tc, arg1);
f1aa6320
TS
1239}
1240
895c2d04 1241void helper_mtc0_tcbind(CPUMIPSState *env, target_ulong arg1)
f1aa6320
TS
1242{
1243 uint32_t mask = (1 << CP0TCBd_TBE);
1244 uint32_t newval;
1245
1246 if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1247 mask |= (1 << CP0TCBd_CurVPE);
d9bea114 1248 newval = (env->active_tc.CP0_TCBind & ~mask) | (arg1 & mask);
b5dc7732 1249 env->active_tc.CP0_TCBind = newval;
f1aa6320
TS
1250}
1251
895c2d04 1252void helper_mttc0_tcbind(CPUMIPSState *env, target_ulong arg1)
f1aa6320
TS
1253{
1254 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1255 uint32_t mask = (1 << CP0TCBd_TBE);
1256 uint32_t newval;
895c2d04 1257 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
f1aa6320 1258
b93bbdcd 1259 if (other->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
f1aa6320 1260 mask |= (1 << CP0TCBd_CurVPE);
b93bbdcd
EI
1261 if (other_tc == other->current_tc) {
1262 newval = (other->active_tc.CP0_TCBind & ~mask) | (arg1 & mask);
1263 other->active_tc.CP0_TCBind = newval;
b5dc7732 1264 } else {
b93bbdcd
EI
1265 newval = (other->tcs[other_tc].CP0_TCBind & ~mask) | (arg1 & mask);
1266 other->tcs[other_tc].CP0_TCBind = newval;
b5dc7732 1267 }
f1aa6320
TS
1268}
1269
895c2d04 1270void helper_mtc0_tcrestart(CPUMIPSState *env, target_ulong arg1)
f1aa6320 1271{
d9bea114 1272 env->active_tc.PC = arg1;
b5dc7732 1273 env->active_tc.CP0_TCStatus &= ~(1 << CP0TCSt_TDS);
c7c7e1e9
LA
1274 env->CP0_LLAddr = 0;
1275 env->lladdr = 0;
f1aa6320
TS
1276 /* MIPS16 not implemented. */
1277}
1278
895c2d04 1279void helper_mttc0_tcrestart(CPUMIPSState *env, target_ulong arg1)
f1aa6320
TS
1280{
1281 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
895c2d04 1282 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
f1aa6320 1283
b93bbdcd
EI
1284 if (other_tc == other->current_tc) {
1285 other->active_tc.PC = arg1;
1286 other->active_tc.CP0_TCStatus &= ~(1 << CP0TCSt_TDS);
c7c7e1e9
LA
1287 other->CP0_LLAddr = 0;
1288 other->lladdr = 0;
b5dc7732
TS
1289 /* MIPS16 not implemented. */
1290 } else {
b93bbdcd
EI
1291 other->tcs[other_tc].PC = arg1;
1292 other->tcs[other_tc].CP0_TCStatus &= ~(1 << CP0TCSt_TDS);
c7c7e1e9
LA
1293 other->CP0_LLAddr = 0;
1294 other->lladdr = 0;
b5dc7732
TS
1295 /* MIPS16 not implemented. */
1296 }
f1aa6320
TS
1297}
1298
895c2d04 1299void helper_mtc0_tchalt(CPUMIPSState *env, target_ulong arg1)
f1aa6320 1300{
135dd63a
AF
1301 MIPSCPU *cpu = mips_env_get_cpu(env);
1302
d9bea114 1303 env->active_tc.CP0_TCHalt = arg1 & 0x1;
f1aa6320
TS
1304
1305 // TODO: Halt TC / Restart (if allocated+active) TC.
f249412c 1306 if (env->active_tc.CP0_TCHalt & 1) {
c6679e90 1307 mips_tc_sleep(cpu, env->current_tc);
f249412c 1308 } else {
135dd63a 1309 mips_tc_wake(cpu, env->current_tc);
f249412c 1310 }
f1aa6320
TS
1311}
1312
895c2d04 1313void helper_mttc0_tchalt(CPUMIPSState *env, target_ulong arg1)
f1aa6320
TS
1314{
1315 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
895c2d04 1316 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
135dd63a 1317 MIPSCPU *other_cpu = mips_env_get_cpu(other);
f1aa6320
TS
1318
1319 // TODO: Halt TC / Restart (if allocated+active) TC.
1320
b93bbdcd
EI
1321 if (other_tc == other->current_tc)
1322 other->active_tc.CP0_TCHalt = arg1;
b5dc7732 1323 else
b93bbdcd 1324 other->tcs[other_tc].CP0_TCHalt = arg1;
f249412c
EI
1325
1326 if (arg1 & 1) {
c6679e90 1327 mips_tc_sleep(other_cpu, other_tc);
f249412c 1328 } else {
135dd63a 1329 mips_tc_wake(other_cpu, other_tc);
f249412c 1330 }
f1aa6320
TS
1331}
1332
895c2d04 1333void helper_mtc0_tccontext(CPUMIPSState *env, target_ulong arg1)
f1aa6320 1334{
d9bea114 1335 env->active_tc.CP0_TCContext = arg1;
f1aa6320
TS
1336}
1337
895c2d04 1338void helper_mttc0_tccontext(CPUMIPSState *env, target_ulong arg1)
f1aa6320
TS
1339{
1340 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
895c2d04 1341 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
f1aa6320 1342
b93bbdcd
EI
1343 if (other_tc == other->current_tc)
1344 other->active_tc.CP0_TCContext = arg1;
b5dc7732 1345 else
b93bbdcd 1346 other->tcs[other_tc].CP0_TCContext = arg1;
f1aa6320
TS
1347}
1348
895c2d04 1349void helper_mtc0_tcschedule(CPUMIPSState *env, target_ulong arg1)
f1aa6320 1350{
d9bea114 1351 env->active_tc.CP0_TCSchedule = arg1;
f1aa6320
TS
1352}
1353
895c2d04 1354void helper_mttc0_tcschedule(CPUMIPSState *env, target_ulong arg1)
f1aa6320
TS
1355{
1356 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
895c2d04 1357 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
f1aa6320 1358
b93bbdcd
EI
1359 if (other_tc == other->current_tc)
1360 other->active_tc.CP0_TCSchedule = arg1;
b5dc7732 1361 else
b93bbdcd 1362 other->tcs[other_tc].CP0_TCSchedule = arg1;
f1aa6320
TS
1363}
1364
895c2d04 1365void helper_mtc0_tcschefback(CPUMIPSState *env, target_ulong arg1)
f1aa6320 1366{
d9bea114 1367 env->active_tc.CP0_TCScheFBack = arg1;
f1aa6320
TS
1368}
1369
895c2d04 1370void helper_mttc0_tcschefback(CPUMIPSState *env, target_ulong arg1)
f1aa6320
TS
1371{
1372 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
895c2d04 1373 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
f1aa6320 1374
b93bbdcd
EI
1375 if (other_tc == other->current_tc)
1376 other->active_tc.CP0_TCScheFBack = arg1;
b5dc7732 1377 else
b93bbdcd 1378 other->tcs[other_tc].CP0_TCScheFBack = arg1;
f1aa6320
TS
1379}
1380
895c2d04 1381void helper_mtc0_entrylo1(CPUMIPSState *env, target_ulong arg1)
f1aa6320 1382{
f1aa6320 1383 /* 1k pages not implemented */
7207c7f9 1384 target_ulong rxi = arg1 & (env->CP0_PageGrain & (3u << CP0PG_XIE));
e117f526
LA
1385 env->CP0_EntryLo1 = (arg1 & MTC0_ENTRYLO_MASK(env))
1386 | (rxi << (CP0EnLo_XI - 30));
f1aa6320
TS
1387}
1388
7207c7f9
LA
1389#if defined(TARGET_MIPS64)
1390void helper_dmtc0_entrylo1(CPUMIPSState *env, uint64_t arg1)
1391{
1392 uint64_t rxi = arg1 & ((env->CP0_PageGrain & (3ull << CP0PG_XIE)) << 32);
e117f526 1393 env->CP0_EntryLo1 = (arg1 & DMTC0_ENTRYLO_MASK(env)) | rxi;
7207c7f9
LA
1394}
1395#endif
1396
895c2d04 1397void helper_mtc0_context(CPUMIPSState *env, target_ulong arg1)
f1aa6320 1398{
d9bea114 1399 env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (arg1 & ~0x007FFFFF);
f1aa6320
TS
1400}
1401
074cfcb4 1402void update_pagemask(CPUMIPSState *env, target_ulong arg1, int32_t *pagemask)
f1aa6320 1403{
ba801af4
LA
1404 uint64_t mask = arg1 >> (TARGET_PAGE_BITS + 1);
1405 if (!(env->insn_flags & ISA_MIPS32R6) || (arg1 == ~0) ||
1406 (mask == 0x0000 || mask == 0x0003 || mask == 0x000F ||
1407 mask == 0x003F || mask == 0x00FF || mask == 0x03FF ||
1408 mask == 0x0FFF || mask == 0x3FFF || mask == 0xFFFF)) {
1409 env->CP0_PageMask = arg1 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
1410 }
f1aa6320
TS
1411}
1412
074cfcb4
YK
1413void helper_mtc0_pagemask(CPUMIPSState *env, target_ulong arg1)
1414{
1415 update_pagemask(env, arg1, &env->CP0_PageMask);
1416}
1417
895c2d04 1418void helper_mtc0_pagegrain(CPUMIPSState *env, target_ulong arg1)
f1aa6320
TS
1419{
1420 /* SmartMIPS not implemented */
f1aa6320 1421 /* 1k pages not implemented */
7207c7f9
LA
1422 env->CP0_PageGrain = (arg1 & env->CP0_PageGrain_rw_bitmask) |
1423 (env->CP0_PageGrain & ~env->CP0_PageGrain_rw_bitmask);
e117f526
LA
1424 compute_hflags(env);
1425 restore_pamask(env);
f1aa6320
TS
1426}
1427
cec56a73
JH
1428void helper_mtc0_segctl0(CPUMIPSState *env, target_ulong arg1)
1429{
1430 CPUState *cs = CPU(mips_env_get_cpu(env));
1431
1432 env->CP0_SegCtl0 = arg1 & CP0SC0_MASK;
1433 tlb_flush(cs);
1434}
1435
1436void helper_mtc0_segctl1(CPUMIPSState *env, target_ulong arg1)
1437{
1438 CPUState *cs = CPU(mips_env_get_cpu(env));
1439
1440 env->CP0_SegCtl1 = arg1 & CP0SC1_MASK;
1441 tlb_flush(cs);
1442}
1443
1444void helper_mtc0_segctl2(CPUMIPSState *env, target_ulong arg1)
1445{
1446 CPUState *cs = CPU(mips_env_get_cpu(env));
1447
1448 env->CP0_SegCtl2 = arg1 & CP0SC2_MASK;
1449 tlb_flush(cs);
1450}
1451
fa75ad14
YK
1452void helper_mtc0_pwfield(CPUMIPSState *env, target_ulong arg1)
1453{
1454#if defined(TARGET_MIPS64)
1455 uint64_t mask = 0x3F3FFFFFFFULL;
1456 uint32_t old_ptei = (env->CP0_PWField >> CP0PF_PTEI) & 0x3FULL;
1457 uint32_t new_ptei = (arg1 >> CP0PF_PTEI) & 0x3FULL;
1458
1459 if ((env->insn_flags & ISA_MIPS32R6)) {
1460 if (((arg1 >> CP0PF_BDI) & 0x3FULL) < 12) {
1461 mask &= ~(0x3FULL << CP0PF_BDI);
1462 }
1463 if (((arg1 >> CP0PF_GDI) & 0x3FULL) < 12) {
1464 mask &= ~(0x3FULL << CP0PF_GDI);
1465 }
1466 if (((arg1 >> CP0PF_UDI) & 0x3FULL) < 12) {
1467 mask &= ~(0x3FULL << CP0PF_UDI);
1468 }
1469 if (((arg1 >> CP0PF_MDI) & 0x3FULL) < 12) {
1470 mask &= ~(0x3FULL << CP0PF_MDI);
1471 }
1472 if (((arg1 >> CP0PF_PTI) & 0x3FULL) < 12) {
1473 mask &= ~(0x3FULL << CP0PF_PTI);
1474 }
1475 }
1476 env->CP0_PWField = arg1 & mask;
1477
1478 if ((new_ptei >= 32) ||
1479 ((env->insn_flags & ISA_MIPS32R6) &&
1480 (new_ptei == 0 || new_ptei == 1))) {
1481 env->CP0_PWField = (env->CP0_PWField & ~0x3FULL) |
1482 (old_ptei << CP0PF_PTEI);
1483 }
1484#else
1485 uint32_t mask = 0x3FFFFFFF;
1486 uint32_t old_ptew = (env->CP0_PWField >> CP0PF_PTEW) & 0x3F;
1487 uint32_t new_ptew = (arg1 >> CP0PF_PTEW) & 0x3F;
1488
1489 if ((env->insn_flags & ISA_MIPS32R6)) {
1490 if (((arg1 >> CP0PF_GDW) & 0x3F) < 12) {
1491 mask &= ~(0x3F << CP0PF_GDW);
1492 }
1493 if (((arg1 >> CP0PF_UDW) & 0x3F) < 12) {
1494 mask &= ~(0x3F << CP0PF_UDW);
1495 }
1496 if (((arg1 >> CP0PF_MDW) & 0x3F) < 12) {
1497 mask &= ~(0x3F << CP0PF_MDW);
1498 }
1499 if (((arg1 >> CP0PF_PTW) & 0x3F) < 12) {
1500 mask &= ~(0x3F << CP0PF_PTW);
1501 }
1502 }
1503 env->CP0_PWField = arg1 & mask;
1504
1505 if ((new_ptew >= 32) ||
1506 ((env->insn_flags & ISA_MIPS32R6) &&
1507 (new_ptew == 0 || new_ptew == 1))) {
1508 env->CP0_PWField = (env->CP0_PWField & ~0x3F) |
1509 (old_ptew << CP0PF_PTEW);
1510 }
1511#endif
1512}
1513
20b28ebc
YK
1514void helper_mtc0_pwsize(CPUMIPSState *env, target_ulong arg1)
1515{
1516#if defined(TARGET_MIPS64)
1517 env->CP0_PWSize = arg1 & 0x3F7FFFFFFFULL;
1518#else
1519 env->CP0_PWSize = arg1 & 0x3FFFFFFF;
1520#endif
1521}
1522
895c2d04 1523void helper_mtc0_wired(CPUMIPSState *env, target_ulong arg1)
f1aa6320 1524{
ba801af4
LA
1525 if (env->insn_flags & ISA_MIPS32R6) {
1526 if (arg1 < env->tlb->nb_tlb) {
1527 env->CP0_Wired = arg1;
1528 }
1529 } else {
1530 env->CP0_Wired = arg1 % env->tlb->nb_tlb;
1531 }
f1aa6320
TS
1532}
1533
103be64c
YK
1534void helper_mtc0_pwctl(CPUMIPSState *env, target_ulong arg1)
1535{
1536#if defined(TARGET_MIPS64)
1537 /* PWEn = 0. Hardware page table walking is not implemented. */
1538 env->CP0_PWCtl = (env->CP0_PWCtl & 0x000000C0) | (arg1 & 0x5C00003F);
1539#else
1540 env->CP0_PWCtl = (arg1 & 0x800000FF);
1541#endif
1542}
1543
895c2d04 1544void helper_mtc0_srsconf0(CPUMIPSState *env, target_ulong arg1)
f1aa6320 1545{
d9bea114 1546 env->CP0_SRSConf0 |= arg1 & env->CP0_SRSConf0_rw_bitmask;
f1aa6320
TS
1547}
1548
895c2d04 1549void helper_mtc0_srsconf1(CPUMIPSState *env, target_ulong arg1)
f1aa6320 1550{
d9bea114 1551 env->CP0_SRSConf1 |= arg1 & env->CP0_SRSConf1_rw_bitmask;
f1aa6320
TS
1552}
1553
895c2d04 1554void helper_mtc0_srsconf2(CPUMIPSState *env, target_ulong arg1)
f1aa6320 1555{
d9bea114 1556 env->CP0_SRSConf2 |= arg1 & env->CP0_SRSConf2_rw_bitmask;
f1aa6320
TS
1557}
1558
895c2d04 1559void helper_mtc0_srsconf3(CPUMIPSState *env, target_ulong arg1)
f1aa6320 1560{
d9bea114 1561 env->CP0_SRSConf3 |= arg1 & env->CP0_SRSConf3_rw_bitmask;
f1aa6320
TS
1562}
1563
895c2d04 1564void helper_mtc0_srsconf4(CPUMIPSState *env, target_ulong arg1)
f1aa6320 1565{
d9bea114 1566 env->CP0_SRSConf4 |= arg1 & env->CP0_SRSConf4_rw_bitmask;
f1aa6320
TS
1567}
1568
895c2d04 1569void helper_mtc0_hwrena(CPUMIPSState *env, target_ulong arg1)
f1aa6320 1570{
d279279e
PJ
1571 uint32_t mask = 0x0000000F;
1572
b00c7218
YK
1573 if ((env->CP0_Config1 & (1 << CP0C1_PC)) &&
1574 (env->insn_flags & ISA_MIPS32R6)) {
1575 mask |= (1 << 4);
1576 }
1577 if (env->insn_flags & ISA_MIPS32R6) {
1578 mask |= (1 << 5);
1579 }
d279279e
PJ
1580 if (env->CP0_Config3 & (1 << CP0C3_ULRI)) {
1581 mask |= (1 << 29);
1582
1583 if (arg1 & (1 << 29)) {
1584 env->hflags |= MIPS_HFLAG_HWRENA_ULR;
1585 } else {
1586 env->hflags &= ~MIPS_HFLAG_HWRENA_ULR;
1587 }
1588 }
1589
1590 env->CP0_HWREna = arg1 & mask;
f1aa6320
TS
1591}
1592
895c2d04 1593void helper_mtc0_count(CPUMIPSState *env, target_ulong arg1)
f1aa6320 1594{
d9bea114 1595 cpu_mips_store_count(env, arg1);
f1aa6320
TS
1596}
1597
5fb2dcd1
YK
1598void helper_mtc0_saari(CPUMIPSState *env, target_ulong arg1)
1599{
1600 uint32_t target = arg1 & 0x3f;
1601 if (target <= 1) {
1602 env->CP0_SAARI = target;
1603 }
1604}
1605
1606void helper_mtc0_saar(CPUMIPSState *env, target_ulong arg1)
1607{
1608 uint32_t target = env->CP0_SAARI & 0x3f;
1609 if (target < 2) {
1610 env->CP0_SAAR[target] = arg1 & 0x00000ffffffff03fULL;
043715d1
YK
1611 switch (target) {
1612 case 0:
1613 if (env->itu) {
1614 itc_reconfigure(env->itu);
1615 }
1616 break;
1617 }
5fb2dcd1
YK
1618 }
1619}
1620
1621void helper_mthc0_saar(CPUMIPSState *env, target_ulong arg1)
1622{
1623 uint32_t target = env->CP0_SAARI & 0x3f;
1624 if (target < 2) {
1625 env->CP0_SAAR[target] =
1626 (((uint64_t) arg1 << 32) & 0x00000fff00000000ULL) |
1627 (env->CP0_SAAR[target] & 0x00000000ffffffffULL);
043715d1
YK
1628 switch (target) {
1629 case 0:
1630 if (env->itu) {
1631 itc_reconfigure(env->itu);
1632 }
1633 break;
1634 }
5fb2dcd1
YK
1635 }
1636}
1637
895c2d04 1638void helper_mtc0_entryhi(CPUMIPSState *env, target_ulong arg1)
f1aa6320 1639{
9456c2fb 1640 target_ulong old, val, mask;
6ec98bd7 1641 mask = (TARGET_PAGE_MASK << 1) | env->CP0_EntryHi_ASID_mask;
9456c2fb
LA
1642 if (((env->CP0_Config4 >> CP0C4_IE) & 0x3) >= 2) {
1643 mask |= 1 << CP0EnHi_EHINV;
1644 }
f1aa6320
TS
1645
1646 /* 1k pages not implemented */
f1aa6320 1647#if defined(TARGET_MIPS64)
ba801af4
LA
1648 if (env->insn_flags & ISA_MIPS32R6) {
1649 int entryhi_r = extract64(arg1, 62, 2);
1650 int config0_at = extract32(env->CP0_Config0, 13, 2);
1651 bool no_supervisor = (env->CP0_Status_rw_bitmask & 0x8) == 0;
1652 if ((entryhi_r == 2) ||
1653 (entryhi_r == 1 && (no_supervisor || config0_at == 1))) {
1654 /* skip EntryHi.R field if new value is reserved */
1655 mask &= ~(0x3ull << 62);
1656 }
1657 }
1658 mask &= env->SEGMask;
f1aa6320
TS
1659#endif
1660 old = env->CP0_EntryHi;
ba801af4 1661 val = (arg1 & mask) | (old & ~mask);
f1aa6320
TS
1662 env->CP0_EntryHi = val;
1663 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
fe8dca8c 1664 sync_c0_entryhi(env, env->current_tc);
f1aa6320
TS
1665 }
1666 /* If the ASID changes, flush qemu's TLB. */
6ec98bd7
PB
1667 if ((old & env->CP0_EntryHi_ASID_mask) !=
1668 (val & env->CP0_EntryHi_ASID_mask)) {
9658e4c3 1669 tlb_flush(CPU(mips_env_get_cpu(env)));
6ec98bd7 1670 }
f1aa6320
TS
1671}
1672
895c2d04 1673void helper_mttc0_entryhi(CPUMIPSState *env, target_ulong arg1)
f1aa6320
TS
1674{
1675 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
895c2d04 1676 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
f1aa6320 1677
fe8dca8c
EI
1678 other->CP0_EntryHi = arg1;
1679 sync_c0_entryhi(other, other_tc);
f1aa6320
TS
1680}
1681
895c2d04 1682void helper_mtc0_compare(CPUMIPSState *env, target_ulong arg1)
f1aa6320 1683{
d9bea114 1684 cpu_mips_store_compare(env, arg1);
f1aa6320
TS
1685}
1686
895c2d04 1687void helper_mtc0_status(CPUMIPSState *env, target_ulong arg1)
f1aa6320 1688{
a47dddd7 1689 MIPSCPU *cpu = mips_env_get_cpu(env);
f1aa6320 1690 uint32_t val, old;
ba801af4 1691
f1aa6320 1692 old = env->CP0_Status;
81a423e6
MR
1693 cpu_mips_store_status(env, arg1);
1694 val = env->CP0_Status;
fe8dca8c 1695
c01fccd2
AJ
1696 if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
1697 qemu_log("Status %08x (%08x) => %08x (%08x) Cause %08x",
1698 old, old & env->CP0_Cause & CP0Ca_IP_mask,
1699 val, val & env->CP0_Cause & CP0Ca_IP_mask,
1700 env->CP0_Cause);
b0fc6003 1701 switch (cpu_mmu_index(env, false)) {
42c86612
JH
1702 case 3:
1703 qemu_log(", ERL\n");
1704 break;
c01fccd2
AJ
1705 case MIPS_HFLAG_UM: qemu_log(", UM\n"); break;
1706 case MIPS_HFLAG_SM: qemu_log(", SM\n"); break;
1707 case MIPS_HFLAG_KM: qemu_log("\n"); break;
a47dddd7
AF
1708 default:
1709 cpu_abort(CPU(cpu), "Invalid MMU mode!\n");
1710 break;
31e3104f 1711 }
c01fccd2 1712 }
f1aa6320
TS
1713}
1714
895c2d04 1715void helper_mttc0_status(CPUMIPSState *env, target_ulong arg1)
f1aa6320
TS
1716{
1717 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1d725ae9 1718 uint32_t mask = env->CP0_Status_rw_bitmask & ~0xf1000018;
895c2d04 1719 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
f1aa6320 1720
1d725ae9 1721 other->CP0_Status = (other->CP0_Status & ~mask) | (arg1 & mask);
895c2d04 1722 sync_c0_status(env, other, other_tc);
f1aa6320
TS
1723}
1724
895c2d04 1725void helper_mtc0_intctl(CPUMIPSState *env, target_ulong arg1)
f1aa6320 1726{
bc45a67a 1727 env->CP0_IntCtl = (env->CP0_IntCtl & ~0x000003e0) | (arg1 & 0x000003e0);
f1aa6320
TS
1728}
1729
895c2d04 1730void helper_mtc0_srsctl(CPUMIPSState *env, target_ulong arg1)
f1aa6320
TS
1731{
1732 uint32_t mask = (0xf << CP0SRSCtl_ESS) | (0xf << CP0SRSCtl_PSS);
d9bea114 1733 env->CP0_SRSCtl = (env->CP0_SRSCtl & ~mask) | (arg1 & mask);
f1aa6320
TS
1734}
1735
895c2d04 1736void helper_mtc0_cause(CPUMIPSState *env, target_ulong arg1)
5a25ce94 1737{
81a423e6 1738 cpu_mips_store_cause(env, arg1);
5a25ce94
EI
1739}
1740
895c2d04 1741void helper_mttc0_cause(CPUMIPSState *env, target_ulong arg1)
5a25ce94
EI
1742{
1743 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
895c2d04 1744 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
5a25ce94 1745
81a423e6 1746 cpu_mips_store_cause(other, arg1);
5a25ce94
EI
1747}
1748
895c2d04 1749target_ulong helper_mftc0_epc(CPUMIPSState *env)
5a25ce94
EI
1750{
1751 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
895c2d04 1752 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
5a25ce94
EI
1753
1754 return other->CP0_EPC;
1755}
1756
895c2d04 1757target_ulong helper_mftc0_ebase(CPUMIPSState *env)
5a25ce94
EI
1758{
1759 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
895c2d04 1760 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
5a25ce94
EI
1761
1762 return other->CP0_EBase;
1763}
1764
895c2d04 1765void helper_mtc0_ebase(CPUMIPSState *env, target_ulong arg1)
f1aa6320 1766{
74dbf824
JH
1767 target_ulong mask = 0x3FFFF000 | env->CP0_EBaseWG_rw_bitmask;
1768 if (arg1 & env->CP0_EBaseWG_rw_bitmask) {
1769 mask |= ~0x3FFFFFFF;
1770 }
1771 env->CP0_EBase = (env->CP0_EBase & ~mask) | (arg1 & mask);
f1aa6320
TS
1772}
1773
895c2d04 1774void helper_mttc0_ebase(CPUMIPSState *env, target_ulong arg1)
5a25ce94
EI
1775{
1776 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
895c2d04 1777 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
74dbf824
JH
1778 target_ulong mask = 0x3FFFF000 | env->CP0_EBaseWG_rw_bitmask;
1779 if (arg1 & env->CP0_EBaseWG_rw_bitmask) {
1780 mask |= ~0x3FFFFFFF;
1781 }
1782 other->CP0_EBase = (other->CP0_EBase & ~mask) | (arg1 & mask);
5a25ce94
EI
1783}
1784
895c2d04 1785target_ulong helper_mftc0_configx(CPUMIPSState *env, target_ulong idx)
5a25ce94
EI
1786{
1787 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
895c2d04 1788 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
5a25ce94
EI
1789
1790 switch (idx) {
1791 case 0: return other->CP0_Config0;
1792 case 1: return other->CP0_Config1;
1793 case 2: return other->CP0_Config2;
1794 case 3: return other->CP0_Config3;
1795 /* 4 and 5 are reserved. */
1796 case 6: return other->CP0_Config6;
1797 case 7: return other->CP0_Config7;
1798 default:
1799 break;
1800 }
1801 return 0;
1802}
1803
895c2d04 1804void helper_mtc0_config0(CPUMIPSState *env, target_ulong arg1)
f1aa6320 1805{
d9bea114 1806 env->CP0_Config0 = (env->CP0_Config0 & 0x81FFFFF8) | (arg1 & 0x00000007);
f1aa6320
TS
1807}
1808
895c2d04 1809void helper_mtc0_config2(CPUMIPSState *env, target_ulong arg1)
f1aa6320
TS
1810{
1811 /* tertiary/secondary caches not implemented */
1812 env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF);
1813}
1814
90f12d73
MR
1815void helper_mtc0_config3(CPUMIPSState *env, target_ulong arg1)
1816{
1817 if (env->insn_flags & ASE_MICROMIPS) {
1818 env->CP0_Config3 = (env->CP0_Config3 & ~(1 << CP0C3_ISA_ON_EXC)) |
1819 (arg1 & (1 << CP0C3_ISA_ON_EXC));
1820 }
1821}
1822
b4160af1
PJ
1823void helper_mtc0_config4(CPUMIPSState *env, target_ulong arg1)
1824{
1825 env->CP0_Config4 = (env->CP0_Config4 & (~env->CP0_Config4_rw_bitmask)) |
1826 (arg1 & env->CP0_Config4_rw_bitmask);
1827}
1828
b4dd99a3
PJ
1829void helper_mtc0_config5(CPUMIPSState *env, target_ulong arg1)
1830{
1831 env->CP0_Config5 = (env->CP0_Config5 & (~env->CP0_Config5_rw_bitmask)) |
1832 (arg1 & env->CP0_Config5_rw_bitmask);
e97a391d 1833 compute_hflags(env);
b4dd99a3
PJ
1834}
1835
895c2d04 1836void helper_mtc0_lladdr(CPUMIPSState *env, target_ulong arg1)
2a6e32dd
AJ
1837{
1838 target_long mask = env->CP0_LLAddr_rw_bitmask;
1839 arg1 = arg1 << env->CP0_LLAddr_shift;
c7c7e1e9 1840 env->CP0_LLAddr = (env->CP0_LLAddr & ~mask) | (arg1 & mask);
2a6e32dd
AJ
1841}
1842
f6d4dd81
YK
1843#define MTC0_MAAR_MASK(env) \
1844 ((0x1ULL << 63) | ((env->PAMask >> 4) & ~0xFFFull) | 0x3)
1845
1846void helper_mtc0_maar(CPUMIPSState *env, target_ulong arg1)
1847{
1848 env->CP0_MAAR[env->CP0_MAARI] = arg1 & MTC0_MAAR_MASK(env);
1849}
1850
1851void helper_mthc0_maar(CPUMIPSState *env, target_ulong arg1)
1852{
1853 env->CP0_MAAR[env->CP0_MAARI] =
1854 (((uint64_t) arg1 << 32) & MTC0_MAAR_MASK(env)) |
1855 (env->CP0_MAAR[env->CP0_MAARI] & 0x00000000ffffffffULL);
1856}
1857
1858void helper_mtc0_maari(CPUMIPSState *env, target_ulong arg1)
1859{
1860 int index = arg1 & 0x3f;
1861 if (index == 0x3f) {
1862 /* Software may write all ones to INDEX to determine the
1863 maximum value supported. */
1864 env->CP0_MAARI = MIPS_MAAR_MAX - 1;
1865 } else if (index < MIPS_MAAR_MAX) {
1866 env->CP0_MAARI = index;
1867 }
1868 /* Other than the all ones, if the
1869 value written is not supported, then INDEX is unchanged
1870 from its previous value. */
1871}
1872
895c2d04 1873void helper_mtc0_watchlo(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
f1aa6320
TS
1874{
1875 /* Watch exceptions for instructions, data loads, data stores
1876 not implemented. */
d9bea114 1877 env->CP0_WatchLo[sel] = (arg1 & ~0x7);
f1aa6320
TS
1878}
1879
895c2d04 1880void helper_mtc0_watchhi(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
f1aa6320 1881{
6ec98bd7
PB
1882 int mask = 0x40000FF8 | (env->CP0_EntryHi_ASID_mask << CP0WH_ASID);
1883 env->CP0_WatchHi[sel] = arg1 & mask;
d9bea114 1884 env->CP0_WatchHi[sel] &= ~(env->CP0_WatchHi[sel] & arg1 & 0x7);
f1aa6320
TS
1885}
1886
895c2d04 1887void helper_mtc0_xcontext(CPUMIPSState *env, target_ulong arg1)
f1aa6320
TS
1888{
1889 target_ulong mask = (1ULL << (env->SEGBITS - 7)) - 1;
d9bea114 1890 env->CP0_XContext = (env->CP0_XContext & mask) | (arg1 & ~mask);
f1aa6320
TS
1891}
1892
895c2d04 1893void helper_mtc0_framemask(CPUMIPSState *env, target_ulong arg1)
f1aa6320 1894{
d9bea114 1895 env->CP0_Framemask = arg1; /* XXX */
f1aa6320
TS
1896}
1897
895c2d04 1898void helper_mtc0_debug(CPUMIPSState *env, target_ulong arg1)
f1aa6320 1899{
d9bea114
AJ
1900 env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (arg1 & 0x13300120);
1901 if (arg1 & (1 << CP0DB_DM))
f1aa6320
TS
1902 env->hflags |= MIPS_HFLAG_DM;
1903 else
1904 env->hflags &= ~MIPS_HFLAG_DM;
1905}
1906
895c2d04 1907void helper_mttc0_debug(CPUMIPSState *env, target_ulong arg1)
f1aa6320
TS
1908{
1909 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
d9bea114 1910 uint32_t val = arg1 & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt));
895c2d04 1911 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
f1aa6320
TS
1912
1913 /* XXX: Might be wrong, check with EJTAG spec. */
b93bbdcd
EI
1914 if (other_tc == other->current_tc)
1915 other->active_tc.CP0_Debug_tcstatus = val;
b5dc7732 1916 else
b93bbdcd
EI
1917 other->tcs[other_tc].CP0_Debug_tcstatus = val;
1918 other->CP0_Debug = (other->CP0_Debug &
1919 ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
d9bea114 1920 (arg1 & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
f1aa6320
TS
1921}
1922
895c2d04 1923void helper_mtc0_performance0(CPUMIPSState *env, target_ulong arg1)
f1aa6320 1924{
d9bea114 1925 env->CP0_Performance0 = arg1 & 0x000007ff;
f1aa6320
TS
1926}
1927
0d74a222
LA
1928void helper_mtc0_errctl(CPUMIPSState *env, target_ulong arg1)
1929{
1930 int32_t wst = arg1 & (1 << CP0EC_WST);
1931 int32_t spr = arg1 & (1 << CP0EC_SPR);
1932 int32_t itc = env->itc_tag ? (arg1 & (1 << CP0EC_ITC)) : 0;
1933
1934 env->CP0_ErrCtl = wst | spr | itc;
1935
1936 if (itc && !wst && !spr) {
1937 env->hflags |= MIPS_HFLAG_ITC_CACHE;
1938 } else {
1939 env->hflags &= ~MIPS_HFLAG_ITC_CACHE;
1940 }
1941}
1942
895c2d04 1943void helper_mtc0_taglo(CPUMIPSState *env, target_ulong arg1)
f1aa6320 1944{
0d74a222
LA
1945 if (env->hflags & MIPS_HFLAG_ITC_CACHE) {
1946 /* If CACHE instruction is configured for ITC tags then make all
1947 CP0.TagLo bits writable. The actual write to ITC Configuration
1948 Tag will take care of the read-only bits. */
1949 env->CP0_TagLo = arg1;
1950 } else {
1951 env->CP0_TagLo = arg1 & 0xFFFFFCF6;
1952 }
f1aa6320
TS
1953}
1954
895c2d04 1955void helper_mtc0_datalo(CPUMIPSState *env, target_ulong arg1)
f1aa6320 1956{
d9bea114 1957 env->CP0_DataLo = arg1; /* XXX */
f1aa6320
TS
1958}
1959
895c2d04 1960void helper_mtc0_taghi(CPUMIPSState *env, target_ulong arg1)
f1aa6320 1961{
d9bea114 1962 env->CP0_TagHi = arg1; /* XXX */
f1aa6320
TS
1963}
1964
895c2d04 1965void helper_mtc0_datahi(CPUMIPSState *env, target_ulong arg1)
f1aa6320 1966{
d9bea114 1967 env->CP0_DataHi = arg1; /* XXX */
f1aa6320
TS
1968}
1969
f1aa6320 1970/* MIPS MT functions */
895c2d04 1971target_ulong helper_mftgpr(CPUMIPSState *env, uint32_t sel)
f1aa6320
TS
1972{
1973 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
895c2d04 1974 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
f1aa6320 1975
b93bbdcd
EI
1976 if (other_tc == other->current_tc)
1977 return other->active_tc.gpr[sel];
b5dc7732 1978 else
b93bbdcd 1979 return other->tcs[other_tc].gpr[sel];
f1aa6320
TS
1980}
1981
895c2d04 1982target_ulong helper_mftlo(CPUMIPSState *env, uint32_t sel)
f1aa6320
TS
1983{
1984 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
895c2d04 1985 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
f1aa6320 1986
b93bbdcd
EI
1987 if (other_tc == other->current_tc)
1988 return other->active_tc.LO[sel];
b5dc7732 1989 else
b93bbdcd 1990 return other->tcs[other_tc].LO[sel];
f1aa6320
TS
1991}
1992
895c2d04 1993target_ulong helper_mfthi(CPUMIPSState *env, uint32_t sel)
f1aa6320
TS
1994{
1995 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
895c2d04 1996 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
f1aa6320 1997
b93bbdcd
EI
1998 if (other_tc == other->current_tc)
1999 return other->active_tc.HI[sel];
b5dc7732 2000 else
b93bbdcd 2001 return other->tcs[other_tc].HI[sel];
f1aa6320
TS
2002}
2003
895c2d04 2004target_ulong helper_mftacx(CPUMIPSState *env, uint32_t sel)
f1aa6320
TS
2005{
2006 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
895c2d04 2007 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
f1aa6320 2008
b93bbdcd
EI
2009 if (other_tc == other->current_tc)
2010 return other->active_tc.ACX[sel];
b5dc7732 2011 else
b93bbdcd 2012 return other->tcs[other_tc].ACX[sel];
f1aa6320
TS
2013}
2014
895c2d04 2015target_ulong helper_mftdsp(CPUMIPSState *env)
f1aa6320
TS
2016{
2017 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
895c2d04 2018 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
f1aa6320 2019
b93bbdcd
EI
2020 if (other_tc == other->current_tc)
2021 return other->active_tc.DSPControl;
b5dc7732 2022 else
b93bbdcd 2023 return other->tcs[other_tc].DSPControl;
f1aa6320 2024}
6af0bf9c 2025
895c2d04 2026void helper_mttgpr(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
f1aa6320
TS
2027{
2028 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
895c2d04 2029 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
f1aa6320 2030
b93bbdcd
EI
2031 if (other_tc == other->current_tc)
2032 other->active_tc.gpr[sel] = arg1;
b5dc7732 2033 else
b93bbdcd 2034 other->tcs[other_tc].gpr[sel] = arg1;
f1aa6320
TS
2035}
2036
895c2d04 2037void helper_mttlo(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
f1aa6320
TS
2038{
2039 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
895c2d04 2040 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
f1aa6320 2041
b93bbdcd
EI
2042 if (other_tc == other->current_tc)
2043 other->active_tc.LO[sel] = arg1;
b5dc7732 2044 else
b93bbdcd 2045 other->tcs[other_tc].LO[sel] = arg1;
f1aa6320
TS
2046}
2047
895c2d04 2048void helper_mtthi(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
f1aa6320
TS
2049{
2050 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
895c2d04 2051 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
f1aa6320 2052
b93bbdcd
EI
2053 if (other_tc == other->current_tc)
2054 other->active_tc.HI[sel] = arg1;
b5dc7732 2055 else
b93bbdcd 2056 other->tcs[other_tc].HI[sel] = arg1;
f1aa6320
TS
2057}
2058
895c2d04 2059void helper_mttacx(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
f1aa6320
TS
2060{
2061 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
895c2d04 2062 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
f1aa6320 2063
b93bbdcd
EI
2064 if (other_tc == other->current_tc)
2065 other->active_tc.ACX[sel] = arg1;
b5dc7732 2066 else
b93bbdcd 2067 other->tcs[other_tc].ACX[sel] = arg1;
f1aa6320
TS
2068}
2069
895c2d04 2070void helper_mttdsp(CPUMIPSState *env, target_ulong arg1)
f1aa6320
TS
2071{
2072 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
895c2d04 2073 CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
f1aa6320 2074
b93bbdcd
EI
2075 if (other_tc == other->current_tc)
2076 other->active_tc.DSPControl = arg1;
b5dc7732 2077 else
b93bbdcd 2078 other->tcs[other_tc].DSPControl = arg1;
f1aa6320
TS
2079}
2080
2081/* MIPS MT functions */
9ed5726c 2082target_ulong helper_dmt(void)
f1aa6320
TS
2083{
2084 // TODO
9ed5726c 2085 return 0;
f1aa6320
TS
2086}
2087
9ed5726c 2088target_ulong helper_emt(void)
f1aa6320
TS
2089{
2090 // TODO
9ed5726c 2091 return 0;
f1aa6320
TS
2092}
2093
895c2d04 2094target_ulong helper_dvpe(CPUMIPSState *env)
f1aa6320 2095{
182735ef 2096 CPUState *other_cs = first_cpu;
f249412c
EI
2097 target_ulong prev = env->mvp->CP0_MVPControl;
2098
bdc44640 2099 CPU_FOREACH(other_cs) {
182735ef 2100 MIPSCPU *other_cpu = MIPS_CPU(other_cs);
f249412c 2101 /* Turn off all VPEs except the one executing the dvpe. */
182735ef
AF
2102 if (&other_cpu->env != env) {
2103 other_cpu->env.mvp->CP0_MVPControl &= ~(1 << CP0MVPCo_EVP);
6f4d6b09 2104 mips_vpe_sleep(other_cpu);
f249412c 2105 }
bdc44640 2106 }
f249412c 2107 return prev;
f1aa6320
TS
2108}
2109
895c2d04 2110target_ulong helper_evpe(CPUMIPSState *env)
f1aa6320 2111{
182735ef 2112 CPUState *other_cs = first_cpu;
f249412c
EI
2113 target_ulong prev = env->mvp->CP0_MVPControl;
2114
bdc44640 2115 CPU_FOREACH(other_cs) {
182735ef 2116 MIPSCPU *other_cpu = MIPS_CPU(other_cs);
b35d77d7 2117
182735ef 2118 if (&other_cpu->env != env
81bad50e 2119 /* If the VPE is WFI, don't disturb its sleep. */
b35d77d7 2120 && !mips_vpe_is_wfi(other_cpu)) {
f249412c 2121 /* Enable the VPE. */
182735ef 2122 other_cpu->env.mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
c3affe56 2123 mips_vpe_wake(other_cpu); /* And wake it up. */
f249412c 2124 }
bdc44640 2125 }
f249412c 2126 return prev;
f1aa6320 2127}
f9480ffc 2128#endif /* !CONFIG_USER_ONLY */
f1aa6320 2129
d9bea114 2130void helper_fork(target_ulong arg1, target_ulong arg2)
f1aa6320 2131{
d9bea114 2132 // arg1 = rt, arg2 = rs
f1aa6320
TS
2133 // TODO: store to TC register
2134}
2135
895c2d04 2136target_ulong helper_yield(CPUMIPSState *env, target_ulong arg)
f1aa6320 2137{
1c7242da
BS
2138 target_long arg1 = arg;
2139
d9bea114 2140 if (arg1 < 0) {
f1aa6320 2141 /* No scheduling policy implemented. */
d9bea114 2142 if (arg1 != -2) {
f1aa6320 2143 if (env->CP0_VPEControl & (1 << CP0VPECo_YSI) &&
b5dc7732 2144 env->active_tc.CP0_TCStatus & (1 << CP0TCSt_DT)) {
f1aa6320
TS
2145 env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
2146 env->CP0_VPEControl |= 4 << CP0VPECo_EXCPT;
9c708c7f 2147 do_raise_exception(env, EXCP_THREAD, GETPC());
f1aa6320
TS
2148 }
2149 }
d9bea114 2150 } else if (arg1 == 0) {
6958549d 2151 if (0 /* TODO: TC underflow */) {
f1aa6320 2152 env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
9c708c7f 2153 do_raise_exception(env, EXCP_THREAD, GETPC());
f1aa6320
TS
2154 } else {
2155 // TODO: Deallocate TC
2156 }
d9bea114 2157 } else if (arg1 > 0) {
f1aa6320
TS
2158 /* Yield qualifier inputs not implemented. */
2159 env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
2160 env->CP0_VPEControl |= 2 << CP0VPECo_EXCPT;
9c708c7f 2161 do_raise_exception(env, EXCP_THREAD, GETPC());
f1aa6320 2162 }
be24bb4f 2163 return env->CP0_YQMask;
f1aa6320
TS
2164}
2165
01bc435b
YK
2166/* R6 Multi-threading */
2167#ifndef CONFIG_USER_ONLY
2168target_ulong helper_dvp(CPUMIPSState *env)
2169{
2170 CPUState *other_cs = first_cpu;
2171 target_ulong prev = env->CP0_VPControl;
2172
2173 if (!((env->CP0_VPControl >> CP0VPCtl_DIS) & 1)) {
2174 CPU_FOREACH(other_cs) {
2175 MIPSCPU *other_cpu = MIPS_CPU(other_cs);
2176 /* Turn off all VPs except the one executing the dvp. */
2177 if (&other_cpu->env != env) {
2178 mips_vpe_sleep(other_cpu);
2179 }
2180 }
2181 env->CP0_VPControl |= (1 << CP0VPCtl_DIS);
2182 }
2183 return prev;
2184}
2185
2186target_ulong helper_evp(CPUMIPSState *env)
2187{
2188 CPUState *other_cs = first_cpu;
2189 target_ulong prev = env->CP0_VPControl;
2190
2191 if ((env->CP0_VPControl >> CP0VPCtl_DIS) & 1) {
2192 CPU_FOREACH(other_cs) {
2193 MIPSCPU *other_cpu = MIPS_CPU(other_cs);
2194 if ((&other_cpu->env != env) && !mips_vp_is_wfi(other_cpu)) {
2195 /* If the VP is WFI, don't disturb its sleep.
2196 * Otherwise, wake it up. */
2197 mips_vpe_wake(other_cpu);
2198 }
2199 }
2200 env->CP0_VPControl &= ~(1 << CP0VPCtl_DIS);
2201 }
2202 return prev;
2203}
2204#endif /* !CONFIG_USER_ONLY */
2205
f1aa6320 2206#ifndef CONFIG_USER_ONLY
6af0bf9c 2207/* TLB management */
7db13fae 2208static void r4k_mips_tlb_flush_extra (CPUMIPSState *env, int first)
814b9a47
TS
2209{
2210 /* Discard entries from env->tlb[first] onwards. */
ead9360e
TS
2211 while (env->tlb->tlb_in_use > first) {
2212 r4k_invalidate_tlb(env, --env->tlb->tlb_in_use, 0);
814b9a47
TS
2213 }
2214}
2215
cd0d45c4
LA
2216static inline uint64_t get_tlb_pfn_from_entrylo(uint64_t entrylo)
2217{
2218#if defined(TARGET_MIPS64)
2219 return extract64(entrylo, 6, 54);
2220#else
2221 return extract64(entrylo, 6, 24) | /* PFN */
2222 (extract64(entrylo, 32, 32) << 24); /* PFNX */
2223#endif
2224}
2225
895c2d04 2226static void r4k_fill_tlb(CPUMIPSState *env, int idx)
6af0bf9c 2227{
c227f099 2228 r4k_tlb_t *tlb;
2d1847ec 2229 uint64_t mask = env->CP0_PageMask >> (TARGET_PAGE_BITS + 1);
6af0bf9c
FB
2230
2231 /* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */
ead9360e 2232 tlb = &env->tlb->mmu.r4k.tlb[idx];
9456c2fb
LA
2233 if (env->CP0_EntryHi & (1 << CP0EnHi_EHINV)) {
2234 tlb->EHINV = 1;
2235 return;
2236 }
2237 tlb->EHINV = 0;
f2e9ebef 2238 tlb->VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1);
d26bc211 2239#if defined(TARGET_MIPS64)
e034e2c3 2240 tlb->VPN &= env->SEGMask;
100ce988 2241#endif
6ec98bd7 2242 tlb->ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
3b1c8be4 2243 tlb->PageMask = env->CP0_PageMask;
6af0bf9c 2244 tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
98c1b82b
PB
2245 tlb->V0 = (env->CP0_EntryLo0 & 2) != 0;
2246 tlb->D0 = (env->CP0_EntryLo0 & 4) != 0;
2247 tlb->C0 = (env->CP0_EntryLo0 >> 3) & 0x7;
2fb58b73
LA
2248 tlb->XI0 = (env->CP0_EntryLo0 >> CP0EnLo_XI) & 1;
2249 tlb->RI0 = (env->CP0_EntryLo0 >> CP0EnLo_RI) & 1;
2d1847ec 2250 tlb->PFN[0] = (get_tlb_pfn_from_entrylo(env->CP0_EntryLo0) & ~mask) << 12;
98c1b82b
PB
2251 tlb->V1 = (env->CP0_EntryLo1 & 2) != 0;
2252 tlb->D1 = (env->CP0_EntryLo1 & 4) != 0;
2253 tlb->C1 = (env->CP0_EntryLo1 >> 3) & 0x7;
2fb58b73
LA
2254 tlb->XI1 = (env->CP0_EntryLo1 >> CP0EnLo_XI) & 1;
2255 tlb->RI1 = (env->CP0_EntryLo1 >> CP0EnLo_RI) & 1;
2d1847ec 2256 tlb->PFN[1] = (get_tlb_pfn_from_entrylo(env->CP0_EntryLo1) & ~mask) << 12;
6af0bf9c
FB
2257}
2258
9456c2fb
LA
2259void r4k_helper_tlbinv(CPUMIPSState *env)
2260{
2261 int idx;
2262 r4k_tlb_t *tlb;
2d72e7b0 2263 uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
9456c2fb
LA
2264
2265 for (idx = 0; idx < env->tlb->nb_tlb; idx++) {
2266 tlb = &env->tlb->mmu.r4k.tlb[idx];
2267 if (!tlb->G && tlb->ASID == ASID) {
2268 tlb->EHINV = 1;
2269 }
2270 }
d10eb08f 2271 cpu_mips_tlb_flush(env);
9456c2fb
LA
2272}
2273
2274void r4k_helper_tlbinvf(CPUMIPSState *env)
2275{
2276 int idx;
2277
2278 for (idx = 0; idx < env->tlb->nb_tlb; idx++) {
2279 env->tlb->mmu.r4k.tlb[idx].EHINV = 1;
2280 }
d10eb08f 2281 cpu_mips_tlb_flush(env);
9456c2fb
LA
2282}
2283
895c2d04 2284void r4k_helper_tlbwi(CPUMIPSState *env)
6af0bf9c 2285{
286d52eb 2286 r4k_tlb_t *tlb;
bbc0d79c 2287 int idx;
286d52eb 2288 target_ulong VPN;
2d72e7b0 2289 uint16_t ASID;
eff6ff94 2290 bool EHINV, G, V0, D0, V1, D1, XI0, XI1, RI0, RI1;
bbc0d79c
AJ
2291
2292 idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb;
286d52eb
AJ
2293 tlb = &env->tlb->mmu.r4k.tlb[idx];
2294 VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1);
2295#if defined(TARGET_MIPS64)
2296 VPN &= env->SEGMask;
2297#endif
6ec98bd7 2298 ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
eff6ff94 2299 EHINV = (env->CP0_EntryHi & (1 << CP0EnHi_EHINV)) != 0;
286d52eb
AJ
2300 G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
2301 V0 = (env->CP0_EntryLo0 & 2) != 0;
2302 D0 = (env->CP0_EntryLo0 & 4) != 0;
eff6ff94
JH
2303 XI0 = (env->CP0_EntryLo0 >> CP0EnLo_XI) &1;
2304 RI0 = (env->CP0_EntryLo0 >> CP0EnLo_RI) &1;
286d52eb
AJ
2305 V1 = (env->CP0_EntryLo1 & 2) != 0;
2306 D1 = (env->CP0_EntryLo1 & 4) != 0;
eff6ff94
JH
2307 XI1 = (env->CP0_EntryLo1 >> CP0EnLo_XI) &1;
2308 RI1 = (env->CP0_EntryLo1 >> CP0EnLo_RI) &1;
286d52eb
AJ
2309
2310 /* Discard cached TLB entries, unless tlbwi is just upgrading access
2311 permissions on the current entry. */
2312 if (tlb->VPN != VPN || tlb->ASID != ASID || tlb->G != G ||
eff6ff94 2313 (!tlb->EHINV && EHINV) ||
286d52eb 2314 (tlb->V0 && !V0) || (tlb->D0 && !D0) ||
eff6ff94
JH
2315 (!tlb->XI0 && XI0) || (!tlb->RI0 && RI0) ||
2316 (tlb->V1 && !V1) || (tlb->D1 && !D1) ||
2317 (!tlb->XI1 && XI1) || (!tlb->RI1 && RI1)) {
286d52eb
AJ
2318 r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb);
2319 }
814b9a47 2320
bbc0d79c 2321 r4k_invalidate_tlb(env, idx, 0);
895c2d04 2322 r4k_fill_tlb(env, idx);
6af0bf9c
FB
2323}
2324
895c2d04 2325void r4k_helper_tlbwr(CPUMIPSState *env)
6af0bf9c
FB
2326{
2327 int r = cpu_mips_get_random(env);
2328
29929e34 2329 r4k_invalidate_tlb(env, r, 1);
895c2d04 2330 r4k_fill_tlb(env, r);
6af0bf9c
FB
2331}
2332
895c2d04 2333void r4k_helper_tlbp(CPUMIPSState *env)
6af0bf9c 2334{
c227f099 2335 r4k_tlb_t *tlb;
f2e9ebef 2336 target_ulong mask;
6af0bf9c 2337 target_ulong tag;
f2e9ebef 2338 target_ulong VPN;
2d72e7b0 2339 uint16_t ASID;
6af0bf9c
FB
2340 int i;
2341
6ec98bd7 2342 ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
ead9360e
TS
2343 for (i = 0; i < env->tlb->nb_tlb; i++) {
2344 tlb = &env->tlb->mmu.r4k.tlb[i];
f2e9ebef
TS
2345 /* 1k pages are not supported. */
2346 mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
2347 tag = env->CP0_EntryHi & ~mask;
2348 VPN = tlb->VPN & ~mask;
bc3e45e1
AJ
2349#if defined(TARGET_MIPS64)
2350 tag &= env->SEGMask;
2351#endif
6af0bf9c 2352 /* Check ASID, virtual page number & size */
9456c2fb 2353 if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag && !tlb->EHINV) {
6af0bf9c 2354 /* TLB match */
9c2149c8 2355 env->CP0_Index = i;
6af0bf9c
FB
2356 break;
2357 }
2358 }
ead9360e 2359 if (i == env->tlb->nb_tlb) {
814b9a47 2360 /* No match. Discard any shadow entries, if any of them match. */
ead9360e 2361 for (i = env->tlb->nb_tlb; i < env->tlb->tlb_in_use; i++) {
6958549d
AJ
2362 tlb = &env->tlb->mmu.r4k.tlb[i];
2363 /* 1k pages are not supported. */
2364 mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
2365 tag = env->CP0_EntryHi & ~mask;
2366 VPN = tlb->VPN & ~mask;
bc3e45e1
AJ
2367#if defined(TARGET_MIPS64)
2368 tag &= env->SEGMask;
2369#endif
6958549d
AJ
2370 /* Check ASID, virtual page number & size */
2371 if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
29929e34 2372 r4k_mips_tlb_flush_extra (env, i);
6958549d
AJ
2373 break;
2374 }
2375 }
814b9a47 2376
9c2149c8 2377 env->CP0_Index |= 0x80000000;
6af0bf9c
FB
2378 }
2379}
2380
cd0d45c4
LA
2381static inline uint64_t get_entrylo_pfn_from_tlb(uint64_t tlb_pfn)
2382{
2383#if defined(TARGET_MIPS64)
2384 return tlb_pfn << 6;
2385#else
2386 return (extract64(tlb_pfn, 0, 24) << 6) | /* PFN */
2387 (extract64(tlb_pfn, 24, 32) << 32); /* PFNX */
2388#endif
2389}
2390
895c2d04 2391void r4k_helper_tlbr(CPUMIPSState *env)
6af0bf9c 2392{
c227f099 2393 r4k_tlb_t *tlb;
2d72e7b0 2394 uint16_t ASID;
bbc0d79c 2395 int idx;
6af0bf9c 2396
6ec98bd7 2397 ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
bbc0d79c
AJ
2398 idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb;
2399 tlb = &env->tlb->mmu.r4k.tlb[idx];
4ad40f36
FB
2400
2401 /* If this will change the current ASID, flush qemu's TLB. */
814b9a47 2402 if (ASID != tlb->ASID)
d10eb08f 2403 cpu_mips_tlb_flush(env);
814b9a47 2404
ead9360e 2405 r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb);
4ad40f36 2406
9456c2fb
LA
2407 if (tlb->EHINV) {
2408 env->CP0_EntryHi = 1 << CP0EnHi_EHINV;
2409 env->CP0_PageMask = 0;
2410 env->CP0_EntryLo0 = 0;
2411 env->CP0_EntryLo1 = 0;
2412 } else {
2413 env->CP0_EntryHi = tlb->VPN | tlb->ASID;
2414 env->CP0_PageMask = tlb->PageMask;
2415 env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) |
284b731a 2416 ((uint64_t)tlb->RI0 << CP0EnLo_RI) |
cd0d45c4
LA
2417 ((uint64_t)tlb->XI0 << CP0EnLo_XI) | (tlb->C0 << 3) |
2418 get_entrylo_pfn_from_tlb(tlb->PFN[0] >> 12);
9456c2fb 2419 env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) |
284b731a 2420 ((uint64_t)tlb->RI1 << CP0EnLo_RI) |
cd0d45c4
LA
2421 ((uint64_t)tlb->XI1 << CP0EnLo_XI) | (tlb->C1 << 3) |
2422 get_entrylo_pfn_from_tlb(tlb->PFN[1] >> 12);
9456c2fb 2423 }
6af0bf9c 2424}
6af0bf9c 2425
895c2d04 2426void helper_tlbwi(CPUMIPSState *env)
a7812ae4 2427{
895c2d04 2428 env->tlb->helper_tlbwi(env);
a7812ae4
PB
2429}
2430
895c2d04 2431void helper_tlbwr(CPUMIPSState *env)
a7812ae4 2432{
895c2d04 2433 env->tlb->helper_tlbwr(env);
a7812ae4
PB
2434}
2435
895c2d04 2436void helper_tlbp(CPUMIPSState *env)
a7812ae4 2437{
895c2d04 2438 env->tlb->helper_tlbp(env);
a7812ae4
PB
2439}
2440
895c2d04 2441void helper_tlbr(CPUMIPSState *env)
a7812ae4 2442{
895c2d04 2443 env->tlb->helper_tlbr(env);
a7812ae4
PB
2444}
2445
9456c2fb
LA
2446void helper_tlbinv(CPUMIPSState *env)
2447{
2448 env->tlb->helper_tlbinv(env);
2449}
2450
2451void helper_tlbinvf(CPUMIPSState *env)
2452{
2453 env->tlb->helper_tlbinvf(env);
2454}
2455
2b0233ab 2456/* Specials */
895c2d04 2457target_ulong helper_di(CPUMIPSState *env)
2b0233ab 2458{
2796188e
TS
2459 target_ulong t0 = env->CP0_Status;
2460
be24bb4f 2461 env->CP0_Status = t0 & ~(1 << CP0St_IE);
be24bb4f 2462 return t0;
2b0233ab
TS
2463}
2464
895c2d04 2465target_ulong helper_ei(CPUMIPSState *env)
2b0233ab 2466{
2796188e
TS
2467 target_ulong t0 = env->CP0_Status;
2468
be24bb4f 2469 env->CP0_Status = t0 | (1 << CP0St_IE);
be24bb4f 2470 return t0;
2b0233ab
TS
2471}
2472
895c2d04 2473static void debug_pre_eret(CPUMIPSState *env)
6af0bf9c 2474{
8fec2b8c 2475 if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
93fcfe39
AL
2476 qemu_log("ERET: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
2477 env->active_tc.PC, env->CP0_EPC);
2478 if (env->CP0_Status & (1 << CP0St_ERL))
2479 qemu_log(" ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
2480 if (env->hflags & MIPS_HFLAG_DM)
2481 qemu_log(" DEPC " TARGET_FMT_lx, env->CP0_DEPC);
2482 qemu_log("\n");
2483 }
f41c52f1
TS
2484}
2485
895c2d04 2486static void debug_post_eret(CPUMIPSState *env)
f41c52f1 2487{
a47dddd7
AF
2488 MIPSCPU *cpu = mips_env_get_cpu(env);
2489
8fec2b8c 2490 if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
93fcfe39
AL
2491 qemu_log(" => PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
2492 env->active_tc.PC, env->CP0_EPC);
2493 if (env->CP0_Status & (1 << CP0St_ERL))
2494 qemu_log(" ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
2495 if (env->hflags & MIPS_HFLAG_DM)
2496 qemu_log(" DEPC " TARGET_FMT_lx, env->CP0_DEPC);
b0fc6003 2497 switch (cpu_mmu_index(env, false)) {
42c86612
JH
2498 case 3:
2499 qemu_log(", ERL\n");
2500 break;
93fcfe39
AL
2501 case MIPS_HFLAG_UM: qemu_log(", UM\n"); break;
2502 case MIPS_HFLAG_SM: qemu_log(", SM\n"); break;
2503 case MIPS_HFLAG_KM: qemu_log("\n"); break;
a47dddd7
AF
2504 default:
2505 cpu_abort(CPU(cpu), "Invalid MMU mode!\n");
2506 break;
93fcfe39 2507 }
623a930e 2508 }
6af0bf9c
FB
2509}
2510
895c2d04 2511static void set_pc(CPUMIPSState *env, target_ulong error_pc)
32188a03
NF
2512{
2513 env->active_tc.PC = error_pc & ~(target_ulong)1;
2514 if (error_pc & 1) {
2515 env->hflags |= MIPS_HFLAG_M16;
2516 } else {
2517 env->hflags &= ~(MIPS_HFLAG_M16);
2518 }
2519}
2520
ce9782f4 2521static inline void exception_return(CPUMIPSState *env)
2b0233ab 2522{
895c2d04 2523 debug_pre_eret(env);
2b0233ab 2524 if (env->CP0_Status & (1 << CP0St_ERL)) {
895c2d04 2525 set_pc(env, env->CP0_ErrorEPC);
2b0233ab
TS
2526 env->CP0_Status &= ~(1 << CP0St_ERL);
2527 } else {
895c2d04 2528 set_pc(env, env->CP0_EPC);
2b0233ab
TS
2529 env->CP0_Status &= ~(1 << CP0St_EXL);
2530 }
2531 compute_hflags(env);
895c2d04 2532 debug_post_eret(env);
ce9782f4
LA
2533}
2534
2535void helper_eret(CPUMIPSState *env)
2536{
2537 exception_return(env);
c7c7e1e9 2538 env->CP0_LLAddr = 1;
5499b6ff 2539 env->lladdr = 1;
2b0233ab
TS
2540}
2541
ce9782f4
LA
2542void helper_eretnc(CPUMIPSState *env)
2543{
2544 exception_return(env);
2545}
2546
895c2d04 2547void helper_deret(CPUMIPSState *env)
2b0233ab 2548{
895c2d04 2549 debug_pre_eret(env);
32188a03 2550
fe87c2b3 2551 env->hflags &= ~MIPS_HFLAG_DM;
2b0233ab 2552 compute_hflags(env);
26324ded
YK
2553
2554 set_pc(env, env->CP0_DEPC);
2555
895c2d04 2556 debug_post_eret(env);
2b0233ab 2557}
0eaef5aa 2558#endif /* !CONFIG_USER_ONLY */
2b0233ab 2559
d96391c1 2560static inline void check_hwrena(CPUMIPSState *env, int reg, uintptr_t pc)
2b0233ab 2561{
b00c7218
YK
2562 if ((env->hflags & MIPS_HFLAG_CP0) || (env->CP0_HWREna & (1 << reg))) {
2563 return;
2564 }
d96391c1 2565 do_raise_exception(env, EXCP_RI, pc);
b00c7218 2566}
be24bb4f 2567
b00c7218
YK
2568target_ulong helper_rdhwr_cpunum(CPUMIPSState *env)
2569{
d96391c1 2570 check_hwrena(env, 0, GETPC());
b00c7218 2571 return env->CP0_EBase & 0x3ff;
2b0233ab
TS
2572}
2573
895c2d04 2574target_ulong helper_rdhwr_synci_step(CPUMIPSState *env)
2b0233ab 2575{
d96391c1 2576 check_hwrena(env, 1, GETPC());
b00c7218 2577 return env->SYNCI_Step;
2b0233ab
TS
2578}
2579
895c2d04 2580target_ulong helper_rdhwr_cc(CPUMIPSState *env)
2b0233ab 2581{
d96391c1 2582 check_hwrena(env, 2, GETPC());
cdfcad78 2583#ifdef CONFIG_USER_ONLY
215581bd 2584 return env->CP0_Count;
cdfcad78 2585#else
215581bd 2586 return (int32_t)cpu_mips_get_count(env);
cdfcad78 2587#endif
2b0233ab
TS
2588}
2589
895c2d04 2590target_ulong helper_rdhwr_ccres(CPUMIPSState *env)
2b0233ab 2591{
d96391c1 2592 check_hwrena(env, 3, GETPC());
b00c7218
YK
2593 return env->CCRes;
2594}
be24bb4f 2595
b00c7218
YK
2596target_ulong helper_rdhwr_performance(CPUMIPSState *env)
2597{
d96391c1 2598 check_hwrena(env, 4, GETPC());
b00c7218
YK
2599 return env->CP0_Performance0;
2600}
2601
2602target_ulong helper_rdhwr_xnp(CPUMIPSState *env)
2603{
d96391c1 2604 check_hwrena(env, 5, GETPC());
b00c7218 2605 return (env->CP0_Config5 >> CP0C5_XNP) & 1;
2b0233ab
TS
2606}
2607
895c2d04 2608void helper_pmon(CPUMIPSState *env, int function)
6af0bf9c
FB
2609{
2610 function /= 2;
2611 switch (function) {
2612 case 2: /* TODO: char inbyte(int waitflag); */
b5dc7732
TS
2613 if (env->active_tc.gpr[4] == 0)
2614 env->active_tc.gpr[2] = -1;
6af0bf9c
FB
2615 /* Fall through */
2616 case 11: /* TODO: char inbyte (void); */
b5dc7732 2617 env->active_tc.gpr[2] = -1;
6af0bf9c
FB
2618 break;
2619 case 3:
2620 case 12:
b5dc7732 2621 printf("%c", (char)(env->active_tc.gpr[4] & 0xFF));
6af0bf9c
FB
2622 break;
2623 case 17:
2624 break;
2625 case 158:
2626 {
b69e48a8 2627 unsigned char *fmt = (void *)(uintptr_t)env->active_tc.gpr[4];
6af0bf9c
FB
2628 printf("%s", fmt);
2629 }
2630 break;
2631 }
2632}
e37e863f 2633
895c2d04 2634void helper_wait(CPUMIPSState *env)
08ba7963 2635{
259186a7
AF
2636 CPUState *cs = CPU(mips_env_get_cpu(env));
2637
2638 cs->halted = 1;
d8ed887b 2639 cpu_reset_interrupt(cs, CPU_INTERRUPT_WAKE);
9c708c7f
PD
2640 /* Last instruction in the block, PC was updated before
2641 - no need to recover PC and icount */
2642 raise_exception(env, EXCP_HLT);
08ba7963
TS
2643}
2644
5fafdf24 2645#if !defined(CONFIG_USER_ONLY)
e37e863f 2646
93e22326 2647void mips_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
b35399bb
SS
2648 MMUAccessType access_type,
2649 int mmu_idx, uintptr_t retaddr)
4ad40f36 2650{
93e22326
PB
2651 MIPSCPU *cpu = MIPS_CPU(cs);
2652 CPUMIPSState *env = &cpu->env;
aea14095
LA
2653 int error_code = 0;
2654 int excp;
93e22326 2655
e807bcc1
YK
2656 if (!(env->hflags & MIPS_HFLAG_DM)) {
2657 env->CP0_BadVAddr = addr;
2658 }
aea14095
LA
2659
2660 if (access_type == MMU_DATA_STORE) {
2661 excp = EXCP_AdES;
2662 } else {
2663 excp = EXCP_AdEL;
2664 if (access_type == MMU_INST_FETCH) {
2665 error_code |= EXCP_INST_NOTAVAIL;
2666 }
2667 }
2668
2669 do_raise_exception_err(env, excp, error_code, retaddr);
4ad40f36
FB
2670}
2671
c658b94f
AF
2672void mips_cpu_unassigned_access(CPUState *cs, hwaddr addr,
2673 bool is_write, bool is_exec, int unused,
2674 unsigned size)
647de6ca 2675{
c658b94f
AF
2676 MIPSCPU *cpu = MIPS_CPU(cs);
2677 CPUMIPSState *env = &cpu->env;
2678
eddedd54
JH
2679 /*
2680 * Raising an exception with KVM enabled will crash because it won't be from
2681 * the main execution loop so the longjmp won't have a matching setjmp.
2682 * Until we can trigger a bus error exception through KVM lets just ignore
2683 * the access.
2684 */
2685 if (kvm_enabled()) {
2686 return;
2687 }
2688
c658b94f 2689 if (is_exec) {
9c708c7f 2690 raise_exception(env, EXCP_IBE);
c658b94f 2691 } else {
9c708c7f 2692 raise_exception(env, EXCP_DBE);
c658b94f 2693 }
647de6ca 2694}
f1aa6320 2695#endif /* !CONFIG_USER_ONLY */
fd4a04eb
TS
2696
2697/* Complex FPU operations which may need stack space. */
2698
f090c9d4
PB
2699#define FLOAT_TWO32 make_float32(1 << 30)
2700#define FLOAT_TWO64 make_float64(1ULL << 62)
87552089 2701
05993cd0
AJ
2702#define FP_TO_INT32_OVERFLOW 0x7fffffff
2703#define FP_TO_INT64_OVERFLOW 0x7fffffffffffffffULL
8dfdb87c 2704
fd4a04eb 2705/* convert MIPS rounding mode in FCR31 to IEEE library */
b7651e95 2706unsigned int ieee_rm[] = {
fd4a04eb
TS
2707 float_round_nearest_even,
2708 float_round_to_zero,
2709 float_round_up,
2710 float_round_down
2711};
2712
895c2d04 2713target_ulong helper_cfc1(CPUMIPSState *env, uint32_t reg)
fd4a04eb 2714{
736d120a 2715 target_ulong arg1 = 0;
6c5c1e20 2716
ead9360e
TS
2717 switch (reg) {
2718 case 0:
d9bea114 2719 arg1 = (int32_t)env->active_fpu.fcr0;
ead9360e 2720 break;
736d120a
PJ
2721 case 1:
2722 /* UFR Support - Read Status FR */
2723 if (env->active_fpu.fcr0 & (1 << FCR0_UFRP)) {
2724 if (env->CP0_Config5 & (1 << CP0C5_UFR)) {
2725 arg1 = (int32_t)
2726 ((env->CP0_Status & (1 << CP0St_FR)) >> CP0St_FR);
2727 } else {
9c708c7f 2728 do_raise_exception(env, EXCP_RI, GETPC());
736d120a
PJ
2729 }
2730 }
2731 break;
7c979afd
LA
2732 case 5:
2733 /* FRE Support - read Config5.FRE bit */
2734 if (env->active_fpu.fcr0 & (1 << FCR0_FREP)) {
2735 if (env->CP0_Config5 & (1 << CP0C5_UFE)) {
2736 arg1 = (env->CP0_Config5 >> CP0C5_FRE) & 1;
2737 } else {
2738 helper_raise_exception(env, EXCP_RI);
2739 }
2740 }
2741 break;
ead9360e 2742 case 25:
d9bea114 2743 arg1 = ((env->active_fpu.fcr31 >> 24) & 0xfe) | ((env->active_fpu.fcr31 >> 23) & 0x1);
ead9360e
TS
2744 break;
2745 case 26:
d9bea114 2746 arg1 = env->active_fpu.fcr31 & 0x0003f07c;
ead9360e
TS
2747 break;
2748 case 28:
d9bea114 2749 arg1 = (env->active_fpu.fcr31 & 0x00000f83) | ((env->active_fpu.fcr31 >> 22) & 0x4);
ead9360e
TS
2750 break;
2751 default:
d9bea114 2752 arg1 = (int32_t)env->active_fpu.fcr31;
ead9360e
TS
2753 break;
2754 }
be24bb4f 2755
d9bea114 2756 return arg1;
ead9360e
TS
2757}
2758
736d120a 2759void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t fs, uint32_t rt)
ead9360e 2760{
736d120a
PJ
2761 switch (fs) {
2762 case 1:
2763 /* UFR Alias - Reset Status FR */
2764 if (!((env->active_fpu.fcr0 & (1 << FCR0_UFRP)) && (rt == 0))) {
2765 return;
2766 }
2767 if (env->CP0_Config5 & (1 << CP0C5_UFR)) {
2768 env->CP0_Status &= ~(1 << CP0St_FR);
2769 compute_hflags(env);
2770 } else {
9c708c7f 2771 do_raise_exception(env, EXCP_RI, GETPC());
736d120a
PJ
2772 }
2773 break;
2774 case 4:
2775 /* UNFR Alias - Set Status FR */
2776 if (!((env->active_fpu.fcr0 & (1 << FCR0_UFRP)) && (rt == 0))) {
2777 return;
2778 }
2779 if (env->CP0_Config5 & (1 << CP0C5_UFR)) {
2780 env->CP0_Status |= (1 << CP0St_FR);
2781 compute_hflags(env);
2782 } else {
9c708c7f 2783 do_raise_exception(env, EXCP_RI, GETPC());
736d120a
PJ
2784 }
2785 break;
7c979afd
LA
2786 case 5:
2787 /* FRE Support - clear Config5.FRE bit */
2788 if (!((env->active_fpu.fcr0 & (1 << FCR0_FREP)) && (rt == 0))) {
2789 return;
2790 }
2791 if (env->CP0_Config5 & (1 << CP0C5_UFE)) {
2792 env->CP0_Config5 &= ~(1 << CP0C5_FRE);
2793 compute_hflags(env);
2794 } else {
2795 helper_raise_exception(env, EXCP_RI);
2796 }
2797 break;
2798 case 6:
2799 /* FRE Support - set Config5.FRE bit */
2800 if (!((env->active_fpu.fcr0 & (1 << FCR0_FREP)) && (rt == 0))) {
2801 return;
2802 }
2803 if (env->CP0_Config5 & (1 << CP0C5_UFE)) {
2804 env->CP0_Config5 |= (1 << CP0C5_FRE);
2805 compute_hflags(env);
2806 } else {
2807 helper_raise_exception(env, EXCP_RI);
2808 }
2809 break;
fd4a04eb 2810 case 25:
ba801af4 2811 if ((env->insn_flags & ISA_MIPS32R6) || (arg1 & 0xffffff00)) {
fd4a04eb 2812 return;
ba801af4 2813 }
d9bea114
AJ
2814 env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0x017fffff) | ((arg1 & 0xfe) << 24) |
2815 ((arg1 & 0x1) << 23);
fd4a04eb
TS
2816 break;
2817 case 26:
d9bea114 2818 if (arg1 & 0x007c0000)
fd4a04eb 2819 return;
d9bea114 2820 env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0xfffc0f83) | (arg1 & 0x0003f07c);
fd4a04eb
TS
2821 break;
2822 case 28:
d9bea114 2823 if (arg1 & 0x007c0000)
fd4a04eb 2824 return;
d9bea114
AJ
2825 env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0xfefff07c) | (arg1 & 0x00000f83) |
2826 ((arg1 & 0x4) << 22);
fd4a04eb
TS
2827 break;
2828 case 31:
599bc5e8
AM
2829 env->active_fpu.fcr31 = (arg1 & env->active_fpu.fcr31_rw_bitmask) |
2830 (env->active_fpu.fcr31 & ~(env->active_fpu.fcr31_rw_bitmask));
fd4a04eb
TS
2831 break;
2832 default:
f48a2cb2
YK
2833 if (env->insn_flags & ISA_MIPS32R6) {
2834 do_raise_exception(env, EXCP_RI, GETPC());
2835 }
fd4a04eb
TS
2836 return;
2837 }
599bc5e8 2838 restore_fp_status(env);
f01be154
TS
2839 set_float_exception_flags(0, &env->active_fpu.fp_status);
2840 if ((GET_FP_ENABLE(env->active_fpu.fcr31) | 0x20) & GET_FP_CAUSE(env->active_fpu.fcr31))
5f7319cd 2841 do_raise_exception(env, EXCP_FPE, GETPC());
fd4a04eb
TS
2842}
2843
b7651e95 2844int ieee_ex_to_mips(int xcpt)
fd4a04eb 2845{
353ebb7a
AJ
2846 int ret = 0;
2847 if (xcpt) {
2848 if (xcpt & float_flag_invalid) {
2849 ret |= FP_INVALID;
2850 }
2851 if (xcpt & float_flag_overflow) {
2852 ret |= FP_OVERFLOW;
2853 }
2854 if (xcpt & float_flag_underflow) {
2855 ret |= FP_UNDERFLOW;
2856 }
2857 if (xcpt & float_flag_divbyzero) {
2858 ret |= FP_DIV0;
2859 }
2860 if (xcpt & float_flag_inexact) {
2861 ret |= FP_INEXACT;
2862 }
2863 }
2864 return ret;
fd4a04eb
TS
2865}
2866
5f7319cd 2867static inline void update_fcr31(CPUMIPSState *env, uintptr_t pc)
fd4a04eb 2868{
f01be154 2869 int tmp = ieee_ex_to_mips(get_float_exception_flags(&env->active_fpu.fp_status));
fd4a04eb 2870
f01be154 2871 SET_FP_CAUSE(env->active_fpu.fcr31, tmp);
4a587b2c
AJ
2872
2873 if (tmp) {
2874 set_float_exception_flags(0, &env->active_fpu.fp_status);
2875
2876 if (GET_FP_ENABLE(env->active_fpu.fcr31) & tmp) {
5f7319cd 2877 do_raise_exception(env, EXCP_FPE, pc);
4a587b2c
AJ
2878 } else {
2879 UPDATE_FP_FLAGS(env->active_fpu.fcr31, tmp);
2880 }
2881 }
fd4a04eb
TS
2882}
2883
a16336e4
TS
2884/* Float support.
2885 Single precition routines have a "s" suffix, double precision a
2886 "d" suffix, 32bit integer "w", 64bit integer "l", paired single "ps",
2887 paired single lower "pl", paired single upper "pu". */
2888
a16336e4 2889/* unary operations, modifying fp status */
895c2d04 2890uint64_t helper_float_sqrt_d(CPUMIPSState *env, uint64_t fdt0)
b6d96bed 2891{
5dbe90bb 2892 fdt0 = float64_sqrt(fdt0, &env->active_fpu.fp_status);
5f7319cd 2893 update_fcr31(env, GETPC());
5dbe90bb 2894 return fdt0;
b6d96bed
TS
2895}
2896
895c2d04 2897uint32_t helper_float_sqrt_s(CPUMIPSState *env, uint32_t fst0)
b6d96bed 2898{
5dbe90bb 2899 fst0 = float32_sqrt(fst0, &env->active_fpu.fp_status);
5f7319cd 2900 update_fcr31(env, GETPC());
5dbe90bb 2901 return fst0;
b6d96bed 2902}
a16336e4 2903
895c2d04 2904uint64_t helper_float_cvtd_s(CPUMIPSState *env, uint32_t fst0)
fd4a04eb 2905{
b6d96bed
TS
2906 uint64_t fdt2;
2907
f01be154 2908 fdt2 = float32_to_float64(fst0, &env->active_fpu.fp_status);
5f7319cd 2909 update_fcr31(env, GETPC());
b6d96bed 2910 return fdt2;
fd4a04eb 2911}
b6d96bed 2912
895c2d04 2913uint64_t helper_float_cvtd_w(CPUMIPSState *env, uint32_t wt0)
fd4a04eb 2914{
b6d96bed
TS
2915 uint64_t fdt2;
2916
f01be154 2917 fdt2 = int32_to_float64(wt0, &env->active_fpu.fp_status);
5f7319cd 2918 update_fcr31(env, GETPC());
b6d96bed 2919 return fdt2;
fd4a04eb 2920}
b6d96bed 2921
895c2d04 2922uint64_t helper_float_cvtd_l(CPUMIPSState *env, uint64_t dt0)
fd4a04eb 2923{
b6d96bed
TS
2924 uint64_t fdt2;
2925
f01be154 2926 fdt2 = int64_to_float64(dt0, &env->active_fpu.fp_status);
5f7319cd 2927 update_fcr31(env, GETPC());
b6d96bed 2928 return fdt2;
fd4a04eb 2929}
b6d96bed 2930
87552089 2931uint64_t helper_float_cvt_l_d(CPUMIPSState *env, uint64_t fdt0)
fd4a04eb 2932{
b6d96bed
TS
2933 uint64_t dt2;
2934
f01be154 2935 dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
4cc2e5f9
AJ
2936 if (get_float_exception_flags(&env->active_fpu.fp_status)
2937 & (float_flag_invalid | float_flag_overflow)) {
05993cd0 2938 dt2 = FP_TO_INT64_OVERFLOW;
4cc2e5f9 2939 }
5f7319cd 2940 update_fcr31(env, GETPC());
b6d96bed 2941 return dt2;
fd4a04eb 2942}
b6d96bed 2943
87552089 2944uint64_t helper_float_cvt_l_s(CPUMIPSState *env, uint32_t fst0)
fd4a04eb 2945{
b6d96bed
TS
2946 uint64_t dt2;
2947
f01be154 2948 dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
4cc2e5f9
AJ
2949 if (get_float_exception_flags(&env->active_fpu.fp_status)
2950 & (float_flag_invalid | float_flag_overflow)) {
05993cd0 2951 dt2 = FP_TO_INT64_OVERFLOW;
4cc2e5f9 2952 }
5f7319cd 2953 update_fcr31(env, GETPC());
b6d96bed 2954 return dt2;
fd4a04eb
TS
2955}
2956
895c2d04 2957uint64_t helper_float_cvtps_pw(CPUMIPSState *env, uint64_t dt0)
fd4a04eb 2958{
b6d96bed
TS
2959 uint32_t fst2;
2960 uint32_t fsth2;
2961
f01be154
TS
2962 fst2 = int32_to_float32(dt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
2963 fsth2 = int32_to_float32(dt0 >> 32, &env->active_fpu.fp_status);
5f7319cd 2964 update_fcr31(env, GETPC());
b6d96bed 2965 return ((uint64_t)fsth2 << 32) | fst2;
fd4a04eb 2966}
b6d96bed 2967
895c2d04 2968uint64_t helper_float_cvtpw_ps(CPUMIPSState *env, uint64_t fdt0)
fd4a04eb 2969{
b6d96bed
TS
2970 uint32_t wt2;
2971 uint32_t wth2;
5dbe90bb 2972 int excp, excph;
b6d96bed 2973
f01be154 2974 wt2 = float32_to_int32(fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
5dbe90bb
AJ
2975 excp = get_float_exception_flags(&env->active_fpu.fp_status);
2976 if (excp & (float_flag_overflow | float_flag_invalid)) {
05993cd0 2977 wt2 = FP_TO_INT32_OVERFLOW;
5dbe90bb
AJ
2978 }
2979
2980 set_float_exception_flags(0, &env->active_fpu.fp_status);
2981 wth2 = float32_to_int32(fdt0 >> 32, &env->active_fpu.fp_status);
2982 excph = get_float_exception_flags(&env->active_fpu.fp_status);
2983 if (excph & (float_flag_overflow | float_flag_invalid)) {
05993cd0 2984 wth2 = FP_TO_INT32_OVERFLOW;
b6d96bed 2985 }
5dbe90bb
AJ
2986
2987 set_float_exception_flags(excp | excph, &env->active_fpu.fp_status);
5f7319cd 2988 update_fcr31(env, GETPC());
5dbe90bb 2989
b6d96bed 2990 return ((uint64_t)wth2 << 32) | wt2;
fd4a04eb 2991}
b6d96bed 2992
895c2d04 2993uint32_t helper_float_cvts_d(CPUMIPSState *env, uint64_t fdt0)
fd4a04eb 2994{
b6d96bed
TS
2995 uint32_t fst2;
2996
f01be154 2997 fst2 = float64_to_float32(fdt0, &env->active_fpu.fp_status);
5f7319cd 2998 update_fcr31(env, GETPC());
b6d96bed 2999 return fst2;
fd4a04eb 3000}
b6d96bed 3001
895c2d04 3002uint32_t helper_float_cvts_w(CPUMIPSState *env, uint32_t wt0)
fd4a04eb 3003{
b6d96bed
TS
3004 uint32_t fst2;
3005
f01be154 3006 fst2 = int32_to_float32(wt0, &env->active_fpu.fp_status);
5f7319cd 3007 update_fcr31(env, GETPC());
b6d96bed 3008 return fst2;
fd4a04eb 3009}
b6d96bed 3010
895c2d04 3011uint32_t helper_float_cvts_l(CPUMIPSState *env, uint64_t dt0)
fd4a04eb 3012{
b6d96bed
TS
3013 uint32_t fst2;
3014
f01be154 3015 fst2 = int64_to_float32(dt0, &env->active_fpu.fp_status);
5f7319cd 3016 update_fcr31(env, GETPC());
b6d96bed 3017 return fst2;
fd4a04eb 3018}
b6d96bed 3019
895c2d04 3020uint32_t helper_float_cvts_pl(CPUMIPSState *env, uint32_t wt0)
fd4a04eb 3021{
b6d96bed
TS
3022 uint32_t wt2;
3023
b6d96bed 3024 wt2 = wt0;
5f7319cd 3025 update_fcr31(env, GETPC());
b6d96bed 3026 return wt2;
fd4a04eb 3027}
b6d96bed 3028
895c2d04 3029uint32_t helper_float_cvts_pu(CPUMIPSState *env, uint32_t wth0)
fd4a04eb 3030{
b6d96bed
TS
3031 uint32_t wt2;
3032
b6d96bed 3033 wt2 = wth0;
5f7319cd 3034 update_fcr31(env, GETPC());
b6d96bed 3035 return wt2;
fd4a04eb 3036}
b6d96bed 3037
87552089 3038uint32_t helper_float_cvt_w_s(CPUMIPSState *env, uint32_t fst0)
fd4a04eb 3039{
b6d96bed
TS
3040 uint32_t wt2;
3041
f01be154 3042 wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
4cc2e5f9
AJ
3043 if (get_float_exception_flags(&env->active_fpu.fp_status)
3044 & (float_flag_invalid | float_flag_overflow)) {
05993cd0 3045 wt2 = FP_TO_INT32_OVERFLOW;
4cc2e5f9 3046 }
2b09f94c 3047 update_fcr31(env, GETPC());
b6d96bed 3048 return wt2;
fd4a04eb 3049}
b6d96bed 3050
87552089 3051uint32_t helper_float_cvt_w_d(CPUMIPSState *env, uint64_t fdt0)
fd4a04eb 3052{
b6d96bed
TS
3053 uint32_t wt2;
3054
f01be154 3055 wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
4cc2e5f9
AJ
3056 if (get_float_exception_flags(&env->active_fpu.fp_status)
3057 & (float_flag_invalid | float_flag_overflow)) {
05993cd0 3058 wt2 = FP_TO_INT32_OVERFLOW;
4cc2e5f9 3059 }
5f7319cd 3060 update_fcr31(env, GETPC());
b6d96bed 3061 return wt2;
fd4a04eb
TS
3062}
3063
87552089 3064uint64_t helper_float_round_l_d(CPUMIPSState *env, uint64_t fdt0)
fd4a04eb 3065{
b6d96bed
TS
3066 uint64_t dt2;
3067
f01be154
TS
3068 set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
3069 dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
e320d05a 3070 restore_rounding_mode(env);
4cc2e5f9
AJ
3071 if (get_float_exception_flags(&env->active_fpu.fp_status)
3072 & (float_flag_invalid | float_flag_overflow)) {
05993cd0 3073 dt2 = FP_TO_INT64_OVERFLOW;
4cc2e5f9 3074 }
5f7319cd 3075 update_fcr31(env, GETPC());
b6d96bed 3076 return dt2;
fd4a04eb 3077}
b6d96bed 3078
87552089 3079uint64_t helper_float_round_l_s(CPUMIPSState *env, uint32_t fst0)
fd4a04eb 3080{
b6d96bed
TS
3081 uint64_t dt2;
3082
f01be154
TS
3083 set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
3084 dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
e320d05a 3085 restore_rounding_mode(env);
4cc2e5f9
AJ
3086 if (get_float_exception_flags(&env->active_fpu.fp_status)
3087 & (float_flag_invalid | float_flag_overflow)) {
05993cd0 3088 dt2 = FP_TO_INT64_OVERFLOW;
4cc2e5f9 3089 }
5f7319cd 3090 update_fcr31(env, GETPC());
b6d96bed 3091 return dt2;
fd4a04eb 3092}
b6d96bed 3093
87552089 3094uint32_t helper_float_round_w_d(CPUMIPSState *env, uint64_t fdt0)
fd4a04eb 3095{
b6d96bed
TS
3096 uint32_t wt2;
3097
f01be154
TS
3098 set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
3099 wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
e320d05a 3100 restore_rounding_mode(env);
4cc2e5f9
AJ
3101 if (get_float_exception_flags(&env->active_fpu.fp_status)
3102 & (float_flag_invalid | float_flag_overflow)) {
05993cd0 3103 wt2 = FP_TO_INT32_OVERFLOW;
4cc2e5f9 3104 }
5f7319cd 3105 update_fcr31(env, GETPC());
b6d96bed 3106 return wt2;
fd4a04eb 3107}
b6d96bed 3108
87552089 3109uint32_t helper_float_round_w_s(CPUMIPSState *env, uint32_t fst0)
fd4a04eb 3110{
b6d96bed
TS
3111 uint32_t wt2;
3112
f01be154
TS
3113 set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
3114 wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
e320d05a 3115 restore_rounding_mode(env);
4cc2e5f9
AJ
3116 if (get_float_exception_flags(&env->active_fpu.fp_status)
3117 & (float_flag_invalid | float_flag_overflow)) {
05993cd0 3118 wt2 = FP_TO_INT32_OVERFLOW;
4cc2e5f9 3119 }
5f7319cd 3120 update_fcr31(env, GETPC());
b6d96bed 3121 return wt2;
fd4a04eb
TS
3122}
3123
87552089 3124uint64_t helper_float_trunc_l_d(CPUMIPSState *env, uint64_t fdt0)
fd4a04eb 3125{
b6d96bed
TS
3126 uint64_t dt2;
3127
f01be154 3128 dt2 = float64_to_int64_round_to_zero(fdt0, &env->active_fpu.fp_status);
4cc2e5f9
AJ
3129 if (get_float_exception_flags(&env->active_fpu.fp_status)
3130 & (float_flag_invalid | float_flag_overflow)) {
05993cd0 3131 dt2 = FP_TO_INT64_OVERFLOW;
4cc2e5f9 3132 }
5f7319cd 3133 update_fcr31(env, GETPC());
b6d96bed 3134 return dt2;
fd4a04eb 3135}
b6d96bed 3136
87552089 3137uint64_t helper_float_trunc_l_s(CPUMIPSState *env, uint32_t fst0)
fd4a04eb 3138{
b6d96bed
TS
3139 uint64_t dt2;
3140
f01be154 3141 dt2 = float32_to_int64_round_to_zero(fst0, &env->active_fpu.fp_status);
4cc2e5f9
AJ
3142 if (get_float_exception_flags(&env->active_fpu.fp_status)
3143 & (float_flag_invalid | float_flag_overflow)) {
05993cd0 3144 dt2 = FP_TO_INT64_OVERFLOW;
4cc2e5f9 3145 }
5f7319cd 3146 update_fcr31(env, GETPC());
b6d96bed 3147 return dt2;
fd4a04eb 3148}
b6d96bed 3149
87552089 3150uint32_t helper_float_trunc_w_d(CPUMIPSState *env, uint64_t fdt0)
fd4a04eb 3151{
b6d96bed
TS
3152 uint32_t wt2;
3153
f01be154 3154 wt2 = float64_to_int32_round_to_zero(fdt0, &env->active_fpu.fp_status);
4cc2e5f9
AJ
3155 if (get_float_exception_flags(&env->active_fpu.fp_status)
3156 & (float_flag_invalid | float_flag_overflow)) {
05993cd0 3157 wt2 = FP_TO_INT32_OVERFLOW;
4cc2e5f9 3158 }
5f7319cd 3159 update_fcr31(env, GETPC());
b6d96bed 3160 return wt2;
fd4a04eb 3161}
b6d96bed 3162
87552089 3163uint32_t helper_float_trunc_w_s(CPUMIPSState *env, uint32_t fst0)
fd4a04eb 3164{
b6d96bed
TS
3165 uint32_t wt2;
3166
f01be154 3167 wt2 = float32_to_int32_round_to_zero(fst0, &env->active_fpu.fp_status);
4cc2e5f9
AJ
3168 if (get_float_exception_flags(&env->active_fpu.fp_status)
3169 & (float_flag_invalid | float_flag_overflow)) {
05993cd0 3170 wt2 = FP_TO_INT32_OVERFLOW;
4cc2e5f9 3171 }
5f7319cd 3172 update_fcr31(env, GETPC());
b6d96bed 3173 return wt2;
fd4a04eb
TS
3174}
3175
87552089 3176uint64_t helper_float_ceil_l_d(CPUMIPSState *env, uint64_t fdt0)
fd4a04eb 3177{
b6d96bed
TS
3178 uint64_t dt2;
3179
f01be154
TS
3180 set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
3181 dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
e320d05a 3182 restore_rounding_mode(env);
4cc2e5f9
AJ
3183 if (get_float_exception_flags(&env->active_fpu.fp_status)
3184 & (float_flag_invalid | float_flag_overflow)) {
05993cd0 3185 dt2 = FP_TO_INT64_OVERFLOW;
4cc2e5f9 3186 }
5f7319cd 3187 update_fcr31(env, GETPC());
b6d96bed 3188 return dt2;
fd4a04eb 3189}
b6d96bed 3190
87552089 3191uint64_t helper_float_ceil_l_s(CPUMIPSState *env, uint32_t fst0)
fd4a04eb 3192{
b6d96bed
TS
3193 uint64_t dt2;
3194
f01be154
TS
3195 set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
3196 dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
e320d05a 3197 restore_rounding_mode(env);
4cc2e5f9
AJ
3198 if (get_float_exception_flags(&env->active_fpu.fp_status)
3199 & (float_flag_invalid | float_flag_overflow)) {
05993cd0 3200 dt2 = FP_TO_INT64_OVERFLOW;
4cc2e5f9 3201 }
5f7319cd 3202 update_fcr31(env, GETPC());
b6d96bed 3203 return dt2;
fd4a04eb 3204}
b6d96bed 3205
87552089 3206uint32_t helper_float_ceil_w_d(CPUMIPSState *env, uint64_t fdt0)
fd4a04eb 3207{
b6d96bed
TS
3208 uint32_t wt2;
3209
f01be154
TS
3210 set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
3211 wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
e320d05a 3212 restore_rounding_mode(env);
4cc2e5f9
AJ
3213 if (get_float_exception_flags(&env->active_fpu.fp_status)
3214 & (float_flag_invalid | float_flag_overflow)) {
05993cd0 3215 wt2 = FP_TO_INT32_OVERFLOW;
4cc2e5f9 3216 }
5f7319cd 3217 update_fcr31(env, GETPC());
b6d96bed 3218 return wt2;
fd4a04eb 3219}
b6d96bed 3220
87552089 3221uint32_t helper_float_ceil_w_s(CPUMIPSState *env, uint32_t fst0)
fd4a04eb 3222{
b6d96bed
TS
3223 uint32_t wt2;
3224
f01be154
TS
3225 set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
3226 wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
e320d05a 3227 restore_rounding_mode(env);
4cc2e5f9
AJ
3228 if (get_float_exception_flags(&env->active_fpu.fp_status)
3229 & (float_flag_invalid | float_flag_overflow)) {
05993cd0 3230 wt2 = FP_TO_INT32_OVERFLOW;
4cc2e5f9 3231 }
5f7319cd 3232 update_fcr31(env, GETPC());
b6d96bed 3233 return wt2;
fd4a04eb
TS
3234}
3235
87552089 3236uint64_t helper_float_floor_l_d(CPUMIPSState *env, uint64_t fdt0)
fd4a04eb 3237{
b6d96bed
TS
3238 uint64_t dt2;
3239
f01be154
TS
3240 set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
3241 dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
e320d05a 3242 restore_rounding_mode(env);
4cc2e5f9
AJ
3243 if (get_float_exception_flags(&env->active_fpu.fp_status)
3244 & (float_flag_invalid | float_flag_overflow)) {
05993cd0 3245 dt2 = FP_TO_INT64_OVERFLOW;
4cc2e5f9 3246 }
5f7319cd 3247 update_fcr31(env, GETPC());
b6d96bed 3248 return dt2;
fd4a04eb 3249}
b6d96bed 3250
87552089 3251uint64_t helper_float_floor_l_s(CPUMIPSState *env, uint32_t fst0)
fd4a04eb 3252{
b6d96bed
TS
3253 uint64_t dt2;
3254
f01be154
TS
3255 set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
3256 dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
e320d05a 3257 restore_rounding_mode(env);
4cc2e5f9
AJ
3258 if (get_float_exception_flags(&env->active_fpu.fp_status)
3259 & (float_flag_invalid | float_flag_overflow)) {
05993cd0 3260 dt2 = FP_TO_INT64_OVERFLOW;
4cc2e5f9 3261 }
5f7319cd 3262 update_fcr31(env, GETPC());
b6d96bed 3263 return dt2;
fd4a04eb 3264}
b6d96bed 3265
87552089 3266uint32_t helper_float_floor_w_d(CPUMIPSState *env, uint64_t fdt0)
fd4a04eb 3267{
b6d96bed
TS
3268 uint32_t wt2;
3269
f01be154
TS
3270 set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
3271 wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
e320d05a 3272 restore_rounding_mode(env);
4cc2e5f9
AJ
3273 if (get_float_exception_flags(&env->active_fpu.fp_status)
3274 & (float_flag_invalid | float_flag_overflow)) {
05993cd0 3275 wt2 = FP_TO_INT32_OVERFLOW;
4cc2e5f9 3276 }
5f7319cd 3277 update_fcr31(env, GETPC());
b6d96bed 3278 return wt2;
fd4a04eb 3279}
b6d96bed 3280
87552089 3281uint32_t helper_float_floor_w_s(CPUMIPSState *env, uint32_t fst0)
fd4a04eb 3282{
b6d96bed
TS
3283 uint32_t wt2;
3284
f01be154
TS
3285 set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
3286 wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
e320d05a 3287 restore_rounding_mode(env);
4cc2e5f9
AJ
3288 if (get_float_exception_flags(&env->active_fpu.fp_status)
3289 & (float_flag_invalid | float_flag_overflow)) {
05993cd0 3290 wt2 = FP_TO_INT32_OVERFLOW;
4cc2e5f9 3291 }
5f7319cd 3292 update_fcr31(env, GETPC());
b6d96bed 3293 return wt2;
fd4a04eb
TS
3294}
3295
87552089
AM
3296uint64_t helper_float_cvt_2008_l_d(CPUMIPSState *env, uint64_t fdt0)
3297{
3298 uint64_t dt2;
3299
3300 dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
3301 if (get_float_exception_flags(&env->active_fpu.fp_status)
3302 & float_flag_invalid) {
3303 if (float64_is_any_nan(fdt0)) {
3304 dt2 = 0;
3305 }
3306 }
3307 update_fcr31(env, GETPC());
3308 return dt2;
3309}
3310
3311uint64_t helper_float_cvt_2008_l_s(CPUMIPSState *env, uint32_t fst0)
3312{
3313 uint64_t dt2;
3314
3315 dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
3316 if (get_float_exception_flags(&env->active_fpu.fp_status)
3317 & float_flag_invalid) {
3318 if (float32_is_any_nan(fst0)) {
3319 dt2 = 0;
3320 }
3321 }
3322 update_fcr31(env, GETPC());
3323 return dt2;
3324}
3325
3326uint32_t helper_float_cvt_2008_w_d(CPUMIPSState *env, uint64_t fdt0)
3327{
3328 uint32_t wt2;
3329
3330 wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
3331 if (get_float_exception_flags(&env->active_fpu.fp_status)
3332 & float_flag_invalid) {
3333 if (float64_is_any_nan(fdt0)) {
3334 wt2 = 0;
3335 }
3336 }
3337 update_fcr31(env, GETPC());
3338 return wt2;
3339}
3340
3341uint32_t helper_float_cvt_2008_w_s(CPUMIPSState *env, uint32_t fst0)
3342{
3343 uint32_t wt2;
3344
3345 wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
3346 if (get_float_exception_flags(&env->active_fpu.fp_status)
3347 & float_flag_invalid) {
3348 if (float32_is_any_nan(fst0)) {
3349 wt2 = 0;
3350 }
3351 }
3352 update_fcr31(env, GETPC());
3353 return wt2;
3354}
3355
3356uint64_t helper_float_round_2008_l_d(CPUMIPSState *env, uint64_t fdt0)
3357{
3358 uint64_t dt2;
3359
3360 set_float_rounding_mode(float_round_nearest_even,
3361 &env->active_fpu.fp_status);
3362 dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
3363 restore_rounding_mode(env);
3364 if (get_float_exception_flags(&env->active_fpu.fp_status)
3365 & float_flag_invalid) {
3366 if (float64_is_any_nan(fdt0)) {
3367 dt2 = 0;
3368 }
3369 }
3370 update_fcr31(env, GETPC());
3371 return dt2;
3372}
3373
3374uint64_t helper_float_round_2008_l_s(CPUMIPSState *env, uint32_t fst0)
3375{
3376 uint64_t dt2;
3377
3378 set_float_rounding_mode(float_round_nearest_even,
3379 &env->active_fpu.fp_status);
3380 dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
3381 restore_rounding_mode(env);
3382 if (get_float_exception_flags(&env->active_fpu.fp_status)
3383 & float_flag_invalid) {
3384 if (float32_is_any_nan(fst0)) {
3385 dt2 = 0;
3386 }
3387 }
3388 update_fcr31(env, GETPC());
3389 return dt2;
3390}
3391
3392uint32_t helper_float_round_2008_w_d(CPUMIPSState *env, uint64_t fdt0)
3393{
3394 uint32_t wt2;
3395
3396 set_float_rounding_mode(float_round_nearest_even,
3397 &env->active_fpu.fp_status);
3398 wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
3399 restore_rounding_mode(env);
3400 if (get_float_exception_flags(&env->active_fpu.fp_status)
3401 & float_flag_invalid) {
3402 if (float64_is_any_nan(fdt0)) {
3403 wt2 = 0;
3404 }
3405 }
3406 update_fcr31(env, GETPC());
3407 return wt2;
3408}
3409
3410uint32_t helper_float_round_2008_w_s(CPUMIPSState *env, uint32_t fst0)
3411{
3412 uint32_t wt2;
3413
3414 set_float_rounding_mode(float_round_nearest_even,
3415 &env->active_fpu.fp_status);
3416 wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
3417 restore_rounding_mode(env);
3418 if (get_float_exception_flags(&env->active_fpu.fp_status)
3419 & float_flag_invalid) {
3420 if (float32_is_any_nan(fst0)) {
3421 wt2 = 0;
3422 }
3423 }
3424 update_fcr31(env, GETPC());
3425 return wt2;
3426}
3427
3428uint64_t helper_float_trunc_2008_l_d(CPUMIPSState *env, uint64_t fdt0)
3429{
3430 uint64_t dt2;
3431
3432 dt2 = float64_to_int64_round_to_zero(fdt0, &env->active_fpu.fp_status);
3433 if (get_float_exception_flags(&env->active_fpu.fp_status)
3434 & float_flag_invalid) {
3435 if (float64_is_any_nan(fdt0)) {
3436 dt2 = 0;
3437 }
3438 }
3439 update_fcr31(env, GETPC());
3440 return dt2;
3441}
3442
3443uint64_t helper_float_trunc_2008_l_s(CPUMIPSState *env, uint32_t fst0)
3444{
3445 uint64_t dt2;
3446
3447 dt2 = float32_to_int64_round_to_zero(fst0, &env->active_fpu.fp_status);
3448 if (get_float_exception_flags(&env->active_fpu.fp_status)
3449 & float_flag_invalid) {
3450 if (float32_is_any_nan(fst0)) {
3451 dt2 = 0;
3452 }
3453 }
3454 update_fcr31(env, GETPC());
3455 return dt2;
3456}
3457
3458uint32_t helper_float_trunc_2008_w_d(CPUMIPSState *env, uint64_t fdt0)
3459{
3460 uint32_t wt2;
3461
3462 wt2 = float64_to_int32_round_to_zero(fdt0, &env->active_fpu.fp_status);
3463 if (get_float_exception_flags(&env->active_fpu.fp_status)
3464 & float_flag_invalid) {
3465 if (float64_is_any_nan(fdt0)) {
3466 wt2 = 0;
3467 }
3468 }
3469 update_fcr31(env, GETPC());
3470 return wt2;
3471}
3472
3473uint32_t helper_float_trunc_2008_w_s(CPUMIPSState *env, uint32_t fst0)
3474{
3475 uint32_t wt2;
3476
3477 wt2 = float32_to_int32_round_to_zero(fst0, &env->active_fpu.fp_status);
3478 if (get_float_exception_flags(&env->active_fpu.fp_status)
3479 & float_flag_invalid) {
3480 if (float32_is_any_nan(fst0)) {
3481 wt2 = 0;
3482 }
3483 }
3484 update_fcr31(env, GETPC());
3485 return wt2;
3486}
3487
3488uint64_t helper_float_ceil_2008_l_d(CPUMIPSState *env, uint64_t fdt0)
3489{
3490 uint64_t dt2;
3491
3492 set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
3493 dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
3494 restore_rounding_mode(env);
3495 if (get_float_exception_flags(&env->active_fpu.fp_status)
3496 & float_flag_invalid) {
3497 if (float64_is_any_nan(fdt0)) {
3498 dt2 = 0;
3499 }
3500 }
3501 update_fcr31(env, GETPC());
3502 return dt2;
3503}
3504
3505uint64_t helper_float_ceil_2008_l_s(CPUMIPSState *env, uint32_t fst0)
3506{
3507 uint64_t dt2;
3508
3509 set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
3510 dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
3511 restore_rounding_mode(env);
3512 if (get_float_exception_flags(&env->active_fpu.fp_status)
3513 & float_flag_invalid) {
3514 if (float32_is_any_nan(fst0)) {
3515 dt2 = 0;
3516 }
3517 }
3518 update_fcr31(env, GETPC());
3519 return dt2;
3520}
3521
3522uint32_t helper_float_ceil_2008_w_d(CPUMIPSState *env, uint64_t fdt0)
3523{
3524 uint32_t wt2;
3525
3526 set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
3527 wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
3528 restore_rounding_mode(env);
3529 if (get_float_exception_flags(&env->active_fpu.fp_status)
3530 & float_flag_invalid) {
3531 if (float64_is_any_nan(fdt0)) {
3532 wt2 = 0;
3533 }
3534 }
3535 update_fcr31(env, GETPC());
3536 return wt2;
3537}
3538
3539uint32_t helper_float_ceil_2008_w_s(CPUMIPSState *env, uint32_t fst0)
3540{
3541 uint32_t wt2;
3542
3543 set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
3544 wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
3545 restore_rounding_mode(env);
3546 if (get_float_exception_flags(&env->active_fpu.fp_status)
3547 & float_flag_invalid) {
3548 if (float32_is_any_nan(fst0)) {
3549 wt2 = 0;
3550 }
3551 }
3552 update_fcr31(env, GETPC());
3553 return wt2;
3554}
3555
3556uint64_t helper_float_floor_2008_l_d(CPUMIPSState *env, uint64_t fdt0)
3557{
3558 uint64_t dt2;
3559
3560 set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
3561 dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
3562 restore_rounding_mode(env);
3563 if (get_float_exception_flags(&env->active_fpu.fp_status)
3564 & float_flag_invalid) {
3565 if (float64_is_any_nan(fdt0)) {
3566 dt2 = 0;
3567 }
3568 }
3569 update_fcr31(env, GETPC());
3570 return dt2;
3571}
3572
3573uint64_t helper_float_floor_2008_l_s(CPUMIPSState *env, uint32_t fst0)
3574{
3575 uint64_t dt2;
3576
3577 set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
3578 dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
3579 restore_rounding_mode(env);
3580 if (get_float_exception_flags(&env->active_fpu.fp_status)
3581 & float_flag_invalid) {
3582 if (float32_is_any_nan(fst0)) {
3583 dt2 = 0;
3584 }
3585 }
3586 update_fcr31(env, GETPC());
3587 return dt2;
3588}
3589
3590uint32_t helper_float_floor_2008_w_d(CPUMIPSState *env, uint64_t fdt0)
3591{
3592 uint32_t wt2;
3593
3594 set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
3595 wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
3596 restore_rounding_mode(env);
3597 if (get_float_exception_flags(&env->active_fpu.fp_status)
3598 & float_flag_invalid) {
3599 if (float64_is_any_nan(fdt0)) {
3600 wt2 = 0;
3601 }
3602 }
3603 update_fcr31(env, GETPC());
3604 return wt2;
3605}
3606
3607uint32_t helper_float_floor_2008_w_s(CPUMIPSState *env, uint32_t fst0)
3608{
3609 uint32_t wt2;
3610
3611 set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
3612 wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
3613 restore_rounding_mode(env);
3614 if (get_float_exception_flags(&env->active_fpu.fp_status)
3615 & float_flag_invalid) {
3616 if (float32_is_any_nan(fst0)) {
3617 wt2 = 0;
3618 }
3619 }
3620 update_fcr31(env, GETPC());
3621 return wt2;
3622}
3623
a16336e4 3624/* unary operations, not modifying fp status */
b6d96bed 3625#define FLOAT_UNOP(name) \
c01fccd2 3626uint64_t helper_float_ ## name ## _d(uint64_t fdt0) \
b6d96bed
TS
3627{ \
3628 return float64_ ## name(fdt0); \
3629} \
c01fccd2 3630uint32_t helper_float_ ## name ## _s(uint32_t fst0) \
b6d96bed
TS
3631{ \
3632 return float32_ ## name(fst0); \
3633} \
c01fccd2 3634uint64_t helper_float_ ## name ## _ps(uint64_t fdt0) \
b6d96bed
TS
3635{ \
3636 uint32_t wt0; \
3637 uint32_t wth0; \
3638 \
3639 wt0 = float32_ ## name(fdt0 & 0XFFFFFFFF); \
3640 wth0 = float32_ ## name(fdt0 >> 32); \
3641 return ((uint64_t)wth0 << 32) | wt0; \
a16336e4
TS
3642}
3643FLOAT_UNOP(abs)
3644FLOAT_UNOP(chs)
3645#undef FLOAT_UNOP
3646
8dfdb87c 3647/* MIPS specific unary operations */
895c2d04 3648uint64_t helper_float_recip_d(CPUMIPSState *env, uint64_t fdt0)
8dfdb87c 3649{
b6d96bed
TS
3650 uint64_t fdt2;
3651
05993cd0 3652 fdt2 = float64_div(float64_one, fdt0, &env->active_fpu.fp_status);
5f7319cd 3653 update_fcr31(env, GETPC());
b6d96bed 3654 return fdt2;
8dfdb87c 3655}
b6d96bed 3656
895c2d04 3657uint32_t helper_float_recip_s(CPUMIPSState *env, uint32_t fst0)
8dfdb87c 3658{
b6d96bed
TS
3659 uint32_t fst2;
3660
05993cd0 3661 fst2 = float32_div(float32_one, fst0, &env->active_fpu.fp_status);
5f7319cd 3662 update_fcr31(env, GETPC());
b6d96bed 3663 return fst2;
57fa1fb3 3664}
57fa1fb3 3665
895c2d04 3666uint64_t helper_float_rsqrt_d(CPUMIPSState *env, uint64_t fdt0)
8dfdb87c 3667{
b6d96bed
TS
3668 uint64_t fdt2;
3669
f01be154 3670 fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status);
05993cd0 3671 fdt2 = float64_div(float64_one, fdt2, &env->active_fpu.fp_status);
5f7319cd 3672 update_fcr31(env, GETPC());
b6d96bed 3673 return fdt2;
8dfdb87c 3674}
b6d96bed 3675
895c2d04 3676uint32_t helper_float_rsqrt_s(CPUMIPSState *env, uint32_t fst0)
8dfdb87c 3677{
b6d96bed
TS
3678 uint32_t fst2;
3679
f01be154 3680 fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status);
05993cd0 3681 fst2 = float32_div(float32_one, fst2, &env->active_fpu.fp_status);
5f7319cd 3682 update_fcr31(env, GETPC());
b6d96bed 3683 return fst2;
8dfdb87c
TS
3684}
3685
895c2d04 3686uint64_t helper_float_recip1_d(CPUMIPSState *env, uint64_t fdt0)
8dfdb87c 3687{
b6d96bed
TS
3688 uint64_t fdt2;
3689
05993cd0 3690 fdt2 = float64_div(float64_one, fdt0, &env->active_fpu.fp_status);
5f7319cd 3691 update_fcr31(env, GETPC());
b6d96bed 3692 return fdt2;
8dfdb87c 3693}
b6d96bed 3694
895c2d04 3695uint32_t helper_float_recip1_s(CPUMIPSState *env, uint32_t fst0)
8dfdb87c 3696{
b6d96bed
TS
3697 uint32_t fst2;
3698
05993cd0 3699 fst2 = float32_div(float32_one, fst0, &env->active_fpu.fp_status);
5f7319cd 3700 update_fcr31(env, GETPC());
b6d96bed 3701 return fst2;
8dfdb87c 3702}
b6d96bed 3703
895c2d04 3704uint64_t helper_float_recip1_ps(CPUMIPSState *env, uint64_t fdt0)
8dfdb87c 3705{
b6d96bed
TS
3706 uint32_t fst2;
3707 uint32_t fsth2;
3708
05993cd0
AJ
3709 fst2 = float32_div(float32_one, fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
3710 fsth2 = float32_div(float32_one, fdt0 >> 32, &env->active_fpu.fp_status);
5f7319cd 3711 update_fcr31(env, GETPC());
b6d96bed 3712 return ((uint64_t)fsth2 << 32) | fst2;
8dfdb87c
TS
3713}
3714
895c2d04 3715uint64_t helper_float_rsqrt1_d(CPUMIPSState *env, uint64_t fdt0)
8dfdb87c 3716{
b6d96bed
TS
3717 uint64_t fdt2;
3718
f01be154 3719 fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status);
05993cd0 3720 fdt2 = float64_div(float64_one, fdt2, &env->active_fpu.fp_status);
5f7319cd 3721 update_fcr31(env, GETPC());
b6d96bed 3722 return fdt2;
8dfdb87c 3723}
b6d96bed 3724
895c2d04 3725uint32_t helper_float_rsqrt1_s(CPUMIPSState *env, uint32_t fst0)
8dfdb87c 3726{
b6d96bed
TS
3727 uint32_t fst2;
3728
f01be154 3729 fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status);
05993cd0 3730 fst2 = float32_div(float32_one, fst2, &env->active_fpu.fp_status);
5f7319cd 3731 update_fcr31(env, GETPC());
b6d96bed 3732 return fst2;
8dfdb87c 3733}
b6d96bed 3734
895c2d04 3735uint64_t helper_float_rsqrt1_ps(CPUMIPSState *env, uint64_t fdt0)
8dfdb87c 3736{
b6d96bed
TS
3737 uint32_t fst2;
3738 uint32_t fsth2;
3739
f01be154
TS
3740 fst2 = float32_sqrt(fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
3741 fsth2 = float32_sqrt(fdt0 >> 32, &env->active_fpu.fp_status);
05993cd0
AJ
3742 fst2 = float32_div(float32_one, fst2, &env->active_fpu.fp_status);
3743 fsth2 = float32_div(float32_one, fsth2, &env->active_fpu.fp_status);
5f7319cd 3744 update_fcr31(env, GETPC());
b6d96bed 3745 return ((uint64_t)fsth2 << 32) | fst2;
57fa1fb3 3746}
57fa1fb3 3747
8fc605b8
MR
3748#define FLOAT_RINT(name, bits) \
3749uint ## bits ## _t helper_float_ ## name (CPUMIPSState *env, \
3750 uint ## bits ## _t fs) \
3751{ \
3752 uint ## bits ## _t fdret; \
3753 \
3754 fdret = float ## bits ## _round_to_int(fs, &env->active_fpu.fp_status); \
3755 update_fcr31(env, GETPC()); \
3756 return fdret; \
3757}
3758
3759FLOAT_RINT(rint_s, 32)
3760FLOAT_RINT(rint_d, 64)
3761#undef FLOAT_RINT
3762
3763#define FLOAT_CLASS_SIGNALING_NAN 0x001
3764#define FLOAT_CLASS_QUIET_NAN 0x002
3765#define FLOAT_CLASS_NEGATIVE_INFINITY 0x004
3766#define FLOAT_CLASS_NEGATIVE_NORMAL 0x008
3767#define FLOAT_CLASS_NEGATIVE_SUBNORMAL 0x010
3768#define FLOAT_CLASS_NEGATIVE_ZERO 0x020
3769#define FLOAT_CLASS_POSITIVE_INFINITY 0x040
3770#define FLOAT_CLASS_POSITIVE_NORMAL 0x080
3771#define FLOAT_CLASS_POSITIVE_SUBNORMAL 0x100
3772#define FLOAT_CLASS_POSITIVE_ZERO 0x200
3773
3774#define FLOAT_CLASS(name, bits) \
af39bc8c
AM
3775uint ## bits ## _t float_ ## name (uint ## bits ## _t arg, \
3776 float_status *status) \
8fc605b8 3777{ \
af39bc8c 3778 if (float ## bits ## _is_signaling_nan(arg, status)) { \
8fc605b8 3779 return FLOAT_CLASS_SIGNALING_NAN; \
af39bc8c 3780 } else if (float ## bits ## _is_quiet_nan(arg, status)) { \
8fc605b8
MR
3781 return FLOAT_CLASS_QUIET_NAN; \
3782 } else if (float ## bits ## _is_neg(arg)) { \
3783 if (float ## bits ## _is_infinity(arg)) { \
3784 return FLOAT_CLASS_NEGATIVE_INFINITY; \
3785 } else if (float ## bits ## _is_zero(arg)) { \
3786 return FLOAT_CLASS_NEGATIVE_ZERO; \
3787 } else if (float ## bits ## _is_zero_or_denormal(arg)) { \
3788 return FLOAT_CLASS_NEGATIVE_SUBNORMAL; \
3789 } else { \
3790 return FLOAT_CLASS_NEGATIVE_NORMAL; \
3791 } \
3792 } else { \
3793 if (float ## bits ## _is_infinity(arg)) { \
3794 return FLOAT_CLASS_POSITIVE_INFINITY; \
3795 } else if (float ## bits ## _is_zero(arg)) { \
3796 return FLOAT_CLASS_POSITIVE_ZERO; \
3797 } else if (float ## bits ## _is_zero_or_denormal(arg)) { \
3798 return FLOAT_CLASS_POSITIVE_SUBNORMAL; \
3799 } else { \
3800 return FLOAT_CLASS_POSITIVE_NORMAL; \
3801 } \
3802 } \
af39bc8c
AM
3803} \
3804 \
3805uint ## bits ## _t helper_float_ ## name (CPUMIPSState *env, \
3806 uint ## bits ## _t arg) \
3807{ \
3808 return float_ ## name(arg, &env->active_fpu.fp_status); \
8fc605b8
MR
3809}
3810
3811FLOAT_CLASS(class_s, 32)
3812FLOAT_CLASS(class_d, 64)
3813#undef FLOAT_CLASS
3814
fd4a04eb 3815/* binary operations */
b6d96bed 3816#define FLOAT_BINOP(name) \
895c2d04
BS
3817uint64_t helper_float_ ## name ## _d(CPUMIPSState *env, \
3818 uint64_t fdt0, uint64_t fdt1) \
b6d96bed
TS
3819{ \
3820 uint64_t dt2; \
3821 \
f01be154 3822 dt2 = float64_ ## name (fdt0, fdt1, &env->active_fpu.fp_status); \
5f7319cd 3823 update_fcr31(env, GETPC()); \
b6d96bed
TS
3824 return dt2; \
3825} \
3826 \
895c2d04
BS
3827uint32_t helper_float_ ## name ## _s(CPUMIPSState *env, \
3828 uint32_t fst0, uint32_t fst1) \
b6d96bed
TS
3829{ \
3830 uint32_t wt2; \
3831 \
f01be154 3832 wt2 = float32_ ## name (fst0, fst1, &env->active_fpu.fp_status); \
5f7319cd 3833 update_fcr31(env, GETPC()); \
b6d96bed
TS
3834 return wt2; \
3835} \
3836 \
895c2d04
BS
3837uint64_t helper_float_ ## name ## _ps(CPUMIPSState *env, \
3838 uint64_t fdt0, \
3839 uint64_t fdt1) \
b6d96bed
TS
3840{ \
3841 uint32_t fst0 = fdt0 & 0XFFFFFFFF; \
3842 uint32_t fsth0 = fdt0 >> 32; \
3843 uint32_t fst1 = fdt1 & 0XFFFFFFFF; \
3844 uint32_t fsth1 = fdt1 >> 32; \
3845 uint32_t wt2; \
3846 uint32_t wth2; \
3847 \
f01be154
TS
3848 wt2 = float32_ ## name (fst0, fst1, &env->active_fpu.fp_status); \
3849 wth2 = float32_ ## name (fsth0, fsth1, &env->active_fpu.fp_status); \
5f7319cd 3850 update_fcr31(env, GETPC()); \
b6d96bed 3851 return ((uint64_t)wth2 << 32) | wt2; \
fd4a04eb 3852}
b6d96bed 3853
fd4a04eb
TS
3854FLOAT_BINOP(add)
3855FLOAT_BINOP(sub)
3856FLOAT_BINOP(mul)
3857FLOAT_BINOP(div)
3858#undef FLOAT_BINOP
3859
8dfdb87c 3860/* MIPS specific binary operations */
895c2d04 3861uint64_t helper_float_recip2_d(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2)
8dfdb87c 3862{
f01be154 3863 fdt2 = float64_mul(fdt0, fdt2, &env->active_fpu.fp_status);
05993cd0 3864 fdt2 = float64_chs(float64_sub(fdt2, float64_one, &env->active_fpu.fp_status));
5f7319cd 3865 update_fcr31(env, GETPC());
b6d96bed 3866 return fdt2;
8dfdb87c 3867}
b6d96bed 3868
895c2d04 3869uint32_t helper_float_recip2_s(CPUMIPSState *env, uint32_t fst0, uint32_t fst2)
8dfdb87c 3870{
f01be154 3871 fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
05993cd0 3872 fst2 = float32_chs(float32_sub(fst2, float32_one, &env->active_fpu.fp_status));
5f7319cd 3873 update_fcr31(env, GETPC());
b6d96bed 3874 return fst2;
8dfdb87c 3875}
b6d96bed 3876
895c2d04 3877uint64_t helper_float_recip2_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2)
8dfdb87c 3878{
b6d96bed
TS
3879 uint32_t fst0 = fdt0 & 0XFFFFFFFF;
3880 uint32_t fsth0 = fdt0 >> 32;
3881 uint32_t fst2 = fdt2 & 0XFFFFFFFF;
3882 uint32_t fsth2 = fdt2 >> 32;
3883
f01be154
TS
3884 fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
3885 fsth2 = float32_mul(fsth0, fsth2, &env->active_fpu.fp_status);
05993cd0
AJ
3886 fst2 = float32_chs(float32_sub(fst2, float32_one, &env->active_fpu.fp_status));
3887 fsth2 = float32_chs(float32_sub(fsth2, float32_one, &env->active_fpu.fp_status));
5f7319cd 3888 update_fcr31(env, GETPC());
b6d96bed 3889 return ((uint64_t)fsth2 << 32) | fst2;
8dfdb87c
TS
3890}
3891
895c2d04 3892uint64_t helper_float_rsqrt2_d(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2)
8dfdb87c 3893{
f01be154 3894 fdt2 = float64_mul(fdt0, fdt2, &env->active_fpu.fp_status);
05993cd0 3895 fdt2 = float64_sub(fdt2, float64_one, &env->active_fpu.fp_status);
f01be154 3896 fdt2 = float64_chs(float64_div(fdt2, FLOAT_TWO64, &env->active_fpu.fp_status));
5f7319cd 3897 update_fcr31(env, GETPC());
b6d96bed 3898 return fdt2;
8dfdb87c 3899}
b6d96bed 3900
895c2d04 3901uint32_t helper_float_rsqrt2_s(CPUMIPSState *env, uint32_t fst0, uint32_t fst2)
8dfdb87c 3902{
f01be154 3903 fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
05993cd0 3904 fst2 = float32_sub(fst2, float32_one, &env->active_fpu.fp_status);
f01be154 3905 fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32, &env->active_fpu.fp_status));
5f7319cd 3906 update_fcr31(env, GETPC());
b6d96bed 3907 return fst2;
8dfdb87c 3908}
b6d96bed 3909
895c2d04 3910uint64_t helper_float_rsqrt2_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2)
8dfdb87c 3911{
b6d96bed
TS
3912 uint32_t fst0 = fdt0 & 0XFFFFFFFF;
3913 uint32_t fsth0 = fdt0 >> 32;
3914 uint32_t fst2 = fdt2 & 0XFFFFFFFF;
3915 uint32_t fsth2 = fdt2 >> 32;
3916
f01be154
TS
3917 fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
3918 fsth2 = float32_mul(fsth0, fsth2, &env->active_fpu.fp_status);
05993cd0
AJ
3919 fst2 = float32_sub(fst2, float32_one, &env->active_fpu.fp_status);
3920 fsth2 = float32_sub(fsth2, float32_one, &env->active_fpu.fp_status);
f01be154
TS
3921 fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32, &env->active_fpu.fp_status));
3922 fsth2 = float32_chs(float32_div(fsth2, FLOAT_TWO32, &env->active_fpu.fp_status));
5f7319cd 3923 update_fcr31(env, GETPC());
b6d96bed 3924 return ((uint64_t)fsth2 << 32) | fst2;
57fa1fb3 3925}
57fa1fb3 3926
895c2d04 3927uint64_t helper_float_addr_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt1)
fd4a04eb 3928{
b6d96bed
TS
3929 uint32_t fst0 = fdt0 & 0XFFFFFFFF;
3930 uint32_t fsth0 = fdt0 >> 32;
3931 uint32_t fst1 = fdt1 & 0XFFFFFFFF;
3932 uint32_t fsth1 = fdt1 >> 32;
3933 uint32_t fst2;
3934 uint32_t fsth2;
3935
f01be154
TS
3936 fst2 = float32_add (fst0, fsth0, &env->active_fpu.fp_status);
3937 fsth2 = float32_add (fst1, fsth1, &env->active_fpu.fp_status);
5f7319cd 3938 update_fcr31(env, GETPC());
b6d96bed 3939 return ((uint64_t)fsth2 << 32) | fst2;
fd4a04eb
TS
3940}
3941
895c2d04 3942uint64_t helper_float_mulr_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt1)
57fa1fb3 3943{
b6d96bed
TS
3944 uint32_t fst0 = fdt0 & 0XFFFFFFFF;
3945 uint32_t fsth0 = fdt0 >> 32;
3946 uint32_t fst1 = fdt1 & 0XFFFFFFFF;
3947 uint32_t fsth1 = fdt1 >> 32;
3948 uint32_t fst2;
3949 uint32_t fsth2;
3950
f01be154
TS
3951 fst2 = float32_mul (fst0, fsth0, &env->active_fpu.fp_status);
3952 fsth2 = float32_mul (fst1, fsth1, &env->active_fpu.fp_status);
5f7319cd 3953 update_fcr31(env, GETPC());
b6d96bed 3954 return ((uint64_t)fsth2 << 32) | fst2;
57fa1fb3
TS
3955}
3956
8fc605b8
MR
3957#define FLOAT_MINMAX(name, bits, minmaxfunc) \
3958uint ## bits ## _t helper_float_ ## name (CPUMIPSState *env, \
3959 uint ## bits ## _t fs, \
3960 uint ## bits ## _t ft) \
3961{ \
3962 uint ## bits ## _t fdret; \
3963 \
3964 fdret = float ## bits ## _ ## minmaxfunc(fs, ft, \
3965 &env->active_fpu.fp_status); \
3966 update_fcr31(env, GETPC()); \
3967 return fdret; \
3968}
3969
3970FLOAT_MINMAX(max_s, 32, maxnum)
3971FLOAT_MINMAX(max_d, 64, maxnum)
3972FLOAT_MINMAX(maxa_s, 32, maxnummag)
3973FLOAT_MINMAX(maxa_d, 64, maxnummag)
3974
3975FLOAT_MINMAX(min_s, 32, minnum)
3976FLOAT_MINMAX(min_d, 64, minnum)
3977FLOAT_MINMAX(mina_s, 32, minnummag)
3978FLOAT_MINMAX(mina_d, 64, minnummag)
3979#undef FLOAT_MINMAX
3980
3981/* ternary operations */
3982#define UNFUSED_FMA(prefix, a, b, c, flags) \
3983{ \
3984 a = prefix##_mul(a, b, &env->active_fpu.fp_status); \
3985 if ((flags) & float_muladd_negate_c) { \
3986 a = prefix##_sub(a, c, &env->active_fpu.fp_status); \
3987 } else { \
3988 a = prefix##_add(a, c, &env->active_fpu.fp_status); \
3989 } \
3990 if ((flags) & float_muladd_negate_result) { \
3991 a = prefix##_chs(a); \
3992 } \
3993}
3994
3995/* FMA based operations */
3996#define FLOAT_FMA(name, type) \
3997uint64_t helper_float_ ## name ## _d(CPUMIPSState *env, \
3998 uint64_t fdt0, uint64_t fdt1, \
3999 uint64_t fdt2) \
4000{ \
4001 UNFUSED_FMA(float64, fdt0, fdt1, fdt2, type); \
4002 update_fcr31(env, GETPC()); \
4003 return fdt0; \
4004} \
4005 \
4006uint32_t helper_float_ ## name ## _s(CPUMIPSState *env, \
4007 uint32_t fst0, uint32_t fst1, \
4008 uint32_t fst2) \
4009{ \
4010 UNFUSED_FMA(float32, fst0, fst1, fst2, type); \
4011 update_fcr31(env, GETPC()); \
4012 return fst0; \
4013} \
4014 \
4015uint64_t helper_float_ ## name ## _ps(CPUMIPSState *env, \
4016 uint64_t fdt0, uint64_t fdt1, \
4017 uint64_t fdt2) \
4018{ \
4019 uint32_t fst0 = fdt0 & 0XFFFFFFFF; \
4020 uint32_t fsth0 = fdt0 >> 32; \
4021 uint32_t fst1 = fdt1 & 0XFFFFFFFF; \
4022 uint32_t fsth1 = fdt1 >> 32; \
4023 uint32_t fst2 = fdt2 & 0XFFFFFFFF; \
4024 uint32_t fsth2 = fdt2 >> 32; \
4025 \
4026 UNFUSED_FMA(float32, fst0, fst1, fst2, type); \
4027 UNFUSED_FMA(float32, fsth0, fsth1, fsth2, type); \
4028 update_fcr31(env, GETPC()); \
4029 return ((uint64_t)fsth0 << 32) | fst0; \
4030}
4031FLOAT_FMA(madd, 0)
4032FLOAT_FMA(msub, float_muladd_negate_c)
4033FLOAT_FMA(nmadd, float_muladd_negate_result)
4034FLOAT_FMA(nmsub, float_muladd_negate_result | float_muladd_negate_c)
4035#undef FLOAT_FMA
4036
4037#define FLOAT_FMADDSUB(name, bits, muladd_arg) \
4038uint ## bits ## _t helper_float_ ## name (CPUMIPSState *env, \
4039 uint ## bits ## _t fs, \
4040 uint ## bits ## _t ft, \
4041 uint ## bits ## _t fd) \
4042{ \
4043 uint ## bits ## _t fdret; \
4044 \
4045 fdret = float ## bits ## _muladd(fs, ft, fd, muladd_arg, \
4046 &env->active_fpu.fp_status); \
4047 update_fcr31(env, GETPC()); \
4048 return fdret; \
4049}
4050
4051FLOAT_FMADDSUB(maddf_s, 32, 0)
4052FLOAT_FMADDSUB(maddf_d, 64, 0)
4053FLOAT_FMADDSUB(msubf_s, 32, float_muladd_negate_product)
4054FLOAT_FMADDSUB(msubf_d, 64, float_muladd_negate_product)
4055#undef FLOAT_FMADDSUB
4056
8dfdb87c 4057/* compare operations */
b6d96bed 4058#define FOP_COND_D(op, cond) \
895c2d04
BS
4059void helper_cmp_d_ ## op(CPUMIPSState *env, uint64_t fdt0, \
4060 uint64_t fdt1, int cc) \
b6d96bed 4061{ \
6a385343 4062 int c; \
6a385343 4063 c = cond; \
5f7319cd 4064 update_fcr31(env, GETPC()); \
b6d96bed 4065 if (c) \
f01be154 4066 SET_FP_COND(cc, env->active_fpu); \
b6d96bed 4067 else \
f01be154 4068 CLEAR_FP_COND(cc, env->active_fpu); \
b6d96bed 4069} \
895c2d04
BS
4070void helper_cmpabs_d_ ## op(CPUMIPSState *env, uint64_t fdt0, \
4071 uint64_t fdt1, int cc) \
b6d96bed
TS
4072{ \
4073 int c; \
4074 fdt0 = float64_abs(fdt0); \
4075 fdt1 = float64_abs(fdt1); \
4076 c = cond; \
5f7319cd 4077 update_fcr31(env, GETPC()); \
b6d96bed 4078 if (c) \
f01be154 4079 SET_FP_COND(cc, env->active_fpu); \
b6d96bed 4080 else \
f01be154 4081 CLEAR_FP_COND(cc, env->active_fpu); \
fd4a04eb
TS
4082}
4083
fd4a04eb 4084/* NOTE: the comma operator will make "cond" to eval to false,
3a599383
AJ
4085 * but float64_unordered_quiet() is still called. */
4086FOP_COND_D(f, (float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status), 0))
4087FOP_COND_D(un, float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status))
06a0e6b1 4088FOP_COND_D(eq, float64_eq_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
211315fb 4089FOP_COND_D(ueq, float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status) || float64_eq_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
06a0e6b1
AJ
4090FOP_COND_D(olt, float64_lt_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
4091FOP_COND_D(ult, float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status) || float64_lt_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
4092FOP_COND_D(ole, float64_le_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
4093FOP_COND_D(ule, float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status) || float64_le_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
fd4a04eb 4094/* NOTE: the comma operator will make "cond" to eval to false,
3a599383
AJ
4095 * but float64_unordered() is still called. */
4096FOP_COND_D(sf, (float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status), 0))
4097FOP_COND_D(ngle,float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status))
06a0e6b1
AJ
4098FOP_COND_D(seq, float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
4099FOP_COND_D(ngl, float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status) || float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
4100FOP_COND_D(lt, float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
3a599383 4101FOP_COND_D(nge, float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status) || float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
06a0e6b1 4102FOP_COND_D(le, float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
3a599383 4103FOP_COND_D(ngt, float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status) || float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
b6d96bed
TS
4104
4105#define FOP_COND_S(op, cond) \
895c2d04
BS
4106void helper_cmp_s_ ## op(CPUMIPSState *env, uint32_t fst0, \
4107 uint32_t fst1, int cc) \
b6d96bed 4108{ \
6a385343 4109 int c; \
6a385343 4110 c = cond; \
5f7319cd 4111 update_fcr31(env, GETPC()); \
b6d96bed 4112 if (c) \
f01be154 4113 SET_FP_COND(cc, env->active_fpu); \
b6d96bed 4114 else \
f01be154 4115 CLEAR_FP_COND(cc, env->active_fpu); \
b6d96bed 4116} \
895c2d04
BS
4117void helper_cmpabs_s_ ## op(CPUMIPSState *env, uint32_t fst0, \
4118 uint32_t fst1, int cc) \
b6d96bed
TS
4119{ \
4120 int c; \
4121 fst0 = float32_abs(fst0); \
4122 fst1 = float32_abs(fst1); \
4123 c = cond; \
5f7319cd 4124 update_fcr31(env, GETPC()); \
b6d96bed 4125 if (c) \
f01be154 4126 SET_FP_COND(cc, env->active_fpu); \
b6d96bed 4127 else \
f01be154 4128 CLEAR_FP_COND(cc, env->active_fpu); \
fd4a04eb
TS
4129}
4130
fd4a04eb 4131/* NOTE: the comma operator will make "cond" to eval to false,
3a599383
AJ
4132 * but float32_unordered_quiet() is still called. */
4133FOP_COND_S(f, (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status), 0))
4134FOP_COND_S(un, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status))
06a0e6b1 4135FOP_COND_S(eq, float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status))
211315fb 4136FOP_COND_S(ueq, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status) || float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status))
06a0e6b1
AJ
4137FOP_COND_S(olt, float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status))
4138FOP_COND_S(ult, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status) || float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status))
4139FOP_COND_S(ole, float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status))
4140FOP_COND_S(ule, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status) || float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status))
fd4a04eb 4141/* NOTE: the comma operator will make "cond" to eval to false,
3a599383
AJ
4142 * but float32_unordered() is still called. */
4143FOP_COND_S(sf, (float32_unordered(fst1, fst0, &env->active_fpu.fp_status), 0))
4144FOP_COND_S(ngle,float32_unordered(fst1, fst0, &env->active_fpu.fp_status))
06a0e6b1
AJ
4145FOP_COND_S(seq, float32_eq(fst0, fst1, &env->active_fpu.fp_status))
4146FOP_COND_S(ngl, float32_unordered(fst1, fst0, &env->active_fpu.fp_status) || float32_eq(fst0, fst1, &env->active_fpu.fp_status))
4147FOP_COND_S(lt, float32_lt(fst0, fst1, &env->active_fpu.fp_status))
3a599383 4148FOP_COND_S(nge, float32_unordered(fst1, fst0, &env->active_fpu.fp_status) || float32_lt(fst0, fst1, &env->active_fpu.fp_status))
06a0e6b1 4149FOP_COND_S(le, float32_le(fst0, fst1, &env->active_fpu.fp_status))
3a599383 4150FOP_COND_S(ngt, float32_unordered(fst1, fst0, &env->active_fpu.fp_status) || float32_le(fst0, fst1, &env->active_fpu.fp_status))
b6d96bed
TS
4151
4152#define FOP_COND_PS(op, condl, condh) \
895c2d04
BS
4153void helper_cmp_ps_ ## op(CPUMIPSState *env, uint64_t fdt0, \
4154 uint64_t fdt1, int cc) \
b6d96bed 4155{ \
6a385343
AJ
4156 uint32_t fst0, fsth0, fst1, fsth1; \
4157 int ch, cl; \
6a385343
AJ
4158 fst0 = fdt0 & 0XFFFFFFFF; \
4159 fsth0 = fdt0 >> 32; \
4160 fst1 = fdt1 & 0XFFFFFFFF; \
4161 fsth1 = fdt1 >> 32; \
4162 cl = condl; \
4163 ch = condh; \
5f7319cd 4164 update_fcr31(env, GETPC()); \
b6d96bed 4165 if (cl) \
f01be154 4166 SET_FP_COND(cc, env->active_fpu); \
b6d96bed 4167 else \
f01be154 4168 CLEAR_FP_COND(cc, env->active_fpu); \
b6d96bed 4169 if (ch) \
f01be154 4170 SET_FP_COND(cc + 1, env->active_fpu); \
b6d96bed 4171 else \
f01be154 4172 CLEAR_FP_COND(cc + 1, env->active_fpu); \
b6d96bed 4173} \
895c2d04
BS
4174void helper_cmpabs_ps_ ## op(CPUMIPSState *env, uint64_t fdt0, \
4175 uint64_t fdt1, int cc) \
b6d96bed 4176{ \
6a385343
AJ
4177 uint32_t fst0, fsth0, fst1, fsth1; \
4178 int ch, cl; \
4179 fst0 = float32_abs(fdt0 & 0XFFFFFFFF); \
4180 fsth0 = float32_abs(fdt0 >> 32); \
4181 fst1 = float32_abs(fdt1 & 0XFFFFFFFF); \
4182 fsth1 = float32_abs(fdt1 >> 32); \
4183 cl = condl; \
4184 ch = condh; \
5f7319cd 4185 update_fcr31(env, GETPC()); \
b6d96bed 4186 if (cl) \
f01be154 4187 SET_FP_COND(cc, env->active_fpu); \
b6d96bed 4188 else \
f01be154 4189 CLEAR_FP_COND(cc, env->active_fpu); \
b6d96bed 4190 if (ch) \
f01be154 4191 SET_FP_COND(cc + 1, env->active_fpu); \
b6d96bed 4192 else \
f01be154 4193 CLEAR_FP_COND(cc + 1, env->active_fpu); \
fd4a04eb
TS
4194}
4195
4196/* NOTE: the comma operator will make "cond" to eval to false,
3a599383
AJ
4197 * but float32_unordered_quiet() is still called. */
4198FOP_COND_PS(f, (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status), 0),
4199 (float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status), 0))
4200FOP_COND_PS(un, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status),
4201 float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status))
06a0e6b1
AJ
4202FOP_COND_PS(eq, float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status),
4203 float32_eq_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
211315fb
AJ
4204FOP_COND_PS(ueq, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status) || float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status),
4205 float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status) || float32_eq_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
06a0e6b1
AJ
4206FOP_COND_PS(olt, float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status),
4207 float32_lt_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
4208FOP_COND_PS(ult, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status) || float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status),
4209 float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status) || float32_lt_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
4210FOP_COND_PS(ole, float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status),
4211 float32_le_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
4212FOP_COND_PS(ule, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status) || float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status),
4213 float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status) || float32_le_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
fd4a04eb 4214/* NOTE: the comma operator will make "cond" to eval to false,
3a599383
AJ
4215 * but float32_unordered() is still called. */
4216FOP_COND_PS(sf, (float32_unordered(fst1, fst0, &env->active_fpu.fp_status), 0),
4217 (float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status), 0))
4218FOP_COND_PS(ngle,float32_unordered(fst1, fst0, &env->active_fpu.fp_status),
4219 float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status))
06a0e6b1
AJ
4220FOP_COND_PS(seq, float32_eq(fst0, fst1, &env->active_fpu.fp_status),
4221 float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
4222FOP_COND_PS(ngl, float32_unordered(fst1, fst0, &env->active_fpu.fp_status) || float32_eq(fst0, fst1, &env->active_fpu.fp_status),
4223 float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status) || float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
4224FOP_COND_PS(lt, float32_lt(fst0, fst1, &env->active_fpu.fp_status),
4225 float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
3a599383
AJ
4226FOP_COND_PS(nge, float32_unordered(fst1, fst0, &env->active_fpu.fp_status) || float32_lt(fst0, fst1, &env->active_fpu.fp_status),
4227 float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status) || float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
06a0e6b1
AJ
4228FOP_COND_PS(le, float32_le(fst0, fst1, &env->active_fpu.fp_status),
4229 float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
3a599383
AJ
4230FOP_COND_PS(ngt, float32_unordered(fst1, fst0, &env->active_fpu.fp_status) || float32_le(fst0, fst1, &env->active_fpu.fp_status),
4231 float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status) || float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
3f493883
YK
4232
4233/* R6 compare operations */
4234#define FOP_CONDN_D(op, cond) \
4235uint64_t helper_r6_cmp_d_ ## op(CPUMIPSState * env, uint64_t fdt0, \
4236 uint64_t fdt1) \
4237{ \
4238 uint64_t c; \
4239 c = cond; \
4240 update_fcr31(env, GETPC()); \
4241 if (c) { \
4242 return -1; \
4243 } else { \
4244 return 0; \
4245 } \
4246}
4247
4248/* NOTE: the comma operator will make "cond" to eval to false,
4249 * but float64_unordered_quiet() is still called. */
4250FOP_CONDN_D(af, (float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status), 0))
4251FOP_CONDN_D(un, (float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)))
4252FOP_CONDN_D(eq, (float64_eq_quiet(fdt0, fdt1, &env->active_fpu.fp_status)))
4253FOP_CONDN_D(ueq, (float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)
4254 || float64_eq_quiet(fdt0, fdt1, &env->active_fpu.fp_status)))
4255FOP_CONDN_D(lt, (float64_lt_quiet(fdt0, fdt1, &env->active_fpu.fp_status)))
4256FOP_CONDN_D(ult, (float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)
4257 || float64_lt_quiet(fdt0, fdt1, &env->active_fpu.fp_status)))
4258FOP_CONDN_D(le, (float64_le_quiet(fdt0, fdt1, &env->active_fpu.fp_status)))
4259FOP_CONDN_D(ule, (float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)
4260 || float64_le_quiet(fdt0, fdt1, &env->active_fpu.fp_status)))
4261/* NOTE: the comma operator will make "cond" to eval to false,
4262 * but float64_unordered() is still called. */
4263FOP_CONDN_D(saf, (float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status), 0))
4264FOP_CONDN_D(sun, (float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status)))
4265FOP_CONDN_D(seq, (float64_eq(fdt0, fdt1, &env->active_fpu.fp_status)))
4266FOP_CONDN_D(sueq, (float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status)
4267 || float64_eq(fdt0, fdt1, &env->active_fpu.fp_status)))
4268FOP_CONDN_D(slt, (float64_lt(fdt0, fdt1, &env->active_fpu.fp_status)))
4269FOP_CONDN_D(sult, (float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status)
4270 || float64_lt(fdt0, fdt1, &env->active_fpu.fp_status)))
4271FOP_CONDN_D(sle, (float64_le(fdt0, fdt1, &env->active_fpu.fp_status)))
4272FOP_CONDN_D(sule, (float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status)
4273 || float64_le(fdt0, fdt1, &env->active_fpu.fp_status)))
4274FOP_CONDN_D(or, (float64_le_quiet(fdt1, fdt0, &env->active_fpu.fp_status)
4275 || float64_le_quiet(fdt0, fdt1, &env->active_fpu.fp_status)))
4276FOP_CONDN_D(une, (float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)
4277 || float64_lt_quiet(fdt1, fdt0, &env->active_fpu.fp_status)
4278 || float64_lt_quiet(fdt0, fdt1, &env->active_fpu.fp_status)))
4279FOP_CONDN_D(ne, (float64_lt_quiet(fdt1, fdt0, &env->active_fpu.fp_status)
4280 || float64_lt_quiet(fdt0, fdt1, &env->active_fpu.fp_status)))
4281FOP_CONDN_D(sor, (float64_le(fdt1, fdt0, &env->active_fpu.fp_status)
4282 || float64_le(fdt0, fdt1, &env->active_fpu.fp_status)))
4283FOP_CONDN_D(sune, (float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status)
4284 || float64_lt(fdt1, fdt0, &env->active_fpu.fp_status)
4285 || float64_lt(fdt0, fdt1, &env->active_fpu.fp_status)))
4286FOP_CONDN_D(sne, (float64_lt(fdt1, fdt0, &env->active_fpu.fp_status)
4287 || float64_lt(fdt0, fdt1, &env->active_fpu.fp_status)))
4288
4289#define FOP_CONDN_S(op, cond) \
4290uint32_t helper_r6_cmp_s_ ## op(CPUMIPSState * env, uint32_t fst0, \
4291 uint32_t fst1) \
4292{ \
4293 uint64_t c; \
4294 c = cond; \
4295 update_fcr31(env, GETPC()); \
4296 if (c) { \
4297 return -1; \
4298 } else { \
4299 return 0; \
4300 } \
4301}
4302
4303/* NOTE: the comma operator will make "cond" to eval to false,
4304 * but float32_unordered_quiet() is still called. */
4305FOP_CONDN_S(af, (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status), 0))
4306FOP_CONDN_S(un, (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)))
4307FOP_CONDN_S(eq, (float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status)))
4308FOP_CONDN_S(ueq, (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)
4309 || float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status)))
4310FOP_CONDN_S(lt, (float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status)))
4311FOP_CONDN_S(ult, (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)
4312 || float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status)))
4313FOP_CONDN_S(le, (float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status)))
4314FOP_CONDN_S(ule, (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)
4315 || float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status)))
4316/* NOTE: the comma operator will make "cond" to eval to false,
4317 * but float32_unordered() is still called. */
4318FOP_CONDN_S(saf, (float32_unordered(fst1, fst0, &env->active_fpu.fp_status), 0))
4319FOP_CONDN_S(sun, (float32_unordered(fst1, fst0, &env->active_fpu.fp_status)))
4320FOP_CONDN_S(seq, (float32_eq(fst0, fst1, &env->active_fpu.fp_status)))
4321FOP_CONDN_S(sueq, (float32_unordered(fst1, fst0, &env->active_fpu.fp_status)
4322 || float32_eq(fst0, fst1, &env->active_fpu.fp_status)))
4323FOP_CONDN_S(slt, (float32_lt(fst0, fst1, &env->active_fpu.fp_status)))
4324FOP_CONDN_S(sult, (float32_unordered(fst1, fst0, &env->active_fpu.fp_status)
4325 || float32_lt(fst0, fst1, &env->active_fpu.fp_status)))
4326FOP_CONDN_S(sle, (float32_le(fst0, fst1, &env->active_fpu.fp_status)))
4327FOP_CONDN_S(sule, (float32_unordered(fst1, fst0, &env->active_fpu.fp_status)
4328 || float32_le(fst0, fst1, &env->active_fpu.fp_status)))
4329FOP_CONDN_S(or, (float32_le_quiet(fst1, fst0, &env->active_fpu.fp_status)
4330 || float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status)))
4331FOP_CONDN_S(une, (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)
4332 || float32_lt_quiet(fst1, fst0, &env->active_fpu.fp_status)
4333 || float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status)))
4334FOP_CONDN_S(ne, (float32_lt_quiet(fst1, fst0, &env->active_fpu.fp_status)
4335 || float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status)))
4336FOP_CONDN_S(sor, (float32_le(fst1, fst0, &env->active_fpu.fp_status)
4337 || float32_le(fst0, fst1, &env->active_fpu.fp_status)))
4338FOP_CONDN_S(sune, (float32_unordered(fst1, fst0, &env->active_fpu.fp_status)
4339 || float32_lt(fst1, fst0, &env->active_fpu.fp_status)
4340 || float32_lt(fst0, fst1, &env->active_fpu.fp_status)))
4341FOP_CONDN_S(sne, (float32_lt(fst1, fst0, &env->active_fpu.fp_status)
4342 || float32_lt(fst0, fst1, &env->active_fpu.fp_status)))
f7685877
YK
4343
4344/* MSA */
4345/* Data format min and max values */
4346#define DF_BITS(df) (1 << ((df) + 3))
4347
4348/* Element-by-element access macros */
4349#define DF_ELEMENTS(df) (MSA_WRLEN / DF_BITS(df))
4350
adc370a4
YK
4351#if !defined(CONFIG_USER_ONLY)
4352#define MEMOP_IDX(DF) \
4353 TCGMemOpIdx oi = make_memop_idx(MO_TE | DF | MO_UNALN, \
97ed5ccd 4354 cpu_mmu_index(env, false));
adc370a4
YK
4355#else
4356#define MEMOP_IDX(DF)
4357#endif
f7685877 4358
83be6b54
MM
4359void helper_msa_ld_b(CPUMIPSState *env, uint32_t wd,
4360 target_ulong addr)
4361{
4362 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4363 MEMOP_IDX(DF_BYTE)
4364#if !defined(CONFIG_USER_ONLY)
4365#if !defined(HOST_WORDS_BIGENDIAN)
4366 pwd->b[0] = helper_ret_ldub_mmu(env, addr + (0 << DF_BYTE), oi, GETPC());
4367 pwd->b[1] = helper_ret_ldub_mmu(env, addr + (1 << DF_BYTE), oi, GETPC());
4368 pwd->b[2] = helper_ret_ldub_mmu(env, addr + (2 << DF_BYTE), oi, GETPC());
4369 pwd->b[3] = helper_ret_ldub_mmu(env, addr + (3 << DF_BYTE), oi, GETPC());
4370 pwd->b[4] = helper_ret_ldub_mmu(env, addr + (4 << DF_BYTE), oi, GETPC());
4371 pwd->b[5] = helper_ret_ldub_mmu(env, addr + (5 << DF_BYTE), oi, GETPC());
4372 pwd->b[6] = helper_ret_ldub_mmu(env, addr + (6 << DF_BYTE), oi, GETPC());
4373 pwd->b[7] = helper_ret_ldub_mmu(env, addr + (7 << DF_BYTE), oi, GETPC());
4374 pwd->b[8] = helper_ret_ldub_mmu(env, addr + (8 << DF_BYTE), oi, GETPC());
4375 pwd->b[9] = helper_ret_ldub_mmu(env, addr + (9 << DF_BYTE), oi, GETPC());
4376 pwd->b[10] = helper_ret_ldub_mmu(env, addr + (10 << DF_BYTE), oi, GETPC());
4377 pwd->b[11] = helper_ret_ldub_mmu(env, addr + (11 << DF_BYTE), oi, GETPC());
4378 pwd->b[12] = helper_ret_ldub_mmu(env, addr + (12 << DF_BYTE), oi, GETPC());
4379 pwd->b[13] = helper_ret_ldub_mmu(env, addr + (13 << DF_BYTE), oi, GETPC());
4380 pwd->b[14] = helper_ret_ldub_mmu(env, addr + (14 << DF_BYTE), oi, GETPC());
4381 pwd->b[15] = helper_ret_ldub_mmu(env, addr + (15 << DF_BYTE), oi, GETPC());
4382#else
4383 pwd->b[0] = helper_ret_ldub_mmu(env, addr + (7 << DF_BYTE), oi, GETPC());
4384 pwd->b[1] = helper_ret_ldub_mmu(env, addr + (6 << DF_BYTE), oi, GETPC());
4385 pwd->b[2] = helper_ret_ldub_mmu(env, addr + (5 << DF_BYTE), oi, GETPC());
4386 pwd->b[3] = helper_ret_ldub_mmu(env, addr + (4 << DF_BYTE), oi, GETPC());
4387 pwd->b[4] = helper_ret_ldub_mmu(env, addr + (3 << DF_BYTE), oi, GETPC());
4388 pwd->b[5] = helper_ret_ldub_mmu(env, addr + (2 << DF_BYTE), oi, GETPC());
4389 pwd->b[6] = helper_ret_ldub_mmu(env, addr + (1 << DF_BYTE), oi, GETPC());
4390 pwd->b[7] = helper_ret_ldub_mmu(env, addr + (0 << DF_BYTE), oi, GETPC());
4391 pwd->b[8] = helper_ret_ldub_mmu(env, addr + (15 << DF_BYTE), oi, GETPC());
4392 pwd->b[9] = helper_ret_ldub_mmu(env, addr + (14 << DF_BYTE), oi, GETPC());
4393 pwd->b[10] = helper_ret_ldub_mmu(env, addr + (13 << DF_BYTE), oi, GETPC());
4394 pwd->b[11] = helper_ret_ldub_mmu(env, addr + (12 << DF_BYTE), oi, GETPC());
4395 pwd->b[12] = helper_ret_ldub_mmu(env, addr + (11 << DF_BYTE), oi, GETPC());
4396 pwd->b[13] = helper_ret_ldub_mmu(env, addr + (10 << DF_BYTE), oi, GETPC());
4397 pwd->b[14] = helper_ret_ldub_mmu(env, addr + (9 << DF_BYTE), oi, GETPC());
4398 pwd->b[15] = helper_ret_ldub_mmu(env, addr + (8 << DF_BYTE), oi, GETPC());
4399#endif
4400#else
4401#if !defined(HOST_WORDS_BIGENDIAN)
4402 pwd->b[0] = cpu_ldub_data(env, addr + (0 << DF_BYTE));
4403 pwd->b[1] = cpu_ldub_data(env, addr + (1 << DF_BYTE));
4404 pwd->b[2] = cpu_ldub_data(env, addr + (2 << DF_BYTE));
4405 pwd->b[3] = cpu_ldub_data(env, addr + (3 << DF_BYTE));
4406 pwd->b[4] = cpu_ldub_data(env, addr + (4 << DF_BYTE));
4407 pwd->b[5] = cpu_ldub_data(env, addr + (5 << DF_BYTE));
4408 pwd->b[6] = cpu_ldub_data(env, addr + (6 << DF_BYTE));
4409 pwd->b[7] = cpu_ldub_data(env, addr + (7 << DF_BYTE));
4410 pwd->b[8] = cpu_ldub_data(env, addr + (8 << DF_BYTE));
4411 pwd->b[9] = cpu_ldub_data(env, addr + (9 << DF_BYTE));
4412 pwd->b[10] = cpu_ldub_data(env, addr + (10 << DF_BYTE));
4413 pwd->b[11] = cpu_ldub_data(env, addr + (11 << DF_BYTE));
4414 pwd->b[12] = cpu_ldub_data(env, addr + (12 << DF_BYTE));
4415 pwd->b[13] = cpu_ldub_data(env, addr + (13 << DF_BYTE));
4416 pwd->b[14] = cpu_ldub_data(env, addr + (14 << DF_BYTE));
4417 pwd->b[15] = cpu_ldub_data(env, addr + (15 << DF_BYTE));
4418#else
4419 pwd->b[0] = cpu_ldub_data(env, addr + (7 << DF_BYTE));
4420 pwd->b[1] = cpu_ldub_data(env, addr + (6 << DF_BYTE));
4421 pwd->b[2] = cpu_ldub_data(env, addr + (5 << DF_BYTE));
4422 pwd->b[3] = cpu_ldub_data(env, addr + (4 << DF_BYTE));
4423 pwd->b[4] = cpu_ldub_data(env, addr + (3 << DF_BYTE));
4424 pwd->b[5] = cpu_ldub_data(env, addr + (2 << DF_BYTE));
4425 pwd->b[6] = cpu_ldub_data(env, addr + (1 << DF_BYTE));
4426 pwd->b[7] = cpu_ldub_data(env, addr + (0 << DF_BYTE));
4427 pwd->b[8] = cpu_ldub_data(env, addr + (15 << DF_BYTE));
4428 pwd->b[9] = cpu_ldub_data(env, addr + (14 << DF_BYTE));
4429 pwd->b[10] = cpu_ldub_data(env, addr + (13 << DF_BYTE));
4430 pwd->b[11] = cpu_ldub_data(env, addr + (12 << DF_BYTE));
4431 pwd->b[12] = cpu_ldub_data(env, addr + (11 << DF_BYTE));
4432 pwd->b[13] = cpu_ldub_data(env, addr + (10 << DF_BYTE));
4433 pwd->b[14] = cpu_ldub_data(env, addr + (9 << DF_BYTE));
4434 pwd->b[15] = cpu_ldub_data(env, addr + (8 << DF_BYTE));
4435#endif
4436#endif
4437}
4438
4439void helper_msa_ld_h(CPUMIPSState *env, uint32_t wd,
4440 target_ulong addr)
4441{
4442 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4443 MEMOP_IDX(DF_HALF)
4444#if !defined(CONFIG_USER_ONLY)
4445#if !defined(HOST_WORDS_BIGENDIAN)
4446 pwd->h[0] = helper_ret_lduw_mmu(env, addr + (0 << DF_HALF), oi, GETPC());
4447 pwd->h[1] = helper_ret_lduw_mmu(env, addr + (1 << DF_HALF), oi, GETPC());
4448 pwd->h[2] = helper_ret_lduw_mmu(env, addr + (2 << DF_HALF), oi, GETPC());
4449 pwd->h[3] = helper_ret_lduw_mmu(env, addr + (3 << DF_HALF), oi, GETPC());
4450 pwd->h[4] = helper_ret_lduw_mmu(env, addr + (4 << DF_HALF), oi, GETPC());
4451 pwd->h[5] = helper_ret_lduw_mmu(env, addr + (5 << DF_HALF), oi, GETPC());
4452 pwd->h[6] = helper_ret_lduw_mmu(env, addr + (6 << DF_HALF), oi, GETPC());
4453 pwd->h[7] = helper_ret_lduw_mmu(env, addr + (7 << DF_HALF), oi, GETPC());
4454#else
4455 pwd->h[0] = helper_ret_lduw_mmu(env, addr + (3 << DF_HALF), oi, GETPC());
4456 pwd->h[1] = helper_ret_lduw_mmu(env, addr + (2 << DF_HALF), oi, GETPC());
4457 pwd->h[2] = helper_ret_lduw_mmu(env, addr + (1 << DF_HALF), oi, GETPC());
4458 pwd->h[3] = helper_ret_lduw_mmu(env, addr + (0 << DF_HALF), oi, GETPC());
4459 pwd->h[4] = helper_ret_lduw_mmu(env, addr + (7 << DF_HALF), oi, GETPC());
4460 pwd->h[5] = helper_ret_lduw_mmu(env, addr + (6 << DF_HALF), oi, GETPC());
4461 pwd->h[6] = helper_ret_lduw_mmu(env, addr + (5 << DF_HALF), oi, GETPC());
4462 pwd->h[7] = helper_ret_lduw_mmu(env, addr + (4 << DF_HALF), oi, GETPC());
4463#endif
4464#else
4465#if !defined(HOST_WORDS_BIGENDIAN)
4466 pwd->h[0] = cpu_lduw_data(env, addr + (0 << DF_HALF));
4467 pwd->h[1] = cpu_lduw_data(env, addr + (1 << DF_HALF));
4468 pwd->h[2] = cpu_lduw_data(env, addr + (2 << DF_HALF));
4469 pwd->h[3] = cpu_lduw_data(env, addr + (3 << DF_HALF));
4470 pwd->h[4] = cpu_lduw_data(env, addr + (4 << DF_HALF));
4471 pwd->h[5] = cpu_lduw_data(env, addr + (5 << DF_HALF));
4472 pwd->h[6] = cpu_lduw_data(env, addr + (6 << DF_HALF));
4473 pwd->h[7] = cpu_lduw_data(env, addr + (7 << DF_HALF));
4474#else
4475 pwd->h[0] = cpu_lduw_data(env, addr + (3 << DF_HALF));
4476 pwd->h[1] = cpu_lduw_data(env, addr + (2 << DF_HALF));
4477 pwd->h[2] = cpu_lduw_data(env, addr + (1 << DF_HALF));
4478 pwd->h[3] = cpu_lduw_data(env, addr + (0 << DF_HALF));
4479 pwd->h[4] = cpu_lduw_data(env, addr + (7 << DF_HALF));
4480 pwd->h[5] = cpu_lduw_data(env, addr + (6 << DF_HALF));
4481 pwd->h[6] = cpu_lduw_data(env, addr + (5 << DF_HALF));
4482 pwd->h[7] = cpu_lduw_data(env, addr + (4 << DF_HALF));
4483#endif
4484#endif
4485}
4486
4487void helper_msa_ld_w(CPUMIPSState *env, uint32_t wd,
4488 target_ulong addr)
4489{
4490 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4491 MEMOP_IDX(DF_WORD)
4492#if !defined(CONFIG_USER_ONLY)
4493#if !defined(HOST_WORDS_BIGENDIAN)
4494 pwd->w[0] = helper_ret_ldul_mmu(env, addr + (0 << DF_WORD), oi, GETPC());
4495 pwd->w[1] = helper_ret_ldul_mmu(env, addr + (1 << DF_WORD), oi, GETPC());
4496 pwd->w[2] = helper_ret_ldul_mmu(env, addr + (2 << DF_WORD), oi, GETPC());
4497 pwd->w[3] = helper_ret_ldul_mmu(env, addr + (3 << DF_WORD), oi, GETPC());
4498#else
4499 pwd->w[0] = helper_ret_ldul_mmu(env, addr + (1 << DF_WORD), oi, GETPC());
4500 pwd->w[1] = helper_ret_ldul_mmu(env, addr + (0 << DF_WORD), oi, GETPC());
4501 pwd->w[2] = helper_ret_ldul_mmu(env, addr + (3 << DF_WORD), oi, GETPC());
4502 pwd->w[3] = helper_ret_ldul_mmu(env, addr + (2 << DF_WORD), oi, GETPC());
4503#endif
4504#else
4505#if !defined(HOST_WORDS_BIGENDIAN)
4506 pwd->w[0] = cpu_ldl_data(env, addr + (0 << DF_WORD));
4507 pwd->w[1] = cpu_ldl_data(env, addr + (1 << DF_WORD));
4508 pwd->w[2] = cpu_ldl_data(env, addr + (2 << DF_WORD));
4509 pwd->w[3] = cpu_ldl_data(env, addr + (3 << DF_WORD));
4510#else
4511 pwd->w[0] = cpu_ldl_data(env, addr + (1 << DF_WORD));
4512 pwd->w[1] = cpu_ldl_data(env, addr + (0 << DF_WORD));
4513 pwd->w[2] = cpu_ldl_data(env, addr + (3 << DF_WORD));
4514 pwd->w[3] = cpu_ldl_data(env, addr + (2 << DF_WORD));
4515#endif
4516#endif
f7685877
YK
4517}
4518
83be6b54
MM
4519void helper_msa_ld_d(CPUMIPSState *env, uint32_t wd,
4520 target_ulong addr)
4521{
4522 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4523 MEMOP_IDX(DF_DOUBLE)
adc370a4 4524#if !defined(CONFIG_USER_ONLY)
83be6b54
MM
4525 pwd->d[0] = helper_ret_ldq_mmu(env, addr + (0 << DF_DOUBLE), oi, GETPC());
4526 pwd->d[1] = helper_ret_ldq_mmu(env, addr + (1 << DF_DOUBLE), oi, GETPC());
adc370a4 4527#else
83be6b54
MM
4528 pwd->d[0] = cpu_ldq_data(env, addr + (0 << DF_DOUBLE));
4529 pwd->d[1] = cpu_ldq_data(env, addr + (1 << DF_DOUBLE));
adc370a4 4530#endif
83be6b54 4531}
f7685877 4532
adc370a4
YK
4533#define MSA_PAGESPAN(x) \
4534 ((((x) & ~TARGET_PAGE_MASK) + MSA_WRLEN/8 - 1) >= TARGET_PAGE_SIZE)
4535
4536static inline void ensure_writable_pages(CPUMIPSState *env,
4537 target_ulong addr,
4538 int mmu_idx,
4539 uintptr_t retaddr)
4540{
4541#if !defined(CONFIG_USER_ONLY)
4542 target_ulong page_addr;
4543 if (unlikely(MSA_PAGESPAN(addr))) {
4544 /* first page */
98670d47 4545 probe_write(env, addr, 0, mmu_idx, retaddr);
adc370a4
YK
4546 /* second page */
4547 page_addr = (addr & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
98670d47 4548 probe_write(env, page_addr, 0, mmu_idx, retaddr);
f7685877 4549 }
adc370a4 4550#endif
f7685877 4551}
adc370a4 4552
6decc572
MM
4553void helper_msa_st_b(CPUMIPSState *env, uint32_t wd,
4554 target_ulong addr)
4555{
4556 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4557 int mmu_idx = cpu_mmu_index(env, false);
4558
4559 MEMOP_IDX(DF_BYTE)
4560 ensure_writable_pages(env, addr, mmu_idx, GETPC());
4561#if !defined(CONFIG_USER_ONLY)
4562#if !defined(HOST_WORDS_BIGENDIAN)
4563 helper_ret_stb_mmu(env, addr + (0 << DF_BYTE), pwd->b[0], oi, GETPC());
4564 helper_ret_stb_mmu(env, addr + (1 << DF_BYTE), pwd->b[1], oi, GETPC());
4565 helper_ret_stb_mmu(env, addr + (2 << DF_BYTE), pwd->b[2], oi, GETPC());
4566 helper_ret_stb_mmu(env, addr + (3 << DF_BYTE), pwd->b[3], oi, GETPC());
4567 helper_ret_stb_mmu(env, addr + (4 << DF_BYTE), pwd->b[4], oi, GETPC());
4568 helper_ret_stb_mmu(env, addr + (5 << DF_BYTE), pwd->b[5], oi, GETPC());
4569 helper_ret_stb_mmu(env, addr + (6 << DF_BYTE), pwd->b[6], oi, GETPC());
4570 helper_ret_stb_mmu(env, addr + (7 << DF_BYTE), pwd->b[7], oi, GETPC());
4571 helper_ret_stb_mmu(env, addr + (8 << DF_BYTE), pwd->b[8], oi, GETPC());
4572 helper_ret_stb_mmu(env, addr + (9 << DF_BYTE), pwd->b[9], oi, GETPC());
4573 helper_ret_stb_mmu(env, addr + (10 << DF_BYTE), pwd->b[10], oi, GETPC());
4574 helper_ret_stb_mmu(env, addr + (11 << DF_BYTE), pwd->b[11], oi, GETPC());
4575 helper_ret_stb_mmu(env, addr + (12 << DF_BYTE), pwd->b[12], oi, GETPC());
4576 helper_ret_stb_mmu(env, addr + (13 << DF_BYTE), pwd->b[13], oi, GETPC());
4577 helper_ret_stb_mmu(env, addr + (14 << DF_BYTE), pwd->b[14], oi, GETPC());
4578 helper_ret_stb_mmu(env, addr + (15 << DF_BYTE), pwd->b[15], oi, GETPC());
4579#else
4580 helper_ret_stb_mmu(env, addr + (7 << DF_BYTE), pwd->b[0], oi, GETPC());
4581 helper_ret_stb_mmu(env, addr + (6 << DF_BYTE), pwd->b[1], oi, GETPC());
4582 helper_ret_stb_mmu(env, addr + (5 << DF_BYTE), pwd->b[2], oi, GETPC());
4583 helper_ret_stb_mmu(env, addr + (4 << DF_BYTE), pwd->b[3], oi, GETPC());
4584 helper_ret_stb_mmu(env, addr + (3 << DF_BYTE), pwd->b[4], oi, GETPC());
4585 helper_ret_stb_mmu(env, addr + (2 << DF_BYTE), pwd->b[5], oi, GETPC());
4586 helper_ret_stb_mmu(env, addr + (1 << DF_BYTE), pwd->b[6], oi, GETPC());
4587 helper_ret_stb_mmu(env, addr + (0 << DF_BYTE), pwd->b[7], oi, GETPC());
4588 helper_ret_stb_mmu(env, addr + (15 << DF_BYTE), pwd->b[8], oi, GETPC());
4589 helper_ret_stb_mmu(env, addr + (14 << DF_BYTE), pwd->b[9], oi, GETPC());
4590 helper_ret_stb_mmu(env, addr + (13 << DF_BYTE), pwd->b[10], oi, GETPC());
4591 helper_ret_stb_mmu(env, addr + (12 << DF_BYTE), pwd->b[11], oi, GETPC());
4592 helper_ret_stb_mmu(env, addr + (11 << DF_BYTE), pwd->b[12], oi, GETPC());
4593 helper_ret_stb_mmu(env, addr + (10 << DF_BYTE), pwd->b[13], oi, GETPC());
4594 helper_ret_stb_mmu(env, addr + (9 << DF_BYTE), pwd->b[14], oi, GETPC());
4595 helper_ret_stb_mmu(env, addr + (8 << DF_BYTE), pwd->b[15], oi, GETPC());
4596#endif
4597#else
4598#if !defined(HOST_WORDS_BIGENDIAN)
4599 cpu_stb_data(env, addr + (0 << DF_BYTE), pwd->b[0]);
4600 cpu_stb_data(env, addr + (1 << DF_BYTE), pwd->b[1]);
4601 cpu_stb_data(env, addr + (2 << DF_BYTE), pwd->b[2]);
4602 cpu_stb_data(env, addr + (3 << DF_BYTE), pwd->b[3]);
4603 cpu_stb_data(env, addr + (4 << DF_BYTE), pwd->b[4]);
4604 cpu_stb_data(env, addr + (5 << DF_BYTE), pwd->b[5]);
4605 cpu_stb_data(env, addr + (6 << DF_BYTE), pwd->b[6]);
4606 cpu_stb_data(env, addr + (7 << DF_BYTE), pwd->b[7]);
4607 cpu_stb_data(env, addr + (8 << DF_BYTE), pwd->b[8]);
4608 cpu_stb_data(env, addr + (9 << DF_BYTE), pwd->b[9]);
4609 cpu_stb_data(env, addr + (10 << DF_BYTE), pwd->b[10]);
4610 cpu_stb_data(env, addr + (11 << DF_BYTE), pwd->b[11]);
4611 cpu_stb_data(env, addr + (12 << DF_BYTE), pwd->b[12]);
4612 cpu_stb_data(env, addr + (13 << DF_BYTE), pwd->b[13]);
4613 cpu_stb_data(env, addr + (14 << DF_BYTE), pwd->b[14]);
4614 cpu_stb_data(env, addr + (15 << DF_BYTE), pwd->b[15]);
4615#else
4616 cpu_stb_data(env, addr + (7 << DF_BYTE), pwd->b[0]);
4617 cpu_stb_data(env, addr + (6 << DF_BYTE), pwd->b[1]);
4618 cpu_stb_data(env, addr + (5 << DF_BYTE), pwd->b[2]);
4619 cpu_stb_data(env, addr + (4 << DF_BYTE), pwd->b[3]);
4620 cpu_stb_data(env, addr + (3 << DF_BYTE), pwd->b[4]);
4621 cpu_stb_data(env, addr + (2 << DF_BYTE), pwd->b[5]);
4622 cpu_stb_data(env, addr + (1 << DF_BYTE), pwd->b[6]);
4623 cpu_stb_data(env, addr + (0 << DF_BYTE), pwd->b[7]);
4624 cpu_stb_data(env, addr + (15 << DF_BYTE), pwd->b[8]);
4625 cpu_stb_data(env, addr + (14 << DF_BYTE), pwd->b[9]);
4626 cpu_stb_data(env, addr + (13 << DF_BYTE), pwd->b[10]);
4627 cpu_stb_data(env, addr + (12 << DF_BYTE), pwd->b[11]);
4628 cpu_stb_data(env, addr + (11 << DF_BYTE), pwd->b[12]);
4629 cpu_stb_data(env, addr + (10 << DF_BYTE), pwd->b[13]);
4630 cpu_stb_data(env, addr + (9 << DF_BYTE), pwd->b[14]);
4631 cpu_stb_data(env, addr + (8 << DF_BYTE), pwd->b[15]);
4632#endif
4633#endif
4634}
4635
4636void helper_msa_st_h(CPUMIPSState *env, uint32_t wd,
4637 target_ulong addr)
4638{
4639 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4640 int mmu_idx = cpu_mmu_index(env, false);
4641
4642 MEMOP_IDX(DF_HALF)
4643 ensure_writable_pages(env, addr, mmu_idx, GETPC());
4644#if !defined(CONFIG_USER_ONLY)
4645#if !defined(HOST_WORDS_BIGENDIAN)
4646 helper_ret_stw_mmu(env, addr + (0 << DF_HALF), pwd->h[0], oi, GETPC());
4647 helper_ret_stw_mmu(env, addr + (1 << DF_HALF), pwd->h[1], oi, GETPC());
4648 helper_ret_stw_mmu(env, addr + (2 << DF_HALF), pwd->h[2], oi, GETPC());
4649 helper_ret_stw_mmu(env, addr + (3 << DF_HALF), pwd->h[3], oi, GETPC());
4650 helper_ret_stw_mmu(env, addr + (4 << DF_HALF), pwd->h[4], oi, GETPC());
4651 helper_ret_stw_mmu(env, addr + (5 << DF_HALF), pwd->h[5], oi, GETPC());
4652 helper_ret_stw_mmu(env, addr + (6 << DF_HALF), pwd->h[6], oi, GETPC());
4653 helper_ret_stw_mmu(env, addr + (7 << DF_HALF), pwd->h[7], oi, GETPC());
4654#else
4655 helper_ret_stw_mmu(env, addr + (3 << DF_HALF), pwd->h[0], oi, GETPC());
4656 helper_ret_stw_mmu(env, addr + (2 << DF_HALF), pwd->h[1], oi, GETPC());
4657 helper_ret_stw_mmu(env, addr + (1 << DF_HALF), pwd->h[2], oi, GETPC());
4658 helper_ret_stw_mmu(env, addr + (0 << DF_HALF), pwd->h[3], oi, GETPC());
4659 helper_ret_stw_mmu(env, addr + (7 << DF_HALF), pwd->h[4], oi, GETPC());
4660 helper_ret_stw_mmu(env, addr + (6 << DF_HALF), pwd->h[5], oi, GETPC());
4661 helper_ret_stw_mmu(env, addr + (5 << DF_HALF), pwd->h[6], oi, GETPC());
4662 helper_ret_stw_mmu(env, addr + (4 << DF_HALF), pwd->h[7], oi, GETPC());
4663#endif
4664#else
4665#if !defined(HOST_WORDS_BIGENDIAN)
4666 cpu_stw_data(env, addr + (0 << DF_HALF), pwd->h[0]);
4667 cpu_stw_data(env, addr + (1 << DF_HALF), pwd->h[1]);
4668 cpu_stw_data(env, addr + (2 << DF_HALF), pwd->h[2]);
4669 cpu_stw_data(env, addr + (3 << DF_HALF), pwd->h[3]);
4670 cpu_stw_data(env, addr + (4 << DF_HALF), pwd->h[4]);
4671 cpu_stw_data(env, addr + (5 << DF_HALF), pwd->h[5]);
4672 cpu_stw_data(env, addr + (6 << DF_HALF), pwd->h[6]);
4673 cpu_stw_data(env, addr + (7 << DF_HALF), pwd->h[7]);
4674#else
4675 cpu_stw_data(env, addr + (3 << DF_HALF), pwd->h[0]);
4676 cpu_stw_data(env, addr + (2 << DF_HALF), pwd->h[1]);
4677 cpu_stw_data(env, addr + (1 << DF_HALF), pwd->h[2]);
4678 cpu_stw_data(env, addr + (0 << DF_HALF), pwd->h[3]);
4679 cpu_stw_data(env, addr + (7 << DF_HALF), pwd->h[4]);
4680 cpu_stw_data(env, addr + (6 << DF_HALF), pwd->h[5]);
4681 cpu_stw_data(env, addr + (5 << DF_HALF), pwd->h[6]);
4682 cpu_stw_data(env, addr + (4 << DF_HALF), pwd->h[7]);
4683#endif
4684#endif
adc370a4
YK
4685}
4686
6decc572
MM
4687void helper_msa_st_w(CPUMIPSState *env, uint32_t wd,
4688 target_ulong addr)
4689{
4690 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4691 int mmu_idx = cpu_mmu_index(env, false);
4692
4693 MEMOP_IDX(DF_WORD)
4694 ensure_writable_pages(env, addr, mmu_idx, GETPC());
adc370a4 4695#if !defined(CONFIG_USER_ONLY)
6decc572
MM
4696#if !defined(HOST_WORDS_BIGENDIAN)
4697 helper_ret_stl_mmu(env, addr + (0 << DF_WORD), oi, GETPC(), pwd->w[0]);
4698 helper_ret_stl_mmu(env, addr + (1 << DF_WORD), oi, GETPC(), pwd->w[1]);
4699 helper_ret_stl_mmu(env, addr + (2 << DF_WORD), oi, GETPC(), pwd->w[2]);
4700 helper_ret_stl_mmu(env, addr + (3 << DF_WORD), oi, GETPC(), pwd->w[3]);
adc370a4 4701#else
6decc572
MM
4702 helper_ret_stl_mmu(env, addr + (1 << DF_WORD), oi, GETPC(), pwd->w[0]);
4703 helper_ret_stl_mmu(env, addr + (0 << DF_WORD), oi, GETPC(), pwd->w[1]);
4704 helper_ret_stl_mmu(env, addr + (3 << DF_WORD), oi, GETPC(), pwd->w[2]);
4705 helper_ret_stl_mmu(env, addr + (2 << DF_WORD), oi, GETPC(), pwd->w[3]);
adc370a4 4706#endif
6decc572
MM
4707#else
4708#if !defined(HOST_WORDS_BIGENDIAN)
4709 cpu_stl_data(env, addr + (0 << DF_WORD), pwd->w[0]);
4710 cpu_stl_data(env, addr + (1 << DF_WORD), pwd->w[1]);
4711 cpu_stl_data(env, addr + (2 << DF_WORD), pwd->w[2]);
4712 cpu_stl_data(env, addr + (3 << DF_WORD), pwd->w[3]);
4713#else
4714 cpu_stl_data(env, addr + (1 << DF_WORD), pwd->w[0]);
4715 cpu_stl_data(env, addr + (0 << DF_WORD), pwd->w[1]);
4716 cpu_stl_data(env, addr + (3 << DF_WORD), pwd->w[2]);
4717 cpu_stl_data(env, addr + (2 << DF_WORD), pwd->w[3]);
4718#endif
4719#endif
4720}
4721
4722void helper_msa_st_d(CPUMIPSState *env, uint32_t wd,
4723 target_ulong addr)
4724{
4725 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
4726 int mmu_idx = cpu_mmu_index(env, false);
4727
4728 MEMOP_IDX(DF_DOUBLE)
4729 ensure_writable_pages(env, addr, mmu_idx, GETPC());
4730#if !defined(CONFIG_USER_ONLY)
4731 helper_ret_stq_mmu(env, addr + (0 << DF_DOUBLE), pwd->d[0], oi, GETPC());
4732 helper_ret_stq_mmu(env, addr + (1 << DF_DOUBLE), pwd->d[1], oi, GETPC());
4733#else
4734 cpu_stq_data(env, addr + (0 << DF_DOUBLE), pwd->d[0]);
4735 cpu_stq_data(env, addr + (1 << DF_DOUBLE), pwd->d[1]);
4736#endif
4737}
0d74a222
LA
4738
4739void helper_cache(CPUMIPSState *env, target_ulong addr, uint32_t op)
4740{
4741#ifndef CONFIG_USER_ONLY
4742 target_ulong index = addr & 0x1fffffff;
4743 if (op == 9) {
4744 /* Index Store Tag */
4745 memory_region_dispatch_write(env->itc_tag, index, env->CP0_TagLo,
4746 8, MEMTXATTRS_UNSPECIFIED);
4747 } else if (op == 5) {
4748 /* Index Load Tag */
4749 memory_region_dispatch_read(env->itc_tag, index, &env->CP0_TagLo,
4750 8, MEMTXATTRS_UNSPECIFIED);
4751 }
4752#endif
4753}
This page took 1.726525 seconds and 4 git commands to generate.