PowerPC fixes (Jocelyn Mayer)
[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 regs (env)
25 #define Ts0 (int32_t)T0
26 #define Ts1 (int32_t)T1
27 #define Ts2 (int32_t)T2
28
29 #define FT0 (env->ft0)
30 #define FT1 (env->ft1)
31 #define FT2 (env->ft2)
32
33 #define FTS0 ((float)env->ft0)
34 #define FTS1 ((float)env->ft1)
35 #define FTS2 ((float)env->ft2)
36
37 #define PPC_OP(name) void op_##name(void)
38
39 #define REG 0
40 #include "op_template.h"
41
42 #define REG 1
43 #include "op_template.h"
44
45 #define REG 2
46 #include "op_template.h"
47
48 #define REG 3
49 #include "op_template.h"
50
51 #define REG 4
52 #include "op_template.h"
53
54 #define REG 5
55 #include "op_template.h"
56
57 #define REG 6
58 #include "op_template.h"
59
60 #define REG 7
61 #include "op_template.h"
62
63 #define REG 8
64 #include "op_template.h"
65
66 #define REG 9
67 #include "op_template.h"
68
69 #define REG 10
70 #include "op_template.h"
71
72 #define REG 11
73 #include "op_template.h"
74
75 #define REG 12
76 #include "op_template.h"
77
78 #define REG 13
79 #include "op_template.h"
80
81 #define REG 14
82 #include "op_template.h"
83
84 #define REG 15
85 #include "op_template.h"
86
87 #define REG 16
88 #include "op_template.h"
89
90 #define REG 17
91 #include "op_template.h"
92
93 #define REG 18
94 #include "op_template.h"
95
96 #define REG 19
97 #include "op_template.h"
98
99 #define REG 20
100 #include "op_template.h"
101
102 #define REG 21
103 #include "op_template.h"
104
105 #define REG 22
106 #include "op_template.h"
107
108 #define REG 23
109 #include "op_template.h"
110
111 #define REG 24
112 #include "op_template.h"
113
114 #define REG 25
115 #include "op_template.h"
116
117 #define REG 26
118 #include "op_template.h"
119
120 #define REG 27
121 #include "op_template.h"
122
123 #define REG 28
124 #include "op_template.h"
125
126 #define REG 29
127 #include "op_template.h"
128
129 #define REG 30
130 #include "op_template.h"
131
132 #define REG 31
133 #include "op_template.h"
134
135 /* PPC state maintenance operations */
136 /* set_Rc0 */
137 PPC_OP(set_Rc0)
138 {
139     uint32_t tmp;
140
141     if (Ts0 < 0) {
142         tmp = 0x08;
143     } else if (Ts0 > 0) {
144         tmp = 0x04;
145     } else {
146         tmp = 0x02;
147     }
148     set_CRn(0, tmp);
149     RETURN();
150 }
151
152 PPC_OP(set_Rc0_ov)
153 {
154     uint32_t tmp;
155
156     if (Ts0 < 0) {
157         tmp = 0x08;
158     } else if (Ts0 > 0) {
159         tmp = 0x04;
160     } else {
161         tmp = 0x02;
162     }
163     tmp |= xer_ov;
164     set_CRn(0, tmp);
165     RETURN();
166 }
167
168 /* reset_Rc0 */
169 PPC_OP(reset_Rc0)
170 {
171     set_CRn(0, 0x02 | xer_ov);
172     RETURN();
173 }
174
175 /* set_Rc0_1 */
176 PPC_OP(set_Rc0_1)
177 {
178     set_CRn(0, 0x04 | xer_ov);
179     RETURN();
180 }
181
182 /* Set Rc1 (for floating point arithmetic) */
183 PPC_OP(set_Rc1)
184 {
185     env->crf[1] = regs->fpscr[7];
186     RETURN();
187 }
188
189 PPC_OP(set_T0)
190 {
191     T0 = PARAM(1);
192     RETURN();
193 }
194
195 PPC_OP(set_T1)
196 {
197     T1 = PARAM(1);
198     RETURN();
199 }
200
201 PPC_OP(set_T2)
202 {
203     T2 = PARAM(1);
204     RETURN();
205 }
206
207 /* Update time base */
208 PPC_OP(update_tb)
209 {
210     T0 = regs->spr[SPR_ENCODE(268)];
211     T1 = T0;
212     T0 += PARAM(1);
213     if (T0 < T1) {
214         T1 = regs->spr[SPR_ENCODE(269)] + 1;
215         regs->spr[SPR_ENCODE(269)] = T1;
216     }
217     regs->spr[SPR_ENCODE(268)] = T0;
218     RETURN();
219 }
220
221 PPC_OP(raise_exception)
222 {
223     raise_exception(PARAM(1));
224     RETURN();
225 }
226
227 PPC_OP(exit_tb)
228 {
229     EXIT_TB();
230 }
231
232 PPC_OP(load_cr)
233 {
234     T0 = do_load_cr();
235     RETURN();
236 }
237
238 PPC_OP(store_cr)
239 {
240     do_store_cr(PARAM(1), T0);
241     RETURN();
242 }
243
244 PPC_OP(load_xer_cr)
245 {
246     T0 = (xer_so << 3) | (xer_ov << 2) | (xer_ca << 1);
247     RETURN();
248 }
249
250 PPC_OP(clear_xer_cr)
251 {
252     xer_so = 0;
253     xer_ov = 0;
254     xer_ca = 0;
255     RETURN();
256 }
257
258 PPC_OP(load_xer_bc)
259 {
260     T0 = xer_bc;
261     RETURN();
262 }
263
264 PPC_OP(load_xer)
265 {
266     T0 = do_load_xer();
267     RETURN();
268 }
269
270 PPC_OP(store_xer)
271 {
272     do_store_xer(T0);
273     RETURN();
274 }
275
276 PPC_OP(load_msr)
277 {
278     T0 = do_load_msr();
279     RETURN();
280 }
281
282 PPC_OP(store_msr)
283 {
284     do_store_msr(T0);
285     RETURN();
286 }
287
288 PPC_OP(load_lr)
289 {
290     regs->LR = PARAM(1);
291     RETURN();
292 }
293
294 /* FPSCR */
295 PPC_OP(load_fpscr)
296 {
297     do_load_fpscr();
298     RETURN();
299 }
300
301 PPC_OP(store_fpscr)
302 {
303     do_store_fpscr(PARAM(1));
304     RETURN();
305 }
306
307 PPC_OP(reset_scrfx)
308 {
309     regs->fpscr[7] &= ~0x8;
310     RETURN();
311 }
312
313 /* Set reservation */
314 PPC_OP(set_reservation)
315 {
316     regs->reserve = T1 & ~0x03;
317     RETURN();
318 }
319
320 /* Reset reservation */
321 PPC_OP(reset_reservation)
322 {
323     regs->reserve = 0;
324     RETURN();
325 }
326
327 /* crf operations */
328 PPC_OP(getbit_T0)
329 {
330     T0 = (T0 >> PARAM(1)) & 1;
331     RETURN();
332 }
333
334 PPC_OP(getbit_T1)
335 {
336     T1 = (T1 >> PARAM(1)) & 1;
337     RETURN();
338 }
339
340 PPC_OP(setcrfbit)
341 {
342     T1 = (T1 & PARAM(1)) | (T0 << PARAM(2)); 
343     RETURN();
344 }
345
346 /* Branch */
347 #define __PPC_OP_B(name, target)                                              \
348 PPC_OP(name)                                                                  \
349 {                                                                             \
350     regs->nip = (target);                                                     \
351     RETURN();                                                                 \
352 }
353
354 #define __PPC_OP_BL(name, target)                                             \
355 PPC_OP(name)                                                                  \
356 {                                                                             \
357     regs->LR = PARAM(1);                                                      \
358     regs->nip = (target);                                                     \
359     RETURN();                                                                 \
360 }
361
362 #define PPC_OP_B(name, target)                                                \
363 __PPC_OP_B(name, target);                                                     \
364 __PPC_OP_BL(name##l, target)
365
366 #define __PPC_OP_BC(name, cond, target)                                       \
367 PPC_OP(name)                                                                  \
368 {                                                                             \
369     if (cond) {                                                               \
370         T0 = (target);                                                        \
371     } else {                                                                  \
372         T0 = PARAM(1);                                                        \
373     }                                                                         \
374     regs->nip = T0;                                                           \
375     RETURN();                                                                 \
376 }
377
378 #define __PPC_OP_BCL(name, cond, target)                                      \
379 PPC_OP(name)                                                                  \
380 {                                                                             \
381     if (cond) {                                                               \
382         T0 = (target);                                                        \
383         regs->LR = PARAM(1);                                                  \
384     } else {                                                                  \
385         T0 = PARAM(1);                                                        \
386     }                                                                         \
387     regs->nip = T0;                                                           \
388     RETURN();                                                                 \
389 }
390
391 #define _PPC_OP_BC(name, namel, cond, target)                                 \
392 __PPC_OP_BC(name, cond, target);                                              \
393 __PPC_OP_BCL(namel, cond, target)
394
395 /* Branch to target */
396 #define PPC_OP_BC(name, cond)                                                 \
397 _PPC_OP_BC(b_##name, bl_##name, cond, PARAM(2))
398
399 PPC_OP_B(b, PARAM(1));
400 PPC_OP_BC(ctr,        (regs->CTR != 0));
401 PPC_OP_BC(ctr_true,   (regs->CTR != 0 && (T0 & PARAM(3)) != 0));
402 PPC_OP_BC(ctr_false,  (regs->CTR != 0 && (T0 & PARAM(3)) == 0));
403 PPC_OP_BC(ctrz,       (regs->CTR == 0));
404 PPC_OP_BC(ctrz_true,  (regs->CTR == 0 && (T0 & PARAM(3)) != 0));
405 PPC_OP_BC(ctrz_false, (regs->CTR == 0 && (T0 & PARAM(3)) == 0));
406 PPC_OP_BC(true,       ((T0 & PARAM(3)) != 0));
407 PPC_OP_BC(false,      ((T0 & PARAM(3)) == 0));
408
409 /* Branch to CTR */
410 #define PPC_OP_BCCTR(name, cond)                                              \
411 _PPC_OP_BC(bctr_##name, bctrl_##name, cond, regs->CTR & ~0x03)
412
413 PPC_OP_B(bctr, regs->CTR & ~0x03);
414 PPC_OP_BCCTR(ctr,        (regs->CTR != 0));
415 PPC_OP_BCCTR(ctr_true,   (regs->CTR != 0 && (T0 & PARAM(2)) != 0));
416 PPC_OP_BCCTR(ctr_false,  (regs->CTR != 0 && (T0 & PARAM(2)) == 0));
417 PPC_OP_BCCTR(ctrz,       (regs->CTR == 0));
418 PPC_OP_BCCTR(ctrz_true,  (regs->CTR == 0 && (T0 & PARAM(2)) != 0));
419 PPC_OP_BCCTR(ctrz_false, (regs->CTR == 0 && (T0 & PARAM(2)) == 0));
420 PPC_OP_BCCTR(true,       ((T0 & PARAM(2)) != 0));
421 PPC_OP_BCCTR(false,      ((T0 & PARAM(2)) == 0));
422
423 /* Branch to LR */
424 #define PPC_OP_BCLR(name, cond)                                               \
425 _PPC_OP_BC(blr_##name, blrl_##name, cond, regs->LR & ~0x03)
426
427 PPC_OP_B(blr, regs->LR & ~0x03);
428 PPC_OP_BCLR(ctr,        (regs->CTR != 0));
429 PPC_OP_BCLR(ctr_true,   (regs->CTR != 0 && (T0 & PARAM(2)) != 0));
430 PPC_OP_BCLR(ctr_false,  (regs->CTR != 0 && (T0 & PARAM(2)) == 0));
431 PPC_OP_BCLR(ctrz,       (regs->CTR == 0));
432 PPC_OP_BCLR(ctrz_true,  (regs->CTR == 0 && (T0 & PARAM(2)) != 0));
433 PPC_OP_BCLR(ctrz_false, (regs->CTR == 0 && (T0 & PARAM(2)) == 0));
434 PPC_OP_BCLR(true,       ((T0 & PARAM(2)) != 0));
435 PPC_OP_BCLR(false,      ((T0 & PARAM(2)) == 0));
436
437 /* CTR maintenance */
438 PPC_OP(dec_ctr)
439 {
440     regs->CTR--;
441     RETURN();
442 }
443
444 /***                           Integer arithmetic                          ***/
445 /* add */
446 PPC_OP(add)
447 {
448     T0 += T1;
449     RETURN();
450 }
451
452 PPC_OP(addo)
453 {
454     T2 = T0;
455     T0 += T1;
456     if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
457         xer_so = 1;
458         xer_ov = 1;
459     } else {
460         xer_ov = 0;
461     }
462     RETURN();
463 }
464
465 /* add carrying */
466 PPC_OP(addc)
467 {
468     T2 = T0;
469     T0 += T1;
470     if (T0 < T2) {
471         xer_ca = 1;
472     } else {
473         xer_ca = 0;
474     }
475     RETURN();
476 }
477
478 PPC_OP(addco)
479 {
480     T2 = T0;
481     T0 += T1;
482     if (T0 < T2) {
483         xer_ca = 1;
484     } else {
485         xer_ca = 0;
486     }
487     if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
488         xer_so = 1;
489         xer_ov = 1;
490     } else {
491         xer_ov = 0;
492     }
493     RETURN();
494 }
495
496 /* add extended */
497 /* candidate for helper (too long) */
498 PPC_OP(adde)
499 {
500     T2 = T0;
501     T0 += T1 + xer_ca;
502     if (T0 < T2 || (xer_ca == 1 && T0 == T2)) {
503         xer_ca = 1;
504     } else {
505         xer_ca = 0;
506     }
507     RETURN();
508 }
509
510 PPC_OP(addeo)
511 {
512     T2 = T0;
513     T0 += T1 + xer_ca;
514     if (T0 < T2 || (xer_ca == 1 && T0 == T2)) {
515         xer_ca = 1;
516     } else {
517         xer_ca = 0;
518     }
519     if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
520         xer_so = 1;
521         xer_ov = 1;
522     } else {
523         xer_ov = 0;
524     }
525     RETURN();
526 }
527
528 /* add immediate */
529 PPC_OP(addi)
530 {
531     T0 += PARAM(1);
532     RETURN();
533 }
534
535 /* add immediate carrying */
536 PPC_OP(addic)
537 {
538     T1 = T0;
539     T0 += PARAM(1);
540     if (T0 < T1) {
541         xer_ca = 1;
542     } else {
543         xer_ca = 0;
544     }
545     RETURN();
546 }
547
548 /* add to minus one extended */
549 PPC_OP(addme)
550 {
551     T1 = T0;
552     T0 += xer_ca + (-1);
553     if (T1 != 0)
554         xer_ca = 1;
555     RETURN();
556 }
557
558 PPC_OP(addmeo)
559 {
560     T1 = T0;
561     T0 += xer_ca + (-1);
562     if (T1 & (T1 ^ T0) & (1 << 31)) {
563         xer_so = 1;
564         xer_ov = 1;
565     } else {
566         xer_ov = 0;
567     }
568     if (T1 != 0)
569         xer_ca = 1;
570     RETURN();
571 }
572
573 /* add to zero extended */
574 PPC_OP(addze)
575 {
576     T1 = T0;
577     T0 += xer_ca;
578     if (T0 < T1) {
579         xer_ca = 1;
580     } else {
581         xer_ca = 0;
582     }
583     RETURN();
584 }
585
586 PPC_OP(addzeo)
587 {
588     T1 = T0;
589     T0 += xer_ca;
590     if ((T1 ^ (-1)) & (T1 ^ T0) & (1 << 31)) {
591         xer_so = 1;
592         xer_ov = 1;
593     } else {
594         xer_ov = 0;
595     }
596     if (T0 < T1) {
597         xer_ca = 1;
598     } else {
599         xer_ca = 0;
600     }
601     RETURN();
602 }
603
604 /* divide word */
605 /* candidate for helper (too long) */
606 PPC_OP(divw)
607 {
608     if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
609         Ts0 = (-1) * (T0 >> 31);
610     } else {
611         Ts0 /= Ts1;
612     }
613     RETURN();
614 }
615
616 PPC_OP(divwo)
617 {
618     if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
619         xer_so = 1;
620         xer_ov = 1;
621         T0 = (-1) * (T0 >> 31);
622     } else {
623         xer_ov = 0;
624         Ts0 /= Ts1;
625     }
626     RETURN();
627 }
628
629 /* divide word unsigned */
630 PPC_OP(divwu)
631 {
632     if (T1 == 0) {
633         T0 = 0;
634     } else {
635         T0 /= T1;
636     }
637     RETURN();
638 }
639
640 PPC_OP(divwuo)
641 {
642     if (T1 == 0) {
643         xer_so = 1;
644         xer_ov = 1;
645         T0 = 0;
646     } else {
647         xer_ov = 0;
648         T0 /= T1;
649     }
650     RETURN();
651 }
652
653 /* multiply high word */
654 PPC_OP(mulhw)
655 {
656     Ts0 = ((int64_t)Ts0 * (int64_t)Ts1) >> 32;
657     RETURN();
658 }
659
660 /* multiply high word unsigned */
661 PPC_OP(mulhwu)
662 {
663     T0 = ((uint64_t)T0 * (uint64_t)T1) >> 32;
664     RETURN();
665 }
666
667 /* multiply low immediate */
668 PPC_OP(mulli)
669 {
670     Ts0 *= SPARAM(1);
671     RETURN();
672 }
673
674 /* multiply low word */
675 PPC_OP(mullw)
676 {
677     T0 *= T1;
678     RETURN();
679 }
680
681 PPC_OP(mullwo)
682 {
683     int64_t res = (int64_t)Ts0 * (int64_t)Ts1;
684
685     if ((int32_t)res != res) {
686         xer_ov = 1;
687         xer_so = 1;
688     } else {
689         xer_ov = 0;
690     }
691     Ts0 = res;
692     RETURN();
693 }
694
695 /* negate */
696 PPC_OP(neg)
697 {
698     if (T0 != 0x80000000) {
699         Ts0 = -Ts0;
700     }
701     RETURN();
702 }
703
704 PPC_OP(nego)
705 {
706     if (T0 == 0x80000000) {
707         xer_ov = 1;
708         xer_so = 1;
709     } else {
710         xer_ov = 0;
711         Ts0 = -Ts0;
712     }
713     RETURN();
714 }
715
716 /* substract from */
717 PPC_OP(subf)
718 {
719     T0 = T1 - T0;
720     RETURN();
721 }
722
723 PPC_OP(subfo)
724 {
725     T2 = T0;
726     T0 = T1 - T0;
727     if (((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)) {
728         xer_so = 1;
729         xer_ov = 1;
730     } else {
731         xer_ov = 0;
732     }
733     RETURN();
734 }
735
736 /* substract from carrying */
737 PPC_OP(subfc)
738 {
739     T0 = T1 - T0;
740     if (T0 <= T1) {
741         xer_ca = 1;
742     } else {
743         xer_ca = 0;
744     }
745     RETURN();
746 }
747
748 PPC_OP(subfco)
749 {
750     T2 = T0;
751     T0 = T1 - T0;
752     if (T0 <= T1) {
753         xer_ca = 1;
754     } else {
755         xer_ca = 0;
756     }
757     if (((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)) {
758         xer_so = 1;
759         xer_ov = 1;
760     } else {
761         xer_ov = 0;
762     }
763     RETURN();
764 }
765
766 /* substract from extended */
767 /* candidate for helper (too long) */
768 PPC_OP(subfe)
769 {
770     T0 = T1 + ~T0 + xer_ca;
771     if (T0 < T1 || (xer_ca == 1 && T0 == T1)) {
772         xer_ca = 1;
773     } else {
774         xer_ca = 0;
775     }
776     RETURN();
777 }
778
779 PPC_OP(subfeo)
780 {
781     T2 = T0;
782     T0 = T1 + ~T0 + xer_ca;
783     if ((~T2 ^ T1 ^ (-1)) & (~T2 ^ T0) & (1 << 31)) {
784         xer_so = 1;
785         xer_ov = 1;
786     } else {
787         xer_ov = 0;
788     }
789     if (T0 < T1 || (xer_ca == 1 && T0 == T1)) {
790         xer_ca = 1;
791     } else {
792         xer_ca = 0;
793     }
794     RETURN();
795 }
796
797 /* substract from immediate carrying */
798 PPC_OP(subfic)
799 {
800     T0 = PARAM(1) + ~T0 + 1;
801     if (T0 <= PARAM(1)) {
802         xer_ca = 1;
803     } else {
804         xer_ca = 0;
805     }
806     RETURN();
807 }
808
809 /* substract from minus one extended */
810 PPC_OP(subfme)
811 {
812     T0 = ~T0 + xer_ca - 1;
813
814     if (T0 != -1)
815         xer_ca = 1;
816     RETURN();
817 }
818
819 PPC_OP(subfmeo)
820 {
821     T1 = T0;
822     T0 = ~T0 + xer_ca - 1;
823     if (~T1 & (~T1 ^ T0) & (1 << 31)) {
824         xer_so = 1;
825         xer_ov = 1;
826     } else {
827         xer_ov = 0;
828     }
829     if (T1 != -1)
830         xer_ca = 1;
831     RETURN();
832 }
833
834 /* substract from zero extended */
835 PPC_OP(subfze)
836 {
837     T1 = ~T0;
838     T0 = T1 + xer_ca;
839     if (T0 < T1) {
840         xer_ca = 1;
841     } else {
842         xer_ca = 0;
843     }
844     RETURN();
845 }
846
847 PPC_OP(subfzeo)
848 {
849     T1 = T0;
850     T0 = ~T0 + xer_ca;
851     if ((~T1 ^ (-1)) & ((~T1) ^ T0) & (1 << 31)) {
852         xer_ov = 1;
853         xer_so = 1;
854     } else {
855         xer_ov = 0;
856     }
857     if (T0 < ~T1) {
858         xer_ca = 1;
859     } else {
860         xer_ca = 0;
861     }
862     RETURN();
863 }
864
865 /***                           Integer comparison                          ***/
866 /* compare */
867 PPC_OP(cmp)
868 {
869     if (Ts0 < Ts1) {
870         T0 = 0x08;
871     } else if (Ts0 > Ts1) {
872         T0 = 0x04;
873     } else {
874         T0 = 0x02;
875     }
876     RETURN();
877 }
878
879 /* compare immediate */
880 PPC_OP(cmpi)
881 {
882     if (Ts0 < SPARAM(1)) {
883         T0 = 0x08;
884     } else if (Ts0 > SPARAM(1)) {
885         T0 = 0x04;
886     } else {
887         T0 = 0x02;
888     }
889     RETURN();
890 }
891
892 /* compare logical */
893 PPC_OP(cmpl)
894 {
895     if (T0 < T1) {
896         T0 = 0x08;
897     } else if (T0 > T1) {
898         T0 = 0x04;
899     } else {
900         T0 = 0x02;
901     }
902     RETURN();
903 }
904
905 /* compare logical immediate */
906 PPC_OP(cmpli)
907 {
908     if (T0 < PARAM(1)) {
909         T0 = 0x08;
910     } else if (T0 > PARAM(1)) {
911         T0 = 0x04;
912     } else {
913         T0 = 0x02;
914     }
915     RETURN();
916 }
917
918 /***                            Integer logical                            ***/
919 /* and */
920 PPC_OP(and)
921 {
922     T0 &= T1;
923     RETURN();
924 }
925
926 /* andc */
927 PPC_OP(andc)
928 {
929     T0 &= ~T1;
930     RETURN();
931 }
932
933 /* andi. */
934 PPC_OP(andi_)
935 {
936     T0 &= PARAM(1);
937     RETURN();
938 }
939
940 /* count leading zero */
941 PPC_OP(cntlzw)
942 {
943     T1 = T0;
944     for (T0 = 32; T1 > 0; T0--)
945         T1 = T1 >> 1;
946     RETURN();
947 }
948
949 /* eqv */
950 PPC_OP(eqv)
951 {
952     T0 = ~(T0 ^ T1);
953     RETURN();
954 }
955
956 /* extend sign byte */
957 PPC_OP(extsb)
958 {
959     Ts0 = s_ext8(Ts0);
960     RETURN();
961 }
962
963 /* extend sign half word */
964 PPC_OP(extsh)
965 {
966     Ts0 = s_ext16(Ts0);
967     RETURN();
968 }
969
970 /* nand */
971 PPC_OP(nand)
972 {
973     T0 = ~(T0 & T1);
974     RETURN();
975 }
976
977 /* nor */
978 PPC_OP(nor)
979 {
980     T0 = ~(T0 | T1);
981     RETURN();
982 }
983
984 /* or */
985 PPC_OP(or)
986 {
987     T0 |= T1;
988     RETURN();
989 }
990
991 /* orc */
992 PPC_OP(orc)
993 {
994     T0 |= ~T1;
995     RETURN();
996 }
997
998 /* ori */
999 PPC_OP(ori)
1000 {
1001     T0 |= PARAM(1);
1002     RETURN();
1003 }
1004
1005 /* xor */
1006 PPC_OP(xor)
1007 {
1008     T0 ^= T1;
1009     RETURN();
1010 }
1011
1012 /* xori */
1013 PPC_OP(xori)
1014 {
1015     T0 ^= PARAM(1);
1016     RETURN();
1017 }
1018
1019 /***                             Integer rotate                            ***/
1020 /* rotate left word immediate then mask insert */
1021 PPC_OP(rlwimi)
1022 {
1023     T0 = (rotl(T0, PARAM(1)) & PARAM(2)) | (T1 & PARAM(3));
1024     RETURN();
1025 }
1026
1027 /* rotate left immediate then and with mask insert */
1028 PPC_OP(rotlwi)
1029 {
1030     T0 = rotl(T0, PARAM(1));
1031     RETURN();
1032 }
1033
1034 PPC_OP(slwi)
1035 {
1036     T0 = T0 << PARAM(1);
1037     RETURN();
1038 }
1039
1040 PPC_OP(srwi)
1041 {
1042     T0 = T0 >> PARAM(1);
1043     RETURN();
1044 }
1045
1046 /* rotate left word then and with mask insert */
1047 PPC_OP(rlwinm)
1048 {
1049     T0 = rotl(T0, PARAM(1)) & PARAM(2);
1050     RETURN();
1051 }
1052
1053 PPC_OP(rotl)
1054 {
1055     T0 = rotl(T0, T1);
1056     RETURN();
1057 }
1058
1059 PPC_OP(rlwnm)
1060 {
1061     T0 = rotl(T0, T1) & PARAM(1);
1062     RETURN();
1063 }
1064
1065 /***                             Integer shift                             ***/
1066 /* shift left word */
1067 PPC_OP(slw)
1068 {
1069     if (T1 & 0x20) {
1070         T0 = 0;
1071     } else {
1072         T0 = T0 << T1;
1073     }
1074     RETURN();
1075 }
1076
1077 /* shift right algebraic word */
1078 PPC_OP(sraw)
1079 {
1080     Ts0 = do_sraw(Ts0, T1);
1081     RETURN();
1082 }
1083
1084 /* shift right algebraic word immediate */
1085 PPC_OP(srawi)
1086 {
1087     Ts1 = Ts0;
1088     Ts0 = Ts0 >> PARAM(1);
1089     if (Ts1 < 0 && (Ts1 & PARAM(2)) != 0) {
1090         xer_ca = 1;
1091     } else {
1092         xer_ca = 0;
1093     }
1094     RETURN();
1095 }
1096
1097 /* shift right word */
1098 PPC_OP(srw)
1099 {
1100     if (T1 & 0x20) {
1101         T0 = 0;
1102     } else {
1103         T0 = T0 >> T1;
1104     }
1105     RETURN();
1106 }
1107
1108 /***                       Floating-Point arithmetic                       ***/
1109
1110 /***                     Floating-Point multiply-and-add                   ***/
1111
1112 /***                     Floating-Point round & convert                    ***/
1113
1114 /***                         Floating-Point compare                        ***/
1115
1116 /***                  Floating-Point status & ctrl register                ***/
1117
1118 /***                             Integer load                              ***/
1119 #define ld16x(x) s_ext16(ld16(x))
1120 #define PPC_ILD_OPX(name, op)                                                 \
1121 PPC_OP(l##name##x_z)                                                          \
1122 {                                                                             \
1123     T1 = op(T0);                                                              \
1124     RETURN();                                                                 \
1125 }                                                                             \
1126 PPC_OP(l##name##x)                                                            \
1127 {                                                                             \
1128     T0 += T1;                                                                 \
1129     T1 = op(T0);                                                              \
1130     RETURN();                                                                 \
1131 }
1132
1133 #define PPC_ILD_OP(name, op)                                                  \
1134 PPC_OP(l##name##_z)                                                           \
1135 {                                                                             \
1136     T1 = op(SPARAM(1));                                                       \
1137     RETURN();                                                                 \
1138 }                                                                             \
1139 PPC_OP(l##name)                                                               \
1140 {                                                                             \
1141     T0 += SPARAM(1);                                                          \
1142     T1 = op(T0);                                                              \
1143     RETURN();                                                                 \
1144 }                                                                             \
1145 PPC_ILD_OPX(name, op)
1146
1147 PPC_ILD_OP(bz, ld8);
1148 PPC_ILD_OP(ha, ld16x);
1149 PPC_ILD_OP(hz, ld16);
1150 PPC_ILD_OP(wz, ld32);
1151
1152 /***                              Integer store                            ***/
1153 #define PPC_IST_OPX(name, op)                                                 \
1154 PPC_OP(st##name##x_z)                                                         \
1155 {                                                                             \
1156     op(T0, T1);                                                               \
1157     RETURN();                                                                 \
1158 }                                                                             \
1159 PPC_OP(st##name##x)                                                           \
1160 {                                                                             \
1161     T0 += T1;                                                                 \
1162     op(T0, T2);                                                               \
1163     RETURN();                                                                 \
1164 }
1165
1166 #define PPC_IST_OP(name, op)                                                  \
1167 PPC_OP(st##name##_z)                                                          \
1168 {                                                                             \
1169     op(SPARAM(1), T0);                                                        \
1170     RETURN();                                                                 \
1171 }                                                                             \
1172 PPC_OP(st##name)                                                              \
1173 {                                                                             \
1174     T0 += SPARAM(1);                                                          \
1175     op(T0, T1);                                                               \
1176     RETURN();                                                                 \
1177 }                                                                             \
1178 PPC_IST_OPX(name, op);
1179
1180 PPC_IST_OP(b, st8);
1181 PPC_IST_OP(h, st16);
1182 PPC_IST_OP(w, st32);
1183
1184 /***                Integer load and store with byte reverse               ***/
1185 PPC_ILD_OPX(hbr, ld16r);
1186 PPC_ILD_OPX(wbr, ld32r);
1187 PPC_IST_OPX(hbr, st16r);
1188 PPC_IST_OPX(wbr, st32r);
1189
1190 /***                    Integer load and store multiple                    ***/
1191 PPC_OP(lmw)
1192 {
1193     do_lmw(PARAM(1), SPARAM(2) + T0);
1194     RETURN();
1195 }
1196
1197 PPC_OP(stmw)
1198 {
1199     do_stmw(PARAM(1), SPARAM(2) + T0);
1200     RETURN();
1201 }
1202
1203 /***                    Integer load and store strings                     ***/
1204 PPC_OP(lswi)
1205 {
1206     do_lsw(PARAM(1), PARAM(2), T0);
1207     RETURN();
1208 }
1209
1210 PPC_OP(lswx)
1211 {
1212     do_lsw(PARAM(1), T0, T1 + T2);
1213     RETURN();
1214 }
1215
1216 PPC_OP(stswi_z)
1217 {
1218     do_stsw(PARAM(1), PARAM(2), 0);
1219     RETURN();
1220 }
1221
1222 PPC_OP(stswi)
1223 {
1224     do_stsw(PARAM(1), PARAM(2), T0);
1225     RETURN();
1226 }
1227
1228 PPC_OP(stswx_z)
1229 {
1230     do_stsw(PARAM(1), T0, T1);
1231     RETURN();
1232 }
1233
1234 PPC_OP(stswx)
1235 {
1236     do_stsw(PARAM(1), T0, T1 + T2);
1237     RETURN();
1238 }
1239
1240 /* SPR */
1241 PPC_OP(load_spr)
1242 {
1243     T0 = regs->spr[PARAM(1)];
1244 }
1245
1246 PPC_OP(store_spr)
1247 {
1248     regs->spr[PARAM(1)] = T0;
1249 }
1250
1251 /***                         Floating-point store                          ***/
1252
1253 PPC_OP(stfd_z_FT0)
1254 {
1255     stfq((void *)SPARAM(1), FT0);
1256 }
1257
1258 PPC_OP(stfd_FT0)
1259 {
1260     T0 += SPARAM(1);
1261     stfq((void *)T0, FT0);
1262 }
1263
1264 PPC_OP(stfdx_z_FT0)
1265 {
1266     stfq((void *)T0, FT0);
1267 }
1268
1269 PPC_OP(stfdx_FT0)
1270 {
1271     T0 += T1;
1272     stfq((void *)T0, FT0);
1273 }
1274
1275 PPC_OP(stfs_z_FT0)
1276 {
1277     float tmp = FT0;
1278     stfl((void *)SPARAM(1), tmp);
1279 }
1280
1281 PPC_OP(stfs_FT0)
1282 {
1283     float tmp = FT0;
1284     T0 += SPARAM(1);
1285     stfl((void *)T0, tmp);
1286 }
1287
1288 PPC_OP(stfsx_z_FT0)
1289 {
1290     float tmp = FT0;
1291     stfl((void *)T0, tmp);
1292 }
1293
1294 PPC_OP(stfsx_FT0)
1295 {
1296     float tmp = FT0;
1297     T0 += T1;
1298     stfl((void *)T0, tmp);
1299 }
1300
1301 /***                         Floating-point load                          ***/
1302 PPC_OP(lfd_z_FT0)
1303 {
1304     FT0 = ldfq((void *)SPARAM(1));
1305 }
1306
1307 PPC_OP(lfd_FT0)
1308 {
1309     T0 += SPARAM(1);
1310     FT0 = ldfq((void *)T0);
1311 }
1312
1313 PPC_OP(lfdx_z_FT0)
1314 {
1315     FT0 = ldfq((void *)T0);
1316 }
1317
1318 PPC_OP(lfdx_FT0)
1319 {
1320     T0 += T1;
1321     FT0 = ldfq((void *)T0);
1322 }
1323
1324 PPC_OP(lfs_z_FT0)
1325 {
1326     float tmp = ldfl((void *)SPARAM(1));
1327     FT0 = tmp;
1328 }
1329
1330 PPC_OP(lfs_FT0)
1331 {
1332     float tmp;
1333     T0 += SPARAM(1);
1334     tmp = ldfl((void *)T0);
1335     FT0 = tmp;
1336 }
1337
1338 PPC_OP(lfsx_z_FT0)
1339 {
1340     float tmp;
1341     tmp = ldfl((void *)T0);
1342     FT0 = tmp;
1343 }
1344
1345 PPC_OP(lfsx_FT0)
1346 {
1347     float tmp;
1348     T0 += T1;
1349     tmp = ldfl((void *)T0);
1350     FT0 = tmp;
1351 }
1352
1353 PPC_OP(lwarx_z)
1354 {
1355     T1 = ld32(T0);
1356     regs->reserve = T0;
1357     RETURN();
1358 }
1359
1360 PPC_OP(lwarx)
1361 {
1362     T0 += T1;
1363     T1 = ld32(T0);
1364     regs->reserve = T0;
1365     RETURN();
1366 }
1367
1368 PPC_OP(stwcx_z)
1369 {
1370     if (regs->reserve != T0) {
1371         env->crf[0] = xer_ov;
1372     } else {
1373         st32(T0, T1);
1374         env->crf[0] = xer_ov | 0x02;
1375     }
1376     regs->reserve = 0;
1377     RETURN();
1378 }
1379
1380 PPC_OP(stwcx)
1381 {
1382     T0 += T1;
1383     if (regs->reserve != (T0 & ~0x03)) {
1384         env->crf[0] = xer_ov;
1385     } else {
1386         st32(T0, T2);
1387         env->crf[0] = xer_ov | 0x02;
1388     }
1389     regs->reserve = 0;
1390     RETURN();
1391 }
1392
1393 PPC_OP(dcbz_z)
1394 {
1395     do_dcbz();
1396     RETURN();
1397 }
1398
1399 PPC_OP(dcbz)
1400 {
1401     T0 += T1;
1402     do_dcbz();
1403     RETURN();
1404 }
1405
1406 /* Instruction cache block invalidate */
1407 PPC_OP(icbi_z)
1408 {
1409     do_icbi();
1410     RETURN();
1411 }
1412
1413 PPC_OP(icbi)
1414 {
1415     T0 += T1;
1416     do_icbi();
1417     RETURN();
1418 }