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