~vcs-imports/qemu/git

« back to all changes in this revision

Viewing changes to target-mips/op.c

  • Committer: ths
  • Date: 2007-10-08 12:45:38 UTC
  • Revision ID: git-v1:450d4ff553af32fc9d83fef20d7106b0151526b8
CRIS disassembler, originally from binutils, by Edgar E. Iglesias.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3356 c046a42c-6fe2-441c-8c8c-71466251a162

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
26
#ifndef CALL_FROM_TB0
 
27
#define CALL_FROM_TB0(func) func()
 
28
#endif
 
29
#ifndef CALL_FROM_TB1
 
30
#define CALL_FROM_TB1(func, arg0) func(arg0)
 
31
#endif
 
32
#ifndef CALL_FROM_TB1_CONST16
 
33
#define CALL_FROM_TB1_CONST16(func, arg0) CALL_FROM_TB1(func, arg0)
 
34
#endif
 
35
#ifndef CALL_FROM_TB2
 
36
#define CALL_FROM_TB2(func, arg0, arg1) func(arg0, arg1)
 
37
#endif
 
38
#ifndef CALL_FROM_TB2_CONST16
 
39
#define CALL_FROM_TB2_CONST16(func, arg0, arg1)     \
 
40
        CALL_FROM_TB2(func, arg0, arg1)
 
41
#endif
 
42
#ifndef CALL_FROM_TB3
 
43
#define CALL_FROM_TB3(func, arg0, arg1, arg2) func(arg0, arg1, arg2)
 
44
#endif
 
45
#ifndef CALL_FROM_TB4
 
46
#define CALL_FROM_TB4(func, arg0, arg1, arg2, arg3) \
 
47
        func(arg0, arg1, arg2, arg3)
 
48
#endif
 
49
 
 
50
#define REG 1
 
51
#include "op_template.c"
 
52
#undef REG
 
53
#define REG 2
 
54
#include "op_template.c"
 
55
#undef REG
 
56
#define REG 3
 
57
#include "op_template.c"
 
58
#undef REG
 
59
#define REG 4
 
60
#include "op_template.c"
 
61
#undef REG
 
62
#define REG 5
 
63
#include "op_template.c"
 
64
#undef REG
 
65
#define REG 6
 
66
#include "op_template.c"
 
67
#undef REG
 
68
#define REG 7
 
69
#include "op_template.c"
 
70
#undef REG
 
71
#define REG 8
 
72
#include "op_template.c"
 
73
#undef REG
 
74
#define REG 9
 
75
#include "op_template.c"
 
76
#undef REG
 
77
#define REG 10
 
78
#include "op_template.c"
 
79
#undef REG
 
80
#define REG 11
 
81
#include "op_template.c"
 
82
#undef REG
 
83
#define REG 12
 
84
#include "op_template.c"
 
85
#undef REG
 
86
#define REG 13
 
87
#include "op_template.c"
 
88
#undef REG
 
89
#define REG 14
 
90
#include "op_template.c"
 
91
#undef REG
 
92
#define REG 15
 
93
#include "op_template.c"
 
94
#undef REG
 
95
#define REG 16
 
96
#include "op_template.c"
 
97
#undef REG
 
98
#define REG 17
 
99
#include "op_template.c"
 
100
#undef REG
 
101
#define REG 18
 
102
#include "op_template.c"
 
103
#undef REG
 
104
#define REG 19
 
105
#include "op_template.c"
 
106
#undef REG
 
107
#define REG 20
 
108
#include "op_template.c"
 
109
#undef REG
 
110
#define REG 21
 
111
#include "op_template.c"
 
112
#undef REG
 
113
#define REG 22
 
114
#include "op_template.c"
 
115
#undef REG
 
116
#define REG 23
 
117
#include "op_template.c"
 
118
#undef REG
 
119
#define REG 24
 
120
#include "op_template.c"
 
121
#undef REG
 
122
#define REG 25
 
123
#include "op_template.c"
 
124
#undef REG
 
125
#define REG 26
 
126
#include "op_template.c"
 
127
#undef REG
 
128
#define REG 27
 
129
#include "op_template.c"
 
130
#undef REG
 
131
#define REG 28
 
132
#include "op_template.c"
 
133
#undef REG
 
134
#define REG 29
 
135
#include "op_template.c"
 
136
#undef REG
 
137
#define REG 30
 
138
#include "op_template.c"
 
139
#undef REG
 
140
#define REG 31
 
141
#include "op_template.c"
 
142
#undef REG
 
143
 
 
144
#define TN
 
145
#include "op_template.c"
 
146
#undef TN
 
147
 
 
148
#define FREG 0
 
149
#include "fop_template.c"
 
150
#undef FREG
 
151
#define FREG 1
 
152
#include "fop_template.c"
 
153
#undef FREG
 
154
#define FREG 2
 
155
#include "fop_template.c"
 
156
#undef FREG
 
157
#define FREG 3
 
158
#include "fop_template.c"
 
159
#undef FREG
 
160
#define FREG 4
 
161
#include "fop_template.c"
 
162
#undef FREG
 
163
#define FREG 5
 
164
#include "fop_template.c"
 
165
#undef FREG
 
166
#define FREG 6
 
167
#include "fop_template.c"
 
168
#undef FREG
 
169
#define FREG 7
 
170
#include "fop_template.c"
 
171
#undef FREG
 
172
#define FREG 8
 
173
#include "fop_template.c"
 
174
#undef FREG
 
175
#define FREG 9
 
176
#include "fop_template.c"
 
177
#undef FREG
 
178
#define FREG 10
 
179
#include "fop_template.c"
 
180
#undef FREG
 
181
#define FREG 11
 
182
#include "fop_template.c"
 
183
#undef FREG
 
184
#define FREG 12
 
185
#include "fop_template.c"
 
186
#undef FREG
 
187
#define FREG 13
 
188
#include "fop_template.c"
 
189
#undef FREG
 
190
#define FREG 14
 
191
#include "fop_template.c"
 
192
#undef FREG
 
193
#define FREG 15
 
194
#include "fop_template.c"
 
195
#undef FREG
 
196
#define FREG 16
 
197
#include "fop_template.c"
 
198
#undef FREG
 
199
#define FREG 17
 
200
#include "fop_template.c"
 
201
#undef FREG
 
202
#define FREG 18
 
203
#include "fop_template.c"
 
204
#undef FREG
 
205
#define FREG 19
 
206
#include "fop_template.c"
 
207
#undef FREG
 
208
#define FREG 20
 
209
#include "fop_template.c"
 
210
#undef FREG
 
211
#define FREG 21
 
212
#include "fop_template.c"
 
213
#undef FREG
 
214
#define FREG 22
 
215
#include "fop_template.c"
 
216
#undef FREG
 
217
#define FREG 23
 
218
#include "fop_template.c"
 
219
#undef FREG
 
220
#define FREG 24
 
221
#include "fop_template.c"
 
222
#undef FREG
 
223
#define FREG 25
 
224
#include "fop_template.c"
 
225
#undef FREG
 
226
#define FREG 26
 
227
#include "fop_template.c"
 
228
#undef FREG
 
229
#define FREG 27
 
230
#include "fop_template.c"
 
231
#undef FREG
 
232
#define FREG 28
 
233
#include "fop_template.c"
 
234
#undef FREG
 
235
#define FREG 29
 
236
#include "fop_template.c"
 
237
#undef FREG
 
238
#define FREG 30
 
239
#include "fop_template.c"
 
240
#undef FREG
 
241
#define FREG 31
 
242
#include "fop_template.c"
 
243
#undef FREG
 
244
 
 
245
#define FTN
 
246
#include "fop_template.c"
 
247
#undef FTN
 
248
 
 
249
void op_dup_T0 (void)
 
250
{
 
251
    T2 = T0;
 
252
    RETURN();
 
253
}
 
254
 
 
255
void op_load_HI (void)
 
256
{
 
257
    T0 = env->HI[PARAM1][env->current_tc];
 
258
    RETURN();
 
259
}
 
260
 
 
261
void op_store_HI (void)
 
262
{
 
263
    env->HI[PARAM1][env->current_tc] = T0;
 
264
    RETURN();
 
265
}
 
266
 
 
267
void op_load_LO (void)
 
268
{
 
269
    T0 = env->LO[PARAM1][env->current_tc];
 
270
    RETURN();
 
271
}
 
272
 
 
273
void op_store_LO (void)
 
274
{
 
275
    env->LO[PARAM1][env->current_tc] = T0;
 
276
    RETURN();
 
277
}
 
278
 
 
279
/* Load and store */
 
280
#define MEMSUFFIX _raw
 
281
#include "op_mem.c"
 
282
#undef MEMSUFFIX
 
283
#if !defined(CONFIG_USER_ONLY)
 
284
#define MEMSUFFIX _user
 
285
#include "op_mem.c"
 
286
#undef MEMSUFFIX
 
287
 
 
288
#define MEMSUFFIX _kernel
 
289
#include "op_mem.c"
 
290
#undef MEMSUFFIX
 
291
#endif
 
292
 
 
293
/* Addresses computation */
 
294
void op_addr_add (void)
 
295
{
 
296
/* For compatibility with 32-bit code, data reference in user mode
 
297
   with Status_UX = 0 should be casted to 32-bit and sign extended.
 
298
   See the MIPS64 PRA manual, section 4.10. */
 
299
#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
 
300
    if ((env->hflags & MIPS_HFLAG_UM) &&
 
301
        !(env->CP0_Status & (1 << CP0St_UX)))
 
302
        T0 = (int64_t)(int32_t)(T0 + T1);
 
303
    else
 
304
#endif
 
305
        T0 += T1;
 
306
    RETURN();
 
307
}
 
308
 
 
309
/* Arithmetic */
 
310
void op_add (void)
 
311
{
 
312
    T0 = (int32_t)((int32_t)T0 + (int32_t)T1);
 
313
    RETURN();
 
314
}
 
315
 
 
316
void op_addo (void)
 
317
{
 
318
    target_ulong tmp;
 
319
 
 
320
    tmp = (int32_t)T0;
 
321
    T0 = (int32_t)T0 + (int32_t)T1;
 
322
    if (((tmp ^ T1 ^ (-1)) & (T0 ^ T1)) >> 31) {
 
323
        /* operands of same sign, result different sign */
 
324
        CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
 
325
    }
 
326
    T0 = (int32_t)T0;
 
327
    RETURN();
 
328
}
 
329
 
 
330
void op_sub (void)
 
331
{
 
332
    T0 = (int32_t)((int32_t)T0 - (int32_t)T1);
 
333
    RETURN();
 
334
}
 
335
 
 
336
void op_subo (void)
 
337
{
 
338
    target_ulong tmp;
 
339
 
 
340
    tmp = (int32_t)T0;
 
341
    T0 = (int32_t)T0 - (int32_t)T1;
 
342
    if (((tmp ^ T1) & (tmp ^ T0)) >> 31) {
 
343
        /* operands of different sign, first operand and result different sign */
 
344
        CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
 
345
    }
 
346
    T0 = (int32_t)T0;
 
347
    RETURN();
 
348
}
 
349
 
 
350
void op_mul (void)
 
351
{
 
352
    T0 = (int32_t)((int32_t)T0 * (int32_t)T1);
 
353
    RETURN();
 
354
}
 
355
 
 
356
#if HOST_LONG_BITS < 64
 
357
void op_div (void)
 
358
{
 
359
    CALL_FROM_TB0(do_div);
 
360
    RETURN();
 
361
}
 
362
#else
 
363
void op_div (void)
 
364
{
 
365
    if (T1 != 0) {
 
366
        env->LO[0][env->current_tc] = (int32_t)((int64_t)(int32_t)T0 / (int32_t)T1);
 
367
        env->HI[0][env->current_tc] = (int32_t)((int64_t)(int32_t)T0 % (int32_t)T1);
 
368
    }
 
369
    RETURN();
 
370
}
 
371
#endif
 
372
 
 
373
void op_divu (void)
 
374
{
 
375
    if (T1 != 0) {
 
376
        env->LO[0][env->current_tc] = (int32_t)((uint32_t)T0 / (uint32_t)T1);
 
377
        env->HI[0][env->current_tc] = (int32_t)((uint32_t)T0 % (uint32_t)T1);
 
378
    }
 
379
    RETURN();
 
380
}
 
381
 
 
382
#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
 
383
/* Arithmetic */
 
384
void op_dadd (void)
 
385
{
 
386
    T0 += T1;
 
387
    RETURN();
 
388
}
 
389
 
 
390
void op_daddo (void)
 
391
{
 
392
    target_long tmp;
 
393
 
 
394
    tmp = T0;
 
395
    T0 += T1;
 
396
    if (((tmp ^ T1 ^ (-1)) & (T0 ^ T1)) >> 63) {
 
397
        /* operands of same sign, result different sign */
 
398
        CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
 
399
    }
 
400
    RETURN();
 
401
}
 
402
 
 
403
void op_dsub (void)
 
404
{
 
405
    T0 -= T1;
 
406
    RETURN();
 
407
}
 
408
 
 
409
void op_dsubo (void)
 
410
{
 
411
    target_long tmp;
 
412
 
 
413
    tmp = T0;
 
414
    T0 = (int64_t)T0 - (int64_t)T1;
 
415
    if (((tmp ^ T1) & (tmp ^ T0)) >> 63) {
 
416
        /* operands of different sign, first operand and result different sign */
 
417
        CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
 
418
    }
 
419
    RETURN();
 
420
}
 
421
 
 
422
void op_dmul (void)
 
423
{
 
424
    T0 = (int64_t)T0 * (int64_t)T1;
 
425
    RETURN();
 
426
}
 
427
 
 
428
/* Those might call libgcc functions.  */
 
429
void op_ddiv (void)
 
430
{
 
431
    do_ddiv();
 
432
    RETURN();
 
433
}
 
434
 
 
435
#if TARGET_LONG_BITS > HOST_LONG_BITS
 
436
void op_ddivu (void)
 
437
{
 
438
    do_ddivu();
 
439
    RETURN();
 
440
}
 
441
#else
 
442
void op_ddivu (void)
 
