Statistics
| Branch: | Revision:

root / target-mips / op.c @ 171b31e7

History | View | Annotate | Download (42.2 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 SFREG 0
148
#define DFREG 0
149
#include "fop_template.c"
150
#undef SFREG
151
#undef DFREG
152
#define SFREG 1
153
#include "fop_template.c"
154
#undef SFREG
155
#define SFREG 2
156
#define DFREG 2
157
#include "fop_template.c"
158
#undef SFREG
159
#undef DFREG
160
#define SFREG 3
161
#include "fop_template.c"
162
#undef SFREG
163
#define SFREG 4
164
#define DFREG 4
165
#include "fop_template.c"
166
#undef SFREG
167
#undef DFREG
168
#define SFREG 5
169
#include "fop_template.c"
170
#undef SFREG
171
#define SFREG 6
172
#define DFREG 6
173
#include "fop_template.c"
174
#undef SFREG
175
#undef DFREG
176
#define SFREG 7
177
#include "fop_template.c"
178
#undef SFREG
179
#define SFREG 8
180
#define DFREG 8
181
#include "fop_template.c"
182
#undef SFREG
183
#undef DFREG
184
#define SFREG 9
185
#include "fop_template.c"
186
#undef SFREG
187
#define SFREG 10
188
#define DFREG 10
189
#include "fop_template.c"
190
#undef SFREG
191
#undef DFREG
192
#define SFREG 11
193
#include "fop_template.c"
194
#undef SFREG
195
#define SFREG 12
196
#define DFREG 12
197
#include "fop_template.c"
198
#undef SFREG
199
#undef DFREG
200
#define SFREG 13
201
#include "fop_template.c"
202
#undef SFREG
203
#define SFREG 14
204
#define DFREG 14
205
#include "fop_template.c"
206
#undef SFREG
207
#undef DFREG
208
#define SFREG 15
209
#include "fop_template.c"
210
#undef SFREG
211
#define SFREG 16
212
#define DFREG 16
213
#include "fop_template.c"
214
#undef SFREG
215
#undef DFREG
216
#define SFREG 17
217
#include "fop_template.c"
218
#undef SFREG
219
#define SFREG 18
220
#define DFREG 18
221
#include "fop_template.c"
222
#undef SFREG
223
#undef DFREG
224
#define SFREG 19
225
#include "fop_template.c"
226
#undef SFREG
227
#define SFREG 20
228
#define DFREG 20
229
#include "fop_template.c"
230
#undef SFREG
231
#undef DFREG
232
#define SFREG 21
233
#include "fop_template.c"
234
#undef SFREG
235
#define SFREG 22
236
#define DFREG 22
237
#include "fop_template.c"
238
#undef SFREG
239
#undef DFREG
240
#define SFREG 23
241
#include "fop_template.c"
242
#undef SFREG
243
#define SFREG 24
244
#define DFREG 24
245
#include "fop_template.c"
246
#undef SFREG
247
#undef DFREG
248
#define SFREG 25
249
#include "fop_template.c"
250
#undef SFREG
251
#define SFREG 26
252
#define DFREG 26
253
#include "fop_template.c"
254
#undef SFREG
255
#undef DFREG
256
#define SFREG 27
257
#include "fop_template.c"
258
#undef SFREG
259
#define SFREG 28
260
#define DFREG 28
261
#include "fop_template.c"
262
#undef SFREG
263
#undef DFREG
264
#define SFREG 29
265
#include "fop_template.c"
266
#undef SFREG
267
#define SFREG 30
268
#define DFREG 30
269
#include "fop_template.c"
270
#undef SFREG
271
#undef DFREG
272
#define SFREG 31
273
#include "fop_template.c"
274
#undef SFREG
275

    
276
#define FTN
277
#include "fop_template.c"
278
#undef FTN
279

    
280
void op_dup_T0 (void)
281
{
282
    T2 = T0;
283
    RETURN();
284
}
285

    
286
void op_load_HI (void)
287
{
288
    T0 = env->HI;
289
    RETURN();
290
}
291

    
292
void op_store_HI (void)
293
{
294
    env->HI = T0;
295
    RETURN();
296
}
297

    
298
void op_load_LO (void)
299
{
300
    T0 = env->LO;
301
    RETURN();
302
}
303

    
304
void op_store_LO (void)
305
{
306
    env->LO = T0;
307
    RETURN();
308
}
309

    
310
/* Load and store */
311
#define MEMSUFFIX _raw
312
#include "op_mem.c"
313
#undef MEMSUFFIX
314
#if !defined(CONFIG_USER_ONLY)
315
#define MEMSUFFIX _user
316
#include "op_mem.c"
317
#undef MEMSUFFIX
318

    
319
#define MEMSUFFIX _kernel
320
#include "op_mem.c"
321
#undef MEMSUFFIX
322
#endif
323

    
324
/* Arithmetic */
325
void op_add (void)
326
{
327
    T0 = (int32_t)((int32_t)T0 + (int32_t)T1);
328
    RETURN();
329
}
330

    
331
void op_addo (void)
332
{
333
    target_ulong tmp;
334

    
335
    tmp = (int32_t)T0;
336
    T0 = (int32_t)T0 + (int32_t)T1;
337
    if (((tmp ^ T1 ^ (-1)) & (T0 ^ T1)) >> 31) {
338
        /* operands of same sign, result different sign */
339
        CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
340
    }
341
    T0 = (int32_t)T0;
342
    RETURN();
343
}
344

    
345
void op_sub (void)
346
{
347
    T0 = (int32_t)((int32_t)T0 - (int32_t)T1);
348
    RETURN();
349
}
350

    
351
void op_subo (void)
352
{
353
    target_ulong tmp;
354

    
355
    tmp = (int32_t)T0;
356
    T0 = (int32_t)T0 - (int32_t)T1;
357
    if (((tmp ^ T1) & (tmp ^ T0)) >> 31) {
358
        /* operands of different sign, first operand and result different sign */
359
        CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
360
    }
361
    T0 = (int32_t)T0;
362
    RETURN();
363
}
364

    
365
void op_mul (void)
366
{
367
    T0 = (int32_t)((int32_t)T0 * (int32_t)T1);
368
    RETURN();
369
}
370

    
371
#if HOST_LONG_BITS < 64
372
void op_div (void)
373
{
374
    CALL_FROM_TB0(do_div);
375
    RETURN();
376
}
377
#else
378
void op_div (void)
379
{
380
    if (T1 != 0) {
381
        env->LO = (int32_t)((int64_t)(int32_t)T0 / (int32_t)T1);
382
        env->HI = (int32_t)((int64_t)(int32_t)T0 % (int32_t)T1);
383
    }
384
    RETURN();
385
}
386
#endif
387

    
388
void op_divu (void)
389
{
390
    if (T1 != 0) {
391
        env->LO = (int32_t)((uint32_t)T0 / (uint32_t)T1);
392
        env->HI = (int32_t)((uint32_t)T0 % (uint32_t)T1);
393
    }
394
    RETURN();
395
}
396

    
397
#ifdef TARGET_MIPS64
398
/* Arithmetic */
399
void op_dadd (void)
400
{
401
    T0 += T1;
402
    RETURN();
403
}
404

    
405
void op_daddo (void)
406
{
407
    target_long tmp;
408

    
409
    tmp = T0;
410
    T0 += T1;
411
    if (((tmp ^ T1 ^ (-1)) & (T0 ^ T1)) >> 63) {
412
        /* operands of same sign, result different sign */
413
        CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
414
    }
415
    RETURN();
416
}
417

    
418
void op_dsub (void)
419
{
420
    T0 -= T1;
421
    RETURN();
422
}
423

    
424
void op_dsubo (void)
425
{
426
    target_long tmp;
427

    
428
    tmp = T0;
429
    T0 = (int64_t)T0 - (int64_t)T1;
430
    if (((tmp ^ T1) & (tmp ^ T0)) >> 63) {
431
        /* operands of different sign, first operand and result different sign */
432
        CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
433
    }
434
    RETURN();
435
}
436

    
437
void op_dmul (void)
438
{
439
    T0 = (int64_t)T0 * (int64_t)T1;
440
    RETURN();
441
}
442

    
443
/* Those might call libgcc functions.  */
444
void op_ddiv (void)
445
{
446
    do_ddiv();
447
    RETURN();
448
}
449

    
450
#if TARGET_LONG_BITS > HOST_LONG_BITS
451
void op_ddivu (void)
452
{
453
    do_ddivu();
454
    RETURN();
455
}
456
#else
457
void op_ddivu (void)
458
{
459
    if (T1 != 0) {
460
        env->LO = T0 / T1;
461
        env->HI = T0 % T1;
462
    }
463
    RETURN();
464
}
465
#endif
466
#endif /* TARGET_MIPS64 */
467

    
468
/* Logical */
469
void op_and (void)
470
{
471
    T0 &= T1;
472
    RETURN();
473
}
474

    
475
void op_nor (void)
476
{
477
    T0 = ~(T0 | T1);
478
    RETURN();
479
}
480

    
481
void op_or (void)
482
{
483
    T0 |= T1;
484
    RETURN();
485
}
486

    
487
void op_xor (void)
488
{
489
    T0 ^= T1;
490
    RETURN();
491
}
492

    
493
void op_sll (void)
494
{
495
    T0 = (int32_t)((uint32_t)T0 << T1);
496
    RETURN();
497
}
498

    
499
void op_sra (void)
500
{
501
    T0 = (int32_t)((int32_t)T0 >> T1);
502
    RETURN();
503
}
504

    
505
void op_srl (void)
506
{
507
    T0 = (int32_t)((uint32_t)T0 >> T1);
508
    RETURN();
509
}
510

    
511
void op_rotr (void)
512
{
513
    target_ulong tmp;
514

    
515
    if (T1) {
516
       tmp = (int32_t)((uint32_t)T0 << (0x20 - T1));
517
       T0 = (int32_t)((uint32_t)T0 >> T1) | tmp;
518
    }
519
    RETURN();
520
}
521

    
522
void op_sllv (void)
523
{
524
    T0 = (int32_t)((uint32_t)T1 << ((uint32_t)T0 & 0x1F));
525
    RETURN();
526
}
527

    
528
void op_srav (void)
529
{
530
    T0 = (int32_t)((int32_t)T1 >> (T0 & 0x1F));
531
    RETURN();
532
}
533

    
534
void op_srlv (void)
535
{
536
    T0 = (int32_t)((uint32_t)T1 >> (T0 & 0x1F));
537
    RETURN();
538
}
539

    
540
void op_rotrv (void)
541
{
542
    target_ulong tmp;
543

    
544
    T0 &= 0x1F;
545
    if (T0) {
546
       tmp = (int32_t)((uint32_t)T1 << (0x20 - T0));
547
       T0 = (int32_t)((uint32_t)T1 >> T0) | tmp;
548
    } else
549
       T0 = T1;
550
    RETURN();
551
}
552

    
553
void op_clo (void)
554
{
555
    int n;
556

    
557
    if (T0 == ~((target_ulong)0)) {
558
        T0 = 32;
559
    } else {
560
        for (n = 0; n < 32; n++) {
561
            if (!(T0 & (1 << 31)))
562
                break;
563
            T0 = T0 << 1;
564
        }
565
        T0 = n;
566
    }
567
    RETURN();
568
}
569

    
570
void op_clz (void)
571
{
572
    int n;
573

    
574
    if (T0 == 0) {
575
        T0 = 32;
576
    } else {
577
        for (n = 0; n < 32; n++) {
578
            if (T0 & (1 << 31))
579
                break;
580
            T0 = T0 << 1;
581
        }
582
        T0 = n;
583
    }
584
    RETURN();
585
}
586

    
587
#ifdef TARGET_MIPS64
588

    
589
#if TARGET_LONG_BITS > HOST_LONG_BITS
590
/* Those might call libgcc functions.  */
591
void op_dsll (void)
592
{
593
    CALL_FROM_TB0(do_dsll);
594
    RETURN();
595
}
596

    
597
void op_dsll32 (void)
598
{
599
    CALL_FROM_TB0(do_dsll32);
600
    RETURN();
601
}
602

    
603
void op_dsra (void)
604
{
605
    CALL_FROM_TB0(do_dsra);
606
    RETURN();
607
}
608

    
609
void op_dsra32 (void)
610
{
611
    CALL_FROM_TB0(do_dsra32);
612
    RETURN();
613
}
614

    
615
void op_dsrl (void)
616
{
617
    CALL_FROM_TB0(do_dsrl);
618
    RETURN();
619
}
620

    
621
void op_dsrl32 (void)
622
{
623
    CALL_FROM_TB0(do_dsrl32);
624
    RETURN();
625
}
626

    
627
void op_drotr (void)
628
{
629
    CALL_FROM_TB0(do_drotr);
630
    RETURN();
631
}
632

    
633
void op_drotr32 (void)
634
{
635
    CALL_FROM_TB0(do_drotr32);
636
    RETURN();
637
}
638

    
639
void op_dsllv (void)
640
{
641
    CALL_FROM_TB0(do_dsllv);
642
    RETURN();
643
}
644

    
645
void op_dsrav (void)
646
{
647
    CALL_FROM_TB0(do_dsrav);
648
    RETURN();
649
}
650

    
651
void op_dsrlv (void)
652
{
653
    CALL_FROM_TB0(do_dsrlv);
654
    RETURN();
655
}
656

    
657
void op_drotrv (void)
658
{
659
    CALL_FROM_TB0(do_drotrv);
660
    RETURN();
661
}
662

    
663
#else /* TARGET_LONG_BITS > HOST_LONG_BITS */
664

    
665
void op_dsll (void)
666
{
667
    T0 = T0 << T1;
668
    RETURN();
669
}
670

    
671
void op_dsll32 (void)
672
{
673
    T0 = T0 << (T1 + 32);
674
    RETURN();
675
}
676

    
677
void op_dsra (void)
678
{
679
    T0 = (int64_t)T0 >> T1;
680
    RETURN();
681
}
682

    
683
void op_dsra32 (void)
684
{
685
    T0 = (int64_t)T0 >> (T1 + 32);
686
    RETURN();
687
}
688

    
689
void op_dsrl (void)
690
{
691
    T0 = T0 >> T1;
692
    RETURN();
693
}
694

    
695
void op_dsrl32 (void)
696
{
697
    T0 = T0 >> (T1 + 32);
698
    RETURN();
699
}
700

    
701
void op_drotr (void)
702
{
703
    target_ulong tmp;
704

    
705
    if (T1) {
706
       tmp = T0 << (0x40 - T1);
707
       T0 = (T0 >> T1) | tmp;
708
    }
709
    RETURN();
710
}
711

    
712
void op_drotr32 (void)
713
{
714
    target_ulong tmp;
715

    
716
    if (T1) {
717
       tmp = T0 << (0x40 - (32 + T1));
718
       T0 = (T0 >> (32 + T1)) | tmp;
719
    }
720
    RETURN();
721
}
722

    
723
void op_dsllv (void)
724
{
725
    T0 = T1 << (T0 & 0x3F);
726
    RETURN();
727
}
728

    
729
void op_dsrav (void)
730
{
731
    T0 = (int64_t)T1 >> (T0 & 0x3F);
732
    RETURN();
733
}
734

    
735
void op_dsrlv (void)
736
{
737
    T0 = T1 >> (T0 & 0x3F);
738
    RETURN();
739
}
740

    
741
void op_drotrv (void)
742
{
743
    target_ulong tmp;
744

    
745
    T0 &= 0x3F;
746
    if (T0) {
747
       tmp = T1 << (0x40 - T0);
748
       T0 = (T1 >> T0) | tmp;
749
    } else
750
       T0 = T1;
751
    RETURN();
752
}
753
#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
754

    
755
void op_dclo (void)
756
{
757
    int n;
758

    
759
    if (T0 == ~((target_ulong)0)) {
760
        T0 = 64;
761
    } else {
762
        for (n = 0; n < 64; n++) {
763
            if (!(T0 & (1ULL << 63)))
764
                break;
765
            T0 = T0 << 1;
766
        }
767
        T0 = n;
768
    }
769
    RETURN();
770
}
771

    
772
void op_dclz (void)
773
{
774
    int n;
775

    
776
    if (T0 == 0) {
777
        T0 = 64;
778
    } else {
779
        for (n = 0; n < 64; n++) {
780
            if (T0 & (1ULL << 63))
781
                break;
782
            T0 = T0 << 1;
783
        }
784
        T0 = n;
785
    }
786
    RETURN();
787
}
788
#endif
789

    
790
/* 64 bits arithmetic */
791
#if TARGET_LONG_BITS > HOST_LONG_BITS
792
void op_mult (void)
793
{
794
    CALL_FROM_TB0(do_mult);
795
    RETURN();
796
}
797

    
798
void op_multu (void)
799
{
800
    CALL_FROM_TB0(do_multu);
801
    RETURN();
802
}
803

    
804
void op_madd (void)
805
{
806
    CALL_FROM_TB0(do_madd);
807
    RETURN();
808
}
809

    
810
void op_maddu (void)
811
{
812
    CALL_FROM_TB0(do_maddu);
813
    RETURN();
814
}
815

    
816
void op_msub (void)
817
{
818
    CALL_FROM_TB0(do_msub);
819
    RETURN();
820
}
821

    
822
void op_msubu (void)
823
{
824
    CALL_FROM_TB0(do_msubu);
825
    RETURN();
826
}
827

    
828
#else /* TARGET_LONG_BITS > HOST_LONG_BITS */
829

    
830
static inline uint64_t get_HILO (void)
831
{
832
    return ((uint64_t)env->HI << 32) | ((uint64_t)(uint32_t)env->LO);
833
}
834

    
835
static inline void set_HILO (uint64_t HILO)
836
{
837
    env->LO = (int32_t)(HILO & 0xFFFFFFFF);
838
    env->HI = (int32_t)(HILO >> 32);
839
}
840

    
841
void op_mult (void)
842
{
843
    set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
844
    RETURN();
845
}
846

    
847
void op_multu (void)
848
{
849
    set_HILO((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
850
    RETURN();
851
}
852

    
853
void op_madd (void)
854
{
855
    int64_t tmp;
856

    
857
    tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
858
    set_HILO((int64_t)get_HILO() + tmp);
859
    RETURN();
860
}
861

    
862
void op_maddu (void)
863
{
864
    uint64_t tmp;
865

    
866
    tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
867
    set_HILO(get_HILO() + tmp);
868
    RETURN();
869
}
870

    
871
void op_msub (void)
872
{
873
    int64_t tmp;
874

    
875
    tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
876
    set_HILO((int64_t)get_HILO() - tmp);
877
    RETURN();
878
}
879

    
880
void op_msubu (void)
881
{
882
    uint64_t tmp;
883

    
884
    tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
885
    set_HILO(get_HILO() - tmp);
886
    RETURN();
887
}
888
#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
889

    
890
#ifdef TARGET_MIPS64
891
void op_dmult (void)
892
{
893
    CALL_FROM_TB0(do_dmult);
894
    RETURN();
895
}
896

    
897
void op_dmultu (void)
898
{
899
    CALL_FROM_TB0(do_dmultu);
900
    RETURN();
901
}
902
#endif
903

    
904
/* Conditional moves */
905
void op_movn (void)
906
{
907
    if (T1 != 0)
908
        env->gpr[PARAM1] = T0;
909
    RETURN();
910
}
911

    
912
void op_movz (void)
913
{
914
    if (T1 == 0)
915
        env->gpr[PARAM1] = T0;
916
    RETURN();
917
}
918

    
919
void op_movf (void)
920
{
921
    if (!(env->fcr31 & PARAM1))
922
        env->gpr[PARAM2] = env->gpr[PARAM3];
923
    RETURN();
924
}
925

    
926
void op_movt (void)
927
{
928
    if (env->fcr31 & PARAM1)
929
        env->gpr[PARAM2] = env->gpr[PARAM3];
930
    RETURN();
931
}
932

    
933
/* Tests */
934
#define OP_COND(name, cond) \
935
void glue(op_, name) (void) \
936
{                           \
937
    if (cond) {             \
938
        T0 = 1;             \
939
    } else {                \
940
        T0 = 0;             \
941
    }                       \
942
    RETURN();               \
943
}
944

    
945
OP_COND(eq, T0 == T1);
946
OP_COND(ne, T0 != T1);
947
OP_COND(ge, (int32_t)T0 >= (int32_t)T1);
948
OP_COND(geu, T0 >= T1);
949
OP_COND(lt, (int32_t)T0 < (int32_t)T1);
950
OP_COND(ltu, T0 < T1);
951
OP_COND(gez, (int32_t)T0 >= 0);
952
OP_COND(gtz, (int32_t)T0 > 0);
953
OP_COND(lez, (int32_t)T0 <= 0);
954
OP_COND(ltz, (int32_t)T0 < 0);
955

    
956
/* Branches */
957
//#undef USE_DIRECT_JUMP
958

    
959
void OPPROTO op_goto_tb0(void)
960
{
961
    GOTO_TB(op_goto_tb0, PARAM1, 0);
962
    RETURN();
963
}
964

    
965
void OPPROTO op_goto_tb1(void)
966
{
967
    GOTO_TB(op_goto_tb1, PARAM1, 1);
968
    RETURN();
969
}
970

    
971
/* Branch to register */
972
void op_save_breg_target (void)
973
{
974
    env->btarget = T2;
975
    RETURN();
976
}
977

    
978
void op_restore_breg_target (void)
979
{
980
    T2 = env->btarget;
981
    RETURN();
982
}
983

    
984
void op_breg (void)
985
{
986
    env->PC = T2;
987
    RETURN();
988
}
989

    
990
void op_save_btarget (void)
991
{
992
    env->btarget = PARAM1;
993
    RETURN();
994
}
995

    
996
/* Conditional branch */
997
void op_set_bcond (void)
998
{
999
    T2 = T0;
1000
    RETURN();
1001
}
1002

    
1003
void op_save_bcond (void)
1004
{
1005
    env->bcond = T2;
1006
    RETURN();
1007
}
1008

    
1009
void op_restore_bcond (void)
1010
{
1011
    T2 = env->bcond;
1012
    RETURN();
1013
}
1014

    
1015
void op_jnz_T2 (void)
1016
{
1017
    if (T2)
1018
        GOTO_LABEL_PARAM(1);
1019
    RETURN();
1020
}
1021

    
1022
/* CP0 functions */
1023
void op_mfc0_index (void)
1024
{
1025
    T0 = env->CP0_Index;
1026
    RETURN();
1027
}
1028

    
1029
void op_mfc0_random (void)
1030
{
1031
    CALL_FROM_TB0(do_mfc0_random);
1032
    RETURN();
1033
}
1034

    
1035
void op_mfc0_entrylo0 (void)
1036
{
1037
    T0 = (int32_t)env->CP0_EntryLo0;
1038
    RETURN();
1039
}
1040

    
1041
void op_mfc0_entrylo1 (void)
1042
{
1043
    T0 = (int32_t)env->CP0_EntryLo1;
1044
    RETURN();
1045
}
1046

    
1047
void op_mfc0_context (void)
1048
{
1049
    T0 = (int32_t)env->CP0_Context;
1050
    RETURN();
1051
}
1052

    
1053
void op_mfc0_pagemask (void)
1054
{
1055
    T0 = env->CP0_PageMask;
1056
    RETURN();
1057
}
1058

    
1059
void op_mfc0_pagegrain (void)
1060
{
1061
    T0 = env->CP0_PageGrain;
1062
    RETURN();
1063
}
1064

    
1065
void op_mfc0_wired (void)
1066
{
1067
    T0 = env->CP0_Wired;
1068
    RETURN();
1069
}
1070

    
1071
void op_mfc0_hwrena (void)
1072
{
1073
    T0 = env->CP0_HWREna;
1074
    RETURN();
1075
}
1076

    
1077
void op_mfc0_badvaddr (void)
1078
{
1079
    T0 = (int32_t)env->CP0_BadVAddr;
1080
    RETURN();
1081
}
1082

    
1083
void op_mfc0_count (void)
1084
{
1085
    CALL_FROM_TB0(do_mfc0_count);
1086
    RETURN();
1087
}
1088

    
1089
void op_mfc0_entryhi (void)
1090
{
1091
    T0 = (int32_t)env->CP0_EntryHi;
1092
    RETURN();
1093
}
1094

    
1095
void op_mfc0_compare (void)
1096
{
1097
    T0 = env->CP0_Compare;
1098
    RETURN();
1099
}
1100

    
1101
void op_mfc0_status (void)
1102
{
1103
    T0 = env->CP0_Status;
1104
    RETURN();
1105
}
1106

    
1107
void op_mfc0_intctl (void)
1108
{
1109
    T0 = env->CP0_IntCtl;
1110
    RETURN();
1111
}
1112

    
1113
void op_mfc0_srsctl (void)
1114
{
1115
    T0 = env->CP0_SRSCtl;
1116
    RETURN();
1117
}
1118

    
1119
void op_mfc0_srsmap (void)
1120
{
1121
    T0 = env->CP0_SRSMap;
1122
    RETURN();
1123
}
1124

    
1125
void op_mfc0_cause (void)
1126
{
1127
    T0 = env->CP0_Cause;
1128
    RETURN();
1129
}
1130

    
1131
void op_mfc0_epc (void)
1132
{
1133
    T0 = (int32_t)env->CP0_EPC;
1134
    RETURN();
1135
}
1136

    
1137
void op_mfc0_prid (void)
1138
{
1139
    T0 = env->CP0_PRid;
1140
    RETURN();
1141
}
1142

    
1143
void op_mfc0_ebase (void)
1144
{
1145
    T0 = env->CP0_EBase;
1146
    RETURN();
1147
}
1148

    
1149
void op_mfc0_config0 (void)
1150
{
1151
    T0 = env->CP0_Config0;
1152
    RETURN();
1153
}
1154

    
1155
void op_mfc0_config1 (void)
1156
{
1157
    T0 = env->CP0_Config1;
1158
    RETURN();
1159
}
1160

    
1161
void op_mfc0_config2 (void)
1162
{
1163
    T0 = env->CP0_Config2;
1164
    RETURN();
1165
}
1166

    
1167
void op_mfc0_config3 (void)
1168
{
1169
    T0 = env->CP0_Config3;
1170
    RETURN();
1171
}
1172

    
1173
void op_mfc0_config6 (void)
1174
{
1175
    T0 = env->CP0_Config6;
1176
    RETURN();
1177
}
1178

    
1179
void op_mfc0_config7 (void)
1180
{
1181
    T0 = env->CP0_Config7;
1182
    RETURN();
1183
}
1184

    
1185
void op_mfc0_lladdr (void)
1186
{
1187
    T0 = (int32_t)env->CP0_LLAddr >> 4;
1188
    RETURN();
1189
}
1190

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

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

    
1203
void op_mfc0_xcontext (void)
1204
{
1205
    T0 = (int32_t)env->CP0_XContext;
1206
    RETURN();
1207
}
1208

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

    
1215
void op_mfc0_debug (void)
1216
{
1217
    T0 = env->CP0_Debug;
1218
    if (env->hflags & MIPS_HFLAG_DM)
1219
        T0 |= 1 << CP0DB_DM;
1220
    RETURN();
1221
}
1222

    
1223
void op_mfc0_depc (void)
1224
{
1225
    T0 = (int32_t)env->CP0_DEPC;
1226
    RETURN();
1227
}
1228

    
1229
void op_mfc0_performance0 (void)
1230
{
1231
    T0 = env->CP0_Performance0;
1232
    RETURN();
1233
}
1234

    
1235
void op_mfc0_taglo (void)
1236
{
1237
    T0 = env->CP0_TagLo;
1238
    RETURN();
1239
}
1240

    
1241
void op_mfc0_datalo (void)
1242
{
1243
    T0 = env->CP0_DataLo;
1244
    RETURN();
1245
}
1246

    
1247
void op_mfc0_taghi (void)
1248
{
1249
    T0 = env->CP0_TagHi;
1250
    RETURN();
1251
}
1252

    
1253
void op_mfc0_datahi (void)
1254
{
1255
    T0 = env->CP0_DataHi;
1256
    RETURN();
1257
}
1258

    
1259
void op_mfc0_errorepc (void)
1260
{
1261
    T0 = (int32_t)env->CP0_ErrorEPC;
1262
    RETURN();
1263
}
1264

    
1265
void op_mfc0_desave (void)
1266
{
1267
    T0 = env->CP0_DESAVE;
1268
    RETURN();
1269
}
1270

    
1271
void op_mtc0_index (void)
1272
{
1273
    env->CP0_Index = (env->CP0_Index & 0x80000000) | (T0 & (MIPS_TLB_NB - 1));
1274
    RETURN();
1275
}
1276

    
1277
void op_mtc0_entrylo0 (void)
1278
{
1279
    /* Large physaddr not implemented */
1280
    /* 1k pages not implemented */
1281
    env->CP0_EntryLo0 = (int32_t)T0 & 0x3FFFFFFF;
1282
    RETURN();
1283
}
1284

    
1285
void op_mtc0_entrylo1 (void)
1286
{
1287
    /* Large physaddr not implemented */
1288
    /* 1k pages not implemented */
1289
    env->CP0_EntryLo1 = (int32_t)T0 & 0x3FFFFFFF;
1290
    RETURN();
1291
}
1292

    
1293
void op_mtc0_context (void)
1294
{
1295
    env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (T0 & ~0x007FFFFF);
1296
    RETURN();
1297
}
1298

    
1299
void op_mtc0_pagemask (void)
1300
{
1301
    /* 1k pages not implemented */
1302
    env->CP0_PageMask = T0 & 0x1FFFE000;
1303
    RETURN();
1304
}
1305

    
1306
void op_mtc0_pagegrain (void)
1307
{
1308
    /* SmartMIPS not implemented */
1309
    /* Large physaddr not implemented */
1310
    /* 1k pages not implemented */
1311
    env->CP0_PageGrain = 0;
1312
    RETURN();
1313
}
1314

    
1315
void op_mtc0_wired (void)
1316
{
1317
    env->CP0_Wired = T0 & (MIPS_TLB_NB - 1);
1318
    RETURN();
1319
}
1320

    
1321
void op_mtc0_hwrena (void)
1322
{
1323
    env->CP0_HWREna = T0 & 0x0000000F;
1324
    RETURN();
1325
}
1326

    
1327
void op_mtc0_count (void)
1328
{
1329
    CALL_FROM_TB2(cpu_mips_store_count, env, T0);
1330
    RETURN();
1331
}
1332

    
1333
void op_mtc0_entryhi (void)
1334
{
1335
    target_ulong old, val;
1336

    
1337
    /* 1k pages not implemented */
1338
    /* Ignore MIPS64 TLB for now */
1339
    val = (target_ulong)(int32_t)T0 & ~(target_ulong)0x1F00;
1340
    old = env->CP0_EntryHi;
1341
    env->CP0_EntryHi = val;
1342
    /* If the ASID changes, flush qemu's TLB.  */
1343
    if ((old & 0xFF) != (val & 0xFF))
1344
        CALL_FROM_TB2(cpu_mips_tlb_flush, env, 1);
1345
    RETURN();
1346
}
1347

    
1348
void op_mtc0_compare (void)
1349
{
1350
    CALL_FROM_TB2(cpu_mips_store_compare, env, T0);
1351
    RETURN();
1352
}
1353

    
1354
void op_mtc0_status (void)
1355
{
1356
    uint32_t val, old;
1357

    
1358
    /* No 64bit FPU, no reverse endianness, no MDMX/DSP, no 64bit ops,
1359
       no 64bit addressing implemented. */
1360
    val = (int32_t)T0 & 0xF878FF17;
1361
    old = env->CP0_Status;
1362
    if (!(val & (1 << CP0St_EXL)) &&
1363
        !(val & (1 << CP0St_ERL)) &&
1364
        !(env->hflags & MIPS_HFLAG_DM) &&
1365
        (val & (1 << CP0St_UM)))
1366
        env->hflags |= MIPS_HFLAG_UM;
1367
    env->CP0_Status = (env->CP0_Status & ~0xF878FF17) | val;
1368
    if (loglevel & CPU_LOG_EXEC)
1369
        CALL_FROM_TB2(do_mtc0_status_debug, old, val);
1370
    CALL_FROM_TB1(cpu_mips_update_irq, env);
1371
    RETURN();
1372
}
1373

    
1374
void op_mtc0_intctl (void)
1375
{
1376
    /* vectored interrupts not implemented, timer on int 7,
1377
       no performance counters. */
1378
    env->CP0_IntCtl |= T0 & 0x000002e0;
1379
    RETURN();
1380
}
1381

    
1382
void op_mtc0_srsctl (void)
1383
{
1384
    /* shadow registers not implemented */
1385
    env->CP0_SRSCtl = 0;
1386
    RETURN();
1387
}
1388

    
1389
void op_mtc0_srsmap (void)
1390
{
1391
    /* shadow registers not implemented */
1392
    env->CP0_SRSMap = 0;
1393
    RETURN();
1394
}
1395

    
1396
void op_mtc0_cause (void)
1397
{
1398
    uint32_t mask = 0x00C00300;
1399

    
1400
    if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) == (1 << CP0C0_AR))
1401
        mask |= 1 << CP0Ca_DC;
1402

    
1403
    env->CP0_Cause = (env->CP0_Cause & ~mask) | (T0 & mask);
1404

    
1405
    /* Handle the software interrupt as an hardware one, as they
1406
       are very similar */
1407
    if (T0 & CP0Ca_IP_mask) {
1408
        CALL_FROM_TB1(cpu_mips_update_irq, env);
1409
    }
1410
    RETURN();
1411
}
1412

    
1413
void op_mtc0_epc (void)
1414
{
1415
    env->CP0_EPC = (int32_t)T0;
1416
    RETURN();
1417
}
1418

    
1419
void op_mtc0_ebase (void)
1420
{
1421
    /* vectored interrupts not implemented */
1422
    /* Multi-CPU not implemented */
1423
    env->CP0_EBase = 0x80000000 | (T0 & 0x3FFFF000);
1424
    RETURN();
1425
}
1426

    
1427
void op_mtc0_config0 (void)
1428
{
1429
#if defined(MIPS_USES_R4K_TLB)
1430
     /* Fixed mapping MMU not implemented */
1431
    env->CP0_Config0 = (env->CP0_Config0 & 0x8017FF88) | (T0 & 0x00000001);
1432
#else
1433
    env->CP0_Config0 = (env->CP0_Config0 & 0xFE17FF88) | (T0 & 0x00000001);
1434
#endif
1435
    RETURN();
1436
}
1437

    
1438
void op_mtc0_config2 (void)
1439
{
1440
    /* tertiary/secondary caches not implemented */
1441
    env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF);
1442
    RETURN();
1443
}
1444

    
1445
void op_mtc0_watchlo0 (void)
1446
{
1447
    /* Watch exceptions for instructions, data loads, data stores
1448
       not implemented. */
1449
    env->CP0_WatchLo = (int32_t)(T0 & ~0x7);
1450
    RETURN();
1451
}
1452

    
1453
void op_mtc0_watchhi0 (void)
1454
{
1455
    env->CP0_WatchHi = (T0 & 0x40FF0FF8);
1456
    env->CP0_WatchHi &= ~(env->CP0_WatchHi & T0 & 0x7);
1457
    RETURN();
1458
}
1459

    
1460
void op_mtc0_framemask (void)
1461
{
1462
    env->CP0_Framemask = T0; /* XXX */
1463
    RETURN();
1464
}
1465

    
1466
void op_mtc0_debug (void)
1467
{
1468
    env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120);
