Statistics
| Branch: | Revision:

root / target-ppc / op.c @ b88e4a9a

History | View | Annotate | Download (20.8 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
#include "config.h"
22
#include "exec.h"
23

    
24
//#define DEBUG_OP
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
/* Segment registers load and store with immediate index */
230
PPC_OP(load_srin)
231
{
232
    T0 = regs->sr[T1 >> 28];
233
    RETURN();
234
}
235

    
236
PPC_OP(store_srin)
237
{
238
#if defined (DEBUG_OP)
239
    dump_store_sr(T1 >> 28);
240
#endif
241
    regs->sr[T1 >> 28] = T0;
242
    RETURN();
243
}
244

    
245
PPC_OP(load_sdr1)
246
{
247
    T0 = regs->sdr1;
248
    RETURN();
249
}
250

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

    
257
PPC_OP(exit_tb)
258
{
259
    EXIT_TB();
260
}
261

    
262
/* Load/store special registers */
263
PPC_OP(load_cr)
264
{
265
    do_load_cr();
266
    RETURN();
267
}
268

    
269
PPC_OP(store_cr)
270
{
271
    do_store_cr(PARAM(1));
272
    RETURN();
273
}
274

    
275
PPC_OP(load_xer_cr)
276
{
277
    T0 = (xer_so << 3) | (xer_ov << 2) | (xer_ca << 1);
278
    RETURN();
279
}
280

    
281
PPC_OP(clear_xer_cr)
282
{
283
    xer_so = 0;
284
    xer_ov = 0;
285
    xer_ca = 0;
286
    RETURN();
287
}
288

    
289
PPC_OP(load_xer_bc)
290
{
291
    T1 = xer_bc;
292
    RETURN();
293
}
294

    
295
PPC_OP(load_xer)
296
{
297
    do_load_xer();
298
    RETURN();
299
}
300

    
301
PPC_OP(store_xer)
302
{
303
    do_store_xer();
304
    RETURN();
305
}
306

    
307
PPC_OP(load_msr)
308
{
309
    do_load_msr();
310
    RETURN();
311
}
312

    
313
PPC_OP(store_msr)
314
{
315
    do_store_msr();
316
    RETURN();
317
}
318

    
319
/* SPR */
320
PPC_OP(load_spr)
321
{
322
    T0 = regs->spr[PARAM(1)];
323
    RETURN();
324
}
325

    
326
PPC_OP(store_spr)
327
{
328
    regs->spr[PARAM(1)] = T0;
329
    RETURN();
330
}
331

    
332
PPC_OP(load_lr)
333
{
334
    T0 = regs->lr;
335
    RETURN();
336
}
337

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

    
344
PPC_OP(load_ctr)
345
{
346
    T0 = regs->ctr;
347
    RETURN();
348
}
349

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

    
356
/* Update time base */
357
PPC_OP(update_tb)
358
{
359
    T0 = regs->tb[0];
360
    T1 = T0;
361
    T0 += PARAM(1);
362
#if defined (DEBUG_OP)
363
    dump_update_tb(PARAM(1));
364
#endif
365
    if (T0 < T1) {
366
        T1 = regs->tb[1] + 1;
367
        regs->tb[1] = T1;
368
    }
369
    regs->tb[0] = T0;
370
    RETURN();
371
}
372

    
373
PPC_OP(load_tb)
374
{
375
    T0 = regs->tb[PARAM(1)];
376
    RETURN();
377
}
378

    
379
PPC_OP(store_tb)
380
{
381
    regs->tb[PARAM(1)] = T0;
382
#if defined (DEBUG_OP)
383
    dump_store_tb(PARAM(1));
384
#endif
385
    RETURN();
386
}
387

    
388
/* Update decrementer */
389
PPC_OP(update_decr)
390
{
391
    T0 = regs->decr;
392
    T1 = T0;
393
    T0 -= PARAM(1);
394
    regs->decr = T0;
395
    if (PARAM(1) > T1) {
396
        do_queue_exception(EXCP_DECR);
397
    }
398
    RETURN();
399
}
400

    
401
PPC_OP(store_decr)
402
{
403
    T1 = regs->decr;
404
    regs->decr = T0;
405
    if (Ts0 < 0 && Ts1 > 0) {
406
        do_queue_exception(EXCP_DECR);
407
    }
408
    RETURN();
409
}
410

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

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

    
424
PPC_OP(load_dbat)
425
{
426
    T0 = regs->DBAT[PARAM(1)][PARAM(2)];
427
}
428

    
429
PPC_OP(store_dbat)
430
{
431
#if defined (DEBUG_OP)
432
    dump_store_dbat(PARAM(1), PARAM(2));
433
#endif
434
    regs->DBAT[PARAM(1)][PARAM(2)] = T0;
435
}
436

    
437
/* FPSCR */
438
PPC_OP(load_fpscr)
439
{
440
    do_load_fpscr();
441
    RETURN();
442
}
443

    
444
PPC_OP(store_fpscr)
445
{
446
    do_store_fpscr(PARAM(1));
447
    RETURN();
448
}
449

    
450
PPC_OP(reset_scrfx)
451
{
452
    regs->fpscr[7] &= ~0x8;
453
    RETURN();
454
}
455

    
456
/* crf operations */
457
PPC_OP(getbit_T0)
458
{
459
    T0 = (T0 >> PARAM(1)) & 1;
460
    RETURN();
461
}
462

    
463
PPC_OP(getbit_T1)
464
{
465
    T1 = (T1 >> PARAM(1)) & 1;
466
    RETURN();
467
}
468

    
469
PPC_OP(setcrfbit)
470
{
471
    T1 = (T1 & PARAM(1)) | (T0 << PARAM(2)); 
472
    RETURN();
473
}
474

    
475
/* Branch */
476
#define EIP regs->nip
477

    
478
PPC_OP(setlr)
479
{
480
    regs->lr = PARAM1;
481
}
482

    
483
PPC_OP(b)
484
{
485
    JUMP_TB(b1, PARAM1, 0, PARAM2);
486
}
487

    
488
PPC_OP(b_T1)
489
{
490
    regs->nip = T1;
491
}
492

    
493
PPC_OP(btest) 
494
{
495
    if (T0) {
496
        JUMP_TB(btest, PARAM1, 0, PARAM2);
497
    } else {
498
        JUMP_TB(btest, PARAM1, 1, PARAM3);
499
    }
500
    RETURN();
501
}
502

    
503
PPC_OP(btest_T1) 
504
{
505
    if (T0) {
506
        regs->nip = T1 & ~3;
507
    } else {
508
        regs->nip = PARAM1;
509
    }
510
    RETURN();
511
}
512

    
513
PPC_OP(movl_T1_ctr)
514
{
515
    T1 = regs->ctr;
516
}
517

    
518
PPC_OP(movl_T1_lr)
519
{
520
    T1 = regs->lr;
521
}
522

    
523
/* tests with result in T0 */
524

    
525
PPC_OP(test_ctr)
526
{
527
    T0 = regs->ctr;
528
}
529

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

    
535
PPC_OP(test_ctr_false)
536
{
537
    T0 = (regs->ctr != 0 && (T0 & PARAM(1)) == 0);
538
}
539

    
540
PPC_OP(test_ctrz)
541
{
542
    T0 = (regs->ctr == 0);
543
}
544

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

    
550
PPC_OP(test_ctrz_false)
551
{
552
    T0 = (regs->ctr == 0 && (T0 & PARAM(1)) == 0);
553
}
554

    
555
PPC_OP(test_true)
556
{
557
    T0 = (T0 & PARAM(1));
558
}
559

    
560
PPC_OP(test_false)
561
{
562
    T0 = ((T0 & PARAM(1)) == 0);
563
}
564

    
565
/* CTR maintenance */
566
PPC_OP(dec_ctr)
567
{
568
    regs->ctr--;
569
    RETURN();
570
}
571

    
572
/***                           Integer arithmetic                          ***/
573
/* add */
574
PPC_OP(add)
575
{
576
    T0 += T1;
577
    RETURN();
578
}
579

    
580
PPC_OP(addo)
581
{
582
    T2 = T0;
583
    T0 += T1;
584
    if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
585
        xer_so = 1;
586
        xer_ov = 1;
587
    } else {
588
        xer_ov = 0;
589
    }
590
    RETURN();
591
}
592

    
593
/* add carrying */
594
PPC_OP(addc)
595
{
596
    T2 = T0;
597
    T0 += T1;
598
    if (T0 < T2) {
599
        xer_ca = 1;
600
    } else {
601
        xer_ca = 0;
602
    }
603
    RETURN();
604
}
605

    
606
PPC_OP(addco)
607
{
608
    T2 = T0;
609
    T0 += T1;
610
    if (T0 < T2) {
611
        xer_ca = 1;
612
    } else {
613
        xer_ca = 0;
614
    }
615
    if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
616
        xer_so = 1;
617
        xer_ov = 1;
618
    } else {
619
        xer_ov = 0;
620
    }
