Statistics
| Branch: | Revision:

root / target-sparc / op_helper.c @ 83469015

History | View | Annotate | Download (22.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
#ifdef USE_INT_TO_FLOAT_HELPERS
13
void do_fitos(void)
14
{
15
    FT0 = (float) *((int32_t *)&FT1);
16
}
17

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
272
void helper_st_asi(int asi, int size, int sign)
273
{
274
    switch(asi) {
275
    case 3: /* MMU flush */
276
        {
277
            int mmulev;
278

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

    
349
            cpu_physical_memory_read(src, (void *) &temp, 32);
350
            cpu_physical_memory_write(dst, (void *) &temp, 32);
351
        }
352
        return;
353
    case 0x1f: /* Block fill, stda access */
354
        {
355
            // value (T1, T2)
356
            // address (T0) = dst
357
            // fill 32 bytes
358
            int i;
359
            uint32_t dst = T0;
360
            uint64_t val;
361
            
362
            val = (((uint64_t)T1) << 32) | T2;
363
            tswap64s(&val);
364

    
365
            for (i = 0; i < 32; i += 8, dst += 8) {
366
                cpu_physical_memory_write(dst, (void *) &val, 8);
367
            }
368
        }
369
        return;
370
    case 0x20 ... 0x2f: /* MMU passthrough */
371
        {
372
            uint32_t temp = T1;
373
            if (size == 4)
374
                tswap32s(&temp);
375
            else if (size == 2)
376
                tswap16s((uint16_t *)&temp);
377
            cpu_physical_memory_write(T0, (void *) &temp, size);
378
        }
379
        return;
380
    default:
381
        return;
382
    }
383
}
384

    
385
#else
386

    
387
void helper_ld_asi(int asi, int size, int sign)
388
{
389
    uint64_t ret = 0;
390

    
391
    if (asi < 0x80 && (env->pstate & PS_PRIV) == 0)
392
        raise_exception(TT_PRIV_ACT);
393

    
394
    switch (asi) {
395
    case 0x14: // Bypass
396
    case 0x15: // Bypass, non-cacheable
397
        {
398
            cpu_physical_memory_read(T0, (void *) &ret, size);
399
            if (size == 8)
400
                tswap64s(&ret);
401
            if (size == 4)
402
                tswap32s((uint32_t *)&ret);
403
            else if (size == 2)
404
                tswap16s((uint16_t *)&ret);
405
            break;
406
        }
407
    case 0x04: // Nucleus
408
    case 0x0c: // Nucleus Little Endian (LE)
409
    case 0x10: // As if user primary
410
    case 0x11: // As if user secondary
411
    case 0x18: // As if user primary LE
412
    case 0x19: // As if user secondary LE
413
    case 0x1c: // Bypass LE
414
    case 0x1d: // Bypass, non-cacheable LE
415
    case 0x24: // Nucleus quad LDD 128 bit atomic
416
    case 0x2c: // Nucleus quad LDD 128 bit atomic
417
    case 0x4a: // UPA config
418
    case 0x82: // Primary no-fault
419
    case 0x83: // Secondary no-fault
420
    case 0x88: // Primary LE
421
    case 0x89: // Secondary LE
422
    case 0x8a: // Primary no-fault LE
423
    case 0x8b: // Secondary no-fault LE
424
        // XXX
425
        break;
426
    case 0x45: // LSU
427
        ret = env->lsu;
428
        break;
429
    case 0x50: // I-MMU regs
430
        {
431
            int reg = (T0 >> 3) & 0xf;
432

    
433
            ret = env->immuregs[reg];
434
            break;
435
        }
436
    case 0x51: // I-MMU 8k TSB pointer
437
    case 0x52: // I-MMU 64k TSB pointer
438
    case 0x55: // I-MMU data access
439
        // XXX
440
        break;
441
    case 0x56: // I-MMU tag read
442
        {
443
            unsigned int i;
444
            
445
            for (i = 0; i < 64; i++) {
446
                // Valid, ctx match, vaddr match
447
                if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0 &&
448
                    env->itlb_tag[i] == T0) {
449
                    ret = env->itlb_tag[i];
450
                    break;
451
                }
452
            }
453
            break;
454
        }
455
    case 0x58: // D-MMU regs
456
        {
457
            int reg = (T0 >> 3) & 0xf;
458

    
459
            ret = env->dmmuregs[reg];
460
            break;
461
        }
462
    case 0x5e: // D-MMU tag read
463
        {
464
            unsigned int i;
465
            
466
            for (i = 0; i < 64; i++) {
467
                // Valid, ctx match, vaddr match
468
                if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0 &&
469
                    env->dtlb_tag[i] == T0) {
470
                    ret = env->dtlb_tag[i];
471
                    break;
472
                }
473
            }
474
            break;
475
        }
476
    case 0x59: // D-MMU 8k TSB pointer
477
    case 0x5a: // D-MMU 64k TSB pointer
478
    case 0x5b: // D-MMU data pointer
479
    case 0x5d: // D-MMU data access
480
    case 0x48: // Interrupt dispatch, RO
481
    case 0x49: // Interrupt data receive
482
    case 0x7f: // Incoming interrupt vector, RO
483
        // XXX
484
        break;
485
    case 0x54: // I-MMU data in, WO
486
    case 0x57: // I-MMU demap, WO
487
    case 0x5c: // D-MMU data in, WO
488
    case 0x5f: // D-MMU demap, WO
489
    case 0x77: // Interrupt vector, WO
490
    default:
491
        ret = 0;
492
        break;
493
    }
