]> git.proxmox.com Git - qemu.git/blame - target-ppc/translate.c
disable keyboard interrupts if keyboard clock disabled (may not be fully correct...
[qemu.git] / target-ppc / translate.c
CommitLineData
79aceca5
FB
1/*
2 * PPC emulation for qemu: main translation routines.
3 *
4 * Copyright (c) 2003 Jocelyn Mayer
5 *
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.
10 *
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.
15 *
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
19 */
20#include "dyngen-exec.h"
21#include "cpu.h"
22#include "exec.h"
23#include "disas.h"
24
25//#define DO_SINGLE_STEP
26//#define DO_STEP_FLUSH
27
28enum {
29#define DEF(s, n, copy_size) INDEX_op_ ## s,
30#include "opc.h"
31#undef DEF
32 NB_OPS,
33};
34
35static uint16_t *gen_opc_ptr;
36static uint32_t *gen_opparam_ptr;
37
38#include "gen-op.h"
28b6751f
FB
39
40typedef void (GenOpFunc)(void);
41
42#define GEN8(func, NAME) \
43static GenOpFunc *NAME ## _table [8] = {\
44NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3,\
45NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7,\
46};\
47static inline void func(int n)\
48{\
49 NAME ## _table[n]();\
50}
51
52#define GEN32(func, NAME) \
53static GenOpFunc *NAME ## _table [32] = {\
54NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3,\
55NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7,\
56NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11,\
57NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,\
58NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,\
59NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,\
60NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,\
61NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,\
62};\
63static inline void func(int n)\
64{\
65 NAME ## _table[n]();\
66}
67
68GEN8(gen_op_load_crf_T0, gen_op_load_crf_T0_crf)
69GEN8(gen_op_load_crf_T1, gen_op_load_crf_T1_crf)
70GEN8(gen_op_store_T0_crf, gen_op_store_T0_crf_crf)
71GEN8(gen_op_store_T1_crf, gen_op_store_T1_crf_crf)
72
73GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr)
74GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr)
75GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr)
76
77GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr)
78GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr)
79GEN32(gen_op_store_T2_gpr, gen_op_store_T2_gpr_gpr)
80
81GEN32(gen_op_load_FT0_fpr, gen_op_load_FT0_fpr)
82GEN32(gen_op_store_FT0_fpr, gen_op_store_FT0_fpr)
79aceca5
FB
83
84static uint8_t spr_access[1024 / 2];
85
86/* internal defines */
87typedef struct DisasContext {
88 struct TranslationBlock *tb;
89 uint32_t *nip;
90 uint32_t opcode;
91 int exception;
92 int retcode;
93 /* Time base */
94 uint32_t tb_offset;
95 int supervisor;
96} DisasContext;
97
98typedef struct opc_handler_t {
99 /* invalid bits */
100 uint32_t inval;
101 /* handler */
102 void (*handler)(DisasContext *ctx);
103} opc_handler_t;
104
105#define SET_RETVAL(n) \
106do { \
107 if ((n) != 0) { \
108 ctx->exception = (n); \
109 } \
110 return; \
111} while (0)
112
113#define GET_RETVAL(func, __opcode) \
114({ \
115 (func)(&ctx); \
116 ctx.exception; \
117})
118
119#define GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
120static void gen_##name (DisasContext *ctx); \
121GEN_OPCODE(name, opc1, opc2, opc3, inval, type); \
122static void gen_##name (DisasContext *ctx)
123
124/* Instruction types */
125enum {
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 */
133};
134
135typedef struct opcode_t {
136 unsigned char opc1, opc2, opc3;
137 uint32_t type;
138 opc_handler_t handler;
139} opcode_t;
140
141/* XXX: move that elsewhere */
142extern FILE *logfile;
143extern int loglevel;
144
145/* XXX: shouldn't stay all alone here ! */
146static int reserve = 0;
147
148/*** Instruction decoding ***/
149#define EXTRACT_HELPER(name, shift, nb) \
150static inline uint32_t name (uint32_t opcode) \
151{ \
152 return (opcode >> (shift)) & ((1 << (nb)) - 1); \
153}
154
155#define EXTRACT_SHELPER(name, shift, nb) \
156static inline int32_t name (uint32_t opcode) \
157{ \
158 return s_ext16((opcode >> (shift)) & ((1 << (nb)) - 1)); \
159}
160
161/* Opcode part 1 */
162EXTRACT_HELPER(opc1, 26, 6);
163/* Opcode part 2 */
164EXTRACT_HELPER(opc2, 1, 5);
165/* Opcode part 3 */
166EXTRACT_HELPER(opc3, 6, 5);
167/* Update Cr0 flags */
168EXTRACT_HELPER(Rc, 0, 1);
169/* Destination */
170EXTRACT_HELPER(rD, 21, 5);
171/* Source */
172EXTRACT_HELPER(rS, 21, 5);
173/* First operand */
174EXTRACT_HELPER(rA, 16, 5);
175/* Second operand */
176EXTRACT_HELPER(rB, 11, 5);
177/* Third operand */
178EXTRACT_HELPER(rC, 6, 5);
179/*** Get CRn ***/
180EXTRACT_HELPER(crfD, 23, 3);
181EXTRACT_HELPER(crfS, 18, 3);
182EXTRACT_HELPER(crbD, 21, 5);
183EXTRACT_HELPER(crbA, 16, 5);
184EXTRACT_HELPER(crbB, 11, 5);
185/* SPR / TBL */
186EXTRACT_HELPER(SPR, 11, 10);
187/*** Get constants ***/
188EXTRACT_HELPER(IMM, 12, 8);
189/* 16 bits signed immediate value */
190EXTRACT_SHELPER(SIMM, 0, 16);
191/* 16 bits unsigned immediate value */
192EXTRACT_HELPER(UIMM, 0, 16);
193/* Bit count */
194EXTRACT_HELPER(NB, 11, 5);
195/* Shift count */
196EXTRACT_HELPER(SH, 11, 5);
197/* Mask start */
198EXTRACT_HELPER(MB, 6, 5);
199/* Mask end */
200EXTRACT_HELPER(ME, 1, 5);
201
202EXTRACT_HELPER(CRM, 12, 8);
203EXTRACT_HELPER(FM, 17, 8);
204EXTRACT_HELPER(SR, 16, 4);
205/*** Jump target decoding ***/
206/* Displacement */
207EXTRACT_SHELPER(d, 0, 16);
208/* Immediate address */
209static inline uint32_t LI (uint32_t opcode)
210{
211 return (opcode >> 0) & 0x03FFFFFC;
212}
213
214static inline uint32_t BD (uint32_t opcode)
215{
216 return (opcode >> 0) & 0xFFFC;
217}
218
219EXTRACT_HELPER(BO, 21, 5);
220EXTRACT_HELPER(BI, 16, 5);
221/* Absolute/relative address */
222EXTRACT_HELPER(AA, 1, 1);
223/* Link */
224EXTRACT_HELPER(LK, 0, 1);
225
226/* Create a mask between <start> and <end> bits */
227static inline uint32_t MASK (uint32_t start, uint32_t end)
228{
229 uint32_t ret;
230
231 ret = (((uint32_t)(-1)) >> (start)) ^ (((uint32_t)(-1) >> (end)) >> 1);
232 if (start > end)
233 return ~ret;
234
235 return ret;
236}
237
238#define GEN_OPCODE(name, op1, op2, op3, invl, _typ) \
239__attribute__ ((section(".opcodes"), unused)) \
240static opcode_t opc_##name = { \
241 .opc1 = op1, \
242 .opc2 = op2, \
243 .opc3 = op3, \
244 .type = _typ, \
245 .handler = { \
246 .inval = invl, \
247 .handler = &gen_##name, \
248 }, \
249}
250
251#define GEN_OPCODE_MARK(name) \
252__attribute__ ((section(".opcodes"), unused)) \
253static opcode_t opc_##name = { \
254 .opc1 = 0xFF, \
255 .opc2 = 0xFF, \
256 .opc3 = 0xFF, \
257 .type = 0x00, \
258 .handler = { \
259 .inval = 0x00000000, \
260 .handler = NULL, \
261 }, \
262}
263
264/* Start opcode list */
265GEN_OPCODE_MARK(start);
266
267/* Invalid instruction */
268GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, 0)
269{
270 /* Branch to next instruction to force nip update */
271 gen_op_b((uint32_t)ctx->nip);
272 SET_RETVAL(EXCP_INVAL);
273}
274
275static opc_handler_t invalid_handler = {
276 .inval = 0xFFFFFFFF,
277 .handler = gen_invalid,
278};
279
280/*** Integer arithmetic ***/
281#define __GEN_INT_ARITH2(name, opc1, opc2, opc3, inval) \
282GEN_HANDLER(name, opc1, opc2, opc3, inval, PPC_INTEGER) \
283{ \
284 gen_op_load_gpr_T0(rA(ctx->opcode)); \
285 gen_op_load_gpr_T1(rB(ctx->opcode)); \
286 gen_op_##name(); \
287 if (Rc(ctx->opcode) != 0) \
288 gen_op_set_Rc0(); \
289 gen_op_store_T0_gpr(rD(ctx->opcode)); \
290 SET_RETVAL(0); \
291}
292
293#define __GEN_INT_ARITH2_O(name, opc1, opc2, opc3, inval) \
294GEN_HANDLER(name, opc1, opc2, opc3, inval, PPC_INTEGER) \
295{ \
296 gen_op_load_gpr_T0(rA(ctx->opcode)); \
297 gen_op_load_gpr_T1(rB(ctx->opcode)); \
298 gen_op_##name(); \
299 if (Rc(ctx->opcode) != 0) \
300 gen_op_set_Rc0_ov(); \
301 gen_op_store_T0_gpr(rD(ctx->opcode)); \
302 SET_RETVAL(0); \
303}
304
305#define __GEN_INT_ARITH1(name, opc1, opc2, opc3) \
306GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, PPC_INTEGER) \
307{ \
308 gen_op_load_gpr_T0(rA(ctx->opcode)); \
309 gen_op_##name(); \
310 if (Rc(ctx->opcode) != 0) \
311 gen_op_set_Rc0(); \
312 gen_op_store_T0_gpr(rD(ctx->opcode)); \
313 SET_RETVAL(0); \
314}
315#define __GEN_INT_ARITH1_O(name, opc1, opc2, opc3) \
316GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, PPC_INTEGER) \
317{ \
318 gen_op_load_gpr_T0(rA(ctx->opcode)); \
319 gen_op_##name(); \
320 if (Rc(ctx->opcode) != 0) \
321 gen_op_set_Rc0_ov(); \
322 gen_op_store_T0_gpr(rD(ctx->opcode)); \
323 SET_RETVAL(0); \
324}
325
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)
330
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)
334
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)
339
340/* add add. addo addo. */
341GEN_INT_ARITH2 (add, 0x1F, 0x0A, 0x08);
342/* addc addc. addco addco. */
343GEN_INT_ARITH2 (addc, 0x1F, 0x0A, 0x00);
344/* adde adde. addeo addeo. */
345GEN_INT_ARITH2 (adde, 0x1F, 0x0A, 0x04);
346/* addme addme. addmeo addmeo. */
347GEN_INT_ARITH1 (addme, 0x1F, 0x0A, 0x07);
348/* addze addze. addzeo addzeo. */
349GEN_INT_ARITH1 (addze, 0x1F, 0x0A, 0x06);
350/* divw divw. divwo divwo. */
351GEN_INT_ARITH2 (divw, 0x1F, 0x0B, 0x0F);
352/* divwu divwu. divwuo divwuo. */
353GEN_INT_ARITH2 (divwu, 0x1F, 0x0B, 0x0E);
354/* mulhw mulhw. */
355GEN_INT_ARITHN (mulhw, 0x1F, 0x0B, 0x02);
356/* mulhwu mulhwu. */
357GEN_INT_ARITHN (mulhwu, 0x1F, 0x0B, 0x00);
358/* mullw mullw. mullwo mullwo. */
359GEN_INT_ARITH2 (mullw, 0x1F, 0x0B, 0x07);
360/* neg neg. nego nego. */
361GEN_INT_ARITH1 (neg, 0x1F, 0x08, 0x03);
362/* subf subf. subfo subfo. */
363GEN_INT_ARITH2 (subf, 0x1F, 0x08, 0x01);
364/* subfc subfc. subfco subfco. */
365GEN_INT_ARITH2 (subfc, 0x1F, 0x08, 0x00);
366/* subfe subfe. subfeo subfeo. */
367GEN_INT_ARITH2 (subfe, 0x1F, 0x08, 0x04);
368/* subfme subfme. subfmeo subfmeo. */
369GEN_INT_ARITH1 (subfme, 0x1F, 0x08, 0x07);
370/* subfze subfze. subfzeo subfzeo. */
371GEN_INT_ARITH1 (subfze, 0x1F, 0x08, 0x06);
372/* addi */
373GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
374{
375 int32_t simm = SIMM(ctx->opcode);
376
377 if (rA(ctx->opcode) == 0) {
378 gen_op_set_T0(simm);
379 } else {
380 gen_op_load_gpr_T0(rA(ctx->opcode));
381 gen_op_addi(simm);
382 }
383 gen_op_store_T0_gpr(rD(ctx->opcode));
384 SET_RETVAL(0);
385}
386/* addic */
387GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
388{
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));
392 SET_RETVAL(0);
393}
394/* addic. */
395GEN_HANDLER(addic_, 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
396{
397 gen_op_load_gpr_T0(rA(ctx->opcode));
398 gen_op_addic(SIMM(ctx->opcode));
399 gen_op_set_Rc0();
400 gen_op_store_T0_gpr(rD(ctx->opcode));
401 SET_RETVAL(0);
402}
403/* addis */
404GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
405{
406 int32_t simm = SIMM(ctx->opcode);
407
408 if (rA(ctx->opcode) == 0) {
409 gen_op_set_T0(simm << 16);
410 } else {
411 gen_op_load_gpr_T0(rA(ctx->opcode));
412 gen_op_addi(simm << 16);
413 }
414 gen_op_store_T0_gpr(rD(ctx->opcode));
415 SET_RETVAL(0);
416}
417/* mulli */
418GEN_HANDLER(mulli, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
419{
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));
423 SET_RETVAL(0);
424}
425/* subfic */
426GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
427{
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));
431 SET_RETVAL(0);
432}
433
434/*** Integer comparison ***/
435#define GEN_CMP(name, opc) \
436GEN_HANDLER(name, 0x1F, 0x00, opc, 0x00400000, PPC_INTEGER) \
437{ \
438 gen_op_load_gpr_T0(rA(ctx->opcode)); \
439 gen_op_load_gpr_T1(rB(ctx->opcode)); \
440 gen_op_##name(); \
441 gen_op_store_T0_crf(crfD(ctx->opcode)); \
442 SET_RETVAL(0); \
443}
444
445/* cmp */
446GEN_CMP(cmp, 0x00);
447/* cmpi */
448GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
449{
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));
453 SET_RETVAL(0);
454}
455/* cmpl */
456GEN_CMP(cmpl, 0x01);
457/* cmpli */
458GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
459{
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));
463 SET_RETVAL(0);
464}
465
466/*** Integer logical ***/
467#define __GEN_LOGICAL2(name, opc2, opc3) \
468GEN_HANDLER(name, 0x1F, opc2, opc3, 0x00000000, PPC_INTEGER) \
469{ \
470 gen_op_load_gpr_T0(rS(ctx->opcode)); \
471 gen_op_load_gpr_T1(rB(ctx->opcode)); \
472 gen_op_##name(); \
473 if (Rc(ctx->opcode) != 0) \
474 gen_op_set_Rc0(); \
475 gen_op_store_T0_gpr(rA(ctx->opcode)); \
476 SET_RETVAL(0); \
477}
478#define GEN_LOGICAL2(name, opc) \
479__GEN_LOGICAL2(name, 0x1C, opc)
480
481#define GEN_LOGICAL1(name, opc) \
482GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, PPC_INTEGER) \
483{ \
484 gen_op_load_gpr_T0(rS(ctx->opcode)); \
485 gen_op_##name(); \
486 if (Rc(ctx->opcode) != 0) \
487 gen_op_set_Rc0(); \
488 gen_op_store_T0_gpr(rA(ctx->opcode)); \
489 SET_RETVAL(0); \
490}
491
492/* and & and. */
493GEN_LOGICAL2(and, 0x00);
494/* andc & andc. */
495GEN_LOGICAL2(andc, 0x01);
496/* andi. */
497GEN_HANDLER(andi_, 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
498{
499 gen_op_load_gpr_T0(rS(ctx->opcode));
500 gen_op_andi_(UIMM(ctx->opcode));
501 gen_op_set_Rc0();
502 gen_op_store_T0_gpr(rA(ctx->opcode));
503 SET_RETVAL(0);
504}
505/* andis. */
506GEN_HANDLER(andis_, 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
507{
508 gen_op_load_gpr_T0(rS(ctx->opcode));
509 gen_op_andi_(UIMM(ctx->opcode) << 16);
510 gen_op_set_Rc0();
511 gen_op_store_T0_gpr(rA(ctx->opcode));
512 SET_RETVAL(0);
513}
514
515/* cntlzw */
516GEN_LOGICAL1(cntlzw, 0x00);
517/* eqv & eqv. */
518GEN_LOGICAL2(eqv, 0x08);
519/* extsb & extsb. */
520GEN_LOGICAL1(extsb, 0x1D);
521/* extsh & extsh. */
522GEN_LOGICAL1(extsh, 0x1C);
523/* nand & nand. */
524GEN_LOGICAL2(nand, 0x0E);
525/* nor & nor. */
526GEN_LOGICAL2(nor, 0x03);
527/* or & or. */
528GEN_LOGICAL2(or, 0x0D);
529/* orc & orc. */
530GEN_LOGICAL2(orc, 0x0C);
531/* xor & xor. */
532GEN_LOGICAL2(xor, 0x09);
533/* ori */
534GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
535{
536 uint32_t uimm = UIMM(ctx->opcode);
537
538#if 0
539 if (uimm == 0) {
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));
543 }
544 } else
545#endif
546 {
547 gen_op_load_gpr_T0(rS(ctx->opcode));
548 gen_op_ori(uimm);
549 gen_op_store_T0_gpr(rA(ctx->opcode));
550 }
551 SET_RETVAL(0);
552}
553/* oris */
554GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
555{
556 uint32_t uimm = UIMM(ctx->opcode);
557
558#if 0
559 if (uimm == 0) {
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));
563 }
564 } else
565#endif
566 {
567 gen_op_load_gpr_T0(rS(ctx->opcode));
568 gen_op_ori(uimm << 16);
569 gen_op_store_T0_gpr(rA(ctx->opcode));
570 }
571 SET_RETVAL(0);
572}
573/* xori */
574GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
575{
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));
579 SET_RETVAL(0);
580}
581
582/* xoris */
583GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
584{
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));
588 SET_RETVAL(0);
589}
590
591/*** Integer rotate ***/
592/* rlwimi & rlwimi. */
593GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
594{
595 uint32_t mb, me;
596
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)
602 gen_op_set_Rc0();
603 gen_op_store_T0_gpr(rA(ctx->opcode));
604 SET_RETVAL(0);
605}
606/* rlwinm & rlwinm. */
607GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
608{
609 uint32_t mb, me, sh;
610
611 sh = SH(ctx->opcode);
612 mb = MB(ctx->opcode);
613 me = ME(ctx->opcode);
614 gen_op_load_gpr_T0(rS(ctx->opcode));
615 if (loglevel > 0) {
616 fprintf(logfile, "%s sh=%u mb=%u me=%u MASK=0x%08x\n",
617 __func__, sh, mb, me, MASK(mb, me));
618 }
619 if (mb == 0) {
620 if (me == 31) {
621 gen_op_rotlwi(sh);
622 goto store;
623 } else if (me == (31 - sh)) {
624 gen_op_slwi(sh);
625 goto store;
626 } else if (sh == 0) {
627 gen_op_andi_(MASK(0, me));
628 goto store;
629 }
630 } else if (me == 31) {
631 if (sh == (32 - mb)) {
632 gen_op_srwi(mb);
633 goto store;
634 } else if (sh == 0) {
635 gen_op_andi_(MASK(mb, 31));
636 goto store;
637 }
638 }
639 gen_op_rlwinm(sh, MASK(mb, me));
640store:
641 if (Rc(ctx->opcode) != 0)
642 gen_op_set_Rc0();
643 gen_op_store_T0_gpr(rA(ctx->opcode));
644 SET_RETVAL(0);
645}
646/* rlwnm & rlwnm. */
647GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
648{
649 uint32_t mb, me;
650
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) {
656 gen_op_rotl();
657 } else
658 {
659 gen_op_rlwnm(MASK(mb, me));
660 }
661 if (Rc(ctx->opcode) != 0)
662 gen_op_set_Rc0();
663 gen_op_store_T0_gpr(rA(ctx->opcode));
664 SET_RETVAL(0);
665}
666
667/*** Integer shift ***/
668/* slw & slw. */
669__GEN_LOGICAL2(slw, 0x18, 0x00);
670/* sraw & sraw. */
671__GEN_LOGICAL2(sraw, 0x18, 0x18);
672/* srawi & srawi. */
673GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER)
674{
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)
678 gen_op_set_Rc0();
679 gen_op_store_T0_gpr(rA(ctx->opcode));
680 SET_RETVAL(0);
681}
682/* srw & srw. */
683__GEN_LOGICAL2(srw, 0x18, 0x10);
684
685/*** Floating-Point arithmetic ***/
686/* fadd */
687GEN_HANDLER(fadd, 0x3F, 0x15, 0xFF, 0x000007C0, PPC_FLOAT)
688{
689 SET_RETVAL(EXCP_INVAL);
690}
691
692/* fadds */
693GEN_HANDLER(fadds, 0x3B, 0x15, 0xFF, 0x000007C0, PPC_FLOAT)
694{
695 SET_RETVAL(EXCP_INVAL);
696}
697
698/* fdiv */
699GEN_HANDLER(fdiv, 0x3F, 0x12, 0xFF, 0x000007C0, PPC_FLOAT)
700{
701 SET_RETVAL(EXCP_INVAL);
702}
703
704/* fdivs */
705GEN_HANDLER(fdivs, 0x3B, 0x12, 0xFF, 0x000007C0, PPC_FLOAT)
706{
707 SET_RETVAL(EXCP_INVAL);
708}
709
710/* fmul */
711GEN_HANDLER(fmul, 0x3F, 0x19, 0xFF, 0x0000F800, PPC_FLOAT)
712{
713 SET_RETVAL(EXCP_INVAL);
714}
715
716/* fmuls */
717GEN_HANDLER(fmuls, 0x3B, 0x19, 0xFF, 0x0000F800, PPC_FLOAT)
718{
719 SET_RETVAL(EXCP_INVAL);
720}
721
722/* fres */
723GEN_HANDLER(fres, 0x3B, 0x18, 0xFF, 0x001807C0, PPC_FLOAT)
724{
725 SET_RETVAL(EXCP_INVAL);
726}
727
728/* frsqrte */
729GEN_HANDLER(frsqrte, 0x3F, 0x1A, 0xFF, 0x001807C0, PPC_FLOAT)
730{
731 SET_RETVAL(EXCP_INVAL);
732}
733
734/* fsel */
735GEN_HANDLER(fsel, 0x3F, 0x17, 0xFF, 0x00000000, PPC_FLOAT)
736{
737 SET_RETVAL(EXCP_INVAL);
738}
739
740/* fsub */
741GEN_HANDLER(fsub, 0x3F, 0x14, 0xFF, 0x000007C0, PPC_FLOAT)
742{
743 SET_RETVAL(EXCP_INVAL);
744}
745
746/* fsubs */
747GEN_HANDLER(fsubs, 0x3B, 0x14, 0xFF, 0x000007C0, PPC_FLOAT)
748{
749 SET_RETVAL(EXCP_INVAL);
750}
751
752/* Optional: */
753/* fsqrt */
754GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001807C0, PPC_FLOAT)
755{
756 SET_RETVAL(EXCP_INVAL);
757}
758
759/* fsqrts */
760GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001807C0, PPC_FLOAT)
761{
762 SET_RETVAL(EXCP_INVAL);
763}
764
765/*** Floating-Point multiply-and-add ***/
766/* fmadd */
767GEN_HANDLER(fmadd, 0x3F, 0x1D, 0xFF, 0x00000000, PPC_FLOAT)
768{
769 SET_RETVAL(EXCP_INVAL);
770}
771
772/* fmadds */
773GEN_HANDLER(fmadds, 0x3B, 0x1D, 0xFF, 0x00000000, PPC_FLOAT)
774{
775 SET_RETVAL(EXCP_INVAL);
776}
777
778/* fmsub */
779GEN_HANDLER(fmsub, 0x3F, 0x1C, 0xFF, 0x00000000, PPC_FLOAT)
780{
781 SET_RETVAL(EXCP_INVAL);
782}
783
784/* fmsubs */
785GEN_HANDLER(fmsubs, 0x3B, 0x1C, 0xFF, 0x00000000, PPC_FLOAT)
786{
787 SET_RETVAL(EXCP_INVAL);
788}
789
790/* fnmadd */
791GEN_HANDLER(fnmadd, 0x3F, 0x1F, 0xFF, 0x00000000, PPC_FLOAT)
792{
793 SET_RETVAL(EXCP_INVAL);
794}
795
796/* fnmadds */
797GEN_HANDLER(fnmadds, 0x3B, 0x1F, 0xFF, 0x00000000, PPC_FLOAT)
798{
799 SET_RETVAL(EXCP_INVAL);
800}
801
802/* fnmsub */
803GEN_HANDLER(fnmsub, 0x3F, 0x1E, 0xFF, 0x00000000, PPC_FLOAT)
804{
805 SET_RETVAL(EXCP_INVAL);
806}
807
808/* fnmsubs */
809GEN_HANDLER(fnmsubs, 0x3B, 0x1E, 0xFF, 0x00000000, PPC_FLOAT)
810{
811 SET_RETVAL(EXCP_INVAL);
812}
813
814/*** Floating-Point round & convert ***/
815/* fctiw */
816GEN_HANDLER(fctiw, 0x3F, 0x0E, 0xFF, 0x001F0000, PPC_FLOAT)
817{
818 SET_RETVAL(EXCP_INVAL);
819}
820
821/* fctiwz */
822GEN_HANDLER(fctiwz, 0x3F, 0x0F, 0xFF, 0x001F0000, PPC_FLOAT)
823{
824 SET_RETVAL(EXCP_INVAL);
825}
826
827/* frsp */
828GEN_HANDLER(frsp, 0x3F, 0x0C, 0xFF, 0x001F0000, PPC_FLOAT)
829{
830 SET_RETVAL(EXCP_INVAL);
831}
832
833/*** Floating-Point compare ***/
834/* fcmpo */
835GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT)
836{
837 SET_RETVAL(EXCP_INVAL);
838}
839
840/* fcmpu */
841GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT)
842{
843 SET_RETVAL(EXCP_INVAL);
844}
845
846/*** Floating-Point status & ctrl register ***/
847/* mcrfs */
848GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT)
849{
850 SET_RETVAL(EXCP_INVAL);
851}
852
853/* mffs */
854GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT)
855{
28b6751f
FB
856 gen_op_load_fpscr();
857 gen_op_store_T0_gpr(rD(ctx->opcode));
79aceca5
FB
858 if (Rc(ctx->opcode)) {
859 /* Update CR1 */
860 }
861 SET_RETVAL(0);
862}
863
864/* mtfsb0 */
865GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT)
866{
867 SET_RETVAL(EXCP_INVAL);
868}
869
870/* mtfsb1 */
871GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT)
872{
873 SET_RETVAL(EXCP_INVAL);
874}
875
876/* mtfsf */
877GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT)
878{
28b6751f
FB
879 gen_op_load_gpr_T0(rB(ctx->opcode));
880 gen_op_store_fpscr(FM(ctx->opcode));
79aceca5
FB
881 if (Rc(ctx->opcode)) {
882 /* Update CR1 */
883 }
884 SET_RETVAL(0);
885}
886
887/* mtfsfi */
888GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT)
889{
890 SET_RETVAL(EXCP_INVAL);
891}
892
893/*** Integer load ***/
894#define GEN_ILDZ(width, opc) \
895GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
896{ \
897 uint32_t simm = SIMM(ctx->opcode); \
898 if (rA(ctx->opcode) == 0) { \
899 gen_op_l##width##_z(simm); \
900 } else { \
901 gen_op_load_gpr_T0(rA(ctx->opcode)); \
902 gen_op_l##width (simm); \
903 } \
904 gen_op_store_T1_gpr(rD(ctx->opcode)); \
905 SET_RETVAL(0); \
906}
907
908#define GEN_ILDZU(width, opc) \
909GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
910{ \
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)); \
918 SET_RETVAL(0); \
919}
920
921#define GEN_ILDZUX(width, opc) \
922GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \
923{ \
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)); \
932 SET_RETVAL(0); \
933}
934
935#define GEN_ILDZX(width, opc2, opc3) \
936GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER) \
937{ \
938 if (rA(ctx->opcode) == 0) { \
939 gen_op_load_gpr_T0(rB(ctx->opcode)); \
940 gen_op_l##width##x_z(); \
941 } else { \
942 gen_op_load_gpr_T0(rA(ctx->opcode)); \
943 gen_op_load_gpr_T1(rB(ctx->opcode)); \
944 gen_op_l##width##x(); \
945 } \
946 gen_op_store_T1_gpr(rD(ctx->opcode)); \
947 SET_RETVAL(0); \
948}
949
950#define GEN_ILD(width, op) \
951GEN_ILDZ(width, op | 0x20) \
952GEN_ILDZU(width, op | 0x21) \
953GEN_ILDZUX(width, op | 0x01) \
954GEN_ILDZX(width, 0x17, op | 0x00)
955
956/* lbz lbzu lbzux lbzx */
957GEN_ILD(bz, 0x02);
958/* lha lhau lhaux lhax */
959GEN_ILD(ha, 0x0A);
960/* lhz lhzu lhzux lhzx */
961GEN_ILD(hz, 0x08);
962/* lwz lwzu lwzux lwzx */
963GEN_ILD(wz, 0x00);
964
965/*** Integer store ***/
966#define GEN_IST(width, opc) \
967GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
968{ \
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); \
973 } else { \
974 gen_op_load_gpr_T0(rA(ctx->opcode)); \
975 gen_op_load_gpr_T1(rS(ctx->opcode)); \
976 gen_op_st##width(simm); \
977 } \
978 SET_RETVAL(0); \
979}
980
981#define GEN_ISTU(width, opc) \
982GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
983{ \
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)); \
990 SET_RETVAL(0); \
991}
992
993#define GEN_ISTUX(width, opc) \
994GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \
995{ \
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)); \
1003 SET_RETVAL(0); \
1004}
1005
1006#define GEN_ISTX(width, opc2, opc3) \
1007GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER) \
1008{ \
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(); \
1013 } else { \
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(); \
1018 } \
1019 SET_RETVAL(0); \
1020}
1021
1022#define GEN_ISTO(width, opc) \
1023GEN_IST(width, opc | 0x20) \
1024GEN_ISTU(width, opc | 0x21) \
1025GEN_ISTUX(width, opc | 0x01) \
1026GEN_ISTX(width, 0x17, opc | 0x00)
1027
1028/* stb stbu stbux stbx */
1029GEN_ISTO(b, 0x06);
1030/* sth sthu sthux sthx */
1031GEN_ISTO(h, 0x0C);
1032/* stw stwu stwux stwx */
1033GEN_ISTO(w, 0x04);
1034
1035/*** Integer load and store with byte reverse ***/
1036/* lhbrx */
1037GEN_ILDZX(hbr, 0x16, 0x18);
1038/* lwbrx */
1039GEN_ILDZX(wbr, 0x16, 0x10);
1040/* sthbrx */
1041GEN_ISTX(hbr, 0x16, 0x1C);
1042/* stwbrx */
1043GEN_ISTX(wbr, 0x16, 0x14);
1044
1045/*** Integer load and store multiple ***/
1046/* lmw */
1047GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1048{
1049 if (rA(ctx->opcode) == 0) {
1050 gen_op_set_T0(0);
1051 } else {
1052 gen_op_load_gpr_T0(rA(ctx->opcode));
1053 }
1054 gen_op_lmw(rD(ctx->opcode), SIMM(ctx->opcode));
1055 SET_RETVAL(0);
1056}
1057
1058/* stmw */
1059GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1060{
1061 if (rA(ctx->opcode) == 0) {
1062 gen_op_set_T0(0);
1063 } else {
1064 gen_op_load_gpr_T0(rA(ctx->opcode));
1065 }
1066 gen_op_stmw(rS(ctx->opcode), SIMM(ctx->opcode));
1067 SET_RETVAL(0);
1068}
1069
1070/*** Integer load and store strings ***/
1071/* lswi */
1072GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_INTEGER)
1073{
1074 int nb = NB(ctx->opcode);
1075 int start = rD(ctx->opcode);
1076 int nr;
1077
1078 if (nb == 0)
1079 nb = 32;
1080 nr = nb / 4;
1081 if ((start + nr) > 32) {
1082 /* handle wrap around r0 */
1083 if (rA(ctx->opcode) == 0) {
1084 gen_op_set_T0(0);
1085 } else {
1086 gen_op_load_gpr_T0(rA(ctx->opcode));
1087 }
1088 gen_op_lswi(start, 4 * (32 - start));
1089 nb -= 4 * (32 - start);
1090 start = 0;
1091 }
1092 if (rA(ctx->opcode) == 0) {
1093 gen_op_set_T0(0);
1094 } else {
1095 gen_op_load_gpr_T0(rA(ctx->opcode));
1096 }
1097 gen_op_lswi(start, nb);
1098 SET_RETVAL(0);
1099}
1100
1101/* lswx */
1102GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_INTEGER)
1103{
1104 gen_op_load_xer_bc();
1105 gen_op_load_gpr_T1(rB(ctx->opcode));
1106 if (rA(ctx->opcode) == 0) {
1107 gen_op_set_T2(0);
1108 } else {
1109 gen_op_load_gpr_T2(rA(ctx->opcode));
1110 }
1111 gen_op_lswx(rD(ctx->opcode));
1112 SET_RETVAL(0);
1113}
1114
1115/* stswi */
1116GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_INTEGER)
1117{
1118 int nb = NB(ctx->opcode);
1119 int start = rS(ctx->opcode);
1120 int nr;
1121
1122 if (nb == 0)
1123 nb = 32;
1124 nr = nb / 4;
1125 if ((start + nr) > 32) {
1126 /* handle wrap around r0 */
1127 if (rA(ctx->opcode) == 0) {
1128 gen_op_set_T0(0);
1129 } else {
1130 gen_op_load_gpr_T0(rA(ctx->opcode));
1131 }
1132 gen_op_stswi(start, 4 * (32 - start));
1133 nb -= 4 * (32 - start);
1134 start = 0;
1135 }
1136 if (rA(ctx->opcode) == 0) {
1137 gen_op_set_T0(0);
1138 } else {
1139 gen_op_load_gpr_T0(rA(ctx->opcode));
1140 }
1141 gen_op_stswi(start, nb);
1142 SET_RETVAL(0);
1143}
1144
1145/* stswx */
1146GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_INTEGER)
1147{
1148 gen_op_load_xer_bc();
1149 gen_op_load_gpr_T1(rB(ctx->opcode));
1150 if (rA(ctx->opcode) == 0) {
1151 gen_op_set_T2(0);
1152 } else {
1153 gen_op_load_gpr_T2(rA(ctx->opcode));
1154 }
1155 gen_op_stswx(rS(ctx->opcode));
1156 SET_RETVAL(0);
1157}
1158
1159/*** Memory synchronisation ***/
1160/* eieio */
1161GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FF0801, PPC_MEM)
1162{
1163 /* Do a branch to next instruction */
1164 gen_op_b((uint32_t)ctx->nip);
1165 SET_RETVAL(EXCP_BRANCH);
1166}
1167
1168/* isync */
1169GEN_HANDLER(isync, 0x13, 0x16, 0xFF, 0x03FF0801, PPC_MEM)
1170{
1171 /* Do a branch to next instruction */
1172 gen_op_b((uint32_t)ctx->nip);
1173 SET_RETVAL(EXCP_BRANCH);
1174}
1175
1176/* lwarx */
1177GEN_HANDLER(lwarx, 0x1F, 0x14, 0xFF, 0x00000001, PPC_MEM)
1178{
1179 reserve = 1;
1180 if (rA(ctx->opcode) == 0) {
1181 gen_op_load_gpr_T0(rB(ctx->opcode));
1182 gen_op_lwzx_z();
1183 gen_op_set_reservation();
1184 } else {
1185 gen_op_load_gpr_T0(rA(ctx->opcode));
1186 gen_op_load_gpr_T1(rB(ctx->opcode));
1187 gen_op_lwzx();
1188 gen_op_set_reservation();
1189 }
1190 gen_op_store_T1_gpr(rD(ctx->opcode));
1191 SET_RETVAL(0);
1192}
1193
1194/* stwcx. */
1195GEN_HANDLER(stwcx_, 0x1F, 0x16, 0x04, 0x00000000, PPC_MEM)
1196{
1197 if (reserve == 0) {
1198 gen_op_reset_Rc0();
1199 } else {
1200 if (rA(ctx->opcode) == 0) {
1201 gen_op_load_gpr_T0(rB(ctx->opcode));
1202 gen_op_load_gpr_T1(rS(ctx->opcode));
1203 gen_op_stwx_z();
1204 } else {
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));
1208 gen_op_stwx();
1209 }
1210 gen_op_set_Rc0_1();
1211 gen_op_reset_reservation();
1212 }
1213 SET_RETVAL(0);
1214}
1215
1216/* sync */
1217GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x03FF0801, PPC_MEM)
1218{
1219 /* Do a branch to next instruction */
1220 gen_op_b((uint32_t)ctx->nip);
1221 SET_RETVAL(EXCP_BRANCH);
1222}
1223
1224/*** Floating-point load ***/
1225#define GEN_LF(width, opc) \
1226GEN_HANDLER(lf##width, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT) \
1227{ \
1228 uint32_t simm = SIMM(ctx->opcode); \
1229 if (rA(ctx->opcode) == 0) { \
28b6751f 1230 gen_op_lf##width##_z_FT0(simm); \
79aceca5
FB
1231 } else { \
1232 gen_op_load_gpr_T0(rA(ctx->opcode)); \
28b6751f 1233 gen_op_lf##width##_FT0(simm); \
79aceca5 1234 } \
28b6751f 1235 gen_op_store_FT0_fpr(rD(ctx->opcode));\
79aceca5
FB
1236 SET_RETVAL(0); \
1237}
1238
1239#define GEN_LFU(width, opc) \
1240GEN_HANDLER(lf##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT) \
1241{ \
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)); \
28b6751f
FB
1246 gen_op_lf##width##_FT0(SIMM(ctx->opcode)); \
1247 gen_op_store_FT0_fpr(rD(ctx->opcode));\
79aceca5
FB
1248 gen_op_store_T0_gpr(rA(ctx->opcode)); \
1249 SET_RETVAL(0); \
1250}
1251
1252#define GEN_LFUX(width, opc) \
1253GEN_HANDLER(lf##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT) \
1254{ \
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)); \
28b6751f
FB
1260 gen_op_lf##width##x_FT0(); \
1261 gen_op_store_FT0_fpr(rD(ctx->opcode));\
79aceca5
FB
1262 gen_op_store_T0_gpr(rA(ctx->opcode)); \
1263 SET_RETVAL(0); \
1264}
1265
1266#define GEN_LFX(width, opc) \
1267GEN_HANDLER(lf##width##x, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT) \
1268{ \
1269 if (rA(ctx->opcode) == 0) { \
1270 gen_op_load_gpr_T0(rB(ctx->opcode)); \
28b6751f 1271 gen_op_lf##width##x_z_FT0(); \
79aceca5
FB
1272 } else { \
1273 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1274 gen_op_load_gpr_T1(rB(ctx->opcode)); \
28b6751f 1275 gen_op_lf##width##x_FT0(); \
79aceca5 1276 } \
28b6751f 1277 gen_op_store_FT0_fpr(rD(ctx->opcode));\
79aceca5
FB
1278 SET_RETVAL(0); \
1279}
1280
1281#define GEN_LDF(width, opc) \
1282GEN_LF(width, opc | 0x20) \
1283GEN_LFU(width, opc | 0x21) \
1284GEN_LFUX(width, opc | 0x01) \
1285GEN_LFX(width, opc | 0x00)
1286
1287/* lfd lfdu lfdux lfdx */
1288GEN_LDF(d, 0x12);
1289/* lfs lfsu lfsux lfsx */
79aceca5
FB
1290GEN_LDF(s, 0x10);
1291
1292/*** Floating-point store ***/
1293#define GEN_STF(width, opc) \
1294GEN_HANDLER(stf##width, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT) \
1295{ \
1296 uint32_t simm = SIMM(ctx->opcode); \
28b6751f 1297 gen_op_load_FT0_fpr(rS(ctx->opcode));\
79aceca5 1298 if (rA(ctx->opcode) == 0) { \
28b6751f 1299 gen_op_stf##width##_z_FT0(simm); \
79aceca5
FB
1300 } else { \
1301 gen_op_load_gpr_T0(rA(ctx->opcode)); \
28b6751f 1302 gen_op_stf##width##_FT0(simm); \
79aceca5
FB
1303 } \
1304 SET_RETVAL(0); \
1305}
1306
1307#define GEN_STFU(width, opc) \
1308GEN_HANDLER(stf##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT) \
1309{ \
1310 if (rA(ctx->opcode) == 0) \
1311 SET_RETVAL(EXCP_INVAL); \
1312 gen_op_load_gpr_T0(rA(ctx->opcode)); \
28b6751f
FB
1313 gen_op_load_FT0_fpr(rS(ctx->opcode));\
1314 gen_op_stf##width##_FT0(SIMM(ctx->opcode)); \
79aceca5
FB
1315 gen_op_store_T0_gpr(rA(ctx->opcode)); \
1316 SET_RETVAL(0); \
1317}
1318
1319#define GEN_STFUX(width, opc) \
1320GEN_HANDLER(stf##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT) \
1321{ \
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)); \
28b6751f
FB
1326 gen_op_load_FT0_fpr(rS(ctx->opcode));\
1327 gen_op_stf##width##x_FT0(); \
79aceca5
FB
1328 gen_op_store_T0_gpr(rA(ctx->opcode)); \
1329 SET_RETVAL(0); \
1330}
1331
1332#define GEN_STFX(width, opc) \
1333GEN_HANDLER(stf##width##x, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT) \
1334{ \
28b6751f 1335 gen_op_load_FT0_fpr(rS(ctx->opcode));\
79aceca5
FB
1336 if (rA(ctx->opcode) == 0) { \
1337 gen_op_load_gpr_T0(rB(ctx->opcode)); \
28b6751f 1338 gen_op_stf##width##x_z_FT0(); \
79aceca5
FB
1339 } else { \
1340 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1341 gen_op_load_gpr_T1(rB(ctx->opcode)); \
28b6751f 1342 gen_op_stf##width##x_FT0(); \
79aceca5
FB
1343 } \
1344 SET_RETVAL(0); \
1345}
1346
1347#define GEN_STOF(width, opc) \
1348GEN_STF(width, opc | 0x20) \
1349GEN_STFU(width, opc | 0x21) \
1350GEN_STFUX(width, opc | 0x01) \
1351GEN_STFX(width, opc | 0x00)
1352
1353/* stfd stfdu stfdux stfdx */
1354GEN_STOF(d, 0x16);
1355/* stfs stfsu stfsux stfsx */
79aceca5
FB
1356GEN_STOF(s, 0x14);
1357
1358/* Optional: */
1359/* stfiwx */
1360GEN_HANDLER(stfiwx, 0x1F, 0x17, 0x1E, 0x00000001, PPC_FLOAT)
1361{
1362 SET_RETVAL(EXCP_INVAL);
1363}
1364
1365/*** Floating-point move ***/
1366/* fabs */
1367GEN_HANDLER(fabs, 0x3F, 0x08, 0x08, 0x001F0000, PPC_FLOAT)
1368{
1369 SET_RETVAL(EXCP_INVAL);
1370}
1371
1372/* fmr */
1373GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT)
1374{
1375 SET_RETVAL(EXCP_INVAL);
1376}
1377
1378/* fnabs */
1379GEN_HANDLER(fnabs, 0x3F, 0x08, 0x04, 0x001F0000, PPC_FLOAT)
1380{
1381 SET_RETVAL(EXCP_INVAL);
1382}
1383
1384/* fneg */
1385GEN_HANDLER(fneg, 0x3F, 0x08, 0x01, 0x001F0000, PPC_FLOAT)
1386{
1387 SET_RETVAL(EXCP_INVAL);
1388}
1389
1390/*** Branch ***/
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) \
1395GEN_HANDLER(name, opc1, opc2, opc3, 0x00000000, PPC_FLOW) \
1396{ \
1397 __attribute__ ((unused)) uint32_t target; \
1398 uint32_t bo = BO(ctx->opcode); \
1399 uint32_t bi = BI(ctx->opcode); \
1400 uint32_t mask; \
1401 prologue; \
1402 if ((bo & 0x4) == 0) \
1403 gen_op_dec_ctr(); \
1404 if (bo & 0x10) { \
1405 /* No CR condition */ \
1406 switch (bo & 0x6) { \
1407 case 0: \
1408 if (LK(ctx->opcode)) { \
1409 bl_ctr; \
1410 } else { \
1411 b_ctr; \
1412 } \
1413 break; \
1414 case 2: \
1415 if (LK(ctx->opcode)) { \
1416 bl_ctrz; \
1417 } else { \
1418 b_ctrz; \
1419 } \
1420 break; \
1421 case 4: \
1422 case 6: \
1423 b; \
1424 if (LK(ctx->opcode)) \
1425 gen_op_load_lr((uint32_t)ctx->nip); \
1426 break; \
1427 default: \
1428 printf("ERROR: %s: unhandled ba case (%d)\n", __func__, bo); \
1429 SET_RETVAL(EXCP_INVAL); \
1430 break; \
1431 } \
1432 } else { \
1433 mask = 1 << (3 - (bi & 0x03)); \
1434 gen_op_load_crf_T0(bi >> 2); \
1435 if (bo & 0x8) { \
1436 switch (bo & 0x6) { \
1437 case 0: \
1438 if (LK(ctx->opcode)) { \
1439 bl_ctr_true; \
1440 } else { \
1441 b_ctr_true; \
1442 } \
1443 break; \
1444 case 2: \
1445 if (LK(ctx->opcode)) { \
1446 bl_ctrz_true; \
1447 } else { \
1448 b_ctrz_true; \
1449 } \
1450 break; \
1451 case 4: \
1452 case 6: \
1453 if (LK(ctx->opcode)) { \
1454 bl_true; \
1455 } else { \
1456 b_true; \
1457 } \
1458 break; \
1459 default: \
1460 printf("ERROR: %s: unhandled b case (%d)\n", __func__, bo); \
1461 SET_RETVAL(EXCP_INVAL); \
1462 break; \
1463 } \
1464 } else { \
1465 switch (bo & 0x6) { \
1466 case 0: \
1467 if (LK(ctx->opcode)) { \
1468 bl_ctr_false; \
1469 } else { \
1470 b_ctr_false; \
1471 } \
1472 break; \
1473 case 2: \
1474 if (LK(ctx->opcode)) { \
1475 bl_ctrz_false; \
1476 } else { \
1477 b_ctrz_false; \
1478 } \
1479 break; \
1480 case 4: \
1481 case 6: \
1482 if (LK(ctx->opcode)) { \
1483 bl_false; \
1484 } else { \
1485 b_false; \
1486 } \
1487 break; \
1488 default: \
1489 printf("ERROR: %s: unhandled bn case (%d)\n", __func__, bo); \
1490 SET_RETVAL(EXCP_INVAL); \
1491 break; \
1492 } \
1493 } \
1494 } \
1495 SET_RETVAL(EXCP_BRANCH); \
1496}
1497
1498/* b ba bl bla */
1499GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
1500{
1501 uint32_t li = s_ext24(LI(ctx->opcode)), target;
1502
1503 if (AA(ctx->opcode) == 0)
1504 target = (uint32_t)ctx->nip + li - 4;
1505 else
1506 target = s_ext24(LI(ctx->opcode));
1507 gen_op_b(target);
1508 if (LK(ctx->opcode))
1509 gen_op_load_lr((uint32_t)ctx->nip);
1510 SET_RETVAL(EXCP_BRANCH);
1511}
1512
1513/* bc bca bcl bcla */
1514GEN_BCOND(bc, 0x10, 0xFF, 0xFF,
1515 do {
1516 uint32_t li = s_ext16(BD(ctx->opcode));
1517 if (AA(ctx->opcode) == 0) {
1518 target = (uint32_t)ctx->nip + li - 4;
1519 } else {
1520 target = li;
1521 }
1522 } while (0),
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),
1527 gen_op_b(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));
1540
1541/* bcctr bcctrl */
1542GEN_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),
1547 gen_op_bctr(),
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))
1560
1561/* bclr bclrl */
1562GEN_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),
1567 gen_op_blr(),
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))
1580
1581/*** Condition register logical ***/
1582#define GEN_CRLOGIC(op, opc) \
1583GEN_HANDLER(cr##op, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER) \
1584{ \
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)); \
1589 gen_op_##op(); \
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); \
1594 SET_RETVAL(0); \
1595}
1596
1597/* crand */
1598GEN_CRLOGIC(and, 0x08)
1599/* crandc */
1600GEN_CRLOGIC(andc, 0x04)
1601/* creqv */
1602GEN_CRLOGIC(eqv, 0x09)
1603/* crnand */
1604GEN_CRLOGIC(nand, 0x07)
1605/* crnor */
1606GEN_CRLOGIC(nor, 0x01)
1607/* cror */
1608GEN_CRLOGIC(or, 0x0E)
1609/* crorc */
1610GEN_CRLOGIC(orc, 0x0D)
1611/* crxor */
1612GEN_CRLOGIC(xor, 0x06)
1613/* mcrf */
1614GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER)
1615{
1616 gen_op_load_crf_T0(crfS(ctx->opcode));
1617 gen_op_store_T0_crf(crfD(ctx->opcode));
1618 SET_RETVAL(0);
1619}
1620
1621/*** System linkage ***/
1622/* rfi (supervisor only) */
1623GEN_HANDLER(rfi, 0x13, 0x12, 0xFF, 0x03FF8001, PPC_FLOW)
1624{
1625 SET_RETVAL(EXCP_INVAL);
1626}
1627
1628/* sc */
1629GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFFFFD, PPC_FLOW)
1630{
1631 gen_op_b((uint32_t)ctx->nip);
1632 SET_RETVAL(EXCP_SYSCALL);
1633}
1634
1635/*** Trap ***/
1636/* tw */
1637GEN_HANDLER(tw, 0x1F, 0x04, 0xFF, 0x00000001, PPC_FLOW)
1638{
1639 SET_RETVAL(EXCP_INVAL);
1640}
1641
1642/* twi */
1643GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
1644{
1645 SET_RETVAL(EXCP_INVAL);
1646}
1647
1648/*** Processor control ***/
1649static inline int check_spr_access (int spr, int rw, int supervisor)
1650{
1651 uint32_t rights = spr_access[spr >> 1] >> (4 * (spr & 1));
1652
1653 rights = rights >> (2 * supervisor);
1654 rights = rights >> rw;
1655
1656 return rights & 1;
1657}
1658
1659/* mcrxr */
1660GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC)
1661{
1662 gen_op_load_xer_cr();
1663 gen_op_store_T0_crf(crfD(ctx->opcode));
1664 gen_op_clear_xer_cr();
1665 SET_RETVAL(0);
1666}
1667
1668/* mfcr */
1669GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x001FF801, PPC_MISC)
1670{
1671 gen_op_load_cr();
1672 gen_op_store_T0_gpr(rD(ctx->opcode));
1673 SET_RETVAL(0);
1674}
1675
1676/* mfmsr */
1677GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC)
1678{
1679 if (!ctx->supervisor)
1680 SET_RETVAL(EXCP_PRIV);
1681 gen_op_load_msr();
1682 gen_op_store_T0_gpr(rD(ctx->opcode));
1683 SET_RETVAL(0);
1684}
1685
1686/* mfspr */
1687GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC)
1688{
1689 uint32_t sprn = SPR(ctx->opcode);
1690
1691 if (check_spr_access(sprn, 0, ctx->supervisor) == 0)
1692 SET_RETVAL(EXCP_PRIV);
1693 /* XXX: make this more generic */
1694 switch (sprn) {
1695 case SPR_ENCODE(1):
1696 if (loglevel > 0) {
1697 fprintf(logfile, "LOAD XER at %p\n", ctx->nip - 1);
1698 }
1699 gen_op_load_xer();
1700 break;
1701 case SPR_ENCODE(268):
1702 /* We need to update the time base before reading it */
1703 gen_op_update_tb(ctx->tb_offset);
1704 ctx->tb_offset = 0;
1705 break;
1706 case SPR_ENCODE(269):
1707 gen_op_update_tb(ctx->tb_offset);
1708 ctx->tb_offset = 0;
1709 break;
1710 default:
1711 gen_op_load_spr(sprn);
1712 break;
1713 }
1714 gen_op_store_T0_gpr(rD(ctx->opcode)); //
1715 SET_RETVAL(0);
1716}
1717
1718/* mftb */
1719GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MISC)
1720{
1721 uint32_t sprn = SPR(ctx->opcode);
1722
1723 if (check_spr_access(sprn, 0, ctx->supervisor) == 0)
1724 SET_RETVAL(EXCP_PRIV);
1725 switch (sprn) {
1726 case SPR_ENCODE(268):
1727 /* We need to update the time base before reading it */
1728 gen_op_update_tb(ctx->tb_offset);
1729 ctx->tb_offset = 0;
1730 break;
1731 case SPR_ENCODE(269):
1732 gen_op_update_tb(ctx->tb_offset);
1733 ctx->tb_offset = 0;
1734 break;
1735 default:
1736 SET_RETVAL(EXCP_INVAL);
1737 break;
1738 }
1739 SET_RETVAL(0);
1740}
1741
1742/* mtcrf */
1743GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00100801, PPC_MISC)
1744{
1745 gen_op_load_gpr_T0(rS(ctx->opcode));
1746 gen_op_store_cr(CRM(ctx->opcode));
1747 SET_RETVAL(0);
1748}
1749
1750/* mtmsr */
1751GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC)
1752{
1753 if (!ctx->supervisor)
1754 SET_RETVAL(EXCP_PRIV);
1755 gen_op_load_gpr_T0(rS(ctx->opcode));
1756 gen_op_store_msr();
1757 /* Must stop the translation as machine state (may have) changed */
1758 SET_RETVAL(EXCP_MTMSR);
1759}
1760
1761/* mtspr */
1762GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC)
1763{
1764 uint32_t sprn = SPR(ctx->opcode);
1765
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)) {
1770 gen_op_store_xer();
1771 } else {
1772 gen_op_store_spr(sprn);
1773 }
1774 SET_RETVAL(0);
1775}
1776
1777/*** Cache management ***/
1778/* For now, all those will be implemented as nop:
1779 * this is valid, regarding the PowerPC specs...
1780 */
1781/* dcbf */
1782GEN_HANDLER(dcbf, 0x1F, 0x16, 0x17, 0x03E00001, PPC_MEM)
1783{
1784 SET_RETVAL(0);
1785}
1786
1787/* dcbi (Supervisor only) */
1788GEN_HANDLER(dcbi, 0x1F, 0x16, 0x1F, 0x03E00001, PPC_MEM)
1789{
1790 SET_RETVAL(0);
1791}
1792
1793/* dcdst */
1794GEN_HANDLER(dcbst, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_MEM)
1795{
1796 SET_RETVAL(0);
1797}
1798
1799/* dcbt */
1800GEN_HANDLER(dcbt, 0x1F, 0x16, 0x01, 0x03E00001, PPC_MEM)
1801{
1802 SET_RETVAL(0);
1803}
1804
1805/* dcbtst */
1806GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x02, 0x03E00001, PPC_MEM)
1807{
1808 SET_RETVAL(0);
1809}
1810
1811/* dcbz */
1812GEN_HANDLER(dcbz, 0x1F, 0x16, 0x08, 0x03E00001, PPC_MEM)
1813{
1814 SET_RETVAL(0);
1815}
1816
1817/* icbi */
1818GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_MEM)
1819{
1820 SET_RETVAL(0);
1821}
1822
1823/* Optional: */
1824/* dcba */
1825GEN_HANDLER(dcba, 0x1F, 0x16, 0x07, 0x03E00001, PPC_MEM)
1826{
1827 SET_RETVAL(0);
1828}
1829
1830/*** Segment register manipulation ***/
1831/* Supervisor only: */
1832/* mfsr */
1833GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT)
1834{
1835 SET_RETVAL(EXCP_INVAL);
1836}
1837
1838/* mfsrin */
1839GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x0010F001, PPC_SEGMENT)
1840{
1841 SET_RETVAL(EXCP_INVAL);
1842}
1843
1844/* mtsr */
1845GEN_HANDLER(mtsr, 0x1F, 0x12, 0x02, 0x0010F801, PPC_SEGMENT)
1846{
1847 SET_RETVAL(EXCP_INVAL);
1848}
1849
1850/* mtsrin */
1851GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x0010F001, PPC_SEGMENT)
1852{
1853 SET_RETVAL(EXCP_INVAL);
1854}
1855
1856/*** Lookaside buffer management ***/
1857/* Optional & supervisor only: */
1858/* tlbia */
1859GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM)
1860{
1861 SET_RETVAL(EXCP_INVAL);
1862}
1863
1864/* tlbie */
1865GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF8001, PPC_MEM)
1866{
1867 SET_RETVAL(EXCP_INVAL);
1868}
1869
1870/* tlbsync */
1871GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFFC01, PPC_MEM)
1872{
1873 SET_RETVAL(EXCP_INVAL);
1874}
1875
1876/*** External control ***/
1877/* Optional: */
1878/* eciwx */
1879GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN)
1880{
1881 SET_RETVAL(EXCP_INVAL);
1882}
1883
1884/* ecowx */
1885GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN)
1886{
1887 SET_RETVAL(EXCP_INVAL);
1888}
1889
1890/* End opcode list */
1891GEN_OPCODE_MARK(end);
1892
1893/*****************************************************************************/
1894
1895#include <string.h>
1896extern FILE *stderr;
1897void free (void *p);
1898int fflush (FILE *f);
1899
1900/* Main ppc opcodes table:
1901 * at init, all opcodes are invalids
1902 */
1903static opc_handler_t *ppc_opcodes[0x40];
1904
1905/* Opcode types */
1906enum {
1907 PPC_DIRECT = 0, /* Opcode routine */
1908 PPC_INDIRECT = 1, /* Indirect opcode table */
1909};
1910
1911static inline int is_indirect_opcode (void *handler)
1912{
1913 return ((unsigned long)handler & 0x03) == PPC_INDIRECT;
1914}
1915
1916static inline opc_handler_t **ind_table(void *handler)
1917{
1918 return (opc_handler_t **)((unsigned long)handler & ~3);
1919}
1920
1921/* Opcodes tables creation */
1922static void fill_new_table (opc_handler_t **table, int len)
1923{
1924 int i;
1925
1926 for (i = 0; i < len; i++)
1927 table[i] = &invalid_handler;
1928}
1929
1930static int create_new_table (opc_handler_t **table, unsigned char idx)
1931{
1932 opc_handler_t **tmp;
1933
1934 tmp = malloc(0x20 * sizeof(opc_handler_t));
1935 if (tmp == NULL)
1936 return -1;
1937 fill_new_table(tmp, 0x20);
1938 table[idx] = (opc_handler_t *)((unsigned long)tmp | PPC_INDIRECT);
1939
1940 return 0;
1941}
1942
1943static int insert_in_table (opc_handler_t **table, unsigned char idx,
1944 opc_handler_t *handler)
1945{
1946 if (table[idx] != &invalid_handler)
1947 return -1;
1948 table[idx] = handler;
1949
1950 return 0;
1951}
1952
1953static int register_direct_insn (unsigned char idx, opc_handler_t *handler)
1954{
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);
1958 return -1;
1959 }
1960
1961 return 0;
1962}
1963
1964static int register_ind_in_table (opc_handler_t **table,
1965 unsigned char idx1, unsigned char idx2,
1966 opc_handler_t *handler)
1967{
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);
1972 return -1;
1973 }
1974 } else {
1975 if (!is_indirect_opcode(table[idx1])) {
1976 fprintf(stderr, "*** ERROR: idx %02x already assigned to a direct "
1977 "opcode\n", idx1);
1978 return -1;
1979 }
1980 }
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);
1985 return -1;
1986 }
1987
1988 return 0;
1989}
1990
1991static int register_ind_insn (unsigned char idx1, unsigned char idx2,
1992 opc_handler_t *handler)
1993{
1994 int ret;
1995
1996 ret = register_ind_in_table(ppc_opcodes, idx1, idx2, handler);
1997
1998 return ret;
1999}
2000
2001static int register_dblind_insn (unsigned char idx1, unsigned char idx2,
2002 unsigned char idx3, opc_handler_t *handler)
2003{
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);
2007 return -1;
2008 }
2009 if (register_ind_in_table(ind_table(ppc_opcodes[idx1]), idx2, idx3,
2010 handler) < 0) {
2011 fprintf(stderr, "*** ERROR: unable to insert opcode "
2012 "[%02x-%02x-%02x]\n", idx1, idx2, idx3);
2013 return -1;
2014 }
2015
2016 return 0;
2017}
2018
2019static int register_insn (opcode_t *insn)
2020{
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)
2025 return -1;
2026 } else {
2027 if (register_ind_insn(insn->opc1, insn->opc2, &insn->handler) < 0)
2028 return -1;
2029 }
2030 } else {
2031 if (register_direct_insn(insn->opc1, &insn->handler) < 0)
2032 return -1;
2033 }
2034
2035 return 0;
2036}
2037
2038static int test_opcode_table (opc_handler_t **table, int len)
2039{
2040 int i, count, tmp;
2041
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);
2049 if (tmp == 0) {
2050 free(table[i]);
2051 table[i] = &invalid_handler;
2052 } else {
2053 count++;
2054 }
2055 } else {
2056 count++;
2057 }
2058 }
2059 }
2060
2061 return count;
2062}
2063
2064static void fix_opcode_tables (void)
2065{
2066 if (test_opcode_table(ppc_opcodes, 0x40) == 0)
2067 fprintf(stderr, "*** WARNING: no opcode defined !\n");
2068}
2069
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)
2075
2076#define spr_set_rights(spr, rights) \
2077do { \
2078 spr_access[(spr) >> 1] |= ((rights) << (4 * ((spr) & 1))); \
2079} while (0)
2080
2081static void init_spr_rights (void)
2082{
2083 /* XER (SPR 1) */
2084 spr_set_rights(SPR_ENCODE(1), SPR_UR | SPR_UW | SPR_SR | SPR_SW);
2085 /* LR (SPR 8) */
2086 spr_set_rights(SPR_ENCODE(8), SPR_UR | SPR_UW | SPR_SR | SPR_SW);
2087 /* CTR (SPR 9) */
2088 spr_set_rights(SPR_ENCODE(9), SPR_UR | SPR_UW | SPR_SR | SPR_SW);
2089 /* TBL (SPR 268) */
2090 spr_set_rights(SPR_ENCODE(268), SPR_UR | SPR_SR);
2091 /* TBU (SPR 269) */
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);
2095 /* DAR (SPR 19) */
2096 spr_set_rights(SPR_ENCODE(19), SPR_SR | SPR_SW);
2097 /* DEC (SPR 22) */
2098 spr_set_rights(SPR_ENCODE(22), SPR_SR | SPR_SW);
2099 /* SDR1 (SPR 25) */
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);
2109 /* ASR (SPR 280) */
2110 spr_set_rights(SPR_ENCODE(281), SPR_SR | SPR_SW);
2111 /* EAR (SPR 282) */
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);
2151 /* PVR (SPR 287) */
2152 spr_set_rights(SPR_ENCODE(287), SPR_SR);
2153 /* TBL (SPR 284) */
2154 spr_set_rights(SPR_ENCODE(284), SPR_SW);
2155 /* TBU (SPR 285) */
2156 spr_set_rights(SPR_ENCODE(285), SPR_SW);
2157}
2158
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)
2162
2163typedef struct ppc_proc_t {
2164 int flags;
2165 void *specific;
2166} ppc_proc_t;
2167
2168typedef struct ppc_def_t {
2169 unsigned long pvr;
2170 unsigned long pvr_mask;
2171 ppc_proc_t *proc;
2172} ppc_def_t;
2173
2174static ppc_proc_t ppc_proc_common = {
2175 .flags = PPC_COMMON,
2176 .specific = NULL,
2177};
2178
2179static ppc_def_t ppc_defs[] =
2180{
2181 /* Fallback */
2182 {
2183 .pvr = 0x00000000,
2184 .pvr_mask = 0x00000000,
2185 .proc = &ppc_proc_common,
2186 },
2187};
2188
2189static int create_ppc_proc (unsigned long pvr)
2190{
2191 opcode_t *opc;
2192 int i, flags;
2193
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;
2199 break;
2200 }
2201 }
2202
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,
2208 opc->opc3);
2209 return -1;
2210 }
2211 }
2212 fix_opcode_tables();
2213
2214 return 0;
2215}
2216
2217/*****************************************************************************/
2218uint32_t do_load_xer (void);
2219
2220void cpu_ppc_dump_state(CPUPPCState *env, FILE *f, int flags)
2221{
2222 int i;
2223
2224 if (loglevel > 0) {
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++) {
2228 if ((i & 7) == 0)
2229 fprintf(logfile, "GPR%02d:", i);
2230 fprintf(logfile, " %08x", env->gpr[i]);
2231 if ((i & 7) == 7)
2232 fprintf(logfile, "\n");
2233 }
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++) {
2239 char a = '-';
2240
2241 if (env->crf[i] & 0x08)
2242 a = 'L';
2243 else if (env->crf[i] & 0x04)
2244 a = 'G';
2245 else if (env->crf[i] & 0x02)
2246 a = 'E';
2247 fprintf(logfile, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
2248 }
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++) {
2253 if ((i & 3) == 0)
2254 fprintf(logfile, "FPR%02d:", i);
2255 fprintf(logfile, " %016llx", env->fpr[i]);
2256 if ((i & 3) == 3)
2257 fprintf(logfile, "\n");
2258 }
2259 fflush(logfile);
2260 }
2261}
2262
2263CPUPPCState *cpu_ppc_init(void)
2264{
2265 CPUPPCState *env;
2266
2267 cpu_exec_init();
2268
2269 env = malloc(sizeof(CPUPPCState));
2270 if (!env)
2271 return NULL;
2272 memset(env, 0, sizeof(CPUPPCState));
2273 env->PVR = 0;
2274 if (create_ppc_proc(0) < 0)
2275 return NULL;
2276 init_spr_rights();
2277
2278 return env;
2279}
2280
2281void cpu_ppc_close(CPUPPCState *env)
2282{
2283 /* Should also remove all opcode tables... */
2284 free(env);
2285}
2286
2287int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
2288 int search_pc)
2289{
2290 DisasContext ctx;
2291 opc_handler_t **table, *handler;
2292 uint32_t pc_start;
2293 uint16_t *gen_opc_end;
2294 int j, lj = -1;
2295 int ret = 0;
2296
2297 pc_start = tb->pc;
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;
2302 ctx.tb_offset = 0;
2303 ctx.supervisor = msr_ip;
2304 ctx.tb = tb;
2305 ctx.exception = 0;
2306
2307 while (ret == 0 && gen_opc_ptr < gen_opc_end) {
2308 if (search_pc) {
2309 if (loglevel > 0)
2310 fprintf(logfile, "Search PC...\n");
2311 j = gen_opc_ptr - gen_opc_buf;
2312 if (lj < j) {
2313 lj++;
2314 while (lj < j)
2315 gen_opc_instr_start[lj++] = 0;
2316 gen_opc_pc[lj] = (uint32_t)ctx.nip;
2317 gen_opc_instr_start[lj] = 1;
2318 }
2319 }
2320 ctx.opcode = __be32_to_cpu(*ctx.nip);
2321#ifdef DEBUG_DISAS
2322 if (loglevel > 0) {
2323 fprintf(logfile, "----------------\n");
2324 fprintf(logfile, "%p: translate opcode %08x\n",
2325 ctx.nip, ctx.opcode);
2326 }
2327#endif
2328 ctx.nip++;
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)];
2337 }
2338 }
2339 /* Is opcode *REALLY* valid ? */
2340 if ((ctx.opcode & handler->inval) != 0) {
2341 if (loglevel > 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);
2346 } else {
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),
2351 handler->handler);
2352 }
2353 }
2354 ret = GET_RETVAL(gen_invalid, ctx.opcode);
2355 } else {
2356 ret = GET_RETVAL(*(handler->handler), ctx.opcode);
2357 }
2358 ctx.tb_offset++;
2359#if defined (DO_SINGLE_STEP)
2360 break;
2361#endif
2362 }
2363#if defined (DO_STEP_FLUSH)
2364 tb_flush();
2365#endif
2366 /* We need to update the time base */
2367 if (!search_pc)
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
2371 */
2372#if defined (DO_SINGLE_STEP)
2373 if (ret == 0) {
2374 gen_op_b((uint32_t)ctx.nip);
2375 ret = EXCP_BRANCH;
2376 }
2377#endif
2378 /* If the exeption isn't a PPC one,
2379 * generate it now.
2380 */
2381 if (ret != EXCP_BRANCH) {
2382 gen_op_set_T0(0);
2383 if ((ret & 0x2000) == 0)
2384 gen_op_raise_exception(ret);
2385 }
2386 /* TO BE FIXED: T0 hasn't got a proper value, which makes tb_add_jump
2387 * do bad business and then qemu crashes !
2388 */
2389 gen_op_set_T0(0);
2390 /* Generate the return instruction */
2391 gen_op_exit_tb();
2392 *gen_opc_ptr = INDEX_op_end;
2393 if (!search_pc)
2394 tb->size = (uint32_t)ctx.nip - pc_start;
2395 else
2396 tb->size = 0;
2397// *gen_opc_ptr = INDEX_op_end;
2398#ifdef DEBUG_DISAS
2399 if (loglevel > 0) {
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");
2403
2404 fprintf(logfile, "OP:\n");
2405 dump_ops(gen_opc_buf, gen_opparam_buf);
2406 fprintf(logfile, "\n");
2407 }
2408#endif
2409
2410 return 0;
2411}
2412
2413int gen_intermediate_code(CPUState *env, struct TranslationBlock *tb)
2414{
2415 return gen_intermediate_code_internal(env, tb, 0);
2416}
2417
2418int gen_intermediate_code_pc(CPUState *env, struct TranslationBlock *tb)
2419{
2420 return gen_intermediate_code_internal(env, tb, 1);
2421}