Statistics
| Branch: | Revision:

root / target-ppc / op.c @ 3cc62370

History | View | Annotate | Download (20.2 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
    tmp |= xer_ov;
151
    env->crf[0] = tmp;
152
    RETURN();
153
}
154

    
155
/* reset_Rc0 */
156
PPC_OP(reset_Rc0)
157
{
158
    env->crf[0] = 0x02 | xer_ov;
159
    RETURN();
160
}
161

    
162
/* set_Rc0_1 */
163
PPC_OP(set_Rc0_1)
164
{
165
    env->crf[0] = 0x04 | xer_ov;
166
    RETURN();
167
}
168

    
169
/* Set Rc1 (for floating point arithmetic) */
170
PPC_OP(set_Rc1)
171
{
172
    env->crf[1] = regs->fpscr[7];
173
    RETURN();
174
}
175

    
176
/* Constants load */
177
PPC_OP(set_T0)
178
{
179
    T0 = PARAM(1);
180
    RETURN();
181
}
182

    
183
PPC_OP(set_T1)
184
{
185
    T1 = PARAM(1);
186
    RETURN();
187
}
188

    
189
PPC_OP(set_T2)
190
{
191
    T2 = PARAM(1);
192
    RETURN();
193
}
194

    
195
/* Generate exceptions */
196
PPC_OP(raise_exception_err)
197
{
198
    do_raise_exception_err(PARAM(1), PARAM(2));
199
}
200

    
201
PPC_OP(raise_exception)
202
{
203
    do_raise_exception(PARAM(1));
204
}
205

    
206
PPC_OP(update_nip)
207
{
208
    env->nip = PARAM(1);
209
}
210

    
211
PPC_OP(debug)
212
{
213
    env->nip = PARAM(1);
214
#if defined (DEBUG_OP)
215
    dump_state();
216
#endif
217
    do_raise_exception(EXCP_DEBUG);
218
    RETURN();
219
}
220

    
221
/* Segment registers load and store with immediate index */
222
PPC_OP(load_srin)
223
{
224
    T0 = regs->sr[T1 >> 28];
225
    RETURN();
226
}
227

    
228
PPC_OP(store_srin)
229
{
230
    do_store_sr(T1 >> 28);
231
    RETURN();
232
}
233

    
234
PPC_OP(load_sdr1)
235
{
236
    T0 = regs->sdr1;
237
    RETURN();
238
}
239

    
240
PPC_OP(store_sdr1)
241
{
242
    regs->sdr1 = T0;
243
    RETURN();
244
}
245

    
246
PPC_OP(exit_tb)
247
{
248
    EXIT_TB();
249
}
250

    
251
/* Load/store special registers */
252
PPC_OP(load_cr)
253
{
254
    do_load_cr();
255
    RETURN();
256
}
257

    
258
PPC_OP(store_cr)
259
{
260
    do_store_cr(PARAM(1));
261
    RETURN();
262
}
263

    
264
PPC_OP(load_xer_cr)
265
{
266
    T0 = (xer_so << 3) | (xer_ov << 2) | (xer_ca << 1);
267
    RETURN();
268
}
269

    
270
PPC_OP(clear_xer_cr)
271
{
272
    xer_so = 0;
273
    xer_ov = 0;
274
    xer_ca = 0;
275
    RETURN();
276
}
277

    
278
PPC_OP(load_xer_bc)
279
{
280
    T1 = xer_bc;
281
    RETURN();
282
}
283

    
284
PPC_OP(load_xer)
285
{
286
    do_load_xer();
287
    RETURN();
288
}
289

    
290
PPC_OP(store_xer)
291
{
292
    do_store_xer();
293
    RETURN();
294
}
295

    
296
PPC_OP(load_msr)
297
{
298
    do_load_msr();
299
    RETURN();
300
}
301

    
302
PPC_OP(store_msr)
303
{
304
    do_store_msr();
305
    RETURN();
306
}
307

    
308
/* SPR */
309
PPC_OP(load_spr)
310
{
311
    T0 = regs->spr[PARAM(1)];
312
    RETURN();
313
}
314

    
315
PPC_OP(store_spr)
316
{
317
    regs->spr[PARAM(1)] = T0;
318
    RETURN();
319
}
320

    
321
PPC_OP(load_lr)
322
{
323
    T0 = regs->lr;
324
    RETURN();
325
}
326

    
327
PPC_OP(store_lr)
328
{
329
    regs->lr = T0;
330
    RETURN();
331
}
332

    
333
PPC_OP(load_ctr)
334
{
335
    T0 = regs->ctr;
336
    RETURN();
337
}
338

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

    
345
PPC_OP(load_tbl)
346
{
347
    T0 = cpu_ppc_load_tbl(regs);
348
    RETURN();
349
}
350

    
351
PPC_OP(load_tbu)
352
{
353
    T0 = cpu_ppc_load_tbu(regs);
354
    RETURN();
355
}
356

    
357
PPC_OP(store_tbl)
358
{
359
    cpu_ppc_store_tbl(regs, T0);
360
    RETURN();
361
}
362

    
363
PPC_OP(store_tbu)
364
{
365
    cpu_ppc_store_tbu(regs, T0);
366
    RETURN();
367
}
368

    
369
PPC_OP(load_decr)
370
{
371
    T0 = cpu_ppc_load_decr(regs);
372
    }
