2 * PPC emulation micro-operations for qemu.
4 * Copyright (c) 2003 Jocelyn Mayer
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.
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.
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
25 #define Ts0 (int32_t)T0
26 #define Ts1 (int32_t)T1
27 #define Ts2 (int32_t)T2
29 #define FT0 (env->ft0)
30 #define FT1 (env->ft1)
31 #define FT2 (env->ft2)
33 #define FTS0 ((float)env->ft0)
34 #define FTS1 ((float)env->ft1)
35 #define FTS2 ((float)env->ft2)
37 #define PPC_OP(name) void op_##name(void)
40 #include "op_template.h"
43 #include "op_template.h"
46 #include "op_template.h"
49 #include "op_template.h"
52 #include "op_template.h"
55 #include "op_template.h"
58 #include "op_template.h"
61 #include "op_template.h"
64 #include "op_template.h"
67 #include "op_template.h"
70 #include "op_template.h"
73 #include "op_template.h"
76 #include "op_template.h"
79 #include "op_template.h"
82 #include "op_template.h"
85 #include "op_template.h"
88 #include "op_template.h"
91 #include "op_template.h"
94 #include "op_template.h"
97 #include "op_template.h"
100 #include "op_template.h"
103 #include "op_template.h"
106 #include "op_template.h"
109 #include "op_template.h"
112 #include "op_template.h"
115 #include "op_template.h"
118 #include "op_template.h"
121 #include "op_template.h"
124 #include "op_template.h"
127 #include "op_template.h"
130 #include "op_template.h"
133 #include "op_template.h"
135 /* PPC state maintenance operations */
143 } else if (Ts0 > 0) {
158 } else if (Ts0 > 0) {
171 set_CRn(0, 0x02 | xer_ov);
178 set_CRn(0, 0x04 | xer_ov);
182 /* Set Rc1 (for floating point arithmetic) */
185 env->crf[1] = regs->fpscr[7];
207 /* Update time base */
210 T0 = regs->spr[SPR_ENCODE(268)];
214 T1 = regs->spr[SPR_ENCODE(269)] + 1;
215 regs->spr[SPR_ENCODE(269)] = T1;
217 regs->spr[SPR_ENCODE(268)] = T0;
221 PPC_OP(raise_exception)
223 raise_exception(PARAM(1));
240 do_store_cr(PARAM(1), T0);
246 T0 = (xer_so << 3) | (xer_ov << 2) | (xer_ca << 1);
303 do_store_fpscr(PARAM(1));
309 regs->fpscr[7] &= ~0x8;
313 /* Set reservation */
314 PPC_OP(set_reservation)
316 regs->reserve = T1 & ~0x03;
320 /* Reset reservation */
321 PPC_OP(reset_reservation)
330 T0 = (T0 >> PARAM(1)) & 1;
336 T1 = (T1 >> PARAM(1)) & 1;
342 T1 = (T1 & PARAM(1)) | (T0 << PARAM(2));
347 #define __PPC_OP_B(name, target) \
350 regs->nip = (target); \
354 #define __PPC_OP_BL(name, target) \
357 regs->LR = PARAM(1); \
358 regs->nip = (target); \
362 #define PPC_OP_B(name, target) \
363 __PPC_OP_B(name, target); \
364 __PPC_OP_BL(name##l, target)
366 #define __PPC_OP_BC(name, cond, target) \
378 #define __PPC_OP_BCL(name, cond, target) \
383 regs->LR = PARAM(1); \
391 #define _PPC_OP_BC(name, namel, cond, target) \
392 __PPC_OP_BC(name, cond, target); \
393 __PPC_OP_BCL(namel, cond, target)
395 /* Branch to target */
396 #define PPC_OP_BC(name, cond) \
397 _PPC_OP_BC(b_##name, bl_##name, cond, PARAM(2))
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));
410 #define PPC_OP_BCCTR(name, cond) \
411 _PPC_OP_BC(bctr_##name, bctrl_##name, cond, regs->CTR & ~0x03)
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));
424 #define PPC_OP_BCLR(name, cond) \
425 _PPC_OP_BC(blr_##name, blrl_##name, cond, regs->LR & ~0x03)
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));
437 /* CTR maintenance */
444 /*** Integer arithmetic ***/
456 if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
487 if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
497 /* candidate for helper (too long) */
502 if (T0 < T2 || (xer_ca == 1 && T0 == T2)) {
514 if (T0 < T2 || (xer_ca == 1 && T0 == T2)) {
519 if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
535 /* add immediate carrying */
548 /* add to minus one extended */
562 if (T1 & (T1 ^ T0) & (1 << 31)) {
573 /* add to zero extended */
590 if ((T1 ^ (-1)) & (T1 ^ T0) & (1 << 31)) {
605 /* candidate for helper (too long) */
608 if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
609 Ts0 = (-1) * (T0 >> 31);
618 if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
621 T0 = (-1) * (T0 >> 31);
629 /* divide word unsigned */
653 /* multiply high word */
656 Ts0 = ((int64_t)Ts0 * (int64_t)Ts1) >> 32;
660 /* multiply high word unsigned */
663 T0 = ((uint64_t)T0 * (uint64_t)T1) >> 32;
667 /* multiply low immediate */
674 /* multiply low word */
683 int64_t res = (int64_t)Ts0 * (int64_t)Ts1;
685 if ((int32_t)res != res) {
698 if (T0 != 0x80000000) {
706 if (T0 == 0x80000000) {
727 if (((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)) {
736 /* substract from carrying */
757 if (((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)) {
766 /* substract from extended */
767 /* candidate for helper (too long) */
770 T0 = T1 + ~T0 + xer_ca;
771 if (T0 < T1 || (xer_ca == 1 && T0 == T1)) {
782 T0 = T1 + ~T0 + xer_ca;
783 if ((~T2 ^ T1 ^ (-1)) & (~T2 ^ T0) & (1 << 31)) {
789 if (T0 < T1 || (xer_ca == 1 && T0 == T1)) {
797 /* substract from immediate carrying */
800 T0 = PARAM(1) + ~T0 + 1;
801 if (T0 <= PARAM(1)) {
809 /* substract from minus one extended */
812 T0 = ~T0 + xer_ca - 1;
822 T0 = ~T0 + xer_ca - 1;
823 if (~T1 & (~T1 ^ T0) & (1 << 31)) {
834 /* substract from zero extended */
851 if ((~T1 ^ (-1)) & ((~T1) ^ T0) & (1 << 31)) {
865 /*** Integer comparison ***/
871 } else if (Ts0 > Ts1) {
879 /* compare immediate */
882 if (Ts0 < SPARAM(1)) {
884 } else if (Ts0 > SPARAM(1)) {
892 /* compare logical */
897 } else if (T0 > T1) {
905 /* compare logical immediate */
910 } else if (T0 > PARAM(1)) {
918 /*** Integer logical ***/
940 /* count leading zero */
944 for (T0 = 32; T1 > 0; T0--)
956 /* extend sign byte */
963 /* extend sign half word */
1019 /*** Integer rotate ***/
1020 /* rotate left word immediate then mask insert */
1023 T0 = (rotl(T0, PARAM(1)) & PARAM(2)) | (T1 & PARAM(3));
1027 /* rotate left immediate then and with mask insert */
1030 T0 = rotl(T0, PARAM(1));
1036 T0 = T0 << PARAM(1);
1042 T0 = T0 >> PARAM(1);
1046 /* rotate left word then and with mask insert */
1049 T0 = rotl(T0, PARAM(1)) & PARAM(2);
1061 T0 = rotl(T0, T1) & PARAM(1);
1065 /*** Integer shift ***/
1066 /* shift left word */
1077 /* shift right algebraic word */
1080 Ts0 = do_sraw(Ts0, T1);
1084 /* shift right algebraic word immediate */
1088 Ts0 = Ts0 >> PARAM(1);
1089 if (Ts1 < 0 && (Ts1 & PARAM(2)) != 0) {
1097 /* shift right word */
1108 /*** Floating-Point arithmetic ***/
1110 /*** Floating-Point multiply-and-add ***/
1112 /*** Floating-Point round & convert ***/
1114 /*** Floating-Point compare ***/
1116 /*** Floating-Point status & ctrl register ***/
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) \
1126 PPC_OP(l##name##x) \
1133 #define PPC_ILD_OP(name, op) \
1134 PPC_OP(l##name##_z) \
1136 T1 = op(SPARAM(1)); \
1145 PPC_ILD_OPX(name, op)
1147 PPC_ILD_OP(bz, ld8);
1148 PPC_ILD_OP(ha, ld16x);
1149 PPC_ILD_OP(hz, ld16);
1150 PPC_ILD_OP(wz, ld32);
1152 /*** Integer store ***/
1153 #define PPC_IST_OPX(name, op) \
1154 PPC_OP(st##name##x_z) \
1159 PPC_OP(st##name##x) \
1166 #define PPC_IST_OP(name, op) \
1167 PPC_OP(st##name##_z) \
1169 op(SPARAM(1), T0); \
1178 PPC_IST_OPX(name, op);
1181 PPC_IST_OP(h, st16);
1182 PPC_IST_OP(w, st32);
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);
1190 /*** Integer load and store multiple ***/
1193 do_lmw(PARAM(1), SPARAM(2) + T0);
1199 do_stmw(PARAM(1), SPARAM(2) + T0);
1203 /*** Integer load and store strings ***/
1206 do_lsw(PARAM(1), PARAM(2), T0);
1212 do_lsw(PARAM(1), T0, T1 + T2);
1218 do_stsw(PARAM(1), PARAM(2), 0);
1224 do_stsw(PARAM(1), PARAM(2), T0);
1230 do_stsw(PARAM(1), T0, T1);
1236 do_stsw(PARAM(1), T0, T1 + T2);
1243 T0 = regs->spr[PARAM(1)];
1248 regs->spr[PARAM(1)] = T0;
1251 /*** Floating-point store ***/
1255 stfq((void *)SPARAM(1), FT0);
1261 stfq((void *)T0, FT0);
1266 stfq((void *)T0, FT0);
1272 stfq((void *)T0, FT0);
1278 stfl((void *)SPARAM(1), tmp);
1285 stfl((void *)T0, tmp);
1291 stfl((void *)T0, tmp);
1298 stfl((void *)T0, tmp);
1301 /*** Floating-point load ***/
1304 FT0 = ldfq((void *)SPARAM(1));
1310 FT0 = ldfq((void *)T0);
1315 FT0 = ldfq((void *)T0);
1321 FT0 = ldfq((void *)T0);
1326 float tmp = ldfl((void *)SPARAM(1));
1334 tmp = ldfl((void *)T0);
1341 tmp = ldfl((void *)T0);
1349 tmp = ldfl((void *)T0);
1370 if (regs->reserve != T0) {
1371 env->crf[0] = xer_ov;
1374 env->crf[0] = xer_ov | 0x02;
1383 if (regs->reserve != (T0 & ~0x03)) {
1384 env->crf[0] = xer_ov;
1387 env->crf[0] = xer_ov | 0x02;
1406 /* Instruction cache block invalidate */