Statistics
| Branch: | Revision:

root / target-sparc / op_helper.c @ 02aab46a

History | View | Annotate | Download (23.3 kB)

1
#include "exec.h"
2

    
3
//#define DEBUG_PCALL
4
//#define DEBUG_MMU
5

    
6
void raise_exception(int tt)
7
{
8
    env->exception_index = tt;
9
    cpu_loop_exit();
10
}   
11

    
12
#ifdef USE_INT_TO_FLOAT_HELPERS
13
void do_fitos(void)
14
{
15
    FT0 = (float) *((int32_t *)&FT1);
16
}
17

    
18
void do_fitod(void)
19
{
20
    DT0 = (double) *((int32_t *)&FT1);
21
}
22
#endif
23

    
24
void do_fabss(void)
25
{
26
    FT0 = float32_abs(FT1);
27
}
28

    
29
#ifdef TARGET_SPARC64
30
void do_fabsd(void)
31
{
32
    DT0 = float64_abs(DT1);
33
}
34
#endif
35

    
36
void do_fsqrts(void)
37
{
38
    FT0 = float32_sqrt(FT1, &env->fp_status);
39
}
40

    
41
void do_fsqrtd(void)
42
{
43
    DT0 = float64_sqrt(DT1, &env->fp_status);
44
}
45

    
46
#define FS 0
47
void do_fcmps (void)
48
{
49
    env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
50
    if (isnan(FT0) || isnan(FT1)) {
51
        T0 = (FSR_FCC1 | FSR_FCC0) << FS;
52
        if (env->fsr & FSR_NVM) {
53
            env->fsr |= T0;
54
            raise_exception(TT_FP_EXCP);
55
        } else {
56
            env->fsr |= FSR_NVA;
57
        }
58
    } else if (FT0 < FT1) {
59
        T0 = FSR_FCC0 << FS;
60
    } else if (FT0 > FT1) {
61
        T0 = FSR_FCC1 << FS;
62
    } else {
63
        T0 = 0;
64
    }
65
    env->fsr |= T0;
66
}
67

    
68
void do_fcmpd (void)
69
{
70
    env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
71
    if (isnan(DT0) || isnan(DT1)) {
72
        T0 = (FSR_FCC1 | FSR_FCC0) << FS;
73
        if (env->fsr & FSR_NVM) {
74
            env->fsr |= T0;
75
            raise_exception(TT_FP_EXCP);
76
        } else {
77
            env->fsr |= FSR_NVA;
78
        }
79
    } else if (DT0 < DT1) {
80
        T0 = FSR_FCC0 << FS;
81
    } else if (DT0 > DT1) {
82
        T0 = FSR_FCC1 << FS;
83
    } else {
84
        T0 = 0;
85
    }
86
    env->fsr |= T0;
87
}
88

    
89
#ifdef TARGET_SPARC64
90
#undef FS
91
#define FS 22
92
void do_fcmps_fcc1 (void)
93
{
94
    env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
95
    if (isnan(FT0) || isnan(FT1)) {
96
        T0 = (FSR_FCC1 | FSR_FCC0) << FS;
97
        if (env->fsr & FSR_NVM) {
98
            env->fsr |= T0;
99
            raise_exception(TT_FP_EXCP);
100
        } else {
101
            env->fsr |= FSR_NVA;
102
        }
103
    } else if (FT0 < FT1) {
104
        T0 = FSR_FCC0 << FS;
105
    } else if (FT0 > FT1) {
106
        T0 = FSR_FCC1 << FS;
107
    } else {
108
        T0 = 0;
109
    }
110
    env->fsr |= T0;
111
}
112

    
113
void do_fcmpd_fcc1 (void)
114
{
115
    env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
116
    if (isnan(DT0) || isnan(DT1)) {
117
        T0 = (FSR_FCC1 | FSR_FCC0) << FS;
118
        if (env->fsr & FSR_NVM) {
119
            env->fsr |= T0;
120
            raise_exception(TT_FP_EXCP);
121
        } else {
122
            env->fsr |= FSR_NVA;
123
        }
124
    } else if (DT0 < DT1) {
125
        T0 = FSR_FCC0 << FS;
126
    } else if (DT0 > DT1) {
127
        T0 = FSR_FCC1 << FS;
128
    } else {
129
        T0 = 0;
130
    }
131
    env->fsr |= T0;
132
}
133

    
134
#undef FS
135
#define FS 24
136
void do_fcmps_fcc2 (void)
137
{
138
    env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
139
    if (isnan(FT0) || isnan(FT1)) {
140
        T0 = (FSR_FCC1 | FSR_FCC0) << FS;
141
        if (env->fsr & FSR_NVM) {
142
            env->fsr |= T0;
143
            raise_exception(TT_FP_EXCP);
144
        } else {
145
            env->fsr |= FSR_NVA;
146
        }
147
    } else if (FT0 < FT1) {
148
        T0 = FSR_FCC0 << FS;
149
    } else if (FT0 > FT1) {
150
        T0 = FSR_FCC1 << FS;
151
    } else {
152
        T0 = 0;
153
    }
154
    env->fsr |= T0;
155
}
156

    
157
void do_fcmpd_fcc2 (void)
158
{
159
    env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
160
    if (isnan(DT0) || isnan(DT1)) {
161
        T0 = (FSR_FCC1 | FSR_FCC0) << FS;
162
        if (env->fsr & FSR_NVM) {
163
            env->fsr |= T0;
164
            raise_exception(TT_FP_EXCP);
165
        } else {
166
            env->fsr |= FSR_NVA;
167
        }
168
    } else if (DT0 < DT1) {
169
        T0 = FSR_FCC0 << FS;
170
    } else if (DT0 > DT1) {
171
        T0 = FSR_FCC1 << FS;
172
    } else {
173
        T0 = 0;
174
    }
175
    env->fsr |= T0;
176
}
177

    
178
#undef FS
179
#define FS 26
180
void do_fcmps_fcc3 (void)
181
{
182
    env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
183
    if (isnan(FT0) || isnan(FT1)) {
184
        T0 = (FSR_FCC1 | FSR_FCC0) << FS;
185
        if (env->fsr & FSR_NVM) {
186
            env->fsr |= T0;
187
            raise_exception(TT_FP_EXCP);
188
        } else {
189
            env->fsr |= FSR_NVA;
190
        }
191
    } else if (FT0 < FT1) {
192
        T0 = FSR_FCC0 << FS;
193
    } else if (FT0 > FT1) {
194
        T0 = FSR_FCC1 << FS;
195
    } else {
196
        T0 = 0;
197
    }
198
    env->fsr |= T0;
199
}
200

    
201
void do_fcmpd_fcc3 (void)
202
{
203
    env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
204
    if (isnan(DT0) || isnan(DT1)) {
205
        T0 = (FSR_FCC1 | FSR_FCC0) << FS;
206
        if (env->fsr & FSR_NVM) {
207
            env->fsr |= T0;
208
            raise_exception(TT_FP_EXCP);
209
        } else {
210
            env->fsr |= FSR_NVA;
211
        }
212
    } else if (DT0 < DT1) {
213
        T0 = FSR_FCC0 << FS;
214
    } else if (DT0 > DT1) {
215
        T0 = FSR_FCC1 << FS;
216
    } else {
217
        T0 = 0;
218
    }
219
    env->fsr |= T0;
220
}
221
#undef FS
222
#endif
223

    
224
#ifndef TARGET_SPARC64
225
void helper_ld_asi(int asi, int size, int sign)
226
{
227
    uint32_t ret = 0;
228

    
229
    switch (asi) {
230
    case 3: /* MMU probe */
231
        {
232
            int mmulev;
233

    
234
            mmulev = (T0 >> 8) & 15;
235
            if (mmulev > 4)
236
                ret = 0;
237
            else {
238
                ret = mmu_probe(env, T0, mmulev);
239
                //bswap32s(&ret);
240
            }
241
#ifdef DEBUG_MMU
242
            printf("mmu_probe: 0x%08x (lev %d) -> 0x%08x\n", T0, mmulev, ret);
243
#endif
244
        }
245
        break;
246
    case 4: /* read MMU regs */
247
        {
248
            int reg = (T0 >> 8) & 0xf;
249
            
250
            ret = env->mmuregs[reg];
251
            if (reg == 3) /* Fault status cleared on read */
252
                env->mmuregs[reg] = 0;
253
#ifdef DEBUG_MMU
254
            printf("mmu_read: reg[%d] = 0x%08x\n", reg, ret);
255
#endif
256
        }
257
        break;
258
    case 0x20 ... 0x2f: /* MMU passthrough */
259
        switch(size) {
260
        case 1:
261
            ret = ldub_phys(T0);
262
            break;
263
        case 2:
264
            ret = lduw_phys(T0 & ~1);
265
            break;
266
        default:
267
        case 4:
268
            ret = ldl_phys(T0 & ~3);
269
            break;
270
        }
271
        break;
272
    default:
273
        ret = 0;
274
        break;
275
    }
276
    T1 = ret;
277
}
278

    
279
void helper_st_asi(int asi, int size, int sign)
280
{
281
    switch(asi) {
282
    case 3: /* MMU flush */
283
        {
284
            int mmulev;
285

    
286
            mmulev = (T0 >> 8) & 15;
287
#ifdef DEBUG_MMU
288
            printf("mmu flush level %d\n", mmulev);
289
#endif
290
            switch (mmulev) {
291
            case 0: // flush page
292
                tlb_flush_page(env, T0 & 0xfffff000);
293
                break;
294
            case 1: // flush segment (256k)
295
            case 2: // flush region (16M)
296
            case 3: // flush context (4G)
297
            case 4: // flush entire
298
                tlb_flush(env, 1);
299
                break;
300
            default:
301
                break;
302
            }
303
#ifdef DEBUG_MMU
304
            dump_mmu(env);
305
#endif
306
            return;
307
        }
308
    case 4: /* write MMU regs */
309
        {
310
            int reg = (T0 >> 8) & 0xf;
311
            uint32_t oldreg;
312
            
313
            oldreg = env->mmuregs[reg];
314
            switch(reg) {
315
            case 0:
316
                env->mmuregs[reg] &= ~(MMU_E | MMU_NF);
317
                env->mmuregs[reg] |= T1 & (MMU_E | MMU_NF);
318
                // Mappings generated during no-fault mode or MMU
319
                // disabled mode are invalid in normal mode
320
                if (oldreg != env->mmuregs[reg])
321
                    tlb_flush(env, 1);
322
                break;
323
            case 2:
324
                env->mmuregs[reg] = T1;
325
                if (oldreg != env->mmuregs[reg]) {
326
                    /* we flush when the MMU context changes because
327
                       QEMU has no MMU context support */
328
                    tlb_flush(env, 1);
329
                }
330
                break;
331
            case 3:
332
            case 4:
333
                break;
334
            default:
335
                env->mmuregs[reg] = T1;
336
                break;
337
            }
338
#ifdef DEBUG_MMU
339
            if (oldreg != env->mmuregs[reg]) {
340
                printf("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->mmuregs[reg]);
341
            }
342
            dump_mmu(env);
343
#endif
344
            return;
345
        }
346
    case 0x17: /* Block copy, sta access */
347
        {
348
            // value (T1) = src
349
            // address (T0) = dst
350
            // copy 32 bytes
351
            uint32_t src = T1, dst = T0;
352
            uint8_t temp[32];
353
            
354
            tswap32s(&src);
355

    
356
            cpu_physical_memory_read(src, (void *) &temp, 32);
357
            cpu_physical_memory_write(dst, (void *) &temp, 32);
358
        }
359
        return;
360
    case 0x1f: /* Block fill, stda access */
361
        {
362
            // value (T1, T2)
363
            // address (T0) = dst
364
            // fill 32 bytes
365
            int i;
366
            uint32_t dst = T0;
367
            uint64_t val;
368
            
369
            val = (((uint64_t)T1) << 32) | T2;
370
            tswap64s(&val);
371

    
372
            for (i = 0; i < 32; i += 8, dst += 8) {
373
                cpu_physical_memory_write(dst, (void *) &val, 8);
374
            }
375
        }
376
        return;
377
    case 0x20 ... 0x2f: /* MMU passthrough */
378
        {
379
            switch(size) {
380
            case 1:
381
                stb_phys(T0, T1);
382
                break;
383
            case 2:
384
                stw_phys(T0 & ~1, T1);
385
                break;
386
            case 4:
387
            default:
388
                stl_phys(T0 & ~3, T1);
389
                break;
390
            }
391
        }
392
        return;
393
    default:
394
        return;
395
    }
396
}
397

    
398
#else
399

    
400
void helper_ld_asi(int asi, int size, int sign)
401
{
402
    uint64_t ret = 0;
403

    
404
    if (asi < 0x80 && (env->pstate & PS_PRIV) == 0)
405
        raise_exception(TT_PRIV_ACT);
406

    
407
    switch (asi) {
408
    case 0x14: // Bypass
409
    case 0x15: // Bypass, non-cacheable
410
        {
411
            switch(size) {
412
            case 1:
413
                ret = ldub_phys(T0);
414
                break;
415
            case 2:
416
                ret = lduw_phys(T0 & ~1);
417
                break;
418
            case 4:
419
                ret = ldl_phys(T0 & ~3);
420
                break;
421
            default:
422
            case 8:
423
                ret = ldq_phys(T0 & ~7);
424
                break;
425
            }
426
            break;
427
        }
428
    case 0x04: // Nucleus
429
    case 0x0c: // Nucleus Little Endian (LE)
430
    case 0x10: // As if user primary
431
    case 0x11: // As if user secondary
432
    case 0x18: // As if user primary LE
433
    case 0x19: // As if user secondary LE
434
    case 0x1c: // Bypass LE
435
    case 0x1d: // Bypass, non-cacheable LE
436
    case 0x24: // Nucleus quad LDD 128 bit atomic
437
    case 0x2c: // Nucleus quad LDD 128 bit atomic
438
    case 0x4a: // UPA config
439
    case 0x82: // Primary no-fault
440
    case 0x83: // Secondary no-fault
441
    case 0x88: // Primary LE
442
    case 0x89: // Secondary LE
443
    case 0x8a: // Primary no-fault LE
444
    case 0x8b: // Secondary no-fault LE
445
        // XXX
446
        break;
447
    case 0x45: // LSU
448
        ret = env->lsu;
449
        break;
450
    case 0x50: // I-MMU regs
451
        {
452
            int reg = (T0 >> 3) & 0xf;
453

    
454
            ret = env->immuregs[reg];
455
            break;
456
        }
457
    case 0x51: // I-MMU 8k TSB pointer
458
    case 0x52: // I-MMU 64k TSB pointer
459
    case 0x55: // I-MMU data access
460
        // XXX
461
        break;
462
    case 0x56: // I-MMU tag read
463
        {
464
            unsigned int i;
465
            
466
            for (i = 0; i < 64; i++) {
467
                // Valid, ctx match, vaddr match
468
                if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0 &&
469
                    env->itlb_tag[i] == T0) {
470
                    ret = env->itlb_tag[i];
471
                    break;
472
                }
473
            }
474
            break;
475
        }
476
    case 0x58: // D-MMU regs
477
        {
478
            int reg = (T0 >> 3) & 0xf;
479

    
480
            ret = env->dmmuregs[reg];
481
            break;
482
        }
483
    case 0x5e: // D-MMU tag read
484
        {
485
            unsigned int i;
486
            
487
            for (i = 0; i < 64; i++) {
488
                // Valid, ctx match, vaddr match
489
                if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0 &&
490
                    env->dtlb_tag[i] == T0) {
491
                    ret = env->dtlb_tag[i];
492
                    break;
493
                }
494
            }
495
            break;
496
        }
497
    case 0x59: // D-MMU 8k TSB pointer
498
    case 0x5a: // D-MMU 64k TSB pointer
499
    case 0x5b: // D-MMU data pointer
500
    case 0x5d: // D-MMU data access
501
    case 0x48: // Interrupt dispatch, RO
502
    case 0x49: // Interrupt data receive
503
    case 0x7f: // Incoming interrupt vector, RO
504
        // XXX
505
        break;
506
    case 0x54: // I-MMU data in, WO
507
    case 0x57: // I-MMU demap, WO
508
    case 0x5c: // D-MMU data in, WO
509
    case 0x5f: // D-MMU demap, WO
510
    case 0x77: // Interrupt vector, WO
511
    default:
512
        ret = 0;
513
        break;
514
    }
