PowerPC support (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 extern uint32_t __a;
26 extern uint32_t __b;
27 extern uint32_t __c;
28 extern uint32_t __d;
29 extern uint32_t __e;
30 extern uint32_t __f;
31 #define Ts0 (int32_t)T0
32 #define Ts1 (int32_t)T1
33 #define Ts2 (int32_t)T2
34
35 #include "op-multi.c"
36
37 #define PPC_OP(name) void op_##name(void)
38
39 /* PPC state maintenance operations */
40 /* set_Rc0 */
41 PPC_OP(set_Rc0)
42 {
43     uint32_t tmp;
44
45     if (Ts0 < 0) {
46         tmp = 0x08;
47     } else if (Ts0 > 0) {
48         tmp = 0x04;
49     } else {
50         tmp = 0x02;
51     }
52     set_CRn(0, tmp);
53     RETURN();
54 }
55
56 PPC_OP(set_Rc0_ov)
57 {
58     uint32_t tmp;
59
60     if (Ts0 < 0) {
61         tmp = 0x08;
62     } else if (Ts0 > 0) {
63         tmp = 0x04;
64     } else {
65         tmp = 0x02;
66     }
67     tmp |= xer_ov;
68     set_CRn(0, tmp);
69     RETURN();
70 }
71
72 /* reset_Rc0 */
73 PPC_OP(reset_Rc0)
74 {
75     set_CRn(0, 0x02 | xer_ov);
76     RETURN();
77 }
78
79 /* set_Rc0_1 */
80 PPC_OP(set_Rc0_1)
81 {
82     set_CRn(0, 0x04 | xer_ov);
83     RETURN();
84 }
85
86 PPC_OP(set_T0)
87 {
88     T0 = PARAM(1);
89     RETURN();
90 }
91
92 PPC_OP(set_T1)
93 {
94     T1 = PARAM(1);
95     RETURN();
96 }
97
98 PPC_OP(set_T2)
99 {
100     T2 = PARAM(1);
101     RETURN();
102 }
103
104 /* Update time base */
105 PPC_OP(update_tb)
106 {
107     T0 = regs->spr[SPR_ENCODE(268)];
108     T1 = T0;
109     T0 += PARAM(1);
110     if (T0 < T1) {
111         T1 = regs->spr[SPR_ENCODE(269)] + 1;
112         regs->spr[SPR_ENCODE(269)] = T1;
113     }
114     regs->spr[SPR_ENCODE(268)] = T0;
115     RETURN();
116 }
117
118 PPC_OP(raise_exception)
119 {
120     raise_exception(PARAM(1));
121     RETURN();
122 }
123
124 PPC_OP(exit_tb)
125 {
126     EXIT_TB();
127 }
128
129 PPC_OP(load_cr)
130 {
131     T0 = do_load_cr();
132     RETURN();
133 }
134
135 PPC_OP(store_cr)
136 {
137     do_store_cr(PARAM(1), T0);
138     RETURN();
139 }
140
141 PPC_OP(load_xer_cr)
142 {
143     T0 = (xer_so << 3) | (xer_ov << 2) | (xer_ca << 1);
144     RETURN();
145 }
146
147 PPC_OP(clear_xer_cr)
148 {
149     xer_so = 0;
150     xer_ov = 0;
151     xer_ca = 0;
152     RETURN();
153 }
154
155 PPC_OP(load_xer_bc)
156 {
157     T0 = xer_bc;
158     RETURN();
159 }
160
161 PPC_OP(load_xer)
162 {
163     T0 = do_load_xer();
164     RETURN();
165 }
166
167 PPC_OP(store_xer)
168 {
169     do_store_xer(T0);
170     RETURN();
171 }
172
173 PPC_OP(load_msr)
174 {
175     T0 = do_load_msr();
176     RETURN();
177 }
178
179 PPC_OP(store_msr)
180 {
181     do_store_msr(T0);
182     RETURN();
183 }
184
185 PPC_OP(load_lr)
186 {
187     regs->LR = PARAM(1);
188     RETURN();
189 }
190
191 /* Set reservation */
192 PPC_OP(set_reservation)
193 {
194     regs->reserve = T1 & ~0x03;
195     RETURN();
196 }
197
198 /* Reset reservation */
199 PPC_OP(reset_reservation)
200 {
201     regs->reserve = 0;
202     RETURN();
203 }
204
205 /* crf operations */
206 PPC_OP(getbit_T0)
207 {
208     T0 = (T0 >> PARAM(1)) & 1;
209     RETURN();
210 }
211
212 PPC_OP(getbit_T1)
213 {
214     T1 = (T1 >> PARAM(1)) & 1;
215     RETURN();
216 }
217
218 PPC_OP(setcrfbit)
219 {
220     T1 = (T1 & PARAM(1)) | (T0 << PARAM(2)); 
221     RETURN();
222 }
223
224 /* Branch */
225 #define __PPC_OP_B(name, target)                                              \
226 PPC_OP(name)                                                                  \
227 {                                                                             \
228     regs->nip = (target);                                                     \
229     RETURN();                                                                 \
230 }
231
232 #define __PPC_OP_BL(name, target)                                             \
233 PPC_OP(name)                                                                  \
234 {                                                                             \
235     regs->LR = PARAM(1);                                                      \
236     regs->nip = (target);                                                     \
237     RETURN();                                                                 \
238 }
239
240 #define PPC_OP_B(name, target)                                                \
241 __PPC_OP_B(name, target);                                                     \
242 __PPC_OP_BL(name##l, target)
243
244 #define __PPC_OP_BC(name, cond, target)                                       \
245 PPC_OP(name)                                                                  \
246 {                                                                             \
247     if (cond) {                                                               \
248         T0 = (target);                                                        \
249     } else {                                                                  \
250         T0 = PARAM(1);                                                        \
251     }                                                                         \
252     regs->nip = T0;                                                           \
253     RETURN();                                                                 \
254 }
255
256 #define __PPC_OP_BCL(name, cond, target)                                      \
257 PPC_OP(name)                                                                  \
258 {                                                                             \
259     if (cond) {                                                               \
260         T0 = (target);                                                        \
261         regs->LR = PARAM(1);                                                  \
262     } else {                                                                  \
263         T0 = PARAM(1);                                                        \
264     }                                                                         \
265     regs->nip = T0;                                                           \
266     RETURN();                                                                 \
267 }
268
269 #define _PPC_OP_BC(name, namel, cond, target)                                 \
270 __PPC_OP_BC(name, cond, target);                                              \
271 __PPC_OP_BCL(namel, cond, target)
272
273 /* Branch to target */
274 #define PPC_OP_BC(name, cond)                                                 \
275 _PPC_OP_BC(b_##name, bl_##name, cond, PARAM(2))
276
277 PPC_OP_B(b, PARAM(1));
278 PPC_OP_BC(ctr,        (regs->CTR != 0));
279 PPC_OP_BC(ctr_true,   (regs->CTR != 0 && (T0 & PARAM(3)) != 0));
280 PPC_OP_BC(ctr_false,  (regs->CTR != 0 && (T0 & PARAM(3)) == 0));
281 PPC_OP_BC(ctrz,       (regs->CTR == 0));
282 PPC_OP_BC(ctrz_true,  (regs->CTR == 0 && (T0 & PARAM(3)) != 0));
283 PPC_OP_BC(ctrz_false, (regs->CTR == 0 && (T0 & PARAM(3)) == 0));
284 PPC_OP_BC(true,       ((T0 & PARAM(3)) != 0));
285 PPC_OP_BC(false,      ((T0 & PARAM(3)) == 0));
286
287 /* Branch to CTR */
288 #define PPC_OP_BCCTR(name, cond)                                              \
289 _PPC_OP_BC(bctr_##name, bctrl_##name, cond, regs->CTR & ~0x03)
290
291 PPC_OP_B(bctr, regs->CTR & ~0x03);
292 PPC_OP_BCCTR(ctr,        (regs->CTR != 0));
293 PPC_OP_BCCTR(ctr_true,   (regs->CTR != 0 && (T0 & PARAM(2)) != 0));
294 PPC_OP_BCCTR(ctr_false,  (regs->CTR != 0 && (T0 & PARAM(2)) == 0));
295 PPC_OP_BCCTR(ctrz,       (regs->CTR == 0));
296 PPC_OP_BCCTR(ctrz_true,  (regs->CTR == 0 && (T0 & PARAM(2)) != 0));
297 PPC_OP_BCCTR(ctrz_false, (regs->CTR == 0 && (T0 & PARAM(2)) == 0));
298 PPC_OP_BCCTR(true,       ((T0 & PARAM(2)) != 0));
299 PPC_OP_BCCTR(false,      ((T0 & PARAM(2)) == 0));
300
301 /* Branch to LR */
302 #define PPC_OP_BCLR(name, cond)                                               \
303 _PPC_OP_BC(blr_##name, blrl_##name, cond, regs->LR & ~0x03)
304
305 PPC_OP_B(blr, regs->LR & ~0x03);
306 PPC_OP_BCLR(ctr,        (regs->CTR != 0));
307 PPC_OP_BCLR(ctr_true,   (regs->CTR != 0 && (T0 & PARAM(2)) != 0));
308 PPC_OP_BCLR(ctr_false,  (regs->CTR != 0 && (T0 & PARAM(2)) == 0));
309 PPC_OP_BCLR(ctrz,       (regs->CTR == 0));
310 PPC_OP_BCLR(ctrz_true,  (regs->CTR == 0 && (T0 & PARAM(2)) != 0));
311 PPC_OP_BCLR(ctrz_false, (regs->CTR == 0 && (T0 & PARAM(2)) == 0));
312 PPC_OP_BCLR(true,       ((T0 & PARAM(2)) != 0));
313 PPC_OP_BCLR(false,      ((T0 & PARAM(2)) == 0));
314
315 /* CTR maintenance */
316 PPC_OP(dec_ctr)
317 {
318     regs->CTR--;
319     RETURN();
320 }
321
322 /***                           Integer arithmetic                          ***/
323 /* add */
324 PPC_OP(add)
325 {
326     T0 += T1;
327     RETURN();
328 }
329
330 PPC_OP(addo)
331 {
332     T2 = T0;
333     T0 += T1;
334     if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
335         xer_so = 1;
336         xer_ov = 1;
337     } else {
338         xer_ov = 0;
339     }
340     RETURN();
341 }
342
343 /* add carrying */
344 PPC_OP(addc)
345 {
346     T2 = T0;
347     T0 += T1;
348     if (T0 < T2) {
349         xer_ca = 1;
350     } else {
351         xer_ca = 0;
352     }
353     RETURN();
354 }
355
356 PPC_OP(addco)
357 {
358     T2 = T0;
359     T0 += T1;
360     if (T0 < T2) {
361         xer_ca = 1;
362     } else {
363         xer_ca = 0;
364     }
365     if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
366         xer_so = 1;
367         xer_ov = 1;
368     } else {
369         xer_ov = 0;
370     }
371     RETURN();
372 }
373
374 /* add extended */
375 /* candidate for helper (too long) */
376 PPC_OP(adde)
377 {
378     T2 = T0;
379     T0 += T1 + xer_ca;
380     if (T0 < T2 || (xer_ca == 1 && T0 == T2)) {
381         xer_ca = 1;
382     } else {
383         xer_ca = 0;
384     }
385     RETURN();
386 }
387
388 PPC_OP(addeo)
389 {
390     T2 = T0;
391     T0 += T1 + xer_ca;
392     if (T0 < T2 || (xer_ca == 1 && T0 == T2)) {
393         xer_ca = 1;
394     } else {
395         xer_ca = 0;
396     }
397     if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
398         xer_so = 1;
399         xer_ov = 1;
400     } else {
401         xer_ov = 0;
402     }
403     RETURN();
404 }
405
406 /* add immediate */
407 PPC_OP(addi)
408 {
409     T0 += PARAM(1);
410     RETURN();
411 }
412
413 /* add immediate carrying */
414 PPC_OP(addic)
415 {
416     T1 = T0;
417     T0 += PARAM(1);
418     if (T0 < T1) {
419         xer_ca = 1;
420     } else {
421         xer_ca = 0;
422     }
423     RETURN();
424 }
425
426 /* add to minus one extended */
427 PPC_OP(addme)
428 {
429     T1 = T0;
430     T0 += xer_ca + (-1);
431     if (T1 != 0)
432         xer_ca = 1;
433     RETURN();
434 }
435
436 PPC_OP(addmeo)
437 {
438     T1 = T0;
439     T0 += xer_ca + (-1);
440     if (T1 & (T1 ^ T0) & (1 << 31)) {
441         xer_so = 1;
442         xer_ov = 1;
443     } else {
444         xer_ov = 0;
445     }
446     if (T1 != 0)
447         xer_ca = 1;
448     RETURN();
449 }
450
451 /* add to zero extended */
452 PPC_OP(addze)
453 {
454     T1 = T0;
455     T0 += xer_ca;
456     if (T0 < T1) {
457         xer_ca = 1;
458     } else {
459         xer_ca = 0;
460     }
461     RETURN();
462 }
463
464 PPC_OP(addzeo)
465 {
466     T1 = T0;
467     T0 += xer_ca;
468     if ((T1 ^ (-1)) & (T1 ^ T0) & (1 << 31)) {
469         xer_so = 1;
470         xer_ov = 1;
471     } else {
472         xer_ov = 0;
473     }
474     if (T0 < T1) {
475         xer_ca = 1;
476     } else {
477         xer_ca = 0;
478     }
479     RETURN();
480 }
481
482 /* divide word */
483 /* candidate for helper (too long) */
484 PPC_OP(divw)
485 {
486     if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
487         Ts0 = (-1) * (T0 >> 31);
488     } else {
489         Ts0 /= Ts1;
490     }
491     RETURN();
492 }
493
494 PPC_OP(divwo)
495 {
496     if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
497         xer_so = 1;
498         xer_ov = 1;
499         T0 = (-1) * (T0 >> 31);
500     } else {
501         xer_ov = 0;
502         Ts0 /= Ts1;
503     }
504     RETURN();
505 }
506
507 /* divide word unsigned */
508 PPC_OP(divwu)
509 {
510     if (T1 == 0) {
511         T0 = 0;
512     } else {
513         T0 /= T1;
514     }
515     RETURN();
516 }
517
518 PPC_OP(divwuo)
519 {
520     if (T1 == 0) {
521         xer_so = 1;
522         xer_ov = 1;
523         T0 = 0;
524     } else {
525         xer_ov = 0;
526         T0 /= T1;
527     }
528     RETURN();
529 }
530
531 /* multiply high word */
532 PPC_OP(mulhw)
533 {
534     Ts0 = ((int64_t)Ts0 * (int64_t)Ts1) >> 32;
535     RETURN();
536 }
537
538 /* multiply high word unsigned */
539 PPC_OP(mulhwu)
540 {
541     T0 = ((uint64_t)T0 * (uint64_t)T1) >> 32;
542     RETURN();
543 }
544
545 /* multiply low immediate */
546 PPC_OP(mulli)
547 {
548     Ts0 *= SPARAM(1);
549     RETURN();
550 }
551
552 /* multiply low word */
553 PPC_OP(mullw)
554 {
555     T0 *= T1;
556     RETURN();
557 }
558
559 PPC_OP(mullwo)
560 {
561     int64_t res = (int64_t)Ts0 * (int64_t)Ts1;
562
563     if ((int32_t)res != res) {
564         xer_ov = 1;
565         xer_so = 1;
566     } else {
567         xer_ov = 0;
568     }
569     Ts0 = res;
570     RETURN();
571 }
572
573 /* negate */
574 PPC_OP(neg)
575 {
576     if (T0 != 0x80000000) {
577         Ts0 = -Ts0;
578     }
579     RETURN();
580 }
581
582 PPC_OP(nego)
583 {
584     if (T0 == 0x80000000) {
585         xer_ov = 1;
586         xer_so = 1;
587     } else {
588         xer_ov = 0;
589         Ts0 = -Ts0;
590     }
591     RETURN();
592 }
593
594 /* substract from */
595 PPC_OP(subf)
596 {
597     T0 = T1 - T0;
598     RETURN();
599 }
600
601 PPC_OP(subfo)
602 {
603     T2 = T0;
604     T0 = T1 - T0;
605     if (((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)) {
606         xer_so = 1;
607         xer_ov = 1;
608     } else {
609         xer_ov = 0;
610     }
611     RETURN();
612 }
613
614 /* substract from carrying */
615 PPC_OP(subfc)
616 {
617     T0 = T1 - T0;
618     if (T0 <= T1) {
619         xer_ca = 1;
620     } else {
621         xer_ca = 0;
622     }
623     RETURN();
624 }
625
626 PPC_OP(subfco)
627 {
628     T2 = T0;
629     T0 = T1 - T0;
630     if (T0 <= T1) {
631         xer_ca = 1;
632     } else {
633         xer_ca = 0;
634     }
635     if (((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)) {
636         xer_so = 1;
637         xer_ov = 1;
638     } else {
639         xer_ov = 0;
640     }
641     RETURN();
642 }
643
644 /* substract from extended */
645 /* candidate for helper (too long) */
646 PPC_OP(subfe)
647 {
648     T0 = T1 + ~T0 + xer_ca;
649     if (T0 < T1 || (xer_ca == 1 && T0 == T1)) {
650         xer_ca = 1;
651     } else {
652         xer_ca = 0;
653     }
654     RETURN();
655 }
656
657 PPC_OP(subfeo)
658 {
659     T2 = T0;
660     T0 = T1 + ~T0 + xer_ca;
661     if ((~T2 ^ T1 ^ (-1)) & (~T2 ^ T0) & (1 << 31)) {
662         xer_so = 1;
663         xer_ov = 1;
664     } else {
665         xer_ov = 0;
666     }
667     if (T0 < T1 || (xer_ca == 1 && T0 == T1)) {
668         xer_ca = 1;
669     } else {
670         xer_ca = 0;
671     }
672     RETURN();
673 }
674
675 /* substract from immediate carrying */
676 PPC_OP(subfic)
677 {
678     T0 = PARAM(1) + ~T0 + 1;
679     if (T0 <= PARAM(1)) {
680         xer_ca = 1;
681     } else {
682         xer_ca = 0;
683     }
684     RETURN();
685 }
686
687 /* substract from minus one extended */
688 PPC_OP(subfme)
689 {
690     T0 = ~T0 + xer_ca - 1;
691
692     if (T0 != -1)
693         xer_ca = 1;
694     RETURN();
695 }
696
697 PPC_OP(subfmeo)
698 {
699     T1 = T0;
700     T0 = ~T0 + xer_ca - 1;
701     if (~T1 & (~T1 ^ T0) & (1 << 31)) {
702         xer_so = 1;
703         xer_ov = 1;
704     } else {
705         xer_ov = 0;
706     }
707     if (T1 != -1)
708         xer_ca = 1;
709     RETURN();
710 }
711
712 /* substract from zero extended */
713 PPC_OP(subfze)
714 {
715     T1 = ~T0;
716     T0 = T1 + xer_ca;
717     if (T0 < T1) {
718         xer_ca = 1;
719     } else {
720         xer_ca = 0;
721     }
722     RETURN();
723 }
724
725 PPC_OP(subfzeo)
726 {
727     T1 = T0;
728     T0 = ~T0 + xer_ca;
729     if ((~T1 ^ (-1)) & ((~T1) ^ T0) & (1 << 31)) {
730         xer_ov = 1;
731         xer_so = 1;
732     } else {
733         xer_ov = 0;
734     }
735     if (T0 < ~T1) {
736         xer_ca = 1;
737     } else {
738         xer_ca = 0;
739     }
740     RETURN();
741 }
742
743 /***                           Integer comparison                          ***/
744 /* compare */
745 PPC_OP(cmp)
746 {
747     if (Ts0 < Ts1) {
748         T0 = 0x08;
749     } else if (Ts0 > Ts1) {
750         T0 = 0x04;
751     } else {
752         T0 = 0x02;
753     }
754     RETURN();
755 }
756
757 /* compare immediate */
758 PPC_OP(cmpi)
759 {
760     if (Ts0 < SPARAM(1)) {
761         T0 = 0x08;
762     } else if (Ts0 > SPARAM(1)) {
763         T0 = 0x04;
764     } else {
765         T0 = 0x02;
766     }
767     RETURN();
768 }
769
770 /* compare logical */
771 PPC_OP(cmpl)
772 {
773     if (T0 < T1) {
774         T0 = 0x08;
775     } else if (T0 > T1) {
776         T0 = 0x04;
777     } else {
778         T0 = 0x02;
779     }
780     RETURN();
781 }
782
783 /* compare logical immediate */
784 PPC_OP(cmpli)
785 {
786     if (T0 < PARAM(1)) {
787         T0 = 0x08;
788     } else if (T0 > PARAM(1)) {
789         T0 = 0x04;
790     } else {
791         T0 = 0x02;
792     }
793     RETURN();
794 }
795
796 /***                            Integer logical                            ***/
797 /* and */
798 PPC_OP(and)
799 {
800     T0 &= T1;
801     RETURN();
802 }
803
804 /* andc */
805 PPC_OP(andc)
806 {
807     T0 &= ~T1;
808     RETURN();
809 }
810
811 /* andi. */
812 PPC_OP(andi_)
813 {
814     T0 &= PARAM(1);
815     RETURN();
816 }
817
818 /* count leading zero */
819 PPC_OP(cntlzw)
820 {
821     T1 = T0;
822     for (T0 = 32; T1 > 0; T0--)
823         T1 = T1 >> 1;
824     RETURN();
825 }
826
827 /* eqv */
828 PPC_OP(eqv)
829 {
830     T0 = ~(T0 ^ T1);
831     RETURN();
832 }
833
834 /* extend sign byte */
835 PPC_OP(extsb)
836 {
837     Ts0 = s_ext8(Ts0);
838     RETURN();
839 }
840
841 /* extend sign half word */
842 PPC_OP(extsh)
843 {
844     Ts0 = s_ext16(Ts0);
845     RETURN();
846 }
847
848 /* nand */
849 PPC_OP(nand)
850 {
851     T0 = ~(T0 & T1);
852     RETURN();
853 }
854
855 /* nor */
856 PPC_OP(nor)
857 {
858     T0 = ~(T0 | T1);
859     RETURN();
860 }
861
862 /* or */
863 PPC_OP(or)
864 {
865     T0 |= T1;
866     RETURN();
867 }
868
869 /* orc */
870 PPC_OP(orc)
871 {
872     T0 |= ~T1;
873     RETURN();
874 }
875
876 /* ori */
877 PPC_OP(ori)
878 {
879     T0 |= PARAM(1);
880     RETURN();
881 }
882
883 /* xor */
884 PPC_OP(xor)
885 {
886     T0 ^= T1;
887     RETURN();
888 }
889
890 /* xori */
891 PPC_OP(xori)
892 {
893     T0 ^= PARAM(1);
894     RETURN();
895 }
896
897 /***                             Integer rotate                            ***/
898 /* rotate left word immediate then mask insert */
899 PPC_OP(rlwimi)
900 {
901     T0 = rotl(T0, PARAM(1) & PARAM(2)) | (T0 & PARAM(3));
902     RETURN();
903 }
904
905 /* rotate left immediate then and with mask insert */
906 PPC_OP(rotlwi)
907 {
908     T0 = rotl(T0, PARAM(1));
909     RETURN();
910 }
911
912 PPC_OP(slwi)
913 {
914     T0 = T0 << PARAM(1);
915     RETURN();
916 }
917
918 PPC_OP(srwi)
919 {
920     T0 = T0 >> PARAM(1);
921     RETURN();
922 }
923
924 /* rotate left word then and with mask insert */
925 PPC_OP(rlwinm)
926 {
927     T0 = rotl(T0, PARAM(1)) & PARAM(2);
928     RETURN();
929 }
930
931 PPC_OP(rotl)
932 {
933     T0 = rotl(T0, T1);
934     RETURN();
935 }
936
937 PPC_OP(rlwnm)
938 {
939     T0 = rotl(T0, T1) & PARAM(1);
940     RETURN();
941 }
942
943 /***                             Integer shift                             ***/
944 /* shift left word */
945 PPC_OP(slw)
946 {
947     if (T1 & 0x20) {
948         T0 = 0;
949     } else {
950         T0 = T0 << T1;
951     }
952     RETURN();
953 }
954
955 /* shift right algebraic word */
956 PPC_OP(sraw)
957 {
958     Ts0 = do_sraw(Ts0, T1);
959     RETURN();
960 }
961
962 /* shift right algebraic word immediate */
963 PPC_OP(srawi)
964 {
965     Ts1 = Ts0;
966     Ts0 = Ts0 >> PARAM(1);
967     if (Ts1 < 0 && (Ts1 & PARAM(2)) != 0) {
968         xer_ca = 1;
969     } else {
970         xer_ca = 0;
971     }
972     RETURN();
973 }
974
975 /* shift right word */
976 PPC_OP(srw)
977 {
978     if (T1 & 0x20) {
979         T0 = 0;
980     } else {
981         T0 = T0 >> T1;
982     }
983     RETURN();
984 }
985
986 /***                       Floating-Point arithmetic                       ***/
987
988 /***                     Floating-Point multiply-and-add                   ***/
989
990 /***                     Floating-Point round & convert                    ***/
991
992 /***                         Floating-Point compare                        ***/
993
994 /***                  Floating-Point status & ctrl register                ***/
995
996 /***                             Integer load                              ***/
997 #define ld16x(x) s_ext16(ld16(x))
998 #define PPC_ILD_OPX(name, op)                                                 \
999 PPC_OP(l##name##x_z)                                                          \
1000 {                                                                             \
1001     T1 = op(T0);                                                              \
1002     RETURN();                                                                 \
1003 }                                                                             \
1004 PPC_OP(l##name##x)                                                            \
1005 {                                                                             \
1006     T0 += T1;                                                                 \
1007     T1 = op(T0);                                                              \
1008     RETURN();                                                                 \
1009 }
1010
1011 #define PPC_ILD_OP(name, op)                                                  \
1012 PPC_OP(l##name##_z)                                                           \
1013 {                                                                             \
1014     T1 = op(SPARAM(1));                                                       \
1015     RETURN();                                                                 \
1016 }                                                                             \
1017 PPC_OP(l##name)                                                               \
1018 {                                                                             \
1019     T0 += SPARAM(1);                                                          \
1020     T1 = op(T0);                                                              \
1021     RETURN();                                                                 \
1022 }                                                                             \
1023 PPC_ILD_OPX(name, op)
1024
1025 PPC_ILD_OP(bz, ld8);
1026 PPC_ILD_OP(ha, ld16x);
1027 PPC_ILD_OP(hz, ld16);
1028 PPC_ILD_OP(wz, ld32);
1029
1030 /***                              Integer store                            ***/
1031 #define PPC_IST_OPX(name, op)                                                 \
1032 PPC_OP(st##name##x_z)                                                         \
1033 {                                                                             \
1034     op(T0, T1);                                                               \
1035     RETURN();                                                                 \
1036 }                                                                             \
1037 PPC_OP(st##name##x)                                                           \
1038 {                                                                             \
1039     T0 += T1;                                                                 \
1040     op(T0, T2);                                                               \
1041     RETURN();                                                                 \
1042 }
1043
1044 #define PPC_IST_OP(name, op)                                                  \
1045 PPC_OP(st##name##_z)                                                          \
1046 {                                                                             \
1047     op(SPARAM(1), T0);                                                        \
1048     RETURN();                                                                 \
1049 }                                                                             \
1050 PPC_OP(st##name)                                                              \
1051 {                                                                             \
1052     T0 += SPARAM(1);                                                          \
1053     op(T0, T1);                                                               \
1054     RETURN();                                                                 \
1055 }                                                                             \
1056 PPC_IST_OPX(name, op);
1057
1058 PPC_IST_OP(b, st8);
1059 PPC_IST_OP(h, st16);
1060 PPC_IST_OP(w, st32);
1061
1062 /***                Integer load and store with byte reverse               ***/
1063 PPC_ILD_OPX(hbr, ld16r);
1064 PPC_ILD_OPX(wbr, ld32r);
1065 PPC_IST_OPX(hbr, st16r);
1066 PPC_IST_OPX(wbr, st32r);
1067
1068 /***                    Integer load and store multiple                    ***/
1069 PPC_OP(lmw)
1070 {
1071     do_lmw(PARAM(1), SPARAM(2) + T0);
1072     RETURN();
1073 }
1074
1075 PPC_OP(stmw)
1076 {
1077     do_stmw(PARAM(1), SPARAM(2) + T0);
1078     RETURN();
1079 }
1080
1081 /***                    Integer load and store strings                     ***/
1082 PPC_OP(lswi)
1083 {
1084     do_lsw(PARAM(1), PARAM(2), T0);
1085     RETURN();
1086 }
1087
1088 PPC_OP(lswx)
1089 {
1090     do_lsw(PARAM(1), T0, T1 + T2);
1091     RETURN();
1092 }
1093
1094 PPC_OP(stswi_z)
1095 {
1096     do_stsw(PARAM(1), PARAM(2), 0);
1097     RETURN();
1098 }
1099
1100 PPC_OP(stswi)
1101 {
1102     do_stsw(PARAM(1), PARAM(2), T0);
1103     RETURN();
1104 }
1105
1106 PPC_OP(stswx_z)
1107 {
1108     do_stsw(PARAM(1), T0, T1);
1109     RETURN();
1110 }
1111
1112 PPC_OP(stswx)
1113 {
1114     do_stsw(PARAM(1), T0, T1 + T2);
1115     RETURN();
1116 }