Statistics
| Branch: | Revision:

root / target-mips / op.c @ 09c69c5b

History | View | Annotate | Download (57.6 kB)

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

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

    
25
#ifndef CALL_FROM_TB0
26
#define CALL_FROM_TB0(func) func()
27
#endif
28
#ifndef CALL_FROM_TB1
29
#define CALL_FROM_TB1(func, arg0) func(arg0)
30
#endif
31
#ifndef CALL_FROM_TB1_CONST16
32
#define CALL_FROM_TB1_CONST16(func, arg0) CALL_FROM_TB1(func, arg0)
33
#endif
34
#ifndef CALL_FROM_TB2
35
#define CALL_FROM_TB2(func, arg0, arg1) func(arg0, arg1)
36
#endif
37
#ifndef CALL_FROM_TB2_CONST16
38
#define CALL_FROM_TB2_CONST16(func, arg0, arg1)     \
39
        CALL_FROM_TB2(func, arg0, arg1)
40
#endif
41
#ifndef CALL_FROM_TB3
42
#define CALL_FROM_TB3(func, arg0, arg1, arg2) func(arg0, arg1, arg2)
43
#endif
44
#ifndef CALL_FROM_TB4
45
#define CALL_FROM_TB4(func, arg0, arg1, arg2, arg3) \
46
        func(arg0, arg1, arg2, arg3)
