Statistics
| Branch: | Revision:

root / target-ppc / op.c @ ea4e754f

History | View | Annotate | Download (16.8 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
    do_raise_exception(EXCP_DEBUG);
210
}
211

    
212
/* Segment registers load and store with immediate index */
213
PPC_OP(load_srin)
214
{
215
    T0 = regs->sr[T1 >> 28];
216
    RETURN();
217
}
218

    
219
PPC_OP(store_srin)
220
{
221
    do_store_sr(env, ((uint32_t)T1 >> 28), T0);
222
    RETURN();
223
}
224

    
225
PPC_OP(load_sdr1)
226
{
227
    T0 = regs->sdr1;
228
    RETURN();
229
}
230

    
231
PPC_OP(store_sdr1)
232
{
233
    do_store_sdr1(env, T0);
234
    RETURN();
235
}
236

    
237
PPC_OP(exit_tb)
238
{
239
    EXIT_TB();
240
}
241

    
242
/* Load/store special registers */
243
PPC_OP(load_cr)
244
{
245
    T0 = do_load_cr(env);
246
    RETURN();
247
}
248

    
249
PPC_OP(store_cr)
250
{
251
    do_store_cr(env, T0, PARAM(1));
252
    RETURN();
253
}
254

    
255
PPC_OP(load_xer_cr)
256
{
257
    T0 = (xer_so << 3) | (xer_ov << 2) | (xer_ca << 1);
258
    RETURN();
259
}
260

    
261
PPC_OP(clear_xer_cr)
262
{
263
    xer_so = 0;
264
    xer_ov = 0;
265
    xer_ca = 0;
266
    RETURN();
267
}
268

    
269
PPC_OP(load_xer_bc)
270
{
271
    T1 = xer_bc;
272
    RETURN();
273
}
274

    
275
PPC_OP(load_xer)
276
{
277
    T0 = do_load_xer(env);
278
    RETURN();
279
}
280

    
281
PPC_OP(store_xer)
282
{
283
    do_store_xer(env, T0);
284
    RETURN();
285
}
286

    
287
PPC_OP(load_msr)
288
{
289
    T0 = do_load_msr(env);
290
    RETURN();
291
}
292

    
293
PPC_OP(store_msr)
294
{
295
    do_store_msr(env, T0);
296
    RETURN();
297
}
298

    
299
/* SPR */
300
PPC_OP(load_spr)
301
{
302
    T0 = regs->spr[PARAM(1)];
303
    RETURN();
304
}
305

    
306
PPC_OP(store_spr)
307
{
308
    regs->spr[PARAM(1)] = T0;
309
    RETURN();
310
}
311

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

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

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

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

    
336
PPC_OP(load_tbl)
337
{
338
    T0 = cpu_ppc_load_tbl(regs);
339
    RETURN();
340
}
341

    
342
PPC_OP(load_tbu)
343
{
344
    T0 = cpu_ppc_load_tbu(regs);
345
    RETURN();
346
}
347

    
348
PPC_OP(store_tbl)
349
{
350
    cpu_ppc_store_tbl(regs, T0);
351
    RETURN();
352
}
353

    
354
PPC_OP(store_tbu)
355
{
356
    cpu_ppc_store_tbu(regs, T0);
357
    RETURN();
358
}
359

    
360
PPC_OP(load_decr)
361
{
362
    T0 = cpu_ppc_load_decr(regs);
363
    }
