]> Git Repo - qemu.git/blame - target-mips/op.c
Use always_inline in the MIPS support where applicable.
[qemu.git] / target-mips / op.c
CommitLineData
6af0bf9c
FB
1/*
2 * MIPS emulation micro-operations for qemu.
5fafdf24 3 *
6af0bf9c 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{
ead9360e 257 T0 = env->HI[PARAM1][env->current_tc];
6af0bf9c
FB
258 RETURN();
259}
260
261void op_store_HI (void)
262{
ead9360e 263 env->HI[PARAM1][env->current_tc] = T0;
6af0bf9c
FB
264 RETURN();
265}
266
267void op_load_LO (void)
268{
ead9360e 269 T0 = env->LO[PARAM1][env->current_tc];
6af0bf9c
FB
270 RETURN();
271}
272
273void op_store_LO (void)
274{
ead9360e 275 env->LO[PARAM1][env->current_tc] = T0;
6af0bf9c
FB
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. */
540635ba 299#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
996ba2cc 300 if ((env->hflags & MIPS_HFLAG_UM) &&
a6763a58
TS
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) {
ead9360e
TS
366 env->LO[0][env->current_tc] = (int32_t)((int64_t)(int32_t)T0 / (int32_t)T1);
367 env->HI[0][env->current_tc] = (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) {
ead9360e
TS
376 env->LO[0][env->current_tc] = (int32_t)((uint32_t)T0 / (uint32_t)T1);
377 env->HI[0][env->current_tc] = (int32_t)((uint32_t)T0 % (uint32_t)T1);
c570fd16
TS
378 }
379 RETURN();
380}
381
540635ba 382#if defined(TARGET_MIPSN32) || defined(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) {
ead9360e
TS
445 env->LO[0][env->current_tc] = T0 / T1;
446 env->HI[0][env->current_tc] = T0 % T1;
6af0bf9c
FB
447 }
448 RETURN();
449}
c570fd16 450#endif
540635ba 451#endif /* TARGET_MIPSN32 || 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
540635ba 572#if defined(TARGET_MIPSN32) || defined(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}
540635ba 773#endif /* TARGET_MIPSN32 || TARGET_MIPS64 */
c570fd16
TS
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
aa343735 815static always_inline uint64_t get_HILO (void)
c570fd16 816{
ead9360e
TS
817 return ((uint64_t)env->HI[0][env->current_tc] << 32) |
818 ((uint64_t)(uint32_t)env->LO[0][env->current_tc]);
c570fd16
TS
819}
820
aa343735 821static always_inline void set_HILO (uint64_t HILO)
c570fd16 822{
ead9360e
TS
823 env->LO[0][env->current_tc] = (int32_t)(HILO & 0xFFFFFFFF);
824 env->HI[0][env->current_tc] = (int32_t)(HILO >> 32);
c570fd16
TS
825}
826
827void op_mult (void)
828{
829 set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
830 RETURN();
831}
832
833void op_multu (void)
834{
835 set_HILO((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
836 RETURN();
837}
838
839void op_madd (void)
840{
841 int64_t tmp;
842
843 tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
844 set_HILO((int64_t)get_HILO() + tmp);
845 RETURN();
846}
847
848void op_maddu (void)
849{
850 uint64_t tmp;
851
852 tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
853 set_HILO(get_HILO() + tmp);
854 RETURN();
855}
856
857void op_msub (void)
858{
859 int64_t tmp;
860
861 tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
862 set_HILO((int64_t)get_HILO() - tmp);
863 RETURN();
864}
865
866void op_msubu (void)
867{
868 uint64_t tmp;
869
870 tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
871 set_HILO(get_HILO() - tmp);
872 RETURN();
873}
874#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
875
540635ba 876#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
c570fd16
TS
877void op_dmult (void)
878{
ead9360e 879 CALL_FROM_TB4(muls64, &(env->HI[0][env->current_tc]), &(env->LO[0][env->current_tc]), T0, T1);
c570fd16
TS
880 RETURN();
881}
882
883void op_dmultu (void)
884{
ead9360e 885 CALL_FROM_TB4(mulu64, &(env->HI[0][env->current_tc]), &(env->LO[0][env->current_tc]), T0, T1);
c570fd16
TS
886 RETURN();
887}
6af0bf9c
FB
888#endif
889
890/* Conditional moves */
891void op_movn (void)
892{
893 if (T1 != 0)
ead9360e 894 env->gpr[PARAM1][env->current_tc] = T0;
6af0bf9c
FB
895 RETURN();
896}
897
898void op_movz (void)
899{
900 if (T1 == 0)
ead9360e 901 env->gpr[PARAM1][env->current_tc] = T0;
6af0bf9c
FB
902 RETURN();
903}
904
7a387fff
TS
905void op_movf (void)
906{
ead9360e 907 if (!(env->fpu->fcr31 & PARAM1))
5a5012ec 908 T0 = T1;
7a387fff
TS
909 RETURN();
910}
911
912void op_movt (void)
913{
ead9360e 914 if (env->fpu->fcr31 & PARAM1)
5a5012ec 915 T0 = T1;
7a387fff
TS
916 RETURN();
917}
918
6af0bf9c
FB
919/* Tests */
920#define OP_COND(name, cond) \
921void glue(op_, name) (void) \
922{ \
923 if (cond) { \
924 T0 = 1; \
925 } else { \
926 T0 = 0; \
927 } \
928 RETURN(); \
929}
930
931OP_COND(eq, T0 == T1);
932OP_COND(ne, T0 != T1);
f469b9db 933OP_COND(ge, (target_long)T0 >= (target_long)T1);
6af0bf9c 934OP_COND(geu, T0 >= T1);
f469b9db 935OP_COND(lt, (target_long)T0 < (target_long)T1);
6af0bf9c 936OP_COND(ltu, T0 < T1);
f469b9db
TS
937OP_COND(gez, (target_long)T0 >= 0);
938OP_COND(gtz, (target_long)T0 > 0);
939OP_COND(lez, (target_long)T0 <= 0);
940OP_COND(ltz, (target_long)T0 < 0);
6af0bf9c 941
7a387fff 942/* Branches */
c53be334
FB
943void OPPROTO op_goto_tb0(void)
944{
945 GOTO_TB(op_goto_tb0, PARAM1, 0);
7a387fff 946 RETURN();
c53be334
FB
947}
948
949void OPPROTO op_goto_tb1(void)
950{
951 GOTO_TB(op_goto_tb1, PARAM1, 1);
7a387fff 952 RETURN();
c53be334 953}
6af0bf9c
FB
954
955/* Branch to register */
956void op_save_breg_target (void)
957{
958 env->btarget = T2;
7a387fff 959 RETURN();
6af0bf9c
FB
960}
961
962void op_restore_breg_target (void)
963{
964 T2 = env->btarget;
7a387fff 965 RETURN();
6af0bf9c
FB
966}
967
968void op_breg (void)
969{
ead9360e 970 env->PC[env->current_tc] = T2;
6af0bf9c
FB
971 RETURN();
972}
973
6af0bf9c
FB
974void op_save_btarget (void)
975{
976 env->btarget = PARAM1;
977 RETURN();
978}
979
540635ba 980#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
9b9e4393
TS
981void op_save_btarget64 (void)
982{
983 env->btarget = ((uint64_t)PARAM1 << 32) | (uint32_t)PARAM2;
984 RETURN();
985}
986#endif
987
6af0bf9c
FB
988/* Conditional branch */
989void op_set_bcond (void)
990{
991 T2 = T0;
992 RETURN();
993}
994
995void op_save_bcond (void)
996{
997 env->bcond = T2;
998 RETURN();
999}
1000
1001void op_restore_bcond (void)
1002{
1003 T2 = env->bcond;
1004 RETURN();
1005}
1006
c53be334 1007void op_jnz_T2 (void)
6af0bf9c 1008{
c53be334
FB
1009 if (T2)
1010 GOTO_LABEL_PARAM(1);
6af0bf9c
FB
1011 RETURN();
1012}
1013
1014/* CP0 functions */
873eb012 1015void op_mfc0_index (void)
6af0bf9c 1016{
9c2149c8 1017 T0 = env->CP0_Index;
873eb012
TS
1018 RETURN();
1019}
1020
ead9360e
TS
1021void op_mfc0_mvpcontrol (void)
1022{
1023 T0 = env->mvp->CP0_MVPControl;
1024 RETURN();
1025}
1026
1027void op_mfc0_mvpconf0 (void)
1028{
1029 T0 = env->mvp->CP0_MVPConf0;
1030 RETURN();
1031}
1032
1033void op_mfc0_mvpconf1 (void)
1034{
1035 T0 = env->mvp->CP0_MVPConf1;
1036 RETURN();
1037}
1038
873eb012
TS
1039void op_mfc0_random (void)
1040{
1041 CALL_FROM_TB0(do_mfc0_random);
1042 RETURN();
1043}
1044
ead9360e
TS
1045void op_mfc0_vpecontrol (void)
1046{
1047 T0 = env->CP0_VPEControl;
1048 RETURN();
1049}
1050
1051void op_mfc0_vpeconf0 (void)
1052{
1053 T0 = env->CP0_VPEConf0;
1054 RETURN();
1055}
1056
1057void op_mfc0_vpeconf1 (void)
1058{
1059 T0 = env->CP0_VPEConf1;
1060 RETURN();
1061}
1062
1063void op_mfc0_yqmask (void)
1064{
1065 T0 = env->CP0_YQMask;
1066 RETURN();
1067}
1068
1069void op_mfc0_vpeschedule (void)
1070{
1071 T0 = env->CP0_VPESchedule;
1072 RETURN();
1073}
1074
1075void op_mfc0_vpeschefback (void)
1076{
1077 T0 = env->CP0_VPEScheFBack;
1078 RETURN();
1079}
1080
1081void op_mfc0_vpeopt (void)
1082{
1083 T0 = env->CP0_VPEOpt;
1084 RETURN();
1085}
1086
873eb012
TS
1087void op_mfc0_entrylo0 (void)
1088{
9c2149c8 1089 T0 = (int32_t)env->CP0_EntryLo0;
873eb012
TS
1090 RETURN();
1091}
1092
ead9360e
TS
1093void op_mfc0_tcstatus (void)
1094{
1095 T0 = env->CP0_TCStatus[env->current_tc];
1096 RETURN();
1097}
1098
1099void op_mftc0_tcstatus(void)
1100{
1101 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1102
1103 T0 = env->CP0_TCStatus[other_tc];
1104 RETURN();
1105}
1106
1107void op_mfc0_tcbind (void)
1108{
1109 T0 = env->CP0_TCBind[env->current_tc];
1110 RETURN();
1111}
1112
1113void op_mftc0_tcbind(void)
1114{
1115 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1116
1117 T0 = env->CP0_TCBind[other_tc];
1118 RETURN();
1119}
1120
1121void op_mfc0_tcrestart (void)
1122{
1123 T0 = env->PC[env->current_tc];
1124 RETURN();
1125}
1126
1127void op_mftc0_tcrestart(void)
1128{
1129 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1130
1131 T0 = env->PC[other_tc];
1132 RETURN();
1133}
1134
1135void op_mfc0_tchalt (void)
1136{
1137 T0 = env->CP0_TCHalt[env->current_tc];
1138 RETURN();
1139}
1140
1141void op_mftc0_tchalt(void)
1142{
1143 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1144
1145 T0 = env->CP0_TCHalt[other_tc];
1146 RETURN();
1147}
1148
1149void op_mfc0_tccontext (void)
1150{
1151 T0 = env->CP0_TCContext[env->current_tc];
1152 RETURN();
1153}
1154
1155void op_mftc0_tccontext(void)
1156{
1157 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1158
1159 T0 = env->CP0_TCContext[other_tc];
1160 RETURN();
1161}
1162
1163void op_mfc0_tcschedule (void)
1164{
1165 T0 = env->CP0_TCSchedule[env->current_tc];
1166 RETURN();
1167}
1168
1169void op_mftc0_tcschedule(void)
1170{
1171 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1172
1173 T0 = env->CP0_TCSchedule[other_tc];
1174 RETURN();
1175}
1176
1177void op_mfc0_tcschefback (void)
1178{
1179 T0 = env->CP0_TCScheFBack[env->current_tc];
1180 RETURN();
1181}
1182
1183void op_mftc0_tcschefback(void)
1184{
1185 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1186
1187 T0 = env->CP0_TCScheFBack[other_tc];
1188 RETURN();
1189}
1190
873eb012
TS
1191void op_mfc0_entrylo1 (void)
1192{
9c2149c8 1193 T0 = (int32_t)env->CP0_EntryLo1;
873eb012
TS
1194 RETURN();
1195}
1196
1197void op_mfc0_context (void)
1198{
9c2149c8 1199 T0 = (int32_t)env->CP0_Context;
873eb012
TS
1200 RETURN();
1201}
1202
1203void op_mfc0_pagemask (void)
1204{
9c2149c8 1205 T0 = env->CP0_PageMask;
873eb012
TS
1206 RETURN();
1207}
1208
7a387fff
TS
1209void op_mfc0_pagegrain (void)
1210{
9c2149c8 1211 T0 = env->CP0_PageGrain;
7a387fff
TS
1212 RETURN();
1213}
1214
873eb012
TS
1215void op_mfc0_wired (void)
1216{
9c2149c8 1217 T0 = env->CP0_Wired;
873eb012
TS
1218 RETURN();
1219}
1220
ead9360e
TS
1221void op_mfc0_srsconf0 (void)
1222{
1223 T0 = env->CP0_SRSConf0;
1224 RETURN();
1225}
1226
1227void op_mfc0_srsconf1 (void)
1228{
1229 T0 = env->CP0_SRSConf1;
1230 RETURN();
1231}
1232
1233void op_mfc0_srsconf2 (void)
1234{
1235 T0 = env->CP0_SRSConf2;
1236 RETURN();
1237}
1238
1239void op_mfc0_srsconf3 (void)
1240{
1241 T0 = env->CP0_SRSConf3;
1242 RETURN();
1243}
1244
1245void op_mfc0_srsconf4 (void)
1246{
1247 T0 = env->CP0_SRSConf4;
1248 RETURN();
1249}
1250
7a387fff
TS
1251void op_mfc0_hwrena (void)
1252{
9c2149c8 1253 T0 = env->CP0_HWREna;
7a387fff
TS
1254 RETURN();
1255}
1256
873eb012
TS
1257void op_mfc0_badvaddr (void)
1258{
9c2149c8 1259 T0 = (int32_t)env->CP0_BadVAddr;
873eb012
TS
1260 RETURN();
1261}
1262
1263void op_mfc0_count (void)
1264{
1265 CALL_FROM_TB0(do_mfc0_count);
1266 RETURN();
1267}
1268
1269void op_mfc0_entryhi (void)
1270{
9c2149c8 1271 T0 = (int32_t)env->CP0_EntryHi;
873eb012
TS
1272 RETURN();
1273}
1274
ead9360e
TS
1275void op_mftc0_entryhi(void)
1276{
1277 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1278
1279 T0 = (env->CP0_EntryHi & ~0xff) | (env->CP0_TCStatus[other_tc] & 0xff);
1280 RETURN();
1281}
1282
873eb012
TS
1283void op_mfc0_compare (void)
1284{
9c2149c8 1285 T0 = env->CP0_Compare;
873eb012
TS
1286 RETURN();
1287}
1288
1289void op_mfc0_status (void)
1290{
9c2149c8 1291 T0 = env->CP0_Status;
873eb012
TS
1292 RETURN();
1293}
1294
ead9360e
TS
1295void op_mftc0_status(void)
1296{
1297 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1298 uint32_t tcstatus = env->CP0_TCStatus[other_tc];
1299
1300 T0 = env->CP0_Status & ~0xf1000018;
1301 T0 |= tcstatus & (0xf << CP0TCSt_TCU0);
1302 T0 |= (tcstatus & (1 << CP0TCSt_TMX)) >> (CP0TCSt_TMX - CP0St_MX);
1303 T0 |= (tcstatus & (0x3 << CP0TCSt_TKSU)) >> (CP0TCSt_TKSU - CP0St_R0);
1304 RETURN();
1305}
1306
7a387fff
TS
1307void op_mfc0_intctl (void)
1308{
9c2149c8 1309 T0 = env->CP0_IntCtl;
7a387fff
TS
1310 RETURN();
1311}
1312
1313void op_mfc0_srsctl (void)
1314{
9c2149c8
TS
1315 T0 = env->CP0_SRSCtl;
1316 RETURN();
1317}
1318
1319void op_mfc0_srsmap (void)
1320{
1321 T0 = env->CP0_SRSMap;
7a387fff
TS
1322 RETURN();
1323}
1324
873eb012
TS
1325void op_mfc0_cause (void)
1326{
9c2149c8 1327 T0 = env->CP0_Cause;
873eb012
TS
1328 RETURN();
1329}
1330
1331void op_mfc0_epc (void)
1332{
9c2149c8 1333 T0 = (int32_t)env->CP0_EPC;
873eb012
TS
1334 RETURN();
1335}
1336
1337void op_mfc0_prid (void)
1338{
9c2149c8 1339 T0 = env->CP0_PRid;
873eb012
TS
1340 RETURN();
1341}
1342
7a387fff
TS
1343void op_mfc0_ebase (void)
1344{
b29a0341 1345 T0 = env->CP0_EBase;
7a387fff
TS
1346 RETURN();
1347}
1348
873eb012
TS
1349void op_mfc0_config0 (void)
1350{
9c2149c8 1351 T0 = env->CP0_Config0;
873eb012
TS
1352 RETURN();
1353}
1354
1355void op_mfc0_config1 (void)
1356{
9c2149c8 1357 T0 = env->CP0_Config1;
873eb012
TS
1358 RETURN();
1359}
1360
7a387fff
TS
1361void op_mfc0_config2 (void)
1362{
9c2149c8 1363 T0 = env->CP0_Config2;
7a387fff
TS
1364 RETURN();
1365}
1366
1367void op_mfc0_config3 (void)
1368{
9c2149c8 1369 T0 = env->CP0_Config3;
7a387fff
TS
1370 RETURN();
1371}
1372
e397ee33
TS
1373void op_mfc0_config6 (void)
1374{
1375 T0 = env->CP0_Config6;
1376 RETURN();
1377}
1378
1379void op_mfc0_config7 (void)
1380{
1381 T0 = env->CP0_Config7;
1382 RETURN();
1383}
1384
873eb012
TS
1385void op_mfc0_lladdr (void)
1386{
9c2149c8 1387 T0 = (int32_t)env->CP0_LLAddr >> 4;
873eb012
TS
1388 RETURN();
1389}
1390
fd88b6ab 1391void op_mfc0_watchlo (void)
873eb012 1392{
fd88b6ab 1393 T0 = (int32_t)env->CP0_WatchLo[PARAM1];
873eb012
TS
1394 RETURN();
1395}
1396
fd88b6ab 1397void op_mfc0_watchhi (void)
873eb012 1398{
fd88b6ab 1399 T0 = env->CP0_WatchHi[PARAM1];
873eb012
TS
1400 RETURN();
1401}
1402
7a387fff
TS
1403void op_mfc0_xcontext (void)
1404{
9c2149c8 1405 T0 = (int32_t)env->CP0_XContext;
7a387fff
TS
1406 RETURN();
1407}
1408
1409void op_mfc0_framemask (void)
1410{
1411 T0 = env->CP0_Framemask;
1412 RETURN();
1413}
1414
873eb012
TS
1415void op_mfc0_debug (void)
1416{
9c2149c8 1417 T0 = env->CP0_Debug;
873eb012
TS
1418 if (env->hflags & MIPS_HFLAG_DM)
1419 T0 |= 1 << CP0DB_DM;
1420 RETURN();
1421}
1422
ead9360e
TS
1423void op_mftc0_debug(void)
1424{
1425 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1426
1427 /* XXX: Might be wrong, check with EJTAG spec. */
1428 T0 = (env->CP0_Debug & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
1429 (env->CP0_Debug_tcstatus[other_tc] &
1430 ((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
1431 RETURN();
1432}
1433
873eb012
TS
1434void op_mfc0_depc (void)
1435{
9c2149c8 1436 T0 = (int32_t)env->CP0_DEPC;
873eb012
TS
1437 RETURN();
1438}
1439
7a387fff
TS
1440void op_mfc0_performance0 (void)
1441{
9c2149c8 1442 T0 = env->CP0_Performance0;
7a387fff
TS
1443 RETURN();
1444}
1445
873eb012
TS
1446void op_mfc0_taglo (void)
1447{
9c2149c8 1448 T0 = env->CP0_TagLo;
873eb012
TS
1449 RETURN();
1450}
1451
1452void op_mfc0_datalo (void)
1453{
9c2149c8 1454 T0 = env->CP0_DataLo;
873eb012
TS
1455 RETURN();
1456}
1457
7a387fff
TS
1458void op_mfc0_taghi (void)
1459{
9c2149c8 1460 T0 = env->CP0_TagHi;
7a387fff
TS
1461 RETURN();
1462}
1463
1464void op_mfc0_datahi (void)
1465{
9c2149c8 1466 T0 = env->CP0_DataHi;
7a387fff
TS
1467 RETURN();
1468}
1469
873eb012
TS
1470void op_mfc0_errorepc (void)
1471{
9c2149c8 1472 T0 = (int32_t)env->CP0_ErrorEPC;
873eb012
TS
1473 RETURN();
1474}
1475
1476void op_mfc0_desave (void)
1477{
9c2149c8 1478 T0 = env->CP0_DESAVE;
6af0bf9c
FB
1479 RETURN();
1480}
1481
8c0fdd85 1482void op_mtc0_index (void)
6af0bf9c 1483{
ead9360e
TS
1484 env->CP0_Index = (env->CP0_Index & 0x80000000) | (T0 % env->tlb->nb_tlb);
1485 RETURN();
1486}
1487
1488void op_mtc0_mvpcontrol (void)
1489{
1490 uint32_t mask = 0;
1491 uint32_t newval;
1492
1493 if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP))
1494 mask |= (1 << CP0MVPCo_CPA) | (1 << CP0MVPCo_VPC) |
1495 (1 << CP0MVPCo_EVP);
1496 if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1497 mask |= (1 << CP0MVPCo_STLB);
1498 newval = (env->mvp->CP0_MVPControl & ~mask) | (T0 & mask);
1499
1500 // TODO: Enable/disable shared TLB, enable/disable VPEs.
1501
1502 env->mvp->CP0_MVPControl = newval;
1503 RETURN();
1504}
1505
1506void op_mtc0_vpecontrol (void)
1507{
1508 uint32_t mask;
1509 uint32_t newval;
1510
1511 mask = (1 << CP0VPECo_YSI) | (1 << CP0VPECo_GSI) |
1512 (1 << CP0VPECo_TE) | (0xff << CP0VPECo_TargTC);
1513 newval = (env->CP0_VPEControl & ~mask) | (T0 & mask);
1514
1515 /* Yield scheduler intercept not implemented. */
1516 /* Gating storage scheduler intercept not implemented. */
1517
1518 // TODO: Enable/disable TCs.
1519
1520 env->CP0_VPEControl = newval;
1521 RETURN();
1522}
1523
1524void op_mtc0_vpeconf0 (void)
1525{
1526 uint32_t mask = 0;
1527 uint32_t newval;
1528
1529 if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) {
1530 if (env->CP0_VPEConf0 & (1 << CP0VPEC0_VPA))
1531 mask |= (0xff << CP0VPEC0_XTC);
1532 mask |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
1533 }
1534 newval = (env->CP0_VPEConf0 & ~mask) | (T0 & mask);
1535
1536 // TODO: TC exclusive handling due to ERL/EXL.
1537
1538 env->CP0_VPEConf0 = newval;
1539 RETURN();
1540}
1541
1542void op_mtc0_vpeconf1 (void)
1543{
1544 uint32_t mask = 0;
1545 uint32_t newval;
1546
1547 if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1548 mask |= (0xff << CP0VPEC1_NCX) | (0xff << CP0VPEC1_NCP2) |
1549 (0xff << CP0VPEC1_NCP1);
1550 newval = (env->CP0_VPEConf1 & ~mask) | (T0 & mask);
1551
1552 /* UDI not implemented. */
1553 /* CP2 not implemented. */
1554
1555 // TODO: Handle FPU (CP1) binding.
1556
1557 env->CP0_VPEConf1 = newval;
1558 RETURN();
1559}
1560
1561void op_mtc0_yqmask (void)
1562{
1563 /* Yield qualifier inputs not implemented. */
1564 env->CP0_YQMask = 0x00000000;
1565 RETURN();
1566}
1567
1568void op_mtc0_vpeschedule (void)
1569{
1570 env->CP0_VPESchedule = T0;
1571 RETURN();
1572}
1573
1574void op_mtc0_vpeschefback (void)
1575{
1576 env->CP0_VPEScheFBack = T0;
1577 RETURN();
1578}
1579
1580void op_mtc0_vpeopt (void)
1581{
1582 env->CP0_VPEOpt = T0 & 0x0000ffff;
8c0fdd85
TS
1583 RETURN();
1584}
1585
1586void op_mtc0_entrylo0 (void)
1587{
7a387fff
TS
1588 /* Large physaddr not implemented */
1589 /* 1k pages not implemented */
f1b0aa5d 1590 env->CP0_EntryLo0 = T0 & 0x3FFFFFFF;
8c0fdd85
TS
1591 RETURN();
1592}
1593
ead9360e
TS
1594void op_mtc0_tcstatus (void)
1595{
1596 uint32_t mask = env->CP0_TCStatus_rw_bitmask;
1597 uint32_t newval;
1598
1599 newval = (env->CP0_TCStatus[env->current_tc] & ~mask) | (T0 & mask);
1600
1601 // TODO: Sync with CP0_Status.
1602
1603 env->CP0_TCStatus[env->current_tc] = newval;
1604 RETURN();
1605}
1606
1607void op_mttc0_tcstatus (void)
1608{
1609 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1610
1611 // TODO: Sync with CP0_Status.
1612
1613 env->CP0_TCStatus[other_tc] = T0;
1614 RETURN();
1615}
1616
1617void op_mtc0_tcbind (void)
1618{
1619 uint32_t mask = (1 << CP0TCBd_TBE);
1620 uint32_t newval;
1621
1622 if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1623 mask |= (1 << CP0TCBd_CurVPE);
1624 newval = (env->CP0_TCBind[env->current_tc] & ~mask) | (T0 & mask);
1625 env->CP0_TCBind[env->current_tc] = newval;
1626 RETURN();
1627}
1628
1629void op_mttc0_tcbind (void)
1630{
1631 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1632 uint32_t mask = (1 << CP0TCBd_TBE);
1633 uint32_t newval;
1634
1635 if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1636 mask |= (1 << CP0TCBd_CurVPE);
1637 newval = (env->CP0_TCBind[other_tc] & ~mask) | (T0 & mask);
1638 env->CP0_TCBind[other_tc] = newval;
1639 RETURN();
1640}
1641
1642void op_mtc0_tcrestart (void)
1643{
1644 env->PC[env->current_tc] = T0;
1645 env->CP0_TCStatus[env->current_tc] &= ~(1 << CP0TCSt_TDS);
1646 env->CP0_LLAddr = 0ULL;
1647 /* MIPS16 not implemented. */
1648 RETURN();
1649}
1650
1651void op_mttc0_tcrestart (void)
1652{
1653 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1654
1655 env->PC[other_tc] = T0;
1656 env->CP0_TCStatus[other_tc] &= ~(1 << CP0TCSt_TDS);
1657 env->CP0_LLAddr = 0ULL;
1658 /* MIPS16 not implemented. */
1659 RETURN();
1660}
1661
1662void op_mtc0_tchalt (void)
1663{
1664 env->CP0_TCHalt[env->current_tc] = T0 & 0x1;
1665
1666 // TODO: Halt TC / Restart (if allocated+active) TC.
1667
1668 RETURN();
1669}
1670
1671void op_mttc0_tchalt (void)
1672{
1673 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1674
1675 // TODO: Halt TC / Restart (if allocated+active) TC.
1676
1677 env->CP0_TCHalt[other_tc] = T0;
1678 RETURN();
1679}
1680
1681void op_mtc0_tccontext (void)
1682{
1683 env->CP0_TCContext[env->current_tc] = T0;
1684 RETURN();
1685}
1686
1687void op_mttc0_tccontext (void)
1688{
1689 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1690
1691 env->CP0_TCContext[other_tc] = T0;
1692 RETURN();
1693}
1694
1695void op_mtc0_tcschedule (void)
1696{
1697 env->CP0_TCSchedule[env->current_tc] = T0;
1698 RETURN();
1699}
1700
1701void op_mttc0_tcschedule (void)
1702{
1703 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1704
1705 env->CP0_TCSchedule[other_tc] = T0;
1706 RETURN();
1707}
1708
1709void op_mtc0_tcschefback (void)
1710{
1711 env->CP0_TCScheFBack[env->current_tc] = T0;
1712 RETURN();
1713}
1714
1715void op_mttc0_tcschefback (void)
1716{
1717 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1718
1719 env->CP0_TCScheFBack[other_tc] = T0;
1720 RETURN();
1721}
1722
8c0fdd85
TS
1723void op_mtc0_entrylo1 (void)
1724{
7a387fff
TS
1725 /* Large physaddr not implemented */
1726 /* 1k pages not implemented */
f1b0aa5d 1727 env->CP0_EntryLo1 = T0 & 0x3FFFFFFF;
8c0fdd85
TS
1728 RETURN();
1729}
1730
1731void op_mtc0_context (void)
1732{
534ce69f 1733 env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (T0 & ~0x007FFFFF);
8c0fdd85
TS
1734 RETURN();
1735}
1736
1737void op_mtc0_pagemask (void)
1738{
7a387fff 1739 /* 1k pages not implemented */
f2e9ebef 1740 env->CP0_PageMask = T0 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
7a387fff
TS
1741 RETURN();
1742}
1743
1744void op_mtc0_pagegrain (void)
1745{
1746 /* SmartMIPS not implemented */
1747 /* Large physaddr not implemented */
1748 /* 1k pages not implemented */
1749 env->CP0_PageGrain = 0;
8c0fdd85
TS
1750 RETURN();
1751}
1752
1753void op_mtc0_wired (void)
1754{
ead9360e
TS
1755 env->CP0_Wired = T0 % env->tlb->nb_tlb;
1756 RETURN();
1757}
1758
1759void op_mtc0_srsconf0 (void)
1760{
1761 env->CP0_SRSConf0 |= T0 & env->CP0_SRSConf0_rw_bitmask;
1762 RETURN();
1763}
1764
1765void op_mtc0_srsconf1 (void)
1766{
1767 env->CP0_SRSConf1 |= T0 & env->CP0_SRSConf1_rw_bitmask;
1768 RETURN();
1769}
1770
1771void op_mtc0_srsconf2 (void)
1772{
1773 env->CP0_SRSConf2 |= T0 & env->CP0_SRSConf2_rw_bitmask;
1774 RETURN();
1775}
1776
1777void op_mtc0_srsconf3 (void)
1778{
1779 env->CP0_SRSConf3 |= T0 & env->CP0_SRSConf3_rw_bitmask;
1780 RETURN();
1781}
1782
1783void op_mtc0_srsconf4 (void)
1784{
1785 env->CP0_SRSConf4 |= T0 & env->CP0_SRSConf4_rw_bitmask;
7a387fff
TS
1786 RETURN();
1787}
1788
1789void op_mtc0_hwrena (void)
1790{
1791 env->CP0_HWREna = T0 & 0x0000000F;
8c0fdd85
TS
1792 RETURN();
1793}
1794
1795void op_mtc0_count (void)
1796{
1797 CALL_FROM_TB2(cpu_mips_store_count, env, T0);
1798 RETURN();
1799}
1800
1801void op_mtc0_entryhi (void)
1802{
0feef828 1803 target_ulong old, val;
8c0fdd85 1804
7a387fff 1805 /* 1k pages not implemented */
100ce988 1806 val = T0 & ((TARGET_PAGE_MASK << 1) | 0xFF);
540635ba 1807#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
e034e2c3 1808 val &= env->SEGMask;
100ce988 1809#endif
8c0fdd85
TS
1810 old = env->CP0_EntryHi;
1811 env->CP0_EntryHi = val;
ead9360e
TS
1812 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
1813 uint32_t tcst = env->CP0_TCStatus[env->current_tc] & ~0xff;
1814 env->CP0_TCStatus[env->current_tc] = tcst | (val & 0xff);
1815 }
8c0fdd85
TS
1816 /* If the ASID changes, flush qemu's TLB. */
1817 if ((old & 0xFF) != (val & 0xFF))
1818 CALL_FROM_TB2(cpu_mips_tlb_flush, env, 1);
1819 RETURN();
1820}
1821
ead9360e
TS
1822void op_mttc0_entryhi(void)
1823{
1824 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1825
1826 env->CP0_EntryHi = (env->CP0_EntryHi & 0xff) | (T0 & ~0xff);
1827 env->CP0_TCStatus[other_tc] = (env->CP0_TCStatus[other_tc] & ~0xff) | (T0 & 0xff);
1828 RETURN();
1829}
1830
8c0fdd85
TS
1831void op_mtc0_compare (void)
1832{
1833 CALL_FROM_TB2(cpu_mips_store_compare, env, T0);
1834 RETURN();
1835}
1836
1837void op_mtc0_status (void)
1838{
4de9b249 1839 uint32_t val, old;
ead9360e 1840 uint32_t mask = env->CP0_Status_rw_bitmask;
8c0fdd85 1841
f1b0aa5d 1842 val = T0 & mask;
8c0fdd85 1843 old = env->CP0_Status;
5a5012ec 1844 env->CP0_Status = (env->CP0_Status & ~mask) | val;
08fa4bab 1845 CALL_FROM_TB1(compute_hflags, env);
f41c52f1
TS
1846 if (loglevel & CPU_LOG_EXEC)
1847 CALL_FROM_TB2(do_mtc0_status_debug, old, val);
4de9b249 1848 CALL_FROM_TB1(cpu_mips_update_irq, env);
8c0fdd85
TS
1849 RETURN();
1850}
1851
ead9360e
TS
1852void op_mttc0_status(void)
1853{
1854 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1855 uint32_t tcstatus = env->CP0_TCStatus[other_tc];
1856
1857 env->CP0_Status = T0 & ~0xf1000018;
1858 tcstatus = (tcstatus & ~(0xf << CP0TCSt_TCU0)) | (T0 & (0xf << CP0St_CU0));
1859 tcstatus = (tcstatus & ~(1 << CP0TCSt_TMX)) | ((T0 & (1 << CP0St_MX)) << (CP0TCSt_TMX - CP0St_MX));
1860 tcstatus = (tcstatus & ~(0x3 << CP0TCSt_TKSU)) | ((T0 & (0x3 << CP0St_R0)) << (CP0TCSt_TKSU - CP0St_R0));
1861 env->CP0_TCStatus[other_tc] = tcstatus;
1862 RETURN();
1863}
1864
7a387fff
TS
1865void op_mtc0_intctl (void)
1866{
42532189
TS
1867 /* vectored interrupts not implemented, no performance counters. */
1868 env->CP0_IntCtl = (env->CP0_IntCtl & ~0x000002e0) | (T0 & 0x000002e0);
7a387fff
TS
1869 RETURN();
1870}
1871
1872void op_mtc0_srsctl (void)
1873{
ead9360e
TS
1874 uint32_t mask = (0xf << CP0SRSCtl_ESS) | (0xf << CP0SRSCtl_PSS);
1875 env->CP0_SRSCtl = (env->CP0_SRSCtl & ~mask) | (T0 & mask);
7a387fff
TS
1876 RETURN();
1877}
1878
9c2149c8
TS
1879void op_mtc0_srsmap (void)
1880{
ead9360e 1881 env->CP0_SRSMap = T0;
9c2149c8
TS
1882 RETURN();
1883}
1884
8c0fdd85
TS
1885void op_mtc0_cause (void)
1886{
39d51eb8 1887 uint32_t mask = 0x00C00300;
42532189 1888 uint32_t old = env->CP0_Cause;
39d51eb8 1889
e189e748 1890 if (env->insn_flags & ISA_MIPS32R2)
39d51eb8
TS
1891 mask |= 1 << CP0Ca_DC;
1892
e58c8ba5 1893 env->CP0_Cause = (env->CP0_Cause & ~mask) | (T0 & mask);
8c0fdd85 1894
42532189
TS
1895 if ((old ^ env->CP0_Cause) & (1 << CP0Ca_DC)) {
1896 if (env->CP0_Cause & (1 << CP0Ca_DC))
1897 CALL_FROM_TB1(cpu_mips_stop_count, env);
1898 else
1899 CALL_FROM_TB1(cpu_mips_start_count, env);
1900 }
1901
4de9b249
TS
1902 /* Handle the software interrupt as an hardware one, as they
1903 are very similar */
1904 if (T0 & CP0Ca_IP_mask) {
1905 CALL_FROM_TB1(cpu_mips_update_irq, env);
8c0fdd85 1906 }
8c0fdd85
TS
1907 RETURN();
1908}
1909
1910void op_mtc0_epc (void)
1911{
f1b0aa5d 1912 env->CP0_EPC = T0;
8c0fdd85
TS
1913 RETURN();
1914}
1915
7a387fff
TS
1916void op_mtc0_ebase (void)
1917{
1918 /* vectored interrupts not implemented */
1919 /* Multi-CPU not implemented */
b29a0341 1920 env->CP0_EBase = 0x80000000 | (T0 & 0x3FFFF000);
7a387fff
TS
1921 RETURN();
1922}
1923
8c0fdd85
TS
1924void op_mtc0_config0 (void)
1925{
7bfd934a 1926 env->CP0_Config0 = (env->CP0_Config0 & 0x81FFFFF8) | (T0 & 0x00000007);
8c0fdd85
TS
1927 RETURN();
1928}
1929
7a387fff
TS
1930void op_mtc0_config2 (void)
1931{
1932 /* tertiary/secondary caches not implemented */
1933 env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF);
1934 RETURN();
1935}
1936
fd88b6ab 1937void op_mtc0_watchlo (void)
8c0fdd85 1938{
4e7a4a4e
TS
1939 /* Watch exceptions for instructions, data loads, data stores
1940 not implemented. */
fd88b6ab 1941 env->CP0_WatchLo[PARAM1] = (T0 & ~0x7);
8c0fdd85
TS
1942 RETURN();
1943}
1944
fd88b6ab 1945void op_mtc0_watchhi (void)
8c0fdd85 1946{
fd88b6ab
TS
1947 env->CP0_WatchHi[PARAM1] = (T0 & 0x40FF0FF8);
1948 env->CP0_WatchHi[PARAM1] &= ~(env->CP0_WatchHi[PARAM1] & T0 & 0x7);
8c0fdd85
TS
1949 RETURN();
1950}
1951
ead9360e
TS
1952void op_mtc0_xcontext (void)
1953{
1954 target_ulong mask = (1ULL << (env->SEGBITS - 7)) - 1;
1955 env->CP0_XContext = (env->CP0_XContext & mask) | (T0 & ~mask);
1956 RETURN();
1957}
1958
7a387fff
TS
1959void op_mtc0_framemask (void)
1960{
1961 env->CP0_Framemask = T0; /* XXX */
1962 RETURN();
1963}
1964
8c0fdd85
TS
1965void op_mtc0_debug (void)
1966{
1967 env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120);
1968 if (T0 & (1 << CP0DB_DM))
1969 env->hflags |= MIPS_HFLAG_DM;
1970 else
1971 env->hflags &= ~MIPS_HFLAG_DM;
1972 RETURN();
1973}
1974
ead9360e
TS
1975void op_mttc0_debug(void)
1976{
1977 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1978
1979 /* XXX: Might be wrong, check with EJTAG spec. */
1980 env->CP0_Debug_tcstatus[other_tc] = T0 & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt));
1981 env->CP0_Debug = (env->CP0_Debug & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
1982 (T0 & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
1983 RETURN();
1984}
1985
8c0fdd85
TS
1986void op_mtc0_depc (void)
1987{
f1b0aa5d 1988 env->CP0_DEPC = T0;
8c0fdd85
TS
1989 RETURN();
1990}
1991
7a387fff
TS
1992void op_mtc0_performance0 (void)
1993{
1994 env->CP0_Performance0 = T0; /* XXX */
1995 RETURN();
1996}
1997
8c0fdd85
TS
1998void op_mtc0_taglo (void)
1999{
9c2149c8 2000 env->CP0_TagLo = T0 & 0xFFFFFCF6;
8c0fdd85
TS
2001 RETURN();
2002}
2003
7a387fff
TS
2004void op_mtc0_datalo (void)
2005{
2006 env->CP0_DataLo = T0; /* XXX */
2007 RETURN();
2008}
2009
2010void op_mtc0_taghi (void)
2011{
2012 env->CP0_TagHi = T0; /* XXX */
2013 RETURN();
2014}
2015
2016void op_mtc0_datahi (void)
2017{
2018 env->CP0_DataHi = T0; /* XXX */
2019 RETURN();
2020}
2021
8c0fdd85
TS
2022void op_mtc0_errorepc (void)
2023{
f1b0aa5d 2024 env->CP0_ErrorEPC = T0;
8c0fdd85
TS
2025 RETURN();
2026}
2027
2028void op_mtc0_desave (void)
2029{
2030 env->CP0_DESAVE = T0;
6af0bf9c
FB
2031 RETURN();
2032}
2033
540635ba 2034#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
ead9360e 2035void op_dmfc0_yqmask (void)
f1b0aa5d 2036{
ead9360e
TS
2037 T0 = env->CP0_YQMask;
2038 RETURN();
2039}
2040
2041void op_dmfc0_vpeschedule (void)
2042{
2043 T0 = env->CP0_VPESchedule;
2044 RETURN();
2045}
2046
2047void op_dmfc0_vpeschefback (void)
2048{
2049 T0 = env->CP0_VPEScheFBack;
f1b0aa5d
TS
2050 RETURN();
2051}
2052
9c2149c8
TS
2053void op_dmfc0_entrylo0 (void)
2054{
2055 T0 = env->CP0_EntryLo0;
2056 RETURN();
2057}
2058
ead9360e
TS
2059void op_dmfc0_tcrestart (void)
2060{
2061 T0 = env->PC[env->current_tc];
2062 RETURN();
2063}
2064
2065void op_dmfc0_tchalt (void)
2066{
2067 T0 = env->CP0_TCHalt[env->current_tc];
2068 RETURN();
2069}
2070
2071void op_dmfc0_tccontext (void)
2072{
2073 T0 = env->CP0_TCContext[env->current_tc];
2074 RETURN();
2075}
2076
2077void op_dmfc0_tcschedule (void)
2078{
2079 T0 = env->CP0_TCSchedule[env->current_tc];
2080 RETURN();
2081}
2082
2083void op_dmfc0_tcschefback (void)
2084{
2085 T0 = env->CP0_TCScheFBack[env->current_tc];
2086 RETURN();
2087}
2088
9c2149c8
TS
2089void op_dmfc0_entrylo1 (void)
2090{
2091 T0 = env->CP0_EntryLo1;
2092 RETURN();
2093}
2094
2095void op_dmfc0_context (void)
2096{
2097 T0 = env->CP0_Context;
2098 RETURN();
2099}
2100
2101void op_dmfc0_badvaddr (void)
2102{
2103 T0 = env->CP0_BadVAddr;
2104 RETURN();
2105}
2106
2107void op_dmfc0_entryhi (void)
2108{
2109 T0 = env->CP0_EntryHi;
2110 RETURN();
2111}
2112
2113void op_dmfc0_epc (void)
2114{
2115 T0 = env->CP0_EPC;
2116 RETURN();
2117}
2118
9c2149c8
TS
2119void op_dmfc0_lladdr (void)
2120{
2121 T0 = env->CP0_LLAddr >> 4;
2122 RETURN();
2123}
2124
fd88b6ab 2125void op_dmfc0_watchlo (void)
9c2149c8 2126{
fd88b6ab 2127 T0 = env->CP0_WatchLo[PARAM1];
9c2149c8
TS
2128 RETURN();
2129}
2130
2131void op_dmfc0_xcontext (void)
2132{
2133 T0 = env->CP0_XContext;
2134 RETURN();
2135}
2136
2137void op_dmfc0_depc (void)
2138{
2139 T0 = env->CP0_DEPC;
2140 RETURN();
2141}
2142
2143void op_dmfc0_errorepc (void)
2144{
2145 T0 = env->CP0_ErrorEPC;
2146 RETURN();
2147}
540635ba 2148#endif /* TARGET_MIPSN32 || TARGET_MIPS64 */
9c2149c8 2149
ead9360e
TS
2150/* MIPS MT functions */
2151void op_mftgpr(void)
2152{
2153 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2154
2155 T0 = env->gpr[PARAM1][other_tc];
2156 RETURN();
2157}
2158
2159void op_mftlo(void)
2160{
2161 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2162
2163 T0 = env->LO[PARAM1][other_tc];
2164 RETURN();
2165}
2166
2167void op_mfthi(void)
2168{
2169 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2170
2171 T0 = env->HI[PARAM1][other_tc];
2172 RETURN();
2173}
2174
2175void op_mftacx(void)
2176{
2177 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2178
2179 T0 = env->ACX[PARAM1][other_tc];
2180 RETURN();
2181}
2182
2183void op_mftdsp(void)
2184{
2185 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2186
2187 T0 = env->DSPControl[other_tc];
2188 RETURN();
2189}
2190
2191void op_mttgpr(void)
2192{
2193 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2194
2195 T0 = env->gpr[PARAM1][other_tc];
2196 RETURN();
2197}
2198
2199void op_mttlo(void)
2200{
2201 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2202
2203 T0 = env->LO[PARAM1][other_tc];
2204 RETURN();
2205}
2206
2207void op_mtthi(void)
2208{
2209 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2210
2211 T0 = env->HI[PARAM1][other_tc];
2212 RETURN();
2213}
2214
2215void op_mttacx(void)
2216{
2217 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2218
2219 T0 = env->ACX[PARAM1][other_tc];
2220 RETURN();
2221}
2222
2223void op_mttdsp(void)
2224{
2225 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2226
2227 T0 = env->DSPControl[other_tc];
2228 RETURN();
2229}
2230
2231
2232void op_dmt(void)
2233{
2234 // TODO
2235 T0 = 0;
2236 // rt = T0
2237 RETURN();
2238}
2239
2240void op_emt(void)
2241{
2242 // TODO
2243 T0 = 0;
2244 // rt = T0
2245 RETURN();
2246}
2247
2248void op_dvpe(void)
2249{
2250 // TODO
2251 T0 = 0;
2252 // rt = T0
2253 RETURN();
2254}
2255
2256void op_evpe(void)
2257{
2258 // TODO
2259 T0 = 0;
2260 // rt = T0
2261 RETURN();
2262}
2263
2264void op_fork(void)
2265{
2266 // T0 = rt, T1 = rs
2267 T0 = 0;
2268 // TODO: store to TC register
2269 RETURN();
2270}
2271
2272void op_yield(void)
2273{
2274 if (T0 < 0) {
2275 /* No scheduling policy implemented. */
2276 if (T0 != -2) {
2277 if (env->CP0_VPEControl & (1 << CP0VPECo_YSI) &&
2278 env->CP0_TCStatus[env->current_tc] & (1 << CP0TCSt_DT)) {
2279 env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
2280 env->CP0_VPEControl |= 4 << CP0VPECo_EXCPT;
2281 CALL_FROM_TB1(do_raise_exception, EXCP_THREAD);
2282 }
2283 }
2284 } else if (T0 == 0) {
2285 if (0 /* TODO: TC underflow */) {
2286 env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
2287 CALL_FROM_TB1(do_raise_exception, EXCP_THREAD);
2288 } else {
2289 // TODO: Deallocate TC
2290 }
2291 } else if (T0 > 0) {
2292 /* Yield qualifier inputs not implemented. */
2293 env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
2294 env->CP0_VPEControl |= 2 << CP0VPECo_EXCPT;
2295 CALL_FROM_TB1(do_raise_exception, EXCP_THREAD);
2296 }
2297 T0 = env->CP0_YQMask;
2298 RETURN();
2299}
2300
5a5012ec 2301/* CP1 functions */
6ea83fed
FB
2302#if 0
2303# define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env)
2304#else
2305# define DEBUG_FPU_STATE() do { } while(0)
2306#endif
2307
5a5012ec
TS
2308void op_cfc1 (void)
2309{
ead9360e 2310 CALL_FROM_TB1(do_cfc1, PARAM1);
5a5012ec
TS
2311 DEBUG_FPU_STATE();
2312 RETURN();
2313}
2314
2315void op_ctc1 (void)
2316{
ead9360e 2317 CALL_FROM_TB1(do_ctc1, PARAM1);
6ea83fed
FB
2318 DEBUG_FPU_STATE();
2319 RETURN();
2320}
2321
2322void op_mfc1 (void)
2323{
2324 T0 = WT0;
2325 DEBUG_FPU_STATE();
2326 RETURN();
2327}
2328
2329void op_mtc1 (void)
2330{
2331 WT0 = T0;
2332 DEBUG_FPU_STATE();
2333 RETURN();
2334}
2335
5a5012ec
TS
2336void op_dmfc1 (void)
2337{
2338 T0 = DT0;
2339 DEBUG_FPU_STATE();
2340 RETURN();
2341}
2342
2343void op_dmtc1 (void)
2344{
2345 DT0 = T0;
2346 DEBUG_FPU_STATE();
2347 RETURN();
2348}
2349
2350void op_mfhc1 (void)
2351{
2352 T0 = WTH0;
2353 DEBUG_FPU_STATE();
2354 RETURN();
2355}
2356
2357void op_mthc1 (void)
2358{
2359 WTH0 = T0;
2360 DEBUG_FPU_STATE();
2361 RETURN();
2362}
2363
6ea83fed
FB
2364/* Float support.
2365 Single precition routines have a "s" suffix, double precision a
5a5012ec
TS
2366 "d" suffix, 32bit integer "w", 64bit integer "l", paired singe "ps",
2367 paired single lowwer "pl", paired single upper "pu". */
6ea83fed
FB
2368
2369#define FLOAT_OP(name, p) void OPPROTO op_float_##name##_##p(void)
2370
dd016883
FB
2371FLOAT_OP(cvtd, s)
2372{
fd4a04eb 2373 CALL_FROM_TB0(do_float_cvtd_s);
dd016883
FB
2374 DEBUG_FPU_STATE();
2375 RETURN();
2376}
6ea83fed
FB
2377FLOAT_OP(cvtd, w)
2378{
fd4a04eb 2379 CALL_FROM_TB0(do_float_cvtd_w);
5a5012ec
TS
2380 DEBUG_FPU_STATE();
2381 RETURN();
2382}
2383FLOAT_OP(cvtd, l)
2384{
fd4a04eb 2385 CALL_FROM_TB0(do_float_cvtd_l);
5a5012ec
TS
2386 DEBUG_FPU_STATE();
2387 RETURN();
2388}
2389FLOAT_OP(cvtl, d)
2390{
fd4a04eb 2391 CALL_FROM_TB0(do_float_cvtl_d);
5a5012ec
TS
2392 DEBUG_FPU_STATE();
2393 RETURN();
2394}
2395FLOAT_OP(cvtl, s)
2396{
fd4a04eb 2397 CALL_FROM_TB0(do_float_cvtl_s);
5a5012ec
TS
2398 DEBUG_FPU_STATE();
2399 RETURN();
2400}
2401FLOAT_OP(cvtps, s)
2402{
2403 WT2 = WT0;
2404 WTH2 = WT1;
2405 DEBUG_FPU_STATE();
2406 RETURN();
2407}
2408FLOAT_OP(cvtps, pw)
2409{
fd4a04eb 2410 CALL_FROM_TB0(do_float_cvtps_pw);
5a5012ec
TS
2411 DEBUG_FPU_STATE();
2412 RETURN();
2413}
2414FLOAT_OP(cvtpw, ps)
2415{
fd4a04eb 2416 CALL_FROM_TB0(do_float_cvtpw_ps);
6ea83fed
FB
2417 DEBUG_FPU_STATE();
2418 RETURN();
2419}
dd016883
FB
2420FLOAT_OP(cvts, d)
2421{
fd4a04eb 2422 CALL_FROM_TB0(do_float_cvts_d);
dd016883
FB
2423 DEBUG_FPU_STATE();
2424 RETURN();
2425}
6ea83fed
FB
2426FLOAT_OP(cvts, w)
2427{
fd4a04eb 2428 CALL_FROM_TB0(do_float_cvts_w);
5a5012ec
TS
2429 DEBUG_FPU_STATE();
2430 RETURN();
2431}
2432FLOAT_OP(cvts, l)
2433{
fd4a04eb 2434 CALL_FROM_TB0(do_float_cvts_l);
5a5012ec
TS
2435 DEBUG_FPU_STATE();
2436 RETURN();
2437}
2438FLOAT_OP(cvts, pl)
2439{
fd4a04eb 2440 CALL_FROM_TB0(do_float_cvts_pl);
5a5012ec
TS
2441 DEBUG_FPU_STATE();
2442 RETURN();
2443}
2444FLOAT_OP(cvts, pu)
2445{
fd4a04eb 2446 CALL_FROM_TB0(do_float_cvts_pu);
6ea83fed
FB
2447 DEBUG_FPU_STATE();
2448 RETURN();
2449}
2450FLOAT_OP(cvtw, s)
2451{
fd4a04eb 2452 CALL_FROM_TB0(do_float_cvtw_s);
6ea83fed
FB
2453 DEBUG_FPU_STATE();
2454 RETURN();
2455}
2456FLOAT_OP(cvtw, d)
2457{
fd4a04eb 2458 CALL_FROM_TB0(do_float_cvtw_d);
5a5012ec
TS
2459 DEBUG_FPU_STATE();
2460 RETURN();
2461}
2462
2463FLOAT_OP(pll, ps)
2464{
2465 DT2 = ((uint64_t)WT0 << 32) | WT1;
2466 DEBUG_FPU_STATE();
2467 RETURN();
2468}
2469FLOAT_OP(plu, ps)
2470{
2471 DT2 = ((uint64_t)WT0 << 32) | WTH1;
2472 DEBUG_FPU_STATE();
2473 RETURN();
2474}
2475FLOAT_OP(pul, ps)
2476{
2477 DT2 = ((uint64_t)WTH0 << 32) | WT1;
2478 DEBUG_FPU_STATE();
2479 RETURN();
2480}
2481FLOAT_OP(puu, ps)
2482{
2483 DT2 = ((uint64_t)WTH0 << 32) | WTH1;
6ea83fed
FB
2484 DEBUG_FPU_STATE();
2485 RETURN();
2486}
2487
fd4a04eb
TS
2488#define FLOAT_ROUNDOP(op, ttype, stype) \
2489FLOAT_OP(op ## ttype, stype) \
2490{ \
2491 CALL_FROM_TB0(do_float_ ## op ## ttype ## _ ## stype); \
2492 DEBUG_FPU_STATE(); \
2493 RETURN(); \
6ea83fed
FB
2494}
2495
fd4a04eb
TS
2496FLOAT_ROUNDOP(round, l, d)
2497FLOAT_ROUNDOP(round, l, s)
2498FLOAT_ROUNDOP(round, w, d)
2499FLOAT_ROUNDOP(round, w, s)
6ea83fed 2500
fd4a04eb
TS
2501FLOAT_ROUNDOP(trunc, l, d)
2502FLOAT_ROUNDOP(trunc, l, s)
2503FLOAT_ROUNDOP(trunc, w, d)
2504FLOAT_ROUNDOP(trunc, w, s)
6ea83fed 2505
fd4a04eb
TS
2506FLOAT_ROUNDOP(ceil, l, d)
2507FLOAT_ROUNDOP(ceil, l, s)
2508FLOAT_ROUNDOP(ceil, w, d)
2509FLOAT_ROUNDOP(ceil, w, s)
2510
2511FLOAT_ROUNDOP(floor, l, d)
2512FLOAT_ROUNDOP(floor, l, s)
2513FLOAT_ROUNDOP(floor, w, d)
2514FLOAT_ROUNDOP(floor, w, s)
2515#undef FLOAR_ROUNDOP
6ea83fed 2516
5a5012ec
TS
2517FLOAT_OP(movf, d)
2518{
ead9360e 2519 if (!(env->fpu->fcr31 & PARAM1))
5a5012ec
TS
2520 DT2 = DT0;
2521 DEBUG_FPU_STATE();
2522 RETURN();
2523}
2524FLOAT_OP(movf, s)
2525{
ead9360e 2526 if (!(env->fpu->fcr31 & PARAM1))
5a5012ec
TS
2527 WT2 = WT0;
2528 DEBUG_FPU_STATE();
2529 RETURN();
2530}
2531FLOAT_OP(movf, ps)
2532{
ead9360e 2533 if (!(env->fpu->fcr31 & PARAM1)) {
5a5012ec
TS
2534 WT2 = WT0;
2535 WTH2 = WTH0;
2536 }
2537 DEBUG_FPU_STATE();
2538 RETURN();
2539}
2540FLOAT_OP(movt, d)
2541{
ead9360e 2542 if (env->fpu->fcr31 & PARAM1)
5a5012ec
TS
2543 DT2 = DT0;
2544 DEBUG_FPU_STATE();
2545 RETURN();
2546}
2547FLOAT_OP(movt, s)
2548{
ead9360e 2549 if (env->fpu->fcr31 & PARAM1)
5a5012ec
TS
2550 WT2 = WT0;
2551 DEBUG_FPU_STATE();
2552 RETURN();
2553}
2554FLOAT_OP(movt, ps)
2555{
ead9360e 2556 if (env->fpu->fcr31 & PARAM1) {
5a5012ec
TS
2557 WT2 = WT0;
2558 WTH2 = WTH0;
2559 }
2560 DEBUG_FPU_STATE();
2561 RETURN();
2562}
2563FLOAT_OP(movz, d)
2564{
2565 if (!T0)
2566 DT2 = DT0;
2567 DEBUG_FPU_STATE();
2568 RETURN();
2569}
2570FLOAT_OP(movz, s)
2571{
2572 if (!T0)
2573 WT2 = WT0;
2574 DEBUG_FPU_STATE();
2575 RETURN();
2576}
2577FLOAT_OP(movz, ps)
2578{
2579 if (!T0) {
2580 WT2 = WT0;
2581 WTH2 = WTH0;
2582 }
2583 DEBUG_FPU_STATE();
2584 RETURN();
2585}
2586FLOAT_OP(movn, d)
2587{
2588 if (T0)
2589 DT2 = DT0;
2590 DEBUG_FPU_STATE();
2591 RETURN();
2592}
2593FLOAT_OP(movn, s)
2594{
2595 if (T0)
2596 WT2 = WT0;
2597 DEBUG_FPU_STATE();
2598 RETURN();
2599}
2600FLOAT_OP(movn, ps)
2601{
2602 if (T0) {
2603 WT2 = WT0;
2604 WTH2 = WTH0;
2605 }
2606 DEBUG_FPU_STATE();
2607 RETURN();
2608}
2609
57fa1fb3
TS
2610/* operations calling helpers, for s, d and ps */
2611#define FLOAT_HOP(name) \
6ea83fed
FB
2612FLOAT_OP(name, d) \
2613{ \
fd4a04eb 2614 CALL_FROM_TB0(do_float_ ## name ## _d); \
6ea83fed 2615 DEBUG_FPU_STATE(); \
fbcc6828 2616 RETURN(); \
6ea83fed
FB
2617} \
2618FLOAT_OP(name, s) \
2619{ \
fd4a04eb 2620 CALL_FROM_TB0(do_float_ ## name ## _s); \
5a5012ec 2621 DEBUG_FPU_STATE(); \
fbcc6828 2622 RETURN(); \
5a5012ec
TS
2623} \
2624FLOAT_OP(name, ps) \
2625{ \
fd4a04eb 2626 CALL_FROM_TB0(do_float_ ## name ## _ps); \
6ea83fed 2627 DEBUG_FPU_STATE(); \
fbcc6828 2628 RETURN(); \
6ea83fed 2629}
57fa1fb3
TS
2630FLOAT_HOP(add)
2631FLOAT_HOP(sub)
2632FLOAT_HOP(mul)
2633FLOAT_HOP(div)
2634FLOAT_HOP(recip2)
2635FLOAT_HOP(rsqrt2)
2636FLOAT_HOP(rsqrt1)
2637FLOAT_HOP(recip1)
2638#undef FLOAT_HOP
2639
2640/* operations calling helpers, for s and d */
2641#define FLOAT_HOP(name) \
2642FLOAT_OP(name, d) \
2643{ \
2644 CALL_FROM_TB0(do_float_ ## name ## _d); \
2645 DEBUG_FPU_STATE(); \
2646 RETURN(); \
2647} \
2648FLOAT_OP(name, s) \
2649{ \
2650 CALL_FROM_TB0(do_float_ ## name ## _s); \
2651 DEBUG_FPU_STATE(); \
2652 RETURN(); \
2653}
2654FLOAT_HOP(rsqrt)
2655FLOAT_HOP(recip)
2656#undef FLOAT_HOP
6ea83fed 2657
57fa1fb3
TS
2658/* operations calling helpers, for ps */
2659#define FLOAT_HOP(name) \
2660FLOAT_OP(name, ps) \
2661{ \
2662 CALL_FROM_TB0(do_float_ ## name ## _ps); \
2663 DEBUG_FPU_STATE(); \
2664 RETURN(); \
fbcc6828 2665}
57fa1fb3
TS
2666FLOAT_HOP(addr)
2667FLOAT_HOP(mulr)
2668#undef FLOAT_HOP
fbcc6828 2669
5a5012ec
TS
2670/* ternary operations */
2671#define FLOAT_TERNOP(name1, name2) \
2672FLOAT_OP(name1 ## name2, d) \
2673{ \
ead9360e
TS
2674 FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status); \
2675 FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status); \
5a5012ec 2676 DEBUG_FPU_STATE(); \
fbcc6828 2677 RETURN(); \
5a5012ec
TS
2678} \
2679FLOAT_OP(name1 ## name2, s) \
2680{ \
ead9360e
TS
2681 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
2682 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
5a5012ec 2683 DEBUG_FPU_STATE(); \
fbcc6828 2684 RETURN(); \
5a5012ec
TS
2685} \
2686FLOAT_OP(name1 ## name2, ps) \
2687{ \
ead9360e
TS
2688 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
2689 FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \
2690 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
2691 FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \
5a5012ec 2692 DEBUG_FPU_STATE(); \
fbcc6828 2693 RETURN(); \
5a5012ec
TS
2694}
2695FLOAT_TERNOP(mul, add)
2696FLOAT_TERNOP(mul, sub)
2697#undef FLOAT_TERNOP
2698
fbcc6828
TS
2699/* negated ternary operations */
2700#define FLOAT_NTERNOP(name1, name2) \
2701FLOAT_OP(n ## name1 ## name2, d) \
2702{ \
ead9360e
TS
2703 FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status); \
2704 FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status); \
fbcc6828
TS
2705 FDT2 ^= 1ULL << 63; \
2706 DEBUG_FPU_STATE(); \
2707 RETURN(); \
2708} \
2709FLOAT_OP(n ## name1 ## name2, s) \
2710{ \
ead9360e
TS
2711 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
2712 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
fbcc6828
TS
2713 FST2 ^= 1 << 31; \
2714 DEBUG_FPU_STATE(); \
2715 RETURN(); \
2716} \
2717FLOAT_OP(n ## name1 ## name2, ps) \
2718{ \
ead9360e
TS
2719 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
2720 FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \
2721 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
2722 FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \
fbcc6828
TS
2723 FST2 ^= 1 << 31; \
2724 FSTH2 ^= 1 << 31; \
2725 DEBUG_FPU_STATE(); \
2726 RETURN(); \
2727}
2728FLOAT_NTERNOP(mul, add)
2729FLOAT_NTERNOP(mul, sub)
2730#undef FLOAT_NTERNOP
2731
6ea83fed
FB
2732/* unary operations, modifying fp status */
2733#define FLOAT_UNOP(name) \
2734FLOAT_OP(name, d) \
2735{ \
ead9360e 2736 FDT2 = float64_ ## name(FDT0, &env->fpu->fp_status); \
6ea83fed 2737 DEBUG_FPU_STATE(); \
fbcc6828 2738 RETURN(); \
6ea83fed
FB
2739} \
2740FLOAT_OP(name, s) \
2741{ \
ead9360e 2742 FST2 = float32_ ## name(FST0, &env->fpu->fp_status); \
6ea83fed 2743 DEBUG_FPU_STATE(); \
57fa1fb3 2744 RETURN(); \
6ea83fed
FB
2745}
2746FLOAT_UNOP(sqrt)
2747#undef FLOAT_UNOP
2748
2749/* unary operations, not modifying fp status */
2750#define FLOAT_UNOP(name) \
2751FLOAT_OP(name, d) \
2752{ \
2753 FDT2 = float64_ ## name(FDT0); \
2754 DEBUG_FPU_STATE(); \
fbcc6828 2755 RETURN(); \
6ea83fed
FB
2756} \
2757FLOAT_OP(name, s) \
2758{ \
2759 FST2 = float32_ ## name(FST0); \
2760 DEBUG_FPU_STATE(); \
fbcc6828 2761 RETURN(); \
5a5012ec
TS
2762} \
2763FLOAT_OP(name, ps) \
2764{ \
2765 FST2 = float32_ ## name(FST0); \
2766 FSTH2 = float32_ ## name(FSTH0); \
2767 DEBUG_FPU_STATE(); \
fbcc6828 2768 RETURN(); \
6ea83fed
FB
2769}
2770FLOAT_UNOP(abs)
2771FLOAT_UNOP(chs)
2772#undef FLOAT_UNOP
2773
2774FLOAT_OP(mov, d)
2775{
2776 FDT2 = FDT0;
2777 DEBUG_FPU_STATE();
2778 RETURN();
2779}
2780FLOAT_OP(mov, s)
2781{
2782 FST2 = FST0;
2783 DEBUG_FPU_STATE();
2784 RETURN();
2785}
5a5012ec
TS
2786FLOAT_OP(mov, ps)
2787{
2788 FST2 = FST0;
2789 FSTH2 = FSTH0;
2790 DEBUG_FPU_STATE();
2791 RETURN();
2792}
2793FLOAT_OP(alnv, ps)
2794{
2795 switch (T0 & 0x7) {
2796 case 0:
2797 FST2 = FST0;
2798 FSTH2 = FSTH0;
2799 break;
2800 case 4:
2801#ifdef TARGET_WORDS_BIGENDIAN
2802 FSTH2 = FST0;
2803 FST2 = FSTH1;
2804#else
2805 FSTH2 = FST1;
2806 FST2 = FSTH0;
2807#endif
2808 break;
2809 default: /* unpredictable */
2810 break;
2811 }
2812 DEBUG_FPU_STATE();
2813 RETURN();
2814}
6ea83fed
FB
2815
2816#ifdef CONFIG_SOFTFLOAT
2817#define clear_invalid() do { \
ead9360e 2818 int flags = get_float_exception_flags(&env->fpu->fp_status); \
6ea83fed 2819 flags &= ~float_flag_invalid; \
ead9360e 2820 set_float_exception_flags(flags, &env->fpu->fp_status); \
6ea83fed
FB
2821} while(0)
2822#else
2823#define clear_invalid() do { } while(0)
2824#endif
2825
2826extern void dump_fpu_s(CPUState *env);
2827
fd4a04eb
TS
2828#define CMP_OP(fmt, op) \
2829void OPPROTO op_cmp ## _ ## fmt ## _ ## op(void) \
2830{ \
2831 CALL_FROM_TB1(do_cmp ## _ ## fmt ## _ ## op, PARAM1); \
2832 DEBUG_FPU_STATE(); \
2833 RETURN(); \
2834} \
2835void OPPROTO op_cmpabs ## _ ## fmt ## _ ## op(void) \
2836{ \
2837 CALL_FROM_TB1(do_cmpabs ## _ ## fmt ## _ ## op, PARAM1); \
2838 DEBUG_FPU_STATE(); \
2839 RETURN(); \
2840}
2841#define CMP_OPS(op) \
2842CMP_OP(d, op) \
2843CMP_OP(s, op) \
2844CMP_OP(ps, op)
2845
2846CMP_OPS(f)
2847CMP_OPS(un)
2848CMP_OPS(eq)
2849CMP_OPS(ueq)
2850CMP_OPS(olt)
2851CMP_OPS(ult)
2852CMP_OPS(ole)
2853CMP_OPS(ule)
2854CMP_OPS(sf)
2855CMP_OPS(ngle)
2856CMP_OPS(seq)
2857CMP_OPS(ngl)
2858CMP_OPS(lt)
2859CMP_OPS(nge)
2860CMP_OPS(le)
2861CMP_OPS(ngt)
2862#undef CMP_OPS
2863#undef CMP_OP
6ea83fed
FB
2864
2865void op_bc1f (void)
2866{
ead9360e 2867 T0 = !!(~GET_FP_COND(env->fpu) & (0x1 << PARAM1));
5a5012ec
TS
2868 DEBUG_FPU_STATE();
2869 RETURN();
2870}
fd4a04eb 2871void op_bc1any2f (void)
5a5012ec 2872{
ead9360e 2873 T0 = !!(~GET_FP_COND(env->fpu) & (0x3 << PARAM1));
5a5012ec
TS
2874 DEBUG_FPU_STATE();
2875 RETURN();
2876}
fd4a04eb 2877void op_bc1any4f (void)
5a5012ec 2878{
ead9360e 2879 T0 = !!(~GET_FP_COND(env->fpu) & (0xf << PARAM1));
6ea83fed
FB
2880 DEBUG_FPU_STATE();
2881 RETURN();
2882}
2883
2884void op_bc1t (void)
2885{
ead9360e 2886 T0 = !!(GET_FP_COND(env->fpu) & (0x1 << PARAM1));
5a5012ec
TS
2887 DEBUG_FPU_STATE();
2888 RETURN();
2889}
fd4a04eb 2890void op_bc1any2t (void)
5a5012ec 2891{
ead9360e 2892 T0 = !!(GET_FP_COND(env->fpu) & (0x3 << PARAM1));
5a5012ec
TS
2893 DEBUG_FPU_STATE();
2894 RETURN();
2895}
fd4a04eb 2896void op_bc1any4t (void)
5a5012ec 2897{
ead9360e 2898 T0 = !!(GET_FP_COND(env->fpu) & (0xf << PARAM1));
6ea83fed
FB
2899 DEBUG_FPU_STATE();
2900 RETURN();
2901}
6ea83fed 2902
6af0bf9c
FB
2903void op_tlbwi (void)
2904{
ead9360e 2905 CALL_FROM_TB0(env->tlb->do_tlbwi);
6af0bf9c
FB
2906 RETURN();
2907}
2908
2909void op_tlbwr (void)
2910{
ead9360e 2911 CALL_FROM_TB0(env->tlb->do_tlbwr);
6af0bf9c
FB
2912 RETURN();
2913}
2914
2915void op_tlbp (void)
2916{
ead9360e 2917 CALL_FROM_TB0(env->tlb->do_tlbp);
6af0bf9c
FB
2918 RETURN();
2919}
2920
2921void op_tlbr (void)
2922{
ead9360e 2923 CALL_FROM_TB0(env->tlb->do_tlbr);
6af0bf9c
FB
2924 RETURN();
2925}
6af0bf9c
FB
2926
2927/* Specials */
6f5b89a0
TS
2928#if defined (CONFIG_USER_ONLY)
2929void op_tls_value (void)
2930{
5a5012ec 2931 T0 = env->tls_value;
6f5b89a0
TS
2932}
2933#endif
2934
6af0bf9c
FB
2935void op_pmon (void)
2936{
2937 CALL_FROM_TB1(do_pmon, PARAM1);
7a387fff
TS
2938 RETURN();
2939}
2940
2941void op_di (void)
2942{
7a387fff 2943 T0 = env->CP0_Status;
4de9b249
TS
2944 env->CP0_Status = T0 & ~(1 << CP0St_IE);
2945 CALL_FROM_TB1(cpu_mips_update_irq, env);
7a387fff
TS
2946 RETURN();
2947}
2948
2949void op_ei (void)
2950{
7a387fff 2951 T0 = env->CP0_Status;
4de9b249
TS
2952 env->CP0_Status = T0 | (1 << CP0St_IE);
2953 CALL_FROM_TB1(cpu_mips_update_irq, env);
7a387fff 2954 RETURN();
6af0bf9c
FB
2955}
2956
2957void op_trap (void)
2958{
2959 if (T0) {
1579a72e 2960 CALL_FROM_TB1(do_raise_exception, EXCP_TRAP);
6af0bf9c
FB
2961 }
2962 RETURN();
2963}
2964
4ad40f36
FB
2965void op_debug (void)
2966{
7a387fff
TS
2967 CALL_FROM_TB1(do_raise_exception, EXCP_DEBUG);
2968 RETURN();
4ad40f36
FB
2969}
2970
6af0bf9c
FB
2971void op_set_lladdr (void)
2972{
2973 env->CP0_LLAddr = T2;
7a387fff 2974 RETURN();
6af0bf9c
FB
2975}
2976
f41c52f1
TS
2977void debug_pre_eret (void);
2978void debug_post_eret (void);
6af0bf9c
FB
2979void op_eret (void)
2980{
f41c52f1
TS
2981 if (loglevel & CPU_LOG_EXEC)
2982 CALL_FROM_TB0(debug_pre_eret);
24c7b0e3 2983 if (env->CP0_Status & (1 << CP0St_ERL)) {
ead9360e 2984 env->PC[env->current_tc] = env->CP0_ErrorEPC;
24c7b0e3 2985 env->CP0_Status &= ~(1 << CP0St_ERL);
51e11d9e 2986 } else {
ead9360e 2987 env->PC[env->current_tc] = env->CP0_EPC;
24c7b0e3 2988 env->CP0_Status &= ~(1 << CP0St_EXL);
51e11d9e 2989 }
08fa4bab 2990 CALL_FROM_TB1(compute_hflags, env);
f41c52f1
TS
2991 if (loglevel & CPU_LOG_EXEC)
2992 CALL_FROM_TB0(debug_post_eret);
6af0bf9c 2993 env->CP0_LLAddr = 1;
7a387fff 2994 RETURN();
6af0bf9c
FB
2995}
2996
2997void op_deret (void)
2998{
f41c52f1
TS
2999 if (loglevel & CPU_LOG_EXEC)
3000 CALL_FROM_TB0(debug_pre_eret);
ead9360e 3001 env->PC[env->current_tc] = env->CP0_DEPC;
08fa4bab
TS
3002 env->hflags &= MIPS_HFLAG_DM;
3003 CALL_FROM_TB1(compute_hflags, env);
f41c52f1
TS
3004 if (loglevel & CPU_LOG_EXEC)
3005 CALL_FROM_TB0(debug_post_eret);
24c7b0e3 3006 env->CP0_LLAddr = 1;
7a387fff
TS
3007 RETURN();
3008}
3009
3010void op_rdhwr_cpunum(void)
3011{
387a8fe5
TS
3012 if ((env->hflags & MIPS_HFLAG_CP0) ||
3013 (env->CP0_HWREna & (1 << 0)))
1579a72e 3014 T0 = env->CP0_EBase & 0x3ff;
7a387fff 3015 else
1579a72e 3016 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
7a387fff
TS
3017 RETURN();
3018}
3019
3020void op_rdhwr_synci_step(void)
3021{
387a8fe5
TS
3022 if ((env->hflags & MIPS_HFLAG_CP0) ||
3023 (env->CP0_HWREna & (1 << 1)))
1579a72e 3024 T0 = env->SYNCI_Step;
7a387fff 3025 else
1579a72e 3026 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
7a387fff
TS
3027 RETURN();
3028}
3029
3030void op_rdhwr_cc(void)
3031{
387a8fe5
TS
3032 if ((env->hflags & MIPS_HFLAG_CP0) ||
3033 (env->CP0_HWREna & (1 << 2)))
1579a72e 3034 T0 = env->CP0_Count;
7a387fff 3035 else
1579a72e 3036 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
7a387fff
TS
3037 RETURN();
3038}
3039
3040void op_rdhwr_ccres(void)
3041{
387a8fe5
TS
3042 if ((env->hflags & MIPS_HFLAG_CP0) ||
3043 (env->CP0_HWREna & (1 << 3)))
1579a72e 3044 T0 = env->CCRes;
7a387fff 3045 else
1579a72e
TS
3046 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
3047 RETURN();
3048}
3049
6af0bf9c
FB
3050void op_save_state (void)
3051{
3052 env->hflags = PARAM1;
3053 RETURN();
3054}
3055
3056void op_save_pc (void)
3057{
ead9360e 3058 env->PC[env->current_tc] = PARAM1;
6af0bf9c
FB
3059 RETURN();
3060}
3061
540635ba 3062#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
9b9e4393
TS
3063void op_save_pc64 (void)
3064{
ead9360e 3065 env->PC[env->current_tc] = ((uint64_t)PARAM1 << 32) | (uint32_t)PARAM2;
9b9e4393
TS
3066 RETURN();
3067}
3068#endif
3069
16c00cb2
TS
3070void op_interrupt_restart (void)
3071{
3072 if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
3073 !(env->CP0_Status & (1 << CP0St_ERL)) &&
3074 !(env->hflags & MIPS_HFLAG_DM) &&
3075 (env->CP0_Status & (1 << CP0St_IE)) &&
3076 (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask)) {
3077 env->CP0_Cause &= ~(0x1f << CP0Ca_EC);
3078 CALL_FROM_TB1(do_raise_exception, EXCP_EXT_INTERRUPT);
3079 }
3080 RETURN();
3081}
3082
6af0bf9c
FB
3083void op_raise_exception (void)
3084{
3085 CALL_FROM_TB1(do_raise_exception, PARAM1);
3086 RETURN();
3087}
3088
3089void op_raise_exception_err (void)
3090{
3091 CALL_FROM_TB2(do_raise_exception_err, PARAM1, PARAM2);
3092 RETURN();
3093}
3094
3095void op_exit_tb (void)
3096{
3097 EXIT_TB();
7a387fff 3098 RETURN();
6af0bf9c
FB
3099}
3100
4ad40f36
FB
3101void op_wait (void)
3102{
3103 env->halted = 1;
3104 CALL_FROM_TB1(do_raise_exception, EXCP_HLT);
7a387fff
TS
3105 RETURN();
3106}
3107
3108/* Bitfield operations. */
3109void op_ext(void)
3110{
3111 unsigned int pos = PARAM1;
3112 unsigned int size = PARAM2;
3113
f757d6ff 3114 T0 = ((uint32_t)T1 >> pos) & ((size < 32) ? ((1 << size) - 1) : ~0);
7a387fff
TS
3115 RETURN();
3116}
3117
3118void op_ins(void)
3119{
3120 unsigned int pos = PARAM1;
3121 unsigned int size = PARAM2;
f757d6ff 3122 target_ulong mask = ((size < 32) ? ((1 << size) - 1) : ~0) << pos;
7a387fff 3123
171b31e7 3124 T0 = (T0 & ~mask) | (((uint32_t)T1 << pos) & mask);
7a387fff
TS
3125 RETURN();
3126}
3127
3128void op_wsbh(void)
3129{
3130 T0 = ((T1 << 8) & ~0x00FF00FF) | ((T1 >> 8) & 0x00FF00FF);
3131 RETURN();
3132}
3133
540635ba 3134#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
c570fd16
TS
3135void op_dext(void)
3136{
3137 unsigned int pos = PARAM1;
3138 unsigned int size = PARAM2;
3139
f757d6ff 3140 T0 = (T1 >> pos) & ((size < 32) ? ((1 << size) - 1) : ~0);
c570fd16
TS
3141 RETURN();
3142}
3143
3144void op_dins(void)
3145{
3146 unsigned int pos = PARAM1;
3147 unsigned int size = PARAM2;
f757d6ff 3148 target_ulong mask = ((size < 32) ? ((1 << size) - 1) : ~0) << pos;
c570fd16 3149
171b31e7 3150 T0 = (T0 & ~mask) | ((T1 << pos) & mask);
c570fd16
TS
3151 RETURN();
3152}
3153
7a387fff
TS
3154void op_dsbh(void)
3155{
3156 T0 = ((T1 << 8) & ~0x00FF00FF00FF00FFULL) | ((T1 >> 8) & 0x00FF00FF00FF00FFULL);
3157 RETURN();
3158}
3159
3160void op_dshd(void)
3161{
3162 T0 = ((T1 << 16) & ~0x0000FFFF0000FFFFULL) | ((T1 >> 16) & 0x0000FFFF0000FFFFULL);
3163 RETURN();
3164}
c570fd16 3165#endif
7a387fff
TS
3166
3167void op_seb(void)
3168{
3169 T0 = ((T1 & 0xFF) ^ 0x80) - 0x80;
3170 RETURN();
3171}
3172
3173void op_seh(void)
3174{
3175 T0 = ((T1 & 0xFFFF) ^ 0x8000) - 0x8000;
3176 RETURN();
4ad40f36 3177}
This page took 0.522926 seconds and 4 git commands to generate.