47
#endif
48

    
49
#define REG 1
50
#include "op_template.c"
51
#undef REG
52
#define REG 2
53
#include "op_template.c"
54
#undef REG
55
#define REG 3
56
#include "op_template.c"
57
#undef REG
58
#define REG 4
59
#include "op_template.c"
60
#undef REG
61
#define REG 5
62
#include "op_template.c"
63
#undef REG
64
#define REG 6
65
#include "op_template.c"
66
#undef REG
67
#define REG 7
68
#include "op_template.c"
69
#undef REG
70
#define REG 8
71
#include "op_template.c"
72
#undef REG
73
#define REG 9
74
#include "op_template.c"
75
#undef REG
76
#define REG 10
77
#include "op_template.c"
78
#undef REG
79
#define REG 11
80
#include "op_template.c"
81
#undef REG
82
#define REG 12
83
#include "op_template.c"
84
#undef REG
85
#define REG 13
86
#include "op_template.c"
87
#undef REG
88
#define REG 14
89
#include "op_template.c"
90
#undef REG
91
#define REG 15
92
#include "op_template.c"
93
#undef REG
94
#define REG 16
95
#include "op_template.c"
96
#undef REG
97
#define REG 17
98
#include "op_template.c"
99
#undef REG
100
#define REG 18
101
#include "op_template.c"
102
#undef REG
103
#define REG 19
104
#include "op_template.c"
105
#undef REG
106
#define REG 20
107
#include "op_template.c"
108
#undef REG
109
#define REG 21
110
#include "op_template.c"
111
#undef REG
112
#define REG 22
113
#include "op_template.c"
114
#undef REG
115
#define REG 23
116
#include "op_template.c"
117
#undef REG
118
#define REG 24
119
#include "op_template.c"
120
#undef REG
121
#define REG 25
122
#include "op_template.c"
123
#undef REG
124
#define REG 26
125
#include "op_template.c"
126
#undef REG
127
#define REG 27
128
#include "op_template.c"
129
#undef REG
130
#define REG 28
131
#include "op_template.c"
132
#undef REG
133
#define REG 29
134
#include "op_template.c"
135
#undef REG
136
#define REG 30
137
#include "op_template.c"
138
#undef REG
139
#define REG 31
140
#include "op_template.c"
141
#undef REG
142

    
143
#define TN
144
#include "op_template.c"
145
#undef TN
146

    
147
#define FREG 0
148
#include "fop_template.c"
149
#undef FREG
150
#define FREG 1
151
#include "fop_template.c"
152
#undef FREG
153
#define FREG 2
154
#include "fop_template.c"
155
#undef FREG
156
#define FREG 3
157
#include "fop_template.c"
158
#undef FREG
159
#define FREG 4
160
#include "fop_template.c"
161
#undef FREG
162
#define FREG 5
163
#include "fop_template.c"
164
#undef FREG
165
#define FREG 6
166
#include "fop_template.c"
167
#undef FREG
168
#define FREG 7
169
#include "fop_template.c"
170
#undef FREG
171
#define FREG 8
172
#include "fop_template.c"
173
#undef FREG
174
#define FREG 9
175
#include "fop_template.c"
176
#undef FREG
177
#define FREG 10
178
#include "fop_template.c"
179
#undef FREG
180
#define FREG 11
181
#include "fop_template.c"
182
#undef FREG
183
#define FREG 12
184
#include "fop_template.c"
185
#undef FREG
186
#define FREG 13
187
#include "fop_template.c"
188
#undef FREG
189
#define FREG 14
190
#include "fop_template.c"
191
#undef FREG
192
#define FREG 15
193
#include "fop_template.c"
194
#undef FREG
195
#define FREG 16
196
#include "fop_template.c"
197
#undef FREG
198
#define FREG 17
199
#include "fop_template.c"
200
#undef FREG
201
#define FREG 18
202
#include "fop_template.c"
203
#undef FREG
204
#define FREG 19
205
#include "fop_template.c"
206
#undef FREG
207
#define FREG 20
208
#include "fop_template.c"
209
#undef FREG
210
#define FREG 21
211
#include "fop_template.c"
212
#undef FREG
213
#define FREG 22
214
#include "fop_template.c"
215
#undef FREG
216
#define FREG 23
217
#include "fop_template.c"
218
#undef FREG
219
#define FREG 24
220
#include "fop_template.c"
221
#undef FREG
222
#define FREG 25
223
#include "fop_template.c"
224
#undef FREG
225
#define FREG 26
226
#include "fop_template.c"
227
#undef FREG
228
#define FREG 27
229
#include "fop_template.c"
230
#undef FREG
231
#define FREG 28
232
#include "fop_template.c"
233
#undef FREG
234
#define FREG 29
235
#include "fop_template.c"
236
#undef FREG
237
#define FREG 30
238
#include "fop_template.c"
239
#undef FREG
240
#define FREG 31
241
#include "fop_template.c"
242
#undef FREG
243

    
244
#define FTN
245
#include "fop_template.c"
246
#undef FTN
247

    
248
void op_dup_T0 (void)
249
{
250
    T2 = T0;
251
    RETURN();
252
}
253

    
254
void op_load_HI (void)
255
{
256
    T0 = env->HI;
257
    RETURN();
258
}
259

    
260
void op_store_HI (void)
261
{
262
    env->HI = T0;
263
    RETURN();
264
}
265

    
266
void op_load_LO (void)
267
{
268
    T0 = env->LO;
269
    RETURN();
270
}
271

    
272
void op_store_LO (void)
273
{
274
    env->LO = T0;
275
    RETURN();
276
}
277

    
278
/* Load and store */
279
#define MEMSUFFIX _raw
280
#include "op_mem.c"
281
#undef MEMSUFFIX
282
#if !defined(CONFIG_USER_ONLY)
283
#define MEMSUFFIX _user
284
#include "op_mem.c"
285
#undef MEMSUFFIX
286

    
287
#define MEMSUFFIX _kernel
288
#include "op_mem.c"
289
#undef MEMSUFFIX
290
#endif
291

    
292
/* Arithmetic */
293
void op_add (void)
294
{
295
    T0 = (int32_t)((int32_t)T0 + (int32_t)T1);
296
    RETURN();
297
}
298

    
299
void op_addo (void)
300
{
301
    target_ulong tmp;
302

    
303
    tmp = (int32_t)T0;
304
    T0 = (int32_t)T0 + (int32_t)T1;
305
    if (((tmp ^ T1 ^ (-1)) & (T0 ^ T1)) >> 31) {
306
        /* operands of same sign, result different sign */
307
        CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
308
    }
309
    T0 = (int32_t)T0;
310
    RETURN();
311
}
312

    
313
void op_sub (void)
314
{
315
    T0 = (int32_t)((int32_t)T0 - (int32_t)T1);
316
    RETURN();
317
}
318

    
319
void op_subo (void)
320
{
321
    target_ulong tmp;
322

    
323
    tmp = (int32_t)T0;
324
    T0 = (int32_t)T0 - (int32_t)T1;
325
    if (((tmp ^ T1) & (tmp ^ T0)) >> 31) {
326
        /* operands of different sign, first operand and result different sign */
327
        CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
328
    }
329
    T0 = (int32_t)T0;
330
    RETURN();
331
}
332

    
333
void op_mul (void)
334
{
335
    T0 = (int32_t)((int32_t)T0 * (int32_t)T1);
336
    RETURN();
337
}
338

    
339
#if HOST_LONG_BITS < 64
340
void op_div (void)
341
{
342
    CALL_FROM_TB0(do_div);
343
    RETURN();
344
}
345
#else
346
void op_div (void)
347
{
348
    if (T1 != 0) {
349
        env->LO = (int32_t)((int64_t)(int32_t)T0 / (int32_t)T1);
350
        env->HI = (int32_t)((int64_t)(int32_t)T0 % (int32_t)T1);
351
    }
352
    RETURN();
353
}
354
#endif
355

    
356
void op_divu (void)
357
{
358
    if (T1 != 0) {
359
        env->LO = (int32_t)((uint32_t)T0 / (uint32_t)T1);
360
        env->HI = (int32_t)((uint32_t)T0 % (uint32_t)T1);
361
    }
362
    RETURN();
363
}
364

    
365
#ifdef TARGET_MIPS64
366
/* Arithmetic */
367
void op_dadd (void)
368
{
369
    T0 += T1;
370
    RETURN();
371
}
372

    
373
void op_daddo (void)
374
{
375
    target_long tmp;
376

    
377
    tmp = T0;
378
    T0 += T1;
379
    if (((tmp ^ T1 ^ (-1)) & (T0 ^ T1)) >> 63) {
380
        /* operands of same sign, result different sign */
381
        CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
382
    }
383
    RETURN();
384
}
385

    
386
void op_dsub (void)
387
{
388
    T0 -= T1;
389
    RETURN();
390
}
391

    
392
void op_dsubo (void)
393
{
394
    target_long tmp;
395

    
396
    tmp = T0;
397
    T0 = (int64_t)T0 - (int64_t)T1;
398
    if (((tmp ^ T1) & (tmp ^ T0)) >> 63) {
399
        /* operands of different sign, first operand and result different sign */
400
        CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
401
    }
402
    RETURN();
403
}
404

    
405
void op_dmul (void)
406
{
407
    T0 = (int64_t)T0 * (int64_t)T1;
408
    RETURN();
409
}
410

    
411
/* Those might call libgcc functions.  */
412
void op_ddiv (void)
413
{
414
    do_ddiv();
415
    RETURN();
416
}
417

    
418
#if TARGET_LONG_BITS > HOST_LONG_BITS
419
void op_ddivu (void)
420
{
421
    do_ddivu();
422
    RETURN();
423
}
424
#else
425
void op_ddivu (void)
426
{
427
    if (T1 != 0) {
428
        env->LO = T0 / T1;
429
        env->HI = T0 % T1;
430
    }
431
    RETURN();
432
}
433
#endif
434
#endif /* TARGET_MIPS64 */
435

    
436
/* Logical */
437
void op_and (void)
438
{
439
    T0 &= T1;
440
    RETURN();
441
}
442

    
443
void op_nor (void)
444
{
445
    T0 = ~(T0 | T1);
446
    RETURN();
447
}
448

    
449
void op_or (void)
450
{
451
    T0 |= T1;
452
    RETURN();
453
}
454

    
455
void op_xor (void)
456
{
457
    T0 ^= T1;
458
    RETURN();
459
}
460

    
461
void op_sll (void)
462
{
463
    T0 = (int32_t)((uint32_t)T0 << T1);
464
    RETURN();
465
}
466

    
467
void op_sra (void)
468
{
469
    T0 = (int32_t)((int32_t)T0 >> T1);
470
    RETURN();
471
}
472

    
473
void op_srl (void)
474
{
475
    T0 = (int32_t)((uint32_t)T0 >> T1);
476
    RETURN();
477
}
478

    
479
void op_rotr (void)
480
{
481
    target_ulong tmp;
482

    
483
    if (T1) {
484
       tmp = (int32_t)((uint32_t)T0 << (0x20 - T1));
485
       T0 = (int32_t)((uint32_t)T0 >> T1) | tmp;
486
    }
487
    RETURN();
488
}
489

    
490
void op_sllv (void)
491
{
492
    T0 = (int32_t)((uint32_t)T1 << ((uint32_t)T0 & 0x1F));
493
    RETURN();
494
}
495

    
496
void op_srav (void)
497
{
498
    T0 = (int32_t)((int32_t)T1 >> (T0 & 0x1F));
499
    RETURN();
500
}
501

    
502
void op_srlv (void)
503
{
504
    T0 = (int32_t)((uint32_t)T1 >> (T0 & 0x1F));
505
    RETURN();
506
}
507

    
508
void op_rotrv (void)
509
{
510
    target_ulong tmp;
511

    
512
    T0 &= 0x1F;
513
    if (T0) {
514
       tmp = (int32_t)((uint32_t)T1 << (0x20 - T0));
515
       T0 = (int32_t)((uint32_t)T1 >> T0) | tmp;
516
    } else
517
       T0 = T1;
518
    RETURN();
519
}
520

    
521
void op_clo (void)
522
{
523
    int n;
524

    
525
    if (T0 == ~((target_ulong)0)) {
526
        T0 = 32;
527
    } else {
528
        for (n = 0; n < 32; n++) {
529
            if (!(T0 & (1 << 31)))
530
                break;
531
            T0 = T0 << 1;
532
        }
533
        T0 = n;
534
    }
535
    RETURN();
536
}
537

    
538
void op_clz (void)
539
{
540
    int n;
541

    
542
    if (T0 == 0) {
543
        T0 = 32;
544
    } else {
545
        for (n = 0; n < 32; n++) {
546
            if (T0 & (1 << 31))
547
                break;
548
            T0 = T0 << 1;
549
        }
550
        T0 = n;
551
    }
552
    RETURN();
553
}
554

    
555
#ifdef TARGET_MIPS64
556

    
557
#if TARGET_LONG_BITS > HOST_LONG_BITS
558
/* Those might call libgcc functions.  */
559
void op_dsll (void)
560
{
561
    CALL_FROM_TB0(do_dsll);
562
    RETURN();
563
}
564

    
565
void op_dsll32 (void)
566
{
567
    CALL_FROM_TB0(do_dsll32);
568
    RETURN();
569
}
570

    
571
void op_dsra (void)
572
{
573
    CALL_FROM_TB0(do_dsra);
574
    RETURN();
575
}
576

    
577
void op_dsra32 (void)
578
{
579
    CALL_FROM_TB0(do_dsra32);
580
    RETURN();
581
}
582

    
583
void op_dsrl (void)
584
{
585
    CALL_FROM_TB0(do_dsrl);
586
    RETURN();
587
}
588

    
589
void op_dsrl32 (void)
590
{
591
    CALL_FROM_TB0(do_dsrl32);
592
    RETURN();
593
}
594

    
595
void op_drotr (void)
596
{
597
    CALL_FROM_TB0(do_drotr);
598
    RETURN();
599
}
600

    
601
void op_drotr32 (void)
602
{
603
    CALL_FROM_TB0(do_drotr32);
604
    RETURN();
605
}
606

    
607
void op_dsllv (void)
608
{
609
    CALL_FROM_TB0(do_dsllv);
610
    RETURN();
611
}
612

    
613
void op_dsrav (void)
614
{
615
    CALL_FROM_TB0(do_dsrav);
616
    RETURN();
617
}
618

    
619
void op_dsrlv (void)
620
{
621
    CALL_FROM_TB0(do_dsrlv);
622
    RETURN();
623
}
624

    
625
void op_drotrv (void)
626
{
627
    CALL_FROM_TB0(do_drotrv);
628
    RETURN();
629
}
630

    
631
#else /* TARGET_LONG_BITS > HOST_LONG_BITS */
632

    
633
void op_dsll (void)
634
{
635
    T0 = T0 << T1;
636
    RETURN();
637
}
638

    
639
void op_dsll32 (void)
640
{
641
    T0 = T0 << (T1 + 32);
642
    RETURN();
643
}
644

    
645
void op_dsra (void)
646
{
647
    T0 = (int64_t)T0 >> T1;
648
    RETURN();
649
}
650

    
651
void op_dsra32 (void)
652
{
653
    T0 = (int64_t)T0 >> (T1 + 32);
654
    RETURN();
655
}
656

    
657
void op_dsrl (void)
658
{
659
    T0 = T0 >> T1;
660
    RETURN();
661
}
662

    
663
void op_dsrl32 (void)
664
{
665
    T0 = T0 >> (T1 + 32);
666
    RETURN();
667
}
668

    
669
void op_drotr (void)
670
{
671
    target_ulong tmp;
672

    
673
    if (T1) {
674
       tmp = T0 << (0x40 - T1);
675
       T0 = (T0 >> T1) | tmp;
676
    }
677
    RETURN();
678
}
679

    
680
void op_drotr32 (void)
681
{
682
    target_ulong tmp;
683

    
684
    if (T1) {
685
       tmp = T0 << (0x40 - (32 + T1));
686
       T0 = (T0 >> (32 + T1)) | tmp;
687
    }
688
    RETURN();
689
}
690

    
691
void op_dsllv (void)
692
{
693
    T0 = T1 << (T0 & 0x3F);
694
    RETURN();
695
}
696

    
697
void op_dsrav (void)
698
{
699
    T0 = (int64_t)T1 >> (T0 & 0x3F);
700
    RETURN();
701
}
702

    
703
void op_dsrlv (void)
704
{
705
    T0 = T1 >> (T0 & 0x3F);
706
    RETURN();
707
}
708

    
709
void op_drotrv (void)
710
{
711
    target_ulong tmp;
712

    
713
    T0 &= 0x3F;
714
    if (T0) {
715
       tmp = T1 << (0x40 - T0);
716
       T0 = (T1 >> T0) | tmp;
717
    } else
718
       T0 = T1;
719
    RETURN();
720
}
721
#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
722

    
723
void op_dclo (void)
724
{
725
    int n;
726

    
727
    if (T0 == ~((target_ulong)0)) {
728
        T0 = 64;
729
    } else {
730
        for (n = 0; n < 64; n++) {
731
            if (!(T0 & (1ULL << 63)))
732
                break;
733
            T0 = T0 << 1;
734
        }
735
        T0 = n;
736
    }
737
    RETURN();
738
}
739

    
740
void op_dclz (void)
741
{
742
    int n;
743

    
744
    if (T0 == 0) {
745
        T0 = 64;
746
    } else {
747
        for (n = 0; n < 64; n++) {
748
            if (T0 & (1ULL << 63))
749
                break;
750
            T0 = T0 << 1;
751
        }
752
        T0 = n;
753
    }
754
    RETURN();
755
}
756
#endif
757

    
758
/* 64 bits arithmetic */
759
#if TARGET_LONG_BITS > HOST_LONG_BITS
760
void op_mult (void)
761
{
762
    CALL_FROM_TB0(do_mult);
763
    RETURN();
764
}
765

    
766
void op_multu (void)
767
{
768
    CALL_FROM_TB0(do_multu);
769
    RETURN();
770
}
771

    
772
void op_madd (void)
773
{
774
    CALL_FROM_TB0(do_madd);
775
    RETURN();
776
}
777

    
778
void op_maddu (void)
779
{
780
    CALL_FROM_TB0(do_maddu);
781
    RETURN();
782
}
783

    
784
void op_msub (void)
785
{
786
    CALL_FROM_TB0(do_msub);
787
    RETURN();
788
}
789

    
790
void op_msubu (void)
791
{
792
    CALL_FROM_TB0(do_msubu);
793
    RETURN();
794
}
795

    
796
#else /* TARGET_LONG_BITS > HOST_LONG_BITS */
797

    
798
static inline uint64_t get_HILO (void)
799
{
800
    return ((uint64_t)env->HI << 32) | ((uint64_t)(uint32_t)env->LO);
801
}
802

    
803
static inline void set_HILO (uint64_t HILO)
804
{
805
    env->LO = (int32_t)(HILO & 0xFFFFFFFF);
806
    env->HI = (int32_t)(HILO >> 32);
807
}
808

    
809
void op_mult (void)
810
{
811
    set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
812
    RETURN();
813
}
814

    
815
void op_multu (void)
816
{
817
    set_HILO((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
818
    RETURN();
819
}
820

    
821
void op_madd (void)
822
{
823
    int64_t tmp;
824

    
825
    tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
826
    set_HILO((int64_t)get_HILO() + tmp);
827
    RETURN();
828
}
829

    
830
void op_maddu (void)
831
{
832
    uint64_t tmp;
833

    
834
    tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
835
    set_HILO(get_HILO() + tmp);
836
    RETURN();
837
}
838

    
839
void op_msub (void)
840
{
841
    int64_t tmp;
842

    
843
    tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
844
    set_HILO((int64_t)get_HILO() - tmp);
845
    RETURN();
846
}
847

    
848
void op_msubu (void)
849
{
850
    uint64_t tmp;
851

    
852
    tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
853
    set_HILO(get_HILO() - tmp);
854
    RETURN();
855
}
856
#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
857

    
858
#ifdef TARGET_MIPS64
859
void op_dmult (void)
860
{
861
    CALL_FROM_TB0(do_dmult);
862
    RETURN();
863
}
864

    
865
void op_dmultu (void)
866
{
867
    CALL_FROM_TB0(do_dmultu);
868
    RETURN();
869
}
870
#endif
871

    
872
/* Conditional moves */
873
void op_movn (void)
874
{
875
    if (T1 != 0)
876
        env->gpr[PARAM1] = T0;
877
    RETURN();
878
}
879

    
880
void op_movz (void)
881
{
882
    if (T1 == 0)
883
        env->gpr[PARAM1] = T0;
884
    RETURN();
885
}
886

    
887
void op_movf (void)
888
{
889
    if (!(env->fcr31 & PARAM1))
890
        T0 = T1;
891
    RETURN();
892
}
893

    
894
void op_movt (void)
895
{
896
    if (env->fcr31 & PARAM1)
897
        T0 = T1;
898
    RETURN();
899
}
900

    
901
/* Tests */
902
#define OP_COND(name, cond) \
903
void glue(op_, name) (void) \
904
{                           \
905
    if (cond) {             \
906
        T0 = 1;             \
907
    } else {                \
908
        T0 = 0;             \
909
    }                       \
910
    RETURN();               \
911
}
912

    
913
OP_COND(eq, T0 == T1);
914
OP_COND(ne, T0 != T1);
915
OP_COND(ge, (int32_t)T0 >= (int32_t)T1);
916
OP_COND(geu, T0 >= T1);
917
OP_COND(lt, (int32_t)T0 < (int32_t)T1);
918
OP_COND(ltu, T0 < T1);
919
OP_COND(gez, (int32_t)T0 >= 0);
920
OP_COND(gtz, (int32_t)T0 > 0);
921
OP_COND(lez, (int32_t)T0 <= 0);
922
OP_COND(ltz, (int32_t)T0 < 0);
923

    
924
/* Branches */
925
//#undef USE_DIRECT_JUMP
926

    
927
void OPPROTO op_goto_tb0(void)
928
{
929
    GOTO_TB(op_goto_tb0, PARAM1, 0);
930
    RETURN();
931
}
932

    
933
void OPPROTO op_goto_tb1(void)
934
{
935
    GOTO_TB(op_goto_tb1, PARAM1, 1);
936
    RETURN();
937
}
938

    
939
/* Branch to register */
940
void op_save_breg_target (void)
941
{
942
    env->btarget = T2;
943
    RETURN();
944
}
945

    
946
void op_restore_breg_target (void)
947
{
948
    T2 = env->btarget;
949
    RETURN();
950
}
951

    
952
void op_breg (void)
953
{
954
    env->PC = T2;
955
    RETURN();
956
}
957

    
958
void op_save_btarget (void)
959
{
960
    env->btarget = PARAM1;
961
    RETURN();
962
}
963

    
964
/* Conditional branch */
965
void op_set_bcond (void)
966
{
967
    T2 = T0;
968
    RETURN();
969
}
970

    
971
void op_save_bcond (void)
972
{
973
    env->bcond = T2;
974
    RETURN();
975
}
976

    
977
void op_restore_bcond (void)
978
{
979
    T2 = env->bcond;
980
    RETURN();
981
}
982

    
983
void op_jnz_T2 (void)
984
{
985
    if (T2)
986
        GOTO_LABEL_PARAM(1);
987
    RETURN();
988
}
989

    
990
/* CP0 functions */
991
void op_mfc0_index (void)
992
{
993
    T0 = env->CP0_Index;
994
    RETURN();
995
}
996

    
997
void op_mfc0_random (void)
998
{
999
    CALL_FROM_TB0(do_mfc0_random);
1000
    RETURN();
1001
}
1002

    
1003
void op_mfc0_entrylo0 (void)
1004
{
1005
    T0 = (int32_t)env->CP0_EntryLo0;
1006
    RETURN();
1007
}
1008

    
1009
void op_mfc0_entrylo1 (void)
1010
{
1011
    T0 = (int32_t)env->CP0_EntryLo1;
1012
    RETURN();
1013
}
1014

    
1015
void op_mfc0_context (void)
1016
{
1017
    T0 = (int32_t)env->CP0_Context;
1018
    RETURN();
1019
}
1020

    
1021
void op_mfc0_pagemask (void)
1022
{
1023
    T0 = env->CP0_PageMask;
1024
    RETURN();
1025
}
1026

    
1027
void op_mfc0_pagegrain (void)
1028
{
1029
    T0 = env->CP0_PageGrain;
1030
    RETURN();
1031
}
1032

    
1033
void op_mfc0_wired (void)
1034
{
1035
    T0 = env->CP0_Wired;
1036
    RETURN();
1037
}
1038

    
1039
void op_mfc0_hwrena (void)
1040
{
1041
    T0 = env->CP0_HWREna;
1042
    RETURN();
1043
}
1044

    
1045
void op_mfc0_badvaddr (void)
1046
{
1047
    T0 = (int32_t)env->CP0_BadVAddr;
1048
    RETURN();
1049
}
1050

    
1051
void op_mfc0_count (void)
1052
{
1053
    CALL_FROM_TB0(do_mfc0_count);
1054
    RETURN();
1055
}
1056

    
1057
void op_mfc0_entryhi (void)
1058
{
1059
    T0 = (int32_t)env->CP0_EntryHi;
1060
    RETURN();
1061
}
1062

    
1063
void op_mfc0_compare (void)
1064
{
1065
    T0 = env->CP0_Compare;
1066
    RETURN();
1067
}
1068

    
1069
void op_mfc0_status (void)
1070
{
1071
    T0 = env->CP0_Status;
1072
    RETURN();
1073
}
1074

    
1075
void op_mfc0_intctl (void)
1076
{
1077
    T0 = env->CP0_IntCtl;
1078
    RETURN();
1079
}
1080

    
1081
void op_mfc0_srsctl (void)
1082
{
1083
    T0 = env->CP0_SRSCtl;
1084
    RETURN();
1085
}
1086

    
1087
void op_mfc0_srsmap (void)
1088
{
1089
    T0 = env->CP0_SRSMap;
1090
    RETURN();
1091
}
1092

    
1093
void op_mfc0_cause (void)
1094
{
1095
    T0 = env->CP0_Cause;
1096
    RETURN();
1097
}
1098

    
1099
void op_mfc0_epc (void)
1100
{
1101
    T0 = (int32_t)env->CP0_EPC;
1102
    RETURN();
1103
}
1104

    
1105
void op_mfc0_prid (void)
1106
{
1107
    T0 = env->CP0_PRid;
1108
    RETURN();
1109
}
1110

    
1111
void op_mfc0_ebase (void)
1112
{
1113
    T0 = env->CP0_EBase;
1114
    RETURN();
1115
}
1116

    
1117
void op_mfc0_config0 (void)
1118
{
1119
    T0 = env->CP0_Config0;
1120
    RETURN();
1121
}
1122

    
1123
void op_mfc0_config1 (void)
1124
{
1125
    T0 = env->CP0_Config1;
1126
    RETURN();
1127
}
1128

    
1129
void op_mfc0_config2 (void)
1130
{
1131
    T0 = env->CP0_Config2;
1132
    RETURN();
1133
}
1134

    
1135
void op_mfc0_config3 (void)
1136
{
1137
    T0 = env->CP0_Config3;
1138
    RETURN();
1139
}
1140

    
1141
void op_mfc0_config6 (void)
1142
{
1143
    T0 = env->CP0_Config6;
1144
    RETURN();
1145
}
1146

    
1147
void op_mfc0_config7 (void)
1148
{
1149
    T0 = env->CP0_Config7;
1150
    RETURN();
1151
}
1152

    
1153
void op_mfc0_lladdr (void)
1154
{
1155
    T0 = (int32_t)env->CP0_LLAddr >> 4;
1156
    RETURN();
1157
}
1158

    
1159
void op_mfc0_watchlo0 (void)
1160
{
1161
    T0 = (int32_t)env->CP0_WatchLo;
1162
    RETURN();
1163
}
1164

    
1165
void op_mfc0_watchhi0 (void)
1166
{
1167
    T0 = env->CP0_WatchHi;
1168
    RETURN();
1169
}
1170

    
1171
void op_mfc0_xcontext (void)
1172
{
1173
    T0 = (int32_t)env->CP0_XContext;
1174
    RETURN();
1175
}
1176

    
1177
void op_mfc0_framemask (void)
1178
{
1179
    T0 = env->CP0_Framemask;
1180
    RETURN();
1181
}
1182

    
1183
void op_mfc0_debug (void)
1184
{
1185
    T0 = env->CP0_Debug;
1186
    if (env->hflags & MIPS_HFLAG_DM)
1187
        T0 |= 1 << CP0DB_DM;
1188
    RETURN();
1189
}
1190

    
1191
void op_mfc0_depc (void)
1192
{
1193
    T0 = (int32_t)env->CP0_DEPC;
1194
    RETURN();
1195
}
1196

    
1197
void op_mfc0_performance0 (void)
1198
{
1199
    T0 = env->CP0_Performance0;
1200
    RETURN();
1201
}
1202

    
1203
void op_mfc0_taglo (void)
1204
{
1205
    T0 = env->CP0_TagLo;
1206
    RETURN();
1207
}
1208

    
1209
void op_mfc0_datalo (void)
1210
{
1211
    T0 = env->CP0_DataLo;
1212
    RETURN();
1213
}
1214

    
1215
void op_mfc0_taghi (void)
1216
{
1217
    T0 = env->CP0_TagHi;
1218
    RETURN();
1219
}
1220

    
1221
void op_mfc0_datahi (void)
1222
{
1223
    T0 = env->CP0_DataHi;
1224
    RETURN();
1225
}
1226

    
1227
void op_mfc0_errorepc (void)
1228
{
1229
    T0 = (int32_t)env->CP0_ErrorEPC;
1230
    RETURN();
1231
}
1232

    
1233
void op_mfc0_desave (void)
1234
{
1235
    T0 = env->CP0_DESAVE;
1236
    RETURN();
1237
}
1238

    
1239
void op_mtc0_index (void)
1240
{
1241
    env->CP0_Index = (env->CP0_Index & 0x80000000) | (T0 % env->nb_tlb);
1242
    RETURN();
1243
}
1244

    
1245
void op_mtc0_entrylo0 (void)
1246
{
1247
    /* Large physaddr not implemented */
1248
    /* 1k pages not implemented */
1249
    env->CP0_EntryLo0 = (int32_t)T0 & 0x3FFFFFFF;
1250
    RETURN();
1251
}
1252

    
1253
void op_mtc0_entrylo1 (void)
1254
{
1255
    /* Large physaddr not implemented */
1256
    /* 1k pages not implemented */
1257
    env->CP0_EntryLo1 = (int32_t)T0 & 0x3FFFFFFF;
1258
    RETURN();
1259
}
1260

    
1261
void op_mtc0_context (void)
1262
{
1263
    env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (T0 & ~0x007FFFFF);
1264
    RETURN();
1265
}
1266

    
1267
void op_mtc0_pagemask (void)
1268
{
1269
    /* 1k pages not implemented */
1270
    env->CP0_PageMask = T0 & 0x1FFFE000;
1271
    RETURN();
1272
}
1273

    
1274
void op_mtc0_pagegrain (void)
1275
{
1276
    /* SmartMIPS not implemented */
1277
    /* Large physaddr not implemented */
1278
    /* 1k pages not implemented */
1279
    env->CP0_PageGrain = 0;
1280
    RETURN();
1281
}
1282

    
1283
void op_mtc0_wired (void)
1284
{
1285
    env->CP0_Wired = T0 % env->nb_tlb;
1286
    RETURN();
1287
}
1288

    
1289
void op_mtc0_hwrena (void)
1290
{
1291
    env->CP0_HWREna = T0 & 0x0000000F;
1292
    RETURN();
1293
}
1294

    
1295
void op_mtc0_count (void)
1296
{
1297
    CALL_FROM_TB2(cpu_mips_store_count, env, T0);
1298
    RETURN();
1299
}
1300

    
1301
void op_mtc0_entryhi (void)
1302
{
1303
    target_ulong old, val;
1304

    
1305
    /* 1k pages not implemented */
1306
    /* Ignore MIPS64 TLB for now */
1307
    val = (target_ulong)(int32_t)T0 & ~(target_ulong)0x1F00;
1308
    old = env->CP0_EntryHi;
1309
    env->CP0_EntryHi = val;
1310
    /* If the ASID changes, flush qemu's TLB.  */
1311
    if ((old & 0xFF) != (val & 0xFF))
1312
        CALL_FROM_TB2(cpu_mips_tlb_flush, env, 1);
1313
    RETURN();
1314
}
1315

    
1316
void op_mtc0_compare (void)
1317
{
1318
    CALL_FROM_TB2(cpu_mips_store_compare, env, T0);
1319
    RETURN();
1320
}
1321

    
1322
void op_mtc0_status (void)
1323
{
1324
    uint32_t val, old;
1325
    uint32_t mask = env->Status_rw_bitmask;
1326

    
1327
    /* No reverse endianness, no MDMX/DSP, no 64bit ops,
1328
       no 64bit addressing implemented. */
1329
    val = (int32_t)T0 & mask;
1330
    old = env->CP0_Status;
1331
    if (!(val & (1 << CP0St_EXL)) &&
1332
        !(val & (1 << CP0St_ERL)) &&
1333
        !(env->hflags & MIPS_HFLAG_DM) &&
1334
        (val & (1 << CP0St_UM)))
1335
        env->hflags |= MIPS_HFLAG_UM;
1336
    env->CP0_Status = (env->CP0_Status & ~mask) | val;
1337
    if (loglevel & CPU_LOG_EXEC)
1338
        CALL_FROM_TB2(do_mtc0_status_debug, old, val);
1339
    CALL_FROM_TB1(cpu_mips_update_irq, env);
1340
    RETURN();
1341
}
1342

    
1343
void op_mtc0_intctl (void)
1344
{
1345
    /* vectored interrupts not implemented, timer on int 7,
1346
       no performance counters. */
1347
    env->CP0_IntCtl |= T0 & 0x000002e0;
1348
    RETURN();
1349
}
1350

    
1351
void op_mtc0_srsctl (void)
1352
{
1353
    /* shadow registers not implemented */
1354
    env->CP0_SRSCtl = 0;
1355
    RETURN();
1356
}
1357

    
1358
void op_mtc0_srsmap (void)
1359
{
1360
    /* shadow registers not implemented */
1361
    env->CP0_SRSMap = 0;
1362
    RETURN();
1363
}
1364

    
1365
void op_mtc0_cause (void)
1366
{
1367
    uint32_t mask = 0x00C00300;
1368

    
1369
    if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) == (1 << CP0C0_AR))
1370
        mask |= 1 << CP0Ca_DC;
1371

    
1372
    env->CP0_Cause = (env->CP0_Cause & ~mask) | (T0 & mask);
1373

    
1374
    /* Handle the software interrupt as an hardware one, as they
1375
       are very similar */
1376
    if (T0 & CP0Ca_IP_mask) {
1377
        CALL_FROM_TB1(cpu_mips_update_irq, env);
1378
    }
1379
    RETURN();
1380
}
1381

    
1382
void op_mtc0_epc (void)
1383
{
1384
    env->CP0_EPC = (int32_t)T0;
1385
    RETURN();
1386
}
1387

    
1388
void op_mtc0_ebase (void)
1389
{
1390
    /* vectored interrupts not implemented */
1391
    /* Multi-CPU not implemented */
1392
    env->CP0_EBase = 0x80000000 | (T0 & 0x3FFFF000);
1393
    RETURN();
1394
}
1395

    
1396
void op_mtc0_config0 (void)
1397
{
1398
#if defined(MIPS_USES_R4K_TLB)
1399
     /* Fixed mapping MMU not implemented */
1400
    env->CP0_Config0 = (env->CP0_Config0 & 0x8017FF88) | (T0 & 0x00000001);
1401
#else
1402
    env->CP0_Config0 = (env->CP0_Config0 & 0xFE17FF88) | (T0 & 0x00000001);
1403
#endif
1404
    RETURN();
1405
}
1406

    
1407
void op_mtc0_config2 (void)
1408
{
1409
    /* tertiary/secondary caches not implemented */
1410
    env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF);