621
    RETURN();
622
}
623

    
624
/* add extended */
625
/* candidate for helper (too long) */
626
PPC_OP(adde)
627
{
628
    T2 = T0;
629
    T0 += T1 + xer_ca;
630
    if (T0 < T2 || (xer_ca == 1 && T0 == T2)) {
631
        xer_ca = 1;
632
    } else {
633
        xer_ca = 0;
634
    }
635
    RETURN();
636
}
637

    
638
PPC_OP(addeo)
639
{
640
    T2 = T0;
641
    T0 += T1 + xer_ca;
642
    if (T0 < T2 || (xer_ca == 1 && T0 == T2)) {
643
        xer_ca = 1;
644
    } else {
645
        xer_ca = 0;
646
    }
647
    if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
648
        xer_so = 1;
649
        xer_ov = 1;
650
    } else {
651
        xer_ov = 0;
652
    }
653
    RETURN();
654
}
655

    
656
/* add immediate */
657
PPC_OP(addi)
658
{
659
    T0 += PARAM(1);
660
    RETURN();
661
}
662

    
663
/* add immediate carrying */
664
PPC_OP(addic)
665
{
666
    T1 = T0;
667
    T0 += PARAM(1);
668
    if (T0 < T1) {
669
        xer_ca = 1;
670
    } else {
671
        xer_ca = 0;
672
    }
673
    RETURN();
674
}
675

    
676
/* add to minus one extended */
677
PPC_OP(addme)
678
{
679
    T1 = T0;
680
    T0 += xer_ca + (-1);
681
    if (T1 != 0)
682
        xer_ca = 1;
683
    RETURN();
684
}
685

    
686
PPC_OP(addmeo)
687
{
688
    T1 = T0;
689
    T0 += xer_ca + (-1);
690
    if (T1 & (T1 ^ T0) & (1 << 31)) {
691
        xer_so = 1;
692
        xer_ov = 1;
693
    } else {
694
        xer_ov = 0;
695
    }
696
    if (T1 != 0)
697
        xer_ca = 1;
698
    RETURN();
699
}
700

    
701
/* add to zero extended */
702
PPC_OP(addze)
703
{
704
    T1 = T0;
705
    T0 += xer_ca;
706
    if (T0 < T1) {
707
        xer_ca = 1;
708
    } else {
709
        xer_ca = 0;
710
    }
711
    RETURN();
712
}
713

    
714
PPC_OP(addzeo)
715
{
716
    T1 = T0;
717
    T0 += xer_ca;
718
    if ((T1 ^ (-1)) & (T1 ^ T0) & (1 << 31)) {
719
        xer_so = 1;
720
        xer_ov = 1;
721
    } else {
722
        xer_ov = 0;
723
    }
724
    if (T0 < T1) {
725
        xer_ca = 1;
726
    } else {
727
        xer_ca = 0;
728
    }
729
    RETURN();
730
}
731

    
732
/* divide word */
733
/* candidate for helper (too long) */
734
PPC_OP(divw)
735
{
736
    if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
737
        Ts0 = (-1) * (T0 >> 31);
738
    } else {
739
        Ts0 /= Ts1;
740
    }
