2 * PowerPC emulation micro-operations for qemu.
4 * Copyright (c) 2003-2005 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 /* PowerPC 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));
207 /* Segment registers load and store with immediate index */
210 T0 = regs->sr[T1 >> 28];
216 do_store_sr(env, ((uint32_t)T1 >> 28), T0);
228 do_store_sdr1(env, T0);
237 /* Load/store special registers */
240 T0 = do_load_cr(env);
246 do_store_cr(env, T0, PARAM(1));
252 T0 = (xer_so << 3) | (xer_ov << 2) | (xer_ca << 1);
272 T0 = do_load_xer(env);
278 do_store_xer(env, T0);
284 T0 = do_load_msr(env);
290 do_store_msr(env, T0);
297 T0 = regs->spr[PARAM(1)];
303 regs->spr[PARAM(1)] = T0;
333 T0 = cpu_ppc_load_tbl(regs);
339 T0 = cpu_ppc_load_tbu(regs);
345 cpu_ppc_store_tbl(regs, T0);
351 cpu_ppc_store_tbu(regs, T0);
357 T0 = cpu_ppc_load_decr(regs);
362 cpu_ppc_store_decr(regs, T0);
368 T0 = regs->IBAT[PARAM(1)][PARAM(2)];
371 void op_store_ibatu (void)
373 do_store_ibatu(env, PARAM1, T0);
377 void op_store_ibatl (void)
380 env->IBAT[1][PARAM1] = T0;
382 do_store_ibatl(env, PARAM1, T0);
389 T0 = regs->DBAT[PARAM(1)][PARAM(2)];
392 void op_store_dbatu (void)
394 do_store_dbatu(env, PARAM1, T0);
398 void op_store_dbatl (void)
401 env->DBAT[1][PARAM1] = T0;
403 do_store_dbatl(env, PARAM1, T0);
411 FT0 = do_load_fpscr(env);
417 do_store_fpscr(env, FT0, PARAM1);
423 regs->fpscr[7] &= ~0x8;
430 T0 = (T0 >> PARAM(1)) & 1;
436 T1 = (T1 >> PARAM(1)) & 1;
442 T1 = (T1 & PARAM(1)) | (T0 << PARAM(2));
447 #define EIP regs->nip
456 GOTO_TB(op_goto_tb0, PARAM1, 0);
461 GOTO_TB(op_goto_tb1, PARAM1, 1);
496 /* tests with result in T0 */
503 PPC_OP(test_ctr_true)
505 T0 = (regs->ctr != 0 && (T0 & PARAM(1)) != 0);
508 PPC_OP(test_ctr_false)
510 T0 = (regs->ctr != 0 && (T0 & PARAM(1)) == 0);
515 T0 = (regs->ctr == 0);
518 PPC_OP(test_ctrz_true)
520 T0 = (regs->ctr == 0 && (T0 & PARAM(1)) != 0);
523 PPC_OP(test_ctrz_false)
525 T0 = (regs->ctr == 0 && (T0 & PARAM(1)) == 0);
530 T0 = (T0 & PARAM(1));
535 T0 = ((T0 & PARAM(1)) == 0);
538 /* CTR maintenance */
545 /*** Integer arithmetic ***/
573 void do_addco (void);
587 void do_addeo (void);
601 /* add immediate carrying */
614 /* add to minus one extended */
624 void do_addmeo (void);
625 void op_addmeo (void)
631 /* add to zero extended */
644 void do_addzeo (void);
645 void op_addzeo (void)
654 if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
655 T0 = (int32_t)((-1) * (T0 >> 31));
662 void do_divwo (void);
669 /* divide word unsigned */
680 void do_divwuo (void);
681 void op_divwuo (void)
687 /* multiply high word */
690 T0 = ((int64_t)Ts0 * (int64_t)Ts1) >> 32;
694 /* multiply high word unsigned */
697 T0 = ((uint64_t)T0 * (uint64_t)T1) >> 32;
701 /* multiply low immediate */
704 T0 = (Ts0 * SPARAM(1));
708 /* multiply low word */
715 void do_mullwo (void);
716 void op_mullwo (void)
725 if (T0 != 0x80000000) {
745 void do_subfo (void);
752 /* substract from carrying */
764 void do_subfco (void);
765 void op_subfco (void)
771 /* substract from extended */
772 void do_subfe (void);
779 void do_subfeo (void);
786 /* substract from immediate carrying */
789 T0 = PARAM(1) + ~T0 + 1;
790 if (T0 <= PARAM(1)) {
798 /* substract from minus one extended */
801 T0 = ~T0 + xer_ca - 1;
808 void do_subfmeo (void);
809 void op_subfmeo (void)
815 /* substract from zero extended */
828 void do_subfzeo (void);
829 void op_subfzeo (void)
835 /*** Integer comparison ***/
841 } else if (Ts0 > Ts1) {
849 /* compare immediate */
852 if (Ts0 < SPARAM(1)) {
854 } else if (Ts0 > SPARAM(1)) {
862 /* compare logical */
867 } else if (T0 > T1) {
875 /* compare logical immediate */
880 } else if (T0 > PARAM(1)) {
888 /*** Integer logical ***/
910 /* count leading zero */
914 for (T0 = 32; T1 > 0; T0--)
926 /* extend sign byte */
929 T0 = (int32_t)((int8_t)(Ts0));
933 /* extend sign half word */
936 T0 = (int32_t)((int16_t)(Ts0));
989 /*** Integer rotate ***/
990 /* rotate left word immediate then mask insert */
993 T0 = (rotl(T0, PARAM(1)) & PARAM(2)) | (T1 & PARAM(3));
997 /* rotate left immediate then and with mask insert */
1000 T0 = rotl(T0, PARAM(1));
1006 T0 = T0 << PARAM(1);
1012 T0 = T0 >> PARAM(1);
1016 /* rotate left word then and with mask insert */
1019 T0 = rotl(T0, PARAM(1)) & PARAM(2);
1031 T0 = rotl(T0, T1) & PARAM(1);
1035 /*** Integer shift ***/
1036 /* shift left word */
1047 /* shift right algebraic word */
1054 /* shift right algebraic word immediate */
1058 T0 = (Ts0 >> PARAM(1));
1059 if (Ts1 < 0 && (Ts1 & PARAM(2)) != 0) {
1067 /* shift right word */
1078 /*** Floating-Point arithmetic ***/
1103 FT0 = float64_div(FT0, FT1, &env->fp_status);
1107 /* fsqrt - fsqrt. */
1121 /* frsqrte - frsqrte. */
1135 /*** Floating-Point multiply-and-add ***/
1136 /* fmadd - fmadd. */
1139 FT0 = (FT0 * FT1) + FT2;
1143 /* fmsub - fmsub. */
1146 FT0 = (FT0 * FT1) - FT2;
1150 /* fnmadd - fnmadd. - fnmadds - fnmadds. */
1157 /* fnmsub - fnmsub. */
1164 /*** Floating-Point round & convert ***/
1172 /* fctiw - fctiw. */
1179 /* fctiwz - fctiwz. */
1187 /*** Floating-Point compare ***/
1202 /*** Floating-point move ***/
1206 FT0 = float64_abs(FT0);
1213 FT0 = float64_abs(FT0);
1214 FT0 = float64_chs(FT0);
1221 FT0 = float64_chs(FT0);
1225 /* Load and store */
1226 #define MEMSUFFIX _raw
1228 #if !defined(CONFIG_USER_ONLY)
1229 #define MEMSUFFIX _user
1232 #define MEMSUFFIX _kernel
1236 /* Special op to check and maybe clear reservation */
1237 PPC_OP(check_reservation)
1239 if ((uint32_t)env->reserve == (uint32_t)(T0 & ~0x00000003))
1244 /* Return from interrupt */
1253 void do_tw (uint32_t cmp, int flags);
1256 do_tw(T1, PARAM(1));
1262 do_tw(PARAM(1), PARAM(2));
1266 /* Instruction cache block invalidate */
1287 void op_store_pir (void)
1289 env->spr[SPR_PIR] = T0 & 0x0000000FUL;