Statistics
| Branch: | Revision:

root / target-sparc / op_helper.c @ 417454b0

History | View | Annotate | Download (23.8 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
void check_ieee_exceptions()
13
{
14
     T0 = get_float_exception_flags(&env->fp_status);
15
     if (T0)
16
     {
17
        /* Copy IEEE 754 flags into FSR */
18
        if (T0 & float_flag_invalid)
19
            env->fsr |= FSR_NVC;
20
        if (T0 & float_flag_overflow)
21
            env->fsr |= FSR_OFC;
22
        if (T0 & float_flag_underflow)
23
            env->fsr |= FSR_UFC;
24
        if (T0 & float_flag_divbyzero)
25
            env->fsr |= FSR_DZC;
26
        if (T0 & float_flag_inexact)
27
            env->fsr |= FSR_NXC;
28

    
29
        if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23))
30
        {
31
            /* Unmasked exception, generate a trap */
32
            env->fsr |= FSR_FTT_IEEE_EXCP;
33
            raise_exception(TT_FP_EXCP);
34
        }
35
        else
36
        {
37
            /* Accumulate exceptions */
38
            env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
39
        }
40
     }
41
}
42

    
43
#ifdef USE_INT_TO_FLOAT_HELPERS
44
void do_fitos(void)
45
{
46
    set_float_exception_flags(0, &env->fp_status);
47
    FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status);
48
    check_ieee_exceptions();
49
}
50

    
51
void do_fitod(void)
52
{
53
    DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status);
54
}
55
#endif
56

    
57
void do_fabss(void)
58
{
59
    FT0 = float32_abs(FT1);
60
}
61

    
62
#ifdef TARGET_SPARC64
63
void do_fabsd(void)
64
{
65
    DT0 = float64_abs(DT1);
66
}
67
#endif
68

    
69
void do_fsqrts(void)
70
{
71
    set_float_exception_flags(0, &env->fp_status);
72
    FT0 = float32_sqrt(FT1, &env->fp_status);
73
    check_ieee_exceptions();
74
}
75

    
76
void do_fsqrtd(void)
77
{
78
    set_float_exception_flags(0, &env->fp_status);
79
    DT0 = float64_sqrt(DT1, &env->fp_status);
80
    check_ieee_exceptions();
81
}
82

    
83
#define GEN_FCMP(name, size, reg1, reg2, FS, TRAP)                      \
84
    void glue(do_, name) (void)                                         \
85
    {                                                                   \
86
        env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                     \
87
        switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) {   \
88
        case float_relation_unordered:                                  \
89
            T0 = (FSR_FCC1 | FSR_FCC0) << FS;                           \
90
            if ((env->fsr & FSR_NVM) || TRAP) {                         \
91
                env->fsr |= T0;                                         \
92
                env->fsr |= FSR_NVC;                                    \
93
                env->fsr |= FSR_FTT_IEEE_EXCP;                          \
94
                raise_exception(TT_FP_EXCP);                            \
95
            } else {                                                    \
96
                env->fsr |= FSR_NVA;                                    \
97
            }                                                           \
98
            break;                                                      \
99
        case float_relation_less:                                       \
100
            T0 = FSR_FCC0 << FS;                                        \
101
            break;                                                      \
102
        case float_relation_greater:                                    \
103
            T0 = FSR_FCC1 << FS;                                        \
104
            break;                                                      \
105
        default:                                                        \
106
            T0 = 0;                                                     \
107
            break;                                                      \
108
        }                                                               \
109
        env->fsr |= T0;                                                 \
110
    }
