Statistics
| Branch: | Revision:

root / target-ppc / op.c @ 1ef59d0a

History | View | Annotate | Download (21 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(queue_exception_err)
212
{
213
    do_queue_exception_err(PARAM(1), PARAM(2));
214
}
215

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

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

    
229
PPC_OP(debug)
230
{
231
    env->nip = PARAM(1);
232
    env->brkstate = 1;
233
#if defined (DEBUG_OP)
234
    dump_state();
235
#endif
236
    do_queue_exception(EXCP_DEBUG);
237
    RETURN();
238
}
239

    
240
/* Segment registers load and store with immediate index */
241
PPC_OP(load_srin)
242
{
243
    T0 = regs->sr[T1 >> 28];
244
    RETURN();
245
}
246

    
247
PPC_OP(store_srin)
248
{
249
#if defined (DEBUG_OP)
250
    dump_store_sr(T1 >> 28);
251
#endif
252
    regs->sr[T1 >> 28] = T0;
253
    RETURN();
254
}
255

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

    
262
PPC_OP(store_sdr1)
263
{
264
    regs->sdr1 = T0;
265
    RETURN();
266
}
267

    
268
PPC_OP(exit_tb)
269
{
270
    EXIT_TB();
271
}
272

    
273
/* Load/store special registers */
274
PPC_OP(load_cr)
275
{
276
    do_load_cr();
277
    RETURN();
278
}
279

    
280
PPC_OP(store_cr)
281
{
282
    do_store_cr(PARAM(1));
283
    RETURN();
284
}
285

    
286
PPC_OP(load_xer_cr)
287
{
288
    T0 = (xer_so << 3) | (xer_ov << 2) | (xer_ca << 1);
289
    RETURN();
290
}
291

    
292
PPC_OP(clear_xer_cr)
293
{
294
    xer_so = 0;
295
    xer_ov = 0;
296
    xer_ca = 0;
297
    RETURN();
298
}
299

    
300
PPC_OP(load_xer_bc)
301
{
302
    T1 = xer_bc;
303
    RETURN();
304
}
305

    
306
PPC_OP(load_xer)
307
{
308
    do_load_xer();
309
    RETURN();
310
}
311

    
312
PPC_OP(store_xer)
313
{
314
    do_store_xer();
315
    RETURN();
316
}
317

    
318
PPC_OP(load_msr)
319
{
320
    do_load_msr();
321
    RETURN();
322
}
323

    
324
PPC_OP(store_msr)
325
{
326
    do_store_msr();
327
    RETURN();
328
}
329

    
330
/* SPR */
331
PPC_OP(load_spr)
332
{
333
    T0 = regs->spr[PARAM(1)];
334
    RETURN();
335
}
336

    
337
PPC_OP(store_spr)
338
{
339
    regs->spr[PARAM(1)] = T0;
340
    RETURN();
341
}
342

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

    
349
PPC_OP(store_lr)
350
{
351
    regs->lr = T0;
352
    RETURN();
353
}
354

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

    
361
PPC_OP(store_ctr)
362
{
363
    regs->ctr = T0;
364
    RETURN();
365
}
366

    
367
/* Update time base */
368
PPC_OP(update_tb)
369
{
370
    T0 = regs->tb[0];
371
    T1 = T0;
372
    T0 += PARAM(1);
373
#if defined (DEBUG_OP)
374
    dump_update_tb(PARAM(1));
375
#endif
376
    if (T0 < T1) {
377
        T1 = regs->tb[1] + 1;
378
        regs->tb[1] = T1;
379
    }
380
    regs->tb[0] = T0;
381
    RETURN();
382
}
383

    
384
PPC_OP(load_tb)
385
{
386
    T0 = regs->tb[PARAM(1)];
387
    RETURN();
388
}
389

    
390
PPC_OP(store_tb)
391
{
392
    regs->tb[PARAM(1)] = T0;
393
#if defined (DEBUG_OP)
394
    dump_store_tb(PARAM(1));
395
#endif
396
    RETURN();
397
}
398

    
399
/* Update decrementer */
400
PPC_OP(update_decr)
401
{
402
    T0 = regs->decr;
403
    T1 = T0;
404
    T0 -= PARAM(1);
405
    regs->decr = T0;
406
    if (PARAM(1) > T1) {
407
        do_queue_exception(EXCP_DECR);
408
    }
409
    RETURN();
410
}
411

    
412
PPC_OP(store_decr)
413
{
414
    T1 = regs->decr;
415
    regs->decr = T0;
416
    if (Ts0 < 0 && Ts1 > 0) {
417
        do_queue_exception(EXCP_DECR);
418
    }
419
    RETURN();
420
}
421

    
422
PPC_OP(load_ibat)
423
{
424
    T0 = regs->IBAT[PARAM(1)][PARAM(2)];
425
}
426

    
427
PPC_OP(store_ibat)
428
{
429
#if defined (DEBUG_OP)
430
    dump_store_ibat(PARAM(1), PARAM(2));
431
#endif
432
    regs->IBAT[PARAM(1)][PARAM(2)] = T0;
433
}
434

    
435
PPC_OP(load_dbat)
436
{
437
    T0 = regs->DBAT[PARAM(1)][PARAM(2)];
438
}
439

    
440
PPC_OP(store_dbat)
441
{
442
#if defined (DEBUG_OP)
443
    dump_store_dbat(PARAM(1), PARAM(2));
444
#endif
445
    regs->DBAT[PARAM(1)][PARAM(2)] = T0;
446
}
447

    
448
/* FPSCR */
449
PPC_OP(load_fpscr)
450
{
451
    do_load_fpscr();
452
    RETURN();
453
}
454

    
455
PPC_OP(store_fpscr)
456
{
457
    do_store_fpscr(PARAM(1));
458
    RETURN();
459
}
460

    
461
PPC_OP(reset_scrfx)
462
{
463
    regs->fpscr[7] &= ~0x8;
464
    RETURN();
465
}
466

    
467
/* crf operations */
468
PPC_OP(getbit_T0)
469
{
470
    T0 = (T0 >> PARAM(1)) & 1;
471
    RETURN();
472
}
473

    
474
PPC_OP(getbit_T1)
475
{
476
    T1 = (T1 >> PARAM(1)) & 1;
477
    RETURN();
478
}
479

    
480
PPC_OP(setcrfbit)
481
{
482
    T1 = (T1 & PARAM(1)) | (T0 << PARAM(2)); 
483
    RETURN();
484
}
485

    
486
/* Branch */
487
#define EIP regs->nip
488

    
489
PPC_OP(setlr)
490
{
491
    regs->lr = PARAM1;
492
}
493

    
494
PPC_OP(b)
495
{
496
    JUMP_TB(b1, PARAM1, 0, PARAM2);
497
}
498

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

    
504
PPC_OP(btest) 
505
{
506
    if (T0) {
507
        JUMP_TB(btest, PARAM1, 0, PARAM2);
508
    } else {
509
        JUMP_TB(btest, PARAM1, 1, PARAM3);
510
    }
511
    RETURN();
512
}
513

    
514
PPC_OP(btest_T1) 
515
{
516
    if (T0) {
517
        regs->nip = T1 & ~3;
518
    } else {
519
        regs->nip = PARAM1;
520
    }
521
    RETURN();
522
}
523

    
524
PPC_OP(movl_T1_ctr)
525
{
526
    T1 = regs->ctr;
527
}
528

    
529
PPC_OP(movl_T1_lr)
530
{
531
    T1 = regs->lr;
532
}
533

    
534
/* tests with result in T0 */
535

    
536
PPC_OP(test_ctr)
537
{
538
    T0 = regs->ctr;
539
}
540

    
541
PPC_OP(test_ctr_true)
542
{
543
    T0 = (regs->ctr != 0 && (T0 & PARAM(1)) != 0);
544
}
545

    
546
PPC_OP(test_ctr_false)
547
{
548
    T0 = (regs->ctr != 0 && (T0 & PARAM(1)) == 0);
549
}
550

    
551
PPC_OP(test_ctrz)
552
{
553
    T0 = (regs->ctr == 0);
554
}
555

    
556
PPC_OP(test_ctrz_true)
557
{
558
    T0 = (regs->ctr == 0 && (T0 & PARAM(1)) != 0);
559
}
560

    
561
PPC_OP(test_ctrz_false)
562
{
563
    T0 = (regs->ctr == 0 && (T0 & PARAM(1)) == 0);
564
}
565

    
566
PPC_OP(test_true)
567
{
568
    T0 = (T0 & PARAM(1));
569
}
570

    
571
PPC_OP(test_false)
572
{
573
    T0 = ((T0 & PARAM(1)) == 0);
574
}
575

    
576
/* CTR maintenance */
577
PPC_OP(dec_ctr)
578
{
579
    regs->ctr--;
580
    RETURN();
581
}
582

    
583
/***                           Integer arithmetic                          ***/
584
/* add */
585
PPC_OP(add)
586
{
587
    T0 += T1;
588
    RETURN();
589
}
590

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

    
604
/* add carrying */
605
PPC_OP(addc)
606
{
607
    T2 = T0;
608
    T0 += T1;
609
    if (T0 < T2) {
610
        xer_ca = 1;
611
    } else {
612
        xer_ca = 0;
613
    }
614
    RETURN();
615
}
616

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

    
635
/* add extended */
636
/* candidate for helper (too long) */
637
PPC_OP(adde)
638
{
639
    T2 = T0;
640
    T0 += T1 + xer_ca;
641
    if (T0 < T2 || (xer_ca == 1 && T0 == T2)) {
642
        xer_ca = 1;
643
    } else {
644
        xer_ca = 0;
645
    }
646
    RETURN();
647
}
648

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

    
667
/* add immediate */
668
PPC_OP(addi)
669
{
670
    T0 += PARAM(1);
671
    RETURN();
672
}
673

    
674
/* add immediate carrying */
675
PPC_OP(addic)
676
{
677
    T1 = T0;
678
    T0 += PARAM(1);
679
    if (T0 < T1) {
680
        xer_ca = 1;
681
    } else {
682
        xer_ca = 0;
683
    }
684
    RETURN();
685
}
686

    
687
/* add to minus one extended */
688
PPC_OP(addme)
689
{
690
    T1 = T0;
691
    T0 += xer_ca + (-1);
692
    if (T1 != 0)
693
        xer_ca = 1;
694
    RETURN();
695
}
696

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

    
712
/* add to zero extended */
713
PPC_OP(addze)
714
{
715
    T1 = T0;
716
    T0 += xer_ca;
717
    if (T0 < T1) {
718
        xer_ca = 1;
719
    } else {
720
        xer_ca = 0;
721
    }
722
    RETURN();
723
}
724

    
725
PPC_OP(addzeo)
726
{
727
    T1 = T0;
728
    T0 += xer_ca;
729
    if ((T1 ^ (-1)) & (T1 ^ T0) & (1 << 31)) {
730
        xer_so = 1;
731
        xer_ov = 1;
732
    } else {
733
        xer_ov = 0;
734
    }
735
    if (T0 < T1) {
736
        xer_ca = 1;
737
    } else {
738
        xer_ca = 0;
739
    }
740
    RETURN();
741
}
742

    
743
/* divide word */
744
/* candidate for helper (too long) */
745
PPC_OP(divw)
746
{
747
    if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
748
        Ts0 = (-1) * (T0 >> 31);
749
    } else {
750
        Ts0 /= Ts1;
751
    }
752
    RETURN();
753
}
754

    
755
PPC_OP(divwo)
756
{
757
    if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
758
        xer_so = 1;
759
        xer_ov = 1;
760
        T0 = (-1) * (T0 >> 31);
761
    } else {
762
        xer_ov = 0;
763
        Ts0 /= Ts1;
764
    }
