Statistics
| Branch: | Revision:

root / target-ppc / op.c @ 004bc62c

History | View | Annotate | Download (25.6 kB)

1
/*
2
 *  PPC emulation micro-operations for qemu.
3
 * 
4
 *  Copyright (c) 2003 Jocelyn Mayer
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 */
20

    
21
#include "config.h"
22
#include "exec.h"
23

    
24
//#define DEBUG_OP
25

    
26
#define regs (env)
27
#define Ts0 (int32_t)T0
28
#define Ts1 (int32_t)T1
29
#define Ts2 (int32_t)T2
30

    
31
#define FT0 (env->ft0)
32
#define FT1 (env->ft1)
33
#define FT2 (env->ft2)
34

    
35
#define FTS0 ((float)env->ft0)
36
#define FTS1 ((float)env->ft1)
37
#define FTS2 ((float)env->ft2)
38

    
39
#define PPC_OP(name) void glue(op_, name)(void)
40

    
41
#define REG 0
42
#include "op_template.h"
43

    
44
#define REG 1
45
#include "op_template.h"
46

    
47
#define REG 2
48
#include "op_template.h"
49

    
50
#define REG 3
51
#include "op_template.h"
52

    
53
#define REG 4
54
#include "op_template.h"
55

    
56
#define REG 5
57
#include "op_template.h"
58

    
59
#define REG 6
60
#include "op_template.h"
61

    
62
#define REG 7
63
#include "op_template.h"
64

    
65
#define REG 8
66
#include "op_template.h"
67

    
68
#define REG 9
69
#include "op_template.h"
70

    
71
#define REG 10
72
#include "op_template.h"
73

    
74
#define REG 11
75
#include "op_template.h"
76

    
77
#define REG 12
78
#include "op_template.h"
79

    
80
#define REG 13
81
#include "op_template.h"
82

    
83
#define REG 14
84
#include "op_template.h"
85

    
86
#define REG 15
87
#include "op_template.h"
88

    
89
#define REG 16
90
#include "op_template.h"
91

    
92
#define REG 17
93
#include "op_template.h"
94

    
95
#define REG 18
96
#include "op_template.h"
97

    
98
#define REG 19
99
#include "op_template.h"
100

    
101
#define REG 20
102
#include "op_template.h"
103

    
104
#define REG 21
105
#include "op_template.h"
106

    
107
#define REG 22
108
#include "op_template.h"
109

    
110
#define REG 23
111
#include "op_template.h"
112

    
113
#define REG 24
114
#include "op_template.h"
115

    
116
#define REG 25
117
#include "op_template.h"
118

    
119
#define REG 26
120
#include "op_template.h"
121

    
122
#define REG 27
123
#include "op_template.h"
124

    
125
#define REG 28
126
#include "op_template.h"
127

    
128
#define REG 29
129
#include "op_template.h"
130

    
131
#define REG 30
132
#include "op_template.h"
133

    
134
#define REG 31
135
#include "op_template.h"
136

    
137
/* PPC state maintenance operations */
138
/* set_Rc0 */
139
PPC_OP(set_Rc0)
140
{
141
    uint32_t tmp;
142

    
143
    if (Ts0 < 0) {
144
        tmp = 0x08;
145
    } else if (Ts0 > 0) {
146
        tmp = 0x04;
147
    } else {
148
        tmp = 0x02;
149
    }
150
    env->crf[0] = tmp;
151
    RETURN();
152
}
153

    
154
PPC_OP(set_Rc0_ov)
155
{
156
    uint32_t tmp;
157

    
158
    if (Ts0 < 0) {
159
        tmp = 0x08;
160
    } else if (Ts0 > 0) {
161
        tmp = 0x04;
162
    } else {
163
        tmp = 0x02;
164
    }
165
    tmp |= xer_ov;
166
    env->crf[0] = tmp;
167
    RETURN();
168
}
169

    
170
/* reset_Rc0 */
171
PPC_OP(reset_Rc0)
172
{
173
    env->crf[0] = 0x02 | xer_ov;
174
    RETURN();
175
}
176

    
177
/* set_Rc0_1 */
178
PPC_OP(set_Rc0_1)
179
{
180
    env->crf[0] = 0x04 | xer_ov;
181
    RETURN();
182
}
183

    
184
/* Set Rc1 (for floating point arithmetic) */
185
PPC_OP(set_Rc1)
186
{
187
    env->crf[1] = regs->fpscr[7];
188
    RETURN();
189
}
190

    
191
/* Constants load */
192
PPC_OP(set_T0)
193
{
194
    T0 = PARAM(1);
195
    RETURN();
196
}
197

    
198
PPC_OP(set_T1)
199
{
200
    T1 = PARAM(1);
201
    RETURN();
202
}
203

    
204
PPC_OP(set_T2)
205
{
206
    T2 = PARAM(1);
207
    RETURN();
208
}
209

    
210
/* Generate exceptions */
211
PPC_OP(queue_exception_err)
212
{
213
    do_queue_exception_err(PARAM(1), PARAM(2));
214
}
215

    
216
PPC_OP(queue_exception)
217
{
218
    do_queue_exception(PARAM(1));
219
}
220

    
221
PPC_OP(process_exceptions)
222
{
223
    env->nip = PARAM(1);
224
    if (env->exceptions != 0) {
225
        do_check_exception_state();
226
    }
227
}
228

    
229
/* Segment registers load and store with immediate index */
230
PPC_OP(load_srin)
231
{
232
    T0 = regs->sr[T1 >> 28];
233
    RETURN();
234
}
235

    
236
PPC_OP(store_srin)
237
{
238
#if defined (DEBUG_OP)
239
    dump_store_sr(T1 >> 28);
240
#endif
241
    regs->sr[T1 >> 28] = T0;
242
    RETURN();
243
}
244

    
245
PPC_OP(load_sdr1)
246
{
247
    T0 = regs->sdr1;
248
    RETURN();
249
}
250

    
251
PPC_OP(store_sdr1)
252
{
253
    regs->sdr1 = T0;
254
    RETURN();
255
}
256

    
257
PPC_OP(exit_tb)
258
{
259
    EXIT_TB();
260
}
261

    
262
/* Load/store special registers */
263
PPC_OP(load_cr)
264
{
265
    do_load_cr();
266
    RETURN();
267
}
268

    
269
PPC_OP(store_cr)
270
{
271
    do_store_cr(PARAM(1));
272
    RETURN();
273
}
274

    
275
PPC_OP(load_xer_cr)
276
{
277
    T0 = (xer_so << 3) | (xer_ov << 2) | (xer_ca << 1);
278
    RETURN();
279
}
280

    
281
PPC_OP(clear_xer_cr)
282
{
283
    xer_so = 0;
284
    xer_ov = 0;
285
    xer_ca = 0;
286
    RETURN();
287
}
288

    
289
PPC_OP(load_xer_bc)
290
{
291
    T1 = xer_bc;
292
    RETURN();
293
}
294

    
295
PPC_OP(load_xer)
296
{
297
    do_load_xer();
298
    RETURN();
299
}
300

    
301
PPC_OP(store_xer)
302
{
303
    do_store_xer();
304
    RETURN();
305
}
306

    
307
PPC_OP(load_msr)
308
{
309
    do_load_msr();
310
    RETURN();
311
}
312

    
313
PPC_OP(store_msr)
314
{
315
    do_store_msr();
316
    RETURN();
317
}
318

    
319
/* SPR */
320
PPC_OP(load_spr)
321
{
322
    T0 = regs->spr[PARAM(1)];
323
    RETURN();
324
}
325

    
326
PPC_OP(store_spr)
327
{
328
    regs->spr[PARAM(1)] = T0;
329
    RETURN();
330
}
331

    
332
PPC_OP(load_lr)
333
{
334
    T0 = regs->lr;
335
    RETURN();
336
}
337

    
338
PPC_OP(store_lr)
339
{
340
    regs->lr = T0;
341
    RETURN();
342
}
343

    
344
PPC_OP(load_ctr)
345
{
346
    T0 = regs->ctr;
347
    RETURN();
348
}
349

    
350
PPC_OP(store_ctr)
351
{
352
    regs->ctr = T0;
353
    RETURN();
354
}
355

    
356
/* Update time base */
357
PPC_OP(update_tb)
358
{
359
    T0 = regs->tb[0];
360
    T1 = T0;
361
    T0 += PARAM(1);
362
#if defined (DEBUG_OP)
363
    dump_update_tb(PARAM(1));
364
#endif
365
    if (T0 < T1) {
366
        T1 = regs->tb[1] + 1;
367
        regs->tb[1] = T1;
368
    }
369
    regs->tb[0] = T0;
370
    RETURN();
371
}
372

    
373
PPC_OP(load_tb)
374
{
375
    T0 = regs->tb[PARAM(1)];
376
    RETURN();
377
}
378

    
379
PPC_OP(store_tb)
380
{
381
    regs->tb[PARAM(1)] = T0;
382
#if defined (DEBUG_OP)
383
    dump_store_tb(PARAM(1));
384
#endif
385
    RETURN();
386
}
387

    
388
/* Update decrementer */
389
PPC_OP(update_decr)
390
{
391
    T0 = regs->decr;
392
    T1 = T0;
393
    T0 -= PARAM(1);
394
    regs->decr = T0;
395
    if (PARAM(1) > T1) {
396
        do_queue_exception(EXCP_DECR);
397
    }
398
    RETURN();
399
}
400

    
401
PPC_OP(store_decr)
402
{
403
    T1 = regs->decr;
404
    regs->decr = T0;
405
    if (Ts0 < 0 && Ts1 > 0) {
406
        do_queue_exception(EXCP_DECR);
407
    }
408
    RETURN();
409
}
410

    
411
PPC_OP(load_ibat)
412
{
413
    T0 = regs->IBAT[PARAM(1)][PARAM(2)];
414
}
415

    
416
PPC_OP(store_ibat)
417
{
418
#if defined (DEBUG_OP)
419
    dump_store_ibat(PARAM(1), PARAM(2));
420
#endif
421
    regs->IBAT[PARAM(1)][PARAM(2)] = T0;
422
}
423

    
424
PPC_OP(load_dbat)
425
{
426
    T0 = regs->DBAT[PARAM(1)][PARAM(2)];
427
}
428

    
429
PPC_OP(store_dbat)
430
{
431
#if defined (DEBUG_OP)
432
    dump_store_dbat(PARAM(1), PARAM(2));
433
#endif
434
    regs->DBAT[PARAM(1)][PARAM(2)] = T0;
435
}
436

    
437
/* FPSCR */
438
PPC_OP(load_fpscr)
439
{
440
    do_load_fpscr();
441
    RETURN();
442
}
443

    
444
PPC_OP(store_fpscr)
445
{
446
    do_store_fpscr(PARAM(1));
447
    RETURN();
448
}
449

    
450
PPC_OP(reset_scrfx)
451
{
452
    regs->fpscr[7] &= ~0x8;
453
    RETURN();
454
}
455

    
456
/* crf operations */
457
PPC_OP(getbit_T0)
458
{
459
    T0 = (T0 >> PARAM(1)) & 1;
460
    RETURN();
461
}
462

    
463
PPC_OP(getbit_T1)
464
{
465
    T1 = (T1 >> PARAM(1)) & 1;
466
    RETURN();
467
}
468

    
469
PPC_OP(setcrfbit)
470
{
471
    T1 = (T1 & PARAM(1)) | (T0 << PARAM(2)); 
472
    RETURN();
473
}
474

    
475
/* Branch */
476
#if 0
477
#define EIP regs->nip
478
#define TB_DO_JUMP(name, tb, n, target) JUMP_TB(name, tb, n, target)
479
#else
480
#define TB_DO_JUMP(name, tb, n, target) regs->nip = target;
481
#endif
482

    
483
#define __PPC_OP_B(name, target)                                              \
484
PPC_OP(name)                                                                  \
485
{                                                                             \
486
    TB_DO_JUMP(glue(op_, name), T1, 0, (target));                             \
487
    RETURN();                                                                 \
488
}
489

    
490
#define __PPC_OP_BL(name, target, link)                                       \
491
PPC_OP(name)                                                                  \
492
{                                                                             \
493
    regs->lr = (link);                                                        \
494
    TB_DO_JUMP(glue(op_, name), T1, 0, (target));                             \
495
    RETURN();                                                                 \
496
}
497

    
498
#define PPC_OP_B(name, target, link)                                          \
499
__PPC_OP_B(name, target);                                                     \
500
__PPC_OP_BL(glue(name, l), target, link)
501

    
502
#define __PPC_OP_BC(name, cond, target)                                       \
503
PPC_OP(name)                                                                  \
504
{                                                                             \
505
    if (cond) {                                                               \
506
        TB_DO_JUMP(glue(op_, name), T1, 1, (target));                         \
507
    } else {                                                                  \
508
        TB_DO_JUMP(glue(op_, name), T1, 0, PARAM(1));                         \
509
    }                                                                         \
510
    RETURN();                                                                 \
511
}
512

    
513
#define __PPC_OP_BCL(name, cond, target)                                      \
514
PPC_OP(name)                                                                  \
515
{                                                                             \
516
    regs->lr = PARAM(1);                                                      \
517
    if (cond) {                                                               \
518
        TB_DO_JUMP(glue(op_, name), T1, 1, (target));                         \
519
    } else {                                                                  \
520
        TB_DO_JUMP(glue(op_, name), T1, 0, PARAM(1));                         \
521
    }                                                                         \
522
    RETURN();                                                                 \
523
}
524

    
525
#define __PPC_OP_BCLRL(name, cond, target)                                    \
526
PPC_OP(name)                                                                  \
527
{                                                                             \
528
    T2 = (target);                                                            \
529
    regs->lr = PARAM(1);                                                      \
530
    if (cond) {                                                               \
531
        TB_DO_JUMP(glue(op_, name), T1, 1, T2);                               \
532
    } else {                                                                  \
533
        TB_DO_JUMP(glue(op_, name), T1, 0, PARAM(1));                         \
534
    }                                                                         \
535
    RETURN();                                                                 \
536
}
537

    
538
#define _PPC_OP_BC(name, namel, cond, target)                                 \
539
__PPC_OP_BC(name, cond, target);                                              \
540
__PPC_OP_BCL(namel, cond, target)
541

    
542
/* Branch to target */
543
#define PPC_OP_BC(name, cond)                                                 \
544
_PPC_OP_BC(b_##name, bl_##name, cond, PARAM(2))
545

    
546
PPC_OP_B(b, PARAM(1), PARAM(2));
547
PPC_OP_BC(ctr,        (regs->ctr != 0));
548
PPC_OP_BC(ctr_true,   (regs->ctr != 0 && (T0 & PARAM(3)) != 0));
549
PPC_OP_BC(ctr_false,  (regs->ctr != 0 && (T0 & PARAM(3)) == 0));
550
PPC_OP_BC(ctrz,       (regs->ctr == 0));
551
PPC_OP_BC(ctrz_true,  (regs->ctr == 0 && (T0 & PARAM(3)) != 0));
552
PPC_OP_BC(ctrz_false, (regs->ctr == 0 && (T0 & PARAM(3)) == 0));
553
PPC_OP_BC(true,       ((T0 & PARAM(3)) != 0));
554
PPC_OP_BC(false,      ((T0 & PARAM(3)) == 0));
555

    
556
/* Branch to CTR */
557
#define PPC_OP_BCCTR(name, cond)                                              \
558
_PPC_OP_BC(bctr_##name, bctrl_##name, cond, regs->ctr & ~0x03)
559

    
560
PPC_OP_B(bctr, regs->ctr & ~0x03, PARAM(1));
561
PPC_OP_BCCTR(ctr,        (regs->ctr != 0));
562
PPC_OP_BCCTR(ctr_true,   (regs->ctr != 0 && (T0 & PARAM(2)) != 0));
563
PPC_OP_BCCTR(ctr_false,  (regs->ctr != 0 && (T0 & PARAM(2)) == 0));
564
PPC_OP_BCCTR(ctrz,       (regs->ctr == 0));
565
PPC_OP_BCCTR(ctrz_true,  (regs->ctr == 0 && (T0 & PARAM(2)) != 0));
566
PPC_OP_BCCTR(ctrz_false, (regs->ctr == 0 && (T0 & PARAM(2)) == 0));
567
PPC_OP_BCCTR(true,       ((T0 & PARAM(2)) != 0));
568
PPC_OP_BCCTR(false,      ((T0 & PARAM(2)) == 0));
569

    
570
/* Branch to LR */
571
#define PPC_OP_BCLR(name, cond)                                               \
572
__PPC_OP_BC(blr_##name, cond, regs->lr & ~0x03);                              \
573
__PPC_OP_BCLRL(blrl_##name, cond, regs->lr & ~0x03)
574

    
575
__PPC_OP_B(blr, regs->lr & ~0x03);
576
PPC_OP(blrl)
577
{
578
    T0 = regs->lr & ~0x03;
579
    regs->lr = PARAM(1);
580
    TB_DO_JUMP(op_blrl, T1, 0, T0);
581
    RETURN();
582
}
583
PPC_OP_BCLR(ctr,        (regs->ctr != 0));
584
PPC_OP_BCLR(ctr_true,   (regs->ctr != 0 && (T0 & PARAM(2)) != 0));
585
PPC_OP_BCLR(ctr_false,  (regs->ctr != 0 && (T0 & PARAM(2)) == 0));
586
PPC_OP_BCLR(ctrz,       (regs->ctr == 0));
587
PPC_OP_BCLR(ctrz_true,  (regs->ctr == 0 && (T0 & PARAM(2)) != 0));
588
PPC_OP_BCLR(ctrz_false, (regs->ctr == 0 && (T0 & PARAM(2)) == 0));
589
PPC_OP_BCLR(true,       ((T0 & PARAM(2)) != 0));
590
PPC_OP_BCLR(false,      ((T0 & PARAM(2)) == 0));
591

    
592
/* CTR maintenance */
593
PPC_OP(dec_ctr)
594
{
595
    regs->ctr--;
596
    RETURN();
597
}
598

    
599
/***                           Integer arithmetic                          ***/
600
/* add */
601
PPC_OP(add)
602
{
603
    T0 += T1;
604
    RETURN();
605
}
606

    
607
PPC_OP(addo)
608
{
609
    T2 = T0;
610
    T0 += T1;
611
    if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
612
        xer_so = 1;
613
        xer_ov = 1;
614
    } else {
615
        xer_ov = 0;
616
    }
617
    RETURN();
618
}
619

    
620
/* add carrying */
621
PPC_OP(addc)
622
{
623
    T2 = T0;
624
    T0 += T1;
625
    if (T0 < T2) {
626
        xer_ca = 1;
627
    } else {
628
        xer_ca = 0;
629
    }
630
    RETURN();
631
}
632

    
633
PPC_OP(addco)
634
{
635
    T2 = T0;
636
    T0 += T1;
637
    if (T0 < T2) {
638
        xer_ca = 1;
639
    } else {
640
        xer_ca = 0;
641
    }
642
    if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
643
        xer_so = 1;
644
        xer_ov = 1;
645
    } else {
646
        xer_ov = 0;
647
    }
648
    RETURN();
649
}
650

    
651
/* add extended */
652
/* candidate for helper (too long) */
653
PPC_OP(adde)
654
{
655
    T2 = T0;
656
    T0 += T1 + xer_ca;
657
    if (T0 < T2 || (xer_ca == 1 && T0 == T2)) {
658
        xer_ca = 1;
659
    } else {
660
        xer_ca = 0;
661
    }
662
    RETURN();
663
}
664

    
665
PPC_OP(addeo)
666
{
667
    T2 = T0;
668
    T0 += T1 + xer_ca;
669
    if (T0 < T2 || (xer_ca == 1 && T0 == T2)) {
670
        xer_ca = 1;
671
    } else {
672
        xer_ca = 0;
673
    }
674
    if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
675
        xer_so = 1;
676
        xer_ov = 1;
677
    } else {
678
        xer_ov = 0;
679
    }
680
    RETURN();
681
}
682

    
683
/* add immediate */
684
PPC_OP(addi)
685
{
686
    T0 += PARAM(1);
687
    RETURN();
688
}
689

    
690
/* add immediate carrying */
691
PPC_OP(addic)
692
{
693
    T1 = T0;
694
    T0 += PARAM(1);
695
    if (T0 < T1) {
696
        xer_ca = 1;
697
    } else {
698
        xer_ca = 0;
699
    }
700
    RETURN();
701
}
702

    
703
/* add to minus one extended */
704
PPC_OP(addme)
705
{
706
    T1 = T0;
707
    T0 += xer_ca + (-1);
708
    if (T1 != 0)
709
        xer_ca = 1;
710
    RETURN();
711
}
712

    
713
PPC_OP(addmeo)
714
{
715
    T1 = T0;
716
    T0 += xer_ca + (-1);
717
    if (T1 & (T1 ^ T0) & (1 << 31)) {
718
        xer_so = 1;
719
        xer_ov = 1;
720
    } else {
721
        xer_ov = 0;
722
    }
723
    if (T1 != 0)
724
        xer_ca = 1;
725
    RETURN();
726
}
727

    
728
/* add to zero extended */
729
PPC_OP(addze)
730
{
731
    T1 = T0;
732
    T0 += xer_ca;
733
    if (T0 < T1) {
734
        xer_ca = 1;
735
    } else {
736
        xer_ca = 0;
737
    }
738
    RETURN();
739
}
740

    
741
PPC_OP(addzeo)
742
{
743
    T1 = T0;
744
    T0 += xer_ca;
745
    if ((T1 ^ (-1)) & (T1 ^ T0) & (1 << 31)) {
746
        xer_so = 1;
747
        xer_ov = 1;
748
    } else {
749
        xer_ov = 0;
750
    }
751
    if (T0 < T1) {
752
        xer_ca = 1;
753
    } else {
754
        xer_ca = 0;
755
    }
756
    RETURN();
757
}
758

    
759
/* divide word */
760
/* candidate for helper (too long) */
761
PPC_OP(divw)
762
{
763
    if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
764
        Ts0 = (-1) * (T0 >> 31);
765
    } else {
766
        Ts0 /= Ts1;
767
    }
768
    RETURN();
769
}
770

    
771
PPC_OP(divwo)
772
{
773
    if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
774
        xer_so = 1;
775
        xer_ov = 1;
776
        T0 = (-1) * (T0 >> 31);
777
    } else {
778
        xer_ov = 0;
779
        Ts0 /= Ts1;
780
    }
