Statistics
| Branch: | Revision:

root / target-ppc / translate.c @ 3fc6c082

History | View | Annotate | Download (95.4 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
enum {
34
#define DEF(s, n, copy_size) INDEX_op_ ## s,
35
#include "opc.h"
36
#undef DEF
37
    NB_OPS,
38
};
39

    
40
static uint16_t *gen_opc_ptr;
41
static uint32_t *gen_opparam_ptr;
42

    
43
#include "gen-op.h"
44

    
45
#define GEN8(func, NAME) \
46
static GenOpFunc *NAME ## _table [8] = {                                      \
47
NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3,                                   \
48
NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7,                                   \
49
};                                                                            \
50
static inline void func(int n)                                                \
51
{                                                                             \
52
    NAME ## _table[n]();                                                      \
53
}
54

    
55
#define GEN16(func, NAME)                                                     \
56
static GenOpFunc *NAME ## _table [16] = {                                     \
57
NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3,                                   \
58
NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7,                                   \
59
NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11,                                 \
60
NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
61
};                                                                            \
62
static inline void func(int n)                                                \
63
{                                                                             \
64
    NAME ## _table[n]();                                                      \
65
}
66

    
67
#define GEN32(func, NAME) \
68
static GenOpFunc *NAME ## _table [32] = {                                     \
69
NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3,                                   \
70
NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7,                                   \
71
NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11,                                 \
72
NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
73
NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,                               \
74
NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,                               \
75
NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,                               \
76
NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,                               \
77
};                                                                            \
78
static inline void func(int n)                                                \
79
{                                                                             \
80
    NAME ## _table[n]();                                                      \
81
}
82

    
83
/* Condition register moves */
84
GEN8(gen_op_load_crf_T0, gen_op_load_crf_T0_crf);
85
GEN8(gen_op_load_crf_T1, gen_op_load_crf_T1_crf);
86
GEN8(gen_op_store_T0_crf, gen_op_store_T0_crf_crf);
87
GEN8(gen_op_store_T1_crf, gen_op_store_T1_crf_crf);
88

    
89
/* Floating point condition and status register moves */
90
GEN8(gen_op_load_fpscr_T0, gen_op_load_fpscr_T0_fpscr);
91
GEN8(gen_op_store_T0_fpscr, gen_op_store_T0_fpscr_fpscr);
92
GEN8(gen_op_clear_fpscr, gen_op_clear_fpscr_fpscr);
93
static GenOpFunc1 *gen_op_store_T0_fpscri_fpscr_table[8] = {
94
    &gen_op_store_T0_fpscri_fpscr0,
95
    &gen_op_store_T0_fpscri_fpscr1,
96
    &gen_op_store_T0_fpscri_fpscr2,
97
    &gen_op_store_T0_fpscri_fpscr3,
98
    &gen_op_store_T0_fpscri_fpscr4,
99
    &gen_op_store_T0_fpscri_fpscr5,
100
    &gen_op_store_T0_fpscri_fpscr6,
101
    &gen_op_store_T0_fpscri_fpscr7,
102
};
103
static inline void gen_op_store_T0_fpscri(int n, uint8_t param)
104
{
105
    (*gen_op_store_T0_fpscri_fpscr_table[n])(param);
106
}
107

    
108
/* Segment register moves */
109
GEN16(gen_op_load_sr, gen_op_load_sr);
110
GEN16(gen_op_store_sr, gen_op_store_sr);
111

    
112
/* General purpose registers moves */
113
GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr);
114
GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr);
115
GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr);
116

    
117
GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr);
118
GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr);
119
GEN32(gen_op_store_T2_gpr, gen_op_store_T2_gpr_gpr);
120

    
121
/* floating point registers moves */
122
GEN32(gen_op_load_fpr_FT0, gen_op_load_fpr_FT0_fpr);
123
GEN32(gen_op_load_fpr_FT1, gen_op_load_fpr_FT1_fpr);
124
GEN32(gen_op_load_fpr_FT2, gen_op_load_fpr_FT2_fpr);
125
GEN32(gen_op_store_FT0_fpr, gen_op_store_FT0_fpr_fpr);
126
GEN32(gen_op_store_FT1_fpr, gen_op_store_FT1_fpr_fpr);
127
GEN32(gen_op_store_FT2_fpr, gen_op_store_FT2_fpr_fpr);
128

    
129
static uint8_t  spr_access[1024 / 2];
130

    
131
/* internal defines */
132
typedef struct DisasContext {
133
    struct TranslationBlock *tb;
134
    target_ulong nip;
135
    uint32_t opcode;
136
    uint32_t exception;
137
    /* Routine used to access memory */
138
    int mem_idx;
139
    /* Translation flags */
140
#if !defined(CONFIG_USER_ONLY)
141
    int supervisor;
142
#endif
143
    int fpu_enabled;
144
    ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */
145
} DisasContext;
146

    
147
struct opc_handler_t {
148
    /* invalid bits */
149
    uint32_t inval;
150
    /* instruction type */
151
    uint32_t type;
152
    /* handler */
153
    void (*handler)(DisasContext *ctx);
154
};
155

    
156
#define RET_EXCP(ctx, excp, error)                                            \
157
do {                                                                          \
158
    if ((ctx)->exception == EXCP_NONE) {                                      \
159
        gen_op_update_nip((ctx)->nip);                                        \
160
    }                                                                         \
161
    gen_op_raise_exception_err((excp), (error));                              \
162
    ctx->exception = (excp);                                                  \
163
} while (0)
164

    
165
#define RET_INVAL(ctx)                                                        \
166
RET_EXCP((ctx), EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL)
167

    
168
#define RET_PRIVOPC(ctx)                                                      \
169
RET_EXCP((ctx), EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_OPC)
170

    
171
#define RET_PRIVREG(ctx)                                                      \
172
RET_EXCP((ctx), EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG)
173

    
174
#define RET_MTMSR(ctx)                                                        \
175
RET_EXCP((ctx), EXCP_MTMSR, 0)
176

    
177
static inline void RET_STOP (DisasContext *ctx)
178
{
179
    RET_EXCP(ctx, EXCP_MTMSR, 0);
180
}
181

    
182
#define GEN_HANDLER(name, opc1, opc2, opc3, inval, type)                      \
183
static void gen_##name (DisasContext *ctx);                                   \
184
GEN_OPCODE(name, opc1, opc2, opc3, inval, type);                              \
185
static void gen_##name (DisasContext *ctx)
186

    
187
typedef struct opcode_t {
188
    unsigned char opc1, opc2, opc3;
189
#if HOST_LONG_BITS == 64 /* Explicitely align to 64 bits */
190
    unsigned char pad[5];
191
#else
192
    unsigned char pad[1];
193
#endif
194
    opc_handler_t handler;
195
    const unsigned char *oname;
196
} opcode_t;
197

    
198
/***                           Instruction decoding                        ***/
199
#define EXTRACT_HELPER(name, shift, nb)                                       \
200
static inline uint32_t name (uint32_t opcode)                                 \
201
{                                                                             \
202
    return (opcode >> (shift)) & ((1 << (nb)) - 1);                           \
203
}
204

    
205
#define EXTRACT_SHELPER(name, shift, nb)                                      \
206
static inline int32_t name (uint32_t opcode)                                  \
207
{                                                                             \
208
    return (int16_t)((opcode >> (shift)) & ((1 << (nb)) - 1));                \
209
}
210

    
211
/* Opcode part 1 */
212
EXTRACT_HELPER(opc1, 26, 6);
213
/* Opcode part 2 */
214
EXTRACT_HELPER(opc2, 1, 5);
215
/* Opcode part 3 */
216
EXTRACT_HELPER(opc3, 6, 5);
217
/* Update Cr0 flags */
218
EXTRACT_HELPER(Rc, 0, 1);
219
/* Destination */
220
EXTRACT_HELPER(rD, 21, 5);
221
/* Source */
222
EXTRACT_HELPER(rS, 21, 5);
223
/* First operand */
224
EXTRACT_HELPER(rA, 16, 5);
225
/* Second operand */
226
EXTRACT_HELPER(rB, 11, 5);
227
/* Third operand */
228
EXTRACT_HELPER(rC, 6, 5);
229
/***                               Get CRn                                 ***/
230
EXTRACT_HELPER(crfD, 23, 3);
231
EXTRACT_HELPER(crfS, 18, 3);
232
EXTRACT_HELPER(crbD, 21, 5);
233
EXTRACT_HELPER(crbA, 16, 5);
234
EXTRACT_HELPER(crbB, 11, 5);
235
/* SPR / TBL */
236
EXTRACT_HELPER(_SPR, 11, 10);
237
static inline uint32_t SPR (uint32_t opcode)
238
{
239
    uint32_t sprn = _SPR(opcode);
240

    
241
    return ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
242
}
243
/***                              Get constants                            ***/
244
EXTRACT_HELPER(IMM, 12, 8);
245
/* 16 bits signed immediate value */
246
EXTRACT_SHELPER(SIMM, 0, 16);
247
/* 16 bits unsigned immediate value */
248
EXTRACT_HELPER(UIMM, 0, 16);
249
/* Bit count */
250
EXTRACT_HELPER(NB, 11, 5);
251
/* Shift count */
252
EXTRACT_HELPER(SH, 11, 5);
253
/* Mask start */
254
EXTRACT_HELPER(MB, 6, 5);
255
/* Mask end */
256
EXTRACT_HELPER(ME, 1, 5);
257
/* Trap operand */
258
EXTRACT_HELPER(TO, 21, 5);
259

    
260
EXTRACT_HELPER(CRM, 12, 8);
261
EXTRACT_HELPER(FM, 17, 8);
262
EXTRACT_HELPER(SR, 16, 4);
263
EXTRACT_HELPER(FPIMM, 20, 4);
264

    
265
/***                            Jump target decoding                       ***/
266
/* Displacement */
267
EXTRACT_SHELPER(d, 0, 16);
268
/* Immediate address */
269
static inline uint32_t LI (uint32_t opcode)
270
{
271
    return (opcode >> 0) & 0x03FFFFFC;
272
}
273

    
274
static inline uint32_t BD (uint32_t opcode)
275
{
276
    return (opcode >> 0) & 0xFFFC;
277
}
278

    
279
EXTRACT_HELPER(BO, 21, 5);
280
EXTRACT_HELPER(BI, 16, 5);
281
/* Absolute/relative address */
282
EXTRACT_HELPER(AA, 1, 1);
283
/* Link */
284
EXTRACT_HELPER(LK, 0, 1);
285

    
286
/* Create a mask between <start> and <end> bits */
287
static inline uint32_t MASK (uint32_t start, uint32_t end)
288
{
289
    uint32_t ret;
290

    
291
    ret = (((uint32_t)(-1)) >> (start)) ^ (((uint32_t)(-1) >> (end)) >> 1);
292
    if (start > end)
293
        return ~ret;
294

    
295
    return ret;
296
}
297

    
298
#if HOST_LONG_BITS == 64
299
#define OPC_ALIGN 8
300
#else
301
#define OPC_ALIGN 4
302
#endif
303
#if defined(__APPLE__)
304
#define OPCODES_SECTION \
305
    __attribute__ ((section("__TEXT,__opcodes"), unused, aligned (OPC_ALIGN) ))
306
#else
307
#define OPCODES_SECTION \
308
    __attribute__ ((section(".opcodes"), unused, aligned (OPC_ALIGN) ))
309
#endif
310

    
311
#define GEN_OPCODE(name, op1, op2, op3, invl, _typ)                           \
312
OPCODES_SECTION opcode_t opc_##name = {                                       \
313
    .opc1 = op1,                                                              \
314
    .opc2 = op2,                                                              \
315
    .opc3 = op3,                                                              \
316
    .pad  = { 0, },                                                           \
317
    .handler = {                                                              \
318
        .inval   = invl,                                                      \
319
        .type = _typ,                                                         \
320
        .handler = &gen_##name,                                               \
321
    },                                                                        \
322
    .oname = stringify(name),                                                 \
323
}
324

    
325
#define GEN_OPCODE_MARK(name)                                                 \
326
OPCODES_SECTION opcode_t opc_##name = {                                       \
327
    .opc1 = 0xFF,                                                             \
328
    .opc2 = 0xFF,                                                             \
329
    .opc3 = 0xFF,                                                             \
330
    .pad  = { 0, },                                                           \
331
    .handler = {                                                              \
332
        .inval   = 0x00000000,                                                \
333
        .type = 0x00,                                                         \
334
        .handler = NULL,                                                      \
335
    },                                                                        \
336
    .oname = stringify(name),                                                 \
