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