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) {
158 env
->crf
[0] = 0x02 | xer_ov
;
165 env
->crf
[0] = 0x04 | xer_ov
;
169 /* Set Rc1 (for floating point arithmetic) */
172 env
->crf
[1] = regs
->fpscr
[7];
195 /* Generate exceptions */
196 PPC_OP(raise_exception_err
)
198 do_raise_exception_err(PARAM(1), PARAM(2));
201 PPC_OP(raise_exception
)
203 do_raise_exception(PARAM(1));
214 #if defined (DEBUG_OP)
217 do_raise_exception(EXCP_DEBUG
);
221 /* Segment registers load and store with immediate index */
224 T0
= regs
->sr
[T1
>> 28];
230 do_store_sr(T1
>> 28);
251 /* Load/store special registers */
260 do_store_cr(PARAM(1));
266 T0
= (xer_so
<< 3) | (xer_ov
<< 2) | (xer_ca
<< 1);
311 T0
= regs
->spr
[PARAM(1)];
317 regs
->spr
[PARAM(1)] = T0
;
347 T0
= cpu_ppc_load_tbl(regs
);
353 T0
= cpu_ppc_load_tbu(regs
);
359 cpu_ppc_store_tbl(regs
, T0
);
365 cpu_ppc_store_tbu(regs
, T0
);
371 T0
= cpu_ppc_load_decr(regs
);
376 cpu_ppc_store_decr(regs
, T0
);
382 T0
= regs
->IBAT
[PARAM(1)][PARAM(2)];
387 do_store_ibat(PARAM(1), PARAM(2));
392 T0
= regs
->DBAT
[PARAM(1)][PARAM(2)];
397 do_store_dbat(PARAM(1), PARAM(2));
409 do_store_fpscr(PARAM(1));
415 regs
->fpscr
[7] &= ~0x8;
422 T0
= (T0
>> PARAM(1)) & 1;
428 T1
= (T1
>> PARAM(1)) & 1;
434 T1
= (T1
& PARAM(1)) | (T0
<< PARAM(2));
439 #define EIP regs->nip
448 JUMP_TB(b1
, PARAM1
, 0, PARAM2
);
459 JUMP_TB(btest
, PARAM1
, 0, PARAM2
);
461 JUMP_TB(btest
, PARAM1
, 1, PARAM3
);
486 /* tests with result in T0 */
493 PPC_OP(test_ctr_true
)
495 T0
= (regs
->ctr
!= 0 && (T0
& PARAM(1)) != 0);
498 PPC_OP(test_ctr_false
)
500 T0
= (regs
->ctr
!= 0 && (T0
& PARAM(1)) == 0);
505 T0
= (regs
->ctr
== 0);
508 PPC_OP(test_ctrz_true
)
510 T0
= (regs
->ctr
== 0 && (T0
& PARAM(1)) != 0);
513 PPC_OP(test_ctrz_false
)
515 T0
= (regs
->ctr
== 0 && (T0
& PARAM(1)) == 0);
520 T0
= (T0
& PARAM(1));
525 T0
= ((T0
& PARAM(1)) == 0);
528 /* CTR maintenance */
535 /*** Integer arithmetic ***/
547 if ((T2
^ T1
^ (-1)) & (T2
^ T0
) & (1 << 31)) {
578 if ((T2
^ T1
^ (-1)) & (T2
^ T0
) & (1 << 31)) {
588 /* candidate for helper (too long) */
593 if (T0
< T2
|| (xer_ca
== 1 && T0
== T2
)) {
605 if (T0
< T2
|| (xer_ca
== 1 && T0
== T2
)) {
610 if ((T2
^ T1
^ (-1)) & (T2
^ T0
) & (1 << 31)) {
626 /* add immediate carrying */
639 /* add to minus one extended */
653 if (T1
& (T1
^ T0
) & (1 << 31)) {
664 /* add to zero extended */
681 if ((T1
^ (-1)) & (T1
^ T0
) & (1 << 31)) {
696 /* candidate for helper (too long) */
699 if ((Ts0
== INT32_MIN
&& Ts1
== -1) || Ts1
== 0) {
700 T0
= (int32_t)((-1) * (T0
>> 31));
709 if ((Ts0
== INT32_MIN
&& Ts1
== -1) || Ts1
== 0) {
712 T0
= (-1) * (T0
>> 31);
720 /* divide word unsigned */
744 /* multiply high word */
747 T0
= ((int64_t)Ts0
* (int64_t)Ts1
) >> 32;
751 /* multiply high word unsigned */
754 T0
= ((uint64_t)T0
* (uint64_t)T1
) >> 32;
758 /* multiply low immediate */
761 T0
= (Ts0
* SPARAM(1));
765 /* multiply low word */
774 int64_t res
= (int64_t)Ts0
* (int64_t)Ts1
;
776 if ((int32_t)res
!= res
) {
789 if (T0
!= 0x80000000) {
797 if (T0
== 0x80000000) {
818 if (((~T2
) ^ T1
^ (-1)) & ((~T2
) ^ T0
) & (1 << 31)) {
827 /* substract from carrying */
848 if (((~T2
) ^ T1
^ (-1)) & ((~T2
) ^ T0
) & (1 << 31)) {
857 /* substract from extended */
858 /* candidate for helper (too long) */
861 T0
= T1
+ ~T0
+ xer_ca
;
862 if (T0
< T1
|| (xer_ca
== 1 && T0
== T1
)) {
873 T0
= T1
+ ~T0
+ xer_ca
;
874 if ((~T2
^ T1
^ (-1)) & (~T2
^ T0
) & (1 << 31)) {
880 if (T0
< T1
|| (xer_ca
== 1 && T0
== T1
)) {
888 /* substract from immediate carrying */
891 T0
= PARAM(1) + ~T0
+ 1;
892 if (T0
<= PARAM(1)) {
900 /* substract from minus one extended */
903 T0
= ~T0
+ xer_ca
- 1;
913 T0
= ~T0
+ xer_ca
- 1;
914 if (~T1
& (~T1
^ T0
) & (1 << 31)) {
925 /* substract from zero extended */
942 if ((~T1
^ (-1)) & ((~T1
) ^ T0
) & (1 << 31)) {
956 /*** Integer comparison ***/
962 } else if (Ts0
> Ts1
) {
970 /* compare immediate */
973 if (Ts0
< SPARAM(1)) {
975 } else if (Ts0
> SPARAM(1)) {
983 /* compare logical */
988 } else if (T0
> T1
) {
996 /* compare logical immediate */
1001 } else if (T0
> PARAM(1)) {
1009 /*** Integer logical ***/
1031 /* count leading zero */
1035 for (T0
= 32; T1
> 0; T0
--)
1047 /* extend sign byte */
1050 T0
= (int32_t)((int8_t)(Ts0
));
1054 /* extend sign half word */
1057 T0
= (int32_t)((int16_t)(Ts0
));
1110 /*** Integer rotate ***/
1111 /* rotate left word immediate then mask insert */
1114 T0
= (rotl(T0
, PARAM(1)) & PARAM(2)) | (T1
& PARAM(3));
1118 /* rotate left immediate then and with mask insert */
1121 T0
= rotl(T0
, PARAM(1));
1127 T0
= T0
<< PARAM(1);
1133 T0
= T0
>> PARAM(1);
1137 /* rotate left word then and with mask insert */
1140 T0
= rotl(T0
, PARAM(1)) & PARAM(2);
1152 T0
= rotl(T0
, T1
) & PARAM(1);
1156 /*** Integer shift ***/
1157 /* shift left word */
1168 /* shift right algebraic word */
1175 /* shift right algebraic word immediate */
1179 T0
= (Ts0
>> PARAM(1));
1180 if (Ts1
< 0 && (Ts1
& PARAM(2)) != 0) {
1188 /* shift right word */
1199 /*** Floating-Point arithmetic ***/
1207 /* fadds - fadds. */
1221 /* fsubs - fsubs. */
1235 /* fmuls - fmuls. */
1249 /* fdivs - fdivs. */
1256 /* fsqrt - fsqrt. */
1263 /* fsqrts - fsqrts. */
1277 /* frsqrte - frsqrte. */
1291 /*** Floating-Point multiply-and-add ***/
1292 /* fmadd - fmadd. */
1295 FT0
= (FT0
* FT1
) + FT2
;
1299 /* fmadds - fmadds. */
1302 FT0
= (FTS0
* FTS1
) + FTS2
;
1306 /* fmsub - fmsub. */
1309 FT0
= (FT0
* FT1
) - FT2
;
1313 /* fmsubs - fmsubs. */
1316 FT0
= (FTS0
* FTS1
) - FTS2
;
1320 /* fnmadd - fnmadd. - fnmadds - fnmadds. */
1327 /* fnmadds - fnmadds. */
1334 /* fnmsub - fnmsub. */
1341 /* fnmsubs - fnmsubs. */
1348 /*** Floating-Point round & convert ***/
1356 /* fctiw - fctiw. */
1363 /* fctiwz - fctiwz. */
1371 /*** Floating-Point compare ***/
1386 /*** Floating-point move ***/
1408 /* Load and store */
1409 #define MEMSUFFIX _raw
1411 #if !defined(CONFIG_USER_ONLY)
1412 #define MEMSUFFIX _user
1415 #define MEMSUFFIX _kernel
1419 /* Special op to check and maybe clear reservation */
1420 PPC_OP(check_reservation
)
1422 do_check_reservation();
1426 /* Return from interrupt */
1429 regs
->nip
= regs
->spr
[SRR0
] & ~0x00000003;
1431 T0
= regs
->spr
[SRR1
] & ~0xFFF00000;
1433 T0
= regs
->spr
[SRR1
] & ~0xFFFF0000;
1436 #if defined (DEBUG_OP)
1440 do_raise_exception(EXCP_RFI
);
1447 if ((Ts0
< Ts1
&& (PARAM(1) & 0x10)) ||
1448 (Ts0
> Ts1
&& (PARAM(1) & 0x08)) ||
1449 (Ts0
== Ts1
&& (PARAM(1) & 0x04)) ||
1450 (T0
< T1
&& (PARAM(1) & 0x02)) ||
1451 (T0
> T1
&& (PARAM(1) & 0x01)))
1452 do_raise_exception_err(EXCP_PROGRAM
, EXCP_TRAP
);
1458 if ((Ts0
< SPARAM(1) && (PARAM(2) & 0x10)) ||
1459 (Ts0
> SPARAM(1) && (PARAM(2) & 0x08)) ||
1460 (Ts0
== SPARAM(1) && (PARAM(2) & 0x04)) ||
1461 (T0
< (uint32_t)SPARAM(1) && (PARAM(2) & 0x02)) ||
1462 (T0
> (uint32_t)SPARAM(1) && (PARAM(2) & 0x01)))
1463 do_raise_exception_err(EXCP_PROGRAM
, EXCP_TRAP
);
1467 /* Instruction cache block invalidate */