Statistics
| Branch: | Revision:

root / target-mips / op.c @ f41c52f1

History | View | Annotate | Download (41.9 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
void op_div (void)
372
{
373
    if (T1 != 0) {
374
        env->LO = (int32_t)((int32_t)T0 / (int32_t)T1);
375
        env->HI = (int32_t)((int32_t)T0 % (int32_t)T1);
376
    }
377
    RETURN();
378
}
379

    
380
void op_divu (void)
381
{
382
    if (T1 != 0) {
383
        env->LO = (int32_t)((uint32_t)T0 / (uint32_t)T1);
384
        env->HI = (int32_t)((uint32_t)T0 % (uint32_t)T1);
385
    }
386
    RETURN();
387
}
388

    
389
#ifdef TARGET_MIPS64
390
/* Arithmetic */
391
void op_dadd (void)
392
{
393
    T0 += T1;
394
    RETURN();
395
}
396

    
397
void op_daddo (void)
398
{
399
    target_long tmp;
400

    
401
    tmp = T0;
402
    T0 += T1;
403
    if (((tmp ^ T1 ^ (-1)) & (T0 ^ T1)) >> 63) {
404
        /* operands of same sign, result different sign */
405
        CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
406
    }
407
    RETURN();
408
}
409

    
410
void op_dsub (void)
411
{
412
    T0 -= T1;
413
    RETURN();
414
}
415

    
416
void op_dsubo (void)
417
{
418
    target_long tmp;
419

    
420
    tmp = T0;
421
    T0 = (int64_t)T0 - (int64_t)T1;
422
    if (((tmp ^ T1) & (tmp ^ T0)) >> 63) {
423
        /* operands of different sign, first operand and result different sign */
424
        CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
425
    }
426
    RETURN();
427
}
428

    
429
void op_dmul (void)
430
{
431
    T0 = (int64_t)T0 * (int64_t)T1;
432
    RETURN();
433
}
434

    
435
#if TARGET_LONG_BITS > HOST_LONG_BITS
436
/* Those might call libgcc functions.  */
437
void op_ddiv (void)
438
{
439
    do_ddiv();
440
    RETURN();
441
}
442

    
443
void op_ddivu (void)
444
{
445
    do_ddivu();
446
    RETURN();
447
}
448
#else
449
void op_ddiv (void)
450
{
451
    if (T1 != 0) {
452
        env->LO = (int64_t)T0 / (int64_t)T1;
453
        env->HI = (int64_t)T0 % (int64_t)T1;
454
    }
455
    RETURN();
456
}
457

    
458
void op_ddivu (void)
459
{
460
    if (T1 != 0) {
461
        env->LO = T0 / T1;
462
        env->HI = T0 % T1;
463
    }
464
    RETURN();
465
}
466
#endif
467
#endif /* TARGET_MIPS64 */
468

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
588
#ifdef TARGET_MIPS64
589

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

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

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

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

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

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

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

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

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

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

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

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

    
664
#else /* TARGET_LONG_BITS > HOST_LONG_BITS */
665

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
829
#else /* TARGET_LONG_BITS > HOST_LONG_BITS */
830

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1375
void op_mtc0_intctl (void)
1376
{
1377
    /* vectored interrupts not implemented */
1378
    env->CP0_IntCtl = 0;
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 & 0xFCC0FF7C) | (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
    env->CP0_WatchLo = (int32_t)T0;
1448
    RETURN();
1449
}
1450

    
1451
void op_mtc0_watchhi0 (void)
1452
{
1453
    env->CP0_WatchHi = T0 & 0x40FF0FF8;
1454
    RETURN();
1455
}
1456

    
1457
void op_mtc0_xcontext (void)
1458
{
1459
    env->CP0_XContext = (int32_t)T0; /* XXX */
1460
    RETURN();
1461
}
1462

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

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

    
1479
void op_mtc0_depc (void)
1480
{
1481
    env->CP0_DEPC = (int32_t)T0;
1482
    RETURN();
1483
}
1484

    
1485
void op_mtc0_performance0 (void)
1486
{
1487
    env->CP0_Performance0 = T0; /* XXX */
1488
    RETURN();
1489
}
1490

    
1491
void op_mtc0_taglo (void)
1492
{
1493
    env->CP0_TagLo = T0 & 0xFFFFFCF6;
1494
    RETURN();
1495
}
1496

    
1497
void op_mtc0_datalo (void)
1498
{
1499
    env->CP0_DataLo = T0; /* XXX */
1500
    RETURN();
1501
}
1502

    
1503
void op_mtc0_taghi (void)
1504
{
1505
    env->CP0_TagHi = T0; /* XXX */
1506
    RETURN();
1507
}
1508

    
1509
void op_mtc0_datahi (void)
1510
{
1511
    env->CP0_DataHi = T0; /* XXX */
1512
    RETURN();
1513
}
1514

    
1515
void op_mtc0_errorepc (void)
1516
{
1517
    env->CP0_ErrorEPC = (int32_t)T0;
1518
    RETURN();
1519
}
1520

    
1521
void op_mtc0_desave (void)
1522
{
1523
    env->CP0_DESAVE = T0;
1524
    RETURN();
1525
}
1526

    
1527
void op_dmfc0_entrylo0 (void)
1528
{
1529
    T0 = env->CP0_EntryLo0;
1530
    RETURN();
1531
}
1532

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1621
void op_dmtc0_watchlo0 (void)
1622
{
1623
    env->CP0_WatchLo = T0;
1624
    RETURN();
1625
}
1626

    
1627
void op_dmtc0_xcontext (void)
1628
{
1629
    env->CP0_XContext = T0; /* XXX */
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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1913
extern void dump_fpu_s(CPUState *env);
1914

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2170
void op_rdhwr_unimpl30(void)
2171
{
2172
    if (!(env->hflags & MIPS_HFLAG_UM) ||
2173
        (env->CP0_HWREna & (1 << 30)) ||
2174
        (env->CP0_Status & (1 << CP0St_CU0)))
2175
        T0 = 0;
2176
    else
2177
        CALL_FROM_TB1(do_raise_exception, EXCP_RI);
2178
    RETURN();
2179
}
2180

    
2181
void op_rdhwr_unimpl31(void)
2182
{
2183
    if (!(env->hflags & MIPS_HFLAG_UM) ||
2184
        (env->CP0_HWREna & (1 << 31)) ||
2185
        (env->CP0_Status & (1 << CP0St_CU0)))
2186
        T0 = 0;
2187
    else
2188
        CALL_FROM_TB1(do_raise_exception, EXCP_RI);
2189
    RETURN();
2190
}
2191

    
2192
void op_save_state (void)
2193
{
2194
    env->hflags = PARAM1;
2195
    RETURN();
2196
}
2197

    
2198
void op_save_pc (void)
2199
{
2200
    env->PC = PARAM1;
2201
    RETURN();
2202
}
2203

    
2204
void op_raise_exception (void)
2205
{
2206
    CALL_FROM_TB1(do_raise_exception, PARAM1);
2207
    RETURN();
2208
}
2209

    
2210
void op_raise_exception_err (void)
2211
{
2212
    CALL_FROM_TB2(do_raise_exception_err, PARAM1, PARAM2);
2213
    RETURN();
2214
}
2215

    
2216
void op_exit_tb (void)
2217
{
2218
    EXIT_TB();
2219
    RETURN();
2220
}
2221

    
2222
void op_wait (void)
2223
{
2224
    env->halted = 1;
2225
    CALL_FROM_TB1(do_raise_exception, EXCP_HLT);
2226
    RETURN();
2227
}
2228

    
2229
/* Bitfield operations. */
2230
void op_ext(void)
2231
{
2232
    unsigned int pos = PARAM1;
2233
    unsigned int size = PARAM2;
2234

    
2235
    T0 = ((uint32_t)T1 >> pos) & ((1 << size) - 1);
2236
    RETURN();
2237
}
2238

    
2239
void op_ins(void)
2240
{
2241
    unsigned int pos = PARAM1;
2242
    unsigned int size = PARAM2;
2243
    target_ulong mask = ((1 << size) - 1) << pos;
2244

    
2245
    T0 = (T2 & ~mask) | (((uint32_t)T1 << pos) & mask);
2246
    RETURN();
2247
}
2248

    
2249
void op_wsbh(void)
2250
{
2251
    T0 = ((T1 << 8) & ~0x00FF00FF) | ((T1 >> 8) & 0x00FF00FF);
2252
    RETURN();
2253
}
2254

    
2255
#ifdef TARGET_MIPS64
2256
void op_dext(void)
2257
{
2258
    unsigned int pos = PARAM1;
2259
    unsigned int size = PARAM2;
2260

    
2261
    T0 = (T1 >> pos) & ((1 << size) - 1);
2262
    RETURN();
2263
}
2264

    
2265
void op_dins(void)
2266
{
2267
    unsigned int pos = PARAM1;
2268
    unsigned int size = PARAM2;
2269
    target_ulong mask = ((1 << size) - 1) << pos;
2270

    
2271
    T0 = (T2 & ~mask) | ((T1 << pos) & mask);
2272
    RETURN();
2273
}
2274

    
2275
void op_dsbh(void)
2276
{
2277
    T0 = ((T1 << 8) & ~0x00FF00FF00FF00FFULL) | ((T1 >> 8) & 0x00FF00FF00FF00FFULL);
2278
    RETURN();
2279
}
2280

    
2281
void op_dshd(void)
2282
{
2283
    T0 = ((T1 << 16) & ~0x0000FFFF0000FFFFULL) | ((T1 >> 16) & 0x0000FFFF0000FFFFULL);
2284
    RETURN();
2285
}
2286
#endif
2287

    
2288
void op_seb(void)
2289
{
2290
    T0 = ((T1 & 0xFF) ^ 0x80) - 0x80;
2291
    RETURN();
2292
}
2293

    
2294
void op_seh(void)
2295
{
2296
    T0 = ((T1 & 0xFFFF) ^ 0x8000) - 0x8000;
2297
    RETURN();
2298
}