Statistics
| Branch: | Revision:

root / target-mips / op.c @ 179e32bb

History | View | Annotate | Download (34.5 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 T0
144
#include "op_template.c"
145
#undef TN
146
#define TN T1
147
#include "op_template.c"
148
#undef TN
149
#define TN T2
150
#include "op_template.c"
151
#undef TN
152

    
153
#ifdef MIPS_USES_FPU
154

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

    
284
#define FTN
285
#include "fop_template.c"
286
#undef FTN
287

    
288
#endif
289

    
290
void op_dup_T0 (void)
291
{
292
    T2 = T0;
293
    RETURN();
294
}
295

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

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

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

    
314
void op_store_LO (void)
315
{
316
    env->LO = T0;
317
    RETURN();
318
}
319

    
320
/* Load and store */
321
#define MEMSUFFIX _raw
322
#include "op_mem.c"
323
#undef MEMSUFFIX
324
#if !defined(CONFIG_USER_ONLY)
325
#define MEMSUFFIX _user
326
#include "op_mem.c"
327
#undef MEMSUFFIX
328

    
329
#define MEMSUFFIX _kernel
330
#include "op_mem.c"
331
#undef MEMSUFFIX
332
#endif
333

    
334
/* Arithmetic */
335
void op_add (void)
336
{
337
    T0 += T1;
338
    RETURN();
339
}
340

    
341
void op_addo (void)
342
{
343
    target_ulong tmp;
344

    
345
    tmp = T0;
346
    T0 += T1;
347
    if (((tmp ^ T1 ^ (-1)) & (T0 ^ T1)) >> 31) {
348
       /* operands of same sign, result different sign */
349
        CALL_FROM_TB1(do_raise_exception_direct, EXCP_OVERFLOW);
350
    }
351
    RETURN();
352
}
353

    
354
void op_sub (void)
355
{
356
    T0 -= T1;
357
    RETURN();
358
}
359

    
360
void op_subo (void)
361
{
362
    target_ulong tmp;
363

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

    
373
void op_mul (void)
374
{
375
    T0 = (int32_t)T0 * (int32_t)T1;
376
    RETURN();
377
}
378

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

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

    
397
/* Logical */
398
void op_and (void)
399
{
400
    T0 &= T1;
401
    RETURN();
402
}
403

    
404
void op_nor (void)
405
{
406
    T0 = ~(T0 | T1);
407
    RETURN();
408
}
409

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

    
416
void op_xor (void)
417
{
418
    T0 ^= T1;
419
    RETURN();
420
}
421

    
422
void op_sll (void)
423
{
424
    T0 = T0 << T1;
425
    RETURN();
426
}
427

    
428
void op_sra (void)
429
{
430
    T0 = (int32_t)T0 >> T1;
431
    RETURN();
432
}
433

    
434
void op_srl (void)
435
{
436
    T0 = T0 >> T1;
437
    RETURN();
438
}
439

    
440
void op_rotr (void)
441
{
442
    target_ulong tmp;
443

    
444
    if (T1) {
445
       tmp = T0 << (0x20 - T1);
446
       T0 = (T0 >> T1) | tmp;
447
    } else
448
       T0 = T1;
449
    RETURN();
450
}
451

    
452
void op_sllv (void)
453
{
454
    T0 = T1 << (T0 & 0x1F);
455
    RETURN();
456
}
457

    
458
void op_srav (void)
459
{
460
    T0 = (int32_t)T1 >> (T0 & 0x1F);
461
    RETURN();
462
}
463

    
464
void op_srlv (void)
465
{
466
    T0 = T1 >> (T0 & 0x1F);
467
    RETURN();
468
}
469

    
470
void op_rotrv (void)
471
{
472
    target_ulong tmp;
473

    
474
    T0 &= 0x1F;
475
    if (T0) {
476
       tmp = T1 << (0x20 - T0);
477
       T0 = (T1 >> T0) | tmp;
478
    } else
479
       T0 = T1;
480
    RETURN();
481
}
482

    
483
void op_clo (void)
484
{
485
    int n;
486

    
487
    if (T0 == (target_ulong)-1) {
488
        T0 = 32;
489
    } else {
490
        for (n = 0; n < 32; n++) {
491
            if (!(T0 & (1 << 31)))
492
                break;
493
            T0 = T0 << 1;
494
        }
495
        T0 = n;
496
    }
497
    RETURN();
498
}
499

    
500
void op_clz (void)
501
{
502
    int n;
503

    
504
    if (T0 == 0) {
505
        T0 = 32;
506
    } else {
507
        for (n = 0; n < 32; n++) {
508
            if (T0 & (1 << 31))
509
                break;
510
            T0 = T0 << 1;
511
        }
512
        T0 = n;
513
    }
514
    RETURN();
515
}
516

    
517
/* 64 bits arithmetic */
518
#if (HOST_LONG_BITS == 64)
519
static inline uint64_t get_HILO (void)
520
{
521
    return ((uint64_t)env->HI << 32) | (uint64_t)env->LO;
522
}
523

    
524
static inline void set_HILO (uint64_t HILO)
525
{
526
    env->LO = HILO & 0xFFFFFFFF;
527
    env->HI = HILO >> 32;
528
}
529

    
530
void op_mult (void)
531
{
532
    set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
533
    RETURN();
534
}
535

    
536
void op_multu (void)
537
{
538
    set_HILO((uint64_t)T0 * (uint64_t)T1);
539
    RETURN();
540
}
541

    
542
void op_madd (void)
543
{
544
    int64_t tmp;
545

    
546
    tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
547
    set_HILO((int64_t)get_HILO() + tmp);
548
    RETURN();
549
}
550

    
551
void op_maddu (void)
552
{
553
    uint64_t tmp;
554

    
555
    tmp = ((uint64_t)T0 * (uint64_t)T1);
556
    set_HILO(get_HILO() + tmp);
557
    RETURN();
558
}
559

    
560
void op_msub (void)
561
{
562
    int64_t tmp;
563

    
564
    tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
565
    set_HILO((int64_t)get_HILO() - tmp);
566
    RETURN();
567
}
568

    
569
void op_msubu (void)
570
{
571
    uint64_t tmp;
572

    
573
    tmp = ((uint64_t)T0 * (uint64_t)T1);
574
    set_HILO(get_HILO() - tmp);
575
    RETURN();
576
}
577
#else
578
void op_mult (void)
579
{
580
    CALL_FROM_TB0(do_mult);
581
    RETURN();
582
}
583

    
584
void op_multu (void)
585
{
586
    CALL_FROM_TB0(do_multu);
587
    RETURN();
588
}
589

    
590
void op_madd (void)
591
{
592
    CALL_FROM_TB0(do_madd);
593
    RETURN();
594
}
595

    
596
void op_maddu (void)
597
{
598
    CALL_FROM_TB0(do_maddu);
599
    RETURN();
600
}
601

    
602
void op_msub (void)
603
{
604
    CALL_FROM_TB0(do_msub);
605
    RETURN();
606
}
607

    
608
void op_msubu (void)
609
{
610
    CALL_FROM_TB0(do_msubu);
611
    RETURN();
612
}
613
#endif
614

    
615
/* Conditional moves */
616
void op_movn (void)
617
{
618
    if (T1 != 0)
619
        env->gpr[PARAM1] = T0;
620
    RETURN();
621
}
622

    
623
void op_movz (void)
624
{
625
    if (T1 == 0)
626
        env->gpr[PARAM1] = T0;
627
    RETURN();
628
}
629

    
630
#ifdef MIPS_USES_FPU
631
void op_movf (void)
632
{
633
    if (!(env->fcr31 & PARAM1))
634
        env->gpr[PARAM2] = env->gpr[PARAM3];
635
    RETURN();
636
}
637

    
638
void op_movt (void)
639
{
640
    if (env->fcr31 & PARAM1)
641
        env->gpr[PARAM2] = env->gpr[PARAM3];
642
    RETURN();
643
}
644
#endif
645

    
646
/* Tests */
647
#define OP_COND(name, cond) \
648
void glue(op_, name) (void) \
649
{                           \
650
    if (cond) {             \
651
        T0 = 1;             \
652
    } else {                \
653
        T0 = 0;             \
654
    }                       \
655
    RETURN();               \
656
}
657

    
658
OP_COND(eq, T0 == T1);
659
OP_COND(ne, T0 != T1);
660
OP_COND(ge, (int32_t)T0 >= (int32_t)T1);
661
OP_COND(geu, T0 >= T1);
662
OP_COND(lt, (int32_t)T0 < (int32_t)T1);
663
OP_COND(ltu, T0 < T1);
664
OP_COND(gez, (int32_t)T0 >= 0);
665
OP_COND(gtz, (int32_t)T0 > 0);
666
OP_COND(lez, (int32_t)T0 <= 0);
667
OP_COND(ltz, (int32_t)T0 < 0);
668

    
669
/* Branches */
670
//#undef USE_DIRECT_JUMP
671

    
672
void OPPROTO op_goto_tb0(void)
673
{
674
    GOTO_TB(op_goto_tb0, PARAM1, 0);
675
    RETURN();
676
}
677

    
678
void OPPROTO op_goto_tb1(void)
679
{
680
    GOTO_TB(op_goto_tb1, PARAM1, 1);
681
    RETURN();
682
}
683

    
684
/* Branch to register */
685
void op_save_breg_target (void)
686
{
687
    env->btarget = T2;
688
    RETURN();
689
}
690

    
691
void op_restore_breg_target (void)
692
{
693
    T2 = env->btarget;
694
    RETURN();
695
}
696

    
697
void op_breg (void)
698
{
699
    env->PC = T2;
700
    RETURN();
701
}
702

    
703
void op_save_btarget (void)
704
{
705
    env->btarget = PARAM1;
706
    RETURN();
707
}
708

    
709
/* Conditional branch */
710
void op_set_bcond (void)
711
{
712
    T2 = T0;
713
    RETURN();
714
}
715

    
716
void op_save_bcond (void)
717
{
718
    env->bcond = T2;
719
    RETURN();
720
}
721

    
722
void op_restore_bcond (void)
723
{
724
    T2 = env->bcond;
725
    RETURN();
726
}
727

    
728
void op_jnz_T2 (void)
729
{
730
    if (T2)
731
        GOTO_LABEL_PARAM(1);
732
    RETURN();
733
}
734

    
735
/* CP0 functions */
736
void op_mfc0_index (void)
737
{
738
    T0 = env->CP0_index;
739
    RETURN();
740
}
741

    
742
void op_mfc0_random (void)
743
{
744
    CALL_FROM_TB0(do_mfc0_random);
745
    RETURN();
746
}
747

    
748
void op_mfc0_entrylo0 (void)
749
{
750
    T0 = env->CP0_EntryLo0;
751
    RETURN();
752
}
753

    
754
void op_mfc0_entrylo1 (void)
755
{
756
    T0 = env->CP0_EntryLo1;
757
    RETURN();
758
}
759

    
760
void op_mfc0_context (void)
761
{
762
    T0 = env->CP0_Context;
763
    RETURN();
764
}
765

    
766
void op_mfc0_pagemask (void)
767
{
768
    T0 = env->CP0_PageMask;
769
    RETURN();
770
}
771

    
772
void op_mfc0_pagegrain (void)
773
{
774
    T0 = env->CP0_PageGrain;
775
    RETURN();
776
}
777

    
778
void op_mfc0_wired (void)
779
{
780
    T0 = env->CP0_Wired;
781
    RETURN();
782
}
783

    
784
void op_mfc0_hwrena (void)
785
{
786
    T0 = env->CP0_HWREna;
787
    RETURN();
788
}
789

    
790
void op_mfc0_badvaddr (void)
791
{
792
    T0 = env->CP0_BadVAddr;
793
    RETURN();
794
}
795

    
796
void op_mfc0_count (void)
797
{
798
    CALL_FROM_TB0(do_mfc0_count);
799
    RETURN();
800
}
801

    
802
void op_mfc0_entryhi (void)
803
{
804
    T0 = env->CP0_EntryHi;
805
    RETURN();
806
}
807

    
808
void op_mfc0_compare (void)
809
{
810
    T0 = env->CP0_Compare;
811
    RETURN();
812
}
813

    
814
void op_mfc0_status (void)
815
{
816
    T0 = env->CP0_Status;
817
    if (env->hflags & MIPS_HFLAG_UM)
818
        T0 |= (1 << CP0St_UM);
819
    if (env->hflags & MIPS_HFLAG_ERL)
820
        T0 |= (1 << CP0St_ERL);
821
    if (env->hflags & MIPS_HFLAG_EXL)
822
        T0 |= (1 << CP0St_EXL);
823
    RETURN();
824
}
825

    
826
void op_mfc0_intctl (void)
827
{
828
    T0 = env->CP0_IntCtl;
829
    RETURN();
830
}
831

    
832
void op_mfc0_srsctl (void)
833
{
834
    T0 = env->CP0_SRSCtl;
835
    RETURN();
836
}
837

    
838
void op_mfc0_cause (void)
839
{
840
    T0 = env->CP0_Cause;
841
    RETURN();
842
}
843

    
844
void op_mfc0_epc (void)
845
{
846
    T0 = env->CP0_EPC;
847
    RETURN();
848
}
849

    
850
void op_mfc0_prid (void)
851
{
852
    T0 = env->CP0_PRid;
853
    RETURN();
854
}
855

    
856
void op_mfc0_ebase (void)
857
{
858
    T0 = env->CP0_EBase;
859
    RETURN();
860
}
861

    
862
void op_mfc0_config0 (void)
863
{
864
    T0 = env->CP0_Config0;
865
    RETURN();
866
}
867

    
868
void op_mfc0_config1 (void)
869
{
870
    T0 = env->CP0_Config1;
871
    RETURN();
872
}
873

    
874
void op_mfc0_config2 (void)
875
{
876
    T0 = env->CP0_Config2;
877
    RETURN();
878
}
879

    
880
void op_mfc0_config3 (void)
881
{
882
    T0 = env->CP0_Config3;
883
    RETURN();
884
}
885

    
886
void op_mfc0_lladdr (void)
887
{
888
    T0 = env->CP0_LLAddr >> 4;
889
    RETURN();
890
}
891

    
892
void op_mfc0_watchlo0 (void)
893
{
894
    T0 = env->CP0_WatchLo;
895
    RETURN();
896
}
897

    
898
void op_mfc0_watchhi0 (void)
899
{
900
    T0 = env->CP0_WatchHi;
901
    RETURN();
902
}
903

    
904
void op_mfc0_xcontext (void)
905
{
906
    T0 = env->CP0_XContext;
907
    RETURN();
908
}
909

    
910
void op_mfc0_framemask (void)
911
{
912
    T0 = env->CP0_Framemask;
913
    RETURN();
914
}
915

    
916
void op_mfc0_debug (void)
917
{
918
    T0 = env->CP0_Debug;
919
    if (env->hflags & MIPS_HFLAG_DM)
920
        T0 |= 1 << CP0DB_DM;
921
    RETURN();
922
}
923

    
924
void op_mfc0_depc (void)
925
{
926
    T0 = env->CP0_DEPC;
927
    RETURN();
928
}
929

    
930
void op_mfc0_performance0 (void)
931
{
932
    T0 = env->CP0_Performance0;
933
    RETURN();
934
}
935

    
936
void op_mfc0_taglo (void)
937
{
938
    T0 = env->CP0_TagLo;
939
    RETURN();
940
}
941

    
942
void op_mfc0_datalo (void)
943
{
944
    T0 = env->CP0_DataLo;
945
    RETURN();
946
}
947

    
948
void op_mfc0_taghi (void)
949
{
950
    T0 = env->CP0_TagHi;
951
    RETURN();
952
}
953

    
954
void op_mfc0_datahi (void)
955
{
956
    T0 = env->CP0_DataHi;
957
    RETURN();
958
}
959

    
960
void op_mfc0_errorepc (void)
961
{
962
    T0 = env->CP0_ErrorEPC;
963
    RETURN();
964
}
965

    
966
void op_mfc0_desave (void)
967
{
968
    T0 = env->CP0_DESAVE;
969
    RETURN();
970
}
971

    
972
void op_mtc0_index (void)
973
{
974
    env->CP0_index = (env->CP0_index & 0x80000000) | (T0 & (MIPS_TLB_NB - 1));
975
    RETURN();
976
}
977

    
978
void op_mtc0_entrylo0 (void)
979
{
980
    /* Large physaddr not implemented */
981
    /* 1k pages not implemented */
982
    env->CP0_EntryLo0 = T0 & 0x3FFFFFFFUL;
983
    RETURN();
984
}
985

    
986
void op_mtc0_entrylo1 (void)
987
{
988
    /* Large physaddr not implemented */
989
    /* 1k pages not implemented */
990
    env->CP0_EntryLo1 = T0 & 0x3FFFFFFFUL;
991
    RETURN();
992
}
993

    
994
void op_mtc0_context (void)
995
{
996
    env->CP0_Context = (env->CP0_Context & ~0x007FFFFF) | (T0 & 0x007FFFF0);
997
    RETURN();
998
}
999

    
1000
void op_mtc0_pagemask (void)
1001
{
1002
    /* 1k pages not implemented */
1003
    env->CP0_PageMask = T0 & 0x1FFFE000;
1004
    RETURN();
1005
}
1006

    
1007
void op_mtc0_pagegrain (void)
1008
{
1009
    /* SmartMIPS not implemented */
1010
    /* Large physaddr not implemented */
1011
    /* 1k pages not implemented */
1012
    env->CP0_PageGrain = 0;
1013
    RETURN();
1014
}
1015

    
1016
void op_mtc0_wired (void)
1017
{
1018
    env->CP0_Wired = T0 & (MIPS_TLB_NB - 1);
1019
    RETURN();
1020
}
1021

    
1022
void op_mtc0_hwrena (void)
1023
{
1024
    env->CP0_HWREna = T0 & 0x0000000F;
1025
    RETURN();
1026
}
1027

    
1028
void op_mtc0_count (void)
1029
{
1030
    CALL_FROM_TB2(cpu_mips_store_count, env, T0);
1031
    RETURN();
1032
}
1033

    
1034
void op_mtc0_entryhi (void)
1035
{
1036
    uint32_t old, val;
1037

    
1038
    /* 1k pages not implemented */
1039
    /* Ignore MIPS64 TLB for now */
1040
    val = T0 & 0xFFFFE0FF;
1041
    old = env->CP0_EntryHi;
1042
    env->CP0_EntryHi = val;
1043
    /* If the ASID changes, flush qemu's TLB.  */
1044
    if ((old & 0xFF) != (val & 0xFF))
1045
        CALL_FROM_TB2(cpu_mips_tlb_flush, env, 1);
1046
    RETURN();
1047
}
1048

    
1049
void op_mtc0_compare (void)
1050
{
1051
    CALL_FROM_TB2(cpu_mips_store_compare, env, T0);
1052
    RETURN();
1053
}
1054

    
1055
void op_mtc0_status (void)
1056
{
1057
    uint32_t val, old, mask;
1058

    
1059
    val = T0 & 0xFA78FF01;
1060
    old = env->CP0_Status;
1061
    if (T0 & (1 << CP0St_UM))
1062
        env->hflags |= MIPS_HFLAG_UM;
1063
    else
1064
        env->hflags &= ~MIPS_HFLAG_UM;
1065
    if (T0 & (1 << CP0St_ERL))
1066
        env->hflags |= MIPS_HFLAG_ERL;
1067
    else
1068
        env->hflags &= ~MIPS_HFLAG_ERL;
1069
    if (T0 & (1 << CP0St_EXL))
1070
        env->hflags |= MIPS_HFLAG_EXL;
1071
    else
1072
        env->hflags &= ~MIPS_HFLAG_EXL;
1073
    env->CP0_Status = val;
1074
    /* If we unmasked an asserted IRQ, raise it */
1075
    mask = 0x0000FF00;
1076
    if (loglevel & CPU_LOG_TB_IN_ASM)
1077
       CALL_FROM_TB2(do_mtc0_status_debug, old, val);
1078
    if ((val & (1 << CP0St_IE)) && !(old & (1 << CP0St_IE)) &&
1079
        !(env->hflags & MIPS_HFLAG_EXL) &&
1080
        !(env->hflags & MIPS_HFLAG_ERL) &&
1081
        !(env->hflags & MIPS_HFLAG_DM) &&
1082
        (env->CP0_Status & env->CP0_Cause & mask)) {
1083
        env->interrupt_request |= CPU_INTERRUPT_HARD;
1084
       if (logfile)
1085
           CALL_FROM_TB0(do_mtc0_status_irqraise_debug);
1086
    } else if (!(val & (1 << CP0St_IE)) && (old & (1 << CP0St_IE))) {
1087
        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
1088
    }
1089
    RETURN();
1090
}
1091

    
1092
void op_mtc0_intctl (void)
1093
{
1094
    /* vectored interrupts not implemented */
1095
    env->CP0_IntCtl = 0;
1096
    RETURN();
1097
}
1098

    
1099
void op_mtc0_srsctl (void)
1100
{
1101
    /* shadow registers not implemented */
1102
    env->CP0_SRSCtl = 0;
1103
    RETURN();
1104
}
1105

    
1106
void op_mtc0_cause (void)
1107
{
1108
    uint32_t val, old;
1109

    
1110
    val = (env->CP0_Cause & 0xB000F87C) | (T0 & 0x000C00300);
1111
    old = env->CP0_Cause;
1112
    env->CP0_Cause = val;
1113
#if 0
1114
    {
1115
        int i, mask;
1116
       /* Check if we ever asserted a software IRQ */
1117
        for (i = 0; i < 2; i++) {
1118
            mask = 0x100 << i;
1119
            if ((val & mask) & !(old & mask))
1120
                CALL_FROM_TB1(mips_set_irq, i);
1121
        }
1122
    }
1123
#endif
1124
    RETURN();
1125
}
1126

    
1127
void op_mtc0_epc (void)
1128
{
1129
    env->CP0_EPC = T0;
1130
    RETURN();
1131
}
1132

    
1133
void op_mtc0_ebase (void)
1134
{
1135
    /* vectored interrupts not implemented */
1136
    /* Multi-CPU not implemented */
1137
    env->CP0_EBase = 0x80000000 | (T0 & 0x3FFFF000);
1138
    RETURN();
1139
}
1140

    
1141
void op_mtc0_config0 (void)
1142
{
1143
#if defined(MIPS_USES_R4K_TLB)
1144
     /* Fixed mapping MMU not implemented */
1145
    env->CP0_Config0 = (env->CP0_Config0 & 0x8017FF88) | (T0 & 0x00000001);
1146
#else
1147
    env->CP0_Config0 = (env->CP0_Config0 & 0xFE17FF88) | (T0 & 0x00000001);
1148
#endif
1149
    RETURN();
1150
}
1151

    
1152
void op_mtc0_config2 (void)
1153
{
1154
    /* tertiary/secondary caches not implemented */
1155
    env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF);
1156
    RETURN();
1157
}
1158

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

    
1165
void op_mtc0_watchhi0 (void)
1166
{
1167
    env->CP0_WatchHi = T0 & 0x40FF0FF8;
1168
    RETURN();
1169
}
1170

    
1171
void op_mtc0_xcontext (void)
1172
{
1173
    env->CP0_XContext = T0; /* XXX */
1174
    RETURN();
1175
}
1176

    
1177
void op_mtc0_framemask (void)
1178
{
1179
    env->CP0_Framemask = T0; /* XXX */
1180
    RETURN();
1181
}
1182

    
1183
void op_mtc0_debug (void)
1184
{
1185
    env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120);
1186
    if (T0 & (1 << CP0DB_DM))
1187
        env->hflags |= MIPS_HFLAG_DM;
1188
    else
1189
        env->hflags &= ~MIPS_HFLAG_DM;
1190
    RETURN();
1191
}
1192

    
1193
void op_mtc0_depc (void)
1194
{
1195
    env->CP0_DEPC = T0;
1196
    RETURN();
1197
}
1198

    
1199
void op_mtc0_performance0 (void)
1200
{
1201
    env->CP0_Performance0 = T0; /* XXX */
1202
    RETURN();
1203
}
1204

    
1205
void op_mtc0_taglo (void)
1206
{
1207
    env->CP0_TagLo = T0 & 0xFFFFFCF6;
1208
    RETURN();
1209
}
1210

    
1211
void op_mtc0_datalo (void)
1212
{
1213
    env->CP0_DataLo = T0; /* XXX */
1214
    RETURN();
1215
}
1216

    
1217
void op_mtc0_taghi (void)
1218
{
1219
    env->CP0_TagHi = T0; /* XXX */
1220
    RETURN();
1221
}
1222

    
1223
void op_mtc0_datahi (void)
1224
{
1225
    env->CP0_DataHi = T0; /* XXX */
1226
    RETURN();
1227
}
1228

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

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

    
1241
#ifdef MIPS_USES_FPU
1242

    
1243
#if 0
1244
# define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env)
1245
#else
1246
# define DEBUG_FPU_STATE() do { } while(0)
1247
#endif
1248

    
1249
void op_cp1_enabled(void)
1250
{
1251
    if (!(env->CP0_Status & (1 << CP0St_CU1))) {
1252
        CALL_FROM_TB2(do_raise_exception_err, EXCP_CpU, 1);
1253
    }
1254
    RETURN();
1255
}
1256

    
1257
/* CP1 functions */
1258
void op_cfc1 (void)
1259
{
1260
    if (T1 == 0) {
1261
        T0 = env->fcr0;
1262
    }
1263
    else {
1264
        /* fetch fcr31, masking unused bits */
1265
        T0 = env->fcr31 & 0x0183FFFF;
1266
    }
1267
    DEBUG_FPU_STATE();
1268
    RETURN();
1269
}
1270

    
1271
/* convert MIPS rounding mode in FCR31 to IEEE library */
1272
unsigned int ieee_rm[] = { 
1273
    float_round_nearest_even,
1274
    float_round_to_zero,
1275
    float_round_up,
1276
    float_round_down
1277
};
1278

    
1279
#define RESTORE_ROUNDING_MODE \
1280
    set_float_rounding_mode(ieee_rm[env->fcr31 & 3], &env->fp_status)