111

    
112
GEN_FCMP(fcmps, float32, FT0, FT1, 0, 0);
113
GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
114

    
115
GEN_FCMP(fcmpes, float32, FT0, FT1, 0, 1);
116
GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
117

    
118
#ifdef TARGET_SPARC64
119
GEN_FCMP(fcmps_fcc1, float32, FT0, FT1, 22, 0);
120
GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
121

    
122
GEN_FCMP(fcmps_fcc2, float32, FT0, FT1, 24, 0);
123
GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
124

    
125
GEN_FCMP(fcmps_fcc3, float32, FT0, FT1, 26, 0);
126
GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
127

    
128
GEN_FCMP(fcmpes_fcc1, float32, FT0, FT1, 22, 1);
129
GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
130

    
131
GEN_FCMP(fcmpes_fcc2, float32, FT0, FT1, 24, 1);
132
GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
133

    
134
GEN_FCMP(fcmpes_fcc3, float32, FT0, FT1, 26, 1);
135
GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
136
#endif
137

    
138
#if defined(CONFIG_USER_ONLY) 
139
void helper_ld_asi(int asi, int size, int sign)
140
{
141
}
142

    
143
void helper_st_asi(int asi, int size, int sign)
144
{
145
}
146
#else
147
#ifndef TARGET_SPARC64
148
void helper_ld_asi(int asi, int size, int sign)
149
{
150
    uint32_t ret = 0;
151

    
152
    switch (asi) {
153
    case 3: /* MMU probe */
154
        {
155
            int mmulev;
156

    
157
            mmulev = (T0 >> 8) & 15;
158
            if (mmulev > 4)
159
                ret = 0;
160
            else {
161
                ret = mmu_probe(env, T0, mmulev);
162
                //bswap32s(&ret);
163
            }
164
#ifdef DEBUG_MMU
165
            printf("mmu_probe: 0x%08x (lev %d) -> 0x%08x\n", T0, mmulev, ret);
166
#endif
167
        }
168
        break;
169
    case 4: /* read MMU regs */
170
        {
171
            int reg = (T0 >> 8) & 0xf;
172
            
173
            ret = env->mmuregs[reg];
174
            if (reg == 3) /* Fault status cleared on read */
175
                env->mmuregs[reg] = 0;
176
#ifdef DEBUG_MMU
177
            printf("mmu_read: reg[%d] = 0x%08x\n", reg, ret);
178
#endif
179
        }
180
        break;
181
    case 0x20 ... 0x2f: /* MMU passthrough */
182
        switch(size) {
183
        case 1:
184
            ret = ldub_phys(T0);
185
            break;
186
        case 2:
187
            ret = lduw_phys(T0 & ~1);
188
            break;
189
        default:
190
        case 4:
191
            ret = ldl_phys(T0 & ~3);
192
            break;
193
        case 8:
194
            ret = ldl_phys(T0 & ~3);
195
            T0 = ldl_phys((T0 + 4) & ~3);
196
            break;
197
        }
198
        break;
199
    default:
200
        ret = 0;
201
        break;
202
    }
203
    T1 = ret;
204
}
205

    
206
void helper_st_asi(int asi, int size, int sign)
207
{
208
    switch(asi) {
209
    case 3: /* MMU flush */
210
        {
211
            int mmulev;
212

    
213
            mmulev = (T0 >> 8) & 15;
214
#ifdef DEBUG_MMU
215
            printf("mmu flush level %d\n", mmulev);
216
#endif
217
            switch (mmulev) {
218
            case 0: // flush page
219
                tlb_flush_page(env, T0 & 0xfffff000);
220
                break;
221
            case 1: // flush segment (256k)
222
            case 2: // flush region (16M)
223
            case 3: // flush context (4G)
224
            case 4: // flush entire
225
                tlb_flush(env, 1);
226
                break;
227
            default:
228
                break;
229
            }
230
#ifdef DEBUG_MMU
231
            dump_mmu(env);
232
#endif
233
            return;
234
        }
235
    case 4: /* write MMU regs */
236
        {
237
            int reg = (T0 >> 8) & 0xf;
238
            uint32_t oldreg;
239
            
240
            oldreg = env->mmuregs[reg];
241
            switch(reg) {
242
            case 0:
243
                env->mmuregs[reg] &= ~(MMU_E | MMU_NF);
244
                env->mmuregs[reg] |= T1 & (MMU_E | MMU_NF);
245
                // Mappings generated during no-fault mode or MMU
246
                // disabled mode are invalid in normal mode
247
                if (oldreg != env->mmuregs[reg])
248
                    tlb_flush(env, 1);
249
                break;
250
            case 2:
251
                env->mmuregs[reg] = T1;
252
                if (oldreg != env->mmuregs[reg]) {
253
                    /* we flush when the MMU context changes because
254
                       QEMU has no MMU context support */
255
                    tlb_flush(env, 1);
256
                }
257
                break;
258
            case 3:
259
            case 4:
260
                break;
261
            default:
262
                env->mmuregs[reg] = T1;
263
                break;
264
            }
265
#ifdef DEBUG_MMU
266
            if (oldreg != env->mmuregs[reg]) {
267
                printf("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->mmuregs[reg]);
268
            }
269
            dump_mmu(env);
270
#endif
271
            return;
272
        }
273
    case 0x17: /* Block copy, sta access */
274
        {
275
            // value (T1) = src
276
            // address (T0) = dst
277
            // copy 32 bytes
278
            uint32_t src = T1, dst = T0;
279
            uint8_t temp[32];
280
            
281
            tswap32s(&src);
282

    
283
            cpu_physical_memory_read(src, (void *) &temp, 32);
284
            cpu_physical_memory_write(dst, (void *) &temp, 32);
285
        }
286
        return;
287
    case 0x1f: /* Block fill, stda access */
288
        {
289
            // value (T1, T2)
290
            // address (T0) = dst
291
            // fill 32 bytes
292
            int i;
293
            uint32_t dst = T0;
294
            uint64_t val;
295
            
296
            val = (((uint64_t)T1) << 32) | T2;
297
            tswap64s(&val);
298

    
299
            for (i = 0; i < 32; i += 8, dst += 8) {
300
                cpu_physical_memory_write(dst, (void *) &val, 8);
301
            }
302
        }
303
        return;
304
    case 0x20 ... 0x2f: /* MMU passthrough */
305
        {
306
            switch(size) {
307
            case 1:
308
                stb_phys(T0, T1);
309
                break;
310
            case 2:
311
                stw_phys(T0 & ~1, T1);
312
                break;
313
            case 4:
314
            default:
315
                stl_phys(T0 & ~3, T1);
316
                break;
317
            case 8:
318
                stl_phys(T0 & ~3, T1);
319
                stl_phys((T0 + 4) & ~3, T2);
320
                break;
321
            }
322
        }
323
        return;
324
    default:
325
        return;
326
    }
327
}
328

    
329
#else
330

    
331
void helper_ld_asi(int asi, int size, int sign)
332
{
333
    uint64_t ret = 0;
334

    
335
    if (asi < 0x80 && (env->pstate & PS_PRIV) == 0)
336
        raise_exception(TT_PRIV_ACT);
337

    
338
    switch (asi) {
339
    case 0x14: // Bypass
340
    case 0x15: // Bypass, non-cacheable
341
        {
342
            switch(size) {
343
            case 1:
344
                ret = ldub_phys(T0);
345
                break;
346
            case 2:
347
                ret = lduw_phys(T0 & ~1);
348
                break;
349
            case 4:
350
                ret = ldl_phys(T0 & ~3);
351
                break;
352
            default:
353
            case 8:
354
                ret = ldq_phys(T0 & ~7);
355
                break;
356
            }
357
            break;
358
        }
359
    case 0x04: // Nucleus
360
    case 0x0c: // Nucleus Little Endian (LE)
361
    case 0x10: // As if user primary
362
    case 0x11: // As if user secondary
363
    case 0x18: // As if user primary LE
364
    case 0x19: // As if user secondary LE
365
    case 0x1c: // Bypass LE
366
    case 0x1d: // Bypass, non-cacheable LE
367
    case 0x24: // Nucleus quad LDD 128 bit atomic
368
    case 0x2c: // Nucleus quad LDD 128 bit atomic
369
    case 0x4a: // UPA config
370
    case 0x82: // Primary no-fault
371
    case 0x83: // Secondary no-fault
372
    case 0x88: // Primary LE
373
    case 0x89: // Secondary LE
374
    case 0x8a: // Primary no-fault LE
375
    case 0x8b: // Secondary no-fault LE
376
        // XXX
377
        break;
378
    case 0x45: // LSU
379
        ret = env->lsu;
380
        break;
381
    case 0x50: // I-MMU regs
382
        {
383
            int reg = (T0 >> 3) & 0xf;
384

    
385
            ret = env->immuregs[reg];
386
            break;
387
        }
388
    case 0x51: // I-MMU 8k TSB pointer
389
    case 0x52: // I-MMU 64k TSB pointer
390
    case 0x55: // I-MMU data access
391
        // XXX
392
        break;
393
    case 0x56: // I-MMU tag read
394
        {
395
            unsigned int i;
396
            
397
            for (i = 0; i < 64; i++) {
398
                // Valid, ctx match, vaddr match
399
                if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0 &&
400
                    env->itlb_tag[i] == T0) {
401
                    ret = env->itlb_tag[i];
402
                    break;
403
                }
404
            }
405
            break;
406
        }
407
    case 0x58: // D-MMU regs
408
        {
409
            int reg = (T0 >> 3) & 0xf;
410

    
411
            ret = env->dmmuregs[reg];
412
            break;
413
        }
414
    case 0x5e: // D-MMU tag read
415
        {
416
            unsigned int i;
417
            
418
            for (i = 0; i < 64; i++) {
419
                // Valid, ctx match, vaddr match
420
                if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0 &&
421
                    env->dtlb_tag[i] == T0) {
422
                    ret = env->dtlb_tag[i];
423
                    break;
424
                }
425
            }
426
            break;
427
        }
428
    case 0x59: // D-MMU 8k TSB pointer
429
    case 0x5a: // D-MMU 64k TSB pointer
430
    case 0x5b: // D-MMU data pointer
431
    case 0x5d: // D-MMU data access
432
    case 0x48: // Interrupt dispatch, RO
433
    case 0x49: // Interrupt data receive
434
    case 0x7f: // Incoming interrupt vector, RO
435
        // XXX
436
        break;
437
    case 0x54: // I-MMU data in, WO
438
    case 0x57: // I-MMU demap, WO
439
    case 0x5c: // D-MMU data in, WO
440
    case 0x5f: // D-MMU demap, WO
441
    case 0x77: // Interrupt vector, WO
442
    default:
443
        ret = 0;
444
        break;
445
    }
