Statistics
| Branch: | Revision:

root / target-mips / op.c @ b29a0341

History | View | Annotate | Download (40.3 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
#ifdef MIPS_USES_FPU
148

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

    
278
#define FTN
279
#include "fop_template.c"
280
#undef FTN
281

    
282
#endif
283

    
284
void op_dup_T0 (void)
285
{
286
    T2 = T0;
287
    RETURN();
288
}
289

    
290
void op_load_HI (void)
291
{
292
    T0 = env->HI;
293
    RETURN();
294
}
295

    
296
void op_store_HI (void)
297
{
298
    env->HI = T0;
299
    RETURN();
300
}
301

    
302
void op_load_LO (void)
303
{
304
    T0 = env->LO;
305
    RETURN();
306
}
307

    
308
void op_store_LO (void)
309
{
310
    env->LO = T0;
311
    RETURN();
312
}
313

    
314
/* Load and store */
315
#define MEMSUFFIX _raw
316
#include "op_mem.c"
317
#undef MEMSUFFIX
318
#if !defined(CONFIG_USER_ONLY)
319
#define MEMSUFFIX _user
320
#include "op_mem.c"
321
#undef MEMSUFFIX
322

    
323
#define MEMSUFFIX _kernel
324
#include "op_mem.c"
325
#undef MEMSUFFIX
326
#endif
327

    
328
/* Arithmetic */
329
void op_add (void)
330
{
331
    T0 = (int32_t)((int32_t)T0 + (int32_t)T1);
332
    RETURN();
333
}
334

    
335
void op_addo (void)
336
{
337
    target_ulong tmp;
338

    
339
    tmp = (int32_t)T0;
340
    T0 = (int32_t)T0 + (int32_t)T1;
341
    if (((tmp ^ T1 ^ (-1)) & (T0 ^ T1)) >> 31) {
342
        /* operands of same sign, result different sign */
343
        CALL_FROM_TB1(do_raise_exception_direct, EXCP_OVERFLOW);
344
    }
345
    T0 = (int32_t)T0;
346
    RETURN();
347
}
348

    
349
void op_sub (void)
350
{
351
    T0 = (int32_t)((int32_t)T0 - (int32_t)T1);
352
    RETURN();
353
}
354

    
355
void op_subo (void)
356
{
357
    target_ulong tmp;
358

    
359
    tmp = (int32_t)T0;
360
    T0 = (int32_t)T0 - (int32_t)T1;
361
    if (((tmp ^ T1) & (tmp ^ T0)) >> 31) {
362
        /* operands of different sign, first operand and result different sign */
363
        CALL_FROM_TB1(do_raise_exception_direct, EXCP_OVERFLOW);
364
    }
365
    T0 = (int32_t)T0;
366
    RETURN();
367
}
368

    
369
void op_mul (void)
370
{
371
    T0 = (int32_t)((int32_t)T0 * (int32_t)T1);
372
    RETURN();
373
}
374

    
375
void op_div (void)
376
{
377
    if (T1 != 0) {
378
        env->LO = (int32_t)((int32_t)T0 / (int32_t)T1);
379
        env->HI = (int32_t)((int32_t)T0 % (int32_t)T1);
380
    }
381
    RETURN();
382
}
383

    
384
void op_divu (void)
385
{
386
    if (T1 != 0) {
387
        env->LO = (int32_t)((uint32_t)T0 / (uint32_t)T1);
388
        env->HI = (int32_t)((uint32_t)T0 % (uint32_t)T1);
389
    }
390
    RETURN();
391
}
392

    
393
#ifdef MIPS_HAS_MIPS64
394
/* Arithmetic */
395
void op_dadd (void)
396
{
397
    T0 += T1;
398
    RETURN();
399
}
400

    
401
void op_daddo (void)
402
{
403
    target_long tmp;
404

    
405
    tmp = T0;
406
    T0 += T1;
407
    if (((tmp ^ T1 ^ (-1)) & (T0 ^ T1)) >> 63) {
408
        /* operands of same sign, result different sign */
409
        CALL_FROM_TB1(do_raise_exception_direct, EXCP_OVERFLOW);
410
    }
411
    RETURN();
412
}
413

    
414
void op_dsub (void)
415
{
416
    T0 -= T1;
417
    RETURN();
418
}
419

    
420
void op_dsubo (void)
421
{
422
    target_long tmp;
423

    
424
    tmp = T0;
425
    T0 = (int64_t)T0 - (int64_t)T1;
426
    if (((tmp ^ T1) & (tmp ^ T0)) >> 63) {
427
        /* operands of different sign, first operand and result different sign */
428
        CALL_FROM_TB1(do_raise_exception_direct, EXCP_OVERFLOW);
429
    }
430
    RETURN();
431
}
432

    
433
void op_dmul (void)
434
{
435
    T0 = (int64_t)T0 * (int64_t)T1;
436
    RETURN();
437
}
438

    
439
#if TARGET_LONG_BITS > HOST_LONG_BITS
440
/* Those might call libgcc functions.  */
441
void op_ddiv (void)
442
{
443
    do_ddiv();
444
    RETURN();
445
}
446

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

    
462
void op_ddivu (void)
463
{
464
    if (T1 != 0) {
465
        env->LO = T0 / T1;
466
        env->HI = T0 % T1;
467
    }
468
    RETURN();
469
}
470
#endif
471
#endif /* MIPS_HAS_MIPS64 */
472

    
473
/* Logical */
474
void op_and (void)
475
{
476
    T0 &= T1;
477
    RETURN();
478
}
479

    
480
void op_nor (void)
481
{
482
    T0 = ~(T0 | T1);
483
    RETURN();
484
}
485

    
486
void op_or (void)
487
{
488
    T0 |= T1;
489
    RETURN();
490
}
491

    
492
void op_xor (void)
493
{
494
    T0 ^= T1;
495
    RETURN();
496
}
497

    
498
void op_sll (void)
499
{
500
    T0 = (int32_t)((uint32_t)T0 << (uint32_t)T1);
501
    RETURN();
502
}
503

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

    
510
void op_srl (void)
511
{
512
    T0 = (int32_t)((uint32_t)T0 >> (uint32_t)T1);
513
    RETURN();
514
}
515

    
516
void op_rotr (void)
517
{
518
    target_ulong tmp;
519

    
520
    if (T1) {
521
       tmp = (int32_t)((uint32_t)T0 << (0x20 - (uint32_t)T1));
522
       T0 = (int32_t)((uint32_t)T0 >> (uint32_t)T1) | tmp;
523
    } else
524
       T0 = T1;
525
    RETURN();
526
}
527

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

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

    
540
void op_srlv (void)
541
{
542
    T0 = (int32_t)((uint32_t)T1 >> (T0 & 0x1F));
543
    RETURN();
544
}
545

    
546
void op_rotrv (void)
547
{
548
    target_ulong tmp;
549

    
550
    T0 &= 0x1F;
551
    if (T0) {
552
       tmp = (int32_t)((uint32_t)T1 << (0x20 - T0));
553
       T0 = (int32_t)((uint32_t)T1 >> T0) | tmp;
554
    } else
555
       T0 = T1;
556
    RETURN();
557
}
558

    
559
void op_clo (void)
560
{
561
    int n;
562

    
563
    if (T0 == ~((target_ulong)0)) {
564
        T0 = 32;
565
    } else {
566
        for (n = 0; n < 32; n++) {
567
            if (!(T0 & (1 << 31)))
568
                break;
569
            T0 = T0 << 1;
570
        }
571
        T0 = n;
572
    }
573
    RETURN();
574
}
575

    
576
void op_clz (void)
577
{
578
    int n;
579

    
580
    if (T0 == 0) {
581
        T0 = 32;
582
    } else {
583
        for (n = 0; n < 32; n++) {
584
            if (T0 & (1 << 31))
585
                break;
586
            T0 = T0 << 1;
587
        }
588
        T0 = n;
589
    }
590
    RETURN();
591
}
592

    
593
#ifdef MIPS_HAS_MIPS64
594

    
595
#if TARGET_LONG_BITS > HOST_LONG_BITS
596
/* Those might call libgcc functions.  */
597
void op_dsll (void)
598
{
599
    CALL_FROM_TB0(do_dsll);
600
    RETURN();
601
}
602

    
603
void op_dsll32 (void)
604
{
605
    CALL_FROM_TB0(do_dsll32);
606
    RETURN();
607
}
608

    
609
void op_dsra (void)
610
{
611
    CALL_FROM_TB0(do_dsra);
612
    RETURN();
613
}
614

    
615
void op_dsra32 (void)
616
{
617
    CALL_FROM_TB0(do_dsra32);
618
    RETURN();
619
}
620

    
621
void op_dsrl (void)
622
{
623
    CALL_FROM_TB0(do_dsrl);
624
    RETURN();
625
}
626

    
627
void op_dsrl32 (void)
628
{
629
    CALL_FROM_TB0(do_dsrl32);
630
    RETURN();
631
}
632

    
633
void op_drotr (void)
634
{
635
    CALL_FROM_TB0(do_drotr);
636
    RETURN();
637
}
638

    
639
void op_drotr32 (void)
640
{
641
    CALL_FROM_TB0(do_drotr32);
642
    RETURN();
643
}
644

    
645
void op_dsllv (void)
646
{
647
    CALL_FROM_TB0(do_dsllv);
648
    RETURN();
649
}
650

    
651
void op_dsrav (void)
652
{
653
    CALL_FROM_TB0(do_dsrav);
654
    RETURN();
655
}
656

    
657
void op_dsrlv (void)
658
{
659
    CALL_FROM_TB0(do_dsrlv);
660
    RETURN();
661
}
662

    
663
void op_drotrv (void)
664
{
665
    CALL_FROM_TB0(do_drotrv);
666
    RETURN();
667
}
668

    
669
#else /* TARGET_LONG_BITS > HOST_LONG_BITS */
670

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

    
677
void op_dsll32 (void)
678
{
679
    T0 = T0 << (T1 + 32);
680
    RETURN();
681
}
682

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

    
689
void op_dsra32 (void)
690
{
691
    T0 = (int64_t)T0 >> (T1 + 32);
692
    RETURN();
693
}
694

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

    
701
void op_dsrl32 (void)
702
{
703
    T0 = T0 >> (T1 + 32);
704
    RETURN();
705
}
706

    
707
void op_drotr (void)
708
{
709
    target_ulong tmp;
710

    
711
    if (T1) {
712
       tmp = T0 << (0x40 - T1);
713
       T0 = (T0 >> T1) | tmp;
714
    } else
715
       T0 = T1;
716
    RETURN();
717
}
718

    
719
void op_drotr32 (void)
720
{
721
    target_ulong tmp;
722

    
723
    if (T1) {
724
       tmp = T0 << (0x40 - (32 + T1));
725
       T0 = (T0 >> (32 + T1)) | tmp;
726
    } else
727
       T0 = T1;
728
    RETURN();
729
}
730

    
731
void op_dsllv (void)
732
{
733
    T0 = T1 << (T0 & 0x3F);
734
    RETURN();
735
}
736

    
737
void op_dsrav (void)
738
{
739
    T0 = (int64_t)T1 >> (T0 & 0x3F);
740
    RETURN();
741
}
742

    
743
void op_dsrlv (void)
744
{
745
    T0 = T1 >> (T0 & 0x3F);
746
    RETURN();
747
}
748

    
749
void op_drotrv (void)
750
{
751
    target_ulong tmp;
752

    
753
    T0 &= 0x3F;
754
    if (T0) {
755
       tmp = T1 << (0x40 - T0);
756
       T0 = (T1 >> T0) | tmp;
757
    } else
758
       T0 = T1;
759
    RETURN();
760
}
761
#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
762

    
763
void op_dclo (void)
764
{
765
    int n;
766

    
767
    if (T0 == ~((target_ulong)0)) {
768
        T0 = 64;
769
    } else {
770
        for (n = 0; n < 64; n++) {
771
            if (!(T0 & (1ULL << 63)))
772
                break;
773
            T0 = T0 << 1;
774
        }
775
        T0 = n;
776
    }
777
    RETURN();
778
}
779

    
780
void op_dclz (void)
781
{
782
    int n;
783

    
784
    if (T0 == 0) {
785
        T0 = 64;
786
    } else {
787
        for (n = 0; n < 64; n++) {
788
            if (T0 & (1ULL << 63))
789
                break;
790
            T0 = T0 << 1;
791
        }
792
        T0 = n;
793
    }
794
    RETURN();
795
}
796
#endif
797

    
798
/* 64 bits arithmetic */
799
#if TARGET_LONG_BITS > HOST_LONG_BITS
800
void op_mult (void)
801
{
802
    CALL_FROM_TB0(do_mult);
803
    RETURN();
804
}
805

    
806
void op_multu (void)
807
{
808
    CALL_FROM_TB0(do_multu);
809
    RETURN();
810
}
811

    
812
void op_madd (void)
813
{
814
    CALL_FROM_TB0(do_madd);
815
    RETURN();
816
}
817

    
818
void op_maddu (void)
819
{
820
    CALL_FROM_TB0(do_maddu);
821
    RETURN();
822
}
823

    
824
void op_msub (void)
825
{
826
    CALL_FROM_TB0(do_msub);
827
    RETURN();
828
}
829

    
830
void op_msubu (void)
831
{
832
    CALL_FROM_TB0(do_msubu);
833
    RETURN();
834
}
835

    
836
#else /* TARGET_LONG_BITS > HOST_LONG_BITS */
837

    
838
static inline uint64_t get_HILO (void)
839
{
840
    return ((uint64_t)env->HI << 32) | ((uint64_t)(uint32_t)env->LO);
841
}
842

    
843
static inline void set_HILO (uint64_t HILO)
844
{
845
    env->LO = (int32_t)(HILO & 0xFFFFFFFF);
846
    env->HI = (int32_t)(HILO >> 32);
847
}
848

    
849
void op_mult (void)
850
{
851
    set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
852
    RETURN();
853
}
854

    
855
void op_multu (void)
856
{
857
    set_HILO((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
858
    RETURN();
859
}
860

    
861
void op_madd (void)
862
{
863
    int64_t tmp;
864

    
865
    tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
866
    set_HILO((int64_t)get_HILO() + tmp);
867
    RETURN();
868
}
869

    
870
void op_maddu (void)
871
{
872
    uint64_t tmp;
873

    
874
    tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
875
    set_HILO(get_HILO() + tmp);
876
    RETURN();
877
}
878

    
879
void op_msub (void)
880
{
881
    int64_t tmp;
882

    
883
    tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
884
    set_HILO((int64_t)get_HILO() - tmp);
885
    RETURN();
886
}
887

    
888
void op_msubu (void)
889
{
890
    uint64_t tmp;
891

    
892
    tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
893
    set_HILO(get_HILO() - tmp);
894
    RETURN();
895
}
896
#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
897

    
898
#ifdef MIPS_HAS_MIPS64
899
void op_dmult (void)
900
{
901
    CALL_FROM_TB0(do_dmult);
902
    RETURN();
903
}
904

    
905
void op_dmultu (void)
906
{
907
    CALL_FROM_TB0(do_dmultu);
908
    RETURN();
909
}
910
#endif
911

    
912
/* Conditional moves */
913
void op_movn (void)
914
{
915
    if (T1 != 0)
916
        env->gpr[PARAM1] = T0;
917
    RETURN();
918
}
919

    
920
void op_movz (void)
921
{
922
    if (T1 == 0)
923
        env->gpr[PARAM1] = T0;
924
    RETURN();
925
}
926

    
927
#ifdef MIPS_USES_FPU
928
void op_movf (void)
929
{
930
    if (!(env->fcr31 & PARAM1))
931
        env->gpr[PARAM2] = env->gpr[PARAM3];
932
    RETURN();
933
}
934

    
935
void op_movt (void)
936
{
937
    if (env->fcr31 & PARAM1)
938
        env->gpr[PARAM2] = env->gpr[PARAM3];
939
    RETURN();
940
}
941
#endif
942

    
943
/* Tests */
944
#define OP_COND(name, cond) \
945
void glue(op_, name) (void) \
946
{                           \
947
    if (cond) {             \
948
        T0 = 1;             \
949
    } else {                \
950
        T0 = 0;             \
951
    }                       \
952
    RETURN();               \
953
}
954

    
955
OP_COND(eq, T0 == T1);
956
OP_COND(ne, T0 != T1);
957
OP_COND(ge, (int32_t)T0 >= (int32_t)T1);
958
OP_COND(geu, T0 >= T1);
959
OP_COND(lt, (int32_t)T0 < (int32_t)T1);
960
OP_COND(ltu, T0 < T1);
961
OP_COND(gez, (int32_t)T0 >= 0);
962
OP_COND(gtz, (int32_t)T0 > 0);
963
OP_COND(lez, (int32_t)T0 <= 0);
964
OP_COND(ltz, (int32_t)T0 < 0);
965

    
966
/* Branches */
967
//#undef USE_DIRECT_JUMP
968

    
969
void OPPROTO op_goto_tb0(void)
970
{
971
    GOTO_TB(op_goto_tb0, PARAM1, 0);
972
    RETURN();
973
}
974

    
975
void OPPROTO op_goto_tb1(void)
976
{
977
    GOTO_TB(op_goto_tb1, PARAM1, 1);
978
    RETURN();
979
}
980

    
981
/* Branch to register */
982
void op_save_breg_target (void)
983
{
984
    env->btarget = T2;
985
    RETURN();
986
}
987

    
988
void op_restore_breg_target (void)
989
{
990
    T2 = env->btarget;
991
    RETURN();
992
}
993

    
994
void op_breg (void)
995
{
996
    env->PC = T2;
997
    RETURN();
998
}
999

    
1000
void op_save_btarget (void)
1001
{
1002
    env->btarget = PARAM1;
1003
    RETURN();
1004
}
1005

    
1006
/* Conditional branch */
1007
void op_set_bcond (void)
1008
{
1009
    T2 = T0;
1010
    RETURN();
1011
}
1012

    
1013
void op_save_bcond (void)
1014
{
1015
    env->bcond = T2;
1016
    RETURN();
1017
}
1018

    
1019
void op_restore_bcond (void)
1020
{
1021
    T2 = env->bcond;
1022
    RETURN();
1023
}
1024

    
1025
void op_jnz_T2 (void)
1026
{
1027
    if (T2)
1028
        GOTO_LABEL_PARAM(1);
1029
    RETURN();
1030
}
1031

    
1032
/* CP0 functions */
1033
void op_mfc0_index (void)
1034
{
1035
    T0 = env->CP0_Index;
1036
    RETURN();
1037
}
1038

    
1039
void op_mfc0_random (void)
1040
{
1041
    CALL_FROM_TB0(do_mfc0_random);
1042
    RETURN();
1043
}
1044

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

    
1051
void op_mfc0_entrylo1 (void)
1052
{
1053
    T0 = (int32_t)env->CP0_EntryLo1;
1054
    RETURN();
1055
}
1056

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

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

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

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

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

    
1087
void op_mfc0_badvaddr (void)
1088
{
1089
    T0 = (int32_t)env->CP0_BadVAddr;
1090
    RETURN();
1091
}
1092

    
1093
void op_mfc0_count (void)
1094
{
1095
    CALL_FROM_TB0(do_mfc0_count);
1096
    RETURN();
1097
}
1098

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

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

    
1111
void op_mfc0_status (void)
1112
{
1113
    T0 = env->CP0_Status;
1114
    if (env->hflags & MIPS_HFLAG_UM)
1115
        T0 |= (1 << CP0St_UM);
1116
    if (env->hflags & MIPS_HFLAG_ERL)
1117
        T0 |= (1 << CP0St_ERL);
1118
    if (env->hflags & MIPS_HFLAG_EXL)
1119
        T0 |= (1 << CP0St_EXL);
1120
    RETURN();
1121
}
1122

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

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

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

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

    
1147
void op_mfc0_epc (void)
1148
{
1149
    T0 = (int32_t)env->CP0_EPC;
1150
    RETURN();
1151
}
1152

    
1153
void op_mfc0_prid (void)
1154
{
1155
    T0 = env->CP0_PRid;
1156
    RETURN();
1157
}
1158

    
1159
void op_mfc0_ebase (void)
1160
{
1161
    T0 = env->CP0_EBase;
1162
    RETURN();
1163
}
1164

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

    
1171
void op_mfc0_config1 (void)
1172
{
1173
    T0 = env->CP0_Config1;
1174
    RETURN();
1175
}
1176

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

    
1183
void op_mfc0_config3 (void)
1184
{
1185
    T0 = env->CP0_Config3;
1186
    RETURN();
1187
}
1188

    
1189
void op_mfc0_lladdr (void)
1190
{
1191
    T0 = (int32_t)env->CP0_LLAddr >> 4;
1192
    RETURN();
1193
}
1194

    
1195
void op_mfc0_watchlo0 (void)
1196
{
1197
    T0 = (int32_t)env->CP0_WatchLo;
1198
    RETURN();
1199
}
1200

    
1201
void op_mfc0_watchhi0 (void)
1202
{
1203
    T0 = env->CP0_WatchHi;
1204
    RETURN();
1205
}
1206

    
1207
void op_mfc0_xcontext (void)
1208
{
1209
    T0 = (int32_t)env->CP0_XContext;
1210
    RETURN();
1211
}
1212

    
1213
void op_mfc0_framemask (void)
1214
{
1215
    T0 = env->CP0_Framemask;
1216
    RETURN();
1217
}
1218

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

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

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

    
1239
void op_mfc0_taglo (void)
1240
{
1241
    T0 = env->CP0_TagLo;
1242
    RETURN();
1243
}
1244

    
1245
void op_mfc0_datalo (void)
1246
{
1247
    T0 = env->CP0_DataLo;
1248
    RETURN();
1249
}
1250

    
1251
void op_mfc0_taghi (void)
1252
{
1253
    T0 = env->CP0_TagHi;
1254
    RETURN();
1255
}
1256

    
1257
void op_mfc0_datahi (void)
1258
{
1259
    T0 = env->CP0_DataHi;
1260
    RETURN();
1261
}
1262

    
1263
void op_mfc0_errorepc (void)
1264
{
1265
    T0 = (int32_t)env->CP0_ErrorEPC;
1266
    RETURN();
1267
}
1268

    
1269
void op_mfc0_desave (void)
1270
{
1271
    T0 = env->CP0_DESAVE;
1272
    RETURN();
1273
}
1274

    
1275
void op_mtc0_index (void)
1276
{
1277
    env->CP0_Index = (env->CP0_Index & 0x80000000) | (T0 & (MIPS_TLB_NB - 1));
1278
    RETURN();
1279
}
1280

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

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

    
1297
void op_mtc0_context (void)
1298
{
1299
    env->CP0_Context = (env->CP0_Context & ~0x007FFFFF) | (T0 & 0x007FFFF0);
1300
    RETURN();
1301
}
1302

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

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

    
1319
void op_mtc0_wired (void)
1320
{
1321
    env->CP0_Wired = T0 & (MIPS_TLB_NB - 1);
1322
    RETURN();
1323
}
1324

    
1325
void op_mtc0_hwrena (void)
1326
{
1327
    env->CP0_HWREna = T0 & 0x0000000F;
1328
    RETURN();
1329
}
1330

    
1331
void op_mtc0_count (void)
1332
{
1333
    CALL_FROM_TB2(cpu_mips_store_count, env, T0);
1334
    RETURN();
1335
}
1336

    
1337
void op_mtc0_entryhi (void)
1338
{
1339
    target_ulong old, val;
1340

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

    
1352
void op_mtc0_compare (void)
1353
{
1354
    CALL_FROM_TB2(cpu_mips_store_compare, env, T0);
1355
    RETURN();
1356
}
1357

    
1358
void op_mtc0_status (void)
1359
{
1360
    uint32_t val, old;
1361

    
1362
    val = (int32_t)T0 & 0xFA78FF01;
1363
    old = env->CP0_Status;
1364
    if (T0 & (1 << CP0St_UM))
1365
        env->hflags |= MIPS_HFLAG_UM;
1366
    else
1367
        env->hflags &= ~MIPS_HFLAG_UM;
1368
    if (T0 & (1 << CP0St_ERL))
1369
        env->hflags |= MIPS_HFLAG_ERL;
1370
    else
1371
        env->hflags &= ~MIPS_HFLAG_ERL;
1372
    if (T0 & (1 << CP0St_EXL))
1373
        env->hflags |= MIPS_HFLAG_EXL;
1374
    else
1375
        env->hflags &= ~MIPS_HFLAG_EXL;
1376
    env->CP0_Status = val;
1377
    if (loglevel & CPU_LOG_TB_IN_ASM)
1378
       CALL_FROM_TB2(do_mtc0_status_debug, old, val);
1379
    CALL_FROM_TB1(cpu_mips_update_irq, env);
1380
    RETURN();
1381
}
1382

    
1383
void op_mtc0_intctl (void)
1384
{
1385
    /* vectored interrupts not implemented */
1386
    env->CP0_IntCtl = 0;
1387
    RETURN();
1388
}
1389

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

    
1397
void op_mtc0_srsmap (void)
1398
{
1399
    /* shadow registers not implemented */
1400
    env->CP0_SRSMap = 0;
1401
    RETURN();
1402
}
1403

    
1404
void op_mtc0_cause (void)
1405
{
1406
    env->CP0_Cause = (env->CP0_Cause & 0xB000F87C) | (T0 & 0x00C00300);
1407

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

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

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

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

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

    
1448
void op_mtc0_watchlo0 (void)
1449
{
1450
    env->CP0_WatchLo = (int32_t)T0;
1451
    RETURN();
1452
}
1453

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1624
void op_dmtc0_watchlo0 (void)
1625
{
1626
    env->CP0_WatchLo = T0;
1627
    RETURN();
1628
}
1629

    
1630
void op_dmtc0_xcontext (void)
1631
{
1632
    env->CP0_XContext = T0; /* XXX */
1633
    RETURN();
1634
}
1635

    
1636
void op_dmtc0_depc (void)
1637
{
1638
    env->CP0_DEPC = T0;
1639
    RETURN();
1640
}
1641

    
1642
void op_dmtc0_errorepc (void)
1643
{
1644
    env->CP0_ErrorEPC = T0;
1645
    RETURN();
1646
}
1647

    
1648
#ifdef MIPS_USES_FPU
1649

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

    
1656
void op_cp1_enabled(void)
1657
{
1658
    if (!(env->CP0_Status & (1 << CP0St_CU1))) {
1659
        CALL_FROM_TB2(do_raise_exception_err, EXCP_CpU, 1);
1660
    }
1661
    RETURN();
1662
}
1663

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

    
1678
/* convert MIPS rounding mode in FCR31 to IEEE library */
1679
unsigned int ieee_rm[] = { 
1680
    float_round_nearest_even,
1681
    float_round_to_zero,
1682
    float_round_up,
1683
    float_round_down
1684
};
1685

    
1686
#define RESTORE_ROUNDING_MODE \
1687
    set_float_rounding_mode(ieee_rm[env->fcr31 & 3], &env->fp_status)
1688

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

    
1701
        /* set rounding mode */
1702
        RESTORE_ROUNDING_MODE;
1703

    
1704
#ifndef CONFIG_SOFTFLOAT
1705
        /* no floating point exception for native float */
1706
        SET_FP_ENABLE(env->fcr31, 0);
1707
#endif
1708
    }
1709
    DEBUG_FPU_STATE();
1710
    RETURN();
1711
}
1712

    
1713
void op_mfc1 (void)
1714
{
1715
    T0 = WT0;
1716
    DEBUG_FPU_STATE();
1717
    RETURN();
1718
}
1719

    
1720
void op_mtc1 (void)
1721
{
1722
    WT0 = T0;
1723
    DEBUG_FPU_STATE();
1724
    RETURN();
1725
}
1726

    
1727
/* Float support.
1728
   Single precition routines have a "s" suffix, double precision a
1729
   "d" suffix.  */
1730

    
1731
#define FLOAT_OP(name, p) void OPPROTO op_float_##name##_##p(void)
1732

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

    
1770
FLOAT_OP(roundw, d)
1771
{
1772
    set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
1773
    WT2 = float64_round_to_int(FDT0, &env->fp_status);
1774
    RESTORE_ROUNDING_MODE;
1775

    
1776
    DEBUG_FPU_STATE();
1777
    RETURN();
1778
}
1779
FLOAT_OP(roundw, s)
1780
{
1781
    set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
1782
    WT2 = float32_round_to_int(FST0, &env->fp_status);
1783
    RESTORE_ROUNDING_MODE;
1784
    DEBUG_FPU_STATE();
1785
    RETURN();
1786
}
1787

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

    
1801
FLOAT_OP(ceilw, d)
1802
{
1803
    set_float_rounding_mode(float_round_up, &env->fp_status);
1804
    WT2 = float64_round_to_int(FDT0, &env->fp_status);
1805
    RESTORE_ROUNDING_MODE;
1806

    
1807
    DEBUG_FPU_STATE();
1808
    RETURN();
1809
}
1810
FLOAT_OP(ceilw, s)
1811
{
1812
    set_float_rounding_mode(float_round_up, &env->fp_status);
1813
    WT2 = float32_round_to_int(FST0, &env->fp_status);
1814
    RESTORE_ROUNDING_MODE;
1815
    DEBUG_FPU_STATE();
1816
    RETURN();
1817
}
1818

    
1819
FLOAT_OP(floorw, d)
1820
{
1821
    set_float_rounding_mode(float_round_down, &env->fp_status);
1822
    WT2 = float64_round_to_int(FDT0, &env->fp_status);
1823
    RESTORE_ROUNDING_MODE;
1824

    
1825
    DEBUG_FPU_STATE();
1826
    RETURN();
1827
}
1828
FLOAT_OP(floorw, s)
1829
{
1830
    set_float_rounding_mode(float_round_down, &env->fp_status);
1831
    WT2 = float32_round_to_int(FST0, &env->fp_status);
1832
    RESTORE_ROUNDING_MODE;
1833
    DEBUG_FPU_STATE();
1834
    RETURN();
1835
}
1836

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

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

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

    
1886
FLOAT_OP(mov, d)
1887
{
1888
    FDT2 = FDT0;
1889
    DEBUG_FPU_STATE();
1890
    RETURN();
1891
}
1892
FLOAT_OP(mov, s)
1893
{
1894
    FST2 = FST0;
1895
    DEBUG_FPU_STATE();
1896
    RETURN();
1897
}
1898

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

    
1909
extern void dump_fpu_s(CPUState *env);
1910

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

    
1925
int float64_is_unordered(float64 a, float64 b STATUS_PARAM)
1926
{
1927
    if (float64_is_nan(a) || float64_is_nan(b)) {
1928
        float_raise(float_flag_invalid, status);
1929
        return 1;
1930
    }
1931
    else {
1932
        return 0;
1933
    }
1934
}
1935

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

    
1956
flag float32_is_unordered(float32 a, float32 b STATUS_PARAM)
1957
{
1958
    extern flag float32_is_nan( float32 a );
1959
    if (float32_is_nan(a) || float32_is_nan(b)) {
1960
        float_raise(float_flag_invalid, status);
1961
        return 1;
1962
    }
1963
    else {
1964
        return 0;
1965
    }
1966
}
1967

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

    
1991
void op_bc1f (void)
1992
{
1993
    T0 = ! IS_FP_COND_SET(env->fcr31);
1994
    DEBUG_FPU_STATE();
1995
    RETURN();
1996
}
1997

    
1998
void op_bc1t (void)
1999
{
2000
    T0 = IS_FP_COND_SET(env->fcr31);
2001
    DEBUG_FPU_STATE();
2002
    RETURN();
2003
}
2004
#endif /* MIPS_USES_FPU */
2005

    
2006
#if defined(MIPS_USES_R4K_TLB)
2007
void op_tlbwi (void)
2008
{
2009
    CALL_FROM_TB0(do_tlbwi);
2010
    RETURN();
2011
}
2012

    
2013
void op_tlbwr (void)
2014
{
2015
    CALL_FROM_TB0(do_tlbwr);
2016
    RETURN();
2017
}
2018

    
2019
void op_tlbp (void)
2020
{
2021
    CALL_FROM_TB0(do_tlbp);
2022
    RETURN();
2023
}
2024

    
2025
void op_tlbr (void)
2026
{
2027
    CALL_FROM_TB0(do_tlbr);
2028
    RETURN();
2029
}
2030
#endif
2031

    
2032
/* Specials */
2033
void op_pmon (void)
2034
{
2035
    CALL_FROM_TB1(do_pmon, PARAM1);
2036
    RETURN();
2037
}
2038

    
2039
void op_di (void)
2040
{
2041
    T0 = env->CP0_Status;
2042
    env->CP0_Status = T0 & ~(1 << CP0St_IE);
2043
    CALL_FROM_TB1(cpu_mips_update_irq, env);
2044
    RETURN();
2045
}
2046

    
2047
void op_ei (void)
2048
{
2049
    T0 = env->CP0_Status;
2050
    env->CP0_Status = T0 | (1 << CP0St_IE);
2051
    CALL_FROM_TB1(cpu_mips_update_irq, env);
2052
    RETURN();
2053
}
2054

    
2055
void op_trap (void)
2056
{
2057
    if (T0) {
2058
        CALL_FROM_TB1(do_raise_exception_direct, EXCP_TRAP);
2059
    }
2060
    RETURN();
2061
}
2062

    
2063
void op_debug (void)
2064
{
2065
    CALL_FROM_TB1(do_raise_exception, EXCP_DEBUG);
2066
    RETURN();
2067
}
2068

    
2069
void op_set_lladdr (void)
2070
{
2071
    env->CP0_LLAddr = T2;
2072
    RETURN();
2073
}
2074

    
2075
void debug_eret (void);
2076
void op_eret (void)
2077
{
2078
    CALL_FROM_TB0(debug_eret);
2079
    if (env->hflags & MIPS_HFLAG_ERL) {
2080
        env->PC = env->CP0_ErrorEPC;
2081
        env->hflags &= ~MIPS_HFLAG_ERL;
2082
        env->CP0_Status &= ~(1 << CP0St_ERL);
2083
    } else {
2084
        env->PC = env->CP0_EPC;
2085
        env->hflags &= ~MIPS_HFLAG_EXL;
2086
        env->CP0_Status &= ~(1 << CP0St_EXL);
2087
    }
2088
    env->CP0_LLAddr = 1;
2089
    RETURN();
2090
}
2091

    
2092
void op_deret (void)
2093
{
2094
    CALL_FROM_TB0(debug_eret);
2095
    env->PC = env->CP0_DEPC;
2096
    RETURN();
2097
}
2098

    
2099
void op_rdhwr_cpunum(void)
2100
{
2101
    if (env->CP0_HWREna & (1 << 0))
2102
       T0 = env->CP0_EBase & 0x2ff;
2103
    else
2104
       CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI);
2105
    RETURN();
2106
}
2107

    
2108
void op_rdhwr_synci_step(void)
2109
{
2110
    if (env->CP0_HWREna & (1 << 1))
2111
       T0 = env->SYNCI_Step;
2112
    else
2113
       CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI);
2114
    RETURN();
2115
}
2116

    
2117
void op_rdhwr_cc(void)
2118
{
2119
    if (env->CP0_HWREna & (1 << 2))
2120
       T0 = env->CP0_Count;
2121
    else
2122
       CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI);
2123
    RETURN();
2124
}
2125

    
2126
void op_rdhwr_ccres(void)
2127
{
2128
    if (env->CP0_HWREna & (1 << 3))
2129
       T0 = env->CCRes;
2130
    else
2131
       CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI);
