Statistics
| Branch: | Revision:

root / target-ppc / op.c @ 4b3686fa

History | View | Annotate | Download (20.3 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
    do_store_sr(T1 >> 28);
246
    RETURN();
247
}
248

    
249
PPC_OP(load_sdr1)
250
{
251
    T0 = regs->sdr1;
252
    RETURN();
253
}
254

    
255
PPC_OP(store_sdr1)
256
{
257
    regs->sdr1 = T0;
258
    RETURN();
259
}
260

    
261
PPC_OP(exit_tb)
262
{
263
    EXIT_TB();
264
}
265

    
266
/* Load/store special registers */
267
PPC_OP(load_cr)
268
{
269
    do_load_cr();
270
    RETURN();
271
}
272

    
273
PPC_OP(store_cr)
274
{
275
    do_store_cr(PARAM(1));
276
    RETURN();
277
}
278

    
279
PPC_OP(load_xer_cr)
280
{
281
    T0 = (xer_so << 3) | (xer_ov << 2) | (xer_ca << 1);
282
    RETURN();
283
}
284

    
285
PPC_OP(clear_xer_cr)
286
{
287
    xer_so = 0;
288
    xer_ov = 0;
289
    xer_ca = 0;
290
    RETURN();
291
}
292

    
293
PPC_OP(load_xer_bc)
294
{
295
    T1 = xer_bc;
296
    RETURN();
297
}
298

    
299
PPC_OP(load_xer)
300
{
301
    do_load_xer();
302
    RETURN();
303
}
304

    
305
PPC_OP(store_xer)
306
{
307
    do_store_xer();
308
    RETURN();
309
}
310

    
311
PPC_OP(load_msr)
312
{
313
    do_load_msr();
314
    RETURN();
315
}
316

    
317
PPC_OP(store_msr)
318
{
319
    do_store_msr();
320
    RETURN();
321
}
322

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

    
330
PPC_OP(store_spr)
331
{
332
    regs->spr[PARAM(1)] = T0;
333
    RETURN();
334
}
335

    
336
PPC_OP(load_lr)
337
{
338
    T0 = regs->lr;
339
    RETURN();
340
}
341

    
342
PPC_OP(store_lr)
343
{
344
    regs->lr = T0;
345
    RETURN();
346
}
347

    
348
PPC_OP(load_ctr)
349
{
350
    T0 = regs->ctr;
351
    RETURN();
352
}
353

    
354
PPC_OP(store_ctr)
355
{
356
    regs->ctr = T0;
357
    RETURN();
358
}
359

    
360
PPC_OP(load_tbl)
361
{
362
    T0 = cpu_ppc_load_tbl(regs);
363
    RETURN();
364
}
365

    
366
PPC_OP(load_tbu)
367
{
368
    T0 = cpu_ppc_load_tbu(regs);
369
    RETURN();
370
}
371

    
372
PPC_OP(store_tbl)
373
{
374
    cpu_ppc_store_tbl(regs, T0);
375
    RETURN();
376
}
377

    
378
PPC_OP(store_tbu)
379
{
380
    cpu_ppc_store_tbu(regs, T0);
381
    RETURN();
382
}
383

    
384
PPC_OP(load_decr)
385
{
386
    T0 = cpu_ppc_load_decr(regs);
387
    }