741
    RETURN();
742
}
743

    
744
PPC_OP(divwo)
745
{
746
    if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
747
        xer_so = 1;
748
        xer_ov = 1;
749
        T0 = (-1) * (T0 >> 31);
750
    } else {
751
        xer_ov = 0;
752
        Ts0 /= Ts1;
753
    }
754
    RETURN();
755
}
756

    
757
/* divide word unsigned */
758
PPC_OP(divwu)
759
{
760
    if (T1 == 0) {
761
        T0 = 0;
762
    } else {
763
        T0 /= T1;
764
    }
765
    RETURN();
766
}
767

    
768
PPC_OP(divwuo)
769
{
770
    if (T1 == 0) {
771
        xer_so = 1;
772
        xer_ov = 1;
773
        T0 = 0;
774
    } else {
775
        xer_ov = 0;
776
        T0 /= T1;
777
    }
778
    RETURN();
779
}
780

    
781
/* multiply high word */
782
PPC_OP(mulhw)
783
{
784
    Ts0 = ((int64_t)Ts0 * (int64_t)Ts1) >> 32;
785
    RETURN();
786
}
787

    
788
/* multiply high word unsigned */
789
PPC_OP(mulhwu)
790
{
791
    T0 = ((uint64_t)T0 * (uint64_t)T1) >> 32;
792
    RETURN();
793
}
794

    
795
/* multiply low immediate */
796
PPC_OP(mulli)
797
{
798
    Ts0 *= SPARAM(1);
799
    RETURN();
800
}
801

    
802
/* multiply low word */
803
PPC_OP(mullw)
804
{
805
    T0 *= T1;
806
    RETURN();
807
}
808

    
809
PPC_OP(mullwo)
810
{
811
    int64_t res = (int64_t)Ts0 * (int64_t)Ts1;
812

    
813
    if ((int32_t)res != res) {
814
        xer_ov = 1;
815
        xer_so = 1;
816
    } else {
817
        xer_ov = 0;
818
    }
819
    Ts0 = res;
820
    RETURN();
821
}
822

    
823
/* negate */
824
PPC_OP(neg)
825
{
826
    if (T0 != 0x80000000) {
827
        Ts0 = -Ts0;
828
    }
829
    RETURN();
830
}
831

    
832
PPC_OP(nego)
833
{
834
    if (T0 == 0x80000000) {
835
        xer_ov = 1;
836
        xer_so = 1;
837
    } else {
838
        xer_ov = 0;
839
        Ts0 = -Ts0;
840
    }
841
    RETURN();
842
}
843

    
844
/* substract from */
845
PPC_OP(subf)
846
{
847
    T0 = T1 - T0;
848
    RETURN();
849
}
850

    
851
PPC_OP(subfo)
852
{
853
    T2 = T0;
854
    T0 = T1 - T0;
855
    if (((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)) {
856
        xer_so = 1;
857
        xer_ov = 1;
858
    } else {
859
        xer_ov = 0;
860
    }
861
    RETURN();
862
}
863

    
864
/* substract from carrying */
865
PPC_OP(subfc)
866
{
867
    T0 = T1 - T0;
868
    if (T0 <= T1) {
869
        xer_ca = 1;
870
    } else {
871
        xer_ca = 0;
872
    }
873
    RETURN();
874
}
875

    
876
PPC_OP(subfco)
877
{
878
    T2 = T0;
879
    T0 = T1 - T0;
880
    if (T0 <= T1) {
881
        xer_ca = 1;
882
    } else {
883
        xer_ca = 0;
884
    }
885
    if (((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)) {
886
        xer_so = 1;
887
        xer_ov = 1;
888
    } else {
889
        xer_ov = 0;
890
    }
891
    RETURN();
892
}
893

    
894
/* substract from extended */
895
/* candidate for helper (too long) */
896
PPC_OP(subfe)
897
{
898
    T0 = T1 + ~T0 + xer_ca;
899
    if (T0 < T1 || (xer_ca == 1 && T0 == T1)) {
900
        xer_ca = 1;
901
    } else {
902
        xer_ca = 0;
903
    }
904
    RETURN();
905
}
906

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

    
925
/* substract from immediate carrying */
926
PPC_OP(subfic)
927
{
928
    T0 = PARAM(1) + ~T0 + 1;
929
    if (T0 <= PARAM(1)) {
930
        xer_ca = 1;
931
    } else {
932
        xer_ca = 0;
933
    }
934
    RETURN();
935
}
936

    
937
/* substract from minus one extended */
938
PPC_OP(subfme)
939
{
940
    T0 = ~T0 + xer_ca - 1;
941

    
942
    if (T0 != -1)
943
        xer_ca = 1;
944
    RETURN();
945
}
946

    
947
PPC_OP(subfmeo)
948
{
949
    T1 = T0;
950
    T0 = ~T0 + xer_ca - 1;
951
    if (~T1 & (~T1 ^ T0) & (1 << 31)) {
952
        xer_so = 1;
953
        xer_ov = 1;
954
    } else {
955
        xer_ov = 0;
956
    }
957
    if (T1 != -1)
958
        xer_ca = 1;
959
    RETURN();
960
}
961

    
962
/* substract from zero extended */
963
PPC_OP(subfze)
964
{
965
    T1 = ~T0;
966
    T0 = T1 + xer_ca;
967
    if (T0 < T1) {
968
        xer_ca = 1;
969
    } else {
970
        xer_ca = 0;
971
    }
972
    RETURN();
973
}
974

    
975
PPC_OP(subfzeo)
976
{
977
    T1 = T0;
978
    T0 = ~T0 + xer_ca;
979
    if ((~T1 ^ (-1)) & ((~T1) ^ T0) & (1 << 31)) {
980
        xer_ov = 1;
981
        xer_so = 1;
982
    } else {
983
        xer_ov = 0;
984
    }
985
    if (T0 < ~T1) {
986
        xer_ca = 1;
987
    } else {
988
        xer_ca = 0;
989
    }
990
    RETURN();
991
}
992

    
993
/***                           Integer comparison                          ***/
994
/* compare */
995
PPC_OP(cmp)
996
{
997
    if (Ts0 < Ts1) {
998
        T0 = 0x08;
999
    } else if (Ts0 > Ts1) {
1000
        T0 = 0x04;
1001
    } else {
1002
        T0 = 0x02;
1003
    }
1004
    RETURN();
1005
}
1006

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

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

    
1033
/* compare logical immediate */
1034
PPC_OP(cmpli)
1035
{
1036
    if (T0 < PARAM(1)) {
1037
        T0 = 0x08;
1038
    } else if (T0 > PARAM(1)) {
1039
        T0 = 0x04;
1040
    } else {
1041
        T0 = 0x02;
1042
    }
1043
    RETURN();
1044
}
1045

    
1046
/***                            Integer logical                            ***/
1047
/* and */
1048
PPC_OP(and)
1049
{
1050
    T0 &= T1;
1051
    RETURN();
1052
}
1053

    
1054
/* andc */
1055
PPC_OP(andc)
1056
{
1057
    T0 &= ~T1;
1058
    RETURN();
1059
}
1060

    
1061
/* andi. */
1062
PPC_OP(andi_)
1063
{
1064
    T0 &= PARAM(1);
1065
    RETURN();
1066
}
1067

    
1068
/* count leading zero */
1069
PPC_OP(cntlzw)
1070
{
1071
    T1 = T0;
1072
    for (T0 = 32; T1 > 0; T0--)
1073
        T1 = T1 >> 1;
1074
    RETURN();
1075
}
1076

    
1077
/* eqv */
1078
PPC_OP(eqv)
1079
{
1080
    T0 = ~(T0 ^ T1);
1081
    RETURN();
1082
}
1083

    
1084
/* extend sign byte */
1085
PPC_OP(extsb)
1086
{
1087
    Ts0 = s_ext8(Ts0);
1088
    RETURN();
1089
}
1090

    
1091
/* extend sign half word */
1092
PPC_OP(extsh)
1093
{
1094
    Ts0 = s_ext16(Ts0);
1095
    RETURN();
1096
}
1097

    
1098
/* nand */
1099
PPC_OP(nand)
1100
{
1101
    T0 = ~(T0 & T1);
1102
    RETURN();
1103
}
1104

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

    
1112
/* or */
1113
PPC_OP(or)
1114
{
1115
    T0 |= T1;
1116
    RETURN();
1117
}
1118

    
1119
/* orc */
1120
PPC_OP(orc)
1121
{
1122
    T0 |= ~T1;
1123
    RETURN();
1124
}
1125

    
1126
/* ori */
1127
PPC_OP(ori)
1128
{
1129
    T0 |= PARAM(1);
1130
    RETURN();
1131
}
1132

    
1133
/* xor */
1134
PPC_OP(xor)
1135
{
1136
    T0 ^= T1;
1137
    RETURN();
1138
}
1139

    
1140
/* xori */
1141
PPC_OP(xori)
1142
{
1143
    T0 ^= PARAM(1);
1144
    RETURN();
1145
}
1146

    
1147
/***                             Integer rotate                            ***/
1148
/* rotate left word immediate then mask insert */
1149
PPC_OP(rlwimi)
1150
{
1151
    T0 = (rotl(T0, PARAM(1)) & PARAM(2)) | (T1 & PARAM(3));
1152
    RETURN();
1153
}
1154

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

    
1162
PPC_OP(slwi)
1163
{
1164
    T0 = T0 << PARAM(1);
1165
    RETURN();
1166
}
1167

    
1168
PPC_OP(srwi)
1169
{
1170
    T0 = T0 >> PARAM(1);
1171
    RETURN();
1172
}
1173

    
1174
/* rotate left word then and with mask insert */
1175
PPC_OP(rlwinm)
1176
{
1177
    T0 = rotl(T0, PARAM(1)) & PARAM(2);
1178
    RETURN();
1179
}
1180

    
1181
PPC_OP(rotl)
1182
{
1183
    T0 = rotl(T0, T1);
1184
    RETURN();
1185
}
1186

    
1187
PPC_OP(rlwnm)
1188
{
1189
    T0 = rotl(T0, T1) & PARAM(1);
1190
    RETURN();
1191
}
1192

    
1193
/***                             Integer shift                             ***/
1194
/* shift left word */
1195
PPC_OP(slw)
1196
{
1197
    if (T1 & 0x20) {
1198
        T0 = 0;
1199
    } else {
1200
        T0 = T0 << T1;
1201
    }
1202
    RETURN();
1203
}
1204

    
1205
/* shift right algebraic word */
1206
PPC_OP(sraw)
1207
{
1208
    do_sraw();
1209
    RETURN();
1210
}
1211

    
1212
/* shift right algebraic word immediate */
1213
PPC_OP(srawi)
1214
{
1215
    Ts1 = Ts0;
1216
    Ts0 = Ts0 >> PARAM(1);
1217
    if (Ts1 < 0 && (Ts1 & PARAM(2)) != 0) {
1218
        xer_ca = 1;
1219
    } else {
1220
        xer_ca = 0;
1221
    }
1222
    RETURN();
1223
}
1224

    
1225
/* shift right word */
1226
PPC_OP(srw)
1227
{
1228
    if (T1 & 0x20) {
1229
        T0 = 0;
1230
    } else {
1231
        T0 = T0 >> T1;
1232
    }
1233
    RETURN();
1234
}
1235

    
1236
/***                       Floating-Point arithmetic                       ***/
1237
/* fadd - fadd. */
1238
PPC_OP(fadd)
1239
{
1240
    FT0 += FT1;
1241
    RETURN();
1242
}
1243

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

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

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

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

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

    
1279
/* fdiv - fdiv. */
1280
PPC_OP(fdiv)
1281
{
1282
    FT0 /= FT1;
1283
    RETURN();
1284
}
1285

    
1286
/* fdivs - fdivs. */
1287
PPC_OP(fdivs)
1288
{
1289
    FTS0 /= FTS1;
1290
    RETURN();
1291
}
1292

    
1293
/* fsqrt - fsqrt. */
1294
PPC_OP(fsqrt)
1295
{
1296
    do_fsqrt();
1297
    RETURN();
1298
}
1299

    
1300
/* fsqrts - fsqrts. */
1301
PPC_OP(fsqrts)
1302
{
1303
    do_fsqrts();
1304
    RETURN();
1305
}
1306

    
1307
/* fres - fres. */
1308
PPC_OP(fres)
1309
{
1310
    do_fres();
1311
    RETURN();
1312
}
1313

    
1314
/* frsqrte  - frsqrte. */
1315
PPC_OP(frsqrte)
1316
{
1317
    do_fsqrte();
1318
    RETURN();
1319
}
1320

    
1321
/* fsel - fsel. */
1322
PPC_OP(fsel)
1323
{
1324
    do_fsel();
1325
    RETURN();
1326
}
1327

    
1328
/***                     Floating-Point multiply-and-add                   ***/
1329
/* fmadd - fmadd. */
1330
PPC_OP(fmadd)
1331
{
1332
    FT0 = (FT0 * FT1) + FT2;
1333
    RETURN();
1334
}
1335

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

    
1343
/* fmsub - fmsub. */
1344
PPC_OP(fmsub)
1345
{
1346
    FT0 = (FT0 * FT1) - FT2;
1347
    RETURN();
1348
}
1349

    
1350
/* fmsubs - fmsubs. */
1351
PPC_OP(fmsubs)
1352
{
1353
    FTS0 = (FTS0 * FTS1) - FTS2;
1354
    RETURN();
1355
}
1356

    
1357
/* fnmadd - fnmadd. - fnmadds - fnmadds. */
1358
PPC_OP(fnmadd)
1359
{
1360
    FT0 = -((FT0 * FT1) + FT2);
1361
    RETURN();
1362
}
1363

    
1364
/* fnmadds - fnmadds. */
1365
PPC_OP(fnmadds)
1366
{
1367
    FTS0 = -((FTS0 * FTS1) + FTS2);
1368
    RETURN();
1369
}
1370

    
1371
/* fnmsub - fnmsub. */
1372
PPC_OP(fnmsub)
1373
{
1374
    FT0 = -((FT0 * FT1) - FT2);
1375
    RETURN();
1376
}
1377

    
1378
/* fnmsubs - fnmsubs. */
1379
PPC_OP(fnmsubs)
1380
{
1381
    FTS0 = -((FTS0 * FTS1) - FTS2);
1382
    RETURN();
1383
}
1384

    
1385
/***                     Floating-Point round & convert                    ***/
1386
/* frsp - frsp. */
1387
PPC_OP(frsp)
1388
{
1389
    FT0 = FTS0;
1390
    RETURN();
1391
}
1392

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

    
1400
/* fctiwz - fctiwz. */
1401
PPC_OP(fctiwz)
1402
{
1403
    do_fctiwz();
1404
    RETURN();
1405
}
1406

    
1407

    
1408
/***                         Floating-Point compare                        ***/
1409
/* fcmpu */
1410
PPC_OP(fcmpu)
1411
{
1412
    do_fcmpu();
1413
    RETURN();
1414
}
1415

    
1416
/* fcmpo */
1417
PPC_OP(fcmpo)
1418
{
1419
    do_fcmpo();
1420
    RETURN();
1421
}
1422

    
1423
/***                         Floating-point move                           ***/
1424
/* fabs */
1425
PPC_OP(fabs)
1426
{
1427
    do_fabs();
1428
    RETURN();
1429
}
1430

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

    
1438
/* fneg */
1439
PPC_OP(fneg)
1440
{
1441
    FT0 = -FT0;
1442
    RETURN();
1443
}
1444

    
1445
/* Load and store */
1446
#if defined(CONFIG_USER_ONLY)
1447
#define MEMSUFFIX _raw
1448
#include "op_mem.h"
1449
#else
1450
#define MEMSUFFIX _user
1451
#include "op_mem.h"
1452

    
1453
#define MEMSUFFIX _kernel
1454
#include "op_mem.h"
1455
#endif
1456

    
1457
/* Return from interrupt */
1458
PPC_OP(rfi)
1459
{
1460
    T0 = regs->spr[SRR1] & ~0xFFFF0000;
1461
    do_store_msr();
1462
    do_tlbia();
1463
    dump_rfi();
1464
    regs->nip = regs->spr[SRR0] & ~0x00000003;
1465
    if (env->exceptions != 0) {
1466
        do_check_exception_state();
1467
    }
1468
    RETURN();
1469
}
1470

    
1471
/* Trap word */
1472
PPC_OP(tw)
1473
{
1474
    if ((Ts0 < Ts1 && (PARAM(1) & 0x10)) ||
1475
        (Ts0 > Ts1 && (PARAM(1) & 0x08)) ||
1476
        (Ts0 == Ts1 && (PARAM(1) & 0x04)) ||
1477
        (T0 < T1 && (PARAM(1) & 0x02)) ||
1478
        (T0 > T1 && (PARAM(1) & 0x01)))
1479
        do_queue_exception_err(EXCP_PROGRAM, EXCP_TRAP);
1480
    RETURN();
1481
}
1482

    
1483
PPC_OP(twi)
1484
{
1485
    if ((Ts0 < SPARAM(1) && (PARAM(2) & 0x10)) ||
1486
        (Ts0 > SPARAM(1) && (PARAM(2) & 0x08)) ||
1487
        (Ts0 == SPARAM(1) && (PARAM(2) & 0x04)) ||
1488
        (T0 < (uint32_t)SPARAM(1) && (PARAM(2) & 0x02)) ||
1489
        (T0 > (uint32_t)SPARAM(1) && (PARAM(2) & 0x01)))
1490
        do_queue_exception_err(EXCP_PROGRAM, EXCP_TRAP);
1491
    RETURN();
1492
}
1493

    
1494
/* Instruction cache block invalidate */
1495
PPC_OP(icbi)
1496
{
1497
    do_icbi();
1498
    RETURN();
1499
}
1500

    
1501
/* tlbia */
1502
PPC_OP(tlbia)
1503
{
1504
    do_tlbia();
1505
    RETURN();
1506
}
1507

    
1508
/* tlbie */
1509
PPC_OP(tlbie)
1510
{
1511
    do_tlbie();
1512
    RETURN();
1513
}