1469
    if (T0 & (1 << CP0DB_DM))
1470
        env->hflags |= MIPS_HFLAG_DM;
1471
    else
1472
        env->hflags &= ~MIPS_HFLAG_DM;
1473
    RETURN();
1474
}
1475

    
1476
void op_mtc0_depc (void)
1477
{
1478
    env->CP0_DEPC = (int32_t)T0;
1479
    RETURN();
1480
}
1481

    
1482
void op_mtc0_performance0 (void)
1483
{
1484
    env->CP0_Performance0 = T0; /* XXX */
1485
    RETURN();
1486
}
1487

    
1488
void op_mtc0_taglo (void)
1489
{
1490
    env->CP0_TagLo = T0 & 0xFFFFFCF6;
1491
    RETURN();
1492
}
1493

    
1494
void op_mtc0_datalo (void)
1495
{
1496
    env->CP0_DataLo = T0; /* XXX */
1497
    RETURN();
1498
}
1499

    
1500
void op_mtc0_taghi (void)
1501
{
1502
    env->CP0_TagHi = T0; /* XXX */
1503
    RETURN();
1504
}
1505

    
1506
void op_mtc0_datahi (void)
1507
{
1508
    env->CP0_DataHi = T0; /* XXX */
1509
    RETURN();
1510
}
1511

    
1512
void op_mtc0_errorepc (void)
1513
{
1514
    env->CP0_ErrorEPC = (int32_t)T0;
1515
    RETURN();
1516
}
1517

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

    
1524
#ifdef TARGET_MIPS64
1525
void op_dmfc0_entrylo0 (void)
1526
{
1527
    T0 = env->CP0_EntryLo0;
1528
    RETURN();
1529
}
1530

    
1531
void op_dmfc0_entrylo1 (void)
1532
{
1533
    T0 = env->CP0_EntryLo1;
1534
    RETURN();
1535
}
1536

    
1537
void op_dmfc0_context (void)
1538
{
1539
    T0 = env->CP0_Context;
1540
    RETURN();
1541
}
1542

    
1543
void op_dmfc0_badvaddr (void)
1544
{
1545
    T0 = env->CP0_BadVAddr;
1546
    RETURN();
1547
}
1548

    
1549
void op_dmfc0_entryhi (void)
1550
{
1551
    T0 = env->CP0_EntryHi;
1552
    RETURN();
1553
}
1554

    
1555
void op_dmfc0_epc (void)
1556
{
1557
    T0 = env->CP0_EPC;
1558
    RETURN();
1559
}
1560

    
1561
void op_dmfc0_lladdr (void)
1562
{
1563
    T0 = env->CP0_LLAddr >> 4;
1564
    RETURN();
1565
}
1566

    
1567
void op_dmfc0_watchlo0 (void)
1568
{
1569
    T0 = env->CP0_WatchLo;
1570
    RETURN();
1571
}
1572

    
1573
void op_dmfc0_xcontext (void)
1574
{
1575
    T0 = env->CP0_XContext;
1576
    RETURN();
1577
}
1578

    
1579
void op_dmfc0_depc (void)
1580
{
1581
    T0 = env->CP0_DEPC;
1582
    RETURN();
1583
}
1584

    
1585
void op_dmfc0_errorepc (void)
1586
{
1587
    T0 = env->CP0_ErrorEPC;
1588
    RETURN();
1589
}
1590

    
1591
void op_dmtc0_entrylo0 (void)
1592
{
1593
    /* Large physaddr not implemented */
1594
    /* 1k pages not implemented */
1595
    env->CP0_EntryLo0 = T0 & 0x3FFFFFFF;
1596
    RETURN();
1597
}
1598

    
1599
void op_dmtc0_entrylo1 (void)
1600
{
1601
    /* Large physaddr not implemented */
1602
    /* 1k pages not implemented */
1603
    env->CP0_EntryLo1 = T0 & 0x3FFFFFFF;
1604
    RETURN();
1605
}
1606

    
1607
void op_dmtc0_context (void)
1608
{
1609
    env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (T0 & ~0x007FFFFF);
1610
    RETURN();
1611
}
1612

    
1613
void op_dmtc0_epc (void)
1614
{
1615
    env->CP0_EPC = T0;
1616
    RETURN();
1617
}
1618

    
1619
void op_dmtc0_watchlo0 (void)
1620
{
1621
    /* Watch exceptions for instructions, data loads, data stores
1622
       not implemented. */
1623
    env->CP0_WatchLo = T0 & ~0x7;
1624
    RETURN();
1625
}
1626

    
1627
void op_dmtc0_xcontext (void)
1628
{
1629
    env->CP0_XContext = (env->CP0_XContext & 0xffffffff) | (T0 & ~0xffffffff);
1630
    RETURN();
1631
}
1632

    
1633
void op_dmtc0_depc (void)
1634
{
1635
    env->CP0_DEPC = T0;
1636
    RETURN();
1637
}
1638

    
1639
void op_dmtc0_errorepc (void)
1640
{
1641
    env->CP0_ErrorEPC = T0;
1642
    RETURN();
1643
}
1644
#endif /* TARGET_MIPS64 */
1645

    
1646
#if 0
1647
# define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env)
1648
#else
1649
# define DEBUG_FPU_STATE() do { } while(0)
1650
#endif
1651

    
1652
void op_cp0_enabled(void)
1653
{
1654
    if (!(env->CP0_Status & (1 << CP0St_CU0)) &&
1655
        (env->hflags & MIPS_HFLAG_UM)) {
1656
        CALL_FROM_TB2(do_raise_exception_err, EXCP_CpU, 0);
1657
    }
1658
    RETURN();
1659
}
1660

    
1661
void op_cp1_enabled(void)
1662
{
1663
    if (!(env->CP0_Status & (1 << CP0St_CU1))) {
1664
        CALL_FROM_TB2(do_raise_exception_err, EXCP_CpU, 1);
1665
    }
1666
    RETURN();
1667
}
1668

    
1669
/* CP1 functions */
1670
void op_cfc1 (void)
1671
{
1672
    if (T1 == 0) {
1673
        T0 = env->fcr0;
1674
    }
1675
    else {
1676
        /* fetch fcr31, masking unused bits */
1677
        T0 = env->fcr31 & 0x0183FFFF;
1678
    }
1679
    DEBUG_FPU_STATE();
1680
    RETURN();
1681
}
1682

    
1683
/* convert MIPS rounding mode in FCR31 to IEEE library */
1684
unsigned int ieee_rm[] = { 
1685
    float_round_nearest_even,
1686
    float_round_to_zero,
1687
    float_round_up,
1688
    float_round_down
1689
};
1690

    
1691
#define RESTORE_ROUNDING_MODE \
1692
    set_float_rounding_mode(ieee_rm[env->fcr31 & 3], &env->fp_status)