1281

    
1282
void op_ctc1 (void)
1283
{
1284
    if (T1 == 0) {
1285
        /* XXX should this throw an exception?
1286
         * don't write to FCR0.
1287
         * env->fcr0 = T0; 
1288
         */
1289
    }
1290
    else {
1291
        /* store new fcr31, masking unused bits */  
1292
        env->fcr31 = T0 & 0x0183FFFF;
1293

    
1294
        /* set rounding mode */
1295
        RESTORE_ROUNDING_MODE;
1296

    
1297
#ifndef CONFIG_SOFTFLOAT
1298
        /* no floating point exception for native float */
1299
        SET_FP_ENABLE(env->fcr31, 0);
1300
#endif
1301
    }
1302
    DEBUG_FPU_STATE();
1303
    RETURN();
1304
}
1305

    
1306
void op_mfc1 (void)
1307
{
1308
    T0 = WT0;
1309
    DEBUG_FPU_STATE();
1310
    RETURN();
1311
}
1312

    
1313
void op_mtc1 (void)
1314
{
1315
    WT0 = T0;
1316
    DEBUG_FPU_STATE();
1317
    RETURN();
1318
}
1319

    
1320
/* Float support.
1321
   Single precition routines have a "s" suffix, double precision a
1322
   "d" suffix.  */