1411
    RETURN();
1412
}
1413

    
1414
void op_mtc0_watchlo0 (void)
1415
{
1416
    /* Watch exceptions for instructions, data loads, data stores
1417
       not implemented. */
1418
    env->CP0_WatchLo = (int32_t)(T0 & ~0x7);
1419
    RETURN();
1420
}
1421

    
1422
void op_mtc0_watchhi0 (void)
1423
{
1424
    env->CP0_WatchHi = (T0 & 0x40FF0FF8);
1425
    env->CP0_WatchHi &= ~(env->CP0_WatchHi & T0 & 0x7);
1426
    RETURN();
1427
}
1428

    
1429
void op_mtc0_framemask (void)
1430
{
1431
    env->CP0_Framemask = T0; /* XXX */
1432
    RETURN();
1433
}
1434

    
1435
void op_mtc0_debug (void)
1436
{
1437
    env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120);
1438
    if (T0 & (1 << CP0DB_DM))
1439
        env->hflags |= MIPS_HFLAG_DM;
1440
    else
1441
        env->hflags &= ~MIPS_HFLAG_DM;
1442
    RETURN();
1443
}
1444

    
1445
void op_mtc0_depc (void)
1446
{
1447
    env->CP0_DEPC = (int32_t)T0;
1448
    RETURN();
1449
}
1450

    
1451
void op_mtc0_performance0 (void)
1452
{
1453
    env->CP0_Performance0 = T0; /* XXX */
1454
    RETURN();
1455
}
1456

    
1457
void op_mtc0_taglo (void)
1458
{
1459
    env->CP0_TagLo = T0 & 0xFFFFFCF6;
1460
    RETURN();
1461
}
1462

    
1463
void op_mtc0_datalo (void)
1464
{
1465
    env->CP0_DataLo = T0; /* XXX */
1466
    RETURN();
1467
}
1468

    
1469
void op_mtc0_taghi (void)
1470
{
1471
    env->CP0_TagHi = T0; /* XXX */
1472
    RETURN();
1473
}
1474

    
1475
void op_mtc0_datahi (void)
1476
{
1477
    env->CP0_DataHi = T0; /* XXX */
1478
    RETURN();
1479
}
1480

    
1481
void op_mtc0_errorepc (void)
1482
{
1483
    env->CP0_ErrorEPC = (int32_t)T0;
1484
    RETURN();
1485
}
1486

    
1487
void op_mtc0_desave (void)
1488
{
1489
    env->CP0_DESAVE = T0;
1490
    RETURN();
1491
}
1492

    
1493
#ifdef TARGET_MIPS64
1494
void op_dmfc0_entrylo0 (void)
1495
{
1496
    T0 = env->CP0_EntryLo0;
1497
    RETURN();
1498
}
1499

    
1500
void op_dmfc0_entrylo1 (void)
1501
{
1502
    T0 = env->CP0_EntryLo1;
1503
    RETURN();
1504
}
1505

    
1506
void op_dmfc0_context (void)
1507
{
1508
    T0 = env->CP0_Context;
1509
    RETURN();
1510
}
1511

    
1512
void op_dmfc0_badvaddr (void)
1513
{
1514
    T0 = env->CP0_BadVAddr;
1515
    RETURN();
1516
}
1517

    
1518
void op_dmfc0_entryhi (void)
1519
{
1520
    T0 = env->CP0_EntryHi;
1521
    RETURN();
1522
}
1523

    
1524
void op_dmfc0_epc (void)
1525
{
1526
    T0 = env->CP0_EPC;
1527
    RETURN();
1528
}
1529

    
1530
void op_dmfc0_lladdr (void)
1531
{
1532
    T0 = env->CP0_LLAddr >> 4;
1533
    RETURN();
1534
}
1535

    
1536
void op_dmfc0_watchlo0 (void)
1537
{
1538
    T0 = env->CP0_WatchLo;
1539
    RETURN();
1540
}
1541

    
1542
void op_dmfc0_xcontext (void)
1543
{
1544
    T0 = env->CP0_XContext;
1545
    RETURN();
1546
}
1547

    
1548
void op_dmfc0_depc (void)
1549
{
1550
    T0 = env->CP0_DEPC;
1551
    RETURN();
1552
}
1553

    
1554
void op_dmfc0_errorepc (void)
1555
{
1556
    T0 = env->CP0_ErrorEPC;
1557
    RETURN();
1558
}
1559

    
1560
void op_dmtc0_entrylo0 (void)
1561
{
1562
    /* Large physaddr not implemented */
1563
    /* 1k pages not implemented */
1564
    env->CP0_EntryLo0 = T0 & 0x3FFFFFFF;
1565
    RETURN();
1566
}
1567

    
1568
void op_dmtc0_entrylo1 (void)
1569
{
1570
    /* Large physaddr not implemented */
1571
    /* 1k pages not implemented */
1572
    env->CP0_EntryLo1 = T0 & 0x3FFFFFFF;
1573
    RETURN();
1574
}
1575

    
1576
void op_dmtc0_context (void)
1577
{
1578
    env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (T0 & ~0x007FFFFF);
1579
    RETURN();
1580
}
1581

    
1582
void op_dmtc0_epc (void)
1583
{
1584
    env->CP0_EPC = T0;
1585
    RETURN();
1586
}
1587

    
1588
void op_dmtc0_watchlo0 (void)
1589
{
1590
    /* Watch exceptions for instructions, data loads, data stores
1591
       not implemented. */
1592
    env->CP0_WatchLo = T0 & ~0x7;
1593
    RETURN();
1594
}
1595

    
1596
void op_dmtc0_xcontext (void)
1597
{
1598
    env->CP0_XContext = (env->CP0_XContext & 0xffffffff) | (T0 & ~0xffffffff);
1599
    RETURN();
1600
}
1601

    
1602
void op_dmtc0_depc (void)
1603
{
1604
    env->CP0_DEPC = T0;
1605
    RETURN();
1606
}
1607

    
1608
void op_dmtc0_errorepc (void)
1609
{
1610
    env->CP0_ErrorEPC = T0;
1611
    RETURN();
1612
}
1613
#endif /* TARGET_MIPS64 */
1614

    
1615
/* CP1 functions */
1616
#if 0
1617
# define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env)
1618
#else
1619
# define DEBUG_FPU_STATE() do { } while(0)
1620
#endif
1621

    
1622
void op_cp0_enabled(void)
1623
{
1624
    if (!(env->CP0_Status & (1 << CP0St_CU0)) &&
1625
        (env->hflags & MIPS_HFLAG_UM)) {
1626
        CALL_FROM_TB2(do_raise_exception_err, EXCP_CpU, 0);
1627
    }
1628
    RETURN();
1629
}
1630

    
1631
void op_cp1_enabled(void)
1632
{
1633
    if (!(env->CP0_Status & (1 << CP0St_CU1))) {
1634
        CALL_FROM_TB2(do_raise_exception_err, EXCP_CpU, 1);
1635
    }
1636
    RETURN();
1637
}
1638

    
1639
/* convert MIPS rounding mode in FCR31 to IEEE library */
1640
unsigned int ieee_rm[] = { 
1641
    float_round_nearest_even,
1642
    float_round_to_zero,
1643
    float_round_up,
1644
    float_round_down
1645
};
1646

    
1647
#define RESTORE_ROUNDING_MODE \
1648
    set_float_rounding_mode(ieee_rm[env->fcr31 & 3], &env->fp_status)
