Statistics
| Branch: | Revision:

root / target-ppc / op.c @ 9fddaa0c

History | View | Annotate | Download (20.4 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
//#define DEBUG_OP
22

    
23
#include "config.h"
24
#include "exec.h"
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(raise_exception_err)
212
{
213
    do_raise_exception_err(PARAM(1), PARAM(2));
214
}
215

    
216
PPC_OP(raise_exception)
217
{
218
    do_raise_exception(PARAM(1));
219
}
220

    
221
PPC_OP(update_nip)
222
{
223
    env->nip = PARAM(1);
224
}
225

    
226
PPC_OP(debug)
227
{
228
    env->nip = PARAM(1);
229
#if defined (DEBUG_OP)
230
    dump_state();
231
#endif
232
    do_raise_exception(EXCP_DEBUG);
233
    RETURN();
234
}
235

    
236
/* Segment registers load and store with immediate index */
237
PPC_OP(load_srin)
238
{
239
    T0 = regs->sr[T1 >> 28];
240
    RETURN();
241
}
242

    
243
PPC_OP(store_srin)
244
{
245
#if defined (DEBUG_OP)
246
    dump_store_sr(T1 >> 28);
247
#endif
248
    regs->sr[T1 >> 28] = T0;
249
    RETURN();
250
}
251

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

    
258
PPC_OP(store_sdr1)
259
{
260
    regs->sdr1 = T0;
261
    RETURN();
262
}
263

    
264
PPC_OP(exit_tb)
265
{
266
    EXIT_TB();
267
}
268

    
269
/* Load/store special registers */
270
PPC_OP(load_cr)
271
{
272
    do_load_cr();
273
    RETURN();
274
}
275

    
276
PPC_OP(store_cr)
277
{
278
    do_store_cr(PARAM(1));
279
    RETURN();
280
}
281

    
282
PPC_OP(load_xer_cr)
283
{
284
    T0 = (xer_so << 3) | (xer_ov << 2) | (xer_ca << 1);
285
    RETURN();
286
}
287

    
288
PPC_OP(clear_xer_cr)
289
{
290
    xer_so = 0;
291
    xer_ov = 0;
292
    xer_ca = 0;
293
    RETURN();
294
}
295

    
296
PPC_OP(load_xer_bc)
297
{
298
    T1 = xer_bc;
299
    RETURN();
300
}
301

    
302
PPC_OP(load_xer)
303
{
304
    do_load_xer();
305
    RETURN();
306
}
307

    
308
PPC_OP(store_xer)
309
{
310
    do_store_xer();
311
    RETURN();
312
}
313

    
314
PPC_OP(load_msr)
315
{
316
    do_load_msr();
317
    RETURN();
318
}
319

    
320
PPC_OP(store_msr)
321
{
322
    do_store_msr();
323
    RETURN();
324
}
325

    
326
/* SPR */
327
PPC_OP(load_spr)
328
{
329
    T0 = regs->spr[PARAM(1)];
330
    RETURN();
331
}
332

    
333
PPC_OP(store_spr)
334
{
335
    regs->spr[PARAM(1)] = T0;
336
    RETURN();
337
}
338

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

    
345
PPC_OP(store_lr)
346
{
347
    regs->lr = T0;
348
    RETURN();
349
}
350

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

    
357
PPC_OP(store_ctr)
358
{
359
    regs->ctr = T0;
360
    RETURN();
361
}
362

    
363
PPC_OP(load_tbl)
364
{
365
    T0 = cpu_ppc_load_tbl(regs);
366
    RETURN();
367
}
368

    
369
PPC_OP(load_tbu)
370
{
371
    T0 = cpu_ppc_load_tbu(regs);
372
    RETURN();
373
}
374

    
375
PPC_OP(store_tbl)
376
{
377
    cpu_ppc_store_tbl(regs, T0);
378
    RETURN();
379
}
380

    
381
PPC_OP(store_tbu)
382
{
383
    cpu_ppc_store_tbu(regs, T0);
384
    RETURN();
385
}
386

    
387
PPC_OP(load_decr)
388
{
389
    T0 = cpu_ppc_load_decr(regs);
390
    }
391

    
392
PPC_OP(store_decr)
393
{
394
    cpu_ppc_store_decr(regs, T0);
395
    RETURN();
396
}
397

    
398
PPC_OP(load_ibat)
399
{
400
    T0 = regs->IBAT[PARAM(1)][PARAM(2)];
401
}
402

    
403
PPC_OP(store_ibat)
404
{
405
#if defined (DEBUG_OP)
406
    dump_store_ibat(PARAM(1), PARAM(2));
407
#endif
408
    regs->IBAT[PARAM(1)][PARAM(2)] = T0;
409
}
410

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

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

    
424
/* FPSCR */
425
PPC_OP(load_fpscr)
426
{
427
    do_load_fpscr();
428
    RETURN();
429
}
430

    
431
PPC_OP(store_fpscr)
432
{
433
    do_store_fpscr(PARAM(1));
434
    RETURN();
435
}
436

    
437
PPC_OP(reset_scrfx)
438
{
439
    regs->fpscr[7] &= ~0x8;
440
    RETURN();
441
}
442

    
443
/* crf operations */
444
PPC_OP(getbit_T0)
445
{
446
    T0 = (T0 >> PARAM(1)) & 1;
447
    RETURN();
448
}
449

    
450
PPC_OP(getbit_T1)
451
{
452
    T1 = (T1 >> PARAM(1)) & 1;
453
    RETURN();
454
}
455

    
456
PPC_OP(setcrfbit)
457
{
458
    T1 = (T1 & PARAM(1)) | (T0 << PARAM(2)); 
459
    RETURN();
460
}
461

    
462
/* Branch */
463
#define EIP regs->nip
464

    
465
PPC_OP(setlr)
466
{
467
    regs->lr = PARAM1;
468
}
469

    
470
PPC_OP(b)
471
{
472
    JUMP_TB(b1, PARAM1, 0, PARAM2);
473
}
474

    
475
PPC_OP(b_T1)
476
{
477
    regs->nip = T1;
478
}
479

    
480
PPC_OP(btest) 
481
{
482
    if (T0) {
483
        JUMP_TB(btest, PARAM1, 0, PARAM2);
484
    } else {
485
        JUMP_TB(btest, PARAM1, 1, PARAM3);
486
    }
487
    RETURN();
488
}
489

    
490
PPC_OP(btest_T1) 
491
{
492
    if (T0) {
493
        regs->nip = T1 & ~3;
494
    } else {
495
        regs->nip = PARAM1;
496
    }
497
    RETURN();
498
}
499

    
500
PPC_OP(movl_T1_ctr)
501
{
502
    T1 = regs->ctr;
503
}
504

    
505
PPC_OP(movl_T1_lr)
506
{
507
    T1 = regs->lr;
508
}
509

    
510
/* tests with result in T0 */
511

    
512
PPC_OP(test_ctr)
513
{
514
    T0 = regs->ctr;
515
}
516

    
517
PPC_OP(test_ctr_true)
518
{
519
    T0 = (regs->ctr != 0 && (T0 & PARAM(1)) != 0);
520
}
521

    
522
PPC_OP(test_ctr_false)
523
{
524
    T0 = (regs->ctr != 0 && (T0 & PARAM(1)) == 0);
525
}
526

    
527
PPC_OP(test_ctrz)
528
{
529
    T0 = (regs->ctr == 0);
530
}
531

    
532
PPC_OP(test_ctrz_true)
533
{
534
    T0 = (regs->ctr == 0 && (T0 & PARAM(1)) != 0);
535
}
536

    
537
PPC_OP(test_ctrz_false)
538
{
539
    T0 = (regs->ctr == 0 && (T0 & PARAM(1)) == 0);
540
}
541

    
542
PPC_OP(test_true)
543
{
544
    T0 = (T0 & PARAM(1));
545
}
546

    
547
PPC_OP(test_false)
548
{
549
    T0 = ((T0 & PARAM(1)) == 0);
550
}
551

    
552
/* CTR maintenance */
553
PPC_OP(dec_ctr)
554
{
555
    regs->ctr--;
556
    RETURN();
557
}
558

    
559
/***                           Integer arithmetic                          ***/
560
/* add */
561
PPC_OP(add)
562
{
563
    T0 += T1;
564
    RETURN();
565
}
566

    
567
PPC_OP(addo)
568
{
569
    T2 = T0;
570
    T0 += T1;
571
    if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
572
        xer_so = 1;
573
        xer_ov = 1;
574
    } else {
575
        xer_ov = 0;
576
    }
577
    RETURN();
578
}
579

    
580
/* add carrying */
581
PPC_OP(addc)
582
{
583
    T2 = T0;
584
    T0 += T1;
585
    if (T0 < T2) {
586
        xer_ca = 1;
587
    } else {
588
        xer_ca = 0;
589
    }
590
    RETURN();
591
}
592

    
593
PPC_OP(addco)
594
{
595
    T2 = T0;
596
    T0 += T1;
597
    if (T0 < T2) {
598
        xer_ca = 1;
599
    } else {
600
        xer_ca = 0;
601
    }
602
    if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
603
        xer_so = 1;
604
        xer_ov = 1;
605
    } else {
606
        xer_ov = 0;
607
    }
