Statistics
| Branch: | Revision:

root / target-ppc / op.c @ ac9eb073

History | View | Annotate | Download (25.7 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 DEBUG_OP
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 FTS0 ((float)env->ft0)
36
#define FTS1 ((float)env->ft1)
37
#define FTS2 ((float)env->ft2)
38

    
39
#define PPC_OP(name) void glue(op_, name)(void)
40

    
41
#define REG 0
42
#include "op_template.h"
43

    
44
#define REG 1
45
#include "op_template.h"
46

    
47
#define REG 2
48
#include "op_template.h"
49

    
50
#define REG 3
51
#include "op_template.h"
52

    
53
#define REG 4
54
#include "op_template.h"
55

    
56
#define REG 5
57
#include "op_template.h"
58

    
59
#define REG 6
60
#include "op_template.h"
61

    
62
#define REG 7
63
#include "op_template.h"
64

    
65
#define REG 8
66
#include "op_template.h"
67

    
68
#define REG 9
69
#include "op_template.h"
70

    
71
#define REG 10
72
#include "op_template.h"
73

    
74
#define REG 11
75
#include "op_template.h"
76

    
77
#define REG 12
78
#include "op_template.h"
79

    
80
#define REG 13
81
#include "op_template.h"
82

    
83
#define REG 14
84
#include "op_template.h"
85

    
86
#define REG 15
87
#include "op_template.h"
88

    
89
#define REG 16
90
#include "op_template.h"
91

    
92
#define REG 17
93
#include "op_template.h"
94

    
95
#define REG 18
96
#include "op_template.h"
97

    
98
#define REG 19
99
#include "op_template.h"
100

    
101
#define REG 20
102
#include "op_template.h"
103

    
104
#define REG 21
105
#include "op_template.h"
106

    
107
#define REG 22
108
#include "op_template.h"
109

    
110
#define REG 23
111
#include "op_template.h"
112

    
113
#define REG 24
114
#include "op_template.h"
115

    
116
#define REG 25
117
#include "op_template.h"
118

    
119
#define REG 26
120
#include "op_template.h"
121

    
122
#define REG 27
123
#include "op_template.h"
124

    
125
#define REG 28
126
#include "op_template.h"
127

    
128
#define REG 29
129
#include "op_template.h"
130

    
131
#define REG 30
132
#include "op_template.h"
133

    
134
#define REG 31
135
#include "op_template.h"
136

    
137
/* PPC state maintenance operations */
138
/* set_Rc0 */
139
PPC_OP(set_Rc0)
140
{
141
    uint32_t tmp;
142

    
143
    if (Ts0 < 0) {
144
        tmp = 0x08;
145
    } else if (Ts0 > 0) {
146
        tmp = 0x04;
147
    } else {
148
        tmp = 0x02;
149
    }
150
    env->crf[0] = tmp;
151
    RETURN();
152
}
153

    
154
PPC_OP(set_Rc0_ov)
155
{
156
    uint32_t tmp;
157

    
158
    if (Ts0 < 0) {
159
        tmp = 0x08;
160
    } else if (Ts0 > 0) {
161
        tmp = 0x04;
162
    } else {
163
        tmp = 0x02;
164
    }
165
    tmp |= xer_ov;
166
    env->crf[0] = tmp;
167
    RETURN();
168
}
169

    
170
/* reset_Rc0 */
171
PPC_OP(reset_Rc0)
172
{
173
    env->crf[0] = 0x02 | xer_ov;
174
    RETURN();
175
}
176

    
177
/* set_Rc0_1 */
178
PPC_OP(set_Rc0_1)
179
{
180
    env->crf[0] = 0x04 | xer_ov;
181
    RETURN();
182
}
183

    
184
/* Set Rc1 (for floating point arithmetic) */
185
PPC_OP(set_Rc1)
186
{
187
    env->crf[1] = regs->fpscr[7];
188
    RETURN();
189
}
190

    
191
/* Constants load */
192
PPC_OP(set_T0)
193
{
194
    T0 = PARAM(1);
195
    RETURN();
196
}
197

    
198
PPC_OP(set_T1)
199
{
200
    T1 = PARAM(1);
201
    RETURN();
202
}
203

    
204
PPC_OP(set_T2)
205
{
206
    T2 = PARAM(1);
207
    RETURN();
208
}
209

    
210
/* Generate exceptions */
211
PPC_OP(queue_exception_err)
212
{
213
    do_queue_exception_err(PARAM(1), PARAM(2));
214
}
215

    
216
PPC_OP(queue_exception)
217
{
218
    do_queue_exception(PARAM(1));
219
}
220

    
221
PPC_OP(process_exceptions)
222
{
223
    if (env->exceptions != 0) {
224
        env->nip = PARAM(1);
225
        do_check_exception_state();
226
    }
227
}
228

    
229
/* Segment registers load and store with immediate index */
230
PPC_OP(load_srin)
231
{
232
    T0 = regs->sr[T1 >> 28];
233
    RETURN();
234
}
235

    
236
PPC_OP(store_srin)
237
{
238
#if defined (DEBUG_OP)
239
    dump_store_sr(T1 >> 28);
240
#endif
241
    regs->sr[T1 >> 28] = T0;
242
    RETURN();
243
}
244

    
245
PPC_OP(load_sdr1)
246
{
247
    T0 = regs->sdr1;
248
    RETURN();
249
}
250

    
251
PPC_OP(store_sdr1)
252
{
253
    regs->sdr1 = T0;
254
    RETURN();
255
}
256

    
257
PPC_OP(exit_tb)
258
{
259
    EXIT_TB();
260
}
261

    
262
/* Load/store special registers */
263
PPC_OP(load_cr)
264
{
265
    do_load_cr();
266
    RETURN();
267
}
268

    
269
PPC_OP(store_cr)
270
{
271
    do_store_cr(PARAM(1));
272
    RETURN();
273
}
274

    
275
PPC_OP(load_xer_cr)
276
{
277
    T0 = (xer_so << 3) | (xer_ov << 2) | (xer_ca << 1);
278
    RETURN();
279
}
280

    
281
PPC_OP(clear_xer_cr)
282
{
283
    xer_so = 0;
284
    xer_ov = 0;
285
    xer_ca = 0;
286
    RETURN();
287
}
288

    
289
PPC_OP(load_xer_bc)
290
{
291
    T1 = xer_bc;
292
    RETURN();
293
}
294

    
295
PPC_OP(load_xer)
296
{
297
    do_load_xer();
298
    RETURN();
299
}
300

    
301
PPC_OP(store_xer)
302
{
303
    do_store_xer();
304
    RETURN();
305
}
306

    
307
PPC_OP(load_msr)
308
{
309
    do_load_msr();
310
    RETURN();
311
}
312

    
313
PPC_OP(store_msr)
314
{
315
    do_store_msr();
316
    RETURN();
317
}
318

    
319
/* SPR */
320
PPC_OP(load_spr)
321
{
322
    T0 = regs->spr[PARAM(1)];
323
    RETURN();
324
}
325

    
326
PPC_OP(store_spr)
327
{
328
    regs->spr[PARAM(1)] = T0;
329
    RETURN();
330
}
331

    
332
PPC_OP(load_lr)
333
{
334
    T0 = regs->lr;
335
    RETURN();
336
}
337

    
338
PPC_OP(store_lr)
339
{
340
    regs->lr = T0;
341
    RETURN();
342
}
343

    
344
PPC_OP(load_ctr)
345
{
346
    T0 = regs->ctr;
347
    RETURN();
348
}
349

    
350
PPC_OP(store_ctr)
351
{
352
    regs->ctr = T0;
353
    RETURN();
354
}
355

    
356
/* Update time base */
357
PPC_OP(update_tb)
358
{
359
    T0 = regs->tb[0];
360
    T1 = T0;
361
    T0 += PARAM(1);
362
#if defined (DEBUG_OP)
363
    dump_update_tb(PARAM(1));
364
#endif
365
    if (T0 < T1) {
366
        T1 = regs->tb[1] + 1;
367
        regs->tb[1] = T1;
368
    }
369
    regs->tb[0] = T0;
370
    RETURN();
371
}
372

    
373
PPC_OP(load_tb)
374
{
375
    T0 = regs->tb[PARAM(1)];
376
    RETURN();
377
}
378

    
379
PPC_OP(store_tb)
380
{
381
    regs->tb[PARAM(1)] = T0;
382
#if defined (DEBUG_OP)
383
    dump_store_tb(PARAM(1));
384
#endif
385
    RETURN();
386
}
387

    
388
/* Update decrementer */
389
PPC_OP(update_decr)
390
{
391
    T0 = regs->decr;
392
    T1 = T0;
393
    T0 -= PARAM(1);
394
    regs->decr = T0;
395
    if (PARAM(1) > T1) {
396
        do_queue_exception(EXCP_DECR);
397
    }
398
    RETURN();
399
}
400

    
401
PPC_OP(store_decr)
402
{
403
    T1 = regs->decr;
404
    regs->decr = T0;
405
    if (Ts0 < 0 && Ts1 > 0) {
406
        do_queue_exception(EXCP_DECR);
407
    }
408
    RETURN();
409
}
410

    
411
PPC_OP(load_ibat)
412
{
413
    T0 = regs->IBAT[PARAM(1)][PARAM(2)];
414
}
415

    
416
PPC_OP(store_ibat)
417
{
418
#if defined (DEBUG_OP)
419
    dump_store_ibat(PARAM(1), PARAM(2));
420
#endif
421
    regs->IBAT[PARAM(1)][PARAM(2)] = T0;
422
}
423

    
424
PPC_OP(load_dbat)
425
{
426
    T0 = regs->DBAT[PARAM(1)][PARAM(2)];
427
}
428

    
429
PPC_OP(store_dbat)
430
{
431
#if defined (DEBUG_OP)
432
    dump_store_dbat(PARAM(1), PARAM(2));
433
#endif
434
    regs->DBAT[PARAM(1)][PARAM(2)] = T0;
435
}
436

    
437
/* FPSCR */
438
PPC_OP(load_fpscr)
439
{
440
    do_load_fpscr();
441
    RETURN();
442
}
443

    
444
PPC_OP(store_fpscr)
445
{
446
    do_store_fpscr(PARAM(1));
447
    RETURN();
448
}
449

    
450
PPC_OP(reset_scrfx)
451
{
452
    regs->fpscr[7] &= ~0x8;
453
    RETURN();
454
}
455

    
456
/* Set reservation */
457
PPC_OP(set_reservation)
458
{
459
    regs->reserve = T0 & ~0x03;
460
    RETURN();
461
}
462

    
463
/* crf operations */
464
PPC_OP(getbit_T0)
465
{
466
    T0 = (T0 >> PARAM(1)) & 1;
467
    RETURN();
468
}
469

    
470
PPC_OP(getbit_T1)
471
{
472
    T1 = (T1 >> PARAM(1)) & 1;
473
    RETURN();
474
}
475

    
476
PPC_OP(setcrfbit)
477
{
478
    T1 = (T1 & PARAM(1)) | (T0 << PARAM(2)); 
479
    RETURN();
480
}
481

    
482
/* Branch */
483
#if 0
484
#define EIP regs->nip
485
#define TB_DO_JUMP(name, tb, n, target) JUMP_TB(name, tb, n, target)
486
#else
487
#define TB_DO_JUMP(name, tb, n, target) regs->nip = target;
488
#endif
489

    
490
#define __PPC_OP_B(name, target)                                              \
491
PPC_OP(name)                                                                  \
492
{                                                                             \
493
    TB_DO_JUMP(glue(op_, name), T1, 0, (target));                             \
494
    RETURN();                                                                 \
495
}
496

    
497
#define __PPC_OP_BL(name, target, link)                                       \
498
PPC_OP(name)                                                                  \
499
{                                                                             \
500
    regs->lr = (link);                                                        \
501
    TB_DO_JUMP(glue(op_, name), T1, 0, (target));                             \
502
    RETURN();                                                                 \
503
}
504

    
505
#define PPC_OP_B(name, target, link)                                          \
506
__PPC_OP_B(name, target);                                                     \
507
__PPC_OP_BL(glue(name, l), target, link)
508

    
509
#define __PPC_OP_BC(name, cond, target)                                       \
510
PPC_OP(name)                                                                  \
511
{                                                                             \
512
    if (cond) {                                                               \
513
        TB_DO_JUMP(glue(op_, name), T1, 1, (target));                         \
514
    } else {                                                                  \
515
        TB_DO_JUMP(glue(op_, name), T1, 0, PARAM(1));                         \
516
    }                                                                         \
517
    RETURN();                                                                 \
518
}
519

    
520
#define __PPC_OP_BCL(name, cond, target)                                      \
521
PPC_OP(name)                                                                  \
522
{                                                                             \
523
    regs->lr = PARAM(1);                                                      \
524
    if (cond) {                                                               \
525
        TB_DO_JUMP(glue(op_, name), T1, 1, (target));                         \
526
    } else {                                                                  \
527
        TB_DO_JUMP(glue(op_, name), T1, 0, PARAM(1));                         \
528
    }                                                                         \
529
    RETURN();                                                                 \
530
}
531

    
532
#define __PPC_OP_BCLRL(name, cond, target)                                    \
533
PPC_OP(name)                                                                  \
534
{                                                                             \
535
    T2 = (target);                                                            \
536
    regs->lr = PARAM(1);                                                      \
537
    if (cond) {                                                               \
538
        TB_DO_JUMP(glue(op_, name), T1, 1, T2);                               \
539
    } else {                                                                  \
540
        TB_DO_JUMP(glue(op_, name), T1, 0, PARAM(1));                         \
541
    }                                                                         \
542
    RETURN();                                                                 \
543
}
544

    
545
#define _PPC_OP_BC(name, namel, cond, target)                                 \
546
__PPC_OP_BC(name, cond, target);                                              \
547
__PPC_OP_BCL(namel, cond, target)
548

    
549
/* Branch to target */
550
#define PPC_OP_BC(name, cond)                                                 \
551
_PPC_OP_BC(b_##name, bl_##name, cond, PARAM(2))
552

    
553
PPC_OP_B(b, PARAM(1), PARAM(2));
554
PPC_OP_BC(ctr,        (regs->ctr != 0));
555
PPC_OP_BC(ctr_true,   (regs->ctr != 0 && (T0 & PARAM(3)) != 0));
556
PPC_OP_BC(ctr_false,  (regs->ctr != 0 && (T0 & PARAM(3)) == 0));
557
PPC_OP_BC(ctrz,       (regs->ctr == 0));
558
PPC_OP_BC(ctrz_true,  (regs->ctr == 0 && (T0 & PARAM(3)) != 0));
559
PPC_OP_BC(ctrz_false, (regs->ctr == 0 && (T0 & PARAM(3)) == 0));
560
PPC_OP_BC(true,       ((T0 & PARAM(3)) != 0));
561
PPC_OP_BC(false,      ((T0 & PARAM(3)) == 0));
562

    
563
/* Branch to CTR */
564
#define PPC_OP_BCCTR(name, cond)                                              \
565
_PPC_OP_BC(bctr_##name, bctrl_##name, cond, regs->ctr & ~0x03)
566

    
567
PPC_OP_B(bctr, regs->ctr & ~0x03, PARAM(1));
568
PPC_OP_BCCTR(ctr,        (regs->ctr != 0));
569
PPC_OP_BCCTR(ctr_true,   (regs->ctr != 0 && (T0 & PARAM(2)) != 0));
570
PPC_OP_BCCTR(ctr_false,  (regs->ctr != 0 && (T0 & PARAM(2)) == 0));
571
PPC_OP_BCCTR(ctrz,       (regs->ctr == 0));
572
PPC_OP_BCCTR(ctrz_true,  (regs->ctr == 0 && (T0 & PARAM(2)) != 0));
573
PPC_OP_BCCTR(ctrz_false, (regs->ctr == 0 && (T0 & PARAM(2)) == 0));
574
PPC_OP_BCCTR(true,       ((T0 & PARAM(2)) != 0));
575
PPC_OP_BCCTR(false,      ((T0 & PARAM(2)) == 0));
576

    
577
/* Branch to LR */
578
#define PPC_OP_BCLR(name, cond)                                               \
579
__PPC_OP_BC(blr_##name, cond, regs->lr & ~0x03);                              \
580
__PPC_OP_BCLRL(blrl_##name, cond, regs->lr & ~0x03)
581

    
582
__PPC_OP_B(blr, regs->lr & ~0x03);
583
PPC_OP(blrl)
584
{
585
    T0 = regs->lr & ~0x03;
586
    regs->lr = PARAM(1);
587
    TB_DO_JUMP(op_blrl, T1, 0, T0);
588
    RETURN();
589
}
590
PPC_OP_BCLR(ctr,        (regs->ctr != 0));
591
PPC_OP_BCLR(ctr_true,   (regs->ctr != 0 && (T0 & PARAM(2)) != 0));
592
PPC_OP_BCLR(ctr_false,  (regs->ctr != 0 && (T0 & PARAM(2)) == 0));
593
PPC_OP_BCLR(ctrz,       (regs->ctr == 0));
594
PPC_OP_BCLR(ctrz_true,  (regs->ctr == 0 && (T0 & PARAM(2)) != 0));
595
PPC_OP_BCLR(ctrz_false, (regs->ctr == 0 && (T0 & PARAM(2)) == 0));
596
PPC_OP_BCLR(true,       ((T0 & PARAM(2)) != 0));
597
PPC_OP_BCLR(false,      ((T0 & PARAM(2)) == 0));
598

    
599
/* CTR maintenance */
600
PPC_OP(dec_ctr)
601
{
602
    regs->ctr--;
603
    RETURN();
604
}
605

    
606
/***                           Integer arithmetic                          ***/
607
/* add */
608
PPC_OP(add)
609
{
610
    T0 += T1;
611
    RETURN();
612
}
613

    
614
PPC_OP(addo)
615
{
616
    T2 = T0;
617
    T0 += T1;
618
    if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
619
        xer_so = 1;
620
        xer_ov = 1;
621
    } else {
622
        xer_ov = 0;
623
    }
624
    RETURN();
625
}
626

    
627
/* add carrying */
628
PPC_OP(addc)
629
{
630
    T2 = T0;
631
    T0 += T1;
632
    if (T0 < T2) {
633
        xer_ca = 1;
634
    } else {
635
        xer_ca = 0;
636
    }
637
    RETURN();
638
}
639

    
640
PPC_OP(addco)
641
{
642
    T2 = T0;
643
    T0 += T1;
644
    if (T0 < T2) {
645
        xer_ca = 1;
646
    } else {
647
        xer_ca = 0;
648
    }
649
    if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
650
        xer_so = 1;
651
        xer_ov = 1;
652
    } else {
653
        xer_ov = 0;
654
    }
655
    RETURN();
656
}
657

    
658
/* add extended */
659
/* candidate for helper (too long) */
660
PPC_OP(adde)
661
{
662
    T2 = T0;
663
    T0 += T1 + xer_ca;
664
    if (T0 < T2 || (xer_ca == 1 && T0 == T2)) {
665
        xer_ca = 1;
666
    } else {
667
        xer_ca = 0;
668
    }
669
    RETURN();
670
}
671

    
672
PPC_OP(addeo)
673
{
674
    T2 = T0;
675
    T0 += T1 + xer_ca;
676
    if (T0 < T2 || (xer_ca == 1 && T0 == T2)) {
677
        xer_ca = 1;
678
    } else {
679
        xer_ca = 0;
680
    }
681
    if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
682
        xer_so = 1;
683
        xer_ov = 1;
684
    } else {
685
        xer_ov = 0;
686
    }
687
    RETURN();
688
}
689

    
690
/* add immediate */
691
PPC_OP(addi)
692
{
693
    T0 += PARAM(1);
694
    RETURN();
695
}
696

    
697
/* add immediate carrying */
698
PPC_OP(addic)
699
{
700
    T1 = T0;
701
    T0 += PARAM(1);
702
    if (T0 < T1) {
703
        xer_ca = 1;
704
    } else {
705
        xer_ca = 0;
706
    }
707
    RETURN();
708
}
709

    
710
/* add to minus one extended */
711
PPC_OP(addme)
712
{
713
    T1 = T0;
714
    T0 += xer_ca + (-1);
715
    if (T1 != 0)
716
        xer_ca = 1;
717
    RETURN();
718
}
719

    
720
PPC_OP(addmeo)
721
{
722
    T1 = T0;
723
    T0 += xer_ca + (-1);
724
    if (T1 & (T1 ^ T0) & (1 << 31)) {
725
        xer_so = 1;
726
        xer_ov = 1;
727
    } else {
728
        xer_ov = 0;
729
    }
730
    if (T1 != 0)
731
        xer_ca = 1;
732
    RETURN();
733
}
734

    
735
/* add to zero extended */
736
PPC_OP(addze)
737
{
738
    T1 = T0;
739
    T0 += xer_ca;
740
    if (T0 < T1) {
741
        xer_ca = 1;
742
    } else {
743
        xer_ca = 0;
744
    }
745
    RETURN();
746
}
747

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

    
766
/* divide word */
767
/* candidate for helper (too long) */
768
PPC_OP(divw)
769
{
770
    if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
771
        Ts0 = (-1) * (T0 >> 31);
772
    } else {
773
        Ts0 /= Ts1;
774
    }
775
    RETURN();
776
}
777

    
778
PPC_OP(divwo)
779
{
780
    if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
781
        xer_so = 1;
782
        xer_ov = 1;
783
        T0 = (-1) * (T0 >> 31);
784
    } else {
785
        xer_ov = 0;
786
        Ts0 /= Ts1;
787
    }
788
    RETURN();
789
}
790

    
791
/* divide word unsigned */
792
PPC_OP(divwu)
793
{
794
    if (T1 == 0) {
795
        T0 = 0;
796
    } else {
797
        T0 /= T1;
798
    }
799
    RETURN();
800
}
801

    
802
PPC_OP(divwuo)
803
{
804
    if (T1 == 0) {
805
        xer_so = 1;
806
        xer_ov = 1;
807
        T0 = 0;
808
    } else {
809
        xer_ov = 0;
810
        T0 /= T1;
811
    }
812
    RETURN();
813
}
814

    
815
/* multiply high word */
816
PPC_OP(mulhw)
817
{
818
    Ts0 = ((int64_t)Ts0 * (int64_t)Ts1) >> 32;
819
    RETURN();
820
}
821

    
822
/* multiply high word unsigned */
823
PPC_OP(mulhwu)
824
{
825
    T0 = ((uint64_t)T0 * (uint64_t)T1) >> 32;
826
    RETURN();
827
}
828

    
829
/* multiply low immediate */
830
PPC_OP(mulli)
831
{
832
    Ts0 *= SPARAM(1);
833
    RETURN();
834
}
835

    
836
/* multiply low word */
837
PPC_OP(mullw)
838
{
839
    T0 *= T1;
840
    RETURN();
841
}
842

    
843
PPC_OP(mullwo)
844
{
845
    int64_t res = (int64_t)Ts0 * (int64_t)Ts1;
846

    
847
    if ((int32_t)res != res) {
848
        xer_ov = 1;
849
        xer_so = 1;
850
    } else {
851
        xer_ov = 0;
852
    }
853
    Ts0 = res;
854
    RETURN();
855
}
856

    
857
/* negate */
858
PPC_OP(neg)
859
{
860
    if (T0 != 0x80000000) {
861
        Ts0 = -Ts0;
862
    }
863
    RETURN();
864
}
865

    
866
PPC_OP(nego)
867
{
868
    if (T0 == 0x80000000) {
869
        xer_ov = 1;
870
        xer_so = 1;
871
    } else {
872
        xer_ov = 0;
873
        Ts0 = -Ts0;
874
    }
875
    RETURN();
876
}
877

    
878
/* substract from */
879
PPC_OP(subf)
880
{
881
    T0 = T1 - T0;
882
    RETURN();
883
}
884

    
885
PPC_OP(subfo)
886
{
887
    T2 = T0;
888
    T0 = T1 - T0;
889
    if (((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)) {
890
        xer_so = 1;
891
        xer_ov = 1;
892
    } else {
893
        xer_ov = 0;
894
    }
895
    RETURN();
896
}
897

    
898
/* substract from carrying */
899
PPC_OP(subfc)
900
{
901
    T0 = T1 - T0;
902
    if (T0 <= T1) {
903
        xer_ca = 1;
904
    } else {
905
        xer_ca = 0;
906
    }
907
    RETURN();
908
}
909

    
910
PPC_OP(subfco)
911
{
912
    T2 = T0;
913
    T0 = T1 - T0;
914
    if (T0 <= T1) {
915
        xer_ca = 1;
916
    } else {
917
        xer_ca = 0;
918
    }
919
    if (((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)) {
920
        xer_so = 1;
921
        xer_ov = 1;
922
    } else {
923
        xer_ov = 0;
924
    }
925
    RETURN();
926
}
927

    
928
/* substract from extended */
929
/* candidate for helper (too long) */
930
PPC_OP(subfe)
931
{
932
    T0 = T1 + ~T0 + xer_ca;
933
    if (T0 < T1 || (xer_ca == 1 && T0 == T1)) {
934
        xer_ca = 1;
935
    } else {
936
        xer_ca = 0;
937
    }
938
    RETURN();
939
}
940

    
941
PPC_OP(subfeo)
942
{
943
    T2 = T0;
944
    T0 = T1 + ~T0 + xer_ca;
945
    if ((~T2 ^ T1 ^ (-1)) & (~T2 ^ T0) & (1 << 31)) {
946
        xer_so = 1;
947
        xer_ov = 1;
948
    } else {
949
        xer_ov = 0;
950
    }
951
    if (T0 < T1 || (xer_ca == 1 && T0 == T1)) {
952
        xer_ca = 1;
953
    } else {
954
        xer_ca = 0;
955
    }
956
    RETURN();
957
}
958

    
959
/* substract from immediate carrying */
960
PPC_OP(subfic)
961
{
962
    T0 = PARAM(1) + ~T0 + 1;
963
    if (T0 <= PARAM(1)) {
964
        xer_ca = 1;
965
    } else {
966
        xer_ca = 0;
967
    }
968
    RETURN();
969
}
970

    
971
/* substract from minus one extended */
972
PPC_OP(subfme)
973
{
974
    T0 = ~T0 + xer_ca - 1;
975

    
976
    if (T0 != -1)
977
        xer_ca = 1;
978
    RETURN();
979
}
980

    
981
PPC_OP(subfmeo)
982
{
983
    T1 = T0;
984
    T0 = ~T0 + xer_ca - 1;
985
    if (~T1 & (~T1 ^ T0) & (1 << 31)) {
986
        xer_so = 1;
987
        xer_ov = 1;
988
    } else {
989
        xer_ov = 0;
990
    }
991
    if (T1 != -1)
992
        xer_ca = 1;
993
    RETURN();
994
}
995

    
996
/* substract from zero extended */
997
PPC_OP(subfze)
998
{
999
    T1 = ~T0;
1000
    T0 = T1 + xer_ca;
1001
    if (T0 < T1) {
1002
        xer_ca = 1;
1003
    } else {
1004
        xer_ca = 0;
1005
    }
1006
    RETURN();
1007
}
1008

    
1009
PPC_OP(subfzeo)
1010
{
1011
    T1 = T0;
1012
    T0 = ~T0 + xer_ca;
1013
    if ((~T1 ^ (-1)) & ((~T1) ^ T0) & (1 << 31)) {
1014
        xer_ov = 1;
1015
        xer_so = 1;
1016
    } else {
1017
        xer_ov = 0;
1018
    }
1019
    if (T0 < ~T1) {
1020
        xer_ca = 1;
1021
    } else {
1022
        xer_ca = 0;
1023
    }
1024
    RETURN();
1025
}
1026

    
1027
/***                           Integer comparison                          ***/
1028
/* compare */
1029
PPC_OP(cmp)
1030
{
1031
    if (Ts0 < Ts1) {
1032
        T0 = 0x08;
1033
    } else if (Ts0 > Ts1) {
1034
        T0 = 0x04;
1035
    } else {
1036
        T0 = 0x02;
1037
    }
1038
    RETURN();
1039
}
1040

    
1041
/* compare immediate */
1042
PPC_OP(cmpi)
1043
{
1044
    if (Ts0 < SPARAM(1)) {
1045
        T0 = 0x08;
1046
    } else if (Ts0 > SPARAM(1)) {
1047
        T0 = 0x04;
1048
    } else {
1049
        T0 = 0x02;
1050
    }
1051
    RETURN();
1052
}
1053

    
1054
/* compare logical */
1055
PPC_OP(cmpl)
1056
{
1057
    if (T0 < T1) {
1058
        T0 = 0x08;
1059
    } else if (T0 > T1) {
1060
        T0 = 0x04;
1061
    } else {
1062
        T0 = 0x02;
1063
    }
1064
    RETURN();
1065
}
1066

    
1067
/* compare logical immediate */
1068
PPC_OP(cmpli)
1069
{
1070
    if (T0 < PARAM(1)) {
1071
        T0 = 0x08;
1072
    } else if (T0 > PARAM(1)) {
1073
        T0 = 0x04;
1074
    } else {
1075
        T0 = 0x02;
1076
    }
1077
    RETURN();
1078
}
1079

    
1080
/***                            Integer logical                            ***/
1081
/* and */
1082
PPC_OP(and)
1083
{
1084
    T0 &= T1;
1085
    RETURN();
1086
}
1087

    
1088
/* andc */
1089
PPC_OP(andc)
1090
{
1091
    T0 &= ~T1;
1092
    RETURN();
1093
}
1094

    
1095
/* andi. */
1096
PPC_OP(andi_)
1097
{
1098
    T0 &= PARAM(1);
1099
    RETURN();
1100
}
1101

    
1102
/* count leading zero */
1103
PPC_OP(cntlzw)
1104
{
1105
    T1 = T0;
1106
    for (T0 = 32; T1 > 0; T0--)
1107
        T1 = T1 >> 1;
1108
    RETURN();
1109
}
1110

    
1111
/* eqv */
1112
PPC_OP(eqv)
1113
{
1114
    T0 = ~(T0 ^ T1);
1115
    RETURN();
1116
}
1117

    
1118
/* extend sign byte */
1119
PPC_OP(extsb)
1120
{
1121
    Ts0 = s_ext8(Ts0);
1122
    RETURN();
1123
}
1124

    
1125
/* extend sign half word */
1126
PPC_OP(extsh)
1127
{
1128
    Ts0 = s_ext16(Ts0);
1129
    RETURN();
1130
}
1131

    
1132
/* nand */
1133
PPC_OP(nand)
1134
{
1135
    T0 = ~(T0 & T1);
1136
    RETURN();
1137
}
1138

    
1139
/* nor */
1140
PPC_OP(nor)
1141
{
1142
    T0 = ~(T0 | T1);
1143
    RETURN();
1144
}
1145

    
1146
/* or */
1147
PPC_OP(or)
1148
{
1149
    T0 |= T1;
1150
    RETURN();
1151
}
1152

    
1153
/* orc */
1154
PPC_OP(orc)
1155
{
1156
    T0 |= ~T1;
1157
    RETURN();
1158
}
1159

    
1160
/* ori */
1161
PPC_OP(ori)
1162
{
1163
    T0 |= PARAM(1);
1164
    RETURN();
1165
}
1166

    
1167
/* xor */
1168
PPC_OP(xor)
1169
{
1170
    T0 ^= T1;
1171
    RETURN();
1172
}
1173

    
1174
/* xori */
1175
PPC_OP(xori)
1176
{
1177
    T0 ^= PARAM(1);
1178
    RETURN();
1179
}
1180

    
1181
/***                             Integer rotate                            ***/
1182
/* rotate left word immediate then mask insert */
1183
PPC_OP(rlwimi)
1184
{
1185
    T0 = (rotl(T0, PARAM(1)) & PARAM(2)) | (T1 & PARAM(3));
1186
    RETURN();
1187
}
1188

    
1189
/* rotate left immediate then and with mask insert */
1190
PPC_OP(rotlwi)
1191
{
1192
    T0 = rotl(T0, PARAM(1));
1193
    RETURN();
1194
}
1195

    
1196
PPC_OP(slwi)
1197
{
1198
    T0 = T0 << PARAM(1);
1199
    RETURN();
1200
}
1201

    
1202
PPC_OP(srwi)
1203
{
1204
    T0 = T0 >> PARAM(1);
1205
    RETURN();
1206
}
1207

    
1208
/* rotate left word then and with mask insert */
1209
PPC_OP(rlwinm)
1210
{
1211
    T0 = rotl(T0, PARAM(1)) & PARAM(2);
1212
    RETURN();
1213
}
1214

    
1215
PPC_OP(rotl)
1216
{
1217
    T0 = rotl(T0, T1);
1218
    RETURN();
1219
}
1220

    
1221
PPC_OP(rlwnm)
1222
{
1223
    T0 = rotl(T0, T1) & PARAM(1);
1224
    RETURN();
1225
}
1226

    
1227
/***                             Integer shift                             ***/
1228
/* shift left word */
1229
PPC_OP(slw)
1230
{
1231
    if (T1 & 0x20) {
1232
        T0 = 0;
1233
    } else {
1234
        T0 = T0 << T1;
1235
    }
1236
    RETURN();
1237
}
1238

    
1239
/* shift right algebraic word */
1240
PPC_OP(sraw)
1241
{
1242
    do_sraw();
1243
    RETURN();
1244
}
1245

    
1246
/* shift right algebraic word immediate */
1247
PPC_OP(srawi)
1248
{
1249
    Ts1 = Ts0;
1250
    Ts0 = Ts0 >> PARAM(1);
1251
    if (Ts1 < 0 && (Ts1 & PARAM(2)) != 0) {
1252
        xer_ca = 1;
1253
    } else {
1254
        xer_ca = 0;
1255
    }
1256
    RETURN();
1257
}
1258

    
1259
/* shift right word */
1260
PPC_OP(srw)
1261
{
1262
    if (T1 & 0x20) {
1263
        T0 = 0;
1264
    } else {
1265
        T0 = T0 >> T1;
1266
    }
1267
    RETURN();
1268
}
1269

    
1270
/***                       Floating-Point arithmetic                       ***/
1271
/* fadd - fadd. */
1272
PPC_OP(fadd)
1273
{
1274
    FT0 += FT1;
1275
    RETURN();
1276
}
1277

    
1278
/* fadds - fadds. */
1279
PPC_OP(fadds)
1280
{
1281
    FTS0 += FTS1;
1282
    RETURN();
1283
}
1284

    
1285
/* fsub - fsub. */
1286
PPC_OP(fsub)
1287
{
1288
    FT0 -= FT1;
1289
    RETURN();
1290
}
1291

    
1292
/* fsubs - fsubs. */
1293
PPC_OP(fsubs)
1294
{
1295
    FTS0 -= FTS1;
1296
    RETURN();
1297
}
1298

    
1299
/* fmul - fmul. */
1300
PPC_OP(fmul)
1301
{
1302
    FT0 *= FT1;
1303
    RETURN();
1304
}
1305

    
1306
/* fmuls - fmuls. */
1307
PPC_OP(fmuls)
1308
{
1309
    FTS0 *= FTS1;
1310
    RETURN();
1311
}
1312

    
1313
/* fdiv - fdiv. */
1314
PPC_OP(fdiv)
1315
{
1316
    FT0 /= FT1;
1317
    RETURN();
1318
}
1319

    
1320
/* fdivs - fdivs. */
1321
PPC_OP(fdivs)
1322
{
1323
    FTS0 /= FTS1;
1324
    RETURN();
1325
}
1326

    
1327
/* fsqrt - fsqrt. */
1328
PPC_OP(fsqrt)
1329
{
1330
    do_fsqrt();
1331
    RETURN();
1332
}
1333

    
1334
/* fsqrts - fsqrts. */
1335
PPC_OP(fsqrts)
1336
{
1337
    do_fsqrts();
1338
    RETURN();
1339
}
1340

    
1341
/* fres - fres. */
1342
PPC_OP(fres)
1343
{
1344
    do_fres();
1345
    RETURN();
1346
}
1347

    
1348
/* frsqrte  - frsqrte. */
1349
PPC_OP(frsqrte)
1350
{
1351
    do_fsqrte();
1352
    RETURN();
1353
}
1354

    
1355
/* fsel - fsel. */
1356
PPC_OP(fsel)
1357
{
1358
    do_fsel();
1359
    RETURN();
1360
}
1361

    
1362
/***                     Floating-Point multiply-and-add                   ***/
1363
/* fmadd - fmadd. */
1364
PPC_OP(fmadd)
1365
{
1366
    FT0 = (FT0 * FT1) + FT2;
1367
    RETURN();
1368
}
1369

    
1370
/* fmadds - fmadds. */
1371
PPC_OP(fmadds)
1372
{
1373
    FTS0 = (FTS0 * FTS1) + FTS2;
1374
    RETURN();
1375
}
1376

    
1377
/* fmsub - fmsub. */
1378
PPC_OP(fmsub)
1379
{
1380
    FT0 = (FT0 * FT1) - FT2;
1381
    RETURN();
1382
}
1383

    
1384
/* fmsubs - fmsubs. */
1385
PPC_OP(fmsubs)
1386
{
1387
    FTS0 = (FTS0 * FTS1) - FTS2;
1388
    RETURN();
1389
}
1390

    
1391
/* fnmadd - fnmadd. - fnmadds - fnmadds. */
1392
PPC_OP(fnmadd)
1393
{
1394
    FT0 = -((FT0 * FT1) + FT2);
1395
    RETURN();
1396
}
1397

    
1398
/* fnmadds - fnmadds. */
1399
PPC_OP(fnmadds)
1400
{
1401
    FTS0 = -((FTS0 * FTS1) + FTS2);
1402
    RETURN();
1403
}
1404

    
1405
/* fnmsub - fnmsub. */
1406
PPC_OP(fnmsub)
1407
{
1408
    FT0 = -((FT0 * FT1) - FT2);
1409
    RETURN();
1410
}
1411

    
1412
/* fnmsubs - fnmsubs. */
1413
PPC_OP(fnmsubs)
1414
{
1415
    FTS0 = -((FTS0 * FTS1) - FTS2);
1416
    RETURN();
1417
}
1418

    
1419
/***                     Floating-Point round & convert                    ***/
1420
/* frsp - frsp. */
1421
PPC_OP(frsp)
1422
{
1423
    FT0 = FTS0;
1424
    RETURN();
1425
}
1426

    
1427
/* fctiw - fctiw. */
1428
PPC_OP(fctiw)
1429
{
1430
    do_fctiw();
1431
    RETURN();
1432
}
1433

    
1434
/* fctiwz - fctiwz. */
1435
PPC_OP(fctiwz)
1436
{
1437
    do_fctiwz();
1438
    RETURN();
1439
}
1440

    
1441

    
1442
/***                         Floating-Point compare                        ***/
1443
/* fcmpu */
1444
PPC_OP(fcmpu)
1445
{
1446
    do_fcmpu();
1447
    RETURN();
1448
}
1449

    
1450
/* fcmpo */
1451
PPC_OP(fcmpo)
1452
{
1453
    do_fcmpo();
1454
    RETURN();
1455
}
1456

    
1457
/***                         Floating-point move                           ***/
1458
/* fabs */
1459
PPC_OP(fabs)
1460
{
1461
    do_fabs();
1462
    RETURN();
1463
}
1464

    
1465
/* fnabs */
1466
PPC_OP(fnabs)
1467
{
1468
    do_fnabs();
1469
    RETURN();
1470
}
1471

    
1472
/* fneg */
1473
PPC_OP(fneg)
1474
{
1475
    FT0 = -FT0;
1476
    RETURN();
1477
}
1478

    
1479
/* Load and store */
1480
#if defined(CONFIG_USER_ONLY)
1481
#define MEMSUFFIX _raw
1482
#include "op_mem.h"
1483
#else
1484
#define MEMSUFFIX _user
1485
#include "op_mem.h"
1486

    
1487
#define MEMSUFFIX _kernel
1488
#include "op_mem.h"
1489
#endif
1490

    
1491
/* Return from interrupt */
1492
PPC_OP(rfi)
1493
{
1494
    T0 = regs->spr[SRR1] & ~0xFFFF0000;
1495
    do_store_msr();
1496
    do_tlbia();
1497
    dump_rfi();
1498
    regs->nip = regs->spr[SRR0] & ~0x00000003;
1499
    if (env->exceptions != 0) {
1500
        do_check_exception_state();
1501
    }
1502
    RETURN();
1503
}
1504

    
1505
/* Trap word */
1506
PPC_OP(tw)
1507
{
1508
    if ((Ts0 < Ts1 && (PARAM(1) & 0x10)) ||
1509
        (Ts0 > Ts1 && (PARAM(1) & 0x08)) ||
1510
        (Ts0 == Ts1 && (PARAM(1) & 0x04)) ||
1511
        (T0 < T1 && (PARAM(1) & 0x02)) ||
1512
        (T0 > T1 && (PARAM(1) & 0x01)))
1513
        do_queue_exception_err(EXCP_PROGRAM, EXCP_TRAP);
1514
    RETURN();
1515
}
1516

    
1517
PPC_OP(twi)
1518
{
1519
    if ((Ts0 < SPARAM(1) && (PARAM(2) & 0x10)) ||
1520
        (Ts0 > SPARAM(1) && (PARAM(2) & 0x08)) ||
1521
        (Ts0 == SPARAM(1) && (PARAM(2) & 0x04)) ||
1522
        (T0 < (uint32_t)SPARAM(1) && (PARAM(2) & 0x02)) ||
1523
        (T0 > (uint32_t)SPARAM(1) && (PARAM(2) & 0x01)))
1524
        do_queue_exception_err(EXCP_PROGRAM, EXCP_TRAP);
1525
    RETURN();
1526
}
1527

    
1528
/* Instruction cache block invalidate */
1529
PPC_OP(icbi)
1530
{
1531
    do_icbi();
1532
    RETURN();
1533
}
1534

    
1535
/* tlbia */
1536
PPC_OP(tlbia)
1537
{
1538
    do_tlbia();
1539
    RETURN();
1540
}
1541

    
1542
/* tlbie */
1543
PPC_OP(tlbie)
1544
{
1545
    do_tlbie();
1546
    RETURN();
1547
}