SATN fixes (Blue Swirl).
[qemu] / target-ppc / op.c
1 /*
2  *  PowerPC emulation micro-operations for qemu.
3  * 
4  *  Copyright (c) 2003-2005 Jocelyn Mayer
5  *
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.
10  *
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.
15  *
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
19  */
20
21 //#define DEBUG_OP
22
23 #include "config.h"
24 #include "exec.h"
25
26 #define regs (env)
27 #define Ts0 (int32_t)T0
28 #define Ts1 (int32_t)T1
29 #define Ts2 (int32_t)T2
30
31 #define FT0 (env->ft0)
32 #define FT1 (env->ft1)
33 #define FT2 (env->ft2)
34
35 #define PPC_OP(name) void glue(op_, name)(void)
36
37 #define REG 0
38 #include "op_template.h"
39
40 #define REG 1
41 #include "op_template.h"
42
43 #define REG 2
44 #include "op_template.h"
45
46 #define REG 3
47 #include "op_template.h"
48
49 #define REG 4
50 #include "op_template.h"
51
52 #define REG 5
53 #include "op_template.h"
54
55 #define REG 6
56 #include "op_template.h"
57
58 #define REG 7
59 #include "op_template.h"
60
61 #define REG 8
62 #include "op_template.h"
63
64 #define REG 9
65 #include "op_template.h"
66
67 #define REG 10
68 #include "op_template.h"
69
70 #define REG 11
71 #include "op_template.h"
72
73 #define REG 12
74 #include "op_template.h"
75
76 #define REG 13
77 #include "op_template.h"
78
79 #define REG 14
80 #include "op_template.h"
81
82 #define REG 15
83 #include "op_template.h"
84
85 #define REG 16
86 #include "op_template.h"
87
88 #define REG 17
89 #include "op_template.h"
90
91 #define REG 18
92 #include "op_template.h"
93
94 #define REG 19
95 #include "op_template.h"
96
97 #define REG 20
98 #include "op_template.h"
99
100 #define REG 21
101 #include "op_template.h"
102
103 #define REG 22
104 #include "op_template.h"
105
106 #define REG 23
107 #include "op_template.h"
108
109 #define REG 24
110 #include "op_template.h"
111
112 #define REG 25
113 #include "op_template.h"
114
115 #define REG 26
116 #include "op_template.h"
117
118 #define REG 27
119 #include "op_template.h"
120
121 #define REG 28
122 #include "op_template.h"
123
124 #define REG 29
125 #include "op_template.h"
126
127 #define REG 30
128 #include "op_template.h"
129
130 #define REG 31
131 #include "op_template.h"
132
133 /* PowerPC state maintenance operations */
134 /* set_Rc0 */
135 PPC_OP(set_Rc0)
136 {
137     uint32_t tmp;
138
139     if (Ts0 < 0) {
140         tmp = 0x08;
141     } else if (Ts0 > 0) {
142         tmp = 0x04;
143     } else {
144         tmp = 0x02;
145     }
146     tmp |= xer_ov;
147     env->crf[0] = tmp;
148     RETURN();
149 }
150
151 /* reset_Rc0 */
152 PPC_OP(reset_Rc0)
153 {
154     env->crf[0] = 0x02 | xer_ov;
155     RETURN();
156 }
157
158 /* set_Rc0_1 */
159 PPC_OP(set_Rc0_1)
160 {
161     env->crf[0] = 0x04 | xer_ov;
162     RETURN();
163 }
164
165 /* Set Rc1 (for floating point arithmetic) */
166 PPC_OP(set_Rc1)
167 {
168     env->crf[1] = regs->fpscr[7];
169     RETURN();
170 }
171
172 /* Constants load */
173 PPC_OP(set_T0)
174 {
175     T0 = PARAM(1);
176     RETURN();
177 }
178
179 PPC_OP(set_T1)
180 {
181     T1 = PARAM(1);
182     RETURN();
183 }
184
185 PPC_OP(set_T2)
186 {
187     T2 = PARAM(1);
188     RETURN();
189 }
190
191 /* Generate exceptions */
192 PPC_OP(raise_exception_err)
193 {
194     do_raise_exception_err(PARAM(1), PARAM(2));
195 }
196
197 PPC_OP(raise_exception)
198 {
199     do_raise_exception(PARAM(1));
200 }
201
202 PPC_OP(update_nip)
203 {
204     env->nip = PARAM(1);
205 }
206
207 PPC_OP(debug)
208 {
209     do_raise_exception(EXCP_DEBUG);
210 }
211
212 /* Segment registers load and store with immediate index */
213 PPC_OP(load_srin)
214 {
215     T0 = regs->sr[T1 >> 28];
216     RETURN();
217 }
218
219 PPC_OP(store_srin)
220 {
221     do_store_sr(env, ((uint32_t)T1 >> 28), T0);
222     RETURN();
223 }
224
225 PPC_OP(load_sdr1)
226 {
227     T0 = regs->sdr1;
228     RETURN();
229 }
230
231 PPC_OP(store_sdr1)
232 {
233     do_store_sdr1(env, T0);
234     RETURN();
235 }
236
237 PPC_OP(exit_tb)
238 {
239     EXIT_TB();
240 }
241
242 /* Load/store special registers */
243 PPC_OP(load_cr)
244 {
245     T0 = do_load_cr(env);
246     RETURN();
247 }
248
249 PPC_OP(store_cr)
250 {
251     do_store_cr(env, T0, PARAM(1));
252     RETURN();
253 }
254
255 PPC_OP(load_xer_cr)
256 {
257     T0 = (xer_so << 3) | (xer_ov << 2) | (xer_ca << 1);
258     RETURN();
259 }
260
261 PPC_OP(clear_xer_cr)
262 {
263     xer_so = 0;
264     xer_ov = 0;
265     xer_ca = 0;
266     RETURN();
267 }
268
269 PPC_OP(load_xer_bc)
270 {
271     T1 = xer_bc;
272     RETURN();
273 }
274
275 PPC_OP(load_xer)
276 {
277     T0 = do_load_xer(env);
278     RETURN();
279 }
280
281 PPC_OP(store_xer)
282 {
283     do_store_xer(env, T0);
284     RETURN();
285 }
286
287 PPC_OP(load_msr)
288 {
289     T0 = do_load_msr(env);
290     RETURN();
291 }
292
293 PPC_OP(store_msr)
294 {
295     do_store_msr(env, T0);
296     RETURN();
297 }
298
299 /* SPR */
300 PPC_OP(load_spr)
301 {
302     T0 = regs->spr[PARAM(1)];
303     RETURN();
304 }
305
306 PPC_OP(store_spr)
307 {
308     regs->spr[PARAM(1)] = T0;
309     RETURN();
310 }
311
312 PPC_OP(load_lr)
313 {
314     T0 = regs->lr;
315     RETURN();
316 }
317
318 PPC_OP(store_lr)
319 {
320     regs->lr = T0;
321     RETURN();
322 }
323
324 PPC_OP(load_ctr)
325 {
326     T0 = regs->ctr;
327     RETURN();
328 }
329
330 PPC_OP(store_ctr)
331 {
332     regs->ctr = T0;
333     RETURN();
334 }
335
336 PPC_OP(load_tbl)
337 {
338     T0 = cpu_ppc_load_tbl(regs);
339     RETURN();
340 }
341
342 PPC_OP(load_tbu)
343 {
344     T0 = cpu_ppc_load_tbu(regs);
345     RETURN();
346 }
347
348 PPC_OP(store_tbl)
349 {
350     cpu_ppc_store_tbl(regs, T0);
351     RETURN();
352 }
353
354 PPC_OP(store_tbu)
355 {
356     cpu_ppc_store_tbu(regs, T0);
357     RETURN();
358 }
359
360 PPC_OP(load_decr)
361 {
362     T0 = cpu_ppc_load_decr(regs);
363     }
364
365 PPC_OP(store_decr)
366 {
367     cpu_ppc_store_decr(regs, T0);
368     RETURN();
369 }
370
371 PPC_OP(load_ibat)
372 {
373     T0 = regs->IBAT[PARAM(1)][PARAM(2)];
374 }
375
376 void op_store_ibatu (void)
377 {
378     do_store_ibatu(env, PARAM1, T0);
379     RETURN();
380 }
381
382 void op_store_ibatl (void)
383 {
384 #if 1
385     env->IBAT[1][PARAM1] = T0;
386 #else
387     do_store_ibatl(env, PARAM1, T0);
388 #endif
389     RETURN();
390 }
391
392 PPC_OP(load_dbat)
393 {
394     T0 = regs->DBAT[PARAM(1)][PARAM(2)];
395 }
396
397 void op_store_dbatu (void)
398 {
399     do_store_dbatu(env, PARAM1, T0);
400     RETURN();
401 }
402
403 void op_store_dbatl (void)
404 {
405 #if 1
406     env->DBAT[1][PARAM1] = T0;
407 #else
408     do_store_dbatl(env, PARAM1, T0);
409 #endif
410     RETURN();
411 }
412
413 /* FPSCR */
414 PPC_OP(load_fpscr)
415 {
416     FT0 = do_load_fpscr(env);
417     RETURN();
418 }
419
420 PPC_OP(store_fpscr)
421 {
422     do_store_fpscr(env, FT0, PARAM1);
423     RETURN();
424 }
425
426 PPC_OP(reset_scrfx)
427 {
428     regs->fpscr[7] &= ~0x8;
429     RETURN();
430 }
431
432 /* crf operations */
433 PPC_OP(getbit_T0)
434 {
435     T0 = (T0 >> PARAM(1)) & 1;
436     RETURN();
437 }
438
439 PPC_OP(getbit_T1)
440 {
441     T1 = (T1 >> PARAM(1)) & 1;
442     RETURN();
443 }
444
445 PPC_OP(setcrfbit)
446 {
447     T1 = (T1 & PARAM(1)) | (T0 << PARAM(2)); 
448     RETURN();
449 }
450
451 /* Branch */
452 #define EIP regs->nip
453
454 PPC_OP(setlr)
455 {
456     regs->lr = PARAM1;
457 }
458
459 PPC_OP(goto_tb0)
460 {
461     GOTO_TB(op_goto_tb0, PARAM1, 0);
462 }
463
464 PPC_OP(goto_tb1)
465 {
466     GOTO_TB(op_goto_tb1, PARAM1, 1);
467 }
468
469 PPC_OP(b_T1)
470 {
471     regs->nip = T1 & ~3;
472 }
473
474 PPC_OP(jz_T0)
475 {
476     if (!T0)
477         GOTO_LABEL_PARAM(1);
478     RETURN();
479 }
480
481 PPC_OP(btest_T1) 
482 {
483     if (T0) {
484         regs->nip = T1 & ~3;
485     } else {
486         regs->nip = PARAM1;
487     }
488     RETURN();
489 }
490
491 PPC_OP(movl_T1_ctr)
492 {
493     T1 = regs->ctr;
494 }
495
496 PPC_OP(movl_T1_lr)
497 {
498     T1 = regs->lr;
499 }
500
501 /* tests with result in T0 */
502
503 PPC_OP(test_ctr)
504 {
505     T0 = regs->ctr;
506 }
507
508 PPC_OP(test_ctr_true)
509 {
510     T0 = (regs->ctr != 0 && (T0 & PARAM(1)) != 0);
511 }
512
513 PPC_OP(test_ctr_false)
514 {
515     T0 = (regs->ctr != 0 && (T0 & PARAM(1)) == 0);
516 }
517
518 PPC_OP(test_ctrz)
519 {
520     T0 = (regs->ctr == 0);
521 }
522
523 PPC_OP(test_ctrz_true)
524 {
525     T0 = (regs->ctr == 0 && (T0 & PARAM(1)) != 0);
526 }
527
528 PPC_OP(test_ctrz_false)
529 {
530     T0 = (regs->ctr == 0 && (T0 & PARAM(1)) == 0);
531 }
532
533 PPC_OP(test_true)
534 {
535     T0 = (T0 & PARAM(1));
536 }
537
538 PPC_OP(test_false)
539 {
540     T0 = ((T0 & PARAM(1)) == 0);
541 }
542
543 /* CTR maintenance */
544 PPC_OP(dec_ctr)
545 {
546     regs->ctr--;
547     RETURN();
548 }
549
550 /***                           Integer arithmetic                          ***/
551 /* add */
552 PPC_OP(add)
553 {
554     T0 += T1;
555     RETURN();
556 }
557
558 void do_addo (void);
559 void op_addo (void)
560 {
561     do_addo();
562     RETURN();
563 }
564
565 /* add carrying */
566 PPC_OP(addc)
567 {
568     T2 = T0;
569     T0 += T1;
570     if (T0 < T2) {
571         xer_ca = 1;
572     } else {
573         xer_ca = 0;
574     }
575     RETURN();
576 }
577
578 void do_addco (void);
579 void op_addco (void)
580 {
581     do_addco();
582     RETURN();
583 }
584
585 /* add extended */
586 void do_adde (void);
587 void op_adde (void)
588 {
589     do_adde();
590 }
591
592 void do_addeo (void);
593 PPC_OP(addeo)
594 {
595     do_addeo();
596     RETURN();
597 }
598
599 /* add immediate */
600 PPC_OP(addi)
601 {
602     T0 += PARAM(1);
603     RETURN();
604 }
605
606 /* add immediate carrying */
607 PPC_OP(addic)
608 {
609     T1 = T0;
610     T0 += PARAM(1);
611     if (T0 < T1) {
612         xer_ca = 1;
613     } else {
614         xer_ca = 0;
615     }
616     RETURN();
617 }
618
619 /* add to minus one extended */
620 PPC_OP(addme)
621 {
622     T1 = T0;
623     T0 += xer_ca + (-1);
624     if (T1 != 0)
625         xer_ca = 1;
626     RETURN();
627 }
628
629 void do_addmeo (void);
630 void op_addmeo (void)
631 {
632     do_addmeo();
633     RETURN();
634 }
635
636 /* add to zero extended */
637 PPC_OP(addze)
638 {
639     T1 = T0;
640     T0 += xer_ca;
641     if (T0 < T1) {
642         xer_ca = 1;
643     } else {
644         xer_ca = 0;
645     }
646     RETURN();
647 }
648
649 void do_addzeo (void);
650 void op_addzeo (void)
651 {
652     do_addzeo();
653     RETURN();
654 }
655
656 /* divide word */
657 PPC_OP(divw)
658 {
659     if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
660         T0 = (int32_t)((-1) * (T0 >> 31));
661     } else {
662         T0 = (Ts0 / Ts1);
663     }
664     RETURN();
665 }
666
667 void do_divwo (void);
668 void op_divwo (void)
669 {
670     do_divwo();
671     RETURN();
672 }
673
674 /* divide word unsigned */
675 PPC_OP(divwu)
676 {
677     if (T1 == 0) {
678         T0 = 0;
679     } else {
680         T0 /= T1;
681     }
682     RETURN();
683 }
684
685 void do_divwuo (void);
686 void op_divwuo (void)
687 {
688     do_divwuo();
689     RETURN();
690 }
691
692 /* multiply high word */
693 PPC_OP(mulhw)
694 {
695     T0 = ((int64_t)Ts0 * (int64_t)Ts1) >> 32;
696     RETURN();
697 }
698
699 /* multiply high word unsigned */
700 PPC_OP(mulhwu)
701 {
702     T0 = ((uint64_t)T0 * (uint64_t)T1) >> 32;
703     RETURN();
704 }
705
706 /* multiply low immediate */
707 PPC_OP(mulli)
708 {
709     T0 = (Ts0 * SPARAM(1));
710     RETURN();
711 }
712
713 /* multiply low word */
714 PPC_OP(mullw)
715 {
716     T0 *= T1;
717     RETURN();
718 }
719
720 void do_mullwo (void);
721 void op_mullwo (void)
722 {
723     do_mullwo();
724     RETURN();
725 }
726
727 /* negate */
728 PPC_OP(neg)
729 {
730     if (T0 != 0x80000000) {
731         T0 = -Ts0;
732     }
733     RETURN();
734 }
735
736 void do_nego (void);
737 void op_nego (void)
738 {
739     do_nego();
740     RETURN();
741 }
742
743 /* substract from */
744 PPC_OP(subf)
745 {
746     T0 = T1 - T0;
747     RETURN();
748 }
749
750 void do_subfo (void);
751 void op_subfo (void)
752 {
753     do_subfo();
754     RETURN();
755 }
756
757 /* substract from carrying */
758 PPC_OP(subfc)
759 {
760     T0 = T1 - T0;
761     if (T0 <= T1) {
762         xer_ca = 1;
763     } else {
764         xer_ca = 0;
765     }
766     RETURN();
767 }
768
769 void do_subfco (void);
770 void op_subfco (void)
771 {
772     do_subfco();
773     RETURN();
774 }
775
776 /* substract from extended */
777 void do_subfe (void);
778 void op_subfe (void)
779 {
780     do_subfe();
781     RETURN();
782 }
783
784 void do_subfeo (void);
785 PPC_OP(subfeo)
786 {
787     do_subfeo();
788     RETURN();
789 }
790
791 /* substract from immediate carrying */
792 PPC_OP(subfic)
793 {
794     T0 = PARAM(1) + ~T0 + 1;
795     if (T0 <= PARAM(1)) {
796         xer_ca = 1;
797     } else {
798         xer_ca = 0;
799     }
800     RETURN();
801 }
802
803 /* substract from minus one extended */
804 PPC_OP(subfme)
805 {
806     T0 = ~T0 + xer_ca - 1;
807
808     if (T0 != -1)
809         xer_ca = 1;
810     RETURN();
811 }
812
813 void do_subfmeo (void);
814 void op_subfmeo (void)
815 {
816     do_subfmeo();
817     RETURN();
818 }
819
820 /* substract from zero extended */
821 PPC_OP(subfze)
822 {
823     T1 = ~T0;
824     T0 = T1 + xer_ca;
825     if (T0 < T1) {
826         xer_ca = 1;
827     } else {
828         xer_ca = 0;
829     }
830     RETURN();
831 }
832
833 void do_subfzeo (void);
834 void op_subfzeo (void)
835 {
836     do_subfzeo();
837     RETURN();
838 }
839
840 /***                           Integer comparison                          ***/
841 /* compare */
842 PPC_OP(cmp)
843 {
844     if (Ts0 < Ts1) {
845         T0 = 0x08;
846     } else if (Ts0 > Ts1) {
847         T0 = 0x04;
848     } else {
849         T0 = 0x02;
850     }
851     RETURN();
852 }
853
854 /* compare immediate */
855 PPC_OP(cmpi)
856 {
857     if (Ts0 < SPARAM(1)) {
858         T0 = 0x08;
859     } else if (Ts0 > SPARAM(1)) {
860         T0 = 0x04;
861     } else {
862         T0 = 0x02;
863     }
864     RETURN();
865 }
866
867 /* compare logical */
868 PPC_OP(cmpl)
869 {
870     if (T0 < T1) {
871         T0 = 0x08;
872     } else if (T0 > T1) {
873         T0 = 0x04;
874     } else {
875         T0 = 0x02;
876     }
877     RETURN();
878 }
879
880 /* compare logical immediate */
881 PPC_OP(cmpli)
882 {
883     if (T0 < PARAM(1)) {
884         T0 = 0x08;
885     } else if (T0 > PARAM(1)) {
886         T0 = 0x04;
887     } else {
888         T0 = 0x02;
889     }
890     RETURN();
891 }
892
893 /***                            Integer logical                            ***/
894 /* and */
895 PPC_OP(and)
896 {
897     T0 &= T1;
898     RETURN();
899 }
900
901 /* andc */
902 PPC_OP(andc)
903 {
904     T0 &= ~T1;
905     RETURN();
906 }
907
908 /* andi. */
909 PPC_OP(andi_)
910 {
911     T0 &= PARAM(1);
912     RETURN();
913 }
914
915 /* count leading zero */
916 PPC_OP(cntlzw)
917 {
918     T1 = T0;
919     for (T0 = 32; T1 > 0; T0--)
920         T1 = T1 >> 1;
921     RETURN();
922 }
923
924 /* eqv */
925 PPC_OP(eqv)
926 {
927     T0 = ~(T0 ^ T1);
928     RETURN();
929 }
930
931 /* extend sign byte */
932 PPC_OP(extsb)
933 {
934     T0 = (int32_t)((int8_t)(Ts0));
935     RETURN();
936 }
937
938 /* extend sign half word */
939 PPC_OP(extsh)
940 {
941     T0 = (int32_t)((int16_t)(Ts0));
942     RETURN();
943 }
944
945 /* nand */
946 PPC_OP(nand)
947 {
948     T0 = ~(T0 & T1);
949     RETURN();
950 }
951
952 /* nor */
953 PPC_OP(nor)
954 {
955     T0 = ~(T0 | T1);
956     RETURN();
957 }
958
959 /* or */
960 PPC_OP(or)
961 {
962     T0 |= T1;
963     RETURN();
964 }
965
966 /* orc */
967 PPC_OP(orc)
968 {
969     T0 |= ~T1;
970     RETURN();
971 }
972
973 /* ori */
974 PPC_OP(ori)
975 {
976     T0 |= PARAM(1);
977     RETURN();
978 }
979
980 /* xor */
981 PPC_OP(xor)
982 {
983     T0 ^= T1;
984     RETURN();
985 }
986
987 /* xori */
988 PPC_OP(xori)
989 {
990     T0 ^= PARAM(1);
991     RETURN();
992 }
993
994 /***                             Integer rotate                            ***/
995 /* rotate left word immediate then mask insert */
996 PPC_OP(rlwimi)
997 {
998     T0 = (rotl(T0, PARAM(1)) & PARAM(2)) | (T1 & PARAM(3));
999     RETURN();
1000 }
1001
1002 /* rotate left immediate then and with mask insert */
1003 PPC_OP(rotlwi)
1004 {
1005     T0 = rotl(T0, PARAM(1));
1006     RETURN();
1007 }
1008
1009 PPC_OP(slwi)
1010 {
1011     T0 = T0 << PARAM(1);
1012     RETURN();
1013 }
1014
1015 PPC_OP(srwi)
1016 {
1017     T0 = T0 >> PARAM(1);
1018     RETURN();
1019 }
1020
1021 /* rotate left word then and with mask insert */
1022 PPC_OP(rlwinm)
1023 {
1024     T0 = rotl(T0, PARAM(1)) & PARAM(2);
1025     RETURN();
1026 }
1027
1028 PPC_OP(rotl)
1029 {
1030     T0 = rotl(T0, T1);
1031     RETURN();
1032 }
1033
1034 PPC_OP(rlwnm)
1035 {
1036     T0 = rotl(T0, T1) & PARAM(1);
1037     RETURN();
1038 }
1039
1040 /***                             Integer shift                             ***/
1041 /* shift left word */
1042 PPC_OP(slw)
1043 {
1044     if (T1 & 0x20) {
1045         T0 = 0;
1046     } else {
1047         T0 = T0 << T1;
1048     }
1049     RETURN();
1050 }
1051
1052 /* shift right algebraic word */
1053 void op_sraw (void)
1054 {
1055     do_sraw();
1056     RETURN();
1057 }
1058
1059 /* shift right algebraic word immediate */
1060 PPC_OP(srawi)
1061 {
1062     T1 = T0;
1063     T0 = (Ts0 >> PARAM(1));
1064     if (Ts1 < 0 && (Ts1 & PARAM(2)) != 0) {
1065         xer_ca = 1;
1066     } else {
1067         xer_ca = 0;
1068     }
1069     RETURN();
1070 }
1071
1072 /* shift right word */
1073 PPC_OP(srw)
1074 {
1075     if (T1 & 0x20) {
1076         T0 = 0;
1077     } else {
1078         T0 = T0 >> T1;
1079     }
1080     RETURN();
1081 }
1082
1083 /***                       Floating-Point arithmetic                       ***/
1084 /* fadd - fadd. */
1085 PPC_OP(fadd)
1086 {
1087     FT0 += FT1;
1088     RETURN();
1089 }
1090
1091 /* fsub - fsub. */
1092 PPC_OP(fsub)
1093 {
1094     FT0 -= FT1;
1095     RETURN();
1096 }
1097
1098 /* fmul - fmul. */
1099 PPC_OP(fmul)
1100 {
1101     FT0 *= FT1;
1102     RETURN();
1103 }
1104
1105 /* fdiv - fdiv. */
1106 PPC_OP(fdiv)
1107 {
1108     FT0 = float64_div(FT0, FT1, &env->fp_status);
1109     RETURN();
1110 }
1111
1112 /* fsqrt - fsqrt. */
1113 PPC_OP(fsqrt)
1114 {
1115     do_fsqrt();
1116     RETURN();
1117 }
1118
1119 /* fres - fres. */
1120 PPC_OP(fres)
1121 {
1122     do_fres();
1123     RETURN();
1124 }
1125
1126 /* frsqrte  - frsqrte. */
1127 PPC_OP(frsqrte)
1128 {
1129     do_frsqrte();
1130     RETURN();
1131 }
1132
1133 /* fsel - fsel. */
1134 PPC_OP(fsel)
1135 {
1136     do_fsel();
1137     RETURN();
1138 }
1139
1140 /***                     Floating-Point multiply-and-add                   ***/
1141 /* fmadd - fmadd. */
1142 PPC_OP(fmadd)
1143 {
1144     FT0 = (FT0 * FT1) + FT2;
1145     RETURN();
1146 }
1147
1148 /* fmsub - fmsub. */
1149 PPC_OP(fmsub)
1150 {
1151     FT0 = (FT0 * FT1) - FT2;
1152     RETURN();
1153 }
1154
1155 /* fnmadd - fnmadd. - fnmadds - fnmadds. */
1156 PPC_OP(fnmadd)
1157 {
1158     do_fnmadd();
1159     RETURN();
1160 }
1161
1162 /* fnmsub - fnmsub. */
1163 PPC_OP(fnmsub)
1164 {
1165     do_fnmsub();
1166     RETURN();
1167 }
1168
1169 /***                     Floating-Point round & convert                    ***/
1170 /* frsp - frsp. */
1171 PPC_OP(frsp)
1172 {
1173     FT0 = (float)FT0;
1174     RETURN();
1175 }
1176
1177 /* fctiw - fctiw. */
1178 PPC_OP(fctiw)
1179 {
1180     do_fctiw();
1181     RETURN();
1182 }
1183
1184 /* fctiwz - fctiwz. */
1185 PPC_OP(fctiwz)
1186 {
1187     do_fctiwz();
1188     RETURN();
1189 }
1190
1191
1192 /***                         Floating-Point compare                        ***/
1193 /* fcmpu */
1194 PPC_OP(fcmpu)
1195 {
1196     do_fcmpu();
1197     RETURN();
1198 }
1199
1200 /* fcmpo */
1201 PPC_OP(fcmpo)
1202 {
1203     do_fcmpo();
1204     RETURN();
1205 }
1206
1207 /***                         Floating-point move                           ***/
1208 /* fabs */
1209 PPC_OP(fabs)
1210 {
1211     FT0 = float64_abs(FT0);
1212     RETURN();
1213 }
1214
1215 /* fnabs */
1216 PPC_OP(fnabs)
1217 {
1218     FT0 = float64_abs(FT0);
1219     FT0 = float64_chs(FT0);
1220     RETURN();
1221 }
1222
1223 /* fneg */
1224 PPC_OP(fneg)
1225 {
1226     FT0 = float64_chs(FT0);
1227     RETURN();
1228 }
1229
1230 /* Load and store */
1231 #define MEMSUFFIX _raw
1232 #include "op_mem.h"
1233 #if !defined(CONFIG_USER_ONLY)
1234 #define MEMSUFFIX _user
1235 #include "op_mem.h"
1236
1237 #define MEMSUFFIX _kernel
1238 #include "op_mem.h"
1239 #endif
1240
1241 /* Special op to check and maybe clear reservation */
1242 PPC_OP(check_reservation)
1243 {
1244     if ((uint32_t)env->reserve == (uint32_t)(T0 & ~0x00000003))
1245         env->reserve = -1;
1246     RETURN();
1247 }
1248
1249 /* Return from interrupt */
1250 void do_rfi (void);
1251 void op_rfi (void)
1252 {
1253     do_rfi();
1254     RETURN();
1255 }
1256
1257 /* Trap word */
1258 void do_tw (uint32_t cmp, int flags);
1259 void op_tw (void)
1260 {
1261     do_tw(T1, PARAM(1));
1262     RETURN();
1263 }
1264
1265 void op_twi (void)
1266 {
1267     do_tw(PARAM(1), PARAM(2));
1268     RETURN();
1269 }
1270
1271 /* Instruction cache block invalidate */
1272 PPC_OP(icbi)
1273 {
1274     do_icbi();
1275     RETURN();
1276 }
1277
1278 /* tlbia */
1279 PPC_OP(tlbia)
1280 {
1281     do_tlbia();
1282     RETURN();
1283 }
1284
1285 /* tlbie */
1286 PPC_OP(tlbie)
1287 {
1288     do_tlbie();
1289     RETURN();
1290 }
1291
1292 void op_store_pir (void)
1293 {
1294     env->spr[SPR_PIR] = T0 & 0x0000000FUL;
1295     RETURN();
1296 }