608
    RETURN();
609
}
610

    
611
/* add extended */
612
/* candidate for helper (too long) */
613
PPC_OP(adde)
614
{
615
    T2 = T0;
616
    T0 += T1 + xer_ca;
617
    if (T0 < T2 || (xer_ca == 1 && T0 == T2)) {
618
        xer_ca = 1;
619
    } else {
620
        xer_ca = 0;
621
    }
622
    RETURN();
623
}
624

    
625
PPC_OP(addeo)
626
{
627
    T2 = T0;
628
    T0 += T1 + xer_ca;
629
    if (T0 < T2 || (xer_ca == 1 && T0 == T2)) {
630
        xer_ca = 1;
631
    } else {
632
        xer_ca = 0;
633
    }
634
    if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
635
        xer_so = 1;
636
        xer_ov = 1;
637
    } else {
638
        xer_ov = 0;
639
    }
640
    RETURN();
641
}
642

    
643
/* add immediate */
644
PPC_OP(addi)
645
{
646
    T0 += PARAM(1);
647
    RETURN();
648
}
649

    
650
/* add immediate carrying */
651
PPC_OP(addic)
652
{
653
    T1 = T0;
654
    T0 += PARAM(1);
655
    if (T0 < T1) {
656
        xer_ca = 1;
657
    } else {
658
        xer_ca = 0;
659
    }
660
    RETURN();
661
}
662

    
663
/* add to minus one extended */
664
PPC_OP(addme)
665
{
666
    T1 = T0;
667
    T0 += xer_ca + (-1);
668
    if (T1 != 0)
669
        xer_ca = 1;
670
    RETURN();
671
}
672

    
673
PPC_OP(addmeo)
674
{
675
    T1 = T0;
676
    T0 += xer_ca + (-1);
677
    if (T1 & (T1 ^ T0) & (1 << 31)) {
678
        xer_so = 1;
679
        xer_ov = 1;
680
    } else {
681
        xer_ov = 0;
682
    }
683
    if (T1 != 0)
684
        xer_ca = 1;
685
    RETURN();
686
}
687

    
688
/* add to zero extended */
689
PPC_OP(addze)
690
{
691
    T1 = T0;
692
    T0 += xer_ca;
693
    if (T0 < T1) {
694
        xer_ca = 1;
695
    } else {
696
        xer_ca = 0;
697
    }
698
    RETURN();
699
}
700

    
701
PPC_OP(addzeo)
702
{
703
    T1 = T0;
704
    T0 += xer_ca;
705
    if ((T1 ^ (-1)) & (T1 ^ T0) & (1 << 31)) {
706
        xer_so = 1;
707
        xer_ov = 1;
708
    } else {
709
        xer_ov = 0;
710
    }
711
    if (T0 < T1) {
712
        xer_ca = 1;
713
    } else {
714
        xer_ca = 0;
715
    }
716
    RETURN();
717
}
718

    
719
/* divide word */
720
/* candidate for helper (too long) */
721
PPC_OP(divw)
722
{
723
    if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
724
        Ts0 = (-1) * (T0 >> 31);
725
    } else {
726
        Ts0 /= Ts1;
727
    }
