2 * PPC emulation for qemu: main translation routines.
4 * Copyright (c) 2003 Jocelyn Mayer
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include "dyngen-exec.h"
25 //#define DO_SINGLE_STEP
26 //#define DO_STEP_FLUSH
29 #define DEF(s, n, copy_size) INDEX_op_ ## s,
35 static uint16_t *gen_opc_ptr;
36 static uint32_t *gen_opparam_ptr;
40 typedef void (GenOpFunc)(void);
42 #define GEN8(func, NAME) \
43 static GenOpFunc *NAME ## _table [8] = {\
44 NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3,\
45 NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7,\
47 static inline void func(int n)\
52 #define GEN32(func, NAME) \
53 static GenOpFunc *NAME ## _table [32] = {\
54 NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3,\
55 NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7,\
56 NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11,\
57 NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,\
58 NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,\
59 NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,\
60 NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,\
61 NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,\
63 static inline void func(int n)\
68 GEN8(gen_op_load_crf_T0, gen_op_load_crf_T0_crf)
69 GEN8(gen_op_load_crf_T1, gen_op_load_crf_T1_crf)
70 GEN8(gen_op_store_T0_crf, gen_op_store_T0_crf_crf)
71 GEN8(gen_op_store_T1_crf, gen_op_store_T1_crf_crf)
73 GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr)
74 GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr)
75 GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr)
77 GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr)
78 GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr)
79 GEN32(gen_op_store_T2_gpr, gen_op_store_T2_gpr_gpr)
81 GEN32(gen_op_load_FT0_fpr, gen_op_load_FT0_fpr)
82 GEN32(gen_op_store_FT0_fpr, gen_op_store_FT0_fpr)
84 static uint8_t spr_access[1024 / 2];
86 /* internal defines */
87 typedef struct DisasContext {
88 struct TranslationBlock *tb;
98 typedef struct opc_handler_t {
102 void (*handler)(DisasContext *ctx);
105 #define SET_RETVAL(n) \
108 ctx->exception = (n); \
113 #define GET_RETVAL(func, __opcode) \
119 #define GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
120 static void gen_##name (DisasContext *ctx); \
121 GEN_OPCODE(name, opc1, opc2, opc3, inval, type); \
122 static void gen_##name (DisasContext *ctx)
124 /* Instruction types */
126 PPC_INTEGER = 0x0001, /* CPU has integer operations instructions */
127 PPC_FLOAT = 0x0002, /* CPU has floating point operations instructions */
128 PPC_FLOW = 0x0004, /* CPU has flow control instructions */
129 PPC_MEM = 0x0008, /* CPU has virtual memory instructions */
130 PPC_MISC = 0x0010, /* CPU has spr/msr access instructions */
131 PPC_EXTERN = 0x0020, /* CPU has external control instructions */
132 PPC_SEGMENT = 0x0040, /* CPU has memory segment instructions */
135 typedef struct opcode_t {
136 unsigned char opc1, opc2, opc3;
138 opc_handler_t handler;
141 /* XXX: move that elsewhere */
142 extern FILE *logfile;
145 /* XXX: shouldn't stay all alone here ! */
146 static int reserve = 0;
148 /*** Instruction decoding ***/
149 #define EXTRACT_HELPER(name, shift, nb) \
150 static inline uint32_t name (uint32_t opcode) \
152 return (opcode >> (shift)) & ((1 << (nb)) - 1); \
155 #define EXTRACT_SHELPER(name, shift, nb) \
156 static inline int32_t name (uint32_t opcode) \
158 return s_ext16((opcode >> (shift)) & ((1 << (nb)) - 1)); \
162 EXTRACT_HELPER(opc1, 26, 6);
164 EXTRACT_HELPER(opc2, 1, 5);
166 EXTRACT_HELPER(opc3, 6, 5);
167 /* Update Cr0 flags */
168 EXTRACT_HELPER(Rc, 0, 1);
170 EXTRACT_HELPER(rD, 21, 5);
172 EXTRACT_HELPER(rS, 21, 5);
174 EXTRACT_HELPER(rA, 16, 5);
176 EXTRACT_HELPER(rB, 11, 5);
178 EXTRACT_HELPER(rC, 6, 5);
180 EXTRACT_HELPER(crfD, 23, 3);
181 EXTRACT_HELPER(crfS, 18, 3);
182 EXTRACT_HELPER(crbD, 21, 5);
183 EXTRACT_HELPER(crbA, 16, 5);
184 EXTRACT_HELPER(crbB, 11, 5);
186 EXTRACT_HELPER(SPR, 11, 10);
187 /*** Get constants ***/
188 EXTRACT_HELPER(IMM, 12, 8);
189 /* 16 bits signed immediate value */
190 EXTRACT_SHELPER(SIMM, 0, 16);
191 /* 16 bits unsigned immediate value */
192 EXTRACT_HELPER(UIMM, 0, 16);
194 EXTRACT_HELPER(NB, 11, 5);
196 EXTRACT_HELPER(SH, 11, 5);
198 EXTRACT_HELPER(MB, 6, 5);
200 EXTRACT_HELPER(ME, 1, 5);
202 EXTRACT_HELPER(CRM, 12, 8);
203 EXTRACT_HELPER(FM, 17, 8);
204 EXTRACT_HELPER(SR, 16, 4);
205 /*** Jump target decoding ***/
207 EXTRACT_SHELPER(d, 0, 16);
208 /* Immediate address */
209 static inline uint32_t LI (uint32_t opcode)
211 return (opcode >> 0) & 0x03FFFFFC;
214 static inline uint32_t BD (uint32_t opcode)
216 return (opcode >> 0) & 0xFFFC;
219 EXTRACT_HELPER(BO, 21, 5);
220 EXTRACT_HELPER(BI, 16, 5);
221 /* Absolute/relative address */
222 EXTRACT_HELPER(AA, 1, 1);
224 EXTRACT_HELPER(LK, 0, 1);
226 /* Create a mask between <start> and <end> bits */
227 static inline uint32_t MASK (uint32_t start, uint32_t end)
231 ret = (((uint32_t)(-1)) >> (start)) ^ (((uint32_t)(-1) >> (end)) >> 1);
238 #define GEN_OPCODE(name, op1, op2, op3, invl, _typ) \
239 __attribute__ ((section(".opcodes"), unused)) \
240 static opcode_t opc_##name = { \
247 .handler = &gen_##name, \
251 #define GEN_OPCODE_MARK(name) \
252 __attribute__ ((section(".opcodes"), unused)) \
253 static opcode_t opc_##name = { \
259 .inval = 0x00000000, \
264 /* Start opcode list */
265 GEN_OPCODE_MARK(start);
267 /* Invalid instruction */
268 GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, 0)
270 /* Branch to next instruction to force nip update */
271 gen_op_b((uint32_t)ctx->nip);
272 SET_RETVAL(EXCP_INVAL);
275 static opc_handler_t invalid_handler = {
277 .handler = gen_invalid,
280 /*** Integer arithmetic ***/
281 #define __GEN_INT_ARITH2(name, opc1, opc2, opc3, inval) \
282 GEN_HANDLER(name, opc1, opc2, opc3, inval, PPC_INTEGER) \
284 gen_op_load_gpr_T0(rA(ctx->opcode)); \
285 gen_op_load_gpr_T1(rB(ctx->opcode)); \
287 if (Rc(ctx->opcode) != 0) \
289 gen_op_store_T0_gpr(rD(ctx->opcode)); \
293 #define __GEN_INT_ARITH2_O(name, opc1, opc2, opc3, inval) \
294 GEN_HANDLER(name, opc1, opc2, opc3, inval, PPC_INTEGER) \
296 gen_op_load_gpr_T0(rA(ctx->opcode)); \
297 gen_op_load_gpr_T1(rB(ctx->opcode)); \
299 if (Rc(ctx->opcode) != 0) \
300 gen_op_set_Rc0_ov(); \
301 gen_op_store_T0_gpr(rD(ctx->opcode)); \
305 #define __GEN_INT_ARITH1(name, opc1, opc2, opc3) \
306 GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, PPC_INTEGER) \
308 gen_op_load_gpr_T0(rA(ctx->opcode)); \
310 if (Rc(ctx->opcode) != 0) \
312 gen_op_store_T0_gpr(rD(ctx->opcode)); \
315 #define __GEN_INT_ARITH1_O(name, opc1, opc2, opc3) \
316 GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, PPC_INTEGER) \
318 gen_op_load_gpr_T0(rA(ctx->opcode)); \
320 if (Rc(ctx->opcode) != 0) \
321 gen_op_set_Rc0_ov(); \
322 gen_op_store_T0_gpr(rD(ctx->opcode)); \
326 /* Two operands arithmetic functions */
327 #define GEN_INT_ARITH2(name, opc1, opc2, opc3) \
328 __GEN_INT_ARITH2(name, opc1, opc2, opc3, 0x00000000) \
329 __GEN_INT_ARITH2_O(name##o, opc1, opc2, opc3 | 0x10, 0x00000000)
331 /* Two operands arithmetic functions with no overflow allowed */
332 #define GEN_INT_ARITHN(name, opc1, opc2, opc3) \
333 __GEN_INT_ARITH2(name, opc1, opc2, opc3, 0x00000400)
335 /* One operand arithmetic functions */
336 #define GEN_INT_ARITH1(name, opc1, opc2, opc3) \
337 __GEN_INT_ARITH1(name, opc1, opc2, opc3) \
338 __GEN_INT_ARITH1_O(name##o, opc1, opc2, opc3 | 0x10)
340 /* add add. addo addo. */
341 GEN_INT_ARITH2 (add, 0x1F, 0x0A, 0x08);
342 /* addc addc. addco addco. */
343 GEN_INT_ARITH2 (addc, 0x1F, 0x0A, 0x00);
344 /* adde adde. addeo addeo. */
345 GEN_INT_ARITH2 (adde, 0x1F, 0x0A, 0x04);
346 /* addme addme. addmeo addmeo. */
347 GEN_INT_ARITH1 (addme, 0x1F, 0x0A, 0x07);
348 /* addze addze. addzeo addzeo. */
349 GEN_INT_ARITH1 (addze, 0x1F, 0x0A, 0x06);
350 /* divw divw. divwo divwo. */
351 GEN_INT_ARITH2 (divw, 0x1F, 0x0B, 0x0F);
352 /* divwu divwu. divwuo divwuo. */
353 GEN_INT_ARITH2 (divwu, 0x1F, 0x0B, 0x0E);
355 GEN_INT_ARITHN (mulhw, 0x1F, 0x0B, 0x02);
357 GEN_INT_ARITHN (mulhwu, 0x1F, 0x0B, 0x00);
358 /* mullw mullw. mullwo mullwo. */
359 GEN_INT_ARITH2 (mullw, 0x1F, 0x0B, 0x07);
360 /* neg neg. nego nego. */
361 GEN_INT_ARITH1 (neg, 0x1F, 0x08, 0x03);
362 /* subf subf. subfo subfo. */
363 GEN_INT_ARITH2 (subf, 0x1F, 0x08, 0x01);
364 /* subfc subfc. subfco subfco. */
365 GEN_INT_ARITH2 (subfc, 0x1F, 0x08, 0x00);
366 /* subfe subfe. subfeo subfeo. */
367 GEN_INT_ARITH2 (subfe, 0x1F, 0x08, 0x04);
368 /* subfme subfme. subfmeo subfmeo. */
369 GEN_INT_ARITH1 (subfme, 0x1F, 0x08, 0x07);
370 /* subfze subfze. subfzeo subfzeo. */
371 GEN_INT_ARITH1 (subfze, 0x1F, 0x08, 0x06);
373 GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
375 int32_t simm = SIMM(ctx->opcode);
377 if (rA(ctx->opcode) == 0) {
380 gen_op_load_gpr_T0(rA(ctx->opcode));
383 gen_op_store_T0_gpr(rD(ctx->opcode));
387 GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
389 gen_op_load_gpr_T0(rA(ctx->opcode));
390 gen_op_addic(SIMM(ctx->opcode));
391 gen_op_store_T0_gpr(rD(ctx->opcode));
395 GEN_HANDLER(addic_, 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
397 gen_op_load_gpr_T0(rA(ctx->opcode));
398 gen_op_addic(SIMM(ctx->opcode));
400 gen_op_store_T0_gpr(rD(ctx->opcode));
404 GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
406 int32_t simm = SIMM(ctx->opcode);
408 if (rA(ctx->opcode) == 0) {
409 gen_op_set_T0(simm << 16);
411 gen_op_load_gpr_T0(rA(ctx->opcode));
412 gen_op_addi(simm << 16);
414 gen_op_store_T0_gpr(rD(ctx->opcode));
418 GEN_HANDLER(mulli, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
420 gen_op_load_gpr_T0(rA(ctx->opcode));
421 gen_op_mulli(SIMM(ctx->opcode));
422 gen_op_store_T0_gpr(rD(ctx->opcode));
426 GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
428 gen_op_load_gpr_T0(rA(ctx->opcode));
429 gen_op_subfic(SIMM(ctx->opcode));
430 gen_op_store_T0_gpr(rD(ctx->opcode));
434 /*** Integer comparison ***/
435 #define GEN_CMP(name, opc) \
436 GEN_HANDLER(name, 0x1F, 0x00, opc, 0x00400000, PPC_INTEGER) \
438 gen_op_load_gpr_T0(rA(ctx->opcode)); \
439 gen_op_load_gpr_T1(rB(ctx->opcode)); \
441 gen_op_store_T0_crf(crfD(ctx->opcode)); \
448 GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
450 gen_op_load_gpr_T0(rA(ctx->opcode));
451 gen_op_cmpi(SIMM(ctx->opcode));
452 gen_op_store_T0_crf(crfD(ctx->opcode));
458 GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
460 gen_op_load_gpr_T0(rA(ctx->opcode));
461 gen_op_cmpli(UIMM(ctx->opcode));
462 gen_op_store_T0_crf(crfD(ctx->opcode));
466 /*** Integer logical ***/
467 #define __GEN_LOGICAL2(name, opc2, opc3) \
468 GEN_HANDLER(name, 0x1F, opc2, opc3, 0x00000000, PPC_INTEGER) \
470 gen_op_load_gpr_T0(rS(ctx->opcode)); \
471 gen_op_load_gpr_T1(rB(ctx->opcode)); \
473 if (Rc(ctx->opcode) != 0) \
475 gen_op_store_T0_gpr(rA(ctx->opcode)); \
478 #define GEN_LOGICAL2(name, opc) \
479 __GEN_LOGICAL2(name, 0x1C, opc)
481 #define GEN_LOGICAL1(name, opc) \
482 GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, PPC_INTEGER) \
484 gen_op_load_gpr_T0(rS(ctx->opcode)); \
486 if (Rc(ctx->opcode) != 0) \
488 gen_op_store_T0_gpr(rA(ctx->opcode)); \
493 GEN_LOGICAL2(and, 0x00);
495 GEN_LOGICAL2(andc, 0x01);
497 GEN_HANDLER(andi_, 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
499 gen_op_load_gpr_T0(rS(ctx->opcode));
500 gen_op_andi_(UIMM(ctx->opcode));
502 gen_op_store_T0_gpr(rA(ctx->opcode));
506 GEN_HANDLER(andis_, 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
508 gen_op_load_gpr_T0(rS(ctx->opcode));
509 gen_op_andi_(UIMM(ctx->opcode) << 16);
511 gen_op_store_T0_gpr(rA(ctx->opcode));
516 GEN_LOGICAL1(cntlzw, 0x00);
518 GEN_LOGICAL2(eqv, 0x08);
520 GEN_LOGICAL1(extsb, 0x1D);
522 GEN_LOGICAL1(extsh, 0x1C);
524 GEN_LOGICAL2(nand, 0x0E);
526 GEN_LOGICAL2(nor, 0x03);
528 GEN_LOGICAL2(or, 0x0D);
530 GEN_LOGICAL2(orc, 0x0C);
532 GEN_LOGICAL2(xor, 0x09);
534 GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
536 uint32_t uimm = UIMM(ctx->opcode);
540 if (rA(ctx->opcode) != rS(ctx->opcode)) {
541 gen_op_load_gpr_T0(rS(ctx->opcode));
542 gen_op_store_T0_gpr(rA(ctx->opcode));
547 gen_op_load_gpr_T0(rS(ctx->opcode));
549 gen_op_store_T0_gpr(rA(ctx->opcode));
554 GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
556 uint32_t uimm = UIMM(ctx->opcode);
560 if (rA(ctx->opcode) != rS(ctx->opcode)) {
561 gen_op_load_gpr_T0(rS(ctx->opcode));
562 gen_op_store_T0_gpr(rA(ctx->opcode));
567 gen_op_load_gpr_T0(rS(ctx->opcode));
568 gen_op_ori(uimm << 16);
569 gen_op_store_T0_gpr(rA(ctx->opcode));
574 GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
576 gen_op_load_gpr_T0(rS(ctx->opcode));
577 gen_op_xori(UIMM(ctx->opcode));
578 gen_op_store_T0_gpr(rA(ctx->opcode));
583 GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
585 gen_op_load_gpr_T0(rS(ctx->opcode));
586 gen_op_xori(UIMM(ctx->opcode) << 16);
587 gen_op_store_T0_gpr(rA(ctx->opcode));
591 /*** Integer rotate ***/
592 /* rlwimi & rlwimi. */
593 GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
597 mb = MB(ctx->opcode);
598 me = ME(ctx->opcode);
599 gen_op_load_gpr_T0(rS(ctx->opcode));
600 gen_op_rlwimi(SH(ctx->opcode), MASK(mb, me), ~MASK(mb, me));
601 if (Rc(ctx->opcode) != 0)
603 gen_op_store_T0_gpr(rA(ctx->opcode));
606 /* rlwinm & rlwinm. */
607 GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
611 sh = SH(ctx->opcode);
612 mb = MB(ctx->opcode);
613 me = ME(ctx->opcode);
614 gen_op_load_gpr_T0(rS(ctx->opcode));
616 fprintf(logfile, "%s sh=%u mb=%u me=%u MASK=0x%08x\n",
617 __func__, sh, mb, me, MASK(mb, me));
623 } else if (me == (31 - sh)) {
626 } else if (sh == 0) {
627 gen_op_andi_(MASK(0, me));
630 } else if (me == 31) {
631 if (sh == (32 - mb)) {
634 } else if (sh == 0) {
635 gen_op_andi_(MASK(mb, 31));
639 gen_op_rlwinm(sh, MASK(mb, me));
641 if (Rc(ctx->opcode) != 0)
643 gen_op_store_T0_gpr(rA(ctx->opcode));
647 GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
651 mb = MB(ctx->opcode);
652 me = ME(ctx->opcode);
653 gen_op_load_gpr_T0(rS(ctx->opcode));
654 gen_op_load_gpr_T1(rB(ctx->opcode));
655 if (mb == 0 && me == 31) {
659 gen_op_rlwnm(MASK(mb, me));
661 if (Rc(ctx->opcode) != 0)
663 gen_op_store_T0_gpr(rA(ctx->opcode));
667 /*** Integer shift ***/
669 __GEN_LOGICAL2(slw, 0x18, 0x00);
671 __GEN_LOGICAL2(sraw, 0x18, 0x18);
673 GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER)
675 gen_op_load_gpr_T0(rS(ctx->opcode));
676 gen_op_srawi(SH(ctx->opcode), MASK(32 - SH(ctx->opcode), 31));
677 if (Rc(ctx->opcode) != 0)
679 gen_op_store_T0_gpr(rA(ctx->opcode));
683 __GEN_LOGICAL2(srw, 0x18, 0x10);
685 /*** Floating-Point arithmetic ***/
687 GEN_HANDLER(fadd, 0x3F, 0x15, 0xFF, 0x000007C0, PPC_FLOAT)
689 SET_RETVAL(EXCP_INVAL);
693 GEN_HANDLER(fadds, 0x3B, 0x15, 0xFF, 0x000007C0, PPC_FLOAT)
695 SET_RETVAL(EXCP_INVAL);
699 GEN_HANDLER(fdiv, 0x3F, 0x12, 0xFF, 0x000007C0, PPC_FLOAT)
701 SET_RETVAL(EXCP_INVAL);
705 GEN_HANDLER(fdivs, 0x3B, 0x12, 0xFF, 0x000007C0, PPC_FLOAT)
707 SET_RETVAL(EXCP_INVAL);
711 GEN_HANDLER(fmul, 0x3F, 0x19, 0xFF, 0x0000F800, PPC_FLOAT)
713 SET_RETVAL(EXCP_INVAL);
717 GEN_HANDLER(fmuls, 0x3B, 0x19, 0xFF, 0x0000F800, PPC_FLOAT)
719 SET_RETVAL(EXCP_INVAL);
723 GEN_HANDLER(fres, 0x3B, 0x18, 0xFF, 0x001807C0, PPC_FLOAT)
725 SET_RETVAL(EXCP_INVAL);
729 GEN_HANDLER(frsqrte, 0x3F, 0x1A, 0xFF, 0x001807C0, PPC_FLOAT)
731 SET_RETVAL(EXCP_INVAL);
735 GEN_HANDLER(fsel, 0x3F, 0x17, 0xFF, 0x00000000, PPC_FLOAT)
737 SET_RETVAL(EXCP_INVAL);
741 GEN_HANDLER(fsub, 0x3F, 0x14, 0xFF, 0x000007C0, PPC_FLOAT)
743 SET_RETVAL(EXCP_INVAL);
747 GEN_HANDLER(fsubs, 0x3B, 0x14, 0xFF, 0x000007C0, PPC_FLOAT)
749 SET_RETVAL(EXCP_INVAL);
754 GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001807C0, PPC_FLOAT)
756 SET_RETVAL(EXCP_INVAL);
760 GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001807C0, PPC_FLOAT)
762 SET_RETVAL(EXCP_INVAL);
765 /*** Floating-Point multiply-and-add ***/
767 GEN_HANDLER(fmadd, 0x3F, 0x1D, 0xFF, 0x00000000, PPC_FLOAT)
769 SET_RETVAL(EXCP_INVAL);
773 GEN_HANDLER(fmadds, 0x3B, 0x1D, 0xFF, 0x00000000, PPC_FLOAT)
775 SET_RETVAL(EXCP_INVAL);
779 GEN_HANDLER(fmsub, 0x3F, 0x1C, 0xFF, 0x00000000, PPC_FLOAT)
781 SET_RETVAL(EXCP_INVAL);
785 GEN_HANDLER(fmsubs, 0x3B, 0x1C, 0xFF, 0x00000000, PPC_FLOAT)
787 SET_RETVAL(EXCP_INVAL);
791 GEN_HANDLER(fnmadd, 0x3F, 0x1F, 0xFF, 0x00000000, PPC_FLOAT)
793 SET_RETVAL(EXCP_INVAL);
797 GEN_HANDLER(fnmadds, 0x3B, 0x1F, 0xFF, 0x00000000, PPC_FLOAT)
799 SET_RETVAL(EXCP_INVAL);
803 GEN_HANDLER(fnmsub, 0x3F, 0x1E, 0xFF, 0x00000000, PPC_FLOAT)
805 SET_RETVAL(EXCP_INVAL);
809 GEN_HANDLER(fnmsubs, 0x3B, 0x1E, 0xFF, 0x00000000, PPC_FLOAT)
811 SET_RETVAL(EXCP_INVAL);
814 /*** Floating-Point round & convert ***/
816 GEN_HANDLER(fctiw, 0x3F, 0x0E, 0xFF, 0x001F0000, PPC_FLOAT)
818 SET_RETVAL(EXCP_INVAL);
822 GEN_HANDLER(fctiwz, 0x3F, 0x0F, 0xFF, 0x001F0000, PPC_FLOAT)
824 SET_RETVAL(EXCP_INVAL);
828 GEN_HANDLER(frsp, 0x3F, 0x0C, 0xFF, 0x001F0000, PPC_FLOAT)
830 SET_RETVAL(EXCP_INVAL);
833 /*** Floating-Point compare ***/
835 GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT)
837 SET_RETVAL(EXCP_INVAL);
841 GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT)
843 SET_RETVAL(EXCP_INVAL);
846 /*** Floating-Point status & ctrl register ***/
848 GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT)
850 SET_RETVAL(EXCP_INVAL);
854 GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT)
857 gen_op_store_T0_gpr(rD(ctx->opcode));
858 if (Rc(ctx->opcode)) {
865 GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT)
867 SET_RETVAL(EXCP_INVAL);
871 GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT)
873 SET_RETVAL(EXCP_INVAL);
877 GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT)
879 gen_op_load_gpr_T0(rB(ctx->opcode));
880 gen_op_store_fpscr(FM(ctx->opcode));
881 if (Rc(ctx->opcode)) {
888 GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT)
890 SET_RETVAL(EXCP_INVAL);
893 /*** Integer load ***/
894 #define GEN_ILDZ(width, opc) \
895 GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
897 uint32_t simm = SIMM(ctx->opcode); \
898 if (rA(ctx->opcode) == 0) { \
899 gen_op_l##width##_z(simm); \
901 gen_op_load_gpr_T0(rA(ctx->opcode)); \
902 gen_op_l##width (simm); \
904 gen_op_store_T1_gpr(rD(ctx->opcode)); \
908 #define GEN_ILDZU(width, opc) \
909 GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
911 if (rA(ctx->opcode) == 0 || \
912 rA(ctx->opcode) == rD(ctx->opcode)) \
913 SET_RETVAL(EXCP_INVAL); \
914 gen_op_load_gpr_T0(rA(ctx->opcode)); \
915 gen_op_l##width(SIMM(ctx->opcode)); \
916 gen_op_store_T1_gpr(rD(ctx->opcode)); \
917 gen_op_store_T0_gpr(rA(ctx->opcode)); \
921 #define GEN_ILDZUX(width, opc) \
922 GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \
924 if (rA(ctx->opcode) == 0 || \
925 rA(ctx->opcode) == rD(ctx->opcode)) \
926 SET_RETVAL(EXCP_INVAL); \
927 gen_op_load_gpr_T0(rA(ctx->opcode)); \
928 gen_op_load_gpr_T1(rB(ctx->opcode)); \
929 gen_op_l##width##x(); \
930 gen_op_store_T1_gpr(rD(ctx->opcode)); \
931 gen_op_store_T0_gpr(rA(ctx->opcode)); \
935 #define GEN_ILDZX(width, opc2, opc3) \
936 GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER) \
938 if (rA(ctx->opcode) == 0) { \
939 gen_op_load_gpr_T0(rB(ctx->opcode)); \
940 gen_op_l##width##x_z(); \
942 gen_op_load_gpr_T0(rA(ctx->opcode)); \
943 gen_op_load_gpr_T1(rB(ctx->opcode)); \
944 gen_op_l##width##x(); \
946 gen_op_store_T1_gpr(rD(ctx->opcode)); \
950 #define GEN_ILD(width, op) \
951 GEN_ILDZ(width, op | 0x20) \
952 GEN_ILDZU(width, op | 0x21) \
953 GEN_ILDZUX(width, op | 0x01) \
954 GEN_ILDZX(width, 0x17, op | 0x00)
956 /* lbz lbzu lbzux lbzx */
958 /* lha lhau lhaux lhax */
960 /* lhz lhzu lhzux lhzx */
962 /* lwz lwzu lwzux lwzx */
965 /*** Integer store ***/
966 #define GEN_IST(width, opc) \
967 GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
969 uint32_t simm = SIMM(ctx->opcode); \
970 if (rA(ctx->opcode) == 0) { \
971 gen_op_load_gpr_T0(rS(ctx->opcode)); \
972 gen_op_st##width##_z(simm); \
974 gen_op_load_gpr_T0(rA(ctx->opcode)); \
975 gen_op_load_gpr_T1(rS(ctx->opcode)); \
976 gen_op_st##width(simm); \
981 #define GEN_ISTU(width, opc) \
982 GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
984 if (rA(ctx->opcode) == 0) \
985 SET_RETVAL(EXCP_INVAL); \
986 gen_op_load_gpr_T0(rA(ctx->opcode)); \
987 gen_op_load_gpr_T1(rS(ctx->opcode)); \
988 gen_op_st##width(SIMM(ctx->opcode)); \
989 gen_op_store_T0_gpr(rA(ctx->opcode)); \
993 #define GEN_ISTUX(width, opc) \
994 GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \
996 if (rA(ctx->opcode) == 0) \
997 SET_RETVAL(EXCP_INVAL); \
998 gen_op_load_gpr_T0(rA(ctx->opcode)); \
999 gen_op_load_gpr_T1(rB(ctx->opcode)); \
1000 gen_op_load_gpr_T2(rS(ctx->opcode)); \
1001 gen_op_st##width##x(); \
1002 gen_op_store_T0_gpr(rA(ctx->opcode)); \
1006 #define GEN_ISTX(width, opc2, opc3) \
1007 GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER) \
1009 if (rA(ctx->opcode) == 0) { \
1010 gen_op_load_gpr_T0(rB(ctx->opcode)); \
1011 gen_op_load_gpr_T1(rS(ctx->opcode)); \
1012 gen_op_st##width##x_z(); \
1014 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1015 gen_op_load_gpr_T1(rB(ctx->opcode)); \
1016 gen_op_load_gpr_T2(rS(ctx->opcode)); \
1017 gen_op_st##width##x(); \
1022 #define GEN_ISTO(width, opc) \
1023 GEN_IST(width, opc | 0x20) \
1024 GEN_ISTU(width, opc | 0x21) \
1025 GEN_ISTUX(width, opc | 0x01) \
1026 GEN_ISTX(width, 0x17, opc | 0x00)
1028 /* stb stbu stbux stbx */
1030 /* sth sthu sthux sthx */
1032 /* stw stwu stwux stwx */
1035 /*** Integer load and store with byte reverse ***/
1037 GEN_ILDZX(hbr, 0x16, 0x18);
1039 GEN_ILDZX(wbr, 0x16, 0x10);
1041 GEN_ISTX(hbr, 0x16, 0x1C);
1043 GEN_ISTX(wbr, 0x16, 0x14);
1045 /*** Integer load and store multiple ***/
1047 GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1049 if (rA(ctx->opcode) == 0) {
1052 gen_op_load_gpr_T0(rA(ctx->opcode));
1054 gen_op_lmw(rD(ctx->opcode), SIMM(ctx->opcode));
1059 GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1061 if (rA(ctx->opcode) == 0) {
1064 gen_op_load_gpr_T0(rA(ctx->opcode));
1066 gen_op_stmw(rS(ctx->opcode), SIMM(ctx->opcode));
1070 /*** Integer load and store strings ***/
1072 GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_INTEGER)
1074 int nb = NB(ctx->opcode);
1075 int start = rD(ctx->opcode);
1081 if ((start + nr) > 32) {
1082 /* handle wrap around r0 */
1083 if (rA(ctx->opcode) == 0) {
1086 gen_op_load_gpr_T0(rA(ctx->opcode));
1088 gen_op_lswi(start, 4 * (32 - start));
1089 nb -= 4 * (32 - start);
1092 if (rA(ctx->opcode) == 0) {
1095 gen_op_load_gpr_T0(rA(ctx->opcode));
1097 gen_op_lswi(start, nb);
1102 GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_INTEGER)
1104 gen_op_load_xer_bc();
1105 gen_op_load_gpr_T1(rB(ctx->opcode));
1106 if (rA(ctx->opcode) == 0) {
1109 gen_op_load_gpr_T2(rA(ctx->opcode));
1111 gen_op_lswx(rD(ctx->opcode));
1116 GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_INTEGER)
1118 int nb = NB(ctx->opcode);
1119 int start = rS(ctx->opcode);
1125 if ((start + nr) > 32) {
1126 /* handle wrap around r0 */
1127 if (rA(ctx->opcode) == 0) {
1130 gen_op_load_gpr_T0(rA(ctx->opcode));
1132 gen_op_stswi(start, 4 * (32 - start));
1133 nb -= 4 * (32 - start);
1136 if (rA(ctx->opcode) == 0) {
1139 gen_op_load_gpr_T0(rA(ctx->opcode));
1141 gen_op_stswi(start, nb);
1146 GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_INTEGER)
1148 gen_op_load_xer_bc();
1149 gen_op_load_gpr_T1(rB(ctx->opcode));
1150 if (rA(ctx->opcode) == 0) {
1153 gen_op_load_gpr_T2(rA(ctx->opcode));
1155 gen_op_stswx(rS(ctx->opcode));
1159 /*** Memory synchronisation ***/
1161 GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FF0801, PPC_MEM)
1163 /* Do a branch to next instruction */
1164 gen_op_b((uint32_t)ctx->nip);
1165 SET_RETVAL(EXCP_BRANCH);
1169 GEN_HANDLER(isync, 0x13, 0x16, 0xFF, 0x03FF0801, PPC_MEM)
1171 /* Do a branch to next instruction */
1172 gen_op_b((uint32_t)ctx->nip);
1173 SET_RETVAL(EXCP_BRANCH);
1177 GEN_HANDLER(lwarx, 0x1F, 0x14, 0xFF, 0x00000001, PPC_MEM)
1180 if (rA(ctx->opcode) == 0) {
1181 gen_op_load_gpr_T0(rB(ctx->opcode));
1183 gen_op_set_reservation();
1185 gen_op_load_gpr_T0(rA(ctx->opcode));
1186 gen_op_load_gpr_T1(rB(ctx->opcode));
1188 gen_op_set_reservation();
1190 gen_op_store_T1_gpr(rD(ctx->opcode));
1195 GEN_HANDLER(stwcx_, 0x1F, 0x16, 0x04, 0x00000000, PPC_MEM)
1200 if (rA(ctx->opcode) == 0) {
1201 gen_op_load_gpr_T0(rB(ctx->opcode));
1202 gen_op_load_gpr_T1(rS(ctx->opcode));
1205 gen_op_load_gpr_T0(rA(ctx->opcode));
1206 gen_op_load_gpr_T1(rB(ctx->opcode));
1207 gen_op_load_gpr_T2(rS(ctx->opcode));
1211 gen_op_reset_reservation();
1217 GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x03FF0801, PPC_MEM)
1219 /* Do a branch to next instruction */
1220 gen_op_b((uint32_t)ctx->nip);
1221 SET_RETVAL(EXCP_BRANCH);
1224 /*** Floating-point load ***/
1225 #define GEN_LF(width, opc) \
1226 GEN_HANDLER(lf##width, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT) \
1228 uint32_t simm = SIMM(ctx->opcode); \
1229 if (rA(ctx->opcode) == 0) { \
1230 gen_op_lf##width##_z_FT0(simm); \
1232 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1233 gen_op_lf##width##_FT0(simm); \
1235 gen_op_store_FT0_fpr(rD(ctx->opcode));\
1239 #define GEN_LFU(width, opc) \
1240 GEN_HANDLER(lf##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT) \
1242 if (rA(ctx->opcode) == 0 || \
1243 rA(ctx->opcode) == rD(ctx->opcode)) \
1244 SET_RETVAL(EXCP_INVAL); \
1245 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1246 gen_op_lf##width##_FT0(SIMM(ctx->opcode)); \
1247 gen_op_store_FT0_fpr(rD(ctx->opcode));\
1248 gen_op_store_T0_gpr(rA(ctx->opcode)); \
1252 #define GEN_LFUX(width, opc) \
1253 GEN_HANDLER(lf##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT) \
1255 if (rA(ctx->opcode) == 0 || \
1256 rA(ctx->opcode) == rD(ctx->opcode)) \
1257 SET_RETVAL(EXCP_INVAL); \
1258 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1259 gen_op_load_gpr_T1(rB(ctx->opcode)); \
1260 gen_op_lf##width##x_FT0(); \
1261 gen_op_store_FT0_fpr(rD(ctx->opcode));\
1262 gen_op_store_T0_gpr(rA(ctx->opcode)); \
1266 #define GEN_LFX(width, opc) \
1267 GEN_HANDLER(lf##width##x, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT) \
1269 if (rA(ctx->opcode) == 0) { \
1270 gen_op_load_gpr_T0(rB(ctx->opcode)); \
1271 gen_op_lf##width##x_z_FT0(); \
1273 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1274 gen_op_load_gpr_T1(rB(ctx->opcode)); \
1275 gen_op_lf##width##x_FT0(); \
1277 gen_op_store_FT0_fpr(rD(ctx->opcode));\
1281 #define GEN_LDF(width, opc) \
1282 GEN_LF(width, opc | 0x20) \
1283 GEN_LFU(width, opc | 0x21) \
1284 GEN_LFUX(width, opc | 0x01) \
1285 GEN_LFX(width, opc | 0x00)
1287 /* lfd lfdu lfdux lfdx */
1289 /* lfs lfsu lfsux lfsx */
1292 /*** Floating-point store ***/
1293 #define GEN_STF(width, opc) \
1294 GEN_HANDLER(stf##width, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT) \
1296 uint32_t simm = SIMM(ctx->opcode); \
1297 gen_op_load_FT0_fpr(rS(ctx->opcode));\
1298 if (rA(ctx->opcode) == 0) { \
1299 gen_op_stf##width##_z_FT0(simm); \
1301 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1302 gen_op_stf##width##_FT0(simm); \
1307 #define GEN_STFU(width, opc) \
1308 GEN_HANDLER(stf##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT) \
1310 if (rA(ctx->opcode) == 0) \
1311 SET_RETVAL(EXCP_INVAL); \
1312 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1313 gen_op_load_FT0_fpr(rS(ctx->opcode));\
1314 gen_op_stf##width##_FT0(SIMM(ctx->opcode)); \
1315 gen_op_store_T0_gpr(rA(ctx->opcode)); \
1319 #define GEN_STFUX(width, opc) \
1320 GEN_HANDLER(stf##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT) \
1322 if (rA(ctx->opcode) == 0) \
1323 SET_RETVAL(EXCP_INVAL); \
1324 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1325 gen_op_load_gpr_T1(rB(ctx->opcode)); \
1326 gen_op_load_FT0_fpr(rS(ctx->opcode));\
1327 gen_op_stf##width##x_FT0(); \
1328 gen_op_store_T0_gpr(rA(ctx->opcode)); \
1332 #define GEN_STFX(width, opc) \
1333 GEN_HANDLER(stf##width##x, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT) \
1335 gen_op_load_FT0_fpr(rS(ctx->opcode));\
1336 if (rA(ctx->opcode) == 0) { \
1337 gen_op_load_gpr_T0(rB(ctx->opcode)); \
1338 gen_op_stf##width##x_z_FT0(); \
1340 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1341 gen_op_load_gpr_T1(rB(ctx->opcode)); \
1342 gen_op_stf##width##x_FT0(); \
1347 #define GEN_STOF(width, opc) \
1348 GEN_STF(width, opc | 0x20) \
1349 GEN_STFU(width, opc | 0x21) \
1350 GEN_STFUX(width, opc | 0x01) \
1351 GEN_STFX(width, opc | 0x00)
1353 /* stfd stfdu stfdux stfdx */
1355 /* stfs stfsu stfsux stfsx */
1360 GEN_HANDLER(stfiwx, 0x1F, 0x17, 0x1E, 0x00000001, PPC_FLOAT)
1362 SET_RETVAL(EXCP_INVAL);
1365 /*** Floating-point move ***/
1367 GEN_HANDLER(fabs, 0x3F, 0x08, 0x08, 0x001F0000, PPC_FLOAT)
1369 SET_RETVAL(EXCP_INVAL);
1373 GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT)
1375 SET_RETVAL(EXCP_INVAL);
1379 GEN_HANDLER(fnabs, 0x3F, 0x08, 0x04, 0x001F0000, PPC_FLOAT)
1381 SET_RETVAL(EXCP_INVAL);
1385 GEN_HANDLER(fneg, 0x3F, 0x08, 0x01, 0x001F0000, PPC_FLOAT)
1387 SET_RETVAL(EXCP_INVAL);
1391 #define GEN_BCOND(name, opc1, opc2, opc3, prologue, \
1392 bl_ctr, b_ctr, bl_ctrz, b_ctrz, b, \
1393 bl_ctr_true, b_ctr_true, bl_ctrz_true, b_ctrz_true, bl_true, b_true, \
1394 bl_ctr_false, b_ctr_false, bl_ctrz_false, b_ctrz_false, bl_false, b_false) \
1395 GEN_HANDLER(name, opc1, opc2, opc3, 0x00000000, PPC_FLOW) \
1397 __attribute__ ((unused)) uint32_t target; \
1398 uint32_t bo = BO(ctx->opcode); \
1399 uint32_t bi = BI(ctx->opcode); \
1402 if ((bo & 0x4) == 0) \
1405 /* No CR condition */ \
1406 switch (bo & 0x6) { \
1408 if (LK(ctx->opcode)) { \
1415 if (LK(ctx->opcode)) { \
1424 if (LK(ctx->opcode)) \
1425 gen_op_load_lr((uint32_t)ctx->nip); \
1428 printf("ERROR: %s: unhandled ba case (%d)\n", __func__, bo); \
1429 SET_RETVAL(EXCP_INVAL); \
1433 mask = 1 << (3 - (bi & 0x03)); \
1434 gen_op_load_crf_T0(bi >> 2); \
1436 switch (bo & 0x6) { \
1438 if (LK(ctx->opcode)) { \
1445 if (LK(ctx->opcode)) { \
1453 if (LK(ctx->opcode)) { \
1460 printf("ERROR: %s: unhandled b case (%d)\n", __func__, bo); \
1461 SET_RETVAL(EXCP_INVAL); \
1465 switch (bo & 0x6) { \
1467 if (LK(ctx->opcode)) { \
1474 if (LK(ctx->opcode)) { \
1482 if (LK(ctx->opcode)) { \
1489 printf("ERROR: %s: unhandled bn case (%d)\n", __func__, bo); \
1490 SET_RETVAL(EXCP_INVAL); \
1495 SET_RETVAL(EXCP_BRANCH); \
1499 GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
1501 uint32_t li = s_ext24(LI(ctx->opcode)), target;
1503 if (AA(ctx->opcode) == 0)
1504 target = (uint32_t)ctx->nip + li - 4;
1506 target = s_ext24(LI(ctx->opcode));
1508 if (LK(ctx->opcode))
1509 gen_op_load_lr((uint32_t)ctx->nip);
1510 SET_RETVAL(EXCP_BRANCH);
1513 /* bc bca bcl bcla */
1514 GEN_BCOND(bc, 0x10, 0xFF, 0xFF,
1516 uint32_t li = s_ext16(BD(ctx->opcode));
1517 if (AA(ctx->opcode) == 0) {
1518 target = (uint32_t)ctx->nip + li - 4;
1523 gen_op_bl_ctr((uint32_t)ctx->nip, target),
1524 gen_op_b_ctr((uint32_t)ctx->nip, target),
1525 gen_op_bl_ctrz((uint32_t)ctx->nip, target),
1526 gen_op_b_ctrz((uint32_t)ctx->nip, target),
1528 gen_op_bl_ctr_true((uint32_t)ctx->nip, target, mask),
1529 gen_op_b_ctr_true((uint32_t)ctx->nip, target, mask),
1530 gen_op_bl_ctrz_true((uint32_t)ctx->nip, target, mask),
1531 gen_op_b_ctrz_true((uint32_t)ctx->nip, target, mask),
1532 gen_op_bl_true((uint32_t)ctx->nip, target, mask),
1533 gen_op_b_true((uint32_t)ctx->nip, target, mask),
1534 gen_op_bl_ctr_false((uint32_t)ctx->nip, target, mask),
1535 gen_op_b_ctr_false((uint32_t)ctx->nip, target, mask),
1536 gen_op_bl_ctrz_false((uint32_t)ctx->nip, target, mask),
1537 gen_op_b_ctrz_false((uint32_t)ctx->nip, target, mask),
1538 gen_op_bl_false((uint32_t)ctx->nip, target, mask),
1539 gen_op_b_false((uint32_t)ctx->nip, target, mask));
1542 GEN_BCOND(bcctr, 0x13, 0x10, 0x10, do { } while (0),
1543 gen_op_bctrl_ctr((uint32_t)ctx->nip),
1544 gen_op_bctr_ctr((uint32_t)ctx->nip),
1545 gen_op_bctrl_ctrz((uint32_t)ctx->nip),
1546 gen_op_bctr_ctrz((uint32_t)ctx->nip),
1548 gen_op_bctrl_ctr_true((uint32_t)ctx->nip, mask),
1549 gen_op_bctr_ctr_true((uint32_t)ctx->nip, mask),
1550 gen_op_bctrl_ctrz_true((uint32_t)ctx->nip, mask),
1551 gen_op_bctr_ctrz_true((uint32_t)ctx->nip, mask),
1552 gen_op_bctrl_true((uint32_t)ctx->nip, mask),
1553 gen_op_bctr_true((uint32_t)ctx->nip, mask),
1554 gen_op_bctrl_ctr_false((uint32_t)ctx->nip, mask),
1555 gen_op_bctr_ctr_false((uint32_t)ctx->nip, mask),
1556 gen_op_bctrl_ctrz_false((uint32_t)ctx->nip, mask),
1557 gen_op_bctr_ctrz_false((uint32_t)ctx->nip, mask),
1558 gen_op_bctrl_false((uint32_t)ctx->nip, mask),
1559 gen_op_bctr_false((uint32_t)ctx->nip, mask))
1562 GEN_BCOND(bclr, 0x13, 0x10, 0x00, do { } while (0),
1563 gen_op_blrl_ctr((uint32_t)ctx->nip),
1564 gen_op_blr_ctr((uint32_t)ctx->nip),
1565 gen_op_blrl_ctrz((uint32_t)ctx->nip),
1566 gen_op_blr_ctrz((uint32_t)ctx->nip),
1568 gen_op_blrl_ctr_true((uint32_t)ctx->nip, mask),
1569 gen_op_blr_ctr_true((uint32_t)ctx->nip, mask),
1570 gen_op_blrl_ctrz_true((uint32_t)ctx->nip, mask),
1571 gen_op_blr_ctrz_true((uint32_t)ctx->nip, mask),
1572 gen_op_blrl_true((uint32_t)ctx->nip, mask),
1573 gen_op_blr_true((uint32_t)ctx->nip, mask),
1574 gen_op_blrl_ctr_false((uint32_t)ctx->nip, mask),
1575 gen_op_blr_ctr_false((uint32_t)ctx->nip, mask),
1576 gen_op_blrl_ctrz_false((uint32_t)ctx->nip, mask),
1577 gen_op_blr_ctrz_false((uint32_t)ctx->nip, mask),
1578 gen_op_blrl_false((uint32_t)ctx->nip, mask),
1579 gen_op_blr_false((uint32_t)ctx->nip, mask))
1581 /*** Condition register logical ***/
1582 #define GEN_CRLOGIC(op, opc) \
1583 GEN_HANDLER(cr##op, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER) \
1585 gen_op_load_crf_T0(crbA(ctx->opcode) >> 2); \
1586 gen_op_getbit_T0(3 - (crbA(ctx->opcode) & 0x03)); \
1587 gen_op_load_crf_T1(crbB(ctx->opcode) >> 2); \
1588 gen_op_getbit_T1(3 - (crbB(ctx->opcode) & 0x03)); \
1590 gen_op_load_crf_T1(crbD(ctx->opcode) >> 2); \
1591 gen_op_setcrfbit(~(1 << (3 - (crbD(ctx->opcode) & 0x03))), \
1592 3 - (crbD(ctx->opcode) & 0x03)); \
1593 gen_op_store_T1_crf(crbD(ctx->opcode) >> 2); \
1598 GEN_CRLOGIC(and, 0x08)
1600 GEN_CRLOGIC(andc, 0x04)
1602 GEN_CRLOGIC(eqv, 0x09)
1604 GEN_CRLOGIC(nand, 0x07)
1606 GEN_CRLOGIC(nor, 0x01)
1608 GEN_CRLOGIC(or, 0x0E)
1610 GEN_CRLOGIC(orc, 0x0D)
1612 GEN_CRLOGIC(xor, 0x06)
1614 GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER)
1616 gen_op_load_crf_T0(crfS(ctx->opcode));
1617 gen_op_store_T0_crf(crfD(ctx->opcode));
1621 /*** System linkage ***/
1622 /* rfi (supervisor only) */
1623 GEN_HANDLER(rfi, 0x13, 0x12, 0xFF, 0x03FF8001, PPC_FLOW)
1625 SET_RETVAL(EXCP_INVAL);
1629 GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFFFFD, PPC_FLOW)
1631 gen_op_b((uint32_t)ctx->nip);
1632 SET_RETVAL(EXCP_SYSCALL);
1637 GEN_HANDLER(tw, 0x1F, 0x04, 0xFF, 0x00000001, PPC_FLOW)
1639 SET_RETVAL(EXCP_INVAL);
1643 GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
1645 SET_RETVAL(EXCP_INVAL);
1648 /*** Processor control ***/
1649 static inline int check_spr_access (int spr, int rw, int supervisor)
1651 uint32_t rights = spr_access[spr >> 1] >> (4 * (spr & 1));
1653 rights = rights >> (2 * supervisor);
1654 rights = rights >> rw;
1660 GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC)
1662 gen_op_load_xer_cr();
1663 gen_op_store_T0_crf(crfD(ctx->opcode));
1664 gen_op_clear_xer_cr();
1669 GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x001FF801, PPC_MISC)
1672 gen_op_store_T0_gpr(rD(ctx->opcode));
1677 GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC)
1679 if (!ctx->supervisor)
1680 SET_RETVAL(EXCP_PRIV);
1682 gen_op_store_T0_gpr(rD(ctx->opcode));
1687 GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC)
1689 uint32_t sprn = SPR(ctx->opcode);
1691 if (check_spr_access(sprn, 0, ctx->supervisor) == 0)
1692 SET_RETVAL(EXCP_PRIV);
1693 /* XXX: make this more generic */
1697 fprintf(logfile, "LOAD XER at %p\n", ctx->nip - 1);
1701 case SPR_ENCODE(268):
1702 /* We need to update the time base before reading it */
1703 gen_op_update_tb(ctx->tb_offset);
1706 case SPR_ENCODE(269):
1707 gen_op_update_tb(ctx->tb_offset);
1711 gen_op_load_spr(sprn);
1714 gen_op_store_T0_gpr(rD(ctx->opcode)); //
1719 GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MISC)
1721 uint32_t sprn = SPR(ctx->opcode);
1723 if (check_spr_access(sprn, 0, ctx->supervisor) == 0)
1724 SET_RETVAL(EXCP_PRIV);
1726 case SPR_ENCODE(268):
1727 /* We need to update the time base before reading it */
1728 gen_op_update_tb(ctx->tb_offset);
1731 case SPR_ENCODE(269):
1732 gen_op_update_tb(ctx->tb_offset);
1736 SET_RETVAL(EXCP_INVAL);
1743 GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00100801, PPC_MISC)
1745 gen_op_load_gpr_T0(rS(ctx->opcode));
1746 gen_op_store_cr(CRM(ctx->opcode));
1751 GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC)
1753 if (!ctx->supervisor)
1754 SET_RETVAL(EXCP_PRIV);
1755 gen_op_load_gpr_T0(rS(ctx->opcode));
1757 /* Must stop the translation as machine state (may have) changed */
1758 SET_RETVAL(EXCP_MTMSR);
1762 GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC)
1764 uint32_t sprn = SPR(ctx->opcode);
1766 if (check_spr_access(sprn, 1, ctx->supervisor) == 0)
1767 SET_RETVAL(EXCP_PRIV);
1768 gen_op_load_gpr_T0(rS(ctx->opcode));
1769 if (sprn == SPR_ENCODE(1)) {
1772 gen_op_store_spr(sprn);
1777 /*** Cache management ***/
1778 /* For now, all those will be implemented as nop:
1779 * this is valid, regarding the PowerPC specs...
1782 GEN_HANDLER(dcbf, 0x1F, 0x16, 0x17, 0x03E00001, PPC_MEM)
1787 /* dcbi (Supervisor only) */
1788 GEN_HANDLER(dcbi, 0x1F, 0x16, 0x1F, 0x03E00001, PPC_MEM)
1794 GEN_HANDLER(dcbst, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_MEM)
1800 GEN_HANDLER(dcbt, 0x1F, 0x16, 0x01, 0x03E00001, PPC_MEM)
1806 GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x02, 0x03E00001, PPC_MEM)
1812 GEN_HANDLER(dcbz, 0x1F, 0x16, 0x08, 0x03E00001, PPC_MEM)
1818 GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_MEM)
1825 GEN_HANDLER(dcba, 0x1F, 0x16, 0x07, 0x03E00001, PPC_MEM)
1830 /*** Segment register manipulation ***/
1831 /* Supervisor only: */
1833 GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT)
1835 SET_RETVAL(EXCP_INVAL);
1839 GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x0010F001, PPC_SEGMENT)
1841 SET_RETVAL(EXCP_INVAL);
1845 GEN_HANDLER(mtsr, 0x1F, 0x12, 0x02, 0x0010F801, PPC_SEGMENT)
1847 SET_RETVAL(EXCP_INVAL);
1851 GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x0010F001, PPC_SEGMENT)
1853 SET_RETVAL(EXCP_INVAL);
1856 /*** Lookaside buffer management ***/
1857 /* Optional & supervisor only: */
1859 GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM)
1861 SET_RETVAL(EXCP_INVAL);
1865 GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF8001, PPC_MEM)
1867 SET_RETVAL(EXCP_INVAL);
1871 GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFFC01, PPC_MEM)
1873 SET_RETVAL(EXCP_INVAL);
1876 /*** External control ***/
1879 GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN)
1881 SET_RETVAL(EXCP_INVAL);
1885 GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN)
1887 SET_RETVAL(EXCP_INVAL);
1890 /* End opcode list */
1891 GEN_OPCODE_MARK(end);
1893 /*****************************************************************************/
1896 extern FILE *stderr;
1897 void free (void *p);
1898 int fflush (FILE *f);
1900 /* Main ppc opcodes table:
1901 * at init, all opcodes are invalids
1903 static opc_handler_t *ppc_opcodes[0x40];
1907 PPC_DIRECT = 0, /* Opcode routine */
1908 PPC_INDIRECT = 1, /* Indirect opcode table */
1911 static inline int is_indirect_opcode (void *handler)
1913 return ((unsigned long)handler & 0x03) == PPC_INDIRECT;
1916 static inline opc_handler_t **ind_table(void *handler)
1918 return (opc_handler_t **)((unsigned long)handler & ~3);
1921 /* Opcodes tables creation */
1922 static void fill_new_table (opc_handler_t **table, int len)
1926 for (i = 0; i < len; i++)
1927 table[i] = &invalid_handler;
1930 static int create_new_table (opc_handler_t **table, unsigned char idx)
1932 opc_handler_t **tmp;
1934 tmp = malloc(0x20 * sizeof(opc_handler_t));
1937 fill_new_table(tmp, 0x20);
1938 table[idx] = (opc_handler_t *)((unsigned long)tmp | PPC_INDIRECT);
1943 static int insert_in_table (opc_handler_t **table, unsigned char idx,
1944 opc_handler_t *handler)
1946 if (table[idx] != &invalid_handler)
1948 table[idx] = handler;
1953 static int register_direct_insn (unsigned char idx, opc_handler_t *handler)
1955 if (insert_in_table(ppc_opcodes, idx, handler) < 0) {
1956 fprintf(stderr, "*** ERROR: opcode %02x already assigned in main "
1957 "opcode table\n", idx);
1964 static int register_ind_in_table (opc_handler_t **table,
1965 unsigned char idx1, unsigned char idx2,
1966 opc_handler_t *handler)
1968 if (table[idx1] == &invalid_handler) {
1969 if (create_new_table(table, idx1) < 0) {
1970 fprintf(stderr, "*** ERROR: unable to create indirect table "
1971 "idx=%02x\n", idx1);
1975 if (!is_indirect_opcode(table[idx1])) {
1976 fprintf(stderr, "*** ERROR: idx %02x already assigned to a direct "
1981 if (handler != NULL &&
1982 insert_in_table(ind_table(table[idx1]), idx2, handler) < 0) {
1983 fprintf(stderr, "*** ERROR: opcode %02x already assigned in "
1984 "opcode table %02x\n", idx2, idx1);
1991 static int register_ind_insn (unsigned char idx1, unsigned char idx2,
1992 opc_handler_t *handler)
1996 ret = register_ind_in_table(ppc_opcodes, idx1, idx2, handler);
2001 static int register_dblind_insn (unsigned char idx1, unsigned char idx2,
2002 unsigned char idx3, opc_handler_t *handler)
2004 if (register_ind_in_table(ppc_opcodes, idx1, idx2, NULL) < 0) {
2005 fprintf(stderr, "*** ERROR: unable to join indirect table idx "
2006 "[%02x-%02x]\n", idx1, idx2);
2009 if (register_ind_in_table(ind_table(ppc_opcodes[idx1]), idx2, idx3,
2011 fprintf(stderr, "*** ERROR: unable to insert opcode "
2012 "[%02x-%02x-%02x]\n", idx1, idx2, idx3);
2019 static int register_insn (opcode_t *insn)
2021 if (insn->opc2 != 0xFF) {
2022 if (insn->opc3 != 0xFF) {
2023 if (register_dblind_insn(insn->opc1, insn->opc2, insn->opc3,
2024 &insn->handler) < 0)
2027 if (register_ind_insn(insn->opc1, insn->opc2, &insn->handler) < 0)
2031 if (register_direct_insn(insn->opc1, &insn->handler) < 0)
2038 static int test_opcode_table (opc_handler_t **table, int len)
2042 for (i = 0, count = 0; i < len; i++) {
2043 /* Consistency fixup */
2044 if (table[i] == NULL)
2045 table[i] = &invalid_handler;
2046 if (table[i] != &invalid_handler) {
2047 if (is_indirect_opcode(table[i])) {
2048 tmp = test_opcode_table(ind_table(table[i]), 0x20);
2051 table[i] = &invalid_handler;
2064 static void fix_opcode_tables (void)
2066 if (test_opcode_table(ppc_opcodes, 0x40) == 0)
2067 fprintf(stderr, "*** WARNING: no opcode defined !\n");
2070 #define SPR_RIGHTS(rw, priv) ((2 * (priv)) + (rw))
2071 #define SPR_UR SPR_RIGHTS(0, 0)
2072 #define SPR_UW SPR_RIGHTS(1, 0)
2073 #define SPR_SR SPR_RIGHTS(0, 1)
2074 #define SPR_SW SPR_RIGHTS(1, 1)
2076 #define spr_set_rights(spr, rights) \
2078 spr_access[(spr) >> 1] |= ((rights) << (4 * ((spr) & 1))); \
2081 static void init_spr_rights (void)
2084 spr_set_rights(SPR_ENCODE(1), SPR_UR | SPR_UW | SPR_SR | SPR_SW);
2086 spr_set_rights(SPR_ENCODE(8), SPR_UR | SPR_UW | SPR_SR | SPR_SW);
2088 spr_set_rights(SPR_ENCODE(9), SPR_UR | SPR_UW | SPR_SR | SPR_SW);
2090 spr_set_rights(SPR_ENCODE(268), SPR_UR | SPR_SR);
2092 spr_set_rights(SPR_ENCODE(269), SPR_UR | SPR_SR);
2093 /* DSISR (SPR 18) */
2094 spr_set_rights(SPR_ENCODE(18), SPR_SR | SPR_SW);
2096 spr_set_rights(SPR_ENCODE(19), SPR_SR | SPR_SW);
2098 spr_set_rights(SPR_ENCODE(22), SPR_SR | SPR_SW);
2100 spr_set_rights(SPR_ENCODE(25), SPR_SR | SPR_SW);
2101 /* SPRG0 (SPR 272) */
2102 spr_set_rights(SPR_ENCODE(272), SPR_SR | SPR_SW);
2103 /* SPRG1 (SPR 273) */
2104 spr_set_rights(SPR_ENCODE(273), SPR_SR | SPR_SW);
2105 /* SPRG2 (SPR 274) */
2106 spr_set_rights(SPR_ENCODE(274), SPR_SR | SPR_SW);
2107 /* SPRG3 (SPR 275) */
2108 spr_set_rights(SPR_ENCODE(275), SPR_SR | SPR_SW);
2110 spr_set_rights(SPR_ENCODE(281), SPR_SR | SPR_SW);
2112 spr_set_rights(SPR_ENCODE(282), SPR_SR | SPR_SW);
2113 /* IBAT0U (SPR 528) */
2114 spr_set_rights(SPR_ENCODE(528), SPR_SR | SPR_SW);
2115 /* IBAT0L (SPR 529) */
2116 spr_set_rights(SPR_ENCODE(529), SPR_SR | SPR_SW);
2117 /* IBAT1U (SPR 530) */
2118 spr_set_rights(SPR_ENCODE(530), SPR_SR | SPR_SW);
2119 /* IBAT1L (SPR 531) */
2120 spr_set_rights(SPR_ENCODE(531), SPR_SR | SPR_SW);
2121 /* IBAT2U (SPR 532) */
2122 spr_set_rights(SPR_ENCODE(532), SPR_SR | SPR_SW);
2123 /* IBAT2L (SPR 533) */
2124 spr_set_rights(SPR_ENCODE(533), SPR_SR | SPR_SW);
2125 /* IBAT3U (SPR 534) */
2126 spr_set_rights(SPR_ENCODE(534), SPR_SR | SPR_SW);
2127 /* IBAT3L (SPR 535) */
2128 spr_set_rights(SPR_ENCODE(535), SPR_SR | SPR_SW);
2129 /* DBAT0U (SPR 536) */
2130 spr_set_rights(SPR_ENCODE(536), SPR_SR | SPR_SW);
2131 /* DBAT0L (SPR 537) */
2132 spr_set_rights(SPR_ENCODE(537), SPR_SR | SPR_SW);
2133 /* DBAT1U (SPR 538) */
2134 spr_set_rights(SPR_ENCODE(538), SPR_SR | SPR_SW);
2135 /* DBAT1L (SPR 539) */
2136 spr_set_rights(SPR_ENCODE(539), SPR_SR | SPR_SW);
2137 /* DBAT2U (SPR 540) */
2138 spr_set_rights(SPR_ENCODE(540), SPR_SR | SPR_SW);
2139 /* DBAT2L (SPR 541) */
2140 spr_set_rights(SPR_ENCODE(541), SPR_SR | SPR_SW);
2141 /* DBAT3U (SPR 542) */
2142 spr_set_rights(SPR_ENCODE(542), SPR_SR | SPR_SW);
2143 /* DBAT3L (SPR 543) */
2144 spr_set_rights(SPR_ENCODE(543), SPR_SR | SPR_SW);
2145 /* DABR (SPR 1013) */
2146 spr_set_rights(SPR_ENCODE(1013), SPR_SR | SPR_SW);
2147 /* FPECR (SPR 1022) */
2148 spr_set_rights(SPR_ENCODE(1022), SPR_SR | SPR_SW);
2149 /* PIR (SPR 1023) */
2150 spr_set_rights(SPR_ENCODE(1023), SPR_SR | SPR_SW);
2152 spr_set_rights(SPR_ENCODE(287), SPR_SR);
2154 spr_set_rights(SPR_ENCODE(284), SPR_SW);
2156 spr_set_rights(SPR_ENCODE(285), SPR_SW);
2159 /* PPC "main stream" common instructions */
2160 #define PPC_COMMON (PPC_INTEGER | PPC_FLOAT | PPC_FLOW | PPC_MEM | \
2161 PPC_MISC | PPC_EXTERN | PPC_SEGMENT)
2163 typedef struct ppc_proc_t {
2168 typedef struct ppc_def_t {
2170 unsigned long pvr_mask;
2174 static ppc_proc_t ppc_proc_common = {
2175 .flags = PPC_COMMON,
2179 static ppc_def_t ppc_defs[] =
2184 .pvr_mask = 0x00000000,
2185 .proc = &ppc_proc_common,
2189 static int create_ppc_proc (unsigned long pvr)
2194 fill_new_table(ppc_opcodes, 0x40);
2195 for (i = 0; ; i++) {
2196 if ((ppc_defs[i].pvr & ppc_defs[i].pvr_mask) ==
2197 (pvr & ppc_defs[i].pvr_mask)) {
2198 flags = ppc_defs[i].proc->flags;
2203 for (opc = &opc_start + 1; opc != &opc_end; opc++) {
2204 if ((opc->type & flags) != 0)
2205 if (register_insn(opc) < 0) {
2206 fprintf(stderr, "*** ERROR initializing PPC instruction "
2207 "0x%02x 0x%02x 0x%02x\n", opc->opc1, opc->opc2,
2212 fix_opcode_tables();
2217 /*****************************************************************************/
2218 uint32_t do_load_xer (void);
2220 void cpu_ppc_dump_state(CPUPPCState *env, FILE *f, int flags)
2225 fprintf(logfile, "nip=0x%08x LR=0x%08x CTR=0x%08x XER=0x%08x\n",
2226 env->nip, env->LR, env->CTR, do_load_xer());
2227 for (i = 0; i < 32; i++) {
2229 fprintf(logfile, "GPR%02d:", i);
2230 fprintf(logfile, " %08x", env->gpr[i]);
2232 fprintf(logfile, "\n");
2234 fprintf(logfile, "CR: 0x");
2235 for (i = 0; i < 8; i++)
2236 fprintf(logfile, "%01x", env->crf[i]);
2237 fprintf(logfile, " [");
2238 for (i = 0; i < 8; i++) {
2241 if (env->crf[i] & 0x08)
2243 else if (env->crf[i] & 0x04)
2245 else if (env->crf[i] & 0x02)
2247 fprintf(logfile, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
2249 fprintf(logfile, " ] ");
2250 fprintf(logfile, "TB: 0x%08x %08x\n", env->spr[SPR_ENCODE(269)],
2251 env->spr[SPR_ENCODE(268)]);
2252 for (i = 0; i < 16; i++) {
2254 fprintf(logfile, "FPR%02d:", i);
2255 fprintf(logfile, " %016llx", env->fpr[i]);
2257 fprintf(logfile, "\n");
2263 CPUPPCState *cpu_ppc_init(void)
2269 env = malloc(sizeof(CPUPPCState));
2272 memset(env, 0, sizeof(CPUPPCState));
2274 if (create_ppc_proc(0) < 0)
2281 void cpu_ppc_close(CPUPPCState *env)
2283 /* Should also remove all opcode tables... */
2287 int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
2291 opc_handler_t **table, *handler;
2293 uint16_t *gen_opc_end;
2298 gen_opc_ptr = gen_opc_buf;
2299 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
2300 gen_opparam_ptr = gen_opparam_buf;
2301 ctx.nip = (uint32_t *)pc_start;
2303 ctx.supervisor = msr_ip;
2307 while (ret == 0 && gen_opc_ptr < gen_opc_end) {
2310 fprintf(logfile, "Search PC...\n");
2311 j = gen_opc_ptr - gen_opc_buf;
2315 gen_opc_instr_start[lj++] = 0;
2316 gen_opc_pc[lj] = (uint32_t)ctx.nip;
2317 gen_opc_instr_start[lj] = 1;
2320 ctx.opcode = __be32_to_cpu(*ctx.nip);
2323 fprintf(logfile, "----------------\n");
2324 fprintf(logfile, "%p: translate opcode %08x\n",
2325 ctx.nip, ctx.opcode);
2329 table = ppc_opcodes;
2330 handler = table[opc1(ctx.opcode)];
2331 if (is_indirect_opcode(handler)) {
2332 table = ind_table(handler);
2333 handler = table[opc2(ctx.opcode)];
2334 if (is_indirect_opcode(handler)) {
2335 table = ind_table(handler);
2336 handler = table[opc3(ctx.opcode)];
2339 /* Is opcode *REALLY* valid ? */
2340 if ((ctx.opcode & handler->inval) != 0) {
2342 if (handler->handler == &gen_invalid) {
2343 fprintf(logfile, "invalid/unsupported opcode: "
2344 "%02x -%02x - %02x (%08x)\n", opc1(ctx.opcode),
2345 opc2(ctx.opcode), opc3(ctx.opcode), ctx.opcode);
2347 fprintf(logfile, "invalid bits: %08x for opcode: "
2348 "%02x -%02x - %02x (%p)\n",
2349 ctx.opcode & handler->inval, opc1(ctx.opcode),
2350 opc2(ctx.opcode), opc3(ctx.opcode),
2354 ret = GET_RETVAL(gen_invalid, ctx.opcode);
2356 ret = GET_RETVAL(*(handler->handler), ctx.opcode);
2359 #if defined (DO_SINGLE_STEP)
2363 #if defined (DO_STEP_FLUSH)
2366 /* We need to update the time base */
2368 gen_op_update_tb(ctx.tb_offset);
2369 /* If we are in step-by-step mode, do a branch to the next instruction
2370 * so the nip will be up-to-date
2372 #if defined (DO_SINGLE_STEP)
2374 gen_op_b((uint32_t)ctx.nip);
2378 /* If the exeption isn't a PPC one,
2381 if (ret != EXCP_BRANCH) {
2383 if ((ret & 0x2000) == 0)
2384 gen_op_raise_exception(ret);
2386 /* TO BE FIXED: T0 hasn't got a proper value, which makes tb_add_jump
2387 * do bad business and then qemu crashes !
2390 /* Generate the return instruction */
2392 *gen_opc_ptr = INDEX_op_end;
2394 tb->size = (uint32_t)ctx.nip - pc_start;
2397 // *gen_opc_ptr = INDEX_op_end;
2400 fprintf(logfile, "IN: %s\n", lookup_symbol((void *)pc_start));
2401 disas(logfile, (void *)pc_start, (uint32_t)ctx.nip - pc_start, 0, 0);
2402 fprintf(logfile, "\n");
2404 fprintf(logfile, "OP:\n");
2405 dump_ops(gen_opc_buf, gen_opparam_buf);
2406 fprintf(logfile, "\n");
2413 int gen_intermediate_code(CPUState *env, struct TranslationBlock *tb)
2415 return gen_intermediate_code_internal(env, tb, 0);
2418 int gen_intermediate_code_pc(CPUState *env, struct TranslationBlock *tb)
2420 return gen_intermediate_code_internal(env, tb, 1);