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