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 PPC_OP(name) void glue(op_, name)(void)
38 #include "op_template.h"
41 #include "op_template.h"
44 #include "op_template.h"
47 #include "op_template.h"
50 #include "op_template.h"
53 #include "op_template.h"
56 #include "op_template.h"
59 #include "op_template.h"
62 #include "op_template.h"
65 #include "op_template.h"
68 #include "op_template.h"
71 #include "op_template.h"
74 #include "op_template.h"
77 #include "op_template.h"
80 #include "op_template.h"
83 #include "op_template.h"
86 #include "op_template.h"
89 #include "op_template.h"
92 #include "op_template.h"
95 #include "op_template.h"
98 #include "op_template.h"
101 #include "op_template.h"
104 #include "op_template.h"
107 #include "op_template.h"
110 #include "op_template.h"
113 #include "op_template.h"
116 #include "op_template.h"
119 #include "op_template.h"
122 #include "op_template.h"
125 #include "op_template.h"
128 #include "op_template.h"
131 #include "op_template.h"
133 /* PPC state maintenance operations */
141 } else if (Ts0 > 0) {
154 env->crf[0] = 0x02 | xer_ov;
161 env->crf[0] = 0x04 | xer_ov;
165 /* Set Rc1 (for floating point arithmetic) */
168 env->crf[1] = regs->fpscr[7];
191 /* Generate exceptions */
192 PPC_OP(raise_exception_err)
194 do_raise_exception_err(PARAM(1), PARAM(2));
197 PPC_OP(raise_exception)
199 do_raise_exception(PARAM(1));
210 #if defined (DEBUG_OP)
213 do_raise_exception(EXCP_DEBUG);
217 /* Segment registers load and store with immediate index */
220 T0 = regs->sr[T1 >> 28];
226 do_store_sr(T1 >> 28);
247 /* Load/store special registers */
256 do_store_cr(PARAM(1));
262 T0 = (xer_so << 3) | (xer_ov << 2) | (xer_ca << 1);
307 T0 = regs->spr[PARAM(1)];
313 regs->spr[PARAM(1)] = T0;
343 T0 = cpu_ppc_load_tbl(regs);
349 T0 = cpu_ppc_load_tbu(regs);
355 cpu_ppc_store_tbl(regs, T0);
361 cpu_ppc_store_tbu(regs, T0);
367 T0 = cpu_ppc_load_decr(regs);
372 cpu_ppc_store_decr(regs, T0);
378 T0 = regs->IBAT[PARAM(1)][PARAM(2)];
383 do_store_ibat(PARAM(1), PARAM(2));
388 T0 = regs->DBAT[PARAM(1)][PARAM(2)];
393 do_store_dbat(PARAM(1), PARAM(2));
405 do_store_fpscr(PARAM(1));
411 regs->fpscr[7] &= ~0x8;
418 T0 = (T0 >> PARAM(1)) & 1;
424 T1 = (T1 >> PARAM(1)) & 1;
430 T1 = (T1 & PARAM(1)) | (T0 << PARAM(2));
435 #define EIP regs->nip
444 JUMP_TB(b1, PARAM1, 0, PARAM2);
455 JUMP_TB(btest, PARAM1, 0, PARAM2);
457 JUMP_TB(btest, PARAM1, 1, PARAM3);
482 /* tests with result in T0 */
489 PPC_OP(test_ctr_true)
491 T0 = (regs->ctr != 0 && (T0 & PARAM(1)) != 0);
494 PPC_OP(test_ctr_false)
496 T0 = (regs->ctr != 0 && (T0 & PARAM(1)) == 0);
501 T0 = (regs->ctr == 0);
504 PPC_OP(test_ctrz_true)
506 T0 = (regs->ctr == 0 && (T0 & PARAM(1)) != 0);
509 PPC_OP(test_ctrz_false)
511 T0 = (regs->ctr == 0 && (T0 & PARAM(1)) == 0);
516 T0 = (T0 & PARAM(1));
521 T0 = ((T0 & PARAM(1)) == 0);
524 /* CTR maintenance */
531 /*** Integer arithmetic ***/
543 if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
574 if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
584 /* candidate for helper (too long) */
589 if (T0 < T2 || (xer_ca == 1 && T0 == T2)) {
601 if (T0 < T2 || (xer_ca == 1 && T0 == T2)) {
606 if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
622 /* add immediate carrying */
635 /* add to minus one extended */
649 if (T1 & (T1 ^ T0) & (1 << 31)) {
660 /* add to zero extended */
677 if ((T1 ^ (-1)) & (T1 ^ T0) & (1 << 31)) {
692 /* candidate for helper (too long) */
695 if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
696 T0 = (int32_t)((-1) * (T0 >> 31));
705 if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
708 T0 = (-1) * (T0 >> 31);
716 /* divide word unsigned */
740 /* multiply high word */
743 T0 = ((int64_t)Ts0 * (int64_t)Ts1) >> 32;
747 /* multiply high word unsigned */
750 T0 = ((uint64_t)T0 * (uint64_t)T1) >> 32;
754 /* multiply low immediate */
757 T0 = (Ts0 * SPARAM(1));
761 /* multiply low word */
770 int64_t res = (int64_t)Ts0 * (int64_t)Ts1;
772 if ((int32_t)res != res) {
785 if (T0 != 0x80000000) {
793 if (T0 == 0x80000000) {
814 if (((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)) {
823 /* substract from carrying */
844 if (((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)) {
853 /* substract from extended */
854 /* candidate for helper (too long) */
857 T0 = T1 + ~T0 + xer_ca;
858 if (T0 < T1 || (xer_ca == 1 && T0 == T1)) {
869 T0 = T1 + ~T0 + xer_ca;
870 if ((~T2 ^ T1 ^ (-1)) & (~T2 ^ T0) & (1 << 31)) {
876 if (T0 < T1 || (xer_ca == 1 && T0 == T1)) {
884 /* substract from immediate carrying */
887 T0 = PARAM(1) + ~T0 + 1;
888 if (T0 <= PARAM(1)) {
896 /* substract from minus one extended */
899 T0 = ~T0 + xer_ca - 1;
909 T0 = ~T0 + xer_ca - 1;
910 if (~T1 & (~T1 ^ T0) & (1 << 31)) {
921 /* substract from zero extended */
938 if ((~T1 ^ (-1)) & ((~T1) ^ T0) & (1 << 31)) {
952 /*** Integer comparison ***/
958 } else if (Ts0 > Ts1) {
966 /* compare immediate */
969 if (Ts0 < SPARAM(1)) {
971 } else if (Ts0 > SPARAM(1)) {
979 /* compare logical */
984 } else if (T0 > T1) {
992 /* compare logical immediate */
997 } else if (T0 > PARAM(1)) {
1005 /*** Integer logical ***/
1027 /* count leading zero */
1031 for (T0 = 32; T1 > 0; T0--)
1043 /* extend sign byte */
1046 T0 = (int32_t)((int8_t)(Ts0));
1050 /* extend sign half word */
1053 T0 = (int32_t)((int16_t)(Ts0));
1106 /*** Integer rotate ***/
1107 /* rotate left word immediate then mask insert */
1110 T0 = (rotl(T0, PARAM(1)) & PARAM(2)) | (T1 & PARAM(3));
1114 /* rotate left immediate then and with mask insert */
1117 T0 = rotl(T0, PARAM(1));
1123 T0 = T0 << PARAM(1);
1129 T0 = T0 >> PARAM(1);
1133 /* rotate left word then and with mask insert */
1136 T0 = rotl(T0, PARAM(1)) & PARAM(2);
1148 T0 = rotl(T0, T1) & PARAM(1);
1152 /*** Integer shift ***/
1153 /* shift left word */
1164 /* shift right algebraic word */
1171 /* shift right algebraic word immediate */
1175 T0 = (Ts0 >> PARAM(1));
1176 if (Ts1 < 0 && (Ts1 & PARAM(2)) != 0) {
1184 /* shift right word */
1195 /*** Floating-Point arithmetic ***/
1218 void do_fdiv (void);
1225 /* fsqrt - fsqrt. */
1239 /* frsqrte - frsqrte. */
1253 /*** Floating-Point multiply-and-add ***/
1254 /* fmadd - fmadd. */
1257 FT0 = (FT0 * FT1) + FT2;
1261 /* fmsub - fmsub. */
1264 FT0 = (FT0 * FT1) - FT2;
1268 /* fnmadd - fnmadd. - fnmadds - fnmadds. */
1275 /* fnmsub - fnmsub. */
1282 /*** Floating-Point round & convert ***/
1290 /* fctiw - fctiw. */
1297 /* fctiwz - fctiwz. */
1305 /*** Floating-Point compare ***/
1320 /*** Floating-point move ***/
1322 void do_fabs (void);
1330 void do_fnabs (void);
1344 /* Load and store */
1345 #define MEMSUFFIX _raw
1347 #if !defined(CONFIG_USER_ONLY)
1348 #define MEMSUFFIX _user
1351 #define MEMSUFFIX _kernel
1355 /* Special op to check and maybe clear reservation */
1356 PPC_OP(check_reservation)
1358 do_check_reservation();
1362 /* Return from interrupt */
1365 regs->nip = regs->spr[SRR0] & ~0x00000003;
1367 T0 = regs->spr[SRR1] & ~0xFFF00000;
1369 T0 = regs->spr[SRR1] & ~0xFFFF0000;
1372 #if defined (DEBUG_OP)
1376 do_raise_exception(EXCP_RFI);
1383 if ((Ts0 < Ts1 && (PARAM(1) & 0x10)) ||
1384 (Ts0 > Ts1 && (PARAM(1) & 0x08)) ||
1385 (Ts0 == Ts1 && (PARAM(1) & 0x04)) ||
1386 (T0 < T1 && (PARAM(1) & 0x02)) ||
1387 (T0 > T1 && (PARAM(1) & 0x01)))
1388 do_raise_exception_err(EXCP_PROGRAM, EXCP_TRAP);
1394 if ((Ts0 < SPARAM(1) && (PARAM(2) & 0x10)) ||
1395 (Ts0 > SPARAM(1) && (PARAM(2) & 0x08)) ||
1396 (Ts0 == SPARAM(1) && (PARAM(2) & 0x04)) ||
1397 (T0 < (uint32_t)SPARAM(1) && (PARAM(2) & 0x02)) ||
1398 (T0 > (uint32_t)SPARAM(1) && (PARAM(2) & 0x01)))
1399 do_raise_exception_err(EXCP_PROGRAM, EXCP_TRAP);
1403 /* Instruction cache block invalidate */