]>
git.proxmox.com Git - qemu.git/blob - target-ppc/op.c
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 JUMP_TB(b1
, PARAM1
, 0, PARAM2
);
467 JUMP_TB(btest
, PARAM1
, 0, PARAM2
);
469 JUMP_TB(btest
, PARAM1
, 1, PARAM3
);
494 /* tests with result in T0 */
501 PPC_OP(test_ctr_true
)
503 T0
= (regs
->ctr
!= 0 && (T0
& PARAM(1)) != 0);
506 PPC_OP(test_ctr_false
)
508 T0
= (regs
->ctr
!= 0 && (T0
& PARAM(1)) == 0);
513 T0
= (regs
->ctr
== 0);
516 PPC_OP(test_ctrz_true
)
518 T0
= (regs
->ctr
== 0 && (T0
& PARAM(1)) != 0);
521 PPC_OP(test_ctrz_false
)
523 T0
= (regs
->ctr
== 0 && (T0
& PARAM(1)) == 0);
528 T0
= (T0
& PARAM(1));
533 T0
= ((T0
& PARAM(1)) == 0);
536 /* CTR maintenance */
543 /*** Integer arithmetic ***/
555 if ((T2
^ T1
^ (-1)) & (T2
^ T0
) & (1 << 31)) {
586 if ((T2
^ T1
^ (-1)) & (T2
^ T0
) & (1 << 31)) {
596 /* candidate for helper (too long) */
601 if (T0
< T2
|| (xer_ca
== 1 && T0
== T2
)) {
613 if (T0
< T2
|| (xer_ca
== 1 && T0
== T2
)) {
618 if ((T2
^ T1
^ (-1)) & (T2
^ T0
) & (1 << 31)) {
634 /* add immediate carrying */
647 /* add to minus one extended */
661 if (T1
& (T1
^ T0
) & (1 << 31)) {
672 /* add to zero extended */
689 if ((T1
^ (-1)) & (T1
^ T0
) & (1 << 31)) {
704 /* candidate for helper (too long) */
707 if ((Ts0
== INT32_MIN
&& Ts1
== -1) || Ts1
== 0) {
708 T0
= (int32_t)((-1) * (T0
>> 31));
717 if ((Ts0
== INT32_MIN
&& Ts1
== -1) || Ts1
== 0) {
720 T0
= (-1) * (T0
>> 31);
728 /* divide word unsigned */
752 /* multiply high word */
755 T0
= ((int64_t)Ts0
* (int64_t)Ts1
) >> 32;
759 /* multiply high word unsigned */
762 T0
= ((uint64_t)T0
* (uint64_t)T1
) >> 32;
766 /* multiply low immediate */
769 T0
= (Ts0
* SPARAM(1));
773 /* multiply low word */
782 int64_t res
= (int64_t)Ts0
* (int64_t)Ts1
;
784 if ((int32_t)res
!= res
) {
797 if (T0
!= 0x80000000) {
805 if (T0
== 0x80000000) {
826 if (((~T2
) ^ T1
^ (-1)) & ((~T2
) ^ T0
) & (1 << 31)) {
835 /* substract from carrying */
856 if (((~T2
) ^ T1
^ (-1)) & ((~T2
) ^ T0
) & (1 << 31)) {
865 /* substract from extended */
866 /* candidate for helper (too long) */
869 T0
= T1
+ ~T0
+ xer_ca
;
870 if (T0
< T1
|| (xer_ca
== 1 && T0
== T1
)) {
881 T0
= T1
+ ~T0
+ xer_ca
;
882 if ((~T2
^ T1
^ (-1)) & (~T2
^ T0
) & (1 << 31)) {
888 if (T0
< T1
|| (xer_ca
== 1 && T0
== T1
)) {
896 /* substract from immediate carrying */
899 T0
= PARAM(1) + ~T0
+ 1;
900 if (T0
<= PARAM(1)) {
908 /* substract from minus one extended */
911 T0
= ~T0
+ xer_ca
- 1;
921 T0
= ~T0
+ xer_ca
- 1;
922 if (~T1
& (~T1
^ T0
) & (1 << 31)) {
933 /* substract from zero extended */
950 if ((~T1
^ (-1)) & ((~T1
) ^ T0
) & (1 << 31)) {
964 /*** Integer comparison ***/
970 } else if (Ts0
> Ts1
) {
978 /* compare immediate */
981 if (Ts0
< SPARAM(1)) {
983 } else if (Ts0
> SPARAM(1)) {
991 /* compare logical */
996 } else if (T0
> T1
) {
1004 /* compare logical immediate */
1007 if (T0
< PARAM(1)) {
1009 } else if (T0
> PARAM(1)) {
1017 /*** Integer logical ***/
1039 /* count leading zero */
1043 for (T0
= 32; T1
> 0; T0
--)
1055 /* extend sign byte */
1058 T0
= (int32_t)((int8_t)(Ts0
));
1062 /* extend sign half word */
1065 T0
= (int32_t)((int16_t)(Ts0
));
1118 /*** Integer rotate ***/
1119 /* rotate left word immediate then mask insert */
1122 T0
= (rotl(T0
, PARAM(1)) & PARAM(2)) | (T1
& PARAM(3));
1126 /* rotate left immediate then and with mask insert */
1129 T0
= rotl(T0
, PARAM(1));
1135 T0
= T0
<< PARAM(1);
1141 T0
= T0
>> PARAM(1);
1145 /* rotate left word then and with mask insert */
1148 T0
= rotl(T0
, PARAM(1)) & PARAM(2);
1160 T0
= rotl(T0
, T1
) & PARAM(1);
1164 /*** Integer shift ***/
1165 /* shift left word */
1176 /* shift right algebraic word */
1183 /* shift right algebraic word immediate */
1187 T0
= (Ts0
>> PARAM(1));
1188 if (Ts1
< 0 && (Ts1
& PARAM(2)) != 0) {
1196 /* shift right word */
1207 /*** Floating-Point arithmetic ***/
1230 void do_fdiv (void);
1237 /* fsqrt - fsqrt. */
1251 /* frsqrte - frsqrte. */
1265 /*** Floating-Point multiply-and-add ***/
1266 /* fmadd - fmadd. */
1269 FT0
= (FT0
* FT1
) + FT2
;
1273 /* fmsub - fmsub. */
1276 FT0
= (FT0
* FT1
) - FT2
;
1280 /* fnmadd - fnmadd. - fnmadds - fnmadds. */
1287 /* fnmsub - fnmsub. */
1294 /*** Floating-Point round & convert ***/
1302 /* fctiw - fctiw. */
1309 /* fctiwz - fctiwz. */
1317 /*** Floating-Point compare ***/
1332 /*** Floating-point move ***/
1334 void do_fabs (void);
1342 void do_fnabs (void);
1356 /* Load and store */
1357 #define MEMSUFFIX _raw
1359 #if !defined(CONFIG_USER_ONLY)
1360 #define MEMSUFFIX _user
1363 #define MEMSUFFIX _kernel
1367 /* Special op to check and maybe clear reservation */
1368 PPC_OP(check_reservation
)
1370 do_check_reservation();
1374 /* Return from interrupt */
1377 env
->nip
= env
->spr
[SPR_SRR0
] & ~0x00000003;
1378 T0
= env
->spr
[SPR_SRR1
] & ~0xFFFF0000UL
;
1379 do_store_msr(env
, T0
);
1380 env
->interrupt_request
|= CPU_INTERRUPT_EXITTB
;
1387 if ((Ts0
< Ts1
&& (PARAM(1) & 0x10)) ||
1388 (Ts0
> Ts1
&& (PARAM(1) & 0x08)) ||
1389 (Ts0
== Ts1
&& (PARAM(1) & 0x04)) ||
1390 (T0
< T1
&& (PARAM(1) & 0x02)) ||
1391 (T0
> T1
&& (PARAM(1) & 0x01)))
1392 do_raise_exception_err(EXCP_PROGRAM
, EXCP_TRAP
);
1398 if ((Ts0
< SPARAM(1) && (PARAM(2) & 0x10)) ||
1399 (Ts0
> SPARAM(1) && (PARAM(2) & 0x08)) ||
1400 (Ts0
== SPARAM(1) && (PARAM(2) & 0x04)) ||
1401 (T0
< (uint32_t)SPARAM(1) && (PARAM(2) & 0x02)) ||
1402 (T0
> (uint32_t)SPARAM(1) && (PARAM(2) & 0x01)))
1403 do_raise_exception_err(EXCP_PROGRAM
, EXCP_TRAP
);
1407 /* Instruction cache block invalidate */
1428 void op_store_pir (void)
1430 env
->spr
[SPR_PIR
] = T0
& 0x0000000FUL
;