373

    
374
PPC_OP(store_decr)
375
{
376
    cpu_ppc_store_decr(regs, T0);
377
    RETURN();
378
}
379

    
380
PPC_OP(load_ibat)
381
{
382
    T0 = regs->IBAT[PARAM(1)][PARAM(2)];
383
}
384

    
385
PPC_OP(store_ibat)
386
{
387
    do_store_ibat(PARAM(1), PARAM(2));
388
}
389

    
390
PPC_OP(load_dbat)
391
{
392
    T0 = regs->DBAT[PARAM(1)][PARAM(2)];
393
}
394

    
395
PPC_OP(store_dbat)
396
{
397
    do_store_dbat(PARAM(1), PARAM(2));
398
}
399

    
400
/* FPSCR */
401
PPC_OP(load_fpscr)
402
{
403
    do_load_fpscr();
404
    RETURN();
405
}
406

    
407
PPC_OP(store_fpscr)
408
{
409
    do_store_fpscr(PARAM(1));
410
    RETURN();
411
}
412

    
413
PPC_OP(reset_scrfx)
414
{
415
    regs->fpscr[7] &= ~0x8;
416
    RETURN();
417
}
418

    
419
/* crf operations */
420
PPC_OP(getbit_T0)
421
{
422
    T0 = (T0 >> PARAM(1)) & 1;
423
    RETURN();
424
}
425

    
426
PPC_OP(getbit_T1)
427
{
428
    T1 = (T1 >> PARAM(1)) & 1;
429
    RETURN();
430
}
431

    
432
PPC_OP(setcrfbit)
433
{
434
    T1 = (T1 & PARAM(1)) | (T0 << PARAM(2)); 
435
    RETURN();
436
}
437

    
438
/* Branch */
439
#define EIP regs->nip
440

    
441
PPC_OP(setlr)
442
{
443
    regs->lr = PARAM1;
444
}
445

    
446
PPC_OP(b)
447
{
448
    JUMP_TB(b1, PARAM1, 0, PARAM2);
449
}
450

    
451
PPC_OP(b_T1)
452
{
453
    regs->nip = T1;
454
}
455

    
456
PPC_OP(btest) 
457
{
458
    if (T0) {
459
        JUMP_TB(btest, PARAM1, 0, PARAM2);
460
    } else {
461
        JUMP_TB(btest, PARAM1, 1, PARAM3);
462
    }
463
    RETURN();
464
}
465

    
466
PPC_OP(btest_T1) 
467
{
468
    if (T0) {
469
        regs->nip = T1 & ~3;
470
    } else {
471
        regs->nip = PARAM1;
472
    }
473
    RETURN();
474
}
475

    
476
PPC_OP(movl_T1_ctr)
477
{
478
    T1 = regs->ctr;
479
}
480

    
481
PPC_OP(movl_T1_lr)
482
{
483
    T1 = regs->lr;
484
}
485

    
486
/* tests with result in T0 */
487

    
488
PPC_OP(test_ctr)
489
{
490
    T0 = regs->ctr;
491
}
492

    
493
PPC_OP(test_ctr_true)
494
{
495
    T0 = (regs->ctr != 0 && (T0 & PARAM(1)) != 0);
496
}
497

    
498
PPC_OP(test_ctr_false)
499
{
500
    T0 = (regs->ctr != 0 && (T0 & PARAM(1)) == 0);
501
}
502

    
503
PPC_OP(test_ctrz)
504
{
505
    T0 = (regs->ctr == 0);
506
}
507

    
508
PPC_OP(test_ctrz_true)
509
{
510
    T0 = (regs->ctr == 0 && (T0 & PARAM(1)) != 0);
511
}
512

    
513
PPC_OP(test_ctrz_false)
514
{
515
    T0 = (regs->ctr == 0 && (T0 & PARAM(1)) == 0);
516
}
517

    
518
PPC_OP(test_true)
519
{
520
    T0 = (T0 & PARAM(1));
521
}
522

    
523
PPC_OP(test_false)
524
{
525
    T0 = ((T0 & PARAM(1)) == 0);
526
}
527

    
528
/* CTR maintenance */
529
PPC_OP(dec_ctr)
530
{
531
    regs->ctr--;
532
    RETURN();
533
}
534

    
535
/***                           Integer arithmetic                          ***/
536
/* add */
537
PPC_OP(add)
538
{
539
    T0 += T1;
540
    RETURN();
541
}
542

    
543
PPC_OP(addo)
544
{
545
    T2 = T0;
546
    T0 += T1;
547
    if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
548
        xer_so = 1;
549
        xer_ov = 1;
550
    } else {
551
        xer_ov = 0;
552
    }
