Statistics
| Branch: | Revision:

root / target-mips / op.c @ c090a8f4

History | View | Annotate | Download (41.8 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 & ~0x007FFFFF);
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, timer on int 7,
1378
       no performance counters. */
1379
    env->CP0_IntCtl |= T0 & 0x000002e0;
1380
    RETURN();
1381
}
1382

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

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

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

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

    
1404
    env->CP0_Cause = (env->CP0_Cause & 0xFCC0FF7C) | (T0 & mask);
1405

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

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

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

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

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

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

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

    
1461
void op_mtc0_xcontext (void)
1462
{
1463
    env->CP0_XContext = (int32_t)T0; /* XXX */
1464
    RETURN();
1465
}
1466

    
1467
void op_mtc0_framemask (void)
1468
{
1469
    env->CP0_Framemask = T0; /* XXX */
1470
    RETURN();
1471
}
1472

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

    
1483
void op_mtc0_depc (void)
1484
{
1485
    env->CP0_DEPC = (int32_t)T0;
1486
    RETURN();
1487
}
1488

    
1489
void op_mtc0_performance0 (void)
1490
{
1491
    env->CP0_Performance0 = T0; /* XXX */
1492
    RETURN();
1493
}
1494

    
1495
void op_mtc0_taglo (void)
1496
{
1497
    env->CP0_TagLo = T0 & 0xFFFFFCF6;
1498
    RETURN();
1499
}
1500

    
1501
void op_mtc0_datalo (void)
1502
{
1503
    env->CP0_DataLo = T0; /* XXX */
1504
    RETURN();
1505
}
1506

    
1507
void op_mtc0_taghi (void)
1508
{
1509
    env->CP0_TagHi = T0; /* XXX */
1510
    RETURN();
1511
}
1512

    
1513
void op_mtc0_datahi (void)
1514
{
1515
    env->CP0_DataHi = T0; /* XXX */
1516
    RETURN();
1517
}
1518

    
1519
void op_mtc0_errorepc (void)
1520
{
1521
    env->CP0_ErrorEPC = (int32_t)T0;
1522
    RETURN();
1523
}
1524

    
1525
void op_mtc0_desave (void)
1526
{
1527
    env->CP0_DESAVE = T0;
1528
    RETURN();
1529
}
1530

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

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

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

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

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

    
1561
void op_dmfc0_epc (void)
1562
{
1563
    T0 = env->CP0_EPC;
1564
    RETURN();
1565
}
1566

    
1567
void op_dmfc0_lladdr (void)
1568
{
1569
    T0 = env->CP0_LLAddr >> 4;
1570
    RETURN();
1571
}
1572

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

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

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

    
1591
void op_dmfc0_errorepc (void)
1592
{
1593
    T0 = env->CP0_ErrorEPC;
1594
    RETURN();
1595
}
1596

    
1597
void op_dmtc0_entrylo0 (void)
1598
{
1599
    /* Large physaddr not implemented */
1600
    /* 1k pages not implemented */
1601
    env->CP0_EntryLo0 = T0 & 0x3FFFFFFF;
1602
    RETURN();
1603
}
1604

    
1605
void op_dmtc0_entrylo1 (void)
1606
{
1607
    /* Large physaddr not implemented */
1608
    /* 1k pages not implemented */
1609
    env->CP0_EntryLo1 = T0 & 0x3FFFFFFF;
1610
    RETURN();
1611
}
1612

    
1613
void op_dmtc0_context (void)
1614
{
1615
    env->CP0_Context = (env->CP0_Context & ~0x007FFFFF) | (T0 & 0x007FFFF0);
1616
    RETURN();
1617
}
1618

    
1619
void op_dmtc0_epc (void)
1620
{
1621
    env->CP0_EPC = T0;
1622
    RETURN();
1623
}
1624

    
1625
void op_dmtc0_watchlo0 (void)
1626
{
1627
    /* Watch exceptions for instructions, data loads, data stores
1628
       not implemented. */
1629
    env->CP0_WatchLo = T0 & ~0x7;
1630
    RETURN();
1631
}
1632

    
1633
void op_dmtc0_xcontext (void)
1634
{
1635
    env->CP0_XContext = T0; /* XXX */
1636
    RETURN();
1637
}
1638

    
1639
void op_dmtc0_depc (void)
1640
{
1641
    env->CP0_DEPC = T0;
1642
    RETURN();
1643
}
1644

    
1645
void op_dmtc0_errorepc (void)
1646
{
1647
    env->CP0_ErrorEPC = T0;
1648
    RETURN();
1649
}
1650

    
1651
#if 0
1652
# define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env)
1653
#else
1654
# define DEBUG_FPU_STATE() do { } while(0)
1655
#endif
1656

    
1657
void op_cp0_enabled(void)
1658
{
1659
    if (!(env->CP0_Status & (1 << CP0St_CU0)) &&
1660
        (env->hflags & MIPS_HFLAG_UM)) {
1661
        CALL_FROM_TB2(do_raise_exception_err, EXCP_CpU, 0);
1662
    }
1663
    RETURN();
1664
}
1665

    
1666
void op_cp1_enabled(void)
1667
{
1668
    if (!(env->CP0_Status & (1 << CP0St_CU1))) {
1669
        CALL_FROM_TB2(do_raise_exception_err, EXCP_CpU, 1);
1670
    }
1671
    RETURN();
1672
}
1673

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

    
1688
/* convert MIPS rounding mode in FCR31 to IEEE library */
1689
unsigned int ieee_rm[] = { 
1690
    float_round_nearest_even,
1691
    float_round_to_zero,
1692
    float_round_up,
1693
    float_round_down
1694
};
1695

    
1696
#define RESTORE_ROUNDING_MODE \
1697
    set_float_rounding_mode(ieee_rm[env->fcr31 & 3], &env->fp_status)