2132
    RETURN();
2133
}
2134

    
2135
void op_save_state (void)
2136
{
2137
    env->hflags = PARAM1;
2138
    RETURN();
2139
}
2140

    
2141
void op_save_pc (void)
2142
{
2143
    env->PC = PARAM1;
2144
    RETURN();
2145
}
2146

    
2147
void op_raise_exception (void)
2148
{
2149
    CALL_FROM_TB1(do_raise_exception, PARAM1);
2150
    RETURN();
2151
}
2152

    
2153
void op_raise_exception_err (void)
2154
{
2155
    CALL_FROM_TB2(do_raise_exception_err, PARAM1, PARAM2);
2156
    RETURN();
2157
}
2158

    
2159
void op_exit_tb (void)
2160
{
2161
    EXIT_TB();
2162
    RETURN();
2163
}
2164

    
2165
void op_wait (void)
2166
{
2167
    env->halted = 1;
2168
    CALL_FROM_TB1(do_raise_exception, EXCP_HLT);
2169
    RETURN();
2170
}
2171

    
2172
/* Bitfield operations. */
2173
void op_ext(void)
2174
{
2175
    unsigned int pos = PARAM1;
2176
    unsigned int size = PARAM2;
2177

    
2178
    T0 = ((uint32_t)T1 >> pos) & ((1 << size) - 1);
2179
    RETURN();
2180
}
2181

    
2182
void op_ins(void)
2183
{
2184
    unsigned int pos = PARAM1;
2185
    unsigned int size = PARAM2;
2186
    target_ulong mask = ((1 << size) - 1) << pos;
2187

    
2188
    T0 = (T2 & ~mask) | (((uint32_t)T1 << pos) & mask);
2189
    RETURN();
2190
}
2191

    
2192
void op_wsbh(void)
2193
{
2194
    T0 = ((T1 << 8) & ~0x00FF00FF) | ((T1 >> 8) & 0x00FF00FF);
2195
    RETURN();
2196
}
2197

    
2198
#ifdef MIPS_HAS_MIPS64
2199
void op_dext(void)
2200
{
2201
    unsigned int pos = PARAM1;
2202
    unsigned int size = PARAM2;
2203

    
2204
    T0 = (T1 >> pos) & ((1 << size) - 1);
2205
    RETURN();
2206
}
2207

    
2208
void op_dins(void)
2209
{
2210
    unsigned int pos = PARAM1;
2211
    unsigned int size = PARAM2;
2212
    target_ulong mask = ((1 << size) - 1) << pos;
2213

    
2214
    T0 = (T2 & ~mask) | ((T1 << pos) & mask);
2215
    RETURN();
2216
}
2217

    
2218
void op_dsbh(void)
2219
{
2220
    T0 = ((T1 << 8) & ~0x00FF00FF00FF00FFULL) | ((T1 >> 8) & 0x00FF00FF00FF00FFULL);
2221
    RETURN();
2222
}
2223

    
2224
void op_dshd(void)
2225
{
2226
    T0 = ((T1 << 16) & ~0x0000FFFF0000FFFFULL) | ((T1 >> 16) & 0x0000FFFF0000FFFFULL);
2227
    RETURN();
2228
}
2229
#endif
2230

    
2231
void op_seb(void)
2232
{
2233
    T0 = ((T1 & 0xFF) ^ 0x80) - 0x80;
2234
    RETURN();
2235
}
2236

    
2237
void op_seh(void)
2238
{
2239
    T0 = ((T1 & 0xFFFF) ^ 0x8000) - 0x8000;
2240
    RETURN();
2241
}