1649

    
1650
inline char ieee_ex_to_mips(char xcpt)
1651
{
1652
    return (xcpt & float_flag_inexact) >> 5 |
1653
           (xcpt & float_flag_underflow) >> 3 |
1654
           (xcpt & float_flag_overflow) >> 1 |
1655
           (xcpt & float_flag_divbyzero) << 1 |
1656
           (xcpt & float_flag_invalid) << 4;
1657
}
1658

    
1659
inline char mips_ex_to_ieee(char xcpt)
1660
{
1661
    return (xcpt & FP_INEXACT) << 5 |
1662
           (xcpt & FP_UNDERFLOW) << 3 |
1663
           (xcpt & FP_OVERFLOW) << 1 |
1664
           (xcpt & FP_DIV0) >> 1 |
1665
           (xcpt & FP_INVALID) >> 4;
1666
}
1667

    
1668
inline void update_fcr31(void)
1669
{
1670
    int tmp = ieee_ex_to_mips(get_float_exception_flags(&env->fp_status));
1671

    
1672
    SET_FP_CAUSE(env->fcr31, tmp);
1673
    if (GET_FP_ENABLE(env->fcr31) & tmp)
1674
        CALL_FROM_TB1(do_raise_exception, EXCP_FPE);
1675
    else
1676
        UPDATE_FP_FLAGS(env->fcr31, tmp);
1677
}
1678

    
1679

    
1680
void op_cfc1 (void)
1681
{
1682
    switch (T1) {
1683
    case 0:
1684
        T0 = (int32_t)env->fcr0;
1685
        break;
1686
    case 25:
1687
        T0 = ((env->fcr31 >> 24) & 0xfe) | ((env->fcr31 >> 23) & 0x1);
1688
        break;
1689
    case 26:
1690
        T0 = env->fcr31 & 0x0003f07c;
1691
        break;
1692
    case 28:
1693
        T0 = (env->fcr31 & 0x00000f83) | ((env->fcr31 >> 22) & 0x4);
1694
        break;
1695
    default:
1696
        T0 = (int32_t)env->fcr31;
1697
        break;
1698
    }
1699
    DEBUG_FPU_STATE();
1700
    RETURN();
1701
}
1702

    
1703
void op_ctc1 (void)
1704
{
1705
    switch(T1) {
1706
    case 25:
1707
        if (T0 & 0xffffff00)
1708
            goto leave;
1709
        env->fcr31 = (env->fcr31 & 0x017fffff) | ((T0 & 0xfe) << 24) |
1710
                     ((T0 & 0x1) << 23);
1711
        break;
1712
    case 26:
1713
        if (T0 & 0x007c0000)
1714
            goto leave;
1715
        env->fcr31 = (env->fcr31 & 0xfffc0f83) | (T0 & 0x0003f07c);
1716
        break;
1717
    case 28:
1718
        if (T0 & 0x007c0000)
1719
            goto leave;
1720
        env->fcr31 = (env->fcr31 & 0xfefff07c) | (T0 & 0x00000f83) |
1721
                     ((T0 & 0x4) << 22);
1722
        break;
1723
    case 31:
1724
        if (T0 & 0x007c0000)
1725
            goto leave;
1726
        env->fcr31 = T0;
1727
        break;
1728
    default:
1729
        goto leave;
1730
    }
1731
    /* set rounding mode */
1732
    RESTORE_ROUNDING_MODE;
1733
    set_float_exception_flags(0, &env->fp_status);
1734
    if ((GET_FP_ENABLE(env->fcr31) | 0x20) & GET_FP_CAUSE(env->fcr31))
1735
        CALL_FROM_TB1(do_raise_exception, EXCP_FPE);
1736
 leave:
1737
    DEBUG_FPU_STATE();
1738
    RETURN();
1739
}
1740

    
1741
void op_mfc1 (void)
1742
{
1743
    T0 = WT0;
1744
    DEBUG_FPU_STATE();
1745
    RETURN();
1746
}
1747

    
1748
void op_mtc1 (void)
1749
{
1750
    WT0 = T0;
1751
    DEBUG_FPU_STATE();
1752
    RETURN();
1753
}
1754

    
1755
void op_dmfc1 (void)
1756
{
1757
    T0 = DT0;
1758
    DEBUG_FPU_STATE();
1759
    RETURN();
1760
}
1761

    
1762
void op_dmtc1 (void)
1763
{
1764
    DT0 = T0;
1765
    DEBUG_FPU_STATE();
1766
    RETURN();
1767
}
1768

    
1769
void op_mfhc1 (void)
1770
{
1771
    T0 = WTH0;
1772
    DEBUG_FPU_STATE();
1773
    RETURN();
1774
}
1775

    
1776
void op_mthc1 (void)
1777
{
1778
    WTH0 = T0;
1779
    DEBUG_FPU_STATE();
1780
    RETURN();
1781
}
1782

    
1783
/* Float support.
1784
   Single precition routines have a "s" suffix, double precision a
1785
   "d" suffix, 32bit integer "w", 64bit integer "l", paired singe "ps",
1786
   paired single lowwer "pl", paired single upper "pu".  */