1698

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

    
1711
        /* set rounding mode */
1712
        RESTORE_ROUNDING_MODE;
1713

    
1714
#ifndef CONFIG_SOFTFLOAT
1715
        /* no floating point exception for native float */
1716
        SET_FP_ENABLE(env->fcr31, 0);
1717
#endif
1718
    }
1719
    DEBUG_FPU_STATE();
1720
    RETURN();
1721
}
1722

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

    
1730
void op_mtc1 (void)
1731
{
1732
    WT0 = T0;
1733
    DEBUG_FPU_STATE();
1734
    RETURN();
1735
}
1736

    
1737
/* Float support.
1738
   Single precition routines have a "s" suffix, double precision a
1739
   "d" suffix.  */
1740

    
1741
#define FLOAT_OP(name, p) void OPPROTO op_float_##name##_##p(void)
1742

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

    
1780
FLOAT_OP(roundw, d)
1781
{
1782
    set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
1783
    WT2 = float64_round_to_int(FDT0, &env->fp_status);
1784
    RESTORE_ROUNDING_MODE;
1785

    
1786
    DEBUG_FPU_STATE();
1787
    RETURN();
1788
}
1789
FLOAT_OP(roundw, s)
1790
{
1791
    set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
1792
    WT2 = float32_round_to_int(FST0, &env->fp_status);
1793
    RESTORE_ROUNDING_MODE;
1794
    DEBUG_FPU_STATE();
1795
    RETURN();
1796
}
1797

    
1798
FLOAT_OP(truncw, d)
1799
{
1800
    WT2 = float64_to_int32_round_to_zero(FDT0, &env->fp_status);
1801
    DEBUG_FPU_STATE();
1802
    RETURN();
1803
}
1804
FLOAT_OP(truncw, s)
1805
{
1806
    WT2 = float32_to_int32_round_to_zero(FST0, &env->fp_status);
1807
    DEBUG_FPU_STATE();
1808
    RETURN();
1809
}
1810

    
1811
FLOAT_OP(ceilw, d)
1812
{
1813
    set_float_rounding_mode(float_round_up, &env->fp_status);
1814
    WT2 = float64_round_to_int(FDT0, &env->fp_status);
1815
    RESTORE_ROUNDING_MODE;
1816

    
1817
    DEBUG_FPU_STATE();
1818
    RETURN();
1819
}
1820
FLOAT_OP(ceilw, s)
1821
{
1822
    set_float_rounding_mode(float_round_up, &env->fp_status);
1823
    WT2 = float32_round_to_int(FST0, &env->fp_status);
1824
    RESTORE_ROUNDING_MODE;
1825
    DEBUG_FPU_STATE();
1826
    RETURN();
1827
}
1828

    
1829
FLOAT_OP(floorw, d)
1830
{
1831
    set_float_rounding_mode(float_round_down, &env->fp_status);
1832
    WT2 = float64_round_to_int(FDT0, &env->fp_status);
1833
    RESTORE_ROUNDING_MODE;
1834

    
1835
    DEBUG_FPU_STATE();
1836
    RETURN();
1837
}
1838
FLOAT_OP(floorw, s)
1839
{
1840
    set_float_rounding_mode(float_round_down, &env->fp_status);
1841
    WT2 = float32_round_to_int(FST0, &env->fp_status);
1842
    RESTORE_ROUNDING_MODE;
1843
    DEBUG_FPU_STATE();
1844
    RETURN();
1845
}
1846

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

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

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

    
1896
FLOAT_OP(mov, d)
1897
{
1898
    FDT2 = FDT0;
1899
    DEBUG_FPU_STATE();
1900
    RETURN();
1901
}
1902
FLOAT_OP(mov, s)
1903
{
1904
    FST2 = FST0;
1905
    DEBUG_FPU_STATE();
1906
    RETURN();
1907
}
1908

    
1909
#ifdef CONFIG_SOFTFLOAT
1910
#define clear_invalid() do {                                \
1911
    int flags = get_float_exception_flags(&env->fp_status); \