515
    T1 = ret;
516
}
517

    
518
void helper_st_asi(int asi, int size, int sign)
519
{
520
    if (asi < 0x80 && (env->pstate & PS_PRIV) == 0)
521
        raise_exception(TT_PRIV_ACT);
522

    
523
    switch(asi) {
524
    case 0x14: // Bypass
525
    case 0x15: // Bypass, non-cacheable
526
        {
527
            switch(size) {
528
            case 1:
529
                stb_phys(T0, T1);
530
                break;
531
            case 2:
532
                stw_phys(T0 & ~1, T1);
533
                break;
534
            case 4:
535
                stl_phys(T0 & ~3, T1);
536
                break;
537
            case 8:
538
            default:
539
                stq_phys(T0 & ~7, T1);
540
                break;
541
            }
542
        }
543
        return;
544
    case 0x04: // Nucleus
545
    case 0x0c: // Nucleus Little Endian (LE)
546
    case 0x10: // As if user primary
547
    case 0x11: // As if user secondary
548
    case 0x18: // As if user primary LE
549
    case 0x19: // As if user secondary LE
550
    case 0x1c: // Bypass LE
551
    case 0x1d: // Bypass, non-cacheable LE
552
    case 0x24: // Nucleus quad LDD 128 bit atomic
553
    case 0x2c: // Nucleus quad LDD 128 bit atomic
554
    case 0x4a: // UPA config
555
    case 0x88: // Primary LE
556
    case 0x89: // Secondary LE
557
        // XXX
558
        return;
559
    case 0x45: // LSU
560
        {
561
            uint64_t oldreg;
562

    
563
            oldreg = env->lsu;
564
            env->lsu = T1 & (DMMU_E | IMMU_E);
565
            // Mappings generated during D/I MMU disabled mode are
566
            // invalid in normal mode
567
            if (oldreg != env->lsu) {
568
#ifdef DEBUG_MMU
569
                printf("LSU change: 0x%llx -> 0x%llx\n", oldreg, env->lsu);
570
                dump_mmu(env);
571
#endif
572
                tlb_flush(env, 1);
573
            }
574
            return;
575
        }
576
    case 0x50: // I-MMU regs
577
        {
578
            int reg = (T0 >> 3) & 0xf;
579
            uint64_t oldreg;
580
            
581
            oldreg = env->immuregs[reg];
582
            switch(reg) {
583
            case 0: // RO
584
            case 4:
585
                return;
586
            case 1: // Not in I-MMU
587
            case 2:
588
            case 7:
589
            case 8:
590
                return;
591
            case 3: // SFSR
592
                if ((T1 & 1) == 0)
593
                    T1 = 0; // Clear SFSR
594
                break;
595
            case 5: // TSB access
596
            case 6: // Tag access
597
            default:
598
                break;
599
            }
600
            env->immuregs[reg] = T1;
601
#ifdef DEBUG_MMU
602
            if (oldreg != env->immuregs[reg]) {
603
                printf("mmu change reg[%d]: 0x%08llx -> 0x%08llx\n", reg, oldreg, env->immuregs[reg]);
604
            }
605
            dump_mmu(env);
606
#endif
607
            return;
608
        }
609
    case 0x54: // I-MMU data in
610
        {
611
            unsigned int i;
612

    
613
            // Try finding an invalid entry
614
            for (i = 0; i < 64; i++) {
615
                if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) {
616
                    env->itlb_tag[i] = env->immuregs[6];
617
                    env->itlb_tte[i] = T1;
618
                    return;
619
                }
620
            }
621
            // Try finding an unlocked entry
622
            for (i = 0; i < 64; i++) {
623
                if ((env->itlb_tte[i] & 0x40) == 0) {
624
                    env->itlb_tag[i] = env->immuregs[6];
625
                    env->itlb_tte[i] = T1;
626
                    return;
627
                }
628
            }
629
            // error state?
630
            return;
631
        }
632
    case 0x55: // I-MMU data access
633
        {
634
            unsigned int i = (T0 >> 3) & 0x3f;
635

    
636
            env->itlb_tag[i] = env->immuregs[6];
637
            env->itlb_tte[i] = T1;
638
            return;
639
        }
640
    case 0x57: // I-MMU demap
641
        // XXX
642
        return;
643
    case 0x58: // D-MMU regs
644
        {
645
            int reg = (T0 >> 3) & 0xf;
646
            uint64_t oldreg;
647
            
648
            oldreg = env->dmmuregs[reg];
649
            switch(reg) {
650
            case 0: // RO
651
            case 4:
652
                return;
653
            case 3: // SFSR
654
                if ((T1 & 1) == 0) {
655
                    T1 = 0; // Clear SFSR, Fault address
656
                    env->dmmuregs[4] = 0;
657
                }
658
                env->dmmuregs[reg] = T1;
659
                break;
660
            case 1: // Primary context
661
            case 2: // Secondary context
662
            case 5: // TSB access
663
            case 6: // Tag access
664
            case 7: // Virtual Watchpoint
665
            case 8: // Physical Watchpoint
666
            default:
667
                break;
668
            }
669
            env->dmmuregs[reg] = T1;
670
#ifdef DEBUG_MMU
671
            if (oldreg != env->dmmuregs[reg]) {
672
                printf("mmu change reg[%d]: 0x%08llx -> 0x%08llx\n", reg, oldreg, env->dmmuregs[reg]);
673
            }
674
            dump_mmu(env);
675
#endif
676
            return;
677
        }
678
    case 0x5c: // D-MMU data in
679
        {
680
            unsigned int i;
681

    
682
            // Try finding an invalid entry
683
            for (i = 0; i < 64; i++) {
684
                if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) {
685
                    env->dtlb_tag[i] = env->dmmuregs[6];
686
                    env->dtlb_tte[i] = T1;
687
                    return;
688
                }
689
            }
690
            // Try finding an unlocked entry
691
            for (i = 0; i < 64; i++) {
692
                if ((env->dtlb_tte[i] & 0x40) == 0) {
693
                    env->dtlb_tag[i] = env->dmmuregs[6];
694
                    env->dtlb_tte[i] = T1;
695
                    return;
696
                }
697
            }
698
            // error state?
699
            return;
700
        }
