]> git.proxmox.com Git - qemu.git/blob - target-ppc/op.c
FRSP fix (Jocelyn Mayer)
[qemu.git] / 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 FTS0 = FT0;
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 }