Revision 9a64fbe4 target-ppc/translate.c

b/target-ppc/translate.c
24 24

  
25 25
//#define DO_SINGLE_STEP
26 26
//#define DO_STEP_FLUSH
27
//#define DEBUG_DISAS
27 28

  
28 29
enum {
29 30
#define DEF(s, n, copy_size) INDEX_op_ ## s,
......
37 38

  
38 39
#include "gen-op.h"
39 40

  
40
typedef void (GenOpFunc)(void);
41
typedef void (GenOpFunc1)(long);
42
typedef void (GenOpFunc2)(long, long);
43
typedef void (GenOpFunc3)(long, long, long);
44

  
45 41
#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]();\
42
static GenOpFunc *NAME ## _table [8] = {                                      \
43
NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3,                                   \
44
NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7,                                   \
45
};                                                                            \
46
static inline void func(int n)                                                \
47
{                                                                             \
48
    NAME ## _table[n]();                                                      \
49
}
50

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

  
55 63
#define GEN32(func, NAME) \
56
static GenOpFunc *NAME ## _table [32] = {\
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
NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,\
62
NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,\
63
NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,\
64
NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,\
65
};\
66
static inline void func(int n)\
67
{\
68
    NAME ## _table[n]();\
69
}
70

  
71
GEN8(gen_op_load_crf_T0, gen_op_load_crf_T0_crf)
72
GEN8(gen_op_load_crf_T1, gen_op_load_crf_T1_crf)
73
GEN8(gen_op_store_T0_crf, gen_op_store_T0_crf_crf)
74
GEN8(gen_op_store_T1_crf, gen_op_store_T1_crf_crf)
64
static GenOpFunc *NAME ## _table [32] = {                                     \
65
NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3,                                   \
66
NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7,                                   \
67
NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11,                                 \
68
NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
69
NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,                               \
70
NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,                               \
71
NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,                               \
72
NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,                               \
73
};                                                                            \
74
static inline void func(int n)                                                \
75
{                                                                             \
76
    NAME ## _table[n]();                                                      \
77
}
78

  
79
/* Condition register moves */
80
GEN8(gen_op_load_crf_T0, gen_op_load_crf_T0_crf);
81
GEN8(gen_op_load_crf_T1, gen_op_load_crf_T1_crf);
82
GEN8(gen_op_store_T0_crf, gen_op_store_T0_crf_crf);
83
GEN8(gen_op_store_T1_crf, gen_op_store_T1_crf_crf);
75 84

  
76 85
/* Floating point condition and status register moves */
77 86
GEN8(gen_op_load_fpscr_T0, gen_op_load_fpscr_T0_fpscr);
......
92 101
    (*gen_op_store_T0_fpscri_fpscr_table[n])(param);
93 102
}
94 103

  
95
GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr)
96
GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr)
97
GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr)
104
/* Segment register moves */
105
GEN16(gen_op_load_sr, gen_op_load_sr);
106
GEN16(gen_op_store_sr, gen_op_store_sr);
98 107

  
99
GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr)
100
GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr)
101
GEN32(gen_op_store_T2_gpr, gen_op_store_T2_gpr_gpr)
108
/* General purpose registers moves */
109
GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr);
110
GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr);
111
GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr);
112

  
113
GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr);
114
GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr);
115
GEN32(gen_op_store_T2_gpr, gen_op_store_T2_gpr_gpr);
102 116

  
103 117
/* floating point registers moves */
104 118
GEN32(gen_op_load_fpr_FT0, gen_op_load_fpr_FT0_fpr);
......
115 129
    struct TranslationBlock *tb;
116 130
    uint32_t *nip;
117 131
    uint32_t opcode;
118
    int exception;
119
    int retcode;
120
    /* Time base */
132
    uint32_t exception;
133
    /* Time base offset */
121 134
    uint32_t tb_offset;
135
    /* Decrementer offset */
136
    uint32_t decr_offset;
137
    /* Execution mode */
138
#if !defined(CONFIG_USER_ONLY)
122 139
    int supervisor;
140
#endif
141
    /* Routine used to access memory */
142
    int mem_idx;
123 143
} DisasContext;
124 144

  
125 145
typedef struct opc_handler_t {
126 146
    /* invalid bits */
127 147
    uint32_t inval;
148
    /* instruction type */
149
    uint32_t type;
128 150
    /* handler */
129 151
    void (*handler)(DisasContext *ctx);
130 152
} opc_handler_t;
131 153

  
132
#define SET_RETVAL(n)                                                         \
154
#define RET_EXCP(excp, error)                                                 \
133 155
do {                                                                          \
134
    if ((n) != 0) {                                                           \
135
        ctx->exception = (n);                                                 \
136
    }                                                                         \
156
    gen_op_queue_exception_err(excp, error);                                  \
157
    ctx->exception = excp;                                                    \
137 158
    return;                                                                   \
138 159
} while (0)
139 160

  
140
#define GET_RETVAL(func, __opcode)                                            \
141
({                                                                            \
142
    (func)(&ctx);                                                             \
143
    ctx.exception;                                                            \
144
})
161
#define RET_INVAL()                                                           \
162
RET_EXCP(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL)
163

  
164
#define RET_PRIVOPC()                                                         \
165
RET_EXCP(EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_OPC)
166

  
167
#define RET_PRIVREG()                                                         \
168
RET_EXCP(EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG)
145 169

  
146 170
#define GEN_HANDLER(name, opc1, opc2, opc3, inval, type)                      \
147 171
static void gen_##name (DisasContext *ctx);                                   \
148 172
GEN_OPCODE(name, opc1, opc2, opc3, inval, type);                              \
149 173
static void gen_##name (DisasContext *ctx)
150 174

  
151
/* Instruction types */
152
enum {
153
    PPC_INTEGER  = 0x0001, /* CPU has integer operations instructions        */
154
    PPC_FLOAT    = 0x0002, /* CPU has floating point operations instructions */
155
    PPC_FLOW     = 0x0004, /* CPU has flow control instructions              */
156
    PPC_MEM      = 0x0008, /* CPU has virtual memory instructions            */
157
    PPC_MISC     = 0x0010, /* CPU has spr/msr access instructions            */
158
    PPC_EXTERN   = 0x0020, /* CPU has external control instructions          */
159
    PPC_SEGMENT  = 0x0040, /* CPU has memory segment instructions            */
160
};
161

  
162 175
typedef struct opcode_t {
163 176
    unsigned char opc1, opc2, opc3;
164
    uint32_t type;
165 177
    opc_handler_t handler;
166 178
} opcode_t;
167 179

  
......
169 181
extern FILE *logfile;
170 182
extern int loglevel;
171 183

  
172
/* XXX: shouldn't stay all alone here ! */
173
static int reserve = 0;
174

  
175 184
/***                           Instruction decoding                        ***/
176 185
#define EXTRACT_HELPER(name, shift, nb)                                       \
177 186
static inline uint32_t name (uint32_t opcode)                                 \
......
272 281
    .opc1 = op1,                                                              \
273 282
    .opc2 = op2,                                                              \
274 283
    .opc3 = op3,                                                              \
275
    .type = _typ,                                                             \
276 284
    .handler = {                                                              \
277 285
        .inval   = invl,                                                      \
286
        .type = _typ,                                                         \
278 287
        .handler = &gen_##name,                                               \
279 288
    },                                                                        \
280 289
}
......
285 294
    .opc1 = 0xFF,                                                             \
286 295
    .opc2 = 0xFF,                                                             \
287 296
    .opc3 = 0xFF,                                                             \
288
    .type = 0x00,                                                             \
289 297
    .handler = {                                                              \
290 298
        .inval   = 0x00000000,                                                \
299
        .type = 0x00,                                                         \
291 300
        .handler = NULL,                                                      \
292 301
    },                                                                        \
