Statistics
| Branch: | Revision:

root / target-sparc / op_helper.c @ 65ce8c2f

History | View | Annotate | Download (22.1 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 = int32_to_float32(*((int32_t *)&FT1));
16
}
17

    
18
void do_fitod(void)
19
{
20
    DT0 = int32_to_float64(*((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 GEN_FCMP(name, size, reg1, reg2, FS)                            \
47
    void glue(do_, name) (void)                                         \
48
    {                                                                   \
49
        env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                     \
50
        switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) {   \
51
        case float_relation_unordered:                                  \
52
            T0 = (FSR_FCC1 | FSR_FCC0) << FS;                           \
53
            if (env->fsr & FSR_NVM) {                                   \
54
                env->fsr |= T0;                                         \
55
                raise_exception(TT_FP_EXCP);                            \
56
            } else {                                                    \
57
                env->fsr |= FSR_NVA;                                    \
58
            }                                                           \
59
            break;                                                      \
60
        case float_relation_less:                                       \
61
            T0 = FSR_FCC0 << FS;                                        \
62
            break;                                                      \
63
        case float_relation_greater:                                    \
64
            T0 = FSR_FCC1 << FS;                                        \
65
            break;                                                      \
66
        default:                                                        \
67
            T0 = 0;                                                     \
68
            break;                                                      \
69
        }                                                               \
70
        env->fsr |= T0;                                                 \
71
    }
72

    
73
GEN_FCMP(fcmps, float32, FT0, FT1, 0);
74
GEN_FCMP(fcmpd, float64, DT0, DT1, 0);
75

    
76
#ifdef TARGET_SPARC64
77
GEN_FCMP(fcmps_fcc1, float32, FT0, FT1, 22);
78
GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22);
79

    
80
GEN_FCMP(fcmps_fcc2, float32, FT0, FT1, 24);
81
GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24);
82

    
83
GEN_FCMP(fcmps_fcc3, float32, FT0, FT1, 26);
84
GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26);
85
#endif
86

    
87
#if defined(CONFIG_USER_ONLY) 
88
void helper_ld_asi(int asi, int size, int sign)
89
{
90
}
91

    
92
void helper_st_asi(int asi, int size, int sign)
93
{
94
}
95
#else
96
#ifndef TARGET_SPARC64
97
void helper_ld_asi(int asi, int size, int sign)
98
{
99
    uint32_t ret = 0;
100

    
101
    switch (asi) {
102
    case 3: /* MMU probe */
103
        {
104
            int mmulev;
105

    
106
            mmulev = (T0 >> 8) & 15;
107
            if (mmulev > 4)
108
                ret = 0;
109
            else {
110
                ret = mmu_probe(env, T0, mmulev);
111
                //bswap32s(&ret);
112
            }
113
#ifdef DEBUG_MMU
114
            printf("mmu_probe: 0x%08x (lev %d) -> 0x%08x\n", T0, mmulev, ret);
115
#endif
116
        }
117
        break;
118
    case 4: /* read MMU regs */
119
        {
120
            int reg = (T0 >> 8) & 0xf;
121
            
122
            ret = env->mmuregs[reg];
123
            if (reg == 3) /* Fault status cleared on read */
124
                env->mmuregs[reg] = 0;
125
#ifdef DEBUG_MMU
126
            printf("mmu_read: reg[%d] = 0x%08x\n", reg, ret);
127
#endif
128
        }
129
        break;
130
    case 0x20 ... 0x2f: /* MMU passthrough */
131
        switch(size) {
132
        case 1:
133
            ret = ldub_phys(T0);
134
            break;
135
        case 2:
136
            ret = lduw_phys(T0 & ~1);
137
            break;
138
        default:
139
        case 4:
140
            ret = ldl_phys(T0 & ~3);
141
            break;
142
        case 8:
143
            ret = ldl_phys(T0 & ~3);
144
            T0 = ldl_phys((T0 + 4) & ~3);
145
            break;
146
        }
147
        break;
148
    default:
149
        ret = 0;
150
        break;
151
    }
152
    T1 = ret;
153
}
154

    
155
void helper_st_asi(int asi, int size, int sign)
156
{
157
    switch(asi) {
158
    case 3: /* MMU flush */
159
        {
160
            int mmulev;
161

    
162
            mmulev = (T0 >> 8) & 15;
163
#ifdef DEBUG_MMU
164
            printf("mmu flush level %d\n", mmulev);
165
#endif
166
            switch (mmulev) {
167
            case 0: // flush page
168
                tlb_flush_page(env, T0 & 0xfffff000);
169
                break;
170
            case 1: // flush segment (256k)
171
            case 2: // flush region (16M)
172
            case 3: // flush context (4G)
173
            case 4: // flush entire
174
                tlb_flush(env, 1);
175
                break;
176
            default:
177
                break;
178
            }
179
#ifdef DEBUG_MMU
180
            dump_mmu(env);
181
#endif
182
            return;
183
        }
184
    case 4: /* write MMU regs */
185
        {
186
            int reg = (T0 >> 8) & 0xf;
187
            uint32_t oldreg;
188
            
189
            oldreg = env->mmuregs[reg];
190
            switch(reg) {
191
            case 0:
192
                env->mmuregs[reg] &= ~(MMU_E | MMU_NF);
193
                env->mmuregs[reg] |= T1 & (MMU_E | MMU_NF);
194
                // Mappings generated during no-fault mode or MMU
195
                // disabled mode are invalid in normal mode
196
                if (oldreg != env->mmuregs[reg])
197
                    tlb_flush(env, 1);
198
                break;
199
            case 2:
200
                env->mmuregs[reg] = T1;
201
                if (oldreg != env->mmuregs[reg]) {
202
                    /* we flush when the MMU context changes because
203
                       QEMU has no MMU context support */
204
                    tlb_flush(env, 1);
205
                }
206
                break;
207
            case 3:
208
            case 4:
209
                break;
210
            default:
211
                env->mmuregs[reg] = T1;
212
                break;
213
            }
214
#ifdef DEBUG_MMU
215
            if (oldreg != env->mmuregs[reg]) {
216
                printf("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->mmuregs[reg]);
217
            }
218
            dump_mmu(env);
219
#endif
220
            return;
221
        }
222
    case 0x17: /* Block copy, sta access */
223
        {
224
            // value (T1) = src
225
            // address (T0) = dst
226
            // copy 32 bytes
227
            uint32_t src = T1, dst = T0;
228
            uint8_t temp[32];
229
            
230
            tswap32s(&src);
231

    
232
            cpu_physical_memory_read(src, (void *) &temp, 32);
233
            cpu_physical_memory_write(dst, (void *) &temp, 32);
234
        }
235
        return;
236
    case 0x1f: /* Block fill, stda access */
237
        {
238
            // value (T1, T2)
239
            // address (T0) = dst
240
            // fill 32 bytes
241
            int i;
242
            uint32_t dst = T0;
243
            uint64_t val;
244
            
245
            val = (((uint64_t)T1) << 32) | T2;
246
            tswap64s(&val);
247

    
248
            for (i = 0; i < 32; i += 8, dst += 8) {
249
                cpu_physical_memory_write(dst, (void *) &val, 8);
250
            }
251
        }
252
        return;
253
    case 0x20 ... 0x2f: /* MMU passthrough */
254
        {
255
            switch(size) {
256
            case 1:
257
                stb_phys(T0, T1);
258
                break;
259
            case 2:
260
                stw_phys(T0 & ~1, T1);
261
                break;
262
            case 4:
263
            default:
264
                stl_phys(T0 & ~3, T1);
265
                break;
266
            case 8:
267
                stl_phys(T0 & ~3, T1);
268
                stl_phys((T0 + 4) & ~3, T2);
269
                break;
270
            }
271
        }
272
        return;
273
    default:
274
        return;
275
    }
276
}
277

    
278
#else
279

    
280
void helper_ld_asi(int asi, int size, int sign)
281
{
282
    uint64_t ret = 0;
283

    
284
    if (asi < 0x80 && (env->pstate & PS_PRIV) == 0)
285
        raise_exception(TT_PRIV_ACT);
286

    
287
    switch (asi) {
288
    case 0x14: // Bypass
289
    case 0x15: // Bypass, non-cacheable
290
        {
291
            switch(size) {
292
            case 1:
293
                ret = ldub_phys(T0);
294
                break;
295
            case 2:
296
                ret = lduw_phys(T0 & ~1);
297
                break;
298
            case 4:
299
                ret = ldl_phys(T0 & ~3);
300
                break;
301
            default:
302
            case 8:
303
                ret = ldq_phys(T0 & ~7);
304
                break;
305
            }
306
            break;
307
        }
308
    case 0x04: // Nucleus
309
    case 0x0c: // Nucleus Little Endian (LE)
310
    case 0x10: // As if user primary
311
    case 0x11: // As if user secondary
312
    case 0x18: // As if user primary LE
313
    case 0x19: // As if user secondary LE
314
    case 0x1c: // Bypass LE
315
    case 0x1d: // Bypass, non-cacheable LE
316
    case 0x24: // Nucleus quad LDD 128 bit atomic
317
    case 0x2c: // Nucleus quad LDD 128 bit atomic
318
    case 0x4a: // UPA config
319
    case 0x82: // Primary no-fault
320
    case 0x83: // Secondary no-fault
321
    case 0x88: // Primary LE
322
    case 0x89: // Secondary LE
323
    case 0x8a: // Primary no-fault LE
324
    case 0x8b: // Secondary no-fault LE
325
        // XXX
326
        break;
327
    case 0x45: // LSU
328
        ret = env->lsu;
329
        break;
330
    case 0x50: // I-MMU regs
331
        {
332
            int reg = (T0 >> 3) & 0xf;
333

    
334
            ret = env->immuregs[reg];
335
            break;
336
        }
337
    case 0x51: // I-MMU 8k TSB pointer
338
    case 0x52: // I-MMU 64k TSB pointer
339
    case 0x55: // I-MMU data access
340
        // XXX
341
        break;
342
    case 0x56: // I-MMU tag read
343
        {
344
            unsigned int i;
345
            
346
            for (i = 0; i < 64; i++) {
347
                // Valid, ctx match, vaddr match
348
                if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0 &&
349
                    env->itlb_tag[i] == T0) {
350
                    ret = env->itlb_tag[i];
351
                    break;
352
                }
353
            }
354
            break;
355
        }
356
    case 0x58: // D-MMU regs
357
        {
358
            int reg = (T0 >> 3) & 0xf;
359

    
360
            ret = env->dmmuregs[reg];
361
            break;
362
        }
363
    case 0x5e: // D-MMU tag read
364
        {
365
            unsigned int i;
366
            
367
            for (i = 0; i < 64; i++) {
368
                // Valid, ctx match, vaddr match
369
                if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0 &&
370
                    env->dtlb_tag[i] == T0) {
371
                    ret = env->dtlb_tag[i];
372
                    break;
373
                }
374
            }
375
            break;
376
        }
377
    case 0x59: // D-MMU 8k TSB pointer
378
    case 0x5a: // D-MMU 64k TSB pointer
379
    case 0x5b: // D-MMU data pointer
380
    case 0x5d: // D-MMU data access
381
    case 0x48: // Interrupt dispatch, RO
382
    case 0x49: // Interrupt data receive
383
    case 0x7f: // Incoming interrupt vector, RO
384
        // XXX
385
        break;
386
    case 0x54: // I-MMU data in, WO
387
    case 0x57: // I-MMU demap, WO
388
    case 0x5c: // D-MMU data in, WO
389
    case 0x5f: // D-MMU demap, WO
390
    case 0x77: // Interrupt vector, WO
391
    default:
392
        ret = 0;
393
        break;
394
    }