1787

    
1788
#define FLOAT_OP(name, p) void OPPROTO op_float_##name##_##p(void)
1789

    
1790
FLOAT_OP(cvtd, s)
1791
{
1792
    set_float_exception_flags(0, &env->fp_status);
1793
    FDT2 = float32_to_float64(FST0, &env->fp_status);
1794
    update_fcr31();
1795
    DEBUG_FPU_STATE();
1796
    RETURN();
1797
}
1798
FLOAT_OP(cvtd, w)
1799
{
1800
    set_float_exception_flags(0, &env->fp_status);
1801
    FDT2 = int32_to_float64(WT0, &env->fp_status);
1802
    update_fcr31();
1803
    DEBUG_FPU_STATE();
1804
    RETURN();
1805
}
1806
FLOAT_OP(cvtd, l)
1807
{
1808
    set_float_exception_flags(0, &env->fp_status);
1809
    FDT2 = int64_to_float64(DT0, &env->fp_status);
1810
    update_fcr31();
1811
    DEBUG_FPU_STATE();
1812
    RETURN();
1813
}
1814
FLOAT_OP(cvtl, d)
1815
{
1816
    set_float_exception_flags(0, &env->fp_status);
1817
    DT2 = float64_to_int64(FDT0, &env->fp_status);
1818
    update_fcr31();
1819
    if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
1820
        DT2 = 0x7fffffffffffffffULL;
1821
    DEBUG_FPU_STATE();
1822
    RETURN();
1823
}
1824
FLOAT_OP(cvtl, s)
1825
{
1826
    set_float_exception_flags(0, &env->fp_status);
1827
    DT2 = float32_to_int64(FST0, &env->fp_status);
1828
    update_fcr31();
1829
    if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
1830
        DT2 = 0x7fffffffffffffffULL;
1831
    DEBUG_FPU_STATE();
1832
    RETURN();
1833
}
1834
FLOAT_OP(cvtps, s)
1835
{
1836
    WT2 = WT0;
1837
    WTH2 = WT1;
1838
    DEBUG_FPU_STATE();
1839
    RETURN();
1840
}
1841
FLOAT_OP(cvtps, pw)
1842
{
1843
    set_float_exception_flags(0, &env->fp_status);
1844
    FST2 = int32_to_float32(WT0, &env->fp_status);
1845
    FSTH2 = int32_to_float32(WTH0, &env->fp_status);
1846
    update_fcr31();
1847
    DEBUG_FPU_STATE();
1848
    RETURN();
1849
}
1850
FLOAT_OP(cvtpw, ps)
1851
{
1852
    set_float_exception_flags(0, &env->fp_status);
1853
    WT2 = float32_to_int32(FST0, &env->fp_status);
1854
    WTH2 = float32_to_int32(FSTH0, &env->fp_status);
1855
    update_fcr31();
1856
    if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
1857
        WT2 = 0x7fffffff;
1858
    DEBUG_FPU_STATE();
1859
    RETURN();
1860
}
1861
FLOAT_OP(cvts, d)
1862
{
1863
    set_float_exception_flags(0, &env->fp_status);
1864
    FST2 = float64_to_float32(FDT0, &env->fp_status);
1865
    update_fcr31();
1866
    DEBUG_FPU_STATE();
1867
    RETURN();
1868
}
1869
FLOAT_OP(cvts, w)
1870
{
1871
    set_float_exception_flags(0, &env->fp_status);
1872
    FST2 = int32_to_float32(WT0, &env->fp_status);
1873
    update_fcr31();
1874
    DEBUG_FPU_STATE();
1875
    RETURN();
1876
}
1877
FLOAT_OP(cvts, l)
1878
{
1879
    set_float_exception_flags(0, &env->fp_status);
1880
    FST2 = int64_to_float32(DT0, &env->fp_status);
1881
    update_fcr31();
1882
    DEBUG_FPU_STATE();
1883
    RETURN();
1884
}
1885
FLOAT_OP(cvts, pl)
1886
{
1887
    set_float_exception_flags(0, &env->fp_status);
1888
    WT2 = WT0;
1889
    update_fcr31();
1890
    DEBUG_FPU_STATE();
1891
    RETURN();
1892
}
1893
FLOAT_OP(cvts, pu)
1894
{
1895
    set_float_exception_flags(0, &env->fp_status);
1896
    WT2 = WTH0;
1897
    update_fcr31();
1898
    DEBUG_FPU_STATE();
1899
    RETURN();
1900
}
1901
FLOAT_OP(cvtw, s)
1902
{
1903
    set_float_exception_flags(0, &env->fp_status);
1904
    WT2 = float32_to_int32(FST0, &env->fp_status);
1905
    update_fcr31();
1906
    if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
1907
        WT2 = 0x7fffffff;
1908
    DEBUG_FPU_STATE();
1909
    RETURN();
1910
}
1911
FLOAT_OP(cvtw, d)
1912
{
1913
    set_float_exception_flags(0, &env->fp_status);
1914
    WT2 = float64_to_int32(FDT0, &env->fp_status);
1915
    update_fcr31();
1916
    if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
1917
        WT2 = 0x7fffffff;
1918
    DEBUG_FPU_STATE();
1919
    RETURN();
1920
}
1921

    
1922
FLOAT_OP(pll, ps)
1923
{
1924
    DT2 = ((uint64_t)WT0 << 32) | WT1;
1925
    DEBUG_FPU_STATE();
1926
    RETURN();
1927
}
1928
FLOAT_OP(plu, ps)
1929
{
1930
    DT2 = ((uint64_t)WT0 << 32) | WTH1;
1931
    DEBUG_FPU_STATE();
1932
    RETURN();
1933
}
1934
FLOAT_OP(pul, ps)
1935
{
1936
    DT2 = ((uint64_t)WTH0 << 32) | WT1;
1937
    DEBUG_FPU_STATE();
1938
    RETURN();
1939
}
1940
FLOAT_OP(puu, ps)
1941
{
1942
    DT2 = ((uint64_t)WTH0 << 32) | WTH1;
1943
    DEBUG_FPU_STATE();
1944
    RETURN();
1945
}
1946

    
1947
FLOAT_OP(roundl, d)
1948
{
1949
    set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
1950
    DT2 = float64_round_to_int(FDT0, &env->fp_status);
1951
    RESTORE_ROUNDING_MODE;
1952
    DEBUG_FPU_STATE();
1953
    RETURN();
1954
}
1955
FLOAT_OP(roundl, s)
1956
{
1957
    set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
1958
    DT2 = float32_round_to_int(FST0, &env->fp_status);
1959
    RESTORE_ROUNDING_MODE;
1960
    DEBUG_FPU_STATE();
1961
    RETURN();
1962
}
1963
FLOAT_OP(roundw, d)
1964
{
1965
    set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
1966
    WT2 = float64_round_to_int(FDT0, &env->fp_status);
1967
    RESTORE_ROUNDING_MODE;
1968
    DEBUG_FPU_STATE();
1969
    RETURN();
1970
}
1971
FLOAT_OP(roundw, s)
1972
{
1973
    set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
1974
    WT2 = float32_round_to_int(FST0, &env->fp_status);
1975
    RESTORE_ROUNDING_MODE;
1976
    DEBUG_FPU_STATE();
1977
    RETURN();
1978
}
1979

    
1980
FLOAT_OP(truncl, d)
1981
{
1982
    DT2 = float64_to_int64_round_to_zero(FDT0, &env->fp_status);
1983
    DEBUG_FPU_STATE();
1984
    RETURN();
1985
}
1986
FLOAT_OP(truncl, s)
1987
{
1988
    DT2 = float32_to_int64_round_to_zero(FST0, &env->fp_status);
1989
    DEBUG_FPU_STATE();
1990
    RETURN();
1991
}
1992
FLOAT_OP(truncw, d)
1993
{
1994
    WT2 = float64_to_int32_round_to_zero(FDT0, &env->fp_status);
1995
    DEBUG_FPU_STATE();
1996
    RETURN();
1997
}
1998
FLOAT_OP(truncw, s)
1999
{
2000
    WT2 = float32_to_int32_round_to_zero(FST0, &env->fp_status);
2001
    DEBUG_FPU_STATE();
2002
    RETURN();
2003
}
2004

    
2005
FLOAT_OP(ceill, d)
2006
{
2007
    set_float_rounding_mode(float_round_up, &env->fp_status);
2008
    DT2 = float64_round_to_int(FDT0, &env->fp_status);
2009
    RESTORE_ROUNDING_MODE;
2010
    DEBUG_FPU_STATE();
2011
    RETURN();
2012
}
2013
FLOAT_OP(ceill, s)
2014
{
2015
    set_float_rounding_mode(float_round_up, &env->fp_status);
2016
    DT2 = float32_round_to_int(FST0, &env->fp_status);
2017
    RESTORE_ROUNDING_MODE;
2018
    DEBUG_FPU_STATE();
2019
    RETURN();
2020
}
2021
FLOAT_OP(ceilw, d)
2022
{
2023
    set_float_rounding_mode(float_round_up, &env->fp_status);
2024
    WT2 = float64_round_to_int(FDT0, &env->fp_status);
2025
    RESTORE_ROUNDING_MODE;
2026
    DEBUG_FPU_STATE();
2027
    RETURN();
2028
}
2029
FLOAT_OP(ceilw, s)
2030
{
2031
    set_float_rounding_mode(float_round_up, &env->fp_status);
2032
    WT2 = float32_round_to_int(FST0, &env->fp_status);
2033
    RESTORE_ROUNDING_MODE;
2034
    DEBUG_FPU_STATE();
2035
    RETURN();
2036
}
2037

    
2038
FLOAT_OP(floorl, d)
2039
{
2040
    set_float_rounding_mode(float_round_down, &env->fp_status);
2041
    DT2 = float64_round_to_int(FDT0, &env->fp_status);
2042
    RESTORE_ROUNDING_MODE;
2043
    DEBUG_FPU_STATE();
2044
    RETURN();
2045
}
2046
FLOAT_OP(floorl, s)
2047
{
2048
    set_float_rounding_mode(float_round_down, &env->fp_status);
2049
    DT2 = float32_round_to_int(FST0, &env->fp_status);
2050
    RESTORE_ROUNDING_MODE;
2051
    DEBUG_FPU_STATE();
2052
    RETURN();
2053
}
2054
FLOAT_OP(floorw, d)
2055
{
2056
    set_float_rounding_mode(float_round_down, &env->fp_status);
2057
    WT2 = float64_round_to_int(FDT0, &env->fp_status);
2058
    RESTORE_ROUNDING_MODE;
2059
    DEBUG_FPU_STATE();
2060
    RETURN();
2061
}
2062
FLOAT_OP(floorw, s)
2063
{
2064
    set_float_rounding_mode(float_round_down, &env->fp_status);
2065
    WT2 = float32_round_to_int(FST0, &env->fp_status);
2066
    RESTORE_ROUNDING_MODE;
2067
    DEBUG_FPU_STATE();
2068
    RETURN();
2069
}
2070

    
2071
FLOAT_OP(movf, d)
2072
{
2073
    if (!(env->fcr31 & PARAM1))
2074
        DT2 = DT0;
2075
    DEBUG_FPU_STATE();
2076
    RETURN();
2077
}
2078
FLOAT_OP(movf, s)
2079
{
2080
    if (!(env->fcr31 & PARAM1))
2081
        WT2 = WT0;
2082
    DEBUG_FPU_STATE();
2083
    RETURN();
2084
}
2085
FLOAT_OP(movf, ps)
2086
{
2087
    if (!(env->fcr31 & PARAM1)) {
2088
        WT2 = WT0;
2089
        WTH2 = WTH0;
2090
    }
2091
    DEBUG_FPU_STATE();
2092
    RETURN();
2093
}
2094
FLOAT_OP(movt, d)
2095
{
2096
    if (env->fcr31 & PARAM1)
2097
        DT2 = DT0;
2098
    DEBUG_FPU_STATE();
2099
    RETURN();
2100
}
2101
FLOAT_OP(movt, s)
2102
{
2103
    if (env->fcr31 & PARAM1)
2104
        WT2 = WT0;
2105
    DEBUG_FPU_STATE();
2106
    RETURN();
2107
}
2108
FLOAT_OP(movt, ps)
2109
{
2110
    if (env->fcr31 & PARAM1) {
2111
        WT2 = WT0;
2112
        WTH2 = WTH0;
2113
    }
2114
    DEBUG_FPU_STATE();
2115
    RETURN();
2116
}
2117
FLOAT_OP(movz, d)
2118
{
2119
    if (!T0)
2120
        DT2 = DT0;
2121
    DEBUG_FPU_STATE();
2122
    RETURN();
2123
}
2124
FLOAT_OP(movz, s)
2125
{
2126
    if (!T0)
2127
        WT2 = WT0;
2128
    DEBUG_FPU_STATE();
2129
    RETURN();
2130
}
2131
FLOAT_OP(movz, ps)
2132
{
2133
    if (!T0) {
2134
        WT2 = WT0;
2135
        WTH2 = WTH0;
2136
    }
2137
    DEBUG_FPU_STATE();
2138
    RETURN();
2139
}
2140
FLOAT_OP(movn, d)
2141
{
2142
    if (T0)
2143
        DT2 = DT0;
2144
    DEBUG_FPU_STATE();
2145
    RETURN();
2146
}
2147
FLOAT_OP(movn, s)
2148
{
2149
    if (T0)
2150
        WT2 = WT0;
2151
    DEBUG_FPU_STATE();
2152
    RETURN();
2153
}
2154
FLOAT_OP(movn, ps)
2155
{
2156
    if (T0) {
2157
        WT2 = WT0;
2158
        WTH2 = WTH0;
2159
    }
2160
    DEBUG_FPU_STATE();
2161
    RETURN();
2162
}
2163

    
2164
/* binary operations */
2165
#define FLOAT_BINOP(name) \
2166
FLOAT_OP(name, d)         \
2167
{                         \
2168
    set_float_exception_flags(0, &env->fp_status);            \
2169
    FDT2 = float64_ ## name (FDT0, FDT1, &env->fp_status);    \
2170
    update_fcr31();       \
2171
    DEBUG_FPU_STATE();    \
2172
}                         \
2173
FLOAT_OP(name, s)         \
2174
{                         \
2175
    set_float_exception_flags(0, &env->fp_status);            \
2176
    FST2 = float32_ ## name (FST0, FST1, &env->fp_status);    \
2177
    update_fcr31();       \
2178
    DEBUG_FPU_STATE();    \
2179
}                         \
2180
FLOAT_OP(name, ps)        \
2181
{                         \
2182
    set_float_exception_flags(0, &env->fp_status);            \
2183
    FST2 = float32_ ## name (FST0, FST1, &env->fp_status);    \
2184
    FSTH2 = float32_ ## name (FSTH0, FSTH1, &env->fp_status); \
2185
    update_fcr31();       \
2186
    DEBUG_FPU_STATE();    \
2187
}
2188
FLOAT_BINOP(add)
2189
FLOAT_BINOP(sub)
2190
FLOAT_BINOP(mul)
2191
FLOAT_BINOP(div)
2192
#undef FLOAT_BINOP
2193

    
2194
/* ternary operations */
2195
#define FLOAT_TERNOP(name1, name2) \
2196
FLOAT_OP(name1 ## name2, d)        \
2197
{                                  \
2198
    FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fp_status);    \
2199
    FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fp_status);    \