293 302
}
......
296 305
GEN_OPCODE_MARK(start);
297 306

  
298 307
/* Invalid instruction */
299
GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, 0)
308
GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE)
309
{
310
    RET_INVAL();
311
}
312

  
313
/* Special opcode to stop emulation */
314
GEN_HANDLER(stop, 0x06, 0x00, 0xFF, 0x03FFFFC1, PPC_COMMON)
300 315
{
301
    /* Branch to next instruction to force nip update */
302
    gen_op_b((uint32_t)ctx->nip);
303
    SET_RETVAL(EXCP_INVAL);
316
    gen_op_queue_exception(EXCP_HLT);
317
    ctx->exception = EXCP_HLT;
318
}
319

  
320
/* Special opcode to call open-firmware */
321
GEN_HANDLER(of_enter, 0x06, 0x01, 0xFF, 0x03FFFFC1, PPC_COMMON)
322
{
323
    gen_op_queue_exception(EXCP_OFCALL);
324
    ctx->exception = EXCP_OFCALL;
325
}
326

  
327
/* Special opcode to call RTAS */
328
GEN_HANDLER(rtas_enter, 0x06, 0x02, 0xFF, 0x03FFFFC1, PPC_COMMON)
329
{
330
    printf("RTAS entry point !\n");
331
    gen_op_queue_exception(EXCP_RTASCALL);
332
    ctx->exception = EXCP_RTASCALL;
304 333
}
305 334

  
306 335
static opc_handler_t invalid_handler = {
307 336
    .inval   = 0xFFFFFFFF,
337
    .type    = PPC_NONE,
308 338
    .handler = gen_invalid,
309 339
};
310 340

  
......
318 348
    if (Rc(ctx->opcode) != 0)                                                 \
319 349
        gen_op_set_Rc0();                                                     \
320 350
    gen_op_store_T0_gpr(rD(ctx->opcode));                                     \
321
    SET_RETVAL(0);                                                            \
322 351
}
323 352

  
324 353
#define __GEN_INT_ARITH2_O(name, opc1, opc2, opc3, inval)                     \
......
330 359
    if (Rc(ctx->opcode) != 0)                                                 \
331 360
        gen_op_set_Rc0_ov();                                                  \
332 361
    gen_op_store_T0_gpr(rD(ctx->opcode));                                     \
333
    SET_RETVAL(0);                                                            \
334 362
}
335 363

  
336 364
#define __GEN_INT_ARITH1(name, opc1, opc2, opc3)                              \
......
341 369
    if (Rc(ctx->opcode) != 0)                                                 \
342 370
        gen_op_set_Rc0();                                                     \
343 371
    gen_op_store_T0_gpr(rD(ctx->opcode));                                     \
344
    SET_RETVAL(0);                                                            \
345 372
}
346 373
#define __GEN_INT_ARITH1_O(name, opc1, opc2, opc3)                            \
347 374
GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, PPC_INTEGER)                  \
......
351 378
    if (Rc(ctx->opcode) != 0)                                                 \
352 379
        gen_op_set_Rc0_ov();                                                  \
353 380
    gen_op_store_T0_gpr(rD(ctx->opcode));                                     \
354
    SET_RETVAL(0);                                                            \
355 381
}
356 382

  
357 383
/* Two operands arithmetic functions */
......
412 438
        gen_op_addi(simm);
413 439
    }
414 440
    gen_op_store_T0_gpr(rD(ctx->opcode));
415
    SET_RETVAL(0);
416 441
}
417 442
/* addic */
418 443
GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
......
420 445
    gen_op_load_gpr_T0(rA(ctx->opcode));
421 446
    gen_op_addic(SIMM(ctx->opcode));
422 447
    gen_op_store_T0_gpr(rD(ctx->opcode));
423
    SET_RETVAL(0);
424 448
}
425 449
/* addic. */
426 450
GEN_HANDLER(addic_, 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
......
429 453
    gen_op_addic(SIMM(ctx->opcode));
430 454
    gen_op_set_Rc0();
431 455
    gen_op_store_T0_gpr(rD(ctx->opcode));
432
    SET_RETVAL(0);
433 456
}
434 457
/* addis */
435 458
GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
......
443 466
        gen_op_addi(simm << 16);
444 467
    }
445 468
    gen_op_store_T0_gpr(rD(ctx->opcode));
446
    SET_RETVAL(0);
447 469
}
448 470
/* mulli */
449 471
GEN_HANDLER(mulli, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
......
451 473
    gen_op_load_gpr_T0(rA(ctx->opcode));
452 474
    gen_op_mulli(SIMM(ctx->opcode));
453 475
    gen_op_store_T0_gpr(rD(ctx->opcode));
454
    SET_RETVAL(0);
455 476
}
456 477
/* subfic */
457 478
GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
......
459 480
    gen_op_load_gpr_T0(rA(ctx->opcode));
460 481
    gen_op_subfic(SIMM(ctx->opcode));
461 482
    gen_op_store_T0_gpr(rD(ctx->opcode));
462
    SET_RETVAL(0);
463 483
}
464 484

  
465 485
/***                           Integer comparison                          ***/
......
470 490
    gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
471 491
    gen_op_##name();                                                          \
472 492
    gen_op_store_T0_crf(crfD(ctx->opcode));                                   \
473
    SET_RETVAL(0);                                                            \
474 493
}
475 494

  
476 495
/* cmp */
......
481 500
    gen_op_load_gpr_T0(rA(ctx->opcode));
482 501
    gen_op_cmpi(SIMM(ctx->opcode));
483 502
    gen_op_store_T0_crf(crfD(ctx->opcode));
484
    SET_RETVAL(0);
485 503
}
486 504
/* cmpl */
487 505
GEN_CMP(cmpl, 0x01);
......
491 509
    gen_op_load_gpr_T0(rA(ctx->opcode));
492 510
    gen_op_cmpli(UIMM(ctx->opcode));
493 511
    gen_op_store_T0_crf(crfD(ctx->opcode));
494
    SET_RETVAL(0);
495 512
}
496 513

  
497 514
/***                            Integer logical                            ***/
......
504 521
    if (Rc(ctx->opcode) != 0)                                                 \
505 522
        gen_op_set_Rc0();                                                     \
506 523
    gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
507
    SET_RETVAL(0);                                                            \
508 524
}
509 525
#define GEN_LOGICAL2(name, opc)                                               \
510 526
__GEN_LOGICAL2(name, 0x1C, opc)
......
517 533
    if (Rc(ctx->opcode) != 0)                                                 \
518 534
        gen_op_set_Rc0();                                                     \
519 535
    gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
520
    SET_RETVAL(0);                                                            \
521 536
}
522 537

  
523 538
/* and & and. */
......
531 546
    gen_op_andi_(UIMM(ctx->opcode));
532 547
    gen_op_set_Rc0();
533 548
    gen_op_store_T0_gpr(rA(ctx->opcode));
534
    SET_RETVAL(0);