1323

    
1324
#define FLOAT_OP(name, p) void OPPROTO op_float_##name##_##p(void)
1325

    
1326
FLOAT_OP(cvtd, s)
1327
{
1328
    FDT2 = float32_to_float64(WT0, &env->fp_status);
1329
    DEBUG_FPU_STATE();
1330
    RETURN();
1331
}
1332
FLOAT_OP(cvtd, w)
1333
{
1334
    FDT2 = int32_to_float64(WT0, &env->fp_status);
1335
    DEBUG_FPU_STATE();
1336
    RETURN();
1337
}
1338
FLOAT_OP(cvts, d)
1339
{
1340
    FST2 = float64_to_float32(FDT0, &env->fp_status);
1341
    DEBUG_FPU_STATE();
1342
    RETURN();
1343
}
1344
FLOAT_OP(cvts, w)
1345
{
1346
    FST2 = int32_to_float32(WT0, &env->fp_status);
1347
    DEBUG_FPU_STATE();
1348
    RETURN();
1349
}
1350
FLOAT_OP(cvtw, s)
1351
{
1352
    WT2 = float32_to_int32(FST0, &env->fp_status);
1353
    DEBUG_FPU_STATE();
1354
    RETURN();
1355
}
1356
FLOAT_OP(cvtw, d)
1357
{
1358
    WT2 = float64_to_int32(FDT0, &env->fp_status);
1359
    DEBUG_FPU_STATE();
1360
    RETURN();
1361
}
1362

    
1363
FLOAT_OP(roundw, d)
1364
{
1365
    set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
1366
    WT2 = float64_round_to_int(FDT0, &env->fp_status);
1367
    RESTORE_ROUNDING_MODE;
1368

    
1369
    DEBUG_FPU_STATE();
1370
    RETURN();
1371
}
1372
FLOAT_OP(roundw, s)
1373
{
1374
    set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
1375
    WT2 = float32_round_to_int(FST0, &env->fp_status);
1376
    RESTORE_ROUNDING_MODE;
1377
    DEBUG_FPU_STATE();
1378
    RETURN();
1379
}
1380

    
1381
FLOAT_OP(truncw, d)
1382
{
1383
    WT2 = float64_to_int32_round_to_zero(FDT0, &env->fp_status);
1384
    DEBUG_FPU_STATE();
1385
    RETURN();
1386
}
1387
FLOAT_OP(truncw, s)
1388
{
1389
    WT2 = float32_to_int32_round_to_zero(FST0, &env->fp_status);
1390
    DEBUG_FPU_STATE();
1391
    RETURN();
1392
}
1393

    
1394
FLOAT_OP(ceilw, d)
1395
{
1396
    set_float_rounding_mode(float_round_up, &env->fp_status);
1397
    WT2 = float64_round_to_int(FDT0, &env->fp_status);
1398
    RESTORE_ROUNDING_MODE;
1399

    
1400
    DEBUG_FPU_STATE();
1401
    RETURN();
1402
}
1403
FLOAT_OP(ceilw, s)
1404
{
1405
    set_float_rounding_mode(float_round_up, &env->fp_status);
1406
    WT2 = float32_round_to_int(FST0, &env->fp_status);
1407
    RESTORE_ROUNDING_MODE;
1408
    DEBUG_FPU_STATE();
1409
    RETURN();
1410
}
1411

    
1412
FLOAT_OP(floorw, d)
1413
{
1414
    set_float_rounding_mode(float_round_down, &env->fp_status);
1415
    WT2 = float64_round_to_int(FDT0, &env->fp_status);
1416
    RESTORE_ROUNDING_MODE;
1417

    
1418
    DEBUG_FPU_STATE();
1419
    RETURN();
1420
}
1421
FLOAT_OP(floorw, s)
1422
{
1423
    set_float_rounding_mode(float_round_down, &env->fp_status);
1424
    WT2 = float32_round_to_int(FST0, &env->fp_status);
1425
    RESTORE_ROUNDING_MODE;
1426
    DEBUG_FPU_STATE();
1427
    RETURN();
1428
}
1429

    
1430
/* binary operations */
1431
#define FLOAT_BINOP(name) \
1432
FLOAT_OP(name, d)         \
1433
{                         \
1434
    FDT2 = float64_ ## name (FDT0, FDT1, &env->fp_status);    \
1435
    DEBUG_FPU_STATE();    \
1436
}                         \
1437
FLOAT_OP(name, s)         \
1438
{                         \
1439
    FST2 = float32_ ## name (FST0, FST1, &env->fp_status);    \
1440
    DEBUG_FPU_STATE();    \
1441
}
1442
FLOAT_BINOP(add)
1443
FLOAT_BINOP(sub)
1444
FLOAT_BINOP(mul)
1445
FLOAT_BINOP(div)
1446
#undef FLOAT_BINOP
1447

    
1448
/* unary operations, modifying fp status  */
1449
#define FLOAT_UNOP(name)  \
1450
FLOAT_OP(name, d)         \
1451
{                         \
1452
    FDT2 = float64_ ## name(FDT0, &env->fp_status);   \
1453
    DEBUG_FPU_STATE();    \
1454
}                         \
1455
FLOAT_OP(name, s)         \
1456
{                         \
1457
    FST2 = float32_ ## name(FST0, &env->fp_status);   \
1458
    DEBUG_FPU_STATE();    \
1459
}
1460
FLOAT_UNOP(sqrt)
1461
#undef FLOAT_UNOP
1462

    
1463
/* unary operations, not modifying fp status  */
1464
#define FLOAT_UNOP(name)  \
1465
FLOAT_OP(name, d)         \
1466
{                         \
1467
    FDT2 = float64_ ## name(FDT0);   \
1468
    DEBUG_FPU_STATE();    \
1469
}                         \
1470
FLOAT_OP(name, s)         \
1471
{                         \
1472
    FST2 = float32_ ## name(FST0);   \
1473
    DEBUG_FPU_STATE();    \
1474
}
1475
FLOAT_UNOP(abs)
1476
FLOAT_UNOP(chs)
1477
#undef FLOAT_UNOP
1478

    
1479
FLOAT_OP(mov, d)
1480
{
1481
    FDT2 = FDT0;
1482
    DEBUG_FPU_STATE();
1483
    RETURN();
1484
}
1485
FLOAT_OP(mov, s)
1486
{
1487
    FST2 = FST0;
1488
    DEBUG_FPU_STATE();
1489
    RETURN();
1490
}
1491

    
1492
#ifdef CONFIG_SOFTFLOAT
1493
#define clear_invalid() do {                                \
1494
    int flags = get_float_exception_flags(&env->fp_status); \
