Statistics
| Branch: | Revision:

root / target-sparc / op_helper.c @ 24741ef3

History | View | Annotate | Download (23.5 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
        }
280
        break;
281
    default:
282
        ret = 0;
283
        break;
284
    }
285
    T1 = ret;
286
}
287

    
288
void helper_st_asi(int asi, int size, int sign)
289
{
290
    switch(asi) {
291
    case 3: /* MMU flush */
292
        {
293
            int mmulev;
294

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

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

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

    
407
#else
408

    
409
void helper_ld_asi(int asi, int size, int sign)
410
{
411
    uint64_t ret = 0;
412

    
413
    if (asi < 0x80 && (env->pstate & PS_PRIV) == 0)
414
        raise_exception(TT_PRIV_ACT);
415

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

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

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

    
527
void helper_st_asi(int asi, int size, int sign)
528
{
529
    if (asi < 0x80 && (env->pstate & PS_PRIV) == 0)
530
        raise_exception(TT_PRIV_ACT);
531

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

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

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

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

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

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

    
742
#ifndef TARGET_SPARC64
743
void helper_rett()
744
{
745
    unsigned int cwp;
746

    
747
    env->psret = 1;
748
    cwp = (env->cwp + 1) & (NWINDOWS - 1); 
749
    if (env->wim & (1 << cwp)) {
750
        raise_exception(TT_WIN_UNF);
751
    }
752
    set_cwp(cwp);
753
    env->psrs = env->psrps;
754
}
755
#endif
756

    
757
void helper_ldfsr(void)
758
{
759
    int rnd_mode;
760
    switch (env->fsr & FSR_RD_MASK) {
761
    case FSR_RD_NEAREST:
762
        rnd_mode = float_round_nearest_even;
763
        break;
764
    default:
765
    case FSR_RD_ZERO:
766
        rnd_mode = float_round_to_zero;
767
        break;
768
    case FSR_RD_POS:
769
        rnd_mode = float_round_up;
770
        break;
771
    case FSR_RD_NEG:
772
        rnd_mode = float_round_down;
773
        break;
774
    }
775
    set_float_rounding_mode(rnd_mode, &env->fp_status);
776
}
777

    
778
void cpu_get_fp64(uint64_t *pmant, uint16_t *pexp, double f)
779
{
780
    int exptemp;
781

    
782
    *pmant = ldexp(frexp(f, &exptemp), 53);
783
    *pexp = exptemp;
784
}
785

    
786
double cpu_put_fp64(uint64_t mant, uint16_t exp)
787
{
788
    return ldexp((double) mant, exp - 53);
789
}
790

    
791
void helper_debug()
792
{
793
    env->exception_index = EXCP_DEBUG;
794
    cpu_loop_exit();
795
}
796

    
797
#ifndef TARGET_SPARC64
798
void do_wrpsr()
799
{
800
    PUT_PSR(env, T0);
801
}
802

    
803
void do_rdpsr()
804
{
805
    T0 = GET_PSR(env);
806
}
807

    
808
#else
809

    
810
void do_popc()
811
{
812
    T0 = (T1 & 0x5555555555555555ULL) + ((T1 >> 1) & 0x5555555555555555ULL);
813
    T0 = (T0 & 0x3333333333333333ULL) + ((T0 >> 2) & 0x3333333333333333ULL);
814
    T0 = (T0 & 0x0f0f0f0f0f0f0f0fULL) + ((T0 >> 4) & 0x0f0f0f0f0f0f0f0fULL);
815
    T0 = (T0 & 0x00ff00ff00ff00ffULL) + ((T0 >> 8) & 0x00ff00ff00ff00ffULL);
816
    T0 = (T0 & 0x0000ffff0000ffffULL) + ((T0 >> 16) & 0x0000ffff0000ffffULL);
817
    T0 = (T0 & 0x00000000ffffffffULL) + ((T0 >> 32) & 0x00000000ffffffffULL);
818
}
819

    
820
static inline uint64_t *get_gregset(uint64_t pstate)
821
{
822
    switch (pstate) {
823
    default:
824
    case 0:
825
        return env->bgregs;
826
    case PS_AG:
827
        return env->agregs;
828
    case PS_MG:
829
        return env->mgregs;
830
    case PS_IG:
831
        return env->igregs;
832
    }
833
}
834

    
835
void do_wrpstate()
836
{
837
    uint64_t new_pstate, pstate_regs, new_pstate_regs;
838
    uint64_t *src, *dst;
839

    
840
    new_pstate = T0 & 0xf3f;
841
    pstate_regs = env->pstate & 0xc01;
842
    new_pstate_regs = new_pstate & 0xc01;
843
    if (new_pstate_regs != pstate_regs) {
844
        // Switch global register bank
845
        src = get_gregset(new_pstate_regs);
846
        dst = get_gregset(pstate_regs);
847
        memcpy32(dst, env->gregs);
848
        memcpy32(env->gregs, src);
849
    }
850
    env->pstate = new_pstate;
851
}
852

    
853
void do_done(void)
854
{
855
    env->tl--;
856
    env->pc = env->tnpc[env->tl];
857
    env->npc = env->tnpc[env->tl] + 4;
858
    PUT_CCR(env, env->tstate[env->tl] >> 32);
859
    env->asi = (env->tstate[env->tl] >> 24) & 0xff;
860
    env->pstate = (env->tstate[env->tl] >> 8) & 0xfff;
861
    set_cwp(env->tstate[env->tl] & 0xff);
862
}
863

    
864
void do_retry(void)
865
{
866
    env->tl--;
867
    env->pc = env->tpc[env->tl];
868
    env->npc = env->tnpc[env->tl];
869
    PUT_CCR(env, env->tstate[env->tl] >> 32);
870
    env->asi = (env->tstate[env->tl] >> 24) & 0xff;
871
    env->pstate = (env->tstate[env->tl] >> 8) & 0xfff;
872
    set_cwp(env->tstate[env->tl] & 0xff);
873
}
874
#endif
875

    
876
void set_cwp(int new_cwp)
877
{
878
    /* put the modified wrap registers at their proper location */
879
    if (env->cwp == (NWINDOWS - 1))
880
        memcpy32(env->regbase, env->regbase + NWINDOWS * 16);
881
    env->cwp = new_cwp;
882
    /* put the wrap registers at their temporary location */
883
    if (new_cwp == (NWINDOWS - 1))
884
        memcpy32(env->regbase + NWINDOWS * 16, env->regbase);
885
    env->regwptr = env->regbase + (new_cwp * 16);
886
    REGWPTR = env->regwptr;
887
}
888

    
889
void cpu_set_cwp(CPUState *env1, int new_cwp)
890
{
891
    CPUState *saved_env;
892
#ifdef reg_REGWPTR
893
    target_ulong *saved_regwptr;
894
#endif
895

    
896
    saved_env = env;
897
#ifdef reg_REGWPTR
898
    saved_regwptr = REGWPTR;
899
#endif
900
    env = env1;
901
    set_cwp(new_cwp);
902
    env = saved_env;
903
#ifdef reg_REGWPTR
904
    REGWPTR = saved_regwptr;
905
#endif
906
}
907

    
908
#ifdef TARGET_SPARC64
909
void do_interrupt(int intno)
910
{
911
#ifdef DEBUG_PCALL
912
    if (loglevel & CPU_LOG_INT) {
913
        static int count;
914
        fprintf(logfile, "%6d: v=%04x pc=%016llx npc=%016llx SP=%016llx\n",
915
                count, intno,
916
                env->pc,
917
                env->npc, env->regwptr[6]);
918
        cpu_dump_state(env, logfile, fprintf, 0);
919
#if 0
920
        {
921
            int i;
922
            uint8_t *ptr;
923

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

    
965
#ifdef DEBUG_PCALL
966
    if (loglevel & CPU_LOG_INT) {
967
        static int count;
968
        fprintf(logfile, "%6d: v=%02x pc=%08x npc=%08x SP=%08x\n",
969
                count, intno,
970
                env->pc,
971
                env->npc, env->regwptr[6]);
972
        cpu_dump_state(env, logfile, fprintf, 0);
973
#if 0
974
        {
975
            int i;
976
            uint8_t *ptr;
977

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

    
1009
#if !defined(CONFIG_USER_ONLY) 
1010

    
1011
#define MMUSUFFIX _mmu
1012
#define GETPC() (__builtin_return_address(0))
1013

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

    
1017
#define SHIFT 1
1018
#include "softmmu_template.h"
1019

    
1020
#define SHIFT 2
1021
#include "softmmu_template.h"
1022

    
1023
#define SHIFT 3
1024
#include "softmmu_template.h"
1025

    
1026

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

    
1038
    /* XXX: hack to restore env in all cases, even if not called from
1039
       generated code */
1040
    saved_env = env;
1041
    env = cpu_single_env;
1042

    
1043
    ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, is_user, 1);
1044
    if (ret) {
1045
        if (retaddr) {
1046
            /* now we have a real cpu fault */
1047
            pc = (unsigned long)retaddr;
1048
            tb = tb_find_pc(pc);
1049
            if (tb) {
1050
                /* the PC is inside the translated code. It means that we have
1051
                   a virtual CPU fault */
1052
                cpu_restore_state(tb, env, pc, (void *)T2);
1053
            }
1054
        }
1055
        cpu_loop_exit();
1056
    }
1057
    env = saved_env;
1058
}
1059

    
1060
#endif