553
    RETURN();
554
}
555

    
556
/* add carrying */
557
PPC_OP(addc)
558
{
559
    T2 = T0;
560
    T0 += T1;
561
    if (T0 < T2) {
562
        xer_ca = 1;
563
    } else {
564
        xer_ca = 0;
565
    }
566
    RETURN();
567
}
568

    
569
PPC_OP(addco)
570
{
571
    T2 = T0;
572
    T0 += T1;
573
    if (T0 < T2) {
574
        xer_ca = 1;
575
    } else {
576
        xer_ca = 0;
577
    }
578
    if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
579
        xer_so = 1;
580
        xer_ov = 1;
581
    } else {
582
        xer_ov = 0;
583
    }
584
    RETURN();
585
}
586

    
587
/* add extended */
588
/* candidate for helper (too long) */
589
PPC_OP(adde)
590
{
591
    T2 = T0;
592
    T0 += T1 + xer_ca;
593
    if (T0 < T2 || (xer_ca == 1 && T0 == T2)) {
594
        xer_ca = 1;
595
    } else {
596
        xer_ca = 0;
597
    }
598
    RETURN();
599
}
600

    
601
PPC_OP(addeo)
602
{
603
    T2 = T0;
604
    T0 += T1 + xer_ca;
605
    if (T0 < T2 || (xer_ca == 1 && T0 == T2)) {
606
        xer_ca = 1;
607
    } else {
608
        xer_ca = 0;
609
    }
610
    if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
611
        xer_so = 1;
612
        xer_ov = 1;
613
    } else {
614
        xer_ov = 0;
615
    }
616
    RETURN();
617
}
618

    
619
/* add immediate */
620
PPC_OP(addi)
621
{
622
    T0 += PARAM(1);
623
    RETURN();
624
}
625

    
626
/* add immediate carrying */
627
PPC_OP(addic)
628
{
629
    T1 = T0;
630
    T0 += PARAM(1);
631
    if (T0 < T1) {
632
        xer_ca = 1;
633
    } else {
634
        xer_ca = 0;
635
    }
636
    RETURN();
637
}
638

    
639
/* add to minus one extended */
640
PPC_OP(addme)
641
{
642
    T1 = T0;
643
    T0 += xer_ca + (-1);
644
    if (T1 != 0)
645
        xer_ca = 1;
646
    RETURN();
647
}
648

    
649
PPC_OP(addmeo)
650
{
651
    T1 = T0;
652
    T0 += xer_ca + (-1);
653
    if (T1 & (T1 ^ T0) & (1 << 31)) {
654
        xer_so = 1;
655
        xer_ov = 1;
656
    } else {
657
        xer_ov = 0;
658
    }
659
    if (T1 != 0)
660
        xer_ca = 1;
661
    RETURN();
662
}
663

    
664
/* add to zero extended */
665
PPC_OP(addze)
666
{
667
    T1 = T0;
668
    T0 += xer_ca;
669
    if (T0 < T1) {
670
        xer_ca = 1;
671
    } else {
672
        xer_ca = 0;
673
    }
674
    RETURN();
675
}
676

    
677
PPC_OP(addzeo)
678
{
679
    T1 = T0;
680
    T0 += xer_ca;
681
    if ((T1 ^ (-1)) & (T1 ^ T0) & (1 << 31)) {
682
        xer_so = 1;
683
        xer_ov = 1;
684
    } else {
685
        xer_ov = 0;
686
    }
687
    if (T0 < T1) {
688
        xer_ca = 1;
689
    } else {
690
        xer_ca = 0;
691
    }
692
    RETURN();
693
}
694

    
695
/* divide word */
696
/* candidate for helper (too long) */
697
PPC_OP(divw)
698
{
699
    if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
700
        T0 = (int32_t)((-1) * (T0 >> 31));
701
    } else {
702
        T0 = (Ts0 / Ts1);
703
    }