535 549
}
536 550
/* andis. */
537 551
GEN_HANDLER(andis_, 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
......
540 554
    gen_op_andi_(UIMM(ctx->opcode) << 16);
541 555
    gen_op_set_Rc0();
542 556
    gen_op_store_T0_gpr(rA(ctx->opcode));
543
    SET_RETVAL(0);
544 557
}
545 558

  
546 559
/* cntlzw */
......
555 568
GEN_LOGICAL2(nand, 0x0E);
556 569
/* nor & nor. */
557 570
GEN_LOGICAL2(nor, 0x03);
571

  
558 572
/* or & or. */
559
GEN_LOGICAL2(or, 0x0D);
573
GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER)
574
{
575
    gen_op_load_gpr_T0(rS(ctx->opcode));
576
    /* Optimisation for mr case */
577
    if (rS(ctx->opcode) != rB(ctx->opcode)) {
578
        gen_op_load_gpr_T1(rB(ctx->opcode));
579
        gen_op_or();
580
    }
581
    if (Rc(ctx->opcode) != 0)
582
        gen_op_set_Rc0();
583
    gen_op_store_T0_gpr(rA(ctx->opcode));
584
}
585

  
560 586
/* orc & orc. */
561 587
GEN_LOGICAL2(orc, 0x0C);
562 588
/* xor & xor. */
563
GEN_LOGICAL2(xor, 0x09);
589
GEN_HANDLER(xor, 0x1F, 0x1C, 0x09, 0x00000000, PPC_INTEGER)
590
{
591
    gen_op_load_gpr_T0(rS(ctx->opcode));
592
    /* Optimisation for "set to zero" case */
593
    if (rS(ctx->opcode) != rB(ctx->opcode)) {
594
        gen_op_load_gpr_T1(rB(ctx->opcode));
595
        gen_op_xor();
596
    } else {
597
        gen_op_set_T0(0);
598
    }
599
    if (Rc(ctx->opcode) != 0)
600
        gen_op_set_Rc0();
601
    gen_op_store_T0_gpr(rA(ctx->opcode));
602
}
564 603
/* ori */
565 604
GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
566 605
{
567 606
    uint32_t uimm = UIMM(ctx->opcode);
568 607

  
569
#if 0
570
    if (uimm == 0) {
571
        if (rA(ctx->opcode) != rS(ctx->opcode)) {
572
            gen_op_load_gpr_T0(rS(ctx->opcode));
573
            gen_op_store_T0_gpr(rA(ctx->opcode));
608
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
609
        /* NOP */
610
        return;
574 611
        }
575
    } else
576
#endif
577
    {
578 612
        gen_op_load_gpr_T0(rS(ctx->opcode));
613
    if (uimm != 0)
579 614
        gen_op_ori(uimm);
580 615
        gen_op_store_T0_gpr(rA(ctx->opcode));
581
    }
582
    SET_RETVAL(0);
583 616
}
584 617
/* oris */
585 618
GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
586 619
{
587 620
    uint32_t uimm = UIMM(ctx->opcode);
588 621

  
589
#if 0
590
    if (uimm == 0) {
591
        if (rA(ctx->opcode) != rS(ctx->opcode)) {
592
            gen_op_load_gpr_T0(rS(ctx->opcode));
593
            gen_op_store_T0_gpr(rA(ctx->opcode));
622
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
623
        /* NOP */
624
        return;
594 625
        }
595
    } else
596
#endif
597
    {
598 626
        gen_op_load_gpr_T0(rS(ctx->opcode));
627
    if (uimm != 0)
599 628
        gen_op_ori(uimm << 16);
600 629
        gen_op_store_T0_gpr(rA(ctx->opcode));
601
    }
602
    SET_RETVAL(0);
603 630
}
604 631
/* xori */
605 632
GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
606 633
{
634
    uint32_t uimm = UIMM(ctx->opcode);
635

  
636
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
637
        /* NOP */
638
        return;
639
    }
607 640
    gen_op_load_gpr_T0(rS(ctx->opcode));
641
    if (uimm != 0)
608 642
    gen_op_xori(UIMM(ctx->opcode));
609 643
    gen_op_store_T0_gpr(rA(ctx->opcode));
610
    SET_RETVAL(0);
611 644
}
612 645

  
613 646
/* xoris */
614 647
GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
615 648
{
649
    uint32_t uimm = UIMM(ctx->opcode);
650

  
651
    if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
652
        /* NOP */
653
        return;
654
    }
616 655
    gen_op_load_gpr_T0(rS(ctx->opcode));
656
    if (uimm != 0)
617 657
    gen_op_xori(UIMM(ctx->opcode) << 16);
618 658
    gen_op_store_T0_gpr(rA(ctx->opcode));
619
    SET_RETVAL(0);
620 659
}
621 660

  
622 661
/***                             Integer rotate                            ***/
......
633 672
    if (Rc(ctx->opcode) != 0)
634 673
        gen_op_set_Rc0();
635 674
    gen_op_store_T0_gpr(rA(ctx->opcode));
636
    SET_RETVAL(0);
637 675
}
638 676
/* rlwinm & rlwinm. */
639 677
GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
......
644 682
    mb = MB(ctx->opcode);
645 683
    me = ME(ctx->opcode);
646 684
    gen_op_load_gpr_T0(rS(ctx->opcode));
647
    if (loglevel > 0) {
648
        fprintf(logfile, "%s sh=%u mb=%u me=%u MASK=0x%08x\n",
649
                __func__, sh, mb, me, MASK(mb, me));
650
    }
651 685
    if (mb == 0) {
652 686
        if (me == 31) {
653 687
            gen_op_rotlwi(sh);
......
673 707
    if (Rc(ctx->opcode) != 0)
674 708
        gen_op_set_Rc0();
675 709
    gen_op_store_T0_gpr(rA(ctx->opcode));
676
    SET_RETVAL(0);
677 710
}
678 711
/* rlwnm & rlwnm. */
679 712
GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
......
693 726
    if (Rc(ctx->opcode) != 0)
694 727
        gen_op_set_Rc0();
695 728
    gen_op_store_T0_gpr(rA(ctx->opcode));
696
    SET_RETVAL(0);
697 729
}
698 730

  
699 731
/***                             Integer shift                             ***/
......
709 741
    if (Rc(ctx->opcode) != 0)
710 742
        gen_op_set_Rc0();
711 743
    gen_op_store_T0_gpr(rA(ctx->opcode));
712
    SET_RETVAL(0);