364

    
365
PPC_OP(store_decr)
366
{
367
    cpu_ppc_store_decr(regs, T0);
368
    RETURN();
369
}
370

    
371
PPC_OP(load_ibat)
372
{
373
    T0 = regs->IBAT[PARAM(1)][PARAM(2)];
374
}
375

    
376
void op_store_ibatu (void)
377
{
378
    do_store_ibatu(env, PARAM1, T0);
379
    RETURN();
380
}
381

    
382
void op_store_ibatl (void)
383
{
384
#if 1
385
    env->IBAT[1][PARAM1] = T0;
386
#else
387
    do_store_ibatl(env, PARAM1, T0);
388
#endif
389
    RETURN();
390
}
391

    
392
PPC_OP(load_dbat)
393
{
394
    T0 = regs->DBAT[PARAM(1)][PARAM(2)];
395
}
396

    
397
void op_store_dbatu (void)
398
{
399
    do_store_dbatu(env, PARAM1, T0);
400
    RETURN();
401
}
402

    
403
void op_store_dbatl (void)
404
{
405
#if 1
406
    env->DBAT[1][PARAM1] = T0;
407
#else
408
    do_store_dbatl(env, PARAM1, T0);
409
#endif
410
    RETURN();
411
}
412

    
413
/* FPSCR */
414
PPC_OP(load_fpscr)
415
{
416
    FT0 = do_load_fpscr(env);
417
    RETURN();
418
}
419

    
420
PPC_OP(store_fpscr)
421
{
422
    do_store_fpscr(env, FT0, PARAM1);
423
    RETURN();
424
}
425

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

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

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

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

    
451
/* Branch */
452
#define EIP regs->nip
453

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

    
459
PPC_OP(goto_tb0)
460
{
461
    GOTO_TB(op_goto_tb0, PARAM1, 0);
462
}
463

    
464
PPC_OP(goto_tb1)
465
{
466
    GOTO_TB(op_goto_tb1, PARAM1, 1);
467
}
468

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

    
474
PPC_OP(jz_T0)
475
{
476
    if (!T0)
477
        GOTO_LABEL_PARAM(1);
478
    RETURN();
479
}
480

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

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

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

    
501
/* tests with result in T0 */
502

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

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

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

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

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

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

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

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

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

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

    
558
void do_addo (void);
559
void op_addo (void)
560
{
561
    do_addo();
562
    RETURN();
563
}
564

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

    
578
void do_addco (void);
579
void op_addco (void)
580
{
581
    do_addco();
582
    RETURN();
583
}
584

    
585
/* add extended */
586
void do_adde (void);
587
void op_adde (void)
588
{
589
    do_adde();
590
}
591

    
592
void do_addeo (void);
593
PPC_OP(addeo)
594
{
595
    do_addeo();
596
    RETURN();
597
}
598

    
599
/* add immediate */
600
PPC_OP(addi)
601
{
602
    T0 += PARAM(1);
603
    RETURN();
604
}
605

    
606
/* add immediate carrying */
607
PPC_OP(addic)
608
{
609
    T1 = T0;
610
    T0 += PARAM(1);
611
    if (T0 < T1) {
612
        xer_ca = 1;
613
    } else {
614
        xer_ca = 0;
615
    }
616
    RETURN();
617
}
618

    
619
/* add to minus one extended */
620
PPC_OP(addme)
621
{
622
    T1 = T0;
623
    T0 += xer_ca + (-1);
624
    if (T1 != 0)
625
        xer_ca = 1;
626
    RETURN();
627
}
628

    
629
void do_addmeo (void);
630
void op_addmeo (void)
631
{
632
    do_addmeo();
633
    RETURN();
634
}
635

    
636
/* add to zero extended */
637
PPC_OP(addze)
638
{
639
    T1 = T0;
640
    T0 += xer_ca;
641
    if (T0 < T1) {
642
        xer_ca = 1;
643
    } else {
644
        xer_ca = 0;
645
    }
646
    RETURN();
647
}
648

    
649
void do_addzeo (void);
650
void op_addzeo (void)
651
{
652
    do_addzeo();
653
    RETURN();
654
}
655

    
656
/* divide word */
657
PPC_OP(divw)
658
{
659
    if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
660
        T0 = (int32_t)((-1) * (T0 >> 31));
661
    } else {
662
        T0 = (Ts0 / Ts1);
663
    }
664
    RETURN();
