halt state support for ppc
[qemu] / target-ppc / translate.c
1 /*
2  *  PowerPC emulation for qemu: main translation routines.
3  * 
4  *  Copyright (c) 2003-2005 Jocelyn Mayer
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 #include <stdarg.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <inttypes.h>
25
26 #include "cpu.h"
27 #include "exec-all.h"
28 #include "disas.h"
29
30 //#define DO_SINGLE_STEP
31 //#define PPC_DEBUG_DISAS
32
33 #ifdef USE_DIRECT_JUMP
34 #define TBPARAM(x)
35 #else
36 #define TBPARAM(x) (long)(x)
37 #endif
38
39 enum {
40 #define DEF(s, n, copy_size) INDEX_op_ ## s,
41 #include "opc.h"
42 #undef DEF
43     NB_OPS,
44 };
45
46 static uint16_t *gen_opc_ptr;
47 static uint32_t *gen_opparam_ptr;
48
49 #include "gen-op.h"
50
51 #define GEN8(func, NAME) \
52 static GenOpFunc *NAME ## _table [8] = {                                      \
53 NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3,                                   \
54 NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7,                                   \
55 };                                                                            \
56 static inline void func(int n)                                                \
57 {                                                                             \
58     NAME ## _table[n]();                                                      \
59 }
60
61 #define GEN16(func, NAME)                                                     \
62 static GenOpFunc *NAME ## _table [16] = {                                     \
63 NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3,                                   \
64 NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7,                                   \
65 NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11,                                 \
66 NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
67 };                                                                            \
68 static inline void func(int n)                                                \
69 {                                                                             \
70     NAME ## _table[n]();                                                      \
71 }
72
73 #define GEN32(func, NAME) \
74 static GenOpFunc *NAME ## _table [32] = {                                     \
75 NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3,                                   \
76 NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7,                                   \
77 NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11,                                 \
78 NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
79 NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,                               \
80 NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,                               \
81 NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,                               \
82 NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,                               \
83 };                                                                            \
84 static inline void func(int n)                                                \
85 {                                                                             \
86     NAME ## _table[n]();                                                      \
87 }
88
89 /* Condition register moves */
90 GEN8(gen_op_load_crf_T0, gen_op_load_crf_T0_crf);
91 GEN8(gen_op_load_crf_T1, gen_op_load_crf_T1_crf);
92 GEN8(gen_op_store_T0_crf, gen_op_store_T0_crf_crf);
93 GEN8(gen_op_store_T1_crf, gen_op_store_T1_crf_crf);
94
95 /* Floating point condition and status register moves */
96 GEN8(gen_op_load_fpscr_T0, gen_op_load_fpscr_T0_fpscr);
97 GEN8(gen_op_store_T0_fpscr, gen_op_store_T0_fpscr_fpscr);
98 GEN8(gen_op_clear_fpscr, gen_op_clear_fpscr_fpscr);
99 static GenOpFunc1 *gen_op_store_T0_fpscri_fpscr_table[8] = {
100     &gen_op_store_T0_fpscri_fpscr0,
101     &gen_op_store_T0_fpscri_fpscr1,
102     &gen_op_store_T0_fpscri_fpscr2,
103     &gen_op_store_T0_fpscri_fpscr3,
104     &gen_op_store_T0_fpscri_fpscr4,
105     &gen_op_store_T0_fpscri_fpscr5,
106     &gen_op_store_T0_fpscri_fpscr6,
107     &gen_op_store_T0_fpscri_fpscr7,
108 };
109 static inline void gen_op_store_T0_fpscri(int n, uint8_t param)
110 {
111     (*gen_op_store_T0_fpscri_fpscr_table[n])(param);
112 }
113
114 /* Segment register moves */
115 GEN16(gen_op_load_sr, gen_op_load_sr);
116 GEN16(gen_op_store_sr, gen_op_store_sr);
117
118 /* General purpose registers moves */
119 GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr);
120 GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr);
121 GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr);
122
123 GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr);
124 GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr);
125 GEN32(gen_op_store_T2_gpr, gen_op_store_T2_gpr_gpr);
126
127 /* floating point registers moves */
128 GEN32(gen_op_load_fpr_FT0, gen_op_load_fpr_FT0_fpr);
129 GEN32(gen_op_load_fpr_FT1, gen_op_load_fpr_FT1_fpr);
130 GEN32(gen_op_load_fpr_FT2, gen_op_load_fpr_FT2_fpr);
131 GEN32(gen_op_store_FT0_fpr, gen_op_store_FT0_fpr_fpr);
132 GEN32(gen_op_store_FT1_fpr, gen_op_store_FT1_fpr_fpr);
133 GEN32(gen_op_store_FT2_fpr, gen_op_store_FT2_fpr_fpr);
134
135 static uint8_t  spr_access[1024 / 2];
136
137 /* internal defines */
138 typedef struct DisasContext {
139     struct TranslationBlock *tb;
140     target_ulong nip;
141     uint32_t opcode;
142     uint32_t exception;
143     /* Routine used to access memory */
144     int mem_idx;
145     /* Translation flags */
146 #if !defined(CONFIG_USER_ONLY)
147     int supervisor;
148 #endif
149     int fpu_enabled;
150     ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */
151 } DisasContext;
152
153 struct opc_handler_t {
154     /* invalid bits */
155     uint32_t inval;
156     /* instruction type */
157     uint32_t type;
158     /* handler */
159     void (*handler)(DisasContext *ctx);
160 };
161
162 #define RET_EXCP(ctx, excp, error)                                            \
163 do {                                                                          \
164     if ((ctx)->exception == EXCP_NONE) {                                      \
165         gen_op_update_nip((ctx)->nip);                                        \
166     }                                                                         \
167     gen_op_raise_exception_err((excp), (error));                              \
168     ctx->exception = (excp);                                                  \
169 } while (0)
170
171 #define RET_INVAL(ctx)                                                        \
172 RET_EXCP((ctx), EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL)
173
174 #define RET_PRIVOPC(ctx)                                                      \
175 RET_EXCP((ctx), EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_OPC)
176
177 #define RET_PRIVREG(ctx)                                                      \
178 RET_EXCP((ctx), EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG)
179
180 /* Stop translation */
181 static inline void RET_STOP (DisasContext *ctx)
182 {
183     gen_op_update_nip((ctx)->nip);
184     ctx->exception = EXCP_MTMSR;
185 }
186
187 /* No need to update nip here, as execution flow will change */
188 static inline void RET_CHG_FLOW (DisasContext *ctx)
189 {
190     ctx->exception = EXCP_MTMSR;
191 }
192
193 #define GEN_HANDLER(name, opc1, opc2, opc3, inval, type)                      \
194 static void gen_##name (DisasContext *ctx);                                   \
195 GEN_OPCODE(name, opc1, opc2, opc3, inval, type);                              \
196 static void gen_##name (DisasContext *ctx)
197
198 typedef struct opcode_t {
199     unsigned char opc1, opc2, opc3;
200 #if HOST_LONG_BITS == 64 /* Explicitely align to 64 bits */
201     unsigned char pad[5];
202 #else
203     unsigned char pad[1];
204 #endif
205     opc_handler_t handler;
206     const unsigned char *oname;
207 } opcode_t;
208
209 /***                           Instruction decoding                        ***/
210 #define EXTRACT_HELPER(name, shift, nb)                                       \
211 static inline uint32_t name (uint32_t opcode)                                 \
212 {                                                                             \
213     return (opcode >> (shift)) & ((1 << (nb)) - 1);                           \
214 }
215
216 #define EXTRACT_SHELPER(name, shift, nb)                                      \
217 static inline int32_t name (uint32_t opcode)                                  \
218 {                                                                             \
219     return (int16_t)((opcode >> (shift)) & ((1 << (nb)) - 1));                \
220 }
221
222 /* Opcode part 1 */
223 EXTRACT_HELPER(opc1, 26, 6);
224 /* Opcode part 2 */
225 EXTRACT_HELPER(opc2, 1, 5);
226 /* Opcode part 3 */
227 EXTRACT_HELPER(opc3, 6, 5);
228 /* Update Cr0 flags */
229 EXTRACT_HELPER(Rc, 0, 1);
230 /* Destination */
231 EXTRACT_HELPER(rD, 21, 5);
232 /* Source */
233 EXTRACT_HELPER(rS, 21, 5);
234 /* First operand */
235 EXTRACT_HELPER(rA, 16, 5);
236 /* Second operand */
237 EXTRACT_HELPER(rB, 11, 5);
238 /* Third operand */
239 EXTRACT_HELPER(rC, 6, 5);
240 /***                               Get CRn                                 ***/
241 EXTRACT_HELPER(crfD, 23, 3);
242 EXTRACT_HELPER(crfS, 18, 3);
243 EXTRACT_HELPER(crbD, 21, 5);
244 EXTRACT_HELPER(crbA, 16, 5);
245 EXTRACT_HELPER(crbB, 11, 5);
246 /* SPR / TBL */
247 EXTRACT_HELPER(_SPR, 11, 10);
248 static inline uint32_t SPR (uint32_t opcode)
249 {
250     uint32_t sprn = _SPR(opcode);
251
252     return ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
253 }
254 /***                              Get constants                            ***/
255 EXTRACT_HELPER(IMM, 12, 8);
256 /* 16 bits signed immediate value */
257 EXTRACT_SHELPER(SIMM, 0, 16);
258 /* 16 bits unsigned immediate value */
259 EXTRACT_HELPER(UIMM, 0, 16);
260 /* Bit count */
261 EXTRACT_HELPER(NB, 11, 5);
262 /* Shift count */
263 EXTRACT_HELPER(SH, 11, 5);
264 /* Mask start */
265 EXTRACT_HELPER(MB, 6, 5);
266 /* Mask end */
267 EXTRACT_HELPER(ME, 1, 5);
268 /* Trap operand */
269 EXTRACT_HELPER(TO, 21, 5);
270
271 EXTRACT_HELPER(CRM, 12, 8);
272 EXTRACT_HELPER(FM, 17, 8);
273 EXTRACT_HELPER(SR, 16, 4);
274 EXTRACT_HELPER(FPIMM, 20, 4);
275
276 /***                            Jump target decoding                       ***/
277 /* Displacement */
278 EXTRACT_SHELPER(d, 0, 16);
279 /* Immediate address */
280 static inline uint32_t LI (uint32_t opcode)
281 {
282     return (opcode >> 0) & 0x03FFFFFC;
283 }
284
285 static inline uint32_t BD (uint32_t opcode)
286 {
287     return (opcode >> 0) & 0xFFFC;
288 }
289
290 EXTRACT_HELPER(BO, 21, 5);
291 EXTRACT_HELPER(BI, 16, 5);
292 /* Absolute/relative address */
293 EXTRACT_HELPER(AA, 1, 1);
294 /* Link */
295 EXTRACT_HELPER(LK, 0, 1);
296
297 /* Create a mask between <start> and <end> bits */
298 static inline uint32_t MASK (uint32_t start, uint32_t end)
299 {
300     uint32_t ret;
301
302     ret = (((uint32_t)(-1)) >> (start)) ^ (((uint32_t)(-1) >> (end)) >> 1);
303     if (start > end)
304         return ~ret;
305
306     return ret;
307 }
308
309 #if HOST_LONG_BITS == 64
310 #define OPC_ALIGN 8
311 #else
312 #define OPC_ALIGN 4
313 #endif
314 #if defined(__APPLE__)
315 #define OPCODES_SECTION \
316     __attribute__ ((section("__TEXT,__opcodes"), unused, aligned (OPC_ALIGN) ))
317 #else
318 #define OPCODES_SECTION \
319     __attribute__ ((section(".opcodes"), unused, aligned (OPC_ALIGN) ))
320 #endif
321
322 #define GEN_OPCODE(name, op1, op2, op3, invl, _typ)                           \
323 OPCODES_SECTION opcode_t opc_##name = {                                       \
324     .opc1 = op1,                                                              \
325     .opc2 = op2,                                                              \
326     .opc3 = op3,                                                              \
327     .pad  = { 0, },                                                           \
328     .handler = {                                                              \
329         .inval   = invl,                                                      \
330         .type = _typ,                                                         \
331         .handler = &gen_##name,                                               \
332     },                                                                        \
333     .oname = stringify(name),                                                 \
334 }
335
336 #define GEN_OPCODE_MARK(name)                                                 \
337 OPCODES_SECTION opcode_t opc_##name = {                                       \
338     .opc1 = 0xFF,                                                             \
339     .opc2 = 0xFF,                                                             \
340     .opc3 = 0xFF,                                                             \
341     .pad  = { 0, },                                                           \
342     .handler = {                                                              \
343         .inval   = 0x00000000,                                                \
344         .type = 0x00,                                                         \
345         .handler = NULL,                                                      \
346     },                                                                        \
347     .oname = stringify(name),                                                 \
348 }
349
350 /* Start opcode list */
351 GEN_OPCODE_MARK(start);
352
353 /* Invalid instruction */
354 GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE)
355 {
356     RET_INVAL(ctx);
357 }
358
359 static opc_handler_t invalid_handler = {
360     .inval   = 0xFFFFFFFF,
361     .type    = PPC_NONE,
362     .handler = gen_invalid,
363 };
364
365 /***                           Integer arithmetic                          ***/
366 #define __GEN_INT_ARITH2(name, opc1, opc2, opc3, inval)                       \
367 GEN_HANDLER(name, opc1, opc2, opc3, inval, PPC_INTEGER)                       \
368 {                                                                             \
369     gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
370     gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
371     gen_op_##name();                                                          \
372     if (Rc(ctx->opcode) != 0)                                                 \
373         gen_op_set_Rc0();                                                     \
374     gen_op_store_T0_gpr(rD(ctx->opcode));                                     \
375 }
376
377 #define __GEN_INT_ARITH2_O(name, opc1, opc2, opc3, inval)                     \
378 GEN_HANDLER(name, opc1, opc2, opc3, inval, PPC_INTEGER)                       \
379 {                                                                             \
380     gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
381     gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
382     gen_op_##name();                                                          \
383     if (Rc(ctx->opcode) != 0)                                                 \
384         gen_op_set_Rc0();                                                     \
385     gen_op_store_T0_gpr(rD(ctx->opcode));                                     \
386 }
387
388 #define __GEN_INT_ARITH1(name, opc1, opc2, opc3)                              \
389 GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, PPC_INTEGER)                  \
390 {                                                                             \
391     gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
392     gen_op_##name();                                                          \
393     if (Rc(ctx->opcode) != 0)                                                 \
394         gen_op_set_Rc0();                                                     \
395     gen_op_store_T0_gpr(rD(ctx->opcode));                                     \
396 }
397 #define __GEN_INT_ARITH1_O(name, opc1, opc2, opc3)                            \
398 GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, PPC_INTEGER)                  \
399 {                                                                             \
400     gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
401     gen_op_##name();                                                          \
402     if (Rc(ctx->opcode) != 0)                                                 \
403         gen_op_set_Rc0();                                                     \
404     gen_op_store_T0_gpr(rD(ctx->opcode));                                     \
405 }
406
407 /* Two operands arithmetic functions */
408 #define GEN_INT_ARITH2(name, opc1, opc2, opc3)                                \
409 __GEN_INT_ARITH2(name, opc1, opc2, opc3, 0x00000000)                          \
410 __GEN_INT_ARITH2_O(name##o, opc1, opc2, opc3 | 0x10, 0x00000000)
411
412 /* Two operands arithmetic functions with no overflow allowed */
413 #define GEN_INT_ARITHN(name, opc1, opc2, opc3)                                \
414 __GEN_INT_ARITH2(name, opc1, opc2, opc3, 0x00000400)
415
416 /* One operand arithmetic functions */
417 #define GEN_INT_ARITH1(name, opc1, opc2, opc3)                                \
418 __GEN_INT_ARITH1(name, opc1, opc2, opc3)                                      \
419 __GEN_INT_ARITH1_O(name##o, opc1, opc2, opc3 | 0x10)
420
421 /* add    add.    addo    addo.    */
422 GEN_INT_ARITH2 (add,    0x1F, 0x0A, 0x08);
423 /* addc   addc.   addco   addco.   */
424 GEN_INT_ARITH2 (addc,   0x1F, 0x0A, 0x00);
425 /* adde   adde.   addeo   addeo.   */
426 GEN_INT_ARITH2 (adde,   0x1F, 0x0A, 0x04);
427 /* addme  addme.  addmeo  addmeo.  */
428 GEN_INT_ARITH1 (addme,  0x1F, 0x0A, 0x07);
429 /* addze  addze.  addzeo  addzeo.  */
430 GEN_INT_ARITH1 (addze,  0x1F, 0x0A, 0x06);
431 /* divw   divw.   divwo   divwo.   */
432 GEN_INT_ARITH2 (divw,   0x1F, 0x0B, 0x0F);
433 /* divwu  divwu.  divwuo  divwuo.  */
434 GEN_INT_ARITH2 (divwu,  0x1F, 0x0B, 0x0E);
435 /* mulhw  mulhw.                   */
436 GEN_INT_ARITHN (mulhw,  0x1F, 0x0B, 0x02);
437 /* mulhwu mulhwu.                  */
438 GEN_INT_ARITHN (mulhwu, 0x1F, 0x0B, 0x00);
439 /* mullw  mullw.  mullwo  mullwo.  */
440 GEN_INT_ARITH2 (mullw,  0x1F, 0x0B, 0x07);
441 /* neg    neg.    nego    nego.    */
442 GEN_INT_ARITH1 (neg,    0x1F, 0x08, 0x03);
443 /* subf   subf.   subfo   subfo.   */
444 GEN_INT_ARITH2 (subf,   0x1F, 0x08, 0x01);
445 /* subfc  subfc.  subfco  subfco.  */
446 GEN_INT_ARITH2 (subfc,  0x1F, 0x08, 0x00);
447 /* subfe  subfe.  subfeo  subfeo.  */
448 GEN_INT_ARITH2 (subfe,  0x1F, 0x08, 0x04);
449 /* subfme subfme. subfmeo subfmeo. */
450 GEN_INT_ARITH1 (subfme, 0x1F, 0x08, 0x07);
451 /* subfze subfze. subfzeo subfzeo. */
452 GEN_INT_ARITH1 (subfze, 0x1F, 0x08, 0x06);
453 /* addi */
454 GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
455 {
456     int32_t simm = SIMM(ctx->opcode);
457
458     if (rA(ctx->opcode) == 0) {
459         gen_op_set_T0(simm);
460     } else {
461         gen_op_load_gpr_T0(rA(ctx->opcode));
462         gen_op_addi(simm);
463     }
464     gen_op_store_T0_gpr(rD(ctx->opcode));
465 }
466 /* addic */
467 GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
468 {
469     gen_op_load_gpr_T0(rA(ctx->opcode));
470     gen_op_addic(SIMM(ctx->opcode));
471     gen_op_store_T0_gpr(rD(ctx->opcode));
472 }
473 /* addic. */
474 GEN_HANDLER(addic_, 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
475 {
476     gen_op_load_gpr_T0(rA(ctx->opcode));
477     gen_op_addic(SIMM(ctx->opcode));
478     gen_op_set_Rc0();
479     gen_op_store_T0_gpr(rD(ctx->opcode));
480 }
481 /* addis */
482 GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
483 {
484     int32_t simm = SIMM(ctx->opcode);
485
486     if (rA(ctx->opcode) == 0) {
487         gen_op_set_T0(simm << 16);
488     } else {
489         gen_op_load_gpr_T0(rA(ctx->opcode));
490         gen_op_addi(simm << 16);
491     }
492     gen_op_store_T0_gpr(rD(ctx->opcode));
493 }
494 /* mulli */
495 GEN_HANDLER(mulli, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
496 {
497     gen_op_load_gpr_T0(rA(ctx->opcode));
498     gen_op_mulli(SIMM(ctx->opcode));
499     gen_op_store_T0_gpr(rD(ctx->opcode));
500 }
501 /* subfic */
502 GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
503 {
504     gen_op_load_gpr_T0(rA(ctx->opcode));
505     gen_op_subfic(SIMM(ctx->opcode));
506     gen_op_store_T0_gpr(rD(ctx->opcode));
507 }
508
509 /***                           Integer comparison                          ***/
510 #define GEN_CMP(name, opc)                                                    \
511 GEN_HANDLER(name, 0x1F, 0x00, opc, 0x00400000, PPC_INTEGER)                   \
512 {                                                                             \
513     gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
514     gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
515     gen_op_##name();                                                          \
516     gen_op_store_T0_crf(crfD(ctx->opcode));                                   \
517 }
518
519 /* cmp */
520 GEN_CMP(cmp, 0x00);
521 /* cmpi */
522 GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
523 {
524     gen_op_load_gpr_T0(rA(ctx->opcode));
525     gen_op_cmpi(SIMM(ctx->opcode));
526     gen_op_store_T0_crf(crfD(ctx->opcode));
527 }
528 /* cmpl */
529 GEN_CMP(cmpl, 0x01);
530 /* cmpli */
531 GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
532 {
533     gen_op_load_gpr_T0(rA(ctx->opcode));
534     gen_op_cmpli(UIMM(ctx->opcode));
535     gen_op_store_T0_crf(crfD(ctx->opcode));
536 }
537
538 /***                            Integer logical                            ***/
539 #define __GEN_LOGICAL2(name, opc2, opc3)                                      \
540 GEN_HANDLER(name, 0x1F, opc2, opc3, 0x00000000, PPC_INTEGER)                  \
541 {                                                                             \
542     gen_op_load_gpr_T0(rS(ctx->opcode));                                      \
543     gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
544     gen_op_##name();                                                          \
545     if (Rc(ctx->opcode) != 0)                                                 \
546         gen_op_set_Rc0();                                                     \
547     gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
548 }
549 #define GEN_LOGICAL2(name, opc)                                               \
550 __GEN_LOGICAL2(name, 0x1C, opc)
551
552 #define GEN_LOGICAL1(name, opc)                                               \
553 GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, PPC_INTEGER)                   \
554 {                                                                             \
555     gen_op_load_gpr_T0(rS(ctx->opcode));                                      \
556     gen_op_##name();                                                          \
557     if (Rc(ctx->opcode) != 0)                                                 \
558         gen_op_set_Rc0();                                                     \
559     gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
560 }
561
562 /* and & and. */
563 GEN_LOGICAL2(and, 0x00);
564 /* andc & andc. */
565 GEN_LOGICAL2(andc, 0x01);
566 /* andi. */
567 GEN_HANDLER(andi_, 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
568 {
569     gen_op_load_gpr_T0(rS(ctx->opcode));
570     gen_op_andi_(UIMM(ctx->opcode));
571     gen_op_set_Rc0();
572     gen_op_store_T0_gpr(rA(ctx->opcode));
573 }
574 /* andis. */
575 GEN_HANDLER(andis_, 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
576 {
577     gen_op_load_gpr_T0(rS(ctx->opcode));
578     gen_op_andi_(UIMM(ctx->opcode) << 16);
579     gen_op_set_Rc0();
580     gen_op_store_T0_gpr(rA(ctx->opcode));
581 }
582
583 /* cntlzw */
584 GEN_LOGICAL1(cntlzw, 0x00);
585 /* eqv & eqv. */
586 GEN_LOGICAL2(eqv, 0x08);
587 /* extsb & extsb. */
588 GEN_LOGICAL1(extsb, 0x1D);
589 /* extsh & extsh. */
590 GEN_LOGICAL1(extsh, 0x1C);
591 /* nand & nand. */
592 GEN_LOGICAL2(nand, 0x0E);
593 /* nor & nor. */
594 GEN_LOGICAL2(nor, 0x03);
595
596 /* or & or. */
597 GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER)
598 {
599     gen_op_load_gpr_T0(rS(ctx->opcode));
600     /* Optimisation for mr case */
601     if (rS(ctx->opcode) != rB(ctx->opcode)) {
602         gen_op_load_gpr_T1(rB(ctx->opcode));
603         gen_op_or();
604     }
605     if (Rc(ctx->opcode) != 0)
606         gen_op_set_Rc0();
607     gen_op_store_T0_gpr(rA(ctx->opcode));
608 }
609
610 /* orc & orc. */
611 GEN_LOGICAL2(orc, 0x0C);
612 /* xor & xor. */
613 GEN_HANDLER(xor, 0x1F, 0x1C, 0x09, 0x00000000, PPC_INTEGER)
614 {
615     gen_op_load_gpr_T0(rS(ctx->opcode));
616     /* Optimisation for "set to zero" case */
617     if (rS(ctx->opcode) != rB(ctx->opcode)) {
618         gen_op_load_gpr_T1(rB(ctx->opcode));
619         gen_op_xor();
620     } else {
621         gen_op_set_T0(0);
622     }
623     if (Rc(ctx->opcode) != 0)
624         gen_op_set_Rc0();
625     gen_op_store_T0_gpr(rA(ctx->opcode));
626 }
627 /* ori */
628 GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
629 {
630     uint32_t uimm = UIMM(ctx->opcode);
631
632     if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
633         /* NOP */
634         return;
635         }
636         gen_op_load_gpr_T0(rS(ctx->opcode));
637     if (uimm != 0)
638         gen_op_ori(uimm);
639         gen_op_store_T0_gpr(rA(ctx->opcode));
640 }
641 /* oris */
642 GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
643 {
644     uint32_t uimm = UIMM(ctx->opcode);
645
646     if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
647         /* NOP */
648         return;
649         }
650         gen_op_load_gpr_T0(rS(ctx->opcode));
651     if (uimm != 0)
652         gen_op_ori(uimm << 16);
653         gen_op_store_T0_gpr(rA(ctx->opcode));
654 }
655 /* xori */
656 GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
657 {
658     uint32_t uimm = UIMM(ctx->opcode);
659
660     if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
661         /* NOP */
662         return;
663     }
664     gen_op_load_gpr_T0(rS(ctx->opcode));
665     if (uimm != 0)
666     gen_op_xori(uimm);
667     gen_op_store_T0_gpr(rA(ctx->opcode));
668 }
669
670 /* xoris */
671 GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
672 {
673     uint32_t uimm = UIMM(ctx->opcode);
674
675     if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
676         /* NOP */
677         return;
678     }
679     gen_op_load_gpr_T0(rS(ctx->opcode));
680     if (uimm != 0)
681     gen_op_xori(uimm << 16);
682     gen_op_store_T0_gpr(rA(ctx->opcode));
683 }
684
685 /***                             Integer rotate                            ***/
686 /* rlwimi & rlwimi. */
687 GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
688 {
689     uint32_t mb, me;
690
691     mb = MB(ctx->opcode);
692     me = ME(ctx->opcode);
693     gen_op_load_gpr_T0(rS(ctx->opcode));
694     gen_op_load_gpr_T1(rA(ctx->opcode));
695     gen_op_rlwimi(SH(ctx->opcode), MASK(mb, me), ~MASK(mb, me));
696     if (Rc(ctx->opcode) != 0)
697         gen_op_set_Rc0();
698     gen_op_store_T0_gpr(rA(ctx->opcode));
699 }
700 /* rlwinm & rlwinm. */
701 GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
702 {
703     uint32_t mb, me, sh;
704     
705     sh = SH(ctx->opcode);
706     mb = MB(ctx->opcode);
707     me = ME(ctx->opcode);
708     gen_op_load_gpr_T0(rS(ctx->opcode));
709 #if 1 // TRY
710     if (sh == 0) {
711         gen_op_andi_(MASK(mb, me));
712         goto store;
713     }
714 #endif
715     if (mb == 0) {
716         if (me == 31) {
717             gen_op_rotlwi(sh);
718             goto store;
719 #if 0
720         } else if (me == (31 - sh)) {
721             gen_op_slwi(sh);
722             goto store;
723 #endif
724         }
725     } else if (me == 31) {
726 #if 0
727         if (sh == (32 - mb)) {
728             gen_op_srwi(mb);
729             goto store;
730         }
731 #endif
732     }
733     gen_op_rlwinm(sh, MASK(mb, me));
734 store:
735     if (Rc(ctx->opcode) != 0)
736         gen_op_set_Rc0();
737     gen_op_store_T0_gpr(rA(ctx->opcode));
738 }
739 /* rlwnm & rlwnm. */
740 GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
741 {
742     uint32_t mb, me;
743
744     mb = MB(ctx->opcode);
745     me = ME(ctx->opcode);
746     gen_op_load_gpr_T0(rS(ctx->opcode));
747     gen_op_load_gpr_T1(rB(ctx->opcode));
748     if (mb == 0 && me == 31) {
749         gen_op_rotl();
750     } else
751     {
752         gen_op_rlwnm(MASK(mb, me));
753     }
754     if (Rc(ctx->opcode) != 0)
755         gen_op_set_Rc0();
756     gen_op_store_T0_gpr(rA(ctx->opcode));
757 }
758
759 /***                             Integer shift                             ***/
760 /* slw & slw. */
761 __GEN_LOGICAL2(slw, 0x18, 0x00);
762 /* sraw & sraw. */
763 __GEN_LOGICAL2(sraw, 0x18, 0x18);
764 /* srawi & srawi. */
765 GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER)
766 {
767     gen_op_load_gpr_T0(rS(ctx->opcode));
768     if (SH(ctx->opcode) != 0)
769     gen_op_srawi(SH(ctx->opcode), MASK(32 - SH(ctx->opcode), 31));
770     if (Rc(ctx->opcode) != 0)
771         gen_op_set_Rc0();
772     gen_op_store_T0_gpr(rA(ctx->opcode));
773 }
774 /* srw & srw. */
775 __GEN_LOGICAL2(srw, 0x18, 0x10);
776
777 /***                       Floating-Point arithmetic                       ***/
778 #define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat)                           \
779 GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, PPC_FLOAT)                   \
780 {                                                                             \
781     if (!ctx->fpu_enabled) {                                                  \
782         RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
783         return;                                                               \
784     }                                                                         \
785     gen_op_reset_scrfx();                                                     \
786     gen_op_load_fpr_FT0(rA(ctx->opcode));                                     \
787     gen_op_load_fpr_FT1(rC(ctx->opcode));                                     \
788     gen_op_load_fpr_FT2(rB(ctx->opcode));                                     \
789     gen_op_f##op();                                                           \
790     if (isfloat) {                                                            \
791         gen_op_frsp();                                                        \
792     }                                                                         \
793     gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
794     if (Rc(ctx->opcode))                                                      \
795         gen_op_set_Rc1();                                                     \
796 }
797
798 #define GEN_FLOAT_ACB(name, op2)                                              \
799 _GEN_FLOAT_ACB(name, name, 0x3F, op2, 0);                                     \
800 _GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1);
801
802 #define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat)                     \
803 GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT)                        \
804 {                                                                             \
805     if (!ctx->fpu_enabled) {                                                  \
806         RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
807         return;                                                               \
808     }                                                                         \
809     gen_op_reset_scrfx();                                                     \
810     gen_op_load_fpr_FT0(rA(ctx->opcode));                                     \
811     gen_op_load_fpr_FT1(rB(ctx->opcode));                                     \
812     gen_op_f##op();                                                           \
813     if (isfloat) {                                                            \
814         gen_op_frsp();                                                        \
815     }                                                                         \
816     gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
817     if (Rc(ctx->opcode))                                                      \
818         gen_op_set_Rc1();                                                     \
819 }
820 #define GEN_FLOAT_AB(name, op2, inval)                                        \
821 _GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0);                               \
822 _GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1);
823
824 #define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat)                     \
825 GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT)                        \
826 {                                                                             \
827     if (!ctx->fpu_enabled) {                                                  \
828         RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
829         return;                                                               \
830     }                                                                         \
831     gen_op_reset_scrfx();                                                     \
832     gen_op_load_fpr_FT0(rA(ctx->opcode));                                     \
833     gen_op_load_fpr_FT1(rC(ctx->opcode));                                     \
834     gen_op_f##op();                                                           \
835     if (isfloat) {                                                            \
836         gen_op_frsp();                                                        \
837     }                                                                         \
838     gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
839     if (Rc(ctx->opcode))                                                      \
840         gen_op_set_Rc1();                                                     \
841 }
842 #define GEN_FLOAT_AC(name, op2, inval)                                        \
843 _GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0);                               \
844 _GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1);
845
846 #define GEN_FLOAT_B(name, op2, op3)                                           \
847 GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, PPC_FLOAT)                   \
848 {                                                                             \
849     if (!ctx->fpu_enabled) {                                                  \
850         RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
851         return;                                                               \
852     }                                                                         \
853     gen_op_reset_scrfx();                                                     \
854     gen_op_load_fpr_FT0(rB(ctx->opcode));                                     \
855     gen_op_f##name();                                                         \
856     gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
857     if (Rc(ctx->opcode))                                                      \
858         gen_op_set_Rc1();                                                     \
859 }
860
861 #define GEN_FLOAT_BS(name, op1, op2)                                          \
862 GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, PPC_FLOAT)                   \
863 {                                                                             \
864     if (!ctx->fpu_enabled) {                                                  \
865         RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
866         return;                                                               \
867     }                                                                         \
868     gen_op_reset_scrfx();                                                     \
869     gen_op_load_fpr_FT0(rB(ctx->opcode));                                     \
870     gen_op_f##name();                                                         \
871     gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
872     if (Rc(ctx->opcode))                                                      \
873         gen_op_set_Rc1();                                                     \
874 }
875
876 /* fadd - fadds */
877 GEN_FLOAT_AB(add, 0x15, 0x000007C0);
878 /* fdiv - fdivs */
879 GEN_FLOAT_AB(div, 0x12, 0x000007C0);
880 /* fmul - fmuls */
881 GEN_FLOAT_AC(mul, 0x19, 0x0000F800);
882
883 /* fres */
884 GEN_FLOAT_BS(res, 0x3B, 0x18);
885
886 /* frsqrte */
887 GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A);
888
889 /* fsel */
890 _GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0);
891 /* fsub - fsubs */
892 GEN_FLOAT_AB(sub, 0x14, 0x000007C0);
893 /* Optional: */
894 /* fsqrt */
895 GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_OPT)
896 {
897     if (!ctx->fpu_enabled) {
898         RET_EXCP(ctx, EXCP_NO_FP, 0);
899         return;
900     }
901     gen_op_reset_scrfx();
902     gen_op_load_fpr_FT0(rB(ctx->opcode));
903     gen_op_fsqrt();
904     gen_op_store_FT0_fpr(rD(ctx->opcode));
905     if (Rc(ctx->opcode))
906         gen_op_set_Rc1();
907 }
908
909 GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_OPT)
910 {
911     if (!ctx->fpu_enabled) {
912         RET_EXCP(ctx, EXCP_NO_FP, 0);
913         return;
914     }
915     gen_op_reset_scrfx();
916     gen_op_load_fpr_FT0(rB(ctx->opcode));
917     gen_op_fsqrt();
918     gen_op_frsp();
919     gen_op_store_FT0_fpr(rD(ctx->opcode));
920     if (Rc(ctx->opcode))
921         gen_op_set_Rc1();
922 }
923
924 /***                     Floating-Point multiply-and-add                   ***/
925 /* fmadd - fmadds */
926 GEN_FLOAT_ACB(madd, 0x1D);
927 /* fmsub - fmsubs */
928 GEN_FLOAT_ACB(msub, 0x1C);
929 /* fnmadd - fnmadds */
930 GEN_FLOAT_ACB(nmadd, 0x1F);
931 /* fnmsub - fnmsubs */
932 GEN_FLOAT_ACB(nmsub, 0x1E);
933
934 /***                     Floating-Point round & convert                    ***/
935 /* fctiw */
936 GEN_FLOAT_B(ctiw, 0x0E, 0x00);
937 /* fctiwz */
938 GEN_FLOAT_B(ctiwz, 0x0F, 0x00);
939 /* frsp */
940 GEN_FLOAT_B(rsp, 0x0C, 0x00);
941
942 /***                         Floating-Point compare                        ***/
943 /* fcmpo */
944 GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT)
945 {
946     if (!ctx->fpu_enabled) {
947         RET_EXCP(ctx, EXCP_NO_FP, 0);
948         return;
949     }
950     gen_op_reset_scrfx();
951     gen_op_load_fpr_FT0(rA(ctx->opcode));
952     gen_op_load_fpr_FT1(rB(ctx->opcode));
953     gen_op_fcmpo();
954     gen_op_store_T0_crf(crfD(ctx->opcode));
955 }
956
957 /* fcmpu */
958 GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT)
959 {
960     if (!ctx->fpu_enabled) {
961         RET_EXCP(ctx, EXCP_NO_FP, 0);
962         return;
963     }
964     gen_op_reset_scrfx();
965     gen_op_load_fpr_FT0(rA(ctx->opcode));
966     gen_op_load_fpr_FT1(rB(ctx->opcode));
967     gen_op_fcmpu();
968     gen_op_store_T0_crf(crfD(ctx->opcode));
969 }
970
971 /***                         Floating-point move                           ***/
972 /* fabs */
973 GEN_FLOAT_B(abs, 0x08, 0x08);
974
975 /* fmr  - fmr. */
976 GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT)
977 {
978     if (!ctx->fpu_enabled) {
979         RET_EXCP(ctx, EXCP_NO_FP, 0);
980         return;
981     }
982     gen_op_reset_scrfx();
983     gen_op_load_fpr_FT0(rB(ctx->opcode));
984     gen_op_store_FT0_fpr(rD(ctx->opcode));
985     if (Rc(ctx->opcode))
986         gen_op_set_Rc1();
987 }
988
989 /* fnabs */
990 GEN_FLOAT_B(nabs, 0x08, 0x04);
991 /* fneg */
992 GEN_FLOAT_B(neg, 0x08, 0x01);
993
994 /***                  Floating-Point status & ctrl register                ***/
995 /* mcrfs */
996 GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT)
997 {
998     if (!ctx->fpu_enabled) {
999         RET_EXCP(ctx, EXCP_NO_FP, 0);
1000         return;
1001     }
1002     gen_op_load_fpscr_T0(crfS(ctx->opcode));
1003     gen_op_store_T0_crf(crfD(ctx->opcode));
1004     gen_op_clear_fpscr(crfS(ctx->opcode));
1005 }
1006
1007 /* mffs */
1008 GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT)
1009 {
1010     if (!ctx->fpu_enabled) {
1011         RET_EXCP(ctx, EXCP_NO_FP, 0);
1012         return;
1013     }
1014     gen_op_load_fpscr();
1015     gen_op_store_FT0_fpr(rD(ctx->opcode));
1016     if (Rc(ctx->opcode))
1017         gen_op_set_Rc1();
1018 }
1019
1020 /* mtfsb0 */
1021 GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT)
1022 {
1023     uint8_t crb;
1024     
1025     if (!ctx->fpu_enabled) {
1026         RET_EXCP(ctx, EXCP_NO_FP, 0);
1027         return;
1028     }
1029     crb = crbD(ctx->opcode) >> 2;
1030     gen_op_load_fpscr_T0(crb);
1031     gen_op_andi_(~(1 << (crbD(ctx->opcode) & 0x03)));
1032     gen_op_store_T0_fpscr(crb);
1033     if (Rc(ctx->opcode))
1034         gen_op_set_Rc1();
1035 }
1036
1037 /* mtfsb1 */
1038 GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT)
1039 {
1040     uint8_t crb;
1041     
1042     if (!ctx->fpu_enabled) {
1043         RET_EXCP(ctx, EXCP_NO_FP, 0);
1044         return;
1045     }
1046     crb = crbD(ctx->opcode) >> 2;
1047     gen_op_load_fpscr_T0(crb);
1048     gen_op_ori(1 << (crbD(ctx->opcode) & 0x03));
1049     gen_op_store_T0_fpscr(crb);
1050     if (Rc(ctx->opcode))
1051         gen_op_set_Rc1();
1052 }
1053
1054 /* mtfsf */
1055 GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT)
1056 {
1057     if (!ctx->fpu_enabled) {
1058         RET_EXCP(ctx, EXCP_NO_FP, 0);
1059         return;
1060     }
1061     gen_op_load_fpr_FT0(rB(ctx->opcode));
1062     gen_op_store_fpscr(FM(ctx->opcode));
1063     if (Rc(ctx->opcode))
1064         gen_op_set_Rc1();
1065 }
1066
1067 /* mtfsfi */
1068 GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT)
1069 {
1070     if (!ctx->fpu_enabled) {
1071         RET_EXCP(ctx, EXCP_NO_FP, 0);
1072         return;
1073     }
1074     gen_op_store_T0_fpscri(crbD(ctx->opcode) >> 2, FPIMM(ctx->opcode));
1075     if (Rc(ctx->opcode))
1076         gen_op_set_Rc1();
1077 }
1078
1079 /***                             Integer load                              ***/
1080 #define op_ldst(name)        (*gen_op_##name[ctx->mem_idx])()
1081 #if defined(CONFIG_USER_ONLY)
1082 #define OP_LD_TABLE(width)                                                    \
1083 static GenOpFunc *gen_op_l##width[] = {                                       \
1084     &gen_op_l##width##_raw,                                                   \
1085     &gen_op_l##width##_le_raw,                                                \
1086 };
1087 #define OP_ST_TABLE(width)                                                    \
1088 static GenOpFunc *gen_op_st##width[] = {                                      \
1089     &gen_op_st##width##_raw,                                                  \
1090     &gen_op_st##width##_le_raw,                                               \
1091 };
1092 /* Byte access routine are endian safe */
1093 #define gen_op_stb_le_raw gen_op_stb_raw
1094 #define gen_op_lbz_le_raw gen_op_lbz_raw
1095 #else
1096 #define OP_LD_TABLE(width)                                                    \
1097 static GenOpFunc *gen_op_l##width[] = {                                       \
1098     &gen_op_l##width##_user,                                                  \
1099     &gen_op_l##width##_le_user,                                               \
1100     &gen_op_l##width##_kernel,                                                \
1101     &gen_op_l##width##_le_kernel,                                             \
1102 };
1103 #define OP_ST_TABLE(width)                                                    \
1104 static GenOpFunc *gen_op_st##width[] = {                                      \
1105     &gen_op_st##width##_user,                                                 \
1106     &gen_op_st##width##_le_user,                                              \
1107     &gen_op_st##width##_kernel,                                               \
1108     &gen_op_st##width##_le_kernel,                                            \
1109 };
1110 /* Byte access routine are endian safe */
1111 #define gen_op_stb_le_user gen_op_stb_user
1112 #define gen_op_lbz_le_user gen_op_lbz_user
1113 #define gen_op_stb_le_kernel gen_op_stb_kernel
1114 #define gen_op_lbz_le_kernel gen_op_lbz_kernel
1115 #endif
1116
1117 #define GEN_LD(width, opc)                                                    \
1118 GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)               \
1119 {                                                                             \
1120     uint32_t simm = SIMM(ctx->opcode);                                        \
1121     if (rA(ctx->opcode) == 0) {                                               \
1122         gen_op_set_T0(simm);                                                  \
1123     } else {                                                                  \
1124         gen_op_load_gpr_T0(rA(ctx->opcode));                                  \
1125         if (simm != 0)                                                        \
1126             gen_op_addi(simm);                                                \
1127     }                                                                         \
1128     op_ldst(l##width);                                                        \
1129     gen_op_store_T1_gpr(rD(ctx->opcode));                                     \
1130 }
1131
1132 #define GEN_LDU(width, opc)                                                   \
1133 GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)            \
1134 {                                                                             \
1135     uint32_t simm = SIMM(ctx->opcode);                                        \
1136     if (rA(ctx->opcode) == 0 ||                                               \
1137         rA(ctx->opcode) == rD(ctx->opcode)) {                                 \
1138         RET_INVAL(ctx);                                                       \
1139         return;                                                               \
1140     }                                                                         \
1141     gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
1142     if (simm != 0)                                                            \
1143         gen_op_addi(simm);                                                    \
1144     op_ldst(l##width);                                                        \
1145     gen_op_store_T1_gpr(rD(ctx->opcode));                                     \
1146     gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
1147 }
1148
1149 #define GEN_LDUX(width, opc)                                                  \
1150 GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER)           \
1151 {                                                                             \
1152     if (rA(ctx->opcode) == 0 ||                                               \
1153         rA(ctx->opcode) == rD(ctx->opcode)) {                                 \
1154         RET_INVAL(ctx);                                                       \
1155         return;                                                               \
1156     }                                                                         \
1157     gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
1158     gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
1159     gen_op_add();                                                             \
1160     op_ldst(l##width);                                                        \
1161     gen_op_store_T1_gpr(rD(ctx->opcode));                                     \
1162     gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
1163 }
1164
1165 #define GEN_LDX(width, opc2, opc3)                                            \
1166 GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER)           \
1167 {                                                                             \
1168     if (rA(ctx->opcode) == 0) {                                               \
1169         gen_op_load_gpr_T0(rB(ctx->opcode));                                  \
1170     } else {                                                                  \
1171         gen_op_load_gpr_T0(rA(ctx->opcode));                                  \
1172         gen_op_load_gpr_T1(rB(ctx->opcode));                                  \
1173         gen_op_add();                                                         \
1174     }                                                                         \
1175     op_ldst(l##width);                                                        \
1176     gen_op_store_T1_gpr(rD(ctx->opcode));                                     \
1177 }
1178
1179 #define GEN_LDS(width, op)                                                    \
1180 OP_LD_TABLE(width);                                                           \
1181 GEN_LD(width, op | 0x20);                                                     \
1182 GEN_LDU(width, op | 0x21);                                                    \
1183 GEN_LDUX(width, op | 0x01);                                                   \
1184 GEN_LDX(width, 0x17, op | 0x00)
1185
1186 /* lbz lbzu lbzux lbzx */
1187 GEN_LDS(bz, 0x02);
1188 /* lha lhau lhaux lhax */
1189 GEN_LDS(ha, 0x0A);
1190 /* lhz lhzu lhzux lhzx */
1191 GEN_LDS(hz, 0x08);
1192 /* lwz lwzu lwzux lwzx */
1193 GEN_LDS(wz, 0x00);
1194
1195 /***                              Integer store                            ***/
1196 #define GEN_ST(width, opc)                                                    \
1197 GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)              \
1198 {                                                                             \
1199     uint32_t simm = SIMM(ctx->opcode);                                        \
1200     if (rA(ctx->opcode) == 0) {                                               \
1201         gen_op_set_T0(simm);                                                  \
1202     } else {                                                                  \
1203         gen_op_load_gpr_T0(rA(ctx->opcode));                                  \
1204         if (simm != 0)                                                        \
1205             gen_op_addi(simm);                                                \
1206     }                                                                         \
1207     gen_op_load_gpr_T1(rS(ctx->opcode));                                      \
1208     op_ldst(st##width);                                                       \
1209 }
1210
1211 #define GEN_STU(width, opc)                                                   \
1212 GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)           \
1213 {                                                                             \
1214     uint32_t simm = SIMM(ctx->opcode);                                        \
1215     if (rA(ctx->opcode) == 0) {                                               \
1216         RET_INVAL(ctx);                                                       \
1217         return;                                                               \
1218     }                                                                         \
1219     gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
1220     if (simm != 0)                                                            \
1221         gen_op_addi(simm);                                                    \
1222     gen_op_load_gpr_T1(rS(ctx->opcode));                                      \
1223     op_ldst(st##width);                                                       \
1224     gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
1225 }
1226
1227 #define GEN_STUX(width, opc)                                                  \
1228 GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER)          \
1229 {                                                                             \
1230     if (rA(ctx->opcode) == 0) {                                               \
1231         RET_INVAL(ctx);                                                       \
1232         return;                                                               \
1233     }                                                                         \
1234     gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
1235     gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
1236     gen_op_add();                                                             \
1237     gen_op_load_gpr_T1(rS(ctx->opcode));                                      \
1238     op_ldst(st##width);                                                       \
1239     gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
1240 }
1241
1242 #define GEN_STX(width, opc2, opc3)                                            \
1243 GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER)          \
1244 {                                                                             \
1245     if (rA(ctx->opcode) == 0) {                                               \
1246         gen_op_load_gpr_T0(rB(ctx->opcode));                                  \
1247     } else {                                                                  \
1248         gen_op_load_gpr_T0(rA(ctx->opcode));                                  \
1249         gen_op_load_gpr_T1(rB(ctx->opcode));                                  \
1250         gen_op_add();                                                         \
1251     }                                                                         \
1252     gen_op_load_gpr_T1(rS(ctx->opcode));                                      \
1253     op_ldst(st##width);                                                       \
1254 }
1255
1256 #define GEN_STS(width, op)                                                    \
1257 OP_ST_TABLE(width);                                                           \
1258 GEN_ST(width, op | 0x20);                                                     \
1259 GEN_STU(width, op | 0x21);                                                    \
1260 GEN_STUX(width, op | 0x01);                                                   \
1261 GEN_STX(width, 0x17, op | 0x00)
1262
1263 /* stb stbu stbux stbx */
1264 GEN_STS(b, 0x06);
1265 /* sth sthu sthux sthx */
1266 GEN_STS(h, 0x0C);
1267 /* stw stwu stwux stwx */
1268 GEN_STS(w, 0x04);
1269
1270 /***                Integer load and store with byte reverse               ***/
1271 /* lhbrx */
1272 OP_LD_TABLE(hbr);
1273 GEN_LDX(hbr, 0x16, 0x18);
1274 /* lwbrx */
1275 OP_LD_TABLE(wbr);
1276 GEN_LDX(wbr, 0x16, 0x10);
1277 /* sthbrx */
1278 OP_ST_TABLE(hbr);
1279 GEN_STX(hbr, 0x16, 0x1C);
1280 /* stwbrx */
1281 OP_ST_TABLE(wbr);
1282 GEN_STX(wbr, 0x16, 0x14);
1283
1284 /***                    Integer load and store multiple                    ***/
1285 #define op_ldstm(name, reg) (*gen_op_##name[ctx->mem_idx])(reg)
1286 #if defined(CONFIG_USER_ONLY)
1287 static GenOpFunc1 *gen_op_lmw[] = {
1288     &gen_op_lmw_raw,
1289     &gen_op_lmw_le_raw,
1290 };
1291 static GenOpFunc1 *gen_op_stmw[] = {
1292     &gen_op_stmw_raw,
1293     &gen_op_stmw_le_raw,
1294 };
1295 #else
1296 static GenOpFunc1 *gen_op_lmw[] = {
1297     &gen_op_lmw_user,
1298     &gen_op_lmw_le_user,
1299     &gen_op_lmw_kernel,
1300     &gen_op_lmw_le_kernel,
1301 };
1302 static GenOpFunc1 *gen_op_stmw[] = {
1303     &gen_op_stmw_user,
1304     &gen_op_stmw_le_user,
1305     &gen_op_stmw_kernel,
1306     &gen_op_stmw_le_kernel,
1307 };
1308 #endif
1309
1310 /* lmw */
1311 GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1312 {
1313     int simm = SIMM(ctx->opcode);
1314
1315     if (rA(ctx->opcode) == 0) {
1316         gen_op_set_T0(simm);
1317     } else {
1318         gen_op_load_gpr_T0(rA(ctx->opcode));
1319         if (simm != 0)
1320             gen_op_addi(simm);
1321     }
1322     op_ldstm(lmw, rD(ctx->opcode));
1323 }
1324
1325 /* stmw */
1326 GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1327 {
1328     int simm = SIMM(ctx->opcode);
1329
1330     if (rA(ctx->opcode) == 0) {
1331         gen_op_set_T0(simm);
1332     } else {
1333         gen_op_load_gpr_T0(rA(ctx->opcode));
1334         if (simm != 0)
1335             gen_op_addi(simm);
1336     }
1337     op_ldstm(stmw, rS(ctx->opcode));
1338 }
1339
1340 /***                    Integer load and store strings                     ***/
1341 #define op_ldsts(name, start) (*gen_op_##name[ctx->mem_idx])(start)
1342 #define op_ldstsx(name, rd, ra, rb) (*gen_op_##name[ctx->mem_idx])(rd, ra, rb)
1343 #if defined(CONFIG_USER_ONLY)
1344 static GenOpFunc1 *gen_op_lswi[] = {
1345     &gen_op_lswi_raw,
1346     &gen_op_lswi_le_raw,
1347 };
1348 static GenOpFunc3 *gen_op_lswx[] = {
1349     &gen_op_lswx_raw,
1350     &gen_op_lswx_le_raw,
1351 };
1352 static GenOpFunc1 *gen_op_stsw[] = {
1353     &gen_op_stsw_raw,
1354     &gen_op_stsw_le_raw,
1355 };
1356 #else
1357 static GenOpFunc1 *gen_op_lswi[] = {
1358     &gen_op_lswi_user,
1359     &gen_op_lswi_le_user,
1360     &gen_op_lswi_kernel,
1361     &gen_op_lswi_le_kernel,
1362 };
1363 static GenOpFunc3 *gen_op_lswx[] = {
1364     &gen_op_lswx_user,
1365     &gen_op_lswx_le_user,
1366     &gen_op_lswx_kernel,
1367     &gen_op_lswx_le_kernel,
1368 };
1369 static GenOpFunc1 *gen_op_stsw[] = {
1370     &gen_op_stsw_user,
1371     &gen_op_stsw_le_user,
1372     &gen_op_stsw_kernel,
1373     &gen_op_stsw_le_kernel,
1374 };
1375 #endif
1376
1377 /* lswi */
1378 /* PowerPC32 specification says we must generate an exception if
1379  * rA is in the range of registers to be loaded.
1380  * In an other hand, IBM says this is valid, but rA won't be loaded.
1381  * For now, I'll follow the spec...
1382  */
1383 GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_INTEGER)
1384 {
1385     int nb = NB(ctx->opcode);
1386     int start = rD(ctx->opcode);
1387     int ra = rA(ctx->opcode);
1388     int nr;
1389
1390     if (nb == 0)
1391         nb = 32;
1392     nr = nb / 4;
1393     if (((start + nr) > 32  && start <= ra && (start + nr - 32) > ra) ||
1394         ((start + nr) <= 32 && start <= ra && (start + nr) > ra)) {
1395         RET_EXCP(ctx, EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_LSWX);
1396         return;
1397     }
1398     if (ra == 0) {
1399         gen_op_set_T0(0);
1400     } else {
1401         gen_op_load_gpr_T0(ra);
1402     }
1403     gen_op_set_T1(nb);
1404     /* NIP cannot be restored if the memory exception comes from an helper */
1405     gen_op_update_nip((ctx)->nip - 4); 
1406     op_ldsts(lswi, start);
1407 }
1408
1409 /* lswx */
1410 GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_INTEGER)
1411 {
1412     int ra = rA(ctx->opcode);
1413     int rb = rB(ctx->opcode);
1414
1415     if (ra == 0) {
1416         gen_op_load_gpr_T0(rb);
1417         ra = rb;
1418     } else {
1419         gen_op_load_gpr_T0(ra);
1420         gen_op_load_gpr_T1(rb);
1421         gen_op_add();
1422     }
1423     gen_op_load_xer_bc();
1424     /* NIP cannot be restored if the memory exception comes from an helper */
1425     gen_op_update_nip((ctx)->nip - 4); 
1426     op_ldstsx(lswx, rD(ctx->opcode), ra, rb);
1427 }
1428
1429 /* stswi */
1430 GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_INTEGER)
1431 {
1432     int nb = NB(ctx->opcode);
1433
1434     if (rA(ctx->opcode) == 0) {
1435         gen_op_set_T0(0);
1436     } else {
1437         gen_op_load_gpr_T0(rA(ctx->opcode));
1438     }
1439     if (nb == 0)
1440         nb = 32;
1441     gen_op_set_T1(nb);
1442     /* NIP cannot be restored if the memory exception comes from an helper */
1443     gen_op_update_nip((ctx)->nip - 4); 
1444     op_ldsts(stsw, rS(ctx->opcode));
1445 }
1446
1447 /* stswx */
1448 GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_INTEGER)
1449 {
1450     int ra = rA(ctx->opcode);
1451
1452     if (ra == 0) {
1453         gen_op_load_gpr_T0(rB(ctx->opcode));
1454         ra = rB(ctx->opcode);
1455     } else {
1456         gen_op_load_gpr_T0(ra);
1457         gen_op_load_gpr_T1(rB(ctx->opcode));
1458         gen_op_add();
1459     }
1460     gen_op_load_xer_bc();
1461     /* NIP cannot be restored if the memory exception comes from an helper */
1462     gen_op_update_nip((ctx)->nip - 4); 
1463     op_ldsts(stsw, rS(ctx->opcode));
1464 }
1465
1466 /***                        Memory synchronisation                         ***/
1467 /* eieio */
1468 GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FF0801, PPC_MEM)
1469 {
1470 }
1471
1472 /* isync */
1473 GEN_HANDLER(isync, 0x13, 0x16, 0xFF, 0x03FF0801, PPC_MEM)
1474 {
1475 }
1476
1477 #define op_lwarx() (*gen_op_lwarx[ctx->mem_idx])()
1478 #define op_stwcx() (*gen_op_stwcx[ctx->mem_idx])()
1479 #if defined(CONFIG_USER_ONLY)
1480 static GenOpFunc *gen_op_lwarx[] = {
1481     &gen_op_lwarx_raw,
1482     &gen_op_lwarx_le_raw,
1483 };
1484 static GenOpFunc *gen_op_stwcx[] = {
1485     &gen_op_stwcx_raw,
1486     &gen_op_stwcx_le_raw,
1487 };
1488 #else
1489 static GenOpFunc *gen_op_lwarx[] = {
1490     &gen_op_lwarx_user,
1491     &gen_op_lwarx_le_user,
1492     &gen_op_lwarx_kernel,
1493     &gen_op_lwarx_le_kernel,
1494 };
1495 static GenOpFunc *gen_op_stwcx[] = {
1496     &gen_op_stwcx_user,
1497     &gen_op_stwcx_le_user,
1498     &gen_op_stwcx_kernel,
1499     &gen_op_stwcx_le_kernel,
1500 };
1501 #endif
1502
1503 /* lwarx */
1504 GEN_HANDLER(lwarx, 0x1F, 0x14, 0xFF, 0x00000001, PPC_RES)
1505 {
1506     if (rA(ctx->opcode) == 0) {
1507         gen_op_load_gpr_T0(rB(ctx->opcode));
1508     } else {
1509         gen_op_load_gpr_T0(rA(ctx->opcode));
1510         gen_op_load_gpr_T1(rB(ctx->opcode));
1511         gen_op_add();
1512     }
1513     op_lwarx();
1514     gen_op_store_T1_gpr(rD(ctx->opcode));
1515 }
1516
1517 /* stwcx. */
1518 GEN_HANDLER(stwcx_, 0x1F, 0x16, 0x04, 0x00000000, PPC_RES)
1519 {
1520         if (rA(ctx->opcode) == 0) {
1521             gen_op_load_gpr_T0(rB(ctx->opcode));
1522         } else {
1523             gen_op_load_gpr_T0(rA(ctx->opcode));
1524             gen_op_load_gpr_T1(rB(ctx->opcode));
1525         gen_op_add();
1526         }
1527     gen_op_load_gpr_T1(rS(ctx->opcode));
1528     op_stwcx();
1529 }
1530
1531 /* sync */
1532 GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x03FF0801, PPC_MEM)
1533 {
1534 }
1535
1536 /***                         Floating-point load                           ***/
1537 #define GEN_LDF(width, opc)                                                   \
1538 GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT)                 \
1539 {                                                                             \
1540     uint32_t simm = SIMM(ctx->opcode);                                        \
1541     if (!ctx->fpu_enabled) {                                                  \
1542         RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
1543         return;                                                               \
1544     }                                                                         \
1545     if (rA(ctx->opcode) == 0) {                                               \
1546         gen_op_set_T0(simm);                                                  \
1547     } else {                                                                  \
1548         gen_op_load_gpr_T0(rA(ctx->opcode));                                  \
1549         if (simm != 0)                                                        \
1550             gen_op_addi(simm);                                                \
1551     }                                                                         \
1552     op_ldst(l##width);                                                        \
1553     gen_op_store_FT1_fpr(rD(ctx->opcode));                                    \
1554 }
1555
1556 #define GEN_LDUF(width, opc)                                                  \
1557 GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT)              \
1558 {                                                                             \
1559     uint32_t simm = SIMM(ctx->opcode);                                        \
1560     if (!ctx->fpu_enabled) {                                                  \
1561         RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
1562         return;                                                               \
1563     }                                                                         \
1564     if (rA(ctx->opcode) == 0 ||                                               \
1565         rA(ctx->opcode) == rD(ctx->opcode)) {                                 \
1566         RET_INVAL(ctx);                                                       \
1567         return;                                                               \
1568     }                                                                         \
1569     gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
1570     if (simm != 0)                                                            \
1571         gen_op_addi(simm);                                                    \
1572     op_ldst(l##width);                                                        \
1573     gen_op_store_FT1_fpr(rD(ctx->opcode));                                    \
1574     gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
1575 }
1576
1577 #define GEN_LDUXF(width, opc)                                                 \
1578 GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT)             \
1579 {                                                                             \
1580     if (!ctx->fpu_enabled) {                                                  \
1581         RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
1582         return;                                                               \
1583     }                                                                         \
1584     if (rA(ctx->opcode) == 0 ||                                               \
1585         rA(ctx->opcode) == rD(ctx->opcode)) {                                 \
1586         RET_INVAL(ctx);                                                       \
1587         return;                                                               \
1588     }                                                                         \
1589     gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
1590     gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
1591     gen_op_add();                                                             \
1592     op_ldst(l##width);                                                        \
1593     gen_op_store_FT1_fpr(rD(ctx->opcode));                                    \
1594     gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
1595 }
1596
1597 #define GEN_LDXF(width, opc2, opc3)                                           \
1598 GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_FLOAT)             \
1599 {                                                                             \
1600     if (!ctx->fpu_enabled) {                                                  \
1601         RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
1602         return;                                                               \
1603     }                                                                         \
1604     if (rA(ctx->opcode) == 0) {                                               \
1605         gen_op_load_gpr_T0(rB(ctx->opcode));                                  \
1606     } else {                                                                  \
1607         gen_op_load_gpr_T0(rA(ctx->opcode));                                  \
1608         gen_op_load_gpr_T1(rB(ctx->opcode));                                  \
1609         gen_op_add();                                                         \
1610     }                                                                         \
1611     op_ldst(l##width);                                                        \
1612     gen_op_store_FT1_fpr(rD(ctx->opcode));                                    \
1613 }
1614
1615 #define GEN_LDFS(width, op)                                                   \
1616 OP_LD_TABLE(width);                                                           \
1617 GEN_LDF(width, op | 0x20);                                                    \
1618 GEN_LDUF(width, op | 0x21);                                                   \
1619 GEN_LDUXF(width, op | 0x01);                                                  \
1620 GEN_LDXF(width, 0x17, op | 0x00)
1621
1622 /* lfd lfdu lfdux lfdx */
1623 GEN_LDFS(fd, 0x12);
1624 /* lfs lfsu lfsux lfsx */
1625 GEN_LDFS(fs, 0x10);
1626
1627 /***                         Floating-point store                          ***/
1628 #define GEN_STF(width, opc)                                                   \
1629 GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT)                \
1630 {                                                                             \
1631     uint32_t simm = SIMM(ctx->opcode);                                        \
1632     if (!ctx->fpu_enabled) {                                                  \
1633         RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
1634         return;                                                               \
1635     }                                                                         \
1636     if (rA(ctx->opcode) == 0) {                                               \
1637         gen_op_set_T0(simm);                                                  \
1638     } else {                                                                  \
1639         gen_op_load_gpr_T0(rA(ctx->opcode));                                  \
1640         if (simm != 0)                                                        \
1641             gen_op_addi(simm);                                                \
1642     }                                                                         \
1643     gen_op_load_fpr_FT1(rS(ctx->opcode));                                     \
1644     op_ldst(st##width);                                                       \
1645 }
1646
1647 #define GEN_STUF(width, opc)                                                  \
1648 GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT)             \
1649 {                                                                             \
1650     uint32_t simm = SIMM(ctx->opcode);                                        \
1651     if (!ctx->fpu_enabled) {                                                  \
1652         RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
1653         return;                                                               \
1654     }                                                                         \
1655     if (rA(ctx->opcode) == 0) {                                               \
1656         RET_INVAL(ctx);                                                       \
1657         return;                                                               \
1658     }                                                                         \
1659     gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
1660     if (simm != 0)                                                            \
1661         gen_op_addi(simm);                                                    \
1662     gen_op_load_fpr_FT1(rS(ctx->opcode));                                     \
1663     op_ldst(st##width);                                                       \
1664     gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
1665 }
1666
1667 #define GEN_STUXF(width, opc)                                                 \
1668 GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT)            \
1669 {                                                                             \
1670     if (!ctx->fpu_enabled) {                                                  \
1671         RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
1672         return;                                                               \
1673     }                                                                         \
1674     if (rA(ctx->opcode) == 0) {                                               \
1675         RET_INVAL(ctx);                                                       \
1676         return;                                                               \
1677     }                                                                         \
1678     gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
1679     gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
1680     gen_op_add();                                                             \
1681     gen_op_load_fpr_FT1(rS(ctx->opcode));                                     \
1682     op_ldst(st##width);                                                       \
1683     gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
1684 }
1685
1686 #define GEN_STXF(width, opc2, opc3)                                           \
1687 GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_FLOAT)            \
1688 {                                                                             \
1689     if (!ctx->fpu_enabled) {                                                  \
1690         RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
1691         return;                                                               \
1692     }                                                                         \
1693     if (rA(ctx->opcode) == 0) {                                               \
1694         gen_op_load_gpr_T0(rB(ctx->opcode));                                  \
1695     } else {                                                                  \
1696         gen_op_load_gpr_T0(rA(ctx->opcode));                                  \
1697         gen_op_load_gpr_T1(rB(ctx->opcode));                                  \
1698         gen_op_add();                                                         \
1699     }                                                                         \
1700     gen_op_load_fpr_FT1(rS(ctx->opcode));                                     \
1701     op_ldst(st##width);                                                       \
1702 }
1703
1704 #define GEN_STFS(width, op)                                                   \
1705 OP_ST_TABLE(width);                                                           \
1706 GEN_STF(width, op | 0x20);                                                    \
1707 GEN_STUF(width, op | 0x21);                                                   \
1708 GEN_STUXF(width, op | 0x01);                                                  \
1709 GEN_STXF(width, 0x17, op | 0x00)
1710
1711 /* stfd stfdu stfdux stfdx */
1712 GEN_STFS(fd, 0x16);
1713 /* stfs stfsu stfsux stfsx */
1714 GEN_STFS(fs, 0x14);
1715
1716 /* Optional: */
1717 /* stfiwx */
1718 GEN_HANDLER(stfiwx, 0x1F, 0x17, 0x1E, 0x00000001, PPC_FLOAT)
1719 {
1720     if (!ctx->fpu_enabled) {
1721         RET_EXCP(ctx, EXCP_NO_FP, 0);
1722         return;
1723     }
1724     RET_INVAL(ctx);
1725 }
1726
1727 /***                                Branch                                 ***/
1728
1729 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
1730 {
1731     TranslationBlock *tb;
1732     tb = ctx->tb;
1733     if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
1734         if (n == 0)
1735             gen_op_goto_tb0(TBPARAM(tb));
1736         else
1737             gen_op_goto_tb1(TBPARAM(tb));
1738         gen_op_set_T1(dest);
1739         gen_op_b_T1();
1740         gen_op_set_T0((long)tb + n);
1741         gen_op_exit_tb();
1742     } else {
1743         gen_op_set_T1(dest);
1744         gen_op_b_T1();
1745         gen_op_set_T0(0);
1746         gen_op_exit_tb();
1747     }
1748 }
1749
1750 /* b ba bl bla */
1751 GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
1752 {
1753     uint32_t li, target;
1754
1755     /* sign extend LI */
1756     li = ((int32_t)LI(ctx->opcode) << 6) >> 6;
1757
1758     if (AA(ctx->opcode) == 0)
1759         target = ctx->nip + li - 4;
1760     else
1761         target = li;
1762     if (LK(ctx->opcode)) {
1763         gen_op_setlr(ctx->nip);
1764     }
1765     gen_goto_tb(ctx, 0, target);
1766     ctx->exception = EXCP_BRANCH;
1767 }
1768
1769 #define BCOND_IM  0
1770 #define BCOND_LR  1
1771 #define BCOND_CTR 2
1772
1773 static inline void gen_bcond(DisasContext *ctx, int type) 
1774 {                                                                             
1775     uint32_t target = 0;
1776     uint32_t bo = BO(ctx->opcode);                                            
1777     uint32_t bi = BI(ctx->opcode);                                            
1778     uint32_t mask;                                                            
1779     uint32_t li;
1780
1781     if ((bo & 0x4) == 0)
1782         gen_op_dec_ctr();                                                     
1783     switch(type) {
1784     case BCOND_IM:
1785         li = (int32_t)((int16_t)(BD(ctx->opcode)));
1786         if (AA(ctx->opcode) == 0) {
1787             target = ctx->nip + li - 4;
1788         } else {
1789             target = li;
1790         }
1791         break;
1792     case BCOND_CTR:
1793         gen_op_movl_T1_ctr();
1794         break;
1795     default:
1796     case BCOND_LR:
1797         gen_op_movl_T1_lr();
1798         break;
1799     }
1800     if (LK(ctx->opcode)) {                                        
1801         gen_op_setlr(ctx->nip);
1802     }
1803     if (bo & 0x10) {
1804         /* No CR condition */                                                 
1805         switch (bo & 0x6) {                                                   
1806         case 0:                                                               
1807             gen_op_test_ctr();
1808             break;
1809         case 2:                                                               
1810             gen_op_test_ctrz();
1811             break;                                                            
1812         default:
1813         case 4:                                                               
1814         case 6:                                                               
1815             if (type == BCOND_IM) {
1816                 gen_goto_tb(ctx, 0, target);
1817             } else {
1818                 gen_op_b_T1();
1819             }
1820             goto no_test;
1821         }
1822     } else {                                                                  
1823         mask = 1 << (3 - (bi & 0x03));                                        
1824         gen_op_load_crf_T0(bi >> 2);                                          
1825         if (bo & 0x8) {                                                       
1826             switch (bo & 0x6) {                                               
1827             case 0:                                                           
1828                 gen_op_test_ctr_true(mask);
1829                 break;                                                        
1830             case 2:                                                           
1831                 gen_op_test_ctrz_true(mask);
1832                 break;                                                        
1833             default:                                                          
1834             case 4:                                                           
1835             case 6:                                                           
1836                 gen_op_test_true(mask);
1837                 break;                                                        
1838             }                                                                 
1839         } else {                                                              
1840             switch (bo & 0x6) {                                               
1841             case 0:                                                           
1842                 gen_op_test_ctr_false(mask);
1843                 break;                                                        
1844             case 2:                                                           
1845                 gen_op_test_ctrz_false(mask);
1846                 break;                                                        
1847             default:
1848             case 4:                                                           
1849             case 6:                                                           
1850                 gen_op_test_false(mask);
1851                 break;                                                        
1852             }                                                                 
1853         }                                                                     
1854     }                                                                         
1855     if (type == BCOND_IM) {
1856         int l1 = gen_new_label();
1857         gen_op_jz_T0(l1);
1858         gen_goto_tb(ctx, 0, target);
1859         gen_set_label(l1);
1860         gen_goto_tb(ctx, 1, ctx->nip);
1861     } else {
1862         gen_op_btest_T1(ctx->nip);
1863     }
1864  no_test:
1865     ctx->exception = EXCP_BRANCH;                                             
1866 }
1867
1868 GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
1869 {                                                                             
1870     gen_bcond(ctx, BCOND_IM);
1871 }
1872
1873 GEN_HANDLER(bcctr, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW)
1874 {                                                                             
1875     gen_bcond(ctx, BCOND_CTR);
1876 }
1877
1878 GEN_HANDLER(bclr, 0x13, 0x10, 0x00, 0x00000000, PPC_FLOW)
1879 {                                                                             
1880     gen_bcond(ctx, BCOND_LR);
1881 }
1882
1883 /***                      Condition register logical                       ***/
1884 #define GEN_CRLOGIC(op, opc)                                                  \
1885 GEN_HANDLER(cr##op, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER)                 \
1886 {                                                                             \
1887     gen_op_load_crf_T0(crbA(ctx->opcode) >> 2);                               \
1888     gen_op_getbit_T0(3 - (crbA(ctx->opcode) & 0x03));                         \
1889     gen_op_load_crf_T1(crbB(ctx->opcode) >> 2);                               \
1890     gen_op_getbit_T1(3 - (crbB(ctx->opcode) & 0x03));                         \
1891     gen_op_##op();                                                            \
1892     gen_op_load_crf_T1(crbD(ctx->opcode) >> 2);                               \
1893     gen_op_setcrfbit(~(1 << (3 - (crbD(ctx->opcode) & 0x03))),                \
1894                      3 - (crbD(ctx->opcode) & 0x03));                         \
1895     gen_op_store_T1_crf(crbD(ctx->opcode) >> 2);                              \
1896 }
1897
1898 /* crand */
1899 GEN_CRLOGIC(and, 0x08)
1900 /* crandc */
1901 GEN_CRLOGIC(andc, 0x04)
1902 /* creqv */
1903 GEN_CRLOGIC(eqv, 0x09)
1904 /* crnand */
1905 GEN_CRLOGIC(nand, 0x07)
1906 /* crnor */
1907 GEN_CRLOGIC(nor, 0x01)
1908 /* cror */
1909 GEN_CRLOGIC(or, 0x0E)
1910 /* crorc */
1911 GEN_CRLOGIC(orc, 0x0D)
1912 /* crxor */
1913 GEN_CRLOGIC(xor, 0x06)
1914 /* mcrf */
1915 GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER)
1916 {
1917     gen_op_load_crf_T0(crfS(ctx->opcode));
1918     gen_op_store_T0_crf(crfD(ctx->opcode));
1919 }
1920
1921 /***                           System linkage                              ***/
1922 /* rfi (supervisor only) */
1923 GEN_HANDLER(rfi, 0x13, 0x12, 0xFF, 0x03FF8001, PPC_FLOW)
1924 {
1925 #if defined(CONFIG_USER_ONLY)
1926     RET_PRIVOPC(ctx);
1927 #else
1928     /* Restore CPU state */
1929     if (!ctx->supervisor) {
1930         RET_PRIVOPC(ctx);
1931         return;
1932     }
1933     gen_op_rfi();
1934     RET_CHG_FLOW(ctx);
1935 #endif
1936 }
1937
1938 /* sc */
1939 GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFFFFD, PPC_FLOW)
1940 {
1941 #if defined(CONFIG_USER_ONLY)
1942     RET_EXCP(ctx, EXCP_SYSCALL_USER, 0);
1943 #else
1944     RET_EXCP(ctx, EXCP_SYSCALL, 0);
1945 #endif
1946 }
1947
1948 /***                                Trap                                   ***/
1949 /* tw */
1950 GEN_HANDLER(tw, 0x1F, 0x04, 0xFF, 0x00000001, PPC_FLOW)
1951 {
1952     gen_op_load_gpr_T0(rA(ctx->opcode));
1953     gen_op_load_gpr_T1(rB(ctx->opcode));
1954     gen_op_tw(TO(ctx->opcode));
1955 }
1956
1957 /* twi */
1958 GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
1959 {
1960     gen_op_load_gpr_T0(rA(ctx->opcode));
1961 #if 0
1962     printf("%s: param=0x%04x T0=0x%04x\n", __func__,
1963            SIMM(ctx->opcode), TO(ctx->opcode));
1964 #endif
1965     gen_op_twi(SIMM(ctx->opcode), TO(ctx->opcode));
1966 }
1967
1968 /***                          Processor control                            ***/
1969 static inline int check_spr_access (int spr, int rw, int supervisor)
1970 {
1971     uint32_t rights = spr_access[spr >> 1] >> (4 * (spr & 1));
1972
1973 #if 0
1974     if (spr != LR && spr != CTR) {
1975     if (loglevel > 0) {
1976         fprintf(logfile, "%s reg=%d s=%d rw=%d r=0x%02x 0x%02x\n", __func__,
1977                 SPR_ENCODE(spr), supervisor, rw, rights,
1978                 (rights >> ((2 * supervisor) + rw)) & 1);
1979     } else {
1980         printf("%s reg=%d s=%d rw=%d r=0x%02x 0x%02x\n", __func__,
1981                SPR_ENCODE(spr), supervisor, rw, rights,
1982                (rights >> ((2 * supervisor) + rw)) & 1);
1983     }
1984     }
1985 #endif
1986     if (rights == 0)
1987         return -1;
1988     rights = rights >> (2 * supervisor);
1989     rights = rights >> rw;
1990
1991     return rights & 1;
1992 }
1993
1994 /* mcrxr */
1995 GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC)
1996 {
1997     gen_op_load_xer_cr();
1998     gen_op_store_T0_crf(crfD(ctx->opcode));
1999     gen_op_clear_xer_cr();
2000 }
2001
2002 /* mfcr */
2003 GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x001FF801, PPC_MISC)
2004 {
2005     gen_op_load_cr();
2006     gen_op_store_T0_gpr(rD(ctx->opcode));
2007 }
2008
2009 /* mfmsr */
2010 GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC)
2011 {
2012 #if defined(CONFIG_USER_ONLY)
2013     RET_PRIVREG(ctx);
2014 #else
2015     if (!ctx->supervisor) {
2016         RET_PRIVREG(ctx);
2017         return;
2018     }
2019     gen_op_load_msr();
2020     gen_op_store_T0_gpr(rD(ctx->opcode));
2021 #endif
2022 }
2023
2024 #if 0
2025 #define SPR_NOACCESS ((void *)(-1))
2026 #else
2027 static void spr_noaccess (void *opaque, int sprn)
2028 {
2029     sprn = ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
2030     printf("ERROR: try to access SPR %d !\n", sprn);
2031 }
2032 #define SPR_NOACCESS (&spr_noaccess)
2033 #endif
2034
2035 /* mfspr */
2036 static inline void gen_op_mfspr (DisasContext *ctx)
2037 {
2038     void (*read_cb)(void *opaque, int sprn);
2039     uint32_t sprn = SPR(ctx->opcode);
2040
2041 #if !defined(CONFIG_USER_ONLY)
2042     if (ctx->supervisor)
2043         read_cb = ctx->spr_cb[sprn].oea_read;
2044     else
2045 #endif
2046         read_cb = ctx->spr_cb[sprn].uea_read;
2047     if (read_cb != NULL) {
2048         if (read_cb != SPR_NOACCESS) {
2049             (*read_cb)(ctx, sprn);
2050             gen_op_store_T0_gpr(rD(ctx->opcode));
2051         } else {
2052             /* Privilege exception */
2053             if (loglevel) {
2054                 fprintf(logfile, "Trying to read priviledged spr %d %03x\n",
2055                         sprn, sprn);
2056             }
2057             printf("Trying to read priviledged spr %d %03x\n", sprn, sprn);
2058         RET_PRIVREG(ctx);
2059         }
2060     } else {
2061         /* Not defined */
2062         if (loglevel) {
2063             fprintf(logfile, "Trying to read invalid spr %d %03x\n",
2064                     sprn, sprn);
2065         }
2066         printf("Trying to read invalid spr %d %03x\n", sprn, sprn);
2067         RET_EXCP(ctx, EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_SPR);
2068     }
2069 }
2070
2071 GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC)
2072 {
2073     gen_op_mfspr(ctx);
2074     }
2075
2076 /* mftb */
2077 GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_TB)
2078 {
2079     gen_op_mfspr(ctx);
2080 }
2081
2082 /* mtcrf */
2083 /* The mask should be 0x00100801, but Mac OS X 10.4 use an alternate form */
2084 GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC)
2085 {
2086     gen_op_load_gpr_T0(rS(ctx->opcode));
2087     gen_op_store_cr(CRM(ctx->opcode));
2088 }
2089
2090 /* mtmsr */
2091 GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC)
2092 {
2093 #if defined(CONFIG_USER_ONLY)
2094     RET_PRIVREG(ctx);
2095 #else
2096     if (!ctx->supervisor) {
2097         RET_PRIVREG(ctx);
2098         return;
2099     }
2100     gen_op_update_nip((ctx)->nip);
2101     gen_op_load_gpr_T0(rS(ctx->opcode));
2102     gen_op_store_msr();
2103     /* Must stop the translation as machine state (may have) changed */
2104     RET_CHG_FLOW(ctx);
2105 #endif
2106 }
2107
2108 /* mtspr */
2109 GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC)
2110 {
2111     void (*write_cb)(void *opaque, int sprn);
2112     uint32_t sprn = SPR(ctx->opcode);
2113
2114 #if !defined(CONFIG_USER_ONLY)
2115     if (ctx->supervisor)
2116         write_cb = ctx->spr_cb[sprn].oea_write;
2117     else
2118 #endif
2119         write_cb = ctx->spr_cb[sprn].uea_write;
2120     if (write_cb != NULL) {
2121         if (write_cb != SPR_NOACCESS) {
2122             gen_op_load_gpr_T0(rS(ctx->opcode));
2123             (*write_cb)(ctx, sprn);
2124         } else {
2125             /* Privilege exception */
2126             if (loglevel) {
2127                 fprintf(logfile, "Trying to write priviledged spr %d %03x\n",
2128                         sprn, sprn);
2129             }
2130             printf("Trying to write priviledged spr %d %03x\n", sprn, sprn);
2131         RET_PRIVREG(ctx);
2132     }
2133     } else {
2134         /* Not defined */
2135         if (loglevel) {
2136             fprintf(logfile, "Trying to write invalid spr %d %03x\n",
2137                     sprn, sprn);
2138         }
2139         printf("Trying to write invalid spr %d %03x\n", sprn, sprn);
2140         RET_EXCP(ctx, EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_SPR);
2141     }
2142 }
2143
2144 /***                         Cache management                              ***/
2145 /* For now, all those will be implemented as nop:
2146  * this is valid, regarding the PowerPC specs...
2147  * We just have to flush tb while invalidating instruction cache lines...
2148  */
2149 /* dcbf */
2150 GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03E00001, PPC_CACHE)
2151 {
2152     if (rA(ctx->opcode) == 0) {
2153         gen_op_load_gpr_T0(rB(ctx->opcode));
2154     } else {
2155         gen_op_load_gpr_T0(rA(ctx->opcode));
2156         gen_op_load_gpr_T1(rB(ctx->opcode));
2157         gen_op_add();
2158     }
2159     op_ldst(lbz);
2160 }
2161
2162 /* dcbi (Supervisor only) */
2163 GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE)
2164 {
2165 #if defined(CONFIG_USER_ONLY)
2166     RET_PRIVOPC(ctx);
2167 #else
2168     if (!ctx->supervisor) {
2169         RET_PRIVOPC(ctx);
2170         return;
2171     }
2172     if (rA(ctx->opcode) == 0) {
2173         gen_op_load_gpr_T0(rB(ctx->opcode));
2174     } else {
2175         gen_op_load_gpr_T0(rA(ctx->opcode));
2176         gen_op_load_gpr_T1(rB(ctx->opcode));
2177         gen_op_add();
2178     }
2179     op_ldst(lbz);
2180     op_ldst(stb);
2181 #endif
2182 }
2183
2184 /* dcdst */
2185 GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE)
2186 {
2187     if (rA(ctx->opcode) == 0) {
2188         gen_op_load_gpr_T0(rB(ctx->opcode));
2189     } else {
2190         gen_op_load_gpr_T0(rA(ctx->opcode));
2191         gen_op_load_gpr_T1(rB(ctx->opcode));
2192         gen_op_add();
2193     }
2194     op_ldst(lbz);
2195 }
2196
2197 /* dcbt */
2198 GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x03E00001, PPC_CACHE)
2199 {
2200 }
2201
2202 /* dcbtst */
2203 GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x03E00001, PPC_CACHE)
2204 {
2205 }
2206
2207 /* dcbz */
2208 #if defined(CONFIG_USER_ONLY)
2209 #define op_dcbz() gen_op_dcbz_raw()
2210 #else
2211 #define op_dcbz() (*gen_op_dcbz[ctx->mem_idx])()
2212 static GenOpFunc *gen_op_dcbz[] = {
2213     &gen_op_dcbz_user,
2214     &gen_op_dcbz_user,
2215     &gen_op_dcbz_kernel,
2216     &gen_op_dcbz_kernel,
2217 };
2218 #endif
2219
2220 GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03E00001, PPC_CACHE)
2221 {
2222     if (rA(ctx->opcode) == 0) {
2223         gen_op_load_gpr_T0(rB(ctx->opcode));
2224     } else {
2225         gen_op_load_gpr_T0(rA(ctx->opcode));
2226         gen_op_load_gpr_T1(rB(ctx->opcode));
2227         gen_op_add();
2228     }
2229     op_dcbz();
2230     gen_op_check_reservation();
2231 }
2232
2233 /* icbi */
2234 GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE)
2235 {
2236     if (rA(ctx->opcode) == 0) {
2237         gen_op_load_gpr_T0(rB(ctx->opcode));
2238     } else {
2239         gen_op_load_gpr_T0(rA(ctx->opcode));
2240         gen_op_load_gpr_T1(rB(ctx->opcode));
2241         gen_op_add();
2242     }
2243     gen_op_icbi();
2244 }
2245
2246 /* Optional: */
2247 /* dcba */
2248 GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_OPT)
2249 {
2250 }
2251
2252 /***                    Segment register manipulation                      ***/
2253 /* Supervisor only: */
2254 /* mfsr */
2255 GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT)
2256 {
2257 #if defined(CONFIG_USER_ONLY)
2258     RET_PRIVREG(ctx);
2259 #else
2260     if (!ctx->supervisor) {
2261         RET_PRIVREG(ctx);
2262         return;
2263     }
2264     gen_op_load_sr(SR(ctx->opcode));
2265     gen_op_store_T0_gpr(rD(ctx->opcode));
2266 #endif
2267 }
2268
2269 /* mfsrin */
2270 GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT)
2271 {
2272 #if defined(CONFIG_USER_ONLY)
2273     RET_PRIVREG(ctx);
2274 #else
2275     if (!ctx->supervisor) {
2276         RET_PRIVREG(ctx);
2277         return;
2278     }
2279     gen_op_load_gpr_T1(rB(ctx->opcode));
2280     gen_op_load_srin();
2281     gen_op_store_T0_gpr(rD(ctx->opcode));
2282 #endif
2283 }
2284
2285 /* mtsr */
2286 GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT)
2287 {
2288 #if defined(CONFIG_USER_ONLY)
2289     RET_PRIVREG(ctx);
2290 #else
2291     if (!ctx->supervisor) {
2292         RET_PRIVREG(ctx);
2293         return;
2294     }
2295     gen_op_load_gpr_T0(rS(ctx->opcode));
2296     gen_op_store_sr(SR(ctx->opcode));
2297     RET_STOP(ctx);
2298 #endif
2299 }
2300
2301 /* mtsrin */
2302 GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT)
2303 {
2304 #if defined(CONFIG_USER_ONLY)
2305     RET_PRIVREG(ctx);
2306 #else
2307     if (!ctx->supervisor) {
2308         RET_PRIVREG(ctx);
2309         return;
2310     }
2311     gen_op_load_gpr_T0(rS(ctx->opcode));
2312     gen_op_load_gpr_T1(rB(ctx->opcode));
2313     gen_op_store_srin();
2314     RET_STOP(ctx);
2315 #endif
2316 }
2317
2318 /***                      Lookaside buffer management                      ***/
2319 /* Optional & supervisor only: */
2320 /* tlbia */
2321 GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA)
2322 {
2323 #if defined(CONFIG_USER_ONLY)
2324     RET_PRIVOPC(ctx);
2325 #else
2326     if (!ctx->supervisor) {
2327         if (loglevel)
2328             fprintf(logfile, "%s: ! supervisor\n", __func__);
2329         RET_PRIVOPC(ctx);
2330         return;
2331     }
2332     gen_op_tlbia();
2333     RET_STOP(ctx);
2334 #endif
2335 }
2336
2337 /* tlbie */
2338 GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM)
2339 {
2340 #if defined(CONFIG_USER_ONLY)
2341     RET_PRIVOPC(ctx);
2342 #else
2343     if (!ctx->supervisor) {
2344         RET_PRIVOPC(ctx);
2345         return;
2346     }
2347     gen_op_load_gpr_T0(rB(ctx->opcode));
2348     gen_op_tlbie();
2349     RET_STOP(ctx);
2350 #endif
2351 }
2352
2353 /* tlbsync */
2354 GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM)
2355 {
2356 #if defined(CONFIG_USER_ONLY)
2357     RET_PRIVOPC(ctx);
2358 #else
2359     if (!ctx->supervisor) {
2360         RET_PRIVOPC(ctx);
2361         return;
2362     }
2363     /* This has no effect: it should ensure that all previous
2364      * tlbie have completed
2365      */
2366     RET_STOP(ctx);
2367 #endif
2368 }
2369
2370 /***                              External control                         ***/
2371 /* Optional: */
2372 #define op_eciwx() (*gen_op_eciwx[ctx->mem_idx])()
2373 #define op_ecowx() (*gen_op_ecowx[ctx->mem_idx])()
2374 #if defined(CONFIG_USER_ONLY)
2375 static GenOpFunc *gen_op_eciwx[] = {
2376     &gen_op_eciwx_raw,
2377     &gen_op_eciwx_le_raw,
2378 };
2379 static GenOpFunc *gen_op_ecowx[] = {
2380     &gen_op_ecowx_raw,
2381     &gen_op_ecowx_le_raw,
2382 };
2383 #else
2384 static GenOpFunc *gen_op_eciwx[] = {
2385     &gen_op_eciwx_user,
2386     &gen_op_eciwx_le_user,
2387     &gen_op_eciwx_kernel,
2388     &gen_op_eciwx_le_kernel,
2389 };
2390 static GenOpFunc *gen_op_ecowx[] = {
2391     &gen_op_ecowx_user,
2392     &gen_op_ecowx_le_user,
2393     &gen_op_ecowx_kernel,
2394     &gen_op_ecowx_le_kernel,
2395 };
2396 #endif
2397
2398 /* eciwx */
2399 GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN)
2400 {
2401     /* Should check EAR[E] & alignment ! */
2402     if (rA(ctx->opcode) == 0) {
2403         gen_op_load_gpr_T0(rB(ctx->opcode));
2404     } else {
2405         gen_op_load_gpr_T0(rA(ctx->opcode));
2406         gen_op_load_gpr_T1(rB(ctx->opcode));
2407         gen_op_add();
2408     }
2409     op_eciwx();
2410     gen_op_store_T0_gpr(rD(ctx->opcode));
2411 }
2412
2413 /* ecowx */
2414 GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN)
2415 {
2416     /* Should check EAR[E] & alignment ! */
2417     if (rA(ctx->opcode) == 0) {
2418         gen_op_load_gpr_T0(rB(ctx->opcode));
2419     } else {
2420         gen_op_load_gpr_T0(rA(ctx->opcode));
2421         gen_op_load_gpr_T1(rB(ctx->opcode));
2422         gen_op_add();
2423     }
2424     gen_op_load_gpr_T2(rS(ctx->opcode));
2425     op_ecowx();
2426 }
2427
2428 /* End opcode list */
2429 GEN_OPCODE_MARK(end);
2430
2431 #include "translate_init.c"
2432
2433 /*****************************************************************************/
2434 /* Misc PowerPC helpers */
2435 void cpu_dump_state(CPUState *env, FILE *f, 
2436                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
2437                     int flags)
2438 {
2439 #if defined(TARGET_PPC64) || 1
2440 #define FILL ""
2441 #define REGX "%016llx"
2442 #define RGPL  4
2443 #define RFPL  4
2444 #else
2445 #define FILL "        "
2446 #define REGX "%08llx"
2447 #define RGPL  8
2448 #define RFPL  4
2449 #endif
2450
2451     int i;
2452
2453     cpu_fprintf(f, "NIP " REGX " LR " REGX " CTR " REGX "\n",
2454                 env->nip, env->lr, env->ctr);
2455     cpu_fprintf(f, "MSR " REGX FILL " XER %08x      TB %08x %08x DECR %08x\n",
2456                 do_load_msr(env), do_load_xer(env), cpu_ppc_load_tbu(env),
2457                 cpu_ppc_load_tbl(env), cpu_ppc_load_decr(env));
2458         for (i = 0; i < 32; i++) {
2459         if ((i & (RGPL - 1)) == 0)
2460             cpu_fprintf(f, "GPR%02d", i);
2461         cpu_fprintf(f, " " REGX, env->gpr[i]);
2462         if ((i & (RGPL - 1)) == (RGPL - 1))
2463             cpu_fprintf(f, "\n");
2464         }
2465     cpu_fprintf(f, "CR ");
2466         for (i = 0; i < 8; i++)
2467         cpu_fprintf(f, "%01x", env->crf[i]);
2468     cpu_fprintf(f, "  [");
2469         for (i = 0; i < 8; i++) {
2470             char a = '-';
2471             if (env->crf[i] & 0x08)
2472                 a = 'L';
2473             else if (env->crf[i] & 0x04)
2474                 a = 'G';
2475             else if (env->crf[i] & 0x02)
2476                 a = 'E';
2477         cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
2478         }
2479     cpu_fprintf(f, " ]             " FILL "RES " REGX "\n", env->reserve);
2480     for (i = 0; i < 32; i++) {
2481         if ((i & (RFPL - 1)) == 0)
2482             cpu_fprintf(f, "FPR%02d", i);
2483         cpu_fprintf(f, " %016llx", *((uint64_t *)&env->fpr[i]));
2484         if ((i & (RFPL - 1)) == (RFPL - 1))
2485             cpu_fprintf(f, "\n");
2486     }
2487     cpu_fprintf(f, "SRR0 " REGX " SRR1 " REGX "         " FILL FILL FILL
2488                 "SDR1 " REGX "\n",
2489                 env->spr[SPR_SRR0], env->spr[SPR_SRR1], env->sdr1);
2490
2491 #undef REGX
2492 #undef RGPL
2493 #undef RFPL
2494 #undef FILL
2495 }
2496
2497 /*****************************************************************************/
2498 int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
2499                                     int search_pc)
2500 {
2501     DisasContext ctx, *ctxp = &ctx;
2502     opc_handler_t **table, *handler;
2503     target_ulong pc_start;
2504     uint16_t *gen_opc_end;
2505     int j, lj = -1;
2506
2507     pc_start = tb->pc;
2508     gen_opc_ptr = gen_opc_buf;
2509     gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
2510     gen_opparam_ptr = gen_opparam_buf;
2511     nb_gen_labels = 0;
2512     ctx.nip = pc_start;
2513     ctx.tb = tb;
2514     ctx.exception = EXCP_NONE;
2515     ctx.spr_cb = env->spr_cb;
2516 #if defined(CONFIG_USER_ONLY)
2517     ctx.mem_idx = msr_le;
2518 #else
2519     ctx.supervisor = 1 - msr_pr;
2520     ctx.mem_idx = ((1 - msr_pr) << 1) | msr_le;
2521 #endif
2522     ctx.fpu_enabled = msr_fp;
2523 #if defined (DO_SINGLE_STEP) && 0
2524     /* Single step trace mode */
2525     msr_se = 1;
2526 #endif
2527     /* Set env in case of segfault during code fetch */
2528     while (ctx.exception == EXCP_NONE && gen_opc_ptr < gen_opc_end) {
2529         if (search_pc) {
2530             j = gen_opc_ptr - gen_opc_buf;
2531             if (lj < j) {
2532                 lj++;
2533                 while (lj < j)
2534                     gen_opc_instr_start[lj++] = 0;
2535                 gen_opc_pc[lj] = ctx.nip;
2536                 gen_opc_instr_start[lj] = 1;
2537             }
2538         }
2539 #if defined PPC_DEBUG_DISAS
2540         if (loglevel & CPU_LOG_TB_IN_ASM) {
2541             fprintf(logfile, "----------------\n");
2542             fprintf(logfile, "nip=%08x super=%d ir=%d\n",
2543                     ctx.nip, 1 - msr_pr, msr_ir);
2544         }
2545 #endif
2546         ctx.opcode = ldl_code(ctx.nip);
2547         if (msr_le) {
2548             ctx.opcode = ((ctx.opcode & 0xFF000000) >> 24) |
2549                 ((ctx.opcode & 0x00FF0000) >> 8) |
2550                 ((ctx.opcode & 0x0000FF00) << 8) |
2551                 ((ctx.opcode & 0x000000FF) << 24);
2552         }
2553 #if defined PPC_DEBUG_DISAS
2554         if (loglevel & CPU_LOG_TB_IN_ASM) {
2555             fprintf(logfile, "translate opcode %08x (%02x %02x %02x) (%s)\n",
2556                     ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
2557                     opc3(ctx.opcode), msr_le ? "little" : "big");
2558         }
2559 #endif
2560         ctx.nip += 4;
2561         table = env->opcodes;
2562         handler = table[opc1(ctx.opcode)];
2563         if (is_indirect_opcode(handler)) {
2564             table = ind_table(handler);
2565             handler = table[opc2(ctx.opcode)];
2566             if (is_indirect_opcode(handler)) {
2567                 table = ind_table(handler);
2568                 handler = table[opc3(ctx.opcode)];
2569             }
2570         }
2571         /* Is opcode *REALLY* valid ? */
2572                 if (handler->handler == &gen_invalid) {
2573             if (loglevel > 0) {
2574                     fprintf(logfile, "invalid/unsupported opcode: "
2575                         "%02x - %02x - %02x (%08x) 0x%08x %d\n",
2576                             opc1(ctx.opcode), opc2(ctx.opcode),
2577                         opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, msr_ir);
2578             } else {
2579                 printf("invalid/unsupported opcode: "
2580                        "%02x - %02x - %02x (%08x) 0x%08x %d\n",
2581                        opc1(ctx.opcode), opc2(ctx.opcode),
2582                        opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, msr_ir);
2583             }
2584                 } else {
2585             if ((ctx.opcode & handler->inval) != 0) {
2586                 if (loglevel > 0) {
2587                     fprintf(logfile, "invalid bits: %08x for opcode: "
2588                             "%02x -%02x - %02x (0x%08x) (0x%08x)\n",
2589                             ctx.opcode & handler->inval, opc1(ctx.opcode),
2590                             opc2(ctx.opcode), opc3(ctx.opcode),
2591                             ctx.opcode, ctx.nip - 4);
2592                 } else {
2593                     printf("invalid bits: %08x for opcode: "
2594                            "%02x -%02x - %02x (0x%08x) (0x%08x)\n",
2595                             ctx.opcode & handler->inval, opc1(ctx.opcode),
2596                             opc2(ctx.opcode), opc3(ctx.opcode),
2597                            ctx.opcode, ctx.nip - 4);
2598             }
2599                 RET_INVAL(ctxp);
2600                 break;
2601             }
2602         }
2603         (*(handler->handler))(&ctx);
2604         /* Check trace mode exceptions */
2605         if ((msr_be && ctx.exception == EXCP_BRANCH) ||
2606             /* Check in single step trace mode
2607              * we need to stop except if:
2608              * - rfi, trap or syscall
2609              * - first instruction of an exception handler
2610              */
2611             (msr_se && (ctx.nip < 0x100 ||
2612                         ctx.nip > 0xF00 ||
2613                         (ctx.nip & 0xFC) != 0x04) &&
2614              ctx.exception != EXCP_SYSCALL &&
2615              ctx.exception != EXCP_SYSCALL_USER &&
2616              ctx.exception != EXCP_TRAP)) {
2617             RET_EXCP(ctxp, EXCP_TRACE, 0);
2618         }
2619         /* if we reach a page boundary, stop generation */
2620         if ((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) {
2621             break;
2622     }
2623 #if defined (DO_SINGLE_STEP)
2624         break;
2625 #endif
2626     }
2627     if (ctx.exception == EXCP_NONE) {
2628         gen_goto_tb(&ctx, 0, ctx.nip);
2629     } else if (ctx.exception != EXCP_BRANCH) {
2630         gen_op_set_T0(0);
2631     }
2632 #if 1
2633     /* TO BE FIXED: T0 hasn't got a proper value, which makes tb_add_jump
2634      *              do bad business and then qemu crashes !
2635      */
2636     gen_op_set_T0(0);
2637 #endif
2638     /* Generate the return instruction */
2639     gen_op_exit_tb();
2640     *gen_opc_ptr = INDEX_op_end;
2641     if (search_pc) {
2642         j = gen_opc_ptr - gen_opc_buf;
2643         lj++;
2644         while (lj <= j)
2645             gen_opc_instr_start[lj++] = 0;
2646         tb->size = 0;
2647 #if 0
2648         if (loglevel > 0) {
2649             page_dump(logfile);
2650         }
2651 #endif
2652     } else {
2653         tb->size = ctx.nip - pc_start;
2654     }
2655 #ifdef DEBUG_DISAS
2656     if (loglevel & CPU_LOG_TB_CPU) {
2657         fprintf(logfile, "---------------- excp: %04x\n", ctx.exception);
2658         cpu_dump_state(env, logfile, fprintf, 0);
2659     }
2660     if (loglevel & CPU_LOG_TB_IN_ASM) {
2661         fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
2662         target_disas(logfile, pc_start, ctx.nip - pc_start, msr_le);
2663         fprintf(logfile, "\n");
2664     }
2665     if (loglevel & CPU_LOG_TB_OP) {
2666         fprintf(logfile, "OP:\n");
2667         dump_ops(gen_opc_buf, gen_opparam_buf);
2668         fprintf(logfile, "\n");
2669     }
2670 #endif
2671     return 0;
2672 }
2673
2674 int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
2675 {
2676     return gen_intermediate_code_internal(env, tb, 0);
2677 }
2678
2679 int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
2680 {
2681     return gen_intermediate_code_internal(env, tb, 1);
2682 }