388

    
389
PPC_OP(store_decr)
390
{
391
    cpu_ppc_store_decr(regs, T0);
392
    RETURN();
393
}
394

    
395
PPC_OP(load_ibat)
396
{
397
    T0 = regs->IBAT[PARAM(1)][PARAM(2)];
398
}
399

    
400
PPC_OP(store_ibat)
401
{
402
    do_store_ibat(PARAM(1), PARAM(2));
403
}
404

    
405
PPC_OP(load_dbat)
406
{
407
    T0 = regs->DBAT[PARAM(1)][PARAM(2)];
408
}
409

    
410
PPC_OP(store_dbat)
411
{
412
    do_store_dbat(PARAM(1), PARAM(2));
413
}
414

    
415
/* FPSCR */
416
PPC_OP(load_fpscr)
417
{
418
    do_load_fpscr();
419
    RETURN();
420
}
421

    
422
PPC_OP(store_fpscr)
423
{
424
    do_store_fpscr(PARAM(1));
425
    RETURN();
426
}
427

    
428
PPC_OP(reset_scrfx)
429
{
430
    regs->fpscr[7] &= ~0x8;
431
    RETURN();
432
}
433

    
434
/* crf operations */
435
PPC_OP(getbit_T0)
436
{
437
    T0 = (T0 >> PARAM(1)) & 1;
438
    RETURN();
439
}
440

    
441
PPC_OP(getbit_T1)
442
{
443
    T1 = (T1 >> PARAM(1)) & 1;
444
    RETURN();
445
}
446

    
447
PPC_OP(setcrfbit)
448
{
449
    T1 = (T1 & PARAM(1)) | (T0 << PARAM(2)); 
450
    RETURN();
451
}
452

    
453
/* Branch */
454
#define EIP regs->nip
455

    
456
PPC_OP(setlr)
457
{
458
    regs->lr = PARAM1;
459
}
460

    
461
PPC_OP(b)
462
{
463
    JUMP_TB(b1, PARAM1, 0, PARAM2);
464
}
465

    
466
PPC_OP(b_T1)
467
{
468
    regs->nip = T1;
469
}
470

    
471
PPC_OP(btest) 
472
{
473
    if (T0) {
474
        JUMP_TB(btest, PARAM1, 0, PARAM2);
475
    } else {
476
        JUMP_TB(btest, PARAM1, 1, PARAM3);
477
    }
478
    RETURN();
479
}
480

    
481
PPC_OP(btest_T1) 
482
{
483
    if (T0) {
484
        regs->nip = T1 & ~3;
485
    } else {
486
        regs->nip = PARAM1;
487
    }
488
    RETURN();
489
}
490

    
491
PPC_OP(movl_T1_ctr)
492
{
493
    T1 = regs->ctr;
494
}
495

    
496
PPC_OP(movl_T1_lr)
497
{
498
    T1 = regs->lr;
499
}
500

    
501
/* tests with result in T0 */
502

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

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

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

    
518
PPC_OP(test_ctrz)
519
{
520
    T0 = (regs->ctr == 0);
521
}
522

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

    
528
PPC_OP(test_ctrz_false)
529
{
530
    T0 = (regs->ctr == 0 && (T0 & PARAM(1)) == 0);
531
}
532

    
533
PPC_OP(test_true)
534
{
535
    T0 = (T0 & PARAM(1));
536
}
537

    
538
PPC_OP(test_false)
539
{
540
    T0 = ((T0 & PARAM(1)) == 0);
541
}
542

    
543
/* CTR maintenance */
544
PPC_OP(dec_ctr)
545
{
546
    regs->ctr--;
547
    RETURN();
548
}
549

    
550
/***                           Integer arithmetic                          ***/
551
/* add */
552
PPC_OP(add)
553
{
554
    T0 += T1;
555
    RETURN();
556
}
557

    
558
PPC_OP(addo)
559
{
560
    T2 = T0;
561
    T0 += T1;
562
    if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
563
        xer_so = 1;
564
        xer_ov = 1;
565
    } else {
566
        xer_ov = 0;
567
    }
568
    RETURN();
569
}
570

    
571
/* add carrying */
572
PPC_OP(addc)
573
{
574
    T2 = T0;
575
    T0 += T1;
576
    if (T0 < T2) {
577
        xer_ca = 1;
578
    } else {
579
        xer_ca = 0;
580
    }
581
    RETURN();
582
}
583

    
584
PPC_OP(addco)
585
{
586
    T2 = T0;
587
    T0 += T1;
588
    if (T0 < T2) {
589
        xer_ca = 1;
590
    } else {
591
        xer_ca = 0;
592
    }
593
    if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
594
        xer_so = 1;
595
        xer_ov = 1;
596
    } else {
597
        xer_ov = 0;
598
    }
599
    RETURN();