494
    T1 = ret;
495
}
496

    
497
void helper_st_asi(int asi, int size, int sign)
498
{
499
    if (asi < 0x80 && (env->pstate & PS_PRIV) == 0)
500
        raise_exception(TT_PRIV_ACT);
501

    
502
    switch(asi) {
503
    case 0x14: // Bypass
504
    case 0x15: // Bypass, non-cacheable
505
        {
506
            target_ulong temp = T1;
507
            if (size == 8)
508
                tswap64s(&temp);
509
            else if (size == 4)
510
                tswap32s((uint32_t *)&temp);
511
            else if (size == 2)
512
                tswap16s((uint16_t *)&temp);
513
            cpu_physical_memory_write(T0, (void *) &temp, size);
514
        }
515
        return;
516
    case 0x04: // Nucleus
517
    case 0x0c: // Nucleus Little Endian (LE)
518
    case 0x10: // As if user primary
519
    case 0x11: // As if user secondary
520
    case 0x18: // As if user primary LE
521
    case 0x19: // As if user secondary LE
522
    case 0x1c: // Bypass LE
523
    case 0x1d: // Bypass, non-cacheable LE
524
    case 0x24: // Nucleus quad LDD 128 bit atomic
525
    case 0x2c: // Nucleus quad LDD 128 bit atomic
526
    case 0x4a: // UPA config
527
    case 0x88: // Primary LE
528
    case 0x89: // Secondary LE
529
        // XXX
530
        return;
531
    case 0x45: // LSU
532
        {
533
            uint64_t oldreg;
534

    
535
            oldreg = env->lsu;
536
            env->lsu = T1 & (DMMU_E | IMMU_E);
537
            // Mappings generated during D/I MMU disabled mode are
538
            // invalid in normal mode
539
            if (oldreg != env->lsu) {
540
#ifdef DEBUG_MMU
541
                printf("LSU change: 0x%llx -> 0x%llx\n", oldreg, env->lsu);
542
                dump_mmu(env);
543
#endif
544
                tlb_flush(env, 1);
545
            }
546
            return;
547
        }
548
    case 0x50: // I-MMU regs
549
        {
550
            int reg = (T0 >> 3) & 0xf;
551
            uint64_t oldreg;
552
            
553
            oldreg = env->immuregs[reg];
554
            switch(reg) {
555
            case 0: // RO
556
            case 4:
557
                return;
558
            case 1: // Not in I-MMU
559
            case 2:
560
            case 7:
561
            case 8:
562
                return;
563
            case 3: // SFSR
564
                if ((T1 & 1) == 0)
565
                    T1 = 0; // Clear SFSR
566
                break;
567
            case 5: // TSB access
568
            case 6: // Tag access
569
            default:
570
                break;
571
            }
572
            env->immuregs[reg] = T1;
573
#ifdef DEBUG_MMU
574
            if (oldreg != env->immuregs[reg]) {
575
                printf("mmu change reg[%d]: 0x%08llx -> 0x%08llx\n", reg, oldreg, env->immuregs[reg]);
576
            }
577
            dump_mmu(env);
578
#endif
579
            return;
580
        }
581
    case 0x54: // I-MMU data in
582
        {
583
            unsigned int i;
584

    
585
            // Try finding an invalid entry
586
            for (i = 0; i < 64; i++) {
587
                if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) {
588
                    env->itlb_tag[i] = env->immuregs[6];
589
                    env->itlb_tte[i] = T1;
590
                    return;
591
                }
592
            }
593
            // Try finding an unlocked entry
594
            for (i = 0; i < 64; i++) {
595
                if ((env->itlb_tte[i] & 0x40) == 0) {
596
                    env->itlb_tag[i] = env->immuregs[6];
597
                    env->itlb_tte[i] = T1;
598
                    return;
599
                }
600
            }
601
            // error state?
602
            return;
603
        }
604
    case 0x55: // I-MMU data access
605
        {
606
            unsigned int i = (T0 >> 3) & 0x3f;
607

    
608
            env->itlb_tag[i] = env->immuregs[6];
609
            env->itlb_tte[i] = T1;
610
            return;
611
        }
612
    case 0x57: // I-MMU demap
613
        // XXX
614
        return;
615
    case 0x58: // D-MMU regs
616
        {
617
            int reg = (T0 >> 3) & 0xf;
618
            uint64_t oldreg;
619
            
620
            oldreg = env->dmmuregs[reg];
621
            switch(reg) {
622
            case 0: // RO
623
            case 4:
624
                return;
625
            case 3: // SFSR
626
                if ((T1 & 1) == 0) {
627
                    T1 = 0; // Clear SFSR, Fault address
628
                    env->dmmuregs[4] = 0;
629
                }
630
                env->dmmuregs[reg] = T1;
631
                break;
632
            case 1: // Primary context
633
            case 2: // Secondary context
634
            case 5: // TSB access
635
            case 6: // Tag access
636
            case 7: // Virtual Watchpoint
637
            case 8: // Physical Watchpoint
638
            default:
639
                break;
640
            }
641
            env->dmmuregs[reg] = T1;
642
#ifdef DEBUG_MMU
643
            if (oldreg != env->dmmuregs[reg]) {
644
                printf("mmu change reg[%d]: 0x%08llx -> 0x%08llx\n", reg, oldreg, env->dmmuregs[reg]);
645
            }
646
            dump_mmu(env);
647
#endif
648
            return;
649
        }
650
    case 0x5c: // D-MMU data in
651
        {
652
            unsigned int i;
653

    
654
            // Try finding an invalid entry
655
            for (i = 0; i < 64; i++) {
656
                if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) {
657
                    env->dtlb_tag[i] = env->dmmuregs[6];
658
                    env->dtlb_tte[i] = T1;
659
                    return;
660
                }
661
            }
662
            // Try finding an unlocked entry
663
            for (i = 0; i < 64; i++) {
664
                if ((env->dtlb_tte[i] & 0x40) == 0) {
665
                    env->dtlb_tag[i] = env->dmmuregs[6];
666
                    env->dtlb_tte[i] = T1;
667
                    return;
668
                }
669
            }
670
            // error state?
671
            return;
672
        }