781
    RETURN();
782
}
783

    
784
/* divide word unsigned */
785
PPC_OP(divwu)
786
{
787
    if (T1 == 0) {
788
        T0 = 0;
789
    } else {
790
        T0 /= T1;
791
    }
792
    RETURN();
793
}
794

    
795
PPC_OP(divwuo)
796
{
797
    if (T1 == 0) {
798
        xer_so = 1;
799
        xer_ov = 1;
800
        T0 = 0;
801
    } else {
802
        xer_ov = 0;
803
        T0 /= T1;
804
    }
805
    RETURN();
806
}
807

    
808
/* multiply high word */
809
PPC_OP(mulhw)
810
{
811
    Ts0 = ((int64_t)Ts0 * (int64_t)Ts1) >> 32;
812
    RETURN();
813
}
814

    
815
/* multiply high word unsigned */
816
PPC_OP(mulhwu)
817
{
818
    T0 = ((uint64_t)T0 * (uint64_t)T1) >> 32;
819
    RETURN();
820
}
821

    
822
/* multiply low immediate */
823
PPC_OP(mulli)
824
{
825
    Ts0 *= SPARAM(1);
826
    RETURN();
827
}
828

    
829
/* multiply low word */
830
PPC_OP(mullw)
831
{
832
    T0 *= T1;
833
    RETURN();
834
}
835

    
836
PPC_OP(mullwo)
837
{
838
    int64_t res = (int64_t)Ts0 * (int64_t)Ts1;
839

    
840
    if ((int32_t)res != res) {
841
        xer_ov = 1;
842
        xer_so = 1;
843
    } else {
844
        xer_ov = 0;
845
    }
846
    Ts0 = res;
847
    RETURN();
848
}
849

    
850
/* negate */
851
PPC_OP(neg)
852
{
853
    if (T0 != 0x80000000) {
854
        Ts0 = -Ts0;
855
    }
856
    RETURN();
857
}
858

    
859
PPC_OP(nego)
860
{
861
    if (T0 == 0x80000000) {
862
        xer_ov = 1;
863
        xer_so = 1;
864
    } else {
865
        xer_ov = 0;
866
        Ts0 = -Ts0;
867
    }
868
    RETURN();
869
}
870

    
871
/* substract from */
872
PPC_OP(subf)
873
{
874
    T0 = T1 - T0;
875
    RETURN();
876
}
877

    
878
PPC_OP(subfo)
879
{
880
    T2 = T0;
881
    T0 = T1 - T0;
882
    if (((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)) {
883
        xer_so = 1;
884
        xer_ov = 1;
885
    } else {
886
        xer_ov = 0;
887
    }
888
    RETURN();
889
}
890

    
891
/* substract from carrying */
892
PPC_OP(subfc)
893
{
894
    T0 = T1 - T0;
895
    if (T0 <= T1) {
896
        xer_ca = 1;
897
    } else {
898
        xer_ca = 0;
899
    }
900
    RETURN();
901
}
902

    
903
PPC_OP(subfco)
904
{
905
    T2 = T0;
906
    T0 = T1 - T0;
907
    if (T0 <= T1) {
908
        xer_ca = 1;
909
    } else {
910
        xer_ca = 0;
911
    }
912
    if (((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)) {
913
        xer_so = 1;
914
        xer_ov = 1;
915
    } else {
916
        xer_ov = 0;
917
    }
918
    RETURN();
919
}
920

    
921
/* substract from extended */
922
/* candidate for helper (too long) */
923
PPC_OP(subfe)
924
{
925
    T0 = T1 + ~T0 + xer_ca;
926
    if (T0 < T1 || (xer_ca == 1 && T0 == T1)) {
927
        xer_ca = 1;
928
    } else {
929
        xer_ca = 0;
930
    }
931
    RETURN();
932
}
933

    
934
PPC_OP(subfeo)
935
{
936
    T2 = T0;
937
    T0 = T1 + ~T0 + xer_ca;
938
    if ((~T2 ^ T1 ^ (-1)) & (~T2 ^ T0) & (1 << 31)) {
939
        xer_so = 1;
940
        xer_ov = 1;
941
    } else {
942
        xer_ov = 0;
943
    }
944
    if (T0 < T1 || (xer_ca == 1 && T0 == T1)) {
945
        xer_ca = 1;
946
    } else {
947
        xer_ca = 0;
948
    }
949
    RETURN();
950
}
951

    
952
/* substract from immediate carrying */
953
PPC_OP(subfic)
954
{
955
    T0 = PARAM(1) + ~T0 + 1;
956
    if (T0 <= PARAM(1)) {
957
        xer_ca = 1;
958
    } else {
959
        xer_ca = 0;
960
    }
961
    RETURN();
962
}
963

    
964
/* substract from minus one extended */
965
PPC_OP(subfme)
966
{
967
    T0 = ~T0 + xer_ca - 1;
968

    
969
    if (T0 != -1)
970
        xer_ca = 1;
971
    RETURN();
972
}
973

    
974
PPC_OP(subfmeo)
975
{
976
    T1 = T0;
977
    T0 = ~T0 + xer_ca - 1;
978
    if (~T1 & (~T1 ^ T0) & (1 << 31)) {
979
        xer_so = 1;
980
        xer_ov = 1;
981
    } else {
982
        xer_ov = 0;
983
    }
984
    if (T1 != -1)
985
        xer_ca = 1;
986
    RETURN();
987
}
988

    
989
/* substract from zero extended */
990
PPC_OP(subfze)
991
{
992
    T1 = ~T0;
993
    T0 = T1 + xer_ca;
994
    if (T0 < T1) {
995
        xer_ca = 1;
996
    } else {
997
        xer_ca = 0;
998
    }
999
    RETURN();
1000
}
1001

    
1002
PPC_OP(subfzeo)
1003
{
1004
    T1 = T0;
1005
    T0 = ~T0 + xer_ca;
1006
    if ((~T1 ^ (-1)) & ((~T1) ^ T0) & (1 << 31)) {
1007
        xer_ov = 1;
1008
        xer_so = 1;
1009
    } else {
1010
        xer_ov = 0;
1011
    }
1012
    if (T0 < ~T1) {
1013
        xer_ca = 1;
1014
    } else {
1015
        xer_ca = 0;
1016
    }
1017
    RETURN();
1018
}
1019

    
1020
/***                           Integer comparison                          ***/
1021
/* compare */
1022
PPC_OP(cmp)
1023
{
1024
    if (Ts0 < Ts1) {
1025
        T0 = 0x08;
1026
    } else if (Ts0 > Ts1) {
1027
        T0 = 0x04;
1028
    } else {
1029
        T0 = 0x02;
1030
    }
1031
    RETURN();
1032
}
1033

    
1034
/* compare immediate */
1035
PPC_OP(cmpi)
1036
{
1037
    if (Ts0 < SPARAM(1)) {
1038
        T0 = 0x08;
1039
    } else if (Ts0 > SPARAM(1)) {
1040
        T0 = 0x04;
1041
    } else {
1042
        T0 = 0x02;
1043
    }
1044
    RETURN();
1045
}
1046

    
1047
/* compare logical */
1048
PPC_OP(cmpl)
1049
{
1050
    if (T0 < T1) {
1051
        T0 = 0x08;
1052
    } else if (T0 > T1) {
1053
        T0 = 0x04;
1054
    } else {
1055
        T0 = 0x02;
1056
    }
1057
    RETURN();
1058
}
1059

    
1060
/* compare logical immediate */
1061
PPC_OP(cmpli)
1062
{
1063
    if (T0 < PARAM(1)) {
1064
        T0 = 0x08;
1065
    } else if (T0 > PARAM(1)) {
1066
        T0 = 0x04;
1067
    } else {
1068
        T0 = 0x02;
1069
    }
1070
    RETURN();
1071
}
1072

    
1073
/***                            Integer logical                            ***/
1074
/* and */
1075
PPC_OP(and)
1076
{
1077
    T0 &= T1;
1078
    RETURN();
1079
}
1080

    
1081
/* andc */
1082
PPC_OP(andc)
1083
{
1084
    T0 &= ~T1;
1085
    RETURN();
1086
}
1087

    
1088
/* andi. */
1089
PPC_OP(andi_)
1090
{
1091
    T0 &= PARAM(1);
1092
    RETURN();
1093
}
1094

    
1095
/* count leading zero */
1096
PPC_OP(cntlzw)
1097
{
1098
    T1 = T0;
1099
    for (T0 = 32; T1 > 0; T0--)
1100
        T1 = T1 >> 1;
1101
    RETURN();
1102
}
1103

    
1104
/* eqv */
1105
PPC_OP(eqv)
1106
{
1107
    T0 = ~(T0 ^ T1);
1108
    RETURN();
1109
}
1110

    
1111
/* extend sign byte */
1112
PPC_OP(extsb)
1113
{
1114
    Ts0 = s_ext8(Ts0);
1115
    RETURN();
1116
}
1117

    
1118
/* extend sign half word */
1119
PPC_OP(extsh)
1120
{
1121
    Ts0 = s_ext16(Ts0);
1122
    RETURN();
1123
}
1124

    
1125
/* nand */
1126
PPC_OP(nand)
1127
{
1128
    T0 = ~(T0 & T1);
1129
    RETURN();
1130
}
1131

    
1132
/* nor */
1133
PPC_OP(nor)
1134
{
1135
    T0 = ~(T0 | T1);
1136
    RETURN();
1137
}
1138

    
1139
/* or */
1140
PPC_OP(or)
1141
{
1142
    T0 |= T1;
1143
    RETURN();
1144
}
1145

    
1146
/* orc */
1147
PPC_OP(orc)
1148
{
1149
    T0 |= ~T1;
1150
    RETURN();
1151
}
1152

    
1153
/* ori */
1154
PPC_OP(ori)
1155
{
1156
    T0 |= PARAM(1);
1157
    RETURN();
1158
}
1159

    
1160
/* xor */
1161
PPC_OP(xor)
1162
{
1163
    T0 ^= T1;
1164
    RETURN();
1165
}
1166

    
1167
/* xori */
1168
PPC_OP(xori)
1169
{
1170
    T0 ^= PARAM(1);
1171
    RETURN();
1172
}
1173

    
1174
/***                             Integer rotate                            ***/
1175
/* rotate left word immediate then mask insert */
1176
PPC_OP(rlwimi)
1177
{
1178
    T0 = (rotl(T0, PARAM(1)) & PARAM(2)) | (T1 & PARAM(3));
1179
    RETURN();
1180
}
1181

    
1182
/* rotate left immediate then and with mask insert */
1183
PPC_OP(rotlwi)
1184
{
1185
    T0 = rotl(T0, PARAM(1));
1186
    RETURN();
1187
}
1188

    
1189
PPC_OP(slwi)
1190
{
1191
    T0 = T0 << PARAM(1);
1192
    RETURN();
1193
}
1194

    
1195
PPC_OP(srwi)
1196
{
1197
    T0 = T0 >> PARAM(1);
1198
    RETURN();
1199
}
1200

    
1201
/* rotate left word then and with mask insert */
1202
PPC_OP(rlwinm)
1203
{
1204
    T0 = rotl(T0, PARAM(1)) & PARAM(2);
1205
    RETURN();
1206
}
1207

    
1208
PPC_OP(rotl)
1209
{
1210
    T0 = rotl(T0, T1);
1211
    RETURN();
1212
}
1213

    
1214
PPC_OP(rlwnm)
1215
{
1216
    T0 = rotl(T0, T1) & PARAM(1);
1217
    RETURN();
1218
}
1219

    
1220
/***                             Integer shift                             ***/
1221
/* shift left word */
1222
PPC_OP(slw)
1223
{
1224
    if (T1 & 0x20) {
1225
        T0 = 0;
1226
    } else {
1227
        T0 = T0 << T1;
1228
    }
1229
    RETURN();
1230
}
1231

    
1232
/* shift right algebraic word */
1233
PPC_OP(sraw)
1234
{
1235
    do_sraw();
1236
    RETURN();
1237
}
1238

    
1239
/* shift right algebraic word immediate */
1240
PPC_OP(srawi)
1241
{
1242
    Ts1 = Ts0;
1243
    Ts0 = Ts0 >> PARAM(1);
1244
    if (Ts1 < 0 && (Ts1 & PARAM(2)) != 0) {
1245
        xer_ca = 1;
1246
    } else {
1247
        xer_ca = 0;
1248
    }
1249
    RETURN();
1250
}
1251

    
1252
/* shift right word */
1253
PPC_OP(srw)
1254
{
1255
    if (T1 & 0x20) {
1256
        T0 = 0;
1257
    } else {
1258
        T0 = T0 >> T1;
1259
    }
1260
    RETURN();
1261
}
1262

    
1263
/***                       Floating-Point arithmetic                       ***/
1264
/* fadd - fadd. */
1265
PPC_OP(fadd)
1266
{
1267
    FT0 += FT1;
1268
    RETURN();
1269
}
1270

    
1271
/* fadds - fadds. */
1272
PPC_OP(fadds)
1273
{
1274
    FTS0 += FTS1;
1275
    RETURN();
1276
}
1277

    
1278
/* fsub - fsub. */
1279
PPC_OP(fsub)
1280
{
1281
    FT0 -= FT1;
1282
    RETURN();
1283
}
1284

    
1285
/* fsubs - fsubs. */
1286
PPC_OP(fsubs)
1287
{
1288
    FTS0 -= FTS1;
1289
    RETURN();
1290
}
1291

    
1292
/* fmul - fmul. */
1293
PPC_OP(fmul)
1294
{
1295
    FT0 *= FT1;
1296
    RETURN();
1297
}
1298

    
1299
/* fmuls - fmuls. */
1300
PPC_OP(fmuls)
1301
{
1302
    FTS0 *= FTS1;
1303
    RETURN();
1304
}
1305

    
1306
/* fdiv - fdiv. */
1307
PPC_OP(fdiv)
1308
{
1309
    FT0 /= FT1;
1310
    RETURN();
1311
}
1312

    
1313
/* fdivs - fdivs. */
1314
PPC_OP(fdivs)
1315
{
1316
    FTS0 /= FTS1;
1317
    RETURN();
1318
}
1319

    
1320
/* fsqrt - fsqrt. */
1321
PPC_OP(fsqrt)
1322
{
1323
    do_fsqrt();
1324
    RETURN();
1325
}
1326

    
1327
/* fsqrts - fsqrts. */
1328
PPC_OP(fsqrts)
1329
{
1330
    do_fsqrts();
1331
    RETURN();
1332
}
1333

    
1334
/* fres - fres. */
1335
PPC_OP(fres)
1336
{
1337
    do_fres();
1338
    RETURN();
1339
}
1340

    
1341
/* frsqrte  - frsqrte. */
1342
PPC_OP(frsqrte)
1343
{
1344
    do_fsqrte();
1345
    RETURN();
1346
}
1347

    
1348
/* fsel - fsel. */
1349
PPC_OP(fsel)
1350
{
1351
    do_fsel();
1352
    RETURN();
1353
}
1354

    
1355
/***                     Floating-Point multiply-and-add                   ***/
1356
/* fmadd - fmadd. */
1357
PPC_OP(fmadd)
1358
{
1359
    FT0 = (FT0 * FT1) + FT2;
1360
    RETURN();
1361
}
1362

    
1363
/* fmadds - fmadds. */
1364
PPC_OP(fmadds)
1365
{
1366
    FTS0 = (FTS0 * FTS1) + FTS2;
1367
    RETURN();
1368
}
1369

    
1370
/* fmsub - fmsub. */
1371
PPC_OP(fmsub)
1372
{
1373
    FT0 = (FT0 * FT1) - FT2;
1374
    RETURN();
1375
}
1376

    
1377
/* fmsubs - fmsubs. */
1378
PPC_OP(fmsubs)
1379
{
1380
    FTS0 = (FTS0 * FTS1) - FTS2;
1381
    RETURN();
1382
}
1383

    
1384
/* fnmadd - fnmadd. - fnmadds - fnmadds. */
1385
PPC_OP(fnmadd)
1386
{
1387
    FT0 = -((FT0 * FT1) + FT2);
1388
    RETURN();
1389
}
1390

    
1391
/* fnmadds - fnmadds. */
1392
PPC_OP(fnmadds)
1393
{
1394
    FTS0 = -((FTS0 * FTS1) + FTS2);
1395
    RETURN();
1396
}
1397

    
1398
/* fnmsub - fnmsub. */
1399
PPC_OP(fnmsub)
1400
{
1401
    FT0 = -((FT0 * FT1) - FT2);
1402
    RETURN();
1403
}
1404

    
1405
/* fnmsubs - fnmsubs. */
1406
PPC_OP(fnmsubs)
1407
{
1408
    FTS0 = -((FTS0 * FTS1) - FTS2);
1409
    RETURN();
1410
}
1411

    
1412
/***                     Floating-Point round & convert                    ***/
1413
/* frsp - frsp. */
1414
PPC_OP(frsp)
1415
{
1416
    FT0 = FTS0;
1417
    RETURN();
1418
}
1419

    
1420
/* fctiw - fctiw. */
1421
PPC_OP(fctiw)
1422
{
1423
    do_fctiw();
1424
    RETURN();
1425
}
1426

    
1427
/* fctiwz - fctiwz. */
1428
PPC_OP(fctiwz)
1429
{
1430
    do_fctiwz();
1431
    RETURN();
1432
}
1433

    
1434

    
1435
/***                         Floating-Point compare                        ***/
1436
/* fcmpu */
1437
PPC_OP(fcmpu)
1438
{
1439
    do_fcmpu();
1440
    RETURN();
1441
}
1442

    
1443
/* fcmpo */
1444
PPC_OP(fcmpo)
1445
{
1446
    do_fcmpo();
1447
    RETURN();
1448
}
1449

    
1450
/***                         Floating-point move                           ***/
1451
/* fabs */
1452
PPC_OP(fabs)
1453
{
1454
    do_fabs();
1455
    RETURN();
1456
}
1457

    
1458
/* fnabs */
1459
PPC_OP(fnabs)
1460
{
1461
    do_fnabs();
1462
    RETURN();
1463
}
1464

    
1465
/* fneg */
1466
PPC_OP(fneg)
1467
{
1468
    FT0 = -FT0;
1469
    RETURN();
1470
}
1471

    
1472
/* Load and store */
1473
#if defined(CONFIG_USER_ONLY)
1474
#define MEMSUFFIX _raw
1475
#include "op_mem.h"
1476
#else
1477
#define MEMSUFFIX _user
1478
#include "op_mem.h"
1479

    
1480
#define MEMSUFFIX _kernel
1481
#include "op_mem.h"
1482
#endif
1483

    
1484
/* Return from interrupt */
1485
PPC_OP(rfi)
1486
{
1487
    T0 = regs->spr[SRR1] & ~0xFFFF0000;
1488
    do_store_msr();
1489
    do_tlbia();
1490
    dump_rfi();
1491
    regs->nip = regs->spr[SRR0] & ~0x00000003;
1492
    if (env->exceptions != 0) {
1493
        do_check_exception_state();
1494
    }
1495
    RETURN();
1496
}
1497

    
1498
/* Trap word */
1499
PPC_OP(tw)
1500
{
1501
    if ((Ts0 < Ts1 && (PARAM(1) & 0x10)) ||
1502
        (Ts0 > Ts1 && (PARAM(1) & 0x08)) ||
1503
        (Ts0 == Ts1 && (PARAM(1) & 0x04)) ||
1504
        (T0 < T1 && (PARAM(1) & 0x02)) ||
1505
        (T0 > T1 && (PARAM(1) & 0x01)))
1506
        do_queue_exception_err(EXCP_PROGRAM, EXCP_TRAP);
1507
    RETURN();
1508
}
1509

    
1510
PPC_OP(twi)
1511
{
1512
    if ((Ts0 < SPARAM(1) && (PARAM(2) & 0x10)) ||
1513
        (Ts0 > SPARAM(1) && (PARAM(2) & 0x08)) ||
1514
        (Ts0 == SPARAM(1) && (PARAM(2) & 0x04)) ||
1515
        (T0 < (uint32_t)SPARAM(1) && (PARAM(2) & 0x02)) ||
1516
        (T0 > (uint32_t)SPARAM(1) && (PARAM(2) & 0x01)))
1517
        do_queue_exception_err(EXCP_PROGRAM, EXCP_TRAP);
1518
    RETURN();
1519
}
1520

    
1521
/* Instruction cache block invalidate */
1522
PPC_OP(icbi)
1523
{
1524
    do_icbi();
1525
    RETURN();
1526
}
1527

    
1528
/* tlbia */
1529
PPC_OP(tlbia)
1530
{
1531
    do_tlbia();
1532
    RETURN();
1533
}
1534

    
1535
/* tlbie */
1536
PPC_OP(tlbie)
1537
{
1538
    do_tlbie();
1539
    RETURN();
1540
}