443
{
 
444
    if (T1 != 0) {
 
445
        env->LO[0][env->current_tc] = T0 / T1;
 
446
        env->HI[0][env->current_tc] = T0 % T1;
 
447
    }
 
448
    RETURN();
 
449
}
 
450
#endif
 
451
#endif /* TARGET_MIPSN32 || TARGET_MIPS64 */
 
452
 
 
453
/* Logical */
 
454
void op_and (void)
 
455
{
 
456
    T0 &= T1;
 
457
    RETURN();
 
458
}
 
459
 
 
460
void op_nor (void)
 
461
{
 
462
    T0 = ~(T0 | T1);
 
463
    RETURN();
 
464
}
 
465
 
 
466
void op_or (void)
 
467
{
 
468
    T0 |= T1;
 
469
    RETURN();
 
470
}
 
471
 
 
472
void op_xor (void)
 
473
{
 
474
    T0 ^= T1;
 
475
    RETURN();
 
476
}
 
477
 
 
478
void op_sll (void)
 
479
{
 
480
    T0 = (int32_t)((uint32_t)T0 << T1);
 
481
    RETURN();
 
482
}
 
483
 
 
484
void op_sra (void)
 
485
{
 
486
    T0 = (int32_t)((int32_t)T0 >> T1);
 
487
    RETURN();
 
488
}
 
489
 
 
490
void op_srl (void)
 
491
{
 
492
    T0 = (int32_t)((uint32_t)T0 >> T1);
 
493
    RETURN();
 
494
}
 
495
 
 
496
void op_rotr (void)
 
497
{
 
498
    target_ulong tmp;
 
499
 
 
500
    if (T1) {
 
501
       tmp = (int32_t)((uint32_t)T0 << (0x20 - T1));
 
502
       T0 = (int32_t)((uint32_t)T0 >> T1) | tmp;
 
503
    }
 
504
    RETURN();
 
505
}
 
506
 
 
507
void op_sllv (void)
 
508
{
 
509
    T0 = (int32_t)((uint32_t)T1 << ((uint32_t)T0 & 0x1F));
 
510
    RETURN();
 
511
}
 
512
 
 
513
void op_srav (void)
 
514
{
 
515
    T0 = (int32_t)((int32_t)T1 >> (T0 & 0x1F));
 
516
    RETURN();
 
517
}
 
518
 
 
519
void op_srlv (void)
 
520
{
 
521
    T0 = (int32_t)((uint32_t)T1 >> (T0 & 0x1F));
 
522
    RETURN();
 
523
}
 
524
 
 
525
void op_rotrv (void)
 
526
{
 
527
    target_ulong tmp;
 
528
 
 
529
    T0 &= 0x1F;
 
530
    if (T0) {
 
531
       tmp = (int32_t)((uint32_t)T1 << (0x20 - T0));
 
532
       T0 = (int32_t)((uint32_t)T1 >> T0) | tmp;
 
533
    } else
 
534
       T0 = T1;
 
535
    RETURN();
 
536
}
 
537
 
 
538
void op_clo (void)
 
539
{
 
540
    int n;
 
541
 
 
542
    if (T0 == ~((target_ulong)0)) {
 
543
        T0 = 32;
 
544
    } else {
 
545
        for (n = 0; n < 32; n++) {
 
546
            if (!(T0 & (1 << 31)))
 
547
                break;
 
548
            T0 = T0 << 1;
 
549
        }
 
550
        T0 = n;
 
551
    }
 
552
    RETURN();
 
553
}
 
554
 
 
555
void op_clz (void)
 
556
{
 
557
    int n;
 
558
 
 
559
    if (T0 == 0) {
 
560
        T0 = 32;
 
561
    } else {
 
562
        for (n = 0; n < 32; n++) {
 
563
            if (T0 & (1 << 31))
 
564
                break;
 
565
            T0 = T0 << 1;
 
566
        }
 
567
        T0 = n;
 
568
    }
 
569
    RETURN();
 
570
}
 
571
 
 
572
#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
 
573
 
 
574
#if TARGET_LONG_BITS > HOST_LONG_BITS
 
575
/* Those might call libgcc functions.  */
 
576
void op_dsll (void)
 
577
{
 
578
    CALL_FROM_TB0(do_dsll);
 
579
    RETURN();
 
580
}
 
581
 
 
582
void op_dsll32 (void)
 
583
{
 
584
    CALL_FROM_TB0(do_dsll32);
 
585
    RETURN();
 
586
}
 
587
 
 
588
void op_dsra (void)
 
589
{
 
590
    CALL_FROM_TB0(do_dsra);
 
591
    RETURN();
 
592
}
 
593
 
 
594
void op_dsra32 (void)
 
595
{
 
596
    CALL_FROM_TB0(do_dsra32);
 
597
    RETURN();
 
598
}
 
599
 
 
600
void op_dsrl (void)
 
601
{
 
602
    CALL_FROM_TB0(do_dsrl);
 
603
    RETURN();
 
604
}
 
605
 
 
606
void op_dsrl32 (void)
 
607
{
 
608
    CALL_FROM_TB0(do_dsrl32);
 
609
    RETURN();
 
610
}
 
611
 
 
612
void op_drotr (void)
 
613
{
 
614
    CALL_FROM_TB0(do_drotr);
 
615
    RETURN();
 
616
}
 
617
 
 
618
void op_drotr32 (void)
 
619
{
 
620
    CALL_FROM_TB0(do_drotr32);
 
621
    RETURN();
 
622
}
 
623
 
 
624
void op_dsllv (void)
 
625
{
 
626
    CALL_FROM_TB0(do_dsllv);
 
627
    RETURN();
 
628
}
 
629
 
 
630
void op_dsrav (void)
 
631
{
 
632
    CALL_FROM_TB0(do_dsrav);
 
633
    RETURN();
 
634
}
 
635
 
 
636
void op_dsrlv (void)
 
637
{
 
638
    CALL_FROM_TB0(do_dsrlv);
 
639
    RETURN();
 
640
}
 
641
 
 
642
void op_drotrv (void)
 
643
{
 
644
    CALL_FROM_TB0(do_drotrv);
 
645
    RETURN();
 
646
}
 
647
 
 
648
#else /* TARGET_LONG_BITS > HOST_LONG_BITS */
 
649
 
 
650
void op_dsll (void)
 
651
{
 
652
    T0 = T0 << T1;
 
653
    RETURN();
 
654
}
 
655
 
 
656
void op_dsll32 (void)
 
657
{
 
658
    T0 = T0 << (T1 + 32);
 
659
    RETURN();
 
660
}
 
661
 
 
662
void op_dsra (void)
 
663
{
 
664
    T0 = (int64_t)T0 >> T1;
 
665
    RETURN();
 
666
}
 
667
 
 
668
void op_dsra32 (void)
 
669
{
 
670
    T0 = (int64_t)T0 >> (T1 + 32);
 
671
    RETURN();
 
672
}
 
673
 
 
674
void op_dsrl (void)
 
675
{
 
676
    T0 = T0 >> T1;
 
677
    RETURN();
 
678
}
 
679
 
 
680
void op_dsrl32 (void)
 
681
{
 
682
    T0 = T0 >> (T1 + 32);
 
683
    RETURN();
 
684
}
 
685
 
 
686
void op_drotr (void)
 
687
{
 
688
    target_ulong tmp;
 
689
 
 
690
    if (T1) {
 
691
       tmp = T0 << (0x40 - T1);
 
692
       T0 = (T0 >> T1) | tmp;
 
693
    }
 
694
    RETURN();
 
695
}
 
696
 
 
697
void op_drotr32 (void)
 
698
{
 
699
    target_ulong tmp;
 
700
 
 
701
    if (T1) {
 
702
       tmp = T0 << (0x40 - (32 + T1));
 
703
       T0 = (T0 >> (32 + T1)) | tmp;
 
704
    }
 
705
    RETURN();
 
706
}
 
707
 
 
708
void op_dsllv (void)
 
709
{
 
710
    T0 = T1 << (T0 & 0x3F);
 
711
    RETURN();
 
712
}
 
713
 
 
714
void op_dsrav (void)
 
715
{
 
716
    T0 = (int64_t)T1 >> (T0 & 0x3F);
 
717
    RETURN();
 
718
}
 
719
 
 
720
void op_dsrlv (void)
 
721
{
 
722
    T0 = T1 >> (T0 & 0x3F);
 
723
    RETURN();
 
724
}
 
725
 
 
726
void op_drotrv (void)
 
727
{
 
728
    target_ulong tmp;
 
729
 
 
730
    T0 &= 0x3F;
 
731
    if (T0) {
 
732
       tmp = T1 << (0x40 - T0);
 
733
       T0 = (T1 >> T0) | tmp;
 
734
    } else
 
735
       T0 = T1;
 
736
    RETURN();
 
737
}
 
738
#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
 
739
 
 
740
void op_dclo (void)
 
741
{
 
742
    int n;
 
743
 
 
744
    if (T0 == ~((target_ulong)0)) {
 
745
        T0 = 64;
 
746
    } else {
 
747
        for (n = 0; n < 64; n++) {
 
748
            if (!(T0 & (1ULL << 63)))
 
749
                break;
 
750
            T0 = T0 << 1;
 
751
        }
 
752
        T0 = n;
 
753
    }
 
754
    RETURN();
 
755
}
 
756
 
 
757
void op_dclz (void)
 
758
{
 
759
    int n;
 
760
 
 
761
    if (T0 == 0) {
 
762
        T0 = 64;
 
763
    } else {
 
764
        for (n = 0; n < 64; n++) {
 
765
            if (T0 & (1ULL << 63))
 
766
                break;
 
767
            T0 = T0 << 1;
 
768
        }
 
769
        T0 = n;
 
770
    }
 
771
    RETURN();
 
772
}
 
773
#endif /* TARGET_MIPSN32 || TARGET_MIPS64 */
 
774
 
 
775
/* 64 bits arithmetic */
 
776
#if TARGET_LONG_BITS > HOST_LONG_BITS
 
777
void op_mult (void)
 
778
{
 
779
    CALL_FROM_TB0(do_mult);
 
780
    RETURN();
 
781
}
 
782
 
 
783
void op_multu (void)
 
784
{
 
785
    CALL_FROM_TB0(do_multu);
 
786
    RETURN();
 
787
}
 
788
 
 
789
void op_madd (void)
 
790
{
 
791
    CALL_FROM_TB0(do_madd);
 
792
    RETURN();
 
793
}
 
794
 
 
795
void op_maddu (void)
 
796
{
 
797
    CALL_FROM_TB0(do_maddu);
 
798
    RETURN();
 
799
}
 
800
 
 
801
void op_msub (void)
 
802
{
 
803
    CALL_FROM_TB0(do_msub);
 
804
    RETURN();
 
805
}
 
806
 
 
807
void op_msubu (void)
 
808
{
 
809
    CALL_FROM_TB0(do_msubu);
 
810
    RETURN();
 
811
}
 
812
 
 
813
#else /* TARGET_LONG_BITS > HOST_LONG_BITS */
 
814
 
 
815
static inline uint64_t get_HILO (void)
 
816
{
 
817
    return ((uint64_t)env->HI[0][env->current_tc] << 32) |
 
818
            ((uint64_t)(uint32_t)env->LO[0][env->current_tc]);
 
819
}
 
820
 
 
821
static inline void set_HILO (uint64_t HILO)
 
822
{
 
823
    env->LO[0][env->current_tc] = (int32_t)(HILO & 0xFFFFFFFF);
 
824
    env->HI[0][env->current_tc] = (int32_t)(HILO >> 32);
 
825
}
 
826
 
 
827
void op_mult (void)
 
828
{
 
829
    set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
 
830
    RETURN();
 
831
}
 
832
 
 
833
void op_multu (void)
 
