]> git.proxmox.com Git - mirror_qemu.git/blame - target-mips/op.c
Add PS/2 keyboard to MIPS R4K, by Herve Poussineau.
[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
c570fd16 143#define TN
6af0bf9c
FB
144#include "op_template.c"
145#undef TN
146
6ea83fed
FB
147#ifdef MIPS_USES_FPU
148
149#define SFREG 0
150#define DFREG 0
151#include "fop_template.c"
152#undef SFREG
153#undef DFREG
154#define SFREG 1
155#include "fop_template.c"
156#undef SFREG
157#define SFREG 2
158#define DFREG 2
159#include "fop_template.c"
160#undef SFREG
161#undef DFREG
162#define SFREG 3
163#include "fop_template.c"
164#undef SFREG
165#define SFREG 4
166#define DFREG 4
167#include "fop_template.c"
168#undef SFREG
169#undef DFREG
170#define SFREG 5
171#include "fop_template.c"
172#undef SFREG
173#define SFREG 6
174#define DFREG 6
175#include "fop_template.c"
176#undef SFREG
177#undef DFREG
178#define SFREG 7
179#include "fop_template.c"
180#undef SFREG
181#define SFREG 8
182#define DFREG 8
183#include "fop_template.c"
184#undef SFREG
185#undef DFREG
186#define SFREG 9
187#include "fop_template.c"
188#undef SFREG
189#define SFREG 10
190#define DFREG 10
191#include "fop_template.c"
192#undef SFREG
193#undef DFREG
194#define SFREG 11
195#include "fop_template.c"
196#undef SFREG
197#define SFREG 12
198#define DFREG 12
199#include "fop_template.c"
200#undef SFREG
201#undef DFREG
202#define SFREG 13
203#include "fop_template.c"
204#undef SFREG
205#define SFREG 14
206#define DFREG 14
207#include "fop_template.c"
208#undef SFREG
209#undef DFREG
210#define SFREG 15
211#include "fop_template.c"
212#undef SFREG
213#define SFREG 16
214#define DFREG 16
215#include "fop_template.c"
216#undef SFREG
217#undef DFREG
218#define SFREG 17
219#include "fop_template.c"
220#undef SFREG
221#define SFREG 18
222#define DFREG 18
223#include "fop_template.c"
224#undef SFREG
225#undef DFREG
226#define SFREG 19
227#include "fop_template.c"
228#undef SFREG
229#define SFREG 20
230#define DFREG 20
231#include "fop_template.c"
232#undef SFREG
233#undef DFREG
234#define SFREG 21
235#include "fop_template.c"
236#undef SFREG
237#define SFREG 22
238#define DFREG 22
239#include "fop_template.c"
240#undef SFREG
241#undef DFREG
242#define SFREG 23
243#include "fop_template.c"
244#undef SFREG
245#define SFREG 24
246#define DFREG 24
247#include "fop_template.c"
248#undef SFREG
249#undef DFREG
250#define SFREG 25
251#include "fop_template.c"
252#undef SFREG
253#define SFREG 26
254#define DFREG 26
255#include "fop_template.c"
256#undef SFREG
257#undef DFREG
258#define SFREG 27
259#include "fop_template.c"
260#undef SFREG
261#define SFREG 28
262#define DFREG 28
263#include "fop_template.c"
264#undef SFREG
265#undef DFREG
266#define SFREG 29
267#include "fop_template.c"
268#undef SFREG
269#define SFREG 30
270#define DFREG 30
271#include "fop_template.c"
272#undef SFREG
273#undef DFREG
274#define SFREG 31
275#include "fop_template.c"
276#undef SFREG
277
278#define FTN
279#include "fop_template.c"
280#undef FTN
281
282#endif
283
6af0bf9c
FB
284void op_dup_T0 (void)
285{
286 T2 = T0;
287 RETURN();
288}
289
290void op_load_HI (void)
291{
292 T0 = env->HI;
293 RETURN();
294}
295
296void op_store_HI (void)
297{
298 env->HI = T0;
299 RETURN();
300}
301
302void op_load_LO (void)
303{
304 T0 = env->LO;
305 RETURN();
306}
307
308void op_store_LO (void)
309{
310 env->LO = T0;
311 RETURN();
312}
313
314/* Load and store */
315#define MEMSUFFIX _raw
316#include "op_mem.c"
317#undef MEMSUFFIX
318#if !defined(CONFIG_USER_ONLY)
319#define MEMSUFFIX _user
320#include "op_mem.c"
321#undef MEMSUFFIX
322
323#define MEMSUFFIX _kernel
324#include "op_mem.c"
325#undef MEMSUFFIX
326#endif
327
328/* Arithmetic */
329void op_add (void)
330{
5dc4b744 331 T0 = (int32_t)((int32_t)T0 + (int32_t)T1);
6af0bf9c
FB
332 RETURN();
333}
334
335void op_addo (void)
336{
337 target_ulong tmp;
338
c570fd16
TS
339 tmp = (int32_t)T0;
340 T0 = (int32_t)T0 + (int32_t)T1;
76e050c2 341 if (((tmp ^ T1 ^ (-1)) & (T0 ^ T1)) >> 31) {
c570fd16 342 /* operands of same sign, result different sign */
4ad40f36 343 CALL_FROM_TB1(do_raise_exception_direct, EXCP_OVERFLOW);
6af0bf9c 344 }
5dc4b744 345 T0 = (int32_t)T0;
6af0bf9c
FB
346 RETURN();
347}
348
349void op_sub (void)
350{
5dc4b744 351 T0 = (int32_t)((int32_t)T0 - (int32_t)T1);
6af0bf9c
FB
352 RETURN();
353}
354
355void op_subo (void)
356{
357 target_ulong tmp;
358
c570fd16 359 tmp = (int32_t)T0;
6af0bf9c 360 T0 = (int32_t)T0 - (int32_t)T1;
76e050c2 361 if (((tmp ^ T1) & (tmp ^ T0)) >> 31) {
c570fd16 362 /* operands of different sign, first operand and result different sign */
4ad40f36 363 CALL_FROM_TB1(do_raise_exception_direct, EXCP_OVERFLOW);
6af0bf9c 364 }
5dc4b744 365 T0 = (int32_t)T0;
6af0bf9c
FB
366 RETURN();
367}
368
369void op_mul (void)
370{
5dc4b744 371 T0 = (int32_t)((int32_t)T0 * (int32_t)T1);
6af0bf9c
FB
372 RETURN();
373}
374
375void op_div (void)
376{
377 if (T1 != 0) {
5dc4b744
TS
378 env->LO = (int32_t)((int32_t)T0 / (int32_t)T1);
379 env->HI = (int32_t)((int32_t)T0 % (int32_t)T1);
6af0bf9c
FB
380 }
381 RETURN();
382}
383
384void op_divu (void)
c570fd16
TS
385{
386 if (T1 != 0) {
5dc4b744
TS
387 env->LO = (int32_t)((uint32_t)T0 / (uint32_t)T1);
388 env->HI = (int32_t)((uint32_t)T0 % (uint32_t)T1);
c570fd16
TS
389 }
390 RETURN();
391}
392
393#ifdef MIPS_HAS_MIPS64
394/* Arithmetic */
395void op_dadd (void)
396{
397 T0 += T1;
398 RETURN();
399}
400
401void op_daddo (void)
402{
403 target_long tmp;
404
405 tmp = T0;
406 T0 += T1;
407 if (((tmp ^ T1 ^ (-1)) & (T0 ^ T1)) >> 63) {
408 /* operands of same sign, result different sign */
409 CALL_FROM_TB1(do_raise_exception_direct, EXCP_OVERFLOW);
410 }
411 RETURN();
412}
413
414void op_dsub (void)
415{
416 T0 -= T1;
417 RETURN();
418}
419
420void op_dsubo (void)
421{
422 target_long tmp;
423
424 tmp = T0;
425 T0 = (int64_t)T0 - (int64_t)T1;
426 if (((tmp ^ T1) & (tmp ^ T0)) >> 63) {
427 /* operands of different sign, first operand and result different sign */
428 CALL_FROM_TB1(do_raise_exception_direct, EXCP_OVERFLOW);
429 }
430 RETURN();
431}
432
433void op_dmul (void)
434{
435 T0 = (int64_t)T0 * (int64_t)T1;
436 RETURN();
437}
438
439#if TARGET_LONG_BITS > HOST_LONG_BITS
440/* Those might call libgcc functions. */
441void op_ddiv (void)
442{
443 do_ddiv();
444 RETURN();
445}
446
447void op_ddivu (void)
448{
449 do_ddivu();
450 RETURN();
451}
452#else
453void op_ddiv (void)
454{
455 if (T1 != 0) {
456 env->LO = (int64_t)T0 / (int64_t)T1;
457 env->HI = (int64_t)T0 % (int64_t)T1;
458 }
459 RETURN();
460}
461
462void op_ddivu (void)
6af0bf9c
FB
463{
464 if (T1 != 0) {
465 env->LO = T0 / T1;
466 env->HI = T0 % T1;
467 }
468 RETURN();
469}
c570fd16
TS
470#endif
471#endif /* MIPS_HAS_MIPS64 */
6af0bf9c
FB
472
473/* Logical */
474void op_and (void)
475{
476 T0 &= T1;
477 RETURN();
478}
479
480void op_nor (void)
481{
482 T0 = ~(T0 | T1);
483 RETURN();
484}
485
486void op_or (void)
487{
488 T0 |= T1;
489 RETURN();
490}
491
492void op_xor (void)
493{
494 T0 ^= T1;
495 RETURN();
496}
497
498void op_sll (void)
499{
5dc4b744 500 T0 = (int32_t)((uint32_t)T0 << (uint32_t)T1);
6af0bf9c
FB
501 RETURN();
502}
503
504void op_sra (void)
505{
5dc4b744 506 T0 = (int32_t)((int32_t)T0 >> (uint32_t)T1);
6af0bf9c
FB
507 RETURN();
508}
509
510void op_srl (void)
511{
5dc4b744 512 T0 = (int32_t)((uint32_t)T0 >> (uint32_t)T1);
6af0bf9c
FB
513 RETURN();
514}
515
7a387fff
TS
516void op_rotr (void)
517{
518 target_ulong tmp;
519
520 if (T1) {
5dc4b744
TS
521 tmp = (int32_t)((uint32_t)T0 << (0x20 - (uint32_t)T1));
522 T0 = (int32_t)((uint32_t)T0 >> (uint32_t)T1) | tmp;
7a387fff
TS
523 } else
524 T0 = T1;
525 RETURN();
526}
527
6af0bf9c
FB
528void op_sllv (void)
529{
5dc4b744 530 T0 = (int32_t)((uint32_t)T1 << ((uint32_t)T0 & 0x1F));
6af0bf9c
FB
531 RETURN();
532}
533
534void op_srav (void)
535{
5dc4b744 536 T0 = (int32_t)((int32_t)T1 >> (T0 & 0x1F));
6af0bf9c
FB
537 RETURN();
538}
539
540void op_srlv (void)
541{
5dc4b744 542 T0 = (int32_t)((uint32_t)T1 >> (T0 & 0x1F));
6af0bf9c
FB
543 RETURN();
544}
545
7a387fff
TS
546void op_rotrv (void)
547{
548 target_ulong tmp;
549
550 T0 &= 0x1F;
551 if (T0) {
5dc4b744
TS
552 tmp = (int32_t)((uint32_t)T1 << (0x20 - T0));
553 T0 = (int32_t)((uint32_t)T1 >> T0) | tmp;
7a387fff
TS
554 } else
555 T0 = T1;
556 RETURN();
557}
558
6af0bf9c
FB
559void op_clo (void)
560{
561 int n;
562
c570fd16 563 if (T0 == ~((target_ulong)0)) {
6af0bf9c
FB
564 T0 = 32;
565 } else {
566 for (n = 0; n < 32; n++) {
567 if (!(T0 & (1 << 31)))
568 break;
569 T0 = T0 << 1;
570 }
571 T0 = n;
572 }
573 RETURN();
574}
575
576void op_clz (void)
577{
578 int n;
579
580 if (T0 == 0) {
581 T0 = 32;
582 } else {
583 for (n = 0; n < 32; n++) {
584 if (T0 & (1 << 31))
585 break;
586 T0 = T0 << 1;
587 }
588 T0 = n;
589 }
590 RETURN();
591}
592
c570fd16
TS
593#ifdef MIPS_HAS_MIPS64
594
595#if TARGET_LONG_BITS > HOST_LONG_BITS
596/* Those might call libgcc functions. */
597void op_dsll (void)
6af0bf9c 598{
c570fd16
TS
599 CALL_FROM_TB0(do_dsll);
600 RETURN();
6af0bf9c
FB
601}
602
c570fd16 603void op_dsll32 (void)
6af0bf9c 604{
c570fd16
TS
605 CALL_FROM_TB0(do_dsll32);
606 RETURN();
6af0bf9c
FB
607}
608
c570fd16 609void op_dsra (void)
6af0bf9c 610{
c570fd16 611 CALL_FROM_TB0(do_dsra);
6af0bf9c
FB
612 RETURN();
613}
614
c570fd16 615void op_dsra32 (void)
6af0bf9c 616{
c570fd16 617 CALL_FROM_TB0(do_dsra32);
6af0bf9c
FB
618 RETURN();
619}
620
c570fd16 621void op_dsrl (void)
6af0bf9c 622{
c570fd16
TS
623 CALL_FROM_TB0(do_dsrl);
624 RETURN();
625}
6af0bf9c 626
c570fd16
TS
627void op_dsrl32 (void)
628{
629 CALL_FROM_TB0(do_dsrl32);
6af0bf9c
FB
630 RETURN();
631}
632
c570fd16 633void op_drotr (void)
6af0bf9c 634{
c570fd16
TS
635 CALL_FROM_TB0(do_drotr);
636 RETURN();
637}
6af0bf9c 638
c570fd16
TS
639void op_drotr32 (void)
640{
641 CALL_FROM_TB0(do_drotr32);
6af0bf9c
FB
642 RETURN();
643}
644
c570fd16 645void op_dsllv (void)
6af0bf9c 646{
c570fd16
TS
647 CALL_FROM_TB0(do_dsllv);
648 RETURN();
649}
6af0bf9c 650
c570fd16
TS
651void op_dsrav (void)
652{
653 CALL_FROM_TB0(do_dsrav);
6af0bf9c
FB
654 RETURN();
655}
656
c570fd16 657void op_dsrlv (void)
6af0bf9c 658{
c570fd16
TS
659 CALL_FROM_TB0(do_dsrlv);
660 RETURN();
661}
6af0bf9c 662
c570fd16
TS
663void op_drotrv (void)
664{
665 CALL_FROM_TB0(do_drotrv);
6af0bf9c
FB
666 RETURN();
667}
c570fd16
TS
668
669#else /* TARGET_LONG_BITS > HOST_LONG_BITS */
670
671void op_dsll (void)
672{
673 T0 = T0 << T1;
674 RETURN();
675}
676
677void op_dsll32 (void)
678{
679 T0 = T0 << (T1 + 32);
680 RETURN();
681}
682
683void op_dsra (void)
684{
685 T0 = (int64_t)T0 >> T1;
686 RETURN();
687}
688
689void op_dsra32 (void)
690{
691 T0 = (int64_t)T0 >> (T1 + 32);
692 RETURN();
693}
694
695void op_dsrl (void)
696{
697 T0 = T0 >> T1;
698 RETURN();
699}
700
701void op_dsrl32 (void)
702{
703 T0 = T0 >> (T1 + 32);
704 RETURN();
705}
706
707void op_drotr (void)
708{
709 target_ulong tmp;
710
711 if (T1) {
712 tmp = T0 << (0x40 - T1);
713 T0 = (T0 >> T1) | tmp;
714 } else
715 T0 = T1;
716 RETURN();
717}
718
719void op_drotr32 (void)
720{
721 target_ulong tmp;
722
723 if (T1) {
724 tmp = T0 << (0x40 - (32 + T1));
725 T0 = (T0 >> (32 + T1)) | tmp;
726 } else
727 T0 = T1;
728 RETURN();
729}
730
731void op_dsllv (void)
732{
733 T0 = T1 << (T0 & 0x3F);
734 RETURN();
735}
736
737void op_dsrav (void)
738{
739 T0 = (int64_t)T1 >> (T0 & 0x3F);
740 RETURN();
741}
742
743void op_dsrlv (void)
744{
745 T0 = T1 >> (T0 & 0x3F);
746 RETURN();
747}
748
749void op_drotrv (void)
750{
751 target_ulong tmp;
752
753 T0 &= 0x3F;
754 if (T0) {
755 tmp = T1 << (0x40 - T0);
756 T0 = (T1 >> T0) | tmp;
757 } else
758 T0 = T1;
759 RETURN();
760}
761#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
762
763void op_dclo (void)
764{
765 int n;
766
767 if (T0 == ~((target_ulong)0)) {
768 T0 = 64;
769 } else {
770 for (n = 0; n < 64; n++) {
771 if (!(T0 & (1ULL << 63)))
772 break;
773 T0 = T0 << 1;
774 }
775 T0 = n;
776 }
777 RETURN();
778}
779
780void op_dclz (void)
781{
782 int n;
783
784 if (T0 == 0) {
785 T0 = 64;
786 } else {
787 for (n = 0; n < 64; n++) {
788 if (T0 & (1ULL << 63))
789 break;
790 T0 = T0 << 1;
791 }
792 T0 = n;
793 }
794 RETURN();
795}
796#endif
797
798/* 64 bits arithmetic */
799#if TARGET_LONG_BITS > HOST_LONG_BITS
6af0bf9c
FB
800void op_mult (void)
801{
802 CALL_FROM_TB0(do_mult);
803 RETURN();
804}
805
806void op_multu (void)
807{
808 CALL_FROM_TB0(do_multu);
809 RETURN();
810}
811
812void op_madd (void)
813{
814 CALL_FROM_TB0(do_madd);
815 RETURN();
816}
817
818void op_maddu (void)
819{
820 CALL_FROM_TB0(do_maddu);
821 RETURN();
822}
823
824void op_msub (void)
825{
826 CALL_FROM_TB0(do_msub);
827 RETURN();
828}
829
830void op_msubu (void)
831{
832 CALL_FROM_TB0(do_msubu);
833 RETURN();
834}
c570fd16
TS
835
836#else /* TARGET_LONG_BITS > HOST_LONG_BITS */
837
838static inline uint64_t get_HILO (void)
839{
840 return ((uint64_t)env->HI << 32) | ((uint64_t)(uint32_t)env->LO);
841}
842
843static inline void set_HILO (uint64_t HILO)
844{
5dc4b744
TS
845 env->LO = (int32_t)(HILO & 0xFFFFFFFF);
846 env->HI = (int32_t)(HILO >> 32);
c570fd16
TS
847}
848
849void op_mult (void)
850{
851 set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
852 RETURN();
853}
854
855void op_multu (void)
856{
857 set_HILO((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
858 RETURN();
859}
860
861void op_madd (void)
862{
863 int64_t tmp;
864
865 tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
866 set_HILO((int64_t)get_HILO() + tmp);
867 RETURN();
868}
869
870void op_maddu (void)
871{
872 uint64_t tmp;
873
874 tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
875 set_HILO(get_HILO() + tmp);
876 RETURN();
877}
878
879void op_msub (void)
880{
881 int64_t tmp;
882
883 tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
884 set_HILO((int64_t)get_HILO() - tmp);
885 RETURN();
886}
887
888void op_msubu (void)
889{
890 uint64_t tmp;
891
892 tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
893 set_HILO(get_HILO() - tmp);
894 RETURN();
895}
896#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
897
898#ifdef MIPS_HAS_MIPS64
899void op_dmult (void)
900{
901 CALL_FROM_TB0(do_dmult);
902 RETURN();
903}
904
905void op_dmultu (void)
906{
907 CALL_FROM_TB0(do_dmultu);
908 RETURN();
909}
6af0bf9c
FB
910#endif
911
912/* Conditional moves */
913void op_movn (void)
914{
915 if (T1 != 0)
916 env->gpr[PARAM1] = T0;
917 RETURN();
918}
919
920void op_movz (void)
921{
922 if (T1 == 0)
923 env->gpr[PARAM1] = T0;
924 RETURN();
925}
926
71fb7241 927#ifdef MIPS_USES_FPU
7a387fff
TS
928void op_movf (void)
929{
930 if (!(env->fcr31 & PARAM1))
931 env->gpr[PARAM2] = env->gpr[PARAM3];
932 RETURN();
933}
934
935void op_movt (void)
936{
937 if (env->fcr31 & PARAM1)
938 env->gpr[PARAM2] = env->gpr[PARAM3];
939 RETURN();
940}
71fb7241 941#endif
7a387fff 942
6af0bf9c
FB
943/* Tests */
944#define OP_COND(name, cond) \
945void glue(op_, name) (void) \
946{ \
947 if (cond) { \
948 T0 = 1; \
949 } else { \
950 T0 = 0; \
951 } \
952 RETURN(); \
953}
954
955OP_COND(eq, T0 == T1);
956OP_COND(ne, T0 != T1);
957OP_COND(ge, (int32_t)T0 >= (int32_t)T1);
958OP_COND(geu, T0 >= T1);
959OP_COND(lt, (int32_t)T0 < (int32_t)T1);
960OP_COND(ltu, T0 < T1);
961OP_COND(gez, (int32_t)T0 >= 0);
962OP_COND(gtz, (int32_t)T0 > 0);
963OP_COND(lez, (int32_t)T0 <= 0);
964OP_COND(ltz, (int32_t)T0 < 0);
965
7a387fff 966/* Branches */
6af0bf9c 967//#undef USE_DIRECT_JUMP
c53be334
FB
968
969void OPPROTO op_goto_tb0(void)
970{
971 GOTO_TB(op_goto_tb0, PARAM1, 0);
7a387fff 972 RETURN();
c53be334
FB
973}
974
975void OPPROTO op_goto_tb1(void)
976{
977 GOTO_TB(op_goto_tb1, PARAM1, 1);
7a387fff 978 RETURN();
c53be334 979}
6af0bf9c
FB
980
981/* Branch to register */
982void op_save_breg_target (void)
983{
984 env->btarget = T2;
7a387fff 985 RETURN();
6af0bf9c
FB
986}
987
988void op_restore_breg_target (void)
989{
990 T2 = env->btarget;
7a387fff 991 RETURN();
6af0bf9c
FB
992}
993
994void op_breg (void)
995{
996 env->PC = T2;
997 RETURN();
998}
999
6af0bf9c
FB
1000void op_save_btarget (void)
1001{
1002 env->btarget = PARAM1;
1003 RETURN();
1004}
1005
1006/* Conditional branch */
1007void op_set_bcond (void)
1008{
1009 T2 = T0;
1010 RETURN();
1011}
1012
1013void op_save_bcond (void)
1014{
1015 env->bcond = T2;
1016 RETURN();
1017}
1018
1019void op_restore_bcond (void)
1020{
1021 T2 = env->bcond;
1022 RETURN();
1023}
1024
c53be334 1025void op_jnz_T2 (void)
6af0bf9c 1026{
c53be334
FB
1027 if (T2)
1028 GOTO_LABEL_PARAM(1);
6af0bf9c
FB
1029 RETURN();
1030}
1031
1032/* CP0 functions */
873eb012 1033void op_mfc0_index (void)
6af0bf9c 1034{
9c2149c8 1035 T0 = env->CP0_Index;
873eb012
TS
1036 RETURN();
1037}
1038
1039void op_mfc0_random (void)
1040{
1041 CALL_FROM_TB0(do_mfc0_random);
1042 RETURN();
1043}
1044
1045void op_mfc0_entrylo0 (void)
1046{
9c2149c8 1047 T0 = (int32_t)env->CP0_EntryLo0;
873eb012
TS
1048 RETURN();
1049}
1050
1051void op_mfc0_entrylo1 (void)
1052{
9c2149c8 1053 T0 = (int32_t)env->CP0_EntryLo1;
873eb012
TS
1054 RETURN();
1055}
1056
1057void op_mfc0_context (void)
1058{
9c2149c8 1059 T0 = (int32_t)env->CP0_Context;
873eb012
TS
1060 RETURN();
1061}
1062
1063void op_mfc0_pagemask (void)
1064{
9c2149c8 1065 T0 = env->CP0_PageMask;
873eb012
TS
1066 RETURN();
1067}
1068
7a387fff
TS
1069void op_mfc0_pagegrain (void)
1070{
9c2149c8 1071 T0 = env->CP0_PageGrain;
7a387fff
TS
1072 RETURN();
1073}
1074
873eb012
TS
1075void op_mfc0_wired (void)
1076{
9c2149c8 1077 T0 = env->CP0_Wired;
873eb012
TS
1078 RETURN();
1079}
1080
7a387fff
TS
1081void op_mfc0_hwrena (void)
1082{
9c2149c8 1083 T0 = env->CP0_HWREna;
7a387fff
TS
1084 RETURN();
1085}
1086
873eb012
TS
1087void op_mfc0_badvaddr (void)
1088{
9c2149c8 1089 T0 = (int32_t)env->CP0_BadVAddr;
873eb012
TS
1090 RETURN();
1091}
1092
1093void op_mfc0_count (void)
1094{
1095 CALL_FROM_TB0(do_mfc0_count);
1096 RETURN();
1097}
1098
1099void op_mfc0_entryhi (void)
1100{
9c2149c8 1101 T0 = (int32_t)env->CP0_EntryHi;
873eb012
TS
1102 RETURN();
1103}
1104
1105void op_mfc0_compare (void)
1106{
9c2149c8 1107 T0 = env->CP0_Compare;
873eb012
TS
1108 RETURN();
1109}
1110
1111void op_mfc0_status (void)
1112{
9c2149c8 1113 T0 = env->CP0_Status;
873eb012
TS
1114 if (env->hflags & MIPS_HFLAG_UM)
1115 T0 |= (1 << CP0St_UM);
1116 if (env->hflags & MIPS_HFLAG_ERL)
1117 T0 |= (1 << CP0St_ERL);
1118 if (env->hflags & MIPS_HFLAG_EXL)
1119 T0 |= (1 << CP0St_EXL);
1120 RETURN();
1121}
1122
7a387fff
TS
1123void op_mfc0_intctl (void)
1124{
9c2149c8 1125 T0 = env->CP0_IntCtl;
7a387fff
TS
1126 RETURN();
1127}
1128
1129void op_mfc0_srsctl (void)
1130{
9c2149c8
TS
1131 T0 = env->CP0_SRSCtl;
1132 RETURN();
1133}
1134
1135void op_mfc0_srsmap (void)
1136{
1137 T0 = env->CP0_SRSMap;
7a387fff
TS
1138 RETURN();
1139}
1140
873eb012
TS
1141void op_mfc0_cause (void)
1142{
9c2149c8 1143 T0 = env->CP0_Cause;
873eb012
TS
1144 RETURN();
1145}
1146
1147void op_mfc0_epc (void)
1148{
9c2149c8 1149 T0 = (int32_t)env->CP0_EPC;
873eb012
TS
1150 RETURN();
1151}
1152
1153void op_mfc0_prid (void)
1154{
9c2149c8 1155 T0 = env->CP0_PRid;
873eb012
TS
1156 RETURN();
1157}
1158
7a387fff
TS
1159void op_mfc0_ebase (void)
1160{
b29a0341 1161 T0 = env->CP0_EBase;
7a387fff
TS
1162 RETURN();
1163}
1164
873eb012
TS
1165void op_mfc0_config0 (void)
1166{
9c2149c8 1167 T0 = env->CP0_Config0;
873eb012
TS
1168 RETURN();
1169}
1170
1171void op_mfc0_config1 (void)
1172{
9c2149c8 1173 T0 = env->CP0_Config1;
873eb012
TS
1174 RETURN();
1175}
1176
7a387fff
TS
1177void op_mfc0_config2 (void)
1178{
9c2149c8 1179 T0 = env->CP0_Config2;
7a387fff
TS
1180 RETURN();
1181}
1182
1183void op_mfc0_config3 (void)
1184{
9c2149c8 1185 T0 = env->CP0_Config3;
7a387fff
TS
1186 RETURN();
1187}
1188
873eb012
TS
1189void op_mfc0_lladdr (void)
1190{
9c2149c8 1191 T0 = (int32_t)env->CP0_LLAddr >> 4;
873eb012
TS
1192 RETURN();
1193}
1194
7a387fff 1195void op_mfc0_watchlo0 (void)
873eb012 1196{
5dc4b744 1197 T0 = (int32_t)env->CP0_WatchLo;
873eb012
TS
1198 RETURN();
1199}
1200
7a387fff 1201void op_mfc0_watchhi0 (void)
873eb012 1202{
9c2149c8 1203 T0 = env->CP0_WatchHi;
873eb012
TS
1204 RETURN();
1205}
1206
7a387fff
TS
1207void op_mfc0_xcontext (void)
1208{
9c2149c8 1209 T0 = (int32_t)env->CP0_XContext;
7a387fff
TS
1210 RETURN();
1211}
1212
1213void op_mfc0_framemask (void)
1214{
1215 T0 = env->CP0_Framemask;
1216 RETURN();
1217}
1218
873eb012
TS
1219void op_mfc0_debug (void)
1220{
9c2149c8 1221 T0 = env->CP0_Debug;
873eb012
TS
1222 if (env->hflags & MIPS_HFLAG_DM)
1223 T0 |= 1 << CP0DB_DM;
1224 RETURN();
1225}
1226
1227void op_mfc0_depc (void)
1228{
9c2149c8 1229 T0 = (int32_t)env->CP0_DEPC;
873eb012
TS
1230 RETURN();
1231}
1232
7a387fff
TS
1233void op_mfc0_performance0 (void)
1234{
9c2149c8 1235 T0 = env->CP0_Performance0;
7a387fff
TS
1236 RETURN();
1237}
1238
873eb012
TS
1239void op_mfc0_taglo (void)
1240{
9c2149c8 1241 T0 = env->CP0_TagLo;
873eb012
TS
1242 RETURN();
1243}
1244
1245void op_mfc0_datalo (void)
1246{
9c2149c8 1247 T0 = env->CP0_DataLo;
873eb012
TS
1248 RETURN();
1249}
1250
7a387fff
TS
1251void op_mfc0_taghi (void)
1252{
9c2149c8 1253 T0 = env->CP0_TagHi;
7a387fff
TS
1254 RETURN();
1255}
1256
1257void op_mfc0_datahi (void)
1258{
9c2149c8 1259 T0 = env->CP0_DataHi;
7a387fff
TS
1260 RETURN();
1261}
1262
873eb012
TS
1263void op_mfc0_errorepc (void)
1264{
9c2149c8 1265 T0 = (int32_t)env->CP0_ErrorEPC;
873eb012
TS
1266 RETURN();
1267}
1268
1269void op_mfc0_desave (void)
1270{
9c2149c8 1271 T0 = env->CP0_DESAVE;
6af0bf9c
FB
1272 RETURN();
1273}
1274
8c0fdd85 1275void op_mtc0_index (void)
6af0bf9c 1276{
9c2149c8 1277 env->CP0_Index = (env->CP0_Index & 0x80000000) | (T0 & (MIPS_TLB_NB - 1));
8c0fdd85
TS
1278 RETURN();
1279}
1280
1281void op_mtc0_entrylo0 (void)
1282{
7a387fff
TS
1283 /* Large physaddr not implemented */
1284 /* 1k pages not implemented */
9c2149c8 1285 env->CP0_EntryLo0 = (int32_t)T0 & 0x3FFFFFFF;
8c0fdd85
TS
1286 RETURN();
1287}
1288
1289void op_mtc0_entrylo1 (void)
1290{
7a387fff
TS
1291 /* Large physaddr not implemented */
1292 /* 1k pages not implemented */
9c2149c8 1293 env->CP0_EntryLo1 = (int32_t)T0 & 0x3FFFFFFF;
8c0fdd85
TS
1294 RETURN();
1295}
1296
1297void op_mtc0_context (void)
1298{
7a387fff 1299 env->CP0_Context = (env->CP0_Context & ~0x007FFFFF) | (T0 & 0x007FFFF0);
8c0fdd85
TS
1300 RETURN();
1301}
1302
1303void op_mtc0_pagemask (void)
1304{
7a387fff
TS
1305 /* 1k pages not implemented */
1306 env->CP0_PageMask = T0 & 0x1FFFE000;
1307 RETURN();
1308}
1309
1310void op_mtc0_pagegrain (void)
1311{
1312 /* SmartMIPS not implemented */
1313 /* Large physaddr not implemented */
1314 /* 1k pages not implemented */
1315 env->CP0_PageGrain = 0;
8c0fdd85
TS
1316 RETURN();
1317}
1318
1319void op_mtc0_wired (void)
1320{
7a387fff
TS
1321 env->CP0_Wired = T0 & (MIPS_TLB_NB - 1);
1322 RETURN();
1323}
1324
1325void op_mtc0_hwrena (void)
1326{
1327 env->CP0_HWREna = T0 & 0x0000000F;
8c0fdd85
TS
1328 RETURN();
1329}
1330
1331void op_mtc0_count (void)
1332{
1333 CALL_FROM_TB2(cpu_mips_store_count, env, T0);
1334 RETURN();
1335}
1336
1337void op_mtc0_entryhi (void)
1338{
0feef828 1339 target_ulong old, val;
8c0fdd85 1340
7a387fff
TS
1341 /* 1k pages not implemented */
1342 /* Ignore MIPS64 TLB for now */
9c2149c8 1343 val = (int32_t)T0 & 0xFFFFE0FF;
8c0fdd85
TS
1344 old = env->CP0_EntryHi;
1345 env->CP0_EntryHi = val;
1346 /* If the ASID changes, flush qemu's TLB. */
1347 if ((old & 0xFF) != (val & 0xFF))
1348 CALL_FROM_TB2(cpu_mips_tlb_flush, env, 1);
1349 RETURN();
1350}
1351
1352void op_mtc0_compare (void)
1353{
1354 CALL_FROM_TB2(cpu_mips_store_compare, env, T0);
1355 RETURN();
1356}
1357
1358void op_mtc0_status (void)
1359{
4de9b249 1360 uint32_t val, old;
8c0fdd85 1361
9c2149c8 1362 val = (int32_t)T0 & 0xFA78FF01;
8c0fdd85
TS
1363 old = env->CP0_Status;
1364 if (T0 & (1 << CP0St_UM))
1365 env->hflags |= MIPS_HFLAG_UM;
1366 else
1367 env->hflags &= ~MIPS_HFLAG_UM;
1368 if (T0 & (1 << CP0St_ERL))
1369 env->hflags |= MIPS_HFLAG_ERL;
1370 else
1371 env->hflags &= ~MIPS_HFLAG_ERL;
1372 if (T0 & (1 << CP0St_EXL))
1373 env->hflags |= MIPS_HFLAG_EXL;
1374 else
1375 env->hflags &= ~MIPS_HFLAG_EXL;
1376 env->CP0_Status = val;
8c0fdd85
TS
1377 if (loglevel & CPU_LOG_TB_IN_ASM)
1378 CALL_FROM_TB2(do_mtc0_status_debug, old, val);
4de9b249 1379 CALL_FROM_TB1(cpu_mips_update_irq, env);
8c0fdd85
TS
1380 RETURN();
1381}
1382
7a387fff
TS
1383void op_mtc0_intctl (void)
1384{
1385 /* vectored interrupts not implemented */
1386 env->CP0_IntCtl = 0;
1387 RETURN();
1388}
1389
1390void op_mtc0_srsctl (void)
1391{
1392 /* shadow registers not implemented */
1393 env->CP0_SRSCtl = 0;
1394 RETURN();
1395}
1396
9c2149c8
TS
1397void op_mtc0_srsmap (void)
1398{
1399 /* shadow registers not implemented */
1400 env->CP0_SRSMap = 0;
1401 RETURN();
1402}
1403
8c0fdd85
TS
1404void op_mtc0_cause (void)
1405{
4de9b249 1406 env->CP0_Cause = (env->CP0_Cause & 0xB000F87C) | (T0 & 0x00C00300);
8c0fdd85 1407
4de9b249
TS
1408 /* Handle the software interrupt as an hardware one, as they
1409 are very similar */
1410 if (T0 & CP0Ca_IP_mask) {
1411 CALL_FROM_TB1(cpu_mips_update_irq, env);
8c0fdd85 1412 }
8c0fdd85
TS
1413 RETURN();
1414}
1415
1416void op_mtc0_epc (void)
1417{
9c2149c8 1418 env->CP0_EPC = (int32_t)T0;
8c0fdd85
TS
1419 RETURN();
1420}
1421
7a387fff
TS
1422void op_mtc0_ebase (void)
1423{
1424 /* vectored interrupts not implemented */
1425 /* Multi-CPU not implemented */
b29a0341 1426 env->CP0_EBase = 0x80000000 | (T0 & 0x3FFFF000);
7a387fff
TS
1427 RETURN();
1428}
1429
8c0fdd85
TS
1430void op_mtc0_config0 (void)
1431{
1432#if defined(MIPS_USES_R4K_TLB)
7a387fff
TS
1433 /* Fixed mapping MMU not implemented */
1434 env->CP0_Config0 = (env->CP0_Config0 & 0x8017FF88) | (T0 & 0x00000001);
8c0fdd85 1435#else
7a387fff 1436 env->CP0_Config0 = (env->CP0_Config0 & 0xFE17FF88) | (T0 & 0x00000001);
8c0fdd85
TS
1437#endif
1438 RETURN();
1439}
1440
7a387fff
TS
1441void op_mtc0_config2 (void)
1442{
1443 /* tertiary/secondary caches not implemented */
1444 env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF);
1445 RETURN();
1446}
1447
1448void op_mtc0_watchlo0 (void)
8c0fdd85 1449{
9c2149c8 1450 env->CP0_WatchLo = (int32_t)T0;
8c0fdd85
TS
1451 RETURN();
1452}
1453
7a387fff 1454void op_mtc0_watchhi0 (void)
8c0fdd85
TS
1455{
1456 env->CP0_WatchHi = T0 & 0x40FF0FF8;
1457 RETURN();
1458}
1459
7a387fff
TS
1460void op_mtc0_xcontext (void)
1461{
9c2149c8 1462 env->CP0_XContext = (int32_t)T0; /* XXX */
7a387fff
TS
1463 RETURN();
1464}
1465
1466void op_mtc0_framemask (void)
1467{
1468 env->CP0_Framemask = T0; /* XXX */
1469 RETURN();
1470}
1471
8c0fdd85
TS
1472void op_mtc0_debug (void)
1473{
1474 env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120);
1475 if (T0 & (1 << CP0DB_DM))
1476 env->hflags |= MIPS_HFLAG_DM;
1477 else
1478 env->hflags &= ~MIPS_HFLAG_DM;
1479 RETURN();
1480}
1481
1482void op_mtc0_depc (void)
1483{
9c2149c8 1484 env->CP0_DEPC = (int32_t)T0;
8c0fdd85
TS
1485 RETURN();
1486}
1487
7a387fff
TS
1488void op_mtc0_performance0 (void)
1489{
1490 env->CP0_Performance0 = T0; /* XXX */
1491 RETURN();
1492}
1493
8c0fdd85
TS
1494void op_mtc0_taglo (void)
1495{
9c2149c8 1496 env->CP0_TagLo = T0 & 0xFFFFFCF6;
8c0fdd85
TS
1497 RETURN();
1498}
1499
7a387fff
TS
1500void op_mtc0_datalo (void)
1501{
1502 env->CP0_DataLo = T0; /* XXX */
1503 RETURN();
1504}
1505
1506void op_mtc0_taghi (void)
1507{
1508 env->CP0_TagHi = T0; /* XXX */
1509 RETURN();
1510}
1511
1512void op_mtc0_datahi (void)
1513{
1514 env->CP0_DataHi = T0; /* XXX */
1515 RETURN();
1516}
1517
8c0fdd85
TS
1518void op_mtc0_errorepc (void)
1519{
9c2149c8 1520 env->CP0_ErrorEPC = (int32_t)T0;
8c0fdd85
TS
1521 RETURN();
1522}
1523
1524void op_mtc0_desave (void)
1525{
1526 env->CP0_DESAVE = T0;
6af0bf9c
FB
1527 RETURN();
1528}
1529
9c2149c8
TS
1530void op_dmfc0_entrylo0 (void)
1531{
1532 T0 = env->CP0_EntryLo0;
1533 RETURN();
1534}
1535
1536void op_dmfc0_entrylo1 (void)
1537{
1538 T0 = env->CP0_EntryLo1;
1539 RETURN();
1540}
1541
1542void op_dmfc0_context (void)
1543{
1544 T0 = env->CP0_Context;
1545 RETURN();
1546}
1547
1548void op_dmfc0_badvaddr (void)
1549{
1550 T0 = env->CP0_BadVAddr;
1551 RETURN();
1552}
1553
1554void op_dmfc0_entryhi (void)
1555{
1556 T0 = env->CP0_EntryHi;
1557 RETURN();
1558}
1559
1560void op_dmfc0_epc (void)
1561{
1562 T0 = env->CP0_EPC;
1563 RETURN();
1564}
1565
9c2149c8
TS
1566void op_dmfc0_lladdr (void)
1567{
1568 T0 = env->CP0_LLAddr >> 4;
1569 RETURN();
1570}
1571
1572void op_dmfc0_watchlo0 (void)
1573{
1574 T0 = env->CP0_WatchLo;
1575 RETURN();
1576}
1577
1578void op_dmfc0_xcontext (void)
1579{
1580 T0 = env->CP0_XContext;
1581 RETURN();
1582}
1583
1584void op_dmfc0_depc (void)
1585{
1586 T0 = env->CP0_DEPC;
1587 RETURN();
1588}
1589
1590void op_dmfc0_errorepc (void)
1591{
1592 T0 = env->CP0_ErrorEPC;
1593 RETURN();
1594}
1595
1596void op_dmtc0_entrylo0 (void)
1597{
1598 /* Large physaddr not implemented */
1599 /* 1k pages not implemented */
1600 env->CP0_EntryLo0 = T0 & 0x3FFFFFFF;
1601 RETURN();
1602}
1603
1604void op_dmtc0_entrylo1 (void)
1605{
1606 /* Large physaddr not implemented */
1607 /* 1k pages not implemented */
1608 env->CP0_EntryLo1 = T0 & 0x3FFFFFFF;
1609 RETURN();
1610}
1611
1612void op_dmtc0_context (void)
1613{
1614 env->CP0_Context = (env->CP0_Context & ~0x007FFFFF) | (T0 & 0x007FFFF0);
1615 RETURN();
1616}
1617
1618void op_dmtc0_epc (void)
1619{
1620 env->CP0_EPC = T0;
1621 RETURN();
1622}
1623
9c2149c8
TS
1624void op_dmtc0_watchlo0 (void)
1625{
1626 env->CP0_WatchLo = T0;
1627 RETURN();
1628}
1629
1630void op_dmtc0_xcontext (void)
1631{
1632 env->CP0_XContext = T0; /* XXX */
1633 RETURN();
1634}
1635
1636void op_dmtc0_depc (void)
1637{
1638 env->CP0_DEPC = T0;
1639 RETURN();
1640}
1641
1642void op_dmtc0_errorepc (void)
1643{
1644 env->CP0_ErrorEPC = T0;
1645 RETURN();
1646}
1647
6ea83fed
FB
1648#ifdef MIPS_USES_FPU
1649
1650#if 0
1651# define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env)
1652#else
1653# define DEBUG_FPU_STATE() do { } while(0)
1654#endif
1655
1656void op_cp1_enabled(void)
1657{
1658 if (!(env->CP0_Status & (1 << CP0St_CU1))) {
1659 CALL_FROM_TB2(do_raise_exception_err, EXCP_CpU, 1);
1660 }
1661 RETURN();
1662}
1663
1664/* CP1 functions */
1665void op_cfc1 (void)
1666{
1667 if (T1 == 0) {
1668 T0 = env->fcr0;
1669 }
1670 else {
1671 /* fetch fcr31, masking unused bits */
1672 T0 = env->fcr31 & 0x0183FFFF;
1673 }
1674 DEBUG_FPU_STATE();
1675 RETURN();
1676}
1677
1678/* convert MIPS rounding mode in FCR31 to IEEE library */
1679unsigned int ieee_rm[] = {
1680 float_round_nearest_even,
1681 float_round_to_zero,
1682 float_round_up,
1683 float_round_down
1684};
1685
1686#define RESTORE_ROUNDING_MODE \
1687 set_float_rounding_mode(ieee_rm[env->fcr31 & 3], &env->fp_status)
1688
1689void op_ctc1 (void)
1690{
1691 if (T1 == 0) {
1692 /* XXX should this throw an exception?
1693 * don't write to FCR0.
1694 * env->fcr0 = T0;
1695 */
1696 }
1697 else {
1698 /* store new fcr31, masking unused bits */
1699 env->fcr31 = T0 & 0x0183FFFF;
1700
1701 /* set rounding mode */
1702 RESTORE_ROUNDING_MODE;
1703
1704#ifndef CONFIG_SOFTFLOAT
1705 /* no floating point exception for native float */
1706 SET_FP_ENABLE(env->fcr31, 0);
1707#endif
1708 }
1709 DEBUG_FPU_STATE();
1710 RETURN();
1711}
1712
1713void op_mfc1 (void)
1714{
1715 T0 = WT0;
1716 DEBUG_FPU_STATE();
1717 RETURN();
1718}
1719
1720void op_mtc1 (void)
1721{
1722 WT0 = T0;
1723 DEBUG_FPU_STATE();
1724 RETURN();
1725}
1726
1727/* Float support.
1728 Single precition routines have a "s" suffix, double precision a
1729 "d" suffix. */
1730
1731#define FLOAT_OP(name, p) void OPPROTO op_float_##name##_##p(void)
1732
dd016883
FB
1733FLOAT_OP(cvtd, s)
1734{
1735 FDT2 = float32_to_float64(WT0, &env->fp_status);
1736 DEBUG_FPU_STATE();
1737 RETURN();
1738}
6ea83fed
FB
1739FLOAT_OP(cvtd, w)
1740{
1741 FDT2 = int32_to_float64(WT0, &env->fp_status);
1742 DEBUG_FPU_STATE();
1743 RETURN();
1744}
dd016883
FB
1745FLOAT_OP(cvts, d)
1746{
417f38f0 1747 FST2 = float64_to_float32(FDT0, &env->fp_status);
dd016883
FB
1748 DEBUG_FPU_STATE();
1749 RETURN();
1750}
6ea83fed
FB
1751FLOAT_OP(cvts, w)
1752{
1753 FST2 = int32_to_float32(WT0, &env->fp_status);
1754 DEBUG_FPU_STATE();
1755 RETURN();
1756}
1757FLOAT_OP(cvtw, s)
1758{
1759 WT2 = float32_to_int32(FST0, &env->fp_status);
1760 DEBUG_FPU_STATE();
1761 RETURN();
1762}
1763FLOAT_OP(cvtw, d)
1764{
1765 WT2 = float64_to_int32(FDT0, &env->fp_status);
1766 DEBUG_FPU_STATE();
1767 RETURN();
1768}
1769
1770FLOAT_OP(roundw, d)
1771{
1772 set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
1773 WT2 = float64_round_to_int(FDT0, &env->fp_status);
1774 RESTORE_ROUNDING_MODE;
1775
1776 DEBUG_FPU_STATE();
1777 RETURN();
1778}
1779FLOAT_OP(roundw, s)
1780{
1781 set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
1782 WT2 = float32_round_to_int(FST0, &env->fp_status);
1783 RESTORE_ROUNDING_MODE;
1784 DEBUG_FPU_STATE();
1785 RETURN();
1786}
1787
1788FLOAT_OP(truncw, d)
1789{
1790 WT2 = float64_to_int32_round_to_zero(FDT0, &env->fp_status);
1791 DEBUG_FPU_STATE();
1792 RETURN();
1793}
1794FLOAT_OP(truncw, s)
1795{
1796 WT2 = float32_to_int32_round_to_zero(FST0, &env->fp_status);
1797 DEBUG_FPU_STATE();
1798 RETURN();
1799}
1800
1801FLOAT_OP(ceilw, d)
1802{
1803 set_float_rounding_mode(float_round_up, &env->fp_status);
1804 WT2 = float64_round_to_int(FDT0, &env->fp_status);
1805 RESTORE_ROUNDING_MODE;
1806
1807 DEBUG_FPU_STATE();
1808 RETURN();
1809}
1810FLOAT_OP(ceilw, s)
1811{
1812 set_float_rounding_mode(float_round_up, &env->fp_status);
1813 WT2 = float32_round_to_int(FST0, &env->fp_status);
1814 RESTORE_ROUNDING_MODE;
1815 DEBUG_FPU_STATE();
1816 RETURN();
1817}
1818
1819FLOAT_OP(floorw, d)
1820{
1821 set_float_rounding_mode(float_round_down, &env->fp_status);
1822 WT2 = float64_round_to_int(FDT0, &env->fp_status);
1823 RESTORE_ROUNDING_MODE;
1824
1825 DEBUG_FPU_STATE();
1826 RETURN();
1827}
1828FLOAT_OP(floorw, s)
1829{
1830 set_float_rounding_mode(float_round_down, &env->fp_status);
1831 WT2 = float32_round_to_int(FST0, &env->fp_status);
1832 RESTORE_ROUNDING_MODE;
1833 DEBUG_FPU_STATE();
1834 RETURN();
1835}
1836
1837/* binary operations */
1838#define FLOAT_BINOP(name) \
1839FLOAT_OP(name, d) \
1840{ \
1841 FDT2 = float64_ ## name (FDT0, FDT1, &env->fp_status); \
1842 DEBUG_FPU_STATE(); \
1843} \
1844FLOAT_OP(name, s) \
1845{ \
1846 FST2 = float32_ ## name (FST0, FST1, &env->fp_status); \
1847 DEBUG_FPU_STATE(); \
1848}
1849FLOAT_BINOP(add)
1850FLOAT_BINOP(sub)
1851FLOAT_BINOP(mul)
1852FLOAT_BINOP(div)
1853#undef FLOAT_BINOP
1854
1855/* unary operations, modifying fp status */
1856#define FLOAT_UNOP(name) \
1857FLOAT_OP(name, d) \
1858{ \
1859 FDT2 = float64_ ## name(FDT0, &env->fp_status); \
1860 DEBUG_FPU_STATE(); \
1861} \
1862FLOAT_OP(name, s) \
1863{ \
1864 FST2 = float32_ ## name(FST0, &env->fp_status); \
1865 DEBUG_FPU_STATE(); \
1866}
1867FLOAT_UNOP(sqrt)
1868#undef FLOAT_UNOP
1869
1870/* unary operations, not modifying fp status */
1871#define FLOAT_UNOP(name) \
1872FLOAT_OP(name, d) \
1873{ \
1874 FDT2 = float64_ ## name(FDT0); \
1875 DEBUG_FPU_STATE(); \
1876} \
1877FLOAT_OP(name, s) \
1878{ \
1879 FST2 = float32_ ## name(FST0); \
1880 DEBUG_FPU_STATE(); \
1881}
1882FLOAT_UNOP(abs)
1883FLOAT_UNOP(chs)
1884#undef FLOAT_UNOP
1885
1886FLOAT_OP(mov, d)
1887{
1888 FDT2 = FDT0;
1889 DEBUG_FPU_STATE();
1890 RETURN();
1891}
1892FLOAT_OP(mov, s)
1893{
1894 FST2 = FST0;
1895 DEBUG_FPU_STATE();
1896 RETURN();
1897}
1898
1899#ifdef CONFIG_SOFTFLOAT
1900#define clear_invalid() do { \
1901 int flags = get_float_exception_flags(&env->fp_status); \
1902 flags &= ~float_flag_invalid; \
1903 set_float_exception_flags(flags, &env->fp_status); \
1904} while(0)
1905#else
1906#define clear_invalid() do { } while(0)
1907#endif
1908
1909extern void dump_fpu_s(CPUState *env);
1910
1911#define FOP_COND(fmt, op, sig, cond) \
1912void op_cmp_ ## fmt ## _ ## op (void) \
1913{ \
1914 if (cond) \
1915 SET_FP_COND(env->fcr31); \
1916 else \
1917 CLEAR_FP_COND(env->fcr31); \
1918 if (!sig) \
1919 clear_invalid(); \
1920 /*CALL_FROM_TB1(dump_fpu_s, env);*/ \
1921 DEBUG_FPU_STATE(); \
1922 RETURN(); \
1923}
1924
569f5d66 1925int float64_is_unordered(float64 a, float64 b STATUS_PARAM)
6ea83fed 1926{
6ea83fed
FB
1927 if (float64_is_nan(a) || float64_is_nan(b)) {
1928 float_raise(float_flag_invalid, status);
1929 return 1;
1930 }
1931 else {
1932 return 0;
1933 }
1934}
1935
1936FOP_COND(d, f, 0, 0)
1937FOP_COND(d, un, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status))
1938FOP_COND(d, eq, 0, float64_eq(FDT0, FDT1, &env->fp_status))
1939FOP_COND(d, ueq, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status))
1940FOP_COND(d, olt, 0, float64_lt(FDT0, FDT1, &env->fp_status))
1941FOP_COND(d, ult, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status))
1942FOP_COND(d, ole, 0, float64_le(FDT0, FDT1, &env->fp_status))
1943FOP_COND(d, ule, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status))
1944/* NOTE: the comma operator will make "cond" to eval to false,
1945 * but float*_is_unordered() is still called
1946 */
1947FOP_COND(d, sf, 1, (float64_is_unordered(FDT0, FDT1, &env->fp_status), 0))
1948FOP_COND(d, ngle,1, float64_is_unordered(FDT1, FDT0, &env->fp_status))
1949FOP_COND(d, seq, 1, float64_eq(FDT0, FDT1, &env->fp_status))
1950FOP_COND(d, ngl, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status))
1951FOP_COND(d, lt, 1, float64_lt(FDT0, FDT1, &env->fp_status))
1952FOP_COND(d, nge, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status))
1953FOP_COND(d, le, 1, float64_le(FDT0, FDT1, &env->fp_status))
1954FOP_COND(d, ngt, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status))
1955
1956flag float32_is_unordered(float32 a, float32 b STATUS_PARAM)
1957{
1958 extern flag float32_is_nan( float32 a );
1959 if (float32_is_nan(a) || float32_is_nan(b)) {
1960 float_raise(float_flag_invalid, status);
1961 return 1;
1962 }
1963 else {
1964 return 0;
1965 }
1966}
1967
1968/* NOTE: the comma operator will make "cond" to eval to false,
1969 * but float*_is_unordered() is still called
1970 */
1971FOP_COND(s, f, 0, 0)
1972FOP_COND(s, un, 0, float32_is_unordered(FST1, FST0, &env->fp_status))
1973FOP_COND(s, eq, 0, float32_eq(FST0, FST1, &env->fp_status))
1974FOP_COND(s, ueq, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status))
1975FOP_COND(s, olt, 0, float32_lt(FST0, FST1, &env->fp_status))
1976FOP_COND(s, ult, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status))
1977FOP_COND(s, ole, 0, float32_le(FST0, FST1, &env->fp_status))
1978FOP_COND(s, ule, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status))
1979/* NOTE: the comma operator will make "cond" to eval to false,
1980 * but float*_is_unordered() is still called
1981 */
1982FOP_COND(s, sf, 1, (float32_is_unordered(FST0, FST1, &env->fp_status), 0))
1983FOP_COND(s, ngle,1, float32_is_unordered(FST1, FST0, &env->fp_status))
1984FOP_COND(s, seq, 1, float32_eq(FST0, FST1, &env->fp_status))
1985FOP_COND(s, ngl, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status))
1986FOP_COND(s, lt, 1, float32_lt(FST0, FST1, &env->fp_status))
1987FOP_COND(s, nge, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status))
1988FOP_COND(s, le, 1, float32_le(FST0, FST1, &env->fp_status))
1989FOP_COND(s, ngt, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status))
1990
1991void op_bc1f (void)
1992{
1993 T0 = ! IS_FP_COND_SET(env->fcr31);
1994 DEBUG_FPU_STATE();
1995 RETURN();
1996}
1997
1998void op_bc1t (void)
1999{
2000 T0 = IS_FP_COND_SET(env->fcr31);
2001 DEBUG_FPU_STATE();
2002 RETURN();
2003}
2004#endif /* MIPS_USES_FPU */
2005
6af0bf9c
FB
2006#if defined(MIPS_USES_R4K_TLB)
2007void op_tlbwi (void)
2008{
2009 CALL_FROM_TB0(do_tlbwi);
2010 RETURN();
2011}
2012
2013void op_tlbwr (void)
2014{
2015 CALL_FROM_TB0(do_tlbwr);
2016 RETURN();
2017}
2018
2019void op_tlbp (void)
2020{
2021 CALL_FROM_TB0(do_tlbp);
2022 RETURN();
2023}
2024
2025void op_tlbr (void)
2026{
2027 CALL_FROM_TB0(do_tlbr);
2028 RETURN();
2029}
2030#endif
2031
2032/* Specials */
2033void op_pmon (void)
2034{
2035 CALL_FROM_TB1(do_pmon, PARAM1);
7a387fff
TS
2036 RETURN();
2037}
2038
2039void op_di (void)
2040{
7a387fff 2041 T0 = env->CP0_Status;
4de9b249
TS
2042 env->CP0_Status = T0 & ~(1 << CP0St_IE);
2043 CALL_FROM_TB1(cpu_mips_update_irq, env);
7a387fff
TS
2044 RETURN();
2045}
2046
2047void op_ei (void)
2048{
7a387fff 2049 T0 = env->CP0_Status;
4de9b249
TS
2050 env->CP0_Status = T0 | (1 << CP0St_IE);
2051 CALL_FROM_TB1(cpu_mips_update_irq, env);
7a387fff 2052 RETURN();
6af0bf9c
FB
2053}
2054
2055void op_trap (void)
2056{
2057 if (T0) {
4ad40f36 2058 CALL_FROM_TB1(do_raise_exception_direct, EXCP_TRAP);
6af0bf9c
FB
2059 }
2060 RETURN();
2061}
2062
4ad40f36
FB
2063void op_debug (void)
2064{
7a387fff
TS
2065 CALL_FROM_TB1(do_raise_exception, EXCP_DEBUG);
2066 RETURN();
4ad40f36
FB
2067}
2068
6af0bf9c
FB
2069void op_set_lladdr (void)
2070{
2071 env->CP0_LLAddr = T2;
7a387fff 2072 RETURN();
6af0bf9c
FB
2073}
2074
2075void debug_eret (void);
2076void op_eret (void)
2077{
2078 CALL_FROM_TB0(debug_eret);
51e11d9e 2079 if (env->hflags & MIPS_HFLAG_ERL) {
6af0bf9c 2080 env->PC = env->CP0_ErrorEPC;
51e11d9e 2081 env->hflags &= ~MIPS_HFLAG_ERL;
3e382bc8 2082 env->CP0_Status &= ~(1 << CP0St_ERL);
51e11d9e 2083 } else {
6af0bf9c 2084 env->PC = env->CP0_EPC;
51e11d9e 2085 env->hflags &= ~MIPS_HFLAG_EXL;
3e382bc8 2086 env->CP0_Status &= ~(1 << CP0St_EXL);
51e11d9e 2087 }
6af0bf9c 2088 env->CP0_LLAddr = 1;
7a387fff 2089 RETURN();
6af0bf9c
FB
2090}
2091
2092void op_deret (void)
2093{
2094 CALL_FROM_TB0(debug_eret);
2095 env->PC = env->CP0_DEPC;
7a387fff
TS
2096 RETURN();
2097}
2098
2099void op_rdhwr_cpunum(void)
2100{
2101 if (env->CP0_HWREna & (1 << 0))
2102 T0 = env->CP0_EBase & 0x2ff;
2103 else
2104 CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI);
2105 RETURN();
2106}
2107
2108void op_rdhwr_synci_step(void)
2109{
2110 if (env->CP0_HWREna & (1 << 1))
2111 T0 = env->SYNCI_Step;
2112 else
2113 CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI);
2114 RETURN();
2115}
2116
2117void op_rdhwr_cc(void)
2118{
2119 if (env->CP0_HWREna & (1 << 2))
2120 T0 = env->CP0_Count;
2121 else
2122 CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI);
2123 RETURN();
2124}
2125
2126void op_rdhwr_ccres(void)
2127{
2128 if (env->CP0_HWREna & (1 << 3))
2129 T0 = env->CCRes;
2130 else
2131 CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI);
2132 RETURN();
6af0bf9c
FB
2133}
2134
2135void op_save_state (void)
2136{
2137 env->hflags = PARAM1;
2138 RETURN();
2139}
2140
2141void op_save_pc (void)
2142{
2143 env->PC = PARAM1;
2144 RETURN();
2145}
2146
2147void op_raise_exception (void)
2148{
2149 CALL_FROM_TB1(do_raise_exception, PARAM1);
2150 RETURN();
2151}
2152
2153void op_raise_exception_err (void)
2154{
2155 CALL_FROM_TB2(do_raise_exception_err, PARAM1, PARAM2);
2156 RETURN();
2157}
2158
2159void op_exit_tb (void)
2160{
2161 EXIT_TB();
7a387fff 2162 RETURN();
6af0bf9c
FB
2163}
2164
4ad40f36
FB
2165void op_wait (void)
2166{
2167 env->halted = 1;
2168 CALL_FROM_TB1(do_raise_exception, EXCP_HLT);
7a387fff
TS
2169 RETURN();
2170}
2171
2172/* Bitfield operations. */
2173void op_ext(void)
2174{
2175 unsigned int pos = PARAM1;
2176 unsigned int size = PARAM2;
2177
c570fd16 2178 T0 = ((uint32_t)T1 >> pos) & ((1 << size) - 1);
7a387fff
TS
2179 RETURN();
2180}
2181
2182void op_ins(void)
2183{
2184 unsigned int pos = PARAM1;
2185 unsigned int size = PARAM2;
2186 target_ulong mask = ((1 << size) - 1) << pos;
2187
c570fd16 2188 T0 = (T2 & ~mask) | (((uint32_t)T1 << pos) & mask);
7a387fff
TS
2189 RETURN();
2190}
2191
2192void op_wsbh(void)
2193{
2194 T0 = ((T1 << 8) & ~0x00FF00FF) | ((T1 >> 8) & 0x00FF00FF);
2195 RETURN();
2196}
2197
c570fd16
TS
2198#ifdef MIPS_HAS_MIPS64
2199void op_dext(void)
2200{
2201 unsigned int pos = PARAM1;
2202 unsigned int size = PARAM2;
2203
2204 T0 = (T1 >> pos) & ((1 << size) - 1);
2205 RETURN();
2206}
2207
2208void op_dins(void)
2209{
2210 unsigned int pos = PARAM1;
2211 unsigned int size = PARAM2;
2212 target_ulong mask = ((1 << size) - 1) << pos;
2213
2214 T0 = (T2 & ~mask) | ((T1 << pos) & mask);
2215 RETURN();
2216}
2217
7a387fff
TS
2218void op_dsbh(void)
2219{
2220 T0 = ((T1 << 8) & ~0x00FF00FF00FF00FFULL) | ((T1 >> 8) & 0x00FF00FF00FF00FFULL);
2221 RETURN();
2222}
2223
2224void op_dshd(void)
2225{
2226 T0 = ((T1 << 16) & ~0x0000FFFF0000FFFFULL) | ((T1 >> 16) & 0x0000FFFF0000FFFFULL);
2227 RETURN();
2228}
c570fd16 2229#endif
7a387fff
TS
2230
2231void op_seb(void)
2232{
2233 T0 = ((T1 & 0xFF) ^ 0x80) - 0x80;
2234 RETURN();
2235}
2236
2237void op_seh(void)
2238{
2239 T0 = ((T1 & 0xFFFF) ^ 0x8000) - 0x8000;
2240 RETURN();
4ad40f36 2241}