Statistics
| Branch: | Revision:

root / target-sparc / op_helper.c @ c68ea704

History | View | Annotate | Download (23.7 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
#if defined(CONFIG_USER_ONLY) 
225
void helper_ld_asi(int asi, int size, int sign)
226
{
227
}
228

    
229
void helper_st_asi(int asi, int size, int sign)
230
{
231
}
232
#else
233
#ifndef TARGET_SPARC64
234
void helper_ld_asi(int asi, int size, int sign)
235
{
236
    uint32_t ret = 0;
237

    
238
    switch (asi) {
239
    case 3: /* MMU probe */
240
        {
241
            int mmulev;
242

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

    
292
void helper_st_asi(int asi, int size, int sign)
293
{
294
    switch(asi) {
295
    case 3: /* MMU flush */
296
        {
297
            int mmulev;
298

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

    
369
            cpu_physical_memory_read(src, (void *) &temp, 32);
370
            cpu_physical_memory_write(dst, (void *) &temp, 32);
371
        }
372
        return;
373
    case 0x1f: /* Block fill, stda access */
374
        {
375
            // value (T1, T2)
376
            // address (T0) = dst
377
            // fill 32 bytes
378
            int i;
379
            uint32_t dst = T0;
380
            uint64_t val;
381
            
382
            val = (((uint64_t)T1) << 32) | T2;
383
            tswap64s(&val);
384

    
385
            for (i = 0; i < 32; i += 8, dst += 8) {
386
                cpu_physical_memory_write(dst, (void *) &val, 8);
387
            }
388
        }
389
        return;
390
    case 0x20 ... 0x2f: /* MMU passthrough */
391
        {
392
            switch(size) {
393
            case 1:
394
                stb_phys(T0, T1);
395
                break;
396
            case 2:
397
                stw_phys(T0 & ~1, T1);
398
                break;
399
            case 4:
400
            default:
401
                stl_phys(T0 & ~3, T1);
402
                break;
403
            case 8:
404
                stl_phys(T0 & ~3, T1);
405
                stl_phys((T0 + 4) & ~3, T2);
406
                break;
407
            }
408
        }
409
        return;
410
    default:
411
        return;
412
    }
413
}
414

    
415
#else
416

    
417
void helper_ld_asi(int asi, int size, int sign)
418
{
419
    uint64_t ret = 0;
420

    
421
    if (asi < 0x80 && (env->pstate & PS_PRIV) == 0)
422
        raise_exception(TT_PRIV_ACT);
423

    
424
    switch (asi) {
425
    case 0x14: // Bypass
426
    case 0x15: // Bypass, non-cacheable
427
        {
428
            switch(size) {
429
            case 1:
430
                ret = ldub_phys(T0);
431
                break;
432
            case 2:
433
                ret = lduw_phys(T0 & ~1);
434
                break;
435
            case 4:
436
                ret = ldl_phys(T0 & ~3);
437
                break;
438
            default:
439
            case 8:
440
                ret = ldq_phys(T0 & ~7);
441
                break;
442
            }
443
            break;
444
        }
445
    case 0x04: // Nucleus
446
    case 0x0c: // Nucleus Little Endian (LE)
447
    case 0x10: // As if user primary
448
    case 0x11: // As if user secondary
449
    case 0x18: // As if user primary LE
450
    case 0x19: // As if user secondary LE
451
    case 0x1c: // Bypass LE
452
    case 0x1d: // Bypass, non-cacheable LE
453
    case 0x24: // Nucleus quad LDD 128 bit atomic
454
    case 0x2c: // Nucleus quad LDD 128 bit atomic
455
    case 0x4a: // UPA config
456
    case 0x82: // Primary no-fault
457
    case 0x83: // Secondary no-fault
458
    case 0x88: // Primary LE
459
    case 0x89: // Secondary LE
460
    case 0x8a: // Primary no-fault LE
461
    case 0x8b: // Secondary no-fault LE
462
        // XXX
463
        break;
464
    case 0x45: // LSU
465
        ret = env->lsu;
466
        break;
467
    case 0x50: // I-MMU regs
468
        {
469
            int reg = (T0 >> 3) & 0xf;
470

    
471
            ret = env->immuregs[reg];
472
            break;
473
        }
474
    case 0x51: // I-MMU 8k TSB pointer
475
    case 0x52: // I-MMU 64k TSB pointer
476
    case 0x55: // I-MMU data access
477
        // XXX
478
        break;
479
    case 0x56: // I-MMU tag read
480
        {
481
            unsigned int i;
482
            
483
            for (i = 0; i < 64; i++) {
484
                // Valid, ctx match, vaddr match
485
                if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0 &&
486
                    env->itlb_tag[i] == T0) {
487
                    ret = env->itlb_tag[i];
488
                    break;
489
                }
490
            }
491
            break;
492
        }
493
    case 0x58: // D-MMU regs
494
        {
495
            int reg = (T0 >> 3) & 0xf;
496

    
497
            ret = env->dmmuregs[reg];
498
            break;
499
        }
500
    case 0x5e: // D-MMU tag read
501
        {
502
            unsigned int i;
503
            
504
            for (i = 0; i < 64; i++) {
505
                // Valid, ctx match, vaddr match
506
                if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0 &&
507
                    env->dtlb_tag[i] == T0) {
508
                    ret = env->dtlb_tag[i];
509
                    break;
510
                }
511
            }
512
            break;
513
        }
514
    case 0x59: // D-MMU 8k TSB pointer
515
    case 0x5a: // D-MMU 64k TSB pointer
516
    case 0x5b: // D-MMU data pointer
517
    case 0x5d: // D-MMU data access
518
    case 0x48: // Interrupt dispatch, RO
519
    case 0x49: // Interrupt data receive
520
    case 0x7f: // Incoming interrupt vector, RO
521
        // XXX
522
        break;
523
    case 0x54: // I-MMU data in, WO
524
    case 0x57: // I-MMU demap, WO
525
    case 0x5c: // D-MMU data in, WO
526
    case 0x5f: // D-MMU demap, WO
527
    case 0x77: // Interrupt vector, WO
528
    default:
529
        ret = 0;
530
        break;
531
    }
532
    T1 = ret;
533
}
534

    
535
void helper_st_asi(int asi, int size, int sign)
536
{
537
    if (asi < 0x80 && (env->pstate & PS_PRIV) == 0)
538
        raise_exception(TT_PRIV_ACT);
539

    
540
    switch(asi) {
541
    case 0x14: // Bypass
542
    case 0x15: // Bypass, non-cacheable
543
        {
544
            switch(size) {
545
            case 1:
546
                stb_phys(T0, T1);
547
                break;
548
            case 2:
549
                stw_phys(T0 & ~1, T1);
550
                break;
551
            case 4:
552
                stl_phys(T0 & ~3, T1);
553
                break;
554
            case 8:
555
            default:
556
                stq_phys(T0 & ~7, T1);
557
                break;
558
            }
559
        }
560
        return;
561
    case 0x04: // Nucleus
562
    case 0x0c: // Nucleus Little Endian (LE)
563
    case 0x10: // As if user primary
564
    case 0x11: // As if user secondary
565
    case 0x18: // As if user primary LE
566
    case 0x19: // As if user secondary LE
567
    case 0x1c: // Bypass LE
568
    case 0x1d: // Bypass, non-cacheable LE
569
    case 0x24: // Nucleus quad LDD 128 bit atomic
570
    case 0x2c: // Nucleus quad LDD 128 bit atomic
571
    case 0x4a: // UPA config
572
    case 0x88: // Primary LE
573
    case 0x89: // Secondary LE
574
        // XXX
575
        return;
576
    case 0x45: // LSU
577
        {
578
            uint64_t oldreg;
579

    
580
            oldreg = env->lsu;
581
            env->lsu = T1 & (DMMU_E | IMMU_E);
582
            // Mappings generated during D/I MMU disabled mode are
583
            // invalid in normal mode
584
            if (oldreg != env->lsu) {
585
#ifdef DEBUG_MMU
586
                printf("LSU change: 0x%llx -> 0x%llx\n", oldreg, env->lsu);
587
                dump_mmu(env);
588
#endif
589
                tlb_flush(env, 1);
590
            }
591
            return;
592
        }
593
    case 0x50: // I-MMU regs
594
        {
595
            int reg = (T0 >> 3) & 0xf;
596
            uint64_t oldreg;
597
            
598
            oldreg = env->immuregs[reg];
599
            switch(reg) {
600
            case 0: // RO
601
            case 4:
602
                return;
603
            case 1: // Not in I-MMU
604
            case 2:
605
            case 7:
606
            case 8:
607
                return;
608
            case 3: // SFSR
609
                if ((T1 & 1) == 0)
610
                    T1 = 0; // Clear SFSR
611
                break;
612
            case 5: // TSB access
613
            case 6: // Tag access
614
            default:
615
                break;
616
            }
617
            env->immuregs[reg] = T1;
618
#ifdef DEBUG_MMU
619
            if (oldreg != env->immuregs[reg]) {
620
                printf("mmu change reg[%d]: 0x%08llx -> 0x%08llx\n", reg, oldreg, env->immuregs[reg]);
621
            }
622
            dump_mmu(env);
623
#endif
624
            return;
625
        }
626
    case 0x54: // I-MMU data in
627
        {
628
            unsigned int i;
629

    
630
            // Try finding an invalid entry
631
            for (i = 0; i < 64; i++) {
632
                if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) {
633
                    env->itlb_tag[i] = env->immuregs[6];
634
                    env->itlb_tte[i] = T1;
635
                    return;
636
                }
637
            }
638
            // Try finding an unlocked entry
639
            for (i = 0; i < 64; i++) {
640
                if ((env->itlb_tte[i] & 0x40) == 0) {
641
                    env->itlb_tag[i] = env->immuregs[6];
642
                    env->itlb_tte[i] = T1;
643
                    return;
644
                }
645
            }
646
            // error state?
647
            return;
648
        }
649
    case 0x55: // I-MMU data access
650
        {
651
            unsigned int i = (T0 >> 3) & 0x3f;
652

    
653
            env->itlb_tag[i] = env->immuregs[6];
654
            env->itlb_tte[i] = T1;
655
            return;
656
        }
657
    case 0x57: // I-MMU demap
658
        // XXX
659
        return;
660
    case 0x58: // D-MMU regs
661
        {
662
            int reg = (T0 >> 3) & 0xf;
663
            uint64_t oldreg;
664
            
665
            oldreg = env->dmmuregs[reg];
666
            switch(reg) {
667
            case 0: // RO
668
            case 4:
669
                return;
670
            case 3: // SFSR
671
                if ((T1 & 1) == 0) {
672
                    T1 = 0; // Clear SFSR, Fault address
673
                    env->dmmuregs[4] = 0;
674
                }
675
                env->dmmuregs[reg] = T1;
676
                break;
677
            case 1: // Primary context
678
            case 2: // Secondary context
679
            case 5: // TSB access
680
            case 6: // Tag access
681
            case 7: // Virtual Watchpoint
682
            case 8: // Physical Watchpoint
683
            default:
684
                break;
685
            }
686
            env->dmmuregs[reg] = T1;
687
#ifdef DEBUG_MMU
688
            if (oldreg != env->dmmuregs[reg]) {
689
                printf("mmu change reg[%d]: 0x%08llx -> 0x%08llx\n", reg, oldreg, env->dmmuregs[reg]);
690
            }
691
            dump_mmu(env);
692
#endif
693
            return;
694
        }
695
    case 0x5c: // D-MMU data in
696
        {
697
            unsigned int i;
698

    
699
            // Try finding an invalid entry
700
            for (i = 0; i < 64; i++) {
701
                if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) {
702
                    env->dtlb_tag[i] = env->dmmuregs[6];
703
                    env->dtlb_tte[i] = T1;
704
                    return;
705
                }
706
            }
707
            // Try finding an unlocked entry
708
            for (i = 0; i < 64; i++) {
709
                if ((env->dtlb_tte[i] & 0x40) == 0) {
710
                    env->dtlb_tag[i] = env->dmmuregs[6];
711
                    env->dtlb_tte[i] = T1;
712
                    return;
713
                }
714
            }
715
            // error state?
716
            return;
717
        }
718
    case 0x5d: // D-MMU data access
719
        {
720
            unsigned int i = (T0 >> 3) & 0x3f;
721

    
722
            env->dtlb_tag[i] = env->dmmuregs[6];
723
            env->dtlb_tte[i] = T1;
724
            return;
725
        }
726
    case 0x5f: // D-MMU demap
727
    case 0x49: // Interrupt data receive
728
        // XXX
729
        return;
730
    case 0x51: // I-MMU 8k TSB pointer, RO
731
    case 0x52: // I-MMU 64k TSB pointer, RO
732
    case 0x56: // I-MMU tag read, RO
733
    case 0x59: // D-MMU 8k TSB pointer, RO
734
    case 0x5a: // D-MMU 64k TSB pointer, RO
735
    case 0x5b: // D-MMU data pointer, RO
736
    case 0x5e: // D-MMU tag read, RO
737
    case 0x48: // Interrupt dispatch, RO
738
    case 0x7f: // Incoming interrupt vector, RO
739
    case 0x82: // Primary no-fault, RO
740
    case 0x83: // Secondary no-fault, RO
741
    case 0x8a: // Primary no-fault LE, RO
742
    case 0x8b: // Secondary no-fault LE, RO
743
    default:
744
        return;
745
    }
746
}
747
#endif
748
#endif /* !CONFIG_USER_ONLY */
749

    
750
#ifndef TARGET_SPARC64
751
void helper_rett()
752
{
753
    unsigned int cwp;
754

    
755
    env->psret = 1;
756
    cwp = (env->cwp + 1) & (NWINDOWS - 1); 
757
    if (env->wim & (1 << cwp)) {
758
        raise_exception(TT_WIN_UNF);
759
    }
760
    set_cwp(cwp);
761
    env->psrs = env->psrps;
762
}
763
#endif
764

    
765
void helper_ldfsr(void)
766
{
767
    int rnd_mode;
768
    switch (env->fsr & FSR_RD_MASK) {
769
    case FSR_RD_NEAREST:
770
        rnd_mode = float_round_nearest_even;
771
        break;
772
    default:
773
    case FSR_RD_ZERO:
774
        rnd_mode = float_round_to_zero;
775
        break;
776
    case FSR_RD_POS:
777
        rnd_mode = float_round_up;
778
        break;
779
    case FSR_RD_NEG:
780
        rnd_mode = float_round_down;
781
        break;
782
    }
783
    set_float_rounding_mode(rnd_mode, &env->fp_status);
784
}
785

    
786
void cpu_get_fp64(uint64_t *pmant, uint16_t *pexp, double f)
787
{
788
    int exptemp;
789

    
790
    *pmant = ldexp(frexp(f, &exptemp), 53);
791
    *pexp = exptemp;
792
}
793

    
794
double cpu_put_fp64(uint64_t mant, uint16_t exp)
795
{
796
    return ldexp((double) mant, exp - 53);
797
}
798

    
799
void helper_debug()
800
{
801
    env->exception_index = EXCP_DEBUG;
802
    cpu_loop_exit();
803
}
804

    
805
#ifndef TARGET_SPARC64
806
void do_wrpsr()
807
{
808
    PUT_PSR(env, T0);
809
}
810

    
811
void do_rdpsr()
812
{
813
    T0 = GET_PSR(env);
814
}
815

    
816
#else
817

    
818
void do_popc()
819
{
820
    T0 = (T1 & 0x5555555555555555ULL) + ((T1 >> 1) & 0x5555555555555555ULL);
821
    T0 = (T0 & 0x3333333333333333ULL) + ((T0 >> 2) & 0x3333333333333333ULL);
822
    T0 = (T0 & 0x0f0f0f0f0f0f0f0fULL) + ((T0 >> 4) & 0x0f0f0f0f0f0f0f0fULL);
823
    T0 = (T0 & 0x00ff00ff00ff00ffULL) + ((T0 >> 8) & 0x00ff00ff00ff00ffULL);
824
    T0 = (T0 & 0x0000ffff0000ffffULL) + ((T0 >> 16) & 0x0000ffff0000ffffULL);
825
    T0 = (T0 & 0x00000000ffffffffULL) + ((T0 >> 32) & 0x00000000ffffffffULL);
826
}
827

    
828
static inline uint64_t *get_gregset(uint64_t pstate)
829
{
830
    switch (pstate) {
831
    default:
832
    case 0:
833
        return env->bgregs;
834
    case PS_AG:
835
        return env->agregs;
836
    case PS_MG:
837
        return env->mgregs;
838
    case PS_IG:
839
        return env->igregs;
840
    }
841
}
842

    
843
void do_wrpstate()
844
{
845
    uint64_t new_pstate, pstate_regs, new_pstate_regs;
846
    uint64_t *src, *dst;
847

    
848
    new_pstate = T0 & 0xf3f;
849
    pstate_regs = env->pstate & 0xc01;
850
    new_pstate_regs = new_pstate & 0xc01;
851
    if (new_pstate_regs != pstate_regs) {
852
        // Switch global register bank
853
        src = get_gregset(new_pstate_regs);
854
        dst = get_gregset(pstate_regs);
855
        memcpy32(dst, env->gregs);
856
        memcpy32(env->gregs, src);
857
    }
858
    env->pstate = new_pstate;
859
}
860

    
861
void do_done(void)
862
{
863
    env->tl--;
864
    env->pc = env->tnpc[env->tl];
865
    env->npc = env->tnpc[env->tl] + 4;
866
    PUT_CCR(env, env->tstate[env->tl] >> 32);
867
    env->asi = (env->tstate[env->tl] >> 24) & 0xff;
868
    env->pstate = (env->tstate[env->tl] >> 8) & 0xfff;
869
    set_cwp(env->tstate[env->tl] & 0xff);
870
}
871

    
872
void do_retry(void)
873
{
874
    env->tl--;
875
    env->pc = env->tpc[env->tl];
876
    env->npc = env->tnpc[env->tl];
877
    PUT_CCR(env, env->tstate[env->tl] >> 32);
878
    env->asi = (env->tstate[env->tl] >> 24) & 0xff;
879
    env->pstate = (env->tstate[env->tl] >> 8) & 0xfff;
880
    set_cwp(env->tstate[env->tl] & 0xff);
881
}
882
#endif
883

    
884
void set_cwp(int new_cwp)
885
{
886
    /* put the modified wrap registers at their proper location */
887
    if (env->cwp == (NWINDOWS - 1))
888
        memcpy32(env->regbase, env->regbase + NWINDOWS * 16);
889
    env->cwp = new_cwp;
890
    /* put the wrap registers at their temporary location */
891
    if (new_cwp == (NWINDOWS - 1))
892
        memcpy32(env->regbase + NWINDOWS * 16, env->regbase);
893
    env->regwptr = env->regbase + (new_cwp * 16);
894
    REGWPTR = env->regwptr;
895
}
896

    
897
void cpu_set_cwp(CPUState *env1, int new_cwp)
898
{
899
    CPUState *saved_env;
900
#ifdef reg_REGWPTR
901
    target_ulong *saved_regwptr;
902
#endif
903

    
904
    saved_env = env;
905
#ifdef reg_REGWPTR
906
    saved_regwptr = REGWPTR;
907
#endif
908
    env = env1;
909
    set_cwp(new_cwp);
910
    env = saved_env;
911
#ifdef reg_REGWPTR
912
    REGWPTR = saved_regwptr;
913
#endif
914
}
915

    
916
#ifdef TARGET_SPARC64
917
void do_interrupt(int intno)
918
{
919
#ifdef DEBUG_PCALL
920
    if (loglevel & CPU_LOG_INT) {
921
        static int count;
922
        fprintf(logfile, "%6d: v=%04x pc=%016llx npc=%016llx SP=%016llx\n",
923
                count, intno,
924
                env->pc,
925
                env->npc, env->regwptr[6]);
926
        cpu_dump_state(env, logfile, fprintf, 0);
927
#if 0
928
        {
929
            int i;
930
            uint8_t *ptr;
931

932
            fprintf(logfile, "       code=");
933
            ptr = (uint8_t *)env->pc;
934
            for(i = 0; i < 16; i++) {
935
                fprintf(logfile, " %02x", ldub(ptr + i));
936
            }
937
            fprintf(logfile, "\n");
938
        }
939
#endif
940
        count++;
941
    }
942
#endif
943
#if !defined(CONFIG_USER_ONLY) 
944
    if (env->tl == MAXTL) {
945
        cpu_abort(env, "Trap 0x%04x while trap level is MAXTL, Error state", env->exception_index);
946
        return;
947
    }
948
#endif
949
    env->tstate[env->tl] = ((uint64_t)GET_CCR(env) << 32) | ((env->asi & 0xff) << 24) |
950
        ((env->pstate & 0xfff) << 8) | (env->cwp & 0xff);
951
    env->tpc[env->tl] = env->pc;
952
    env->tnpc[env->tl] = env->npc;
953
    env->tt[env->tl] = intno;
954
    env->pstate = PS_PEF | PS_PRIV | PS_AG;
955
    env->tbr &= ~0x7fffULL;
956
    env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
957
    if (env->tl < MAXTL - 1) {
958
        env->tl++;
959
    } else {
960
        env->pstate |= PS_RED;
961
        if (env->tl != MAXTL)
962
            env->tl++;
963
    }
964
    env->pc = env->tbr;
965
    env->npc = env->pc + 4;
966
    env->exception_index = 0;
967
}
968
#else
969
void do_interrupt(int intno)
970
{
971
    int cwp;
972

    
973
#ifdef DEBUG_PCALL
974
    if (loglevel & CPU_LOG_INT) {
975
        static int count;
976
        fprintf(logfile, "%6d: v=%02x pc=%08x npc=%08x SP=%08x\n",
977
                count, intno,
978
                env->pc,
979
                env->npc, env->regwptr[6]);
980
        cpu_dump_state(env, logfile, fprintf, 0);
981
#if 0
982
        {
983
            int i;
984
            uint8_t *ptr;
985

986
            fprintf(logfile, "       code=");
987
            ptr = (uint8_t *)env->pc;
988
            for(i = 0; i < 16; i++) {
989
                fprintf(logfile, " %02x", ldub(ptr + i));
990
            }
991
            fprintf(logfile, "\n");
992
        }
993
#endif
994
        count++;
995
    }
996
#endif
997
#if !defined(CONFIG_USER_ONLY) 
998
    if (env->psret == 0) {
999
        cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index);
1000
        return;
1001
    }