337
}
338

    
339
/* Start opcode list */
340
GEN_OPCODE_MARK(start);
341

    
342
/* Invalid instruction */
343
GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE)
344
{
345
    RET_INVAL(ctx);
346
}
347

    
348
static opc_handler_t invalid_handler = {
349
    .inval   = 0xFFFFFFFF,
350
    .type    = PPC_NONE,
351
    .handler = gen_invalid,
352
};
353

    
354
/***                           Integer arithmetic                          ***/
355
#define __GEN_INT_ARITH2(name, opc1, opc2, opc3, inval)                       \
356
GEN_HANDLER(name, opc1, opc2, opc3, inval, PPC_INTEGER)                       \
357
{                                                                             \
358
    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
359
    gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
360
    gen_op_##name();                                                          \
361
    if (Rc(ctx->opcode) != 0)                                                 \
362
        gen_op_set_Rc0();                                                     \
363
    gen_op_store_T0_gpr(rD(ctx->opcode));                                     \
364
}
365

    
366
#define __GEN_INT_ARITH2_O(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_ARITH1(name, opc1, opc2, opc3)                              \
378
GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, PPC_INTEGER)                  \
379
{                                                                             \
380
    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
381
    gen_op_##name();                                                          \
382
    if (Rc(ctx->opcode) != 0)                                                 \
383
        gen_op_set_Rc0();                                                     \
384
    gen_op_store_T0_gpr(rD(ctx->opcode));                                     \
385
}
386
#define __GEN_INT_ARITH1_O(name, opc1, opc2, opc3)                            \
387
GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, PPC_INTEGER)                  \
388
{                                                                             \
389
    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
390
    gen_op_##name();                                                          \
391
    if (Rc(ctx->opcode) != 0)                                                 \
392
        gen_op_set_Rc0();                                                     \
393
    gen_op_store_T0_gpr(rD(ctx->opcode));                                     \
394
}
395

    
396
/* Two operands arithmetic functions */
397
#define GEN_INT_ARITH2(name, opc1, opc2, opc3)                                \
398
__GEN_INT_ARITH2(name, opc1, opc2, opc3, 0x00000000)                          \
399
__GEN_INT_ARITH2_O(name##o, opc1, opc2, opc3 | 0x10, 0x00000000)
400

    
401
/* Two operands arithmetic functions with no overflow allowed */
402
#define GEN_INT_ARITHN(name, opc1, opc2, opc3)                                \
403
__GEN_INT_ARITH2(name, opc1, opc2, opc3, 0x00000400)
404

    
405
/* One operand arithmetic functions */
406
#define GEN_INT_ARITH1(name, opc1, opc2, opc3)                                \
407
__GEN_INT_ARITH1(name, opc1, opc2, opc3)                                      \
408
__GEN_INT_ARITH1_O(name##o, opc1, opc2, opc3 | 0x10)
409

    
410
/* add    add.    addo    addo.    */
411
GEN_INT_ARITH2 (add,    0x1F, 0x0A, 0x08);
412
/* addc   addc.   addco   addco.   */
413
GEN_INT_ARITH2 (addc,   0x1F, 0x0A, 0x00);
414
/* adde   adde.   addeo   addeo.   */
415
GEN_INT_ARITH2 (adde,   0x1F, 0x0A, 0x04);
416
/* addme  addme.  addmeo  addmeo.  */
417
GEN_INT_ARITH1 (addme,  0x1F, 0x0A, 0x07);
418
/* addze  addze.  addzeo  addzeo.  */
419
GEN_INT_ARITH1 (addze,  0x1F, 0x0A, 0x06);
420
/* divw   divw.   divwo   divwo.   */
421
GEN_INT_ARITH2 (divw,   0x1F, 0x0B, 0x0F);
422
/* divwu  divwu.  divwuo  divwuo.  */
423
GEN_INT_ARITH2 (divwu,  0x1F, 0x0B, 0x0E);
424
/* mulhw  mulhw.                   */
425
GEN_INT_ARITHN (mulhw,  0x1F, 0x0B, 0x02);
426
/* mulhwu mulhwu.                  */
427
GEN_INT_ARITHN (mulhwu, 0x1F, 0x0B, 0x00);
428
/* mullw  mullw.  mullwo  mullwo.  */
429
GEN_INT_ARITH2 (mullw,  0x1F, 0x0B, 0x07);
430
/* neg    neg.    nego    nego.    */
431
GEN_INT_ARITH1 (neg,    0x1F, 0x08, 0x03);
432
/* subf   subf.   subfo   subfo.   */
433
GEN_INT_ARITH2 (subf,   0x1F, 0x08, 0x01);
434
/* subfc  subfc.  subfco  subfco.  */
435
GEN_INT_ARITH2 (subfc,  0x1F, 0x08, 0x00);
436
/* subfe  subfe.  subfeo  subfeo.  */
437
GEN_INT_ARITH2 (subfe,  0x1F, 0x08, 0x04);
438
/* subfme subfme. subfmeo subfmeo. */
439
GEN_INT_ARITH1 (subfme, 0x1F, 0x08, 0x07);
440
/* subfze subfze. subfzeo subfzeo. */
441
GEN_INT_ARITH1 (subfze, 0x1F, 0x08, 0x06);
442
/* addi */
443
GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
444
{
445
    int32_t simm = SIMM(ctx->opcode);
446

    
447
    if (rA(ctx->opcode) == 0) {
448
        gen_op_set_T0(simm);
449
    } else {
450
        gen_op_load_gpr_T0(rA(ctx->opcode));
451
        gen_op_addi(simm);
452
    }
453
    gen_op_store_T0_gpr(rD(ctx->opcode));
454
}
455
/* addic */
456
GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
457
{
458
    gen_op_load_gpr_T0(rA(ctx->opcode));
459
    gen_op_addic(SIMM(ctx->opcode));
460
    gen_op_store_T0_gpr(rD(ctx->opcode));
461
}
462
/* addic. */
463
GEN_HANDLER(addic_, 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
464
{
465
    gen_op_load_gpr_T0(rA(ctx->opcode));
466
    gen_op_addic(SIMM(ctx->opcode));
467
    gen_op_set_Rc0();
468
    gen_op_store_T0_gpr(rD(ctx->opcode));
469
}
470
/* addis */
471
GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
472
{
473
    int32_t simm = SIMM(ctx->opcode);
474

    
475
    if (rA(ctx->opcode) == 0) {
476
        gen_op_set_T0(simm << 16);
477
    } else {
478
        gen_op_load_gpr_T0(rA(ctx->opcode));
479
        gen_op_addi(simm << 16);
480
    }
481
    gen_op_store_T0_gpr(rD(ctx->opcode));
482
}
483
/* mulli */
484
GEN_HANDLER(mulli, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
485
{
486
    gen_op_load_gpr_T0(rA(ctx->opcode));
487
    gen_op_mulli(SIMM(ctx->opcode));
488
    gen_op_store_T0_gpr(rD(ctx->opcode));
489
}
490
/* subfic */
491
GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
492
{
493
    gen_op_load_gpr_T0(rA(ctx->opcode));
494
    gen_op_subfic(SIMM(ctx->opcode));
495
    gen_op_store_T0_gpr(rD(ctx->opcode));
496
}
497

    
498
/***                           Integer comparison                          ***/
499
#define GEN_CMP(name, opc)                                                    \
500
GEN_HANDLER(name, 0x1F, 0x00, opc, 0x00400000, PPC_INTEGER)                   \
501
{                                                                             \
502
    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
503
    gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
504
    gen_op_##name();                                                          \
505
    gen_op_store_T0_crf(crfD(ctx->opcode));                                   \
506
}
507

    
508
/* cmp */
509
GEN_CMP(cmp, 0x00);
510
/* cmpi */
511
GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
512
{
513
    gen_op_load_gpr_T0(rA(ctx->opcode));
514
    gen_op_cmpi(SIMM(ctx->opcode));
515
    gen_op_store_T0_crf(crfD(ctx->opcode));
516
}
517
/* cmpl */
518
GEN_CMP(cmpl, 0x01);
519
/* cmpli */
520
GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
521
{
522
    gen_op_load_gpr_T0(rA(ctx->opcode));
523
    gen_op_cmpli(UIMM(ctx->opcode));
524
    gen_op_store_T0_crf(crfD(ctx->opcode));
525
}
526

    
527
/***                            Integer logical                            ***/
528
#define __GEN_LOGICAL2(name, opc2, opc3)                                      \
529
GEN_HANDLER(name, 0x1F, opc2, opc3, 0x00000000, PPC_INTEGER)                  \
530
{                                                                             \
531
    gen_op_load_gpr_T0(rS(ctx->opcode));                                      \
532
    gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
533
    gen_op_##name();                                                          \
534
    if (Rc(ctx->opcode) != 0)                                                 \
535
        gen_op_set_Rc0();                                                     \
536
    gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
537
}
538
#define GEN_LOGICAL2(name, opc)                                               \
539
__GEN_LOGICAL2(name, 0x1C, opc)
540

    
541
#define GEN_LOGICAL1(name, opc)                                               \
542
GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, PPC_INTEGER)                   \
543
{                                                                             \
544
    gen_op_load_gpr_T0(rS(ctx->opcode));                                      \
545
    gen_op_##name();                                                          \
546
    if (Rc(ctx->opcode) != 0)                                                 \
547
        gen_op_set_Rc0();                                                     \
548
    gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
549
}
550

    
551
/* and & and. */
552
GEN_LOGICAL2(and, 0x00);
553
/* andc & andc. */
554
GEN_LOGICAL2(andc, 0x01);
555
/* andi. */
556
GEN_HANDLER(andi_, 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
557
{
558
    gen_op_load_gpr_T0(rS(ctx->opcode));
559
    gen_op_andi_(UIMM(ctx->opcode));
560
    gen_op_set_Rc0();
561
    gen_op_store_T0_gpr(rA(ctx->opcode));
562
}
563
/* andis. */
564
GEN_HANDLER(andis_, 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
565
{
566
    gen_op_load_gpr_T0(rS(ctx->opcode));
567
    gen_op_andi_(UIMM(ctx->opcode) << 16);
568
    gen_op_set_Rc0();
569
    gen_op_store_T0_gpr(rA(ctx->opcode));
570
}
571

    
572
/* cntlzw */
573
GEN_LOGICAL1(cntlzw, 0x00);
574
/* eqv & eqv. */
575
GEN_LOGICAL2(eqv, 0x08);
576
/* extsb & extsb. */
577
GEN_LOGICAL1(extsb, 0x1D);
578
/* extsh & extsh. */
579
GEN_LOGICAL1(extsh, 0x1C);
580
/* nand & nand. */
581
GEN_LOGICAL2(nand, 0x0E);
582
/* nor & nor. */
583
GEN_LOGICAL2(nor, 0x03);
584

    
585
/* or & or. */
586
GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER)
587
{
588
    gen_op_load_gpr_T0(rS(ctx->opcode));
589
    /* Optimisation for mr case */
590
    if (rS(ctx->opcode) != rB(ctx->opcode)) {
591
        gen_op_load_gpr_T1(rB(ctx->opcode));
592
        gen_op_or();
593
    }
594
    if (Rc(ctx->opcode) != 0)
595
        gen_op_set_Rc0();
596
    gen_op_store_T0_gpr(rA(ctx->opcode));
597
}
598

    
599
/* orc & orc. */
600
GEN_LOGICAL2(orc, 0x0C);
601
/* xor & xor. */
602
GEN_HANDLER(xor, 0x1F, 0x1C, 0x09, 0x00000000, PPC_INTEGER)
603
{
604
    gen_op_load_gpr_T0(rS(ctx->opcode));
605
    /* Optimisation for "set to zero" case */
606
    if (rS(ctx->opcode) != rB(ctx->opcode)) {
607
        gen_op_load_gpr_T1(rB(ctx->opcode));
608
        gen_op_xor();
609
    } else {
610
        gen_op_set_T0(0);
611
    }
612
    if (Rc(ctx->opcode) != 0)
613
        gen_op_set_Rc0();
614
    gen_op_store_T0_gpr(rA(ctx->opcode));
615
}
616
/* ori */
617
GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
618
{
619
    uint32_t uimm = UIMM(ctx->opcode);
620

    
621
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
622
        /* NOP */
623
        return;
624
        }
625
        gen_op_load_gpr_T0(rS(ctx->opcode));
626
    if (uimm != 0)
627
        gen_op_ori(uimm);
628
        gen_op_store_T0_gpr(rA(ctx->opcode));
629
}
630
/* oris */
631
GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
632
{
633
    uint32_t uimm = UIMM(ctx->opcode);
634

    
635
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
636
        /* NOP */
637
        return;
638
        }
639
        gen_op_load_gpr_T0(rS(ctx->opcode));
640
    if (uimm != 0)
641
        gen_op_ori(uimm << 16);
642
        gen_op_store_T0_gpr(rA(ctx->opcode));
643
}
644
/* xori */
645
GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
646
{
647
    uint32_t uimm = UIMM(ctx->opcode);
648

    
649
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
650
        /* NOP */
651
        return;
652
    }
653
    gen_op_load_gpr_T0(rS(ctx->opcode));
654
    if (uimm != 0)
655
    gen_op_xori(uimm);
656
    gen_op_store_T0_gpr(rA(ctx->opcode));
657
}
658

    
659
/* xoris */
660
GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
661
{
662
    uint32_t uimm = UIMM(ctx->opcode);
663

    
664
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
665
        /* NOP */
666
        return;
667
    }
668
    gen_op_load_gpr_T0(rS(ctx->opcode));
669
    if (uimm != 0)
670
    gen_op_xori(uimm << 16);
671
    gen_op_store_T0_gpr(rA(ctx->opcode));
672
}
673

    
674
/***                             Integer rotate                            ***/
675
/* rlwimi & rlwimi. */
676
GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
677
{
678
    uint32_t mb, me;
679

    
680
    mb = MB(ctx->opcode);
681
    me = ME(ctx->opcode);
682
    gen_op_load_gpr_T0(rS(ctx->opcode));
683
    gen_op_load_gpr_T1(rA(ctx->opcode));
684
    gen_op_rlwimi(SH(ctx->opcode), MASK(mb, me), ~MASK(mb, me));
685
    if (Rc(ctx->opcode) != 0)
686
        gen_op_set_Rc0();
687
    gen_op_store_T0_gpr(rA(ctx->opcode));
688
}
689
/* rlwinm & rlwinm. */
690
GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
691
{
692
    uint32_t mb, me, sh;
693
    
694
    sh = SH(ctx->opcode);
695
    mb = MB(ctx->opcode);
696
    me = ME(ctx->opcode);
697
    gen_op_load_gpr_T0(rS(ctx->opcode));
698
#if 1 // TRY
699
    if (sh == 0) {
700
        gen_op_andi_(MASK(mb, me));
701
        goto store;
702
    }
703
#endif
704
    if (mb == 0) {
705
        if (me == 31) {
706
            gen_op_rotlwi(sh);
707
            goto store;
708
#if 0
709
        } else if (me == (31 - sh)) {
710
            gen_op_slwi(sh);
711
            goto store;
712
#endif
713
        }
714
    } else if (me == 31) {
715
#if 0
716
        if (sh == (32 - mb)) {
717
            gen_op_srwi(mb);
718
            goto store;
719
        }
720
#endif
721
    }
722
    gen_op_rlwinm(sh, MASK(mb, me));
723
store:
724
    if (Rc(ctx->opcode) != 0)
725
        gen_op_set_Rc0();
726
    gen_op_store_T0_gpr(rA(ctx->opcode));
727
}
728
/* rlwnm & rlwnm. */
729
GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
730
{
731
    uint32_t mb, me;
732

    
733
    mb = MB(ctx->opcode);
734
    me = ME(ctx->opcode);
735
    gen_op_load_gpr_T0(rS(ctx->opcode));
736
    gen_op_load_gpr_T1(rB(ctx->opcode));
737
    if (mb == 0 && me == 31) {
738
        gen_op_rotl();
739
    } else
740
    {
741
        gen_op_rlwnm(MASK(mb, me));
742
    }
743
    if (Rc(ctx->opcode) != 0)
744
        gen_op_set_Rc0();
745
    gen_op_store_T0_gpr(rA(ctx->opcode));
746
}
747

    
748
/***                             Integer shift                             ***/
749
/* slw & slw. */
750
__GEN_LOGICAL2(slw, 0x18, 0x00);
751
/* sraw & sraw. */
752
__GEN_LOGICAL2(sraw, 0x18, 0x18);
753
/* srawi & srawi. */
754
GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER)
755
{
756
    gen_op_load_gpr_T0(rS(ctx->opcode));
757
    if (SH(ctx->opcode) != 0)
758
    gen_op_srawi(SH(ctx->opcode), MASK(32 - SH(ctx->opcode), 31));
759
    if (Rc(ctx->opcode) != 0)
760
        gen_op_set_Rc0();
761
    gen_op_store_T0_gpr(rA(ctx->opcode));
762
}
763
/* srw & srw. */
764
__GEN_LOGICAL2(srw, 0x18, 0x10);
765

    
766
/***                       Floating-Point arithmetic                       ***/
767
#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat)                           \
768
GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, PPC_FLOAT)                   \
769
{                                                                             \
770
    if (!ctx->fpu_enabled) {                                                  \
771
        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
772
        return;                                                               \
773
    }                                                                         \
774
    gen_op_reset_scrfx();                                                     \
775
    gen_op_load_fpr_FT0(rA(ctx->opcode));                                     \
776
    gen_op_load_fpr_FT1(rC(ctx->opcode));                                     \
777
    gen_op_load_fpr_FT2(rB(ctx->opcode));                                     \
778
    gen_op_f##op();                                                           \
779
    if (isfloat) {                                                            \
780
        gen_op_frsp();                                                        \
781
    }                                                                         \
782
    gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
783
    if (Rc(ctx->opcode))                                                      \
784
        gen_op_set_Rc1();                                                     \
785
}
786

    
787
#define GEN_FLOAT_ACB(name, op2)                                              \
788
_GEN_FLOAT_ACB(name, name, 0x3F, op2, 0);                                     \
789
_GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1);
790

    
791
#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat)                     \
792
GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT)                        \
793
{                                                                             \
794
    if (!ctx->fpu_enabled) {                                                  \
795
        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
796
        return;                                                               \
797
    }                                                                         \
798
    gen_op_reset_scrfx();                                                     \
799
    gen_op_load_fpr_FT0(rA(ctx->opcode));                                     \
800
    gen_op_load_fpr_FT1(rB(ctx->opcode));                                     \
801
    gen_op_f##op();                                                           \
802
    if (isfloat) {                                                            \
803
        gen_op_frsp();                                                        \
804
    }                                                                         \
805
    gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
806
    if (Rc(ctx->opcode))                                                      \
807
        gen_op_set_Rc1();                                                     \
808
}
809
#define GEN_FLOAT_AB(name, op2, inval)                                        \
810
_GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0);                               \
811
_GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1);
812

    
813
#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat)                     \
814
GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT)                        \
815
{                                                                             \
816
    if (!ctx->fpu_enabled) {                                                  \
817
        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
818
        return;                                                               \
819
    }                                                                         \
820
    gen_op_reset_scrfx();                                                     \
821
    gen_op_load_fpr_FT0(rA(ctx->opcode));                                     \
822
    gen_op_load_fpr_FT1(rC(ctx->opcode));                                     \
823
    gen_op_f##op();                                                           \
824
    if (isfloat) {                                                            \
825
        gen_op_frsp();                                                        \
826
    }                                                                         \
827
    gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
828
    if (Rc(ctx->opcode))                                                      \
829
        gen_op_set_Rc1();                                                     \
830
}
831
#define GEN_FLOAT_AC(name, op2, inval)                                        \
832
_GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0);                               \
833
_GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1);
834

    
835
#define GEN_FLOAT_B(name, op2, op3)                                           \
836
GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, PPC_FLOAT)                   \
837
{                                                                             \
838
    if (!ctx->fpu_enabled) {                                                  \
839
        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
840
        return;                                                               \
841
    }                                                                         \
842
    gen_op_reset_scrfx();                                                     \
843
    gen_op_load_fpr_FT0(rB(ctx->opcode));                                     \
844
    gen_op_f##name();                                                         \
845
    gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
846
    if (Rc(ctx->opcode))                                                      \
847
        gen_op_set_Rc1();                                                     \
848
}
849

    
850
#define GEN_FLOAT_BS(name, op1, op2)                                          \
851
GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, PPC_FLOAT)                   \
852
{                                                                             \
853
    if (!ctx->fpu_enabled) {                                                  \
854
        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
855
        return;                                                               \
856
    }                                                                         \
857
    gen_op_reset_scrfx();                                                     \
858
    gen_op_load_fpr_FT0(rB(ctx->opcode));                                     \
859
    gen_op_f##name();                                                         \
860
    gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
861
    if (Rc(ctx->opcode))                                                      \
862
        gen_op_set_Rc1();                                                     \
863
}
864

    
865
/* fadd - fadds */
866
GEN_FLOAT_AB(add, 0x15, 0x000007C0);
867
/* fdiv - fdivs */
868
GEN_FLOAT_AB(div, 0x12, 0x000007C0);
869
/* fmul - fmuls */
870
GEN_FLOAT_AC(mul, 0x19, 0x0000F800);
871

    
872
/* fres */
873
GEN_FLOAT_BS(res, 0x3B, 0x18);
874

    
875
/* frsqrte */
876
GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A);
877

    
878
/* fsel */
879
_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0);
880
/* fsub - fsubs */
881
GEN_FLOAT_AB(sub, 0x14, 0x000007C0);
882
/* Optional: */
883
/* fsqrt */
884
GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_OPT)
885
{
886
    if (!ctx->fpu_enabled) {
887
        RET_EXCP(ctx, EXCP_NO_FP, 0);
888
        return;
889
    }
890
    gen_op_reset_scrfx();
891
    gen_op_load_fpr_FT0(rB(ctx->opcode));
892
    gen_op_fsqrt();
893
    gen_op_store_FT0_fpr(rD(ctx->opcode));
894
    if (Rc(ctx->opcode))
895
        gen_op_set_Rc1();
896
}
897

    
898
GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_OPT)
899
{
900
    if (!ctx->fpu_enabled) {
901
        RET_EXCP(ctx, EXCP_NO_FP, 0);
902
        return;
903
    }
904
    gen_op_reset_scrfx();
905
    gen_op_load_fpr_FT0(rB(ctx->opcode));
906
    gen_op_fsqrt();
907
    gen_op_frsp();
908
    gen_op_store_FT0_fpr(rD(ctx->opcode));
909
    if (Rc(ctx->opcode))
910
        gen_op_set_Rc1();
911
}
912

    
913
/***                     Floating-Point multiply-and-add                   ***/
914
/* fmadd - fmadds */
915
GEN_FLOAT_ACB(madd, 0x1D);
916
/* fmsub - fmsubs */
917
GEN_FLOAT_ACB(msub, 0x1C);
918
/* fnmadd - fnmadds */
919
GEN_FLOAT_ACB(nmadd, 0x1F);
920
/* fnmsub - fnmsubs */
921
GEN_FLOAT_ACB(nmsub, 0x1E);
922

    
923
/***                     Floating-Point round & convert                    ***/
924
/* fctiw */
925
GEN_FLOAT_B(ctiw, 0x0E, 0x00);
926
/* fctiwz */
927
GEN_FLOAT_B(ctiwz, 0x0F, 0x00);
928
/* frsp */
929
GEN_FLOAT_B(rsp, 0x0C, 0x00);
930

    
931
/***                         Floating-Point compare                        ***/
932
/* fcmpo */
933
GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT)
934
{
935
    if (!ctx->fpu_enabled) {
936
        RET_EXCP(ctx, EXCP_NO_FP, 0);
937
        return;
938
    }
939
    gen_op_reset_scrfx();
940
    gen_op_load_fpr_FT0(rA(ctx->opcode));
941
    gen_op_load_fpr_FT1(rB(ctx->opcode));
942
    gen_op_fcmpo();
943
    gen_op_store_T0_crf(crfD(ctx->opcode));
944
}
945

    
946
/* fcmpu */
947
GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT)
948
{
949
    if (!ctx->fpu_enabled) {
950
        RET_EXCP(ctx, EXCP_NO_FP, 0);
951
        return;
952
    }
953
    gen_op_reset_scrfx();
954
    gen_op_load_fpr_FT0(rA(ctx->opcode));
955
    gen_op_load_fpr_FT1(rB(ctx->opcode));
956
    gen_op_fcmpu();
957
    gen_op_store_T0_crf(crfD(ctx->opcode));
958
}
959

    
960
/***                         Floating-point move                           ***/
961
/* fabs */
962
GEN_FLOAT_B(abs, 0x08, 0x08);
963

    
964
/* fmr  - fmr. */
965
GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT)
966
{
967
    if (!ctx->fpu_enabled) {
968
        RET_EXCP(ctx, EXCP_NO_FP, 0);
969
        return;
970
    }
971
    gen_op_reset_scrfx();
972
    gen_op_load_fpr_FT0(rB(ctx->opcode));
973
    gen_op_store_FT0_fpr(rD(ctx->opcode));
974
    if (Rc(ctx->opcode))
975
        gen_op_set_Rc1();
976
}
977

    
978
/* fnabs */
979
GEN_FLOAT_B(nabs, 0x08, 0x04);
980
/* fneg */
981
GEN_FLOAT_B(neg, 0x08, 0x01);
982

    
983
/***                  Floating-Point status & ctrl register                ***/
984
/* mcrfs */
985
GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT)
986
{
987
    if (!ctx->fpu_enabled) {
988
        RET_EXCP(ctx, EXCP_NO_FP, 0);
989
        return;
990
    }
991
    gen_op_load_fpscr_T0(crfS(ctx->opcode));
992
    gen_op_store_T0_crf(crfD(ctx->opcode));
993
    gen_op_clear_fpscr(crfS(ctx->opcode));
994
}
995

    
996
/* mffs */
997
GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT)
998
{
999
    if (!ctx->fpu_enabled) {
1000
        RET_EXCP(ctx, EXCP_NO_FP, 0);
1001
        return;
1002
    }
1003
    gen_op_load_fpscr();
1004
    gen_op_store_FT0_fpr(rD(ctx->opcode));
1005
    if (Rc(ctx->opcode))
1006
        gen_op_set_Rc1();
1007
}
1008

    
1009
/* mtfsb0 */
1010
GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT)
1011
{
1012
    uint8_t crb;
1013
    
1014
    if (!ctx->fpu_enabled) {
1015
        RET_EXCP(ctx, EXCP_NO_FP, 0);
1016
        return;
1017
    }
1018
    crb = crbD(ctx->opcode) >> 2;
1019
    gen_op_load_fpscr_T0(crb);
1020
    gen_op_andi_(~(1 << (crbD(ctx->opcode) & 0x03)));
1021
    gen_op_store_T0_fpscr(crb);
1022
    if (Rc(ctx->opcode))
1023
        gen_op_set_Rc1();
1024
}
1025

    
1026
/* mtfsb1 */
1027
GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT)
1028
{
1029
    uint8_t crb;
1030
    
1031
    if (!ctx->fpu_enabled) {
1032
        RET_EXCP(ctx, EXCP_NO_FP, 0);
1033
        return;
1034
    }
1035
    crb = crbD(ctx->opcode) >> 2;
1036
    gen_op_load_fpscr_T0(crb);
1037
    gen_op_ori(1 << (crbD(ctx->opcode) & 0x03));
1038
    gen_op_store_T0_fpscr(crb);
1039
    if (Rc(ctx->opcode))
1040
        gen_op_set_Rc1();
1041
}
1042

    
1043
/* mtfsf */
1044
GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT)
1045
{
1046
    if (!ctx->fpu_enabled) {
1047
        RET_EXCP(ctx, EXCP_NO_FP, 0);
1048
        return;
1049
    }
1050
    gen_op_load_fpr_FT0(rB(ctx->opcode));
1051
    gen_op_store_fpscr(FM(ctx->opcode));
1052
    if (Rc(ctx->opcode))
1053
        gen_op_set_Rc1();
1054
}
1055

    
1056
/* mtfsfi */
1057
GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT)
1058
{
1059
    if (!ctx->fpu_enabled) {
1060
        RET_EXCP(ctx, EXCP_NO_FP, 0);
1061
        return;
1062
    }
1063
    gen_op_store_T0_fpscri(crbD(ctx->opcode) >> 2, FPIMM(ctx->opcode));
1064
    if (Rc(ctx->opcode))
1065
        gen_op_set_Rc1();
1066
}
1067

    
1068
/***                             Integer load                              ***/
1069
#define op_ldst(name)        (*gen_op_##name[ctx->mem_idx])()
1070
#if defined(CONFIG_USER_ONLY)
1071
#define OP_LD_TABLE(width)                                                    \
1072
static GenOpFunc *gen_op_l##width[] = {                                       \
1073
    &gen_op_l##width##_raw,                                                   \
