Remove dead code.
[qemu/mini2440.git] / target-ppc / translate.c
blob6145701187fd74e45ad57011900e29db15aa8b2a
1 /*
2 * PowerPC emulation for qemu: main translation routines.
3 *
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 //#define DO_SINGLE_STEP
31 //#define PPC_DEBUG_DISAS
32 //#define DO_PPC_STATISTICS
34 #if defined(USE_DIRECT_JUMP)
35 #define TBPARAM(x)
36 #else
37 #define TBPARAM(x) (long)(x)
38 #endif
40 enum {
41 #define DEF(s, n, copy_size) INDEX_op_ ## s,
42 #include "opc.h"
43 #undef DEF
44 NB_OPS,
47 static uint16_t *gen_opc_ptr;
48 static uint32_t *gen_opparam_ptr;
50 #include "gen-op.h"
52 static inline void gen_set_T0 (target_ulong val)
54 #if defined(TARGET_PPC64)
55 if (val >> 32)
56 gen_op_set_T0_64(val >> 32, val);
57 else
58 #endif
59 gen_op_set_T0(val);
62 static inline void gen_set_T1 (target_ulong val)
64 #if defined(TARGET_PPC64)
65 if (val >> 32)
66 gen_op_set_T1_64(val >> 32, val);
67 else
68 #endif
69 gen_op_set_T1(val);
72 #define GEN8(func, NAME) \
73 static GenOpFunc *NAME ## _table [8] = { \
74 NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
75 NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
76 }; \
77 static inline void func(int n) \
78 { \
79 NAME ## _table[n](); \
82 #define GEN16(func, NAME) \
83 static GenOpFunc *NAME ## _table [16] = { \
84 NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
85 NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
86 NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
87 NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
88 }; \
89 static inline void func(int n) \
90 { \
91 NAME ## _table[n](); \
94 #define GEN32(func, NAME) \
95 static GenOpFunc *NAME ## _table [32] = { \
96 NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
97 NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
98 NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
99 NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
100 NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \
101 NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \
102 NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \
103 NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \
104 }; \
105 static inline void func(int n) \
107 NAME ## _table[n](); \
110 /* Condition register moves */
111 GEN8(gen_op_load_crf_T0, gen_op_load_crf_T0_crf);
112 GEN8(gen_op_load_crf_T1, gen_op_load_crf_T1_crf);
113 GEN8(gen_op_store_T0_crf, gen_op_store_T0_crf_crf);
114 GEN8(gen_op_store_T1_crf, gen_op_store_T1_crf_crf);
116 /* Floating point condition and status register moves */
117 GEN8(gen_op_load_fpscr_T0, gen_op_load_fpscr_T0_fpscr);
118 GEN8(gen_op_store_T0_fpscr, gen_op_store_T0_fpscr_fpscr);
119 GEN8(gen_op_clear_fpscr, gen_op_clear_fpscr_fpscr);
120 static inline void gen_op_store_T0_fpscri(int n, uint8_t param)
122 gen_op_set_T0(param);
123 gen_op_store_T0_fpscr(n);
126 /* General purpose registers moves */
127 GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr);
128 GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr);
129 GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr);
131 GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr);
132 GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr);
133 #if 0 // unused
134 GEN32(gen_op_store_T2_gpr, gen_op_store_T2_gpr_gpr);
135 #endif
137 /* floating point registers moves */
138 GEN32(gen_op_load_fpr_FT0, gen_op_load_fpr_FT0_fpr);
139 GEN32(gen_op_load_fpr_FT1, gen_op_load_fpr_FT1_fpr);
140 GEN32(gen_op_load_fpr_FT2, gen_op_load_fpr_FT2_fpr);
141 GEN32(gen_op_store_FT0_fpr, gen_op_store_FT0_fpr_fpr);
142 GEN32(gen_op_store_FT1_fpr, gen_op_store_FT1_fpr_fpr);
143 #if 0 // unused
144 GEN32(gen_op_store_FT2_fpr, gen_op_store_FT2_fpr_fpr);
145 #endif
147 /* internal defines */
148 typedef struct DisasContext {
149 struct TranslationBlock *tb;
150 target_ulong nip;
151 uint32_t opcode;
152 uint32_t exception;
153 /* Routine used to access memory */
154 int mem_idx;
155 /* Translation flags */
156 #if !defined(CONFIG_USER_ONLY)
157 int supervisor;
158 #endif
159 #if defined(TARGET_PPC64)
160 int sf_mode;
161 #endif
162 int fpu_enabled;
163 #if defined(TARGET_PPCSPE)
164 int spe_enabled;
165 #endif
166 ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */
167 int singlestep_enabled;
168 } DisasContext;
170 struct opc_handler_t {
171 /* invalid bits */
172 uint32_t inval;
173 /* instruction type */
174 uint64_t type;
175 /* handler */
176 void (*handler)(DisasContext *ctx);
177 #if defined(DO_PPC_STATISTICS)
178 const unsigned char *oname;
179 uint64_t count;
180 #endif
183 static inline void gen_set_Rc0 (DisasContext *ctx)
185 #if defined(TARGET_PPC64)
186 if (ctx->sf_mode)
187 gen_op_cmpi_64(0);
188 else
189 #endif
190 gen_op_cmpi(0);
191 gen_op_set_Rc0();
194 static inline void gen_update_nip (DisasContext *ctx, target_ulong nip)
196 #if defined(TARGET_PPC64)
197 if (ctx->sf_mode)
198 gen_op_update_nip_64(nip >> 32, nip);
199 else
200 #endif
201 gen_op_update_nip(nip);
204 #define RET_EXCP(ctx, excp, error) \
205 do { \
206 if ((ctx)->exception == EXCP_NONE) { \
207 gen_update_nip(ctx, (ctx)->nip); \
209 gen_op_raise_exception_err((excp), (error)); \
210 ctx->exception = (excp); \
211 } while (0)
213 #define RET_INVAL(ctx) \
214 RET_EXCP((ctx), EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL)
216 #define RET_PRIVOPC(ctx) \
217 RET_EXCP((ctx), EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_OPC)
219 #define RET_PRIVREG(ctx) \
220 RET_EXCP((ctx), EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG)
222 /* Stop translation */
223 static inline void RET_STOP (DisasContext *ctx)
225 gen_update_nip(ctx, ctx->nip);
226 ctx->exception = EXCP_MTMSR;
229 /* No need to update nip here, as execution flow will change */
230 static inline void RET_CHG_FLOW (DisasContext *ctx)
232 ctx->exception = EXCP_MTMSR;
235 #define GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
236 static void gen_##name (DisasContext *ctx); \
237 GEN_OPCODE(name, opc1, opc2, opc3, inval, type); \
238 static void gen_##name (DisasContext *ctx)
240 typedef struct opcode_t {
241 unsigned char opc1, opc2, opc3;
242 #if HOST_LONG_BITS == 64 /* Explicitely align to 64 bits */
243 unsigned char pad[5];
244 #else
245 unsigned char pad[1];
246 #endif
247 opc_handler_t handler;
248 const unsigned char *oname;
249 } opcode_t;
251 /*** Instruction decoding ***/
252 #define EXTRACT_HELPER(name, shift, nb) \
253 static inline uint32_t name (uint32_t opcode) \
255 return (opcode >> (shift)) & ((1 << (nb)) - 1); \
258 #define EXTRACT_SHELPER(name, shift, nb) \
259 static inline int32_t name (uint32_t opcode) \
261 return (int16_t)((opcode >> (shift)) & ((1 << (nb)) - 1)); \
264 /* Opcode part 1 */
265 EXTRACT_HELPER(opc1, 26, 6);
266 /* Opcode part 2 */
267 EXTRACT_HELPER(opc2, 1, 5);
268 /* Opcode part 3 */
269 EXTRACT_HELPER(opc3, 6, 5);
270 /* Update Cr0 flags */
271 EXTRACT_HELPER(Rc, 0, 1);
272 /* Destination */
273 EXTRACT_HELPER(rD, 21, 5);
274 /* Source */
275 EXTRACT_HELPER(rS, 21, 5);
276 /* First operand */
277 EXTRACT_HELPER(rA, 16, 5);
278 /* Second operand */
279 EXTRACT_HELPER(rB, 11, 5);
280 /* Third operand */
281 EXTRACT_HELPER(rC, 6, 5);
282 /*** Get CRn ***/
283 EXTRACT_HELPER(crfD, 23, 3);
284 EXTRACT_HELPER(crfS, 18, 3);
285 EXTRACT_HELPER(crbD, 21, 5);
286 EXTRACT_HELPER(crbA, 16, 5);
287 EXTRACT_HELPER(crbB, 11, 5);
288 /* SPR / TBL */
289 EXTRACT_HELPER(_SPR, 11, 10);
290 static inline uint32_t SPR (uint32_t opcode)
292 uint32_t sprn = _SPR(opcode);
294 return ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
296 /*** Get constants ***/
297 EXTRACT_HELPER(IMM, 12, 8);
298 /* 16 bits signed immediate value */
299 EXTRACT_SHELPER(SIMM, 0, 16);
300 /* 16 bits unsigned immediate value */
301 EXTRACT_HELPER(UIMM, 0, 16);
302 /* Bit count */
303 EXTRACT_HELPER(NB, 11, 5);
304 /* Shift count */
305 EXTRACT_HELPER(SH, 11, 5);
306 /* Mask start */
307 EXTRACT_HELPER(MB, 6, 5);
308 /* Mask end */
309 EXTRACT_HELPER(ME, 1, 5);
310 /* Trap operand */
311 EXTRACT_HELPER(TO, 21, 5);
313 EXTRACT_HELPER(CRM, 12, 8);
314 EXTRACT_HELPER(FM, 17, 8);
315 EXTRACT_HELPER(SR, 16, 4);
316 EXTRACT_HELPER(FPIMM, 20, 4);
318 /*** Jump target decoding ***/
319 /* Displacement */
320 EXTRACT_SHELPER(d, 0, 16);
321 /* Immediate address */
322 static inline target_ulong LI (uint32_t opcode)
324 return (opcode >> 0) & 0x03FFFFFC;
327 static inline uint32_t BD (uint32_t opcode)
329 return (opcode >> 0) & 0xFFFC;
332 EXTRACT_HELPER(BO, 21, 5);
333 EXTRACT_HELPER(BI, 16, 5);
334 /* Absolute/relative address */
335 EXTRACT_HELPER(AA, 1, 1);
336 /* Link */
337 EXTRACT_HELPER(LK, 0, 1);
339 /* Create a mask between <start> and <end> bits */
340 static inline target_ulong MASK (uint32_t start, uint32_t end)
342 target_ulong ret;
344 #if defined(TARGET_PPC64)
345 if (likely(start == 0)) {
346 ret = (uint64_t)(-1ULL) << (63 - end);
347 } else if (likely(end == 63)) {
348 ret = (uint64_t)(-1ULL) >> start;
350 #else
351 if (likely(start == 0)) {
352 ret = (uint32_t)(-1ULL) << (31 - end);
353 } else if (likely(end == 31)) {
354 ret = (uint32_t)(-1ULL) >> start;
356 #endif
357 else {
358 ret = (((target_ulong)(-1ULL)) >> (start)) ^
359 (((target_ulong)(-1ULL) >> (end)) >> 1);
360 if (unlikely(start > end))
361 return ~ret;
364 return ret;
367 #if HOST_LONG_BITS == 64
368 #define OPC_ALIGN 8
369 #else
370 #define OPC_ALIGN 4
371 #endif
372 #if defined(__APPLE__)
373 #define OPCODES_SECTION \
374 __attribute__ ((section("__TEXT,__opcodes"), unused, aligned (OPC_ALIGN) ))
375 #else
376 #define OPCODES_SECTION \
377 __attribute__ ((section(".opcodes"), unused, aligned (OPC_ALIGN) ))
378 #endif
380 #if defined(DO_PPC_STATISTICS)
381 #define GEN_OPCODE(name, op1, op2, op3, invl, _typ) \
382 OPCODES_SECTION opcode_t opc_##name = { \
383 .opc1 = op1, \
384 .opc2 = op2, \
385 .opc3 = op3, \
386 .pad = { 0, }, \
387 .handler = { \
388 .inval = invl, \
389 .type = _typ, \
390 .handler = &gen_##name, \
391 .oname = stringify(name), \
392 }, \
393 .oname = stringify(name), \
395 #else
396 #define GEN_OPCODE(name, op1, op2, op3, invl, _typ) \
397 OPCODES_SECTION opcode_t opc_##name = { \
398 .opc1 = op1, \
399 .opc2 = op2, \
400 .opc3 = op3, \
401 .pad = { 0, }, \
402 .handler = { \
403 .inval = invl, \
404 .type = _typ, \
405 .handler = &gen_##name, \
406 }, \
407 .oname = stringify(name), \
409 #endif
411 #define GEN_OPCODE_MARK(name) \
412 OPCODES_SECTION opcode_t opc_##name = { \
413 .opc1 = 0xFF, \
414 .opc2 = 0xFF, \
415 .opc3 = 0xFF, \
416 .pad = { 0, }, \
417 .handler = { \
418 .inval = 0x00000000, \
419 .type = 0x00, \
420 .handler = NULL, \
421 }, \
422 .oname = stringify(name), \
425 /* Start opcode list */
426 GEN_OPCODE_MARK(start);
428 /* Invalid instruction */
429 GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE)
431 RET_INVAL(ctx);
434 static opc_handler_t invalid_handler = {
435 .inval = 0xFFFFFFFF,
436 .type = PPC_NONE,
437 .handler = gen_invalid,
440 /*** Integer arithmetic ***/
441 #define __GEN_INT_ARITH2(name, opc1, opc2, opc3, inval, type) \
442 GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
444 gen_op_load_gpr_T0(rA(ctx->opcode)); \
445 gen_op_load_gpr_T1(rB(ctx->opcode)); \
446 gen_op_##name(); \
447 gen_op_store_T0_gpr(rD(ctx->opcode)); \
448 if (unlikely(Rc(ctx->opcode) != 0)) \
449 gen_set_Rc0(ctx); \
452 #define __GEN_INT_ARITH2_O(name, opc1, opc2, opc3, inval, type) \
453 GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
455 gen_op_load_gpr_T0(rA(ctx->opcode)); \
456 gen_op_load_gpr_T1(rB(ctx->opcode)); \
457 gen_op_##name(); \
458 gen_op_store_T0_gpr(rD(ctx->opcode)); \
459 if (unlikely(Rc(ctx->opcode) != 0)) \
460 gen_set_Rc0(ctx); \
463 #define __GEN_INT_ARITH1(name, opc1, opc2, opc3, type) \
464 GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, type) \
466 gen_op_load_gpr_T0(rA(ctx->opcode)); \
467 gen_op_##name(); \
468 gen_op_store_T0_gpr(rD(ctx->opcode)); \
469 if (unlikely(Rc(ctx->opcode) != 0)) \
470 gen_set_Rc0(ctx); \
472 #define __GEN_INT_ARITH1_O(name, opc1, opc2, opc3, type) \
473 GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, type) \
475 gen_op_load_gpr_T0(rA(ctx->opcode)); \
476 gen_op_##name(); \
477 gen_op_store_T0_gpr(rD(ctx->opcode)); \
478 if (unlikely(Rc(ctx->opcode) != 0)) \
479 gen_set_Rc0(ctx); \
482 /* Two operands arithmetic functions */
483 #define GEN_INT_ARITH2(name, opc1, opc2, opc3, type) \
484 __GEN_INT_ARITH2(name, opc1, opc2, opc3, 0x00000000, type) \
485 __GEN_INT_ARITH2_O(name##o, opc1, opc2, opc3 | 0x10, 0x00000000, type)
487 /* Two operands arithmetic functions with no overflow allowed */
488 #define GEN_INT_ARITHN(name, opc1, opc2, opc3, type) \
489 __GEN_INT_ARITH2(name, opc1, opc2, opc3, 0x00000400, type)
491 /* One operand arithmetic functions */
492 #define GEN_INT_ARITH1(name, opc1, opc2, opc3, type) \
493 __GEN_INT_ARITH1(name, opc1, opc2, opc3, type) \
494 __GEN_INT_ARITH1_O(name##o, opc1, opc2, opc3 | 0x10, type)
496 #if defined(TARGET_PPC64)
497 #define __GEN_INT_ARITH2_64(name, opc1, opc2, opc3, inval, type) \
498 GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
500 gen_op_load_gpr_T0(rA(ctx->opcode)); \
501 gen_op_load_gpr_T1(rB(ctx->opcode)); \
502 if (ctx->sf_mode) \
503 gen_op_##name##_64(); \
504 else \
505 gen_op_##name(); \
506 gen_op_store_T0_gpr(rD(ctx->opcode)); \
507 if (unlikely(Rc(ctx->opcode) != 0)) \
508 gen_set_Rc0(ctx); \
511 #define __GEN_INT_ARITH2_O_64(name, opc1, opc2, opc3, inval, type) \
512 GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
514 gen_op_load_gpr_T0(rA(ctx->opcode)); \
515 gen_op_load_gpr_T1(rB(ctx->opcode)); \
516 if (ctx->sf_mode) \
517 gen_op_##name##_64(); \
518 else \
519 gen_op_##name(); \
520 gen_op_store_T0_gpr(rD(ctx->opcode)); \
521 if (unlikely(Rc(ctx->opcode) != 0)) \
522 gen_set_Rc0(ctx); \
525 #define __GEN_INT_ARITH1_64(name, opc1, opc2, opc3, type) \
526 GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, type) \
528 gen_op_load_gpr_T0(rA(ctx->opcode)); \
529 if (ctx->sf_mode) \
530 gen_op_##name##_64(); \
531 else \
532 gen_op_##name(); \
533 gen_op_store_T0_gpr(rD(ctx->opcode)); \
534 if (unlikely(Rc(ctx->opcode) != 0)) \
535 gen_set_Rc0(ctx); \
537 #define __GEN_INT_ARITH1_O_64(name, opc1, opc2, opc3, type) \
538 GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, type) \
540 gen_op_load_gpr_T0(rA(ctx->opcode)); \
541 if (ctx->sf_mode) \
542 gen_op_##name##_64(); \
543 else \
544 gen_op_##name(); \
545 gen_op_store_T0_gpr(rD(ctx->opcode)); \
546 if (unlikely(Rc(ctx->opcode) != 0)) \
547 gen_set_Rc0(ctx); \
550 /* Two operands arithmetic functions */
551 #define GEN_INT_ARITH2_64(name, opc1, opc2, opc3, type) \
552 __GEN_INT_ARITH2_64(name, opc1, opc2, opc3, 0x00000000, type) \
553 __GEN_INT_ARITH2_O_64(name##o, opc1, opc2, opc3 | 0x10, 0x00000000, type)
555 /* Two operands arithmetic functions with no overflow allowed */
556 #define GEN_INT_ARITHN_64(name, opc1, opc2, opc3, type) \
557 __GEN_INT_ARITH2_64(name, opc1, opc2, opc3, 0x00000400, type)
559 /* One operand arithmetic functions */
560 #define GEN_INT_ARITH1_64(name, opc1, opc2, opc3, type) \
561 __GEN_INT_ARITH1_64(name, opc1, opc2, opc3, type) \
562 __GEN_INT_ARITH1_O_64(name##o, opc1, opc2, opc3 | 0x10, type)
563 #else
564 #define GEN_INT_ARITH2_64 GEN_INT_ARITH2
565 #define GEN_INT_ARITHN_64 GEN_INT_ARITHN
566 #define GEN_INT_ARITH1_64 GEN_INT_ARITH1
567 #endif
569 /* add add. addo addo. */
570 static inline void gen_op_addo (void)
572 gen_op_move_T2_T0();
573 gen_op_add();
574 gen_op_check_addo();
576 #if defined(TARGET_PPC64)
577 #define gen_op_add_64 gen_op_add
578 static inline void gen_op_addo_64 (void)
580 gen_op_move_T2_T0();
581 gen_op_add();
582 gen_op_check_addo_64();
584 #endif
585 GEN_INT_ARITH2_64 (add, 0x1F, 0x0A, 0x08, PPC_INTEGER);
586 /* addc addc. addco addco. */
587 static inline void gen_op_addc (void)
589 gen_op_move_T2_T0();
590 gen_op_add();
591 gen_op_check_addc();
593 static inline void gen_op_addco (void)
595 gen_op_move_T2_T0();
596 gen_op_add();
597 gen_op_check_addc();
598 gen_op_check_addo();
600 #if defined(TARGET_PPC64)
601 static inline void gen_op_addc_64 (void)
603 gen_op_move_T2_T0();
604 gen_op_add();
605 gen_op_check_addc_64();
607 static inline void gen_op_addco_64 (void)
609 gen_op_move_T2_T0();
610 gen_op_add();
611 gen_op_check_addc_64();
612 gen_op_check_addo_64();
614 #endif
615 GEN_INT_ARITH2_64 (addc, 0x1F, 0x0A, 0x00, PPC_INTEGER);
616 /* adde adde. addeo addeo. */
617 static inline void gen_op_addeo (void)
619 gen_op_move_T2_T0();
620 gen_op_adde();
621 gen_op_check_addo();
623 #if defined(TARGET_PPC64)
624 static inline void gen_op_addeo_64 (void)
626 gen_op_move_T2_T0();
627 gen_op_adde_64();
628 gen_op_check_addo_64();
630 #endif
631 GEN_INT_ARITH2_64 (adde, 0x1F, 0x0A, 0x04, PPC_INTEGER);
632 /* addme addme. addmeo addmeo. */
633 static inline void gen_op_addme (void)
635 gen_op_move_T1_T0();
636 gen_op_add_me();
638 #if defined(TARGET_PPC64)
639 static inline void gen_op_addme_64 (void)
641 gen_op_move_T1_T0();
642 gen_op_add_me_64();
644 #endif
645 GEN_INT_ARITH1_64 (addme, 0x1F, 0x0A, 0x07, PPC_INTEGER);
646 /* addze addze. addzeo addzeo. */
647 static inline void gen_op_addze (void)
649 gen_op_move_T2_T0();
650 gen_op_add_ze();
651 gen_op_check_addc();
653 static inline void gen_op_addzeo (void)
655 gen_op_move_T2_T0();
656 gen_op_add_ze();
657 gen_op_check_addc();
658 gen_op_check_addo();
660 #if defined(TARGET_PPC64)
661 static inline void gen_op_addze_64 (void)
663 gen_op_move_T2_T0();
664 gen_op_add_ze();
665 gen_op_check_addc_64();
667 static inline void gen_op_addzeo_64 (void)
669 gen_op_move_T2_T0();
670 gen_op_add_ze();
671 gen_op_check_addc_64();
672 gen_op_check_addo_64();
674 #endif
675 GEN_INT_ARITH1_64 (addze, 0x1F, 0x0A, 0x06, PPC_INTEGER);
676 /* divw divw. divwo divwo. */
677 GEN_INT_ARITH2 (divw, 0x1F, 0x0B, 0x0F, PPC_INTEGER);
678 /* divwu divwu. divwuo divwuo. */
679 GEN_INT_ARITH2 (divwu, 0x1F, 0x0B, 0x0E, PPC_INTEGER);
680 /* mulhw mulhw. */
681 GEN_INT_ARITHN (mulhw, 0x1F, 0x0B, 0x02, PPC_INTEGER);
682 /* mulhwu mulhwu. */
683 GEN_INT_ARITHN (mulhwu, 0x1F, 0x0B, 0x00, PPC_INTEGER);
684 /* mullw mullw. mullwo mullwo. */
685 GEN_INT_ARITH2 (mullw, 0x1F, 0x0B, 0x07, PPC_INTEGER);
686 /* neg neg. nego nego. */
687 GEN_INT_ARITH1_64 (neg, 0x1F, 0x08, 0x03, PPC_INTEGER);
688 /* subf subf. subfo subfo. */
689 static inline void gen_op_subfo (void)
691 gen_op_move_T2_T0();
692 gen_op_subf();
693 gen_op_check_subfo();
695 #if defined(TARGET_PPC64)
696 #define gen_op_subf_64 gen_op_subf
697 static inline void gen_op_subfo_64 (void)
699 gen_op_move_T2_T0();
700 gen_op_subf();
701 gen_op_check_subfo_64();
703 #endif
704 GEN_INT_ARITH2_64 (subf, 0x1F, 0x08, 0x01, PPC_INTEGER);
705 /* subfc subfc. subfco subfco. */
706 static inline void gen_op_subfc (void)
708 gen_op_subf();
709 gen_op_check_subfc();
711 static inline void gen_op_subfco (void)
713 gen_op_move_T2_T0();
714 gen_op_subf();
715 gen_op_check_subfc();
716 gen_op_check_subfo();
718 #if defined(TARGET_PPC64)
719 static inline void gen_op_subfc_64 (void)
721 gen_op_subf();
722 gen_op_check_subfc_64();
724 static inline void gen_op_subfco_64 (void)
726 gen_op_move_T2_T0();
727 gen_op_subf();
728 gen_op_check_subfc_64();
729 gen_op_check_subfo_64();
731 #endif
732 GEN_INT_ARITH2_64 (subfc, 0x1F, 0x08, 0x00, PPC_INTEGER);
733 /* subfe subfe. subfeo subfeo. */
734 static inline void gen_op_subfeo (void)
736 gen_op_move_T2_T0();
737 gen_op_subfe();
738 gen_op_check_subfo();
740 #if defined(TARGET_PPC64)
741 #define gen_op_subfe_64 gen_op_subfe
742 static inline void gen_op_subfeo_64 (void)
744 gen_op_move_T2_T0();
745 gen_op_subfe_64();
746 gen_op_check_subfo_64();
748 #endif
749 GEN_INT_ARITH2_64 (subfe, 0x1F, 0x08, 0x04, PPC_INTEGER);
750 /* subfme subfme. subfmeo subfmeo. */
751 GEN_INT_ARITH1_64 (subfme, 0x1F, 0x08, 0x07, PPC_INTEGER);
752 /* subfze subfze. subfzeo subfzeo. */
753 GEN_INT_ARITH1_64 (subfze, 0x1F, 0x08, 0x06, PPC_INTEGER);
754 /* addi */
755 GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
757 target_long simm = SIMM(ctx->opcode);
759 if (rA(ctx->opcode) == 0) {
760 /* li case */
761 gen_set_T0(simm);
762 } else {
763 gen_op_load_gpr_T0(rA(ctx->opcode));
764 if (likely(simm != 0))
765 gen_op_addi(simm);
767 gen_op_store_T0_gpr(rD(ctx->opcode));
769 /* addic */
770 GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
772 target_long simm = SIMM(ctx->opcode);
774 gen_op_load_gpr_T0(rA(ctx->opcode));
775 if (likely(simm != 0)) {
776 gen_op_move_T2_T0();
777 gen_op_addi(simm);
778 #if defined(TARGET_PPC64)
779 if (ctx->sf_mode)
780 gen_op_check_addc_64();
781 else
782 #endif
783 gen_op_check_addc();
784 } else {
785 gen_op_clear_xer_ca();
787 gen_op_store_T0_gpr(rD(ctx->opcode));
789 /* addic. */
790 GEN_HANDLER(addic_, 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
792 target_long simm = SIMM(ctx->opcode);
794 gen_op_load_gpr_T0(rA(ctx->opcode));
795 if (likely(simm != 0)) {
796 gen_op_move_T2_T0();
797 gen_op_addi(simm);
798 #if defined(TARGET_PPC64)
799 if (ctx->sf_mode)
800 gen_op_check_addc_64();
801 else
802 #endif
803 gen_op_check_addc();
805 gen_op_store_T0_gpr(rD(ctx->opcode));
806 gen_set_Rc0(ctx);
808 /* addis */
809 GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
811 target_long simm = SIMM(ctx->opcode);
813 if (rA(ctx->opcode) == 0) {
814 /* lis case */
815 gen_set_T0(simm << 16);
816 } else {
817 gen_op_load_gpr_T0(rA(ctx->opcode));
818 if (likely(simm != 0))
819 gen_op_addi(simm << 16);
821 gen_op_store_T0_gpr(rD(ctx->opcode));
823 /* mulli */
824 GEN_HANDLER(mulli, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
826 gen_op_load_gpr_T0(rA(ctx->opcode));
827 gen_op_mulli(SIMM(ctx->opcode));
828 gen_op_store_T0_gpr(rD(ctx->opcode));
830 /* subfic */
831 GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
833 gen_op_load_gpr_T0(rA(ctx->opcode));
834 #if defined(TARGET_PPC64)
835 if (ctx->sf_mode)
836 gen_op_subfic_64(SIMM(ctx->opcode));
837 else
838 #endif
839 gen_op_subfic(SIMM(ctx->opcode));
840 gen_op_store_T0_gpr(rD(ctx->opcode));
843 #if defined(TARGET_PPC64)
844 /* mulhd mulhd. */
845 GEN_INT_ARITHN (mulhd, 0x1F, 0x09, 0x02, PPC_INTEGER);
846 /* mulhdu mulhdu. */
847 GEN_INT_ARITHN (mulhdu, 0x1F, 0x09, 0x00, PPC_INTEGER);
848 /* mulld mulld. mulldo mulldo. */
849 GEN_INT_ARITH2 (mulld, 0x1F, 0x09, 0x07, PPC_INTEGER);
850 /* divd divd. divdo divdo. */
851 GEN_INT_ARITH2 (divd, 0x1F, 0x09, 0x0F, PPC_INTEGER);
852 /* divdu divdu. divduo divduo. */
853 GEN_INT_ARITH2 (divdu, 0x1F, 0x09, 0x0E, PPC_INTEGER);
854 #endif
856 /*** Integer comparison ***/
857 #if defined(TARGET_PPC64)
858 #define GEN_CMP(name, opc, type) \
859 GEN_HANDLER(name, 0x1F, 0x00, opc, 0x00400000, type) \
861 gen_op_load_gpr_T0(rA(ctx->opcode)); \
862 gen_op_load_gpr_T1(rB(ctx->opcode)); \
863 if (ctx->sf_mode) \
864 gen_op_##name##_64(); \
865 else \
866 gen_op_##name(); \
867 gen_op_store_T0_crf(crfD(ctx->opcode)); \
869 #else
870 #define GEN_CMP(name, opc, type) \
871 GEN_HANDLER(name, 0x1F, 0x00, opc, 0x00400000, type) \
873 gen_op_load_gpr_T0(rA(ctx->opcode)); \
874 gen_op_load_gpr_T1(rB(ctx->opcode)); \
875 gen_op_##name(); \
876 gen_op_store_T0_crf(crfD(ctx->opcode)); \
878 #endif
880 /* cmp */
881 GEN_CMP(cmp, 0x00, PPC_INTEGER);
882 /* cmpi */
883 GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
885 gen_op_load_gpr_T0(rA(ctx->opcode));
886 #if defined(TARGET_PPC64)
887 if (ctx->sf_mode)
888 gen_op_cmpi_64(SIMM(ctx->opcode));
889 else
890 #endif
891 gen_op_cmpi(SIMM(ctx->opcode));
892 gen_op_store_T0_crf(crfD(ctx->opcode));
894 /* cmpl */
895 GEN_CMP(cmpl, 0x01, PPC_INTEGER);
896 /* cmpli */
897 GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
899 gen_op_load_gpr_T0(rA(ctx->opcode));
900 #if defined(TARGET_PPC64)
901 if (ctx->sf_mode)
902 gen_op_cmpli_64(UIMM(ctx->opcode));
903 else
904 #endif
905 gen_op_cmpli(UIMM(ctx->opcode));
906 gen_op_store_T0_crf(crfD(ctx->opcode));
909 /* isel (PowerPC 2.03 specification) */
910 GEN_HANDLER(isel, 0x1F, 0x0F, 0x00, 0x00000001, PPC_203)
912 uint32_t bi = rC(ctx->opcode);
913 uint32_t mask;
915 if (rA(ctx->opcode) == 0) {
916 gen_set_T0(0);
917 } else {
918 gen_op_load_gpr_T1(rA(ctx->opcode));
920 gen_op_load_gpr_T2(rB(ctx->opcode));
921 mask = 1 << (3 - (bi & 0x03));
922 gen_op_load_crf_T0(bi >> 2);
923 gen_op_test_true(mask);
924 gen_op_isel();
925 gen_op_store_T0_gpr(rD(ctx->opcode));
928 /*** Integer logical ***/
929 #define __GEN_LOGICAL2(name, opc2, opc3, type) \
930 GEN_HANDLER(name, 0x1F, opc2, opc3, 0x00000000, type) \
932 gen_op_load_gpr_T0(rS(ctx->opcode)); \
933 gen_op_load_gpr_T1(rB(ctx->opcode)); \
934 gen_op_##name(); \
935 gen_op_store_T0_gpr(rA(ctx->opcode)); \
936 if (unlikely(Rc(ctx->opcode) != 0)) \
937 gen_set_Rc0(ctx); \
939 #define GEN_LOGICAL2(name, opc, type) \
940 __GEN_LOGICAL2(name, 0x1C, opc, type)
942 #define GEN_LOGICAL1(name, opc, type) \
943 GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, type) \
945 gen_op_load_gpr_T0(rS(ctx->opcode)); \
946 gen_op_##name(); \
947 gen_op_store_T0_gpr(rA(ctx->opcode)); \
948 if (unlikely(Rc(ctx->opcode) != 0)) \
949 gen_set_Rc0(ctx); \
952 /* and & and. */
953 GEN_LOGICAL2(and, 0x00, PPC_INTEGER);
954 /* andc & andc. */
955 GEN_LOGICAL2(andc, 0x01, PPC_INTEGER);
956 /* andi. */
957 GEN_HANDLER(andi_, 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
959 gen_op_load_gpr_T0(rS(ctx->opcode));
960 gen_op_andi_T0(UIMM(ctx->opcode));
961 gen_op_store_T0_gpr(rA(ctx->opcode));
962 gen_set_Rc0(ctx);
964 /* andis. */
965 GEN_HANDLER(andis_, 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
967 gen_op_load_gpr_T0(rS(ctx->opcode));
968 gen_op_andi_T0(UIMM(ctx->opcode) << 16);
969 gen_op_store_T0_gpr(rA(ctx->opcode));
970 gen_set_Rc0(ctx);
973 /* cntlzw */
974 GEN_LOGICAL1(cntlzw, 0x00, PPC_INTEGER);
975 /* eqv & eqv. */
976 GEN_LOGICAL2(eqv, 0x08, PPC_INTEGER);
977 /* extsb & extsb. */
978 GEN_LOGICAL1(extsb, 0x1D, PPC_INTEGER);
979 /* extsh & extsh. */
980 GEN_LOGICAL1(extsh, 0x1C, PPC_INTEGER);
981 /* nand & nand. */
982 GEN_LOGICAL2(nand, 0x0E, PPC_INTEGER);
983 /* nor & nor. */
984 GEN_LOGICAL2(nor, 0x03, PPC_INTEGER);
986 /* or & or. */
987 GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER)
989 int rs, ra, rb;
991 rs = rS(ctx->opcode);
992 ra = rA(ctx->opcode);
993 rb = rB(ctx->opcode);
994 /* Optimisation for mr. ri case */
995 if (rs != ra || rs != rb) {
996 gen_op_load_gpr_T0(rs);
997 if (rs != rb) {
998 gen_op_load_gpr_T1(rb);
999 gen_op_or();
1001 gen_op_store_T0_gpr(ra);
1002 if (unlikely(Rc(ctx->opcode) != 0))
1003 gen_set_Rc0(ctx);
1004 } else if (unlikely(Rc(ctx->opcode) != 0)) {
1005 gen_op_load_gpr_T0(rs);
1006 gen_set_Rc0(ctx);
1010 /* orc & orc. */
1011 GEN_LOGICAL2(orc, 0x0C, PPC_INTEGER);
1012 /* xor & xor. */
1013 GEN_HANDLER(xor, 0x1F, 0x1C, 0x09, 0x00000000, PPC_INTEGER)
1015 gen_op_load_gpr_T0(rS(ctx->opcode));
1016 /* Optimisation for "set to zero" case */
1017 if (rS(ctx->opcode) != rB(ctx->opcode)) {
1018 gen_op_load_gpr_T1(rB(ctx->opcode));
1019 gen_op_xor();
1020 } else {
1021 gen_op_reset_T0();
1023 gen_op_store_T0_gpr(rA(ctx->opcode));
1024 if (unlikely(Rc(ctx->opcode) != 0))
1025 gen_set_Rc0(ctx);
1027 /* ori */
1028 GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1030 target_ulong uimm = UIMM(ctx->opcode);
1032 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1033 /* NOP */
1034 /* XXX: should handle special NOPs for POWER series */
1035 return;
1037 gen_op_load_gpr_T0(rS(ctx->opcode));
1038 if (likely(uimm != 0))
1039 gen_op_ori(uimm);
1040 gen_op_store_T0_gpr(rA(ctx->opcode));
1042 /* oris */
1043 GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1045 target_ulong uimm = UIMM(ctx->opcode);
1047 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1048 /* NOP */
1049 return;
1051 gen_op_load_gpr_T0(rS(ctx->opcode));
1052 if (likely(uimm != 0))
1053 gen_op_ori(uimm << 16);
1054 gen_op_store_T0_gpr(rA(ctx->opcode));
1056 /* xori */
1057 GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1059 target_ulong uimm = UIMM(ctx->opcode);
1061 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1062 /* NOP */
1063 return;
1065 gen_op_load_gpr_T0(rS(ctx->opcode));
1066 if (likely(uimm != 0))
1067 gen_op_xori(uimm);
1068 gen_op_store_T0_gpr(rA(ctx->opcode));
1071 /* xoris */
1072 GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1074 target_ulong uimm = UIMM(ctx->opcode);
1076 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1077 /* NOP */
1078 return;
1080 gen_op_load_gpr_T0(rS(ctx->opcode));
1081 if (likely(uimm != 0))
1082 gen_op_xori(uimm << 16);
1083 gen_op_store_T0_gpr(rA(ctx->opcode));
1086 /* popcntb : PowerPC 2.03 specification */
1087 GEN_HANDLER(popcntb, 0x1F, 0x03, 0x03, 0x0000F801, PPC_203)
1089 gen_op_load_gpr_T0(rS(ctx->opcode));
1090 #if defined(TARGET_PPC64)
1091 if (ctx->sf_mode)
1092 gen_op_popcntb_64();
1093 else
1094 #endif
1095 gen_op_popcntb();
1096 gen_op_store_T0_gpr(rA(ctx->opcode));
1099 #if defined(TARGET_PPC64)
1100 /* extsw & extsw. */
1101 GEN_LOGICAL1(extsw, 0x1E, PPC_64B);
1102 /* cntlzd */
1103 GEN_LOGICAL1(cntlzd, 0x01, PPC_64B);
1104 #endif
1106 /*** Integer rotate ***/
1107 /* rlwimi & rlwimi. */
1108 GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1110 target_ulong mask;
1111 uint32_t mb, me, sh;
1113 mb = MB(ctx->opcode);
1114 me = ME(ctx->opcode);
1115 sh = SH(ctx->opcode);
1116 if (likely(sh == 0)) {
1117 if (likely(mb == 0 && me == 31)) {
1118 gen_op_load_gpr_T0(rS(ctx->opcode));
1119 goto do_store;
1120 } else if (likely(mb == 31 && me == 0)) {
1121 gen_op_load_gpr_T0(rA(ctx->opcode));
1122 goto do_store;
1124 gen_op_load_gpr_T0(rS(ctx->opcode));
1125 gen_op_load_gpr_T1(rA(ctx->opcode));
1126 goto do_mask;
1128 gen_op_load_gpr_T0(rS(ctx->opcode));
1129 gen_op_load_gpr_T1(rA(ctx->opcode));
1130 gen_op_rotli32_T0(SH(ctx->opcode));
1131 do_mask:
1132 #if defined(TARGET_PPC64)
1133 mb += 32;
1134 me += 32;
1135 #endif
1136 mask = MASK(mb, me);
1137 gen_op_andi_T0(mask);
1138 gen_op_andi_T1(~mask);
1139 gen_op_or();
1140 do_store:
1141 gen_op_store_T0_gpr(rA(ctx->opcode));
1142 if (unlikely(Rc(ctx->opcode) != 0))
1143 gen_set_Rc0(ctx);
1145 /* rlwinm & rlwinm. */
1146 GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1148 uint32_t mb, me, sh;
1150 sh = SH(ctx->opcode);
1151 mb = MB(ctx->opcode);
1152 me = ME(ctx->opcode);
1153 gen_op_load_gpr_T0(rS(ctx->opcode));
1154 if (likely(sh == 0)) {
1155 goto do_mask;
1157 if (likely(mb == 0)) {
1158 if (likely(me == 31)) {
1159 gen_op_rotli32_T0(sh);
1160 goto do_store;
1161 } else if (likely(me == (31 - sh))) {
1162 gen_op_sli_T0(sh);
1163 goto do_store;
1165 } else if (likely(me == 31)) {
1166 if (likely(sh == (32 - mb))) {
1167 gen_op_srli_T0(mb);
1168 goto do_store;
1171 gen_op_rotli32_T0(sh);
1172 do_mask:
1173 #if defined(TARGET_PPC64)
1174 mb += 32;
1175 me += 32;
1176 #endif
1177 gen_op_andi_T0(MASK(mb, me));
1178 do_store:
1179 gen_op_store_T0_gpr(rA(ctx->opcode));
1180 if (unlikely(Rc(ctx->opcode) != 0))
1181 gen_set_Rc0(ctx);
1183 /* rlwnm & rlwnm. */
1184 GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1186 uint32_t mb, me;
1188 mb = MB(ctx->opcode);
1189 me = ME(ctx->opcode);
1190 gen_op_load_gpr_T0(rS(ctx->opcode));
1191 gen_op_load_gpr_T1(rB(ctx->opcode));
1192 gen_op_rotl32_T0_T1();
1193 if (unlikely(mb != 0 || me != 31)) {
1194 #if defined(TARGET_PPC64)
1195 mb += 32;
1196 me += 32;
1197 #endif
1198 gen_op_andi_T0(MASK(mb, me));
1200 gen_op_store_T0_gpr(rA(ctx->opcode));
1201 if (unlikely(Rc(ctx->opcode) != 0))
1202 gen_set_Rc0(ctx);
1205 #if defined(TARGET_PPC64)
1206 #define GEN_PPC64_R2(name, opc1, opc2) \
1207 GEN_HANDLER(name##0, opc1, opc2, 0xFF, 0x00000000, PPC_64B) \
1209 gen_##name(ctx, 0); \
1211 GEN_HANDLER(name##1, opc1, opc2 | 0x10, 0xFF, 0x00000000, PPC_64B) \
1213 gen_##name(ctx, 1); \
1215 #define GEN_PPC64_R4(name, opc1, opc2) \
1216 GEN_HANDLER(name##0, opc1, opc2, 0xFF, 0x00000000, PPC_64B) \
1218 gen_##name(ctx, 0, 0); \
1220 GEN_HANDLER(name##1, opc1, opc2 | 0x01, 0xFF, 0x00000000, PPC_64B) \
1222 gen_##name(ctx, 0, 1); \
1224 GEN_HANDLER(name##2, opc1, opc2 | 0x10, 0xFF, 0x00000000, PPC_64B) \
1226 gen_##name(ctx, 1, 0); \
1228 GEN_HANDLER(name##3, opc1, opc2 | 0x11, 0xFF, 0x00000000, PPC_64B) \
1230 gen_##name(ctx, 1, 1); \
1233 static inline void gen_rldinm (DisasContext *ctx, uint32_t mb, uint32_t me,
1234 uint32_t sh)
1236 gen_op_load_gpr_T0(rS(ctx->opcode));
1237 if (likely(sh == 0)) {
1238 goto do_mask;
1240 if (likely(mb == 0)) {
1241 if (likely(me == 63)) {
1242 gen_op_rotli32_T0(sh);
1243 goto do_store;
1244 } else if (likely(me == (63 - sh))) {
1245 gen_op_sli_T0(sh);
1246 goto do_store;
1248 } else if (likely(me == 63)) {
1249 if (likely(sh == (64 - mb))) {
1250 gen_op_srli_T0(mb);
1251 goto do_store;
1254 gen_op_rotli64_T0(sh);
1255 do_mask:
1256 gen_op_andi_T0(MASK(mb, me));
1257 do_store:
1258 gen_op_store_T0_gpr(rA(ctx->opcode));
1259 if (unlikely(Rc(ctx->opcode) != 0))
1260 gen_set_Rc0(ctx);
1262 /* rldicl - rldicl. */
1263 static inline void gen_rldicl (DisasContext *ctx, int mbn, int shn)
1265 uint32_t sh, mb;
1267 sh = SH(ctx->opcode) | (shn << 5);
1268 mb = MB(ctx->opcode) | (mbn << 5);
1269 gen_rldinm(ctx, mb, 63, sh);
1271 GEN_PPC64_R4(rldicl, 0x1E, 0x00);
1272 /* rldicr - rldicr. */
1273 static inline void gen_rldicr (DisasContext *ctx, int men, int shn)
1275 uint32_t sh, me;
1277 sh = SH(ctx->opcode) | (shn << 5);
1278 me = MB(ctx->opcode) | (men << 5);
1279 gen_rldinm(ctx, 0, me, sh);
1281 GEN_PPC64_R4(rldicr, 0x1E, 0x02);
1282 /* rldic - rldic. */
1283 static inline void gen_rldic (DisasContext *ctx, int mbn, int shn)
1285 uint32_t sh, mb;
1287 sh = SH(ctx->opcode) | (shn << 5);
1288 mb = MB(ctx->opcode) | (mbn << 5);
1289 gen_rldinm(ctx, mb, 63 - sh, sh);
1291 GEN_PPC64_R4(rldic, 0x1E, 0x04);
1293 static inline void gen_rldnm (DisasContext *ctx, uint32_t mb, uint32_t me)
1295 gen_op_load_gpr_T0(rS(ctx->opcode));
1296 gen_op_load_gpr_T1(rB(ctx->opcode));
1297 gen_op_rotl64_T0_T1();
1298 if (unlikely(mb != 0 || me != 63)) {
1299 gen_op_andi_T0(MASK(mb, me));
1301 gen_op_store_T0_gpr(rA(ctx->opcode));
1302 if (unlikely(Rc(ctx->opcode) != 0))
1303 gen_set_Rc0(ctx);
1306 /* rldcl - rldcl. */
1307 static inline void gen_rldcl (DisasContext *ctx, int mbn)
1309 uint32_t mb;
1311 mb = MB(ctx->opcode) | (mbn << 5);
1312 gen_rldnm(ctx, mb, 63);
1314 GEN_PPC64_R2(rldcl, 0x1E, 0x08)
1315 /* rldcr - rldcr. */
1316 static inline void gen_rldcr (DisasContext *ctx, int men)
1318 uint32_t me;
1320 me = MB(ctx->opcode) | (men << 5);
1321 gen_rldnm(ctx, 0, me);
1323 GEN_PPC64_R2(rldcr, 0x1E, 0x09)
1324 /* rldimi - rldimi. */
1325 static inline void gen_rldimi (DisasContext *ctx, int mbn, int shn)
1327 uint64_t mask;
1328 uint32_t sh, mb;
1330 sh = SH(ctx->opcode) | (shn << 5);
1331 mb = MB(ctx->opcode) | (mbn << 5);
1332 if (likely(sh == 0)) {
1333 if (likely(mb == 0)) {
1334 gen_op_load_gpr_T0(rS(ctx->opcode));
1335 goto do_store;
1336 } else if (likely(mb == 63)) {
1337 gen_op_load_gpr_T0(rA(ctx->opcode));
1338 goto do_store;
1340 gen_op_load_gpr_T0(rS(ctx->opcode));
1341 gen_op_load_gpr_T1(rA(ctx->opcode));
1342 goto do_mask;
1344 gen_op_load_gpr_T0(rS(ctx->opcode));
1345 gen_op_load_gpr_T1(rA(ctx->opcode));
1346 gen_op_rotli64_T0(SH(ctx->opcode));
1347 do_mask:
1348 mask = MASK(mb, 63 - sh);
1349 gen_op_andi_T0(mask);
1350 gen_op_andi_T1(~mask);
1351 gen_op_or();
1352 do_store:
1353 gen_op_store_T0_gpr(rA(ctx->opcode));
1354 if (unlikely(Rc(ctx->opcode) != 0))
1355 gen_set_Rc0(ctx);
1357 GEN_PPC64_R4(rldimi, 0x1E, 0x06)
1358 #endif
1360 /*** Integer shift ***/
1361 /* slw & slw. */
1362 __GEN_LOGICAL2(slw, 0x18, 0x00, PPC_INTEGER);
1363 /* sraw & sraw. */
1364 __GEN_LOGICAL2(sraw, 0x18, 0x18, PPC_INTEGER);
1365 /* srawi & srawi. */
1366 GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER)
1368 int mb, me;
1369 gen_op_load_gpr_T0(rS(ctx->opcode));
1370 if (SH(ctx->opcode) != 0) {
1371 gen_op_move_T1_T0();
1372 mb = 32 - SH(ctx->opcode);
1373 me = 31;
1374 #if defined(TARGET_PPC64)
1375 mb += 32;
1376 me += 32;
1377 #endif
1378 gen_op_srawi(SH(ctx->opcode), MASK(mb, me));
1380 gen_op_store_T0_gpr(rA(ctx->opcode));
1381 if (unlikely(Rc(ctx->opcode) != 0))
1382 gen_set_Rc0(ctx);
1384 /* srw & srw. */
1385 __GEN_LOGICAL2(srw, 0x18, 0x10, PPC_INTEGER);
1387 #if defined(TARGET_PPC64)
1388 /* sld & sld. */
1389 __GEN_LOGICAL2(sld, 0x1B, 0x00, PPC_64B);
1390 /* srad & srad. */
1391 __GEN_LOGICAL2(srad, 0x1A, 0x18, PPC_64B);
1392 /* sradi & sradi. */
1393 static inline void gen_sradi (DisasContext *ctx, int n)
1395 uint64_t mask;
1396 int sh, mb, me;
1398 gen_op_load_gpr_T0(rS(ctx->opcode));
1399 sh = SH(ctx->opcode) + (n << 5);
1400 if (sh != 0) {
1401 gen_op_move_T1_T0();
1402 mb = 64 - SH(ctx->opcode);
1403 me = 63;
1404 mask = MASK(mb, me);
1405 gen_op_sradi(sh, mask >> 32, mask);
1407 gen_op_store_T0_gpr(rA(ctx->opcode));
1408 if (unlikely(Rc(ctx->opcode) != 0))
1409 gen_set_Rc0(ctx);
1411 GEN_HANDLER(sradi0, 0x1F, 0x1A, 0x19, 0x00000000, PPC_64B)
1413 gen_sradi(ctx, 0);
1415 GEN_HANDLER(sradi1, 0x1F, 0x1B, 0x19, 0x00000000, PPC_64B)
1417 gen_sradi(ctx, 1);
1419 /* srd & srd. */
1420 __GEN_LOGICAL2(srd, 0x1B, 0x10, PPC_64B);
1421 #endif
1423 /*** Floating-Point arithmetic ***/
1424 #define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat) \
1425 GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, PPC_FLOAT) \
1427 if (unlikely(!ctx->fpu_enabled)) { \
1428 RET_EXCP(ctx, EXCP_NO_FP, 0); \
1429 return; \
1431 gen_op_reset_scrfx(); \
1432 gen_op_load_fpr_FT0(rA(ctx->opcode)); \
1433 gen_op_load_fpr_FT1(rC(ctx->opcode)); \
1434 gen_op_load_fpr_FT2(rB(ctx->opcode)); \
1435 gen_op_f##op(); \
1436 if (isfloat) { \
1437 gen_op_frsp(); \
1439 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
1440 if (unlikely(Rc(ctx->opcode) != 0)) \
1441 gen_op_set_Rc1(); \
1444 #define GEN_FLOAT_ACB(name, op2) \
1445 _GEN_FLOAT_ACB(name, name, 0x3F, op2, 0); \
1446 _GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1);
1448 #define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat) \
1449 GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \
1451 if (unlikely(!ctx->fpu_enabled)) { \
1452 RET_EXCP(ctx, EXCP_NO_FP, 0); \
1453 return; \
1455 gen_op_reset_scrfx(); \
1456 gen_op_load_fpr_FT0(rA(ctx->opcode)); \
1457 gen_op_load_fpr_FT1(rB(ctx->opcode)); \
1458 gen_op_f##op(); \
1459 if (isfloat) { \
1460 gen_op_frsp(); \
1462 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
1463 if (unlikely(Rc(ctx->opcode) != 0)) \
1464 gen_op_set_Rc1(); \
1466 #define GEN_FLOAT_AB(name, op2, inval) \
1467 _GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0); \
1468 _GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1);
1470 #define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat) \
1471 GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \
1473 if (unlikely(!ctx->fpu_enabled)) { \
1474 RET_EXCP(ctx, EXCP_NO_FP, 0); \
1475 return; \
1477 gen_op_reset_scrfx(); \
1478 gen_op_load_fpr_FT0(rA(ctx->opcode)); \
1479 gen_op_load_fpr_FT1(rC(ctx->opcode)); \
1480 gen_op_f##op(); \
1481 if (isfloat) { \
1482 gen_op_frsp(); \
1484 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
1485 if (unlikely(Rc(ctx->opcode) != 0)) \
1486 gen_op_set_Rc1(); \
1488 #define GEN_FLOAT_AC(name, op2, inval) \
1489 _GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0); \
1490 _GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1);
1492 #define GEN_FLOAT_B(name, op2, op3) \
1493 GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, PPC_FLOAT) \
1495 if (unlikely(!ctx->fpu_enabled)) { \
1496 RET_EXCP(ctx, EXCP_NO_FP, 0); \
1497 return; \
1499 gen_op_reset_scrfx(); \
1500 gen_op_load_fpr_FT0(rB(ctx->opcode)); \
1501 gen_op_f##name(); \
1502 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
1503 if (unlikely(Rc(ctx->opcode) != 0)) \
1504 gen_op_set_Rc1(); \
1507 #define GEN_FLOAT_BS(name, op1, op2) \
1508 GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, PPC_FLOAT) \
1510 if (unlikely(!ctx->fpu_enabled)) { \
1511 RET_EXCP(ctx, EXCP_NO_FP, 0); \
1512 return; \
1514 gen_op_reset_scrfx(); \
1515 gen_op_load_fpr_FT0(rB(ctx->opcode)); \
1516 gen_op_f##name(); \
1517 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
1518 if (unlikely(Rc(ctx->opcode) != 0)) \
1519 gen_op_set_Rc1(); \
1522 /* fadd - fadds */
1523 GEN_FLOAT_AB(add, 0x15, 0x000007C0);
1524 /* fdiv - fdivs */
1525 GEN_FLOAT_AB(div, 0x12, 0x000007C0);
1526 /* fmul - fmuls */
1527 GEN_FLOAT_AC(mul, 0x19, 0x0000F800);
1529 /* fres */ /* XXX: not in 601 */
1530 GEN_FLOAT_BS(res, 0x3B, 0x18);
1532 /* frsqrte */ /* XXX: not in 601 */
1533 GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A);
1535 /* fsel */ /* XXX: not in 601 */
1536 _GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0);
1537 /* fsub - fsubs */
1538 GEN_FLOAT_AB(sub, 0x14, 0x000007C0);
1539 /* Optional: */
1540 /* fsqrt */
1541 GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_OPT)
1543 if (unlikely(!ctx->fpu_enabled)) {
1544 RET_EXCP(ctx, EXCP_NO_FP, 0);
1545 return;
1547 gen_op_reset_scrfx();
1548 gen_op_load_fpr_FT0(rB(ctx->opcode));
1549 gen_op_fsqrt();
1550 gen_op_store_FT0_fpr(rD(ctx->opcode));
1551 if (unlikely(Rc(ctx->opcode) != 0))
1552 gen_op_set_Rc1();
1555 GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_OPT)
1557 if (unlikely(!ctx->fpu_enabled)) {
1558 RET_EXCP(ctx, EXCP_NO_FP, 0);
1559 return;
1561 gen_op_reset_scrfx();
1562 gen_op_load_fpr_FT0(rB(ctx->opcode));
1563 gen_op_fsqrt();
1564 gen_op_frsp();
1565 gen_op_store_FT0_fpr(rD(ctx->opcode));
1566 if (unlikely(Rc(ctx->opcode) != 0))
1567 gen_op_set_Rc1();
1570 /*** Floating-Point multiply-and-add ***/
1571 /* fmadd - fmadds */
1572 GEN_FLOAT_ACB(madd, 0x1D);
1573 /* fmsub - fmsubs */
1574 GEN_FLOAT_ACB(msub, 0x1C);
1575 /* fnmadd - fnmadds */
1576 GEN_FLOAT_ACB(nmadd, 0x1F);
1577 /* fnmsub - fnmsubs */
1578 GEN_FLOAT_ACB(nmsub, 0x1E);
1580 /*** Floating-Point round & convert ***/
1581 /* fctiw */
1582 GEN_FLOAT_B(ctiw, 0x0E, 0x00);
1583 /* fctiwz */
1584 GEN_FLOAT_B(ctiwz, 0x0F, 0x00);
1585 /* frsp */
1586 GEN_FLOAT_B(rsp, 0x0C, 0x00);
1587 #if defined(TARGET_PPC64)
1588 /* fcfid */
1589 GEN_FLOAT_B(cfid, 0x0E, 0x1A);
1590 /* fctid */
1591 GEN_FLOAT_B(ctid, 0x0E, 0x19);
1592 /* fctidz */
1593 GEN_FLOAT_B(ctidz, 0x0F, 0x19);
1594 #endif
1596 /*** Floating-Point compare ***/
1597 /* fcmpo */
1598 GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT)
1600 if (unlikely(!ctx->fpu_enabled)) {
1601 RET_EXCP(ctx, EXCP_NO_FP, 0);
1602 return;
1604 gen_op_reset_scrfx();
1605 gen_op_load_fpr_FT0(rA(ctx->opcode));
1606 gen_op_load_fpr_FT1(rB(ctx->opcode));
1607 gen_op_fcmpo();
1608 gen_op_store_T0_crf(crfD(ctx->opcode));
1611 /* fcmpu */
1612 GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT)
1614 if (unlikely(!ctx->fpu_enabled)) {
1615 RET_EXCP(ctx, EXCP_NO_FP, 0);
1616 return;
1618 gen_op_reset_scrfx();
1619 gen_op_load_fpr_FT0(rA(ctx->opcode));
1620 gen_op_load_fpr_FT1(rB(ctx->opcode));
1621 gen_op_fcmpu();
1622 gen_op_store_T0_crf(crfD(ctx->opcode));
1625 /*** Floating-point move ***/
1626 /* fabs */
1627 GEN_FLOAT_B(abs, 0x08, 0x08);
1629 /* fmr - fmr. */
1630 GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT)
1632 if (unlikely(!ctx->fpu_enabled)) {
1633 RET_EXCP(ctx, EXCP_NO_FP, 0);
1634 return;
1636 gen_op_reset_scrfx();
1637 gen_op_load_fpr_FT0(rB(ctx->opcode));
1638 gen_op_store_FT0_fpr(rD(ctx->opcode));
1639 if (unlikely(Rc(ctx->opcode) != 0))
1640 gen_op_set_Rc1();
1643 /* fnabs */
1644 GEN_FLOAT_B(nabs, 0x08, 0x04);
1645 /* fneg */
1646 GEN_FLOAT_B(neg, 0x08, 0x01);
1648 /*** Floating-Point status & ctrl register ***/
1649 /* mcrfs */
1650 GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT)
1652 if (unlikely(!ctx->fpu_enabled)) {
1653 RET_EXCP(ctx, EXCP_NO_FP, 0);
1654 return;
1656 gen_op_load_fpscr_T0(crfS(ctx->opcode));
1657 gen_op_store_T0_crf(crfD(ctx->opcode));
1658 gen_op_clear_fpscr(crfS(ctx->opcode));
1661 /* mffs */
1662 GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT)
1664 if (unlikely(!ctx->fpu_enabled)) {
1665 RET_EXCP(ctx, EXCP_NO_FP, 0);
1666 return;
1668 gen_op_load_fpscr();
1669 gen_op_store_FT0_fpr(rD(ctx->opcode));
1670 if (unlikely(Rc(ctx->opcode) != 0))
1671 gen_op_set_Rc1();
1674 /* mtfsb0 */
1675 GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT)
1677 uint8_t crb;
1679 if (unlikely(!ctx->fpu_enabled)) {
1680 RET_EXCP(ctx, EXCP_NO_FP, 0);
1681 return;
1683 crb = crbD(ctx->opcode) >> 2;
1684 gen_op_load_fpscr_T0(crb);
1685 gen_op_andi_T0(~(1 << (crbD(ctx->opcode) & 0x03)));
1686 gen_op_store_T0_fpscr(crb);
1687 if (unlikely(Rc(ctx->opcode) != 0))
1688 gen_op_set_Rc1();
1691 /* mtfsb1 */
1692 GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT)
1694 uint8_t crb;
1696 if (unlikely(!ctx->fpu_enabled)) {
1697 RET_EXCP(ctx, EXCP_NO_FP, 0);
1698 return;
1700 crb = crbD(ctx->opcode) >> 2;
1701 gen_op_load_fpscr_T0(crb);
1702 gen_op_ori(1 << (crbD(ctx->opcode) & 0x03));
1703 gen_op_store_T0_fpscr(crb);
1704 if (unlikely(Rc(ctx->opcode) != 0))
1705 gen_op_set_Rc1();
1708 /* mtfsf */
1709 GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT)
1711 if (unlikely(!ctx->fpu_enabled)) {
1712 RET_EXCP(ctx, EXCP_NO_FP, 0);
1713 return;
1715 gen_op_load_fpr_FT0(rB(ctx->opcode));
1716 gen_op_store_fpscr(FM(ctx->opcode));
1717 if (unlikely(Rc(ctx->opcode) != 0))
1718 gen_op_set_Rc1();
1721 /* mtfsfi */
1722 GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT)
1724 if (unlikely(!ctx->fpu_enabled)) {
1725 RET_EXCP(ctx, EXCP_NO_FP, 0);
1726 return;
1728 gen_op_store_T0_fpscri(crbD(ctx->opcode) >> 2, FPIMM(ctx->opcode));
1729 if (unlikely(Rc(ctx->opcode) != 0))
1730 gen_op_set_Rc1();
1733 /*** Addressing modes ***/
1734 /* Register indirect with immediate index : EA = (rA|0) + SIMM */
1735 static inline void gen_addr_imm_index (DisasContext *ctx, int maskl)
1737 target_long simm = SIMM(ctx->opcode);
1739 if (maskl)
1740 simm &= ~0x03;
1741 if (rA(ctx->opcode) == 0) {
1742 gen_set_T0(simm);
1743 } else {
1744 gen_op_load_gpr_T0(rA(ctx->opcode));
1745 if (likely(simm != 0))
1746 gen_op_addi(simm);
1750 static inline void gen_addr_reg_index (DisasContext *ctx)
1752 if (rA(ctx->opcode) == 0) {
1753 gen_op_load_gpr_T0(rB(ctx->opcode));
1754 } else {
1755 gen_op_load_gpr_T0(rA(ctx->opcode));
1756 gen_op_load_gpr_T1(rB(ctx->opcode));
1757 gen_op_add();
1761 static inline void gen_addr_register (DisasContext *ctx)
1763 if (rA(ctx->opcode) == 0) {
1764 gen_op_reset_T0();
1765 } else {
1766 gen_op_load_gpr_T0(rA(ctx->opcode));
1770 /*** Integer load ***/
1771 #define op_ldst(name) (*gen_op_##name[ctx->mem_idx])()
1772 #if defined(CONFIG_USER_ONLY)
1773 #if defined(TARGET_PPC64)
1774 #define OP_LD_TABLE(width) \
1775 static GenOpFunc *gen_op_l##width[] = { \
1776 &gen_op_l##width##_raw, \
1777 &gen_op_l##width##_le_raw, \
1778 &gen_op_l##width##_64_raw, \
1779 &gen_op_l##width##_le_64_raw, \
1781 #define OP_ST_TABLE(width) \
1782 static GenOpFunc *gen_op_st##width[] = { \
1783 &gen_op_st##width##_raw, \
1784 &gen_op_st##width##_le_raw, \
1785 &gen_op_st##width##_64_raw, \
1786 &gen_op_st##width##_le_64_raw, \
1788 /* Byte access routine are endian safe */
1789 #define gen_op_stb_le_64_raw gen_op_stb_64_raw
1790 #define gen_op_lbz_le_64_raw gen_op_lbz_64_raw
1791 #else
1792 #define OP_LD_TABLE(width) \
1793 static GenOpFunc *gen_op_l##width[] = { \
1794 &gen_op_l##width##_raw, \
1795 &gen_op_l##width##_le_raw, \
1797 #define OP_ST_TABLE(width) \
1798 static GenOpFunc *gen_op_st##width[] = { \
1799 &gen_op_st##width##_raw, \
1800 &gen_op_st##width##_le_raw, \
1802 #endif
1803 /* Byte access routine are endian safe */
1804 #define gen_op_stb_le_raw gen_op_stb_raw
1805 #define gen_op_lbz_le_raw gen_op_lbz_raw
1806 #else
1807 #if defined(TARGET_PPC64)
1808 #define OP_LD_TABLE(width) \
1809 static GenOpFunc *gen_op_l##width[] = { \
1810 &gen_op_l##width##_user, \
1811 &gen_op_l##width##_le_user, \
1812 &gen_op_l##width##_kernel, \
1813 &gen_op_l##width##_le_kernel, \
1814 &gen_op_l##width##_64_user, \
1815 &gen_op_l##width##_le_64_user, \
1816 &gen_op_l##width##_64_kernel, \
1817 &gen_op_l##width##_le_64_kernel, \
1819 #define OP_ST_TABLE(width) \
1820 static GenOpFunc *gen_op_st##width[] = { \
1821 &gen_op_st##width##_user, \
1822 &gen_op_st##width##_le_user, \
1823 &gen_op_st##width##_kernel, \
1824 &gen_op_st##width##_le_kernel, \
1825 &gen_op_st##width##_64_user, \
1826 &gen_op_st##width##_le_64_user, \
1827 &gen_op_st##width##_64_kernel, \
1828 &gen_op_st##width##_le_64_kernel, \
1830 /* Byte access routine are endian safe */
1831 #define gen_op_stb_le_64_user gen_op_stb_64_user
1832 #define gen_op_lbz_le_64_user gen_op_lbz_64_user
1833 #define gen_op_stb_le_64_kernel gen_op_stb_64_kernel
1834 #define gen_op_lbz_le_64_kernel gen_op_lbz_64_kernel
1835 #else
1836 #define OP_LD_TABLE(width) \
1837 static GenOpFunc *gen_op_l##width[] = { \
1838 &gen_op_l##width##_user, \
1839 &gen_op_l##width##_le_user, \
1840 &gen_op_l##width##_kernel, \
1841 &gen_op_l##width##_le_kernel, \
1843 #define OP_ST_TABLE(width) \
1844 static GenOpFunc *gen_op_st##width[] = { \
1845 &gen_op_st##width##_user, \
1846 &gen_op_st##width##_le_user, \
1847 &gen_op_st##width##_kernel, \
1848 &gen_op_st##width##_le_kernel, \
1850 #endif
1851 /* Byte access routine are endian safe */
1852 #define gen_op_stb_le_user gen_op_stb_user
1853 #define gen_op_lbz_le_user gen_op_lbz_user
1854 #define gen_op_stb_le_kernel gen_op_stb_kernel
1855 #define gen_op_lbz_le_kernel gen_op_lbz_kernel
1856 #endif
1858 #define GEN_LD(width, opc, type) \
1859 GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, type) \
1861 gen_addr_imm_index(ctx, 0); \
1862 op_ldst(l##width); \
1863 gen_op_store_T1_gpr(rD(ctx->opcode)); \
1866 #define GEN_LDU(width, opc, type) \
1867 GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, type) \
1869 if (unlikely(rA(ctx->opcode) == 0 || \
1870 rA(ctx->opcode) == rD(ctx->opcode))) { \
1871 RET_INVAL(ctx); \
1872 return; \
1874 if (type == PPC_64B) \
1875 gen_addr_imm_index(ctx, 1); \
1876 else \
1877 gen_addr_imm_index(ctx, 0); \
1878 op_ldst(l##width); \
1879 gen_op_store_T1_gpr(rD(ctx->opcode)); \
1880 gen_op_store_T0_gpr(rA(ctx->opcode)); \
1883 #define GEN_LDUX(width, opc2, opc3, type) \
1884 GEN_HANDLER(l##width##ux, 0x1F, opc2, opc3, 0x00000001, type) \
1886 if (unlikely(rA(ctx->opcode) == 0 || \
1887 rA(ctx->opcode) == rD(ctx->opcode))) { \
1888 RET_INVAL(ctx); \
1889 return; \
1891 gen_addr_reg_index(ctx); \
1892 op_ldst(l##width); \
1893 gen_op_store_T1_gpr(rD(ctx->opcode)); \
1894 gen_op_store_T0_gpr(rA(ctx->opcode)); \
1897 #define GEN_LDX(width, opc2, opc3, type) \
1898 GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, type) \
1900 gen_addr_reg_index(ctx); \
1901 op_ldst(l##width); \
1902 gen_op_store_T1_gpr(rD(ctx->opcode)); \
1905 #define GEN_LDS(width, op, type) \
1906 OP_LD_TABLE(width); \
1907 GEN_LD(width, op | 0x20, type); \
1908 GEN_LDU(width, op | 0x21, type); \
1909 GEN_LDUX(width, 0x17, op | 0x01, type); \
1910 GEN_LDX(width, 0x17, op | 0x00, type)
1912 /* lbz lbzu lbzux lbzx */
1913 GEN_LDS(bz, 0x02, PPC_INTEGER);
1914 /* lha lhau lhaux lhax */
1915 GEN_LDS(ha, 0x0A, PPC_INTEGER);
1916 /* lhz lhzu lhzux lhzx */
1917 GEN_LDS(hz, 0x08, PPC_INTEGER);
1918 /* lwz lwzu lwzux lwzx */
1919 GEN_LDS(wz, 0x00, PPC_INTEGER);
1920 #if defined(TARGET_PPC64)
1921 OP_LD_TABLE(wa);
1922 OP_LD_TABLE(d);
1923 /* lwaux */
1924 GEN_LDUX(wa, 0x15, 0x0B, PPC_64B);
1925 /* lwax */
1926 GEN_LDX(wa, 0x15, 0x0A, PPC_64B);
1927 /* ldux */
1928 GEN_LDUX(d, 0x15, 0x01, PPC_64B);
1929 /* ldx */
1930 GEN_LDX(d, 0x15, 0x00, PPC_64B);
1931 GEN_HANDLER(ld, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B)
1933 if (Rc(ctx->opcode)) {
1934 if (unlikely(rA(ctx->opcode) == 0 ||
1935 rA(ctx->opcode) == rD(ctx->opcode))) {
1936 RET_INVAL(ctx);
1937 return;
1940 gen_addr_imm_index(ctx, 1);
1941 if (ctx->opcode & 0x02) {
1942 /* lwa (lwau is undefined) */
1943 op_ldst(lwa);
1944 } else {
1945 /* ld - ldu */
1946 op_ldst(ld);
1948 gen_op_store_T1_gpr(rD(ctx->opcode));
1949 if (Rc(ctx->opcode))
1950 gen_op_store_T0_gpr(rA(ctx->opcode));
1952 #endif
1954 /*** Integer store ***/
1955 #define GEN_ST(width, opc, type) \
1956 GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, type) \
1958 gen_addr_imm_index(ctx, 0); \
1959 gen_op_load_gpr_T1(rS(ctx->opcode)); \
1960 op_ldst(st##width); \
1963 #define GEN_STU(width, opc, type) \
1964 GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, type) \
1966 if (unlikely(rA(ctx->opcode) == 0)) { \
1967 RET_INVAL(ctx); \
1968 return; \
1970 if (type == PPC_64B) \
1971 gen_addr_imm_index(ctx, 1); \
1972 else \
1973 gen_addr_imm_index(ctx, 0); \
1974 gen_op_load_gpr_T1(rS(ctx->opcode)); \
1975 op_ldst(st##width); \
1976 gen_op_store_T0_gpr(rA(ctx->opcode)); \
1979 #define GEN_STUX(width, opc2, opc3, type) \
1980 GEN_HANDLER(st##width##ux, 0x1F, opc2, opc3, 0x00000001, type) \
1982 if (unlikely(rA(ctx->opcode) == 0)) { \
1983 RET_INVAL(ctx); \
1984 return; \
1986 gen_addr_reg_index(ctx); \
1987 gen_op_load_gpr_T1(rS(ctx->opcode)); \
1988 op_ldst(st##width); \
1989 gen_op_store_T0_gpr(rA(ctx->opcode)); \
1992 #define GEN_STX(width, opc2, opc3, type) \
1993 GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, type) \
1995 gen_addr_reg_index(ctx); \
1996 gen_op_load_gpr_T1(rS(ctx->opcode)); \
1997 op_ldst(st##width); \
2000 #define GEN_STS(width, op, type) \
2001 OP_ST_TABLE(width); \
2002 GEN_ST(width, op | 0x20, type); \
2003 GEN_STU(width, op | 0x21, type); \
2004 GEN_STUX(width, 0x17, op | 0x01, type); \
2005 GEN_STX(width, 0x17, op | 0x00, type)
2007 /* stb stbu stbux stbx */
2008 GEN_STS(b, 0x06, PPC_INTEGER);
2009 /* sth sthu sthux sthx */
2010 GEN_STS(h, 0x0C, PPC_INTEGER);
2011 /* stw stwu stwux stwx */
2012 GEN_STS(w, 0x04, PPC_INTEGER);
2013 #if defined(TARGET_PPC64)
2014 OP_ST_TABLE(d);
2015 GEN_STUX(d, 0x15, 0x05, PPC_64B);
2016 GEN_STX(d, 0x15, 0x04, PPC_64B);
2017 GEN_HANDLER(std, 0x3E, 0xFF, 0xFF, 0x00000002, PPC_64B)
2019 if (Rc(ctx->opcode)) {
2020 if (unlikely(rA(ctx->opcode) == 0)) {
2021 RET_INVAL(ctx);
2022 return;
2025 gen_addr_imm_index(ctx, 1);
2026 gen_op_load_gpr_T1(rS(ctx->opcode));
2027 op_ldst(std);
2028 if (Rc(ctx->opcode))
2029 gen_op_store_T0_gpr(rA(ctx->opcode));
2031 #endif
2032 /*** Integer load and store with byte reverse ***/
2033 /* lhbrx */
2034 OP_LD_TABLE(hbr);
2035 GEN_LDX(hbr, 0x16, 0x18, PPC_INTEGER);
2036 /* lwbrx */
2037 OP_LD_TABLE(wbr);
2038 GEN_LDX(wbr, 0x16, 0x10, PPC_INTEGER);
2039 /* sthbrx */
2040 OP_ST_TABLE(hbr);
2041 GEN_STX(hbr, 0x16, 0x1C, PPC_INTEGER);
2042 /* stwbrx */
2043 OP_ST_TABLE(wbr);
2044 GEN_STX(wbr, 0x16, 0x14, PPC_INTEGER);
2046 /*** Integer load and store multiple ***/
2047 #define op_ldstm(name, reg) (*gen_op_##name[ctx->mem_idx])(reg)
2048 #if defined(TARGET_PPC64)
2049 #if defined(CONFIG_USER_ONLY)
2050 static GenOpFunc1 *gen_op_lmw[] = {
2051 &gen_op_lmw_raw,
2052 &gen_op_lmw_le_raw,
2053 &gen_op_lmw_64_raw,
2054 &gen_op_lmw_le_64_raw,
2056 static GenOpFunc1 *gen_op_stmw[] = {
2057 &gen_op_stmw_64_raw,
2058 &gen_op_stmw_le_64_raw,
2060 #else
2061 static GenOpFunc1 *gen_op_lmw[] = {
2062 &gen_op_lmw_user,
2063 &gen_op_lmw_le_user,
2064 &gen_op_lmw_kernel,
2065 &gen_op_lmw_le_kernel,
2066 &gen_op_lmw_64_user,
2067 &gen_op_lmw_le_64_user,
2068 &gen_op_lmw_64_kernel,
2069 &gen_op_lmw_le_64_kernel,
2071 static GenOpFunc1 *gen_op_stmw[] = {
2072 &gen_op_stmw_user,
2073 &gen_op_stmw_le_user,
2074 &gen_op_stmw_kernel,
2075 &gen_op_stmw_le_kernel,
2076 &gen_op_stmw_64_user,
2077 &gen_op_stmw_le_64_user,
2078 &gen_op_stmw_64_kernel,
2079 &gen_op_stmw_le_64_kernel,
2081 #endif
2082 #else
2083 #if defined(CONFIG_USER_ONLY)
2084 static GenOpFunc1 *gen_op_lmw[] = {
2085 &gen_op_lmw_raw,
2086 &gen_op_lmw_le_raw,
2088 static GenOpFunc1 *gen_op_stmw[] = {
2089 &gen_op_stmw_raw,
2090 &gen_op_stmw_le_raw,
2092 #else
2093 static GenOpFunc1 *gen_op_lmw[] = {
2094 &gen_op_lmw_user,
2095 &gen_op_lmw_le_user,
2096 &gen_op_lmw_kernel,
2097 &gen_op_lmw_le_kernel,
2099 static GenOpFunc1 *gen_op_stmw[] = {
2100 &gen_op_stmw_user,
2101 &gen_op_stmw_le_user,
2102 &gen_op_stmw_kernel,
2103 &gen_op_stmw_le_kernel,
2105 #endif
2106 #endif
2108 /* lmw */
2109 GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
2111 /* NIP cannot be restored if the memory exception comes from an helper */
2112 gen_update_nip(ctx, ctx->nip - 4);
2113 gen_addr_imm_index(ctx, 0);
2114 op_ldstm(lmw, rD(ctx->opcode));
2117 /* stmw */
2118 GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
2120 /* NIP cannot be restored if the memory exception comes from an helper */
2121 gen_update_nip(ctx, ctx->nip - 4);
2122 gen_addr_imm_index(ctx, 0);
2123 op_ldstm(stmw, rS(ctx->opcode));
2126 /*** Integer load and store strings ***/
2127 #define op_ldsts(name, start) (*gen_op_##name[ctx->mem_idx])(start)
2128 #define op_ldstsx(name, rd, ra, rb) (*gen_op_##name[ctx->mem_idx])(rd, ra, rb)
2129 #if defined(TARGET_PPC64)
2130 #if defined(CONFIG_USER_ONLY)
2131 static GenOpFunc1 *gen_op_lswi[] = {
2132 &gen_op_lswi_raw,
2133 &gen_op_lswi_le_raw,
2134 &gen_op_lswi_64_raw,
2135 &gen_op_lswi_le_64_raw,
2137 static GenOpFunc3 *gen_op_lswx[] = {
2138 &gen_op_lswx_raw,
2139 &gen_op_lswx_le_raw,
2140 &gen_op_lswx_64_raw,
2141 &gen_op_lswx_le_64_raw,
2143 static GenOpFunc1 *gen_op_stsw[] = {
2144 &gen_op_stsw_raw,
2145 &gen_op_stsw_le_raw,
2146 &gen_op_stsw_64_raw,
2147 &gen_op_stsw_le_64_raw,
2149 #else
2150 static GenOpFunc1 *gen_op_lswi[] = {
2151 &gen_op_lswi_user,
2152 &gen_op_lswi_le_user,
2153 &gen_op_lswi_kernel,
2154 &gen_op_lswi_le_kernel,
2155 &gen_op_lswi_64_user,
2156 &gen_op_lswi_le_64_user,
2157 &gen_op_lswi_64_kernel,
2158 &gen_op_lswi_le_64_kernel,
2160 static GenOpFunc3 *gen_op_lswx[] = {
2161 &gen_op_lswx_user,
2162 &gen_op_lswx_le_user,
2163 &gen_op_lswx_kernel,
2164 &gen_op_lswx_le_kernel,
2165 &gen_op_lswx_64_user,
2166 &gen_op_lswx_le_64_user,
2167 &gen_op_lswx_64_kernel,
2168 &gen_op_lswx_le_64_kernel,
2170 static GenOpFunc1 *gen_op_stsw[] = {
2171 &gen_op_stsw_user,
2172 &gen_op_stsw_le_user,
2173 &gen_op_stsw_kernel,
2174 &gen_op_stsw_le_kernel,
2175 &gen_op_stsw_64_user,
2176 &gen_op_stsw_le_64_user,
2177 &gen_op_stsw_64_kernel,
2178 &gen_op_stsw_le_64_kernel,
2180 #endif
2181 #else
2182 #if defined(CONFIG_USER_ONLY)
2183 static GenOpFunc1 *gen_op_lswi[] = {
2184 &gen_op_lswi_raw,
2185 &gen_op_lswi_le_raw,
2187 static GenOpFunc3 *gen_op_lswx[] = {
2188 &gen_op_lswx_raw,
2189 &gen_op_lswx_le_raw,
2191 static GenOpFunc1 *gen_op_stsw[] = {
2192 &gen_op_stsw_raw,
2193 &gen_op_stsw_le_raw,
2195 #else
2196 static GenOpFunc1 *gen_op_lswi[] = {
2197 &gen_op_lswi_user,
2198 &gen_op_lswi_le_user,
2199 &gen_op_lswi_kernel,
2200 &gen_op_lswi_le_kernel,
2202 static GenOpFunc3 *gen_op_lswx[] = {
2203 &gen_op_lswx_user,
2204 &gen_op_lswx_le_user,
2205 &gen_op_lswx_kernel,
2206 &gen_op_lswx_le_kernel,
2208 static GenOpFunc1 *gen_op_stsw[] = {
2209 &gen_op_stsw_user,
2210 &gen_op_stsw_le_user,
2211 &gen_op_stsw_kernel,
2212 &gen_op_stsw_le_kernel,
2214 #endif
2215 #endif
2217 /* lswi */
2218 /* PowerPC32 specification says we must generate an exception if
2219 * rA is in the range of registers to be loaded.
2220 * In an other hand, IBM says this is valid, but rA won't be loaded.
2221 * For now, I'll follow the spec...
2223 GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_INTEGER)
2225 int nb = NB(ctx->opcode);
2226 int start = rD(ctx->opcode);
2227 int ra = rA(ctx->opcode);
2228 int nr;
2230 if (nb == 0)
2231 nb = 32;
2232 nr = nb / 4;
2233 if (unlikely(((start + nr) > 32 &&
2234 start <= ra && (start + nr - 32) > ra) ||
2235 ((start + nr) <= 32 && start <= ra && (start + nr) > ra))) {
2236 RET_EXCP(ctx, EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_LSWX);
2237 return;
2239 /* NIP cannot be restored if the memory exception comes from an helper */
2240 gen_update_nip(ctx, ctx->nip - 4);
2241 gen_addr_register(ctx);
2242 gen_op_set_T1(nb);
2243 op_ldsts(lswi, start);
2246 /* lswx */
2247 GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_INTEGER)
2249 int ra = rA(ctx->opcode);
2250 int rb = rB(ctx->opcode);
2252 /* NIP cannot be restored if the memory exception comes from an helper */
2253 gen_update_nip(ctx, ctx->nip - 4);
2254 gen_addr_reg_index(ctx);
2255 if (ra == 0) {
2256 ra = rb;
2258 gen_op_load_xer_bc();
2259 op_ldstsx(lswx, rD(ctx->opcode), ra, rb);
2262 /* stswi */
2263 GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_INTEGER)
2265 int nb = NB(ctx->opcode);
2267 /* NIP cannot be restored if the memory exception comes from an helper */
2268 gen_update_nip(ctx, ctx->nip - 4);
2269 gen_addr_register(ctx);
2270 if (nb == 0)
2271 nb = 32;
2272 gen_op_set_T1(nb);
2273 op_ldsts(stsw, rS(ctx->opcode));
2276 /* stswx */
2277 GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_INTEGER)
2279 /* NIP cannot be restored if the memory exception comes from an helper */
2280 gen_update_nip(ctx, ctx->nip - 4);
2281 gen_addr_reg_index(ctx);
2282 gen_op_load_xer_bc();
2283 op_ldsts(stsw, rS(ctx->opcode));
2286 /*** Memory synchronisation ***/
2287 /* eieio */
2288 GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FF0801, PPC_MEM_EIEIO)
2292 /* isync */
2293 GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FF0801, PPC_MEM)
2297 #define op_lwarx() (*gen_op_lwarx[ctx->mem_idx])()
2298 #define op_stwcx() (*gen_op_stwcx[ctx->mem_idx])()
2299 #if defined(TARGET_PPC64)
2300 #if defined(CONFIG_USER_ONLY)
2301 static GenOpFunc *gen_op_lwarx[] = {
2302 &gen_op_lwarx_raw,
2303 &gen_op_lwarx_le_raw,
2304 &gen_op_lwarx_64_raw,
2305 &gen_op_lwarx_le_64_raw,
2307 static GenOpFunc *gen_op_stwcx[] = {
2308 &gen_op_stwcx_raw,
2309 &gen_op_stwcx_le_raw,
2310 &gen_op_stwcx_64_raw,
2311 &gen_op_stwcx_le_64_raw,
2313 #else
2314 static GenOpFunc *gen_op_lwarx[] = {
2315 &gen_op_lwarx_user,
2316 &gen_op_lwarx_le_user,
2317 &gen_op_lwarx_kernel,
2318 &gen_op_lwarx_le_kernel,
2319 &gen_op_lwarx_64_user,
2320 &gen_op_lwarx_le_64_user,
2321 &gen_op_lwarx_64_kernel,
2322 &gen_op_lwarx_le_64_kernel,
2324 static GenOpFunc *gen_op_stwcx[] = {
2325 &gen_op_stwcx_user,
2326 &gen_op_stwcx_le_user,
2327 &gen_op_stwcx_kernel,
2328 &gen_op_stwcx_le_kernel,
2329 &gen_op_stwcx_64_user,
2330 &gen_op_stwcx_le_64_user,
2331 &gen_op_stwcx_64_kernel,
2332 &gen_op_stwcx_le_64_kernel,
2334 #endif
2335 #else
2336 #if defined(CONFIG_USER_ONLY)
2337 static GenOpFunc *gen_op_lwarx[] = {
2338 &gen_op_lwarx_raw,
2339 &gen_op_lwarx_le_raw,
2341 static GenOpFunc *gen_op_stwcx[] = {
2342 &gen_op_stwcx_raw,
2343 &gen_op_stwcx_le_raw,
2345 #else
2346 static GenOpFunc *gen_op_lwarx[] = {
2347 &gen_op_lwarx_user,
2348 &gen_op_lwarx_le_user,
2349 &gen_op_lwarx_kernel,
2350 &gen_op_lwarx_le_kernel,
2352 static GenOpFunc *gen_op_stwcx[] = {
2353 &gen_op_stwcx_user,
2354 &gen_op_stwcx_le_user,
2355 &gen_op_stwcx_kernel,
2356 &gen_op_stwcx_le_kernel,
2358 #endif
2359 #endif
2361 /* lwarx */
2362 GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000001, PPC_RES)
2364 gen_addr_reg_index(ctx);
2365 op_lwarx();
2366 gen_op_store_T1_gpr(rD(ctx->opcode));
2369 /* stwcx. */
2370 GEN_HANDLER(stwcx_, 0x1F, 0x16, 0x04, 0x00000000, PPC_RES)
2372 gen_addr_reg_index(ctx);
2373 gen_op_load_gpr_T1(rS(ctx->opcode));
2374 op_stwcx();
2377 #if defined(TARGET_PPC64)
2378 #define op_ldarx() (*gen_op_ldarx[ctx->mem_idx])()
2379 #define op_stdcx() (*gen_op_stdcx[ctx->mem_idx])()
2380 #if defined(CONFIG_USER_ONLY)
2381 static GenOpFunc *gen_op_ldarx[] = {
2382 &gen_op_ldarx_raw,
2383 &gen_op_ldarx_le_raw,
2384 &gen_op_ldarx_64_raw,
2385 &gen_op_ldarx_le_64_raw,
2387 static GenOpFunc *gen_op_stdcx[] = {
2388 &gen_op_stdcx_raw,
2389 &gen_op_stdcx_le_raw,
2390 &gen_op_stdcx_64_raw,
2391 &gen_op_stdcx_le_64_raw,
2393 #else
2394 static GenOpFunc *gen_op_ldarx[] = {
2395 &gen_op_ldarx_user,
2396 &gen_op_ldarx_le_user,
2397 &gen_op_ldarx_kernel,
2398 &gen_op_ldarx_le_kernel,
2399 &gen_op_ldarx_64_user,
2400 &gen_op_ldarx_le_64_user,
2401 &gen_op_ldarx_64_kernel,
2402 &gen_op_ldarx_le_64_kernel,
2404 static GenOpFunc *gen_op_stdcx[] = {
2405 &gen_op_stdcx_user,
2406 &gen_op_stdcx_le_user,
2407 &gen_op_stdcx_kernel,
2408 &gen_op_stdcx_le_kernel,
2409 &gen_op_stdcx_64_user,
2410 &gen_op_stdcx_le_64_user,
2411 &gen_op_stdcx_64_kernel,
2412 &gen_op_stdcx_le_64_kernel,
2414 #endif
2416 /* ldarx */
2417 GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000001, PPC_RES)
2419 gen_addr_reg_index(ctx);
2420 op_ldarx();
2421 gen_op_store_T1_gpr(rD(ctx->opcode));
2424 /* stdcx. */
2425 GEN_HANDLER(stdcx_, 0x1F, 0x16, 0x06, 0x00000000, PPC_RES)
2427 gen_addr_reg_index(ctx);
2428 gen_op_load_gpr_T1(rS(ctx->opcode));
2429 op_stdcx();
2431 #endif /* defined(TARGET_PPC64) */
2433 /* sync */
2434 GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x03FF0801, PPC_MEM_SYNC)
2438 /*** Floating-point load ***/
2439 #define GEN_LDF(width, opc) \
2440 GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT) \
2442 if (unlikely(!ctx->fpu_enabled)) { \
2443 RET_EXCP(ctx, EXCP_NO_FP, 0); \
2444 return; \
2446 gen_addr_imm_index(ctx, 0); \
2447 op_ldst(l##width); \
2448 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
2451 #define GEN_LDUF(width, opc) \
2452 GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT) \
2454 if (unlikely(!ctx->fpu_enabled)) { \
2455 RET_EXCP(ctx, EXCP_NO_FP, 0); \
2456 return; \
2458 if (unlikely(rA(ctx->opcode) == 0)) { \
2459 RET_INVAL(ctx); \
2460 return; \
2462 gen_addr_imm_index(ctx, 0); \
2463 op_ldst(l##width); \
2464 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
2465 gen_op_store_T0_gpr(rA(ctx->opcode)); \
2468 #define GEN_LDUXF(width, opc) \
2469 GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT) \
2471 if (unlikely(!ctx->fpu_enabled)) { \
2472 RET_EXCP(ctx, EXCP_NO_FP, 0); \
2473 return; \
2475 if (unlikely(rA(ctx->opcode) == 0)) { \
2476 RET_INVAL(ctx); \
2477 return; \
2479 gen_addr_reg_index(ctx); \
2480 op_ldst(l##width); \
2481 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
2482 gen_op_store_T0_gpr(rA(ctx->opcode)); \
2485 #define GEN_LDXF(width, opc2, opc3) \
2486 GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_FLOAT) \
2488 if (unlikely(!ctx->fpu_enabled)) { \
2489 RET_EXCP(ctx, EXCP_NO_FP, 0); \
2490 return; \
2492 gen_addr_reg_index(ctx); \
2493 op_ldst(l##width); \
2494 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
2497 #define GEN_LDFS(width, op) \
2498 OP_LD_TABLE(width); \
2499 GEN_LDF(width, op | 0x20); \
2500 GEN_LDUF(width, op | 0x21); \
2501 GEN_LDUXF(width, op | 0x01); \
2502 GEN_LDXF(width, 0x17, op | 0x00)
2504 /* lfd lfdu lfdux lfdx */
2505 GEN_LDFS(fd, 0x12);
2506 /* lfs lfsu lfsux lfsx */
2507 GEN_LDFS(fs, 0x10);
2509 /*** Floating-point store ***/
2510 #define GEN_STF(width, opc) \
2511 GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT) \
2513 if (unlikely(!ctx->fpu_enabled)) { \
2514 RET_EXCP(ctx, EXCP_NO_FP, 0); \
2515 return; \
2517 gen_addr_imm_index(ctx, 0); \
2518 gen_op_load_fpr_FT0(rS(ctx->opcode)); \
2519 op_ldst(st##width); \
2522 #define GEN_STUF(width, opc) \
2523 GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT) \
2525 if (unlikely(!ctx->fpu_enabled)) { \
2526 RET_EXCP(ctx, EXCP_NO_FP, 0); \
2527 return; \
2529 if (unlikely(rA(ctx->opcode) == 0)) { \
2530 RET_INVAL(ctx); \
2531 return; \
2533 gen_addr_imm_index(ctx, 0); \
2534 gen_op_load_fpr_FT0(rS(ctx->opcode)); \
2535 op_ldst(st##width); \
2536 gen_op_store_T0_gpr(rA(ctx->opcode)); \
2539 #define GEN_STUXF(width, opc) \
2540 GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT) \
2542 if (unlikely(!ctx->fpu_enabled)) { \
2543 RET_EXCP(ctx, EXCP_NO_FP, 0); \
2544 return; \
2546 if (unlikely(rA(ctx->opcode) == 0)) { \
2547 RET_INVAL(ctx); \
2548 return; \
2550 gen_addr_reg_index(ctx); \
2551 gen_op_load_fpr_FT0(rS(ctx->opcode)); \
2552 op_ldst(st##width); \
2553 gen_op_store_T0_gpr(rA(ctx->opcode)); \
2556 #define GEN_STXF(width, opc2, opc3) \
2557 GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_FLOAT) \
2559 if (unlikely(!ctx->fpu_enabled)) { \
2560 RET_EXCP(ctx, EXCP_NO_FP, 0); \
2561 return; \
2563 gen_addr_reg_index(ctx); \
2564 gen_op_load_fpr_FT0(rS(ctx->opcode)); \
2565 op_ldst(st##width); \
2568 #define GEN_STFS(width, op) \
2569 OP_ST_TABLE(width); \
2570 GEN_STF(width, op | 0x20); \
2571 GEN_STUF(width, op | 0x21); \
2572 GEN_STUXF(width, op | 0x01); \
2573 GEN_STXF(width, 0x17, op | 0x00)
2575 /* stfd stfdu stfdux stfdx */
2576 GEN_STFS(fd, 0x16);
2577 /* stfs stfsu stfsux stfsx */
2578 GEN_STFS(fs, 0x14);
2580 /* Optional: */
2581 /* stfiwx */
2582 GEN_HANDLER(stfiwx, 0x1F, 0x17, 0x1E, 0x00000001, PPC_FLOAT)
2584 if (unlikely(!ctx->fpu_enabled)) {
2585 RET_EXCP(ctx, EXCP_NO_FP, 0);
2586 return;
2588 gen_addr_reg_index(ctx);
2589 /* XXX: TODO: memcpy low order 32 bits of FRP(rs) into memory */
2590 RET_INVAL(ctx);
2593 /*** Branch ***/
2595 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
2597 TranslationBlock *tb;
2598 tb = ctx->tb;
2599 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
2600 if (n == 0)
2601 gen_op_goto_tb0(TBPARAM(tb));
2602 else
2603 gen_op_goto_tb1(TBPARAM(tb));
2604 gen_set_T1(dest);
2605 #if defined(TARGET_PPC64)
2606 if (ctx->sf_mode)
2607 gen_op_b_T1_64();
2608 else
2609 #endif
2610 gen_op_b_T1();
2611 gen_op_set_T0((long)tb + n);
2612 if (ctx->singlestep_enabled)
2613 gen_op_debug();
2614 gen_op_exit_tb();
2615 } else {
2616 gen_set_T1(dest);
2617 #if defined(TARGET_PPC64)
2618 if (ctx->sf_mode)
2619 gen_op_b_T1_64();
2620 else
2621 #endif
2622 gen_op_b_T1();
2623 gen_op_reset_T0();
2624 if (ctx->singlestep_enabled)
2625 gen_op_debug();
2626 gen_op_exit_tb();
2630 /* b ba bl bla */
2631 GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
2633 target_ulong li, target;
2635 /* sign extend LI */
2636 #if defined(TARGET_PPC64)
2637 if (ctx->sf_mode)
2638 li = ((int64_t)LI(ctx->opcode) << 38) >> 38;
2639 else
2640 #endif
2641 li = ((int32_t)LI(ctx->opcode) << 6) >> 6;
2642 if (likely(AA(ctx->opcode) == 0))
2643 target = ctx->nip + li - 4;
2644 else
2645 target = li;
2646 if (LK(ctx->opcode)) {
2647 #if defined(TARGET_PPC64)
2648 if (ctx->sf_mode)
2649 gen_op_setlr_64(ctx->nip >> 32, ctx->nip);
2650 else
2651 #endif
2652 gen_op_setlr(ctx->nip);
2654 gen_goto_tb(ctx, 0, target);
2655 ctx->exception = EXCP_BRANCH;
2658 #define BCOND_IM 0
2659 #define BCOND_LR 1
2660 #define BCOND_CTR 2
2662 static inline void gen_bcond(DisasContext *ctx, int type)
2664 target_ulong target = 0;
2665 target_ulong li;
2666 uint32_t bo = BO(ctx->opcode);
2667 uint32_t bi = BI(ctx->opcode);
2668 uint32_t mask;
2670 if ((bo & 0x4) == 0)
2671 gen_op_dec_ctr();
2672 switch(type) {
2673 case BCOND_IM:
2674 li = (target_long)((int16_t)(BD(ctx->opcode)));
2675 if (likely(AA(ctx->opcode) == 0)) {
2676 target = ctx->nip + li - 4;
2677 } else {
2678 target = li;
2680 break;
2681 case BCOND_CTR:
2682 gen_op_movl_T1_ctr();
2683 break;
2684 default:
2685 case BCOND_LR:
2686 gen_op_movl_T1_lr();
2687 break;
2689 if (LK(ctx->opcode)) {
2690 #if defined(TARGET_PPC64)
2691 if (ctx->sf_mode)
2692 gen_op_setlr_64(ctx->nip >> 32, ctx->nip);
2693 else
2694 #endif
2695 gen_op_setlr(ctx->nip);
2697 if (bo & 0x10) {
2698 /* No CR condition */
2699 switch (bo & 0x6) {
2700 case 0:
2701 #if defined(TARGET_PPC64)
2702 if (ctx->sf_mode)
2703 gen_op_test_ctr_64();
2704 else
2705 #endif
2706 gen_op_test_ctr();
2707 break;
2708 case 2:
2709 #if defined(TARGET_PPC64)
2710 if (ctx->sf_mode)
2711 gen_op_test_ctrz_64();
2712 else
2713 #endif
2714 gen_op_test_ctrz();
2715 break;
2716 default:
2717 case 4:
2718 case 6:
2719 if (type == BCOND_IM) {
2720 gen_goto_tb(ctx, 0, target);
2721 } else {
2722 #if defined(TARGET_PPC64)
2723 if (ctx->sf_mode)
2724 gen_op_b_T1_64();
2725 else
2726 #endif
2727 gen_op_b_T1();
2728 gen_op_reset_T0();
2730 goto no_test;
2732 } else {
2733 mask = 1 << (3 - (bi & 0x03));
2734 gen_op_load_crf_T0(bi >> 2);
2735 if (bo & 0x8) {
2736 switch (bo & 0x6) {
2737 case 0:
2738 #if defined(TARGET_PPC64)
2739 if (ctx->sf_mode)
2740 gen_op_test_ctr_true_64(mask);
2741 else
2742 #endif
2743 gen_op_test_ctr_true(mask);
2744 break;
2745 case 2:
2746 #if defined(TARGET_PPC64)
2747 if (ctx->sf_mode)
2748 gen_op_test_ctrz_true_64(mask);
2749 else
2750 #endif
2751 gen_op_test_ctrz_true(mask);
2752 break;
2753 default:
2754 case 4:
2755 case 6:
2756 gen_op_test_true(mask);
2757 break;
2759 } else {
2760 switch (bo & 0x6) {
2761 case 0:
2762 #if defined(TARGET_PPC64)
2763 if (ctx->sf_mode)
2764 gen_op_test_ctr_false_64(mask);
2765 else
2766 #endif
2767 gen_op_test_ctr_false(mask);
2768 break;
2769 case 2:
2770 #if defined(TARGET_PPC64)
2771 if (ctx->sf_mode)
2772 gen_op_test_ctrz_false_64(mask);
2773 else
2774 #endif
2775 gen_op_test_ctrz_false(mask);
2776 break;
2777 default:
2778 case 4:
2779 case 6:
2780 gen_op_test_false(mask);
2781 break;
2785 if (type == BCOND_IM) {
2786 int l1 = gen_new_label();
2787 gen_op_jz_T0(l1);
2788 gen_goto_tb(ctx, 0, target);
2789 gen_set_label(l1);
2790 gen_goto_tb(ctx, 1, ctx->nip);
2791 } else {
2792 #if defined(TARGET_PPC64)
2793 if (ctx->sf_mode)
2794 gen_op_btest_T1_64(ctx->nip >> 32, ctx->nip);
2795 else
2796 #endif
2797 gen_op_btest_T1(ctx->nip);
2798 gen_op_reset_T0();
2800 no_test:
2801 if (ctx->singlestep_enabled)
2802 gen_op_debug();
2803 gen_op_exit_tb();
2804 ctx->exception = EXCP_BRANCH;
2807 GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
2809 gen_bcond(ctx, BCOND_IM);
2812 GEN_HANDLER(bcctr, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW)
2814 gen_bcond(ctx, BCOND_CTR);
2817 GEN_HANDLER(bclr, 0x13, 0x10, 0x00, 0x00000000, PPC_FLOW)
2819 gen_bcond(ctx, BCOND_LR);
2822 /*** Condition register logical ***/
2823 #define GEN_CRLOGIC(op, opc) \
2824 GEN_HANDLER(cr##op, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER) \
2826 gen_op_load_crf_T0(crbA(ctx->opcode) >> 2); \
2827 gen_op_getbit_T0(3 - (crbA(ctx->opcode) & 0x03)); \
2828 gen_op_load_crf_T1(crbB(ctx->opcode) >> 2); \
2829 gen_op_getbit_T1(3 - (crbB(ctx->opcode) & 0x03)); \
2830 gen_op_##op(); \
2831 gen_op_load_crf_T1(crbD(ctx->opcode) >> 2); \
2832 gen_op_setcrfbit(~(1 << (3 - (crbD(ctx->opcode) & 0x03))), \
2833 3 - (crbD(ctx->opcode) & 0x03)); \
2834 gen_op_store_T1_crf(crbD(ctx->opcode) >> 2); \
2837 /* crand */
2838 GEN_CRLOGIC(and, 0x08);
2839 /* crandc */
2840 GEN_CRLOGIC(andc, 0x04);
2841 /* creqv */
2842 GEN_CRLOGIC(eqv, 0x09);
2843 /* crnand */
2844 GEN_CRLOGIC(nand, 0x07);
2845 /* crnor */
2846 GEN_CRLOGIC(nor, 0x01);
2847 /* cror */
2848 GEN_CRLOGIC(or, 0x0E);
2849 /* crorc */
2850 GEN_CRLOGIC(orc, 0x0D);
2851 /* crxor */
2852 GEN_CRLOGIC(xor, 0x06);
2853 /* mcrf */
2854 GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER)
2856 gen_op_load_crf_T0(crfS(ctx->opcode));
2857 gen_op_store_T0_crf(crfD(ctx->opcode));
2860 /*** System linkage ***/
2861 /* rfi (supervisor only) */
2862 GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW)
2864 #if defined(CONFIG_USER_ONLY)
2865 RET_PRIVOPC(ctx);
2866 #else
2867 /* Restore CPU state */
2868 if (unlikely(!ctx->supervisor)) {
2869 RET_PRIVOPC(ctx);
2870 return;
2872 gen_op_rfi();
2873 RET_CHG_FLOW(ctx);
2874 #endif
2877 #if defined(TARGET_PPC64)
2878 GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_FLOW)
2880 #if defined(CONFIG_USER_ONLY)
2881 RET_PRIVOPC(ctx);
2882 #else
2883 /* Restore CPU state */
2884 if (unlikely(!ctx->supervisor)) {
2885 RET_PRIVOPC(ctx);
2886 return;
2888 gen_op_rfid();
2889 RET_CHG_FLOW(ctx);
2890 #endif
2892 #endif
2894 /* sc */
2895 GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFFFFD, PPC_FLOW)
2897 #if defined(CONFIG_USER_ONLY)
2898 RET_EXCP(ctx, EXCP_SYSCALL_USER, 0);
2899 #else
2900 RET_EXCP(ctx, EXCP_SYSCALL, 0);
2901 #endif
2904 /*** Trap ***/
2905 /* tw */
2906 GEN_HANDLER(tw, 0x1F, 0x04, 0x00, 0x00000001, PPC_FLOW)
2908 gen_op_load_gpr_T0(rA(ctx->opcode));
2909 gen_op_load_gpr_T1(rB(ctx->opcode));
2910 /* Update the nip since this might generate a trap exception */
2911 gen_update_nip(ctx, ctx->nip);
2912 gen_op_tw(TO(ctx->opcode));
2915 /* twi */
2916 GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
2918 gen_op_load_gpr_T0(rA(ctx->opcode));
2919 gen_set_T1(SIMM(ctx->opcode));
2920 /* Update the nip since this might generate a trap exception */
2921 gen_update_nip(ctx, ctx->nip);
2922 gen_op_tw(TO(ctx->opcode));
2925 #if defined(TARGET_PPC64)
2926 /* td */
2927 GEN_HANDLER(td, 0x1F, 0x04, 0x02, 0x00000001, PPC_64B)
2929 gen_op_load_gpr_T0(rA(ctx->opcode));
2930 gen_op_load_gpr_T1(rB(ctx->opcode));
2931 /* Update the nip since this might generate a trap exception */
2932 gen_update_nip(ctx, ctx->nip);
2933 gen_op_td(TO(ctx->opcode));
2936 /* tdi */
2937 GEN_HANDLER(tdi, 0x02, 0xFF, 0xFF, 0x00000000, PPC_64B)
2939 gen_op_load_gpr_T0(rA(ctx->opcode));
2940 gen_set_T1(SIMM(ctx->opcode));
2941 /* Update the nip since this might generate a trap exception */
2942 gen_update_nip(ctx, ctx->nip);
2943 gen_op_td(TO(ctx->opcode));
2945 #endif
2947 /*** Processor control ***/
2948 /* mcrxr */
2949 GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC)
2951 gen_op_load_xer_cr();
2952 gen_op_store_T0_crf(crfD(ctx->opcode));
2953 gen_op_clear_xer_ov();
2954 gen_op_clear_xer_ca();
2957 /* mfcr */
2958 GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x00000801, PPC_MISC)
2960 uint32_t crm, crn;
2962 if (likely(ctx->opcode & 0x00100000)) {
2963 crm = CRM(ctx->opcode);
2964 if (likely((crm ^ (crm - 1)) == 0)) {
2965 crn = ffs(crm);
2966 gen_op_load_cro(7 - crn);
2968 } else {
2969 gen_op_load_cr();
2971 gen_op_store_T0_gpr(rD(ctx->opcode));
2974 /* mfmsr */
2975 GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC)
2977 #if defined(CONFIG_USER_ONLY)
2978 RET_PRIVREG(ctx);
2979 #else
2980 if (unlikely(!ctx->supervisor)) {
2981 RET_PRIVREG(ctx);
2982 return;
2984 gen_op_load_msr();
2985 gen_op_store_T0_gpr(rD(ctx->opcode));
2986 #endif
2989 #if 0
2990 #define SPR_NOACCESS ((void *)(-1))
2991 #else
2992 static void spr_noaccess (void *opaque, int sprn)
2994 sprn = ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
2995 printf("ERROR: try to access SPR %d !\n", sprn);
2997 #define SPR_NOACCESS (&spr_noaccess)
2998 #endif
3000 /* mfspr */
3001 static inline void gen_op_mfspr (DisasContext *ctx)
3003 void (*read_cb)(void *opaque, int sprn);
3004 uint32_t sprn = SPR(ctx->opcode);
3006 #if !defined(CONFIG_USER_ONLY)
3007 if (ctx->supervisor)
3008 read_cb = ctx->spr_cb[sprn].oea_read;
3009 else
3010 #endif
3011 read_cb = ctx->spr_cb[sprn].uea_read;
3012 if (likely(read_cb != NULL)) {
3013 if (likely(read_cb != SPR_NOACCESS)) {
3014 (*read_cb)(ctx, sprn);
3015 gen_op_store_T0_gpr(rD(ctx->opcode));
3016 } else {
3017 /* Privilege exception */
3018 if (loglevel) {
3019 fprintf(logfile, "Trying to read priviledged spr %d %03x\n",
3020 sprn, sprn);
3022 printf("Trying to read priviledged spr %d %03x\n", sprn, sprn);
3023 RET_PRIVREG(ctx);
3025 } else {
3026 /* Not defined */
3027 if (loglevel) {
3028 fprintf(logfile, "Trying to read invalid spr %d %03x\n",
3029 sprn, sprn);
3031 printf("Trying to read invalid spr %d %03x\n", sprn, sprn);
3032 RET_EXCP(ctx, EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_SPR);
3036 GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC)
3038 gen_op_mfspr(ctx);
3041 /* mftb */
3042 GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_TB)
3044 gen_op_mfspr(ctx);
3047 /* mtcrf */
3048 GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC)
3050 uint32_t crm, crn;
3052 gen_op_load_gpr_T0(rS(ctx->opcode));
3053 crm = CRM(ctx->opcode);
3054 if (likely((ctx->opcode & 0x00100000) || (crm ^ (crm - 1)) == 0)) {
3055 crn = ffs(crm);
3056 gen_op_srli_T0(crn * 4);
3057 gen_op_andi_T0(0xF);
3058 gen_op_store_cro(7 - crn);
3059 } else {
3060 gen_op_store_cr(crm);
3064 /* mtmsr */
3065 #if defined(TARGET_PPC64)
3066 GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001FF801, PPC_MISC)
3068 #if defined(CONFIG_USER_ONLY)
3069 RET_PRIVREG(ctx);
3070 #else
3071 if (unlikely(!ctx->supervisor)) {
3072 RET_PRIVREG(ctx);
3073 return;
3075 gen_update_nip(ctx, ctx->nip);
3076 gen_op_load_gpr_T0(rS(ctx->opcode));
3077 gen_op_store_msr();
3078 /* Must stop the translation as machine state (may have) changed */
3079 RET_CHG_FLOW(ctx);
3080 #endif
3082 #endif
3084 GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC)
3086 #if defined(CONFIG_USER_ONLY)
3087 RET_PRIVREG(ctx);
3088 #else
3089 if (unlikely(!ctx->supervisor)) {
3090 RET_PRIVREG(ctx);
3091 return;
3093 gen_update_nip(ctx, ctx->nip);
3094 gen_op_load_gpr_T0(rS(ctx->opcode));
3095 #if defined(TARGET_PPC64)
3096 if (!ctx->sf_mode)
3097 gen_op_store_msr_32();
3098 else
3099 #endif
3100 gen_op_store_msr();
3101 /* Must stop the translation as machine state (may have) changed */
3102 RET_CHG_FLOW(ctx);
3103 #endif
3106 /* mtspr */
3107 GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC)
3109 void (*write_cb)(void *opaque, int sprn);
3110 uint32_t sprn = SPR(ctx->opcode);
3112 #if !defined(CONFIG_USER_ONLY)
3113 if (ctx->supervisor)
3114 write_cb = ctx->spr_cb[sprn].oea_write;
3115 else
3116 #endif
3117 write_cb = ctx->spr_cb[sprn].uea_write;
3118 if (likely(write_cb != NULL)) {
3119 if (likely(write_cb != SPR_NOACCESS)) {
3120 gen_op_load_gpr_T0(rS(ctx->opcode));
3121 (*write_cb)(ctx, sprn);
3122 } else {
3123 /* Privilege exception */
3124 if (loglevel) {
3125 fprintf(logfile, "Trying to write priviledged spr %d %03x\n",
3126 sprn, sprn);
3128 printf("Trying to write priviledged spr %d %03x\n", sprn, sprn);
3129 RET_PRIVREG(ctx);
3131 } else {
3132 /* Not defined */
3133 if (loglevel) {
3134 fprintf(logfile, "Trying to write invalid spr %d %03x\n",
3135 sprn, sprn);
3137 printf("Trying to write invalid spr %d %03x\n", sprn, sprn);
3138 RET_EXCP(ctx, EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_SPR);
3142 /*** Cache management ***/
3143 /* For now, all those will be implemented as nop:
3144 * this is valid, regarding the PowerPC specs...
3145 * We just have to flush tb while invalidating instruction cache lines...
3147 /* dcbf */
3148 GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03E00001, PPC_CACHE)
3150 gen_addr_reg_index(ctx);
3151 op_ldst(lbz);
3154 /* dcbi (Supervisor only) */
3155 GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE)
3157 #if defined(CONFIG_USER_ONLY)
3158 RET_PRIVOPC(ctx);
3159 #else
3160 if (unlikely(!ctx->supervisor)) {
3161 RET_PRIVOPC(ctx);
3162 return;
3164 gen_addr_reg_index(ctx);
3165 /* XXX: specification says this should be treated as a store by the MMU */
3166 //op_ldst(lbz);
3167 op_ldst(stb);
3168 #endif
3171 /* dcdst */
3172 GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE)
3174 /* XXX: specification say this is treated as a load by the MMU */
3175 gen_addr_reg_index(ctx);
3176 op_ldst(lbz);
3179 /* dcbt */
3180 GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x03E00001, PPC_CACHE)
3182 /* XXX: specification say this is treated as a load by the MMU
3183 * but does not generate any exception
3187 /* dcbtst */
3188 GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x03E00001, PPC_CACHE)
3190 /* XXX: specification say this is treated as a load by the MMU
3191 * but does not generate any exception
3195 /* dcbz */
3196 #define op_dcbz() (*gen_op_dcbz[ctx->mem_idx])()
3197 #if defined(TARGET_PPC64)
3198 #if defined(CONFIG_USER_ONLY)
3199 static GenOpFunc *gen_op_dcbz[] = {
3200 &gen_op_dcbz_raw,
3201 &gen_op_dcbz_raw,
3202 &gen_op_dcbz_64_raw,
3203 &gen_op_dcbz_64_raw,
3205 #else
3206 static GenOpFunc *gen_op_dcbz[] = {
3207 &gen_op_dcbz_user,
3208 &gen_op_dcbz_user,
3209 &gen_op_dcbz_kernel,
3210 &gen_op_dcbz_kernel,
3211 &gen_op_dcbz_64_user,
3212 &gen_op_dcbz_64_user,
3213 &gen_op_dcbz_64_kernel,
3214 &gen_op_dcbz_64_kernel,
3216 #endif
3217 #else
3218 #if defined(CONFIG_USER_ONLY)
3219 static GenOpFunc *gen_op_dcbz[] = {
3220 &gen_op_dcbz_raw,
3221 &gen_op_dcbz_raw,
3223 #else
3224 static GenOpFunc *gen_op_dcbz[] = {
3225 &gen_op_dcbz_user,
3226 &gen_op_dcbz_user,
3227 &gen_op_dcbz_kernel,
3228 &gen_op_dcbz_kernel,
3230 #endif
3231 #endif
3233 GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03E00001, PPC_CACHE)
3235 gen_addr_reg_index(ctx);
3236 op_dcbz();
3237 gen_op_check_reservation();
3240 /* icbi */
3241 #define op_icbi() (*gen_op_icbi[ctx->mem_idx])()
3242 #if defined(TARGET_PPC64)
3243 #if defined(CONFIG_USER_ONLY)
3244 static GenOpFunc *gen_op_icbi[] = {
3245 &gen_op_icbi_raw,
3246 &gen_op_icbi_raw,
3247 &gen_op_icbi_64_raw,
3248 &gen_op_icbi_64_raw,
3250 #else
3251 static GenOpFunc *gen_op_icbi[] = {
3252 &gen_op_icbi_user,
3253 &gen_op_icbi_user,
3254 &gen_op_icbi_kernel,
3255 &gen_op_icbi_kernel,
3256 &gen_op_icbi_64_user,
3257 &gen_op_icbi_64_user,
3258 &gen_op_icbi_64_kernel,
3259 &gen_op_icbi_64_kernel,
3261 #endif
3262 #else
3263 #if defined(CONFIG_USER_ONLY)
3264 static GenOpFunc *gen_op_icbi[] = {
3265 &gen_op_icbi_raw,
3266 &gen_op_icbi_raw,
3268 #else
3269 static GenOpFunc *gen_op_icbi[] = {
3270 &gen_op_icbi_user,
3271 &gen_op_icbi_user,
3272 &gen_op_icbi_kernel,
3273 &gen_op_icbi_kernel,
3275 #endif
3276 #endif
3277 GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE)
3279 /* NIP cannot be restored if the memory exception comes from an helper */
3280 gen_update_nip(ctx, ctx->nip - 4);
3281 gen_addr_reg_index(ctx);
3282 op_icbi();
3283 RET_STOP(ctx);
3286 /* Optional: */
3287 /* dcba */
3288 GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_OPT)
3292 /*** Segment register manipulation ***/
3293 /* Supervisor only: */
3294 /* mfsr */
3295 GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT)
3297 #if defined(CONFIG_USER_ONLY)
3298 RET_PRIVREG(ctx);
3299 #else
3300 if (unlikely(!ctx->supervisor)) {
3301 RET_PRIVREG(ctx);
3302 return;
3304 gen_op_set_T1(SR(ctx->opcode));
3305 gen_op_load_sr();
3306 gen_op_store_T0_gpr(rD(ctx->opcode));
3307 #endif
3310 /* mfsrin */
3311 GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT)
3313 #if defined(CONFIG_USER_ONLY)
3314 RET_PRIVREG(ctx);
3315 #else
3316 if (unlikely(!ctx->supervisor)) {
3317 RET_PRIVREG(ctx);
3318 return;
3320 gen_op_load_gpr_T1(rB(ctx->opcode));
3321 gen_op_srli_T1(28);
3322 gen_op_load_sr();
3323 gen_op_store_T0_gpr(rD(ctx->opcode));
3324 #endif
3327 /* mtsr */
3328 GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT)
3330 #if defined(CONFIG_USER_ONLY)
3331 RET_PRIVREG(ctx);
3332 #else
3333 if (unlikely(!ctx->supervisor)) {
3334 RET_PRIVREG(ctx);
3335 return;
3337 gen_op_load_gpr_T0(rS(ctx->opcode));
3338 gen_op_set_T1(SR(ctx->opcode));
3339 gen_op_store_sr();
3340 RET_STOP(ctx);
3341 #endif
3344 /* mtsrin */
3345 GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT)
3347 #if defined(CONFIG_USER_ONLY)
3348 RET_PRIVREG(ctx);
3349 #else
3350 if (unlikely(!ctx->supervisor)) {
3351 RET_PRIVREG(ctx);
3352 return;
3354 gen_op_load_gpr_T0(rS(ctx->opcode));
3355 gen_op_load_gpr_T1(rB(ctx->opcode));
3356 gen_op_srli_T1(28);
3357 gen_op_store_sr();
3358 RET_STOP(ctx);
3359 #endif
3362 /*** Lookaside buffer management ***/
3363 /* Optional & supervisor only: */
3364 /* tlbia */
3365 GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA)
3367 #if defined(CONFIG_USER_ONLY)
3368 RET_PRIVOPC(ctx);
3369 #else
3370 if (unlikely(!ctx->supervisor)) {
3371 if (loglevel)
3372 fprintf(logfile, "%s: ! supervisor\n", __func__);
3373 RET_PRIVOPC(ctx);
3374 return;
3376 gen_op_tlbia();
3377 RET_STOP(ctx);
3378 #endif
3381 /* tlbie */
3382 GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM_TLBIE)
3384 #if defined(CONFIG_USER_ONLY)
3385 RET_PRIVOPC(ctx);
3386 #else
3387 if (unlikely(!ctx->supervisor)) {
3388 RET_PRIVOPC(ctx);
3389 return;
3391 gen_op_load_gpr_T0(rB(ctx->opcode));
3392 #if defined(TARGET_PPC64)
3393 if (ctx->sf_mode)
3394 gen_op_tlbie_64();
3395 else
3396 #endif
3397 gen_op_tlbie();
3398 RET_STOP(ctx);
3399 #endif
3402 /* tlbsync */
3403 GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC)
3405 #if defined(CONFIG_USER_ONLY)
3406 RET_PRIVOPC(ctx);
3407 #else
3408 if (unlikely(!ctx->supervisor)) {
3409 RET_PRIVOPC(ctx);
3410 return;
3412 /* This has no effect: it should ensure that all previous
3413 * tlbie have completed
3415 RET_STOP(ctx);
3416 #endif
3419 #if defined(TARGET_PPC64)
3420 /* slbia */
3421 GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x03FFFC01, PPC_SLBI)
3423 #if defined(CONFIG_USER_ONLY)
3424 RET_PRIVOPC(ctx);
3425 #else
3426 if (unlikely(!ctx->supervisor)) {
3427 if (loglevel)
3428 fprintf(logfile, "%s: ! supervisor\n", __func__);
3429 RET_PRIVOPC(ctx);
3430 return;
3432 gen_op_slbia();
3433 RET_STOP(ctx);
3434 #endif
3437 /* slbie */
3438 GEN_HANDLER(slbie, 0x1F, 0x12, 0x0D, 0x03FF0001, PPC_SLBI)
3440 #if defined(CONFIG_USER_ONLY)
3441 RET_PRIVOPC(ctx);
3442 #else
3443 if (unlikely(!ctx->supervisor)) {
3444 RET_PRIVOPC(ctx);
3445 return;
3447 gen_op_load_gpr_T0(rB(ctx->opcode));
3448 gen_op_slbie();
3449 RET_STOP(ctx);
3450 #endif
3452 #endif
3454 /*** External control ***/
3455 /* Optional: */
3456 #define op_eciwx() (*gen_op_eciwx[ctx->mem_idx])()
3457 #define op_ecowx() (*gen_op_ecowx[ctx->mem_idx])()
3458 #if defined(TARGET_PPC64)
3459 #if defined(CONFIG_USER_ONLY)
3460 static GenOpFunc *gen_op_eciwx[] = {
3461 &gen_op_eciwx_raw,
3462 &gen_op_eciwx_le_raw,
3463 &gen_op_eciwx_64_raw,
3464 &gen_op_eciwx_le_64_raw,
3466 static GenOpFunc *gen_op_ecowx[] = {
3467 &gen_op_ecowx_raw,
3468 &gen_op_ecowx_le_raw,
3469 &gen_op_ecowx_64_raw,
3470 &gen_op_ecowx_le_64_raw,
3472 #else
3473 static GenOpFunc *gen_op_eciwx[] = {
3474 &gen_op_eciwx_user,
3475 &gen_op_eciwx_le_user,
3476 &gen_op_eciwx_kernel,
3477 &gen_op_eciwx_le_kernel,
3478 &gen_op_eciwx_64_user,
3479 &gen_op_eciwx_le_64_user,
3480 &gen_op_eciwx_64_kernel,
3481 &gen_op_eciwx_le_64_kernel,
3483 static GenOpFunc *gen_op_ecowx[] = {
3484 &gen_op_ecowx_user,
3485 &gen_op_ecowx_le_user,
3486 &gen_op_ecowx_kernel,
3487 &gen_op_ecowx_le_kernel,
3488 &gen_op_ecowx_64_user,
3489 &gen_op_ecowx_le_64_user,
3490 &gen_op_ecowx_64_kernel,
3491 &gen_op_ecowx_le_64_kernel,
3493 #endif
3494 #else
3495 #if defined(CONFIG_USER_ONLY)
3496 static GenOpFunc *gen_op_eciwx[] = {
3497 &gen_op_eciwx_raw,
3498 &gen_op_eciwx_le_raw,
3500 static GenOpFunc *gen_op_ecowx[] = {
3501 &gen_op_ecowx_raw,
3502 &gen_op_ecowx_le_raw,
3504 #else
3505 static GenOpFunc *gen_op_eciwx[] = {
3506 &gen_op_eciwx_user,
3507 &gen_op_eciwx_le_user,
3508 &gen_op_eciwx_kernel,
3509 &gen_op_eciwx_le_kernel,
3511 static GenOpFunc *gen_op_ecowx[] = {
3512 &gen_op_ecowx_user,
3513 &gen_op_ecowx_le_user,
3514 &gen_op_ecowx_kernel,
3515 &gen_op_ecowx_le_kernel,
3517 #endif
3518 #endif
3520 /* eciwx */
3521 GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN)
3523 /* Should check EAR[E] & alignment ! */
3524 gen_addr_reg_index(ctx);
3525 op_eciwx();
3526 gen_op_store_T0_gpr(rD(ctx->opcode));
3529 /* ecowx */
3530 GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN)
3532 /* Should check EAR[E] & alignment ! */
3533 gen_addr_reg_index(ctx);
3534 gen_op_load_gpr_T1(rS(ctx->opcode));
3535 op_ecowx();
3538 /* PowerPC 601 specific instructions */
3539 /* abs - abs. */
3540 GEN_HANDLER(abs, 0x1F, 0x08, 0x0B, 0x0000F800, PPC_POWER_BR)
3542 gen_op_load_gpr_T0(rA(ctx->opcode));
3543 gen_op_POWER_abs();
3544 gen_op_store_T0_gpr(rD(ctx->opcode));
3545 if (unlikely(Rc(ctx->opcode) != 0))
3546 gen_set_Rc0(ctx);
3549 /* abso - abso. */
3550 GEN_HANDLER(abso, 0x1F, 0x08, 0x1B, 0x0000F800, PPC_POWER_BR)
3552 gen_op_load_gpr_T0(rA(ctx->opcode));
3553 gen_op_POWER_abso();
3554 gen_op_store_T0_gpr(rD(ctx->opcode));
3555 if (unlikely(Rc(ctx->opcode) != 0))
3556 gen_set_Rc0(ctx);
3559 /* clcs */
3560 GEN_HANDLER(clcs, 0x1F, 0x10, 0x13, 0x0000F800, PPC_POWER_BR) /* 601 ? */
3562 gen_op_load_gpr_T0(rA(ctx->opcode));
3563 gen_op_POWER_clcs();
3564 gen_op_store_T0_gpr(rD(ctx->opcode));
3567 /* div - div. */
3568 GEN_HANDLER(div, 0x1F, 0x0B, 0x0A, 0x00000000, PPC_POWER_BR)
3570 gen_op_load_gpr_T0(rA(ctx->opcode));
3571 gen_op_load_gpr_T1(rB(ctx->opcode));
3572 gen_op_POWER_div();
3573 gen_op_store_T0_gpr(rD(ctx->opcode));
3574 if (unlikely(Rc(ctx->opcode) != 0))
3575 gen_set_Rc0(ctx);
3578 /* divo - divo. */
3579 GEN_HANDLER(divo, 0x1F, 0x0B, 0x1A, 0x00000000, PPC_POWER_BR)
3581 gen_op_load_gpr_T0(rA(ctx->opcode));
3582 gen_op_load_gpr_T1(rB(ctx->opcode));
3583 gen_op_POWER_divo();
3584 gen_op_store_T0_gpr(rD(ctx->opcode));
3585 if (unlikely(Rc(ctx->opcode) != 0))
3586 gen_set_Rc0(ctx);
3589 /* divs - divs. */
3590 GEN_HANDLER(divs, 0x1F, 0x0B, 0x0B, 0x00000000, PPC_POWER_BR)
3592 gen_op_load_gpr_T0(rA(ctx->opcode));
3593 gen_op_load_gpr_T1(rB(ctx->opcode));
3594 gen_op_POWER_divs();
3595 gen_op_store_T0_gpr(rD(ctx->opcode));
3596 if (unlikely(Rc(ctx->opcode) != 0))
3597 gen_set_Rc0(ctx);
3600 /* divso - divso. */
3601 GEN_HANDLER(divso, 0x1F, 0x0B, 0x1B, 0x00000000, PPC_POWER_BR)
3603 gen_op_load_gpr_T0(rA(ctx->opcode));
3604 gen_op_load_gpr_T1(rB(ctx->opcode));
3605 gen_op_POWER_divso();
3606 gen_op_store_T0_gpr(rD(ctx->opcode));
3607 if (unlikely(Rc(ctx->opcode) != 0))
3608 gen_set_Rc0(ctx);
3611 /* doz - doz. */
3612 GEN_HANDLER(doz, 0x1F, 0x08, 0x08, 0x00000000, PPC_POWER_BR)
3614 gen_op_load_gpr_T0(rA(ctx->opcode));
3615 gen_op_load_gpr_T1(rB(ctx->opcode));
3616 gen_op_POWER_doz();
3617 gen_op_store_T0_gpr(rD(ctx->opcode));
3618 if (unlikely(Rc(ctx->opcode) != 0))
3619 gen_set_Rc0(ctx);
3622 /* dozo - dozo. */
3623 GEN_HANDLER(dozo, 0x1F, 0x08, 0x18, 0x00000000, PPC_POWER_BR)
3625 gen_op_load_gpr_T0(rA(ctx->opcode));
3626 gen_op_load_gpr_T1(rB(ctx->opcode));
3627 gen_op_POWER_dozo();
3628 gen_op_store_T0_gpr(rD(ctx->opcode));
3629 if (unlikely(Rc(ctx->opcode) != 0))
3630 gen_set_Rc0(ctx);
3633 /* dozi */
3634 GEN_HANDLER(dozi, 0x09, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR)
3636 gen_op_load_gpr_T0(rA(ctx->opcode));
3637 gen_op_set_T1(SIMM(ctx->opcode));
3638 gen_op_POWER_doz();
3639 gen_op_store_T0_gpr(rD(ctx->opcode));
3642 /* As lscbx load from memory byte after byte, it's always endian safe */
3643 #define op_POWER_lscbx(start, ra, rb) \
3644 (*gen_op_POWER_lscbx[ctx->mem_idx])(start, ra, rb)
3645 #if defined(CONFIG_USER_ONLY)
3646 static GenOpFunc3 *gen_op_POWER_lscbx[] = {
3647 &gen_op_POWER_lscbx_raw,
3648 &gen_op_POWER_lscbx_raw,
3650 #else
3651 static GenOpFunc3 *gen_op_POWER_lscbx[] = {
3652 &gen_op_POWER_lscbx_user,
3653 &gen_op_POWER_lscbx_user,
3654 &gen_op_POWER_lscbx_kernel,
3655 &gen_op_POWER_lscbx_kernel,
3657 #endif
3659 /* lscbx - lscbx. */
3660 GEN_HANDLER(lscbx, 0x1F, 0x15, 0x08, 0x00000000, PPC_POWER_BR)
3662 int ra = rA(ctx->opcode);
3663 int rb = rB(ctx->opcode);
3665 gen_addr_reg_index(ctx);
3666 if (ra == 0) {
3667 ra = rb;
3669 /* NIP cannot be restored if the memory exception comes from an helper */
3670 gen_update_nip(ctx, ctx->nip - 4);
3671 gen_op_load_xer_bc();
3672 gen_op_load_xer_cmp();
3673 op_POWER_lscbx(rD(ctx->opcode), ra, rb);
3674 gen_op_store_xer_bc();
3675 if (unlikely(Rc(ctx->opcode) != 0))
3676 gen_set_Rc0(ctx);
3679 /* maskg - maskg. */
3680 GEN_HANDLER(maskg, 0x1F, 0x1D, 0x00, 0x00000000, PPC_POWER_BR)
3682 gen_op_load_gpr_T0(rS(ctx->opcode));
3683 gen_op_load_gpr_T1(rB(ctx->opcode));
3684 gen_op_POWER_maskg();
3685 gen_op_store_T0_gpr(rA(ctx->opcode));
3686 if (unlikely(Rc(ctx->opcode) != 0))
3687 gen_set_Rc0(ctx);
3690 /* maskir - maskir. */
3691 GEN_HANDLER(maskir, 0x1F, 0x1D, 0x10, 0x00000000, PPC_POWER_BR)
3693 gen_op_load_gpr_T0(rA(ctx->opcode));
3694 gen_op_load_gpr_T1(rS(ctx->opcode));
3695 gen_op_load_gpr_T2(rB(ctx->opcode));
3696 gen_op_POWER_maskir();
3697 gen_op_store_T0_gpr(rA(ctx->opcode));
3698 if (unlikely(Rc(ctx->opcode) != 0))
3699 gen_set_Rc0(ctx);
3702 /* mul - mul. */
3703 GEN_HANDLER(mul, 0x1F, 0x0B, 0x03, 0x00000000, PPC_POWER_BR)
3705 gen_op_load_gpr_T0(rA(ctx->opcode));
3706 gen_op_load_gpr_T1(rB(ctx->opcode));
3707 gen_op_POWER_mul();
3708 gen_op_store_T0_gpr(rD(ctx->opcode));
3709 if (unlikely(Rc(ctx->opcode) != 0))
3710 gen_set_Rc0(ctx);
3713 /* mulo - mulo. */
3714 GEN_HANDLER(mulo, 0x1F, 0x0B, 0x13, 0x00000000, PPC_POWER_BR)
3716 gen_op_load_gpr_T0(rA(ctx->opcode));
3717 gen_op_load_gpr_T1(rB(ctx->opcode));
3718 gen_op_POWER_mulo();
3719 gen_op_store_T0_gpr(rD(ctx->opcode));
3720 if (unlikely(Rc(ctx->opcode) != 0))
3721 gen_set_Rc0(ctx);
3724 /* nabs - nabs. */
3725 GEN_HANDLER(nabs, 0x1F, 0x08, 0x0F, 0x00000000, PPC_POWER_BR)
3727 gen_op_load_gpr_T0(rA(ctx->opcode));
3728 gen_op_POWER_nabs();
3729 gen_op_store_T0_gpr(rD(ctx->opcode));
3730 if (unlikely(Rc(ctx->opcode) != 0))
3731 gen_set_Rc0(ctx);
3734 /* nabso - nabso. */
3735 GEN_HANDLER(nabso, 0x1F, 0x08, 0x1F, 0x00000000, PPC_POWER_BR)
3737 gen_op_load_gpr_T0(rA(ctx->opcode));
3738 gen_op_POWER_nabso();
3739 gen_op_store_T0_gpr(rD(ctx->opcode));
3740 if (unlikely(Rc(ctx->opcode) != 0))
3741 gen_set_Rc0(ctx);
3744 /* rlmi - rlmi. */
3745 GEN_HANDLER(rlmi, 0x16, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR)
3747 uint32_t mb, me;
3749 mb = MB(ctx->opcode);
3750 me = ME(ctx->opcode);
3751 gen_op_load_gpr_T0(rS(ctx->opcode));
3752 gen_op_load_gpr_T1(rA(ctx->opcode));
3753 gen_op_load_gpr_T2(rB(ctx->opcode));
3754 gen_op_POWER_rlmi(MASK(mb, me), ~MASK(mb, me));
3755 gen_op_store_T0_gpr(rA(ctx->opcode));
3756 if (unlikely(Rc(ctx->opcode) != 0))
3757 gen_set_Rc0(ctx);
3760 /* rrib - rrib. */
3761 GEN_HANDLER(rrib, 0x1F, 0x19, 0x10, 0x00000000, PPC_POWER_BR)
3763 gen_op_load_gpr_T0(rS(ctx->opcode));
3764 gen_op_load_gpr_T1(rA(ctx->opcode));
3765 gen_op_load_gpr_T2(rB(ctx->opcode));
3766 gen_op_POWER_rrib();
3767 gen_op_store_T0_gpr(rA(ctx->opcode));
3768 if (unlikely(Rc(ctx->opcode) != 0))
3769 gen_set_Rc0(ctx);
3772 /* sle - sle. */
3773 GEN_HANDLER(sle, 0x1F, 0x19, 0x04, 0x00000000, PPC_POWER_BR)
3775 gen_op_load_gpr_T0(rS(ctx->opcode));
3776 gen_op_load_gpr_T1(rB(ctx->opcode));
3777 gen_op_POWER_sle();
3778 gen_op_store_T0_gpr(rA(ctx->opcode));
3779 if (unlikely(Rc(ctx->opcode) != 0))
3780 gen_set_Rc0(ctx);
3783 /* sleq - sleq. */
3784 GEN_HANDLER(sleq, 0x1F, 0x19, 0x06, 0x00000000, PPC_POWER_BR)
3786 gen_op_load_gpr_T0(rS(ctx->opcode));
3787 gen_op_load_gpr_T1(rB(ctx->opcode));
3788 gen_op_POWER_sleq();
3789 gen_op_store_T0_gpr(rA(ctx->opcode));
3790 if (unlikely(Rc(ctx->opcode) != 0))
3791 gen_set_Rc0(ctx);
3794 /* sliq - sliq. */
3795 GEN_HANDLER(sliq, 0x1F, 0x18, 0x05, 0x00000000, PPC_POWER_BR)
3797 gen_op_load_gpr_T0(rS(ctx->opcode));
3798 gen_op_set_T1(SH(ctx->opcode));
3799 gen_op_POWER_sle();
3800 gen_op_store_T0_gpr(rA(ctx->opcode));
3801 if (unlikely(Rc(ctx->opcode) != 0))
3802 gen_set_Rc0(ctx);
3805 /* slliq - slliq. */
3806 GEN_HANDLER(slliq, 0x1F, 0x18, 0x07, 0x00000000, PPC_POWER_BR)
3808 gen_op_load_gpr_T0(rS(ctx->opcode));
3809 gen_op_set_T1(SH(ctx->opcode));
3810 gen_op_POWER_sleq();
3811 gen_op_store_T0_gpr(rA(ctx->opcode));
3812 if (unlikely(Rc(ctx->opcode) != 0))
3813 gen_set_Rc0(ctx);
3816 /* sllq - sllq. */
3817 GEN_HANDLER(sllq, 0x1F, 0x18, 0x06, 0x00000000, PPC_POWER_BR)
3819 gen_op_load_gpr_T0(rS(ctx->opcode));
3820 gen_op_load_gpr_T1(rB(ctx->opcode));
3821 gen_op_POWER_sllq();
3822 gen_op_store_T0_gpr(rA(ctx->opcode));
3823 if (unlikely(Rc(ctx->opcode) != 0))
3824 gen_set_Rc0(ctx);
3827 /* slq - slq. */
3828 GEN_HANDLER(slq, 0x1F, 0x18, 0x04, 0x00000000, PPC_POWER_BR)
3830 gen_op_load_gpr_T0(rS(ctx->opcode));
3831 gen_op_load_gpr_T1(rB(ctx->opcode));
3832 gen_op_POWER_slq();
3833 gen_op_store_T0_gpr(rA(ctx->opcode));
3834 if (unlikely(Rc(ctx->opcode) != 0))
3835 gen_set_Rc0(ctx);
3838 /* sraiq - sraiq. */
3839 GEN_HANDLER(sraiq, 0x1F, 0x18, 0x1D, 0x00000000, PPC_POWER_BR)
3841 gen_op_load_gpr_T0(rS(ctx->opcode));
3842 gen_op_set_T1(SH(ctx->opcode));
3843 gen_op_POWER_sraq();
3844 gen_op_store_T0_gpr(rA(ctx->opcode));
3845 if (unlikely(Rc(ctx->opcode) != 0))
3846 gen_set_Rc0(ctx);
3849 /* sraq - sraq. */
3850 GEN_HANDLER(sraq, 0x1F, 0x18, 0x1C, 0x00000000, PPC_POWER_BR)
3852 gen_op_load_gpr_T0(rS(ctx->opcode));
3853 gen_op_load_gpr_T1(rB(ctx->opcode));
3854 gen_op_POWER_sraq();
3855 gen_op_store_T0_gpr(rA(ctx->opcode));
3856 if (unlikely(Rc(ctx->opcode) != 0))
3857 gen_set_Rc0(ctx);
3860 /* sre - sre. */
3861 GEN_HANDLER(sre, 0x1F, 0x19, 0x14, 0x00000000, PPC_POWER_BR)
3863 gen_op_load_gpr_T0(rS(ctx->opcode));
3864 gen_op_load_gpr_T1(rB(ctx->opcode));
3865 gen_op_POWER_sre();
3866 gen_op_store_T0_gpr(rA(ctx->opcode));
3867 if (unlikely(Rc(ctx->opcode) != 0))
3868 gen_set_Rc0(ctx);
3871 /* srea - srea. */
3872 GEN_HANDLER(srea, 0x1F, 0x19, 0x1C, 0x00000000, PPC_POWER_BR)
3874 gen_op_load_gpr_T0(rS(ctx->opcode));
3875 gen_op_load_gpr_T1(rB(ctx->opcode));
3876 gen_op_POWER_srea();
3877 gen_op_store_T0_gpr(rA(ctx->opcode));
3878 if (unlikely(Rc(ctx->opcode) != 0))
3879 gen_set_Rc0(ctx);
3882 /* sreq */
3883 GEN_HANDLER(sreq, 0x1F, 0x19, 0x16, 0x00000000, PPC_POWER_BR)
3885 gen_op_load_gpr_T0(rS(ctx->opcode));
3886 gen_op_load_gpr_T1(rB(ctx->opcode));
3887 gen_op_POWER_sreq();
3888 gen_op_store_T0_gpr(rA(ctx->opcode));
3889 if (unlikely(Rc(ctx->opcode) != 0))
3890 gen_set_Rc0(ctx);
3893 /* sriq */
3894 GEN_HANDLER(sriq, 0x1F, 0x18, 0x15, 0x00000000, PPC_POWER_BR)
3896 gen_op_load_gpr_T0(rS(ctx->opcode));
3897 gen_op_set_T1(SH(ctx->opcode));
3898 gen_op_POWER_srq();
3899 gen_op_store_T0_gpr(rA(ctx->opcode));
3900 if (unlikely(Rc(ctx->opcode) != 0))
3901 gen_set_Rc0(ctx);
3904 /* srliq */
3905 GEN_HANDLER(srliq, 0x1F, 0x18, 0x17, 0x00000000, PPC_POWER_BR)
3907 gen_op_load_gpr_T0(rS(ctx->opcode));
3908 gen_op_load_gpr_T1(rB(ctx->opcode));
3909 gen_op_set_T1(SH(ctx->opcode));
3910 gen_op_POWER_srlq();
3911 gen_op_store_T0_gpr(rA(ctx->opcode));
3912 if (unlikely(Rc(ctx->opcode) != 0))
3913 gen_set_Rc0(ctx);
3916 /* srlq */
3917 GEN_HANDLER(srlq, 0x1F, 0x18, 0x16, 0x00000000, PPC_POWER_BR)
3919 gen_op_load_gpr_T0(rS(ctx->opcode));
3920 gen_op_load_gpr_T1(rB(ctx->opcode));
3921 gen_op_POWER_srlq();
3922 gen_op_store_T0_gpr(rA(ctx->opcode));
3923 if (unlikely(Rc(ctx->opcode) != 0))
3924 gen_set_Rc0(ctx);
3927 /* srq */
3928 GEN_HANDLER(srq, 0x1F, 0x18, 0x14, 0x00000000, PPC_POWER_BR)
3930 gen_op_load_gpr_T0(rS(ctx->opcode));
3931 gen_op_load_gpr_T1(rB(ctx->opcode));
3932 gen_op_POWER_srq();
3933 gen_op_store_T0_gpr(rA(ctx->opcode));
3934 if (unlikely(Rc(ctx->opcode) != 0))
3935 gen_set_Rc0(ctx);
3938 /* PowerPC 602 specific instructions */
3939 /* dsa */
3940 GEN_HANDLER(dsa, 0x1F, 0x14, 0x13, 0x03FFF801, PPC_602_SPEC)
3942 /* XXX: TODO */
3943 RET_INVAL(ctx);
3946 /* esa */
3947 GEN_HANDLER(esa, 0x1F, 0x14, 0x12, 0x03FFF801, PPC_602_SPEC)
3949 /* XXX: TODO */
3950 RET_INVAL(ctx);
3953 /* mfrom */
3954 GEN_HANDLER(mfrom, 0x1F, 0x09, 0x08, 0x03E0F801, PPC_602_SPEC)
3956 #if defined(CONFIG_USER_ONLY)
3957 RET_PRIVOPC(ctx);
3958 #else
3959 if (unlikely(!ctx->supervisor)) {
3960 RET_PRIVOPC(ctx);
3961 return;
3963 gen_op_load_gpr_T0(rA(ctx->opcode));
3964 gen_op_602_mfrom();
3965 gen_op_store_T0_gpr(rD(ctx->opcode));
3966 #endif
3969 /* 602 - 603 - G2 TLB management */
3970 /* tlbld */
3971 GEN_HANDLER(tlbld, 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB)
3973 #if defined(CONFIG_USER_ONLY)
3974 RET_PRIVOPC(ctx);
3975 #else
3976 if (unlikely(!ctx->supervisor)) {
3977 RET_PRIVOPC(ctx);
3978 return;
3980 gen_op_load_gpr_T0(rB(ctx->opcode));
3981 gen_op_6xx_tlbld();
3982 RET_STOP(ctx);
3983 #endif
3986 /* tlbli */
3987 GEN_HANDLER(tlbli, 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB)
3989 #if defined(CONFIG_USER_ONLY)
3990 RET_PRIVOPC(ctx);
3991 #else
3992 if (unlikely(!ctx->supervisor)) {
3993 RET_PRIVOPC(ctx);
3994 return;
3996 gen_op_load_gpr_T0(rB(ctx->opcode));
3997 gen_op_6xx_tlbli();
3998 RET_STOP(ctx);
3999 #endif
4002 /* POWER instructions not in PowerPC 601 */
4003 /* clf */
4004 GEN_HANDLER(clf, 0x1F, 0x16, 0x03, 0x03E00000, PPC_POWER)
4006 /* Cache line flush: implemented as no-op */
4009 /* cli */
4010 GEN_HANDLER(cli, 0x1F, 0x16, 0x0F, 0x03E00000, PPC_POWER)
4012 /* Cache line invalidate: priviledged and treated as no-op */
4013 #if defined(CONFIG_USER_ONLY)
4014 RET_PRIVOPC(ctx);
4015 #else
4016 if (unlikely(!ctx->supervisor)) {
4017 RET_PRIVOPC(ctx);
4018 return;
4020 #endif
4023 /* dclst */
4024 GEN_HANDLER(dclst, 0x1F, 0x16, 0x13, 0x03E00000, PPC_POWER)
4026 /* Data cache line store: treated as no-op */
4029 GEN_HANDLER(mfsri, 0x1F, 0x13, 0x13, 0x00000001, PPC_POWER)
4031 #if defined(CONFIG_USER_ONLY)
4032 RET_PRIVOPC(ctx);
4033 #else
4034 if (unlikely(!ctx->supervisor)) {
4035 RET_PRIVOPC(ctx);
4036 return;
4038 int ra = rA(ctx->opcode);
4039 int rd = rD(ctx->opcode);
4041 gen_addr_reg_index(ctx);
4042 gen_op_POWER_mfsri();
4043 gen_op_store_T0_gpr(rd);
4044 if (ra != 0 && ra != rd)
4045 gen_op_store_T1_gpr(ra);
4046 #endif
4049 GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER)
4051 #if defined(CONFIG_USER_ONLY)
4052 RET_PRIVOPC(ctx);
4053 #else
4054 if (unlikely(!ctx->supervisor)) {
4055 RET_PRIVOPC(ctx);
4056 return;
4058 gen_addr_reg_index(ctx);
4059 gen_op_POWER_rac();
4060 gen_op_store_T0_gpr(rD(ctx->opcode));
4061 #endif
4064 GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02, 0x03FFF0001, PPC_POWER)
4066 #if defined(CONFIG_USER_ONLY)
4067 RET_PRIVOPC(ctx);
4068 #else
4069 if (unlikely(!ctx->supervisor)) {
4070 RET_PRIVOPC(ctx);
4071 return;
4073 gen_op_POWER_rfsvc();
4074 RET_CHG_FLOW(ctx);
4075 #endif
4078 /* svc is not implemented for now */
4080 /* POWER2 specific instructions */
4081 /* Quad manipulation (load/store two floats at a time) */
4082 #define op_POWER2_lfq() (*gen_op_POWER2_lfq[ctx->mem_idx])()
4083 #define op_POWER2_stfq() (*gen_op_POWER2_stfq[ctx->mem_idx])()
4084 #if defined(CONFIG_USER_ONLY)
4085 static GenOpFunc *gen_op_POWER2_lfq[] = {
4086 &gen_op_POWER2_lfq_le_raw,
4087 &gen_op_POWER2_lfq_raw,
4089 static GenOpFunc *gen_op_POWER2_stfq[] = {
4090 &gen_op_POWER2_stfq_le_raw,
4091 &gen_op_POWER2_stfq_raw,
4093 #else
4094 static GenOpFunc *gen_op_POWER2_lfq[] = {
4095 &gen_op_POWER2_lfq_le_user,
4096 &gen_op_POWER2_lfq_user,
4097 &gen_op_POWER2_lfq_le_kernel,
4098 &gen_op_POWER2_lfq_kernel,
4100 static GenOpFunc *gen_op_POWER2_stfq[] = {
4101 &gen_op_POWER2_stfq_le_user,
4102 &gen_op_POWER2_stfq_user,
4103 &gen_op_POWER2_stfq_le_kernel,
4104 &gen_op_POWER2_stfq_kernel,
4106 #endif
4108 /* lfq */
4109 GEN_HANDLER(lfq, 0x38, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
4111 /* NIP cannot be restored if the memory exception comes from an helper */
4112 gen_update_nip(ctx, ctx->nip - 4);
4113 gen_addr_imm_index(ctx, 0);
4114 op_POWER2_lfq();
4115 gen_op_store_FT0_fpr(rD(ctx->opcode));
4116 gen_op_store_FT1_fpr(rD(ctx->opcode) + 1);
4119 /* lfqu */
4120 GEN_HANDLER(lfqu, 0x39, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
4122 int ra = rA(ctx->opcode);
4124 /* NIP cannot be restored if the memory exception comes from an helper */
4125 gen_update_nip(ctx, ctx->nip - 4);
4126 gen_addr_imm_index(ctx, 0);
4127 op_POWER2_lfq();
4128 gen_op_store_FT0_fpr(rD(ctx->opcode));
4129 gen_op_store_FT1_fpr(rD(ctx->opcode) + 1);
4130 if (ra != 0)
4131 gen_op_store_T0_gpr(ra);
4134 /* lfqux */
4135 GEN_HANDLER(lfqux, 0x1F, 0x17, 0x19, 0x00000001, PPC_POWER2)
4137 int ra = rA(ctx->opcode);
4139 /* NIP cannot be restored if the memory exception comes from an helper */
4140 gen_update_nip(ctx, ctx->nip - 4);
4141 gen_addr_reg_index(ctx);
4142 op_POWER2_lfq();
4143 gen_op_store_FT0_fpr(rD(ctx->opcode));
4144 gen_op_store_FT1_fpr(rD(ctx->opcode) + 1);
4145 if (ra != 0)
4146 gen_op_store_T0_gpr(ra);
4149 /* lfqx */
4150 GEN_HANDLER(lfqx, 0x1F, 0x17, 0x18, 0x00000001, PPC_POWER2)
4152 /* NIP cannot be restored if the memory exception comes from an helper */
4153 gen_update_nip(ctx, ctx->nip - 4);
4154 gen_addr_reg_index(ctx);
4155 op_POWER2_lfq();
4156 gen_op_store_FT0_fpr(rD(ctx->opcode));
4157 gen_op_store_FT1_fpr(rD(ctx->opcode) + 1);
4160 /* stfq */
4161 GEN_HANDLER(stfq, 0x3C, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
4163 /* NIP cannot be restored if the memory exception comes from an helper */
4164 gen_update_nip(ctx, ctx->nip - 4);
4165 gen_addr_imm_index(ctx, 0);
4166 gen_op_load_fpr_FT0(rS(ctx->opcode));
4167 gen_op_load_fpr_FT1(rS(ctx->opcode) + 1);
4168 op_POWER2_stfq();
4171 /* stfqu */
4172 GEN_HANDLER(stfqu, 0x3D, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
4174 int ra = rA(ctx->opcode);
4176 /* NIP cannot be restored if the memory exception comes from an helper */
4177 gen_update_nip(ctx, ctx->nip - 4);
4178 gen_addr_imm_index(ctx, 0);
4179 gen_op_load_fpr_FT0(rS(ctx->opcode));
4180 gen_op_load_fpr_FT1(rS(ctx->opcode) + 1);
4181 op_POWER2_stfq();
4182 if (ra != 0)
4183 gen_op_store_T0_gpr(ra);
4186 /* stfqux */
4187 GEN_HANDLER(stfqux, 0x1F, 0x17, 0x1D, 0x00000001, PPC_POWER2)
4189 int ra = rA(ctx->opcode);
4191 /* NIP cannot be restored if the memory exception comes from an helper */
4192 gen_update_nip(ctx, ctx->nip - 4);
4193 gen_addr_reg_index(ctx);
4194 gen_op_load_fpr_FT0(rS(ctx->opcode));
4195 gen_op_load_fpr_FT1(rS(ctx->opcode) + 1);
4196 op_POWER2_stfq();
4197 if (ra != 0)
4198 gen_op_store_T0_gpr(ra);
4201 /* stfqx */
4202 GEN_HANDLER(stfqx, 0x1F, 0x17, 0x1C, 0x00000001, PPC_POWER2)
4204 /* NIP cannot be restored if the memory exception comes from an helper */
4205 gen_update_nip(ctx, ctx->nip - 4);
4206 gen_addr_reg_index(ctx);
4207 gen_op_load_fpr_FT0(rS(ctx->opcode));
4208 gen_op_load_fpr_FT1(rS(ctx->opcode) + 1);
4209 op_POWER2_stfq();
4212 /* BookE specific instructions */
4213 GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_BOOKE)
4215 /* XXX: TODO */
4216 RET_INVAL(ctx);
4219 GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_BOOKE)
4221 #if defined(CONFIG_USER_ONLY)
4222 RET_PRIVOPC(ctx);
4223 #else
4224 if (unlikely(!ctx->supervisor)) {
4225 RET_PRIVOPC(ctx);
4226 return;
4228 gen_addr_reg_index(ctx);
4229 /* Use the same micro-ops as for tlbie */
4230 #if defined(TARGET_PPC64)
4231 if (ctx->sf_mode)
4232 gen_op_tlbie_64();
4233 else
4234 #endif
4235 gen_op_tlbie();
4236 RET_STOP(ctx);
4237 #endif
4240 /* All 405 MAC instructions are translated here */
4241 static inline void gen_405_mulladd_insn (DisasContext *ctx, int opc2, int opc3,
4242 int ra, int rb, int rt, int Rc)
4244 gen_op_load_gpr_T0(ra);
4245 gen_op_load_gpr_T1(rb);
4246 switch (opc3 & 0x0D) {
4247 case 0x05:
4248 /* macchw - macchw. - macchwo - macchwo. */
4249 /* macchws - macchws. - macchwso - macchwso. */
4250 /* nmacchw - nmacchw. - nmacchwo - nmacchwo. */
4251 /* nmacchws - nmacchws. - nmacchwso - nmacchwso. */
4252 /* mulchw - mulchw. */
4253 gen_op_405_mulchw();
4254 break;
4255 case 0x04:
4256 /* macchwu - macchwu. - macchwuo - macchwuo. */
4257 /* macchwsu - macchwsu. - macchwsuo - macchwsuo. */
4258 /* mulchwu - mulchwu. */
4259 gen_op_405_mulchwu();
4260 break;
4261 case 0x01:
4262 /* machhw - machhw. - machhwo - machhwo. */
4263 /* machhws - machhws. - machhwso - machhwso. */
4264 /* nmachhw - nmachhw. - nmachhwo - nmachhwo. */
4265 /* nmachhws - nmachhws. - nmachhwso - nmachhwso. */
4266 /* mulhhw - mulhhw. */
4267 gen_op_405_mulhhw();
4268 break;
4269 case 0x00:
4270 /* machhwu - machhwu. - machhwuo - machhwuo. */
4271 /* machhwsu - machhwsu. - machhwsuo - machhwsuo. */
4272 /* mulhhwu - mulhhwu. */
4273 gen_op_405_mulhhwu();
4274 break;
4275 case 0x0D:
4276 /* maclhw - maclhw. - maclhwo - maclhwo. */
4277 /* maclhws - maclhws. - maclhwso - maclhwso. */
4278 /* nmaclhw - nmaclhw. - nmaclhwo - nmaclhwo. */
4279 /* nmaclhws - nmaclhws. - nmaclhwso - nmaclhwso. */
4280 /* mullhw - mullhw. */
4281 gen_op_405_mullhw();
4282 break;
4283 case 0x0C:
4284 /* maclhwu - maclhwu. - maclhwuo - maclhwuo. */
4285 /* maclhwsu - maclhwsu. - maclhwsuo - maclhwsuo. */
4286 /* mullhwu - mullhwu. */
4287 gen_op_405_mullhwu();
4288 break;
4290 if (opc2 & 0x02) {
4291 /* nmultiply-and-accumulate (0x0E) */
4292 gen_op_neg();
4294 if (opc2 & 0x04) {
4295 /* (n)multiply-and-accumulate (0x0C - 0x0E) */
4296 gen_op_load_gpr_T2(rt);
4297 gen_op_move_T1_T0();
4298 gen_op_405_add_T0_T2();
4300 if (opc3 & 0x10) {
4301 /* Check overflow */
4302 if (opc3 & 0x01)
4303 gen_op_405_check_ov();
4304 else
4305 gen_op_405_check_ovu();
4307 if (opc3 & 0x02) {
4308 /* Saturate */
4309 if (opc3 & 0x01)
4310 gen_op_405_check_sat();
4311 else
4312 gen_op_405_check_satu();
4314 gen_op_store_T0_gpr(rt);
4315 if (unlikely(Rc) != 0) {
4316 /* Update Rc0 */
4317 gen_set_Rc0(ctx);
4321 #define GEN_MAC_HANDLER(name, opc2, opc3) \
4322 GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_405_MAC) \
4324 gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode), \
4325 rD(ctx->opcode), Rc(ctx->opcode)); \
4328 /* macchw - macchw. */
4329 GEN_MAC_HANDLER(macchw, 0x0C, 0x05);
4330 /* macchwo - macchwo. */
4331 GEN_MAC_HANDLER(macchwo, 0x0C, 0x15);
4332 /* macchws - macchws. */
4333 GEN_MAC_HANDLER(macchws, 0x0C, 0x07);
4334 /* macchwso - macchwso. */
4335 GEN_MAC_HANDLER(macchwso, 0x0C, 0x17);
4336 /* macchwsu - macchwsu. */
4337 GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06);
4338 /* macchwsuo - macchwsuo. */
4339 GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16);
4340 /* macchwu - macchwu. */
4341 GEN_MAC_HANDLER(macchwu, 0x0C, 0x04);
4342 /* macchwuo - macchwuo. */
4343 GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14);
4344 /* machhw - machhw. */
4345 GEN_MAC_HANDLER(machhw, 0x0C, 0x01);
4346 /* machhwo - machhwo. */
4347 GEN_MAC_HANDLER(machhwo, 0x0C, 0x11);
4348 /* machhws - machhws. */
4349 GEN_MAC_HANDLER(machhws, 0x0C, 0x03);
4350 /* machhwso - machhwso. */
4351 GEN_MAC_HANDLER(machhwso, 0x0C, 0x13);
4352 /* machhwsu - machhwsu. */
4353 GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02);
4354 /* machhwsuo - machhwsuo. */
4355 GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12);
4356 /* machhwu - machhwu. */
4357 GEN_MAC_HANDLER(machhwu, 0x0C, 0x00);
4358 /* machhwuo - machhwuo. */
4359 GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10);
4360 /* maclhw - maclhw. */
4361 GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D);
4362 /* maclhwo - maclhwo. */
4363 GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D);
4364 /* maclhws - maclhws. */
4365 GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F);
4366 /* maclhwso - maclhwso. */
4367 GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F);
4368 /* maclhwu - maclhwu. */
4369 GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C);
4370 /* maclhwuo - maclhwuo. */
4371 GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C);
4372 /* maclhwsu - maclhwsu. */
4373 GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E);
4374 /* maclhwsuo - maclhwsuo. */
4375 GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E);
4376 /* nmacchw - nmacchw. */
4377 GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05);
4378 /* nmacchwo - nmacchwo. */
4379 GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15);
4380 /* nmacchws - nmacchws. */
4381 GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07);
4382 /* nmacchwso - nmacchwso. */
4383 GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17);
4384 /* nmachhw - nmachhw. */
4385 GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01);
4386 /* nmachhwo - nmachhwo. */
4387 GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11);
4388 /* nmachhws - nmachhws. */
4389 GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03);
4390 /* nmachhwso - nmachhwso. */
4391 GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13);
4392 /* nmaclhw - nmaclhw. */
4393 GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D);
4394 /* nmaclhwo - nmaclhwo. */
4395 GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D);
4396 /* nmaclhws - nmaclhws. */
4397 GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F);
4398 /* nmaclhwso - nmaclhwso. */
4399 GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F);
4401 /* mulchw - mulchw. */
4402 GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
4403 /* mulchwu - mulchwu. */
4404 GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
4405 /* mulhhw - mulhhw. */
4406 GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
4407 /* mulhhwu - mulhhwu. */
4408 GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
4409 /* mullhw - mullhw. */
4410 GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
4411 /* mullhwu - mullhwu. */
4412 GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
4414 /* mfdcr */
4415 GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_EMB_COMMON)
4417 #if defined(CONFIG_USER_ONLY)
4418 RET_PRIVREG(ctx);
4419 #else
4420 uint32_t dcrn = SPR(ctx->opcode);
4422 if (unlikely(!ctx->supervisor)) {
4423 RET_PRIVREG(ctx);
4424 return;
4426 gen_op_set_T0(dcrn);
4427 gen_op_load_dcr();
4428 gen_op_store_T0_gpr(rD(ctx->opcode));
4429 #endif
4432 /* mtdcr */
4433 GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_EMB_COMMON)
4435 #if defined(CONFIG_USER_ONLY)
4436 RET_PRIVREG(ctx);
4437 #else
4438 uint32_t dcrn = SPR(ctx->opcode);
4440 if (unlikely(!ctx->supervisor)) {
4441 RET_PRIVREG(ctx);
4442 return;
4444 gen_op_set_T0(dcrn);
4445 gen_op_load_gpr_T1(rS(ctx->opcode));
4446 gen_op_store_dcr();
4447 #endif
4450 /* mfdcrx */
4451 GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000001, PPC_BOOKE)
4453 #if defined(CONFIG_USER_ONLY)
4454 RET_PRIVREG(ctx);
4455 #else
4456 if (unlikely(!ctx->supervisor)) {
4457 RET_PRIVREG(ctx);
4458 return;
4460 gen_op_load_gpr_T0(rA(ctx->opcode));
4461 gen_op_load_dcr();
4462 gen_op_store_T0_gpr(rD(ctx->opcode));
4463 #endif
4466 /* mtdcrx */
4467 GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000001, PPC_BOOKE)
4469 #if defined(CONFIG_USER_ONLY)
4470 RET_PRIVREG(ctx);
4471 #else
4472 if (unlikely(!ctx->supervisor)) {
4473 RET_PRIVREG(ctx);
4474 return;
4476 gen_op_load_gpr_T0(rA(ctx->opcode));
4477 gen_op_load_gpr_T1(rS(ctx->opcode));
4478 gen_op_store_dcr();
4479 #endif
4482 /* dccci */
4483 GEN_HANDLER(dccci, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON)
4485 #if defined(CONFIG_USER_ONLY)
4486 RET_PRIVOPC(ctx);
4487 #else
4488 if (unlikely(!ctx->supervisor)) {
4489 RET_PRIVOPC(ctx);
4490 return;
4492 /* interpreted as no-op */
4493 #endif
4496 /* dcread */
4497 GEN_HANDLER(dcread, 0x1F, 0x06, 0x0F, 0x00000001, PPC_4xx_COMMON)
4499 #if defined(CONFIG_USER_ONLY)
4500 RET_PRIVOPC(ctx);
4501 #else
4502 if (unlikely(!ctx->supervisor)) {
4503 RET_PRIVOPC(ctx);
4504 return;
4506 gen_addr_reg_index(ctx);
4507 op_ldst(lwz);
4508 gen_op_store_T0_gpr(rD(ctx->opcode));
4509 #endif
4512 /* icbt */
4513 GEN_HANDLER(icbt_40x, 0x1F, 0x06, 0x08, 0x03E00001, PPC_40x_SPEC)
4515 /* interpreted as no-op */
4516 /* XXX: specification say this is treated as a load by the MMU
4517 * but does not generate any exception
4521 /* iccci */
4522 GEN_HANDLER(iccci, 0x1F, 0x06, 0x1E, 0x00000001, PPC_4xx_COMMON)
4524 #if defined(CONFIG_USER_ONLY)
4525 RET_PRIVOPC(ctx);
4526 #else
4527 if (unlikely(!ctx->supervisor)) {
4528 RET_PRIVOPC(ctx);
4529 return;
4531 /* interpreted as no-op */
4532 #endif
4535 /* icread */
4536 GEN_HANDLER(icread, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON)
4538 #if defined(CONFIG_USER_ONLY)
4539 RET_PRIVOPC(ctx);
4540 #else
4541 if (unlikely(!ctx->supervisor)) {
4542 RET_PRIVOPC(ctx);
4543 return;
4545 /* interpreted as no-op */
4546 #endif
4549 /* rfci (supervisor only) */
4550 GEN_HANDLER(rfci_40x, 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP)
4552 #if defined(CONFIG_USER_ONLY)
4553 RET_PRIVOPC(ctx);
4554 #else
4555 if (unlikely(!ctx->supervisor)) {
4556 RET_PRIVOPC(ctx);
4557 return;
4559 /* Restore CPU state */
4560 gen_op_40x_rfci();
4561 RET_CHG_FLOW(ctx);
4562 #endif
4565 GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE)
4567 #if defined(CONFIG_USER_ONLY)
4568 RET_PRIVOPC(ctx);
4569 #else
4570 if (unlikely(!ctx->supervisor)) {
4571 RET_PRIVOPC(ctx);
4572 return;
4574 /* Restore CPU state */
4575 gen_op_rfci();
4576 RET_CHG_FLOW(ctx);
4577 #endif
4580 /* BookE specific */
4581 GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_BOOKE)
4583 #if defined(CONFIG_USER_ONLY)
4584 RET_PRIVOPC(ctx);
4585 #else
4586 if (unlikely(!ctx->supervisor)) {
4587 RET_PRIVOPC(ctx);
4588 return;
4590 /* Restore CPU state */
4591 gen_op_rfdi();
4592 RET_CHG_FLOW(ctx);
4593 #endif
4596 GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_BOOKE)
4598 #if defined(CONFIG_USER_ONLY)
4599 RET_PRIVOPC(ctx);
4600 #else
4601 if (unlikely(!ctx->supervisor)) {
4602 RET_PRIVOPC(ctx);
4603 return;
4605 /* Restore CPU state */
4606 gen_op_rfmci();
4607 RET_CHG_FLOW(ctx);
4608 #endif
4610 /* TLB management - PowerPC 405 implementation */
4611 /* tlbre */
4612 GEN_HANDLER(tlbre, 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_SPEC)
4614 #if defined(CONFIG_USER_ONLY)
4615 RET_PRIVOPC(ctx);
4616 #else
4617 if (unlikely(!ctx->supervisor)) {
4618 RET_PRIVOPC(ctx);
4619 return;
4621 switch (rB(ctx->opcode)) {
4622 case 0:
4623 gen_op_load_gpr_T0(rA(ctx->opcode));
4624 gen_op_4xx_tlbre_hi();
4625 gen_op_store_T0_gpr(rD(ctx->opcode));
4626 break;
4627 case 1:
4628 gen_op_load_gpr_T0(rA(ctx->opcode));
4629 gen_op_4xx_tlbre_lo();
4630 gen_op_store_T0_gpr(rD(ctx->opcode));
4631 break;
4632 default:
4633 RET_INVAL(ctx);
4634 break;
4636 #endif
4639 /* tlbsx - tlbsx. */
4640 GEN_HANDLER(tlbsx, 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_SPEC)
4642 #if defined(CONFIG_USER_ONLY)
4643 RET_PRIVOPC(ctx);
4644 #else
4645 if (unlikely(!ctx->supervisor)) {
4646 RET_PRIVOPC(ctx);
4647 return;
4649 gen_addr_reg_index(ctx);
4650 if (Rc(ctx->opcode))
4651 gen_op_4xx_tlbsx_();
4652 else
4653 gen_op_4xx_tlbsx();
4654 gen_op_store_T0_gpr(rD(ctx->opcode));
4655 #endif
4658 /* tlbwe */
4659 GEN_HANDLER(tlbwe, 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_SPEC)
4661 #if defined(CONFIG_USER_ONLY)
4662 RET_PRIVOPC(ctx);
4663 #else
4664 if (unlikely(!ctx->supervisor)) {
4665 RET_PRIVOPC(ctx);
4666 return;
4668 switch (rB(ctx->opcode)) {
4669 case 0:
4670 gen_op_load_gpr_T0(rA(ctx->opcode));
4671 gen_op_load_gpr_T1(rS(ctx->opcode));
4672 gen_op_4xx_tlbwe_hi();
4673 break;
4674 case 1:
4675 gen_op_load_gpr_T0(rA(ctx->opcode));
4676 gen_op_load_gpr_T1(rS(ctx->opcode));
4677 gen_op_4xx_tlbwe_lo();
4678 break;
4679 default:
4680 RET_INVAL(ctx);
4681 break;
4683 #endif
4686 /* wrtee */
4687 GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_EMB_COMMON)
4689 #if defined(CONFIG_USER_ONLY)
4690 RET_PRIVOPC(ctx);
4691 #else
4692 if (unlikely(!ctx->supervisor)) {
4693 RET_PRIVOPC(ctx);
4694 return;
4696 gen_op_load_gpr_T0(rD(ctx->opcode));
4697 gen_op_wrte();
4698 RET_EXCP(ctx, EXCP_MTMSR, 0);
4699 #endif
4702 /* wrteei */
4703 GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000EFC01, PPC_EMB_COMMON)
4705 #if defined(CONFIG_USER_ONLY)
4706 RET_PRIVOPC(ctx);
4707 #else
4708 if (unlikely(!ctx->supervisor)) {
4709 RET_PRIVOPC(ctx);
4710 return;
4712 gen_op_set_T0(ctx->opcode & 0x00010000);
4713 gen_op_wrte();
4714 RET_EXCP(ctx, EXCP_MTMSR, 0);
4715 #endif
4718 /* PPC 440 specific instructions */
4719 /* dlmzb */
4720 GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC)
4722 gen_op_load_gpr_T0(rS(ctx->opcode));
4723 gen_op_load_gpr_T1(rB(ctx->opcode));
4724 gen_op_440_dlmzb();
4725 gen_op_store_T0_gpr(rA(ctx->opcode));
4726 gen_op_store_xer_bc();
4727 if (Rc(ctx->opcode)) {
4728 gen_op_440_dlmzb_update_Rc();
4729 gen_op_store_T0_crf(0);
4733 /* mbar replaces eieio on 440 */
4734 GEN_HANDLER(mbar, 0x1F, 0x16, 0x13, 0x001FF801, PPC_BOOKE)
4736 /* interpreted as no-op */
4739 /* msync replaces sync on 440 */
4740 GEN_HANDLER(msync, 0x1F, 0x16, 0x12, 0x03FF0801, PPC_BOOKE)
4742 /* interpreted as no-op */
4745 /* icbt */
4746 GEN_HANDLER(icbt_440, 0x1F, 0x16, 0x00, 0x03E00001, PPC_BOOKE)
4748 /* interpreted as no-op */
4749 /* XXX: specification say this is treated as a load by the MMU
4750 * but does not generate any exception
4754 #if defined(TARGET_PPCSPE)
4755 /*** SPE extension ***/
4757 /* Register moves */
4758 GEN32(gen_op_load_gpr64_T0, gen_op_load_gpr64_T0_gpr);
4759 GEN32(gen_op_load_gpr64_T1, gen_op_load_gpr64_T1_gpr);
4760 #if 0 // unused
4761 GEN32(gen_op_load_gpr64_T2, gen_op_load_gpr64_T2_gpr);
4762 #endif
4764 GEN32(gen_op_store_T0_gpr64, gen_op_store_T0_gpr64_gpr);
4765 GEN32(gen_op_store_T1_gpr64, gen_op_store_T1_gpr64_gpr);
4766 #if 0 // unused
4767 GEN32(gen_op_store_T2_gpr64, gen_op_store_T2_gpr64_gpr);
4768 #endif
4770 #define GEN_SPE(name0, name1, opc2, opc3, inval, type) \
4771 GEN_HANDLER(name0##_##name1, 0x04, opc2, opc3, inval, type) \
4773 if (Rc(ctx->opcode)) \
4774 gen_##name1(ctx); \
4775 else \
4776 gen_##name0(ctx); \
4779 /* Handler for undefined SPE opcodes */
4780 static inline void gen_speundef (DisasContext *ctx)
4782 RET_INVAL(ctx);
4785 /* SPE load and stores */
4786 static inline void gen_addr_spe_imm_index (DisasContext *ctx, int sh)
4788 target_long simm = rB(ctx->opcode);
4790 if (rA(ctx->opcode) == 0) {
4791 gen_set_T0(simm << sh);
4792 } else {
4793 gen_op_load_gpr_T0(rA(ctx->opcode));
4794 if (likely(simm != 0))
4795 gen_op_addi(simm << sh);
4799 #define op_spe_ldst(name) (*gen_op_##name[ctx->mem_idx])()
4800 #if defined(CONFIG_USER_ONLY)
4801 #if defined(TARGET_PPC64)
4802 #define OP_SPE_LD_TABLE(name) \
4803 static GenOpFunc *gen_op_spe_l##name[] = { \
4804 &gen_op_spe_l##name##_raw, \
4805 &gen_op_spe_l##name##_le_raw, \
4806 &gen_op_spe_l##name##_64_raw, \
4807 &gen_op_spe_l##name##_le_64_raw, \
4809 #define OP_SPE_ST_TABLE(name) \
4810 static GenOpFunc *gen_op_spe_st##name[] = { \
4811 &gen_op_spe_st##name##_raw, \
4812 &gen_op_spe_st##name##_le_raw, \
4813 &gen_op_spe_st##name##_64_raw, \
4814 &gen_op_spe_st##name##_le_64_raw, \
4816 #else /* defined(TARGET_PPC64) */
4817 #define OP_SPE_LD_TABLE(name) \
4818 static GenOpFunc *gen_op_spe_l##name[] = { \
4819 &gen_op_spe_l##name##_raw, \
4820 &gen_op_spe_l##name##_le_raw, \
4822 #define OP_SPE_ST_TABLE(name) \
4823 static GenOpFunc *gen_op_spe_st##name[] = { \
4824 &gen_op_spe_st##name##_raw, \
4825 &gen_op_spe_st##name##_le_raw, \
4827 #endif /* defined(TARGET_PPC64) */
4828 #else /* defined(CONFIG_USER_ONLY) */
4829 #if defined(TARGET_PPC64)
4830 #define OP_SPE_LD_TABLE(name) \
4831 static GenOpFunc *gen_op_spe_l##name[] = { \
4832 &gen_op_spe_l##name##_user, \
4833 &gen_op_spe_l##name##_le_user, \
4834 &gen_op_spe_l##name##_kernel, \
4835 &gen_op_spe_l##name##_le_kernel, \
4836 &gen_op_spe_l##name##_64_user, \
4837 &gen_op_spe_l##name##_le_64_user, \
4838 &gen_op_spe_l##name##_64_kernel, \
4839 &gen_op_spe_l##name##_le_64_kernel, \
4841 #define OP_SPE_ST_TABLE(name) \
4842 static GenOpFunc *gen_op_spe_st##name[] = { \
4843 &gen_op_spe_st##name##_user, \
4844 &gen_op_spe_st##name##_le_user, \
4845 &gen_op_spe_st##name##_kernel, \
4846 &gen_op_spe_st##name##_le_kernel, \
4847 &gen_op_spe_st##name##_64_user, \
4848 &gen_op_spe_st##name##_le_64_user, \
4849 &gen_op_spe_st##name##_64_kernel, \
4850 &gen_op_spe_st##name##_le_64_kernel, \
4852 #else /* defined(TARGET_PPC64) */
4853 #define OP_SPE_LD_TABLE(name) \
4854 static GenOpFunc *gen_op_spe_l##name[] = { \
4855 &gen_op_spe_l##name##_user, \
4856 &gen_op_spe_l##name##_le_user, \
4857 &gen_op_spe_l##name##_kernel, \
4858 &gen_op_spe_l##name##_le_kernel, \
4860 #define OP_SPE_ST_TABLE(name) \
4861 static GenOpFunc *gen_op_spe_st##name[] = { \
4862 &gen_op_spe_st##name##_user, \
4863 &gen_op_spe_st##name##_le_user, \
4864 &gen_op_spe_st##name##_kernel, \
4865 &gen_op_spe_st##name##_le_kernel, \
4867 #endif /* defined(TARGET_PPC64) */
4868 #endif /* defined(CONFIG_USER_ONLY) */
4870 #define GEN_SPE_LD(name, sh) \
4871 static inline void gen_evl##name (DisasContext *ctx) \
4873 if (unlikely(!ctx->spe_enabled)) { \
4874 RET_EXCP(ctx, EXCP_NO_SPE, 0); \
4875 return; \
4877 gen_addr_spe_imm_index(ctx, sh); \
4878 op_spe_ldst(spe_l##name); \
4879 gen_op_store_T1_gpr64(rD(ctx->opcode)); \
4882 #define GEN_SPE_LDX(name) \
4883 static inline void gen_evl##name##x (DisasContext *ctx) \
4885 if (unlikely(!ctx->spe_enabled)) { \
4886 RET_EXCP(ctx, EXCP_NO_SPE, 0); \
4887 return; \
4889 gen_addr_reg_index(ctx); \
4890 op_spe_ldst(spe_l##name); \
4891 gen_op_store_T1_gpr64(rD(ctx->opcode)); \
4894 #define GEN_SPEOP_LD(name, sh) \
4895 OP_SPE_LD_TABLE(name); \
4896 GEN_SPE_LD(name, sh); \
4897 GEN_SPE_LDX(name)
4899 #define GEN_SPE_ST(name, sh) \
4900 static inline void gen_evst##name (DisasContext *ctx) \
4902 if (unlikely(!ctx->spe_enabled)) { \
4903 RET_EXCP(ctx, EXCP_NO_SPE, 0); \
4904 return; \
4906 gen_addr_spe_imm_index(ctx, sh); \
4907 gen_op_load_gpr64_T1(rS(ctx->opcode)); \
4908 op_spe_ldst(spe_st##name); \
4911 #define GEN_SPE_STX(name) \
4912 static inline void gen_evst##name##x (DisasContext *ctx) \
4914 if (unlikely(!ctx->spe_enabled)) { \
4915 RET_EXCP(ctx, EXCP_NO_SPE, 0); \
4916 return; \
4918 gen_addr_reg_index(ctx); \
4919 gen_op_load_gpr64_T1(rS(ctx->opcode)); \
4920 op_spe_ldst(spe_st##name); \
4923 #define GEN_SPEOP_ST(name, sh) \
4924 OP_SPE_ST_TABLE(name); \
4925 GEN_SPE_ST(name, sh); \
4926 GEN_SPE_STX(name)
4928 #define GEN_SPEOP_LDST(name, sh) \
4929 GEN_SPEOP_LD(name, sh); \
4930 GEN_SPEOP_ST(name, sh)
4932 /* SPE arithmetic and logic */
4933 #define GEN_SPEOP_ARITH2(name) \
4934 static inline void gen_##name (DisasContext *ctx) \
4936 if (unlikely(!ctx->spe_enabled)) { \
4937 RET_EXCP(ctx, EXCP_NO_SPE, 0); \
4938 return; \
4940 gen_op_load_gpr64_T0(rA(ctx->opcode)); \
4941 gen_op_load_gpr64_T1(rB(ctx->opcode)); \
4942 gen_op_##name(); \
4943 gen_op_store_T0_gpr64(rD(ctx->opcode)); \
4946 #define GEN_SPEOP_ARITH1(name) \
4947 static inline void gen_##name (DisasContext *ctx) \
4949 if (unlikely(!ctx->spe_enabled)) { \
4950 RET_EXCP(ctx, EXCP_NO_SPE, 0); \
4951 return; \
4953 gen_op_load_gpr64_T0(rA(ctx->opcode)); \
4954 gen_op_##name(); \
4955 gen_op_store_T0_gpr64(rD(ctx->opcode)); \
4958 #define GEN_SPEOP_COMP(name) \
4959 static inline void gen_##name (DisasContext *ctx) \
4961 if (unlikely(!ctx->spe_enabled)) { \
4962 RET_EXCP(ctx, EXCP_NO_SPE, 0); \
4963 return; \
4965 gen_op_load_gpr64_T0(rA(ctx->opcode)); \
4966 gen_op_load_gpr64_T1(rB(ctx->opcode)); \
4967 gen_op_##name(); \
4968 gen_op_store_T0_crf(crfD(ctx->opcode)); \
4971 /* Logical */
4972 GEN_SPEOP_ARITH2(evand);
4973 GEN_SPEOP_ARITH2(evandc);
4974 GEN_SPEOP_ARITH2(evxor);
4975 GEN_SPEOP_ARITH2(evor);
4976 GEN_SPEOP_ARITH2(evnor);
4977 GEN_SPEOP_ARITH2(eveqv);
4978 GEN_SPEOP_ARITH2(evorc);
4979 GEN_SPEOP_ARITH2(evnand);
4980 GEN_SPEOP_ARITH2(evsrwu);
4981 GEN_SPEOP_ARITH2(evsrws);
4982 GEN_SPEOP_ARITH2(evslw);
4983 GEN_SPEOP_ARITH2(evrlw);
4984 GEN_SPEOP_ARITH2(evmergehi);
4985 GEN_SPEOP_ARITH2(evmergelo);
4986 GEN_SPEOP_ARITH2(evmergehilo);
4987 GEN_SPEOP_ARITH2(evmergelohi);
4989 /* Arithmetic */
4990 GEN_SPEOP_ARITH2(evaddw);
4991 GEN_SPEOP_ARITH2(evsubfw);
4992 GEN_SPEOP_ARITH1(evabs);
4993 GEN_SPEOP_ARITH1(evneg);
4994 GEN_SPEOP_ARITH1(evextsb);
4995 GEN_SPEOP_ARITH1(evextsh);
4996 GEN_SPEOP_ARITH1(evrndw);
4997 GEN_SPEOP_ARITH1(evcntlzw);
4998 GEN_SPEOP_ARITH1(evcntlsw);
4999 static inline void gen_brinc (DisasContext *ctx)
5001 /* Note: brinc is usable even if SPE is disabled */
5002 gen_op_load_gpr64_T0(rA(ctx->opcode));
5003 gen_op_load_gpr64_T1(rB(ctx->opcode));
5004 gen_op_brinc();
5005 gen_op_store_T0_gpr64(rD(ctx->opcode));
5008 #define GEN_SPEOP_ARITH_IMM2(name) \
5009 static inline void gen_##name##i (DisasContext *ctx) \
5011 if (unlikely(!ctx->spe_enabled)) { \
5012 RET_EXCP(ctx, EXCP_NO_SPE, 0); \
5013 return; \
5015 gen_op_load_gpr64_T0(rB(ctx->opcode)); \
5016 gen_op_splatwi_T1_64(rA(ctx->opcode)); \
5017 gen_op_##name(); \
5018 gen_op_store_T0_gpr64(rD(ctx->opcode)); \
5021 #define GEN_SPEOP_LOGIC_IMM2(name) \
5022 static inline void gen_##name##i (DisasContext *ctx) \
5024 if (unlikely(!ctx->spe_enabled)) { \
5025 RET_EXCP(ctx, EXCP_NO_SPE, 0); \
5026 return; \
5028 gen_op_load_gpr64_T0(rA(ctx->opcode)); \
5029 gen_op_splatwi_T1_64(rB(ctx->opcode)); \
5030 gen_op_##name(); \
5031 gen_op_store_T0_gpr64(rD(ctx->opcode)); \
5034 GEN_SPEOP_ARITH_IMM2(evaddw);
5035 #define gen_evaddiw gen_evaddwi
5036 GEN_SPEOP_ARITH_IMM2(evsubfw);
5037 #define gen_evsubifw gen_evsubfwi
5038 GEN_SPEOP_LOGIC_IMM2(evslw);
5039 GEN_SPEOP_LOGIC_IMM2(evsrwu);
5040 #define gen_evsrwis gen_evsrwsi
5041 GEN_SPEOP_LOGIC_IMM2(evsrws);
5042 #define gen_evsrwiu gen_evsrwui
5043 GEN_SPEOP_LOGIC_IMM2(evrlw);
5045 static inline void gen_evsplati (DisasContext *ctx)
5047 int32_t imm = (int32_t)(rA(ctx->opcode) << 27) >> 27;
5049 gen_op_splatwi_T0_64(imm);
5050 gen_op_store_T0_gpr64(rD(ctx->opcode));
5053 static inline void gen_evsplatfi (DisasContext *ctx)
5055 uint32_t imm = rA(ctx->opcode) << 27;
5057 gen_op_splatwi_T0_64(imm);
5058 gen_op_store_T0_gpr64(rD(ctx->opcode));
5061 /* Comparison */
5062 GEN_SPEOP_COMP(evcmpgtu);
5063 GEN_SPEOP_COMP(evcmpgts);
5064 GEN_SPEOP_COMP(evcmpltu);
5065 GEN_SPEOP_COMP(evcmplts);
5066 GEN_SPEOP_COMP(evcmpeq);
5068 GEN_SPE(evaddw, speundef, 0x00, 0x08, 0x00000000, PPC_SPE); ////
5069 GEN_SPE(evaddiw, speundef, 0x01, 0x08, 0x00000000, PPC_SPE);
5070 GEN_SPE(evsubfw, speundef, 0x02, 0x08, 0x00000000, PPC_SPE); ////
5071 GEN_SPE(evsubifw, speundef, 0x03, 0x08, 0x00000000, PPC_SPE);
5072 GEN_SPE(evabs, evneg, 0x04, 0x08, 0x0000F800, PPC_SPE); ////
5073 GEN_SPE(evextsb, evextsh, 0x05, 0x08, 0x0000F800, PPC_SPE); ////
5074 GEN_SPE(evrndw, evcntlzw, 0x06, 0x08, 0x0000F800, PPC_SPE); ////
5075 GEN_SPE(evcntlsw, brinc, 0x07, 0x08, 0x00000000, PPC_SPE); //
5076 GEN_SPE(speundef, evand, 0x08, 0x08, 0x00000000, PPC_SPE); ////
5077 GEN_SPE(evandc, speundef, 0x09, 0x08, 0x00000000, PPC_SPE); ////
5078 GEN_SPE(evxor, evor, 0x0B, 0x08, 0x00000000, PPC_SPE); ////
5079 GEN_SPE(evnor, eveqv, 0x0C, 0x08, 0x00000000, PPC_SPE); ////
5080 GEN_SPE(speundef, evorc, 0x0D, 0x08, 0x00000000, PPC_SPE); ////
5081 GEN_SPE(evnand, speundef, 0x0F, 0x08, 0x00000000, PPC_SPE); ////
5082 GEN_SPE(evsrwu, evsrws, 0x10, 0x08, 0x00000000, PPC_SPE); ////
5083 GEN_SPE(evsrwiu, evsrwis, 0x11, 0x08, 0x00000000, PPC_SPE);
5084 GEN_SPE(evslw, speundef, 0x12, 0x08, 0x00000000, PPC_SPE); ////
5085 GEN_SPE(evslwi, speundef, 0x13, 0x08, 0x00000000, PPC_SPE);
5086 GEN_SPE(evrlw, evsplati, 0x14, 0x08, 0x00000000, PPC_SPE); //
5087 GEN_SPE(evrlwi, evsplatfi, 0x15, 0x08, 0x00000000, PPC_SPE);
5088 GEN_SPE(evmergehi, evmergelo, 0x16, 0x08, 0x00000000, PPC_SPE); ////
5089 GEN_SPE(evmergehilo, evmergelohi, 0x17, 0x08, 0x00000000, PPC_SPE); ////
5090 GEN_SPE(evcmpgtu, evcmpgts, 0x18, 0x08, 0x00600000, PPC_SPE); ////
5091 GEN_SPE(evcmpltu, evcmplts, 0x19, 0x08, 0x00600000, PPC_SPE); ////
5092 GEN_SPE(evcmpeq, speundef, 0x1A, 0x08, 0x00600000, PPC_SPE); ////
5094 static inline void gen_evsel (DisasContext *ctx)
5096 if (unlikely(!ctx->spe_enabled)) {
5097 RET_EXCP(ctx, EXCP_NO_SPE, 0);
5098 return;
5100 gen_op_load_crf_T0(ctx->opcode & 0x7);
5101 gen_op_load_gpr64_T0(rA(ctx->opcode));
5102 gen_op_load_gpr64_T1(rB(ctx->opcode));
5103 gen_op_evsel();
5104 gen_op_store_T0_gpr64(rD(ctx->opcode));
5107 GEN_HANDLER(evsel0, 0x04, 0x1c, 0x09, 0x00000000, PPC_SPE)
5109 gen_evsel(ctx);
5111 GEN_HANDLER(evsel1, 0x04, 0x1d, 0x09, 0x00000000, PPC_SPE)
5113 gen_evsel(ctx);
5115 GEN_HANDLER(evsel2, 0x04, 0x1e, 0x09, 0x00000000, PPC_SPE)
5117 gen_evsel(ctx);
5119 GEN_HANDLER(evsel3, 0x04, 0x1f, 0x09, 0x00000000, PPC_SPE)
5121 gen_evsel(ctx);
5124 /* Load and stores */
5125 #if defined(TARGET_PPC64)
5126 /* In that case, we already have 64 bits load & stores
5127 * so, spe_ldd is equivalent to ld and spe_std is equivalent to std
5129 #if defined(CONFIG_USER_ONLY)
5130 #define gen_op_spe_ldd_raw gen_op_ld_raw
5131 #define gen_op_spe_ldd_64_raw gen_op_ld_64_raw
5132 #define gen_op_spe_ldd_le_raw gen_op_ld_le_raw
5133 #define gen_op_spe_ldd_le_64_raw gen_op_ld_le_64_raw
5134 #define gen_op_spe_stdd_raw gen_op_ld_raw
5135 #define gen_op_spe_stdd_64_raw gen_op_std_64_raw
5136 #define gen_op_spe_stdd_le_raw gen_op_std_le_raw
5137 #define gen_op_spe_stdd_le_64_raw gen_op_std_le_64_raw
5138 #else /* defined(CONFIG_USER_ONLY) */
5139 #define gen_op_spe_ldd_kernel gen_op_ld_kernel
5140 #define gen_op_spe_ldd_64_kernel gen_op_ld_64_kernel
5141 #define gen_op_spe_ldd_le_kernel gen_op_ld_kernel
5142 #define gen_op_spe_ldd_le_64_kernel gen_op_ld_64_kernel
5143 #define gen_op_spe_ldd_user gen_op_ld_user
5144 #define gen_op_spe_ldd_64_user gen_op_ld_64_user
5145 #define gen_op_spe_ldd_le_user gen_op_ld_le_user
5146 #define gen_op_spe_ldd_le_64_user gen_op_ld_le_64_user
5147 #define gen_op_spe_stdd_kernel gen_op_std_kernel
5148 #define gen_op_spe_stdd_64_kernel gen_op_std_64_kernel
5149 #define gen_op_spe_stdd_le_kernel gen_op_std_kernel
5150 #define gen_op_spe_stdd_le_64_kernel gen_op_std_64_kernel
5151 #define gen_op_spe_stdd_user gen_op_std_user
5152 #define gen_op_spe_stdd_64_user gen_op_std_64_user
5153 #define gen_op_spe_stdd_le_user gen_op_std_le_user
5154 #define gen_op_spe_stdd_le_64_user gen_op_std_le_64_user
5155 #endif /* defined(CONFIG_USER_ONLY) */
5156 #endif /* defined(TARGET_PPC64) */
5157 GEN_SPEOP_LDST(dd, 3);
5158 GEN_SPEOP_LDST(dw, 3);
5159 GEN_SPEOP_LDST(dh, 3);
5160 GEN_SPEOP_LDST(whe, 2);
5161 GEN_SPEOP_LD(whou, 2);
5162 GEN_SPEOP_LD(whos, 2);
5163 GEN_SPEOP_ST(who, 2);
5165 #if defined(TARGET_PPC64)
5166 /* In that case, spe_stwwo is equivalent to stw */
5167 #if defined(CONFIG_USER_ONLY)
5168 #define gen_op_spe_stwwo_raw gen_op_stw_raw
5169 #define gen_op_spe_stwwo_le_raw gen_op_stw_le_raw
5170 #define gen_op_spe_stwwo_64_raw gen_op_stw_64_raw
5171 #define gen_op_spe_stwwo_le_64_raw gen_op_stw_le_64_raw
5172 #else
5173 #define gen_op_spe_stwwo_user gen_op_stw_user
5174 #define gen_op_spe_stwwo_le_user gen_op_stw_le_user
5175 #define gen_op_spe_stwwo_64_user gen_op_stw_64_user
5176 #define gen_op_spe_stwwo_le_64_user gen_op_stw_le_64_user
5177 #define gen_op_spe_stwwo_kernel gen_op_stw_kernel
5178 #define gen_op_spe_stwwo_le_kernel gen_op_stw_le_kernel
5179 #define gen_op_spe_stwwo_64_kernel gen_op_stw_64_kernel
5180 #define gen_op_spe_stwwo_le_64_kernel gen_op_stw_le_64_kernel
5181 #endif
5182 #endif
5183 #define _GEN_OP_SPE_STWWE(suffix) \
5184 static inline void gen_op_spe_stwwe_##suffix (void) \
5186 gen_op_srli32_T1_64(); \
5187 gen_op_spe_stwwo_##suffix(); \
5189 #define _GEN_OP_SPE_STWWE_LE(suffix) \
5190 static inline void gen_op_spe_stwwe_le_##suffix (void) \
5192 gen_op_srli32_T1_64(); \
5193 gen_op_spe_stwwo_le_##suffix(); \
5195 #if defined(TARGET_PPC64)
5196 #define GEN_OP_SPE_STWWE(suffix) \
5197 _GEN_OP_SPE_STWWE(suffix); \
5198 _GEN_OP_SPE_STWWE_LE(suffix); \
5199 static inline void gen_op_spe_stwwe_64_##suffix (void) \
5201 gen_op_srli32_T1_64(); \
5202 gen_op_spe_stwwo_64_##suffix(); \
5204 static inline void gen_op_spe_stwwe_le_64_##suffix (void) \
5206 gen_op_srli32_T1_64(); \
5207 gen_op_spe_stwwo_le_64_##suffix(); \
5209 #else
5210 #define GEN_OP_SPE_STWWE(suffix) \
5211 _GEN_OP_SPE_STWWE(suffix); \
5212 _GEN_OP_SPE_STWWE_LE(suffix)
5213 #endif
5214 #if defined(CONFIG_USER_ONLY)
5215 GEN_OP_SPE_STWWE(raw);
5216 #else /* defined(CONFIG_USER_ONLY) */
5217 GEN_OP_SPE_STWWE(kernel);
5218 GEN_OP_SPE_STWWE(user);
5219 #endif /* defined(CONFIG_USER_ONLY) */
5220 GEN_SPEOP_ST(wwe, 2);
5221 GEN_SPEOP_ST(wwo, 2);
5223 #define GEN_SPE_LDSPLAT(name, op, suffix) \
5224 static inline void gen_op_spe_l##name##_##suffix (void) \
5226 gen_op_##op##_##suffix(); \
5227 gen_op_splatw_T1_64(); \
5230 #define GEN_OP_SPE_LHE(suffix) \
5231 static inline void gen_op_spe_lhe_##suffix (void) \
5233 gen_op_spe_lh_##suffix(); \
5234 gen_op_sli16_T1_64(); \
5237 #define GEN_OP_SPE_LHX(suffix) \
5238 static inline void gen_op_spe_lhx_##suffix (void) \
5240 gen_op_spe_lh_##suffix(); \
5241 gen_op_extsh_T1_64(); \
5244 #if defined(CONFIG_USER_ONLY)
5245 GEN_OP_SPE_LHE(raw);
5246 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, raw);
5247 GEN_OP_SPE_LHE(le_raw);
5248 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_raw);
5249 GEN_SPE_LDSPLAT(hhousplat, spe_lh, raw);
5250 GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_raw);
5251 GEN_OP_SPE_LHX(raw);
5252 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, raw);
5253 GEN_OP_SPE_LHX(le_raw);
5254 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_raw);
5255 #if defined(TARGET_PPC64)
5256 GEN_OP_SPE_LHE(64_raw);
5257 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_raw);
5258 GEN_OP_SPE_LHE(le_64_raw);
5259 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_raw);
5260 GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_raw);
5261 GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_raw);
5262 GEN_OP_SPE_LHX(64_raw);
5263 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_raw);
5264 GEN_OP_SPE_LHX(le_64_raw);
5265 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_raw);
5266 #endif
5267 #else
5268 GEN_OP_SPE_LHE(kernel);
5269 GEN_OP_SPE_LHE(user);
5270 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, kernel);
5271 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, user);
5272 GEN_OP_SPE_LHE(le_kernel);
5273 GEN_OP_SPE_LHE(le_user);
5274 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_kernel);
5275 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_user);
5276 GEN_SPE_LDSPLAT(hhousplat, spe_lh, kernel);
5277 GEN_SPE_LDSPLAT(hhousplat, spe_lh, user);
5278 GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_kernel);
5279 GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_user);
5280 GEN_OP_SPE_LHX(kernel);
5281 GEN_OP_SPE_LHX(user);
5282 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, kernel);
5283 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, user);
5284 GEN_OP_SPE_LHX(le_kernel);
5285 GEN_OP_SPE_LHX(le_user);
5286 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_kernel);
5287 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_user);
5288 #if defined(TARGET_PPC64)
5289 GEN_OP_SPE_LHE(64_kernel);
5290 GEN_OP_SPE_LHE(64_user);
5291 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_kernel);
5292 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_user);
5293 GEN_OP_SPE_LHE(le_64_kernel);
5294 GEN_OP_SPE_LHE(le_64_user);
5295 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_kernel);
5296 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_user);
5297 GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_kernel);
5298 GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_user);
5299 GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_kernel);
5300 GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_user);
5301 GEN_OP_SPE_LHX(64_kernel);
5302 GEN_OP_SPE_LHX(64_user);
5303 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_kernel);
5304 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_user);
5305 GEN_OP_SPE_LHX(le_64_kernel);
5306 GEN_OP_SPE_LHX(le_64_user);
5307 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_kernel);
5308 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_user);
5309 #endif
5310 #endif
5311 GEN_SPEOP_LD(hhesplat, 1);
5312 GEN_SPEOP_LD(hhousplat, 1);
5313 GEN_SPEOP_LD(hhossplat, 1);
5314 GEN_SPEOP_LD(wwsplat, 2);
5315 GEN_SPEOP_LD(whsplat, 2);
5317 GEN_SPE(evlddx, evldd, 0x00, 0x0C, 0x00000000, PPC_SPE); //
5318 GEN_SPE(evldwx, evldw, 0x01, 0x0C, 0x00000000, PPC_SPE); //
5319 GEN_SPE(evldhx, evldh, 0x02, 0x0C, 0x00000000, PPC_SPE); //
5320 GEN_SPE(evlhhesplatx, evlhhesplat, 0x04, 0x0C, 0x00000000, PPC_SPE); //
5321 GEN_SPE(evlhhousplatx, evlhhousplat, 0x06, 0x0C, 0x00000000, PPC_SPE); //
5322 GEN_SPE(evlhhossplatx, evlhhossplat, 0x07, 0x0C, 0x00000000, PPC_SPE); //
5323 GEN_SPE(evlwhex, evlwhe, 0x08, 0x0C, 0x00000000, PPC_SPE); //
5324 GEN_SPE(evlwhoux, evlwhou, 0x0A, 0x0C, 0x00000000, PPC_SPE); //
5325 GEN_SPE(evlwhosx, evlwhos, 0x0B, 0x0C, 0x00000000, PPC_SPE); //
5326 GEN_SPE(evlwwsplatx, evlwwsplat, 0x0C, 0x0C, 0x00000000, PPC_SPE); //
5327 GEN_SPE(evlwhsplatx, evlwhsplat, 0x0E, 0x0C, 0x00000000, PPC_SPE); //
5328 GEN_SPE(evstddx, evstdd, 0x10, 0x0C, 0x00000000, PPC_SPE); //
5329 GEN_SPE(evstdwx, evstdw, 0x11, 0x0C, 0x00000000, PPC_SPE); //
5330 GEN_SPE(evstdhx, evstdh, 0x12, 0x0C, 0x00000000, PPC_SPE); //
5331 GEN_SPE(evstwhex, evstwhe, 0x18, 0x0C, 0x00000000, PPC_SPE); //
5332 GEN_SPE(evstwhox, evstwho, 0x1A, 0x0C, 0x00000000, PPC_SPE); //
5333 GEN_SPE(evstwwex, evstwwe, 0x1C, 0x0C, 0x00000000, PPC_SPE); //
5334 GEN_SPE(evstwwox, evstwwo, 0x1E, 0x0C, 0x00000000, PPC_SPE); //
5336 /* Multiply and add - TODO */
5337 #if 0
5338 GEN_SPE(speundef, evmhessf, 0x01, 0x10, 0x00000000, PPC_SPE);
5339 GEN_SPE(speundef, evmhossf, 0x03, 0x10, 0x00000000, PPC_SPE);
5340 GEN_SPE(evmheumi, evmhesmi, 0x04, 0x10, 0x00000000, PPC_SPE);
5341 GEN_SPE(speundef, evmhesmf, 0x05, 0x10, 0x00000000, PPC_SPE);
5342 GEN_SPE(evmhoumi, evmhosmi, 0x06, 0x10, 0x00000000, PPC_SPE);
5343 GEN_SPE(speundef, evmhosmf, 0x07, 0x10, 0x00000000, PPC_SPE);
5344 GEN_SPE(speundef, evmhessfa, 0x11, 0x10, 0x00000000, PPC_SPE);
5345 GEN_SPE(speundef, evmhossfa, 0x13, 0x10, 0x00000000, PPC_SPE);
5346 GEN_SPE(evmheumia, evmhesmia, 0x14, 0x10, 0x00000000, PPC_SPE);
5347 GEN_SPE(speundef, evmhesmfa, 0x15, 0x10, 0x00000000, PPC_SPE);
5348 GEN_SPE(evmhoumia, evmhosmia, 0x16, 0x10, 0x00000000, PPC_SPE);
5349 GEN_SPE(speundef, evmhosmfa, 0x17, 0x10, 0x00000000, PPC_SPE);
5351 GEN_SPE(speundef, evmwhssf, 0x03, 0x11, 0x00000000, PPC_SPE);
5352 GEN_SPE(evmwlumi, speundef, 0x04, 0x11, 0x00000000, PPC_SPE);
5353 GEN_SPE(evmwhumi, evmwhsmi, 0x06, 0x11, 0x00000000, PPC_SPE);
5354 GEN_SPE(speundef, evmwhsmf, 0x07, 0x11, 0x00000000, PPC_SPE);
5355 GEN_SPE(speundef, evmwssf, 0x09, 0x11, 0x00000000, PPC_SPE);
5356 GEN_SPE(evmwumi, evmwsmi, 0x0C, 0x11, 0x00000000, PPC_SPE);
5357 GEN_SPE(speundef, evmwsmf, 0x0D, 0x11, 0x00000000, PPC_SPE);
5358 GEN_SPE(speundef, evmwhssfa, 0x13, 0x11, 0x00000000, PPC_SPE);
5359 GEN_SPE(evmwlumia, speundef, 0x14, 0x11, 0x00000000, PPC_SPE);
5360 GEN_SPE(evmwhumia, evmwhsmia, 0x16, 0x11, 0x00000000, PPC_SPE);
5361 GEN_SPE(speundef, evmwhsmfa, 0x17, 0x11, 0x00000000, PPC_SPE);
5362 GEN_SPE(speundef, evmwssfa, 0x19, 0x11, 0x00000000, PPC_SPE);
5363 GEN_SPE(evmwumia, evmwsmia, 0x1C, 0x11, 0x00000000, PPC_SPE);
5364 GEN_SPE(speundef, evmwsmfa, 0x1D, 0x11, 0x00000000, PPC_SPE);
5366 GEN_SPE(evadduiaaw, evaddsiaaw, 0x00, 0x13, 0x0000F800, PPC_SPE);
5367 GEN_SPE(evsubfusiaaw, evsubfssiaaw, 0x01, 0x13, 0x0000F800, PPC_SPE);
5368 GEN_SPE(evaddumiaaw, evaddsmiaaw, 0x04, 0x13, 0x0000F800, PPC_SPE);
5369 GEN_SPE(evsubfumiaaw, evsubfsmiaaw, 0x05, 0x13, 0x0000F800, PPC_SPE);
5370 GEN_SPE(evdivws, evdivwu, 0x06, 0x13, 0x00000000, PPC_SPE);
5371 GEN_SPE(evmra, speundef, 0x07, 0x13, 0x0000F800, PPC_SPE);
5373 GEN_SPE(evmheusiaaw, evmhessiaaw, 0x00, 0x14, 0x00000000, PPC_SPE);
5374 GEN_SPE(speundef, evmhessfaaw, 0x01, 0x14, 0x00000000, PPC_SPE);
5375 GEN_SPE(evmhousiaaw, evmhossiaaw, 0x02, 0x14, 0x00000000, PPC_SPE);
5376 GEN_SPE(speundef, evmhossfaaw, 0x03, 0x14, 0x00000000, PPC_SPE);
5377 GEN_SPE(evmheumiaaw, evmhesmiaaw, 0x04, 0x14, 0x00000000, PPC_SPE);
5378 GEN_SPE(speundef, evmhesmfaaw, 0x05, 0x14, 0x00000000, PPC_SPE);
5379 GEN_SPE(evmhoumiaaw, evmhosmiaaw, 0x06, 0x14, 0x00000000, PPC_SPE);
5380 GEN_SPE(speundef, evmhosmfaaw, 0x07, 0x14, 0x00000000, PPC_SPE);
5381 GEN_SPE(evmhegumiaa, evmhegsmiaa, 0x14, 0x14, 0x00000000, PPC_SPE);
5382 GEN_SPE(speundef, evmhegsmfaa, 0x15, 0x14, 0x00000000, PPC_SPE);
5383 GEN_SPE(evmhogumiaa, evmhogsmiaa, 0x16, 0x14, 0x00000000, PPC_SPE);
5384 GEN_SPE(speundef, evmhogsmfaa, 0x17, 0x14, 0x00000000, PPC_SPE);
5386 GEN_SPE(evmwlusiaaw, evmwlssiaaw, 0x00, 0x15, 0x00000000, PPC_SPE);
5387 GEN_SPE(evmwlumiaaw, evmwlsmiaaw, 0x04, 0x15, 0x00000000, PPC_SPE);
5388 GEN_SPE(speundef, evmwssfaa, 0x09, 0x15, 0x00000000, PPC_SPE);
5389 GEN_SPE(evmwumiaa, evmwsmiaa, 0x0C, 0x15, 0x00000000, PPC_SPE);
5390 GEN_SPE(speundef, evmwsmfaa, 0x0D, 0x15, 0x00000000, PPC_SPE);
5392 GEN_SPE(evmheusianw, evmhessianw, 0x00, 0x16, 0x00000000, PPC_SPE);
5393 GEN_SPE(speundef, evmhessfanw, 0x01, 0x16, 0x00000000, PPC_SPE);
5394 GEN_SPE(evmhousianw, evmhossianw, 0x02, 0x16, 0x00000000, PPC_SPE);
5395 GEN_SPE(speundef, evmhossfanw, 0x03, 0x16, 0x00000000, PPC_SPE);
5396 GEN_SPE(evmheumianw, evmhesmianw, 0x04, 0x16, 0x00000000, PPC_SPE);
5397 GEN_SPE(speundef, evmhesmfanw, 0x05, 0x16, 0x00000000, PPC_SPE);
5398 GEN_SPE(evmhoumianw, evmhosmianw, 0x06, 0x16, 0x00000000, PPC_SPE);
5399 GEN_SPE(speundef, evmhosmfanw, 0x07, 0x16, 0x00000000, PPC_SPE);
5400 GEN_SPE(evmhegumian, evmhegsmian, 0x14, 0x16, 0x00000000, PPC_SPE);
5401 GEN_SPE(speundef, evmhegsmfan, 0x15, 0x16, 0x00000000, PPC_SPE);
5402 GEN_SPE(evmhigumian, evmhigsmian, 0x16, 0x16, 0x00000000, PPC_SPE);
5403 GEN_SPE(speundef, evmhogsmfan, 0x17, 0x16, 0x00000000, PPC_SPE);
5405 GEN_SPE(evmwlusianw, evmwlssianw, 0x00, 0x17, 0x00000000, PPC_SPE);
5406 GEN_SPE(evmwlumianw, evmwlsmianw, 0x04, 0x17, 0x00000000, PPC_SPE);
5407 GEN_SPE(speundef, evmwssfan, 0x09, 0x17, 0x00000000, PPC_SPE);
5408 GEN_SPE(evmwumian, evmwsmian, 0x0C, 0x17, 0x00000000, PPC_SPE);
5409 GEN_SPE(speundef, evmwsmfan, 0x0D, 0x17, 0x00000000, PPC_SPE);
5410 #endif
5412 /*** SPE floating-point extension ***/
5413 #define GEN_SPEFPUOP_CONV(name) \
5414 static inline void gen_##name (DisasContext *ctx) \
5416 gen_op_load_gpr64_T0(rB(ctx->opcode)); \
5417 gen_op_##name(); \
5418 gen_op_store_T0_gpr64(rD(ctx->opcode)); \
5421 /* Single precision floating-point vectors operations */
5422 /* Arithmetic */
5423 GEN_SPEOP_ARITH2(evfsadd);
5424 GEN_SPEOP_ARITH2(evfssub);
5425 GEN_SPEOP_ARITH2(evfsmul);
5426 GEN_SPEOP_ARITH2(evfsdiv);
5427 GEN_SPEOP_ARITH1(evfsabs);
5428 GEN_SPEOP_ARITH1(evfsnabs);
5429 GEN_SPEOP_ARITH1(evfsneg);
5430 /* Conversion */
5431 GEN_SPEFPUOP_CONV(evfscfui);
5432 GEN_SPEFPUOP_CONV(evfscfsi);
5433 GEN_SPEFPUOP_CONV(evfscfuf);
5434 GEN_SPEFPUOP_CONV(evfscfsf);
5435 GEN_SPEFPUOP_CONV(evfsctui);
5436 GEN_SPEFPUOP_CONV(evfsctsi);
5437 GEN_SPEFPUOP_CONV(evfsctuf);
5438 GEN_SPEFPUOP_CONV(evfsctsf);
5439 GEN_SPEFPUOP_CONV(evfsctuiz);
5440 GEN_SPEFPUOP_CONV(evfsctsiz);
5441 /* Comparison */
5442 GEN_SPEOP_COMP(evfscmpgt);
5443 GEN_SPEOP_COMP(evfscmplt);
5444 GEN_SPEOP_COMP(evfscmpeq);
5445 GEN_SPEOP_COMP(evfststgt);
5446 GEN_SPEOP_COMP(evfststlt);
5447 GEN_SPEOP_COMP(evfststeq);
5449 /* Opcodes definitions */
5450 GEN_SPE(evfsadd, evfssub, 0x00, 0x0A, 0x00000000, PPC_SPEFPU); //
5451 GEN_SPE(evfsabs, evfsnabs, 0x02, 0x0A, 0x0000F800, PPC_SPEFPU); //
5452 GEN_SPE(evfsneg, speundef, 0x03, 0x0A, 0x0000F800, PPC_SPEFPU); //
5453 GEN_SPE(evfsmul, evfsdiv, 0x04, 0x0A, 0x00000000, PPC_SPEFPU); //
5454 GEN_SPE(evfscmpgt, evfscmplt, 0x06, 0x0A, 0x00600000, PPC_SPEFPU); //
5455 GEN_SPE(evfscmpeq, speundef, 0x07, 0x0A, 0x00600000, PPC_SPEFPU); //
5456 GEN_SPE(evfscfui, evfscfsi, 0x08, 0x0A, 0x00180000, PPC_SPEFPU); //
5457 GEN_SPE(evfscfuf, evfscfsf, 0x09, 0x0A, 0x00180000, PPC_SPEFPU); //
5458 GEN_SPE(evfsctui, evfsctsi, 0x0A, 0x0A, 0x00180000, PPC_SPEFPU); //
5459 GEN_SPE(evfsctuf, evfsctsf, 0x0B, 0x0A, 0x00180000, PPC_SPEFPU); //
5460 GEN_SPE(evfsctuiz, speundef, 0x0C, 0x0A, 0x00180000, PPC_SPEFPU); //
5461 GEN_SPE(evfsctsiz, speundef, 0x0D, 0x0A, 0x00180000, PPC_SPEFPU); //
5462 GEN_SPE(evfststgt, evfststlt, 0x0E, 0x0A, 0x00600000, PPC_SPEFPU); //
5463 GEN_SPE(evfststeq, speundef, 0x0F, 0x0A, 0x00600000, PPC_SPEFPU); //
5465 /* Single precision floating-point operations */
5466 /* Arithmetic */
5467 GEN_SPEOP_ARITH2(efsadd);
5468 GEN_SPEOP_ARITH2(efssub);
5469 GEN_SPEOP_ARITH2(efsmul);
5470 GEN_SPEOP_ARITH2(efsdiv);
5471 GEN_SPEOP_ARITH1(efsabs);
5472 GEN_SPEOP_ARITH1(efsnabs);
5473 GEN_SPEOP_ARITH1(efsneg);
5474 /* Conversion */
5475 GEN_SPEFPUOP_CONV(efscfui);
5476 GEN_SPEFPUOP_CONV(efscfsi);
5477 GEN_SPEFPUOP_CONV(efscfuf);
5478 GEN_SPEFPUOP_CONV(efscfsf);
5479 GEN_SPEFPUOP_CONV(efsctui);
5480 GEN_SPEFPUOP_CONV(efsctsi);
5481 GEN_SPEFPUOP_CONV(efsctuf);
5482 GEN_SPEFPUOP_CONV(efsctsf);
5483 GEN_SPEFPUOP_CONV(efsctuiz);
5484 GEN_SPEFPUOP_CONV(efsctsiz);
5485 GEN_SPEFPUOP_CONV(efscfd);
5486 /* Comparison */
5487 GEN_SPEOP_COMP(efscmpgt);
5488 GEN_SPEOP_COMP(efscmplt);
5489 GEN_SPEOP_COMP(efscmpeq);
5490 GEN_SPEOP_COMP(efststgt);
5491 GEN_SPEOP_COMP(efststlt);
5492 GEN_SPEOP_COMP(efststeq);
5494 /* Opcodes definitions */
5495 GEN_SPE(efsadd, efssub, 0x00, 0x0A, 0x00000000, PPC_SPEFPU); //
5496 GEN_SPE(efsabs, efsnabs, 0x02, 0x0B, 0x0000F800, PPC_SPEFPU); //
5497 GEN_SPE(efsneg, speundef, 0x03, 0x0B, 0x0000F800, PPC_SPEFPU); //
5498 GEN_SPE(efsmul, efsdiv, 0x04, 0x0B, 0x00000000, PPC_SPEFPU); //
5499 GEN_SPE(efscmpgt, efscmplt, 0x06, 0x0B, 0x00600000, PPC_SPEFPU); //
5500 GEN_SPE(efscmpeq, efscfd, 0x07, 0x0B, 0x00600000, PPC_SPEFPU); //
5501 GEN_SPE(efscfui, efscfsi, 0x08, 0x0B, 0x00180000, PPC_SPEFPU); //
5502 GEN_SPE(efscfuf, efscfsf, 0x09, 0x0B, 0x00180000, PPC_SPEFPU); //
5503 GEN_SPE(efsctui, efsctsi, 0x0A, 0x0B, 0x00180000, PPC_SPEFPU); //
5504 GEN_SPE(efsctuf, efsctsf, 0x0B, 0x0B, 0x00180000, PPC_SPEFPU); //
5505 GEN_SPE(efsctuiz, efsctsiz, 0x0C, 0x0B, 0x00180000, PPC_SPEFPU); //
5506 GEN_SPE(efststgt, efststlt, 0x0E, 0x0B, 0x00600000, PPC_SPEFPU); //
5507 GEN_SPE(efststeq, speundef, 0x0F, 0x0B, 0x00600000, PPC_SPEFPU); //
5509 /* Double precision floating-point operations */
5510 /* Arithmetic */
5511 GEN_SPEOP_ARITH2(efdadd);
5512 GEN_SPEOP_ARITH2(efdsub);
5513 GEN_SPEOP_ARITH2(efdmul);
5514 GEN_SPEOP_ARITH2(efddiv);
5515 GEN_SPEOP_ARITH1(efdabs);
5516 GEN_SPEOP_ARITH1(efdnabs);
5517 GEN_SPEOP_ARITH1(efdneg);
5518 /* Conversion */
5520 GEN_SPEFPUOP_CONV(efdcfui);
5521 GEN_SPEFPUOP_CONV(efdcfsi);
5522 GEN_SPEFPUOP_CONV(efdcfuf);
5523 GEN_SPEFPUOP_CONV(efdcfsf);
5524 GEN_SPEFPUOP_CONV(efdctui);
5525 GEN_SPEFPUOP_CONV(efdctsi);
5526 GEN_SPEFPUOP_CONV(efdctuf);
5527 GEN_SPEFPUOP_CONV(efdctsf);
5528 GEN_SPEFPUOP_CONV(efdctuiz);
5529 GEN_SPEFPUOP_CONV(efdctsiz);
5530 GEN_SPEFPUOP_CONV(efdcfs);
5531 GEN_SPEFPUOP_CONV(efdcfuid);
5532 GEN_SPEFPUOP_CONV(efdcfsid);
5533 GEN_SPEFPUOP_CONV(efdctuidz);
5534 GEN_SPEFPUOP_CONV(efdctsidz);
5535 /* Comparison */
5536 GEN_SPEOP_COMP(efdcmpgt);
5537 GEN_SPEOP_COMP(efdcmplt);
5538 GEN_SPEOP_COMP(efdcmpeq);
5539 GEN_SPEOP_COMP(efdtstgt);
5540 GEN_SPEOP_COMP(efdtstlt);
5541 GEN_SPEOP_COMP(efdtsteq);
5543 /* Opcodes definitions */
5544 GEN_SPE(efdadd, efdsub, 0x10, 0x0B, 0x00000000, PPC_SPEFPU); //
5545 GEN_SPE(efdcfuid, efdcfsid, 0x11, 0x0B, 0x00180000, PPC_SPEFPU); //
5546 GEN_SPE(efdabs, efdnabs, 0x12, 0x0B, 0x0000F800, PPC_SPEFPU); //
5547 GEN_SPE(efdneg, speundef, 0x13, 0x0B, 0x0000F800, PPC_SPEFPU); //
5548 GEN_SPE(efdmul, efddiv, 0x14, 0x0B, 0x00000000, PPC_SPEFPU); //
5549 GEN_SPE(efdctuidz, efdctsidz, 0x15, 0x0B, 0x00180000, PPC_SPEFPU); //
5550 GEN_SPE(efdcmpgt, efdcmplt, 0x16, 0x0B, 0x00600000, PPC_SPEFPU); //
5551 GEN_SPE(efdcmpeq, efdcfs, 0x17, 0x0B, 0x00600000, PPC_SPEFPU); //
5552 GEN_SPE(efdcfui, efdcfsi, 0x18, 0x0B, 0x00180000, PPC_SPEFPU); //
5553 GEN_SPE(efdcfuf, efdcfsf, 0x19, 0x0B, 0x00180000, PPC_SPEFPU); //
5554 GEN_SPE(efdctui, efdctsi, 0x1A, 0x0B, 0x00180000, PPC_SPEFPU); //
5555 GEN_SPE(efdctuf, efdctsf, 0x1B, 0x0B, 0x00180000, PPC_SPEFPU); //
5556 GEN_SPE(efdctuiz, speundef, 0x1C, 0x0B, 0x00180000, PPC_SPEFPU); //
5557 GEN_SPE(efdctsiz, speundef, 0x1D, 0x0B, 0x00180000, PPC_SPEFPU); //
5558 GEN_SPE(efdtstgt, efdtstlt, 0x1E, 0x0B, 0x00600000, PPC_SPEFPU); //
5559 GEN_SPE(efdtsteq, speundef, 0x1F, 0x0B, 0x00600000, PPC_SPEFPU); //
5560 #endif
5562 /* End opcode list */
5563 GEN_OPCODE_MARK(end);
5565 #include "translate_init.c"
5567 /*****************************************************************************/
5568 /* Misc PowerPC helpers */
5569 static inline uint32_t load_xer (CPUState *env)
5571 return (xer_so << XER_SO) |
5572 (xer_ov << XER_OV) |
5573 (xer_ca << XER_CA) |
5574 (xer_bc << XER_BC) |
5575 (xer_cmp << XER_CMP);
5578 void cpu_dump_state(CPUState *env, FILE *f,
5579 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
5580 int flags)
5582 #if defined(TARGET_PPC64) || 1
5583 #define FILL ""
5584 #define RGPL 4
5585 #define RFPL 4
5586 #else
5587 #define FILL " "
5588 #define RGPL 8
5589 #define RFPL 4
5590 #endif
5592 int i;
5594 cpu_fprintf(f, "NIP " ADDRX " LR " ADDRX " CTR " ADDRX "\n",
5595 env->nip, env->lr, env->ctr);
5596 cpu_fprintf(f, "MSR " REGX FILL " XER %08x "
5597 #if !defined(NO_TIMER_DUMP)
5598 "TB %08x %08x "
5599 #if !defined(CONFIG_USER_ONLY)
5600 "DECR %08x"
5601 #endif
5602 #endif
5603 "\n",
5604 do_load_msr(env), load_xer(env)
5605 #if !defined(NO_TIMER_DUMP)
5606 , cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
5607 #if !defined(CONFIG_USER_ONLY)
5608 , cpu_ppc_load_decr(env)
5609 #endif
5610 #endif
5612 for (i = 0; i < 32; i++) {
5613 if ((i & (RGPL - 1)) == 0)
5614 cpu_fprintf(f, "GPR%02d", i);
5615 cpu_fprintf(f, " " REGX, env->gpr[i]);
5616 if ((i & (RGPL - 1)) == (RGPL - 1))
5617 cpu_fprintf(f, "\n");
5619 cpu_fprintf(f, "CR ");
5620 for (i = 0; i < 8; i++)
5621 cpu_fprintf(f, "%01x", env->crf[i]);
5622 cpu_fprintf(f, " [");
5623 for (i = 0; i < 8; i++) {
5624 char a = '-';
5625 if (env->crf[i] & 0x08)
5626 a = 'L';
5627 else if (env->crf[i] & 0x04)
5628 a = 'G';
5629 else if (env->crf[i] & 0x02)
5630 a = 'E';
5631 cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
5633 cpu_fprintf(f, " ] " FILL "RES " REGX "\n", env->reserve);
5634 for (i = 0; i < 32; i++) {
5635 if ((i & (RFPL - 1)) == 0)
5636 cpu_fprintf(f, "FPR%02d", i);
5637 cpu_fprintf(f, " %016" PRIx64, *((uint64_t *)&env->fpr[i]));
5638 if ((i & (RFPL - 1)) == (RFPL - 1))
5639 cpu_fprintf(f, "\n");
5641 cpu_fprintf(f, "SRR0 " REGX " SRR1 " REGX " " FILL FILL FILL
5642 "SDR1 " REGX "\n",
5643 env->spr[SPR_SRR0], env->spr[SPR_SRR1], env->sdr1);
5645 #undef RGPL
5646 #undef RFPL
5647 #undef FILL
5650 void cpu_dump_statistics (CPUState *env, FILE*f,
5651 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
5652 int flags)
5654 #if defined(DO_PPC_STATISTICS)
5655 opc_handler_t **t1, **t2, **t3, *handler;
5656 int op1, op2, op3;
5658 t1 = env->opcodes;
5659 for (op1 = 0; op1 < 64; op1++) {
5660 handler = t1[op1];
5661 if (is_indirect_opcode(handler)) {
5662 t2 = ind_table(handler);
5663 for (op2 = 0; op2 < 32; op2++) {
5664 handler = t2[op2];
5665 if (is_indirect_opcode(handler)) {
5666 t3 = ind_table(handler);
5667 for (op3 = 0; op3 < 32; op3++) {
5668 handler = t3[op3];
5669 if (handler->count == 0)
5670 continue;
5671 cpu_fprintf(f, "%02x %02x %02x (%02x %04d) %16s: "
5672 "%016llx %lld\n",
5673 op1, op2, op3, op1, (op3 << 5) | op2,
5674 handler->oname,
5675 handler->count, handler->count);
5677 } else {
5678 if (handler->count == 0)
5679 continue;
5680 cpu_fprintf(f, "%02x %02x (%02x %04d) %16s: "
5681 "%016llx %lld\n",
5682 op1, op2, op1, op2, handler->oname,
5683 handler->count, handler->count);
5686 } else {
5687 if (handler->count == 0)
5688 continue;
5689 cpu_fprintf(f, "%02x (%02x ) %16s: %016llx %lld\n",
5690 op1, op1, handler->oname,
5691 handler->count, handler->count);
5694 #endif
5697 /*****************************************************************************/
5698 static inline int gen_intermediate_code_internal (CPUState *env,
5699 TranslationBlock *tb,
5700 int search_pc)
5702 DisasContext ctx, *ctxp = &ctx;
5703 opc_handler_t **table, *handler;
5704 target_ulong pc_start;
5705 uint16_t *gen_opc_end;
5706 int j, lj = -1;
5708 pc_start = tb->pc;
5709 gen_opc_ptr = gen_opc_buf;
5710 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
5711 gen_opparam_ptr = gen_opparam_buf;
5712 nb_gen_labels = 0;
5713 ctx.nip = pc_start;
5714 ctx.tb = tb;
5715 ctx.exception = EXCP_NONE;
5716 ctx.spr_cb = env->spr_cb;
5717 #if defined(CONFIG_USER_ONLY)
5718 ctx.mem_idx = msr_le;
5719 #if defined(TARGET_PPC64)
5720 ctx.mem_idx |= msr_sf << 1;
5721 #endif
5722 #else
5723 ctx.supervisor = 1 - msr_pr;
5724 ctx.mem_idx = ((1 - msr_pr) << 1) | msr_le;
5725 #if defined(TARGET_PPC64)
5726 ctx.mem_idx |= msr_sf << 2;
5727 #endif
5728 #endif
5729 #if defined(TARGET_PPC64)
5730 ctx.sf_mode = msr_sf;
5731 #endif
5732 ctx.fpu_enabled = msr_fp;
5733 #if defined(TARGET_PPCSPE)
5734 ctx.spe_enabled = msr_spe;
5735 #endif
5736 ctx.singlestep_enabled = env->singlestep_enabled;
5737 #if defined (DO_SINGLE_STEP) && 0
5738 /* Single step trace mode */
5739 msr_se = 1;
5740 #endif
5741 /* Set env in case of segfault during code fetch */
5742 while (ctx.exception == EXCP_NONE && gen_opc_ptr < gen_opc_end) {
5743 if (unlikely(env->nb_breakpoints > 0)) {
5744 for (j = 0; j < env->nb_breakpoints; j++) {
5745 if (env->breakpoints[j] == ctx.nip) {
5746 gen_update_nip(&ctx, ctx.nip);
5747 gen_op_debug();
5748 break;
5752 if (unlikely(search_pc)) {
5753 j = gen_opc_ptr - gen_opc_buf;
5754 if (lj < j) {
5755 lj++;
5756 while (lj < j)
5757 gen_opc_instr_start[lj++] = 0;
5758 gen_opc_pc[lj] = ctx.nip;
5759 gen_opc_instr_start[lj] = 1;
5762 #if defined PPC_DEBUG_DISAS
5763 if (loglevel & CPU_LOG_TB_IN_ASM) {
5764 fprintf(logfile, "----------------\n");
5765 fprintf(logfile, "nip=" ADDRX " super=%d ir=%d\n",
5766 ctx.nip, 1 - msr_pr, msr_ir);
5768 #endif
5769 ctx.opcode = ldl_code(ctx.nip);
5770 if (msr_le) {
5771 ctx.opcode = ((ctx.opcode & 0xFF000000) >> 24) |
5772 ((ctx.opcode & 0x00FF0000) >> 8) |
5773 ((ctx.opcode & 0x0000FF00) << 8) |
5774 ((ctx.opcode & 0x000000FF) << 24);
5776 #if defined PPC_DEBUG_DISAS
5777 if (loglevel & CPU_LOG_TB_IN_ASM) {
5778 fprintf(logfile, "translate opcode %08x (%02x %02x %02x) (%s)\n",
5779 ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
5780 opc3(ctx.opcode), msr_le ? "little" : "big");
5782 #endif
5783 ctx.nip += 4;
5784 table = env->opcodes;
5785 handler = table[opc1(ctx.opcode)];
5786 if (is_indirect_opcode(handler)) {
5787 table = ind_table(handler);
5788 handler = table[opc2(ctx.opcode)];
5789 if (is_indirect_opcode(handler)) {
5790 table = ind_table(handler);
5791 handler = table[opc3(ctx.opcode)];
5794 /* Is opcode *REALLY* valid ? */
5795 if (unlikely(handler->handler == &gen_invalid)) {
5796 if (loglevel > 0) {
5797 fprintf(logfile, "invalid/unsupported opcode: "
5798 "%02x - %02x - %02x (%08x) 0x" ADDRX " %d\n",
5799 opc1(ctx.opcode), opc2(ctx.opcode),
5800 opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, msr_ir);
5801 } else {
5802 printf("invalid/unsupported opcode: "
5803 "%02x - %02x - %02x (%08x) 0x" ADDRX " %d\n",
5804 opc1(ctx.opcode), opc2(ctx.opcode),
5805 opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, msr_ir);
5807 } else {
5808 if (unlikely((ctx.opcode & handler->inval) != 0)) {
5809 if (loglevel > 0) {
5810 fprintf(logfile, "invalid bits: %08x for opcode: "
5811 "%02x -%02x - %02x (%08x) 0x" ADDRX "\n",
5812 ctx.opcode & handler->inval, opc1(ctx.opcode),
5813 opc2(ctx.opcode), opc3(ctx.opcode),
5814 ctx.opcode, ctx.nip - 4);
5815 } else {
5816 printf("invalid bits: %08x for opcode: "
5817 "%02x -%02x - %02x (%08x) 0x" ADDRX "\n",
5818 ctx.opcode & handler->inval, opc1(ctx.opcode),
5819 opc2(ctx.opcode), opc3(ctx.opcode),
5820 ctx.opcode, ctx.nip - 4);
5822 RET_INVAL(ctxp);
5823 break;
5826 (*(handler->handler))(&ctx);
5827 #if defined(DO_PPC_STATISTICS)
5828 handler->count++;
5829 #endif
5830 /* Check trace mode exceptions */
5831 if (unlikely((msr_be && ctx.exception == EXCP_BRANCH) ||
5832 /* Check in single step trace mode
5833 * we need to stop except if:
5834 * - rfi, trap or syscall
5835 * - first instruction of an exception handler
5837 (msr_se && (ctx.nip < 0x100 ||
5838 ctx.nip > 0xF00 ||
5839 (ctx.nip & 0xFC) != 0x04) &&
5840 ctx.exception != EXCP_SYSCALL &&
5841 ctx.exception != EXCP_SYSCALL_USER &&
5842 ctx.exception != EXCP_TRAP))) {
5843 RET_EXCP(ctxp, EXCP_TRACE, 0);
5845 /* if we reach a page boundary or are single stepping, stop
5846 * generation
5848 if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
5849 (env->singlestep_enabled))) {
5850 break;
5852 #if defined (DO_SINGLE_STEP)
5853 break;
5854 #endif
5856 if (ctx.exception == EXCP_NONE) {
5857 gen_goto_tb(&ctx, 0, ctx.nip);
5858 } else if (ctx.exception != EXCP_BRANCH) {
5859 gen_op_reset_T0();
5860 /* Generate the return instruction */
5861 gen_op_exit_tb();
5863 *gen_opc_ptr = INDEX_op_end;
5864 if (unlikely(search_pc)) {
5865 j = gen_opc_ptr - gen_opc_buf;
5866 lj++;
5867 while (lj <= j)
5868 gen_opc_instr_start[lj++] = 0;
5869 tb->size = 0;
5870 } else {
5871 tb->size = ctx.nip - pc_start;
5873 #if defined(DEBUG_DISAS)
5874 if (loglevel & CPU_LOG_TB_CPU) {
5875 fprintf(logfile, "---------------- excp: %04x\n", ctx.exception);
5876 cpu_dump_state(env, logfile, fprintf, 0);
5878 if (loglevel & CPU_LOG_TB_IN_ASM) {
5879 int flags;
5880 flags = msr_le;
5881 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
5882 target_disas(logfile, pc_start, ctx.nip - pc_start, flags);
5883 fprintf(logfile, "\n");
5885 if (loglevel & CPU_LOG_TB_OP) {
5886 fprintf(logfile, "OP:\n");
5887 dump_ops(gen_opc_buf, gen_opparam_buf);
5888 fprintf(logfile, "\n");
5890 #endif
5891 return 0;
5894 int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
5896 return gen_intermediate_code_internal(env, tb, 0);
5899 int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
5901 return gen_intermediate_code_internal(env, tb, 1);