1002
#endif
1003
    env->psret = 0;
1004
    cwp = (env->cwp - 1) & (NWINDOWS - 1); 
1005
    set_cwp(cwp);
1006
    env->regwptr[9] = env->pc;
1007
    env->regwptr[10] = env->npc;
1008
    env->psrps = env->psrs;
1009
    env->psrs = 1;
1010
    env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
1011
    env->pc = env->tbr;
1012
    env->npc = env->pc + 4;
1013
    env->exception_index = 0;
1014
}
1015
#endif
1016

    
1017
#if !defined(CONFIG_USER_ONLY) 
1018

    
1019
#define MMUSUFFIX _mmu
1020
#define GETPC() (__builtin_return_address(0))
1021

    
1022
#define SHIFT 0
1023
#include "softmmu_template.h"
1024

    
1025
#define SHIFT 1
1026
#include "softmmu_template.h"
1027

    
1028
#define SHIFT 2
1029
#include "softmmu_template.h"
1030

    
1031
#define SHIFT 3
1032
#include "softmmu_template.h"
1033

    
1034

    
1035
/* try to fill the TLB and return an exception if error. If retaddr is
1036
   NULL, it means that the function was called in C code (i.e. not
1037
   from generated code or from helper.c) */
1038
/* XXX: fix it to restore all registers */
1039
void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr)
1040
{
1041
    TranslationBlock *tb;
1042
    int ret;
1043
    unsigned long pc;
1044
    CPUState *saved_env;
1045

    
1046
    /* XXX: hack to restore env in all cases, even if not called from
1047
       generated code */
1048
    saved_env = env;
1049
    env = cpu_single_env;
1050

    
1051
    ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, is_user, 1);
1052
    if (ret) {
1053
        if (retaddr) {
1054
            /* now we have a real cpu fault */
1055
            pc = (unsigned long)retaddr;
1056
            tb = tb_find_pc(pc);
1057
            if (tb) {
1058
                /* the PC is inside the translated code. It means that we have
1059
                   a virtual CPU fault */
1060
                cpu_restore_state(tb, env, pc, (void *)T2);
1061
            }
1062
        }
1063
        cpu_loop_exit();
1064
    }
1065
    env = saved_env;
1066
}
1067

    
1068
#endif