Statistics
| Branch: | Revision:

root / target-ppc / op.c @ 2be0071f

History | View | Annotate | Download (19.7 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
/* Segment registers load and store with immediate index */
208
PPC_OP(load_srin)
209
{
210
    T0 = regs->sr[T1 >> 28];
211
    RETURN();
212
}
213

    
214
PPC_OP(store_srin)
215
{
216
    do_store_sr(env, ((uint32_t)T1 >> 28), T0);
217
    RETURN();
218
}
219

    
220
PPC_OP(load_sdr1)
221
{
222
    T0 = regs->sdr1;
223
    RETURN();
224
}
225

    
226
PPC_OP(store_sdr1)
227
{
228
    do_store_sdr1(env, T0);
229
    RETURN();
230
}
231

    
232
PPC_OP(exit_tb)
233
{
234
    EXIT_TB();
235
}
236

    
237
/* Load/store special registers */
238
PPC_OP(load_cr)
239
{
240
    T0 = do_load_cr(env);
241
    RETURN();
242
}
243

    
244
PPC_OP(store_cr)
245
{
246
    do_store_cr(env, T0, PARAM(1));
247
    RETURN();
248
}
249

    
250
PPC_OP(load_xer_cr)
251
{
252
    T0 = (xer_so << 3) | (xer_ov << 2) | (xer_ca << 1);
253
    RETURN();
254
}
255

    
256
PPC_OP(clear_xer_cr)
257
{
258
    xer_so = 0;
259
    xer_ov = 0;
260
    xer_ca = 0;
261
    RETURN();
262
}
263

    
264
PPC_OP(load_xer_bc)
265
{
266
    T1 = xer_bc;
267
    RETURN();
268
}
269

    
270
PPC_OP(load_xer)
271
{
272
    T0 = do_load_xer(env);
273
    RETURN();
274
}
275

    
276
PPC_OP(store_xer)
277
{
278
    do_store_xer(env, T0);
279
    RETURN();
280
}
281

    
282
PPC_OP(load_msr)
283
{
284
    T0 = do_load_msr(env);
285
    RETURN();
286
}
287

    
288
PPC_OP(store_msr)
289
{
290
    do_store_msr(env, T0);
291
    RETURN();
292
}
293

    
294
/* SPR */
295
PPC_OP(load_spr)
296
{
297
    T0 = regs->spr[PARAM(1)];
298
    RETURN();
299
}
300

    
301
PPC_OP(store_spr)
302
{
303
    regs->spr[PARAM(1)] = T0;
304
    RETURN();
305
}
306

    
307
PPC_OP(load_lr)
308
{
309
    T0 = regs->lr;
310
    RETURN();
311
}
312

    
313
PPC_OP(store_lr)
314
{
315
    regs->lr = T0;
316
    RETURN();
317
}
318

    
319
PPC_OP(load_ctr)
320
{
321
    T0 = regs->ctr;
322
    RETURN();
323
}
324

    
325
PPC_OP(store_ctr)
326
{
327
    regs->ctr = T0;
328
    RETURN();
329
}
330

    
331
PPC_OP(load_tbl)
332
{
333
    T0 = cpu_ppc_load_tbl(regs);
334
    RETURN();
335
}
336

    
337
PPC_OP(load_tbu)
338
{
339
    T0 = cpu_ppc_load_tbu(regs);
340
    RETURN();
341
}
342

    
343
PPC_OP(store_tbl)
344
{
345
    cpu_ppc_store_tbl(regs, T0);
346
    RETURN();
347
}
348

    
349
PPC_OP(store_tbu)
350
{
351
    cpu_ppc_store_tbu(regs, T0);
352
    RETURN();
353
}
354

    
355
PPC_OP(load_decr)
356
{
357
    T0 = cpu_ppc_load_decr(regs);
358
    }
359

    
360
PPC_OP(store_decr)
361
{
362
    cpu_ppc_store_decr(regs, T0);
363
    RETURN();
364
}
365

    
366
PPC_OP(load_ibat)
367
{
368
    T0 = regs->IBAT[PARAM(1)][PARAM(2)];
369
}
370

    
371
void op_store_ibatu (void)
372
{
373
    do_store_ibatu(env, PARAM1, T0);
374
    RETURN();
375
}
376

    
377
void op_store_ibatl (void)
378
{
379
#if 1
380
    env->IBAT[1][PARAM1] = T0;
381
#else
382
    do_store_ibatl(env, PARAM1, T0);
383
#endif
384
    RETURN();
385
}
386

    
387
PPC_OP(load_dbat)
388
{
389
    T0 = regs->DBAT[PARAM(1)][PARAM(2)];
390
}
391

    
392
void op_store_dbatu (void)
393
{
394
    do_store_dbatu(env, PARAM1, T0);
395
    RETURN();
396
}
397

    
398
void op_store_dbatl (void)
399
{
400
#if 1
401
    env->DBAT[1][PARAM1] = T0;
402
#else
403
    do_store_dbatl(env, PARAM1, T0);
404
#endif
405
    RETURN();
406
}
407

    
408
/* FPSCR */
409
PPC_OP(load_fpscr)
410
{
411
    FT0 = do_load_fpscr(env);
412
    RETURN();
413
}
414

    
415
PPC_OP(store_fpscr)
416
{
417
    do_store_fpscr(env, FT0, PARAM1);
418
    RETURN();
419
}
420

    
421
PPC_OP(reset_scrfx)
422
{
423
    regs->fpscr[7] &= ~0x8;
424
    RETURN();
425
}
426

    
427
/* crf operations */
428
PPC_OP(getbit_T0)
429
{
430
    T0 = (T0 >> PARAM(1)) & 1;
431
    RETURN();
432
}
433

    
434
PPC_OP(getbit_T1)
435
{
436
    T1 = (T1 >> PARAM(1)) & 1;
437
    RETURN();
438
}
439

    
440
PPC_OP(setcrfbit)
441
{
442
    T1 = (T1 & PARAM(1)) | (T0 << PARAM(2)); 
443
    RETURN();
444
}
445

    
446
/* Branch */
447
#define EIP regs->nip
448

    
449
PPC_OP(setlr)
450
{
451
    regs->lr = PARAM1;
452
}
453

    
454
PPC_OP(b)
455
{
456
    JUMP_TB(b1, PARAM1, 0, PARAM2);
457
}
458

    
459
PPC_OP(b_T1)
460
{
461
    regs->nip = T1 & ~3;
462
}
463

    
464
PPC_OP(btest) 
465
{
466
    if (T0) {
467
        JUMP_TB(btest, PARAM1, 0, PARAM2);
468
    } else {
469
        JUMP_TB(btest, PARAM1, 1, PARAM3);
470
    }
471
    RETURN();
472
}
473

    
474
PPC_OP(btest_T1) 
475
{
476
    if (T0) {
477
        regs->nip = T1 & ~3;
478
    } else {
479
        regs->nip = PARAM1;
480
    }
481
    RETURN();
482
}
483

    
484
PPC_OP(movl_T1_ctr)
485
{
486
    T1 = regs->ctr;
487
}
488

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

    
494
/* tests with result in T0 */
495

    
496
PPC_OP(test_ctr)
497
{
498
    T0 = regs->ctr;
499
}
500

    
501
PPC_OP(test_ctr_true)
502
{
503
    T0 = (regs->ctr != 0 && (T0 & PARAM(1)) != 0);
504
}
505

    
506
PPC_OP(test_ctr_false)
507
{
508
    T0 = (regs->ctr != 0 && (T0 & PARAM(1)) == 0);
509
}
510

    
511
PPC_OP(test_ctrz)
512
{
513
    T0 = (regs->ctr == 0);
514
}
515

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

    
521
PPC_OP(test_ctrz_false)
522
{
523
    T0 = (regs->ctr == 0 && (T0 & PARAM(1)) == 0);
524
}
525

    
526
PPC_OP(test_true)
527
{
528
    T0 = (T0 & PARAM(1));
529
}
530

    
531
PPC_OP(test_false)
532
{
533
    T0 = ((T0 & PARAM(1)) == 0);
534
}
535

    
536
/* CTR maintenance */
537
PPC_OP(dec_ctr)
538
{
539
    regs->ctr--;
540
    RETURN();
541
}
542

    
543
/***                           Integer arithmetic                          ***/
544
/* add */
545
PPC_OP(add)
546
{
547
    T0 += T1;
548
    RETURN();
549
}
550

    
551
PPC_OP(addo)
552
{
553
    T2 = T0;
554
    T0 += T1;
555
    if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
556
        xer_so = 1;
557
        xer_ov = 1;
558
    } else {
559
        xer_ov = 0;
560
    }
561
    RETURN();
562
}
563

    
564
/* add carrying */
565
PPC_OP(addc)
566
{
567
    T2 = T0;
568
    T0 += T1;
569
    if (T0 < T2) {
570
        xer_ca = 1;
571
    } else {
572
        xer_ca = 0;
573
    }
574
    RETURN();
575
}
576

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

    
595
/* add extended */
596
/* candidate for helper (too long) */
597
PPC_OP(adde)
598
{
599
    T2 = T0;
600
    T0 += T1 + xer_ca;
601
    if (T0 < T2 || (xer_ca == 1 && T0 == T2)) {
602
        xer_ca = 1;
603
    } else {
604
        xer_ca = 0;
605
    }
606
    RETURN();
607
}
608

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

    
627
/* add immediate */
628
PPC_OP(addi)
629
{
630
    T0 += PARAM(1);
631
    RETURN();
632
}
633

    
634
/* add immediate carrying */
635
PPC_OP(addic)
636
{
637
    T1 = T0;
638
    T0 += PARAM(1);
639
    if (T0 < T1) {
640
        xer_ca = 1;
641
    } else {
642
        xer_ca = 0;
643
    }
644
    RETURN();
645
}
646

    
647
/* add to minus one extended */
648
PPC_OP(addme)
649
{
650
    T1 = T0;
651
    T0 += xer_ca + (-1);
652
    if (T1 != 0)
653
        xer_ca = 1;
654
    RETURN();
655
}
656

    
657
PPC_OP(addmeo)
658
{
659
    T1 = T0;
660
    T0 += xer_ca + (-1);
661
    if (T1 & (T1 ^ T0) & (1 << 31)) {
662
        xer_so = 1;
663
        xer_ov = 1;
664
    } else {
665
        xer_ov = 0;
666
    }
667
    if (T1 != 0)
668
        xer_ca = 1;
669
    RETURN();
670
}
671

    
672
/* add to zero extended */
673
PPC_OP(addze)
674
{
675
    T1 = T0;
676
    T0 += xer_ca;
677
    if (T0 < T1) {
678
        xer_ca = 1;
679
    } else {
680
        xer_ca = 0;
681
    }
682
    RETURN();
683
}
684

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

    
703
/* divide word */
704
/* candidate for helper (too long) */
705
PPC_OP(divw)
706
{
707
    if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
708
        T0 = (int32_t)((-1) * (T0 >> 31));
709
    } else {
710
        T0 = (Ts0 / Ts1);
711
    }