1074
    &gen_op_l##width##_le_raw,                                                \
1075
};
1076
#define OP_ST_TABLE(width)                                                    \
1077
static GenOpFunc *gen_op_st##width[] = {                                      \
1078
    &gen_op_st##width##_raw,                                                  \
1079
    &gen_op_st##width##_le_raw,                                               \
1080
};
1081
/* Byte access routine are endian safe */
1082
#define gen_op_stb_le_raw gen_op_stb_raw
1083
#define gen_op_lbz_le_raw gen_op_lbz_raw
1084
#else
1085
#define OP_LD_TABLE(width)                                                    \
1086
static GenOpFunc *gen_op_l##width[] = {                                       \
1087
    &gen_op_l##width##_user,                                                  \
1088
    &gen_op_l##width##_le_user,                                               \
1089
    &gen_op_l##width##_kernel,                                                \
1090
    &gen_op_l##width##_le_kernel,                                             \
1091
};
1092
#define OP_ST_TABLE(width)                                                    \
1093
static GenOpFunc *gen_op_st##width[] = {                                      \
1094
    &gen_op_st##width##_user,                                                 \
1095
    &gen_op_st##width##_le_user,                                              \
1096
    &gen_op_st##width##_kernel,                                               \
1097
    &gen_op_st##width##_le_kernel,                                            \
