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