1693

    
1694
void op_ctc1 (void)
1695
{
1696
    if (T1 == 0) {
1697
        /* XXX should this throw an exception?
1698
         * don't write to FCR0.
1699
         * env->fcr0 = T0; 
1700
         */
1701
    }
1702
    else {
1703
        /* store new fcr31, masking unused bits */  
1704
        env->fcr31 = T0 & 0x0183FFFF;
1705

    
1706
        /* set rounding mode */
1707
        RESTORE_ROUNDING_MODE;
1708

    
1709
#ifndef CONFIG_SOFTFLOAT
1710
        /* no floating point exception for native float */
1711
        SET_FP_ENABLE(env->fcr31, 0);
1712
#endif
1713
    }
1714
    DEBUG_FPU_STATE();
1715
    RETURN();
1716
}
1717

    
1718
void op_mfc1 (void)
1719
{
1720
    T0 = WT0;
1721
    DEBUG_FPU_STATE();
1722
    RETURN();
1723
}
1724

    
1725
void op_mtc1 (void)
1726
{
1727
    WT0 = T0;
1728
    DEBUG_FPU_STATE();
1729
    RETURN();
1730
}
1731

    
1732
/* Float support.
1733
   Single precition routines have a "s" suffix, double precision a
1734
   "d" suffix.  */