673
    case 0x5d: // D-MMU data access
674
        {
675
            unsigned int i = (T0 >> 3) & 0x3f;
676

    
677
            env->dtlb_tag[i] = env->dmmuregs[6];
678
            env->dtlb_tte[i] = T1;
679
            return;
680
        }
681
    case 0x5f: // D-MMU demap
682
    case 0x49: // Interrupt data receive
683
        // XXX
684
        return;
685
    case 0x51: // I-MMU 8k TSB pointer, RO
686
    case 0x52: // I-MMU 64k TSB pointer, RO
687
    case 0x56: // I-MMU tag read, RO
688
    case 0x59: // D-MMU 8k TSB pointer, RO
689
    case 0x5a: // D-MMU 64k TSB pointer, RO
690
    case 0x5b: // D-MMU data pointer, RO
691
    case 0x5e: // D-MMU tag read, RO
692
    case 0x48: // Interrupt dispatch, RO
693
    case 0x7f: // Incoming interrupt vector, RO
694
    case 0x82: // Primary no-fault, RO
695
    case 0x83: // Secondary no-fault, RO
696
    case 0x8a: // Primary no-fault LE, RO
697
    case 0x8b: // Secondary no-fault LE, RO
698
    default:
699
        return;
700
    }
701
}
702

    
703
#endif
704

    
705
#ifndef TARGET_SPARC64
706
void helper_rett()
707
{
708
    unsigned int cwp;
709

    
710
    env->psret = 1;
711
    cwp = (env->cwp + 1) & (NWINDOWS - 1); 
712
    if (env->wim & (1 << cwp)) {
713
        raise_exception(TT_WIN_UNF);
714
    }
715
    set_cwp(cwp);
716
    env->psrs = env->psrps;
717
}
718
#endif
719

    
720
void helper_ldfsr(void)
721
{
722
    int rnd_mode;
723
    switch (env->fsr & FSR_RD_MASK) {
724
    case FSR_RD_NEAREST:
725
        rnd_mode = float_round_nearest_even;
726
        break;
727
    default:
728
    case FSR_RD_ZERO:
729
        rnd_mode = float_round_to_zero;
730
        break;
731
    case FSR_RD_POS:
732
        rnd_mode = float_round_up;
733
        break;
734
    case FSR_RD_NEG:
735
        rnd_mode = float_round_down;
736
        break;
737
    }
738
    set_float_rounding_mode(rnd_mode, &env->fp_status);
739
}
740

    
741
void cpu_get_fp64(uint64_t *pmant, uint16_t *pexp, double f)
742
{
743
    int exptemp;
744

    
745
    *pmant = ldexp(frexp(f, &exptemp), 53);
746
    *pexp = exptemp;
747
}
748

    
749
double cpu_put_fp64(uint64_t mant, uint16_t exp)
750
{
751
    return ldexp((double) mant, exp - 53);
752
}
753

    
754
void helper_debug()
755
{
756
    env->exception_index = EXCP_DEBUG;
757
    cpu_loop_exit();
758
}
759

    
760
#ifndef TARGET_SPARC64
761
void do_wrpsr()
762
{
763
    PUT_PSR(env, T0);
764
}
765

    
766
void do_rdpsr()
767
{
768
    T0 = GET_PSR(env);
769
}
770

    
771
#else
772

    
773
void do_popc()
774
{
775
    T0 = (T1 & 0x5555555555555555ULL) + ((T1 >> 1) & 0x5555555555555555ULL);
776
    T0 = (T0 & 0x3333333333333333ULL) + ((T0 >> 2) & 0x3333333333333333ULL);
777
    T0 = (T0 & 0x0f0f0f0f0f0f0f0fULL) + ((T0 >> 4) & 0x0f0f0f0f0f0f0f0fULL);
778
    T0 = (T0 & 0x00ff00ff00ff00ffULL) + ((T0 >> 8) & 0x00ff00ff00ff00ffULL);
779
    T0 = (T0 & 0x0000ffff0000ffffULL) + ((T0 >> 16) & 0x0000ffff0000ffffULL);
780
    T0 = (T0 & 0x00000000ffffffffULL) + ((T0 >> 32) & 0x00000000ffffffffULL);
781
}
782

    
783
static inline uint64_t *get_gregset(uint64_t pstate)
784
{
785
    switch (pstate) {
786
    default:
787
    case 0:
788
        return env->bgregs;
789
    case PS_AG:
790
        return env->agregs;
791
    case PS_MG:
792
        return env->mgregs;
793
    case PS_IG:
794
        return env->igregs;
795
    }
796
}
797

    
798
void do_wrpstate()
799
{
800
    uint64_t new_pstate, pstate_regs, new_pstate_regs;
801
    uint64_t *src, *dst;
802

    
803
    new_pstate = T0 & 0xf3f;
804
    pstate_regs = env->pstate & 0xc01;
805
    new_pstate_regs = new_pstate & 0xc01;
806
    if (new_pstate_regs != pstate_regs) {
807
        // Switch global register bank
808
        src = get_gregset(new_pstate_regs);
809
        dst = get_gregset(pstate_regs);
810
        memcpy32(dst, env->gregs);
811
        memcpy32(env->gregs, src);
812
    }
813
    env->pstate = new_pstate;
814
}
815

    
816
void do_done(void)
817
{
818
    env->tl--;
819
    env->pc = env->tnpc[env->tl];
820
    env->npc = env->tnpc[env->tl] + 4;
821
    PUT_CCR(env, env->tstate[env->tl] >> 32);
822
    env->asi = (env->tstate[env->tl] >> 24) & 0xff;
823
    env->pstate = (env->tstate[env->tl] >> 8) & 0xfff;
824
    set_cwp(env->tstate[env->tl] & 0xff);
825
}
826

    
827
void do_retry(void)
828
{
829
    env->tl--;
830
    env->pc = env->tpc[env->tl];
831
    env->npc = env->tnpc[env->tl];
832
    PUT_CCR(env, env->tstate[env->tl] >> 32);
833
    env->asi = (env->tstate[env->tl] >> 24) & 0xff;
834
    env->pstate = (env->tstate[env->tl] >> 8) & 0xfff;
835
    set_cwp(env->tstate[env->tl] & 0xff);
836
}
837
#endif
838

    
839
void set_cwp(int new_cwp)
840
{
841
    /* put the modified wrap registers at their proper location */
842
    if (env->cwp == (NWINDOWS - 1))
843
        memcpy32(env->regbase, env->regbase + NWINDOWS * 16);
844
    env->cwp = new_cwp;
845
    /* put the wrap registers at their temporary location */
846
    if (new_cwp == (NWINDOWS - 1))
847
        memcpy32(env->regbase + NWINDOWS * 16, env->regbase);
848
    env->regwptr = env->regbase + (new_cwp * 16);
849
    REGWPTR = env->regwptr;
850
}
851

    
852
void cpu_set_cwp(CPUState *env1, int new_cwp)
853
{
854
    CPUState *saved_env;
855
#ifdef reg_REGWPTR
856
    target_ulong *saved_regwptr;
857
#endif
858

    
859
    saved_env = env;
860
#ifdef reg_REGWPTR
861
    saved_regwptr = REGWPTR;
862
#endif
863
    env = env1;
864
    set_cwp(new_cwp);
865
    env = saved_env;
866
#ifdef reg_REGWPTR
867
    REGWPTR = saved_regwptr;
868
#endif
869
}
870

    
871
#ifdef TARGET_SPARC64
872
void do_interrupt(int intno)
873
{
874
#ifdef DEBUG_PCALL
875
    if (loglevel & CPU_LOG_INT) {
876
        static int count;
877
        fprintf(logfile, "%6d: v=%04x pc=%016llx npc=%016llx SP=%016llx\n",
878
                count, intno,
879
                env->pc,
880
                env->npc, env->regwptr[6]);
881
        cpu_dump_state(env, logfile, fprintf, 0);
882
#if 0
883
        {
884
            int i;
885
            uint8_t *ptr;
886

887
            fprintf(logfile, "       code=");
888
            ptr = (uint8_t *)env->pc;
889
            for(i = 0; i < 16; i++) {
890
                fprintf(logfile, " %02x", ldub(ptr + i));
891
            }
892
            fprintf(logfile, "\n");
893
        }
894
#endif
895
        count++;
896
    }
897
#endif
898
#if !defined(CONFIG_USER_ONLY) 
899
    if (env->tl == MAXTL) {
900
        cpu_abort(cpu_single_env, "Trap 0x%04x while trap level is MAXTL, Error state", env->exception_index);
901
        return;
902
    }
903
#endif
904
    env->tstate[env->tl] = ((uint64_t)GET_CCR(env) << 32) | ((env->asi & 0xff) << 24) |
905
        ((env->pstate & 0xfff) << 8) | (env->cwp & 0xff);
906
    env->tpc[env->tl] = env->pc;
907
    env->tnpc[env->tl] = env->npc;
908
    env->tt[env->tl] = intno;
909
    env->pstate = PS_PEF | PS_PRIV | PS_AG;
910
    env->tbr &= ~0x7fffULL;
911
    env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
912
    if (env->tl < MAXTL - 1) {
913
        env->tl++;
914
    } else {
915
        env->pstate |= PS_RED;
916
        if (env->tl != MAXTL)
917
            env->tl++;
918
    }
919
    env->pc = env->tbr;
920
    env->npc = env->pc + 4;
921
    env->exception_index = 0;
922
}
923
#else
924
void do_interrupt(int intno)
925
{
926
    int cwp;
927

    
928
#ifdef DEBUG_PCALL
929
    if (loglevel & CPU_LOG_INT) {
930
        static int count;
931
        fprintf(logfile, "%6d: v=%02x pc=%08x npc=%08x SP=%08x\n",
932
                count, intno,
933
                env->pc,
934
                env->npc, env->regwptr[6]);
935
        cpu_dump_state(env, logfile, fprintf, 0);
936
#if 0
937
        {
938
            int i;
939
            uint8_t *ptr;
940

941
            fprintf(logfile, "       code=");
942
            ptr = (uint8_t *)env->pc;
943
            for(i = 0; i < 16; i++) {
944
                fprintf(logfile, " %02x", ldub(ptr + i));
945
            }
946
            fprintf(logfile, "\n");
947
        }
948
#endif
949
        count++;
950
    }
951
#endif
952
#if !defined(CONFIG_USER_ONLY) 
953
    if (env->psret == 0) {
954
        cpu_abort(cpu_single_env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index);
955
        return;
956
    }
957
#endif
958
    env->psret = 0;
959
    cwp = (env->cwp - 1) & (NWINDOWS - 1); 
960
    set_cwp(cwp);
961
    env->regwptr[9] = env->pc;
962
    env->regwptr[10] = env->npc;
963
    env->psrps = env->psrs;
964
    env->psrs = 1;
965
    env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
966
    env->pc = env->tbr;
967
    env->npc = env->pc + 4;
968
    env->exception_index = 0;
969
}
970
#endif
971

    
972
#if !defined(CONFIG_USER_ONLY) 
973

    
974
#define MMUSUFFIX _mmu
975
#define GETPC() (__builtin_return_address(0))
976

    
977
#define SHIFT 0
978
#include "softmmu_template.h"
979

    
980
#define SHIFT 1
981
#include "softmmu_template.h"
982

    
983
#define SHIFT 2
984
#include "softmmu_template.h"
985

    
986
#define SHIFT 3
987
#include "softmmu_template.h"
988

    
989

    
990
/* try to fill the TLB and return an exception if error. If retaddr is
991
   NULL, it means that the function was called in C code (i.e. not
992
   from generated code or from helper.c) */
993
/* XXX: fix it to restore all registers */
994
void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr)
995
{
996
    TranslationBlock *tb;
997
    int ret;
998
    unsigned long pc;
999
    CPUState *saved_env;
1000

    
1001
    /* XXX: hack to restore env in all cases, even if not called from
1002
       generated code */
1003
    saved_env = env;
1004
    env = cpu_single_env;
1005

    
1006
    ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, is_user, 1);
1007
    if (ret) {
1008
        if (retaddr) {
1009
            /* now we have a real cpu fault */
1010
            pc = (unsigned long)retaddr;
1011
            tb = tb_find_pc(pc);
1012
            if (tb) {
1013
                /* the PC is inside the translated code. It means that we have
1014
                   a virtual CPU fault */
1015
                cpu_restore_state(tb, env, pc, (void *)T2);
1016
            }
1017
        }
1018
        cpu_loop_exit();
1019
    }
1020
    env = saved_env;
1021
}
1022

    
1023
#endif