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