]> git.proxmox.com Git - mirror_qemu.git/blame - target-mips/op.c
Windows sparse file support (Frediano Ziglio)
[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
788FLOAT_OP(cvtd, w)
789{
790 FDT2 = int32_to_float64(WT0, &env->fp_status);
791 DEBUG_FPU_STATE();
792 RETURN();
793}
794FLOAT_OP(cvts, w)
795{
796 FST2 = int32_to_float32(WT0, &env->fp_status);
797 DEBUG_FPU_STATE();
798 RETURN();
799}
800FLOAT_OP(cvtw, s)
801{
802 WT2 = float32_to_int32(FST0, &env->fp_status);
803 DEBUG_FPU_STATE();
804 RETURN();
805}
806FLOAT_OP(cvtw, d)
807{
808 WT2 = float64_to_int32(FDT0, &env->fp_status);
809 DEBUG_FPU_STATE();
810 RETURN();
811}
812
813FLOAT_OP(roundw, d)
814{
815 set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
816 WT2 = float64_round_to_int(FDT0, &env->fp_status);
817 RESTORE_ROUNDING_MODE;
818
819 DEBUG_FPU_STATE();
820 RETURN();
821}
822FLOAT_OP(roundw, s)
823{
824 set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
825 WT2 = float32_round_to_int(FST0, &env->fp_status);
826 RESTORE_ROUNDING_MODE;
827 DEBUG_FPU_STATE();
828 RETURN();
829}
830
831FLOAT_OP(truncw, d)
832{
833 WT2 = float64_to_int32_round_to_zero(FDT0, &env->fp_status);
834 DEBUG_FPU_STATE();
835 RETURN();
836}
837FLOAT_OP(truncw, s)
838{
839 WT2 = float32_to_int32_round_to_zero(FST0, &env->fp_status);
840 DEBUG_FPU_STATE();
841 RETURN();
842}
843
844FLOAT_OP(ceilw, d)
845{
846 set_float_rounding_mode(float_round_up, &env->fp_status);
847 WT2 = float64_round_to_int(FDT0, &env->fp_status);
848 RESTORE_ROUNDING_MODE;
849
850 DEBUG_FPU_STATE();
851 RETURN();
852}
853FLOAT_OP(ceilw, s)
854{
855 set_float_rounding_mode(float_round_up, &env->fp_status);
856 WT2 = float32_round_to_int(FST0, &env->fp_status);
857 RESTORE_ROUNDING_MODE;
858 DEBUG_FPU_STATE();
859 RETURN();
860}
861
862FLOAT_OP(floorw, d)
863{
864 set_float_rounding_mode(float_round_down, &env->fp_status);
865 WT2 = float64_round_to_int(FDT0, &env->fp_status);
866 RESTORE_ROUNDING_MODE;
867
868 DEBUG_FPU_STATE();
869 RETURN();
870}
871FLOAT_OP(floorw, s)
872{
873 set_float_rounding_mode(float_round_down, &env->fp_status);
874 WT2 = float32_round_to_int(FST0, &env->fp_status);
875 RESTORE_ROUNDING_MODE;
876 DEBUG_FPU_STATE();
877 RETURN();
878}
879
880/* binary operations */
881#define FLOAT_BINOP(name) \
882FLOAT_OP(name, d) \
883{ \
884 FDT2 = float64_ ## name (FDT0, FDT1, &env->fp_status); \
885 DEBUG_FPU_STATE(); \
886} \
887FLOAT_OP(name, s) \
888{ \
889 FST2 = float32_ ## name (FST0, FST1, &env->fp_status); \
890 DEBUG_FPU_STATE(); \
891}
892FLOAT_BINOP(add)
893FLOAT_BINOP(sub)
894FLOAT_BINOP(mul)
895FLOAT_BINOP(div)
896#undef FLOAT_BINOP
897
898/* unary operations, modifying fp status */
899#define FLOAT_UNOP(name) \
900FLOAT_OP(name, d) \
901{ \
902 FDT2 = float64_ ## name(FDT0, &env->fp_status); \
903 DEBUG_FPU_STATE(); \
904} \
905FLOAT_OP(name, s) \
906{ \
907 FST2 = float32_ ## name(FST0, &env->fp_status); \
908 DEBUG_FPU_STATE(); \
909}
910FLOAT_UNOP(sqrt)
911#undef FLOAT_UNOP
912
913/* unary operations, not modifying fp status */
914#define FLOAT_UNOP(name) \
915FLOAT_OP(name, d) \
916{ \
917 FDT2 = float64_ ## name(FDT0); \
918 DEBUG_FPU_STATE(); \
919} \
920FLOAT_OP(name, s) \
921{ \
922 FST2 = float32_ ## name(FST0); \
923 DEBUG_FPU_STATE(); \
924}
925FLOAT_UNOP(abs)
926FLOAT_UNOP(chs)
927#undef FLOAT_UNOP
928
929FLOAT_OP(mov, d)
930{
931 FDT2 = FDT0;
932 DEBUG_FPU_STATE();
933 RETURN();
934}
935FLOAT_OP(mov, s)
936{
937 FST2 = FST0;
938 DEBUG_FPU_STATE();
939 RETURN();
940}
941
942#ifdef CONFIG_SOFTFLOAT
943#define clear_invalid() do { \
944 int flags = get_float_exception_flags(&env->fp_status); \
945 flags &= ~float_flag_invalid; \
946 set_float_exception_flags(flags, &env->fp_status); \
947} while(0)
948#else
949#define clear_invalid() do { } while(0)
950#endif
951
952extern void dump_fpu_s(CPUState *env);
953
954#define FOP_COND(fmt, op, sig, cond) \
955void op_cmp_ ## fmt ## _ ## op (void) \
956{ \
957 if (cond) \
958 SET_FP_COND(env->fcr31); \
959 else \
960 CLEAR_FP_COND(env->fcr31); \
961 if (!sig) \
962 clear_invalid(); \
963 /*CALL_FROM_TB1(dump_fpu_s, env);*/ \
964 DEBUG_FPU_STATE(); \
965 RETURN(); \
966}
967
968flag float64_is_unordered(float64 a, float64 b STATUS_PARAM)
969{
970 extern flag float64_is_nan( float64 a );
971 if (float64_is_nan(a) || float64_is_nan(b)) {
972 float_raise(float_flag_invalid, status);
973 return 1;
974 }
975 else {
976 return 0;
977 }
978}
979
980FOP_COND(d, f, 0, 0)
981FOP_COND(d, un, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status))
982FOP_COND(d, eq, 0, float64_eq(FDT0, FDT1, &env->fp_status))
983FOP_COND(d, ueq, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status))
984FOP_COND(d, olt, 0, float64_lt(FDT0, FDT1, &env->fp_status))
985FOP_COND(d, ult, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status))
986FOP_COND(d, ole, 0, float64_le(FDT0, FDT1, &env->fp_status))
987FOP_COND(d, ule, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status))
988/* NOTE: the comma operator will make "cond" to eval to false,
989 * but float*_is_unordered() is still called
990 */
991FOP_COND(d, sf, 1, (float64_is_unordered(FDT0, FDT1, &env->fp_status), 0))
992FOP_COND(d, ngle,1, float64_is_unordered(FDT1, FDT0, &env->fp_status))
993FOP_COND(d, seq, 1, float64_eq(FDT0, FDT1, &env->fp_status))
994FOP_COND(d, ngl, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status))
995FOP_COND(d, lt, 1, float64_lt(FDT0, FDT1, &env->fp_status))
996FOP_COND(d, nge, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status))
997FOP_COND(d, le, 1, float64_le(FDT0, FDT1, &env->fp_status))
998FOP_COND(d, ngt, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status))
999
1000flag float32_is_unordered(float32 a, float32 b STATUS_PARAM)
1001{
1002 extern flag float32_is_nan( float32 a );
1003 if (float32_is_nan(a) || float32_is_nan(b)) {
1004 float_raise(float_flag_invalid, status);
1005 return 1;
1006 }
1007 else {
1008 return 0;
1009 }
1010}
1011
1012/* NOTE: the comma operator will make "cond" to eval to false,
1013 * but float*_is_unordered() is still called
1014 */
1015FOP_COND(s, f, 0, 0)
1016FOP_COND(s, un, 0, float32_is_unordered(FST1, FST0, &env->fp_status))
1017FOP_COND(s, eq, 0, float32_eq(FST0, FST1, &env->fp_status))
1018FOP_COND(s, ueq, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status))
1019FOP_COND(s, olt, 0, float32_lt(FST0, FST1, &env->fp_status))
1020FOP_COND(s, ult, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status))
1021FOP_COND(s, ole, 0, float32_le(FST0, FST1, &env->fp_status))
1022FOP_COND(s, ule, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status))
1023/* NOTE: the comma operator will make "cond" to eval to false,
1024 * but float*_is_unordered() is still called
1025 */
1026FOP_COND(s, sf, 1, (float32_is_unordered(FST0, FST1, &env->fp_status), 0))
1027FOP_COND(s, ngle,1, float32_is_unordered(FST1, FST0, &env->fp_status))
1028FOP_COND(s, seq, 1, float32_eq(FST0, FST1, &env->fp_status))
1029FOP_COND(s, ngl, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status))
1030FOP_COND(s, lt, 1, float32_lt(FST0, FST1, &env->fp_status))
1031FOP_COND(s, nge, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status))
1032FOP_COND(s, le, 1, float32_le(FST0, FST1, &env->fp_status))
1033FOP_COND(s, ngt, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status))
1034
1035void op_bc1f (void)
1036{
1037 T0 = ! IS_FP_COND_SET(env->fcr31);
1038 DEBUG_FPU_STATE();
1039 RETURN();
1040}
1041
1042void op_bc1t (void)
1043{
1044 T0 = IS_FP_COND_SET(env->fcr31);
1045 DEBUG_FPU_STATE();
1046 RETURN();
1047}
1048#endif /* MIPS_USES_FPU */
1049
6af0bf9c
FB
1050#if defined(MIPS_USES_R4K_TLB)
1051void op_tlbwi (void)
1052{
1053 CALL_FROM_TB0(do_tlbwi);
1054 RETURN();
1055}
1056
1057void op_tlbwr (void)
1058{
1059 CALL_FROM_TB0(do_tlbwr);
1060 RETURN();
1061}
1062
1063void op_tlbp (void)
1064{
1065 CALL_FROM_TB0(do_tlbp);
1066 RETURN();
1067}
1068
1069void op_tlbr (void)
1070{
1071 CALL_FROM_TB0(do_tlbr);
1072 RETURN();
1073}
1074#endif
1075
1076/* Specials */
1077void op_pmon (void)
1078{
1079 CALL_FROM_TB1(do_pmon, PARAM1);
1080}
1081
1082void op_trap (void)
1083{
1084 if (T0) {
4ad40f36 1085 CALL_FROM_TB1(do_raise_exception_direct, EXCP_TRAP);
6af0bf9c
FB
1086 }
1087 RETURN();
1088}
1089
4ad40f36
FB
1090void op_debug (void)
1091{
ce2f4b3c 1092 CALL_FROM_TB1(do_raise_exception, EXCP_DEBUG);
4ad40f36
FB
1093}
1094
6af0bf9c
FB
1095void op_set_lladdr (void)
1096{
1097 env->CP0_LLAddr = T2;
1098}
1099
1100void debug_eret (void);
1101void op_eret (void)
1102{
1103 CALL_FROM_TB0(debug_eret);
51e11d9e 1104 if (env->hflags & MIPS_HFLAG_ERL) {
6af0bf9c 1105 env->PC = env->CP0_ErrorEPC;
51e11d9e
FB
1106 env->hflags &= ~MIPS_HFLAG_ERL;
1107 } else {
6af0bf9c 1108 env->PC = env->CP0_EPC;
51e11d9e
FB
1109 env->hflags &= ~MIPS_HFLAG_EXL;
1110 }
6af0bf9c
FB
1111 env->CP0_LLAddr = 1;
1112}
1113
1114void op_deret (void)
1115{
1116 CALL_FROM_TB0(debug_eret);
1117 env->PC = env->CP0_DEPC;
1118}
1119
1120void op_save_state (void)
1121{
1122 env->hflags = PARAM1;
1123 RETURN();
1124}
1125
1126void op_save_pc (void)
1127{
1128 env->PC = PARAM1;
1129 RETURN();
1130}
1131
1132void op_raise_exception (void)
1133{
1134 CALL_FROM_TB1(do_raise_exception, PARAM1);
1135 RETURN();
1136}
1137
1138void op_raise_exception_err (void)
1139{
1140 CALL_FROM_TB2(do_raise_exception_err, PARAM1, PARAM2);
1141 RETURN();
1142}
1143
1144void op_exit_tb (void)
1145{
1146 EXIT_TB();
1147}
1148
4ad40f36
FB
1149void op_wait (void)
1150{
1151 env->halted = 1;
1152 CALL_FROM_TB1(do_raise_exception, EXCP_HLT);
1153}