fpu init fix (Jocelyn Mayer)
[qemu/qemu_0_9_1_stable.git] / target-ppc / op.c
blob5accc55064c1caa5a81b2fd0bb6198a35fb839ba
1 /*
2 * PPC emulation micro-operations for qemu.
3 *
4 * Copyright (c) 2003 Jocelyn Mayer
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 //#define DEBUG_OP
23 #include "config.h"
24 #include "exec.h"
26 #define regs (env)
27 #define Ts0 (int32_t)T0
28 #define Ts1 (int32_t)T1
29 #define Ts2 (int32_t)T2
31 #define FT0 (env->ft0)
32 #define FT1 (env->ft1)
33 #define FT2 (env->ft2)
35 #define FTS0 ((float)env->ft0)
36 #define FTS1 ((float)env->ft1)
37 #define FTS2 ((float)env->ft2)
39 #define PPC_OP(name) void glue(op_, name)(void)
41 #define REG 0
42 #include "op_template.h"
44 #define REG 1
45 #include "op_template.h"
47 #define REG 2
48 #include "op_template.h"
50 #define REG 3
51 #include "op_template.h"
53 #define REG 4
54 #include "op_template.h"
56 #define REG 5
57 #include "op_template.h"
59 #define REG 6
60 #include "op_template.h"
62 #define REG 7
63 #include "op_template.h"
65 #define REG 8
66 #include "op_template.h"
68 #define REG 9
69 #include "op_template.h"
71 #define REG 10
72 #include "op_template.h"
74 #define REG 11
75 #include "op_template.h"
77 #define REG 12
78 #include "op_template.h"
80 #define REG 13
81 #include "op_template.h"
83 #define REG 14
84 #include "op_template.h"
86 #define REG 15
87 #include "op_template.h"
89 #define REG 16
90 #include "op_template.h"
92 #define REG 17
93 #include "op_template.h"
95 #define REG 18
96 #include "op_template.h"
98 #define REG 19
99 #include "op_template.h"
101 #define REG 20
102 #include "op_template.h"
104 #define REG 21
105 #include "op_template.h"
107 #define REG 22
108 #include "op_template.h"
110 #define REG 23
111 #include "op_template.h"
113 #define REG 24
114 #include "op_template.h"
116 #define REG 25
117 #include "op_template.h"
119 #define REG 26
120 #include "op_template.h"
122 #define REG 27
123 #include "op_template.h"
125 #define REG 28
126 #include "op_template.h"
128 #define REG 29
129 #include "op_template.h"
131 #define REG 30
132 #include "op_template.h"
134 #define REG 31
135 #include "op_template.h"
137 /* PPC state maintenance operations */
138 /* set_Rc0 */
139 PPC_OP(set_Rc0)
141 uint32_t tmp;
143 if (Ts0 < 0) {
144 tmp = 0x08;
145 } else if (Ts0 > 0) {
146 tmp = 0x04;
147 } else {
148 tmp = 0x02;
150 tmp |= xer_ov;
151 env->crf[0] = tmp;
152 RETURN();
155 /* reset_Rc0 */
156 PPC_OP(reset_Rc0)
158 env->crf[0] = 0x02 | xer_ov;
159 RETURN();
162 /* set_Rc0_1 */
163 PPC_OP(set_Rc0_1)
165 env->crf[0] = 0x04 | xer_ov;
166 RETURN();
169 /* Set Rc1 (for floating point arithmetic) */
170 PPC_OP(set_Rc1)
172 env->crf[1] = regs->fpscr[7];
173 RETURN();
176 /* Constants load */
177 PPC_OP(set_T0)
179 T0 = PARAM(1);
180 RETURN();
183 PPC_OP(set_T1)
185 T1 = PARAM(1);
186 RETURN();
189 PPC_OP(set_T2)
191 T2 = PARAM(1);
192 RETURN();
195 /* Generate exceptions */
196 PPC_OP(raise_exception_err)
198 do_raise_exception_err(PARAM(1), PARAM(2));
201 PPC_OP(raise_exception)
203 do_raise_exception(PARAM(1));
206 PPC_OP(update_nip)
208 env->nip = PARAM(1);
211 PPC_OP(debug)
213 env->nip = PARAM(1);
214 #if defined (DEBUG_OP)
215 dump_state();
216 #endif
217 do_raise_exception(EXCP_DEBUG);
218 RETURN();
221 /* Segment registers load and store with immediate index */
222 PPC_OP(load_srin)
224 T0 = regs->sr[T1 >> 28];
225 RETURN();
228 PPC_OP(store_srin)
230 do_store_sr(T1 >> 28);
231 RETURN();
234 PPC_OP(load_sdr1)
236 T0 = regs->sdr1;
237 RETURN();
240 PPC_OP(store_sdr1)
242 regs->sdr1 = T0;
243 RETURN();
246 PPC_OP(exit_tb)
248 EXIT_TB();
251 /* Load/store special registers */
252 PPC_OP(load_cr)
254 do_load_cr();
255 RETURN();
258 PPC_OP(store_cr)
260 do_store_cr(PARAM(1));
261 RETURN();
264 PPC_OP(load_xer_cr)
266 T0 = (xer_so << 3) | (xer_ov << 2) | (xer_ca << 1);
267 RETURN();
270 PPC_OP(clear_xer_cr)
272 xer_so = 0;
273 xer_ov = 0;
274 xer_ca = 0;
275 RETURN();
278 PPC_OP(load_xer_bc)
280 T1 = xer_bc;
281 RETURN();
284 PPC_OP(load_xer)
286 do_load_xer();
287 RETURN();
290 PPC_OP(store_xer)
292 do_store_xer();
293 RETURN();
296 PPC_OP(load_msr)
298 do_load_msr();
299 RETURN();
302 PPC_OP(store_msr)
304 do_store_msr();
305 RETURN();
308 /* SPR */
309 PPC_OP(load_spr)
311 T0 = regs->spr[PARAM(1)];
312 RETURN();
315 PPC_OP(store_spr)
317 regs->spr[PARAM(1)] = T0;
318 RETURN();
321 PPC_OP(load_lr)
323 T0 = regs->lr;
324 RETURN();
327 PPC_OP(store_lr)
329 regs->lr = T0;
330 RETURN();
333 PPC_OP(load_ctr)
335 T0 = regs->ctr;
336 RETURN();
339 PPC_OP(store_ctr)
341 regs->ctr = T0;
342 RETURN();
345 PPC_OP(load_tbl)
347 T0 = cpu_ppc_load_tbl(regs);
348 RETURN();
351 PPC_OP(load_tbu)
353 T0 = cpu_ppc_load_tbu(regs);
354 RETURN();
357 PPC_OP(store_tbl)
359 cpu_ppc_store_tbl(regs, T0);
360 RETURN();
363 PPC_OP(store_tbu)
365 cpu_ppc_store_tbu(regs, T0);
366 RETURN();
369 PPC_OP(load_decr)
371 T0 = cpu_ppc_load_decr(regs);
374 PPC_OP(store_decr)
376 cpu_ppc_store_decr(regs, T0);
377 RETURN();
380 PPC_OP(load_ibat)
382 T0 = regs->IBAT[PARAM(1)][PARAM(2)];
385 PPC_OP(store_ibat)
387 do_store_ibat(PARAM(1), PARAM(2));
390 PPC_OP(load_dbat)
392 T0 = regs->DBAT[PARAM(1)][PARAM(2)];
395 PPC_OP(store_dbat)
397 do_store_dbat(PARAM(1), PARAM(2));
400 /* FPSCR */
401 PPC_OP(load_fpscr)
403 do_load_fpscr();
404 RETURN();
407 PPC_OP(store_fpscr)
409 do_store_fpscr(PARAM(1));
410 RETURN();
413 PPC_OP(reset_scrfx)
415 regs->fpscr[7] &= ~0x8;
416 RETURN();
419 /* crf operations */
420 PPC_OP(getbit_T0)
422 T0 = (T0 >> PARAM(1)) & 1;
423 RETURN();
426 PPC_OP(getbit_T1)
428 T1 = (T1 >> PARAM(1)) & 1;
429 RETURN();
432 PPC_OP(setcrfbit)
434 T1 = (T1 & PARAM(1)) | (T0 << PARAM(2));
435 RETURN();
438 /* Branch */
439 #define EIP regs->nip
441 PPC_OP(setlr)
443 regs->lr = PARAM1;
446 PPC_OP(b)
448 JUMP_TB(b1, PARAM1, 0, PARAM2);
451 PPC_OP(b_T1)
453 regs->nip = T1;
456 PPC_OP(btest)
458 if (T0) {
459 JUMP_TB(btest, PARAM1, 0, PARAM2);
460 } else {
461 JUMP_TB(btest, PARAM1, 1, PARAM3);
463 RETURN();
466 PPC_OP(btest_T1)
468 if (T0) {
469 regs->nip = T1 & ~3;
470 } else {
471 regs->nip = PARAM1;
473 RETURN();
476 PPC_OP(movl_T1_ctr)
478 T1 = regs->ctr;
481 PPC_OP(movl_T1_lr)
483 T1 = regs->lr;
486 /* tests with result in T0 */
488 PPC_OP(test_ctr)
490 T0 = regs->ctr;
493 PPC_OP(test_ctr_true)
495 T0 = (regs->ctr != 0 && (T0 & PARAM(1)) != 0);
498 PPC_OP(test_ctr_false)
500 T0 = (regs->ctr != 0 && (T0 & PARAM(1)) == 0);
503 PPC_OP(test_ctrz)
505 T0 = (regs->ctr == 0);
508 PPC_OP(test_ctrz_true)
510 T0 = (regs->ctr == 0 && (T0 & PARAM(1)) != 0);
513 PPC_OP(test_ctrz_false)
515 T0 = (regs->ctr == 0 && (T0 & PARAM(1)) == 0);
518 PPC_OP(test_true)
520 T0 = (T0 & PARAM(1));
523 PPC_OP(test_false)
525 T0 = ((T0 & PARAM(1)) == 0);
528 /* CTR maintenance */
529 PPC_OP(dec_ctr)
531 regs->ctr--;
532 RETURN();
535 /*** Integer arithmetic ***/
536 /* add */
537 PPC_OP(add)
539 T0 += T1;
540 RETURN();
543 PPC_OP(addo)
545 T2 = T0;
546 T0 += T1;
547 if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
548 xer_so = 1;
549 xer_ov = 1;
550 } else {
551 xer_ov = 0;
553 RETURN();
556 /* add carrying */
557 PPC_OP(addc)
559 T2 = T0;
560 T0 += T1;
561 if (T0 < T2) {
562 xer_ca = 1;
563 } else {
564 xer_ca = 0;
566 RETURN();
569 PPC_OP(addco)
571 T2 = T0;
572 T0 += T1;
573 if (T0 < T2) {
574 xer_ca = 1;
575 } else {
576 xer_ca = 0;
578 if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
579 xer_so = 1;
580 xer_ov = 1;
581 } else {
582 xer_ov = 0;
584 RETURN();
587 /* add extended */
588 /* candidate for helper (too long) */
589 PPC_OP(adde)
591 T2 = T0;
592 T0 += T1 + xer_ca;
593 if (T0 < T2 || (xer_ca == 1 && T0 == T2)) {
594 xer_ca = 1;
595 } else {
596 xer_ca = 0;
598 RETURN();
601 PPC_OP(addeo)
603 T2 = T0;
604 T0 += T1 + xer_ca;
605 if (T0 < T2 || (xer_ca == 1 && T0 == T2)) {
606 xer_ca = 1;
607 } else {
608 xer_ca = 0;
610 if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
611 xer_so = 1;
612 xer_ov = 1;
613 } else {
614 xer_ov = 0;
616 RETURN();
619 /* add immediate */
620 PPC_OP(addi)
622 T0 += PARAM(1);
623 RETURN();
626 /* add immediate carrying */
627 PPC_OP(addic)
629 T1 = T0;
630 T0 += PARAM(1);
631 if (T0 < T1) {
632 xer_ca = 1;
633 } else {
634 xer_ca = 0;
636 RETURN();
639 /* add to minus one extended */
640 PPC_OP(addme)
642 T1 = T0;
643 T0 += xer_ca + (-1);
644 if (T1 != 0)
645 xer_ca = 1;
646 RETURN();
649 PPC_OP(addmeo)
651 T1 = T0;
652 T0 += xer_ca + (-1);
653 if (T1 & (T1 ^ T0) & (1 << 31)) {
654 xer_so = 1;
655 xer_ov = 1;
656 } else {
657 xer_ov = 0;
659 if (T1 != 0)
660 xer_ca = 1;
661 RETURN();
664 /* add to zero extended */
665 PPC_OP(addze)
667 T1 = T0;
668 T0 += xer_ca;
669 if (T0 < T1) {
670 xer_ca = 1;
671 } else {
672 xer_ca = 0;
674 RETURN();
677 PPC_OP(addzeo)
679 T1 = T0;
680 T0 += xer_ca;
681 if ((T1 ^ (-1)) & (T1 ^ T0) & (1 << 31)) {
682 xer_so = 1;
683 xer_ov = 1;
684 } else {
685 xer_ov = 0;
687 if (T0 < T1) {
688 xer_ca = 1;
689 } else {
690 xer_ca = 0;
692 RETURN();
695 /* divide word */
696 /* candidate for helper (too long) */
697 PPC_OP(divw)
699 if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
700 T0 = (int32_t)((-1) * (T0 >> 31));
701 } else {
702 T0 = (Ts0 / Ts1);
704 RETURN();
707 PPC_OP(divwo)
709 if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
710 xer_so = 1;
711 xer_ov = 1;
712 T0 = (-1) * (T0 >> 31);
713 } else {
714 xer_ov = 0;
715 T0 = (Ts0 / Ts1);
717 RETURN();
720 /* divide word unsigned */
721 PPC_OP(divwu)
723 if (T1 == 0) {
724 T0 = 0;
725 } else {
726 T0 /= T1;
728 RETURN();
731 PPC_OP(divwuo)
733 if (T1 == 0) {
734 xer_so = 1;
735 xer_ov = 1;
736 T0 = 0;
737 } else {
738 xer_ov = 0;
739 T0 /= T1;
741 RETURN();
744 /* multiply high word */
745 PPC_OP(mulhw)
747 T0 = ((int64_t)Ts0 * (int64_t)Ts1) >> 32;
748 RETURN();
751 /* multiply high word unsigned */
752 PPC_OP(mulhwu)
754 T0 = ((uint64_t)T0 * (uint64_t)T1) >> 32;
755 RETURN();
758 /* multiply low immediate */
759 PPC_OP(mulli)
761 T0 = (Ts0 * SPARAM(1));
762 RETURN();
765 /* multiply low word */
766 PPC_OP(mullw)
768 T0 *= T1;
769 RETURN();
772 PPC_OP(mullwo)
774 int64_t res = (int64_t)Ts0 * (int64_t)Ts1;
776 if ((int32_t)res != res) {
777 xer_ov = 1;
778 xer_so = 1;
779 } else {
780 xer_ov = 0;
782 T0 = (int32_t)res;
783 RETURN();
786 /* negate */
787 PPC_OP(neg)
789 if (T0 != 0x80000000) {
790 T0 = -Ts0;
792 RETURN();
795 PPC_OP(nego)
797 if (T0 == 0x80000000) {
798 xer_ov = 1;
799 xer_so = 1;
800 } else {
801 xer_ov = 0;
802 T0 = -Ts0;
804 RETURN();
807 /* substract from */
808 PPC_OP(subf)
810 T0 = T1 - T0;
811 RETURN();
814 PPC_OP(subfo)
816 T2 = T0;
817 T0 = T1 - T0;
818 if (((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)) {
819 xer_so = 1;
820 xer_ov = 1;
821 } else {
822 xer_ov = 0;
824 RETURN();
827 /* substract from carrying */
828 PPC_OP(subfc)
830 T0 = T1 - T0;
831 if (T0 <= T1) {
832 xer_ca = 1;
833 } else {
834 xer_ca = 0;
836 RETURN();
839 PPC_OP(subfco)
841 T2 = T0;
842 T0 = T1 - T0;
843 if (T0 <= T1) {
844 xer_ca = 1;
845 } else {
846 xer_ca = 0;
848 if (((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)) {
849 xer_so = 1;
850 xer_ov = 1;
851 } else {
852 xer_ov = 0;
854 RETURN();
857 /* substract from extended */
858 /* candidate for helper (too long) */
859 PPC_OP(subfe)
861 T0 = T1 + ~T0 + xer_ca;
862 if (T0 < T1 || (xer_ca == 1 && T0 == T1)) {
863 xer_ca = 1;
864 } else {
865 xer_ca = 0;
867 RETURN();
870 PPC_OP(subfeo)
872 T2 = T0;
873 T0 = T1 + ~T0 + xer_ca;
874 if ((~T2 ^ T1 ^ (-1)) & (~T2 ^ T0) & (1 << 31)) {
875 xer_so = 1;
876 xer_ov = 1;
877 } else {
878 xer_ov = 0;
880 if (T0 < T1 || (xer_ca == 1 && T0 == T1)) {
881 xer_ca = 1;
882 } else {
883 xer_ca = 0;
885 RETURN();
888 /* substract from immediate carrying */
889 PPC_OP(subfic)
891 T0 = PARAM(1) + ~T0 + 1;
892 if (T0 <= PARAM(1)) {
893 xer_ca = 1;
894 } else {
895 xer_ca = 0;
897 RETURN();
900 /* substract from minus one extended */
901 PPC_OP(subfme)
903 T0 = ~T0 + xer_ca - 1;
905 if (T0 != -1)
906 xer_ca = 1;
907 RETURN();
910 PPC_OP(subfmeo)
912 T1 = T0;
913 T0 = ~T0 + xer_ca - 1;
914 if (~T1 & (~T1 ^ T0) & (1 << 31)) {
915 xer_so = 1;
916 xer_ov = 1;
917 } else {
918 xer_ov = 0;
920 if (T1 != -1)
921 xer_ca = 1;
922 RETURN();
925 /* substract from zero extended */
926 PPC_OP(subfze)
928 T1 = ~T0;
929 T0 = T1 + xer_ca;
930 if (T0 < T1) {
931 xer_ca = 1;
932 } else {
933 xer_ca = 0;
935 RETURN();
938 PPC_OP(subfzeo)
940 T1 = T0;
941 T0 = ~T0 + xer_ca;
942 if ((~T1 ^ (-1)) & ((~T1) ^ T0) & (1 << 31)) {
943 xer_ov = 1;
944 xer_so = 1;
945 } else {
946 xer_ov = 0;
948 if (T0 < ~T1) {
949 xer_ca = 1;
950 } else {
951 xer_ca = 0;
953 RETURN();
956 /*** Integer comparison ***/
957 /* compare */
958 PPC_OP(cmp)
960 if (Ts0 < Ts1) {
961 T0 = 0x08;
962 } else if (Ts0 > Ts1) {
963 T0 = 0x04;
964 } else {
965 T0 = 0x02;
967 RETURN();
970 /* compare immediate */
971 PPC_OP(cmpi)
973 if (Ts0 < SPARAM(1)) {
974 T0 = 0x08;
975 } else if (Ts0 > SPARAM(1)) {
976 T0 = 0x04;
977 } else {
978 T0 = 0x02;
980 RETURN();
983 /* compare logical */
984 PPC_OP(cmpl)
986 if (T0 < T1) {
987 T0 = 0x08;
988 } else if (T0 > T1) {
989 T0 = 0x04;
990 } else {
991 T0 = 0x02;
993 RETURN();
996 /* compare logical immediate */
997 PPC_OP(cmpli)
999 if (T0 < PARAM(1)) {
1000 T0 = 0x08;
1001 } else if (T0 > PARAM(1)) {
1002 T0 = 0x04;
1003 } else {
1004 T0 = 0x02;
1006 RETURN();
1009 /*** Integer logical ***/
1010 /* and */
1011 PPC_OP(and)
1013 T0 &= T1;
1014 RETURN();
1017 /* andc */
1018 PPC_OP(andc)
1020 T0 &= ~T1;
1021 RETURN();
1024 /* andi. */
1025 PPC_OP(andi_)
1027 T0 &= PARAM(1);
1028 RETURN();
1031 /* count leading zero */
1032 PPC_OP(cntlzw)
1034 T1 = T0;
1035 for (T0 = 32; T1 > 0; T0--)
1036 T1 = T1 >> 1;
1037 RETURN();
1040 /* eqv */
1041 PPC_OP(eqv)
1043 T0 = ~(T0 ^ T1);
1044 RETURN();
1047 /* extend sign byte */
1048 PPC_OP(extsb)
1050 T0 = (int32_t)((int8_t)(Ts0));
1051 RETURN();
1054 /* extend sign half word */
1055 PPC_OP(extsh)
1057 T0 = (int32_t)((int16_t)(Ts0));
1058 RETURN();
1061 /* nand */
1062 PPC_OP(nand)
1064 T0 = ~(T0 & T1);
1065 RETURN();
1068 /* nor */
1069 PPC_OP(nor)
1071 T0 = ~(T0 | T1);
1072 RETURN();
1075 /* or */
1076 PPC_OP(or)
1078 T0 |= T1;
1079 RETURN();
1082 /* orc */
1083 PPC_OP(orc)
1085 T0 |= ~T1;
1086 RETURN();
1089 /* ori */
1090 PPC_OP(ori)
1092 T0 |= PARAM(1);
1093 RETURN();
1096 /* xor */
1097 PPC_OP(xor)
1099 T0 ^= T1;
1100 RETURN();
1103 /* xori */
1104 PPC_OP(xori)
1106 T0 ^= PARAM(1);
1107 RETURN();
1110 /*** Integer rotate ***/
1111 /* rotate left word immediate then mask insert */
1112 PPC_OP(rlwimi)
1114 T0 = (rotl(T0, PARAM(1)) & PARAM(2)) | (T1 & PARAM(3));
1115 RETURN();
1118 /* rotate left immediate then and with mask insert */
1119 PPC_OP(rotlwi)
1121 T0 = rotl(T0, PARAM(1));
1122 RETURN();
1125 PPC_OP(slwi)
1127 T0 = T0 << PARAM(1);
1128 RETURN();
1131 PPC_OP(srwi)
1133 T0 = T0 >> PARAM(1);
1134 RETURN();
1137 /* rotate left word then and with mask insert */
1138 PPC_OP(rlwinm)
1140 T0 = rotl(T0, PARAM(1)) & PARAM(2);
1141 RETURN();
1144 PPC_OP(rotl)
1146 T0 = rotl(T0, T1);
1147 RETURN();
1150 PPC_OP(rlwnm)
1152 T0 = rotl(T0, T1) & PARAM(1);
1153 RETURN();
1156 /*** Integer shift ***/
1157 /* shift left word */
1158 PPC_OP(slw)
1160 if (T1 & 0x20) {
1161 T0 = 0;
1162 } else {
1163 T0 = T0 << T1;
1165 RETURN();
1168 /* shift right algebraic word */
1169 PPC_OP(sraw)
1171 do_sraw();
1172 RETURN();
1175 /* shift right algebraic word immediate */
1176 PPC_OP(srawi)
1178 T1 = T0;
1179 T0 = (Ts0 >> PARAM(1));
1180 if (Ts1 < 0 && (Ts1 & PARAM(2)) != 0) {
1181 xer_ca = 1;
1182 } else {
1183 xer_ca = 0;
1185 RETURN();
1188 /* shift right word */
1189 PPC_OP(srw)
1191 if (T1 & 0x20) {
1192 T0 = 0;
1193 } else {
1194 T0 = T0 >> T1;
1196 RETURN();
1199 /*** Floating-Point arithmetic ***/
1200 /* fadd - fadd. */
1201 PPC_OP(fadd)
1203 FT0 += FT1;
1204 RETURN();
1207 /* fadds - fadds. */
1208 PPC_OP(fadds)
1210 FT0 = FTS0 + FTS1;
1211 RETURN();
1214 /* fsub - fsub. */
1215 PPC_OP(fsub)
1217 FT0 -= FT1;
1218 RETURN();
1221 /* fsubs - fsubs. */
1222 PPC_OP(fsubs)
1224 FT0 = FTS0 - FTS1;
1225 RETURN();
1228 /* fmul - fmul. */
1229 PPC_OP(fmul)
1231 FT0 *= FT1;
1232 RETURN();
1235 /* fmuls - fmuls. */
1236 PPC_OP(fmuls)
1238 FT0 = FTS0 * FTS1;
1239 RETURN();
1242 /* fdiv - fdiv. */
1243 PPC_OP(fdiv)
1245 FT0 /= FT1;
1246 RETURN();
1249 /* fdivs - fdivs. */
1250 PPC_OP(fdivs)
1252 FT0 = FTS0 / FTS1;
1253 RETURN();
1256 /* fsqrt - fsqrt. */
1257 PPC_OP(fsqrt)
1259 do_fsqrt();
1260 RETURN();
1263 /* fsqrts - fsqrts. */
1264 PPC_OP(fsqrts)
1266 do_fsqrts();
1267 RETURN();
1270 /* fres - fres. */
1271 PPC_OP(fres)
1273 do_fres();
1274 RETURN();
1277 /* frsqrte - frsqrte. */
1278 PPC_OP(frsqrte)
1280 do_fsqrte();
1281 RETURN();
1284 /* fsel - fsel. */
1285 PPC_OP(fsel)
1287 do_fsel();
1288 RETURN();
1291 /*** Floating-Point multiply-and-add ***/
1292 /* fmadd - fmadd. */
1293 PPC_OP(fmadd)
1295 FT0 = (FT0 * FT1) + FT2;
1296 RETURN();
1299 /* fmadds - fmadds. */
1300 PPC_OP(fmadds)
1302 FT0 = (FTS0 * FTS1) + FTS2;
1303 RETURN();
1306 /* fmsub - fmsub. */
1307 PPC_OP(fmsub)
1309 FT0 = (FT0 * FT1) - FT2;
1310 RETURN();
1313 /* fmsubs - fmsubs. */
1314 PPC_OP(fmsubs)
1316 FT0 = (FTS0 * FTS1) - FTS2;
1317 RETURN();
1320 /* fnmadd - fnmadd. - fnmadds - fnmadds. */
1321 PPC_OP(fnmadd)
1323 do_fnmadd();
1324 RETURN();
1327 /* fnmadds - fnmadds. */
1328 PPC_OP(fnmadds)
1330 do_fnmadds();
1331 RETURN();
1334 /* fnmsub - fnmsub. */
1335 PPC_OP(fnmsub)
1337 do_fnmsub();
1338 RETURN();
1341 /* fnmsubs - fnmsubs. */
1342 PPC_OP(fnmsubs)
1344 do_fnmsubs();
1345 RETURN();
1348 /*** Floating-Point round & convert ***/
1349 /* frsp - frsp. */
1350 PPC_OP(frsp)
1352 FT0 = (float)FT0;
1353 RETURN();
1356 /* fctiw - fctiw. */
1357 PPC_OP(fctiw)
1359 do_fctiw();
1360 RETURN();
1363 /* fctiwz - fctiwz. */
1364 PPC_OP(fctiwz)
1366 do_fctiwz();
1367 RETURN();
1371 /*** Floating-Point compare ***/
1372 /* fcmpu */
1373 PPC_OP(fcmpu)
1375 do_fcmpu();
1376 RETURN();
1379 /* fcmpo */
1380 PPC_OP(fcmpo)
1382 do_fcmpo();
1383 RETURN();
1386 /*** Floating-point move ***/
1387 /* fabs */
1388 PPC_OP(fabs)
1390 do_fabs();
1391 RETURN();
1394 /* fnabs */
1395 PPC_OP(fnabs)
1397 do_fnabs();
1398 RETURN();
1401 /* fneg */
1402 PPC_OP(fneg)
1404 FT0 = -FT0;
1405 RETURN();
1408 /* Load and store */
1409 #define MEMSUFFIX _raw
1410 #include "op_mem.h"
1411 #if !defined(CONFIG_USER_ONLY)
1412 #define MEMSUFFIX _user
1413 #include "op_mem.h"
1415 #define MEMSUFFIX _kernel
1416 #include "op_mem.h"
1417 #endif
1419 /* Special op to check and maybe clear reservation */
1420 PPC_OP(check_reservation)
1422 do_check_reservation();
1423 RETURN();
1426 /* Return from interrupt */
1427 PPC_OP(rfi)
1429 regs->nip = regs->spr[SRR0] & ~0x00000003;
1430 #if 1 // TRY
1431 T0 = regs->spr[SRR1] & ~0xFFF00000;
1432 #else
1433 T0 = regs->spr[SRR1] & ~0xFFFF0000;
1434 #endif
1435 do_store_msr();
1436 #if defined (DEBUG_OP)
1437 dump_rfi();
1438 #endif
1439 // do_tlbia();
1440 do_raise_exception(EXCP_RFI);
1441 RETURN();
1444 /* Trap word */
1445 PPC_OP(tw)
1447 if ((Ts0 < Ts1 && (PARAM(1) & 0x10)) ||
1448 (Ts0 > Ts1 && (PARAM(1) & 0x08)) ||
1449 (Ts0 == Ts1 && (PARAM(1) & 0x04)) ||
1450 (T0 < T1 && (PARAM(1) & 0x02)) ||
1451 (T0 > T1 && (PARAM(1) & 0x01)))
1452 do_raise_exception_err(EXCP_PROGRAM, EXCP_TRAP);
1453 RETURN();
1456 PPC_OP(twi)
1458 if ((Ts0 < SPARAM(1) && (PARAM(2) & 0x10)) ||
1459 (Ts0 > SPARAM(1) && (PARAM(2) & 0x08)) ||
1460 (Ts0 == SPARAM(1) && (PARAM(2) & 0x04)) ||
1461 (T0 < (uint32_t)SPARAM(1) && (PARAM(2) & 0x02)) ||
1462 (T0 > (uint32_t)SPARAM(1) && (PARAM(2) & 0x01)))
1463 do_raise_exception_err(EXCP_PROGRAM, EXCP_TRAP);
1464 RETURN();
1467 /* Instruction cache block invalidate */
1468 PPC_OP(icbi)
1470 do_icbi();
1471 RETURN();
1474 /* tlbia */
1475 PPC_OP(tlbia)
1477 do_tlbia();
1478 RETURN();
1481 /* tlbie */
1482 PPC_OP(tlbie)
1484 do_tlbie();
1485 RETURN();