600
}
601

    
602
/* add extended */
603
/* candidate for helper (too long) */
604
PPC_OP(adde)
605
{
606
    T2 = T0;
607
    T0 += T1 + xer_ca;
608
    if (T0 < T2 || (xer_ca == 1 && T0 == T2)) {
609
        xer_ca = 1;
610
    } else {
611
        xer_ca = 0;
612
    }
613
    RETURN();
614
}
615

    
616
PPC_OP(addeo)
617
{
618
    T2 = T0;
619
    T0 += T1 + xer_ca;
620
    if (T0 < T2 || (xer_ca == 1 && T0 == T2)) {
621
        xer_ca = 1;
622
    } else {
623
        xer_ca = 0;
624
    }
625
    if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
626
        xer_so = 1;
627
        xer_ov = 1;
628
    } else {
629
        xer_ov = 0;
630
    }
631
    RETURN();
632
}
633

    
634
/* add immediate */
635
PPC_OP(addi)
636
{
637
    T0 += PARAM(1);
638
    RETURN();
639
}
640

    
641
/* add immediate carrying */
642
PPC_OP(addic)
643
{
644
    T1 = T0;
645
    T0 += PARAM(1);
646
    if (T0 < T1) {
647
        xer_ca = 1;
648
    } else {
649
        xer_ca = 0;
650
    }
651
    RETURN();
652
}
653

    
654
/* add to minus one extended */
655
PPC_OP(addme)
656
{
657
    T1 = T0;
658
    T0 += xer_ca + (-1);
659
    if (T1 != 0)
660
        xer_ca = 1;
661
    RETURN();
662
}
663

    
664
PPC_OP(addmeo)
665
{
666
    T1 = T0;
667
    T0 += xer_ca + (-1);
668
    if (T1 & (T1 ^ T0) & (1 << 31)) {
669
        xer_so = 1;
670
        xer_ov = 1;
671
    } else {
672
        xer_ov = 0;
673
    }
674
    if (T1 != 0)
675
        xer_ca = 1;
676
    RETURN();
677
}
678

    
679
/* add to zero extended */
680
PPC_OP(addze)
681
{
682
    T1 = T0;
683
    T0 += xer_ca;
684
    if (T0 < T1) {
685
        xer_ca = 1;
686
    } else {
687
        xer_ca = 0;
688
    }
689
    RETURN();
690
}
691

    
692
PPC_OP(addzeo)
693
{
694
    T1 = T0;
695
    T0 += xer_ca;
696
    if ((T1 ^ (-1)) & (T1 ^ T0) & (1 << 31)) {
697
        xer_so = 1;
698
        xer_ov = 1;
699
    } else {
700
        xer_ov = 0;
701
    }
702
    if (T0 < T1) {
703
        xer_ca = 1;
704
    } else {
705
        xer_ca = 0;
706
    }
707
    RETURN();
708
}
709

    
710
/* divide word */
711
/* candidate for helper (too long) */
712
PPC_OP(divw)
713
{
714
    if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
715
        Ts0 = (-1) * (T0 >> 31);
716
    } else {
717
        Ts0 /= Ts1;
718
    }
719
    RETURN();
720
}
721

    
722
PPC_OP(divwo)
723
{
724
    if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
725
        xer_so = 1;
726
        xer_ov = 1;
727
        T0 = (-1) * (T0 >> 31);
728
    } else {
729
        xer_ov = 0;
730
        Ts0 /= Ts1;
731
    }
732
    RETURN();