1735

    
1736
#define FLOAT_OP(name, p) void OPPROTO op_float_##name##_##p(void)
1737

    
1738
FLOAT_OP(cvtd, s)
1739
{
1740
    FDT2 = float32_to_float64(FST0, &env->fp_status);
1741
    DEBUG_FPU_STATE();
1742
    RETURN();
1743
}
1744
FLOAT_OP(cvtd, w)
1745
{
1746
    FDT2 = int32_to_float64(WT0, &env->fp_status);
1747
    DEBUG_FPU_STATE();
1748
    RETURN();
1749
}
1750
FLOAT_OP(cvts, d)
1751
{
1752
    FST2 = float64_to_float32(FDT0, &env->fp_status);
1753
    DEBUG_FPU_STATE();
1754
    RETURN();
1755
}
1756
FLOAT_OP(cvts, w)
1757
{
1758
    FST2 = int32_to_float32(WT0, &env->fp_status);
1759
    DEBUG_FPU_STATE();
1760
    RETURN();
1761
}
1762
FLOAT_OP(cvtw, s)
1763
{
1764
    WT2 = float32_to_int32(FST0, &env->fp_status);
1765
    DEBUG_FPU_STATE();
1766
    RETURN();
1767
}
1768
FLOAT_OP(cvtw, d)
1769
{
1770
    WT2 = float64_to_int32(FDT0, &env->fp_status);
1771
    DEBUG_FPU_STATE();
1772
    RETURN();
1773
}
1774

    
1775
FLOAT_OP(roundw, d)
1776
{
1777
    set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
1778
    WT2 = float64_round_to_int(FDT0, &env->fp_status);
1779
    RESTORE_ROUNDING_MODE;
1780

    
1781
    DEBUG_FPU_STATE();
1782
    RETURN();
1783
}
1784
FLOAT_OP(roundw, s)
1785
{
1786
    set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
1787
    WT2 = float32_round_to_int(FST0, &env->fp_status);
1788
    RESTORE_ROUNDING_MODE;
1789
    DEBUG_FPU_STATE();
1790
    RETURN();
1791
}
1792

    
1793
FLOAT_OP(truncw, d)
1794
{
1795
    WT2 = float64_to_int32_round_to_zero(FDT0, &env->fp_status);
1796
    DEBUG_FPU_STATE();
1797
    RETURN();
1798
}
1799
FLOAT_OP(truncw, s)
1800
{
1801
    WT2 = float32_to_int32_round_to_zero(FST0, &env->fp_status);
1802
    DEBUG_FPU_STATE();
1803
    RETURN();
1804
}
1805

    
1806
FLOAT_OP(ceilw, d)
1807
{
1808
    set_float_rounding_mode(float_round_up, &env->fp_status);
1809
    WT2 = float64_round_to_int(FDT0, &env->fp_status);
1810
    RESTORE_ROUNDING_MODE;
1811

    
1812
    DEBUG_FPU_STATE();
1813
    RETURN();
1814
}
1815
FLOAT_OP(ceilw, s)
1816
{
1817
    set_float_rounding_mode(float_round_up, &env->fp_status);
1818
    WT2 = float32_round_to_int(FST0, &env->fp_status);
1819
    RESTORE_ROUNDING_MODE;
1820
    DEBUG_FPU_STATE();
1821
    RETURN();
1822
}
1823

    
1824
FLOAT_OP(floorw, d)
1825
{
1826
    set_float_rounding_mode(float_round_down, &env->fp_status);
1827
    WT2 = float64_round_to_int(FDT0, &env->fp_status);
1828
    RESTORE_ROUNDING_MODE;
1829

    
1830
    DEBUG_FPU_STATE();
1831
    RETURN();
1832
}
1833
FLOAT_OP(floorw, s)
1834
{
1835
    set_float_rounding_mode(float_round_down, &env->fp_status);
1836
    WT2 = float32_round_to_int(FST0, &env->fp_status);
1837
    RESTORE_ROUNDING_MODE;
1838
    DEBUG_FPU_STATE();
1839
    RETURN();
1840
}
1841

    
1842
/* binary operations */
1843
#define FLOAT_BINOP(name) \
1844
FLOAT_OP(name, d)         \
1845
{                         \
1846
    FDT2 = float64_ ## name (FDT0, FDT1, &env->fp_status);    \
1847
    DEBUG_FPU_STATE();    \
1848
}                         \
1849
FLOAT_OP(name, s)         \
1850
{                         \
1851
    FST2 = float32_ ## name (FST0, FST1, &env->fp_status);    \
1852
    DEBUG_FPU_STATE();    \
1853
}
1854
FLOAT_BINOP(add)
1855
FLOAT_BINOP(sub)
1856
FLOAT_BINOP(mul)
1857
FLOAT_BINOP(div)
1858
#undef FLOAT_BINOP
1859

    
1860
/* unary operations, modifying fp status  */
1861
#define FLOAT_UNOP(name)  \
1862
FLOAT_OP(name, d)         \
1863
{                         \
1864
    FDT2 = float64_ ## name(FDT0, &env->fp_status);   \
1865
    DEBUG_FPU_STATE();    \
1866
}                         \
1867
FLOAT_OP(name, s)         \
1868
{                         \
1869
    FST2 = float32_ ## name(FST0, &env->fp_status);   \
1870
    DEBUG_FPU_STATE();    \
1871
}
1872
FLOAT_UNOP(sqrt)
1873
#undef FLOAT_UNOP
1874

    
1875
/* unary operations, not modifying fp status  */
1876
#define FLOAT_UNOP(name)  \
1877
FLOAT_OP(name, d)         \
1878
{                         \
1879
    FDT2 = float64_ ## name(FDT0);   \
1880
    DEBUG_FPU_STATE();    \
1881
}                         \
1882
FLOAT_OP(name, s)         \
1883
{                         \
1884
    FST2 = float32_ ## name(FST0);   \
1885
    DEBUG_FPU_STATE();    \
1886
}
1887
FLOAT_UNOP(abs)
1888
FLOAT_UNOP(chs)
1889
#undef FLOAT_UNOP
1890

    
1891
FLOAT_OP(mov, d)
1892
{
1893
    FDT2 = FDT0;
1894
    DEBUG_FPU_STATE();
1895
    RETURN();
1896
}
1897
FLOAT_OP(mov, s)
1898
{
1899
    FST2 = FST0;
1900
    DEBUG_FPU_STATE();
1901
    RETURN();
1902
}
1903

    
1904
#ifdef CONFIG_SOFTFLOAT
1905
#define clear_invalid() do {                                \
1906
    int flags = get_float_exception_flags(&env->fp_status); \
