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
27 #define Ts0 (int32_t)T0
28 #define Ts1 (int32_t)T1
29 #define Ts2 (int32_t)T2
31 #define FT0 (env->ft0)
32 #define FT1 (env->ft1)
33 #define FT2 (env->ft2)
35 #define FTS0 ((float)env->ft0)
36 #define FTS1 ((float)env->ft1)
37 #define FTS2 ((float)env->ft2)
39 #define PPC_OP(name) void glue(op_, name)(void)
42 #include "op_template.h"
45 #include "op_template.h"
48 #include "op_template.h"
51 #include "op_template.h"
54 #include "op_template.h"
57 #include "op_template.h"
60 #include "op_template.h"
63 #include "op_template.h"
66 #include "op_template.h"
69 #include "op_template.h"
72 #include "op_template.h"
75 #include "op_template.h"
78 #include "op_template.h"
81 #include "op_template.h"
84 #include "op_template.h"
87 #include "op_template.h"
90 #include "op_template.h"
93 #include "op_template.h"
96 #include "op_template.h"
99 #include "op_template.h"
102 #include "op_template.h"
105 #include "op_template.h"
108 #include "op_template.h"
111 #include "op_template.h"
114 #include "op_template.h"
117 #include "op_template.h"
120 #include "op_template.h"
123 #include "op_template.h"
126 #include "op_template.h"
129 #include "op_template.h"
132 #include "op_template.h"
135 #include "op_template.h"
137 /* PPC state maintenance operations */
145 } else if (Ts0 > 0) {
160 } else if (Ts0 > 0) {
173 env->crf[0] = 0x02 | xer_ov;
180 env->crf[0] = 0x04 | xer_ov;
184 /* Set Rc1 (for floating point arithmetic) */
187 env->crf[1] = regs->fpscr[7];
210 /* Generate exceptions */
211 PPC_OP(raise_exception_err)
213 do_raise_exception_err(PARAM(1), PARAM(2));
216 PPC_OP(raise_exception)
218 do_raise_exception(PARAM(1));
229 #if defined (DEBUG_OP)
232 do_raise_exception(EXCP_DEBUG);
236 /* Segment registers load and store with immediate index */
239 T0 = regs->sr[T1 >> 28];
245 #if defined (DEBUG_OP)
246 dump_store_sr(T1 >> 28);
248 regs->sr[T1 >> 28] = T0;
269 /* Load/store special registers */
278 do_store_cr(PARAM(1));
284 T0 = (xer_so << 3) | (xer_ov << 2) | (xer_ca << 1);
329 T0 = regs->spr[PARAM(1)];
335 regs->spr[PARAM(1)] = T0;
365 T0 = cpu_ppc_load_tbl(regs);
371 T0 = cpu_ppc_load_tbu(regs);
377 cpu_ppc_store_tbl(regs, T0);
383 cpu_ppc_store_tbu(regs, T0);
389 T0 = cpu_ppc_load_decr(regs);
394 cpu_ppc_store_decr(regs, T0);
400 T0 = regs->IBAT[PARAM(1)][PARAM(2)];
405 #if defined (DEBUG_OP)
406 dump_store_ibat(PARAM(1), PARAM(2));
408 regs->IBAT[PARAM(1)][PARAM(2)] = T0;
413 T0 = regs->DBAT[PARAM(1)][PARAM(2)];
418 #if defined (DEBUG_OP)
419 dump_store_dbat(PARAM(1), PARAM(2));
421 regs->DBAT[PARAM(1)][PARAM(2)] = T0;
433 do_store_fpscr(PARAM(1));
439 regs->fpscr[7] &= ~0x8;
446 T0 = (T0 >> PARAM(1)) & 1;
452 T1 = (T1 >> PARAM(1)) & 1;
458 T1 = (T1 & PARAM(1)) | (T0 << PARAM(2));
463 #define EIP regs->nip
472 JUMP_TB(b1, PARAM1, 0, PARAM2);
483 JUMP_TB(btest, PARAM1, 0, PARAM2);
485 JUMP_TB(btest, PARAM1, 1, PARAM3);
510 /* tests with result in T0 */
517 PPC_OP(test_ctr_true)
519 T0 = (regs->ctr != 0 && (T0 & PARAM(1)) != 0);
522 PPC_OP(test_ctr_false)
524 T0 = (regs->ctr != 0 && (T0 & PARAM(1)) == 0);
529 T0 = (regs->ctr == 0);
532 PPC_OP(test_ctrz_true)
534 T0 = (regs->ctr == 0 && (T0 & PARAM(1)) != 0);
537 PPC_OP(test_ctrz_false)
539 T0 = (regs->ctr == 0 && (T0 & PARAM(1)) == 0);
544 T0 = (T0 & PARAM(1));
549 T0 = ((T0 & PARAM(1)) == 0);
552 /* CTR maintenance */
559 /*** Integer arithmetic ***/
571 if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
602 if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
612 /* candidate for helper (too long) */
617 if (T0 < T2 || (xer_ca == 1 && T0 == T2)) {
629 if (T0 < T2 || (xer_ca == 1 && T0 == T2)) {
634 if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
650 /* add immediate carrying */
663 /* add to minus one extended */
677 if (T1 & (T1 ^ T0) & (1 << 31)) {
688 /* add to zero extended */
705 if ((T1 ^ (-1)) & (T1 ^ T0) & (1 << 31)) {
720 /* candidate for helper (too long) */
723 if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
724 Ts0 = (-1) * (T0 >> 31);
733 if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
736 T0 = (-1) * (T0 >> 31);
744 /* divide word unsigned */
768 /* multiply high word */
771 Ts0 = ((int64_t)Ts0 * (int64_t)Ts1) >> 32;
775 /* multiply high word unsigned */
778 T0 = ((uint64_t)T0 * (uint64_t)T1) >> 32;
782 /* multiply low immediate */
789 /* multiply low word */
798 int64_t res = (int64_t)Ts0 * (int64_t)Ts1;
800 if ((int32_t)res != res) {
813 if (T0 != 0x80000000) {
821 if (T0 == 0x80000000) {
842 if (((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)) {
851 /* substract from carrying */
872 if (((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)) {
881 /* substract from extended */
882 /* candidate for helper (too long) */
885 T0 = T1 + ~T0 + xer_ca;
886 if (T0 < T1 || (xer_ca == 1 && T0 == T1)) {
897 T0 = T1 + ~T0 + xer_ca;
898 if ((~T2 ^ T1 ^ (-1)) & (~T2 ^ T0) & (1 << 31)) {
904 if (T0 < T1 || (xer_ca == 1 && T0 == T1)) {
912 /* substract from immediate carrying */
915 T0 = PARAM(1) + ~T0 + 1;
916 if (T0 <= PARAM(1)) {
924 /* substract from minus one extended */
927 T0 = ~T0 + xer_ca - 1;
937 T0 = ~T0 + xer_ca - 1;
938 if (~T1 & (~T1 ^ T0) & (1 << 31)) {
949 /* substract from zero extended */
966 if ((~T1 ^ (-1)) & ((~T1) ^ T0) & (1 << 31)) {
980 /*** Integer comparison ***/
986 } else if (Ts0 > Ts1) {
994 /* compare immediate */
997 if (Ts0 < SPARAM(1)) {
999 } else if (Ts0 > SPARAM(1)) {
1007 /* compare logical */
1012 } else if (T0 > T1) {
1020 /* compare logical immediate */
1023 if (T0 < PARAM(1)) {
1025 } else if (T0 > PARAM(1)) {
1033 /*** Integer logical ***/
1055 /* count leading zero */
1059 for (T0 = 32; T1 > 0; T0--)
1071 /* extend sign byte */
1078 /* extend sign half word */
1134 /*** Integer rotate ***/
1135 /* rotate left word immediate then mask insert */
1138 T0 = (rotl(T0, PARAM(1)) & PARAM(2)) | (T1 & PARAM(3));
1142 /* rotate left immediate then and with mask insert */
1145 T0 = rotl(T0, PARAM(1));
1151 T0 = T0 << PARAM(1);
1157 T0 = T0 >> PARAM(1);
1161 /* rotate left word then and with mask insert */
1164 T0 = rotl(T0, PARAM(1)) & PARAM(2);
1176 T0 = rotl(T0, T1) & PARAM(1);
1180 /*** Integer shift ***/
1181 /* shift left word */
1192 /* shift right algebraic word */
1199 /* shift right algebraic word immediate */
1203 Ts0 = Ts0 >> PARAM(1);
1204 if (Ts1 < 0 && (Ts1 & PARAM(2)) != 0) {
1212 /* shift right word */
1223 /*** Floating-Point arithmetic ***/
1231 /* fadds - fadds. */
1245 /* fsubs - fsubs. */
1259 /* fmuls - fmuls. */
1273 /* fdivs - fdivs. */
1280 /* fsqrt - fsqrt. */
1287 /* fsqrts - fsqrts. */
1301 /* frsqrte - frsqrte. */
1315 /*** Floating-Point multiply-and-add ***/
1316 /* fmadd - fmadd. */
1319 FT0 = (FT0 * FT1) + FT2;
1323 /* fmadds - fmadds. */
1326 FTS0 = (FTS0 * FTS1) + FTS2;
1330 /* fmsub - fmsub. */
1333 FT0 = (FT0 * FT1) - FT2;
1337 /* fmsubs - fmsubs. */
1340 FTS0 = (FTS0 * FTS1) - FTS2;
1344 /* fnmadd - fnmadd. - fnmadds - fnmadds. */
1353 /* fnmadds - fnmadds. */
1360 /* fnmsub - fnmsub. */
1369 /* fnmsubs - fnmsubs. */
1376 /*** Floating-Point round & convert ***/
1384 /* fctiw - fctiw. */
1391 /* fctiwz - fctiwz. */
1399 /*** Floating-Point compare ***/
1414 /*** Floating-point move ***/
1436 /* Load and store */
1437 #define MEMSUFFIX _raw
1439 #if !defined(CONFIG_USER_ONLY)
1440 #define MEMSUFFIX _user
1443 #define MEMSUFFIX _kernel
1447 /* Return from interrupt */
1450 regs->nip = regs->spr[SRR0] & ~0x00000003;
1451 T0 = regs->spr[SRR1] & ~0xFFFF0000;
1453 #if defined (DEBUG_OP)
1457 do_raise_exception(EXCP_RFI);
1464 if ((Ts0 < Ts1 && (PARAM(1) & 0x10)) ||
1465 (Ts0 > Ts1 && (PARAM(1) & 0x08)) ||
1466 (Ts0 == Ts1 && (PARAM(1) & 0x04)) ||
1467 (T0 < T1 && (PARAM(1) & 0x02)) ||
1468 (T0 > T1 && (PARAM(1) & 0x01)))
1469 do_raise_exception_err(EXCP_PROGRAM, EXCP_TRAP);
1475 if ((Ts0 < SPARAM(1) && (PARAM(2) & 0x10)) ||
1476 (Ts0 > SPARAM(1) && (PARAM(2) & 0x08)) ||
1477 (Ts0 == SPARAM(1) && (PARAM(2) & 0x04)) ||
1478 (T0 < (uint32_t)SPARAM(1) && (PARAM(2) & 0x02)) ||
1479 (T0 > (uint32_t)SPARAM(1) && (PARAM(2) & 0x01)))
1480 do_raise_exception_err(EXCP_PROGRAM, EXCP_TRAP);
1484 /* Instruction cache block invalidate */