1098
};
1099
/* Byte access routine are endian safe */
1100
#define gen_op_stb_le_user gen_op_stb_user
1101
#define gen_op_lbz_le_user gen_op_lbz_user
1102
#define gen_op_stb_le_kernel gen_op_stb_kernel
1103
#define gen_op_lbz_le_kernel gen_op_lbz_kernel
1104
#endif
1105

    
1106
#define GEN_LD(width, opc)                                                    \
1107
GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)               \
1108
{                                                                             \
1109
    uint32_t simm = SIMM(ctx->opcode);                                        \
1110
    if (rA(ctx->opcode) == 0) {                                               \
1111
        gen_op_set_T0(simm);                                                  \
1112
    } else {                                                                  \
1113
        gen_op_load_gpr_T0(rA(ctx->opcode));                                  \
1114
        if (simm != 0)                                                        \
1115
            gen_op_addi(simm);                                                \
1116
    }                                                                         \
1117
    op_ldst(l##width);                                                        \
1118
    gen_op_store_T1_gpr(rD(ctx->opcode));                                     \
1119
}
1120

    
1121
#define GEN_LDU(width, opc)                                                   \
1122
GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)            \
1123
{                                                                             \
1124
    uint32_t simm = SIMM(ctx->opcode);                                        \
1125
    if (rA(ctx->opcode) == 0 ||                                               \
1126
        rA(ctx->opcode) == rD(ctx->opcode)) {                                 \
1127
        RET_INVAL(ctx);                                                       \
1128
        return;                                                               \
1129
    }                                                                         \
1130
    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
1131
    if (simm != 0)                                                            \
1132
        gen_op_addi(simm);                                                    \
1133
    op_ldst(l##width);                                                        \
1134
    gen_op_store_T1_gpr(rD(ctx->opcode));                                     \
1135
    gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
1136
}
1137

    
1138
#define GEN_LDUX(width, opc)                                                  \
1139
GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER)           \
1140
{                                                                             \
1141
    if (rA(ctx->opcode) == 0 ||                                               \
1142
        rA(ctx->opcode) == rD(ctx->opcode)) {                                 \
1143
        RET_INVAL(ctx);                                                       \
1144
        return;                                                               \
1145
    }                                                                         \
1146
    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
1147
    gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
1148
    gen_op_add();                                                             \
1149
    op_ldst(l##width);                                                        \
1150
    gen_op_store_T1_gpr(rD(ctx->opcode));                                     \
1151
    gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
1152
}
1153

    
1154
#define GEN_LDX(width, opc2, opc3)                                            \
1155
GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER)           \
1156
{                                                                             \
1157
    if (rA(ctx->opcode) == 0) {                                               \
1158
        gen_op_load_gpr_T0(rB(ctx->opcode));                                  \
1159
    } else {                                                                  \
1160
        gen_op_load_gpr_T0(rA(ctx->opcode));                                  \
1161
        gen_op_load_gpr_T1(rB(ctx->opcode));                                  \
1162
        gen_op_add();                                                         \
1163
    }                                                                         \
1164
    op_ldst(l##width);                                                        \
1165
    gen_op_store_T1_gpr(rD(ctx->opcode));                                     \
1166
}
1167

    
1168
#define GEN_LDS(width, op)                                                    \
1169
OP_LD_TABLE(width);                                                           \
1170
GEN_LD(width, op | 0x20);                                                     \
1171
GEN_LDU(width, op | 0x21);                                                    \
1172
GEN_LDUX(width, op | 0x01);                                                   \
1173
GEN_LDX(width, 0x17, op | 0x00)
1174

    
1175
/* lbz lbzu lbzux lbzx */
1176
GEN_LDS(bz, 0x02);
1177
/* lha lhau lhaux lhax */
1178
GEN_LDS(ha, 0x0A);
1179
/* lhz lhzu lhzux lhzx */
1180
GEN_LDS(hz, 0x08);
1181
/* lwz lwzu lwzux lwzx */
1182
GEN_LDS(wz, 0x00);
1183

    
1184
/***                              Integer store                            ***/
1185
#define GEN_ST(width, opc)                                                    \
1186
GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)              \
1187
{                                                                             \
1188
    uint32_t simm = SIMM(ctx->opcode);                                        \
1189
    if (rA(ctx->opcode) == 0) {                                               \
1190
        gen_op_set_T0(simm);                                                  \
1191
    } else {                                                                  \
1192
        gen_op_load_gpr_T0(rA(ctx->opcode));                                  \
1193
        if (simm != 0)                                                        \
1194
            gen_op_addi(simm);                                                \
1195
    }                                                                         \
1196
    gen_op_load_gpr_T1(rS(ctx->opcode));                                      \
1197
    op_ldst(st##width);                                                       \
1198
}
1199

    
1200
#define GEN_STU(width, opc)                                                   \
1201
GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)           \
1202
{                                                                             \
1203
    uint32_t simm = SIMM(ctx->opcode);                                        \
1204
    if (rA(ctx->opcode) == 0) {                                               \
1205
        RET_INVAL(ctx);                                                       \
1206
        return;                                                               \
1207
    }                                                                         \
1208
    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
1209
    if (simm != 0)                                                            \
1210
        gen_op_addi(simm);                                                    \
1211
    gen_op_load_gpr_T1(rS(ctx->opcode));                                      \
1212
    op_ldst(st##width);                                                       \
1213
    gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
1214
}
1215

    
1216
#define GEN_STUX(width, opc)                                                  \
1217
GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER)          \
1218
{                                                                             \
1219
    if (rA(ctx->opcode) == 0) {                                               \
1220
        RET_INVAL(ctx);                                                       \
1221
        return;                                                               \
1222
    }                                                                         \
1223
    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
1224
    gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
1225
    gen_op_add();                                                             \
1226
    gen_op_load_gpr_T1(rS(ctx->opcode));                                      \
1227
    op_ldst(st##width);                                                       \
1228
    gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
1229
}
1230

    
1231
#define GEN_STX(width, opc2, opc3)                                            \
1232
GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER)          \
1233
{                                                                             \
1234
    if (rA(ctx->opcode) == 0) {                                               \
1235
        gen_op_load_gpr_T0(rB(ctx->opcode));                                  \
1236
    } else {                                                                  \
1237
        gen_op_load_gpr_T0(rA(ctx->opcode));                                  \
1238
        gen_op_load_gpr_T1(rB(ctx->opcode));                                  \
1239
        gen_op_add();                                                         \
1240
    }                                                                         \
1241
    gen_op_load_gpr_T1(rS(ctx->opcode));                                      \
1242
    op_ldst(st##width);                                                       \
1243
}
1244

    
1245
#define GEN_STS(width, op)                                                    \
1246
OP_ST_TABLE(width);                                                           \
1247
GEN_ST(width, op | 0x20);                                                     \
1248
GEN_STU(width, op | 0x21);                                                    \
1249
GEN_STUX(width, op | 0x01);                                                   \
1250
GEN_STX(width, 0x17, op | 0x00)
1251

    
1252
/* stb stbu stbux stbx */
1253
GEN_STS(b, 0x06);
1254
/* sth sthu sthux sthx */
1255
GEN_STS(h, 0x0C);
1256
/* stw stwu stwux stwx */
1257
GEN_STS(w, 0x04);
1258

    
1259
/***                Integer load and store with byte reverse               ***/
1260
/* lhbrx */
1261
OP_LD_TABLE(hbr);
1262
GEN_LDX(hbr, 0x16, 0x18);
1263
/* lwbrx */
1264
OP_LD_TABLE(wbr);
1265
GEN_LDX(wbr, 0x16, 0x10);
1266
/* sthbrx */
1267
OP_ST_TABLE(hbr);
1268
GEN_STX(hbr, 0x16, 0x1C);
1269
/* stwbrx */
1270
OP_ST_TABLE(wbr);
1271
GEN_STX(wbr, 0x16, 0x14);
1272

    
1273
/***                    Integer load and store multiple                    ***/
1274
#define op_ldstm(name, reg) (*gen_op_##name[ctx->mem_idx])(reg)
1275
#if defined(CONFIG_USER_ONLY)
1276
static GenOpFunc1 *gen_op_lmw[] = {
1277
    &gen_op_lmw_raw,
1278
    &gen_op_lmw_le_raw,
1279
};
1280
static GenOpFunc1 *gen_op_stmw[] = {
1281
    &gen_op_stmw_raw,
1282
    &gen_op_stmw_le_raw,
1283
};
1284
#else
1285
static GenOpFunc1 *gen_op_lmw[] = {
1286
    &gen_op_lmw_user,
1287
    &gen_op_lmw_le_user,
1288
    &gen_op_lmw_kernel,
1289
    &gen_op_lmw_le_kernel,
1290
};
1291
static GenOpFunc1 *gen_op_stmw[] = {
1292
    &gen_op_stmw_user,
1293
    &gen_op_stmw_le_user,
1294
    &gen_op_stmw_kernel,
1295
    &gen_op_stmw_le_kernel,
1296
};
1297
#endif
1298

    
1299
/* lmw */
1300
GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1301
{
1302
    int simm = SIMM(ctx->opcode);
1303

    
1304
    if (rA(ctx->opcode) == 0) {
1305
        gen_op_set_T0(simm);
1306
    } else {
1307
        gen_op_load_gpr_T0(rA(ctx->opcode));
1308
        if (simm != 0)
1309
            gen_op_addi(simm);
1310
    }
1311
    op_ldstm(lmw, rD(ctx->opcode));
1312
}
1313

    
1314
/* stmw */
1315
GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1316
{
1317
    int simm = SIMM(ctx->opcode);
1318

    
1319
    if (rA(ctx->opcode) == 0) {
1320
        gen_op_set_T0(simm);
1321
    } else {
1322
        gen_op_load_gpr_T0(rA(ctx->opcode));
1323
        if (simm != 0)
1324
            gen_op_addi(simm);
1325
    }
1326
    op_ldstm(stmw, rS(ctx->opcode));
1327
}
1328

    
1329
/***                    Integer load and store strings                     ***/
1330
#define op_ldsts(name, start) (*gen_op_##name[ctx->mem_idx])(start)
1331
#define op_ldstsx(name, rd, ra, rb) (*gen_op_##name[ctx->mem_idx])(rd, ra, rb)
1332
#if defined(CONFIG_USER_ONLY)
1333
static GenOpFunc1 *gen_op_lswi[] = {
1334
    &gen_op_lswi_raw,
1335
    &gen_op_lswi_le_raw,
1336
};
1337
static GenOpFunc3 *gen_op_lswx[] = {
1338
    &gen_op_lswx_raw,
1339
    &gen_op_lswx_le_raw,
1340
};
1341
static GenOpFunc1 *gen_op_stsw[] = {
1342
    &gen_op_stsw_raw,
1343
    &gen_op_stsw_le_raw,
1344
};
1345
#else
1346
static GenOpFunc1 *gen_op_lswi[] = {
1347
    &gen_op_lswi_user,
1348
    &gen_op_lswi_le_user,
1349
    &gen_op_lswi_kernel,
1350
    &gen_op_lswi_le_kernel,
1351
};
1352
static GenOpFunc3 *gen_op_lswx[] = {
1353
    &gen_op_lswx_user,
1354
    &gen_op_lswx_le_user,
1355
    &gen_op_lswx_kernel,
1356
    &gen_op_lswx_le_kernel,
1357
};
1358
static GenOpFunc1 *gen_op_stsw[] = {
1359
    &gen_op_stsw_user,
1360
    &gen_op_stsw_le_user,
1361
    &gen_op_stsw_kernel,
1362
    &gen_op_stsw_le_kernel,
1363
};
1364
#endif
1365

    
1366
/* lswi */
1367
/* PowerPC32 specification says we must generate an exception if
1368
 * rA is in the range of registers to be loaded.
1369
 * In an other hand, IBM says this is valid, but rA won't be loaded.
1370
 * For now, I'll follow the spec...
1371
 */
1372
GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_INTEGER)
1373
{
1374
    int nb = NB(ctx->opcode);
1375
    int start = rD(ctx->opcode);
1376
    int ra = rA(ctx->opcode);
1377
    int nr;
1378

    
1379
    if (nb == 0)
1380
        nb = 32;
1381
    nr = nb / 4;
1382
    if (((start + nr) > 32  && start <= ra && (start + nr - 32) > ra) ||
1383
        ((start + nr) <= 32 && start <= ra && (start + nr) > ra)) {
1384
        RET_EXCP(ctx, EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_LSWX);
1385
        return;
1386
    }
1387
    if (ra == 0) {
1388
        gen_op_set_T0(0);
1389
    } else {
1390
        gen_op_load_gpr_T0(ra);
1391
    }
1392
    gen_op_set_T1(nb);
1393
    /* NIP cannot be restored if the memory exception comes from an helper */
1394
    gen_op_update_nip((ctx)->nip - 4); 
1395
    op_ldsts(lswi, start);
1396
}
1397

    
1398
/* lswx */
1399
GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_INTEGER)
1400
{
1401
    int ra = rA(ctx->opcode);
1402
    int rb = rB(ctx->opcode);
1403

    
1404
    if (ra == 0) {
1405
        gen_op_load_gpr_T0(rb);
1406
        ra = rb;
1407
    } else {
1408
        gen_op_load_gpr_T0(ra);
1409
        gen_op_load_gpr_T1(rb);
1410
        gen_op_add();
1411
    }
1412
    gen_op_load_xer_bc();
1413
    /* NIP cannot be restored if the memory exception comes from an helper */
1414
    gen_op_update_nip((ctx)->nip - 4); 
1415
    op_ldstsx(lswx, rD(ctx->opcode), ra, rb);
1416
}
1417

    
1418
/* stswi */
1419
GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_INTEGER)
1420
{
1421
    int nb = NB(ctx->opcode);
1422

    
1423
    if (rA(ctx->opcode) == 0) {
1424
        gen_op_set_T0(0);
1425
    } else {
1426
        gen_op_load_gpr_T0(rA(ctx->opcode));
1427
    }
1428
    if (nb == 0)
1429
        nb = 32;
1430
    gen_op_set_T1(nb);
1431
    /* NIP cannot be restored if the memory exception comes from an helper */
1432
    gen_op_update_nip((ctx)->nip - 4); 
1433
    op_ldsts(stsw, rS(ctx->opcode));
1434
}
1435

    
1436
/* stswx */
1437
GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_INTEGER)
1438
{
1439
    int ra = rA(ctx->opcode);
1440

    
1441
    if (ra == 0) {
1442
        gen_op_load_gpr_T0(rB(ctx->opcode));
1443
        ra = rB(ctx->opcode);
1444
    } else {
1445
        gen_op_load_gpr_T0(ra);
1446
        gen_op_load_gpr_T1(rB(ctx->opcode));
1447
        gen_op_add();
1448
    }
1449
    gen_op_load_xer_bc();
1450
    /* NIP cannot be restored if the memory exception comes from an helper */
1451
    gen_op_update_nip((ctx)->nip - 4); 
1452
    op_ldsts(stsw, rS(ctx->opcode));
1453
}
1454

    
1455
/***                        Memory synchronisation                         ***/
1456
/* eieio */
1457
GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FF0801, PPC_MEM)
1458
{
1459
}
1460

    
1461
/* isync */
1462
GEN_HANDLER(isync, 0x13, 0x16, 0xFF, 0x03FF0801, PPC_MEM)
1463
{
1464
}
1465

    
1466
#define op_lwarx() (*gen_op_lwarx[ctx->mem_idx])()
1467
#define op_stwcx() (*gen_op_stwcx[ctx->mem_idx])()
1468
#if defined(CONFIG_USER_ONLY)
1469
static GenOpFunc *gen_op_lwarx[] = {
1470
    &gen_op_lwarx_raw,
1471
    &gen_op_lwarx_le_raw,
1472
};
1473
static GenOpFunc *gen_op_stwcx[] = {
1474
    &gen_op_stwcx_raw,
1475
    &gen_op_stwcx_le_raw,
1476
};
1477
#else
1478
static GenOpFunc *gen_op_lwarx[] = {
1479
    &gen_op_lwarx_user,
1480
    &gen_op_lwarx_le_user,
1481
    &gen_op_lwarx_kernel,
1482
    &gen_op_lwarx_le_kernel,
1483
};
1484
static GenOpFunc *gen_op_stwcx[] = {
1485
    &gen_op_stwcx_user,
1486
    &gen_op_stwcx_le_user,
1487
    &gen_op_stwcx_kernel,
1488
    &gen_op_stwcx_le_kernel,
1489
};
1490
#endif
1491

    
1492
/* lwarx */
1493
GEN_HANDLER(lwarx, 0x1F, 0x14, 0xFF, 0x00000001, PPC_RES)
1494
{
1495
    if (rA(ctx->opcode) == 0) {
1496
        gen_op_load_gpr_T0(rB(ctx->opcode));
1497
    } else {
1498
        gen_op_load_gpr_T0(rA(ctx->opcode));
1499
        gen_op_load_gpr_T1(rB(ctx->opcode));
1500
        gen_op_add();
1501
    }
1502
    op_lwarx();
1503
    gen_op_store_T1_gpr(rD(ctx->opcode));
1504
}
1505

    
1506
/* stwcx. */
1507
GEN_HANDLER(stwcx_, 0x1F, 0x16, 0x04, 0x00000000, PPC_RES)
1508
{
1509
        if (rA(ctx->opcode) == 0) {
1510
            gen_op_load_gpr_T0(rB(ctx->opcode));
1511
        } else {
1512
            gen_op_load_gpr_T0(rA(ctx->opcode));
1513
            gen_op_load_gpr_T1(rB(ctx->opcode));
1514
        gen_op_add();
1515
        }
1516
    gen_op_load_gpr_T1(rS(ctx->opcode));
1517
    op_stwcx();
1518
}
1519

    
1520
/* sync */
1521
GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x03FF0801, PPC_MEM)
1522
{
1523
}
1524

    
1525
/***                         Floating-point load                           ***/
1526
#define GEN_LDF(width, opc)                                                   \
1527
GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT)                 \
1528
{                                                                             \
1529
    uint32_t simm = SIMM(ctx->opcode);                                        \
1530
    if (!ctx->fpu_enabled) {                                                  \
1531
        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
1532
        return;                                                               \
1533
    }                                                                         \
1534
    if (rA(ctx->opcode) == 0) {                                               \
1535
        gen_op_set_T0(simm);                                                  \
1536
    } else {                                                                  \
1537
        gen_op_load_gpr_T0(rA(ctx->opcode));                                  \
1538
        if (simm != 0)                                                        \
1539
            gen_op_addi(simm);                                                \
1540
    }                                                                         \
1541
    op_ldst(l##width);                                                        \
1542
    gen_op_store_FT1_fpr(rD(ctx->opcode));                                    \
1543
}
1544

    
1545
#define GEN_LDUF(width, opc)                                                  \
1546
GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT)              \
1547
{                                                                             \
1548
    uint32_t simm = SIMM(ctx->opcode);                                        \
1549
    if (!ctx->fpu_enabled) {                                                  \
1550
        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
1551
        return;                                                               \
1552
    }                                                                         \
1553
    if (rA(ctx->opcode) == 0 ||                                               \
1554
        rA(ctx->opcode) == rD(ctx->opcode)) {                                 \
1555
        RET_INVAL(ctx);                                                       \
1556
        return;                                                               \
1557
    }                                                                         \
1558
    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
1559
    if (simm != 0)                                                            \
1560
        gen_op_addi(simm);                                                    \
1561
    op_ldst(l##width);                                                        \
1562
    gen_op_store_FT1_fpr(rD(ctx->opcode));                                    \
1563
    gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
1564
}
1565

    
1566
#define GEN_LDUXF(width, opc)                                                 \
1567
GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT)             \
1568
{                                                                             \
1569
    if (!ctx->fpu_enabled) {                                                  \
1570
        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
1571
        return;                                                               \
1572
    }                                                                         \
1573
    if (rA(ctx->opcode) == 0 ||                                               \
1574
        rA(ctx->opcode) == rD(ctx->opcode)) {                                 \
1575
        RET_INVAL(ctx);                                                       \
1576
        return;                                                               \
1577
    }                                                                         \
1578
    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
1579
    gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
1580
    gen_op_add();                                                             \
1581
    op_ldst(l##width);                                                        \
1582
    gen_op_store_FT1_fpr(rD(ctx->opcode));                                    \
1583
    gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
1584
}
1585

    
1586
#define GEN_LDXF(width, opc2, opc3)                                           \
1587
GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_FLOAT)             \
1588
{                                                                             \
1589
    if (!ctx->fpu_enabled) {                                                  \
1590
        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
1591
        return;                                                               \
1592
    }                                                                         \
1593
    if (rA(ctx->opcode) == 0) {                                               \
1594
        gen_op_load_gpr_T0(rB(ctx->opcode));                                  \
1595
    } else {                                                                  \
1596
        gen_op_load_gpr_T0(rA(ctx->opcode));                                  \
1597
        gen_op_load_gpr_T1(rB(ctx->opcode));                                  \
1598
        gen_op_add();                                                         \
1599
    }                                                                         \
1600
    op_ldst(l##width);                                                        \
1601
    gen_op_store_FT1_fpr(rD(ctx->opcode));                                    \
1602
}
1603

    
1604
#define GEN_LDFS(width, op)                                                   \
1605
OP_LD_TABLE(width);                                                           \
1606
GEN_LDF(width, op | 0x20);                                                    \
1607
GEN_LDUF(width, op | 0x21);                                                   \
1608
GEN_LDUXF(width, op | 0x01);                                                  \
1609
GEN_LDXF(width, 0x17, op | 0x00)
1610

    
1611
/* lfd lfdu lfdux lfdx */
1612
GEN_LDFS(fd, 0x12);
1613
/* lfs lfsu lfsux lfsx */
1614
GEN_LDFS(fs, 0x10);
1615

    
1616
/***                         Floating-point store                          ***/
1617
#define GEN_STF(width, opc)                                                   \
1618
GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT)                \
1619
{                                                                             \
1620
    uint32_t simm = SIMM(ctx->opcode);                                        \
1621
    if (!ctx->fpu_enabled) {                                                  \
1622
        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
1623
        return;                                                               \
1624
    }                                                                         \
1625
    if (rA(ctx->opcode) == 0) {                                               \
1626
        gen_op_set_T0(simm);                                                  \
1627
    } else {                                                                  \
1628
        gen_op_load_gpr_T0(rA(ctx->opcode));                                  \
1629
        if (simm != 0)                                                        \
1630
            gen_op_addi(simm);                                                \
1631
    }                                                                         \
1632
    gen_op_load_fpr_FT1(rS(ctx->opcode));                                     \
1633
    op_ldst(st##width);                                                       \
1634
}
1635

    
1636
#define GEN_STUF(width, opc)                                                  \
1637
GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT)             \
1638
{                                                                             \
1639
    uint32_t simm = SIMM(ctx->opcode);                                        \
1640
    if (!ctx->fpu_enabled) {                                                  \
1641
        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
1642
        return;                                                               \
1643
    }                                                                         \
1644
    if (rA(ctx->opcode) == 0) {                                               \
1645
        RET_INVAL(ctx);                                                       \
1646
        return;                                                               \
1647
    }                                                                         \
1648
    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
1649
    if (simm != 0)                                                            \
1650
        gen_op_addi(simm);                                                    \
1651
    gen_op_load_fpr_FT1(rS(ctx->opcode));                                     \
1652
    op_ldst(st##width);                                                       \
1653
    gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
1654
}
1655

    
1656
#define GEN_STUXF(width, opc)                                                 \
1657
GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT)            \
1658
{                                                                             \
1659
    if (!ctx->fpu_enabled) {                                                  \
1660
        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
1661
        return;                                                               \
1662
    }                                                                         \
1663
    if (rA(ctx->opcode) == 0) {                                               \
1664
        RET_INVAL(ctx);                                                       \
1665
        return;                                                               \
1666
    }                                                                         \
1667
    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
1668
    gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
1669
    gen_op_add();                                                             \
1670
    gen_op_load_fpr_FT1(rS(ctx->opcode));                                     \
1671
    op_ldst(st##width);                                                       \
1672
    gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
1673
}
1674

    
1675
#define GEN_STXF(width, opc2, opc3)                                           \
1676
GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_FLOAT)            \
1677
{                                                                             \
1678
    if (!ctx->fpu_enabled) {                                                  \
1679
        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
1680
        return;                                                               \
1681
    }                                                                         \
1682
    if (rA(ctx->opcode) == 0) {                                               \
1683
        gen_op_load_gpr_T0(rB(ctx->opcode));                                  \
1684
    } else {                                                                  \
1685
        gen_op_load_gpr_T0(rA(ctx->opcode));                                  \
1686
        gen_op_load_gpr_T1(rB(ctx->opcode));                                  \
1687
        gen_op_add();                                                         \
1688
    }                                                                         \
1689
    gen_op_load_fpr_FT1(rS(ctx->opcode));                                     \
1690
    op_ldst(st##width);                                                       \
1691
}
1692

    
1693
#define GEN_STFS(width, op)                                                   \
1694
OP_ST_TABLE(width);                                                           \
1695
GEN_STF(width, op | 0x20);                                                    \
1696
GEN_STUF(width, op | 0x21);                                                   \
1697
GEN_STUXF(width, op | 0x01);                                                  \
1698
GEN_STXF(width, 0x17, op | 0x00)
1699

    
1700
/* stfd stfdu stfdux stfdx */
1701
GEN_STFS(fd, 0x16);
1702
/* stfs stfsu stfsux stfsx */
1703
GEN_STFS(fs, 0x14);
1704

    
1705
/* Optional: */
1706
/* stfiwx */
1707
GEN_HANDLER(stfiwx, 0x1F, 0x17, 0x1E, 0x00000001, PPC_FLOAT)
1708
{
1709
    if (!ctx->fpu_enabled) {
1710
        RET_EXCP(ctx, EXCP_NO_FP, 0);
1711
        return;
1712
    }
1713
    RET_INVAL(ctx);
1714
}
1715

    
1716
/***                                Branch                                 ***/
1717

    
1718
/* b ba bl bla */
1719
GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
1720
{
1721
    uint32_t li, target;
1722

    
1723
    /* sign extend LI */
1724
    li = ((int32_t)LI(ctx->opcode) << 6) >> 6;
1725

    
1726
    if (AA(ctx->opcode) == 0)
1727
        target = ctx->nip + li - 4;
1728
    else
1729
        target = li;
1730
    if (LK(ctx->opcode)) {
1731
        gen_op_setlr(ctx->nip);
1732
    }
1733
    gen_op_b((long)ctx->tb, target);
1734
    ctx->exception = EXCP_BRANCH;
1735
}
1736

    
1737
#define BCOND_IM  0
1738
#define BCOND_LR  1
1739
#define BCOND_CTR 2
1740

    
1741
static inline void gen_bcond(DisasContext *ctx, int type) 
1742
{                                                                             
1743
    uint32_t target = 0;
1744
    uint32_t bo = BO(ctx->opcode);                                            
1745
    uint32_t bi = BI(ctx->opcode);                                            
1746
    uint32_t mask;                                                            
1747
    uint32_t li;
1748

    
1749
    if ((bo & 0x4) == 0)
1750
        gen_op_dec_ctr();                                                     
1751
    switch(type) {
1752
    case BCOND_IM:
1753
        li = (int32_t)((int16_t)(BD(ctx->opcode)));
1754
        if (AA(ctx->opcode) == 0) {
1755
            target = ctx->nip + li - 4;
1756
        } else {
1757
            target = li;
1758
        }
1759
        break;
1760
    case BCOND_CTR:
1761
        gen_op_movl_T1_ctr();
1762
        break;
1763
    default:
1764
    case BCOND_LR:
1765
        gen_op_movl_T1_lr();
1766
        break;
1767
    }
1768
    if (LK(ctx->opcode)) {                                        
1769
        gen_op_setlr(ctx->nip);
1770
    }
1771
    if (bo & 0x10) {
1772
        /* No CR condition */                                                 
1773
        switch (bo & 0x6) {                                                   
1774
        case 0:                                                               
1775
            gen_op_test_ctr();
1776
            break;
1777
        case 2:                                                               
1778
            gen_op_test_ctrz();
1779
            break;                                                            
1780
        default:
1781
        case 4:                                                               
1782
        case 6:                                                               
1783
            if (type == BCOND_IM) {
1784
                gen_op_b((long)ctx->tb, target);
1785
            } else {
1786
                gen_op_b_T1();
1787
            }
1788
            goto no_test;
1789
        }
1790
    } else {                                                                  
1791
        mask = 1 << (3 - (bi & 0x03));                                        
1792
        gen_op_load_crf_T0(bi >> 2);                                          
1793
        if (bo & 0x8) {                                                       
1794
            switch (bo & 0x6) {                                               
1795
            case 0:                                                           
1796
                gen_op_test_ctr_true(mask);
1797
                break;                                                        
1798
            case 2:                                                           
1799
                gen_op_test_ctrz_true(mask);
1800
                break;                                                        
1801
            default:                                                          
1802
            case 4:                                                           
1803
            case 6:                                                           
1804
                gen_op_test_true(mask);
1805
                break;                                                        
1806
            }                                                                 
1807
        } else {                                                              
1808
            switch (bo & 0x6) {                                               
1809
            case 0:                                                           
1810
                gen_op_test_ctr_false(mask);
1811
                break;                                                        
1812
            case 2:                                                           
1813
                gen_op_test_ctrz_false(mask);
1814
                break;                                                        
1815
            default:
1816
            case 4:                                                           
1817
            case 6:                                                           
1818
                gen_op_test_false(mask);
1819
                break;                                                        
1820
            }                                                                 
1821
        }                                                                     
1822
    }                                                                         
1823
    if (type == BCOND_IM) {
1824
        gen_op_btest((long)ctx->tb, target, ctx->nip);
1825
    } else {
1826
        gen_op_btest_T1(ctx->nip);
1827
    }
1828
 no_test:
1829
    ctx->exception = EXCP_BRANCH;                                             
1830
}
1831

    
1832
GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
1833
{                                                                             
1834
    gen_bcond(ctx, BCOND_IM);
1835
}
1836

    
1837
GEN_HANDLER(bcctr, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW)
1838
{                                                                             
1839
    gen_bcond(ctx, BCOND_CTR);
1840
}
1841

    
1842
GEN_HANDLER(bclr, 0x13, 0x10, 0x00, 0x00000000, PPC_FLOW)
1843
{                                                                             
1844
    gen_bcond(ctx, BCOND_LR);
1845
}
1846

    
1847
/***                      Condition register logical                       ***/
1848
#define GEN_CRLOGIC(op, opc)                                                  \
1849
GEN_HANDLER(cr##op, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER)                 \
1850
{                                                                             \
1851
    gen_op_load_crf_T0(crbA(ctx->opcode) >> 2);                               \
1852
    gen_op_getbit_T0(3 - (crbA(ctx->opcode) & 0x03));                         \
1853
    gen_op_load_crf_T1(crbB(ctx->opcode) >> 2);                               \
1854
    gen_op_getbit_T1(3 - (crbB(ctx->opcode) & 0x03));                         \
1855
    gen_op_##op();                                                            \
1856
    gen_op_load_crf_T1(crbD(ctx->opcode) >> 2);                               \
1857
    gen_op_setcrfbit(~(1 << (3 - (crbD(ctx->opcode) & 0x03))),                \
1858
                     3 - (crbD(ctx->opcode) & 0x03));                         \
1859
    gen_op_store_T1_crf(crbD(ctx->opcode) >> 2);                              \
1860
}
1861

    
1862
/* crand */
1863
GEN_CRLOGIC(and, 0x08)
1864
/* crandc */
1865
GEN_CRLOGIC(andc, 0x04)
1866
/* creqv */
1867
GEN_CRLOGIC(eqv, 0x09)
1868
/* crnand */
1869
GEN_CRLOGIC(nand, 0x07)
1870
/* crnor */
1871
GEN_CRLOGIC(nor, 0x01)
1872
/* cror */
1873
GEN_CRLOGIC(or, 0x0E)
1874
/* crorc */
1875
GEN_CRLOGIC(orc, 0x0D)
1876
/* crxor */
1877
GEN_CRLOGIC(xor, 0x06)
1878
/* mcrf */
1879
GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER)
1880
{
1881
    gen_op_load_crf_T0(crfS(ctx->opcode));
1882
    gen_op_store_T0_crf(crfD(ctx->opcode));
1883
}
1884

    
1885
/***                           System linkage                              ***/
1886
/* rfi (supervisor only) */
1887
GEN_HANDLER(rfi, 0x13, 0x12, 0xFF, 0x03FF8001, PPC_FLOW)
1888
{
1889
#if defined(CONFIG_USER_ONLY)
1890
    RET_PRIVOPC(ctx);
1891
#else
1892
    /* Restore CPU state */
1893
    if (!ctx->supervisor) {
1894
        RET_PRIVOPC(ctx);
1895
        return;
1896
    }
1897
    gen_op_rfi();
1898
    RET_EXCP(ctx, EXCP_RFI, 0);
1899
#endif
1900
}
1901

    
1902
/* sc */
1903
GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFFFFD, PPC_FLOW)
1904
{
1905
#if defined(CONFIG_USER_ONLY)
1906
    RET_EXCP(ctx, EXCP_SYSCALL_USER, 0);
1907
#else
1908
    RET_EXCP(ctx, EXCP_SYSCALL, 0);
1909
#endif
1910
}
1911

    
1912
/***                                Trap                                   ***/
1913
/* tw */
1914
GEN_HANDLER(tw, 0x1F, 0x04, 0xFF, 0x00000001, PPC_FLOW)
1915
{
1916
    gen_op_load_gpr_T0(rA(ctx->opcode));
1917
    gen_op_load_gpr_T1(rB(ctx->opcode));
1918
    gen_op_tw(TO(ctx->opcode));
1919
}
1920

    
1921
/* twi */
1922
GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
1923
{
1924
    gen_op_load_gpr_T0(rA(ctx->opcode));
1925
#if 0
1926
    printf("%s: param=0x%04x T0=0x%04x\n", __func__,
1927
           SIMM(ctx->opcode), TO(ctx->opcode));
1928
#endif
1929
    gen_op_twi(SIMM(ctx->opcode), TO(ctx->opcode));
1930
}
1931

    
1932
/***                          Processor control                            ***/
1933
static inline int check_spr_access (int spr, int rw, int supervisor)
1934
{
1935
    uint32_t rights = spr_access[spr >> 1] >> (4 * (spr & 1));
1936

    
1937
#if 0
1938
    if (spr != LR && spr != CTR) {
1939
    if (loglevel > 0) {
1940
        fprintf(logfile, "%s reg=%d s=%d rw=%d r=0x%02x 0x%02x\n", __func__,
1941
                SPR_ENCODE(spr), supervisor, rw, rights,
1942
                (rights >> ((2 * supervisor) + rw)) & 1);
1943
    } else {
1944
        printf("%s reg=%d s=%d rw=%d r=0x%02x 0x%02x\n", __func__,
1945
               SPR_ENCODE(spr), supervisor, rw, rights,
1946
               (rights >> ((2 * supervisor) + rw)) & 1);
1947
    }
1948
    }
1949
#endif
1950
    if (rights == 0)
1951
        return -1;
1952
    rights = rights >> (2 * supervisor);
1953
    rights = rights >> rw;
1954

    
1955
    return rights & 1;
1956
}
1957

    
1958
/* mcrxr */
1959
GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC)
1960
{
1961
    gen_op_load_xer_cr();
1962
    gen_op_store_T0_crf(crfD(ctx->opcode));
1963
    gen_op_clear_xer_cr();
1964
}
1965

    
1966
/* mfcr */
1967
GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x001FF801, PPC_MISC)
1968
{
1969
    gen_op_load_cr();
1970
    gen_op_store_T0_gpr(rD(ctx->opcode));
1971
}
1972

    
1973
/* mfmsr */
1974
GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC)
1975
{
1976
#if defined(CONFIG_USER_ONLY)
1977
    RET_PRIVREG(ctx);
1978
#else
1979
    if (!ctx->supervisor) {
1980
        RET_PRIVREG(ctx);
1981
        return;
1982
    }
1983
    gen_op_load_msr();
1984
    gen_op_store_T0_gpr(rD(ctx->opcode));
1985
#endif
1986
}
1987

    
1988
#if 0
1989
#define SPR_NOACCESS ((void *)(-1))
1990
#else
1991
static void spr_noaccess (void *opaque, int sprn)
1992
{
1993
    sprn = ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
1994
    printf("ERROR: try to access SPR %d !\n", sprn);
1995
}
1996
#define SPR_NOACCESS (&spr_noaccess)
1997
#endif
1998

    
1999
/* mfspr */
2000
static inline void gen_op_mfspr (DisasContext *ctx)
2001
{
2002
    void (*read_cb)(void *opaque, int sprn);
2003
    uint32_t sprn = SPR(ctx->opcode);
2004

    
2005
#if !defined(CONFIG_USER_ONLY)
2006
    if (ctx->supervisor)
2007
        read_cb = ctx->spr_cb[sprn].oea_read;
2008
    else
2009
#endif
2010
        read_cb = ctx->spr_cb[sprn].uea_read;
2011
    if (read_cb != NULL) {
2012
        if (read_cb != SPR_NOACCESS) {
2013
            (*read_cb)(ctx, sprn);
2014
            gen_op_store_T0_gpr(rD(ctx->opcode));
2015
        } else {
2016
            /* Privilege exception */
2017
            printf("Trying to read priviledged spr %d %03x\n", sprn, sprn);
2018
        RET_PRIVREG(ctx);
2019
        }
2020
    } else {
2021
        /* Not defined */
2022
        printf("Trying to read invalid spr %d %03x\n", sprn, sprn);
2023
        RET_EXCP(ctx, EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_SPR);
2024
    }
2025
}
2026

    
2027
GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC)
2028
{
2029
    gen_op_mfspr(ctx);
2030
    }
