Statistics
| Branch: | Revision:

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

History | View | Annotate | Download (19.9 kB)

1
/*
2
 *  PowerPC emulation micro-operations for qemu.
3
 * 
4
 *  Copyright (c) 2003-2005 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 PPC_OP(name) void glue(op_, name)(void)
36

    
37
#define REG 0
38
#include "op_template.h"
39

    
40
#define REG 1
41
#include "op_template.h"
42

    
43
#define REG 2
44
#include "op_template.h"
45

    
46
#define REG 3
47
#include "op_template.h"
48

    
49
#define REG 4
50
#include "op_template.h"
51

    
52
#define REG 5
53
#include "op_template.h"
54

    
55
#define REG 6
56
#include "op_template.h"
57

    
58
#define REG 7
59
#include "op_template.h"
60

    
61
#define REG 8
62
#include "op_template.h"
63

    
64
#define REG 9
65
#include "op_template.h"
66

    
67
#define REG 10
68
#include "op_template.h"
69

    
70
#define REG 11
71
#include "op_template.h"
72

    
73
#define REG 12
74
#include "op_template.h"
75

    
76
#define REG 13
77
#include "op_template.h"
78

    
79
#define REG 14
80
#include "op_template.h"
81

    
82
#define REG 15
83
#include "op_template.h"
84

    
85
#define REG 16
86
#include "op_template.h"
87

    
88
#define REG 17
89
#include "op_template.h"
90

    
91
#define REG 18
92
#include "op_template.h"
93

    
94
#define REG 19
95
#include "op_template.h"
96

    
97
#define REG 20
98
#include "op_template.h"
99

    
100
#define REG 21
101
#include "op_template.h"
102

    
103
#define REG 22
104
#include "op_template.h"
105

    
106
#define REG 23
107
#include "op_template.h"
108

    
109
#define REG 24
110
#include "op_template.h"
111

    
112
#define REG 25
113
#include "op_template.h"
114

    
115
#define REG 26
116
#include "op_template.h"
117

    
118
#define REG 27
119
#include "op_template.h"
120

    
121
#define REG 28
122
#include "op_template.h"
123

    
124
#define REG 29
125
#include "op_template.h"
126

    
127
#define REG 30
128
#include "op_template.h"
129

    
130
#define REG 31
131
#include "op_template.h"
132

    
133
/* PowerPC state maintenance operations */
134
/* set_Rc0 */
135
PPC_OP(set_Rc0)
136
{
137
    uint32_t tmp;
138

    
139
    if (Ts0 < 0) {
140
        tmp = 0x08;
141
    } else if (Ts0 > 0) {
142
        tmp = 0x04;
143
    } else {
144
        tmp = 0x02;
145
    }
146
    tmp |= xer_ov;
147
    env->crf[0] = tmp;
148
    RETURN();
149
}
150

    
151
/* reset_Rc0 */
152
PPC_OP(reset_Rc0)
153
{
154
    env->crf[0] = 0x02 | xer_ov;
155
    RETURN();
156
}
157

    
158
/* set_Rc0_1 */
159
PPC_OP(set_Rc0_1)
160
{
161
    env->crf[0] = 0x04 | xer_ov;
162
    RETURN();
163
}
164

    
165
/* Set Rc1 (for floating point arithmetic) */
166
PPC_OP(set_Rc1)
167
{
168
    env->crf[1] = regs->fpscr[7];
169
    RETURN();
170
}
171

    
172
/* Constants load */
173
PPC_OP(set_T0)
174
{
175
    T0 = PARAM(1);
176
    RETURN();
177
}
178

    
179
PPC_OP(set_T1)
180
{
181
    T1 = PARAM(1);
182
    RETURN();
183
}
184

    
185
PPC_OP(set_T2)
186
{
187
    T2 = PARAM(1);
188
    RETURN();
189
}
190

    
191
/* Generate exceptions */
192
PPC_OP(raise_exception_err)
193
{
194
    do_raise_exception_err(PARAM(1), PARAM(2));
195
}
196

    
197
PPC_OP(raise_exception)
198
{
199
    do_raise_exception(PARAM(1));
200
}
201

    
202
PPC_OP(update_nip)
203
{
204
    env->nip = PARAM(1);
205
}
206

    
207
PPC_OP(debug)
208
{
209
    env->nip = PARAM(1);
210
#if defined (DEBUG_OP)
211
    dump_state();
212
#endif
213
    do_raise_exception(EXCP_DEBUG);
214
    RETURN();
215
}
216

    
217
/* Segment registers load and store with immediate index */
218
PPC_OP(load_srin)
219
{
220
    T0 = regs->sr[T1 >> 28];
221
    RETURN();
222
}
223

    
224
PPC_OP(store_srin)
225
{
226
    do_store_sr(env, ((uint32_t)T1 >> 28), T0);
227
    RETURN();
228
}
229

    
230
PPC_OP(load_sdr1)
231
{
232
    T0 = regs->sdr1;
233
    RETURN();
234
}
235

    
236
PPC_OP(store_sdr1)
237
{
238
    do_store_sdr1(env, T0);
239
    RETURN();
240
}
241

    
242
PPC_OP(exit_tb)
243
{
244
    EXIT_TB();
245
}
246

    
247
/* Load/store special registers */
248
PPC_OP(load_cr)
249
{
250
    T0 = do_load_cr(env);
251
    RETURN();
252
}
253

    
254
PPC_OP(store_cr)
255
{
256
    do_store_cr(env, T0, PARAM(1));
257
    RETURN();
258
}
259

    
260
PPC_OP(load_xer_cr)
261
{
262
    T0 = (xer_so << 3) | (xer_ov << 2) | (xer_ca << 1);
263
    RETURN();
264
}
265

    
266
PPC_OP(clear_xer_cr)
267
{
268
    xer_so = 0;
269
    xer_ov = 0;
270
    xer_ca = 0;
271
    RETURN();
272
}
273

    
274
PPC_OP(load_xer_bc)
275
{
276
    T1 = xer_bc;
277
    RETURN();
278
}
279

    
280
PPC_OP(load_xer)
281
{
282
    T0 = do_load_xer(env);
283
    RETURN();
284
}
285

    
286
PPC_OP(store_xer)
287
{
288
    do_store_xer(env, T0);
289
    RETURN();
290
}
291

    
292
PPC_OP(load_msr)
293
{
294
    T0 = do_load_msr(env);
295
    RETURN();
296
}
297

    
298
PPC_OP(store_msr)
299
{
300
    do_store_msr(env, T0);
301
    RETURN();
302
}
303

    
304
/* SPR */
305
PPC_OP(load_spr)
306
{
307
    T0 = regs->spr[PARAM(1)];
308
    RETURN();
309
}
310

    
311
PPC_OP(store_spr)
312
{
313
    regs->spr[PARAM(1)] = T0;
314
    RETURN();
315
}
316

    
317
PPC_OP(load_lr)
318
{
319
    T0 = regs->lr;
320
    RETURN();
321
}
322

    
323
PPC_OP(store_lr)
324
{
325
    regs->lr = T0;
326
    RETURN();
327
}
328

    
329
PPC_OP(load_ctr)
330
{
331
    T0 = regs->ctr;
332
    RETURN();
333
}
334

    
335
PPC_OP(store_ctr)
336
{
337
    regs->ctr = T0;
338
    RETURN();
339
}
340

    
341
PPC_OP(load_tbl)
342
{
343
    T0 = cpu_ppc_load_tbl(regs);
344
    RETURN();
345
}
346

    
347
PPC_OP(load_tbu)
348
{
349
    T0 = cpu_ppc_load_tbu(regs);
350
    RETURN();
351
}
352

    
353
PPC_OP(store_tbl)
354
{
355
    cpu_ppc_store_tbl(regs, T0);
356
    RETURN();
357
}
358

    
359
PPC_OP(store_tbu)
360
{
361
    cpu_ppc_store_tbu(regs, T0);
362
    RETURN();
363
}
364

    
365
PPC_OP(load_decr)
366
{
367
    T0 = cpu_ppc_load_decr(regs);
368
    }
