Statistics
| Branch: | Revision:

root / target-ppc / op.c @ c53be334

History | View | Annotate | Download (16.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(goto_tb0)
455
{
456
    GOTO_TB(op_goto_tb0, PARAM1, 0);
457
}
458

    
459
PPC_OP(goto_tb1)
460
{
461
    GOTO_TB(op_goto_tb1, PARAM1, 1);
462
}
463

    
464
PPC_OP(b_T1)
465
{
466
    regs->nip = T1 & ~3;
467
}
468

    
469
PPC_OP(jz_T0)
470
{
471
    if (!T0)
472
        GOTO_LABEL_PARAM(1);
473
    RETURN();
474
}
475

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

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

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

    
496
/* tests with result in T0 */
497

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

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

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

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

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

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

    
528
PPC_OP(test_true)
529
{
530
    T0 = (T0 & PARAM(1));
531
}
532

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

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

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

    
553
void do_addo (void);
554
void op_addo (void)
555
{
556
    do_addo();
557
    RETURN();
558
}
559

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

    
573
void do_addco (void);
574
void op_addco (void)
575
{
576
    do_addco();
577
    RETURN();
578
}
579

    
580
/* add extended */
581
void do_adde (void);
582
void op_adde (void)
583
{
584
    do_adde();
585
}
586

    
587
void do_addeo (void);
588
PPC_OP(addeo)
589
{
590
    do_addeo();
591
    RETURN();
592
}
593

    
594
/* add immediate */
595
PPC_OP(addi)
596
{
597
    T0 += PARAM(1);
598
    RETURN();
599
}
600

    
601
/* add immediate carrying */
602
PPC_OP(addic)
603
{
604
    T1 = T0;
605
    T0 += PARAM(1);
606
    if (T0 < T1) {
607
        xer_ca = 1;
608
    } else {
609
        xer_ca = 0;
610
    }
611
    RETURN();
612
}
613

    
614
/* add to minus one extended */
615
PPC_OP(addme)
616
{
617
    T1 = T0;
618
    T0 += xer_ca + (-1);
619
    if (T1 != 0)
620
        xer_ca = 1;
621
    RETURN();
622
}
623

    
624
void do_addmeo (void);
625
void op_addmeo (void)
626
{
627
    do_addmeo();
628
    RETURN();
629
}
630

    
631
/* add to zero extended */
632
PPC_OP(addze)
633
{
634
    T1 = T0;
635
    T0 += xer_ca;
636
    if (T0 < T1) {
637
        xer_ca = 1;
638
    } else {
639
        xer_ca = 0;
640
    }
641
    RETURN();
642
}
643

    
644
void do_addzeo (void);
645
void op_addzeo (void)
646
{
647
    do_addzeo();
648
    RETURN();
649
}
650

    
651
/* divide word */
652
PPC_OP(divw)
653
{
654
    if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
655
        T0 = (int32_t)((-1) * (T0 >> 31));
656
    } else {
657
        T0 = (Ts0 / Ts1);
658
    }
659
    RETURN();
660
}
661

    
662
void do_divwo (void);
663
void op_divwo (void)
664
{
665
    do_divwo();
666
    RETURN();
667
}
668

    
669
/* divide word unsigned */
670
PPC_OP(divwu)
671
{
672
    if (T1 == 0) {
673
        T0 = 0;
674
    } else {
675
        T0 /= T1;
676
    }
677
    RETURN();
678
}
679

    
680
void do_divwuo (void);
681
void op_divwuo (void)
682
{
683
    do_divwuo();
684
    RETURN();
685
}
686

    
687
/* multiply high word */
688
PPC_OP(mulhw)
689
{
690
    T0 = ((int64_t)Ts0 * (int64_t)Ts1) >> 32;
691
    RETURN();
692
}
693

    
694
/* multiply high word unsigned */
695
PPC_OP(mulhwu)
696
{
697
    T0 = ((uint64_t)T0 * (uint64_t)T1) >> 32;
698
    RETURN();
699
}
700

    
701
/* multiply low immediate */
702
PPC_OP(mulli)
703
{
704
    T0 = (Ts0 * SPARAM(1));
705
    RETURN();
706
}
707

    
708
/* multiply low word */
709
PPC_OP(mullw)
710
{
711
    T0 *= T1;
712
    RETURN();
713
}
714

    
715
void do_mullwo (void);
716
void op_mullwo (void)
717
{
718
    do_mullwo();
719
    RETURN();
720
}
721

    
722
/* negate */
723
PPC_OP(neg)
724
{
725
    if (T0 != 0x80000000) {
726
        T0 = -Ts0;
727
    }
728
    RETURN();
729
}
730

    
731
void do_nego (void);
732
void op_nego (void)
733
{
734
    do_nego();
735
    RETURN();
736
}
737

    
738
/* substract from */
739
PPC_OP(subf)
740
{
741
    T0 = T1 - T0;
742
    RETURN();
743
}
744

    
745
void do_subfo (void);
746
void op_subfo (void)
747
{
748
    do_subfo();
749
    RETURN();
750
}
751

    
752
/* substract from carrying */
753
PPC_OP(subfc)
754
{
755
    T0 = T1 - T0;
756
    if (T0 <= T1) {
757
        xer_ca = 1;
758
    } else {
759
        xer_ca = 0;
760
    }
761
    RETURN();
762
}
763

    
764
void do_subfco (void);
765
void op_subfco (void)
766
{
767
    do_subfco();
768
    RETURN();
769
}
770

    
771
/* substract from extended */
772
void do_subfe (void);
773
void op_subfe (void)
774
{
775
    do_subfe();
776
    RETURN();
777
}
778

    
779
void do_subfeo (void);
780
PPC_OP(subfeo)
781
{
782
    do_subfeo();
783
    RETURN();
784
}
785

    
786
/* substract from immediate carrying */
787
PPC_OP(subfic)
788
{
789
    T0 = PARAM(1) + ~T0 + 1;
790
    if (T0 <= PARAM(1)) {
791
        xer_ca = 1;
792
    } else {
793
        xer_ca = 0;
794
    }
795
    RETURN();
796
}
797

    
798
/* substract from minus one extended */
799
PPC_OP(subfme)
800
{
801
    T0 = ~T0 + xer_ca - 1;
802

    
803
    if (T0 != -1)
804
        xer_ca = 1;
805
    RETURN();
806
}
807

    
808
void do_subfmeo (void);
809
void op_subfmeo (void)
810
{
811
    do_subfmeo();
812
    RETURN();
813
}
814

    
815
/* substract from zero extended */
816
PPC_OP(subfze)
817
{
818
    T1 = ~T0;
819
    T0 = T1 + xer_ca;
820
    if (T0 < T1) {
821
        xer_ca = 1;
822
    } else {
823
        xer_ca = 0;
824
    }
825
    RETURN();
826
}
827

    
828
void do_subfzeo (void);
829
void op_subfzeo (void)
830
{
831
    do_subfzeo();
832
    RETURN();
833
}
834

    
835
/***                           Integer comparison                          ***/
836
/* compare */
837
PPC_OP(cmp)
838
{
839
    if (Ts0 < Ts1) {
840
        T0 = 0x08;
841
    } else if (Ts0 > Ts1) {
842
        T0 = 0x04;
843
    } else {
844
        T0 = 0x02;
845
    }
846
    RETURN();
847
}
848

    
849
/* compare immediate */
850
PPC_OP(cmpi)
851
{
852
    if (Ts0 < SPARAM(1)) {
853
        T0 = 0x08;
854
    } else if (Ts0 > SPARAM(1)) {
855
        T0 = 0x04;
856
    } else {
857
        T0 = 0x02;
858
    }
859
    RETURN();
860
}
861

    
862
/* compare logical */
863
PPC_OP(cmpl)
864
{
865
    if (T0 < T1) {
866
        T0 = 0x08;
867
    } else if (T0 > T1) {
868
        T0 = 0x04;
869
    } else {
870
        T0 = 0x02;
871
    }
872
    RETURN();
873
}
874

    
875
/* compare logical immediate */
876
PPC_OP(cmpli)
877
{
878
    if (T0 < PARAM(1)) {
879
        T0 = 0x08;
880
    } else if (T0 > PARAM(1)) {
881
        T0 = 0x04;
882
    } else {
883
        T0 = 0x02;
884
    }
885
    RETURN();
886
}
887

    
888
/***                            Integer logical                            ***/
889
/* and */
890
PPC_OP(and)
891
{
892
    T0 &= T1;
893
    RETURN();
894
}
895

    
896
/* andc */
897
PPC_OP(andc)
898
{
899
    T0 &= ~T1;
900
    RETURN();
901
}
902

    
903
/* andi. */
904
PPC_OP(andi_)
905
{
906
    T0 &= PARAM(1);
907
    RETURN();
908
}
909

    
910
/* count leading zero */
911
PPC_OP(cntlzw)
912
{
913
    T1 = T0;
914
    for (T0 = 32; T1 > 0; T0--)
915
        T1 = T1 >> 1;
916
    RETURN();
917
}
918

    
919
/* eqv */
920
PPC_OP(eqv)
921
{
922
    T0 = ~(T0 ^ T1);
923
    RETURN();
924
}
925

    
926
/* extend sign byte */
927
PPC_OP(extsb)
928
{
929
    T0 = (int32_t)((int8_t)(Ts0));
930
    RETURN();
931
}
932

    
933
/* extend sign half word */
934
PPC_OP(extsh)
935
{
936
    T0 = (int32_t)((int16_t)(Ts0));
937
    RETURN();
938
}
939

    
940
/* nand */
941
PPC_OP(nand)
942
{
943
    T0 = ~(T0 & T1);
944
    RETURN();
945
}
946

    
947
/* nor */
948
PPC_OP(nor)
949
{
950
    T0 = ~(T0 | T1);
951
    RETURN();
952
}
953

    
954
/* or */
955
PPC_OP(or)
956
{
957
    T0 |= T1;
958
    RETURN();
959
}
960

    
961
/* orc */
962
PPC_OP(orc)
963
{
964
    T0 |= ~T1;
965
    RETURN();
966
}
967

    
968
/* ori */
969
PPC_OP(ori)
970
{
971
    T0 |= PARAM(1);
972
    RETURN();
973
}
974

    
975
/* xor */
976
PPC_OP(xor)
977
{
978
    T0 ^= T1;
979
    RETURN();
980
}
981

    
982
/* xori */
983
PPC_OP(xori)
984
{
985
    T0 ^= PARAM(1);
986
    RETURN();
987
}
988

    
989
/***                             Integer rotate                            ***/
990
/* rotate left word immediate then mask insert */
991
PPC_OP(rlwimi)
992
{
993
    T0 = (rotl(T0, PARAM(1)) & PARAM(2)) | (T1 & PARAM(3));
994
    RETURN();
995
}
996

    
997
/* rotate left immediate then and with mask insert */
998
PPC_OP(rotlwi)
999
{
1000
    T0 = rotl(T0, PARAM(1));
1001
    RETURN();
1002
}
1003

    
1004
PPC_OP(slwi)
1005
{
1006
    T0 = T0 << PARAM(1);
1007
    RETURN();
1008
}
1009

    
1010
PPC_OP(srwi)
1011
{
1012
    T0 = T0 >> PARAM(1);
1013
    RETURN();
1014
}
1015

    
1016
/* rotate left word then and with mask insert */
1017
PPC_OP(rlwinm)
1018
{
1019
    T0 = rotl(T0, PARAM(1)) & PARAM(2);
1020
    RETURN();
1021
}
1022

    
1023
PPC_OP(rotl)
1024
{
1025
    T0 = rotl(T0, T1);
1026
    RETURN();
1027
}
1028

    
1029
PPC_OP(rlwnm)
1030
{
1031
    T0 = rotl(T0, T1) & PARAM(1);
1032
    RETURN();
1033
}
1034

    
1035
/***                             Integer shift                             ***/
1036
/* shift left word */
1037
PPC_OP(slw)
1038
{
1039
    if (T1 & 0x20) {
1040
        T0 = 0;
1041
    } else {
1042
        T0 = T0 << T1;
1043
    }
1044
    RETURN();
1045
}
1046

    
1047
/* shift right algebraic word */
1048
void op_sraw (void)
1049
{
1050
    do_sraw();
1051
    RETURN();
1052
}
1053

    
1054
/* shift right algebraic word immediate */
1055
PPC_OP(srawi)
1056
{
1057
    T1 = T0;
1058
    T0 = (Ts0 >> PARAM(1));
1059
    if (Ts1 < 0 && (Ts1 & PARAM(2)) != 0) {
1060
        xer_ca = 1;
1061
    } else {
1062
        xer_ca = 0;
1063
    }
1064
    RETURN();
1065
}
1066

    
1067
/* shift right word */
1068
PPC_OP(srw)
1069
{
1070
    if (T1 & 0x20) {
1071
        T0 = 0;
1072
    } else {
1073
        T0 = T0 >> T1;
1074
    }
1075
    RETURN();
1076
}
1077

    
1078
/***                       Floating-Point arithmetic                       ***/
1079
/* fadd - fadd. */
1080
PPC_OP(fadd)
1081
{
1082
    FT0 += FT1;
1083
    RETURN();
1084
}
1085

    
1086
/* fsub - fsub. */
1087
PPC_OP(fsub)
1088
{
1089
    FT0 -= FT1;
1090
    RETURN();
1091
}
1092

    
1093
/* fmul - fmul. */
1094
PPC_OP(fmul)
1095
{
1096
    FT0 *= FT1;
1097
    RETURN();
1098
}
1099

    
1100
/* fdiv - fdiv. */
1101
PPC_OP(fdiv)
1102
{
1103
    FT0 = float64_div(FT0, FT1, &env->fp_status);
1104
    RETURN();
1105
}
1106

    
1107
/* fsqrt - fsqrt. */
1108
PPC_OP(fsqrt)
1109
{
1110
    do_fsqrt();
1111
    RETURN();
1112
}
1113

    
1114
/* fres - fres. */
1115
PPC_OP(fres)
1116
{
1117
    do_fres();
1118
    RETURN();
1119
}
1120

    
1121
/* frsqrte  - frsqrte. */
1122
PPC_OP(frsqrte)
1123
{
1124
    do_frsqrte();
1125
    RETURN();
1126
}
1127

    
1128
/* fsel - fsel. */
1129
PPC_OP(fsel)
1130
{
1131
    do_fsel();
1132
    RETURN();
1133
}
1134

    
1135
/***                     Floating-Point multiply-and-add                   ***/
1136
/* fmadd - fmadd. */
1137
PPC_OP(fmadd)
1138
{
1139
    FT0 = (FT0 * FT1) + FT2;
1140
    RETURN();
1141
}
1142

    
1143
/* fmsub - fmsub. */
1144
PPC_OP(fmsub)
1145
{
1146
    FT0 = (FT0 * FT1) - FT2;
1147
    RETURN();
1148
}
1149

    
1150
/* fnmadd - fnmadd. - fnmadds - fnmadds. */
1151
PPC_OP(fnmadd)
1152
{
1153
    do_fnmadd();
1154
    RETURN();
1155
}
1156

    
1157
/* fnmsub - fnmsub. */
1158
PPC_OP(fnmsub)
1159
{
1160
    do_fnmsub();
1161
    RETURN();
1162
}
1163

    
1164
/***                     Floating-Point round & convert                    ***/
1165
/* frsp - frsp. */
1166
PPC_OP(frsp)
1167
{
1168
    FT0 = (float)FT0;
1169
    RETURN();
1170
}
1171

    
1172
/* fctiw - fctiw. */
1173
PPC_OP(fctiw)
1174
{
1175
    do_fctiw();
1176
    RETURN();
1177
}
1178

    
1179
/* fctiwz - fctiwz. */
1180
PPC_OP(fctiwz)
1181
{
1182
    do_fctiwz();
1183
    RETURN();
1184
}
1185

    
1186

    
1187
/***                         Floating-Point compare                        ***/
1188
/* fcmpu */
1189
PPC_OP(fcmpu)
1190
{
1191
    do_fcmpu();
1192
    RETURN();
1193
}
1194

    
1195
/* fcmpo */
1196
PPC_OP(fcmpo)
1197
{
1198
    do_fcmpo();
1199
    RETURN();
1200
}
1201

    
1202
/***                         Floating-point move                           ***/
1203
/* fabs */
1204
PPC_OP(fabs)
1205
{
1206
    FT0 = float64_abs(FT0);
1207
    RETURN();
1208
}
1209

    
1210
/* fnabs */
1211
PPC_OP(fnabs)
1212
{
1213
    FT0 = float64_abs(FT0);
1214
    FT0 = float64_chs(FT0);
1215
    RETURN();
1216
}
1217

    
1218
/* fneg */
1219
PPC_OP(fneg)
1220
{
1221
    FT0 = float64_chs(FT0);
1222
    RETURN();
1223
}
1224

    
1225
/* Load and store */
1226
#define MEMSUFFIX _raw
1227
#include "op_mem.h"
1228
#if !defined(CONFIG_USER_ONLY)
1229
#define MEMSUFFIX _user
1230
#include "op_mem.h"
1231

    
1232
#define MEMSUFFIX _kernel
1233
#include "op_mem.h"
1234
#endif
1235

    
1236
/* Special op to check and maybe clear reservation */
1237
PPC_OP(check_reservation)
1238
{
1239
    if ((uint32_t)env->reserve == (uint32_t)(T0 & ~0x00000003))
1240
        env->reserve = -1;
1241
    RETURN();
1242
}
1243

    
1244
/* Return from interrupt */
1245
void do_rfi (void);
1246
void op_rfi (void)
1247
{
1248
    do_rfi();
1249
    RETURN();
1250
}
1251

    
1252
/* Trap word */
1253
void do_tw (uint32_t cmp, int flags);
1254
void op_tw (void)
1255
{
1256
    do_tw(T1, PARAM(1));
1257
    RETURN();
1258
}
1259

    
1260
void op_twi (void)
1261
{
1262
    do_tw(PARAM(1), PARAM(2));
1263
    RETURN();
1264
}
1265

    
1266
/* Instruction cache block invalidate */
1267
PPC_OP(icbi)
1268
{
1269
    do_icbi();
1270
    RETURN();
1271
}
1272

    
1273
/* tlbia */
1274
PPC_OP(tlbia)
1275
{
1276
    do_tlbia();
1277
    RETURN();
1278
}
1279

    
1280
/* tlbie */
1281
PPC_OP(tlbie)
1282
{
1283
    do_tlbie();
1284
    RETURN();
1285
}
1286

    
1287
void op_store_pir (void)
1288
{
1289
    env->spr[SPR_PIR] = T0 & 0x0000000FUL;
1290
    RETURN();
1291
}