2200
    DEBUG_FPU_STATE();             \
2201
}                                  \
2202
FLOAT_OP(name1 ## name2, s)        \
2203
{                                  \
2204
    FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status);    \
2205
    FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status);    \
2206
    DEBUG_FPU_STATE();             \
2207
}                                  \
2208
FLOAT_OP(name1 ## name2, ps)       \
2209
{                                  \
2210
    FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status);    \
2211
    FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fp_status); \
2212
    FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status);    \
2213
    FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fp_status); \
2214
    DEBUG_FPU_STATE();             \
2215
}
2216
FLOAT_TERNOP(mul, add)
2217
FLOAT_TERNOP(mul, sub)
2218
#undef FLOAT_TERNOP
2219

    
2220
/* unary operations, modifying fp status  */
2221
#define FLOAT_UNOP(name)  \
2222
FLOAT_OP(name, d)         \
2223
{                         \
2224
    FDT2 = float64_ ## name(FDT0, &env->fp_status);   \
2225
    DEBUG_FPU_STATE();    \
2226
}                         \
2227
FLOAT_OP(name, s)         \
2228
{                         \
2229
    FST2 = float32_ ## name(FST0, &env->fp_status);   \
2230
    DEBUG_FPU_STATE();    \
2231
}                         \
2232
FLOAT_OP(name, ps)        \
2233
{                         \
2234
    FST2 = float32_ ## name(FST0, &env->fp_status);   \
2235
    FSTH2 = float32_ ## name(FSTH0, &env->fp_status); \
2236
    DEBUG_FPU_STATE();    \
2237
}
2238
FLOAT_UNOP(sqrt)
2239
#undef FLOAT_UNOP
2240

    
2241
/* unary operations, not modifying fp status  */
2242
#define FLOAT_UNOP(name)  \
2243
FLOAT_OP(name, d)         \
2244
{                         \
2245
    FDT2 = float64_ ## name(FDT0);   \
2246
    DEBUG_FPU_STATE();    \
2247
}                         \
2248
FLOAT_OP(name, s)         \
2249
{                         \
2250
    FST2 = float32_ ## name(FST0);   \
2251
    DEBUG_FPU_STATE();    \
2252
}                         \
2253
FLOAT_OP(name, ps)        \
2254
{                         \
2255
    FST2 = float32_ ## name(FST0);   \
2256
    FSTH2 = float32_ ## name(FSTH0); \
2257
    DEBUG_FPU_STATE();    \
2258
}
2259
FLOAT_UNOP(abs)
2260
FLOAT_UNOP(chs)
2261
#undef FLOAT_UNOP
2262

    
2263
FLOAT_OP(mov, d)
2264
{
2265
    FDT2 = FDT0;
2266
    DEBUG_FPU_STATE();
2267
    RETURN();
2268
}
2269
FLOAT_OP(mov, s)
2270
{
2271
    FST2 = FST0;
2272
    DEBUG_FPU_STATE();
2273
    RETURN();
2274
}
2275
FLOAT_OP(mov, ps)
2276
{
2277
    FST2 = FST0;
2278
    FSTH2 = FSTH0;
2279
    DEBUG_FPU_STATE();
2280
    RETURN();
2281
}
2282
FLOAT_OP(alnv, ps)
2283
{
2284
    switch (T0 & 0x7) {
2285
    case 0:
2286
        FST2 = FST0;
2287
        FSTH2 = FSTH0;
2288
        break;
2289
    case 4:
2290
#ifdef TARGET_WORDS_BIGENDIAN
2291
        FSTH2 = FST0;
2292
        FST2 = FSTH1;
2293
#else
2294
        FSTH2 = FST1;
2295
        FST2 = FSTH0;
2296
#endif
2297
        break;
2298
    default: /* unpredictable */
2299
        break;
2300
    }
2301
    DEBUG_FPU_STATE();
2302
    RETURN();
2303
}
2304

    
2305
#ifdef CONFIG_SOFTFLOAT
2306
#define clear_invalid() do {                                \
2307
    int flags = get_float_exception_flags(&env->fp_status); \
2308
    flags &= ~float_flag_invalid;                           \
2309
    set_float_exception_flags(flags, &env->fp_status);      \
2310
} while(0)
2311
#else
2312
#define clear_invalid() do { } while(0)
2313
#endif
2314

    
2315
extern void dump_fpu_s(CPUState *env);
2316

    
2317
#define FOP_COND_D(op, cond)                   \
2318
void op_cmp_d_ ## op (void)                    \
2319
{                                              \
2320
    int c = cond;                              \
2321
    update_fcr31();                            \
2322
    if (c)                                     \
2323
        SET_FP_COND(PARAM1, env);              \
2324
    else                                       \
2325
        CLEAR_FP_COND(PARAM1, env);            \
2326
    DEBUG_FPU_STATE();                         \
2327
    RETURN();                                  \
2328
}
2329

    
2330
int float64_is_unordered(int sig, float64 a, float64 b STATUS_PARAM)
2331
{
2332
    if (float64_is_signaling_nan(a) ||
2333
        float64_is_signaling_nan(b) ||
2334
        (sig && (float64_is_nan(a) || float64_is_nan(b)))) {
2335
        float_raise(float_flag_invalid, status);
2336
        return 1;
2337
    } else if (float64_is_nan(a) || float64_is_nan(b)) {
2338
        return 1;
2339
    } else {
2340
        return 0;
2341
    }
2342
}
2343

    
2344
/* NOTE: the comma operator will make "cond" to eval to false,
2345
 * but float*_is_unordered() is still called. */