2031

    
2032
/* mftb */
2033
GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_TB)
2034
{
2035
    gen_op_mfspr(ctx);
2036
}
2037

    
2038
/* mtcrf */
2039
/* The mask should be 0x00100801, but Mac OS X 10.4 use an alternate form */
2040
GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC)
2041
{
2042
    gen_op_load_gpr_T0(rS(ctx->opcode));
2043
    gen_op_store_cr(CRM(ctx->opcode));
2044
}
2045

    
2046
/* mtmsr */
2047
GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC)
2048
{
2049
#if defined(CONFIG_USER_ONLY)
2050
    RET_PRIVREG(ctx);
2051
#else
2052
    if (!ctx->supervisor) {
2053
        RET_PRIVREG(ctx);
2054
        return;
2055
    }
2056
    gen_op_load_gpr_T0(rS(ctx->opcode));
2057
    gen_op_store_msr();
2058
    /* Must stop the translation as machine state (may have) changed */
2059
    RET_MTMSR(ctx);
2060
#endif
2061
}
2062

    
2063
/* mtspr */
2064
GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC)
2065
{
2066
    void (*write_cb)(void *opaque, int sprn);
2067
    uint32_t sprn = SPR(ctx->opcode);
2068

    
2069
#if !defined(CONFIG_USER_ONLY)
2070
    if (ctx->supervisor)
2071
        write_cb = ctx->spr_cb[sprn].oea_write;
2072
    else
2073
#endif
2074
        write_cb = ctx->spr_cb[sprn].uea_write;
2075
    if (write_cb != NULL) {
2076
        if (write_cb != SPR_NOACCESS) {
2077
            gen_op_load_gpr_T0(rS(ctx->opcode));
2078
            (*write_cb)(ctx, sprn);
2079
        } else {
2080
            /* Privilege exception */
2081
            printf("Trying to write priviledged spr %d %03x\n", sprn, sprn);
2082
        RET_PRIVREG(ctx);
2083
    }
2084
    } else {
2085
        /* Not defined */
2086
        printf("Trying to write invalid spr %d %03x\n", sprn, sprn);
2087
        RET_EXCP(ctx, EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_SPR);
2088
    }
2089
}
2090

    
2091
/***                         Cache management                              ***/
2092
/* For now, all those will be implemented as nop:
2093
 * this is valid, regarding the PowerPC specs...
2094
 * We just have to flush tb while invalidating instruction cache lines...
2095
 */