834
{
 
835
    set_HILO((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
 
836
    RETURN();
 
837
}
 
838
 
 
839
void op_madd (void)
 
840
{
 
841
    int64_t tmp;
 
842
 
 
843
    tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
 
844
    set_HILO((int64_t)get_HILO() + tmp);
 
845
    RETURN();
 
846
}
 
847
 
 
848
void op_maddu (void)
 
849
{
 
850
    uint64_t tmp;
 
851
 
 
852
    tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
 
853
    set_HILO(get_HILO() + tmp);
 
854
    RETURN();
 
855
}
 
856
 
 
857
void op_msub (void)
 
858
{
 
859
    int64_t tmp;
 
860
 
 
861
    tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
 
862
    set_HILO((int64_t)get_HILO() - tmp);
 
863
    RETURN();
 
864
}
 
865
 
 
866
void op_msubu (void)
 
867
{
 
868
    uint64_t tmp;
 
869
 
 
870
    tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
 
871
    set_HILO(get_HILO() - tmp);
 
872
    RETURN();
 
873
}
 
874
#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
 
875
 
 
876
#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
 
877
void op_dmult (void)
 
878
{
 
879
    CALL_FROM_TB4(muls64, &(env->HI[0][env->current_tc]), &(env->LO[0][env->current_tc]), T0, T1);
 
880
    RETURN();
 
881
}
 
882
 
 
883
void op_dmultu (void)
 
884
{
 
885
    CALL_FROM_TB4(mulu64, &(env->HI[0][env->current_tc]), &(env->LO[0][env->current_tc]), T0, T1);
 
886
    RETURN();
 
887
}
 
888
#endif
 
889
 
 
890
/* Conditional moves */
 
891
void op_movn (void)
 
892
{
 
893
    if (T1 != 0)
 
894
        env->gpr[PARAM1][env->current_tc] = T0;
 
895
    RETURN();
 
896
}
 
897
 
 
898
void op_movz (void)
 
899
{
 
900
    if (T1 == 0)
 
901
        env->gpr[PARAM1][env->current_tc] = T0;
 
902
    RETURN();
 
903
}
 
904
 
 
905
void op_movf (void)
 
906
{
 
907
    if (!(env->fpu->fcr31 & PARAM1))
 
908
        T0 = T1;
 
909
    RETURN();
 
910
}
 
911
 
 
912
void op_movt (void)
 
913
{
 
914
    if (env->fpu->fcr31 & PARAM1)
 
915
        T0 = T1;
 
916
    RETURN();
 
917
}
 
918
 
 
919
/* Tests */
 
920
#define OP_COND(name, cond) \
 
921
void glue(op_, name) (void) \
 
922
{                           \
 
923
    if (cond) {             \
 
924
        T0 = 1;             \
 
925
    } else {                \
 
926
        T0 = 0;             \
 
927
    }                       \
 
928
    RETURN();               \
 
929
}
 
930
 
 
931
OP_COND(eq, T0 == T1);
 
932
OP_COND(ne, T0 != T1);
 
933
OP_COND(ge, (target_long)T0 >= (target_long)T1);
 
934
OP_COND(geu, T0 >= T1);
 
935
OP_COND(lt, (target_long)T0 < (target_long)T1);
 
936
OP_COND(ltu, T0 < T1);
 
937
OP_COND(gez, (target_long)T0 >= 0);
 
938
OP_COND(gtz, (target_long)T0 > 0);
 
939
OP_COND(lez, (target_long)T0 <= 0);
 
940
OP_COND(ltz, (target_long)T0 < 0);
 
941
 
 
942
/* Branches */
 
943
void OPPROTO op_goto_tb0(void)
 
944
{
 
945
    GOTO_TB(op_goto_tb0, PARAM1, 0);
 
946
    RETURN();
 
947
}
 
948
 
 
949
void OPPROTO op_goto_tb1(void)
 
950
{
 
951
    GOTO_TB(op_goto_tb1, PARAM1, 1);
 
952
    RETURN();
 
953
}
 
954
 
 
955
/* Branch to register */
 
956
void op_save_breg_target (void)
 
957
{
 
958
    env->btarget = T2;
 
959
    RETURN();
 
960
}
 
961
 
 
962
void op_restore_breg_target (void)
 
963
{
 
964
    T2 = env->btarget;
 
965
    RETURN();
 
966
}
 
967
 
 
968
void op_breg (void)
 
969
{
 
970
    env->PC[env->current_tc] = T2;
 
971
    RETURN();
 
972
}
 
973
 
 
974
void op_save_btarget (void)
 
975
{
 
976
    env->btarget = PARAM1;
 
977
    RETURN();
 
978
}
 
979
 
 
980
#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
 
981
void op_save_btarget64 (void)
 
982
{
 
983
    env->btarget = ((uint64_t)PARAM1 << 32) | (uint32_t)PARAM2;
 
984
    RETURN();
 
985
}
 
986
#endif
 
987
 
 
988
/* Conditional branch */
 
989
void op_set_bcond (void)
 
990
{
 
991
    T2 = T0;
 
992
    RETURN();
 
993
}
 
994
 
 
995
void op_save_bcond (void)
 
996
{
 
997
    env->bcond = T2;
 
998
    RETURN();
 
999
}
 
1000
 
 
1001
void op_restore_bcond (void)
 
1002
{
 
1003
    T2 = env->bcond;
 
1004
    RETURN();
 
1005
}
 
1006
 
 
1007
void op_jnz_T2 (void)
 
1008
{
 
1009
    if (T2)
 
1010
        GOTO_LABEL_PARAM(1);
 
1011
    RETURN();
 
1012
}
 
1013
 
 
1014
/* CP0 functions */
 
1015
void op_mfc0_index (void)
 
1016
{
 
1017
    T0 = env->CP0_Index;
 
1018
    RETURN();
 
1019
}
 
1020
 
 
1021
void op_mfc0_mvpcontrol (void)
 
1022
{
 
1023
    T0 = env->mvp->CP0_MVPControl;
 
1024
    RETURN();
 
1025
}
 
1026
 
 
1027
void op_mfc0_mvpconf0 (void)
 
1028
{
 
1029
    T0 = env->mvp->CP0_MVPConf0;
 
1030
    RETURN();
 
1031
}
 
1032
 
 
1033
void op_mfc0_mvpconf1 (void)
 
1034
{
 
1035
    T0 = env->mvp->CP0_MVPConf1;
 
1036
    RETURN();
 
1037
}
 
1038
 
 
1039
void op_mfc0_random (void)
 
1040
{
 
1041
    CALL_FROM_TB0(do_mfc0_random);
 
1042
    RETURN();
 
1043
}
 
1044
 
 
1045
void op_mfc0_vpecontrol (void)
 
1046
{
 
1047
    T0 = env->CP0_VPEControl;
 
1048
    RETURN();
 
1049
}
 
1050
 
 
1051
void op_mfc0_vpeconf0 (void)
 
1052
{
 
1053
    T0 = env->CP0_VPEConf0;
 
1054
    RETURN();
 
1055
}
 
1056
 
 
1057
void op_mfc0_vpeconf1 (void)
 
1058
{
 
1059
    T0 = env->CP0_VPEConf1;
 
1060
    RETURN();
 
1061
}
 
1062
 
 
1063
void op_mfc0_yqmask (void)
 
1064
{
 
1065
    T0 = env->CP0_YQMask;
 
1066
    RETURN();
 
1067
}
 
1068
 
 
1069
void op_mfc0_vpeschedule (void)
 
1070
{
 
1071
    T0 = env->CP0_VPESchedule;
 
1072
    RETURN();
 
1073
}
 
1074
 
 
1075
void op_mfc0_vpeschefback (void)
 
1076
{
 
1077
    T0 = env->CP0_VPEScheFBack;
 
1078
    RETURN();
 
1079
}
 
1080
 
 
1081
void op_mfc0_vpeopt (void)
 
1082
{
 
1083
    T0 = env->CP0_VPEOpt;
 
1084
    RETURN();
 
1085
}
 
1086
 
 
1087
void op_mfc0_entrylo0 (void)
 
1088
{
 
1089
    T0 = (int32_t)env->CP0_EntryLo0;
 
1090
    RETURN();
 
1091
}
 
1092
 
 
1093
void op_mfc0_tcstatus (void)
 
1094
{
 
1095
    T0 = env->CP0_TCStatus[env->current_tc];
 
1096
    RETURN();
 
1097
}
 
1098
 
 
1099
void op_mftc0_tcstatus(void)
 
1100
{
 
1101
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 
1102
 
 
1103
    T0 = env->CP0_TCStatus[other_tc];
 
1104
    RETURN();
 
1105
}
 
1106
 
 
1107
void op_mfc0_tcbind (void)
 
1108
{
 
1109
    T0 = env->CP0_TCBind[env->current_tc];
 
1110
    RETURN();
 
1111
}
 
1112
 
 
1113
void op_mftc0_tcbind(void)
 
1114
{
 
1115
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 
1116
 
 
1117
    T0 = env->CP0_TCBind[other_tc];
 
1118
    RETURN();
 
1119
}
 
1120
 
 
1121
void op_mfc0_tcrestart (void)
 
1122
{
 
1123
    T0 = env->PC[env->current_tc];
 
1124
    RETURN();
 
1125
}
 
1126
 
 
1127
void op_mftc0_tcrestart(void)
 
1128
{
 
1129
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 
1130
 
 
1131
    T0 = env->PC[other_tc];
 
1132
    RETURN();
 
1133
}
 
1134
 
 
1135
void op_mfc0_tchalt (void)
 
1136
{
 
1137
    T0 = env->CP0_TCHalt[env->current_tc];
 
1138
    RETURN();
 
1139
}
 
1140
 
 
1141
void op_mftc0_tchalt(void)
 
1142
{
 
1143
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 
1144
 
 
1145
    T0 = env->CP0_TCHalt[other_tc];
 
1146
    RETURN();
 
1147
}
 
1148
 
 
1149
void op_mfc0_tccontext (void)
 
1150
{
 
1151
    T0 = env->CP0_TCContext[env->current_tc];
 
1152
    RETURN();
 
1153
}
 
1154
 
 
1155
void op_mftc0_tccontext(void)
 
1156
{
 
1157
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 
1158
 
 
1159
    T0 = env->CP0_TCContext[other_tc];
 
1160
    RETURN();
 
1161
}
 
1162
 
 
1163
void op_mfc0_tcschedule (void)
 
1164
{
 
1165
    T0 = env->CP0_TCSchedule[env->current_tc];
 
1166
    RETURN();
 
1167
}
 
1168
 
 
1169
void op_mftc0_tcschedule(void)
 
1170
{
 
1171
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 
1172
 
 
1173
    T0 = env->CP0_TCSchedule[other_tc];
 
1174
    RETURN();
 
1175
}
 
1176
 
 
1177
void op_mfc0_tcschefback (void)
 
1178
{
 
1179
    T0 = env->CP0_TCScheFBack[env->current_tc];
 
1180
    RETURN();
 
1181
}
 
1182
 
 
1183
void op_mftc0_tcschefback(void)
 
1184
{
 
1185
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 
1186
 
 
1187
    T0 = env->CP0_TCScheFBack[other_tc];
 
1188
    RETURN();
 
1189
}
 
1190
 
 
1191
void op_mfc0_entrylo1 (void)
 
1192
{
 
1193
    T0 = (int32_t)env->CP0_EntryLo1;
 
1194
    RETURN();
 
1195
}
 
1196
 
 
1197
void op_mfc0_context (void)
 
1198
{
 
1199
    T0 = (int32_t)env->CP0_Context;
 
1200
    RETURN();
 
1201
}
 
1202
 
 
1203
void op_mfc0_pagemask (void)
 
1204
{
 
1205
    T0 = env->CP0_PageMask;
 
1206
    RETURN();
 
1207
}
 
1208
 
 
1209
void op_mfc0_pagegrain (void)
 
1210
{
 
1211
    T0 = env->CP0_PageGrain;
 
1212
    RETURN();
 
1213
}
 
1214
 
 
1215
void op_mfc0_wired (void)
 
1216
{
 
1217
    T0 = env->CP0_Wired;
 
1218
    RETURN();
 
1219
}
 
1220
 
 
1221
void op_mfc0_srsconf0 (void)
 
1222
{
 
1223
    T0 = env->CP0_SRSConf0;
 
1224
    RETURN();
 
1225
}
 
1226
 
 
1227
void op_mfc0_srsconf1 (void)
 
1228
{
 
1229
    T0 = env->CP0_SRSConf1;
 
1230
    RETURN();
 
1231
}
 
1232
 
 
1233
void op_mfc0_srsconf2 (void)
 
1234
{
 
1235
    T0 = env->CP0_SRSConf2;
 
1236
    RETURN();
 
1237
}
 
1238
 
 
1239
void op_mfc0_srsconf3 (void)
 
1240
{
 
1241
    T0 = env->CP0_SRSConf3;
 
1242
    RETURN();
 
1243
}
 
1244
 
 
1245
void op_mfc0_srsconf4 (void)
 
1246
{
 
1247
    T0 = env->CP0_SRSConf4;
 
1248
    RETURN();
 
1249
}
 
1250
 
 
1251
void op_mfc0_hwrena (void)
 
1252
{
 
1253
    T0 = env->CP0_HWREna;
 
1254
    RETURN();
 
1255
}
 
1256
 
 
1257
void op_mfc0_badvaddr (void)
 
1258
{
 
1259
    T0 = (int32_t)env->CP0_BadVAddr;
 
1260
    RETURN();
 
1261
}
 
1262
 
 
1263
void op_mfc0_count (void)
 
1264
{
 
1265
    CALL_FROM_TB0(do_mfc0_count);
 
1266
    RETURN();
 
1267
}
 
1268
 
 
1269
void op_mfc0_entryhi (void)
 
1270
{
 
1271
    T0 = (int32_t)env->CP0_EntryHi;
 
1272
    RETURN();
 
1273
}
 
1274
 
 
1275
void op_mftc0_entryhi(void)
 
1276
{
 
1277
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 
1278
 
 
1279
    T0 = (env->CP0_EntryHi & ~0xff) | (env->CP0_TCStatus[other_tc] & 0xff);
 
1280
    RETURN();
 
1281
}
 
1282
 
 
1283
void op_mfc0_compare (void)
 
1284
{
 
1285
    T0 = env->CP0_Compare;
 
1286
    RETURN();
 
1287
}
 
1288
 
 
1289
void op_mfc0_status (void)
 
1290
{
 
1291
    T0 = env->CP0_Status;
 
1292
    RETURN();
 
1293
}
 
1294
 
 
1295
void op_mftc0_status(void)
 
1296
{
 
1297
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 
1298
    uint32_t tcstatus = env->CP0_TCStatus[other_tc];
 
1299
 
 
1300
    T0 = env->CP0_Status & ~0xf1000018;
 
1301
    T0 |= tcstatus & (0xf << CP0TCSt_TCU0);
 
1302
    T0 |= (tcstatus & (1 << CP0TCSt_TMX)) >> (CP0TCSt_TMX - CP0St_MX);
 
1303
    T0 |= (tcstatus & (0x3 << CP0TCSt_TKSU)) >> (CP0TCSt_TKSU - CP0St_R0);
 
1304
    RETURN();
 
1305
}
 
1306
 
 
1307
void op_mfc0_intctl (void)
 
1308
{
 
1309
    T0 = env->CP0_IntCtl;
 
1310
    RETURN();
 
1311
}
 
1312
 
 
1313
void op_mfc0_srsctl (void)
 
1314
{
 
1315
    T0 = env->CP0_SRSCtl;
 
1316
    RETURN();
 
1317
}
 
1318
 
 
1319
void op_mfc0_srsmap (void)
 
1320
{
 
1321
    T0 = env->CP0_SRSMap;
 
1322
    RETURN();
 
1323
}
 
1324
 
 
1325
void op_mfc0_cause (void)
 
1326
{
 
1327
    T0 = env->CP0_Cause;
 
1328
    RETURN();
 
1329
}
 
1330
 
 
1331
void op_mfc0_epc (void)
 
1332
{
 
1333
    T0 = (int32_t)env->CP0_EPC;
 
1334
    RETURN();
 
1335
}
 
1336
 
 
1337
void op_mfc0_prid (void)
 
1338
{
 
1339
    T0 = env->CP0_PRid;
 
1340
    RETURN();
 
1341
}
 
1342
 
 
1343
void op_mfc0_ebase (void)
 
1344
{
 
1345
    T0 = env->CP0_EBase;
 
1346
    RETURN();
 
1347
}
 
1348
 
 
1349
void op_mfc0_config0 (void)
 
1350
{
 
1351
    T0 = env->CP0_Config0;
 
1352
    RETURN();
 
1353
}
 
1354
 
 
1355
void op_mfc0_config1 (void)
 
1356
{
 
1357
    T0 = env->CP0_Config1;
 
1358
    RETURN();
 
1359
}
 
1360
 
 
1361
void op_mfc0_config2 (void)
 
1362
{
 
1363
    T0 = env->CP0_Config2;
 
1364
    RETURN();
 
1365
}
 
1366
 
 
1367
void op_mfc0_config3 (void)
 
1368
{
 
1369
    T0 = env->CP0_Config3;
 
1370
    RETURN();
 
1371
}
 
1372
 
 
1373
void op_mfc0_config6 (void)
 
1374
{
 
1375
    T0 = env->CP0_Config6;
 
1376
    RETURN();
 
1377
}
 
1378
 
 
1379
void op_mfc0_config7 (void)
 
1380
{
 
1381
    T0 = env->CP0_Config7;
 
1382
    RETURN();
 
1383
}
 
1384
 
 
1385
void op_mfc0_lladdr (void)
 
1386
{
 
1387
    T0 = (int32_t)env->CP0_LLAddr >> 4;
 
1388
    RETURN();
 
1389
}
 
1390
 
 
1391
void op_mfc0_watchlo (void)
 
1392
{
 
1393
    T0 = (int32_t)env->CP0_WatchLo[PARAM1];
 
1394
    RETURN();
 
1395
}
 
1396
 
 
1397
void op_mfc0_watchhi (void)
 
1398
{
 
1399
    T0 = env->CP0_WatchHi[PARAM1];
 
1400
    RETURN();
 
1401
}
 
1402
 
 
1403
void op_mfc0_xcontext (void)
 
1404
{
 
1405
    T0 = (int32_t)env->CP0_XContext;
 
1406
    RETURN();
 
1407
}
 
1408
 
 
1409
void op_mfc0_framemask (void)
 
1410
{
 
1411
    T0 = env->CP0_Framemask;
 
1412
    RETURN();
 
1413
}
 
1414
 
 
1415
void op_mfc0_debug (void)
 
1416
{
 
1417
    T0 = env->CP0_Debug;
 
1418
    if (env->hflags & MIPS_HFLAG_DM)
 
1419
        T0 |= 1 << CP0DB_DM;
 
1420
    RETURN();
 
1421
}
 
1422
 
 
1423
void op_mftc0_debug(void)
 
1424
{
 
1425
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 
1426
 
 
1427
    /* XXX: Might be wrong, check with EJTAG spec. */
 
1428
    T0 = (env->CP0_Debug & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
 
1429
         (env->CP0_Debug_tcstatus[other_tc] &
 
1430
          ((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
 
1431
    RETURN();
 
1432
}
 
1433
 
 
1434
void op_mfc0_depc (void)
 
1435
{
 
1436
    T0 = (int32_t)env->CP0_DEPC;
 
1437
    RETURN();
 
1438
}
 
1439
 
 
1440
void op_mfc0_performance0 (void)
 
1441
{
 
1442
    T0 = env->CP0_Performance0;
 
1443
    RETURN();
 
1444
}
 
1445
 
 
1446
void op_mfc0_taglo (void)
 
1447
{
 
1448
    T0 = env->CP0_TagLo;
 
1449
    RETURN();
 
1450
}
 
1451
 
 
1452
void op_mfc0_datalo (void)
 
1453
{
 
1454
    T0 = env->CP0_DataLo;
 
1455
    RETURN();
 
1456
}
 
1457
 
 
1458
void op_mfc0_taghi (void)
 
1459
{
 
1460
    T0 = env->CP0_TagHi;
 
1461
    RETURN();
 
1462
}
 
1463
 
 
1464
void op_mfc0_datahi (void)
 
1465
{
 
1466
    T0 = env->CP0_DataHi;
 
1467
    RETURN();
 
1468
}
 
1469
 
 
1470
void op_mfc0_errorepc (void)
 
1471
{
 
1472
    T0 = (int32_t)env->CP0_ErrorEPC;
 
1473
    RETURN();
 
1474
}
 
1475
 
 
1476
void op_mfc0_desave (void)
 
1477
{
 
1478
    T0 = env->CP0_DESAVE;
 
1479
    RETURN();
 
1480
}
 
1481
 
 
1482
void op_mtc0_index (void)
 
1483
{
 
1484
    env->CP0_Index = (env->CP0_Index & 0x80000000) | (T0 % env->tlb->nb_tlb);
 
1485
    RETURN();
 
1486
}
 
1487
 
 
1488
void op_mtc0_mvpcontrol (void)
 
1489
{
 
1490
    uint32_t mask = 0;
 
1491
    uint32_t newval;
 
1492
 
 
1493
    if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP))
 
1494
        mask |= (1 << CP0MVPCo_CPA) | (1 << CP0MVPCo_VPC) |
 
1495
                (1 << CP0MVPCo_EVP);
 
1496
    if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
 
1497
        mask |= (1 << CP0MVPCo_STLB);
 
1498
    newval = (env->mvp->CP0_MVPControl & ~mask) | (T0 & mask);
 
1499
 
 
1500
    // TODO: Enable/disable shared TLB, enable/disable VPEs.
 
1501
 
 
1502
    env->mvp->CP0_MVPControl = newval;
 
1503
    RETURN();
 
1504
}
 
1505
 
 
1506
void op_mtc0_vpecontrol (void)
 
1507
{
 
1508
    uint32_t mask;
 
1509
    uint32_t newval;
 
1510
 
 
1511
    mask = (1 << CP0VPECo_YSI) | (1 << CP0VPECo_GSI) |
 
1512
           (1 << CP0VPECo_TE) | (0xff << CP0VPECo_TargTC);
 
1513
    newval = (env->CP0_VPEControl & ~mask) | (T0 & mask);
 
1514
 
 
1515
    /* Yield scheduler intercept not implemented. */
 
1516
    /* Gating storage scheduler intercept not implemented. */
 
1517
 
 
1518
    // TODO: Enable/disable TCs.
 
1519
 
 
1520
    env->CP0_VPEControl = newval;
 
1521
    RETURN();
 
1522
}
 
1523
 
 
1524
void op_mtc0_vpeconf0 (void)
 
1525
{
 
1526
    uint32_t mask = 0;
 
1527
    uint32_t newval;
 
1528
 
 
1529
    if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) {
 
1530
        if (env->CP0_VPEConf0 & (1 << CP0VPEC0_VPA))
 
1531
            mask |= (0xff << CP0VPEC0_XTC);
 
1532
        mask |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
 
1533
    }
 
1534
    newval = (env->CP0_VPEConf0 & ~mask) | (T0 & mask);
 
1535
 
 
1536
    // TODO: TC exclusive handling due to ERL/EXL.
 
1537
 
 
1538
    env->CP0_VPEConf0 = newval;
 
1539
    RETURN();
 
1540
}
 
1541
 
 
1542
void op_mtc0_vpeconf1 (void)
 
1543
{
 
1544
    uint32_t mask = 0;
 
1545
    uint32_t newval;
 
1546
 
 
1547
    if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
 
1548
        mask |= (0xff << CP0VPEC1_NCX) | (0xff << CP0VPEC1_NCP2) |
 
1549
                (0xff << CP0VPEC1_NCP1);
 
1550
    newval = (env->CP0_VPEConf1 & ~mask) | (T0 & mask);
 
1551
 
 
1552
    /* UDI not implemented. */
 
1553
    /* CP2 not implemented. */
 
1554
 
 
1555
    // TODO: Handle FPU (CP1) binding.
 
1556
 
 
1557
    env->CP0_VPEConf1 = newval;
 
1558
    RETURN();
 
1559
}
 
1560
 
 
1561
void op_mtc0_yqmask (void)
 
1562
{
 
1563
    /* Yield qualifier inputs not implemented. */
 
1564
    env->CP0_YQMask = 0x00000000;
 
1565
    RETURN();
 
1566
}
 
1567
 
 
1568
void op_mtc0_vpeschedule (void)
 
1569
{
 
1570
    env->CP0_VPESchedule = T0;
 
1571
    RETURN();
 
1572
}
 
1573
 
 
1574
void op_mtc0_vpeschefback (void)
 
1575
{
 
1576
    env->CP0_VPEScheFBack = T0;
 
1577
    RETURN();
 
1578
}
 
1579
 
 
1580
void op_mtc0_vpeopt (void)
 
1581
{
 
1582
    env->CP0_VPEOpt = T0 & 0x0000ffff;
 
1583
    RETURN();
 
1584
}
 
1585
 
 
1586
void op_mtc0_entrylo0 (void)
 
1587
{
 
1588
    /* Large physaddr not implemented */
 
1589
    /* 1k pages not implemented */
 
1590
    env->CP0_EntryLo0 = T0 & 0x3FFFFFFF;
 
1591
    RETURN();
 
1592
}
 
1593
 
 
1594
void op_mtc0_tcstatus (void)
 
1595
{
 
1596
    uint32_t mask = env->CP0_TCStatus_rw_bitmask;
 
1597
    uint32_t newval;
 
1598
 
 
1599
    newval = (env->CP0_TCStatus[env->current_tc] & ~mask) | (T0 & mask);
 
1600
 
 
1601
    // TODO: Sync with CP0_Status.
 
1602
 
 
1603
    env->CP0_TCStatus[env->current_tc] = newval;
 
1604
    RETURN();
 
1605
}
 
1606
 
 
1607
void op_mttc0_tcstatus (void)
 
1608
{
 
1609
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 
1610
 
 
1611
    // TODO: Sync with CP0_Status.
 
1612
 
 
1613
    env->CP0_TCStatus[other_tc] = T0;
 
1614
    RETURN();
 
1615
}
 
1616
 
 
1617
void op_mtc0_tcbind (void)
 
1618
{
 
1619
    uint32_t mask = (1 << CP0TCBd_TBE);
 
1620
    uint32_t newval;
 
1621
 
 
1622
    if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
 
1623
        mask |= (1 << CP0TCBd_CurVPE);
 
1624
    newval = (env->CP0_TCBind[env->current_tc] & ~mask) | (T0 & mask);
 
1625
    env->CP0_TCBind[env->current_tc] = newval;
 
1626
    RETURN();
 
1627
}
 
1628
 
 
1629
void op_mttc0_tcbind (void)
 
1630
{
 
1631
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 
1632
    uint32_t mask = (1 << CP0TCBd_TBE);
 
1633
    uint32_t newval;
 
1634
 
 
1635
    if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
 
1636
        mask |= (1 << CP0TCBd_CurVPE);
 
1637
    newval = (env->CP0_TCBind[other_tc] & ~mask) | (T0 & mask);
 
1638
    env->CP0_TCBind[other_tc] = newval;
 
1639
    RETURN();
 
1640
}
 
1641
 
 
1642
void op_mtc0_tcrestart (void)
 
1643
{
 
1644
    env->PC[env->current_tc] = T0;
 
1645
    env->CP0_TCStatus[env->current_tc] &= ~(1 << CP0TCSt_TDS);
 
1646
    env->CP0_LLAddr = 0ULL;
 
1647
    /* MIPS16 not implemented. */
 
1648
    RETURN();
 
1649
}
 
1650
 
 
1651
void op_mttc0_tcrestart (void)
 
1652
{
 
1653
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 
1654
 
 
1655
    env->PC[other_tc] = T0;
 
1656
    env->CP0_TCStatus[other_tc] &= ~(1 << CP0TCSt_TDS);
 
1657
    env->CP0_LLAddr = 0ULL;
 
1658
    /* MIPS16 not implemented. */
 
1659
    RETURN();
 
1660
}
 
1661
 
 
1662
void op_mtc0_tchalt (void)
 
1663
{
 
1664
    env->CP0_TCHalt[env->current_tc] = T0 & 0x1;
 
1665
 
 
1666
    // TODO: Halt TC / Restart (if allocated+active) TC.
 
1667
 
 
1668
    RETURN();
 
1669
}
 
1670
 
 
1671
void op_mttc0_tchalt (void)
 
1672
{
 
1673
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 
1674
 
 
1675
    // TODO: Halt TC / Restart (if allocated+active) TC.
 
1676
 
 
1677
    env->CP0_TCHalt[other_tc] = T0;
 
1678
    RETURN();
 
1679
}
 
1680
 
 
1681
void op_mtc0_tccontext (void)
 
1682
{
 
1683
    env->CP0_TCContext[env->current_tc] = T0;
 
1684
    RETURN();
 
1685
}
 
1686
 
 
1687
void op_mttc0_tccontext (void)
 
1688
{
 
1689
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 
1690
 
 
1691
    env->CP0_TCContext[other_tc] = T0;
 
1692
    RETURN();
 
1693
}
 
1694
 
 
1695
void op_mtc0_tcschedule (void)
 
1696
{
 
1697
    env->CP0_TCSchedule[env->current_tc] = T0;
 
1698
    RETURN();
 
1699
}
 
1700
 
 
1701
void op_mttc0_tcschedule (void)
 
1702
{
 
1703
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 
1704
 
 
1705
    env->CP0_TCSchedule[other_tc] = T0;
 
1706
    RETURN();
 
1707
}
 
1708
 
 
1709
void op_mtc0_tcschefback (void)
 
1710
{
 
1711
    env->CP0_TCScheFBack[env->current_tc] = T0;
 
1712
    RETURN();
 
1713
}
 
1714
 
 
1715
void op_mttc0_tcschefback (void)
 
1716
{
 
1717
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 
1718
 
 
1719
    env->CP0_TCScheFBack[other_tc] = T0;
 
1720
    RETURN();
 
1721
}
 
1722
 
 
1723
void op_mtc0_entrylo1 (void)
 
1724
{
 
1725
    /* Large physaddr not implemented */
 
1726
    /* 1k pages not implemented */
 
1727
    env->CP0_EntryLo1 = T0 & 0x3FFFFFFF;
 
1728
    RETURN();
 
1729
}
 
1730
 
 
1731
void op_mtc0_context (void)
 
1732
{
 
1733
    env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (T0 & ~0x007FFFFF);
 
1734
    RETURN();
 
1735
}
 
1736
 
 
1737
void op_mtc0_pagemask (void)
 
1738
{
 
1739
    /* 1k pages not implemented */
 
1740
    env->CP0_PageMask = T0 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
 
1741
    RETURN();
 
1742
}
 
1743
 
 
1744
void op_mtc0_pagegrain (void)
 
1745
{
 
1746
    /* SmartMIPS not implemented */
 
1747
    /* Large physaddr not implemented */
 
1748
    /* 1k pages not implemented */
 
1749
    env->CP0_PageGrain = 0;
 
1750
    RETURN();
 
1751
}
 
1752
 
 
1753
void op_mtc0_wired (void)
 
1754
{
 
1755
    env->CP0_Wired = T0 % env->tlb->nb_tlb;
 
1756
    RETURN();
 
1757
}
 
1758
 
 
1759
void op_mtc0_srsconf0 (void)
 
1760
{
 
1761
    env->CP0_SRSConf0 |= T0 & env->CP0_SRSConf0_rw_bitmask;
 
1762
    RETURN();
 
1763
}
 
1764
 
 
1765
void op_mtc0_srsconf1 (void)
 
1766
{
 
1767
    env->CP0_SRSConf1 |= T0 & env->CP0_SRSConf1_rw_bitmask;
 
1768
    RETURN();
 
1769
}
 
1770
 
 
1771
void op_mtc0_srsconf2 (void)
 
1772
{
 
1773
    env->CP0_SRSConf2 |= T0 & env->CP0_SRSConf2_rw_bitmask;
 
1774
    RETURN();
 
1775
}
 
1776
 
 
1777
void op_mtc0_srsconf3 (void)
 
1778
{
 
1779
    env->CP0_SRSConf3 |= T0 & env->CP0_SRSConf3_rw_bitmask;
 
1780
    RETURN();
 
1781
}
 
1782
 
 
1783
void op_mtc0_srsconf4 (void)
 
1784
{
 
1785
    env->CP0_SRSConf4 |= T0 & env->CP0_SRSConf4_rw_bitmask;
 
1786
    RETURN();
 
1787
}
 
1788
 
 
1789
void op_mtc0_hwrena (void)
 
1790
{
 
1791
    env->CP0_HWREna = T0 & 0x0000000F;
 
1792
    RETURN();
 
1793
}
 
1794
 
 
1795
void op_mtc0_count (void)
 
1796
{
 
1797
    CALL_FROM_TB2(cpu_mips_store_count, env, T0);
 
1798
    RETURN();
 
1799
}
 
1800
 
 
1801
void op_mtc0_entryhi (void)
 
1802
{
 
1803
    target_ulong old, val;
 
1804
 
 
1805
    /* 1k pages not implemented */
 
1806
    val = T0 & ((TARGET_PAGE_MASK << 1) | 0xFF);
 
1807
#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
 
1808
    val &= env->SEGMask;
 
1809
#endif
 
1810
    old = env->CP0_EntryHi;
 
1811
    env->CP0_EntryHi = val;
 
1812
    if (env->CP0_Config3 & (1 << CP0C3_MT)) {
 
1813
        uint32_t tcst = env->CP0_TCStatus[env->current_tc] & ~0xff;
 
1814
        env->CP0_TCStatus[env->current_tc] = tcst | (val & 0xff);
 
1815
    }
 
1816
    /* If the ASID changes, flush qemu's TLB.  */
 
1817
    if ((old & 0xFF) != (val & 0xFF))
 
1818
        CALL_FROM_TB2(cpu_mips_tlb_flush, env, 1);
 
1819
    RETURN();
 
1820
}
 
1821
 
 
1822
void op_mttc0_entryhi(void)
 
1823
{
 
1824
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 
1825
 
 
1826
    env->CP0_EntryHi = (env->CP0_EntryHi & 0xff) | (T0 & ~0xff);
 
1827
    env->CP0_TCStatus[other_tc] = (env->CP0_TCStatus[other_tc] & ~0xff) | (T0 & 0xff);
 
1828
    RETURN();
 
1829
}
 
1830
 
 
1831
void op_mtc0_compare (void)
 
1832
{
 
1833
    CALL_FROM_TB2(cpu_mips_store_compare, env, T0);
 
1834
    RETURN();
 
1835
}
 
1836
 
 
1837
void op_mtc0_status (void)
 
1838
{
 
1839
    uint32_t val, old;
 
1840
    uint32_t mask = env->CP0_Status_rw_bitmask;
 
1841
 
 
1842
    val = T0 & mask;
 
1843
    old = env->CP0_Status;
 
1844
    env->CP0_Status = (env->CP0_Status & ~mask) | val;
 
1845
    CALL_FROM_TB1(compute_hflags, env);
 
1846
    if (loglevel & CPU_LOG_EXEC)
 
1847
        CALL_FROM_TB2(do_mtc0_status_debug, old, val);
 
1848
    CALL_FROM_TB1(cpu_mips_update_irq, env);
 
1849
    RETURN();
 
1850
}
 
1851
 
 
1852
void op_mttc0_status(void)
 
1853
{
 
1854
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 
1855
    uint32_t tcstatus = env->CP0_TCStatus[other_tc];
 
1856
 
 
1857
    env->CP0_Status = T0 & ~0xf1000018;
 
1858
    tcstatus = (tcstatus & ~(0xf << CP0TCSt_TCU0)) | (T0 & (0xf << CP0St_CU0));
 
1859
    tcstatus = (tcstatus & ~(1 << CP0TCSt_TMX)) | ((T0 & (1 << CP0St_MX)) << (CP0TCSt_TMX - CP0St_MX));
 
1860
    tcstatus = (tcstatus & ~(0x3 << CP0TCSt_TKSU)) | ((T0 & (0x3 << CP0St_R0)) << (CP0TCSt_TKSU - CP0St_R0));
 
1861
    env->CP0_TCStatus[other_tc] = tcstatus;
 
1862
    RETURN();
 
1863
}
 
1864
 
 
1865
void op_mtc0_intctl (void)
 
1866
{
 
1867
    /* vectored interrupts not implemented, no performance counters. */
 
1868
    env->CP0_IntCtl = (env->CP0_IntCtl & ~0x000002e0) | (T0 & 0x000002e0);
 
1869
    RETURN();
 
1870
}
 
1871
 
 
1872
void op_mtc0_srsctl (void)
 
1873
{
 
1874
    uint32_t mask = (0xf << CP0SRSCtl_ESS) | (0xf << CP0SRSCtl_PSS);
 
1875
    env->CP0_SRSCtl = (env->CP0_SRSCtl & ~mask) | (T0 & mask);
 
1876
    RETURN();
 
1877
}
 
1878
 
 
1879
void op_mtc0_srsmap (void)
 
1880
{
 
1881
    env->CP0_SRSMap = T0;
 
1882
    RETURN();
 
1883
}
 
1884
 
 
1885
void op_mtc0_cause (void)
 
1886
{
 
1887
    uint32_t mask = 0x00C00300;
 
1888
    uint32_t old = env->CP0_Cause;
 
1889
 
 
1890
    if (env->insn_flags & ISA_MIPS32R2)
 
1891
        mask |= 1 << CP0Ca_DC;
 
1892
 
 
1893
    env->CP0_Cause = (env->CP0_Cause & ~mask) | (T0 & mask);
 
1894
 
 
1895
    if ((old ^ env->CP0_Cause) & (1 << CP0Ca_DC)) {
 
1896
        if (env->CP0_Cause & (1 << CP0Ca_DC))
 
1897
            CALL_FROM_TB1(cpu_mips_stop_count, env);
 
1898
        else
 
1899
            CALL_FROM_TB1(cpu_mips_start_count, env);
 
1900
    }
 
1901
 
 
1902
    /* Handle the software interrupt as an hardware one, as they
 
1903
       are very similar */
 
1904
    if (T0 & CP0Ca_IP_mask) {
 
1905
        CALL_FROM_TB1(cpu_mips_update_irq, env);
 
1906
    }
 
1907
    RETURN();
 
1908
}
 
1909
 
 
1910
void op_mtc0_epc (void)
 
1911
{
 
1912
    env->CP0_EPC = T0;
 
1913
    RETURN();
 
1914
}
 
1915
 
 
1916
void op_mtc0_ebase (void)
 
1917
{
 
1918
    /* vectored interrupts not implemented */
 
1919
    /* Multi-CPU not implemented */
 
1920
    env->CP0_EBase = 0x80000000 | (T0 & 0x3FFFF000);
 
1921
    RETURN();
 
1922
}
 
1923
 
 
1924
void op_mtc0_config0 (void)
 
1925
{
 
1926
    env->CP0_Config0 = (env->CP0_Config0 & 0x81FFFFF8) | (T0 & 0x00000007);
 
1927
    RETURN();
 
1928
}
 
1929
 
 
1930
void op_mtc0_config2 (void)
 
1931
{
 
1932
    /* tertiary/secondary caches not implemented */
 
1933
    env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF);
 
1934
    RETURN();
 
1935
}
 
1936
 
 
1937
void op_mtc0_watchlo (void)
 
1938
{
 
1939
    /* Watch exceptions for instructions, data loads, data stores
 
1940
       not implemented. */
 
1941
    env->CP0_WatchLo[PARAM1] = (T0 & ~0x7);
 
1942
    RETURN();
 
1943
}
 
1944
 
 
1945
void op_mtc0_watchhi (void)
 
1946
{
 
1947
    env->CP0_WatchHi[PARAM1] = (T0 & 0x40FF0FF8);
 
1948
    env->CP0_WatchHi[PARAM1] &= ~(env->CP0_WatchHi[PARAM1] & T0 & 0x7);
 
1949
    RETURN();
 
1950
}
 
1951
 
 
1952
void op_mtc0_xcontext (void)
 
1953
{
 
1954
    target_ulong mask = (1ULL << (env->SEGBITS - 7)) - 1;
 
1955
    env->CP0_XContext = (env->CP0_XContext & mask) | (T0 & ~mask);
 
1956
    RETURN();
 
1957
}
 
1958
 
 
1959
void op_mtc0_framemask (void)
 
1960
{
 
1961
    env->CP0_Framemask = T0; /* XXX */
 
1962
    RETURN();
 
1963
}
 
1964
 
 
1965
void op_mtc0_debug (void)
 
1966
{
 
1967
    env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120);
 
1968
    if (T0 & (1 << CP0DB_DM))
 
1969
        env->hflags |= MIPS_HFLAG_DM;
 
1970
    else
 
1971
        env->hflags &= ~MIPS_HFLAG_DM;
 
1972
    RETURN();
 
1973
}
 
1974
 
 
1975
void op_mttc0_debug(void)
 
1976
{
 
1977
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 
1978
 
 
1979
    /* XXX: Might be wrong, check with EJTAG spec. */
 
1980
    env->CP0_Debug_tcstatus[other_tc] = T0 & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt));
 
