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