1907
    flags &= ~float_flag_invalid;                           \
1908
    set_float_exception_flags(flags, &env->fp_status);      \
1909
} while(0)
1910
#else
1911
#define clear_invalid() do { } while(0)
1912
#endif
1913

    
1914
extern void dump_fpu_s(CPUState *env);
1915

    
1916
#define FOP_COND(fmt, op, sig, cond)           \
1917
void op_cmp_ ## fmt ## _ ## op (void)          \
1918
{                                              \
1919
    if (cond)                                  \
1920
        SET_FP_COND(env->fcr31);               \
1921
    else                                       \
1922
        CLEAR_FP_COND(env->fcr31);             \
1923
    if (!sig)                                  \
1924
        clear_invalid();                       \
1925
    /*CALL_FROM_TB1(dump_fpu_s, env);*/ \
1926
    DEBUG_FPU_STATE();                         \
1927
    RETURN();                                  \
1928
}
1929

    
1930
int float64_is_unordered(float64 a, float64 b STATUS_PARAM)
1931
{
1932
    if (float64_is_nan(a) || float64_is_nan(b)) {
1933
        float_raise(float_flag_invalid, status);
1934
        return 1;
1935
    }
1936
    else {
1937
        return 0;
1938
    }
1939
}
1940

    
1941
FOP_COND(d, f,   0,                                                      0) 
1942
FOP_COND(d, un,  0, float64_is_unordered(FDT1, FDT0, &env->fp_status))
1943
FOP_COND(d, eq,  0,                                                      float64_eq(FDT0, FDT1, &env->fp_status))
1944
FOP_COND(d, ueq, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status))
1945
FOP_COND(d, olt, 0,                                                      float64_lt(FDT0, FDT1, &env->fp_status))
1946
FOP_COND(d, ult, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status))
1947
FOP_COND(d, ole, 0,                                                      float64_le(FDT0, FDT1, &env->fp_status))
1948
FOP_COND(d, ule, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status))
1949
/* NOTE: the comma operator will make "cond" to eval to false,
1950
 * but float*_is_unordered() is still called
1951
 */
