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