369

    
370
PPC_OP(store_decr)
371
{
372
    cpu_ppc_store_decr(regs, T0);
373
    RETURN();
374
}
375

    
376
PPC_OP(load_ibat)
377
{
378
    T0 = regs->IBAT[PARAM(1)][PARAM(2)];
379
}
380

    
381
void op_store_ibatu (void)
382
{
383
    do_store_ibatu(env, PARAM1, T0);
384
    RETURN();
385
}
386

    
387
void op_store_ibatl (void)
388
{
389
#if 1
390
    env->IBAT[1][PARAM1] = T0;
391
#else
392
    do_store_ibatl(env, PARAM1, T0);
393
#endif
394
    RETURN();
395
}
396

    
397
PPC_OP(load_dbat)
398
{
399
    T0 = regs->DBAT[PARAM(1)][PARAM(2)];
400
}
401

    
402
void op_store_dbatu (void)
403
{
404
    do_store_dbatu(env, PARAM1, T0);
405
    RETURN();
406
}
407

    
408
void op_store_dbatl (void)
409
{
410
#if 1
411
    env->DBAT[1][PARAM1] = T0;
412
#else
413
    do_store_dbatl(env, PARAM1, T0);
414
#endif
415
    RETURN();
416
}
417

    
418
/* FPSCR */
419
PPC_OP(load_fpscr)
420
{
421
    FT0 = do_load_fpscr(env);
422
    RETURN();
423
}
424

    
425
PPC_OP(store_fpscr)
426
{
427
    do_store_fpscr(env, FT0, PARAM1);
428
    RETURN();
429
}
430

    
431
PPC_OP(reset_scrfx)
432
{
433
    regs->fpscr[7] &= ~0x8;
434
    RETURN();
435
}
436

    
437
/* crf operations */
438
PPC_OP(getbit_T0)
439
{
440
    T0 = (T0 >> PARAM(1)) & 1;
441
    RETURN();
442
}
443

    
444
PPC_OP(getbit_T1)
445
{
446
    T1 = (T1 >> PARAM(1)) & 1;
447
    RETURN();
448
}
449

    
450
PPC_OP(setcrfbit)
451
{
452
    T1 = (T1 & PARAM(1)) | (T0 << PARAM(2)); 
453
    RETURN();
454
}
455

    
456
/* Branch */
457
#define EIP regs->nip
458

    
459
PPC_OP(setlr)
460
{
461
    regs->lr = PARAM1;
462
}
463

    
464
PPC_OP(b)
465
{
466
    JUMP_TB(b1, PARAM1, 0, PARAM2);
467
}
468

    
469
PPC_OP(b_T1)
470
{
471
    regs->nip = T1 & ~3;
472
}
473

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

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

    
494
PPC_OP(movl_T1_ctr)
495
{
496
    T1 = regs->ctr;
497
}
498

    
499
PPC_OP(movl_T1_lr)
500
{
501
    T1 = regs->lr;
502
}
503

    
504
/* tests with result in T0 */
505

    
506
PPC_OP(test_ctr)
507
{
508
    T0 = regs->ctr;
509
}
510

    
511
PPC_OP(test_ctr_true)
512
{
513
    T0 = (regs->ctr != 0 && (T0 & PARAM(1)) != 0);
514
}
515

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

    
521
PPC_OP(test_ctrz)
522
{
523
    T0 = (regs->ctr == 0);
524
}
525

    
526
PPC_OP(test_ctrz_true)
527
{
528
    T0 = (regs->ctr == 0 && (T0 & PARAM(1)) != 0);
529
}
530

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

    
536
PPC_OP(test_true)
537
{
538
    T0 = (T0 & PARAM(1));
539
}
540

    
541
PPC_OP(test_false)
542
{
543
    T0 = ((T0 & PARAM(1)) == 0);
544
}
545

    
546
/* CTR maintenance */
547
PPC_OP(dec_ctr)
548
{
549
    regs->ctr--;
550
    RETURN();
551
}
552

    
553
/***                           Integer arithmetic                          ***/
554
/* add */
555
PPC_OP(add)
556
{
557
    T0 += T1;
558
    RETURN();
559
}
560

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

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

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

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

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

    
637
/* add immediate */
638
PPC_OP(addi)
639
{
640
    T0 += PARAM(1);
641
    RETURN();
642
}
643

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

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

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

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

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

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

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

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

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

    
762
/* multiply high word */
763
PPC_OP(mulhw)
764
{
765
    T0 = ((int64_t)Ts0 * (int64_t)Ts1) >> 32;
766
    RETURN();
767
}
768

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

    
776
/* multiply low immediate */
777
PPC_OP(mulli)
778
{
779
    T0 = (Ts0 * SPARAM(1));
780
    RETURN();
781
}
782

    
783
/* multiply low word */
784
PPC_OP(mullw)
785
{
786
    T0 *= T1;
787
    RETURN();
788
}
789

    
790
PPC_OP(mullwo)
791
{
792
    int64_t res = (int64_t)Ts0 * (int64_t)Ts1;
793

    
794
    if ((int32_t)res != res) {
795
        xer_ov = 1;
796
        xer_so = 1;
797
    } else {
798
        xer_ov = 0;
799
    }
800
    T0 = (int32_t)res;
801
    RETURN();
802
}
803

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

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

    
825
/* substract from */
826
PPC_OP(subf)
827
{
828
    T0 = T1 - T0;
829
    RETURN();
830
}
831

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

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

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

    
875
/* substract from extended */
876
/* candidate for helper (too long) */
877
PPC_OP(subfe)
878
{
879
    T0 = T1 + ~T0 + xer_ca;
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
PPC_OP(subfeo)
889
{
890
    T2 = T0;
891
    T0 = T1 + ~T0 + xer_ca;
892
    if ((~T2 ^ T1 ^ (-1)) & (~T2 ^ T0) & (1 << 31)) {
893
        xer_so = 1;
894
        xer_ov = 1;
895
    } else {
896
        xer_ov = 0;
897
    }
898
    if (T0 < T1 || (xer_ca == 1 && T0 == T1)) {
899
        xer_ca = 1;
900
    } else {
901
        xer_ca = 0;
902
    }
903
    RETURN();
904
}
905

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

    
918
/* substract from minus one extended */
919
PPC_OP(subfme)
920
{
921
    T0 = ~T0 + xer_ca - 1;
922

    
923
    if (T0 != -1)
924
        xer_ca = 1;
925
    RETURN();
926
}
927

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

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

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

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

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

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

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

    
1027
/***                            Integer logical                            ***/
1028
/* and */
1029
PPC_OP(and)
1030
{
1031
    T0 &= T1;
1032
    RETURN();
1033
}
1034

    
1035
/* andc */
1036
PPC_OP(andc)
1037
{
1038
    T0 &= ~T1;
1039
    RETURN();
1040
}
1041

    
1042
/* andi. */
1043
PPC_OP(andi_)
1044
{
1045
    T0 &= PARAM(1);
1046
    RETURN();
1047
}
1048

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

    
1058
/* eqv */
1059
PPC_OP(eqv)
1060
{
1061
    T0 = ~(T0 ^ T1);
1062
    RETURN();
1063
}
1064

    
1065
/* extend sign byte */
1066
PPC_OP(extsb)
1067
{
1068
    T0 = (int32_t)((int8_t)(Ts0));
1069
    RETURN();
1070
}
1071

    
1072
/* extend sign half word */
1073
PPC_OP(extsh)
1074
{
1075
    T0 = (int32_t)((int16_t)(Ts0));
1076
    RETURN();
1077
}
1078

    
1079
/* nand */
1080
PPC_OP(nand)
1081
{
1082
    T0 = ~(T0 & T1);
1083
    RETURN();
1084
}
1085

    
1086
/* nor */
1087
PPC_OP(nor)
1088
{
1089
    T0 = ~(T0 | T1);
1090
    RETURN();
1091
}
1092

    
1093
/* or */
1094
PPC_OP(or)
1095
{
1096
    T0 |= T1;
1097
    RETURN();
1098
}
1099

    
1100
/* orc */
1101
PPC_OP(orc)
1102
{
1103
    T0 |= ~T1;
1104
    RETURN();
1105
}
1106

    
1107
/* ori */
1108
PPC_OP(ori)
1109
{
1110
    T0 |= PARAM(1);
1111
    RETURN();
1112
}
1113

    
1114
/* xor */
1115
PPC_OP(xor)
1116
{
1117
    T0 ^= T1;
1118
    RETURN();
1119
}
1120

    
1121
/* xori */
1122
PPC_OP(xori)
1123
{
1124
    T0 ^= PARAM(1);
1125
    RETURN();
1126
}
1127

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

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

    
1143
PPC_OP(slwi)
1144
{
1145
    T0 = T0 << PARAM(1);
1146
    RETURN();
1147
}
1148

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

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

    
1162
PPC_OP(rotl)
1163
{
1164
    T0 = rotl(T0, T1);
1165
    RETURN();
1166
}
1167

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

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

    
1186
/* shift right algebraic word */
1187
PPC_OP(sraw)
1188
{
1189
    do_sraw();
1190
    RETURN();
1191
}
1192

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

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

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

    
1225
/* fsub - fsub. */
1226
PPC_OP(fsub)
1227
{
1228
    FT0 -= FT1;
1229
    RETURN();
1230
}
1231

    
1232
/* fmul - fmul. */
1233
PPC_OP(fmul)
1234
{
1235
    FT0 *= FT1;
1236
    RETURN();
1237
}
1238

    
1239
/* fdiv - fdiv. */
1240
void do_fdiv (void);
1241
PPC_OP(fdiv)
1242
{
1243
    do_fdiv();
1244
    RETURN();
1245
}
1246

    
1247
/* fsqrt - fsqrt. */
1248
PPC_OP(fsqrt)
1249
{
1250
    do_fsqrt();
1251
    RETURN();
1252
}
1253

    
1254
/* fres - fres. */
1255
PPC_OP(fres)
1256
{
1257
    do_fres();
1258
    RETURN();
1259
}
1260

    
1261
/* frsqrte  - frsqrte. */
1262
PPC_OP(frsqrte)
1263
{
1264
    do_frsqrte();
1265
    RETURN();
1266
}
1267

    
1268
/* fsel - fsel. */
1269
PPC_OP(fsel)
1270
{
1271
    do_fsel();
1272
    RETURN();
1273
}
1274

    
1275
/***                     Floating-Point multiply-and-add                   ***/
1276
/* fmadd - fmadd. */
1277
PPC_OP(fmadd)
1278
{
1279
    FT0 = (FT0 * FT1) + FT2;
1280
    RETURN();
1281
}
1282

    
1283
/* fmsub - fmsub. */
1284
PPC_OP(fmsub)
1285
{
1286
    FT0 = (FT0 * FT1) - FT2;
1287
    RETURN();
1288
}
1289

    
1290
/* fnmadd - fnmadd. - fnmadds - fnmadds. */
1291
PPC_OP(fnmadd)
1292
{
1293
    do_fnmadd();
1294
    RETURN();
1295
}
1296

    
1297
/* fnmsub - fnmsub. */
1298
PPC_OP(fnmsub)
1299
{
1300
    do_fnmsub();
1301
    RETURN();
1302
}
1303

    
1304
/***                     Floating-Point round & convert                    ***/
1305
/* frsp - frsp. */
1306
PPC_OP(frsp)
1307
{
1308
    FT0 = (float)FT0;
1309
    RETURN();
1310
}
1311

    
1312
/* fctiw - fctiw. */
1313
PPC_OP(fctiw)
1314
{
1315
    do_fctiw();
1316
    RETURN();
1317
}
1318

    
1319
/* fctiwz - fctiwz. */
1320
PPC_OP(fctiwz)
1321
{
1322
    do_fctiwz();
1323
    RETURN();
1324
}
1325

    
1326

    
1327
/***                         Floating-Point compare                        ***/
1328
/* fcmpu */
1329
PPC_OP(fcmpu)
1330
{
1331
    do_fcmpu();
1332
    RETURN();
1333
}
1334

    
1335
/* fcmpo */
1336
PPC_OP(fcmpo)
1337
{
1338
    do_fcmpo();
1339
    RETURN();
1340
}
1341

    
1342
/***                         Floating-point move                           ***/
1343
/* fabs */
1344
void do_fabs (void);
1345
PPC_OP(fabs)
1346
{
1347
    do_fabs();
1348
    RETURN();
1349
}
1350

    
1351
/* fnabs */
1352
void do_fnabs (void);
1353
PPC_OP(fnabs)
1354
{
1355
    do_fnabs();
1356
    RETURN();
1357
}
1358

    
1359
/* fneg */
1360
PPC_OP(fneg)
1361
{
1362
    FT0 = -FT0;
1363
    RETURN();
1364
}
1365

    
1366
/* Load and store */
1367
#define MEMSUFFIX _raw
1368
#include "op_mem.h"
1369
#if !defined(CONFIG_USER_ONLY)
1370
#define MEMSUFFIX _user
1371
#include "op_mem.h"
1372

    
1373
#define MEMSUFFIX _kernel
1374
#include "op_mem.h"
1375
#endif
1376

    
1377
/* Special op to check and maybe clear reservation */
1378
PPC_OP(check_reservation)
1379
{
1380
    do_check_reservation();
1381
    RETURN();
1382
}
1383

    
1384
/* Return from interrupt */
1385
PPC_OP(rfi)
1386
{
1387
    regs->nip = regs->spr[SPR_SRR0] & ~0x00000003;
1388
#if 1 // TRY
1389
    T0 = regs->spr[SPR_SRR1] & ~0xFFF00000;
1390
#else
1391
    T0 = regs->spr[SPR_SRR1] & ~0xFFFF0000;
1392
#endif
1393
    do_store_msr(env, T0);
1394
    do_raise_exception(EXCP_RFI);
1395
    RETURN();
1396
}
1397

    
1398
/* Trap word */
1399
PPC_OP(tw)
1400
{
1401
    if ((Ts0 < Ts1 && (PARAM(1) & 0x10)) ||
1402
        (Ts0 > Ts1 && (PARAM(1) & 0x08)) ||
1403
        (Ts0 == Ts1 && (PARAM(1) & 0x04)) ||
1404
        (T0 < T1 && (PARAM(1) & 0x02)) ||
1405
        (T0 > T1 && (PARAM(1) & 0x01)))
1406
        do_raise_exception_err(EXCP_PROGRAM, EXCP_TRAP);
1407
    RETURN();
1408
}
1409

    
1410
PPC_OP(twi)
1411
{
1412
    if ((Ts0 < SPARAM(1) && (PARAM(2) & 0x10)) ||
1413
        (Ts0 > SPARAM(1) && (PARAM(2) & 0x08)) ||
1414
        (Ts0 == SPARAM(1) && (PARAM(2) & 0x04)) ||
1415
        (T0 < (uint32_t)SPARAM(1) && (PARAM(2) & 0x02)) ||
1416
        (T0 > (uint32_t)SPARAM(1) && (PARAM(2) & 0x01)))
1417
        do_raise_exception_err(EXCP_PROGRAM, EXCP_TRAP);
1418
    RETURN();
1419
}
1420

    
1421
/* Instruction cache block invalidate */
1422
PPC_OP(icbi)
1423
{
1424
    do_icbi();
1425
    RETURN();
1426
}
1427

    
1428
/* tlbia */
1429
PPC_OP(tlbia)
1430
{
1431
    do_tlbia();
1432
    RETURN();
1433
}
1434

    
1435
/* tlbie */
1436
PPC_OP(tlbie)
1437
{
1438
    do_tlbie();
1439
    RETURN();
1440
}
1441

    
1442
void op_store_pir (void)
1443
{
1444
    env->spr[SPR_PIR] = T0 & 0x0000000FUL;
1445
    RETURN();
1446
}