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