665
}
666

    
667
void do_divwo (void);
668
void op_divwo (void)
669
{
670
    do_divwo();
671
    RETURN();
672
}
673

    
674
/* divide word unsigned */
675
PPC_OP(divwu)
676
{
677
    if (T1 == 0) {
678
        T0 = 0;
679
    } else {
680
        T0 /= T1;
681
    }
682
    RETURN();
683
}
684

    
685
void do_divwuo (void);
686
void op_divwuo (void)
687
{
688
    do_divwuo();
689
    RETURN();
690
}
691

    
692
/* multiply high word */
693
PPC_OP(mulhw)
694
{
695
    T0 = ((int64_t)Ts0 * (int64_t)Ts1) >> 32;
696
    RETURN();
697
}
698

    
699
/* multiply high word unsigned */
700
PPC_OP(mulhwu)
701
{
702
    T0 = ((uint64_t)T0 * (uint64_t)T1) >> 32;
703
    RETURN();
704
}
705

    
706
/* multiply low immediate */
707
PPC_OP(mulli)
708
{
709
    T0 = (Ts0 * SPARAM(1));
710
    RETURN();
711
}
712

    
713
/* multiply low word */
714
PPC_OP(mullw)
715
{
716
    T0 *= T1;
717
    RETURN();
718
}
719

    
720
void do_mullwo (void);
721
void op_mullwo (void)
722
{
723
    do_mullwo();
724
    RETURN();
725
}
726

    
727
/* negate */
728
PPC_OP(neg)
729
{
730
    if (T0 != 0x80000000) {
731
        T0 = -Ts0;
732
    }
733
    RETURN();
734
}
735

    
736
void do_nego (void);
737
void op_nego (void)
738
{
739
    do_nego();
740
    RETURN();
741
}
742

    
743
/* substract from */
744
PPC_OP(subf)
745
{
746
    T0 = T1 - T0;
747
    RETURN();
748
}
749

    
750
void do_subfo (void);
751
void op_subfo (void)
752
{
753
    do_subfo();
754
    RETURN();
755
}
756

    
757
/* substract from carrying */
758
PPC_OP(subfc)
759
{
760
    T0 = T1 - T0;
761
    if (T0 <= T1) {
762
        xer_ca = 1;
763
    } else {
764
        xer_ca = 0;
765
    }
766
    RETURN();
767
}
768

    
769
void do_subfco (void);
770
void op_subfco (void)
771
{
772
    do_subfco();
773
    RETURN();
774
}
775

    
776
/* substract from extended */
777
void do_subfe (void);
778
void op_subfe (void)
779
{
780
    do_subfe();
781
    RETURN();
782
}
783

    
784
void do_subfeo (void);
785
PPC_OP(subfeo)
786
{
787
    do_subfeo();
788
    RETURN();
789
}
790

    
791
/* substract from immediate carrying */
792
PPC_OP(subfic)
793
{
794
    T0 = PARAM(1) + ~T0 + 1;
795
    if (T0 <= PARAM(1)) {
796
        xer_ca = 1;
797
    } else {
798
        xer_ca = 0;
799
    }
800
    RETURN();
801
}
802

    
803
/* substract from minus one extended */
804
PPC_OP(subfme)
805
{
806
    T0 = ~T0 + xer_ca - 1;
807

    
808
    if (T0 != -1)
809
        xer_ca = 1;
810
    RETURN();
811
}
812

    
813
void do_subfmeo (void);
814
void op_subfmeo (void)
815
{
816
    do_subfmeo();
817
    RETURN();
818
}
819

    
820
/* substract from zero extended */
821
PPC_OP(subfze)
822
{
823
    T1 = ~T0;
824
    T0 = T1 + xer_ca;
825
    if (T0 < T1) {
826
        xer_ca = 1;
827
    } else {
828
        xer_ca = 0;
829
    }
830
    RETURN();
831
}
832

    
833
void do_subfzeo (void);
834
void op_subfzeo (void)
835
{
836
    do_subfzeo();
837
    RETURN();
838
}
839

    
840
/***                           Integer comparison                          ***/
841
/* compare */
842
PPC_OP(cmp)
843
{
844
    if (Ts0 < Ts1) {
845
        T0 = 0x08;
846
    } else if (Ts0 > Ts1) {
847
        T0 = 0x04;
848
    } else {
849
        T0 = 0x02;
850
    }
851
    RETURN();
852
}
853

    
854
/* compare immediate */
855
PPC_OP(cmpi)
856
{
857
    if (Ts0 < SPARAM(1)) {
858
        T0 = 0x08;
859
    } else if (Ts0 > SPARAM(1)) {
860
        T0 = 0x04;
861
    } else {
862
        T0 = 0x02;
863
    }
864
    RETURN();
865
}
866

    
867
/* compare logical */
868
PPC_OP(cmpl)
869
{
870
    if (T0 < T1) {
871
        T0 = 0x08;
872
    } else if (T0 > T1) {
873
        T0 = 0x04;
874
    } else {
875
        T0 = 0x02;
876
    }
877
    RETURN();
878
}
879

    
880
/* compare logical immediate */
881
PPC_OP(cmpli)
882
{
883
    if (T0 < PARAM(1)) {
884
        T0 = 0x08;
885
    } else if (T0 > PARAM(1)) {
886
        T0 = 0x04;
887
    } else {
888
        T0 = 0x02;
889
    }
890
    RETURN();
891
}
892

    
893
/***                            Integer logical                            ***/
894
/* and */
895
PPC_OP(and)
896
{
897
    T0 &= T1;
898
    RETURN();
899
}
900

    
901
/* andc */
902
PPC_OP(andc)
903
{
904
    T0 &= ~T1;
905
    RETURN();
906
}
907

    
908
/* andi. */
909
PPC_OP(andi_)
910
{
911
    T0 &= PARAM(1);
912
    RETURN();
913
}
914

    
915
/* count leading zero */
916
PPC_OP(cntlzw)
917
{
918
    T1 = T0;
919
    for (T0 = 32; T1 > 0; T0--)
920
        T1 = T1 >> 1;
921
    RETURN();
922
}
923

    
924
/* eqv */
925
PPC_OP(eqv)
926
{
927
    T0 = ~(T0 ^ T1);
928
    RETURN();
929
}
930

    
931
/* extend sign byte */
932
PPC_OP(extsb)
933
{
934
    T0 = (int32_t)((int8_t)(Ts0));
935
    RETURN();
936
}
937

    
938
/* extend sign half word */
939
PPC_OP(extsh)
940
{
941
    T0 = (int32_t)((int16_t)(Ts0));
942
    RETURN();
943
}
944

    
945
/* nand */
946
PPC_OP(nand)
947
{
948
    T0 = ~(T0 & T1);
949
    RETURN();
950
}
951

    
952
/* nor */
953
PPC_OP(nor)
954
{
955
    T0 = ~(T0 | T1);
956
    RETURN();
957
}
958

    
959
/* or */
960
PPC_OP(or)
961
{
962
    T0 |= T1;
963
    RETURN();
964
}
965

    
966
/* orc */
967
PPC_OP(orc)
968
{
969
    T0 |= ~T1;
970
    RETURN();
971
}
972

    
973
/* ori */
974
PPC_OP(ori)
975
{
976
    T0 |= PARAM(1);
977
    RETURN();
978
}
979

    
980
/* xor */
981
PPC_OP(xor)
982
{
983
    T0 ^= T1;
984
    RETURN();
985
}
986

    
987
/* xori */
988
PPC_OP(xori)
989
{
990
    T0 ^= PARAM(1);
991
    RETURN();
992
}
993

    
994
/***                             Integer rotate                            ***/
995
/* rotate left word immediate then mask insert */
996
PPC_OP(rlwimi)
997
{
998
    T0 = (rotl(T0, PARAM(1)) & PARAM(2)) | (T1 & PARAM(3));
999
    RETURN();
1000
}
1001

    
1002
/* rotate left immediate then and with mask insert */
1003
PPC_OP(rotlwi)
1004
{
1005
    T0 = rotl(T0, PARAM(1));
1006
    RETURN();
1007
}
1008

    
1009
PPC_OP(slwi)
1010
{
1011
    T0 = T0 << PARAM(1);
1012
    RETURN();
1013
}
1014

    
1015
PPC_OP(srwi)
1016
{
1017
    T0 = T0 >> PARAM(1);
1018
    RETURN();
1019
}
1020

    
1021
/* rotate left word then and with mask insert */
1022
PPC_OP(rlwinm)
1023
{
1024
    T0 = rotl(T0, PARAM(1)) & PARAM(2);
1025
    RETURN();
1026
}
1027

    
1028
PPC_OP(rotl)
1029
{
1030
    T0 = rotl(T0, T1);
1031
    RETURN();
1032
}
1033

    
1034
PPC_OP(rlwnm)
1035
{
1036
    T0 = rotl(T0, T1) & PARAM(1);
1037
    RETURN();
1038
}
1039

    
1040
/***                             Integer shift                             ***/
1041
/* shift left word */
1042
PPC_OP(slw)
1043
{
1044
    if (T1 & 0x20) {
1045
        T0 = 0;
1046
    } else {
1047
        T0 = T0 << T1;
1048
    }
1049
    RETURN();
1050
}
1051

    
1052
/* shift right algebraic word */
1053
void op_sraw (void)
1054
{
1055
    do_sraw();
1056
    RETURN();
1057
}
1058

    
1059
/* shift right algebraic word immediate */
1060
PPC_OP(srawi)
1061
{
1062
    T1 = T0;
1063
    T0 = (Ts0 >> PARAM(1));
1064
    if (Ts1 < 0 && (Ts1 & PARAM(2)) != 0) {
1065
        xer_ca = 1;
1066
    } else {
1067
        xer_ca = 0;
1068
    }
1069
    RETURN();
1070
}
1071

    
1072
/* shift right word */
1073
PPC_OP(srw)
1074
{
1075
    if (T1 & 0x20) {
1076
        T0 = 0;
1077
    } else {
1078
        T0 = T0 >> T1;
1079
    }
1080
    RETURN();
1081
}
1082

    
1083
/***                       Floating-Point arithmetic                       ***/
1084
/* fadd - fadd. */
1085
PPC_OP(fadd)
1086
{
1087
    FT0 += FT1;
1088
    RETURN();
1089
}
1090

    
1091
/* fsub - fsub. */
1092
PPC_OP(fsub)
1093
{
1094
    FT0 -= FT1;
1095
    RETURN();
1096
}
1097

    
1098
/* fmul - fmul. */
1099
PPC_OP(fmul)
1100
{
1101
    FT0 *= FT1;
1102
    RETURN();
1103
}
1104

    
1105
/* fdiv - fdiv. */
1106
PPC_OP(fdiv)
1107
{
1108
    FT0 = float64_div(FT0, FT1, &env->fp_status);
1109
    RETURN();
1110
}
1111

    
1112
/* fsqrt - fsqrt. */
1113
PPC_OP(fsqrt)
1114
{
1115
    do_fsqrt();
1116
    RETURN();
1117
}
1118

    
1119
/* fres - fres. */
1120
PPC_OP(fres)
1121
{
1122
    do_fres();
1123
    RETURN();
1124
}
1125

    
1126
/* frsqrte  - frsqrte. */
1127
PPC_OP(frsqrte)
1128
{
1129
    do_frsqrte();
1130
    RETURN();
1131
}
1132

    
1133
/* fsel - fsel. */
1134
PPC_OP(fsel)
1135
{
1136
    do_fsel();
1137
    RETURN();
1138
}
1139

    
1140
/***                     Floating-Point multiply-and-add                   ***/
1141
/* fmadd - fmadd. */
1142
PPC_OP(fmadd)
1143
{
1144
    FT0 = (FT0 * FT1) + FT2;
1145
    RETURN();
1146
}
1147

    
1148
/* fmsub - fmsub. */
1149
PPC_OP(fmsub)
1150
{
1151
    FT0 = (FT0 * FT1) - FT2;
1152
    RETURN();
1153
}
1154

    
1155
/* fnmadd - fnmadd. - fnmadds - fnmadds. */
1156
PPC_OP(fnmadd)
1157
{
1158
    do_fnmadd();
1159
    RETURN();
1160
}
1161

    
1162
/* fnmsub - fnmsub. */
1163
PPC_OP(fnmsub)
1164
{
1165
    do_fnmsub();
1166
    RETURN();
1167
}
1168

    
1169
/***                     Floating-Point round & convert                    ***/
1170
/* frsp - frsp. */
1171
PPC_OP(frsp)
1172
{
1173
    FT0 = (float)FT0;
1174
    RETURN();
1175
}
1176

    
1177
/* fctiw - fctiw. */
1178
PPC_OP(fctiw)
1179
{
1180
    do_fctiw();
1181
    RETURN();
1182
}
1183

    
1184
/* fctiwz - fctiwz. */
1185
PPC_OP(fctiwz)
1186
{
1187
    do_fctiwz();
1188
    RETURN();
1189
}
1190

    
1191

    
1192
/***                         Floating-Point compare                        ***/
1193
/* fcmpu */
1194
PPC_OP(fcmpu)
1195
{
1196
    do_fcmpu();
1197
    RETURN();
1198
}
1199

    
1200
/* fcmpo */
1201
PPC_OP(fcmpo)
1202
{
1203
    do_fcmpo();
1204
    RETURN();
1205
}
1206

    
1207
/***                         Floating-point move                           ***/
1208
/* fabs */
1209
PPC_OP(fabs)
1210
{
1211
    FT0 = float64_abs(FT0);
1212
    RETURN();
1213
}
1214

    
1215
/* fnabs */
1216
PPC_OP(fnabs)
1217
{
1218
    FT0 = float64_abs(FT0);
1219
    FT0 = float64_chs(FT0);
1220
    RETURN();
1221
}
1222

    
1223
/* fneg */
1224
PPC_OP(fneg)
1225
{
1226
    FT0 = float64_chs(FT0);
1227
    RETURN();
1228
}
1229

    
1230
/* Load and store */
1231
#define MEMSUFFIX _raw
1232
#include "op_mem.h"
1233
#if !defined(CONFIG_USER_ONLY)
1234
#define MEMSUFFIX _user
1235
#include "op_mem.h"
1236

    
1237
#define MEMSUFFIX _kernel
1238
#include "op_mem.h"
1239
#endif
1240

    
1241
/* Special op to check and maybe clear reservation */
1242
PPC_OP(check_reservation)
1243
{
1244
    if ((uint32_t)env->reserve == (uint32_t)(T0 & ~0x00000003))
1245
        env->reserve = -1;
1246
    RETURN();
1247
}
1248

    
1249
/* Return from interrupt */
1250
void do_rfi (void);
1251
void op_rfi (void)
1252
{
1253
    do_rfi();
1254
    RETURN();
1255
}
1256

    
1257
/* Trap word */
1258
void do_tw (uint32_t cmp, int flags);
1259
void op_tw (void)
1260
{
1261
    do_tw(T1, PARAM(1));
1262
    RETURN();
1263
}
1264

    
1265
void op_twi (void)
1266
{
1267
    do_tw(PARAM(1), PARAM(2));
1268
    RETURN();
1269
}
1270

    
1271
/* Instruction cache block invalidate */
1272
PPC_OP(icbi)
1273
{
1274
    do_icbi();
1275
    RETURN();
1276
}
1277

    
1278
/* tlbia */
1279
PPC_OP(tlbia)
1280
{
1281
    do_tlbia();
1282
    RETURN();
1283
}
1284

    
1285
/* tlbie */
1286
PPC_OP(tlbie)
1287
{
1288
    do_tlbie();
1289
    RETURN();
1290
}
1291

    
1292
void op_store_pir (void)
1293
{
1294
    env->spr[SPR_PIR] = T0 & 0x0000000FUL;
1295
    RETURN();
1296
}