712
    RETURN();
713
}
714

    
715
PPC_OP(divwo)
716
{
717
    if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
718
        xer_so = 1;
719
        xer_ov = 1;
720
        T0 = (-1) * (T0 >> 31);
721
    } else {
722
        xer_ov = 0;
723
        T0 = (Ts0 / Ts1);
724
    }
725
    RETURN();
726
}
727

    
728
/* divide word unsigned */
729
PPC_OP(divwu)
730
{
731
    if (T1 == 0) {
732
        T0 = 0;
733
    } else {
734
        T0 /= T1;
735
    }
736
    RETURN();
737
}
738

    
739
PPC_OP(divwuo)
740
{
741
    if (T1 == 0) {
742
        xer_so = 1;
743
        xer_ov = 1;
744
        T0 = 0;
745
    } else {
746
        xer_ov = 0;
747
        T0 /= T1;
748
    }
749
    RETURN();
750
}
751

    
752
/* multiply high word */
753
PPC_OP(mulhw)
754
{
755
    T0 = ((int64_t)Ts0 * (int64_t)Ts1) >> 32;
756
    RETURN();
757
}
758

    
759
/* multiply high word unsigned */
760
PPC_OP(mulhwu)
761
{
762
    T0 = ((uint64_t)T0 * (uint64_t)T1) >> 32;
763
    RETURN();
764
}
765

    
766
/* multiply low immediate */
767
PPC_OP(mulli)
768
{
769
    T0 = (Ts0 * SPARAM(1));
770
    RETURN();
771
}
772

    
773
/* multiply low word */
774
PPC_OP(mullw)
775
{
776
    T0 *= T1;
777
    RETURN();
778
}
779

    
780
PPC_OP(mullwo)
781
{
782
    int64_t res = (int64_t)Ts0 * (int64_t)Ts1;
783

    
784
    if ((int32_t)res != res) {
785
        xer_ov = 1;
786
        xer_so = 1;
787
    } else {
788
        xer_ov = 0;
789
    }
790
    T0 = (int32_t)res;
791
    RETURN();
792
}
793

    
794
/* negate */
795
PPC_OP(neg)
796
{
797
    if (T0 != 0x80000000) {
798
        T0 = -Ts0;
799
    }
800
    RETURN();
801
}
802

    
803
PPC_OP(nego)
804
{
805
    if (T0 == 0x80000000) {
806
        xer_ov = 1;
807
        xer_so = 1;
808
    } else {
809
        xer_ov = 0;
810
        T0 = -Ts0;
811
    }
812
    RETURN();
813
}
814

    
815
/* substract from */
816
PPC_OP(subf)
817
{
818
    T0 = T1 - T0;
819
    RETURN();
820
}
821

    
822
PPC_OP(subfo)
823
{
824
    T2 = T0;
825
    T0 = T1 - T0;
826
    if (((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)) {
827
        xer_so = 1;
828
        xer_ov = 1;
829
    } else {
830
        xer_ov = 0;
831
    }
832
    RETURN();
833
}
834

    
835
/* substract from carrying */
836
PPC_OP(subfc)
837
{
838
    T0 = T1 - T0;
839
    if (T0 <= T1) {
840
        xer_ca = 1;
841
    } else {
842
        xer_ca = 0;
843
    }
844
    RETURN();
845
}
846

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

    
865
/* substract from extended */
866
/* candidate for helper (too long) */
867
PPC_OP(subfe)
868
{
869
    T0 = T1 + ~T0 + xer_ca;
870
    if (T0 < T1 || (xer_ca == 1 && T0 == T1)) {
871
        xer_ca = 1;
872
    } else {
873
        xer_ca = 0;
874
    }
875
    RETURN();
876
}
877

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

    
896
/* substract from immediate carrying */
897
PPC_OP(subfic)
898
{
899
    T0 = PARAM(1) + ~T0 + 1;
900
    if (T0 <= PARAM(1)) {
901
        xer_ca = 1;
902
    } else {
903
        xer_ca = 0;
904
    }
905
    RETURN();
906
}
907

    
908
/* substract from minus one extended */
909
PPC_OP(subfme)
910
{
911
    T0 = ~T0 + xer_ca - 1;
912

    
913
    if (T0 != -1)
914
        xer_ca = 1;
915
    RETURN();
916
}
917

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

    
933
/* substract from zero extended */
934
PPC_OP(subfze)
935
{
936
    T1 = ~T0;
937
    T0 = T1 + xer_ca;
938
    if (T0 < T1) {
939
        xer_ca = 1;
940
    } else {
941
        xer_ca = 0;
942
    }
943
    RETURN();
944
}
945

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

    
964
/***                           Integer comparison                          ***/
965
/* compare */
966
PPC_OP(cmp)
967
{
968
    if (Ts0 < Ts1) {
969
        T0 = 0x08;
970
    } else if (Ts0 > Ts1) {
971
        T0 = 0x04;
972
    } else {
973
        T0 = 0x02;
974
    }
975
    RETURN();
976
}
977

    
978
/* compare immediate */
979
PPC_OP(cmpi)
980
{
981
    if (Ts0 < SPARAM(1)) {
982
        T0 = 0x08;
983
    } else if (Ts0 > SPARAM(1)) {
984
        T0 = 0x04;
985
    } else {
986
        T0 = 0x02;
987
    }
988
    RETURN();
989
}
990

    
991
/* compare logical */
992
PPC_OP(cmpl)
993
{
994
    if (T0 < T1) {
995
        T0 = 0x08;
996
    } else if (T0 > T1) {
997
        T0 = 0x04;
998
    } else {
999
        T0 = 0x02;
1000
    }
1001
    RETURN();
1002
}
1003

    
1004
/* compare logical immediate */
1005
PPC_OP(cmpli)
1006
{
1007
    if (T0 < PARAM(1)) {
1008
        T0 = 0x08;
1009
    } else if (T0 > PARAM(1)) {
1010
        T0 = 0x04;
1011
    } else {
1012
        T0 = 0x02;
1013
    }
1014
    RETURN();
1015
}
1016

    
1017
/***                            Integer logical                            ***/
1018
/* and */
1019
PPC_OP(and)
1020
{
1021
    T0 &= T1;
1022
    RETURN();
1023
}
1024

    
1025
/* andc */
1026
PPC_OP(andc)
1027
{
1028
    T0 &= ~T1;
1029
    RETURN();
1030
}
1031

    
1032
/* andi. */
1033
PPC_OP(andi_)
1034
{
1035
    T0 &= PARAM(1);
1036
    RETURN();
1037
}
1038

    
1039
/* count leading zero */
1040
PPC_OP(cntlzw)
1041
{
1042
    T1 = T0;
1043
    for (T0 = 32; T1 > 0; T0--)
1044
        T1 = T1 >> 1;
1045
    RETURN();
1046
}
1047

    
1048
/* eqv */
1049
PPC_OP(eqv)
1050
{
1051
    T0 = ~(T0 ^ T1);
1052
    RETURN();
1053
}
1054

    
1055
/* extend sign byte */
1056
PPC_OP(extsb)
1057
{
1058
    T0 = (int32_t)((int8_t)(Ts0));
1059
    RETURN();
1060
}
1061

    
1062
/* extend sign half word */
1063
PPC_OP(extsh)
1064
{
1065
    T0 = (int32_t)((int16_t)(Ts0));
1066
    RETURN();
1067
}
1068

    
1069
/* nand */
1070
PPC_OP(nand)
1071
{
1072
    T0 = ~(T0 & T1);
1073
    RETURN();
1074
}
1075

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

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

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

    
1097
/* ori */
1098
PPC_OP(ori)
1099
{
1100
    T0 |= PARAM(1);
1101
    RETURN();
1102
}
1103

    
1104
/* xor */
1105
PPC_OP(xor)
1106
{
1107
    T0 ^= T1;
1108
    RETURN();
1109
}
1110

    
1111
/* xori */
1112
PPC_OP(xori)
1113
{
1114
    T0 ^= PARAM(1);
1115
    RETURN();
1116
}
1117

    
1118
/***                             Integer rotate                            ***/
1119
/* rotate left word immediate then mask insert */
1120
PPC_OP(rlwimi)
1121
{
1122
    T0 = (rotl(T0, PARAM(1)) & PARAM(2)) | (T1 & PARAM(3));
1123
    RETURN();
1124
}
1125

    
1126
/* rotate left immediate then and with mask insert */
1127
PPC_OP(rotlwi)
1128
{
1129
    T0 = rotl(T0, PARAM(1));
1130
    RETURN();
1131
}
1132

    
1133
PPC_OP(slwi)
1134
{
1135
    T0 = T0 << PARAM(1);
1136
    RETURN();
1137
}
1138

    
1139
PPC_OP(srwi)
1140
{
1141
    T0 = T0 >> PARAM(1);
1142
    RETURN();
1143
}
1144

    
1145
/* rotate left word then and with mask insert */
1146
PPC_OP(rlwinm)
1147
{
1148
    T0 = rotl(T0, PARAM(1)) & PARAM(2);
1149
    RETURN();
1150
}
1151

    
1152
PPC_OP(rotl)
1153
{
1154
    T0 = rotl(T0, T1);
1155
    RETURN();
1156
}
1157

    
1158
PPC_OP(rlwnm)
1159
{
1160
    T0 = rotl(T0, T1) & PARAM(1);
1161
    RETURN();
1162
}
1163

    
1164
/***                             Integer shift                             ***/
1165
/* shift left word */
1166
PPC_OP(slw)
1167
{
1168
    if (T1 & 0x20) {
1169
        T0 = 0;
1170
    } else {
1171
        T0 = T0 << T1;
1172
    }
1173
    RETURN();
1174
}
1175

    
1176
/* shift right algebraic word */
1177
PPC_OP(sraw)
1178
{
1179
    do_sraw();
1180
    RETURN();
1181
}
1182

    
1183
/* shift right algebraic word immediate */
1184
PPC_OP(srawi)
1185
{
1186
    T1 = T0;
1187
    T0 = (Ts0 >> PARAM(1));
1188
    if (Ts1 < 0 && (Ts1 & PARAM(2)) != 0) {
1189
        xer_ca = 1;
1190
    } else {
1191
        xer_ca = 0;
1192
    }
1193
    RETURN();
1194
}
1195

    
1196
/* shift right word */
1197
PPC_OP(srw)
1198
{
1199
    if (T1 & 0x20) {
1200
        T0 = 0;
1201
    } else {
1202
        T0 = T0 >> T1;
1203
    }
1204
    RETURN();
1205
}
1206

    
1207
/***                       Floating-Point arithmetic                       ***/
1208
/* fadd - fadd. */
1209
PPC_OP(fadd)
1210
{
1211
    FT0 += FT1;
1212
    RETURN();
1213
}
1214

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

    
1222
/* fmul - fmul. */
1223
PPC_OP(fmul)
1224
{
1225
    FT0 *= FT1;
1226
    RETURN();
1227
}
1228

    
1229
/* fdiv - fdiv. */
1230
void do_fdiv (void);
1231
PPC_OP(fdiv)
1232
{
1233
    do_fdiv();
1234
    RETURN();
1235
}
1236

    
1237
/* fsqrt - fsqrt. */
1238
PPC_OP(fsqrt)
1239
{
1240
    do_fsqrt();
1241
    RETURN();
1242
}
1243

    
1244
/* fres - fres. */
1245
PPC_OP(fres)
1246
{
1247
    do_fres();
1248
    RETURN();
1249
}
1250

    
1251
/* frsqrte  - frsqrte. */
1252
PPC_OP(frsqrte)
1253
{
1254
    do_frsqrte();
1255
    RETURN();
1256
}
1257

    
1258
/* fsel - fsel. */
1259
PPC_OP(fsel)
1260
{
1261
    do_fsel();
1262
    RETURN();
1263
}
1264

    
1265
/***                     Floating-Point multiply-and-add                   ***/
1266
/* fmadd - fmadd. */
1267
PPC_OP(fmadd)
1268
{
1269
    FT0 = (FT0 * FT1) + FT2;
1270
    RETURN();
1271
}
1272

    
1273
/* fmsub - fmsub. */
1274
PPC_OP(fmsub)
1275
{
1276
    FT0 = (FT0 * FT1) - FT2;
1277
    RETURN();
1278
}
1279

    
1280
/* fnmadd - fnmadd. - fnmadds - fnmadds. */
1281
PPC_OP(fnmadd)
1282
{
1283
    do_fnmadd();
1284
    RETURN();
1285
}
1286

    
1287
/* fnmsub - fnmsub. */
1288
PPC_OP(fnmsub)
1289
{
1290
    do_fnmsub();
1291
    RETURN();
1292
}
1293

    
1294
/***                     Floating-Point round & convert                    ***/
1295
/* frsp - frsp. */
1296
PPC_OP(frsp)
1297
{
1298
    FT0 = (float)FT0;
1299
    RETURN();
1300
}
1301

    
1302
/* fctiw - fctiw. */
1303
PPC_OP(fctiw)
1304
{
1305
    do_fctiw();
1306
    RETURN();
1307
}
1308

    
1309
/* fctiwz - fctiwz. */
1310
PPC_OP(fctiwz)
1311
{
1312
    do_fctiwz();
1313
    RETURN();
1314
}
1315

    
1316

    
1317
/***                         Floating-Point compare                        ***/
1318
/* fcmpu */
1319
PPC_OP(fcmpu)
1320
{
1321
    do_fcmpu();
1322
    RETURN();
1323
}
1324

    
1325
/* fcmpo */
1326
PPC_OP(fcmpo)
1327
{
1328
    do_fcmpo();
1329
    RETURN();
1330
}
1331

    
1332
/***                         Floating-point move                           ***/
1333
/* fabs */
1334
void do_fabs (void);
1335
PPC_OP(fabs)
1336
{
1337
    do_fabs();
1338
    RETURN();
1339
}
1340

    
1341
/* fnabs */
1342
void do_fnabs (void);
1343
PPC_OP(fnabs)
1344
{
1345
    do_fnabs();
1346
    RETURN();
1347
}
1348

    
1349
/* fneg */
1350
PPC_OP(fneg)
1351
{
1352
    FT0 = -FT0;
1353
    RETURN();
1354
}
1355

    
1356
/* Load and store */
1357
#define MEMSUFFIX _raw
1358
#include "op_mem.h"
1359
#if !defined(CONFIG_USER_ONLY)
1360
#define MEMSUFFIX _user
1361
#include "op_mem.h"
1362

    
1363
#define MEMSUFFIX _kernel
1364
#include "op_mem.h"
1365
#endif
1366

    
1367
/* Special op to check and maybe clear reservation */
1368
PPC_OP(check_reservation)
1369
{
1370
    do_check_reservation();
1371
    RETURN();
1372
}
1373

    
1374
/* Return from interrupt */
1375
PPC_OP(rfi)
1376
{
1377
    env->nip = env->spr[SPR_SRR0] & ~0x00000003;
1378
    T0 = env->spr[SPR_SRR1] & ~0xFFFF0000UL;
1379
    do_store_msr(env, T0);
1380
    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
1381
    RETURN();
1382
}
1383

    
1384
/* Trap word */
1385
PPC_OP(tw)
1386
{
1387
    if ((Ts0 < Ts1 && (PARAM(1) & 0x10)) ||
1388
        (Ts0 > Ts1 && (PARAM(1) & 0x08)) ||
1389
        (Ts0 == Ts1 && (PARAM(1) & 0x04)) ||
1390
        (T0 < T1 && (PARAM(1) & 0x02)) ||
1391
        (T0 > T1 && (PARAM(1) & 0x01)))
1392
        do_raise_exception_err(EXCP_PROGRAM, EXCP_TRAP);
1393
    RETURN();
1394
}
1395

    
1396
PPC_OP(twi)
1397
{
1398
    if ((Ts0 < SPARAM(1) && (PARAM(2) & 0x10)) ||
1399
        (Ts0 > SPARAM(1) && (PARAM(2) & 0x08)) ||
1400
        (Ts0 == SPARAM(1) && (PARAM(2) & 0x04)) ||
1401
        (T0 < (uint32_t)SPARAM(1) && (PARAM(2) & 0x02)) ||
1402
        (T0 > (uint32_t)SPARAM(1) && (PARAM(2) & 0x01)))
1403
        do_raise_exception_err(EXCP_PROGRAM, EXCP_TRAP);
1404
    RETURN();
1405
}
1406

    
1407
/* Instruction cache block invalidate */
1408
PPC_OP(icbi)
1409
{
1410
    do_icbi();
1411
    RETURN();
1412
}
1413

    
1414
/* tlbia */
1415
PPC_OP(tlbia)
1416
{
1417
    do_tlbia();
1418
    RETURN();
1419
}
1420

    
1421
/* tlbie */
1422
PPC_OP(tlbie)
1423
{
1424
    do_tlbie();
1425
    RETURN();
1426
}
1427

    
1428
void op_store_pir (void)
1429
{
1430
    env->spr[SPR_PIR] = T0 & 0x0000000FUL;
1431
    RETURN();
1432
}