2 * PowerPC emulation for qemu: main translation routines.
4 * Copyright (c) 2003-2007 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
30 /* Include definitions for instructions classes and implementations flags */
31 //#define DO_SINGLE_STEP
32 //#define PPC_DEBUG_DISAS
33 //#define DEBUG_MEMORY_ACCESSES
34 //#define DO_PPC_STATISTICS
36 /*****************************************************************************/
37 /* Code translation helpers */
38 #if defined(USE_DIRECT_JUMP)
41 #define TBPARAM(x) (long)(x)
45 #define DEF(s, n, copy_size) INDEX_op_ ## s,
51 static uint16_t *gen_opc_ptr
;
52 static uint32_t *gen_opparam_ptr
;
56 static inline void gen_set_T0 (target_ulong val
)
58 #if defined(TARGET_PPC64)
60 gen_op_set_T0_64(val
>> 32, val
);
66 static inline void gen_set_T1 (target_ulong val
)
68 #if defined(TARGET_PPC64)
70 gen_op_set_T1_64(val
>> 32, val
);
76 #define GEN8(func, NAME) \
77 static GenOpFunc *NAME ## _table [8] = { \
78 NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
79 NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
81 static inline void func(int n) \
83 NAME ## _table[n](); \
86 #define GEN16(func, NAME) \
87 static GenOpFunc *NAME ## _table [16] = { \
88 NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
89 NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
90 NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
91 NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
93 static inline void func(int n) \
95 NAME ## _table[n](); \
98 #define GEN32(func, NAME) \
99 static GenOpFunc *NAME ## _table [32] = { \
100 NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
101 NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
102 NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
103 NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
104 NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \
105 NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \
106 NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \
107 NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \
109 static inline void func(int n) \
111 NAME ## _table[n](); \
114 /* Condition register moves */
115 GEN8(gen_op_load_crf_T0
, gen_op_load_crf_T0_crf
);
116 GEN8(gen_op_load_crf_T1
, gen_op_load_crf_T1_crf
);
117 GEN8(gen_op_store_T0_crf
, gen_op_store_T0_crf_crf
);
118 GEN8(gen_op_store_T1_crf
, gen_op_store_T1_crf_crf
);
120 /* Floating point condition and status register moves */
121 GEN8(gen_op_load_fpscr_T0
, gen_op_load_fpscr_T0_fpscr
);
122 GEN8(gen_op_store_T0_fpscr
, gen_op_store_T0_fpscr_fpscr
);
123 GEN8(gen_op_clear_fpscr
, gen_op_clear_fpscr_fpscr
);
124 static inline void gen_op_store_T0_fpscri (int n
, uint8_t param
)
126 gen_op_set_T0(param
);
127 gen_op_store_T0_fpscr(n
);
130 /* General purpose registers moves */
131 GEN32(gen_op_load_gpr_T0
, gen_op_load_gpr_T0_gpr
);
132 GEN32(gen_op_load_gpr_T1
, gen_op_load_gpr_T1_gpr
);
133 GEN32(gen_op_load_gpr_T2
, gen_op_load_gpr_T2_gpr
);
135 GEN32(gen_op_store_T0_gpr
, gen_op_store_T0_gpr_gpr
);
136 GEN32(gen_op_store_T1_gpr
, gen_op_store_T1_gpr_gpr
);
138 GEN32(gen_op_store_T2_gpr
, gen_op_store_T2_gpr_gpr
);
141 /* floating point registers moves */
142 GEN32(gen_op_load_fpr_FT0
, gen_op_load_fpr_FT0_fpr
);
143 GEN32(gen_op_load_fpr_FT1
, gen_op_load_fpr_FT1_fpr
);
144 GEN32(gen_op_load_fpr_FT2
, gen_op_load_fpr_FT2_fpr
);
145 GEN32(gen_op_store_FT0_fpr
, gen_op_store_FT0_fpr_fpr
);
146 GEN32(gen_op_store_FT1_fpr
, gen_op_store_FT1_fpr_fpr
);
148 GEN32(gen_op_store_FT2_fpr
, gen_op_store_FT2_fpr_fpr
);
151 /* internal defines */
152 typedef struct DisasContext
{
153 struct TranslationBlock
*tb
;
157 /* Routine used to access memory */
159 /* Translation flags */
160 #if !defined(CONFIG_USER_ONLY)
163 #if defined(TARGET_PPC64)
167 #if defined(TARGET_PPCEMB)
170 ppc_spr_t
*spr_cb
; /* Needed to check rights for mfspr/mtspr */
171 int singlestep_enabled
;
174 struct opc_handler_t
{
177 /* instruction type */
180 void (*handler
)(DisasContext
*ctx
);
181 #if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
182 const unsigned char *oname
;
184 #if defined(DO_PPC_STATISTICS)
189 static inline void gen_set_Rc0 (DisasContext
*ctx
)
191 #if defined(TARGET_PPC64)
200 static inline void gen_update_nip (DisasContext
*ctx
, target_ulong nip
)
202 #if defined(TARGET_PPC64)
204 gen_op_update_nip_64(nip
>> 32, nip
);
207 gen_op_update_nip(nip
);
210 #define RET_EXCP(ctx, excp, error) \
212 if ((ctx)->exception == EXCP_NONE) { \
213 gen_update_nip(ctx, (ctx)->nip); \
215 gen_op_raise_exception_err((excp), (error)); \
216 ctx->exception = (excp); \
219 #define RET_INVAL(ctx) \
220 RET_EXCP((ctx), EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL)
222 #define RET_PRIVOPC(ctx) \
223 RET_EXCP((ctx), EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_OPC)
225 #define RET_PRIVREG(ctx) \
226 RET_EXCP((ctx), EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG)
228 /* Stop translation */
229 static inline void RET_STOP (DisasContext
*ctx
)
231 gen_update_nip(ctx
, ctx
->nip
);
232 ctx
->exception
= EXCP_MTMSR
;
235 /* No need to update nip here, as execution flow will change */
236 static inline void RET_CHG_FLOW (DisasContext
*ctx
)
238 ctx
->exception
= EXCP_MTMSR
;
241 #define GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
242 static void gen_##name (DisasContext *ctx); \
243 GEN_OPCODE(name, opc1, opc2, opc3, inval, type); \
244 static void gen_##name (DisasContext *ctx)
246 typedef struct opcode_t
{
247 unsigned char opc1
, opc2
, opc3
;
248 #if HOST_LONG_BITS == 64 /* Explicitely align to 64 bits */
249 unsigned char pad
[5];
251 unsigned char pad
[1];
253 opc_handler_t handler
;
254 const unsigned char *oname
;
257 /*****************************************************************************/
258 /*** Instruction decoding ***/
259 #define EXTRACT_HELPER(name, shift, nb) \
260 static inline uint32_t name (uint32_t opcode) \
262 return (opcode >> (shift)) & ((1 << (nb)) - 1); \
265 #define EXTRACT_SHELPER(name, shift, nb) \
266 static inline int32_t name (uint32_t opcode) \
268 return (int16_t)((opcode >> (shift)) & ((1 << (nb)) - 1)); \
272 EXTRACT_HELPER(opc1
, 26, 6);
274 EXTRACT_HELPER(opc2
, 1, 5);
276 EXTRACT_HELPER(opc3
, 6, 5);
277 /* Update Cr0 flags */
278 EXTRACT_HELPER(Rc
, 0, 1);
280 EXTRACT_HELPER(rD
, 21, 5);
282 EXTRACT_HELPER(rS
, 21, 5);
284 EXTRACT_HELPER(rA
, 16, 5);
286 EXTRACT_HELPER(rB
, 11, 5);
288 EXTRACT_HELPER(rC
, 6, 5);
290 EXTRACT_HELPER(crfD
, 23, 3);
291 EXTRACT_HELPER(crfS
, 18, 3);
292 EXTRACT_HELPER(crbD
, 21, 5);
293 EXTRACT_HELPER(crbA
, 16, 5);
294 EXTRACT_HELPER(crbB
, 11, 5);
296 EXTRACT_HELPER(_SPR
, 11, 10);
297 static inline uint32_t SPR (uint32_t opcode
)
299 uint32_t sprn
= _SPR(opcode
);
301 return ((sprn
>> 5) & 0x1F) | ((sprn
& 0x1F) << 5);
303 /*** Get constants ***/
304 EXTRACT_HELPER(IMM
, 12, 8);
305 /* 16 bits signed immediate value */
306 EXTRACT_SHELPER(SIMM
, 0, 16);
307 /* 16 bits unsigned immediate value */
308 EXTRACT_HELPER(UIMM
, 0, 16);
310 EXTRACT_HELPER(NB
, 11, 5);
312 EXTRACT_HELPER(SH
, 11, 5);
314 EXTRACT_HELPER(MB
, 6, 5);
316 EXTRACT_HELPER(ME
, 1, 5);
318 EXTRACT_HELPER(TO
, 21, 5);
320 EXTRACT_HELPER(CRM
, 12, 8);
321 EXTRACT_HELPER(FM
, 17, 8);
322 EXTRACT_HELPER(SR
, 16, 4);
323 EXTRACT_HELPER(FPIMM
, 20, 4);
325 /*** Jump target decoding ***/
327 EXTRACT_SHELPER(d
, 0, 16);
328 /* Immediate address */
329 static inline target_ulong
LI (uint32_t opcode
)
331 return (opcode
>> 0) & 0x03FFFFFC;
334 static inline uint32_t BD (uint32_t opcode
)
336 return (opcode
>> 0) & 0xFFFC;
339 EXTRACT_HELPER(BO
, 21, 5);
340 EXTRACT_HELPER(BI
, 16, 5);
341 /* Absolute/relative address */
342 EXTRACT_HELPER(AA
, 1, 1);
344 EXTRACT_HELPER(LK
, 0, 1);
346 /* Create a mask between <start> and <end> bits */
347 static inline target_ulong
MASK (uint32_t start
, uint32_t end
)
351 #if defined(TARGET_PPC64)
352 if (likely(start
== 0)) {
353 ret
= (uint64_t)(-1ULL) << (63 - end
);
354 } else if (likely(end
== 63)) {
355 ret
= (uint64_t)(-1ULL) >> start
;
358 if (likely(start
== 0)) {
359 ret
= (uint32_t)(-1ULL) << (31 - end
);
360 } else if (likely(end
== 31)) {
361 ret
= (uint32_t)(-1ULL) >> start
;
365 ret
= (((target_ulong
)(-1ULL)) >> (start
)) ^
366 (((target_ulong
)(-1ULL) >> (end
)) >> 1);
367 if (unlikely(start
> end
))
374 /*****************************************************************************/
375 /* PowerPC Instructions types definitions */
377 PPC_NONE
= 0x0000000000000000ULL
,
378 /* integer operations instructions */
379 /* flow control instructions */
380 /* virtual memory instructions */
381 /* ld/st with reservation instructions */
382 /* cache control instructions */
383 /* spr/msr access instructions */
384 PPC_INSNS_BASE
= 0x0000000000000001ULL
,
385 #define PPC_INTEGER PPC_INSNS_BASE
386 #define PPC_FLOW PPC_INSNS_BASE
387 #define PPC_MEM PPC_INSNS_BASE
388 #define PPC_RES PPC_INSNS_BASE
389 #define PPC_CACHE PPC_INSNS_BASE
390 #define PPC_MISC PPC_INSNS_BASE
391 /* Optional floating point instructions */
392 PPC_FLOAT
= 0x0000000000000002ULL
,
393 PPC_FLOAT_FSQRT
= 0x0000000000000004ULL
,
394 PPC_FLOAT_FRES
= 0x0000000000000008ULL
,
395 PPC_FLOAT_FRSQRTE
= 0x0000000000000010ULL
,
396 PPC_FLOAT_FSEL
= 0x0000000000000020ULL
,
397 PPC_FLOAT_STFIWX
= 0x0000000000000040ULL
,
398 /* external control instructions */
399 PPC_EXTERN
= 0x0000000000000080ULL
,
400 /* segment register access instructions */
401 PPC_SEGMENT
= 0x0000000000000100ULL
,
402 /* Optional cache control instruction */
403 PPC_CACHE_DCBA
= 0x0000000000000200ULL
,
404 /* Optional memory control instructions */
405 PPC_MEM_TLBIA
= 0x0000000000000400ULL
,
406 PPC_MEM_TLBIE
= 0x0000000000000800ULL
,
407 PPC_MEM_TLBSYNC
= 0x0000000000001000ULL
,
409 PPC_MEM_SYNC
= 0x0000000000002000ULL
,
410 /* PowerPC 6xx TLB management instructions */
411 PPC_6xx_TLB
= 0x0000000000004000ULL
,
412 /* Altivec support */
413 PPC_ALTIVEC
= 0x0000000000008000ULL
,
414 /* Time base mftb instruction */
415 PPC_MFTB
= 0x0000000000010000ULL
,
416 /* Embedded PowerPC dedicated instructions */
417 PPC_EMB_COMMON
= 0x0000000000020000ULL
,
418 /* PowerPC 40x exception model */
419 PPC_40x_EXCP
= 0x0000000000040000ULL
,
420 /* PowerPC 40x TLB management instructions */
421 PPC_40x_TLB
= 0x0000000000080000ULL
,
422 /* PowerPC 405 Mac instructions */
423 PPC_405_MAC
= 0x0000000000100000ULL
,
424 /* PowerPC 440 specific instructions */
425 PPC_440_SPEC
= 0x0000000000200000ULL
,
426 /* Power-to-PowerPC bridge (601) */
427 PPC_POWER_BR
= 0x0000000000400000ULL
,
428 /* PowerPC 602 specific */
429 PPC_602_SPEC
= 0x0000000000800000ULL
,
430 /* Deprecated instructions */
431 /* Original POWER instruction set */
432 PPC_POWER
= 0x0000000001000000ULL
,
433 /* POWER2 instruction set extension */
434 PPC_POWER2
= 0x0000000002000000ULL
,
435 /* Power RTC support */
436 PPC_POWER_RTC
= 0x0000000004000000ULL
,
437 /* 64 bits PowerPC instructions */
438 /* 64 bits PowerPC instruction set */
439 PPC_64B
= 0x0000000008000000ULL
,
440 /* 64 bits hypervisor extensions */
441 PPC_64H
= 0x0000000010000000ULL
,
442 /* 64 bits PowerPC "bridge" features */
443 PPC_64_BRIDGE
= 0x0000000020000000ULL
,
444 /* BookE (embedded) PowerPC specification */
445 PPC_BOOKE
= 0x0000000040000000ULL
,
447 PPC_MEM_EIEIO
= 0x0000000080000000ULL
,
448 /* e500 vector instructions */
449 PPC_E500_VECTOR
= 0x0000000100000000ULL
,
450 /* PowerPC 4xx dedicated instructions */
451 PPC_4xx_COMMON
= 0x0000000200000000ULL
,
452 /* PowerPC 2.03 specification extensions */
453 PPC_203
= 0x0000000400000000ULL
,
454 /* PowerPC 2.03 SPE extension */
455 PPC_SPE
= 0x0000000800000000ULL
,
456 /* PowerPC 2.03 SPE floating-point extension */
457 PPC_SPEFPU
= 0x0000001000000000ULL
,
459 PPC_SLBI
= 0x0000002000000000ULL
,
460 /* PowerPC 40x ibct instructions */
461 PPC_40x_ICBT
= 0x0000004000000000ULL
,
462 /* PowerPC 74xx TLB management instructions */
463 PPC_74xx_TLB
= 0x0000008000000000ULL
,
464 /* More BookE (embedded) instructions... */
465 PPC_BOOKE_EXT
= 0x0000010000000000ULL
,
466 /* rfmci is not implemented in all BookE PowerPC */
467 PPC_RFMCI
= 0x0000020000000000ULL
,
468 /* user-mode DCR access, implemented in PowerPC 460 */
469 PPC_DCRUX
= 0x0000040000000000ULL
,
472 /*****************************************************************************/
473 /* PowerPC instructions table */
474 #if HOST_LONG_BITS == 64
479 #if defined(__APPLE__)
480 #define OPCODES_SECTION \
481 __attribute__ ((section("__TEXT,__opcodes"), unused, aligned (OPC_ALIGN) ))
483 #define OPCODES_SECTION \
484 __attribute__ ((section(".opcodes"), unused, aligned (OPC_ALIGN) ))
487 #if defined(DO_PPC_STATISTICS)
488 #define GEN_OPCODE(name, op1, op2, op3, invl, _typ) \
489 OPCODES_SECTION opcode_t opc_##name = { \
497 .handler = &gen_##name, \
498 .oname = stringify(name), \
500 .oname = stringify(name), \
503 #define GEN_OPCODE(name, op1, op2, op3, invl, _typ) \
504 OPCODES_SECTION opcode_t opc_##name = { \
512 .handler = &gen_##name, \
514 .oname = stringify(name), \
518 #define GEN_OPCODE_MARK(name) \
519 OPCODES_SECTION opcode_t opc_##name = { \
525 .inval = 0x00000000, \
529 .oname = stringify(name), \
532 /* Start opcode list */
533 GEN_OPCODE_MARK(start
);
535 /* Invalid instruction */
536 GEN_HANDLER(invalid
, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE
)
541 static opc_handler_t invalid_handler
= {
544 .handler
= gen_invalid
,
547 /*** Integer arithmetic ***/
548 #define __GEN_INT_ARITH2(name, opc1, opc2, opc3, inval, type) \
549 GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
551 gen_op_load_gpr_T0(rA(ctx->opcode)); \
552 gen_op_load_gpr_T1(rB(ctx->opcode)); \
554 gen_op_store_T0_gpr(rD(ctx->opcode)); \
555 if (unlikely(Rc(ctx->opcode) != 0)) \
559 #define __GEN_INT_ARITH2_O(name, opc1, opc2, opc3, inval, type) \
560 GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
562 gen_op_load_gpr_T0(rA(ctx->opcode)); \
563 gen_op_load_gpr_T1(rB(ctx->opcode)); \
565 gen_op_store_T0_gpr(rD(ctx->opcode)); \
566 if (unlikely(Rc(ctx->opcode) != 0)) \
570 #define __GEN_INT_ARITH1(name, opc1, opc2, opc3, type) \
571 GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, type) \
573 gen_op_load_gpr_T0(rA(ctx->opcode)); \
575 gen_op_store_T0_gpr(rD(ctx->opcode)); \
576 if (unlikely(Rc(ctx->opcode) != 0)) \
579 #define __GEN_INT_ARITH1_O(name, opc1, opc2, opc3, type) \
580 GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, type) \
582 gen_op_load_gpr_T0(rA(ctx->opcode)); \
584 gen_op_store_T0_gpr(rD(ctx->opcode)); \
585 if (unlikely(Rc(ctx->opcode) != 0)) \
589 /* Two operands arithmetic functions */
590 #define GEN_INT_ARITH2(name, opc1, opc2, opc3, type) \
591 __GEN_INT_ARITH2(name, opc1, opc2, opc3, 0x00000000, type) \
592 __GEN_INT_ARITH2_O(name##o, opc1, opc2, opc3 | 0x10, 0x00000000, type)
594 /* Two operands arithmetic functions with no overflow allowed */
595 #define GEN_INT_ARITHN(name, opc1, opc2, opc3, type) \
596 __GEN_INT_ARITH2(name, opc1, opc2, opc3, 0x00000400, type)
598 /* One operand arithmetic functions */
599 #define GEN_INT_ARITH1(name, opc1, opc2, opc3, type) \
600 __GEN_INT_ARITH1(name, opc1, opc2, opc3, type) \
601 __GEN_INT_ARITH1_O(name##o, opc1, opc2, opc3 | 0x10, type)
603 #if defined(TARGET_PPC64)
604 #define __GEN_INT_ARITH2_64(name, opc1, opc2, opc3, inval, type) \
605 GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
607 gen_op_load_gpr_T0(rA(ctx->opcode)); \
608 gen_op_load_gpr_T1(rB(ctx->opcode)); \
610 gen_op_##name##_64(); \
613 gen_op_store_T0_gpr(rD(ctx->opcode)); \
614 if (unlikely(Rc(ctx->opcode) != 0)) \
618 #define __GEN_INT_ARITH2_O_64(name, opc1, opc2, opc3, inval, type) \
619 GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
621 gen_op_load_gpr_T0(rA(ctx->opcode)); \
622 gen_op_load_gpr_T1(rB(ctx->opcode)); \
624 gen_op_##name##_64(); \
627 gen_op_store_T0_gpr(rD(ctx->opcode)); \
628 if (unlikely(Rc(ctx->opcode) != 0)) \
632 #define __GEN_INT_ARITH1_64(name, opc1, opc2, opc3, type) \
633 GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, type) \
635 gen_op_load_gpr_T0(rA(ctx->opcode)); \
637 gen_op_##name##_64(); \
640 gen_op_store_T0_gpr(rD(ctx->opcode)); \
641 if (unlikely(Rc(ctx->opcode) != 0)) \
644 #define __GEN_INT_ARITH1_O_64(name, opc1, opc2, opc3, type) \
645 GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, type) \
647 gen_op_load_gpr_T0(rA(ctx->opcode)); \
649 gen_op_##name##_64(); \
652 gen_op_store_T0_gpr(rD(ctx->opcode)); \
653 if (unlikely(Rc(ctx->opcode) != 0)) \
657 /* Two operands arithmetic functions */
658 #define GEN_INT_ARITH2_64(name, opc1, opc2, opc3, type) \
659 __GEN_INT_ARITH2_64(name, opc1, opc2, opc3, 0x00000000, type) \
660 __GEN_INT_ARITH2_O_64(name##o, opc1, opc2, opc3 | 0x10, 0x00000000, type)
662 /* Two operands arithmetic functions with no overflow allowed */
663 #define GEN_INT_ARITHN_64(name, opc1, opc2, opc3, type) \
664 __GEN_INT_ARITH2_64(name, opc1, opc2, opc3, 0x00000400, type)
666 /* One operand arithmetic functions */
667 #define GEN_INT_ARITH1_64(name, opc1, opc2, opc3, type) \
668 __GEN_INT_ARITH1_64(name, opc1, opc2, opc3, type) \
669 __GEN_INT_ARITH1_O_64(name##o, opc1, opc2, opc3 | 0x10, type)
671 #define GEN_INT_ARITH2_64 GEN_INT_ARITH2
672 #define GEN_INT_ARITHN_64 GEN_INT_ARITHN
673 #define GEN_INT_ARITH1_64 GEN_INT_ARITH1
676 /* add add. addo addo. */
677 static inline void gen_op_addo (void)
683 #if defined(TARGET_PPC64)
684 #define gen_op_add_64 gen_op_add
685 static inline void gen_op_addo_64 (void)
689 gen_op_check_addo_64();
692 GEN_INT_ARITH2_64 (add
, 0x1F, 0x0A, 0x08, PPC_INTEGER
);
693 /* addc addc. addco addco. */
694 static inline void gen_op_addc (void)
700 static inline void gen_op_addco (void)
707 #if defined(TARGET_PPC64)
708 static inline void gen_op_addc_64 (void)
712 gen_op_check_addc_64();
714 static inline void gen_op_addco_64 (void)
718 gen_op_check_addc_64();
719 gen_op_check_addo_64();
722 GEN_INT_ARITH2_64 (addc
, 0x1F, 0x0A, 0x00, PPC_INTEGER
);
723 /* adde adde. addeo addeo. */
724 static inline void gen_op_addeo (void)
730 #if defined(TARGET_PPC64)
731 static inline void gen_op_addeo_64 (void)
735 gen_op_check_addo_64();
738 GEN_INT_ARITH2_64 (adde
, 0x1F, 0x0A, 0x04, PPC_INTEGER
);
739 /* addme addme. addmeo addmeo. */
740 static inline void gen_op_addme (void)
745 #if defined(TARGET_PPC64)
746 static inline void gen_op_addme_64 (void)
752 GEN_INT_ARITH1_64 (addme
, 0x1F, 0x0A, 0x07, PPC_INTEGER
);
753 /* addze addze. addzeo addzeo. */
754 static inline void gen_op_addze (void)
760 static inline void gen_op_addzeo (void)
767 #if defined(TARGET_PPC64)
768 static inline void gen_op_addze_64 (void)
772 gen_op_check_addc_64();
774 static inline void gen_op_addzeo_64 (void)
778 gen_op_check_addc_64();
779 gen_op_check_addo_64();
782 GEN_INT_ARITH1_64 (addze
, 0x1F, 0x0A, 0x06, PPC_INTEGER
);
783 /* divw divw. divwo divwo. */
784 GEN_INT_ARITH2 (divw
, 0x1F, 0x0B, 0x0F, PPC_INTEGER
);
785 /* divwu divwu. divwuo divwuo. */
786 GEN_INT_ARITH2 (divwu
, 0x1F, 0x0B, 0x0E, PPC_INTEGER
);
788 GEN_INT_ARITHN (mulhw
, 0x1F, 0x0B, 0x02, PPC_INTEGER
);
790 GEN_INT_ARITHN (mulhwu
, 0x1F, 0x0B, 0x00, PPC_INTEGER
);
791 /* mullw mullw. mullwo mullwo. */
792 GEN_INT_ARITH2 (mullw
, 0x1F, 0x0B, 0x07, PPC_INTEGER
);
793 /* neg neg. nego nego. */
794 GEN_INT_ARITH1_64 (neg
, 0x1F, 0x08, 0x03, PPC_INTEGER
);
795 /* subf subf. subfo subfo. */
796 static inline void gen_op_subfo (void)
800 gen_op_check_subfo();
802 #if defined(TARGET_PPC64)
803 #define gen_op_subf_64 gen_op_subf
804 static inline void gen_op_subfo_64 (void)
808 gen_op_check_subfo_64();
811 GEN_INT_ARITH2_64 (subf
, 0x1F, 0x08, 0x01, PPC_INTEGER
);
812 /* subfc subfc. subfco subfco. */
813 static inline void gen_op_subfc (void)
816 gen_op_check_subfc();
818 static inline void gen_op_subfco (void)
822 gen_op_check_subfc();
823 gen_op_check_subfo();
825 #if defined(TARGET_PPC64)
826 static inline void gen_op_subfc_64 (void)
829 gen_op_check_subfc_64();
831 static inline void gen_op_subfco_64 (void)
835 gen_op_check_subfc_64();
836 gen_op_check_subfo_64();
839 GEN_INT_ARITH2_64 (subfc
, 0x1F, 0x08, 0x00, PPC_INTEGER
);
840 /* subfe subfe. subfeo subfeo. */
841 static inline void gen_op_subfeo (void)
845 gen_op_check_subfo();
847 #if defined(TARGET_PPC64)
848 #define gen_op_subfe_64 gen_op_subfe
849 static inline void gen_op_subfeo_64 (void)
853 gen_op_check_subfo_64();
856 GEN_INT_ARITH2_64 (subfe
, 0x1F, 0x08, 0x04, PPC_INTEGER
);
857 /* subfme subfme. subfmeo subfmeo. */
858 GEN_INT_ARITH1_64 (subfme
, 0x1F, 0x08, 0x07, PPC_INTEGER
);
859 /* subfze subfze. subfzeo subfzeo. */
860 GEN_INT_ARITH1_64 (subfze
, 0x1F, 0x08, 0x06, PPC_INTEGER
);
862 GEN_HANDLER(addi
, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER
)
864 target_long simm
= SIMM(ctx
->opcode
);
866 if (rA(ctx
->opcode
) == 0) {
870 gen_op_load_gpr_T0(rA(ctx
->opcode
));
871 if (likely(simm
!= 0))
874 gen_op_store_T0_gpr(rD(ctx
->opcode
));
877 GEN_HANDLER(addic
, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER
)
879 target_long simm
= SIMM(ctx
->opcode
);
881 gen_op_load_gpr_T0(rA(ctx
->opcode
));
882 if (likely(simm
!= 0)) {
885 #if defined(TARGET_PPC64)
887 gen_op_check_addc_64();
892 gen_op_clear_xer_ca();
894 gen_op_store_T0_gpr(rD(ctx
->opcode
));
897 GEN_HANDLER(addic_
, 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER
)
899 target_long simm
= SIMM(ctx
->opcode
);
901 gen_op_load_gpr_T0(rA(ctx
->opcode
));
902 if (likely(simm
!= 0)) {
905 #if defined(TARGET_PPC64)
907 gen_op_check_addc_64();
912 gen_op_clear_xer_ca();
914 gen_op_store_T0_gpr(rD(ctx
->opcode
));
918 GEN_HANDLER(addis
, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER
)
920 target_long simm
= SIMM(ctx
->opcode
);
922 if (rA(ctx
->opcode
) == 0) {
924 gen_set_T0(simm
<< 16);
926 gen_op_load_gpr_T0(rA(ctx
->opcode
));
927 if (likely(simm
!= 0))
928 gen_op_addi(simm
<< 16);
930 gen_op_store_T0_gpr(rD(ctx
->opcode
));
933 GEN_HANDLER(mulli
, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER
)
935 gen_op_load_gpr_T0(rA(ctx
->opcode
));
936 gen_op_mulli(SIMM(ctx
->opcode
));
937 gen_op_store_T0_gpr(rD(ctx
->opcode
));
940 GEN_HANDLER(subfic
, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER
)
942 gen_op_load_gpr_T0(rA(ctx
->opcode
));
943 #if defined(TARGET_PPC64)
945 gen_op_subfic_64(SIMM(ctx
->opcode
));
948 gen_op_subfic(SIMM(ctx
->opcode
));
949 gen_op_store_T0_gpr(rD(ctx
->opcode
));
952 #if defined(TARGET_PPC64)
954 GEN_INT_ARITHN (mulhd
, 0x1F, 0x09, 0x02, PPC_64B
);
956 GEN_INT_ARITHN (mulhdu
, 0x1F, 0x09, 0x00, PPC_64B
);
957 /* mulld mulld. mulldo mulldo. */
958 GEN_INT_ARITH2 (mulld
, 0x1F, 0x09, 0x07, PPC_64B
);
959 /* divd divd. divdo divdo. */
960 GEN_INT_ARITH2 (divd
, 0x1F, 0x09, 0x0F, PPC_64B
);
961 /* divdu divdu. divduo divduo. */
962 GEN_INT_ARITH2 (divdu
, 0x1F, 0x09, 0x0E, PPC_64B
);
965 /*** Integer comparison ***/
966 #if defined(TARGET_PPC64)
967 #define GEN_CMP(name, opc, type) \
968 GEN_HANDLER(name, 0x1F, 0x00, opc, 0x00400000, type) \
970 gen_op_load_gpr_T0(rA(ctx->opcode)); \
971 gen_op_load_gpr_T1(rB(ctx->opcode)); \
972 if (ctx->sf_mode && (ctx->opcode & 0x00200000)) \
973 gen_op_##name##_64(); \
976 gen_op_store_T0_crf(crfD(ctx->opcode)); \
979 #define GEN_CMP(name, opc, type) \
980 GEN_HANDLER(name, 0x1F, 0x00, opc, 0x00400000, type) \
982 gen_op_load_gpr_T0(rA(ctx->opcode)); \
983 gen_op_load_gpr_T1(rB(ctx->opcode)); \
985 gen_op_store_T0_crf(crfD(ctx->opcode)); \
990 GEN_CMP(cmp
, 0x00, PPC_INTEGER
);
992 GEN_HANDLER(cmpi
, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER
)
994 gen_op_load_gpr_T0(rA(ctx
->opcode
));
995 #if defined(TARGET_PPC64)
996 if (ctx
->sf_mode
&& (ctx
->opcode
& 0x00200000))
997 gen_op_cmpi_64(SIMM(ctx
->opcode
));
1000 gen_op_cmpi(SIMM(ctx
->opcode
));
1001 gen_op_store_T0_crf(crfD(ctx
->opcode
));
1004 GEN_CMP(cmpl
, 0x01, PPC_INTEGER
);
1006 GEN_HANDLER(cmpli
, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER
)
1008 gen_op_load_gpr_T0(rA(ctx
->opcode
));
1009 #if defined(TARGET_PPC64)
1010 if (ctx
->sf_mode
&& (ctx
->opcode
& 0x00200000))
1011 gen_op_cmpli_64(UIMM(ctx
->opcode
));
1014 gen_op_cmpli(UIMM(ctx
->opcode
));
1015 gen_op_store_T0_crf(crfD(ctx
->opcode
));
1018 /* isel (PowerPC 2.03 specification) */
1019 GEN_HANDLER(isel
, 0x1F, 0x0F, 0x00, 0x00000001, PPC_203
)
1021 uint32_t bi
= rC(ctx
->opcode
);
1024 if (rA(ctx
->opcode
) == 0) {
1027 gen_op_load_gpr_T1(rA(ctx
->opcode
));
1029 gen_op_load_gpr_T2(rB(ctx
->opcode
));
1030 mask
= 1 << (3 - (bi
& 0x03));
1031 gen_op_load_crf_T0(bi
>> 2);
1032 gen_op_test_true(mask
);
1034 gen_op_store_T0_gpr(rD(ctx
->opcode
));
1037 /*** Integer logical ***/
1038 #define __GEN_LOGICAL2(name, opc2, opc3, type) \
1039 GEN_HANDLER(name, 0x1F, opc2, opc3, 0x00000000, type) \
1041 gen_op_load_gpr_T0(rS(ctx->opcode)); \
1042 gen_op_load_gpr_T1(rB(ctx->opcode)); \
1044 gen_op_store_T0_gpr(rA(ctx->opcode)); \
1045 if (unlikely(Rc(ctx->opcode) != 0)) \
1048 #define GEN_LOGICAL2(name, opc, type) \
1049 __GEN_LOGICAL2(name, 0x1C, opc, type)
1051 #define GEN_LOGICAL1(name, opc, type) \
1052 GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, type) \
1054 gen_op_load_gpr_T0(rS(ctx->opcode)); \
1056 gen_op_store_T0_gpr(rA(ctx->opcode)); \
1057 if (unlikely(Rc(ctx->opcode) != 0)) \
1062 GEN_LOGICAL2(and, 0x00, PPC_INTEGER
);
1064 GEN_LOGICAL2(andc
, 0x01, PPC_INTEGER
);
1066 GEN_HANDLER(andi_
, 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER
)
1068 gen_op_load_gpr_T0(rS(ctx
->opcode
));
1069 gen_op_andi_T0(UIMM(ctx
->opcode
));
1070 gen_op_store_T0_gpr(rA(ctx
->opcode
));
1074 GEN_HANDLER(andis_
, 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER
)
1076 gen_op_load_gpr_T0(rS(ctx
->opcode
));
1077 gen_op_andi_T0(UIMM(ctx
->opcode
) << 16);
1078 gen_op_store_T0_gpr(rA(ctx
->opcode
));
1083 GEN_LOGICAL1(cntlzw
, 0x00, PPC_INTEGER
);
1085 GEN_LOGICAL2(eqv
, 0x08, PPC_INTEGER
);
1086 /* extsb & extsb. */
1087 GEN_LOGICAL1(extsb
, 0x1D, PPC_INTEGER
);
1088 /* extsh & extsh. */
1089 GEN_LOGICAL1(extsh
, 0x1C, PPC_INTEGER
);
1091 GEN_LOGICAL2(nand
, 0x0E, PPC_INTEGER
);
1093 GEN_LOGICAL2(nor
, 0x03, PPC_INTEGER
);
1096 GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER
)
1100 rs
= rS(ctx
->opcode
);
1101 ra
= rA(ctx
->opcode
);
1102 rb
= rB(ctx
->opcode
);
1103 /* Optimisation for mr. ri case */
1104 if (rs
!= ra
|| rs
!= rb
) {
1105 gen_op_load_gpr_T0(rs
);
1107 gen_op_load_gpr_T1(rb
);
1110 gen_op_store_T0_gpr(ra
);
1111 if (unlikely(Rc(ctx
->opcode
) != 0))
1113 } else if (unlikely(Rc(ctx
->opcode
) != 0)) {
1114 gen_op_load_gpr_T0(rs
);
1120 GEN_LOGICAL2(orc
, 0x0C, PPC_INTEGER
);
1122 GEN_HANDLER(xor, 0x1F, 0x1C, 0x09, 0x00000000, PPC_INTEGER
)
1124 gen_op_load_gpr_T0(rS(ctx
->opcode
));
1125 /* Optimisation for "set to zero" case */
1126 if (rS(ctx
->opcode
) != rB(ctx
->opcode
)) {
1127 gen_op_load_gpr_T1(rB(ctx
->opcode
));
1132 gen_op_store_T0_gpr(rA(ctx
->opcode
));
1133 if (unlikely(Rc(ctx
->opcode
) != 0))
1137 GEN_HANDLER(ori
, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER
)
1139 target_ulong uimm
= UIMM(ctx
->opcode
);
1141 if (rS(ctx
->opcode
) == rA(ctx
->opcode
) && uimm
== 0) {
1143 /* XXX: should handle special NOPs for POWER series */
1146 gen_op_load_gpr_T0(rS(ctx
->opcode
));
1147 if (likely(uimm
!= 0))
1149 gen_op_store_T0_gpr(rA(ctx
->opcode
));
1152 GEN_HANDLER(oris
, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER
)
1154 target_ulong uimm
= UIMM(ctx
->opcode
);
1156 if (rS(ctx
->opcode
) == rA(ctx
->opcode
) && uimm
== 0) {
1160 gen_op_load_gpr_T0(rS(ctx
->opcode
));
1161 if (likely(uimm
!= 0))
1162 gen_op_ori(uimm
<< 16);
1163 gen_op_store_T0_gpr(rA(ctx
->opcode
));
1166 GEN_HANDLER(xori
, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER
)
1168 target_ulong uimm
= UIMM(ctx
->opcode
);
1170 if (rS(ctx
->opcode
) == rA(ctx
->opcode
) && uimm
== 0) {
1174 gen_op_load_gpr_T0(rS(ctx
->opcode
));
1175 if (likely(uimm
!= 0))
1177 gen_op_store_T0_gpr(rA(ctx
->opcode
));
1181 GEN_HANDLER(xoris
, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER
)
1183 target_ulong uimm
= UIMM(ctx
->opcode
);
1185 if (rS(ctx
->opcode
) == rA(ctx
->opcode
) && uimm
== 0) {
1189 gen_op_load_gpr_T0(rS(ctx
->opcode
));
1190 if (likely(uimm
!= 0))
1191 gen_op_xori(uimm
<< 16);
1192 gen_op_store_T0_gpr(rA(ctx
->opcode
));
1195 /* popcntb : PowerPC 2.03 specification */
1196 GEN_HANDLER(popcntb
, 0x1F, 0x03, 0x03, 0x0000F801, PPC_203
)
1198 gen_op_load_gpr_T0(rS(ctx
->opcode
));
1199 #if defined(TARGET_PPC64)
1201 gen_op_popcntb_64();
1205 gen_op_store_T0_gpr(rA(ctx
->opcode
));
1208 #if defined(TARGET_PPC64)
1209 /* extsw & extsw. */
1210 GEN_LOGICAL1(extsw
, 0x1E, PPC_64B
);
1212 GEN_LOGICAL1(cntlzd
, 0x01, PPC_64B
);
1215 /*** Integer rotate ***/
1216 /* rlwimi & rlwimi. */
1217 GEN_HANDLER(rlwimi
, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER
)
1220 uint32_t mb
, me
, sh
;
1222 mb
= MB(ctx
->opcode
);
1223 me
= ME(ctx
->opcode
);
1224 sh
= SH(ctx
->opcode
);
1225 if (likely(sh
== 0)) {
1226 if (likely(mb
== 0 && me
== 31)) {
1227 gen_op_load_gpr_T0(rS(ctx
->opcode
));
1229 } else if (likely(mb
== 31 && me
== 0)) {
1230 gen_op_load_gpr_T0(rA(ctx
->opcode
));
1233 gen_op_load_gpr_T0(rS(ctx
->opcode
));
1234 gen_op_load_gpr_T1(rA(ctx
->opcode
));
1237 gen_op_load_gpr_T0(rS(ctx
->opcode
));
1238 gen_op_load_gpr_T1(rA(ctx
->opcode
));
1239 gen_op_rotli32_T0(SH(ctx
->opcode
));
1241 #if defined(TARGET_PPC64)
1245 mask
= MASK(mb
, me
);
1246 gen_op_andi_T0(mask
);
1247 gen_op_andi_T1(~mask
);
1250 gen_op_store_T0_gpr(rA(ctx
->opcode
));
1251 if (unlikely(Rc(ctx
->opcode
) != 0))
1254 /* rlwinm & rlwinm. */
1255 GEN_HANDLER(rlwinm
, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER
)
1257 uint32_t mb
, me
, sh
;
1259 sh
= SH(ctx
->opcode
);
1260 mb
= MB(ctx
->opcode
);
1261 me
= ME(ctx
->opcode
);
1262 gen_op_load_gpr_T0(rS(ctx
->opcode
));
1263 if (likely(sh
== 0)) {
1266 if (likely(mb
== 0)) {
1267 if (likely(me
== 31)) {
1268 gen_op_rotli32_T0(sh
);
1270 } else if (likely(me
== (31 - sh
))) {
1274 } else if (likely(me
== 31)) {
1275 if (likely(sh
== (32 - mb
))) {
1280 gen_op_rotli32_T0(sh
);
1282 #if defined(TARGET_PPC64)
1286 gen_op_andi_T0(MASK(mb
, me
));
1288 gen_op_store_T0_gpr(rA(ctx
->opcode
));
1289 if (unlikely(Rc(ctx
->opcode
) != 0))
1292 /* rlwnm & rlwnm. */
1293 GEN_HANDLER(rlwnm
, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER
)
1297 mb
= MB(ctx
->opcode
);
1298 me
= ME(ctx
->opcode
);
1299 gen_op_load_gpr_T0(rS(ctx
->opcode
));
1300 gen_op_load_gpr_T1(rB(ctx
->opcode
));
1301 gen_op_rotl32_T0_T1();
1302 if (unlikely(mb
!= 0 || me
!= 31)) {
1303 #if defined(TARGET_PPC64)
1307 gen_op_andi_T0(MASK(mb
, me
));
1309 gen_op_store_T0_gpr(rA(ctx
->opcode
));
1310 if (unlikely(Rc(ctx
->opcode
) != 0))
1314 #if defined(TARGET_PPC64)
1315 #define GEN_PPC64_R2(name, opc1, opc2) \
1316 GEN_HANDLER(name##0, opc1, opc2, 0xFF, 0x00000000, PPC_64B) \
1318 gen_##name(ctx, 0); \
1320 GEN_HANDLER(name##1, opc1, opc2 | 0x10, 0xFF, 0x00000000, PPC_64B) \
1322 gen_##name(ctx, 1); \
1324 #define GEN_PPC64_R4(name, opc1, opc2) \
1325 GEN_HANDLER(name##0, opc1, opc2, 0xFF, 0x00000000, PPC_64B) \
1327 gen_##name(ctx, 0, 0); \
1329 GEN_HANDLER(name##1, opc1, opc2 | 0x01, 0xFF, 0x00000000, PPC_64B) \
1331 gen_##name(ctx, 0, 1); \
1333 GEN_HANDLER(name##2, opc1, opc2 | 0x10, 0xFF, 0x00000000, PPC_64B) \
1335 gen_##name(ctx, 1, 0); \
1337 GEN_HANDLER(name##3, opc1, opc2 | 0x11, 0xFF, 0x00000000, PPC_64B) \
1339 gen_##name(ctx, 1, 1); \
1342 static inline void gen_andi_T0_64 (DisasContext
*ctx
, uint64_t mask
)
1345 gen_op_andi_T0_64(mask
>> 32, mask
& 0xFFFFFFFF);
1347 gen_op_andi_T0(mask
);
1350 static inline void gen_andi_T1_64 (DisasContext
*ctx
, uint64_t mask
)
1353 gen_op_andi_T1_64(mask
>> 32, mask
& 0xFFFFFFFF);
1355 gen_op_andi_T1(mask
);
1358 static inline void gen_rldinm (DisasContext
*ctx
, uint32_t mb
, uint32_t me
,
1361 gen_op_load_gpr_T0(rS(ctx
->opcode
));
1362 if (likely(sh
== 0)) {
1365 if (likely(mb
== 0)) {
1366 if (likely(me
== 63)) {
1367 gen_op_rotli64_T0(sh
);
1369 } else if (likely(me
== (63 - sh
))) {
1373 } else if (likely(me
== 63)) {
1374 if (likely(sh
== (64 - mb
))) {
1375 gen_op_srli_T0_64(mb
);
1379 gen_op_rotli64_T0(sh
);
1381 gen_andi_T0_64(ctx
, MASK(mb
, me
));
1383 gen_op_store_T0_gpr(rA(ctx
->opcode
));
1384 if (unlikely(Rc(ctx
->opcode
) != 0))
1387 /* rldicl - rldicl. */
1388 static inline void gen_rldicl (DisasContext
*ctx
, int mbn
, int shn
)
1392 sh
= SH(ctx
->opcode
) | (shn
<< 5);
1393 mb
= MB(ctx
->opcode
) | (mbn
<< 5);
1394 gen_rldinm(ctx
, mb
, 63, sh
);
1396 GEN_PPC64_R4(rldicl
, 0x1E, 0x00);
1397 /* rldicr - rldicr. */
1398 static inline void gen_rldicr (DisasContext
*ctx
, int men
, int shn
)
1402 sh
= SH(ctx
->opcode
) | (shn
<< 5);
1403 me
= MB(ctx
->opcode
) | (men
<< 5);
1404 gen_rldinm(ctx
, 0, me
, sh
);
1406 GEN_PPC64_R4(rldicr
, 0x1E, 0x02);
1407 /* rldic - rldic. */
1408 static inline void gen_rldic (DisasContext
*ctx
, int mbn
, int shn
)
1412 sh
= SH(ctx
->opcode
) | (shn
<< 5);
1413 mb
= MB(ctx
->opcode
) | (mbn
<< 5);
1414 gen_rldinm(ctx
, mb
, 63 - sh
, sh
);
1416 GEN_PPC64_R4(rldic
, 0x1E, 0x04);
1418 static inline void gen_rldnm (DisasContext
*ctx
, uint32_t mb
, uint32_t me
)
1420 gen_op_load_gpr_T0(rS(ctx
->opcode
));
1421 gen_op_load_gpr_T1(rB(ctx
->opcode
));
1422 gen_op_rotl64_T0_T1();
1423 if (unlikely(mb
!= 0 || me
!= 63)) {
1424 gen_andi_T0_64(ctx
, MASK(mb
, me
));
1426 gen_op_store_T0_gpr(rA(ctx
->opcode
));
1427 if (unlikely(Rc(ctx
->opcode
) != 0))
1431 /* rldcl - rldcl. */
1432 static inline void gen_rldcl (DisasContext
*ctx
, int mbn
)
1436 mb
= MB(ctx
->opcode
) | (mbn
<< 5);
1437 gen_rldnm(ctx
, mb
, 63);
1439 GEN_PPC64_R2(rldcl
, 0x1E, 0x08);
1440 /* rldcr - rldcr. */
1441 static inline void gen_rldcr (DisasContext
*ctx
, int men
)
1445 me
= MB(ctx
->opcode
) | (men
<< 5);
1446 gen_rldnm(ctx
, 0, me
);
1448 GEN_PPC64_R2(rldcr
, 0x1E, 0x09);
1449 /* rldimi - rldimi. */
1450 static inline void gen_rldimi (DisasContext
*ctx
, int mbn
, int shn
)
1455 sh
= SH(ctx
->opcode
) | (shn
<< 5);
1456 mb
= MB(ctx
->opcode
) | (mbn
<< 5);
1457 if (likely(sh
== 0)) {
1458 if (likely(mb
== 0)) {
1459 gen_op_load_gpr_T0(rS(ctx
->opcode
));
1461 } else if (likely(mb
== 63)) {
1462 gen_op_load_gpr_T0(rA(ctx
->opcode
));
1465 gen_op_load_gpr_T0(rS(ctx
->opcode
));
1466 gen_op_load_gpr_T1(rA(ctx
->opcode
));
1469 gen_op_load_gpr_T0(rS(ctx
->opcode
));
1470 gen_op_load_gpr_T1(rA(ctx
->opcode
));
1471 gen_op_rotli64_T0(sh
);
1473 mask
= MASK(mb
, 63 - sh
);
1474 gen_andi_T0_64(ctx
, mask
);
1475 gen_andi_T1_64(ctx
, ~mask
);
1478 gen_op_store_T0_gpr(rA(ctx
->opcode
));
1479 if (unlikely(Rc(ctx
->opcode
) != 0))
1482 GEN_PPC64_R4(rldimi
, 0x1E, 0x06);
1485 /*** Integer shift ***/
1487 __GEN_LOGICAL2(slw
, 0x18, 0x00, PPC_INTEGER
);
1489 __GEN_LOGICAL2(sraw
, 0x18, 0x18, PPC_INTEGER
);
1490 /* srawi & srawi. */
1491 GEN_HANDLER(srawi
, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER
)
1494 gen_op_load_gpr_T0(rS(ctx
->opcode
));
1495 if (SH(ctx
->opcode
) != 0) {
1496 gen_op_move_T1_T0();
1497 mb
= 32 - SH(ctx
->opcode
);
1499 #if defined(TARGET_PPC64)
1503 gen_op_srawi(SH(ctx
->opcode
), MASK(mb
, me
));
1505 gen_op_store_T0_gpr(rA(ctx
->opcode
));
1506 if (unlikely(Rc(ctx
->opcode
) != 0))
1510 __GEN_LOGICAL2(srw
, 0x18, 0x10, PPC_INTEGER
);
1512 #if defined(TARGET_PPC64)
1514 __GEN_LOGICAL2(sld
, 0x1B, 0x00, PPC_64B
);
1516 __GEN_LOGICAL2(srad
, 0x1A, 0x18, PPC_64B
);
1517 /* sradi & sradi. */
1518 static inline void gen_sradi (DisasContext
*ctx
, int n
)
1523 gen_op_load_gpr_T0(rS(ctx
->opcode
));
1524 sh
= SH(ctx
->opcode
) + (n
<< 5);
1526 gen_op_move_T1_T0();
1527 mb
= 64 - SH(ctx
->opcode
);
1529 mask
= MASK(mb
, me
);
1530 gen_op_sradi(sh
, mask
>> 32, mask
);
1532 gen_op_store_T0_gpr(rA(ctx
->opcode
));
1533 if (unlikely(Rc(ctx
->opcode
) != 0))
1536 GEN_HANDLER(sradi0
, 0x1F, 0x1A, 0x19, 0x00000000, PPC_64B
)
1540 GEN_HANDLER(sradi1
, 0x1F, 0x1B, 0x19, 0x00000000, PPC_64B
)
1545 __GEN_LOGICAL2(srd
, 0x1B, 0x10, PPC_64B
);
1548 /*** Floating-Point arithmetic ***/
1549 #define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, type) \
1550 GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, type) \
1552 if (unlikely(!ctx->fpu_enabled)) { \
1553 RET_EXCP(ctx, EXCP_NO_FP, 0); \
1556 gen_op_reset_scrfx(); \
1557 gen_op_load_fpr_FT0(rA(ctx->opcode)); \
1558 gen_op_load_fpr_FT1(rC(ctx->opcode)); \
1559 gen_op_load_fpr_FT2(rB(ctx->opcode)); \
1564 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
1565 if (unlikely(Rc(ctx->opcode) != 0)) \
1569 #define GEN_FLOAT_ACB(name, op2, type) \
1570 _GEN_FLOAT_ACB(name, name, 0x3F, op2, 0, type); \
1571 _GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, type);
1573 #define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat) \
1574 GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \
1576 if (unlikely(!ctx->fpu_enabled)) { \
1577 RET_EXCP(ctx, EXCP_NO_FP, 0); \
1580 gen_op_reset_scrfx(); \
1581 gen_op_load_fpr_FT0(rA(ctx->opcode)); \
1582 gen_op_load_fpr_FT1(rB(ctx->opcode)); \
1587 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
1588 if (unlikely(Rc(ctx->opcode) != 0)) \
1591 #define GEN_FLOAT_AB(name, op2, inval) \
1592 _GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0); \
1593 _GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1);
1595 #define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat) \
1596 GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \
1598 if (unlikely(!ctx->fpu_enabled)) { \
1599 RET_EXCP(ctx, EXCP_NO_FP, 0); \
1602 gen_op_reset_scrfx(); \
1603 gen_op_load_fpr_FT0(rA(ctx->opcode)); \
1604 gen_op_load_fpr_FT1(rC(ctx->opcode)); \
1609 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
1610 if (unlikely(Rc(ctx->opcode) != 0)) \
1613 #define GEN_FLOAT_AC(name, op2, inval) \
1614 _GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0); \
1615 _GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1);
1617 #define GEN_FLOAT_B(name, op2, op3, type) \
1618 GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, type) \
1620 if (unlikely(!ctx->fpu_enabled)) { \
1621 RET_EXCP(ctx, EXCP_NO_FP, 0); \
1624 gen_op_reset_scrfx(); \
1625 gen_op_load_fpr_FT0(rB(ctx->opcode)); \
1627 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
1628 if (unlikely(Rc(ctx->opcode) != 0)) \
1632 #define GEN_FLOAT_BS(name, op1, op2, type) \
1633 GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, type) \
1635 if (unlikely(!ctx->fpu_enabled)) { \
1636 RET_EXCP(ctx, EXCP_NO_FP, 0); \
1639 gen_op_reset_scrfx(); \
1640 gen_op_load_fpr_FT0(rB(ctx->opcode)); \
1642 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
1643 if (unlikely(Rc(ctx->opcode) != 0)) \
1648 GEN_FLOAT_AB(add
, 0x15, 0x000007C0);
1650 GEN_FLOAT_AB(div
, 0x12, 0x000007C0);
1652 GEN_FLOAT_AC(mul
, 0x19, 0x0000F800);
1655 GEN_FLOAT_BS(res
, 0x3B, 0x18, PPC_FLOAT_FRES
);
1658 GEN_FLOAT_BS(rsqrte
, 0x3F, 0x1A, PPC_FLOAT_FRSQRTE
);
1661 _GEN_FLOAT_ACB(sel
, sel
, 0x3F, 0x17, 0, PPC_FLOAT_FSEL
);
1663 GEN_FLOAT_AB(sub
, 0x14, 0x000007C0);
1666 GEN_HANDLER(fsqrt
, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT
)
1668 if (unlikely(!ctx
->fpu_enabled
)) {
1669 RET_EXCP(ctx
, EXCP_NO_FP
, 0);
1672 gen_op_reset_scrfx();
1673 gen_op_load_fpr_FT0(rB(ctx
->opcode
));
1675 gen_op_store_FT0_fpr(rD(ctx
->opcode
));
1676 if (unlikely(Rc(ctx
->opcode
) != 0))
1680 GEN_HANDLER(fsqrts
, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT
)
1682 if (unlikely(!ctx
->fpu_enabled
)) {
1683 RET_EXCP(ctx
, EXCP_NO_FP
, 0);
1686 gen_op_reset_scrfx();
1687 gen_op_load_fpr_FT0(rB(ctx
->opcode
));
1690 gen_op_store_FT0_fpr(rD(ctx
->opcode
));
1691 if (unlikely(Rc(ctx
->opcode
) != 0))
1695 /*** Floating-Point multiply-and-add ***/
1696 /* fmadd - fmadds */
1697 GEN_FLOAT_ACB(madd
, 0x1D, PPC_FLOAT
);
1698 /* fmsub - fmsubs */
1699 GEN_FLOAT_ACB(msub
, 0x1C, PPC_FLOAT
);
1700 /* fnmadd - fnmadds */
1701 GEN_FLOAT_ACB(nmadd
, 0x1F, PPC_FLOAT
);
1702 /* fnmsub - fnmsubs */
1703 GEN_FLOAT_ACB(nmsub
, 0x1E, PPC_FLOAT
);
1705 /*** Floating-Point round & convert ***/
1707 GEN_FLOAT_B(ctiw
, 0x0E, 0x00, PPC_FLOAT
);
1709 GEN_FLOAT_B(ctiwz
, 0x0F, 0x00, PPC_FLOAT
);
1711 GEN_FLOAT_B(rsp
, 0x0C, 0x00, PPC_FLOAT
);
1712 #if defined(TARGET_PPC64)
1714 GEN_FLOAT_B(cfid
, 0x0E, 0x1A, PPC_64B
);
1716 GEN_FLOAT_B(ctid
, 0x0E, 0x19, PPC_64B
);
1718 GEN_FLOAT_B(ctidz
, 0x0F, 0x19, PPC_64B
);
1721 /*** Floating-Point compare ***/
1723 GEN_HANDLER(fcmpo
, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT
)
1725 if (unlikely(!ctx
->fpu_enabled
)) {
1726 RET_EXCP(ctx
, EXCP_NO_FP
, 0);
1729 gen_op_reset_scrfx();
1730 gen_op_load_fpr_FT0(rA(ctx
->opcode
));
1731 gen_op_load_fpr_FT1(rB(ctx
->opcode
));
1733 gen_op_store_T0_crf(crfD(ctx
->opcode
));
1737 GEN_HANDLER(fcmpu
, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT
)
1739 if (unlikely(!ctx
->fpu_enabled
)) {
1740 RET_EXCP(ctx
, EXCP_NO_FP
, 0);
1743 gen_op_reset_scrfx();
1744 gen_op_load_fpr_FT0(rA(ctx
->opcode
));
1745 gen_op_load_fpr_FT1(rB(ctx
->opcode
));
1747 gen_op_store_T0_crf(crfD(ctx
->opcode
));
1750 /*** Floating-point move ***/
1752 GEN_FLOAT_B(abs
, 0x08, 0x08, PPC_FLOAT
);
1755 GEN_HANDLER(fmr
, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT
)
1757 if (unlikely(!ctx
->fpu_enabled
)) {
1758 RET_EXCP(ctx
, EXCP_NO_FP
, 0);
1761 gen_op_reset_scrfx();
1762 gen_op_load_fpr_FT0(rB(ctx
->opcode
));
1763 gen_op_store_FT0_fpr(rD(ctx
->opcode
));
1764 if (unlikely(Rc(ctx
->opcode
) != 0))
1769 GEN_FLOAT_B(nabs
, 0x08, 0x04, PPC_FLOAT
);
1771 GEN_FLOAT_B(neg
, 0x08, 0x01, PPC_FLOAT
);
1773 /*** Floating-Point status & ctrl register ***/
1775 GEN_HANDLER(mcrfs
, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT
)
1777 if (unlikely(!ctx
->fpu_enabled
)) {
1778 RET_EXCP(ctx
, EXCP_NO_FP
, 0);
1781 gen_op_load_fpscr_T0(crfS(ctx
->opcode
));
1782 gen_op_store_T0_crf(crfD(ctx
->opcode
));
1783 gen_op_clear_fpscr(crfS(ctx
->opcode
));
1787 GEN_HANDLER(mffs
, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT
)
1789 if (unlikely(!ctx
->fpu_enabled
)) {
1790 RET_EXCP(ctx
, EXCP_NO_FP
, 0);
1793 gen_op_load_fpscr();
1794 gen_op_store_FT0_fpr(rD(ctx
->opcode
));
1795 if (unlikely(Rc(ctx
->opcode
) != 0))
1800 GEN_HANDLER(mtfsb0
, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT
)
1804 if (unlikely(!ctx
->fpu_enabled
)) {
1805 RET_EXCP(ctx
, EXCP_NO_FP
, 0);
1808 crb
= crbD(ctx
->opcode
) >> 2;
1809 gen_op_load_fpscr_T0(crb
);
1810 gen_op_andi_T0(~(1 << (crbD(ctx
->opcode
) & 0x03)));
1811 gen_op_store_T0_fpscr(crb
);
1812 if (unlikely(Rc(ctx
->opcode
) != 0))
1817 GEN_HANDLER(mtfsb1
, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT
)
1821 if (unlikely(!ctx
->fpu_enabled
)) {
1822 RET_EXCP(ctx
, EXCP_NO_FP
, 0);
1825 crb
= crbD(ctx
->opcode
) >> 2;
1826 gen_op_load_fpscr_T0(crb
);
1827 gen_op_ori(1 << (crbD(ctx
->opcode
) & 0x03));
1828 gen_op_store_T0_fpscr(crb
);
1829 if (unlikely(Rc(ctx
->opcode
) != 0))
1834 GEN_HANDLER(mtfsf
, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT
)
1836 if (unlikely(!ctx
->fpu_enabled
)) {
1837 RET_EXCP(ctx
, EXCP_NO_FP
, 0);
1840 gen_op_load_fpr_FT0(rB(ctx
->opcode
));
1841 gen_op_store_fpscr(FM(ctx
->opcode
));
1842 if (unlikely(Rc(ctx
->opcode
) != 0))
1847 GEN_HANDLER(mtfsfi
, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT
)
1849 if (unlikely(!ctx
->fpu_enabled
)) {
1850 RET_EXCP(ctx
, EXCP_NO_FP
, 0);
1853 gen_op_store_T0_fpscri(crbD(ctx
->opcode
) >> 2, FPIMM(ctx
->opcode
));
1854 if (unlikely(Rc(ctx
->opcode
) != 0))
1858 /*** Addressing modes ***/
1859 /* Register indirect with immediate index : EA = (rA|0) + SIMM */
1860 static inline void gen_addr_imm_index (DisasContext
*ctx
, int maskl
)
1862 target_long simm
= SIMM(ctx
->opcode
);
1866 if (rA(ctx
->opcode
) == 0) {
1869 gen_op_load_gpr_T0(rA(ctx
->opcode
));
1870 if (likely(simm
!= 0))
1873 #ifdef DEBUG_MEMORY_ACCESSES
1874 gen_op_print_mem_EA();
1878 static inline void gen_addr_reg_index (DisasContext
*ctx
)
1880 if (rA(ctx
->opcode
) == 0) {
1881 gen_op_load_gpr_T0(rB(ctx
->opcode
));
1883 gen_op_load_gpr_T0(rA(ctx
->opcode
));
1884 gen_op_load_gpr_T1(rB(ctx
->opcode
));
1887 #ifdef DEBUG_MEMORY_ACCESSES
1888 gen_op_print_mem_EA();
1892 static inline void gen_addr_register (DisasContext
*ctx
)
1894 if (rA(ctx
->opcode
) == 0) {
1897 gen_op_load_gpr_T0(rA(ctx
->opcode
));
1899 #ifdef DEBUG_MEMORY_ACCESSES
1900 gen_op_print_mem_EA();
1904 /*** Integer load ***/
1905 #define op_ldst(name) (*gen_op_##name[ctx->mem_idx])()
1906 #if defined(CONFIG_USER_ONLY)
1907 #if defined(TARGET_PPC64)
1908 #define OP_LD_TABLE(width) \
1909 static GenOpFunc *gen_op_l##width[] = { \
1910 &gen_op_l##width##_raw, \
1911 &gen_op_l##width##_le_raw, \
1912 &gen_op_l##width##_64_raw, \
1913 &gen_op_l##width##_le_64_raw, \
1915 #define OP_ST_TABLE(width) \
1916 static GenOpFunc *gen_op_st##width[] = { \
1917 &gen_op_st##width##_raw, \
1918 &gen_op_st##width##_le_raw, \
1919 &gen_op_st##width##_64_raw, \
1920 &gen_op_st##width##_le_64_raw, \
1922 /* Byte access routine are endian safe */
1923 #define gen_op_stb_le_64_raw gen_op_stb_64_raw
1924 #define gen_op_lbz_le_64_raw gen_op_lbz_64_raw
1926 #define OP_LD_TABLE(width) \
1927 static GenOpFunc *gen_op_l##width[] = { \
1928 &gen_op_l##width##_raw, \
1929 &gen_op_l##width##_le_raw, \
1931 #define OP_ST_TABLE(width) \
1932 static GenOpFunc *gen_op_st##width[] = { \
1933 &gen_op_st##width##_raw, \
1934 &gen_op_st##width##_le_raw, \
1937 /* Byte access routine are endian safe */
1938 #define gen_op_stb_le_raw gen_op_stb_raw
1939 #define gen_op_lbz_le_raw gen_op_lbz_raw
1941 #if defined(TARGET_PPC64)
1942 #define OP_LD_TABLE(width) \
1943 static GenOpFunc *gen_op_l##width[] = { \
1944 &gen_op_l##width##_user, \
1945 &gen_op_l##width##_le_user, \
1946 &gen_op_l##width##_kernel, \
1947 &gen_op_l##width##_le_kernel, \
1948 &gen_op_l##width##_64_user, \
1949 &gen_op_l##width##_le_64_user, \
1950 &gen_op_l##width##_64_kernel, \
1951 &gen_op_l##width##_le_64_kernel, \
1953 #define OP_ST_TABLE(width) \
1954 static GenOpFunc *gen_op_st##width[] = { \
1955 &gen_op_st##width##_user, \
1956 &gen_op_st##width##_le_user, \
1957 &gen_op_st##width##_kernel, \
1958 &gen_op_st##width##_le_kernel, \
1959 &gen_op_st##width##_64_user, \
1960 &gen_op_st##width##_le_64_user, \
1961 &gen_op_st##width##_64_kernel, \
1962 &gen_op_st##width##_le_64_kernel, \
1964 /* Byte access routine are endian safe */
1965 #define gen_op_stb_le_64_user gen_op_stb_64_user
1966 #define gen_op_lbz_le_64_user gen_op_lbz_64_user
1967 #define gen_op_stb_le_64_kernel gen_op_stb_64_kernel
1968 #define gen_op_lbz_le_64_kernel gen_op_lbz_64_kernel
1970 #define OP_LD_TABLE(width) \
1971 static GenOpFunc *gen_op_l##width[] = { \
1972 &gen_op_l##width##_user, \
1973 &gen_op_l##width##_le_user, \
1974 &gen_op_l##width##_kernel, \
1975 &gen_op_l##width##_le_kernel, \
1977 #define OP_ST_TABLE(width) \
1978 static GenOpFunc *gen_op_st##width[] = { \
1979 &gen_op_st##width##_user, \
1980 &gen_op_st##width##_le_user, \
1981 &gen_op_st##width##_kernel, \
1982 &gen_op_st##width##_le_kernel, \
1985 /* Byte access routine are endian safe */
1986 #define gen_op_stb_le_user gen_op_stb_user
1987 #define gen_op_lbz_le_user gen_op_lbz_user
1988 #define gen_op_stb_le_kernel gen_op_stb_kernel
1989 #define gen_op_lbz_le_kernel gen_op_lbz_kernel
1992 #define GEN_LD(width, opc, type) \
1993 GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, type) \
1995 gen_addr_imm_index(ctx, 0); \
1996 op_ldst(l##width); \
1997 gen_op_store_T1_gpr(rD(ctx->opcode)); \
2000 #define GEN_LDU(width, opc, type) \
2001 GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, type) \
2003 if (unlikely(rA(ctx->opcode) == 0 || \
2004 rA(ctx->opcode) == rD(ctx->opcode))) { \
2008 if (type == PPC_64B) \
2009 gen_addr_imm_index(ctx, 1); \
2011 gen_addr_imm_index(ctx, 0); \
2012 op_ldst(l##width); \
2013 gen_op_store_T1_gpr(rD(ctx->opcode)); \
2014 gen_op_store_T0_gpr(rA(ctx->opcode)); \
2017 #define GEN_LDUX(width, opc2, opc3, type) \
2018 GEN_HANDLER(l##width##ux, 0x1F, opc2, opc3, 0x00000001, type) \
2020 if (unlikely(rA(ctx->opcode) == 0 || \
2021 rA(ctx->opcode) == rD(ctx->opcode))) { \
2025 gen_addr_reg_index(ctx); \
2026 op_ldst(l##width); \
2027 gen_op_store_T1_gpr(rD(ctx->opcode)); \
2028 gen_op_store_T0_gpr(rA(ctx->opcode)); \
2031 #define GEN_LDX(width, opc2, opc3, type) \
2032 GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, type) \
2034 gen_addr_reg_index(ctx); \
2035 op_ldst(l##width); \
2036 gen_op_store_T1_gpr(rD(ctx->opcode)); \
2039 #define GEN_LDS(width, op, type) \
2040 OP_LD_TABLE(width); \
2041 GEN_LD(width, op | 0x20, type); \
2042 GEN_LDU(width, op | 0x21, type); \
2043 GEN_LDUX(width, 0x17, op | 0x01, type); \
2044 GEN_LDX(width, 0x17, op | 0x00, type)
2046 /* lbz lbzu lbzux lbzx */
2047 GEN_LDS(bz
, 0x02, PPC_INTEGER
);
2048 /* lha lhau lhaux lhax */
2049 GEN_LDS(ha
, 0x0A, PPC_INTEGER
);
2050 /* lhz lhzu lhzux lhzx */
2051 GEN_LDS(hz
, 0x08, PPC_INTEGER
);
2052 /* lwz lwzu lwzux lwzx */
2053 GEN_LDS(wz
, 0x00, PPC_INTEGER
);
2054 #if defined(TARGET_PPC64)
2058 GEN_LDUX(wa
, 0x15, 0x0B, PPC_64B
);
2060 GEN_LDX(wa
, 0x15, 0x0A, PPC_64B
);
2062 GEN_LDUX(d
, 0x15, 0x01, PPC_64B
);
2064 GEN_LDX(d
, 0x15, 0x00, PPC_64B
);
2065 GEN_HANDLER(ld
, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B
)
2067 if (Rc(ctx
->opcode
)) {
2068 if (unlikely(rA(ctx
->opcode
) == 0 ||
2069 rA(ctx
->opcode
) == rD(ctx
->opcode
))) {
2074 gen_addr_imm_index(ctx
, 1);
2075 if (ctx
->opcode
& 0x02) {
2076 /* lwa (lwau is undefined) */
2082 gen_op_store_T1_gpr(rD(ctx
->opcode
));
2083 if (Rc(ctx
->opcode
))
2084 gen_op_store_T0_gpr(rA(ctx
->opcode
));
2088 /*** Integer store ***/
2089 #define GEN_ST(width, opc, type) \
2090 GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, type) \
2092 gen_addr_imm_index(ctx, 0); \
2093 gen_op_load_gpr_T1(rS(ctx->opcode)); \
2094 op_ldst(st##width); \
2097 #define GEN_STU(width, opc, type) \
2098 GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, type) \
2100 if (unlikely(rA(ctx->opcode) == 0)) { \
2104 if (type == PPC_64B) \
2105 gen_addr_imm_index(ctx, 1); \
2107 gen_addr_imm_index(ctx, 0); \
2108 gen_op_load_gpr_T1(rS(ctx->opcode)); \
2109 op_ldst(st##width); \
2110 gen_op_store_T0_gpr(rA(ctx->opcode)); \
2113 #define GEN_STUX(width, opc2, opc3, type) \
2114 GEN_HANDLER(st##width##ux, 0x1F, opc2, opc3, 0x00000001, type) \
2116 if (unlikely(rA(ctx->opcode) == 0)) { \
2120 gen_addr_reg_index(ctx); \
2121 gen_op_load_gpr_T1(rS(ctx->opcode)); \
2122 op_ldst(st##width); \
2123 gen_op_store_T0_gpr(rA(ctx->opcode)); \
2126 #define GEN_STX(width, opc2, opc3, type) \
2127 GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, type) \
2129 gen_addr_reg_index(ctx); \
2130 gen_op_load_gpr_T1(rS(ctx->opcode)); \
2131 op_ldst(st##width); \
2134 #define GEN_STS(width, op, type) \
2135 OP_ST_TABLE(width); \
2136 GEN_ST(width, op | 0x20, type); \
2137 GEN_STU(width, op | 0x21, type); \
2138 GEN_STUX(width, 0x17, op | 0x01, type); \
2139 GEN_STX(width, 0x17, op | 0x00, type)
2141 /* stb stbu stbux stbx */
2142 GEN_STS(b
, 0x06, PPC_INTEGER
);
2143 /* sth sthu sthux sthx */
2144 GEN_STS(h
, 0x0C, PPC_INTEGER
);
2145 /* stw stwu stwux stwx */
2146 GEN_STS(w
, 0x04, PPC_INTEGER
);
2147 #if defined(TARGET_PPC64)
2149 GEN_STUX(d
, 0x15, 0x05, PPC_64B
);
2150 GEN_STX(d
, 0x15, 0x04, PPC_64B
);
2151 GEN_HANDLER(std
, 0x3E, 0xFF, 0xFF, 0x00000002, PPC_64B
)
2153 if (Rc(ctx
->opcode
)) {
2154 if (unlikely(rA(ctx
->opcode
) == 0)) {
2159 gen_addr_imm_index(ctx
, 1);
2160 gen_op_load_gpr_T1(rS(ctx
->opcode
));
2162 if (Rc(ctx
->opcode
))
2163 gen_op_store_T0_gpr(rA(ctx
->opcode
));
2166 /*** Integer load and store with byte reverse ***/
2169 GEN_LDX(hbr
, 0x16, 0x18, PPC_INTEGER
);
2172 GEN_LDX(wbr
, 0x16, 0x10, PPC_INTEGER
);
2175 GEN_STX(hbr
, 0x16, 0x1C, PPC_INTEGER
);
2178 GEN_STX(wbr
, 0x16, 0x14, PPC_INTEGER
);
2180 /*** Integer load and store multiple ***/
2181 #define op_ldstm(name, reg) (*gen_op_##name[ctx->mem_idx])(reg)
2182 #if defined(TARGET_PPC64)
2183 #if defined(CONFIG_USER_ONLY)
2184 static GenOpFunc1
*gen_op_lmw
[] = {
2188 &gen_op_lmw_le_64_raw
,
2190 static GenOpFunc1
*gen_op_stmw
[] = {
2191 &gen_op_stmw_64_raw
,
2192 &gen_op_stmw_le_64_raw
,
2195 static GenOpFunc1
*gen_op_lmw
[] = {
2197 &gen_op_lmw_le_user
,
2199 &gen_op_lmw_le_kernel
,
2200 &gen_op_lmw_64_user
,
2201 &gen_op_lmw_le_64_user
,
2202 &gen_op_lmw_64_kernel
,
2203 &gen_op_lmw_le_64_kernel
,
2205 static GenOpFunc1
*gen_op_stmw
[] = {
2207 &gen_op_stmw_le_user
,
2208 &gen_op_stmw_kernel
,
2209 &gen_op_stmw_le_kernel
,
2210 &gen_op_stmw_64_user
,
2211 &gen_op_stmw_le_64_user
,
2212 &gen_op_stmw_64_kernel
,
2213 &gen_op_stmw_le_64_kernel
,
2217 #if defined(CONFIG_USER_ONLY)
2218 static GenOpFunc1
*gen_op_lmw
[] = {
2222 static GenOpFunc1
*gen_op_stmw
[] = {
2224 &gen_op_stmw_le_raw
,
2227 static GenOpFunc1
*gen_op_lmw
[] = {
2229 &gen_op_lmw_le_user
,
2231 &gen_op_lmw_le_kernel
,
2233 static GenOpFunc1
*gen_op_stmw
[] = {
2235 &gen_op_stmw_le_user
,
2236 &gen_op_stmw_kernel
,
2237 &gen_op_stmw_le_kernel
,
2243 GEN_HANDLER(lmw
, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER
)
2245 /* NIP cannot be restored if the memory exception comes from an helper */
2246 gen_update_nip(ctx
, ctx
->nip
- 4);
2247 gen_addr_imm_index(ctx
, 0);
2248 op_ldstm(lmw
, rD(ctx
->opcode
));
2252 GEN_HANDLER(stmw
, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER
)
2254 /* NIP cannot be restored if the memory exception comes from an helper */
2255 gen_update_nip(ctx
, ctx
->nip
- 4);
2256 gen_addr_imm_index(ctx
, 0);
2257 op_ldstm(stmw
, rS(ctx
->opcode
));
2260 /*** Integer load and store strings ***/
2261 #define op_ldsts(name, start) (*gen_op_##name[ctx->mem_idx])(start)
2262 #define op_ldstsx(name, rd, ra, rb) (*gen_op_##name[ctx->mem_idx])(rd, ra, rb)
2263 #if defined(TARGET_PPC64)
2264 #if defined(CONFIG_USER_ONLY)
2265 static GenOpFunc1
*gen_op_lswi
[] = {
2267 &gen_op_lswi_le_raw
,
2268 &gen_op_lswi_64_raw
,
2269 &gen_op_lswi_le_64_raw
,
2271 static GenOpFunc3
*gen_op_lswx
[] = {
2273 &gen_op_lswx_le_raw
,
2274 &gen_op_lswx_64_raw
,
2275 &gen_op_lswx_le_64_raw
,
2277 static GenOpFunc1
*gen_op_stsw
[] = {
2279 &gen_op_stsw_le_raw
,
2280 &gen_op_stsw_64_raw
,
2281 &gen_op_stsw_le_64_raw
,
2284 static GenOpFunc1
*gen_op_lswi
[] = {
2286 &gen_op_lswi_le_user
,
2287 &gen_op_lswi_kernel
,
2288 &gen_op_lswi_le_kernel
,
2289 &gen_op_lswi_64_user
,
2290 &gen_op_lswi_le_64_user
,
2291 &gen_op_lswi_64_kernel
,
2292 &gen_op_lswi_le_64_kernel
,
2294 static GenOpFunc3
*gen_op_lswx
[] = {
2296 &gen_op_lswx_le_user
,
2297 &gen_op_lswx_kernel
,
2298 &gen_op_lswx_le_kernel
,
2299 &gen_op_lswx_64_user
,
2300 &gen_op_lswx_le_64_user
,
2301 &gen_op_lswx_64_kernel
,
2302 &gen_op_lswx_le_64_kernel
,
2304 static GenOpFunc1
*gen_op_stsw
[] = {
2306 &gen_op_stsw_le_user
,
2307 &gen_op_stsw_kernel
,
2308 &gen_op_stsw_le_kernel
,
2309 &gen_op_stsw_64_user
,
2310 &gen_op_stsw_le_64_user
,
2311 &gen_op_stsw_64_kernel
,
2312 &gen_op_stsw_le_64_kernel
,
2316 #if defined(CONFIG_USER_ONLY)
2317 static GenOpFunc1
*gen_op_lswi
[] = {
2319 &gen_op_lswi_le_raw
,
2321 static GenOpFunc3
*gen_op_lswx
[] = {
2323 &gen_op_lswx_le_raw
,
2325 static GenOpFunc1
*gen_op_stsw
[] = {
2327 &gen_op_stsw_le_raw
,
2330 static GenOpFunc1
*gen_op_lswi
[] = {
2332 &gen_op_lswi_le_user
,
2333 &gen_op_lswi_kernel
,
2334 &gen_op_lswi_le_kernel
,
2336 static GenOpFunc3
*gen_op_lswx
[] = {
2338 &gen_op_lswx_le_user
,
2339 &gen_op_lswx_kernel
,
2340 &gen_op_lswx_le_kernel
,
2342 static GenOpFunc1
*gen_op_stsw
[] = {
2344 &gen_op_stsw_le_user
,
2345 &gen_op_stsw_kernel
,
2346 &gen_op_stsw_le_kernel
,
2352 /* PowerPC32 specification says we must generate an exception if
2353 * rA is in the range of registers to be loaded.
2354 * In an other hand, IBM says this is valid, but rA won't be loaded.
2355 * For now, I'll follow the spec...
2357 GEN_HANDLER(lswi
, 0x1F, 0x15, 0x12, 0x00000001, PPC_INTEGER
)
2359 int nb
= NB(ctx
->opcode
);
2360 int start
= rD(ctx
->opcode
);
2361 int ra
= rA(ctx
->opcode
);
2367 if (unlikely(((start
+ nr
) > 32 &&
2368 start
<= ra
&& (start
+ nr
- 32) > ra
) ||
2369 ((start
+ nr
) <= 32 && start
<= ra
&& (start
+ nr
) > ra
))) {
2370 RET_EXCP(ctx
, EXCP_PROGRAM
, EXCP_INVAL
| EXCP_INVAL_LSWX
);
2373 /* NIP cannot be restored if the memory exception comes from an helper */
2374 gen_update_nip(ctx
, ctx
->nip
- 4);
2375 gen_addr_register(ctx
);
2377 op_ldsts(lswi
, start
);
2381 GEN_HANDLER(lswx
, 0x1F, 0x15, 0x10, 0x00000001, PPC_INTEGER
)
2383 int ra
= rA(ctx
->opcode
);
2384 int rb
= rB(ctx
->opcode
);
2386 /* NIP cannot be restored if the memory exception comes from an helper */
2387 gen_update_nip(ctx
, ctx
->nip
- 4);
2388 gen_addr_reg_index(ctx
);
2392 gen_op_load_xer_bc();
2393 op_ldstsx(lswx
, rD(ctx
->opcode
), ra
, rb
);
2397 GEN_HANDLER(stswi
, 0x1F, 0x15, 0x16, 0x00000001, PPC_INTEGER
)
2399 int nb
= NB(ctx
->opcode
);
2401 /* NIP cannot be restored if the memory exception comes from an helper */
2402 gen_update_nip(ctx
, ctx
->nip
- 4);
2403 gen_addr_register(ctx
);
2407 op_ldsts(stsw
, rS(ctx
->opcode
));
2411 GEN_HANDLER(stswx
, 0x1F, 0x15, 0x14, 0x00000001, PPC_INTEGER
)
2413 /* NIP cannot be restored if the memory exception comes from an helper */
2414 gen_update_nip(ctx
, ctx
->nip
- 4);
2415 gen_addr_reg_index(ctx
);
2416 gen_op_load_xer_bc();
2417 op_ldsts(stsw
, rS(ctx
->opcode
));
2420 /*** Memory synchronisation ***/
2422 GEN_HANDLER(eieio
, 0x1F, 0x16, 0x1A, 0x03FF0801, PPC_MEM_EIEIO
)
2427 GEN_HANDLER(isync
, 0x13, 0x16, 0x04, 0x03FF0801, PPC_MEM
)
2431 #define op_lwarx() (*gen_op_lwarx[ctx->mem_idx])()
2432 #define op_stwcx() (*gen_op_stwcx[ctx->mem_idx])()
2433 #if defined(TARGET_PPC64)
2434 #if defined(CONFIG_USER_ONLY)
2435 static GenOpFunc
*gen_op_lwarx
[] = {
2437 &gen_op_lwarx_le_raw
,
2438 &gen_op_lwarx_64_raw
,
2439 &gen_op_lwarx_le_64_raw
,
2441 static GenOpFunc
*gen_op_stwcx
[] = {
2443 &gen_op_stwcx_le_raw
,
2444 &gen_op_stwcx_64_raw
,
2445 &gen_op_stwcx_le_64_raw
,
2448 static GenOpFunc
*gen_op_lwarx
[] = {
2450 &gen_op_lwarx_le_user
,
2451 &gen_op_lwarx_kernel
,
2452 &gen_op_lwarx_le_kernel
,
2453 &gen_op_lwarx_64_user
,
2454 &gen_op_lwarx_le_64_user
,
2455 &gen_op_lwarx_64_kernel
,
2456 &gen_op_lwarx_le_64_kernel
,
2458 static GenOpFunc
*gen_op_stwcx
[] = {
2460 &gen_op_stwcx_le_user
,
2461 &gen_op_stwcx_kernel
,
2462 &gen_op_stwcx_le_kernel
,
2463 &gen_op_stwcx_64_user
,
2464 &gen_op_stwcx_le_64_user
,
2465 &gen_op_stwcx_64_kernel
,
2466 &gen_op_stwcx_le_64_kernel
,
2470 #if defined(CONFIG_USER_ONLY)
2471 static GenOpFunc
*gen_op_lwarx
[] = {
2473 &gen_op_lwarx_le_raw
,
2475 static GenOpFunc
*gen_op_stwcx
[] = {
2477 &gen_op_stwcx_le_raw
,
2480 static GenOpFunc
*gen_op_lwarx
[] = {
2482 &gen_op_lwarx_le_user
,
2483 &gen_op_lwarx_kernel
,
2484 &gen_op_lwarx_le_kernel
,
2486 static GenOpFunc
*gen_op_stwcx
[] = {
2488 &gen_op_stwcx_le_user
,
2489 &gen_op_stwcx_kernel
,
2490 &gen_op_stwcx_le_kernel
,
2496 GEN_HANDLER(lwarx
, 0x1F, 0x14, 0x00, 0x00000001, PPC_RES
)
2498 gen_addr_reg_index(ctx
);
2500 gen_op_store_T1_gpr(rD(ctx
->opcode
));
2504 GEN_HANDLER(stwcx_
, 0x1F, 0x16, 0x04, 0x00000000, PPC_RES
)
2506 gen_addr_reg_index(ctx
);
2507 gen_op_load_gpr_T1(rS(ctx
->opcode
));
2511 #if defined(TARGET_PPC64)
2512 #define op_ldarx() (*gen_op_ldarx[ctx->mem_idx])()
2513 #define op_stdcx() (*gen_op_stdcx[ctx->mem_idx])()
2514 #if defined(CONFIG_USER_ONLY)
2515 static GenOpFunc
*gen_op_ldarx
[] = {
2517 &gen_op_ldarx_le_raw
,
2518 &gen_op_ldarx_64_raw
,
2519 &gen_op_ldarx_le_64_raw
,
2521 static GenOpFunc
*gen_op_stdcx
[] = {
2523 &gen_op_stdcx_le_raw
,
2524 &gen_op_stdcx_64_raw
,
2525 &gen_op_stdcx_le_64_raw
,
2528 static GenOpFunc
*gen_op_ldarx
[] = {
2530 &gen_op_ldarx_le_user
,
2531 &gen_op_ldarx_kernel
,
2532 &gen_op_ldarx_le_kernel
,
2533 &gen_op_ldarx_64_user
,
2534 &gen_op_ldarx_le_64_user
,
2535 &gen_op_ldarx_64_kernel
,
2536 &gen_op_ldarx_le_64_kernel
,
2538 static GenOpFunc
*gen_op_stdcx
[] = {
2540 &gen_op_stdcx_le_user
,
2541 &gen_op_stdcx_kernel
,
2542 &gen_op_stdcx_le_kernel
,
2543 &gen_op_stdcx_64_user
,
2544 &gen_op_stdcx_le_64_user
,
2545 &gen_op_stdcx_64_kernel
,
2546 &gen_op_stdcx_le_64_kernel
,
2551 GEN_HANDLER(ldarx
, 0x1F, 0x14, 0x02, 0x00000001, PPC_64B
)
2553 gen_addr_reg_index(ctx
);
2555 gen_op_store_T1_gpr(rD(ctx
->opcode
));
2559 GEN_HANDLER(stdcx_
, 0x1F, 0x16, 0x06, 0x00000000, PPC_64B
)
2561 gen_addr_reg_index(ctx
);
2562 gen_op_load_gpr_T1(rS(ctx
->opcode
));
2565 #endif /* defined(TARGET_PPC64) */
2568 GEN_HANDLER(sync
, 0x1F, 0x16, 0x12, 0x03CF0801, PPC_MEM_SYNC
)
2572 /*** Floating-point load ***/
2573 #define GEN_LDF(width, opc) \
2574 GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT) \
2576 if (unlikely(!ctx->fpu_enabled)) { \
2577 RET_EXCP(ctx, EXCP_NO_FP, 0); \
2580 gen_addr_imm_index(ctx, 0); \
2581 op_ldst(l##width); \
2582 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
2585 #define GEN_LDUF(width, opc) \
2586 GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT) \
2588 if (unlikely(!ctx->fpu_enabled)) { \
2589 RET_EXCP(ctx, EXCP_NO_FP, 0); \
2592 if (unlikely(rA(ctx->opcode) == 0)) { \
2596 gen_addr_imm_index(ctx, 0); \
2597 op_ldst(l##width); \
2598 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
2599 gen_op_store_T0_gpr(rA(ctx->opcode)); \
2602 #define GEN_LDUXF(width, opc) \
2603 GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT) \
2605 if (unlikely(!ctx->fpu_enabled)) { \
2606 RET_EXCP(ctx, EXCP_NO_FP, 0); \
2609 if (unlikely(rA(ctx->opcode) == 0)) { \
2613 gen_addr_reg_index(ctx); \
2614 op_ldst(l##width); \
2615 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
2616 gen_op_store_T0_gpr(rA(ctx->opcode)); \
2619 #define GEN_LDXF(width, opc2, opc3) \
2620 GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_FLOAT) \
2622 if (unlikely(!ctx->fpu_enabled)) { \
2623 RET_EXCP(ctx, EXCP_NO_FP, 0); \
2626 gen_addr_reg_index(ctx); \
2627 op_ldst(l##width); \
2628 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
2631 #define GEN_LDFS(width, op) \
2632 OP_LD_TABLE(width); \
2633 GEN_LDF(width, op | 0x20); \
2634 GEN_LDUF(width, op | 0x21); \
2635 GEN_LDUXF(width, op | 0x01); \
2636 GEN_LDXF(width, 0x17, op | 0x00)
2638 /* lfd lfdu lfdux lfdx */
2640 /* lfs lfsu lfsux lfsx */
2643 /*** Floating-point store ***/
2644 #define GEN_STF(width, opc) \
2645 GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT) \
2647 if (unlikely(!ctx->fpu_enabled)) { \
2648 RET_EXCP(ctx, EXCP_NO_FP, 0); \
2651 gen_addr_imm_index(ctx, 0); \
2652 gen_op_load_fpr_FT0(rS(ctx->opcode)); \
2653 op_ldst(st##width); \
2656 #define GEN_STUF(width, opc) \
2657 GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT) \
2659 if (unlikely(!ctx->fpu_enabled)) { \
2660 RET_EXCP(ctx, EXCP_NO_FP, 0); \
2663 if (unlikely(rA(ctx->opcode) == 0)) { \
2667 gen_addr_imm_index(ctx, 0); \
2668 gen_op_load_fpr_FT0(rS(ctx->opcode)); \
2669 op_ldst(st##width); \
2670 gen_op_store_T0_gpr(rA(ctx->opcode)); \
2673 #define GEN_STUXF(width, opc) \
2674 GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT) \
2676 if (unlikely(!ctx->fpu_enabled)) { \
2677 RET_EXCP(ctx, EXCP_NO_FP, 0); \
2680 if (unlikely(rA(ctx->opcode) == 0)) { \
2684 gen_addr_reg_index(ctx); \
2685 gen_op_load_fpr_FT0(rS(ctx->opcode)); \
2686 op_ldst(st##width); \
2687 gen_op_store_T0_gpr(rA(ctx->opcode)); \
2690 #define GEN_STXF(width, opc2, opc3) \
2691 GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_FLOAT) \
2693 if (unlikely(!ctx->fpu_enabled)) { \
2694 RET_EXCP(ctx, EXCP_NO_FP, 0); \
2697 gen_addr_reg_index(ctx); \
2698 gen_op_load_fpr_FT0(rS(ctx->opcode)); \
2699 op_ldst(st##width); \
2702 #define GEN_STFS(width, op) \
2703 OP_ST_TABLE(width); \
2704 GEN_STF(width, op | 0x20); \
2705 GEN_STUF(width, op | 0x21); \
2706 GEN_STUXF(width, op | 0x01); \
2707 GEN_STXF(width, 0x17, op | 0x00)
2709 /* stfd stfdu stfdux stfdx */
2711 /* stfs stfsu stfsux stfsx */
2716 GEN_HANDLER(stfiwx
, 0x1F, 0x17, 0x1E, 0x00000001, PPC_FLOAT_STFIWX
)
2718 if (unlikely(!ctx
->fpu_enabled
)) {
2719 RET_EXCP(ctx
, EXCP_NO_FP
, 0);
2722 gen_addr_reg_index(ctx
);
2723 /* XXX: TODO: memcpy low order 32 bits of FRP(rs) into memory */
2728 static inline void gen_goto_tb (DisasContext
*ctx
, int n
, target_ulong dest
)
2730 TranslationBlock
*tb
;
2732 if ((tb
->pc
& TARGET_PAGE_MASK
) == (dest
& TARGET_PAGE_MASK
)) {
2734 gen_op_goto_tb0(TBPARAM(tb
));
2736 gen_op_goto_tb1(TBPARAM(tb
));
2738 #if defined(TARGET_PPC64)
2744 gen_op_set_T0((long)tb
+ n
);
2745 if (ctx
->singlestep_enabled
)
2750 #if defined(TARGET_PPC64)
2757 if (ctx
->singlestep_enabled
)
2764 GEN_HANDLER(b
, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW
)
2766 target_ulong li
, target
;
2768 /* sign extend LI */
2769 #if defined(TARGET_PPC64)
2771 li
= ((int64_t)LI(ctx
->opcode
) << 38) >> 38;
2774 li
= ((int32_t)LI(ctx
->opcode
) << 6) >> 6;
2775 if (likely(AA(ctx
->opcode
) == 0))
2776 target
= ctx
->nip
+ li
- 4;
2779 if (LK(ctx
->opcode
)) {
2780 #if defined(TARGET_PPC64)
2782 gen_op_setlr_64(ctx
->nip
>> 32, ctx
->nip
);
2785 gen_op_setlr(ctx
->nip
);
2787 gen_goto_tb(ctx
, 0, target
);
2788 ctx
->exception
= EXCP_BRANCH
;
2795 static inline void gen_bcond (DisasContext
*ctx
, int type
)
2797 target_ulong target
= 0;
2799 uint32_t bo
= BO(ctx
->opcode
);
2800 uint32_t bi
= BI(ctx
->opcode
);
2803 if ((bo
& 0x4) == 0)
2807 li
= (target_long
)((int16_t)(BD(ctx
->opcode
)));
2808 if (likely(AA(ctx
->opcode
) == 0)) {
2809 target
= ctx
->nip
+ li
- 4;
2815 gen_op_movl_T1_ctr();
2819 gen_op_movl_T1_lr();
2822 if (LK(ctx
->opcode
)) {
2823 #if defined(TARGET_PPC64)
2825 gen_op_setlr_64(ctx
->nip
>> 32, ctx
->nip
);
2828 gen_op_setlr(ctx
->nip
);
2831 /* No CR condition */
2834 #if defined(TARGET_PPC64)
2836 gen_op_test_ctr_64();
2842 #if defined(TARGET_PPC64)
2844 gen_op_test_ctrz_64();
2852 if (type
== BCOND_IM
) {
2853 gen_goto_tb(ctx
, 0, target
);
2855 #if defined(TARGET_PPC64)
2866 mask
= 1 << (3 - (bi
& 0x03));
2867 gen_op_load_crf_T0(bi
>> 2);
2871 #if defined(TARGET_PPC64)
2873 gen_op_test_ctr_true_64(mask
);
2876 gen_op_test_ctr_true(mask
);
2879 #if defined(TARGET_PPC64)
2881 gen_op_test_ctrz_true_64(mask
);
2884 gen_op_test_ctrz_true(mask
);
2889 gen_op_test_true(mask
);
2895 #if defined(TARGET_PPC64)
2897 gen_op_test_ctr_false_64(mask
);
2900 gen_op_test_ctr_false(mask
);
2903 #if defined(TARGET_PPC64)
2905 gen_op_test_ctrz_false_64(mask
);
2908 gen_op_test_ctrz_false(mask
);
2913 gen_op_test_false(mask
);
2918 if (type
== BCOND_IM
) {
2919 int l1
= gen_new_label();
2921 gen_goto_tb(ctx
, 0, target
);
2923 gen_goto_tb(ctx
, 1, ctx
->nip
);
2925 #if defined(TARGET_PPC64)
2927 gen_op_btest_T1_64(ctx
->nip
>> 32, ctx
->nip
);
2930 gen_op_btest_T1(ctx
->nip
);
2933 if (ctx
->singlestep_enabled
)
2937 ctx
->exception
= EXCP_BRANCH
;
2940 GEN_HANDLER(bc
, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW
)
2942 gen_bcond(ctx
, BCOND_IM
);
2945 GEN_HANDLER(bcctr
, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW
)
2947 gen_bcond(ctx
, BCOND_CTR
);
2950 GEN_HANDLER(bclr
, 0x13, 0x10, 0x00, 0x00000000, PPC_FLOW
)
2952 gen_bcond(ctx
, BCOND_LR
);
2955 /*** Condition register logical ***/
2956 #define GEN_CRLOGIC(op, opc) \
2957 GEN_HANDLER(cr##op, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER) \
2959 gen_op_load_crf_T0(crbA(ctx->opcode) >> 2); \
2960 gen_op_getbit_T0(3 - (crbA(ctx->opcode) & 0x03)); \
2961 gen_op_load_crf_T1(crbB(ctx->opcode) >> 2); \
2962 gen_op_getbit_T1(3 - (crbB(ctx->opcode) & 0x03)); \
2964 gen_op_load_crf_T1(crbD(ctx->opcode) >> 2); \
2965 gen_op_setcrfbit(~(1 << (3 - (crbD(ctx->opcode) & 0x03))), \
2966 3 - (crbD(ctx->opcode) & 0x03)); \
2967 gen_op_store_T1_crf(crbD(ctx->opcode) >> 2); \
2971 GEN_CRLOGIC(and, 0x08);
2973 GEN_CRLOGIC(andc
, 0x04);
2975 GEN_CRLOGIC(eqv
, 0x09);
2977 GEN_CRLOGIC(nand
, 0x07);
2979 GEN_CRLOGIC(nor
, 0x01);
2981 GEN_CRLOGIC(or, 0x0E);
2983 GEN_CRLOGIC(orc
, 0x0D);
2985 GEN_CRLOGIC(xor, 0x06);
2987 GEN_HANDLER(mcrf
, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER
)
2989 gen_op_load_crf_T0(crfS(ctx
->opcode
));
2990 gen_op_store_T0_crf(crfD(ctx
->opcode
));
2993 /*** System linkage ***/
2994 /* rfi (supervisor only) */
2995 GEN_HANDLER(rfi
, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW
)
2997 #if defined(CONFIG_USER_ONLY)
3000 /* Restore CPU state */
3001 if (unlikely(!ctx
->supervisor
)) {
3010 #if defined(TARGET_PPC64)
3011 GEN_HANDLER(rfid
, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B
)
3013 #if defined(CONFIG_USER_ONLY)
3016 /* Restore CPU state */
3017 if (unlikely(!ctx
->supervisor
)) {
3028 GEN_HANDLER(sc
, 0x11, 0xFF, 0xFF, 0x03FFFFFD, PPC_FLOW
)
3030 #if defined(CONFIG_USER_ONLY)
3031 RET_EXCP(ctx
, EXCP_SYSCALL_USER
, 0);
3033 RET_EXCP(ctx
, EXCP_SYSCALL
, 0);
3039 GEN_HANDLER(tw
, 0x1F, 0x04, 0x00, 0x00000001, PPC_FLOW
)
3041 gen_op_load_gpr_T0(rA(ctx
->opcode
));
3042 gen_op_load_gpr_T1(rB(ctx
->opcode
));
3043 /* Update the nip since this might generate a trap exception */
3044 gen_update_nip(ctx
, ctx
->nip
);
3045 gen_op_tw(TO(ctx
->opcode
));
3049 GEN_HANDLER(twi
, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW
)
3051 gen_op_load_gpr_T0(rA(ctx
->opcode
));
3052 gen_set_T1(SIMM(ctx
->opcode
));
3053 /* Update the nip since this might generate a trap exception */
3054 gen_update_nip(ctx
, ctx
->nip
);
3055 gen_op_tw(TO(ctx
->opcode
));
3058 #if defined(TARGET_PPC64)
3060 GEN_HANDLER(td
, 0x1F, 0x04, 0x02, 0x00000001, PPC_64B
)
3062 gen_op_load_gpr_T0(rA(ctx
->opcode
));
3063 gen_op_load_gpr_T1(rB(ctx
->opcode
));
3064 /* Update the nip since this might generate a trap exception */
3065 gen_update_nip(ctx
, ctx
->nip
);
3066 gen_op_td(TO(ctx
->opcode
));
3070 GEN_HANDLER(tdi
, 0x02, 0xFF, 0xFF, 0x00000000, PPC_64B
)
3072 gen_op_load_gpr_T0(rA(ctx
->opcode
));
3073 gen_set_T1(SIMM(ctx
->opcode
));
3074 /* Update the nip since this might generate a trap exception */
3075 gen_update_nip(ctx
, ctx
->nip
);
3076 gen_op_td(TO(ctx
->opcode
));
3080 /*** Processor control ***/
3082 GEN_HANDLER(mcrxr
, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC
)
3084 gen_op_load_xer_cr();
3085 gen_op_store_T0_crf(crfD(ctx
->opcode
));
3086 gen_op_clear_xer_ov();
3087 gen_op_clear_xer_ca();
3091 GEN_HANDLER(mfcr
, 0x1F, 0x13, 0x00, 0x00000801, PPC_MISC
)
3095 if (likely(ctx
->opcode
& 0x00100000)) {
3096 crm
= CRM(ctx
->opcode
);
3097 if (likely((crm
^ (crm
- 1)) == 0)) {
3099 gen_op_load_cro(7 - crn
);
3104 gen_op_store_T0_gpr(rD(ctx
->opcode
));
3108 GEN_HANDLER(mfmsr
, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC
)
3110 #if defined(CONFIG_USER_ONLY)
3113 if (unlikely(!ctx
->supervisor
)) {
3118 gen_op_store_T0_gpr(rD(ctx
->opcode
));
3123 #define SPR_NOACCESS ((void *)(-1))
3125 static void spr_noaccess (void *opaque
, int sprn
)
3127 sprn
= ((sprn
>> 5) & 0x1F) | ((sprn
& 0x1F) << 5);
3128 printf("ERROR: try to access SPR %d !\n", sprn
);
3130 #define SPR_NOACCESS (&spr_noaccess)
3134 static inline void gen_op_mfspr (DisasContext
*ctx
)
3136 void (*read_cb
)(void *opaque
, int sprn
);
3137 uint32_t sprn
= SPR(ctx
->opcode
);
3139 #if !defined(CONFIG_USER_ONLY)
3140 if (ctx
->supervisor
)
3141 read_cb
= ctx
->spr_cb
[sprn
].oea_read
;
3144 read_cb
= ctx
->spr_cb
[sprn
].uea_read
;
3145 if (likely(read_cb
!= NULL
)) {
3146 if (likely(read_cb
!= SPR_NOACCESS
)) {
3147 (*read_cb
)(ctx
, sprn
);
3148 gen_op_store_T0_gpr(rD(ctx
->opcode
));
3150 /* Privilege exception */
3151 if (loglevel
!= 0) {
3152 fprintf(logfile
, "Trying to read privileged spr %d %03x\n",
3155 printf("Trying to read privileged spr %d %03x\n", sprn
, sprn
);
3160 if (loglevel
!= 0) {
3161 fprintf(logfile
, "Trying to read invalid spr %d %03x\n",
3164 printf("Trying to read invalid spr %d %03x\n", sprn
, sprn
);
3165 RET_EXCP(ctx
, EXCP_PROGRAM
, EXCP_INVAL
| EXCP_INVAL_SPR
);
3169 GEN_HANDLER(mfspr
, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC
)
3175 GEN_HANDLER(mftb
, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MFTB
)
3181 GEN_HANDLER(mtcrf
, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC
)
3185 gen_op_load_gpr_T0(rS(ctx
->opcode
));
3186 crm
= CRM(ctx
->opcode
);
3187 if (likely((ctx
->opcode
& 0x00100000) || (crm
^ (crm
- 1)) == 0)) {
3189 gen_op_srli_T0(crn
* 4);
3190 gen_op_andi_T0(0xF);
3191 gen_op_store_cro(7 - crn
);
3193 gen_op_store_cr(crm
);
3198 #if defined(TARGET_PPC64)
3199 GEN_HANDLER(mtmsrd
, 0x1F, 0x12, 0x05, 0x001FF801, PPC_64B
)
3201 #if defined(CONFIG_USER_ONLY)
3204 if (unlikely(!ctx
->supervisor
)) {
3208 gen_update_nip(ctx
, ctx
->nip
);
3209 gen_op_load_gpr_T0(rS(ctx
->opcode
));
3211 /* Must stop the translation as machine state (may have) changed */
3217 GEN_HANDLER(mtmsr
, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC
)
3219 #if defined(CONFIG_USER_ONLY)
3222 if (unlikely(!ctx
->supervisor
)) {
3226 gen_update_nip(ctx
, ctx
->nip
);
3227 gen_op_load_gpr_T0(rS(ctx
->opcode
));
3228 #if defined(TARGET_PPC64)
3230 gen_op_store_msr_32();
3234 /* Must stop the translation as machine state (may have) changed */
3240 GEN_HANDLER(mtspr
, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC
)
3242 void (*write_cb
)(void *opaque
, int sprn
);
3243 uint32_t sprn
= SPR(ctx
->opcode
);
3245 #if !defined(CONFIG_USER_ONLY)
3246 if (ctx
->supervisor
)
3247 write_cb
= ctx
->spr_cb
[sprn
].oea_write
;
3250 write_cb
= ctx
->spr_cb
[sprn
].uea_write
;
3251 if (likely(write_cb
!= NULL
)) {
3252 if (likely(write_cb
!= SPR_NOACCESS
)) {
3253 gen_op_load_gpr_T0(rS(ctx
->opcode
));
3254 (*write_cb
)(ctx
, sprn
);
3256 /* Privilege exception */
3257 if (loglevel
!= 0) {
3258 fprintf(logfile
, "Trying to write privileged spr %d %03x\n",
3261 printf("Trying to write privileged spr %d %03x\n", sprn
, sprn
);
3266 if (loglevel
!= 0) {
3267 fprintf(logfile
, "Trying to write invalid spr %d %03x\n",
3270 printf("Trying to write invalid spr %d %03x\n", sprn
, sprn
);
3271 RET_EXCP(ctx
, EXCP_PROGRAM
, EXCP_INVAL
| EXCP_INVAL_SPR
);
3275 /*** Cache management ***/
3276 /* For now, all those will be implemented as nop:
3277 * this is valid, regarding the PowerPC specs...
3278 * We just have to flush tb while invalidating instruction cache lines...
3281 GEN_HANDLER(dcbf
, 0x1F, 0x16, 0x02, 0x03E00001, PPC_CACHE
)
3283 gen_addr_reg_index(ctx
);
3287 /* dcbi (Supervisor only) */
3288 GEN_HANDLER(dcbi
, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE
)
3290 #if defined(CONFIG_USER_ONLY)
3293 if (unlikely(!ctx
->supervisor
)) {
3297 gen_addr_reg_index(ctx
);
3298 /* XXX: specification says this should be treated as a store by the MMU */
3305 GEN_HANDLER(dcbst
, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE
)
3307 /* XXX: specification say this is treated as a load by the MMU */
3308 gen_addr_reg_index(ctx
);
3313 GEN_HANDLER(dcbt
, 0x1F, 0x16, 0x08, 0x03E00001, PPC_CACHE
)
3315 /* XXX: specification say this is treated as a load by the MMU
3316 * but does not generate any exception
3321 GEN_HANDLER(dcbtst
, 0x1F, 0x16, 0x07, 0x03E00001, PPC_CACHE
)
3323 /* XXX: specification say this is treated as a load by the MMU
3324 * but does not generate any exception
3329 #define op_dcbz() (*gen_op_dcbz[ctx->mem_idx])()
3330 #if defined(TARGET_PPC64)
3331 #if defined(CONFIG_USER_ONLY)
3332 static GenOpFunc
*gen_op_dcbz
[] = {
3335 &gen_op_dcbz_64_raw
,
3336 &gen_op_dcbz_64_raw
,
3339 static GenOpFunc
*gen_op_dcbz
[] = {
3342 &gen_op_dcbz_kernel
,
3343 &gen_op_dcbz_kernel
,
3344 &gen_op_dcbz_64_user
,
3345 &gen_op_dcbz_64_user
,
3346 &gen_op_dcbz_64_kernel
,
3347 &gen_op_dcbz_64_kernel
,
3351 #if defined(CONFIG_USER_ONLY)
3352 static GenOpFunc
*gen_op_dcbz
[] = {
3357 static GenOpFunc
*gen_op_dcbz
[] = {
3360 &gen_op_dcbz_kernel
,
3361 &gen_op_dcbz_kernel
,
3366 GEN_HANDLER(dcbz
, 0x1F, 0x16, 0x1F, 0x03E00001, PPC_CACHE
)
3368 gen_addr_reg_index(ctx
);
3370 gen_op_check_reservation();
3374 #define op_icbi() (*gen_op_icbi[ctx->mem_idx])()
3375 #if defined(TARGET_PPC64)
3376 #if defined(CONFIG_USER_ONLY)
3377 static GenOpFunc
*gen_op_icbi
[] = {
3380 &gen_op_icbi_64_raw
,
3381 &gen_op_icbi_64_raw
,
3384 static GenOpFunc
*gen_op_icbi
[] = {
3387 &gen_op_icbi_kernel
,
3388 &gen_op_icbi_kernel
,
3389 &gen_op_icbi_64_user
,
3390 &gen_op_icbi_64_user
,
3391 &gen_op_icbi_64_kernel
,
3392 &gen_op_icbi_64_kernel
,
3396 #if defined(CONFIG_USER_ONLY)
3397 static GenOpFunc
*gen_op_icbi
[] = {
3402 static GenOpFunc
*gen_op_icbi
[] = {
3405 &gen_op_icbi_kernel
,
3406 &gen_op_icbi_kernel
,
3410 GEN_HANDLER(icbi
, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE
)
3412 /* NIP cannot be restored if the memory exception comes from an helper */
3413 gen_update_nip(ctx
, ctx
->nip
- 4);
3414 gen_addr_reg_index(ctx
);
3421 GEN_HANDLER(dcba
, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_DCBA
)
3425 /*** Segment register manipulation ***/
3426 /* Supervisor only: */
3428 GEN_HANDLER(mfsr
, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT
)
3430 #if defined(CONFIG_USER_ONLY)
3433 if (unlikely(!ctx
->supervisor
)) {
3437 gen_op_set_T1(SR(ctx
->opcode
));
3439 gen_op_store_T0_gpr(rD(ctx
->opcode
));
3444 GEN_HANDLER(mfsrin
, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT
)
3446 #if defined(CONFIG_USER_ONLY)
3449 if (unlikely(!ctx
->supervisor
)) {
3453 gen_op_load_gpr_T1(rB(ctx
->opcode
));
3456 gen_op_store_T0_gpr(rD(ctx
->opcode
));
3461 GEN_HANDLER(mtsr
, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT
)
3463 #if defined(CONFIG_USER_ONLY)
3466 if (unlikely(!ctx
->supervisor
)) {
3470 gen_op_load_gpr_T0(rS(ctx
->opcode
));
3471 gen_op_set_T1(SR(ctx
->opcode
));
3478 GEN_HANDLER(mtsrin
, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT
)
3480 #if defined(CONFIG_USER_ONLY)
3483 if (unlikely(!ctx
->supervisor
)) {
3487 gen_op_load_gpr_T0(rS(ctx
->opcode
));
3488 gen_op_load_gpr_T1(rB(ctx
->opcode
));
3495 /*** Lookaside buffer management ***/
3496 /* Optional & supervisor only: */
3498 GEN_HANDLER(tlbia
, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA
)
3500 #if defined(CONFIG_USER_ONLY)
3503 if (unlikely(!ctx
->supervisor
)) {
3505 fprintf(logfile
, "%s: ! supervisor\n", __func__
);
3515 GEN_HANDLER(tlbie
, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM_TLBIE
)
3517 #if defined(CONFIG_USER_ONLY)
3520 if (unlikely(!ctx
->supervisor
)) {
3524 gen_op_load_gpr_T0(rB(ctx
->opcode
));
3525 #if defined(TARGET_PPC64)
3536 GEN_HANDLER(tlbsync
, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC
)
3538 #if defined(CONFIG_USER_ONLY)
3541 if (unlikely(!ctx
->supervisor
)) {
3545 /* This has no effect: it should ensure that all previous
3546 * tlbie have completed
3552 #if defined(TARGET_PPC64)
3554 GEN_HANDLER(slbia
, 0x1F, 0x12, 0x0F, 0x03FFFC01, PPC_SLBI
)
3556 #if defined(CONFIG_USER_ONLY)
3559 if (unlikely(!ctx
->supervisor
)) {
3561 fprintf(logfile
, "%s: ! supervisor\n", __func__
);
3571 GEN_HANDLER(slbie
, 0x1F, 0x12, 0x0D, 0x03FF0001, PPC_SLBI
)
3573 #if defined(CONFIG_USER_ONLY)
3576 if (unlikely(!ctx
->supervisor
)) {
3580 gen_op_load_gpr_T0(rB(ctx
->opcode
));
3587 /*** External control ***/
3589 #define op_eciwx() (*gen_op_eciwx[ctx->mem_idx])()
3590 #define op_ecowx() (*gen_op_ecowx[ctx->mem_idx])()
3591 #if defined(TARGET_PPC64)
3592 #if defined(CONFIG_USER_ONLY)
3593 static GenOpFunc
*gen_op_eciwx
[] = {
3595 &gen_op_eciwx_le_raw
,
3596 &gen_op_eciwx_64_raw
,
3597 &gen_op_eciwx_le_64_raw
,
3599 static GenOpFunc
*gen_op_ecowx
[] = {
3601 &gen_op_ecowx_le_raw
,
3602 &gen_op_ecowx_64_raw
,
3603 &gen_op_ecowx_le_64_raw
,
3606 static GenOpFunc
*gen_op_eciwx
[] = {
3608 &gen_op_eciwx_le_user
,
3609 &gen_op_eciwx_kernel
,
3610 &gen_op_eciwx_le_kernel
,
3611 &gen_op_eciwx_64_user
,
3612 &gen_op_eciwx_le_64_user
,
3613 &gen_op_eciwx_64_kernel
,
3614 &gen_op_eciwx_le_64_kernel
,
3616 static GenOpFunc
*gen_op_ecowx
[] = {
3618 &gen_op_ecowx_le_user
,
3619 &gen_op_ecowx_kernel
,
3620 &gen_op_ecowx_le_kernel
,
3621 &gen_op_ecowx_64_user
,
3622 &gen_op_ecowx_le_64_user
,
3623 &gen_op_ecowx_64_kernel
,
3624 &gen_op_ecowx_le_64_kernel
,
3628 #if defined(CONFIG_USER_ONLY)
3629 static GenOpFunc
*gen_op_eciwx
[] = {
3631 &gen_op_eciwx_le_raw
,
3633 static GenOpFunc
*gen_op_ecowx
[] = {
3635 &gen_op_ecowx_le_raw
,
3638 static GenOpFunc
*gen_op_eciwx
[] = {
3640 &gen_op_eciwx_le_user
,
3641 &gen_op_eciwx_kernel
,
3642 &gen_op_eciwx_le_kernel
,
3644 static GenOpFunc
*gen_op_ecowx
[] = {
3646 &gen_op_ecowx_le_user
,
3647 &gen_op_ecowx_kernel
,
3648 &gen_op_ecowx_le_kernel
,
3654 GEN_HANDLER(eciwx
, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN
)
3656 /* Should check EAR[E] & alignment ! */
3657 gen_addr_reg_index(ctx
);
3659 gen_op_store_T0_gpr(rD(ctx
->opcode
));
3663 GEN_HANDLER(ecowx
, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN
)
3665 /* Should check EAR[E] & alignment ! */
3666 gen_addr_reg_index(ctx
);
3667 gen_op_load_gpr_T1(rS(ctx
->opcode
));
3671 /* PowerPC 601 specific instructions */
3673 GEN_HANDLER(abs
, 0x1F, 0x08, 0x0B, 0x0000F800, PPC_POWER_BR
)
3675 gen_op_load_gpr_T0(rA(ctx
->opcode
));
3677 gen_op_store_T0_gpr(rD(ctx
->opcode
));
3678 if (unlikely(Rc(ctx
->opcode
) != 0))
3683 GEN_HANDLER(abso
, 0x1F, 0x08, 0x1B, 0x0000F800, PPC_POWER_BR
)
3685 gen_op_load_gpr_T0(rA(ctx
->opcode
));
3686 gen_op_POWER_abso();
3687 gen_op_store_T0_gpr(rD(ctx
->opcode
));
3688 if (unlikely(Rc(ctx
->opcode
) != 0))
3693 GEN_HANDLER(clcs
, 0x1F, 0x10, 0x13, 0x0000F800, PPC_POWER_BR
)
3695 gen_op_load_gpr_T0(rA(ctx
->opcode
));
3696 gen_op_POWER_clcs();
3697 gen_op_store_T0_gpr(rD(ctx
->opcode
));
3701 GEN_HANDLER(div
, 0x1F, 0x0B, 0x0A, 0x00000000, PPC_POWER_BR
)
3703 gen_op_load_gpr_T0(rA(ctx
->opcode
));
3704 gen_op_load_gpr_T1(rB(ctx
->opcode
));
3706 gen_op_store_T0_gpr(rD(ctx
->opcode
));
3707 if (unlikely(Rc(ctx
->opcode
) != 0))
3712 GEN_HANDLER(divo
, 0x1F, 0x0B, 0x1A, 0x00000000, PPC_POWER_BR
)
3714 gen_op_load_gpr_T0(rA(ctx
->opcode
));
3715 gen_op_load_gpr_T1(rB(ctx
->opcode
));
3716 gen_op_POWER_divo();
3717 gen_op_store_T0_gpr(rD(ctx
->opcode
));
3718 if (unlikely(Rc(ctx
->opcode
) != 0))
3723 GEN_HANDLER(divs
, 0x1F, 0x0B, 0x0B, 0x00000000, PPC_POWER_BR
)
3725 gen_op_load_gpr_T0(rA(ctx
->opcode
));
3726 gen_op_load_gpr_T1(rB(ctx
->opcode
));
3727 gen_op_POWER_divs();
3728 gen_op_store_T0_gpr(rD(ctx
->opcode
));
3729 if (unlikely(Rc(ctx
->opcode
) != 0))
3733 /* divso - divso. */
3734 GEN_HANDLER(divso
, 0x1F, 0x0B, 0x1B, 0x00000000, PPC_POWER_BR
)
3736 gen_op_load_gpr_T0(rA(ctx
->opcode
));
3737 gen_op_load_gpr_T1(rB(ctx
->opcode
));
3738 gen_op_POWER_divso();
3739 gen_op_store_T0_gpr(rD(ctx
->opcode
));
3740 if (unlikely(Rc(ctx
->opcode
) != 0))
3745 GEN_HANDLER(doz
, 0x1F, 0x08, 0x08, 0x00000000, PPC_POWER_BR
)
3747 gen_op_load_gpr_T0(rA(ctx
->opcode
));
3748 gen_op_load_gpr_T1(rB(ctx
->opcode
));
3750 gen_op_store_T0_gpr(rD(ctx
->opcode
));
3751 if (unlikely(Rc(ctx
->opcode
) != 0))
3756 GEN_HANDLER(dozo
, 0x1F, 0x08, 0x18, 0x00000000, PPC_POWER_BR
)
3758 gen_op_load_gpr_T0(rA(ctx
->opcode
));
3759 gen_op_load_gpr_T1(rB(ctx
->opcode
));
3760 gen_op_POWER_dozo();
3761 gen_op_store_T0_gpr(rD(ctx
->opcode
));
3762 if (unlikely(Rc(ctx
->opcode
) != 0))
3767 GEN_HANDLER(dozi
, 0x09, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR
)
3769 gen_op_load_gpr_T0(rA(ctx
->opcode
));
3770 gen_op_set_T1(SIMM(ctx
->opcode
));
3772 gen_op_store_T0_gpr(rD(ctx
->opcode
));
3775 /* As lscbx load from memory byte after byte, it's always endian safe */
3776 #define op_POWER_lscbx(start, ra, rb) \
3777 (*gen_op_POWER_lscbx[ctx->mem_idx])(start, ra, rb)
3778 #if defined(CONFIG_USER_ONLY)
3779 static GenOpFunc3
*gen_op_POWER_lscbx
[] = {
3780 &gen_op_POWER_lscbx_raw
,
3781 &gen_op_POWER_lscbx_raw
,
3784 static GenOpFunc3
*gen_op_POWER_lscbx
[] = {
3785 &gen_op_POWER_lscbx_user
,
3786 &gen_op_POWER_lscbx_user
,
3787 &gen_op_POWER_lscbx_kernel
,
3788 &gen_op_POWER_lscbx_kernel
,
3792 /* lscbx - lscbx. */
3793 GEN_HANDLER(lscbx
, 0x1F, 0x15, 0x08, 0x00000000, PPC_POWER_BR
)
3795 int ra
= rA(ctx
->opcode
);
3796 int rb
= rB(ctx
->opcode
);
3798 gen_addr_reg_index(ctx
);
3802 /* NIP cannot be restored if the memory exception comes from an helper */
3803 gen_update_nip(ctx
, ctx
->nip
- 4);
3804 gen_op_load_xer_bc();
3805 gen_op_load_xer_cmp();
3806 op_POWER_lscbx(rD(ctx
->opcode
), ra
, rb
);
3807 gen_op_store_xer_bc();
3808 if (unlikely(Rc(ctx
->opcode
) != 0))
3812 /* maskg - maskg. */
3813 GEN_HANDLER(maskg
, 0x1F, 0x1D, 0x00, 0x00000000, PPC_POWER_BR
)
3815 gen_op_load_gpr_T0(rS(ctx
->opcode
));
3816 gen_op_load_gpr_T1(rB(ctx
->opcode
));
3817 gen_op_POWER_maskg();
3818 gen_op_store_T0_gpr(rA(ctx
->opcode
));
3819 if (unlikely(Rc(ctx
->opcode
) != 0))
3823 /* maskir - maskir. */
3824 GEN_HANDLER(maskir
, 0x1F, 0x1D, 0x10, 0x00000000, PPC_POWER_BR
)
3826 gen_op_load_gpr_T0(rA(ctx
->opcode
));
3827 gen_op_load_gpr_T1(rS(ctx
->opcode
));
3828 gen_op_load_gpr_T2(rB(ctx
->opcode
));
3829 gen_op_POWER_maskir();
3830 gen_op_store_T0_gpr(rA(ctx
->opcode
));
3831 if (unlikely(Rc(ctx
->opcode
) != 0))
3836 GEN_HANDLER(mul
, 0x1F, 0x0B, 0x03, 0x00000000, PPC_POWER_BR
)
3838 gen_op_load_gpr_T0(rA(ctx
->opcode
));
3839 gen_op_load_gpr_T1(rB(ctx
->opcode
));
3841 gen_op_store_T0_gpr(rD(ctx
->opcode
));
3842 if (unlikely(Rc(ctx
->opcode
) != 0))
3847 GEN_HANDLER(mulo
, 0x1F, 0x0B, 0x13, 0x00000000, PPC_POWER_BR
)
3849 gen_op_load_gpr_T0(rA(ctx
->opcode
));
3850 gen_op_load_gpr_T1(rB(ctx
->opcode
));
3851 gen_op_POWER_mulo();
3852 gen_op_store_T0_gpr(rD(ctx
->opcode
));
3853 if (unlikely(Rc(ctx
->opcode
) != 0))
3858 GEN_HANDLER(nabs
, 0x1F, 0x08, 0x0F, 0x00000000, PPC_POWER_BR
)
3860 gen_op_load_gpr_T0(rA(ctx
->opcode
));
3861 gen_op_POWER_nabs();
3862 gen_op_store_T0_gpr(rD(ctx
->opcode
));
3863 if (unlikely(Rc(ctx
->opcode
) != 0))
3867 /* nabso - nabso. */
3868 GEN_HANDLER(nabso
, 0x1F, 0x08, 0x1F, 0x00000000, PPC_POWER_BR
)
3870 gen_op_load_gpr_T0(rA(ctx
->opcode
));
3871 gen_op_POWER_nabso();
3872 gen_op_store_T0_gpr(rD(ctx
->opcode
));
3873 if (unlikely(Rc(ctx
->opcode
) != 0))
3878 GEN_HANDLER(rlmi
, 0x16, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR
)
3882 mb
= MB(ctx
->opcode
);
3883 me
= ME(ctx
->opcode
);
3884 gen_op_load_gpr_T0(rS(ctx
->opcode
));
3885 gen_op_load_gpr_T1(rA(ctx
->opcode
));
3886 gen_op_load_gpr_T2(rB(ctx
->opcode
));
3887 gen_op_POWER_rlmi(MASK(mb
, me
), ~MASK(mb
, me
));
3888 gen_op_store_T0_gpr(rA(ctx
->opcode
));
3889 if (unlikely(Rc(ctx
->opcode
) != 0))
3894 GEN_HANDLER(rrib
, 0x1F, 0x19, 0x10, 0x00000000, PPC_POWER_BR
)
3896 gen_op_load_gpr_T0(rS(ctx
->opcode
));
3897 gen_op_load_gpr_T1(rA(ctx
->opcode
));
3898 gen_op_load_gpr_T2(rB(ctx
->opcode
));
3899 gen_op_POWER_rrib();
3900 gen_op_store_T0_gpr(rA(ctx
->opcode
));
3901 if (unlikely(Rc(ctx
->opcode
) != 0))
3906 GEN_HANDLER(sle
, 0x1F, 0x19, 0x04, 0x00000000, PPC_POWER_BR
)
3908 gen_op_load_gpr_T0(rS(ctx
->opcode
));
3909 gen_op_load_gpr_T1(rB(ctx
->opcode
));
3911 gen_op_store_T0_gpr(rA(ctx
->opcode
));
3912 if (unlikely(Rc(ctx
->opcode
) != 0))
3917 GEN_HANDLER(sleq
, 0x1F, 0x19, 0x06, 0x00000000, PPC_POWER_BR
)
3919 gen_op_load_gpr_T0(rS(ctx
->opcode
));
3920 gen_op_load_gpr_T1(rB(ctx
->opcode
));
3921 gen_op_POWER_sleq();
3922 gen_op_store_T0_gpr(rA(ctx
->opcode
));
3923 if (unlikely(Rc(ctx
->opcode
) != 0))
3928 GEN_HANDLER(sliq
, 0x1F, 0x18, 0x05, 0x00000000, PPC_POWER_BR
)
3930 gen_op_load_gpr_T0(rS(ctx
->opcode
));
3931 gen_op_set_T1(SH(ctx
->opcode
));
3933 gen_op_store_T0_gpr(rA(ctx
->opcode
));
3934 if (unlikely(Rc(ctx
->opcode
) != 0))
3938 /* slliq - slliq. */
3939 GEN_HANDLER(slliq
, 0x1F, 0x18, 0x07, 0x00000000, PPC_POWER_BR
)
3941 gen_op_load_gpr_T0(rS(ctx
->opcode
));
3942 gen_op_set_T1(SH(ctx
->opcode
));
3943 gen_op_POWER_sleq();
3944 gen_op_store_T0_gpr(rA(ctx
->opcode
));
3945 if (unlikely(Rc(ctx
->opcode
) != 0))
3950 GEN_HANDLER(sllq
, 0x1F, 0x18, 0x06, 0x00000000, PPC_POWER_BR
)
3952 gen_op_load_gpr_T0(rS(ctx
->opcode
));
3953 gen_op_load_gpr_T1(rB(ctx
->opcode
));
3954 gen_op_POWER_sllq();
3955 gen_op_store_T0_gpr(rA(ctx
->opcode
));
3956 if (unlikely(Rc(ctx
->opcode
) != 0))
3961 GEN_HANDLER(slq
, 0x1F, 0x18, 0x04, 0x00000000, PPC_POWER_BR
)
3963 gen_op_load_gpr_T0(rS(ctx
->opcode
));
3964 gen_op_load_gpr_T1(rB(ctx
->opcode
));
3966 gen_op_store_T0_gpr(rA(ctx
->opcode
));
3967 if (unlikely(Rc(ctx
->opcode
) != 0))
3971 /* sraiq - sraiq. */
3972 GEN_HANDLER(sraiq
, 0x1F, 0x18, 0x1D, 0x00000000, PPC_POWER_BR
)
3974 gen_op_load_gpr_T0(rS(ctx
->opcode
));
3975 gen_op_set_T1(SH(ctx
->opcode
));
3976 gen_op_POWER_sraq();
3977 gen_op_store_T0_gpr(rA(ctx
->opcode
));
3978 if (unlikely(Rc(ctx
->opcode
) != 0))
3983 GEN_HANDLER(sraq
, 0x1F, 0x18, 0x1C, 0x00000000, PPC_POWER_BR
)
3985 gen_op_load_gpr_T0(rS(ctx
->opcode
));
3986 gen_op_load_gpr_T1(rB(ctx
->opcode
));
3987 gen_op_POWER_sraq();
3988 gen_op_store_T0_gpr(rA(ctx
->opcode
));
3989 if (unlikely(Rc(ctx
->opcode
) != 0))
3994 GEN_HANDLER(sre
, 0x1F, 0x19, 0x14, 0x00000000, PPC_POWER_BR
)
3996 gen_op_load_gpr_T0(rS(ctx
->opcode
));
3997 gen_op_load_gpr_T1(rB(ctx
->opcode
));
3999 gen_op_store_T0_gpr(rA(ctx
->opcode
));
4000 if (unlikely(Rc(ctx
->opcode
) != 0))
4005 GEN_HANDLER(srea
, 0x1F, 0x19, 0x1C, 0x00000000, PPC_POWER_BR
)
4007 gen_op_load_gpr_T0(rS(ctx
->opcode
));
4008 gen_op_load_gpr_T1(rB(ctx
->opcode
));
4009 gen_op_POWER_srea();
4010 gen_op_store_T0_gpr(rA(ctx
->opcode
));
4011 if (unlikely(Rc(ctx
->opcode
) != 0))
4016 GEN_HANDLER(sreq
, 0x1F, 0x19, 0x16, 0x00000000, PPC_POWER_BR
)
4018 gen_op_load_gpr_T0(rS(ctx
->opcode
));
4019 gen_op_load_gpr_T1(rB(ctx
->opcode
));
4020 gen_op_POWER_sreq();
4021 gen_op_store_T0_gpr(rA(ctx
->opcode
));
4022 if (unlikely(Rc(ctx
->opcode
) != 0))
4027 GEN_HANDLER(sriq
, 0x1F, 0x18, 0x15, 0x00000000, PPC_POWER_BR
)
4029 gen_op_load_gpr_T0(rS(ctx
->opcode
));
4030 gen_op_set_T1(SH(ctx
->opcode
));
4032 gen_op_store_T0_gpr(rA(ctx
->opcode
));
4033 if (unlikely(Rc(ctx
->opcode
) != 0))
4038 GEN_HANDLER(srliq
, 0x1F, 0x18, 0x17, 0x00000000, PPC_POWER_BR
)
4040 gen_op_load_gpr_T0(rS(ctx
->opcode
));
4041 gen_op_load_gpr_T1(rB(ctx
->opcode
));
4042 gen_op_set_T1(SH(ctx
->opcode
));
4043 gen_op_POWER_srlq();
4044 gen_op_store_T0_gpr(rA(ctx
->opcode
));
4045 if (unlikely(Rc(ctx
->opcode
) != 0))
4050 GEN_HANDLER(srlq
, 0x1F, 0x18, 0x16, 0x00000000, PPC_POWER_BR
)
4052 gen_op_load_gpr_T0(rS(ctx
->opcode
));
4053 gen_op_load_gpr_T1(rB(ctx
->opcode
));
4054 gen_op_POWER_srlq();
4055 gen_op_store_T0_gpr(rA(ctx
->opcode
));
4056 if (unlikely(Rc(ctx
->opcode
) != 0))
4061 GEN_HANDLER(srq
, 0x1F, 0x18, 0x14, 0x00000000, PPC_POWER_BR
)
4063 gen_op_load_gpr_T0(rS(ctx
->opcode
));
4064 gen_op_load_gpr_T1(rB(ctx
->opcode
));
4066 gen_op_store_T0_gpr(rA(ctx
->opcode
));
4067 if (unlikely(Rc(ctx
->opcode
) != 0))
4071 /* PowerPC 602 specific instructions */
4073 GEN_HANDLER(dsa
, 0x1F, 0x14, 0x13, 0x03FFF801, PPC_602_SPEC
)
4080 GEN_HANDLER(esa
, 0x1F, 0x14, 0x12, 0x03FFF801, PPC_602_SPEC
)
4087 GEN_HANDLER(mfrom
, 0x1F, 0x09, 0x08, 0x03E0F801, PPC_602_SPEC
)
4089 #if defined(CONFIG_USER_ONLY)
4092 if (unlikely(!ctx
->supervisor
)) {
4096 gen_op_load_gpr_T0(rA(ctx
->opcode
));
4098 gen_op_store_T0_gpr(rD(ctx
->opcode
));
4102 /* 602 - 603 - G2 TLB management */
4104 GEN_HANDLER(tlbld
, 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB
)
4106 #if defined(CONFIG_USER_ONLY)
4109 if (unlikely(!ctx
->supervisor
)) {
4113 gen_op_load_gpr_T0(rB(ctx
->opcode
));
4120 GEN_HANDLER(tlbli
, 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB
)
4122 #if defined(CONFIG_USER_ONLY)
4125 if (unlikely(!ctx
->supervisor
)) {
4129 gen_op_load_gpr_T0(rB(ctx
->opcode
));
4135 /* POWER instructions not in PowerPC 601 */
4137 GEN_HANDLER(clf
, 0x1F, 0x16, 0x03, 0x03E00000, PPC_POWER
)
4139 /* Cache line flush: implemented as no-op */
4143 GEN_HANDLER(cli
, 0x1F, 0x16, 0x0F, 0x03E00000, PPC_POWER
)
4145 /* Cache line invalidate: privileged and treated as no-op */
4146 #if defined(CONFIG_USER_ONLY)
4149 if (unlikely(!ctx
->supervisor
)) {
4157 GEN_HANDLER(dclst
, 0x1F, 0x16, 0x13, 0x03E00000, PPC_POWER
)
4159 /* Data cache line store: treated as no-op */
4162 GEN_HANDLER(mfsri
, 0x1F, 0x13, 0x13, 0x00000001, PPC_POWER
)
4164 #if defined(CONFIG_USER_ONLY)
4167 if (unlikely(!ctx
->supervisor
)) {
4171 int ra
= rA(ctx
->opcode
);
4172 int rd
= rD(ctx
->opcode
);
4174 gen_addr_reg_index(ctx
);
4175 gen_op_POWER_mfsri();
4176 gen_op_store_T0_gpr(rd
);
4177 if (ra
!= 0 && ra
!= rd
)
4178 gen_op_store_T1_gpr(ra
);
4182 GEN_HANDLER(rac
, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER
)
4184 #if defined(CONFIG_USER_ONLY)
4187 if (unlikely(!ctx
->supervisor
)) {
4191 gen_addr_reg_index(ctx
);
4193 gen_op_store_T0_gpr(rD(ctx
->opcode
));
4197 GEN_HANDLER(rfsvc
, 0x13, 0x12, 0x02, 0x03FFF0001, PPC_POWER
)
4199 #if defined(CONFIG_USER_ONLY)
4202 if (unlikely(!ctx
->supervisor
)) {
4206 gen_op_POWER_rfsvc();
4211 /* svc is not implemented for now */
4213 /* POWER2 specific instructions */
4214 /* Quad manipulation (load/store two floats at a time) */
4215 #define op_POWER2_lfq() (*gen_op_POWER2_lfq[ctx->mem_idx])()
4216 #define op_POWER2_stfq() (*gen_op_POWER2_stfq[ctx->mem_idx])()
4217 #if defined(CONFIG_USER_ONLY)
4218 static GenOpFunc
*gen_op_POWER2_lfq
[] = {
4219 &gen_op_POWER2_lfq_le_raw
,
4220 &gen_op_POWER2_lfq_raw
,
4222 static GenOpFunc
*gen_op_POWER2_stfq
[] = {
4223 &gen_op_POWER2_stfq_le_raw
,
4224 &gen_op_POWER2_stfq_raw
,
4227 static GenOpFunc
*gen_op_POWER2_lfq
[] = {
4228 &gen_op_POWER2_lfq_le_user
,
4229 &gen_op_POWER2_lfq_user
,
4230 &gen_op_POWER2_lfq_le_kernel
,
4231 &gen_op_POWER2_lfq_kernel
,
4233 static GenOpFunc
*gen_op_POWER2_stfq
[] = {
4234 &gen_op_POWER2_stfq_le_user
,
4235 &gen_op_POWER2_stfq_user
,
4236 &gen_op_POWER2_stfq_le_kernel
,
4237 &gen_op_POWER2_stfq_kernel
,
4242 GEN_HANDLER(lfq
, 0x38, 0xFF, 0xFF, 0x00000003, PPC_POWER2
)
4244 /* NIP cannot be restored if the memory exception comes from an helper */
4245 gen_update_nip(ctx
, ctx
->nip
- 4);
4246 gen_addr_imm_index(ctx
, 0);
4248 gen_op_store_FT0_fpr(rD(ctx
->opcode
));
4249 gen_op_store_FT1_fpr(rD(ctx
->opcode
) + 1);
4253 GEN_HANDLER(lfqu
, 0x39, 0xFF, 0xFF, 0x00000003, PPC_POWER2
)
4255 int ra
= rA(ctx
->opcode
);
4257 /* NIP cannot be restored if the memory exception comes from an helper */
4258 gen_update_nip(ctx
, ctx
->nip
- 4);
4259 gen_addr_imm_index(ctx
, 0);
4261 gen_op_store_FT0_fpr(rD(ctx
->opcode
));
4262 gen_op_store_FT1_fpr(rD(ctx
->opcode
) + 1);
4264 gen_op_store_T0_gpr(ra
);
4268 GEN_HANDLER(lfqux
, 0x1F, 0x17, 0x19, 0x00000001, PPC_POWER2
)
4270 int ra
= rA(ctx
->opcode
);
4272 /* NIP cannot be restored if the memory exception comes from an helper */
4273 gen_update_nip(ctx
, ctx
->nip
- 4);
4274 gen_addr_reg_index(ctx
);
4276 gen_op_store_FT0_fpr(rD(ctx
->opcode
));
4277 gen_op_store_FT1_fpr(rD(ctx
->opcode
) + 1);
4279 gen_op_store_T0_gpr(ra
);
4283 GEN_HANDLER(lfqx
, 0x1F, 0x17, 0x18, 0x00000001, PPC_POWER2
)
4285 /* NIP cannot be restored if the memory exception comes from an helper */
4286 gen_update_nip(ctx
, ctx
->nip
- 4);
4287 gen_addr_reg_index(ctx
);
4289 gen_op_store_FT0_fpr(rD(ctx
->opcode
));
4290 gen_op_store_FT1_fpr(rD(ctx
->opcode
) + 1);
4294 GEN_HANDLER(stfq
, 0x3C, 0xFF, 0xFF, 0x00000003, PPC_POWER2
)
4296 /* NIP cannot be restored if the memory exception comes from an helper */
4297 gen_update_nip(ctx
, ctx
->nip
- 4);
4298 gen_addr_imm_index(ctx
, 0);
4299 gen_op_load_fpr_FT0(rS(ctx
->opcode
));
4300 gen_op_load_fpr_FT1(rS(ctx
->opcode
) + 1);
4305 GEN_HANDLER(stfqu
, 0x3D, 0xFF, 0xFF, 0x00000003, PPC_POWER2
)
4307 int ra
= rA(ctx
->opcode
);
4309 /* NIP cannot be restored if the memory exception comes from an helper */
4310 gen_update_nip(ctx
, ctx
->nip
- 4);
4311 gen_addr_imm_index(ctx
, 0);
4312 gen_op_load_fpr_FT0(rS(ctx
->opcode
));
4313 gen_op_load_fpr_FT1(rS(ctx
->opcode
) + 1);
4316 gen_op_store_T0_gpr(ra
);
4320 GEN_HANDLER(stfqux
, 0x1F, 0x17, 0x1D, 0x00000001, PPC_POWER2
)
4322 int ra
= rA(ctx
->opcode
);
4324 /* NIP cannot be restored if the memory exception comes from an helper */
4325 gen_update_nip(ctx
, ctx
->nip
- 4);
4326 gen_addr_reg_index(ctx
);
4327 gen_op_load_fpr_FT0(rS(ctx
->opcode
));
4328 gen_op_load_fpr_FT1(rS(ctx
->opcode
) + 1);
4331 gen_op_store_T0_gpr(ra
);
4335 GEN_HANDLER(stfqx
, 0x1F, 0x17, 0x1C, 0x00000001, PPC_POWER2
)
4337 /* NIP cannot be restored if the memory exception comes from an helper */
4338 gen_update_nip(ctx
, ctx
->nip
- 4);
4339 gen_addr_reg_index(ctx
);
4340 gen_op_load_fpr_FT0(rS(ctx
->opcode
));
4341 gen_op_load_fpr_FT1(rS(ctx
->opcode
) + 1);
4345 /* BookE specific instructions */
4346 /* XXX: not implemented on 440 ? */
4347 GEN_HANDLER(mfapidi
, 0x1F, 0x13, 0x08, 0x0000F801, PPC_BOOKE_EXT
)
4353 /* XXX: not implemented on 440 ? */
4354 GEN_HANDLER(tlbiva
, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_BOOKE_EXT
)
4356 #if defined(CONFIG_USER_ONLY)
4359 if (unlikely(!ctx
->supervisor
)) {
4363 gen_addr_reg_index(ctx
);
4364 /* Use the same micro-ops as for tlbie */
4365 #if defined(TARGET_PPC64)
4375 /* All 405 MAC instructions are translated here */
4376 static inline void gen_405_mulladd_insn (DisasContext
*ctx
, int opc2
, int opc3
,
4377 int ra
, int rb
, int rt
, int Rc
)
4379 gen_op_load_gpr_T0(ra
);
4380 gen_op_load_gpr_T1(rb
);
4381 switch (opc3
& 0x0D) {
4383 /* macchw - macchw. - macchwo - macchwo. */
4384 /* macchws - macchws. - macchwso - macchwso. */
4385 /* nmacchw - nmacchw. - nmacchwo - nmacchwo. */
4386 /* nmacchws - nmacchws. - nmacchwso - nmacchwso. */
4387 /* mulchw - mulchw. */
4388 gen_op_405_mulchw();
4391 /* macchwu - macchwu. - macchwuo - macchwuo. */
4392 /* macchwsu - macchwsu. - macchwsuo - macchwsuo. */
4393 /* mulchwu - mulchwu. */
4394 gen_op_405_mulchwu();
4397 /* machhw - machhw. - machhwo - machhwo. */
4398 /* machhws - machhws. - machhwso - machhwso. */
4399 /* nmachhw - nmachhw. - nmachhwo - nmachhwo. */
4400 /* nmachhws - nmachhws. - nmachhwso - nmachhwso. */
4401 /* mulhhw - mulhhw. */
4402 gen_op_405_mulhhw();
4405 /* machhwu - machhwu. - machhwuo - machhwuo. */
4406 /* machhwsu - machhwsu. - machhwsuo - machhwsuo. */
4407 /* mulhhwu - mulhhwu. */
4408 gen_op_405_mulhhwu();
4411 /* maclhw - maclhw. - maclhwo - maclhwo. */
4412 /* maclhws - maclhws. - maclhwso - maclhwso. */
4413 /* nmaclhw - nmaclhw. - nmaclhwo - nmaclhwo. */
4414 /* nmaclhws - nmaclhws. - nmaclhwso - nmaclhwso. */
4415 /* mullhw - mullhw. */
4416 gen_op_405_mullhw();
4419 /* maclhwu - maclhwu. - maclhwuo - maclhwuo. */
4420 /* maclhwsu - maclhwsu. - maclhwsuo - maclhwsuo. */
4421 /* mullhwu - mullhwu. */
4422 gen_op_405_mullhwu();
4426 /* nmultiply-and-accumulate (0x0E) */
4430 /* (n)multiply-and-accumulate (0x0C - 0x0E) */
4431 gen_op_load_gpr_T2(rt
);
4432 gen_op_move_T1_T0();
4433 gen_op_405_add_T0_T2();
4436 /* Check overflow */
4438 gen_op_405_check_ov();
4440 gen_op_405_check_ovu();
4445 gen_op_405_check_sat();
4447 gen_op_405_check_satu();
4449 gen_op_store_T0_gpr(rt
);
4450 if (unlikely(Rc
) != 0) {
4456 #define GEN_MAC_HANDLER(name, opc2, opc3) \
4457 GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_405_MAC) \
4459 gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode), \
4460 rD(ctx->opcode), Rc(ctx->opcode)); \
4463 /* macchw - macchw. */
4464 GEN_MAC_HANDLER(macchw
, 0x0C, 0x05);
4465 /* macchwo - macchwo. */
4466 GEN_MAC_HANDLER(macchwo
, 0x0C, 0x15);
4467 /* macchws - macchws. */
4468 GEN_MAC_HANDLER(macchws
, 0x0C, 0x07);
4469 /* macchwso - macchwso. */
4470 GEN_MAC_HANDLER(macchwso
, 0x0C, 0x17);
4471 /* macchwsu - macchwsu. */
4472 GEN_MAC_HANDLER(macchwsu
, 0x0C, 0x06);
4473 /* macchwsuo - macchwsuo. */
4474 GEN_MAC_HANDLER(macchwsuo
, 0x0C, 0x16);
4475 /* macchwu - macchwu. */
4476 GEN_MAC_HANDLER(macchwu
, 0x0C, 0x04);
4477 /* macchwuo - macchwuo. */
4478 GEN_MAC_HANDLER(macchwuo
, 0x0C, 0x14);
4479 /* machhw - machhw. */
4480 GEN_MAC_HANDLER(machhw
, 0x0C, 0x01);
4481 /* machhwo - machhwo. */
4482 GEN_MAC_HANDLER(machhwo
, 0x0C, 0x11);
4483 /* machhws - machhws. */
4484 GEN_MAC_HANDLER(machhws
, 0x0C, 0x03);
4485 /* machhwso - machhwso. */
4486 GEN_MAC_HANDLER(machhwso
, 0x0C, 0x13);
4487 /* machhwsu - machhwsu. */
4488 GEN_MAC_HANDLER(machhwsu
, 0x0C, 0x02);
4489 /* machhwsuo - machhwsuo. */
4490 GEN_MAC_HANDLER(machhwsuo
, 0x0C, 0x12);
4491 /* machhwu - machhwu. */
4492 GEN_MAC_HANDLER(machhwu
, 0x0C, 0x00);
4493 /* machhwuo - machhwuo. */
4494 GEN_MAC_HANDLER(machhwuo
, 0x0C, 0x10);
4495 /* maclhw - maclhw. */
4496 GEN_MAC_HANDLER(maclhw
, 0x0C, 0x0D);
4497 /* maclhwo - maclhwo. */
4498 GEN_MAC_HANDLER(maclhwo
, 0x0C, 0x1D);
4499 /* maclhws - maclhws. */
4500 GEN_MAC_HANDLER(maclhws
, 0x0C, 0x0F);
4501 /* maclhwso - maclhwso. */
4502 GEN_MAC_HANDLER(maclhwso
, 0x0C, 0x1F);
4503 /* maclhwu - maclhwu. */
4504 GEN_MAC_HANDLER(maclhwu
, 0x0C, 0x0C);
4505 /* maclhwuo - maclhwuo. */
4506 GEN_MAC_HANDLER(maclhwuo
, 0x0C, 0x1C);
4507 /* maclhwsu - maclhwsu. */
4508 GEN_MAC_HANDLER(maclhwsu
, 0x0C, 0x0E);
4509 /* maclhwsuo - maclhwsuo. */
4510 GEN_MAC_HANDLER(maclhwsuo
, 0x0C, 0x1E);
4511 /* nmacchw - nmacchw. */
4512 GEN_MAC_HANDLER(nmacchw
, 0x0E, 0x05);
4513 /* nmacchwo - nmacchwo. */
4514 GEN_MAC_HANDLER(nmacchwo
, 0x0E, 0x15);
4515 /* nmacchws - nmacchws. */
4516 GEN_MAC_HANDLER(nmacchws
, 0x0E, 0x07);
4517 /* nmacchwso - nmacchwso. */
4518 GEN_MAC_HANDLER(nmacchwso
, 0x0E, 0x17);
4519 /* nmachhw - nmachhw. */
4520 GEN_MAC_HANDLER(nmachhw
, 0x0E, 0x01);
4521 /* nmachhwo - nmachhwo. */
4522 GEN_MAC_HANDLER(nmachhwo
, 0x0E, 0x11);
4523 /* nmachhws - nmachhws. */
4524 GEN_MAC_HANDLER(nmachhws
, 0x0E, 0x03);
4525 /* nmachhwso - nmachhwso. */
4526 GEN_MAC_HANDLER(nmachhwso
, 0x0E, 0x13);
4527 /* nmaclhw - nmaclhw. */
4528 GEN_MAC_HANDLER(nmaclhw
, 0x0E, 0x0D);
4529 /* nmaclhwo - nmaclhwo. */
4530 GEN_MAC_HANDLER(nmaclhwo
, 0x0E, 0x1D);
4531 /* nmaclhws - nmaclhws. */
4532 GEN_MAC_HANDLER(nmaclhws
, 0x0E, 0x0F);
4533 /* nmaclhwso - nmaclhwso. */
4534 GEN_MAC_HANDLER(nmaclhwso
, 0x0E, 0x1F);
4536 /* mulchw - mulchw. */
4537 GEN_MAC_HANDLER(mulchw
, 0x08, 0x05);
4538 /* mulchwu - mulchwu. */
4539 GEN_MAC_HANDLER(mulchwu
, 0x08, 0x04);
4540 /* mulhhw - mulhhw. */
4541 GEN_MAC_HANDLER(mulhhw
, 0x08, 0x01);
4542 /* mulhhwu - mulhhwu. */
4543 GEN_MAC_HANDLER(mulhhwu
, 0x08, 0x00);
4544 /* mullhw - mullhw. */
4545 GEN_MAC_HANDLER(mullhw
, 0x08, 0x0D);
4546 /* mullhwu - mullhwu. */
4547 GEN_MAC_HANDLER(mullhwu
, 0x08, 0x0C);
4550 GEN_HANDLER(mfdcr
, 0x1F, 0x03, 0x0A, 0x00000001, PPC_EMB_COMMON
)
4552 #if defined(CONFIG_USER_ONLY)
4555 uint32_t dcrn
= SPR(ctx
->opcode
);
4557 if (unlikely(!ctx
->supervisor
)) {
4561 gen_op_set_T0(dcrn
);
4563 gen_op_store_T0_gpr(rD(ctx
->opcode
));
4568 GEN_HANDLER(mtdcr
, 0x1F, 0x03, 0x0E, 0x00000001, PPC_EMB_COMMON
)
4570 #if defined(CONFIG_USER_ONLY)
4573 uint32_t dcrn
= SPR(ctx
->opcode
);
4575 if (unlikely(!ctx
->supervisor
)) {
4579 gen_op_set_T0(dcrn
);
4580 gen_op_load_gpr_T1(rS(ctx
->opcode
));
4586 /* XXX: not implemented on 440 ? */
4587 GEN_HANDLER(mfdcrx
, 0x1F, 0x03, 0x08, 0x00000000, PPC_BOOKE_EXT
)
4589 #if defined(CONFIG_USER_ONLY)
4592 if (unlikely(!ctx
->supervisor
)) {
4596 gen_op_load_gpr_T0(rA(ctx
->opcode
));
4598 gen_op_store_T0_gpr(rD(ctx
->opcode
));
4599 /* Note: Rc update flag set leads to undefined state of Rc0 */
4604 /* XXX: not implemented on 440 ? */
4605 GEN_HANDLER(mtdcrx
, 0x1F, 0x03, 0x0C, 0x00000000, PPC_BOOKE_EXT
)
4607 #if defined(CONFIG_USER_ONLY)
4610 if (unlikely(!ctx
->supervisor
)) {
4614 gen_op_load_gpr_T0(rA(ctx
->opcode
));
4615 gen_op_load_gpr_T1(rS(ctx
->opcode
));
4617 /* Note: Rc update flag set leads to undefined state of Rc0 */
4621 /* mfdcrux (PPC 460) : user-mode access to DCR */
4622 GEN_HANDLER(mfdcrux
, 0x1F, 0x03, 0x09, 0x00000000, PPC_DCRUX
)
4624 gen_op_load_gpr_T0(rA(ctx
->opcode
));
4626 gen_op_store_T0_gpr(rD(ctx
->opcode
));
4627 /* Note: Rc update flag set leads to undefined state of Rc0 */
4630 /* mtdcrux (PPC 460) : user-mode access to DCR */
4631 GEN_HANDLER(mtdcrux
, 0x1F, 0x03, 0x0D, 0x00000000, PPC_DCRUX
)
4633 gen_op_load_gpr_T0(rA(ctx
->opcode
));
4634 gen_op_load_gpr_T1(rS(ctx
->opcode
));
4636 /* Note: Rc update flag set leads to undefined state of Rc0 */
4640 GEN_HANDLER(dccci
, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON
)
4642 #if defined(CONFIG_USER_ONLY)
4645 if (unlikely(!ctx
->supervisor
)) {
4649 /* interpreted as no-op */
4654 GEN_HANDLER(dcread
, 0x1F, 0x06, 0x0F, 0x00000001, PPC_4xx_COMMON
)
4656 #if defined(CONFIG_USER_ONLY)
4659 if (unlikely(!ctx
->supervisor
)) {
4663 gen_addr_reg_index(ctx
);
4665 gen_op_store_T0_gpr(rD(ctx
->opcode
));
4670 GEN_HANDLER(icbt_40x
, 0x1F, 0x06, 0x08, 0x03E00001, PPC_40x_ICBT
)
4672 /* interpreted as no-op */
4673 /* XXX: specification say this is treated as a load by the MMU
4674 * but does not generate any exception
4679 GEN_HANDLER(iccci
, 0x1F, 0x06, 0x1E, 0x00000001, PPC_4xx_COMMON
)
4681 #if defined(CONFIG_USER_ONLY)
4684 if (unlikely(!ctx
->supervisor
)) {
4688 /* interpreted as no-op */
4693 GEN_HANDLER(icread
, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON
)
4695 #if defined(CONFIG_USER_ONLY)
4698 if (unlikely(!ctx
->supervisor
)) {
4702 /* interpreted as no-op */
4706 /* rfci (supervisor only) */
4707 GEN_HANDLER(rfci_40x
, 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP
)
4709 #if defined(CONFIG_USER_ONLY)
4712 if (unlikely(!ctx
->supervisor
)) {
4716 /* Restore CPU state */
4722 GEN_HANDLER(rfci
, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE
)
4724 #if defined(CONFIG_USER_ONLY)
4727 if (unlikely(!ctx
->supervisor
)) {
4731 /* Restore CPU state */
4737 /* BookE specific */
4738 /* XXX: not implemented on 440 ? */
4739 GEN_HANDLER(rfdi
, 0x13, 0x07, 0x01, 0x03FF8001, PPC_BOOKE_EXT
)
4741 #if defined(CONFIG_USER_ONLY)
4744 if (unlikely(!ctx
->supervisor
)) {
4748 /* Restore CPU state */
4754 /* XXX: not implemented on 440 ? */
4755 GEN_HANDLER(rfmci
, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI
)
4757 #if defined(CONFIG_USER_ONLY)
4760 if (unlikely(!ctx
->supervisor
)) {
4764 /* Restore CPU state */
4770 /* TLB management - PowerPC 405 implementation */
4772 GEN_HANDLER(tlbre_40x
, 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB
)
4774 #if defined(CONFIG_USER_ONLY)
4777 if (unlikely(!ctx
->supervisor
)) {
4781 switch (rB(ctx
->opcode
)) {
4783 gen_op_load_gpr_T0(rA(ctx
->opcode
));
4784 gen_op_4xx_tlbre_hi();
4785 gen_op_store_T0_gpr(rD(ctx
->opcode
));
4788 gen_op_load_gpr_T0(rA(ctx
->opcode
));
4789 gen_op_4xx_tlbre_lo();
4790 gen_op_store_T0_gpr(rD(ctx
->opcode
));
4799 /* tlbsx - tlbsx. */
4800 GEN_HANDLER(tlbsx_40x
, 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_TLB
)
4802 #if defined(CONFIG_USER_ONLY)
4805 if (unlikely(!ctx
->supervisor
)) {
4809 gen_addr_reg_index(ctx
);
4810 if (Rc(ctx
->opcode
))
4811 gen_op_4xx_tlbsx_();
4814 gen_op_store_T0_gpr(rD(ctx
->opcode
));
4819 GEN_HANDLER(tlbwe_40x
, 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB
)
4821 #if defined(CONFIG_USER_ONLY)
4824 if (unlikely(!ctx
->supervisor
)) {
4828 switch (rB(ctx
->opcode
)) {
4830 gen_op_load_gpr_T0(rA(ctx
->opcode
));
4831 gen_op_load_gpr_T1(rS(ctx
->opcode
));
4832 gen_op_4xx_tlbwe_hi();
4835 gen_op_load_gpr_T0(rA(ctx
->opcode
));
4836 gen_op_load_gpr_T1(rS(ctx
->opcode
));
4837 gen_op_4xx_tlbwe_lo();
4846 /* TLB management - PowerPC 440 implementation */
4848 GEN_HANDLER(tlbre_440
, 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE
)
4850 #if defined(CONFIG_USER_ONLY)
4853 if (unlikely(!ctx
->supervisor
)) {
4857 switch (rB(ctx
->opcode
)) {
4861 gen_op_load_gpr_T0(rA(ctx
->opcode
));
4862 gen_op_440_tlbre(rB(ctx
->opcode
));
4863 gen_op_store_T0_gpr(rD(ctx
->opcode
));
4872 /* tlbsx - tlbsx. */
4873 GEN_HANDLER(tlbsx_440
, 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE
)
4875 #if defined(CONFIG_USER_ONLY)
4878 if (unlikely(!ctx
->supervisor
)) {
4882 gen_addr_reg_index(ctx
);
4883 if (Rc(ctx
->opcode
))
4884 gen_op_440_tlbsx_();
4887 gen_op_store_T0_gpr(rD(ctx
->opcode
));
4892 GEN_HANDLER(tlbwe_440
, 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE
)
4894 #if defined(CONFIG_USER_ONLY)
4897 if (unlikely(!ctx
->supervisor
)) {
4901 switch (rB(ctx
->opcode
)) {
4905 gen_op_load_gpr_T0(rA(ctx
->opcode
));
4906 gen_op_load_gpr_T1(rS(ctx
->opcode
));
4907 gen_op_440_tlbwe(rB(ctx
->opcode
));
4917 GEN_HANDLER(wrtee
, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_EMB_COMMON
)
4919 #if defined(CONFIG_USER_ONLY)
4922 if (unlikely(!ctx
->supervisor
)) {
4926 gen_op_load_gpr_T0(rD(ctx
->opcode
));
4928 RET_EXCP(ctx
, EXCP_MTMSR
, 0);
4933 GEN_HANDLER(wrteei
, 0x1F, 0x03, 0x05, 0x000EFC01, PPC_EMB_COMMON
)
4935 #if defined(CONFIG_USER_ONLY)
4938 if (unlikely(!ctx
->supervisor
)) {
4942 gen_op_set_T0(ctx
->opcode
& 0x00010000);
4944 RET_EXCP(ctx
, EXCP_MTMSR
, 0);
4948 /* PowerPC 440 specific instructions */
4950 GEN_HANDLER(dlmzb
, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC
)
4952 gen_op_load_gpr_T0(rS(ctx
->opcode
));
4953 gen_op_load_gpr_T1(rB(ctx
->opcode
));
4955 gen_op_store_T0_gpr(rA(ctx
->opcode
));
4956 gen_op_store_xer_bc();
4957 if (Rc(ctx
->opcode
)) {
4958 gen_op_440_dlmzb_update_Rc();
4959 gen_op_store_T0_crf(0);
4963 /* mbar replaces eieio on 440 */
4964 GEN_HANDLER(mbar
, 0x1F, 0x16, 0x13, 0x001FF801, PPC_BOOKE
)
4966 /* interpreted as no-op */
4969 /* msync replaces sync on 440 */
4970 GEN_HANDLER(msync
, 0x1F, 0x16, 0x12, 0x03FF0801, PPC_BOOKE
)
4972 /* interpreted as no-op */
4976 GEN_HANDLER(icbt_440
, 0x1F, 0x16, 0x00, 0x03E00001, PPC_BOOKE
)
4978 /* interpreted as no-op */
4979 /* XXX: specification say this is treated as a load by the MMU
4980 * but does not generate any exception
4984 #if defined(TARGET_PPCEMB)
4985 /*** SPE extension ***/
4987 /* Register moves */
4988 GEN32(gen_op_load_gpr64_T0
, gen_op_load_gpr64_T0_gpr
);
4989 GEN32(gen_op_load_gpr64_T1
, gen_op_load_gpr64_T1_gpr
);
4991 GEN32(gen_op_load_gpr64_T2
, gen_op_load_gpr64_T2_gpr
);
4994 GEN32(gen_op_store_T0_gpr64
, gen_op_store_T0_gpr64_gpr
);
4995 GEN32(gen_op_store_T1_gpr64
, gen_op_store_T1_gpr64_gpr
);
4997 GEN32(gen_op_store_T2_gpr64
, gen_op_store_T2_gpr64_gpr
);
5000 #define GEN_SPE(name0, name1, opc2, opc3, inval, type) \
5001 GEN_HANDLER(name0##_##name1, 0x04, opc2, opc3, inval, type) \
5003 if (Rc(ctx->opcode)) \
5009 /* Handler for undefined SPE opcodes */
5010 static inline void gen_speundef (DisasContext
*ctx
)
5015 /* SPE load and stores */
5016 static inline void gen_addr_spe_imm_index (DisasContext
*ctx
, int sh
)
5018 target_long simm
= rB(ctx
->opcode
);
5020 if (rA(ctx
->opcode
) == 0) {
5021 gen_set_T0(simm
<< sh
);
5023 gen_op_load_gpr_T0(rA(ctx
->opcode
));
5024 if (likely(simm
!= 0))
5025 gen_op_addi(simm
<< sh
);
5029 #define op_spe_ldst(name) (*gen_op_##name[ctx->mem_idx])()
5030 #if defined(CONFIG_USER_ONLY)
5031 #if defined(TARGET_PPC64)
5032 #define OP_SPE_LD_TABLE(name) \
5033 static GenOpFunc *gen_op_spe_l##name[] = { \
5034 &gen_op_spe_l##name##_raw, \
5035 &gen_op_spe_l##name##_le_raw, \
5036 &gen_op_spe_l##name##_64_raw, \
5037 &gen_op_spe_l##name##_le_64_raw, \
5039 #define OP_SPE_ST_TABLE(name) \
5040 static GenOpFunc *gen_op_spe_st##name[] = { \
5041 &gen_op_spe_st##name##_raw, \
5042 &gen_op_spe_st##name##_le_raw, \
5043 &gen_op_spe_st##name##_64_raw, \
5044 &gen_op_spe_st##name##_le_64_raw, \
5046 #else /* defined(TARGET_PPC64) */
5047 #define OP_SPE_LD_TABLE(name) \
5048 static GenOpFunc *gen_op_spe_l##name[] = { \
5049 &gen_op_spe_l##name##_raw, \
5050 &gen_op_spe_l##name##_le_raw, \
5052 #define OP_SPE_ST_TABLE(name) \
5053 static GenOpFunc *gen_op_spe_st##name[] = { \
5054 &gen_op_spe_st##name##_raw, \
5055 &gen_op_spe_st##name##_le_raw, \
5057 #endif /* defined(TARGET_PPC64) */
5058 #else /* defined(CONFIG_USER_ONLY) */
5059 #if defined(TARGET_PPC64)
5060 #define OP_SPE_LD_TABLE(name) \
5061 static GenOpFunc *gen_op_spe_l##name[] = { \
5062 &gen_op_spe_l##name##_user, \
5063 &gen_op_spe_l##name##_le_user, \
5064 &gen_op_spe_l##name##_kernel, \
5065 &gen_op_spe_l##name##_le_kernel, \
5066 &gen_op_spe_l##name##_64_user, \
5067 &gen_op_spe_l##name##_le_64_user, \
5068 &gen_op_spe_l##name##_64_kernel, \
5069 &gen_op_spe_l##name##_le_64_kernel, \
5071 #define OP_SPE_ST_TABLE(name) \
5072 static GenOpFunc *gen_op_spe_st##name[] = { \
5073 &gen_op_spe_st##name##_user, \
5074 &gen_op_spe_st##name##_le_user, \
5075 &gen_op_spe_st##name##_kernel, \
5076 &gen_op_spe_st##name##_le_kernel, \
5077 &gen_op_spe_st##name##_64_user, \
5078 &gen_op_spe_st##name##_le_64_user, \
5079 &gen_op_spe_st##name##_64_kernel, \
5080 &gen_op_spe_st##name##_le_64_kernel, \
5082 #else /* defined(TARGET_PPC64) */
5083 #define OP_SPE_LD_TABLE(name) \
5084 static GenOpFunc *gen_op_spe_l##name[] = { \
5085 &gen_op_spe_l##name##_user, \
5086 &gen_op_spe_l##name##_le_user, \
5087 &gen_op_spe_l##name##_kernel, \
5088 &gen_op_spe_l##name##_le_kernel, \
5090 #define OP_SPE_ST_TABLE(name) \
5091 static GenOpFunc *gen_op_spe_st##name[] = { \
5092 &gen_op_spe_st##name##_user, \
5093 &gen_op_spe_st##name##_le_user, \
5094 &gen_op_spe_st##name##_kernel, \
5095 &gen_op_spe_st##name##_le_kernel, \
5097 #endif /* defined(TARGET_PPC64) */
5098 #endif /* defined(CONFIG_USER_ONLY) */
5100 #define GEN_SPE_LD(name, sh) \
5101 static inline void gen_evl##name (DisasContext *ctx) \
5103 if (unlikely(!ctx->spe_enabled)) { \
5104 RET_EXCP(ctx, EXCP_NO_SPE, 0); \
5107 gen_addr_spe_imm_index(ctx, sh); \
5108 op_spe_ldst(spe_l##name); \
5109 gen_op_store_T1_gpr64(rD(ctx->opcode)); \
5112 #define GEN_SPE_LDX(name) \
5113 static inline void gen_evl##name##x (DisasContext *ctx) \
5115 if (unlikely(!ctx->spe_enabled)) { \
5116 RET_EXCP(ctx, EXCP_NO_SPE, 0); \
5119 gen_addr_reg_index(ctx); \
5120 op_spe_ldst(spe_l##name); \
5121 gen_op_store_T1_gpr64(rD(ctx->opcode)); \
5124 #define GEN_SPEOP_LD(name, sh) \
5125 OP_SPE_LD_TABLE(name); \
5126 GEN_SPE_LD(name, sh); \
5129 #define GEN_SPE_ST(name, sh) \
5130 static inline void gen_evst##name (DisasContext *ctx) \
5132 if (unlikely(!ctx->spe_enabled)) { \
5133 RET_EXCP(ctx, EXCP_NO_SPE, 0); \
5136 gen_addr_spe_imm_index(ctx, sh); \
5137 gen_op_load_gpr64_T1(rS(ctx->opcode)); \
5138 op_spe_ldst(spe_st##name); \
5141 #define GEN_SPE_STX(name) \
5142 static inline void gen_evst##name##x (DisasContext *ctx) \
5144 if (unlikely(!ctx->spe_enabled)) { \
5145 RET_EXCP(ctx, EXCP_NO_SPE, 0); \
5148 gen_addr_reg_index(ctx); \
5149 gen_op_load_gpr64_T1(rS(ctx->opcode)); \
5150 op_spe_ldst(spe_st##name); \
5153 #define GEN_SPEOP_ST(name, sh) \
5154 OP_SPE_ST_TABLE(name); \
5155 GEN_SPE_ST(name, sh); \
5158 #define GEN_SPEOP_LDST(name, sh) \
5159 GEN_SPEOP_LD(name, sh); \
5160 GEN_SPEOP_ST(name, sh)
5162 /* SPE arithmetic and logic */
5163 #define GEN_SPEOP_ARITH2(name) \
5164 static inline void gen_##name (DisasContext *ctx) \
5166 if (unlikely(!ctx->spe_enabled)) { \
5167 RET_EXCP(ctx, EXCP_NO_SPE, 0); \
5170 gen_op_load_gpr64_T0(rA(ctx->opcode)); \
5171 gen_op_load_gpr64_T1(rB(ctx->opcode)); \
5173 gen_op_store_T0_gpr64(rD(ctx->opcode)); \
5176 #define GEN_SPEOP_ARITH1(name) \
5177 static inline void gen_##name (DisasContext *ctx) \
5179 if (unlikely(!ctx->spe_enabled)) { \
5180 RET_EXCP(ctx, EXCP_NO_SPE, 0); \
5183 gen_op_load_gpr64_T0(rA(ctx->opcode)); \
5185 gen_op_store_T0_gpr64(rD(ctx->opcode)); \
5188 #define GEN_SPEOP_COMP(name) \
5189 static inline void gen_##name (DisasContext *ctx) \
5191 if (unlikely(!ctx->spe_enabled)) { \
5192 RET_EXCP(ctx, EXCP_NO_SPE, 0); \
5195 gen_op_load_gpr64_T0(rA(ctx->opcode)); \
5196 gen_op_load_gpr64_T1(rB(ctx->opcode)); \
5198 gen_op_store_T0_crf(crfD(ctx->opcode)); \
5202 GEN_SPEOP_ARITH2(evand
);
5203 GEN_SPEOP_ARITH2(evandc
);
5204 GEN_SPEOP_ARITH2(evxor
);
5205 GEN_SPEOP_ARITH2(evor
);
5206 GEN_SPEOP_ARITH2(evnor
);
5207 GEN_SPEOP_ARITH2(eveqv
);
5208 GEN_SPEOP_ARITH2(evorc
);
5209 GEN_SPEOP_ARITH2(evnand
);
5210 GEN_SPEOP_ARITH2(evsrwu
);
5211 GEN_SPEOP_ARITH2(evsrws
);
5212 GEN_SPEOP_ARITH2(evslw
);
5213 GEN_SPEOP_ARITH2(evrlw
);
5214 GEN_SPEOP_ARITH2(evmergehi
);
5215 GEN_SPEOP_ARITH2(evmergelo
);
5216 GEN_SPEOP_ARITH2(evmergehilo
);
5217 GEN_SPEOP_ARITH2(evmergelohi
);
5220 GEN_SPEOP_ARITH2(evaddw
);
5221 GEN_SPEOP_ARITH2(evsubfw
);
5222 GEN_SPEOP_ARITH1(evabs
);
5223 GEN_SPEOP_ARITH1(evneg
);
5224 GEN_SPEOP_ARITH1(evextsb
);
5225 GEN_SPEOP_ARITH1(evextsh
);
5226 GEN_SPEOP_ARITH1(evrndw
);
5227 GEN_SPEOP_ARITH1(evcntlzw
);
5228 GEN_SPEOP_ARITH1(evcntlsw
);
5229 static inline void gen_brinc (DisasContext
*ctx
)
5231 /* Note: brinc is usable even if SPE is disabled */
5232 gen_op_load_gpr64_T0(rA(ctx
->opcode
));
5233 gen_op_load_gpr64_T1(rB(ctx
->opcode
));
5235 gen_op_store_T0_gpr64(rD(ctx
->opcode
));
5238 #define GEN_SPEOP_ARITH_IMM2(name) \
5239 static inline void gen_##name##i (DisasContext *ctx) \
5241 if (unlikely(!ctx->spe_enabled)) { \
5242 RET_EXCP(ctx, EXCP_NO_SPE, 0); \
5245 gen_op_load_gpr64_T0(rB(ctx->opcode)); \
5246 gen_op_splatwi_T1_64(rA(ctx->opcode)); \
5248 gen_op_store_T0_gpr64(rD(ctx->opcode)); \
5251 #define GEN_SPEOP_LOGIC_IMM2(name) \
5252 static inline void gen_##name##i (DisasContext *ctx) \
5254 if (unlikely(!ctx->spe_enabled)) { \
5255 RET_EXCP(ctx, EXCP_NO_SPE, 0); \
5258 gen_op_load_gpr64_T0(rA(ctx->opcode)); \
5259 gen_op_splatwi_T1_64(rB(ctx->opcode)); \
5261 gen_op_store_T0_gpr64(rD(ctx->opcode)); \
5264 GEN_SPEOP_ARITH_IMM2(evaddw
);
5265 #define gen_evaddiw gen_evaddwi
5266 GEN_SPEOP_ARITH_IMM2(evsubfw
);
5267 #define gen_evsubifw gen_evsubfwi
5268 GEN_SPEOP_LOGIC_IMM2(evslw
);
5269 GEN_SPEOP_LOGIC_IMM2(evsrwu
);
5270 #define gen_evsrwis gen_evsrwsi
5271 GEN_SPEOP_LOGIC_IMM2(evsrws
);
5272 #define gen_evsrwiu gen_evsrwui
5273 GEN_SPEOP_LOGIC_IMM2(evrlw
);
5275 static inline void gen_evsplati (DisasContext
*ctx
)
5277 int32_t imm
= (int32_t)(rA(ctx
->opcode
) << 27) >> 27;
5279 gen_op_splatwi_T0_64(imm
);
5280 gen_op_store_T0_gpr64(rD(ctx
->opcode
));
5283 static inline void gen_evsplatfi (DisasContext
*ctx
)
5285 uint32_t imm
= rA(ctx
->opcode
) << 27;
5287 gen_op_splatwi_T0_64(imm
);
5288 gen_op_store_T0_gpr64(rD(ctx
->opcode
));
5292 GEN_SPEOP_COMP(evcmpgtu
);
5293 GEN_SPEOP_COMP(evcmpgts
);
5294 GEN_SPEOP_COMP(evcmpltu
);
5295 GEN_SPEOP_COMP(evcmplts
);
5296 GEN_SPEOP_COMP(evcmpeq
);
5298 GEN_SPE(evaddw
, speundef
, 0x00, 0x08, 0x00000000, PPC_SPE
); ////
5299 GEN_SPE(evaddiw
, speundef
, 0x01, 0x08, 0x00000000, PPC_SPE
);
5300 GEN_SPE(evsubfw
, speundef
, 0x02, 0x08, 0x00000000, PPC_SPE
); ////
5301 GEN_SPE(evsubifw
, speundef
, 0x03, 0x08, 0x00000000, PPC_SPE
);
5302 GEN_SPE(evabs
, evneg
, 0x04, 0x08, 0x0000F800, PPC_SPE
); ////
5303 GEN_SPE(evextsb
, evextsh
, 0x05, 0x08, 0x0000F800, PPC_SPE
); ////
5304 GEN_SPE(evrndw
, evcntlzw
, 0x06, 0x08, 0x0000F800, PPC_SPE
); ////
5305 GEN_SPE(evcntlsw
, brinc
, 0x07, 0x08, 0x00000000, PPC_SPE
); //
5306 GEN_SPE(speundef
, evand
, 0x08, 0x08, 0x00000000, PPC_SPE
); ////
5307 GEN_SPE(evandc
, speundef
, 0x09, 0x08, 0x00000000, PPC_SPE
); ////
5308 GEN_SPE(evxor
, evor
, 0x0B, 0x08, 0x00000000, PPC_SPE
); ////
5309 GEN_SPE(evnor
, eveqv
, 0x0C, 0x08, 0x00000000, PPC_SPE
); ////
5310 GEN_SPE(speundef
, evorc
, 0x0D, 0x08, 0x00000000, PPC_SPE
); ////
5311 GEN_SPE(evnand
, speundef
, 0x0F, 0x08, 0x00000000, PPC_SPE
); ////
5312 GEN_SPE(evsrwu
, evsrws
, 0x10, 0x08, 0x00000000, PPC_SPE
); ////
5313 GEN_SPE(evsrwiu
, evsrwis
, 0x11, 0x08, 0x00000000, PPC_SPE
);
5314 GEN_SPE(evslw
, speundef
, 0x12, 0x08, 0x00000000, PPC_SPE
); ////
5315 GEN_SPE(evslwi
, speundef
, 0x13, 0x08, 0x00000000, PPC_SPE
);
5316 GEN_SPE(evrlw
, evsplati
, 0x14, 0x08, 0x00000000, PPC_SPE
); //
5317 GEN_SPE(evrlwi
, evsplatfi
, 0x15, 0x08, 0x00000000, PPC_SPE
);
5318 GEN_SPE(evmergehi
, evmergelo
, 0x16, 0x08, 0x00000000, PPC_SPE
); ////
5319 GEN_SPE(evmergehilo
, evmergelohi
, 0x17, 0x08, 0x00000000, PPC_SPE
); ////
5320 GEN_SPE(evcmpgtu
, evcmpgts
, 0x18, 0x08, 0x00600000, PPC_SPE
); ////
5321 GEN_SPE(evcmpltu
, evcmplts
, 0x19, 0x08, 0x00600000, PPC_SPE
); ////
5322 GEN_SPE(evcmpeq
, speundef
, 0x1A, 0x08, 0x00600000, PPC_SPE
); ////
5324 static inline void gen_evsel (DisasContext
*ctx
)
5326 if (unlikely(!ctx
->spe_enabled
)) {
5327 RET_EXCP(ctx
, EXCP_NO_SPE
, 0);
5330 gen_op_load_crf_T0(ctx
->opcode
& 0x7);
5331 gen_op_load_gpr64_T0(rA(ctx
->opcode
));
5332 gen_op_load_gpr64_T1(rB(ctx
->opcode
));
5334 gen_op_store_T0_gpr64(rD(ctx
->opcode
));
5337 GEN_HANDLER(evsel0
, 0x04, 0x1c, 0x09, 0x00000000, PPC_SPE
)
5341 GEN_HANDLER(evsel1
, 0x04, 0x1d, 0x09, 0x00000000, PPC_SPE
)
5345 GEN_HANDLER(evsel2
, 0x04, 0x1e, 0x09, 0x00000000, PPC_SPE
)
5349 GEN_HANDLER(evsel3
, 0x04, 0x1f, 0x09, 0x00000000, PPC_SPE
)
5354 /* Load and stores */
5355 #if defined(TARGET_PPC64)
5356 /* In that case, we already have 64 bits load & stores
5357 * so, spe_ldd is equivalent to ld and spe_std is equivalent to std
5359 #if defined(CONFIG_USER_ONLY)
5360 #define gen_op_spe_ldd_raw gen_op_ld_raw
5361 #define gen_op_spe_ldd_64_raw gen_op_ld_64_raw
5362 #define gen_op_spe_ldd_le_raw gen_op_ld_le_raw
5363 #define gen_op_spe_ldd_le_64_raw gen_op_ld_le_64_raw
5364 #define gen_op_spe_stdd_raw gen_op_ld_raw
5365 #define gen_op_spe_stdd_64_raw gen_op_std_64_raw
5366 #define gen_op_spe_stdd_le_raw gen_op_std_le_raw
5367 #define gen_op_spe_stdd_le_64_raw gen_op_std_le_64_raw
5368 #else /* defined(CONFIG_USER_ONLY) */
5369 #define gen_op_spe_ldd_kernel gen_op_ld_kernel
5370 #define gen_op_spe_ldd_64_kernel gen_op_ld_64_kernel
5371 #define gen_op_spe_ldd_le_kernel gen_op_ld_kernel
5372 #define gen_op_spe_ldd_le_64_kernel gen_op_ld_64_kernel
5373 #define gen_op_spe_ldd_user gen_op_ld_user
5374 #define gen_op_spe_ldd_64_user gen_op_ld_64_user
5375 #define gen_op_spe_ldd_le_user gen_op_ld_le_user
5376 #define gen_op_spe_ldd_le_64_user gen_op_ld_le_64_user
5377 #define gen_op_spe_stdd_kernel gen_op_std_kernel
5378 #define gen_op_spe_stdd_64_kernel gen_op_std_64_kernel
5379 #define gen_op_spe_stdd_le_kernel gen_op_std_kernel
5380 #define gen_op_spe_stdd_le_64_kernel gen_op_std_64_kernel
5381 #define gen_op_spe_stdd_user gen_op_std_user
5382 #define gen_op_spe_stdd_64_user gen_op_std_64_user
5383 #define gen_op_spe_stdd_le_user gen_op_std_le_user
5384 #define gen_op_spe_stdd_le_64_user gen_op_std_le_64_user
5385 #endif /* defined(CONFIG_USER_ONLY) */
5386 #endif /* defined(TARGET_PPC64) */
5387 GEN_SPEOP_LDST(dd
, 3);
5388 GEN_SPEOP_LDST(dw
, 3);
5389 GEN_SPEOP_LDST(dh
, 3);
5390 GEN_SPEOP_LDST(whe
, 2);
5391 GEN_SPEOP_LD(whou
, 2);
5392 GEN_SPEOP_LD(whos
, 2);
5393 GEN_SPEOP_ST(who
, 2);
5395 #if defined(TARGET_PPC64)
5396 /* In that case, spe_stwwo is equivalent to stw */
5397 #if defined(CONFIG_USER_ONLY)
5398 #define gen_op_spe_stwwo_raw gen_op_stw_raw
5399 #define gen_op_spe_stwwo_le_raw gen_op_stw_le_raw
5400 #define gen_op_spe_stwwo_64_raw gen_op_stw_64_raw
5401 #define gen_op_spe_stwwo_le_64_raw gen_op_stw_le_64_raw
5403 #define gen_op_spe_stwwo_user gen_op_stw_user
5404 #define gen_op_spe_stwwo_le_user gen_op_stw_le_user
5405 #define gen_op_spe_stwwo_64_user gen_op_stw_64_user
5406 #define gen_op_spe_stwwo_le_64_user gen_op_stw_le_64_user
5407 #define gen_op_spe_stwwo_kernel gen_op_stw_kernel
5408 #define gen_op_spe_stwwo_le_kernel gen_op_stw_le_kernel
5409 #define gen_op_spe_stwwo_64_kernel gen_op_stw_64_kernel
5410 #define gen_op_spe_stwwo_le_64_kernel gen_op_stw_le_64_kernel
5413 #define _GEN_OP_SPE_STWWE(suffix) \
5414 static inline void gen_op_spe_stwwe_##suffix (void) \
5416 gen_op_srli32_T1_64(); \
5417 gen_op_spe_stwwo_##suffix(); \
5419 #define _GEN_OP_SPE_STWWE_LE(suffix) \
5420 static inline void gen_op_spe_stwwe_le_##suffix (void) \
5422 gen_op_srli32_T1_64(); \
5423 gen_op_spe_stwwo_le_##suffix(); \
5425 #if defined(TARGET_PPC64)
5426 #define GEN_OP_SPE_STWWE(suffix) \
5427 _GEN_OP_SPE_STWWE(suffix); \
5428 _GEN_OP_SPE_STWWE_LE(suffix); \
5429 static inline void gen_op_spe_stwwe_64_##suffix (void) \
5431 gen_op_srli32_T1_64(); \
5432 gen_op_spe_stwwo_64_##suffix(); \
5434 static inline void gen_op_spe_stwwe_le_64_##suffix (void) \
5436 gen_op_srli32_T1_64(); \
5437 gen_op_spe_stwwo_le_64_##suffix(); \
5440 #define GEN_OP_SPE_STWWE(suffix) \
5441 _GEN_OP_SPE_STWWE(suffix); \
5442 _GEN_OP_SPE_STWWE_LE(suffix)
5444 #if defined(CONFIG_USER_ONLY)
5445 GEN_OP_SPE_STWWE(raw
);
5446 #else /* defined(CONFIG_USER_ONLY) */
5447 GEN_OP_SPE_STWWE(kernel
);
5448 GEN_OP_SPE_STWWE(user
);
5449 #endif /* defined(CONFIG_USER_ONLY) */
5450 GEN_SPEOP_ST(wwe
, 2);
5451 GEN_SPEOP_ST(wwo
, 2);
5453 #define GEN_SPE_LDSPLAT(name, op, suffix) \
5454 static inline void gen_op_spe_l##name##_##suffix (void) \
5456 gen_op_##op##_##suffix(); \
5457 gen_op_splatw_T1_64(); \
5460 #define GEN_OP_SPE_LHE(suffix) \
5461 static inline void gen_op_spe_lhe_##suffix (void) \
5463 gen_op_spe_lh_##suffix(); \
5464 gen_op_sli16_T1_64(); \
5467 #define GEN_OP_SPE_LHX(suffix) \
5468 static inline void gen_op_spe_lhx_##suffix (void) \
5470 gen_op_spe_lh_##suffix(); \
5471 gen_op_extsh_T1_64(); \
5474 #if defined(CONFIG_USER_ONLY)
5475 GEN_OP_SPE_LHE(raw
);
5476 GEN_SPE_LDSPLAT(hhesplat
, spe_lhe
, raw
);
5477 GEN_OP_SPE_LHE(le_raw
);
5478 GEN_SPE_LDSPLAT(hhesplat
, spe_lhe
, le_raw
);
5479 GEN_SPE_LDSPLAT(hhousplat
, spe_lh
, raw
);
5480 GEN_SPE_LDSPLAT(hhousplat
, spe_lh
, le_raw
);
5481 GEN_OP_SPE_LHX(raw
);
5482 GEN_SPE_LDSPLAT(hhossplat
, spe_lhx
, raw
);
5483 GEN_OP_SPE_LHX(le_raw
);
5484 GEN_SPE_LDSPLAT(hhossplat
, spe_lhx
, le_raw
);
5485 #if defined(TARGET_PPC64)
5486 GEN_OP_SPE_LHE(64_raw
);
5487 GEN_SPE_LDSPLAT(hhesplat
, spe_lhe
, 64_raw
);
5488 GEN_OP_SPE_LHE(le_64_raw
);
5489 GEN_SPE_LDSPLAT(hhesplat
, spe_lhe
, le_64_raw
);
5490 GEN_SPE_LDSPLAT(hhousplat
, spe_lh
, 64_raw
);
5491 GEN_SPE_LDSPLAT(hhousplat
, spe_lh
, le_64_raw
);
5492 GEN_OP_SPE_LHX(64_raw
);
5493 GEN_SPE_LDSPLAT(hhossplat
, spe_lhx
, 64_raw
);
5494 GEN_OP_SPE_LHX(le_64_raw
);
5495 GEN_SPE_LDSPLAT(hhossplat
, spe_lhx
, le_64_raw
);
5498 GEN_OP_SPE_LHE(kernel
);
5499 GEN_OP_SPE_LHE(user
);
5500 GEN_SPE_LDSPLAT(hhesplat
, spe_lhe
, kernel
);
5501 GEN_SPE_LDSPLAT(hhesplat
, spe_lhe
, user
);
5502 GEN_OP_SPE_LHE(le_kernel
);
5503 GEN_OP_SPE_LHE(le_user
);
5504 GEN_SPE_LDSPLAT(hhesplat
, spe_lhe
, le_kernel
);
5505 GEN_SPE_LDSPLAT(hhesplat
, spe_lhe
, le_user
);
5506 GEN_SPE_LDSPLAT(hhousplat
, spe_lh
, kernel
);
5507 GEN_SPE_LDSPLAT(hhousplat
, spe_lh
, user
);
5508 GEN_SPE_LDSPLAT(hhousplat
, spe_lh
, le_kernel
);
5509 GEN_SPE_LDSPLAT(hhousplat
, spe_lh
, le_user
);
5510 GEN_OP_SPE_LHX(kernel
);
5511 GEN_OP_SPE_LHX(user
);
5512 GEN_SPE_LDSPLAT(hhossplat
, spe_lhx
, kernel
);
5513 GEN_SPE_LDSPLAT(hhossplat
, spe_lhx
, user
);
5514 GEN_OP_SPE_LHX(le_kernel
);
5515 GEN_OP_SPE_LHX(le_user
);
5516 GEN_SPE_LDSPLAT(hhossplat
, spe_lhx
, le_kernel
);
5517 GEN_SPE_LDSPLAT(hhossplat
, spe_lhx
, le_user
);
5518 #if defined(TARGET_PPC64)
5519 GEN_OP_SPE_LHE(64_kernel
);
5520 GEN_OP_SPE_LHE(64_user
);
5521 GEN_SPE_LDSPLAT(hhesplat
, spe_lhe
, 64_kernel
);
5522 GEN_SPE_LDSPLAT(hhesplat
, spe_lhe
, 64_user
);
5523 GEN_OP_SPE_LHE(le_64_kernel
);
5524 GEN_OP_SPE_LHE(le_64_user
);
5525 GEN_SPE_LDSPLAT(hhesplat
, spe_lhe
, le_64_kernel
);
5526 GEN_SPE_LDSPLAT(hhesplat
, spe_lhe
, le_64_user
);
5527 GEN_SPE_LDSPLAT(hhousplat
, spe_lh
, 64_kernel
);
5528 GEN_SPE_LDSPLAT(hhousplat
, spe_lh
, 64_user
);
5529 GEN_SPE_LDSPLAT(hhousplat
, spe_lh
, le_64_kernel
);
5530 GEN_SPE_LDSPLAT(hhousplat
, spe_lh
, le_64_user
);
5531 GEN_OP_SPE_LHX(64_kernel
);
5532 GEN_OP_SPE_LHX(64_user
);
5533 GEN_SPE_LDSPLAT(hhossplat
, spe_lhx
, 64_kernel
);
5534 GEN_SPE_LDSPLAT(hhossplat
, spe_lhx
, 64_user
);
5535 GEN_OP_SPE_LHX(le_64_kernel
);
5536 GEN_OP_SPE_LHX(le_64_user
);
5537 GEN_SPE_LDSPLAT(hhossplat
, spe_lhx
, le_64_kernel
);
5538 GEN_SPE_LDSPLAT(hhossplat
, spe_lhx
, le_64_user
);
5541 GEN_SPEOP_LD(hhesplat
, 1);
5542 GEN_SPEOP_LD(hhousplat
, 1);
5543 GEN_SPEOP_LD(hhossplat
, 1);
5544 GEN_SPEOP_LD(wwsplat
, 2);
5545 GEN_SPEOP_LD(whsplat
, 2);
5547 GEN_SPE(evlddx
, evldd
, 0x00, 0x0C, 0x00000000, PPC_SPE
); //
5548 GEN_SPE(evldwx
, evldw
, 0x01, 0x0C, 0x00000000, PPC_SPE
); //
5549 GEN_SPE(evldhx
, evldh
, 0x02, 0x0C, 0x00000000, PPC_SPE
); //
5550 GEN_SPE(evlhhesplatx
, evlhhesplat
, 0x04, 0x0C, 0x00000000, PPC_SPE
); //
5551 GEN_SPE(evlhhousplatx
, evlhhousplat
, 0x06, 0x0C, 0x00000000, PPC_SPE
); //
5552 GEN_SPE(evlhhossplatx
, evlhhossplat
, 0x07, 0x0C, 0x00000000, PPC_SPE
); //
5553 GEN_SPE(evlwhex
, evlwhe
, 0x08, 0x0C, 0x00000000, PPC_SPE
); //
5554 GEN_SPE(evlwhoux
, evlwhou
, 0x0A, 0x0C, 0x00000000, PPC_SPE
); //
5555 GEN_SPE(evlwhosx
, evlwhos
, 0x0B, 0x0C, 0x00000000, PPC_SPE
); //
5556 GEN_SPE(evlwwsplatx
, evlwwsplat
, 0x0C, 0x0C, 0x00000000, PPC_SPE
); //
5557 GEN_SPE(evlwhsplatx
, evlwhsplat
, 0x0E, 0x0C, 0x00000000, PPC_SPE
); //
5558 GEN_SPE(evstddx
, evstdd
, 0x10, 0x0C, 0x00000000, PPC_SPE
); //
5559 GEN_SPE(evstdwx
, evstdw
, 0x11, 0x0C, 0x00000000, PPC_SPE
); //
5560 GEN_SPE(evstdhx
, evstdh
, 0x12, 0x0C, 0x00000000, PPC_SPE
); //
5561 GEN_SPE(evstwhex
, evstwhe
, 0x18, 0x0C, 0x00000000, PPC_SPE
); //
5562 GEN_SPE(evstwhox
, evstwho
, 0x1A, 0x0C, 0x00000000, PPC_SPE
); //
5563 GEN_SPE(evstwwex
, evstwwe
, 0x1C, 0x0C, 0x00000000, PPC_SPE
); //
5564 GEN_SPE(evstwwox
, evstwwo
, 0x1E, 0x0C, 0x00000000, PPC_SPE
); //
5566 /* Multiply and add - TODO */
5568 GEN_SPE(speundef
, evmhessf
, 0x01, 0x10, 0x00000000, PPC_SPE
);
5569 GEN_SPE(speundef
, evmhossf
, 0x03, 0x10, 0x00000000, PPC_SPE
);
5570 GEN_SPE(evmheumi
, evmhesmi
, 0x04, 0x10, 0x00000000, PPC_SPE
);
5571 GEN_SPE(speundef
, evmhesmf
, 0x05, 0x10, 0x00000000, PPC_SPE
);
5572 GEN_SPE(evmhoumi
, evmhosmi
, 0x06, 0x10, 0x00000000, PPC_SPE
);
5573 GEN_SPE(speundef
, evmhosmf
, 0x07, 0x10, 0x00000000, PPC_SPE
);
5574 GEN_SPE(speundef
, evmhessfa
, 0x11, 0x10, 0x00000000, PPC_SPE
);
5575 GEN_SPE(speundef
, evmhossfa
, 0x13, 0x10, 0x00000000, PPC_SPE
);
5576 GEN_SPE(evmheumia
, evmhesmia
, 0x14, 0x10, 0x00000000, PPC_SPE
);
5577 GEN_SPE(speundef
, evmhesmfa
, 0x15, 0x10, 0x00000000, PPC_SPE
);
5578 GEN_SPE(evmhoumia
, evmhosmia
, 0x16, 0x10, 0x00000000, PPC_SPE
);
5579 GEN_SPE(speundef
, evmhosmfa
, 0x17, 0x10, 0x00000000, PPC_SPE
);
5581 GEN_SPE(speundef
, evmwhssf
, 0x03, 0x11, 0x00000000, PPC_SPE
);
5582 GEN_SPE(evmwlumi
, speundef
, 0x04, 0x11, 0x00000000, PPC_SPE
);
5583 GEN_SPE(evmwhumi
, evmwhsmi
, 0x06, 0x11, 0x00000000, PPC_SPE
);
5584 GEN_SPE(speundef
, evmwhsmf
, 0x07, 0x11, 0x00000000, PPC_SPE
);
5585 GEN_SPE(speundef
, evmwssf
, 0x09, 0x11, 0x00000000, PPC_SPE
);
5586 GEN_SPE(evmwumi
, evmwsmi
, 0x0C, 0x11, 0x00000000, PPC_SPE
);
5587 GEN_SPE(speundef
, evmwsmf
, 0x0D, 0x11, 0x00000000, PPC_SPE
);
5588 GEN_SPE(speundef
, evmwhssfa
, 0x13, 0x11, 0x00000000, PPC_SPE
);
5589 GEN_SPE(evmwlumia
, speundef
, 0x14, 0x11, 0x00000000, PPC_SPE
);
5590 GEN_SPE(evmwhumia
, evmwhsmia
, 0x16, 0x11, 0x00000000, PPC_SPE
);
5591 GEN_SPE(speundef
, evmwhsmfa
, 0x17, 0x11, 0x00000000, PPC_SPE
);
5592 GEN_SPE(speundef
, evmwssfa
, 0x19, 0x11, 0x00000000, PPC_SPE
);
5593 GEN_SPE(evmwumia
, evmwsmia
, 0x1C, 0x11, 0x00000000, PPC_SPE
);
5594 GEN_SPE(speundef
, evmwsmfa
, 0x1D, 0x11, 0x00000000, PPC_SPE
);
5596 GEN_SPE(evadduiaaw
, evaddsiaaw
, 0x00, 0x13, 0x0000F800, PPC_SPE
);
5597 GEN_SPE(evsubfusiaaw
, evsubfssiaaw
, 0x01, 0x13, 0x0000F800, PPC_SPE
);
5598 GEN_SPE(evaddumiaaw
, evaddsmiaaw
, 0x04, 0x13, 0x0000F800, PPC_SPE
);
5599 GEN_SPE(evsubfumiaaw
, evsubfsmiaaw
, 0x05, 0x13, 0x0000F800, PPC_SPE
);
5600 GEN_SPE(evdivws
, evdivwu
, 0x06, 0x13, 0x00000000, PPC_SPE
);
5601 GEN_SPE(evmra
, speundef
, 0x07, 0x13, 0x0000F800, PPC_SPE
);
5603 GEN_SPE(evmheusiaaw
, evmhessiaaw
, 0x00, 0x14, 0x00000000, PPC_SPE
);
5604 GEN_SPE(speundef
, evmhessfaaw
, 0x01, 0x14, 0x00000000, PPC_SPE
);
5605 GEN_SPE(evmhousiaaw
, evmhossiaaw
, 0x02, 0x14, 0x00000000, PPC_SPE
);
5606 GEN_SPE(speundef
, evmhossfaaw
, 0x03, 0x14, 0x00000000, PPC_SPE
);
5607 GEN_SPE(evmheumiaaw
, evmhesmiaaw
, 0x04, 0x14, 0x00000000, PPC_SPE
);
5608 GEN_SPE(speundef
, evmhesmfaaw
, 0x05, 0x14, 0x00000000, PPC_SPE
);
5609 GEN_SPE(evmhoumiaaw
, evmhosmiaaw
, 0x06, 0x14, 0x00000000, PPC_SPE
);
5610 GEN_SPE(speundef
, evmhosmfaaw
, 0x07, 0x14, 0x00000000, PPC_SPE
);
5611 GEN_SPE(evmhegumiaa
, evmhegsmiaa
, 0x14, 0x14, 0x00000000, PPC_SPE
);
5612 GEN_SPE(speundef
, evmhegsmfaa
, 0x15, 0x14, 0x00000000, PPC_SPE
);
5613 GEN_SPE(evmhogumiaa
, evmhogsmiaa
, 0x16, 0x14, 0x00000000, PPC_SPE
);
5614 GEN_SPE(speundef
, evmhogsmfaa
, 0x17, 0x14, 0x00000000, PPC_SPE
);
5616 GEN_SPE(evmwlusiaaw
, evmwlssiaaw
, 0x00, 0x15, 0x00000000, PPC_SPE
);
5617 GEN_SPE(evmwlumiaaw
, evmwlsmiaaw
, 0x04, 0x15, 0x00000000, PPC_SPE
);
5618 GEN_SPE(speundef
, evmwssfaa
, 0x09, 0x15, 0x00000000, PPC_SPE
);
5619 GEN_SPE(evmwumiaa
, evmwsmiaa
, 0x0C, 0x15, 0x00000000, PPC_SPE
);
5620 GEN_SPE(speundef
, evmwsmfaa
, 0x0D, 0x15, 0x00000000, PPC_SPE
);
5622 GEN_SPE(evmheusianw
, evmhessianw
, 0x00, 0x16, 0x00000000, PPC_SPE
);
5623 GEN_SPE(speundef
, evmhessfanw
, 0x01, 0x16, 0x00000000, PPC_SPE
);
5624 GEN_SPE(evmhousianw
, evmhossianw
, 0x02, 0x16, 0x00000000, PPC_SPE
);
5625 GEN_SPE(speundef
, evmhossfanw
, 0x03, 0x16, 0x00000000, PPC_SPE
);
5626 GEN_SPE(evmheumianw
, evmhesmianw
, 0x04, 0x16, 0x00000000, PPC_SPE
);
5627 GEN_SPE(speundef
, evmhesmfanw
, 0x05, 0x16, 0x00000000, PPC_SPE
);
5628 GEN_SPE(evmhoumianw
, evmhosmianw
, 0x06, 0x16, 0x00000000, PPC_SPE
);
5629 GEN_SPE(speundef
, evmhosmfanw
, 0x07, 0x16, 0x00000000, PPC_SPE
);
5630 GEN_SPE(evmhegumian
, evmhegsmian
, 0x14, 0x16, 0x00000000, PPC_SPE
);
5631 GEN_SPE(speundef
, evmhegsmfan
, 0x15, 0x16, 0x00000000, PPC_SPE
);
5632 GEN_SPE(evmhigumian
, evmhigsmian
, 0x16, 0x16, 0x00000000, PPC_SPE
);
5633 GEN_SPE(speundef
, evmhogsmfan
, 0x17, 0x16, 0x00000000, PPC_SPE
);
5635 GEN_SPE(evmwlusianw
, evmwlssianw
, 0x00, 0x17, 0x00000000, PPC_SPE
);
5636 GEN_SPE(evmwlumianw
, evmwlsmianw
, 0x04, 0x17, 0x00000000, PPC_SPE
);
5637 GEN_SPE(speundef
, evmwssfan
, 0x09, 0x17, 0x00000000, PPC_SPE
);
5638 GEN_SPE(evmwumian
, evmwsmian
, 0x0C, 0x17, 0x00000000, PPC_SPE
);
5639 GEN_SPE(speundef
, evmwsmfan
, 0x0D, 0x17, 0x00000000, PPC_SPE
);
5642 /*** SPE floating-point extension ***/
5643 #define GEN_SPEFPUOP_CONV(name) \
5644 static inline void gen_##name (DisasContext *ctx) \
5646 gen_op_load_gpr64_T0(rB(ctx->opcode)); \
5648 gen_op_store_T0_gpr64(rD(ctx->opcode)); \
5651 /* Single precision floating-point vectors operations */
5653 GEN_SPEOP_ARITH2(evfsadd
);
5654 GEN_SPEOP_ARITH2(evfssub
);
5655 GEN_SPEOP_ARITH2(evfsmul
);
5656 GEN_SPEOP_ARITH2(evfsdiv
);
5657 GEN_SPEOP_ARITH1(evfsabs
);
5658 GEN_SPEOP_ARITH1(evfsnabs
);
5659 GEN_SPEOP_ARITH1(evfsneg
);
5661 GEN_SPEFPUOP_CONV(evfscfui
);
5662 GEN_SPEFPUOP_CONV(evfscfsi
);
5663 GEN_SPEFPUOP_CONV(evfscfuf
);
5664 GEN_SPEFPUOP_CONV(evfscfsf
);
5665 GEN_SPEFPUOP_CONV(evfsctui
);
5666 GEN_SPEFPUOP_CONV(evfsctsi
);
5667 GEN_SPEFPUOP_CONV(evfsctuf
);
5668 GEN_SPEFPUOP_CONV(evfsctsf
);
5669 GEN_SPEFPUOP_CONV(evfsctuiz
);
5670 GEN_SPEFPUOP_CONV(evfsctsiz
);
5672 GEN_SPEOP_COMP(evfscmpgt
);
5673 GEN_SPEOP_COMP(evfscmplt
);
5674 GEN_SPEOP_COMP(evfscmpeq
);
5675 GEN_SPEOP_COMP(evfststgt
);
5676 GEN_SPEOP_COMP(evfststlt
);
5677 GEN_SPEOP_COMP(evfststeq
);
5679 /* Opcodes definitions */
5680 GEN_SPE(evfsadd
, evfssub
, 0x00, 0x0A, 0x00000000, PPC_SPEFPU
); //
5681 GEN_SPE(evfsabs
, evfsnabs
, 0x02, 0x0A, 0x0000F800, PPC_SPEFPU
); //
5682 GEN_SPE(evfsneg
, speundef
, 0x03, 0x0A, 0x0000F800, PPC_SPEFPU
); //
5683 GEN_SPE(evfsmul
, evfsdiv
, 0x04, 0x0A, 0x00000000, PPC_SPEFPU
); //
5684 GEN_SPE(evfscmpgt
, evfscmplt
, 0x06, 0x0A, 0x00600000, PPC_SPEFPU
); //
5685 GEN_SPE(evfscmpeq
, speundef
, 0x07, 0x0A, 0x00600000, PPC_SPEFPU
); //
5686 GEN_SPE(evfscfui
, evfscfsi
, 0x08, 0x0A, 0x00180000, PPC_SPEFPU
); //
5687 GEN_SPE(evfscfuf
, evfscfsf
, 0x09, 0x0A, 0x00180000, PPC_SPEFPU
); //
5688 GEN_SPE(evfsctui
, evfsctsi
, 0x0A, 0x0A, 0x00180000, PPC_SPEFPU
); //
5689 GEN_SPE(evfsctuf
, evfsctsf
, 0x0B, 0x0A, 0x00180000, PPC_SPEFPU
); //
5690 GEN_SPE(evfsctuiz
, speundef
, 0x0C, 0x0A, 0x00180000, PPC_SPEFPU
); //
5691 GEN_SPE(evfsctsiz
, speundef
, 0x0D, 0x0A, 0x00180000, PPC_SPEFPU
); //
5692 GEN_SPE(evfststgt
, evfststlt
, 0x0E, 0x0A, 0x00600000, PPC_SPEFPU
); //
5693 GEN_SPE(evfststeq
, speundef
, 0x0F, 0x0A, 0x00600000, PPC_SPEFPU
); //
5695 /* Single precision floating-point operations */
5697 GEN_SPEOP_ARITH2(efsadd
);
5698 GEN_SPEOP_ARITH2(efssub
);
5699 GEN_SPEOP_ARITH2(efsmul
);
5700 GEN_SPEOP_ARITH2(efsdiv
);
5701 GEN_SPEOP_ARITH1(efsabs
);
5702 GEN_SPEOP_ARITH1(efsnabs
);
5703 GEN_SPEOP_ARITH1(efsneg
);
5705 GEN_SPEFPUOP_CONV(efscfui
);
5706 GEN_SPEFPUOP_CONV(efscfsi
);
5707 GEN_SPEFPUOP_CONV(efscfuf
);
5708 GEN_SPEFPUOP_CONV(efscfsf
);
5709 GEN_SPEFPUOP_CONV(efsctui
);
5710 GEN_SPEFPUOP_CONV(efsctsi
);
5711 GEN_SPEFPUOP_CONV(efsctuf
);
5712 GEN_SPEFPUOP_CONV(efsctsf
);
5713 GEN_SPEFPUOP_CONV(efsctuiz
);
5714 GEN_SPEFPUOP_CONV(efsctsiz
);
5715 GEN_SPEFPUOP_CONV(efscfd
);
5717 GEN_SPEOP_COMP(efscmpgt
);
5718 GEN_SPEOP_COMP(efscmplt
);
5719 GEN_SPEOP_COMP(efscmpeq
);
5720 GEN_SPEOP_COMP(efststgt
);
5721 GEN_SPEOP_COMP(efststlt
);
5722 GEN_SPEOP_COMP(efststeq
);
5724 /* Opcodes definitions */
5725 GEN_SPE(efsadd
, efssub
, 0x00, 0x0A, 0x00000000, PPC_SPEFPU
); //
5726 GEN_SPE(efsabs
, efsnabs
, 0x02, 0x0B, 0x0000F800, PPC_SPEFPU
); //
5727 GEN_SPE(efsneg
, speundef
, 0x03, 0x0B, 0x0000F800, PPC_SPEFPU
); //
5728 GEN_SPE(efsmul
, efsdiv
, 0x04, 0x0B, 0x00000000, PPC_SPEFPU
); //
5729 GEN_SPE(efscmpgt
, efscmplt
, 0x06, 0x0B, 0x00600000, PPC_SPEFPU
); //
5730 GEN_SPE(efscmpeq
, efscfd
, 0x07, 0x0B, 0x00600000, PPC_SPEFPU
); //
5731 GEN_SPE(efscfui
, efscfsi
, 0x08, 0x0B, 0x00180000, PPC_SPEFPU
); //
5732 GEN_SPE(efscfuf
, efscfsf
, 0x09, 0x0B, 0x00180000, PPC_SPEFPU
); //
5733 GEN_SPE(efsctui
, efsctsi
, 0x0A, 0x0B, 0x00180000, PPC_SPEFPU
); //
5734 GEN_SPE(efsctuf
, efsctsf
, 0x0B, 0x0B, 0x00180000, PPC_SPEFPU
); //
5735 GEN_SPE(efsctuiz
, efsctsiz
, 0x0C, 0x0B, 0x00180000, PPC_SPEFPU
); //
5736 GEN_SPE(efststgt
, efststlt
, 0x0E, 0x0B, 0x00600000, PPC_SPEFPU
); //
5737 GEN_SPE(efststeq
, speundef
, 0x0F, 0x0B, 0x00600000, PPC_SPEFPU
); //
5739 /* Double precision floating-point operations */
5741 GEN_SPEOP_ARITH2(efdadd
);
5742 GEN_SPEOP_ARITH2(efdsub
);
5743 GEN_SPEOP_ARITH2(efdmul
);
5744 GEN_SPEOP_ARITH2(efddiv
);
5745 GEN_SPEOP_ARITH1(efdabs
);
5746 GEN_SPEOP_ARITH1(efdnabs
);
5747 GEN_SPEOP_ARITH1(efdneg
);
5750 GEN_SPEFPUOP_CONV(efdcfui
);
5751 GEN_SPEFPUOP_CONV(efdcfsi
);
5752 GEN_SPEFPUOP_CONV(efdcfuf
);
5753 GEN_SPEFPUOP_CONV(efdcfsf
);
5754 GEN_SPEFPUOP_CONV(efdctui
);
5755 GEN_SPEFPUOP_CONV(efdctsi
);
5756 GEN_SPEFPUOP_CONV(efdctuf
);
5757 GEN_SPEFPUOP_CONV(efdctsf
);
5758 GEN_SPEFPUOP_CONV(efdctuiz
);
5759 GEN_SPEFPUOP_CONV(efdctsiz
);
5760 GEN_SPEFPUOP_CONV(efdcfs
);
5761 GEN_SPEFPUOP_CONV(efdcfuid
);
5762 GEN_SPEFPUOP_CONV(efdcfsid
);
5763 GEN_SPEFPUOP_CONV(efdctuidz
);
5764 GEN_SPEFPUOP_CONV(efdctsidz
);
5766 GEN_SPEOP_COMP(efdcmpgt
);
5767 GEN_SPEOP_COMP(efdcmplt
);
5768 GEN_SPEOP_COMP(efdcmpeq
);
5769 GEN_SPEOP_COMP(efdtstgt
);
5770 GEN_SPEOP_COMP(efdtstlt
);
5771 GEN_SPEOP_COMP(efdtsteq
);
5773 /* Opcodes definitions */
5774 GEN_SPE(efdadd
, efdsub
, 0x10, 0x0B, 0x00000000, PPC_SPEFPU
); //
5775 GEN_SPE(efdcfuid
, efdcfsid
, 0x11, 0x0B, 0x00180000, PPC_SPEFPU
); //
5776 GEN_SPE(efdabs
, efdnabs
, 0x12, 0x0B, 0x0000F800, PPC_SPEFPU
); //
5777 GEN_SPE(efdneg
, speundef
, 0x13, 0x0B, 0x0000F800, PPC_SPEFPU
); //
5778 GEN_SPE(efdmul
, efddiv
, 0x14, 0x0B, 0x00000000, PPC_SPEFPU
); //
5779 GEN_SPE(efdctuidz
, efdctsidz
, 0x15, 0x0B, 0x00180000, PPC_SPEFPU
); //
5780 GEN_SPE(efdcmpgt
, efdcmplt
, 0x16, 0x0B, 0x00600000, PPC_SPEFPU
); //
5781 GEN_SPE(efdcmpeq
, efdcfs
, 0x17, 0x0B, 0x00600000, PPC_SPEFPU
); //
5782 GEN_SPE(efdcfui
, efdcfsi
, 0x18, 0x0B, 0x00180000, PPC_SPEFPU
); //
5783 GEN_SPE(efdcfuf
, efdcfsf
, 0x19, 0x0B, 0x00180000, PPC_SPEFPU
); //
5784 GEN_SPE(efdctui
, efdctsi
, 0x1A, 0x0B, 0x00180000, PPC_SPEFPU
); //
5785 GEN_SPE(efdctuf
, efdctsf
, 0x1B, 0x0B, 0x00180000, PPC_SPEFPU
); //
5786 GEN_SPE(efdctuiz
, speundef
, 0x1C, 0x0B, 0x00180000, PPC_SPEFPU
); //
5787 GEN_SPE(efdctsiz
, speundef
, 0x1D, 0x0B, 0x00180000, PPC_SPEFPU
); //
5788 GEN_SPE(efdtstgt
, efdtstlt
, 0x1E, 0x0B, 0x00600000, PPC_SPEFPU
); //
5789 GEN_SPE(efdtsteq
, speundef
, 0x1F, 0x0B, 0x00600000, PPC_SPEFPU
); //
5792 /* End opcode list */
5793 GEN_OPCODE_MARK(end
);
5795 #include "translate_init.c"
5797 /*****************************************************************************/
5798 /* Misc PowerPC helpers */
5799 static inline uint32_t load_xer (CPUState
*env
)
5801 return (xer_so
<< XER_SO
) |
5802 (xer_ov
<< XER_OV
) |
5803 (xer_ca
<< XER_CA
) |
5804 (xer_bc
<< XER_BC
) |
5805 (xer_cmp
<< XER_CMP
);
5808 void cpu_dump_state (CPUState
*env
, FILE *f
,
5809 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...),
5812 #if defined(TARGET_PPC64) || 1
5824 cpu_fprintf(f
, "NIP " ADDRX
" LR " ADDRX
" CTR " ADDRX
"\n",
5825 env
->nip
, env
->lr
, env
->ctr
);
5826 cpu_fprintf(f
, "MSR " REGX FILL
" XER %08x "
5827 #if !defined(NO_TIMER_DUMP)
5829 #if !defined(CONFIG_USER_ONLY)
5834 do_load_msr(env
), load_xer(env
)
5835 #if !defined(NO_TIMER_DUMP)
5836 , cpu_ppc_load_tbu(env
), cpu_ppc_load_tbl(env
)
5837 #if !defined(CONFIG_USER_ONLY)
5838 , cpu_ppc_load_decr(env
)
5842 for (i
= 0; i
< 32; i
++) {
5843 if ((i
& (RGPL
- 1)) == 0)
5844 cpu_fprintf(f
, "GPR%02d", i
);
5845 cpu_fprintf(f
, " " REGX
, (target_ulong
)env
->gpr
[i
]);
5846 if ((i
& (RGPL
- 1)) == (RGPL
- 1))
5847 cpu_fprintf(f
, "\n");
5849 cpu_fprintf(f
, "CR ");
5850 for (i
= 0; i
< 8; i
++)
5851 cpu_fprintf(f
, "%01x", env
->crf
[i
]);
5852 cpu_fprintf(f
, " [");
5853 for (i
= 0; i
< 8; i
++) {
5855 if (env
->crf
[i
] & 0x08)
5857 else if (env
->crf
[i
] & 0x04)
5859 else if (env
->crf
[i
] & 0x02)
5861 cpu_fprintf(f
, " %c%c", a
, env
->crf
[i
] & 0x01 ? 'O' : ' ');
5863 cpu_fprintf(f
, " ] " FILL
"RES " REGX
"\n", env
->reserve
);
5864 for (i
= 0; i
< 32; i
++) {
5865 if ((i
& (RFPL
- 1)) == 0)
5866 cpu_fprintf(f
, "FPR%02d", i
);
5867 cpu_fprintf(f
, " %016" PRIx64
, *((uint64_t *)&env
->fpr
[i
]));
5868 if ((i
& (RFPL
- 1)) == (RFPL
- 1))
5869 cpu_fprintf(f
, "\n");
5871 cpu_fprintf(f
, "SRR0 " REGX
" SRR1 " REGX
" " FILL FILL FILL
5873 env
->spr
[SPR_SRR0
], env
->spr
[SPR_SRR1
], env
->sdr1
);
5880 void cpu_dump_statistics (CPUState
*env
, FILE*f
,
5881 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...),
5884 #if defined(DO_PPC_STATISTICS)
5885 opc_handler_t
**t1
, **t2
, **t3
, *handler
;
5889 for (op1
= 0; op1
< 64; op1
++) {
5891 if (is_indirect_opcode(handler
)) {
5892 t2
= ind_table(handler
);
5893 for (op2
= 0; op2
< 32; op2
++) {
5895 if (is_indirect_opcode(handler
)) {
5896 t3
= ind_table(handler
);
5897 for (op3
= 0; op3
< 32; op3
++) {
5899 if (handler
->count
== 0)
5901 cpu_fprintf(f
, "%02x %02x %02x (%02x %04d) %16s: "
5903 op1
, op2
, op3
, op1
, (op3
<< 5) | op2
,
5905 handler
->count
, handler
->count
);
5908 if (handler
->count
== 0)
5910 cpu_fprintf(f
, "%02x %02x (%02x %04d) %16s: "
5912 op1
, op2
, op1
, op2
, handler
->oname
,
5913 handler
->count
, handler
->count
);
5917 if (handler
->count
== 0)
5919 cpu_fprintf(f
, "%02x (%02x ) %16s: %016llx %lld\n",
5920 op1
, op1
, handler
->oname
,
5921 handler
->count
, handler
->count
);
5927 /*****************************************************************************/
5928 static inline int gen_intermediate_code_internal (CPUState
*env
,
5929 TranslationBlock
*tb
,
5932 DisasContext ctx
, *ctxp
= &ctx
;
5933 opc_handler_t
**table
, *handler
;
5934 target_ulong pc_start
;
5935 uint16_t *gen_opc_end
;
5939 gen_opc_ptr
= gen_opc_buf
;
5940 gen_opc_end
= gen_opc_buf
+ OPC_MAX_SIZE
;
5941 gen_opparam_ptr
= gen_opparam_buf
;
5945 ctx
.exception
= EXCP_NONE
;
5946 ctx
.spr_cb
= env
->spr_cb
;
5947 #if defined(CONFIG_USER_ONLY)
5948 ctx
.mem_idx
= msr_le
;
5949 #if defined(TARGET_PPC64)
5950 ctx
.mem_idx
|= msr_sf
<< 1;
5953 ctx
.supervisor
= 1 - msr_pr
;
5954 ctx
.mem_idx
= ((1 - msr_pr
) << 1) | msr_le
;
5955 #if defined(TARGET_PPC64)
5956 ctx
.mem_idx
|= msr_sf
<< 2;
5959 #if defined(TARGET_PPC64)
5960 ctx
.sf_mode
= msr_sf
;
5962 ctx
.fpu_enabled
= msr_fp
;
5963 #if defined(TARGET_PPCEMB)
5964 ctx
.spe_enabled
= msr_spe
;
5966 ctx
.singlestep_enabled
= env
->singlestep_enabled
;
5967 #if defined (DO_SINGLE_STEP) && 0
5968 /* Single step trace mode */
5971 /* Set env in case of segfault during code fetch */
5972 while (ctx
.exception
== EXCP_NONE
&& gen_opc_ptr
< gen_opc_end
) {
5973 if (unlikely(env
->nb_breakpoints
> 0)) {
5974 for (j
= 0; j
< env
->nb_breakpoints
; j
++) {
5975 if (env
->breakpoints
[j
] == ctx
.nip
) {
5976 gen_update_nip(&ctx
, ctx
.nip
);
5982 if (unlikely(search_pc
)) {
5983 j
= gen_opc_ptr
- gen_opc_buf
;
5987 gen_opc_instr_start
[lj
++] = 0;
5988 gen_opc_pc
[lj
] = ctx
.nip
;
5989 gen_opc_instr_start
[lj
] = 1;
5992 #if defined PPC_DEBUG_DISAS
5993 if (loglevel
& CPU_LOG_TB_IN_ASM
) {
5994 fprintf(logfile
, "----------------\n");
5995 fprintf(logfile
, "nip=" ADDRX
" super=%d ir=%d\n",
5996 ctx
.nip
, 1 - msr_pr
, msr_ir
);
5999 ctx
.opcode
= ldl_code(ctx
.nip
);
6001 ctx
.opcode
= ((ctx
.opcode
& 0xFF000000) >> 24) |
6002 ((ctx
.opcode
& 0x00FF0000) >> 8) |
6003 ((ctx
.opcode
& 0x0000FF00) << 8) |
6004 ((ctx
.opcode
& 0x000000FF) << 24);
6006 #if defined PPC_DEBUG_DISAS
6007 if (loglevel
& CPU_LOG_TB_IN_ASM
) {
6008 fprintf(logfile
, "translate opcode %08x (%02x %02x %02x) (%s)\n",
6009 ctx
.opcode
, opc1(ctx
.opcode
), opc2(ctx
.opcode
),
6010 opc3(ctx
.opcode
), msr_le
? "little" : "big");
6014 table
= env
->opcodes
;
6015 handler
= table
[opc1(ctx
.opcode
)];
6016 if (is_indirect_opcode(handler
)) {
6017 table
= ind_table(handler
);
6018 handler
= table
[opc2(ctx
.opcode
)];
6019 if (is_indirect_opcode(handler
)) {
6020 table
= ind_table(handler
);
6021 handler
= table
[opc3(ctx
.opcode
)];
6024 /* Is opcode *REALLY* valid ? */
6025 if (unlikely(handler
->handler
== &gen_invalid
)) {
6026 if (loglevel
!= 0) {
6027 fprintf(logfile
, "invalid/unsupported opcode: "
6028 "%02x - %02x - %02x (%08x) 0x" ADDRX
" %d\n",
6029 opc1(ctx
.opcode
), opc2(ctx
.opcode
),
6030 opc3(ctx
.opcode
), ctx
.opcode
, ctx
.nip
- 4, msr_ir
);
6032 printf("invalid/unsupported opcode: "
6033 "%02x - %02x - %02x (%08x) 0x" ADDRX
" %d\n",
6034 opc1(ctx
.opcode
), opc2(ctx
.opcode
),
6035 opc3(ctx
.opcode
), ctx
.opcode
, ctx
.nip
- 4, msr_ir
);
6038 if (unlikely((ctx
.opcode
& handler
->inval
) != 0)) {
6039 if (loglevel
!= 0) {
6040 fprintf(logfile
, "invalid bits: %08x for opcode: "
6041 "%02x -%02x - %02x (%08x) 0x" ADDRX
"\n",
6042 ctx
.opcode
& handler
->inval
, opc1(ctx
.opcode
),
6043 opc2(ctx
.opcode
), opc3(ctx
.opcode
),
6044 ctx
.opcode
, ctx
.nip
- 4);
6046 printf("invalid bits: %08x for opcode: "
6047 "%02x -%02x - %02x (%08x) 0x" ADDRX
"\n",
6048 ctx
.opcode
& handler
->inval
, opc1(ctx
.opcode
),
6049 opc2(ctx
.opcode
), opc3(ctx
.opcode
),
6050 ctx
.opcode
, ctx
.nip
- 4);
6056 (*(handler
->handler
))(&ctx
);
6057 #if defined(DO_PPC_STATISTICS)
6060 /* Check trace mode exceptions */
6061 #if 0 // XXX: buggy on embedded PowerPC
6062 if (unlikely((msr_be
&& ctx
.exception
== EXCP_BRANCH
) ||
6063 /* Check in single step trace mode
6064 * we need to stop except if:
6065 * - rfi, trap or syscall
6066 * - first instruction of an exception handler
6068 (msr_se
&& (ctx
.nip
< 0x100 ||
6070 (ctx
.nip
& 0xFC) != 0x04) &&
6071 ctx
.exception
!= EXCP_SYSCALL
&&
6072 ctx
.exception
!= EXCP_SYSCALL_USER
&&
6073 ctx
.exception
!= EXCP_TRAP
))) {
6074 RET_EXCP(ctxp
, EXCP_TRACE
, 0);
6077 /* if we reach a page boundary or are single stepping, stop
6080 if (unlikely(((ctx
.nip
& (TARGET_PAGE_SIZE
- 1)) == 0) ||
6081 (env
->singlestep_enabled
))) {
6084 #if defined (DO_SINGLE_STEP)
6088 if (ctx
.exception
== EXCP_NONE
) {
6089 gen_goto_tb(&ctx
, 0, ctx
.nip
);
6090 } else if (ctx
.exception
!= EXCP_BRANCH
) {
6092 /* Generate the return instruction */
6095 *gen_opc_ptr
= INDEX_op_end
;
6096 if (unlikely(search_pc
)) {
6097 j
= gen_opc_ptr
- gen_opc_buf
;
6100 gen_opc_instr_start
[lj
++] = 0;
6102 tb
->size
= ctx
.nip
- pc_start
;
6104 #if defined(DEBUG_DISAS)
6105 if (loglevel
& CPU_LOG_TB_CPU
) {
6106 fprintf(logfile
, "---------------- excp: %04x\n", ctx
.exception
);
6107 cpu_dump_state(env
, logfile
, fprintf
, 0);
6109 if (loglevel
& CPU_LOG_TB_IN_ASM
) {
6111 flags
= env
->bfd_mach
;
6112 flags
|= msr_le
<< 16;
6113 fprintf(logfile
, "IN: %s\n", lookup_symbol(pc_start
));
6114 target_disas(logfile
, pc_start
, ctx
.nip
- pc_start
, flags
);
6115 fprintf(logfile
, "\n");
6117 if (loglevel
& CPU_LOG_TB_OP
) {
6118 fprintf(logfile
, "OP:\n");
6119 dump_ops(gen_opc_buf
, gen_opparam_buf
);
6120 fprintf(logfile
, "\n");
6126 int gen_intermediate_code (CPUState
*env
, struct TranslationBlock
*tb
)
6128 return gen_intermediate_code_internal(env
, tb
, 0);
6131 int gen_intermediate_code_pc (CPUState
*env
, struct TranslationBlock
*tb
)
6133 return gen_intermediate_code_internal(env
, tb
, 1);