1495
    flags &= ~float_flag_invalid;                           \
1496
    set_float_exception_flags(flags, &env->fp_status);      \
1497
} while(0)
1498
#else
1499
#define clear_invalid() do { } while(0)
1500
#endif
1501

    
1502
extern void dump_fpu_s(CPUState *env);
1503

    
1504
#define FOP_COND(fmt, op, sig, cond)           \
1505
void op_cmp_ ## fmt ## _ ## op (void)          \
1506
{                                              \
1507
    if (cond)                                  \
1508
        SET_FP_COND(env->fcr31);               \
1509
    else                                       \
1510
        CLEAR_FP_COND(env->fcr31);             \
1511
    if (!sig)                                  \
1512
        clear_invalid();                       \
1513
    /*CALL_FROM_TB1(dump_fpu_s, env);*/ \
1514
    DEBUG_FPU_STATE();                         \
1515
    RETURN();                                  \
1516
}
1517

    
1518
int float64_is_unordered(float64 a, float64 b STATUS_PARAM)
1519
{
1520
    if (float64_is_nan(a) || float64_is_nan(b)) {
1521
        float_raise(float_flag_invalid, status);
1522
        return 1;
1523
    }
1524
    else {
1525
        return 0;
1526
    }
1527
}
1528

    
1529
FOP_COND(d, f,   0,                                                      0) 
1530
FOP_COND(d, un,  0, float64_is_unordered(FDT1, FDT0, &env->fp_status))
1531
FOP_COND(d, eq,  0,                                                      float64_eq(FDT0, FDT1, &env->fp_status))
1532
FOP_COND(d, ueq, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status))
1533
FOP_COND(d, olt, 0,                                                      float64_lt(FDT0, FDT1, &env->fp_status))
1534
FOP_COND(d, ult, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status))
1535
FOP_COND(d, ole, 0,                                                      float64_le(FDT0, FDT1, &env->fp_status))
1536
FOP_COND(d, ule, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status))
1537
/* NOTE: the comma operator will make "cond" to eval to false,
1538
 * but float*_is_unordered() is still called
1539
 */
