Less debug noise from the mipsnet driver.
[qemu/qemu_0_9_1_stable.git] / target-ppc / translate.c
blobc3e5340f207d44ef7203788a6d324f07a591554e
1 /*
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
20 #include <stdarg.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <inttypes.h>
26 #include "cpu.h"
27 #include "exec-all.h"
28 #include "disas.h"
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
35 //#define OPTIMIZE_FPRF_UPDATE
37 /*****************************************************************************/
38 /* Code translation helpers */
39 #if defined(USE_DIRECT_JUMP)
40 #define TBPARAM(x)
41 #else
42 #define TBPARAM(x) (long)(x)
43 #endif
45 enum {
46 #define DEF(s, n, copy_size) INDEX_op_ ## s,
47 #include "opc.h"
48 #undef DEF
49 NB_OPS,
52 static uint16_t *gen_opc_ptr;
53 static uint32_t *gen_opparam_ptr;
54 #if defined(OPTIMIZE_FPRF_UPDATE)
55 static uint16_t *gen_fprf_buf[OPC_BUF_SIZE];
56 static uint16_t **gen_fprf_ptr;
57 #endif
59 #include "gen-op.h"
61 static always_inline void gen_set_T0 (target_ulong val)
63 #if defined(TARGET_PPC64)
64 if (val >> 32)
65 gen_op_set_T0_64(val >> 32, val);
66 else
67 #endif
68 gen_op_set_T0(val);
71 static always_inline void gen_set_T1 (target_ulong val)
73 #if defined(TARGET_PPC64)
74 if (val >> 32)
75 gen_op_set_T1_64(val >> 32, val);
76 else
77 #endif
78 gen_op_set_T1(val);
81 #define GEN8(func, NAME) \
82 static GenOpFunc *NAME ## _table [8] = { \
83 NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
84 NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
85 }; \
86 static always_inline void func (int n) \
87 { \
88 NAME ## _table[n](); \
91 #define GEN16(func, NAME) \
92 static GenOpFunc *NAME ## _table [16] = { \
93 NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
94 NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
95 NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
96 NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
97 }; \
98 static always_inline void func (int n) \
99 { \
100 NAME ## _table[n](); \
103 #define GEN32(func, NAME) \
104 static GenOpFunc *NAME ## _table [32] = { \
105 NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
106 NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
107 NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
108 NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
109 NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \
110 NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \
111 NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \
112 NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \
113 }; \
114 static always_inline void func (int n) \
116 NAME ## _table[n](); \
119 /* Condition register moves */
120 GEN8(gen_op_load_crf_T0, gen_op_load_crf_T0_crf);
121 GEN8(gen_op_load_crf_T1, gen_op_load_crf_T1_crf);
122 GEN8(gen_op_store_T0_crf, gen_op_store_T0_crf_crf);
123 GEN8(gen_op_store_T1_crf, gen_op_store_T1_crf_crf);
125 /* General purpose registers moves */
126 GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr);
127 GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr);
128 GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr);
130 GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr);
131 GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr);
132 #if 0 // unused
133 GEN32(gen_op_store_T2_gpr, gen_op_store_T2_gpr_gpr);
134 #endif
136 /* floating point registers moves */
137 GEN32(gen_op_load_fpr_FT0, gen_op_load_fpr_FT0_fpr);
138 GEN32(gen_op_load_fpr_FT1, gen_op_load_fpr_FT1_fpr);
139 GEN32(gen_op_load_fpr_FT2, gen_op_load_fpr_FT2_fpr);
140 GEN32(gen_op_store_FT0_fpr, gen_op_store_FT0_fpr_fpr);
141 GEN32(gen_op_store_FT1_fpr, gen_op_store_FT1_fpr_fpr);
142 #if 0 // unused
143 GEN32(gen_op_store_FT2_fpr, gen_op_store_FT2_fpr_fpr);
144 #endif
146 /* internal defines */
147 typedef struct DisasContext {
148 struct TranslationBlock *tb;
149 target_ulong nip;
150 uint32_t opcode;
151 uint32_t exception;
152 /* Routine used to access memory */
153 int mem_idx;
154 /* Translation flags */
155 #if !defined(CONFIG_USER_ONLY)
156 int supervisor;
157 #endif
158 #if defined(TARGET_PPC64)
159 int sf_mode;
160 #endif
161 int fpu_enabled;
162 int altivec_enabled;
163 #if defined(TARGET_PPCEMB)
164 int spe_enabled;
165 #endif
166 ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */
167 int singlestep_enabled;
168 int dcache_line_size;
169 } DisasContext;
171 struct opc_handler_t {
172 /* invalid bits */
173 uint32_t inval;
174 /* instruction type */
175 uint64_t type;
176 /* handler */
177 void (*handler)(DisasContext *ctx);
178 #if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
179 const unsigned char *oname;
180 #endif
181 #if defined(DO_PPC_STATISTICS)
182 uint64_t count;
183 #endif
186 static always_inline void gen_set_Rc0 (DisasContext *ctx)
188 #if defined(TARGET_PPC64)
189 if (ctx->sf_mode)
190 gen_op_cmpi_64(0);
191 else
192 #endif
193 gen_op_cmpi(0);
194 gen_op_set_Rc0();
197 static always_inline void gen_reset_fpstatus (void)
199 #ifdef CONFIG_SOFTFLOAT
200 gen_op_reset_fpstatus();
201 #endif
204 static always_inline void gen_compute_fprf (int set_fprf, int set_rc)
206 if (set_fprf != 0) {
207 /* This case might be optimized later */
208 #if defined(OPTIMIZE_FPRF_UPDATE)
209 *gen_fprf_ptr++ = gen_opc_ptr;
210 #endif
211 gen_op_compute_fprf(1);
212 if (unlikely(set_rc))
213 gen_op_store_T0_crf(1);
214 gen_op_float_check_status();
215 } else if (unlikely(set_rc)) {
216 /* We always need to compute fpcc */
217 gen_op_compute_fprf(0);
218 gen_op_store_T0_crf(1);
219 if (set_fprf)
220 gen_op_float_check_status();
224 static always_inline void gen_optimize_fprf (void)
226 #if defined(OPTIMIZE_FPRF_UPDATE)
227 uint16_t **ptr;
229 for (ptr = gen_fprf_buf; ptr != (gen_fprf_ptr - 1); ptr++)
230 *ptr = INDEX_op_nop1;
231 gen_fprf_ptr = gen_fprf_buf;
232 #endif
235 static always_inline void gen_update_nip (DisasContext *ctx, target_ulong nip)
237 #if defined(TARGET_PPC64)
238 if (ctx->sf_mode)
239 gen_op_update_nip_64(nip >> 32, nip);
240 else
241 #endif
242 gen_op_update_nip(nip);
245 #define GEN_EXCP(ctx, excp, error) \
246 do { \
247 if ((ctx)->exception == POWERPC_EXCP_NONE) { \
248 gen_update_nip(ctx, (ctx)->nip); \
250 gen_op_raise_exception_err((excp), (error)); \
251 ctx->exception = (excp); \
252 } while (0)
254 #define GEN_EXCP_INVAL(ctx) \
255 GEN_EXCP((ctx), POWERPC_EXCP_PROGRAM, \
256 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL)
258 #define GEN_EXCP_PRIVOPC(ctx) \
259 GEN_EXCP((ctx), POWERPC_EXCP_PROGRAM, \
260 POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_OPC)
262 #define GEN_EXCP_PRIVREG(ctx) \
263 GEN_EXCP((ctx), POWERPC_EXCP_PROGRAM, \
264 POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG)
266 #define GEN_EXCP_NO_FP(ctx) \
267 GEN_EXCP(ctx, POWERPC_EXCP_FPU, 0)
269 #define GEN_EXCP_NO_AP(ctx) \
270 GEN_EXCP(ctx, POWERPC_EXCP_APU, 0)
272 #define GEN_EXCP_NO_VR(ctx) \
273 GEN_EXCP(ctx, POWERPC_EXCP_VPU, 0)
275 /* Stop translation */
276 static always_inline void GEN_STOP (DisasContext *ctx)
278 gen_update_nip(ctx, ctx->nip);
279 ctx->exception = POWERPC_EXCP_STOP;
282 /* No need to update nip here, as execution flow will change */
283 static always_inline void GEN_SYNC (DisasContext *ctx)
285 ctx->exception = POWERPC_EXCP_SYNC;
288 #define GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
289 static void gen_##name (DisasContext *ctx); \
290 GEN_OPCODE(name, opc1, opc2, opc3, inval, type); \
291 static void gen_##name (DisasContext *ctx)
293 #define GEN_HANDLER2(name, onam, opc1, opc2, opc3, inval, type) \
294 static void gen_##name (DisasContext *ctx); \
295 GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type); \
296 static void gen_##name (DisasContext *ctx)
298 typedef struct opcode_t {
299 unsigned char opc1, opc2, opc3;
300 #if HOST_LONG_BITS == 64 /* Explicitely align to 64 bits */
301 unsigned char pad[5];
302 #else
303 unsigned char pad[1];
304 #endif
305 opc_handler_t handler;
306 const unsigned char *oname;
307 } opcode_t;
309 /*****************************************************************************/
310 /*** Instruction decoding ***/
311 #define EXTRACT_HELPER(name, shift, nb) \
312 static always_inline uint32_t name (uint32_t opcode) \
314 return (opcode >> (shift)) & ((1 << (nb)) - 1); \
317 #define EXTRACT_SHELPER(name, shift, nb) \
318 static always_inline int32_t name (uint32_t opcode) \
320 return (int16_t)((opcode >> (shift)) & ((1 << (nb)) - 1)); \
323 /* Opcode part 1 */
324 EXTRACT_HELPER(opc1, 26, 6);
325 /* Opcode part 2 */
326 EXTRACT_HELPER(opc2, 1, 5);
327 /* Opcode part 3 */
328 EXTRACT_HELPER(opc3, 6, 5);
329 /* Update Cr0 flags */
330 EXTRACT_HELPER(Rc, 0, 1);
331 /* Destination */
332 EXTRACT_HELPER(rD, 21, 5);
333 /* Source */
334 EXTRACT_HELPER(rS, 21, 5);
335 /* First operand */
336 EXTRACT_HELPER(rA, 16, 5);
337 /* Second operand */
338 EXTRACT_HELPER(rB, 11, 5);
339 /* Third operand */
340 EXTRACT_HELPER(rC, 6, 5);
341 /*** Get CRn ***/
342 EXTRACT_HELPER(crfD, 23, 3);
343 EXTRACT_HELPER(crfS, 18, 3);
344 EXTRACT_HELPER(crbD, 21, 5);
345 EXTRACT_HELPER(crbA, 16, 5);
346 EXTRACT_HELPER(crbB, 11, 5);
347 /* SPR / TBL */
348 EXTRACT_HELPER(_SPR, 11, 10);
349 static always_inline uint32_t SPR (uint32_t opcode)
351 uint32_t sprn = _SPR(opcode);
353 return ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
355 /*** Get constants ***/
356 EXTRACT_HELPER(IMM, 12, 8);
357 /* 16 bits signed immediate value */
358 EXTRACT_SHELPER(SIMM, 0, 16);
359 /* 16 bits unsigned immediate value */
360 EXTRACT_HELPER(UIMM, 0, 16);
361 /* Bit count */
362 EXTRACT_HELPER(NB, 11, 5);
363 /* Shift count */
364 EXTRACT_HELPER(SH, 11, 5);
365 /* Mask start */
366 EXTRACT_HELPER(MB, 6, 5);
367 /* Mask end */
368 EXTRACT_HELPER(ME, 1, 5);
369 /* Trap operand */
370 EXTRACT_HELPER(TO, 21, 5);
372 EXTRACT_HELPER(CRM, 12, 8);
373 EXTRACT_HELPER(FM, 17, 8);
374 EXTRACT_HELPER(SR, 16, 4);
375 EXTRACT_HELPER(FPIMM, 20, 4);
377 /*** Jump target decoding ***/
378 /* Displacement */
379 EXTRACT_SHELPER(d, 0, 16);
380 /* Immediate address */
381 static always_inline target_ulong LI (uint32_t opcode)
383 return (opcode >> 0) & 0x03FFFFFC;
386 static always_inline uint32_t BD (uint32_t opcode)
388 return (opcode >> 0) & 0xFFFC;
391 EXTRACT_HELPER(BO, 21, 5);
392 EXTRACT_HELPER(BI, 16, 5);
393 /* Absolute/relative address */
394 EXTRACT_HELPER(AA, 1, 1);
395 /* Link */
396 EXTRACT_HELPER(LK, 0, 1);
398 /* Create a mask between <start> and <end> bits */
399 static always_inline target_ulong MASK (uint32_t start, uint32_t end)
401 target_ulong ret;
403 #if defined(TARGET_PPC64)
404 if (likely(start == 0)) {
405 ret = (uint64_t)(-1ULL) << (63 - end);
406 } else if (likely(end == 63)) {
407 ret = (uint64_t)(-1ULL) >> start;
409 #else
410 if (likely(start == 0)) {
411 ret = (uint32_t)(-1ULL) << (31 - end);
412 } else if (likely(end == 31)) {
413 ret = (uint32_t)(-1ULL) >> start;
415 #endif
416 else {
417 ret = (((target_ulong)(-1ULL)) >> (start)) ^
418 (((target_ulong)(-1ULL) >> (end)) >> 1);
419 if (unlikely(start > end))
420 return ~ret;
423 return ret;
426 /*****************************************************************************/
427 /* PowerPC Instructions types definitions */
428 enum {
429 PPC_NONE = 0x0000000000000000ULL,
430 /* PowerPC base instructions set */
431 PPC_INSNS_BASE = 0x0000000000000001ULL,
432 /* integer operations instructions */
433 #define PPC_INTEGER PPC_INSNS_BASE
434 /* flow control instructions */
435 #define PPC_FLOW PPC_INSNS_BASE
436 /* virtual memory instructions */
437 #define PPC_MEM PPC_INSNS_BASE
438 /* ld/st with reservation instructions */
439 #define PPC_RES PPC_INSNS_BASE
440 /* cache control instructions */
441 #define PPC_CACHE PPC_INSNS_BASE
442 /* spr/msr access instructions */
443 #define PPC_MISC PPC_INSNS_BASE
444 /* Optional floating point instructions */
445 PPC_FLOAT = 0x0000000000000002ULL,
446 PPC_FLOAT_FSQRT = 0x0000000000000004ULL,
447 PPC_FLOAT_FRES = 0x0000000000000008ULL,
448 PPC_FLOAT_FRSQRTE = 0x0000000000000010ULL,
449 PPC_FLOAT_FSEL = 0x0000000000000020ULL,
450 PPC_FLOAT_STFIWX = 0x0000000000000040ULL,
451 /* external control instructions */
452 PPC_EXTERN = 0x0000000000000080ULL,
453 /* segment register access instructions */
454 PPC_SEGMENT = 0x0000000000000100ULL,
455 /* Optional cache control instruction */
456 PPC_CACHE_DCBA = 0x0000000000000200ULL,
457 /* Optional memory control instructions */
458 PPC_MEM_TLBIA = 0x0000000000000400ULL,
459 PPC_MEM_TLBIE = 0x0000000000000800ULL,
460 PPC_MEM_TLBSYNC = 0x0000000000001000ULL,
461 /* eieio & sync */
462 PPC_MEM_SYNC = 0x0000000000002000ULL,
463 /* PowerPC 6xx TLB management instructions */
464 PPC_6xx_TLB = 0x0000000000004000ULL,
465 /* Altivec support */
466 PPC_ALTIVEC = 0x0000000000008000ULL,
467 /* Time base mftb instruction */
468 PPC_MFTB = 0x0000000000010000ULL,
469 /* Embedded PowerPC dedicated instructions */
470 PPC_EMB_COMMON = 0x0000000000020000ULL,
471 /* PowerPC 40x exception model */
472 PPC_40x_EXCP = 0x0000000000040000ULL,
473 /* PowerPC 40x TLB management instructions */
474 PPC_40x_TLB = 0x0000000000080000ULL,
475 /* PowerPC 405 Mac instructions */
476 PPC_405_MAC = 0x0000000000100000ULL,
477 /* PowerPC 440 specific instructions */
478 PPC_440_SPEC = 0x0000000000200000ULL,
479 /* Power-to-PowerPC bridge (601) */
480 PPC_POWER_BR = 0x0000000000400000ULL,
481 /* PowerPC 602 specific */
482 PPC_602_SPEC = 0x0000000000800000ULL,
483 /* Deprecated instructions */
484 /* Original POWER instruction set */
485 PPC_POWER = 0x0000000001000000ULL,
486 /* POWER2 instruction set extension */
487 PPC_POWER2 = 0x0000000002000000ULL,
488 /* Power RTC support */
489 PPC_POWER_RTC = 0x0000000004000000ULL,
490 /* 64 bits PowerPC instruction set */
491 PPC_64B = 0x0000000008000000ULL,
492 /* 64 bits hypervisor extensions */
493 PPC_64H = 0x0000000010000000ULL,
494 /* segment register access instructions for PowerPC 64 "bridge" */
495 PPC_SEGMENT_64B = 0x0000000020000000ULL,
496 /* BookE (embedded) PowerPC specification */
497 PPC_BOOKE = 0x0000000040000000ULL,
498 /* eieio */
499 PPC_MEM_EIEIO = 0x0000000080000000ULL,
500 /* e500 vector instructions */
501 PPC_E500_VECTOR = 0x0000000100000000ULL,
502 /* PowerPC 4xx dedicated instructions */
503 PPC_4xx_COMMON = 0x0000000200000000ULL,
504 /* PowerPC 2.03 specification extensions */
505 PPC_203 = 0x0000000400000000ULL,
506 /* PowerPC 2.03 SPE extension */
507 PPC_SPE = 0x0000000800000000ULL,
508 /* PowerPC 2.03 SPE floating-point extension */
509 PPC_SPEFPU = 0x0000001000000000ULL,
510 /* SLB management */
511 PPC_SLBI = 0x0000002000000000ULL,
512 /* PowerPC 40x ibct instructions */
513 PPC_40x_ICBT = 0x0000004000000000ULL,
514 /* PowerPC 74xx TLB management instructions */
515 PPC_74xx_TLB = 0x0000008000000000ULL,
516 /* More BookE (embedded) instructions... */
517 PPC_BOOKE_EXT = 0x0000010000000000ULL,
518 /* rfmci is not implemented in all BookE PowerPC */
519 PPC_RFMCI = 0x0000020000000000ULL,
520 /* user-mode DCR access, implemented in PowerPC 460 */
521 PPC_DCRUX = 0x0000040000000000ULL,
522 /* New floating-point extensions (PowerPC 2.0x) */
523 PPC_FLOAT_EXT = 0x0000080000000000ULL,
524 /* New wait instruction (PowerPC 2.0x) */
525 PPC_WAIT = 0x0000100000000000ULL,
526 /* New 64 bits extensions (PowerPC 2.0x) */
527 PPC_64BX = 0x0000200000000000ULL,
528 /* dcbz instruction with fixed cache line size */
529 PPC_CACHE_DCBZ = 0x0000400000000000ULL,
530 /* dcbz instruction with tunable cache line size */
531 PPC_CACHE_DCBZT = 0x0000800000000000ULL,
532 /* frsqrtes extension */
533 PPC_FLOAT_FRSQRTES = 0x0001000000000000ULL,
536 /*****************************************************************************/
537 /* PowerPC instructions table */
538 #if HOST_LONG_BITS == 64
539 #define OPC_ALIGN 8
540 #else
541 #define OPC_ALIGN 4
542 #endif
543 #if defined(__APPLE__)
544 #define OPCODES_SECTION \
545 __attribute__ ((section("__TEXT,__opcodes"), unused, aligned (OPC_ALIGN) ))
546 #else
547 #define OPCODES_SECTION \
548 __attribute__ ((section(".opcodes"), unused, aligned (OPC_ALIGN) ))
549 #endif
551 #if defined(DO_PPC_STATISTICS)
552 #define GEN_OPCODE(name, op1, op2, op3, invl, _typ) \
553 OPCODES_SECTION opcode_t opc_##name = { \
554 .opc1 = op1, \
555 .opc2 = op2, \
556 .opc3 = op3, \
557 .pad = { 0, }, \
558 .handler = { \
559 .inval = invl, \
560 .type = _typ, \
561 .handler = &gen_##name, \
562 .oname = stringify(name), \
563 }, \
564 .oname = stringify(name), \
566 #define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ) \
567 OPCODES_SECTION opcode_t opc_##name = { \
568 .opc1 = op1, \
569 .opc2 = op2, \
570 .opc3 = op3, \
571 .pad = { 0, }, \
572 .handler = { \
573 .inval = invl, \
574 .type = _typ, \
575 .handler = &gen_##name, \
576 .oname = onam, \
577 }, \
578 .oname = onam, \
580 #else
581 #define GEN_OPCODE(name, op1, op2, op3, invl, _typ) \
582 OPCODES_SECTION opcode_t opc_##name = { \
583 .opc1 = op1, \
584 .opc2 = op2, \
585 .opc3 = op3, \
586 .pad = { 0, }, \
587 .handler = { \
588 .inval = invl, \
589 .type = _typ, \
590 .handler = &gen_##name, \
591 }, \
592 .oname = stringify(name), \
594 #define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ) \
595 OPCODES_SECTION opcode_t opc_##name = { \
596 .opc1 = op1, \
597 .opc2 = op2, \
598 .opc3 = op3, \
599 .pad = { 0, }, \
600 .handler = { \
601 .inval = invl, \
602 .type = _typ, \
603 .handler = &gen_##name, \
604 }, \
605 .oname = onam, \
607 #endif
609 #define GEN_OPCODE_MARK(name) \
610 OPCODES_SECTION opcode_t opc_##name = { \
611 .opc1 = 0xFF, \
612 .opc2 = 0xFF, \
613 .opc3 = 0xFF, \
614 .pad = { 0, }, \
615 .handler = { \
616 .inval = 0x00000000, \
617 .type = 0x00, \
618 .handler = NULL, \
619 }, \
620 .oname = stringify(name), \
623 /* Start opcode list */
624 GEN_OPCODE_MARK(start);
626 /* Invalid instruction */
627 GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE)
629 GEN_EXCP_INVAL(ctx);
632 static opc_handler_t invalid_handler = {
633 .inval = 0xFFFFFFFF,
634 .type = PPC_NONE,
635 .handler = gen_invalid,
638 /*** Integer arithmetic ***/
639 #define __GEN_INT_ARITH2(name, opc1, opc2, opc3, inval, type) \
640 GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
642 gen_op_load_gpr_T0(rA(ctx->opcode)); \
643 gen_op_load_gpr_T1(rB(ctx->opcode)); \
644 gen_op_##name(); \
645 gen_op_store_T0_gpr(rD(ctx->opcode)); \
646 if (unlikely(Rc(ctx->opcode) != 0)) \
647 gen_set_Rc0(ctx); \
650 #define __GEN_INT_ARITH2_O(name, opc1, opc2, opc3, inval, type) \
651 GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
653 gen_op_load_gpr_T0(rA(ctx->opcode)); \
654 gen_op_load_gpr_T1(rB(ctx->opcode)); \
655 gen_op_##name(); \
656 gen_op_store_T0_gpr(rD(ctx->opcode)); \
657 if (unlikely(Rc(ctx->opcode) != 0)) \
658 gen_set_Rc0(ctx); \
661 #define __GEN_INT_ARITH1(name, opc1, opc2, opc3, type) \
662 GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, type) \
664 gen_op_load_gpr_T0(rA(ctx->opcode)); \
665 gen_op_##name(); \
666 gen_op_store_T0_gpr(rD(ctx->opcode)); \
667 if (unlikely(Rc(ctx->opcode) != 0)) \
668 gen_set_Rc0(ctx); \
670 #define __GEN_INT_ARITH1_O(name, opc1, opc2, opc3, type) \
671 GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, type) \
673 gen_op_load_gpr_T0(rA(ctx->opcode)); \
674 gen_op_##name(); \
675 gen_op_store_T0_gpr(rD(ctx->opcode)); \
676 if (unlikely(Rc(ctx->opcode) != 0)) \
677 gen_set_Rc0(ctx); \
680 /* Two operands arithmetic functions */
681 #define GEN_INT_ARITH2(name, opc1, opc2, opc3, type) \
682 __GEN_INT_ARITH2(name, opc1, opc2, opc3, 0x00000000, type) \
683 __GEN_INT_ARITH2_O(name##o, opc1, opc2, opc3 | 0x10, 0x00000000, type)
685 /* Two operands arithmetic functions with no overflow allowed */
686 #define GEN_INT_ARITHN(name, opc1, opc2, opc3, type) \
687 __GEN_INT_ARITH2(name, opc1, opc2, opc3, 0x00000400, type)
689 /* One operand arithmetic functions */
690 #define GEN_INT_ARITH1(name, opc1, opc2, opc3, type) \
691 __GEN_INT_ARITH1(name, opc1, opc2, opc3, type) \
692 __GEN_INT_ARITH1_O(name##o, opc1, opc2, opc3 | 0x10, type)
694 #if defined(TARGET_PPC64)
695 #define __GEN_INT_ARITH2_64(name, opc1, opc2, opc3, inval, type) \
696 GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
698 gen_op_load_gpr_T0(rA(ctx->opcode)); \
699 gen_op_load_gpr_T1(rB(ctx->opcode)); \
700 if (ctx->sf_mode) \
701 gen_op_##name##_64(); \
702 else \
703 gen_op_##name(); \
704 gen_op_store_T0_gpr(rD(ctx->opcode)); \
705 if (unlikely(Rc(ctx->opcode) != 0)) \
706 gen_set_Rc0(ctx); \
709 #define __GEN_INT_ARITH2_O_64(name, opc1, opc2, opc3, inval, type) \
710 GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
712 gen_op_load_gpr_T0(rA(ctx->opcode)); \
713 gen_op_load_gpr_T1(rB(ctx->opcode)); \
714 if (ctx->sf_mode) \
715 gen_op_##name##_64(); \
716 else \
717 gen_op_##name(); \
718 gen_op_store_T0_gpr(rD(ctx->opcode)); \
719 if (unlikely(Rc(ctx->opcode) != 0)) \
720 gen_set_Rc0(ctx); \
723 #define __GEN_INT_ARITH1_64(name, opc1, opc2, opc3, type) \
724 GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, type) \
726 gen_op_load_gpr_T0(rA(ctx->opcode)); \
727 if (ctx->sf_mode) \
728 gen_op_##name##_64(); \
729 else \
730 gen_op_##name(); \
731 gen_op_store_T0_gpr(rD(ctx->opcode)); \
732 if (unlikely(Rc(ctx->opcode) != 0)) \
733 gen_set_Rc0(ctx); \
735 #define __GEN_INT_ARITH1_O_64(name, opc1, opc2, opc3, type) \
736 GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, type) \
738 gen_op_load_gpr_T0(rA(ctx->opcode)); \
739 if (ctx->sf_mode) \
740 gen_op_##name##_64(); \
741 else \
742 gen_op_##name(); \
743 gen_op_store_T0_gpr(rD(ctx->opcode)); \
744 if (unlikely(Rc(ctx->opcode) != 0)) \
745 gen_set_Rc0(ctx); \
748 /* Two operands arithmetic functions */
749 #define GEN_INT_ARITH2_64(name, opc1, opc2, opc3, type) \
750 __GEN_INT_ARITH2_64(name, opc1, opc2, opc3, 0x00000000, type) \
751 __GEN_INT_ARITH2_O_64(name##o, opc1, opc2, opc3 | 0x10, 0x00000000, type)
753 /* Two operands arithmetic functions with no overflow allowed */
754 #define GEN_INT_ARITHN_64(name, opc1, opc2, opc3, type) \
755 __GEN_INT_ARITH2_64(name, opc1, opc2, opc3, 0x00000400, type)
757 /* One operand arithmetic functions */
758 #define GEN_INT_ARITH1_64(name, opc1, opc2, opc3, type) \
759 __GEN_INT_ARITH1_64(name, opc1, opc2, opc3, type) \
760 __GEN_INT_ARITH1_O_64(name##o, opc1, opc2, opc3 | 0x10, type)
761 #else
762 #define GEN_INT_ARITH2_64 GEN_INT_ARITH2
763 #define GEN_INT_ARITHN_64 GEN_INT_ARITHN
764 #define GEN_INT_ARITH1_64 GEN_INT_ARITH1
765 #endif
767 /* add add. addo addo. */
768 static always_inline void gen_op_addo (void)
770 gen_op_move_T2_T0();
771 gen_op_add();
772 gen_op_check_addo();
774 #if defined(TARGET_PPC64)
775 #define gen_op_add_64 gen_op_add
776 static always_inline void gen_op_addo_64 (void)
778 gen_op_move_T2_T0();
779 gen_op_add();
780 gen_op_check_addo_64();
782 #endif
783 GEN_INT_ARITH2_64 (add, 0x1F, 0x0A, 0x08, PPC_INTEGER);
784 /* addc addc. addco addco. */
785 static always_inline void gen_op_addc (void)
787 gen_op_move_T2_T0();
788 gen_op_add();
789 gen_op_check_addc();
791 static always_inline void gen_op_addco (void)
793 gen_op_move_T2_T0();
794 gen_op_add();
795 gen_op_check_addc();
796 gen_op_check_addo();
798 #if defined(TARGET_PPC64)
799 static always_inline void gen_op_addc_64 (void)
801 gen_op_move_T2_T0();
802 gen_op_add();
803 gen_op_check_addc_64();
805 static always_inline void gen_op_addco_64 (void)
807 gen_op_move_T2_T0();
808 gen_op_add();
809 gen_op_check_addc_64();
810 gen_op_check_addo_64();
812 #endif
813 GEN_INT_ARITH2_64 (addc, 0x1F, 0x0A, 0x00, PPC_INTEGER);
814 /* adde adde. addeo addeo. */
815 static always_inline void gen_op_addeo (void)
817 gen_op_move_T2_T0();
818 gen_op_adde();
819 gen_op_check_addo();
821 #if defined(TARGET_PPC64)
822 static always_inline void gen_op_addeo_64 (void)
824 gen_op_move_T2_T0();
825 gen_op_adde_64();
826 gen_op_check_addo_64();
828 #endif
829 GEN_INT_ARITH2_64 (adde, 0x1F, 0x0A, 0x04, PPC_INTEGER);
830 /* addme addme. addmeo addmeo. */
831 static always_inline void gen_op_addme (void)
833 gen_op_move_T1_T0();
834 gen_op_add_me();
836 #if defined(TARGET_PPC64)
837 static always_inline void gen_op_addme_64 (void)
839 gen_op_move_T1_T0();
840 gen_op_add_me_64();
842 #endif
843 GEN_INT_ARITH1_64 (addme, 0x1F, 0x0A, 0x07, PPC_INTEGER);
844 /* addze addze. addzeo addzeo. */
845 static always_inline void gen_op_addze (void)
847 gen_op_move_T2_T0();
848 gen_op_add_ze();
849 gen_op_check_addc();
851 static always_inline void gen_op_addzeo (void)
853 gen_op_move_T2_T0();
854 gen_op_add_ze();
855 gen_op_check_addc();
856 gen_op_check_addo();
858 #if defined(TARGET_PPC64)
859 static always_inline void gen_op_addze_64 (void)
861 gen_op_move_T2_T0();
862 gen_op_add_ze();
863 gen_op_check_addc_64();
865 static always_inline void gen_op_addzeo_64 (void)
867 gen_op_move_T2_T0();
868 gen_op_add_ze();
869 gen_op_check_addc_64();
870 gen_op_check_addo_64();
872 #endif
873 GEN_INT_ARITH1_64 (addze, 0x1F, 0x0A, 0x06, PPC_INTEGER);
874 /* divw divw. divwo divwo. */
875 GEN_INT_ARITH2 (divw, 0x1F, 0x0B, 0x0F, PPC_INTEGER);
876 /* divwu divwu. divwuo divwuo. */
877 GEN_INT_ARITH2 (divwu, 0x1F, 0x0B, 0x0E, PPC_INTEGER);
878 /* mulhw mulhw. */
879 GEN_INT_ARITHN (mulhw, 0x1F, 0x0B, 0x02, PPC_INTEGER);
880 /* mulhwu mulhwu. */
881 GEN_INT_ARITHN (mulhwu, 0x1F, 0x0B, 0x00, PPC_INTEGER);
882 /* mullw mullw. mullwo mullwo. */
883 GEN_INT_ARITH2 (mullw, 0x1F, 0x0B, 0x07, PPC_INTEGER);
884 /* neg neg. nego nego. */
885 GEN_INT_ARITH1_64 (neg, 0x1F, 0x08, 0x03, PPC_INTEGER);
886 /* subf subf. subfo subfo. */
887 static always_inline void gen_op_subfo (void)
889 gen_op_move_T2_T0();
890 gen_op_subf();
891 gen_op_check_subfo();
893 #if defined(TARGET_PPC64)
894 #define gen_op_subf_64 gen_op_subf
895 static always_inline void gen_op_subfo_64 (void)
897 gen_op_move_T2_T0();
898 gen_op_subf();
899 gen_op_check_subfo_64();
901 #endif
902 GEN_INT_ARITH2_64 (subf, 0x1F, 0x08, 0x01, PPC_INTEGER);
903 /* subfc subfc. subfco subfco. */
904 static always_inline void gen_op_subfc (void)
906 gen_op_subf();
907 gen_op_check_subfc();
909 static always_inline void gen_op_subfco (void)
911 gen_op_move_T2_T0();
912 gen_op_subf();
913 gen_op_check_subfc();
914 gen_op_check_subfo();
916 #if defined(TARGET_PPC64)
917 static always_inline void gen_op_subfc_64 (void)
919 gen_op_subf();
920 gen_op_check_subfc_64();
922 static always_inline void gen_op_subfco_64 (void)
924 gen_op_move_T2_T0();
925 gen_op_subf();
926 gen_op_check_subfc_64();
927 gen_op_check_subfo_64();
929 #endif
930 GEN_INT_ARITH2_64 (subfc, 0x1F, 0x08, 0x00, PPC_INTEGER);
931 /* subfe subfe. subfeo subfeo. */
932 static always_inline void gen_op_subfeo (void)
934 gen_op_move_T2_T0();
935 gen_op_subfe();
936 gen_op_check_subfo();
938 #if defined(TARGET_PPC64)
939 #define gen_op_subfe_64 gen_op_subfe
940 static always_inline void gen_op_subfeo_64 (void)
942 gen_op_move_T2_T0();
943 gen_op_subfe_64();
944 gen_op_check_subfo_64();
946 #endif
947 GEN_INT_ARITH2_64 (subfe, 0x1F, 0x08, 0x04, PPC_INTEGER);
948 /* subfme subfme. subfmeo subfmeo. */
949 GEN_INT_ARITH1_64 (subfme, 0x1F, 0x08, 0x07, PPC_INTEGER);
950 /* subfze subfze. subfzeo subfzeo. */
951 GEN_INT_ARITH1_64 (subfze, 0x1F, 0x08, 0x06, PPC_INTEGER);
952 /* addi */
953 GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
955 target_long simm = SIMM(ctx->opcode);
957 if (rA(ctx->opcode) == 0) {
958 /* li case */
959 gen_set_T0(simm);
960 } else {
961 gen_op_load_gpr_T0(rA(ctx->opcode));
962 if (likely(simm != 0))
963 gen_op_addi(simm);
965 gen_op_store_T0_gpr(rD(ctx->opcode));
967 /* addic */
968 GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
970 target_long simm = SIMM(ctx->opcode);
972 gen_op_load_gpr_T0(rA(ctx->opcode));
973 if (likely(simm != 0)) {
974 gen_op_move_T2_T0();
975 gen_op_addi(simm);
976 #if defined(TARGET_PPC64)
977 if (ctx->sf_mode)
978 gen_op_check_addc_64();
979 else
980 #endif
981 gen_op_check_addc();
982 } else {
983 gen_op_clear_xer_ca();
985 gen_op_store_T0_gpr(rD(ctx->opcode));
987 /* addic. */
988 GEN_HANDLER2(addic_, "addic.", 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
990 target_long simm = SIMM(ctx->opcode);
992 gen_op_load_gpr_T0(rA(ctx->opcode));
993 if (likely(simm != 0)) {
994 gen_op_move_T2_T0();
995 gen_op_addi(simm);
996 #if defined(TARGET_PPC64)
997 if (ctx->sf_mode)
998 gen_op_check_addc_64();
999 else
1000 #endif
1001 gen_op_check_addc();
1002 } else {
1003 gen_op_clear_xer_ca();
1005 gen_op_store_T0_gpr(rD(ctx->opcode));
1006 gen_set_Rc0(ctx);
1008 /* addis */
1009 GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1011 target_long simm = SIMM(ctx->opcode);
1013 if (rA(ctx->opcode) == 0) {
1014 /* lis case */
1015 gen_set_T0(simm << 16);
1016 } else {
1017 gen_op_load_gpr_T0(rA(ctx->opcode));
1018 if (likely(simm != 0))
1019 gen_op_addi(simm << 16);
1021 gen_op_store_T0_gpr(rD(ctx->opcode));
1023 /* mulli */
1024 GEN_HANDLER(mulli, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1026 gen_op_load_gpr_T0(rA(ctx->opcode));
1027 gen_op_mulli(SIMM(ctx->opcode));
1028 gen_op_store_T0_gpr(rD(ctx->opcode));
1030 /* subfic */
1031 GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1033 gen_op_load_gpr_T0(rA(ctx->opcode));
1034 #if defined(TARGET_PPC64)
1035 if (ctx->sf_mode)
1036 gen_op_subfic_64(SIMM(ctx->opcode));
1037 else
1038 #endif
1039 gen_op_subfic(SIMM(ctx->opcode));
1040 gen_op_store_T0_gpr(rD(ctx->opcode));
1043 #if defined(TARGET_PPC64)
1044 /* mulhd mulhd. */
1045 GEN_INT_ARITHN (mulhd, 0x1F, 0x09, 0x02, PPC_64B);
1046 /* mulhdu mulhdu. */
1047 GEN_INT_ARITHN (mulhdu, 0x1F, 0x09, 0x00, PPC_64B);
1048 /* mulld mulld. mulldo mulldo. */
1049 GEN_INT_ARITH2 (mulld, 0x1F, 0x09, 0x07, PPC_64B);
1050 /* divd divd. divdo divdo. */
1051 GEN_INT_ARITH2 (divd, 0x1F, 0x09, 0x0F, PPC_64B);
1052 /* divdu divdu. divduo divduo. */
1053 GEN_INT_ARITH2 (divdu, 0x1F, 0x09, 0x0E, PPC_64B);
1054 #endif
1056 /*** Integer comparison ***/
1057 #if defined(TARGET_PPC64)
1058 #define GEN_CMP(name, opc, type) \
1059 GEN_HANDLER(name, 0x1F, 0x00, opc, 0x00400000, type) \
1061 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1062 gen_op_load_gpr_T1(rB(ctx->opcode)); \
1063 if (ctx->sf_mode && (ctx->opcode & 0x00200000)) \
1064 gen_op_##name##_64(); \
1065 else \
1066 gen_op_##name(); \
1067 gen_op_store_T0_crf(crfD(ctx->opcode)); \
1069 #else
1070 #define GEN_CMP(name, opc, type) \
1071 GEN_HANDLER(name, 0x1F, 0x00, opc, 0x00400000, type) \
1073 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1074 gen_op_load_gpr_T1(rB(ctx->opcode)); \
1075 gen_op_##name(); \
1076 gen_op_store_T0_crf(crfD(ctx->opcode)); \
1078 #endif
1080 /* cmp */
1081 GEN_CMP(cmp, 0x00, PPC_INTEGER);
1082 /* cmpi */
1083 GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
1085 gen_op_load_gpr_T0(rA(ctx->opcode));
1086 #if defined(TARGET_PPC64)
1087 if (ctx->sf_mode && (ctx->opcode & 0x00200000))
1088 gen_op_cmpi_64(SIMM(ctx->opcode));
1089 else
1090 #endif
1091 gen_op_cmpi(SIMM(ctx->opcode));
1092 gen_op_store_T0_crf(crfD(ctx->opcode));
1094 /* cmpl */
1095 GEN_CMP(cmpl, 0x01, PPC_INTEGER);
1096 /* cmpli */
1097 GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
1099 gen_op_load_gpr_T0(rA(ctx->opcode));
1100 #if defined(TARGET_PPC64)
1101 if (ctx->sf_mode && (ctx->opcode & 0x00200000))
1102 gen_op_cmpli_64(UIMM(ctx->opcode));
1103 else
1104 #endif
1105 gen_op_cmpli(UIMM(ctx->opcode));
1106 gen_op_store_T0_crf(crfD(ctx->opcode));
1109 /* isel (PowerPC 2.03 specification) */
1110 GEN_HANDLER(isel, 0x1F, 0x0F, 0x00, 0x00000001, PPC_203)
1112 uint32_t bi = rC(ctx->opcode);
1113 uint32_t mask;
1115 if (rA(ctx->opcode) == 0) {
1116 gen_set_T0(0);
1117 } else {
1118 gen_op_load_gpr_T1(rA(ctx->opcode));
1120 gen_op_load_gpr_T2(rB(ctx->opcode));
1121 mask = 1 << (3 - (bi & 0x03));
1122 gen_op_load_crf_T0(bi >> 2);
1123 gen_op_test_true(mask);
1124 gen_op_isel();
1125 gen_op_store_T0_gpr(rD(ctx->opcode));
1128 /*** Integer logical ***/
1129 #define __GEN_LOGICAL2(name, opc2, opc3, type) \
1130 GEN_HANDLER(name, 0x1F, opc2, opc3, 0x00000000, type) \
1132 gen_op_load_gpr_T0(rS(ctx->opcode)); \
1133 gen_op_load_gpr_T1(rB(ctx->opcode)); \
1134 gen_op_##name(); \
1135 gen_op_store_T0_gpr(rA(ctx->opcode)); \
1136 if (unlikely(Rc(ctx->opcode) != 0)) \
1137 gen_set_Rc0(ctx); \
1139 #define GEN_LOGICAL2(name, opc, type) \
1140 __GEN_LOGICAL2(name, 0x1C, opc, type)
1142 #define GEN_LOGICAL1(name, opc, type) \
1143 GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, type) \
1145 gen_op_load_gpr_T0(rS(ctx->opcode)); \
1146 gen_op_##name(); \
1147 gen_op_store_T0_gpr(rA(ctx->opcode)); \
1148 if (unlikely(Rc(ctx->opcode) != 0)) \
1149 gen_set_Rc0(ctx); \
1152 /* and & and. */
1153 GEN_LOGICAL2(and, 0x00, PPC_INTEGER);
1154 /* andc & andc. */
1155 GEN_LOGICAL2(andc, 0x01, PPC_INTEGER);
1156 /* andi. */
1157 GEN_HANDLER2(andi_, "andi.", 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1159 gen_op_load_gpr_T0(rS(ctx->opcode));
1160 gen_op_andi_T0(UIMM(ctx->opcode));
1161 gen_op_store_T0_gpr(rA(ctx->opcode));
1162 gen_set_Rc0(ctx);
1164 /* andis. */
1165 GEN_HANDLER2(andis_, "andis.", 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1167 gen_op_load_gpr_T0(rS(ctx->opcode));
1168 gen_op_andi_T0(UIMM(ctx->opcode) << 16);
1169 gen_op_store_T0_gpr(rA(ctx->opcode));
1170 gen_set_Rc0(ctx);
1173 /* cntlzw */
1174 GEN_LOGICAL1(cntlzw, 0x00, PPC_INTEGER);
1175 /* eqv & eqv. */
1176 GEN_LOGICAL2(eqv, 0x08, PPC_INTEGER);
1177 /* extsb & extsb. */
1178 GEN_LOGICAL1(extsb, 0x1D, PPC_INTEGER);
1179 /* extsh & extsh. */
1180 GEN_LOGICAL1(extsh, 0x1C, PPC_INTEGER);
1181 /* nand & nand. */
1182 GEN_LOGICAL2(nand, 0x0E, PPC_INTEGER);
1183 /* nor & nor. */
1184 GEN_LOGICAL2(nor, 0x03, PPC_INTEGER);
1186 /* or & or. */
1187 GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER)
1189 int rs, ra, rb;
1191 rs = rS(ctx->opcode);
1192 ra = rA(ctx->opcode);
1193 rb = rB(ctx->opcode);
1194 /* Optimisation for mr. ri case */
1195 if (rs != ra || rs != rb) {
1196 gen_op_load_gpr_T0(rs);
1197 if (rs != rb) {
1198 gen_op_load_gpr_T1(rb);
1199 gen_op_or();
1201 gen_op_store_T0_gpr(ra);
1202 if (unlikely(Rc(ctx->opcode) != 0))
1203 gen_set_Rc0(ctx);
1204 } else if (unlikely(Rc(ctx->opcode) != 0)) {
1205 gen_op_load_gpr_T0(rs);
1206 gen_set_Rc0(ctx);
1207 #if defined(TARGET_PPC64)
1208 } else {
1209 switch (rs) {
1210 case 1:
1211 /* Set process priority to low */
1212 gen_op_store_pri(2);
1213 break;
1214 case 6:
1215 /* Set process priority to medium-low */
1216 gen_op_store_pri(3);
1217 break;
1218 case 2:
1219 /* Set process priority to normal */
1220 gen_op_store_pri(4);
1221 break;
1222 #if !defined(CONFIG_USER_ONLY)
1223 case 31:
1224 if (ctx->supervisor > 0) {
1225 /* Set process priority to very low */
1226 gen_op_store_pri(1);
1228 break;
1229 case 5:
1230 if (ctx->supervisor > 0) {
1231 /* Set process priority to medium-hight */
1232 gen_op_store_pri(5);
1234 break;
1235 case 3:
1236 if (ctx->supervisor > 0) {
1237 /* Set process priority to high */
1238 gen_op_store_pri(6);
1240 break;
1241 #if defined(TARGET_PPC64H)
1242 case 7:
1243 if (ctx->supervisor > 1) {
1244 /* Set process priority to very high */
1245 gen_op_store_pri(7);
1247 break;
1248 #endif
1249 #endif
1250 default:
1251 /* nop */
1252 break;
1254 #endif
1258 /* orc & orc. */
1259 GEN_LOGICAL2(orc, 0x0C, PPC_INTEGER);
1260 /* xor & xor. */
1261 GEN_HANDLER(xor, 0x1F, 0x1C, 0x09, 0x00000000, PPC_INTEGER)
1263 gen_op_load_gpr_T0(rS(ctx->opcode));
1264 /* Optimisation for "set to zero" case */
1265 if (rS(ctx->opcode) != rB(ctx->opcode)) {
1266 gen_op_load_gpr_T1(rB(ctx->opcode));
1267 gen_op_xor();
1268 } else {
1269 gen_op_reset_T0();
1271 gen_op_store_T0_gpr(rA(ctx->opcode));
1272 if (unlikely(Rc(ctx->opcode) != 0))
1273 gen_set_Rc0(ctx);
1275 /* ori */
1276 GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1278 target_ulong uimm = UIMM(ctx->opcode);
1280 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1281 /* NOP */
1282 /* XXX: should handle special NOPs for POWER series */
1283 return;
1285 gen_op_load_gpr_T0(rS(ctx->opcode));
1286 if (likely(uimm != 0))
1287 gen_op_ori(uimm);
1288 gen_op_store_T0_gpr(rA(ctx->opcode));
1290 /* oris */
1291 GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1293 target_ulong uimm = UIMM(ctx->opcode);
1295 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1296 /* NOP */
1297 return;
1299 gen_op_load_gpr_T0(rS(ctx->opcode));
1300 if (likely(uimm != 0))
1301 gen_op_ori(uimm << 16);
1302 gen_op_store_T0_gpr(rA(ctx->opcode));
1304 /* xori */
1305 GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1307 target_ulong uimm = UIMM(ctx->opcode);
1309 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1310 /* NOP */
1311 return;
1313 gen_op_load_gpr_T0(rS(ctx->opcode));
1314 if (likely(uimm != 0))
1315 gen_op_xori(uimm);
1316 gen_op_store_T0_gpr(rA(ctx->opcode));
1319 /* xoris */
1320 GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1322 target_ulong uimm = UIMM(ctx->opcode);
1324 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1325 /* NOP */
1326 return;
1328 gen_op_load_gpr_T0(rS(ctx->opcode));
1329 if (likely(uimm != 0))
1330 gen_op_xori(uimm << 16);
1331 gen_op_store_T0_gpr(rA(ctx->opcode));
1334 /* popcntb : PowerPC 2.03 specification */
1335 GEN_HANDLER(popcntb, 0x1F, 0x03, 0x03, 0x0000F801, PPC_203)
1337 gen_op_load_gpr_T0(rS(ctx->opcode));
1338 #if defined(TARGET_PPC64)
1339 if (ctx->sf_mode)
1340 gen_op_popcntb_64();
1341 else
1342 #endif
1343 gen_op_popcntb();
1344 gen_op_store_T0_gpr(rA(ctx->opcode));
1347 #if defined(TARGET_PPC64)
1348 /* extsw & extsw. */
1349 GEN_LOGICAL1(extsw, 0x1E, PPC_64B);
1350 /* cntlzd */
1351 GEN_LOGICAL1(cntlzd, 0x01, PPC_64B);
1352 #endif
1354 /*** Integer rotate ***/
1355 /* rlwimi & rlwimi. */
1356 GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1358 target_ulong mask;
1359 uint32_t mb, me, sh;
1361 mb = MB(ctx->opcode);
1362 me = ME(ctx->opcode);
1363 sh = SH(ctx->opcode);
1364 if (likely(sh == 0)) {
1365 if (likely(mb == 0 && me == 31)) {
1366 gen_op_load_gpr_T0(rS(ctx->opcode));
1367 goto do_store;
1368 } else if (likely(mb == 31 && me == 0)) {
1369 gen_op_load_gpr_T0(rA(ctx->opcode));
1370 goto do_store;
1372 gen_op_load_gpr_T0(rS(ctx->opcode));
1373 gen_op_load_gpr_T1(rA(ctx->opcode));
1374 goto do_mask;
1376 gen_op_load_gpr_T0(rS(ctx->opcode));
1377 gen_op_load_gpr_T1(rA(ctx->opcode));
1378 gen_op_rotli32_T0(SH(ctx->opcode));
1379 do_mask:
1380 #if defined(TARGET_PPC64)
1381 mb += 32;
1382 me += 32;
1383 #endif
1384 mask = MASK(mb, me);
1385 gen_op_andi_T0(mask);
1386 gen_op_andi_T1(~mask);
1387 gen_op_or();
1388 do_store:
1389 gen_op_store_T0_gpr(rA(ctx->opcode));
1390 if (unlikely(Rc(ctx->opcode) != 0))
1391 gen_set_Rc0(ctx);
1393 /* rlwinm & rlwinm. */
1394 GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1396 uint32_t mb, me, sh;
1398 sh = SH(ctx->opcode);
1399 mb = MB(ctx->opcode);
1400 me = ME(ctx->opcode);
1401 gen_op_load_gpr_T0(rS(ctx->opcode));
1402 if (likely(sh == 0)) {
1403 goto do_mask;
1405 if (likely(mb == 0)) {
1406 if (likely(me == 31)) {
1407 gen_op_rotli32_T0(sh);
1408 goto do_store;
1409 } else if (likely(me == (31 - sh))) {
1410 gen_op_sli_T0(sh);
1411 goto do_store;
1413 } else if (likely(me == 31)) {
1414 if (likely(sh == (32 - mb))) {
1415 gen_op_srli_T0(mb);
1416 goto do_store;
1419 gen_op_rotli32_T0(sh);
1420 do_mask:
1421 #if defined(TARGET_PPC64)
1422 mb += 32;
1423 me += 32;
1424 #endif
1425 gen_op_andi_T0(MASK(mb, me));
1426 do_store:
1427 gen_op_store_T0_gpr(rA(ctx->opcode));
1428 if (unlikely(Rc(ctx->opcode) != 0))
1429 gen_set_Rc0(ctx);
1431 /* rlwnm & rlwnm. */
1432 GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1434 uint32_t mb, me;
1436 mb = MB(ctx->opcode);
1437 me = ME(ctx->opcode);
1438 gen_op_load_gpr_T0(rS(ctx->opcode));
1439 gen_op_load_gpr_T1(rB(ctx->opcode));
1440 gen_op_rotl32_T0_T1();
1441 if (unlikely(mb != 0 || me != 31)) {
1442 #if defined(TARGET_PPC64)
1443 mb += 32;
1444 me += 32;
1445 #endif
1446 gen_op_andi_T0(MASK(mb, me));
1448 gen_op_store_T0_gpr(rA(ctx->opcode));
1449 if (unlikely(Rc(ctx->opcode) != 0))
1450 gen_set_Rc0(ctx);
1453 #if defined(TARGET_PPC64)
1454 #define GEN_PPC64_R2(name, opc1, opc2) \
1455 GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B) \
1457 gen_##name(ctx, 0); \
1459 GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000, \
1460 PPC_64B) \
1462 gen_##name(ctx, 1); \
1464 #define GEN_PPC64_R4(name, opc1, opc2) \
1465 GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B) \
1467 gen_##name(ctx, 0, 0); \
1469 GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x01, 0xFF, 0x00000000, \
1470 PPC_64B) \
1472 gen_##name(ctx, 0, 1); \
1474 GEN_HANDLER2(name##2, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000, \
1475 PPC_64B) \
1477 gen_##name(ctx, 1, 0); \
1479 GEN_HANDLER2(name##3, stringify(name), opc1, opc2 | 0x11, 0xFF, 0x00000000, \
1480 PPC_64B) \
1482 gen_##name(ctx, 1, 1); \
1485 static always_inline void gen_andi_T0_64 (DisasContext *ctx, uint64_t mask)
1487 if (mask >> 32)
1488 gen_op_andi_T0_64(mask >> 32, mask & 0xFFFFFFFF);
1489 else
1490 gen_op_andi_T0(mask);
1493 static always_inline void gen_andi_T1_64 (DisasContext *ctx, uint64_t mask)
1495 if (mask >> 32)
1496 gen_op_andi_T1_64(mask >> 32, mask & 0xFFFFFFFF);
1497 else
1498 gen_op_andi_T1(mask);
1501 static always_inline void gen_rldinm (DisasContext *ctx, uint32_t mb,
1502 uint32_t me, uint32_t sh)
1504 gen_op_load_gpr_T0(rS(ctx->opcode));
1505 if (likely(sh == 0)) {
1506 goto do_mask;
1508 if (likely(mb == 0)) {
1509 if (likely(me == 63)) {
1510 gen_op_rotli64_T0(sh);
1511 goto do_store;
1512 } else if (likely(me == (63 - sh))) {
1513 gen_op_sli_T0(sh);
1514 goto do_store;
1516 } else if (likely(me == 63)) {
1517 if (likely(sh == (64 - mb))) {
1518 gen_op_srli_T0_64(mb);
1519 goto do_store;
1522 gen_op_rotli64_T0(sh);
1523 do_mask:
1524 gen_andi_T0_64(ctx, MASK(mb, me));
1525 do_store:
1526 gen_op_store_T0_gpr(rA(ctx->opcode));
1527 if (unlikely(Rc(ctx->opcode) != 0))
1528 gen_set_Rc0(ctx);
1530 /* rldicl - rldicl. */
1531 static always_inline void gen_rldicl (DisasContext *ctx, int mbn, int shn)
1533 uint32_t sh, mb;
1535 sh = SH(ctx->opcode) | (shn << 5);
1536 mb = MB(ctx->opcode) | (mbn << 5);
1537 gen_rldinm(ctx, mb, 63, sh);
1539 GEN_PPC64_R4(rldicl, 0x1E, 0x00);
1540 /* rldicr - rldicr. */
1541 static always_inline void gen_rldicr (DisasContext *ctx, int men, int shn)
1543 uint32_t sh, me;
1545 sh = SH(ctx->opcode) | (shn << 5);
1546 me = MB(ctx->opcode) | (men << 5);
1547 gen_rldinm(ctx, 0, me, sh);
1549 GEN_PPC64_R4(rldicr, 0x1E, 0x02);
1550 /* rldic - rldic. */
1551 static always_inline void gen_rldic (DisasContext *ctx, int mbn, int shn)
1553 uint32_t sh, mb;
1555 sh = SH(ctx->opcode) | (shn << 5);
1556 mb = MB(ctx->opcode) | (mbn << 5);
1557 gen_rldinm(ctx, mb, 63 - sh, sh);
1559 GEN_PPC64_R4(rldic, 0x1E, 0x04);
1561 static always_inline void gen_rldnm (DisasContext *ctx, uint32_t mb,
1562 uint32_t me)
1564 gen_op_load_gpr_T0(rS(ctx->opcode));
1565 gen_op_load_gpr_T1(rB(ctx->opcode));
1566 gen_op_rotl64_T0_T1();
1567 if (unlikely(mb != 0 || me != 63)) {
1568 gen_andi_T0_64(ctx, MASK(mb, me));
1570 gen_op_store_T0_gpr(rA(ctx->opcode));
1571 if (unlikely(Rc(ctx->opcode) != 0))
1572 gen_set_Rc0(ctx);
1575 /* rldcl - rldcl. */
1576 static always_inline void gen_rldcl (DisasContext *ctx, int mbn)
1578 uint32_t mb;
1580 mb = MB(ctx->opcode) | (mbn << 5);
1581 gen_rldnm(ctx, mb, 63);
1583 GEN_PPC64_R2(rldcl, 0x1E, 0x08);
1584 /* rldcr - rldcr. */
1585 static always_inline void gen_rldcr (DisasContext *ctx, int men)
1587 uint32_t me;
1589 me = MB(ctx->opcode) | (men << 5);
1590 gen_rldnm(ctx, 0, me);
1592 GEN_PPC64_R2(rldcr, 0x1E, 0x09);
1593 /* rldimi - rldimi. */
1594 static always_inline void gen_rldimi (DisasContext *ctx, int mbn, int shn)
1596 uint64_t mask;
1597 uint32_t sh, mb;
1599 sh = SH(ctx->opcode) | (shn << 5);
1600 mb = MB(ctx->opcode) | (mbn << 5);
1601 if (likely(sh == 0)) {
1602 if (likely(mb == 0)) {
1603 gen_op_load_gpr_T0(rS(ctx->opcode));
1604 goto do_store;
1605 } else if (likely(mb == 63)) {
1606 gen_op_load_gpr_T0(rA(ctx->opcode));
1607 goto do_store;
1609 gen_op_load_gpr_T0(rS(ctx->opcode));
1610 gen_op_load_gpr_T1(rA(ctx->opcode));
1611 goto do_mask;
1613 gen_op_load_gpr_T0(rS(ctx->opcode));
1614 gen_op_load_gpr_T1(rA(ctx->opcode));
1615 gen_op_rotli64_T0(sh);
1616 do_mask:
1617 mask = MASK(mb, 63 - sh);
1618 gen_andi_T0_64(ctx, mask);
1619 gen_andi_T1_64(ctx, ~mask);
1620 gen_op_or();
1621 do_store:
1622 gen_op_store_T0_gpr(rA(ctx->opcode));
1623 if (unlikely(Rc(ctx->opcode) != 0))
1624 gen_set_Rc0(ctx);
1626 GEN_PPC64_R4(rldimi, 0x1E, 0x06);
1627 #endif
1629 /*** Integer shift ***/
1630 /* slw & slw. */
1631 __GEN_LOGICAL2(slw, 0x18, 0x00, PPC_INTEGER);
1632 /* sraw & sraw. */
1633 __GEN_LOGICAL2(sraw, 0x18, 0x18, PPC_INTEGER);
1634 /* srawi & srawi. */
1635 GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER)
1637 int mb, me;
1638 gen_op_load_gpr_T0(rS(ctx->opcode));
1639 if (SH(ctx->opcode) != 0) {
1640 gen_op_move_T1_T0();
1641 mb = 32 - SH(ctx->opcode);
1642 me = 31;
1643 #if defined(TARGET_PPC64)
1644 mb += 32;
1645 me += 32;
1646 #endif
1647 gen_op_srawi(SH(ctx->opcode), MASK(mb, me));
1649 gen_op_store_T0_gpr(rA(ctx->opcode));
1650 if (unlikely(Rc(ctx->opcode) != 0))
1651 gen_set_Rc0(ctx);
1653 /* srw & srw. */
1654 __GEN_LOGICAL2(srw, 0x18, 0x10, PPC_INTEGER);
1656 #if defined(TARGET_PPC64)
1657 /* sld & sld. */
1658 __GEN_LOGICAL2(sld, 0x1B, 0x00, PPC_64B);
1659 /* srad & srad. */
1660 __GEN_LOGICAL2(srad, 0x1A, 0x18, PPC_64B);
1661 /* sradi & sradi. */
1662 static always_inline void gen_sradi (DisasContext *ctx, int n)
1664 uint64_t mask;
1665 int sh, mb, me;
1667 gen_op_load_gpr_T0(rS(ctx->opcode));
1668 sh = SH(ctx->opcode) + (n << 5);
1669 if (sh != 0) {
1670 gen_op_move_T1_T0();
1671 mb = 64 - SH(ctx->opcode);
1672 me = 63;
1673 mask = MASK(mb, me);
1674 gen_op_sradi(sh, mask >> 32, mask);
1676 gen_op_store_T0_gpr(rA(ctx->opcode));
1677 if (unlikely(Rc(ctx->opcode) != 0))
1678 gen_set_Rc0(ctx);
1680 GEN_HANDLER2(sradi0, "sradi", 0x1F, 0x1A, 0x19, 0x00000000, PPC_64B)
1682 gen_sradi(ctx, 0);
1684 GEN_HANDLER2(sradi1, "sradi", 0x1F, 0x1B, 0x19, 0x00000000, PPC_64B)
1686 gen_sradi(ctx, 1);
1688 /* srd & srd. */
1689 __GEN_LOGICAL2(srd, 0x1B, 0x10, PPC_64B);
1690 #endif
1692 /*** Floating-Point arithmetic ***/
1693 #define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type) \
1694 GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, type) \
1696 if (unlikely(!ctx->fpu_enabled)) { \
1697 GEN_EXCP_NO_FP(ctx); \
1698 return; \
1700 gen_op_load_fpr_FT0(rA(ctx->opcode)); \
1701 gen_op_load_fpr_FT1(rC(ctx->opcode)); \
1702 gen_op_load_fpr_FT2(rB(ctx->opcode)); \
1703 gen_reset_fpstatus(); \
1704 gen_op_f##op(); \
1705 if (isfloat) { \
1706 gen_op_frsp(); \
1708 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
1709 gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0); \
1712 #define GEN_FLOAT_ACB(name, op2, set_fprf, type) \
1713 _GEN_FLOAT_ACB(name, name, 0x3F, op2, 0, set_fprf, type); \
1714 _GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, set_fprf, type);
1716 #define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type) \
1717 GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type) \
1719 if (unlikely(!ctx->fpu_enabled)) { \
1720 GEN_EXCP_NO_FP(ctx); \
1721 return; \
1723 gen_op_load_fpr_FT0(rA(ctx->opcode)); \
1724 gen_op_load_fpr_FT1(rB(ctx->opcode)); \
1725 gen_reset_fpstatus(); \
1726 gen_op_f##op(); \
1727 if (isfloat) { \
1728 gen_op_frsp(); \
1730 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
1731 gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0); \
1733 #define GEN_FLOAT_AB(name, op2, inval, set_fprf, type) \
1734 _GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0, set_fprf, type); \
1735 _GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
1737 #define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type) \
1738 GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type) \
1740 if (unlikely(!ctx->fpu_enabled)) { \
1741 GEN_EXCP_NO_FP(ctx); \
1742 return; \
1744 gen_op_load_fpr_FT0(rA(ctx->opcode)); \
1745 gen_op_load_fpr_FT1(rC(ctx->opcode)); \
1746 gen_reset_fpstatus(); \
1747 gen_op_f##op(); \
1748 if (isfloat) { \
1749 gen_op_frsp(); \
1751 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
1752 gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0); \
1754 #define GEN_FLOAT_AC(name, op2, inval, set_fprf, type) \
1755 _GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0, set_fprf, type); \
1756 _GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
1758 #define GEN_FLOAT_B(name, op2, op3, set_fprf, type) \
1759 GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, type) \
1761 if (unlikely(!ctx->fpu_enabled)) { \
1762 GEN_EXCP_NO_FP(ctx); \
1763 return; \
1765 gen_op_load_fpr_FT0(rB(ctx->opcode)); \
1766 gen_reset_fpstatus(); \
1767 gen_op_f##name(); \
1768 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
1769 gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0); \
1772 #define GEN_FLOAT_BS(name, op1, op2, set_fprf, type) \
1773 GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, type) \
1775 if (unlikely(!ctx->fpu_enabled)) { \
1776 GEN_EXCP_NO_FP(ctx); \
1777 return; \
1779 gen_op_load_fpr_FT0(rB(ctx->opcode)); \
1780 gen_reset_fpstatus(); \
1781 gen_op_f##name(); \
1782 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
1783 gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0); \
1786 /* fadd - fadds */
1787 GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT);
1788 /* fdiv - fdivs */
1789 GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT);
1790 /* fmul - fmuls */
1791 GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT);
1793 /* fre */
1794 GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT);
1796 /* fres */
1797 GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES);
1799 /* frsqrte */
1800 GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE);
1802 /* frsqrtes */
1803 static always_inline void gen_op_frsqrtes (void)
1805 gen_op_frsqrte();
1806 gen_op_frsp();
1808 GEN_FLOAT_BS(rsqrtes, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTES);
1810 /* fsel */
1811 _GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL);
1812 /* fsub - fsubs */
1813 GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
1814 /* Optional: */
1815 /* fsqrt */
1816 GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT)
1818 if (unlikely(!ctx->fpu_enabled)) {
1819 GEN_EXCP_NO_FP(ctx);
1820 return;
1822 gen_op_load_fpr_FT0(rB(ctx->opcode));
1823 gen_reset_fpstatus();
1824 gen_op_fsqrt();
1825 gen_op_store_FT0_fpr(rD(ctx->opcode));
1826 gen_compute_fprf(1, Rc(ctx->opcode) != 0);
1829 GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT)
1831 if (unlikely(!ctx->fpu_enabled)) {
1832 GEN_EXCP_NO_FP(ctx);
1833 return;
1835 gen_op_load_fpr_FT0(rB(ctx->opcode));
1836 gen_reset_fpstatus();
1837 gen_op_fsqrt();
1838 gen_op_frsp();
1839 gen_op_store_FT0_fpr(rD(ctx->opcode));
1840 gen_compute_fprf(1, Rc(ctx->opcode) != 0);
1843 /*** Floating-Point multiply-and-add ***/
1844 /* fmadd - fmadds */
1845 GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT);
1846 /* fmsub - fmsubs */
1847 GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT);
1848 /* fnmadd - fnmadds */
1849 GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT);
1850 /* fnmsub - fnmsubs */
1851 GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT);
1853 /*** Floating-Point round & convert ***/
1854 /* fctiw */
1855 GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT);
1856 /* fctiwz */
1857 GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT);
1858 /* frsp */
1859 GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT);
1860 #if defined(TARGET_PPC64)
1861 /* fcfid */
1862 GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC_64B);
1863 /* fctid */
1864 GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC_64B);
1865 /* fctidz */
1866 GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC_64B);
1867 #endif
1869 /* frin */
1870 GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT);
1871 /* friz */
1872 GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT);
1873 /* frip */
1874 GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT);
1875 /* frim */
1876 GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT);
1878 /*** Floating-Point compare ***/
1879 /* fcmpo */
1880 GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT)
1882 if (unlikely(!ctx->fpu_enabled)) {
1883 GEN_EXCP_NO_FP(ctx);
1884 return;
1886 gen_op_load_fpr_FT0(rA(ctx->opcode));
1887 gen_op_load_fpr_FT1(rB(ctx->opcode));
1888 gen_reset_fpstatus();
1889 gen_op_fcmpo();
1890 gen_op_store_T0_crf(crfD(ctx->opcode));
1891 gen_op_float_check_status();
1894 /* fcmpu */
1895 GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT)
1897 if (unlikely(!ctx->fpu_enabled)) {
1898 GEN_EXCP_NO_FP(ctx);
1899 return;
1901 gen_op_load_fpr_FT0(rA(ctx->opcode));
1902 gen_op_load_fpr_FT1(rB(ctx->opcode));
1903 gen_reset_fpstatus();
1904 gen_op_fcmpu();
1905 gen_op_store_T0_crf(crfD(ctx->opcode));
1906 gen_op_float_check_status();
1909 /*** Floating-point move ***/
1910 /* fabs */
1911 /* XXX: beware that fabs never checks for NaNs nor update FPSCR */
1912 GEN_FLOAT_B(abs, 0x08, 0x08, 0, PPC_FLOAT);
1914 /* fmr - fmr. */
1915 /* XXX: beware that fmr never checks for NaNs nor update FPSCR */
1916 GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT)
1918 if (unlikely(!ctx->fpu_enabled)) {
1919 GEN_EXCP_NO_FP(ctx);
1920 return;
1922 gen_op_load_fpr_FT0(rB(ctx->opcode));
1923 gen_op_store_FT0_fpr(rD(ctx->opcode));
1924 gen_compute_fprf(0, Rc(ctx->opcode) != 0);
1927 /* fnabs */
1928 /* XXX: beware that fnabs never checks for NaNs nor update FPSCR */
1929 GEN_FLOAT_B(nabs, 0x08, 0x04, 0, PPC_FLOAT);
1930 /* fneg */
1931 /* XXX: beware that fneg never checks for NaNs nor update FPSCR */
1932 GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT);
1934 /*** Floating-Point status & ctrl register ***/
1935 /* mcrfs */
1936 GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT)
1938 int bfa;
1940 if (unlikely(!ctx->fpu_enabled)) {
1941 GEN_EXCP_NO_FP(ctx);
1942 return;
1944 gen_optimize_fprf();
1945 bfa = 4 * (7 - crfS(ctx->opcode));
1946 gen_op_load_fpscr_T0(bfa);
1947 gen_op_store_T0_crf(crfD(ctx->opcode));
1948 gen_op_fpscr_resetbit(~(0xF << bfa));
1951 /* mffs */
1952 GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT)
1954 if (unlikely(!ctx->fpu_enabled)) {
1955 GEN_EXCP_NO_FP(ctx);
1956 return;
1958 gen_optimize_fprf();
1959 gen_reset_fpstatus();
1960 gen_op_load_fpscr_FT0();
1961 gen_op_store_FT0_fpr(rD(ctx->opcode));
1962 gen_compute_fprf(0, Rc(ctx->opcode) != 0);
1965 /* mtfsb0 */
1966 GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT)
1968 uint8_t crb;
1970 if (unlikely(!ctx->fpu_enabled)) {
1971 GEN_EXCP_NO_FP(ctx);
1972 return;
1974 crb = 32 - (crbD(ctx->opcode) >> 2);
1975 gen_optimize_fprf();
1976 gen_reset_fpstatus();
1977 if (likely(crb != 30 && crb != 29))
1978 gen_op_fpscr_resetbit(~(1 << crb));
1979 if (unlikely(Rc(ctx->opcode) != 0)) {
1980 gen_op_load_fpcc();
1981 gen_op_set_Rc0();
1985 /* mtfsb1 */
1986 GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT)
1988 uint8_t crb;
1990 if (unlikely(!ctx->fpu_enabled)) {
1991 GEN_EXCP_NO_FP(ctx);
1992 return;
1994 crb = 32 - (crbD(ctx->opcode) >> 2);
1995 gen_optimize_fprf();
1996 gen_reset_fpstatus();
1997 /* XXX: we pretend we can only do IEEE floating-point computations */
1998 if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI))
1999 gen_op_fpscr_setbit(crb);
2000 if (unlikely(Rc(ctx->opcode) != 0)) {
2001 gen_op_load_fpcc();
2002 gen_op_set_Rc0();
2004 /* We can raise a differed exception */
2005 gen_op_float_check_status();
2008 /* mtfsf */
2009 GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT)
2011 if (unlikely(!ctx->fpu_enabled)) {
2012 GEN_EXCP_NO_FP(ctx);
2013 return;
2015 gen_optimize_fprf();
2016 gen_op_load_fpr_FT0(rB(ctx->opcode));
2017 gen_reset_fpstatus();
2018 gen_op_store_fpscr(FM(ctx->opcode));
2019 if (unlikely(Rc(ctx->opcode) != 0)) {
2020 gen_op_load_fpcc();
2021 gen_op_set_Rc0();
2023 /* We can raise a differed exception */
2024 gen_op_float_check_status();
2027 /* mtfsfi */
2028 GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT)
2030 int bf, sh;
2032 if (unlikely(!ctx->fpu_enabled)) {
2033 GEN_EXCP_NO_FP(ctx);
2034 return;
2036 bf = crbD(ctx->opcode) >> 2;
2037 sh = 7 - bf;
2038 gen_optimize_fprf();
2039 gen_op_set_FT0(FPIMM(ctx->opcode) << (4 * sh));
2040 gen_reset_fpstatus();
2041 gen_op_store_fpscr(1 << sh);
2042 if (unlikely(Rc(ctx->opcode) != 0)) {
2043 gen_op_load_fpcc();
2044 gen_op_set_Rc0();
2046 /* We can raise a differed exception */
2047 gen_op_float_check_status();
2050 /*** Addressing modes ***/
2051 /* Register indirect with immediate index : EA = (rA|0) + SIMM */
2052 static always_inline void gen_addr_imm_index (DisasContext *ctx,
2053 target_long maskl)
2055 target_long simm = SIMM(ctx->opcode);
2057 simm &= ~maskl;
2058 if (rA(ctx->opcode) == 0) {
2059 gen_set_T0(simm);
2060 } else {
2061 gen_op_load_gpr_T0(rA(ctx->opcode));
2062 if (likely(simm != 0))
2063 gen_op_addi(simm);
2065 #ifdef DEBUG_MEMORY_ACCESSES
2066 gen_op_print_mem_EA();
2067 #endif
2070 static always_inline void gen_addr_reg_index (DisasContext *ctx)
2072 if (rA(ctx->opcode) == 0) {
2073 gen_op_load_gpr_T0(rB(ctx->opcode));
2074 } else {
2075 gen_op_load_gpr_T0(rA(ctx->opcode));
2076 gen_op_load_gpr_T1(rB(ctx->opcode));
2077 gen_op_add();
2079 #ifdef DEBUG_MEMORY_ACCESSES
2080 gen_op_print_mem_EA();
2081 #endif
2084 static always_inline void gen_addr_register (DisasContext *ctx)
2086 if (rA(ctx->opcode) == 0) {
2087 gen_op_reset_T0();
2088 } else {
2089 gen_op_load_gpr_T0(rA(ctx->opcode));
2091 #ifdef DEBUG_MEMORY_ACCESSES
2092 gen_op_print_mem_EA();
2093 #endif
2096 /*** Integer load ***/
2097 #define op_ldst(name) (*gen_op_##name[ctx->mem_idx])()
2098 #if defined(CONFIG_USER_ONLY)
2099 #if defined(TARGET_PPC64)
2100 /* User mode only - 64 bits */
2101 #define OP_LD_TABLE(width) \
2102 static GenOpFunc *gen_op_l##width[] = { \
2103 &gen_op_l##width##_raw, \
2104 &gen_op_l##width##_le_raw, \
2105 &gen_op_l##width##_64_raw, \
2106 &gen_op_l##width##_le_64_raw, \
2108 #define OP_ST_TABLE(width) \
2109 static GenOpFunc *gen_op_st##width[] = { \
2110 &gen_op_st##width##_raw, \
2111 &gen_op_st##width##_le_raw, \
2112 &gen_op_st##width##_64_raw, \
2113 &gen_op_st##width##_le_64_raw, \
2115 /* Byte access routine are endian safe */
2116 #define gen_op_stb_le_64_raw gen_op_stb_64_raw
2117 #define gen_op_lbz_le_64_raw gen_op_lbz_64_raw
2118 #else
2119 /* User mode only - 32 bits */
2120 #define OP_LD_TABLE(width) \
2121 static GenOpFunc *gen_op_l##width[] = { \
2122 &gen_op_l##width##_raw, \
2123 &gen_op_l##width##_le_raw, \
2125 #define OP_ST_TABLE(width) \
2126 static GenOpFunc *gen_op_st##width[] = { \
2127 &gen_op_st##width##_raw, \
2128 &gen_op_st##width##_le_raw, \
2130 #endif
2131 /* Byte access routine are endian safe */
2132 #define gen_op_stb_le_raw gen_op_stb_raw
2133 #define gen_op_lbz_le_raw gen_op_lbz_raw
2134 #else
2135 #if defined(TARGET_PPC64)
2136 #if defined(TARGET_PPC64H)
2137 /* Full system - 64 bits with hypervisor mode */
2138 #define OP_LD_TABLE(width) \
2139 static GenOpFunc *gen_op_l##width[] = { \
2140 &gen_op_l##width##_user, \
2141 &gen_op_l##width##_le_user, \
2142 &gen_op_l##width##_64_user, \
2143 &gen_op_l##width##_le_64_user, \
2144 &gen_op_l##width##_kernel, \
2145 &gen_op_l##width##_le_kernel, \
2146 &gen_op_l##width##_64_kernel, \
2147 &gen_op_l##width##_le_64_kernel, \
2148 &gen_op_l##width##_hypv, \
2149 &gen_op_l##width##_le_hypv, \
2150 &gen_op_l##width##_64_hypv, \
2151 &gen_op_l##width##_le_64_hypv, \
2153 #define OP_ST_TABLE(width) \
2154 static GenOpFunc *gen_op_st##width[] = { \
2155 &gen_op_st##width##_user, \
2156 &gen_op_st##width##_le_user, \
2157 &gen_op_st##width##_64_user, \
2158 &gen_op_st##width##_le_64_user, \
2159 &gen_op_st##width##_kernel, \
2160 &gen_op_st##width##_le_kernel, \
2161 &gen_op_st##width##_64_kernel, \
2162 &gen_op_st##width##_le_64_kernel, \
2163 &gen_op_st##width##_hypv, \
2164 &gen_op_st##width##_le_hypv, \
2165 &gen_op_st##width##_64_hypv, \
2166 &gen_op_st##width##_le_64_hypv, \
2168 /* Byte access routine are endian safe */
2169 #define gen_op_stb_le_hypv gen_op_stb_64_hypv
2170 #define gen_op_lbz_le_hypv gen_op_lbz_64_hypv
2171 #define gen_op_stb_le_64_hypv gen_op_stb_64_hypv
2172 #define gen_op_lbz_le_64_hypv gen_op_lbz_64_hypv
2173 #else
2174 /* Full system - 64 bits */
2175 #define OP_LD_TABLE(width) \
2176 static GenOpFunc *gen_op_l##width[] = { \
2177 &gen_op_l##width##_user, \
2178 &gen_op_l##width##_le_user, \
2179 &gen_op_l##width##_64_user, \
2180 &gen_op_l##width##_le_64_user, \
2181 &gen_op_l##width##_kernel, \
2182 &gen_op_l##width##_le_kernel, \
2183 &gen_op_l##width##_64_kernel, \
2184 &gen_op_l##width##_le_64_kernel, \
2186 #define OP_ST_TABLE(width) \
2187 static GenOpFunc *gen_op_st##width[] = { \
2188 &gen_op_st##width##_user, \
2189 &gen_op_st##width##_le_user, \
2190 &gen_op_st##width##_64_user, \
2191 &gen_op_st##width##_le_64_user, \
2192 &gen_op_st##width##_kernel, \
2193 &gen_op_st##width##_le_kernel, \
2194 &gen_op_st##width##_64_kernel, \
2195 &gen_op_st##width##_le_64_kernel, \
2197 #endif
2198 /* Byte access routine are endian safe */
2199 #define gen_op_stb_le_64_user gen_op_stb_64_user
2200 #define gen_op_lbz_le_64_user gen_op_lbz_64_user
2201 #define gen_op_stb_le_64_kernel gen_op_stb_64_kernel
2202 #define gen_op_lbz_le_64_kernel gen_op_lbz_64_kernel
2203 #else
2204 /* Full system - 32 bits */
2205 #define OP_LD_TABLE(width) \
2206 static GenOpFunc *gen_op_l##width[] = { \
2207 &gen_op_l##width##_user, \
2208 &gen_op_l##width##_le_user, \
2209 &gen_op_l##width##_kernel, \
2210 &gen_op_l##width##_le_kernel, \
2212 #define OP_ST_TABLE(width) \
2213 static GenOpFunc *gen_op_st##width[] = { \
2214 &gen_op_st##width##_user, \
2215 &gen_op_st##width##_le_user, \
2216 &gen_op_st##width##_kernel, \
2217 &gen_op_st##width##_le_kernel, \
2219 #endif
2220 /* Byte access routine are endian safe */
2221 #define gen_op_stb_le_user gen_op_stb_user
2222 #define gen_op_lbz_le_user gen_op_lbz_user
2223 #define gen_op_stb_le_kernel gen_op_stb_kernel
2224 #define gen_op_lbz_le_kernel gen_op_lbz_kernel
2225 #endif
2227 #define GEN_LD(width, opc, type) \
2228 GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, type) \
2230 gen_addr_imm_index(ctx, 0); \
2231 op_ldst(l##width); \
2232 gen_op_store_T1_gpr(rD(ctx->opcode)); \
2235 #define GEN_LDU(width, opc, type) \
2236 GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, type) \
2238 if (unlikely(rA(ctx->opcode) == 0 || \
2239 rA(ctx->opcode) == rD(ctx->opcode))) { \
2240 GEN_EXCP_INVAL(ctx); \
2241 return; \
2243 if (type == PPC_64B) \
2244 gen_addr_imm_index(ctx, 0x03); \
2245 else \
2246 gen_addr_imm_index(ctx, 0); \
2247 op_ldst(l##width); \
2248 gen_op_store_T1_gpr(rD(ctx->opcode)); \
2249 gen_op_store_T0_gpr(rA(ctx->opcode)); \
2252 #define GEN_LDUX(width, opc2, opc3, type) \
2253 GEN_HANDLER(l##width##ux, 0x1F, opc2, opc3, 0x00000001, type) \
2255 if (unlikely(rA(ctx->opcode) == 0 || \
2256 rA(ctx->opcode) == rD(ctx->opcode))) { \
2257 GEN_EXCP_INVAL(ctx); \
2258 return; \
2260 gen_addr_reg_index(ctx); \
2261 op_ldst(l##width); \
2262 gen_op_store_T1_gpr(rD(ctx->opcode)); \
2263 gen_op_store_T0_gpr(rA(ctx->opcode)); \
2266 #define GEN_LDX(width, opc2, opc3, type) \
2267 GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, type) \
2269 gen_addr_reg_index(ctx); \
2270 op_ldst(l##width); \
2271 gen_op_store_T1_gpr(rD(ctx->opcode)); \
2274 #define GEN_LDS(width, op, type) \
2275 OP_LD_TABLE(width); \
2276 GEN_LD(width, op | 0x20, type); \
2277 GEN_LDU(width, op | 0x21, type); \
2278 GEN_LDUX(width, 0x17, op | 0x01, type); \
2279 GEN_LDX(width, 0x17, op | 0x00, type)
2281 /* lbz lbzu lbzux lbzx */
2282 GEN_LDS(bz, 0x02, PPC_INTEGER);
2283 /* lha lhau lhaux lhax */
2284 GEN_LDS(ha, 0x0A, PPC_INTEGER);
2285 /* lhz lhzu lhzux lhzx */
2286 GEN_LDS(hz, 0x08, PPC_INTEGER);
2287 /* lwz lwzu lwzux lwzx */
2288 GEN_LDS(wz, 0x00, PPC_INTEGER);
2289 #if defined(TARGET_PPC64)
2290 OP_LD_TABLE(wa);
2291 OP_LD_TABLE(d);
2292 /* lwaux */
2293 GEN_LDUX(wa, 0x15, 0x0B, PPC_64B);
2294 /* lwax */
2295 GEN_LDX(wa, 0x15, 0x0A, PPC_64B);
2296 /* ldux */
2297 GEN_LDUX(d, 0x15, 0x01, PPC_64B);
2298 /* ldx */
2299 GEN_LDX(d, 0x15, 0x00, PPC_64B);
2300 GEN_HANDLER(ld, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B)
2302 if (Rc(ctx->opcode)) {
2303 if (unlikely(rA(ctx->opcode) == 0 ||
2304 rA(ctx->opcode) == rD(ctx->opcode))) {
2305 GEN_EXCP_INVAL(ctx);
2306 return;
2309 gen_addr_imm_index(ctx, 0x03);
2310 if (ctx->opcode & 0x02) {
2311 /* lwa (lwau is undefined) */
2312 op_ldst(lwa);
2313 } else {
2314 /* ld - ldu */
2315 op_ldst(ld);
2317 gen_op_store_T1_gpr(rD(ctx->opcode));
2318 if (Rc(ctx->opcode))
2319 gen_op_store_T0_gpr(rA(ctx->opcode));
2321 /* lq */
2322 GEN_HANDLER(lq, 0x38, 0xFF, 0xFF, 0x00000000, PPC_64BX)
2324 #if defined(CONFIG_USER_ONLY)
2325 GEN_EXCP_PRIVOPC(ctx);
2326 #else
2327 int ra, rd;
2329 /* Restore CPU state */
2330 if (unlikely(ctx->supervisor == 0)) {
2331 GEN_EXCP_PRIVOPC(ctx);
2332 return;
2334 ra = rA(ctx->opcode);
2335 rd = rD(ctx->opcode);
2336 if (unlikely((rd & 1) || rd == ra)) {
2337 GEN_EXCP_INVAL(ctx);
2338 return;
2340 if (unlikely(ctx->mem_idx & 1)) {
2341 /* Little-endian mode is not handled */
2342 GEN_EXCP(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
2343 return;
2345 gen_addr_imm_index(ctx, 0x0F);
2346 op_ldst(ld);
2347 gen_op_store_T1_gpr(rd);
2348 gen_op_addi(8);
2349 op_ldst(ld);
2350 gen_op_store_T1_gpr(rd + 1);
2351 #endif
2353 #endif
2355 /*** Integer store ***/
2356 #define GEN_ST(width, opc, type) \
2357 GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, type) \
2359 gen_addr_imm_index(ctx, 0); \
2360 gen_op_load_gpr_T1(rS(ctx->opcode)); \
2361 op_ldst(st##width); \
2364 #define GEN_STU(width, opc, type) \
2365 GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, type) \
2367 if (unlikely(rA(ctx->opcode) == 0)) { \
2368 GEN_EXCP_INVAL(ctx); \
2369 return; \
2371 if (type == PPC_64B) \
2372 gen_addr_imm_index(ctx, 0x03); \
2373 else \
2374 gen_addr_imm_index(ctx, 0); \
2375 gen_op_load_gpr_T1(rS(ctx->opcode)); \
2376 op_ldst(st##width); \
2377 gen_op_store_T0_gpr(rA(ctx->opcode)); \
2380 #define GEN_STUX(width, opc2, opc3, type) \
2381 GEN_HANDLER(st##width##ux, 0x1F, opc2, opc3, 0x00000001, type) \
2383 if (unlikely(rA(ctx->opcode) == 0)) { \
2384 GEN_EXCP_INVAL(ctx); \
2385 return; \
2387 gen_addr_reg_index(ctx); \
2388 gen_op_load_gpr_T1(rS(ctx->opcode)); \
2389 op_ldst(st##width); \
2390 gen_op_store_T0_gpr(rA(ctx->opcode)); \
2393 #define GEN_STX(width, opc2, opc3, type) \
2394 GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, type) \
2396 gen_addr_reg_index(ctx); \
2397 gen_op_load_gpr_T1(rS(ctx->opcode)); \
2398 op_ldst(st##width); \
2401 #define GEN_STS(width, op, type) \
2402 OP_ST_TABLE(width); \
2403 GEN_ST(width, op | 0x20, type); \
2404 GEN_STU(width, op | 0x21, type); \
2405 GEN_STUX(width, 0x17, op | 0x01, type); \
2406 GEN_STX(width, 0x17, op | 0x00, type)
2408 /* stb stbu stbux stbx */
2409 GEN_STS(b, 0x06, PPC_INTEGER);
2410 /* sth sthu sthux sthx */
2411 GEN_STS(h, 0x0C, PPC_INTEGER);
2412 /* stw stwu stwux stwx */
2413 GEN_STS(w, 0x04, PPC_INTEGER);
2414 #if defined(TARGET_PPC64)
2415 OP_ST_TABLE(d);
2416 GEN_STUX(d, 0x15, 0x05, PPC_64B);
2417 GEN_STX(d, 0x15, 0x04, PPC_64B);
2418 GEN_HANDLER(std, 0x3E, 0xFF, 0xFF, 0x00000000, PPC_64B)
2420 int rs;
2422 rs = rS(ctx->opcode);
2423 if ((ctx->opcode & 0x3) == 0x2) {
2424 #if defined(CONFIG_USER_ONLY)
2425 GEN_EXCP_PRIVOPC(ctx);
2426 #else
2427 /* stq */
2428 if (unlikely(ctx->supervisor == 0)) {
2429 GEN_EXCP_PRIVOPC(ctx);
2430 return;
2432 if (unlikely(rs & 1)) {
2433 GEN_EXCP_INVAL(ctx);
2434 return;
2436 if (unlikely(ctx->mem_idx & 1)) {
2437 /* Little-endian mode is not handled */
2438 GEN_EXCP(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
2439 return;
2441 gen_addr_imm_index(ctx, 0x03);
2442 gen_op_load_gpr_T1(rs);
2443 op_ldst(std);
2444 gen_op_addi(8);
2445 gen_op_load_gpr_T1(rs + 1);
2446 op_ldst(std);
2447 #endif
2448 } else {
2449 /* std / stdu */
2450 if (Rc(ctx->opcode)) {
2451 if (unlikely(rA(ctx->opcode) == 0)) {
2452 GEN_EXCP_INVAL(ctx);
2453 return;
2456 gen_addr_imm_index(ctx, 0x03);
2457 gen_op_load_gpr_T1(rs);
2458 op_ldst(std);
2459 if (Rc(ctx->opcode))
2460 gen_op_store_T0_gpr(rA(ctx->opcode));
2463 #endif
2464 /*** Integer load and store with byte reverse ***/
2465 /* lhbrx */
2466 OP_LD_TABLE(hbr);
2467 GEN_LDX(hbr, 0x16, 0x18, PPC_INTEGER);
2468 /* lwbrx */
2469 OP_LD_TABLE(wbr);
2470 GEN_LDX(wbr, 0x16, 0x10, PPC_INTEGER);
2471 /* sthbrx */
2472 OP_ST_TABLE(hbr);
2473 GEN_STX(hbr, 0x16, 0x1C, PPC_INTEGER);
2474 /* stwbrx */
2475 OP_ST_TABLE(wbr);
2476 GEN_STX(wbr, 0x16, 0x14, PPC_INTEGER);
2478 /*** Integer load and store multiple ***/
2479 #define op_ldstm(name, reg) (*gen_op_##name[ctx->mem_idx])(reg)
2480 #if defined(CONFIG_USER_ONLY)
2481 /* User-mode only */
2482 static GenOpFunc1 *gen_op_lmw[] = {
2483 &gen_op_lmw_raw,
2484 &gen_op_lmw_le_raw,
2485 #if defined(TARGET_PPC64)
2486 &gen_op_lmw_64_raw,
2487 &gen_op_lmw_le_64_raw,
2488 #endif
2490 static GenOpFunc1 *gen_op_stmw[] = {
2491 &gen_op_stmw_raw,
2492 &gen_op_stmw_le_raw,
2493 #if defined(TARGET_PPC64)
2494 &gen_op_stmw_64_raw,
2495 &gen_op_stmw_le_64_raw,
2496 #endif
2498 #else
2499 #if defined(TARGET_PPC64)
2500 /* Full system - 64 bits mode */
2501 static GenOpFunc1 *gen_op_lmw[] = {
2502 &gen_op_lmw_user,
2503 &gen_op_lmw_le_user,
2504 &gen_op_lmw_64_user,
2505 &gen_op_lmw_le_64_user,
2506 &gen_op_lmw_kernel,
2507 &gen_op_lmw_le_kernel,
2508 &gen_op_lmw_64_kernel,
2509 &gen_op_lmw_le_64_kernel,
2510 #if defined(TARGET_PPC64H)
2511 &gen_op_lmw_hypv,
2512 &gen_op_lmw_le_hypv,
2513 &gen_op_lmw_64_hypv,
2514 &gen_op_lmw_le_64_hypv,
2515 #endif
2517 static GenOpFunc1 *gen_op_stmw[] = {
2518 &gen_op_stmw_user,
2519 &gen_op_stmw_le_user,
2520 &gen_op_stmw_64_user,
2521 &gen_op_stmw_le_64_user,
2522 &gen_op_stmw_kernel,
2523 &gen_op_stmw_le_kernel,
2524 &gen_op_stmw_64_kernel,
2525 &gen_op_stmw_le_64_kernel,
2526 #if defined(TARGET_PPC64H)
2527 &gen_op_stmw_hypv,
2528 &gen_op_stmw_le_hypv,
2529 &gen_op_stmw_64_hypv,
2530 &gen_op_stmw_le_64_hypv,
2531 #endif
2533 #else
2534 /* Full system - 32 bits mode */
2535 static GenOpFunc1 *gen_op_lmw[] = {
2536 &gen_op_lmw_user,
2537 &gen_op_lmw_le_user,
2538 &gen_op_lmw_kernel,
2539 &gen_op_lmw_le_kernel,
2541 static GenOpFunc1 *gen_op_stmw[] = {
2542 &gen_op_stmw_user,
2543 &gen_op_stmw_le_user,
2544 &gen_op_stmw_kernel,
2545 &gen_op_stmw_le_kernel,
2547 #endif
2548 #endif
2550 /* lmw */
2551 GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
2553 /* NIP cannot be restored if the memory exception comes from an helper */
2554 gen_update_nip(ctx, ctx->nip - 4);
2555 gen_addr_imm_index(ctx, 0);
2556 op_ldstm(lmw, rD(ctx->opcode));
2559 /* stmw */
2560 GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
2562 /* NIP cannot be restored if the memory exception comes from an helper */
2563 gen_update_nip(ctx, ctx->nip - 4);
2564 gen_addr_imm_index(ctx, 0);
2565 op_ldstm(stmw, rS(ctx->opcode));
2568 /*** Integer load and store strings ***/
2569 #define op_ldsts(name, start) (*gen_op_##name[ctx->mem_idx])(start)
2570 #define op_ldstsx(name, rd, ra, rb) (*gen_op_##name[ctx->mem_idx])(rd, ra, rb)
2571 #if defined(CONFIG_USER_ONLY)
2572 /* User-mode only */
2573 static GenOpFunc1 *gen_op_lswi[] = {
2574 &gen_op_lswi_raw,
2575 &gen_op_lswi_le_raw,
2576 #if defined(TARGET_PPC64)
2577 &gen_op_lswi_64_raw,
2578 &gen_op_lswi_le_64_raw,
2579 #endif
2581 static GenOpFunc3 *gen_op_lswx[] = {
2582 &gen_op_lswx_raw,
2583 &gen_op_lswx_le_raw,
2584 #if defined(TARGET_PPC64)
2585 &gen_op_lswx_64_raw,
2586 &gen_op_lswx_le_64_raw,
2587 #endif
2589 static GenOpFunc1 *gen_op_stsw[] = {
2590 &gen_op_stsw_raw,
2591 &gen_op_stsw_le_raw,
2592 #if defined(TARGET_PPC64)
2593 &gen_op_stsw_64_raw,
2594 &gen_op_stsw_le_64_raw,
2595 #endif
2597 #else
2598 #if defined(TARGET_PPC64)
2599 /* Full system - 64 bits mode */
2600 static GenOpFunc1 *gen_op_lswi[] = {
2601 &gen_op_lswi_user,
2602 &gen_op_lswi_le_user,
2603 &gen_op_lswi_64_user,
2604 &gen_op_lswi_le_64_user,
2605 &gen_op_lswi_kernel,
2606 &gen_op_lswi_le_kernel,
2607 &gen_op_lswi_64_kernel,
2608 &gen_op_lswi_le_64_kernel,
2609 #if defined(TARGET_PPC64H)
2610 &gen_op_lswi_hypv,
2611 &gen_op_lswi_le_hypv,
2612 &gen_op_lswi_64_hypv,
2613 &gen_op_lswi_le_64_hypv,
2614 #endif
2616 static GenOpFunc3 *gen_op_lswx[] = {
2617 &gen_op_lswx_user,
2618 &gen_op_lswx_le_user,
2619 &gen_op_lswx_64_user,
2620 &gen_op_lswx_le_64_user,
2621 &gen_op_lswx_kernel,
2622 &gen_op_lswx_le_kernel,
2623 &gen_op_lswx_64_kernel,
2624 &gen_op_lswx_le_64_kernel,
2625 #if defined(TARGET_PPC64H)
2626 &gen_op_lswx_hypv,
2627 &gen_op_lswx_le_hypv,
2628 &gen_op_lswx_64_hypv,
2629 &gen_op_lswx_le_64_hypv,
2630 #endif
2632 static GenOpFunc1 *gen_op_stsw[] = {
2633 &gen_op_stsw_user,
2634 &gen_op_stsw_le_user,
2635 &gen_op_stsw_64_user,
2636 &gen_op_stsw_le_64_user,
2637 &gen_op_stsw_kernel,
2638 &gen_op_stsw_le_kernel,
2639 &gen_op_stsw_64_kernel,
2640 &gen_op_stsw_le_64_kernel,
2641 #if defined(TARGET_PPC64H)
2642 &gen_op_stsw_hypv,
2643 &gen_op_stsw_le_hypv,
2644 &gen_op_stsw_64_hypv,
2645 &gen_op_stsw_le_64_hypv,
2646 #endif
2648 #else
2649 /* Full system - 32 bits mode */
2650 static GenOpFunc1 *gen_op_lswi[] = {
2651 &gen_op_lswi_user,
2652 &gen_op_lswi_le_user,
2653 &gen_op_lswi_kernel,
2654 &gen_op_lswi_le_kernel,
2656 static GenOpFunc3 *gen_op_lswx[] = {
2657 &gen_op_lswx_user,
2658 &gen_op_lswx_le_user,
2659 &gen_op_lswx_kernel,
2660 &gen_op_lswx_le_kernel,
2662 static GenOpFunc1 *gen_op_stsw[] = {
2663 &gen_op_stsw_user,
2664 &gen_op_stsw_le_user,
2665 &gen_op_stsw_kernel,
2666 &gen_op_stsw_le_kernel,
2668 #endif
2669 #endif
2671 /* lswi */
2672 /* PowerPC32 specification says we must generate an exception if
2673 * rA is in the range of registers to be loaded.
2674 * In an other hand, IBM says this is valid, but rA won't be loaded.
2675 * For now, I'll follow the spec...
2677 GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_INTEGER)
2679 int nb = NB(ctx->opcode);
2680 int start = rD(ctx->opcode);
2681 int ra = rA(ctx->opcode);
2682 int nr;
2684 if (nb == 0)
2685 nb = 32;
2686 nr = nb / 4;
2687 if (unlikely(((start + nr) > 32 &&
2688 start <= ra && (start + nr - 32) > ra) ||
2689 ((start + nr) <= 32 && start <= ra && (start + nr) > ra))) {
2690 GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
2691 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_LSWX);
2692 return;
2694 /* NIP cannot be restored if the memory exception comes from an helper */
2695 gen_update_nip(ctx, ctx->nip - 4);
2696 gen_addr_register(ctx);
2697 gen_op_set_T1(nb);
2698 op_ldsts(lswi, start);
2701 /* lswx */
2702 GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_INTEGER)
2704 int ra = rA(ctx->opcode);
2705 int rb = rB(ctx->opcode);
2707 /* NIP cannot be restored if the memory exception comes from an helper */
2708 gen_update_nip(ctx, ctx->nip - 4);
2709 gen_addr_reg_index(ctx);
2710 if (ra == 0) {
2711 ra = rb;
2713 gen_op_load_xer_bc();
2714 op_ldstsx(lswx, rD(ctx->opcode), ra, rb);
2717 /* stswi */
2718 GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_INTEGER)
2720 int nb = NB(ctx->opcode);
2722 /* NIP cannot be restored if the memory exception comes from an helper */
2723 gen_update_nip(ctx, ctx->nip - 4);
2724 gen_addr_register(ctx);
2725 if (nb == 0)
2726 nb = 32;
2727 gen_op_set_T1(nb);
2728 op_ldsts(stsw, rS(ctx->opcode));
2731 /* stswx */
2732 GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_INTEGER)
2734 /* NIP cannot be restored if the memory exception comes from an helper */
2735 gen_update_nip(ctx, ctx->nip - 4);
2736 gen_addr_reg_index(ctx);
2737 gen_op_load_xer_bc();
2738 op_ldsts(stsw, rS(ctx->opcode));
2741 /*** Memory synchronisation ***/
2742 /* eieio */
2743 GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FFF801, PPC_MEM_EIEIO)
2747 /* isync */
2748 GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FFF801, PPC_MEM)
2750 GEN_STOP(ctx);
2753 #define op_lwarx() (*gen_op_lwarx[ctx->mem_idx])()
2754 #define op_stwcx() (*gen_op_stwcx[ctx->mem_idx])()
2755 #if defined(CONFIG_USER_ONLY)
2756 /* User-mode only */
2757 static GenOpFunc *gen_op_lwarx[] = {
2758 &gen_op_lwarx_raw,
2759 &gen_op_lwarx_le_raw,
2760 #if defined(TARGET_PPC64)
2761 &gen_op_lwarx_64_raw,
2762 &gen_op_lwarx_le_64_raw,
2763 #endif
2765 static GenOpFunc *gen_op_stwcx[] = {
2766 &gen_op_stwcx_raw,
2767 &gen_op_stwcx_le_raw,
2768 #if defined(TARGET_PPC64)
2769 &gen_op_stwcx_64_raw,
2770 &gen_op_stwcx_le_64_raw,
2771 #endif
2773 #else
2774 #if defined(TARGET_PPC64)
2775 /* Full system - 64 bits mode */
2776 static GenOpFunc *gen_op_lwarx[] = {
2777 &gen_op_lwarx_user,
2778 &gen_op_lwarx_le_user,
2779 &gen_op_lwarx_64_user,
2780 &gen_op_lwarx_le_64_user,
2781 &gen_op_lwarx_kernel,
2782 &gen_op_lwarx_le_kernel,
2783 &gen_op_lwarx_64_kernel,
2784 &gen_op_lwarx_le_64_kernel,
2785 #if defined(TARGET_PPC64H)
2786 &gen_op_lwarx_hypv,
2787 &gen_op_lwarx_le_hypv,
2788 &gen_op_lwarx_64_hypv,
2789 &gen_op_lwarx_le_64_hypv,
2790 #endif
2792 static GenOpFunc *gen_op_stwcx[] = {
2793 &gen_op_stwcx_user,
2794 &gen_op_stwcx_le_user,
2795 &gen_op_stwcx_64_user,
2796 &gen_op_stwcx_le_64_user,
2797 &gen_op_stwcx_kernel,
2798 &gen_op_stwcx_le_kernel,
2799 &gen_op_stwcx_64_kernel,
2800 &gen_op_stwcx_le_64_kernel,
2801 #if defined(TARGET_PPC64H)
2802 &gen_op_stwcx_hypv,
2803 &gen_op_stwcx_le_hypv,
2804 &gen_op_stwcx_64_hypv,
2805 &gen_op_stwcx_le_64_hypv,
2806 #endif
2808 #else
2809 /* Full system - 32 bits mode */
2810 static GenOpFunc *gen_op_lwarx[] = {
2811 &gen_op_lwarx_user,
2812 &gen_op_lwarx_le_user,
2813 &gen_op_lwarx_kernel,
2814 &gen_op_lwarx_le_kernel,
2816 static GenOpFunc *gen_op_stwcx[] = {
2817 &gen_op_stwcx_user,
2818 &gen_op_stwcx_le_user,
2819 &gen_op_stwcx_kernel,
2820 &gen_op_stwcx_le_kernel,
2822 #endif
2823 #endif
2825 /* lwarx */
2826 GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000001, PPC_RES)
2828 /* NIP cannot be restored if the memory exception comes from an helper */
2829 gen_update_nip(ctx, ctx->nip - 4);
2830 gen_addr_reg_index(ctx);
2831 op_lwarx();
2832 gen_op_store_T1_gpr(rD(ctx->opcode));
2835 /* stwcx. */
2836 GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES)
2838 /* NIP cannot be restored if the memory exception comes from an helper */
2839 gen_update_nip(ctx, ctx->nip - 4);
2840 gen_addr_reg_index(ctx);
2841 gen_op_load_gpr_T1(rS(ctx->opcode));
2842 op_stwcx();
2845 #if defined(TARGET_PPC64)
2846 #define op_ldarx() (*gen_op_ldarx[ctx->mem_idx])()
2847 #define op_stdcx() (*gen_op_stdcx[ctx->mem_idx])()
2848 #if defined(CONFIG_USER_ONLY)
2849 /* User-mode only */
2850 static GenOpFunc *gen_op_ldarx[] = {
2851 &gen_op_ldarx_raw,
2852 &gen_op_ldarx_le_raw,
2853 &gen_op_ldarx_64_raw,
2854 &gen_op_ldarx_le_64_raw,
2856 static GenOpFunc *gen_op_stdcx[] = {
2857 &gen_op_stdcx_raw,
2858 &gen_op_stdcx_le_raw,
2859 &gen_op_stdcx_64_raw,
2860 &gen_op_stdcx_le_64_raw,
2862 #else
2863 /* Full system */
2864 static GenOpFunc *gen_op_ldarx[] = {
2865 &gen_op_ldarx_user,
2866 &gen_op_ldarx_le_user,
2867 &gen_op_ldarx_64_user,
2868 &gen_op_ldarx_le_64_user,
2869 &gen_op_ldarx_kernel,
2870 &gen_op_ldarx_le_kernel,
2871 &gen_op_ldarx_64_kernel,
2872 &gen_op_ldarx_le_64_kernel,
2873 #if defined(TARGET_PPC64H)
2874 &gen_op_ldarx_hypv,
2875 &gen_op_ldarx_le_hypv,
2876 &gen_op_ldarx_64_hypv,
2877 &gen_op_ldarx_le_64_hypv,
2878 #endif
2880 static GenOpFunc *gen_op_stdcx[] = {
2881 &gen_op_stdcx_user,
2882 &gen_op_stdcx_le_user,
2883 &gen_op_stdcx_64_user,
2884 &gen_op_stdcx_le_64_user,
2885 &gen_op_stdcx_kernel,
2886 &gen_op_stdcx_le_kernel,
2887 &gen_op_stdcx_64_kernel,
2888 &gen_op_stdcx_le_64_kernel,
2889 #if defined(TARGET_PPC64H)
2890 &gen_op_stdcx_hypv,
2891 &gen_op_stdcx_le_hypv,
2892 &gen_op_stdcx_64_hypv,
2893 &gen_op_stdcx_le_64_hypv,
2894 #endif
2896 #endif
2898 /* ldarx */
2899 GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000001, PPC_64B)
2901 /* NIP cannot be restored if the memory exception comes from an helper */
2902 gen_update_nip(ctx, ctx->nip - 4);
2903 gen_addr_reg_index(ctx);
2904 op_ldarx();
2905 gen_op_store_T1_gpr(rD(ctx->opcode));
2908 /* stdcx. */
2909 GEN_HANDLER2(stdcx_, "stdcx.", 0x1F, 0x16, 0x06, 0x00000000, PPC_64B)
2911 /* NIP cannot be restored if the memory exception comes from an helper */
2912 gen_update_nip(ctx, ctx->nip - 4);
2913 gen_addr_reg_index(ctx);
2914 gen_op_load_gpr_T1(rS(ctx->opcode));
2915 op_stdcx();
2917 #endif /* defined(TARGET_PPC64) */
2919 /* sync */
2920 GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x039FF801, PPC_MEM_SYNC)
2924 /* wait */
2925 GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x03FFF801, PPC_WAIT)
2927 /* Stop translation, as the CPU is supposed to sleep from now */
2928 gen_op_wait();
2929 GEN_EXCP(ctx, EXCP_HLT, 1);
2932 /*** Floating-point load ***/
2933 #define GEN_LDF(width, opc, type) \
2934 GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, type) \
2936 if (unlikely(!ctx->fpu_enabled)) { \
2937 GEN_EXCP_NO_FP(ctx); \
2938 return; \
2940 gen_addr_imm_index(ctx, 0); \
2941 op_ldst(l##width); \
2942 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
2945 #define GEN_LDUF(width, opc, type) \
2946 GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, type) \
2948 if (unlikely(!ctx->fpu_enabled)) { \
2949 GEN_EXCP_NO_FP(ctx); \
2950 return; \
2952 if (unlikely(rA(ctx->opcode) == 0)) { \
2953 GEN_EXCP_INVAL(ctx); \
2954 return; \
2956 gen_addr_imm_index(ctx, 0); \
2957 op_ldst(l##width); \
2958 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
2959 gen_op_store_T0_gpr(rA(ctx->opcode)); \
2962 #define GEN_LDUXF(width, opc, type) \
2963 GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, type) \
2965 if (unlikely(!ctx->fpu_enabled)) { \
2966 GEN_EXCP_NO_FP(ctx); \
2967 return; \
2969 if (unlikely(rA(ctx->opcode) == 0)) { \
2970 GEN_EXCP_INVAL(ctx); \
2971 return; \
2973 gen_addr_reg_index(ctx); \
2974 op_ldst(l##width); \
2975 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
2976 gen_op_store_T0_gpr(rA(ctx->opcode)); \
2979 #define GEN_LDXF(width, opc2, opc3, type) \
2980 GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, type) \
2982 if (unlikely(!ctx->fpu_enabled)) { \
2983 GEN_EXCP_NO_FP(ctx); \
2984 return; \
2986 gen_addr_reg_index(ctx); \
2987 op_ldst(l##width); \
2988 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
2991 #define GEN_LDFS(width, op, type) \
2992 OP_LD_TABLE(width); \
2993 GEN_LDF(width, op | 0x20, type); \
2994 GEN_LDUF(width, op | 0x21, type); \
2995 GEN_LDUXF(width, op | 0x01, type); \
2996 GEN_LDXF(width, 0x17, op | 0x00, type)
2998 /* lfd lfdu lfdux lfdx */
2999 GEN_LDFS(fd, 0x12, PPC_FLOAT);
3000 /* lfs lfsu lfsux lfsx */
3001 GEN_LDFS(fs, 0x10, PPC_FLOAT);
3003 /*** Floating-point store ***/
3004 #define GEN_STF(width, opc, type) \
3005 GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, type) \
3007 if (unlikely(!ctx->fpu_enabled)) { \
3008 GEN_EXCP_NO_FP(ctx); \
3009 return; \
3011 gen_addr_imm_index(ctx, 0); \
3012 gen_op_load_fpr_FT0(rS(ctx->opcode)); \
3013 op_ldst(st##width); \
3016 #define GEN_STUF(width, opc, type) \
3017 GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, type) \
3019 if (unlikely(!ctx->fpu_enabled)) { \
3020 GEN_EXCP_NO_FP(ctx); \
3021 return; \
3023 if (unlikely(rA(ctx->opcode) == 0)) { \
3024 GEN_EXCP_INVAL(ctx); \
3025 return; \
3027 gen_addr_imm_index(ctx, 0); \
3028 gen_op_load_fpr_FT0(rS(ctx->opcode)); \
3029 op_ldst(st##width); \
3030 gen_op_store_T0_gpr(rA(ctx->opcode)); \
3033 #define GEN_STUXF(width, opc, type) \
3034 GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, type) \
3036 if (unlikely(!ctx->fpu_enabled)) { \
3037 GEN_EXCP_NO_FP(ctx); \
3038 return; \
3040 if (unlikely(rA(ctx->opcode) == 0)) { \
3041 GEN_EXCP_INVAL(ctx); \
3042 return; \
3044 gen_addr_reg_index(ctx); \
3045 gen_op_load_fpr_FT0(rS(ctx->opcode)); \
3046 op_ldst(st##width); \
3047 gen_op_store_T0_gpr(rA(ctx->opcode)); \
3050 #define GEN_STXF(width, opc2, opc3, type) \
3051 GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, type) \
3053 if (unlikely(!ctx->fpu_enabled)) { \
3054 GEN_EXCP_NO_FP(ctx); \
3055 return; \
3057 gen_addr_reg_index(ctx); \
3058 gen_op_load_fpr_FT0(rS(ctx->opcode)); \
3059 op_ldst(st##width); \
3062 #define GEN_STFS(width, op, type) \
3063 OP_ST_TABLE(width); \
3064 GEN_STF(width, op | 0x20, type); \
3065 GEN_STUF(width, op | 0x21, type); \
3066 GEN_STUXF(width, op | 0x01, type); \
3067 GEN_STXF(width, 0x17, op | 0x00, type)
3069 /* stfd stfdu stfdux stfdx */
3070 GEN_STFS(fd, 0x16, PPC_FLOAT);
3071 /* stfs stfsu stfsux stfsx */
3072 GEN_STFS(fs, 0x14, PPC_FLOAT);
3074 /* Optional: */
3075 /* stfiwx */
3076 OP_ST_TABLE(fiwx);
3077 GEN_STXF(fiwx, 0x17, 0x1E, PPC_FLOAT_STFIWX);
3079 /*** Branch ***/
3080 static always_inline void gen_goto_tb (DisasContext *ctx, int n,
3081 target_ulong dest)
3083 TranslationBlock *tb;
3084 tb = ctx->tb;
3085 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
3086 if (n == 0)
3087 gen_op_goto_tb0(TBPARAM(tb));
3088 else
3089 gen_op_goto_tb1(TBPARAM(tb));
3090 gen_set_T1(dest);
3091 #if defined(TARGET_PPC64)
3092 if (ctx->sf_mode)
3093 gen_op_b_T1_64();
3094 else
3095 #endif
3096 gen_op_b_T1();
3097 gen_op_set_T0((long)tb + n);
3098 if (ctx->singlestep_enabled)
3099 gen_op_debug();
3100 gen_op_exit_tb();
3101 } else {
3102 gen_set_T1(dest);
3103 #if defined(TARGET_PPC64)
3104 if (ctx->sf_mode)
3105 gen_op_b_T1_64();
3106 else
3107 #endif
3108 gen_op_b_T1();
3109 gen_op_reset_T0();
3110 if (ctx->singlestep_enabled)
3111 gen_op_debug();
3112 gen_op_exit_tb();
3116 static always_inline void gen_setlr (DisasContext *ctx, target_ulong nip)
3118 #if defined(TARGET_PPC64)
3119 if (ctx->sf_mode != 0 && (nip >> 32))
3120 gen_op_setlr_64(ctx->nip >> 32, ctx->nip);
3121 else
3122 #endif
3123 gen_op_setlr(ctx->nip);
3126 /* b ba bl bla */
3127 GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
3129 target_ulong li, target;
3131 /* sign extend LI */
3132 #if defined(TARGET_PPC64)
3133 if (ctx->sf_mode)
3134 li = ((int64_t)LI(ctx->opcode) << 38) >> 38;
3135 else
3136 #endif
3137 li = ((int32_t)LI(ctx->opcode) << 6) >> 6;
3138 if (likely(AA(ctx->opcode) == 0))
3139 target = ctx->nip + li - 4;
3140 else
3141 target = li;
3142 #if defined(TARGET_PPC64)
3143 if (!ctx->sf_mode)
3144 target = (uint32_t)target;
3145 #endif
3146 if (LK(ctx->opcode))
3147 gen_setlr(ctx, ctx->nip);
3148 gen_goto_tb(ctx, 0, target);
3149 ctx->exception = POWERPC_EXCP_BRANCH;
3152 #define BCOND_IM 0
3153 #define BCOND_LR 1
3154 #define BCOND_CTR 2
3156 static always_inline void gen_bcond (DisasContext *ctx, int type)
3158 target_ulong target = 0;
3159 target_ulong li;
3160 uint32_t bo = BO(ctx->opcode);
3161 uint32_t bi = BI(ctx->opcode);
3162 uint32_t mask;
3164 if ((bo & 0x4) == 0)
3165 gen_op_dec_ctr();
3166 switch(type) {
3167 case BCOND_IM:
3168 li = (target_long)((int16_t)(BD(ctx->opcode)));
3169 if (likely(AA(ctx->opcode) == 0)) {
3170 target = ctx->nip + li - 4;
3171 } else {
3172 target = li;
3174 #if defined(TARGET_PPC64)
3175 if (!ctx->sf_mode)
3176 target = (uint32_t)target;
3177 #endif
3178 break;
3179 case BCOND_CTR:
3180 gen_op_movl_T1_ctr();
3181 break;
3182 default:
3183 case BCOND_LR:
3184 gen_op_movl_T1_lr();
3185 break;
3187 if (LK(ctx->opcode))
3188 gen_setlr(ctx, ctx->nip);
3189 if (bo & 0x10) {
3190 /* No CR condition */
3191 switch (bo & 0x6) {
3192 case 0:
3193 #if defined(TARGET_PPC64)
3194 if (ctx->sf_mode)
3195 gen_op_test_ctr_64();
3196 else
3197 #endif
3198 gen_op_test_ctr();
3199 break;
3200 case 2:
3201 #if defined(TARGET_PPC64)
3202 if (ctx->sf_mode)
3203 gen_op_test_ctrz_64();
3204 else
3205 #endif
3206 gen_op_test_ctrz();
3207 break;
3208 default:
3209 case 4:
3210 case 6:
3211 if (type == BCOND_IM) {
3212 gen_goto_tb(ctx, 0, target);
3213 goto out;
3214 } else {
3215 #if defined(TARGET_PPC64)
3216 if (ctx->sf_mode)
3217 gen_op_b_T1_64();
3218 else
3219 #endif
3220 gen_op_b_T1();
3221 gen_op_reset_T0();
3222 goto no_test;
3224 break;
3226 } else {
3227 mask = 1 << (3 - (bi & 0x03));
3228 gen_op_load_crf_T0(bi >> 2);
3229 if (bo & 0x8) {
3230 switch (bo & 0x6) {
3231 case 0:
3232 #if defined(TARGET_PPC64)
3233 if (ctx->sf_mode)
3234 gen_op_test_ctr_true_64(mask);
3235 else
3236 #endif
3237 gen_op_test_ctr_true(mask);
3238 break;
3239 case 2:
3240 #if defined(TARGET_PPC64)
3241 if (ctx->sf_mode)
3242 gen_op_test_ctrz_true_64(mask);
3243 else
3244 #endif
3245 gen_op_test_ctrz_true(mask);
3246 break;
3247 default:
3248 case 4:
3249 case 6:
3250 gen_op_test_true(mask);
3251 break;
3253 } else {
3254 switch (bo & 0x6) {
3255 case 0:
3256 #if defined(TARGET_PPC64)
3257 if (ctx->sf_mode)
3258 gen_op_test_ctr_false_64(mask);
3259 else
3260 #endif
3261 gen_op_test_ctr_false(mask);
3262 break;
3263 case 2:
3264 #if defined(TARGET_PPC64)
3265 if (ctx->sf_mode)
3266 gen_op_test_ctrz_false_64(mask);
3267 else
3268 #endif
3269 gen_op_test_ctrz_false(mask);
3270 break;
3271 default:
3272 case 4:
3273 case 6:
3274 gen_op_test_false(mask);
3275 break;
3279 if (type == BCOND_IM) {
3280 int l1 = gen_new_label();
3281 gen_op_jz_T0(l1);
3282 gen_goto_tb(ctx, 0, target);
3283 gen_set_label(l1);
3284 gen_goto_tb(ctx, 1, ctx->nip);
3285 } else {
3286 #if defined(TARGET_PPC64)
3287 if (ctx->sf_mode)
3288 gen_op_btest_T1_64(ctx->nip >> 32, ctx->nip);
3289 else
3290 #endif
3291 gen_op_btest_T1(ctx->nip);
3292 gen_op_reset_T0();
3293 no_test:
3294 if (ctx->singlestep_enabled)
3295 gen_op_debug();
3296 gen_op_exit_tb();
3298 out:
3299 ctx->exception = POWERPC_EXCP_BRANCH;
3302 GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
3304 gen_bcond(ctx, BCOND_IM);
3307 GEN_HANDLER(bcctr, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW)
3309 gen_bcond(ctx, BCOND_CTR);
3312 GEN_HANDLER(bclr, 0x13, 0x10, 0x00, 0x00000000, PPC_FLOW)
3314 gen_bcond(ctx, BCOND_LR);
3317 /*** Condition register logical ***/
3318 #define GEN_CRLOGIC(op, opc) \
3319 GEN_HANDLER(cr##op, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER) \
3321 gen_op_load_crf_T0(crbA(ctx->opcode) >> 2); \
3322 gen_op_getbit_T0(3 - (crbA(ctx->opcode) & 0x03)); \
3323 gen_op_load_crf_T1(crbB(ctx->opcode) >> 2); \
3324 gen_op_getbit_T1(3 - (crbB(ctx->opcode) & 0x03)); \
3325 gen_op_##op(); \
3326 gen_op_load_crf_T1(crbD(ctx->opcode) >> 2); \
3327 gen_op_setcrfbit(~(1 << (3 - (crbD(ctx->opcode) & 0x03))), \
3328 3 - (crbD(ctx->opcode) & 0x03)); \
3329 gen_op_store_T1_crf(crbD(ctx->opcode) >> 2); \
3332 /* crand */
3333 GEN_CRLOGIC(and, 0x08);
3334 /* crandc */
3335 GEN_CRLOGIC(andc, 0x04);
3336 /* creqv */
3337 GEN_CRLOGIC(eqv, 0x09);
3338 /* crnand */
3339 GEN_CRLOGIC(nand, 0x07);
3340 /* crnor */
3341 GEN_CRLOGIC(nor, 0x01);
3342 /* cror */
3343 GEN_CRLOGIC(or, 0x0E);
3344 /* crorc */
3345 GEN_CRLOGIC(orc, 0x0D);
3346 /* crxor */
3347 GEN_CRLOGIC(xor, 0x06);
3348 /* mcrf */
3349 GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER)
3351 gen_op_load_crf_T0(crfS(ctx->opcode));
3352 gen_op_store_T0_crf(crfD(ctx->opcode));
3355 /*** System linkage ***/
3356 /* rfi (supervisor only) */
3357 GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW)
3359 #if defined(CONFIG_USER_ONLY)
3360 GEN_EXCP_PRIVOPC(ctx);
3361 #else
3362 /* Restore CPU state */
3363 if (unlikely(!ctx->supervisor)) {
3364 GEN_EXCP_PRIVOPC(ctx);
3365 return;
3367 gen_op_rfi();
3368 GEN_SYNC(ctx);
3369 #endif
3372 #if defined(TARGET_PPC64)
3373 GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B)
3375 #if defined(CONFIG_USER_ONLY)
3376 GEN_EXCP_PRIVOPC(ctx);
3377 #else
3378 /* Restore CPU state */
3379 if (unlikely(!ctx->supervisor)) {
3380 GEN_EXCP_PRIVOPC(ctx);
3381 return;
3383 gen_op_rfid();
3384 GEN_SYNC(ctx);
3385 #endif
3387 #endif
3389 #if defined(TARGET_PPC64H)
3390 GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64B)
3392 #if defined(CONFIG_USER_ONLY)
3393 GEN_EXCP_PRIVOPC(ctx);
3394 #else
3395 /* Restore CPU state */
3396 if (unlikely(ctx->supervisor <= 1)) {
3397 GEN_EXCP_PRIVOPC(ctx);
3398 return;
3400 gen_op_hrfid();
3401 GEN_SYNC(ctx);
3402 #endif
3404 #endif
3406 /* sc */
3407 #if defined(CONFIG_USER_ONLY)
3408 #define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
3409 #else
3410 #define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
3411 #endif
3412 GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFF01D, PPC_FLOW)
3414 uint32_t lev;
3416 lev = (ctx->opcode >> 5) & 0x7F;
3417 GEN_EXCP(ctx, POWERPC_SYSCALL, lev);
3420 /*** Trap ***/
3421 /* tw */
3422 GEN_HANDLER(tw, 0x1F, 0x04, 0x00, 0x00000001, PPC_FLOW)
3424 gen_op_load_gpr_T0(rA(ctx->opcode));
3425 gen_op_load_gpr_T1(rB(ctx->opcode));
3426 /* Update the nip since this might generate a trap exception */
3427 gen_update_nip(ctx, ctx->nip);
3428 gen_op_tw(TO(ctx->opcode));
3431 /* twi */
3432 GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
3434 gen_op_load_gpr_T0(rA(ctx->opcode));
3435 gen_set_T1(SIMM(ctx->opcode));
3436 /* Update the nip since this might generate a trap exception */
3437 gen_update_nip(ctx, ctx->nip);
3438 gen_op_tw(TO(ctx->opcode));
3441 #if defined(TARGET_PPC64)
3442 /* td */
3443 GEN_HANDLER(td, 0x1F, 0x04, 0x02, 0x00000001, PPC_64B)
3445 gen_op_load_gpr_T0(rA(ctx->opcode));
3446 gen_op_load_gpr_T1(rB(ctx->opcode));
3447 /* Update the nip since this might generate a trap exception */
3448 gen_update_nip(ctx, ctx->nip);
3449 gen_op_td(TO(ctx->opcode));
3452 /* tdi */
3453 GEN_HANDLER(tdi, 0x02, 0xFF, 0xFF, 0x00000000, PPC_64B)
3455 gen_op_load_gpr_T0(rA(ctx->opcode));
3456 gen_set_T1(SIMM(ctx->opcode));
3457 /* Update the nip since this might generate a trap exception */
3458 gen_update_nip(ctx, ctx->nip);
3459 gen_op_td(TO(ctx->opcode));
3461 #endif
3463 /*** Processor control ***/
3464 /* mcrxr */
3465 GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC)
3467 gen_op_load_xer_cr();
3468 gen_op_store_T0_crf(crfD(ctx->opcode));
3469 gen_op_clear_xer_ov();
3470 gen_op_clear_xer_ca();
3473 /* mfcr */
3474 GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x00000801, PPC_MISC)
3476 uint32_t crm, crn;
3478 if (likely(ctx->opcode & 0x00100000)) {
3479 crm = CRM(ctx->opcode);
3480 if (likely((crm ^ (crm - 1)) == 0)) {
3481 crn = ffs(crm);
3482 gen_op_load_cro(7 - crn);
3484 } else {
3485 gen_op_load_cr();
3487 gen_op_store_T0_gpr(rD(ctx->opcode));
3490 /* mfmsr */
3491 GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC)
3493 #if defined(CONFIG_USER_ONLY)
3494 GEN_EXCP_PRIVREG(ctx);
3495 #else
3496 if (unlikely(!ctx->supervisor)) {
3497 GEN_EXCP_PRIVREG(ctx);
3498 return;
3500 gen_op_load_msr();
3501 gen_op_store_T0_gpr(rD(ctx->opcode));
3502 #endif
3505 #if 1
3506 #define SPR_NOACCESS ((void *)(-1))
3507 #else
3508 static void spr_noaccess (void *opaque, int sprn)
3510 sprn = ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
3511 printf("ERROR: try to access SPR %d !\n", sprn);
3513 #define SPR_NOACCESS (&spr_noaccess)
3514 #endif
3516 /* mfspr */
3517 static always_inline void gen_op_mfspr (DisasContext *ctx)
3519 void (*read_cb)(void *opaque, int sprn);
3520 uint32_t sprn = SPR(ctx->opcode);
3522 #if !defined(CONFIG_USER_ONLY)
3523 #if defined(TARGET_PPC64H)
3524 if (ctx->supervisor == 2)
3525 read_cb = ctx->spr_cb[sprn].hea_read;
3526 else
3527 #endif
3528 if (ctx->supervisor)
3529 read_cb = ctx->spr_cb[sprn].oea_read;
3530 else
3531 #endif
3532 read_cb = ctx->spr_cb[sprn].uea_read;
3533 if (likely(read_cb != NULL)) {
3534 if (likely(read_cb != SPR_NOACCESS)) {
3535 (*read_cb)(ctx, sprn);
3536 gen_op_store_T0_gpr(rD(ctx->opcode));
3537 } else {
3538 /* Privilege exception */
3539 if (loglevel != 0) {
3540 fprintf(logfile, "Trying to read privileged spr %d %03x\n",
3541 sprn, sprn);
3543 printf("Trying to read privileged spr %d %03x\n", sprn, sprn);
3544 GEN_EXCP_PRIVREG(ctx);
3546 } else {
3547 /* Not defined */
3548 if (loglevel != 0) {
3549 fprintf(logfile, "Trying to read invalid spr %d %03x\n",
3550 sprn, sprn);
3552 printf("Trying to read invalid spr %d %03x\n", sprn, sprn);
3553 GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
3554 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_SPR);
3558 GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC)
3560 gen_op_mfspr(ctx);
3563 /* mftb */
3564 GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MFTB)
3566 gen_op_mfspr(ctx);
3569 /* mtcrf */
3570 GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC)
3572 uint32_t crm, crn;
3574 gen_op_load_gpr_T0(rS(ctx->opcode));
3575 crm = CRM(ctx->opcode);
3576 if (likely((ctx->opcode & 0x00100000) || (crm ^ (crm - 1)) == 0)) {
3577 crn = ffs(crm);
3578 gen_op_srli_T0(crn * 4);
3579 gen_op_andi_T0(0xF);
3580 gen_op_store_cro(7 - crn);
3581 } else {
3582 gen_op_store_cr(crm);
3586 /* mtmsr */
3587 #if defined(TARGET_PPC64)
3588 GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001EF801, PPC_64B)
3590 #if defined(CONFIG_USER_ONLY)
3591 GEN_EXCP_PRIVREG(ctx);
3592 #else
3593 if (unlikely(!ctx->supervisor)) {
3594 GEN_EXCP_PRIVREG(ctx);
3595 return;
3597 gen_op_load_gpr_T0(rS(ctx->opcode));
3598 if (ctx->opcode & 0x00010000) {
3599 /* Special form that does not need any synchronisation */
3600 gen_op_update_riee();
3601 } else {
3602 /* XXX: we need to update nip before the store
3603 * if we enter power saving mode, we will exit the loop
3604 * directly from ppc_store_msr
3606 gen_update_nip(ctx, ctx->nip);
3607 gen_op_store_msr();
3608 /* Must stop the translation as machine state (may have) changed */
3609 /* Note that mtmsr is not always defined as context-synchronizing */
3610 ctx->exception = POWERPC_EXCP_STOP;
3612 #endif
3614 #endif
3616 GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC)
3618 #if defined(CONFIG_USER_ONLY)
3619 GEN_EXCP_PRIVREG(ctx);
3620 #else
3621 if (unlikely(!ctx->supervisor)) {
3622 GEN_EXCP_PRIVREG(ctx);
3623 return;
3625 gen_op_load_gpr_T0(rS(ctx->opcode));
3626 if (ctx->opcode & 0x00010000) {
3627 /* Special form that does not need any synchronisation */
3628 gen_op_update_riee();
3629 } else {
3630 /* XXX: we need to update nip before the store
3631 * if we enter power saving mode, we will exit the loop
3632 * directly from ppc_store_msr
3634 gen_update_nip(ctx, ctx->nip);
3635 #if defined(TARGET_PPC64)
3636 if (!ctx->sf_mode)
3637 gen_op_store_msr_32();
3638 else
3639 #endif
3640 gen_op_store_msr();
3641 /* Must stop the translation as machine state (may have) changed */
3642 /* Note that mtmsrd is not always defined as context-synchronizing */
3643 ctx->exception = POWERPC_EXCP_STOP;
3645 #endif
3648 /* mtspr */
3649 GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC)
3651 void (*write_cb)(void *opaque, int sprn);
3652 uint32_t sprn = SPR(ctx->opcode);
3654 #if !defined(CONFIG_USER_ONLY)
3655 #if defined(TARGET_PPC64H)
3656 if (ctx->supervisor == 2)
3657 write_cb = ctx->spr_cb[sprn].hea_write;
3658 else
3659 #endif
3660 if (ctx->supervisor)
3661 write_cb = ctx->spr_cb[sprn].oea_write;
3662 else
3663 #endif
3664 write_cb = ctx->spr_cb[sprn].uea_write;
3665 if (likely(write_cb != NULL)) {
3666 if (likely(write_cb != SPR_NOACCESS)) {
3667 gen_op_load_gpr_T0(rS(ctx->opcode));
3668 (*write_cb)(ctx, sprn);
3669 } else {
3670 /* Privilege exception */
3671 if (loglevel != 0) {
3672 fprintf(logfile, "Trying to write privileged spr %d %03x\n",
3673 sprn, sprn);
3675 printf("Trying to write privileged spr %d %03x\n", sprn, sprn);
3676 GEN_EXCP_PRIVREG(ctx);
3678 } else {
3679 /* Not defined */
3680 if (loglevel != 0) {
3681 fprintf(logfile, "Trying to write invalid spr %d %03x\n",
3682 sprn, sprn);
3684 printf("Trying to write invalid spr %d %03x\n", sprn, sprn);
3685 GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
3686 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_SPR);
3690 /*** Cache management ***/
3691 /* dcbf */
3692 GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03C00001, PPC_CACHE)
3694 /* XXX: specification says this is treated as a load by the MMU */
3695 gen_addr_reg_index(ctx);
3696 op_ldst(lbz);
3699 /* dcbi (Supervisor only) */
3700 GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE)
3702 #if defined(CONFIG_USER_ONLY)
3703 GEN_EXCP_PRIVOPC(ctx);
3704 #else
3705 if (unlikely(!ctx->supervisor)) {
3706 GEN_EXCP_PRIVOPC(ctx);
3707 return;
3709 gen_addr_reg_index(ctx);
3710 /* XXX: specification says this should be treated as a store by the MMU */
3711 op_ldst(lbz);
3712 op_ldst(stb);
3713 #endif
3716 /* dcdst */
3717 GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE)
3719 /* XXX: specification say this is treated as a load by the MMU */
3720 gen_addr_reg_index(ctx);
3721 op_ldst(lbz);
3724 /* dcbt */
3725 GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x02000001, PPC_CACHE)
3727 /* interpreted as no-op */
3728 /* XXX: specification say this is treated as a load by the MMU
3729 * but does not generate any exception
3733 /* dcbtst */
3734 GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x02000001, PPC_CACHE)
3736 /* interpreted as no-op */
3737 /* XXX: specification say this is treated as a load by the MMU
3738 * but does not generate any exception
3742 /* dcbz */
3743 #define op_dcbz(n) (*gen_op_dcbz[n][ctx->mem_idx])()
3744 #if defined(CONFIG_USER_ONLY)
3745 /* User-mode only */
3746 static GenOpFunc *gen_op_dcbz[4][4] = {
3748 &gen_op_dcbz_l32_raw,
3749 &gen_op_dcbz_l32_raw,
3750 #if defined(TARGET_PPC64)
3751 &gen_op_dcbz_l32_64_raw,
3752 &gen_op_dcbz_l32_64_raw,
3753 #endif
3756 &gen_op_dcbz_l64_raw,
3757 &gen_op_dcbz_l64_raw,
3758 #if defined(TARGET_PPC64)
3759 &gen_op_dcbz_l64_64_raw,
3760 &gen_op_dcbz_l64_64_raw,
3761 #endif
3764 &gen_op_dcbz_l128_raw,
3765 &gen_op_dcbz_l128_raw,
3766 #if defined(TARGET_PPC64)
3767 &gen_op_dcbz_l128_64_raw,
3768 &gen_op_dcbz_l128_64_raw,
3769 #endif
3772 &gen_op_dcbz_raw,
3773 &gen_op_dcbz_raw,
3774 #if defined(TARGET_PPC64)
3775 &gen_op_dcbz_64_raw,
3776 &gen_op_dcbz_64_raw,
3777 #endif
3780 #else
3781 #if defined(TARGET_PPC64)
3782 /* Full system - 64 bits mode */
3783 static GenOpFunc *gen_op_dcbz[4][12] = {
3785 &gen_op_dcbz_l32_user,
3786 &gen_op_dcbz_l32_user,
3787 &gen_op_dcbz_l32_64_user,
3788 &gen_op_dcbz_l32_64_user,
3789 &gen_op_dcbz_l32_kernel,
3790 &gen_op_dcbz_l32_kernel,
3791 &gen_op_dcbz_l32_64_kernel,
3792 &gen_op_dcbz_l32_64_kernel,
3793 #if defined(TARGET_PPC64H)
3794 &gen_op_dcbz_l32_hypv,
3795 &gen_op_dcbz_l32_hypv,
3796 &gen_op_dcbz_l32_64_hypv,
3797 &gen_op_dcbz_l32_64_hypv,
3798 #endif
3801 &gen_op_dcbz_l64_user,
3802 &gen_op_dcbz_l64_user,
3803 &gen_op_dcbz_l64_64_user,
3804 &gen_op_dcbz_l64_64_user,
3805 &gen_op_dcbz_l64_kernel,
3806 &gen_op_dcbz_l64_kernel,
3807 &gen_op_dcbz_l64_64_kernel,
3808 &gen_op_dcbz_l64_64_kernel,
3809 #if defined(TARGET_PPC64H)
3810 &gen_op_dcbz_l64_hypv,
3811 &gen_op_dcbz_l64_hypv,
3812 &gen_op_dcbz_l64_64_hypv,
3813 &gen_op_dcbz_l64_64_hypv,
3814 #endif
3817 &gen_op_dcbz_l128_user,
3818 &gen_op_dcbz_l128_user,
3819 &gen_op_dcbz_l128_64_user,
3820 &gen_op_dcbz_l128_64_user,
3821 &gen_op_dcbz_l128_kernel,
3822 &gen_op_dcbz_l128_kernel,
3823 &gen_op_dcbz_l128_64_kernel,
3824 &gen_op_dcbz_l128_64_kernel,
3825 #if defined(TARGET_PPC64H)
3826 &gen_op_dcbz_l128_hypv,
3827 &gen_op_dcbz_l128_hypv,
3828 &gen_op_dcbz_l128_64_hypv,
3829 &gen_op_dcbz_l128_64_hypv,
3830 #endif
3833 &gen_op_dcbz_user,
3834 &gen_op_dcbz_user,
3835 &gen_op_dcbz_64_user,
3836 &gen_op_dcbz_64_user,
3837 &gen_op_dcbz_kernel,
3838 &gen_op_dcbz_kernel,
3839 &gen_op_dcbz_64_kernel,
3840 &gen_op_dcbz_64_kernel,
3841 #if defined(TARGET_PPC64H)
3842 &gen_op_dcbz_hypv,
3843 &gen_op_dcbz_hypv,
3844 &gen_op_dcbz_64_hypv,
3845 &gen_op_dcbz_64_hypv,
3846 #endif
3849 #else
3850 /* Full system - 32 bits mode */
3851 static GenOpFunc *gen_op_dcbz[4][4] = {
3853 &gen_op_dcbz_l32_user,
3854 &gen_op_dcbz_l32_user,
3855 &gen_op_dcbz_l32_kernel,
3856 &gen_op_dcbz_l32_kernel,
3859 &gen_op_dcbz_l64_user,
3860 &gen_op_dcbz_l64_user,
3861 &gen_op_dcbz_l64_kernel,
3862 &gen_op_dcbz_l64_kernel,
3865 &gen_op_dcbz_l128_user,
3866 &gen_op_dcbz_l128_user,
3867 &gen_op_dcbz_l128_kernel,
3868 &gen_op_dcbz_l128_kernel,
3871 &gen_op_dcbz_user,
3872 &gen_op_dcbz_user,
3873 &gen_op_dcbz_kernel,
3874 &gen_op_dcbz_kernel,
3877 #endif
3878 #endif
3880 static always_inline void handler_dcbz (DisasContext *ctx,
3881 int dcache_line_size)
3883 int n;
3885 switch (dcache_line_size) {
3886 case 32:
3887 n = 0;
3888 break;
3889 case 64:
3890 n = 1;
3891 break;
3892 case 128:
3893 n = 2;
3894 break;
3895 default:
3896 n = 3;
3897 break;
3899 op_dcbz(n);
3902 GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03E00001, PPC_CACHE_DCBZ)
3904 gen_addr_reg_index(ctx);
3905 handler_dcbz(ctx, ctx->dcache_line_size);
3906 gen_op_check_reservation();
3909 GEN_HANDLER2(dcbz_970, "dcbz", 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZT)
3911 gen_addr_reg_index(ctx);
3912 if (ctx->opcode & 0x00200000)
3913 handler_dcbz(ctx, ctx->dcache_line_size);
3914 else
3915 handler_dcbz(ctx, -1);
3916 gen_op_check_reservation();
3919 /* icbi */
3920 #define op_icbi() (*gen_op_icbi[ctx->mem_idx])()
3921 #if defined(CONFIG_USER_ONLY)
3922 /* User-mode only */
3923 static GenOpFunc *gen_op_icbi[] = {
3924 &gen_op_icbi_raw,
3925 &gen_op_icbi_raw,
3926 #if defined(TARGET_PPC64)
3927 &gen_op_icbi_64_raw,
3928 &gen_op_icbi_64_raw,
3929 #endif
3931 #else
3932 /* Full system - 64 bits mode */
3933 #if defined(TARGET_PPC64)
3934 static GenOpFunc *gen_op_icbi[] = {
3935 &gen_op_icbi_user,
3936 &gen_op_icbi_user,
3937 &gen_op_icbi_64_user,
3938 &gen_op_icbi_64_user,
3939 &gen_op_icbi_kernel,
3940 &gen_op_icbi_kernel,
3941 &gen_op_icbi_64_kernel,
3942 &gen_op_icbi_64_kernel,
3943 #if defined(TARGET_PPC64H)
3944 &gen_op_icbi_hypv,
3945 &gen_op_icbi_hypv,
3946 &gen_op_icbi_64_hypv,
3947 &gen_op_icbi_64_hypv,
3948 #endif
3950 #else
3951 /* Full system - 32 bits mode */
3952 static GenOpFunc *gen_op_icbi[] = {
3953 &gen_op_icbi_user,
3954 &gen_op_icbi_user,
3955 &gen_op_icbi_kernel,
3956 &gen_op_icbi_kernel,
3958 #endif
3959 #endif
3961 GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE)
3963 /* NIP cannot be restored if the memory exception comes from an helper */
3964 gen_update_nip(ctx, ctx->nip - 4);
3965 gen_addr_reg_index(ctx);
3966 op_icbi();
3969 /* Optional: */
3970 /* dcba */
3971 GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_DCBA)
3973 /* interpreted as no-op */
3974 /* XXX: specification say this is treated as a store by the MMU
3975 * but does not generate any exception
3979 /*** Segment register manipulation ***/
3980 /* Supervisor only: */
3981 /* mfsr */
3982 GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT)
3984 #if defined(CONFIG_USER_ONLY)
3985 GEN_EXCP_PRIVREG(ctx);
3986 #else
3987 if (unlikely(!ctx->supervisor)) {
3988 GEN_EXCP_PRIVREG(ctx);
3989 return;
3991 gen_op_set_T1(SR(ctx->opcode));
3992 gen_op_load_sr();
3993 gen_op_store_T0_gpr(rD(ctx->opcode));
3994 #endif
3997 /* mfsrin */
3998 GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT)
4000 #if defined(CONFIG_USER_ONLY)
4001 GEN_EXCP_PRIVREG(ctx);
4002 #else
4003 if (unlikely(!ctx->supervisor)) {
4004 GEN_EXCP_PRIVREG(ctx);
4005 return;
4007 gen_op_load_gpr_T1(rB(ctx->opcode));
4008 gen_op_srli_T1(28);
4009 gen_op_load_sr();
4010 gen_op_store_T0_gpr(rD(ctx->opcode));
4011 #endif
4014 /* mtsr */
4015 GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT)
4017 #if defined(CONFIG_USER_ONLY)
4018 GEN_EXCP_PRIVREG(ctx);
4019 #else
4020 if (unlikely(!ctx->supervisor)) {
4021 GEN_EXCP_PRIVREG(ctx);
4022 return;
4024 gen_op_load_gpr_T0(rS(ctx->opcode));
4025 gen_op_set_T1(SR(ctx->opcode));
4026 gen_op_store_sr();
4027 #endif
4030 /* mtsrin */
4031 GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT)
4033 #if defined(CONFIG_USER_ONLY)
4034 GEN_EXCP_PRIVREG(ctx);
4035 #else
4036 if (unlikely(!ctx->supervisor)) {
4037 GEN_EXCP_PRIVREG(ctx);
4038 return;
4040 gen_op_load_gpr_T0(rS(ctx->opcode));
4041 gen_op_load_gpr_T1(rB(ctx->opcode));
4042 gen_op_srli_T1(28);
4043 gen_op_store_sr();
4044 #endif
4047 #if defined(TARGET_PPC64)
4048 /* Specific implementation for PowerPC 64 "bridge" emulation using SLB */
4049 /* mfsr */
4050 GEN_HANDLER2(mfsr_64b, "mfsr", 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT_64B)
4052 #if defined(CONFIG_USER_ONLY)
4053 GEN_EXCP_PRIVREG(ctx);
4054 #else
4055 if (unlikely(!ctx->supervisor)) {
4056 GEN_EXCP_PRIVREG(ctx);
4057 return;
4059 gen_op_set_T1(SR(ctx->opcode));
4060 gen_op_load_slb();
4061 gen_op_store_T0_gpr(rD(ctx->opcode));
4062 #endif
4065 /* mfsrin */
4066 GEN_HANDLER2(mfsrin_64b, "mfsrin", 0x1F, 0x13, 0x14, 0x001F0001,
4067 PPC_SEGMENT_64B)
4069 #if defined(CONFIG_USER_ONLY)
4070 GEN_EXCP_PRIVREG(ctx);
4071 #else
4072 if (unlikely(!ctx->supervisor)) {
4073 GEN_EXCP_PRIVREG(ctx);
4074 return;
4076 gen_op_load_gpr_T1(rB(ctx->opcode));
4077 gen_op_srli_T1(28);
4078 gen_op_load_slb();
4079 gen_op_store_T0_gpr(rD(ctx->opcode));
4080 #endif
4083 /* mtsr */
4084 GEN_HANDLER2(mtsr_64b, "mtsr", 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B)
4086 #if defined(CONFIG_USER_ONLY)
4087 GEN_EXCP_PRIVREG(ctx);
4088 #else
4089 if (unlikely(!ctx->supervisor)) {
4090 GEN_EXCP_PRIVREG(ctx);
4091 return;
4093 gen_op_load_gpr_T0(rS(ctx->opcode));
4094 gen_op_set_T1(SR(ctx->opcode));
4095 gen_op_store_slb();
4096 #endif
4099 /* mtsrin */
4100 GEN_HANDLER2(mtsrin_64b, "mtsrin", 0x1F, 0x12, 0x07, 0x001F0001,
4101 PPC_SEGMENT_64B)
4103 #if defined(CONFIG_USER_ONLY)
4104 GEN_EXCP_PRIVREG(ctx);
4105 #else
4106 if (unlikely(!ctx->supervisor)) {
4107 GEN_EXCP_PRIVREG(ctx);
4108 return;
4110 gen_op_load_gpr_T0(rS(ctx->opcode));
4111 gen_op_load_gpr_T1(rB(ctx->opcode));
4112 gen_op_srli_T1(28);
4113 gen_op_store_slb();
4114 #endif
4116 #endif /* defined(TARGET_PPC64) */
4118 /*** Lookaside buffer management ***/
4119 /* Optional & supervisor only: */
4120 /* tlbia */
4121 GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA)
4123 #if defined(CONFIG_USER_ONLY)
4124 GEN_EXCP_PRIVOPC(ctx);
4125 #else
4126 if (unlikely(!ctx->supervisor)) {
4127 if (loglevel != 0)
4128 fprintf(logfile, "%s: ! supervisor\n", __func__);
4129 GEN_EXCP_PRIVOPC(ctx);
4130 return;
4132 gen_op_tlbia();
4133 #endif
4136 /* tlbie */
4137 GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM_TLBIE)
4139 #if defined(CONFIG_USER_ONLY)
4140 GEN_EXCP_PRIVOPC(ctx);
4141 #else
4142 if (unlikely(!ctx->supervisor)) {
4143 GEN_EXCP_PRIVOPC(ctx);
4144 return;
4146 gen_op_load_gpr_T0(rB(ctx->opcode));
4147 #if defined(TARGET_PPC64)
4148 if (ctx->sf_mode)
4149 gen_op_tlbie_64();
4150 else
4151 #endif
4152 gen_op_tlbie();
4153 #endif
4156 /* tlbsync */
4157 GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC)
4159 #if defined(CONFIG_USER_ONLY)
4160 GEN_EXCP_PRIVOPC(ctx);
4161 #else
4162 if (unlikely(!ctx->supervisor)) {
4163 GEN_EXCP_PRIVOPC(ctx);
4164 return;
4166 /* This has no effect: it should ensure that all previous
4167 * tlbie have completed
4169 GEN_STOP(ctx);
4170 #endif
4173 #if defined(TARGET_PPC64)
4174 /* slbia */
4175 GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x03FFFC01, PPC_SLBI)
4177 #if defined(CONFIG_USER_ONLY)
4178 GEN_EXCP_PRIVOPC(ctx);
4179 #else
4180 if (unlikely(!ctx->supervisor)) {
4181 if (loglevel != 0)
4182 fprintf(logfile, "%s: ! supervisor\n", __func__);
4183 GEN_EXCP_PRIVOPC(ctx);
4184 return;
4186 gen_op_slbia();
4187 #endif
4190 /* slbie */
4191 GEN_HANDLER(slbie, 0x1F, 0x12, 0x0D, 0x03FF0001, PPC_SLBI)
4193 #if defined(CONFIG_USER_ONLY)
4194 GEN_EXCP_PRIVOPC(ctx);
4195 #else
4196 if (unlikely(!ctx->supervisor)) {
4197 GEN_EXCP_PRIVOPC(ctx);
4198 return;
4200 gen_op_load_gpr_T0(rB(ctx->opcode));
4201 gen_op_slbie();
4202 #endif
4204 #endif
4206 /*** External control ***/
4207 /* Optional: */
4208 #define op_eciwx() (*gen_op_eciwx[ctx->mem_idx])()
4209 #define op_ecowx() (*gen_op_ecowx[ctx->mem_idx])()
4210 #if defined(CONFIG_USER_ONLY)
4211 /* User-mode only */
4212 static GenOpFunc *gen_op_eciwx[] = {
4213 &gen_op_eciwx_raw,
4214 &gen_op_eciwx_le_raw,
4215 #if defined(TARGET_PPC64)
4216 &gen_op_eciwx_64_raw,
4217 &gen_op_eciwx_le_64_raw,
4218 #endif
4220 static GenOpFunc *gen_op_ecowx[] = {
4221 &gen_op_ecowx_raw,
4222 &gen_op_ecowx_le_raw,
4223 #if defined(TARGET_PPC64)
4224 &gen_op_ecowx_64_raw,
4225 &gen_op_ecowx_le_64_raw,
4226 #endif
4228 #else
4229 #if defined(TARGET_PPC64)
4230 /* Full system - 64 bits mode */
4231 static GenOpFunc *gen_op_eciwx[] = {
4232 &gen_op_eciwx_user,
4233 &gen_op_eciwx_le_user,
4234 &gen_op_eciwx_64_user,
4235 &gen_op_eciwx_le_64_user,
4236 &gen_op_eciwx_kernel,
4237 &gen_op_eciwx_le_kernel,
4238 &gen_op_eciwx_64_kernel,
4239 &gen_op_eciwx_le_64_kernel,
4240 #if defined(TARGET_PPC64H)
4241 &gen_op_eciwx_hypv,
4242 &gen_op_eciwx_le_hypv,
4243 &gen_op_eciwx_64_hypv,
4244 &gen_op_eciwx_le_64_hypv,
4245 #endif
4247 static GenOpFunc *gen_op_ecowx[] = {
4248 &gen_op_ecowx_user,
4249 &gen_op_ecowx_le_user,
4250 &gen_op_ecowx_64_user,
4251 &gen_op_ecowx_le_64_user,
4252 &gen_op_ecowx_kernel,
4253 &gen_op_ecowx_le_kernel,
4254 &gen_op_ecowx_64_kernel,
4255 &gen_op_ecowx_le_64_kernel,
4256 #if defined(TARGET_PPC64H)
4257 &gen_op_ecowx_hypv,
4258 &gen_op_ecowx_le_hypv,
4259 &gen_op_ecowx_64_hypv,
4260 &gen_op_ecowx_le_64_hypv,
4261 #endif
4263 #else
4264 /* Full system - 32 bits mode */
4265 static GenOpFunc *gen_op_eciwx[] = {
4266 &gen_op_eciwx_user,
4267 &gen_op_eciwx_le_user,
4268 &gen_op_eciwx_kernel,
4269 &gen_op_eciwx_le_kernel,
4271 static GenOpFunc *gen_op_ecowx[] = {
4272 &gen_op_ecowx_user,
4273 &gen_op_ecowx_le_user,
4274 &gen_op_ecowx_kernel,
4275 &gen_op_ecowx_le_kernel,
4277 #endif
4278 #endif
4280 /* eciwx */
4281 GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN)
4283 /* Should check EAR[E] & alignment ! */
4284 gen_addr_reg_index(ctx);
4285 op_eciwx();
4286 gen_op_store_T0_gpr(rD(ctx->opcode));
4289 /* ecowx */
4290 GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN)
4292 /* Should check EAR[E] & alignment ! */
4293 gen_addr_reg_index(ctx);
4294 gen_op_load_gpr_T1(rS(ctx->opcode));
4295 op_ecowx();
4298 /* PowerPC 601 specific instructions */
4299 /* abs - abs. */
4300 GEN_HANDLER(abs, 0x1F, 0x08, 0x0B, 0x0000F800, PPC_POWER_BR)
4302 gen_op_load_gpr_T0(rA(ctx->opcode));
4303 gen_op_POWER_abs();
4304 gen_op_store_T0_gpr(rD(ctx->opcode));
4305 if (unlikely(Rc(ctx->opcode) != 0))
4306 gen_set_Rc0(ctx);
4309 /* abso - abso. */
4310 GEN_HANDLER(abso, 0x1F, 0x08, 0x1B, 0x0000F800, PPC_POWER_BR)
4312 gen_op_load_gpr_T0(rA(ctx->opcode));
4313 gen_op_POWER_abso();
4314 gen_op_store_T0_gpr(rD(ctx->opcode));
4315 if (unlikely(Rc(ctx->opcode) != 0))
4316 gen_set_Rc0(ctx);
4319 /* clcs */
4320 GEN_HANDLER(clcs, 0x1F, 0x10, 0x13, 0x0000F800, PPC_POWER_BR)
4322 gen_op_load_gpr_T0(rA(ctx->opcode));
4323 gen_op_POWER_clcs();
4324 /* Rc=1 sets CR0 to an undefined state */
4325 gen_op_store_T0_gpr(rD(ctx->opcode));
4328 /* div - div. */
4329 GEN_HANDLER(div, 0x1F, 0x0B, 0x0A, 0x00000000, PPC_POWER_BR)
4331 gen_op_load_gpr_T0(rA(ctx->opcode));
4332 gen_op_load_gpr_T1(rB(ctx->opcode));
4333 gen_op_POWER_div();
4334 gen_op_store_T0_gpr(rD(ctx->opcode));
4335 if (unlikely(Rc(ctx->opcode) != 0))
4336 gen_set_Rc0(ctx);
4339 /* divo - divo. */
4340 GEN_HANDLER(divo, 0x1F, 0x0B, 0x1A, 0x00000000, PPC_POWER_BR)
4342 gen_op_load_gpr_T0(rA(ctx->opcode));
4343 gen_op_load_gpr_T1(rB(ctx->opcode));
4344 gen_op_POWER_divo();
4345 gen_op_store_T0_gpr(rD(ctx->opcode));
4346 if (unlikely(Rc(ctx->opcode) != 0))
4347 gen_set_Rc0(ctx);
4350 /* divs - divs. */
4351 GEN_HANDLER(divs, 0x1F, 0x0B, 0x0B, 0x00000000, PPC_POWER_BR)
4353 gen_op_load_gpr_T0(rA(ctx->opcode));
4354 gen_op_load_gpr_T1(rB(ctx->opcode));
4355 gen_op_POWER_divs();
4356 gen_op_store_T0_gpr(rD(ctx->opcode));
4357 if (unlikely(Rc(ctx->opcode) != 0))
4358 gen_set_Rc0(ctx);
4361 /* divso - divso. */
4362 GEN_HANDLER(divso, 0x1F, 0x0B, 0x1B, 0x00000000, PPC_POWER_BR)
4364 gen_op_load_gpr_T0(rA(ctx->opcode));
4365 gen_op_load_gpr_T1(rB(ctx->opcode));
4366 gen_op_POWER_divso();
4367 gen_op_store_T0_gpr(rD(ctx->opcode));
4368 if (unlikely(Rc(ctx->opcode) != 0))
4369 gen_set_Rc0(ctx);
4372 /* doz - doz. */
4373 GEN_HANDLER(doz, 0x1F, 0x08, 0x08, 0x00000000, PPC_POWER_BR)
4375 gen_op_load_gpr_T0(rA(ctx->opcode));
4376 gen_op_load_gpr_T1(rB(ctx->opcode));
4377 gen_op_POWER_doz();
4378 gen_op_store_T0_gpr(rD(ctx->opcode));
4379 if (unlikely(Rc(ctx->opcode) != 0))
4380 gen_set_Rc0(ctx);
4383 /* dozo - dozo. */
4384 GEN_HANDLER(dozo, 0x1F, 0x08, 0x18, 0x00000000, PPC_POWER_BR)
4386 gen_op_load_gpr_T0(rA(ctx->opcode));
4387 gen_op_load_gpr_T1(rB(ctx->opcode));
4388 gen_op_POWER_dozo();
4389 gen_op_store_T0_gpr(rD(ctx->opcode));
4390 if (unlikely(Rc(ctx->opcode) != 0))
4391 gen_set_Rc0(ctx);
4394 /* dozi */
4395 GEN_HANDLER(dozi, 0x09, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR)
4397 gen_op_load_gpr_T0(rA(ctx->opcode));
4398 gen_op_set_T1(SIMM(ctx->opcode));
4399 gen_op_POWER_doz();
4400 gen_op_store_T0_gpr(rD(ctx->opcode));
4403 /* As lscbx load from memory byte after byte, it's always endian safe */
4404 #define op_POWER_lscbx(start, ra, rb) \
4405 (*gen_op_POWER_lscbx[ctx->mem_idx])(start, ra, rb)
4406 #if defined(CONFIG_USER_ONLY)
4407 static GenOpFunc3 *gen_op_POWER_lscbx[] = {
4408 &gen_op_POWER_lscbx_raw,
4409 &gen_op_POWER_lscbx_raw,
4411 #else
4412 static GenOpFunc3 *gen_op_POWER_lscbx[] = {
4413 &gen_op_POWER_lscbx_user,
4414 &gen_op_POWER_lscbx_user,
4415 &gen_op_POWER_lscbx_kernel,
4416 &gen_op_POWER_lscbx_kernel,
4418 #endif
4420 /* lscbx - lscbx. */
4421 GEN_HANDLER(lscbx, 0x1F, 0x15, 0x08, 0x00000000, PPC_POWER_BR)
4423 int ra = rA(ctx->opcode);
4424 int rb = rB(ctx->opcode);
4426 gen_addr_reg_index(ctx);
4427 if (ra == 0) {
4428 ra = rb;
4430 /* NIP cannot be restored if the memory exception comes from an helper */
4431 gen_update_nip(ctx, ctx->nip - 4);
4432 gen_op_load_xer_bc();
4433 gen_op_load_xer_cmp();
4434 op_POWER_lscbx(rD(ctx->opcode), ra, rb);
4435 gen_op_store_xer_bc();
4436 if (unlikely(Rc(ctx->opcode) != 0))
4437 gen_set_Rc0(ctx);
4440 /* maskg - maskg. */
4441 GEN_HANDLER(maskg, 0x1F, 0x1D, 0x00, 0x00000000, PPC_POWER_BR)
4443 gen_op_load_gpr_T0(rS(ctx->opcode));
4444 gen_op_load_gpr_T1(rB(ctx->opcode));
4445 gen_op_POWER_maskg();
4446 gen_op_store_T0_gpr(rA(ctx->opcode));
4447 if (unlikely(Rc(ctx->opcode) != 0))
4448 gen_set_Rc0(ctx);
4451 /* maskir - maskir. */
4452 GEN_HANDLER(maskir, 0x1F, 0x1D, 0x10, 0x00000000, PPC_POWER_BR)
4454 gen_op_load_gpr_T0(rA(ctx->opcode));
4455 gen_op_load_gpr_T1(rS(ctx->opcode));
4456 gen_op_load_gpr_T2(rB(ctx->opcode));
4457 gen_op_POWER_maskir();
4458 gen_op_store_T0_gpr(rA(ctx->opcode));
4459 if (unlikely(Rc(ctx->opcode) != 0))
4460 gen_set_Rc0(ctx);
4463 /* mul - mul. */
4464 GEN_HANDLER(mul, 0x1F, 0x0B, 0x03, 0x00000000, PPC_POWER_BR)
4466 gen_op_load_gpr_T0(rA(ctx->opcode));
4467 gen_op_load_gpr_T1(rB(ctx->opcode));
4468 gen_op_POWER_mul();
4469 gen_op_store_T0_gpr(rD(ctx->opcode));
4470 if (unlikely(Rc(ctx->opcode) != 0))
4471 gen_set_Rc0(ctx);
4474 /* mulo - mulo. */
4475 GEN_HANDLER(mulo, 0x1F, 0x0B, 0x13, 0x00000000, PPC_POWER_BR)
4477 gen_op_load_gpr_T0(rA(ctx->opcode));
4478 gen_op_load_gpr_T1(rB(ctx->opcode));
4479 gen_op_POWER_mulo();
4480 gen_op_store_T0_gpr(rD(ctx->opcode));
4481 if (unlikely(Rc(ctx->opcode) != 0))
4482 gen_set_Rc0(ctx);
4485 /* nabs - nabs. */
4486 GEN_HANDLER(nabs, 0x1F, 0x08, 0x0F, 0x00000000, PPC_POWER_BR)
4488 gen_op_load_gpr_T0(rA(ctx->opcode));
4489 gen_op_POWER_nabs();
4490 gen_op_store_T0_gpr(rD(ctx->opcode));
4491 if (unlikely(Rc(ctx->opcode) != 0))
4492 gen_set_Rc0(ctx);
4495 /* nabso - nabso. */
4496 GEN_HANDLER(nabso, 0x1F, 0x08, 0x1F, 0x00000000, PPC_POWER_BR)
4498 gen_op_load_gpr_T0(rA(ctx->opcode));
4499 gen_op_POWER_nabso();
4500 gen_op_store_T0_gpr(rD(ctx->opcode));
4501 if (unlikely(Rc(ctx->opcode) != 0))
4502 gen_set_Rc0(ctx);
4505 /* rlmi - rlmi. */
4506 GEN_HANDLER(rlmi, 0x16, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR)
4508 uint32_t mb, me;
4510 mb = MB(ctx->opcode);
4511 me = ME(ctx->opcode);
4512 gen_op_load_gpr_T0(rS(ctx->opcode));
4513 gen_op_load_gpr_T1(rA(ctx->opcode));
4514 gen_op_load_gpr_T2(rB(ctx->opcode));
4515 gen_op_POWER_rlmi(MASK(mb, me), ~MASK(mb, me));
4516 gen_op_store_T0_gpr(rA(ctx->opcode));
4517 if (unlikely(Rc(ctx->opcode) != 0))
4518 gen_set_Rc0(ctx);
4521 /* rrib - rrib. */
4522 GEN_HANDLER(rrib, 0x1F, 0x19, 0x10, 0x00000000, PPC_POWER_BR)
4524 gen_op_load_gpr_T0(rS(ctx->opcode));
4525 gen_op_load_gpr_T1(rA(ctx->opcode));
4526 gen_op_load_gpr_T2(rB(ctx->opcode));
4527 gen_op_POWER_rrib();
4528 gen_op_store_T0_gpr(rA(ctx->opcode));
4529 if (unlikely(Rc(ctx->opcode) != 0))
4530 gen_set_Rc0(ctx);
4533 /* sle - sle. */
4534 GEN_HANDLER(sle, 0x1F, 0x19, 0x04, 0x00000000, PPC_POWER_BR)
4536 gen_op_load_gpr_T0(rS(ctx->opcode));
4537 gen_op_load_gpr_T1(rB(ctx->opcode));
4538 gen_op_POWER_sle();
4539 gen_op_store_T0_gpr(rA(ctx->opcode));
4540 if (unlikely(Rc(ctx->opcode) != 0))
4541 gen_set_Rc0(ctx);
4544 /* sleq - sleq. */
4545 GEN_HANDLER(sleq, 0x1F, 0x19, 0x06, 0x00000000, PPC_POWER_BR)
4547 gen_op_load_gpr_T0(rS(ctx->opcode));
4548 gen_op_load_gpr_T1(rB(ctx->opcode));
4549 gen_op_POWER_sleq();
4550 gen_op_store_T0_gpr(rA(ctx->opcode));
4551 if (unlikely(Rc(ctx->opcode) != 0))
4552 gen_set_Rc0(ctx);
4555 /* sliq - sliq. */
4556 GEN_HANDLER(sliq, 0x1F, 0x18, 0x05, 0x00000000, PPC_POWER_BR)
4558 gen_op_load_gpr_T0(rS(ctx->opcode));
4559 gen_op_set_T1(SH(ctx->opcode));
4560 gen_op_POWER_sle();
4561 gen_op_store_T0_gpr(rA(ctx->opcode));
4562 if (unlikely(Rc(ctx->opcode) != 0))
4563 gen_set_Rc0(ctx);
4566 /* slliq - slliq. */
4567 GEN_HANDLER(slliq, 0x1F, 0x18, 0x07, 0x00000000, PPC_POWER_BR)
4569 gen_op_load_gpr_T0(rS(ctx->opcode));
4570 gen_op_set_T1(SH(ctx->opcode));
4571 gen_op_POWER_sleq();
4572 gen_op_store_T0_gpr(rA(ctx->opcode));
4573 if (unlikely(Rc(ctx->opcode) != 0))
4574 gen_set_Rc0(ctx);
4577 /* sllq - sllq. */
4578 GEN_HANDLER(sllq, 0x1F, 0x18, 0x06, 0x00000000, PPC_POWER_BR)
4580 gen_op_load_gpr_T0(rS(ctx->opcode));
4581 gen_op_load_gpr_T1(rB(ctx->opcode));
4582 gen_op_POWER_sllq();
4583 gen_op_store_T0_gpr(rA(ctx->opcode));
4584 if (unlikely(Rc(ctx->opcode) != 0))
4585 gen_set_Rc0(ctx);
4588 /* slq - slq. */
4589 GEN_HANDLER(slq, 0x1F, 0x18, 0x04, 0x00000000, PPC_POWER_BR)
4591 gen_op_load_gpr_T0(rS(ctx->opcode));
4592 gen_op_load_gpr_T1(rB(ctx->opcode));
4593 gen_op_POWER_slq();
4594 gen_op_store_T0_gpr(rA(ctx->opcode));
4595 if (unlikely(Rc(ctx->opcode) != 0))
4596 gen_set_Rc0(ctx);
4599 /* sraiq - sraiq. */
4600 GEN_HANDLER(sraiq, 0x1F, 0x18, 0x1D, 0x00000000, PPC_POWER_BR)
4602 gen_op_load_gpr_T0(rS(ctx->opcode));
4603 gen_op_set_T1(SH(ctx->opcode));
4604 gen_op_POWER_sraq();
4605 gen_op_store_T0_gpr(rA(ctx->opcode));
4606 if (unlikely(Rc(ctx->opcode) != 0))
4607 gen_set_Rc0(ctx);
4610 /* sraq - sraq. */
4611 GEN_HANDLER(sraq, 0x1F, 0x18, 0x1C, 0x00000000, PPC_POWER_BR)
4613 gen_op_load_gpr_T0(rS(ctx->opcode));
4614 gen_op_load_gpr_T1(rB(ctx->opcode));
4615 gen_op_POWER_sraq();
4616 gen_op_store_T0_gpr(rA(ctx->opcode));
4617 if (unlikely(Rc(ctx->opcode) != 0))
4618 gen_set_Rc0(ctx);
4621 /* sre - sre. */
4622 GEN_HANDLER(sre, 0x1F, 0x19, 0x14, 0x00000000, PPC_POWER_BR)
4624 gen_op_load_gpr_T0(rS(ctx->opcode));
4625 gen_op_load_gpr_T1(rB(ctx->opcode));
4626 gen_op_POWER_sre();
4627 gen_op_store_T0_gpr(rA(ctx->opcode));
4628 if (unlikely(Rc(ctx->opcode) != 0))
4629 gen_set_Rc0(ctx);
4632 /* srea - srea. */
4633 GEN_HANDLER(srea, 0x1F, 0x19, 0x1C, 0x00000000, PPC_POWER_BR)
4635 gen_op_load_gpr_T0(rS(ctx->opcode));
4636 gen_op_load_gpr_T1(rB(ctx->opcode));
4637 gen_op_POWER_srea();
4638 gen_op_store_T0_gpr(rA(ctx->opcode));
4639 if (unlikely(Rc(ctx->opcode) != 0))
4640 gen_set_Rc0(ctx);
4643 /* sreq */
4644 GEN_HANDLER(sreq, 0x1F, 0x19, 0x16, 0x00000000, PPC_POWER_BR)
4646 gen_op_load_gpr_T0(rS(ctx->opcode));
4647 gen_op_load_gpr_T1(rB(ctx->opcode));
4648 gen_op_POWER_sreq();
4649 gen_op_store_T0_gpr(rA(ctx->opcode));
4650 if (unlikely(Rc(ctx->opcode) != 0))
4651 gen_set_Rc0(ctx);
4654 /* sriq */
4655 GEN_HANDLER(sriq, 0x1F, 0x18, 0x15, 0x00000000, PPC_POWER_BR)
4657 gen_op_load_gpr_T0(rS(ctx->opcode));
4658 gen_op_set_T1(SH(ctx->opcode));
4659 gen_op_POWER_srq();
4660 gen_op_store_T0_gpr(rA(ctx->opcode));
4661 if (unlikely(Rc(ctx->opcode) != 0))
4662 gen_set_Rc0(ctx);
4665 /* srliq */
4666 GEN_HANDLER(srliq, 0x1F, 0x18, 0x17, 0x00000000, PPC_POWER_BR)
4668 gen_op_load_gpr_T0(rS(ctx->opcode));
4669 gen_op_load_gpr_T1(rB(ctx->opcode));
4670 gen_op_set_T1(SH(ctx->opcode));
4671 gen_op_POWER_srlq();
4672 gen_op_store_T0_gpr(rA(ctx->opcode));
4673 if (unlikely(Rc(ctx->opcode) != 0))
4674 gen_set_Rc0(ctx);
4677 /* srlq */
4678 GEN_HANDLER(srlq, 0x1F, 0x18, 0x16, 0x00000000, PPC_POWER_BR)
4680 gen_op_load_gpr_T0(rS(ctx->opcode));
4681 gen_op_load_gpr_T1(rB(ctx->opcode));
4682 gen_op_POWER_srlq();
4683 gen_op_store_T0_gpr(rA(ctx->opcode));
4684 if (unlikely(Rc(ctx->opcode) != 0))
4685 gen_set_Rc0(ctx);
4688 /* srq */
4689 GEN_HANDLER(srq, 0x1F, 0x18, 0x14, 0x00000000, PPC_POWER_BR)
4691 gen_op_load_gpr_T0(rS(ctx->opcode));
4692 gen_op_load_gpr_T1(rB(ctx->opcode));
4693 gen_op_POWER_srq();
4694 gen_op_store_T0_gpr(rA(ctx->opcode));
4695 if (unlikely(Rc(ctx->opcode) != 0))
4696 gen_set_Rc0(ctx);
4699 /* PowerPC 602 specific instructions */
4700 /* dsa */
4701 GEN_HANDLER(dsa, 0x1F, 0x14, 0x13, 0x03FFF801, PPC_602_SPEC)
4703 /* XXX: TODO */
4704 GEN_EXCP_INVAL(ctx);
4707 /* esa */
4708 GEN_HANDLER(esa, 0x1F, 0x14, 0x12, 0x03FFF801, PPC_602_SPEC)
4710 /* XXX: TODO */
4711 GEN_EXCP_INVAL(ctx);
4714 /* mfrom */
4715 GEN_HANDLER(mfrom, 0x1F, 0x09, 0x08, 0x03E0F801, PPC_602_SPEC)
4717 #if defined(CONFIG_USER_ONLY)
4718 GEN_EXCP_PRIVOPC(ctx);
4719 #else
4720 if (unlikely(!ctx->supervisor)) {
4721 GEN_EXCP_PRIVOPC(ctx);
4722 return;
4724 gen_op_load_gpr_T0(rA(ctx->opcode));
4725 gen_op_602_mfrom();
4726 gen_op_store_T0_gpr(rD(ctx->opcode));
4727 #endif
4730 /* 602 - 603 - G2 TLB management */
4731 /* tlbld */
4732 GEN_HANDLER2(tlbld_6xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB)
4734 #if defined(CONFIG_USER_ONLY)
4735 GEN_EXCP_PRIVOPC(ctx);
4736 #else
4737 if (unlikely(!ctx->supervisor)) {
4738 GEN_EXCP_PRIVOPC(ctx);
4739 return;
4741 gen_op_load_gpr_T0(rB(ctx->opcode));
4742 gen_op_6xx_tlbld();
4743 #endif
4746 /* tlbli */
4747 GEN_HANDLER2(tlbli_6xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB)
4749 #if defined(CONFIG_USER_ONLY)
4750 GEN_EXCP_PRIVOPC(ctx);
4751 #else
4752 if (unlikely(!ctx->supervisor)) {
4753 GEN_EXCP_PRIVOPC(ctx);
4754 return;
4756 gen_op_load_gpr_T0(rB(ctx->opcode));
4757 gen_op_6xx_tlbli();
4758 #endif
4761 /* 74xx TLB management */
4762 /* tlbld */
4763 GEN_HANDLER2(tlbld_74xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_74xx_TLB)
4765 #if defined(CONFIG_USER_ONLY)
4766 GEN_EXCP_PRIVOPC(ctx);
4767 #else
4768 if (unlikely(!ctx->supervisor)) {
4769 GEN_EXCP_PRIVOPC(ctx);
4770 return;
4772 gen_op_load_gpr_T0(rB(ctx->opcode));
4773 gen_op_74xx_tlbld();
4774 #endif
4777 /* tlbli */
4778 GEN_HANDLER2(tlbli_74xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_74xx_TLB)
4780 #if defined(CONFIG_USER_ONLY)
4781 GEN_EXCP_PRIVOPC(ctx);
4782 #else
4783 if (unlikely(!ctx->supervisor)) {
4784 GEN_EXCP_PRIVOPC(ctx);
4785 return;
4787 gen_op_load_gpr_T0(rB(ctx->opcode));
4788 gen_op_74xx_tlbli();
4789 #endif
4792 /* POWER instructions not in PowerPC 601 */
4793 /* clf */
4794 GEN_HANDLER(clf, 0x1F, 0x16, 0x03, 0x03E00000, PPC_POWER)
4796 /* Cache line flush: implemented as no-op */
4799 /* cli */
4800 GEN_HANDLER(cli, 0x1F, 0x16, 0x0F, 0x03E00000, PPC_POWER)
4802 /* Cache line invalidate: privileged and treated as no-op */
4803 #if defined(CONFIG_USER_ONLY)
4804 GEN_EXCP_PRIVOPC(ctx);
4805 #else
4806 if (unlikely(!ctx->supervisor)) {
4807 GEN_EXCP_PRIVOPC(ctx);
4808 return;
4810 #endif
4813 /* dclst */
4814 GEN_HANDLER(dclst, 0x1F, 0x16, 0x13, 0x03E00000, PPC_POWER)
4816 /* Data cache line store: treated as no-op */
4819 GEN_HANDLER(mfsri, 0x1F, 0x13, 0x13, 0x00000001, PPC_POWER)
4821 #if defined(CONFIG_USER_ONLY)
4822 GEN_EXCP_PRIVOPC(ctx);
4823 #else
4824 if (unlikely(!ctx->supervisor)) {
4825 GEN_EXCP_PRIVOPC(ctx);
4826 return;
4828 int ra = rA(ctx->opcode);
4829 int rd = rD(ctx->opcode);
4831 gen_addr_reg_index(ctx);
4832 gen_op_POWER_mfsri();
4833 gen_op_store_T0_gpr(rd);
4834 if (ra != 0 && ra != rd)
4835 gen_op_store_T1_gpr(ra);
4836 #endif
4839 GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER)
4841 #if defined(CONFIG_USER_ONLY)
4842 GEN_EXCP_PRIVOPC(ctx);
4843 #else
4844 if (unlikely(!ctx->supervisor)) {
4845 GEN_EXCP_PRIVOPC(ctx);
4846 return;
4848 gen_addr_reg_index(ctx);
4849 gen_op_POWER_rac();
4850 gen_op_store_T0_gpr(rD(ctx->opcode));
4851 #endif
4854 GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02, 0x03FFF0001, PPC_POWER)
4856 #if defined(CONFIG_USER_ONLY)
4857 GEN_EXCP_PRIVOPC(ctx);
4858 #else
4859 if (unlikely(!ctx->supervisor)) {
4860 GEN_EXCP_PRIVOPC(ctx);
4861 return;
4863 gen_op_POWER_rfsvc();
4864 GEN_SYNC(ctx);
4865 #endif
4868 /* svc is not implemented for now */
4870 /* POWER2 specific instructions */
4871 /* Quad manipulation (load/store two floats at a time) */
4872 #define op_POWER2_lfq() (*gen_op_POWER2_lfq[ctx->mem_idx])()
4873 #define op_POWER2_stfq() (*gen_op_POWER2_stfq[ctx->mem_idx])()
4874 #if defined(CONFIG_USER_ONLY)
4875 static GenOpFunc *gen_op_POWER2_lfq[] = {
4876 &gen_op_POWER2_lfq_le_raw,
4877 &gen_op_POWER2_lfq_raw,
4879 static GenOpFunc *gen_op_POWER2_stfq[] = {
4880 &gen_op_POWER2_stfq_le_raw,
4881 &gen_op_POWER2_stfq_raw,
4883 #else
4884 static GenOpFunc *gen_op_POWER2_lfq[] = {
4885 &gen_op_POWER2_lfq_le_user,
4886 &gen_op_POWER2_lfq_user,
4887 &gen_op_POWER2_lfq_le_kernel,
4888 &gen_op_POWER2_lfq_kernel,
4890 static GenOpFunc *gen_op_POWER2_stfq[] = {
4891 &gen_op_POWER2_stfq_le_user,
4892 &gen_op_POWER2_stfq_user,
4893 &gen_op_POWER2_stfq_le_kernel,
4894 &gen_op_POWER2_stfq_kernel,
4896 #endif
4898 /* lfq */
4899 GEN_HANDLER(lfq, 0x38, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
4901 /* NIP cannot be restored if the memory exception comes from an helper */
4902 gen_update_nip(ctx, ctx->nip - 4);
4903 gen_addr_imm_index(ctx, 0);
4904 op_POWER2_lfq();
4905 gen_op_store_FT0_fpr(rD(ctx->opcode));
4906 gen_op_store_FT1_fpr(rD(ctx->opcode) + 1);
4909 /* lfqu */
4910 GEN_HANDLER(lfqu, 0x39, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
4912 int ra = rA(ctx->opcode);
4914 /* NIP cannot be restored if the memory exception comes from an helper */
4915 gen_update_nip(ctx, ctx->nip - 4);
4916 gen_addr_imm_index(ctx, 0);
4917 op_POWER2_lfq();
4918 gen_op_store_FT0_fpr(rD(ctx->opcode));
4919 gen_op_store_FT1_fpr(rD(ctx->opcode) + 1);
4920 if (ra != 0)
4921 gen_op_store_T0_gpr(ra);
4924 /* lfqux */
4925 GEN_HANDLER(lfqux, 0x1F, 0x17, 0x19, 0x00000001, PPC_POWER2)
4927 int ra = rA(ctx->opcode);
4929 /* NIP cannot be restored if the memory exception comes from an helper */
4930 gen_update_nip(ctx, ctx->nip - 4);
4931 gen_addr_reg_index(ctx);
4932 op_POWER2_lfq();
4933 gen_op_store_FT0_fpr(rD(ctx->opcode));
4934 gen_op_store_FT1_fpr(rD(ctx->opcode) + 1);
4935 if (ra != 0)
4936 gen_op_store_T0_gpr(ra);
4939 /* lfqx */
4940 GEN_HANDLER(lfqx, 0x1F, 0x17, 0x18, 0x00000001, PPC_POWER2)
4942 /* NIP cannot be restored if the memory exception comes from an helper */
4943 gen_update_nip(ctx, ctx->nip - 4);
4944 gen_addr_reg_index(ctx);
4945 op_POWER2_lfq();
4946 gen_op_store_FT0_fpr(rD(ctx->opcode));
4947 gen_op_store_FT1_fpr(rD(ctx->opcode) + 1);
4950 /* stfq */
4951 GEN_HANDLER(stfq, 0x3C, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
4953 /* NIP cannot be restored if the memory exception comes from an helper */
4954 gen_update_nip(ctx, ctx->nip - 4);
4955 gen_addr_imm_index(ctx, 0);
4956 gen_op_load_fpr_FT0(rS(ctx->opcode));
4957 gen_op_load_fpr_FT1(rS(ctx->opcode) + 1);
4958 op_POWER2_stfq();
4961 /* stfqu */
4962 GEN_HANDLER(stfqu, 0x3D, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
4964 int ra = rA(ctx->opcode);
4966 /* NIP cannot be restored if the memory exception comes from an helper */
4967 gen_update_nip(ctx, ctx->nip - 4);
4968 gen_addr_imm_index(ctx, 0);
4969 gen_op_load_fpr_FT0(rS(ctx->opcode));
4970 gen_op_load_fpr_FT1(rS(ctx->opcode) + 1);
4971 op_POWER2_stfq();
4972 if (ra != 0)
4973 gen_op_store_T0_gpr(ra);
4976 /* stfqux */
4977 GEN_HANDLER(stfqux, 0x1F, 0x17, 0x1D, 0x00000001, PPC_POWER2)
4979 int ra = rA(ctx->opcode);
4981 /* NIP cannot be restored if the memory exception comes from an helper */
4982 gen_update_nip(ctx, ctx->nip - 4);
4983 gen_addr_reg_index(ctx);
4984 gen_op_load_fpr_FT0(rS(ctx->opcode));
4985 gen_op_load_fpr_FT1(rS(ctx->opcode) + 1);
4986 op_POWER2_stfq();
4987 if (ra != 0)
4988 gen_op_store_T0_gpr(ra);
4991 /* stfqx */
4992 GEN_HANDLER(stfqx, 0x1F, 0x17, 0x1C, 0x00000001, PPC_POWER2)
4994 /* NIP cannot be restored if the memory exception comes from an helper */
4995 gen_update_nip(ctx, ctx->nip - 4);
4996 gen_addr_reg_index(ctx);
4997 gen_op_load_fpr_FT0(rS(ctx->opcode));
4998 gen_op_load_fpr_FT1(rS(ctx->opcode) + 1);
4999 op_POWER2_stfq();
5002 /* BookE specific instructions */
5003 /* XXX: not implemented on 440 ? */
5004 GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_BOOKE_EXT)
5006 /* XXX: TODO */
5007 GEN_EXCP_INVAL(ctx);
5010 /* XXX: not implemented on 440 ? */
5011 GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_BOOKE_EXT)
5013 #if defined(CONFIG_USER_ONLY)
5014 GEN_EXCP_PRIVOPC(ctx);
5015 #else
5016 if (unlikely(!ctx->supervisor)) {
5017 GEN_EXCP_PRIVOPC(ctx);
5018 return;
5020 gen_addr_reg_index(ctx);
5021 /* Use the same micro-ops as for tlbie */
5022 #if defined(TARGET_PPC64)
5023 if (ctx->sf_mode)
5024 gen_op_tlbie_64();
5025 else
5026 #endif
5027 gen_op_tlbie();
5028 #endif
5031 /* All 405 MAC instructions are translated here */
5032 static always_inline void gen_405_mulladd_insn (DisasContext *ctx,
5033 int opc2, int opc3,
5034 int ra, int rb, int rt, int Rc)
5036 gen_op_load_gpr_T0(ra);
5037 gen_op_load_gpr_T1(rb);
5038 switch (opc3 & 0x0D) {
5039 case 0x05:
5040 /* macchw - macchw. - macchwo - macchwo. */
5041 /* macchws - macchws. - macchwso - macchwso. */
5042 /* nmacchw - nmacchw. - nmacchwo - nmacchwo. */
5043 /* nmacchws - nmacchws. - nmacchwso - nmacchwso. */
5044 /* mulchw - mulchw. */
5045 gen_op_405_mulchw();
5046 break;
5047 case 0x04:
5048 /* macchwu - macchwu. - macchwuo - macchwuo. */
5049 /* macchwsu - macchwsu. - macchwsuo - macchwsuo. */
5050 /* mulchwu - mulchwu. */
5051 gen_op_405_mulchwu();
5052 break;
5053 case 0x01:
5054 /* machhw - machhw. - machhwo - machhwo. */
5055 /* machhws - machhws. - machhwso - machhwso. */
5056 /* nmachhw - nmachhw. - nmachhwo - nmachhwo. */
5057 /* nmachhws - nmachhws. - nmachhwso - nmachhwso. */
5058 /* mulhhw - mulhhw. */
5059 gen_op_405_mulhhw();
5060 break;
5061 case 0x00:
5062 /* machhwu - machhwu. - machhwuo - machhwuo. */
5063 /* machhwsu - machhwsu. - machhwsuo - machhwsuo. */
5064 /* mulhhwu - mulhhwu. */
5065 gen_op_405_mulhhwu();
5066 break;
5067 case 0x0D:
5068 /* maclhw - maclhw. - maclhwo - maclhwo. */
5069 /* maclhws - maclhws. - maclhwso - maclhwso. */
5070 /* nmaclhw - nmaclhw. - nmaclhwo - nmaclhwo. */
5071 /* nmaclhws - nmaclhws. - nmaclhwso - nmaclhwso. */
5072 /* mullhw - mullhw. */
5073 gen_op_405_mullhw();
5074 break;
5075 case 0x0C:
5076 /* maclhwu - maclhwu. - maclhwuo - maclhwuo. */
5077 /* maclhwsu - maclhwsu. - maclhwsuo - maclhwsuo. */
5078 /* mullhwu - mullhwu. */
5079 gen_op_405_mullhwu();
5080 break;
5082 if (opc2 & 0x02) {
5083 /* nmultiply-and-accumulate (0x0E) */
5084 gen_op_neg();
5086 if (opc2 & 0x04) {
5087 /* (n)multiply-and-accumulate (0x0C - 0x0E) */
5088 gen_op_load_gpr_T2(rt);
5089 gen_op_move_T1_T0();
5090 gen_op_405_add_T0_T2();
5092 if (opc3 & 0x10) {
5093 /* Check overflow */
5094 if (opc3 & 0x01)
5095 gen_op_405_check_ov();
5096 else
5097 gen_op_405_check_ovu();
5099 if (opc3 & 0x02) {
5100 /* Saturate */
5101 if (opc3 & 0x01)
5102 gen_op_405_check_sat();
5103 else
5104 gen_op_405_check_satu();
5106 gen_op_store_T0_gpr(rt);
5107 if (unlikely(Rc) != 0) {
5108 /* Update Rc0 */
5109 gen_set_Rc0(ctx);
5113 #define GEN_MAC_HANDLER(name, opc2, opc3) \
5114 GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_405_MAC) \
5116 gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode), \
5117 rD(ctx->opcode), Rc(ctx->opcode)); \
5120 /* macchw - macchw. */
5121 GEN_MAC_HANDLER(macchw, 0x0C, 0x05);
5122 /* macchwo - macchwo. */
5123 GEN_MAC_HANDLER(macchwo, 0x0C, 0x15);
5124 /* macchws - macchws. */
5125 GEN_MAC_HANDLER(macchws, 0x0C, 0x07);
5126 /* macchwso - macchwso. */
5127 GEN_MAC_HANDLER(macchwso, 0x0C, 0x17);
5128 /* macchwsu - macchwsu. */
5129 GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06);
5130 /* macchwsuo - macchwsuo. */
5131 GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16);
5132 /* macchwu - macchwu. */
5133 GEN_MAC_HANDLER(macchwu, 0x0C, 0x04);
5134 /* macchwuo - macchwuo. */
5135 GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14);
5136 /* machhw - machhw. */
5137 GEN_MAC_HANDLER(machhw, 0x0C, 0x01);
5138 /* machhwo - machhwo. */
5139 GEN_MAC_HANDLER(machhwo, 0x0C, 0x11);
5140 /* machhws - machhws. */
5141 GEN_MAC_HANDLER(machhws, 0x0C, 0x03);
5142 /* machhwso - machhwso. */
5143 GEN_MAC_HANDLER(machhwso, 0x0C, 0x13);
5144 /* machhwsu - machhwsu. */
5145 GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02);
5146 /* machhwsuo - machhwsuo. */
5147 GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12);
5148 /* machhwu - machhwu. */
5149 GEN_MAC_HANDLER(machhwu, 0x0C, 0x00);
5150 /* machhwuo - machhwuo. */
5151 GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10);
5152 /* maclhw - maclhw. */
5153 GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D);
5154 /* maclhwo - maclhwo. */
5155 GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D);
5156 /* maclhws - maclhws. */
5157 GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F);
5158 /* maclhwso - maclhwso. */
5159 GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F);
5160 /* maclhwu - maclhwu. */
5161 GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C);
5162 /* maclhwuo - maclhwuo. */
5163 GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C);
5164 /* maclhwsu - maclhwsu. */
5165 GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E);
5166 /* maclhwsuo - maclhwsuo. */
5167 GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E);
5168 /* nmacchw - nmacchw. */
5169 GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05);
5170 /* nmacchwo - nmacchwo. */
5171 GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15);
5172 /* nmacchws - nmacchws. */
5173 GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07);
5174 /* nmacchwso - nmacchwso. */
5175 GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17);
5176 /* nmachhw - nmachhw. */
5177 GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01);
5178 /* nmachhwo - nmachhwo. */
5179 GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11);
5180 /* nmachhws - nmachhws. */
5181 GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03);
5182 /* nmachhwso - nmachhwso. */
5183 GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13);
5184 /* nmaclhw - nmaclhw. */
5185 GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D);
5186 /* nmaclhwo - nmaclhwo. */
5187 GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D);
5188 /* nmaclhws - nmaclhws. */
5189 GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F);
5190 /* nmaclhwso - nmaclhwso. */
5191 GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F);
5193 /* mulchw - mulchw. */
5194 GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
5195 /* mulchwu - mulchwu. */
5196 GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
5197 /* mulhhw - mulhhw. */
5198 GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
5199 /* mulhhwu - mulhhwu. */
5200 GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
5201 /* mullhw - mullhw. */
5202 GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
5203 /* mullhwu - mullhwu. */
5204 GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
5206 /* mfdcr */
5207 GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_EMB_COMMON)
5209 #if defined(CONFIG_USER_ONLY)
5210 GEN_EXCP_PRIVREG(ctx);
5211 #else
5212 uint32_t dcrn = SPR(ctx->opcode);
5214 if (unlikely(!ctx->supervisor)) {
5215 GEN_EXCP_PRIVREG(ctx);
5216 return;
5218 gen_op_set_T0(dcrn);
5219 gen_op_load_dcr();
5220 gen_op_store_T0_gpr(rD(ctx->opcode));
5221 #endif
5224 /* mtdcr */
5225 GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_EMB_COMMON)
5227 #if defined(CONFIG_USER_ONLY)
5228 GEN_EXCP_PRIVREG(ctx);
5229 #else
5230 uint32_t dcrn = SPR(ctx->opcode);
5232 if (unlikely(!ctx->supervisor)) {
5233 GEN_EXCP_PRIVREG(ctx);
5234 return;
5236 gen_op_set_T0(dcrn);
5237 gen_op_load_gpr_T1(rS(ctx->opcode));
5238 gen_op_store_dcr();
5239 #endif
5242 /* mfdcrx */
5243 /* XXX: not implemented on 440 ? */
5244 GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000000, PPC_BOOKE_EXT)
5246 #if defined(CONFIG_USER_ONLY)
5247 GEN_EXCP_PRIVREG(ctx);
5248 #else
5249 if (unlikely(!ctx->supervisor)) {
5250 GEN_EXCP_PRIVREG(ctx);
5251 return;
5253 gen_op_load_gpr_T0(rA(ctx->opcode));
5254 gen_op_load_dcr();
5255 gen_op_store_T0_gpr(rD(ctx->opcode));
5256 /* Note: Rc update flag set leads to undefined state of Rc0 */
5257 #endif
5260 /* mtdcrx */
5261 /* XXX: not implemented on 440 ? */
5262 GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000000, PPC_BOOKE_EXT)
5264 #if defined(CONFIG_USER_ONLY)
5265 GEN_EXCP_PRIVREG(ctx);
5266 #else
5267 if (unlikely(!ctx->supervisor)) {
5268 GEN_EXCP_PRIVREG(ctx);
5269 return;
5271 gen_op_load_gpr_T0(rA(ctx->opcode));
5272 gen_op_load_gpr_T1(rS(ctx->opcode));
5273 gen_op_store_dcr();
5274 /* Note: Rc update flag set leads to undefined state of Rc0 */
5275 #endif
5278 /* mfdcrux (PPC 460) : user-mode access to DCR */
5279 GEN_HANDLER(mfdcrux, 0x1F, 0x03, 0x09, 0x00000000, PPC_DCRUX)
5281 gen_op_load_gpr_T0(rA(ctx->opcode));
5282 gen_op_load_dcr();
5283 gen_op_store_T0_gpr(rD(ctx->opcode));
5284 /* Note: Rc update flag set leads to undefined state of Rc0 */
5287 /* mtdcrux (PPC 460) : user-mode access to DCR */
5288 GEN_HANDLER(mtdcrux, 0x1F, 0x03, 0x0D, 0x00000000, PPC_DCRUX)
5290 gen_op_load_gpr_T0(rA(ctx->opcode));
5291 gen_op_load_gpr_T1(rS(ctx->opcode));
5292 gen_op_store_dcr();
5293 /* Note: Rc update flag set leads to undefined state of Rc0 */
5296 /* dccci */
5297 GEN_HANDLER(dccci, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON)
5299 #if defined(CONFIG_USER_ONLY)
5300 GEN_EXCP_PRIVOPC(ctx);
5301 #else
5302 if (unlikely(!ctx->supervisor)) {
5303 GEN_EXCP_PRIVOPC(ctx);
5304 return;
5306 /* interpreted as no-op */
5307 #endif
5310 /* dcread */
5311 GEN_HANDLER(dcread, 0x1F, 0x06, 0x0F, 0x00000001, PPC_4xx_COMMON)
5313 #if defined(CONFIG_USER_ONLY)
5314 GEN_EXCP_PRIVOPC(ctx);
5315 #else
5316 if (unlikely(!ctx->supervisor)) {
5317 GEN_EXCP_PRIVOPC(ctx);
5318 return;
5320 gen_addr_reg_index(ctx);
5321 op_ldst(lwz);
5322 gen_op_store_T0_gpr(rD(ctx->opcode));
5323 #endif
5326 /* icbt */
5327 GEN_HANDLER2(icbt_40x, "icbt", 0x1F, 0x06, 0x08, 0x03E00001, PPC_40x_ICBT)
5329 /* interpreted as no-op */
5330 /* XXX: specification say this is treated as a load by the MMU
5331 * but does not generate any exception
5335 /* iccci */
5336 GEN_HANDLER(iccci, 0x1F, 0x06, 0x1E, 0x00000001, PPC_4xx_COMMON)
5338 #if defined(CONFIG_USER_ONLY)
5339 GEN_EXCP_PRIVOPC(ctx);
5340 #else
5341 if (unlikely(!ctx->supervisor)) {
5342 GEN_EXCP_PRIVOPC(ctx);
5343 return;
5345 /* interpreted as no-op */
5346 #endif
5349 /* icread */
5350 GEN_HANDLER(icread, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON)
5352 #if defined(CONFIG_USER_ONLY)
5353 GEN_EXCP_PRIVOPC(ctx);
5354 #else
5355 if (unlikely(!ctx->supervisor)) {
5356 GEN_EXCP_PRIVOPC(ctx);
5357 return;
5359 /* interpreted as no-op */
5360 #endif
5363 /* rfci (supervisor only) */
5364 GEN_HANDLER2(rfci_40x, "rfci", 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP)
5366 #if defined(CONFIG_USER_ONLY)
5367 GEN_EXCP_PRIVOPC(ctx);
5368 #else
5369 if (unlikely(!ctx->supervisor)) {
5370 GEN_EXCP_PRIVOPC(ctx);
5371 return;
5373 /* Restore CPU state */
5374 gen_op_40x_rfci();
5375 GEN_SYNC(ctx);
5376 #endif
5379 GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE)
5381 #if defined(CONFIG_USER_ONLY)
5382 GEN_EXCP_PRIVOPC(ctx);
5383 #else
5384 if (unlikely(!ctx->supervisor)) {
5385 GEN_EXCP_PRIVOPC(ctx);
5386 return;
5388 /* Restore CPU state */
5389 gen_op_rfci();
5390 GEN_SYNC(ctx);
5391 #endif
5394 /* BookE specific */
5395 /* XXX: not implemented on 440 ? */
5396 GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_BOOKE_EXT)
5398 #if defined(CONFIG_USER_ONLY)
5399 GEN_EXCP_PRIVOPC(ctx);
5400 #else
5401 if (unlikely(!ctx->supervisor)) {
5402 GEN_EXCP_PRIVOPC(ctx);
5403 return;
5405 /* Restore CPU state */
5406 gen_op_rfdi();
5407 GEN_SYNC(ctx);
5408 #endif
5411 /* XXX: not implemented on 440 ? */
5412 GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI)
5414 #if defined(CONFIG_USER_ONLY)
5415 GEN_EXCP_PRIVOPC(ctx);
5416 #else
5417 if (unlikely(!ctx->supervisor)) {
5418 GEN_EXCP_PRIVOPC(ctx);
5419 return;
5421 /* Restore CPU state */
5422 gen_op_rfmci();
5423 GEN_SYNC(ctx);
5424 #endif
5427 /* TLB management - PowerPC 405 implementation */
5428 /* tlbre */
5429 GEN_HANDLER2(tlbre_40x, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB)
5431 #if defined(CONFIG_USER_ONLY)
5432 GEN_EXCP_PRIVOPC(ctx);
5433 #else
5434 if (unlikely(!ctx->supervisor)) {
5435 GEN_EXCP_PRIVOPC(ctx);
5436 return;
5438 switch (rB(ctx->opcode)) {
5439 case 0:
5440 gen_op_load_gpr_T0(rA(ctx->opcode));
5441 gen_op_4xx_tlbre_hi();
5442 gen_op_store_T0_gpr(rD(ctx->opcode));
5443 break;
5444 case 1:
5445 gen_op_load_gpr_T0(rA(ctx->opcode));
5446 gen_op_4xx_tlbre_lo();
5447 gen_op_store_T0_gpr(rD(ctx->opcode));
5448 break;
5449 default:
5450 GEN_EXCP_INVAL(ctx);
5451 break;
5453 #endif
5456 /* tlbsx - tlbsx. */
5457 GEN_HANDLER2(tlbsx_40x, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_TLB)
5459 #if defined(CONFIG_USER_ONLY)
5460 GEN_EXCP_PRIVOPC(ctx);
5461 #else
5462 if (unlikely(!ctx->supervisor)) {
5463 GEN_EXCP_PRIVOPC(ctx);
5464 return;
5466 gen_addr_reg_index(ctx);
5467 gen_op_4xx_tlbsx();
5468 if (Rc(ctx->opcode))
5469 gen_op_4xx_tlbsx_check();
5470 gen_op_store_T0_gpr(rD(ctx->opcode));
5471 #endif
5474 /* tlbwe */
5475 GEN_HANDLER2(tlbwe_40x, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB)
5477 #if defined(CONFIG_USER_ONLY)
5478 GEN_EXCP_PRIVOPC(ctx);
5479 #else
5480 if (unlikely(!ctx->supervisor)) {
5481 GEN_EXCP_PRIVOPC(ctx);
5482 return;
5484 switch (rB(ctx->opcode)) {
5485 case 0:
5486 gen_op_load_gpr_T0(rA(ctx->opcode));
5487 gen_op_load_gpr_T1(rS(ctx->opcode));
5488 gen_op_4xx_tlbwe_hi();
5489 break;
5490 case 1:
5491 gen_op_load_gpr_T0(rA(ctx->opcode));
5492 gen_op_load_gpr_T1(rS(ctx->opcode));
5493 gen_op_4xx_tlbwe_lo();
5494 break;
5495 default:
5496 GEN_EXCP_INVAL(ctx);
5497 break;
5499 #endif
5502 /* TLB management - PowerPC 440 implementation */
5503 /* tlbre */
5504 GEN_HANDLER2(tlbre_440, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE)
5506 #if defined(CONFIG_USER_ONLY)
5507 GEN_EXCP_PRIVOPC(ctx);
5508 #else
5509 if (unlikely(!ctx->supervisor)) {
5510 GEN_EXCP_PRIVOPC(ctx);
5511 return;
5513 switch (rB(ctx->opcode)) {
5514 case 0:
5515 case 1:
5516 case 2:
5517 gen_op_load_gpr_T0(rA(ctx->opcode));
5518 gen_op_440_tlbre(rB(ctx->opcode));
5519 gen_op_store_T0_gpr(rD(ctx->opcode));
5520 break;
5521 default:
5522 GEN_EXCP_INVAL(ctx);
5523 break;
5525 #endif
5528 /* tlbsx - tlbsx. */
5529 GEN_HANDLER2(tlbsx_440, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE)
5531 #if defined(CONFIG_USER_ONLY)
5532 GEN_EXCP_PRIVOPC(ctx);
5533 #else
5534 if (unlikely(!ctx->supervisor)) {
5535 GEN_EXCP_PRIVOPC(ctx);
5536 return;
5538 gen_addr_reg_index(ctx);
5539 gen_op_440_tlbsx();
5540 if (Rc(ctx->opcode))
5541 gen_op_4xx_tlbsx_check();
5542 gen_op_store_T0_gpr(rD(ctx->opcode));
5543 #endif
5546 /* tlbwe */
5547 GEN_HANDLER2(tlbwe_440, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE)
5549 #if defined(CONFIG_USER_ONLY)
5550 GEN_EXCP_PRIVOPC(ctx);
5551 #else
5552 if (unlikely(!ctx->supervisor)) {
5553 GEN_EXCP_PRIVOPC(ctx);
5554 return;
5556 switch (rB(ctx->opcode)) {
5557 case 0:
5558 case 1:
5559 case 2:
5560 gen_op_load_gpr_T0(rA(ctx->opcode));
5561 gen_op_load_gpr_T1(rS(ctx->opcode));
5562 gen_op_440_tlbwe(rB(ctx->opcode));
5563 break;
5564 default:
5565 GEN_EXCP_INVAL(ctx);
5566 break;
5568 #endif
5571 /* wrtee */
5572 GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_EMB_COMMON)
5574 #if defined(CONFIG_USER_ONLY)
5575 GEN_EXCP_PRIVOPC(ctx);
5576 #else
5577 if (unlikely(!ctx->supervisor)) {
5578 GEN_EXCP_PRIVOPC(ctx);
5579 return;
5581 gen_op_load_gpr_T0(rD(ctx->opcode));
5582 gen_op_wrte();
5583 /* Stop translation to have a chance to raise an exception
5584 * if we just set msr_ee to 1
5586 GEN_STOP(ctx);
5587 #endif
5590 /* wrteei */
5591 GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000EFC01, PPC_EMB_COMMON)
5593 #if defined(CONFIG_USER_ONLY)
5594 GEN_EXCP_PRIVOPC(ctx);
5595 #else
5596 if (unlikely(!ctx->supervisor)) {
5597 GEN_EXCP_PRIVOPC(ctx);
5598 return;
5600 gen_op_set_T0(ctx->opcode & 0x00010000);
5601 gen_op_wrte();
5602 /* Stop translation to have a chance to raise an exception
5603 * if we just set msr_ee to 1
5605 GEN_STOP(ctx);
5606 #endif
5609 /* PowerPC 440 specific instructions */
5610 /* dlmzb */
5611 GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC)
5613 gen_op_load_gpr_T0(rS(ctx->opcode));
5614 gen_op_load_gpr_T1(rB(ctx->opcode));
5615 gen_op_440_dlmzb();
5616 gen_op_store_T0_gpr(rA(ctx->opcode));
5617 gen_op_store_xer_bc();
5618 if (Rc(ctx->opcode)) {
5619 gen_op_440_dlmzb_update_Rc();
5620 gen_op_store_T0_crf(0);
5624 /* mbar replaces eieio on 440 */
5625 GEN_HANDLER(mbar, 0x1F, 0x16, 0x13, 0x001FF801, PPC_BOOKE)
5627 /* interpreted as no-op */
5630 /* msync replaces sync on 440 */
5631 GEN_HANDLER(msync, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE)
5633 /* interpreted as no-op */
5636 /* icbt */
5637 GEN_HANDLER2(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001, PPC_BOOKE)
5639 /* interpreted as no-op */
5640 /* XXX: specification say this is treated as a load by the MMU
5641 * but does not generate any exception
5645 /*** Altivec vector extension ***/
5646 /* Altivec registers moves */
5647 GEN32(gen_op_load_avr_A0, gen_op_load_avr_A0_avr);
5648 GEN32(gen_op_load_avr_A1, gen_op_load_avr_A1_avr);
5649 GEN32(gen_op_load_avr_A2, gen_op_load_avr_A2_avr);
5651 GEN32(gen_op_store_A0_avr, gen_op_store_A0_avr_avr);
5652 GEN32(gen_op_store_A1_avr, gen_op_store_A1_avr_avr);
5653 #if 0 // unused
5654 GEN32(gen_op_store_A2_avr, gen_op_store_A2_avr_avr);
5655 #endif
5657 #define op_vr_ldst(name) (*gen_op_##name[ctx->mem_idx])()
5658 #if defined(CONFIG_USER_ONLY)
5659 #if defined(TARGET_PPC64)
5660 /* User-mode only - 64 bits mode */
5661 #define OP_VR_LD_TABLE(name) \
5662 static GenOpFunc *gen_op_vr_l##name[] = { \
5663 &gen_op_vr_l##name##_raw, \
5664 &gen_op_vr_l##name##_le_raw, \
5665 &gen_op_vr_l##name##_64_raw, \
5666 &gen_op_vr_l##name##_le_64_raw, \
5668 #define OP_VR_ST_TABLE(name) \
5669 static GenOpFunc *gen_op_vr_st##name[] = { \
5670 &gen_op_vr_st##name##_raw, \
5671 &gen_op_vr_st##name##_le_raw, \
5672 &gen_op_vr_st##name##_64_raw, \
5673 &gen_op_vr_st##name##_le_64_raw, \
5675 #else /* defined(TARGET_PPC64) */
5676 /* User-mode only - 32 bits mode */
5677 #define OP_VR_LD_TABLE(name) \
5678 static GenOpFunc *gen_op_vr_l##name[] = { \
5679 &gen_op_vr_l##name##_raw, \
5680 &gen_op_vr_l##name##_le_raw, \
5682 #define OP_VR_ST_TABLE(name) \
5683 static GenOpFunc *gen_op_vr_st##name[] = { \
5684 &gen_op_vr_st##name##_raw, \
5685 &gen_op_vr_st##name##_le_raw, \
5687 #endif /* defined(TARGET_PPC64) */
5688 #else /* defined(CONFIG_USER_ONLY) */
5689 #if defined(TARGET_PPC64H)
5690 /* Full system with hypervisor mode */
5691 #define OP_VR_LD_TABLE(name) \
5692 static GenOpFunc *gen_op_vr_l##name[] = { \
5693 &gen_op_vr_l##name##_user, \
5694 &gen_op_vr_l##name##_le_user, \
5695 &gen_op_vr_l##name##_64_user, \
5696 &gen_op_vr_l##name##_le_64_user, \
5697 &gen_op_vr_l##name##_kernel, \
5698 &gen_op_vr_l##name##_le_kernel, \
5699 &gen_op_vr_l##name##_64_kernel, \
5700 &gen_op_vr_l##name##_le_64_kernel, \
5701 &gen_op_vr_l##name##_hypv, \
5702 &gen_op_vr_l##name##_le_hypv, \
5703 &gen_op_vr_l##name##_64_hypv, \
5704 &gen_op_vr_l##name##_le_64_hypv, \
5706 #define OP_VR_ST_TABLE(name) \
5707 static GenOpFunc *gen_op_vr_st##name[] = { \
5708 &gen_op_vr_st##name##_user, \
5709 &gen_op_vr_st##name##_le_user, \
5710 &gen_op_vr_st##name##_64_user, \
5711 &gen_op_vr_st##name##_le_64_user, \
5712 &gen_op_vr_st##name##_kernel, \
5713 &gen_op_vr_st##name##_le_kernel, \
5714 &gen_op_vr_st##name##_64_kernel, \
5715 &gen_op_vr_st##name##_le_64_kernel, \
5716 &gen_op_vr_st##name##_hypv, \
5717 &gen_op_vr_st##name##_le_hypv, \
5718 &gen_op_vr_st##name##_64_hypv, \
5719 &gen_op_vr_st##name##_le_64_hypv, \
5721 #elif defined(TARGET_PPC64)
5722 /* Full system - 64 bits mode */
5723 #define OP_VR_LD_TABLE(name) \
5724 static GenOpFunc *gen_op_vr_l##name[] = { \
5725 &gen_op_vr_l##name##_user, \
5726 &gen_op_vr_l##name##_le_user, \
5727 &gen_op_vr_l##name##_64_user, \
5728 &gen_op_vr_l##name##_le_64_user, \
5729 &gen_op_vr_l##name##_kernel, \
5730 &gen_op_vr_l##name##_le_kernel, \
5731 &gen_op_vr_l##name##_64_kernel, \
5732 &gen_op_vr_l##name##_le_64_kernel, \
5734 #define OP_VR_ST_TABLE(name) \
5735 static GenOpFunc *gen_op_vr_st##name[] = { \
5736 &gen_op_vr_st##name##_user, \
5737 &gen_op_vr_st##name##_le_user, \
5738 &gen_op_vr_st##name##_64_user, \
5739 &gen_op_vr_st##name##_le_64_user, \
5740 &gen_op_vr_st##name##_kernel, \
5741 &gen_op_vr_st##name##_le_kernel, \
5742 &gen_op_vr_st##name##_64_kernel, \
5743 &gen_op_vr_st##name##_le_64_kernel, \
5745 #else /* defined(TARGET_PPC64) */
5746 /* Full system - 32 bits mode */
5747 #define OP_VR_LD_TABLE(name) \
5748 static GenOpFunc *gen_op_vr_l##name[] = { \
5749 &gen_op_vr_l##name##_user, \
5750 &gen_op_vr_l##name##_le_user, \
5751 &gen_op_vr_l##name##_kernel, \
5752 &gen_op_vr_l##name##_le_kernel, \
5754 #define OP_VR_ST_TABLE(name) \
5755 static GenOpFunc *gen_op_vr_st##name[] = { \
5756 &gen_op_vr_st##name##_user, \
5757 &gen_op_vr_st##name##_le_user, \
5758 &gen_op_vr_st##name##_kernel, \
5759 &gen_op_vr_st##name##_le_kernel, \
5761 #endif /* defined(TARGET_PPC64) */
5762 #endif /* defined(CONFIG_USER_ONLY) */
5764 #define GEN_VR_LDX(name, opc2, opc3) \
5765 GEN_HANDLER(l##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC) \
5767 if (unlikely(!ctx->altivec_enabled)) { \
5768 GEN_EXCP_NO_VR(ctx); \
5769 return; \
5771 gen_addr_reg_index(ctx); \
5772 op_vr_ldst(vr_l##name); \
5773 gen_op_store_A0_avr(rD(ctx->opcode)); \
5776 #define GEN_VR_STX(name, opc2, opc3) \
5777 GEN_HANDLER(st##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC) \
5779 if (unlikely(!ctx->altivec_enabled)) { \
5780 GEN_EXCP_NO_VR(ctx); \
5781 return; \
5783 gen_addr_reg_index(ctx); \
5784 gen_op_load_avr_A0(rS(ctx->opcode)); \
5785 op_vr_ldst(vr_st##name); \
5788 OP_VR_LD_TABLE(vx);
5789 GEN_VR_LDX(vx, 0x07, 0x03);
5790 /* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
5791 #define gen_op_vr_lvxl gen_op_vr_lvx
5792 GEN_VR_LDX(vxl, 0x07, 0x0B);
5794 OP_VR_ST_TABLE(vx);
5795 GEN_VR_STX(vx, 0x07, 0x07);
5796 /* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
5797 #define gen_op_vr_stvxl gen_op_vr_stvx
5798 GEN_VR_STX(vxl, 0x07, 0x0F);
5800 #if defined(TARGET_PPCEMB)
5801 /*** SPE extension ***/
5803 /* Register moves */
5804 GEN32(gen_op_load_gpr64_T0, gen_op_load_gpr64_T0_gpr);
5805 GEN32(gen_op_load_gpr64_T1, gen_op_load_gpr64_T1_gpr);
5806 #if 0 // unused
5807 GEN32(gen_op_load_gpr64_T2, gen_op_load_gpr64_T2_gpr);
5808 #endif
5810 GEN32(gen_op_store_T0_gpr64, gen_op_store_T0_gpr64_gpr);
5811 GEN32(gen_op_store_T1_gpr64, gen_op_store_T1_gpr64_gpr);
5812 #if 0 // unused
5813 GEN32(gen_op_store_T2_gpr64, gen_op_store_T2_gpr64_gpr);
5814 #endif
5816 #define GEN_SPE(name0, name1, opc2, opc3, inval, type) \
5817 GEN_HANDLER(name0##_##name1, 0x04, opc2, opc3, inval, type) \
5819 if (Rc(ctx->opcode)) \
5820 gen_##name1(ctx); \
5821 else \
5822 gen_##name0(ctx); \
5825 /* Handler for undefined SPE opcodes */
5826 static always_inline void gen_speundef (DisasContext *ctx)
5828 GEN_EXCP_INVAL(ctx);
5831 /* SPE load and stores */
5832 static always_inline void gen_addr_spe_imm_index (DisasContext *ctx, int sh)
5834 target_long simm = rB(ctx->opcode);
5836 if (rA(ctx->opcode) == 0) {
5837 gen_set_T0(simm << sh);
5838 } else {
5839 gen_op_load_gpr_T0(rA(ctx->opcode));
5840 if (likely(simm != 0))
5841 gen_op_addi(simm << sh);
5845 #define op_spe_ldst(name) (*gen_op_##name[ctx->mem_idx])()
5846 #if defined(CONFIG_USER_ONLY)
5847 #if defined(TARGET_PPC64)
5848 /* User-mode only - 64 bits mode */
5849 #define OP_SPE_LD_TABLE(name) \
5850 static GenOpFunc *gen_op_spe_l##name[] = { \
5851 &gen_op_spe_l##name##_raw, \
5852 &gen_op_spe_l##name##_le_raw, \
5853 &gen_op_spe_l##name##_64_raw, \
5854 &gen_op_spe_l##name##_le_64_raw, \
5856 #define OP_SPE_ST_TABLE(name) \
5857 static GenOpFunc *gen_op_spe_st##name[] = { \
5858 &gen_op_spe_st##name##_raw, \
5859 &gen_op_spe_st##name##_le_raw, \
5860 &gen_op_spe_st##name##_64_raw, \
5861 &gen_op_spe_st##name##_le_64_raw, \
5863 #else /* defined(TARGET_PPC64) */
5864 /* User-mode only - 32 bits mode */
5865 #define OP_SPE_LD_TABLE(name) \
5866 static GenOpFunc *gen_op_spe_l##name[] = { \
5867 &gen_op_spe_l##name##_raw, \
5868 &gen_op_spe_l##name##_le_raw, \
5870 #define OP_SPE_ST_TABLE(name) \
5871 static GenOpFunc *gen_op_spe_st##name[] = { \
5872 &gen_op_spe_st##name##_raw, \
5873 &gen_op_spe_st##name##_le_raw, \
5875 #endif /* defined(TARGET_PPC64) */
5876 #else /* defined(CONFIG_USER_ONLY) */
5877 #if defined(TARGET_PPC64H)
5878 /* Full system with hypervisor mode */
5879 #define OP_SPE_LD_TABLE(name) \
5880 static GenOpFunc *gen_op_spe_l##name[] = { \
5881 &gen_op_spe_l##name##_user, \
5882 &gen_op_spe_l##name##_le_user, \
5883 &gen_op_spe_l##name##_64_user, \
5884 &gen_op_spe_l##name##_le_64_user, \
5885 &gen_op_spe_l##name##_kernel, \
5886 &gen_op_spe_l##name##_le_kernel, \
5887 &gen_op_spe_l##name##_64_kernel, \
5888 &gen_op_spe_l##name##_le_64_kernel, \
5889 &gen_op_spe_l##name##_hypv, \
5890 &gen_op_spe_l##name##_le_hypv, \
5891 &gen_op_spe_l##name##_64_hypv, \
5892 &gen_op_spe_l##name##_le_64_hypv, \
5894 #define OP_SPE_ST_TABLE(name) \
5895 static GenOpFunc *gen_op_spe_st##name[] = { \
5896 &gen_op_spe_st##name##_user, \
5897 &gen_op_spe_st##name##_le_user, \
5898 &gen_op_spe_st##name##_64_user, \
5899 &gen_op_spe_st##name##_le_64_user, \
5900 &gen_op_spe_st##name##_kernel, \
5901 &gen_op_spe_st##name##_le_kernel, \
5902 &gen_op_spe_st##name##_64_kernel, \
5903 &gen_op_spe_st##name##_le_64_kernel, \
5904 &gen_op_spe_st##name##_hypv, \
5905 &gen_op_spe_st##name##_le_hypv, \
5906 &gen_op_spe_st##name##_64_hypv, \
5907 &gen_op_spe_st##name##_le_64_hypv, \
5909 #elif defined(TARGET_PPC64)
5910 /* Full system - 64 bits mode */
5911 #define OP_SPE_LD_TABLE(name) \
5912 static GenOpFunc *gen_op_spe_l##name[] = { \
5913 &gen_op_spe_l##name##_user, \
5914 &gen_op_spe_l##name##_le_user, \
5915 &gen_op_spe_l##name##_64_user, \
5916 &gen_op_spe_l##name##_le_64_user, \
5917 &gen_op_spe_l##name##_kernel, \
5918 &gen_op_spe_l##name##_le_kernel, \
5919 &gen_op_spe_l##name##_64_kernel, \
5920 &gen_op_spe_l##name##_le_64_kernel, \
5922 #define OP_SPE_ST_TABLE(name) \
5923 static GenOpFunc *gen_op_spe_st##name[] = { \
5924 &gen_op_spe_st##name##_user, \
5925 &gen_op_spe_st##name##_le_user, \
5926 &gen_op_spe_st##name##_64_user, \
5927 &gen_op_spe_st##name##_le_64_user, \
5928 &gen_op_spe_st##name##_kernel, \
5929 &gen_op_spe_st##name##_le_kernel, \
5930 &gen_op_spe_st##name##_64_kernel, \
5931 &gen_op_spe_st##name##_le_64_kernel, \
5933 #else /* defined(TARGET_PPC64) */
5934 /* Full system - 32 bits mode */
5935 #define OP_SPE_LD_TABLE(name) \
5936 static GenOpFunc *gen_op_spe_l##name[] = { \
5937 &gen_op_spe_l##name##_user, \
5938 &gen_op_spe_l##name##_le_user, \
5939 &gen_op_spe_l##name##_kernel, \
5940 &gen_op_spe_l##name##_le_kernel, \
5942 #define OP_SPE_ST_TABLE(name) \
5943 static GenOpFunc *gen_op_spe_st##name[] = { \
5944 &gen_op_spe_st##name##_user, \
5945 &gen_op_spe_st##name##_le_user, \
5946 &gen_op_spe_st##name##_kernel, \
5947 &gen_op_spe_st##name##_le_kernel, \
5949 #endif /* defined(TARGET_PPC64) */
5950 #endif /* defined(CONFIG_USER_ONLY) */
5952 #define GEN_SPE_LD(name, sh) \
5953 static always_inline void gen_evl##name (DisasContext *ctx) \
5955 if (unlikely(!ctx->spe_enabled)) { \
5956 GEN_EXCP_NO_AP(ctx); \
5957 return; \
5959 gen_addr_spe_imm_index(ctx, sh); \
5960 op_spe_ldst(spe_l##name); \
5961 gen_op_store_T1_gpr64(rD(ctx->opcode)); \
5964 #define GEN_SPE_LDX(name) \
5965 static always_inline void gen_evl##name##x (DisasContext *ctx) \
5967 if (unlikely(!ctx->spe_enabled)) { \
5968 GEN_EXCP_NO_AP(ctx); \
5969 return; \
5971 gen_addr_reg_index(ctx); \
5972 op_spe_ldst(spe_l##name); \
5973 gen_op_store_T1_gpr64(rD(ctx->opcode)); \
5976 #define GEN_SPEOP_LD(name, sh) \
5977 OP_SPE_LD_TABLE(name); \
5978 GEN_SPE_LD(name, sh); \
5979 GEN_SPE_LDX(name)
5981 #define GEN_SPE_ST(name, sh) \
5982 static always_inline void gen_evst##name (DisasContext *ctx) \
5984 if (unlikely(!ctx->spe_enabled)) { \
5985 GEN_EXCP_NO_AP(ctx); \
5986 return; \
5988 gen_addr_spe_imm_index(ctx, sh); \
5989 gen_op_load_gpr64_T1(rS(ctx->opcode)); \
5990 op_spe_ldst(spe_st##name); \
5993 #define GEN_SPE_STX(name) \
5994 static always_inline void gen_evst##name##x (DisasContext *ctx) \
5996 if (unlikely(!ctx->spe_enabled)) { \
5997 GEN_EXCP_NO_AP(ctx); \
5998 return; \
6000 gen_addr_reg_index(ctx); \
6001 gen_op_load_gpr64_T1(rS(ctx->opcode)); \
6002 op_spe_ldst(spe_st##name); \
6005 #define GEN_SPEOP_ST(name, sh) \
6006 OP_SPE_ST_TABLE(name); \
6007 GEN_SPE_ST(name, sh); \
6008 GEN_SPE_STX(name)
6010 #define GEN_SPEOP_LDST(name, sh) \
6011 GEN_SPEOP_LD(name, sh); \
6012 GEN_SPEOP_ST(name, sh)
6014 /* SPE arithmetic and logic */
6015 #define GEN_SPEOP_ARITH2(name) \
6016 static always_inline void gen_##name (DisasContext *ctx) \
6018 if (unlikely(!ctx->spe_enabled)) { \
6019 GEN_EXCP_NO_AP(ctx); \
6020 return; \
6022 gen_op_load_gpr64_T0(rA(ctx->opcode)); \
6023 gen_op_load_gpr64_T1(rB(ctx->opcode)); \
6024 gen_op_##name(); \
6025 gen_op_store_T0_gpr64(rD(ctx->opcode)); \
6028 #define GEN_SPEOP_ARITH1(name) \
6029 static always_inline void gen_##name (DisasContext *ctx) \
6031 if (unlikely(!ctx->spe_enabled)) { \
6032 GEN_EXCP_NO_AP(ctx); \
6033 return; \
6035 gen_op_load_gpr64_T0(rA(ctx->opcode)); \
6036 gen_op_##name(); \
6037 gen_op_store_T0_gpr64(rD(ctx->opcode)); \
6040 #define GEN_SPEOP_COMP(name) \
6041 static always_inline void gen_##name (DisasContext *ctx) \
6043 if (unlikely(!ctx->spe_enabled)) { \
6044 GEN_EXCP_NO_AP(ctx); \
6045 return; \
6047 gen_op_load_gpr64_T0(rA(ctx->opcode)); \
6048 gen_op_load_gpr64_T1(rB(ctx->opcode)); \
6049 gen_op_##name(); \
6050 gen_op_store_T0_crf(crfD(ctx->opcode)); \
6053 /* Logical */
6054 GEN_SPEOP_ARITH2(evand);
6055 GEN_SPEOP_ARITH2(evandc);
6056 GEN_SPEOP_ARITH2(evxor);
6057 GEN_SPEOP_ARITH2(evor);
6058 GEN_SPEOP_ARITH2(evnor);
6059 GEN_SPEOP_ARITH2(eveqv);
6060 GEN_SPEOP_ARITH2(evorc);
6061 GEN_SPEOP_ARITH2(evnand);
6062 GEN_SPEOP_ARITH2(evsrwu);
6063 GEN_SPEOP_ARITH2(evsrws);
6064 GEN_SPEOP_ARITH2(evslw);
6065 GEN_SPEOP_ARITH2(evrlw);
6066 GEN_SPEOP_ARITH2(evmergehi);
6067 GEN_SPEOP_ARITH2(evmergelo);
6068 GEN_SPEOP_ARITH2(evmergehilo);
6069 GEN_SPEOP_ARITH2(evmergelohi);
6071 /* Arithmetic */
6072 GEN_SPEOP_ARITH2(evaddw);
6073 GEN_SPEOP_ARITH2(evsubfw);
6074 GEN_SPEOP_ARITH1(evabs);
6075 GEN_SPEOP_ARITH1(evneg);
6076 GEN_SPEOP_ARITH1(evextsb);
6077 GEN_SPEOP_ARITH1(evextsh);
6078 GEN_SPEOP_ARITH1(evrndw);
6079 GEN_SPEOP_ARITH1(evcntlzw);
6080 GEN_SPEOP_ARITH1(evcntlsw);
6081 static always_inline void gen_brinc (DisasContext *ctx)
6083 /* Note: brinc is usable even if SPE is disabled */
6084 gen_op_load_gpr64_T0(rA(ctx->opcode));
6085 gen_op_load_gpr64_T1(rB(ctx->opcode));
6086 gen_op_brinc();
6087 gen_op_store_T0_gpr64(rD(ctx->opcode));
6090 #define GEN_SPEOP_ARITH_IMM2(name) \
6091 static always_inline void gen_##name##i (DisasContext *ctx) \
6093 if (unlikely(!ctx->spe_enabled)) { \
6094 GEN_EXCP_NO_AP(ctx); \
6095 return; \
6097 gen_op_load_gpr64_T0(rB(ctx->opcode)); \
6098 gen_op_splatwi_T1_64(rA(ctx->opcode)); \
6099 gen_op_##name(); \
6100 gen_op_store_T0_gpr64(rD(ctx->opcode)); \
6103 #define GEN_SPEOP_LOGIC_IMM2(name) \
6104 static always_inline void gen_##name##i (DisasContext *ctx) \
6106 if (unlikely(!ctx->spe_enabled)) { \
6107 GEN_EXCP_NO_AP(ctx); \
6108 return; \
6110 gen_op_load_gpr64_T0(rA(ctx->opcode)); \
6111 gen_op_splatwi_T1_64(rB(ctx->opcode)); \
6112 gen_op_##name(); \
6113 gen_op_store_T0_gpr64(rD(ctx->opcode)); \
6116 GEN_SPEOP_ARITH_IMM2(evaddw);
6117 #define gen_evaddiw gen_evaddwi
6118 GEN_SPEOP_ARITH_IMM2(evsubfw);
6119 #define gen_evsubifw gen_evsubfwi
6120 GEN_SPEOP_LOGIC_IMM2(evslw);
6121 GEN_SPEOP_LOGIC_IMM2(evsrwu);
6122 #define gen_evsrwis gen_evsrwsi
6123 GEN_SPEOP_LOGIC_IMM2(evsrws);
6124 #define gen_evsrwiu gen_evsrwui
6125 GEN_SPEOP_LOGIC_IMM2(evrlw);
6127 static always_inline void gen_evsplati (DisasContext *ctx)
6129 int32_t imm = (int32_t)(rA(ctx->opcode) << 27) >> 27;
6131 gen_op_splatwi_T0_64(imm);
6132 gen_op_store_T0_gpr64(rD(ctx->opcode));
6135 static always_inline void gen_evsplatfi (DisasContext *ctx)
6137 uint32_t imm = rA(ctx->opcode) << 27;
6139 gen_op_splatwi_T0_64(imm);
6140 gen_op_store_T0_gpr64(rD(ctx->opcode));
6143 /* Comparison */
6144 GEN_SPEOP_COMP(evcmpgtu);
6145 GEN_SPEOP_COMP(evcmpgts);
6146 GEN_SPEOP_COMP(evcmpltu);
6147 GEN_SPEOP_COMP(evcmplts);
6148 GEN_SPEOP_COMP(evcmpeq);
6150 GEN_SPE(evaddw, speundef, 0x00, 0x08, 0x00000000, PPC_SPE); ////
6151 GEN_SPE(evaddiw, speundef, 0x01, 0x08, 0x00000000, PPC_SPE);
6152 GEN_SPE(evsubfw, speundef, 0x02, 0x08, 0x00000000, PPC_SPE); ////
6153 GEN_SPE(evsubifw, speundef, 0x03, 0x08, 0x00000000, PPC_SPE);
6154 GEN_SPE(evabs, evneg, 0x04, 0x08, 0x0000F800, PPC_SPE); ////
6155 GEN_SPE(evextsb, evextsh, 0x05, 0x08, 0x0000F800, PPC_SPE); ////
6156 GEN_SPE(evrndw, evcntlzw, 0x06, 0x08, 0x0000F800, PPC_SPE); ////
6157 GEN_SPE(evcntlsw, brinc, 0x07, 0x08, 0x00000000, PPC_SPE); //
6158 GEN_SPE(speundef, evand, 0x08, 0x08, 0x00000000, PPC_SPE); ////
6159 GEN_SPE(evandc, speundef, 0x09, 0x08, 0x00000000, PPC_SPE); ////
6160 GEN_SPE(evxor, evor, 0x0B, 0x08, 0x00000000, PPC_SPE); ////
6161 GEN_SPE(evnor, eveqv, 0x0C, 0x08, 0x00000000, PPC_SPE); ////
6162 GEN_SPE(speundef, evorc, 0x0D, 0x08, 0x00000000, PPC_SPE); ////
6163 GEN_SPE(evnand, speundef, 0x0F, 0x08, 0x00000000, PPC_SPE); ////
6164 GEN_SPE(evsrwu, evsrws, 0x10, 0x08, 0x00000000, PPC_SPE); ////
6165 GEN_SPE(evsrwiu, evsrwis, 0x11, 0x08, 0x00000000, PPC_SPE);
6166 GEN_SPE(evslw, speundef, 0x12, 0x08, 0x00000000, PPC_SPE); ////
6167 GEN_SPE(evslwi, speundef, 0x13, 0x08, 0x00000000, PPC_SPE);
6168 GEN_SPE(evrlw, evsplati, 0x14, 0x08, 0x00000000, PPC_SPE); //
6169 GEN_SPE(evrlwi, evsplatfi, 0x15, 0x08, 0x00000000, PPC_SPE);
6170 GEN_SPE(evmergehi, evmergelo, 0x16, 0x08, 0x00000000, PPC_SPE); ////
6171 GEN_SPE(evmergehilo, evmergelohi, 0x17, 0x08, 0x00000000, PPC_SPE); ////
6172 GEN_SPE(evcmpgtu, evcmpgts, 0x18, 0x08, 0x00600000, PPC_SPE); ////
6173 GEN_SPE(evcmpltu, evcmplts, 0x19, 0x08, 0x00600000, PPC_SPE); ////
6174 GEN_SPE(evcmpeq, speundef, 0x1A, 0x08, 0x00600000, PPC_SPE); ////
6176 static always_inline void gen_evsel (DisasContext *ctx)
6178 if (unlikely(!ctx->spe_enabled)) {
6179 GEN_EXCP_NO_AP(ctx);
6180 return;
6182 gen_op_load_crf_T0(ctx->opcode & 0x7);
6183 gen_op_load_gpr64_T0(rA(ctx->opcode));
6184 gen_op_load_gpr64_T1(rB(ctx->opcode));
6185 gen_op_evsel();
6186 gen_op_store_T0_gpr64(rD(ctx->opcode));
6189 GEN_HANDLER2(evsel0, "evsel", 0x04, 0x1c, 0x09, 0x00000000, PPC_SPE)
6191 gen_evsel(ctx);
6193 GEN_HANDLER2(evsel1, "evsel", 0x04, 0x1d, 0x09, 0x00000000, PPC_SPE)
6195 gen_evsel(ctx);
6197 GEN_HANDLER2(evsel2, "evsel", 0x04, 0x1e, 0x09, 0x00000000, PPC_SPE)
6199 gen_evsel(ctx);
6201 GEN_HANDLER2(evsel3, "evsel", 0x04, 0x1f, 0x09, 0x00000000, PPC_SPE)
6203 gen_evsel(ctx);
6206 /* Load and stores */
6207 #if defined(TARGET_PPC64)
6208 /* In that case, we already have 64 bits load & stores
6209 * so, spe_ldd is equivalent to ld and spe_std is equivalent to std
6211 #if defined(CONFIG_USER_ONLY)
6212 #define gen_op_spe_ldd_raw gen_op_ld_raw
6213 #define gen_op_spe_ldd_64_raw gen_op_ld_64_raw
6214 #define gen_op_spe_ldd_le_raw gen_op_ld_le_raw
6215 #define gen_op_spe_ldd_le_64_raw gen_op_ld_le_64_raw
6216 #define gen_op_spe_stdd_raw gen_op_ld_raw
6217 #define gen_op_spe_stdd_64_raw gen_op_std_64_raw
6218 #define gen_op_spe_stdd_le_raw gen_op_std_le_raw
6219 #define gen_op_spe_stdd_le_64_raw gen_op_std_le_64_raw
6220 #else /* defined(CONFIG_USER_ONLY) */
6221 #define gen_op_spe_ldd_kernel gen_op_ld_kernel
6222 #define gen_op_spe_ldd_64_kernel gen_op_ld_64_kernel
6223 #define gen_op_spe_ldd_le_kernel gen_op_ld_kernel
6224 #define gen_op_spe_ldd_le_64_kernel gen_op_ld_64_kernel
6225 #define gen_op_spe_ldd_user gen_op_ld_user
6226 #define gen_op_spe_ldd_64_user gen_op_ld_64_user
6227 #define gen_op_spe_ldd_le_user gen_op_ld_le_user
6228 #define gen_op_spe_ldd_le_64_user gen_op_ld_le_64_user
6229 #define gen_op_spe_stdd_kernel gen_op_std_kernel
6230 #define gen_op_spe_stdd_64_kernel gen_op_std_64_kernel
6231 #define gen_op_spe_stdd_le_kernel gen_op_std_kernel
6232 #define gen_op_spe_stdd_le_64_kernel gen_op_std_64_kernel
6233 #define gen_op_spe_stdd_user gen_op_std_user
6234 #define gen_op_spe_stdd_64_user gen_op_std_64_user
6235 #define gen_op_spe_stdd_le_user gen_op_std_le_user
6236 #define gen_op_spe_stdd_le_64_user gen_op_std_le_64_user
6237 #endif /* defined(CONFIG_USER_ONLY) */
6238 #endif /* defined(TARGET_PPC64) */
6239 GEN_SPEOP_LDST(dd, 3);
6240 GEN_SPEOP_LDST(dw, 3);
6241 GEN_SPEOP_LDST(dh, 3);
6242 GEN_SPEOP_LDST(whe, 2);
6243 GEN_SPEOP_LD(whou, 2);
6244 GEN_SPEOP_LD(whos, 2);
6245 GEN_SPEOP_ST(who, 2);
6247 #if defined(TARGET_PPC64)
6248 /* In that case, spe_stwwo is equivalent to stw */
6249 #if defined(CONFIG_USER_ONLY)
6250 #define gen_op_spe_stwwo_raw gen_op_stw_raw
6251 #define gen_op_spe_stwwo_le_raw gen_op_stw_le_raw
6252 #define gen_op_spe_stwwo_64_raw gen_op_stw_64_raw
6253 #define gen_op_spe_stwwo_le_64_raw gen_op_stw_le_64_raw
6254 #else
6255 #define gen_op_spe_stwwo_user gen_op_stw_user
6256 #define gen_op_spe_stwwo_le_user gen_op_stw_le_user
6257 #define gen_op_spe_stwwo_64_user gen_op_stw_64_user
6258 #define gen_op_spe_stwwo_le_64_user gen_op_stw_le_64_user
6259 #define gen_op_spe_stwwo_kernel gen_op_stw_kernel
6260 #define gen_op_spe_stwwo_le_kernel gen_op_stw_le_kernel
6261 #define gen_op_spe_stwwo_64_kernel gen_op_stw_64_kernel
6262 #define gen_op_spe_stwwo_le_64_kernel gen_op_stw_le_64_kernel
6263 #endif
6264 #endif
6265 #define _GEN_OP_SPE_STWWE(suffix) \
6266 static always_inline void gen_op_spe_stwwe_##suffix (void) \
6268 gen_op_srli32_T1_64(); \
6269 gen_op_spe_stwwo_##suffix(); \
6271 #define _GEN_OP_SPE_STWWE_LE(suffix) \
6272 static always_inline void gen_op_spe_stwwe_le_##suffix (void) \
6274 gen_op_srli32_T1_64(); \
6275 gen_op_spe_stwwo_le_##suffix(); \
6277 #if defined(TARGET_PPC64)
6278 #define GEN_OP_SPE_STWWE(suffix) \
6279 _GEN_OP_SPE_STWWE(suffix); \
6280 _GEN_OP_SPE_STWWE_LE(suffix); \
6281 static always_inline void gen_op_spe_stwwe_64_##suffix (void) \
6283 gen_op_srli32_T1_64(); \
6284 gen_op_spe_stwwo_64_##suffix(); \
6286 static always_inline void gen_op_spe_stwwe_le_64_##suffix (void) \
6288 gen_op_srli32_T1_64(); \
6289 gen_op_spe_stwwo_le_64_##suffix(); \
6291 #else
6292 #define GEN_OP_SPE_STWWE(suffix) \
6293 _GEN_OP_SPE_STWWE(suffix); \
6294 _GEN_OP_SPE_STWWE_LE(suffix)
6295 #endif
6296 #if defined(CONFIG_USER_ONLY)
6297 GEN_OP_SPE_STWWE(raw);
6298 #else /* defined(CONFIG_USER_ONLY) */
6299 GEN_OP_SPE_STWWE(kernel);
6300 GEN_OP_SPE_STWWE(user);
6301 #endif /* defined(CONFIG_USER_ONLY) */
6302 GEN_SPEOP_ST(wwe, 2);
6303 GEN_SPEOP_ST(wwo, 2);
6305 #define GEN_SPE_LDSPLAT(name, op, suffix) \
6306 static always_inline void gen_op_spe_l##name##_##suffix (void) \
6308 gen_op_##op##_##suffix(); \
6309 gen_op_splatw_T1_64(); \
6312 #define GEN_OP_SPE_LHE(suffix) \
6313 static always_inline void gen_op_spe_lhe_##suffix (void) \
6315 gen_op_spe_lh_##suffix(); \
6316 gen_op_sli16_T1_64(); \
6319 #define GEN_OP_SPE_LHX(suffix) \
6320 static always_inline void gen_op_spe_lhx_##suffix (void) \
6322 gen_op_spe_lh_##suffix(); \
6323 gen_op_extsh_T1_64(); \
6326 #if defined(CONFIG_USER_ONLY)
6327 GEN_OP_SPE_LHE(raw);
6328 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, raw);
6329 GEN_OP_SPE_LHE(le_raw);
6330 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_raw);
6331 GEN_SPE_LDSPLAT(hhousplat, spe_lh, raw);
6332 GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_raw);
6333 GEN_OP_SPE_LHX(raw);
6334 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, raw);
6335 GEN_OP_SPE_LHX(le_raw);
6336 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_raw);
6337 #if defined(TARGET_PPC64)
6338 GEN_OP_SPE_LHE(64_raw);
6339 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_raw);
6340 GEN_OP_SPE_LHE(le_64_raw);
6341 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_raw);
6342 GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_raw);
6343 GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_raw);
6344 GEN_OP_SPE_LHX(64_raw);
6345 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_raw);
6346 GEN_OP_SPE_LHX(le_64_raw);
6347 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_raw);
6348 #endif
6349 #else
6350 GEN_OP_SPE_LHE(kernel);
6351 GEN_OP_SPE_LHE(user);
6352 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, kernel);
6353 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, user);
6354 GEN_OP_SPE_LHE(le_kernel);
6355 GEN_OP_SPE_LHE(le_user);
6356 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_kernel);
6357 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_user);
6358 GEN_SPE_LDSPLAT(hhousplat, spe_lh, kernel);
6359 GEN_SPE_LDSPLAT(hhousplat, spe_lh, user);
6360 GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_kernel);
6361 GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_user);
6362 GEN_OP_SPE_LHX(kernel);
6363 GEN_OP_SPE_LHX(user);
6364 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, kernel);
6365 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, user);
6366 GEN_OP_SPE_LHX(le_kernel);
6367 GEN_OP_SPE_LHX(le_user);
6368 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_kernel);
6369 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_user);
6370 #if defined(TARGET_PPC64)
6371 GEN_OP_SPE_LHE(64_kernel);
6372 GEN_OP_SPE_LHE(64_user);
6373 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_kernel);
6374 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_user);
6375 GEN_OP_SPE_LHE(le_64_kernel);
6376 GEN_OP_SPE_LHE(le_64_user);
6377 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_kernel);
6378 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_user);
6379 GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_kernel);
6380 GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_user);
6381 GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_kernel);
6382 GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_user);
6383 GEN_OP_SPE_LHX(64_kernel);
6384 GEN_OP_SPE_LHX(64_user);
6385 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_kernel);
6386 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_user);
6387 GEN_OP_SPE_LHX(le_64_kernel);
6388 GEN_OP_SPE_LHX(le_64_user);
6389 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_kernel);
6390 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_user);
6391 #endif
6392 #endif
6393 GEN_SPEOP_LD(hhesplat, 1);
6394 GEN_SPEOP_LD(hhousplat, 1);
6395 GEN_SPEOP_LD(hhossplat, 1);
6396 GEN_SPEOP_LD(wwsplat, 2);
6397 GEN_SPEOP_LD(whsplat, 2);
6399 GEN_SPE(evlddx, evldd, 0x00, 0x0C, 0x00000000, PPC_SPE); //
6400 GEN_SPE(evldwx, evldw, 0x01, 0x0C, 0x00000000, PPC_SPE); //
6401 GEN_SPE(evldhx, evldh, 0x02, 0x0C, 0x00000000, PPC_SPE); //
6402 GEN_SPE(evlhhesplatx, evlhhesplat, 0x04, 0x0C, 0x00000000, PPC_SPE); //
6403 GEN_SPE(evlhhousplatx, evlhhousplat, 0x06, 0x0C, 0x00000000, PPC_SPE); //
6404 GEN_SPE(evlhhossplatx, evlhhossplat, 0x07, 0x0C, 0x00000000, PPC_SPE); //
6405 GEN_SPE(evlwhex, evlwhe, 0x08, 0x0C, 0x00000000, PPC_SPE); //
6406 GEN_SPE(evlwhoux, evlwhou, 0x0A, 0x0C, 0x00000000, PPC_SPE); //
6407 GEN_SPE(evlwhosx, evlwhos, 0x0B, 0x0C, 0x00000000, PPC_SPE); //
6408 GEN_SPE(evlwwsplatx, evlwwsplat, 0x0C, 0x0C, 0x00000000, PPC_SPE); //
6409 GEN_SPE(evlwhsplatx, evlwhsplat, 0x0E, 0x0C, 0x00000000, PPC_SPE); //
6410 GEN_SPE(evstddx, evstdd, 0x10, 0x0C, 0x00000000, PPC_SPE); //
6411 GEN_SPE(evstdwx, evstdw, 0x11, 0x0C, 0x00000000, PPC_SPE); //
6412 GEN_SPE(evstdhx, evstdh, 0x12, 0x0C, 0x00000000, PPC_SPE); //
6413 GEN_SPE(evstwhex, evstwhe, 0x18, 0x0C, 0x00000000, PPC_SPE); //
6414 GEN_SPE(evstwhox, evstwho, 0x1A, 0x0C, 0x00000000, PPC_SPE); //
6415 GEN_SPE(evstwwex, evstwwe, 0x1C, 0x0C, 0x00000000, PPC_SPE); //
6416 GEN_SPE(evstwwox, evstwwo, 0x1E, 0x0C, 0x00000000, PPC_SPE); //
6418 /* Multiply and add - TODO */
6419 #if 0
6420 GEN_SPE(speundef, evmhessf, 0x01, 0x10, 0x00000000, PPC_SPE);
6421 GEN_SPE(speundef, evmhossf, 0x03, 0x10, 0x00000000, PPC_SPE);
6422 GEN_SPE(evmheumi, evmhesmi, 0x04, 0x10, 0x00000000, PPC_SPE);
6423 GEN_SPE(speundef, evmhesmf, 0x05, 0x10, 0x00000000, PPC_SPE);
6424 GEN_SPE(evmhoumi, evmhosmi, 0x06, 0x10, 0x00000000, PPC_SPE);
6425 GEN_SPE(speundef, evmhosmf, 0x07, 0x10, 0x00000000, PPC_SPE);
6426 GEN_SPE(speundef, evmhessfa, 0x11, 0x10, 0x00000000, PPC_SPE);
6427 GEN_SPE(speundef, evmhossfa, 0x13, 0x10, 0x00000000, PPC_SPE);
6428 GEN_SPE(evmheumia, evmhesmia, 0x14, 0x10, 0x00000000, PPC_SPE);
6429 GEN_SPE(speundef, evmhesmfa, 0x15, 0x10, 0x00000000, PPC_SPE);
6430 GEN_SPE(evmhoumia, evmhosmia, 0x16, 0x10, 0x00000000, PPC_SPE);
6431 GEN_SPE(speundef, evmhosmfa, 0x17, 0x10, 0x00000000, PPC_SPE);
6433 GEN_SPE(speundef, evmwhssf, 0x03, 0x11, 0x00000000, PPC_SPE);
6434 GEN_SPE(evmwlumi, speundef, 0x04, 0x11, 0x00000000, PPC_SPE);
6435 GEN_SPE(evmwhumi, evmwhsmi, 0x06, 0x11, 0x00000000, PPC_SPE);
6436 GEN_SPE(speundef, evmwhsmf, 0x07, 0x11, 0x00000000, PPC_SPE);
6437 GEN_SPE(speundef, evmwssf, 0x09, 0x11, 0x00000000, PPC_SPE);
6438 GEN_SPE(evmwumi, evmwsmi, 0x0C, 0x11, 0x00000000, PPC_SPE);
6439 GEN_SPE(speundef, evmwsmf, 0x0D, 0x11, 0x00000000, PPC_SPE);
6440 GEN_SPE(speundef, evmwhssfa, 0x13, 0x11, 0x00000000, PPC_SPE);
6441 GEN_SPE(evmwlumia, speundef, 0x14, 0x11, 0x00000000, PPC_SPE);
6442 GEN_SPE(evmwhumia, evmwhsmia, 0x16, 0x11, 0x00000000, PPC_SPE);
6443 GEN_SPE(speundef, evmwhsmfa, 0x17, 0x11, 0x00000000, PPC_SPE);
6444 GEN_SPE(speundef, evmwssfa, 0x19, 0x11, 0x00000000, PPC_SPE);
6445 GEN_SPE(evmwumia, evmwsmia, 0x1C, 0x11, 0x00000000, PPC_SPE);
6446 GEN_SPE(speundef, evmwsmfa, 0x1D, 0x11, 0x00000000, PPC_SPE);
6448 GEN_SPE(evadduiaaw, evaddsiaaw, 0x00, 0x13, 0x0000F800, PPC_SPE);
6449 GEN_SPE(evsubfusiaaw, evsubfssiaaw, 0x01, 0x13, 0x0000F800, PPC_SPE);
6450 GEN_SPE(evaddumiaaw, evaddsmiaaw, 0x04, 0x13, 0x0000F800, PPC_SPE);
6451 GEN_SPE(evsubfumiaaw, evsubfsmiaaw, 0x05, 0x13, 0x0000F800, PPC_SPE);
6452 GEN_SPE(evdivws, evdivwu, 0x06, 0x13, 0x00000000, PPC_SPE);
6453 GEN_SPE(evmra, speundef, 0x07, 0x13, 0x0000F800, PPC_SPE);
6455 GEN_SPE(evmheusiaaw, evmhessiaaw, 0x00, 0x14, 0x00000000, PPC_SPE);
6456 GEN_SPE(speundef, evmhessfaaw, 0x01, 0x14, 0x00000000, PPC_SPE);
6457 GEN_SPE(evmhousiaaw, evmhossiaaw, 0x02, 0x14, 0x00000000, PPC_SPE);
6458 GEN_SPE(speundef, evmhossfaaw, 0x03, 0x14, 0x00000000, PPC_SPE);
6459 GEN_SPE(evmheumiaaw, evmhesmiaaw, 0x04, 0x14, 0x00000000, PPC_SPE);
6460 GEN_SPE(speundef, evmhesmfaaw, 0x05, 0x14, 0x00000000, PPC_SPE);
6461 GEN_SPE(evmhoumiaaw, evmhosmiaaw, 0x06, 0x14, 0x00000000, PPC_SPE);
6462 GEN_SPE(speundef, evmhosmfaaw, 0x07, 0x14, 0x00000000, PPC_SPE);
6463 GEN_SPE(evmhegumiaa, evmhegsmiaa, 0x14, 0x14, 0x00000000, PPC_SPE);
6464 GEN_SPE(speundef, evmhegsmfaa, 0x15, 0x14, 0x00000000, PPC_SPE);
6465 GEN_SPE(evmhogumiaa, evmhogsmiaa, 0x16, 0x14, 0x00000000, PPC_SPE);
6466 GEN_SPE(speundef, evmhogsmfaa, 0x17, 0x14, 0x00000000, PPC_SPE);
6468 GEN_SPE(evmwlusiaaw, evmwlssiaaw, 0x00, 0x15, 0x00000000, PPC_SPE);
6469 GEN_SPE(evmwlumiaaw, evmwlsmiaaw, 0x04, 0x15, 0x00000000, PPC_SPE);
6470 GEN_SPE(speundef, evmwssfaa, 0x09, 0x15, 0x00000000, PPC_SPE);
6471 GEN_SPE(evmwumiaa, evmwsmiaa, 0x0C, 0x15, 0x00000000, PPC_SPE);
6472 GEN_SPE(speundef, evmwsmfaa, 0x0D, 0x15, 0x00000000, PPC_SPE);
6474 GEN_SPE(evmheusianw, evmhessianw, 0x00, 0x16, 0x00000000, PPC_SPE);
6475 GEN_SPE(speundef, evmhessfanw, 0x01, 0x16, 0x00000000, PPC_SPE);
6476 GEN_SPE(evmhousianw, evmhossianw, 0x02, 0x16, 0x00000000, PPC_SPE);
6477 GEN_SPE(speundef, evmhossfanw, 0x03, 0x16, 0x00000000, PPC_SPE);
6478 GEN_SPE(evmheumianw, evmhesmianw, 0x04, 0x16, 0x00000000, PPC_SPE);
6479 GEN_SPE(speundef, evmhesmfanw, 0x05, 0x16, 0x00000000, PPC_SPE);
6480 GEN_SPE(evmhoumianw, evmhosmianw, 0x06, 0x16, 0x00000000, PPC_SPE);
6481 GEN_SPE(speundef, evmhosmfanw, 0x07, 0x16, 0x00000000, PPC_SPE);
6482 GEN_SPE(evmhegumian, evmhegsmian, 0x14, 0x16, 0x00000000, PPC_SPE);
6483 GEN_SPE(speundef, evmhegsmfan, 0x15, 0x16, 0x00000000, PPC_SPE);
6484 GEN_SPE(evmhigumian, evmhigsmian, 0x16, 0x16, 0x00000000, PPC_SPE);
6485 GEN_SPE(speundef, evmhogsmfan, 0x17, 0x16, 0x00000000, PPC_SPE);
6487 GEN_SPE(evmwlusianw, evmwlssianw, 0x00, 0x17, 0x00000000, PPC_SPE);
6488 GEN_SPE(evmwlumianw, evmwlsmianw, 0x04, 0x17, 0x00000000, PPC_SPE);
6489 GEN_SPE(speundef, evmwssfan, 0x09, 0x17, 0x00000000, PPC_SPE);
6490 GEN_SPE(evmwumian, evmwsmian, 0x0C, 0x17, 0x00000000, PPC_SPE);
6491 GEN_SPE(speundef, evmwsmfan, 0x0D, 0x17, 0x00000000, PPC_SPE);
6492 #endif
6494 /*** SPE floating-point extension ***/
6495 #define GEN_SPEFPUOP_CONV(name) \
6496 static always_inline void gen_##name (DisasContext *ctx) \
6498 gen_op_load_gpr64_T0(rB(ctx->opcode)); \
6499 gen_op_##name(); \
6500 gen_op_store_T0_gpr64(rD(ctx->opcode)); \
6503 /* Single precision floating-point vectors operations */
6504 /* Arithmetic */
6505 GEN_SPEOP_ARITH2(evfsadd);
6506 GEN_SPEOP_ARITH2(evfssub);
6507 GEN_SPEOP_ARITH2(evfsmul);
6508 GEN_SPEOP_ARITH2(evfsdiv);
6509 GEN_SPEOP_ARITH1(evfsabs);
6510 GEN_SPEOP_ARITH1(evfsnabs);
6511 GEN_SPEOP_ARITH1(evfsneg);
6512 /* Conversion */
6513 GEN_SPEFPUOP_CONV(evfscfui);
6514 GEN_SPEFPUOP_CONV(evfscfsi);
6515 GEN_SPEFPUOP_CONV(evfscfuf);
6516 GEN_SPEFPUOP_CONV(evfscfsf);
6517 GEN_SPEFPUOP_CONV(evfsctui);
6518 GEN_SPEFPUOP_CONV(evfsctsi);
6519 GEN_SPEFPUOP_CONV(evfsctuf);
6520 GEN_SPEFPUOP_CONV(evfsctsf);
6521 GEN_SPEFPUOP_CONV(evfsctuiz);
6522 GEN_SPEFPUOP_CONV(evfsctsiz);
6523 /* Comparison */
6524 GEN_SPEOP_COMP(evfscmpgt);
6525 GEN_SPEOP_COMP(evfscmplt);
6526 GEN_SPEOP_COMP(evfscmpeq);
6527 GEN_SPEOP_COMP(evfststgt);
6528 GEN_SPEOP_COMP(evfststlt);
6529 GEN_SPEOP_COMP(evfststeq);
6531 /* Opcodes definitions */
6532 GEN_SPE(evfsadd, evfssub, 0x00, 0x0A, 0x00000000, PPC_SPEFPU); //
6533 GEN_SPE(evfsabs, evfsnabs, 0x02, 0x0A, 0x0000F800, PPC_SPEFPU); //
6534 GEN_SPE(evfsneg, speundef, 0x03, 0x0A, 0x0000F800, PPC_SPEFPU); //
6535 GEN_SPE(evfsmul, evfsdiv, 0x04, 0x0A, 0x00000000, PPC_SPEFPU); //
6536 GEN_SPE(evfscmpgt, evfscmplt, 0x06, 0x0A, 0x00600000, PPC_SPEFPU); //
6537 GEN_SPE(evfscmpeq, speundef, 0x07, 0x0A, 0x00600000, PPC_SPEFPU); //
6538 GEN_SPE(evfscfui, evfscfsi, 0x08, 0x0A, 0x00180000, PPC_SPEFPU); //
6539 GEN_SPE(evfscfuf, evfscfsf, 0x09, 0x0A, 0x00180000, PPC_SPEFPU); //
6540 GEN_SPE(evfsctui, evfsctsi, 0x0A, 0x0A, 0x00180000, PPC_SPEFPU); //
6541 GEN_SPE(evfsctuf, evfsctsf, 0x0B, 0x0A, 0x00180000, PPC_SPEFPU); //
6542 GEN_SPE(evfsctuiz, speundef, 0x0C, 0x0A, 0x00180000, PPC_SPEFPU); //
6543 GEN_SPE(evfsctsiz, speundef, 0x0D, 0x0A, 0x00180000, PPC_SPEFPU); //
6544 GEN_SPE(evfststgt, evfststlt, 0x0E, 0x0A, 0x00600000, PPC_SPEFPU); //
6545 GEN_SPE(evfststeq, speundef, 0x0F, 0x0A, 0x00600000, PPC_SPEFPU); //
6547 /* Single precision floating-point operations */
6548 /* Arithmetic */
6549 GEN_SPEOP_ARITH2(efsadd);
6550 GEN_SPEOP_ARITH2(efssub);
6551 GEN_SPEOP_ARITH2(efsmul);
6552 GEN_SPEOP_ARITH2(efsdiv);
6553 GEN_SPEOP_ARITH1(efsabs);
6554 GEN_SPEOP_ARITH1(efsnabs);
6555 GEN_SPEOP_ARITH1(efsneg);
6556 /* Conversion */
6557 GEN_SPEFPUOP_CONV(efscfui);
6558 GEN_SPEFPUOP_CONV(efscfsi);
6559 GEN_SPEFPUOP_CONV(efscfuf);
6560 GEN_SPEFPUOP_CONV(efscfsf);
6561 GEN_SPEFPUOP_CONV(efsctui);
6562 GEN_SPEFPUOP_CONV(efsctsi);
6563 GEN_SPEFPUOP_CONV(efsctuf);
6564 GEN_SPEFPUOP_CONV(efsctsf);
6565 GEN_SPEFPUOP_CONV(efsctuiz);
6566 GEN_SPEFPUOP_CONV(efsctsiz);
6567 GEN_SPEFPUOP_CONV(efscfd);
6568 /* Comparison */
6569 GEN_SPEOP_COMP(efscmpgt);
6570 GEN_SPEOP_COMP(efscmplt);
6571 GEN_SPEOP_COMP(efscmpeq);
6572 GEN_SPEOP_COMP(efststgt);
6573 GEN_SPEOP_COMP(efststlt);
6574 GEN_SPEOP_COMP(efststeq);
6576 /* Opcodes definitions */
6577 GEN_SPE(efsadd, efssub, 0x00, 0x0A, 0x00000000, PPC_SPEFPU); //
6578 GEN_SPE(efsabs, efsnabs, 0x02, 0x0B, 0x0000F800, PPC_SPEFPU); //
6579 GEN_SPE(efsneg, speundef, 0x03, 0x0B, 0x0000F800, PPC_SPEFPU); //
6580 GEN_SPE(efsmul, efsdiv, 0x04, 0x0B, 0x00000000, PPC_SPEFPU); //
6581 GEN_SPE(efscmpgt, efscmplt, 0x06, 0x0B, 0x00600000, PPC_SPEFPU); //
6582 GEN_SPE(efscmpeq, efscfd, 0x07, 0x0B, 0x00600000, PPC_SPEFPU); //
6583 GEN_SPE(efscfui, efscfsi, 0x08, 0x0B, 0x00180000, PPC_SPEFPU); //
6584 GEN_SPE(efscfuf, efscfsf, 0x09, 0x0B, 0x00180000, PPC_SPEFPU); //
6585 GEN_SPE(efsctui, efsctsi, 0x0A, 0x0B, 0x00180000, PPC_SPEFPU); //
6586 GEN_SPE(efsctuf, efsctsf, 0x0B, 0x0B, 0x00180000, PPC_SPEFPU); //
6587 GEN_SPE(efsctuiz, efsctsiz, 0x0C, 0x0B, 0x00180000, PPC_SPEFPU); //
6588 GEN_SPE(efststgt, efststlt, 0x0E, 0x0B, 0x00600000, PPC_SPEFPU); //
6589 GEN_SPE(efststeq, speundef, 0x0F, 0x0B, 0x00600000, PPC_SPEFPU); //
6591 /* Double precision floating-point operations */
6592 /* Arithmetic */
6593 GEN_SPEOP_ARITH2(efdadd);
6594 GEN_SPEOP_ARITH2(efdsub);
6595 GEN_SPEOP_ARITH2(efdmul);
6596 GEN_SPEOP_ARITH2(efddiv);
6597 GEN_SPEOP_ARITH1(efdabs);
6598 GEN_SPEOP_ARITH1(efdnabs);
6599 GEN_SPEOP_ARITH1(efdneg);
6600 /* Conversion */
6602 GEN_SPEFPUOP_CONV(efdcfui);
6603 GEN_SPEFPUOP_CONV(efdcfsi);
6604 GEN_SPEFPUOP_CONV(efdcfuf);
6605 GEN_SPEFPUOP_CONV(efdcfsf);
6606 GEN_SPEFPUOP_CONV(efdctui);
6607 GEN_SPEFPUOP_CONV(efdctsi);
6608 GEN_SPEFPUOP_CONV(efdctuf);
6609 GEN_SPEFPUOP_CONV(efdctsf);
6610 GEN_SPEFPUOP_CONV(efdctuiz);
6611 GEN_SPEFPUOP_CONV(efdctsiz);
6612 GEN_SPEFPUOP_CONV(efdcfs);
6613 GEN_SPEFPUOP_CONV(efdcfuid);
6614 GEN_SPEFPUOP_CONV(efdcfsid);
6615 GEN_SPEFPUOP_CONV(efdctuidz);
6616 GEN_SPEFPUOP_CONV(efdctsidz);
6617 /* Comparison */
6618 GEN_SPEOP_COMP(efdcmpgt);
6619 GEN_SPEOP_COMP(efdcmplt);
6620 GEN_SPEOP_COMP(efdcmpeq);
6621 GEN_SPEOP_COMP(efdtstgt);
6622 GEN_SPEOP_COMP(efdtstlt);
6623 GEN_SPEOP_COMP(efdtsteq);
6625 /* Opcodes definitions */
6626 GEN_SPE(efdadd, efdsub, 0x10, 0x0B, 0x00000000, PPC_SPEFPU); //
6627 GEN_SPE(efdcfuid, efdcfsid, 0x11, 0x0B, 0x00180000, PPC_SPEFPU); //
6628 GEN_SPE(efdabs, efdnabs, 0x12, 0x0B, 0x0000F800, PPC_SPEFPU); //
6629 GEN_SPE(efdneg, speundef, 0x13, 0x0B, 0x0000F800, PPC_SPEFPU); //
6630 GEN_SPE(efdmul, efddiv, 0x14, 0x0B, 0x00000000, PPC_SPEFPU); //
6631 GEN_SPE(efdctuidz, efdctsidz, 0x15, 0x0B, 0x00180000, PPC_SPEFPU); //
6632 GEN_SPE(efdcmpgt, efdcmplt, 0x16, 0x0B, 0x00600000, PPC_SPEFPU); //
6633 GEN_SPE(efdcmpeq, efdcfs, 0x17, 0x0B, 0x00600000, PPC_SPEFPU); //
6634 GEN_SPE(efdcfui, efdcfsi, 0x18, 0x0B, 0x00180000, PPC_SPEFPU); //
6635 GEN_SPE(efdcfuf, efdcfsf, 0x19, 0x0B, 0x00180000, PPC_SPEFPU); //
6636 GEN_SPE(efdctui, efdctsi, 0x1A, 0x0B, 0x00180000, PPC_SPEFPU); //
6637 GEN_SPE(efdctuf, efdctsf, 0x1B, 0x0B, 0x00180000, PPC_SPEFPU); //
6638 GEN_SPE(efdctuiz, speundef, 0x1C, 0x0B, 0x00180000, PPC_SPEFPU); //
6639 GEN_SPE(efdctsiz, speundef, 0x1D, 0x0B, 0x00180000, PPC_SPEFPU); //
6640 GEN_SPE(efdtstgt, efdtstlt, 0x1E, 0x0B, 0x00600000, PPC_SPEFPU); //
6641 GEN_SPE(efdtsteq, speundef, 0x1F, 0x0B, 0x00600000, PPC_SPEFPU); //
6642 #endif
6644 /* End opcode list */
6645 GEN_OPCODE_MARK(end);
6647 #include "translate_init.c"
6648 #include "helper_regs.h"
6650 /*****************************************************************************/
6651 /* Misc PowerPC helpers */
6652 void cpu_dump_state (CPUState *env, FILE *f,
6653 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
6654 int flags)
6656 #if defined(TARGET_PPC64) || 1
6657 #define FILL ""
6658 #define RGPL 4
6659 #define RFPL 4
6660 #else
6661 #define FILL " "
6662 #define RGPL 8
6663 #define RFPL 4
6664 #endif
6666 int i;
6668 cpu_fprintf(f, "NIP " ADDRX " LR " ADDRX " CTR " ADDRX " idx %d\n",
6669 env->nip, env->lr, env->ctr, env->mmu_idx);
6670 cpu_fprintf(f, "MSR " REGX FILL " XER %08x "
6671 #if !defined(NO_TIMER_DUMP)
6672 "TB %08x %08x "
6673 #if !defined(CONFIG_USER_ONLY)
6674 "DECR %08x"
6675 #endif
6676 #endif
6677 "\n",
6678 env->msr, hreg_load_xer(env)
6679 #if !defined(NO_TIMER_DUMP)
6680 , cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
6681 #if !defined(CONFIG_USER_ONLY)
6682 , cpu_ppc_load_decr(env)
6683 #endif
6684 #endif
6686 for (i = 0; i < 32; i++) {
6687 if ((i & (RGPL - 1)) == 0)
6688 cpu_fprintf(f, "GPR%02d", i);
6689 cpu_fprintf(f, " " REGX, (target_ulong)env->gpr[i]);
6690 if ((i & (RGPL - 1)) == (RGPL - 1))
6691 cpu_fprintf(f, "\n");
6693 cpu_fprintf(f, "CR ");
6694 for (i = 0; i < 8; i++)
6695 cpu_fprintf(f, "%01x", env->crf[i]);
6696 cpu_fprintf(f, " [");
6697 for (i = 0; i < 8; i++) {
6698 char a = '-';
6699 if (env->crf[i] & 0x08)
6700 a = 'L';
6701 else if (env->crf[i] & 0x04)
6702 a = 'G';
6703 else if (env->crf[i] & 0x02)
6704 a = 'E';
6705 cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
6707 cpu_fprintf(f, " ] " FILL "RES " REGX "\n", env->reserve);
6708 for (i = 0; i < 32; i++) {
6709 if ((i & (RFPL - 1)) == 0)
6710 cpu_fprintf(f, "FPR%02d", i);
6711 cpu_fprintf(f, " %016" PRIx64, *((uint64_t *)&env->fpr[i]));
6712 if ((i & (RFPL - 1)) == (RFPL - 1))
6713 cpu_fprintf(f, "\n");
6715 #if !defined(CONFIG_USER_ONLY)
6716 cpu_fprintf(f, "SRR0 " REGX " SRR1 " REGX " " FILL FILL FILL
6717 "SDR1 " REGX "\n",
6718 env->spr[SPR_SRR0], env->spr[SPR_SRR1], env->sdr1);
6719 #endif
6721 #undef RGPL
6722 #undef RFPL
6723 #undef FILL
6726 void cpu_dump_statistics (CPUState *env, FILE*f,
6727 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
6728 int flags)
6730 #if defined(DO_PPC_STATISTICS)
6731 opc_handler_t **t1, **t2, **t3, *handler;
6732 int op1, op2, op3;
6734 t1 = env->opcodes;
6735 for (op1 = 0; op1 < 64; op1++) {
6736 handler = t1[op1];
6737 if (is_indirect_opcode(handler)) {
6738 t2 = ind_table(handler);
6739 for (op2 = 0; op2 < 32; op2++) {
6740 handler = t2[op2];
6741 if (is_indirect_opcode(handler)) {
6742 t3 = ind_table(handler);
6743 for (op3 = 0; op3 < 32; op3++) {
6744 handler = t3[op3];
6745 if (handler->count == 0)
6746 continue;
6747 cpu_fprintf(f, "%02x %02x %02x (%02x %04d) %16s: "
6748 "%016llx %lld\n",
6749 op1, op2, op3, op1, (op3 << 5) | op2,
6750 handler->oname,
6751 handler->count, handler->count);
6753 } else {
6754 if (handler->count == 0)
6755 continue;
6756 cpu_fprintf(f, "%02x %02x (%02x %04d) %16s: "
6757 "%016llx %lld\n",
6758 op1, op2, op1, op2, handler->oname,
6759 handler->count, handler->count);
6762 } else {
6763 if (handler->count == 0)
6764 continue;
6765 cpu_fprintf(f, "%02x (%02x ) %16s: %016llx %lld\n",
6766 op1, op1, handler->oname,
6767 handler->count, handler->count);
6770 #endif
6773 /*****************************************************************************/
6774 static always_inline int gen_intermediate_code_internal (CPUState *env,
6775 TranslationBlock *tb,
6776 int search_pc)
6778 DisasContext ctx, *ctxp = &ctx;
6779 opc_handler_t **table, *handler;
6780 target_ulong pc_start;
6781 uint16_t *gen_opc_end;
6782 int supervisor;
6783 int single_step, branch_step;
6784 int j, lj = -1;
6786 pc_start = tb->pc;
6787 gen_opc_ptr = gen_opc_buf;
6788 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
6789 gen_opparam_ptr = gen_opparam_buf;
6790 #if defined(OPTIMIZE_FPRF_UPDATE)
6791 gen_fprf_ptr = gen_fprf_buf;
6792 #endif
6793 nb_gen_labels = 0;
6794 ctx.nip = pc_start;
6795 ctx.tb = tb;
6796 ctx.exception = POWERPC_EXCP_NONE;
6797 ctx.spr_cb = env->spr_cb;
6798 supervisor = env->mmu_idx;
6799 #if !defined(CONFIG_USER_ONLY)
6800 ctx.supervisor = supervisor;
6801 #endif
6802 #if defined(TARGET_PPC64)
6803 ctx.sf_mode = msr_sf;
6804 ctx.mem_idx = (supervisor << 2) | (msr_sf << 1) | msr_le;
6805 #else
6806 ctx.mem_idx = (supervisor << 1) | msr_le;
6807 #endif
6808 ctx.dcache_line_size = env->dcache_line_size;
6809 ctx.fpu_enabled = msr_fp;
6810 #if defined(TARGET_PPCEMB)
6811 if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
6812 ctx.spe_enabled = msr_spe;
6813 else
6814 ctx.spe_enabled = 0;
6815 #endif
6816 if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
6817 ctx.altivec_enabled = msr_vr;
6818 else
6819 ctx.altivec_enabled = 0;
6820 if ((env->flags & POWERPC_FLAG_SE) && msr_se)
6821 single_step = 1;
6822 else
6823 single_step = 0;
6824 if ((env->flags & POWERPC_FLAG_BE) && msr_be)
6825 branch_step = 1;
6826 else
6827 branch_step = 0;
6828 ctx.singlestep_enabled = env->singlestep_enabled || single_step == 1;
6829 #if defined (DO_SINGLE_STEP) && 0
6830 /* Single step trace mode */
6831 msr_se = 1;
6832 #endif
6833 /* Set env in case of segfault during code fetch */
6834 while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) {
6835 if (unlikely(env->nb_breakpoints > 0)) {
6836 for (j = 0; j < env->nb_breakpoints; j++) {
6837 if (env->breakpoints[j] == ctx.nip) {
6838 gen_update_nip(&ctx, ctx.nip);
6839 gen_op_debug();
6840 break;
6844 if (unlikely(search_pc)) {
6845 j = gen_opc_ptr - gen_opc_buf;
6846 if (lj < j) {
6847 lj++;
6848 while (lj < j)
6849 gen_opc_instr_start[lj++] = 0;
6850 gen_opc_pc[lj] = ctx.nip;
6851 gen_opc_instr_start[lj] = 1;
6854 #if defined PPC_DEBUG_DISAS
6855 if (loglevel & CPU_LOG_TB_IN_ASM) {
6856 fprintf(logfile, "----------------\n");
6857 fprintf(logfile, "nip=" ADDRX " super=%d ir=%d\n",
6858 ctx.nip, supervisor, (int)msr_ir);
6860 #endif
6861 ctx.opcode = ldl_code(ctx.nip);
6862 if (msr_le) {
6863 ctx.opcode = ((ctx.opcode & 0xFF000000) >> 24) |
6864 ((ctx.opcode & 0x00FF0000) >> 8) |
6865 ((ctx.opcode & 0x0000FF00) << 8) |
6866 ((ctx.opcode & 0x000000FF) << 24);
6868 #if defined PPC_DEBUG_DISAS
6869 if (loglevel & CPU_LOG_TB_IN_ASM) {
6870 fprintf(logfile, "translate opcode %08x (%02x %02x %02x) (%s)\n",
6871 ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
6872 opc3(ctx.opcode), msr_le ? "little" : "big");
6874 #endif
6875 ctx.nip += 4;
6876 table = env->opcodes;
6877 handler = table[opc1(ctx.opcode)];
6878 if (is_indirect_opcode(handler)) {
6879 table = ind_table(handler);
6880 handler = table[opc2(ctx.opcode)];
6881 if (is_indirect_opcode(handler)) {
6882 table = ind_table(handler);
6883 handler = table[opc3(ctx.opcode)];
6886 /* Is opcode *REALLY* valid ? */
6887 if (unlikely(handler->handler == &gen_invalid)) {
6888 if (loglevel != 0) {
6889 fprintf(logfile, "invalid/unsupported opcode: "
6890 "%02x - %02x - %02x (%08x) 0x" ADDRX " %d\n",
6891 opc1(ctx.opcode), opc2(ctx.opcode),
6892 opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
6893 } else {
6894 printf("invalid/unsupported opcode: "
6895 "%02x - %02x - %02x (%08x) 0x" ADDRX " %d\n",
6896 opc1(ctx.opcode), opc2(ctx.opcode),
6897 opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
6899 } else {
6900 if (unlikely((ctx.opcode & handler->inval) != 0)) {
6901 if (loglevel != 0) {
6902 fprintf(logfile, "invalid bits: %08x for opcode: "
6903 "%02x - %02x - %02x (%08x) 0x" ADDRX "\n",
6904 ctx.opcode & handler->inval, opc1(ctx.opcode),
6905 opc2(ctx.opcode), opc3(ctx.opcode),
6906 ctx.opcode, ctx.nip - 4);
6907 } else {
6908 printf("invalid bits: %08x for opcode: "
6909 "%02x - %02x - %02x (%08x) 0x" ADDRX "\n",
6910 ctx.opcode & handler->inval, opc1(ctx.opcode),
6911 opc2(ctx.opcode), opc3(ctx.opcode),
6912 ctx.opcode, ctx.nip - 4);
6914 GEN_EXCP_INVAL(ctxp);
6915 break;
6918 (*(handler->handler))(&ctx);
6919 #if defined(DO_PPC_STATISTICS)
6920 handler->count++;
6921 #endif
6922 /* Check trace mode exceptions */
6923 if (unlikely(branch_step != 0 &&
6924 ctx.exception == POWERPC_EXCP_BRANCH)) {
6925 GEN_EXCP(ctxp, POWERPC_EXCP_TRACE, 0);
6926 } else if (unlikely(single_step != 0 &&
6927 (ctx.nip <= 0x100 || ctx.nip > 0xF00 ||
6928 (ctx.nip & 0xFC) != 0x04) &&
6929 ctx.exception != POWERPC_SYSCALL &&
6930 ctx.exception != POWERPC_EXCP_TRAP)) {
6931 GEN_EXCP(ctxp, POWERPC_EXCP_TRACE, 0);
6932 } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
6933 (env->singlestep_enabled))) {
6934 /* if we reach a page boundary or are single stepping, stop
6935 * generation
6937 break;
6939 #if defined (DO_SINGLE_STEP)
6940 break;
6941 #endif
6943 if (ctx.exception == POWERPC_EXCP_NONE) {
6944 gen_goto_tb(&ctx, 0, ctx.nip);
6945 } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
6946 gen_op_reset_T0();
6947 /* Generate the return instruction */
6948 gen_op_exit_tb();
6950 *gen_opc_ptr = INDEX_op_end;
6951 if (unlikely(search_pc)) {
6952 j = gen_opc_ptr - gen_opc_buf;
6953 lj++;
6954 while (lj <= j)
6955 gen_opc_instr_start[lj++] = 0;
6956 } else {
6957 tb->size = ctx.nip - pc_start;
6959 #if defined(DEBUG_DISAS)
6960 if (loglevel & CPU_LOG_TB_CPU) {
6961 fprintf(logfile, "---------------- excp: %04x\n", ctx.exception);
6962 cpu_dump_state(env, logfile, fprintf, 0);
6964 if (loglevel & CPU_LOG_TB_IN_ASM) {
6965 int flags;
6966 flags = env->bfd_mach;
6967 flags |= msr_le << 16;
6968 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
6969 target_disas(logfile, pc_start, ctx.nip - pc_start, flags);
6970 fprintf(logfile, "\n");
6972 if (loglevel & CPU_LOG_TB_OP) {
6973 fprintf(logfile, "OP:\n");
6974 dump_ops(gen_opc_buf, gen_opparam_buf);
6975 fprintf(logfile, "\n");
6977 #endif
6978 return 0;
6981 int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
6983 return gen_intermediate_code_internal(env, tb, 0);
6986 int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
6988 return gen_intermediate_code_internal(env, tb, 1);