395
    T1 = ret;
396
}
397

    
398
void helper_st_asi(int asi, int size, int sign)
399
{
400
    if (asi < 0x80 && (env->pstate & PS_PRIV) == 0)
401
        raise_exception(TT_PRIV_ACT);
402

    
403
    switch(asi) {
404
    case 0x14: // Bypass
405
    case 0x15: // Bypass, non-cacheable
406
        {
407
            switch(size) {
408
            case 1:
409
                stb_phys(T0, T1);
410
                break;
411
            case 2:
412
                stw_phys(T0 & ~1, T1);
413
                break;
414
            case 4:
415
                stl_phys(T0 & ~3, T1);
416
                break;
417
            case 8:
418
            default:
419
                stq_phys(T0 & ~7, T1);
420
                break;
421
            }
422
        }
423
        return;
424
    case 0x04: // Nucleus
425
    case 0x0c: // Nucleus Little Endian (LE)
426
    case 0x10: // As if user primary
427
    case 0x11: // As if user secondary
428
    case 0x18: // As if user primary LE
429
    case 0x19: // As if user secondary LE
430
    case 0x1c: // Bypass LE
431
    case 0x1d: // Bypass, non-cacheable LE
432
    case 0x24: // Nucleus quad LDD 128 bit atomic
433
    case 0x2c: // Nucleus quad LDD 128 bit atomic
434
    case 0x4a: // UPA config
435
    case 0x88: // Primary LE
436
    case 0x89: // Secondary LE
437
        // XXX
438
        return;
439
    case 0x45: // LSU
440
        {
441
            uint64_t oldreg;
442

    
443
            oldreg = env->lsu;
444
            env->lsu = T1 & (DMMU_E | IMMU_E);
445
            // Mappings generated during D/I MMU disabled mode are
446
            // invalid in normal mode
447
            if (oldreg != env->lsu) {
448
#ifdef DEBUG_MMU
449
                printf("LSU change: 0x%llx -> 0x%llx\n", oldreg, env->lsu);
450
                dump_mmu(env);
451
#endif
452
                tlb_flush(env, 1);
453
            }
454
            return;
455
        }
456
    case 0x50: // I-MMU regs
457
        {
458
            int reg = (T0 >> 3) & 0xf;
459
            uint64_t oldreg;
460
            
461
            oldreg = env->immuregs[reg];
462
            switch(reg) {
463
            case 0: // RO
464
            case 4:
465
                return;
466
            case 1: // Not in I-MMU
467
            case 2:
468
            case 7:
469
            case 8:
470
                return;
471
            case 3: // SFSR
472
                if ((T1 & 1) == 0)
473
                    T1 = 0; // Clear SFSR
474
                break;
475
            case 5: // TSB access
476
            case 6: // Tag access
477
            default:
478
                break;
479
            }
480
            env->immuregs[reg] = T1;
481
#ifdef DEBUG_MMU
482
            if (oldreg != env->immuregs[reg]) {
483
                printf("mmu change reg[%d]: 0x%08llx -> 0x%08llx\n", reg, oldreg, env->immuregs[reg]);
484
            }
485
            dump_mmu(env);
486
#endif
487
            return;
488
        }
489
    case 0x54: // I-MMU data in
490
        {
491
            unsigned int i;
492

    
493
            // Try finding an invalid entry
494
            for (i = 0; i < 64; i++) {
495
                if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) {
496
                    env->itlb_tag[i] = env->immuregs[6];
497
                    env->itlb_tte[i] = T1;
498
                    return;
499
                }
500
            }
501
            // Try finding an unlocked entry
502
            for (i = 0; i < 64; i++) {
503
                if ((env->itlb_tte[i] & 0x40) == 0) {
504
                    env->itlb_tag[i] = env->immuregs[6];
505
                    env->itlb_tte[i] = T1;
506
                    return;
507
                }
508
            }
509
            // error state?
510
            return;
511
        }
512
    case 0x55: // I-MMU data access
513
        {
514
            unsigned int i = (T0 >> 3) & 0x3f;
515

    
516
            env->itlb_tag[i] = env->immuregs[6];
517
            env->itlb_tte[i] = T1;
518
            return;
519
        }
520
    case 0x57: // I-MMU demap
521
        // XXX
522
        return;
523
    case 0x58: // D-MMU regs
524
        {
525
            int reg = (T0 >> 3) & 0xf;
526
            uint64_t oldreg;
527
            
528
            oldreg = env->dmmuregs[reg];
529
            switch(reg) {
530
            case 0: // RO
531
            case 4:
532
                return;
533
            case 3: // SFSR
534
                if ((T1 & 1) == 0) {
535
                    T1 = 0; // Clear SFSR, Fault address
536
                    env->dmmuregs[4] = 0;
537
                }
538
                env->dmmuregs[reg] = T1;
539
                break;
540
            case 1: // Primary context
541
            case 2: // Secondary context
542
            case 5: // TSB access
543
            case 6: // Tag access
544
            case 7: // Virtual Watchpoint
545
            case 8: // Physical Watchpoint
546
            default:
547
                break;
548
            }
549
            env->dmmuregs[reg] = T1;
550
#ifdef DEBUG_MMU
551
            if (oldreg != env->dmmuregs[reg]) {
552
                printf("mmu change reg[%d]: 0x%08llx -> 0x%08llx\n", reg, oldreg, env->dmmuregs[reg]);
553
            }
554
            dump_mmu(env);
555
#endif
556
            return;
557
        }
558
    case 0x5c: // D-MMU data in
559
        {
560
            unsigned int i;
561

    
562
            // Try finding an invalid entry
563
            for (i = 0; i < 64; i++) {
564
                if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) {
565
                    env->dtlb_tag[i] = env->dmmuregs[6];
566
                    env->dtlb_tte[i] = T1;
567
                    return;
568
                }
569
            }
570
            // Try finding an unlocked entry
571
            for (i = 0; i < 64; i++) {
572
                if ((env->dtlb_tte[i] & 0x40) == 0) {
573
                    env->dtlb_tag[i] = env->dmmuregs[6];
574
                    env->dtlb_tte[i] = T1;
575
                    return;
576
                }
577
            }
578
            // error state?
579
            return;
580
        }