1912
    flags &= ~float_flag_invalid;                           \
1913
    set_float_exception_flags(flags, &env->fp_status);      \
1914
} while(0)
1915
#else
1916
#define clear_invalid() do { } while(0)
1917
#endif
1918

    
1919
extern void dump_fpu_s(CPUState *env);
1920

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

    
1935
int float64_is_unordered(float64 a, float64 b STATUS_PARAM)
1936
{
1937
    if (float64_is_nan(a) || float64_is_nan(b)) {
1938
        float_raise(float_flag_invalid, status);
1939
        return 1;
1940
    }
1941
    else {
1942
        return 0;
1943
    }
1944
}
1945

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

    
1966
flag float32_is_unordered(float32 a, float32 b STATUS_PARAM)
1967
{
1968
    extern flag float32_is_nan( float32 a );
1969
    if (float32_is_nan(a) || float32_is_nan(b)) {
1970
        float_raise(float_flag_invalid, status);
1971
        return 1;
1972
    }
1973
    else {
1974
        return 0;
1975
    }
1976
}
1977

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

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

    
2008
void op_bc1t (void)
2009
{
2010
    T0 = IS_FP_COND_SET(env->fcr31);
2011
    DEBUG_FPU_STATE();
2012
    RETURN();
2013
}
2014

    
2015
#if defined(MIPS_USES_R4K_TLB)
2016
void op_tlbwi (void)
2017
{
2018
    CALL_FROM_TB0(do_tlbwi);
2019
    RETURN();
2020
}
2021

    
2022
void op_tlbwr (void)
2023
{
2024
    CALL_FROM_TB0(do_tlbwr);
2025
    RETURN();
2026
}
2027

    
2028
void op_tlbp (void)
2029
{
2030
    CALL_FROM_TB0(do_tlbp);
2031
    RETURN();
2032
}
2033

    
2034
void op_tlbr (void)
2035
{
2036
    CALL_FROM_TB0(do_tlbr);
2037
    RETURN();
2038
}
2039
#endif
2040

    
2041
/* Specials */
2042
#if defined (CONFIG_USER_ONLY)
2043
void op_tls_value (void)
2044
{
2045
  T0 = env->tls_value;
2046
}
2047
#endif
2048

    
2049
void op_pmon (void)
2050
{
2051
    CALL_FROM_TB1(do_pmon, PARAM1);
2052
    RETURN();
2053
}
2054

    
2055
void op_di (void)
2056
{
2057
    T0 = env->CP0_Status;
2058
    env->CP0_Status = T0 & ~(1 << CP0St_IE);
2059
    CALL_FROM_TB1(cpu_mips_update_irq, env);
2060
    RETURN();
2061
}
2062

    
2063
void op_ei (void)
2064
{
2065
    T0 = env->CP0_Status;
2066
    env->CP0_Status = T0 | (1 << CP0St_IE);
2067
    CALL_FROM_TB1(cpu_mips_update_irq, env);
2068
    RETURN();
2069
}
2070

    
2071
void op_trap (void)
2072
{
2073
    if (T0) {
2074
        CALL_FROM_TB1(do_raise_exception, EXCP_TRAP);
2075
    }
2076
    RETURN();
2077
}
2078

    
2079
void op_debug (void)
2080
{
2081
    CALL_FROM_TB1(do_raise_exception, EXCP_DEBUG);
2082
    RETURN();
2083
}
2084

    
2085
void op_set_lladdr (void)
2086
{
2087
    env->CP0_LLAddr = T2;
2088
    RETURN();
2089
}
2090

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

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

    
2132
void op_rdhwr_cpunum(void)
2133
{
2134
    if (!(env->hflags & MIPS_HFLAG_UM) ||
2135
        (env->CP0_HWREna & (1 << 0)) ||
2136
        (env->CP0_Status & (1 << CP0St_CU0)))
2137
        T0 = env->CP0_EBase & 0x3ff;
2138
    else
2139
        CALL_FROM_TB1(do_raise_exception, EXCP_RI);
2140
    RETURN();
2141
}
2142

    
2143
void op_rdhwr_synci_step(void)
2144
{
2145
    if (!(env->hflags & MIPS_HFLAG_UM) ||
2146
        (env->CP0_HWREna & (1 << 1)) ||
2147
        (env->CP0_Status & (1 << CP0St_CU0)))
2148
        T0 = env->SYNCI_Step;
2149
    else
2150
        CALL_FROM_TB1(do_raise_exception, EXCP_RI);
2151
    RETURN();
2152
}
2153

    
2154
void op_rdhwr_cc(void)
2155
{
2156
    if (!(env->hflags & MIPS_HFLAG_UM) ||
2157
        (env->CP0_HWREna & (1 << 2)) ||
2158
        (env->CP0_Status & (1 << CP0St_CU0)))
2159
        T0 = env->CP0_Count;
2160
    else
2161
        CALL_FROM_TB1(do_raise_exception, EXCP_RI);
2162
    RETURN();
2163
}
2164

    
2165
void op_rdhwr_ccres(void)
2166
{
2167
    if (!(env->hflags & MIPS_HFLAG_UM) ||
2168
        (env->CP0_HWREna & (1 << 3)) ||
2169
        (env->CP0_Status & (1 << CP0St_CU0)))
2170
        T0 = env->CCRes;
2171
    else
2172
        CALL_FROM_TB1(do_raise_exception, EXCP_RI);
2173
    RETURN();
2174
}
2175

    
2176
void op_save_state (void)
2177
{
2178
    env->hflags = PARAM1;
2179
    RETURN();
2180
}
2181

    
2182
void op_save_pc (void)
2183
{
2184
    env->PC = PARAM1;
2185
    RETURN();
2186
}
2187

    
2188
void op_raise_exception (void)
2189
{
2190
    CALL_FROM_TB1(do_raise_exception, PARAM1);
2191
    RETURN();
2192
}
2193

    
2194
void op_raise_exception_err (void)
2195
{
2196
    CALL_FROM_TB2(do_raise_exception_err, PARAM1, PARAM2);
2197
    RETURN();
2198
}
2199

    
2200
void op_exit_tb (void)
2201
{
2202
    EXIT_TB();
2203
    RETURN();
2204
}
2205

    
2206
void op_wait (void)
2207
{
2208
    env->halted = 1;
2209
    CALL_FROM_TB1(do_raise_exception, EXCP_HLT);
2210
    RETURN();
2211
}
2212

    
2213
/* Bitfield operations. */
2214
void op_ext(void)
2215
{
2216
    unsigned int pos = PARAM1;
2217
    unsigned int size = PARAM2;
2218

    
2219
    T0 = ((uint32_t)T1 >> pos) & ((size < 32) ? ((1 << size) - 1) : ~0);
2220
    RETURN();
2221
}
2222

    
2223
void op_ins(void)
2224
{
2225
    unsigned int pos = PARAM1;
2226
    unsigned int size = PARAM2;
2227
    target_ulong mask = ((size < 32) ? ((1 << size) - 1) : ~0) << pos;
2228

    
2229
    T0 = (T2 & ~mask) | (((uint32_t)T1 << pos) & mask);
2230
    RETURN();
2231
}
2232

    
2233
void op_wsbh(void)
2234
{
2235
    T0 = ((T1 << 8) & ~0x00FF00FF) | ((T1 >> 8) & 0x00FF00FF);
2236
    RETURN();
2237
}
2238

    
2239
#ifdef TARGET_MIPS64
2240
void op_dext(void)
2241
{
2242
    unsigned int pos = PARAM1;
2243
    unsigned int size = PARAM2;
2244

    
2245
    T0 = (T1 >> pos) & ((size < 32) ? ((1 << size) - 1) : ~0);
2246
    RETURN();
2247
}
2248

    
2249
void op_dins(void)
2250
{
2251
    unsigned int pos = PARAM1;
2252
    unsigned int size = PARAM2;
2253
    target_ulong mask = ((size < 32) ? ((1 << size) - 1) : ~0) << pos;
2254

    
2255
    T0 = (T2 & ~mask) | ((T1 << pos) & mask);
2256
    RETURN();
2257
}
2258

    
2259
void op_dsbh(void)
2260
{
2261
    T0 = ((T1 << 8) & ~0x00FF00FF00FF00FFULL) | ((T1 >> 8) & 0x00FF00FF00FF00FFULL);
2262
    RETURN();
2263
}
2264

    
2265
void op_dshd(void)
2266
{
2267
    T0 = ((T1 << 16) & ~0x0000FFFF0000FFFFULL) | ((T1 >> 16) & 0x0000FFFF0000FFFFULL);
2268
    RETURN();
2269
}
2270
#endif
2271

    
2272
void op_seb(void)
2273
{
2274
    T0 = ((T1 & 0xFF) ^ 0x80) - 0x80;
2275
    RETURN();
2276
}
2277

    
2278
void op_seh(void)
2279
{
2280
    T0 = ((T1 & 0xFFFF) ^ 0x8000) - 0x8000;
2281
    RETURN();
2282
}