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