704
    RETURN();
705
}
706

    
707
PPC_OP(divwo)
708
{
709
    if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
710
        xer_so = 1;
711
        xer_ov = 1;
712
        T0 = (-1) * (T0 >> 31);
713
    } else {
714
        xer_ov = 0;
715
        T0 = (Ts0 / Ts1);
716
    }
717
    RETURN();
718
}
719

    
720
/* divide word unsigned */
721
PPC_OP(divwu)
722
{
723
    if (T1 == 0) {
724
        T0 = 0;
725
    } else {
726
        T0 /= T1;
727
    }
728
    RETURN();
729
}
730

    
731
PPC_OP(divwuo)
732
{
733
    if (T1 == 0) {
734
        xer_so = 1;
735
        xer_ov = 1;
736
        T0 = 0;
737
    } else {
738
        xer_ov = 0;
739
        T0 /= T1;
740
    }
741
    RETURN();
742
}
743

    
744
/* multiply high word */
745
PPC_OP(mulhw)
746
{
747
    T0 = ((int64_t)Ts0 * (int64_t)Ts1) >> 32;
748
    RETURN();
749
}
750

    
751
/* multiply high word unsigned */
752
PPC_OP(mulhwu)
753
{
754
    T0 = ((uint64_t)T0 * (uint64_t)T1) >> 32;
755
    RETURN();
756
}
757

    
758
/* multiply low immediate */
759
PPC_OP(mulli)
760
{
761
    T0 = (Ts0 * SPARAM(1));
762
    RETURN();
763
}
764

    
765
/* multiply low word */
766
PPC_OP(mullw)
767
{
768
    T0 *= T1;
769
    RETURN();
770
}
771

    
772
PPC_OP(mullwo)
773
{
774
    int64_t res = (int64_t)Ts0 * (int64_t)Ts1;
775

    
776
    if ((int32_t)res != res) {
777
        xer_ov = 1;
778
        xer_so = 1;
779
    } else {
780
        xer_ov = 0;
781
    }
782
    T0 = (int32_t)res;
783
    RETURN();
784
}
785

    
786
/* negate */
787
PPC_OP(neg)
788
{
789
    if (T0 != 0x80000000) {
790
        T0 = -Ts0;
791
    }
792
    RETURN();
793
}
794

    
795
PPC_OP(nego)
796
{
797
    if (T0 == 0x80000000) {
798
        xer_ov = 1;
799
        xer_so = 1;
800
    } else {
801
        xer_ov = 0;
802
        T0 = -Ts0;
803
    }
804
    RETURN();
805
}
806

    
807
/* substract from */
808
PPC_OP(subf)
809
{
810
    T0 = T1 - T0;
811
    RETURN();
812
}
813

    
814
PPC_OP(subfo)
815
{
816
    T2 = T0;
817
    T0 = T1 - T0;
818
    if (((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)) {
819
        xer_so = 1;
820
        xer_ov = 1;
821
    } else {
822
        xer_ov = 0;
823
    }
824
    RETURN();
825
}
826

    
827
/* substract from carrying */
828
PPC_OP(subfc)
829
{
830
    T0 = T1 - T0;
831
    if (T0 <= T1) {
832
        xer_ca = 1;
833
    } else {
834
        xer_ca = 0;
835
    }
836
    RETURN();
837
}
838

    
839
PPC_OP(subfco)
840
{
841
    T2 = T0;
842
    T0 = T1 - T0;
843
    if (T0 <= T1) {
844
        xer_ca = 1;
845
    } else {
846
        xer_ca = 0;
847
    }
848
    if (((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)) {
849
        xer_so = 1;
850
        xer_ov = 1;
851
    } else {
852
        xer_ov = 0;
853
    }
854
    RETURN();
855
}
856

    
857
/* substract from extended */
858
/* candidate for helper (too long) */
859
PPC_OP(subfe)
860
{
861
    T0 = T1 + ~T0 + xer_ca;
862
    if (T0 < T1 || (xer_ca == 1 && T0 == T1)) {
863
        xer_ca = 1;
864
    } else {
865
        xer_ca = 0;
866
    }
867
    RETURN();
868
}
869

    
870
PPC_OP(subfeo)
871
{
872
    T2 = T0;
873
    T0 = T1 + ~T0 + xer_ca;
874
    if ((~T2 ^ T1 ^ (-1)) & (~T2 ^ T0) & (1 << 31)) {
875
        xer_so = 1;
876
        xer_ov = 1;
877
    } else {
878
        xer_ov = 0;
879
    }
880
    if (T0 < T1 || (xer_ca == 1 && T0 == T1)) {
881
        xer_ca = 1;
882
    } else {
883
        xer_ca = 0;
884
    }
885
    RETURN();
886
}
887

    
888
/* substract from immediate carrying */
889
PPC_OP(subfic)
890
{
891
    T0 = PARAM(1) + ~T0 + 1;
892
    if (T0 <= PARAM(1)) {
893
        xer_ca = 1;
894
    } else {
895
        xer_ca = 0;
896
    }
897
    RETURN();
898
}
899

    
900
/* substract from minus one extended */
901
PPC_OP(subfme)
902
{
903
    T0 = ~T0 + xer_ca - 1;
904

    
905
    if (T0 != -1)
906
        xer_ca = 1;
907
    RETURN();
908
}
909

    
910
PPC_OP(subfmeo)
911
{
912
    T1 = T0;
913
    T0 = ~T0 + xer_ca - 1;
914
    if (~T1 & (~T1 ^ T0) & (1 << 31)) {
915
        xer_so = 1;
916
        xer_ov = 1;
917
    } else {
918
        xer_ov = 0;
919
    }
920
    if (T1 != -1)
921
        xer_ca = 1;
922
    RETURN();
923
}
924

    
925
/* substract from zero extended */
926
PPC_OP(subfze)
927
{
928
    T1 = ~T0;
929
    T0 = T1 + xer_ca;
930
    if (T0 < T1) {
931
        xer_ca = 1;
932
    } else {
933
        xer_ca = 0;
934
    }
935
    RETURN();
936
}
937

    
938
PPC_OP(subfzeo)
939
{
940
    T1 = T0;
941
    T0 = ~T0 + xer_ca;
942
    if ((~T1 ^ (-1)) & ((~T1) ^ T0) & (1 << 31)) {
943
        xer_ov = 1;
944
        xer_so = 1;
945
    } else {
946
        xer_ov = 0;
947
    }
948
    if (T0 < ~T1) {
949
        xer_ca = 1;
950
    } else {
951
        xer_ca = 0;
952
    }
953
    RETURN();
954
}
955

    
956
/***                           Integer comparison                          ***/
957
/* compare */
958
PPC_OP(cmp)
959
{
960
    if (Ts0 < Ts1) {
961
        T0 = 0x08;
962
    } else if (Ts0 > Ts1) {
963
        T0 = 0x04;
964
    } else {
965
        T0 = 0x02;
966
    }
967
    RETURN();
968
}
969

    
970
/* compare immediate */
971
PPC_OP(cmpi)
972
{
973
    if (Ts0 < SPARAM(1)) {
974
        T0 = 0x08;
975
    } else if (Ts0 > SPARAM(1)) {
976
        T0 = 0x04;
977
    } else {
978
        T0 = 0x02;
979
    }
980
    RETURN();
981
}
982

    
983
/* compare logical */
984
PPC_OP(cmpl)
985
{
986
    if (T0 < T1) {
987
        T0 = 0x08;
988
    } else if (T0 > T1) {
989
        T0 = 0x04;
990
    } else {
991
        T0 = 0x02;
992
    }
993
    RETURN();
994
}
995

    
996
/* compare logical immediate */
997
PPC_OP(cmpli)
998
{
999
    if (T0 < PARAM(1)) {
1000
        T0 = 0x08;
1001
    } else if (T0 > PARAM(1)) {
1002
        T0 = 0x04;
1003
    } else {
1004
        T0 = 0x02;
1005
    }
1006
    RETURN();
1007
}
1008

    
1009
/***                            Integer logical                            ***/
1010
/* and */
1011
PPC_OP(and)
1012
{
1013
    T0 &= T1;
1014
    RETURN();
1015
}
1016

    
1017
/* andc */
1018
PPC_OP(andc)
1019
{
1020
    T0 &= ~T1;
1021
    RETURN();
1022
}
1023

    
1024
/* andi. */
1025
PPC_OP(andi_)
1026
{
1027
    T0 &= PARAM(1);
1028
    RETURN();
1029
}
1030

    
1031
/* count leading zero */
1032
PPC_OP(cntlzw)
1033
{
1034
    T1 = T0;
1035
    for (T0 = 32; T1 > 0; T0--)
1036
        T1 = T1 >> 1;
1037
    RETURN();
1038
}
1039

    
1040
/* eqv */
1041
PPC_OP(eqv)
1042
{
1043
    T0 = ~(T0 ^ T1);
1044
    RETURN();
1045
}
1046

    
1047
/* extend sign byte */
1048
PPC_OP(extsb)
1049
{
1050
    T0 = (int32_t)((int8_t)(Ts0));
1051
    RETURN();
1052
}
1053

    
1054
/* extend sign half word */
1055
PPC_OP(extsh)
1056
{
1057
    T0 = (int32_t)((int16_t)(Ts0));
1058
    RETURN();
1059
}
1060

    
1061
/* nand */
1062
PPC_OP(nand)
1063
{
1064
    T0 = ~(T0 & T1);
1065
    RETURN();
1066
}
1067

    
1068
/* nor */
1069
PPC_OP(nor)
1070
{
1071
    T0 = ~(T0 | T1);
1072
    RETURN();
1073
}
1074

    
1075
/* or */
1076
PPC_OP(or)
1077
{
1078
    T0 |= T1;
1079
    RETURN();
1080
}
1081

    
1082
/* orc */
1083
PPC_OP(orc)
1084
{
1085
    T0 |= ~T1;
1086
    RETURN();
1087
}
1088

    
1089
/* ori */
1090
PPC_OP(ori)
1091
{
1092
    T0 |= PARAM(1);
1093
    RETURN();
1094
}
1095

    
1096
/* xor */
1097
PPC_OP(xor)
1098
{
1099
    T0 ^= T1;
1100
    RETURN();
1101
}
1102

    
1103
/* xori */
1104
PPC_OP(xori)
1105
{
1106
    T0 ^= PARAM(1);
1107
    RETURN();
1108
}
1109

    
1110
/***                             Integer rotate                            ***/
1111
/* rotate left word immediate then mask insert */
1112
PPC_OP(rlwimi)
1113
{
1114
    T0 = (rotl(T0, PARAM(1)) & PARAM(2)) | (T1 & PARAM(3));
1115
    RETURN();
1116
}
1117

    
1118
/* rotate left immediate then and with mask insert */
1119
PPC_OP(rotlwi)
1120
{
1121
    T0 = rotl(T0, PARAM(1));
1122
    RETURN();
1123
}
1124

    
1125
PPC_OP(slwi)
1126
{
1127
    T0 = T0 << PARAM(1);
1128
    RETURN();
1129
}
1130

    
1131
PPC_OP(srwi)
1132
{
1133
    T0 = T0 >> PARAM(1);
1134
    RETURN();
1135
}
1136

    
1137
/* rotate left word then and with mask insert */
1138
PPC_OP(rlwinm)
1139
{
1140
    T0 = rotl(T0, PARAM(1)) & PARAM(2);
1141
    RETURN();
1142
}
1143

    
1144
PPC_OP(rotl)
1145
{
1146
    T0 = rotl(T0, T1);
1147
    RETURN();
1148
}
1149

    
1150
PPC_OP(rlwnm)
1151
{
1152
    T0 = rotl(T0, T1) & PARAM(1);
1153
    RETURN();
1154
}
1155

    
1156
/***                             Integer shift                             ***/
1157
/* shift left word */
1158
PPC_OP(slw)
1159
{
1160
    if (T1 & 0x20) {
1161
        T0 = 0;
1162
    } else {
1163
        T0 = T0 << T1;
1164
    }
1165
    RETURN();
1166
}
1167

    
1168
/* shift right algebraic word */
1169
PPC_OP(sraw)
1170
{
1171
    do_sraw();
1172
    RETURN();
1173
}
1174

    
1175
/* shift right algebraic word immediate */
1176
PPC_OP(srawi)
1177
{
1178
    T1 = T0;
1179
    T0 = (Ts0 >> PARAM(1));
1180
    if (Ts1 < 0 && (Ts1 & PARAM(2)) != 0) {
1181
        xer_ca = 1;
1182
    } else {
1183
        xer_ca = 0;
1184
    }
1185
    RETURN();
1186
}
1187

    
1188
/* shift right word */
1189
PPC_OP(srw)
1190
{
1191
    if (T1 & 0x20) {
1192
        T0 = 0;
1193
    } else {
1194
        T0 = T0 >> T1;
1195
    }
1196
    RETURN();
1197
}
1198

    
1199
/***                       Floating-Point arithmetic                       ***/
1200
/* fadd - fadd. */
1201
PPC_OP(fadd)
1202
{
1203
    FT0 += FT1;
1204
    RETURN();
1205
}
1206

    
1207
/* fadds - fadds. */
1208
PPC_OP(fadds)
1209
{
1210
    FT0 = FTS0 + FTS1;
1211
    RETURN();
1212
}
1213

    
1214
/* fsub - fsub. */
1215
PPC_OP(fsub)
1216
{
1217
    FT0 -= FT1;
1218
    RETURN();
1219
}
1220

    
1221
/* fsubs - fsubs. */
1222
PPC_OP(fsubs)
1223
{
1224
    FT0 = FTS0 - FTS1;
1225
    RETURN();
1226
}
1227

    
1228
/* fmul - fmul. */
1229
PPC_OP(fmul)
1230
{
1231
    FT0 *= FT1;
1232
    RETURN();
1233
}
1234

    
1235
/* fmuls - fmuls. */
1236
PPC_OP(fmuls)
1237
{
1238
    FT0 = FTS0 * FTS1;
1239
    RETURN();
1240
}
1241

    
1242
/* fdiv - fdiv. */
1243
PPC_OP(fdiv)
1244
{
1245
    FT0 /= FT1;
1246
    RETURN();
1247
}
1248

    
1249
/* fdivs - fdivs. */
1250
PPC_OP(fdivs)
1251
{
1252
    FT0 = FTS0 / FTS1;
1253
    RETURN();
1254
}
1255

    
1256
/* fsqrt - fsqrt. */
1257
PPC_OP(fsqrt)
1258
{
1259
    do_fsqrt();
1260
    RETURN();
1261
}
1262

    
1263
/* fsqrts - fsqrts. */
1264
PPC_OP(fsqrts)
1265
{
1266
    do_fsqrts();
1267
    RETURN();
1268
}
1269

    
1270
/* fres - fres. */
1271
PPC_OP(fres)
1272
{
1273
    do_fres();
1274
    RETURN();
1275
}
1276

    
1277
/* frsqrte  - frsqrte. */
1278
PPC_OP(frsqrte)
1279
{
1280
    do_fsqrte();
1281
    RETURN();
1282
}
1283

    
1284
/* fsel - fsel. */
1285
PPC_OP(fsel)
1286
{
1287
    do_fsel();
1288
    RETURN();
1289
}
1290

    
1291
/***                     Floating-Point multiply-and-add                   ***/
1292
/* fmadd - fmadd. */
1293
PPC_OP(fmadd)
1294
{
1295
    FT0 = (FT0 * FT1) + FT2;
1296
    RETURN();
1297
}
1298

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

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

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

    
1320
/* fnmadd - fnmadd. - fnmadds - fnmadds. */
1321
PPC_OP(fnmadd)
1322
{
1323
    do_fnmadd();
1324
    RETURN();
1325
}
1326

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

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

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

    
1348
/***                     Floating-Point round & convert                    ***/
1349
/* frsp - frsp. */
1350
PPC_OP(frsp)
1351
{
1352
    FT0 = (float)FT0;
1353
    RETURN();
1354
}
1355

    
1356
/* fctiw - fctiw. */
1357
PPC_OP(fctiw)
1358
{
1359
    do_fctiw();
1360
    RETURN();
1361
}
1362

    
1363
/* fctiwz - fctiwz. */
1364
PPC_OP(fctiwz)
1365
{
1366
    do_fctiwz();
1367
    RETURN();
1368
}
1369

    
1370

    
1371
/***                         Floating-Point compare                        ***/
1372
/* fcmpu */
1373
PPC_OP(fcmpu)
1374
{
1375
    do_fcmpu();
1376
    RETURN();
1377
}
1378

    
1379
/* fcmpo */
1380
PPC_OP(fcmpo)
1381
{
1382
    do_fcmpo();
1383
    RETURN();
1384
}
1385

    
1386
/***                         Floating-point move                           ***/
1387
/* fabs */
1388
PPC_OP(fabs)
1389
{
1390
    do_fabs();
1391
    RETURN();
1392
}
1393

    
1394
/* fnabs */
1395
PPC_OP(fnabs)
1396
{
1397
    do_fnabs();
1398
    RETURN();
1399
}
1400

    
1401
/* fneg */
1402
PPC_OP(fneg)
1403
{
1404
    FT0 = -FT0;
1405
    RETURN();
1406
}
1407

    
1408
/* Load and store */
1409
#define MEMSUFFIX _raw
1410
#include "op_mem.h"
1411
#if !defined(CONFIG_USER_ONLY)
1412
#define MEMSUFFIX _user
1413
#include "op_mem.h"
1414

    
1415
#define MEMSUFFIX _kernel
1416
#include "op_mem.h"
1417
#endif
1418

    
1419
/* Special op to check and maybe clear reservation */
1420
PPC_OP(check_reservation)
1421
{
1422
    do_check_reservation();
1423
    RETURN();
1424
}
1425

    
1426
/* Return from interrupt */
1427
PPC_OP(rfi)
1428
{
1429
    regs->nip = regs->spr[SRR0] & ~0x00000003;
1430
#if 1 // TRY
1431
    T0 = regs->spr[SRR1] & ~0xFFF00000;
1432
#else
1433
    T0 = regs->spr[SRR1] & ~0xFFFF0000;
1434
#endif
1435
    do_store_msr();
1436
#if defined (DEBUG_OP)
1437
    dump_rfi();
1438
#endif
1439
    //    do_tlbia();
1440
    do_raise_exception(EXCP_RFI);
1441
    RETURN();
1442
}
1443

    
1444
/* Trap word */
1445
PPC_OP(tw)
1446
{
1447
    if ((Ts0 < Ts1 && (PARAM(1) & 0x10)) ||
1448
        (Ts0 > Ts1 && (PARAM(1) & 0x08)) ||
1449
        (Ts0 == Ts1 && (PARAM(1) & 0x04)) ||
1450
        (T0 < T1 && (PARAM(1) & 0x02)) ||
1451
        (T0 > T1 && (PARAM(1) & 0x01)))
1452
        do_raise_exception_err(EXCP_PROGRAM, EXCP_TRAP);
1453
    RETURN();
1454
}
1455

    
1456
PPC_OP(twi)
1457
{
1458
    if ((Ts0 < SPARAM(1) && (PARAM(2) & 0x10)) ||
1459
        (Ts0 > SPARAM(1) && (PARAM(2) & 0x08)) ||
1460
        (Ts0 == SPARAM(1) && (PARAM(2) & 0x04)) ||
1461
        (T0 < (uint32_t)SPARAM(1) && (PARAM(2) & 0x02)) ||
1462
        (T0 > (uint32_t)SPARAM(1) && (PARAM(2) & 0x01)))
1463
        do_raise_exception_err(EXCP_PROGRAM, EXCP_TRAP);
1464
    RETURN();
1465
}
1466

    
1467
/* Instruction cache block invalidate */
1468
PPC_OP(icbi)
1469
{
1470
    do_icbi();
1471
    RETURN();
1472
}
1473

    
1474
/* tlbia */
1475
PPC_OP(tlbia)
1476
{
1477
    do_tlbia();
1478
    RETURN();
1479
}
1480

    
1481
/* tlbie */
1482
PPC_OP(tlbie)
1483
{
1484
    do_tlbie();
1485
    RETURN();
1486
}