581
    case 0x5d: // D-MMU data access
582
        {
583
            unsigned int i = (T0 >> 3) & 0x3f;
584

    
585
            env->dtlb_tag[i] = env->dmmuregs[6];
586
            env->dtlb_tte[i] = T1;
587
            return;
588
        }
589
    case 0x5f: // D-MMU demap
590
    case 0x49: // Interrupt data receive
591
        // XXX
592
        return;
593
    case 0x51: // I-MMU 8k TSB pointer, RO
594
    case 0x52: // I-MMU 64k TSB pointer, RO
595
    case 0x56: // I-MMU tag read, RO
596
    case 0x59: // D-MMU 8k TSB pointer, RO
597
    case 0x5a: // D-MMU 64k TSB pointer, RO
598
    case 0x5b: // D-MMU data pointer, RO
599
    case 0x5e: // D-MMU tag read, RO
600
    case 0x48: // Interrupt dispatch, RO
601
    case 0x7f: // Incoming interrupt vector, RO
602
    case 0x82: // Primary no-fault, RO
603
    case 0x83: // Secondary no-fault, RO
604
    case 0x8a: // Primary no-fault LE, RO
605
    case 0x8b: // Secondary no-fault LE, RO
606
    default:
607
        return;
608
    }
609
}
610
#endif
611
#endif /* !CONFIG_USER_ONLY */
612

    
613
#ifndef TARGET_SPARC64
614
void helper_rett()
615
{
616
    unsigned int cwp;
617

    
618
    env->psret = 1;
619
    cwp = (env->cwp + 1) & (NWINDOWS - 1); 
620
    if (env->wim & (1 << cwp)) {
621
        raise_exception(TT_WIN_UNF);
622
    }
623
    set_cwp(cwp);
624
    env->psrs = env->psrps;
625
}
626
#endif
627

    
628
void helper_ldfsr(void)
629
{
630
    int rnd_mode;
631
    switch (env->fsr & FSR_RD_MASK) {
632
    case FSR_RD_NEAREST:
633
        rnd_mode = float_round_nearest_even;
634
        break;
635
    default:
636
    case FSR_RD_ZERO:
637
        rnd_mode = float_round_to_zero;
638
        break;
639
    case FSR_RD_POS:
640
        rnd_mode = float_round_up;
641
        break;
642
    case FSR_RD_NEG:
643
        rnd_mode = float_round_down;
644
        break;
645
    }
646
    set_float_rounding_mode(rnd_mode, &env->fp_status);
647
}
648

    
649
void helper_debug()
650
{
651
    env->exception_index = EXCP_DEBUG;
652
    cpu_loop_exit();
653
}
654

    
655
#ifndef TARGET_SPARC64
656
void do_wrpsr()
657
{
658
    PUT_PSR(env, T0);
659
}
660

    
661
void do_rdpsr()
662
{
663
    T0 = GET_PSR(env);
664
}
665

    
666
#else
667

    
668
void do_popc()
669
{
670
    T0 = (T1 & 0x5555555555555555ULL) + ((T1 >> 1) & 0x5555555555555555ULL);
671
    T0 = (T0 & 0x3333333333333333ULL) + ((T0 >> 2) & 0x3333333333333333ULL);
672
    T0 = (T0 & 0x0f0f0f0f0f0f0f0fULL) + ((T0 >> 4) & 0x0f0f0f0f0f0f0f0fULL);
673
    T0 = (T0 & 0x00ff00ff00ff00ffULL) + ((T0 >> 8) & 0x00ff00ff00ff00ffULL);
674
    T0 = (T0 & 0x0000ffff0000ffffULL) + ((T0 >> 16) & 0x0000ffff0000ffffULL);
675
    T0 = (T0 & 0x00000000ffffffffULL) + ((T0 >> 32) & 0x00000000ffffffffULL);
676
}
677

    
678
static inline uint64_t *get_gregset(uint64_t pstate)
679
{
680
    switch (pstate) {
681
    default:
682
    case 0:
683
        return env->bgregs;
684
    case PS_AG:
685
        return env->agregs;
686
    case PS_MG:
687
        return env->mgregs;
688
    case PS_IG:
689
        return env->igregs;
690
    }
691
}
692

    
693
void do_wrpstate()
694
{
695
    uint64_t new_pstate, pstate_regs, new_pstate_regs;
696
    uint64_t *src, *dst;
697

    
698
    new_pstate = T0 & 0xf3f;
699
    pstate_regs = env->pstate & 0xc01;
700
    new_pstate_regs = new_pstate & 0xc01;
701
    if (new_pstate_regs != pstate_regs) {
702
        // Switch global register bank
703
        src = get_gregset(new_pstate_regs);
704
        dst = get_gregset(pstate_regs);
705
        memcpy32(dst, env->gregs);
706
        memcpy32(env->gregs, src);
707
    }
708
    env->pstate = new_pstate;
709
}
710

    
711
void do_done(void)
712
{
713
    env->tl--;
714
    env->pc = env->tnpc[env->tl];
715
    env->npc = env->tnpc[env->tl] + 4;
716
    PUT_CCR(env, env->tstate[env->tl] >> 32);
717
    env->asi = (env->tstate[env->tl] >> 24) & 0xff;
718
    env->pstate = (env->tstate[env->tl] >> 8) & 0xfff;
719
    set_cwp(env->tstate[env->tl] & 0xff);
720
}
721

    
722
void do_retry(void)
723
{
724
    env->tl--;
725
    env->pc = env->tpc[env->tl];
726
    env->npc = env->tnpc[env->tl];
727
    PUT_CCR(env, env->tstate[env->tl] >> 32);
728
    env->asi = (env->tstate[env->tl] >> 24) & 0xff;
729
    env->pstate = (env->tstate[env->tl] >> 8) & 0xfff;
730
    set_cwp(env->tstate[env->tl] & 0xff);
731
}
732
#endif
733

    
734
void set_cwp(int new_cwp)
735
{
736
    /* put the modified wrap registers at their proper location */
737
    if (env->cwp == (NWINDOWS - 1))
738
        memcpy32(env->regbase, env->regbase + NWINDOWS * 16);
739
    env->cwp = new_cwp;
740
    /* put the wrap registers at their temporary location */
741
    if (new_cwp == (NWINDOWS - 1))
742
        memcpy32(env->regbase + NWINDOWS * 16, env->regbase);
743
    env->regwptr = env->regbase + (new_cwp * 16);
744
    REGWPTR = env->regwptr;
745
}
746

    
747
void cpu_set_cwp(CPUState *env1, int new_cwp)
748
{
749
    CPUState *saved_env;
750
#ifdef reg_REGWPTR
751
    target_ulong *saved_regwptr;
752
#endif
753

    
754
    saved_env = env;
755
#ifdef reg_REGWPTR
756
    saved_regwptr = REGWPTR;
757
#endif
758
    env = env1;
759
    set_cwp(new_cwp);
760
    env = saved_env;
761
#ifdef reg_REGWPTR
762
    REGWPTR = saved_regwptr;
763
#endif
764
}
765

    
766
#ifdef TARGET_SPARC64
767
void do_interrupt(int intno)
768
{
769
#ifdef DEBUG_PCALL
770
    if (loglevel & CPU_LOG_INT) {
771
        static int count;
772
        fprintf(logfile, "%6d: v=%04x pc=%016llx npc=%016llx SP=%016llx\n",
773
                count, intno,
774
                env->pc,
775
                env->npc, env->regwptr[6]);
776
        cpu_dump_state(env, logfile, fprintf, 0);
777
#if 0
778
        {
779
            int i;
780
            uint8_t *ptr;
781

782
            fprintf(logfile, "       code=");
783
            ptr = (uint8_t *)env->pc;
784
            for(i = 0; i < 16; i++) {
785
                fprintf(logfile, " %02x", ldub(ptr + i));
786
            }
787
            fprintf(logfile, "\n");
788
        }
789
#endif
790
        count++;
791
    }
792
#endif
793
#if !defined(CONFIG_USER_ONLY) 
794
    if (env->tl == MAXTL) {
795
        cpu_abort(env, "Trap 0x%04x while trap level is MAXTL, Error state", env->exception_index);
796
        return;
797
    }
798
#endif
799
    env->tstate[env->tl] = ((uint64_t)GET_CCR(env) << 32) | ((env->asi & 0xff) << 24) |
800
        ((env->pstate & 0xfff) << 8) | (env->cwp & 0xff);
801
    env->tpc[env->tl] = env->pc;
802
    env->tnpc[env->tl] = env->npc;
803
    env->tt[env->tl] = intno;
804
    env->pstate = PS_PEF | PS_PRIV | PS_AG;
805
    env->tbr &= ~0x7fffULL;
806
    env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
807
    if (env->tl < MAXTL - 1) {
808
        env->tl++;
809
    } else {
810
        env->pstate |= PS_RED;
811
        if (env->tl != MAXTL)
812
            env->tl++;
813
    }
814
    env->pc = env->tbr;
815
    env->npc = env->pc + 4;
816
    env->exception_index = 0;
817
}
818
#else
819
void do_interrupt(int intno)
820
{
821
    int cwp;
822

    
823
#ifdef DEBUG_PCALL
824
    if (loglevel & CPU_LOG_INT) {
825
        static int count;
826
        fprintf(logfile, "%6d: v=%02x pc=%08x npc=%08x SP=%08x\n",
827
                count, intno,
828
                env->pc,
829
                env->npc, env->regwptr[6]);
830
        cpu_dump_state(env, logfile, fprintf, 0);
831
#if 0
832
        {
833
            int i;
834
            uint8_t *ptr;
835

836
            fprintf(logfile, "       code=");
837
            ptr = (uint8_t *)env->pc;
838
            for(i = 0; i < 16; i++) {
839
                fprintf(logfile, " %02x", ldub(ptr + i));
840
            }
841
            fprintf(logfile, "\n");
842
        }
843
#endif
844
        count++;
845
    }
846
#endif
847
#if !defined(CONFIG_USER_ONLY) 
848
    if (env->psret == 0) {
849
        cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index);
850
        return;
851
    }