1540
FOP_COND(d, sf,  1,                                                      (float64_is_unordered(FDT0, FDT1, &env->fp_status), 0))
1541
FOP_COND(d, ngle,1, float64_is_unordered(FDT1, FDT0, &env->fp_status))
1542
FOP_COND(d, seq, 1,                                                      float64_eq(FDT0, FDT1, &env->fp_status))
1543
FOP_COND(d, ngl, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status))
1544
FOP_COND(d, lt,  1,                                                      float64_lt(FDT0, FDT1, &env->fp_status))
1545
FOP_COND(d, nge, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status))
1546
FOP_COND(d, le,  1,                                                      float64_le(FDT0, FDT1, &env->fp_status))
1547
FOP_COND(d, ngt, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status))
1548

    
1549
flag float32_is_unordered(float32 a, float32 b STATUS_PARAM)
1550
{
1551
    extern flag float32_is_nan( float32 a );
1552
    if (float32_is_nan(a) || float32_is_nan(b)) {
1553
        float_raise(float_flag_invalid, status);
1554
        return 1;
1555
    }
1556
    else {
1557
        return 0;
1558
    }
1559
}
1560

    
1561
/* NOTE: the comma operator will make "cond" to eval to false,
1562
 * but float*_is_unordered() is still called
1563
 */
