Statistics
| Branch: | Revision:

root / target-ppc / op.c @ 24741ef3

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(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
void do_addo (void);
552
void op_addo (void)
553
{
554
    do_addo();
555
    RETURN();
556
}
557

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

    
571
void do_addco (void);
572
void op_addco (void)
573
{
574
    do_addco();
575
    RETURN();
576
}
577

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

    
585
void do_addeo (void);
586
PPC_OP(addeo)
587
{
588
    do_addeo();
589
    RETURN();
590
}
591

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

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

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

    
622
void do_addmeo (void);
623
void op_addmeo (void)
624
{
625
    do_addmeo();
626
    RETURN();
627
}
628

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

    
642
void do_addzeo (void);
643
void op_addzeo (void)
644
{
645
    do_addzeo();
646
    RETURN();
647
}
648

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

    
660
void do_divwo (void);
661
void op_divwo (void)
662
{
663
    do_divwo();
664
    RETURN();
665
}
666

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

    
678
void do_divwuo (void);
679
void op_divwuo (void)
680
{
681
    do_divwuo();
682
    RETURN();
683
}
684

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

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

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

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

    
713
void do_mullwo (void);
714
void op_mullwo (void)
715
{
716
    do_mullwo();
717
    RETURN();
718
}
719

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

    
729
void do_nego (void);
730
void op_nego (void)
731
{
732
    do_nego();
733
    RETURN();
734
}
735

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

    
743
void do_subfo (void);
744
void op_subfo (void)
745
{
746
    do_subfo();
747
    RETURN();
748
}
749

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

    
762
void do_subfco (void);
763
void op_subfco (void)
764
{
765
    do_subfco();
766
    RETURN();
767
}
768

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

    
777
void do_subfeo (void);
778
PPC_OP(subfeo)
779
{
780
    do_subfeo();
781
    RETURN();
782
}
783

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

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

    
801
    if (T0 != -1)
802
        xer_ca = 1;
803
    RETURN();
804
}
805

    
806
void do_subfmeo (void);
807
void op_subfmeo (void)
808
{
809
    do_subfmeo();
810
    RETURN();
811
}
812

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

    
826
void do_subfzeo (void);
827
void op_subfzeo (void)
828
{
829
    do_subfzeo();
830
    RETURN();
831
}
832

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1184

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

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

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

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

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

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

    
1230
#define MEMSUFFIX _kernel
1231
#include "op_mem.h"
1232
#endif
1233

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

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

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

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

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

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

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

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