]> Git Repo - qemu.git/blame - target-mips/op.c
Fix mfc0 and dmtc0 instructions on MIPS64, by Aurelien Jarno.
[qemu.git] / target-mips / op.c
CommitLineData
6af0bf9c
FB
1/*
2 * MIPS emulation micro-operations for qemu.
3 *
4 * Copyright (c) 2004-2005 Jocelyn Mayer
6ea83fed 5 * Copyright (c) 2006 Marius Groeger (FPU operations)
6af0bf9c
FB
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#include "config.h"
23#include "exec.h"
24
1b351e52 25#ifndef CALL_FROM_TB0
5a5012ec 26#define CALL_FROM_TB0(func) func()
1b351e52
FB
27#endif
28#ifndef CALL_FROM_TB1
5a5012ec 29#define CALL_FROM_TB1(func, arg0) func(arg0)
1b351e52
FB
30#endif
31#ifndef CALL_FROM_TB1_CONST16
5a5012ec 32#define CALL_FROM_TB1_CONST16(func, arg0) CALL_FROM_TB1(func, arg0)
1b351e52
FB
33#endif
34#ifndef CALL_FROM_TB2
5a5012ec 35#define CALL_FROM_TB2(func, arg0, arg1) func(arg0, arg1)
1b351e52
FB
36#endif
37#ifndef CALL_FROM_TB2_CONST16
38#define CALL_FROM_TB2_CONST16(func, arg0, arg1) \
5a5012ec 39 CALL_FROM_TB2(func, arg0, arg1)
1b351e52
FB
40#endif
41#ifndef CALL_FROM_TB3
5a5012ec 42#define CALL_FROM_TB3(func, arg0, arg1, arg2) func(arg0, arg1, arg2)
1b351e52
FB
43#endif
44#ifndef CALL_FROM_TB4
45#define CALL_FROM_TB4(func, arg0, arg1, arg2, arg3) \
5a5012ec 46 func(arg0, arg1, arg2, arg3)
1b351e52
FB
47#endif
48
6af0bf9c
FB
49#define REG 1
50#include "op_template.c"
51#undef REG
52#define REG 2
53#include "op_template.c"
54#undef REG
55#define REG 3
56#include "op_template.c"
57#undef REG
58#define REG 4
59#include "op_template.c"
60#undef REG
61#define REG 5
62#include "op_template.c"
63#undef REG
64#define REG 6
65#include "op_template.c"
66#undef REG
67#define REG 7
68#include "op_template.c"
69#undef REG
70#define REG 8
71#include "op_template.c"
72#undef REG
73#define REG 9
74#include "op_template.c"
75#undef REG
76#define REG 10
77#include "op_template.c"
78#undef REG
79#define REG 11
80#include "op_template.c"
81#undef REG
82#define REG 12
83#include "op_template.c"
84#undef REG
85#define REG 13
86#include "op_template.c"
87#undef REG
88#define REG 14
89#include "op_template.c"
90#undef REG
91#define REG 15
92#include "op_template.c"
93#undef REG
94#define REG 16
95#include "op_template.c"
96#undef REG
97#define REG 17
98#include "op_template.c"
99#undef REG
100#define REG 18
101#include "op_template.c"
102#undef REG
103#define REG 19
104#include "op_template.c"
105#undef REG
106#define REG 20
107#include "op_template.c"
108#undef REG
109#define REG 21
110#include "op_template.c"
111#undef REG
112#define REG 22
113#include "op_template.c"
114#undef REG
115#define REG 23
116#include "op_template.c"
117#undef REG
118#define REG 24
119#include "op_template.c"
120#undef REG
121#define REG 25
122#include "op_template.c"
123#undef REG
124#define REG 26
125#include "op_template.c"
126#undef REG
127#define REG 27
128#include "op_template.c"
129#undef REG
130#define REG 28
131#include "op_template.c"
132#undef REG
133#define REG 29
134#include "op_template.c"
135#undef REG
136#define REG 30
137#include "op_template.c"
138#undef REG
139#define REG 31
140#include "op_template.c"
141#undef REG
142
c570fd16 143#define TN
6af0bf9c
FB
144#include "op_template.c"
145#undef TN
146
5a5012ec 147#define FREG 0
6ea83fed 148#include "fop_template.c"
5a5012ec
TS
149#undef FREG
150#define FREG 1
6ea83fed 151#include "fop_template.c"
5a5012ec
TS
152#undef FREG
153#define FREG 2
6ea83fed 154#include "fop_template.c"
5a5012ec
TS
155#undef FREG
156#define FREG 3
6ea83fed 157#include "fop_template.c"
5a5012ec
TS
158#undef FREG
159#define FREG 4
6ea83fed 160#include "fop_template.c"
5a5012ec
TS
161#undef FREG
162#define FREG 5
6ea83fed 163#include "fop_template.c"
5a5012ec
TS
164#undef FREG
165#define FREG 6
6ea83fed 166#include "fop_template.c"
5a5012ec
TS
167#undef FREG
168#define FREG 7
6ea83fed 169#include "fop_template.c"
5a5012ec
TS
170#undef FREG
171#define FREG 8
6ea83fed 172#include "fop_template.c"
5a5012ec
TS
173#undef FREG
174#define FREG 9
6ea83fed 175#include "fop_template.c"
5a5012ec
TS
176#undef FREG
177#define FREG 10
6ea83fed 178#include "fop_template.c"
5a5012ec
TS
179#undef FREG
180#define FREG 11
6ea83fed 181#include "fop_template.c"
5a5012ec
TS
182#undef FREG
183#define FREG 12
6ea83fed 184#include "fop_template.c"
5a5012ec
TS
185#undef FREG
186#define FREG 13
6ea83fed 187#include "fop_template.c"
5a5012ec
TS
188#undef FREG
189#define FREG 14
6ea83fed 190#include "fop_template.c"
5a5012ec
TS
191#undef FREG
192#define FREG 15
6ea83fed 193#include "fop_template.c"
5a5012ec
TS
194#undef FREG
195#define FREG 16
6ea83fed 196#include "fop_template.c"
5a5012ec
TS
197#undef FREG
198#define FREG 17
6ea83fed 199#include "fop_template.c"
5a5012ec
TS
200#undef FREG
201#define FREG 18
6ea83fed 202#include "fop_template.c"
5a5012ec
TS
203#undef FREG
204#define FREG 19
6ea83fed 205#include "fop_template.c"
5a5012ec
TS
206#undef FREG
207#define FREG 20
6ea83fed 208#include "fop_template.c"
5a5012ec
TS
209#undef FREG
210#define FREG 21
6ea83fed 211#include "fop_template.c"
5a5012ec
TS
212#undef FREG
213#define FREG 22
6ea83fed 214#include "fop_template.c"
5a5012ec
TS
215#undef FREG
216#define FREG 23
6ea83fed 217#include "fop_template.c"
5a5012ec
TS
218#undef FREG
219#define FREG 24
6ea83fed 220#include "fop_template.c"
5a5012ec
TS
221#undef FREG
222#define FREG 25
6ea83fed 223#include "fop_template.c"
5a5012ec
TS
224#undef FREG
225#define FREG 26
6ea83fed 226#include "fop_template.c"
5a5012ec
TS
227#undef FREG
228#define FREG 27
6ea83fed 229#include "fop_template.c"
5a5012ec
TS
230#undef FREG
231#define FREG 28
6ea83fed 232#include "fop_template.c"
5a5012ec
TS
233#undef FREG
234#define FREG 29
6ea83fed 235#include "fop_template.c"
5a5012ec
TS
236#undef FREG
237#define FREG 30
6ea83fed 238#include "fop_template.c"
5a5012ec
TS
239#undef FREG
240#define FREG 31
6ea83fed 241#include "fop_template.c"
5a5012ec 242#undef FREG
6ea83fed
FB
243
244#define FTN
245#include "fop_template.c"
246#undef FTN
247
6af0bf9c
FB
248void op_dup_T0 (void)
249{
250 T2 = T0;
251 RETURN();
252}
253
254void op_load_HI (void)
255{
256 T0 = env->HI;
257 RETURN();
258}
259
260void op_store_HI (void)
261{
262 env->HI = T0;
263 RETURN();
264}
265
266void op_load_LO (void)
267{
268 T0 = env->LO;
269 RETURN();
270}
271
272void op_store_LO (void)
273{
274 env->LO = T0;
275 RETURN();
276}
277
278/* Load and store */
279#define MEMSUFFIX _raw
280#include "op_mem.c"
281#undef MEMSUFFIX
282#if !defined(CONFIG_USER_ONLY)
283#define MEMSUFFIX _user
284#include "op_mem.c"
285#undef MEMSUFFIX
286
287#define MEMSUFFIX _kernel
288#include "op_mem.c"
289#undef MEMSUFFIX
290#endif
291
a6763a58
TS
292/* Addresses computation */
293void op_addr_add (void)
294{
295/* For compatibility with 32-bit code, data reference in user mode
296 with Status_UX = 0 should be casted to 32-bit and sign extended.
297 See the MIPS64 PRA manual, section 4.10. */
298#ifdef TARGET_MIPS64
299 if ((env->CP0_Status & (1 << CP0St_UM)) &&
300 !(env->CP0_Status & (1 << CP0St_UX)))
301 T0 = (int64_t)(int32_t)(T0 + T1);
302 else
303#endif
304 T0 += T1;
305 RETURN();
306}
307
6af0bf9c
FB
308/* Arithmetic */
309void op_add (void)
310{
5dc4b744 311 T0 = (int32_t)((int32_t)T0 + (int32_t)T1);
6af0bf9c
FB
312 RETURN();
313}
314
315void op_addo (void)
316{
317 target_ulong tmp;
318
c570fd16
TS
319 tmp = (int32_t)T0;
320 T0 = (int32_t)T0 + (int32_t)T1;
76e050c2 321 if (((tmp ^ T1 ^ (-1)) & (T0 ^ T1)) >> 31) {
c570fd16 322 /* operands of same sign, result different sign */
1579a72e 323 CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
6af0bf9c 324 }
5dc4b744 325 T0 = (int32_t)T0;
6af0bf9c
FB
326 RETURN();
327}
328
329void op_sub (void)
330{
5dc4b744 331 T0 = (int32_t)((int32_t)T0 - (int32_t)T1);
6af0bf9c
FB
332 RETURN();
333}
334
335void op_subo (void)
336{
337 target_ulong tmp;
338
c570fd16 339 tmp = (int32_t)T0;
6af0bf9c 340 T0 = (int32_t)T0 - (int32_t)T1;
76e050c2 341 if (((tmp ^ T1) & (tmp ^ T0)) >> 31) {
c570fd16 342 /* operands of different sign, first operand and result different sign */
1579a72e 343 CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
6af0bf9c 344 }
5dc4b744 345 T0 = (int32_t)T0;
6af0bf9c
FB
346 RETURN();
347}
348
349void op_mul (void)
350{
5dc4b744 351 T0 = (int32_t)((int32_t)T0 * (int32_t)T1);
6af0bf9c
FB
352 RETURN();
353}
354
80c27194
TS
355#if HOST_LONG_BITS < 64
356void op_div (void)
357{
358 CALL_FROM_TB0(do_div);
359 RETURN();
360}
361#else
6af0bf9c
FB
362void op_div (void)
363{
364 if (T1 != 0) {
80c27194
TS
365 env->LO = (int32_t)((int64_t)(int32_t)T0 / (int32_t)T1);
366 env->HI = (int32_t)((int64_t)(int32_t)T0 % (int32_t)T1);
6af0bf9c
FB
367 }
368 RETURN();
369}
80c27194 370#endif
6af0bf9c
FB
371
372void op_divu (void)
c570fd16
TS
373{
374 if (T1 != 0) {
5dc4b744
TS
375 env->LO = (int32_t)((uint32_t)T0 / (uint32_t)T1);
376 env->HI = (int32_t)((uint32_t)T0 % (uint32_t)T1);
c570fd16
TS
377 }
378 RETURN();
379}
380
60aa19ab 381#ifdef TARGET_MIPS64
c570fd16
TS
382/* Arithmetic */
383void op_dadd (void)
384{
385 T0 += T1;
386 RETURN();
387}
388
389void op_daddo (void)
390{
391 target_long tmp;
392
393 tmp = T0;
394 T0 += T1;
395 if (((tmp ^ T1 ^ (-1)) & (T0 ^ T1)) >> 63) {
396 /* operands of same sign, result different sign */
1579a72e 397 CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
c570fd16
TS
398 }
399 RETURN();
400}
401
402void op_dsub (void)
403{
404 T0 -= T1;
405 RETURN();
406}
407
408void op_dsubo (void)
409{
410 target_long tmp;
411
412 tmp = T0;
413 T0 = (int64_t)T0 - (int64_t)T1;
414 if (((tmp ^ T1) & (tmp ^ T0)) >> 63) {
415 /* operands of different sign, first operand and result different sign */
1579a72e 416 CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
c570fd16
TS
417 }
418 RETURN();
419}
420
421void op_dmul (void)
422{
423 T0 = (int64_t)T0 * (int64_t)T1;
424 RETURN();
425}
426
c570fd16
TS
427/* Those might call libgcc functions. */
428void op_ddiv (void)
429{
430 do_ddiv();
431 RETURN();
432}
433
80c27194 434#if TARGET_LONG_BITS > HOST_LONG_BITS
c570fd16
TS
435void op_ddivu (void)
436{
437 do_ddivu();
438 RETURN();
439}
440#else
c570fd16 441void op_ddivu (void)
6af0bf9c
FB
442{
443 if (T1 != 0) {
444 env->LO = T0 / T1;
445 env->HI = T0 % T1;
446 }
447 RETURN();
448}
c570fd16 449#endif
60aa19ab 450#endif /* TARGET_MIPS64 */
6af0bf9c
FB
451
452/* Logical */
453void op_and (void)
454{
455 T0 &= T1;
456 RETURN();
457}
458
459void op_nor (void)
460{
461 T0 = ~(T0 | T1);
462 RETURN();
463}
464
465void op_or (void)
466{
467 T0 |= T1;
468 RETURN();
469}
470
471void op_xor (void)
472{
473 T0 ^= T1;
474 RETURN();
475}
476
477void op_sll (void)
478{
5a63bcb2 479 T0 = (int32_t)((uint32_t)T0 << T1);
6af0bf9c
FB
480 RETURN();
481}
482
483void op_sra (void)
484{
5a63bcb2 485 T0 = (int32_t)((int32_t)T0 >> T1);
6af0bf9c
FB
486 RETURN();
487}
488
489void op_srl (void)
490{
5a63bcb2 491 T0 = (int32_t)((uint32_t)T0 >> T1);
6af0bf9c
FB
492 RETURN();
493}
494
7a387fff
TS
495void op_rotr (void)
496{
497 target_ulong tmp;
498
499 if (T1) {
5a63bcb2
TS
500 tmp = (int32_t)((uint32_t)T0 << (0x20 - T1));
501 T0 = (int32_t)((uint32_t)T0 >> T1) | tmp;
502 }
7a387fff
TS
503 RETURN();
504}
505
6af0bf9c
FB
506void op_sllv (void)
507{
5dc4b744 508 T0 = (int32_t)((uint32_t)T1 << ((uint32_t)T0 & 0x1F));
6af0bf9c
FB
509 RETURN();
510}
511
512void op_srav (void)
513{
5dc4b744 514 T0 = (int32_t)((int32_t)T1 >> (T0 & 0x1F));
6af0bf9c
FB
515 RETURN();
516}
517
518void op_srlv (void)
519{
5dc4b744 520 T0 = (int32_t)((uint32_t)T1 >> (T0 & 0x1F));
6af0bf9c
FB
521 RETURN();
522}
523
7a387fff
TS
524void op_rotrv (void)
525{
526 target_ulong tmp;
527
528 T0 &= 0x1F;
529 if (T0) {
5dc4b744
TS
530 tmp = (int32_t)((uint32_t)T1 << (0x20 - T0));
531 T0 = (int32_t)((uint32_t)T1 >> T0) | tmp;
7a387fff
TS
532 } else
533 T0 = T1;
534 RETURN();
535}
536
6af0bf9c
FB
537void op_clo (void)
538{
539 int n;
540
c570fd16 541 if (T0 == ~((target_ulong)0)) {
6af0bf9c
FB
542 T0 = 32;
543 } else {
544 for (n = 0; n < 32; n++) {
545 if (!(T0 & (1 << 31)))
546 break;
547 T0 = T0 << 1;
548 }
549 T0 = n;
550 }
551 RETURN();
552}
553
554void op_clz (void)
555{
556 int n;
557
558 if (T0 == 0) {
559 T0 = 32;
560 } else {
561 for (n = 0; n < 32; n++) {
562 if (T0 & (1 << 31))
563 break;
564 T0 = T0 << 1;
565 }
566 T0 = n;
567 }
568 RETURN();
569}
570
60aa19ab 571#ifdef TARGET_MIPS64
c570fd16
TS
572
573#if TARGET_LONG_BITS > HOST_LONG_BITS
574/* Those might call libgcc functions. */
575void op_dsll (void)
6af0bf9c 576{
c570fd16
TS
577 CALL_FROM_TB0(do_dsll);
578 RETURN();
6af0bf9c
FB
579}
580
c570fd16 581void op_dsll32 (void)
6af0bf9c 582{
c570fd16
TS
583 CALL_FROM_TB0(do_dsll32);
584 RETURN();
6af0bf9c
FB
585}
586
c570fd16 587void op_dsra (void)
6af0bf9c 588{
c570fd16 589 CALL_FROM_TB0(do_dsra);
6af0bf9c
FB
590 RETURN();
591}
592
c570fd16 593void op_dsra32 (void)
6af0bf9c 594{
c570fd16 595 CALL_FROM_TB0(do_dsra32);
6af0bf9c
FB
596 RETURN();
597}
598
c570fd16 599void op_dsrl (void)
6af0bf9c 600{
c570fd16
TS
601 CALL_FROM_TB0(do_dsrl);
602 RETURN();
603}
6af0bf9c 604
c570fd16
TS
605void op_dsrl32 (void)
606{
607 CALL_FROM_TB0(do_dsrl32);
6af0bf9c
FB
608 RETURN();
609}
610
c570fd16 611void op_drotr (void)
6af0bf9c 612{
c570fd16
TS
613 CALL_FROM_TB0(do_drotr);
614 RETURN();
615}
6af0bf9c 616
c570fd16
TS
617void op_drotr32 (void)
618{
619 CALL_FROM_TB0(do_drotr32);
6af0bf9c
FB
620 RETURN();
621}
622
c570fd16 623void op_dsllv (void)
6af0bf9c 624{
c570fd16
TS
625 CALL_FROM_TB0(do_dsllv);
626 RETURN();
627}
6af0bf9c 628
c570fd16
TS
629void op_dsrav (void)
630{
631 CALL_FROM_TB0(do_dsrav);
6af0bf9c
FB
632 RETURN();
633}
634
c570fd16 635void op_dsrlv (void)
6af0bf9c 636{
c570fd16
TS
637 CALL_FROM_TB0(do_dsrlv);
638 RETURN();
639}
6af0bf9c 640
c570fd16
TS
641void op_drotrv (void)
642{
643 CALL_FROM_TB0(do_drotrv);
6af0bf9c
FB
644 RETURN();
645}
c570fd16
TS
646
647#else /* TARGET_LONG_BITS > HOST_LONG_BITS */
648
649void op_dsll (void)
650{
651 T0 = T0 << T1;
652 RETURN();
653}
654
655void op_dsll32 (void)
656{
657 T0 = T0 << (T1 + 32);
658 RETURN();
659}
660
661void op_dsra (void)
662{
663 T0 = (int64_t)T0 >> T1;
664 RETURN();
665}
666
667void op_dsra32 (void)
668{
669 T0 = (int64_t)T0 >> (T1 + 32);
670 RETURN();
671}
672
673void op_dsrl (void)
674{
675 T0 = T0 >> T1;
676 RETURN();
677}
678
679void op_dsrl32 (void)
680{
681 T0 = T0 >> (T1 + 32);
682 RETURN();
683}
684
685void op_drotr (void)
686{
687 target_ulong tmp;
688
689 if (T1) {
690 tmp = T0 << (0x40 - T1);
691 T0 = (T0 >> T1) | tmp;
5a63bcb2 692 }
c570fd16
TS
693 RETURN();
694}
695
696void op_drotr32 (void)
697{
698 target_ulong tmp;
699
700 if (T1) {
701 tmp = T0 << (0x40 - (32 + T1));
702 T0 = (T0 >> (32 + T1)) | tmp;
5a63bcb2 703 }
c570fd16
TS
704 RETURN();
705}
706
707void op_dsllv (void)
708{
709 T0 = T1 << (T0 & 0x3F);
710 RETURN();
711}
712
713void op_dsrav (void)
714{
715 T0 = (int64_t)T1 >> (T0 & 0x3F);
716 RETURN();
717}
718
719void op_dsrlv (void)
720{
721 T0 = T1 >> (T0 & 0x3F);
722 RETURN();
723}
724
725void op_drotrv (void)
726{
727 target_ulong tmp;
728
729 T0 &= 0x3F;
730 if (T0) {
731 tmp = T1 << (0x40 - T0);
732 T0 = (T1 >> T0) | tmp;
733 } else
734 T0 = T1;
735 RETURN();
736}
737#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
738
739void op_dclo (void)
740{
741 int n;
742
743 if (T0 == ~((target_ulong)0)) {
744 T0 = 64;
745 } else {
746 for (n = 0; n < 64; n++) {
747 if (!(T0 & (1ULL << 63)))
748 break;
749 T0 = T0 << 1;
750 }
751 T0 = n;
752 }
753 RETURN();
754}
755
756void op_dclz (void)
757{
758 int n;
759
760 if (T0 == 0) {
761 T0 = 64;
762 } else {
763 for (n = 0; n < 64; n++) {
764 if (T0 & (1ULL << 63))
765 break;
766 T0 = T0 << 1;
767 }
768 T0 = n;
769 }
770 RETURN();
771}
772#endif
773
774/* 64 bits arithmetic */
775#if TARGET_LONG_BITS > HOST_LONG_BITS
6af0bf9c
FB
776void op_mult (void)
777{
778 CALL_FROM_TB0(do_mult);
779 RETURN();
780}
781
782void op_multu (void)
783{
784 CALL_FROM_TB0(do_multu);
785 RETURN();
786}
787
788void op_madd (void)
789{
790 CALL_FROM_TB0(do_madd);
791 RETURN();
792}
793
794void op_maddu (void)
795{
796 CALL_FROM_TB0(do_maddu);
797 RETURN();
798}
799
800void op_msub (void)
801{
802 CALL_FROM_TB0(do_msub);
803 RETURN();
804}
805
806void op_msubu (void)
807{
808 CALL_FROM_TB0(do_msubu);
809 RETURN();
810}
c570fd16
TS
811
812#else /* TARGET_LONG_BITS > HOST_LONG_BITS */
813
814static inline uint64_t get_HILO (void)
815{
816 return ((uint64_t)env->HI << 32) | ((uint64_t)(uint32_t)env->LO);
817}
818
819static inline void set_HILO (uint64_t HILO)
820{
5dc4b744
TS
821 env->LO = (int32_t)(HILO & 0xFFFFFFFF);
822 env->HI = (int32_t)(HILO >> 32);
c570fd16
TS
823}
824
825void op_mult (void)
826{
827 set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
828 RETURN();
829}
830
831void op_multu (void)
832{
833 set_HILO((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
834 RETURN();
835}
836
837void op_madd (void)
838{
839 int64_t tmp;
840
841 tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
842 set_HILO((int64_t)get_HILO() + tmp);
843 RETURN();
844}
845
846void op_maddu (void)
847{
848 uint64_t tmp;
849
850 tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
851 set_HILO(get_HILO() + tmp);
852 RETURN();
853}
854
855void op_msub (void)
856{
857 int64_t tmp;
858
859 tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
860 set_HILO((int64_t)get_HILO() - tmp);
861 RETURN();
862}
863
864void op_msubu (void)
865{
866 uint64_t tmp;
867
868 tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
869 set_HILO(get_HILO() - tmp);
870 RETURN();
871}
872#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
873
60aa19ab 874#ifdef TARGET_MIPS64
c570fd16
TS
875void op_dmult (void)
876{
877 CALL_FROM_TB0(do_dmult);
878 RETURN();
879}
880
881void op_dmultu (void)
882{
883 CALL_FROM_TB0(do_dmultu);
884 RETURN();
885}
6af0bf9c
FB
886#endif
887
888/* Conditional moves */
889void op_movn (void)
890{
891 if (T1 != 0)
892 env->gpr[PARAM1] = T0;
893 RETURN();
894}
895
896void op_movz (void)
897{
898 if (T1 == 0)
899 env->gpr[PARAM1] = T0;
900 RETURN();
901}
902
7a387fff
TS
903void op_movf (void)
904{
905 if (!(env->fcr31 & PARAM1))
5a5012ec 906 T0 = T1;
7a387fff
TS
907 RETURN();
908}
909
910void op_movt (void)
911{
912 if (env->fcr31 & PARAM1)
5a5012ec 913 T0 = T1;
7a387fff
TS
914 RETURN();
915}
916
6af0bf9c
FB
917/* Tests */
918#define OP_COND(name, cond) \
919void glue(op_, name) (void) \
920{ \
921 if (cond) { \
922 T0 = 1; \
923 } else { \
924 T0 = 0; \
925 } \
926 RETURN(); \
927}
928
929OP_COND(eq, T0 == T1);
930OP_COND(ne, T0 != T1);
931OP_COND(ge, (int32_t)T0 >= (int32_t)T1);
932OP_COND(geu, T0 >= T1);
933OP_COND(lt, (int32_t)T0 < (int32_t)T1);
934OP_COND(ltu, T0 < T1);
935OP_COND(gez, (int32_t)T0 >= 0);
936OP_COND(gtz, (int32_t)T0 > 0);
937OP_COND(lez, (int32_t)T0 <= 0);
938OP_COND(ltz, (int32_t)T0 < 0);
939
7a387fff 940/* Branches */
c53be334
FB
941void OPPROTO op_goto_tb0(void)
942{
943 GOTO_TB(op_goto_tb0, PARAM1, 0);
7a387fff 944 RETURN();
c53be334
FB
945}
946
947void OPPROTO op_goto_tb1(void)
948{
949 GOTO_TB(op_goto_tb1, PARAM1, 1);
7a387fff 950 RETURN();
c53be334 951}
6af0bf9c
FB
952
953/* Branch to register */
954void op_save_breg_target (void)
955{
956 env->btarget = T2;
7a387fff 957 RETURN();
6af0bf9c
FB
958}
959
960void op_restore_breg_target (void)
961{
962 T2 = env->btarget;
7a387fff 963 RETURN();
6af0bf9c
FB
964}
965
966void op_breg (void)
967{
968 env->PC = T2;
969 RETURN();
970}
971
6af0bf9c
FB
972void op_save_btarget (void)
973{
974 env->btarget = PARAM1;
975 RETURN();
976}
977
978/* Conditional branch */
979void op_set_bcond (void)
980{
981 T2 = T0;
982 RETURN();
983}
984
985void op_save_bcond (void)
986{
987 env->bcond = T2;
988 RETURN();
989}
990
991void op_restore_bcond (void)
992{
993 T2 = env->bcond;
994 RETURN();
995}
996
c53be334 997void op_jnz_T2 (void)
6af0bf9c 998{
c53be334
FB
999 if (T2)
1000 GOTO_LABEL_PARAM(1);
6af0bf9c
FB
1001 RETURN();
1002}
1003
1004/* CP0 functions */
873eb012 1005void op_mfc0_index (void)
6af0bf9c 1006{
9c2149c8 1007 T0 = env->CP0_Index;
873eb012
TS
1008 RETURN();
1009}
1010
1011void op_mfc0_random (void)
1012{
1013 CALL_FROM_TB0(do_mfc0_random);
1014 RETURN();
1015}
1016
1017void op_mfc0_entrylo0 (void)
1018{
9c2149c8 1019 T0 = (int32_t)env->CP0_EntryLo0;
873eb012
TS
1020 RETURN();
1021}
1022
1023void op_mfc0_entrylo1 (void)
1024{
9c2149c8 1025 T0 = (int32_t)env->CP0_EntryLo1;
873eb012
TS
1026 RETURN();
1027}
1028
1029void op_mfc0_context (void)
1030{
9c2149c8 1031 T0 = (int32_t)env->CP0_Context;
873eb012
TS
1032 RETURN();
1033}
1034
1035void op_mfc0_pagemask (void)
1036{
9c2149c8 1037 T0 = env->CP0_PageMask;
873eb012
TS
1038 RETURN();
1039}
1040
7a387fff
TS
1041void op_mfc0_pagegrain (void)
1042{
9c2149c8 1043 T0 = env->CP0_PageGrain;
7a387fff
TS
1044 RETURN();
1045}
1046
873eb012
TS
1047void op_mfc0_wired (void)
1048{
9c2149c8 1049 T0 = env->CP0_Wired;
873eb012
TS
1050 RETURN();
1051}
1052
7a387fff
TS
1053void op_mfc0_hwrena (void)
1054{
9c2149c8 1055 T0 = env->CP0_HWREna;
7a387fff
TS
1056 RETURN();
1057}
1058
873eb012
TS
1059void op_mfc0_badvaddr (void)
1060{
9c2149c8 1061 T0 = (int32_t)env->CP0_BadVAddr;
873eb012
TS
1062 RETURN();
1063}
1064
1065void op_mfc0_count (void)
1066{
1067 CALL_FROM_TB0(do_mfc0_count);
1068 RETURN();
1069}
1070
1071void op_mfc0_entryhi (void)
1072{
9c2149c8 1073 T0 = (int32_t)env->CP0_EntryHi;
873eb012
TS
1074 RETURN();
1075}
1076
1077void op_mfc0_compare (void)
1078{
9c2149c8 1079 T0 = env->CP0_Compare;
873eb012
TS
1080 RETURN();
1081}
1082
1083void op_mfc0_status (void)
1084{
9c2149c8 1085 T0 = env->CP0_Status;
873eb012
TS
1086 RETURN();
1087}
1088
7a387fff
TS
1089void op_mfc0_intctl (void)
1090{
9c2149c8 1091 T0 = env->CP0_IntCtl;
7a387fff
TS
1092 RETURN();
1093}
1094
1095void op_mfc0_srsctl (void)
1096{
9c2149c8
TS
1097 T0 = env->CP0_SRSCtl;
1098 RETURN();
1099}
1100
1101void op_mfc0_srsmap (void)
1102{
1103 T0 = env->CP0_SRSMap;
7a387fff
TS
1104 RETURN();
1105}
1106
873eb012
TS
1107void op_mfc0_cause (void)
1108{
9c2149c8 1109 T0 = env->CP0_Cause;
873eb012
TS
1110 RETURN();
1111}
1112
1113void op_mfc0_epc (void)
1114{
9c2149c8 1115 T0 = (int32_t)env->CP0_EPC;
873eb012
TS
1116 RETURN();
1117}
1118
1119void op_mfc0_prid (void)
1120{
9c2149c8 1121 T0 = env->CP0_PRid;
873eb012
TS
1122 RETURN();
1123}
1124
7a387fff
TS
1125void op_mfc0_ebase (void)
1126{
b29a0341 1127 T0 = env->CP0_EBase;
7a387fff
TS
1128 RETURN();
1129}
1130
873eb012
TS
1131void op_mfc0_config0 (void)
1132{
9c2149c8 1133 T0 = env->CP0_Config0;
873eb012
TS
1134 RETURN();
1135}
1136
1137void op_mfc0_config1 (void)
1138{
9c2149c8 1139 T0 = env->CP0_Config1;
873eb012
TS
1140 RETURN();
1141}
1142
7a387fff
TS
1143void op_mfc0_config2 (void)
1144{
9c2149c8 1145 T0 = env->CP0_Config2;
7a387fff
TS
1146 RETURN();
1147}
1148
1149void op_mfc0_config3 (void)
1150{
9c2149c8 1151 T0 = env->CP0_Config3;
7a387fff
TS
1152 RETURN();
1153}
1154
e397ee33
TS
1155void op_mfc0_config6 (void)
1156{
1157 T0 = env->CP0_Config6;
1158 RETURN();
1159}
1160
1161void op_mfc0_config7 (void)
1162{
1163 T0 = env->CP0_Config7;
1164 RETURN();
1165}
1166
873eb012
TS
1167void op_mfc0_lladdr (void)
1168{
9c2149c8 1169 T0 = (int32_t)env->CP0_LLAddr >> 4;
873eb012
TS
1170 RETURN();
1171}
1172
7a387fff 1173void op_mfc0_watchlo0 (void)
873eb012 1174{
5dc4b744 1175 T0 = (int32_t)env->CP0_WatchLo;
873eb012
TS
1176 RETURN();
1177}
1178
7a387fff 1179void op_mfc0_watchhi0 (void)
873eb012 1180{
9c2149c8 1181 T0 = env->CP0_WatchHi;
873eb012
TS
1182 RETURN();
1183}
1184
7a387fff
TS
1185void op_mfc0_xcontext (void)
1186{
9c2149c8 1187 T0 = (int32_t)env->CP0_XContext;
7a387fff
TS
1188 RETURN();
1189}
1190
1191void op_mfc0_framemask (void)
1192{
1193 T0 = env->CP0_Framemask;
1194 RETURN();
1195}
1196
873eb012
TS
1197void op_mfc0_debug (void)
1198{
9c2149c8 1199 T0 = env->CP0_Debug;
873eb012
TS
1200 if (env->hflags & MIPS_HFLAG_DM)
1201 T0 |= 1 << CP0DB_DM;
1202 RETURN();
1203}
1204
1205void op_mfc0_depc (void)
1206{
9c2149c8 1207 T0 = (int32_t)env->CP0_DEPC;
873eb012
TS
1208 RETURN();
1209}
1210
7a387fff
TS
1211void op_mfc0_performance0 (void)
1212{
9c2149c8 1213 T0 = env->CP0_Performance0;
7a387fff
TS
1214 RETURN();
1215}
1216
873eb012
TS
1217void op_mfc0_taglo (void)
1218{
9c2149c8 1219 T0 = env->CP0_TagLo;
873eb012
TS
1220 RETURN();
1221}
1222
1223void op_mfc0_datalo (void)
1224{
9c2149c8 1225 T0 = env->CP0_DataLo;
873eb012
TS
1226 RETURN();
1227}
1228
7a387fff
TS
1229void op_mfc0_taghi (void)
1230{
9c2149c8 1231 T0 = env->CP0_TagHi;
7a387fff
TS
1232 RETURN();
1233}
1234
1235void op_mfc0_datahi (void)
1236{
9c2149c8 1237 T0 = env->CP0_DataHi;
7a387fff
TS
1238 RETURN();
1239}
1240
873eb012
TS
1241void op_mfc0_errorepc (void)
1242{
9c2149c8 1243 T0 = (int32_t)env->CP0_ErrorEPC;
873eb012
TS
1244 RETURN();
1245}
1246
1247void op_mfc0_desave (void)
1248{
9c2149c8 1249 T0 = env->CP0_DESAVE;
6af0bf9c
FB
1250 RETURN();
1251}
1252
8c0fdd85 1253void op_mtc0_index (void)
6af0bf9c 1254{
fcb4a419 1255 env->CP0_Index = (env->CP0_Index & 0x80000000) | (T0 % env->nb_tlb);
8c0fdd85
TS
1256 RETURN();
1257}
1258
1259void op_mtc0_entrylo0 (void)
1260{
7a387fff
TS
1261 /* Large physaddr not implemented */
1262 /* 1k pages not implemented */
f1b0aa5d 1263 env->CP0_EntryLo0 = T0 & 0x3FFFFFFF;
8c0fdd85
TS
1264 RETURN();
1265}
1266
1267void op_mtc0_entrylo1 (void)
1268{
7a387fff
TS
1269 /* Large physaddr not implemented */
1270 /* 1k pages not implemented */
f1b0aa5d 1271 env->CP0_EntryLo1 = T0 & 0x3FFFFFFF;
8c0fdd85
TS
1272 RETURN();
1273}
1274
1275void op_mtc0_context (void)
1276{
534ce69f 1277 env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (T0 & ~0x007FFFFF);
8c0fdd85
TS
1278 RETURN();
1279}
1280
1281void op_mtc0_pagemask (void)
1282{
7a387fff 1283 /* 1k pages not implemented */
f2e9ebef 1284 env->CP0_PageMask = T0 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
7a387fff
TS
1285 RETURN();
1286}
1287
1288void op_mtc0_pagegrain (void)
1289{
1290 /* SmartMIPS not implemented */
1291 /* Large physaddr not implemented */
1292 /* 1k pages not implemented */
1293 env->CP0_PageGrain = 0;
8c0fdd85
TS
1294 RETURN();
1295}
1296
1297void op_mtc0_wired (void)
1298{
fcb4a419 1299 env->CP0_Wired = T0 % env->nb_tlb;
7a387fff
TS
1300 RETURN();
1301}
1302
1303void op_mtc0_hwrena (void)
1304{
1305 env->CP0_HWREna = T0 & 0x0000000F;
8c0fdd85
TS
1306 RETURN();
1307}
1308
1309void op_mtc0_count (void)
1310{
1311 CALL_FROM_TB2(cpu_mips_store_count, env, T0);
1312 RETURN();
1313}
1314
1315void op_mtc0_entryhi (void)
1316{
0feef828 1317 target_ulong old, val;
8c0fdd85 1318
7a387fff
TS
1319 /* 1k pages not implemented */
1320 /* Ignore MIPS64 TLB for now */
925fd0f2 1321 val = (target_ulong)(int32_t)T0 & ~(target_ulong)0x1F00;
8c0fdd85
TS
1322 old = env->CP0_EntryHi;
1323 env->CP0_EntryHi = val;
1324 /* If the ASID changes, flush qemu's TLB. */
1325 if ((old & 0xFF) != (val & 0xFF))
1326 CALL_FROM_TB2(cpu_mips_tlb_flush, env, 1);
1327 RETURN();
1328}
1329
1330void op_mtc0_compare (void)
1331{
1332 CALL_FROM_TB2(cpu_mips_store_compare, env, T0);
1333 RETURN();
1334}
1335
1336void op_mtc0_status (void)
1337{
4de9b249 1338 uint32_t val, old;
5a5012ec 1339 uint32_t mask = env->Status_rw_bitmask;
8c0fdd85 1340
f1b0aa5d
TS
1341 /* No reverse endianness, no MDMX/DSP, no 64bit ops
1342 implemented. */
1343 val = T0 & mask;
8c0fdd85 1344 old = env->CP0_Status;
f41c52f1
TS
1345 if (!(val & (1 << CP0St_EXL)) &&
1346 !(val & (1 << CP0St_ERL)) &&
1347 !(env->hflags & MIPS_HFLAG_DM) &&
1348 (val & (1 << CP0St_UM)))
1349 env->hflags |= MIPS_HFLAG_UM;
5a5012ec 1350 env->CP0_Status = (env->CP0_Status & ~mask) | val;
f41c52f1
TS
1351 if (loglevel & CPU_LOG_EXEC)
1352 CALL_FROM_TB2(do_mtc0_status_debug, old, val);
4de9b249 1353 CALL_FROM_TB1(cpu_mips_update_irq, env);
8c0fdd85
TS
1354 RETURN();
1355}
1356
7a387fff
TS
1357void op_mtc0_intctl (void)
1358{
c090a8f4
TS
1359 /* vectored interrupts not implemented, timer on int 7,
1360 no performance counters. */
1361 env->CP0_IntCtl |= T0 & 0x000002e0;
7a387fff
TS
1362 RETURN();
1363}
1364
1365void op_mtc0_srsctl (void)
1366{
1367 /* shadow registers not implemented */
1368 env->CP0_SRSCtl = 0;
1369 RETURN();
1370}
1371
9c2149c8
TS
1372void op_mtc0_srsmap (void)
1373{
1374 /* shadow registers not implemented */
1375 env->CP0_SRSMap = 0;
1376 RETURN();
1377}
1378
8c0fdd85
TS
1379void op_mtc0_cause (void)
1380{
39d51eb8
TS
1381 uint32_t mask = 0x00C00300;
1382
1383 if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) == (1 << CP0C0_AR))
1384 mask |= 1 << CP0Ca_DC;
1385
e58c8ba5 1386 env->CP0_Cause = (env->CP0_Cause & ~mask) | (T0 & mask);
8c0fdd85 1387
4de9b249
TS
1388 /* Handle the software interrupt as an hardware one, as they
1389 are very similar */
1390 if (T0 & CP0Ca_IP_mask) {
1391 CALL_FROM_TB1(cpu_mips_update_irq, env);
8c0fdd85 1392 }
8c0fdd85
TS
1393 RETURN();
1394}
1395
1396void op_mtc0_epc (void)
1397{
f1b0aa5d 1398 env->CP0_EPC = T0;
8c0fdd85
TS
1399 RETURN();
1400}
1401
7a387fff
TS
1402void op_mtc0_ebase (void)
1403{
1404 /* vectored interrupts not implemented */
1405 /* Multi-CPU not implemented */
b29a0341 1406 env->CP0_EBase = 0x80000000 | (T0 & 0x3FFFF000);
7a387fff
TS
1407 RETURN();
1408}
1409
8c0fdd85
TS
1410void op_mtc0_config0 (void)
1411{
29929e34 1412 env->CP0_Config0 = (env->CP0_Config0 & 0x81FFFFF8) | (T0 & 0x00000001);
8c0fdd85
TS
1413 RETURN();
1414}
1415
7a387fff
TS
1416void op_mtc0_config2 (void)
1417{
1418 /* tertiary/secondary caches not implemented */
1419 env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF);
1420 RETURN();
1421}
1422
1423void op_mtc0_watchlo0 (void)
8c0fdd85 1424{
4e7a4a4e
TS
1425 /* Watch exceptions for instructions, data loads, data stores
1426 not implemented. */
f1b0aa5d 1427 env->CP0_WatchLo = (T0 & ~0x7);
8c0fdd85
TS
1428 RETURN();
1429}
1430
7a387fff 1431void op_mtc0_watchhi0 (void)
8c0fdd85 1432{
4e7a4a4e
TS
1433 env->CP0_WatchHi = (T0 & 0x40FF0FF8);
1434 env->CP0_WatchHi &= ~(env->CP0_WatchHi & T0 & 0x7);
8c0fdd85
TS
1435 RETURN();
1436}
1437
7a387fff
TS
1438void op_mtc0_framemask (void)
1439{
1440 env->CP0_Framemask = T0; /* XXX */
1441 RETURN();
1442}
1443
8c0fdd85
TS
1444void op_mtc0_debug (void)
1445{
1446 env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120);
1447 if (T0 & (1 << CP0DB_DM))
1448 env->hflags |= MIPS_HFLAG_DM;
1449 else
1450 env->hflags &= ~MIPS_HFLAG_DM;
1451 RETURN();
1452}
1453
1454void op_mtc0_depc (void)
1455{
f1b0aa5d 1456 env->CP0_DEPC = T0;
8c0fdd85
TS
1457 RETURN();
1458}
1459
7a387fff
TS
1460void op_mtc0_performance0 (void)
1461{
1462 env->CP0_Performance0 = T0; /* XXX */
1463 RETURN();
1464}
1465
8c0fdd85
TS
1466void op_mtc0_taglo (void)
1467{
9c2149c8 1468 env->CP0_TagLo = T0 & 0xFFFFFCF6;
8c0fdd85
TS
1469 RETURN();
1470}
1471
7a387fff
TS
1472void op_mtc0_datalo (void)
1473{
1474 env->CP0_DataLo = T0; /* XXX */
1475 RETURN();
1476}
1477
1478void op_mtc0_taghi (void)
1479{
1480 env->CP0_TagHi = T0; /* XXX */
1481 RETURN();
1482}
1483
1484void op_mtc0_datahi (void)
1485{
1486 env->CP0_DataHi = T0; /* XXX */
1487 RETURN();
1488}
1489
8c0fdd85
TS
1490void op_mtc0_errorepc (void)
1491{
f1b0aa5d 1492 env->CP0_ErrorEPC = T0;
8c0fdd85
TS
1493 RETURN();
1494}
1495
1496void op_mtc0_desave (void)
1497{
1498 env->CP0_DESAVE = T0;
6af0bf9c
FB
1499 RETURN();
1500}
1501
534ce69f 1502#ifdef TARGET_MIPS64
f1b0aa5d
TS
1503void op_mtc0_xcontext (void)
1504{
1505 env->CP0_XContext = (env->CP0_XContext & 0x1ffffffffULL) | (T0 & ~0x1ffffffffULL);
1506 RETURN();
1507}
1508
9c2149c8
TS
1509void op_dmfc0_entrylo0 (void)
1510{
1511 T0 = env->CP0_EntryLo0;
1512 RETURN();
1513}
1514
1515void op_dmfc0_entrylo1 (void)
1516{
1517 T0 = env->CP0_EntryLo1;
1518 RETURN();
1519}
1520
1521void op_dmfc0_context (void)
1522{
1523 T0 = env->CP0_Context;
1524 RETURN();
1525}
1526
1527void op_dmfc0_badvaddr (void)
1528{
1529 T0 = env->CP0_BadVAddr;
1530 RETURN();
1531}
1532
1533void op_dmfc0_entryhi (void)
1534{
1535 T0 = env->CP0_EntryHi;
1536 RETURN();
1537}
1538
1539void op_dmfc0_epc (void)
1540{
1541 T0 = env->CP0_EPC;
1542 RETURN();
1543}
1544
9c2149c8
TS
1545void op_dmfc0_lladdr (void)
1546{
1547 T0 = env->CP0_LLAddr >> 4;
1548 RETURN();
1549}
1550
1551void op_dmfc0_watchlo0 (void)
1552{
1553 T0 = env->CP0_WatchLo;
1554 RETURN();
1555}
1556
1557void op_dmfc0_xcontext (void)
1558{
1559 T0 = env->CP0_XContext;
1560 RETURN();
1561}
1562
1563void op_dmfc0_depc (void)
1564{
1565 T0 = env->CP0_DEPC;
1566 RETURN();
1567}
1568
1569void op_dmfc0_errorepc (void)
1570{
1571 T0 = env->CP0_ErrorEPC;
1572 RETURN();
1573}
534ce69f 1574#endif /* TARGET_MIPS64 */
9c2149c8 1575
5a5012ec 1576/* CP1 functions */
6ea83fed
FB
1577#if 0
1578# define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env)
1579#else
1580# define DEBUG_FPU_STATE() do { } while(0)
1581#endif
1582
24c7b0e3
TS
1583void op_cp0_enabled(void)
1584{
1585 if (!(env->CP0_Status & (1 << CP0St_CU0)) &&
1586 (env->hflags & MIPS_HFLAG_UM)) {
1579a72e 1587 CALL_FROM_TB2(do_raise_exception_err, EXCP_CpU, 0);
24c7b0e3
TS
1588 }
1589 RETURN();
1590}
1591
6ea83fed
FB
1592void op_cp1_enabled(void)
1593{
1594 if (!(env->CP0_Status & (1 << CP0St_CU1))) {
1579a72e 1595 CALL_FROM_TB2(do_raise_exception_err, EXCP_CpU, 1);
6ea83fed
FB
1596 }
1597 RETURN();
1598}
1599
6ea83fed
FB
1600/* convert MIPS rounding mode in FCR31 to IEEE library */
1601unsigned int ieee_rm[] = {
1602 float_round_nearest_even,
1603 float_round_to_zero,
1604 float_round_up,
1605 float_round_down
1606};
1607
1608#define RESTORE_ROUNDING_MODE \
1609 set_float_rounding_mode(ieee_rm[env->fcr31 & 3], &env->fp_status)
1610
09c69c5b 1611inline char ieee_ex_to_mips(char xcpt)
6ea83fed 1612{
09c69c5b
TS
1613 return (xcpt & float_flag_inexact) >> 5 |
1614 (xcpt & float_flag_underflow) >> 3 |
1615 (xcpt & float_flag_overflow) >> 1 |
1616 (xcpt & float_flag_divbyzero) << 1 |
1617 (xcpt & float_flag_invalid) << 4;
5a5012ec 1618}
6ea83fed 1619
09c69c5b 1620inline char mips_ex_to_ieee(char xcpt)
5a5012ec 1621{
09c69c5b
TS
1622 return (xcpt & FP_INEXACT) << 5 |
1623 (xcpt & FP_UNDERFLOW) << 3 |
1624 (xcpt & FP_OVERFLOW) << 1 |
1625 (xcpt & FP_DIV0) >> 1 |
1626 (xcpt & FP_INVALID) >> 4;
5a5012ec 1627}
6ea83fed 1628
5a5012ec
TS
1629inline void update_fcr31(void)
1630{
1631 int tmp = ieee_ex_to_mips(get_float_exception_flags(&env->fp_status));
1632
1633 SET_FP_CAUSE(env->fcr31, tmp);
1634 if (GET_FP_ENABLE(env->fcr31) & tmp)
1635 CALL_FROM_TB1(do_raise_exception, EXCP_FPE);
1636 else
1637 UPDATE_FP_FLAGS(env->fcr31, tmp);
1638}
1639
1640
1641void op_cfc1 (void)
1642{
1643 switch (T1) {
1644 case 0:
1645 T0 = (int32_t)env->fcr0;
1646 break;
1647 case 25:
1648 T0 = ((env->fcr31 >> 24) & 0xfe) | ((env->fcr31 >> 23) & 0x1);
1649 break;
1650 case 26:
1651 T0 = env->fcr31 & 0x0003f07c;
1652 break;
1653 case 28:
1654 T0 = (env->fcr31 & 0x00000f83) | ((env->fcr31 >> 22) & 0x4);
1655 break;
1656 default:
1657 T0 = (int32_t)env->fcr31;
1658 break;
1659 }
1660 DEBUG_FPU_STATE();
1661 RETURN();
1662}
1663
1664void op_ctc1 (void)
1665{
1666 switch(T1) {
1667 case 25:
1668 if (T0 & 0xffffff00)
1669 goto leave;
1670 env->fcr31 = (env->fcr31 & 0x017fffff) | ((T0 & 0xfe) << 24) |
1671 ((T0 & 0x1) << 23);
1672 break;
1673 case 26:
1674 if (T0 & 0x007c0000)
1675 goto leave;
1676 env->fcr31 = (env->fcr31 & 0xfffc0f83) | (T0 & 0x0003f07c);
1677 break;
1678 case 28:
1679 if (T0 & 0x007c0000)
1680 goto leave;
1681 env->fcr31 = (env->fcr31 & 0xfefff07c) | (T0 & 0x00000f83) |
1682 ((T0 & 0x4) << 22);
1683 break;
1684 case 31:
1685 if (T0 & 0x007c0000)
1686 goto leave;
1687 env->fcr31 = T0;
1688 break;
1689 default:
1690 goto leave;
6ea83fed 1691 }
5a5012ec
TS
1692 /* set rounding mode */
1693 RESTORE_ROUNDING_MODE;
1694 set_float_exception_flags(0, &env->fp_status);
1695 if ((GET_FP_ENABLE(env->fcr31) | 0x20) & GET_FP_CAUSE(env->fcr31))
1696 CALL_FROM_TB1(do_raise_exception, EXCP_FPE);
1697 leave:
6ea83fed
FB
1698 DEBUG_FPU_STATE();
1699 RETURN();
1700}
1701
1702void op_mfc1 (void)
1703{
1704 T0 = WT0;
1705 DEBUG_FPU_STATE();
1706 RETURN();
1707}
1708
1709void op_mtc1 (void)
1710{
1711 WT0 = T0;
1712 DEBUG_FPU_STATE();
1713 RETURN();
1714}
1715
5a5012ec
TS
1716void op_dmfc1 (void)
1717{
1718 T0 = DT0;
1719 DEBUG_FPU_STATE();
1720 RETURN();
1721}
1722
1723void op_dmtc1 (void)
1724{
1725 DT0 = T0;
1726 DEBUG_FPU_STATE();
1727 RETURN();
1728}
1729
1730void op_mfhc1 (void)
1731{
1732 T0 = WTH0;
1733 DEBUG_FPU_STATE();
1734 RETURN();
1735}
1736
1737void op_mthc1 (void)
1738{
1739 WTH0 = T0;
1740 DEBUG_FPU_STATE();
1741 RETURN();
1742}
1743
6ea83fed
FB
1744/* Float support.
1745 Single precition routines have a "s" suffix, double precision a
5a5012ec
TS
1746 "d" suffix, 32bit integer "w", 64bit integer "l", paired singe "ps",
1747 paired single lowwer "pl", paired single upper "pu". */
6ea83fed
FB
1748
1749#define FLOAT_OP(name, p) void OPPROTO op_float_##name##_##p(void)
1750
dd016883
FB
1751FLOAT_OP(cvtd, s)
1752{
5a5012ec 1753 set_float_exception_flags(0, &env->fp_status);
00a709c7 1754 FDT2 = float32_to_float64(FST0, &env->fp_status);
5a5012ec 1755 update_fcr31();
dd016883
FB
1756 DEBUG_FPU_STATE();
1757 RETURN();
1758}
6ea83fed
FB
1759FLOAT_OP(cvtd, w)
1760{
5a5012ec 1761 set_float_exception_flags(0, &env->fp_status);
6ea83fed 1762 FDT2 = int32_to_float64(WT0, &env->fp_status);
5a5012ec
TS
1763 update_fcr31();
1764 DEBUG_FPU_STATE();
1765 RETURN();
1766}
1767FLOAT_OP(cvtd, l)
1768{
1769 set_float_exception_flags(0, &env->fp_status);
1770 FDT2 = int64_to_float64(DT0, &env->fp_status);
1771 update_fcr31();
1772 DEBUG_FPU_STATE();
1773 RETURN();
1774}
1775FLOAT_OP(cvtl, d)
1776{
1777 set_float_exception_flags(0, &env->fp_status);
1778 DT2 = float64_to_int64(FDT0, &env->fp_status);
1779 update_fcr31();
1780 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
1781 DT2 = 0x7fffffffffffffffULL;
1782 DEBUG_FPU_STATE();
1783 RETURN();
1784}
1785FLOAT_OP(cvtl, s)
1786{
1787 set_float_exception_flags(0, &env->fp_status);
1788 DT2 = float32_to_int64(FST0, &env->fp_status);
1789 update_fcr31();
1790 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
1791 DT2 = 0x7fffffffffffffffULL;
1792 DEBUG_FPU_STATE();
1793 RETURN();
1794}
1795FLOAT_OP(cvtps, s)
1796{
1797 WT2 = WT0;
1798 WTH2 = WT1;
1799 DEBUG_FPU_STATE();
1800 RETURN();
1801}
1802FLOAT_OP(cvtps, pw)
1803{
1804 set_float_exception_flags(0, &env->fp_status);
1805 FST2 = int32_to_float32(WT0, &env->fp_status);
1806 FSTH2 = int32_to_float32(WTH0, &env->fp_status);
1807 update_fcr31();
1808 DEBUG_FPU_STATE();
1809 RETURN();
1810}
1811FLOAT_OP(cvtpw, ps)
1812{
1813 set_float_exception_flags(0, &env->fp_status);
1814 WT2 = float32_to_int32(FST0, &env->fp_status);
1815 WTH2 = float32_to_int32(FSTH0, &env->fp_status);
1816 update_fcr31();
1817 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
1818 WT2 = 0x7fffffff;
6ea83fed
FB
1819 DEBUG_FPU_STATE();
1820 RETURN();
1821}
dd016883
FB
1822FLOAT_OP(cvts, d)
1823{
5a5012ec 1824 set_float_exception_flags(0, &env->fp_status);
417f38f0 1825 FST2 = float64_to_float32(FDT0, &env->fp_status);
5a5012ec 1826 update_fcr31();
dd016883
FB
1827 DEBUG_FPU_STATE();
1828 RETURN();
1829}
6ea83fed
FB
1830FLOAT_OP(cvts, w)
1831{
5a5012ec 1832 set_float_exception_flags(0, &env->fp_status);
6ea83fed 1833 FST2 = int32_to_float32(WT0, &env->fp_status);
5a5012ec
TS
1834 update_fcr31();
1835 DEBUG_FPU_STATE();
1836 RETURN();
1837}
1838FLOAT_OP(cvts, l)
1839{
1840 set_float_exception_flags(0, &env->fp_status);
1841 FST2 = int64_to_float32(DT0, &env->fp_status);
1842 update_fcr31();
1843 DEBUG_FPU_STATE();
1844 RETURN();
1845}
1846FLOAT_OP(cvts, pl)
1847{
1848 set_float_exception_flags(0, &env->fp_status);
1849 WT2 = WT0;
1850 update_fcr31();
1851 DEBUG_FPU_STATE();
1852 RETURN();
1853}
1854FLOAT_OP(cvts, pu)
1855{
1856 set_float_exception_flags(0, &env->fp_status);
1857 WT2 = WTH0;
1858 update_fcr31();
6ea83fed
FB
1859 DEBUG_FPU_STATE();
1860 RETURN();
1861}
1862FLOAT_OP(cvtw, s)
1863{
5a5012ec 1864 set_float_exception_flags(0, &env->fp_status);
6ea83fed 1865 WT2 = float32_to_int32(FST0, &env->fp_status);
5a5012ec
TS
1866 update_fcr31();
1867 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
1868 WT2 = 0x7fffffff;
6ea83fed
FB
1869 DEBUG_FPU_STATE();
1870 RETURN();
1871}
1872FLOAT_OP(cvtw, d)
1873{
5a5012ec 1874 set_float_exception_flags(0, &env->fp_status);
6ea83fed 1875 WT2 = float64_to_int32(FDT0, &env->fp_status);
5a5012ec
TS
1876 update_fcr31();
1877 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
1878 WT2 = 0x7fffffff;
1879 DEBUG_FPU_STATE();
1880 RETURN();
1881}
1882
1883FLOAT_OP(pll, ps)
1884{
1885 DT2 = ((uint64_t)WT0 << 32) | WT1;
1886 DEBUG_FPU_STATE();
1887 RETURN();
1888}
1889FLOAT_OP(plu, ps)
1890{
1891 DT2 = ((uint64_t)WT0 << 32) | WTH1;
1892 DEBUG_FPU_STATE();
1893 RETURN();
1894}
1895FLOAT_OP(pul, ps)
1896{
1897 DT2 = ((uint64_t)WTH0 << 32) | WT1;
1898 DEBUG_FPU_STATE();
1899 RETURN();
1900}
1901FLOAT_OP(puu, ps)
1902{
1903 DT2 = ((uint64_t)WTH0 << 32) | WTH1;
6ea83fed
FB
1904 DEBUG_FPU_STATE();
1905 RETURN();
1906}
1907
5a5012ec
TS
1908FLOAT_OP(roundl, d)
1909{
1910 set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
1911 DT2 = float64_round_to_int(FDT0, &env->fp_status);
1912 RESTORE_ROUNDING_MODE;
5a1e8ffb
TS
1913 update_fcr31();
1914 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
1915 DT2 = 0x7fffffffffffffffULL;
5a5012ec
TS
1916 DEBUG_FPU_STATE();
1917 RETURN();
1918}
1919FLOAT_OP(roundl, s)
1920{
1921 set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
1922 DT2 = float32_round_to_int(FST0, &env->fp_status);
1923 RESTORE_ROUNDING_MODE;
5a1e8ffb
TS
1924 update_fcr31();
1925 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
1926 DT2 = 0x7fffffffffffffffULL;
5a5012ec
TS
1927 DEBUG_FPU_STATE();
1928 RETURN();
1929}
6ea83fed
FB
1930FLOAT_OP(roundw, d)
1931{
1932 set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
1933 WT2 = float64_round_to_int(FDT0, &env->fp_status);
1934 RESTORE_ROUNDING_MODE;
5a1e8ffb
TS
1935 update_fcr31();
1936 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
1937 WT2 = 0x7fffffff;
6ea83fed
FB
1938 DEBUG_FPU_STATE();
1939 RETURN();
1940}
1941FLOAT_OP(roundw, s)
1942{
1943 set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
1944 WT2 = float32_round_to_int(FST0, &env->fp_status);
1945 RESTORE_ROUNDING_MODE;
5a1e8ffb
TS
1946 update_fcr31();
1947 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
1948 WT2 = 0x7fffffff;
6ea83fed
FB
1949 DEBUG_FPU_STATE();
1950 RETURN();
1951}
1952
5a5012ec
TS
1953FLOAT_OP(truncl, d)
1954{
1955 DT2 = float64_to_int64_round_to_zero(FDT0, &env->fp_status);
5a1e8ffb
TS
1956 update_fcr31();
1957 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
1958 DT2 = 0x7fffffffffffffffULL;
5a5012ec
TS
1959 DEBUG_FPU_STATE();
1960 RETURN();
1961}
1962FLOAT_OP(truncl, s)
1963{
1964 DT2 = float32_to_int64_round_to_zero(FST0, &env->fp_status);
5a1e8ffb
TS
1965 update_fcr31();
1966 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
1967 DT2 = 0x7fffffffffffffffULL;
5a5012ec
TS
1968 DEBUG_FPU_STATE();
1969 RETURN();
1970}
6ea83fed
FB
1971FLOAT_OP(truncw, d)
1972{
1973 WT2 = float64_to_int32_round_to_zero(FDT0, &env->fp_status);
5a1e8ffb
TS
1974 update_fcr31();
1975 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
1976 WT2 = 0x7fffffff;
6ea83fed
FB
1977 DEBUG_FPU_STATE();
1978 RETURN();
1979}
1980FLOAT_OP(truncw, s)
1981{
1982 WT2 = float32_to_int32_round_to_zero(FST0, &env->fp_status);
5a1e8ffb
TS
1983 update_fcr31();
1984 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
1985 WT2 = 0x7fffffff;
6ea83fed
FB
1986 DEBUG_FPU_STATE();
1987 RETURN();
1988}
1989
5a5012ec
TS
1990FLOAT_OP(ceill, d)
1991{
1992 set_float_rounding_mode(float_round_up, &env->fp_status);
1993 DT2 = float64_round_to_int(FDT0, &env->fp_status);
1994 RESTORE_ROUNDING_MODE;
5a1e8ffb
TS
1995 update_fcr31();
1996 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
1997 DT2 = 0x7fffffffffffffffULL;
5a5012ec
TS
1998 DEBUG_FPU_STATE();
1999 RETURN();
2000}
2001FLOAT_OP(ceill, s)
2002{
2003 set_float_rounding_mode(float_round_up, &env->fp_status);
2004 DT2 = float32_round_to_int(FST0, &env->fp_status);
2005 RESTORE_ROUNDING_MODE;
5a1e8ffb
TS
2006 update_fcr31();
2007 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
2008 DT2 = 0x7fffffffffffffffULL;
5a5012ec
TS
2009 DEBUG_FPU_STATE();
2010 RETURN();
2011}
6ea83fed
FB
2012FLOAT_OP(ceilw, d)
2013{
2014 set_float_rounding_mode(float_round_up, &env->fp_status);
2015 WT2 = float64_round_to_int(FDT0, &env->fp_status);
2016 RESTORE_ROUNDING_MODE;
5a1e8ffb
TS
2017 update_fcr31();
2018 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
2019 WT2 = 0x7fffffff;
6ea83fed
FB
2020 DEBUG_FPU_STATE();
2021 RETURN();
2022}
2023FLOAT_OP(ceilw, s)
2024{
2025 set_float_rounding_mode(float_round_up, &env->fp_status);
2026 WT2 = float32_round_to_int(FST0, &env->fp_status);
2027 RESTORE_ROUNDING_MODE;
5a1e8ffb
TS
2028 update_fcr31();
2029 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
2030 WT2 = 0x7fffffff;
6ea83fed
FB
2031 DEBUG_FPU_STATE();
2032 RETURN();
2033}
2034
5a5012ec
TS
2035FLOAT_OP(floorl, d)
2036{
2037 set_float_rounding_mode(float_round_down, &env->fp_status);
2038 DT2 = float64_round_to_int(FDT0, &env->fp_status);
2039 RESTORE_ROUNDING_MODE;
5a1e8ffb
TS
2040 update_fcr31();
2041 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
2042 DT2 = 0x7fffffffffffffffULL;
5a5012ec
TS
2043 DEBUG_FPU_STATE();
2044 RETURN();
2045}
2046FLOAT_OP(floorl, s)
2047{
2048 set_float_rounding_mode(float_round_down, &env->fp_status);
2049 DT2 = float32_round_to_int(FST0, &env->fp_status);
2050 RESTORE_ROUNDING_MODE;
5a1e8ffb
TS
2051 update_fcr31();
2052 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
2053 DT2 = 0x7fffffffffffffffULL;
5a5012ec
TS
2054 DEBUG_FPU_STATE();
2055 RETURN();
2056}
6ea83fed
FB
2057FLOAT_OP(floorw, d)
2058{
2059 set_float_rounding_mode(float_round_down, &env->fp_status);
2060 WT2 = float64_round_to_int(FDT0, &env->fp_status);
2061 RESTORE_ROUNDING_MODE;
5a1e8ffb
TS
2062 update_fcr31();
2063 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
2064 WT2 = 0x7fffffff;
6ea83fed
FB
2065 DEBUG_FPU_STATE();
2066 RETURN();
2067}
2068FLOAT_OP(floorw, s)
2069{
2070 set_float_rounding_mode(float_round_down, &env->fp_status);
2071 WT2 = float32_round_to_int(FST0, &env->fp_status);
2072 RESTORE_ROUNDING_MODE;
5a1e8ffb
TS
2073 update_fcr31();
2074 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
2075 WT2 = 0x7fffffff;
6ea83fed
FB
2076 DEBUG_FPU_STATE();
2077 RETURN();
2078}
2079
5a5012ec
TS
2080FLOAT_OP(movf, d)
2081{
2082 if (!(env->fcr31 & PARAM1))
2083 DT2 = DT0;
2084 DEBUG_FPU_STATE();
2085 RETURN();
2086}
2087FLOAT_OP(movf, s)
2088{
2089 if (!(env->fcr31 & PARAM1))
2090 WT2 = WT0;
2091 DEBUG_FPU_STATE();
2092 RETURN();
2093}
2094FLOAT_OP(movf, ps)
2095{
2096 if (!(env->fcr31 & PARAM1)) {
2097 WT2 = WT0;
2098 WTH2 = WTH0;
2099 }
2100 DEBUG_FPU_STATE();
2101 RETURN();
2102}
2103FLOAT_OP(movt, d)
2104{
2105 if (env->fcr31 & PARAM1)
2106 DT2 = DT0;
2107 DEBUG_FPU_STATE();
2108 RETURN();
2109}
2110FLOAT_OP(movt, s)
2111{
2112 if (env->fcr31 & PARAM1)
2113 WT2 = WT0;
2114 DEBUG_FPU_STATE();
2115 RETURN();
2116}
2117FLOAT_OP(movt, ps)
2118{
2119 if (env->fcr31 & PARAM1) {
2120 WT2 = WT0;
2121 WTH2 = WTH0;
2122 }
2123 DEBUG_FPU_STATE();
2124 RETURN();
2125}
2126FLOAT_OP(movz, d)
2127{
2128 if (!T0)
2129 DT2 = DT0;
2130 DEBUG_FPU_STATE();
2131 RETURN();
2132}
2133FLOAT_OP(movz, s)
2134{
2135 if (!T0)
2136 WT2 = WT0;
2137 DEBUG_FPU_STATE();
2138 RETURN();
2139}
2140FLOAT_OP(movz, ps)
2141{
2142 if (!T0) {
2143 WT2 = WT0;
2144 WTH2 = WTH0;
2145 }
2146 DEBUG_FPU_STATE();
2147 RETURN();
2148}
2149FLOAT_OP(movn, d)
2150{
2151 if (T0)
2152 DT2 = DT0;
2153 DEBUG_FPU_STATE();
2154 RETURN();
2155}
2156FLOAT_OP(movn, s)
2157{
2158 if (T0)
2159 WT2 = WT0;
2160 DEBUG_FPU_STATE();
2161 RETURN();
2162}
2163FLOAT_OP(movn, ps)
2164{
2165 if (T0) {
2166 WT2 = WT0;
2167 WTH2 = WTH0;
2168 }
2169 DEBUG_FPU_STATE();
2170 RETURN();
2171}
2172
6ea83fed
FB
2173/* binary operations */
2174#define FLOAT_BINOP(name) \
2175FLOAT_OP(name, d) \
2176{ \
5a5012ec 2177 set_float_exception_flags(0, &env->fp_status); \
6ea83fed 2178 FDT2 = float64_ ## name (FDT0, FDT1, &env->fp_status); \
5a5012ec 2179 update_fcr31(); \
6ea83fed 2180 DEBUG_FPU_STATE(); \
fbcc6828 2181 RETURN(); \
6ea83fed
FB
2182} \
2183FLOAT_OP(name, s) \
2184{ \
5a5012ec 2185 set_float_exception_flags(0, &env->fp_status); \
6ea83fed 2186 FST2 = float32_ ## name (FST0, FST1, &env->fp_status); \
5a5012ec
TS
2187 update_fcr31(); \
2188 DEBUG_FPU_STATE(); \
fbcc6828 2189 RETURN(); \
5a5012ec
TS
2190} \
2191FLOAT_OP(name, ps) \
2192{ \
2193 set_float_exception_flags(0, &env->fp_status); \
2194 FST2 = float32_ ## name (FST0, FST1, &env->fp_status); \
2195 FSTH2 = float32_ ## name (FSTH0, FSTH1, &env->fp_status); \
2196 update_fcr31(); \
6ea83fed 2197 DEBUG_FPU_STATE(); \
fbcc6828 2198 RETURN(); \
6ea83fed
FB
2199}
2200FLOAT_BINOP(add)
2201FLOAT_BINOP(sub)
2202FLOAT_BINOP(mul)
2203FLOAT_BINOP(div)
2204#undef FLOAT_BINOP
2205
fbcc6828
TS
2206FLOAT_OP(addr, ps)
2207{
2208 set_float_exception_flags(0, &env->fp_status);
2209 FST2 = float32_add (FST0, FSTH0, &env->fp_status);
2210 FSTH2 = float32_add (FST1, FSTH1, &env->fp_status);
2211 update_fcr31();
2212 DEBUG_FPU_STATE();
2213 RETURN();
2214}
2215
5a5012ec
TS
2216/* ternary operations */
2217#define FLOAT_TERNOP(name1, name2) \
2218FLOAT_OP(name1 ## name2, d) \
2219{ \
2220 FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fp_status); \
2221 FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fp_status); \
2222 DEBUG_FPU_STATE(); \
fbcc6828 2223 RETURN(); \
5a5012ec
TS
2224} \
2225FLOAT_OP(name1 ## name2, s) \
2226{ \
2227 FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status); \
2228 FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \
2229 DEBUG_FPU_STATE(); \
fbcc6828 2230 RETURN(); \
5a5012ec
TS
2231} \
2232FLOAT_OP(name1 ## name2, ps) \
2233{ \
2234 FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status); \
2235 FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fp_status); \
2236 FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \
2237 FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fp_status); \
2238 DEBUG_FPU_STATE(); \
fbcc6828 2239 RETURN(); \
5a5012ec
TS
2240}
2241FLOAT_TERNOP(mul, add)
2242FLOAT_TERNOP(mul, sub)
2243#undef FLOAT_TERNOP
2244
fbcc6828
TS
2245/* negated ternary operations */
2246#define FLOAT_NTERNOP(name1, name2) \
2247FLOAT_OP(n ## name1 ## name2, d) \
2248{ \
2249 FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fp_status); \
2250 FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fp_status); \
2251 FDT2 ^= 1ULL << 63; \
2252 DEBUG_FPU_STATE(); \
2253 RETURN(); \
2254} \
2255FLOAT_OP(n ## name1 ## name2, s) \
2256{ \
2257 FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status); \
2258 FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \
2259 FST2 ^= 1 << 31; \
2260 DEBUG_FPU_STATE(); \
2261 RETURN(); \
2262} \
2263FLOAT_OP(n ## name1 ## name2, ps) \
2264{ \
2265 FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status); \
2266 FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fp_status); \
2267 FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \
2268 FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fp_status); \
2269 FST2 ^= 1 << 31; \
2270 FSTH2 ^= 1 << 31; \
2271 DEBUG_FPU_STATE(); \
2272 RETURN(); \
2273}
2274FLOAT_NTERNOP(mul, add)
2275FLOAT_NTERNOP(mul, sub)
2276#undef FLOAT_NTERNOP
2277
6ea83fed
FB
2278/* unary operations, modifying fp status */
2279#define FLOAT_UNOP(name) \
2280FLOAT_OP(name, d) \
2281{ \
2282 FDT2 = float64_ ## name(FDT0, &env->fp_status); \
2283 DEBUG_FPU_STATE(); \
fbcc6828 2284 RETURN(); \
6ea83fed
FB
2285} \
2286FLOAT_OP(name, s) \
2287{ \
2288 FST2 = float32_ ## name(FST0, &env->fp_status); \
2289 DEBUG_FPU_STATE(); \
fbcc6828 2290 RETURN(); \
5a5012ec
TS
2291} \
2292FLOAT_OP(name, ps) \
2293{ \
2294 FST2 = float32_ ## name(FST0, &env->fp_status); \
2295 FSTH2 = float32_ ## name(FSTH0, &env->fp_status); \
2296 DEBUG_FPU_STATE(); \
fbcc6828 2297 RETURN(); \
6ea83fed
FB
2298}
2299FLOAT_UNOP(sqrt)
2300#undef FLOAT_UNOP
2301
2302/* unary operations, not modifying fp status */
2303#define FLOAT_UNOP(name) \
2304FLOAT_OP(name, d) \
2305{ \
2306 FDT2 = float64_ ## name(FDT0); \
2307 DEBUG_FPU_STATE(); \
fbcc6828 2308 RETURN(); \
6ea83fed
FB
2309} \
2310FLOAT_OP(name, s) \
2311{ \
2312 FST2 = float32_ ## name(FST0); \
2313 DEBUG_FPU_STATE(); \
fbcc6828 2314 RETURN(); \
5a5012ec
TS
2315} \
2316FLOAT_OP(name, ps) \
2317{ \
2318 FST2 = float32_ ## name(FST0); \
2319 FSTH2 = float32_ ## name(FSTH0); \
2320 DEBUG_FPU_STATE(); \
fbcc6828 2321 RETURN(); \
6ea83fed
FB
2322}
2323FLOAT_UNOP(abs)
2324FLOAT_UNOP(chs)
2325#undef FLOAT_UNOP
2326
2327FLOAT_OP(mov, d)
2328{
2329 FDT2 = FDT0;
2330 DEBUG_FPU_STATE();
2331 RETURN();
2332}
2333FLOAT_OP(mov, s)
2334{
2335 FST2 = FST0;
2336 DEBUG_FPU_STATE();
2337 RETURN();
2338}
5a5012ec
TS
2339FLOAT_OP(mov, ps)
2340{
2341 FST2 = FST0;
2342 FSTH2 = FSTH0;
2343 DEBUG_FPU_STATE();
2344 RETURN();
2345}
2346FLOAT_OP(alnv, ps)
2347{
2348 switch (T0 & 0x7) {
2349 case 0:
2350 FST2 = FST0;
2351 FSTH2 = FSTH0;
2352 break;
2353 case 4:
2354#ifdef TARGET_WORDS_BIGENDIAN
2355 FSTH2 = FST0;
2356 FST2 = FSTH1;
2357#else
2358 FSTH2 = FST1;
2359 FST2 = FSTH0;
2360#endif
2361 break;
2362 default: /* unpredictable */
2363 break;
2364 }
2365 DEBUG_FPU_STATE();
2366 RETURN();
2367}
6ea83fed
FB
2368
2369#ifdef CONFIG_SOFTFLOAT
2370#define clear_invalid() do { \
2371 int flags = get_float_exception_flags(&env->fp_status); \
2372 flags &= ~float_flag_invalid; \
2373 set_float_exception_flags(flags, &env->fp_status); \
2374} while(0)
2375#else
2376#define clear_invalid() do { } while(0)
2377#endif
2378
2379extern void dump_fpu_s(CPUState *env);
2380
5a5012ec
TS
2381#define FOP_COND_D(op, cond) \
2382void op_cmp_d_ ## op (void) \
6ea83fed 2383{ \
5a5012ec
TS
2384 int c = cond; \
2385 update_fcr31(); \
2386 if (c) \
2387 SET_FP_COND(PARAM1, env); \
6ea83fed 2388 else \
5a5012ec 2389 CLEAR_FP_COND(PARAM1, env); \
6ea83fed
FB
2390 DEBUG_FPU_STATE(); \
2391 RETURN(); \
5a1e8ffb
TS
2392} \
2393void op_cmpabs_d_ ## op (void) \
2394{ \
2395 int c; \
2396 FDT0 &= ~(1ULL << 63); \
2397 FDT1 &= ~(1ULL << 63); \
2398 c = cond; \
2399 update_fcr31(); \
2400 if (c) \
2401 SET_FP_COND(PARAM1, env); \
2402 else \
2403 CLEAR_FP_COND(PARAM1, env); \
2404 DEBUG_FPU_STATE(); \
2405 RETURN(); \
6ea83fed
FB
2406}
2407
5a5012ec 2408int float64_is_unordered(int sig, float64 a, float64 b STATUS_PARAM)
6ea83fed 2409{
5a5012ec
TS
2410 if (float64_is_signaling_nan(a) ||
2411 float64_is_signaling_nan(b) ||
2412 (sig && (float64_is_nan(a) || float64_is_nan(b)))) {
6ea83fed
FB
2413 float_raise(float_flag_invalid, status);
2414 return 1;
5a5012ec
TS
2415 } else if (float64_is_nan(a) || float64_is_nan(b)) {
2416 return 1;
2417 } else {
6ea83fed
FB
2418 return 0;
2419 }
2420}
2421
6ea83fed 2422/* NOTE: the comma operator will make "cond" to eval to false,
5a5012ec
TS
2423 * but float*_is_unordered() is still called. */
2424FOP_COND_D(f, (float64_is_unordered(0, FDT1, FDT0, &env->fp_status), 0))
2425FOP_COND_D(un, float64_is_unordered(0, FDT1, FDT0, &env->fp_status))
2426FOP_COND_D(eq, !float64_is_unordered(0, FDT1, FDT0, &env->fp_status) && float64_eq(FDT0, FDT1, &env->fp_status))
2427FOP_COND_D(ueq, float64_is_unordered(0, FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status))
2428FOP_COND_D(olt, !float64_is_unordered(0, FDT1, FDT0, &env->fp_status) && float64_lt(FDT0, FDT1, &env->fp_status))
2429FOP_COND_D(ult, float64_is_unordered(0, FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status))
2430FOP_COND_D(ole, !float64_is_unordered(0, FDT1, FDT0, &env->fp_status) && float64_le(FDT0, FDT1, &env->fp_status))
2431FOP_COND_D(ule, float64_is_unordered(0, FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status))
2432/* NOTE: the comma operator will make "cond" to eval to false,
2433 * but float*_is_unordered() is still called. */
2434FOP_COND_D(sf, (float64_is_unordered(1, FDT1, FDT0, &env->fp_status), 0))
2435FOP_COND_D(ngle,float64_is_unordered(1, FDT1, FDT0, &env->fp_status))
2436FOP_COND_D(seq, !float64_is_unordered(1, FDT1, FDT0, &env->fp_status) && float64_eq(FDT0, FDT1, &env->fp_status))
2437FOP_COND_D(ngl, float64_is_unordered(1, FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status))
2438FOP_COND_D(lt, !float64_is_unordered(1, FDT1, FDT0, &env->fp_status) && float64_lt(FDT0, FDT1, &env->fp_status))
2439FOP_COND_D(nge, float64_is_unordered(1, FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status))
2440FOP_COND_D(le, !float64_is_unordered(1, FDT1, FDT0, &env->fp_status) && float64_le(FDT0, FDT1, &env->fp_status))
2441FOP_COND_D(ngt, float64_is_unordered(1, FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status))
2442
2443#define FOP_COND_S(op, cond) \
2444void op_cmp_s_ ## op (void) \
2445{ \
2446 int c = cond; \
2447 update_fcr31(); \
2448 if (c) \
2449 SET_FP_COND(PARAM1, env); \
2450 else \
2451 CLEAR_FP_COND(PARAM1, env); \
2452 DEBUG_FPU_STATE(); \
2453 RETURN(); \
5a1e8ffb
TS
2454} \
2455void op_cmpabs_s_ ## op (void) \
2456{ \
2457 int c; \
2458 FST0 &= ~(1 << 31); \
2459 FST1 &= ~(1 << 31); \
2460 c = cond; \
2461 update_fcr31(); \
2462 if (c) \
2463 SET_FP_COND(PARAM1, env); \
2464 else \
2465 CLEAR_FP_COND(PARAM1, env); \
2466 DEBUG_FPU_STATE(); \
2467 RETURN(); \
5a5012ec
TS
2468}
2469
2470flag float32_is_unordered(int sig, float32 a, float32 b STATUS_PARAM)
2471{
2472 extern flag float32_is_nan(float32 a);
2473 if (float32_is_signaling_nan(a) ||
2474 float32_is_signaling_nan(b) ||
2475 (sig && (float32_is_nan(a) || float32_is_nan(b)))) {
6ea83fed
FB
2476 float_raise(float_flag_invalid, status);
2477 return 1;
5a5012ec
TS
2478 } else if (float32_is_nan(a) || float32_is_nan(b)) {
2479 return 1;
2480 } else {
6ea83fed
FB
2481 return 0;
2482 }
2483}
2484
2485/* NOTE: the comma operator will make "cond" to eval to false,
5a5012ec
TS
2486 * but float*_is_unordered() is still called. */
2487FOP_COND_S(f, (float32_is_unordered(0, FST1, FST0, &env->fp_status), 0))
2488FOP_COND_S(un, float32_is_unordered(0, FST1, FST0, &env->fp_status))
2489FOP_COND_S(eq, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_eq(FST0, FST1, &env->fp_status))
2490FOP_COND_S(ueq, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status))
2491FOP_COND_S(olt, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_lt(FST0, FST1, &env->fp_status))
2492FOP_COND_S(ult, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status))
2493FOP_COND_S(ole, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_le(FST0, FST1, &env->fp_status))
2494FOP_COND_S(ule, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status))
6ea83fed 2495/* NOTE: the comma operator will make "cond" to eval to false,
5a5012ec
TS
2496 * but float*_is_unordered() is still called. */
2497FOP_COND_S(sf, (float32_is_unordered(1, FST1, FST0, &env->fp_status), 0))
2498FOP_COND_S(ngle,float32_is_unordered(1, FST1, FST0, &env->fp_status))
2499FOP_COND_S(seq, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_eq(FST0, FST1, &env->fp_status))
2500FOP_COND_S(ngl, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status))
2501FOP_COND_S(lt, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_lt(FST0, FST1, &env->fp_status))
2502FOP_COND_S(nge, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status))
2503FOP_COND_S(le, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_le(FST0, FST1, &env->fp_status))
2504FOP_COND_S(ngt, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status))
2505
2506#define FOP_COND_PS(op, condl, condh) \
2507void op_cmp_ps_ ## op (void) \
2508{ \
2509 int cl = condl; \
2510 int ch = condh; \
2511 update_fcr31(); \
2512 if (cl) \
2513 SET_FP_COND(PARAM1, env); \
2514 else \
2515 CLEAR_FP_COND(PARAM1, env); \
2516 if (ch) \
2517 SET_FP_COND(PARAM1 + 1, env); \
2518 else \
2519 CLEAR_FP_COND(PARAM1 + 1, env); \
2520 DEBUG_FPU_STATE(); \
2521 RETURN(); \
5a1e8ffb
TS
2522} \
2523void op_cmpabs_ps_ ## op (void) \
2524{ \
2525 int cl, ch; \
2526 FST0 &= ~(1 << 31); \
2527 FSTH0 &= ~(1 << 31); \
2528 FST1 &= ~(1 << 31); \
2529 FSTH1 &= ~(1 << 31); \
2530 cl = condl; \
2531 ch = condh; \
2532 update_fcr31(); \
2533 if (cl) \
2534 SET_FP_COND(PARAM1, env); \
2535 else \
2536 CLEAR_FP_COND(PARAM1, env); \
2537 if (ch) \
2538 SET_FP_COND(PARAM1 + 1, env); \
2539 else \
2540 CLEAR_FP_COND(PARAM1 + 1, env); \
2541 DEBUG_FPU_STATE(); \
2542 RETURN(); \
5a5012ec
TS
2543}
2544
2545/* NOTE: the comma operator will make "cond" to eval to false,
2546 * but float*_is_unordered() is still called. */
2547FOP_COND_PS(f, (float32_is_unordered(0, FST1, FST0, &env->fp_status), 0),
2548 (float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status), 0))
2549FOP_COND_PS(un, float32_is_unordered(0, FST1, FST0, &env->fp_status),
2550 float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status))
2551FOP_COND_PS(eq, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_eq(FST0, FST1, &env->fp_status),
2552 !float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) && float32_eq(FSTH0, FSTH1, &env->fp_status))
2553FOP_COND_PS(ueq, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status),
2554 float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) || float32_eq(FSTH0, FSTH1, &env->fp_status))
2555FOP_COND_PS(olt, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_lt(FST0, FST1, &env->fp_status),
2556 !float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) && float32_lt(FSTH0, FSTH1, &env->fp_status))
2557FOP_COND_PS(ult, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status),
2558 float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) || float32_lt(FSTH0, FSTH1, &env->fp_status))
2559FOP_COND_PS(ole, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_le(FST0, FST1, &env->fp_status),
2560 !float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) && float32_le(FSTH0, FSTH1, &env->fp_status))
2561FOP_COND_PS(ule, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status),
2562 float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) || float32_le(FSTH0, FSTH1, &env->fp_status))
2563/* NOTE: the comma operator will make "cond" to eval to false,
2564 * but float*_is_unordered() is still called. */
2565FOP_COND_PS(sf, (float32_is_unordered(1, FST1, FST0, &env->fp_status), 0),
2566 (float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status), 0))
2567FOP_COND_PS(ngle,float32_is_unordered(1, FST1, FST0, &env->fp_status),
2568 float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status))
2569FOP_COND_PS(seq, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_eq(FST0, FST1, &env->fp_status),
2570 !float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) && float32_eq(FSTH0, FSTH1, &env->fp_status))
2571FOP_COND_PS(ngl, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status),
2572 float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) || float32_eq(FSTH0, FSTH1, &env->fp_status))
2573FOP_COND_PS(lt, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_lt(FST0, FST1, &env->fp_status),
2574 !float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) && float32_lt(FSTH0, FSTH1, &env->fp_status))
2575FOP_COND_PS(nge, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status),
2576 float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) || float32_lt(FSTH0, FSTH1, &env->fp_status))
2577FOP_COND_PS(le, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_le(FST0, FST1, &env->fp_status),
2578 !float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) && float32_le(FSTH0, FSTH1, &env->fp_status))
2579FOP_COND_PS(ngt, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status),
2580 float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) || float32_le(FSTH0, FSTH1, &env->fp_status))
6ea83fed
FB
2581
2582void op_bc1f (void)
2583{
5a5012ec
TS
2584 T0 = !IS_FP_COND_SET(PARAM1, env);
2585 DEBUG_FPU_STATE();
2586 RETURN();
2587}
2588void op_bc1fany2 (void)
2589{
2590 T0 = (!IS_FP_COND_SET(PARAM1, env) ||
2591 !IS_FP_COND_SET(PARAM1 + 1, env));
2592 DEBUG_FPU_STATE();
2593 RETURN();
2594}
2595void op_bc1fany4 (void)
2596{
2597 T0 = (!IS_FP_COND_SET(PARAM1, env) ||
2598 !IS_FP_COND_SET(PARAM1 + 1, env) ||
2599 !IS_FP_COND_SET(PARAM1 + 2, env) ||
2600 !IS_FP_COND_SET(PARAM1 + 3, env));
6ea83fed
FB
2601 DEBUG_FPU_STATE();
2602 RETURN();
2603}
2604
2605void op_bc1t (void)
2606{
5a5012ec
TS
2607 T0 = IS_FP_COND_SET(PARAM1, env);
2608 DEBUG_FPU_STATE();
2609 RETURN();
2610}
2611void op_bc1tany2 (void)
2612{
2613 T0 = (IS_FP_COND_SET(PARAM1, env) ||
2614 IS_FP_COND_SET(PARAM1 + 1, env));
2615 DEBUG_FPU_STATE();
2616 RETURN();
2617}
2618void op_bc1tany4 (void)
2619{
2620 T0 = (IS_FP_COND_SET(PARAM1, env) ||
2621 IS_FP_COND_SET(PARAM1 + 1, env) ||
2622 IS_FP_COND_SET(PARAM1 + 2, env) ||
2623 IS_FP_COND_SET(PARAM1 + 3, env));
6ea83fed
FB
2624 DEBUG_FPU_STATE();
2625 RETURN();
2626}
6ea83fed 2627
6af0bf9c
FB
2628void op_tlbwi (void)
2629{
29929e34 2630 CALL_FROM_TB0(env->do_tlbwi);
6af0bf9c
FB
2631 RETURN();
2632}
2633
2634void op_tlbwr (void)
2635{
29929e34 2636 CALL_FROM_TB0(env->do_tlbwr);
6af0bf9c
FB
2637 RETURN();
2638}
2639
2640void op_tlbp (void)
2641{
29929e34 2642 CALL_FROM_TB0(env->do_tlbp);
6af0bf9c
FB
2643 RETURN();
2644}
2645
2646void op_tlbr (void)
2647{
29929e34 2648 CALL_FROM_TB0(env->do_tlbr);
6af0bf9c
FB
2649 RETURN();
2650}
6af0bf9c
FB
2651
2652/* Specials */
6f5b89a0
TS
2653#if defined (CONFIG_USER_ONLY)
2654void op_tls_value (void)
2655{
5a5012ec 2656 T0 = env->tls_value;
6f5b89a0
TS
2657}
2658#endif
2659
6af0bf9c
FB
2660void op_pmon (void)
2661{
2662 CALL_FROM_TB1(do_pmon, PARAM1);
7a387fff
TS
2663 RETURN();
2664}
2665
2666void op_di (void)
2667{
7a387fff 2668 T0 = env->CP0_Status;
4de9b249
TS
2669 env->CP0_Status = T0 & ~(1 << CP0St_IE);
2670 CALL_FROM_TB1(cpu_mips_update_irq, env);
7a387fff
TS
2671 RETURN();
2672}
2673
2674void op_ei (void)
2675{
7a387fff 2676 T0 = env->CP0_Status;
4de9b249
TS
2677 env->CP0_Status = T0 | (1 << CP0St_IE);
2678 CALL_FROM_TB1(cpu_mips_update_irq, env);
7a387fff 2679 RETURN();
6af0bf9c
FB
2680}
2681
2682void op_trap (void)
2683{
2684 if (T0) {
1579a72e 2685 CALL_FROM_TB1(do_raise_exception, EXCP_TRAP);
6af0bf9c
FB
2686 }
2687 RETURN();
2688}
2689
4ad40f36
FB
2690void op_debug (void)
2691{
7a387fff
TS
2692 CALL_FROM_TB1(do_raise_exception, EXCP_DEBUG);
2693 RETURN();
4ad40f36
FB
2694}
2695
6af0bf9c
FB
2696void op_set_lladdr (void)
2697{
2698 env->CP0_LLAddr = T2;
7a387fff 2699 RETURN();
6af0bf9c
FB
2700}
2701
f41c52f1
TS
2702void debug_pre_eret (void);
2703void debug_post_eret (void);
6af0bf9c
FB
2704void op_eret (void)
2705{
f41c52f1
TS
2706 if (loglevel & CPU_LOG_EXEC)
2707 CALL_FROM_TB0(debug_pre_eret);
24c7b0e3 2708 if (env->CP0_Status & (1 << CP0St_ERL)) {
6af0bf9c 2709 env->PC = env->CP0_ErrorEPC;
24c7b0e3 2710 env->CP0_Status &= ~(1 << CP0St_ERL);
51e11d9e 2711 } else {
6af0bf9c 2712 env->PC = env->CP0_EPC;
24c7b0e3 2713 env->CP0_Status &= ~(1 << CP0St_EXL);
51e11d9e 2714 }
24c7b0e3
TS
2715 if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
2716 !(env->CP0_Status & (1 << CP0St_ERL)) &&
2717 !(env->hflags & MIPS_HFLAG_DM) &&
2718 (env->CP0_Status & (1 << CP0St_UM)))
2719 env->hflags |= MIPS_HFLAG_UM;
f41c52f1
TS
2720 if (loglevel & CPU_LOG_EXEC)
2721 CALL_FROM_TB0(debug_post_eret);
6af0bf9c 2722 env->CP0_LLAddr = 1;
7a387fff 2723 RETURN();
6af0bf9c
FB
2724}
2725
2726void op_deret (void)
2727{
f41c52f1
TS
2728 if (loglevel & CPU_LOG_EXEC)
2729 CALL_FROM_TB0(debug_pre_eret);
6af0bf9c 2730 env->PC = env->CP0_DEPC;
24c7b0e3
TS
2731 env->hflags |= MIPS_HFLAG_DM;
2732 if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
2733 !(env->CP0_Status & (1 << CP0St_ERL)) &&
2734 !(env->hflags & MIPS_HFLAG_DM) &&
2735 (env->CP0_Status & (1 << CP0St_UM)))
2736 env->hflags |= MIPS_HFLAG_UM;
f41c52f1
TS
2737 if (loglevel & CPU_LOG_EXEC)
2738 CALL_FROM_TB0(debug_post_eret);
24c7b0e3 2739 env->CP0_LLAddr = 1;
7a387fff
TS
2740 RETURN();
2741}
2742
2743void op_rdhwr_cpunum(void)
2744{
1579a72e 2745 if (!(env->hflags & MIPS_HFLAG_UM) ||
97428a4d 2746 (env->CP0_HWREna & (1 << 0)) ||
1579a72e
TS
2747 (env->CP0_Status & (1 << CP0St_CU0)))
2748 T0 = env->CP0_EBase & 0x3ff;
7a387fff 2749 else
1579a72e 2750 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
7a387fff
TS
2751 RETURN();
2752}
2753
2754void op_rdhwr_synci_step(void)
2755{
1579a72e 2756 if (!(env->hflags & MIPS_HFLAG_UM) ||
97428a4d 2757 (env->CP0_HWREna & (1 << 1)) ||
1579a72e
TS
2758 (env->CP0_Status & (1 << CP0St_CU0)))
2759 T0 = env->SYNCI_Step;
7a387fff 2760 else
1579a72e 2761 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
7a387fff
TS
2762 RETURN();
2763}
2764
2765void op_rdhwr_cc(void)
2766{
1579a72e 2767 if (!(env->hflags & MIPS_HFLAG_UM) ||
97428a4d 2768 (env->CP0_HWREna & (1 << 2)) ||
1579a72e
TS
2769 (env->CP0_Status & (1 << CP0St_CU0)))
2770 T0 = env->CP0_Count;
7a387fff 2771 else
1579a72e 2772 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
7a387fff
TS
2773 RETURN();
2774}
2775
2776void op_rdhwr_ccres(void)
2777{
1579a72e 2778 if (!(env->hflags & MIPS_HFLAG_UM) ||
97428a4d 2779 (env->CP0_HWREna & (1 << 3)) ||
1579a72e
TS
2780 (env->CP0_Status & (1 << CP0St_CU0)))
2781 T0 = env->CCRes;
7a387fff 2782 else
1579a72e
TS
2783 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
2784 RETURN();
2785}
2786
6af0bf9c
FB
2787void op_save_state (void)
2788{
2789 env->hflags = PARAM1;
2790 RETURN();
2791}
2792
2793void op_save_pc (void)
2794{
2795 env->PC = PARAM1;
2796 RETURN();
2797}
2798
5a5012ec
TS
2799void op_save_fp_status (void)
2800{
2801 union fps {
2802 uint32_t i;
2803 float_status f;
2804 } fps;
2805 fps.i = PARAM1;
2806 env->fp_status = fps.f;
2807 RETURN();
2808}
2809
16c00cb2
TS
2810void op_interrupt_restart (void)
2811{
2812 if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
2813 !(env->CP0_Status & (1 << CP0St_ERL)) &&
2814 !(env->hflags & MIPS_HFLAG_DM) &&
2815 (env->CP0_Status & (1 << CP0St_IE)) &&
2816 (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask)) {
2817 env->CP0_Cause &= ~(0x1f << CP0Ca_EC);
2818 CALL_FROM_TB1(do_raise_exception, EXCP_EXT_INTERRUPT);
2819 }
2820 RETURN();
2821}
2822
6af0bf9c
FB
2823void op_raise_exception (void)
2824{
2825 CALL_FROM_TB1(do_raise_exception, PARAM1);
2826 RETURN();
2827}
2828
2829void op_raise_exception_err (void)
2830{
2831 CALL_FROM_TB2(do_raise_exception_err, PARAM1, PARAM2);
2832 RETURN();
2833}
2834
2835void op_exit_tb (void)
2836{
2837 EXIT_TB();
7a387fff 2838 RETURN();
6af0bf9c
FB
2839}
2840
4ad40f36
FB
2841void op_wait (void)
2842{
2843 env->halted = 1;
2844 CALL_FROM_TB1(do_raise_exception, EXCP_HLT);
7a387fff
TS
2845 RETURN();
2846}
2847
2848/* Bitfield operations. */
2849void op_ext(void)
2850{
2851 unsigned int pos = PARAM1;
2852 unsigned int size = PARAM2;
2853
f757d6ff 2854 T0 = ((uint32_t)T1 >> pos) & ((size < 32) ? ((1 << size) - 1) : ~0);
7a387fff
TS
2855 RETURN();
2856}
2857
2858void op_ins(void)
2859{
2860 unsigned int pos = PARAM1;
2861 unsigned int size = PARAM2;
f757d6ff 2862 target_ulong mask = ((size < 32) ? ((1 << size) - 1) : ~0) << pos;
7a387fff 2863
171b31e7 2864 T0 = (T0 & ~mask) | (((uint32_t)T1 << pos) & mask);
7a387fff
TS
2865 RETURN();
2866}
2867
2868void op_wsbh(void)
2869{
2870 T0 = ((T1 << 8) & ~0x00FF00FF) | ((T1 >> 8) & 0x00FF00FF);
2871 RETURN();
2872}
2873
60aa19ab 2874#ifdef TARGET_MIPS64
c570fd16
TS
2875void op_dext(void)
2876{
2877 unsigned int pos = PARAM1;
2878 unsigned int size = PARAM2;
2879
f757d6ff 2880 T0 = (T1 >> pos) & ((size < 32) ? ((1 << size) - 1) : ~0);
c570fd16
TS
2881 RETURN();
2882}
2883
2884void op_dins(void)
2885{
2886 unsigned int pos = PARAM1;
2887 unsigned int size = PARAM2;
f757d6ff 2888 target_ulong mask = ((size < 32) ? ((1 << size) - 1) : ~0) << pos;
c570fd16 2889
171b31e7 2890 T0 = (T0 & ~mask) | ((T1 << pos) & mask);
c570fd16
TS
2891 RETURN();
2892}
2893
7a387fff
TS
2894void op_dsbh(void)
2895{
2896 T0 = ((T1 << 8) & ~0x00FF00FF00FF00FFULL) | ((T1 >> 8) & 0x00FF00FF00FF00FFULL);
2897 RETURN();
2898}
2899
2900void op_dshd(void)
2901{
2902 T0 = ((T1 << 16) & ~0x0000FFFF0000FFFFULL) | ((T1 >> 16) & 0x0000FFFF0000FFFFULL);
2903 RETURN();
2904}
c570fd16 2905#endif
7a387fff
TS
2906
2907void op_seb(void)
2908{
2909 T0 = ((T1 & 0xFF) ^ 0x80) - 0x80;
2910 RETURN();
2911}
2912
2913void op_seh(void)
2914{
2915 T0 = ((T1 & 0xFFFF) ^ 0x8000) - 0x8000;
2916 RETURN();
4ad40f36 2917}
This page took 0.457924 seconds and 4 git commands to generate.