1952
FOP_COND(d, sf,  1,                                                      (float64_is_unordered(FDT0, FDT1, &env->fp_status), 0))
1953
FOP_COND(d, ngle,1, float64_is_unordered(FDT1, FDT0, &env->fp_status))
1954
FOP_COND(d, seq, 1,                                                      float64_eq(FDT0, FDT1, &env->fp_status))
1955
FOP_COND(d, ngl, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status))
1956
FOP_COND(d, lt,  1,                                                      float64_lt(FDT0, FDT1, &env->fp_status))
1957
FOP_COND(d, nge, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status))
1958
FOP_COND(d, le,  1,                                                      float64_le(FDT0, FDT1, &env->fp_status))
1959
FOP_COND(d, ngt, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status))
1960

    
1961
flag float32_is_unordered(float32 a, float32 b STATUS_PARAM)
1962
{
1963
    extern flag float32_is_nan( float32 a );
1964
    if (float32_is_nan(a) || float32_is_nan(b)) {
1965
        float_raise(float_flag_invalid, status);
1966
        return 1;
1967
    }
1968
    else {
1969
        return 0;
1970
    }
1971
}
1972

    
1973
/* NOTE: the comma operator will make "cond" to eval to false,
1974
 * but float*_is_unordered() is still called
1975
 */
