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