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