]> git.proxmox.com Git - mirror_qemu.git/blame - target-mips/op.c
M68k build fix.
[mirror_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
FB
25#ifndef CALL_FROM_TB0
26#define CALL_FROM_TB0(func) func();
27#endif
28#ifndef CALL_FROM_TB1
29#define CALL_FROM_TB1(func, arg0) func(arg0);
30#endif
31#ifndef CALL_FROM_TB1_CONST16
32#define CALL_FROM_TB1_CONST16(func, arg0) CALL_FROM_TB1(func, arg0);
33#endif
34#ifndef CALL_FROM_TB2
35#define CALL_FROM_TB2(func, arg0, arg1) func(arg0, arg1);
36#endif
37#ifndef CALL_FROM_TB2_CONST16
38#define CALL_FROM_TB2_CONST16(func, arg0, arg1) \
39CALL_FROM_TB2(func, arg0, arg1);
40#endif
41#ifndef CALL_FROM_TB3
42#define CALL_FROM_TB3(func, arg0, arg1, arg2) func(arg0, arg1, arg2);
43#endif
44#ifndef CALL_FROM_TB4
45#define CALL_FROM_TB4(func, arg0, arg1, arg2, arg3) \
46 func(arg0, arg1, arg2, arg3);
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
143#define TN T0
144#include "op_template.c"
145#undef TN
146#define TN T1
147#include "op_template.c"
148#undef TN
149#define TN T2
150#include "op_template.c"
151#undef TN
152
6ea83fed
FB
153#ifdef MIPS_USES_FPU
154
155#define SFREG 0
156#define DFREG 0
157#include "fop_template.c"
158#undef SFREG
159#undef DFREG
160#define SFREG 1
161#include "fop_template.c"
162#undef SFREG
163#define SFREG 2
164#define DFREG 2
165#include "fop_template.c"
166#undef SFREG
167#undef DFREG
168#define SFREG 3
169#include "fop_template.c"
170#undef SFREG
171#define SFREG 4
172#define DFREG 4
173#include "fop_template.c"
174#undef SFREG
175#undef DFREG
176#define SFREG 5
177#include "fop_template.c"
178#undef SFREG
179#define SFREG 6
180#define DFREG 6
181#include "fop_template.c"
182#undef SFREG
183#undef DFREG
184#define SFREG 7
185#include "fop_template.c"
186#undef SFREG
187#define SFREG 8
188#define DFREG 8
189#include "fop_template.c"
190#undef SFREG
191#undef DFREG
192#define SFREG 9
193#include "fop_template.c"
194#undef SFREG
195#define SFREG 10
196#define DFREG 10
197#include "fop_template.c"
198#undef SFREG
199#undef DFREG
200#define SFREG 11
201#include "fop_template.c"
202#undef SFREG
203#define SFREG 12
204#define DFREG 12
205#include "fop_template.c"
206#undef SFREG
207#undef DFREG
208#define SFREG 13
209#include "fop_template.c"
210#undef SFREG
211#define SFREG 14
212#define DFREG 14
213#include "fop_template.c"
214#undef SFREG
215#undef DFREG
216#define SFREG 15
217#include "fop_template.c"
218#undef SFREG
219#define SFREG 16
220#define DFREG 16
221#include "fop_template.c"
222#undef SFREG
223#undef DFREG
224#define SFREG 17
225#include "fop_template.c"
226#undef SFREG
227#define SFREG 18
228#define DFREG 18
229#include "fop_template.c"
230#undef SFREG
231#undef DFREG
232#define SFREG 19
233#include "fop_template.c"
234#undef SFREG
235#define SFREG 20
236#define DFREG 20
237#include "fop_template.c"
238#undef SFREG
239#undef DFREG
240#define SFREG 21
241#include "fop_template.c"
242#undef SFREG
243#define SFREG 22
244#define DFREG 22
245#include "fop_template.c"
246#undef SFREG
247#undef DFREG
248#define SFREG 23
249#include "fop_template.c"
250#undef SFREG
251#define SFREG 24
252#define DFREG 24
253#include "fop_template.c"
254#undef SFREG
255#undef DFREG
256#define SFREG 25
257#include "fop_template.c"
258#undef SFREG
259#define SFREG 26
260#define DFREG 26
261#include "fop_template.c"
262#undef SFREG
263#undef DFREG
264#define SFREG 27
265#include "fop_template.c"
266#undef SFREG
267#define SFREG 28
268#define DFREG 28
269#include "fop_template.c"
270#undef SFREG
271#undef DFREG
272#define SFREG 29
273#include "fop_template.c"
274#undef SFREG
275#define SFREG 30
276#define DFREG 30
277#include "fop_template.c"
278#undef SFREG
279#undef DFREG
280#define SFREG 31
281#include "fop_template.c"
282#undef SFREG
283
284#define FTN
285#include "fop_template.c"
286#undef FTN
287
288#endif
289
6af0bf9c
FB
290void op_dup_T0 (void)
291{
292 T2 = T0;
293 RETURN();
294}
295
296void op_load_HI (void)
297{
298 T0 = env->HI;
299 RETURN();
300}
301
302void op_store_HI (void)
303{
304 env->HI = T0;
305 RETURN();
306}
307
308void op_load_LO (void)
309{
310 T0 = env->LO;
311 RETURN();
312}
313
314void op_store_LO (void)
315{
316 env->LO = T0;
317 RETURN();
318}
319
320/* Load and store */
321#define MEMSUFFIX _raw
322#include "op_mem.c"
323#undef MEMSUFFIX
324#if !defined(CONFIG_USER_ONLY)
325#define MEMSUFFIX _user
326#include "op_mem.c"
327#undef MEMSUFFIX
328
329#define MEMSUFFIX _kernel
330#include "op_mem.c"
331#undef MEMSUFFIX
332#endif
333
334/* Arithmetic */
335void op_add (void)
336{
337 T0 += T1;
338 RETURN();
339}
340
341void op_addo (void)
342{
343 target_ulong tmp;
344
345 tmp = T0;
346 T0 += T1;
76e050c2
FB
347 if (((tmp ^ T1 ^ (-1)) & (T0 ^ T1)) >> 31) {
348 /* operands of same sign, result different sign */
4ad40f36 349 CALL_FROM_TB1(do_raise_exception_direct, EXCP_OVERFLOW);
6af0bf9c
FB
350 }
351 RETURN();
352}
353
354void op_sub (void)
355{
356 T0 -= T1;
357 RETURN();
358}
359
360void op_subo (void)
361{
362 target_ulong tmp;
363
364 tmp = T0;
365 T0 = (int32_t)T0 - (int32_t)T1;
76e050c2
FB
366 if (((tmp ^ T1) & (tmp ^ T0)) >> 31) {
367 /* operands of different sign, first operand and result different sign */
4ad40f36 368 CALL_FROM_TB1(do_raise_exception_direct, EXCP_OVERFLOW);
6af0bf9c
FB
369 }
370 RETURN();
371}
372
373void op_mul (void)
374{
375 T0 = (int32_t)T0 * (int32_t)T1;
376 RETURN();
377}
378
379void op_div (void)
380{
381 if (T1 != 0) {
382 env->LO = (int32_t)T0 / (int32_t)T1;
383 env->HI = (int32_t)T0 % (int32_t)T1;
384 }
385 RETURN();
386}
387
388void op_divu (void)
389{
390 if (T1 != 0) {
391 env->LO = T0 / T1;
392 env->HI = T0 % T1;
393 }
394 RETURN();
395}
396
397/* Logical */
398void op_and (void)
399{
400 T0 &= T1;
401 RETURN();
402}
403
404void op_nor (void)
405{
406 T0 = ~(T0 | T1);
407 RETURN();
408}
409
410void op_or (void)
411{
412 T0 |= T1;
413 RETURN();
414}
415
416void op_xor (void)
417{
418 T0 ^= T1;
419 RETURN();
420}
421
422void op_sll (void)
423{
424 T0 = T0 << T1;
425 RETURN();
426}
427
428void op_sra (void)
429{
430 T0 = (int32_t)T0 >> T1;
431 RETURN();
432}
433
434void op_srl (void)
435{
436 T0 = T0 >> T1;
437 RETURN();
438}
439
440void op_sllv (void)
441{
442 T0 = T1 << (T0 & 0x1F);
443 RETURN();
444}
445
446void op_srav (void)
447{
448 T0 = (int32_t)T1 >> (T0 & 0x1F);
449 RETURN();
450}
451
452void op_srlv (void)
453{
454 T0 = T1 >> (T0 & 0x1F);
455 RETURN();
456}
457
458void op_clo (void)
459{
460 int n;
461
462 if (T0 == (target_ulong)-1) {
463 T0 = 32;
464 } else {
465 for (n = 0; n < 32; n++) {
466 if (!(T0 & (1 << 31)))
467 break;
468 T0 = T0 << 1;
469 }
470 T0 = n;
471 }
472 RETURN();
473}
474
475void op_clz (void)
476{
477 int n;
478
479 if (T0 == 0) {
480 T0 = 32;
481 } else {
482 for (n = 0; n < 32; n++) {
483 if (T0 & (1 << 31))
484 break;
485 T0 = T0 << 1;
486 }
487 T0 = n;
488 }
489 RETURN();
490}
491
492/* 64 bits arithmetic */
493#if (HOST_LONG_BITS == 64)
494static inline uint64_t get_HILO (void)
495{
496 return ((uint64_t)env->HI << 32) | (uint64_t)env->LO;
497}
498
499static inline void set_HILO (uint64_t HILO)
500{
501 env->LO = HILO & 0xFFFFFFFF;
502 env->HI = HILO >> 32;
503}
504
505void op_mult (void)
506{
4ad40f36 507 set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
6af0bf9c
FB
508 RETURN();
509}
510
511void op_multu (void)
512{
513 set_HILO((uint64_t)T0 * (uint64_t)T1);
514 RETURN();
515}
516
517void op_madd (void)
518{
519 int64_t tmp;
520
4ad40f36 521 tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
6af0bf9c
FB
522 set_HILO((int64_t)get_HILO() + tmp);
523 RETURN();
524}
525
526void op_maddu (void)
527{
528 uint64_t tmp;
529
530 tmp = ((uint64_t)T0 * (uint64_t)T1);
531 set_HILO(get_HILO() + tmp);
532 RETURN();
533}
534
535void op_msub (void)
536{
537 int64_t tmp;
538
4ad40f36 539 tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
6af0bf9c
FB
540 set_HILO((int64_t)get_HILO() - tmp);
541 RETURN();
542}
543
544void op_msubu (void)
545{
546 uint64_t tmp;
547
548 tmp = ((uint64_t)T0 * (uint64_t)T1);
549 set_HILO(get_HILO() - tmp);
550 RETURN();
551}
552#else
553void op_mult (void)
554{
555 CALL_FROM_TB0(do_mult);
556 RETURN();
557}
558
559void op_multu (void)
560{
561 CALL_FROM_TB0(do_multu);
562 RETURN();
563}
564
565void op_madd (void)
566{
567 CALL_FROM_TB0(do_madd);
568 RETURN();
569}
570
571void op_maddu (void)
572{
573 CALL_FROM_TB0(do_maddu);
574 RETURN();
575}
576
577void op_msub (void)
578{
579 CALL_FROM_TB0(do_msub);
580 RETURN();
581}
582
583void op_msubu (void)
584{
585 CALL_FROM_TB0(do_msubu);
586 RETURN();
587}
588#endif
589
590/* Conditional moves */
591void op_movn (void)
592{
593 if (T1 != 0)
594 env->gpr[PARAM1] = T0;
595 RETURN();
596}
597
598void op_movz (void)
599{
600 if (T1 == 0)
601 env->gpr[PARAM1] = T0;
602 RETURN();
603}
604
605/* Tests */
606#define OP_COND(name, cond) \
607void glue(op_, name) (void) \
608{ \
609 if (cond) { \
610 T0 = 1; \
611 } else { \
612 T0 = 0; \
613 } \
614 RETURN(); \
615}
616
617OP_COND(eq, T0 == T1);
618OP_COND(ne, T0 != T1);
619OP_COND(ge, (int32_t)T0 >= (int32_t)T1);
620OP_COND(geu, T0 >= T1);
621OP_COND(lt, (int32_t)T0 < (int32_t)T1);
622OP_COND(ltu, T0 < T1);
623OP_COND(gez, (int32_t)T0 >= 0);
624OP_COND(gtz, (int32_t)T0 > 0);
625OP_COND(lez, (int32_t)T0 <= 0);
626OP_COND(ltz, (int32_t)T0 < 0);
627
628/* Branchs */
629//#undef USE_DIRECT_JUMP
c53be334
FB
630
631void OPPROTO op_goto_tb0(void)
632{
633 GOTO_TB(op_goto_tb0, PARAM1, 0);
634}
635
636void OPPROTO op_goto_tb1(void)
637{
638 GOTO_TB(op_goto_tb1, PARAM1, 1);
639}
6af0bf9c
FB
640
641/* Branch to register */
642void op_save_breg_target (void)
643{
644 env->btarget = T2;
645}
646
647void op_restore_breg_target (void)
648{
649 T2 = env->btarget;
650}
651
652void op_breg (void)
653{
654 env->PC = T2;
655 RETURN();
656}
657
6af0bf9c
FB
658void op_save_btarget (void)
659{
660 env->btarget = PARAM1;
661 RETURN();
662}
663
664/* Conditional branch */
665void op_set_bcond (void)
666{
667 T2 = T0;
668 RETURN();
669}
670
671void op_save_bcond (void)
672{
673 env->bcond = T2;
674 RETURN();
675}
676
677void op_restore_bcond (void)
678{
679 T2 = env->bcond;
680 RETURN();
681}
682
c53be334 683void op_jnz_T2 (void)
6af0bf9c 684{
c53be334
FB
685 if (T2)
686 GOTO_LABEL_PARAM(1);
6af0bf9c
FB
687 RETURN();
688}
689
690/* CP0 functions */
691void op_mfc0 (void)
692{
693 CALL_FROM_TB2(do_mfc0, PARAM1, PARAM2);
694 RETURN();
695}
696
697void op_mtc0 (void)
698{
699 CALL_FROM_TB2(do_mtc0, PARAM1, PARAM2);
700 RETURN();
701}
702
6ea83fed
FB
703#ifdef MIPS_USES_FPU
704
705#if 0
706# define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env)
707#else
708# define DEBUG_FPU_STATE() do { } while(0)
709#endif
710
711void op_cp1_enabled(void)
712{
713 if (!(env->CP0_Status & (1 << CP0St_CU1))) {
714 CALL_FROM_TB2(do_raise_exception_err, EXCP_CpU, 1);
715 }
716 RETURN();
717}
718
719/* CP1 functions */
720void op_cfc1 (void)
721{
722 if (T1 == 0) {
723 T0 = env->fcr0;
724 }
725 else {
726 /* fetch fcr31, masking unused bits */
727 T0 = env->fcr31 & 0x0183FFFF;
728 }
729 DEBUG_FPU_STATE();
730 RETURN();
731}
732
733/* convert MIPS rounding mode in FCR31 to IEEE library */
734unsigned int ieee_rm[] = {
735 float_round_nearest_even,
736 float_round_to_zero,
737 float_round_up,
738 float_round_down
739};
740
741#define RESTORE_ROUNDING_MODE \
742 set_float_rounding_mode(ieee_rm[env->fcr31 & 3], &env->fp_status)
743
744void op_ctc1 (void)
745{
746 if (T1 == 0) {
747 /* XXX should this throw an exception?
748 * don't write to FCR0.
749 * env->fcr0 = T0;
750 */
751 }
752 else {
753 /* store new fcr31, masking unused bits */
754 env->fcr31 = T0 & 0x0183FFFF;
755
756 /* set rounding mode */
757 RESTORE_ROUNDING_MODE;
758
759#ifndef CONFIG_SOFTFLOAT
760 /* no floating point exception for native float */
761 SET_FP_ENABLE(env->fcr31, 0);
762#endif
763 }
764 DEBUG_FPU_STATE();
765 RETURN();
766}
767
768void op_mfc1 (void)
769{
770 T0 = WT0;
771 DEBUG_FPU_STATE();
772 RETURN();
773}
774
775void op_mtc1 (void)
776{
777 WT0 = T0;
778 DEBUG_FPU_STATE();
779 RETURN();
780}
781
782/* Float support.
783 Single precition routines have a "s" suffix, double precision a
784 "d" suffix. */
785
786#define FLOAT_OP(name, p) void OPPROTO op_float_##name##_##p(void)
787
dd016883
FB
788FLOAT_OP(cvtd, s)
789{
790 FDT2 = float32_to_float64(WT0, &env->fp_status);
791 DEBUG_FPU_STATE();
792 RETURN();
793}
6ea83fed
FB
794FLOAT_OP(cvtd, w)
795{
796 FDT2 = int32_to_float64(WT0, &env->fp_status);
797 DEBUG_FPU_STATE();
798 RETURN();
799}
dd016883
FB
800FLOAT_OP(cvts, d)
801{
802 FST2 = float64_to_float32(WT0, &env->fp_status);
803 DEBUG_FPU_STATE();
804 RETURN();
805}
6ea83fed
FB
806FLOAT_OP(cvts, w)
807{
808 FST2 = int32_to_float32(WT0, &env->fp_status);
809 DEBUG_FPU_STATE();
810 RETURN();
811}
812FLOAT_OP(cvtw, s)
813{
814 WT2 = float32_to_int32(FST0, &env->fp_status);
815 DEBUG_FPU_STATE();
816 RETURN();
817}
818FLOAT_OP(cvtw, d)
819{
820 WT2 = float64_to_int32(FDT0, &env->fp_status);
821 DEBUG_FPU_STATE();
822 RETURN();
823}
824
825FLOAT_OP(roundw, d)
826{
827 set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
828 WT2 = float64_round_to_int(FDT0, &env->fp_status);
829 RESTORE_ROUNDING_MODE;
830
831 DEBUG_FPU_STATE();
832 RETURN();
833}
834FLOAT_OP(roundw, s)
835{
836 set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
837 WT2 = float32_round_to_int(FST0, &env->fp_status);
838 RESTORE_ROUNDING_MODE;
839 DEBUG_FPU_STATE();
840 RETURN();
841}
842
843FLOAT_OP(truncw, d)
844{
845 WT2 = float64_to_int32_round_to_zero(FDT0, &env->fp_status);
846 DEBUG_FPU_STATE();
847 RETURN();
848}
849FLOAT_OP(truncw, s)
850{
851 WT2 = float32_to_int32_round_to_zero(FST0, &env->fp_status);
852 DEBUG_FPU_STATE();
853 RETURN();
854}
855
856FLOAT_OP(ceilw, d)
857{
858 set_float_rounding_mode(float_round_up, &env->fp_status);
859 WT2 = float64_round_to_int(FDT0, &env->fp_status);
860 RESTORE_ROUNDING_MODE;
861
862 DEBUG_FPU_STATE();
863 RETURN();
864}
865FLOAT_OP(ceilw, s)
866{
867 set_float_rounding_mode(float_round_up, &env->fp_status);
868 WT2 = float32_round_to_int(FST0, &env->fp_status);
869 RESTORE_ROUNDING_MODE;
870 DEBUG_FPU_STATE();
871 RETURN();
872}
873
874FLOAT_OP(floorw, d)
875{
876 set_float_rounding_mode(float_round_down, &env->fp_status);
877 WT2 = float64_round_to_int(FDT0, &env->fp_status);
878 RESTORE_ROUNDING_MODE;
879
880 DEBUG_FPU_STATE();
881 RETURN();
882}
883FLOAT_OP(floorw, s)
884{
885 set_float_rounding_mode(float_round_down, &env->fp_status);
886 WT2 = float32_round_to_int(FST0, &env->fp_status);
887 RESTORE_ROUNDING_MODE;
888 DEBUG_FPU_STATE();
889 RETURN();
890}
891
892/* binary operations */
893#define FLOAT_BINOP(name) \
894FLOAT_OP(name, d) \
895{ \
896 FDT2 = float64_ ## name (FDT0, FDT1, &env->fp_status); \
897 DEBUG_FPU_STATE(); \
898} \
899FLOAT_OP(name, s) \
900{ \
901 FST2 = float32_ ## name (FST0, FST1, &env->fp_status); \
902 DEBUG_FPU_STATE(); \
903}
904FLOAT_BINOP(add)
905FLOAT_BINOP(sub)
906FLOAT_BINOP(mul)
907FLOAT_BINOP(div)
908#undef FLOAT_BINOP
909
910/* unary operations, modifying fp status */
911#define FLOAT_UNOP(name) \
912FLOAT_OP(name, d) \
913{ \
914 FDT2 = float64_ ## name(FDT0, &env->fp_status); \
915 DEBUG_FPU_STATE(); \
916} \
917FLOAT_OP(name, s) \
918{ \
919 FST2 = float32_ ## name(FST0, &env->fp_status); \
920 DEBUG_FPU_STATE(); \
921}
922FLOAT_UNOP(sqrt)
923#undef FLOAT_UNOP
924
925/* unary operations, not modifying fp status */
926#define FLOAT_UNOP(name) \
927FLOAT_OP(name, d) \
928{ \
929 FDT2 = float64_ ## name(FDT0); \
930 DEBUG_FPU_STATE(); \
931} \
932FLOAT_OP(name, s) \
933{ \
934 FST2 = float32_ ## name(FST0); \
935 DEBUG_FPU_STATE(); \
936}
937FLOAT_UNOP(abs)
938FLOAT_UNOP(chs)
939#undef FLOAT_UNOP
940
941FLOAT_OP(mov, d)
942{
943 FDT2 = FDT0;
944 DEBUG_FPU_STATE();
945 RETURN();
946}
947FLOAT_OP(mov, s)
948{
949 FST2 = FST0;
950 DEBUG_FPU_STATE();
951 RETURN();
952}
953
954#ifdef CONFIG_SOFTFLOAT
955#define clear_invalid() do { \
956 int flags = get_float_exception_flags(&env->fp_status); \
957 flags &= ~float_flag_invalid; \
958 set_float_exception_flags(flags, &env->fp_status); \
959} while(0)
960#else
961#define clear_invalid() do { } while(0)
962#endif
963
964extern void dump_fpu_s(CPUState *env);
965
966#define FOP_COND(fmt, op, sig, cond) \
967void op_cmp_ ## fmt ## _ ## op (void) \
968{ \
969 if (cond) \
970 SET_FP_COND(env->fcr31); \
971 else \
972 CLEAR_FP_COND(env->fcr31); \
973 if (!sig) \
974 clear_invalid(); \
975 /*CALL_FROM_TB1(dump_fpu_s, env);*/ \
976 DEBUG_FPU_STATE(); \
977 RETURN(); \
978}
979
569f5d66 980int float64_is_unordered(float64 a, float64 b STATUS_PARAM)
6ea83fed 981{
6ea83fed
FB
982 if (float64_is_nan(a) || float64_is_nan(b)) {
983 float_raise(float_flag_invalid, status);
984 return 1;
985 }
986 else {
987 return 0;
988 }
989}
990
991FOP_COND(d, f, 0, 0)
992FOP_COND(d, un, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status))
993FOP_COND(d, eq, 0, float64_eq(FDT0, FDT1, &env->fp_status))
994FOP_COND(d, ueq, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status))
995FOP_COND(d, olt, 0, float64_lt(FDT0, FDT1, &env->fp_status))
996FOP_COND(d, ult, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status))
997FOP_COND(d, ole, 0, float64_le(FDT0, FDT1, &env->fp_status))
998FOP_COND(d, ule, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status))
999/* NOTE: the comma operator will make "cond" to eval to false,
1000 * but float*_is_unordered() is still called
1001 */
1002FOP_COND(d, sf, 1, (float64_is_unordered(FDT0, FDT1, &env->fp_status), 0))
1003FOP_COND(d, ngle,1, float64_is_unordered(FDT1, FDT0, &env->fp_status))
1004FOP_COND(d, seq, 1, float64_eq(FDT0, FDT1, &env->fp_status))
1005FOP_COND(d, ngl, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status))
1006FOP_COND(d, lt, 1, float64_lt(FDT0, FDT1, &env->fp_status))
1007FOP_COND(d, nge, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status))
1008FOP_COND(d, le, 1, float64_le(FDT0, FDT1, &env->fp_status))
1009FOP_COND(d, ngt, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status))
1010
1011flag float32_is_unordered(float32 a, float32 b STATUS_PARAM)
1012{
1013 extern flag float32_is_nan( float32 a );
1014 if (float32_is_nan(a) || float32_is_nan(b)) {
1015 float_raise(float_flag_invalid, status);
1016 return 1;
1017 }
1018 else {
1019 return 0;
1020 }
1021}
1022
1023/* NOTE: the comma operator will make "cond" to eval to false,
1024 * but float*_is_unordered() is still called
1025 */
1026FOP_COND(s, f, 0, 0)
1027FOP_COND(s, un, 0, float32_is_unordered(FST1, FST0, &env->fp_status))
1028FOP_COND(s, eq, 0, float32_eq(FST0, FST1, &env->fp_status))
1029FOP_COND(s, ueq, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status))
1030FOP_COND(s, olt, 0, float32_lt(FST0, FST1, &env->fp_status))
1031FOP_COND(s, ult, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status))
1032FOP_COND(s, ole, 0, float32_le(FST0, FST1, &env->fp_status))
1033FOP_COND(s, ule, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status))
1034/* NOTE: the comma operator will make "cond" to eval to false,
1035 * but float*_is_unordered() is still called
1036 */
1037FOP_COND(s, sf, 1, (float32_is_unordered(FST0, FST1, &env->fp_status), 0))
1038FOP_COND(s, ngle,1, float32_is_unordered(FST1, FST0, &env->fp_status))
1039FOP_COND(s, seq, 1, float32_eq(FST0, FST1, &env->fp_status))
1040FOP_COND(s, ngl, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status))
1041FOP_COND(s, lt, 1, float32_lt(FST0, FST1, &env->fp_status))
1042FOP_COND(s, nge, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status))
1043FOP_COND(s, le, 1, float32_le(FST0, FST1, &env->fp_status))
1044FOP_COND(s, ngt, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status))
1045
1046void op_bc1f (void)
1047{
1048 T0 = ! IS_FP_COND_SET(env->fcr31);
1049 DEBUG_FPU_STATE();
1050 RETURN();
1051}
1052
1053void op_bc1t (void)
1054{
1055 T0 = IS_FP_COND_SET(env->fcr31);
1056 DEBUG_FPU_STATE();
1057 RETURN();
1058}
1059#endif /* MIPS_USES_FPU */
1060
6af0bf9c
FB
1061#if defined(MIPS_USES_R4K_TLB)
1062void op_tlbwi (void)
1063{
1064 CALL_FROM_TB0(do_tlbwi);
1065 RETURN();
1066}
1067
1068void op_tlbwr (void)
1069{
1070 CALL_FROM_TB0(do_tlbwr);
1071 RETURN();
1072}
1073
1074void op_tlbp (void)
1075{
1076 CALL_FROM_TB0(do_tlbp);
1077 RETURN();
1078}
1079
1080void op_tlbr (void)
1081{
1082 CALL_FROM_TB0(do_tlbr);
1083 RETURN();
1084}
1085#endif
1086
1087/* Specials */
1088void op_pmon (void)
1089{
1090 CALL_FROM_TB1(do_pmon, PARAM1);
1091}
1092
1093void op_trap (void)
1094{
1095 if (T0) {
4ad40f36 1096 CALL_FROM_TB1(do_raise_exception_direct, EXCP_TRAP);
6af0bf9c
FB
1097 }
1098 RETURN();
1099}
1100
4ad40f36
FB
1101void op_debug (void)
1102{
ce2f4b3c 1103 CALL_FROM_TB1(do_raise_exception, EXCP_DEBUG);
4ad40f36
FB
1104}
1105
6af0bf9c
FB
1106void op_set_lladdr (void)
1107{
1108 env->CP0_LLAddr = T2;
1109}
1110
1111void debug_eret (void);
1112void op_eret (void)
1113{
1114 CALL_FROM_TB0(debug_eret);
51e11d9e 1115 if (env->hflags & MIPS_HFLAG_ERL) {
6af0bf9c 1116 env->PC = env->CP0_ErrorEPC;
51e11d9e 1117 env->hflags &= ~MIPS_HFLAG_ERL;
3e382bc8 1118 env->CP0_Status &= ~(1 << CP0St_ERL);
51e11d9e 1119 } else {
6af0bf9c 1120 env->PC = env->CP0_EPC;
51e11d9e 1121 env->hflags &= ~MIPS_HFLAG_EXL;
3e382bc8 1122 env->CP0_Status &= ~(1 << CP0St_EXL);
51e11d9e 1123 }
6af0bf9c
FB
1124 env->CP0_LLAddr = 1;
1125}
1126
1127void op_deret (void)
1128{
1129 CALL_FROM_TB0(debug_eret);
1130 env->PC = env->CP0_DEPC;
1131}
1132
1133void op_save_state (void)
1134{
1135 env->hflags = PARAM1;
1136 RETURN();
1137}
1138
1139void op_save_pc (void)
1140{
1141 env->PC = PARAM1;
1142 RETURN();
1143}
1144
1145void op_raise_exception (void)
1146{
1147 CALL_FROM_TB1(do_raise_exception, PARAM1);
1148 RETURN();
1149}
1150
1151void op_raise_exception_err (void)
1152{
1153 CALL_FROM_TB2(do_raise_exception_err, PARAM1, PARAM2);
1154 RETURN();
1155}
1156
1157void op_exit_tb (void)
1158{
1159 EXIT_TB();
1160}
1161
4ad40f36
FB
1162void op_wait (void)
1163{
1164 env->halted = 1;
1165 CALL_FROM_TB1(do_raise_exception, EXCP_HLT);
1166}