2096
/* dcbf */
2097
GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03E00001, PPC_CACHE)
2098
{
2099
    if (rA(ctx->opcode) == 0) {
2100
        gen_op_load_gpr_T0(rB(ctx->opcode));
2101
    } else {
2102
        gen_op_load_gpr_T0(rA(ctx->opcode));
2103
        gen_op_load_gpr_T1(rB(ctx->opcode));
2104
        gen_op_add();
2105
    }
2106
    op_ldst(lbz);
2107
}
2108

    
2109
/* dcbi (Supervisor only) */
2110
GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE)
2111
{
2112
#if defined(CONFIG_USER_ONLY)
2113
    RET_PRIVOPC(ctx);
2114
#else
2115
    if (!ctx->supervisor) {
2116
        RET_PRIVOPC(ctx);
2117
        return;
2118
    }
2119
    if (rA(ctx->opcode) == 0) {
2120
        gen_op_load_gpr_T0(rB(ctx->opcode));
2121
    } else {
2122
        gen_op_load_gpr_T0(rA(ctx->opcode));
2123
        gen_op_load_gpr_T1(rB(ctx->opcode));
2124
        gen_op_add();
2125
    }
2126
    op_ldst(lbz);
2127
    op_ldst(stb);
2128
#endif
2129
}
2130

    
2131
/* dcdst */
2132
GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE)
2133
{
2134
    if (rA(ctx->opcode) == 0) {
2135
        gen_op_load_gpr_T0(rB(ctx->opcode));
2136
    } else {
2137
        gen_op_load_gpr_T0(rA(ctx->opcode));
2138
        gen_op_load_gpr_T1(rB(ctx->opcode));
2139
        gen_op_add();
2140
    }
2141
    op_ldst(lbz);
2142
}
2143

    
2144
/* dcbt */
2145
GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x03E00001, PPC_CACHE)
2146
{
2147
}
2148

    
2149
/* dcbtst */
2150
GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x03E00001, PPC_CACHE)
2151
{
2152
}
2153

    
2154
/* dcbz */
2155
#if defined(CONFIG_USER_ONLY)
2156
#define op_dcbz() gen_op_dcbz_raw()
2157
#else
2158
#define op_dcbz() (*gen_op_dcbz[ctx->mem_idx])()
2159
static GenOpFunc *gen_op_dcbz[] = {
2160
    &gen_op_dcbz_user,
2161
    &gen_op_dcbz_user,
2162
    &gen_op_dcbz_kernel,
2163
    &gen_op_dcbz_kernel,
2164
};
2165
#endif
2166

    
2167
GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03E00001, PPC_CACHE)
2168
{
2169
    if (rA(ctx->opcode) == 0) {
2170
        gen_op_load_gpr_T0(rB(ctx->opcode));
2171
    } else {
2172
        gen_op_load_gpr_T0(rA(ctx->opcode));
2173
        gen_op_load_gpr_T1(rB(ctx->opcode));
2174
        gen_op_add();
2175
    }
2176
    op_dcbz();
2177
    gen_op_check_reservation();
2178
}
2179

    
2180
/* icbi */
2181
GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE)
2182
{
2183
    if (rA(ctx->opcode) == 0) {
2184
        gen_op_load_gpr_T0(rB(ctx->opcode));
2185
    } else {
2186
        gen_op_load_gpr_T0(rA(ctx->opcode));
2187
        gen_op_load_gpr_T1(rB(ctx->opcode));
2188
        gen_op_add();
2189
    }
2190
    gen_op_icbi();
2191
}
2192

    
2193
/* Optional: */
2194
/* dcba */
2195
GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_OPT)
2196
{
2197
}
2198

    
2199
/***                    Segment register manipulation                      ***/
2200
/* Supervisor only: */
2201
/* mfsr */
2202
GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT)
2203
{
2204
#if defined(CONFIG_USER_ONLY)
2205
    RET_PRIVREG(ctx);
2206
#else
2207
    if (!ctx->supervisor) {
2208
        RET_PRIVREG(ctx);
2209
        return;
2210
    }
2211
    gen_op_load_sr(SR(ctx->opcode));
2212
    gen_op_store_T0_gpr(rD(ctx->opcode));
2213
#endif
2214
}
2215

    
2216
/* mfsrin */
2217
GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT)
2218
{
2219
#if defined(CONFIG_USER_ONLY)
2220
    RET_PRIVREG(ctx);
2221
#else
2222
    if (!ctx->supervisor) {
2223
        RET_PRIVREG(ctx);
2224
        return;
2225
    }
2226
    gen_op_load_gpr_T1(rB(ctx->opcode));
2227
    gen_op_load_srin();
2228
    gen_op_store_T0_gpr(rD(ctx->opcode));
2229
#endif
2230
}
2231

    
2232
/* mtsr */
2233
GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT)
2234
{
2235
#if defined(CONFIG_USER_ONLY)
2236
    RET_PRIVREG(ctx);
2237
#else
2238
    if (!ctx->supervisor) {
2239
        RET_PRIVREG(ctx);
2240
        return;
2241
    }
2242
    gen_op_load_gpr_T0(rS(ctx->opcode));
2243
    gen_op_store_sr(SR(ctx->opcode));
2244
#endif
2245
}
2246

    
2247
/* mtsrin */
2248
GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT)
2249
{
2250
#if defined(CONFIG_USER_ONLY)
2251
    RET_PRIVREG(ctx);
2252
#else
2253
    if (!ctx->supervisor) {
2254
        RET_PRIVREG(ctx);
2255
        return;
2256
    }
2257
    gen_op_load_gpr_T0(rS(ctx->opcode));
2258
    gen_op_load_gpr_T1(rB(ctx->opcode));
2259
    gen_op_store_srin();
2260
#endif
2261
}
2262

    
2263
/***                      Lookaside buffer management                      ***/
2264
/* Optional & supervisor only: */
2265
/* tlbia */
2266
GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA)
2267
{
2268
#if defined(CONFIG_USER_ONLY)
2269
    RET_PRIVOPC(ctx);
2270
#else
2271
    if (!ctx->supervisor) {
2272
        if (loglevel)
2273
            fprintf(logfile, "%s: ! supervisor\n", __func__);
2274
        RET_PRIVOPC(ctx);
2275
        return;
2276
    }
2277
    gen_op_tlbia();
2278
    RET_MTMSR(ctx);
2279
#endif
2280
}
2281

    
2282
/* tlbie */
2283
GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM)
2284
{
2285
#if defined(CONFIG_USER_ONLY)
2286
    RET_PRIVOPC(ctx);
2287
#else
2288
    if (!ctx->supervisor) {
2289
        RET_PRIVOPC(ctx);
2290
        return;
2291
    }
2292
    gen_op_load_gpr_T0(rB(ctx->opcode));
2293
    gen_op_tlbie();
2294
    RET_MTMSR(ctx);
2295
#endif
2296
}
2297

    
2298
/* tlbsync */
2299
GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM)
2300
{
2301
#if defined(CONFIG_USER_ONLY)
2302
    RET_PRIVOPC(ctx);
2303
#else
2304
    if (!ctx->supervisor) {
2305
        RET_PRIVOPC(ctx);
2306
        return;
2307
    }
2308
    /* This has no effect: it should ensure that all previous
2309
     * tlbie have completed
2310
     */
2311
    RET_MTMSR(ctx);
2312
#endif
2313
}
2314

    
2315
/***                              External control                         ***/
2316
/* Optional: */
2317
#define op_eciwx() (*gen_op_eciwx[ctx->mem_idx])()
2318
#define op_ecowx() (*gen_op_ecowx[ctx->mem_idx])()
2319
#if defined(CONFIG_USER_ONLY)
2320
static GenOpFunc *gen_op_eciwx[] = {
2321
    &gen_op_eciwx_raw,
2322
    &gen_op_eciwx_le_raw,
2323
};
2324
static GenOpFunc *gen_op_ecowx[] = {
2325
    &gen_op_ecowx_raw,
2326
    &gen_op_ecowx_le_raw,
2327
};
2328
#else
2329
static GenOpFunc *gen_op_eciwx[] = {
2330
    &gen_op_eciwx_user,
2331
    &gen_op_eciwx_le_user,
2332
    &gen_op_eciwx_kernel,
2333
    &gen_op_eciwx_le_kernel,
2334
};
2335
static GenOpFunc *gen_op_ecowx[] = {
2336
    &gen_op_ecowx_user,
2337
    &gen_op_ecowx_le_user,
2338
    &gen_op_ecowx_kernel,
2339
    &gen_op_ecowx_le_kernel,
2340
};
2341
#endif
2342

    
2343
/* eciwx */
2344
GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN)
2345
{
2346
    /* Should check EAR[E] & alignment ! */
2347
    if (rA(ctx->opcode) == 0) {
2348
        gen_op_load_gpr_T0(rB(ctx->opcode));
2349
    } else {
2350
        gen_op_load_gpr_T0(rA(ctx->opcode));
2351
        gen_op_load_gpr_T1(rB(ctx->opcode));
2352
        gen_op_add();
2353
    }
2354
    op_eciwx();
2355
    gen_op_store_T0_gpr(rD(ctx->opcode));
2356
}
2357

    
2358
/* ecowx */
2359
GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN)
2360
{
2361
    /* Should check EAR[E] & alignment ! */
2362
    if (rA(ctx->opcode) == 0) {
2363
        gen_op_load_gpr_T0(rB(ctx->opcode));
2364
    } else {
2365
        gen_op_load_gpr_T0(rA(ctx->opcode));
2366
        gen_op_load_gpr_T1(rB(ctx->opcode));
2367
        gen_op_add();
2368
    }
2369
    gen_op_load_gpr_T2(rS(ctx->opcode));
2370
    op_ecowx();
2371
}
2372

    
2373
/* End opcode list */
2374
GEN_OPCODE_MARK(end);
2375

    
2376
#include "translate_init.c"
2377

    
2378
/*****************************************************************************/
2379
/* Misc PowerPC helpers */
2380
void cpu_dump_state(CPUState *env, FILE *f, 
2381
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
2382
                    int flags)
