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