]> git.proxmox.com Git - mirror_qemu.git/blame - target-mips/op.c
Clean out the N32 macros from target-mips, and introduce MIPS ABI specific
[mirror_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"
05f778c8 25#include "host-utils.h"
6af0bf9c 26
1b351e52 27#ifndef CALL_FROM_TB0
5a5012ec 28#define CALL_FROM_TB0(func) func()
1b351e52
FB
29#endif
30#ifndef CALL_FROM_TB1
5a5012ec 31#define CALL_FROM_TB1(func, arg0) func(arg0)
1b351e52
FB
32#endif
33#ifndef CALL_FROM_TB1_CONST16
5a5012ec 34#define CALL_FROM_TB1_CONST16(func, arg0) CALL_FROM_TB1(func, arg0)
1b351e52
FB
35#endif
36#ifndef CALL_FROM_TB2
5a5012ec 37#define CALL_FROM_TB2(func, arg0, arg1) func(arg0, arg1)
1b351e52
FB
38#endif
39#ifndef CALL_FROM_TB2_CONST16
40#define CALL_FROM_TB2_CONST16(func, arg0, arg1) \
5a5012ec 41 CALL_FROM_TB2(func, arg0, arg1)
1b351e52
FB
42#endif
43#ifndef CALL_FROM_TB3
5a5012ec 44#define CALL_FROM_TB3(func, arg0, arg1, arg2) func(arg0, arg1, arg2)
1b351e52
FB
45#endif
46#ifndef CALL_FROM_TB4
47#define CALL_FROM_TB4(func, arg0, arg1, arg2, arg3) \
5a5012ec 48 func(arg0, arg1, arg2, arg3)
1b351e52
FB
49#endif
50
6af0bf9c
FB
51#define REG 1
52#include "op_template.c"
53#undef REG
54#define REG 2
55#include "op_template.c"
56#undef REG
57#define REG 3
58#include "op_template.c"
59#undef REG
60#define REG 4
61#include "op_template.c"
62#undef REG
63#define REG 5
64#include "op_template.c"
65#undef REG
66#define REG 6
67#include "op_template.c"
68#undef REG
69#define REG 7
70#include "op_template.c"
71#undef REG
72#define REG 8
73#include "op_template.c"
74#undef REG
75#define REG 9
76#include "op_template.c"
77#undef REG
78#define REG 10
79#include "op_template.c"
80#undef REG
81#define REG 11
82#include "op_template.c"
83#undef REG
84#define REG 12
85#include "op_template.c"
86#undef REG
87#define REG 13
88#include "op_template.c"
89#undef REG
90#define REG 14
91#include "op_template.c"
92#undef REG
93#define REG 15
94#include "op_template.c"
95#undef REG
96#define REG 16
97#include "op_template.c"
98#undef REG
99#define REG 17
100#include "op_template.c"
101#undef REG
102#define REG 18
103#include "op_template.c"
104#undef REG
105#define REG 19
106#include "op_template.c"
107#undef REG
108#define REG 20
109#include "op_template.c"
110#undef REG
111#define REG 21
112#include "op_template.c"
113#undef REG
114#define REG 22
115#include "op_template.c"
116#undef REG
117#define REG 23
118#include "op_template.c"
119#undef REG
120#define REG 24
121#include "op_template.c"
122#undef REG
123#define REG 25
124#include "op_template.c"
125#undef REG
126#define REG 26
127#include "op_template.c"
128#undef REG
129#define REG 27
130#include "op_template.c"
131#undef REG
132#define REG 28
133#include "op_template.c"
134#undef REG
135#define REG 29
136#include "op_template.c"
137#undef REG
138#define REG 30
139#include "op_template.c"
140#undef REG
141#define REG 31
142#include "op_template.c"
143#undef REG
144
c570fd16 145#define TN
6af0bf9c
FB
146#include "op_template.c"
147#undef TN
148
5a5012ec 149#define FREG 0
6ea83fed 150#include "fop_template.c"
5a5012ec
TS
151#undef FREG
152#define FREG 1
6ea83fed 153#include "fop_template.c"
5a5012ec
TS
154#undef FREG
155#define FREG 2
6ea83fed 156#include "fop_template.c"
5a5012ec
TS
157#undef FREG
158#define FREG 3
6ea83fed 159#include "fop_template.c"
5a5012ec
TS
160#undef FREG
161#define FREG 4
6ea83fed 162#include "fop_template.c"
5a5012ec
TS
163#undef FREG
164#define FREG 5
6ea83fed 165#include "fop_template.c"
5a5012ec
TS
166#undef FREG
167#define FREG 6
6ea83fed 168#include "fop_template.c"
5a5012ec
TS
169#undef FREG
170#define FREG 7
6ea83fed 171#include "fop_template.c"
5a5012ec
TS
172#undef FREG
173#define FREG 8
6ea83fed 174#include "fop_template.c"
5a5012ec
TS
175#undef FREG
176#define FREG 9
6ea83fed 177#include "fop_template.c"
5a5012ec
TS
178#undef FREG
179#define FREG 10
6ea83fed 180#include "fop_template.c"
5a5012ec
TS
181#undef FREG
182#define FREG 11
6ea83fed 183#include "fop_template.c"
5a5012ec
TS
184#undef FREG
185#define FREG 12
6ea83fed 186#include "fop_template.c"
5a5012ec
TS
187#undef FREG
188#define FREG 13
6ea83fed 189#include "fop_template.c"
5a5012ec
TS
190#undef FREG
191#define FREG 14
6ea83fed 192#include "fop_template.c"
5a5012ec
TS
193#undef FREG
194#define FREG 15
6ea83fed 195#include "fop_template.c"
5a5012ec
TS
196#undef FREG
197#define FREG 16
6ea83fed 198#include "fop_template.c"
5a5012ec
TS
199#undef FREG
200#define FREG 17
6ea83fed 201#include "fop_template.c"
5a5012ec
TS
202#undef FREG
203#define FREG 18
6ea83fed 204#include "fop_template.c"
5a5012ec
TS
205#undef FREG
206#define FREG 19
6ea83fed 207#include "fop_template.c"
5a5012ec
TS
208#undef FREG
209#define FREG 20
6ea83fed 210#include "fop_template.c"
5a5012ec
TS
211#undef FREG
212#define FREG 21
6ea83fed 213#include "fop_template.c"
5a5012ec
TS
214#undef FREG
215#define FREG 22
6ea83fed 216#include "fop_template.c"
5a5012ec
TS
217#undef FREG
218#define FREG 23
6ea83fed 219#include "fop_template.c"
5a5012ec
TS
220#undef FREG
221#define FREG 24
6ea83fed 222#include "fop_template.c"
5a5012ec
TS
223#undef FREG
224#define FREG 25
6ea83fed 225#include "fop_template.c"
5a5012ec
TS
226#undef FREG
227#define FREG 26
6ea83fed 228#include "fop_template.c"
5a5012ec
TS
229#undef FREG
230#define FREG 27
6ea83fed 231#include "fop_template.c"
5a5012ec
TS
232#undef FREG
233#define FREG 28
6ea83fed 234#include "fop_template.c"
5a5012ec
TS
235#undef FREG
236#define FREG 29
6ea83fed 237#include "fop_template.c"
5a5012ec
TS
238#undef FREG
239#define FREG 30
6ea83fed 240#include "fop_template.c"
5a5012ec
TS
241#undef FREG
242#define FREG 31
6ea83fed 243#include "fop_template.c"
5a5012ec 244#undef FREG
6ea83fed
FB
245
246#define FTN
247#include "fop_template.c"
248#undef FTN
249
6af0bf9c
FB
250void op_dup_T0 (void)
251{
252 T2 = T0;
253 RETURN();
254}
255
256void op_load_HI (void)
257{
ead9360e 258 T0 = env->HI[PARAM1][env->current_tc];
6af0bf9c
FB
259 RETURN();
260}
261
262void op_store_HI (void)
263{
ead9360e 264 env->HI[PARAM1][env->current_tc] = T0;
6af0bf9c
FB
265 RETURN();
266}
267
268void op_load_LO (void)
269{
ead9360e 270 T0 = env->LO[PARAM1][env->current_tc];
6af0bf9c
FB
271 RETURN();
272}
273
274void op_store_LO (void)
275{
ead9360e 276 env->LO[PARAM1][env->current_tc] = T0;
6af0bf9c
FB
277 RETURN();
278}
279
280/* Load and store */
281#define MEMSUFFIX _raw
282#include "op_mem.c"
283#undef MEMSUFFIX
284#if !defined(CONFIG_USER_ONLY)
285#define MEMSUFFIX _user
286#include "op_mem.c"
287#undef MEMSUFFIX
288
623a930e
TS
289#define MEMSUFFIX _super
290#include "op_mem.c"
291#undef MEMSUFFIX
292
6af0bf9c
FB
293#define MEMSUFFIX _kernel
294#include "op_mem.c"
295#undef MEMSUFFIX
296#endif
297
a6763a58
TS
298/* Addresses computation */
299void op_addr_add (void)
300{
301/* For compatibility with 32-bit code, data reference in user mode
302 with Status_UX = 0 should be casted to 32-bit and sign extended.
303 See the MIPS64 PRA manual, section 4.10. */
d26bc211 304#if defined(TARGET_MIPS64)
623a930e 305 if (((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
a6763a58
TS
306 !(env->CP0_Status & (1 << CP0St_UX)))
307 T0 = (int64_t)(int32_t)(T0 + T1);
308 else
309#endif
310 T0 += T1;
311 RETURN();
312}
313
6af0bf9c
FB
314/* Arithmetic */
315void op_add (void)
316{
5dc4b744 317 T0 = (int32_t)((int32_t)T0 + (int32_t)T1);
6af0bf9c
FB
318 RETURN();
319}
320
321void op_addo (void)
322{
323 target_ulong tmp;
324
c570fd16
TS
325 tmp = (int32_t)T0;
326 T0 = (int32_t)T0 + (int32_t)T1;
76e050c2 327 if (((tmp ^ T1 ^ (-1)) & (T0 ^ T1)) >> 31) {
c570fd16 328 /* operands of same sign, result different sign */
1579a72e 329 CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
6af0bf9c 330 }
5dc4b744 331 T0 = (int32_t)T0;
6af0bf9c
FB
332 RETURN();
333}
334
335void op_sub (void)
336{
5dc4b744 337 T0 = (int32_t)((int32_t)T0 - (int32_t)T1);
6af0bf9c
FB
338 RETURN();
339}
340
341void op_subo (void)
342{
343 target_ulong tmp;
344
c570fd16 345 tmp = (int32_t)T0;
6af0bf9c 346 T0 = (int32_t)T0 - (int32_t)T1;
76e050c2 347 if (((tmp ^ T1) & (tmp ^ T0)) >> 31) {
c570fd16 348 /* operands of different sign, first operand and result different sign */
1579a72e 349 CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
6af0bf9c 350 }
5dc4b744 351 T0 = (int32_t)T0;
6af0bf9c
FB
352 RETURN();
353}
354
355void op_mul (void)
356{
5dc4b744 357 T0 = (int32_t)((int32_t)T0 * (int32_t)T1);
6af0bf9c
FB
358 RETURN();
359}
360
80c27194
TS
361#if HOST_LONG_BITS < 64
362void op_div (void)
363{
364 CALL_FROM_TB0(do_div);
365 RETURN();
366}
367#else
6af0bf9c
FB
368void op_div (void)
369{
370 if (T1 != 0) {
ead9360e
TS
371 env->LO[0][env->current_tc] = (int32_t)((int64_t)(int32_t)T0 / (int32_t)T1);
372 env->HI[0][env->current_tc] = (int32_t)((int64_t)(int32_t)T0 % (int32_t)T1);
6af0bf9c
FB
373 }
374 RETURN();
375}
80c27194 376#endif
6af0bf9c
FB
377
378void op_divu (void)
c570fd16
TS
379{
380 if (T1 != 0) {
ead9360e
TS
381 env->LO[0][env->current_tc] = (int32_t)((uint32_t)T0 / (uint32_t)T1);
382 env->HI[0][env->current_tc] = (int32_t)((uint32_t)T0 % (uint32_t)T1);
c570fd16
TS
383 }
384 RETURN();
385}
386
d26bc211 387#if defined(TARGET_MIPS64)
c570fd16
TS
388/* Arithmetic */
389void op_dadd (void)
390{
391 T0 += T1;
392 RETURN();
393}
394
395void op_daddo (void)
396{
397 target_long tmp;
398
399 tmp = T0;
400 T0 += T1;
401 if (((tmp ^ T1 ^ (-1)) & (T0 ^ T1)) >> 63) {
402 /* operands of same sign, result different sign */
1579a72e 403 CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
c570fd16
TS
404 }
405 RETURN();
406}
407
408void op_dsub (void)
409{
410 T0 -= T1;
411 RETURN();
412}
413
414void op_dsubo (void)
415{
416 target_long tmp;
417
418 tmp = T0;
419 T0 = (int64_t)T0 - (int64_t)T1;
420 if (((tmp ^ T1) & (tmp ^ T0)) >> 63) {
421 /* operands of different sign, first operand and result different sign */
1579a72e 422 CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
c570fd16
TS
423 }
424 RETURN();
425}
426
427void op_dmul (void)
428{
429 T0 = (int64_t)T0 * (int64_t)T1;
430 RETURN();
431}
432
c570fd16
TS
433/* Those might call libgcc functions. */
434void op_ddiv (void)
435{
436 do_ddiv();
437 RETURN();
438}
439
80c27194 440#if TARGET_LONG_BITS > HOST_LONG_BITS
c570fd16
TS
441void op_ddivu (void)
442{
443 do_ddivu();
444 RETURN();
445}
446#else
c570fd16 447void op_ddivu (void)
6af0bf9c
FB
448{
449 if (T1 != 0) {
ead9360e
TS
450 env->LO[0][env->current_tc] = T0 / T1;
451 env->HI[0][env->current_tc] = T0 % T1;
6af0bf9c
FB
452 }
453 RETURN();
454}
c570fd16 455#endif
d26bc211 456#endif /* TARGET_MIPS64 */
6af0bf9c
FB
457
458/* Logical */
459void op_and (void)
460{
461 T0 &= T1;
462 RETURN();
463}
464
465void op_nor (void)
466{
467 T0 = ~(T0 | T1);
468 RETURN();
469}
470
471void op_or (void)
472{
473 T0 |= T1;
474 RETURN();
475}
476
477void op_xor (void)
478{
479 T0 ^= T1;
480 RETURN();
481}
482
483void op_sll (void)
484{
5a63bcb2 485 T0 = (int32_t)((uint32_t)T0 << T1);
6af0bf9c
FB
486 RETURN();
487}
488
489void op_sra (void)
490{
5a63bcb2 491 T0 = (int32_t)((int32_t)T0 >> T1);
6af0bf9c
FB
492 RETURN();
493}
494
495void op_srl (void)
496{
5a63bcb2 497 T0 = (int32_t)((uint32_t)T0 >> T1);
6af0bf9c
FB
498 RETURN();
499}
500
7a387fff
TS
501void op_rotr (void)
502{
503 target_ulong tmp;
504
505 if (T1) {
5a63bcb2
TS
506 tmp = (int32_t)((uint32_t)T0 << (0x20 - T1));
507 T0 = (int32_t)((uint32_t)T0 >> T1) | tmp;
508 }
7a387fff
TS
509 RETURN();
510}
511
6af0bf9c
FB
512void op_sllv (void)
513{
5dc4b744 514 T0 = (int32_t)((uint32_t)T1 << ((uint32_t)T0 & 0x1F));
6af0bf9c
FB
515 RETURN();
516}
517
518void op_srav (void)
519{
5dc4b744 520 T0 = (int32_t)((int32_t)T1 >> (T0 & 0x1F));
6af0bf9c
FB
521 RETURN();
522}
523
524void op_srlv (void)
525{
5dc4b744 526 T0 = (int32_t)((uint32_t)T1 >> (T0 & 0x1F));
6af0bf9c
FB
527 RETURN();
528}
529
7a387fff
TS
530void op_rotrv (void)
531{
532 target_ulong tmp;
533
534 T0 &= 0x1F;
535 if (T0) {
5dc4b744
TS
536 tmp = (int32_t)((uint32_t)T1 << (0x20 - T0));
537 T0 = (int32_t)((uint32_t)T1 >> T0) | tmp;
7a387fff
TS
538 } else
539 T0 = T1;
540 RETURN();
541}
542
6af0bf9c
FB
543void op_clo (void)
544{
05f778c8 545 T0 = clo32(T0);
6af0bf9c
FB
546 RETURN();
547}
548
549void op_clz (void)
550{
05f778c8 551 T0 = clz32(T0);
6af0bf9c
FB
552 RETURN();
553}
554
d26bc211 555#if defined(TARGET_MIPS64)
c570fd16
TS
556
557#if TARGET_LONG_BITS > HOST_LONG_BITS
558/* Those might call libgcc functions. */
559void op_dsll (void)
6af0bf9c 560{
c570fd16
TS
561 CALL_FROM_TB0(do_dsll);
562 RETURN();
6af0bf9c
FB
563}
564
c570fd16 565void op_dsll32 (void)
6af0bf9c 566{
c570fd16
TS
567 CALL_FROM_TB0(do_dsll32);
568 RETURN();
6af0bf9c
FB
569}
570
c570fd16 571void op_dsra (void)
6af0bf9c 572{
c570fd16 573 CALL_FROM_TB0(do_dsra);
6af0bf9c
FB
574 RETURN();
575}
576
c570fd16 577void op_dsra32 (void)
6af0bf9c 578{
c570fd16 579 CALL_FROM_TB0(do_dsra32);
6af0bf9c
FB
580 RETURN();
581}
582
c570fd16 583void op_dsrl (void)
6af0bf9c 584{
c570fd16
TS
585 CALL_FROM_TB0(do_dsrl);
586 RETURN();
587}
6af0bf9c 588
c570fd16
TS
589void op_dsrl32 (void)
590{
591 CALL_FROM_TB0(do_dsrl32);
6af0bf9c
FB
592 RETURN();
593}
594
c570fd16 595void op_drotr (void)
6af0bf9c 596{
c570fd16
TS
597 CALL_FROM_TB0(do_drotr);
598 RETURN();
599}
6af0bf9c 600
c570fd16
TS
601void op_drotr32 (void)
602{
603 CALL_FROM_TB0(do_drotr32);
6af0bf9c
FB
604 RETURN();
605}
606
c570fd16 607void op_dsllv (void)
6af0bf9c 608{
c570fd16
TS
609 CALL_FROM_TB0(do_dsllv);
610 RETURN();
611}
6af0bf9c 612
c570fd16
TS
613void op_dsrav (void)
614{
615 CALL_FROM_TB0(do_dsrav);
6af0bf9c
FB
616 RETURN();
617}
618
c570fd16 619void op_dsrlv (void)
6af0bf9c 620{
c570fd16
TS
621 CALL_FROM_TB0(do_dsrlv);
622 RETURN();
623}
6af0bf9c 624
c570fd16
TS
625void op_drotrv (void)
626{
627 CALL_FROM_TB0(do_drotrv);
6af0bf9c
FB
628 RETURN();
629}
c570fd16 630
05f778c8
TS
631void op_dclo (void)
632{
633 CALL_FROM_TB0(do_dclo);
634 RETURN();
635}
636
637void op_dclz (void)
638{
639 CALL_FROM_TB0(do_dclz);
640 RETURN();
641}
642
c570fd16
TS
643#else /* TARGET_LONG_BITS > HOST_LONG_BITS */
644
645void op_dsll (void)
646{
647 T0 = T0 << T1;
648 RETURN();
649}
650
651void op_dsll32 (void)
652{
653 T0 = T0 << (T1 + 32);
654 RETURN();
655}
656
657void op_dsra (void)
658{
659 T0 = (int64_t)T0 >> T1;
660 RETURN();
661}
662
663void op_dsra32 (void)
664{
665 T0 = (int64_t)T0 >> (T1 + 32);
666 RETURN();
667}
668
669void op_dsrl (void)
670{
671 T0 = T0 >> T1;
672 RETURN();
673}
674
675void op_dsrl32 (void)
676{
677 T0 = T0 >> (T1 + 32);
678 RETURN();
679}
680
681void op_drotr (void)
682{
683 target_ulong tmp;
684
685 if (T1) {
686 tmp = T0 << (0x40 - T1);
687 T0 = (T0 >> T1) | tmp;
5a63bcb2 688 }
c570fd16
TS
689 RETURN();
690}
691
692void op_drotr32 (void)
693{
694 target_ulong tmp;
695
696 if (T1) {
697 tmp = T0 << (0x40 - (32 + T1));
698 T0 = (T0 >> (32 + T1)) | tmp;
5a63bcb2 699 }
c570fd16
TS
700 RETURN();
701}
702
703void op_dsllv (void)
704{
705 T0 = T1 << (T0 & 0x3F);
706 RETURN();
707}
708
709void op_dsrav (void)
710{
711 T0 = (int64_t)T1 >> (T0 & 0x3F);
712 RETURN();
713}
714
715void op_dsrlv (void)
716{
717 T0 = T1 >> (T0 & 0x3F);
718 RETURN();
719}
720
721void op_drotrv (void)
722{
723 target_ulong tmp;
724
725 T0 &= 0x3F;
726 if (T0) {
727 tmp = T1 << (0x40 - T0);
728 T0 = (T1 >> T0) | tmp;
729 } else
730 T0 = T1;
731 RETURN();
732}
c570fd16
TS
733
734void op_dclo (void)
735{
05f778c8 736 T0 = clo64(T0);
c570fd16
TS
737 RETURN();
738}
739
740void op_dclz (void)
741{
05f778c8 742 T0 = clz64(T0);
c570fd16
TS
743 RETURN();
744}
05f778c8 745#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
d26bc211 746#endif /* TARGET_MIPS64 */
c570fd16
TS
747
748/* 64 bits arithmetic */
749#if TARGET_LONG_BITS > HOST_LONG_BITS
6af0bf9c
FB
750void op_mult (void)
751{
752 CALL_FROM_TB0(do_mult);
753 RETURN();
754}
755
756void op_multu (void)
757{
758 CALL_FROM_TB0(do_multu);
759 RETURN();
760}
761
762void op_madd (void)
763{
764 CALL_FROM_TB0(do_madd);
765 RETURN();
766}
767
768void op_maddu (void)
769{
770 CALL_FROM_TB0(do_maddu);
771 RETURN();
772}
773
774void op_msub (void)
775{
776 CALL_FROM_TB0(do_msub);
777 RETURN();
778}
779
780void op_msubu (void)
781{
782 CALL_FROM_TB0(do_msubu);
783 RETURN();
784}
c570fd16
TS
785
786#else /* TARGET_LONG_BITS > HOST_LONG_BITS */
787
aa343735 788static always_inline uint64_t get_HILO (void)
c570fd16 789{
ead9360e
TS
790 return ((uint64_t)env->HI[0][env->current_tc] << 32) |
791 ((uint64_t)(uint32_t)env->LO[0][env->current_tc]);
c570fd16
TS
792}
793
aa343735 794static always_inline void set_HILO (uint64_t HILO)
c570fd16 795{
ead9360e
TS
796 env->LO[0][env->current_tc] = (int32_t)(HILO & 0xFFFFFFFF);
797 env->HI[0][env->current_tc] = (int32_t)(HILO >> 32);
c570fd16
TS
798}
799
800void op_mult (void)
801{
802 set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
803 RETURN();
804}
805
806void op_multu (void)
807{
808 set_HILO((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
809 RETURN();
810}
811
812void op_madd (void)
813{
814 int64_t tmp;
815
816 tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
817 set_HILO((int64_t)get_HILO() + tmp);
818 RETURN();
819}
820
821void op_maddu (void)
822{
823 uint64_t tmp;
824
825 tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
826 set_HILO(get_HILO() + tmp);
827 RETURN();
828}
829
830void op_msub (void)
831{
832 int64_t tmp;
833
834 tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
835 set_HILO((int64_t)get_HILO() - tmp);
836 RETURN();
837}
838
839void op_msubu (void)
840{
841 uint64_t tmp;
842
843 tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
844 set_HILO(get_HILO() - tmp);
845 RETURN();
846}
847#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
848
d26bc211 849#if defined(TARGET_MIPS64)
c570fd16
TS
850void op_dmult (void)
851{
5592a750 852 CALL_FROM_TB4(muls64, &(env->LO[0][env->current_tc]), &(env->HI[0][env->current_tc]), T0, T1);
c570fd16
TS
853 RETURN();
854}
855
856void op_dmultu (void)
857{
5592a750 858 CALL_FROM_TB4(mulu64, &(env->LO[0][env->current_tc]), &(env->HI[0][env->current_tc]), T0, T1);
c570fd16
TS
859 RETURN();
860}
6af0bf9c
FB
861#endif
862
863/* Conditional moves */
864void op_movn (void)
865{
866 if (T1 != 0)
ead9360e 867 env->gpr[PARAM1][env->current_tc] = T0;
6af0bf9c
FB
868 RETURN();
869}
870
871void op_movz (void)
872{
873 if (T1 == 0)
ead9360e 874 env->gpr[PARAM1][env->current_tc] = T0;
6af0bf9c
FB
875 RETURN();
876}
877
7a387fff
TS
878void op_movf (void)
879{
ead9360e 880 if (!(env->fpu->fcr31 & PARAM1))
5a5012ec 881 T0 = T1;
7a387fff
TS
882 RETURN();
883}
884
885void op_movt (void)
886{
ead9360e 887 if (env->fpu->fcr31 & PARAM1)
5a5012ec 888 T0 = T1;
7a387fff
TS
889 RETURN();
890}
891
6af0bf9c
FB
892/* Tests */
893#define OP_COND(name, cond) \
894void glue(op_, name) (void) \
895{ \
896 if (cond) { \
897 T0 = 1; \
898 } else { \
899 T0 = 0; \
900 } \
901 RETURN(); \
902}
903
904OP_COND(eq, T0 == T1);
905OP_COND(ne, T0 != T1);
f469b9db 906OP_COND(ge, (target_long)T0 >= (target_long)T1);
6af0bf9c 907OP_COND(geu, T0 >= T1);
f469b9db 908OP_COND(lt, (target_long)T0 < (target_long)T1);
6af0bf9c 909OP_COND(ltu, T0 < T1);
f469b9db
TS
910OP_COND(gez, (target_long)T0 >= 0);
911OP_COND(gtz, (target_long)T0 > 0);
912OP_COND(lez, (target_long)T0 <= 0);
913OP_COND(ltz, (target_long)T0 < 0);
6af0bf9c 914
7a387fff 915/* Branches */
c53be334
FB
916void OPPROTO op_goto_tb0(void)
917{
918 GOTO_TB(op_goto_tb0, PARAM1, 0);
7a387fff 919 RETURN();
c53be334
FB
920}
921
922void OPPROTO op_goto_tb1(void)
923{
924 GOTO_TB(op_goto_tb1, PARAM1, 1);
7a387fff 925 RETURN();
c53be334 926}
6af0bf9c
FB
927
928/* Branch to register */
929void op_save_breg_target (void)
930{
931 env->btarget = T2;
7a387fff 932 RETURN();
6af0bf9c
FB
933}
934
935void op_restore_breg_target (void)
936{
937 T2 = env->btarget;
7a387fff 938 RETURN();
6af0bf9c
FB
939}
940
941void op_breg (void)
942{
ead9360e 943 env->PC[env->current_tc] = T2;
6af0bf9c
FB
944 RETURN();
945}
946
6af0bf9c
FB
947void op_save_btarget (void)
948{
949 env->btarget = PARAM1;
950 RETURN();
951}
952
d26bc211 953#if defined(TARGET_MIPS64)
9b9e4393
TS
954void op_save_btarget64 (void)
955{
956 env->btarget = ((uint64_t)PARAM1 << 32) | (uint32_t)PARAM2;
957 RETURN();
958}
959#endif
960
6af0bf9c
FB
961/* Conditional branch */
962void op_set_bcond (void)
963{
964 T2 = T0;
965 RETURN();
966}
967
968void op_save_bcond (void)
969{
970 env->bcond = T2;
971 RETURN();
972}
973
974void op_restore_bcond (void)
975{
976 T2 = env->bcond;
977 RETURN();
978}
979
c53be334 980void op_jnz_T2 (void)
6af0bf9c 981{
c53be334
FB
982 if (T2)
983 GOTO_LABEL_PARAM(1);
6af0bf9c
FB
984 RETURN();
985}
986
987/* CP0 functions */
873eb012 988void op_mfc0_index (void)
6af0bf9c 989{
9c2149c8 990 T0 = env->CP0_Index;
873eb012
TS
991 RETURN();
992}
993
ead9360e
TS
994void op_mfc0_mvpcontrol (void)
995{
996 T0 = env->mvp->CP0_MVPControl;
997 RETURN();
998}
999
1000void op_mfc0_mvpconf0 (void)
1001{
1002 T0 = env->mvp->CP0_MVPConf0;
1003 RETURN();
1004}
1005
1006void op_mfc0_mvpconf1 (void)
1007{
1008 T0 = env->mvp->CP0_MVPConf1;
1009 RETURN();
1010}
1011
873eb012
TS
1012void op_mfc0_random (void)
1013{
1014 CALL_FROM_TB0(do_mfc0_random);
1015 RETURN();
1016}
1017
ead9360e
TS
1018void op_mfc0_vpecontrol (void)
1019{
1020 T0 = env->CP0_VPEControl;
1021 RETURN();
1022}
1023
1024void op_mfc0_vpeconf0 (void)
1025{
1026 T0 = env->CP0_VPEConf0;
1027 RETURN();
1028}
1029
1030void op_mfc0_vpeconf1 (void)
1031{
1032 T0 = env->CP0_VPEConf1;
1033 RETURN();
1034}
1035
1036void op_mfc0_yqmask (void)
1037{
1038 T0 = env->CP0_YQMask;
1039 RETURN();
1040}
1041
1042void op_mfc0_vpeschedule (void)
1043{
1044 T0 = env->CP0_VPESchedule;
1045 RETURN();
1046}
1047
1048void op_mfc0_vpeschefback (void)
1049{
1050 T0 = env->CP0_VPEScheFBack;
1051 RETURN();
1052}
1053
1054void op_mfc0_vpeopt (void)
1055{
1056 T0 = env->CP0_VPEOpt;
1057 RETURN();
1058}
1059
873eb012
TS
1060void op_mfc0_entrylo0 (void)
1061{
9c2149c8 1062 T0 = (int32_t)env->CP0_EntryLo0;
873eb012
TS
1063 RETURN();
1064}
1065
ead9360e
TS
1066void op_mfc0_tcstatus (void)
1067{
1068 T0 = env->CP0_TCStatus[env->current_tc];
1069 RETURN();
1070}
1071
1072void op_mftc0_tcstatus(void)
1073{
1074 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1075
1076 T0 = env->CP0_TCStatus[other_tc];
1077 RETURN();
1078}
1079
1080void op_mfc0_tcbind (void)
1081{
1082 T0 = env->CP0_TCBind[env->current_tc];
1083 RETURN();
1084}
1085
1086void op_mftc0_tcbind(void)
1087{
1088 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1089
1090 T0 = env->CP0_TCBind[other_tc];
1091 RETURN();
1092}
1093
1094void op_mfc0_tcrestart (void)
1095{
1096 T0 = env->PC[env->current_tc];
1097 RETURN();
1098}
1099
1100void op_mftc0_tcrestart(void)
1101{
1102 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1103
1104 T0 = env->PC[other_tc];
1105 RETURN();
1106}
1107
1108void op_mfc0_tchalt (void)
1109{
1110 T0 = env->CP0_TCHalt[env->current_tc];
1111 RETURN();
1112}
1113
1114void op_mftc0_tchalt(void)
1115{
1116 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1117
1118 T0 = env->CP0_TCHalt[other_tc];
1119 RETURN();
1120}
1121
1122void op_mfc0_tccontext (void)
1123{
1124 T0 = env->CP0_TCContext[env->current_tc];
1125 RETURN();
1126}
1127
1128void op_mftc0_tccontext(void)
1129{
1130 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1131
1132 T0 = env->CP0_TCContext[other_tc];
1133 RETURN();
1134}
1135
1136void op_mfc0_tcschedule (void)
1137{
1138 T0 = env->CP0_TCSchedule[env->current_tc];
1139 RETURN();
1140}
1141
1142void op_mftc0_tcschedule(void)
1143{
1144 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1145
1146 T0 = env->CP0_TCSchedule[other_tc];
1147 RETURN();
1148}
1149
1150void op_mfc0_tcschefback (void)
1151{
1152 T0 = env->CP0_TCScheFBack[env->current_tc];
1153 RETURN();
1154}
1155
1156void op_mftc0_tcschefback(void)
1157{
1158 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1159
1160 T0 = env->CP0_TCScheFBack[other_tc];
1161 RETURN();
1162}
1163
873eb012
TS
1164void op_mfc0_entrylo1 (void)
1165{
9c2149c8 1166 T0 = (int32_t)env->CP0_EntryLo1;
873eb012
TS
1167 RETURN();
1168}
1169
1170void op_mfc0_context (void)
1171{
9c2149c8 1172 T0 = (int32_t)env->CP0_Context;
873eb012
TS
1173 RETURN();
1174}
1175
1176void op_mfc0_pagemask (void)
1177{
9c2149c8 1178 T0 = env->CP0_PageMask;
873eb012
TS
1179 RETURN();
1180}
1181
7a387fff
TS
1182void op_mfc0_pagegrain (void)
1183{
9c2149c8 1184 T0 = env->CP0_PageGrain;
7a387fff
TS
1185 RETURN();
1186}
1187
873eb012
TS
1188void op_mfc0_wired (void)
1189{
9c2149c8 1190 T0 = env->CP0_Wired;
873eb012
TS
1191 RETURN();
1192}
1193
ead9360e
TS
1194void op_mfc0_srsconf0 (void)
1195{
1196 T0 = env->CP0_SRSConf0;
1197 RETURN();
1198}
1199
1200void op_mfc0_srsconf1 (void)
1201{
1202 T0 = env->CP0_SRSConf1;
1203 RETURN();
1204}
1205
1206void op_mfc0_srsconf2 (void)
1207{
1208 T0 = env->CP0_SRSConf2;
1209 RETURN();
1210}
1211
1212void op_mfc0_srsconf3 (void)
1213{
1214 T0 = env->CP0_SRSConf3;
1215 RETURN();
1216}
1217
1218void op_mfc0_srsconf4 (void)
1219{
1220 T0 = env->CP0_SRSConf4;
1221 RETURN();
1222}
1223
7a387fff
TS
1224void op_mfc0_hwrena (void)
1225{
9c2149c8 1226 T0 = env->CP0_HWREna;
7a387fff
TS
1227 RETURN();
1228}
1229
873eb012
TS
1230void op_mfc0_badvaddr (void)
1231{
9c2149c8 1232 T0 = (int32_t)env->CP0_BadVAddr;
873eb012
TS
1233 RETURN();
1234}
1235
1236void op_mfc0_count (void)
1237{
1238 CALL_FROM_TB0(do_mfc0_count);
1239 RETURN();
1240}
1241
1242void op_mfc0_entryhi (void)
1243{
9c2149c8 1244 T0 = (int32_t)env->CP0_EntryHi;
873eb012
TS
1245 RETURN();
1246}
1247
ead9360e
TS
1248void op_mftc0_entryhi(void)
1249{
1250 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1251
1252 T0 = (env->CP0_EntryHi & ~0xff) | (env->CP0_TCStatus[other_tc] & 0xff);
1253 RETURN();
1254}
1255
873eb012
TS
1256void op_mfc0_compare (void)
1257{
9c2149c8 1258 T0 = env->CP0_Compare;
873eb012
TS
1259 RETURN();
1260}
1261
1262void op_mfc0_status (void)
1263{
9c2149c8 1264 T0 = env->CP0_Status;
873eb012
TS
1265 RETURN();
1266}
1267
ead9360e
TS
1268void op_mftc0_status(void)
1269{
1270 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1271 uint32_t tcstatus = env->CP0_TCStatus[other_tc];
1272
1273 T0 = env->CP0_Status & ~0xf1000018;
1274 T0 |= tcstatus & (0xf << CP0TCSt_TCU0);
1275 T0 |= (tcstatus & (1 << CP0TCSt_TMX)) >> (CP0TCSt_TMX - CP0St_MX);
623a930e 1276 T0 |= (tcstatus & (0x3 << CP0TCSt_TKSU)) >> (CP0TCSt_TKSU - CP0St_KSU);
ead9360e
TS
1277 RETURN();
1278}
1279
7a387fff
TS
1280void op_mfc0_intctl (void)
1281{
9c2149c8 1282 T0 = env->CP0_IntCtl;
7a387fff
TS
1283 RETURN();
1284}
1285
1286void op_mfc0_srsctl (void)
1287{
9c2149c8
TS
1288 T0 = env->CP0_SRSCtl;
1289 RETURN();
1290}
1291
1292void op_mfc0_srsmap (void)
1293{
1294 T0 = env->CP0_SRSMap;
7a387fff
TS
1295 RETURN();
1296}
1297
873eb012
TS
1298void op_mfc0_cause (void)
1299{
9c2149c8 1300 T0 = env->CP0_Cause;
873eb012
TS
1301 RETURN();
1302}
1303
1304void op_mfc0_epc (void)
1305{
9c2149c8 1306 T0 = (int32_t)env->CP0_EPC;
873eb012
TS
1307 RETURN();
1308}
1309
1310void op_mfc0_prid (void)
1311{
9c2149c8 1312 T0 = env->CP0_PRid;
873eb012
TS
1313 RETURN();
1314}
1315
7a387fff
TS
1316void op_mfc0_ebase (void)
1317{
b29a0341 1318 T0 = env->CP0_EBase;
7a387fff
TS
1319 RETURN();
1320}
1321
873eb012
TS
1322void op_mfc0_config0 (void)
1323{
9c2149c8 1324 T0 = env->CP0_Config0;
873eb012
TS
1325 RETURN();
1326}
1327
1328void op_mfc0_config1 (void)
1329{
9c2149c8 1330 T0 = env->CP0_Config1;
873eb012
TS
1331 RETURN();
1332}
1333
7a387fff
TS
1334void op_mfc0_config2 (void)
1335{
9c2149c8 1336 T0 = env->CP0_Config2;
7a387fff
TS
1337 RETURN();
1338}
1339
1340void op_mfc0_config3 (void)
1341{
9c2149c8 1342 T0 = env->CP0_Config3;
7a387fff
TS
1343 RETURN();
1344}
1345
e397ee33
TS
1346void op_mfc0_config6 (void)
1347{
1348 T0 = env->CP0_Config6;
1349 RETURN();
1350}
1351
1352void op_mfc0_config7 (void)
1353{
1354 T0 = env->CP0_Config7;
1355 RETURN();
1356}
1357
873eb012
TS
1358void op_mfc0_lladdr (void)
1359{
9c2149c8 1360 T0 = (int32_t)env->CP0_LLAddr >> 4;
873eb012
TS
1361 RETURN();
1362}
1363
fd88b6ab 1364void op_mfc0_watchlo (void)
873eb012 1365{
fd88b6ab 1366 T0 = (int32_t)env->CP0_WatchLo[PARAM1];
873eb012
TS
1367 RETURN();
1368}
1369
fd88b6ab 1370void op_mfc0_watchhi (void)
873eb012 1371{
fd88b6ab 1372 T0 = env->CP0_WatchHi[PARAM1];
873eb012
TS
1373 RETURN();
1374}
1375
7a387fff
TS
1376void op_mfc0_xcontext (void)
1377{
9c2149c8 1378 T0 = (int32_t)env->CP0_XContext;
7a387fff
TS
1379 RETURN();
1380}
1381
1382void op_mfc0_framemask (void)
1383{
1384 T0 = env->CP0_Framemask;
1385 RETURN();
1386}
1387
873eb012
TS
1388void op_mfc0_debug (void)
1389{
9c2149c8 1390 T0 = env->CP0_Debug;
873eb012
TS
1391 if (env->hflags & MIPS_HFLAG_DM)
1392 T0 |= 1 << CP0DB_DM;
1393 RETURN();
1394}
1395
ead9360e
TS
1396void op_mftc0_debug(void)
1397{
1398 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1399
1400 /* XXX: Might be wrong, check with EJTAG spec. */
1401 T0 = (env->CP0_Debug & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
1402 (env->CP0_Debug_tcstatus[other_tc] &
1403 ((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
1404 RETURN();
1405}
1406
873eb012
TS
1407void op_mfc0_depc (void)
1408{
9c2149c8 1409 T0 = (int32_t)env->CP0_DEPC;
873eb012
TS
1410 RETURN();
1411}
1412
7a387fff
TS
1413void op_mfc0_performance0 (void)
1414{
9c2149c8 1415 T0 = env->CP0_Performance0;
7a387fff
TS
1416 RETURN();
1417}
1418
873eb012
TS
1419void op_mfc0_taglo (void)
1420{
9c2149c8 1421 T0 = env->CP0_TagLo;
873eb012
TS
1422 RETURN();
1423}
1424
1425void op_mfc0_datalo (void)
1426{
9c2149c8 1427 T0 = env->CP0_DataLo;
873eb012
TS
1428 RETURN();
1429}
1430
7a387fff
TS
1431void op_mfc0_taghi (void)
1432{
9c2149c8 1433 T0 = env->CP0_TagHi;
7a387fff
TS
1434 RETURN();
1435}
1436
1437void op_mfc0_datahi (void)
1438{
9c2149c8 1439 T0 = env->CP0_DataHi;
7a387fff
TS
1440 RETURN();
1441}
1442
873eb012
TS
1443void op_mfc0_errorepc (void)
1444{
9c2149c8 1445 T0 = (int32_t)env->CP0_ErrorEPC;
873eb012
TS
1446 RETURN();
1447}
1448
1449void op_mfc0_desave (void)
1450{
9c2149c8 1451 T0 = env->CP0_DESAVE;
6af0bf9c
FB
1452 RETURN();
1453}
1454
8c0fdd85 1455void op_mtc0_index (void)
6af0bf9c 1456{
60445285
TS
1457 int num = 1;
1458 unsigned int tmp = env->tlb->nb_tlb;
1459
1460 do {
1461 tmp >>= 1;
1462 num <<= 1;
1463 } while (tmp);
1464 env->CP0_Index = (env->CP0_Index & 0x80000000) | (T0 & (num - 1));
ead9360e
TS
1465 RETURN();
1466}
1467
1468void op_mtc0_mvpcontrol (void)
1469{
1470 uint32_t mask = 0;
1471 uint32_t newval;
1472
1473 if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP))
1474 mask |= (1 << CP0MVPCo_CPA) | (1 << CP0MVPCo_VPC) |
1475 (1 << CP0MVPCo_EVP);
1476 if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1477 mask |= (1 << CP0MVPCo_STLB);
1478 newval = (env->mvp->CP0_MVPControl & ~mask) | (T0 & mask);
1479
1480 // TODO: Enable/disable shared TLB, enable/disable VPEs.
1481
1482 env->mvp->CP0_MVPControl = newval;
1483 RETURN();
1484}
1485
1486void op_mtc0_vpecontrol (void)
1487{
1488 uint32_t mask;
1489 uint32_t newval;
1490
1491 mask = (1 << CP0VPECo_YSI) | (1 << CP0VPECo_GSI) |
1492 (1 << CP0VPECo_TE) | (0xff << CP0VPECo_TargTC);
1493 newval = (env->CP0_VPEControl & ~mask) | (T0 & mask);
1494
1495 /* Yield scheduler intercept not implemented. */
1496 /* Gating storage scheduler intercept not implemented. */
1497
1498 // TODO: Enable/disable TCs.
1499
1500 env->CP0_VPEControl = newval;
1501 RETURN();
1502}
1503
1504void op_mtc0_vpeconf0 (void)
1505{
1506 uint32_t mask = 0;
1507 uint32_t newval;
1508
1509 if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) {
1510 if (env->CP0_VPEConf0 & (1 << CP0VPEC0_VPA))
1511 mask |= (0xff << CP0VPEC0_XTC);
1512 mask |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
1513 }
1514 newval = (env->CP0_VPEConf0 & ~mask) | (T0 & mask);
1515
1516 // TODO: TC exclusive handling due to ERL/EXL.
1517
1518 env->CP0_VPEConf0 = newval;
1519 RETURN();
1520}
1521
1522void op_mtc0_vpeconf1 (void)
1523{
1524 uint32_t mask = 0;
1525 uint32_t newval;
1526
1527 if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1528 mask |= (0xff << CP0VPEC1_NCX) | (0xff << CP0VPEC1_NCP2) |
1529 (0xff << CP0VPEC1_NCP1);
1530 newval = (env->CP0_VPEConf1 & ~mask) | (T0 & mask);
1531
1532 /* UDI not implemented. */
1533 /* CP2 not implemented. */
1534
1535 // TODO: Handle FPU (CP1) binding.
1536
1537 env->CP0_VPEConf1 = newval;
1538 RETURN();
1539}
1540
1541void op_mtc0_yqmask (void)
1542{
1543 /* Yield qualifier inputs not implemented. */
1544 env->CP0_YQMask = 0x00000000;
1545 RETURN();
1546}
1547
1548void op_mtc0_vpeschedule (void)
1549{
1550 env->CP0_VPESchedule = T0;
1551 RETURN();
1552}
1553
1554void op_mtc0_vpeschefback (void)
1555{
1556 env->CP0_VPEScheFBack = T0;
1557 RETURN();
1558}
1559
1560void op_mtc0_vpeopt (void)
1561{
1562 env->CP0_VPEOpt = T0 & 0x0000ffff;
8c0fdd85
TS
1563 RETURN();
1564}
1565
1566void op_mtc0_entrylo0 (void)
1567{
7a387fff
TS
1568 /* Large physaddr not implemented */
1569 /* 1k pages not implemented */
f1b0aa5d 1570 env->CP0_EntryLo0 = T0 & 0x3FFFFFFF;
8c0fdd85
TS
1571 RETURN();
1572}
1573
ead9360e
TS
1574void op_mtc0_tcstatus (void)
1575{
1576 uint32_t mask = env->CP0_TCStatus_rw_bitmask;
1577 uint32_t newval;
1578
1579 newval = (env->CP0_TCStatus[env->current_tc] & ~mask) | (T0 & mask);
1580
1581 // TODO: Sync with CP0_Status.
1582
1583 env->CP0_TCStatus[env->current_tc] = newval;
1584 RETURN();
1585}
1586
1587void op_mttc0_tcstatus (void)
1588{
1589 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1590
1591 // TODO: Sync with CP0_Status.
1592
1593 env->CP0_TCStatus[other_tc] = T0;
1594 RETURN();
1595}
1596
1597void op_mtc0_tcbind (void)
1598{
1599 uint32_t mask = (1 << CP0TCBd_TBE);
1600 uint32_t newval;
1601
1602 if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1603 mask |= (1 << CP0TCBd_CurVPE);
1604 newval = (env->CP0_TCBind[env->current_tc] & ~mask) | (T0 & mask);
1605 env->CP0_TCBind[env->current_tc] = newval;
1606 RETURN();
1607}
1608
1609void op_mttc0_tcbind (void)
1610{
1611 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1612 uint32_t mask = (1 << CP0TCBd_TBE);
1613 uint32_t newval;
1614
1615 if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1616 mask |= (1 << CP0TCBd_CurVPE);
1617 newval = (env->CP0_TCBind[other_tc] & ~mask) | (T0 & mask);
1618 env->CP0_TCBind[other_tc] = newval;
1619 RETURN();
1620}
1621
1622void op_mtc0_tcrestart (void)
1623{
1624 env->PC[env->current_tc] = T0;
1625 env->CP0_TCStatus[env->current_tc] &= ~(1 << CP0TCSt_TDS);
1626 env->CP0_LLAddr = 0ULL;
1627 /* MIPS16 not implemented. */
1628 RETURN();
1629}
1630
1631void op_mttc0_tcrestart (void)
1632{
1633 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1634
1635 env->PC[other_tc] = T0;
1636 env->CP0_TCStatus[other_tc] &= ~(1 << CP0TCSt_TDS);
1637 env->CP0_LLAddr = 0ULL;
1638 /* MIPS16 not implemented. */
1639 RETURN();
1640}
1641
1642void op_mtc0_tchalt (void)
1643{
1644 env->CP0_TCHalt[env->current_tc] = T0 & 0x1;
1645
1646 // TODO: Halt TC / Restart (if allocated+active) TC.
1647
1648 RETURN();
1649}
1650
1651void op_mttc0_tchalt (void)
1652{
1653 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1654
1655 // TODO: Halt TC / Restart (if allocated+active) TC.
1656
1657 env->CP0_TCHalt[other_tc] = T0;
1658 RETURN();
1659}
1660
1661void op_mtc0_tccontext (void)
1662{
1663 env->CP0_TCContext[env->current_tc] = T0;
1664 RETURN();
1665}
1666
1667void op_mttc0_tccontext (void)
1668{
1669 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1670
1671 env->CP0_TCContext[other_tc] = T0;
1672 RETURN();
1673}
1674
1675void op_mtc0_tcschedule (void)
1676{
1677 env->CP0_TCSchedule[env->current_tc] = T0;
1678 RETURN();
1679}
1680
1681void op_mttc0_tcschedule (void)
1682{
1683 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1684
1685 env->CP0_TCSchedule[other_tc] = T0;
1686 RETURN();
1687}
1688
1689void op_mtc0_tcschefback (void)
1690{
1691 env->CP0_TCScheFBack[env->current_tc] = T0;
1692 RETURN();
1693}
1694
1695void op_mttc0_tcschefback (void)
1696{
1697 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1698
1699 env->CP0_TCScheFBack[other_tc] = T0;
1700 RETURN();
1701}
1702
8c0fdd85
TS
1703void op_mtc0_entrylo1 (void)
1704{
7a387fff
TS
1705 /* Large physaddr not implemented */
1706 /* 1k pages not implemented */
f1b0aa5d 1707 env->CP0_EntryLo1 = T0 & 0x3FFFFFFF;
8c0fdd85
TS
1708 RETURN();
1709}
1710
1711void op_mtc0_context (void)
1712{
534ce69f 1713 env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (T0 & ~0x007FFFFF);
8c0fdd85
TS
1714 RETURN();
1715}
1716
1717void op_mtc0_pagemask (void)
1718{
7a387fff 1719 /* 1k pages not implemented */
f2e9ebef 1720 env->CP0_PageMask = T0 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
7a387fff
TS
1721 RETURN();
1722}
1723
1724void op_mtc0_pagegrain (void)
1725{
1726 /* SmartMIPS not implemented */
1727 /* Large physaddr not implemented */
1728 /* 1k pages not implemented */
1729 env->CP0_PageGrain = 0;
8c0fdd85
TS
1730 RETURN();
1731}
1732
1733void op_mtc0_wired (void)
1734{
ead9360e
TS
1735 env->CP0_Wired = T0 % env->tlb->nb_tlb;
1736 RETURN();
1737}
1738
1739void op_mtc0_srsconf0 (void)
1740{
1741 env->CP0_SRSConf0 |= T0 & env->CP0_SRSConf0_rw_bitmask;
1742 RETURN();
1743}
1744
1745void op_mtc0_srsconf1 (void)
1746{
1747 env->CP0_SRSConf1 |= T0 & env->CP0_SRSConf1_rw_bitmask;
1748 RETURN();
1749}
1750
1751void op_mtc0_srsconf2 (void)
1752{
1753 env->CP0_SRSConf2 |= T0 & env->CP0_SRSConf2_rw_bitmask;
1754 RETURN();
1755}
1756
1757void op_mtc0_srsconf3 (void)
1758{
1759 env->CP0_SRSConf3 |= T0 & env->CP0_SRSConf3_rw_bitmask;
1760 RETURN();
1761}
1762
1763void op_mtc0_srsconf4 (void)
1764{
1765 env->CP0_SRSConf4 |= T0 & env->CP0_SRSConf4_rw_bitmask;
7a387fff
TS
1766 RETURN();
1767}
1768
1769void op_mtc0_hwrena (void)
1770{
1771 env->CP0_HWREna = T0 & 0x0000000F;
8c0fdd85
TS
1772 RETURN();
1773}
1774
1775void op_mtc0_count (void)
1776{
1777 CALL_FROM_TB2(cpu_mips_store_count, env, T0);
1778 RETURN();
1779}
1780
1781void op_mtc0_entryhi (void)
1782{
0feef828 1783 target_ulong old, val;
8c0fdd85 1784
7a387fff 1785 /* 1k pages not implemented */
100ce988 1786 val = T0 & ((TARGET_PAGE_MASK << 1) | 0xFF);
d26bc211 1787#if defined(TARGET_MIPS64)
e034e2c3 1788 val &= env->SEGMask;
100ce988 1789#endif
8c0fdd85
TS
1790 old = env->CP0_EntryHi;
1791 env->CP0_EntryHi = val;
ead9360e
TS
1792 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
1793 uint32_t tcst = env->CP0_TCStatus[env->current_tc] & ~0xff;
1794 env->CP0_TCStatus[env->current_tc] = tcst | (val & 0xff);
1795 }
8c0fdd85
TS
1796 /* If the ASID changes, flush qemu's TLB. */
1797 if ((old & 0xFF) != (val & 0xFF))
1798 CALL_FROM_TB2(cpu_mips_tlb_flush, env, 1);
1799 RETURN();
1800}
1801
ead9360e
TS
1802void op_mttc0_entryhi(void)
1803{
1804 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1805
1806 env->CP0_EntryHi = (env->CP0_EntryHi & 0xff) | (T0 & ~0xff);
1807 env->CP0_TCStatus[other_tc] = (env->CP0_TCStatus[other_tc] & ~0xff) | (T0 & 0xff);
1808 RETURN();
1809}
1810
8c0fdd85
TS
1811void op_mtc0_compare (void)
1812{
1813 CALL_FROM_TB2(cpu_mips_store_compare, env, T0);
1814 RETURN();
1815}
1816
1817void op_mtc0_status (void)
1818{
4de9b249 1819 uint32_t val, old;
ead9360e 1820 uint32_t mask = env->CP0_Status_rw_bitmask;
8c0fdd85 1821
f1b0aa5d 1822 val = T0 & mask;
8c0fdd85 1823 old = env->CP0_Status;
5a5012ec 1824 env->CP0_Status = (env->CP0_Status & ~mask) | val;
08fa4bab 1825 CALL_FROM_TB1(compute_hflags, env);
f41c52f1
TS
1826 if (loglevel & CPU_LOG_EXEC)
1827 CALL_FROM_TB2(do_mtc0_status_debug, old, val);
4de9b249 1828 CALL_FROM_TB1(cpu_mips_update_irq, env);
8c0fdd85
TS
1829 RETURN();
1830}
1831
ead9360e
TS
1832void op_mttc0_status(void)
1833{
1834 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1835 uint32_t tcstatus = env->CP0_TCStatus[other_tc];
1836
1837 env->CP0_Status = T0 & ~0xf1000018;
1838 tcstatus = (tcstatus & ~(0xf << CP0TCSt_TCU0)) | (T0 & (0xf << CP0St_CU0));
1839 tcstatus = (tcstatus & ~(1 << CP0TCSt_TMX)) | ((T0 & (1 << CP0St_MX)) << (CP0TCSt_TMX - CP0St_MX));
623a930e 1840 tcstatus = (tcstatus & ~(0x3 << CP0TCSt_TKSU)) | ((T0 & (0x3 << CP0St_KSU)) << (CP0TCSt_TKSU - CP0St_KSU));
ead9360e
TS
1841 env->CP0_TCStatus[other_tc] = tcstatus;
1842 RETURN();
1843}
1844
7a387fff
TS
1845void op_mtc0_intctl (void)
1846{
42532189
TS
1847 /* vectored interrupts not implemented, no performance counters. */
1848 env->CP0_IntCtl = (env->CP0_IntCtl & ~0x000002e0) | (T0 & 0x000002e0);
7a387fff
TS
1849 RETURN();
1850}
1851
1852void op_mtc0_srsctl (void)
1853{
ead9360e
TS
1854 uint32_t mask = (0xf << CP0SRSCtl_ESS) | (0xf << CP0SRSCtl_PSS);
1855 env->CP0_SRSCtl = (env->CP0_SRSCtl & ~mask) | (T0 & mask);
7a387fff
TS
1856 RETURN();
1857}
1858
9c2149c8
TS
1859void op_mtc0_srsmap (void)
1860{
ead9360e 1861 env->CP0_SRSMap = T0;
9c2149c8
TS
1862 RETURN();
1863}
1864
8c0fdd85
TS
1865void op_mtc0_cause (void)
1866{
39d51eb8 1867 uint32_t mask = 0x00C00300;
42532189 1868 uint32_t old = env->CP0_Cause;
39d51eb8 1869
e189e748 1870 if (env->insn_flags & ISA_MIPS32R2)
39d51eb8
TS
1871 mask |= 1 << CP0Ca_DC;
1872
e58c8ba5 1873 env->CP0_Cause = (env->CP0_Cause & ~mask) | (T0 & mask);
8c0fdd85 1874
42532189
TS
1875 if ((old ^ env->CP0_Cause) & (1 << CP0Ca_DC)) {
1876 if (env->CP0_Cause & (1 << CP0Ca_DC))
1877 CALL_FROM_TB1(cpu_mips_stop_count, env);
1878 else
1879 CALL_FROM_TB1(cpu_mips_start_count, env);
1880 }
1881
4de9b249
TS
1882 /* Handle the software interrupt as an hardware one, as they
1883 are very similar */
1884 if (T0 & CP0Ca_IP_mask) {
1885 CALL_FROM_TB1(cpu_mips_update_irq, env);
8c0fdd85 1886 }
8c0fdd85
TS
1887 RETURN();
1888}
1889
1890void op_mtc0_epc (void)
1891{
f1b0aa5d 1892 env->CP0_EPC = T0;
8c0fdd85
TS
1893 RETURN();
1894}
1895
7a387fff
TS
1896void op_mtc0_ebase (void)
1897{
1898 /* vectored interrupts not implemented */
1899 /* Multi-CPU not implemented */
b29a0341 1900 env->CP0_EBase = 0x80000000 | (T0 & 0x3FFFF000);
7a387fff
TS
1901 RETURN();
1902}
1903
8c0fdd85
TS
1904void op_mtc0_config0 (void)
1905{
7bfd934a 1906 env->CP0_Config0 = (env->CP0_Config0 & 0x81FFFFF8) | (T0 & 0x00000007);
8c0fdd85
TS
1907 RETURN();
1908}
1909
7a387fff
TS
1910void op_mtc0_config2 (void)
1911{
1912 /* tertiary/secondary caches not implemented */
1913 env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF);
1914 RETURN();
1915}
1916
fd88b6ab 1917void op_mtc0_watchlo (void)
8c0fdd85 1918{
4e7a4a4e
TS
1919 /* Watch exceptions for instructions, data loads, data stores
1920 not implemented. */
fd88b6ab 1921 env->CP0_WatchLo[PARAM1] = (T0 & ~0x7);
8c0fdd85
TS
1922 RETURN();
1923}
1924
fd88b6ab 1925void op_mtc0_watchhi (void)
8c0fdd85 1926{
fd88b6ab
TS
1927 env->CP0_WatchHi[PARAM1] = (T0 & 0x40FF0FF8);
1928 env->CP0_WatchHi[PARAM1] &= ~(env->CP0_WatchHi[PARAM1] & T0 & 0x7);
8c0fdd85
TS
1929 RETURN();
1930}
1931
ead9360e
TS
1932void op_mtc0_xcontext (void)
1933{
1934 target_ulong mask = (1ULL << (env->SEGBITS - 7)) - 1;
1935 env->CP0_XContext = (env->CP0_XContext & mask) | (T0 & ~mask);
1936 RETURN();
1937}
1938
7a387fff
TS
1939void op_mtc0_framemask (void)
1940{
1941 env->CP0_Framemask = T0; /* XXX */
1942 RETURN();
1943}
1944
8c0fdd85
TS
1945void op_mtc0_debug (void)
1946{
1947 env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120);
1948 if (T0 & (1 << CP0DB_DM))
1949 env->hflags |= MIPS_HFLAG_DM;
1950 else
1951 env->hflags &= ~MIPS_HFLAG_DM;
1952 RETURN();
1953}
1954
ead9360e
TS
1955void op_mttc0_debug(void)
1956{
1957 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1958
1959 /* XXX: Might be wrong, check with EJTAG spec. */
1960 env->CP0_Debug_tcstatus[other_tc] = T0 & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt));
1961 env->CP0_Debug = (env->CP0_Debug & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
1962 (T0 & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
1963 RETURN();
1964}
1965
8c0fdd85
TS
1966void op_mtc0_depc (void)
1967{
f1b0aa5d 1968 env->CP0_DEPC = T0;
8c0fdd85
TS
1969 RETURN();
1970}
1971
7a387fff
TS
1972void op_mtc0_performance0 (void)
1973{
1b6fd0bc 1974 env->CP0_Performance0 = T0 & 0x000007ff;
7a387fff
TS
1975 RETURN();
1976}
1977
8c0fdd85
TS
1978void op_mtc0_taglo (void)
1979{
9c2149c8 1980 env->CP0_TagLo = T0 & 0xFFFFFCF6;
8c0fdd85
TS
1981 RETURN();
1982}
1983
7a387fff
TS
1984void op_mtc0_datalo (void)
1985{
1986 env->CP0_DataLo = T0; /* XXX */
1987 RETURN();
1988}
1989
1990void op_mtc0_taghi (void)
1991{
1992 env->CP0_TagHi = T0; /* XXX */
1993 RETURN();
1994}
1995
1996void op_mtc0_datahi (void)
1997{
1998 env->CP0_DataHi = T0; /* XXX */
1999 RETURN();
2000}
2001
8c0fdd85
TS
2002void op_mtc0_errorepc (void)
2003{
f1b0aa5d 2004 env->CP0_ErrorEPC = T0;
8c0fdd85
TS
2005 RETURN();
2006}
2007
2008void op_mtc0_desave (void)
2009{
2010 env->CP0_DESAVE = T0;
6af0bf9c
FB
2011 RETURN();
2012}
2013
d26bc211 2014#if defined(TARGET_MIPS64)
ead9360e 2015void op_dmfc0_yqmask (void)
f1b0aa5d 2016{
ead9360e
TS
2017 T0 = env->CP0_YQMask;
2018 RETURN();
2019}
2020
2021void op_dmfc0_vpeschedule (void)
2022{
2023 T0 = env->CP0_VPESchedule;
2024 RETURN();
2025}
2026
2027void op_dmfc0_vpeschefback (void)
2028{
2029 T0 = env->CP0_VPEScheFBack;
f1b0aa5d
TS
2030 RETURN();
2031}
2032
9c2149c8
TS
2033void op_dmfc0_entrylo0 (void)
2034{
2035 T0 = env->CP0_EntryLo0;
2036 RETURN();
2037}
2038
ead9360e
TS
2039void op_dmfc0_tcrestart (void)
2040{
2041 T0 = env->PC[env->current_tc];
2042 RETURN();
2043}
2044
2045void op_dmfc0_tchalt (void)
2046{
2047 T0 = env->CP0_TCHalt[env->current_tc];
2048 RETURN();
2049}
2050
2051void op_dmfc0_tccontext (void)
2052{
2053 T0 = env->CP0_TCContext[env->current_tc];
2054 RETURN();
2055}
2056
2057void op_dmfc0_tcschedule (void)
2058{
2059 T0 = env->CP0_TCSchedule[env->current_tc];
2060 RETURN();
2061}
2062
2063void op_dmfc0_tcschefback (void)
2064{
2065 T0 = env->CP0_TCScheFBack[env->current_tc];
2066 RETURN();
2067}
2068
9c2149c8
TS
2069void op_dmfc0_entrylo1 (void)
2070{
2071 T0 = env->CP0_EntryLo1;
2072 RETURN();
2073}
2074
2075void op_dmfc0_context (void)
2076{
2077 T0 = env->CP0_Context;
2078 RETURN();
2079}
2080
2081void op_dmfc0_badvaddr (void)
2082{
2083 T0 = env->CP0_BadVAddr;
2084 RETURN();
2085}
2086
2087void op_dmfc0_entryhi (void)
2088{
2089 T0 = env->CP0_EntryHi;
2090 RETURN();
2091}
2092
2093void op_dmfc0_epc (void)
2094{
2095 T0 = env->CP0_EPC;
2096 RETURN();
2097}
2098
9c2149c8
TS
2099void op_dmfc0_lladdr (void)
2100{
2101 T0 = env->CP0_LLAddr >> 4;
2102 RETURN();
2103}
2104
fd88b6ab 2105void op_dmfc0_watchlo (void)
9c2149c8 2106{
fd88b6ab 2107 T0 = env->CP0_WatchLo[PARAM1];
9c2149c8
TS
2108 RETURN();
2109}
2110
2111void op_dmfc0_xcontext (void)
2112{
2113 T0 = env->CP0_XContext;
2114 RETURN();
2115}
2116
2117void op_dmfc0_depc (void)
2118{
2119 T0 = env->CP0_DEPC;
2120 RETURN();
2121}
2122
2123void op_dmfc0_errorepc (void)
2124{
2125 T0 = env->CP0_ErrorEPC;
2126 RETURN();
2127}
d26bc211 2128#endif /* TARGET_MIPS64 */
9c2149c8 2129
ead9360e
TS
2130/* MIPS MT functions */
2131void op_mftgpr(void)
2132{
2133 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2134
2135 T0 = env->gpr[PARAM1][other_tc];
2136 RETURN();
2137}
2138
2139void op_mftlo(void)
2140{
2141 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2142
2143 T0 = env->LO[PARAM1][other_tc];
2144 RETURN();
2145}
2146
2147void op_mfthi(void)
2148{
2149 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2150
2151 T0 = env->HI[PARAM1][other_tc];
2152 RETURN();
2153}
2154
2155void op_mftacx(void)
2156{
2157 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2158
2159 T0 = env->ACX[PARAM1][other_tc];
2160 RETURN();
2161}
2162
2163void op_mftdsp(void)
2164{
2165 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2166
2167 T0 = env->DSPControl[other_tc];
2168 RETURN();
2169}
2170
2171void op_mttgpr(void)
2172{
2173 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2174
2175 T0 = env->gpr[PARAM1][other_tc];
2176 RETURN();
2177}
2178
2179void op_mttlo(void)
2180{
2181 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2182
2183 T0 = env->LO[PARAM1][other_tc];
2184 RETURN();
2185}
2186
2187void op_mtthi(void)
2188{
2189 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2190
2191 T0 = env->HI[PARAM1][other_tc];
2192 RETURN();
2193}
2194
2195void op_mttacx(void)
2196{
2197 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2198
2199 T0 = env->ACX[PARAM1][other_tc];
2200 RETURN();
2201}
2202
2203void op_mttdsp(void)
2204{
2205 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2206
2207 T0 = env->DSPControl[other_tc];
2208 RETURN();
2209}
2210
2211
2212void op_dmt(void)
2213{
2214 // TODO
2215 T0 = 0;
2216 // rt = T0
2217 RETURN();
2218}
2219
2220void op_emt(void)
2221{
2222 // TODO
2223 T0 = 0;
2224 // rt = T0
2225 RETURN();
2226}
2227
2228void op_dvpe(void)
2229{
2230 // TODO
2231 T0 = 0;
2232 // rt = T0
2233 RETURN();
2234}
2235
2236void op_evpe(void)
2237{
2238 // TODO
2239 T0 = 0;
2240 // rt = T0
2241 RETURN();
2242}
2243
2244void op_fork(void)
2245{
2246 // T0 = rt, T1 = rs
2247 T0 = 0;
2248 // TODO: store to TC register
2249 RETURN();
2250}
2251
2252void op_yield(void)
2253{
2254 if (T0 < 0) {
2255 /* No scheduling policy implemented. */
2256 if (T0 != -2) {
2257 if (env->CP0_VPEControl & (1 << CP0VPECo_YSI) &&
2258 env->CP0_TCStatus[env->current_tc] & (1 << CP0TCSt_DT)) {
2259 env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
2260 env->CP0_VPEControl |= 4 << CP0VPECo_EXCPT;
2261 CALL_FROM_TB1(do_raise_exception, EXCP_THREAD);
2262 }
2263 }
2264 } else if (T0 == 0) {
2265 if (0 /* TODO: TC underflow */) {
2266 env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
2267 CALL_FROM_TB1(do_raise_exception, EXCP_THREAD);
2268 } else {
2269 // TODO: Deallocate TC
2270 }
2271 } else if (T0 > 0) {
2272 /* Yield qualifier inputs not implemented. */
2273 env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
2274 env->CP0_VPEControl |= 2 << CP0VPECo_EXCPT;
2275 CALL_FROM_TB1(do_raise_exception, EXCP_THREAD);
2276 }
2277 T0 = env->CP0_YQMask;
2278 RETURN();
2279}
2280
5a5012ec 2281/* CP1 functions */
6ea83fed
FB
2282#if 0
2283# define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env)
2284#else
2285# define DEBUG_FPU_STATE() do { } while(0)
2286#endif
2287
5a5012ec
TS
2288void op_cfc1 (void)
2289{
ead9360e 2290 CALL_FROM_TB1(do_cfc1, PARAM1);
5a5012ec
TS
2291 DEBUG_FPU_STATE();
2292 RETURN();
2293}
2294
2295void op_ctc1 (void)
2296{
ead9360e 2297 CALL_FROM_TB1(do_ctc1, PARAM1);
6ea83fed
FB
2298 DEBUG_FPU_STATE();
2299 RETURN();
2300}
2301
2302void op_mfc1 (void)
2303{
6ad38722 2304 T0 = (int32_t)WT0;
6ea83fed
FB
2305 DEBUG_FPU_STATE();
2306 RETURN();
2307}
2308
2309void op_mtc1 (void)
2310{
2311 WT0 = T0;
2312 DEBUG_FPU_STATE();
2313 RETURN();
2314}
2315
5a5012ec
TS
2316void op_dmfc1 (void)
2317{
2318 T0 = DT0;
2319 DEBUG_FPU_STATE();
2320 RETURN();
2321}
2322
2323void op_dmtc1 (void)
2324{
2325 DT0 = T0;
2326 DEBUG_FPU_STATE();
2327 RETURN();
2328}
2329
2330void op_mfhc1 (void)
2331{
6ad38722 2332 T0 = (int32_t)WTH0;
5a5012ec
TS
2333 DEBUG_FPU_STATE();
2334 RETURN();
2335}
2336
2337void op_mthc1 (void)
2338{
2339 WTH0 = T0;
2340 DEBUG_FPU_STATE();
2341 RETURN();
2342}
2343
6ea83fed
FB
2344/* Float support.
2345 Single precition routines have a "s" suffix, double precision a
5a5012ec
TS
2346 "d" suffix, 32bit integer "w", 64bit integer "l", paired singe "ps",
2347 paired single lowwer "pl", paired single upper "pu". */
6ea83fed
FB
2348
2349#define FLOAT_OP(name, p) void OPPROTO op_float_##name##_##p(void)
2350
dd016883
FB
2351FLOAT_OP(cvtd, s)
2352{
fd4a04eb 2353 CALL_FROM_TB0(do_float_cvtd_s);
dd016883
FB
2354 DEBUG_FPU_STATE();
2355 RETURN();
2356}
6ea83fed
FB
2357FLOAT_OP(cvtd, w)
2358{
fd4a04eb 2359 CALL_FROM_TB0(do_float_cvtd_w);
5a5012ec
TS
2360 DEBUG_FPU_STATE();
2361 RETURN();
2362}
2363FLOAT_OP(cvtd, l)
2364{
fd4a04eb 2365 CALL_FROM_TB0(do_float_cvtd_l);
5a5012ec
TS
2366 DEBUG_FPU_STATE();
2367 RETURN();
2368}
2369FLOAT_OP(cvtl, d)
2370{
fd4a04eb 2371 CALL_FROM_TB0(do_float_cvtl_d);
5a5012ec
TS
2372 DEBUG_FPU_STATE();
2373 RETURN();
2374}
2375FLOAT_OP(cvtl, s)
2376{
fd4a04eb 2377 CALL_FROM_TB0(do_float_cvtl_s);
5a5012ec
TS
2378 DEBUG_FPU_STATE();
2379 RETURN();
2380}
2381FLOAT_OP(cvtps, s)
2382{
2383 WT2 = WT0;
2384 WTH2 = WT1;
2385 DEBUG_FPU_STATE();
2386 RETURN();
2387}
2388FLOAT_OP(cvtps, pw)
2389{
fd4a04eb 2390 CALL_FROM_TB0(do_float_cvtps_pw);
5a5012ec
TS
2391 DEBUG_FPU_STATE();
2392 RETURN();
2393}
2394FLOAT_OP(cvtpw, ps)
2395{
fd4a04eb 2396 CALL_FROM_TB0(do_float_cvtpw_ps);
6ea83fed
FB
2397 DEBUG_FPU_STATE();
2398 RETURN();
2399}
dd016883
FB
2400FLOAT_OP(cvts, d)
2401{
fd4a04eb 2402 CALL_FROM_TB0(do_float_cvts_d);
dd016883
FB
2403 DEBUG_FPU_STATE();
2404 RETURN();
2405}
6ea83fed
FB
2406FLOAT_OP(cvts, w)
2407{
fd4a04eb 2408 CALL_FROM_TB0(do_float_cvts_w);
5a5012ec
TS
2409 DEBUG_FPU_STATE();
2410 RETURN();
2411}
2412FLOAT_OP(cvts, l)
2413{
fd4a04eb 2414 CALL_FROM_TB0(do_float_cvts_l);
5a5012ec
TS
2415 DEBUG_FPU_STATE();
2416 RETURN();
2417}
2418FLOAT_OP(cvts, pl)
2419{
fd4a04eb 2420 CALL_FROM_TB0(do_float_cvts_pl);
5a5012ec
TS
2421 DEBUG_FPU_STATE();
2422 RETURN();
2423}
2424FLOAT_OP(cvts, pu)
2425{
fd4a04eb 2426 CALL_FROM_TB0(do_float_cvts_pu);
6ea83fed
FB
2427 DEBUG_FPU_STATE();
2428 RETURN();
2429}
2430FLOAT_OP(cvtw, s)
2431{
fd4a04eb 2432 CALL_FROM_TB0(do_float_cvtw_s);
6ea83fed
FB
2433 DEBUG_FPU_STATE();
2434 RETURN();
2435}
2436FLOAT_OP(cvtw, d)
2437{
fd4a04eb 2438 CALL_FROM_TB0(do_float_cvtw_d);
5a5012ec
TS
2439 DEBUG_FPU_STATE();
2440 RETURN();
2441}
2442
2443FLOAT_OP(pll, ps)
2444{
2445 DT2 = ((uint64_t)WT0 << 32) | WT1;
2446 DEBUG_FPU_STATE();
2447 RETURN();
2448}
2449FLOAT_OP(plu, ps)
2450{
2451 DT2 = ((uint64_t)WT0 << 32) | WTH1;
2452 DEBUG_FPU_STATE();
2453 RETURN();
2454}
2455FLOAT_OP(pul, ps)
2456{
2457 DT2 = ((uint64_t)WTH0 << 32) | WT1;
2458 DEBUG_FPU_STATE();
2459 RETURN();
2460}
2461FLOAT_OP(puu, ps)
2462{
2463 DT2 = ((uint64_t)WTH0 << 32) | WTH1;
6ea83fed
FB
2464 DEBUG_FPU_STATE();
2465 RETURN();
2466}
2467
fd4a04eb
TS
2468#define FLOAT_ROUNDOP(op, ttype, stype) \
2469FLOAT_OP(op ## ttype, stype) \
2470{ \
2471 CALL_FROM_TB0(do_float_ ## op ## ttype ## _ ## stype); \
2472 DEBUG_FPU_STATE(); \
2473 RETURN(); \
6ea83fed
FB
2474}
2475
fd4a04eb
TS
2476FLOAT_ROUNDOP(round, l, d)
2477FLOAT_ROUNDOP(round, l, s)
2478FLOAT_ROUNDOP(round, w, d)
2479FLOAT_ROUNDOP(round, w, s)
6ea83fed 2480
fd4a04eb
TS
2481FLOAT_ROUNDOP(trunc, l, d)
2482FLOAT_ROUNDOP(trunc, l, s)
2483FLOAT_ROUNDOP(trunc, w, d)
2484FLOAT_ROUNDOP(trunc, w, s)
6ea83fed 2485
fd4a04eb
TS
2486FLOAT_ROUNDOP(ceil, l, d)
2487FLOAT_ROUNDOP(ceil, l, s)
2488FLOAT_ROUNDOP(ceil, w, d)
2489FLOAT_ROUNDOP(ceil, w, s)
2490
2491FLOAT_ROUNDOP(floor, l, d)
2492FLOAT_ROUNDOP(floor, l, s)
2493FLOAT_ROUNDOP(floor, w, d)
2494FLOAT_ROUNDOP(floor, w, s)
2495#undef FLOAR_ROUNDOP
6ea83fed 2496
5a5012ec
TS
2497FLOAT_OP(movf, d)
2498{
ead9360e 2499 if (!(env->fpu->fcr31 & PARAM1))
5a5012ec
TS
2500 DT2 = DT0;
2501 DEBUG_FPU_STATE();
2502 RETURN();
2503}
2504FLOAT_OP(movf, s)
2505{
ead9360e 2506 if (!(env->fpu->fcr31 & PARAM1))
5a5012ec
TS
2507 WT2 = WT0;
2508 DEBUG_FPU_STATE();
2509 RETURN();
2510}
2511FLOAT_OP(movf, ps)
2512{
ead9360e 2513 if (!(env->fpu->fcr31 & PARAM1)) {
5a5012ec
TS
2514 WT2 = WT0;
2515 WTH2 = WTH0;
2516 }
2517 DEBUG_FPU_STATE();
2518 RETURN();
2519}
2520FLOAT_OP(movt, d)
2521{
ead9360e 2522 if (env->fpu->fcr31 & PARAM1)
5a5012ec
TS
2523 DT2 = DT0;
2524 DEBUG_FPU_STATE();
2525 RETURN();
2526}
2527FLOAT_OP(movt, s)
2528{
ead9360e 2529 if (env->fpu->fcr31 & PARAM1)
5a5012ec
TS
2530 WT2 = WT0;
2531 DEBUG_FPU_STATE();
2532 RETURN();
2533}
2534FLOAT_OP(movt, ps)
2535{
ead9360e 2536 if (env->fpu->fcr31 & PARAM1) {
5a5012ec
TS
2537 WT2 = WT0;
2538 WTH2 = WTH0;
2539 }
2540 DEBUG_FPU_STATE();
2541 RETURN();
2542}
2543FLOAT_OP(movz, d)
2544{
2545 if (!T0)
2546 DT2 = DT0;
2547 DEBUG_FPU_STATE();
2548 RETURN();
2549}
2550FLOAT_OP(movz, s)
2551{
2552 if (!T0)
2553 WT2 = WT0;
2554 DEBUG_FPU_STATE();
2555 RETURN();
2556}
2557FLOAT_OP(movz, ps)
2558{
2559 if (!T0) {
2560 WT2 = WT0;
2561 WTH2 = WTH0;
2562 }
2563 DEBUG_FPU_STATE();
2564 RETURN();
2565}
2566FLOAT_OP(movn, d)
2567{
2568 if (T0)
2569 DT2 = DT0;
2570 DEBUG_FPU_STATE();
2571 RETURN();
2572}
2573FLOAT_OP(movn, s)
2574{
2575 if (T0)
2576 WT2 = WT0;
2577 DEBUG_FPU_STATE();
2578 RETURN();
2579}
2580FLOAT_OP(movn, ps)
2581{
2582 if (T0) {
2583 WT2 = WT0;
2584 WTH2 = WTH0;
2585 }
2586 DEBUG_FPU_STATE();
2587 RETURN();
2588}
2589
57fa1fb3
TS
2590/* operations calling helpers, for s, d and ps */
2591#define FLOAT_HOP(name) \
6ea83fed
FB
2592FLOAT_OP(name, d) \
2593{ \
fd4a04eb 2594 CALL_FROM_TB0(do_float_ ## name ## _d); \
6ea83fed 2595 DEBUG_FPU_STATE(); \
fbcc6828 2596 RETURN(); \
6ea83fed
FB
2597} \
2598FLOAT_OP(name, s) \
2599{ \
fd4a04eb 2600 CALL_FROM_TB0(do_float_ ## name ## _s); \
5a5012ec 2601 DEBUG_FPU_STATE(); \
fbcc6828 2602 RETURN(); \
5a5012ec
TS
2603} \
2604FLOAT_OP(name, ps) \
2605{ \
fd4a04eb 2606 CALL_FROM_TB0(do_float_ ## name ## _ps); \
6ea83fed 2607 DEBUG_FPU_STATE(); \
fbcc6828 2608 RETURN(); \
6ea83fed 2609}
57fa1fb3
TS
2610FLOAT_HOP(add)
2611FLOAT_HOP(sub)
2612FLOAT_HOP(mul)
2613FLOAT_HOP(div)
2614FLOAT_HOP(recip2)
2615FLOAT_HOP(rsqrt2)
2616FLOAT_HOP(rsqrt1)
2617FLOAT_HOP(recip1)
2618#undef FLOAT_HOP
2619
2620/* operations calling helpers, for s and d */
2621#define FLOAT_HOP(name) \
2622FLOAT_OP(name, d) \
2623{ \
2624 CALL_FROM_TB0(do_float_ ## name ## _d); \
2625 DEBUG_FPU_STATE(); \
2626 RETURN(); \
2627} \
2628FLOAT_OP(name, s) \
2629{ \
2630 CALL_FROM_TB0(do_float_ ## name ## _s); \
2631 DEBUG_FPU_STATE(); \
2632 RETURN(); \
2633}
2634FLOAT_HOP(rsqrt)
2635FLOAT_HOP(recip)
2636#undef FLOAT_HOP
6ea83fed 2637
57fa1fb3
TS
2638/* operations calling helpers, for ps */
2639#define FLOAT_HOP(name) \
2640FLOAT_OP(name, ps) \
2641{ \
2642 CALL_FROM_TB0(do_float_ ## name ## _ps); \
2643 DEBUG_FPU_STATE(); \
2644 RETURN(); \
fbcc6828 2645}
57fa1fb3
TS
2646FLOAT_HOP(addr)
2647FLOAT_HOP(mulr)
2648#undef FLOAT_HOP
fbcc6828 2649
5a5012ec
TS
2650/* ternary operations */
2651#define FLOAT_TERNOP(name1, name2) \
2652FLOAT_OP(name1 ## name2, d) \
2653{ \
ead9360e
TS
2654 FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status); \
2655 FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status); \
5a5012ec 2656 DEBUG_FPU_STATE(); \
fbcc6828 2657 RETURN(); \
5a5012ec
TS
2658} \
2659FLOAT_OP(name1 ## name2, s) \
2660{ \
ead9360e
TS
2661 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
2662 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
5a5012ec 2663 DEBUG_FPU_STATE(); \
fbcc6828 2664 RETURN(); \
5a5012ec
TS
2665} \
2666FLOAT_OP(name1 ## name2, ps) \
2667{ \
ead9360e
TS
2668 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
2669 FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \
2670 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
2671 FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \
5a5012ec 2672 DEBUG_FPU_STATE(); \
fbcc6828 2673 RETURN(); \
5a5012ec
TS
2674}
2675FLOAT_TERNOP(mul, add)
2676FLOAT_TERNOP(mul, sub)
2677#undef FLOAT_TERNOP
2678
fbcc6828
TS
2679/* negated ternary operations */
2680#define FLOAT_NTERNOP(name1, name2) \
2681FLOAT_OP(n ## name1 ## name2, d) \
2682{ \
ead9360e
TS
2683 FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status); \
2684 FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status); \
fbcc6828
TS
2685 FDT2 ^= 1ULL << 63; \
2686 DEBUG_FPU_STATE(); \
2687 RETURN(); \
2688} \
2689FLOAT_OP(n ## name1 ## name2, s) \
2690{ \
ead9360e
TS
2691 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
2692 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
fbcc6828
TS
2693 FST2 ^= 1 << 31; \
2694 DEBUG_FPU_STATE(); \
2695 RETURN(); \
2696} \
2697FLOAT_OP(n ## name1 ## name2, ps) \
2698{ \
ead9360e
TS
2699 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
2700 FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \
2701 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
2702 FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \
fbcc6828
TS
2703 FST2 ^= 1 << 31; \
2704 FSTH2 ^= 1 << 31; \
2705 DEBUG_FPU_STATE(); \
2706 RETURN(); \
2707}
2708FLOAT_NTERNOP(mul, add)
2709FLOAT_NTERNOP(mul, sub)
2710#undef FLOAT_NTERNOP
2711
6ea83fed
FB
2712/* unary operations, modifying fp status */
2713#define FLOAT_UNOP(name) \
2714FLOAT_OP(name, d) \
2715{ \
ead9360e 2716 FDT2 = float64_ ## name(FDT0, &env->fpu->fp_status); \
6ea83fed 2717 DEBUG_FPU_STATE(); \
fbcc6828 2718 RETURN(); \
6ea83fed
FB
2719} \
2720FLOAT_OP(name, s) \
2721{ \
ead9360e 2722 FST2 = float32_ ## name(FST0, &env->fpu->fp_status); \
6ea83fed 2723 DEBUG_FPU_STATE(); \
57fa1fb3 2724 RETURN(); \
6ea83fed
FB
2725}
2726FLOAT_UNOP(sqrt)
2727#undef FLOAT_UNOP
2728
2729/* unary operations, not modifying fp status */
2730#define FLOAT_UNOP(name) \
2731FLOAT_OP(name, d) \
2732{ \
2733 FDT2 = float64_ ## name(FDT0); \
2734 DEBUG_FPU_STATE(); \
fbcc6828 2735 RETURN(); \
6ea83fed
FB
2736} \
2737FLOAT_OP(name, s) \
2738{ \
2739 FST2 = float32_ ## name(FST0); \
2740 DEBUG_FPU_STATE(); \
fbcc6828 2741 RETURN(); \
5a5012ec
TS
2742} \
2743FLOAT_OP(name, ps) \
2744{ \
2745 FST2 = float32_ ## name(FST0); \
2746 FSTH2 = float32_ ## name(FSTH0); \
2747 DEBUG_FPU_STATE(); \
fbcc6828 2748 RETURN(); \
6ea83fed
FB
2749}
2750FLOAT_UNOP(abs)
2751FLOAT_UNOP(chs)
2752#undef FLOAT_UNOP
2753
2754FLOAT_OP(mov, d)
2755{
2756 FDT2 = FDT0;
2757 DEBUG_FPU_STATE();
2758 RETURN();
2759}
2760FLOAT_OP(mov, s)
2761{
2762 FST2 = FST0;
2763 DEBUG_FPU_STATE();
2764 RETURN();
2765}
5a5012ec
TS
2766FLOAT_OP(mov, ps)
2767{
2768 FST2 = FST0;
2769 FSTH2 = FSTH0;
2770 DEBUG_FPU_STATE();
2771 RETURN();
2772}
2773FLOAT_OP(alnv, ps)
2774{
2775 switch (T0 & 0x7) {
2776 case 0:
2777 FST2 = FST0;
2778 FSTH2 = FSTH0;
2779 break;
2780 case 4:
2781#ifdef TARGET_WORDS_BIGENDIAN
2782 FSTH2 = FST0;
2783 FST2 = FSTH1;
2784#else
2785 FSTH2 = FST1;
2786 FST2 = FSTH0;
2787#endif
2788 break;
2789 default: /* unpredictable */
2790 break;
2791 }
2792 DEBUG_FPU_STATE();
2793 RETURN();
2794}
6ea83fed
FB
2795
2796#ifdef CONFIG_SOFTFLOAT
2797#define clear_invalid() do { \
ead9360e 2798 int flags = get_float_exception_flags(&env->fpu->fp_status); \
6ea83fed 2799 flags &= ~float_flag_invalid; \
ead9360e 2800 set_float_exception_flags(flags, &env->fpu->fp_status); \
6ea83fed
FB
2801} while(0)
2802#else
2803#define clear_invalid() do { } while(0)
2804#endif
2805
2806extern void dump_fpu_s(CPUState *env);
2807
fd4a04eb
TS
2808#define CMP_OP(fmt, op) \
2809void OPPROTO op_cmp ## _ ## fmt ## _ ## op(void) \
2810{ \
2811 CALL_FROM_TB1(do_cmp ## _ ## fmt ## _ ## op, PARAM1); \
2812 DEBUG_FPU_STATE(); \
2813 RETURN(); \
2814} \
2815void OPPROTO op_cmpabs ## _ ## fmt ## _ ## op(void) \
2816{ \
2817 CALL_FROM_TB1(do_cmpabs ## _ ## fmt ## _ ## op, PARAM1); \
2818 DEBUG_FPU_STATE(); \
2819 RETURN(); \
2820}
2821#define CMP_OPS(op) \
2822CMP_OP(d, op) \
2823CMP_OP(s, op) \
2824CMP_OP(ps, op)
2825
2826CMP_OPS(f)
2827CMP_OPS(un)
2828CMP_OPS(eq)
2829CMP_OPS(ueq)
2830CMP_OPS(olt)
2831CMP_OPS(ult)
2832CMP_OPS(ole)
2833CMP_OPS(ule)
2834CMP_OPS(sf)
2835CMP_OPS(ngle)
2836CMP_OPS(seq)
2837CMP_OPS(ngl)
2838CMP_OPS(lt)
2839CMP_OPS(nge)
2840CMP_OPS(le)
2841CMP_OPS(ngt)
2842#undef CMP_OPS
2843#undef CMP_OP
6ea83fed
FB
2844
2845void op_bc1f (void)
2846{
ead9360e 2847 T0 = !!(~GET_FP_COND(env->fpu) & (0x1 << PARAM1));
5a5012ec
TS
2848 DEBUG_FPU_STATE();
2849 RETURN();
2850}
fd4a04eb 2851void op_bc1any2f (void)
5a5012ec 2852{
ead9360e 2853 T0 = !!(~GET_FP_COND(env->fpu) & (0x3 << PARAM1));
5a5012ec
TS
2854 DEBUG_FPU_STATE();
2855 RETURN();
2856}
fd4a04eb 2857void op_bc1any4f (void)
5a5012ec 2858{
ead9360e 2859 T0 = !!(~GET_FP_COND(env->fpu) & (0xf << PARAM1));
6ea83fed
FB
2860 DEBUG_FPU_STATE();
2861 RETURN();
2862}
2863
2864void op_bc1t (void)
2865{
ead9360e 2866 T0 = !!(GET_FP_COND(env->fpu) & (0x1 << PARAM1));
5a5012ec
TS
2867 DEBUG_FPU_STATE();
2868 RETURN();
2869}
fd4a04eb 2870void op_bc1any2t (void)
5a5012ec 2871{
ead9360e 2872 T0 = !!(GET_FP_COND(env->fpu) & (0x3 << PARAM1));
5a5012ec
TS
2873 DEBUG_FPU_STATE();
2874 RETURN();
2875}
fd4a04eb 2876void op_bc1any4t (void)
5a5012ec 2877{
ead9360e 2878 T0 = !!(GET_FP_COND(env->fpu) & (0xf << PARAM1));
6ea83fed
FB
2879 DEBUG_FPU_STATE();
2880 RETURN();
2881}
6ea83fed 2882
6af0bf9c
FB
2883void op_tlbwi (void)
2884{
ead9360e 2885 CALL_FROM_TB0(env->tlb->do_tlbwi);
6af0bf9c
FB
2886 RETURN();
2887}
2888
2889void op_tlbwr (void)
2890{
ead9360e 2891 CALL_FROM_TB0(env->tlb->do_tlbwr);
6af0bf9c
FB
2892 RETURN();
2893}
2894
2895void op_tlbp (void)
2896{
ead9360e 2897 CALL_FROM_TB0(env->tlb->do_tlbp);
6af0bf9c
FB
2898 RETURN();
2899}
2900
2901void op_tlbr (void)
2902{
ead9360e 2903 CALL_FROM_TB0(env->tlb->do_tlbr);
6af0bf9c
FB
2904 RETURN();
2905}
6af0bf9c
FB
2906
2907/* Specials */
6f5b89a0
TS
2908#if defined (CONFIG_USER_ONLY)
2909void op_tls_value (void)
2910{
5a5012ec 2911 T0 = env->tls_value;
6f5b89a0
TS
2912}
2913#endif
2914
6af0bf9c
FB
2915void op_pmon (void)
2916{
2917 CALL_FROM_TB1(do_pmon, PARAM1);
7a387fff
TS
2918 RETURN();
2919}
2920
2921void op_di (void)
2922{
7a387fff 2923 T0 = env->CP0_Status;
4de9b249
TS
2924 env->CP0_Status = T0 & ~(1 << CP0St_IE);
2925 CALL_FROM_TB1(cpu_mips_update_irq, env);
7a387fff
TS
2926 RETURN();
2927}
2928
2929void op_ei (void)
2930{
7a387fff 2931 T0 = env->CP0_Status;
4de9b249
TS
2932 env->CP0_Status = T0 | (1 << CP0St_IE);
2933 CALL_FROM_TB1(cpu_mips_update_irq, env);
7a387fff 2934 RETURN();
6af0bf9c
FB
2935}
2936
2937void op_trap (void)
2938{
2939 if (T0) {
1579a72e 2940 CALL_FROM_TB1(do_raise_exception, EXCP_TRAP);
6af0bf9c
FB
2941 }
2942 RETURN();
2943}
2944
4ad40f36
FB
2945void op_debug (void)
2946{
7a387fff
TS
2947 CALL_FROM_TB1(do_raise_exception, EXCP_DEBUG);
2948 RETURN();
4ad40f36
FB
2949}
2950
6af0bf9c
FB
2951void op_set_lladdr (void)
2952{
2953 env->CP0_LLAddr = T2;
7a387fff 2954 RETURN();
6af0bf9c
FB
2955}
2956
f41c52f1
TS
2957void debug_pre_eret (void);
2958void debug_post_eret (void);
6af0bf9c
FB
2959void op_eret (void)
2960{
f41c52f1
TS
2961 if (loglevel & CPU_LOG_EXEC)
2962 CALL_FROM_TB0(debug_pre_eret);
24c7b0e3 2963 if (env->CP0_Status & (1 << CP0St_ERL)) {
ead9360e 2964 env->PC[env->current_tc] = env->CP0_ErrorEPC;
24c7b0e3 2965 env->CP0_Status &= ~(1 << CP0St_ERL);
51e11d9e 2966 } else {
ead9360e 2967 env->PC[env->current_tc] = env->CP0_EPC;
24c7b0e3 2968 env->CP0_Status &= ~(1 << CP0St_EXL);
51e11d9e 2969 }
08fa4bab 2970 CALL_FROM_TB1(compute_hflags, env);
f41c52f1
TS
2971 if (loglevel & CPU_LOG_EXEC)
2972 CALL_FROM_TB0(debug_post_eret);
6af0bf9c 2973 env->CP0_LLAddr = 1;
7a387fff 2974 RETURN();
6af0bf9c
FB
2975}
2976
2977void op_deret (void)
2978{
f41c52f1
TS
2979 if (loglevel & CPU_LOG_EXEC)
2980 CALL_FROM_TB0(debug_pre_eret);
ead9360e 2981 env->PC[env->current_tc] = env->CP0_DEPC;
08fa4bab
TS
2982 env->hflags &= MIPS_HFLAG_DM;
2983 CALL_FROM_TB1(compute_hflags, env);
f41c52f1
TS
2984 if (loglevel & CPU_LOG_EXEC)
2985 CALL_FROM_TB0(debug_post_eret);
24c7b0e3 2986 env->CP0_LLAddr = 1;
7a387fff
TS
2987 RETURN();
2988}
2989
2990void op_rdhwr_cpunum(void)
2991{
387a8fe5
TS
2992 if ((env->hflags & MIPS_HFLAG_CP0) ||
2993 (env->CP0_HWREna & (1 << 0)))
1579a72e 2994 T0 = env->CP0_EBase & 0x3ff;
7a387fff 2995 else
1579a72e 2996 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
7a387fff
TS
2997 RETURN();
2998}
2999
3000void op_rdhwr_synci_step(void)
3001{
387a8fe5
TS
3002 if ((env->hflags & MIPS_HFLAG_CP0) ||
3003 (env->CP0_HWREna & (1 << 1)))
1579a72e 3004 T0 = env->SYNCI_Step;
7a387fff 3005 else
1579a72e 3006 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
7a387fff
TS
3007 RETURN();
3008}
3009
3010void op_rdhwr_cc(void)
3011{
387a8fe5
TS
3012 if ((env->hflags & MIPS_HFLAG_CP0) ||
3013 (env->CP0_HWREna & (1 << 2)))
1579a72e 3014 T0 = env->CP0_Count;
7a387fff 3015 else
1579a72e 3016 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
7a387fff
TS
3017 RETURN();
3018}
3019
3020void op_rdhwr_ccres(void)
3021{
387a8fe5
TS
3022 if ((env->hflags & MIPS_HFLAG_CP0) ||
3023 (env->CP0_HWREna & (1 << 3)))
1579a72e 3024 T0 = env->CCRes;
7a387fff 3025 else
1579a72e
TS
3026 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
3027 RETURN();
3028}
3029
6af0bf9c
FB
3030void op_save_state (void)
3031{
3032 env->hflags = PARAM1;
3033 RETURN();
3034}
3035
3036void op_save_pc (void)
3037{
ead9360e 3038 env->PC[env->current_tc] = PARAM1;
6af0bf9c
FB
3039 RETURN();
3040}
3041
d26bc211 3042#if defined(TARGET_MIPS64)
9b9e4393
TS
3043void op_save_pc64 (void)
3044{
ead9360e 3045 env->PC[env->current_tc] = ((uint64_t)PARAM1 << 32) | (uint32_t)PARAM2;
9b9e4393
TS
3046 RETURN();
3047}
3048#endif
3049
16c00cb2
TS
3050void op_interrupt_restart (void)
3051{
3052 if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
3053 !(env->CP0_Status & (1 << CP0St_ERL)) &&
3054 !(env->hflags & MIPS_HFLAG_DM) &&
3055 (env->CP0_Status & (1 << CP0St_IE)) &&
3056 (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask)) {
3057 env->CP0_Cause &= ~(0x1f << CP0Ca_EC);
3058 CALL_FROM_TB1(do_raise_exception, EXCP_EXT_INTERRUPT);
3059 }
3060 RETURN();
3061}
3062
6af0bf9c
FB
3063void op_raise_exception (void)
3064{
3065 CALL_FROM_TB1(do_raise_exception, PARAM1);
3066 RETURN();
3067}
3068
3069void op_raise_exception_err (void)
3070{
3071 CALL_FROM_TB2(do_raise_exception_err, PARAM1, PARAM2);
3072 RETURN();
3073}
3074
3075void op_exit_tb (void)
3076{
3077 EXIT_TB();
7a387fff 3078 RETURN();
6af0bf9c
FB
3079}
3080
4ad40f36
FB
3081void op_wait (void)
3082{
3083 env->halted = 1;
3084 CALL_FROM_TB1(do_raise_exception, EXCP_HLT);
7a387fff
TS
3085 RETURN();
3086}
3087
3088/* Bitfield operations. */
3089void op_ext(void)
3090{
3091 unsigned int pos = PARAM1;
3092 unsigned int size = PARAM2;
3093
f757d6ff 3094 T0 = ((uint32_t)T1 >> pos) & ((size < 32) ? ((1 << size) - 1) : ~0);
7a387fff
TS
3095 RETURN();
3096}
3097
3098void op_ins(void)
3099{
3100 unsigned int pos = PARAM1;
3101 unsigned int size = PARAM2;
f757d6ff 3102 target_ulong mask = ((size < 32) ? ((1 << size) - 1) : ~0) << pos;
7a387fff 3103
171b31e7 3104 T0 = (T0 & ~mask) | (((uint32_t)T1 << pos) & mask);
7a387fff
TS
3105 RETURN();
3106}
3107
3108void op_wsbh(void)
3109{
3110 T0 = ((T1 << 8) & ~0x00FF00FF) | ((T1 >> 8) & 0x00FF00FF);
3111 RETURN();
3112}
3113
d26bc211 3114#if defined(TARGET_MIPS64)
c570fd16
TS
3115void op_dext(void)
3116{
3117 unsigned int pos = PARAM1;
3118 unsigned int size = PARAM2;
3119
f757d6ff 3120 T0 = (T1 >> pos) & ((size < 32) ? ((1 << size) - 1) : ~0);
c570fd16
TS
3121 RETURN();
3122}
3123
3124void op_dins(void)
3125{
3126 unsigned int pos = PARAM1;
3127 unsigned int size = PARAM2;
f757d6ff 3128 target_ulong mask = ((size < 32) ? ((1 << size) - 1) : ~0) << pos;
c570fd16 3129
171b31e7 3130 T0 = (T0 & ~mask) | ((T1 << pos) & mask);
c570fd16
TS
3131 RETURN();
3132}
3133
7a387fff
TS
3134void op_dsbh(void)
3135{
3136 T0 = ((T1 << 8) & ~0x00FF00FF00FF00FFULL) | ((T1 >> 8) & 0x00FF00FF00FF00FFULL);
3137 RETURN();
3138}
3139
3140void op_dshd(void)
3141{
3142 T0 = ((T1 << 16) & ~0x0000FFFF0000FFFFULL) | ((T1 >> 16) & 0x0000FFFF0000FFFFULL);
3143 RETURN();
3144}
c570fd16 3145#endif
7a387fff
TS
3146
3147void op_seb(void)
3148{
3149 T0 = ((T1 & 0xFF) ^ 0x80) - 0x80;
3150 RETURN();
3151}
3152
3153void op_seh(void)
3154{
3155 T0 = ((T1 & 0xFFFF) ^ 0x8000) - 0x8000;
3156 RETURN();
4ad40f36 3157}