1564
FOP_COND(s, f,   0,                                                      0) 
1565
FOP_COND(s, un,  0, float32_is_unordered(FST1, FST0, &env->fp_status))
1566
FOP_COND(s, eq,  0,                                                      float32_eq(FST0, FST1, &env->fp_status))
1567
FOP_COND(s, ueq, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status))
1568
FOP_COND(s, olt, 0,                                                      float32_lt(FST0, FST1, &env->fp_status))
1569
FOP_COND(s, ult, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status))
1570
FOP_COND(s, ole, 0,                                                      float32_le(FST0, FST1, &env->fp_status))
1571
FOP_COND(s, ule, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status))
1572
/* NOTE: the comma operator will make "cond" to eval to false,
1573
 * but float*_is_unordered() is still called
1574
 */
1575
FOP_COND(s, sf,  1,                                                      (float32_is_unordered(FST0, FST1, &env->fp_status), 0))
1576
FOP_COND(s, ngle,1, float32_is_unordered(FST1, FST0, &env->fp_status))
1577
FOP_COND(s, seq, 1,                                                      float32_eq(FST0, FST1, &env->fp_status))
1578
FOP_COND(s, ngl, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status))
1579
FOP_COND(s, lt,  1,                                                      float32_lt(FST0, FST1, &env->fp_status))
1580
FOP_COND(s, nge, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status))
1581
FOP_COND(s, le,  1,                                                      float32_le(FST0, FST1, &env->fp_status))
1582
FOP_COND(s, ngt, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status))
1583

    
1584
void op_bc1f (void)
1585
{
1586
    T0 = ! IS_FP_COND_SET(env->fcr31);
1587
    DEBUG_FPU_STATE();
1588
    RETURN();
1589
}
1590

    
1591
void op_bc1t (void)
1592
{
1593
    T0 = IS_FP_COND_SET(env->fcr31);
1594
    DEBUG_FPU_STATE();
1595
    RETURN();
1596
}
1597
#endif /* MIPS_USES_FPU */
1598

    
1599
#if defined(MIPS_USES_R4K_TLB)
1600
void op_tlbwi (void)
1601
{
1602
    CALL_FROM_TB0(do_tlbwi);
1603
    RETURN();
1604
}
1605

    
1606
void op_tlbwr (void)
1607
{
1608
    CALL_FROM_TB0(do_tlbwr);
1609
    RETURN();
1610
}
1611

    
1612
void op_tlbp (void)
1613
{
1614
    CALL_FROM_TB0(do_tlbp);
1615
    RETURN();
1616
}
1617

    
1618
void op_tlbr (void)
1619
{
1620
    CALL_FROM_TB0(do_tlbr);
1621
    RETURN();
1622
}
1623
#endif
1624

    
1625
/* Specials */
1626
void op_pmon (void)
1627
{
1628
    CALL_FROM_TB1(do_pmon, PARAM1);
1629
    RETURN();
1630
}
1631

    
1632
void op_di (void)
1633
{
1634
    uint32_t val;
1635

    
1636
    T0 = env->CP0_Status;
1637
    val = T0 & ~(1 << CP0St_IE);
1638
    if (val != T0) {
1639
        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
1640
        env->CP0_Status = val;
1641
    }
1642
    RETURN();
1643
}
1644

    
1645
void op_ei (void)
1646
{
1647
    uint32_t val;
1648

    
1649
    T0 = env->CP0_Status;
1650
    val = T0 | (1 << CP0St_IE);
1651
    if (val != T0) {
1652
       const uint32_t mask = 0x0000FF00;
1653

    
1654
       env->CP0_Status = val;
1655
       if (!(env->hflags & MIPS_HFLAG_EXL) &&
1656
           !(env->hflags & MIPS_HFLAG_ERL) &&
1657
           !(env->hflags & MIPS_HFLAG_DM) &&
1658
           (env->CP0_Status & env->CP0_Cause & mask)) {
1659
               env->interrupt_request |= CPU_INTERRUPT_HARD;
1660
               if (logfile)
1661
                   CALL_FROM_TB0(do_mtc0_status_irqraise_debug);
1662
       }
1663
    }
1664
    RETURN();
1665
}
1666

    
1667
void op_trap (void)
1668
{
1669
    if (T0) {
1670
        CALL_FROM_TB1(do_raise_exception_direct, EXCP_TRAP);
1671
    }
1672
    RETURN();
1673
}
1674

    
1675
void op_debug (void)
1676
{
1677
    CALL_FROM_TB1(do_raise_exception, EXCP_DEBUG);
1678
    RETURN();
1679
}
1680

    
1681
void op_set_lladdr (void)
1682
{
1683
    env->CP0_LLAddr = T2;
1684
    RETURN();
1685
}
1686

    
1687
void debug_eret (void);
1688
void op_eret (void)
1689
{
1690
    CALL_FROM_TB0(debug_eret);
1691
    if (env->hflags & MIPS_HFLAG_ERL) {
1692
        env->PC = env->CP0_ErrorEPC;
1693
        env->hflags &= ~MIPS_HFLAG_ERL;
1694
        env->CP0_Status &= ~(1 << CP0St_ERL);
1695
    } else {
1696
        env->PC = env->CP0_EPC;
1697
        env->hflags &= ~MIPS_HFLAG_EXL;
1698
        env->CP0_Status &= ~(1 << CP0St_EXL);
1699
    }
1700
    env->CP0_LLAddr = 1;
1701
    RETURN();
1702
}
1703

    
1704
void op_deret (void)
1705
{
1706
    CALL_FROM_TB0(debug_eret);
1707
    env->PC = env->CP0_DEPC;
1708
    RETURN();
1709
}
1710

    
1711
void op_rdhwr_cpunum(void)
1712
{
1713
    if (env->CP0_HWREna & (1 << 0))
1714
       T0 = env->CP0_EBase & 0x2ff;
1715
    else
1716
       CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI);