733
}
734

    
735
/* divide word unsigned */
736
PPC_OP(divwu)
737
{
738
    if (T1 == 0) {
739
        T0 = 0;
740
    } else {
741
        T0 /= T1;
742
    }
743
    RETURN();
744
}
745

    
746
PPC_OP(divwuo)
747
{
748
    if (T1 == 0) {
749
        xer_so = 1;
750
        xer_ov = 1;
751
        T0 = 0;
752
    } else {
753
        xer_ov = 0;
754
        T0 /= T1;
755
    }
756
    RETURN();
757
}
758

    
759
/* multiply high word */
760
PPC_OP(mulhw)
761
{
762
    Ts0 = ((int64_t)Ts0 * (int64_t)Ts1) >> 32;
763
    RETURN();
764
}
765

    
766
/* multiply high word unsigned */
767
PPC_OP(mulhwu)
768
{
769
    T0 = ((uint64_t)T0 * (uint64_t)T1) >> 32;
770
    RETURN();
771
}
772

    
773
/* multiply low immediate */
774
PPC_OP(mulli)
775
{
776
    Ts0 *= SPARAM(1);
777
    RETURN();
778
}
779

    
780
/* multiply low word */
781
PPC_OP(mullw)
782
{
783
    T0 *= T1;
784
    RETURN();
785
}
786

    
787
PPC_OP(mullwo)
788
{
789
    int64_t res = (int64_t)Ts0 * (int64_t)Ts1;
790

    
791
    if ((int32_t)res != res) {
792
        xer_ov = 1;
793
        xer_so = 1;
794
    } else {
795
        xer_ov = 0;
796
    }
797
    Ts0 = res;
798
    RETURN();
799
}
800

    
801
/* negate */
802
PPC_OP(neg)
803
{
804
    if (T0 != 0x80000000) {
805
        Ts0 = -Ts0;
806
    }
807
    RETURN();
808
}
809

    
810
PPC_OP(nego)
811
{
812
    if (T0 == 0x80000000) {
813
        xer_ov = 1;
814
        xer_so = 1;
815
    } else {
816
        xer_ov = 0;
817
        Ts0 = -Ts0;
818
    }
819
    RETURN();
820
}
821

    
822
/* substract from */
823
PPC_OP(subf)
824
{
825
    T0 = T1 - T0;
826
    RETURN();
827
}
828

    
829
PPC_OP(subfo)
830
{
831
    T2 = T0;
832
    T0 = T1 - T0;
833
    if (((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)) {
834
        xer_so = 1;
835
        xer_ov = 1;
836
    } else {
837
        xer_ov = 0;
838
    }
839
    RETURN();
840
}
841

    
842
/* substract from carrying */
843
PPC_OP(subfc)
844
{
845
    T0 = T1 - T0;
846
    if (T0 <= T1) {
847
        xer_ca = 1;
848
    } else {
849
        xer_ca = 0;
850
    }
851
    RETURN();
852
}
853

    
854
PPC_OP(subfco)
855
{
856
    T2 = T0;
857
    T0 = T1 - T0;
858
    if (T0 <= T1) {
859
        xer_ca = 1;
860
    } else {
861
        xer_ca = 0;
862
    }
863
    if (((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)) {
864
        xer_so = 1;
865
        xer_ov = 1;
866
    } else {
867
        xer_ov = 0;
868
    }
869
    RETURN();
870
}
871

    
872
/* substract from extended */
873
/* candidate for helper (too long) */
874
PPC_OP(subfe)
875
{
876
    T0 = T1 + ~T0 + xer_ca;
877
    if (T0 < T1 || (xer_ca == 1 && T0 == T1)) {
878
        xer_ca = 1;
879
    } else {
880
        xer_ca = 0;
881
    }
882
    RETURN();
883
}
884

    
885
PPC_OP(subfeo)
886
{
887
    T2 = T0;
888
    T0 = T1 + ~T0 + xer_ca;
889
    if ((~T2 ^ T1 ^ (-1)) & (~T2 ^ T0) & (1 << 31)) {
890
        xer_so = 1;
891
        xer_ov = 1;
892
    } else {
893
        xer_ov = 0;
894
    }
895
    if (T0 < T1 || (xer_ca == 1 && T0 == T1)) {
896
        xer_ca = 1;
897
    } else {
898
        xer_ca = 0;
899
    }
900
    RETURN();
901
}
902

    
903
/* substract from immediate carrying */
904
PPC_OP(subfic)
905
{
906
    T0 = PARAM(1) + ~T0 + 1;
907
    if (T0 <= PARAM(1)) {
908
        xer_ca = 1;
909
    } else {
910
        xer_ca = 0;
911
    }
912
    RETURN();
913
}
914

    
915
/* substract from minus one extended */
916
PPC_OP(subfme)
917
{
918
    T0 = ~T0 + xer_ca - 1;
919

    
920
    if (T0 != -1)
921
        xer_ca = 1;
922
    RETURN();
923
}
924

    
925
PPC_OP(subfmeo)
926
{
927
    T1 = T0;
928
    T0 = ~T0 + xer_ca - 1;
929
    if (~T1 & (~T1 ^ T0) & (1 << 31)) {
930
        xer_so = 1;
931
        xer_ov = 1;
932
    } else {
933
        xer_ov = 0;
934
    }
935
    if (T1 != -1)
936
        xer_ca = 1;
937
    RETURN();
938
}
939

    
940
/* substract from zero extended */
941
PPC_OP(subfze)
942
{
943
    T1 = ~T0;
944
    T0 = T1 + xer_ca;
945
    if (T0 < T1) {
946
        xer_ca = 1;
947
    } else {
948
        xer_ca = 0;
949
    }
950
    RETURN();
951
}
952

    
953
PPC_OP(subfzeo)
954
{
955
    T1 = T0;
956
    T0 = ~T0 + xer_ca;
957
    if ((~T1 ^ (-1)) & ((~T1) ^ T0) & (1 << 31)) {
958
        xer_ov = 1;
959
        xer_so = 1;
960
    } else {
961
        xer_ov = 0;
962
    }
963
    if (T0 < ~T1) {
964
        xer_ca = 1;
965
    } else {
966
        xer_ca = 0;
967
    }
968
    RETURN();
969
}
970

    
971
/***                           Integer comparison                          ***/
972
/* compare */
973
PPC_OP(cmp)
974
{
975
    if (Ts0 < Ts1) {
976
        T0 = 0x08;
977
    } else if (Ts0 > Ts1) {
978
        T0 = 0x04;
979
    } else {
980
        T0 = 0x02;
981
    }
982
    RETURN();
983
}
984

    
985
/* compare immediate */
986
PPC_OP(cmpi)
987
{
988
    if (Ts0 < SPARAM(1)) {
989
        T0 = 0x08;
990
    } else if (Ts0 > SPARAM(1)) {
991
        T0 = 0x04;
992
    } else {
993
        T0 = 0x02;
994
    }
995
    RETURN();
996
}
997

    
998
/* compare logical */
999
PPC_OP(cmpl)
1000
{
1001
    if (T0 < T1) {
1002
        T0 = 0x08;
1003
    } else if (T0 > T1) {
1004
        T0 = 0x04;
1005
    } else {
1006
        T0 = 0x02;
1007
    }
1008
    RETURN();
1009
}
1010

    
1011
/* compare logical immediate */
1012
PPC_OP(cmpli)
1013
{
1014
    if (T0 < PARAM(1)) {
1015
        T0 = 0x08;
1016
    } else if (T0 > PARAM(1)) {
1017
        T0 = 0x04;
1018
    } else {
1019
        T0 = 0x02;
1020
    }
1021
    RETURN();
1022
}
1023

    
1024
/***                            Integer logical                            ***/
1025
/* and */
1026
PPC_OP(and)
1027
{
1028
    T0 &= T1;
1029
    RETURN();
1030
}
1031

    
1032
/* andc */
1033
PPC_OP(andc)
1034
{
1035
    T0 &= ~T1;
1036
    RETURN();
1037
}
1038

    
1039
/* andi. */
1040
PPC_OP(andi_)
1041
{
1042
    T0 &= PARAM(1);
1043
    RETURN();
1044
}
1045

    
1046
/* count leading zero */
1047
PPC_OP(cntlzw)
1048
{
1049
    T1 = T0;
1050
    for (T0 = 32; T1 > 0; T0--)
1051
        T1 = T1 >> 1;
1052
    RETURN();
1053
}
1054

    
1055
/* eqv */
1056
PPC_OP(eqv)
1057
{
1058
    T0 = ~(T0 ^ T1);
1059
    RETURN();
1060
}
1061

    
1062
/* extend sign byte */
1063
PPC_OP(extsb)
1064
{
1065
    Ts0 = s_ext8(Ts0);
1066
    RETURN();
1067
}
1068

    
1069
/* extend sign half word */
1070
PPC_OP(extsh)
1071
{
1072
    Ts0 = s_ext16(Ts0);
1073
    RETURN();
1074
}
1075

    
1076
/* nand */
1077
PPC_OP(nand)
1078
{
1079
    T0 = ~(T0 & T1);
1080
    RETURN();
1081
}
1082

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

    
1090
/* or */
1091
PPC_OP(or)
1092
{
1093
    T0 |= T1;
1094
    RETURN();
1095
}
1096

    
1097
/* orc */
1098
PPC_OP(orc)
1099
{
1100
    T0 |= ~T1;
1101
    RETURN();
1102
}
1103

    
1104
/* ori */
1105
PPC_OP(ori)
1106
{
1107
    T0 |= PARAM(1);
1108
    RETURN();
1109
}
1110

    
1111
/* xor */
1112
PPC_OP(xor)
1113
{
1114
    T0 ^= T1;
1115
    RETURN();
1116
}
1117

    
1118
/* xori */
1119
PPC_OP(xori)
1120
{
1121
    T0 ^= PARAM(1);
1122
    RETURN();
1123
}
1124

    
1125
/***                             Integer rotate                            ***/
1126
/* rotate left word immediate then mask insert */
1127
PPC_OP(rlwimi)
1128
{
1129
    T0 = (rotl(T0, PARAM(1)) & PARAM(2)) | (T1 & PARAM(3));
1130
    RETURN();
1131
}
1132

    
1133
/* rotate left immediate then and with mask insert */
1134
PPC_OP(rotlwi)
1135
{
1136
    T0 = rotl(T0, PARAM(1));
1137
    RETURN();
1138
}
1139

    
1140
PPC_OP(slwi)
1141
{
1142
    T0 = T0 << PARAM(1);
1143
    RETURN();
1144
}
1145

    
1146
PPC_OP(srwi)
1147
{
1148
    T0 = T0 >> PARAM(1);
1149
    RETURN();
1150
}
1151

    
1152
/* rotate left word then and with mask insert */
1153
PPC_OP(rlwinm)
1154
{
1155
    T0 = rotl(T0, PARAM(1)) & PARAM(2);
1156
    RETURN();
1157
}
1158

    
1159
PPC_OP(rotl)
1160
{
1161
    T0 = rotl(T0, T1);
1162
    RETURN();
1163
}
1164

    
1165
PPC_OP(rlwnm)
1166
{
1167
    T0 = rotl(T0, T1) & PARAM(1);
1168
    RETURN();
1169
}
1170

    
1171
/***                             Integer shift                             ***/
1172
/* shift left word */
1173
PPC_OP(slw)
1174
{
1175
    if (T1 & 0x20) {
1176
        T0 = 0;
1177
    } else {
1178
        T0 = T0 << T1;
1179
    }
1180
    RETURN();
1181
}
1182

    
1183
/* shift right algebraic word */
1184
PPC_OP(sraw)
1185
{
1186
    do_sraw();
1187
    RETURN();
1188
}
1189

    
1190
/* shift right algebraic word immediate */
1191
PPC_OP(srawi)
1192
{
1193
    Ts1 = Ts0;
1194
    Ts0 = Ts0 >> PARAM(1);
1195
    if (Ts1 < 0 && (Ts1 & PARAM(2)) != 0) {
1196
        xer_ca = 1;
1197
    } else {
1198
        xer_ca = 0;
1199
    }
1200
    RETURN();
1201
}
1202

    
1203
/* shift right word */
1204
PPC_OP(srw)
1205
{
1206
    if (T1 & 0x20) {
1207
        T0 = 0;
1208
    } else {
1209
        T0 = T0 >> T1;
1210
    }
1211
    RETURN();
1212
}
1213

    
1214
/***                       Floating-Point arithmetic                       ***/
1215
/* fadd - fadd. */
1216
PPC_OP(fadd)
1217
{
1218
    FT0 += FT1;
1219
    RETURN();
1220
}
1221

    
1222
/* fadds - fadds. */
1223
PPC_OP(fadds)
1224
{
1225
    FTS0 += FTS1;
1226
    RETURN();
1227
}
1228

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

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

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

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

    
1257
/* fdiv - fdiv. */
1258
PPC_OP(fdiv)
1259
{
1260
    FT0 /= FT1;
1261
    RETURN();
1262
}
1263

    
1264
/* fdivs - fdivs. */
1265
PPC_OP(fdivs)
1266
{
1267
    FTS0 /= FTS1;
1268
    RETURN();
1269
}
1270

    
1271
/* fsqrt - fsqrt. */
1272
PPC_OP(fsqrt)
1273
{
1274
    do_fsqrt();
1275
    RETURN();
1276
}
1277

    
1278
/* fsqrts - fsqrts. */
1279
PPC_OP(fsqrts)
1280
{
1281
    do_fsqrts();
1282
    RETURN();
1283
}
1284

    
1285
/* fres - fres. */
1286
PPC_OP(fres)
1287
{
1288
    do_fres();
1289
    RETURN();
1290
}
1291

    
1292
/* frsqrte  - frsqrte. */
1293
PPC_OP(frsqrte)
1294
{
1295
    do_fsqrte();
1296
    RETURN();
1297
}
1298

    
1299
/* fsel - fsel. */
1300
PPC_OP(fsel)
1301
{
1302
    do_fsel();
1303
    RETURN();
1304
}
1305

    
1306
/***                     Floating-Point multiply-and-add                   ***/
1307
/* fmadd - fmadd. */
1308
PPC_OP(fmadd)
1309
{
1310
    FT0 = (FT0 * FT1) + FT2;
1311
    RETURN();
1312
}
1313

    
1314
/* fmadds - fmadds. */
1315
PPC_OP(fmadds)
1316
{
1317
    FTS0 = (FTS0 * FTS1) + FTS2;
1318
    RETURN();
1319
}
1320

    
1321
/* fmsub - fmsub. */
1322
PPC_OP(fmsub)
1323
{
1324
    FT0 = (FT0 * FT1) - FT2;
1325
    RETURN();
1326
}
1327

    
1328
/* fmsubs - fmsubs. */
1329
PPC_OP(fmsubs)
1330
{
1331
    FTS0 = (FTS0 * FTS1) - FTS2;
1332
    RETURN();
1333
}
1334

    
1335
/* fnmadd - fnmadd. - fnmadds - fnmadds. */
1336
PPC_OP(fnmadd)
1337
{
1338
    do_fnmadd();
1339
    RETURN();
1340
}
1341

    
1342
/* fnmadds - fnmadds. */
1343
PPC_OP(fnmadds)
1344
{
1345
    do_fnmadds();
1346
    RETURN();
1347
}
1348

    
1349
/* fnmsub - fnmsub. */
1350
PPC_OP(fnmsub)
1351
{
1352
    do_fnmsub();
1353
    RETURN();
1354
}
1355

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

    
1363
/***                     Floating-Point round & convert                    ***/
1364
/* frsp - frsp. */
1365
PPC_OP(frsp)
1366
{
1367
    FT0 = FTS0;
1368
    RETURN();
1369
}
1370

    
1371
/* fctiw - fctiw. */
1372
PPC_OP(fctiw)
1373
{
1374
    do_fctiw();
1375
    RETURN();
1376
}
1377

    
1378
/* fctiwz - fctiwz. */
1379
PPC_OP(fctiwz)
1380
{
1381
    do_fctiwz();
1382
    RETURN();
1383
}
1384

    
1385

    
1386
/***                         Floating-Point compare                        ***/
1387
/* fcmpu */
1388
PPC_OP(fcmpu)
1389
{
1390
    do_fcmpu();
1391
    RETURN();
1392
}
1393

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

    
1401
/***                         Floating-point move                           ***/
1402
/* fabs */
1403
PPC_OP(fabs)
1404
{
1405
    do_fabs();
1406
    RETURN();
1407
}
1408

    
1409
/* fnabs */
1410
PPC_OP(fnabs)
1411
{
1412
    do_fnabs();
1413
    RETURN();
1414
}
1415

    
1416
/* fneg */
1417
PPC_OP(fneg)
1418
{
1419
    FT0 = -FT0;
1420
    RETURN();
1421
}
1422

    
1423
/* Load and store */
1424
#define MEMSUFFIX _raw
1425
#include "op_mem.h"
1426
#if !defined(CONFIG_USER_ONLY)
1427
#define MEMSUFFIX _user
1428
#include "op_mem.h"
1429

    
1430
#define MEMSUFFIX _kernel
1431
#include "op_mem.h"
1432
#endif
1433

    
1434
/* Special op to check and maybe clear reservation */
1435
PPC_OP(check_reservation)
1436
{
1437
    do_check_reservation();
1438
    RETURN();
1439
}
1440

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

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

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

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

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

    
1496
/* tlbie */
1497
PPC_OP(tlbie)
1498
{
1499
    do_tlbie();
1500
    RETURN();
1501
}