]> git.proxmox.com Git - qemu.git/blame - target-ppc/translate.c
disable PCI device for PMAC
[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 */
c6a1c22b
FB
20#include <stdarg.h>
21#include <stdlib.h>
22#include <stdio.h>
23#include <string.h>
24#include <inttypes.h>
25
79aceca5 26#include "cpu.h"
c6a1c22b 27#include "exec-all.h"
79aceca5
FB
28#include "disas.h"
29
30//#define DO_SINGLE_STEP
9fddaa0c 31//#define PPC_DEBUG_DISAS
79aceca5
FB
32
33enum {
34#define DEF(s, n, copy_size) INDEX_op_ ## s,
35#include "opc.h"
36#undef DEF
37 NB_OPS,
38};
39
40static uint16_t *gen_opc_ptr;
41static uint32_t *gen_opparam_ptr;
42
43#include "gen-op.h"
28b6751f 44
28b6751f 45#define GEN8(func, NAME) \
9a64fbe4
FB
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 GEN16(func, NAME) \
56static GenOpFunc *NAME ## _table [16] = { \
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, \
61}; \
62static inline void func(int n) \
63{ \
64 NAME ## _table[n](); \
28b6751f
FB
65}
66
67#define GEN32(func, NAME) \
9a64fbe4
FB
68static GenOpFunc *NAME ## _table [32] = { \
69NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
70NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
71NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
72NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
73NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \
74NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \
75NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \
76NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \
77}; \
78static inline void func(int n) \
79{ \
80 NAME ## _table[n](); \
81}
82
83/* Condition register moves */
84GEN8(gen_op_load_crf_T0, gen_op_load_crf_T0_crf);
85GEN8(gen_op_load_crf_T1, gen_op_load_crf_T1_crf);
86GEN8(gen_op_store_T0_crf, gen_op_store_T0_crf_crf);
87GEN8(gen_op_store_T1_crf, gen_op_store_T1_crf_crf);
28b6751f 88
fb0eaffc
FB
89/* Floating point condition and status register moves */
90GEN8(gen_op_load_fpscr_T0, gen_op_load_fpscr_T0_fpscr);
91GEN8(gen_op_store_T0_fpscr, gen_op_store_T0_fpscr_fpscr);
92GEN8(gen_op_clear_fpscr, gen_op_clear_fpscr_fpscr);
93static GenOpFunc1 *gen_op_store_T0_fpscri_fpscr_table[8] = {
94 &gen_op_store_T0_fpscri_fpscr0,
95 &gen_op_store_T0_fpscri_fpscr1,
96 &gen_op_store_T0_fpscri_fpscr2,
97 &gen_op_store_T0_fpscri_fpscr3,
98 &gen_op_store_T0_fpscri_fpscr4,
99 &gen_op_store_T0_fpscri_fpscr5,
100 &gen_op_store_T0_fpscri_fpscr6,
101 &gen_op_store_T0_fpscri_fpscr7,
102};
103static inline void gen_op_store_T0_fpscri(int n, uint8_t param)
104{
105 (*gen_op_store_T0_fpscri_fpscr_table[n])(param);
106}
107
9a64fbe4
FB
108/* Segment register moves */
109GEN16(gen_op_load_sr, gen_op_load_sr);
110GEN16(gen_op_store_sr, gen_op_store_sr);
28b6751f 111
9a64fbe4
FB
112/* General purpose registers moves */
113GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr);
114GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr);
115GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr);
116
117GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr);
118GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr);
119GEN32(gen_op_store_T2_gpr, gen_op_store_T2_gpr_gpr);
28b6751f 120
fb0eaffc
FB
121/* floating point registers moves */
122GEN32(gen_op_load_fpr_FT0, gen_op_load_fpr_FT0_fpr);
123GEN32(gen_op_load_fpr_FT1, gen_op_load_fpr_FT1_fpr);
124GEN32(gen_op_load_fpr_FT2, gen_op_load_fpr_FT2_fpr);
125GEN32(gen_op_store_FT0_fpr, gen_op_store_FT0_fpr_fpr);
126GEN32(gen_op_store_FT1_fpr, gen_op_store_FT1_fpr_fpr);
127GEN32(gen_op_store_FT2_fpr, gen_op_store_FT2_fpr_fpr);
79aceca5
FB
128
129static uint8_t spr_access[1024 / 2];
130
131/* internal defines */
132typedef struct DisasContext {
133 struct TranslationBlock *tb;
046d6672 134 uint32_t nip;
79aceca5 135 uint32_t opcode;
9a64fbe4 136 uint32_t exception;
9a64fbe4
FB
137 /* Execution mode */
138#if !defined(CONFIG_USER_ONLY)
79aceca5 139 int supervisor;
9a64fbe4
FB
140#endif
141 /* Routine used to access memory */
142 int mem_idx;
79aceca5
FB
143} DisasContext;
144
145typedef struct opc_handler_t {
146 /* invalid bits */
147 uint32_t inval;
9a64fbe4
FB
148 /* instruction type */
149 uint32_t type;
79aceca5
FB
150 /* handler */
151 void (*handler)(DisasContext *ctx);
152} opc_handler_t;
153
9fddaa0c 154#define RET_EXCP(ctx, excp, error) \
79aceca5 155do { \
9fddaa0c
FB
156 if ((ctx)->exception == EXCP_NONE) { \
157 gen_op_update_nip((ctx)->nip); \
158 } \
159 gen_op_raise_exception_err((excp), (error)); \
160 ctx->exception = (excp); \
79aceca5
FB
161} while (0)
162
9fddaa0c
FB
163#define RET_INVAL(ctx) \
164RET_EXCP((ctx), EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL)
165
166#define RET_PRIVOPC(ctx) \
167RET_EXCP((ctx), EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_OPC)
9a64fbe4 168
9fddaa0c
FB
169#define RET_PRIVREG(ctx) \
170RET_EXCP((ctx), EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG)
9a64fbe4 171
9fddaa0c
FB
172#define RET_MTMSR(ctx) \
173RET_EXCP((ctx), EXCP_MTMSR, 0)
79aceca5
FB
174
175#define GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
176static void gen_##name (DisasContext *ctx); \
177GEN_OPCODE(name, opc1, opc2, opc3, inval, type); \
178static void gen_##name (DisasContext *ctx)
179
79aceca5
FB
180typedef struct opcode_t {
181 unsigned char opc1, opc2, opc3;
79aceca5
FB
182 opc_handler_t handler;
183} opcode_t;
184
79aceca5
FB
185/*** Instruction decoding ***/
186#define EXTRACT_HELPER(name, shift, nb) \
187static inline uint32_t name (uint32_t opcode) \
188{ \
189 return (opcode >> (shift)) & ((1 << (nb)) - 1); \
190}
191
192#define EXTRACT_SHELPER(name, shift, nb) \
193static inline int32_t name (uint32_t opcode) \
194{ \
195 return s_ext16((opcode >> (shift)) & ((1 << (nb)) - 1)); \
196}
197
198/* Opcode part 1 */
199EXTRACT_HELPER(opc1, 26, 6);
200/* Opcode part 2 */
201EXTRACT_HELPER(opc2, 1, 5);
202/* Opcode part 3 */
203EXTRACT_HELPER(opc3, 6, 5);
204/* Update Cr0 flags */
205EXTRACT_HELPER(Rc, 0, 1);
206/* Destination */
207EXTRACT_HELPER(rD, 21, 5);
208/* Source */
209EXTRACT_HELPER(rS, 21, 5);
210/* First operand */
211EXTRACT_HELPER(rA, 16, 5);
212/* Second operand */
213EXTRACT_HELPER(rB, 11, 5);
214/* Third operand */
215EXTRACT_HELPER(rC, 6, 5);
216/*** Get CRn ***/
217EXTRACT_HELPER(crfD, 23, 3);
218EXTRACT_HELPER(crfS, 18, 3);
219EXTRACT_HELPER(crbD, 21, 5);
220EXTRACT_HELPER(crbA, 16, 5);
221EXTRACT_HELPER(crbB, 11, 5);
222/* SPR / TBL */
223EXTRACT_HELPER(SPR, 11, 10);
224/*** Get constants ***/
225EXTRACT_HELPER(IMM, 12, 8);
226/* 16 bits signed immediate value */
227EXTRACT_SHELPER(SIMM, 0, 16);
228/* 16 bits unsigned immediate value */
229EXTRACT_HELPER(UIMM, 0, 16);
230/* Bit count */
231EXTRACT_HELPER(NB, 11, 5);
232/* Shift count */
233EXTRACT_HELPER(SH, 11, 5);
234/* Mask start */
235EXTRACT_HELPER(MB, 6, 5);
236/* Mask end */
237EXTRACT_HELPER(ME, 1, 5);
fb0eaffc
FB
238/* Trap operand */
239EXTRACT_HELPER(TO, 21, 5);
79aceca5
FB
240
241EXTRACT_HELPER(CRM, 12, 8);
242EXTRACT_HELPER(FM, 17, 8);
243EXTRACT_HELPER(SR, 16, 4);
fb0eaffc
FB
244EXTRACT_HELPER(FPIMM, 20, 4);
245
79aceca5
FB
246/*** Jump target decoding ***/
247/* Displacement */
248EXTRACT_SHELPER(d, 0, 16);
249/* Immediate address */
250static inline uint32_t LI (uint32_t opcode)
251{
252 return (opcode >> 0) & 0x03FFFFFC;
253}
254
255static inline uint32_t BD (uint32_t opcode)
256{
257 return (opcode >> 0) & 0xFFFC;
258}
259
260EXTRACT_HELPER(BO, 21, 5);
261EXTRACT_HELPER(BI, 16, 5);
262/* Absolute/relative address */
263EXTRACT_HELPER(AA, 1, 1);
264/* Link */
265EXTRACT_HELPER(LK, 0, 1);
266
267/* Create a mask between <start> and <end> bits */
268static inline uint32_t MASK (uint32_t start, uint32_t end)
269{
270 uint32_t ret;
271
272 ret = (((uint32_t)(-1)) >> (start)) ^ (((uint32_t)(-1) >> (end)) >> 1);
273 if (start > end)
274 return ~ret;
275
276 return ret;
277}
278
279#define GEN_OPCODE(name, op1, op2, op3, invl, _typ) \
1ef59d0a 280__attribute__ ((section(".opcodes"), unused, aligned (8) )) \
79aceca5
FB
281static opcode_t opc_##name = { \
282 .opc1 = op1, \
283 .opc2 = op2, \
284 .opc3 = op3, \
79aceca5
FB
285 .handler = { \
286 .inval = invl, \
9a64fbe4 287 .type = _typ, \
79aceca5
FB
288 .handler = &gen_##name, \
289 }, \
290}
291
292#define GEN_OPCODE_MARK(name) \
1ef59d0a 293__attribute__ ((section(".opcodes"), unused, aligned (8) )) \
79aceca5
FB
294static opcode_t opc_##name = { \
295 .opc1 = 0xFF, \
296 .opc2 = 0xFF, \
297 .opc3 = 0xFF, \
79aceca5
FB
298 .handler = { \
299 .inval = 0x00000000, \
9a64fbe4 300 .type = 0x00, \
79aceca5
FB
301 .handler = NULL, \
302 }, \
303}
304
305/* Start opcode list */
306GEN_OPCODE_MARK(start);
307
308/* Invalid instruction */
9a64fbe4
FB
309GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE)
310{
9fddaa0c 311 RET_INVAL(ctx);
9a64fbe4
FB
312}
313
314/* Special opcode to stop emulation */
315GEN_HANDLER(stop, 0x06, 0x00, 0xFF, 0x03FFFFC1, PPC_COMMON)
79aceca5 316{
9fddaa0c 317 RET_EXCP(ctx, EXCP_HLT, 0);
9a64fbe4
FB
318}
319
320/* Special opcode to call open-firmware */
321GEN_HANDLER(of_enter, 0x06, 0x01, 0xFF, 0x03FFFFC1, PPC_COMMON)
322{
9fddaa0c 323 RET_EXCP(ctx, EXCP_OFCALL, 0);
9a64fbe4
FB
324}
325
326/* Special opcode to call RTAS */
327GEN_HANDLER(rtas_enter, 0x06, 0x02, 0xFF, 0x03FFFFC1, PPC_COMMON)
328{
329 printf("RTAS entry point !\n");
9fddaa0c 330 RET_EXCP(ctx, EXCP_RTASCALL, 0);
79aceca5
FB
331}
332
333static opc_handler_t invalid_handler = {
334 .inval = 0xFFFFFFFF,
9a64fbe4 335 .type = PPC_NONE,
79aceca5
FB
336 .handler = gen_invalid,
337};
338
339/*** Integer arithmetic ***/
340#define __GEN_INT_ARITH2(name, opc1, opc2, opc3, inval) \
341GEN_HANDLER(name, opc1, opc2, opc3, inval, PPC_INTEGER) \
342{ \
343 gen_op_load_gpr_T0(rA(ctx->opcode)); \
344 gen_op_load_gpr_T1(rB(ctx->opcode)); \
345 gen_op_##name(); \
346 if (Rc(ctx->opcode) != 0) \
347 gen_op_set_Rc0(); \
348 gen_op_store_T0_gpr(rD(ctx->opcode)); \
79aceca5
FB
349}
350
351#define __GEN_INT_ARITH2_O(name, opc1, opc2, opc3, inval) \
352GEN_HANDLER(name, opc1, opc2, opc3, inval, PPC_INTEGER) \
353{ \
354 gen_op_load_gpr_T0(rA(ctx->opcode)); \
355 gen_op_load_gpr_T1(rB(ctx->opcode)); \
356 gen_op_##name(); \
357 if (Rc(ctx->opcode) != 0) \
358 gen_op_set_Rc0_ov(); \
359 gen_op_store_T0_gpr(rD(ctx->opcode)); \
79aceca5
FB
360}
361
362#define __GEN_INT_ARITH1(name, opc1, opc2, opc3) \
363GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, PPC_INTEGER) \
364{ \
365 gen_op_load_gpr_T0(rA(ctx->opcode)); \
366 gen_op_##name(); \
367 if (Rc(ctx->opcode) != 0) \
368 gen_op_set_Rc0(); \
369 gen_op_store_T0_gpr(rD(ctx->opcode)); \
79aceca5
FB
370}
371#define __GEN_INT_ARITH1_O(name, opc1, opc2, opc3) \
372GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, PPC_INTEGER) \
373{ \
374 gen_op_load_gpr_T0(rA(ctx->opcode)); \
375 gen_op_##name(); \
376 if (Rc(ctx->opcode) != 0) \
377 gen_op_set_Rc0_ov(); \
378 gen_op_store_T0_gpr(rD(ctx->opcode)); \
79aceca5
FB
379}
380
381/* Two operands arithmetic functions */
382#define GEN_INT_ARITH2(name, opc1, opc2, opc3) \
383__GEN_INT_ARITH2(name, opc1, opc2, opc3, 0x00000000) \
384__GEN_INT_ARITH2_O(name##o, opc1, opc2, opc3 | 0x10, 0x00000000)
385
386/* Two operands arithmetic functions with no overflow allowed */
387#define GEN_INT_ARITHN(name, opc1, opc2, opc3) \
388__GEN_INT_ARITH2(name, opc1, opc2, opc3, 0x00000400)
389
390/* One operand arithmetic functions */
391#define GEN_INT_ARITH1(name, opc1, opc2, opc3) \
392__GEN_INT_ARITH1(name, opc1, opc2, opc3) \
393__GEN_INT_ARITH1_O(name##o, opc1, opc2, opc3 | 0x10)
394
395/* add add. addo addo. */
396GEN_INT_ARITH2 (add, 0x1F, 0x0A, 0x08);
397/* addc addc. addco addco. */
398GEN_INT_ARITH2 (addc, 0x1F, 0x0A, 0x00);
399/* adde adde. addeo addeo. */
400GEN_INT_ARITH2 (adde, 0x1F, 0x0A, 0x04);
401/* addme addme. addmeo addmeo. */
402GEN_INT_ARITH1 (addme, 0x1F, 0x0A, 0x07);
403/* addze addze. addzeo addzeo. */
404GEN_INT_ARITH1 (addze, 0x1F, 0x0A, 0x06);
405/* divw divw. divwo divwo. */
406GEN_INT_ARITH2 (divw, 0x1F, 0x0B, 0x0F);
407/* divwu divwu. divwuo divwuo. */
408GEN_INT_ARITH2 (divwu, 0x1F, 0x0B, 0x0E);
409/* mulhw mulhw. */
410GEN_INT_ARITHN (mulhw, 0x1F, 0x0B, 0x02);
411/* mulhwu mulhwu. */
412GEN_INT_ARITHN (mulhwu, 0x1F, 0x0B, 0x00);
413/* mullw mullw. mullwo mullwo. */
414GEN_INT_ARITH2 (mullw, 0x1F, 0x0B, 0x07);
415/* neg neg. nego nego. */
416GEN_INT_ARITH1 (neg, 0x1F, 0x08, 0x03);
417/* subf subf. subfo subfo. */
418GEN_INT_ARITH2 (subf, 0x1F, 0x08, 0x01);
419/* subfc subfc. subfco subfco. */
420GEN_INT_ARITH2 (subfc, 0x1F, 0x08, 0x00);
421/* subfe subfe. subfeo subfeo. */
422GEN_INT_ARITH2 (subfe, 0x1F, 0x08, 0x04);
423/* subfme subfme. subfmeo subfmeo. */
424GEN_INT_ARITH1 (subfme, 0x1F, 0x08, 0x07);
425/* subfze subfze. subfzeo subfzeo. */
426GEN_INT_ARITH1 (subfze, 0x1F, 0x08, 0x06);
427/* addi */
428GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
429{
430 int32_t simm = SIMM(ctx->opcode);
431
432 if (rA(ctx->opcode) == 0) {
433 gen_op_set_T0(simm);
434 } else {
435 gen_op_load_gpr_T0(rA(ctx->opcode));
436 gen_op_addi(simm);
437 }
438 gen_op_store_T0_gpr(rD(ctx->opcode));
79aceca5
FB
439}
440/* addic */
441GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
442{
443 gen_op_load_gpr_T0(rA(ctx->opcode));
444 gen_op_addic(SIMM(ctx->opcode));
445 gen_op_store_T0_gpr(rD(ctx->opcode));
79aceca5
FB
446}
447/* addic. */
448GEN_HANDLER(addic_, 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
449{
450 gen_op_load_gpr_T0(rA(ctx->opcode));
451 gen_op_addic(SIMM(ctx->opcode));
452 gen_op_set_Rc0();
453 gen_op_store_T0_gpr(rD(ctx->opcode));
79aceca5
FB
454}
455/* addis */
456GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
457{
458 int32_t simm = SIMM(ctx->opcode);
459
460 if (rA(ctx->opcode) == 0) {
461 gen_op_set_T0(simm << 16);
462 } else {
463 gen_op_load_gpr_T0(rA(ctx->opcode));
464 gen_op_addi(simm << 16);
465 }
466 gen_op_store_T0_gpr(rD(ctx->opcode));
79aceca5
FB
467}
468/* mulli */
469GEN_HANDLER(mulli, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
470{
471 gen_op_load_gpr_T0(rA(ctx->opcode));
472 gen_op_mulli(SIMM(ctx->opcode));
473 gen_op_store_T0_gpr(rD(ctx->opcode));
79aceca5
FB
474}
475/* subfic */
476GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
477{
478 gen_op_load_gpr_T0(rA(ctx->opcode));
479 gen_op_subfic(SIMM(ctx->opcode));
480 gen_op_store_T0_gpr(rD(ctx->opcode));
79aceca5
FB
481}
482
483/*** Integer comparison ***/
484#define GEN_CMP(name, opc) \
485GEN_HANDLER(name, 0x1F, 0x00, opc, 0x00400000, PPC_INTEGER) \
486{ \
487 gen_op_load_gpr_T0(rA(ctx->opcode)); \
488 gen_op_load_gpr_T1(rB(ctx->opcode)); \
489 gen_op_##name(); \
490 gen_op_store_T0_crf(crfD(ctx->opcode)); \
79aceca5
FB
491}
492
493/* cmp */
494GEN_CMP(cmp, 0x00);
495/* cmpi */
496GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
497{
498 gen_op_load_gpr_T0(rA(ctx->opcode));
499 gen_op_cmpi(SIMM(ctx->opcode));
500 gen_op_store_T0_crf(crfD(ctx->opcode));
79aceca5
FB
501}
502/* cmpl */
503GEN_CMP(cmpl, 0x01);
504/* cmpli */
505GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
506{
507 gen_op_load_gpr_T0(rA(ctx->opcode));
508 gen_op_cmpli(UIMM(ctx->opcode));
509 gen_op_store_T0_crf(crfD(ctx->opcode));
79aceca5
FB
510}
511
512/*** Integer logical ***/
513#define __GEN_LOGICAL2(name, opc2, opc3) \
514GEN_HANDLER(name, 0x1F, opc2, opc3, 0x00000000, PPC_INTEGER) \
515{ \
516 gen_op_load_gpr_T0(rS(ctx->opcode)); \
517 gen_op_load_gpr_T1(rB(ctx->opcode)); \
518 gen_op_##name(); \
519 if (Rc(ctx->opcode) != 0) \
520 gen_op_set_Rc0(); \
521 gen_op_store_T0_gpr(rA(ctx->opcode)); \
79aceca5
FB
522}
523#define GEN_LOGICAL2(name, opc) \
524__GEN_LOGICAL2(name, 0x1C, opc)
525
526#define GEN_LOGICAL1(name, opc) \
527GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, PPC_INTEGER) \
528{ \
529 gen_op_load_gpr_T0(rS(ctx->opcode)); \
530 gen_op_##name(); \
531 if (Rc(ctx->opcode) != 0) \
532 gen_op_set_Rc0(); \
533 gen_op_store_T0_gpr(rA(ctx->opcode)); \
79aceca5
FB
534}
535
536/* and & and. */
537GEN_LOGICAL2(and, 0x00);
538/* andc & andc. */
539GEN_LOGICAL2(andc, 0x01);
540/* andi. */
541GEN_HANDLER(andi_, 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
542{
543 gen_op_load_gpr_T0(rS(ctx->opcode));
544 gen_op_andi_(UIMM(ctx->opcode));
545 gen_op_set_Rc0();
546 gen_op_store_T0_gpr(rA(ctx->opcode));
79aceca5
FB
547}
548/* andis. */
549GEN_HANDLER(andis_, 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
550{
551 gen_op_load_gpr_T0(rS(ctx->opcode));
552 gen_op_andi_(UIMM(ctx->opcode) << 16);
553 gen_op_set_Rc0();
554 gen_op_store_T0_gpr(rA(ctx->opcode));
79aceca5
FB
555}
556
557/* cntlzw */
558GEN_LOGICAL1(cntlzw, 0x00);
559/* eqv & eqv. */
560GEN_LOGICAL2(eqv, 0x08);
561/* extsb & extsb. */
562GEN_LOGICAL1(extsb, 0x1D);
563/* extsh & extsh. */
564GEN_LOGICAL1(extsh, 0x1C);
565/* nand & nand. */
566GEN_LOGICAL2(nand, 0x0E);
567/* nor & nor. */
568GEN_LOGICAL2(nor, 0x03);
9a64fbe4 569
79aceca5 570/* or & or. */
9a64fbe4
FB
571GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER)
572{
573 gen_op_load_gpr_T0(rS(ctx->opcode));
574 /* Optimisation for mr case */
575 if (rS(ctx->opcode) != rB(ctx->opcode)) {
576 gen_op_load_gpr_T1(rB(ctx->opcode));
577 gen_op_or();
578 }
579 if (Rc(ctx->opcode) != 0)
580 gen_op_set_Rc0();
581 gen_op_store_T0_gpr(rA(ctx->opcode));
582}
583
79aceca5
FB
584/* orc & orc. */
585GEN_LOGICAL2(orc, 0x0C);
586/* xor & xor. */
9a64fbe4
FB
587GEN_HANDLER(xor, 0x1F, 0x1C, 0x09, 0x00000000, PPC_INTEGER)
588{
589 gen_op_load_gpr_T0(rS(ctx->opcode));
590 /* Optimisation for "set to zero" case */
591 if (rS(ctx->opcode) != rB(ctx->opcode)) {
592 gen_op_load_gpr_T1(rB(ctx->opcode));
593 gen_op_xor();
594 } else {
595 gen_op_set_T0(0);
596 }
597 if (Rc(ctx->opcode) != 0)
598 gen_op_set_Rc0();
599 gen_op_store_T0_gpr(rA(ctx->opcode));
600}
79aceca5
FB
601/* ori */
602GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
603{
604 uint32_t uimm = UIMM(ctx->opcode);
605
9a64fbe4
FB
606 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
607 /* NOP */
608 return;
79aceca5 609 }
79aceca5 610 gen_op_load_gpr_T0(rS(ctx->opcode));
9a64fbe4 611 if (uimm != 0)
79aceca5
FB
612 gen_op_ori(uimm);
613 gen_op_store_T0_gpr(rA(ctx->opcode));
79aceca5
FB
614}
615/* oris */
616GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
617{
618 uint32_t uimm = UIMM(ctx->opcode);
619
9a64fbe4
FB
620 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
621 /* NOP */
622 return;
79aceca5 623 }
79aceca5 624 gen_op_load_gpr_T0(rS(ctx->opcode));
9a64fbe4 625 if (uimm != 0)
79aceca5
FB
626 gen_op_ori(uimm << 16);
627 gen_op_store_T0_gpr(rA(ctx->opcode));
79aceca5
FB
628}
629/* xori */
630GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
631{
9a64fbe4
FB
632 uint32_t uimm = UIMM(ctx->opcode);
633
634 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
635 /* NOP */
636 return;
637 }
79aceca5 638 gen_op_load_gpr_T0(rS(ctx->opcode));
9a64fbe4 639 if (uimm != 0)
4b3686fa 640 gen_op_xori(uimm);
79aceca5 641 gen_op_store_T0_gpr(rA(ctx->opcode));
79aceca5
FB
642}
643
644/* xoris */
645GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
646{
9a64fbe4
FB
647 uint32_t uimm = UIMM(ctx->opcode);
648
649 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
650 /* NOP */
651 return;
652 }
79aceca5 653 gen_op_load_gpr_T0(rS(ctx->opcode));
9a64fbe4 654 if (uimm != 0)
4b3686fa 655 gen_op_xori(uimm << 16);
79aceca5 656 gen_op_store_T0_gpr(rA(ctx->opcode));
79aceca5
FB
657}
658
659/*** Integer rotate ***/
660/* rlwimi & rlwimi. */
661GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
662{
663 uint32_t mb, me;
664
665 mb = MB(ctx->opcode);
666 me = ME(ctx->opcode);
667 gen_op_load_gpr_T0(rS(ctx->opcode));
fb0eaffc 668 gen_op_load_gpr_T1(rA(ctx->opcode));
79aceca5
FB
669 gen_op_rlwimi(SH(ctx->opcode), MASK(mb, me), ~MASK(mb, me));
670 if (Rc(ctx->opcode) != 0)
671 gen_op_set_Rc0();
672 gen_op_store_T0_gpr(rA(ctx->opcode));
79aceca5
FB
673}
674/* rlwinm & rlwinm. */
675GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
676{
677 uint32_t mb, me, sh;
678
679 sh = SH(ctx->opcode);
680 mb = MB(ctx->opcode);
681 me = ME(ctx->opcode);
682 gen_op_load_gpr_T0(rS(ctx->opcode));
4b3686fa
FB
683#if 1 // TRY
684 if (sh == 0) {
685 gen_op_andi_(MASK(mb, me));
686 goto store;
687 }
688#endif
79aceca5
FB
689 if (mb == 0) {
690 if (me == 31) {
691 gen_op_rotlwi(sh);
692 goto store;
4b3686fa 693#if 0
79aceca5
FB
694 } else if (me == (31 - sh)) {
695 gen_op_slwi(sh);
696 goto store;
4b3686fa 697#endif
79aceca5
FB
698 }
699 } else if (me == 31) {
4b3686fa 700#if 0
79aceca5
FB
701 if (sh == (32 - mb)) {
702 gen_op_srwi(mb);
703 goto store;
79aceca5 704 }
4b3686fa 705#endif
79aceca5
FB
706 }
707 gen_op_rlwinm(sh, MASK(mb, me));
708store:
709 if (Rc(ctx->opcode) != 0)
710 gen_op_set_Rc0();
711 gen_op_store_T0_gpr(rA(ctx->opcode));
79aceca5
FB
712}
713/* rlwnm & rlwnm. */
714GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
715{
716 uint32_t mb, me;
717
718 mb = MB(ctx->opcode);
719 me = ME(ctx->opcode);
720 gen_op_load_gpr_T0(rS(ctx->opcode));
721 gen_op_load_gpr_T1(rB(ctx->opcode));
722 if (mb == 0 && me == 31) {
723 gen_op_rotl();
724 } else
725 {
726 gen_op_rlwnm(MASK(mb, me));
727 }
728 if (Rc(ctx->opcode) != 0)
729 gen_op_set_Rc0();
730 gen_op_store_T0_gpr(rA(ctx->opcode));
79aceca5
FB
731}
732
733/*** Integer shift ***/
734/* slw & slw. */
735__GEN_LOGICAL2(slw, 0x18, 0x00);
736/* sraw & sraw. */
737__GEN_LOGICAL2(sraw, 0x18, 0x18);
738/* srawi & srawi. */
739GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER)
740{
741 gen_op_load_gpr_T0(rS(ctx->opcode));
742 gen_op_srawi(SH(ctx->opcode), MASK(32 - SH(ctx->opcode), 31));
743 if (Rc(ctx->opcode) != 0)
744 gen_op_set_Rc0();
745 gen_op_store_T0_gpr(rA(ctx->opcode));
79aceca5
FB
746}
747/* srw & srw. */
748__GEN_LOGICAL2(srw, 0x18, 0x10);
749
750/*** Floating-Point arithmetic ***/
9a64fbe4
FB
751#define _GEN_FLOAT_ACB(name, op1, op2) \
752GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, PPC_FLOAT) \
753{ \
754 gen_op_reset_scrfx(); \
755 gen_op_load_fpr_FT0(rA(ctx->opcode)); \
756 gen_op_load_fpr_FT1(rC(ctx->opcode)); \
757 gen_op_load_fpr_FT2(rB(ctx->opcode)); \
758 gen_op_f##name(); \
759 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
760 if (Rc(ctx->opcode)) \
761 gen_op_set_Rc1(); \
762}
763
764#define GEN_FLOAT_ACB(name, op2) \
765_GEN_FLOAT_ACB(name, 0x3F, op2); \
766_GEN_FLOAT_ACB(name##s, 0x3B, op2);
767
768#define _GEN_FLOAT_AB(name, op1, op2, inval) \
769GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \
770{ \
771 gen_op_reset_scrfx(); \
772 gen_op_load_fpr_FT0(rA(ctx->opcode)); \
773 gen_op_load_fpr_FT1(rB(ctx->opcode)); \
774 gen_op_f##name(); \
775 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
776 if (Rc(ctx->opcode)) \
777 gen_op_set_Rc1(); \
778}
779#define GEN_FLOAT_AB(name, op2, inval) \
780_GEN_FLOAT_AB(name, 0x3F, op2, inval); \
781_GEN_FLOAT_AB(name##s, 0x3B, op2, inval);
782
783#define _GEN_FLOAT_AC(name, op1, op2, inval) \
784GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \
785{ \
786 gen_op_reset_scrfx(); \
787 gen_op_load_fpr_FT0(rA(ctx->opcode)); \
788 gen_op_load_fpr_FT1(rC(ctx->opcode)); \
789 gen_op_f##name(); \
790 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
791 if (Rc(ctx->opcode)) \
792 gen_op_set_Rc1(); \
793}
794#define GEN_FLOAT_AC(name, op2, inval) \
795_GEN_FLOAT_AC(name, 0x3F, op2, inval); \
796_GEN_FLOAT_AC(name##s, 0x3B, op2, inval);
797
798#define GEN_FLOAT_B(name, op2, op3) \
799GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, PPC_FLOAT) \
800{ \
801 gen_op_reset_scrfx(); \
802 gen_op_load_fpr_FT0(rB(ctx->opcode)); \
803 gen_op_f##name(); \
804 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
805 if (Rc(ctx->opcode)) \
806 gen_op_set_Rc1(); \
79aceca5
FB
807}
808
9a64fbe4
FB
809#define GEN_FLOAT_BS(name, op2) \
810GEN_HANDLER(f##name, 0x3F, op2, 0xFF, 0x001F07C0, PPC_FLOAT) \
811{ \
812 gen_op_reset_scrfx(); \
813 gen_op_load_fpr_FT0(rB(ctx->opcode)); \
814 gen_op_f##name(); \
815 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
816 if (Rc(ctx->opcode)) \
817 gen_op_set_Rc1(); \
79aceca5
FB
818}
819
9a64fbe4
FB
820/* fadd - fadds */
821GEN_FLOAT_AB(add, 0x15, 0x000007C0);
79aceca5 822/* fdiv */
9a64fbe4 823GEN_FLOAT_AB(div, 0x12, 0x000007C0);
79aceca5 824/* fmul */
9a64fbe4 825GEN_FLOAT_AC(mul, 0x19, 0x0000F800);
79aceca5
FB
826
827/* fres */
9a64fbe4 828GEN_FLOAT_BS(res, 0x18);
79aceca5
FB
829
830/* frsqrte */
9a64fbe4 831GEN_FLOAT_BS(rsqrte, 0x1A);
79aceca5
FB
832
833/* fsel */
9a64fbe4 834_GEN_FLOAT_ACB(sel, 0x3F, 0x17);
79aceca5 835/* fsub */
9a64fbe4 836GEN_FLOAT_AB(sub, 0x14, 0x000007C0);
79aceca5
FB
837/* Optional: */
838/* fsqrt */
9a64fbe4 839GEN_FLOAT_BS(sqrt, 0x16);
79aceca5 840
9a64fbe4 841GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_OPT)
79aceca5 842{
9a64fbe4
FB
843 gen_op_reset_scrfx();
844 gen_op_load_fpr_FT0(rB(ctx->opcode));
845 gen_op_fsqrts();
846 gen_op_store_FT0_fpr(rD(ctx->opcode));
847 if (Rc(ctx->opcode))
848 gen_op_set_Rc1();
79aceca5
FB
849}
850
851/*** Floating-Point multiply-and-add ***/
852/* fmadd */
9a64fbe4 853GEN_FLOAT_ACB(madd, 0x1D);
79aceca5 854/* fmsub */
9a64fbe4 855GEN_FLOAT_ACB(msub, 0x1C);
79aceca5 856/* fnmadd */
9a64fbe4 857GEN_FLOAT_ACB(nmadd, 0x1F);
79aceca5 858/* fnmsub */
9a64fbe4 859GEN_FLOAT_ACB(nmsub, 0x1E);
79aceca5
FB
860
861/*** Floating-Point round & convert ***/
862/* fctiw */
9a64fbe4 863GEN_FLOAT_B(ctiw, 0x0E, 0x00);
79aceca5 864/* fctiwz */
9a64fbe4 865GEN_FLOAT_B(ctiwz, 0x0F, 0x00);
79aceca5 866/* frsp */
9a64fbe4 867GEN_FLOAT_B(rsp, 0x0C, 0x00);
79aceca5
FB
868
869/*** Floating-Point compare ***/
870/* fcmpo */
871GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT)
872{
9a64fbe4
FB
873 gen_op_reset_scrfx();
874 gen_op_load_fpr_FT0(rA(ctx->opcode));
875 gen_op_load_fpr_FT1(rB(ctx->opcode));
876 gen_op_fcmpo();
877 gen_op_store_T0_crf(crfD(ctx->opcode));
79aceca5
FB
878}
879
880/* fcmpu */
881GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT)
882{
9a64fbe4
FB
883 gen_op_reset_scrfx();
884 gen_op_load_fpr_FT0(rA(ctx->opcode));
885 gen_op_load_fpr_FT1(rB(ctx->opcode));
886 gen_op_fcmpu();
887 gen_op_store_T0_crf(crfD(ctx->opcode));
79aceca5
FB
888}
889
9a64fbe4
FB
890/*** Floating-point move ***/
891/* fabs */
892GEN_FLOAT_B(abs, 0x08, 0x08);
893
894/* fmr - fmr. */
895GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT)
896{
897 gen_op_reset_scrfx();
898 gen_op_load_fpr_FT0(rB(ctx->opcode));
899 gen_op_store_FT0_fpr(rD(ctx->opcode));
900 if (Rc(ctx->opcode))
901 gen_op_set_Rc1();
902}
903
904/* fnabs */
905GEN_FLOAT_B(nabs, 0x08, 0x04);
906/* fneg */
907GEN_FLOAT_B(neg, 0x08, 0x01);
908
79aceca5
FB
909/*** Floating-Point status & ctrl register ***/
910/* mcrfs */
911GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT)
912{
fb0eaffc
FB
913 gen_op_load_fpscr_T0(crfS(ctx->opcode));
914 gen_op_store_T0_crf(crfD(ctx->opcode));
915 gen_op_clear_fpscr(crfS(ctx->opcode));
79aceca5
FB
916}
917
918/* mffs */
919GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT)
920{
28b6751f 921 gen_op_load_fpscr();
fb0eaffc
FB
922 gen_op_store_FT0_fpr(rD(ctx->opcode));
923 if (Rc(ctx->opcode))
924 gen_op_set_Rc1();
79aceca5
FB
925}
926
927/* mtfsb0 */
928GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT)
929{
fb0eaffc
FB
930 uint8_t crb;
931
932 crb = crbD(ctx->opcode) >> 2;
933 gen_op_load_fpscr_T0(crb);
934 gen_op_andi_(~(1 << (crbD(ctx->opcode) & 0x03)));
935 gen_op_store_T0_fpscr(crb);
936 if (Rc(ctx->opcode))
937 gen_op_set_Rc1();
79aceca5
FB
938}
939
940/* mtfsb1 */
941GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT)
942{
fb0eaffc
FB
943 uint8_t crb;
944
945 crb = crbD(ctx->opcode) >> 2;
946 gen_op_load_fpscr_T0(crb);
947 gen_op_ori(1 << (crbD(ctx->opcode) & 0x03));
948 gen_op_store_T0_fpscr(crb);
949 if (Rc(ctx->opcode))
950 gen_op_set_Rc1();
79aceca5
FB
951}
952
953/* mtfsf */
954GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT)
955{
fb0eaffc 956 gen_op_load_fpr_FT0(rB(ctx->opcode));
28b6751f 957 gen_op_store_fpscr(FM(ctx->opcode));
fb0eaffc
FB
958 if (Rc(ctx->opcode))
959 gen_op_set_Rc1();
79aceca5
FB
960}
961
962/* mtfsfi */
963GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT)
964{
fb0eaffc
FB
965 gen_op_store_T0_fpscri(crbD(ctx->opcode) >> 2, FPIMM(ctx->opcode));
966 if (Rc(ctx->opcode))
967 gen_op_set_Rc1();
79aceca5
FB
968}
969
970/*** Integer load ***/
9a64fbe4
FB
971#if defined(CONFIG_USER_ONLY)
972#define op_ldst(name) gen_op_##name##_raw()
973#define OP_LD_TABLE(width)
974#define OP_ST_TABLE(width)
975#else
976#define op_ldst(name) (*gen_op_##name[ctx->mem_idx])()
977#define OP_LD_TABLE(width) \
978static GenOpFunc *gen_op_l##width[] = { \
979 &gen_op_l##width##_user, \
980 &gen_op_l##width##_kernel, \
981}
982#define OP_ST_TABLE(width) \
983static GenOpFunc *gen_op_st##width[] = { \
984 &gen_op_st##width##_user, \
985 &gen_op_st##width##_kernel, \
986}
987#endif
988
989#define GEN_LD(width, opc) \
79aceca5
FB
990GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
991{ \
992 uint32_t simm = SIMM(ctx->opcode); \
993 if (rA(ctx->opcode) == 0) { \
9a64fbe4 994 gen_op_set_T0(simm); \
79aceca5
FB
995 } else { \
996 gen_op_load_gpr_T0(rA(ctx->opcode)); \
9a64fbe4
FB
997 if (simm != 0) \
998 gen_op_addi(simm); \
79aceca5 999 } \
9a64fbe4 1000 op_ldst(l##width); \
79aceca5 1001 gen_op_store_T1_gpr(rD(ctx->opcode)); \
79aceca5
FB
1002}
1003
9a64fbe4 1004#define GEN_LDU(width, opc) \
79aceca5
FB
1005GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
1006{ \
9a64fbe4 1007 uint32_t simm = SIMM(ctx->opcode); \
79aceca5 1008 if (rA(ctx->opcode) == 0 || \
9a64fbe4 1009 rA(ctx->opcode) == rD(ctx->opcode)) { \
9fddaa0c
FB
1010 RET_INVAL(ctx); \
1011 return; \
9a64fbe4 1012 } \
79aceca5 1013 gen_op_load_gpr_T0(rA(ctx->opcode)); \
9a64fbe4
FB
1014 if (simm != 0) \
1015 gen_op_addi(simm); \
1016 op_ldst(l##width); \
79aceca5
FB
1017 gen_op_store_T1_gpr(rD(ctx->opcode)); \
1018 gen_op_store_T0_gpr(rA(ctx->opcode)); \
79aceca5
FB
1019}
1020
9a64fbe4 1021#define GEN_LDUX(width, opc) \
79aceca5
FB
1022GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \
1023{ \
1024 if (rA(ctx->opcode) == 0 || \
9a64fbe4 1025 rA(ctx->opcode) == rD(ctx->opcode)) { \
9fddaa0c
FB
1026 RET_INVAL(ctx); \
1027 return; \
9a64fbe4 1028 } \
79aceca5
FB
1029 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1030 gen_op_load_gpr_T1(rB(ctx->opcode)); \
9a64fbe4
FB
1031 gen_op_add(); \
1032 op_ldst(l##width); \
79aceca5
FB
1033 gen_op_store_T1_gpr(rD(ctx->opcode)); \
1034 gen_op_store_T0_gpr(rA(ctx->opcode)); \
79aceca5
FB
1035}
1036
9a64fbe4 1037#define GEN_LDX(width, opc2, opc3) \
79aceca5
FB
1038GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER) \
1039{ \
1040 if (rA(ctx->opcode) == 0) { \
1041 gen_op_load_gpr_T0(rB(ctx->opcode)); \
79aceca5
FB
1042 } else { \
1043 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1044 gen_op_load_gpr_T1(rB(ctx->opcode)); \
9a64fbe4 1045 gen_op_add(); \
79aceca5 1046 } \
9a64fbe4 1047 op_ldst(l##width); \
79aceca5 1048 gen_op_store_T1_gpr(rD(ctx->opcode)); \
79aceca5
FB
1049}
1050
9a64fbe4
FB
1051#define GEN_LDS(width, op) \
1052OP_LD_TABLE(width); \
1053GEN_LD(width, op | 0x20); \
1054GEN_LDU(width, op | 0x21); \
1055GEN_LDUX(width, op | 0x01); \
1056GEN_LDX(width, 0x17, op | 0x00)
79aceca5
FB
1057
1058/* lbz lbzu lbzux lbzx */
9a64fbe4 1059GEN_LDS(bz, 0x02);
79aceca5 1060/* lha lhau lhaux lhax */
9a64fbe4 1061GEN_LDS(ha, 0x0A);
79aceca5 1062/* lhz lhzu lhzux lhzx */
9a64fbe4 1063GEN_LDS(hz, 0x08);
79aceca5 1064/* lwz lwzu lwzux lwzx */
9a64fbe4 1065GEN_LDS(wz, 0x00);
79aceca5
FB
1066
1067/*** Integer store ***/
9a64fbe4 1068#define GEN_ST(width, opc) \
79aceca5
FB
1069GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
1070{ \
1071 uint32_t simm = SIMM(ctx->opcode); \
1072 if (rA(ctx->opcode) == 0) { \
9a64fbe4 1073 gen_op_set_T0(simm); \
79aceca5
FB
1074 } else { \
1075 gen_op_load_gpr_T0(rA(ctx->opcode)); \
9a64fbe4
FB
1076 if (simm != 0) \
1077 gen_op_addi(simm); \
79aceca5 1078 } \
9a64fbe4
FB
1079 gen_op_load_gpr_T1(rS(ctx->opcode)); \
1080 op_ldst(st##width); \
79aceca5
FB
1081}
1082
9a64fbe4 1083#define GEN_STU(width, opc) \
79aceca5
FB
1084GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
1085{ \
9a64fbe4
FB
1086 uint32_t simm = SIMM(ctx->opcode); \
1087 if (rA(ctx->opcode) == 0) { \
9fddaa0c
FB
1088 RET_INVAL(ctx); \
1089 return; \
9a64fbe4 1090 } \
79aceca5 1091 gen_op_load_gpr_T0(rA(ctx->opcode)); \
9a64fbe4
FB
1092 if (simm != 0) \
1093 gen_op_addi(simm); \
79aceca5 1094 gen_op_load_gpr_T1(rS(ctx->opcode)); \
9a64fbe4 1095 op_ldst(st##width); \
79aceca5 1096 gen_op_store_T0_gpr(rA(ctx->opcode)); \
79aceca5
FB
1097}
1098
9a64fbe4 1099#define GEN_STUX(width, opc) \
79aceca5
FB
1100GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \
1101{ \
9a64fbe4 1102 if (rA(ctx->opcode) == 0) { \
9fddaa0c
FB
1103 RET_INVAL(ctx); \
1104 return; \
9a64fbe4 1105 } \
79aceca5
FB
1106 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1107 gen_op_load_gpr_T1(rB(ctx->opcode)); \
9a64fbe4
FB
1108 gen_op_add(); \
1109 gen_op_load_gpr_T1(rS(ctx->opcode)); \
1110 op_ldst(st##width); \
79aceca5 1111 gen_op_store_T0_gpr(rA(ctx->opcode)); \
79aceca5
FB
1112}
1113
9a64fbe4 1114#define GEN_STX(width, opc2, opc3) \
79aceca5
FB
1115GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER) \
1116{ \
1117 if (rA(ctx->opcode) == 0) { \
1118 gen_op_load_gpr_T0(rB(ctx->opcode)); \
79aceca5
FB
1119 } else { \
1120 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1121 gen_op_load_gpr_T1(rB(ctx->opcode)); \
9a64fbe4 1122 gen_op_add(); \
79aceca5 1123 } \
9a64fbe4
FB
1124 gen_op_load_gpr_T1(rS(ctx->opcode)); \
1125 op_ldst(st##width); \
79aceca5
FB
1126}
1127
9a64fbe4
FB
1128#define GEN_STS(width, op) \
1129OP_ST_TABLE(width); \
1130GEN_ST(width, op | 0x20); \
1131GEN_STU(width, op | 0x21); \
1132GEN_STUX(width, op | 0x01); \
1133GEN_STX(width, 0x17, op | 0x00)
79aceca5
FB
1134
1135/* stb stbu stbux stbx */
9a64fbe4 1136GEN_STS(b, 0x06);
79aceca5 1137/* sth sthu sthux sthx */
9a64fbe4 1138GEN_STS(h, 0x0C);
79aceca5 1139/* stw stwu stwux stwx */
9a64fbe4 1140GEN_STS(w, 0x04);
79aceca5
FB
1141
1142/*** Integer load and store with byte reverse ***/
1143/* lhbrx */
9a64fbe4
FB
1144OP_LD_TABLE(hbr);
1145GEN_LDX(hbr, 0x16, 0x18);
79aceca5 1146/* lwbrx */
9a64fbe4
FB
1147OP_LD_TABLE(wbr);
1148GEN_LDX(wbr, 0x16, 0x10);
79aceca5 1149/* sthbrx */
9a64fbe4
FB
1150OP_ST_TABLE(hbr);
1151GEN_STX(hbr, 0x16, 0x1C);
79aceca5 1152/* stwbrx */
9a64fbe4
FB
1153OP_ST_TABLE(wbr);
1154GEN_STX(wbr, 0x16, 0x14);
79aceca5
FB
1155
1156/*** Integer load and store multiple ***/
9a64fbe4
FB
1157#if defined(CONFIG_USER_ONLY)
1158#define op_ldstm(name, reg) gen_op_##name##_raw(reg)
1159#else
1160#define op_ldstm(name, reg) (*gen_op_##name[ctx->mem_idx])(reg)
1161static GenOpFunc1 *gen_op_lmw[] = {
1162 &gen_op_lmw_user,
1163 &gen_op_lmw_kernel,
1164};
1165static GenOpFunc1 *gen_op_stmw[] = {
1166 &gen_op_stmw_user,
1167 &gen_op_stmw_kernel,
1168};
1169#endif
1170
79aceca5
FB
1171/* lmw */
1172GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1173{
9a64fbe4
FB
1174 int simm = SIMM(ctx->opcode);
1175
79aceca5 1176 if (rA(ctx->opcode) == 0) {
9a64fbe4 1177 gen_op_set_T0(simm);
79aceca5
FB
1178 } else {
1179 gen_op_load_gpr_T0(rA(ctx->opcode));
9a64fbe4
FB
1180 if (simm != 0)
1181 gen_op_addi(simm);
79aceca5 1182 }
9a64fbe4 1183 op_ldstm(lmw, rD(ctx->opcode));
79aceca5
FB
1184}
1185
1186/* stmw */
1187GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1188{
9a64fbe4
FB
1189 int simm = SIMM(ctx->opcode);
1190
79aceca5 1191 if (rA(ctx->opcode) == 0) {
9a64fbe4 1192 gen_op_set_T0(simm);
79aceca5
FB
1193 } else {
1194 gen_op_load_gpr_T0(rA(ctx->opcode));
9a64fbe4
FB
1195 if (simm != 0)
1196 gen_op_addi(simm);
79aceca5 1197 }
9a64fbe4 1198 op_ldstm(stmw, rS(ctx->opcode));
79aceca5
FB
1199}
1200
1201/*** Integer load and store strings ***/
9a64fbe4
FB
1202#if defined(CONFIG_USER_ONLY)
1203#define op_ldsts(name, start) gen_op_##name##_raw(start)
1204#define op_ldstsx(name, rd, ra, rb) gen_op_##name##_raw(rd, ra, rb)
1205#else
1206#define op_ldsts(name, start) (*gen_op_##name[ctx->mem_idx])(start)
1207#define op_ldstsx(name, rd, ra, rb) (*gen_op_##name[ctx->mem_idx])(rd, ra, rb)
1208static GenOpFunc1 *gen_op_lswi[] = {
1209 &gen_op_lswi_user,
1210 &gen_op_lswi_kernel,
1211};
1212static GenOpFunc3 *gen_op_lswx[] = {
1213 &gen_op_lswx_user,
1214 &gen_op_lswx_kernel,
1215};
1216static GenOpFunc1 *gen_op_stsw[] = {
1217 &gen_op_stsw_user,
1218 &gen_op_stsw_kernel,
1219};
1220#endif
1221
79aceca5 1222/* lswi */
9a64fbe4
FB
1223/* PPC32 specification says we must generate an exception if
1224 * rA is in the range of registers to be loaded.
1225 * In an other hand, IBM says this is valid, but rA won't be loaded.
1226 * For now, I'll follow the spec...
1227 */
79aceca5
FB
1228GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_INTEGER)
1229{
1230 int nb = NB(ctx->opcode);
1231 int start = rD(ctx->opcode);
9a64fbe4 1232 int ra = rA(ctx->opcode);
79aceca5
FB
1233 int nr;
1234
1235 if (nb == 0)
1236 nb = 32;
1237 nr = nb / 4;
297d8e62
FB
1238 if (((start + nr) > 32 && start <= ra && (start + nr - 32) > ra) ||
1239 ((start + nr) <= 32 && start <= ra && (start + nr) > ra)) {
9fddaa0c
FB
1240 RET_EXCP(ctx, EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_LSWX);
1241 return;
297d8e62 1242 }
9a64fbe4 1243 if (ra == 0) {
79aceca5
FB
1244 gen_op_set_T0(0);
1245 } else {
9a64fbe4 1246 gen_op_load_gpr_T0(ra);
79aceca5 1247 }
9a64fbe4
FB
1248 gen_op_set_T1(nb);
1249 op_ldsts(lswi, start);
79aceca5
FB
1250}
1251
1252/* lswx */
1253GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_INTEGER)
1254{
9a64fbe4
FB
1255 int ra = rA(ctx->opcode);
1256 int rb = rB(ctx->opcode);
1257
1258 if (ra == 0) {
1259 gen_op_load_gpr_T0(rb);
1260 ra = rb;
79aceca5 1261 } else {
9a64fbe4
FB
1262 gen_op_load_gpr_T0(ra);
1263 gen_op_load_gpr_T1(rb);
1264 gen_op_add();
79aceca5 1265 }
9a64fbe4
FB
1266 gen_op_load_xer_bc();
1267 op_ldstsx(lswx, rD(ctx->opcode), ra, rb);
79aceca5
FB
1268}
1269
1270/* stswi */
1271GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_INTEGER)
1272{
4b3686fa
FB
1273 int nb = NB(ctx->opcode);
1274
79aceca5
FB
1275 if (rA(ctx->opcode) == 0) {
1276 gen_op_set_T0(0);
1277 } else {
1278 gen_op_load_gpr_T0(rA(ctx->opcode));
1279 }
4b3686fa
FB
1280 if (nb == 0)
1281 nb = 32;
1282 gen_op_set_T1(nb);
9a64fbe4 1283 op_ldsts(stsw, rS(ctx->opcode));
79aceca5
FB
1284}
1285
1286/* stswx */
1287GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_INTEGER)
1288{
9a64fbe4
FB
1289 int ra = rA(ctx->opcode);
1290
1291 if (ra == 0) {
1292 gen_op_load_gpr_T0(rB(ctx->opcode));
1293 ra = rB(ctx->opcode);
79aceca5 1294 } else {
9a64fbe4
FB
1295 gen_op_load_gpr_T0(ra);
1296 gen_op_load_gpr_T1(rB(ctx->opcode));
1297 gen_op_add();
79aceca5 1298 }
9a64fbe4
FB
1299 gen_op_load_xer_bc();
1300 op_ldsts(stsw, rS(ctx->opcode));
79aceca5
FB
1301}
1302
1303/*** Memory synchronisation ***/
1304/* eieio */
1305GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FF0801, PPC_MEM)
1306{
79aceca5
FB
1307}
1308
1309/* isync */
1310GEN_HANDLER(isync, 0x13, 0x16, 0xFF, 0x03FF0801, PPC_MEM)
1311{
79aceca5
FB
1312}
1313
1314/* lwarx */
9a64fbe4 1315#if defined(CONFIG_USER_ONLY)
985a19d6 1316#define op_lwarx() gen_op_lwarx_raw()
9a64fbe4
FB
1317#define op_stwcx() gen_op_stwcx_raw()
1318#else
985a19d6
FB
1319#define op_lwarx() (*gen_op_lwarx[ctx->mem_idx])()
1320static GenOpFunc *gen_op_lwarx[] = {
1321 &gen_op_lwarx_user,
1322 &gen_op_lwarx_kernel,
1323};
9a64fbe4
FB
1324#define op_stwcx() (*gen_op_stwcx[ctx->mem_idx])()
1325static GenOpFunc *gen_op_stwcx[] = {
1326 &gen_op_stwcx_user,
1327 &gen_op_stwcx_kernel,
1328};
1329#endif
1330
1331GEN_HANDLER(lwarx, 0x1F, 0x14, 0xFF, 0x00000001, PPC_RES)
79aceca5 1332{
79aceca5
FB
1333 if (rA(ctx->opcode) == 0) {
1334 gen_op_load_gpr_T0(rB(ctx->opcode));
79aceca5
FB
1335 } else {
1336 gen_op_load_gpr_T0(rA(ctx->opcode));
1337 gen_op_load_gpr_T1(rB(ctx->opcode));
9a64fbe4 1338 gen_op_add();
79aceca5 1339 }
985a19d6 1340 op_lwarx();
79aceca5 1341 gen_op_store_T1_gpr(rD(ctx->opcode));
79aceca5
FB
1342}
1343
1344/* stwcx. */
9a64fbe4 1345GEN_HANDLER(stwcx_, 0x1F, 0x16, 0x04, 0x00000000, PPC_RES)
79aceca5 1346{
79aceca5
FB
1347 if (rA(ctx->opcode) == 0) {
1348 gen_op_load_gpr_T0(rB(ctx->opcode));
79aceca5
FB
1349 } else {
1350 gen_op_load_gpr_T0(rA(ctx->opcode));
1351 gen_op_load_gpr_T1(rB(ctx->opcode));
9a64fbe4 1352 gen_op_add();
79aceca5 1353 }
9a64fbe4
FB
1354 gen_op_load_gpr_T1(rS(ctx->opcode));
1355 op_stwcx();
79aceca5
FB
1356}
1357
1358/* sync */
1359GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x03FF0801, PPC_MEM)
1360{
79aceca5
FB
1361}
1362
1363/*** Floating-point load ***/
9a64fbe4
FB
1364#define GEN_LDF(width, opc) \
1365GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
79aceca5
FB
1366{ \
1367 uint32_t simm = SIMM(ctx->opcode); \
1368 if (rA(ctx->opcode) == 0) { \
9a64fbe4 1369 gen_op_set_T0(simm); \
79aceca5
FB
1370 } else { \
1371 gen_op_load_gpr_T0(rA(ctx->opcode)); \
9a64fbe4
FB
1372 if (simm != 0) \
1373 gen_op_addi(simm); \
79aceca5 1374 } \
9a64fbe4
FB
1375 op_ldst(l##width); \
1376 gen_op_store_FT1_fpr(rD(ctx->opcode)); \
79aceca5
FB
1377}
1378
9a64fbe4
FB
1379#define GEN_LDUF(width, opc) \
1380GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
79aceca5 1381{ \
9a64fbe4 1382 uint32_t simm = SIMM(ctx->opcode); \
79aceca5 1383 if (rA(ctx->opcode) == 0 || \
9a64fbe4 1384 rA(ctx->opcode) == rD(ctx->opcode)) { \
9fddaa0c
FB
1385 RET_INVAL(ctx); \
1386 return; \
9a64fbe4 1387 } \
79aceca5 1388 gen_op_load_gpr_T0(rA(ctx->opcode)); \
9a64fbe4
FB
1389 if (simm != 0) \
1390 gen_op_addi(simm); \
1391 op_ldst(l##width); \
1392 gen_op_store_FT1_fpr(rD(ctx->opcode)); \
79aceca5 1393 gen_op_store_T0_gpr(rA(ctx->opcode)); \
79aceca5
FB
1394}
1395
9a64fbe4
FB
1396#define GEN_LDUXF(width, opc) \
1397GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \
79aceca5
FB
1398{ \
1399 if (rA(ctx->opcode) == 0 || \
9a64fbe4 1400 rA(ctx->opcode) == rD(ctx->opcode)) { \
9fddaa0c
FB
1401 RET_INVAL(ctx); \
1402 return; \
9a64fbe4 1403 } \
79aceca5
FB
1404 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1405 gen_op_load_gpr_T1(rB(ctx->opcode)); \
9a64fbe4
FB
1406 gen_op_add(); \
1407 op_ldst(l##width); \
1408 gen_op_store_FT1_fpr(rD(ctx->opcode)); \
79aceca5 1409 gen_op_store_T0_gpr(rA(ctx->opcode)); \
79aceca5
FB
1410}
1411
9a64fbe4
FB
1412#define GEN_LDXF(width, opc2, opc3) \
1413GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER) \
79aceca5
FB
1414{ \
1415 if (rA(ctx->opcode) == 0) { \
1416 gen_op_load_gpr_T0(rB(ctx->opcode)); \
79aceca5
FB
1417 } else { \
1418 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1419 gen_op_load_gpr_T1(rB(ctx->opcode)); \
9a64fbe4 1420 gen_op_add(); \
79aceca5 1421 } \
9a64fbe4
FB
1422 op_ldst(l##width); \
1423 gen_op_store_FT1_fpr(rD(ctx->opcode)); \
79aceca5
FB
1424}
1425
9a64fbe4
FB
1426#define GEN_LDFS(width, op) \
1427OP_LD_TABLE(width); \
1428GEN_LDF(width, op | 0x20); \
1429GEN_LDUF(width, op | 0x21); \
1430GEN_LDUXF(width, op | 0x01); \
1431GEN_LDXF(width, 0x17, op | 0x00)
79aceca5
FB
1432
1433/* lfd lfdu lfdux lfdx */
9a64fbe4 1434GEN_LDFS(fd, 0x12);
79aceca5 1435/* lfs lfsu lfsux lfsx */
9a64fbe4 1436GEN_LDFS(fs, 0x10);
79aceca5
FB
1437
1438/*** Floating-point store ***/
1439#define GEN_STF(width, opc) \
9a64fbe4 1440GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
79aceca5
FB
1441{ \
1442 uint32_t simm = SIMM(ctx->opcode); \
1443 if (rA(ctx->opcode) == 0) { \
9a64fbe4 1444 gen_op_set_T0(simm); \
79aceca5
FB
1445 } else { \
1446 gen_op_load_gpr_T0(rA(ctx->opcode)); \
9a64fbe4
FB
1447 if (simm != 0) \
1448 gen_op_addi(simm); \
79aceca5 1449 } \
9a64fbe4
FB
1450 gen_op_load_fpr_FT1(rS(ctx->opcode)); \
1451 op_ldst(st##width); \
79aceca5
FB
1452}
1453
9a64fbe4
FB
1454#define GEN_STUF(width, opc) \
1455GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
79aceca5 1456{ \
9a64fbe4
FB
1457 uint32_t simm = SIMM(ctx->opcode); \
1458 if (rA(ctx->opcode) == 0) { \
9fddaa0c
FB
1459 RET_INVAL(ctx); \
1460 return; \
9a64fbe4 1461 } \
79aceca5 1462 gen_op_load_gpr_T0(rA(ctx->opcode)); \
9a64fbe4
FB
1463 if (simm != 0) \
1464 gen_op_addi(simm); \
1465 gen_op_load_fpr_FT1(rS(ctx->opcode)); \
1466 op_ldst(st##width); \
79aceca5 1467 gen_op_store_T0_gpr(rA(ctx->opcode)); \
79aceca5
FB
1468}
1469
9a64fbe4
FB
1470#define GEN_STUXF(width, opc) \
1471GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \
79aceca5 1472{ \
9a64fbe4 1473 if (rA(ctx->opcode) == 0) { \
9fddaa0c
FB
1474 RET_INVAL(ctx); \
1475 return; \
9a64fbe4 1476 } \
79aceca5
FB
1477 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1478 gen_op_load_gpr_T1(rB(ctx->opcode)); \
9a64fbe4
FB
1479 gen_op_add(); \
1480 gen_op_load_fpr_FT1(rS(ctx->opcode)); \
1481 op_ldst(st##width); \
79aceca5 1482 gen_op_store_T0_gpr(rA(ctx->opcode)); \
79aceca5
FB
1483}
1484
9a64fbe4
FB
1485#define GEN_STXF(width, opc2, opc3) \
1486GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER) \
79aceca5
FB
1487{ \
1488 if (rA(ctx->opcode) == 0) { \
1489 gen_op_load_gpr_T0(rB(ctx->opcode)); \
79aceca5
FB
1490 } else { \
1491 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1492 gen_op_load_gpr_T1(rB(ctx->opcode)); \
9a64fbe4 1493 gen_op_add(); \
79aceca5 1494 } \
9a64fbe4
FB
1495 gen_op_load_fpr_FT1(rS(ctx->opcode)); \
1496 op_ldst(st##width); \
79aceca5
FB
1497}
1498
9a64fbe4
FB
1499#define GEN_STFS(width, op) \
1500OP_ST_TABLE(width); \
1501GEN_STF(width, op | 0x20); \
1502GEN_STUF(width, op | 0x21); \
1503GEN_STUXF(width, op | 0x01); \
1504GEN_STXF(width, 0x17, op | 0x00)
79aceca5
FB
1505
1506/* stfd stfdu stfdux stfdx */
9a64fbe4 1507GEN_STFS(fd, 0x16);
79aceca5 1508/* stfs stfsu stfsux stfsx */
9a64fbe4 1509GEN_STFS(fs, 0x14);
79aceca5
FB
1510
1511/* Optional: */
1512/* stfiwx */
1513GEN_HANDLER(stfiwx, 0x1F, 0x17, 0x1E, 0x00000001, PPC_FLOAT)
1514{
9fddaa0c 1515 RET_INVAL(ctx);
79aceca5
FB
1516}
1517
1518/*** Branch ***/
79aceca5
FB
1519
1520/* b ba bl bla */
1521GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
1522{
1523 uint32_t li = s_ext24(LI(ctx->opcode)), target;
1524
1525 if (AA(ctx->opcode) == 0)
046d6672 1526 target = ctx->nip + li - 4;
79aceca5 1527 else
9a64fbe4 1528 target = li;
9a64fbe4 1529 if (LK(ctx->opcode)) {
046d6672 1530 gen_op_setlr(ctx->nip);
9a64fbe4 1531 }
e98a6e40 1532 gen_op_b((long)ctx->tb, target);
9a64fbe4 1533 ctx->exception = EXCP_BRANCH;
79aceca5
FB
1534}
1535
e98a6e40
FB
1536#define BCOND_IM 0
1537#define BCOND_LR 1
1538#define BCOND_CTR 2
1539
1540static inline void gen_bcond(DisasContext *ctx, int type)
1541{
1542 uint32_t target = 0;
1543 uint32_t bo = BO(ctx->opcode);
1544 uint32_t bi = BI(ctx->opcode);
1545 uint32_t mask;
1546 uint32_t li;
1547
e98a6e40
FB
1548 if ((bo & 0x4) == 0)
1549 gen_op_dec_ctr();
1550 switch(type) {
1551 case BCOND_IM:
1552 li = s_ext16(BD(ctx->opcode));
1553 if (AA(ctx->opcode) == 0) {
046d6672 1554 target = ctx->nip + li - 4;
e98a6e40
FB
1555 } else {
1556 target = li;
1557 }
1558 break;
1559 case BCOND_CTR:
1560 gen_op_movl_T1_ctr();
1561 break;
1562 default:
1563 case BCOND_LR:
1564 gen_op_movl_T1_lr();
1565 break;
1566 }
1567 if (LK(ctx->opcode)) {
046d6672 1568 gen_op_setlr(ctx->nip);
e98a6e40
FB
1569 }
1570 if (bo & 0x10) {
1571 /* No CR condition */
1572 switch (bo & 0x6) {
1573 case 0:
1574 gen_op_test_ctr();
1575 break;
1576 case 2:
1577 gen_op_test_ctrz();
1578 break;
1579 default:
1580 case 4:
1581 case 6:
1582 if (type == BCOND_IM) {
1583 gen_op_b((long)ctx->tb, target);
1584 } else {
1585 gen_op_b_T1();
e98a6e40
FB
1586 }
1587 goto no_test;
1588 }
1589 } else {
1590 mask = 1 << (3 - (bi & 0x03));
1591 gen_op_load_crf_T0(bi >> 2);
1592 if (bo & 0x8) {
1593 switch (bo & 0x6) {
1594 case 0:
1595 gen_op_test_ctr_true(mask);
1596 break;
1597 case 2:
1598 gen_op_test_ctrz_true(mask);
1599 break;
1600 default:
1601 case 4:
1602 case 6:
1603 gen_op_test_true(mask);
1604 break;
1605 }
1606 } else {
1607 switch (bo & 0x6) {
1608 case 0:
1609 gen_op_test_ctr_false(mask);
1610 break;
1611 case 2:
1612 gen_op_test_ctrz_false(mask);
1613 break;
1614 default:
1615 case 4:
1616 case 6:
1617 gen_op_test_false(mask);
1618 break;
1619 }
1620 }
1621 }
1622 if (type == BCOND_IM) {
046d6672 1623 gen_op_btest((long)ctx->tb, target, ctx->nip);
e98a6e40 1624 } else {
046d6672 1625 gen_op_btest_T1(ctx->nip);
e98a6e40
FB
1626 }
1627 no_test:
1628 ctx->exception = EXCP_BRANCH;
1629}
1630
1631GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
1632{
1633 gen_bcond(ctx, BCOND_IM);
1634}
1635
1636GEN_HANDLER(bcctr, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW)
1637{
1638 gen_bcond(ctx, BCOND_CTR);
1639}
1640
1641GEN_HANDLER(bclr, 0x13, 0x10, 0x00, 0x00000000, PPC_FLOW)
1642{
1643 gen_bcond(ctx, BCOND_LR);
1644}
79aceca5
FB
1645
1646/*** Condition register logical ***/
1647#define GEN_CRLOGIC(op, opc) \
1648GEN_HANDLER(cr##op, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER) \
1649{ \
1650 gen_op_load_crf_T0(crbA(ctx->opcode) >> 2); \
1651 gen_op_getbit_T0(3 - (crbA(ctx->opcode) & 0x03)); \
1652 gen_op_load_crf_T1(crbB(ctx->opcode) >> 2); \
1653 gen_op_getbit_T1(3 - (crbB(ctx->opcode) & 0x03)); \
1654 gen_op_##op(); \
1655 gen_op_load_crf_T1(crbD(ctx->opcode) >> 2); \
1656 gen_op_setcrfbit(~(1 << (3 - (crbD(ctx->opcode) & 0x03))), \
1657 3 - (crbD(ctx->opcode) & 0x03)); \
1658 gen_op_store_T1_crf(crbD(ctx->opcode) >> 2); \
79aceca5
FB
1659}
1660
1661/* crand */
1662GEN_CRLOGIC(and, 0x08)
1663/* crandc */
1664GEN_CRLOGIC(andc, 0x04)
1665/* creqv */
1666GEN_CRLOGIC(eqv, 0x09)
1667/* crnand */
1668GEN_CRLOGIC(nand, 0x07)
1669/* crnor */
1670GEN_CRLOGIC(nor, 0x01)
1671/* cror */
1672GEN_CRLOGIC(or, 0x0E)
1673/* crorc */
1674GEN_CRLOGIC(orc, 0x0D)
1675/* crxor */
1676GEN_CRLOGIC(xor, 0x06)
1677/* mcrf */
1678GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER)
1679{
1680 gen_op_load_crf_T0(crfS(ctx->opcode));
1681 gen_op_store_T0_crf(crfD(ctx->opcode));
79aceca5
FB
1682}
1683
1684/*** System linkage ***/
1685/* rfi (supervisor only) */
1686GEN_HANDLER(rfi, 0x13, 0x12, 0xFF, 0x03FF8001, PPC_FLOW)
1687{
9a64fbe4 1688#if defined(CONFIG_USER_ONLY)
9fddaa0c 1689 RET_PRIVOPC(ctx);
9a64fbe4
FB
1690#else
1691 /* Restore CPU state */
1692 if (!ctx->supervisor) {
9fddaa0c
FB
1693 RET_PRIVOPC(ctx);
1694 return;
9a64fbe4
FB
1695 }
1696 gen_op_rfi();
9fddaa0c 1697 RET_EXCP(ctx, EXCP_RFI, 0);
9a64fbe4 1698#endif
79aceca5
FB
1699}
1700
1701/* sc */
1702GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFFFFD, PPC_FLOW)
1703{
9a64fbe4 1704#if defined(CONFIG_USER_ONLY)
9fddaa0c 1705 RET_EXCP(ctx, EXCP_SYSCALL_USER, 0);
9a64fbe4 1706#else
9fddaa0c 1707 RET_EXCP(ctx, EXCP_SYSCALL, 0);
9a64fbe4 1708#endif
79aceca5
FB
1709}
1710
1711/*** Trap ***/
1712/* tw */
1713GEN_HANDLER(tw, 0x1F, 0x04, 0xFF, 0x00000001, PPC_FLOW)
1714{
9a64fbe4
FB
1715 gen_op_load_gpr_T0(rA(ctx->opcode));
1716 gen_op_load_gpr_T1(rB(ctx->opcode));
1717 gen_op_tw(TO(ctx->opcode));
79aceca5
FB
1718}
1719
1720/* twi */
1721GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
1722{
9a64fbe4
FB
1723 gen_op_load_gpr_T0(rA(ctx->opcode));
1724#if 0
1725 printf("%s: param=0x%04x T0=0x%04x\n", __func__,
1726 SIMM(ctx->opcode), TO(ctx->opcode));
1727#endif
1728 gen_op_twi(SIMM(ctx->opcode), TO(ctx->opcode));
79aceca5
FB
1729}
1730
1731/*** Processor control ***/
1732static inline int check_spr_access (int spr, int rw, int supervisor)
1733{
1734 uint32_t rights = spr_access[spr >> 1] >> (4 * (spr & 1));
1735
9a64fbe4
FB
1736#if 0
1737 if (spr != LR && spr != CTR) {
1738 if (loglevel > 0) {
1739 fprintf(logfile, "%s reg=%d s=%d rw=%d r=0x%02x 0x%02x\n", __func__,
1740 SPR_ENCODE(spr), supervisor, rw, rights,
1741 (rights >> ((2 * supervisor) + rw)) & 1);
1742 } else {
1743 printf("%s reg=%d s=%d rw=%d r=0x%02x 0x%02x\n", __func__,
1744 SPR_ENCODE(spr), supervisor, rw, rights,
1745 (rights >> ((2 * supervisor) + rw)) & 1);
1746 }
1747 }
1748#endif
1749 if (rights == 0)
1750 return -1;
79aceca5
FB
1751 rights = rights >> (2 * supervisor);
1752 rights = rights >> rw;
1753
1754 return rights & 1;
1755}
1756
1757/* mcrxr */
1758GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC)
1759{
1760 gen_op_load_xer_cr();
1761 gen_op_store_T0_crf(crfD(ctx->opcode));
1762 gen_op_clear_xer_cr();
79aceca5
FB
1763}
1764
1765/* mfcr */
1766GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x001FF801, PPC_MISC)
1767{
1768 gen_op_load_cr();
1769 gen_op_store_T0_gpr(rD(ctx->opcode));
79aceca5
FB
1770}
1771
1772/* mfmsr */
1773GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC)
1774{
9a64fbe4 1775#if defined(CONFIG_USER_ONLY)
9fddaa0c 1776 RET_PRIVREG(ctx);
9a64fbe4
FB
1777#else
1778 if (!ctx->supervisor) {
9fddaa0c
FB
1779 RET_PRIVREG(ctx);
1780 return;
9a64fbe4 1781 }
79aceca5
FB
1782 gen_op_load_msr();
1783 gen_op_store_T0_gpr(rD(ctx->opcode));
9a64fbe4 1784#endif
79aceca5
FB
1785}
1786
1787/* mfspr */
1788GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC)
1789{
1790 uint32_t sprn = SPR(ctx->opcode);
1791
9a64fbe4
FB
1792#if defined(CONFIG_USER_ONLY)
1793 switch (check_spr_access(sprn, 0, 0))
1794#else
1795 switch (check_spr_access(sprn, 0, ctx->supervisor))
1796#endif
1797 {
1798 case -1:
9fddaa0c
FB
1799 RET_EXCP(ctx, EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_SPR);
1800 return;
9a64fbe4 1801 case 0:
9fddaa0c
FB
1802 RET_PRIVREG(ctx);
1803 return;
9a64fbe4
FB
1804 default:
1805 break;
79aceca5 1806 }
9a64fbe4
FB
1807 switch (sprn) {
1808 case XER:
79aceca5
FB
1809 gen_op_load_xer();
1810 break;
9a64fbe4
FB
1811 case LR:
1812 gen_op_load_lr();
1813 break;
1814 case CTR:
1815 gen_op_load_ctr();
1816 break;
1817 case IBAT0U:
1818 gen_op_load_ibat(0, 0);
1819 break;
1820 case IBAT1U:
1821 gen_op_load_ibat(0, 1);
1822 break;
1823 case IBAT2U:
1824 gen_op_load_ibat(0, 2);
1825 break;
1826 case IBAT3U:
1827 gen_op_load_ibat(0, 3);
1828 break;
1829 case IBAT4U:
1830 gen_op_load_ibat(0, 4);
1831 break;
1832 case IBAT5U:
1833 gen_op_load_ibat(0, 5);
1834 break;
1835 case IBAT6U:
1836 gen_op_load_ibat(0, 6);
1837 break;
1838 case IBAT7U:
1839 gen_op_load_ibat(0, 7);
1840 break;
1841 case IBAT0L:
1842 gen_op_load_ibat(1, 0);
1843 break;
1844 case IBAT1L:
1845 gen_op_load_ibat(1, 1);
1846 break;
1847 case IBAT2L:
1848 gen_op_load_ibat(1, 2);
1849 break;
1850 case IBAT3L:
1851 gen_op_load_ibat(1, 3);
1852 break;
1853 case IBAT4L:
1854 gen_op_load_ibat(1, 4);
1855 break;
1856 case IBAT5L:
1857 gen_op_load_ibat(1, 5);
1858 break;
1859 case IBAT6L:
1860 gen_op_load_ibat(1, 6);
1861 break;
1862 case IBAT7L:
1863 gen_op_load_ibat(1, 7);
1864 break;
1865 case DBAT0U:
1866 gen_op_load_dbat(0, 0);
1867 break;
1868 case DBAT1U:
1869 gen_op_load_dbat(0, 1);
1870 break;
1871 case DBAT2U:
1872 gen_op_load_dbat(0, 2);
1873 break;
1874 case DBAT3U:
1875 gen_op_load_dbat(0, 3);
1876 break;
1877 case DBAT4U:
1878 gen_op_load_dbat(0, 4);
1879 break;
1880 case DBAT5U:
1881 gen_op_load_dbat(0, 5);
1882 break;
1883 case DBAT6U:
1884 gen_op_load_dbat(0, 6);
1885 break;
1886 case DBAT7U:
1887 gen_op_load_dbat(0, 7);
1888 break;
1889 case DBAT0L:
1890 gen_op_load_dbat(1, 0);
1891 break;
1892 case DBAT1L:
1893 gen_op_load_dbat(1, 1);
1894 break;
1895 case DBAT2L:
1896 gen_op_load_dbat(1, 2);
1897 break;
1898 case DBAT3L:
1899 gen_op_load_dbat(1, 3);
1900 break;
1901 case DBAT4L:
1902 gen_op_load_dbat(1, 4);
1903 break;
1904 case DBAT5L:
1905 gen_op_load_dbat(1, 5);
1906 break;
1907 case DBAT6L:
1908 gen_op_load_dbat(1, 6);
1909 break;
1910 case DBAT7L:
1911 gen_op_load_dbat(1, 7);
1912 break;
1913 case SDR1:
1914 gen_op_load_sdr1();
1915 break;
1916 case V_TBL:
9fddaa0c 1917 gen_op_load_tbl();
79aceca5 1918 break;
9a64fbe4 1919 case V_TBU:
9fddaa0c 1920 gen_op_load_tbu();
9a64fbe4
FB
1921 break;
1922 case DECR:
9fddaa0c 1923 gen_op_load_decr();
79aceca5
FB
1924 break;
1925 default:
1926 gen_op_load_spr(sprn);
1927 break;
1928 }
9a64fbe4 1929 gen_op_store_T0_gpr(rD(ctx->opcode));
79aceca5
FB
1930}
1931
1932/* mftb */
1933GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MISC)
1934{
1935 uint32_t sprn = SPR(ctx->opcode);
1936
79aceca5 1937 /* We need to update the time base before reading it */
9a64fbe4
FB
1938 switch (sprn) {
1939 case V_TBL:
9fddaa0c 1940 gen_op_load_tbl();
79aceca5 1941 break;
9a64fbe4 1942 case V_TBU:
9fddaa0c 1943 gen_op_load_tbu();
79aceca5
FB
1944 break;
1945 default:
9fddaa0c
FB
1946 RET_INVAL(ctx);
1947 return;
79aceca5 1948 }
9a64fbe4 1949 gen_op_store_T0_gpr(rD(ctx->opcode));
79aceca5
FB
1950}
1951
1952/* mtcrf */
1953GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00100801, PPC_MISC)
1954{
1955 gen_op_load_gpr_T0(rS(ctx->opcode));
1956 gen_op_store_cr(CRM(ctx->opcode));
79aceca5
FB
1957}
1958
1959/* mtmsr */
1960GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC)
1961{
9a64fbe4 1962#if defined(CONFIG_USER_ONLY)
9fddaa0c 1963 RET_PRIVREG(ctx);
9a64fbe4
FB
1964#else
1965 if (!ctx->supervisor) {
9fddaa0c
FB
1966 RET_PRIVREG(ctx);
1967 return;
9a64fbe4 1968 }
79aceca5
FB
1969 gen_op_load_gpr_T0(rS(ctx->opcode));
1970 gen_op_store_msr();
1971 /* Must stop the translation as machine state (may have) changed */
9fddaa0c 1972 RET_MTMSR(ctx);
9a64fbe4 1973#endif
79aceca5
FB
1974}
1975
1976/* mtspr */
1977GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC)
1978{
1979 uint32_t sprn = SPR(ctx->opcode);
1980
9a64fbe4
FB
1981#if 0
1982 if (loglevel > 0) {
1983 fprintf(logfile, "MTSPR %d src=%d (%d)\n", SPR_ENCODE(sprn),
1984 rS(ctx->opcode), sprn);
1985 }
1986#endif
1987#if defined(CONFIG_USER_ONLY)
1988 switch (check_spr_access(sprn, 1, 0))
1989#else
1990 switch (check_spr_access(sprn, 1, ctx->supervisor))
1991#endif
1992 {
1993 case -1:
9fddaa0c 1994 RET_EXCP(ctx, EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_SPR);
9a64fbe4
FB
1995 break;
1996 case 0:
9fddaa0c 1997 RET_PRIVREG(ctx);
9a64fbe4
FB
1998 break;
1999 default:
2000 break;
2001 }
79aceca5 2002 gen_op_load_gpr_T0(rS(ctx->opcode));
9a64fbe4
FB
2003 switch (sprn) {
2004 case XER:
79aceca5 2005 gen_op_store_xer();
9a64fbe4
FB
2006 break;
2007 case LR:
9a64fbe4
FB
2008 gen_op_store_lr();
2009 break;
2010 case CTR:
2011 gen_op_store_ctr();
2012 break;
2013 case IBAT0U:
2014 gen_op_store_ibat(0, 0);
4b3686fa 2015 RET_MTMSR(ctx);
9a64fbe4
FB
2016 break;
2017 case IBAT1U:
2018 gen_op_store_ibat(0, 1);
4b3686fa 2019 RET_MTMSR(ctx);
9a64fbe4
FB
2020 break;
2021 case IBAT2U:
2022 gen_op_store_ibat(0, 2);
4b3686fa 2023 RET_MTMSR(ctx);
9a64fbe4
FB
2024 break;
2025 case IBAT3U:
2026 gen_op_store_ibat(0, 3);
4b3686fa 2027 RET_MTMSR(ctx);
9a64fbe4
FB
2028 break;
2029 case IBAT4U:
2030 gen_op_store_ibat(0, 4);
4b3686fa 2031 RET_MTMSR(ctx);
9a64fbe4
FB
2032 break;
2033 case IBAT5U:
2034 gen_op_store_ibat(0, 5);
4b3686fa 2035 RET_MTMSR(ctx);
9a64fbe4
FB
2036 break;
2037 case IBAT6U:
2038 gen_op_store_ibat(0, 6);
4b3686fa 2039 RET_MTMSR(ctx);
9a64fbe4
FB
2040 break;
2041 case IBAT7U:
2042 gen_op_store_ibat(0, 7);
4b3686fa 2043 RET_MTMSR(ctx);
9a64fbe4
FB
2044 break;
2045 case IBAT0L:
2046 gen_op_store_ibat(1, 0);
4b3686fa 2047 RET_MTMSR(ctx);
9a64fbe4
FB
2048 break;
2049 case IBAT1L:
2050 gen_op_store_ibat(1, 1);
4b3686fa 2051 RET_MTMSR(ctx);
9a64fbe4
FB
2052 break;
2053 case IBAT2L:
2054 gen_op_store_ibat(1, 2);
4b3686fa 2055 RET_MTMSR(ctx);
9a64fbe4
FB
2056 break;
2057 case IBAT3L:
2058 gen_op_store_ibat(1, 3);
4b3686fa 2059 RET_MTMSR(ctx);
9a64fbe4
FB
2060 break;
2061 case IBAT4L:
2062 gen_op_store_ibat(1, 4);
4b3686fa 2063 RET_MTMSR(ctx);
9a64fbe4
FB
2064 break;
2065 case IBAT5L:
2066 gen_op_store_ibat(1, 5);
4b3686fa 2067 RET_MTMSR(ctx);
9a64fbe4
FB
2068 break;
2069 case IBAT6L:
2070 gen_op_store_ibat(1, 6);
4b3686fa 2071 RET_MTMSR(ctx);
9a64fbe4
FB
2072 break;
2073 case IBAT7L:
2074 gen_op_store_ibat(1, 7);
4b3686fa 2075 RET_MTMSR(ctx);
9a64fbe4
FB
2076 break;
2077 case DBAT0U:
2078 gen_op_store_dbat(0, 0);
4b3686fa 2079 RET_MTMSR(ctx);
9a64fbe4
FB
2080 break;
2081 case DBAT1U:
2082 gen_op_store_dbat(0, 1);
4b3686fa 2083 RET_MTMSR(ctx);
9a64fbe4
FB
2084 break;
2085 case DBAT2U:
2086 gen_op_store_dbat(0, 2);
4b3686fa 2087 RET_MTMSR(ctx);
9a64fbe4
FB
2088 break;
2089 case DBAT3U:
2090 gen_op_store_dbat(0, 3);
4b3686fa 2091 RET_MTMSR(ctx);
9a64fbe4
FB
2092 break;
2093 case DBAT4U:
2094 gen_op_store_dbat(0, 4);
4b3686fa 2095 RET_MTMSR(ctx);
9a64fbe4
FB
2096 break;
2097 case DBAT5U:
2098 gen_op_store_dbat(0, 5);
4b3686fa 2099 RET_MTMSR(ctx);
9a64fbe4
FB
2100 break;
2101 case DBAT6U:
2102 gen_op_store_dbat(0, 6);
4b3686fa 2103 RET_MTMSR(ctx);
9a64fbe4
FB
2104 break;
2105 case DBAT7U:
2106 gen_op_store_dbat(0, 7);
4b3686fa 2107 RET_MTMSR(ctx);
9a64fbe4
FB
2108 break;
2109 case DBAT0L:
2110 gen_op_store_dbat(1, 0);
4b3686fa 2111 RET_MTMSR(ctx);
9a64fbe4
FB
2112 break;
2113 case DBAT1L:
2114 gen_op_store_dbat(1, 1);
4b3686fa 2115 RET_MTMSR(ctx);
9a64fbe4
FB
2116 break;
2117 case DBAT2L:
2118 gen_op_store_dbat(1, 2);
4b3686fa 2119 RET_MTMSR(ctx);
9a64fbe4
FB
2120 break;
2121 case DBAT3L:
2122 gen_op_store_dbat(1, 3);
4b3686fa 2123 RET_MTMSR(ctx);
9a64fbe4
FB
2124 break;
2125 case DBAT4L:
2126 gen_op_store_dbat(1, 4);
4b3686fa 2127 RET_MTMSR(ctx);
9a64fbe4
FB
2128 break;
2129 case DBAT5L:
2130 gen_op_store_dbat(1, 5);
4b3686fa 2131 RET_MTMSR(ctx);
9a64fbe4
FB
2132 break;
2133 case DBAT6L:
2134 gen_op_store_dbat(1, 6);
4b3686fa 2135 RET_MTMSR(ctx);
9a64fbe4
FB
2136 break;
2137 case DBAT7L:
2138 gen_op_store_dbat(1, 7);
4b3686fa 2139 RET_MTMSR(ctx);
9a64fbe4
FB
2140 break;
2141 case SDR1:
2142 gen_op_store_sdr1();
4b3686fa 2143 RET_MTMSR(ctx);
9a64fbe4
FB
2144 break;
2145 case O_TBL:
9fddaa0c 2146 gen_op_store_tbl();
9a64fbe4
FB
2147 break;
2148 case O_TBU:
9fddaa0c 2149 gen_op_store_tbu();
9a64fbe4
FB
2150 break;
2151 case DECR:
2152 gen_op_store_decr();
9a64fbe4 2153 break;
4b3686fa
FB
2154#if 0
2155 case HID0:
2156 gen_op_store_hid0();
2157 break;
2158#endif
9a64fbe4 2159 default:
79aceca5 2160 gen_op_store_spr(sprn);
9a64fbe4 2161 break;
79aceca5 2162 }
79aceca5
FB
2163}
2164
2165/*** Cache management ***/
2166/* For now, all those will be implemented as nop:
2167 * this is valid, regarding the PowerPC specs...
9a64fbe4 2168 * We just have to flush tb while invalidating instruction cache lines...
79aceca5
FB
2169 */
2170/* dcbf */
9a64fbe4 2171GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03E00001, PPC_CACHE)
79aceca5 2172{
a541f297
FB
2173 if (rA(ctx->opcode) == 0) {
2174 gen_op_load_gpr_T0(rB(ctx->opcode));
2175 } else {
2176 gen_op_load_gpr_T0(rA(ctx->opcode));
2177 gen_op_load_gpr_T1(rB(ctx->opcode));
2178 gen_op_add();
2179 }
2180 op_ldst(lbz);
79aceca5
FB
2181}
2182
2183/* dcbi (Supervisor only) */
9a64fbe4 2184GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE)
79aceca5 2185{
a541f297 2186#if defined(CONFIG_USER_ONLY)
9fddaa0c 2187 RET_PRIVOPC(ctx);
a541f297
FB
2188#else
2189 if (!ctx->supervisor) {
9fddaa0c
FB
2190 RET_PRIVOPC(ctx);
2191 return;
9a64fbe4 2192 }
a541f297
FB
2193 if (rA(ctx->opcode) == 0) {
2194 gen_op_load_gpr_T0(rB(ctx->opcode));
2195 } else {
2196 gen_op_load_gpr_T0(rA(ctx->opcode));
2197 gen_op_load_gpr_T1(rB(ctx->opcode));
2198 gen_op_add();
2199 }
2200 op_ldst(lbz);
2201 op_ldst(stb);
2202#endif
79aceca5
FB
2203}
2204
2205/* dcdst */
9a64fbe4 2206GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE)
79aceca5 2207{
a541f297
FB
2208 if (rA(ctx->opcode) == 0) {
2209 gen_op_load_gpr_T0(rB(ctx->opcode));
2210 } else {
2211 gen_op_load_gpr_T0(rA(ctx->opcode));
2212 gen_op_load_gpr_T1(rB(ctx->opcode));
2213 gen_op_add();
2214 }
2215 op_ldst(lbz);
79aceca5
FB
2216}
2217
2218/* dcbt */
9a64fbe4 2219GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x03E00001, PPC_CACHE)
79aceca5 2220{
79aceca5
FB
2221}
2222
2223/* dcbtst */
9a64fbe4 2224GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x03E00001, PPC_CACHE)
79aceca5 2225{
79aceca5
FB
2226}
2227
2228/* dcbz */
9a64fbe4
FB
2229#if defined(CONFIG_USER_ONLY)
2230#define op_dcbz() gen_op_dcbz_raw()
2231#else
2232#define op_dcbz() (*gen_op_dcbz[ctx->mem_idx])()
2233static GenOpFunc *gen_op_dcbz[] = {
2234 &gen_op_dcbz_user,
2235 &gen_op_dcbz_kernel,
2236};
2237#endif
2238
2239GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03E00001, PPC_CACHE)
79aceca5 2240{
fb0eaffc
FB
2241 if (rA(ctx->opcode) == 0) {
2242 gen_op_load_gpr_T0(rB(ctx->opcode));
fb0eaffc
FB
2243 } else {
2244 gen_op_load_gpr_T0(rA(ctx->opcode));
2245 gen_op_load_gpr_T1(rB(ctx->opcode));
9a64fbe4 2246 gen_op_add();
fb0eaffc 2247 }
9a64fbe4 2248 op_dcbz();
4b3686fa 2249 gen_op_check_reservation();
79aceca5
FB
2250}
2251
2252/* icbi */
9a64fbe4 2253GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE)
79aceca5 2254{
fb0eaffc
FB
2255 if (rA(ctx->opcode) == 0) {
2256 gen_op_load_gpr_T0(rB(ctx->opcode));
fb0eaffc
FB
2257 } else {
2258 gen_op_load_gpr_T0(rA(ctx->opcode));
2259 gen_op_load_gpr_T1(rB(ctx->opcode));
9a64fbe4 2260 gen_op_add();
fb0eaffc 2261 }
9a64fbe4 2262 gen_op_icbi();
79aceca5
FB
2263}
2264
2265/* Optional: */
2266/* dcba */
9a64fbe4 2267GEN_HANDLER(dcba, 0x1F, 0x16, 0x07, 0x03E00001, PPC_CACHE_OPT)
79aceca5 2268{
79aceca5
FB
2269}
2270
2271/*** Segment register manipulation ***/
2272/* Supervisor only: */
2273/* mfsr */
2274GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT)
2275{
9a64fbe4 2276#if defined(CONFIG_USER_ONLY)
9fddaa0c 2277 RET_PRIVREG(ctx);
9a64fbe4
FB
2278#else
2279 if (!ctx->supervisor) {
9fddaa0c
FB
2280 RET_PRIVREG(ctx);
2281 return;
9a64fbe4
FB
2282 }
2283 gen_op_load_sr(SR(ctx->opcode));
2284 gen_op_store_T0_gpr(rD(ctx->opcode));
2285#endif
79aceca5
FB
2286}
2287
2288/* mfsrin */
9a64fbe4 2289GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT)
79aceca5 2290{
9a64fbe4 2291#if defined(CONFIG_USER_ONLY)
9fddaa0c 2292 RET_PRIVREG(ctx);
9a64fbe4
FB
2293#else
2294 if (!ctx->supervisor) {
9fddaa0c
FB
2295 RET_PRIVREG(ctx);
2296 return;
9a64fbe4
FB
2297 }
2298 gen_op_load_gpr_T1(rB(ctx->opcode));
2299 gen_op_load_srin();
2300 gen_op_store_T0_gpr(rD(ctx->opcode));
2301#endif
79aceca5
FB
2302}
2303
2304/* mtsr */
e63c59cb 2305GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT)
79aceca5 2306{
9a64fbe4 2307#if defined(CONFIG_USER_ONLY)
9fddaa0c 2308 RET_PRIVREG(ctx);
9a64fbe4
FB
2309#else
2310 if (!ctx->supervisor) {
9fddaa0c
FB
2311 RET_PRIVREG(ctx);
2312 return;
9a64fbe4
FB
2313 }
2314 gen_op_load_gpr_T0(rS(ctx->opcode));
2315 gen_op_store_sr(SR(ctx->opcode));
9a64fbe4 2316#endif
79aceca5
FB
2317}
2318
2319/* mtsrin */
9a64fbe4 2320GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT)
79aceca5 2321{
9a64fbe4 2322#if defined(CONFIG_USER_ONLY)
9fddaa0c 2323 RET_PRIVREG(ctx);
9a64fbe4
FB
2324#else
2325 if (!ctx->supervisor) {
9fddaa0c
FB
2326 RET_PRIVREG(ctx);
2327 return;
9a64fbe4
FB
2328 }
2329 gen_op_load_gpr_T0(rS(ctx->opcode));
2330 gen_op_load_gpr_T1(rB(ctx->opcode));
2331 gen_op_store_srin();
9a64fbe4 2332#endif
79aceca5
FB
2333}
2334
2335/*** Lookaside buffer management ***/
2336/* Optional & supervisor only: */
2337/* tlbia */
9a64fbe4 2338GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_OPT)
79aceca5 2339{
9a64fbe4 2340#if defined(CONFIG_USER_ONLY)
9fddaa0c 2341 RET_PRIVOPC(ctx);
9a64fbe4
FB
2342#else
2343 if (!ctx->supervisor) {
9fddaa0c
FB
2344 if (loglevel)
2345 fprintf(logfile, "%s: ! supervisor\n", __func__);
2346 RET_PRIVOPC(ctx);
2347 return;
9a64fbe4
FB
2348 }
2349 gen_op_tlbia();
4b3686fa 2350 RET_MTMSR(ctx);
9a64fbe4 2351#endif
79aceca5
FB
2352}
2353
2354/* tlbie */
9a64fbe4 2355GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM)
79aceca5 2356{
9a64fbe4 2357#if defined(CONFIG_USER_ONLY)
9fddaa0c 2358 RET_PRIVOPC(ctx);
9a64fbe4
FB
2359#else
2360 if (!ctx->supervisor) {
9fddaa0c
FB
2361 RET_PRIVOPC(ctx);
2362 return;
9a64fbe4
FB
2363 }
2364 gen_op_load_gpr_T0(rB(ctx->opcode));
2365 gen_op_tlbie();
4b3686fa 2366 RET_MTMSR(ctx);
9a64fbe4 2367#endif
79aceca5
FB
2368}
2369
2370/* tlbsync */
e63c59cb 2371GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM)
79aceca5 2372{
9a64fbe4 2373#if defined(CONFIG_USER_ONLY)
9fddaa0c 2374 RET_PRIVOPC(ctx);
9a64fbe4
FB
2375#else
2376 if (!ctx->supervisor) {
9fddaa0c
FB
2377 RET_PRIVOPC(ctx);
2378 return;
9a64fbe4
FB
2379 }
2380 /* This has no effect: it should ensure that all previous
2381 * tlbie have completed
2382 */
4b3686fa 2383 RET_MTMSR(ctx);
9a64fbe4 2384#endif
79aceca5
FB
2385}
2386
2387/*** External control ***/
2388/* Optional: */
2389/* eciwx */
9a64fbe4
FB
2390#if defined(CONFIG_USER_ONLY)
2391#define op_eciwx() gen_op_eciwx_raw()
2392#define op_ecowx() gen_op_ecowx_raw()
2393#else
2394#define op_eciwx() (*gen_op_eciwx[ctx->mem_idx])()
2395#define op_ecowx() (*gen_op_ecowx[ctx->mem_idx])()
2396static GenOpFunc *gen_op_eciwx[] = {
2397 &gen_op_eciwx_user,
2398 &gen_op_eciwx_kernel,
2399};
2400static GenOpFunc *gen_op_ecowx[] = {
2401 &gen_op_ecowx_user,
2402 &gen_op_ecowx_kernel,
2403};
2404#endif
2405
79aceca5
FB
2406GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN)
2407{
9a64fbe4
FB
2408 /* Should check EAR[E] & alignment ! */
2409 if (rA(ctx->opcode) == 0) {
2410 gen_op_load_gpr_T0(rB(ctx->opcode));
2411 } else {
2412 gen_op_load_gpr_T0(rA(ctx->opcode));
2413 gen_op_load_gpr_T1(rB(ctx->opcode));
2414 gen_op_add();
2415 }
2416 op_eciwx();
2417 gen_op_store_T0_gpr(rD(ctx->opcode));
79aceca5
FB
2418}
2419
2420/* ecowx */
2421GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN)
2422{
9a64fbe4
FB
2423 /* Should check EAR[E] & alignment ! */
2424 if (rA(ctx->opcode) == 0) {
2425 gen_op_load_gpr_T0(rB(ctx->opcode));
2426 } else {
2427 gen_op_load_gpr_T0(rA(ctx->opcode));
2428 gen_op_load_gpr_T1(rB(ctx->opcode));
2429 gen_op_add();
2430 }
2431 gen_op_load_gpr_T2(rS(ctx->opcode));
2432 op_ecowx();
79aceca5
FB
2433}
2434
2435/* End opcode list */
2436GEN_OPCODE_MARK(end);
2437
2438/*****************************************************************************/
9a64fbe4 2439#include <stdlib.h>
79aceca5 2440#include <string.h>
9a64fbe4
FB
2441
2442int fflush (FILE *stream);
79aceca5
FB
2443
2444/* Main ppc opcodes table:
2445 * at init, all opcodes are invalids
2446 */
2447static opc_handler_t *ppc_opcodes[0x40];
2448
2449/* Opcode types */
2450enum {
2451 PPC_DIRECT = 0, /* Opcode routine */
2452 PPC_INDIRECT = 1, /* Indirect opcode table */
2453};
2454
2455static inline int is_indirect_opcode (void *handler)
2456{
2457 return ((unsigned long)handler & 0x03) == PPC_INDIRECT;
2458}
2459
2460static inline opc_handler_t **ind_table(void *handler)
2461{
2462 return (opc_handler_t **)((unsigned long)handler & ~3);
2463}
2464
9a64fbe4 2465/* Instruction table creation */
79aceca5
FB
2466/* Opcodes tables creation */
2467static void fill_new_table (opc_handler_t **table, int len)
2468{
2469 int i;
2470
2471 for (i = 0; i < len; i++)
2472 table[i] = &invalid_handler;
2473}
2474
2475static int create_new_table (opc_handler_t **table, unsigned char idx)
2476{
2477 opc_handler_t **tmp;
2478
2479 tmp = malloc(0x20 * sizeof(opc_handler_t));
2480 if (tmp == NULL)
2481 return -1;
2482 fill_new_table(tmp, 0x20);
2483 table[idx] = (opc_handler_t *)((unsigned long)tmp | PPC_INDIRECT);
2484
2485 return 0;
2486}
2487
2488static int insert_in_table (opc_handler_t **table, unsigned char idx,
2489 opc_handler_t *handler)
2490{
2491 if (table[idx] != &invalid_handler)
2492 return -1;
2493 table[idx] = handler;
2494
2495 return 0;
2496}
2497
9a64fbe4
FB
2498static int register_direct_insn (opc_handler_t **ppc_opcodes,
2499 unsigned char idx, opc_handler_t *handler)
79aceca5
FB
2500{
2501 if (insert_in_table(ppc_opcodes, idx, handler) < 0) {
9a64fbe4 2502 printf("*** ERROR: opcode %02x already assigned in main "
79aceca5
FB
2503 "opcode table\n", idx);
2504 return -1;
2505 }
2506
2507 return 0;
2508}
2509
2510static int register_ind_in_table (opc_handler_t **table,
2511 unsigned char idx1, unsigned char idx2,
2512 opc_handler_t *handler)
2513{
2514 if (table[idx1] == &invalid_handler) {
2515 if (create_new_table(table, idx1) < 0) {
9a64fbe4 2516 printf("*** ERROR: unable to create indirect table "
79aceca5
FB
2517 "idx=%02x\n", idx1);
2518 return -1;
2519 }
2520 } else {
2521 if (!is_indirect_opcode(table[idx1])) {
9a64fbe4 2522 printf("*** ERROR: idx %02x already assigned to a direct "
79aceca5
FB
2523 "opcode\n", idx1);
2524 return -1;
2525 }
2526 }
2527 if (handler != NULL &&
2528 insert_in_table(ind_table(table[idx1]), idx2, handler) < 0) {
9a64fbe4 2529 printf("*** ERROR: opcode %02x already assigned in "
79aceca5
FB
2530 "opcode table %02x\n", idx2, idx1);
2531 return -1;
2532 }
2533
2534 return 0;
2535}
2536
9a64fbe4
FB
2537static int register_ind_insn (opc_handler_t **ppc_opcodes,
2538 unsigned char idx1, unsigned char idx2,
79aceca5
FB
2539 opc_handler_t *handler)
2540{
2541 int ret;
2542
2543 ret = register_ind_in_table(ppc_opcodes, idx1, idx2, handler);
2544
2545 return ret;
2546}
2547
9a64fbe4
FB
2548static int register_dblind_insn (opc_handler_t **ppc_opcodes,
2549 unsigned char idx1, unsigned char idx2,
79aceca5
FB
2550 unsigned char idx3, opc_handler_t *handler)
2551{
2552 if (register_ind_in_table(ppc_opcodes, idx1, idx2, NULL) < 0) {
9a64fbe4 2553 printf("*** ERROR: unable to join indirect table idx "
79aceca5
FB
2554 "[%02x-%02x]\n", idx1, idx2);
2555 return -1;
2556 }
2557 if (register_ind_in_table(ind_table(ppc_opcodes[idx1]), idx2, idx3,
2558 handler) < 0) {
9a64fbe4 2559 printf("*** ERROR: unable to insert opcode "
79aceca5
FB
2560 "[%02x-%02x-%02x]\n", idx1, idx2, idx3);
2561 return -1;
2562 }
2563
2564 return 0;
2565}
2566
9a64fbe4 2567static int register_insn (opc_handler_t **ppc_opcodes, opcode_t *insn)
79aceca5
FB
2568{
2569 if (insn->opc2 != 0xFF) {
2570 if (insn->opc3 != 0xFF) {
9a64fbe4
FB
2571 if (register_dblind_insn(ppc_opcodes, insn->opc1, insn->opc2,
2572 insn->opc3, &insn->handler) < 0)
79aceca5
FB
2573 return -1;
2574 } else {
9a64fbe4
FB
2575 if (register_ind_insn(ppc_opcodes, insn->opc1,
2576 insn->opc2, &insn->handler) < 0)
79aceca5
FB
2577 return -1;
2578 }
2579 } else {
9a64fbe4 2580 if (register_direct_insn(ppc_opcodes, insn->opc1, &insn->handler) < 0)
79aceca5
FB
2581 return -1;
2582 }
2583
2584 return 0;
2585}
2586
2587static int test_opcode_table (opc_handler_t **table, int len)
2588{
2589 int i, count, tmp;
2590
2591 for (i = 0, count = 0; i < len; i++) {
2592 /* Consistency fixup */
2593 if (table[i] == NULL)
2594 table[i] = &invalid_handler;
2595 if (table[i] != &invalid_handler) {
2596 if (is_indirect_opcode(table[i])) {
2597 tmp = test_opcode_table(ind_table(table[i]), 0x20);
2598 if (tmp == 0) {
2599 free(table[i]);
2600 table[i] = &invalid_handler;
2601 } else {
2602 count++;
2603 }
2604 } else {
2605 count++;
2606 }
2607 }
2608 }
2609
2610 return count;
2611}
2612
9a64fbe4 2613static void fix_opcode_tables (opc_handler_t **ppc_opcodes)
79aceca5
FB
2614{
2615 if (test_opcode_table(ppc_opcodes, 0x40) == 0)
9a64fbe4 2616 printf("*** WARNING: no opcode defined !\n");
79aceca5
FB
2617}
2618
9a64fbe4 2619#define SPR_RIGHTS(rw, priv) (1 << ((2 * (priv)) + (rw)))
79aceca5
FB
2620#define SPR_UR SPR_RIGHTS(0, 0)
2621#define SPR_UW SPR_RIGHTS(1, 0)
2622#define SPR_SR SPR_RIGHTS(0, 1)
2623#define SPR_SW SPR_RIGHTS(1, 1)
2624
2625#define spr_set_rights(spr, rights) \
2626do { \
2627 spr_access[(spr) >> 1] |= ((rights) << (4 * ((spr) & 1))); \
2628} while (0)
2629
9a64fbe4 2630static void init_spr_rights (uint32_t pvr)
79aceca5
FB
2631{
2632 /* XER (SPR 1) */
9a64fbe4 2633 spr_set_rights(XER, SPR_UR | SPR_UW | SPR_SR | SPR_SW);
79aceca5 2634 /* LR (SPR 8) */
9a64fbe4 2635 spr_set_rights(LR, SPR_UR | SPR_UW | SPR_SR | SPR_SW);
79aceca5 2636 /* CTR (SPR 9) */
9a64fbe4 2637 spr_set_rights(CTR, SPR_UR | SPR_UW | SPR_SR | SPR_SW);
79aceca5 2638 /* TBL (SPR 268) */
9a64fbe4 2639 spr_set_rights(V_TBL, SPR_UR | SPR_SR);
79aceca5 2640 /* TBU (SPR 269) */
9a64fbe4 2641 spr_set_rights(V_TBU, SPR_UR | SPR_SR);
79aceca5 2642 /* DSISR (SPR 18) */
9a64fbe4 2643 spr_set_rights(DSISR, SPR_SR | SPR_SW);
79aceca5 2644 /* DAR (SPR 19) */
9a64fbe4 2645 spr_set_rights(DAR, SPR_SR | SPR_SW);
79aceca5 2646 /* DEC (SPR 22) */
9a64fbe4 2647 spr_set_rights(DECR, SPR_SR | SPR_SW);
79aceca5 2648 /* SDR1 (SPR 25) */
9a64fbe4
FB
2649 spr_set_rights(SDR1, SPR_SR | SPR_SW);
2650 /* SRR0 (SPR 26) */
2651 spr_set_rights(SRR0, SPR_SR | SPR_SW);
2652 /* SRR1 (SPR 27) */
2653 spr_set_rights(SRR1, SPR_SR | SPR_SW);
79aceca5 2654 /* SPRG0 (SPR 272) */
9a64fbe4 2655 spr_set_rights(SPRG0, SPR_SR | SPR_SW);
79aceca5 2656 /* SPRG1 (SPR 273) */
9a64fbe4 2657 spr_set_rights(SPRG1, SPR_SR | SPR_SW);
79aceca5 2658 /* SPRG2 (SPR 274) */
9a64fbe4 2659 spr_set_rights(SPRG2, SPR_SR | SPR_SW);
79aceca5 2660 /* SPRG3 (SPR 275) */
9a64fbe4 2661 spr_set_rights(SPRG3, SPR_SR | SPR_SW);
79aceca5 2662 /* ASR (SPR 280) */
9a64fbe4 2663 spr_set_rights(ASR, SPR_SR | SPR_SW);
79aceca5 2664 /* EAR (SPR 282) */
9a64fbe4
FB
2665 spr_set_rights(EAR, SPR_SR | SPR_SW);
2666 /* TBL (SPR 284) */
2667 spr_set_rights(O_TBL, SPR_SW);
2668 /* TBU (SPR 285) */
2669 spr_set_rights(O_TBU, SPR_SW);
2670 /* PVR (SPR 287) */
2671 spr_set_rights(PVR, SPR_SR);
79aceca5 2672 /* IBAT0U (SPR 528) */
9a64fbe4 2673 spr_set_rights(IBAT0U, SPR_SR | SPR_SW);
79aceca5 2674 /* IBAT0L (SPR 529) */
9a64fbe4 2675 spr_set_rights(IBAT0L, SPR_SR | SPR_SW);
79aceca5 2676 /* IBAT1U (SPR 530) */
9a64fbe4 2677 spr_set_rights(IBAT1U, SPR_SR | SPR_SW);
79aceca5 2678 /* IBAT1L (SPR 531) */
9a64fbe4 2679 spr_set_rights(IBAT1L, SPR_SR | SPR_SW);
79aceca5 2680 /* IBAT2U (SPR 532) */
9a64fbe4 2681 spr_set_rights(IBAT2U, SPR_SR | SPR_SW);
79aceca5 2682 /* IBAT2L (SPR 533) */
9a64fbe4 2683 spr_set_rights(IBAT2L, SPR_SR | SPR_SW);
79aceca5 2684 /* IBAT3U (SPR 534) */
9a64fbe4 2685 spr_set_rights(IBAT3U, SPR_SR | SPR_SW);
79aceca5 2686 /* IBAT3L (SPR 535) */
9a64fbe4 2687 spr_set_rights(IBAT3L, SPR_SR | SPR_SW);
79aceca5 2688 /* DBAT0U (SPR 536) */
9a64fbe4 2689 spr_set_rights(DBAT0U, SPR_SR | SPR_SW);
79aceca5 2690 /* DBAT0L (SPR 537) */
9a64fbe4 2691 spr_set_rights(DBAT0L, SPR_SR | SPR_SW);
79aceca5 2692 /* DBAT1U (SPR 538) */
9a64fbe4 2693 spr_set_rights(DBAT1U, SPR_SR | SPR_SW);
79aceca5 2694 /* DBAT1L (SPR 539) */
9a64fbe4 2695 spr_set_rights(DBAT1L, SPR_SR | SPR_SW);
79aceca5 2696 /* DBAT2U (SPR 540) */
9a64fbe4 2697 spr_set_rights(DBAT2U, SPR_SR | SPR_SW);
79aceca5 2698 /* DBAT2L (SPR 541) */
9a64fbe4 2699 spr_set_rights(DBAT2L, SPR_SR | SPR_SW);
79aceca5 2700 /* DBAT3U (SPR 542) */
9a64fbe4 2701 spr_set_rights(DBAT3U, SPR_SR | SPR_SW);
79aceca5 2702 /* DBAT3L (SPR 543) */
9a64fbe4 2703 spr_set_rights(DBAT3L, SPR_SR | SPR_SW);
79aceca5 2704 /* FPECR (SPR 1022) */
9a64fbe4 2705 spr_set_rights(FPECR, SPR_SR | SPR_SW);
4b3686fa
FB
2706 /* Special registers for PPC 604 */
2707 if ((pvr & 0xFFFF0000) == 0x00040000) {
2708 /* IABR */
2709 spr_set_rights(IABR , SPR_SR | SPR_SW);
2710 /* DABR (SPR 1013) */
2711 spr_set_rights(DABR, SPR_SR | SPR_SW);
2712 /* HID0 */
2713 spr_set_rights(HID0, SPR_SR | SPR_SW);
2714 /* PIR */
9a64fbe4 2715 spr_set_rights(PIR, SPR_SR | SPR_SW);
4b3686fa
FB
2716 /* PMC1 */
2717 spr_set_rights(PMC1, SPR_SR | SPR_SW);
2718 /* PMC2 */
2719 spr_set_rights(PMC2, SPR_SR | SPR_SW);
2720 /* MMCR0 */
2721 spr_set_rights(MMCR0, SPR_SR | SPR_SW);
2722 /* SIA */
2723 spr_set_rights(SIA, SPR_SR | SPR_SW);
2724 /* SDA */
2725 spr_set_rights(SDA, SPR_SR | SPR_SW);
2726 }
9a64fbe4
FB
2727 /* Special registers for MPC740/745/750/755 (aka G3) & IBM 750 */
2728 if ((pvr & 0xFFFF0000) == 0x00080000 ||
2729 (pvr & 0xFFFF0000) == 0x70000000) {
2730 /* HID0 */
4b3686fa 2731 spr_set_rights(HID0, SPR_SR | SPR_SW);
9a64fbe4 2732 /* HID1 */
4b3686fa 2733 spr_set_rights(HID1, SPR_SR | SPR_SW);
9a64fbe4 2734 /* IABR */
4b3686fa 2735 spr_set_rights(IABR, SPR_SR | SPR_SW);
9a64fbe4 2736 /* ICTC */
4b3686fa 2737 spr_set_rights(ICTC, SPR_SR | SPR_SW);
9a64fbe4 2738 /* L2CR */
4b3686fa 2739 spr_set_rights(L2CR, SPR_SR | SPR_SW);
9a64fbe4 2740 /* MMCR0 */
4b3686fa 2741 spr_set_rights(MMCR0, SPR_SR | SPR_SW);
9a64fbe4 2742 /* MMCR1 */
4b3686fa 2743 spr_set_rights(MMCR1, SPR_SR | SPR_SW);
9a64fbe4 2744 /* PMC1 */
4b3686fa 2745 spr_set_rights(PMC1, SPR_SR | SPR_SW);
9a64fbe4 2746 /* PMC2 */
4b3686fa 2747 spr_set_rights(PMC2, SPR_SR | SPR_SW);
9a64fbe4 2748 /* PMC3 */
4b3686fa 2749 spr_set_rights(PMC3, SPR_SR | SPR_SW);
9a64fbe4 2750 /* PMC4 */
4b3686fa 2751 spr_set_rights(PMC4, SPR_SR | SPR_SW);
9a64fbe4 2752 /* SIA */
4b3686fa
FB
2753 spr_set_rights(SIA, SPR_SR | SPR_SW);
2754 /* SDA */
2755 spr_set_rights(SDA, SPR_SR | SPR_SW);
9a64fbe4 2756 /* THRM1 */
4b3686fa 2757 spr_set_rights(THRM1, SPR_SR | SPR_SW);
9a64fbe4 2758 /* THRM2 */
4b3686fa 2759 spr_set_rights(THRM2, SPR_SR | SPR_SW);
9a64fbe4 2760 /* THRM3 */
4b3686fa 2761 spr_set_rights(THRM3, SPR_SR | SPR_SW);
9a64fbe4 2762 /* UMMCR0 */
4b3686fa 2763 spr_set_rights(UMMCR0, SPR_UR | SPR_UW);
9a64fbe4 2764 /* UMMCR1 */
4b3686fa 2765 spr_set_rights(UMMCR1, SPR_UR | SPR_UW);
9a64fbe4 2766 /* UPMC1 */
4b3686fa 2767 spr_set_rights(UPMC1, SPR_UR | SPR_UW);
9a64fbe4 2768 /* UPMC2 */
4b3686fa 2769 spr_set_rights(UPMC2, SPR_UR | SPR_UW);
9a64fbe4 2770 /* UPMC3 */
4b3686fa 2771 spr_set_rights(UPMC3, SPR_UR | SPR_UW);
9a64fbe4 2772 /* UPMC4 */
4b3686fa 2773 spr_set_rights(UPMC4, SPR_UR | SPR_UW);
9a64fbe4 2774 /* USIA */
4b3686fa 2775 spr_set_rights(USIA, SPR_UR | SPR_UW);
9a64fbe4
FB
2776 }
2777 /* MPC755 has special registers */
2778 if (pvr == 0x00083100) {
2779 /* SPRG4 */
2780 spr_set_rights(SPRG4, SPR_SR | SPR_SW);
2781 /* SPRG5 */
2782 spr_set_rights(SPRG5, SPR_SR | SPR_SW);
2783 /* SPRG6 */
2784 spr_set_rights(SPRG6, SPR_SR | SPR_SW);
2785 /* SPRG7 */
2786 spr_set_rights(SPRG7, SPR_SR | SPR_SW);
2787 /* IBAT4U */
2788 spr_set_rights(IBAT4U, SPR_SR | SPR_SW);
2789 /* IBAT4L */
2790 spr_set_rights(IBAT4L, SPR_SR | SPR_SW);
2791 /* IBAT5U */
2792 spr_set_rights(IBAT5U, SPR_SR | SPR_SW);
2793 /* IBAT5L */
2794 spr_set_rights(IBAT5L, SPR_SR | SPR_SW);
2795 /* IBAT6U */
2796 spr_set_rights(IBAT6U, SPR_SR | SPR_SW);
2797 /* IBAT6L */
2798 spr_set_rights(IBAT6L, SPR_SR | SPR_SW);
2799 /* IBAT7U */
2800 spr_set_rights(IBAT7U, SPR_SR | SPR_SW);
2801 /* IBAT7L */
2802 spr_set_rights(IBAT7L, SPR_SR | SPR_SW);
2803 /* DBAT4U */
2804 spr_set_rights(DBAT4U, SPR_SR | SPR_SW);
2805 /* DBAT4L */
2806 spr_set_rights(DBAT4L, SPR_SR | SPR_SW);
2807 /* DBAT5U */
2808 spr_set_rights(DBAT5U, SPR_SR | SPR_SW);
2809 /* DBAT5L */
2810 spr_set_rights(DBAT5L, SPR_SR | SPR_SW);
2811 /* DBAT6U */
2812 spr_set_rights(DBAT6U, SPR_SR | SPR_SW);
2813 /* DBAT6L */
2814 spr_set_rights(DBAT6L, SPR_SR | SPR_SW);
2815 /* DBAT7U */
2816 spr_set_rights(DBAT7U, SPR_SR | SPR_SW);
2817 /* DBAT7L */
2818 spr_set_rights(DBAT7L, SPR_SR | SPR_SW);
2819 /* DMISS */
4b3686fa 2820 spr_set_rights(DMISS, SPR_SR | SPR_SW);
9a64fbe4 2821 /* DCMP */
4b3686fa 2822 spr_set_rights(DCMP, SPR_SR | SPR_SW);
9a64fbe4 2823 /* DHASH1 */
4b3686fa 2824 spr_set_rights(DHASH1, SPR_SR | SPR_SW);
9a64fbe4 2825 /* DHASH2 */
4b3686fa 2826 spr_set_rights(DHASH2, SPR_SR | SPR_SW);
9a64fbe4 2827 /* IMISS */
4b3686fa 2828 spr_set_rights(IMISS, SPR_SR | SPR_SW);
9a64fbe4 2829 /* ICMP */
4b3686fa 2830 spr_set_rights(ICMP, SPR_SR | SPR_SW);
9a64fbe4 2831 /* RPA */
4b3686fa 2832 spr_set_rights(RPA, SPR_SR | SPR_SW);
9a64fbe4 2833 /* HID2 */
4b3686fa 2834 spr_set_rights(HID2, SPR_SR | SPR_SW);
9a64fbe4 2835 /* L2PM */
4b3686fa 2836 spr_set_rights(L2PM, SPR_SR | SPR_SW);
9a64fbe4 2837 }
79aceca5
FB
2838}
2839
9a64fbe4
FB
2840/*****************************************************************************/
2841/* PPC "main stream" common instructions (no optional ones) */
79aceca5
FB
2842
2843typedef struct ppc_proc_t {
2844 int flags;
2845 void *specific;
2846} ppc_proc_t;
2847
2848typedef struct ppc_def_t {
2849 unsigned long pvr;
2850 unsigned long pvr_mask;
2851 ppc_proc_t *proc;
2852} ppc_def_t;
2853
2854static ppc_proc_t ppc_proc_common = {
2855 .flags = PPC_COMMON,
2856 .specific = NULL,
2857};
2858
9a64fbe4
FB
2859static ppc_proc_t ppc_proc_G3 = {
2860 .flags = PPC_750,
2861 .specific = NULL,
2862};
2863
79aceca5
FB
2864static ppc_def_t ppc_defs[] =
2865{
9a64fbe4
FB
2866 /* MPC740/745/750/755 (G3) */
2867 {
2868 .pvr = 0x00080000,
2869 .pvr_mask = 0xFFFF0000,
2870 .proc = &ppc_proc_G3,
2871 },
2872 /* IBM 750FX (G3 embedded) */
2873 {
2874 .pvr = 0x70000000,
2875 .pvr_mask = 0xFFFF0000,
2876 .proc = &ppc_proc_G3,
2877 },
2878 /* Fallback (generic PPC) */
79aceca5
FB
2879 {
2880 .pvr = 0x00000000,
2881 .pvr_mask = 0x00000000,
2882 .proc = &ppc_proc_common,
2883 },
2884};
2885
9a64fbe4 2886static int create_ppc_proc (opc_handler_t **ppc_opcodes, unsigned long pvr)
79aceca5
FB
2887{
2888 opcode_t *opc;
2889 int i, flags;
2890
2891 fill_new_table(ppc_opcodes, 0x40);
2892 for (i = 0; ; i++) {
2893 if ((ppc_defs[i].pvr & ppc_defs[i].pvr_mask) ==
2894 (pvr & ppc_defs[i].pvr_mask)) {
2895 flags = ppc_defs[i].proc->flags;
2896 break;
2897 }
2898 }
2899
2900 for (opc = &opc_start + 1; opc != &opc_end; opc++) {
9a64fbe4
FB
2901 if ((opc->handler.type & flags) != 0)
2902 if (register_insn(ppc_opcodes, opc) < 0) {
2903 printf("*** ERROR initializing PPC instruction "
79aceca5
FB
2904 "0x%02x 0x%02x 0x%02x\n", opc->opc1, opc->opc2,
2905 opc->opc3);
2906 return -1;
2907 }
2908 }
9a64fbe4 2909 fix_opcode_tables(ppc_opcodes);
79aceca5
FB
2910
2911 return 0;
2912}
2913
9a64fbe4 2914
79aceca5 2915/*****************************************************************************/
9a64fbe4 2916/* Misc PPC helpers */
79aceca5
FB
2917
2918void cpu_ppc_dump_state(CPUPPCState *env, FILE *f, int flags)
2919{
2920 int i;
2921
9a64fbe4
FB
2922 fprintf(f, "nip=0x%08x LR=0x%08x CTR=0x%08x XER=0x%08x "
2923 "MSR=0x%08x\n", env->nip, env->lr, env->ctr,
a541f297 2924 _load_xer(env), _load_msr(env));
79aceca5
FB
2925 for (i = 0; i < 32; i++) {
2926 if ((i & 7) == 0)
9a64fbe4
FB
2927 fprintf(f, "GPR%02d:", i);
2928 fprintf(f, " %08x", env->gpr[i]);
79aceca5 2929 if ((i & 7) == 7)
9a64fbe4 2930 fprintf(f, "\n");
79aceca5 2931 }
9a64fbe4 2932 fprintf(f, "CR: 0x");
79aceca5 2933 for (i = 0; i < 8; i++)
9a64fbe4
FB
2934 fprintf(f, "%01x", env->crf[i]);
2935 fprintf(f, " [");
79aceca5
FB
2936 for (i = 0; i < 8; i++) {
2937 char a = '-';
79aceca5
FB
2938 if (env->crf[i] & 0x08)
2939 a = 'L';
2940 else if (env->crf[i] & 0x04)
2941 a = 'G';
2942 else if (env->crf[i] & 0x02)
2943 a = 'E';
9a64fbe4 2944 fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
79aceca5 2945 }
9a64fbe4 2946 fprintf(f, " ] ");
9fddaa0c
FB
2947 fprintf(f, "TB: 0x%08x %08x\n", cpu_ppc_load_tbu(env),
2948 cpu_ppc_load_tbl(env));
79aceca5
FB
2949 for (i = 0; i < 16; i++) {
2950 if ((i & 3) == 0)
9a64fbe4
FB
2951 fprintf(f, "FPR%02d:", i);
2952 fprintf(f, " %016llx", *((uint64_t *)&env->fpr[i]));
79aceca5 2953 if ((i & 3) == 3)
9a64fbe4 2954 fprintf(f, "\n");
79aceca5 2955 }
9fddaa0c
FB
2956 fprintf(f, "SRR0 0x%08x SRR1 0x%08x DECR=0x%08x\n",
2957 env->spr[SRR0], env->spr[SRR1], cpu_ppc_load_decr(env));
9a64fbe4
FB
2958 fprintf(f, "reservation 0x%08x\n", env->reserve);
2959 fflush(f);
79aceca5
FB
2960}
2961
9a64fbe4
FB
2962#if !defined(CONFIG_USER_ONLY) && defined (USE_OPENFIRMWARE)
2963int setup_machine (CPUPPCState *env, uint32_t mid);
2964#endif
2965
79aceca5
FB
2966CPUPPCState *cpu_ppc_init(void)
2967{
2968 CPUPPCState *env;
2969
2970 cpu_exec_init();
2971
4b3686fa 2972 env = qemu_mallocz(sizeof(CPUPPCState));
79aceca5
FB
2973 if (!env)
2974 return NULL;
9a64fbe4
FB
2975#if !defined(CONFIG_USER_ONLY) && defined (USE_OPEN_FIRMWARE)
2976 setup_machine(env, 0);
2977#else
2978// env->spr[PVR] = 0; /* Basic PPC */
2979 env->spr[PVR] = 0x00080100; /* G3 CPU */
2980// env->spr[PVR] = 0x00083100; /* MPC755 (G3 embedded) */
2981// env->spr[PVR] = 0x00070100; /* IBM 750FX */
2982#endif
ad081323 2983 tlb_flush(env, 1);
9a64fbe4
FB
2984#if defined (DO_SINGLE_STEP)
2985 /* Single step trace mode */
2986 msr_se = 1;
2987#endif
4b3686fa
FB
2988 msr_fp = 1; /* Allow floating point exceptions */
2989 msr_me = 1; /* Allow machine check exceptions */
9a64fbe4
FB
2990#if defined(CONFIG_USER_ONLY)
2991 msr_pr = 1;
4b3686fa
FB
2992 cpu_ppc_register(env, 0x00080000);
2993#else
2994 env->nip = 0xFFFFFFFC;
9a64fbe4 2995#endif
a541f297 2996 env->access_type = ACCESS_INT;
79aceca5
FB
2997
2998 return env;
2999}
3000
4b3686fa
FB
3001int cpu_ppc_register (CPUPPCState *env, uint32_t pvr)
3002{
3003 env->spr[PVR] = pvr;
3004 if (create_ppc_proc(ppc_opcodes, env->spr[PVR]) < 0)
3005 return -1;
3006 init_spr_rights(env->spr[PVR]);
3007
3008 return 0;
3009}
3010
79aceca5
FB
3011void cpu_ppc_close(CPUPPCState *env)
3012{
3013 /* Should also remove all opcode tables... */
3014 free(env);
3015}
3016
9a64fbe4 3017/*****************************************************************************/
9a64fbe4
FB
3018int print_insn_powerpc (FILE *out, unsigned long insn, unsigned memaddr,
3019 int dialect);
3020
79aceca5
FB
3021int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
3022 int search_pc)
3023{
9fddaa0c 3024 DisasContext ctx, *ctxp = &ctx;
79aceca5
FB
3025 opc_handler_t **table, *handler;
3026 uint32_t pc_start;
3027 uint16_t *gen_opc_end;
3028 int j, lj = -1;
79aceca5
FB
3029
3030 pc_start = tb->pc;
3031 gen_opc_ptr = gen_opc_buf;
3032 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
3033 gen_opparam_ptr = gen_opparam_buf;
046d6672 3034 ctx.nip = pc_start;
79aceca5 3035 ctx.tb = tb;
9a64fbe4
FB
3036 ctx.exception = EXCP_NONE;
3037#if defined(CONFIG_USER_ONLY)
3038 ctx.mem_idx = 0;
3039#else
3040 ctx.supervisor = 1 - msr_pr;
3041 ctx.mem_idx = (1 - msr_pr);
3042#endif
3043#if defined (DO_SINGLE_STEP)
3044 /* Single step trace mode */
3045 msr_se = 1;
3046#endif
a541f297 3047 env->access_type = ACCESS_CODE;
9a64fbe4
FB
3048 /* Set env in case of segfault during code fetch */
3049 while (ctx.exception == EXCP_NONE && gen_opc_ptr < gen_opc_end) {
79aceca5
FB
3050 if (search_pc) {
3051 if (loglevel > 0)
3052 fprintf(logfile, "Search PC...\n");
3053 j = gen_opc_ptr - gen_opc_buf;
3054 if (lj < j) {
3055 lj++;
3056 while (lj < j)
3057 gen_opc_instr_start[lj++] = 0;
046d6672 3058 gen_opc_pc[lj] = ctx.nip;
79aceca5
FB
3059 gen_opc_instr_start[lj] = 1;
3060 }
3061 }
9fddaa0c
FB
3062#if defined PPC_DEBUG_DISAS
3063 if (loglevel & CPU_LOG_TB_IN_ASM) {
79aceca5 3064 fprintf(logfile, "----------------\n");
046d6672 3065 fprintf(logfile, "nip=%08x super=%d ir=%d\n",
9a64fbe4
FB
3066 ctx.nip, 1 - msr_pr, msr_ir);
3067 }
3068#endif
046d6672 3069 ctx.opcode = ldl_code((void *)ctx.nip);
9fddaa0c
FB
3070#if defined PPC_DEBUG_DISAS
3071 if (loglevel & CPU_LOG_TB_IN_ASM) {
9a64fbe4
FB
3072 fprintf(logfile, "translate opcode %08x (%02x %02x %02x)\n",
3073 ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
3074 opc3(ctx.opcode));
79aceca5
FB
3075 }
3076#endif
046d6672 3077 ctx.nip += 4;
79aceca5
FB
3078 table = ppc_opcodes;
3079 handler = table[opc1(ctx.opcode)];
3080 if (is_indirect_opcode(handler)) {
3081 table = ind_table(handler);
3082 handler = table[opc2(ctx.opcode)];
3083 if (is_indirect_opcode(handler)) {
3084 table = ind_table(handler);
3085 handler = table[opc3(ctx.opcode)];
3086 }
3087 }
3088 /* Is opcode *REALLY* valid ? */
79aceca5 3089 if (handler->handler == &gen_invalid) {
4b3686fa 3090 if (loglevel > 0) {
79aceca5 3091 fprintf(logfile, "invalid/unsupported opcode: "
4b3686fa 3092 "%02x - %02x - %02x (%08x) 0x%08x %d\n",
9a64fbe4 3093 opc1(ctx.opcode), opc2(ctx.opcode),
4b3686fa
FB
3094 opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, msr_ir);
3095 } else {
3096 printf("invalid/unsupported opcode: "
3097 "%02x - %02x - %02x (%08x) 0x%08x %d\n",
3098 opc1(ctx.opcode), opc2(ctx.opcode),
3099 opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, msr_ir);
3100 }
79aceca5 3101 } else {
4b3686fa
FB
3102 if ((ctx.opcode & handler->inval) != 0) {
3103 if (loglevel > 0) {
79aceca5 3104 fprintf(logfile, "invalid bits: %08x for opcode: "
046d6672 3105 "%02x -%02x - %02x (0x%08x) (0x%08x)\n",
79aceca5
FB
3106 ctx.opcode & handler->inval, opc1(ctx.opcode),
3107 opc2(ctx.opcode), opc3(ctx.opcode),
046d6672 3108 ctx.opcode, ctx.nip - 4);
9a64fbe4
FB
3109 } else {
3110 printf("invalid bits: %08x for opcode: "
046d6672 3111 "%02x -%02x - %02x (0x%08x) (0x%08x)\n",
9a64fbe4
FB
3112 ctx.opcode & handler->inval, opc1(ctx.opcode),
3113 opc2(ctx.opcode), opc3(ctx.opcode),
046d6672 3114 ctx.opcode, ctx.nip - 4);
9a64fbe4 3115 }
4b3686fa
FB
3116 RET_INVAL(ctxp);
3117 break;
79aceca5 3118 }
79aceca5 3119 }
4b3686fa 3120 (*(handler->handler))(&ctx);
9a64fbe4
FB
3121 /* Check trace mode exceptions */
3122 if ((msr_be && ctx.exception == EXCP_BRANCH) ||
3123 /* Check in single step trace mode
3124 * we need to stop except if:
3125 * - rfi, trap or syscall
3126 * - first instruction of an exception handler
3127 */
046d6672
FB
3128 (msr_se && (ctx.nip < 0x100 ||
3129 ctx.nip > 0xF00 ||
3130 (ctx.nip & 0xFC) != 0x04) &&
9a64fbe4
FB
3131 ctx.exception != EXCP_SYSCALL && ctx.exception != EXCP_RFI &&
3132 ctx.exception != EXCP_TRAP)) {
9fddaa0c 3133 RET_EXCP(ctxp, EXCP_TRACE, 0);
9a64fbe4 3134 }
a541f297 3135 /* if we reach a page boundary, stop generation */
046d6672 3136 if ((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) {
9fddaa0c 3137 RET_EXCP(ctxp, EXCP_BRANCH, 0);
79aceca5 3138 }
9a64fbe4 3139 }
9fddaa0c
FB
3140 if (ctx.exception == EXCP_NONE) {
3141 gen_op_b((unsigned long)ctx.tb, ctx.nip);
3142 } else if (ctx.exception != EXCP_BRANCH) {
3143 gen_op_set_T0(0);
9a64fbe4
FB
3144 }
3145#if 1
79aceca5
FB
3146 /* TO BE FIXED: T0 hasn't got a proper value, which makes tb_add_jump
3147 * do bad business and then qemu crashes !
3148 */
3149 gen_op_set_T0(0);
9a64fbe4 3150#endif
79aceca5
FB
3151 /* Generate the return instruction */
3152 gen_op_exit_tb();
3153 *gen_opc_ptr = INDEX_op_end;
9a64fbe4
FB
3154 if (search_pc) {
3155 j = gen_opc_ptr - gen_opc_buf;
3156 lj++;
3157 while (lj <= j)
3158 gen_opc_instr_start[lj++] = 0;
79aceca5 3159 tb->size = 0;
985a19d6 3160#if 0
9a64fbe4
FB
3161 if (loglevel > 0) {
3162 page_dump(logfile);
3163 }
985a19d6 3164#endif
9a64fbe4 3165 } else {
046d6672 3166 tb->size = ctx.nip - pc_start;
9a64fbe4 3167 }
79aceca5 3168#ifdef DEBUG_DISAS
9fddaa0c 3169 if (loglevel & CPU_LOG_TB_CPU) {
9a64fbe4
FB
3170 fprintf(logfile, "---------------- excp: %04x\n", ctx.exception);
3171 cpu_ppc_dump_state(env, logfile, 0);
9fddaa0c
FB
3172 }
3173 if (loglevel & CPU_LOG_TB_IN_ASM) {
79aceca5 3174 fprintf(logfile, "IN: %s\n", lookup_symbol((void *)pc_start));
046d6672 3175 disas(logfile, (void *)pc_start, ctx.nip - pc_start, 0, 0);
79aceca5 3176 fprintf(logfile, "\n");
9fddaa0c
FB
3177 }
3178 if (loglevel & CPU_LOG_TB_OP) {
79aceca5
FB
3179 fprintf(logfile, "OP:\n");
3180 dump_ops(gen_opc_buf, gen_opparam_buf);
3181 fprintf(logfile, "\n");
3182 }
3183#endif
4b3686fa 3184 env->access_type = ACCESS_INT;
79aceca5
FB
3185
3186 return 0;
3187}
3188
9a64fbe4 3189int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
79aceca5
FB
3190{
3191 return gen_intermediate_code_internal(env, tb, 0);
3192}
3193
9a64fbe4 3194int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
79aceca5
FB
3195{
3196 return gen_intermediate_code_internal(env, tb, 1);
3197}