1976
FOP_COND(s, f,   0,                                                      0) 
1977
FOP_COND(s, un,  0, float32_is_unordered(FST1, FST0, &env->fp_status))
1978
FOP_COND(s, eq,  0,                                                      float32_eq(FST0, FST1, &env->fp_status))
1979
FOP_COND(s, ueq, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status))
1980
FOP_COND(s, olt, 0,                                                      float32_lt(FST0, FST1, &env->fp_status))
1981
FOP_COND(s, ult, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status))
1982
FOP_COND(s, ole, 0,                                                      float32_le(FST0, FST1, &env->fp_status))
1983
FOP_COND(s, ule, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status))
1984
/* NOTE: the comma operator will make "cond" to eval to false,
1985
 * but float*_is_unordered() is still called
1986
 */
1987
FOP_COND(s, sf,  1,                                                      (float32_is_unordered(FST0, FST1, &env->fp_status), 0))
1988
FOP_COND(s, ngle,1, float32_is_unordered(FST1, FST0, &env->fp_status))
1989
FOP_COND(s, seq, 1,                                                      float32_eq(FST0, FST1, &env->fp_status))
1990
FOP_COND(s, ngl, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status))
1991
FOP_COND(s, lt,  1,                                                      float32_lt(FST0, FST1, &env->fp_status))
1992
FOP_COND(s, nge, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status))
1993
FOP_COND(s, le,  1,                                                      float32_le(FST0, FST1, &env->fp_status))
1994
FOP_COND(s, ngt, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status))
1995

    
1996
void op_bc1f (void)
1997
{
1998
    T0 = ! IS_FP_COND_SET(env->fcr31);
1999
    DEBUG_FPU_STATE();
2000
    RETURN();
2001
}
2002

    
2003
void op_bc1t (void)
2004
{
2005
    T0 = IS_FP_COND_SET(env->fcr31);
2006
    DEBUG_FPU_STATE();
2007
    RETURN();
2008
}
2009

    
2010
#if defined(MIPS_USES_R4K_TLB)
2011
void op_tlbwi (void)
2012
{
2013
    CALL_FROM_TB0(do_tlbwi);
2014
    RETURN();
2015
}
2016

    
2017
void op_tlbwr (void)
2018
{
2019
    CALL_FROM_TB0(do_tlbwr);
2020
    RETURN();
2021
}
2022

    
2023
void op_tlbp (void)
2024
{
2025
    CALL_FROM_TB0(do_tlbp);
2026
    RETURN();
2027
}
2028

    
2029
void op_tlbr (void)
2030
{
2031
    CALL_FROM_TB0(do_tlbr);
2032
    RETURN();
2033
}
2034
#endif
2035

    
2036
/* Specials */
2037
#if defined (CONFIG_USER_ONLY)
2038
void op_tls_value (void)
2039
{
2040
  T0 = env->tls_value;
2041
}
2042
#endif
2043

    
2044
void op_pmon (void)
2045
{
2046
    CALL_FROM_TB1(do_pmon, PARAM1);
2047
    RETURN();
2048
}
2049

    
2050
void op_di (void)
2051
{
2052
    T0 = env->CP0_Status;
2053
    env->CP0_Status = T0 & ~(1 << CP0St_IE);
2054
    CALL_FROM_TB1(cpu_mips_update_irq, env);
2055
    RETURN();
2056
}
2057

    
2058
void op_ei (void)
2059
{
2060
    T0 = env->CP0_Status;
2061
    env->CP0_Status = T0 | (1 << CP0St_IE);
2062
    CALL_FROM_TB1(cpu_mips_update_irq, env);
2063
    RETURN();
2064
}
2065

    
2066
void op_trap (void)
2067
{
2068
    if (T0) {
2069
        CALL_FROM_TB1(do_raise_exception, EXCP_TRAP);
2070
    }
2071
    RETURN();
2072
}
2073

    
2074
void op_debug (void)
2075
{
2076
    CALL_FROM_TB1(do_raise_exception, EXCP_DEBUG);
2077
    RETURN();
2078
}
2079

    
2080
void op_set_lladdr (void)
2081
{
2082
    env->CP0_LLAddr = T2;
2083
    RETURN();
2084
}
2085

    
2086
void debug_pre_eret (void);
2087
void debug_post_eret (void);
2088
void op_eret (void)
2089
{
2090
    if (loglevel & CPU_LOG_EXEC)
2091
        CALL_FROM_TB0(debug_pre_eret);
2092
    if (env->CP0_Status & (1 << CP0St_ERL)) {
2093
        env->PC = env->CP0_ErrorEPC;
2094
        env->CP0_Status &= ~(1 << CP0St_ERL);
2095
    } else {
2096
        env->PC = env->CP0_EPC;
2097
        env->CP0_Status &= ~(1 << CP0St_EXL);
2098
    }
2099
    if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
2100
        !(env->CP0_Status & (1 << CP0St_ERL)) &&
2101
        !(env->hflags & MIPS_HFLAG_DM) &&
2102
        (env->CP0_Status & (1 << CP0St_UM)))
