1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#include <stdlib.h>
20#include "cpu.h"
21#include "dyngen-exec.h"
22
23#include "host-utils.h"
24
25#include "helper.h"
26
27#if !defined(CONFIG_USER_ONLY)
28#include "softmmu_exec.h"
29#endif
30
31#ifndef CONFIG_USER_ONLY
32static inline void cpu_mips_tlb_flush (CPUState *env, int flush_global);
33#endif
34
35static inline void compute_hflags(CPUState *env)
36{
37 env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 |
38 MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU |
39 MIPS_HFLAG_UX);
40 if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
41 !(env->CP0_Status & (1 << CP0St_ERL)) &&
42 !(env->hflags & MIPS_HFLAG_DM)) {
43 env->hflags |= (env->CP0_Status >> CP0St_KSU) & MIPS_HFLAG_KSU;
44 }
45#if defined(TARGET_MIPS64)
46 if (((env->hflags & MIPS_HFLAG_KSU) != MIPS_HFLAG_UM) ||
47 (env->CP0_Status & (1 << CP0St_PX)) ||
48 (env->CP0_Status & (1 << CP0St_UX))) {
49 env->hflags |= MIPS_HFLAG_64;
50 }
51 if (env->CP0_Status & (1 << CP0St_UX)) {
52 env->hflags |= MIPS_HFLAG_UX;
53 }
54#endif
55 if ((env->CP0_Status & (1 << CP0St_CU0)) ||
56 !(env->hflags & MIPS_HFLAG_KSU)) {
57 env->hflags |= MIPS_HFLAG_CP0;
58 }
59 if (env->CP0_Status & (1 << CP0St_CU1)) {
60 env->hflags |= MIPS_HFLAG_FPU;
61 }
62 if (env->CP0_Status & (1 << CP0St_FR)) {
63 env->hflags |= MIPS_HFLAG_F64;
64 }
65 if (env->insn_flags & ISA_MIPS32R2) {
66 if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
67 env->hflags |= MIPS_HFLAG_COP1X;
68 }
69 } else if (env->insn_flags & ISA_MIPS32) {
70 if (env->hflags & MIPS_HFLAG_64) {
71 env->hflags |= MIPS_HFLAG_COP1X;
72 }
73 } else if (env->insn_flags & ISA_MIPS4) {
74
75
76
77
78 if (env->CP0_Status & (1 << CP0St_CU3)) {
79 env->hflags |= MIPS_HFLAG_COP1X;
80 }
81 }
82}
83
84
85
86
87void helper_raise_exception_err (uint32_t exception, int error_code)
88{
89#if 1
90 if (exception < 0x100)
91 qemu_log("%s: %d %d\n", __func__, exception, error_code);
92#endif
93 env->exception_index = exception;
94 env->error_code = error_code;
95 cpu_loop_exit(env);
96}
97
98void helper_raise_exception (uint32_t exception)
99{
100 helper_raise_exception_err(exception, 0);
101}
102
103#if !defined(CONFIG_USER_ONLY)
104static void do_restore_state (void *pc_ptr)
105{
106 TranslationBlock *tb;
107 unsigned long pc = (unsigned long) pc_ptr;
108
109 tb = tb_find_pc (pc);
110 if (tb) {
111 cpu_restore_state(tb, env, pc);
112 }
113}
114#endif
115
116#if defined(CONFIG_USER_ONLY)
117#define HELPER_LD(name, insn, type) \
118static inline type do_##name(target_ulong addr, int mem_idx) \
119{ \
120 return (type) insn##_raw(addr); \
121}
122#else
123#define HELPER_LD(name, insn, type) \
124static inline type do_##name(target_ulong addr, int mem_idx) \
125{ \
126 switch (mem_idx) \
127 { \
128 case 0: return (type) insn##_kernel(addr); break; \
129 case 1: return (type) insn##_super(addr); break; \
130 default: \
131 case 2: return (type) insn##_user(addr); break; \
132 } \
133}
134#endif
135HELPER_LD(lbu, ldub, uint8_t)
136HELPER_LD(lw, ldl, int32_t)
137#ifdef TARGET_MIPS64
138HELPER_LD(ld, ldq, int64_t)
139#endif
140#undef HELPER_LD
141
142#if defined(CONFIG_USER_ONLY)
143#define HELPER_ST(name, insn, type) \
144static inline void do_##name(target_ulong addr, type val, int mem_idx) \
145{ \
146 insn##_raw(addr, val); \
147}
148#else
149#define HELPER_ST(name, insn, type) \
150static inline void do_##name(target_ulong addr, type val, int mem_idx) \
151{ \
152 switch (mem_idx) \
153 { \
154 case 0: insn##_kernel(addr, val); break; \
155 case 1: insn##_super(addr, val); break; \
156 default: \
157 case 2: insn##_user(addr, val); break; \
158 } \
159}
160#endif
161HELPER_ST(sb, stb, uint8_t)
162HELPER_ST(sw, stl, uint32_t)
163#ifdef TARGET_MIPS64
164HELPER_ST(sd, stq, uint64_t)
165#endif
166#undef HELPER_ST
167
168target_ulong helper_clo (target_ulong arg1)
169{
170 return clo32(arg1);
171}
172
173target_ulong helper_clz (target_ulong arg1)
174{
175 return clz32(arg1);
176}
177
178#if defined(TARGET_MIPS64)
179target_ulong helper_dclo (target_ulong arg1)
180{
181 return clo64(arg1);
182}
183
184target_ulong helper_dclz (target_ulong arg1)
185{
186 return clz64(arg1);
187}
188#endif
189
190
191static inline uint64_t get_HILO (void)
192{
193 return ((uint64_t)(env->active_tc.HI[0]) << 32) | (uint32_t)env->active_tc.LO[0];
194}
195
196static inline void set_HILO (uint64_t HILO)
197{
198 env->active_tc.LO[0] = (int32_t)HILO;
199 env->active_tc.HI[0] = (int32_t)(HILO >> 32);
200}
201
202static inline void set_HIT0_LO (target_ulong arg1, uint64_t HILO)
203{
204 env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF);
205 arg1 = env->active_tc.HI[0] = (int32_t)(HILO >> 32);
206}
207
208static inline void set_HI_LOT0 (target_ulong arg1, uint64_t HILO)
209{
210 arg1 = env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF);
211 env->active_tc.HI[0] = (int32_t)(HILO >> 32);
212}
213
214
215target_ulong helper_muls (target_ulong arg1, target_ulong arg2)
216{
217 set_HI_LOT0(arg1, 0 - ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2));
218
219 return arg1;
220}
221
222target_ulong helper_mulsu (target_ulong arg1, target_ulong arg2)
223{
224 set_HI_LOT0(arg1, 0 - ((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2));
225
226 return arg1;
227}
228
229target_ulong helper_macc (target_ulong arg1, target_ulong arg2)
230{
231 set_HI_LOT0(arg1, ((int64_t)get_HILO()) + ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2));
232
233 return arg1;
234}
235
236target_ulong helper_macchi (target_ulong arg1, target_ulong arg2)
237{
238 set_HIT0_LO(arg1, ((int64_t)get_HILO()) + ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2));
239
240 return arg1;
241}
242
243target_ulong helper_maccu (target_ulong arg1, target_ulong arg2)
244{
245 set_HI_LOT0(arg1, ((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2));
246
247 return arg1;
248}
249
250target_ulong helper_macchiu (target_ulong arg1, target_ulong arg2)
251{
252 set_HIT0_LO(arg1, ((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2));
253
254 return arg1;
255}
256
257target_ulong helper_msac (target_ulong arg1, target_ulong arg2)
258{
259 set_HI_LOT0(arg1, ((int64_t)get_HILO()) - ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2));
260
261 return arg1;
262}
263
264target_ulong helper_msachi (target_ulong arg1, target_ulong arg2)
265{
266 set_HIT0_LO(arg1, ((int64_t)get_HILO()) - ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2));
267
268 return arg1;
269}
270
271target_ulong helper_msacu (target_ulong arg1, target_ulong arg2)
272{
273 set_HI_LOT0(arg1, ((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2));
274
275 return arg1;
276}
277
278target_ulong helper_msachiu (target_ulong arg1, target_ulong arg2)
279{
280 set_HIT0_LO(arg1, ((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2));
281
282 return arg1;
283}
284
285target_ulong helper_mulhi (target_ulong arg1, target_ulong arg2)
286{
287 set_HIT0_LO(arg1, (int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2);
288
289 return arg1;
290}
291
292target_ulong helper_mulhiu (target_ulong arg1, target_ulong arg2)
293{
294 set_HIT0_LO(arg1, (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2);
295
296 return arg1;
297}
298
299target_ulong helper_mulshi (target_ulong arg1, target_ulong arg2)
300{
301 set_HIT0_LO(arg1, 0 - ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2));
302
303 return arg1;
304}
305
306target_ulong helper_mulshiu (target_ulong arg1, target_ulong arg2)
307{
308 set_HIT0_LO(arg1, 0 - ((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2));
309
310 return arg1;
311}
312
313#ifdef TARGET_MIPS64
314void helper_dmult (target_ulong arg1, target_ulong arg2)
315{
316 muls64(&(env->active_tc.LO[0]), &(env->active_tc.HI[0]), arg1, arg2);
317}
318
319void helper_dmultu (target_ulong arg1, target_ulong arg2)
320{
321 mulu64(&(env->active_tc.LO[0]), &(env->active_tc.HI[0]), arg1, arg2);
322}
323#endif
324
325#ifndef CONFIG_USER_ONLY
326
327static inline target_phys_addr_t do_translate_address(target_ulong address, int rw)
328{
329 target_phys_addr_t lladdr;
330
331 lladdr = cpu_mips_translate_address(env, address, rw);
332
333 if (lladdr == -1LL) {
334 cpu_loop_exit(env);
335 } else {
336 return lladdr;
337 }
338}
339
340#define HELPER_LD_ATOMIC(name, insn) \
341target_ulong helper_##name(target_ulong arg, int mem_idx) \
342{ \
343 env->lladdr = do_translate_address(arg, 0); \
344 env->llval = do_##insn(arg, mem_idx); \
345 return env->llval; \
346}
347HELPER_LD_ATOMIC(ll, lw)
348#ifdef TARGET_MIPS64
349HELPER_LD_ATOMIC(lld, ld)
350#endif
351#undef HELPER_LD_ATOMIC
352
353#define HELPER_ST_ATOMIC(name, ld_insn, st_insn, almask) \
354target_ulong helper_##name(target_ulong arg1, target_ulong arg2, int mem_idx) \
355{ \
356 target_long tmp; \
357 \
358 if (arg2 & almask) { \
359 env->CP0_BadVAddr = arg2; \
360 helper_raise_exception(EXCP_AdES); \
361 } \
362 if (do_translate_address(arg2, 1) == env->lladdr) { \
363 tmp = do_##ld_insn(arg2, mem_idx); \
364 if (tmp == env->llval) { \
365 do_##st_insn(arg2, arg1, mem_idx); \
366 return 1; \
367 } \
368 } \
369 return 0; \
370}
371HELPER_ST_ATOMIC(sc, lw, sw, 0x3)
372#ifdef TARGET_MIPS64
373HELPER_ST_ATOMIC(scd, ld, sd, 0x7)
374#endif
375#undef HELPER_ST_ATOMIC
376#endif
377
378#ifdef TARGET_WORDS_BIGENDIAN
379#define GET_LMASK(v) ((v) & 3)
380#define GET_OFFSET(addr, offset) (addr + (offset))
381#else
382#define GET_LMASK(v) (((v) & 3) ^ 3)
383#define GET_OFFSET(addr, offset) (addr - (offset))
384#endif
385
386target_ulong helper_lwl(target_ulong arg1, target_ulong arg2, int mem_idx)
387{
388 target_ulong tmp;
389
390 tmp = do_lbu(arg2, mem_idx);
391 arg1 = (arg1 & 0x00FFFFFF) | (tmp << 24);
392
393 if (GET_LMASK(arg2) <= 2) {
394 tmp = do_lbu(GET_OFFSET(arg2, 1), mem_idx);
395 arg1 = (arg1 & 0xFF00FFFF) | (tmp << 16);
396 }
397
398 if (GET_LMASK(arg2) <= 1) {
399 tmp = do_lbu(GET_OFFSET(arg2, 2), mem_idx);
400 arg1 = (arg1 & 0xFFFF00FF) | (tmp << 8);
401 }
402
403 if (GET_LMASK(arg2) == 0) {
404 tmp = do_lbu(GET_OFFSET(arg2, 3), mem_idx);
405 arg1 = (arg1 & 0xFFFFFF00) | tmp;
406 }
407 return (int32_t)arg1;
408}
409
410target_ulong helper_lwr(target_ulong arg1, target_ulong arg2, int mem_idx)
411{
412 target_ulong tmp;
413
414 tmp = do_lbu(arg2, mem_idx);
415 arg1 = (arg1 & 0xFFFFFF00) | tmp;
416
417 if (GET_LMASK(arg2) >= 1) {
418 tmp = do_lbu(GET_OFFSET(arg2, -1), mem_idx);
419 arg1 = (arg1 & 0xFFFF00FF) | (tmp << 8);
420 }
421
422 if (GET_LMASK(arg2) >= 2) {
423 tmp = do_lbu(GET_OFFSET(arg2, -2), mem_idx);
424 arg1 = (arg1 & 0xFF00FFFF) | (tmp << 16);
425 }
426
427 if (GET_LMASK(arg2) == 3) {
428 tmp = do_lbu(GET_OFFSET(arg2, -3), mem_idx);
429 arg1 = (arg1 & 0x00FFFFFF) | (tmp << 24);
430 }
431 return (int32_t)arg1;
432}
433
434void helper_swl(target_ulong arg1, target_ulong arg2, int mem_idx)
435{
436 do_sb(arg2, (uint8_t)(arg1 >> 24), mem_idx);
437
438 if (GET_LMASK(arg2) <= 2)
439 do_sb(GET_OFFSET(arg2, 1), (uint8_t)(arg1 >> 16), mem_idx);
440
441 if (GET_LMASK(arg2) <= 1)
442 do_sb(GET_OFFSET(arg2, 2), (uint8_t)(arg1 >> 8), mem_idx);
443
444 if (GET_LMASK(arg2) == 0)
445 do_sb(GET_OFFSET(arg2, 3), (uint8_t)arg1, mem_idx);
446}
447
448void helper_swr(target_ulong arg1, target_ulong arg2, int mem_idx)
449{
450 do_sb(arg2, (uint8_t)arg1, mem_idx);
451
452 if (GET_LMASK(arg2) >= 1)
453 do_sb(GET_OFFSET(arg2, -1), (uint8_t)(arg1 >> 8), mem_idx);
454
455 if (GET_LMASK(arg2) >= 2)
456 do_sb(GET_OFFSET(arg2, -2), (uint8_t)(arg1 >> 16), mem_idx);
457
458 if (GET_LMASK(arg2) == 3)
459 do_sb(GET_OFFSET(arg2, -3), (uint8_t)(arg1 >> 24), mem_idx);
460}
461
462#if defined(TARGET_MIPS64)
463
464
465
466#ifdef TARGET_WORDS_BIGENDIAN
467#define GET_LMASK64(v) ((v) & 7)
468#else
469#define GET_LMASK64(v) (((v) & 7) ^ 7)
470#endif
471
472target_ulong helper_ldl(target_ulong arg1, target_ulong arg2, int mem_idx)
473{
474 uint64_t tmp;
475
476 tmp = do_lbu(arg2, mem_idx);
477 arg1 = (arg1 & 0x00FFFFFFFFFFFFFFULL) | (tmp << 56);
478
479 if (GET_LMASK64(arg2) <= 6) {
480 tmp = do_lbu(GET_OFFSET(arg2, 1), mem_idx);
481 arg1 = (arg1 & 0xFF00FFFFFFFFFFFFULL) | (tmp << 48);
482 }
483
484 if (GET_LMASK64(arg2) <= 5) {
485 tmp = do_lbu(GET_OFFSET(arg2, 2), mem_idx);
486 arg1 = (arg1 & 0xFFFF00FFFFFFFFFFULL) | (tmp << 40);
487 }
488
489 if (GET_LMASK64(arg2) <= 4) {
490 tmp = do_lbu(GET_OFFSET(arg2, 3), mem_idx);
491 arg1 = (arg1 & 0xFFFFFF00FFFFFFFFULL) | (tmp << 32);
492 }
493
494 if (GET_LMASK64(arg2) <= 3) {
495 tmp = do_lbu(GET_OFFSET(arg2, 4), mem_idx);
496 arg1 = (arg1 & 0xFFFFFFFF00FFFFFFULL) | (tmp << 24);
497 }
498
499 if (GET_LMASK64(arg2) <= 2) {
500 tmp = do_lbu(GET_OFFSET(arg2, 5), mem_idx);
501 arg1 = (arg1 & 0xFFFFFFFFFF00FFFFULL) | (tmp << 16);
502 }
503
504 if (GET_LMASK64(arg2) <= 1) {
505 tmp = do_lbu(GET_OFFSET(arg2, 6), mem_idx);
506 arg1 = (arg1 & 0xFFFFFFFFFFFF00FFULL) | (tmp << 8);
507 }
508
509 if (GET_LMASK64(arg2) == 0) {
510 tmp = do_lbu(GET_OFFSET(arg2, 7), mem_idx);
511 arg1 = (arg1 & 0xFFFFFFFFFFFFFF00ULL) | tmp;
512 }
513
514 return arg1;
515}
516
517target_ulong helper_ldr(target_ulong arg1, target_ulong arg2, int mem_idx)
518{
519 uint64_t tmp;
520
521 tmp = do_lbu(arg2, mem_idx);
522 arg1 = (arg1 & 0xFFFFFFFFFFFFFF00ULL) | tmp;
523
524 if (GET_LMASK64(arg2) >= 1) {
525 tmp = do_lbu(GET_OFFSET(arg2, -1), mem_idx);
526 arg1 = (arg1 & 0xFFFFFFFFFFFF00FFULL) | (tmp << 8);
527 }
528
529 if (GET_LMASK64(arg2) >= 2) {
530 tmp = do_lbu(GET_OFFSET(arg2, -2), mem_idx);
531 arg1 = (arg1 & 0xFFFFFFFFFF00FFFFULL) | (tmp << 16);
532 }
533
534 if (GET_LMASK64(arg2) >= 3) {
535 tmp = do_lbu(GET_OFFSET(arg2, -3), mem_idx);
536 arg1 = (arg1 & 0xFFFFFFFF00FFFFFFULL) | (tmp << 24);
537 }
538
539 if (GET_LMASK64(arg2) >= 4) {
540 tmp = do_lbu(GET_OFFSET(arg2, -4), mem_idx);
541 arg1 = (arg1 & 0xFFFFFF00FFFFFFFFULL) | (tmp << 32);
542 }
543
544 if (GET_LMASK64(arg2) >= 5) {
545 tmp = do_lbu(GET_OFFSET(arg2, -5), mem_idx);
546 arg1 = (arg1 & 0xFFFF00FFFFFFFFFFULL) | (tmp << 40);
547 }
548
549 if (GET_LMASK64(arg2) >= 6) {
550 tmp = do_lbu(GET_OFFSET(arg2, -6), mem_idx);
551 arg1 = (arg1 & 0xFF00FFFFFFFFFFFFULL) | (tmp << 48);
552 }
553
554 if (GET_LMASK64(arg2) == 7) {
555 tmp = do_lbu(GET_OFFSET(arg2, -7), mem_idx);
556 arg1 = (arg1 & 0x00FFFFFFFFFFFFFFULL) | (tmp << 56);
557 }
558
559 return arg1;
560}
561
562void helper_sdl(target_ulong arg1, target_ulong arg2, int mem_idx)
563{
564 do_sb(arg2, (uint8_t)(arg1 >> 56), mem_idx);
565
566 if (GET_LMASK64(arg2) <= 6)
567 do_sb(GET_OFFSET(arg2, 1), (uint8_t)(arg1 >> 48), mem_idx);
568
569 if (GET_LMASK64(arg2) <= 5)
570 do_sb(GET_OFFSET(arg2, 2), (uint8_t)(arg1 >> 40), mem_idx);
571
572 if (GET_LMASK64(arg2) <= 4)
573 do_sb(GET_OFFSET(arg2, 3), (uint8_t)(arg1 >> 32), mem_idx);
574
575 if (GET_LMASK64(arg2) <= 3)
576 do_sb(GET_OFFSET(arg2, 4), (uint8_t)(arg1 >> 24), mem_idx);
577
578 if (GET_LMASK64(arg2) <= 2)
579 do_sb(GET_OFFSET(arg2, 5), (uint8_t)(arg1 >> 16), mem_idx);
580
581 if (GET_LMASK64(arg2) <= 1)
582 do_sb(GET_OFFSET(arg2, 6), (uint8_t)(arg1 >> 8), mem_idx);
583
584 if (GET_LMASK64(arg2) <= 0)
585 do_sb(GET_OFFSET(arg2, 7), (uint8_t)arg1, mem_idx);
586}
587
588void helper_sdr(target_ulong arg1, target_ulong arg2, int mem_idx)
589{
590 do_sb(arg2, (uint8_t)arg1, mem_idx);
591
592 if (GET_LMASK64(arg2) >= 1)
593 do_sb(GET_OFFSET(arg2, -1), (uint8_t)(arg1 >> 8), mem_idx);
594
595 if (GET_LMASK64(arg2) >= 2)
596 do_sb(GET_OFFSET(arg2, -2), (uint8_t)(arg1 >> 16), mem_idx);
597
598 if (GET_LMASK64(arg2) >= 3)
599 do_sb(GET_OFFSET(arg2, -3), (uint8_t)(arg1 >> 24), mem_idx);
600
601 if (GET_LMASK64(arg2) >= 4)
602 do_sb(GET_OFFSET(arg2, -4), (uint8_t)(arg1 >> 32), mem_idx);
603
604 if (GET_LMASK64(arg2) >= 5)
605 do_sb(GET_OFFSET(arg2, -5), (uint8_t)(arg1 >> 40), mem_idx);
606
607 if (GET_LMASK64(arg2) >= 6)
608 do_sb(GET_OFFSET(arg2, -6), (uint8_t)(arg1 >> 48), mem_idx);
609
610 if (GET_LMASK64(arg2) == 7)
611 do_sb(GET_OFFSET(arg2, -7), (uint8_t)(arg1 >> 56), mem_idx);
612}
613#endif
614
615static const int multiple_regs[] = { 16, 17, 18, 19, 20, 21, 22, 23, 30 };
616
617void helper_lwm (target_ulong addr, target_ulong reglist, uint32_t mem_idx)
618{
619 target_ulong base_reglist = reglist & 0xf;
620 target_ulong do_r31 = reglist & 0x10;
621#ifdef CONFIG_USER_ONLY
622#undef ldfun
623#define ldfun ldl_raw
624#else
625 uint32_t (*ldfun)(target_ulong);
626
627 switch (mem_idx)
628 {
629 case 0: ldfun = ldl_kernel; break;
630 case 1: ldfun = ldl_super; break;
631 default:
632 case 2: ldfun = ldl_user; break;
633 }
634#endif
635
636 if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) {
637 target_ulong i;
638
639 for (i = 0; i < base_reglist; i++) {
640 env->active_tc.gpr[multiple_regs[i]] = (target_long) ldfun(addr);
641 addr += 4;
642 }
643 }
644
645 if (do_r31) {
646 env->active_tc.gpr[31] = (target_long) ldfun(addr);
647 }
648}
649
650void helper_swm (target_ulong addr, target_ulong reglist, uint32_t mem_idx)
651{
652 target_ulong base_reglist = reglist & 0xf;
653 target_ulong do_r31 = reglist & 0x10;
654#ifdef CONFIG_USER_ONLY
655#undef stfun
656#define stfun stl_raw
657#else
658 void (*stfun)(target_ulong, uint32_t);
659
660 switch (mem_idx)
661 {
662 case 0: stfun = stl_kernel; break;
663 case 1: stfun = stl_super; break;
664 default:
665 case 2: stfun = stl_user; break;
666 }
667#endif
668
669 if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) {
670 target_ulong i;
671
672 for (i = 0; i < base_reglist; i++) {
673 stfun(addr, env->active_tc.gpr[multiple_regs[i]]);
674 addr += 4;
675 }
676 }
677
678 if (do_r31) {
679 stfun(addr, env->active_tc.gpr[31]);
680 }
681}
682
683#if defined(TARGET_MIPS64)
684void helper_ldm (target_ulong addr, target_ulong reglist, uint32_t mem_idx)
685{
686 target_ulong base_reglist = reglist & 0xf;
687 target_ulong do_r31 = reglist & 0x10;
688#ifdef CONFIG_USER_ONLY
689#undef ldfun
690#define ldfun ldq_raw
691#else
692 uint64_t (*ldfun)(target_ulong);
693
694 switch (mem_idx)
695 {
696 case 0: ldfun = ldq_kernel; break;
697 case 1: ldfun = ldq_super; break;
698 default:
699 case 2: ldfun = ldq_user; break;
700 }
701#endif
702
703 if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) {
704 target_ulong i;
705
706 for (i = 0; i < base_reglist; i++) {
707 env->active_tc.gpr[multiple_regs[i]] = ldfun(addr);
708 addr += 8;
709 }
710 }
711
712 if (do_r31) {
713 env->active_tc.gpr[31] = ldfun(addr);
714 }
715}
716
717void helper_sdm (target_ulong addr, target_ulong reglist, uint32_t mem_idx)
718{
719 target_ulong base_reglist = reglist & 0xf;
720 target_ulong do_r31 = reglist & 0x10;
721#ifdef CONFIG_USER_ONLY
722#undef stfun
723#define stfun stq_raw
724#else
725 void (*stfun)(target_ulong, uint64_t);
726
727 switch (mem_idx)
728 {
729 case 0: stfun = stq_kernel; break;
730 case 1: stfun = stq_super; break;
731 default:
732 case 2: stfun = stq_user; break;
733 }
734#endif
735
736 if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) {
737 target_ulong i;
738
739 for (i = 0; i < base_reglist; i++) {
740 stfun(addr, env->active_tc.gpr[multiple_regs[i]]);
741 addr += 8;
742 }
743 }
744
745 if (do_r31) {
746 stfun(addr, env->active_tc.gpr[31]);
747 }
748}
749#endif
750
751#ifndef CONFIG_USER_ONLY
752
753static int mips_vpe_is_wfi(CPUState *c)
754{
755
756
757 return c->halted && mips_vpe_active(c);
758}
759
760static inline void mips_vpe_wake(CPUState *c)
761{
762
763
764
765 cpu_interrupt(c, CPU_INTERRUPT_WAKE);
766}
767
768static inline void mips_vpe_sleep(CPUState *c)
769{
770
771
772 c->halted = 1;
773 cpu_reset_interrupt(c, CPU_INTERRUPT_WAKE);
774}
775
776static inline void mips_tc_wake(CPUState *c, int tc)
777{
778
779 if (mips_vpe_active(c) && !mips_vpe_is_wfi(c)) {
780 mips_vpe_wake(c);
781 }
782}
783
784static inline void mips_tc_sleep(CPUState *c, int tc)
785{
786
787 if (!mips_vpe_active(c)) {
788 mips_vpe_sleep(c);
789 }
790}
791
792
793
794
795
796
797
798
799static CPUState *mips_cpu_map_tc(int *tc)
800{
801 CPUState *other;
802 int vpe_idx, nr_threads = env->nr_threads;
803 int tc_idx = *tc;
804
805 if (!(env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP))) {
806
807 *tc = env->current_tc;
808 return env;
809 }
810
811 vpe_idx = tc_idx / nr_threads;
812 *tc = tc_idx % nr_threads;
813 other = qemu_get_cpu(vpe_idx);
814 return other ? other : env;
815}
816
817
818
819
820
821
822
823
824
825
826static void sync_c0_status(CPUState *cpu, int tc)
827{
828 int32_t tcstatus, *tcst;
829 uint32_t v = cpu->CP0_Status;
830 uint32_t cu, mx, asid, ksu;
831 uint32_t mask = ((1 << CP0TCSt_TCU3)
832 | (1 << CP0TCSt_TCU2)
833 | (1 << CP0TCSt_TCU1)
834 | (1 << CP0TCSt_TCU0)
835 | (1 << CP0TCSt_TMX)
836 | (3 << CP0TCSt_TKSU)
837 | (0xff << CP0TCSt_TASID));
838
839 cu = (v >> CP0St_CU0) & 0xf;
840 mx = (v >> CP0St_MX) & 0x1;
841 ksu = (v >> CP0St_KSU) & 0x3;
842 asid = env->CP0_EntryHi & 0xff;
843
844 tcstatus = cu << CP0TCSt_TCU0;
845 tcstatus |= mx << CP0TCSt_TMX;
846 tcstatus |= ksu << CP0TCSt_TKSU;
847 tcstatus |= asid;
848
849 if (tc == cpu->current_tc) {
850 tcst = &cpu->active_tc.CP0_TCStatus;
851 } else {
852 tcst = &cpu->tcs[tc].CP0_TCStatus;
853 }
854
855 *tcst &= ~mask;
856 *tcst |= tcstatus;
857 compute_hflags(cpu);
858}
859
860
861static void sync_c0_tcstatus(CPUState *cpu, int tc, target_ulong v)
862{
863 uint32_t status;
864 uint32_t tcu, tmx, tasid, tksu;
865 uint32_t mask = ((1 << CP0St_CU3)
866 | (1 << CP0St_CU2)
867 | (1 << CP0St_CU1)
868 | (1 << CP0St_CU0)
869 | (1 << CP0St_MX)
870 | (3 << CP0St_KSU));
871
872 tcu = (v >> CP0TCSt_TCU0) & 0xf;
873 tmx = (v >> CP0TCSt_TMX) & 0x1;
874 tasid = v & 0xff;
875 tksu = (v >> CP0TCSt_TKSU) & 0x3;
876
877 status = tcu << CP0St_CU0;
878 status |= tmx << CP0St_MX;
879 status |= tksu << CP0St_KSU;
880
881 cpu->CP0_Status &= ~mask;
882 cpu->CP0_Status |= status;
883
884
885 cpu->CP0_EntryHi &= ~0xff;
886 cpu->CP0_EntryHi = tasid;
887
888 compute_hflags(cpu);
889}
890
891
892static void sync_c0_entryhi(CPUState *cpu, int tc)
893{
894 int32_t *tcst;
895 uint32_t asid, v = cpu->CP0_EntryHi;
896
897 asid = v & 0xff;
898
899 if (tc == cpu->current_tc) {
900 tcst = &cpu->active_tc.CP0_TCStatus;
901 } else {
902 tcst = &cpu->tcs[tc].CP0_TCStatus;
903 }
904
905 *tcst &= ~0xff;
906 *tcst |= asid;
907}
908
909
910target_ulong helper_mfc0_mvpcontrol (void)
911{
912 return env->mvp->CP0_MVPControl;
913}
914
915target_ulong helper_mfc0_mvpconf0 (void)
916{
917 return env->mvp->CP0_MVPConf0;
918}
919
920target_ulong helper_mfc0_mvpconf1 (void)
921{
922 return env->mvp->CP0_MVPConf1;
923}
924
925target_ulong helper_mfc0_random (void)
926{
927 return (int32_t)cpu_mips_get_random(env);
928}
929
930target_ulong helper_mfc0_tcstatus (void)
931{
932 return env->active_tc.CP0_TCStatus;
933}
934
935target_ulong helper_mftc0_tcstatus(void)
936{
937 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
938 CPUState *other = mips_cpu_map_tc(&other_tc);
939
940 if (other_tc == other->current_tc)
941 return other->active_tc.CP0_TCStatus;
942 else
943 return other->tcs[other_tc].CP0_TCStatus;
944}
945
946target_ulong helper_mfc0_tcbind (void)
947{
948 return env->active_tc.CP0_TCBind;
949}
950
951target_ulong helper_mftc0_tcbind(void)
952{
953 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
954 CPUState *other = mips_cpu_map_tc(&other_tc);
955
956 if (other_tc == other->current_tc)
957 return other->active_tc.CP0_TCBind;
958 else
959 return other->tcs[other_tc].CP0_TCBind;
960}
961
962target_ulong helper_mfc0_tcrestart (void)
963{
964 return env->active_tc.PC;
965}
966
967target_ulong helper_mftc0_tcrestart(void)
968{
969 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
970 CPUState *other = mips_cpu_map_tc(&other_tc);
971
972 if (other_tc == other->current_tc)
973 return other->active_tc.PC;
974 else
975 return other->tcs[other_tc].PC;
976}
977
978target_ulong helper_mfc0_tchalt (void)
979{
980 return env->active_tc.CP0_TCHalt;
981}
982
983target_ulong helper_mftc0_tchalt(void)
984{
985 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
986 CPUState *other = mips_cpu_map_tc(&other_tc);
987
988 if (other_tc == other->current_tc)
989 return other->active_tc.CP0_TCHalt;
990 else
991 return other->tcs[other_tc].CP0_TCHalt;
992}
993
994target_ulong helper_mfc0_tccontext (void)
995{
996 return env->active_tc.CP0_TCContext;
997}
998
999target_ulong helper_mftc0_tccontext(void)
1000{
1001 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1002 CPUState *other = mips_cpu_map_tc(&other_tc);
1003
1004 if (other_tc == other->current_tc)
1005 return other->active_tc.CP0_TCContext;
1006 else
1007 return other->tcs[other_tc].CP0_TCContext;
1008}
1009
1010target_ulong helper_mfc0_tcschedule (void)
1011{
1012 return env->active_tc.CP0_TCSchedule;
1013}
1014
1015target_ulong helper_mftc0_tcschedule(void)
1016{
1017 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1018 CPUState *other = mips_cpu_map_tc(&other_tc);
1019
1020 if (other_tc == other->current_tc)
1021 return other->active_tc.CP0_TCSchedule;
1022 else
1023 return other->tcs[other_tc].CP0_TCSchedule;
1024}
1025
1026target_ulong helper_mfc0_tcschefback (void)
1027{
1028 return env->active_tc.CP0_TCScheFBack;
1029}
1030
1031target_ulong helper_mftc0_tcschefback(void)
1032{
1033 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1034 CPUState *other = mips_cpu_map_tc(&other_tc);
1035
1036 if (other_tc == other->current_tc)
1037 return other->active_tc.CP0_TCScheFBack;
1038 else
1039 return other->tcs[other_tc].CP0_TCScheFBack;
1040}
1041
1042target_ulong helper_mfc0_count (void)
1043{
1044 return (int32_t)cpu_mips_get_count(env);
1045}
1046
1047target_ulong helper_mftc0_entryhi(void)
1048{
1049 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1050 CPUState *other = mips_cpu_map_tc(&other_tc);
1051
1052 return other->CP0_EntryHi;
1053}
1054
1055target_ulong helper_mftc0_cause(void)
1056{
1057 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1058 int32_t tccause;
1059 CPUState *other = mips_cpu_map_tc(&other_tc);
1060
1061 if (other_tc == other->current_tc) {
1062 tccause = other->CP0_Cause;
1063 } else {
1064 tccause = other->CP0_Cause;
1065 }
1066
1067 return tccause;
1068}
1069
1070target_ulong helper_mftc0_status(void)
1071{
1072 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1073 CPUState *other = mips_cpu_map_tc(&other_tc);
1074
1075 return other->CP0_Status;
1076}
1077
1078target_ulong helper_mfc0_lladdr (void)
1079{
1080 return (int32_t)(env->lladdr >> env->CP0_LLAddr_shift);
1081}
1082
1083target_ulong helper_mfc0_watchlo (uint32_t sel)
1084{
1085 return (int32_t)env->CP0_WatchLo[sel];
1086}
1087
1088target_ulong helper_mfc0_watchhi (uint32_t sel)
1089{
1090 return env->CP0_WatchHi[sel];
1091}
1092
1093target_ulong helper_mfc0_debug (void)
1094{
1095 target_ulong t0 = env->CP0_Debug;
1096 if (env->hflags & MIPS_HFLAG_DM)
1097 t0 |= 1 << CP0DB_DM;
1098
1099 return t0;
1100}
1101
1102target_ulong helper_mftc0_debug(void)
1103{
1104 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1105 int32_t tcstatus;
1106 CPUState *other = mips_cpu_map_tc(&other_tc);
1107
1108 if (other_tc == other->current_tc)
1109 tcstatus = other->active_tc.CP0_Debug_tcstatus;
1110 else
1111 tcstatus = other->tcs[other_tc].CP0_Debug_tcstatus;
1112
1113
1114 return (other->CP0_Debug & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
1115 (tcstatus & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
1116}
1117
1118#if defined(TARGET_MIPS64)
1119target_ulong helper_dmfc0_tcrestart (void)
1120{
1121 return env->active_tc.PC;
1122}
1123
1124target_ulong helper_dmfc0_tchalt (void)
1125{
1126 return env->active_tc.CP0_TCHalt;
1127}
1128
1129target_ulong helper_dmfc0_tccontext (void)
1130{
1131 return env->active_tc.CP0_TCContext;
1132}
1133
1134target_ulong helper_dmfc0_tcschedule (void)
1135{
1136 return env->active_tc.CP0_TCSchedule;
1137}
1138
1139target_ulong helper_dmfc0_tcschefback (void)
1140{
1141 return env->active_tc.CP0_TCScheFBack;
1142}
1143
1144target_ulong helper_dmfc0_lladdr (void)
1145{
1146 return env->lladdr >> env->CP0_LLAddr_shift;
1147}
1148
1149target_ulong helper_dmfc0_watchlo (uint32_t sel)
1150{
1151 return env->CP0_WatchLo[sel];
1152}
1153#endif
1154
1155void helper_mtc0_index (target_ulong arg1)
1156{
1157 int num = 1;
1158 unsigned int tmp = env->tlb->nb_tlb;
1159
1160 do {
1161 tmp >>= 1;
1162 num <<= 1;
1163 } while (tmp);
1164 env->CP0_Index = (env->CP0_Index & 0x80000000) | (arg1 & (num - 1));
1165}
1166
1167void helper_mtc0_mvpcontrol (target_ulong arg1)
1168{
1169 uint32_t mask = 0;
1170 uint32_t newval;
1171
1172 if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP))
1173 mask |= (1 << CP0MVPCo_CPA) | (1 << CP0MVPCo_VPC) |
1174 (1 << CP0MVPCo_EVP);
1175 if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1176 mask |= (1 << CP0MVPCo_STLB);
1177 newval = (env->mvp->CP0_MVPControl & ~mask) | (arg1 & mask);
1178
1179
1180
1181 env->mvp->CP0_MVPControl = newval;
1182}
1183
1184void helper_mtc0_vpecontrol (target_ulong arg1)
1185{
1186 uint32_t mask;
1187 uint32_t newval;
1188
1189 mask = (1 << CP0VPECo_YSI) | (1 << CP0VPECo_GSI) |
1190 (1 << CP0VPECo_TE) | (0xff << CP0VPECo_TargTC);
1191 newval = (env->CP0_VPEControl & ~mask) | (arg1 & mask);
1192
1193
1194
1195
1196
1197
1198 env->CP0_VPEControl = newval;
1199}
1200
1201void helper_mttc0_vpecontrol(target_ulong arg1)
1202{
1203 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1204 CPUState *other = mips_cpu_map_tc(&other_tc);
1205 uint32_t mask;
1206 uint32_t newval;
1207
1208 mask = (1 << CP0VPECo_YSI) | (1 << CP0VPECo_GSI) |
1209 (1 << CP0VPECo_TE) | (0xff << CP0VPECo_TargTC);
1210 newval = (other->CP0_VPEControl & ~mask) | (arg1 & mask);
1211
1212
1213
1214 other->CP0_VPEControl = newval;
1215}
1216
1217target_ulong helper_mftc0_vpecontrol(void)
1218{
1219 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1220 CPUState *other = mips_cpu_map_tc(&other_tc);
1221
1222 return other->CP0_VPEControl;
1223}
1224
1225target_ulong helper_mftc0_vpeconf0(void)
1226{
1227 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1228 CPUState *other = mips_cpu_map_tc(&other_tc);
1229
1230 return other->CP0_VPEConf0;
1231}
1232
1233void helper_mtc0_vpeconf0 (target_ulong arg1)
1234{
1235 uint32_t mask = 0;
1236 uint32_t newval;
1237
1238 if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) {
1239 if (env->CP0_VPEConf0 & (1 << CP0VPEC0_VPA))
1240 mask |= (0xff << CP0VPEC0_XTC);
1241 mask |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
1242 }
1243 newval = (env->CP0_VPEConf0 & ~mask) | (arg1 & mask);
1244
1245
1246
1247 env->CP0_VPEConf0 = newval;
1248}
1249
1250void helper_mttc0_vpeconf0(target_ulong arg1)
1251{
1252 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1253 CPUState *other = mips_cpu_map_tc(&other_tc);
1254 uint32_t mask = 0;
1255 uint32_t newval;
1256
1257 mask |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
1258 newval = (other->CP0_VPEConf0 & ~mask) | (arg1 & mask);
1259
1260
1261 other->CP0_VPEConf0 = newval;
1262}
1263
1264void helper_mtc0_vpeconf1 (target_ulong arg1)
1265{
1266 uint32_t mask = 0;
1267 uint32_t newval;
1268
1269 if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1270 mask |= (0xff << CP0VPEC1_NCX) | (0xff << CP0VPEC1_NCP2) |
1271 (0xff << CP0VPEC1_NCP1);
1272 newval = (env->CP0_VPEConf1 & ~mask) | (arg1 & mask);
1273
1274
1275
1276
1277
1278
1279 env->CP0_VPEConf1 = newval;
1280}
1281
1282void helper_mtc0_yqmask (target_ulong arg1)
1283{
1284
1285 env->CP0_YQMask = 0x00000000;
1286}
1287
1288void helper_mtc0_vpeopt (target_ulong arg1)
1289{
1290 env->CP0_VPEOpt = arg1 & 0x0000ffff;
1291}
1292
1293void helper_mtc0_entrylo0 (target_ulong arg1)
1294{
1295
1296
1297 env->CP0_EntryLo0 = arg1 & 0x3FFFFFFF;
1298}
1299
1300void helper_mtc0_tcstatus (target_ulong arg1)
1301{
1302 uint32_t mask = env->CP0_TCStatus_rw_bitmask;
1303 uint32_t newval;
1304
1305 newval = (env->active_tc.CP0_TCStatus & ~mask) | (arg1 & mask);
1306
1307 env->active_tc.CP0_TCStatus = newval;
1308 sync_c0_tcstatus(env, env->current_tc, newval);
1309}
1310
1311void helper_mttc0_tcstatus (target_ulong arg1)
1312{
1313 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1314 CPUState *other = mips_cpu_map_tc(&other_tc);
1315
1316 if (other_tc == other->current_tc)
1317 other->active_tc.CP0_TCStatus = arg1;
1318 else
1319 other->tcs[other_tc].CP0_TCStatus = arg1;
1320 sync_c0_tcstatus(other, other_tc, arg1);
1321}
1322
1323void helper_mtc0_tcbind (target_ulong arg1)
1324{
1325 uint32_t mask = (1 << CP0TCBd_TBE);
1326 uint32_t newval;
1327
1328 if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1329 mask |= (1 << CP0TCBd_CurVPE);
1330 newval = (env->active_tc.CP0_TCBind & ~mask) | (arg1 & mask);
1331 env->active_tc.CP0_TCBind = newval;
1332}
1333
1334void helper_mttc0_tcbind (target_ulong arg1)
1335{
1336 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1337 uint32_t mask = (1 << CP0TCBd_TBE);
1338 uint32_t newval;
1339 CPUState *other = mips_cpu_map_tc(&other_tc);
1340
1341 if (other->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1342 mask |= (1 << CP0TCBd_CurVPE);
1343 if (other_tc == other->current_tc) {
1344 newval = (other->active_tc.CP0_TCBind & ~mask) | (arg1 & mask);
1345 other->active_tc.CP0_TCBind = newval;
1346 } else {
1347 newval = (other->tcs[other_tc].CP0_TCBind & ~mask) | (arg1 & mask);
1348 other->tcs[other_tc].CP0_TCBind = newval;
1349 }
1350}
1351
1352void helper_mtc0_tcrestart (target_ulong arg1)
1353{
1354 env->active_tc.PC = arg1;
1355 env->active_tc.CP0_TCStatus &= ~(1 << CP0TCSt_TDS);
1356 env->lladdr = 0ULL;
1357
1358}
1359
1360void helper_mttc0_tcrestart (target_ulong arg1)
1361{
1362 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1363 CPUState *other = mips_cpu_map_tc(&other_tc);
1364
1365 if (other_tc == other->current_tc) {
1366 other->active_tc.PC = arg1;
1367 other->active_tc.CP0_TCStatus &= ~(1 << CP0TCSt_TDS);
1368 other->lladdr = 0ULL;
1369
1370 } else {
1371 other->tcs[other_tc].PC = arg1;
1372 other->tcs[other_tc].CP0_TCStatus &= ~(1 << CP0TCSt_TDS);
1373 other->lladdr = 0ULL;
1374
1375 }
1376}
1377
1378void helper_mtc0_tchalt (target_ulong arg1)
1379{
1380 env->active_tc.CP0_TCHalt = arg1 & 0x1;
1381
1382
1383 if (env->active_tc.CP0_TCHalt & 1) {
1384 mips_tc_sleep(env, env->current_tc);
1385 } else {
1386 mips_tc_wake(env, env->current_tc);
1387 }
1388}
1389
1390void helper_mttc0_tchalt (target_ulong arg1)
1391{
1392 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1393 CPUState *other = mips_cpu_map_tc(&other_tc);
1394
1395
1396
1397 if (other_tc == other->current_tc)
1398 other->active_tc.CP0_TCHalt = arg1;
1399 else
1400 other->tcs[other_tc].CP0_TCHalt = arg1;
1401
1402 if (arg1 & 1) {
1403 mips_tc_sleep(other, other_tc);
1404 } else {
1405 mips_tc_wake(other, other_tc);
1406 }
1407}
1408
1409void helper_mtc0_tccontext (target_ulong arg1)
1410{
1411 env->active_tc.CP0_TCContext = arg1;
1412}
1413
1414void helper_mttc0_tccontext (target_ulong arg1)
1415{
1416 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1417 CPUState *other = mips_cpu_map_tc(&other_tc);
1418
1419 if (other_tc == other->current_tc)
1420 other->active_tc.CP0_TCContext = arg1;
1421 else
1422 other->tcs[other_tc].CP0_TCContext = arg1;
1423}
1424
1425void helper_mtc0_tcschedule (target_ulong arg1)
1426{
1427 env->active_tc.CP0_TCSchedule = arg1;
1428}
1429
1430void helper_mttc0_tcschedule (target_ulong arg1)
1431{
1432 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1433 CPUState *other = mips_cpu_map_tc(&other_tc);
1434
1435 if (other_tc == other->current_tc)
1436 other->active_tc.CP0_TCSchedule = arg1;
1437 else
1438 other->tcs[other_tc].CP0_TCSchedule = arg1;
1439}
1440
1441void helper_mtc0_tcschefback (target_ulong arg1)
1442{
1443 env->active_tc.CP0_TCScheFBack = arg1;
1444}
1445
1446void helper_mttc0_tcschefback (target_ulong arg1)
1447{
1448 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1449 CPUState *other = mips_cpu_map_tc(&other_tc);
1450
1451 if (other_tc == other->current_tc)
1452 other->active_tc.CP0_TCScheFBack = arg1;
1453 else
1454 other->tcs[other_tc].CP0_TCScheFBack = arg1;
1455}
1456
1457void helper_mtc0_entrylo1 (target_ulong arg1)
1458{
1459
1460
1461 env->CP0_EntryLo1 = arg1 & 0x3FFFFFFF;
1462}
1463
1464void helper_mtc0_context (target_ulong arg1)
1465{
1466 env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (arg1 & ~0x007FFFFF);
1467}
1468
1469void helper_mtc0_pagemask (target_ulong arg1)
1470{
1471
1472 env->CP0_PageMask = arg1 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
1473}
1474
1475void helper_mtc0_pagegrain (target_ulong arg1)
1476{
1477
1478
1479
1480 env->CP0_PageGrain = 0;
1481}
1482
1483void helper_mtc0_wired (target_ulong arg1)
1484{
1485 env->CP0_Wired = arg1 % env->tlb->nb_tlb;
1486}
1487
1488void helper_mtc0_srsconf0 (target_ulong arg1)
1489{
1490 env->CP0_SRSConf0 |= arg1 & env->CP0_SRSConf0_rw_bitmask;
1491}
1492
1493void helper_mtc0_srsconf1 (target_ulong arg1)
1494{
1495 env->CP0_SRSConf1 |= arg1 & env->CP0_SRSConf1_rw_bitmask;
1496}
1497
1498void helper_mtc0_srsconf2 (target_ulong arg1)
1499{
1500 env->CP0_SRSConf2 |= arg1 & env->CP0_SRSConf2_rw_bitmask;
1501}
1502
1503void helper_mtc0_srsconf3 (target_ulong arg1)
1504{
1505 env->CP0_SRSConf3 |= arg1 & env->CP0_SRSConf3_rw_bitmask;
1506}
1507
1508void helper_mtc0_srsconf4 (target_ulong arg1)
1509{
1510 env->CP0_SRSConf4 |= arg1 & env->CP0_SRSConf4_rw_bitmask;
1511}
1512
1513void helper_mtc0_hwrena (target_ulong arg1)
1514{
1515 env->CP0_HWREna = arg1 & 0x0000000F;
1516}
1517
1518void helper_mtc0_count (target_ulong arg1)
1519{
1520 cpu_mips_store_count(env, arg1);
1521}
1522
1523void helper_mtc0_entryhi (target_ulong arg1)
1524{
1525 target_ulong old, val;
1526
1527
1528 val = arg1 & ((TARGET_PAGE_MASK << 1) | 0xFF);
1529#if defined(TARGET_MIPS64)
1530 val &= env->SEGMask;
1531#endif
1532 old = env->CP0_EntryHi;
1533 env->CP0_EntryHi = val;
1534 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
1535 sync_c0_entryhi(env, env->current_tc);
1536 }
1537
1538 if ((old & 0xFF) != (val & 0xFF))
1539 cpu_mips_tlb_flush(env, 1);
1540}
1541
1542void helper_mttc0_entryhi(target_ulong arg1)
1543{
1544 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1545 CPUState *other = mips_cpu_map_tc(&other_tc);
1546
1547 other->CP0_EntryHi = arg1;
1548 sync_c0_entryhi(other, other_tc);
1549}
1550
1551void helper_mtc0_compare (target_ulong arg1)
1552{
1553 cpu_mips_store_compare(env, arg1);
1554}
1555
1556void helper_mtc0_status (target_ulong arg1)
1557{
1558 uint32_t val, old;
1559 uint32_t mask = env->CP0_Status_rw_bitmask;
1560
1561 val = arg1 & mask;
1562 old = env->CP0_Status;
1563 env->CP0_Status = (env->CP0_Status & ~mask) | val;
1564 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
1565 sync_c0_status(env, env->current_tc);
1566 } else {
1567 compute_hflags(env);
1568 }
1569
1570 if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
1571 qemu_log("Status %08x (%08x) => %08x (%08x) Cause %08x",
1572 old, old & env->CP0_Cause & CP0Ca_IP_mask,
1573 val, val & env->CP0_Cause & CP0Ca_IP_mask,
1574 env->CP0_Cause);
1575 switch (env->hflags & MIPS_HFLAG_KSU) {
1576 case MIPS_HFLAG_UM: qemu_log(", UM\n"); break;
1577 case MIPS_HFLAG_SM: qemu_log(", SM\n"); break;
1578 case MIPS_HFLAG_KM: qemu_log("\n"); break;
1579 default: cpu_abort(env, "Invalid MMU mode!\n"); break;
1580 }
1581 }
1582}
1583
1584void helper_mttc0_status(target_ulong arg1)
1585{
1586 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1587 CPUState *other = mips_cpu_map_tc(&other_tc);
1588
1589 other->CP0_Status = arg1 & ~0xf1000018;
1590 sync_c0_status(other, other_tc);
1591}
1592
1593void helper_mtc0_intctl (target_ulong arg1)
1594{
1595
1596 env->CP0_IntCtl = (env->CP0_IntCtl & ~0x000003e0) | (arg1 & 0x000003e0);
1597}
1598
1599void helper_mtc0_srsctl (target_ulong arg1)
1600{
1601 uint32_t mask = (0xf << CP0SRSCtl_ESS) | (0xf << CP0SRSCtl_PSS);
1602 env->CP0_SRSCtl = (env->CP0_SRSCtl & ~mask) | (arg1 & mask);
1603}
1604
1605static void mtc0_cause(CPUState *cpu, target_ulong arg1)
1606{
1607 uint32_t mask = 0x00C00300;
1608 uint32_t old = cpu->CP0_Cause;
1609 int i;
1610
1611 if (cpu->insn_flags & ISA_MIPS32R2) {
1612 mask |= 1 << CP0Ca_DC;
1613 }
1614
1615 cpu->CP0_Cause = (cpu->CP0_Cause & ~mask) | (arg1 & mask);
1616
1617 if ((old ^ cpu->CP0_Cause) & (1 << CP0Ca_DC)) {
1618 if (cpu->CP0_Cause & (1 << CP0Ca_DC)) {
1619 cpu_mips_stop_count(cpu);
1620 } else {
1621 cpu_mips_start_count(cpu);
1622 }
1623 }
1624
1625
1626 for (i = 0 ; i < 2 ; i++) {
1627 if ((old ^ cpu->CP0_Cause) & (1 << (CP0Ca_IP + i))) {
1628 cpu_mips_soft_irq(cpu, i, cpu->CP0_Cause & (1 << (CP0Ca_IP + i)));
1629 }
1630 }
1631}
1632
1633void helper_mtc0_cause(target_ulong arg1)
1634{
1635 mtc0_cause(env, arg1);
1636}
1637
1638void helper_mttc0_cause(target_ulong arg1)
1639{
1640 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1641 CPUState *other = mips_cpu_map_tc(&other_tc);
1642
1643 mtc0_cause(other, arg1);
1644}
1645
1646target_ulong helper_mftc0_epc(void)
1647{
1648 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1649 CPUState *other = mips_cpu_map_tc(&other_tc);
1650
1651 return other->CP0_EPC;
1652}
1653
1654target_ulong helper_mftc0_ebase(void)
1655{
1656 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1657 CPUState *other = mips_cpu_map_tc(&other_tc);
1658
1659 return other->CP0_EBase;
1660}
1661
1662void helper_mtc0_ebase (target_ulong arg1)
1663{
1664
1665 env->CP0_EBase = (env->CP0_EBase & ~0x3FFFF000) | (arg1 & 0x3FFFF000);
1666}
1667
1668void helper_mttc0_ebase(target_ulong arg1)
1669{
1670 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1671 CPUState *other = mips_cpu_map_tc(&other_tc);
1672 other->CP0_EBase = (other->CP0_EBase & ~0x3FFFF000) | (arg1 & 0x3FFFF000);
1673}
1674
1675target_ulong helper_mftc0_configx(target_ulong idx)
1676{
1677 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1678 CPUState *other = mips_cpu_map_tc(&other_tc);
1679
1680 switch (idx) {
1681 case 0: return other->CP0_Config0;
1682 case 1: return other->CP0_Config1;
1683 case 2: return other->CP0_Config2;
1684 case 3: return other->CP0_Config3;
1685
1686 case 6: return other->CP0_Config6;
1687 case 7: return other->CP0_Config7;
1688 default:
1689 break;
1690 }
1691 return 0;
1692}
1693
1694void helper_mtc0_config0 (target_ulong arg1)
1695{
1696 env->CP0_Config0 = (env->CP0_Config0 & 0x81FFFFF8) | (arg1 & 0x00000007);
1697}
1698
1699void helper_mtc0_config2 (target_ulong arg1)
1700{
1701
1702 env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF);
1703}
1704
1705void helper_mtc0_lladdr (target_ulong arg1)
1706{
1707 target_long mask = env->CP0_LLAddr_rw_bitmask;
1708 arg1 = arg1 << env->CP0_LLAddr_shift;
1709 env->lladdr = (env->lladdr & ~mask) | (arg1 & mask);
1710}
1711
1712void helper_mtc0_watchlo (target_ulong arg1, uint32_t sel)
1713{
1714
1715
1716 env->CP0_WatchLo[sel] = (arg1 & ~0x7);
1717}
1718
1719void helper_mtc0_watchhi (target_ulong arg1, uint32_t sel)
1720{
1721 env->CP0_WatchHi[sel] = (arg1 & 0x40FF0FF8);
1722 env->CP0_WatchHi[sel] &= ~(env->CP0_WatchHi[sel] & arg1 & 0x7);
1723}
1724
1725void helper_mtc0_xcontext (target_ulong arg1)
1726{
1727 target_ulong mask = (1ULL << (env->SEGBITS - 7)) - 1;
1728 env->CP0_XContext = (env->CP0_XContext & mask) | (arg1 & ~mask);
1729}
1730
1731void helper_mtc0_framemask (target_ulong arg1)
1732{
1733 env->CP0_Framemask = arg1;
1734}
1735
1736void helper_mtc0_debug (target_ulong arg1)
1737{
1738 env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (arg1 & 0x13300120);
1739 if (arg1 & (1 << CP0DB_DM))
1740 env->hflags |= MIPS_HFLAG_DM;
1741 else
1742 env->hflags &= ~MIPS_HFLAG_DM;
1743}
1744
1745void helper_mttc0_debug(target_ulong arg1)
1746{
1747 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1748 uint32_t val = arg1 & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt));
1749 CPUState *other = mips_cpu_map_tc(&other_tc);
1750
1751
1752 if (other_tc == other->current_tc)
1753 other->active_tc.CP0_Debug_tcstatus = val;
1754 else
1755 other->tcs[other_tc].CP0_Debug_tcstatus = val;
1756 other->CP0_Debug = (other->CP0_Debug &
1757 ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
1758 (arg1 & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
1759}
1760
1761void helper_mtc0_performance0 (target_ulong arg1)
1762{
1763 env->CP0_Performance0 = arg1 & 0x000007ff;
1764}
1765
1766void helper_mtc0_taglo (target_ulong arg1)
1767{
1768 env->CP0_TagLo = arg1 & 0xFFFFFCF6;
1769}
1770
1771void helper_mtc0_datalo (target_ulong arg1)
1772{
1773 env->CP0_DataLo = arg1;
1774}
1775
1776void helper_mtc0_taghi (target_ulong arg1)
1777{
1778 env->CP0_TagHi = arg1;
1779}
1780
1781void helper_mtc0_datahi (target_ulong arg1)
1782{
1783 env->CP0_DataHi = arg1;
1784}
1785
1786
1787target_ulong helper_mftgpr(uint32_t sel)
1788{
1789 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1790 CPUState *other = mips_cpu_map_tc(&other_tc);
1791
1792 if (other_tc == other->current_tc)
1793 return other->active_tc.gpr[sel];
1794 else
1795 return other->tcs[other_tc].gpr[sel];
1796}
1797
1798target_ulong helper_mftlo(uint32_t sel)
1799{
1800 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1801 CPUState *other = mips_cpu_map_tc(&other_tc);
1802
1803 if (other_tc == other->current_tc)
1804 return other->active_tc.LO[sel];
1805 else
1806 return other->tcs[other_tc].LO[sel];
1807}
1808
1809target_ulong helper_mfthi(uint32_t sel)
1810{
1811 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1812 CPUState *other = mips_cpu_map_tc(&other_tc);
1813
1814 if (other_tc == other->current_tc)
1815 return other->active_tc.HI[sel];
1816 else
1817 return other->tcs[other_tc].HI[sel];
1818}
1819
1820target_ulong helper_mftacx(uint32_t sel)
1821{
1822 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1823 CPUState *other = mips_cpu_map_tc(&other_tc);
1824
1825 if (other_tc == other->current_tc)
1826 return other->active_tc.ACX[sel];
1827 else
1828 return other->tcs[other_tc].ACX[sel];
1829}
1830
1831target_ulong helper_mftdsp(void)
1832{
1833 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1834 CPUState *other = mips_cpu_map_tc(&other_tc);
1835
1836 if (other_tc == other->current_tc)
1837 return other->active_tc.DSPControl;
1838 else
1839 return other->tcs[other_tc].DSPControl;
1840}
1841
1842void helper_mttgpr(target_ulong arg1, uint32_t sel)
1843{
1844 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1845 CPUState *other = mips_cpu_map_tc(&other_tc);
1846
1847 if (other_tc == other->current_tc)
1848 other->active_tc.gpr[sel] = arg1;
1849 else
1850 other->tcs[other_tc].gpr[sel] = arg1;
1851}
1852
1853void helper_mttlo(target_ulong arg1, uint32_t sel)
1854{
1855 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1856 CPUState *other = mips_cpu_map_tc(&other_tc);
1857
1858 if (other_tc == other->current_tc)
1859 other->active_tc.LO[sel] = arg1;
1860 else
1861 other->tcs[other_tc].LO[sel] = arg1;
1862}
1863
1864void helper_mtthi(target_ulong arg1, uint32_t sel)
1865{
1866 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1867 CPUState *other = mips_cpu_map_tc(&other_tc);
1868
1869 if (other_tc == other->current_tc)
1870 other->active_tc.HI[sel] = arg1;
1871 else
1872 other->tcs[other_tc].HI[sel] = arg1;
1873}
1874
1875void helper_mttacx(target_ulong arg1, uint32_t sel)
1876{
1877 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1878 CPUState *other = mips_cpu_map_tc(&other_tc);
1879
1880 if (other_tc == other->current_tc)
1881 other->active_tc.ACX[sel] = arg1;
1882 else
1883 other->tcs[other_tc].ACX[sel] = arg1;
1884}
1885
1886void helper_mttdsp(target_ulong arg1)
1887{
1888 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1889 CPUState *other = mips_cpu_map_tc(&other_tc);
1890
1891 if (other_tc == other->current_tc)
1892 other->active_tc.DSPControl = arg1;
1893 else
1894 other->tcs[other_tc].DSPControl = arg1;
1895}
1896
1897
1898target_ulong helper_dmt(void)
1899{
1900
1901 return 0;
1902}
1903
1904target_ulong helper_emt(void)
1905{
1906
1907 return 0;
1908}
1909
1910target_ulong helper_dvpe(void)
1911{
1912 CPUState *other_cpu = first_cpu;
1913 target_ulong prev = env->mvp->CP0_MVPControl;
1914
1915 do {
1916
1917 if (other_cpu != env) {
1918 other_cpu->mvp->CP0_MVPControl &= ~(1 << CP0MVPCo_EVP);
1919 mips_vpe_sleep(other_cpu);
1920 }
1921 other_cpu = other_cpu->next_cpu;
1922 } while (other_cpu);
1923 return prev;
1924}
1925
1926target_ulong helper_evpe(void)
1927{
1928 CPUState *other_cpu = first_cpu;
1929 target_ulong prev = env->mvp->CP0_MVPControl;
1930
1931 do {
1932 if (other_cpu != env
1933
1934 && !mips_vpe_is_wfi(other_cpu)) {
1935
1936 other_cpu->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
1937 mips_vpe_wake(other_cpu);
1938 }
1939 other_cpu = other_cpu->next_cpu;
1940 } while (other_cpu);
1941 return prev;
1942}
1943#endif
1944
1945void helper_fork(target_ulong arg1, target_ulong arg2)
1946{
1947
1948 arg1 = 0;
1949
1950}
1951
1952target_ulong helper_yield(target_ulong arg)
1953{
1954 target_long arg1 = arg;
1955
1956 if (arg1 < 0) {
1957
1958 if (arg1 != -2) {
1959 if (env->CP0_VPEControl & (1 << CP0VPECo_YSI) &&
1960 env->active_tc.CP0_TCStatus & (1 << CP0TCSt_DT)) {
1961 env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
1962 env->CP0_VPEControl |= 4 << CP0VPECo_EXCPT;
1963 helper_raise_exception(EXCP_THREAD);
1964 }
1965 }
1966 } else if (arg1 == 0) {
1967 if (0 ) {
1968 env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
1969 helper_raise_exception(EXCP_THREAD);
1970 } else {
1971
1972 }
1973 } else if (arg1 > 0) {
1974
1975 env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
1976 env->CP0_VPEControl |= 2 << CP0VPECo_EXCPT;
1977 helper_raise_exception(EXCP_THREAD);
1978 }
1979 return env->CP0_YQMask;
1980}
1981
1982#ifndef CONFIG_USER_ONLY
1983
1984static void cpu_mips_tlb_flush (CPUState *env, int flush_global)
1985{
1986
1987 tlb_flush (env, flush_global);
1988 env->tlb->tlb_in_use = env->tlb->nb_tlb;
1989}
1990
1991static void r4k_mips_tlb_flush_extra (CPUState *env, int first)
1992{
1993
1994 while (env->tlb->tlb_in_use > first) {
1995 r4k_invalidate_tlb(env, --env->tlb->tlb_in_use, 0);
1996 }
1997}
1998
1999static void r4k_fill_tlb (int idx)
2000{
2001 r4k_tlb_t *tlb;
2002
2003
2004 tlb = &env->tlb->mmu.r4k.tlb[idx];
2005 tlb->VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1);
2006#if defined(TARGET_MIPS64)
2007 tlb->VPN &= env->SEGMask;
2008#endif
2009 tlb->ASID = env->CP0_EntryHi & 0xFF;
2010 tlb->PageMask = env->CP0_PageMask;
2011 tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
2012 tlb->V0 = (env->CP0_EntryLo0 & 2) != 0;
2013 tlb->D0 = (env->CP0_EntryLo0 & 4) != 0;
2014 tlb->C0 = (env->CP0_EntryLo0 >> 3) & 0x7;
2015 tlb->PFN[0] = (env->CP0_EntryLo0 >> 6) << 12;
2016 tlb->V1 = (env->CP0_EntryLo1 & 2) != 0;
2017 tlb->D1 = (env->CP0_EntryLo1 & 4) != 0;
2018 tlb->C1 = (env->CP0_EntryLo1 >> 3) & 0x7;
2019 tlb->PFN[1] = (env->CP0_EntryLo1 >> 6) << 12;
2020}
2021
2022void r4k_helper_tlbwi (void)
2023{
2024 int idx;
2025
2026 idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb;
2027
2028
2029
2030
2031 r4k_mips_tlb_flush_extra (env, env->tlb->nb_tlb);
2032
2033 r4k_invalidate_tlb(env, idx, 0);
2034 r4k_fill_tlb(idx);
2035}
2036
2037void r4k_helper_tlbwr (void)
2038{
2039 int r = cpu_mips_get_random(env);
2040
2041 r4k_invalidate_tlb(env, r, 1);
2042 r4k_fill_tlb(r);
2043}
2044
2045void r4k_helper_tlbp (void)
2046{
2047 r4k_tlb_t *tlb;
2048 target_ulong mask;
2049 target_ulong tag;
2050 target_ulong VPN;
2051 uint8_t ASID;
2052 int i;
2053
2054 ASID = env->CP0_EntryHi & 0xFF;
2055 for (i = 0; i < env->tlb->nb_tlb; i++) {
2056 tlb = &env->tlb->mmu.r4k.tlb[i];
2057
2058 mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
2059 tag = env->CP0_EntryHi & ~mask;
2060 VPN = tlb->VPN & ~mask;
2061
2062 if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
2063
2064 env->CP0_Index = i;
2065 break;
2066 }
2067 }
2068 if (i == env->tlb->nb_tlb) {
2069
2070 for (i = env->tlb->nb_tlb; i < env->tlb->tlb_in_use; i++) {
2071 tlb = &env->tlb->mmu.r4k.tlb[i];
2072
2073 mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
2074 tag = env->CP0_EntryHi & ~mask;
2075 VPN = tlb->VPN & ~mask;
2076
2077 if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
2078 r4k_mips_tlb_flush_extra (env, i);
2079 break;
2080 }
2081 }
2082
2083 env->CP0_Index |= 0x80000000;
2084 }
2085}
2086
2087void r4k_helper_tlbr (void)
2088{
2089 r4k_tlb_t *tlb;
2090 uint8_t ASID;
2091 int idx;
2092
2093 ASID = env->CP0_EntryHi & 0xFF;
2094 idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb;
2095 tlb = &env->tlb->mmu.r4k.tlb[idx];
2096
2097
2098 if (ASID != tlb->ASID)
2099 cpu_mips_tlb_flush (env, 1);
2100
2101 r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb);
2102
2103 env->CP0_EntryHi = tlb->VPN | tlb->ASID;
2104 env->CP0_PageMask = tlb->PageMask;
2105 env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) |
2106 (tlb->C0 << 3) | (tlb->PFN[0] >> 6);
2107 env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) |
2108 (tlb->C1 << 3) | (tlb->PFN[1] >> 6);
2109}
2110
2111void helper_tlbwi(void)
2112{
2113 env->tlb->helper_tlbwi();
2114}
2115
2116void helper_tlbwr(void)
2117{
2118 env->tlb->helper_tlbwr();
2119}
2120
2121void helper_tlbp(void)
2122{
2123 env->tlb->helper_tlbp();
2124}
2125
2126void helper_tlbr(void)
2127{
2128 env->tlb->helper_tlbr();
2129}
2130
2131
2132target_ulong helper_di (void)
2133{
2134 target_ulong t0 = env->CP0_Status;
2135
2136 env->CP0_Status = t0 & ~(1 << CP0St_IE);
2137 return t0;
2138}
2139
2140target_ulong helper_ei (void)
2141{
2142 target_ulong t0 = env->CP0_Status;
2143
2144 env->CP0_Status = t0 | (1 << CP0St_IE);
2145 return t0;
2146}
2147
2148static void debug_pre_eret (void)
2149{
2150 if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
2151 qemu_log("ERET: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
2152 env->active_tc.PC, env->CP0_EPC);
2153 if (env->CP0_Status & (1 << CP0St_ERL))
2154 qemu_log(" ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
2155 if (env->hflags & MIPS_HFLAG_DM)
2156 qemu_log(" DEPC " TARGET_FMT_lx, env->CP0_DEPC);
2157 qemu_log("\n");
2158 }
2159}
2160
2161static void debug_post_eret (void)
2162{
2163 if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
2164 qemu_log(" => PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
2165 env->active_tc.PC, env->CP0_EPC);
2166 if (env->CP0_Status & (1 << CP0St_ERL))
2167 qemu_log(" ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
2168 if (env->hflags & MIPS_HFLAG_DM)
2169 qemu_log(" DEPC " TARGET_FMT_lx, env->CP0_DEPC);
2170 switch (env->hflags & MIPS_HFLAG_KSU) {
2171 case MIPS_HFLAG_UM: qemu_log(", UM\n"); break;
2172 case MIPS_HFLAG_SM: qemu_log(", SM\n"); break;
2173 case MIPS_HFLAG_KM: qemu_log("\n"); break;
2174 default: cpu_abort(env, "Invalid MMU mode!\n"); break;
2175 }
2176 }
2177}
2178
2179static void set_pc (target_ulong error_pc)
2180{
2181 env->active_tc.PC = error_pc & ~(target_ulong)1;
2182 if (error_pc & 1) {
2183 env->hflags |= MIPS_HFLAG_M16;
2184 } else {
2185 env->hflags &= ~(MIPS_HFLAG_M16);
2186 }
2187}
2188
2189void helper_eret (void)
2190{
2191 debug_pre_eret();
2192 if (env->CP0_Status & (1 << CP0St_ERL)) {
2193 set_pc(env->CP0_ErrorEPC);
2194 env->CP0_Status &= ~(1 << CP0St_ERL);
2195 } else {
2196 set_pc(env->CP0_EPC);
2197 env->CP0_Status &= ~(1 << CP0St_EXL);
2198 }
2199 compute_hflags(env);
2200 debug_post_eret();
2201 env->lladdr = 1;
2202}
2203
2204void helper_deret (void)
2205{
2206 debug_pre_eret();
2207 set_pc(env->CP0_DEPC);
2208
2209 env->hflags &= MIPS_HFLAG_DM;
2210 compute_hflags(env);
2211 debug_post_eret();
2212 env->lladdr = 1;
2213}
2214#endif
2215
2216target_ulong helper_rdhwr_cpunum(void)
2217{
2218 if ((env->hflags & MIPS_HFLAG_CP0) ||
2219 (env->CP0_HWREna & (1 << 0)))
2220 return env->CP0_EBase & 0x3ff;
2221 else
2222 helper_raise_exception(EXCP_RI);
2223
2224 return 0;
2225}
2226
2227target_ulong helper_rdhwr_synci_step(void)
2228{
2229 if ((env->hflags & MIPS_HFLAG_CP0) ||
2230 (env->CP0_HWREna & (1 << 1)))
2231 return env->SYNCI_Step;
2232 else
2233 helper_raise_exception(EXCP_RI);
2234
2235 return 0;
2236}
2237
2238target_ulong helper_rdhwr_cc(void)
2239{
2240 if ((env->hflags & MIPS_HFLAG_CP0) ||
2241 (env->CP0_HWREna & (1 << 2)))
2242 return env->CP0_Count;
2243 else
2244 helper_raise_exception(EXCP_RI);
2245
2246 return 0;
2247}
2248
2249target_ulong helper_rdhwr_ccres(void)
2250{
2251 if ((env->hflags & MIPS_HFLAG_CP0) ||
2252 (env->CP0_HWREna & (1 << 3)))
2253 return env->CCRes;
2254 else
2255 helper_raise_exception(EXCP_RI);
2256
2257 return 0;
2258}
2259
2260void helper_pmon (int function)
2261{
2262 function /= 2;
2263 switch (function) {
2264 case 2:
2265 if (env->active_tc.gpr[4] == 0)
2266 env->active_tc.gpr[2] = -1;
2267
2268 case 11:
2269 env->active_tc.gpr[2] = -1;
2270 break;
2271 case 3:
2272 case 12:
2273 printf("%c", (char)(env->active_tc.gpr[4] & 0xFF));
2274 break;
2275 case 17:
2276 break;
2277 case 158:
2278 {
2279 unsigned char *fmt = (void *)(unsigned long)env->active_tc.gpr[4];
2280 printf("%s", fmt);
2281 }
2282 break;
2283 }
2284}
2285
2286void helper_wait (void)
2287{
2288 env->halted = 1;
2289 cpu_reset_interrupt(env, CPU_INTERRUPT_WAKE);
2290 helper_raise_exception(EXCP_HLT);
2291}
2292
2293#if !defined(CONFIG_USER_ONLY)
2294
2295static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr);
2296
2297#define MMUSUFFIX _mmu
2298#define ALIGNED_ONLY
2299
2300#define SHIFT 0
2301#include "softmmu_template.h"
2302
2303#define SHIFT 1
2304#include "softmmu_template.h"
2305
2306#define SHIFT 2
2307#include "softmmu_template.h"
2308
2309#define SHIFT 3
2310#include "softmmu_template.h"
2311
2312static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr)
2313{
2314 env->CP0_BadVAddr = addr;
2315 do_restore_state (retaddr);
2316 helper_raise_exception ((is_write == 1) ? EXCP_AdES : EXCP_AdEL);
2317}
2318
2319void tlb_fill(CPUState *env1, target_ulong addr, int is_write, int mmu_idx,
2320 void *retaddr)
2321{
2322 TranslationBlock *tb;
2323 CPUState *saved_env;
2324 unsigned long pc;
2325 int ret;
2326
2327 saved_env = env;
2328 env = env1;
2329 ret = cpu_mips_handle_mmu_fault(env, addr, is_write, mmu_idx);
2330 if (ret) {
2331 if (retaddr) {
2332
2333 pc = (unsigned long)retaddr;
2334 tb = tb_find_pc(pc);
2335 if (tb) {
2336
2337
2338 cpu_restore_state(tb, env, pc);
2339 }
2340 }
2341 helper_raise_exception_err(env->exception_index, env->error_code);
2342 }
2343 env = saved_env;
2344}
2345
2346void cpu_unassigned_access(CPUState *env1, target_phys_addr_t addr,
2347 int is_write, int is_exec, int unused, int size)
2348{
2349 env = env1;
2350
2351 if (is_exec)
2352 helper_raise_exception(EXCP_IBE);
2353 else
2354 helper_raise_exception(EXCP_DBE);
2355}
2356#endif
2357
2358
2359
2360#define FLOAT_ONE32 make_float32(0x3f8 << 20)
2361#define FLOAT_ONE64 make_float64(0x3ffULL << 52)
2362#define FLOAT_TWO32 make_float32(1 << 30)
2363#define FLOAT_TWO64 make_float64(1ULL << 62)
2364#define FLOAT_QNAN32 0x7fbfffff
2365#define FLOAT_QNAN64 0x7ff7ffffffffffffULL
2366#define FLOAT_SNAN32 0x7fffffff
2367#define FLOAT_SNAN64 0x7fffffffffffffffULL
2368
2369
2370static unsigned int ieee_rm[] = {
2371 float_round_nearest_even,
2372 float_round_to_zero,
2373 float_round_up,
2374 float_round_down
2375};
2376
2377#define RESTORE_ROUNDING_MODE \
2378 set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3], &env->active_fpu.fp_status)
2379
2380#define RESTORE_FLUSH_MODE \
2381 set_flush_to_zero((env->active_fpu.fcr31 & (1 << 24)) != 0, &env->active_fpu.fp_status);
2382
2383target_ulong helper_cfc1 (uint32_t reg)
2384{
2385 target_ulong arg1;
2386
2387 switch (reg) {
2388 case 0:
2389 arg1 = (int32_t)env->active_fpu.fcr0;
2390 break;
2391 case 25:
2392 arg1 = ((env->active_fpu.fcr31 >> 24) & 0xfe) | ((env->active_fpu.fcr31 >> 23) & 0x1);
2393 break;
2394 case 26:
2395 arg1 = env->active_fpu.fcr31 & 0x0003f07c;
2396 break;
2397 case 28:
2398 arg1 = (env->active_fpu.fcr31 & 0x00000f83) | ((env->active_fpu.fcr31 >> 22) & 0x4);
2399 break;
2400 default:
2401 arg1 = (int32_t)env->active_fpu.fcr31;
2402 break;
2403 }
2404
2405 return arg1;
2406}
2407
2408void helper_ctc1 (target_ulong arg1, uint32_t reg)
2409{
2410 switch(reg) {
2411 case 25:
2412 if (arg1 & 0xffffff00)
2413 return;
2414 env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0x017fffff) | ((arg1 & 0xfe) << 24) |
2415 ((arg1 & 0x1) << 23);
2416 break;
2417 case 26:
2418 if (arg1 & 0x007c0000)
2419 return;
2420 env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0xfffc0f83) | (arg1 & 0x0003f07c);
2421 break;
2422 case 28:
2423 if (arg1 & 0x007c0000)
2424 return;
2425 env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0xfefff07c) | (arg1 & 0x00000f83) |
2426 ((arg1 & 0x4) << 22);
2427 break;
2428 case 31:
2429 if (arg1 & 0x007c0000)
2430 return;
2431 env->active_fpu.fcr31 = arg1;
2432 break;
2433 default:
2434 return;
2435 }
2436
2437 RESTORE_ROUNDING_MODE;
2438
2439 RESTORE_FLUSH_MODE;
2440 set_float_exception_flags(0, &env->active_fpu.fp_status);
2441 if ((GET_FP_ENABLE(env->active_fpu.fcr31) | 0x20) & GET_FP_CAUSE(env->active_fpu.fcr31))
2442 helper_raise_exception(EXCP_FPE);
2443}
2444
2445static inline int ieee_ex_to_mips(int xcpt)
2446{
2447 int ret = 0;
2448 if (xcpt) {
2449 if (xcpt & float_flag_invalid) {
2450 ret |= FP_INVALID;
2451 }
2452 if (xcpt & float_flag_overflow) {
2453 ret |= FP_OVERFLOW;
2454 }
2455 if (xcpt & float_flag_underflow) {
2456 ret |= FP_UNDERFLOW;
2457 }
2458 if (xcpt & float_flag_divbyzero) {
2459 ret |= FP_DIV0;
2460 }
2461 if (xcpt & float_flag_inexact) {
2462 ret |= FP_INEXACT;
2463 }
2464 }
2465 return ret;
2466}
2467
2468static inline void update_fcr31(void)
2469{
2470 int tmp = ieee_ex_to_mips(get_float_exception_flags(&env->active_fpu.fp_status));
2471
2472 SET_FP_CAUSE(env->active_fpu.fcr31, tmp);
2473 if (GET_FP_ENABLE(env->active_fpu.fcr31) & tmp)
2474 helper_raise_exception(EXCP_FPE);
2475 else
2476 UPDATE_FP_FLAGS(env->active_fpu.fcr31, tmp);
2477}
2478
2479
2480
2481
2482
2483
2484
2485uint64_t helper_float_sqrt_d(uint64_t fdt0)
2486{
2487 return float64_sqrt(fdt0, &env->active_fpu.fp_status);
2488}
2489
2490uint32_t helper_float_sqrt_s(uint32_t fst0)
2491{
2492 return float32_sqrt(fst0, &env->active_fpu.fp_status);
2493}
2494
2495uint64_t helper_float_cvtd_s(uint32_t fst0)
2496{
2497 uint64_t fdt2;
2498
2499 set_float_exception_flags(0, &env->active_fpu.fp_status);
2500 fdt2 = float32_to_float64(fst0, &env->active_fpu.fp_status);
2501 update_fcr31();
2502 return fdt2;
2503}
2504
2505uint64_t helper_float_cvtd_w(uint32_t wt0)
2506{
2507 uint64_t fdt2;
2508
2509 set_float_exception_flags(0, &env->active_fpu.fp_status);
2510 fdt2 = int32_to_float64(wt0, &env->active_fpu.fp_status);
2511 update_fcr31();
2512 return fdt2;
2513}
2514
2515uint64_t helper_float_cvtd_l(uint64_t dt0)
2516{
2517 uint64_t fdt2;
2518
2519 set_float_exception_flags(0, &env->active_fpu.fp_status);
2520 fdt2 = int64_to_float64(dt0, &env->active_fpu.fp_status);
2521 update_fcr31();
2522 return fdt2;
2523}
2524
2525uint64_t helper_float_cvtl_d(uint64_t fdt0)
2526{
2527 uint64_t dt2;
2528
2529 set_float_exception_flags(0, &env->active_fpu.fp_status);
2530 dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
2531 update_fcr31();
2532 if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2533 dt2 = FLOAT_SNAN64;
2534 return dt2;
2535}
2536
2537uint64_t helper_float_cvtl_s(uint32_t fst0)
2538{
2539 uint64_t dt2;
2540
2541 set_float_exception_flags(0, &env->active_fpu.fp_status);
2542 dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
2543 update_fcr31();
2544 if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2545 dt2 = FLOAT_SNAN64;
2546 return dt2;
2547}
2548
2549uint64_t helper_float_cvtps_pw(uint64_t dt0)
2550{
2551 uint32_t fst2;
2552 uint32_t fsth2;
2553
2554 set_float_exception_flags(0, &env->active_fpu.fp_status);
2555 fst2 = int32_to_float32(dt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
2556 fsth2 = int32_to_float32(dt0 >> 32, &env->active_fpu.fp_status);
2557 update_fcr31();
2558 return ((uint64_t)fsth2 << 32) | fst2;
2559}
2560
2561uint64_t helper_float_cvtpw_ps(uint64_t fdt0)
2562{
2563 uint32_t wt2;
2564 uint32_t wth2;
2565
2566 set_float_exception_flags(0, &env->active_fpu.fp_status);
2567 wt2 = float32_to_int32(fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
2568 wth2 = float32_to_int32(fdt0 >> 32, &env->active_fpu.fp_status);
2569 update_fcr31();
2570 if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) {
2571 wt2 = FLOAT_SNAN32;
2572 wth2 = FLOAT_SNAN32;
2573 }
2574 return ((uint64_t)wth2 << 32) | wt2;
2575}
2576
2577uint32_t helper_float_cvts_d(uint64_t fdt0)
2578{
2579 uint32_t fst2;
2580
2581 set_float_exception_flags(0, &env->active_fpu.fp_status);
2582 fst2 = float64_to_float32(fdt0, &env->active_fpu.fp_status);
2583 update_fcr31();
2584 return fst2;
2585}
2586
2587uint32_t helper_float_cvts_w(uint32_t wt0)
2588{
2589 uint32_t fst2;
2590
2591 set_float_exception_flags(0, &env->active_fpu.fp_status);
2592 fst2 = int32_to_float32(wt0, &env->active_fpu.fp_status);
2593 update_fcr31();
2594 return fst2;
2595}
2596
2597uint32_t helper_float_cvts_l(uint64_t dt0)
2598{
2599 uint32_t fst2;
2600
2601 set_float_exception_flags(0, &env->active_fpu.fp_status);
2602 fst2 = int64_to_float32(dt0, &env->active_fpu.fp_status);
2603 update_fcr31();
2604 return fst2;
2605}
2606
2607uint32_t helper_float_cvts_pl(uint32_t wt0)
2608{
2609 uint32_t wt2;
2610
2611 set_float_exception_flags(0, &env->active_fpu.fp_status);
2612 wt2 = wt0;
2613 update_fcr31();
2614 return wt2;
2615}
2616
2617uint32_t helper_float_cvts_pu(uint32_t wth0)
2618{
2619 uint32_t wt2;
2620
2621 set_float_exception_flags(0, &env->active_fpu.fp_status);
2622 wt2 = wth0;
2623 update_fcr31();
2624 return wt2;
2625}
2626
2627uint32_t helper_float_cvtw_s(uint32_t fst0)
2628{
2629 uint32_t wt2;
2630
2631 set_float_exception_flags(0, &env->active_fpu.fp_status);
2632 wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
2633 update_fcr31();
2634 if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2635 wt2 = FLOAT_SNAN32;
2636 return wt2;
2637}
2638
2639uint32_t helper_float_cvtw_d(uint64_t fdt0)
2640{
2641 uint32_t wt2;
2642
2643 set_float_exception_flags(0, &env->active_fpu.fp_status);
2644 wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
2645 update_fcr31();
2646 if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2647 wt2 = FLOAT_SNAN32;
2648 return wt2;
2649}
2650
2651uint64_t helper_float_roundl_d(uint64_t fdt0)
2652{
2653 uint64_t dt2;
2654
2655 set_float_exception_flags(0, &env->active_fpu.fp_status);
2656 set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
2657 dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
2658 RESTORE_ROUNDING_MODE;
2659 update_fcr31();
2660 if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2661 dt2 = FLOAT_SNAN64;
2662 return dt2;
2663}
2664
2665uint64_t helper_float_roundl_s(uint32_t fst0)
2666{
2667 uint64_t dt2;
2668
2669 set_float_exception_flags(0, &env->active_fpu.fp_status);
2670 set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
2671 dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
2672 RESTORE_ROUNDING_MODE;
2673 update_fcr31();
2674 if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2675 dt2 = FLOAT_SNAN64;
2676 return dt2;
2677}
2678
2679uint32_t helper_float_roundw_d(uint64_t fdt0)
2680{
2681 uint32_t wt2;
2682
2683 set_float_exception_flags(0, &env->active_fpu.fp_status);
2684 set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
2685 wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
2686 RESTORE_ROUNDING_MODE;
2687 update_fcr31();
2688 if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2689 wt2 = FLOAT_SNAN32;
2690 return wt2;
2691}
2692
2693uint32_t helper_float_roundw_s(uint32_t fst0)
2694{
2695 uint32_t wt2;
2696
2697 set_float_exception_flags(0, &env->active_fpu.fp_status);
2698 set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
2699 wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
2700 RESTORE_ROUNDING_MODE;
2701 update_fcr31();
2702 if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2703 wt2 = FLOAT_SNAN32;
2704 return wt2;
2705}
2706
2707uint64_t helper_float_truncl_d(uint64_t fdt0)
2708{
2709 uint64_t dt2;
2710
2711 set_float_exception_flags(0, &env->active_fpu.fp_status);
2712 dt2 = float64_to_int64_round_to_zero(fdt0, &env->active_fpu.fp_status);
2713 update_fcr31();
2714 if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2715 dt2 = FLOAT_SNAN64;
2716 return dt2;
2717}
2718
2719uint64_t helper_float_truncl_s(uint32_t fst0)
2720{
2721 uint64_t dt2;
2722
2723 set_float_exception_flags(0, &env->active_fpu.fp_status);
2724 dt2 = float32_to_int64_round_to_zero(fst0, &env->active_fpu.fp_status);
2725 update_fcr31();
2726 if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2727 dt2 = FLOAT_SNAN64;
2728 return dt2;
2729}
2730
2731uint32_t helper_float_truncw_d(uint64_t fdt0)
2732{
2733 uint32_t wt2;
2734
2735 set_float_exception_flags(0, &env->active_fpu.fp_status);
2736 wt2 = float64_to_int32_round_to_zero(fdt0, &env->active_fpu.fp_status);
2737 update_fcr31();
2738 if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2739 wt2 = FLOAT_SNAN32;
2740 return wt2;
2741}
2742
2743uint32_t helper_float_truncw_s(uint32_t fst0)
2744{
2745 uint32_t wt2;
2746
2747 set_float_exception_flags(0, &env->active_fpu.fp_status);
2748 wt2 = float32_to_int32_round_to_zero(fst0, &env->active_fpu.fp_status);
2749 update_fcr31();
2750 if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2751 wt2 = FLOAT_SNAN32;
2752 return wt2;
2753}
2754
2755uint64_t helper_float_ceill_d(uint64_t fdt0)
2756{
2757 uint64_t dt2;
2758
2759 set_float_exception_flags(0, &env->active_fpu.fp_status);
2760 set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
2761 dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
2762 RESTORE_ROUNDING_MODE;
2763 update_fcr31();
2764 if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2765 dt2 = FLOAT_SNAN64;
2766 return dt2;
2767}
2768
2769uint64_t helper_float_ceill_s(uint32_t fst0)
2770{
2771 uint64_t dt2;
2772
2773 set_float_exception_flags(0, &env->active_fpu.fp_status);
2774 set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
2775 dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
2776 RESTORE_ROUNDING_MODE;
2777 update_fcr31();
2778 if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2779 dt2 = FLOAT_SNAN64;
2780 return dt2;
2781}
2782
2783uint32_t helper_float_ceilw_d(uint64_t fdt0)
2784{
2785 uint32_t wt2;
2786
2787 set_float_exception_flags(0, &env->active_fpu.fp_status);
2788 set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
2789 wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
2790 RESTORE_ROUNDING_MODE;
2791 update_fcr31();
2792 if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2793 wt2 = FLOAT_SNAN32;
2794 return wt2;
2795}
2796
2797uint32_t helper_float_ceilw_s(uint32_t fst0)
2798{
2799 uint32_t wt2;
2800
2801 set_float_exception_flags(0, &env->active_fpu.fp_status);
2802 set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
2803 wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
2804 RESTORE_ROUNDING_MODE;
2805 update_fcr31();
2806 if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2807 wt2 = FLOAT_SNAN32;
2808 return wt2;
2809}
2810
2811uint64_t helper_float_floorl_d(uint64_t fdt0)
2812{
2813 uint64_t dt2;
2814
2815 set_float_exception_flags(0, &env->active_fpu.fp_status);
2816 set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
2817 dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
2818 RESTORE_ROUNDING_MODE;
2819 update_fcr31();
2820 if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2821 dt2 = FLOAT_SNAN64;
2822 return dt2;
2823}
2824
2825uint64_t helper_float_floorl_s(uint32_t fst0)
2826{
2827 uint64_t dt2;
2828
2829 set_float_exception_flags(0, &env->active_fpu.fp_status);
2830 set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
2831 dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
2832 RESTORE_ROUNDING_MODE;
2833 update_fcr31();
2834 if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2835 dt2 = FLOAT_SNAN64;
2836 return dt2;
2837}
2838
2839uint32_t helper_float_floorw_d(uint64_t fdt0)
2840{
2841 uint32_t wt2;
2842
2843 set_float_exception_flags(0, &env->active_fpu.fp_status);
2844 set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
2845 wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
2846 RESTORE_ROUNDING_MODE;
2847 update_fcr31();
2848 if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2849 wt2 = FLOAT_SNAN32;
2850 return wt2;
2851}
2852
2853uint32_t helper_float_floorw_s(uint32_t fst0)
2854{
2855 uint32_t wt2;
2856
2857 set_float_exception_flags(0, &env->active_fpu.fp_status);
2858 set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
2859 wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
2860 RESTORE_ROUNDING_MODE;
2861 update_fcr31();
2862 if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2863 wt2 = FLOAT_SNAN32;
2864 return wt2;
2865}
2866
2867
2868#define FLOAT_UNOP(name) \
2869uint64_t helper_float_ ## name ## _d(uint64_t fdt0) \
2870{ \
2871 return float64_ ## name(fdt0); \
2872} \
2873uint32_t helper_float_ ## name ## _s(uint32_t fst0) \
2874{ \
2875 return float32_ ## name(fst0); \
2876} \
2877uint64_t helper_float_ ## name ## _ps(uint64_t fdt0) \
2878{ \
2879 uint32_t wt0; \
2880 uint32_t wth0; \
2881 \
2882 wt0 = float32_ ## name(fdt0 & 0XFFFFFFFF); \
2883 wth0 = float32_ ## name(fdt0 >> 32); \
2884 return ((uint64_t)wth0 << 32) | wt0; \
2885}
2886FLOAT_UNOP(abs)
2887FLOAT_UNOP(chs)
2888#undef FLOAT_UNOP
2889
2890
2891uint64_t helper_float_recip_d(uint64_t fdt0)
2892{
2893 uint64_t fdt2;
2894
2895 set_float_exception_flags(0, &env->active_fpu.fp_status);
2896 fdt2 = float64_div(FLOAT_ONE64, fdt0, &env->active_fpu.fp_status);
2897 update_fcr31();
2898 return fdt2;
2899}
2900
2901uint32_t helper_float_recip_s(uint32_t fst0)
2902{
2903 uint32_t fst2;
2904
2905 set_float_exception_flags(0, &env->active_fpu.fp_status);
2906 fst2 = float32_div(FLOAT_ONE32, fst0, &env->active_fpu.fp_status);
2907 update_fcr31();
2908 return fst2;
2909}
2910
2911uint64_t helper_float_rsqrt_d(uint64_t fdt0)
2912{
2913 uint64_t fdt2;
2914
2915 set_float_exception_flags(0, &env->active_fpu.fp_status);
2916 fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status);
2917 fdt2 = float64_div(FLOAT_ONE64, fdt2, &env->active_fpu.fp_status);
2918 update_fcr31();
2919 return fdt2;
2920}
2921
2922uint32_t helper_float_rsqrt_s(uint32_t fst0)
2923{
2924 uint32_t fst2;
2925
2926 set_float_exception_flags(0, &env->active_fpu.fp_status);
2927 fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status);
2928 fst2 = float32_div(FLOAT_ONE32, fst2, &env->active_fpu.fp_status);
2929 update_fcr31();
2930 return fst2;
2931}
2932
2933uint64_t helper_float_recip1_d(uint64_t fdt0)
2934{
2935 uint64_t fdt2;
2936
2937 set_float_exception_flags(0, &env->active_fpu.fp_status);
2938 fdt2 = float64_div(FLOAT_ONE64, fdt0, &env->active_fpu.fp_status);
2939 update_fcr31();
2940 return fdt2;
2941}
2942
2943uint32_t helper_float_recip1_s(uint32_t fst0)
2944{
2945 uint32_t fst2;
2946
2947 set_float_exception_flags(0, &env->active_fpu.fp_status);
2948 fst2 = float32_div(FLOAT_ONE32, fst0, &env->active_fpu.fp_status);
2949 update_fcr31();
2950 return fst2;
2951}
2952
2953uint64_t helper_float_recip1_ps(uint64_t fdt0)
2954{
2955 uint32_t fst2;
2956 uint32_t fsth2;
2957
2958 set_float_exception_flags(0, &env->active_fpu.fp_status);
2959 fst2 = float32_div(FLOAT_ONE32, fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
2960 fsth2 = float32_div(FLOAT_ONE32, fdt0 >> 32, &env->active_fpu.fp_status);
2961 update_fcr31();
2962 return ((uint64_t)fsth2 << 32) | fst2;
2963}
2964
2965uint64_t helper_float_rsqrt1_d(uint64_t fdt0)
2966{
2967 uint64_t fdt2;
2968
2969 set_float_exception_flags(0, &env->active_fpu.fp_status);
2970 fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status);
2971 fdt2 = float64_div(FLOAT_ONE64, fdt2, &env->active_fpu.fp_status);
2972 update_fcr31();
2973 return fdt2;
2974}
2975
2976uint32_t helper_float_rsqrt1_s(uint32_t fst0)
2977{
2978 uint32_t fst2;
2979
2980 set_float_exception_flags(0, &env->active_fpu.fp_status);
2981 fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status);
2982 fst2 = float32_div(FLOAT_ONE32, fst2, &env->active_fpu.fp_status);
2983 update_fcr31();
2984 return fst2;
2985}
2986
2987uint64_t helper_float_rsqrt1_ps(uint64_t fdt0)
2988{
2989 uint32_t fst2;
2990 uint32_t fsth2;
2991
2992 set_float_exception_flags(0, &env->active_fpu.fp_status);
2993 fst2 = float32_sqrt(fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
2994 fsth2 = float32_sqrt(fdt0 >> 32, &env->active_fpu.fp_status);
2995 fst2 = float32_div(FLOAT_ONE32, fst2, &env->active_fpu.fp_status);
2996 fsth2 = float32_div(FLOAT_ONE32, fsth2, &env->active_fpu.fp_status);
2997 update_fcr31();
2998 return ((uint64_t)fsth2 << 32) | fst2;
2999}
3000
3001#define FLOAT_OP(name, p) void helper_float_##name##_##p(void)
3002
3003
3004#define FLOAT_BINOP(name) \
3005uint64_t helper_float_ ## name ## _d(uint64_t fdt0, uint64_t fdt1) \
3006{ \
3007 uint64_t dt2; \
3008 \
3009 set_float_exception_flags(0, &env->active_fpu.fp_status); \
3010 dt2 = float64_ ## name (fdt0, fdt1, &env->active_fpu.fp_status); \
3011 update_fcr31(); \
3012 if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INVALID) \
3013 dt2 = FLOAT_QNAN64; \
3014 return dt2; \
3015} \
3016 \
3017uint32_t helper_float_ ## name ## _s(uint32_t fst0, uint32_t fst1) \
3018{ \
3019 uint32_t wt2; \
3020 \
3021 set_float_exception_flags(0, &env->active_fpu.fp_status); \
3022 wt2 = float32_ ## name (fst0, fst1, &env->active_fpu.fp_status); \
3023 update_fcr31(); \
3024 if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INVALID) \
3025 wt2 = FLOAT_QNAN32; \
3026 return wt2; \
3027} \
3028 \
3029uint64_t helper_float_ ## name ## _ps(uint64_t fdt0, uint64_t fdt1) \
3030{ \
3031 uint32_t fst0 = fdt0 & 0XFFFFFFFF; \
3032 uint32_t fsth0 = fdt0 >> 32; \
3033 uint32_t fst1 = fdt1 & 0XFFFFFFFF; \
3034 uint32_t fsth1 = fdt1 >> 32; \
3035 uint32_t wt2; \
3036 uint32_t wth2; \
3037 \
3038 set_float_exception_flags(0, &env->active_fpu.fp_status); \
3039 wt2 = float32_ ## name (fst0, fst1, &env->active_fpu.fp_status); \
3040 wth2 = float32_ ## name (fsth0, fsth1, &env->active_fpu.fp_status); \
3041 update_fcr31(); \
3042 if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INVALID) { \
3043 wt2 = FLOAT_QNAN32; \
3044 wth2 = FLOAT_QNAN32; \
3045 } \
3046 return ((uint64_t)wth2 << 32) | wt2; \
3047}
3048
3049FLOAT_BINOP(add)
3050FLOAT_BINOP(sub)
3051FLOAT_BINOP(mul)
3052FLOAT_BINOP(div)
3053#undef FLOAT_BINOP
3054
3055
3056#define FLOAT_TERNOP(name1, name2) \
3057uint64_t helper_float_ ## name1 ## name2 ## _d(uint64_t fdt0, uint64_t fdt1, \
3058 uint64_t fdt2) \
3059{ \
3060 fdt0 = float64_ ## name1 (fdt0, fdt1, &env->active_fpu.fp_status); \
3061 return float64_ ## name2 (fdt0, fdt2, &env->active_fpu.fp_status); \
3062} \
3063 \
3064uint32_t helper_float_ ## name1 ## name2 ## _s(uint32_t fst0, uint32_t fst1, \
3065 uint32_t fst2) \
3066{ \
3067 fst0 = float32_ ## name1 (fst0, fst1, &env->active_fpu.fp_status); \
3068 return float32_ ## name2 (fst0, fst2, &env->active_fpu.fp_status); \
3069} \
3070 \
3071uint64_t helper_float_ ## name1 ## name2 ## _ps(uint64_t fdt0, uint64_t fdt1, \
3072 uint64_t fdt2) \
3073{ \
3074 uint32_t fst0 = fdt0 & 0XFFFFFFFF; \
3075 uint32_t fsth0 = fdt0 >> 32; \
3076 uint32_t fst1 = fdt1 & 0XFFFFFFFF; \
3077 uint32_t fsth1 = fdt1 >> 32; \
3078 uint32_t fst2 = fdt2 & 0XFFFFFFFF; \
3079 uint32_t fsth2 = fdt2 >> 32; \
3080 \
3081 fst0 = float32_ ## name1 (fst0, fst1, &env->active_fpu.fp_status); \
3082 fsth0 = float32_ ## name1 (fsth0, fsth1, &env->active_fpu.fp_status); \
3083 fst2 = float32_ ## name2 (fst0, fst2, &env->active_fpu.fp_status); \
3084 fsth2 = float32_ ## name2 (fsth0, fsth2, &env->active_fpu.fp_status); \
3085 return ((uint64_t)fsth2 << 32) | fst2; \
3086}
3087
3088FLOAT_TERNOP(mul, add)
3089FLOAT_TERNOP(mul, sub)
3090#undef FLOAT_TERNOP
3091
3092
3093#define FLOAT_NTERNOP(name1, name2) \
3094uint64_t helper_float_n ## name1 ## name2 ## _d(uint64_t fdt0, uint64_t fdt1, \
3095 uint64_t fdt2) \
3096{ \
3097 fdt0 = float64_ ## name1 (fdt0, fdt1, &env->active_fpu.fp_status); \
3098 fdt2 = float64_ ## name2 (fdt0, fdt2, &env->active_fpu.fp_status); \
3099 return float64_chs(fdt2); \
3100} \
3101 \
3102uint32_t helper_float_n ## name1 ## name2 ## _s(uint32_t fst0, uint32_t fst1, \
3103 uint32_t fst2) \
3104{ \
3105 fst0 = float32_ ## name1 (fst0, fst1, &env->active_fpu.fp_status); \
3106 fst2 = float32_ ## name2 (fst0, fst2, &env->active_fpu.fp_status); \
3107 return float32_chs(fst2); \
3108} \
3109 \
3110uint64_t helper_float_n ## name1 ## name2 ## _ps(uint64_t fdt0, uint64_t fdt1,\
3111 uint64_t fdt2) \
3112{ \
3113 uint32_t fst0 = fdt0 & 0XFFFFFFFF; \
3114 uint32_t fsth0 = fdt0 >> 32; \
3115 uint32_t fst1 = fdt1 & 0XFFFFFFFF; \
3116 uint32_t fsth1 = fdt1 >> 32; \
3117 uint32_t fst2 = fdt2 & 0XFFFFFFFF; \
3118 uint32_t fsth2 = fdt2 >> 32; \
3119 \
3120 fst0 = float32_ ## name1 (fst0, fst1, &env->active_fpu.fp_status); \
3121 fsth0 = float32_ ## name1 (fsth0, fsth1, &env->active_fpu.fp_status); \
3122 fst2 = float32_ ## name2 (fst0, fst2, &env->active_fpu.fp_status); \
3123 fsth2 = float32_ ## name2 (fsth0, fsth2, &env->active_fpu.fp_status); \
3124 fst2 = float32_chs(fst2); \
3125 fsth2 = float32_chs(fsth2); \
3126 return ((uint64_t)fsth2 << 32) | fst2; \
3127}
3128
3129FLOAT_NTERNOP(mul, add)
3130FLOAT_NTERNOP(mul, sub)
3131#undef FLOAT_NTERNOP
3132
3133
3134uint64_t helper_float_recip2_d(uint64_t fdt0, uint64_t fdt2)
3135{
3136 set_float_exception_flags(0, &env->active_fpu.fp_status);
3137 fdt2 = float64_mul(fdt0, fdt2, &env->active_fpu.fp_status);
3138 fdt2 = float64_chs(float64_sub(fdt2, FLOAT_ONE64, &env->active_fpu.fp_status));
3139 update_fcr31();
3140 return fdt2;
3141}
3142
3143uint32_t helper_float_recip2_s(uint32_t fst0, uint32_t fst2)
3144{
3145 set_float_exception_flags(0, &env->active_fpu.fp_status);
3146 fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
3147 fst2 = float32_chs(float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status));
3148 update_fcr31();
3149 return fst2;
3150}
3151
3152uint64_t helper_float_recip2_ps(uint64_t fdt0, uint64_t fdt2)
3153{
3154 uint32_t fst0 = fdt0 & 0XFFFFFFFF;
3155 uint32_t fsth0 = fdt0 >> 32;
3156 uint32_t fst2 = fdt2 & 0XFFFFFFFF;
3157 uint32_t fsth2 = fdt2 >> 32;
3158
3159 set_float_exception_flags(0, &env->active_fpu.fp_status);
3160 fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
3161 fsth2 = float32_mul(fsth0, fsth2, &env->active_fpu.fp_status);
3162 fst2 = float32_chs(float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status));
3163 fsth2 = float32_chs(float32_sub(fsth2, FLOAT_ONE32, &env->active_fpu.fp_status));
3164 update_fcr31();
3165 return ((uint64_t)fsth2 << 32) | fst2;
3166}
3167
3168uint64_t helper_float_rsqrt2_d(uint64_t fdt0, uint64_t fdt2)
3169{
3170 set_float_exception_flags(0, &env->active_fpu.fp_status);
3171 fdt2 = float64_mul(fdt0, fdt2, &env->active_fpu.fp_status);
3172 fdt2 = float64_sub(fdt2, FLOAT_ONE64, &env->active_fpu.fp_status);
3173 fdt2 = float64_chs(float64_div(fdt2, FLOAT_TWO64, &env->active_fpu.fp_status));
3174 update_fcr31();
3175 return fdt2;
3176}
3177
3178uint32_t helper_float_rsqrt2_s(uint32_t fst0, uint32_t fst2)
3179{
3180 set_float_exception_flags(0, &env->active_fpu.fp_status);
3181 fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
3182 fst2 = float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status);
3183 fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32, &env->active_fpu.fp_status));
3184 update_fcr31();
3185 return fst2;
3186}
3187
3188uint64_t helper_float_rsqrt2_ps(uint64_t fdt0, uint64_t fdt2)
3189{
3190 uint32_t fst0 = fdt0 & 0XFFFFFFFF;
3191 uint32_t fsth0 = fdt0 >> 32;
3192 uint32_t fst2 = fdt2 & 0XFFFFFFFF;
3193 uint32_t fsth2 = fdt2 >> 32;
3194
3195 set_float_exception_flags(0, &env->active_fpu.fp_status);
3196 fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
3197 fsth2 = float32_mul(fsth0, fsth2, &env->active_fpu.fp_status);
3198 fst2 = float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status);
3199 fsth2 = float32_sub(fsth2, FLOAT_ONE32, &env->active_fpu.fp_status);
3200 fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32, &env->active_fpu.fp_status));
3201 fsth2 = float32_chs(float32_div(fsth2, FLOAT_TWO32, &env->active_fpu.fp_status));
3202 update_fcr31();
3203 return ((uint64_t)fsth2 << 32) | fst2;
3204}
3205
3206uint64_t helper_float_addr_ps(uint64_t fdt0, uint64_t fdt1)
3207{
3208 uint32_t fst0 = fdt0 & 0XFFFFFFFF;
3209 uint32_t fsth0 = fdt0 >> 32;
3210 uint32_t fst1 = fdt1 & 0XFFFFFFFF;
3211 uint32_t fsth1 = fdt1 >> 32;
3212 uint32_t fst2;
3213 uint32_t fsth2;
3214
3215 set_float_exception_flags(0, &env->active_fpu.fp_status);
3216 fst2 = float32_add (fst0, fsth0, &env->active_fpu.fp_status);
3217 fsth2 = float32_add (fst1, fsth1, &env->active_fpu.fp_status);
3218 update_fcr31();
3219 return ((uint64_t)fsth2 << 32) | fst2;
3220}
3221
3222uint64_t helper_float_mulr_ps(uint64_t fdt0, uint64_t fdt1)
3223{
3224 uint32_t fst0 = fdt0 & 0XFFFFFFFF;
3225 uint32_t fsth0 = fdt0 >> 32;
3226 uint32_t fst1 = fdt1 & 0XFFFFFFFF;
3227 uint32_t fsth1 = fdt1 >> 32;
3228 uint32_t fst2;
3229 uint32_t fsth2;
3230
3231 set_float_exception_flags(0, &env->active_fpu.fp_status);
3232 fst2 = float32_mul (fst0, fsth0, &env->active_fpu.fp_status);
3233 fsth2 = float32_mul (fst1, fsth1, &env->active_fpu.fp_status);
3234 update_fcr31();
3235 return ((uint64_t)fsth2 << 32) | fst2;
3236}
3237
3238
3239#define FOP_COND_D(op, cond) \
3240void helper_cmp_d_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \
3241{ \
3242 int c; \
3243 set_float_exception_flags(0, &env->active_fpu.fp_status); \
3244 c = cond; \
3245 update_fcr31(); \
3246 if (c) \
3247 SET_FP_COND(cc, env->active_fpu); \
3248 else \
3249 CLEAR_FP_COND(cc, env->active_fpu); \
3250} \
3251void helper_cmpabs_d_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \
3252{ \
3253 int c; \
3254 set_float_exception_flags(0, &env->active_fpu.fp_status); \
3255 fdt0 = float64_abs(fdt0); \
3256 fdt1 = float64_abs(fdt1); \
3257 c = cond; \
3258 update_fcr31(); \
3259 if (c) \
3260 SET_FP_COND(cc, env->active_fpu); \
3261 else \
3262 CLEAR_FP_COND(cc, env->active_fpu); \
3263}
3264
3265
3266
3267FOP_COND_D(f, (float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status), 0))
3268FOP_COND_D(un, float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status))
3269FOP_COND_D(eq, float64_eq_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
3270FOP_COND_D(ueq, float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status) || float64_eq_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
3271FOP_COND_D(olt, float64_lt_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
3272FOP_COND_D(ult, float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status) || float64_lt_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
3273FOP_COND_D(ole, float64_le_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
3274FOP_COND_D(ule, float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status) || float64_le_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
3275
3276
3277FOP_COND_D(sf, (float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status), 0))
3278FOP_COND_D(ngle,float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status))
3279FOP_COND_D(seq, float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
3280FOP_COND_D(ngl, float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status) || float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
3281FOP_COND_D(lt, float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
3282FOP_COND_D(nge, float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status) || float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
3283FOP_COND_D(le, float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
3284FOP_COND_D(ngt, float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status) || float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
3285
3286#define FOP_COND_S(op, cond) \
3287void helper_cmp_s_ ## op (uint32_t fst0, uint32_t fst1, int cc) \
3288{ \
3289 int c; \
3290 set_float_exception_flags(0, &env->active_fpu.fp_status); \
3291 c = cond; \
3292 update_fcr31(); \
3293 if (c) \
3294 SET_FP_COND(cc, env->active_fpu); \
3295 else \
3296 CLEAR_FP_COND(cc, env->active_fpu); \
3297} \
3298void helper_cmpabs_s_ ## op (uint32_t fst0, uint32_t fst1, int cc) \
3299{ \
3300 int c; \
3301 set_float_exception_flags(0, &env->active_fpu.fp_status); \
3302 fst0 = float32_abs(fst0); \
3303 fst1 = float32_abs(fst1); \
3304 c = cond; \
3305 update_fcr31(); \
3306 if (c) \
3307 SET_FP_COND(cc, env->active_fpu); \
3308 else \
3309 CLEAR_FP_COND(cc, env->active_fpu); \
3310}
3311
3312
3313
3314FOP_COND_S(f, (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status), 0))
3315FOP_COND_S(un, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status))
3316FOP_COND_S(eq, float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status))
3317FOP_COND_S(ueq, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status) || float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status))
3318FOP_COND_S(olt, float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status))
3319FOP_COND_S(ult, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status) || float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status))
3320FOP_COND_S(ole, float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status))
3321FOP_COND_S(ule, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status) || float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status))
3322
3323
3324FOP_COND_S(sf, (float32_unordered(fst1, fst0, &env->active_fpu.fp_status), 0))
3325FOP_COND_S(ngle,float32_unordered(fst1, fst0, &env->active_fpu.fp_status))
3326FOP_COND_S(seq, float32_eq(fst0, fst1, &env->active_fpu.fp_status))
3327FOP_COND_S(ngl, float32_unordered(fst1, fst0, &env->active_fpu.fp_status) || float32_eq(fst0, fst1, &env->active_fpu.fp_status))
3328FOP_COND_S(lt, float32_lt(fst0, fst1, &env->active_fpu.fp_status))
3329FOP_COND_S(nge, float32_unordered(fst1, fst0, &env->active_fpu.fp_status) || float32_lt(fst0, fst1, &env->active_fpu.fp_status))
3330FOP_COND_S(le, float32_le(fst0, fst1, &env->active_fpu.fp_status))
3331FOP_COND_S(ngt, float32_unordered(fst1, fst0, &env->active_fpu.fp_status) || float32_le(fst0, fst1, &env->active_fpu.fp_status))
3332
3333#define FOP_COND_PS(op, condl, condh) \
3334void helper_cmp_ps_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \
3335{ \
3336 uint32_t fst0, fsth0, fst1, fsth1; \
3337 int ch, cl; \
3338 set_float_exception_flags(0, &env->active_fpu.fp_status); \
3339 fst0 = fdt0 & 0XFFFFFFFF; \
3340 fsth0 = fdt0 >> 32; \
3341 fst1 = fdt1 & 0XFFFFFFFF; \
3342 fsth1 = fdt1 >> 32; \
3343 cl = condl; \
3344 ch = condh; \
3345 update_fcr31(); \
3346 if (cl) \
3347 SET_FP_COND(cc, env->active_fpu); \
3348 else \
3349 CLEAR_FP_COND(cc, env->active_fpu); \
3350 if (ch) \
3351 SET_FP_COND(cc + 1, env->active_fpu); \
3352 else \
3353 CLEAR_FP_COND(cc + 1, env->active_fpu); \
3354} \
3355void helper_cmpabs_ps_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \
3356{ \
3357 uint32_t fst0, fsth0, fst1, fsth1; \
3358 int ch, cl; \
3359 fst0 = float32_abs(fdt0 & 0XFFFFFFFF); \
3360 fsth0 = float32_abs(fdt0 >> 32); \
3361 fst1 = float32_abs(fdt1 & 0XFFFFFFFF); \
3362 fsth1 = float32_abs(fdt1 >> 32); \
3363 cl = condl; \
3364 ch = condh; \
3365 update_fcr31(); \
3366 if (cl) \
3367 SET_FP_COND(cc, env->active_fpu); \
3368 else \
3369 CLEAR_FP_COND(cc, env->active_fpu); \
3370 if (ch) \
3371 SET_FP_COND(cc + 1, env->active_fpu); \
3372 else \
3373 CLEAR_FP_COND(cc + 1, env->active_fpu); \
3374}
3375
3376
3377
3378FOP_COND_PS(f, (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status), 0),
3379 (float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status), 0))
3380FOP_COND_PS(un, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status),
3381 float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status))
3382FOP_COND_PS(eq, float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status),
3383 float32_eq_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
3384FOP_COND_PS(ueq, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status) || float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status),
3385 float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status) || float32_eq_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
3386FOP_COND_PS(olt, float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status),
3387 float32_lt_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
3388FOP_COND_PS(ult, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status) || float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status),
3389 float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status) || float32_lt_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
3390FOP_COND_PS(ole, float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status),
3391 float32_le_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
3392FOP_COND_PS(ule, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status) || float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status),
3393 float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status) || float32_le_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
3394
3395
3396FOP_COND_PS(sf, (float32_unordered(fst1, fst0, &env->active_fpu.fp_status), 0),
3397 (float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status), 0))
3398FOP_COND_PS(ngle,float32_unordered(fst1, fst0, &env->active_fpu.fp_status),
3399 float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status))
3400FOP_COND_PS(seq, float32_eq(fst0, fst1, &env->active_fpu.fp_status),
3401 float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
3402FOP_COND_PS(ngl, float32_unordered(fst1, fst0, &env->active_fpu.fp_status) || float32_eq(fst0, fst1, &env->active_fpu.fp_status),
3403 float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status) || float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
3404FOP_COND_PS(lt, float32_lt(fst0, fst1, &env->active_fpu.fp_status),
3405 float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
3406FOP_COND_PS(nge, float32_unordered(fst1, fst0, &env->active_fpu.fp_status) || float32_lt(fst0, fst1, &env->active_fpu.fp_status),
3407 float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status) || float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
3408FOP_COND_PS(le, float32_le(fst0, fst1, &env->active_fpu.fp_status),
3409 float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
3410FOP_COND_PS(ngt, float32_unordered(fst1, fst0, &env->active_fpu.fp_status) || float32_le(fst0, fst1, &env->active_fpu.fp_status),
3411 float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status) || float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
3412