446
    T1 = ret;
447
}
448

    
449
void helper_st_asi(int asi, int size, int sign)
450
{
451
    if (asi < 0x80 && (env->pstate & PS_PRIV) == 0)
452
        raise_exception(TT_PRIV_ACT);
453

    
454
    switch(asi) {
455
    case 0x14: // Bypass
456
    case 0x15: // Bypass, non-cacheable
457
        {
458
            switch(size) {
459
            case 1:
460
                stb_phys(T0, T1);
461
                break;
462
            case 2:
463
                stw_phys(T0 & ~1, T1);
464
                break;
465
            case 4:
466
                stl_phys(T0 & ~3, T1);
467
                break;
468
            case 8:
469
            default:
470
                stq_phys(T0 & ~7, T1);
471
                break;
472
            }
473
        }
474
        return;
475
    case 0x04: // Nucleus
476
    case 0x0c: // Nucleus Little Endian (LE)
477
    case 0x10: // As if user primary
478
    case 0x11: // As if user secondary
479
    case 0x18: // As if user primary LE
480
    case 0x19: // As if user secondary LE
481
    case 0x1c: // Bypass LE
482
    case 0x1d: // Bypass, non-cacheable LE
483
    case 0x24: // Nucleus quad LDD 128 bit atomic
484
    case 0x2c: // Nucleus quad LDD 128 bit atomic
485
    case 0x4a: // UPA config
486
    case 0x88: // Primary LE
487
    case 0x89: // Secondary LE
488
        // XXX
489
        return;
490
    case 0x45: // LSU
491
        {
492
            uint64_t oldreg;
493

    
494
            oldreg = env->lsu;
495
            env->lsu = T1 & (DMMU_E | IMMU_E);
496
            // Mappings generated during D/I MMU disabled mode are
497
            // invalid in normal mode
498
            if (oldreg != env->lsu) {
499
#ifdef DEBUG_MMU
500
                printf("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n", oldreg, env->lsu);
501
                dump_mmu(env);
502
#endif
503
                tlb_flush(env, 1);
504
            }
505
            return;
506
        }
507
    case 0x50: // I-MMU regs
508
        {
509
            int reg = (T0 >> 3) & 0xf;
510
            uint64_t oldreg;
511
            
512
            oldreg = env->immuregs[reg];
513
            switch(reg) {
514
            case 0: // RO
515
            case 4:
516
                return;
517
            case 1: // Not in I-MMU
518
            case 2:
519
            case 7:
520
            case 8:
521
                return;
522
            case 3: // SFSR
523
                if ((T1 & 1) == 0)
524
                    T1 = 0; // Clear SFSR
525
                break;
526
            case 5: // TSB access
527
            case 6: // Tag access
528
            default:
529
                break;
530
            }
531
            env->immuregs[reg] = T1;
532
#ifdef DEBUG_MMU
533
            if (oldreg != env->immuregs[reg]) {
534
                printf("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
535
            }
536
            dump_mmu(env);
537
#endif
538
            return;
539
        }
540
    case 0x54: // I-MMU data in
541
        {
542
            unsigned int i;
543

    
544
            // Try finding an invalid entry
545
            for (i = 0; i < 64; i++) {
546
                if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) {
547
                    env->itlb_tag[i] = env->immuregs[6];
548
                    env->itlb_tte[i] = T1;
549
                    return;
550
                }
551
            }
552
            // Try finding an unlocked entry
553
            for (i = 0; i < 64; i++) {
554
                if ((env->itlb_tte[i] & 0x40) == 0) {
555
                    env->itlb_tag[i] = env->immuregs[6];
556
                    env->itlb_tte[i] = T1;
557
                    return;
558
                }
559
            }
560
            // error state?
561
            return;
562
        }
563
    case 0x55: // I-MMU data access
564
        {
565
            unsigned int i = (T0 >> 3) & 0x3f;
566

    
567
            env->itlb_tag[i] = env->immuregs[6];
568
            env->itlb_tte[i] = T1;
569
            return;
570
        }
571
    case 0x57: // I-MMU demap
572
        // XXX
573
        return;
574
    case 0x58: // D-MMU regs
575
        {
576
            int reg = (T0 >> 3) & 0xf;
577
            uint64_t oldreg;
578
            
579
            oldreg = env->dmmuregs[reg];
580
            switch(reg) {
581
            case 0: // RO
582
            case 4:
583
                return;
584
            case 3: // SFSR
585
                if ((T1 & 1) == 0) {
586
                    T1 = 0; // Clear SFSR, Fault address
587
                    env->dmmuregs[4] = 0;
588
                }
589
                env->dmmuregs[reg] = T1;
590
                break;
591
            case 1: // Primary context
592
            case 2: // Secondary context
593
            case 5: // TSB access
594
            case 6: // Tag access
595
            case 7: // Virtual Watchpoint
596
            case 8: // Physical Watchpoint
597
            default:
598
                break;
599
            }
600
            env->dmmuregs[reg] = T1;
601
#ifdef DEBUG_MMU
602
            if (oldreg != env->dmmuregs[reg]) {
603
                printf("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
604
            }
605
            dump_mmu(env);
606
#endif
607
            return;
608
        }
609
    case 0x5c: // D-MMU data in
610
        {
611
            unsigned int i;
612

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

    
636
            env->dtlb_tag[i] = env->dmmuregs[6];
637
            env->dtlb_tte[i] = T1;
638
            return;
639
        }
640
    case 0x5f: // D-MMU demap
641
    case 0x49: // Interrupt data receive
642
        // XXX
643
        return;
644
    case 0x51: // I-MMU 8k TSB pointer, RO
645
    case 0x52: // I-MMU 64k TSB pointer, RO
646
    case 0x56: // I-MMU tag read, RO
647
    case 0x59: // D-MMU 8k TSB pointer, RO
648
    case 0x5a: // D-MMU 64k TSB pointer, RO
649
    case 0x5b: // D-MMU data pointer, RO
650
    case 0x5e: // D-MMU tag read, RO
651
    case 0x48: // Interrupt dispatch, RO
652
    case 0x7f: // Incoming interrupt vector, RO
653
    case 0x82: // Primary no-fault, RO
654
    case 0x83: // Secondary no-fault, RO
655
    case 0x8a: // Primary no-fault LE, RO
656
    case 0x8b: // Secondary no-fault LE, RO
657
    default:
658
        return;
659
    }
660
}
661
#endif
662
#endif /* !CONFIG_USER_ONLY */
663

    
664
#ifndef TARGET_SPARC64
665
void helper_rett()
666
{
667
    unsigned int cwp;
668

    
669
    if (env->psret == 1)
670
        raise_exception(TT_ILL_INSN);
671

    
672
    env->psret = 1;
673
    cwp = (env->cwp + 1) & (NWINDOWS - 1); 
674
    if (env->wim & (1 << cwp)) {
675
        raise_exception(TT_WIN_UNF);
676
    }
677
    set_cwp(cwp);
678
    env->psrs = env->psrps;
679
}
680
#endif
681

    
682
void helper_ldfsr(void)
683
{
684
    int rnd_mode;
685
    switch (env->fsr & FSR_RD_MASK) {
686
    case FSR_RD_NEAREST:
687
        rnd_mode = float_round_nearest_even;
688
        break;
689
    default:
690
    case FSR_RD_ZERO:
691
        rnd_mode = float_round_to_zero;
692
        break;
693
    case FSR_RD_POS:
694
        rnd_mode = float_round_up;
695
        break;
696
    case FSR_RD_NEG:
697
        rnd_mode = float_round_down;
698
        break;
699
    }
700
    set_float_rounding_mode(rnd_mode, &env->fp_status);
701
}
702

    
703
void helper_debug()
704
{
705
    env->exception_index = EXCP_DEBUG;
706
    cpu_loop_exit();
707
}
708

    
709
#ifndef TARGET_SPARC64
710
void do_wrpsr()
711
{
712
    if ((T0 & PSR_CWP) >= NWINDOWS)
713
        raise_exception(TT_ILL_INSN);
714
    else
715
        PUT_PSR(env, T0);
716
}
717

    
718
void do_rdpsr()
719
{
720
    T0 = GET_PSR(env);
721
}
722

    
723
#else
724

    
725
void do_popc()
726
{
727
    T0 = (T1 & 0x5555555555555555ULL) + ((T1 >> 1) & 0x5555555555555555ULL);
728
    T0 = (T0 & 0x3333333333333333ULL) + ((T0 >> 2) & 0x3333333333333333ULL);
729
    T0 = (T0 & 0x0f0f0f0f0f0f0f0fULL) + ((T0 >> 4) & 0x0f0f0f0f0f0f0f0fULL);
730
    T0 = (T0 & 0x00ff00ff00ff00ffULL) + ((T0 >> 8) & 0x00ff00ff00ff00ffULL);
731
    T0 = (T0 & 0x0000ffff0000ffffULL) + ((T0 >> 16) & 0x0000ffff0000ffffULL);
732
    T0 = (T0 & 0x00000000ffffffffULL) + ((T0 >> 32) & 0x00000000ffffffffULL);
733
}
734

    
735
static inline uint64_t *get_gregset(uint64_t pstate)
736
{
737
    switch (pstate) {
738
    default:
739
    case 0:
740
        return env->bgregs;
741
    case PS_AG:
742
        return env->agregs;
743
    case PS_MG:
744
        return env->mgregs;
745
    case PS_IG:
746
        return env->igregs;
747
    }
748
}
749

    
750
void do_wrpstate()
751
{
752
    uint64_t new_pstate, pstate_regs, new_pstate_regs;
753
    uint64_t *src, *dst;
754

    
755
    new_pstate = T0 & 0xf3f;
756
    pstate_regs = env->pstate & 0xc01;
757
    new_pstate_regs = new_pstate & 0xc01;
758
    if (new_pstate_regs != pstate_regs) {
759
        // Switch global register bank
760
        src = get_gregset(new_pstate_regs);
761
        dst = get_gregset(pstate_regs);
762
        memcpy32(dst, env->gregs);
763
        memcpy32(env->gregs, src);
764
    }
765
    env->pstate = new_pstate;
766
}
767

    
768
void do_done(void)
769
{
770
    env->tl--;
771
    env->pc = env->tnpc[env->tl];
772
    env->npc = env->tnpc[env->tl] + 4;
773
    PUT_CCR(env, env->tstate[env->tl] >> 32);
774
    env->asi = (env->tstate[env->tl] >> 24) & 0xff;
775
    env->pstate = (env->tstate[env->tl] >> 8) & 0xfff;
776
    set_cwp(env->tstate[env->tl] & 0xff);
777
}
778

    
779
void do_retry(void)
780
{
781
    env->tl--;
782
    env->pc = env->tpc[env->tl];
783
    env->npc = env->tnpc[env->tl];
784
    PUT_CCR(env, env->tstate[env->tl] >> 32);
785
    env->asi = (env->tstate[env->tl] >> 24) & 0xff;
786
    env->pstate = (env->tstate[env->tl] >> 8) & 0xfff;
787
    set_cwp(env->tstate[env->tl] & 0xff);
788
}
789
#endif
790

    
791
void set_cwp(int new_cwp)
792
{
793
    /* put the modified wrap registers at their proper location */
794
    if (env->cwp == (NWINDOWS - 1))
795
        memcpy32(env->regbase, env->regbase + NWINDOWS * 16);
796
    env->cwp = new_cwp;
797
    /* put the wrap registers at their temporary location */
798
    if (new_cwp == (NWINDOWS - 1))
799
        memcpy32(env->regbase + NWINDOWS * 16, env->regbase);
800
    env->regwptr = env->regbase + (new_cwp * 16);
801
    REGWPTR = env->regwptr;
802
}
803

    
804
void cpu_set_cwp(CPUState *env1, int new_cwp)
805
{
806
    CPUState *saved_env;
807
#ifdef reg_REGWPTR
808
    target_ulong *saved_regwptr;
809
#endif
810

    
811
    saved_env = env;
812
#ifdef reg_REGWPTR
813
    saved_regwptr = REGWPTR;
814
#endif
815
    env = env1;
816
    set_cwp(new_cwp);
817
    env = saved_env;
818
#ifdef reg_REGWPTR
819
    REGWPTR = saved_regwptr;
820
#endif
821
}
822

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

839
            fprintf(logfile, "       code=");
840
            ptr = (uint8_t *)env->pc;
841
            for(i = 0; i < 16; i++) {
842
                fprintf(logfile, " %02x", ldub(ptr + i));
843
            }
844
            fprintf(logfile, "\n");
845
        }