2103
        env->hflags |= MIPS_HFLAG_UM;
2104
    if (loglevel & CPU_LOG_EXEC)
2105
        CALL_FROM_TB0(debug_post_eret);
2106
    env->CP0_LLAddr = 1;
2107
    RETURN();
2108
}
2109

    
2110
void op_deret (void)
2111
{
2112
    if (loglevel & CPU_LOG_EXEC)
2113
        CALL_FROM_TB0(debug_pre_eret);
2114
    env->PC = env->CP0_DEPC;
2115
    env->hflags |= MIPS_HFLAG_DM;
2116
    if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
2117
        !(env->CP0_Status & (1 << CP0St_ERL)) &&
2118
        !(env->hflags & MIPS_HFLAG_DM) &&
2119
        (env->CP0_Status & (1 << CP0St_UM)))
2120
        env->hflags |= MIPS_HFLAG_UM;
2121
    if (loglevel & CPU_LOG_EXEC)
2122
        CALL_FROM_TB0(debug_post_eret);
2123
    env->CP0_LLAddr = 1;
2124
    RETURN();
2125
}
2126

    
2127
void op_rdhwr_cpunum(void)
2128
{
2129
    if (!(env->hflags & MIPS_HFLAG_UM) ||
2130
        (env->CP0_HWREna & (1 << 0)) ||
2131
        (env->CP0_Status & (1 << CP0St_CU0)))
2132
        T0 = env->CP0_EBase & 0x3ff;
2133
    else
2134
        CALL_FROM_TB1(do_raise_exception, EXCP_RI);
2135
    RETURN();
2136
}
2137

    
2138
void op_rdhwr_synci_step(void)
2139
{
2140
    if (!(env->hflags & MIPS_HFLAG_UM) ||
2141
        (env->CP0_HWREna & (1 << 1)) ||
2142
        (env->CP0_Status & (1 << CP0St_CU0)))
2143
        T0 = env->SYNCI_Step;
2144
    else
2145
        CALL_FROM_TB1(do_raise_exception, EXCP_RI);
2146
    RETURN();
2147
}
2148

    
2149
void op_rdhwr_cc(void)
2150
{
2151
    if (!(env->hflags & MIPS_HFLAG_UM) ||
2152
        (env->CP0_HWREna & (1 << 2)) ||
2153
        (env->CP0_Status & (1 << CP0St_CU0)))
2154
        T0 = env->CP0_Count;
2155
    else
2156
        CALL_FROM_TB1(do_raise_exception, EXCP_RI);
2157
    RETURN();
2158
}
2159

    
2160
void op_rdhwr_ccres(void)
2161
{
2162
    if (!(env->hflags & MIPS_HFLAG_UM) ||
2163
        (env->CP0_HWREna & (1 << 3)) ||
2164
        (env->CP0_Status & (1 << CP0St_CU0)))
2165
        T0 = env->CCRes;
2166
    else
2167
        CALL_FROM_TB1(do_raise_exception, EXCP_RI);
2168
    RETURN();
2169
}
2170

    
2171
void op_save_state (void)
2172
{
2173
    env->hflags = PARAM1;
2174
    RETURN();
2175
}
2176

    
2177
void op_save_pc (void)
2178
{
2179
    env->PC = PARAM1;
2180
    RETURN();
2181
}
2182

    
2183
void op_interrupt_restart (void)
2184
{
2185
    if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
2186
        !(env->CP0_Status & (1 << CP0St_ERL)) &&
2187
        !(env->hflags & MIPS_HFLAG_DM) &&
2188
        (env->CP0_Status & (1 << CP0St_IE)) &&
2189
        (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask)) {
2190
        env->CP0_Cause &= ~(0x1f << CP0Ca_EC);
2191
        CALL_FROM_TB1(do_raise_exception, EXCP_EXT_INTERRUPT);
2192
    }
2193
    RETURN();
2194
}
2195

    
2196
void op_raise_exception (void)
2197
{
2198
    CALL_FROM_TB1(do_raise_exception, PARAM1);
2199
    RETURN();
2200
}
2201

    
2202
void op_raise_exception_err (void)
2203
{
2204
    CALL_FROM_TB2(do_raise_exception_err, PARAM1, PARAM2);
2205
    RETURN();
2206
}
2207

    
2208
void op_exit_tb (void)
2209
{
2210
    EXIT_TB();
2211
    RETURN();
2212
}
2213

    
2214
void op_wait (void)
2215
{
2216
    env->halted = 1;
2217
    CALL_FROM_TB1(do_raise_exception, EXCP_HLT);
2218
    RETURN();
2219
}
2220

    
2221
/* Bitfield operations. */
2222
void op_ext(void)
2223
{
2224
    unsigned int pos = PARAM1;
2225
    unsigned int size = PARAM2;
2226

    
2227
    T0 = ((uint32_t)T1 >> pos) & ((size < 32) ? ((1 << size) - 1) : ~0);
2228
    RETURN();
2229
}
2230

    
2231
void op_ins(void)
2232
{
2233
    unsigned int pos = PARAM1;
2234
    unsigned int size = PARAM2;
2235
    target_ulong mask = ((size < 32) ? ((1 << size) - 1) : ~0) << pos;
2236

    
2237
    T0 = (T0 & ~mask) | (((uint32_t)T1 << pos) & mask);
2238
    RETURN();
2239
}
2240

    
2241
void op_wsbh(void)
2242
{
2243
    T0 = ((T1 << 8) & ~0x00FF00FF) | ((T1 >> 8) & 0x00FF00FF);
2244
    RETURN();
2245
}
2246

    
2247
#ifdef TARGET_MIPS64
2248
void op_dext(void)
2249
{
2250
    unsigned int pos = PARAM1;
2251
    unsigned int size = PARAM2;
2252

    
2253
    T0 = (T1 >> pos) & ((size < 32) ? ((1 << size) - 1) : ~0);
2254
    RETURN();
2255
}
2256

    
2257
void op_dins(void)
2258
{
2259
    unsigned int pos = PARAM1;
2260
    unsigned int size = PARAM2;
2261
    target_ulong mask = ((size < 32) ? ((1 << size) - 1) : ~0) << pos;
2262

    
2263
    T0 = (T0 & ~mask) | ((T1 << pos) & mask);
2264
    RETURN();
2265
}
2266

    
2267
void op_dsbh(void)
2268
{
2269
    T0 = ((T1 << 8) & ~0x00FF00FF00FF00FFULL) | ((T1 >> 8) & 0x00FF00FF00FF00FFULL);
2270
    RETURN();
2271
}
2272

    
2273
void op_dshd(void)
2274
{
2275
    T0 = ((T1 << 16) & ~0x0000FFFF0000FFFFULL) | ((T1 >> 16) & 0x0000FFFF0000FFFFULL);
2276
    RETURN();
2277
}
2278
#endif
2279

    
2280
void op_seb(void)
2281
{
2282
    T0 = ((T1 & 0xFF) ^ 0x80) - 0x80;
2283
    RETURN();
2284
}
2285

    
2286
void op_seh(void)
2287
{
2288
    T0 = ((T1 & 0xFFFF) ^ 0x8000) - 0x8000;
2289
    RETURN();
2290
}