713 744
}
714 745
/* srw & srw. */
715 746
__GEN_LOGICAL2(srw, 0x18, 0x10);
716 747

  
717 748
/***                       Floating-Point arithmetic                       ***/
718
/* fadd */
719
GEN_HANDLER(fadd, 0x3F, 0x15, 0xFF, 0x000007C0, PPC_FLOAT)
720
{
721
    SET_RETVAL(EXCP_INVAL);
749
#define _GEN_FLOAT_ACB(name, op1, op2)                                        \
750
GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, PPC_FLOAT)                   \
751
{                                                                             \
752
    gen_op_reset_scrfx();                                                     \
753
    gen_op_load_fpr_FT0(rA(ctx->opcode));                                     \
754
    gen_op_load_fpr_FT1(rC(ctx->opcode));                                     \
755
    gen_op_load_fpr_FT2(rB(ctx->opcode));                                     \
756
    gen_op_f##name();                                                         \
757
    gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
758
    if (Rc(ctx->opcode))                                                      \
759
        gen_op_set_Rc1();                                                     \
760
}
761

  
762
#define GEN_FLOAT_ACB(name, op2)                                              \
763
_GEN_FLOAT_ACB(name, 0x3F, op2);                                              \
764
_GEN_FLOAT_ACB(name##s, 0x3B, op2);
765

  
766
#define _GEN_FLOAT_AB(name, op1, op2, inval)                                  \
767
GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT)                        \
768
{                                                                             \
769
    gen_op_reset_scrfx();                                                     \
770
    gen_op_load_fpr_FT0(rA(ctx->opcode));                                     \
771
    gen_op_load_fpr_FT1(rB(ctx->opcode));                                     \
772
    gen_op_f##name();                                                         \
773
    gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
774
    if (Rc(ctx->opcode))                                                      \
775
        gen_op_set_Rc1();                                                     \
776
}
777
#define GEN_FLOAT_AB(name, op2, inval)                                        \
778
_GEN_FLOAT_AB(name, 0x3F, op2, inval);                                        \
779
_GEN_FLOAT_AB(name##s, 0x3B, op2, inval);
780

  
781
#define _GEN_FLOAT_AC(name, op1, op2, inval)                                  \
782
GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT)                        \
783
{                                                                             \
784
    gen_op_reset_scrfx();                                                     \
785
    gen_op_load_fpr_FT0(rA(ctx->opcode));                                     \
786
    gen_op_load_fpr_FT1(rC(ctx->opcode));                                     \
787
    gen_op_f##name();                                                         \
788
    gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
789
    if (Rc(ctx->opcode))                                                      \
790
        gen_op_set_Rc1();                                                     \
791
}
792
#define GEN_FLOAT_AC(name, op2, inval)                                        \
793
_GEN_FLOAT_AC(name, 0x3F, op2, inval);                                        \
794
_GEN_FLOAT_AC(name##s, 0x3B, op2, inval);
795

  
796
#define GEN_FLOAT_B(name, op2, op3)                                           \
797
GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, PPC_FLOAT)                   \
798
{                                                                             \
799
    gen_op_reset_scrfx();                                                     \
800
    gen_op_load_fpr_FT0(rB(ctx->opcode));                                     \
801
    gen_op_f##name();                                                         \
802
    gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
803
    if (Rc(ctx->opcode))                                                      \
804
        gen_op_set_Rc1();                                                     \
722 805
}
723 806

  
724
/* fadds */
725
GEN_HANDLER(fadds, 0x3B, 0x15, 0xFF, 0x000007C0, PPC_FLOAT)
726
{
727
    SET_RETVAL(EXCP_INVAL);
807
#define GEN_FLOAT_BS(name, op2)                                               \
808
GEN_HANDLER(f##name, 0x3F, op2, 0xFF, 0x001F07C0, PPC_FLOAT)                  \
809
{                                                                             \
810
    gen_op_reset_scrfx();                                                     \
811
    gen_op_load_fpr_FT0(rB(ctx->opcode));                                     \
812
    gen_op_f##name();                                                         \
813
    gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
814
    if (Rc(ctx->opcode))                                                      \
815
        gen_op_set_Rc1();                                                     \
728 816
}
729 817

  
818
/* fadd - fadds */
819
GEN_FLOAT_AB(add, 0x15, 0x000007C0);
730 820
/* fdiv */
731
GEN_HANDLER(fdiv, 0x3F, 0x12, 0xFF, 0x000007C0, PPC_FLOAT)
732
{
733
    SET_RETVAL(EXCP_INVAL);
734
}
735

  
736
/* fdivs */
737
GEN_HANDLER(fdivs, 0x3B, 0x12, 0xFF, 0x000007C0, PPC_FLOAT)
738
{
739
    SET_RETVAL(EXCP_INVAL);
740
}
741

  
821
GEN_FLOAT_AB(div, 0x12, 0x000007C0);
742 822
/* fmul */
743
GEN_HANDLER(fmul, 0x3F, 0x19, 0xFF, 0x0000F800, PPC_FLOAT)
744
{
745
    SET_RETVAL(EXCP_INVAL);
746
}
747

  
748
/* fmuls */
749
GEN_HANDLER(fmuls, 0x3B, 0x19, 0xFF, 0x0000F800, PPC_FLOAT)
750
{
751
    SET_RETVAL(EXCP_INVAL);
752
}
823
GEN_FLOAT_AC(mul, 0x19, 0x0000F800);
753 824

  
754 825
/* fres */
755
GEN_HANDLER(fres, 0x3B, 0x18, 0xFF, 0x001807C0, PPC_FLOAT)
756
{
757
    SET_RETVAL(EXCP_INVAL);
758
}
826
GEN_FLOAT_BS(res, 0x18);
759 827

  
760 828
/* frsqrte */
761
GEN_HANDLER(frsqrte, 0x3F, 0x1A, 0xFF, 0x001807C0, PPC_FLOAT)
762
{
763
    SET_RETVAL(EXCP_INVAL);
764
}
829
GEN_FLOAT_BS(rsqrte, 0x1A);
765 830

  
766 831
/* fsel */
767
GEN_HANDLER(fsel, 0x3F, 0x17, 0xFF, 0x00000000, PPC_FLOAT)
768
{
769
    SET_RETVAL(EXCP_INVAL);
770
}
771

  
832
_GEN_FLOAT_ACB(sel, 0x3F, 0x17);
772 833
/* fsub */
773
GEN_HANDLER(fsub, 0x3F, 0x14, 0xFF, 0x000007C0, PPC_FLOAT)
774
{
775
    SET_RETVAL(EXCP_INVAL);
776
}
777

  
778
/* fsubs */
779
GEN_HANDLER(fsubs, 0x3B, 0x14, 0xFF, 0x000007C0, PPC_FLOAT)
780
{
781
    SET_RETVAL(EXCP_INVAL);
782
}
783

  
834
GEN_FLOAT_AB(sub, 0x14, 0x000007C0);
784 835
/* Optional: */
785 836
/* fsqrt */
786
GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001807C0, PPC_FLOAT)
787
{
788
    SET_RETVAL(EXCP_INVAL);
789
}
837
GEN_FLOAT_BS(sqrt, 0x16);
790 838

  
791
/* fsqrts */
792
GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001807C0, PPC_FLOAT)
839
GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_OPT)
793 840
{
794
    SET_RETVAL(EXCP_INVAL);
841
    gen_op_reset_scrfx();
842
    gen_op_load_fpr_FT0(rB(ctx->opcode));
843
    gen_op_fsqrts();
844
    gen_op_store_FT0_fpr(rD(ctx->opcode));
845
    if (Rc(ctx->opcode))
846
        gen_op_set_Rc1();
795 847
}
796 848

  
797 849
/***                     Floating-Point multiply-and-add                   ***/
798 850
/* fmadd */
799
GEN_HANDLER(fmadd, 0x3F, 0x1D, 0xFF, 0x00000000, PPC_FLOAT)
800
{
801
    SET_RETVAL(EXCP_INVAL);
802
}
803

  
804
/* fmadds */
805
GEN_HANDLER(fmadds, 0x3B, 0x1D, 0xFF, 0x00000000, PPC_FLOAT)
806
{
807
    SET_RETVAL(EXCP_INVAL);
808
}
809

  
851
GEN_FLOAT_ACB(madd, 0x1D);
810 852
/* fmsub */
811
GEN_HANDLER(fmsub, 0x3F, 0x1C, 0xFF, 0x00000000, PPC_FLOAT)
812
{
813
    SET_RETVAL(EXCP_INVAL);
814
}
815

  
816
/* fmsubs */
817
GEN_HANDLER(fmsubs, 0x3B, 0x1C, 0xFF, 0x00000000, PPC_FLOAT)
818
{
819
    SET_RETVAL(EXCP_INVAL);
820
}
821

  
853
GEN_FLOAT_ACB(msub, 0x1C);
822 854
/* fnmadd */
823
GEN_HANDLER(fnmadd, 0x3F, 0x1F, 0xFF, 0x00000000, PPC_FLOAT)
824
{
825
    SET_RETVAL(EXCP_INVAL);
826
}
827

  
828
/* fnmadds */
829
GEN_HANDLER(fnmadds, 0x3B, 0x1F, 0xFF, 0x00000000, PPC_FLOAT)
830
{
831
    SET_RETVAL(EXCP_INVAL);
832
}
833

  
855
GEN_FLOAT_ACB(nmadd, 0x1F);
834 856
/* fnmsub */
835
GEN_HANDLER(fnmsub, 0x3F, 0x1E, 0xFF, 0x00000000, PPC_FLOAT)
836
{
837
    SET_RETVAL(EXCP_INVAL);
838
}
839

  
840
/* fnmsubs */
841
GEN_HANDLER(fnmsubs, 0x3B, 0x1E, 0xFF, 0x00000000, PPC_FLOAT)
842
{
843
    SET_RETVAL(EXCP_INVAL);
844
}
857
GEN_FLOAT_ACB(nmsub, 0x1E);
845 858

  
846 859
/***                     Floating-Point round & convert                    ***/
847 860
/* fctiw */
848
GEN_HANDLER(fctiw, 0x3F, 0x0E, 0xFF, 0x001F0000, PPC_FLOAT)
849
{
850
    SET_RETVAL(EXCP_INVAL);
851
}
852

  
861
GEN_FLOAT_B(ctiw, 0x0E, 0x00);
853 862
/* fctiwz */
854
GEN_HANDLER(fctiwz, 0x3F, 0x0F, 0xFF, 0x001F0000, PPC_FLOAT)
855
{
856
    SET_RETVAL(EXCP_INVAL);
857
}
858

  
863
GEN_FLOAT_B(ctiwz, 0x0F, 0x00);
859 864
/* frsp */
860
GEN_HANDLER(frsp, 0x3F, 0x0C, 0xFF, 0x001F0000, PPC_FLOAT)
861
{
862
    SET_RETVAL(EXCP_INVAL);
863
}
865
GEN_FLOAT_B(rsp, 0x0C, 0x00);
864 866

  
865 867
/***                         Floating-Point compare                        ***/
866 868
/* fcmpo */
867 869
GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT)
868 870
{
869
    SET_RETVAL(EXCP_INVAL);
871
    gen_op_reset_scrfx();
872
    gen_op_load_fpr_FT0(rA(ctx->opcode));
873
    gen_op_load_fpr_FT1(rB(ctx->opcode));
874
    gen_op_fcmpo();
875
    gen_op_store_T0_crf(crfD(ctx->opcode));
870 876
}
871 877

  
872 878
/* fcmpu */
873 879
GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT)
874 880
{
875
    SET_RETVAL(EXCP_INVAL);
881
    gen_op_reset_scrfx();
882
    gen_op_load_fpr_FT0(rA(ctx->opcode));
883
    gen_op_load_fpr_FT1(rB(ctx->opcode));
884
    gen_op_fcmpu();
885
    gen_op_store_T0_crf(crfD(ctx->opcode));
876 886
}
877 887

  
888
/***                         Floating-point move                           ***/
889
/* fabs */
890
GEN_FLOAT_B(abs, 0x08, 0x08);
891

  
892
/* fmr  - fmr. */
893
GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT)
894
{
895
    gen_op_reset_scrfx();
896
    gen_op_load_fpr_FT0(rB(ctx->opcode));
897
    gen_op_store_FT0_fpr(rD(ctx->opcode));
898
    if (Rc(ctx->opcode))
899
        gen_op_set_Rc1();
900
}
901

  
902
/* fnabs */
903
GEN_FLOAT_B(nabs, 0x08, 0x04);
904
/* fneg */
905
GEN_FLOAT_B(neg, 0x08, 0x01);
906

  
878 907
/***                  Floating-Point status & ctrl register                ***/
879 908
/* mcrfs */
880 909
GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT)
......
882 911
    gen_op_load_fpscr_T0(crfS(ctx->opcode));
