Statistics
| Branch: | Revision:

root / target-ppc / op.c @ 07ad1b93

History | View | Annotate | Download (25.4 kB)

1
/*
2
 *  PPC emulation micro-operations for qemu.
3
 * 
4
 *  Copyright (c) 2003 Jocelyn Mayer
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 */
20

    
21
#include "config.h"
22
#include "exec.h"
23

    
24
#define regs (env)
25
#define Ts0 (int32_t)T0
26
#define Ts1 (int32_t)T1
27
#define Ts2 (int32_t)T2
28

    
29
#define FT0 (env->ft0)
30

    
31
#define PPC_OP(name) void op_##name(void)
32

    
33
#define REG 0
34
#include "op_template.h"
35

    
36
#define REG 1
37
#include "op_template.h"
38

    
39
#define REG 2
40
#include "op_template.h"
41

    
42
#define REG 3
43
#include "op_template.h"
44

    
45
#define REG 4
46
#include "op_template.h"
47

    
48
#define REG 5
49
#include "op_template.h"
50

    
51
#define REG 6
52
#include "op_template.h"
53

    
54
#define REG 7
55
#include "op_template.h"
56

    
57
#define REG 8
58
#include "op_template.h"
59

    
60
#define REG 9
61
#include "op_template.h"
62

    
63
#define REG 10
64
#include "op_template.h"
65

    
66
#define REG 11
67
#include "op_template.h"
68

    
69
#define REG 12
70
#include "op_template.h"
71

    
72
#define REG 13
73
#include "op_template.h"
74

    
75
#define REG 14
76
#include "op_template.h"
77

    
78
#define REG 15
79
#include "op_template.h"
80

    
81
#define REG 16
82
#include "op_template.h"
83

    
84
#define REG 17
85
#include "op_template.h"
86

    
87
#define REG 18
88
#include "op_template.h"
89

    
90
#define REG 19
91
#include "op_template.h"
92

    
93
#define REG 20
94
#include "op_template.h"
95

    
96
#define REG 21
97
#include "op_template.h"
98

    
99
#define REG 22
100
#include "op_template.h"
101

    
102
#define REG 23
103
#include "op_template.h"
104

    
105
#define REG 24
106
#include "op_template.h"
107

    
108
#define REG 25
109
#include "op_template.h"
110

    
111
#define REG 26
112
#include "op_template.h"
113

    
114
#define REG 27
115
#include "op_template.h"
116

    
117
#define REG 28
118
#include "op_template.h"
119

    
120
#define REG 29
121
#include "op_template.h"
122

    
123
#define REG 30
124
#include "op_template.h"
125

    
126
#define REG 31
127
#include "op_template.h"
128

    
129
/* PPC state maintenance operations */
130
/* set_Rc0 */
131
PPC_OP(set_Rc0)
132
{
133
    uint32_t tmp;
134

    
135
    if (Ts0 < 0) {
136
        tmp = 0x08;
137
    } else if (Ts0 > 0) {
138
        tmp = 0x04;
139
    } else {
140
        tmp = 0x02;
141
    }
142
    set_CRn(0, tmp);
143
    RETURN();
144
}
145

    
146
PPC_OP(set_Rc0_ov)
147
{
148
    uint32_t tmp;
149

    
150
    if (Ts0 < 0) {
151
        tmp = 0x08;
152
    } else if (Ts0 > 0) {
153
        tmp = 0x04;
154
    } else {
155
        tmp = 0x02;
156
    }
157
    tmp |= xer_ov;
158
    set_CRn(0, tmp);
159
    RETURN();
160
}
161

    
162
/* reset_Rc0 */
163
PPC_OP(reset_Rc0)
164
{
165
    set_CRn(0, 0x02 | xer_ov);
166
    RETURN();
167
}
168

    
169
/* set_Rc0_1 */
170
PPC_OP(set_Rc0_1)
171
{
172
    set_CRn(0, 0x04 | xer_ov);
173
    RETURN();
174
}
175

    
176
PPC_OP(set_T0)
177
{
178
    T0 = PARAM(1);
179
    RETURN();
180
}
181

    
182
PPC_OP(set_T1)
183
{
184
    T1 = PARAM(1);
185
    RETURN();
186
}
187

    
188
PPC_OP(set_T2)
189
{
190
    T2 = PARAM(1);
191
    RETURN();
192
}
193

    
194
/* Update time base */
195
PPC_OP(update_tb)
196
{
197
    T0 = regs->spr[SPR_ENCODE(268)];
198
    T1 = T0;
199
    T0 += PARAM(1);
200
    if (T0 < T1) {
201
        T1 = regs->spr[SPR_ENCODE(269)] + 1;
202
        regs->spr[SPR_ENCODE(269)] = T1;
203
    }
204
    regs->spr[SPR_ENCODE(268)] = T0;
205
    RETURN();
206
}
207

    
208
PPC_OP(raise_exception)
209
{
210
    raise_exception(PARAM(1));
211
    RETURN();
212
}
213

    
214
PPC_OP(exit_tb)
215
{
216
    EXIT_TB();
217
}
218

    
219
PPC_OP(load_cr)
220
{
221
    T0 = do_load_cr();
222
    RETURN();
223
}
224

    
225
PPC_OP(store_cr)
226
{
227
    do_store_cr(PARAM(1), T0);
228
    RETURN();
229
}
230

    
231
PPC_OP(load_xer_cr)
232
{
233
    T0 = (xer_so << 3) | (xer_ov << 2) | (xer_ca << 1);
234
    RETURN();
235
}
236

    
237
PPC_OP(clear_xer_cr)
238
{
239
    xer_so = 0;
240
    xer_ov = 0;
241
    xer_ca = 0;
242
    RETURN();
243
}
244

    
245
PPC_OP(load_xer_bc)
246
{
247
    T0 = xer_bc;
248
    RETURN();
249
}
250

    
251
PPC_OP(load_xer)
252
{
253
    T0 = do_load_xer();
254
    RETURN();
255
}
256

    
257
PPC_OP(store_xer)
258
{
259
    do_store_xer(T0);
260
    RETURN();
261
}
262

    
263
PPC_OP(load_msr)
264
{
265
    T0 = do_load_msr();
266
    RETURN();
267
}
268

    
269
PPC_OP(store_msr)
270
{
271
    do_store_msr(T0);
272
    RETURN();
273
}
274

    
275
PPC_OP(load_lr)
276
{
277
    regs->LR = PARAM(1);
278
    RETURN();
279
}
280

    
281
/* Set reservation */
282
PPC_OP(set_reservation)
283
{
284
    regs->reserve = T1 & ~0x03;
285
    RETURN();
286
}
287

    
288
/* Reset reservation */
289
PPC_OP(reset_reservation)
290
{
291
    regs->reserve = 0;
292
    RETURN();
293
}
294

    
295
/* crf operations */
296
PPC_OP(getbit_T0)
297
{
298
    T0 = (T0 >> PARAM(1)) & 1;
299
    RETURN();
300
}
301

    
302
PPC_OP(getbit_T1)
303
{
304
    T1 = (T1 >> PARAM(1)) & 1;
305
    RETURN();
306
}
307

    
308
PPC_OP(setcrfbit)
309
{
310
    T1 = (T1 & PARAM(1)) | (T0 << PARAM(2)); 
311
    RETURN();
312
}
313

    
314
/* Branch */
315
#define __PPC_OP_B(name, target)                                              \
316
PPC_OP(name)                                                                  \
317
{                                                                             \
318
    regs->nip = (target);                                                     \
319
    RETURN();                                                                 \
320
}
321

    
322
#define __PPC_OP_BL(name, target)                                             \
323
PPC_OP(name)                                                                  \
324
{                                                                             \
325
    regs->LR = PARAM(1);                                                      \
326
    regs->nip = (target);                                                     \
327
    RETURN();                                                                 \
328
}
329

    
330
#define PPC_OP_B(name, target)                                                \
331
__PPC_OP_B(name, target);                                                     \
332
__PPC_OP_BL(name##l, target)
333

    
334
#define __PPC_OP_BC(name, cond, target)                                       \
335
PPC_OP(name)                                                                  \
336
{                                                                             \
337
    if (cond) {                                                               \
338
        T0 = (target);                                                        \
339
    } else {                                                                  \
340
        T0 = PARAM(1);                                                        \
341
    }                                                                         \
342
    regs->nip = T0;                                                           \
343
    RETURN();                                                                 \
344
}
345

    
346
#define __PPC_OP_BCL(name, cond, target)                                      \
347
PPC_OP(name)                                                                  \
348
{                                                                             \
349
    if (cond) {                                                               \
350
        T0 = (target);                                                        \
351
        regs->LR = PARAM(1);                                                  \
352
    } else {                                                                  \
353
        T0 = PARAM(1);                                                        \
354
    }                                                                         \
355
    regs->nip = T0;                                                           \
356
    RETURN();                                                                 \
357
}
358

    
359
#define _PPC_OP_BC(name, namel, cond, target)                                 \
360
__PPC_OP_BC(name, cond, target);                                              \
361
__PPC_OP_BCL(namel, cond, target)
362

    
363
/* Branch to target */
364
#define PPC_OP_BC(name, cond)                                                 \
365
_PPC_OP_BC(b_##name, bl_##name, cond, PARAM(2))
366

    
367
PPC_OP_B(b, PARAM(1));
368
PPC_OP_BC(ctr,        (regs->CTR != 0));
369
PPC_OP_BC(ctr_true,   (regs->CTR != 0 && (T0 & PARAM(3)) != 0));
370
PPC_OP_BC(ctr_false,  (regs->CTR != 0 && (T0 & PARAM(3)) == 0));
371
PPC_OP_BC(ctrz,       (regs->CTR == 0));
372
PPC_OP_BC(ctrz_true,  (regs->CTR == 0 && (T0 & PARAM(3)) != 0));
373
PPC_OP_BC(ctrz_false, (regs->CTR == 0 && (T0 & PARAM(3)) == 0));
374
PPC_OP_BC(true,       ((T0 & PARAM(3)) != 0));
375
PPC_OP_BC(false,      ((T0 & PARAM(3)) == 0));
376

    
377
/* Branch to CTR */
378
#define PPC_OP_BCCTR(name, cond)                                              \
379
_PPC_OP_BC(bctr_##name, bctrl_##name, cond, regs->CTR & ~0x03)
380

    
381
PPC_OP_B(bctr, regs->CTR & ~0x03);
382
PPC_OP_BCCTR(ctr,        (regs->CTR != 0));
383
PPC_OP_BCCTR(ctr_true,   (regs->CTR != 0 && (T0 & PARAM(2)) != 0));
384
PPC_OP_BCCTR(ctr_false,  (regs->CTR != 0 && (T0 & PARAM(2)) == 0));
385
PPC_OP_BCCTR(ctrz,       (regs->CTR == 0));
386
PPC_OP_BCCTR(ctrz_true,  (regs->CTR == 0 && (T0 & PARAM(2)) != 0));
387
PPC_OP_BCCTR(ctrz_false, (regs->CTR == 0 && (T0 & PARAM(2)) == 0));
388
PPC_OP_BCCTR(true,       ((T0 & PARAM(2)) != 0));
389
PPC_OP_BCCTR(false,      ((T0 & PARAM(2)) == 0));
390

    
391
/* Branch to LR */
392
#define PPC_OP_BCLR(name, cond)                                               \
393
_PPC_OP_BC(blr_##name, blrl_##name, cond, regs->LR & ~0x03)
394

    
395
PPC_OP_B(blr, regs->LR & ~0x03);
396
PPC_OP_BCLR(ctr,        (regs->CTR != 0));
397
PPC_OP_BCLR(ctr_true,   (regs->CTR != 0 && (T0 & PARAM(2)) != 0));
398
PPC_OP_BCLR(ctr_false,  (regs->CTR != 0 && (T0 & PARAM(2)) == 0));
399
PPC_OP_BCLR(ctrz,       (regs->CTR == 0));
400
PPC_OP_BCLR(ctrz_true,  (regs->CTR == 0 && (T0 & PARAM(2)) != 0));
401
PPC_OP_BCLR(ctrz_false, (regs->CTR == 0 && (T0 & PARAM(2)) == 0));
402
PPC_OP_BCLR(true,       ((T0 & PARAM(2)) != 0));
403
PPC_OP_BCLR(false,      ((T0 & PARAM(2)) == 0));
404

    
405
/* CTR maintenance */
406
PPC_OP(dec_ctr)
407
{
408
    regs->CTR--;
409
    RETURN();
410
}
411

    
412
/***                           Integer arithmetic                          ***/
413
/* add */
414
PPC_OP(add)
415
{
416
    T0 += T1;
417
    RETURN();
418
}
419

    
420
PPC_OP(addo)
421
{
422
    T2 = T0;
423
    T0 += T1;
424
    if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
425
        xer_so = 1;
426
        xer_ov = 1;
427
    } else {
428
        xer_ov = 0;
429
    }
430
    RETURN();
431
}
432

    
433
/* add carrying */
434
PPC_OP(addc)
435
{
436
    T2 = T0;
437
    T0 += T1;
438
    if (T0 < T2) {
439
        xer_ca = 1;
440
    } else {
441
        xer_ca = 0;
442
    }
443
    RETURN();
444
}
445

    
446
PPC_OP(addco)
447
{
448
    T2 = T0;
449
    T0 += T1;
450
    if (T0 < T2) {
451
        xer_ca = 1;
452
    } else {
453
        xer_ca = 0;
454
    }
455
    if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
456
        xer_so = 1;
457
        xer_ov = 1;
458
    } else {
459
        xer_ov = 0;
460
    }
461
    RETURN();
462
}
463

    
464
/* add extended */
465
/* candidate for helper (too long) */
466
PPC_OP(adde)
467
{
468
    T2 = T0;
469
    T0 += T1 + xer_ca;
470
    if (T0 < T2 || (xer_ca == 1 && T0 == T2)) {
471
        xer_ca = 1;
472
    } else {
473
        xer_ca = 0;
474
    }
475
    RETURN();
476
}
477

    
478
PPC_OP(addeo)
479
{
480
    T2 = T0;
481
    T0 += T1 + xer_ca;
482
    if (T0 < T2 || (xer_ca == 1 && T0 == T2)) {
483
        xer_ca = 1;
484
    } else {
485
        xer_ca = 0;
486
    }
487
    if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
488
        xer_so = 1;
489
        xer_ov = 1;
490
    } else {
491
        xer_ov = 0;
492
    }
493
    RETURN();
494
}
495

    
496
/* add immediate */
497
PPC_OP(addi)
498
{
499
    T0 += PARAM(1);
500
    RETURN();
501
}
502

    
503
/* add immediate carrying */
504
PPC_OP(addic)
505
{
506
    T1 = T0;
507
    T0 += PARAM(1);
508
    if (T0 < T1) {
509
        xer_ca = 1;
510
    } else {
511
        xer_ca = 0;
512
    }
513
    RETURN();
514
}
515

    
516
/* add to minus one extended */
517
PPC_OP(addme)
518
{
519
    T1 = T0;
520
    T0 += xer_ca + (-1);
521
    if (T1 != 0)
522
        xer_ca = 1;
523
    RETURN();
524
}
525

    
526
PPC_OP(addmeo)
527
{
528
    T1 = T0;
529
    T0 += xer_ca + (-1);
530
    if (T1 & (T1 ^ T0) & (1 << 31)) {
531
        xer_so = 1;
532
        xer_ov = 1;
533
    } else {
534
        xer_ov = 0;
535
    }
536
    if (T1 != 0)
537
        xer_ca = 1;
538
    RETURN();
539
}
540

    
541
/* add to zero extended */
542
PPC_OP(addze)
543
{
544
    T1 = T0;
545
    T0 += xer_ca;
546
    if (T0 < T1) {
547
        xer_ca = 1;
548
    } else {
549
        xer_ca = 0;
550
    }
551
    RETURN();
552
}
553

    
554
PPC_OP(addzeo)
555
{
556
    T1 = T0;
557
    T0 += xer_ca;
558
    if ((T1 ^ (-1)) & (T1 ^ T0) & (1 << 31)) {
559
        xer_so = 1;
560
        xer_ov = 1;
561
    } else {
562
        xer_ov = 0;
563
    }
564
    if (T0 < T1) {
565
        xer_ca = 1;
566
    } else {
567
        xer_ca = 0;
568
    }
569
    RETURN();
570
}
571

    
572
/* divide word */
573
/* candidate for helper (too long) */
574
PPC_OP(divw)
575
{
576
    if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
577
        Ts0 = (-1) * (T0 >> 31);
578
    } else {
579
        Ts0 /= Ts1;
580
    }
581
    RETURN();
582
}
583

    
584
PPC_OP(divwo)
585
{
586
    if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
587
        xer_so = 1;
588
        xer_ov = 1;
589
        T0 = (-1) * (T0 >> 31);
590
    } else {
591
        xer_ov = 0;
592
        Ts0 /= Ts1;
593
    }