728
    RETURN();
729
}
730

    
731
PPC_OP(divwo)
732
{
733
    if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
734
        xer_so = 1;
735
        xer_ov = 1;
736
        T0 = (-1) * (T0 >> 31);
737
    } else {
738
        xer_ov = 0;
739
        Ts0 /= Ts1;
740
    }
741
    RETURN();
742
}
743

    
744
/* divide word unsigned */
745
PPC_OP(divwu)
746
{
747
    if (T1 == 0) {
748
        T0 = 0;
749
    } else {
750
        T0 /= T1;
751
    }
752
    RETURN();
753
}
754

    
755
PPC_OP(divwuo)
756
{
757
    if (T1 == 0) {
758
        xer_so = 1;
759
        xer_ov = 1;
760
        T0 = 0;
761
    } else {
762
        xer_ov = 0;
763
        T0 /= T1;
764
    }
765
    RETURN();
766
}
767

    
768
/* multiply high word */
769
PPC_OP(mulhw)
770
{
771
    Ts0 = ((int64_t)Ts0 * (int64_t)Ts1) >> 32;
772
    RETURN();
773
}
774

    
775
/* multiply high word unsigned */
776
PPC_OP(mulhwu)
777
{
778
    T0 = ((uint64_t)T0 * (uint64_t)T1) >> 32;
779
    RETURN();
780
}
781

    
782
/* multiply low immediate */
783
PPC_OP(mulli)
784
{
785
    Ts0 *= SPARAM(1);
786
    RETURN();
787
}
788

    
789
/* multiply low word */
790
PPC_OP(mullw)
791
{
792
    T0 *= T1;
793
    RETURN();
794
}
795

    
796
PPC_OP(mullwo)
797
{
798
    int64_t res = (int64_t)Ts0 * (int64_t)Ts1;
799

    
800
    if ((int32_t)res != res) {
801
        xer_ov = 1;
802
        xer_so = 1;
803
    } else {
804
        xer_ov = 0;
805
    }
806
    Ts0 = res;
807
    RETURN();
808
}
809

    
810
/* negate */
811
PPC_OP(neg)
812
{
813
    if (T0 != 0x80000000) {
814
        Ts0 = -Ts0;
815
    }
816
    RETURN();
817
}
818

    
819
PPC_OP(nego)
820
{
821
    if (T0 == 0x80000000) {
822
        xer_ov = 1;
823
        xer_so = 1;
824
    } else {
825
        xer_ov = 0;
826
        Ts0 = -Ts0;
827
    }
828
    RETURN();
829
}
830

    
831
/* substract from */
832
PPC_OP(subf)
833
{
834
    T0 = T1 - T0;
835
    RETURN();
836
}
837

    
838
PPC_OP(subfo)
839
{
840
    T2 = T0;
841
    T0 = T1 - T0;
842
    if (((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)) {
843
        xer_so = 1;
844
        xer_ov = 1;
845
    } else {
846
        xer_ov = 0;
847
    }
848
    RETURN();
849
}
850

    
851
/* substract from carrying */
852
PPC_OP(subfc)
853
{
854
    T0 = T1 - T0;
855
    if (T0 <= T1) {
856
        xer_ca = 1;
857
    } else {
858
        xer_ca = 0;
859
    }
860
    RETURN();
861
}
862

    
863
PPC_OP(subfco)
864
{
865
    T2 = T0;
866
    T0 = T1 - T0;
867
    if (T0 <= T1) {
868
        xer_ca = 1;
869
    } else {
870
        xer_ca = 0;
871
    }
872
    if (((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)) {
873
        xer_so = 1;
874
        xer_ov = 1;
875
    } else {
876
        xer_ov = 0;
877
    }
878
    RETURN();
879
}
880

    
881
/* substract from extended */
882
/* candidate for helper (too long) */
883
PPC_OP(subfe)
884
{
885
    T0 = T1 + ~T0 + xer_ca;
886
    if (T0 < T1 || (xer_ca == 1 && T0 == T1)) {
887
        xer_ca = 1;
888
    } else {
889
        xer_ca = 0;
890
    }
891
    RETURN();
892
}
893

    
894
PPC_OP(subfeo)
895
{
896
    T2 = T0;
897
    T0 = T1 + ~T0 + xer_ca;
898
    if ((~T2 ^ T1 ^ (-1)) & (~T2 ^ T0) & (1 << 31)) {
899
        xer_so = 1;
900
        xer_ov = 1;
901
    } else {
902
        xer_ov = 0;
903
    }
904
    if (T0 < T1 || (xer_ca == 1 && T0 == T1)) {
905
        xer_ca = 1;
906
    } else {
907
        xer_ca = 0;
908
    }
909
    RETURN();
910
}
911

    
912
/* substract from immediate carrying */
913
PPC_OP(subfic)
914
{
915
    T0 = PARAM(1) + ~T0 + 1;
916
    if (T0 <= PARAM(1)) {
917
        xer_ca = 1;
918
    } else {
919
        xer_ca = 0;
920
    }
921
    RETURN();
922
}
923

    
924
/* substract from minus one extended */
925
PPC_OP(subfme)
926
{
927
    T0 = ~T0 + xer_ca - 1;
928

    
929
    if (T0 != -1)
930
        xer_ca = 1;
931
    RETURN();
932
}
933

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

    
949
/* substract from zero extended */
950
PPC_OP(subfze)
951
{
952
    T1 = ~T0;
953
    T0 = T1 + xer_ca;
954
    if (T0 < T1) {
955
        xer_ca = 1;
956
    } else {
957
        xer_ca = 0;
958
    }
959
    RETURN();
960
}
961

    
962
PPC_OP(subfzeo)
963
{
964
    T1 = T0;
965
    T0 = ~T0 + xer_ca;
966
    if ((~T1 ^ (-1)) & ((~T1) ^ T0) & (1 << 31)) {
967
        xer_ov = 1;
968
        xer_so = 1;
969
    } else {
970
        xer_ov = 0;
971
    }
972
    if (T0 < ~T1) {
973
        xer_ca = 1;
974
    } else {
975
        xer_ca = 0;
976
    }
977
    RETURN();
978
}
979

    
980
/***                           Integer comparison                          ***/
981
/* compare */
982
PPC_OP(cmp)
983
{
984
    if (Ts0 < Ts1) {
985
        T0 = 0x08;
986
    } else if (Ts0 > Ts1) {
987
        T0 = 0x04;
988
    } else {
989
        T0 = 0x02;
990
    }
991
    RETURN();
992
}
993

    
994
/* compare immediate */
995
PPC_OP(cmpi)
996
{
997
    if (Ts0 < SPARAM(1)) {
998
        T0 = 0x08;
999
    } else if (Ts0 > SPARAM(1)) {
1000
        T0 = 0x04;
1001
    } else {
1002
        T0 = 0x02;
1003
    }
1004
    RETURN();
1005
}
1006

    
1007
/* compare logical */
1008
PPC_OP(cmpl)
1009
{
1010
    if (T0 < T1) {
1011
        T0 = 0x08;
1012
    } else if (T0 > T1) {
1013
        T0 = 0x04;
1014
    } else {
1015
        T0 = 0x02;
1016
    }
1017
    RETURN();
1018
}
1019

    
1020
/* compare logical immediate */
1021
PPC_OP(cmpli)
1022
{
1023
    if (T0 < PARAM(1)) {
1024
        T0 = 0x08;
1025
    } else if (T0 > PARAM(1)) {
1026
        T0 = 0x04;
1027
    } else {
1028
        T0 = 0x02;
1029
    }
1030
    RETURN();
1031
}
1032

    
1033
/***                            Integer logical                            ***/
1034
/* and */
1035
PPC_OP(and)
1036
{
1037
    T0 &= T1;
1038
    RETURN();
1039
}
1040

    
1041
/* andc */
1042
PPC_OP(andc)
1043
{
1044
    T0 &= ~T1;
1045
    RETURN();
1046
}
1047

    
1048
/* andi. */
1049
PPC_OP(andi_)
1050
{
1051
    T0 &= PARAM(1);
1052
    RETURN();
1053
}
1054

    
1055
/* count leading zero */
1056
PPC_OP(cntlzw)
1057
{
1058
    T1 = T0;
1059
    for (T0 = 32; T1 > 0; T0--)
1060
        T1 = T1 >> 1;
1061
    RETURN();
1062
}
1063

    
1064
/* eqv */
1065
PPC_OP(eqv)
1066
{
1067
    T0 = ~(T0 ^ T1);
1068
    RETURN();
1069
}
1070

    
1071
/* extend sign byte */
1072
PPC_OP(extsb)
1073
{
1074
    Ts0 = s_ext8(Ts0);
1075
    RETURN();
1076
}
1077

    
1078
/* extend sign half word */
1079
PPC_OP(extsh)
1080
{
1081
    Ts0 = s_ext16(Ts0);
1082
    RETURN();
1083
}
1084

    
1085
/* nand */
1086
PPC_OP(nand)
1087
{
1088
    T0 = ~(T0 & T1);
1089
    RETURN();
1090
}
1091

    
1092
/* nor */
1093
PPC_OP(nor)
1094
{
1095
    T0 = ~(T0 | T1);
1096
    RETURN();
1097
}
1098

    
1099
/* or */
1100
PPC_OP(or)
1101
{
1102
    T0 |= T1;
1103
    RETURN();
1104
}
1105

    
1106
/* orc */
1107
PPC_OP(orc)
1108
{
1109
    T0 |= ~T1;
1110
    RETURN();
1111
}
1112

    
1113
/* ori */
1114
PPC_OP(ori)
1115
{
1116
    T0 |= PARAM(1);
1117
    RETURN();
1118
}
1119

    
1120
/* xor */
1121
PPC_OP(xor)
1122
{
1123
    T0 ^= T1;
1124
    RETURN();
1125
}
1126

    
1127
/* xori */
1128
PPC_OP(xori)
1129
{
1130
    T0 ^= PARAM(1);
1131
    RETURN();
1132
}
1133

    
1134
/***                             Integer rotate                            ***/
1135
/* rotate left word immediate then mask insert */
1136
PPC_OP(rlwimi)
1137
{
1138
    T0 = (rotl(T0, PARAM(1)) & PARAM(2)) | (T1 & PARAM(3));
1139
    RETURN();
1140
}
1141

    
1142
/* rotate left immediate then and with mask insert */
1143
PPC_OP(rotlwi)
1144
{
1145
    T0 = rotl(T0, PARAM(1));
1146
    RETURN();
1147
}
1148

    
1149
PPC_OP(slwi)
1150
{
1151
    T0 = T0 << PARAM(1);
1152
    RETURN();
1153
}
1154

    
1155
PPC_OP(srwi)
1156
{
1157
    T0 = T0 >> PARAM(1);
1158
    RETURN();
1159
}
1160

    
1161
/* rotate left word then and with mask insert */
1162
PPC_OP(rlwinm)
1163
{
1164
    T0 = rotl(T0, PARAM(1)) & PARAM(2);
1165
    RETURN();
1166
}
1167

    
1168
PPC_OP(rotl)
1169
{
1170
    T0 = rotl(T0, T1);
1171
    RETURN();
1172
}
1173

    
1174
PPC_OP(rlwnm)
1175
{
1176
    T0 = rotl(T0, T1) & PARAM(1);
1177
    RETURN();
1178
}
1179

    
1180
/***                             Integer shift                             ***/
1181
/* shift left word */
1182
PPC_OP(slw)
1183
{
1184
    if (T1 & 0x20) {
1185
        T0 = 0;
1186
    } else {
1187
        T0 = T0 << T1;
1188
    }
1189
    RETURN();
1190
}
1191

    
1192
/* shift right algebraic word */
1193
PPC_OP(sraw)
1194
{
1195
    do_sraw();
1196
    RETURN();
1197
}
1198

    
1199
/* shift right algebraic word immediate */
1200
PPC_OP(srawi)
1201
{
1202
    Ts1 = Ts0;
1203
    Ts0 = Ts0 >> PARAM(1);
1204
    if (Ts1 < 0 && (Ts1 & PARAM(2)) != 0) {
1205
        xer_ca = 1;
1206
    } else {
1207
        xer_ca = 0;
1208
    }
1209
    RETURN();
1210
}
1211

    
1212
/* shift right word */
1213
PPC_OP(srw)
1214
{
1215
    if (T1 & 0x20) {
1216
        T0 = 0;
1217
    } else {
1218
        T0 = T0 >> T1;
1219
    }
1220
    RETURN();
1221
}
1222

    
1223
/***                       Floating-Point arithmetic                       ***/
1224
/* fadd - fadd. */
1225
PPC_OP(fadd)
1226
{
1227
    FT0 += FT1;
1228
    RETURN();
1229
}
1230

    
1231
/* fadds - fadds. */
1232
PPC_OP(fadds)
1233
{
1234
    FTS0 += FTS1;
1235
    RETURN();
1236
}
1237

    
1238
/* fsub - fsub. */
1239
PPC_OP(fsub)
1240
{
1241
    FT0 -= FT1;
1242
    RETURN();
1243
}
1244

    
1245
/* fsubs - fsubs. */
1246
PPC_OP(fsubs)
1247
{
1248
    FTS0 -= FTS1;
1249
    RETURN();
1250
}
1251

    
1252
/* fmul - fmul. */
1253
PPC_OP(fmul)
1254
{
1255
    FT0 *= FT1;
1256
    RETURN();
1257
}
1258

    
1259
/* fmuls - fmuls. */
1260
PPC_OP(fmuls)
1261
{
1262
    FTS0 *= FTS1;
1263
    RETURN();
1264
}
1265

    
1266
/* fdiv - fdiv. */
1267
PPC_OP(fdiv)
1268
{
1269
    FT0 /= FT1;
1270
    RETURN();
1271
}
1272

    
1273
/* fdivs - fdivs. */
1274
PPC_OP(fdivs)
1275
{
1276
    FTS0 /= FTS1;
1277
    RETURN();
1278
}
1279

    
1280
/* fsqrt - fsqrt. */
1281
PPC_OP(fsqrt)
1282
{
1283
    do_fsqrt();
1284
    RETURN();
1285
}
1286

    
1287
/* fsqrts - fsqrts. */
1288
PPC_OP(fsqrts)
1289
{
1290
    do_fsqrts();
1291
    RETURN();
1292
}
1293

    
1294
/* fres - fres. */
1295
PPC_OP(fres)
1296
{
1297
    do_fres();
1298
    RETURN();
1299
}
1300

    
1301
/* frsqrte  - frsqrte. */
1302
PPC_OP(frsqrte)
1303
{
1304
    do_fsqrte();
1305
    RETURN();
1306
}
1307

    
1308
/* fsel - fsel. */
1309
PPC_OP(fsel)
1310
{
1311
    do_fsel();
1312
    RETURN();
1313
}
1314

    
1315
/***                     Floating-Point multiply-and-add                   ***/
1316
/* fmadd - fmadd. */
1317
PPC_OP(fmadd)
1318
{
1319
    FT0 = (FT0 * FT1) + FT2;
1320
    RETURN();
1321
}
1322

    
1323
/* fmadds - fmadds. */
1324
PPC_OP(fmadds)
1325
{
1326
    FTS0 = (FTS0 * FTS1) + FTS2;
1327
    RETURN();
1328
}
1329

    
1330
/* fmsub - fmsub. */
1331
PPC_OP(fmsub)
1332
{
1333
    FT0 = (FT0 * FT1) - FT2;
1334
    RETURN();
1335
}
1336

    
1337
/* fmsubs - fmsubs. */
1338
PPC_OP(fmsubs)
1339
{
1340
    FTS0 = (FTS0 * FTS1) - FTS2;
1341
    RETURN();
1342
}
1343

    
1344
/* fnmadd - fnmadd. - fnmadds - fnmadds. */
1345
PPC_OP(fnmadd)
1346
{
1347
    FT0 *= FT1;
1348
    FT0 += FT2;
1349
    FT0 = -FT0;
1350
    RETURN();
1351
}
1352

    
1353
/* fnmadds - fnmadds. */
1354
PPC_OP(fnmadds)
1355
{
1356
    do_fnmadds();
1357
    RETURN();
1358
}
1359

    
1360
/* fnmsub - fnmsub. */
1361
PPC_OP(fnmsub)
1362
{
1363
    FT0 *= FT1;
1364
    FT0 -= FT2;
1365
    FT0 = -FT0;
1366
    RETURN();
1367
}
1368

    
1369
/* fnmsubs - fnmsubs. */
1370
PPC_OP(fnmsubs)
1371
{
1372
    do_fnmsubs();
1373
    RETURN();
1374
}
1375

    
1376
/***                     Floating-Point round & convert                    ***/
1377
/* frsp - frsp. */
1378
PPC_OP(frsp)
1379
{
1380
    FT0 = FTS0;
1381
    RETURN();
1382
}
1383

    
1384
/* fctiw - fctiw. */
1385
PPC_OP(fctiw)
1386
{
1387
    do_fctiw();
1388
    RETURN();
1389
}
1390

    
1391
/* fctiwz - fctiwz. */
1392
PPC_OP(fctiwz)
1393
{
1394
    do_fctiwz();
1395
    RETURN();
1396
}
1397

    
1398

    
1399
/***                         Floating-Point compare                        ***/
1400
/* fcmpu */
1401
PPC_OP(fcmpu)
1402
{
1403
    do_fcmpu();
1404
    RETURN();
1405
}
1406

    
1407
/* fcmpo */
1408
PPC_OP(fcmpo)
1409
{
1410
    do_fcmpo();
1411
    RETURN();
1412
}
1413

    
1414
/***                         Floating-point move                           ***/
1415
/* fabs */
1416
PPC_OP(fabs)
1417
{
1418
    do_fabs();
1419
    RETURN();
1420
}
1421

    
1422
/* fnabs */
1423
PPC_OP(fnabs)
1424
{
1425
    do_fnabs();
1426
    RETURN();
1427
}
1428

    
1429
/* fneg */
1430
PPC_OP(fneg)
1431
{
1432
    FT0 = -FT0;
1433
    RETURN();
1434
}
1435

    
1436
/* Load and store */
1437
#define MEMSUFFIX _raw
1438
#include "op_mem.h"
1439
#if !defined(CONFIG_USER_ONLY)
1440
#define MEMSUFFIX _user
1441
#include "op_mem.h"
1442

    
1443
#define MEMSUFFIX _kernel
1444
#include "op_mem.h"
1445
#endif
1446

    
1447
/* Return from interrupt */
1448
PPC_OP(rfi)
1449
{
1450
    regs->nip = regs->spr[SRR0] & ~0x00000003;
1451
    T0 = regs->spr[SRR1] & ~0xFFFF0000;
1452
    do_store_msr();
1453
#if defined (DEBUG_OP)
1454
    dump_rfi();
1455
#endif
1456
    //    do_tlbia();
1457
    do_raise_exception(EXCP_RFI);
1458
    RETURN();
1459
}
1460

    
1461
/* Trap word */
1462
PPC_OP(tw)
1463
{
1464
    if ((Ts0 < Ts1 && (PARAM(1) & 0x10)) ||
1465
        (Ts0 > Ts1 && (PARAM(1) & 0x08)) ||
1466
        (Ts0 == Ts1 && (PARAM(1) & 0x04)) ||
1467
        (T0 < T1 && (PARAM(1) & 0x02)) ||
1468
        (T0 > T1 && (PARAM(1) & 0x01)))
1469
        do_raise_exception_err(EXCP_PROGRAM, EXCP_TRAP);
1470
    RETURN();
1471
}
1472

    
1473
PPC_OP(twi)
1474
{
1475
    if ((Ts0 < SPARAM(1) && (PARAM(2) & 0x10)) ||
1476
        (Ts0 > SPARAM(1) && (PARAM(2) & 0x08)) ||
1477
        (Ts0 == SPARAM(1) && (PARAM(2) & 0x04)) ||
1478
        (T0 < (uint32_t)SPARAM(1) && (PARAM(2) & 0x02)) ||
1479
        (T0 > (uint32_t)SPARAM(1) && (PARAM(2) & 0x01)))
1480
        do_raise_exception_err(EXCP_PROGRAM, EXCP_TRAP);
1481
    RETURN();
1482
}
1483

    
1484
/* Instruction cache block invalidate */
1485
PPC_OP(icbi)
1486
{
1487
    do_icbi();
1488
    RETURN();
1489
}
1490

    
1491
/* tlbia */
1492
PPC_OP(tlbia)
1493
{
1494
    do_tlbia();
1495
    RETURN();
1496
}
1497

    
1498
/* tlbie */
1499
PPC_OP(tlbie)
1500
{
1501
    do_tlbie();
1502
    RETURN();
1503
}