883 912
    gen_op_store_T0_crf(crfD(ctx->opcode));
884 913
    gen_op_clear_fpscr(crfS(ctx->opcode));
885
    SET_RETVAL(0);
886 914
}
887 915

  
888 916
/* mffs */
......
892 920
    gen_op_store_FT0_fpr(rD(ctx->opcode));
893 921
    if (Rc(ctx->opcode))
894 922
        gen_op_set_Rc1();
895
    SET_RETVAL(0);
896 923
}
897 924

  
898 925
/* mtfsb0 */
......
906 933
    gen_op_store_T0_fpscr(crb);
907 934
    if (Rc(ctx->opcode))
908 935
        gen_op_set_Rc1();
909
    SET_RETVAL(0);
910 936
}
911 937

  
912 938
/* mtfsb1 */
......
920 946
    gen_op_store_T0_fpscr(crb);
921 947
    if (Rc(ctx->opcode))
922 948
        gen_op_set_Rc1();
923
    SET_RETVAL(0);
924 949
}
925 950

  
926 951
/* mtfsf */
......
930 955
    gen_op_store_fpscr(FM(ctx->opcode));
931 956
    if (Rc(ctx->opcode))
932 957
        gen_op_set_Rc1();
933
    SET_RETVAL(0);
934 958
}
935 959

  
936 960
/* mtfsfi */
......
939 963
    gen_op_store_T0_fpscri(crbD(ctx->opcode) >> 2, FPIMM(ctx->opcode));
940 964
    if (Rc(ctx->opcode))
941 965
        gen_op_set_Rc1();
942
    SET_RETVAL(0);
943 966
}
944 967

  
945 968
/***                             Integer load                              ***/
946
#define GEN_ILDZ(width, opc)                                                  \
969
#if defined(CONFIG_USER_ONLY)
970
#define op_ldst(name)        gen_op_##name##_raw()
971
#define OP_LD_TABLE(width)
972
#define OP_ST_TABLE(width)
973
#else
974
#define op_ldst(name)        (*gen_op_##name[ctx->mem_idx])()
975
#define OP_LD_TABLE(width)                                                    \
976
static GenOpFunc *gen_op_l##width[] = {                                       \
977
    &gen_op_l##width##_user,                                                  \
978
    &gen_op_l##width##_kernel,                                                \
979
}
980
#define OP_ST_TABLE(width)                                                    \
981
static GenOpFunc *gen_op_st##width[] = {                                      \
982
    &gen_op_st##width##_user,                                                 \
983
    &gen_op_st##width##_kernel,                                               \
984
}
985
#endif
986

  
987
#define GEN_LD(width, opc)                                                    \
947 988
GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)               \
948 989
{                                                                             \
949 990
    uint32_t simm = SIMM(ctx->opcode);                                        \
950 991
    if (rA(ctx->opcode) == 0) {                                               \
951
        gen_op_l##width##_z(simm);                                            \
992
        gen_op_set_T0(simm);                                                  \
952 993
    } else {                                                                  \
953 994
        gen_op_load_gpr_T0(rA(ctx->opcode));                                  \
954
        gen_op_l##width (simm);                                               \
995
        if (simm != 0)                                                        \
996
            gen_op_addi(simm);                                                \
955 997
    }                                                                         \
998
    op_ldst(l##width);                                                        \
956 999
    gen_op_store_T1_gpr(rD(ctx->opcode));                                     \
957
    SET_RETVAL(0);                                                            \
958 1000
}
959 1001

  
960
#define GEN_ILDZU(width, opc)                                                 \
1002
#define GEN_LDU(width, opc)                                                   \
961 1003
GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)            \
962 1004
{                                                                             \
1005
    uint32_t simm = SIMM(ctx->opcode);                                        \
963 1006
    if (rA(ctx->opcode) == 0 ||                                               \
964
        rA(ctx->opcode) == rD(ctx->opcode))                                   \
965
        SET_RETVAL(EXCP_INVAL);                                               \
1007
        rA(ctx->opcode) == rD(ctx->opcode)) {                                 \
1008
        RET_INVAL();                                                          \
1009
    }                                                                         \
966 1010
    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
967
    gen_op_l##width(SIMM(ctx->opcode));                                       \
1011
    if (simm != 0)                                                            \
1012
        gen_op_addi(simm);                                                    \
1013
    op_ldst(l##width);                                                        \
968 1014
    gen_op_store_T1_gpr(rD(ctx->opcode));                                     \
969 1015
    gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
970
    SET_RETVAL(0);                                                            \
971 1016
}
972 1017

  
973
#define GEN_ILDZUX(width, opc)                                                \
1018
#define GEN_LDUX(width, opc)                                                  \
974 1019
GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER)           \
975 1020
{                                                                             \
976 1021
    if (rA(ctx->opcode) == 0 ||                                               \
977
        rA(ctx->opcode) == rD(ctx->opcode))                                   \
978
        SET_RETVAL(EXCP_INVAL);                                               \
1022
        rA(ctx->opcode) == rD(ctx->opcode)) {                                 \
1023
        RET_INVAL();                                                          \
1024
    }                                                                         \
979 1025
    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
980 1026
    gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
981
    gen_op_l##width##x();                                                     \
1027
    gen_op_add();                                                             \
