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(queue_exception_err)
213 do_queue_exception_err(PARAM(1), PARAM(2));
216 PPC_OP(queue_exception)
218 do_queue_exception(PARAM(1));
221 PPC_OP(process_exceptions)
224 if (env->exceptions != 0) {
225 do_check_exception_state();
233 #if defined (DEBUG_OP)
236 do_queue_exception(EXCP_DEBUG);
240 /* Segment registers load and store with immediate index */
243 T0 = regs->sr[T1 >> 28];
249 #if defined (DEBUG_OP)
250 dump_store_sr(T1 >> 28);
252 regs->sr[T1 >> 28] = T0;
273 /* Load/store special registers */
282 do_store_cr(PARAM(1));
288 T0 = (xer_so << 3) | (xer_ov << 2) | (xer_ca << 1);
333 T0 = regs->spr[PARAM(1)];
339 regs->spr[PARAM(1)] = T0;
367 /* Update time base */
373 #if defined (DEBUG_OP)
374 dump_update_tb(PARAM(1));
377 T1 = regs->tb[1] + 1;
386 T0 = regs->tb[PARAM(1)];
392 regs->tb[PARAM(1)] = T0;
393 #if defined (DEBUG_OP)
394 dump_store_tb(PARAM(1));
399 /* Update decrementer */
407 do_queue_exception(EXCP_DECR);
416 if (Ts0 < 0 && Ts1 > 0) {
417 do_queue_exception(EXCP_DECR);
424 T0 = regs->IBAT[PARAM(1)][PARAM(2)];
429 #if defined (DEBUG_OP)
430 dump_store_ibat(PARAM(1), PARAM(2));
432 regs->IBAT[PARAM(1)][PARAM(2)] = T0;
437 T0 = regs->DBAT[PARAM(1)][PARAM(2)];
442 #if defined (DEBUG_OP)
443 dump_store_dbat(PARAM(1), PARAM(2));
445 regs->DBAT[PARAM(1)][PARAM(2)] = T0;
457 do_store_fpscr(PARAM(1));
463 regs->fpscr[7] &= ~0x8;
470 T0 = (T0 >> PARAM(1)) & 1;
476 T1 = (T1 >> PARAM(1)) & 1;
482 T1 = (T1 & PARAM(1)) | (T0 << PARAM(2));
487 #define EIP regs->nip
496 JUMP_TB(b1, PARAM1, 0, PARAM2);
507 JUMP_TB(btest, PARAM1, 0, PARAM2);
509 JUMP_TB(btest, PARAM1, 1, PARAM3);
534 /* tests with result in T0 */
541 PPC_OP(test_ctr_true)
543 T0 = (regs->ctr != 0 && (T0 & PARAM(1)) != 0);
546 PPC_OP(test_ctr_false)
548 T0 = (regs->ctr != 0 && (T0 & PARAM(1)) == 0);
553 T0 = (regs->ctr == 0);
556 PPC_OP(test_ctrz_true)
558 T0 = (regs->ctr == 0 && (T0 & PARAM(1)) != 0);
561 PPC_OP(test_ctrz_false)
563 T0 = (regs->ctr == 0 && (T0 & PARAM(1)) == 0);
568 T0 = (T0 & PARAM(1));
573 T0 = ((T0 & PARAM(1)) == 0);
576 /* CTR maintenance */
583 /*** Integer arithmetic ***/
595 if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
626 if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
636 /* candidate for helper (too long) */
641 if (T0 < T2 || (xer_ca == 1 && T0 == T2)) {
653 if (T0 < T2 || (xer_ca == 1 && T0 == T2)) {
658 if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
674 /* add immediate carrying */
687 /* add to minus one extended */
701 if (T1 & (T1 ^ T0) & (1 << 31)) {
712 /* add to zero extended */
729 if ((T1 ^ (-1)) & (T1 ^ T0) & (1 << 31)) {
744 /* candidate for helper (too long) */
747 if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
748 Ts0 = (-1) * (T0 >> 31);
757 if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
760 T0 = (-1) * (T0 >> 31);
768 /* divide word unsigned */
792 /* multiply high word */
795 Ts0 = ((int64_t)Ts0 * (int64_t)Ts1) >> 32;
799 /* multiply high word unsigned */
802 T0 = ((uint64_t)T0 * (uint64_t)T1) >> 32;
806 /* multiply low immediate */
813 /* multiply low word */
822 int64_t res = (int64_t)Ts0 * (int64_t)Ts1;
824 if ((int32_t)res != res) {
837 if (T0 != 0x80000000) {
845 if (T0 == 0x80000000) {
866 if (((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)) {
875 /* substract from carrying */
896 if (((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)) {
905 /* substract from extended */
906 /* candidate for helper (too long) */
909 T0 = T1 + ~T0 + xer_ca;
910 if (T0 < T1 || (xer_ca == 1 && T0 == T1)) {
921 T0 = T1 + ~T0 + xer_ca;
922 if ((~T2 ^ T1 ^ (-1)) & (~T2 ^ T0) & (1 << 31)) {
928 if (T0 < T1 || (xer_ca == 1 && T0 == T1)) {
936 /* substract from immediate carrying */
939 T0 = PARAM(1) + ~T0 + 1;
940 if (T0 <= PARAM(1)) {
948 /* substract from minus one extended */
951 T0 = ~T0 + xer_ca - 1;
961 T0 = ~T0 + xer_ca - 1;
962 if (~T1 & (~T1 ^ T0) & (1 << 31)) {
973 /* substract from zero extended */
990 if ((~T1 ^ (-1)) & ((~T1) ^ T0) & (1 << 31)) {
1004 /*** Integer comparison ***/
1010 } else if (Ts0 > Ts1) {
1018 /* compare immediate */
1021 if (Ts0 < SPARAM(1)) {
1023 } else if (Ts0 > SPARAM(1)) {
1031 /* compare logical */
1036 } else if (T0 > T1) {
1044 /* compare logical immediate */
1047 if (T0 < PARAM(1)) {
1049 } else if (T0 > PARAM(1)) {
1057 /*** Integer logical ***/
1079 /* count leading zero */
1083 for (T0 = 32; T1 > 0; T0--)
1095 /* extend sign byte */
1102 /* extend sign half word */
1158 /*** Integer rotate ***/
1159 /* rotate left word immediate then mask insert */
1162 T0 = (rotl(T0, PARAM(1)) & PARAM(2)) | (T1 & PARAM(3));
1166 /* rotate left immediate then and with mask insert */
1169 T0 = rotl(T0, PARAM(1));
1175 T0 = T0 << PARAM(1);
1181 T0 = T0 >> PARAM(1);
1185 /* rotate left word then and with mask insert */
1188 T0 = rotl(T0, PARAM(1)) & PARAM(2);
1200 T0 = rotl(T0, T1) & PARAM(1);
1204 /*** Integer shift ***/
1205 /* shift left word */
1216 /* shift right algebraic word */
1223 /* shift right algebraic word immediate */
1227 Ts0 = Ts0 >> PARAM(1);
1228 if (Ts1 < 0 && (Ts1 & PARAM(2)) != 0) {
1236 /* shift right word */
1247 /*** Floating-Point arithmetic ***/
1255 /* fadds - fadds. */
1269 /* fsubs - fsubs. */
1283 /* fmuls - fmuls. */
1297 /* fdivs - fdivs. */
1304 /* fsqrt - fsqrt. */
1311 /* fsqrts - fsqrts. */
1325 /* frsqrte - frsqrte. */
1339 /*** Floating-Point multiply-and-add ***/
1340 /* fmadd - fmadd. */
1343 FT0 = (FT0 * FT1) + FT2;
1347 /* fmadds - fmadds. */
1350 FTS0 = (FTS0 * FTS1) + FTS2;
1354 /* fmsub - fmsub. */
1357 FT0 = (FT0 * FT1) - FT2;
1361 /* fmsubs - fmsubs. */
1364 FTS0 = (FTS0 * FTS1) - FTS2;
1368 /* fnmadd - fnmadd. - fnmadds - fnmadds. */
1377 /* fnmadds - fnmadds. */
1384 /* fnmsub - fnmsub. */
1393 /* fnmsubs - fnmsubs. */
1400 /*** Floating-Point round & convert ***/
1408 /* fctiw - fctiw. */
1415 /* fctiwz - fctiwz. */
1423 /*** Floating-Point compare ***/
1438 /*** Floating-point move ***/
1460 /* Load and store */
1461 #define MEMSUFFIX _raw
1463 #if !defined(CONFIG_USER_ONLY)
1464 #define MEMSUFFIX _user
1467 #define MEMSUFFIX _kernel
1471 /* Return from interrupt */
1474 T0 = regs->spr[SRR1] & ~0xFFFF0000;
1477 #if defined (DEBUG_OP)
1480 regs->nip = regs->spr[SRR0] & ~0x00000003;
1481 do_queue_exception(EXCP_RFI);
1482 if (env->exceptions != 0) {
1483 do_check_exception_state();
1491 if ((Ts0 < Ts1 && (PARAM(1) & 0x10)) ||
1492 (Ts0 > Ts1 && (PARAM(1) & 0x08)) ||
1493 (Ts0 == Ts1 && (PARAM(1) & 0x04)) ||
1494 (T0 < T1 && (PARAM(1) & 0x02)) ||
1495 (T0 > T1 && (PARAM(1) & 0x01)))
1496 do_queue_exception_err(EXCP_PROGRAM, EXCP_TRAP);
1502 if ((Ts0 < SPARAM(1) && (PARAM(2) & 0x10)) ||
1503 (Ts0 > SPARAM(1) && (PARAM(2) & 0x08)) ||
1504 (Ts0 == SPARAM(1) && (PARAM(2) & 0x04)) ||
1505 (T0 < (uint32_t)SPARAM(1) && (PARAM(2) & 0x02)) ||
1506 (T0 > (uint32_t)SPARAM(1) && (PARAM(2) & 0x01)))
1507 do_queue_exception_err(EXCP_PROGRAM, EXCP_TRAP);
1511 /* Instruction cache block invalidate */