Statistics
| Branch: | Revision:

root / target-mips / op.c @ d26bc211

History | View | Annotate | Download (57.4 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
 *  Copyright (c) 2007 Thiemo Seufer (64-bit FPU support)
7
 *
8
 * This library is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public
10
 * License as published by the Free Software Foundation; either
11
 * version 2 of the License, or (at your option) any later version.
12
 *
13
 * This library is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public
19
 * License along with this library; if not, write to the Free Software
20
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
 */
22

    
23
#include "config.h"
24
#include "exec.h"
25
#include "host-utils.h"
26

    
27
#ifndef CALL_FROM_TB0
28
#define CALL_FROM_TB0(func) func()
29
#endif
30
#ifndef CALL_FROM_TB1
31
#define CALL_FROM_TB1(func, arg0) func(arg0)
32
#endif
33
#ifndef CALL_FROM_TB1_CONST16
34
#define CALL_FROM_TB1_CONST16(func, arg0) CALL_FROM_TB1(func, arg0)
35
#endif
36
#ifndef CALL_FROM_TB2
37
#define CALL_FROM_TB2(func, arg0, arg1) func(arg0, arg1)
38
#endif
39
#ifndef CALL_FROM_TB2_CONST16
40
#define CALL_FROM_TB2_CONST16(func, arg0, arg1)     \
41
        CALL_FROM_TB2(func, arg0, arg1)
42
#endif
43
#ifndef CALL_FROM_TB3
44
#define CALL_FROM_TB3(func, arg0, arg1, arg2) func(arg0, arg1, arg2)
45
#endif
46
#ifndef CALL_FROM_TB4
47
#define CALL_FROM_TB4(func, arg0, arg1, arg2, arg3) \
48
        func(arg0, arg1, arg2, arg3)
49
#endif
50

    
51
#define REG 1
52
#include "op_template.c"
53
#undef REG
54
#define REG 2
55
#include "op_template.c"
56
#undef REG
57
#define REG 3
58
#include "op_template.c"
59
#undef REG
60
#define REG 4
61
#include "op_template.c"
62
#undef REG
63
#define REG 5
64
#include "op_template.c"
65
#undef REG
66
#define REG 6
67
#include "op_template.c"
68
#undef REG
69
#define REG 7
70
#include "op_template.c"
71
#undef REG
72
#define REG 8
73
#include "op_template.c"
74
#undef REG
75
#define REG 9
76
#include "op_template.c"
77
#undef REG
78
#define REG 10
79
#include "op_template.c"
80
#undef REG
81
#define REG 11
82
#include "op_template.c"
83
#undef REG
84
#define REG 12
85
#include "op_template.c"
86
#undef REG
87
#define REG 13
88
#include "op_template.c"
89
#undef REG
90
#define REG 14
91
#include "op_template.c"
92
#undef REG
93
#define REG 15
94
#include "op_template.c"
95
#undef REG
96
#define REG 16
97
#include "op_template.c"
98
#undef REG
99
#define REG 17
100
#include "op_template.c"
101
#undef REG
102
#define REG 18
103
#include "op_template.c"
104
#undef REG
105
#define REG 19
106
#include "op_template.c"
107
#undef REG
108
#define REG 20
109
#include "op_template.c"
110
#undef REG
111
#define REG 21
112
#include "op_template.c"
113
#undef REG
114
#define REG 22
115
#include "op_template.c"
116
#undef REG
117
#define REG 23
118
#include "op_template.c"
119
#undef REG
120
#define REG 24
121
#include "op_template.c"
122
#undef REG
123
#define REG 25
124
#include "op_template.c"
125
#undef REG
126
#define REG 26
127
#include "op_template.c"
128
#undef REG
129
#define REG 27
130
#include "op_template.c"
131
#undef REG
132
#define REG 28
133
#include "op_template.c"
134
#undef REG
135
#define REG 29
136
#include "op_template.c"
137
#undef REG
138
#define REG 30
139
#include "op_template.c"
140
#undef REG
141
#define REG 31
142
#include "op_template.c"
143
#undef REG
144

    
145
#define TN
146
#include "op_template.c"
147
#undef TN
148

    
149
#define FREG 0
150
#include "fop_template.c"
151
#undef FREG
152
#define FREG 1
153
#include "fop_template.c"
154
#undef FREG
155
#define FREG 2
156
#include "fop_template.c"
157
#undef FREG
158
#define FREG 3
159
#include "fop_template.c"
160
#undef FREG
161
#define FREG 4
162
#include "fop_template.c"
163
#undef FREG
164
#define FREG 5
165
#include "fop_template.c"
166
#undef FREG
167
#define FREG 6
168
#include "fop_template.c"
169
#undef FREG
170
#define FREG 7
171
#include "fop_template.c"
172
#undef FREG
173
#define FREG 8
174
#include "fop_template.c"
175
#undef FREG
176
#define FREG 9
177
#include "fop_template.c"
178
#undef FREG
179
#define FREG 10
180
#include "fop_template.c"
181
#undef FREG
182
#define FREG 11
183
#include "fop_template.c"
184
#undef FREG
185
#define FREG 12
186
#include "fop_template.c"
187
#undef FREG
188
#define FREG 13
189
#include "fop_template.c"
190
#undef FREG
191
#define FREG 14
192
#include "fop_template.c"
193
#undef FREG
194
#define FREG 15
195
#include "fop_template.c"
196
#undef FREG
197
#define FREG 16
198
#include "fop_template.c"
199
#undef FREG
200
#define FREG 17
201
#include "fop_template.c"
202
#undef FREG
203
#define FREG 18
204
#include "fop_template.c"
205
#undef FREG
206
#define FREG 19
207
#include "fop_template.c"
208
#undef FREG
209
#define FREG 20
210
#include "fop_template.c"
211
#undef FREG
212
#define FREG 21
213
#include "fop_template.c"
214
#undef FREG
215
#define FREG 22
216
#include "fop_template.c"
217
#undef FREG
218
#define FREG 23
219
#include "fop_template.c"
220
#undef FREG
221
#define FREG 24
222
#include "fop_template.c"
223
#undef FREG
224
#define FREG 25
225
#include "fop_template.c"
226
#undef FREG
227
#define FREG 26
228
#include "fop_template.c"
229
#undef FREG
230
#define FREG 27
231
#include "fop_template.c"
232
#undef FREG
233
#define FREG 28
234
#include "fop_template.c"
235
#undef FREG
236
#define FREG 29
237
#include "fop_template.c"
238
#undef FREG
239
#define FREG 30
240
#include "fop_template.c"
241
#undef FREG
242
#define FREG 31
243
#include "fop_template.c"
244
#undef FREG
245

    
246
#define FTN
247
#include "fop_template.c"
248
#undef FTN
249

    
250
void op_dup_T0 (void)
251
{
252
    T2 = T0;
253
    RETURN();
254
}
255

    
256
void op_load_HI (void)
257
{
258
    T0 = env->HI[PARAM1][env->current_tc];
259
    RETURN();
260
}
261

    
262
void op_store_HI (void)
263
{
264
    env->HI[PARAM1][env->current_tc] = T0;
265
    RETURN();
266
}
267

    
268
void op_load_LO (void)
269
{
270
    T0 = env->LO[PARAM1][env->current_tc];
271
    RETURN();
272
}
273

    
274
void op_store_LO (void)
275
{
276
    env->LO[PARAM1][env->current_tc] = T0;
277
    RETURN();
278
}
279

    
280
/* Load and store */
281
#define MEMSUFFIX _raw
282
#include "op_mem.c"
283
#undef MEMSUFFIX
284
#if !defined(CONFIG_USER_ONLY)
285
#define MEMSUFFIX _user
286
#include "op_mem.c"
287
#undef MEMSUFFIX
288

    
289
#define MEMSUFFIX _super
290
#include "op_mem.c"
291
#undef MEMSUFFIX
292

    
293
#define MEMSUFFIX _kernel
294
#include "op_mem.c"
295
#undef MEMSUFFIX
296
#endif
297

    
298
/* Addresses computation */
299
void op_addr_add (void)
300
{
301
/* For compatibility with 32-bit code, data reference in user mode
302
   with Status_UX = 0 should be casted to 32-bit and sign extended.
303
   See the MIPS64 PRA manual, section 4.10. */
304
#if defined(TARGET_MIPS64)
305
    if (((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
306
        !(env->CP0_Status & (1 << CP0St_UX)))
307
        T0 = (int64_t)(int32_t)(T0 + T1);
308
    else
309
#endif
310
        T0 += T1;
311
    RETURN();
312
}
313

    
314
/* Arithmetic */
315
void op_add (void)
316
{
317
    T0 = (int32_t)((int32_t)T0 + (int32_t)T1);
318
    RETURN();
319
}
320

    
321
void op_addo (void)
322
{
323
    target_ulong tmp;
324

    
325
    tmp = (int32_t)T0;
326
    T0 = (int32_t)T0 + (int32_t)T1;
327
    if (((tmp ^ T1 ^ (-1)) & (T0 ^ T1)) >> 31) {
328
        /* operands of same sign, result different sign */
329
        CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
330
    }
331
    T0 = (int32_t)T0;
332
    RETURN();
333
}
334

    
335
void op_sub (void)
336
{
337
    T0 = (int32_t)((int32_t)T0 - (int32_t)T1);
338
    RETURN();
339
}
340

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

    
345
    tmp = (int32_t)T0;
346
    T0 = (int32_t)T0 - (int32_t)T1;
347
    if (((tmp ^ T1) & (tmp ^ T0)) >> 31) {
348
        /* operands of different sign, first operand and result different sign */
349
        CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
350
    }
351
    T0 = (int32_t)T0;
352
    RETURN();
353
}
354

    
355
void op_mul (void)
356
{
357
    T0 = (int32_t)((int32_t)T0 * (int32_t)T1);
358
    RETURN();
359
}
360

    
361
#if HOST_LONG_BITS < 64
362
void op_div (void)
363
{
364
    CALL_FROM_TB0(do_div);
365
    RETURN();
366
}
367
#else
368
void op_div (void)
369
{
370
    if (T1 != 0) {
371
        env->LO[0][env->current_tc] = (int32_t)((int64_t)(int32_t)T0 / (int32_t)T1);
372
        env->HI[0][env->current_tc] = (int32_t)((int64_t)(int32_t)T0 % (int32_t)T1);
373
    }
374
    RETURN();
375
}
376
#endif
377

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

    
387
#if defined(TARGET_MIPS64)
388
/* Arithmetic */
389
void op_dadd (void)
390
{
391
    T0 += T1;
392
    RETURN();
393
}
394

    
395
void op_daddo (void)
396
{
397
    target_long tmp;
398

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

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

    
414
void op_dsubo (void)
415
{
416
    target_long tmp;
417

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

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

    
433
/* Those might call libgcc functions.  */
434
void op_ddiv (void)
435
{
436
    do_ddiv();
437
    RETURN();
438
}
439

    
440
#if TARGET_LONG_BITS > HOST_LONG_BITS
441
void op_ddivu (void)
442
{
443
    do_ddivu();
444
    RETURN();
445
}
446
#else
447
void op_ddivu (void)
448
{
449
    if (T1 != 0) {
450
        env->LO[0][env->current_tc] = T0 / T1;
451
        env->HI[0][env->current_tc] = T0 % T1;
452
    }
453
    RETURN();
454
}
455
#endif
456
#endif /* TARGET_MIPS64 */
457

    
458
/* Logical */
459
void op_and (void)
460
{
461
    T0 &= T1;
462
    RETURN();
463
}
464

    
465
void op_nor (void)
466
{
467
    T0 = ~(T0 | T1);
468
    RETURN();
469
}
470

    
471
void op_or (void)
472
{
473
    T0 |= T1;
474
    RETURN();
475
}
476

    
477
void op_xor (void)
478
{
479
    T0 ^= T1;
480
    RETURN();
481
}
482

    
483
void op_sll (void)
484
{
485
    T0 = (int32_t)((uint32_t)T0 << T1);
486
    RETURN();
487
}
488

    
489
void op_sra (void)
490
{
491
    T0 = (int32_t)((int32_t)T0 >> T1);
492
    RETURN();
493
}
494

    
495
void op_srl (void)
496
{
497
    T0 = (int32_t)((uint32_t)T0 >> T1);
498
    RETURN();
499
}
500

    
501
void op_rotr (void)
502
{
503
    target_ulong tmp;
504

    
505
    if (T1) {
506
       tmp = (int32_t)((uint32_t)T0 << (0x20 - T1));
507
       T0 = (int32_t)((uint32_t)T0 >> T1) | tmp;
508
    }
509
    RETURN();
510
}
511

    
512
void op_sllv (void)
513
{
514
    T0 = (int32_t)((uint32_t)T1 << ((uint32_t)T0 & 0x1F));
515
    RETURN();
516
}
517

    
518
void op_srav (void)
519
{
520
    T0 = (int32_t)((int32_t)T1 >> (T0 & 0x1F));
521
    RETURN();
522
}
523

    
524
void op_srlv (void)
525
{
526
    T0 = (int32_t)((uint32_t)T1 >> (T0 & 0x1F));
527
    RETURN();
528
}
529

    
530
void op_rotrv (void)
531
{
532
    target_ulong tmp;
533

    
534
    T0 &= 0x1F;
535
    if (T0) {
536
       tmp = (int32_t)((uint32_t)T1 << (0x20 - T0));
537
       T0 = (int32_t)((uint32_t)T1 >> T0) | tmp;
538
    } else
539
       T0 = T1;
540
    RETURN();
541
}
542

    
543
void op_clo (void)
544
{
545
    T0 = clo32(T0);
546
    RETURN();
547
}
548

    
549
void op_clz (void)
550
{
551
    T0 = clz32(T0);
552
    RETURN();
553
}
554

    
555
#if defined(TARGET_MIPS64)
556

    
557
#if TARGET_LONG_BITS > HOST_LONG_BITS
558
/* Those might call libgcc functions.  */
559
void op_dsll (void)
560
{
561
    CALL_FROM_TB0(do_dsll);
562
    RETURN();
563
}
564

    
565
void op_dsll32 (void)
566
{
567
    CALL_FROM_TB0(do_dsll32);
568
    RETURN();
569
}
570

    
571
void op_dsra (void)
572
{
573
    CALL_FROM_TB0(do_dsra);
574
    RETURN();
575
}
576

    
577
void op_dsra32 (void)
578
{
579
    CALL_FROM_TB0(do_dsra32);
580
    RETURN();
581
}
582

    
583
void op_dsrl (void)
584
{
585
    CALL_FROM_TB0(do_dsrl);
586
    RETURN();
587
}
588

    
589
void op_dsrl32 (void)
590
{
591
    CALL_FROM_TB0(do_dsrl32);
592
    RETURN();
593
}
594

    
595
void op_drotr (void)
596
{
597
    CALL_FROM_TB0(do_drotr);
598
    RETURN();
599
}
600

    
601
void op_drotr32 (void)
602
{
603
    CALL_FROM_TB0(do_drotr32);
604
    RETURN();
605
}
606

    
607
void op_dsllv (void)
608
{
609
    CALL_FROM_TB0(do_dsllv);
610
    RETURN();
611
}
612

    
613
void op_dsrav (void)
614
{
615
    CALL_FROM_TB0(do_dsrav);
616
    RETURN();
617
}
618

    
619
void op_dsrlv (void)
620
{
621
    CALL_FROM_TB0(do_dsrlv);
622
    RETURN();
623
}
624

    
625
void op_drotrv (void)
626
{
627
    CALL_FROM_TB0(do_drotrv);
628
    RETURN();
629
}
630

    
631
void op_dclo (void)
632
{
633
    CALL_FROM_TB0(do_dclo);
634
    RETURN();
635
}
636

    
637
void op_dclz (void)
638
{
639
    CALL_FROM_TB0(do_dclz);
640
    RETURN();
641
}
642

    
643
#else /* TARGET_LONG_BITS > HOST_LONG_BITS */
644

    
645
void op_dsll (void)
646
{
647
    T0 = T0 << T1;
648
    RETURN();
649
}
650

    
651
void op_dsll32 (void)
652
{
653
    T0 = T0 << (T1 + 32);
654
    RETURN();
655
}
656

    
657
void op_dsra (void)
658
{
659
    T0 = (int64_t)T0 >> T1;
660
    RETURN();
661
}
662

    
663
void op_dsra32 (void)
664
{
665
    T0 = (int64_t)T0 >> (T1 + 32);
666
    RETURN();
667
}
668

    
669
void op_dsrl (void)
670
{
671
    T0 = T0 >> T1;
672
    RETURN();
673
}
674

    
675
void op_dsrl32 (void)
676
{
677
    T0 = T0 >> (T1 + 32);
678
    RETURN();
679
}
680

    
681
void op_drotr (void)
682
{
683
    target_ulong tmp;
684

    
685
    if (T1) {
686
       tmp = T0 << (0x40 - T1);
687
       T0 = (T0 >> T1) | tmp;
688
    }
689
    RETURN();
690
}
691

    
692
void op_drotr32 (void)
693
{
694
    target_ulong tmp;
695

    
696
    if (T1) {
697
       tmp = T0 << (0x40 - (32 + T1));
698
       T0 = (T0 >> (32 + T1)) | tmp;
699
    }
700
    RETURN();
701
}
702

    
703
void op_dsllv (void)
704
{
705
    T0 = T1 << (T0 & 0x3F);
706
    RETURN();
707
}
708

    
709
void op_dsrav (void)
710
{
711
    T0 = (int64_t)T1 >> (T0 & 0x3F);
712
    RETURN();
713
}
714

    
715
void op_dsrlv (void)
716
{
717
    T0 = T1 >> (T0 & 0x3F);
718
    RETURN();
719
}
720

    
721
void op_drotrv (void)
722
{
723
    target_ulong tmp;
724

    
725
    T0 &= 0x3F;
726
    if (T0) {
727
       tmp = T1 << (0x40 - T0);
728
       T0 = (T1 >> T0) | tmp;
729
    } else
730
       T0 = T1;
731
    RETURN();
732
}
733

    
734
void op_dclo (void)
735
{
736
    T0 = clo64(T0);
737
    RETURN();
738
}
739

    
740
void op_dclz (void)
741
{
742
    T0 = clz64(T0);
743
    RETURN();
744
}
745
#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
746
#endif /* TARGET_MIPS64 */
747

    
748
/* 64 bits arithmetic */
749
#if TARGET_LONG_BITS > HOST_LONG_BITS
750
void op_mult (void)
751
{
752
    CALL_FROM_TB0(do_mult);
753
    RETURN();
754
}
755

    
756
void op_multu (void)
757
{
758
    CALL_FROM_TB0(do_multu);
759
    RETURN();
760
}
761

    
762
void op_madd (void)
763
{
764
    CALL_FROM_TB0(do_madd);
765
    RETURN();
766
}
767

    
768
void op_maddu (void)
769
{
770
    CALL_FROM_TB0(do_maddu);
771
    RETURN();
772
}
773

    
774
void op_msub (void)
775
{
776
    CALL_FROM_TB0(do_msub);
777
    RETURN();
778
}
779

    
780
void op_msubu (void)
781
{
782
    CALL_FROM_TB0(do_msubu);
783
    RETURN();
784
}
785

    
786
#else /* TARGET_LONG_BITS > HOST_LONG_BITS */
787

    
788
static always_inline uint64_t get_HILO (void)
789
{
790
    return ((uint64_t)env->HI[0][env->current_tc] << 32) |
791
            ((uint64_t)(uint32_t)env->LO[0][env->current_tc]);
792
}
793

    
794
static always_inline void set_HILO (uint64_t HILO)
795
{
796
    env->LO[0][env->current_tc] = (int32_t)(HILO & 0xFFFFFFFF);
797
    env->HI[0][env->current_tc] = (int32_t)(HILO >> 32);
798
}
799

    
800
void op_mult (void)
801
{
802
    set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
803
    RETURN();
804
}
805

    
806
void op_multu (void)
807
{
808
    set_HILO((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
809
    RETURN();
810
}
811

    
812
void op_madd (void)
813
{
814
    int64_t tmp;
815

    
816
    tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
817
    set_HILO((int64_t)get_HILO() + tmp);
818
    RETURN();
819
}
820

    
821
void op_maddu (void)
822
{
823
    uint64_t tmp;
824

    
825
    tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
826
    set_HILO(get_HILO() + tmp);
827
    RETURN();
828
}
829

    
830
void op_msub (void)
831
{
832
    int64_t tmp;
833

    
834
    tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
835
    set_HILO((int64_t)get_HILO() - tmp);
836
    RETURN();
837
}
838

    
839
void op_msubu (void)
840
{
841
    uint64_t tmp;
842

    
843
    tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
844
    set_HILO(get_HILO() - tmp);
845
    RETURN();
846
}
847
#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
848

    
849
#if defined(TARGET_MIPS64)
850
void op_dmult (void)
851
{
852
    CALL_FROM_TB4(muls64, &(env->LO[0][env->current_tc]), &(env->HI[0][env->current_tc]), T0, T1);
853
    RETURN();
854
}
855

    
856
void op_dmultu (void)
857
{
858
    CALL_FROM_TB4(mulu64, &(env->LO[0][env->current_tc]), &(env->HI[0][env->current_tc]), T0, T1);
859
    RETURN();
860
}
861
#endif
862

    
863
/* Conditional moves */
864
void op_movn (void)
865
{
866
    if (T1 != 0)
867
        env->gpr[PARAM1][env->current_tc] = T0;
868
    RETURN();
869
}
870

    
871
void op_movz (void)
872
{
873
    if (T1 == 0)
874
        env->gpr[PARAM1][env->current_tc] = T0;
875
    RETURN();
876
}
877

    
878
void op_movf (void)
879
{
880
    if (!(env->fpu->fcr31 & PARAM1))
881
        T0 = T1;
882
    RETURN();
883
}
884

    
885
void op_movt (void)
886
{
887
    if (env->fpu->fcr31 & PARAM1)
888
        T0 = T1;
889
    RETURN();
890
}
891

    
892
/* Tests */
893
#define OP_COND(name, cond) \
894
void glue(op_, name) (void) \
895
{                           \
896
    if (cond) {             \
897
        T0 = 1;             \
898
    } else {                \
899
        T0 = 0;             \
900
    }                       \
901
    RETURN();               \
902
}
903

    
904
OP_COND(eq, T0 == T1);
905
OP_COND(ne, T0 != T1);
906
OP_COND(ge, (target_long)T0 >= (target_long)T1);
907
OP_COND(geu, T0 >= T1);
908
OP_COND(lt, (target_long)T0 < (target_long)T1);
909
OP_COND(ltu, T0 < T1);
910
OP_COND(gez, (target_long)T0 >= 0);
911
OP_COND(gtz, (target_long)T0 > 0);
912
OP_COND(lez, (target_long)T0 <= 0);
913
OP_COND(ltz, (target_long)T0 < 0);
914

    
915
/* Branches */
916
void OPPROTO op_goto_tb0(void)
917
{
918
    GOTO_TB(op_goto_tb0, PARAM1, 0);
919
    RETURN();
920
}
921

    
922
void OPPROTO op_goto_tb1(void)
923
{
924
    GOTO_TB(op_goto_tb1, PARAM1, 1);
925
    RETURN();
926
}
927

    
928
/* Branch to register */
929
void op_save_breg_target (void)
930
{
931
    env->btarget = T2;
932
    RETURN();
933
}
934

    
935
void op_restore_breg_target (void)
936
{
937
    T2 = env->btarget;
938
    RETURN();
939
}
940

    
941
void op_breg (void)
942
{
943
    env->PC[env->current_tc] = T2;
944
    RETURN();
945
}
946

    
947
void op_save_btarget (void)
948
{
949
    env->btarget = PARAM1;
950
    RETURN();
951
}
952

    
953
#if defined(TARGET_MIPS64)
954
void op_save_btarget64 (void)
955
{
956
    env->btarget = ((uint64_t)PARAM1 << 32) | (uint32_t)PARAM2;
957
    RETURN();
958
}
959
#endif
960

    
961
/* Conditional branch */
962
void op_set_bcond (void)
963
{
964
    T2 = T0;
965
    RETURN();
966
}
967

    
968
void op_save_bcond (void)
969
{
970
    env->bcond = T2;
971
    RETURN();
972
}
973

    
974
void op_restore_bcond (void)
975
{
976
    T2 = env->bcond;
977
    RETURN();
978
}
979

    
980
void op_jnz_T2 (void)
981
{
982
    if (T2)
983
        GOTO_LABEL_PARAM(1);
984
    RETURN();
985
}
986

    
987
/* CP0 functions */
988
void op_mfc0_index (void)
989
{
990
    T0 = env->CP0_Index;
991
    RETURN();
992
}
993

    
994
void op_mfc0_mvpcontrol (void)
995
{
996
    T0 = env->mvp->CP0_MVPControl;
997
    RETURN();
998
}
999

    
1000
void op_mfc0_mvpconf0 (void)
1001
{
1002
    T0 = env->mvp->CP0_MVPConf0;
1003
    RETURN();
1004
}
1005

    
1006
void op_mfc0_mvpconf1 (void)
1007
{
1008
    T0 = env->mvp->CP0_MVPConf1;
1009
    RETURN();
1010
}
1011

    
1012
void op_mfc0_random (void)
1013
{
1014
    CALL_FROM_TB0(do_mfc0_random);
1015
    RETURN();
1016
}
1017

    
1018
void op_mfc0_vpecontrol (void)
1019
{
1020
    T0 = env->CP0_VPEControl;
1021
    RETURN();
1022
}
1023

    
1024
void op_mfc0_vpeconf0 (void)
1025
{
1026
    T0 = env->CP0_VPEConf0;
1027
    RETURN();
1028
}
1029

    
1030
void op_mfc0_vpeconf1 (void)
1031
{
1032
    T0 = env->CP0_VPEConf1;
1033
    RETURN();
1034
}
1035

    
1036
void op_mfc0_yqmask (void)
1037
{
1038
    T0 = env->CP0_YQMask;
1039
    RETURN();
1040
}
1041

    
1042
void op_mfc0_vpeschedule (void)
1043
{
1044
    T0 = env->CP0_VPESchedule;
1045
    RETURN();
1046
}
1047

    
1048
void op_mfc0_vpeschefback (void)
1049
{
1050
    T0 = env->CP0_VPEScheFBack;
1051
    RETURN();
1052
}
1053

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

    
1060
void op_mfc0_entrylo0 (void)
1061
{
1062
    T0 = (int32_t)env->CP0_EntryLo0;
1063
    RETURN();
1064
}
1065

    
1066
void op_mfc0_tcstatus (void)
1067
{
1068
    T0 = env->CP0_TCStatus[env->current_tc];
1069
    RETURN();
1070
}
1071

    
1072
void op_mftc0_tcstatus(void)
1073
{
1074
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1075

    
1076
    T0 = env->CP0_TCStatus[other_tc];
1077
    RETURN();
1078
}
1079

    
1080
void op_mfc0_tcbind (void)
1081
{
1082
    T0 = env->CP0_TCBind[env->current_tc];
1083
    RETURN();
1084
}
1085

    
1086
void op_mftc0_tcbind(void)
1087
{
1088
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1089

    
1090
    T0 = env->CP0_TCBind[other_tc];
1091
    RETURN();
1092
}
1093

    
1094
void op_mfc0_tcrestart (void)
1095
{
1096
    T0 = env->PC[env->current_tc];
1097
    RETURN();
1098
}
1099

    
1100
void op_mftc0_tcrestart(void)
1101
{
1102
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1103

    
1104
    T0 = env->PC[other_tc];
1105
    RETURN();
1106
}
1107

    
1108
void op_mfc0_tchalt (void)
1109
{
1110
    T0 = env->CP0_TCHalt[env->current_tc];
1111
    RETURN();
1112
}
1113

    
1114
void op_mftc0_tchalt(void)
1115
{
1116
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1117

    
1118
    T0 = env->CP0_TCHalt[other_tc];
1119
    RETURN();
1120
}
1121

    
1122
void op_mfc0_tccontext (void)
1123
{
1124
    T0 = env->CP0_TCContext[env->current_tc];
1125
    RETURN();
1126
}
1127

    
1128
void op_mftc0_tccontext(void)
1129
{
1130
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1131

    
1132
    T0 = env->CP0_TCContext[other_tc];
1133
    RETURN();
1134
}
1135

    
1136
void op_mfc0_tcschedule (void)
1137
{
1138
    T0 = env->CP0_TCSchedule[env->current_tc];
1139
    RETURN();
1140
}
1141

    
1142
void op_mftc0_tcschedule(void)
1143
{
1144
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1145

    
1146
    T0 = env->CP0_TCSchedule[other_tc];
1147
    RETURN();
1148
}
1149

    
1150
void op_mfc0_tcschefback (void)
1151
{
1152
    T0 = env->CP0_TCScheFBack[env->current_tc];
1153
    RETURN();
1154
}
1155

    
1156
void op_mftc0_tcschefback(void)
1157
{
1158
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1159

    
1160
    T0 = env->CP0_TCScheFBack[other_tc];
1161
    RETURN();
1162
}
1163

    
1164
void op_mfc0_entrylo1 (void)
1165
{
1166
    T0 = (int32_t)env->CP0_EntryLo1;
1167
    RETURN();
1168
}
1169

    
1170
void op_mfc0_context (void)
1171
{
1172
    T0 = (int32_t)env->CP0_Context;
1173
    RETURN();
1174
}
1175

    
1176
void op_mfc0_pagemask (void)
1177
{
1178
    T0 = env->CP0_PageMask;
1179
    RETURN();
1180
}
1181

    
1182
void op_mfc0_pagegrain (void)
1183
{
1184
    T0 = env->CP0_PageGrain;
1185
    RETURN();
1186
}
1187

    
1188
void op_mfc0_wired (void)
1189
{
1190
    T0 = env->CP0_Wired;
1191
    RETURN();
1192
}
1193

    
1194
void op_mfc0_srsconf0 (void)
1195
{
1196
    T0 = env->CP0_SRSConf0;
1197
    RETURN();
1198
}
1199

    
1200
void op_mfc0_srsconf1 (void)
1201
{
1202
    T0 = env->CP0_SRSConf1;
1203
    RETURN();
1204
}
1205

    
1206
void op_mfc0_srsconf2 (void)
1207
{
1208
    T0 = env->CP0_SRSConf2;
1209
    RETURN();
1210
}
1211

    
1212
void op_mfc0_srsconf3 (void)
1213
{
1214
    T0 = env->CP0_SRSConf3;
1215
    RETURN();
1216
}
1217

    
1218
void op_mfc0_srsconf4 (void)
1219
{
1220
    T0 = env->CP0_SRSConf4;
1221
    RETURN();
1222
}
1223

    
1224
void op_mfc0_hwrena (void)
1225
{
1226
    T0 = env->CP0_HWREna;
1227
    RETURN();
1228
}
1229

    
1230
void op_mfc0_badvaddr (void)
1231
{
1232
    T0 = (int32_t)env->CP0_BadVAddr;
1233
    RETURN();
1234
}
1235

    
1236
void op_mfc0_count (void)
1237
{
1238
    CALL_FROM_TB0(do_mfc0_count);
1239
    RETURN();
1240
}
1241

    
1242
void op_mfc0_entryhi (void)
1243
{
1244
    T0 = (int32_t)env->CP0_EntryHi;
1245
    RETURN();
1246
}
1247

    
1248
void op_mftc0_entryhi(void)
1249
{
1250
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1251

    
1252
    T0 = (env->CP0_EntryHi & ~0xff) | (env->CP0_TCStatus[other_tc] & 0xff);
1253
    RETURN();
1254
}
1255

    
1256
void op_mfc0_compare (void)
1257
{
1258
    T0 = env->CP0_Compare;
1259
    RETURN();
1260
}
1261

    
1262
void op_mfc0_status (void)
1263
{
1264
    T0 = env->CP0_Status;
1265
    RETURN();
1266
}
1267

    
1268
void op_mftc0_status(void)
1269
{
1270
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1271
    uint32_t tcstatus = env->CP0_TCStatus[other_tc];
1272

    
1273
    T0 = env->CP0_Status & ~0xf1000018;
1274
    T0 |= tcstatus & (0xf << CP0TCSt_TCU0);
1275
    T0 |= (tcstatus & (1 << CP0TCSt_TMX)) >> (CP0TCSt_TMX - CP0St_MX);
1276
    T0 |= (tcstatus & (0x3 << CP0TCSt_TKSU)) >> (CP0TCSt_TKSU - CP0St_KSU);
1277
    RETURN();
1278
}
1279

    
1280
void op_mfc0_intctl (void)
1281
{
1282
    T0 = env->CP0_IntCtl;
1283
    RETURN();
1284
}
1285

    
1286
void op_mfc0_srsctl (void)
1287
{
1288
    T0 = env->CP0_SRSCtl;
1289
    RETURN();
1290
}
1291

    
1292
void op_mfc0_srsmap (void)
1293
{
1294
    T0 = env->CP0_SRSMap;
1295
    RETURN();
1296
}
1297

    
1298
void op_mfc0_cause (void)
1299
{
1300
    T0 = env->CP0_Cause;
1301
    RETURN();
1302
}
1303

    
1304
void op_mfc0_epc (void)
1305
{
1306
    T0 = (int32_t)env->CP0_EPC;
1307
    RETURN();
1308
}
1309

    
1310
void op_mfc0_prid (void)
1311
{
1312
    T0 = env->CP0_PRid;
1313
    RETURN();
1314
}
1315

    
1316
void op_mfc0_ebase (void)
1317
{
1318
    T0 = env->CP0_EBase;
1319
    RETURN();
1320
}
1321

    
1322
void op_mfc0_config0 (void)
1323
{
1324
    T0 = env->CP0_Config0;
1325
    RETURN();
1326
}
1327

    
1328
void op_mfc0_config1 (void)
1329
{
1330
    T0 = env->CP0_Config1;
1331
    RETURN();
1332
}
1333

    
1334
void op_mfc0_config2 (void)
1335
{
1336
    T0 = env->CP0_Config2;
1337
    RETURN();
1338
}
1339

    
1340
void op_mfc0_config3 (void)
1341
{
1342
    T0 = env->CP0_Config3;
1343
    RETURN();
1344
}
1345

    
1346
void op_mfc0_config6 (void)
1347
{
1348
    T0 = env->CP0_Config6;
1349
    RETURN();
1350
}
1351

    
1352
void op_mfc0_config7 (void)
1353
{
1354
    T0 = env->CP0_Config7;
1355
    RETURN();
1356
}
1357

    
1358
void op_mfc0_lladdr (void)
1359
{
1360
    T0 = (int32_t)env->CP0_LLAddr >> 4;
1361
    RETURN();
1362
}
1363

    
1364
void op_mfc0_watchlo (void)
1365
{
1366
    T0 = (int32_t)env->CP0_WatchLo[PARAM1];
1367
    RETURN();
1368
}
1369

    
1370
void op_mfc0_watchhi (void)
1371
{
1372
    T0 = env->CP0_WatchHi[PARAM1];
1373
    RETURN();
1374
}
1375

    
1376
void op_mfc0_xcontext (void)
1377
{
1378
    T0 = (int32_t)env->CP0_XContext;
1379
    RETURN();
1380
}
1381

    
1382
void op_mfc0_framemask (void)
1383
{
1384
    T0 = env->CP0_Framemask;
1385
    RETURN();
1386
}
1387

    
1388
void op_mfc0_debug (void)
1389
{
1390
    T0 = env->CP0_Debug;
1391
    if (env->hflags & MIPS_HFLAG_DM)
1392
        T0 |= 1 << CP0DB_DM;
1393
    RETURN();
1394
}
1395

    
1396
void op_mftc0_debug(void)
1397
{
1398
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1399

    
1400
    /* XXX: Might be wrong, check with EJTAG spec. */
1401
    T0 = (env->CP0_Debug & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
1402
         (env->CP0_Debug_tcstatus[other_tc] &
1403
          ((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
1404
    RETURN();
1405
}
1406

    
1407
void op_mfc0_depc (void)
1408
{
1409
    T0 = (int32_t)env->CP0_DEPC;
1410
    RETURN();
1411
}
1412

    
1413
void op_mfc0_performance0 (void)
1414
{
1415
    T0 = env->CP0_Performance0;
1416
    RETURN();
1417
}
1418

    
1419
void op_mfc0_taglo (void)
1420
{
1421
    T0 = env->CP0_TagLo;
1422
    RETURN();
1423
}
1424

    
1425
void op_mfc0_datalo (void)
1426
{
1427
    T0 = env->CP0_DataLo;
1428
    RETURN();
1429
}
1430

    
1431
void op_mfc0_taghi (void)
1432
{
1433
    T0 = env->CP0_TagHi;
1434
    RETURN();
1435
}
1436

    
1437
void op_mfc0_datahi (void)
1438
{
1439
    T0 = env->CP0_DataHi;
1440
    RETURN();
1441
}
1442

    
1443
void op_mfc0_errorepc (void)
1444
{
1445
    T0 = (int32_t)env->CP0_ErrorEPC;
1446
    RETURN();
1447
}
1448

    
1449
void op_mfc0_desave (void)
1450
{
1451
    T0 = env->CP0_DESAVE;
1452
    RETURN();
1453
}
1454

    
1455
void op_mtc0_index (void)
1456
{
1457
    int num = 1;
1458
    unsigned int tmp = env->tlb->nb_tlb;
1459

    
1460
    do {
1461
        tmp >>= 1;
1462
        num <<= 1;
1463
    } while (tmp);
1464
    env->CP0_Index = (env->CP0_Index & 0x80000000) | (T0 & (num - 1));
1465
    RETURN();
1466
}
1467

    
1468
void op_mtc0_mvpcontrol (void)
1469
{
1470
    uint32_t mask = 0;
1471
    uint32_t newval;
1472

    
1473
    if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP))
1474
        mask |= (1 << CP0MVPCo_CPA) | (1 << CP0MVPCo_VPC) |
1475
                (1 << CP0MVPCo_EVP);
1476
    if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1477
        mask |= (1 << CP0MVPCo_STLB);
1478
    newval = (env->mvp->CP0_MVPControl & ~mask) | (T0 & mask);
1479

    
1480
    // TODO: Enable/disable shared TLB, enable/disable VPEs.
1481

    
1482
    env->mvp->CP0_MVPControl = newval;
1483
    RETURN();
1484
}
1485

    
1486
void op_mtc0_vpecontrol (void)
1487
{
1488
    uint32_t mask;
1489
    uint32_t newval;
1490

    
1491
    mask = (1 << CP0VPECo_YSI) | (1 << CP0VPECo_GSI) |
1492
           (1 << CP0VPECo_TE) | (0xff << CP0VPECo_TargTC);
1493
    newval = (env->CP0_VPEControl & ~mask) | (T0 & mask);
1494

    
1495
    /* Yield scheduler intercept not implemented. */
1496
    /* Gating storage scheduler intercept not implemented. */
1497

    
1498
    // TODO: Enable/disable TCs.
1499

    
1500
    env->CP0_VPEControl = newval;
1501
    RETURN();
1502
}
1503

    
1504
void op_mtc0_vpeconf0 (void)
1505
{
1506
    uint32_t mask = 0;
1507
    uint32_t newval;
1508

    
1509
    if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) {
1510
        if (env->CP0_VPEConf0 & (1 << CP0VPEC0_VPA))
1511
            mask |= (0xff << CP0VPEC0_XTC);
1512
        mask |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
1513
    }
1514
    newval = (env->CP0_VPEConf0 & ~mask) | (T0 & mask);
1515

    
1516
    // TODO: TC exclusive handling due to ERL/EXL.
1517

    
1518
    env->CP0_VPEConf0 = newval;
1519
    RETURN();
1520
}
1521

    
1522
void op_mtc0_vpeconf1 (void)
1523
{
1524
    uint32_t mask = 0;
1525
    uint32_t newval;
1526

    
1527
    if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1528
        mask |= (0xff << CP0VPEC1_NCX) | (0xff << CP0VPEC1_NCP2) |
1529
                (0xff << CP0VPEC1_NCP1);
1530
    newval = (env->CP0_VPEConf1 & ~mask) | (T0 & mask);
1531

    
1532
    /* UDI not implemented. */
1533
    /* CP2 not implemented. */
1534

    
1535
    // TODO: Handle FPU (CP1) binding.
1536

    
1537
    env->CP0_VPEConf1 = newval;
1538
    RETURN();
1539
}
1540

    
1541
void op_mtc0_yqmask (void)
1542
{
1543
    /* Yield qualifier inputs not implemented. */
1544
    env->CP0_YQMask = 0x00000000;
1545
    RETURN();
1546
}
1547

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

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

    
1560
void op_mtc0_vpeopt (void)
1561
{
1562
    env->CP0_VPEOpt = T0 & 0x0000ffff;
1563
    RETURN();
1564
}
1565

    
1566
void op_mtc0_entrylo0 (void)
1567
{
1568
    /* Large physaddr not implemented */
1569
    /* 1k pages not implemented */
1570
    env->CP0_EntryLo0 = T0 & 0x3FFFFFFF;
1571
    RETURN();
1572
}
1573

    
1574
void op_mtc0_tcstatus (void)
1575
{
1576
    uint32_t mask = env->CP0_TCStatus_rw_bitmask;
1577
    uint32_t newval;
1578

    
1579
    newval = (env->CP0_TCStatus[env->current_tc] & ~mask) | (T0 & mask);
1580

    
1581
    // TODO: Sync with CP0_Status.
1582

    
1583
    env->CP0_TCStatus[env->current_tc] = newval;
1584
    RETURN();
1585
}
1586

    
1587
void op_mttc0_tcstatus (void)
1588
{
1589
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1590

    
1591
    // TODO: Sync with CP0_Status.
1592

    
1593
    env->CP0_TCStatus[other_tc] = T0;
1594
    RETURN();
1595
}
1596

    
1597
void op_mtc0_tcbind (void)
1598
{
1599
    uint32_t mask = (1 << CP0TCBd_TBE);
1600
    uint32_t newval;
1601

    
1602
    if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1603
        mask |= (1 << CP0TCBd_CurVPE);
1604
    newval = (env->CP0_TCBind[env->current_tc] & ~mask) | (T0 & mask);
1605
    env->CP0_TCBind[env->current_tc] = newval;
1606
    RETURN();
1607
}
1608

    
1609
void op_mttc0_tcbind (void)
1610
{
1611
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1612
    uint32_t mask = (1 << CP0TCBd_TBE);
1613
    uint32_t newval;
1614

    
1615
    if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1616
        mask |= (1 << CP0TCBd_CurVPE);
1617
    newval = (env->CP0_TCBind[other_tc] & ~mask) | (T0 & mask);
1618
    env->CP0_TCBind[other_tc] = newval;
1619
    RETURN();
1620
}
1621

    
1622
void op_mtc0_tcrestart (void)
1623
{
1624
    env->PC[env->current_tc] = T0;
1625
    env->CP0_TCStatus[env->current_tc] &= ~(1 << CP0TCSt_TDS);
1626
    env->CP0_LLAddr = 0ULL;
1627
    /* MIPS16 not implemented. */
1628
    RETURN();
1629
}
1630

    
1631
void op_mttc0_tcrestart (void)
1632
{
1633
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1634

    
1635
    env->PC[other_tc] = T0;
1636
    env->CP0_TCStatus[other_tc] &= ~(1 << CP0TCSt_TDS);
1637
    env->CP0_LLAddr = 0ULL;
1638
    /* MIPS16 not implemented. */
1639
    RETURN();
1640
}
1641

    
1642
void op_mtc0_tchalt (void)
1643
{
1644
    env->CP0_TCHalt[env->current_tc] = T0 & 0x1;
1645

    
1646
    // TODO: Halt TC / Restart (if allocated+active) TC.
1647

    
1648
    RETURN();
1649
}
1650

    
1651
void op_mttc0_tchalt (void)
1652
{
1653
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1654

    
1655
    // TODO: Halt TC / Restart (if allocated+active) TC.
1656

    
1657
    env->CP0_TCHalt[other_tc] = T0;
1658
    RETURN();
1659
}
1660

    
1661
void op_mtc0_tccontext (void)
1662
{
1663
    env->CP0_TCContext[env->current_tc] = T0;
1664
    RETURN();
1665
}
1666

    
1667
void op_mttc0_tccontext (void)
1668
{
1669
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1670

    
1671
    env->CP0_TCContext[other_tc] = T0;
1672
    RETURN();
1673
}
1674

    
1675
void op_mtc0_tcschedule (void)
1676
{
1677
    env->CP0_TCSchedule[env->current_tc] = T0;
1678
    RETURN();
1679
}
1680

    
1681
void op_mttc0_tcschedule (void)
1682
{
1683
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1684

    
1685
    env->CP0_TCSchedule[other_tc] = T0;
1686
    RETURN();
1687
}
1688

    
1689
void op_mtc0_tcschefback (void)
1690
{
1691
    env->CP0_TCScheFBack[env->current_tc] = T0;
1692
    RETURN();
1693
}
1694

    
1695
void op_mttc0_tcschefback (void)
1696
{
1697
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1698

    
1699
    env->CP0_TCScheFBack[other_tc] = T0;
1700
    RETURN();
1701
}
1702

    
1703
void op_mtc0_entrylo1 (void)
1704
{
1705
    /* Large physaddr not implemented */
1706
    /* 1k pages not implemented */
1707
    env->CP0_EntryLo1 = T0 & 0x3FFFFFFF;
1708
    RETURN();
1709
}
1710

    
1711
void op_mtc0_context (void)
1712
{
1713
    env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (T0 & ~0x007FFFFF);
1714
    RETURN();
1715
}
1716

    
1717
void op_mtc0_pagemask (void)
1718
{
1719
    /* 1k pages not implemented */
1720
    env->CP0_PageMask = T0 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
1721
    RETURN();
1722
}
1723

    
1724
void op_mtc0_pagegrain (void)
1725
{
1726
    /* SmartMIPS not implemented */
1727
    /* Large physaddr not implemented */
1728
    /* 1k pages not implemented */
1729
    env->CP0_PageGrain = 0;
1730
    RETURN();
1731
}
1732

    
1733
void op_mtc0_wired (void)
1734
{
1735
    env->CP0_Wired = T0 % env->tlb->nb_tlb;
1736
    RETURN();
1737
}
1738

    
1739
void op_mtc0_srsconf0 (void)
1740
{
1741
    env->CP0_SRSConf0 |= T0 & env->CP0_SRSConf0_rw_bitmask;
1742
    RETURN();
1743
}
1744

    
1745
void op_mtc0_srsconf1 (void)
1746
{
1747
    env->CP0_SRSConf1 |= T0 & env->CP0_SRSConf1_rw_bitmask;
1748
    RETURN();
1749
}
1750

    
1751
void op_mtc0_srsconf2 (void)
1752
{
1753
    env->CP0_SRSConf2 |= T0 & env->CP0_SRSConf2_rw_bitmask;
1754
    RETURN();
1755
}
1756

    
1757
void op_mtc0_srsconf3 (void)
1758
{
1759
    env->CP0_SRSConf3 |= T0 & env->CP0_SRSConf3_rw_bitmask;
1760
    RETURN();
1761
}
1762

    
1763
void op_mtc0_srsconf4 (void)
1764
{
1765
    env->CP0_SRSConf4 |= T0 & env->CP0_SRSConf4_rw_bitmask;
1766
    RETURN();
1767
}
1768

    
1769
void op_mtc0_hwrena (void)
1770
{
1771
    env->CP0_HWREna = T0 & 0x0000000F;
1772
    RETURN();
1773
}
1774

    
1775
void op_mtc0_count (void)
1776
{
1777
    CALL_FROM_TB2(cpu_mips_store_count, env, T0);
1778
    RETURN();
1779
}
1780

    
1781
void op_mtc0_entryhi (void)
1782
{
1783
    target_ulong old, val;
1784

    
1785
    /* 1k pages not implemented */
1786
    val = T0 & ((TARGET_PAGE_MASK << 1) | 0xFF);
1787
#if defined(TARGET_MIPS64)
1788
    val &= env->SEGMask;
1789
#endif
1790
    old = env->CP0_EntryHi;
1791
    env->CP0_EntryHi = val;
1792
    if (env->CP0_Config3 & (1 << CP0C3_MT)) {
1793
        uint32_t tcst = env->CP0_TCStatus[env->current_tc] & ~0xff;
1794
        env->CP0_TCStatus[env->current_tc] = tcst | (val & 0xff);
1795
    }
1796
    /* If the ASID changes, flush qemu's TLB.  */
1797
    if ((old & 0xFF) != (val & 0xFF))
1798
        CALL_FROM_TB2(cpu_mips_tlb_flush, env, 1);
1799
    RETURN();
1800
}
1801

    
1802
void op_mttc0_entryhi(void)
1803
{
1804
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1805

    
1806
    env->CP0_EntryHi = (env->CP0_EntryHi & 0xff) | (T0 & ~0xff);
1807
    env->CP0_TCStatus[other_tc] = (env->CP0_TCStatus[other_tc] & ~0xff) | (T0 & 0xff);
1808
    RETURN();
1809
}
1810

    
1811
void op_mtc0_compare (void)
1812
{
1813
    CALL_FROM_TB2(cpu_mips_store_compare, env, T0);
1814
    RETURN();
1815
}
1816

    
1817
void op_mtc0_status (void)
1818
{
1819
    uint32_t val, old;
1820
    uint32_t mask = env->CP0_Status_rw_bitmask;
1821

    
1822
    val = T0 & mask;
1823
    old = env->CP0_Status;
1824
    env->CP0_Status = (env->CP0_Status & ~mask) | val;
1825
    CALL_FROM_TB1(compute_hflags, env);
1826
    if (loglevel & CPU_LOG_EXEC)
1827
        CALL_FROM_TB2(do_mtc0_status_debug, old, val);
1828
    CALL_FROM_TB1(cpu_mips_update_irq, env);
1829
    RETURN();
1830
}
1831

    
1832
void op_mttc0_status(void)
1833
{
1834
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1835
    uint32_t tcstatus = env->CP0_TCStatus[other_tc];
1836

    
1837
    env->CP0_Status = T0 & ~0xf1000018;
1838
    tcstatus = (tcstatus & ~(0xf << CP0TCSt_TCU0)) | (T0 & (0xf << CP0St_CU0));
1839
    tcstatus = (tcstatus & ~(1 << CP0TCSt_TMX)) | ((T0 & (1 << CP0St_MX)) << (CP0TCSt_TMX - CP0St_MX));
1840
    tcstatus = (tcstatus & ~(0x3 << CP0TCSt_TKSU)) | ((T0 & (0x3 << CP0St_KSU)) << (CP0TCSt_TKSU - CP0St_KSU));
1841
    env->CP0_TCStatus[other_tc] = tcstatus;
1842
    RETURN();
1843
}
1844

    
1845
void op_mtc0_intctl (void)
1846
{
1847
    /* vectored interrupts not implemented, no performance counters. */
1848
    env->CP0_IntCtl = (env->CP0_IntCtl & ~0x000002e0) | (T0 & 0x000002e0);
1849
    RETURN();
1850
}
1851

    
1852
void op_mtc0_srsctl (void)
1853
{
1854
    uint32_t mask = (0xf << CP0SRSCtl_ESS) | (0xf << CP0SRSCtl_PSS);
1855
    env->CP0_SRSCtl = (env->CP0_SRSCtl & ~mask) | (T0 & mask);
1856
    RETURN();
1857
}
1858

    
1859
void op_mtc0_srsmap (void)
1860
{
1861
    env->CP0_SRSMap = T0;
1862
    RETURN();
1863
}
1864

    
1865
void op_mtc0_cause (void)
1866
{
1867
    uint32_t mask = 0x00C00300;
1868
    uint32_t old = env->CP0_Cause;
1869

    
1870
    if (env->insn_flags & ISA_MIPS32R2)
1871
        mask |= 1 << CP0Ca_DC;
1872

    
1873
    env->CP0_Cause = (env->CP0_Cause & ~mask) | (T0 & mask);
1874

    
1875
    if ((old ^ env->CP0_Cause) & (1 << CP0Ca_DC)) {
1876
        if (env->CP0_Cause & (1 << CP0Ca_DC))
1877
            CALL_FROM_TB1(cpu_mips_stop_count, env);
1878
        else
1879
            CALL_FROM_TB1(cpu_mips_start_count, env);
1880
    }
1881

    
1882
    /* Handle the software interrupt as an hardware one, as they
1883
       are very similar */
1884
    if (T0 & CP0Ca_IP_mask) {
1885
        CALL_FROM_TB1(cpu_mips_update_irq, env);
1886
    }
1887
    RETURN();
1888
}
1889

    
1890
void op_mtc0_epc (void)
1891
{
1892
    env->CP0_EPC = T0;
1893
    RETURN();
1894
}
1895

    
1896
void op_mtc0_ebase (void)
1897
{
1898
    /* vectored interrupts not implemented */
1899
    /* Multi-CPU not implemented */
1900
    env->CP0_EBase = 0x80000000 | (T0 & 0x3FFFF000);
1901
    RETURN();
1902
}
1903

    
1904
void op_mtc0_config0 (void)
1905
{
1906
    env->CP0_Config0 = (env->CP0_Config0 & 0x81FFFFF8) | (T0 & 0x00000007);
1907
    RETURN();
1908
}
1909

    
1910
void op_mtc0_config2 (void)
1911
{
1912
    /* tertiary/secondary caches not implemented */
1913
    env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF);
1914
    RETURN();
1915
}
1916

    
1917
void op_mtc0_watchlo (void)
1918
{
1919
    /* Watch exceptions for instructions, data loads, data stores
1920
       not implemented. */
1921
    env->CP0_WatchLo[PARAM1] = (T0 & ~0x7);
1922
    RETURN();
1923
}
1924

    
1925
void op_mtc0_watchhi (void)
1926
{
1927
    env->CP0_WatchHi[PARAM1] = (T0 & 0x40FF0FF8);
1928
    env->CP0_WatchHi[PARAM1] &= ~(env->CP0_WatchHi[PARAM1] & T0 & 0x7);
1929
    RETURN();
1930
}
1931

    
1932
void op_mtc0_xcontext (void)
1933
{
1934
    target_ulong mask = (1ULL << (env->SEGBITS - 7)) - 1;
1935
    env->CP0_XContext = (env->CP0_XContext & mask) | (T0 & ~mask);
1936
    RETURN();
1937
}
1938

    
1939
void op_mtc0_framemask (void)
1940
{
1941
    env->CP0_Framemask = T0; /* XXX */
1942
    RETURN();
1943
}
1944

    
1945
void op_mtc0_debug (void)
1946
{
1947
    env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120);
1948
    if (T0 & (1 << CP0DB_DM))
1949
        env->hflags |= MIPS_HFLAG_DM;
1950
    else
1951
        env->hflags &= ~MIPS_HFLAG_DM;
1952
    RETURN();
1953
}
1954

    
1955
void op_mttc0_debug(void)
1956
{
1957
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1958

    
1959
    /* XXX: Might be wrong, check with EJTAG spec. */
1960
    env->CP0_Debug_tcstatus[other_tc] = T0 & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt));
1961
    env->CP0_Debug = (env->CP0_Debug & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
1962
                     (T0 & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
1963
    RETURN();
1964
}
1965

    
1966
void op_mtc0_depc (void)
1967
{
1968
    env->CP0_DEPC = T0;
1969
    RETURN();
1970
}
1971

    
1972
void op_mtc0_performance0 (void)
1973
{
1974
    env->CP0_Performance0 = T0 & 0x000007ff;
1975
    RETURN();
1976
}
1977

    
1978
void op_mtc0_taglo (void)
1979
{
1980
    env->CP0_TagLo = T0 & 0xFFFFFCF6;
1981
    RETURN();
1982
}
1983

    
1984
void op_mtc0_datalo (void)
1985
{
1986
    env->CP0_DataLo = T0; /* XXX */
1987
    RETURN();
1988
}
1989

    
1990
void op_mtc0_taghi (void)
1991
{
1992
    env->CP0_TagHi = T0; /* XXX */
1993
    RETURN();
1994
}
1995

    
1996
void op_mtc0_datahi (void)
1997
{
1998
    env->CP0_DataHi = T0; /* XXX */
1999
    RETURN();
2000
}
2001

    
2002
void op_mtc0_errorepc (void)
2003
{
2004
    env->CP0_ErrorEPC = T0;
2005
    RETURN();
2006
}
2007

    
2008
void op_mtc0_desave (void)
2009
{
2010
    env->CP0_DESAVE = T0;
2011
    RETURN();
2012
}
2013

    
2014
#if defined(TARGET_MIPS64)
2015
void op_dmfc0_yqmask (void)
2016
{
2017
    T0 = env->CP0_YQMask;
2018
    RETURN();
2019
}
2020

    
2021
void op_dmfc0_vpeschedule (void)
2022
{
2023
    T0 = env->CP0_VPESchedule;
2024
    RETURN();
2025
}
2026

    
2027
void op_dmfc0_vpeschefback (void)
2028
{
2029
    T0 = env->CP0_VPEScheFBack;
2030
    RETURN();
2031
}
2032

    
2033
void op_dmfc0_entrylo0 (void)
2034
{
2035
    T0 = env->CP0_EntryLo0;
2036
    RETURN();
2037
}
2038

    
2039
void op_dmfc0_tcrestart (void)
2040
{
2041
    T0 = env->PC[env->current_tc];
2042
    RETURN();
2043
}
2044

    
2045
void op_dmfc0_tchalt (void)
2046
{
2047
    T0 = env->CP0_TCHalt[env->current_tc];
2048
    RETURN();
2049
}
2050

    
2051
void op_dmfc0_tccontext (void)
2052
{
2053
    T0 = env->CP0_TCContext[env->current_tc];
2054
    RETURN();
2055
}
2056

    
2057
void op_dmfc0_tcschedule (void)
2058
{
2059
    T0 = env->CP0_TCSchedule[env->current_tc];
2060
    RETURN();
2061
}
2062

    
2063
void op_dmfc0_tcschefback (void)
2064
{
2065
    T0 = env->CP0_TCScheFBack[env->current_tc];
2066
    RETURN();
2067
}
2068

    
2069
void op_dmfc0_entrylo1 (void)
2070
{
2071
    T0 = env->CP0_EntryLo1;
2072
    RETURN();
2073
}
2074

    
2075
void op_dmfc0_context (void)
2076
{
2077
    T0 = env->CP0_Context;
2078
    RETURN();
2079
}
2080

    
2081
void op_dmfc0_badvaddr (void)
2082
{
2083
    T0 = env->CP0_BadVAddr;
2084
    RETURN();
2085
}
2086

    
2087
void op_dmfc0_entryhi (void)
2088
{
2089
    T0 = env->CP0_EntryHi;
2090
    RETURN();
2091
}
2092

    
2093
void op_dmfc0_epc (void)
2094
{
2095
    T0 = env->CP0_EPC;
2096
    RETURN();
2097
}
2098

    
2099
void op_dmfc0_lladdr (void)
2100
{
2101
    T0 = env->CP0_LLAddr >> 4;
2102
    RETURN();
2103
}
2104

    
2105
void op_dmfc0_watchlo (void)
2106
{
2107
    T0 = env->CP0_WatchLo[PARAM1];
2108
    RETURN();
2109
}
2110

    
2111
void op_dmfc0_xcontext (void)
2112
{
2113
    T0 = env->CP0_XContext;
2114
    RETURN();
2115
}
2116

    
2117
void op_dmfc0_depc (void)
2118
{
2119
    T0 = env->CP0_DEPC;
2120
    RETURN();
2121
}
2122

    
2123
void op_dmfc0_errorepc (void)
2124
{
2125
    T0 = env->CP0_ErrorEPC;
2126
    RETURN();
2127
}
2128
#endif /* TARGET_MIPS64 */
2129

    
2130
/* MIPS MT functions */
2131
void op_mftgpr(void)
2132
{
2133
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2134

    
2135
    T0 = env->gpr[PARAM1][other_tc];
2136
    RETURN();
2137
}
2138

    
2139
void op_mftlo(void)
2140
{
2141
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2142

    
2143
    T0 = env->LO[PARAM1][other_tc];
2144
    RETURN();
2145
}
2146

    
2147
void op_mfthi(void)
2148
{
2149
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2150

    
2151
    T0 = env->HI[PARAM1][other_tc];
2152
    RETURN();
2153
}
2154

    
2155
void op_mftacx(void)
2156
{
2157
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2158

    
2159
    T0 = env->ACX[PARAM1][other_tc];
2160
    RETURN();
2161
}
2162

    
2163
void op_mftdsp(void)
2164
{
2165
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2166

    
2167
    T0 = env->DSPControl[other_tc];
2168
    RETURN();
2169
}
2170

    
2171
void op_mttgpr(void)
2172
{
2173
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2174

    
2175
    T0 = env->gpr[PARAM1][other_tc];
2176
    RETURN();
2177
}
2178

    
2179
void op_mttlo(void)
2180
{
2181
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2182

    
2183
    T0 = env->LO[PARAM1][other_tc];
2184
    RETURN();
2185
}
2186

    
2187
void op_mtthi(void)
2188
{
2189
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2190

    
2191
    T0 = env->HI[PARAM1][other_tc];
2192
    RETURN();
2193
}
2194

    
2195
void op_mttacx(void)
2196
{
2197
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2198

    
2199
    T0 = env->ACX[PARAM1][other_tc];
2200
    RETURN();
2201
}
2202

    
2203
void op_mttdsp(void)
2204
{
2205
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2206

    
2207
    T0 = env->DSPControl[other_tc];
2208
    RETURN();
2209
}
2210

    
2211

    
2212
void op_dmt(void)
2213
{
2214
    // TODO
2215
    T0 = 0;
2216
    // rt = T0
2217
    RETURN();
2218
}
2219

    
2220
void op_emt(void)
2221
{
2222
    // TODO
2223
    T0 = 0;
2224
    // rt = T0
2225
    RETURN();
2226
}
2227

    
2228
void op_dvpe(void)
2229
{
2230
    // TODO
2231
    T0 = 0;
2232
    // rt = T0
2233
    RETURN();
2234
}
2235

    
2236
void op_evpe(void)
2237
{
2238
    // TODO
2239
    T0 = 0;
2240
    // rt = T0
2241
    RETURN();
2242
}
2243

    
2244
void op_fork(void)
2245
{
2246
    // T0 = rt, T1 = rs
2247
    T0 = 0;
2248
    // TODO: store to TC register
2249
    RETURN();
2250
}
2251

    
2252
void op_yield(void)
2253
{
2254
    if (T0 < 0) {
2255
        /* No scheduling policy implemented. */
2256
        if (T0 != -2) {
2257
            if (env->CP0_VPEControl & (1 << CP0VPECo_YSI) &&
2258
                env->CP0_TCStatus[env->current_tc] & (1 << CP0TCSt_DT)) {
2259
                env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
2260
                env->CP0_VPEControl |= 4 << CP0VPECo_EXCPT;
2261
                CALL_FROM_TB1(do_raise_exception, EXCP_THREAD);
2262
            }
2263
        }
2264
    } else if (T0 == 0) {
2265
        if (0 /* TODO: TC underflow */) {
2266
            env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
2267
            CALL_FROM_TB1(do_raise_exception, EXCP_THREAD);
2268
        } else {
2269
            // TODO: Deallocate TC
2270
        }
2271
    } else if (T0 > 0) {
2272
        /* Yield qualifier inputs not implemented. */
2273
        env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
2274
        env->CP0_VPEControl |= 2 << CP0VPECo_EXCPT;
2275
        CALL_FROM_TB1(do_raise_exception, EXCP_THREAD);
2276
    }
2277
    T0 = env->CP0_YQMask;
2278
    RETURN();
2279
}
2280

    
2281
/* CP1 functions */
2282
#if 0
2283
# define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env)
2284
#else
2285
# define DEBUG_FPU_STATE() do { } while(0)
2286
#endif
2287

    
2288
void op_cfc1 (void)
2289
{
2290
    CALL_FROM_TB1(do_cfc1, PARAM1);
2291
    DEBUG_FPU_STATE();
2292
    RETURN();
2293
}
2294

    
2295
void op_ctc1 (void)
2296
{
2297
    CALL_FROM_TB1(do_ctc1, PARAM1);
2298
    DEBUG_FPU_STATE();
2299
    RETURN();
2300
}
2301

    
2302
void op_mfc1 (void)
2303
{
2304
    T0 = (int32_t)WT0;
2305
    DEBUG_FPU_STATE();
2306
    RETURN();
2307
}
2308

    
2309
void op_mtc1 (void)
2310
{
2311
    WT0 = T0;
2312
    DEBUG_FPU_STATE();
2313
    RETURN();
2314
}
2315

    
2316
void op_dmfc1 (void)
2317
{
2318
    T0 = DT0;
2319
    DEBUG_FPU_STATE();
2320
    RETURN();
2321
}
2322

    
2323
void op_dmtc1 (void)
2324
{
2325
    DT0 = T0;
2326
    DEBUG_FPU_STATE();
2327
    RETURN();
2328
}
2329

    
2330
void op_mfhc1 (void)
2331
{
2332
    T0 = (int32_t)WTH0;
2333
    DEBUG_FPU_STATE();
2334
    RETURN();
2335
}
2336

    
2337
void op_mthc1 (void)
2338
{
2339
    WTH0 = T0;
2340
    DEBUG_FPU_STATE();
2341
    RETURN();
2342
}
2343

    
2344
/* Float support.
2345
   Single precition routines have a "s" suffix, double precision a
2346
   "d" suffix, 32bit integer "w", 64bit integer "l", paired singe "ps",
2347
   paired single lowwer "pl", paired single upper "pu".  */
2348

    
2349
#define FLOAT_OP(name, p) void OPPROTO op_float_##name##_##p(void)
2350

    
2351
FLOAT_OP(cvtd, s)
2352
{
2353
    CALL_FROM_TB0(do_float_cvtd_s);
2354
    DEBUG_FPU_STATE();
2355
    RETURN();
2356
}
2357
FLOAT_OP(cvtd, w)
2358
{
2359
    CALL_FROM_TB0(do_float_cvtd_w);
2360
    DEBUG_FPU_STATE();
2361
    RETURN();
2362
}
2363
FLOAT_OP(cvtd, l)
2364
{
2365
    CALL_FROM_TB0(do_float_cvtd_l);
2366
    DEBUG_FPU_STATE();
2367
    RETURN();
2368
}
2369
FLOAT_OP(cvtl, d)
2370
{
2371
    CALL_FROM_TB0(do_float_cvtl_d);
2372
    DEBUG_FPU_STATE();
2373
    RETURN();
2374
}
2375
FLOAT_OP(cvtl, s)
2376
{
2377
    CALL_FROM_TB0(do_float_cvtl_s);
2378
    DEBUG_FPU_STATE();
2379
    RETURN();
2380
}
2381
FLOAT_OP(cvtps, s)
2382
{
2383
    WT2 = WT0;
2384
    WTH2 = WT1;
2385
    DEBUG_FPU_STATE();
2386
    RETURN();
2387
}
2388
FLOAT_OP(cvtps, pw)
2389
{
2390
    CALL_FROM_TB0(do_float_cvtps_pw);
2391
    DEBUG_FPU_STATE();
2392
    RETURN();
2393
}
2394
FLOAT_OP(cvtpw, ps)
2395
{
2396
    CALL_FROM_TB0(do_float_cvtpw_ps);
2397
    DEBUG_FPU_STATE();
2398
    RETURN();
2399
}
2400
FLOAT_OP(cvts, d)
2401
{
2402
    CALL_FROM_TB0(do_float_cvts_d);
2403
    DEBUG_FPU_STATE();
2404
    RETURN();
2405
}
2406
FLOAT_OP(cvts, w)
2407
{
2408
    CALL_FROM_TB0(do_float_cvts_w);
2409
    DEBUG_FPU_STATE();
2410
    RETURN();
2411
}
2412
FLOAT_OP(cvts, l)
2413
{
2414
    CALL_FROM_TB0(do_float_cvts_l);
2415
    DEBUG_FPU_STATE();
2416
    RETURN();
2417
}
2418
FLOAT_OP(cvts, pl)
2419
{
2420
    CALL_FROM_TB0(do_float_cvts_pl);
2421
    DEBUG_FPU_STATE();
2422
    RETURN();
2423
}
2424
FLOAT_OP(cvts, pu)
2425
{
2426
    CALL_FROM_TB0(do_float_cvts_pu);
2427
    DEBUG_FPU_STATE();
2428
    RETURN();
2429
}
2430
FLOAT_OP(cvtw, s)
2431
{
2432
    CALL_FROM_TB0(do_float_cvtw_s);
2433
    DEBUG_FPU_STATE();
2434
    RETURN();
2435
}
2436
FLOAT_OP(cvtw, d)
2437
{
2438
    CALL_FROM_TB0(do_float_cvtw_d);
2439
    DEBUG_FPU_STATE();
2440
    RETURN();
2441
}
2442

    
2443
FLOAT_OP(pll, ps)
2444
{
2445
    DT2 = ((uint64_t)WT0 << 32) | WT1;
2446
    DEBUG_FPU_STATE();
2447
    RETURN();
2448
}
2449
FLOAT_OP(plu, ps)
2450
{
2451
    DT2 = ((uint64_t)WT0 << 32) | WTH1;
2452
    DEBUG_FPU_STATE();
2453
    RETURN();
2454
}
2455
FLOAT_OP(pul, ps)
2456
{
2457
    DT2 = ((uint64_t)WTH0 << 32) | WT1;
2458
    DEBUG_FPU_STATE();
2459
    RETURN();
2460
}
2461
FLOAT_OP(puu, ps)
2462
{
2463
    DT2 = ((uint64_t)WTH0 << 32) | WTH1;
2464
    DEBUG_FPU_STATE();
2465
    RETURN();
2466
}
2467

    
2468
#define FLOAT_ROUNDOP(op, ttype, stype)                    \
2469
FLOAT_OP(op ## ttype, stype)                               \
2470
{                                                          \
2471
    CALL_FROM_TB0(do_float_ ## op ## ttype ## _ ## stype); \
2472
    DEBUG_FPU_STATE();                                     \
2473
    RETURN();                                              \
2474
}
2475

    
2476
FLOAT_ROUNDOP(round, l, d)
2477
FLOAT_ROUNDOP(round, l, s)
2478
FLOAT_ROUNDOP(round, w, d)
2479
FLOAT_ROUNDOP(round, w, s)
2480

    
2481
FLOAT_ROUNDOP(trunc, l, d)
2482
FLOAT_ROUNDOP(trunc, l, s)
2483
FLOAT_ROUNDOP(trunc, w, d)
2484
FLOAT_ROUNDOP(trunc, w, s)
2485

    
2486
FLOAT_ROUNDOP(ceil, l, d)
2487
FLOAT_ROUNDOP(ceil, l, s)
2488
FLOAT_ROUNDOP(ceil, w, d)
2489
FLOAT_ROUNDOP(ceil, w, s)
2490

    
2491
FLOAT_ROUNDOP(floor, l, d)
2492
FLOAT_ROUNDOP(floor, l, s)
2493
FLOAT_ROUNDOP(floor, w, d)
2494
FLOAT_ROUNDOP(floor, w, s)
2495
#undef FLOAR_ROUNDOP
2496

    
2497
FLOAT_OP(movf, d)
2498
{
2499
    if (!(env->fpu->fcr31 & PARAM1))
2500
        DT2 = DT0;
2501
    DEBUG_FPU_STATE();
2502
    RETURN();
2503
}
2504
FLOAT_OP(movf, s)
2505
{
2506
    if (!(env->fpu->fcr31 & PARAM1))
2507
        WT2 = WT0;
2508
    DEBUG_FPU_STATE();
2509
    RETURN();
2510
}
2511
FLOAT_OP(movf, ps)
2512
{
2513
    if (!(env->fpu->fcr31 & PARAM1)) {
2514
        WT2 = WT0;
2515
        WTH2 = WTH0;
2516
    }
2517
    DEBUG_FPU_STATE();
2518
    RETURN();
2519
}
2520
FLOAT_OP(movt, d)
2521
{
2522
    if (env->fpu->fcr31 & PARAM1)
2523
        DT2 = DT0;
2524
    DEBUG_FPU_STATE();
2525
    RETURN();
2526
}
2527
FLOAT_OP(movt, s)
2528
{
2529
    if (env->fpu->fcr31 & PARAM1)
2530
        WT2 = WT0;
2531
    DEBUG_FPU_STATE();
2532
    RETURN();
2533
}
2534
FLOAT_OP(movt, ps)
2535
{
2536
    if (env->fpu->fcr31 & PARAM1) {
2537
        WT2 = WT0;
2538
        WTH2 = WTH0;
2539
    }
2540
    DEBUG_FPU_STATE();
2541
    RETURN();
2542
}
2543
FLOAT_OP(movz, d)
2544
{
2545
    if (!T0)
2546
        DT2 = DT0;
2547
    DEBUG_FPU_STATE();
2548
    RETURN();
2549
}
2550
FLOAT_OP(movz, s)
2551
{
2552
    if (!T0)
2553
        WT2 = WT0;
2554
    DEBUG_FPU_STATE();
2555
    RETURN();
2556
}
2557
FLOAT_OP(movz, ps)
2558
{
2559
    if (!T0) {
2560
        WT2 = WT0;
2561
        WTH2 = WTH0;
2562
    }
2563
    DEBUG_FPU_STATE();
2564
    RETURN();
2565
}
2566
FLOAT_OP(movn, d)
2567
{
2568
    if (T0)
2569
        DT2 = DT0;
2570
    DEBUG_FPU_STATE();
2571
    RETURN();
2572
}
2573
FLOAT_OP(movn, s)
2574
{
2575
    if (T0)
2576
        WT2 = WT0;
2577
    DEBUG_FPU_STATE();
2578
    RETURN();
2579
}
2580
FLOAT_OP(movn, ps)
2581
{
2582
    if (T0) {
2583
        WT2 = WT0;
2584
        WTH2 = WTH0;
2585
    }
2586
    DEBUG_FPU_STATE();
2587
    RETURN();
2588
}
2589

    
2590
/* operations calling helpers, for s, d and ps */
2591
#define FLOAT_HOP(name) \
2592
FLOAT_OP(name, d)         \
2593
{                         \
2594
    CALL_FROM_TB0(do_float_ ## name ## _d);  \
2595
    DEBUG_FPU_STATE();    \
2596
    RETURN();             \
2597
}                         \
2598
FLOAT_OP(name, s)         \
2599
{                         \
2600
    CALL_FROM_TB0(do_float_ ## name ## _s);  \
2601
    DEBUG_FPU_STATE();    \
2602
    RETURN();             \
2603
}                         \
2604
FLOAT_OP(name, ps)        \
2605
{                         \
2606
    CALL_FROM_TB0(do_float_ ## name ## _ps); \
2607
    DEBUG_FPU_STATE();    \
2608
    RETURN();             \
2609
}
2610
FLOAT_HOP(add)
2611
FLOAT_HOP(sub)
2612
FLOAT_HOP(mul)
2613
FLOAT_HOP(div)
2614
FLOAT_HOP(recip2)
2615
FLOAT_HOP(rsqrt2)
2616
FLOAT_HOP(rsqrt1)
2617
FLOAT_HOP(recip1)
2618
#undef FLOAT_HOP
2619

    
2620
/* operations calling helpers, for s and d */
2621
#define FLOAT_HOP(name)   \
2622
FLOAT_OP(name, d)         \
2623
{                         \
2624
    CALL_FROM_TB0(do_float_ ## name ## _d);  \
2625
    DEBUG_FPU_STATE();    \
2626
    RETURN();             \
2627
}                         \
2628
FLOAT_OP(name, s)         \
2629
{                         \
2630
    CALL_FROM_TB0(do_float_ ## name ## _s);  \
2631
    DEBUG_FPU_STATE();    \
2632
    RETURN();             \
2633
}
2634
FLOAT_HOP(rsqrt)
2635
FLOAT_HOP(recip)
2636
#undef FLOAT_HOP
2637

    
2638
/* operations calling helpers, for ps */
2639
#define FLOAT_HOP(name)   \
2640
FLOAT_OP(name, ps)        \
2641
{                         \
2642
    CALL_FROM_TB0(do_float_ ## name ## _ps); \
2643
    DEBUG_FPU_STATE();    \
2644
    RETURN();             \
2645
}
2646
FLOAT_HOP(addr)
2647
FLOAT_HOP(mulr)
2648
#undef FLOAT_HOP
2649

    
2650
/* ternary operations */
2651
#define FLOAT_TERNOP(name1, name2) \
2652
FLOAT_OP(name1 ## name2, d)        \
2653
{                                  \
2654
    FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status);    \
2655
    FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status);    \
2656
    DEBUG_FPU_STATE();             \
2657
    RETURN();                      \
2658
}                                  \
2659
FLOAT_OP(name1 ## name2, s)        \
2660
{                                  \
2661
    FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status);    \
2662
    FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status);    \
2663
    DEBUG_FPU_STATE();             \
2664
    RETURN();                      \
2665
}                                  \
2666
FLOAT_OP(name1 ## name2, ps)       \
2667
{                                  \
2668
    FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status);    \
2669
    FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \
2670
    FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status);    \
2671
    FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \
2672
    DEBUG_FPU_STATE();             \
2673
    RETURN();                      \
2674
}
2675
FLOAT_TERNOP(mul, add)
2676
FLOAT_TERNOP(mul, sub)
2677
#undef FLOAT_TERNOP
2678

    
2679
/* negated ternary operations */
2680
#define FLOAT_NTERNOP(name1, name2) \
2681
FLOAT_OP(n ## name1 ## name2, d)    \
2682
{                                   \
2683
    FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status);    \
2684
    FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status);    \
2685
    FDT2 ^= 1ULL << 63;             \
2686
    DEBUG_FPU_STATE();              \
2687
    RETURN();                       \
2688
}                                   \
2689
FLOAT_OP(n ## name1 ## name2, s)    \
2690
{                                   \
2691
    FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status);    \
2692
    FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status);    \
2693
    FST2 ^= 1 << 31;                \
2694
    DEBUG_FPU_STATE();              \
2695
    RETURN();                       \
2696
}                                   \
2697
FLOAT_OP(n ## name1 ## name2, ps)   \
2698
{                                   \
2699
    FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status);    \
2700
    FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \
2701
    FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status);    \
2702
    FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \
2703
    FST2 ^= 1 << 31;                \
2704
    FSTH2 ^= 1 << 31;               \
2705
    DEBUG_FPU_STATE();              \
2706
    RETURN();                       \
2707
}
2708
FLOAT_NTERNOP(mul, add)
2709
FLOAT_NTERNOP(mul, sub)
2710
#undef FLOAT_NTERNOP
2711

    
2712
/* unary operations, modifying fp status  */
2713
#define FLOAT_UNOP(name)  \
2714
FLOAT_OP(name, d)         \
2715
{                         \
2716
    FDT2 = float64_ ## name(FDT0, &env->fpu->fp_status);   \
2717
    DEBUG_FPU_STATE();    \
2718
    RETURN();                      \
2719
}                         \
2720
FLOAT_OP(name, s)         \
2721
{                         \
2722
    FST2 = float32_ ## name(FST0, &env->fpu->fp_status);   \
2723
    DEBUG_FPU_STATE();    \
2724
    RETURN();             \
2725
}
2726
FLOAT_UNOP(sqrt)
2727
#undef FLOAT_UNOP
2728

    
2729
/* unary operations, not modifying fp status  */
2730
#define FLOAT_UNOP(name)  \
2731
FLOAT_OP(name, d)         \
2732
{                         \
2733
    FDT2 = float64_ ## name(FDT0);   \
2734
    DEBUG_FPU_STATE();    \
2735
    RETURN();             \
2736
}                         \
2737
FLOAT_OP(name, s)         \
2738
{                         \
2739
    FST2 = float32_ ## name(FST0);   \
2740
    DEBUG_FPU_STATE();    \
2741
    RETURN();             \
2742
}                         \
2743
FLOAT_OP(name, ps)        \
2744
{                         \
2745
    FST2 = float32_ ## name(FST0);   \
2746
    FSTH2 = float32_ ## name(FSTH0); \
2747
    DEBUG_FPU_STATE();    \
2748
    RETURN();             \
2749
}
2750
FLOAT_UNOP(abs)
2751
FLOAT_UNOP(chs)
2752
#undef FLOAT_UNOP
2753

    
2754
FLOAT_OP(mov, d)
2755
{
2756
    FDT2 = FDT0;
2757
    DEBUG_FPU_STATE();
2758
    RETURN();
2759
}
2760
FLOAT_OP(mov, s)
2761
{
2762
    FST2 = FST0;
2763
    DEBUG_FPU_STATE();
2764
    RETURN();
2765
}
2766
FLOAT_OP(mov, ps)
2767
{
2768
    FST2 = FST0;
2769
    FSTH2 = FSTH0;
2770
    DEBUG_FPU_STATE();
2771
    RETURN();
2772
}
2773
FLOAT_OP(alnv, ps)
2774
{
2775
    switch (T0 & 0x7) {
2776
    case 0:
2777
        FST2 = FST0;
2778
        FSTH2 = FSTH0;
2779
        break;
2780
    case 4:
2781
#ifdef TARGET_WORDS_BIGENDIAN
2782
        FSTH2 = FST0;
2783
        FST2 = FSTH1;
2784
#else
2785
        FSTH2 = FST1;
2786
        FST2 = FSTH0;
2787
#endif
2788
        break;
2789
    default: /* unpredictable */
2790
        break;
2791
    }
2792
    DEBUG_FPU_STATE();
2793
    RETURN();
2794
}
2795

    
2796
#ifdef CONFIG_SOFTFLOAT
2797
#define clear_invalid() do {                                \
2798
    int flags = get_float_exception_flags(&env->fpu->fp_status); \
2799
    flags &= ~float_flag_invalid;                           \
2800
    set_float_exception_flags(flags, &env->fpu->fp_status);      \
2801
} while(0)
2802
#else
2803
#define clear_invalid() do { } while(0)
2804
#endif
2805

    
2806
extern void dump_fpu_s(CPUState *env);
2807

    
2808
#define CMP_OP(fmt, op)                                \
2809
void OPPROTO op_cmp ## _ ## fmt ## _ ## op(void)       \
2810
{                                                      \
2811
    CALL_FROM_TB1(do_cmp ## _ ## fmt ## _ ## op, PARAM1); \
2812
    DEBUG_FPU_STATE();                                 \
2813
    RETURN();                                          \
2814
}                                                      \
2815
void OPPROTO op_cmpabs ## _ ## fmt ## _ ## op(void)    \
2816
{                                                      \
2817
    CALL_FROM_TB1(do_cmpabs ## _ ## fmt ## _ ## op, PARAM1); \
2818
    DEBUG_FPU_STATE();                                 \
2819
    RETURN();                                          \
2820
}
2821
#define CMP_OPS(op)   \
2822
CMP_OP(d, op)         \
2823
CMP_OP(s, op)         \
2824
CMP_OP(ps, op)
2825

    
2826
CMP_OPS(f)
2827
CMP_OPS(un)
2828
CMP_OPS(eq)
2829
CMP_OPS(ueq)
2830
CMP_OPS(olt)
2831
CMP_OPS(ult)
2832
CMP_OPS(ole)
2833
CMP_OPS(ule)
2834
CMP_OPS(sf)
2835
CMP_OPS(ngle)
2836
CMP_OPS(seq)
2837
CMP_OPS(ngl)
2838
CMP_OPS(lt)
2839
CMP_OPS(nge)
2840
CMP_OPS(le)
2841
CMP_OPS(ngt)
2842
#undef CMP_OPS
2843
#undef CMP_OP
2844

    
2845
void op_bc1f (void)
2846
{
2847
    T0 = !!(~GET_FP_COND(env->fpu) & (0x1 << PARAM1));
2848
    DEBUG_FPU_STATE();
2849
    RETURN();
2850
}
2851
void op_bc1any2f (void)
2852
{
2853
    T0 = !!(~GET_FP_COND(env->fpu) & (0x3 << PARAM1));
2854
    DEBUG_FPU_STATE();
2855
    RETURN();
2856
}
2857
void op_bc1any4f (void)
2858
{
2859
    T0 = !!(~GET_FP_COND(env->fpu) & (0xf << PARAM1));
2860
    DEBUG_FPU_STATE();
2861
    RETURN();
2862
}
2863

    
2864
void op_bc1t (void)
2865
{
2866
    T0 = !!(GET_FP_COND(env->fpu) & (0x1 << PARAM1));
2867
    DEBUG_FPU_STATE();
2868
    RETURN();
2869
}
2870
void op_bc1any2t (void)
2871
{
2872
    T0 = !!(GET_FP_COND(env->fpu) & (0x3 << PARAM1));
2873
    DEBUG_FPU_STATE();
2874
    RETURN();
2875
}
2876
void op_bc1any4t (void)
2877
{
2878
    T0 = !!(GET_FP_COND(env->fpu) & (0xf << PARAM1));
2879
    DEBUG_FPU_STATE();
2880
    RETURN();
2881
}
2882

    
2883
void op_tlbwi (void)
2884
{
2885
    CALL_FROM_TB0(env->tlb->do_tlbwi);
2886
    RETURN();
2887
}
2888

    
2889
void op_tlbwr (void)
2890
{
2891
    CALL_FROM_TB0(env->tlb->do_tlbwr);
2892
    RETURN();
2893
}
2894

    
2895
void op_tlbp (void)
2896
{
2897
    CALL_FROM_TB0(env->tlb->do_tlbp);
2898
    RETURN();
2899
}
2900

    
2901
void op_tlbr (void)
2902
{
2903
    CALL_FROM_TB0(env->tlb->do_tlbr);
2904
    RETURN();
2905
}
2906

    
2907
/* Specials */
2908
#if defined (CONFIG_USER_ONLY)
2909
void op_tls_value (void)
2910
{
2911
    T0 = env->tls_value;
2912
}
2913
#endif
2914

    
2915
void op_pmon (void)
2916
{
2917
    CALL_FROM_TB1(do_pmon, PARAM1);
2918
    RETURN();
2919
}
2920

    
2921
void op_di (void)
2922
{
2923
    T0 = env->CP0_Status;
2924
    env->CP0_Status = T0 & ~(1 << CP0St_IE);
2925
    CALL_FROM_TB1(cpu_mips_update_irq, env);
2926
    RETURN();
2927
}
2928

    
2929
void op_ei (void)
2930
{
2931
    T0 = env->CP0_Status;
2932
    env->CP0_Status = T0 | (1 << CP0St_IE);
2933
    CALL_FROM_TB1(cpu_mips_update_irq, env);
2934
    RETURN();
2935
}
2936

    
2937
void op_trap (void)
2938
{
2939
    if (T0) {
2940
        CALL_FROM_TB1(do_raise_exception, EXCP_TRAP);
2941
    }
2942
    RETURN();
2943
}
2944

    
2945
void op_debug (void)
2946
{
2947
    CALL_FROM_TB1(do_raise_exception, EXCP_DEBUG);
2948
    RETURN();
2949
}
2950

    
2951
void op_set_lladdr (void)
2952
{
2953
    env->CP0_LLAddr = T2;
2954
    RETURN();
2955
}
2956

    
2957
void debug_pre_eret (void);
2958
void debug_post_eret (void);
2959
void op_eret (void)
2960
{
2961
    if (loglevel & CPU_LOG_EXEC)
2962
        CALL_FROM_TB0(debug_pre_eret);
2963
    if (env->CP0_Status & (1 << CP0St_ERL)) {
2964
        env->PC[env->current_tc] = env->CP0_ErrorEPC;
2965
        env->CP0_Status &= ~(1 << CP0St_ERL);
2966
    } else {
2967
        env->PC[env->current_tc] = env->CP0_EPC;
2968
        env->CP0_Status &= ~(1 << CP0St_EXL);
2969
    }
2970
    CALL_FROM_TB1(compute_hflags, env);
2971
    if (loglevel & CPU_LOG_EXEC)
2972
        CALL_FROM_TB0(debug_post_eret);
2973
    env->CP0_LLAddr = 1;
2974
    RETURN();
2975
}
2976

    
2977
void op_deret (void)
2978
{
2979
    if (loglevel & CPU_LOG_EXEC)
2980
        CALL_FROM_TB0(debug_pre_eret);
2981
    env->PC[env->current_tc] = env->CP0_DEPC;
2982
    env->hflags &= MIPS_HFLAG_DM;
2983
    CALL_FROM_TB1(compute_hflags, env);
2984
    if (loglevel & CPU_LOG_EXEC)
2985
        CALL_FROM_TB0(debug_post_eret);
2986
    env->CP0_LLAddr = 1;
2987
    RETURN();
2988
}
2989

    
2990
void op_rdhwr_cpunum(void)
2991
{
2992
    if ((env->hflags & MIPS_HFLAG_CP0) ||
2993
        (env->CP0_HWREna & (1 << 0)))
2994
        T0 = env->CP0_EBase & 0x3ff;
2995
    else
2996
        CALL_FROM_TB1(do_raise_exception, EXCP_RI);
2997
    RETURN();
2998
}
2999

    
3000
void op_rdhwr_synci_step(void)
3001
{
3002
    if ((env->hflags & MIPS_HFLAG_CP0) ||
3003
        (env->CP0_HWREna & (1 << 1)))
3004
        T0 = env->SYNCI_Step;
3005
    else
3006
        CALL_FROM_TB1(do_raise_exception, EXCP_RI);
3007
    RETURN();
3008
}
3009

    
3010
void op_rdhwr_cc(void)
3011
{
3012
    if ((env->hflags & MIPS_HFLAG_CP0) ||
3013
        (env->CP0_HWREna & (1 << 2)))
3014
        T0 = env->CP0_Count;
3015
    else
3016
        CALL_FROM_TB1(do_raise_exception, EXCP_RI);
3017
    RETURN();
3018
}
3019

    
3020
void op_rdhwr_ccres(void)
3021
{
3022
    if ((env->hflags & MIPS_HFLAG_CP0) ||
3023
        (env->CP0_HWREna & (1 << 3)))
3024
        T0 = env->CCRes;
3025
    else
3026
        CALL_FROM_TB1(do_raise_exception, EXCP_RI);
3027
    RETURN();
3028
}
3029

    
3030
void op_save_state (void)
3031
{
3032
    env->hflags = PARAM1;
3033
    RETURN();
3034
}
3035

    
3036
void op_save_pc (void)
3037
{
3038
    env->PC[env->current_tc] = PARAM1;
3039
    RETURN();
3040
}
3041

    
3042
#if defined(TARGET_MIPS64)
3043
void op_save_pc64 (void)
3044
{
3045
    env->PC[env->current_tc] = ((uint64_t)PARAM1 << 32) | (uint32_t)PARAM2;
3046
    RETURN();
3047
}
3048
#endif
3049

    
3050
void op_interrupt_restart (void)
3051
{
3052
    if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
3053
        !(env->CP0_Status & (1 << CP0St_ERL)) &&
3054
        !(env->hflags & MIPS_HFLAG_DM) &&
3055
        (env->CP0_Status & (1 << CP0St_IE)) &&
3056
        (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask)) {
3057
        env->CP0_Cause &= ~(0x1f << CP0Ca_EC);
3058
        CALL_FROM_TB1(do_raise_exception, EXCP_EXT_INTERRUPT);
3059
    }
3060
    RETURN();
3061
}
3062

    
3063
void op_raise_exception (void)
3064
{
3065
    CALL_FROM_TB1(do_raise_exception, PARAM1);
3066
    RETURN();
3067
}
3068

    
3069
void op_raise_exception_err (void)
3070
{
3071
    CALL_FROM_TB2(do_raise_exception_err, PARAM1, PARAM2);
3072
    RETURN();
3073
}
3074

    
3075
void op_exit_tb (void)
3076
{
3077
    EXIT_TB();
3078
    RETURN();
3079
}
3080

    
3081
void op_wait (void)
3082
{
3083
    env->halted = 1;
3084
    CALL_FROM_TB1(do_raise_exception, EXCP_HLT);
3085
    RETURN();
3086
}
3087

    
3088
/* Bitfield operations. */
3089
void op_ext(void)
3090
{
3091
    unsigned int pos = PARAM1;
3092
    unsigned int size = PARAM2;
3093

    
3094
    T0 = ((uint32_t)T1 >> pos) & ((size < 32) ? ((1 << size) - 1) : ~0);
3095
    RETURN();
3096
}
3097

    
3098
void op_ins(void)
3099
{
3100
    unsigned int pos = PARAM1;
3101
    unsigned int size = PARAM2;
3102
    target_ulong mask = ((size < 32) ? ((1 << size) - 1) : ~0) << pos;
3103

    
3104
    T0 = (T0 & ~mask) | (((uint32_t)T1 << pos) & mask);
3105
    RETURN();
3106
}
3107

    
3108
void op_wsbh(void)
3109
{
3110
    T0 = ((T1 << 8) & ~0x00FF00FF) | ((T1 >> 8) & 0x00FF00FF);
3111
    RETURN();
3112
}
3113

    
3114
#if defined(TARGET_MIPS64)
3115
void op_dext(void)
3116
{
3117
    unsigned int pos = PARAM1;
3118
    unsigned int size = PARAM2;
3119

    
3120
    T0 = (T1 >> pos) & ((size < 32) ? ((1 << size) - 1) : ~0);
3121
    RETURN();
3122
}
3123

    
3124
void op_dins(void)
3125
{
3126
    unsigned int pos = PARAM1;
3127
    unsigned int size = PARAM2;
3128
    target_ulong mask = ((size < 32) ? ((1 << size) - 1) : ~0) << pos;
3129

    
3130
    T0 = (T0 & ~mask) | ((T1 << pos) & mask);
3131
    RETURN();
3132
}
3133

    
3134
void op_dsbh(void)
3135
{
3136
    T0 = ((T1 << 8) & ~0x00FF00FF00FF00FFULL) | ((T1 >> 8) & 0x00FF00FF00FF00FFULL);
3137
    RETURN();
3138
}
3139

    
3140
void op_dshd(void)
3141
{
3142
    T0 = ((T1 << 16) & ~0x0000FFFF0000FFFFULL) | ((T1 >> 16) & 0x0000FFFF0000FFFFULL);
3143
    RETURN();
3144
}
3145
#endif
3146

    
3147
void op_seb(void)
3148
{
3149
    T0 = ((T1 & 0xFF) ^ 0x80) - 0x80;
3150
    RETURN();
3151
}
3152

    
3153
void op_seh(void)
3154
{
3155
    T0 = ((T1 & 0xFFFF) ^ 0x8000) - 0x8000;
3156
    RETURN();
3157
}