846
#endif
847
        count++;
848
    }
849
#endif
850
#if !defined(CONFIG_USER_ONLY) 
851
    if (env->tl == MAXTL) {
852
        cpu_abort(env, "Trap 0x%04x while trap level is MAXTL, Error state", env->exception_index);
853
        return;
854
    }
855
#endif
856
    env->tstate[env->tl] = ((uint64_t)GET_CCR(env) << 32) | ((env->asi & 0xff) << 24) |
857
        ((env->pstate & 0xfff) << 8) | (env->cwp & 0xff);
858
    env->tpc[env->tl] = env->pc;
859
    env->tnpc[env->tl] = env->npc;
860
    env->tt[env->tl] = intno;
861
    env->pstate = PS_PEF | PS_PRIV | PS_AG;
862
    env->tbr &= ~0x7fffULL;
863
    env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
864
    if (env->tl < MAXTL - 1) {
865
        env->tl++;
866
    } else {
867
        env->pstate |= PS_RED;
868
        if (env->tl != MAXTL)
869
            env->tl++;
870
    }
871
    env->pc = env->tbr;
872
    env->npc = env->pc + 4;
873
    env->exception_index = 0;
874
}
875
#else
876
void do_interrupt(int intno)
877
{
878
    int cwp;
879

    
880
#ifdef DEBUG_PCALL
881
    if (loglevel & CPU_LOG_INT) {
882
        static int count;
883
        fprintf(logfile, "%6d: v=%02x pc=%08x npc=%08x SP=%08x\n",
884
                count, intno,
885
                env->pc,
886
                env->npc, env->regwptr[6]);
887
        cpu_dump_state(env, logfile, fprintf, 0);
888
#if 0
889
        {
890
            int i;
891
            uint8_t *ptr;
892

893
            fprintf(logfile, "       code=");
894
            ptr = (uint8_t *)env->pc;
895
            for(i = 0; i < 16; i++) {
896
                fprintf(logfile, " %02x", ldub(ptr + i));
897
            }
898
            fprintf(logfile, "\n");
899
        }
900
#endif
901
        count++;
902
    }
903
#endif
904
#if !defined(CONFIG_USER_ONLY) 
905
    if (env->psret == 0) {
906
        cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index);
907
        return;
908
    }