1028
    op_ldst(l##width);                                                        \
982 1029
    gen_op_store_T1_gpr(rD(ctx->opcode));                                     \
983 1030
    gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
984
    SET_RETVAL(0);                                                            \
985 1031
}
986 1032

  
987
#define GEN_ILDZX(width, opc2, opc3)                                          \
1033
#define GEN_LDX(width, opc2, opc3)                                            \
988 1034
GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER)           \
989 1035
{                                                                             \
990 1036
    if (rA(ctx->opcode) == 0) {                                               \
991 1037
        gen_op_load_gpr_T0(rB(ctx->opcode));                                  \
992
        gen_op_l##width##x_z();                                               \
993 1038
    } else {                                                                  \
994 1039
        gen_op_load_gpr_T0(rA(ctx->opcode));                                  \
995 1040
        gen_op_load_gpr_T1(rB(ctx->opcode));                                  \
996
        gen_op_l##width##x();                                                 \
1041
        gen_op_add();                                                         \
997 1042
    }                                                                         \
1043
    op_ldst(l##width);                                                        \
998 1044
    gen_op_store_T1_gpr(rD(ctx->opcode));                                     \
999
    SET_RETVAL(0);                                                            \
1000 1045
}
1001 1046

  
1002
#define GEN_ILD(width, op)                                                    \
1003
GEN_ILDZ(width, op | 0x20)                                                    \
1004
GEN_ILDZU(width, op | 0x21)                                                   \
1005
GEN_ILDZUX(width, op | 0x01)                                                  \
1006
GEN_ILDZX(width, 0x17, op | 0x00)
1047
#define GEN_LDS(width, op)                                                    \
1048
OP_LD_TABLE(width);                                                           \
1049
GEN_LD(width, op | 0x20);                                                     \
1050
GEN_LDU(width, op | 0x21);                                                    \
1051
GEN_LDUX(width, op | 0x01);                                                   \
1052
GEN_LDX(width, 0x17, op | 0x00)
1007 1053

  
1008 1054
/* lbz lbzu lbzux lbzx */
1009
GEN_ILD(bz, 0x02);
1055
GEN_LDS(bz, 0x02);
1010 1056
/* lha lhau lhaux lhax */
1011
GEN_ILD(ha, 0x0A);
1057
GEN_LDS(ha, 0x0A);
1012 1058
/* lhz lhzu lhzux lhzx */
1013
GEN_ILD(hz, 0x08);
1059
GEN_LDS(hz, 0x08);
1014 1060
/* lwz lwzu lwzux lwzx */
1015
GEN_ILD(wz, 0x00);
1061
GEN_LDS(wz, 0x00);
1016 1062

  
1017 1063
/***                              Integer store                            ***/
1018
#define GEN_IST(width, opc)                                                   \
1064
#define GEN_ST(width, opc)                                                    \
1019 1065
GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)              \
1020 1066
{                                                                             \
1021 1067
    uint32_t simm = SIMM(ctx->opcode);                                        \
1022 1068
    if (rA(ctx->opcode) == 0) {                                               \
1023
        gen_op_load_gpr_T0(rS(ctx->opcode));                                  \
1024
        gen_op_st##width##_z(simm);                                           \
1069
        gen_op_set_T0(simm);                                                  \
1025 1070
    } else {                                                                  \
1026 1071
        gen_op_load_gpr_T0(rA(ctx->opcode));                                  \
1027
        gen_op_load_gpr_T1(rS(ctx->opcode));                                  \
1028
        gen_op_st##width(simm);                                               \
1072
        if (simm != 0)                                                        \
1073
            gen_op_addi(simm);                                                \
1029 1074
    }                                                                         \
1030
    SET_RETVAL(0);                                                            \
1075
    gen_op_load_gpr_T1(rS(ctx->opcode));                                      \
1076
    op_ldst(st##width);                                                       \
1031 1077
}
1032 1078

  
1033
#define GEN_ISTU(width, opc)                                                  \
1079
#define GEN_STU(width, opc)                                                   \
1034 1080
GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)           \
1035 1081
{                                                                             \
1036
    if (rA(ctx->opcode) == 0)                                                 \
1037
        SET_RETVAL(EXCP_INVAL);                                               \
1082
    uint32_t simm = SIMM(ctx->opcode);                                        \
1083
    if (rA(ctx->opcode) == 0) {                                               \
1084
        RET_INVAL();                                                          \
1085
    }                                                                         \
1038 1086
    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
1087
    if (simm != 0)                                                            \
1088
        gen_op_addi(simm);                                                    \
1039 1089
    gen_op_load_gpr_T1(rS(ctx->opcode));                                      \
1040
    gen_op_st##width(SIMM(ctx->opcode));                                      \
1090
    op_ldst(st##width);                                                       \
1041 1091
    gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
1042
    SET_RETVAL(0);                                                            \
1043 1092
}
1044 1093

  
1045
#define GEN_ISTUX(width, opc)                                                 \
1094
#define GEN_STUX(width, opc)                                                  \
1046 1095
GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER)          \
1047 1096
{                                                                             \
1048
    if (rA(ctx->opcode) == 0)                                                 \
1049
        SET_RETVAL(EXCP_INVAL);                                               \
1097
    if (rA(ctx->opcode) == 0) {                                               \
1098
        RET_INVAL();                                                          \
1099
    }                                                                         \
1050 1100
    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
1051 1101
    gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
1052
    gen_op_load_gpr_T2(rS(ctx->opcode));                                      \
1053
    gen_op_st##width##x();                                                    \
1102
    gen_op_add();                                                             \
1103
    gen_op_load_gpr_T1(rS(ctx->opcode));                                      \
1104
    op_ldst(st##width);                                                       \
1054 1105
    gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
1055
    SET_RETVAL(0);                                                            \
1056 1106
}
1057 1107

  
1058
#define GEN_ISTX(width, opc2, opc3)                                           \
1108
#define GEN_STX(width, opc2, opc3)                                            \
1059 1109
GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER)          \
1060 1110
{                                                                             \
1061 1111
    if (rA(ctx->opcode) == 0) {                                               \
1062 1112
        gen_op_load_gpr_T0(rB(ctx->opcode));                                  \
1063
        gen_op_load_gpr_T1(rS(ctx->opcode));                                  \
1064
        gen_op_st##width##x_z();                                              \
1065 1113
    } else {                                                                  \
1066 1114
        gen_op_load_gpr_T0(rA(ctx->opcode));                                  \
1067 1115
        gen_op_load_gpr_T1(rB(ctx->opcode));                                  \
1068
        gen_op_load_gpr_T2(rS(ctx->opcode));                                  \
1069
        gen_op_st##width##x();                                                \
1116
        gen_op_add();                                                         \
1070 1117
    }                                                                         \
1071
    SET_RETVAL(0);                                                            \
1118
    gen_op_load_gpr_T1(rS(ctx->opcode));                                      \
1119
    op_ldst(st##width);                                                       \
1072 1120
}
1073 1121

  
1074
#define GEN_ISTO(width, opc)                                                  \
1075
GEN_IST(width, opc | 0x20)                                                    \
1076
GEN_ISTU(width, opc | 0x21)                                                   \
1077
GEN_ISTUX(width, opc | 0x01)                                                  \
1078
GEN_ISTX(width, 0x17, opc | 0x00)
1122
#define GEN_STS(width, op)                                                    \
1123
OP_ST_TABLE(width);                                                           \
1124
GEN_ST(width, op | 0x20);                                                     \
1125
GEN_STU(width, op | 0x21);                                                    \
1126
GEN_STUX(width, op | 0x01);                                                   \
1127
GEN_STX(width, 0x17, op | 0x00)
1079 1128

  
1080 1129
/* stb stbu stbux stbx */
1081
GEN_ISTO(b, 0x06);
1130
GEN_STS(b, 0x06);
1082 1131
/* sth sthu sthux sthx */
1083
GEN_ISTO(h, 0x0C);
1132
GEN_STS(h, 0x0C);
1084 1133
/* stw stwu stwux stwx */
1085
GEN_ISTO(w, 0x04);
1134
GEN_STS(w, 0x04);
1086 1135

  
1087 1136
/***                Integer load and store with byte reverse               ***/
1088 1137
/* lhbrx */
1089
GEN_ILDZX(hbr, 0x16, 0x18);
1138
OP_LD_TABLE(hbr);
1139
GEN_LDX(hbr, 0x16, 0x18);
1090 1140
/* lwbrx */
1091
GEN_ILDZX(wbr, 0x16, 0x10);
1141
OP_LD_TABLE(wbr);
1142
GEN_LDX(wbr, 0x16, 0x10);
1092 1143
/* sthbrx */
1093
GEN_ISTX(hbr, 0x16, 0x1C);
1144
OP_ST_TABLE(hbr);
1145
GEN_STX(hbr, 0x16, 0x1C);
1094 1146
/* stwbrx */
1095
GEN_ISTX(wbr, 0x16, 0x14);
1147
OP_ST_TABLE(wbr);
1148
GEN_STX(wbr, 0x16, 0x14);
1096 1149

  
1097 1150
/***                    Integer load and store multiple                    ***/
1151
#if defined(CONFIG_USER_ONLY)
1152
#define op_ldstm(name, reg) gen_op_##name##_raw(reg)
1153
#else
1154
#define op_ldstm(name, reg) (*gen_op_##name[ctx->mem_idx])(reg)
1155
static GenOpFunc1 *gen_op_lmw[] = {
1156
    &gen_op_lmw_user,
1157
    &gen_op_lmw_kernel,
1158
};
1159
static GenOpFunc1 *gen_op_stmw[] = {
1160
    &gen_op_stmw_user,
1161
    &gen_op_stmw_kernel,
1162
};
1163
#endif
1164

  
1098 1165
/* lmw */
1099 1166
GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1100 1167
{
1168
    int simm = SIMM(ctx->opcode);
1169

  
1101 1170
    if (rA(ctx->opcode) == 0) {
1102
        gen_op_set_T0(0);
1171
        gen_op_set_T0(simm);
1103 1172
    } else {
1104 1173
        gen_op_load_gpr_T0(rA(ctx->opcode));
1174
        if (simm != 0)
1175
            gen_op_addi(simm);
1105 1176
    }
1106
    gen_op_lmw(rD(ctx->opcode), SIMM(ctx->opcode));
1107
    SET_RETVAL(0);
1177
    op_ldstm(lmw, rD(ctx->opcode));
1108 1178
}
1109 1179

  
1110 1180
/* stmw */
1111 1181
GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1112 1182
{
1183
    int simm = SIMM(ctx->opcode);
1184

  
1113 1185
    if (rA(ctx->opcode) == 0) {
1114
        gen_op_set_T0(0);
1186
        gen_op_set_T0(simm);
1115 1187
    } else {
1116 1188
        gen_op_load_gpr_T0(rA(ctx->opcode));
1189
        if (simm != 0)
1190
            gen_op_addi(simm);
1117 1191
    }
1118
    gen_op_stmw(rS(ctx->opcode), SIMM(ctx->opcode));
1119
    SET_RETVAL(0);
1192
    op_ldstm(stmw, rS(ctx->opcode));
1120 1193
}
1121 1194

  
1122 1195
/***                    Integer load and store strings                     ***/
1196
#if defined(CONFIG_USER_ONLY)
1197
#define op_ldsts(name, start) gen_op_##name##_raw(start)
1198
#define op_ldstsx(name, rd, ra, rb) gen_op_##name##_raw(rd, ra, rb)
1199
#else
1200
#define op_ldsts(name, start) (*gen_op_##name[ctx->mem_idx])(start)
1201
#define op_ldstsx(name, rd, ra, rb) (*gen_op_##name[ctx->mem_idx])(rd, ra, rb)
1202
static GenOpFunc1 *gen_op_lswi[] = {
1203
    &gen_op_lswi_user,
1204
    &gen_op_lswi_kernel,
1205
};
1206
static GenOpFunc3 *gen_op_lswx[] = {
1207
    &gen_op_lswx_user,
1208
    &gen_op_lswx_kernel,
1209
};
1210
static GenOpFunc1 *gen_op_stsw[] = {
1211
    &gen_op_stsw_user,
1212
    &gen_op_stsw_kernel,
1213
};
1214
#endif
1215

  
1123 1216
/* lswi */
1217
/* PPC32 specification says we must generate an exception if
1218
 * rA is in the range of registers to be loaded.
1219
 * In an other hand, IBM says this is valid, but rA won't be loaded.
1220
 * For now, I'll follow the spec...
1221
 */
1124 1222
GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_INTEGER)
1125 1223
{
1126 1224
    int nb = NB(ctx->opcode);
1127 1225
    int start = rD(ctx->opcode);
1226
    int ra = rA(ctx->opcode);
1128 1227
    int nr;
1129 1228

  
1130 1229
    if (nb == 0)
1131 1230
        nb = 32;
1132 1231
    nr = nb / 4;
1133
    if ((start + nr) > 32) {
1134
        /* handle wrap around r0 */
1135
        if (rA(ctx->opcode) == 0) {
1136
            gen_op_set_T0(0);
1137
        } else {
1138
            gen_op_load_gpr_T0(rA(ctx->opcode));
1232
    if (((start + nr) > 32  && start <= ra && (start + nr - 32) >= ra) ||
1233
        ((start + nr) <= 32 && start <= ra && (start + nr) >= ra)) {
1234
        RET_EXCP(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_LSWX);
1139 1235
        }
1140
        gen_op_lswi(start, 4 * (32 - start));
1141
        nb -= 4 * (32 - start);
1142
        start = 0;
1143
    }
1144
    if (rA(ctx->opcode) == 0) {
1236
    if (ra == 0) {
1145 1237
        gen_op_set_T0(0);
1146 1238
    } else {
1147
        gen_op_load_gpr_T0(rA(ctx->opcode));
1239
        gen_op_load_gpr_T0(ra);
1148 1240
    }
1149
    gen_op_lswi(start, nb);
1150
    SET_RETVAL(0);
1241
    gen_op_set_T1(nb);
1242
    op_ldsts(lswi, start);
1151 1243
}
1152 1244

  
1153 1245
/* lswx */
1154 1246
GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_INTEGER)
1155 1247
{
1156
    gen_op_load_xer_bc();
1157
    gen_op_load_gpr_T1(rB(ctx->opcode));
1158
    if (rA(ctx->opcode) == 0) {
1159
        gen_op_set_T2(0);
1248
    int ra = rA(ctx->opcode);
1249
    int rb = rB(ctx->opcode);
1250

  
1251
    if (ra == 0) {
1252
        gen_op_load_gpr_T0(rb);
1253
        ra = rb;
1160 1254
    } else {
1161
        gen_op_load_gpr_T2(rA(ctx->opcode));
1255
        gen_op_load_gpr_T0(ra);
1256
        gen_op_load_gpr_T1(rb);
1257
        gen_op_add();
1162 1258
    }
1163
    gen_op_lswx(rD(ctx->opcode));
1164
    SET_RETVAL(0);
1259
    gen_op_load_xer_bc();
1260
    op_ldstsx(lswx, rD(ctx->opcode), ra, rb);
1165 1261
}
1166 1262

  
1167 1263
/* stswi */
1168 1264
GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_INTEGER)
1169 1265
{
1170
    int nb = NB(ctx->opcode);
1171
    int start = rS(ctx->opcode);
1172
    int nr;
1173

  
1174
    if (nb == 0)
1175
        nb = 32;
1176
    nr = nb / 4;
1177
    if ((start + nr) > 32) {
1178
        /* handle wrap around r0 */
1179
        if (rA(ctx->opcode) == 0) {
1180
            gen_op_set_T0(0);
1181
        } else {
1182
            gen_op_load_gpr_T0(rA(ctx->opcode));
1183
        }
1184
        gen_op_stswi(start, 4 * (32 - start));
1185
        nb -= 4 * (32 - start);
1186
        start = 0;
1187
    }
1188 1266
    if (rA(ctx->opcode) == 0) {
1189 1267
        gen_op_set_T0(0);
1190 1268
    } else {
1191 1269
        gen_op_load_gpr_T0(rA(ctx->opcode));
1192 1270
    }
1193
    gen_op_stswi(start, nb);
1194
    SET_RETVAL(0);
1271
    gen_op_set_T1(NB(ctx->opcode));
1272
    op_ldsts(stsw, rS(ctx->opcode));
1195 1273
}
1196 1274

  
1197 1275
/* stswx */
1198 1276
GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_INTEGER)
1199 1277
{
1200
    gen_op_load_xer_bc();
1201
    gen_op_load_gpr_T1(rB(ctx->opcode));
1202
    if (rA(ctx->opcode) == 0) {
1203
        gen_op_set_T2(0);
1278
    int ra = rA(ctx->opcode);
1279

  
1280
    if (ra == 0) {
1281
        gen_op_load_gpr_T0(rB(ctx->opcode));
1282
        ra = rB(ctx->opcode);
1204 1283
    } else {
1205
        gen_op_load_gpr_T2(rA(ctx->opcode));
1284
        gen_op_load_gpr_T0(ra);
1285
        gen_op_load_gpr_T1(rB(ctx->opcode));
1286
        gen_op_add();
1206 1287
    }
1207
    gen_op_stswx(rS(ctx->opcode));
1208
    SET_RETVAL(0);
1288
    gen_op_load_xer_bc();
1289
    op_ldsts(stsw, rS(ctx->opcode));
1209 1290
}
1210 1291

  
1211 1292
/***                        Memory synchronisation                         ***/
1212 1293
/* eieio */
1213 1294
GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FF0801, PPC_MEM)
1214 1295
{
1215
    /* Do a branch to next instruction */
1216
    gen_op_b((uint32_t)ctx->nip);
1217
    SET_RETVAL(EXCP_BRANCH);
1218 1296
}
1219 1297

  
1220 1298
/* isync */
1221 1299
GEN_HANDLER(isync, 0x13, 0x16, 0xFF, 0x03FF0801, PPC_MEM)
1222 1300
{
1223
    /* Do a branch to next instruction */
1224
    gen_op_b((uint32_t)ctx->nip);
1225
    SET_RETVAL(EXCP_BRANCH);
1226 1301
}
1227 1302

  
1228 1303
/* lwarx */
1229
GEN_HANDLER(lwarx, 0x1F, 0x14, 0xFF, 0x00000001, PPC_MEM)
1304
#if defined(CONFIG_USER_ONLY)
1305
#define op_stwcx() gen_op_stwcx_raw()
1306
#else
1307
#define op_stwcx() (*gen_op_stwcx[ctx->mem_idx])()
1308
static GenOpFunc *gen_op_stwcx[] = {
1309
    &gen_op_stwcx_user,
1310
    &gen_op_stwcx_kernel,
1311
};
1312
#endif
1313

  
1314
GEN_HANDLER(lwarx, 0x1F, 0x14, 0xFF, 0x00000001, PPC_RES)
1230 1315
{
1231
    reserve = 1;
1232 1316
    if (rA(ctx->opcode) == 0) {
1233 1317
        gen_op_load_gpr_T0(rB(ctx->opcode));
1234
        gen_op_lwarx_z();
1235 1318
    } else {
1236 1319
        gen_op_load_gpr_T0(rA(ctx->opcode));
1237 1320
        gen_op_load_gpr_T1(rB(ctx->opcode));
1238
        gen_op_lwarx();
1321
        gen_op_add();
1239 1322
    }
1323
    op_ldst(lwz);
1240 1324
    gen_op_store_T1_gpr(rD(ctx->opcode));
1241
    SET_RETVAL(0);
1325
    gen_op_set_reservation();
1242 1326
}
1243 1327

  
1244 1328
/* stwcx. */
1245
GEN_HANDLER(stwcx_, 0x1F, 0x16, 0x04, 0x00000000, PPC_MEM)
1329
GEN_HANDLER(stwcx_, 0x1F, 0x16, 0x04, 0x00000000, PPC_RES)
1246 1330
{
1247
    if (reserve == 0) {
1248
        gen_op_reset_Rc0();
1249
    } else {
1250 1331
        if (rA(ctx->opcode) == 0) {
1251 1332
            gen_op_load_gpr_T0(rB(ctx->opcode));
1252
            gen_op_load_gpr_T1(rS(ctx->opcode));
1253
            gen_op_stwx_z();
1254 1333
        } else {
1255 1334
            gen_op_load_gpr_T0(rA(ctx->opcode));
1256 1335
            gen_op_load_gpr_T1(rB(ctx->opcode));
1257
            gen_op_load_gpr_T2(rS(ctx->opcode));
1258
            gen_op_stwx();
1336
        gen_op_add();
1259 1337
        }
1260
    }
1261
    SET_RETVAL(0);
1338
    gen_op_load_gpr_T1(rS(ctx->opcode));
1339
    op_stwcx();
1262 1340
}
1263 1341

  
1264 1342
/* sync */
1265 1343
GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x03FF0801, PPC_MEM)
1266 1344
{
1267
    /* Do a branch to next instruction */
1268
    gen_op_b((uint32_t)ctx->nip);
1269
    SET_RETVAL(EXCP_BRANCH);
1270 1345
}
1271 1346

  
1272 1347
/***                         Floating-point load                           ***/
1273
#define GEN_LF(width, opc)                                                    \
1274
GEN_HANDLER(lf##width, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT)                \
1348
#define GEN_LDF(width, opc)                                                   \
1349
GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)               \
1275 1350
{                                                                             \
1276 1351
    uint32_t simm = SIMM(ctx->opcode);                                        \
1277 1352
    if (rA(ctx->opcode) == 0) {                                               \
1278
        gen_op_lf##width##_z_FT0(simm);                          \
1353
        gen_op_set_T0(simm);                                                  \
1279 1354
    } else {                                                                  \
1280 1355
        gen_op_load_gpr_T0(rA(ctx->opcode));                                  \
1281
        gen_op_lf##width##_FT0(simm);                              \
1356
        if (simm != 0)                                                        \
1357
            gen_op_addi(simm);                                                \
1282 1358
    }                                                                         \
1283
    gen_op_store_FT0_fpr(rD(ctx->opcode));\
1284
    SET_RETVAL(0);                                                            \
1359
    op_ldst(l##width);                                                        \
1360
    gen_op_store_FT1_fpr(rD(ctx->opcode));                                    \
1285 1361
}
1286 1362

  
1287
#define GEN_LFU(width, opc)                                                   \
1288
GEN_HANDLER(lf##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT)             \
1363
#define GEN_LDUF(width, opc)                                                  \
1364
GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)            \
1289 1365
{                                                                             \
1366
    uint32_t simm = SIMM(ctx->opcode);                                        \
1290 1367
    if (rA(ctx->opcode) == 0 ||                                               \
1291
        rA(ctx->opcode) == rD(ctx->opcode))                                   \
1292
        SET_RETVAL(EXCP_INVAL);                                               \
1368
        rA(ctx->opcode) == rD(ctx->opcode)) {                                 \
1369
        RET_INVAL();                                                          \
1370
    }                                                                         \
1293 1371
    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
1294
    gen_op_lf##width##_FT0(SIMM(ctx->opcode));                     \
1295
    gen_op_store_FT0_fpr(rD(ctx->opcode));\
1372
    if (simm != 0)                                                            \
1373
        gen_op_addi(simm);                                                    \
1374
    op_ldst(l##width);                                                        \
1375
    gen_op_store_FT1_fpr(rD(ctx->opcode));                                    \
1296 1376
    gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
1297
    SET_RETVAL(0);                                                            \
1298 1377
}
1299 1378

  
1300
#define GEN_LFUX(width, opc)                                                  \
1301
GEN_HANDLER(lf##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT)            \
1379
#define GEN_LDUXF(width, opc)                                                 \
1380
GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER)           \
1302 1381
{                                                                             \
1303 1382
    if (rA(ctx->opcode) == 0 ||                                               \
1304
        rA(ctx->opcode) == rD(ctx->opcode))                                   \
1305
        SET_RETVAL(EXCP_INVAL);                                               \
1383
        rA(ctx->opcode) == rD(ctx->opcode)) {                                 \
1384
        RET_INVAL();                                                          \
1385
    }                                                                         \
1306 1386
    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
1307 1387
    gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
1308
    gen_op_lf##width##x_FT0();                                     \
1309
    gen_op_store_FT0_fpr(rD(ctx->opcode));\
1388
    gen_op_add();                                                             \
1389
    op_ldst(l##width);                                                        \
1390
    gen_op_store_FT1_fpr(rD(ctx->opcode));                                    \
1310 1391
    gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
1311
    SET_RETVAL(0);                                                            \
1312 1392
}
1313 1393

  
1314
#define GEN_LFX(width, opc)                                                   \
1315
GEN_HANDLER(lf##width##x, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT)             \
1394
#define GEN_LDXF(width, opc2, opc3)                                           \
1395
GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER)           \
1316 1396
{                                                                             \
1317 1397
    if (rA(ctx->opcode) == 0) {                                               \
1318 1398
        gen_op_load_gpr_T0(rB(ctx->opcode));                                  \
1319
        gen_op_lf##width##x_z_FT0();                               \
1320 1399
    } else {                                                                  \
1321 1400
        gen_op_load_gpr_T0(rA(ctx->opcode));                                  \
1322 1401
        gen_op_load_gpr_T1(rB(ctx->opcode));                                  \
1323
        gen_op_lf##width##x_FT0();                                 \
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff