Statistics
| Branch: | Revision:

root / target-mips / op.c @ c570fd16

History | View | Annotate | Download (40 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 = SIGN_EXTEND32((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 = SIGN_EXTEND32(T0);
346
    RETURN();
347
}
348

    
349
void op_sub (void)
350
{
351
    T0 = SIGN_EXTEND32((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 = SIGN_EXTEND32(T0);
366
    RETURN();
367
}
368

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

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

    
384
void op_divu (void)
385
{
386
    if (T1 != 0) {
387
        env->LO = SIGN_EXTEND32((uint32_t)T0 / (uint32_t)T1);
388
        env->HI = SIGN_EXTEND32((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 = SIGN_EXTEND32((uint32_t)T0 << (uint32_t)T1);
501
    RETURN();
502
}
503

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

    
510
void op_srl (void)
511
{
512
    T0 = SIGN_EXTEND32((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 = SIGN_EXTEND32((uint32_t)T0 << (0x20 - (uint32_t)T1));
522
       T0 = SIGN_EXTEND32((uint32_t)T0 >> (uint32_t)T1) | tmp;
523
    } else
524
       T0 = T1;
525
    RETURN();
526
}
527

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

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

    
540
void op_srlv (void)
541
{
542
    T0 = SIGN_EXTEND32((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 = SIGN_EXTEND32((uint32_t)T1 << (0x20 - T0));
553
       T0 = SIGN_EXTEND32((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 = SIGN_EXTEND32(HILO & 0xFFFFFFFF);
846
    env->HI = SIGN_EXTEND32(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 = SIGN_EXTEND32(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 = env->CP0_EntryLo0;
1048
    RETURN();
1049
}
1050

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

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

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

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

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

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

    
1087
void op_mfc0_badvaddr (void)
1088
{
1089
    T0 = 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 = env->CP0_EntryHi;
1102
    RETURN();
1103
}
1104

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

    
1111
void op_mfc0_status (void)
1112
{
1113
    T0 = SIGN_EXTEND32(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 = SIGN_EXTEND32(env->CP0_IntCtl);
1126
    RETURN();
1127
}
1128

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

    
1135
void op_mfc0_cause (void)
1136
{
1137
    T0 = SIGN_EXTEND32(env->CP0_Cause);
1138
    RETURN();
1139
}
1140

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

    
1147
void op_mfc0_prid (void)
1148
{
1149
    T0 = SIGN_EXTEND32(env->CP0_PRid);
1150
    RETURN();
1151
}
1152

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

    
1159
void op_mfc0_config0 (void)
1160
{
1161
    T0 = SIGN_EXTEND32(env->CP0_Config0);
1162
    RETURN();
1163
}
1164

    
1165
void op_mfc0_config1 (void)
1166
{
1167
    T0 = SIGN_EXTEND32(env->CP0_Config1);
1168
    RETURN();
1169
}
1170

    
1171
void op_mfc0_config2 (void)
1172
{
1173
    T0 = SIGN_EXTEND32(env->CP0_Config2);
1174
    RETURN();
1175
}
1176

    
1177
void op_mfc0_config3 (void)
1178
{
1179
    T0 = SIGN_EXTEND32(env->CP0_Config3);
1180
    RETURN();
1181
}
1182

    
1183
void op_mfc0_lladdr (void)
1184
{
1185
    T0 = env->CP0_LLAddr >> 4;
1186
    RETURN();
1187
}
1188

    
1189
void op_mfc0_watchlo0 (void)
1190
{
1191
    T0 = SIGN_EXTEND32(env->CP0_WatchLo);
1192
    RETURN();
1193
}
1194

    
1195
void op_mfc0_watchhi0 (void)
1196
{
1197
    T0 = SIGN_EXTEND32(env->CP0_WatchHi);
1198
    RETURN();
1199
}
1200

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

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

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

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

    
1227
void op_mfc0_performance0 (void)
1228
{
1229
    T0 = SIGN_EXTEND32(env->CP0_Performance0);
1230
    RETURN();
1231
}
1232

    
1233
void op_mfc0_taglo (void)
1234
{
1235
    T0 = SIGN_EXTEND32(env->CP0_TagLo);
1236
    RETURN();
1237
}
1238

    
1239
void op_mfc0_datalo (void)
1240
{
1241
    T0 = SIGN_EXTEND32(env->CP0_DataLo);
1242
    RETURN();
1243
}
1244

    
1245
void op_mfc0_taghi (void)
1246
{
1247
    T0 = SIGN_EXTEND32(env->CP0_TagHi);
1248
    RETURN();
1249
}
1250

    
1251
void op_mfc0_datahi (void)
1252
{
1253
    T0 = SIGN_EXTEND32(env->CP0_DataHi);
1254
    RETURN();
1255
}
1256

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

    
1263
void op_mfc0_desave (void)
1264
{
1265
    T0 = SIGN_EXTEND32(env->CP0_DESAVE);
1266
    RETURN();
1267
}
1268

    
1269
void op_mtc0_index (void)
1270
{
1271
    env->CP0_index = (env->CP0_index & 0x80000000) | (T0 & (MIPS_TLB_NB - 1));
1272
    RETURN();
1273
}
1274

    
1275
void op_mtc0_entrylo0 (void)
1276
{
1277
    /* Large physaddr not implemented */
1278
    /* 1k pages not implemented */
1279
    env->CP0_EntryLo0 = T0 & SIGN_EXTEND32(0x3FFFFFFFUL);
1280
    RETURN();
1281
}
1282

    
1283
void op_mtc0_entrylo1 (void)
1284
{
1285
    /* Large physaddr not implemented */
1286
    /* 1k pages not implemented */
1287
    env->CP0_EntryLo1 = T0 & SIGN_EXTEND32(0x3FFFFFFFUL);
1288
    RETURN();
1289
}
1290

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

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

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

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

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

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

    
1331
void op_mtc0_entryhi (void)
1332
{
1333
    uint32_t old, val;
1334

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

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

    
1352
void op_mtc0_status (void)
1353
{
1354
    uint32_t val, old, mask;
1355

    
1356
    val = T0 & SIGN_EXTEND32(0xFA78FF01);
1357
    old = env->CP0_Status;
1358
    if (T0 & (1 << CP0St_UM))
1359
        env->hflags |= MIPS_HFLAG_UM;
1360
    else
1361
        env->hflags &= ~MIPS_HFLAG_UM;
1362
    if (T0 & (1 << CP0St_ERL))
1363
        env->hflags |= MIPS_HFLAG_ERL;
1364
    else
1365
        env->hflags &= ~MIPS_HFLAG_ERL;
1366
    if (T0 & (1 << CP0St_EXL))
1367
        env->hflags |= MIPS_HFLAG_EXL;
1368
    else
1369
        env->hflags &= ~MIPS_HFLAG_EXL;
1370
    env->CP0_Status = val;
1371
    /* If we unmasked an asserted IRQ, raise it */
1372
    mask = 0x0000FF00;
1373
    if (loglevel & CPU_LOG_TB_IN_ASM)
1374
       CALL_FROM_TB2(do_mtc0_status_debug, old, val);
1375
    if ((val & (1 << CP0St_IE)) && !(old & (1 << CP0St_IE)) &&
1376
        !(env->hflags & MIPS_HFLAG_EXL) &&
1377
        !(env->hflags & MIPS_HFLAG_ERL) &&
1378
        !(env->hflags & MIPS_HFLAG_DM) &&
1379
        (env->CP0_Status & env->CP0_Cause & mask)) {
1380
        env->interrupt_request |= CPU_INTERRUPT_HARD;
1381
       if (logfile)
1382
           CALL_FROM_TB0(do_mtc0_status_irqraise_debug);
1383
    } else if (!(val & (1 << CP0St_IE)) && (old & (1 << CP0St_IE))) {
1384
        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
1385
    }
1386
    RETURN();
1387
}
1388

    
1389
void op_mtc0_intctl (void)
1390
{
1391
    /* vectored interrupts not implemented */
1392
    env->CP0_IntCtl = 0;
1393
    RETURN();
1394
}
1395

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

    
1403
void op_mtc0_cause (void)
1404
{
1405
    uint32_t val, old;
1406

    
1407
    val = (env->CP0_Cause & 0xB000F87C) | (T0 & 0x00C00300);
1408
    old = env->CP0_Cause;
1409
    env->CP0_Cause = val;
1410
#if 0
1411
    {
1412
        int i, mask;
1413
       /* Check if we ever asserted a software IRQ */
1414
        for (i = 0; i < 2; i++) {
1415
            mask = 0x100 << i;
1416
            if ((val & mask) & !(old & mask))
1417
                CALL_FROM_TB1(mips_set_irq, i);
1418
        }
1419
    }
1420
#endif
1421
    RETURN();
1422
}
1423

    
1424
void op_mtc0_epc (void)
1425
{
1426
    env->CP0_EPC = T0;
1427
    RETURN();
1428
}
1429

    
1430
void op_mtc0_ebase (void)
1431
{
1432
    /* vectored interrupts not implemented */
1433
    /* Multi-CPU not implemented */
1434
    env->CP0_EBase = SIGN_EXTEND32(0x80000000) | (T0 & 0x3FFFF000);
1435
    RETURN();
1436
}
1437

    
1438
void op_mtc0_config0 (void)
1439
{
1440
#if defined(MIPS_USES_R4K_TLB)
1441
     /* Fixed mapping MMU not implemented */
1442
    env->CP0_Config0 = (env->CP0_Config0 & 0x8017FF88) | (T0 & 0x00000001);
1443
#else
1444
    env->CP0_Config0 = (env->CP0_Config0 & 0xFE17FF88) | (T0 & 0x00000001);
1445
#endif
1446
    RETURN();
1447
}
1448

    
1449
void op_mtc0_config2 (void)
1450
{
1451
    /* tertiary/secondary caches not implemented */
1452
    env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF);
1453
    RETURN();
1454
}
1455

    
1456
void op_mtc0_watchlo0 (void)
1457
{
1458
    env->CP0_WatchLo = T0;
1459
    RETURN();
1460
}
1461

    
1462
void op_mtc0_watchhi0 (void)
1463
{
1464
    env->CP0_WatchHi = T0 & 0x40FF0FF8;
1465
    RETURN();
1466
}
1467

    
1468
void op_mtc0_xcontext (void)
1469
{
1470
    env->CP0_XContext = T0; /* XXX */
1471
    RETURN();
1472
}
1473

    
1474
void op_mtc0_framemask (void)
1475
{
1476
    env->CP0_Framemask = T0; /* XXX */
1477
    RETURN();
1478
}
1479

    
1480
void op_mtc0_debug (void)
1481
{
1482
    env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120);
1483
    if (T0 & (1 << CP0DB_DM))
1484
        env->hflags |= MIPS_HFLAG_DM;
1485
    else
1486
        env->hflags &= ~MIPS_HFLAG_DM;
1487
    RETURN();
1488
}
1489

    
1490
void op_mtc0_depc (void)
1491
{
1492
    env->CP0_DEPC = T0;
1493
    RETURN();
1494
}
1495

    
1496
void op_mtc0_performance0 (void)
1497
{
1498
    env->CP0_Performance0 = T0; /* XXX */
1499
    RETURN();
1500
}
1501

    
1502
void op_mtc0_taglo (void)
1503
{
1504
    env->CP0_TagLo = T0 & SIGN_EXTEND32(0xFFFFFCF6);
1505
    RETURN();
1506
}
1507

    
1508
void op_mtc0_datalo (void)
1509
{
1510
    env->CP0_DataLo = T0; /* XXX */
1511
    RETURN();
1512
}
1513

    
1514
void op_mtc0_taghi (void)
1515
{
1516
    env->CP0_TagHi = T0; /* XXX */
1517
    RETURN();
1518
}
1519

    
1520
void op_mtc0_datahi (void)
1521
{
1522
    env->CP0_DataHi = T0; /* XXX */
1523
    RETURN();
1524
}
1525

    
1526
void op_mtc0_errorepc (void)
1527
{
1528
    env->CP0_ErrorEPC = T0;
1529
    RETURN();
1530
}
1531

    
1532
void op_mtc0_desave (void)
1533
{
1534
    env->CP0_DESAVE = T0;
1535
    RETURN();
1536
}
1537

    
1538
#ifdef MIPS_USES_FPU
1539

    
1540
#if 0
1541
# define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env)
1542
#else
1543
# define DEBUG_FPU_STATE() do { } while(0)
1544
#endif
1545

    
1546
void op_cp1_enabled(void)
1547
{
1548
    if (!(env->CP0_Status & (1 << CP0St_CU1))) {
1549
        CALL_FROM_TB2(do_raise_exception_err, EXCP_CpU, 1);
1550
    }
1551
    RETURN();
1552
}
1553

    
1554
/* CP1 functions */
1555
void op_cfc1 (void)
1556
{
1557
    if (T1 == 0) {
1558
        T0 = env->fcr0;
1559
    }
1560
    else {
1561
        /* fetch fcr31, masking unused bits */
1562
        T0 = env->fcr31 & 0x0183FFFF;
1563
    }
1564
    DEBUG_FPU_STATE();
1565
    RETURN();
1566
}
1567

    
1568
/* convert MIPS rounding mode in FCR31 to IEEE library */
1569
unsigned int ieee_rm[] = { 
1570
    float_round_nearest_even,
1571
    float_round_to_zero,
1572
    float_round_up,
1573
    float_round_down
1574
};
1575

    
1576
#define RESTORE_ROUNDING_MODE \
1577
    set_float_rounding_mode(ieee_rm[env->fcr31 & 3], &env->fp_status)
1578

    
1579
void op_ctc1 (void)
1580
{
1581
    if (T1 == 0) {
1582
        /* XXX should this throw an exception?
1583
         * don't write to FCR0.
1584
         * env->fcr0 = T0; 
1585
         */
1586
    }
1587
    else {
1588
        /* store new fcr31, masking unused bits */  
1589
        env->fcr31 = T0 & 0x0183FFFF;
1590

    
1591
        /* set rounding mode */
1592
        RESTORE_ROUNDING_MODE;
1593

    
1594
#ifndef CONFIG_SOFTFLOAT
1595
        /* no floating point exception for native float */
1596
        SET_FP_ENABLE(env->fcr31, 0);
1597
#endif
1598
    }
1599
    DEBUG_FPU_STATE();
1600
    RETURN();
1601
}
1602

    
1603
void op_mfc1 (void)
1604
{
1605
    T0 = WT0;
1606
    DEBUG_FPU_STATE();
1607
    RETURN();
1608
}
1609

    
1610
void op_mtc1 (void)
1611
{
1612
    WT0 = T0;
1613
    DEBUG_FPU_STATE();
1614
    RETURN();
1615
}
1616

    
1617
/* Float support.
1618
   Single precition routines have a "s" suffix, double precision a
1619
   "d" suffix.  */
1620

    
1621
#define FLOAT_OP(name, p) void OPPROTO op_float_##name##_##p(void)
1622

    
1623
FLOAT_OP(cvtd, s)
1624
{
1625
    FDT2 = float32_to_float64(WT0, &env->fp_status);
1626
    DEBUG_FPU_STATE();
1627
    RETURN();
1628
}
1629
FLOAT_OP(cvtd, w)
1630
{
1631
    FDT2 = int32_to_float64(WT0, &env->fp_status);
1632
    DEBUG_FPU_STATE();
1633
    RETURN();
1634
}
1635
FLOAT_OP(cvts, d)
1636
{
1637
    FST2 = float64_to_float32(FDT0, &env->fp_status);
1638
    DEBUG_FPU_STATE();
1639
    RETURN();
1640
}
1641
FLOAT_OP(cvts, w)
1642
{
1643
    FST2 = int32_to_float32(WT0, &env->fp_status);
1644
    DEBUG_FPU_STATE();
1645
    RETURN();
1646
}
1647
FLOAT_OP(cvtw, s)
1648
{
1649
    WT2 = float32_to_int32(FST0, &env->fp_status);
1650
    DEBUG_FPU_STATE();
1651
    RETURN();
1652
}
1653
FLOAT_OP(cvtw, d)
1654
{
1655
    WT2 = float64_to_int32(FDT0, &env->fp_status);
1656
    DEBUG_FPU_STATE();
1657
    RETURN();
1658
}
1659

    
1660
FLOAT_OP(roundw, d)
1661
{
1662
    set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
1663
    WT2 = float64_round_to_int(FDT0, &env->fp_status);
1664
    RESTORE_ROUNDING_MODE;
1665

    
1666
    DEBUG_FPU_STATE();
1667
    RETURN();
1668
}
1669
FLOAT_OP(roundw, s)
1670
{
1671
    set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
1672
    WT2 = float32_round_to_int(FST0, &env->fp_status);
1673
    RESTORE_ROUNDING_MODE;
1674
    DEBUG_FPU_STATE();
1675
    RETURN();
1676
}
1677

    
1678
FLOAT_OP(truncw, d)
1679
{
1680
    WT2 = float64_to_int32_round_to_zero(FDT0, &env->fp_status);
1681
    DEBUG_FPU_STATE();
1682
    RETURN();
1683
}
1684
FLOAT_OP(truncw, s)
1685
{
1686
    WT2 = float32_to_int32_round_to_zero(FST0, &env->fp_status);
1687
    DEBUG_FPU_STATE();
1688
    RETURN();
1689
}
1690

    
1691
FLOAT_OP(ceilw, d)
1692
{
1693
    set_float_rounding_mode(float_round_up, &env->fp_status);
1694
    WT2 = float64_round_to_int(FDT0, &env->fp_status);
1695
    RESTORE_ROUNDING_MODE;
1696

    
1697
    DEBUG_FPU_STATE();
1698
    RETURN();
1699
}
1700
FLOAT_OP(ceilw, s)
1701
{
1702
    set_float_rounding_mode(float_round_up, &env->fp_status);
1703
    WT2 = float32_round_to_int(FST0, &env->fp_status);
1704
    RESTORE_ROUNDING_MODE;
1705
    DEBUG_FPU_STATE();
1706
    RETURN();
1707
}
1708

    
1709
FLOAT_OP(floorw, d)
1710
{
1711
    set_float_rounding_mode(float_round_down, &env->fp_status);
1712
    WT2 = float64_round_to_int(FDT0, &env->fp_status);
1713
    RESTORE_ROUNDING_MODE;
1714

    
1715
    DEBUG_FPU_STATE();
1716
    RETURN();
1717
}
1718
FLOAT_OP(floorw, s)
1719
{
1720
    set_float_rounding_mode(float_round_down, &env->fp_status);
1721
    WT2 = float32_round_to_int(FST0, &env->fp_status);
1722
    RESTORE_ROUNDING_MODE;
1723
    DEBUG_FPU_STATE();
1724
    RETURN();
1725
}
1726

    
1727
/* binary operations */
1728
#define FLOAT_BINOP(name) \
1729
FLOAT_OP(name, d)         \
1730
{                         \
1731
    FDT2 = float64_ ## name (FDT0, FDT1, &env->fp_status);    \
1732
    DEBUG_FPU_STATE();    \
1733
}                         \
1734
FLOAT_OP(name, s)         \
1735
{                         \
1736
    FST2 = float32_ ## name (FST0, FST1, &env->fp_status);    \
1737
    DEBUG_FPU_STATE();    \
1738
}
1739
FLOAT_BINOP(add)
1740
FLOAT_BINOP(sub)
1741
FLOAT_BINOP(mul)
1742
FLOAT_BINOP(div)
1743
#undef FLOAT_BINOP
1744

    
1745
/* unary operations, modifying fp status  */
1746
#define FLOAT_UNOP(name)  \
1747
FLOAT_OP(name, d)         \
1748
{                         \
1749
    FDT2 = float64_ ## name(FDT0, &env->fp_status);   \
1750
    DEBUG_FPU_STATE();    \
1751
}                         \
1752
FLOAT_OP(name, s)         \
1753
{                         \
1754
    FST2 = float32_ ## name(FST0, &env->fp_status);   \
1755
    DEBUG_FPU_STATE();    \
1756
}
1757
FLOAT_UNOP(sqrt)
1758
#undef FLOAT_UNOP
1759

    
1760
/* unary operations, not modifying fp status  */
1761
#define FLOAT_UNOP(name)  \
1762
FLOAT_OP(name, d)         \
1763
{                         \
1764
    FDT2 = float64_ ## name(FDT0);   \
1765
    DEBUG_FPU_STATE();    \
1766
}                         \
1767
FLOAT_OP(name, s)         \
1768
{                         \
1769
    FST2 = float32_ ## name(FST0);   \
1770
    DEBUG_FPU_STATE();    \
1771
}
1772
FLOAT_UNOP(abs)
1773
FLOAT_UNOP(chs)
1774
#undef FLOAT_UNOP
1775

    
1776
FLOAT_OP(mov, d)
1777
{
1778
    FDT2 = FDT0;
1779
    DEBUG_FPU_STATE();
1780
    RETURN();
1781
}
1782
FLOAT_OP(mov, s)
1783
{
1784
    FST2 = FST0;
1785
    DEBUG_FPU_STATE();
1786
    RETURN();
1787
}
1788

    
1789
#ifdef CONFIG_SOFTFLOAT
1790
#define clear_invalid() do {                                \
1791
    int flags = get_float_exception_flags(&env->fp_status); \
1792
    flags &= ~float_flag_invalid;                           \
1793
    set_float_exception_flags(flags, &env->fp_status);      \
1794
} while(0)
1795
#else
1796
#define clear_invalid() do { } while(0)
1797
#endif
1798

    
1799
extern void dump_fpu_s(CPUState *env);
1800

    
1801
#define FOP_COND(fmt, op, sig, cond)           \
1802
void op_cmp_ ## fmt ## _ ## op (void)          \
1803
{                                              \
1804
    if (cond)                                  \
1805
        SET_FP_COND(env->fcr31);               \
1806
    else                                       \
1807
        CLEAR_FP_COND(env->fcr31);             \
1808
    if (!sig)                                  \
1809
        clear_invalid();                       \
1810
    /*CALL_FROM_TB1(dump_fpu_s, env);*/ \
1811
    DEBUG_FPU_STATE();                         \
1812
    RETURN();                                  \
1813
}
1814

    
1815
int float64_is_unordered(float64 a, float64 b STATUS_PARAM)
1816
{
1817
    if (float64_is_nan(a) || float64_is_nan(b)) {
1818
        float_raise(float_flag_invalid, status);
1819
        return 1;
1820
    }
1821
    else {
1822
        return 0;
1823
    }
1824
}
1825

    
1826
FOP_COND(d, f,   0,                                                      0) 
1827
FOP_COND(d, un,  0, float64_is_unordered(FDT1, FDT0, &env->fp_status))
1828
FOP_COND(d, eq,  0,                                                      float64_eq(FDT0, FDT1, &env->fp_status))
1829
FOP_COND(d, ueq, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status))
1830
FOP_COND(d, olt, 0,                                                      float64_lt(FDT0, FDT1, &env->fp_status))
1831
FOP_COND(d, ult, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status))
1832
FOP_COND(d, ole, 0,                                                      float64_le(FDT0, FDT1, &env->fp_status))
1833
FOP_COND(d, ule, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status))
1834
/* NOTE: the comma operator will make "cond" to eval to false,
1835
 * but float*_is_unordered() is still called
1836
 */
1837
FOP_COND(d, sf,  1,                                                      (float64_is_unordered(FDT0, FDT1, &env->fp_status), 0))
1838
FOP_COND(d, ngle,1, float64_is_unordered(FDT1, FDT0, &env->fp_status))
1839
FOP_COND(d, seq, 1,                                                      float64_eq(FDT0, FDT1, &env->fp_status))
1840
FOP_COND(d, ngl, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status))
1841
FOP_COND(d, lt,  1,                                                      float64_lt(FDT0, FDT1, &env->fp_status))
1842
FOP_COND(d, nge, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status))
1843
FOP_COND(d, le,  1,                                                      float64_le(FDT0, FDT1, &env->fp_status))
1844
FOP_COND(d, ngt, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status))
1845

    
1846
flag float32_is_unordered(float32 a, float32 b STATUS_PARAM)
1847
{
1848
    extern flag float32_is_nan( float32 a );
1849
    if (float32_is_nan(a) || float32_is_nan(b)) {
1850
        float_raise(float_flag_invalid, status);
1851
        return 1;
1852
    }
1853
    else {
1854
        return 0;
1855
    }
1856
}
1857

    
1858
/* NOTE: the comma operator will make "cond" to eval to false,
1859
 * but float*_is_unordered() is still called
1860
 */
1861
FOP_COND(s, f,   0,                                                      0) 
1862
FOP_COND(s, un,  0, float32_is_unordered(FST1, FST0, &env->fp_status))
1863
FOP_COND(s, eq,  0,                                                      float32_eq(FST0, FST1, &env->fp_status))
1864
FOP_COND(s, ueq, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status))
1865
FOP_COND(s, olt, 0,                                                      float32_lt(FST0, FST1, &env->fp_status))
1866
FOP_COND(s, ult, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status))
1867
FOP_COND(s, ole, 0,                                                      float32_le(FST0, FST1, &env->fp_status))
1868
FOP_COND(s, ule, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status))
1869
/* NOTE: the comma operator will make "cond" to eval to false,
1870
 * but float*_is_unordered() is still called
1871
 */
1872
FOP_COND(s, sf,  1,                                                      (float32_is_unordered(FST0, FST1, &env->fp_status), 0))
1873
FOP_COND(s, ngle,1, float32_is_unordered(FST1, FST0, &env->fp_status))
1874
FOP_COND(s, seq, 1,                                                      float32_eq(FST0, FST1, &env->fp_status))
1875
FOP_COND(s, ngl, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status))
1876
FOP_COND(s, lt,  1,                                                      float32_lt(FST0, FST1, &env->fp_status))
1877
FOP_COND(s, nge, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status))
1878
FOP_COND(s, le,  1,                                                      float32_le(FST0, FST1, &env->fp_status))
1879
FOP_COND(s, ngt, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status))
1880

    
1881
void op_bc1f (void)
1882
{
1883
    T0 = ! IS_FP_COND_SET(env->fcr31);
1884
    DEBUG_FPU_STATE();
1885
    RETURN();
1886
}
1887

    
1888
void op_bc1t (void)
1889
{
1890
    T0 = IS_FP_COND_SET(env->fcr31);
1891
    DEBUG_FPU_STATE();
1892
    RETURN();
1893
}
1894
#endif /* MIPS_USES_FPU */
1895

    
1896
#if defined(MIPS_USES_R4K_TLB)
1897
void op_tlbwi (void)
1898
{
1899
    CALL_FROM_TB0(do_tlbwi);
1900
    RETURN();
1901
}
1902

    
1903
void op_tlbwr (void)
1904
{
1905
    CALL_FROM_TB0(do_tlbwr);
1906
    RETURN();
1907
}
1908

    
1909
void op_tlbp (void)
1910
{
1911
    CALL_FROM_TB0(do_tlbp);
1912
    RETURN();
1913
}
1914

    
1915
void op_tlbr (void)
1916
{
1917
    CALL_FROM_TB0(do_tlbr);
1918
    RETURN();
1919
}
1920
#endif
1921

    
1922
/* Specials */
1923
void op_pmon (void)
1924
{
1925
    CALL_FROM_TB1(do_pmon, PARAM1);
1926
    RETURN();
1927
}
1928

    
1929
void op_di (void)
1930
{
1931
    uint32_t val;
1932

    
1933
    T0 = env->CP0_Status;
1934
    val = T0 & ~(1 << CP0St_IE);
1935
    if (val != T0) {
1936
        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
1937
        env->CP0_Status = val;
1938
    }
1939
    RETURN();
1940
}
1941

    
1942
void op_ei (void)
1943
{
1944
    uint32_t val;
1945

    
1946
    T0 = env->CP0_Status;
1947
    val = T0 | (1 << CP0St_IE);
1948
    if (val != T0) {
1949
       const uint32_t mask = 0x0000FF00;
1950

    
1951
       env->CP0_Status = val;
1952
       if (!(env->hflags & MIPS_HFLAG_EXL) &&
1953
           !(env->hflags & MIPS_HFLAG_ERL) &&
1954
           !(env->hflags & MIPS_HFLAG_DM) &&
1955
           (env->CP0_Status & env->CP0_Cause & mask)) {
1956
               env->interrupt_request |= CPU_INTERRUPT_HARD;
1957
               if (logfile)
1958
                   CALL_FROM_TB0(do_mtc0_status_irqraise_debug);
1959
       }
1960
    }
1961
    RETURN();
1962
}
1963

    
1964
void op_trap (void)
1965
{
1966
    if (T0) {
1967
        CALL_FROM_TB1(do_raise_exception_direct, EXCP_TRAP);
1968
    }
1969
    RETURN();
1970
}
1971

    
1972
void op_debug (void)
1973
{
1974
    CALL_FROM_TB1(do_raise_exception, EXCP_DEBUG);
1975
    RETURN();
1976
}
1977

    
1978
void op_set_lladdr (void)
1979
{
1980
    env->CP0_LLAddr = T2;
1981
    RETURN();
1982
}
1983

    
1984
void debug_eret (void);
1985
void op_eret (void)
1986
{
1987
    CALL_FROM_TB0(debug_eret);
1988
    if (env->hflags & MIPS_HFLAG_ERL) {
1989
        env->PC = env->CP0_ErrorEPC;
1990
        env->hflags &= ~MIPS_HFLAG_ERL;
1991
        env->CP0_Status &= ~(1 << CP0St_ERL);
1992
    } else {
1993
        env->PC = env->CP0_EPC;
1994
        env->hflags &= ~MIPS_HFLAG_EXL;
1995
        env->CP0_Status &= ~(1 << CP0St_EXL);
1996
    }
1997
    env->CP0_LLAddr = 1;
1998
    RETURN();
1999
}
2000

    
2001
void op_deret (void)
2002
{
2003
    CALL_FROM_TB0(debug_eret);
2004
    env->PC = env->CP0_DEPC;
2005
    RETURN();
2006
}
2007

    
2008
void op_rdhwr_cpunum(void)
2009
{
2010
    if (env->CP0_HWREna & (1 << 0))
2011
       T0 = env->CP0_EBase & 0x2ff;
2012
    else
2013
       CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI);
2014
    RETURN();
2015
}
2016

    
2017
void op_rdhwr_synci_step(void)
2018
{
2019
    if (env->CP0_HWREna & (1 << 1))
2020
       T0 = env->SYNCI_Step;
2021
    else
2022
       CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI);
2023
    RETURN();
2024
}
2025

    
2026
void op_rdhwr_cc(void)
2027
{
2028
    if (env->CP0_HWREna & (1 << 2))
2029
       T0 = env->CP0_Count;
2030
    else
2031
       CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI);
2032
    RETURN();
2033
}
2034

    
2035
void op_rdhwr_ccres(void)
2036
{
2037
    if (env->CP0_HWREna & (1 << 3))
2038
       T0 = env->CCRes;
2039
    else
2040
       CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI);
2041
    RETURN();
2042
}
2043

    
2044
void op_save_state (void)
2045
{
2046
    env->hflags = PARAM1;
2047
    RETURN();
2048
}
2049

    
2050
void op_save_pc (void)
2051
{
2052
    env->PC = PARAM1;
2053
    RETURN();
2054
}
2055

    
2056
void op_raise_exception (void)
2057
{
2058
    CALL_FROM_TB1(do_raise_exception, PARAM1);
2059
    RETURN();
2060
}
2061

    
2062
void op_raise_exception_err (void)
2063
{
2064
    CALL_FROM_TB2(do_raise_exception_err, PARAM1, PARAM2);
2065
    RETURN();
2066
}
2067

    
2068
void op_exit_tb (void)
2069
{
2070
    EXIT_TB();
2071
    RETURN();
2072
}
2073

    
2074
void op_wait (void)
2075
{
2076
    env->halted = 1;
2077
    CALL_FROM_TB1(do_raise_exception, EXCP_HLT);
2078
    RETURN();
2079
}
2080

    
2081
/* Bitfield operations. */
2082
void op_ext(void)
2083
{
2084
    unsigned int pos = PARAM1;
2085
    unsigned int size = PARAM2;
2086

    
2087
    T0 = ((uint32_t)T1 >> pos) & ((1 << size) - 1);
2088
    RETURN();
2089
}
2090

    
2091
void op_ins(void)
2092
{
2093
    unsigned int pos = PARAM1;
2094
    unsigned int size = PARAM2;
2095
    target_ulong mask = ((1 << size) - 1) << pos;
2096

    
2097
    T0 = (T2 & ~mask) | (((uint32_t)T1 << pos) & mask);
2098
    RETURN();
2099
}
2100

    
2101
void op_wsbh(void)
2102
{
2103
    T0 = ((T1 << 8) & ~0x00FF00FF) | ((T1 >> 8) & 0x00FF00FF);
2104
    RETURN();
2105
}
2106

    
2107
#ifdef MIPS_HAS_MIPS64
2108
void op_dext(void)
2109
{
2110
    unsigned int pos = PARAM1;
2111
    unsigned int size = PARAM2;
2112

    
2113
    T0 = (T1 >> pos) & ((1 << size) - 1);
2114
    RETURN();
2115
}
2116

    
2117
void op_dins(void)
2118
{
2119
    unsigned int pos = PARAM1;
2120
    unsigned int size = PARAM2;
2121
    target_ulong mask = ((1 << size) - 1) << pos;
2122

    
2123
    T0 = (T2 & ~mask) | ((T1 << pos) & mask);
2124
    RETURN();
2125
}
2126

    
2127
void op_dsbh(void)
2128
{
2129
    T0 = ((T1 << 8) & ~0x00FF00FF00FF00FFULL) | ((T1 >> 8) & 0x00FF00FF00FF00FFULL);
2130
    RETURN();
2131
}
2132

    
2133
void op_dshd(void)
2134
{
2135
    T0 = ((T1 << 16) & ~0x0000FFFF0000FFFFULL) | ((T1 >> 16) & 0x0000FFFF0000FFFFULL);
2136
    RETURN();
2137
}
2138
#endif
2139

    
2140
void op_seb(void)
2141
{
2142
    T0 = ((T1 & 0xFF) ^ 0x80) - 0x80;
2143
    RETURN();
2144
}
2145

    
2146
void op_seh(void)
2147
{
2148
    T0 = ((T1 & 0xFFFF) ^ 0x8000) - 0x8000;
2149
    RETURN();
2150
}