2346
FOP_COND_D(f,   (float64_is_unordered(0, FDT1, FDT0, &env->fp_status), 0))
2347
FOP_COND_D(un,  float64_is_unordered(0, FDT1, FDT0, &env->fp_status))
2348
FOP_COND_D(eq,  !float64_is_unordered(0, FDT1, FDT0, &env->fp_status) && float64_eq(FDT0, FDT1, &env->fp_status))
2349
FOP_COND_D(ueq, float64_is_unordered(0, FDT1, FDT0, &env->fp_status)  || float64_eq(FDT0, FDT1, &env->fp_status))
2350
FOP_COND_D(olt, !float64_is_unordered(0, FDT1, FDT0, &env->fp_status) && float64_lt(FDT0, FDT1, &env->fp_status))
2351
FOP_COND_D(ult, float64_is_unordered(0, FDT1, FDT0, &env->fp_status)  || float64_lt(FDT0, FDT1, &env->fp_status))
2352
FOP_COND_D(ole, !float64_is_unordered(0, FDT1, FDT0, &env->fp_status) && float64_le(FDT0, FDT1, &env->fp_status))
2353
FOP_COND_D(ule, float64_is_unordered(0, FDT1, FDT0, &env->fp_status)  || float64_le(FDT0, FDT1, &env->fp_status))
2354
/* NOTE: the comma operator will make "cond" to eval to false,
2355
 * but float*_is_unordered() is still called. */
2356
FOP_COND_D(sf,  (float64_is_unordered(1, FDT1, FDT0, &env->fp_status), 0))
2357
FOP_COND_D(ngle,float64_is_unordered(1, FDT1, FDT0, &env->fp_status))
2358
FOP_COND_D(seq, !float64_is_unordered(1, FDT1, FDT0, &env->fp_status) && float64_eq(FDT0, FDT1, &env->fp_status))
2359
FOP_COND_D(ngl, float64_is_unordered(1, FDT1, FDT0, &env->fp_status)  || float64_eq(FDT0, FDT1, &env->fp_status))
2360
FOP_COND_D(lt,  !float64_is_unordered(1, FDT1, FDT0, &env->fp_status) && float64_lt(FDT0, FDT1, &env->fp_status))
2361
FOP_COND_D(nge, float64_is_unordered(1, FDT1, FDT0, &env->fp_status)  || float64_lt(FDT0, FDT1, &env->fp_status))
2362
FOP_COND_D(le,  !float64_is_unordered(1, FDT1, FDT0, &env->fp_status) && float64_le(FDT0, FDT1, &env->fp_status))
2363
FOP_COND_D(ngt, float64_is_unordered(1, FDT1, FDT0, &env->fp_status)  || float64_le(FDT0, FDT1, &env->fp_status))
2364

    
2365
#define FOP_COND_S(op, cond)                   \
2366
void op_cmp_s_ ## op (void)                    \
2367
{                                              \
2368
    int c = cond;                              \
2369
    update_fcr31();                            \
2370
    if (c)                                     \
2371
        SET_FP_COND(PARAM1, env);              \
2372
    else                                       \
2373
        CLEAR_FP_COND(PARAM1, env);            \
2374
    DEBUG_FPU_STATE();                         \
2375
    RETURN();                                  \
2376
}
2377

    
2378
flag float32_is_unordered(int sig, float32 a, float32 b STATUS_PARAM)
2379
{
2380
    extern flag float32_is_nan(float32 a);
2381
    if (float32_is_signaling_nan(a) ||
2382
        float32_is_signaling_nan(b) ||
2383
        (sig && (float32_is_nan(a) || float32_is_nan(b)))) {
2384
        float_raise(float_flag_invalid, status);
2385
        return 1;
2386
    } else if (float32_is_nan(a) || float32_is_nan(b)) {
2387
        return 1;
2388
    } else {
2389
        return 0;
2390
    }
2391
}
2392

    
2393
/* NOTE: the comma operator will make "cond" to eval to false,
2394
 * but float*_is_unordered() is still called. */
2395
FOP_COND_S(f,   (float32_is_unordered(0, FST1, FST0, &env->fp_status), 0))
2396
FOP_COND_S(un,  float32_is_unordered(0, FST1, FST0, &env->fp_status))
2397
FOP_COND_S(eq,  !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_eq(FST0, FST1, &env->fp_status))
2398
FOP_COND_S(ueq, float32_is_unordered(0, FST1, FST0, &env->fp_status)  || float32_eq(FST0, FST1, &env->fp_status))
2399
FOP_COND_S(olt, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_lt(FST0, FST1, &env->fp_status))
2400
FOP_COND_S(ult, float32_is_unordered(0, FST1, FST0, &env->fp_status)  || float32_lt(FST0, FST1, &env->fp_status))
2401
FOP_COND_S(ole, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_le(FST0, FST1, &env->fp_status))
2402
FOP_COND_S(ule, float32_is_unordered(0, FST1, FST0, &env->fp_status)  || float32_le(FST0, FST1, &env->fp_status))
2403
/* NOTE: the comma operator will make "cond" to eval to false,
2404
 * but float*_is_unordered() is still called. */
2405
FOP_COND_S(sf,  (float32_is_unordered(1, FST1, FST0, &env->fp_status), 0))
2406
FOP_COND_S(ngle,float32_is_unordered(1, FST1, FST0, &env->fp_status))
2407
FOP_COND_S(seq, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_eq(FST0, FST1, &env->fp_status))
2408
FOP_COND_S(ngl, float32_is_unordered(1, FST1, FST0, &env->fp_status)  || float32_eq(FST0, FST1, &env->fp_status))
2409
FOP_COND_S(lt,  !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_lt(FST0, FST1, &env->fp_status))
2410
FOP_COND_S(nge, float32_is_unordered(1, FST1, FST0, &env->fp_status)  || float32_lt(FST0, FST1, &env->fp_status))
2411
FOP_COND_S(le,  !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_le(FST0, FST1, &env->fp_status))
2412
FOP_COND_S(ngt, float32_is_unordered(1, FST1, FST0, &env->fp_status)  || float32_le(FST0, FST1, &env->fp_status))
2413

    
2414
#define FOP_COND_PS(op, condl, condh)          \
2415
void op_cmp_ps_ ## op (void)                   \
2416
{                                              \
2417
    int cl = condl;                            \
2418
    int ch = condh;                            \
2419
    update_fcr31();                            \
2420
    if (cl)                                    \
2421
        SET_FP_COND(PARAM1, env);              \
2422
    else                                       \
2423
        CLEAR_FP_COND(PARAM1, env);            \
2424
    if (ch)                                    \
2425
        SET_FP_COND(PARAM1 + 1, env);          \
2426
    else                                       \
2427
        CLEAR_FP_COND(PARAM1 + 1, env);        \
2428
    DEBUG_FPU_STATE();                         \
2429
    RETURN();                                  \
2430
}
2431

    
2432
/* NOTE: the comma operator will make "cond" to eval to false,
2433
 * but float*_is_unordered() is still called. */
2434
FOP_COND_PS(f,   (float32_is_unordered(0, FST1, FST0, &env->fp_status), 0),
2435
                 (float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status), 0))
2436
FOP_COND_PS(un,  float32_is_unordered(0, FST1, FST0, &env->fp_status),
2437
                 float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status))
2438
FOP_COND_PS(eq,  !float32_is_unordered(0, FST1, FST0, &env->fp_status)   && float32_eq(FST0, FST1, &env->fp_status),
2439
                 !float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) && float32_eq(FSTH0, FSTH1, &env->fp_status))
2440
FOP_COND_PS(ueq, float32_is_unordered(0, FST1, FST0, &env->fp_status)    || float32_eq(FST0, FST1, &env->fp_status),
2441
                 float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status)  || float32_eq(FSTH0, FSTH1, &env->fp_status))
2442
FOP_COND_PS(olt, !float32_is_unordered(0, FST1, FST0, &env->fp_status)   && float32_lt(FST0, FST1, &env->fp_status),
2443
                 !float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) && float32_lt(FSTH0, FSTH1, &env->fp_status))
2444
FOP_COND_PS(ult, float32_is_unordered(0, FST1, FST0, &env->fp_status)    || float32_lt(FST0, FST1, &env->fp_status),
2445
                 float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status)  || float32_lt(FSTH0, FSTH1, &env->fp_status))
2446
FOP_COND_PS(ole, !float32_is_unordered(0, FST1, FST0, &env->fp_status)   && float32_le(FST0, FST1, &env->fp_status),
2447
                 !float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) && float32_le(FSTH0, FSTH1, &env->fp_status))
2448
FOP_COND_PS(ule, float32_is_unordered(0, FST1, FST0, &env->fp_status)    || float32_le(FST0, FST1, &env->fp_status),
2449
                 float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status)  || float32_le(FSTH0, FSTH1, &env->fp_status))
2450
/* NOTE: the comma operator will make "cond" to eval to false,
2451
 * but float*_is_unordered() is still called. */
2452
FOP_COND_PS(sf,  (float32_is_unordered(1, FST1, FST0, &env->fp_status), 0),
2453
                 (float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status), 0))
2454
FOP_COND_PS(ngle,float32_is_unordered(1, FST1, FST0, &env->fp_status),
2455
                 float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status))
2456
FOP_COND_PS(seq, !float32_is_unordered(1, FST1, FST0, &env->fp_status)   && float32_eq(FST0, FST1, &env->fp_status),
2457
                 !float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) && float32_eq(FSTH0, FSTH1, &env->fp_status))
2458
FOP_COND_PS(ngl, float32_is_unordered(1, FST1, FST0, &env->fp_status)    || float32_eq(FST0, FST1, &env->fp_status),
2459
                 float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status)  || float32_eq(FSTH0, FSTH1, &env->fp_status))
2460
FOP_COND_PS(lt,  !float32_is_unordered(1, FST1, FST0, &env->fp_status)   && float32_lt(FST0, FST1, &env->fp_status),
2461
                 !float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) && float32_lt(FSTH0, FSTH1, &env->fp_status))
2462
FOP_COND_PS(nge, float32_is_unordered(1, FST1, FST0, &env->fp_status)    || float32_lt(FST0, FST1, &env->fp_status),
2463
                 float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status)  || float32_lt(FSTH0, FSTH1, &env->fp_status))
2464
FOP_COND_PS(le,  !float32_is_unordered(1, FST1, FST0, &env->fp_status)   && float32_le(FST0, FST1, &env->fp_status),
2465
                 !float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) && float32_le(FSTH0, FSTH1, &env->fp_status))
2466
FOP_COND_PS(ngt, float32_is_unordered(1, FST1, FST0, &env->fp_status)    || float32_le(FST0, FST1, &env->fp_status),
2467
                 float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status)  || float32_le(FSTH0, FSTH1, &env->fp_status))