2383
{
2384
#if defined(TARGET_PPC64) || 1
2385
#define FILL ""
2386
#define REGX "%016llx"
2387
#define RGPL  4
2388
#define RFPL  4
2389
#else
2390
#define FILL "        "
2391
#define REGX "%08llx"
2392
#define RGPL  8
2393
#define RFPL  4
2394
#endif
2395

    
2396
    int i;
2397

    
2398
    cpu_fprintf(f, "NIP " REGX " LR " REGX " CTR " REGX "\n",
2399
                env->nip, env->lr, env->ctr);
2400
    cpu_fprintf(f, "MSR " REGX FILL " XER %08x      TB %08x %08x DECR %08x\n",
2401
                do_load_msr(env), do_load_xer(env), cpu_ppc_load_tbu(env),
2402
                cpu_ppc_load_tbl(env), cpu_ppc_load_decr(env));
2403
        for (i = 0; i < 32; i++) {
2404
        if ((i & (RGPL - 1)) == 0)
2405
            cpu_fprintf(f, "GPR%02d", i);
2406
        cpu_fprintf(f, " " REGX, env->gpr[i]);
2407
        if ((i & (RGPL - 1)) == (RGPL - 1))
2408
            cpu_fprintf(f, "\n");
2409
        }
2410
    cpu_fprintf(f, "CR ");
2411
        for (i = 0; i < 8; i++)
2412
        cpu_fprintf(f, "%01x", env->crf[i]);
2413
    cpu_fprintf(f, "  [");
2414
        for (i = 0; i < 8; i++) {
2415
            char a = '-';
2416
            if (env->crf[i] & 0x08)
2417
                a = 'L';
2418
            else if (env->crf[i] & 0x04)
2419
                a = 'G';
2420
            else if (env->crf[i] & 0x02)
2421
                a = 'E';
2422
        cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
2423
        }
2424
    cpu_fprintf(f, " ]             " FILL "RES " REGX "\n", env->reserve);
2425
    for (i = 0; i < 32; i++) {
2426
        if ((i & (RFPL - 1)) == 0)
2427
            cpu_fprintf(f, "FPR%02d", i);
2428
        cpu_fprintf(f, " %016llx", *((uint64_t *)&env->fpr[i]));
2429
        if ((i & (RFPL - 1)) == (RFPL - 1))
2430
            cpu_fprintf(f, "\n");
2431
    }
2432
    cpu_fprintf(f, "SRR0 " REGX " SRR1 " REGX "         " FILL FILL FILL
2433
                "SDR1 " REGX "\n",
2434
                env->spr[SPR_SRR0], env->spr[SPR_SRR1], env->sdr1);
2435

    
2436
#undef REGX
2437
#undef RGPL
2438
#undef RFPL
2439
#undef FILL
2440
}
2441

    
2442
/*****************************************************************************/
2443
int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
2444
                                    int search_pc)