909
#endif
910
    env->psret = 0;
911
    cwp = (env->cwp - 1) & (NWINDOWS - 1); 
912
    set_cwp(cwp);
913
    env->regwptr[9] = env->pc;
914
    env->regwptr[10] = env->npc;
915
    env->psrps = env->psrs;
916
    env->psrs = 1;
917
    env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
918
    env->pc = env->tbr;
919
    env->npc = env->pc + 4;
920
    env->exception_index = 0;
921
}
922
#endif
923

    
924
#if !defined(CONFIG_USER_ONLY) 
925

    
926
#define MMUSUFFIX _mmu
927
#define GETPC() (__builtin_return_address(0))
928

    
929
#define SHIFT 0
930
#include "softmmu_template.h"
931

    
932
#define SHIFT 1
933
#include "softmmu_template.h"
934

    
935
#define SHIFT 2
936
#include "softmmu_template.h"
937

    
938
#define SHIFT 3
939
#include "softmmu_template.h"
940

    
941

    
942
/* try to fill the TLB and return an exception if error. If retaddr is
943
   NULL, it means that the function was called in C code (i.e. not
944
   from generated code or from helper.c) */
945
/* XXX: fix it to restore all registers */
946
void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr)
947
{
948
    TranslationBlock *tb;
949
    int ret;
950
    unsigned long pc;
951
    CPUState *saved_env;
952

    
953
    /* XXX: hack to restore env in all cases, even if not called from
954
       generated code */
955
    saved_env = env;
956
    env = cpu_single_env;
957

    
958
    ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, is_user, 1);
959
    if (ret) {
960
        if (retaddr) {
961
            /* now we have a real cpu fault */
962
            pc = (unsigned long)retaddr;
963
            tb = tb_find_pc(pc);
964
            if (tb) {
965
                /* the PC is inside the translated code. It means that we have
966
                   a virtual CPU fault */
967
                cpu_restore_state(tb, env, pc, (void *)T2);
968
            }
969
        }
970
        cpu_loop_exit();
971
    }
972
    env = saved_env;
973
}
974

    
975
#endif