1981
    env->CP0_Debug = (env->CP0_Debug & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
 
1982
                     (T0 & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
 
1983
    RETURN();
 
1984
}
 
1985
 
 
1986
void op_mtc0_depc (void)
 
1987
{
 
1988
    env->CP0_DEPC = T0;
 
1989
    RETURN();
 
1990
}
 
1991
 
 
1992
void op_mtc0_performance0 (void)
 
1993
{
 
1994
    env->CP0_Performance0 = T0; /* XXX */
 
1995
    RETURN();
 
1996
}
 
1997
 
 
1998
void op_mtc0_taglo (void)
 
1999
{
 
2000
    env->CP0_TagLo = T0 & 0xFFFFFCF6;
 
2001
    RETURN();
 
2002
}
 
2003
 
 
2004
void op_mtc0_datalo (void)
 
2005
{
 
2006
    env->CP0_DataLo = T0; /* XXX */
 
2007
    RETURN();
 
2008
}
 
2009
 
 
2010
void op_mtc0_taghi (void)
 
2011
{
 
2012
    env->CP0_TagHi = T0; /* XXX */
 
2013
    RETURN();
 
2014
}
 
2015
 
 
2016
void op_mtc0_datahi (void)
 
2017
{
 
2018
    env->CP0_DataHi = T0; /* XXX */
 
2019
    RETURN();
 
2020
}
 
2021
 
 
2022
void op_mtc0_errorepc (void)
 
2023
{
 
2024
    env->CP0_ErrorEPC = T0;
 
2025
    RETURN();
 
2026
}
 
2027
 
 
2028
void op_mtc0_desave (void)
 
2029
{
 
2030
    env->CP0_DESAVE = T0;
 
2031
    RETURN();
 
2032
}
 
2033
 
 
2034
#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
 
2035
void op_dmfc0_yqmask (void)
 
2036
{
 
2037
    T0 = env->CP0_YQMask;
 
2038
    RETURN();
 
2039
}
 
2040
 
 
2041
void op_dmfc0_vpeschedule (void)
 
2042
{
 
2043
    T0 = env->CP0_VPESchedule;
 
2044
    RETURN();
 
2045
}
 
2046
 
 
2047
void op_dmfc0_vpeschefback (void)
 
2048
{
 
2049
    T0 = env->CP0_VPEScheFBack;
 
2050
    RETURN();
 
2051
}
 
2052
 
 
2053
void op_dmfc0_entrylo0 (void)
 
2054
{
 
2055
    T0 = env->CP0_EntryLo0;
 
2056
    RETURN();
 
2057
}
 
2058
 
 
2059
void op_dmfc0_tcrestart (void)
 
2060
{
 
2061
    T0 = env->PC[env->current_tc];
 
2062
    RETURN();
 
2063
}
 
2064
 
 
2065
void op_dmfc0_tchalt (void)
 
2066
{
 
2067
    T0 = env->CP0_TCHalt[env->current_tc];
 
2068
    RETURN();
 
2069
}
 
2070
 
 
2071
void op_dmfc0_tccontext (void)
 
2072
{
 
2073
    T0 = env->CP0_TCContext[env->current_tc];
 
2074
    RETURN();
 
2075
}
 
2076
 
 
2077
void op_dmfc0_tcschedule (void)
 
2078
{
 
2079
    T0 = env->CP0_TCSchedule[env->current_tc];
 
2080
    RETURN();
 
2081
}
 
2082
 
 
2083
void op_dmfc0_tcschefback (void)
 
2084
{
 
2085
    T0 = env->CP0_TCScheFBack[env->current_tc];
 
2086
    RETURN();
 
2087
}
 
2088
 
 
2089
void op_dmfc0_entrylo1 (void)
 
2090
{
 
2091
    T0 = env->CP0_EntryLo1;
 
2092
    RETURN();
 
2093
}
 
2094
 
 
2095
void op_dmfc0_context (void)
 
2096
{
 
2097
    T0 = env->CP0_Context;
 
2098
    RETURN();
 
2099
}
 
2100
 
 
2101
void op_dmfc0_badvaddr (void)
 
2102
{
 
2103
    T0 = env->CP0_BadVAddr;
 
2104
    RETURN();
 
2105
}
 
2106
 
 
2107
void op_dmfc0_entryhi (void)
 
2108
{
 
2109
    T0 = env->CP0_EntryHi;
 
2110
    RETURN();
 
2111
}
 
2112
 
 
2113
void op_dmfc0_epc (void)
 
2114
{
 
2115
    T0 = env->CP0_EPC;
 
2116
    RETURN();
 
2117
}
 
2118
 
 
2119
void op_dmfc0_lladdr (void)
 
2120
{
 
2121
    T0 = env->CP0_LLAddr >> 4;
 
2122
    RETURN();
 
2123
}
 
2124
 
 
2125
void op_dmfc0_watchlo (void)
 
2126
{
 
2127
    T0 = env->CP0_WatchLo[PARAM1];
 
2128
    RETURN();
 
2129
}
 
2130
 
 
2131
void op_dmfc0_xcontext (void)
 
2132
{
 
2133
    T0 = env->CP0_XContext;
 
2134
    RETURN();
 
2135
}
 
2136
 
 
2137
void op_dmfc0_depc (void)
 
2138
{
 
2139
    T0 = env->CP0_DEPC;
 
2140
    RETURN();
 
2141
}
 
2142
 
 
2143
void op_dmfc0_errorepc (void)
 
2144
{
 
2145
    T0 = env->CP0_ErrorEPC;
 
2146
    RETURN();
 
2147
}
 
2148
#endif /* TARGET_MIPSN32 || TARGET_MIPS64 */
 
2149
 
 
2150
/* MIPS MT functions */
 
2151
void op_mftgpr(void)
 
2152
{
 
2153
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 
2154
 
 
2155
    T0 = env->gpr[PARAM1][other_tc];
 
2156
    RETURN();
 
2157
}
 
2158
 
 
2159
void op_mftlo(void)
 
2160
{
 
2161
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 
2162
 
 
2163
    T0 = env->LO[PARAM1][other_tc];
 
2164
    RETURN();
 
2165
}
 
2166
 
 
2167
void op_mfthi(void)
 
2168
{
 
2169
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 
2170
 
 
2171
    T0 = env->HI[PARAM1][other_tc];
 
2172
    RETURN();
 
2173
}
 
2174
 
 
2175
void op_mftacx(void)
 
2176
{
 
2177
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 
2178
 
 
2179
    T0 = env->ACX[PARAM1][other_tc];
 
2180
    RETURN();
 
2181
}
 
2182
 
 
2183
void op_mftdsp(void)
 
2184
{
 
2185
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 
2186
 
 
2187
    T0 = env->DSPControl[other_tc];
 
2188
    RETURN();
 
2189
}
 
2190
 
 
2191
void op_mttgpr(void)
 
2192
{
 
2193
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 
2194
 
 
2195
    T0 = env->gpr[PARAM1][other_tc];
 
2196
    RETURN();
 
2197
}
 
2198
 
 
2199
void op_mttlo(void)
 
2200
{
 
2201
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 
2202
 
 
2203
    T0 = env->LO[PARAM1][other_tc];
 
2204
    RETURN();
 
2205
}
 
2206
 
 
2207
void op_mtthi(void)
 
2208
{
 
2209
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 
2210
 
 
2211
    T0 = env->HI[PARAM1][other_tc];
 
2212
    RETURN();
 
2213
}
 
2214
 
 
2215
void op_mttacx(void)
 
2216
{
 
2217
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 
2218
 
 
2219
    T0 = env->ACX[PARAM1][other_tc];
 
2220
    RETURN();
 
2221
}
 
2222
 
 
2223
void op_mttdsp(void)
 
2224
{
 
2225
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
 
2226
 
 
2227
    T0 = env->DSPControl[other_tc];
 
2228
    RETURN();
 
2229
}
 
2230
 
 
2231
 
 
2232
void op_dmt(void)
 
2233
{
 
2234
    // TODO
 
2235
    T0 = 0;
 
2236
    // rt = T0
 
2237
    RETURN();
 
2238
}
 
2239
 
 
2240
void op_emt(void)
 
2241
{
 
2242
    // TODO
 
2243
    T0 = 0;
 
2244
    // rt = T0
 
2245
    RETURN();
 
2246
}
 
2247
 
 
2248
void op_dvpe(void)
 
2249
{
 
2250
    // TODO
 
2251
    T0 = 0;
 
2252
    // rt = T0
 
2253
    RETURN();
 
2254
}
 
2255
 
 
2256
void op_evpe(void)
 
2257
{
 
2258
    // TODO
 
2259
    T0 = 0;
 
2260
    // rt = T0
 
2261
    RETURN();
 
2262
}
 
2263
 
 
2264
void op_fork(void)
 
2265
{
 
2266
    // T0 = rt, T1 = rs
 
2267
    T0 = 0;
 
2268
    // TODO: store to TC register
 
2269
    RETURN();
 
2270
}
 
2271
 
 
2272
void op_yield(void)
 
2273
{
 
2274
    if (T0 < 0) {
 
2275
        /* No scheduling policy implemented. */
 
2276
        if (T0 != -2) {
 
2277
            if (env->CP0_VPEControl & (1 << CP0VPECo_YSI) &&
 
2278
                env->CP0_TCStatus[env->current_tc] & (1 << CP0TCSt_DT)) {
 
2279
                env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
 
2280
                env->CP0_VPEControl |= 4 << CP0VPECo_EXCPT;
 
2281
                CALL_FROM_TB1(do_raise_exception, EXCP_THREAD);
 
2282
            }
 
2283
        }
 
2284
    } else if (T0 == 0) {
 
2285
        if (0 /* TODO: TC underflow */) {
 
2286
            env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
 
2287
            CALL_FROM_TB1(do_raise_exception, EXCP_THREAD);
 
2288
        } else {
 
2289
            // TODO: Deallocate TC
 
2290
        }
 
2291
    } else if (T0 > 0) {
 
2292
        /* Yield qualifier inputs not implemented. */
 
2293
        env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
 
2294
        env->CP0_VPEControl |= 2 << CP0VPECo_EXCPT;
 
2295
        CALL_FROM_TB1(do_raise_exception, EXCP_THREAD);
 
2296
    }
 
2297
    T0 = env->CP0_YQMask;
 
2298
    RETURN();
 
2299
}
 
2300
 
 
2301
/* CP1 functions */
 
2302
#if 0
 
2303
# define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env)
 
2304
#else
 
2305
# define DEBUG_FPU_STATE() do { } while(0)
 
2306
#endif
 
2307
 
 
2308
void op_cfc1 (void)
 
2309
{
 
2310
    CALL_FROM_TB1(do_cfc1, PARAM1);
 
2311
    DEBUG_FPU_STATE();
 
2312
    RETURN();
 
2313
}
 
2314
 
 
2315
void op_ctc1 (void)
 
2316
{
 
2317
    CALL_FROM_TB1(do_ctc1, PARAM1);
 
2318
    DEBUG_FPU_STATE();
 
2319
    RETURN();
 
2320
}
 
2321
 
 
2322
void op_mfc1 (void)
 
2323
{
 
2324
    T0 = WT0;
 
2325
    DEBUG_FPU_STATE();
 
2326
    RETURN();
 
2327
}
 
2328
 
 
2329
void op_mtc1 (void)
 
2330
{
 
2331
    WT0 = T0;
 
2332
    DEBUG_FPU_STATE();
 
2333
    RETURN();
 
2334
}
 
2335
 
 
2336
void op_dmfc1 (void)
 
2337
{
 
2338
    T0 = DT0;
 
2339
    DEBUG_FPU_STATE();
 
2340
    RETURN();
 
2341
}
 
2342
 
 
2343
void op_dmtc1 (void)
 
2344
{
 
2345
    DT0 = T0;
 
2346
    DEBUG_FPU_STATE();
 
2347
    RETURN();
 
2348
}
 
2349
 
 
2350
void op_mfhc1 (void)
 
2351
{
 
2352
    T0 = WTH0;
 
2353
    DEBUG_FPU_STATE();
 
2354
    RETURN();
 
2355
}
 
2356
 
 
2357
void op_mthc1 (void)
 
2358
{
 
2359
    WTH0 = T0;
 
2360
    DEBUG_FPU_STATE();
 
2361
    RETURN();
 
2362
}
 
2363
 
 
2364
/* Float support.
 
2365
   Single precition routines have a "s" suffix, double precision a
 
2366
   "d" suffix, 32bit integer "w", 64bit integer "l", paired singe "ps",
 
2367
   paired single lowwer "pl", paired single upper "pu".  */
 
2368
 
 
2369
#define FLOAT_OP(name, p) void OPPROTO op_float_##name##_##p(void)
 
2370
 
 
2371
FLOAT_OP(cvtd, s)
 
2372
{
 
2373
    CALL_FROM_TB0(do_float_cvtd_s);
 
2374
    DEBUG_FPU_STATE();
 
2375
    RETURN();
 
2376
}
 
2377
FLOAT_OP(cvtd, w)
 
2378
{
 
2379
    CALL_FROM_TB0(do_float_cvtd_w);
 
2380
    DEBUG_FPU_STATE();
 
2381
    RETURN();
 
2382
}
 
2383
FLOAT_OP(cvtd, l)
 
2384
{
 
2385
    CALL_FROM_TB0(do_float_cvtd_l);
 
2386
    DEBUG_FPU_STATE();
 
2387
    RETURN();
 
2388
}
 
2389
FLOAT_OP(cvtl, d)
 
2390
{
 
2391
    CALL_FROM_TB0(do_float_cvtl_d);
 
2392
    DEBUG_FPU_STATE();
 
2393
    RETURN();
 
2394
}
 
2395
FLOAT_OP(cvtl, s)
 
2396
{
 
2397
    CALL_FROM_TB0(do_float_cvtl_s);
 
2398
    DEBUG_FPU_STATE();
 
2399
    RETURN();
 
2400
}
 
2401
FLOAT_OP(cvtps, s)
 
2402
{
 
2403
    WT2 = WT0;
 
2404
    WTH2 = WT1;
 
2405
    DEBUG_FPU_STATE();
 
2406
    RETURN();
 
2407
}
 
2408
FLOAT_OP(cvtps, pw)
 
2409
{
 
2410
    CALL_FROM_TB0(do_float_cvtps_pw);
 
2411
    DEBUG_FPU_STATE();
 
2412
    RETURN();
 
2413
}
 
2414
FLOAT_OP(cvtpw, ps)
 
2415
{
 
2416
    CALL_FROM_TB0(do_float_cvtpw_ps);
 
2417
    DEBUG_FPU_STATE();
 
2418
    RETURN();
 
2419
}
 
2420
FLOAT_OP(cvts, d)
 
2421
{
 
2422
    CALL_FROM_TB0(do_float_cvts_d);
 
2423
    DEBUG_FPU_STATE();
 
2424
    RETURN();
 
2425
}
 
2426
FLOAT_OP(cvts, w)
 
2427
{
 
2428
    CALL_FROM_TB0(do_float_cvts_w);
 
2429
    DEBUG_FPU_STATE();
 
2430
    RETURN();
 
2431
}
 
2432
FLOAT_OP(cvts, l)
 
2433
{
 
2434
    CALL_FROM_TB0(do_float_cvts_l);
 
2435
    DEBUG_FPU_STATE();
 
2436
    RETURN();
 
2437
}
 
2438
FLOAT_OP(cvts, pl)
 
2439
{
 
2440
    CALL_FROM_TB0(do_float_cvts_pl);
 
2441
    DEBUG_FPU_STATE();
 
2442
    RETURN();
 
2443
}
 
2444
FLOAT_OP(cvts, pu)
 
2445
{
 
2446
    CALL_FROM_TB0(do_float_cvts_pu);
 
2447
    DEBUG_FPU_STATE();
 
2448
    RETURN();
 
2449
}
 
2450
FLOAT_OP(cvtw, s)
 
2451
{
 
2452
    CALL_FROM_TB0(do_float_cvtw_s);
 
2453
    DEBUG_FPU_STATE();
 
2454
    RETURN();
 
2455
}
 
2456
FLOAT_OP(cvtw, d)
 
2457
{
 
2458
    CALL_FROM_TB0(do_float_cvtw_d);
 
2459
    DEBUG_FPU_STATE();
 
2460
    RETURN();
 
2461
}
 
2462
 
 
2463
FLOAT_OP(pll, ps)
 
2464
{
 
2465
    DT2 = ((uint64_t)WT0 << 32) | WT1;
 
2466
    DEBUG_FPU_STATE();
 
2467
    RETURN();
 
2468
}
 
2469
FLOAT_OP(plu, ps)
 
2470
{
 
2471
    DT2 = ((uint64_t)WT0 << 32) | WTH1;
 
2472
    DEBUG_FPU_STATE();
 
2473
    RETURN();
 
2474
}
 
2475
FLOAT_OP(pul, ps)
 
2476
{
 
2477
    DT2 = ((uint64_t)WTH0 << 32) | WT1;
 
2478
    DEBUG_FPU_STATE();
 
2479
    RETURN();
 
2480
}
 
2481
FLOAT_OP(puu, ps)
 
2482
{
 
2483
    DT2 = ((uint64_t)WTH0 << 32) | WTH1;
 
2484
    DEBUG_FPU_STATE();
 
2485
    RETURN();
 
2486
}
 
2487
 
 
2488
#define FLOAT_ROUNDOP(op, ttype, stype)                    \
 
2489
FLOAT_OP(op ## ttype, stype)                               \
 
2490
{                                                          \
 
2491
    CALL_FROM_TB0(do_float_ ## op ## ttype ## _ ## stype); \
 
2492
    DEBUG_FPU_STATE();                                     \
 
2493
    RETURN();                                              \
 
2494
}
 
2495
 
 
2496
FLOAT_ROUNDOP(round, l, d)
 
2497
FLOAT_ROUNDOP(round, l, s)
 
2498
FLOAT_ROUNDOP(round, w, d)
 
2499
FLOAT_ROUNDOP(round, w, s)
 
2500
 
 
2501
FLOAT_ROUNDOP(trunc, l, d)
 
2502
FLOAT_ROUNDOP(trunc, l, s)
 
2503
FLOAT_ROUNDOP(trunc, w, d)
 
2504
FLOAT_ROUNDOP(trunc, w, s)
 
2505
 
 
2506
FLOAT_ROUNDOP(ceil, l, d)
 
2507
FLOAT_ROUNDOP(ceil, l, s)
 
2508
FLOAT_ROUNDOP(ceil, w, d)
 
2509
FLOAT_ROUNDOP(ceil, w, s)
 
2510
 
 
2511
FLOAT_ROUNDOP(floor, l, d)
 
2512
FLOAT_ROUNDOP(floor, l, s)
 
2513
FLOAT_ROUNDOP(floor, w, d)
 
2514
FLOAT_ROUNDOP(floor, w, s)
 
2515
#undef FLOAR_ROUNDOP
 
2516
 
 
2517
FLOAT_OP(movf, d)
 
2518
{
 
2519
    if (!(env->fpu->fcr31 & PARAM1))
 
2520
        DT2 = DT0;
 
2521
    DEBUG_FPU_STATE();
 
2522
    RETURN();
 
2523
}
 
2524
FLOAT_OP(movf, s)
 
2525
{
 
2526
    if (!(env->fpu->fcr31 & PARAM1))
 
2527
        WT2 = WT0;
 
2528
    DEBUG_FPU_STATE();
 
2529
    RETURN();
 
2530
}
 
2531
FLOAT_OP(movf, ps)
 
2532
{
 
2533
    if (!(env->fpu->fcr31 & PARAM1)) {
 
2534
        WT2 = WT0;
 
2535
        WTH2 = WTH0;
 
2536
    }
 
2537
    DEBUG_FPU_STATE();
 
2538
    RETURN();
 
2539
}
 
2540
FLOAT_OP(movt, d)
 
2541
{
 
2542
    if (env->fpu->fcr31 & PARAM1)
 
2543
        DT2 = DT0;
 
2544
    DEBUG_FPU_STATE();
 
2545
    RETURN();
 
2546
}
 
2547
FLOAT_OP(movt, s)
 
2548
{
 
2549
    if (env->fpu->fcr31 & PARAM1)
 
2550
        WT2 = WT0;
 
2551
    DEBUG_FPU_STATE();
 
2552
    RETURN();
 
2553
}
 
2554
FLOAT_OP(movt, ps)
 
2555
{
 
2556
    if (env->fpu->fcr31 & PARAM1) {
 
2557
        WT2 = WT0;
 
2558
        WTH2 = WTH0;
 
2559
    }
 
2560
    DEBUG_FPU_STATE();
 
2561
    RETURN();
 
2562
}
 
2563
FLOAT_OP(movz, d)
 
2564
{
 
2565
    if (!T0)
 
2566
        DT2 = DT0;
 
2567
    DEBUG_FPU_STATE();
 
2568
    RETURN();
 
2569
}
 
2570
FLOAT_OP(movz, s)
 
2571
{
 
2572
    if (!T0)
 
2573
        WT2 = WT0;
 
2574
    DEBUG_FPU_STATE();
 
2575
    RETURN();
 
2576
}
 
2577
FLOAT_OP(movz, ps)
 
2578
{
 
2579
    if (!T0) {
 
2580
        WT2 = WT0;
 
2581
        WTH2 = WTH0;
 
2582
    }
 
2583
    DEBUG_FPU_STATE();
 
2584
    RETURN();
 
2585
}
 
2586
FLOAT_OP(movn, d)
 
2587
{
 
2588
    if (T0)
 
2589
        DT2 = DT0;
 
2590
    DEBUG_FPU_STATE();
 
2591
    RETURN();
 
2592
}
 
2593
FLOAT_OP(movn, s)
 
2594
{
 
2595
    if (T0)
 
2596
        WT2 = WT0;
 
2597
    DEBUG_FPU_STATE();
 
2598
    RETURN();
 
2599
}
 
2600
FLOAT_OP(movn, ps)
 
2601
{
 
2602
    if (T0) {
 
2603
        WT2 = WT0;
 
2604
        WTH2 = WTH0;
 
2605
    }
 
2606
    DEBUG_FPU_STATE();
 
2607
    RETURN();
 
2608
}
 
2609
 
 
2610
/* operations calling helpers, for s, d and ps */
 
2611
#define FLOAT_HOP(name) \
 
2612
FLOAT_OP(name, d)         \
 
2613
{                         \
 
2614
    CALL_FROM_TB0(do_float_ ## name ## _d);  \
 
2615
    DEBUG_FPU_STATE();    \
 
2616
    RETURN();             \
 
2617
}                         \
 
2618
FLOAT_OP(name, s)         \
 
2619
{                         \
 
2620
    CALL_FROM_TB0(do_float_ ## name ## _s);  \
 
2621
    DEBUG_FPU_STATE();    \
 
2622
    RETURN();             \
 
2623
}                         \
 
2624
FLOAT_OP(name, ps)        \
 
2625
{                         \
 
2626
    CALL_FROM_TB0(do_float_ ## name ## _ps); \
 
2627
    DEBUG_FPU_STATE();    \
 
2628
    RETURN();             \
 
2629
}
 
2630
FLOAT_HOP(add)
 
2631
FLOAT_HOP(sub)
 
2632
FLOAT_HOP(mul)
 
2633
FLOAT_HOP(div)
 
2634
FLOAT_HOP(recip2)
 
2635
FLOAT_HOP(rsqrt2)
 
2636
FLOAT_HOP(rsqrt1)
 
2637
FLOAT_HOP(recip1)
 
2638
#undef FLOAT_HOP
 
2639
 
 
2640
/* operations calling helpers, for s and d */
 
2641
#define FLOAT_HOP(name)   \
 
2642
FLOAT_OP(name, d)         \
 
2643
{                         \
 
2644
    CALL_FROM_TB0(do_float_ ## name ## _d);  \
 
2645
    DEBUG_FPU_STATE();    \
 
2646
    RETURN();             \
 
2647
}                         \
 
2648
FLOAT_OP(name, s)         \
 
2649
{                         \
 
2650
    CALL_FROM_TB0(do_float_ ## name ## _s);  \
 
2651
    DEBUG_FPU_STATE();    \
 
2652
    RETURN();             \
 
2653
}
 
2654
FLOAT_HOP(rsqrt)
 
2655
FLOAT_HOP(recip)
 
2656
#undef FLOAT_HOP
 
2657
 
 
2658
/* operations calling helpers, for ps */
 
2659
#define FLOAT_HOP(name)   \
 
2660
FLOAT_OP(name, ps)        \
 
2661
{                         \
 
2662
    CALL_FROM_TB0(do_float_ ## name ## _ps); \
 
2663
    DEBUG_FPU_STATE();    \
 
2664
    RETURN();             \
 
2665
}
 
2666
FLOAT_HOP(addr)
 
2667
FLOAT_HOP(mulr)
 
2668
#undef FLOAT_HOP
 
2669
 
 
2670
/* ternary operations */
 
2671
#define FLOAT_TERNOP(name1, name2) \
 
2672
FLOAT_OP(name1 ## name2, d)        \
 
2673
{                                  \
 
2674
    FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status);    \
 
2675
    FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status);    \
 
2676
    DEBUG_FPU_STATE();             \
 
2677
    RETURN();                      \
 
2678
}                                  \
 
2679
FLOAT_OP(name1 ## name2, s)        \
 
2680
{                                  \
 
2681
    FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status);    \
 
2682
    FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status);    \
 
2683
    DEBUG_FPU_STATE();             \
 
2684
    RETURN();                      \
 
2685
}                                  \
 
2686
FLOAT_OP(name1 ## name2, ps)       \
 
2687
{                                  \
 
2688
    FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status);    \
 
2689
    FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \
 
2690
    FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status);    \
 
2691
    FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \
 
2692
    DEBUG_FPU_STATE();             \
 
2693
    RETURN();                      \
 
2694
}
 
2695
FLOAT_TERNOP(mul, add)
 
2696
FLOAT_TERNOP(mul, sub)
 
2697
#undef FLOAT_TERNOP
 
2698
 
 
2699
/* negated ternary operations */
 
2700
#define FLOAT_NTERNOP(name1, name2) \
 
2701
FLOAT_OP(n ## name1 ## name2, d)    \
 
2702
{                                   \
 
2703
    FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status);    \
 
2704
    FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status);    \
 
2705
    FDT2 ^= 1ULL << 63;             \
 
2706
    DEBUG_FPU_STATE();              \
 
2707
    RETURN();                       \
 
2708
}                                   \
 
2709
FLOAT_OP(n ## name1 ## name2, s)    \
 
2710
{                                   \
 
2711
    FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status);    \
 
2712
    FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status);    \
 
2713
    FST2 ^= 1 << 31;                \
 
2714
    DEBUG_FPU_STATE();              \
 
2715
    RETURN();                       \
 
2716
}                                   \
 
2717
FLOAT_OP(n ## name1 ## name2, ps)   \
 
2718
{                                   \
 
2719
    FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status);    \
 
2720
    FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \
 
2721
    FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status);    \
 
2722
    FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \
 
2723
    FST2 ^= 1 << 31;                \
 
2724
    FSTH2 ^= 1 << 31;               \
 
2725
    DEBUG_FPU_STATE();              \
 
2726
    RETURN();                       \
 
2727
}
 
2728
FLOAT_NTERNOP(mul, add)
 
2729
FLOAT_NTERNOP(mul, sub)
 
2730
#undef FLOAT_NTERNOP
 
2731
 
 
2732
/* unary operations, modifying fp status  */
 
2733
#define FLOAT_UNOP(name)  \
 
2734
FLOAT_OP(name, d)         \
 
2735
{                         \
 
2736
    FDT2 = float64_ ## name(FDT0, &env->fpu->fp_status);   \
 
2737
    DEBUG_FPU_STATE();    \
 
2738
    RETURN();                      \
 
2739
}                         \
 
2740
FLOAT_OP(name, s)         \
 
2741
{                         \
 
2742
    FST2 = float32_ ## name(FST0, &env->fpu->fp_status);   \
 
2743
    DEBUG_FPU_STATE();    \
 
2744
    RETURN();             \
 
2745
}
 
2746
FLOAT_UNOP(sqrt)
 
2747
#undef FLOAT_UNOP
 
2748
 
 
2749
/* unary operations, not modifying fp status  */
 
2750
#define FLOAT_UNOP(name)  \
 
2751
FLOAT_OP(name, d)         \
 
2752
{                         \
 
2753
    FDT2 = float64_ ## name(FDT0);   \
 
2754
    DEBUG_FPU_STATE();    \
 
2755
    RETURN();             \
 
2756
}                         \
 
2757
FLOAT_OP(name, s)         \
 
2758
{                         \
 
2759
    FST2 = float32_ ## name(FST0);   \
 
2760
    DEBUG_FPU_STATE();    \
 
2761
    RETURN();             \
 
2762
}                         \
 
2763
FLOAT_OP(name, ps)        \
 
2764
{                         \
 
2765
    FST2 = float32_ ## name(FST0);   \
 
2766
    FSTH2 = float32_ ## name(FSTH0); \
 
2767
    DEBUG_FPU_STATE();    \
 
2768
    RETURN();             \
 
2769
}
 
2770
FLOAT_UNOP(abs)
 
2771
FLOAT_UNOP(chs)
 
2772
#undef FLOAT_UNOP
 
2773
 
 
2774
FLOAT_OP(mov, d)
 
2775
{
 
2776
    FDT2 = FDT0;
 
2777
    DEBUG_FPU_STATE();
 
2778
    RETURN();
 
2779
}
 
2780
FLOAT_OP(mov, s)
 
2781
{
 
2782
    FST2 = FST0;
 
2783
    DEBUG_FPU_STATE();
 
2784
    RETURN();
 
2785
}
 
2786
FLOAT_OP(mov, ps)
 
2787
{
 
2788
    FST2 = FST0;
 
2789
    FSTH2 = FSTH0;
 
2790
    DEBUG_FPU_STATE();
 
2791
    RETURN();
 
2792
}
 
2793
FLOAT_OP(alnv, ps)
 
2794
{
 
2795
    switch (T0 & 0x7) {
 
2796
    case 0:
 
2797
        FST2 = FST0;
 
2798
        FSTH2 = FSTH0;
 
2799
        break;
 
2800
    case 4:
 
2801
#ifdef TARGET_WORDS_BIGENDIAN
 
2802
        FSTH2 = FST0;
 
2803
        FST2 = FSTH1;
 
2804
#else
 
2805
        FSTH2 = FST1;
 
2806
        FST2 = FSTH0;
 
2807
#endif
 
2808
        break;
 
2809
    default: /* unpredictable */
 
2810
        break;
 
2811
    }
 
2812
    DEBUG_FPU_STATE();
 
2813
    RETURN();
 
2814
}
 
2815
 
 
2816
#ifdef CONFIG_SOFTFLOAT
 
2817
#define clear_invalid() do {                                \
 
2818
    int flags = get_float_exception_flags(&env->fpu->fp_status); \
 
2819
    flags &= ~float_flag_invalid;                           \
 
2820
    set_float_exception_flags(flags, &env->fpu->fp_status);      \
 
2821
} while(0)
 
2822
#else
 
2823
#define clear_invalid() do { } while(0)
 
2824
#endif
 
2825
 
 
2826
extern void dump_fpu_s(CPUState *env);
 
2827
 
 
2828
#define CMP_OP(fmt, op)                                \
 
2829
void OPPROTO op_cmp ## _ ## fmt ## _ ## op(void)       \
 
2830
{                                                      \
 
2831
    CALL_FROM_TB1(do_cmp ## _ ## fmt ## _ ## op, PARAM1); \
 
2832
    DEBUG_FPU_STATE();                                 \
 
2833
    RETURN();                                          \
 
2834
}                                                      \
 
2835
void OPPROTO op_cmpabs ## _ ## fmt ## _ ## op(void)    \
 
2836
{                                                      \
 
2837
    CALL_FROM_TB1(do_cmpabs ## _ ## fmt ## _ ## op, PARAM1); \
 
2838
    DEBUG_FPU_STATE();                                 \
 
2839
    RETURN();                                          \
 
2840
}
 
2841
#define CMP_OPS(op)   \
 
2842
CMP_OP(d, op)         \
 
2843
CMP_OP(s, op)         \
 
2844
CMP_OP(ps, op)
 
2845
 
 
2846
CMP_OPS(f)
 
2847
CMP_OPS(un)
 
2848
CMP_OPS(eq)
 
2849
CMP_OPS(ueq)
 
2850
CMP_OPS(olt)
 
2851
CMP_OPS(ult)
 
2852
CMP_OPS(ole)
 
2853
CMP_OPS(ule)
 
2854
CMP_OPS(sf)
 
2855
CMP_OPS(ngle)
 
2856
CMP_OPS(seq)
 
2857
CMP_OPS(ngl)
 
2858
CMP_OPS(lt)
 
2859
CMP_OPS(nge)
 
2860
CMP_OPS(le)
 
2861
CMP_OPS(ngt)
 
2862
#undef CMP_OPS
 
2863
#undef CMP_OP
 
2864
 
 
2865
void op_bc1f (void)
 
2866
{
 
2867
    T0 = !!(~GET_FP_COND(env->fpu) & (0x1 << PARAM1));
 
2868
    DEBUG_FPU_STATE();
 
2869
    RETURN();
 
2870
}
 
2871
void op_bc1any2f (void)
 
2872
{
 
2873
    T0 = !!(~GET_FP_COND(env->fpu) & (0x3 << PARAM1));
 
2874
    DEBUG_FPU_STATE();
 
2875
    RETURN();
 
2876
}
 
2877
void op_bc1any4f (void)
 
2878
{
 
2879
    T0 = !!(~GET_FP_COND(env->fpu) & (0xf << PARAM1));
 
2880
    DEBUG_FPU_STATE();
 
2881
    RETURN();
 
2882
}
 
2883
 
 
2884
void op_bc1t (void)
 
2885
{
 
2886
    T0 = !!(GET_FP_COND(env->fpu) & (0x1 << PARAM1));
 
2887
    DEBUG_FPU_STATE();
 
2888
    RETURN();
 
2889
}
 
2890
void op_bc1any2t (void)
 
2891
{
 
2892
    T0 = !!(GET_FP_COND(env->fpu) & (0x3 << PARAM1));
 
2893
    DEBUG_FPU_STATE();
 
2894
    RETURN();
 
2895
}
 
2896
void op_bc1any4t (void)
 
2897
{
 
2898
    T0 = !!(GET_FP_COND(env->fpu) & (0xf << PARAM1));
 
2899
    DEBUG_FPU_STATE();
 
2900
    RETURN();
 
2901
}
 
2902
 
 
2903
void op_tlbwi (void)
 
2904
{
 
2905
    CALL_FROM_TB0(env->tlb->do_tlbwi);
 
2906
    RETURN();
 
2907
}
 
2908
 
 
2909
void op_tlbwr (void)
 
2910
{
 
2911
    CALL_FROM_TB0(env->tlb->do_tlbwr);
 
2912
    RETURN();
 
2913
}
 
2914
 
 
2915
void op_tlbp (void)
 
2916
{
 
2917
    CALL_FROM_TB0(env->tlb->do_tlbp);
 
2918
    RETURN();
 
2919
}
 
2920
 
 
2921
void op_tlbr (void)
 
2922
{
 
2923
    CALL_FROM_TB0(env->tlb->do_tlbr);
 
2924
    RETURN();
 
2925
}
 
2926
 
 
2927
/* Specials */
 
2928
#if defined (CONFIG_USER_ONLY)
 
2929
void op_tls_value (void)
 
2930
{
 
2931
    T0 = env->tls_value;
 
2932
}
 
2933
#endif
 
2934
 
 
2935
void op_pmon (void)
 
2936
{
 
2937
    CALL_FROM_TB1(do_pmon, PARAM1);
 
2938
    RETURN();
 
2939
}
 
2940
 
 
2941
void op_di (void)
 
2942
{
 
2943
    T0 = env->CP0_Status;
 
2944
    env->CP0_Status = T0 & ~(1 << CP0St_IE);
 
2945
    CALL_FROM_TB1(cpu_mips_update_irq, env);
 
2946
    RETURN();
 
2947
}
 
2948
 
 
2949
void op_ei (void)
 
2950
{
 
2951
    T0 = env->CP0_Status;
 
2952
    env->CP0_Status = T0 | (1 << CP0St_IE);
 
2953
    CALL_FROM_TB1(cpu_mips_update_irq, env);
 
2954
    RETURN();
 
2955
}
 
2956
 
 
2957
void op_trap (void)
 
2958
{
 
2959
    if (T0) {
 
2960
        CALL_FROM_TB1(do_raise_exception, EXCP_TRAP);
 
2961
    }
 
2962
    RETURN();
 
2963
}
 
2964
 
 
2965
void op_debug (void)
 
2966
{
 
2967
    CALL_FROM_TB1(do_raise_exception, EXCP_DEBUG);
 
2968
    RETURN();
 
2969
}
 
2970
 
 
2971
void op_set_lladdr (void)
 
2972
{
 
2973
    env->CP0_LLAddr = T2;
 
2974
    RETURN();
 
2975
}
 
2976
 
 
2977
void debug_pre_eret (void);
 
2978
void debug_post_eret (void);
 
2979
void op_eret (void)
 
2980
{
 
2981
    if (loglevel & CPU_LOG_EXEC)
 
2982
        CALL_FROM_TB0(debug_pre_eret);
 
2983
    if (env->CP0_Status & (1 << CP0St_ERL)) {
 
2984
        env->PC[env->current_tc] = env->CP0_ErrorEPC;
 
2985
        env->CP0_Status &= ~(1 << CP0St_ERL);
 
2986
    } else {
 
2987
        env->PC[env->current_tc] = env->CP0_EPC;
 
2988
        env->CP0_Status &= ~(1 << CP0St_EXL);
 
2989
    }
 
2990
    CALL_FROM_TB1(compute_hflags, env);
 
2991
    if (loglevel & CPU_LOG_EXEC)
 
2992
        CALL_FROM_TB0(debug_post_eret);
 
2993
    env->CP0_LLAddr = 1;
 
2994
    RETURN();
 
2995
}
 
2996
 
 
2997
void op_deret (void)
 
2998
{
 
2999
    if (loglevel & CPU_LOG_EXEC)
 
3000
        CALL_FROM_TB0(debug_pre_eret);
 
3001
    env->PC[env->current_tc] = env->CP0_DEPC;
 
3002
    env->hflags &= MIPS_HFLAG_DM;
 
3003
    CALL_FROM_TB1(compute_hflags, env);
 
3004
    if (loglevel & CPU_LOG_EXEC)
 
3005
        CALL_FROM_TB0(debug_post_eret);
 
3006
    env->CP0_LLAddr = 1;
 
3007
    RETURN();
 
3008
}
 
3009
 
 
3010
void op_rdhwr_cpunum(void)
 
3011
{
 
3012
    if ((env->hflags & MIPS_HFLAG_CP0) ||
 
3013
        (env->CP0_HWREna & (1 << 0)))
 
3014
        T0 = env->CP0_EBase & 0x3ff;
 
3015
    else
 
3016
        CALL_FROM_TB1(do_raise_exception, EXCP_RI);
 
3017
    RETURN();
 
3018
}
 
3019
 
 
3020
void op_rdhwr_synci_step(void)
 
3021
{
 
3022
    if ((env->hflags & MIPS_HFLAG_CP0) ||
 
3023
        (env->CP0_HWREna & (1 << 1)))
 
3024
        T0 = env->SYNCI_Step;
 
3025
    else
 
3026
        CALL_FROM_TB1(do_raise_exception, EXCP_RI);
 
3027
    RETURN();
 
3028
}
 
3029
 
 
3030
void op_rdhwr_cc(void)
 
3031
{
 
3032
    if ((env->hflags & MIPS_HFLAG_CP0) ||
 
3033
        (env->CP0_HWREna & (1 << 2)))
 
3034
        T0 = env->CP0_Count;
 
3035
    else
 
3036
        CALL_FROM_TB1(do_raise_exception, EXCP_RI);
 
3037
    RETURN();
 
3038
}
 
3039
 
 
3040
void op_rdhwr_ccres(void)
 
3041
{
 
3042
    if ((env->hflags & MIPS_HFLAG_CP0) ||
 
3043
        (env->CP0_HWREna & (1 << 3)))
 
3044
        T0 = env->CCRes;
 
3045
    else
 
3046
        CALL_FROM_TB1(do_raise_exception, EXCP_RI);
 
3047
    RETURN();
 
3048
}
 
3049
 
 
3050
void op_save_state (void)
 
3051
{
 
3052
    env->hflags = PARAM1;
 
3053
    RETURN();
 
3054
}
 
3055
 
 
3056
void op_save_pc (void)
 
3057
{
 
3058
    env->PC[env->current_tc] = PARAM1;
 
3059
    RETURN();
 
3060
}
 
3061
 
 
3062
#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
 
3063
void op_save_pc64 (void)
 
3064
{
 
3065
    env->PC[env->current_tc] = ((uint64_t)PARAM1 << 32) | (uint32_t)PARAM2;
 
3066
    RETURN();
 
3067
}
 
3068
#endif
 
3069
 
 
3070
void op_interrupt_restart (void)
 
3071
{
 
3072
    if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
 
3073
        !(env->CP0_Status & (1 << CP0St_ERL)) &&
 
3074
        !(env->hflags & MIPS_HFLAG_DM) &&
 
3075
        (env->CP0_Status & (1 << CP0St_IE)) &&
 
3076
        (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask)) {
 
3077
        env->CP0_Cause &= ~(0x1f << CP0Ca_EC);
 
3078
        CALL_FROM_TB1(do_raise_exception, EXCP_EXT_INTERRUPT);
 
3079
    }
 
3080
    RETURN();
 
3081
}
 
3082
 
 
3083
void op_raise_exception (void)
 
3084
{
 
3085
    CALL_FROM_TB1(do_raise_exception, PARAM1);
 
3086
    RETURN();
 
3087
}
 
3088
 
 
3089
void op_raise_exception_err (void)
 
3090
{
 
3091
    CALL_FROM_TB2(do_raise_exception_err, PARAM1, PARAM2);
 
3092
    RETURN();
 
3093
}
 
3094
 
 
3095
void op_exit_tb (void)
 
3096
{
 
3097
    EXIT_TB();
 
3098
    RETURN();
 
3099
}
 
3100
 
 
3101
void op_wait (void)
 
3102
{
 
3103
    env->halted = 1;
 
3104
    CALL_FROM_TB1(do_raise_exception, EXCP_HLT);
 
3105
    RETURN();
 
3106
}
 
3107
 
 
3108
/* Bitfield operations. */
 
3109
void op_ext(void)
 
3110
{
 
3111
    unsigned int pos = PARAM1;
 
3112
    unsigned int size = PARAM2;
 
3113
 
 
3114
    T0 = ((uint32_t)T1 >> pos) & ((size < 32) ? ((1 << size) - 1) : ~0);
 
3115
    RETURN();
 
3116
}
 
3117
 
 
3118
void op_ins(void)
 
3119
{
 
3120
    unsigned int pos = PARAM1;
 
3121
    unsigned int size = PARAM2;
 
3122
    target_ulong mask = ((size < 32) ? ((1 << size) - 1) : ~0) << pos;
 
3123
 
 
3124
    T0 = (T0 & ~mask) | (((uint32_t)T1 << pos) & mask);
 
3125
    RETURN();
 
3126
}
 
3127
 
 
3128
void op_wsbh(void)
 
3129
{
 
3130
    T0 = ((T1 << 8) & ~0x00FF00FF) | ((T1 >> 8) & 0x00FF00FF);
 
3131
    RETURN();
 
3132
}
 
3133
 
 
3134
#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
 
3135
void op_dext(void)
 
3136
{
 
3137
    unsigned int pos = PARAM1;
 
3138
    unsigned int size = PARAM2;
 
3139
 
 
3140
    T0 = (T1 >> pos) & ((size < 32) ? ((1 << size) - 1) : ~0);
 
3141
    RETURN();
 
3142
}
 
3143
 
 
3144
void op_dins(void)
 
3145
{
 
3146
    unsigned int pos = PARAM1;
 
3147
    unsigned int size = PARAM2;
 
3148
    target_ulong mask = ((size < 32) ? ((1 << size) - 1) : ~0) << pos;
 
3149
 
 
3150
    T0 = (T0 & ~mask) | ((T1 << pos) & mask);
 
3151
    RETURN();
 
3152
}
 
3153
 
 
3154
void op_dsbh(void)
 
3155
{
 
3156
    T0 = ((T1 << 8) & ~0x00FF00FF00FF00FFULL) | ((T1 >> 8) & 0x00FF00FF00FF00FFULL);
 
3157
    RETURN();
 
3158
}
 
3159
 
 
3160
void op_dshd(void)
 
3161
{
 
3162
    T0 = ((T1 << 16) & ~0x0000FFFF0000FFFFULL) | ((T1 >> 16) & 0x0000FFFF0000FFFFULL);
 
3163
    RETURN();
 
3164
}
 
3165
#endif
 
3166
 
 
3167
void op_seb(void)
 
3168
{
 
3169
    T0 = ((T1 & 0xFF) ^ 0x80) - 0x80;
 
3170
    RETURN();
 
3171
}
 
3172
 
 
3173
void op_seh(void)
 
3174
{
 
3175
    T0 = ((T1 & 0xFFFF) ^ 0x8000) - 0x8000;
 
3176
    RETURN();
 
3177
}