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