2468

    
2469
void op_bc1f (void)
2470
{
2471
    T0 = !IS_FP_COND_SET(PARAM1, env);
2472
    DEBUG_FPU_STATE();
2473
    RETURN();
2474
}
2475
void op_bc1fany2 (void)
2476
{
2477
    T0 = (!IS_FP_COND_SET(PARAM1, env) ||
2478
          !IS_FP_COND_SET(PARAM1 + 1, env));
2479
    DEBUG_FPU_STATE();
2480
    RETURN();
2481
}
2482
void op_bc1fany4 (void)
2483
{
2484
    T0 = (!IS_FP_COND_SET(PARAM1, env) ||
2485
          !IS_FP_COND_SET(PARAM1 + 1, env) ||
2486
          !IS_FP_COND_SET(PARAM1 + 2, env) ||
2487
          !IS_FP_COND_SET(PARAM1 + 3, env));
2488
    DEBUG_FPU_STATE();
2489
    RETURN();
2490
}
2491

    
2492
void op_bc1t (void)
2493
{
2494
    T0 = IS_FP_COND_SET(PARAM1, env);
2495
    DEBUG_FPU_STATE();
2496
    RETURN();
2497
}
2498
void op_bc1tany2 (void)
2499
{
2500
    T0 = (IS_FP_COND_SET(PARAM1, env) ||
2501
          IS_FP_COND_SET(PARAM1 + 1, env));
2502
    DEBUG_FPU_STATE();
2503
    RETURN();
2504
}
2505
void op_bc1tany4 (void)
2506
{
2507
    T0 = (IS_FP_COND_SET(PARAM1, env) ||
2508
          IS_FP_COND_SET(PARAM1 + 1, env) ||
2509
          IS_FP_COND_SET(PARAM1 + 2, env) ||
2510
          IS_FP_COND_SET(PARAM1 + 3, env));
2511
    DEBUG_FPU_STATE();
2512
    RETURN();
2513
}
2514

    
2515
#if defined(MIPS_USES_R4K_TLB)
2516
void op_tlbwi (void)
2517
{
2518
    CALL_FROM_TB0(do_tlbwi);
2519
    RETURN();
2520
}
2521

    
2522
void op_tlbwr (void)
2523
{
2524
    CALL_FROM_TB0(do_tlbwr);
2525
    RETURN();
2526
}
2527

    
2528
void op_tlbp (void)
2529
{
2530
    CALL_FROM_TB0(do_tlbp);
2531
    RETURN();
2532
}
2533

    
2534
void op_tlbr (void)
2535
{
2536
    CALL_FROM_TB0(do_tlbr);
2537
    RETURN();
2538
}
2539
#endif
2540

    
2541
/* Specials */
2542
#if defined (CONFIG_USER_ONLY)
2543
void op_tls_value (void)
2544
{
2545
    T0 = env->tls_value;
2546
}
2547
#endif
2548

    
2549
void op_pmon (void)
2550
{
2551
    CALL_FROM_TB1(do_pmon, PARAM1);
2552
    RETURN();
2553
}
2554

    
2555
void op_di (void)
2556
{
2557
    T0 = env->CP0_Status;
2558
    env->CP0_Status = T0 & ~(1 << CP0St_IE);
2559
    CALL_FROM_TB1(cpu_mips_update_irq, env);
2560
    RETURN();
2561
}
2562

    
2563
void op_ei (void)
2564
{
2565
    T0 = env->CP0_Status;
2566
    env->CP0_Status = T0 | (1 << CP0St_IE);
2567
    CALL_FROM_TB1(cpu_mips_update_irq, env);
2568
    RETURN();
2569
}
2570

    
2571
void op_trap (void)
2572
{
2573
    if (T0) {
2574
        CALL_FROM_TB1(do_raise_exception, EXCP_TRAP);
2575
    }
2576
    RETURN();
2577
}
2578

    
2579
void op_debug (void)
2580
{
2581
    CALL_FROM_TB1(do_raise_exception, EXCP_DEBUG);
2582
    RETURN();
2583
}
2584

    
2585
void op_set_lladdr (void)
2586
{
2587
    env->CP0_LLAddr = T2;
2588
    RETURN();
2589
}
2590

    
2591
void debug_pre_eret (void);
2592
void debug_post_eret (void);
2593
void op_eret (void)
2594
{
2595
    if (loglevel & CPU_LOG_EXEC)
2596
        CALL_FROM_TB0(debug_pre_eret);
2597
    if (env->CP0_Status & (1 << CP0St_ERL)) {
2598
        env->PC = env->CP0_ErrorEPC;
2599
        env->CP0_Status &= ~(1 << CP0St_ERL);
2600
    } else {
2601
        env->PC = env->CP0_EPC;
2602
        env->CP0_Status &= ~(1 << CP0St_EXL);
2603
    }
2604
    if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
2605
        !(env->CP0_Status & (1 << CP0St_ERL)) &&
2606
        !(env->hflags & MIPS_HFLAG_DM) &&
2607
        (env->CP0_Status & (1 << CP0St_UM)))
2608
        env->hflags |= MIPS_HFLAG_UM;
2609
    if (loglevel & CPU_LOG_EXEC)
2610
        CALL_FROM_TB0(debug_post_eret);
2611
    env->CP0_LLAddr = 1;
2612
    RETURN();
2613
}
2614

    
2615
void op_deret (void)
2616
{
2617
    if (loglevel & CPU_LOG_EXEC)
2618
        CALL_FROM_TB0(debug_pre_eret);
2619
    env->PC = env->CP0_DEPC;
2620
    env->hflags |= MIPS_HFLAG_DM;
2621
    if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
2622
        !(env->CP0_Status & (1 << CP0St_ERL)) &&
2623
        !(env->hflags & MIPS_HFLAG_DM) &&
2624
        (env->CP0_Status & (1 << CP0St_UM)))
2625
        env->hflags |= MIPS_HFLAG_UM;
2626
    if (loglevel & CPU_LOG_EXEC)
2627
        CALL_FROM_TB0(debug_post_eret);
2628
    env->CP0_LLAddr = 1;
2629
    RETURN();
2630
}
2631

    
2632
void op_rdhwr_cpunum(void)
2633
{
2634
    if (!(env->hflags & MIPS_HFLAG_UM) ||
2635
        (env->CP0_HWREna & (1 << 0)) ||
2636
        (env->CP0_Status & (1 << CP0St_CU0)))
2637
        T0 = env->CP0_EBase & 0x3ff;
2638
    else
2639
        CALL_FROM_TB1(do_raise_exception, EXCP_RI);
2640
    RETURN();
2641
}
2642

    
2643
void op_rdhwr_synci_step(void)
2644
{
2645
    if (!(env->hflags & MIPS_HFLAG_UM) ||
2646
        (env->CP0_HWREna & (1 << 1)) ||
2647
        (env->CP0_Status & (1 << CP0St_CU0)))
2648
        T0 = env->SYNCI_Step;
2649
    else
2650
        CALL_FROM_TB1(do_raise_exception, EXCP_RI);
2651
    RETURN();
2652
}
2653

    
2654
void op_rdhwr_cc(void)
2655
{
2656
    if (!(env->hflags & MIPS_HFLAG_UM) ||
2657
        (env->CP0_HWREna & (1 << 2)) ||
2658
        (env->CP0_Status & (1 << CP0St_CU0)))
2659
        T0 = env->CP0_Count;
2660
    else
2661
        CALL_FROM_TB1(do_raise_exception, EXCP_RI);
2662
    RETURN();
2663
}
2664

    
2665
void op_rdhwr_ccres(void)
2666
{
2667
    if (!(env->hflags & MIPS_HFLAG_UM) ||
2668
        (env->CP0_HWREna & (1 << 3)) ||
2669
        (env->CP0_Status & (1 << CP0St_CU0)))
2670
        T0 = env->CCRes;
2671
    else
2672
        CALL_FROM_TB1(do_raise_exception, EXCP_RI);
2673
    RETURN();
2674
}
2675

    
2676
void op_save_state (void)
2677
{
2678
    env->hflags = PARAM1;
2679
    RETURN();
2680
}
2681

    
2682
void op_save_pc (void)
2683
{
2684
    env->PC = PARAM1;
2685
    RETURN();
2686
}
2687

    
2688
void op_save_fp_status (void)
2689
{
2690
    union fps {
2691
        uint32_t i;
2692
        float_status f;
2693
    } fps;
2694
    fps.i = PARAM1;
2695
    env->fp_status = fps.f;
2696
    RETURN();
2697
}
2698

    
2699
void op_interrupt_restart (void)
2700
{
2701
    if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
2702
        !(env->CP0_Status & (1 << CP0St_ERL)) &&
2703
        !(env->hflags & MIPS_HFLAG_DM) &&
2704
        (env->CP0_Status & (1 << CP0St_IE)) &&
2705
        (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask)) {
2706
        env->CP0_Cause &= ~(0x1f << CP0Ca_EC);
2707
        CALL_FROM_TB1(do_raise_exception, EXCP_EXT_INTERRUPT);
2708
    }
2709
    RETURN();
2710
}
2711

    
2712
void op_raise_exception (void)
2713
{
2714
    CALL_FROM_TB1(do_raise_exception, PARAM1);
2715
    RETURN();
2716
}
2717

    
2718
void op_raise_exception_err (void)
2719
{
2720
    CALL_FROM_TB2(do_raise_exception_err, PARAM1, PARAM2);
2721
    RETURN();
2722
}
2723

    
2724
void op_exit_tb (void)
2725
{
2726
    EXIT_TB();
2727
    RETURN();
2728
}
2729

    
2730
void op_wait (void)
2731
{
2732
    env->halted = 1;
2733
    CALL_FROM_TB1(do_raise_exception, EXCP_HLT);
2734
    RETURN();
2735
}
2736

    
2737
/* Bitfield operations. */
2738
void op_ext(void)
2739
{
2740
    unsigned int pos = PARAM1;
2741
    unsigned int size = PARAM2;
2742

    
2743
    T0 = ((uint32_t)T1 >> pos) & ((size < 32) ? ((1 << size) - 1) : ~0);
2744
    RETURN();
2745
}
2746

    
2747
void op_ins(void)
2748
{
2749
    unsigned int pos = PARAM1;
2750
    unsigned int size = PARAM2;
2751
    target_ulong mask = ((size < 32) ? ((1 << size) - 1) : ~0) << pos;
2752

    
2753
    T0 = (T0 & ~mask) | (((uint32_t)T1 << pos) & mask);
2754
    RETURN();
2755
}
2756

    
2757
void op_wsbh(void)
2758
{
2759
    T0 = ((T1 << 8) & ~0x00FF00FF) | ((T1 >> 8) & 0x00FF00FF);
2760
    RETURN();
2761
}
2762

    
2763
#ifdef TARGET_MIPS64
2764
void op_dext(void)
2765
{
2766
    unsigned int pos = PARAM1;
2767
    unsigned int size = PARAM2;
2768

    
2769
    T0 = (T1 >> pos) & ((size < 32) ? ((1 << size) - 1) : ~0);
2770
    RETURN();
2771
}
2772

    
2773
void op_dins(void)
2774
{
2775
    unsigned int pos = PARAM1;
2776
    unsigned int size = PARAM2;
2777
    target_ulong mask = ((size < 32) ? ((1 << size) - 1) : ~0) << pos;
2778

    
2779
    T0 = (T0 & ~mask) | ((T1 << pos) & mask);
2780
    RETURN();
2781
}
2782

    
2783
void op_dsbh(void)
2784
{
2785
    T0 = ((T1 << 8) & ~0x00FF00FF00FF00FFULL) | ((T1 >> 8) & 0x00FF00FF00FF00FFULL);
2786
    RETURN();
2787
}
2788

    
2789
void op_dshd(void)
2790
{
2791
    T0 = ((T1 << 16) & ~0x0000FFFF0000FFFFULL) | ((T1 >> 16) & 0x0000FFFF0000FFFFULL);
2792
    RETURN();
2793
}
2794
#endif
2795

    
2796
void op_seb(void)
2797
{
2798
    T0 = ((T1 & 0xFF) ^ 0x80) - 0x80;
2799
    RETURN();
2800
}
2801

    
2802
void op_seh(void)
2803
{
2804
    T0 = ((T1 & 0xFFFF) ^ 0x8000) - 0x8000;
2805
    RETURN();
2806
}