Statistics
| Branch: | Revision:

root / target-ppc / translate.c @ 67f36560

History | View | Annotate | Download (96.9 kB)

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
}