701
    case 0x5d: // D-MMU data access
702
        {
703
            unsigned int i = (T0 >> 3) & 0x3f;
704

    
705
            env->dtlb_tag[i] = env->dmmuregs[6];
706
            env->dtlb_tte[i] = T1;
707
            return;
708
        }
709
    case 0x5f: // D-MMU demap
710
    case 0x49: // Interrupt data receive
711
        // XXX
712
        return;
713
    case 0x51: // I-MMU 8k TSB pointer, RO
714
    case 0x52: // I-MMU 64k TSB pointer, RO
715
    case 0x56: // I-MMU tag read, RO
716
    case 0x59: // D-MMU 8k TSB pointer, RO
717
    case 0x5a: // D-MMU 64k TSB pointer, RO
718
    case 0x5b: // D-MMU data pointer, RO
719
    case 0x5e: // D-MMU tag read, RO
720
    case 0x48: // Interrupt dispatch, RO
721
    case 0x7f: // Incoming interrupt vector, RO
722
    case 0x82: // Primary no-fault, RO
723
    case 0x83: // Secondary no-fault, RO
724
    case 0x8a: // Primary no-fault LE, RO
725
    case 0x8b: // Secondary no-fault LE, RO
726
    default:
727
        return;
728
    }
729
}
730

    
731
#endif
732

    
733
#ifndef TARGET_SPARC64
734
void helper_rett()
735
{
736
    unsigned int cwp;
737

    
738
    env->psret = 1;
739
    cwp = (env->cwp + 1) & (NWINDOWS - 1); 
740
    if (env->wim & (1 << cwp)) {
741
        raise_exception(TT_WIN_UNF);
742
    }
743
    set_cwp(cwp);
744
    env->psrs = env->psrps;
745
}
746
#endif
747

    
748
void helper_ldfsr(void)
749
{
750
    int rnd_mode;
751
    switch (env->fsr & FSR_RD_MASK) {
752
    case FSR_RD_NEAREST:
753
        rnd_mode = float_round_nearest_even;
754
        break;
755
    default:
756
    case FSR_RD_ZERO:
757
        rnd_mode = float_round_to_zero;
758
        break;
759
    case FSR_RD_POS:
760
        rnd_mode = float_round_up;
761
        break;
762
    case FSR_RD_NEG:
763
        rnd_mode = float_round_down;
764
        break;
765
    }
766
    set_float_rounding_mode(rnd_mode, &env->fp_status);
767
}
768

    
769
void cpu_get_fp64(uint64_t *pmant, uint16_t *pexp, double f)
770
{
771
    int exptemp;
772

    
773
    *pmant = ldexp(frexp(f, &exptemp), 53);
774
    *pexp = exptemp;
775
}
776

    
777
double cpu_put_fp64(uint64_t mant, uint16_t exp)
778
{
779
    return ldexp((double) mant, exp - 53);
780
}
781

    
782
void helper_debug()
783
{
784
    env->exception_index = EXCP_DEBUG;
785
    cpu_loop_exit();
786
}
787

    
788
#ifndef TARGET_SPARC64
789
void do_wrpsr()
790
{
791
    PUT_PSR(env, T0);
792
}
793

    
794
void do_rdpsr()
795
{
796
    T0 = GET_PSR(env);
797
}
798

    
799
#else
800

    
801
void do_popc()
802
{
803
    T0 = (T1 & 0x5555555555555555ULL) + ((T1 >> 1) & 0x5555555555555555ULL);
804
    T0 = (T0 & 0x3333333333333333ULL) + ((T0 >> 2) & 0x3333333333333333ULL);
805
    T0 = (T0 & 0x0f0f0f0f0f0f0f0fULL) + ((T0 >> 4) & 0x0f0f0f0f0f0f0f0fULL);
806
    T0 = (T0 & 0x00ff00ff00ff00ffULL) + ((T0 >> 8) & 0x00ff00ff00ff00ffULL);
807
    T0 = (T0 & 0x0000ffff0000ffffULL) + ((T0 >> 16) & 0x0000ffff0000ffffULL);
808
    T0 = (T0 & 0x00000000ffffffffULL) + ((T0 >> 32) & 0x00000000ffffffffULL);
809
}
810

    
811
static inline uint64_t *get_gregset(uint64_t pstate)
812
{
813
    switch (pstate) {
814
    default:
815
    case 0:
816
        return env->bgregs;
817
    case PS_AG:
818
        return env->agregs;
819
    case PS_MG:
820
        return env->mgregs;
821
    case PS_IG:
822
        return env->igregs;
823
    }
824
}
825

    
826
void do_wrpstate()
827
{
828
    uint64_t new_pstate, pstate_regs, new_pstate_regs;
829
    uint64_t *src, *dst;
830

    
831
    new_pstate = T0 & 0xf3f;
832
    pstate_regs = env->pstate & 0xc01;
833
    new_pstate_regs = new_pstate & 0xc01;
834
    if (new_pstate_regs != pstate_regs) {
835
        // Switch global register bank
836
        src = get_gregset(new_pstate_regs);
837
        dst = get_gregset(pstate_regs);
838
        memcpy32(dst, env->gregs);
839
        memcpy32(env->gregs, src);
840
    }
841
    env->pstate = new_pstate;
842
}
843

    
844
void do_done(void)
845
{
846
    env->tl--;
847
    env->pc = env->tnpc[env->tl];
848
    env->npc = env->tnpc[env->tl] + 4;
849
    PUT_CCR(env, env->tstate[env->tl] >> 32);
850
    env->asi = (env->tstate[env->tl] >> 24) & 0xff;
851
    env->pstate = (env->tstate[env->tl] >> 8) & 0xfff;
852
    set_cwp(env->tstate[env->tl] & 0xff);
853
}
854

    
855
void do_retry(void)
856
{
857
    env->tl--;
858
    env->pc = env->tpc[env->tl];
859
    env->npc = env->tnpc[env->tl];
860
    PUT_CCR(env, env->tstate[env->tl] >> 32);
861
    env->asi = (env->tstate[env->tl] >> 24) & 0xff;
862
    env->pstate = (env->tstate[env->tl] >> 8) & 0xfff;
863
    set_cwp(env->tstate[env->tl] & 0xff);
864
}
865
#endif
866

    
867
void set_cwp(int new_cwp)
868
{
869
    /* put the modified wrap registers at their proper location */
870
    if (env->cwp == (NWINDOWS - 1))
871
        memcpy32(env->regbase, env->regbase + NWINDOWS * 16);
872
    env->cwp = new_cwp;
873
    /* put the wrap registers at their temporary location */
874
    if (new_cwp == (NWINDOWS - 1))
875
        memcpy32(env->regbase + NWINDOWS * 16, env->regbase);
876
    env->regwptr = env->regbase + (new_cwp * 16);
877
    REGWPTR = env->regwptr;
878
}
879

    
880
void cpu_set_cwp(CPUState *env1, int new_cwp)
881
{
882
    CPUState *saved_env;
883
#ifdef reg_REGWPTR
884
    target_ulong *saved_regwptr;
885
#endif
886

    
887
    saved_env = env;
888
#ifdef reg_REGWPTR
889
    saved_regwptr = REGWPTR;
890
#endif
891
    env = env1;
892
    set_cwp(new_cwp);
893
    env = saved_env;
894
#ifdef reg_REGWPTR
895
    REGWPTR = saved_regwptr;
896
#endif
897
}
898

    
899
#ifdef TARGET_SPARC64
900
void do_interrupt(int intno)
901
{
902
#ifdef DEBUG_PCALL
903
    if (loglevel & CPU_LOG_INT) {
904
        static int count;
905
        fprintf(logfile, "%6d: v=%04x pc=%016llx npc=%016llx SP=%016llx\n",
906
                count, intno,
907
                env->pc,
908
                env->npc, env->regwptr[6]);
909
        cpu_dump_state(env, logfile, fprintf, 0);
910
#if 0
911
        {
912
            int i;
913
            uint8_t *ptr;
914

915
            fprintf(logfile, "       code=");
916
            ptr = (uint8_t *)env->pc;
917
            for(i = 0; i < 16; i++) {
918
                fprintf(logfile, " %02x", ldub(ptr + i));
919
            }
920
            fprintf(logfile, "\n");
921
        }
922
#endif
923
        count++;
924
    }
925
#endif
926
#if !defined(CONFIG_USER_ONLY) 
927
    if (env->tl == MAXTL) {
928
        cpu_abort(cpu_single_env, "Trap 0x%04x while trap level is MAXTL, Error state", env->exception_index);
929
        return;
930
    }
931
#endif
932
    env->tstate[env->tl] = ((uint64_t)GET_CCR(env) << 32) | ((env->asi & 0xff) << 24) |
933
        ((env->pstate & 0xfff) << 8) | (env->cwp & 0xff);
934
    env->tpc[env->tl] = env->pc;
935
    env->tnpc[env->tl] = env->npc;
936
    env->tt[env->tl] = intno;
937
    env->pstate = PS_PEF | PS_PRIV | PS_AG;
938
    env->tbr &= ~0x7fffULL;
939
    env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
940
    if (env->tl < MAXTL - 1) {
941
        env->tl++;
942
    } else {
943
        env->pstate |= PS_RED;
944
        if (env->tl != MAXTL)
945
            env->tl++;
946
    }
947
    env->pc = env->tbr;
948
    env->npc = env->pc + 4;
949
    env->exception_index = 0;
950
}
951
#else
952
void do_interrupt(int intno)
953
{
954
    int cwp;
955

    
956
#ifdef DEBUG_PCALL
957
    if (loglevel & CPU_LOG_INT) {
958
        static int count;
959
        fprintf(logfile, "%6d: v=%02x pc=%08x npc=%08x SP=%08x\n",
960
                count, intno,
961
                env->pc,
962
                env->npc, env->regwptr[6]);
963
        cpu_dump_state(env, logfile, fprintf, 0);
964
#if 0
965
        {
966
            int i;
967
            uint8_t *ptr;
968

969
            fprintf(logfile, "       code=");
970
            ptr = (uint8_t *)env->pc;
971
            for(i = 0; i < 16; i++) {
972
                fprintf(logfile, " %02x", ldub(ptr + i));
973
            }
974
            fprintf(logfile, "\n");
975
        }
976
#endif
977
        count++;
978
    }
979
#endif
980
#if !defined(CONFIG_USER_ONLY) 
981
    if (env->psret == 0) {
982
        cpu_abort(cpu_single_env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index);
983
        return;
984
    }
985
#endif
986
    env->psret = 0;
987
    cwp = (env->cwp - 1) & (NWINDOWS - 1); 
988
    set_cwp(cwp);
989
    env->regwptr[9] = env->pc;
990
    env->regwptr[10] = env->npc;
991
    env->psrps = env->psrs;
992
    env->psrs = 1;
993
    env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
994
    env->pc = env->tbr;
995
    env->npc = env->pc + 4;
996
    env->exception_index = 0;
997
}
998
#endif
999

    
1000
#if !defined(CONFIG_USER_ONLY) 
1001

    
1002
#define MMUSUFFIX _mmu
1003
#define GETPC() (__builtin_return_address(0))
1004

    
1005
#define SHIFT 0
1006
#include "softmmu_template.h"
1007

    
1008
#define SHIFT 1
1009
#include "softmmu_template.h"
1010

    
1011
#define SHIFT 2
1012
#include "softmmu_template.h"
1013

    
1014
#define SHIFT 3
1015
#include "softmmu_template.h"
1016

    
1017

    
1018
/* try to fill the TLB and return an exception if error. If retaddr is
1019
   NULL, it means that the function was called in C code (i.e. not
1020
   from generated code or from helper.c) */
1021
/* XXX: fix it to restore all registers */
1022
void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr)
1023
{
1024
    TranslationBlock *tb;
1025
    int ret;
1026
    unsigned long pc;
1027
    CPUState *saved_env;
1028

    
1029
    /* XXX: hack to restore env in all cases, even if not called from
1030
       generated code */
1031
    saved_env = env;
1032
    env = cpu_single_env;
1033

    
1034
    ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, is_user, 1);
1035
    if (ret) {
1036
        if (retaddr) {
1037
            /* now we have a real cpu fault */
1038
            pc = (unsigned long)retaddr;
1039
            tb = tb_find_pc(pc);
1040
            if (tb) {
1041
                /* the PC is inside the translated code. It means that we have
1042
                   a virtual CPU fault */
1043
                cpu_restore_state(tb, env, pc, (void *)T2);
1044
            }
1045
        }
1046
        cpu_loop_exit();
1047
    }
1048
    env = saved_env;
1049
}
1050

    
1051
#endif