Statistics
| Branch: | Revision:

root / target-ppc / op.c @ 79aceca5

History | View | Annotate | Download (22.6 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
extern uint32_t __a;
26
extern uint32_t __b;
27
extern uint32_t __c;
28
extern uint32_t __d;
29
extern uint32_t __e;
30
extern uint32_t __f;
31
#define Ts0 (int32_t)T0
32
#define Ts1 (int32_t)T1
33
#define Ts2 (int32_t)T2
34

    
35
#include "op-multi.c"
36

    
37
#define PPC_OP(name) void op_##name(void)
38

    
39
/* PPC state maintenance operations */
40
/* set_Rc0 */
41
PPC_OP(set_Rc0)
42
{
43
    uint32_t tmp;
44

    
45
    if (Ts0 < 0) {
46
        tmp = 0x08;
47
    } else if (Ts0 > 0) {
48
        tmp = 0x04;
49
    } else {
50
        tmp = 0x02;
51
    }
52
    set_CRn(0, tmp);
53
    RETURN();
54
}
55

    
56
PPC_OP(set_Rc0_ov)
57
{
58
    uint32_t tmp;
59

    
60
    if (Ts0 < 0) {
61
        tmp = 0x08;
62
    } else if (Ts0 > 0) {
63
        tmp = 0x04;
64
    } else {
65
        tmp = 0x02;
66
    }
67
    tmp |= xer_ov;
68
    set_CRn(0, tmp);
69
    RETURN();
70
}
71

    
72
/* reset_Rc0 */
73
PPC_OP(reset_Rc0)
74
{
75
    set_CRn(0, 0x02 | xer_ov);
76
    RETURN();
77
}
78

    
79
/* set_Rc0_1 */
80
PPC_OP(set_Rc0_1)
81
{
82
    set_CRn(0, 0x04 | xer_ov);
83
    RETURN();
84
}
85

    
86
PPC_OP(set_T0)
87
{
88
    T0 = PARAM(1);
89
    RETURN();
90
}
91

    
92
PPC_OP(set_T1)
93
{
94
    T1 = PARAM(1);
95
    RETURN();
96
}
97

    
98
PPC_OP(set_T2)
99
{
100
    T2 = PARAM(1);
101
    RETURN();
102
}
103

    
104
/* Update time base */
105
PPC_OP(update_tb)
106
{
107
    T0 = regs->spr[SPR_ENCODE(268)];
108
    T1 = T0;
109
    T0 += PARAM(1);
110
    if (T0 < T1) {
111
        T1 = regs->spr[SPR_ENCODE(269)] + 1;
112
        regs->spr[SPR_ENCODE(269)] = T1;
113
    }
114
    regs->spr[SPR_ENCODE(268)] = T0;
115
    RETURN();
116
}
117

    
118
PPC_OP(raise_exception)
119
{
120
    raise_exception(PARAM(1));
121
    RETURN();
122
}
123

    
124
PPC_OP(exit_tb)
125
{
126
    EXIT_TB();
127
}
128

    
129
PPC_OP(load_cr)
130
{
131
    T0 = do_load_cr();
132
    RETURN();
133
}
134

    
135
PPC_OP(store_cr)
136
{
137
    do_store_cr(PARAM(1), T0);
138
    RETURN();
139
}
140

    
141
PPC_OP(load_xer_cr)
142
{
143
    T0 = (xer_so << 3) | (xer_ov << 2) | (xer_ca << 1);
144
    RETURN();
145
}
146

    
147
PPC_OP(clear_xer_cr)
148
{
149
    xer_so = 0;
150
    xer_ov = 0;
151
    xer_ca = 0;
152
    RETURN();
153
}
154

    
155
PPC_OP(load_xer_bc)
156
{
157
    T0 = xer_bc;
158
    RETURN();
159
}
160

    
161
PPC_OP(load_xer)
162
{
163
    T0 = do_load_xer();
164
    RETURN();
165
}
166

    
167
PPC_OP(store_xer)
168
{
169
    do_store_xer(T0);
170
    RETURN();
171
}
172

    
173
PPC_OP(load_msr)
174
{
175
    T0 = do_load_msr();
176
    RETURN();
177
}
178

    
179
PPC_OP(store_msr)
180
{
181
    do_store_msr(T0);
182
    RETURN();
183
}
184

    
185
PPC_OP(load_lr)
186
{
187
    regs->LR = PARAM(1);
188
    RETURN();
189
}
190

    
191
/* Set reservation */
192
PPC_OP(set_reservation)
193
{
194
    regs->reserve = T1 & ~0x03;
195
    RETURN();
196
}
197

    
198
/* Reset reservation */
199
PPC_OP(reset_reservation)
200
{
201
    regs->reserve = 0;
202
    RETURN();
203
}
204

    
205
/* crf operations */
206
PPC_OP(getbit_T0)
207
{
208
    T0 = (T0 >> PARAM(1)) & 1;
209
    RETURN();
210
}
211

    
212
PPC_OP(getbit_T1)
213
{
214
    T1 = (T1 >> PARAM(1)) & 1;
215
    RETURN();
216
}
217

    
218
PPC_OP(setcrfbit)
219
{
220
    T1 = (T1 & PARAM(1)) | (T0 << PARAM(2)); 
221
    RETURN();
222
}
223

    
224
/* Branch */
225
#define __PPC_OP_B(name, target)                                              \
226
PPC_OP(name)                                                                  \
227
{                                                                             \
228
    regs->nip = (target);                                                     \
229
    RETURN();                                                                 \
230
}
231

    
232
#define __PPC_OP_BL(name, target)                                             \
233
PPC_OP(name)                                                                  \
234
{                                                                             \
235
    regs->LR = PARAM(1);                                                      \
236
    regs->nip = (target);                                                     \
237
    RETURN();                                                                 \
238
}
239

    
240
#define PPC_OP_B(name, target)                                                \
241
__PPC_OP_B(name, target);                                                     \
242
__PPC_OP_BL(name##l, target)
243

    
244
#define __PPC_OP_BC(name, cond, target)                                       \
245
PPC_OP(name)                                                                  \
246
{                                                                             \
247
    if (cond) {                                                               \
248
        T0 = (target);                                                        \
249
    } else {                                                                  \
250
        T0 = PARAM(1);                                                        \
251
    }                                                                         \
252
    regs->nip = T0;                                                           \
253
    RETURN();                                                                 \
254
}
255

    
256
#define __PPC_OP_BCL(name, cond, target)                                      \
257
PPC_OP(name)                                                                  \
258
{                                                                             \
259
    if (cond) {                                                               \
260
        T0 = (target);                                                        \
261
        regs->LR = PARAM(1);                                                  \
262
    } else {                                                                  \
263
        T0 = PARAM(1);                                                        \
264
    }                                                                         \
265
    regs->nip = T0;                                                           \
266
    RETURN();                                                                 \
267
}
268

    
269
#define _PPC_OP_BC(name, namel, cond, target)                                 \
270
__PPC_OP_BC(name, cond, target);                                              \
271
__PPC_OP_BCL(namel, cond, target)
272

    
273
/* Branch to target */
274
#define PPC_OP_BC(name, cond)                                                 \
275
_PPC_OP_BC(b_##name, bl_##name, cond, PARAM(2))
276

    
277
PPC_OP_B(b, PARAM(1));
278
PPC_OP_BC(ctr,        (regs->CTR != 0));
279
PPC_OP_BC(ctr_true,   (regs->CTR != 0 && (T0 & PARAM(3)) != 0));
280
PPC_OP_BC(ctr_false,  (regs->CTR != 0 && (T0 & PARAM(3)) == 0));
281
PPC_OP_BC(ctrz,       (regs->CTR == 0));
282
PPC_OP_BC(ctrz_true,  (regs->CTR == 0 && (T0 & PARAM(3)) != 0));
283
PPC_OP_BC(ctrz_false, (regs->CTR == 0 && (T0 & PARAM(3)) == 0));
284
PPC_OP_BC(true,       ((T0 & PARAM(3)) != 0));
285
PPC_OP_BC(false,      ((T0 & PARAM(3)) == 0));
286

    
287
/* Branch to CTR */
288
#define PPC_OP_BCCTR(name, cond)                                              \
289
_PPC_OP_BC(bctr_##name, bctrl_##name, cond, regs->CTR & ~0x03)
290

    
291
PPC_OP_B(bctr, regs->CTR & ~0x03);
292
PPC_OP_BCCTR(ctr,        (regs->CTR != 0));
293
PPC_OP_BCCTR(ctr_true,   (regs->CTR != 0 && (T0 & PARAM(2)) != 0));
294
PPC_OP_BCCTR(ctr_false,  (regs->CTR != 0 && (T0 & PARAM(2)) == 0));
295
PPC_OP_BCCTR(ctrz,       (regs->CTR == 0));
296
PPC_OP_BCCTR(ctrz_true,  (regs->CTR == 0 && (T0 & PARAM(2)) != 0));
297
PPC_OP_BCCTR(ctrz_false, (regs->CTR == 0 && (T0 & PARAM(2)) == 0));
298
PPC_OP_BCCTR(true,       ((T0 & PARAM(2)) != 0));
299
PPC_OP_BCCTR(false,      ((T0 & PARAM(2)) == 0));
300

    
301
/* Branch to LR */
302
#define PPC_OP_BCLR(name, cond)                                               \
303
_PPC_OP_BC(blr_##name, blrl_##name, cond, regs->LR & ~0x03)
304

    
305
PPC_OP_B(blr, regs->LR & ~0x03);
306
PPC_OP_BCLR(ctr,        (regs->CTR != 0));
307
PPC_OP_BCLR(ctr_true,   (regs->CTR != 0 && (T0 & PARAM(2)) != 0));
308
PPC_OP_BCLR(ctr_false,  (regs->CTR != 0 && (T0 & PARAM(2)) == 0));
309
PPC_OP_BCLR(ctrz,       (regs->CTR == 0));
310
PPC_OP_BCLR(ctrz_true,  (regs->CTR == 0 && (T0 & PARAM(2)) != 0));
311
PPC_OP_BCLR(ctrz_false, (regs->CTR == 0 && (T0 & PARAM(2)) == 0));
312
PPC_OP_BCLR(true,       ((T0 & PARAM(2)) != 0));
313
PPC_OP_BCLR(false,      ((T0 & PARAM(2)) == 0));
314

    
315
/* CTR maintenance */
316
PPC_OP(dec_ctr)
317
{
318
    regs->CTR--;
319
    RETURN();
320
}
321

    
322
/***                           Integer arithmetic                          ***/
323
/* add */
324
PPC_OP(add)
325
{
326
    T0 += T1;
327
    RETURN();
328
}
329

    
330
PPC_OP(addo)
331
{
332
    T2 = T0;
333
    T0 += T1;
334
    if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
335
        xer_so = 1;
336
        xer_ov = 1;
337
    } else {
338
        xer_ov = 0;
339
    }
340
    RETURN();
341
}
342

    
343
/* add carrying */
344
PPC_OP(addc)
345
{
346
    T2 = T0;
347
    T0 += T1;
348
    if (T0 < T2) {
349
        xer_ca = 1;
350
    } else {
351
        xer_ca = 0;
352
    }
353
    RETURN();
354
}
355

    
356
PPC_OP(addco)
357
{
358
    T2 = T0;
359
    T0 += T1;
360
    if (T0 < T2) {
361
        xer_ca = 1;
362
    } else {
363
        xer_ca = 0;
364
    }
365
    if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
366
        xer_so = 1;
367
        xer_ov = 1;
368
    } else {
369
        xer_ov = 0;
370
    }
371
    RETURN();
372
}
373

    
374
/* add extended */
375
/* candidate for helper (too long) */
376
PPC_OP(adde)
377
{
378
    T2 = T0;
379
    T0 += T1 + xer_ca;
380
    if (T0 < T2 || (xer_ca == 1 && T0 == T2)) {
381
        xer_ca = 1;
382
    } else {
383
        xer_ca = 0;
384
    }
385
    RETURN();
386
}
387

    
388
PPC_OP(addeo)
389
{
390
    T2 = T0;
391
    T0 += T1 + xer_ca;
392
    if (T0 < T2 || (xer_ca == 1 && T0 == T2)) {
393
        xer_ca = 1;
394
    } else {
395
        xer_ca = 0;
396
    }
397
    if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
398
        xer_so = 1;
399
        xer_ov = 1;
400
    } else {
401
        xer_ov = 0;
402
    }
403
    RETURN();
404
}
405

    
406
/* add immediate */
407
PPC_OP(addi)
408
{
409
    T0 += PARAM(1);
410
    RETURN();
411
}
412

    
413
/* add immediate carrying */
414
PPC_OP(addic)
415
{
416
    T1 = T0;
417
    T0 += PARAM(1);
418
    if (T0 < T1) {
419
        xer_ca = 1;
420
    } else {
421
        xer_ca = 0;
422
    }
423
    RETURN();
424
}
425

    
426
/* add to minus one extended */
427
PPC_OP(addme)
428
{
429
    T1 = T0;
430
    T0 += xer_ca + (-1);
431
    if (T1 != 0)
432
        xer_ca = 1;
433
    RETURN();
434
}
435

    
436
PPC_OP(addmeo)
437
{
438
    T1 = T0;
439
    T0 += xer_ca + (-1);
440
    if (T1 & (T1 ^ T0) & (1 << 31)) {
441
        xer_so = 1;
442
        xer_ov = 1;
443
    } else {
444
        xer_ov = 0;
445
    }
446
    if (T1 != 0)
447
        xer_ca = 1;
448
    RETURN();
449
}
450

    
451
/* add to zero extended */
452
PPC_OP(addze)
453
{
454
    T1 = T0;
455
    T0 += xer_ca;
456
    if (T0 < T1) {
457
        xer_ca = 1;
458
    } else {
459
        xer_ca = 0;
460
    }
461
    RETURN();
462
}
463

    
464
PPC_OP(addzeo)
465
{
466
    T1 = T0;
467
    T0 += xer_ca;
468
    if ((T1 ^ (-1)) & (T1 ^ T0) & (1 << 31)) {
469
        xer_so = 1;
470
        xer_ov = 1;
471
    } else {
472
        xer_ov = 0;
473
    }
474
    if (T0 < T1) {
475
        xer_ca = 1;
476
    } else {
477
        xer_ca = 0;
478
    }
479
    RETURN();
480
}
481

    
482
/* divide word */
483
/* candidate for helper (too long) */
484
PPC_OP(divw)
485
{
486
    if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
487
        Ts0 = (-1) * (T0 >> 31);
488
    } else {
489
        Ts0 /= Ts1;
490
    }
491
    RETURN();
492
}
493

    
494
PPC_OP(divwo)
495
{
496
    if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
497
        xer_so = 1;
498
        xer_ov = 1;
499
        T0 = (-1) * (T0 >> 31);
500
    } else {
501
        xer_ov = 0;
502
        Ts0 /= Ts1;
503
    }
504
    RETURN();
505
}
506

    
507
/* divide word unsigned */
508
PPC_OP(divwu)
509
{
510
    if (T1 == 0) {
511
        T0 = 0;
512
    } else {
513
        T0 /= T1;
514
    }
515
    RETURN();
516
}
517

    
518
PPC_OP(divwuo)
519
{
520
    if (T1 == 0) {
521
        xer_so = 1;
522
        xer_ov = 1;
523
        T0 = 0;
524
    } else {
525
        xer_ov = 0;
526
        T0 /= T1;
527
    }
528
    RETURN();
529
}
530

    
531
/* multiply high word */
532
PPC_OP(mulhw)
533
{
534
    Ts0 = ((int64_t)Ts0 * (int64_t)Ts1) >> 32;
535
    RETURN();
536
}
537

    
538
/* multiply high word unsigned */
539
PPC_OP(mulhwu)
540
{
541
    T0 = ((uint64_t)T0 * (uint64_t)T1) >> 32;
542
    RETURN();
543
}
544

    
545
/* multiply low immediate */
546
PPC_OP(mulli)
547
{
548
    Ts0 *= SPARAM(1);
549
    RETURN();
550
}
551

    
552
/* multiply low word */
553
PPC_OP(mullw)
554
{
555
    T0 *= T1;
556
    RETURN();
557
}
558

    
559
PPC_OP(mullwo)
560
{
561
    int64_t res = (int64_t)Ts0 * (int64_t)Ts1;
562

    
563
    if ((int32_t)res != res) {
564
        xer_ov = 1;
565
        xer_so = 1;
566
    } else {
567
        xer_ov = 0;
568
    }
569
    Ts0 = res;
570
    RETURN();
571
}
572

    
573
/* negate */
574
PPC_OP(neg)
575
{
576
    if (T0 != 0x80000000) {
577
        Ts0 = -Ts0;
578
    }
579
    RETURN();
580
}
581

    
582
PPC_OP(nego)
583
{
584
    if (T0 == 0x80000000) {
585
        xer_ov = 1;
586
        xer_so = 1;
587
    } else {
588
        xer_ov = 0;
589
        Ts0 = -Ts0;
590
    }
591
    RETURN();
592
}
593

    
594
/* substract from */
595
PPC_OP(subf)
596
{
597
    T0 = T1 - T0;
598
    RETURN();
599
}
600

    
601
PPC_OP(subfo)
602
{
603
    T2 = T0;
604
    T0 = T1 - T0;
605
    if (((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)) {
606
        xer_so = 1;
607
        xer_ov = 1;
608
    } else {
609
        xer_ov = 0;
610
    }
611
    RETURN();
612
}
613

    
614
/* substract from carrying */
615
PPC_OP(subfc)
616
{
617
    T0 = T1 - T0;
618
    if (T0 <= T1) {
619
        xer_ca = 1;
620
    } else {
621
        xer_ca = 0;
622
    }
623
    RETURN();
624
}
625

    
626
PPC_OP(subfco)
627
{
628
    T2 = T0;
629
    T0 = T1 - T0;
630
    if (T0 <= T1) {
631
        xer_ca = 1;
632
    } else {
633
        xer_ca = 0;
634
    }
635
    if (((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)) {
636
        xer_so = 1;
637
        xer_ov = 1;
638
    } else {
639
        xer_ov = 0;
640
    }
641
    RETURN();
642
}
643

    
644
/* substract from extended */
645
/* candidate for helper (too long) */
646
PPC_OP(subfe)
647
{
648
    T0 = T1 + ~T0 + xer_ca;
649
    if (T0 < T1 || (xer_ca == 1 && T0 == T1)) {
650
        xer_ca = 1;
651
    } else {
652
        xer_ca = 0;
653
    }
654
    RETURN();
655
}
656

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

    
675
/* substract from immediate carrying */
676
PPC_OP(subfic)
677
{
678
    T0 = PARAM(1) + ~T0 + 1;
679
    if (T0 <= PARAM(1)) {
680
        xer_ca = 1;
681
    } else {
682
        xer_ca = 0;
683
    }
684
    RETURN();
685
}
686

    
687
/* substract from minus one extended */
688
PPC_OP(subfme)
689
{
690
    T0 = ~T0 + xer_ca - 1;
691

    
692
    if (T0 != -1)
693
        xer_ca = 1;
694
    RETURN();
695
}
696

    
697
PPC_OP(subfmeo)
698
{
699
    T1 = T0;
700
    T0 = ~T0 + xer_ca - 1;
701
    if (~T1 & (~T1 ^ T0) & (1 << 31)) {
702
        xer_so = 1;
703
        xer_ov = 1;
704
    } else {
705
        xer_ov = 0;
706
    }
707
    if (T1 != -1)
708
        xer_ca = 1;
709
    RETURN();
710
}
711

    
712
/* substract from zero extended */
713
PPC_OP(subfze)
714
{
715
    T1 = ~T0;
716
    T0 = T1 + xer_ca;
717
    if (T0 < T1) {
718
        xer_ca = 1;
719
    } else {
720
        xer_ca = 0;
721
    }
722
    RETURN();
723
}
724

    
725
PPC_OP(subfzeo)
726
{
727
    T1 = T0;
728
    T0 = ~T0 + xer_ca;
729
    if ((~T1 ^ (-1)) & ((~T1) ^ T0) & (1 << 31)) {
730
        xer_ov = 1;
731
        xer_so = 1;
732
    } else {
733
        xer_ov = 0;
734
    }
735
    if (T0 < ~T1) {
736
        xer_ca = 1;
737
    } else {
738
        xer_ca = 0;
739
    }
740
    RETURN();
741
}
742

    
743
/***                           Integer comparison                          ***/
744
/* compare */
745
PPC_OP(cmp)
746
{
747
    if (Ts0 < Ts1) {
748
        T0 = 0x08;
749
    } else if (Ts0 > Ts1) {
750
        T0 = 0x04;
751
    } else {
752
        T0 = 0x02;
753
    }
754
    RETURN();
755
}
756

    
757
/* compare immediate */
758
PPC_OP(cmpi)
759
{
760
    if (Ts0 < SPARAM(1)) {
761
        T0 = 0x08;
762
    } else if (Ts0 > SPARAM(1)) {
763
        T0 = 0x04;
764
    } else {
765
        T0 = 0x02;
766
    }
767
    RETURN();
768
}
769

    
770
/* compare logical */
771
PPC_OP(cmpl)
772
{
773
    if (T0 < T1) {
774
        T0 = 0x08;
775
    } else if (T0 > T1) {
776
        T0 = 0x04;
777
    } else {
778
        T0 = 0x02;
779
    }
780
    RETURN();
781
}
782

    
783
/* compare logical immediate */
784
PPC_OP(cmpli)
785
{
786
    if (T0 < PARAM(1)) {
787
        T0 = 0x08;
788
    } else if (T0 > PARAM(1)) {
789
        T0 = 0x04;
790
    } else {
791
        T0 = 0x02;
792
    }
793
    RETURN();
794
}
795

    
796
/***                            Integer logical                            ***/
797
/* and */
798
PPC_OP(and)
799
{
800
    T0 &= T1;
801
    RETURN();
802
}
803

    
804
/* andc */
805
PPC_OP(andc)
806
{
807
    T0 &= ~T1;
808
    RETURN();
809
}
810

    
811
/* andi. */
812
PPC_OP(andi_)
813
{
814
    T0 &= PARAM(1);
815
    RETURN();
816
}
817

    
818
/* count leading zero */
819
PPC_OP(cntlzw)
820
{
821
    T1 = T0;
822
    for (T0 = 32; T1 > 0; T0--)
823
        T1 = T1 >> 1;
824
    RETURN();
825
}
826

    
827
/* eqv */
828
PPC_OP(eqv)
829
{
830
    T0 = ~(T0 ^ T1);
831
    RETURN();
832
}
833

    
834
/* extend sign byte */
835
PPC_OP(extsb)
836
{
837
    Ts0 = s_ext8(Ts0);
838
    RETURN();
839
}
840

    
841
/* extend sign half word */
842
PPC_OP(extsh)
843
{
844
    Ts0 = s_ext16(Ts0);
845
    RETURN();
846
}
847

    
848
/* nand */
849
PPC_OP(nand)
850
{
851
    T0 = ~(T0 & T1);
852
    RETURN();
853
}
854

    
855
/* nor */
856
PPC_OP(nor)
857
{
858
    T0 = ~(T0 | T1);
859
    RETURN();
860
}
861

    
862
/* or */
863
PPC_OP(or)
864
{
865
    T0 |= T1;
866
    RETURN();
867
}
868

    
869
/* orc */
870
PPC_OP(orc)
871
{
872
    T0 |= ~T1;
873
    RETURN();
874
}
875

    
876
/* ori */
877
PPC_OP(ori)
878
{
879
    T0 |= PARAM(1);
880
    RETURN();
881
}
882

    
883
/* xor */
884
PPC_OP(xor)
885
{
886
    T0 ^= T1;
887
    RETURN();
888
}
889

    
890
/* xori */
891
PPC_OP(xori)
892
{
893
    T0 ^= PARAM(1);
894
    RETURN();
895
}
896

    
897
/***                             Integer rotate                            ***/
898
/* rotate left word immediate then mask insert */
899
PPC_OP(rlwimi)
900
{
901
    T0 = rotl(T0, PARAM(1) & PARAM(2)) | (T0 & PARAM(3));
902
    RETURN();
903
}
904

    
905
/* rotate left immediate then and with mask insert */
906
PPC_OP(rotlwi)
907
{
908
    T0 = rotl(T0, PARAM(1));
909
    RETURN();
910
}
911

    
912
PPC_OP(slwi)
913
{
914
    T0 = T0 << PARAM(1);
915
    RETURN();
916
}
917

    
918
PPC_OP(srwi)
919
{
920
    T0 = T0 >> PARAM(1);
921
    RETURN();
922
}
923

    
924
/* rotate left word then and with mask insert */
925
PPC_OP(rlwinm)
926
{
927
    T0 = rotl(T0, PARAM(1)) & PARAM(2);
928
    RETURN();
929
}
930

    
931
PPC_OP(rotl)
932
{
933
    T0 = rotl(T0, T1);
934
    RETURN();
935
}
936

    
937
PPC_OP(rlwnm)
938
{
939
    T0 = rotl(T0, T1) & PARAM(1);
940
    RETURN();
941
}
942

    
943
/***                             Integer shift                             ***/
944
/* shift left word */
945
PPC_OP(slw)
946
{
947
    if (T1 & 0x20) {
948
        T0 = 0;
949
    } else {
950
        T0 = T0 << T1;
951
    }
952
    RETURN();
953
}
954

    
955
/* shift right algebraic word */
956
PPC_OP(sraw)
957
{
958
    Ts0 = do_sraw(Ts0, T1);
959
    RETURN();
960
}
961

    
962
/* shift right algebraic word immediate */
963
PPC_OP(srawi)
964
{
965
    Ts1 = Ts0;
966
    Ts0 = Ts0 >> PARAM(1);
967
    if (Ts1 < 0 && (Ts1 & PARAM(2)) != 0) {
968
        xer_ca = 1;
969
    } else {
970
        xer_ca = 0;
971
    }
972
    RETURN();
973
}
974

    
975
/* shift right word */
976
PPC_OP(srw)
977
{
978
    if (T1 & 0x20) {
979
        T0 = 0;
980
    } else {
981
        T0 = T0 >> T1;
982
    }
983
    RETURN();
984
}
985

    
986
/***                       Floating-Point arithmetic                       ***/
987

    
988
/***                     Floating-Point multiply-and-add                   ***/
989

    
990
/***                     Floating-Point round & convert                    ***/
991

    
992
/***                         Floating-Point compare                        ***/
993

    
994
/***                  Floating-Point status & ctrl register                ***/
995

    
996
/***                             Integer load                              ***/
997
#define ld16x(x) s_ext16(ld16(x))
998
#define PPC_ILD_OPX(name, op)                                                 \
999
PPC_OP(l##name##x_z)                                                          \
1000
{                                                                             \
1001
    T1 = op(T0);                                                              \
1002
    RETURN();                                                                 \
1003
}                                                                             \
1004
PPC_OP(l##name##x)                                                            \
1005
{                                                                             \
1006
    T0 += T1;                                                                 \
1007
    T1 = op(T0);                                                              \
1008
    RETURN();                                                                 \
1009
}
1010

    
1011
#define PPC_ILD_OP(name, op)                                                  \
1012
PPC_OP(l##name##_z)                                                           \
1013
{                                                                             \
1014
    T1 = op(SPARAM(1));                                                       \
1015
    RETURN();                                                                 \
1016
}                                                                             \
1017
PPC_OP(l##name)                                                               \
1018
{                                                                             \
1019
    T0 += SPARAM(1);                                                          \
1020
    T1 = op(T0);                                                              \
1021
    RETURN();                                                                 \
1022
}                                                                             \
1023
PPC_ILD_OPX(name, op)
1024

    
1025
PPC_ILD_OP(bz, ld8);
1026
PPC_ILD_OP(ha, ld16x);
1027
PPC_ILD_OP(hz, ld16);
1028
PPC_ILD_OP(wz, ld32);
1029

    
1030
/***                              Integer store                            ***/
1031
#define PPC_IST_OPX(name, op)                                                 \
1032
PPC_OP(st##name##x_z)                                                         \
1033
{                                                                             \
1034
    op(T0, T1);                                                               \
1035
    RETURN();                                                                 \
1036
}                                                                             \
1037
PPC_OP(st##name##x)                                                           \
1038
{                                                                             \
1039
    T0 += T1;                                                                 \
1040
    op(T0, T2);                                                               \
1041
    RETURN();                                                                 \
1042
}
1043

    
1044
#define PPC_IST_OP(name, op)                                                  \
1045
PPC_OP(st##name##_z)                                                          \
1046
{                                                                             \
1047
    op(SPARAM(1), T0);                                                        \
1048
    RETURN();                                                                 \
1049
}                                                                             \
1050
PPC_OP(st##name)                                                              \
1051
{                                                                             \
1052
    T0 += SPARAM(1);                                                          \
1053
    op(T0, T1);                                                               \
1054
    RETURN();                                                                 \
1055
}                                                                             \
1056
PPC_IST_OPX(name, op);
1057

    
1058
PPC_IST_OP(b, st8);
1059
PPC_IST_OP(h, st16);
1060
PPC_IST_OP(w, st32);
1061

    
1062
/***                Integer load and store with byte reverse               ***/
1063
PPC_ILD_OPX(hbr, ld16r);
1064
PPC_ILD_OPX(wbr, ld32r);
1065
PPC_IST_OPX(hbr, st16r);
1066
PPC_IST_OPX(wbr, st32r);
1067

    
1068
/***                    Integer load and store multiple                    ***/
1069
PPC_OP(lmw)
1070
{
1071
    do_lmw(PARAM(1), SPARAM(2) + T0);
1072
    RETURN();
1073
}
1074

    
1075
PPC_OP(stmw)
1076
{
1077
    do_stmw(PARAM(1), SPARAM(2) + T0);
1078
    RETURN();
1079
}
1080

    
1081
/***                    Integer load and store strings                     ***/
1082
PPC_OP(lswi)
1083
{
1084
    do_lsw(PARAM(1), PARAM(2), T0);
1085
    RETURN();
1086
}
1087

    
1088
PPC_OP(lswx)
1089
{
1090
    do_lsw(PARAM(1), T0, T1 + T2);
1091
    RETURN();
1092
}
1093

    
1094
PPC_OP(stswi_z)
1095
{
1096
    do_stsw(PARAM(1), PARAM(2), 0);
1097
    RETURN();
1098
}
1099

    
1100
PPC_OP(stswi)
1101
{
1102
    do_stsw(PARAM(1), PARAM(2), T0);
1103
    RETURN();
1104
}
1105

    
1106
PPC_OP(stswx_z)
1107
{
1108
    do_stsw(PARAM(1), T0, T1);
1109
    RETURN();
1110
}
1111

    
1112
PPC_OP(stswx)
1113
{
1114
    do_stsw(PARAM(1), T0, T1 + T2);
1115
    RETURN();
1116
}