765
    RETURN();
766
}
767

    
768
/* divide word unsigned */
769
PPC_OP(divwu)
770
{
771
    if (T1 == 0) {
772
        T0 = 0;
773
    } else {
774
        T0 /= T1;
775
    }
776
    RETURN();
777
}
778

    
779
PPC_OP(divwuo)
780
{
781
    if (T1 == 0) {
782
        xer_so = 1;
783
        xer_ov = 1;
784
        T0 = 0;
785
    } else {
786
        xer_ov = 0;
787
        T0 /= T1;
788
    }
789
    RETURN();
790
}
791

    
792
/* multiply high word */
793
PPC_OP(mulhw)
794
{
795
    Ts0 = ((int64_t)Ts0 * (int64_t)Ts1) >> 32;
796
    RETURN();
797
}
798

    
799
/* multiply high word unsigned */
800
PPC_OP(mulhwu)
801
{
802
    T0 = ((uint64_t)T0 * (uint64_t)T1) >> 32;
803
    RETURN();
804
}
805

    
806
/* multiply low immediate */
807
PPC_OP(mulli)
808
{
809
    Ts0 *= SPARAM(1);
810
    RETURN();
811
}
812

    
813
/* multiply low word */
814
PPC_OP(mullw)
815
{
816
    T0 *= T1;
817
    RETURN();
818
}
819

    
820
PPC_OP(mullwo)
821
{
822
    int64_t res = (int64_t)Ts0 * (int64_t)Ts1;
823

    
824
    if ((int32_t)res != res) {
825
        xer_ov = 1;
826
        xer_so = 1;
827
    } else {
828
        xer_ov = 0;
829
    }
830
    Ts0 = res;
831
    RETURN();
832
}
833

    
834
/* negate */
835
PPC_OP(neg)
836
{
837
    if (T0 != 0x80000000) {
838
        Ts0 = -Ts0;
839
    }
840
    RETURN();
841
}
842

    
843
PPC_OP(nego)
844
{
845
    if (T0 == 0x80000000) {
846
        xer_ov = 1;
847
        xer_so = 1;
848
    } else {
849
        xer_ov = 0;
850
        Ts0 = -Ts0;
851
    }
852
    RETURN();
853
}
854

    
855
/* substract from */
856
PPC_OP(subf)
857
{
858
    T0 = T1 - T0;
859
    RETURN();
860
}
861

    
862
PPC_OP(subfo)
863
{
864
    T2 = T0;
865
    T0 = T1 - T0;
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 carrying */
876
PPC_OP(subfc)
877
{
878
    T0 = T1 - T0;
879
    if (T0 <= T1) {
880
        xer_ca = 1;
881
    } else {
882
        xer_ca = 0;
883
    }
884
    RETURN();
885
}
886

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

    
905
/* substract from extended */
906
/* candidate for helper (too long) */
907
PPC_OP(subfe)
908
{
909
    T0 = T1 + ~T0 + xer_ca;
910
    if (T0 < T1 || (xer_ca == 1 && T0 == T1)) {
911
        xer_ca = 1;
912
    } else {
913
        xer_ca = 0;
914
    }
915
    RETURN();
916
}
917

    
918
PPC_OP(subfeo)
919
{
920
    T2 = T0;
921
    T0 = T1 + ~T0 + xer_ca;
922
    if ((~T2 ^ T1 ^ (-1)) & (~T2 ^ T0) & (1 << 31)) {
923
        xer_so = 1;
924
        xer_ov = 1;
925
    } else {
926
        xer_ov = 0;
927
    }
928
    if (T0 < T1 || (xer_ca == 1 && T0 == T1)) {
929
        xer_ca = 1;
930
    } else {
931
        xer_ca = 0;
932
    }
933
    RETURN();
934
}
935

    
936
/* substract from immediate carrying */
937
PPC_OP(subfic)
938
{
939
    T0 = PARAM(1) + ~T0 + 1;
940
    if (T0 <= PARAM(1)) {
941
        xer_ca = 1;
942
    } else {
943
        xer_ca = 0;
944
    }
945
    RETURN();
946
}
947

    
948
/* substract from minus one extended */
949
PPC_OP(subfme)
950
{
951
    T0 = ~T0 + xer_ca - 1;
952

    
953
    if (T0 != -1)
954
        xer_ca = 1;
955
    RETURN();
956
}
957

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

    
973
/* substract from zero extended */
974
PPC_OP(subfze)
975
{
976
    T1 = ~T0;
977
    T0 = T1 + xer_ca;
978
    if (T0 < T1) {
979
        xer_ca = 1;
980
    } else {
981
        xer_ca = 0;
982
    }
983
    RETURN();
984
}
985

    
986
PPC_OP(subfzeo)
987
{
988
    T1 = T0;
989
    T0 = ~T0 + xer_ca;
990
    if ((~T1 ^ (-1)) & ((~T1) ^ T0) & (1 << 31)) {
991
        xer_ov = 1;
992
        xer_so = 1;
993
    } else {
994
        xer_ov = 0;
995
    }
996
    if (T0 < ~T1) {
997
        xer_ca = 1;
998
    } else {
999
        xer_ca = 0;
1000
    }
1001
    RETURN();
1002
}
1003

    
1004
/***                           Integer comparison                          ***/
1005
/* compare */
1006
PPC_OP(cmp)
1007
{
1008
    if (Ts0 < Ts1) {
1009
        T0 = 0x08;
1010
    } else if (Ts0 > Ts1) {
1011
        T0 = 0x04;
1012
    } else {
1013
        T0 = 0x02;
1014
    }
1015
    RETURN();
1016
}
1017

    
1018
/* compare immediate */
1019
PPC_OP(cmpi)
1020
{
1021
    if (Ts0 < SPARAM(1)) {
1022
        T0 = 0x08;
1023
    } else if (Ts0 > SPARAM(1)) {
1024
        T0 = 0x04;
1025
    } else {
1026
        T0 = 0x02;
1027
    }
1028
    RETURN();
1029
}
1030

    
1031
/* compare logical */
1032
PPC_OP(cmpl)
1033
{
1034
    if (T0 < T1) {
1035
        T0 = 0x08;
1036
    } else if (T0 > T1) {
1037
        T0 = 0x04;
1038
    } else {
1039
        T0 = 0x02;
1040
    }
1041
    RETURN();
1042
}
1043

    
1044
/* compare logical immediate */
1045
PPC_OP(cmpli)
1046
{
1047
    if (T0 < PARAM(1)) {
1048
        T0 = 0x08;
1049
    } else if (T0 > PARAM(1)) {
1050
        T0 = 0x04;
1051
    } else {
1052
        T0 = 0x02;
1053
    }
1054
    RETURN();
1055
}
1056

    
1057
/***                            Integer logical                            ***/
1058
/* and */
1059
PPC_OP(and)
1060
{
1061
    T0 &= T1;
1062
    RETURN();
1063
}
1064

    
1065
/* andc */
1066
PPC_OP(andc)
1067
{
1068
    T0 &= ~T1;
1069
    RETURN();
1070
}
1071

    
1072
/* andi. */
1073
PPC_OP(andi_)
1074
{
1075
    T0 &= PARAM(1);
1076
    RETURN();
1077
}
1078

    
1079
/* count leading zero */
1080
PPC_OP(cntlzw)
1081
{
1082
    T1 = T0;
1083
    for (T0 = 32; T1 > 0; T0--)
1084
        T1 = T1 >> 1;
1085
    RETURN();
1086
}
1087

    
1088
/* eqv */
1089
PPC_OP(eqv)
1090
{
1091
    T0 = ~(T0 ^ T1);
1092
    RETURN();
1093
}
1094

    
1095
/* extend sign byte */
1096
PPC_OP(extsb)
1097
{
1098
    Ts0 = s_ext8(Ts0);
1099
    RETURN();
1100
}
1101

    
1102
/* extend sign half word */
1103
PPC_OP(extsh)
1104
{
1105
    Ts0 = s_ext16(Ts0);
1106
    RETURN();
1107
}
1108

    
1109
/* nand */
1110
PPC_OP(nand)
1111
{
1112
    T0 = ~(T0 & T1);
1113
    RETURN();
1114
}
1115

    
1116
/* nor */
1117
PPC_OP(nor)
1118
{
1119
    T0 = ~(T0 | T1);
1120
    RETURN();
1121
}
1122

    
1123
/* or */
1124
PPC_OP(or)
1125
{
1126
    T0 |= T1;
1127
    RETURN();
1128
}
1129

    
1130
/* orc */
1131
PPC_OP(orc)
1132
{
1133
    T0 |= ~T1;
1134
    RETURN();
1135
}
1136

    
1137
/* ori */
1138
PPC_OP(ori)
1139
{
1140
    T0 |= PARAM(1);
1141
    RETURN();
1142
}
1143

    
1144
/* xor */
1145
PPC_OP(xor)
1146
{
1147
    T0 ^= T1;
1148
    RETURN();
1149
}
1150

    
1151
/* xori */
1152
PPC_OP(xori)
1153
{
1154
    T0 ^= PARAM(1);
1155
    RETURN();
1156
}
1157

    
1158
/***                             Integer rotate                            ***/
1159
/* rotate left word immediate then mask insert */
1160
PPC_OP(rlwimi)
1161
{
1162
    T0 = (rotl(T0, PARAM(1)) & PARAM(2)) | (T1 & PARAM(3));
1163
    RETURN();
1164
}
1165

    
1166
/* rotate left immediate then and with mask insert */
1167
PPC_OP(rotlwi)
1168
{
1169
    T0 = rotl(T0, PARAM(1));
1170
    RETURN();
1171
}
1172

    
1173
PPC_OP(slwi)
1174
{
1175
    T0 = T0 << PARAM(1);
1176
    RETURN();
1177
}
1178

    
1179
PPC_OP(srwi)
1180
{
1181
    T0 = T0 >> PARAM(1);
1182
    RETURN();
1183
}
1184

    
1185
/* rotate left word then and with mask insert */
1186
PPC_OP(rlwinm)
1187
{
1188
    T0 = rotl(T0, PARAM(1)) & PARAM(2);
1189
    RETURN();
1190
}
1191

    
1192
PPC_OP(rotl)
1193
{
1194
    T0 = rotl(T0, T1);
1195
    RETURN();
1196
}
1197

    
1198
PPC_OP(rlwnm)
1199
{
1200
    T0 = rotl(T0, T1) & PARAM(1);
1201
    RETURN();
1202
}
1203

    
1204
/***                             Integer shift                             ***/
1205
/* shift left word */
1206
PPC_OP(slw)
1207
{
1208
    if (T1 & 0x20) {
1209
        T0 = 0;
1210
    } else {
1211
        T0 = T0 << T1;
1212
    }
1213
    RETURN();
1214
}
1215

    
1216
/* shift right algebraic word */
1217
PPC_OP(sraw)
1218
{
1219
    do_sraw();
1220
    RETURN();
1221
}
1222

    
1223
/* shift right algebraic word immediate */
1224
PPC_OP(srawi)
1225
{
1226
    Ts1 = Ts0;
1227
    Ts0 = Ts0 >> PARAM(1);
1228
    if (Ts1 < 0 && (Ts1 & PARAM(2)) != 0) {
1229
        xer_ca = 1;
1230
    } else {
1231
        xer_ca = 0;
1232
    }
1233
    RETURN();
1234
}
1235

    
1236
/* shift right word */
1237
PPC_OP(srw)
1238
{
1239
    if (T1 & 0x20) {
1240
        T0 = 0;
1241
    } else {
1242
        T0 = T0 >> T1;
1243
    }
1244
    RETURN();
1245
}
1246

    
1247
/***                       Floating-Point arithmetic                       ***/
1248
/* fadd - fadd. */
1249
PPC_OP(fadd)
1250
{
1251
    FT0 += FT1;
1252
    RETURN();
1253
}
1254

    
1255
/* fadds - fadds. */
1256
PPC_OP(fadds)
1257
{
1258
    FTS0 += FTS1;
1259
    RETURN();
1260
}
1261

    
1262
/* fsub - fsub. */
1263
PPC_OP(fsub)
1264
{
1265
    FT0 -= FT1;
1266
    RETURN();
1267
}
1268

    
1269
/* fsubs - fsubs. */
1270
PPC_OP(fsubs)
1271
{
1272
    FTS0 -= FTS1;
1273
    RETURN();
1274
}
1275

    
1276
/* fmul - fmul. */
1277
PPC_OP(fmul)
1278
{
1279
    FT0 *= FT1;
1280
    RETURN();
1281
}
1282

    
1283
/* fmuls - fmuls. */
1284
PPC_OP(fmuls)
1285
{
1286
    FTS0 *= FTS1;
1287
    RETURN();
1288
}
1289

    
1290
/* fdiv - fdiv. */
1291
PPC_OP(fdiv)
1292
{
1293
    FT0 /= FT1;
1294
    RETURN();
1295
}
1296

    
1297
/* fdivs - fdivs. */
1298
PPC_OP(fdivs)
1299
{
1300
    FTS0 /= FTS1;
1301
    RETURN();
1302
}
1303

    
1304
/* fsqrt - fsqrt. */
1305
PPC_OP(fsqrt)
1306
{
1307
    do_fsqrt();
1308
    RETURN();
1309
}
1310

    
1311
/* fsqrts - fsqrts. */
1312
PPC_OP(fsqrts)
1313
{
1314
    do_fsqrts();
1315
    RETURN();
1316
}
1317

    
1318
/* fres - fres. */
1319
PPC_OP(fres)
1320
{
1321
    do_fres();
1322
    RETURN();
1323
}
1324

    
1325
/* frsqrte  - frsqrte. */
1326
PPC_OP(frsqrte)
1327
{
1328
    do_fsqrte();
1329
    RETURN();
1330
}
1331

    
1332
/* fsel - fsel. */
1333
PPC_OP(fsel)
1334
{
1335
    do_fsel();
1336
    RETURN();
1337
}
1338

    
1339
/***                     Floating-Point multiply-and-add                   ***/
1340
/* fmadd - fmadd. */
1341
PPC_OP(fmadd)
1342
{
1343
    FT0 = (FT0 * FT1) + FT2;
1344
    RETURN();
1345
}
1346

    
1347
/* fmadds - fmadds. */
1348
PPC_OP(fmadds)
1349
{
1350
    FTS0 = (FTS0 * FTS1) + FTS2;
1351
    RETURN();
1352
}
1353

    
1354
/* fmsub - fmsub. */
1355
PPC_OP(fmsub)
1356
{
1357
    FT0 = (FT0 * FT1) - FT2;
1358
    RETURN();
1359
}
1360

    
1361
/* fmsubs - fmsubs. */
1362
PPC_OP(fmsubs)
1363
{
1364
    FTS0 = (FTS0 * FTS1) - FTS2;
1365
    RETURN();
1366
}
1367

    
1368
/* fnmadd - fnmadd. - fnmadds - fnmadds. */
1369
PPC_OP(fnmadd)
1370
{
1371
    FT0 *= FT1;
1372
    FT0 += FT2;
1373
    FT0 = -FT0;
1374
    RETURN();
1375
}
1376

    
1377
/* fnmadds - fnmadds. */
1378
PPC_OP(fnmadds)
1379
{
1380
    do_fnmadds();
1381
    RETURN();
1382
}
1383

    
1384
/* fnmsub - fnmsub. */
1385
PPC_OP(fnmsub)
1386
{
1387
    FT0 *= FT1;
1388
    FT0 -= FT2;
1389
    FT0 = -FT0;
1390
    RETURN();
1391
}
1392

    
1393
/* fnmsubs - fnmsubs. */
1394
PPC_OP(fnmsubs)
1395
{
1396
    do_fnmsubs();
1397
    RETURN();
1398
}
1399

    
1400
/***                     Floating-Point round & convert                    ***/
1401
/* frsp - frsp. */
1402
PPC_OP(frsp)
1403
{
1404
    FT0 = FTS0;
1405
    RETURN();
1406
}
1407

    
1408
/* fctiw - fctiw. */
1409
PPC_OP(fctiw)
1410
{
1411
    do_fctiw();
1412
    RETURN();
1413
}
1414

    
1415
/* fctiwz - fctiwz. */
1416
PPC_OP(fctiwz)
1417
{
1418
    do_fctiwz();
1419
    RETURN();
1420
}
1421

    
1422

    
1423
/***                         Floating-Point compare                        ***/
1424
/* fcmpu */
1425
PPC_OP(fcmpu)
1426
{
1427
    do_fcmpu();
1428
    RETURN();
1429
}
1430

    
1431
/* fcmpo */
1432
PPC_OP(fcmpo)
1433
{
1434
    do_fcmpo();
1435
    RETURN();
1436
}
1437

    
1438
/***                         Floating-point move                           ***/
1439
/* fabs */
1440
PPC_OP(fabs)
1441
{
1442
    do_fabs();
1443
    RETURN();
1444
}
1445

    
1446
/* fnabs */
1447
PPC_OP(fnabs)
1448
{
1449
    do_fnabs();
1450
    RETURN();
1451
}
1452

    
1453
/* fneg */
1454
PPC_OP(fneg)
1455
{
1456
    FT0 = -FT0;
1457
    RETURN();
1458
}
1459

    
1460
/* Load and store */
1461
#define MEMSUFFIX _raw
1462
#include "op_mem.h"
1463
#if !defined(CONFIG_USER_ONLY)
1464
#define MEMSUFFIX _user
1465
#include "op_mem.h"
1466

    
1467
#define MEMSUFFIX _kernel
1468
#include "op_mem.h"
1469
#endif
1470

    
1471
/* Return from interrupt */
1472
PPC_OP(rfi)
1473
{
1474
    T0 = regs->spr[SRR1] & ~0xFFFF0000;
1475
    do_store_msr();
1476
    do_tlbia();
1477
#if defined (DEBUG_OP)
1478
    dump_rfi();
1479
#endif
1480
    regs->nip = regs->spr[SRR0] & ~0x00000003;
1481
    do_queue_exception(EXCP_RFI);
1482
    if (env->exceptions != 0) {
1483
        do_check_exception_state();
1484
    }
1485
    RETURN();
1486
}
1487

    
1488
/* Trap word */
1489
PPC_OP(tw)
1490
{
1491
    if ((Ts0 < Ts1 && (PARAM(1) & 0x10)) ||
1492
        (Ts0 > Ts1 && (PARAM(1) & 0x08)) ||
1493
        (Ts0 == Ts1 && (PARAM(1) & 0x04)) ||
1494
        (T0 < T1 && (PARAM(1) & 0x02)) ||
1495
        (T0 > T1 && (PARAM(1) & 0x01)))
1496
        do_queue_exception_err(EXCP_PROGRAM, EXCP_TRAP);
1497
    RETURN();
1498
}
1499

    
1500
PPC_OP(twi)
1501
{
1502
    if ((Ts0 < SPARAM(1) && (PARAM(2) & 0x10)) ||
1503
        (Ts0 > SPARAM(1) && (PARAM(2) & 0x08)) ||
1504
        (Ts0 == SPARAM(1) && (PARAM(2) & 0x04)) ||
1505
        (T0 < (uint32_t)SPARAM(1) && (PARAM(2) & 0x02)) ||
1506
        (T0 > (uint32_t)SPARAM(1) && (PARAM(2) & 0x01)))
1507
        do_queue_exception_err(EXCP_PROGRAM, EXCP_TRAP);
1508
    RETURN();
1509
}
1510

    
1511
/* Instruction cache block invalidate */
1512
PPC_OP(icbi)
1513
{
1514
    do_icbi();
1515
    RETURN();
1516
}
1517

    
1518
/* tlbia */
1519
PPC_OP(tlbia)
1520
{
1521
    do_tlbia();
1522
    RETURN();
1523
}
1524

    
1525
/* tlbie */
1526
PPC_OP(tlbie)
1527
{
1528
    do_tlbie();
1529
    RETURN();
1530
}