1717
    RETURN();
1718
}
1719

    
1720
void op_rdhwr_synci_step(void)
1721
{
1722
    if (env->CP0_HWREna & (1 << 1))
1723
       T0 = env->SYNCI_Step;
1724
    else
1725
       CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI);
1726
    RETURN();
1727
}
1728

    
1729
void op_rdhwr_cc(void)
1730
{
1731
    if (env->CP0_HWREna & (1 << 2))
1732
       T0 = env->CP0_Count;
1733
    else
1734
       CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI);
1735
    RETURN();
1736
}
1737

    
1738
void op_rdhwr_ccres(void)
1739
{
1740
    if (env->CP0_HWREna & (1 << 3))
1741
       T0 = env->CCRes;
1742
    else
1743
       CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI);
1744
    RETURN();
1745
}
1746

    
1747
void op_save_state (void)
1748
{
1749
    env->hflags = PARAM1;
1750
    RETURN();
1751
}
1752

    
1753
void op_save_pc (void)
1754
{
1755
    env->PC = PARAM1;
1756
    RETURN();
1757
}
1758

    
1759
void op_raise_exception (void)
1760
{
1761
    CALL_FROM_TB1(do_raise_exception, PARAM1);
1762
    RETURN();
1763
}
1764

    
1765
void op_raise_exception_err (void)
1766
{
1767
    CALL_FROM_TB2(do_raise_exception_err, PARAM1, PARAM2);
1768
    RETURN();
1769
}
1770

    
1771
void op_exit_tb (void)
1772
{
1773
    EXIT_TB();
1774
    RETURN();
1775
}
1776

    
1777
void op_wait (void)
1778
{
1779
    env->halted = 1;
1780
    CALL_FROM_TB1(do_raise_exception, EXCP_HLT);
1781
    RETURN();
1782
}
1783

    
1784
/* Bitfield operations. */
1785
void op_ext(void)
1786
{
1787
    unsigned int pos = PARAM1;
1788
    unsigned int size = PARAM2;
1789

    
1790
    T0 = (T1 >> pos) & ((1 << size) - 1);
1791
    RETURN();
1792
}
1793

    
1794
void op_ins(void)
1795
{
1796
    unsigned int pos = PARAM1;
1797
    unsigned int size = PARAM2;
1798
    target_ulong mask = ((1 << size) - 1) << pos;
1799

    
1800
    T0 = (T2 & ~mask) | ((T1 << pos) & mask);
1801
    RETURN();
1802
}
1803

    
1804
void op_wsbh(void)
1805
{
1806
    T0 = ((T1 << 8) & ~0x00FF00FF) | ((T1 >> 8) & 0x00FF00FF);
1807
    RETURN();
1808
}
1809

    
1810
void op_dsbh(void)
1811
{
1812
    T0 = ((T1 << 8) & ~0x00FF00FF00FF00FFULL) | ((T1 >> 8) & 0x00FF00FF00FF00FFULL);
1813
    RETURN();
1814
}
1815

    
1816
void op_dshd(void)
1817
{
1818
    T0 = ((T1 << 16) & ~0x0000FFFF0000FFFFULL) | ((T1 >> 16) & 0x0000FFFF0000FFFFULL);
1819
    RETURN();
1820
}
1821

    
1822
void op_seb(void)
1823
{
1824
    T0 = ((T1 & 0xFF) ^ 0x80) - 0x80;
1825
    RETURN();
1826
}
1827

    
1828
void op_seh(void)
1829
{
1830
    T0 = ((T1 & 0xFFFF) ^ 0x8000) - 0x8000;
1831
    RETURN();
1832
}