2445
{
2446
    DisasContext ctx, *ctxp = &ctx;
2447
    opc_handler_t **table, *handler;
2448
    target_ulong pc_start;
2449
    uint16_t *gen_opc_end;
2450
    int j, lj = -1;
2451

    
2452
    pc_start = tb->pc;
2453
    gen_opc_ptr = gen_opc_buf;
2454
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
2455
    gen_opparam_ptr = gen_opparam_buf;
2456
    ctx.nip = pc_start;
2457
    ctx.tb = tb;
2458
    ctx.exception = EXCP_NONE;
2459
    ctx.spr_cb = env->spr_cb;
2460
#if defined(CONFIG_USER_ONLY)
2461
    ctx.mem_idx = msr_le;
2462
#else
2463
    ctx.supervisor = 1 - msr_pr;
2464
    ctx.mem_idx = ((1 - msr_pr) << 1) | msr_le;
2465
#endif
2466
    ctx.fpu_enabled = msr_fp;
2467
#if defined (DO_SINGLE_STEP) && 0
2468
    /* Single step trace mode */
2469
    msr_se = 1;
2470
#endif
2471
    /* Set env in case of segfault during code fetch */
2472
    while (ctx.exception == EXCP_NONE && gen_opc_ptr < gen_opc_end) {
2473
        if (search_pc) {
2474
            j = gen_opc_ptr - gen_opc_buf;
2475
            if (lj < j) {
2476
                lj++;
2477
                while (lj < j)
2478
                    gen_opc_instr_start[lj++] = 0;
2479
                gen_opc_pc[lj] = ctx.nip;
2480
                gen_opc_instr_start[lj] = 1;
2481
            }
2482
        }
2483
#if defined PPC_DEBUG_DISAS
2484
        if (loglevel & CPU_LOG_TB_IN_ASM) {
2485
            fprintf(logfile, "----------------\n");
2486
            fprintf(logfile, "nip=%08x super=%d ir=%d\n",
2487
                    ctx.nip, 1 - msr_pr, msr_ir);
2488
        }
2489
#endif
2490
        ctx.opcode = ldl_code(ctx.nip);
2491
        if (msr_le) {
2492
            ctx.opcode = ((ctx.opcode & 0xFF000000) >> 24) |
2493
                ((ctx.opcode & 0x00FF0000) >> 8) |
2494
                ((ctx.opcode & 0x0000FF00) << 8) |
2495
                ((ctx.opcode & 0x000000FF) << 24);
2496
        }
2497
#if defined PPC_DEBUG_DISAS
2498
        if (loglevel & CPU_LOG_TB_IN_ASM) {
2499
            fprintf(logfile, "translate opcode %08x (%02x %02x %02x) (%s)\n",
2500
                    ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
2501
                    opc3(ctx.opcode), msr_le ? "little" : "big");
2502
        }
2503
#endif
2504
        ctx.nip += 4;
2505
        table = env->opcodes;
2506
        handler = table[opc1(ctx.opcode)];
2507
        if (is_indirect_opcode(handler)) {
2508
            table = ind_table(handler);
2509
            handler = table[opc2(ctx.opcode)];
2510
            if (is_indirect_opcode(handler)) {
2511
                table = ind_table(handler);
2512
                handler = table[opc3(ctx.opcode)];
2513
            }
2514
        }
2515
        /* Is opcode *REALLY* valid ? */
2516
                if (handler->handler == &gen_invalid) {
2517
            if (loglevel > 0) {
2518
                    fprintf(logfile, "invalid/unsupported opcode: "
2519
                        "%02x - %02x - %02x (%08x) 0x%08x %d\n",
2520
                            opc1(ctx.opcode), opc2(ctx.opcode),
2521
                        opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, msr_ir);
2522
            } else {
2523
                printf("invalid/unsupported opcode: "
2524
                       "%02x - %02x - %02x (%08x) 0x%08x %d\n",
2525
                       opc1(ctx.opcode), opc2(ctx.opcode),
2526
                       opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, msr_ir);
2527
            }
2528
                } else {
2529
            if ((ctx.opcode & handler->inval) != 0) {
2530
                if (loglevel > 0) {
2531
                    fprintf(logfile, "invalid bits: %08x for opcode: "
2532
                            "%02x -%02x - %02x (0x%08x) (0x%08x)\n",
2533
                            ctx.opcode & handler->inval, opc1(ctx.opcode),
2534
                            opc2(ctx.opcode), opc3(ctx.opcode),
2535
                            ctx.opcode, ctx.nip - 4);
2536
                } else {
2537
                    printf("invalid bits: %08x for opcode: "
2538
                           "%02x -%02x - %02x (0x%08x) (0x%08x)\n",
2539
                            ctx.opcode & handler->inval, opc1(ctx.opcode),
2540
                            opc2(ctx.opcode), opc3(ctx.opcode),
2541
                           ctx.opcode, ctx.nip - 4);
2542
            }
2543
                RET_INVAL(ctxp);
2544
                break;
2545
            }
2546
        }
2547
        (*(handler->handler))(&ctx);
2548
        /* Check trace mode exceptions */
2549
        if ((msr_be && ctx.exception == EXCP_BRANCH) ||
2550
            /* Check in single step trace mode
2551
             * we need to stop except if:
2552
             * - rfi, trap or syscall
2553
             * - first instruction of an exception handler
2554
             */
2555
            (msr_se && (ctx.nip < 0x100 ||
2556
                        ctx.nip > 0xF00 ||
2557
                        (ctx.nip & 0xFC) != 0x04) &&
2558
             ctx.exception != EXCP_SYSCALL && ctx.exception != EXCP_RFI &&
2559
             ctx.exception != EXCP_TRAP)) {
2560
            RET_EXCP(ctxp, EXCP_TRACE, 0);
2561
        }
2562
        /* if we reach a page boundary, stop generation */
2563
        if ((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) {
2564
            break;
2565
    }
2566
#if defined (DO_SINGLE_STEP)
2567
        break;
2568
#endif
2569
    }
2570
    if (ctx.exception == EXCP_NONE) {
2571
        gen_op_b((unsigned long)ctx.tb, ctx.nip);
2572
    } else if (ctx.exception != EXCP_BRANCH) {
2573
        gen_op_set_T0(0);
2574
    }
2575
#if 1
2576
    /* TO BE FIXED: T0 hasn't got a proper value, which makes tb_add_jump
2577
     *              do bad business and then qemu crashes !
2578
     */
2579
    gen_op_set_T0(0);
2580
#endif
2581
    /* Generate the return instruction */
2582
    gen_op_exit_tb();
2583
    *gen_opc_ptr = INDEX_op_end;
2584
    if (search_pc) {
2585
        j = gen_opc_ptr - gen_opc_buf;
2586
        lj++;
2587
        while (lj <= j)
2588
            gen_opc_instr_start[lj++] = 0;
2589
        tb->size = 0;
2590
#if 0
2591
        if (loglevel > 0) {
2592
            page_dump(logfile);
2593
        }
2594
#endif
2595
    } else {
2596
        tb->size = ctx.nip - pc_start;
2597
    }
2598
#ifdef DEBUG_DISAS
2599
    if (loglevel & CPU_LOG_TB_CPU) {
2600
        fprintf(logfile, "---------------- excp: %04x\n", ctx.exception);
2601
        cpu_dump_state(env, logfile, fprintf, 0);
2602
    }
2603
    if (loglevel & CPU_LOG_TB_IN_ASM) {
2604
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
2605
        target_disas(logfile, pc_start, ctx.nip - pc_start, 0);
2606
        fprintf(logfile, "\n");
2607
    }
2608
    if (loglevel & CPU_LOG_TB_OP) {
2609
        fprintf(logfile, "OP:\n");
2610
        dump_ops(gen_opc_buf, gen_opparam_buf);
2611
        fprintf(logfile, "\n");
2612
    }
2613
#endif
2614
    return 0;
2615
}
2616

    
2617
int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
2618
{
2619
    return gen_intermediate_code_internal(env, tb, 0);
2620
}
2621

    
2622
int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
2623
{
2624
    return gen_intermediate_code_internal(env, tb, 1);
2625
}