594
    RETURN();
595
}
596

    
597
/* divide word unsigned */
598
PPC_OP(divwu)
599
{
600
    if (T1 == 0) {
601
        T0 = 0;
602
    } else {
603
        T0 /= T1;
604
    }
605
    RETURN();
606
}
607

    
608
PPC_OP(divwuo)
609
{
610
    if (T1 == 0) {
611
        xer_so = 1;
612
        xer_ov = 1;
613
        T0 = 0;
614
    } else {
615
        xer_ov = 0;
616
        T0 /= T1;
617
    }
618
    RETURN();
619
}
620

    
621
/* multiply high word */
622
PPC_OP(mulhw)
623
{
624
    Ts0 = ((int64_t)Ts0 * (int64_t)Ts1) >> 32;
625
    RETURN();
626
}
627

    
628
/* multiply high word unsigned */
629
PPC_OP(mulhwu)
630
{
631
    T0 = ((uint64_t)T0 * (uint64_t)T1) >> 32;
632
    RETURN();
633
}
634

    
635
/* multiply low immediate */
636
PPC_OP(mulli)
637
{
638
    Ts0 *= SPARAM(1);
639
    RETURN();
640
}
641

    
642
/* multiply low word */
643
PPC_OP(mullw)
644
{
645
    T0 *= T1;
646
    RETURN();
647
}
648

    
649
PPC_OP(mullwo)
650
{
651
    int64_t res = (int64_t)Ts0 * (int64_t)Ts1;
652

    
653
    if ((int32_t)res != res) {
654
        xer_ov = 1;
655
        xer_so = 1;
656
    } else {
657
        xer_ov = 0;
658
    }
659
    Ts0 = res;
660
    RETURN();
661
}
662

    
663
/* negate */
664
PPC_OP(neg)
665
{
666
    if (T0 != 0x80000000) {
667
        Ts0 = -Ts0;
668
    }
669
    RETURN();
670
}
671

    
672
PPC_OP(nego)
673
{
674
    if (T0 == 0x80000000) {
675
        xer_ov = 1;
676
        xer_so = 1;
677
    } else {
678
        xer_ov = 0;
679
        Ts0 = -Ts0;
680
    }
681
    RETURN();
682
}
683

    
684
/* substract from */
685
PPC_OP(subf)
686
{
687
    T0 = T1 - T0;
688
    RETURN();
689
}
690

    
691
PPC_OP(subfo)
692
{
693
    T2 = T0;
694
    T0 = T1 - T0;
695
    if (((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)) {
696
        xer_so = 1;
697
        xer_ov = 1;
698
    } else {
699
        xer_ov = 0;
700
    }
701
    RETURN();
702
}
703

    
704
/* substract from carrying */
705
PPC_OP(subfc)
706
{
707
    T0 = T1 - T0;
708
    if (T0 <= T1) {
709
        xer_ca = 1;
710
    } else {
711
        xer_ca = 0;
712
    }
713
    RETURN();
714
}
715

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

    
734
/* substract from extended */
735
/* candidate for helper (too long) */
736
PPC_OP(subfe)
737
{
738
    T0 = T1 + ~T0 + xer_ca;
739
    if (T0 < T1 || (xer_ca == 1 && T0 == T1)) {
740
        xer_ca = 1;
741
    } else {
742
        xer_ca = 0;
743
    }
744
    RETURN();
745
}
746

    
747
PPC_OP(subfeo)
748
{
749
    T2 = T0;
750
    T0 = T1 + ~T0 + xer_ca;
751
    if ((~T2 ^ T1 ^ (-1)) & (~T2 ^ T0) & (1 << 31)) {
752
        xer_so = 1;
753
        xer_ov = 1;
754
    } else {
755
        xer_ov = 0;
756
    }
757
    if (T0 < T1 || (xer_ca == 1 && T0 == T1)) {
758
        xer_ca = 1;
759
    } else {
760
        xer_ca = 0;
761
    }
762
    RETURN();
763
}
764

    
765
/* substract from immediate carrying */
766
PPC_OP(subfic)
767
{
768
    T0 = PARAM(1) + ~T0 + 1;
769
    if (T0 <= PARAM(1)) {
770
        xer_ca = 1;
771
    } else {
772
        xer_ca = 0;
773
    }
774
    RETURN();
775
}
776

    
777
/* substract from minus one extended */
778
PPC_OP(subfme)
779
{
780
    T0 = ~T0 + xer_ca - 1;
781

    
782
    if (T0 != -1)
783
        xer_ca = 1;
784
    RETURN();
785
}
786

    
787
PPC_OP(subfmeo)
788
{
789
    T1 = T0;
790
    T0 = ~T0 + xer_ca - 1;
791
    if (~T1 & (~T1 ^ T0) & (1 << 31)) {
792
        xer_so = 1;
793
        xer_ov = 1;
794
    } else {
795
        xer_ov = 0;
796
    }
797
    if (T1 != -1)
798
        xer_ca = 1;
799
    RETURN();
800
}
801

    
802
/* substract from zero extended */
803
PPC_OP(subfze)
804
{
805
    T1 = ~T0;
806
    T0 = T1 + xer_ca;
807
    if (T0 < T1) {
808
        xer_ca = 1;
809
    } else {
810
        xer_ca = 0;
811
    }
812
    RETURN();
813
}
814

    
815
PPC_OP(subfzeo)
816
{
817
    T1 = T0;
818
    T0 = ~T0 + xer_ca;
819
    if ((~T1 ^ (-1)) & ((~T1) ^ T0) & (1 << 31)) {
820
        xer_ov = 1;
821
        xer_so = 1;
822
    } else {
823
        xer_ov = 0;
824
    }
825
    if (T0 < ~T1) {
826
        xer_ca = 1;
827
    } else {
828
        xer_ca = 0;
829
    }
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
    Ts0 = s_ext8(Ts0);
928
    RETURN();
929
}
930

    
931
/* extend sign half word */
932
PPC_OP(extsh)
933
{
934
    Ts0 = s_ext16(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)) | (T0 & 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
PPC_OP(sraw)
1047
{
1048
    Ts0 = do_sraw(Ts0, T1);
1049
    RETURN();
1050
}
1051

    
1052
/* shift right algebraic word immediate */
1053
PPC_OP(srawi)
1054
{
1055
    Ts1 = Ts0;
1056
    Ts0 = 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

    
1078
/***                     Floating-Point multiply-and-add                   ***/
1079

    
1080
/***                     Floating-Point round & convert                    ***/
1081

    
1082
/***                         Floating-Point compare                        ***/
1083

    
1084
/***                  Floating-Point status & ctrl register                ***/
1085

    
1086
/***                             Integer load                              ***/
1087
#define ld16x(x) s_ext16(ld16(x))
1088
#define PPC_ILD_OPX(name, op)                                                 \
1089
PPC_OP(l##name##x_z)                                                          \
1090
{                                                                             \
1091
    T1 = op(T0);                                                              \
1092
    RETURN();                                                                 \
1093
}                                                                             \
1094
PPC_OP(l##name##x)                                                            \
1095
{                                                                             \
1096
    T0 += T1;                                                                 \
1097
    T1 = op(T0);                                                              \
1098
    RETURN();                                                                 \
1099
}
1100

    
1101
#define PPC_ILD_OP(name, op)                                                  \
1102
PPC_OP(l##name##_z)                                                           \
1103
{                                                                             \
1104
    T1 = op(SPARAM(1));                                                       \
1105
    RETURN();                                                                 \
1106
}                                                                             \
1107
PPC_OP(l##name)                                                               \
1108
{                                                                             \
1109
    T0 += SPARAM(1);                                                          \
1110
    T1 = op(T0);                                                              \
1111
    RETURN();                                                                 \
1112
}                                                                             \
1113
PPC_ILD_OPX(name, op)
1114

    
1115
PPC_ILD_OP(bz, ld8);
1116
PPC_ILD_OP(ha, ld16x);
1117
PPC_ILD_OP(hz, ld16);
1118
PPC_ILD_OP(wz, ld32);
1119

    
1120
/***                              Integer store                            ***/
1121
#define PPC_IST_OPX(name, op)                                                 \
1122
PPC_OP(st##name##x_z)                                                         \
1123
{                                                                             \
1124
    op(T0, T1);                                                               \
1125
    RETURN();                                                                 \
1126
}                                                                             \
1127
PPC_OP(st##name##x)                                                           \
1128
{                                                                             \
1129
    T0 += T1;                                                                 \
1130
    op(T0, T2);                                                               \
1131
    RETURN();                                                                 \
1132
}
1133

    
1134
#define PPC_IST_OP(name, op)                                                  \
1135
PPC_OP(st##name##_z)                                                          \
1136
{                                                                             \
1137
    op(SPARAM(1), T0);                                                        \
1138
    RETURN();                                                                 \
1139
}                                                                             \
1140
PPC_OP(st##name)                                                              \
1141
{                                                                             \
1142
    T0 += SPARAM(1);                                                          \
1143
    op(T0, T1);                                                               \
1144
    RETURN();                                                                 \
1145
}                                                                             \
1146
PPC_IST_OPX(name, op);
1147

    
1148
PPC_IST_OP(b, st8);
1149
PPC_IST_OP(h, st16);
1150
PPC_IST_OP(w, st32);
1151

    
1152
/***                Integer load and store with byte reverse               ***/
1153
PPC_ILD_OPX(hbr, ld16r);
1154
PPC_ILD_OPX(wbr, ld32r);
1155
PPC_IST_OPX(hbr, st16r);
1156
PPC_IST_OPX(wbr, st32r);
1157

    
1158
/***                    Integer load and store multiple                    ***/
1159
PPC_OP(lmw)
1160
{
1161
    do_lmw(PARAM(1), SPARAM(2) + T0);
1162
    RETURN();
1163
}
1164

    
1165
PPC_OP(stmw)
1166
{
1167
    do_stmw(PARAM(1), SPARAM(2) + T0);
1168
    RETURN();
1169
}
1170

    
1171
/***                    Integer load and store strings                     ***/
1172
PPC_OP(lswi)
1173
{
1174
    do_lsw(PARAM(1), PARAM(2), T0);
1175
    RETURN();
1176
}
1177

    
1178
PPC_OP(lswx)
1179
{
1180
    do_lsw(PARAM(1), T0, T1 + T2);
1181
    RETURN();
1182
}
1183

    
1184
PPC_OP(stswi_z)
1185
{
1186
    do_stsw(PARAM(1), PARAM(2), 0);
1187
    RETURN();
1188
}
1189

    
1190
PPC_OP(stswi)
1191
{
1192
    do_stsw(PARAM(1), PARAM(2), T0);
1193
    RETURN();
1194
}
1195

    
1196
PPC_OP(stswx_z)
1197
{
1198
    do_stsw(PARAM(1), T0, T1);
1199
    RETURN();
1200
}
1201

    
1202
PPC_OP(stswx)
1203
{
1204
    do_stsw(PARAM(1), T0, T1 + T2);
1205
    RETURN();
1206
}
1207

    
1208
/* SPR */
1209
PPC_OP(load_spr)
1210
{
1211
    T0 = regs->spr[PARAM(1)];
1212
}
1213

    
1214
PPC_OP(store_spr)
1215
{
1216
    regs->spr[PARAM(1)] = T0;
1217
}
1218

    
1219
/* FPSCR */
1220
PPC_OP(load_fpscr)
1221
{
1222
    T0 = do_load_fpscr();
1223
}
1224

    
1225
PPC_OP(store_fpscr)
1226
{
1227
    do_store_fpscr(PARAM(1), T0);
1228
}
1229

    
1230
/***                         Floating-point store                          ***/
1231

    
1232
static inline uint32_t dtos(uint64_t f)
1233
{
1234
    unsigned int e, m, s;
1235
    e = (((f >> 52) & 0x7ff) - 1022) + 126;
1236
    s = (f >> 63);
1237
    m = (f >> 29);
1238
    return (s << 31) | (e << 23) | m;
1239
}
1240

    
1241
static inline uint64_t stod(uint32_t f)
1242
{
1243
    unsigned int e, m, s;
1244
    e = ((f >> 23) & 0xff) - 126 + 1022;
1245
    s = f >> 31;
1246
    m = f & ((1 << 23) - 1);
1247
    return ((uint64_t)s << 63) | ((uint64_t)e << 52) | ((uint64_t)m << 29);
1248
}
1249

    
1250
PPC_OP(stfd_z_FT0)
1251
{
1252
    st64(SPARAM(1), FT0);
1253
}
1254

    
1255
PPC_OP(stfd_FT0)
1256
{
1257
    T0 += SPARAM(1);
1258
    st64(T0, FT0);
1259
}
1260

    
1261
PPC_OP(stfdx_z_FT0)
1262
{
1263
    st64(T0, FT0);
1264
}
1265

    
1266
PPC_OP(stfdx_FT0)
1267
{
1268
    T0 += T1;
1269
    st64(T0, FT0);
1270
}
1271

    
1272

    
1273
PPC_OP(stfs_z_FT0)
1274
{
1275
    st32(SPARAM(1), dtos(FT0));
1276
}
1277

    
1278
PPC_OP(stfs_FT0)
1279
{
1280
    T0 += SPARAM(1);
1281
    st32(T0, dtos(FT0));
1282
}
1283

    
1284
PPC_OP(stfsx_z_FT0)
1285
{
1286
    st32(T0, dtos(FT0));
1287
}
1288

    
1289
PPC_OP(stfsx_FT0)
1290
{
1291
    T0 += T1;
1292
    st32(T0, dtos(FT0));
1293
}
1294

    
1295
/***                         Floating-point load                          ***/
1296
PPC_OP(lfd_z_FT0)
1297
{
1298
    FT0 = ld64(SPARAM(1));
1299
}
1300

    
1301
PPC_OP(lfd_FT0)
1302
{
1303
    T0 += SPARAM(1);
1304
    FT0 = ld64(T0);
1305
}
1306

    
1307
PPC_OP(lfdx_z_FT0)
1308
{
1309
    FT0 = ld64(T0);
1310
}
1311

    
1312
PPC_OP(lfdx_FT0)
1313
{
1314
    T0 += T1;
1315
    FT0 = ld64(T0);
1316
}
1317

    
1318
PPC_OP(lfs_z_FT0)
1319
{
1320
    FT0 = stod(ld32(SPARAM(1)));
1321
}
1322

    
1323
PPC_OP(lfs_FT0)
1324
{
1325
    T0 += SPARAM(1);
1326
    FT0 = stod(ld32(T0));
1327
}
1328

    
1329
PPC_OP(lfsx_z_FT0)
1330
{
1331
    FT0 = stod(ld32(T0));
1332
}
1333

    
1334
PPC_OP(lfsx_FT0)
1335
{
1336
    T0 += T1;
1337
    FT0 = stod(ld32(T0));
1338
}