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