852
#endif
853
    env->psret = 0;
854
    cwp = (env->cwp - 1) & (NWINDOWS - 1); 
855
    set_cwp(cwp);
856
    env->regwptr[9] = env->pc;
857
    env->regwptr[10] = env->npc;
858
    env->psrps = env->psrs;
859
    env->psrs = 1;
860
    env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
861
    env->pc = env->tbr;
862
    env->npc = env->pc + 4;
863
    env->exception_index = 0;
864
}
865
#endif
866

    
867
#if !defined(CONFIG_USER_ONLY) 
868

    
869
#define MMUSUFFIX _mmu
870
#define GETPC() (__builtin_return_address(0))
871

    
872
#define SHIFT 0
873
#include "softmmu_template.h"
874

    
875
#define SHIFT 1
876
#include "softmmu_template.h"
877

    
878
#define SHIFT 2
879
#include "softmmu_template.h"
880

    
881
#define SHIFT 3
882
#include "softmmu_template.h"
883

    
884

    
885
/* try to fill the TLB and return an exception if error. If retaddr is
886
   NULL, it means that the function was called in C code (i.e. not
887
   from generated code or from helper.c) */
888
/* XXX: fix it to restore all registers */
889
void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr)
890
{
891
    TranslationBlock *tb;
892
    int ret;
893
    unsigned long pc;
894
    CPUState *saved_env;
895

    
896
    /* XXX: hack to restore env in all cases, even if not called from
897
       generated code */
898
    saved_env = env;
899
    env = cpu_single_env;
900

    
901
    ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, is_user, 1);
902
    if (ret) {
903
        if (retaddr) {
904
            /* now we have a real cpu fault */
905
            pc = (unsigned long)retaddr;
906
            tb = tb_find_pc(pc);
907
            if (tb) {
908
                /* the PC is inside the translated code. It means that we have
909
                   a virtual CPU fault */
910
                cpu_restore_state(tb, env, pc, (void *)T2);
911
            }
912
        }
913
        cpu_loop_exit();
914
    }
915
    env = saved_env;
916
}
917

    
918
#endif