Statistics
| Branch: | Revision:

root / target-sparc / op_helper.c @ 5a834bb4

History | View | Annotate | Download (113.2 kB)

1
#include "exec.h"
2
#include "host-utils.h"
3
#include "helper.h"
4

    
5
//#define DEBUG_MMU
6
//#define DEBUG_MXCC
7
//#define DEBUG_UNALIGNED
8
//#define DEBUG_UNASSIGNED
9
//#define DEBUG_ASI
10
//#define DEBUG_PCALL
11
//#define DEBUG_PSTATE
12

    
13
#ifdef DEBUG_MMU
14
#define DPRINTF_MMU(fmt, ...)                                   \
15
    do { printf("MMU: " fmt , ## __VA_ARGS__); } while (0)
16
#else
17
#define DPRINTF_MMU(fmt, ...) do {} while (0)
18
#endif
19

    
20
#ifdef DEBUG_MXCC
21
#define DPRINTF_MXCC(fmt, ...)                                  \
22
    do { printf("MXCC: " fmt , ## __VA_ARGS__); } while (0)
23
#else
24
#define DPRINTF_MXCC(fmt, ...) do {} while (0)
25
#endif
26

    
27
#ifdef DEBUG_ASI
28
#define DPRINTF_ASI(fmt, ...)                                   \
29
    do { printf("ASI: " fmt , ## __VA_ARGS__); } while (0)
30
#endif
31

    
32
#ifdef DEBUG_PSTATE
33
#define DPRINTF_PSTATE(fmt, ...)                                   \
34
    do { printf("PSTATE: " fmt , ## __VA_ARGS__); } while (0)
35
#else
36
#define DPRINTF_PSTATE(fmt, ...) do {} while (0)
37
#endif
38

    
39
#ifdef TARGET_SPARC64
40
#ifndef TARGET_ABI32
41
#define AM_CHECK(env1) ((env1)->pstate & PS_AM)
42
#else
43
#define AM_CHECK(env1) (1)
44
#endif
45
#endif
46

    
47
#if defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64)
48
static void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
49
                          int is_asi, int size);
50
#endif
51

    
52
#if defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
53
// Calculates TSB pointer value for fault page size 8k or 64k
54
static uint64_t ultrasparc_tsb_pointer(uint64_t tsb_register,
55
                                       uint64_t tag_access_register,
56
                                       int page_size)
57
{
58
    uint64_t tsb_base = tsb_register & ~0x1fffULL;
59
    int tsb_split = (tsb_register & 0x1000ULL) ? 1 : 0;
60
    int tsb_size  = tsb_register & 0xf;
61

    
62
    // discard lower 13 bits which hold tag access context
63
    uint64_t tag_access_va = tag_access_register & ~0x1fffULL;
64

    
65
    // now reorder bits
66
    uint64_t tsb_base_mask = ~0x1fffULL;
67
    uint64_t va = tag_access_va;
68

    
69
    // move va bits to correct position
70
    if (page_size == 8*1024) {
71
        va >>= 9;
72
    } else if (page_size == 64*1024) {
73
        va >>= 12;
74
    }
75

    
76
    if (tsb_size) {
77
        tsb_base_mask <<= tsb_size;
78
    }
79

    
80
    // calculate tsb_base mask and adjust va if split is in use
81
    if (tsb_split) {
82
        if (page_size == 8*1024) {
83
            va &= ~(1ULL << (13 + tsb_size));
84
        } else if (page_size == 64*1024) {
85
            va |= (1ULL << (13 + tsb_size));
86
        }
87
        tsb_base_mask <<= 1;
88
    }
89

    
90
    return ((tsb_base & tsb_base_mask) | (va & ~tsb_base_mask)) & ~0xfULL;
91
}
92

    
93
// Calculates tag target register value by reordering bits
94
// in tag access register
95
static uint64_t ultrasparc_tag_target(uint64_t tag_access_register)
96
{
97
    return ((tag_access_register & 0x1fff) << 48) | (tag_access_register >> 22);
98
}
99

    
100
static void replace_tlb_entry(SparcTLBEntry *tlb,
101
                              uint64_t tlb_tag, uint64_t tlb_tte,
102
                              CPUState *env1)
103
{
104
    target_ulong mask, size, va, offset;
105

    
106
    // flush page range if translation is valid
107
    if (TTE_IS_VALID(tlb->tte)) {
108

    
109
        mask = 0xffffffffffffe000ULL;
110
        mask <<= 3 * ((tlb->tte >> 61) & 3);
111
        size = ~mask + 1;
112

    
113
        va = tlb->tag & mask;
114

    
115
        for (offset = 0; offset < size; offset += TARGET_PAGE_SIZE) {
116
            tlb_flush_page(env1, va + offset);
117
        }
118
    }
119

    
120
    tlb->tag = tlb_tag;
121
    tlb->tte = tlb_tte;
122
}
123

    
124
static void demap_tlb(SparcTLBEntry *tlb, target_ulong demap_addr,
125
                      const char* strmmu, CPUState *env1)
126
{
127
    unsigned int i;
128
    target_ulong mask;
129
    uint64_t context;
130

    
131
    int is_demap_context = (demap_addr >> 6) & 1;
132

    
133
    // demap context
134
    switch ((demap_addr >> 4) & 3) {
135
    case 0: // primary
136
        context = env1->dmmu.mmu_primary_context;
137
        break;
138
    case 1: // secondary
139
        context = env1->dmmu.mmu_secondary_context;
140
        break;
141
    case 2: // nucleus
142
        context = 0;
143
        break;
144
    case 3: // reserved
145
    default:
146
        return;
147
    }
148

    
149
    for (i = 0; i < 64; i++) {
150
        if (TTE_IS_VALID(tlb[i].tte)) {
151

    
152
            if (is_demap_context) {
153
                // will remove non-global entries matching context value
154
                if (TTE_IS_GLOBAL(tlb[i].tte) ||
155
                    !tlb_compare_context(&tlb[i], context)) {
156
                    continue;
157
                }
158
            } else {
159
                // demap page
160
                // will remove any entry matching VA
161
                mask = 0xffffffffffffe000ULL;
162
                mask <<= 3 * ((tlb[i].tte >> 61) & 3);
163

    
164
                if (!compare_masked(demap_addr, tlb[i].tag, mask)) {
165
                    continue;
166
                }
167

    
168
                // entry should be global or matching context value
169
                if (!TTE_IS_GLOBAL(tlb[i].tte) &&
170
                    !tlb_compare_context(&tlb[i], context)) {
171
                    continue;
172
                }
173
            }
174

    
175
            replace_tlb_entry(&tlb[i], 0, 0, env1);
176
#ifdef DEBUG_MMU
177
            DPRINTF_MMU("%s demap invalidated entry [%02u]\n", strmmu, i);
178
            dump_mmu(env1);
179
#endif
180
        }
181
    }
182
}
183

    
184
static void replace_tlb_1bit_lru(SparcTLBEntry *tlb,
185
                                 uint64_t tlb_tag, uint64_t tlb_tte,
186
                                 const char* strmmu, CPUState *env1)
187
{
188
    unsigned int i, replace_used;
189

    
190
    // Try replacing invalid entry
191
    for (i = 0; i < 64; i++) {
192
        if (!TTE_IS_VALID(tlb[i].tte)) {
193
            replace_tlb_entry(&tlb[i], tlb_tag, tlb_tte, env1);
194
#ifdef DEBUG_MMU
195
            DPRINTF_MMU("%s lru replaced invalid entry [%i]\n", strmmu, i);
196
            dump_mmu(env1);
197
#endif
198
            return;
199
        }
200
    }
201

    
202
    // All entries are valid, try replacing unlocked entry
203

    
204
    for (replace_used = 0; replace_used < 2; ++replace_used) {
205

    
206
        // Used entries are not replaced on first pass
207

    
208
        for (i = 0; i < 64; i++) {
209
            if (!TTE_IS_LOCKED(tlb[i].tte) && !TTE_IS_USED(tlb[i].tte)) {
210

    
211
                replace_tlb_entry(&tlb[i], tlb_tag, tlb_tte, env1);
212
#ifdef DEBUG_MMU
213
                DPRINTF_MMU("%s lru replaced unlocked %s entry [%i]\n",
214
                            strmmu, (replace_used?"used":"unused"), i);
215
                dump_mmu(env1);
216
#endif
217
                return;
218
            }
219
        }
220

    
221
        // Now reset used bit and search for unused entries again
222

    
223
        for (i = 0; i < 64; i++) {
224
            TTE_SET_UNUSED(tlb[i].tte);
225
        }
226
    }
227

    
228
#ifdef DEBUG_MMU
229
    DPRINTF_MMU("%s lru replacement failed: no entries available\n", strmmu);
230
#endif
231
    // error state?
232
}
233

    
234
#endif
235

    
236
static inline target_ulong address_mask(CPUState *env1, target_ulong addr)
237
{
238
#ifdef TARGET_SPARC64
239
    if (AM_CHECK(env1))
240
        addr &= 0xffffffffULL;
241
#endif
242
    return addr;
243
}
244

    
245
static void raise_exception(int tt)
246
{
247
    env->exception_index = tt;
248
    cpu_loop_exit();
249
}
250

    
251
void HELPER(raise_exception)(int tt)
252
{
253
    raise_exception(tt);
254
}
255

    
256
void helper_check_align(target_ulong addr, uint32_t align)
257
{
258
    if (addr & align) {
259
#ifdef DEBUG_UNALIGNED
260
    printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
261
           "\n", addr, env->pc);
262
#endif
263
        raise_exception(TT_UNALIGNED);
264
    }
265
}
266

    
267
#define F_HELPER(name, p) void helper_f##name##p(void)
268

    
269
#define F_BINOP(name)                                           \
270
    float32 helper_f ## name ## s (float32 src1, float32 src2)  \
271
    {                                                           \
272
        return float32_ ## name (src1, src2, &env->fp_status);  \
273
    }                                                           \
274
    F_HELPER(name, d)                                           \
275
    {                                                           \
276
        DT0 = float64_ ## name (DT0, DT1, &env->fp_status);     \
277
    }                                                           \
278
    F_HELPER(name, q)                                           \
279
    {                                                           \
280
        QT0 = float128_ ## name (QT0, QT1, &env->fp_status);    \
281
    }
282

    
283
F_BINOP(add);
284
F_BINOP(sub);
285
F_BINOP(mul);
286
F_BINOP(div);
287
#undef F_BINOP
288

    
289
void helper_fsmuld(float32 src1, float32 src2)
290
{
291
    DT0 = float64_mul(float32_to_float64(src1, &env->fp_status),
292
                      float32_to_float64(src2, &env->fp_status),
293
                      &env->fp_status);
294
}
295

    
296
void helper_fdmulq(void)
297
{
298
    QT0 = float128_mul(float64_to_float128(DT0, &env->fp_status),
299
                       float64_to_float128(DT1, &env->fp_status),
300
                       &env->fp_status);
301
}
302

    
303
float32 helper_fnegs(float32 src)
304
{
305
    return float32_chs(src);
306
}
307

    
308
#ifdef TARGET_SPARC64
309
F_HELPER(neg, d)
310
{
311
    DT0 = float64_chs(DT1);
312
}
313

    
314
F_HELPER(neg, q)
315
{
316
    QT0 = float128_chs(QT1);
317
}
318
#endif
319

    
320
/* Integer to float conversion.  */
321
float32 helper_fitos(int32_t src)
322
{
323
    return int32_to_float32(src, &env->fp_status);
324
}
325

    
326
void helper_fitod(int32_t src)
327
{
328
    DT0 = int32_to_float64(src, &env->fp_status);
329
}
330

    
331
void helper_fitoq(int32_t src)
332
{
333
    QT0 = int32_to_float128(src, &env->fp_status);
334
}
335

    
336
#ifdef TARGET_SPARC64
337
float32 helper_fxtos(void)
338
{
339
    return int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
340
}
341

    
342
F_HELPER(xto, d)
343
{
344
    DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
345
}
346

    
347
F_HELPER(xto, q)
348
{
349
    QT0 = int64_to_float128(*((int64_t *)&DT1), &env->fp_status);
350
}
351
#endif
352
#undef F_HELPER
353

    
354
/* floating point conversion */
355
float32 helper_fdtos(void)
356
{
357
    return float64_to_float32(DT1, &env->fp_status);
358
}
359

    
360
void helper_fstod(float32 src)
361
{
362
    DT0 = float32_to_float64(src, &env->fp_status);
363
}
364

    
365
float32 helper_fqtos(void)
366
{
367
    return float128_to_float32(QT1, &env->fp_status);
368
}
369

    
370
void helper_fstoq(float32 src)
371
{
372
    QT0 = float32_to_float128(src, &env->fp_status);
373
}
374

    
375
void helper_fqtod(void)
376
{
377
    DT0 = float128_to_float64(QT1, &env->fp_status);
378
}
379

    
380
void helper_fdtoq(void)
381
{
382
    QT0 = float64_to_float128(DT1, &env->fp_status);
383
}
384

    
385
/* Float to integer conversion.  */
386
int32_t helper_fstoi(float32 src)
387
{
388
    return float32_to_int32_round_to_zero(src, &env->fp_status);
389
}
390

    
391
int32_t helper_fdtoi(void)
392
{
393
    return float64_to_int32_round_to_zero(DT1, &env->fp_status);
394
}
395

    
396
int32_t helper_fqtoi(void)
397
{
398
    return float128_to_int32_round_to_zero(QT1, &env->fp_status);
399
}
400

    
401
#ifdef TARGET_SPARC64
402
void helper_fstox(float32 src)
403
{
404
    *((int64_t *)&DT0) = float32_to_int64_round_to_zero(src, &env->fp_status);
405
}
406

    
407
void helper_fdtox(void)
408
{
409
    *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status);
410
}
411

    
412
void helper_fqtox(void)
413
{
414
    *((int64_t *)&DT0) = float128_to_int64_round_to_zero(QT1, &env->fp_status);
415
}
416

    
417
void helper_faligndata(void)
418
{
419
    uint64_t tmp;
420

    
421
    tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8);
422
    /* on many architectures a shift of 64 does nothing */
423
    if ((env->gsr & 7) != 0) {
424
        tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8);
425
    }
426
    *((uint64_t *)&DT0) = tmp;
427
}
428

    
429
#ifdef HOST_WORDS_BIGENDIAN
430
#define VIS_B64(n) b[7 - (n)]
431
#define VIS_W64(n) w[3 - (n)]
432
#define VIS_SW64(n) sw[3 - (n)]
433
#define VIS_L64(n) l[1 - (n)]
434
#define VIS_B32(n) b[3 - (n)]
435
#define VIS_W32(n) w[1 - (n)]
436
#else
437
#define VIS_B64(n) b[n]
438
#define VIS_W64(n) w[n]
439
#define VIS_SW64(n) sw[n]
440
#define VIS_L64(n) l[n]
441
#define VIS_B32(n) b[n]
442
#define VIS_W32(n) w[n]
443
#endif
444

    
445
typedef union {
446
    uint8_t b[8];
447
    uint16_t w[4];
448
    int16_t sw[4];
449
    uint32_t l[2];
450
    float64 d;
451
} vis64;
452

    
453
typedef union {
454
    uint8_t b[4];
455
    uint16_t w[2];
456
    uint32_t l;
457
    float32 f;
458
} vis32;
459

    
460
void helper_fpmerge(void)
461
{
462
    vis64 s, d;
463

    
464
    s.d = DT0;
465
    d.d = DT1;
466

    
467
    // Reverse calculation order to handle overlap
468
    d.VIS_B64(7) = s.VIS_B64(3);
469
    d.VIS_B64(6) = d.VIS_B64(3);
470
    d.VIS_B64(5) = s.VIS_B64(2);
471
    d.VIS_B64(4) = d.VIS_B64(2);
472
    d.VIS_B64(3) = s.VIS_B64(1);
473
    d.VIS_B64(2) = d.VIS_B64(1);
474
    d.VIS_B64(1) = s.VIS_B64(0);
475
    //d.VIS_B64(0) = d.VIS_B64(0);
476

    
477
    DT0 = d.d;
478
}
479

    
480
void helper_fmul8x16(void)
481
{
482
    vis64 s, d;
483
    uint32_t tmp;
484

    
485
    s.d = DT0;
486
    d.d = DT1;
487

    
488
#define PMUL(r)                                                 \
489
    tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r);       \
490
    if ((tmp & 0xff) > 0x7f)                                    \
491
        tmp += 0x100;                                           \
492
    d.VIS_W64(r) = tmp >> 8;
493

    
494
    PMUL(0);
495
    PMUL(1);
496
    PMUL(2);
497
    PMUL(3);
498
#undef PMUL
499

    
500
    DT0 = d.d;
501
}
502

    
503
void helper_fmul8x16al(void)
504
{
505
    vis64 s, d;
506
    uint32_t tmp;
507

    
508
    s.d = DT0;
509
    d.d = DT1;
510

    
511
#define PMUL(r)                                                 \
512
    tmp = (int32_t)d.VIS_SW64(1) * (int32_t)s.VIS_B64(r);       \
513
    if ((tmp & 0xff) > 0x7f)                                    \
514
        tmp += 0x100;                                           \
515
    d.VIS_W64(r) = tmp >> 8;
516

    
517
    PMUL(0);
518
    PMUL(1);
519
    PMUL(2);
520
    PMUL(3);
521
#undef PMUL
522

    
523
    DT0 = d.d;
524
}
525

    
526
void helper_fmul8x16au(void)
527
{
528
    vis64 s, d;
529
    uint32_t tmp;
530

    
531
    s.d = DT0;
532
    d.d = DT1;
533

    
534
#define PMUL(r)                                                 \
535
    tmp = (int32_t)d.VIS_SW64(0) * (int32_t)s.VIS_B64(r);       \
536
    if ((tmp & 0xff) > 0x7f)                                    \
537
        tmp += 0x100;                                           \
538
    d.VIS_W64(r) = tmp >> 8;
539

    
540
    PMUL(0);
541
    PMUL(1);
542
    PMUL(2);
543
    PMUL(3);
544
#undef PMUL
545

    
546
    DT0 = d.d;
547
}
548

    
549
void helper_fmul8sux16(void)
550
{
551
    vis64 s, d;
552
    uint32_t tmp;
553

    
554
    s.d = DT0;
555
    d.d = DT1;
556

    
557
#define PMUL(r)                                                         \
558
    tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
559
    if ((tmp & 0xff) > 0x7f)                                            \
560
        tmp += 0x100;                                                   \
561
    d.VIS_W64(r) = tmp >> 8;
562

    
563
    PMUL(0);
564
    PMUL(1);
565
    PMUL(2);
566
    PMUL(3);
567
#undef PMUL
568

    
569
    DT0 = d.d;
570
}
571

    
572
void helper_fmul8ulx16(void)
573
{
574
    vis64 s, d;
575
    uint32_t tmp;
576

    
577
    s.d = DT0;
578
    d.d = DT1;
579

    
580
#define PMUL(r)                                                         \
581
    tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
582
    if ((tmp & 0xff) > 0x7f)                                            \
583
        tmp += 0x100;                                                   \
584
    d.VIS_W64(r) = tmp >> 8;
585

    
586
    PMUL(0);
587
    PMUL(1);
588
    PMUL(2);
589
    PMUL(3);
590
#undef PMUL
591

    
592
    DT0 = d.d;
593
}
594

    
595
void helper_fmuld8sux16(void)
596
{
597
    vis64 s, d;
598
    uint32_t tmp;
599

    
600
    s.d = DT0;
601
    d.d = DT1;
602

    
603
#define PMUL(r)                                                         \
604
    tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
605
    if ((tmp & 0xff) > 0x7f)                                            \
606
        tmp += 0x100;                                                   \
607
    d.VIS_L64(r) = tmp;
608

    
609
    // Reverse calculation order to handle overlap
610
    PMUL(1);
611
    PMUL(0);
612
#undef PMUL
613

    
614
    DT0 = d.d;
615
}
616

    
617
void helper_fmuld8ulx16(void)
618
{
619
    vis64 s, d;
620
    uint32_t tmp;
621

    
622
    s.d = DT0;
623
    d.d = DT1;
624

    
625
#define PMUL(r)                                                         \
626
    tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
627
    if ((tmp & 0xff) > 0x7f)                                            \
628
        tmp += 0x100;                                                   \
629
    d.VIS_L64(r) = tmp;
630

    
631
    // Reverse calculation order to handle overlap
632
    PMUL(1);
633
    PMUL(0);
634
#undef PMUL
635

    
636
    DT0 = d.d;
637
}
638

    
639
void helper_fexpand(void)
640
{
641
    vis32 s;
642
    vis64 d;
643

    
644
    s.l = (uint32_t)(*(uint64_t *)&DT0 & 0xffffffff);
645
    d.d = DT1;
646
    d.VIS_W64(0) = s.VIS_B32(0) << 4;
647
    d.VIS_W64(1) = s.VIS_B32(1) << 4;
648
    d.VIS_W64(2) = s.VIS_B32(2) << 4;
649
    d.VIS_W64(3) = s.VIS_B32(3) << 4;
650

    
651
    DT0 = d.d;
652
}
653

    
654
#define VIS_HELPER(name, F)                             \
655
    void name##16(void)                                 \
656
    {                                                   \
657
        vis64 s, d;                                     \
658
                                                        \
659
        s.d = DT0;                                      \
660
        d.d = DT1;                                      \
661
                                                        \
662
        d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0));   \
663
        d.VIS_W64(1) = F(d.VIS_W64(1), s.VIS_W64(1));   \
664
        d.VIS_W64(2) = F(d.VIS_W64(2), s.VIS_W64(2));   \
665
        d.VIS_W64(3) = F(d.VIS_W64(3), s.VIS_W64(3));   \
666
                                                        \
667
        DT0 = d.d;                                      \
668
    }                                                   \
669
                                                        \
670
    uint32_t name##16s(uint32_t src1, uint32_t src2)    \
671
    {                                                   \
672
        vis32 s, d;                                     \
673
                                                        \
674
        s.l = src1;                                     \
675
        d.l = src2;                                     \
676
                                                        \
677
        d.VIS_W32(0) = F(d.VIS_W32(0), s.VIS_W32(0));   \
678
        d.VIS_W32(1) = F(d.VIS_W32(1), s.VIS_W32(1));   \
679
                                                        \
680
        return d.l;                                     \
681
    }                                                   \
682
                                                        \
683
    void name##32(void)                                 \
684
    {                                                   \
685
        vis64 s, d;                                     \
686
                                                        \
687
        s.d = DT0;                                      \
688
        d.d = DT1;                                      \
689
                                                        \
690
        d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0));   \
691
        d.VIS_L64(1) = F(d.VIS_L64(1), s.VIS_L64(1));   \
692
                                                        \
693
        DT0 = d.d;                                      \
694
    }                                                   \
695
                                                        \
696
    uint32_t name##32s(uint32_t src1, uint32_t src2)    \
697
    {                                                   \
698
        vis32 s, d;                                     \
699
                                                        \
700
        s.l = src1;                                     \
701
        d.l = src2;                                     \
702
                                                        \
703
        d.l = F(d.l, s.l);                              \
704
                                                        \
705
        return d.l;                                     \
706
    }
707

    
708
#define FADD(a, b) ((a) + (b))
709
#define FSUB(a, b) ((a) - (b))
710
VIS_HELPER(helper_fpadd, FADD)
711
VIS_HELPER(helper_fpsub, FSUB)
712

    
713
#define VIS_CMPHELPER(name, F)                                        \
714
    void name##16(void)                                           \
715
    {                                                             \
716
        vis64 s, d;                                               \
717
                                                                  \
718
        s.d = DT0;                                                \
719
        d.d = DT1;                                                \
720
                                                                  \
721
        d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0))? 1: 0;       \
722
        d.VIS_W64(0) |= F(d.VIS_W64(1), s.VIS_W64(1))? 2: 0;      \
723
        d.VIS_W64(0) |= F(d.VIS_W64(2), s.VIS_W64(2))? 4: 0;      \
724
        d.VIS_W64(0) |= F(d.VIS_W64(3), s.VIS_W64(3))? 8: 0;      \
725
                                                                  \
726
        DT0 = d.d;                                                \
727
    }                                                             \
728
                                                                  \
729
    void name##32(void)                                           \
730
    {                                                             \
731
        vis64 s, d;                                               \
732
                                                                  \
733
        s.d = DT0;                                                \
734
        d.d = DT1;                                                \
735
                                                                  \
736
        d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0))? 1: 0;       \
737
        d.VIS_L64(0) |= F(d.VIS_L64(1), s.VIS_L64(1))? 2: 0;      \
738
                                                                  \
739
        DT0 = d.d;                                                \
740
    }
741

    
742
#define FCMPGT(a, b) ((a) > (b))
743
#define FCMPEQ(a, b) ((a) == (b))
744
#define FCMPLE(a, b) ((a) <= (b))
745
#define FCMPNE(a, b) ((a) != (b))
746

    
747
VIS_CMPHELPER(helper_fcmpgt, FCMPGT)
748
VIS_CMPHELPER(helper_fcmpeq, FCMPEQ)
749
VIS_CMPHELPER(helper_fcmple, FCMPLE)
750
VIS_CMPHELPER(helper_fcmpne, FCMPNE)
751
#endif
752

    
753
void helper_check_ieee_exceptions(void)
754
{
755
    target_ulong status;
756

    
757
    status = get_float_exception_flags(&env->fp_status);
758
    if (status) {
759
        /* Copy IEEE 754 flags into FSR */
760
        if (status & float_flag_invalid)
761
            env->fsr |= FSR_NVC;
762
        if (status & float_flag_overflow)
763
            env->fsr |= FSR_OFC;
764
        if (status & float_flag_underflow)
765
            env->fsr |= FSR_UFC;
766
        if (status & float_flag_divbyzero)
767
            env->fsr |= FSR_DZC;
768
        if (status & float_flag_inexact)
769
            env->fsr |= FSR_NXC;
770

    
771
        if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) {
772
            /* Unmasked exception, generate a trap */
773
            env->fsr |= FSR_FTT_IEEE_EXCP;
774
            raise_exception(TT_FP_EXCP);
775
        } else {
776
            /* Accumulate exceptions */
777
            env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
778
        }
779
    }
780
}
781

    
782
void helper_clear_float_exceptions(void)
783
{
784
    set_float_exception_flags(0, &env->fp_status);
785
}
786

    
787
float32 helper_fabss(float32 src)
788
{
789
    return float32_abs(src);
790
}
791

    
792
#ifdef TARGET_SPARC64
793
void helper_fabsd(void)
794
{
795
    DT0 = float64_abs(DT1);
796
}
797

    
798
void helper_fabsq(void)
799
{
800
    QT0 = float128_abs(QT1);
801
}
802
#endif
803

    
804
float32 helper_fsqrts(float32 src)
805
{
806
    return float32_sqrt(src, &env->fp_status);
807
}
808

    
809
void helper_fsqrtd(void)
810
{
811
    DT0 = float64_sqrt(DT1, &env->fp_status);
812
}
813

    
814
void helper_fsqrtq(void)
815
{
816
    QT0 = float128_sqrt(QT1, &env->fp_status);
817
}
818

    
819
#define GEN_FCMP(name, size, reg1, reg2, FS, TRAP)                      \
820
    void glue(helper_, name) (void)                                     \
821
    {                                                                   \
822
        target_ulong new_fsr;                                           \
823
                                                                        \
824
        env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                     \
825
        switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) {   \
826
        case float_relation_unordered:                                  \
827
            new_fsr = (FSR_FCC1 | FSR_FCC0) << FS;                      \
828
            if ((env->fsr & FSR_NVM) || TRAP) {                         \
829
                env->fsr |= new_fsr;                                    \
830
                env->fsr |= FSR_NVC;                                    \
831
                env->fsr |= FSR_FTT_IEEE_EXCP;                          \
832
                raise_exception(TT_FP_EXCP);                            \
833
            } else {                                                    \
834
                env->fsr |= FSR_NVA;                                    \
835
            }                                                           \
836
            break;                                                      \
837
        case float_relation_less:                                       \
838
            new_fsr = FSR_FCC0 << FS;                                   \
839
            break;                                                      \
840
        case float_relation_greater:                                    \
841
            new_fsr = FSR_FCC1 << FS;                                   \
842
            break;                                                      \
843
        default:                                                        \
844
            new_fsr = 0;                                                \
845
            break;                                                      \
846
        }                                                               \
847
        env->fsr |= new_fsr;                                            \
848
    }
849
#define GEN_FCMPS(name, size, FS, TRAP)                                 \
850
    void glue(helper_, name)(float32 src1, float32 src2)                \
851
    {                                                                   \
852
        target_ulong new_fsr;                                           \
853
                                                                        \
854
        env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                     \
855
        switch (glue(size, _compare) (src1, src2, &env->fp_status)) {   \
856
        case float_relation_unordered:                                  \
857
            new_fsr = (FSR_FCC1 | FSR_FCC0) << FS;                      \
858
            if ((env->fsr & FSR_NVM) || TRAP) {                         \
859
                env->fsr |= new_fsr;                                    \
860
                env->fsr |= FSR_NVC;                                    \
861
                env->fsr |= FSR_FTT_IEEE_EXCP;                          \
862
                raise_exception(TT_FP_EXCP);                            \
863
            } else {                                                    \
864
                env->fsr |= FSR_NVA;                                    \
865
            }                                                           \
866
            break;                                                      \
867
        case float_relation_less:                                       \
868
            new_fsr = FSR_FCC0 << FS;                                   \
869
            break;                                                      \
870
        case float_relation_greater:                                    \
871
            new_fsr = FSR_FCC1 << FS;                                   \
872
            break;                                                      \
873
        default:                                                        \
874
            new_fsr = 0;                                                \
875
            break;                                                      \
876
        }                                                               \
877
        env->fsr |= new_fsr;                                            \
878
    }
879

    
880
GEN_FCMPS(fcmps, float32, 0, 0);
881
GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
882

    
883
GEN_FCMPS(fcmpes, float32, 0, 1);
884
GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
885

    
886
GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0);
887
GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1);
888

    
889
static uint32_t compute_all_flags(void)
890
{
891
    return env->psr & PSR_ICC;
892
}
893

    
894
static uint32_t compute_C_flags(void)
895
{
896
    return env->psr & PSR_CARRY;
897
}
898

    
899
static inline uint32_t get_NZ_icc(target_ulong dst)
900
{
901
    uint32_t ret = 0;
902

    
903
    if (!(dst & 0xffffffffULL))
904
        ret |= PSR_ZERO;
905
    if ((int32_t) (dst & 0xffffffffULL) < 0)
906
        ret |= PSR_NEG;
907
    return ret;
908
}
909

    
910
#ifdef TARGET_SPARC64
911
static uint32_t compute_all_flags_xcc(void)
912
{
913
    return env->xcc & PSR_ICC;
914
}
915

    
916
static uint32_t compute_C_flags_xcc(void)
917
{
918
    return env->xcc & PSR_CARRY;
919
}
920

    
921
static inline uint32_t get_NZ_xcc(target_ulong dst)
922
{
923
    uint32_t ret = 0;
924

    
925
    if (!dst)
926
        ret |= PSR_ZERO;
927
    if ((int64_t)dst < 0)
928
        ret |= PSR_NEG;
929
    return ret;
930
}
931
#endif
932

    
933
static inline uint32_t get_V_div_icc(target_ulong src2)
934
{
935
    uint32_t ret = 0;
936

    
937
    if (src2 != 0)
938
        ret |= PSR_OVF;
939
    return ret;
940
}
941

    
942
static uint32_t compute_all_div(void)
943
{
944
    uint32_t ret;
945

    
946
    ret = get_NZ_icc(CC_DST);
947
    ret |= get_V_div_icc(CC_SRC2);
948
    return ret;
949
}
950

    
951
static uint32_t compute_C_div(void)
952
{
953
    return 0;
954
}
955

    
956
/* carry = (src1[31] & src2[31]) | ( ~dst[31] & (src1[31] | src2[31])) */
957
static inline uint32_t get_C_add_icc(target_ulong dst, target_ulong src1,
958
                                     target_ulong src2)
959
{
960
    uint32_t ret = 0;
961

    
962
    if (((src1 & (1ULL << 31)) & (src2 & (1ULL << 31)))
963
        | ((~(dst & (1ULL << 31)))
964
           & ((src1 & (1ULL << 31)) | (src2 & (1ULL << 31)))))
965
        ret |= PSR_CARRY;
966
    return ret;
967
}
968

    
969
static inline uint32_t get_V_add_icc(target_ulong dst, target_ulong src1,
970
                                         target_ulong src2)
971
{
972
    uint32_t ret = 0;
973

    
974
    if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1ULL << 31))
975
        ret |= PSR_OVF;
976
    return ret;
977
}
978

    
979
#ifdef TARGET_SPARC64
980
static inline uint32_t get_C_add_xcc(target_ulong dst, target_ulong src1)
981
{
982
    uint32_t ret = 0;
983

    
984
    if (dst < src1)
985
        ret |= PSR_CARRY;
986
    return ret;
987
}
988

    
989
static inline uint32_t get_V_add_xcc(target_ulong dst, target_ulong src1,
990
                                         target_ulong src2)
991
{
992
    uint32_t ret = 0;
993

    
994
    if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1ULL << 63))
995
        ret |= PSR_OVF;
996
    return ret;
997
}
998

    
999
static uint32_t compute_all_add_xcc(void)
1000
{
1001
    uint32_t ret;
1002

    
1003
    ret = get_NZ_xcc(CC_DST);
1004
    ret |= get_C_add_xcc(CC_DST, CC_SRC);
1005
    ret |= get_V_add_xcc(CC_DST, CC_SRC, CC_SRC2);
1006
    return ret;
1007
}
1008

    
1009
static uint32_t compute_C_add_xcc(void)
1010
{
1011
    return get_C_add_xcc(CC_DST, CC_SRC);
1012
}
1013
#endif
1014

    
1015
static uint32_t compute_all_add(void)
1016
{
1017
    uint32_t ret;
1018

    
1019
    ret = get_NZ_icc(CC_DST);
1020
    ret |= get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
1021
    ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
1022
    return ret;
1023
}
1024

    
1025
static uint32_t compute_C_add(void)
1026
{
1027
    return get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
1028
}
1029

    
1030
#ifdef TARGET_SPARC64
1031
static uint32_t compute_all_addx_xcc(void)
1032
{
1033
    uint32_t ret;
1034

    
1035
    ret = get_NZ_xcc(CC_DST);
1036
    ret |= get_C_add_xcc(CC_DST - CC_SRC2, CC_SRC);
1037
    ret |= get_C_add_xcc(CC_DST, CC_SRC);
1038
    ret |= get_V_add_xcc(CC_DST, CC_SRC, CC_SRC2);
1039
    return ret;
1040
}
1041

    
1042
static uint32_t compute_C_addx_xcc(void)
1043
{
1044
    uint32_t ret;
1045

    
1046
    ret = get_C_add_xcc(CC_DST - CC_SRC2, CC_SRC);
1047
    ret |= get_C_add_xcc(CC_DST, CC_SRC);
1048
    return ret;
1049
}
1050
#endif
1051

    
1052
static inline uint32_t get_V_tag_icc(target_ulong src1, target_ulong src2)
1053
{
1054
    uint32_t ret = 0;
1055

    
1056
    if ((src1 | src2) & 0x3)
1057
        ret |= PSR_OVF;
1058
    return ret;
1059
}
1060

    
1061
static uint32_t compute_all_tadd(void)
1062
{
1063
    uint32_t ret;
1064

    
1065
    ret = get_NZ_icc(CC_DST);
1066
    ret |= get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
1067
    ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
1068
    ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
1069
    return ret;
1070
}
1071

    
1072
static uint32_t compute_C_tadd(void)
1073
{
1074
    return get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
1075
}
1076

    
1077
static uint32_t compute_all_taddtv(void)
1078
{
1079
    uint32_t ret;
1080

    
1081
    ret = get_NZ_icc(CC_DST);
1082
    ret |= get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
1083
    return ret;
1084
}
1085

    
1086
static uint32_t compute_C_taddtv(void)
1087
{
1088
    return get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
1089
}
1090

    
1091
/* carry = (~src1[31] & src2[31]) | ( dst[31]  & (~src1[31] | src2[31])) */
1092
static inline uint32_t get_C_sub_icc(target_ulong dst, target_ulong src1,
1093
                                     target_ulong src2)
1094
{
1095
    uint32_t ret = 0;
1096

    
1097
    if (((~(src1 & (1ULL << 31))) & (src2 & (1ULL << 31)))
1098
        | ((dst & (1ULL << 31)) & (( ~(src1 & (1ULL << 31)))
1099
                                   | (src2 & (1ULL << 31)))))
1100
        ret |= PSR_CARRY;
1101
    return ret;
1102
}
1103

    
1104
static inline uint32_t get_V_sub_icc(target_ulong dst, target_ulong src1,
1105
                                     target_ulong src2)
1106
{
1107
    uint32_t ret = 0;
1108

    
1109
    if (((src1 ^ src2) & (src1 ^ dst)) & (1ULL << 31))
1110
        ret |= PSR_OVF;
1111
    return ret;
1112
}
1113

    
1114

    
1115
#ifdef TARGET_SPARC64
1116
static inline uint32_t get_C_sub_xcc(target_ulong src1, target_ulong src2)
1117
{
1118
    uint32_t ret = 0;
1119

    
1120
    if (src1 < src2)
1121
        ret |= PSR_CARRY;
1122
    return ret;
1123
}
1124

    
1125
static inline uint32_t get_V_sub_xcc(target_ulong dst, target_ulong src1,
1126
                                     target_ulong src2)
1127
{
1128
    uint32_t ret = 0;
1129

    
1130
    if (((src1 ^ src2) & (src1 ^ dst)) & (1ULL << 63))
1131
        ret |= PSR_OVF;
1132
    return ret;
1133
}
1134

    
1135
static uint32_t compute_all_sub_xcc(void)
1136
{
1137
    uint32_t ret;
1138

    
1139
    ret = get_NZ_xcc(CC_DST);
1140
    ret |= get_C_sub_xcc(CC_SRC, CC_SRC2);
1141
    ret |= get_V_sub_xcc(CC_DST, CC_SRC, CC_SRC2);
1142
    return ret;
1143
}
1144

    
1145
static uint32_t compute_C_sub_xcc(void)
1146
{
1147
    return get_C_sub_xcc(CC_SRC, CC_SRC2);
1148
}
1149
#endif
1150

    
1151
static uint32_t compute_all_sub(void)
1152
{
1153
    uint32_t ret;
1154

    
1155
    ret = get_NZ_icc(CC_DST);
1156
    ret |= get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1157
    ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1158
    return ret;
1159
}
1160

    
1161
static uint32_t compute_C_sub(void)
1162
{
1163
    return get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1164
}
1165

    
1166
#ifdef TARGET_SPARC64
1167
static uint32_t compute_all_subx_xcc(void)
1168
{
1169
    uint32_t ret;
1170

    
1171
    ret = get_NZ_xcc(CC_DST);
1172
    ret |= get_C_sub_xcc(CC_DST - CC_SRC2, CC_SRC);
1173
    ret |= get_C_sub_xcc(CC_DST, CC_SRC2);
1174
    ret |= get_V_sub_xcc(CC_DST, CC_SRC, CC_SRC2);
1175
    return ret;
1176
}
1177

    
1178
static uint32_t compute_C_subx_xcc(void)
1179
{
1180
    uint32_t ret;
1181

    
1182
    ret = get_C_sub_xcc(CC_DST - CC_SRC2, CC_SRC);
1183
    ret |= get_C_sub_xcc(CC_DST, CC_SRC2);
1184
    return ret;
1185
}
1186
#endif
1187

    
1188
static uint32_t compute_all_tsub(void)
1189
{
1190
    uint32_t ret;
1191

    
1192
    ret = get_NZ_icc(CC_DST);
1193
    ret |= get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1194
    ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1195
    ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
1196
    return ret;
1197
}
1198

    
1199
static uint32_t compute_C_tsub(void)
1200
{
1201
    return get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1202
}
1203

    
1204
static uint32_t compute_all_tsubtv(void)
1205
{
1206
    uint32_t ret;
1207

    
1208
    ret = get_NZ_icc(CC_DST);
1209
    ret |= get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1210
    return ret;
1211
}
1212

    
1213
static uint32_t compute_C_tsubtv(void)
1214
{
1215
    return get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1216
}
1217

    
1218
static uint32_t compute_all_logic(void)
1219
{
1220
    return get_NZ_icc(CC_DST);
1221
}
1222

    
1223
static uint32_t compute_C_logic(void)
1224
{
1225
    return 0;
1226
}
1227

    
1228
#ifdef TARGET_SPARC64
1229
static uint32_t compute_all_logic_xcc(void)
1230
{
1231
    return get_NZ_xcc(CC_DST);
1232
}
1233
#endif
1234

    
1235
typedef struct CCTable {
1236
    uint32_t (*compute_all)(void); /* return all the flags */
1237
    uint32_t (*compute_c)(void);  /* return the C flag */
1238
} CCTable;
1239

    
1240
static const CCTable icc_table[CC_OP_NB] = {
1241
    /* CC_OP_DYNAMIC should never happen */
1242
    [CC_OP_FLAGS] = { compute_all_flags, compute_C_flags },
1243
    [CC_OP_DIV] = { compute_all_div, compute_C_div },
1244
    [CC_OP_ADD] = { compute_all_add, compute_C_add },
1245
    [CC_OP_ADDX] = { compute_all_add, compute_C_add },
1246
    [CC_OP_TADD] = { compute_all_tadd, compute_C_tadd },
1247
    [CC_OP_TADDTV] = { compute_all_taddtv, compute_C_taddtv },
1248
    [CC_OP_SUB] = { compute_all_sub, compute_C_sub },
1249
    [CC_OP_SUBX] = { compute_all_sub, compute_C_sub },
1250
    [CC_OP_TSUB] = { compute_all_tsub, compute_C_tsub },
1251
    [CC_OP_TSUBTV] = { compute_all_tsubtv, compute_C_tsubtv },
1252
    [CC_OP_LOGIC] = { compute_all_logic, compute_C_logic },
1253
};
1254

    
1255
#ifdef TARGET_SPARC64
1256
static const CCTable xcc_table[CC_OP_NB] = {
1257
    /* CC_OP_DYNAMIC should never happen */
1258
    [CC_OP_FLAGS] = { compute_all_flags_xcc, compute_C_flags_xcc },
1259
    [CC_OP_DIV] = { compute_all_logic_xcc, compute_C_logic },
1260
    [CC_OP_ADD] = { compute_all_add_xcc, compute_C_add_xcc },
1261
    [CC_OP_ADDX] = { compute_all_addx_xcc, compute_C_addx_xcc },
1262
    [CC_OP_TADD] = { compute_all_add_xcc, compute_C_add_xcc },
1263
    [CC_OP_TADDTV] = { compute_all_add_xcc, compute_C_add_xcc },
1264
    [CC_OP_SUB] = { compute_all_sub_xcc, compute_C_sub_xcc },
1265
    [CC_OP_SUBX] = { compute_all_subx_xcc, compute_C_subx_xcc },
1266
    [CC_OP_TSUB] = { compute_all_sub_xcc, compute_C_sub_xcc },
1267
    [CC_OP_TSUBTV] = { compute_all_sub_xcc, compute_C_sub_xcc },
1268
    [CC_OP_LOGIC] = { compute_all_logic_xcc, compute_C_logic },
1269
};
1270
#endif
1271

    
1272
void helper_compute_psr(void)
1273
{
1274
    uint32_t new_psr;
1275

    
1276
    new_psr = icc_table[CC_OP].compute_all();
1277
    env->psr = new_psr;
1278
#ifdef TARGET_SPARC64
1279
    new_psr = xcc_table[CC_OP].compute_all();
1280
    env->xcc = new_psr;
1281
#endif
1282
    CC_OP = CC_OP_FLAGS;
1283
}
1284

    
1285
uint32_t helper_compute_C_icc(void)
1286
{
1287
    uint32_t ret;
1288

    
1289
    ret = icc_table[CC_OP].compute_c() >> PSR_CARRY_SHIFT;
1290
    return ret;
1291
}
1292

    
1293
static inline void memcpy32(target_ulong *dst, const target_ulong *src)
1294
{
1295
    dst[0] = src[0];
1296
    dst[1] = src[1];
1297
    dst[2] = src[2];
1298
    dst[3] = src[3];
1299
    dst[4] = src[4];
1300
    dst[5] = src[5];
1301
    dst[6] = src[6];
1302
    dst[7] = src[7];
1303
}
1304

    
1305
static void set_cwp(int new_cwp)
1306
{
1307
    /* put the modified wrap registers at their proper location */
1308
    if (env->cwp == env->nwindows - 1) {
1309
        memcpy32(env->regbase, env->regbase + env->nwindows * 16);
1310
    }
1311
    env->cwp = new_cwp;
1312

    
1313
    /* put the wrap registers at their temporary location */
1314
    if (new_cwp == env->nwindows - 1) {
1315
        memcpy32(env->regbase + env->nwindows * 16, env->regbase);
1316
    }
1317
    env->regwptr = env->regbase + (new_cwp * 16);
1318
}
1319

    
1320
void cpu_set_cwp(CPUState *env1, int new_cwp)
1321
{
1322
    CPUState *saved_env;
1323

    
1324
    saved_env = env;
1325
    env = env1;
1326
    set_cwp(new_cwp);
1327
    env = saved_env;
1328
}
1329

    
1330
static target_ulong get_psr(void)
1331
{
1332
    helper_compute_psr();
1333

    
1334
#if !defined (TARGET_SPARC64)
1335
    return env->version | (env->psr & PSR_ICC) |
1336
        (env->psref? PSR_EF : 0) |
1337
        (env->psrpil << 8) |
1338
        (env->psrs? PSR_S : 0) |
1339
        (env->psrps? PSR_PS : 0) |
1340
        (env->psret? PSR_ET : 0) | env->cwp;
1341
#else
1342
    return env->version | (env->psr & PSR_ICC) |
1343
        (env->psref? PSR_EF : 0) |
1344
        (env->psrpil << 8) |
1345
        (env->psrs? PSR_S : 0) |
1346
        (env->psrps? PSR_PS : 0) | env->cwp;
1347
#endif
1348
}
1349

    
1350
target_ulong cpu_get_psr(CPUState *env1)
1351
{
1352
    CPUState *saved_env;
1353
    target_ulong ret;
1354

    
1355
    saved_env = env;
1356
    env = env1;
1357
    ret = get_psr();
1358
    env = saved_env;
1359
    return ret;
1360
}
1361

    
1362
static void put_psr(target_ulong val)
1363
{
1364
    env->psr = val & PSR_ICC;
1365
    env->psref = (val & PSR_EF)? 1 : 0;
1366
    env->psrpil = (val & PSR_PIL) >> 8;
1367
#if ((!defined (TARGET_SPARC64)) && !defined(CONFIG_USER_ONLY))
1368
    cpu_check_irqs(env);
1369
#endif
1370
    env->psrs = (val & PSR_S)? 1 : 0;
1371
    env->psrps = (val & PSR_PS)? 1 : 0;
1372
#if !defined (TARGET_SPARC64)
1373
    env->psret = (val & PSR_ET)? 1 : 0;
1374
#endif
1375
    set_cwp(val & PSR_CWP);
1376
    env->cc_op = CC_OP_FLAGS;
1377
}
1378

    
1379
void cpu_put_psr(CPUState *env1, target_ulong val)
1380
{
1381
    CPUState *saved_env;
1382

    
1383
    saved_env = env;
1384
    env = env1;
1385
    put_psr(val);
1386
    env = saved_env;
1387
}
1388

    
1389
static int cwp_inc(int cwp)
1390
{
1391
    if (unlikely(cwp >= env->nwindows)) {
1392
        cwp -= env->nwindows;
1393
    }
1394
    return cwp;
1395
}
1396

    
1397
int cpu_cwp_inc(CPUState *env1, int cwp)
1398
{
1399
    CPUState *saved_env;
1400
    target_ulong ret;
1401

    
1402
    saved_env = env;
1403
    env = env1;
1404
    ret = cwp_inc(cwp);
1405
    env = saved_env;
1406
    return ret;
1407
}
1408

    
1409
static int cwp_dec(int cwp)
1410
{
1411
    if (unlikely(cwp < 0)) {
1412
        cwp += env->nwindows;
1413
    }
1414
    return cwp;
1415
}
1416

    
1417
int cpu_cwp_dec(CPUState *env1, int cwp)
1418
{
1419
    CPUState *saved_env;
1420
    target_ulong ret;
1421

    
1422
    saved_env = env;
1423
    env = env1;
1424
    ret = cwp_dec(cwp);
1425
    env = saved_env;
1426
    return ret;
1427
}
1428

    
1429
#ifdef TARGET_SPARC64
1430
GEN_FCMPS(fcmps_fcc1, float32, 22, 0);
1431
GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
1432
GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0);
1433

    
1434
GEN_FCMPS(fcmps_fcc2, float32, 24, 0);
1435
GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
1436
GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0);
1437

    
1438
GEN_FCMPS(fcmps_fcc3, float32, 26, 0);
1439
GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
1440
GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0);
1441

    
1442
GEN_FCMPS(fcmpes_fcc1, float32, 22, 1);
1443
GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
1444
GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1);
1445

    
1446
GEN_FCMPS(fcmpes_fcc2, float32, 24, 1);
1447
GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
1448
GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1);
1449

    
1450
GEN_FCMPS(fcmpes_fcc3, float32, 26, 1);
1451
GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
1452
GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
1453
#endif
1454
#undef GEN_FCMPS
1455

    
1456
#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) && \
1457
    defined(DEBUG_MXCC)
1458
static void dump_mxcc(CPUState *env)
1459
{
1460
    printf("mxccdata: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64
1461
           "\n",
1462
           env->mxccdata[0], env->mxccdata[1],
1463
           env->mxccdata[2], env->mxccdata[3]);
1464
    printf("mxccregs: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64
1465
           "\n"
1466
           "          %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64
1467
           "\n",
1468
           env->mxccregs[0], env->mxccregs[1],
1469
           env->mxccregs[2], env->mxccregs[3],
1470
           env->mxccregs[4], env->mxccregs[5],
1471
           env->mxccregs[6], env->mxccregs[7]);
1472
}
1473
#endif
1474

    
1475
#if (defined(TARGET_SPARC64) || !defined(CONFIG_USER_ONLY)) \
1476
    && defined(DEBUG_ASI)
1477
static void dump_asi(const char *txt, target_ulong addr, int asi, int size,
1478
                     uint64_t r1)
1479
{
1480
    switch (size)
1481
    {
1482
    case 1:
1483
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %02" PRIx64 "\n", txt,
1484
                    addr, asi, r1 & 0xff);
1485
        break;
1486
    case 2:
1487
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %04" PRIx64 "\n", txt,
1488
                    addr, asi, r1 & 0xffff);
1489
        break;
1490
    case 4:
1491
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %08" PRIx64 "\n", txt,
1492
                    addr, asi, r1 & 0xffffffff);
1493
        break;
1494
    case 8:
1495
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %016" PRIx64 "\n", txt,
1496
                    addr, asi, r1);
1497
        break;
1498
    }
1499
}
1500
#endif
1501

    
1502
#ifndef TARGET_SPARC64
1503
#ifndef CONFIG_USER_ONLY
1504
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1505
{
1506
    uint64_t ret = 0;
1507
#if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
1508
    uint32_t last_addr = addr;
1509
#endif
1510

    
1511
    helper_check_align(addr, size - 1);
1512
    switch (asi) {
1513
    case 2: /* SuperSparc MXCC registers */
1514
        switch (addr) {
1515
        case 0x01c00a00: /* MXCC control register */
1516
            if (size == 8)
1517
                ret = env->mxccregs[3];
1518
            else
1519
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1520
                             size);
1521
            break;
1522
        case 0x01c00a04: /* MXCC control register */
1523
            if (size == 4)
1524
                ret = env->mxccregs[3];
1525
            else
1526
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1527
                             size);
1528
            break;
1529
        case 0x01c00c00: /* Module reset register */
1530
            if (size == 8) {
1531
                ret = env->mxccregs[5];
1532
                // should we do something here?
1533
            } else
1534
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1535
                             size);
1536
            break;
1537
        case 0x01c00f00: /* MBus port address register */
1538
            if (size == 8)
1539
                ret = env->mxccregs[7];
1540
            else
1541
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1542
                             size);
1543
            break;
1544
        default:
1545
            DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr,
1546
                         size);
1547
            break;
1548
        }
1549
        DPRINTF_MXCC("asi = %d, size = %d, sign = %d, "
1550
                     "addr = %08x -> ret = %" PRIx64 ","
1551
                     "addr = %08x\n", asi, size, sign, last_addr, ret, addr);
1552
#ifdef DEBUG_MXCC
1553
        dump_mxcc(env);
1554
#endif
1555
        break;
1556
    case 3: /* MMU probe */
1557
        {
1558
            int mmulev;
1559

    
1560
            mmulev = (addr >> 8) & 15;
1561
            if (mmulev > 4)
1562
                ret = 0;
1563
            else
1564
                ret = mmu_probe(env, addr, mmulev);
1565
            DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08" PRIx64 "\n",
1566
                        addr, mmulev, ret);
1567
        }
1568
        break;
1569
    case 4: /* read MMU regs */
1570
        {
1571
            int reg = (addr >> 8) & 0x1f;
1572

    
1573
            ret = env->mmuregs[reg];
1574
            if (reg == 3) /* Fault status cleared on read */
1575
                env->mmuregs[3] = 0;
1576
            else if (reg == 0x13) /* Fault status read */
1577
                ret = env->mmuregs[3];
1578
            else if (reg == 0x14) /* Fault address read */
1579
                ret = env->mmuregs[4];
1580
            DPRINTF_MMU("mmu_read: reg[%d] = 0x%08" PRIx64 "\n", reg, ret);
1581
        }
1582
        break;
1583
    case 5: // Turbosparc ITLB Diagnostic
1584
    case 6: // Turbosparc DTLB Diagnostic
1585
    case 7: // Turbosparc IOTLB Diagnostic
1586
        break;
1587
    case 9: /* Supervisor code access */
1588
        switch(size) {
1589
        case 1:
1590
            ret = ldub_code(addr);
1591
            break;
1592
        case 2:
1593
            ret = lduw_code(addr);
1594
            break;
1595
        default:
1596
        case 4:
1597
            ret = ldl_code(addr);
1598
            break;
1599
        case 8:
1600
            ret = ldq_code(addr);
1601
            break;
1602
        }
1603
        break;
1604
    case 0xa: /* User data access */
1605
        switch(size) {
1606
        case 1:
1607
            ret = ldub_user(addr);
1608
            break;
1609
        case 2:
1610
            ret = lduw_user(addr);
1611
            break;
1612
        default:
1613
        case 4:
1614
            ret = ldl_user(addr);
1615
            break;
1616
        case 8:
1617
            ret = ldq_user(addr);
1618
            break;
1619
        }
1620
        break;
1621
    case 0xb: /* Supervisor data access */
1622
        switch(size) {
1623
        case 1:
1624
            ret = ldub_kernel(addr);
1625
            break;
1626
        case 2:
1627
            ret = lduw_kernel(addr);
1628
            break;
1629
        default:
1630
        case 4:
1631
            ret = ldl_kernel(addr);
1632
            break;
1633
        case 8:
1634
            ret = ldq_kernel(addr);
1635
            break;
1636
        }
1637
        break;
1638
    case 0xc: /* I-cache tag */
1639
    case 0xd: /* I-cache data */
1640
    case 0xe: /* D-cache tag */
1641
    case 0xf: /* D-cache data */
1642
        break;
1643
    case 0x20: /* MMU passthrough */
1644
        switch(size) {
1645
        case 1:
1646
            ret = ldub_phys(addr);
1647
            break;
1648
        case 2:
1649
            ret = lduw_phys(addr);
1650
            break;
1651
        default:
1652
        case 4:
1653
            ret = ldl_phys(addr);
1654
            break;
1655
        case 8:
1656
            ret = ldq_phys(addr);
1657
            break;
1658
        }
1659
        break;
1660
    case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
1661
        switch(size) {
1662
        case 1:
1663
            ret = ldub_phys((target_phys_addr_t)addr
1664
                            | ((target_phys_addr_t)(asi & 0xf) << 32));
1665
            break;
1666
        case 2:
1667
            ret = lduw_phys((target_phys_addr_t)addr
1668
                            | ((target_phys_addr_t)(asi & 0xf) << 32));
1669
            break;
1670
        default:
1671
        case 4:
1672
            ret = ldl_phys((target_phys_addr_t)addr
1673
                           | ((target_phys_addr_t)(asi & 0xf) << 32));
1674
            break;
1675
        case 8:
1676
            ret = ldq_phys((target_phys_addr_t)addr
1677
                           | ((target_phys_addr_t)(asi & 0xf) << 32));
1678
            break;
1679
        }
1680
        break;
1681
    case 0x30: // Turbosparc secondary cache diagnostic
1682
    case 0x31: // Turbosparc RAM snoop
1683
    case 0x32: // Turbosparc page table descriptor diagnostic
1684
    case 0x39: /* data cache diagnostic register */
1685
        ret = 0;
1686
        break;
1687
    case 0x38: /* SuperSPARC MMU Breakpoint Control Registers */
1688
        {
1689
            int reg = (addr >> 8) & 3;
1690

    
1691
            switch(reg) {
1692
            case 0: /* Breakpoint Value (Addr) */
1693
                ret = env->mmubpregs[reg];
1694
                break;
1695
            case 1: /* Breakpoint Mask */
1696
                ret = env->mmubpregs[reg];
1697
                break;
1698
            case 2: /* Breakpoint Control */
1699
                ret = env->mmubpregs[reg];
1700
                break;
1701
            case 3: /* Breakpoint Status */
1702
                ret = env->mmubpregs[reg];
1703
                env->mmubpregs[reg] = 0ULL;
1704
                break;
1705
            }
1706
            DPRINTF_MMU("read breakpoint reg[%d] 0x%016" PRIx64 "\n", reg,
1707
                        ret);
1708
        }
1709
        break;
1710
    case 8: /* User code access, XXX */
1711
    default:
1712
        do_unassigned_access(addr, 0, 0, asi, size);
1713
        ret = 0;
1714
        break;
1715
    }
1716
    if (sign) {
1717
        switch(size) {
1718
        case 1:
1719
            ret = (int8_t) ret;
1720
            break;
1721
        case 2:
1722
            ret = (int16_t) ret;
1723
            break;
1724
        case 4:
1725
            ret = (int32_t) ret;
1726
            break;
1727
        default:
1728
            break;
1729
        }
1730
    }
1731
#ifdef DEBUG_ASI
1732
    dump_asi("read ", last_addr, asi, size, ret);
1733
#endif
1734
    return ret;
1735
}
1736

    
1737
void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
1738
{
1739
    helper_check_align(addr, size - 1);
1740
    switch(asi) {
1741
    case 2: /* SuperSparc MXCC registers */
1742
        switch (addr) {
1743
        case 0x01c00000: /* MXCC stream data register 0 */
1744
            if (size == 8)
1745
                env->mxccdata[0] = val;
1746
            else
1747
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1748
                             size);
1749
            break;
1750
        case 0x01c00008: /* MXCC stream data register 1 */
1751
            if (size == 8)
1752
                env->mxccdata[1] = val;
1753
            else
1754
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1755
                             size);
1756
            break;
1757
        case 0x01c00010: /* MXCC stream data register 2 */
1758
            if (size == 8)
1759
                env->mxccdata[2] = val;
1760
            else
1761
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1762
                             size);
1763
            break;
1764
        case 0x01c00018: /* MXCC stream data register 3 */
1765
            if (size == 8)
1766
                env->mxccdata[3] = val;
1767
            else
1768
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1769
                             size);
1770
            break;
1771
        case 0x01c00100: /* MXCC stream source */
1772
            if (size == 8)
1773
                env->mxccregs[0] = val;
1774
            else
1775
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1776
                             size);
1777
            env->mxccdata[0] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1778
                                        0);
1779
            env->mxccdata[1] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1780
                                        8);
1781
            env->mxccdata[2] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1782
                                        16);
1783
            env->mxccdata[3] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1784
                                        24);
1785
            break;
1786
        case 0x01c00200: /* MXCC stream destination */
1787
            if (size == 8)
1788
                env->mxccregs[1] = val;
1789
            else
1790
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1791
                             size);
1792
            stq_phys((env->mxccregs[1] & 0xffffffffULL) +  0,
1793
                     env->mxccdata[0]);
1794
            stq_phys((env->mxccregs[1] & 0xffffffffULL) +  8,
1795
                     env->mxccdata[1]);
1796
            stq_phys((env->mxccregs[1] & 0xffffffffULL) + 16,
1797
                     env->mxccdata[2]);
1798
            stq_phys((env->mxccregs[1] & 0xffffffffULL) + 24,
1799
                     env->mxccdata[3]);
1800
            break;
1801
        case 0x01c00a00: /* MXCC control register */
1802
            if (size == 8)
1803
                env->mxccregs[3] = val;
1804
            else
1805
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1806
                             size);
1807
            break;
1808
        case 0x01c00a04: /* MXCC control register */
1809
            if (size == 4)
1810
                env->mxccregs[3] = (env->mxccregs[3] & 0xffffffff00000000ULL)
1811
                    | val;
1812
            else
1813
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1814
                             size);
1815
            break;
1816
        case 0x01c00e00: /* MXCC error register  */
1817
            // writing a 1 bit clears the error
1818
            if (size == 8)
1819
                env->mxccregs[6] &= ~val;
1820
            else
1821
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1822
                             size);
1823
            break;
1824
        case 0x01c00f00: /* MBus port address register */
1825
            if (size == 8)
1826
                env->mxccregs[7] = val;
1827
            else
1828
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1829
                             size);
1830
            break;
1831
        default:
1832
            DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr,
1833
                         size);
1834
            break;
1835
        }
1836
        DPRINTF_MXCC("asi = %d, size = %d, addr = %08x, val = %" PRIx64 "\n",
1837
                     asi, size, addr, val);
1838
#ifdef DEBUG_MXCC
1839
        dump_mxcc(env);
1840
#endif
1841
        break;
1842
    case 3: /* MMU flush */
1843
        {
1844
            int mmulev;
1845

    
1846
            mmulev = (addr >> 8) & 15;
1847
            DPRINTF_MMU("mmu flush level %d\n", mmulev);
1848
            switch (mmulev) {
1849
            case 0: // flush page
1850
                tlb_flush_page(env, addr & 0xfffff000);
1851
                break;
1852
            case 1: // flush segment (256k)
1853
            case 2: // flush region (16M)
1854
            case 3: // flush context (4G)
1855
            case 4: // flush entire
1856
                tlb_flush(env, 1);
1857
                break;
1858
            default:
1859
                break;
1860
            }
1861
#ifdef DEBUG_MMU
1862
            dump_mmu(env);
1863
#endif
1864
        }
1865
        break;
1866
    case 4: /* write MMU regs */
1867
        {
1868
            int reg = (addr >> 8) & 0x1f;
1869
            uint32_t oldreg;
1870

    
1871
            oldreg = env->mmuregs[reg];
1872
            switch(reg) {
1873
            case 0: // Control Register
1874
                env->mmuregs[reg] = (env->mmuregs[reg] & 0xff000000) |
1875
                                    (val & 0x00ffffff);
1876
                // Mappings generated during no-fault mode or MMU
1877
                // disabled mode are invalid in normal mode
1878
                if ((oldreg & (MMU_E | MMU_NF | env->def->mmu_bm)) !=
1879
                    (env->mmuregs[reg] & (MMU_E | MMU_NF | env->def->mmu_bm)))
1880
                    tlb_flush(env, 1);
1881
                break;
1882
            case 1: // Context Table Pointer Register
1883
                env->mmuregs[reg] = val & env->def->mmu_ctpr_mask;
1884
                break;
1885
            case 2: // Context Register
1886
                env->mmuregs[reg] = val & env->def->mmu_cxr_mask;
1887
                if (oldreg != env->mmuregs[reg]) {
1888
                    /* we flush when the MMU context changes because
1889
                       QEMU has no MMU context support */
1890
                    tlb_flush(env, 1);
1891
                }
1892
                break;
1893
            case 3: // Synchronous Fault Status Register with Clear
1894
            case 4: // Synchronous Fault Address Register
1895
                break;
1896
            case 0x10: // TLB Replacement Control Register
1897
                env->mmuregs[reg] = val & env->def->mmu_trcr_mask;
1898
                break;
1899
            case 0x13: // Synchronous Fault Status Register with Read and Clear
1900
                env->mmuregs[3] = val & env->def->mmu_sfsr_mask;
1901
                break;
1902
            case 0x14: // Synchronous Fault Address Register
1903
                env->mmuregs[4] = val;
1904
                break;
1905
            default:
1906
                env->mmuregs[reg] = val;
1907
                break;
1908
            }
1909
            if (oldreg != env->mmuregs[reg]) {
1910
                DPRINTF_MMU("mmu change reg[%d]: 0x%08x -> 0x%08x\n",
1911
                            reg, oldreg, env->mmuregs[reg]);
1912
            }
1913
#ifdef DEBUG_MMU
1914
            dump_mmu(env);
1915
#endif
1916
        }
1917
        break;
1918
    case 5: // Turbosparc ITLB Diagnostic
1919
    case 6: // Turbosparc DTLB Diagnostic
1920
    case 7: // Turbosparc IOTLB Diagnostic
1921
        break;
1922
    case 0xa: /* User data access */
1923
        switch(size) {
1924
        case 1:
1925
            stb_user(addr, val);
1926
            break;
1927
        case 2:
1928
            stw_user(addr, val);
1929
            break;
1930
        default:
1931
        case 4:
1932
            stl_user(addr, val);
1933
            break;
1934
        case 8:
1935
            stq_user(addr, val);
1936
            break;
1937
        }
1938
        break;
1939
    case 0xb: /* Supervisor data access */
1940
        switch(size) {
1941
        case 1:
1942
            stb_kernel(addr, val);
1943
            break;
1944
        case 2:
1945
            stw_kernel(addr, val);
1946
            break;
1947
        default:
1948
        case 4:
1949
            stl_kernel(addr, val);
1950
            break;
1951
        case 8:
1952
            stq_kernel(addr, val);
1953
            break;
1954
        }
1955
        break;
1956
    case 0xc: /* I-cache tag */
1957
    case 0xd: /* I-cache data */
1958
    case 0xe: /* D-cache tag */
1959
    case 0xf: /* D-cache data */
1960
    case 0x10: /* I/D-cache flush page */
1961
    case 0x11: /* I/D-cache flush segment */
1962
    case 0x12: /* I/D-cache flush region */
1963
    case 0x13: /* I/D-cache flush context */
1964
    case 0x14: /* I/D-cache flush user */
1965
        break;
1966
    case 0x17: /* Block copy, sta access */
1967
        {
1968
            // val = src
1969
            // addr = dst
1970
            // copy 32 bytes
1971
            unsigned int i;
1972
            uint32_t src = val & ~3, dst = addr & ~3, temp;
1973

    
1974
            for (i = 0; i < 32; i += 4, src += 4, dst += 4) {
1975
                temp = ldl_kernel(src);
1976
                stl_kernel(dst, temp);
1977
            }
1978
        }
1979
        break;
1980
    case 0x1f: /* Block fill, stda access */
1981
        {
1982
            // addr = dst
1983
            // fill 32 bytes with val
1984
            unsigned int i;
1985
            uint32_t dst = addr & 7;
1986

    
1987
            for (i = 0; i < 32; i += 8, dst += 8)
1988
                stq_kernel(dst, val);
1989
        }
1990
        break;
1991
    case 0x20: /* MMU passthrough */
1992
        {
1993
            switch(size) {
1994
            case 1:
1995
                stb_phys(addr, val);
1996
                break;
1997
            case 2:
1998
                stw_phys(addr, val);
1999
                break;
2000
            case 4:
2001
            default:
2002
                stl_phys(addr, val);
2003
                break;
2004
            case 8:
2005
                stq_phys(addr, val);
2006
                break;
2007
            }
2008
        }
2009
        break;
2010
    case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
2011
        {
2012
            switch(size) {
2013
            case 1:
2014
                stb_phys((target_phys_addr_t)addr
2015
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
2016
                break;
2017
            case 2:
2018
                stw_phys((target_phys_addr_t)addr
2019
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
2020
                break;
2021
            case 4:
2022
            default:
2023
                stl_phys((target_phys_addr_t)addr
2024
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
2025
                break;
2026
            case 8:
2027
                stq_phys((target_phys_addr_t)addr
2028
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
2029
                break;
2030
            }
2031
        }
2032
        break;
2033
    case 0x30: // store buffer tags or Turbosparc secondary cache diagnostic
2034
    case 0x31: // store buffer data, Ross RT620 I-cache flush or
2035
               // Turbosparc snoop RAM
2036
    case 0x32: // store buffer control or Turbosparc page table
2037
               // descriptor diagnostic
2038
    case 0x36: /* I-cache flash clear */
2039
    case 0x37: /* D-cache flash clear */
2040
    case 0x4c: /* breakpoint action */
2041
        break;
2042
    case 0x38: /* SuperSPARC MMU Breakpoint Control Registers*/
2043
        {
2044
            int reg = (addr >> 8) & 3;
2045

    
2046
            switch(reg) {
2047
            case 0: /* Breakpoint Value (Addr) */
2048
                env->mmubpregs[reg] = (val & 0xfffffffffULL);
2049
                break;
2050
            case 1: /* Breakpoint Mask */
2051
                env->mmubpregs[reg] = (val & 0xfffffffffULL);
2052
                break;
2053
            case 2: /* Breakpoint Control */
2054
                env->mmubpregs[reg] = (val & 0x7fULL);
2055
                break;
2056
            case 3: /* Breakpoint Status */
2057
                env->mmubpregs[reg] = (val & 0xfULL);
2058
                break;
2059
            }
2060
            DPRINTF_MMU("write breakpoint reg[%d] 0x%016x\n", reg,
2061
                        env->mmuregs[reg]);
2062
        }
2063
        break;
2064
    case 8: /* User code access, XXX */
2065
    case 9: /* Supervisor code access, XXX */
2066
    default:
2067
        do_unassigned_access(addr, 1, 0, asi, size);
2068
        break;
2069
    }
2070
#ifdef DEBUG_ASI
2071
    dump_asi("write", addr, asi, size, val);
2072
#endif
2073
}
2074

    
2075
#endif /* CONFIG_USER_ONLY */
2076
#else /* TARGET_SPARC64 */
2077

    
2078
#ifdef CONFIG_USER_ONLY
2079
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
2080
{
2081
    uint64_t ret = 0;
2082
#if defined(DEBUG_ASI)
2083
    target_ulong last_addr = addr;
2084
#endif
2085

    
2086
    if (asi < 0x80)
2087
        raise_exception(TT_PRIV_ACT);
2088

    
2089
    helper_check_align(addr, size - 1);
2090
    addr = address_mask(env, addr);
2091

    
2092
    switch (asi) {
2093
    case 0x82: // Primary no-fault
2094
    case 0x8a: // Primary no-fault LE
2095
        if (page_check_range(addr, size, PAGE_READ) == -1) {
2096
#ifdef DEBUG_ASI
2097
            dump_asi("read ", last_addr, asi, size, ret);
2098
#endif
2099
            return 0;
2100
        }
2101
        // Fall through
2102
    case 0x80: // Primary
2103
    case 0x88: // Primary LE
2104
        {
2105
            switch(size) {
2106
            case 1:
2107
                ret = ldub_raw(addr);
2108
                break;
2109
            case 2:
2110
                ret = lduw_raw(addr);
2111
                break;
2112
            case 4:
2113
                ret = ldl_raw(addr);
2114
                break;
2115
            default:
2116
            case 8:
2117
                ret = ldq_raw(addr);
2118
                break;
2119
            }
2120
        }
2121
        break;
2122
    case 0x83: // Secondary no-fault
2123
    case 0x8b: // Secondary no-fault LE
2124
        if (page_check_range(addr, size, PAGE_READ) == -1) {
2125
#ifdef DEBUG_ASI
2126
            dump_asi("read ", last_addr, asi, size, ret);
2127
#endif
2128
            return 0;
2129
        }
2130
        // Fall through
2131
    case 0x81: // Secondary
2132
    case 0x89: // Secondary LE
2133
        // XXX
2134
        break;
2135
    default:
2136
        break;
2137
    }
2138

    
2139
    /* Convert from little endian */
2140
    switch (asi) {
2141
    case 0x88: // Primary LE
2142
    case 0x89: // Secondary LE
2143
    case 0x8a: // Primary no-fault LE
2144
    case 0x8b: // Secondary no-fault LE
2145
        switch(size) {
2146
        case 2:
2147
            ret = bswap16(ret);
2148
            break;
2149
        case 4:
2150
            ret = bswap32(ret);
2151
            break;
2152
        case 8:
2153
            ret = bswap64(ret);
2154
            break;
2155
        default:
2156
            break;
2157
        }
2158
    default:
2159
        break;
2160
    }
2161

    
2162
    /* Convert to signed number */
2163
    if (sign) {
2164
        switch(size) {
2165
        case 1:
2166
            ret = (int8_t) ret;
2167
            break;
2168
        case 2:
2169
            ret = (int16_t) ret;
2170
            break;
2171
        case 4:
2172
            ret = (int32_t) ret;
2173
            break;
2174
        default:
2175
            break;
2176
        }
2177
    }
2178
#ifdef DEBUG_ASI
2179
    dump_asi("read ", last_addr, asi, size, ret);
2180
#endif
2181
    return ret;
2182
}
2183

    
2184
void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
2185
{
2186
#ifdef DEBUG_ASI
2187
    dump_asi("write", addr, asi, size, val);
2188
#endif
2189
    if (asi < 0x80)
2190
        raise_exception(TT_PRIV_ACT);
2191

    
2192
    helper_check_align(addr, size - 1);
2193
    addr = address_mask(env, addr);
2194

    
2195
    /* Convert to little endian */
2196
    switch (asi) {
2197
    case 0x88: // Primary LE
2198
    case 0x89: // Secondary LE
2199
        switch(size) {
2200
        case 2:
2201
            val = bswap16(val);
2202
            break;
2203
        case 4:
2204
            val = bswap32(val);
2205
            break;
2206
        case 8:
2207
            val = bswap64(val);
2208
            break;
2209
        default:
2210
            break;
2211
        }
2212
    default:
2213
        break;
2214
    }
2215

    
2216
    switch(asi) {
2217
    case 0x80: // Primary
2218
    case 0x88: // Primary LE
2219
        {
2220
            switch(size) {
2221
            case 1:
2222
                stb_raw(addr, val);
2223
                break;
2224
            case 2:
2225
                stw_raw(addr, val);
2226
                break;
2227
            case 4:
2228
                stl_raw(addr, val);
2229
                break;
2230
            case 8:
2231
            default:
2232
                stq_raw(addr, val);
2233
                break;
2234
            }
2235
        }
2236
        break;
2237
    case 0x81: // Secondary
2238
    case 0x89: // Secondary LE
2239
        // XXX
2240
        return;
2241

    
2242
    case 0x82: // Primary no-fault, RO
2243
    case 0x83: // Secondary no-fault, RO
2244
    case 0x8a: // Primary no-fault LE, RO
2245
    case 0x8b: // Secondary no-fault LE, RO
2246
    default:
2247
        do_unassigned_access(addr, 1, 0, 1, size);
2248
        return;
2249
    }
2250
}
2251

    
2252
#else /* CONFIG_USER_ONLY */
2253

    
2254
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
2255
{
2256
    uint64_t ret = 0;
2257
#if defined(DEBUG_ASI)
2258
    target_ulong last_addr = addr;
2259
#endif
2260

    
2261
    asi &= 0xff;
2262

    
2263
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
2264
        || ((env->def->features & CPU_FEATURE_HYPV)
2265
            && asi >= 0x30 && asi < 0x80
2266
            && !(env->hpstate & HS_PRIV)))
2267
        raise_exception(TT_PRIV_ACT);
2268

    
2269
    helper_check_align(addr, size - 1);
2270
    switch (asi) {
2271
    case 0x82: // Primary no-fault
2272
    case 0x8a: // Primary no-fault LE
2273
    case 0x83: // Secondary no-fault
2274
    case 0x8b: // Secondary no-fault LE
2275
        {
2276
            /* secondary space access has lowest asi bit equal to 1 */
2277
            int access_mmu_idx = ( asi & 1 ) ? MMU_KERNEL_IDX
2278
                                             : MMU_KERNEL_SECONDARY_IDX;
2279

    
2280
            if (cpu_get_phys_page_nofault(env, addr, access_mmu_idx) == -1ULL) {
2281
#ifdef DEBUG_ASI
2282
                dump_asi("read ", last_addr, asi, size, ret);
2283
#endif
2284
                return 0;
2285
            }
2286
        }
2287
        // Fall through
2288
    case 0x10: // As if user primary
2289
    case 0x11: // As if user secondary
2290
    case 0x18: // As if user primary LE
2291
    case 0x19: // As if user secondary LE
2292
    case 0x80: // Primary
2293
    case 0x81: // Secondary
2294
    case 0x88: // Primary LE
2295
    case 0x89: // Secondary LE
2296
    case 0xe2: // UA2007 Primary block init
2297
    case 0xe3: // UA2007 Secondary block init
2298
        if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
2299
            if ((env->def->features & CPU_FEATURE_HYPV)
2300
                && env->hpstate & HS_PRIV) {
2301
                switch(size) {
2302
                case 1:
2303
                    ret = ldub_hypv(addr);
2304
                    break;
2305
                case 2:
2306
                    ret = lduw_hypv(addr);
2307
                    break;
2308
                case 4:
2309
                    ret = ldl_hypv(addr);
2310
                    break;
2311
                default:
2312
                case 8:
2313
                    ret = ldq_hypv(addr);
2314
                    break;
2315
                }
2316
            } else {
2317
                /* secondary space access has lowest asi bit equal to 1 */
2318
                if (asi & 1) {
2319
                    switch(size) {
2320
                    case 1:
2321
                        ret = ldub_kernel_secondary(addr);
2322
                        break;
2323
                    case 2:
2324
                        ret = lduw_kernel_secondary(addr);
2325
                        break;
2326
                    case 4:
2327
                        ret = ldl_kernel_secondary(addr);
2328
                        break;
2329
                    default:
2330
                    case 8:
2331
                        ret = ldq_kernel_secondary(addr);
2332
                        break;
2333
                    }
2334
                } else {
2335
                    switch(size) {
2336
                    case 1:
2337
                        ret = ldub_kernel(addr);
2338
                        break;
2339
                    case 2:
2340
                        ret = lduw_kernel(addr);
2341
                        break;
2342
                    case 4:
2343
                        ret = ldl_kernel(addr);
2344
                        break;
2345
                    default:
2346
                    case 8:
2347
                        ret = ldq_kernel(addr);
2348
                        break;
2349
                    }
2350
                }
2351
            }
2352
        } else {
2353
            /* secondary space access has lowest asi bit equal to 1 */
2354
            if (asi & 1) {
2355
                switch(size) {
2356
                case 1:
2357
                    ret = ldub_user_secondary(addr);
2358
                    break;
2359
                case 2:
2360
                    ret = lduw_user_secondary(addr);
2361
                    break;
2362
                case 4:
2363
                    ret = ldl_user_secondary(addr);
2364
                    break;
2365
                default:
2366
                case 8:
2367
                    ret = ldq_user_secondary(addr);
2368
                    break;
2369
                }
2370
            } else {
2371
                switch(size) {
2372
                case 1:
2373
                    ret = ldub_user(addr);
2374
                    break;
2375
                case 2:
2376
                    ret = lduw_user(addr);
2377
                    break;
2378
                case 4:
2379
                    ret = ldl_user(addr);
2380
                    break;
2381
                default:
2382
                case 8:
2383
                    ret = ldq_user(addr);
2384
                    break;
2385
                }
2386
            }
2387
        }
2388
        break;
2389
    case 0x14: // Bypass
2390
    case 0x15: // Bypass, non-cacheable
2391
    case 0x1c: // Bypass LE
2392
    case 0x1d: // Bypass, non-cacheable LE
2393
        {
2394
            switch(size) {
2395
            case 1:
2396
                ret = ldub_phys(addr);
2397
                break;
2398
            case 2:
2399
                ret = lduw_phys(addr);
2400
                break;
2401
            case 4:
2402
                ret = ldl_phys(addr);
2403
                break;
2404
            default:
2405
            case 8:
2406
                ret = ldq_phys(addr);
2407
                break;
2408
            }
2409
            break;
2410
        }
2411
    case 0x24: // Nucleus quad LDD 128 bit atomic
2412
    case 0x2c: // Nucleus quad LDD 128 bit atomic LE
2413
        //  Only ldda allowed
2414
        raise_exception(TT_ILL_INSN);
2415
        return 0;
2416
    case 0x04: // Nucleus
2417
    case 0x0c: // Nucleus Little Endian (LE)
2418
    {
2419
        switch(size) {
2420
        case 1:
2421
            ret = ldub_nucleus(addr);
2422
            break;
2423
        case 2:
2424
            ret = lduw_nucleus(addr);
2425
            break;
2426
        case 4:
2427
            ret = ldl_nucleus(addr);
2428
            break;
2429
        default:
2430
        case 8:
2431
            ret = ldq_nucleus(addr);
2432
            break;
2433
        }
2434
        break;
2435
    }
2436
    case 0x4a: // UPA config
2437
        // XXX
2438
        break;
2439
    case 0x45: // LSU
2440
        ret = env->lsu;
2441
        break;
2442
    case 0x50: // I-MMU regs
2443
        {
2444
            int reg = (addr >> 3) & 0xf;
2445

    
2446
            if (reg == 0) {
2447
                // I-TSB Tag Target register
2448
                ret = ultrasparc_tag_target(env->immu.tag_access);
2449
            } else {
2450
                ret = env->immuregs[reg];
2451
            }
2452

    
2453
            break;
2454
        }
2455
    case 0x51: // I-MMU 8k TSB pointer
2456
        {
2457
            // env->immuregs[5] holds I-MMU TSB register value
2458
            // env->immuregs[6] holds I-MMU Tag Access register value
2459
            ret = ultrasparc_tsb_pointer(env->immu.tsb, env->immu.tag_access,
2460
                                         8*1024);
2461
            break;
2462
        }
2463
    case 0x52: // I-MMU 64k TSB pointer
2464
        {
2465
            // env->immuregs[5] holds I-MMU TSB register value
2466
            // env->immuregs[6] holds I-MMU Tag Access register value
2467
            ret = ultrasparc_tsb_pointer(env->immu.tsb, env->immu.tag_access,
2468
                                         64*1024);
2469
            break;
2470
        }
2471
    case 0x55: // I-MMU data access
2472
        {
2473
            int reg = (addr >> 3) & 0x3f;
2474

    
2475
            ret = env->itlb[reg].tte;
2476
            break;
2477
        }
2478
    case 0x56: // I-MMU tag read
2479
        {
2480
            int reg = (addr >> 3) & 0x3f;
2481

    
2482
            ret = env->itlb[reg].tag;
2483
            break;
2484
        }
2485
    case 0x58: // D-MMU regs
2486
        {
2487
            int reg = (addr >> 3) & 0xf;
2488

    
2489
            if (reg == 0) {
2490
                // D-TSB Tag Target register
2491
                ret = ultrasparc_tag_target(env->dmmu.tag_access);
2492
            } else {
2493
                ret = env->dmmuregs[reg];
2494
            }
2495
            break;
2496
        }
2497
    case 0x59: // D-MMU 8k TSB pointer
2498
        {
2499
            // env->dmmuregs[5] holds D-MMU TSB register value
2500
            // env->dmmuregs[6] holds D-MMU Tag Access register value
2501
            ret = ultrasparc_tsb_pointer(env->dmmu.tsb, env->dmmu.tag_access,
2502
                                         8*1024);
2503
            break;
2504
        }
2505
    case 0x5a: // D-MMU 64k TSB pointer
2506
        {
2507
            // env->dmmuregs[5] holds D-MMU TSB register value
2508
            // env->dmmuregs[6] holds D-MMU Tag Access register value
2509
            ret = ultrasparc_tsb_pointer(env->dmmu.tsb, env->dmmu.tag_access,
2510
                                         64*1024);
2511
            break;
2512
        }
2513
    case 0x5d: // D-MMU data access
2514
        {
2515
            int reg = (addr >> 3) & 0x3f;
2516

    
2517
            ret = env->dtlb[reg].tte;
2518
            break;
2519
        }
2520
    case 0x5e: // D-MMU tag read
2521
        {
2522
            int reg = (addr >> 3) & 0x3f;
2523

    
2524
            ret = env->dtlb[reg].tag;
2525
            break;
2526
        }
2527
    case 0x46: // D-cache data
2528
    case 0x47: // D-cache tag access
2529
    case 0x4b: // E-cache error enable
2530
    case 0x4c: // E-cache asynchronous fault status
2531
    case 0x4d: // E-cache asynchronous fault address
2532
    case 0x4e: // E-cache tag data
2533
    case 0x66: // I-cache instruction access
2534
    case 0x67: // I-cache tag access
2535
    case 0x6e: // I-cache predecode
2536
    case 0x6f: // I-cache LRU etc.
2537
    case 0x76: // E-cache tag
2538
    case 0x7e: // E-cache tag
2539
        break;
2540
    case 0x5b: // D-MMU data pointer
2541
    case 0x48: // Interrupt dispatch, RO
2542
    case 0x49: // Interrupt data receive
2543
    case 0x7f: // Incoming interrupt vector, RO
2544
        // XXX
2545
        break;
2546
    case 0x54: // I-MMU data in, WO
2547
    case 0x57: // I-MMU demap, WO
2548
    case 0x5c: // D-MMU data in, WO
2549
    case 0x5f: // D-MMU demap, WO
2550
    case 0x77: // Interrupt vector, WO
2551
    default:
2552
        do_unassigned_access(addr, 0, 0, 1, size);
2553
        ret = 0;
2554
        break;
2555
    }
2556

    
2557
    /* Convert from little endian */
2558
    switch (asi) {
2559
    case 0x0c: // Nucleus Little Endian (LE)
2560
    case 0x18: // As if user primary LE
2561
    case 0x19: // As if user secondary LE
2562
    case 0x1c: // Bypass LE
2563
    case 0x1d: // Bypass, non-cacheable LE
2564
    case 0x88: // Primary LE
2565
    case 0x89: // Secondary LE
2566
    case 0x8a: // Primary no-fault LE
2567
    case 0x8b: // Secondary no-fault LE
2568
        switch(size) {
2569
        case 2:
2570
            ret = bswap16(ret);
2571
            break;
2572
        case 4:
2573
            ret = bswap32(ret);
2574
            break;
2575
        case 8:
2576
            ret = bswap64(ret);
2577
            break;
2578
        default:
2579
            break;
2580
        }
2581
    default:
2582
        break;
2583
    }
2584

    
2585
    /* Convert to signed number */
2586
    if (sign) {
2587
        switch(size) {
2588
        case 1:
2589
            ret = (int8_t) ret;
2590
            break;
2591
        case 2:
2592
            ret = (int16_t) ret;
2593
            break;
2594
        case 4:
2595
            ret = (int32_t) ret;
2596
            break;
2597
        default:
2598
            break;
2599
        }
2600
    }
2601
#ifdef DEBUG_ASI
2602
    dump_asi("read ", last_addr, asi, size, ret);
2603
#endif
2604
    return ret;
2605
}
2606

    
2607
void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
2608
{
2609
#ifdef DEBUG_ASI
2610
    dump_asi("write", addr, asi, size, val);
2611
#endif
2612

    
2613
    asi &= 0xff;
2614

    
2615
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
2616
        || ((env->def->features & CPU_FEATURE_HYPV)
2617
            && asi >= 0x30 && asi < 0x80
2618
            && !(env->hpstate & HS_PRIV)))
2619
        raise_exception(TT_PRIV_ACT);
2620

    
2621
    helper_check_align(addr, size - 1);
2622
    /* Convert to little endian */
2623
    switch (asi) {
2624
    case 0x0c: // Nucleus Little Endian (LE)
2625
    case 0x18: // As if user primary LE
2626
    case 0x19: // As if user secondary LE
2627
    case 0x1c: // Bypass LE
2628
    case 0x1d: // Bypass, non-cacheable LE
2629
    case 0x88: // Primary LE
2630
    case 0x89: // Secondary LE
2631
        switch(size) {
2632
        case 2:
2633
            val = bswap16(val);
2634
            break;
2635
        case 4:
2636
            val = bswap32(val);
2637
            break;
2638
        case 8:
2639
            val = bswap64(val);
2640
            break;
2641
        default:
2642
            break;
2643
        }
2644
    default:
2645
        break;
2646
    }
2647

    
2648
    switch(asi) {
2649
    case 0x10: // As if user primary
2650
    case 0x11: // As if user secondary
2651
    case 0x18: // As if user primary LE
2652
    case 0x19: // As if user secondary LE
2653
    case 0x80: // Primary
2654
    case 0x81: // Secondary
2655
    case 0x88: // Primary LE
2656
    case 0x89: // Secondary LE
2657
    case 0xe2: // UA2007 Primary block init
2658
    case 0xe3: // UA2007 Secondary block init
2659
        if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
2660
            if ((env->def->features & CPU_FEATURE_HYPV)
2661
                && env->hpstate & HS_PRIV) {
2662
                switch(size) {
2663
                case 1:
2664
                    stb_hypv(addr, val);
2665
                    break;
2666
                case 2:
2667
                    stw_hypv(addr, val);
2668
                    break;
2669
                case 4:
2670
                    stl_hypv(addr, val);
2671
                    break;
2672
                case 8:
2673
                default:
2674
                    stq_hypv(addr, val);
2675
                    break;
2676
                }
2677
            } else {
2678
                /* secondary space access has lowest asi bit equal to 1 */
2679
                if (asi & 1) {
2680
                    switch(size) {
2681
                    case 1:
2682
                        stb_kernel_secondary(addr, val);
2683
                        break;
2684
                    case 2:
2685
                        stw_kernel_secondary(addr, val);
2686
                        break;
2687
                    case 4:
2688
                        stl_kernel_secondary(addr, val);
2689
                        break;
2690
                    case 8:
2691
                    default:
2692
                        stq_kernel_secondary(addr, val);
2693
                        break;
2694
                    }
2695
                } else {
2696
                    switch(size) {
2697
                    case 1:
2698
                        stb_kernel(addr, val);
2699
                        break;
2700
                    case 2:
2701
                        stw_kernel(addr, val);
2702
                        break;
2703
                    case 4:
2704
                        stl_kernel(addr, val);
2705
                        break;
2706
                    case 8:
2707
                    default:
2708
                        stq_kernel(addr, val);
2709
                        break;
2710
                    }
2711
                }
2712
            }
2713
        } else {
2714
            /* secondary space access has lowest asi bit equal to 1 */
2715
            if (asi & 1) {
2716
                switch(size) {
2717
                case 1:
2718
                    stb_user_secondary(addr, val);
2719
                    break;
2720
                case 2:
2721
                    stw_user_secondary(addr, val);
2722
                    break;
2723
                case 4:
2724
                    stl_user_secondary(addr, val);
2725
                    break;
2726
                case 8:
2727
                default:
2728
                    stq_user_secondary(addr, val);
2729
                    break;
2730
                }
2731
            } else {
2732
                switch(size) {
2733
                case 1:
2734
                    stb_user(addr, val);
2735
                    break;
2736
                case 2:
2737
                    stw_user(addr, val);
2738
                    break;
2739
                case 4:
2740
                    stl_user(addr, val);
2741
                    break;
2742
                case 8:
2743
                default:
2744
                    stq_user(addr, val);
2745
                    break;
2746
                }
2747
            }
2748
        }
2749
        break;
2750
    case 0x14: // Bypass
2751
    case 0x15: // Bypass, non-cacheable
2752
    case 0x1c: // Bypass LE
2753
    case 0x1d: // Bypass, non-cacheable LE
2754
        {
2755
            switch(size) {
2756
            case 1:
2757
                stb_phys(addr, val);
2758
                break;
2759
            case 2:
2760
                stw_phys(addr, val);
2761
                break;
2762
            case 4:
2763
                stl_phys(addr, val);
2764
                break;
2765
            case 8:
2766
            default:
2767
                stq_phys(addr, val);
2768
                break;
2769
            }
2770
        }
2771
        return;
2772
    case 0x24: // Nucleus quad LDD 128 bit atomic
2773
    case 0x2c: // Nucleus quad LDD 128 bit atomic LE
2774
        //  Only ldda allowed
2775
        raise_exception(TT_ILL_INSN);
2776
        return;
2777
    case 0x04: // Nucleus
2778
    case 0x0c: // Nucleus Little Endian (LE)
2779
    {
2780
        switch(size) {
2781
        case 1:
2782
            stb_nucleus(addr, val);
2783
            break;
2784
        case 2:
2785
            stw_nucleus(addr, val);
2786
            break;
2787
        case 4:
2788
            stl_nucleus(addr, val);
2789
            break;
2790
        default:
2791
        case 8:
2792
            stq_nucleus(addr, val);
2793
            break;
2794
        }
2795
        break;
2796
    }
2797

    
2798
    case 0x4a: // UPA config
2799
        // XXX
2800
        return;
2801
    case 0x45: // LSU
2802
        {
2803
            uint64_t oldreg;
2804

    
2805
            oldreg = env->lsu;
2806
            env->lsu = val & (DMMU_E | IMMU_E);
2807
            // Mappings generated during D/I MMU disabled mode are
2808
            // invalid in normal mode
2809
            if (oldreg != env->lsu) {
2810
                DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n",
2811
                            oldreg, env->lsu);
2812
#ifdef DEBUG_MMU
2813
                dump_mmu(env);
2814
#endif
2815
                tlb_flush(env, 1);
2816
            }
2817
            return;
2818
        }
2819
    case 0x50: // I-MMU regs
2820
        {
2821
            int reg = (addr >> 3) & 0xf;
2822
            uint64_t oldreg;
2823

    
2824
            oldreg = env->immuregs[reg];
2825
            switch(reg) {
2826
            case 0: // RO
2827
                return;
2828
            case 1: // Not in I-MMU
2829
            case 2:
2830
                return;
2831
            case 3: // SFSR
2832
                if ((val & 1) == 0)
2833
                    val = 0; // Clear SFSR
2834
                env->immu.sfsr = val;
2835
                break;
2836
            case 4: // RO
2837
                return;
2838
            case 5: // TSB access
2839
                DPRINTF_MMU("immu TSB write: 0x%016" PRIx64 " -> 0x%016"
2840
                            PRIx64 "\n", env->immu.tsb, val);
2841
                env->immu.tsb = val;
2842
                break;
2843
            case 6: // Tag access
2844
                env->immu.tag_access = val;
2845
                break;
2846
            case 7:
2847
            case 8:
2848
                return;
2849
            default:
2850
                break;
2851
            }
2852

    
2853
            if (oldreg != env->immuregs[reg]) {
2854
                DPRINTF_MMU("immu change reg[%d]: 0x%016" PRIx64 " -> 0x%016"
2855
                            PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
2856
            }
2857
#ifdef DEBUG_MMU
2858
            dump_mmu(env);
2859
#endif
2860
            return;
2861
        }
2862
    case 0x54: // I-MMU data in
2863
        replace_tlb_1bit_lru(env->itlb, env->immu.tag_access, val, "immu", env);
2864
        return;
2865
    case 0x55: // I-MMU data access
2866
        {
2867
            // TODO: auto demap
2868

    
2869
            unsigned int i = (addr >> 3) & 0x3f;
2870

    
2871
            replace_tlb_entry(&env->itlb[i], env->immu.tag_access, val, env);
2872

    
2873
#ifdef DEBUG_MMU
2874
            DPRINTF_MMU("immu data access replaced entry [%i]\n", i);
2875
            dump_mmu(env);
2876
#endif
2877
            return;
2878
        }
2879
    case 0x57: // I-MMU demap
2880
        demap_tlb(env->itlb, val, "immu", env);
2881
        return;
2882
    case 0x58: // D-MMU regs
2883
        {
2884
            int reg = (addr >> 3) & 0xf;
2885
            uint64_t oldreg;
2886

    
2887
            oldreg = env->dmmuregs[reg];
2888
            switch(reg) {
2889
            case 0: // RO
2890
            case 4:
2891
                return;
2892
            case 3: // SFSR
2893
                if ((val & 1) == 0) {
2894
                    val = 0; // Clear SFSR, Fault address
2895
                    env->dmmu.sfar = 0;
2896
                }
2897
                env->dmmu.sfsr = val;
2898
                break;
2899
            case 1: // Primary context
2900
                env->dmmu.mmu_primary_context = val;
2901
                break;
2902
            case 2: // Secondary context
2903
                env->dmmu.mmu_secondary_context = val;
2904
                break;
2905
            case 5: // TSB access
2906
                DPRINTF_MMU("dmmu TSB write: 0x%016" PRIx64 " -> 0x%016"
2907
                            PRIx64 "\n", env->dmmu.tsb, val);
2908
                env->dmmu.tsb = val;
2909
                break;
2910
            case 6: // Tag access
2911
                env->dmmu.tag_access = val;
2912
                break;
2913
            case 7: // Virtual Watchpoint
2914
            case 8: // Physical Watchpoint
2915
            default:
2916
                env->dmmuregs[reg] = val;
2917
                break;
2918
            }
2919

    
2920
            if (oldreg != env->dmmuregs[reg]) {
2921
                DPRINTF_MMU("dmmu change reg[%d]: 0x%016" PRIx64 " -> 0x%016"
2922
                            PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
2923
            }
2924
#ifdef DEBUG_MMU
2925
            dump_mmu(env);
2926
#endif
2927
            return;
2928
        }
2929
    case 0x5c: // D-MMU data in
2930
        replace_tlb_1bit_lru(env->dtlb, env->dmmu.tag_access, val, "dmmu", env);
2931
        return;
2932
    case 0x5d: // D-MMU data access
2933
        {
2934
            unsigned int i = (addr >> 3) & 0x3f;
2935

    
2936
            replace_tlb_entry(&env->dtlb[i], env->dmmu.tag_access, val, env);
2937

    
2938
#ifdef DEBUG_MMU
2939
            DPRINTF_MMU("dmmu data access replaced entry [%i]\n", i);
2940
            dump_mmu(env);
2941
#endif
2942
            return;
2943
        }
2944
    case 0x5f: // D-MMU demap
2945
        demap_tlb(env->dtlb, val, "dmmu", env);
2946
        return;
2947
    case 0x49: // Interrupt data receive
2948
        // XXX
2949
        return;
2950
    case 0x46: // D-cache data
2951
    case 0x47: // D-cache tag access
2952
    case 0x4b: // E-cache error enable
2953
    case 0x4c: // E-cache asynchronous fault status
2954
    case 0x4d: // E-cache asynchronous fault address
2955
    case 0x4e: // E-cache tag data
2956
    case 0x66: // I-cache instruction access
2957
    case 0x67: // I-cache tag access
2958
    case 0x6e: // I-cache predecode
2959
    case 0x6f: // I-cache LRU etc.
2960
    case 0x76: // E-cache tag
2961
    case 0x7e: // E-cache tag
2962
        return;
2963
    case 0x51: // I-MMU 8k TSB pointer, RO
2964
    case 0x52: // I-MMU 64k TSB pointer, RO
2965
    case 0x56: // I-MMU tag read, RO
2966
    case 0x59: // D-MMU 8k TSB pointer, RO
2967
    case 0x5a: // D-MMU 64k TSB pointer, RO
2968
    case 0x5b: // D-MMU data pointer, RO
2969
    case 0x5e: // D-MMU tag read, RO
2970
    case 0x48: // Interrupt dispatch, RO
2971
    case 0x7f: // Incoming interrupt vector, RO
2972
    case 0x82: // Primary no-fault, RO
2973
    case 0x83: // Secondary no-fault, RO
2974
    case 0x8a: // Primary no-fault LE, RO
2975
    case 0x8b: // Secondary no-fault LE, RO
2976
    default:
2977
        do_unassigned_access(addr, 1, 0, 1, size);
2978
        return;
2979
    }
2980
}
2981
#endif /* CONFIG_USER_ONLY */
2982

    
2983
void helper_ldda_asi(target_ulong addr, int asi, int rd)
2984
{
2985
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
2986
        || ((env->def->features & CPU_FEATURE_HYPV)
2987
            && asi >= 0x30 && asi < 0x80
2988
            && !(env->hpstate & HS_PRIV)))
2989
        raise_exception(TT_PRIV_ACT);
2990

    
2991
    switch (asi) {
2992
    case 0x24: // Nucleus quad LDD 128 bit atomic
2993
    case 0x2c: // Nucleus quad LDD 128 bit atomic LE
2994
        helper_check_align(addr, 0xf);
2995
        if (rd == 0) {
2996
            env->gregs[1] = ldq_kernel(addr + 8);
2997
            if (asi == 0x2c)
2998
                bswap64s(&env->gregs[1]);
2999
        } else if (rd < 8) {
3000
            env->gregs[rd] = ldq_kernel(addr);
3001
            env->gregs[rd + 1] = ldq_kernel(addr + 8);
3002
            if (asi == 0x2c) {
3003
                bswap64s(&env->gregs[rd]);
3004
                bswap64s(&env->gregs[rd + 1]);
3005
            }
3006
        } else {
3007
            env->regwptr[rd] = ldq_kernel(addr);
3008
            env->regwptr[rd + 1] = ldq_kernel(addr + 8);
3009
            if (asi == 0x2c) {
3010
                bswap64s(&env->regwptr[rd]);
3011
                bswap64s(&env->regwptr[rd + 1]);
3012
            }
3013
        }
3014
        break;
3015
    default:
3016
        helper_check_align(addr, 0x3);
3017
        if (rd == 0)
3018
            env->gregs[1] = helper_ld_asi(addr + 4, asi, 4, 0);
3019
        else if (rd < 8) {
3020
            env->gregs[rd] = helper_ld_asi(addr, asi, 4, 0);
3021
            env->gregs[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
3022
        } else {
3023
            env->regwptr[rd] = helper_ld_asi(addr, asi, 4, 0);
3024
            env->regwptr[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
3025
        }
3026
        break;
3027
    }
3028
}
3029

    
3030
void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
3031
{
3032
    unsigned int i;
3033
    target_ulong val;
3034

    
3035
    helper_check_align(addr, 3);
3036
    switch (asi) {
3037
    case 0xf0: // Block load primary
3038
    case 0xf1: // Block load secondary
3039
    case 0xf8: // Block load primary LE
3040
    case 0xf9: // Block load secondary LE
3041
        if (rd & 7) {
3042
            raise_exception(TT_ILL_INSN);
3043
            return;
3044
        }
3045
        helper_check_align(addr, 0x3f);
3046
        for (i = 0; i < 16; i++) {
3047
            *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x8f, 4,
3048
                                                         0);
3049
            addr += 4;
3050
        }
3051

    
3052
        return;
3053
    default:
3054
        break;
3055
    }
3056

    
3057
    val = helper_ld_asi(addr, asi, size, 0);
3058
    switch(size) {
3059
    default:
3060
    case 4:
3061
        *((uint32_t *)&env->fpr[rd]) = val;
3062
        break;
3063
    case 8:
3064
        *((int64_t *)&DT0) = val;
3065
        break;
3066
    case 16:
3067
        // XXX
3068
        break;
3069
    }
3070
}
3071

    
3072
void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
3073
{
3074
    unsigned int i;
3075
    target_ulong val = 0;
3076

    
3077
    helper_check_align(addr, 3);
3078
    switch (asi) {
3079
    case 0xe0: // UA2007 Block commit store primary (cache flush)
3080
    case 0xe1: // UA2007 Block commit store secondary (cache flush)
3081
    case 0xf0: // Block store primary
3082
    case 0xf1: // Block store secondary
3083
    case 0xf8: // Block store primary LE
3084
    case 0xf9: // Block store secondary LE
3085
        if (rd & 7) {
3086
            raise_exception(TT_ILL_INSN);
3087
            return;
3088
        }
3089
        helper_check_align(addr, 0x3f);
3090
        for (i = 0; i < 16; i++) {
3091
            val = *(uint32_t *)&env->fpr[rd++];
3092
            helper_st_asi(addr, val, asi & 0x8f, 4);
3093
            addr += 4;
3094
        }
3095

    
3096
        return;
3097
    default:
3098
        break;
3099
    }
3100

    
3101
    switch(size) {
3102
    default:
3103
    case 4:
3104
        val = *((uint32_t *)&env->fpr[rd]);
3105
        break;
3106
    case 8:
3107
        val = *((int64_t *)&DT0);
3108
        break;
3109
    case 16:
3110
        // XXX
3111
        break;
3112
    }
3113
    helper_st_asi(addr, val, asi, size);
3114
}
3115

    
3116
target_ulong helper_cas_asi(target_ulong addr, target_ulong val1,
3117
                            target_ulong val2, uint32_t asi)
3118
{
3119
    target_ulong ret;
3120

    
3121
    val2 &= 0xffffffffUL;
3122
    ret = helper_ld_asi(addr, asi, 4, 0);
3123
    ret &= 0xffffffffUL;
3124
    if (val2 == ret)
3125
        helper_st_asi(addr, val1 & 0xffffffffUL, asi, 4);
3126
    return ret;
3127
}
3128

    
3129
target_ulong helper_casx_asi(target_ulong addr, target_ulong val1,
3130
                             target_ulong val2, uint32_t asi)
3131
{
3132
    target_ulong ret;
3133

    
3134
    ret = helper_ld_asi(addr, asi, 8, 0);
3135
    if (val2 == ret)
3136
        helper_st_asi(addr, val1, asi, 8);
3137
    return ret;
3138
}
3139
#endif /* TARGET_SPARC64 */
3140

    
3141
#ifndef TARGET_SPARC64
3142
void helper_rett(void)
3143
{
3144
    unsigned int cwp;
3145

    
3146
    if (env->psret == 1)
3147
        raise_exception(TT_ILL_INSN);
3148

    
3149
    env->psret = 1;
3150
    cwp = cwp_inc(env->cwp + 1) ;
3151
    if (env->wim & (1 << cwp)) {
3152
        raise_exception(TT_WIN_UNF);
3153
    }
3154
    set_cwp(cwp);
3155
    env->psrs = env->psrps;
3156
}
3157
#endif
3158

    
3159
target_ulong helper_udiv(target_ulong a, target_ulong b)
3160
{
3161
    uint64_t x0;
3162
    uint32_t x1;
3163

    
3164
    x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
3165
    x1 = b;
3166

    
3167
    if (x1 == 0) {
3168
        raise_exception(TT_DIV_ZERO);
3169
    }
3170

    
3171
    x0 = x0 / x1;
3172
    if (x0 > 0xffffffff) {
3173
        env->cc_src2 = 1;
3174
        return 0xffffffff;
3175
    } else {
3176
        env->cc_src2 = 0;
3177
        return x0;
3178
    }
3179
}
3180

    
3181
target_ulong helper_sdiv(target_ulong a, target_ulong b)
3182
{
3183
    int64_t x0;
3184
    int32_t x1;
3185

    
3186
    x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
3187
    x1 = b;
3188

    
3189
    if (x1 == 0) {
3190
        raise_exception(TT_DIV_ZERO);
3191
    }
3192

    
3193
    x0 = x0 / x1;
3194
    if ((int32_t) x0 != x0) {
3195
        env->cc_src2 = 1;
3196
        return x0 < 0? 0x80000000: 0x7fffffff;
3197
    } else {
3198
        env->cc_src2 = 0;
3199
        return x0;
3200
    }
3201
}
3202

    
3203
void helper_stdf(target_ulong addr, int mem_idx)
3204
{
3205
    helper_check_align(addr, 7);
3206
#if !defined(CONFIG_USER_ONLY)
3207
    switch (mem_idx) {
3208
    case 0:
3209
        stfq_user(addr, DT0);
3210
        break;
3211
    case 1:
3212
        stfq_kernel(addr, DT0);
3213
        break;
3214
#ifdef TARGET_SPARC64
3215
    case 2:
3216
        stfq_hypv(addr, DT0);
3217
        break;
3218
#endif
3219
    default:
3220
        break;
3221
    }
3222
#else
3223
    stfq_raw(address_mask(env, addr), DT0);
3224
#endif
3225
}
3226

    
3227
void helper_lddf(target_ulong addr, int mem_idx)
3228
{
3229
    helper_check_align(addr, 7);
3230
#if !defined(CONFIG_USER_ONLY)
3231
    switch (mem_idx) {
3232
    case 0:
3233
        DT0 = ldfq_user(addr);
3234
        break;
3235
    case 1:
3236
        DT0 = ldfq_kernel(addr);
3237
        break;
3238
#ifdef TARGET_SPARC64
3239
    case 2:
3240
        DT0 = ldfq_hypv(addr);
3241
        break;
3242
#endif
3243
    default:
3244
        break;
3245
    }
3246
#else
3247
    DT0 = ldfq_raw(address_mask(env, addr));
3248
#endif
3249
}
3250

    
3251
void helper_ldqf(target_ulong addr, int mem_idx)
3252
{
3253
    // XXX add 128 bit load
3254
    CPU_QuadU u;
3255

    
3256
    helper_check_align(addr, 7);
3257
#if !defined(CONFIG_USER_ONLY)
3258
    switch (mem_idx) {
3259
    case 0:
3260
        u.ll.upper = ldq_user(addr);
3261
        u.ll.lower = ldq_user(addr + 8);
3262
        QT0 = u.q;
3263
        break;
3264
    case 1:
3265
        u.ll.upper = ldq_kernel(addr);
3266
        u.ll.lower = ldq_kernel(addr + 8);
3267
        QT0 = u.q;
3268
        break;
3269
#ifdef TARGET_SPARC64
3270
    case 2:
3271
        u.ll.upper = ldq_hypv(addr);
3272
        u.ll.lower = ldq_hypv(addr + 8);
3273
        QT0 = u.q;
3274
        break;
3275
#endif
3276
    default:
3277
        break;
3278
    }
3279
#else
3280
    u.ll.upper = ldq_raw(address_mask(env, addr));
3281
    u.ll.lower = ldq_raw(address_mask(env, addr + 8));
3282
    QT0 = u.q;
3283
#endif
3284
}
3285

    
3286
void helper_stqf(target_ulong addr, int mem_idx)
3287
{
3288
    // XXX add 128 bit store
3289
    CPU_QuadU u;
3290

    
3291
    helper_check_align(addr, 7);
3292
#if !defined(CONFIG_USER_ONLY)
3293
    switch (mem_idx) {
3294
    case 0:
3295
        u.q = QT0;
3296
        stq_user(addr, u.ll.upper);
3297
        stq_user(addr + 8, u.ll.lower);
3298
        break;
3299
    case 1:
3300
        u.q = QT0;
3301
        stq_kernel(addr, u.ll.upper);
3302
        stq_kernel(addr + 8, u.ll.lower);
3303
        break;
3304
#ifdef TARGET_SPARC64
3305
    case 2:
3306
        u.q = QT0;
3307
        stq_hypv(addr, u.ll.upper);
3308
        stq_hypv(addr + 8, u.ll.lower);
3309
        break;
3310
#endif
3311
    default:
3312
        break;
3313
    }
3314
#else
3315
    u.q = QT0;
3316
    stq_raw(address_mask(env, addr), u.ll.upper);
3317
    stq_raw(address_mask(env, addr + 8), u.ll.lower);
3318
#endif
3319
}
3320

    
3321
static inline void set_fsr(void)
3322
{
3323
    int rnd_mode;
3324

    
3325
    switch (env->fsr & FSR_RD_MASK) {
3326
    case FSR_RD_NEAREST:
3327
        rnd_mode = float_round_nearest_even;
3328
        break;
3329
    default:
3330
    case FSR_RD_ZERO:
3331
        rnd_mode = float_round_to_zero;
3332
        break;
3333
    case FSR_RD_POS:
3334
        rnd_mode = float_round_up;
3335
        break;
3336
    case FSR_RD_NEG:
3337
        rnd_mode = float_round_down;
3338
        break;
3339
    }
3340
    set_float_rounding_mode(rnd_mode, &env->fp_status);
3341
}
3342

    
3343
void helper_ldfsr(uint32_t new_fsr)
3344
{
3345
    env->fsr = (new_fsr & FSR_LDFSR_MASK) | (env->fsr & FSR_LDFSR_OLDMASK);
3346
    set_fsr();
3347
}
3348

    
3349
#ifdef TARGET_SPARC64
3350
void helper_ldxfsr(uint64_t new_fsr)
3351
{
3352
    env->fsr = (new_fsr & FSR_LDXFSR_MASK) | (env->fsr & FSR_LDXFSR_OLDMASK);
3353
    set_fsr();
3354
}
3355
#endif
3356

    
3357
void helper_debug(void)
3358
{
3359
    env->exception_index = EXCP_DEBUG;
3360
    cpu_loop_exit();
3361
}
3362

    
3363
#ifndef TARGET_SPARC64
3364
/* XXX: use another pointer for %iN registers to avoid slow wrapping
3365
   handling ? */
3366
void helper_save(void)
3367
{
3368
    uint32_t cwp;
3369

    
3370
    cwp = cwp_dec(env->cwp - 1);
3371
    if (env->wim & (1 << cwp)) {
3372
        raise_exception(TT_WIN_OVF);
3373
    }
3374
    set_cwp(cwp);
3375
}
3376

    
3377
void helper_restore(void)
3378
{
3379
    uint32_t cwp;
3380

    
3381
    cwp = cwp_inc(env->cwp + 1);
3382
    if (env->wim & (1 << cwp)) {
3383
        raise_exception(TT_WIN_UNF);
3384
    }
3385
    set_cwp(cwp);
3386
}
3387

    
3388
void helper_wrpsr(target_ulong new_psr)
3389
{
3390
    if ((new_psr & PSR_CWP) >= env->nwindows) {
3391
        raise_exception(TT_ILL_INSN);
3392
    } else {
3393
        cpu_put_psr(env, new_psr);
3394
    }
3395
}
3396

    
3397
target_ulong helper_rdpsr(void)
3398
{
3399
    return get_psr();
3400
}
3401

    
3402
#else
3403
/* XXX: use another pointer for %iN registers to avoid slow wrapping
3404
   handling ? */
3405
void helper_save(void)
3406
{
3407
    uint32_t cwp;
3408

    
3409
    cwp = cwp_dec(env->cwp - 1);
3410
    if (env->cansave == 0) {
3411
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
3412
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
3413
                                    ((env->wstate & 0x7) << 2)));
3414
    } else {
3415
        if (env->cleanwin - env->canrestore == 0) {
3416
            // XXX Clean windows without trap
3417
            raise_exception(TT_CLRWIN);
3418
        } else {
3419
            env->cansave--;
3420
            env->canrestore++;
3421
            set_cwp(cwp);
3422
        }
3423
    }
3424
}
3425

    
3426
void helper_restore(void)
3427
{
3428
    uint32_t cwp;
3429

    
3430
    cwp = cwp_inc(env->cwp + 1);
3431
    if (env->canrestore == 0) {
3432
        raise_exception(TT_FILL | (env->otherwin != 0 ?
3433
                                   (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
3434
                                   ((env->wstate & 0x7) << 2)));
3435
    } else {
3436
        env->cansave++;
3437
        env->canrestore--;
3438
        set_cwp(cwp);
3439
    }
3440
}
3441

    
3442
void helper_flushw(void)
3443
{
3444
    if (env->cansave != env->nwindows - 2) {
3445
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
3446
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
3447
                                    ((env->wstate & 0x7) << 2)));
3448
    }
3449
}
3450

    
3451
void helper_saved(void)
3452
{
3453
    env->cansave++;
3454
    if (env->otherwin == 0)
3455
        env->canrestore--;
3456
    else
3457
        env->otherwin--;
3458
}
3459

    
3460
void helper_restored(void)
3461
{
3462
    env->canrestore++;
3463
    if (env->cleanwin < env->nwindows - 1)
3464
        env->cleanwin++;
3465
    if (env->otherwin == 0)
3466
        env->cansave--;
3467
    else
3468
        env->otherwin--;
3469
}
3470

    
3471
static target_ulong get_ccr(void)
3472
{
3473
    target_ulong psr;
3474

    
3475
    psr = get_psr();
3476

    
3477
    return ((env->xcc >> 20) << 4) | ((psr & PSR_ICC) >> 20);
3478
}
3479

    
3480
target_ulong cpu_get_ccr(CPUState *env1)
3481
{
3482
    CPUState *saved_env;
3483
    target_ulong ret;
3484

    
3485
    saved_env = env;
3486
    env = env1;
3487
    ret = get_ccr();
3488
    env = saved_env;
3489
    return ret;
3490
}
3491

    
3492
static void put_ccr(target_ulong val)
3493
{
3494
    target_ulong tmp = val;
3495

    
3496
    env->xcc = (tmp >> 4) << 20;
3497
    env->psr = (tmp & 0xf) << 20;
3498
    CC_OP = CC_OP_FLAGS;
3499
}
3500

    
3501
void cpu_put_ccr(CPUState *env1, target_ulong val)
3502
{
3503
    CPUState *saved_env;
3504

    
3505
    saved_env = env;
3506
    env = env1;
3507
    put_ccr(val);
3508
    env = saved_env;
3509
}
3510

    
3511
static target_ulong get_cwp64(void)
3512
{
3513
    return env->nwindows - 1 - env->cwp;
3514
}
3515

    
3516
target_ulong cpu_get_cwp64(CPUState *env1)
3517
{
3518
    CPUState *saved_env;
3519
    target_ulong ret;
3520

    
3521
    saved_env = env;
3522
    env = env1;
3523
    ret = get_cwp64();
3524
    env = saved_env;
3525
    return ret;
3526
}
3527

    
3528
static void put_cwp64(int cwp)
3529
{
3530
    if (unlikely(cwp >= env->nwindows || cwp < 0)) {
3531
        cwp %= env->nwindows;
3532
    }
3533
    set_cwp(env->nwindows - 1 - cwp);
3534
}
3535

    
3536
void cpu_put_cwp64(CPUState *env1, int cwp)
3537
{
3538
    CPUState *saved_env;
3539

    
3540
    saved_env = env;
3541
    env = env1;
3542
    put_cwp64(cwp);
3543
    env = saved_env;
3544
}
3545

    
3546
target_ulong helper_rdccr(void)
3547
{
3548
    return get_ccr();
3549
}
3550

    
3551
void helper_wrccr(target_ulong new_ccr)
3552
{
3553
    put_ccr(new_ccr);
3554
}
3555

    
3556
// CWP handling is reversed in V9, but we still use the V8 register
3557
// order.
3558
target_ulong helper_rdcwp(void)
3559
{
3560
    return get_cwp64();
3561
}
3562

    
3563
void helper_wrcwp(target_ulong new_cwp)
3564
{
3565
    put_cwp64(new_cwp);
3566
}
3567

    
3568
// This function uses non-native bit order
3569
#define GET_FIELD(X, FROM, TO)                                  \
3570
    ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
3571

    
3572
// This function uses the order in the manuals, i.e. bit 0 is 2^0
3573
#define GET_FIELD_SP(X, FROM, TO)               \
3574
    GET_FIELD(X, 63 - (TO), 63 - (FROM))
3575

    
3576
target_ulong helper_array8(target_ulong pixel_addr, target_ulong cubesize)
3577
{
3578
    return (GET_FIELD_SP(pixel_addr, 60, 63) << (17 + 2 * cubesize)) |
3579
        (GET_FIELD_SP(pixel_addr, 39, 39 + cubesize - 1) << (17 + cubesize)) |
3580
        (GET_FIELD_SP(pixel_addr, 17 + cubesize - 1, 17) << 17) |
3581
        (GET_FIELD_SP(pixel_addr, 56, 59) << 13) |
3582
        (GET_FIELD_SP(pixel_addr, 35, 38) << 9) |
3583
        (GET_FIELD_SP(pixel_addr, 13, 16) << 5) |
3584
        (((pixel_addr >> 55) & 1) << 4) |
3585
        (GET_FIELD_SP(pixel_addr, 33, 34) << 2) |
3586
        GET_FIELD_SP(pixel_addr, 11, 12);
3587
}
3588

    
3589
target_ulong helper_alignaddr(target_ulong addr, target_ulong offset)
3590
{
3591
    uint64_t tmp;
3592

    
3593
    tmp = addr + offset;
3594
    env->gsr &= ~7ULL;
3595
    env->gsr |= tmp & 7ULL;
3596
    return tmp & ~7ULL;
3597
}
3598

    
3599
target_ulong helper_popc(target_ulong val)
3600
{
3601
    return ctpop64(val);
3602
}
3603

    
3604
static inline uint64_t *get_gregset(uint32_t pstate)
3605
{
3606
    switch (pstate) {
3607
    default:
3608
        DPRINTF_PSTATE("ERROR in get_gregset: active pstate bits=%x%s%s%s\n",
3609
                pstate,
3610
                (pstate & PS_IG) ? " IG" : "",
3611
                (pstate & PS_MG) ? " MG" : "",
3612
                (pstate & PS_AG) ? " AG" : "");
3613
        /* pass through to normal set of global registers */
3614
    case 0:
3615
        return env->bgregs;
3616
    case PS_AG:
3617
        return env->agregs;
3618
    case PS_MG:
3619
        return env->mgregs;
3620
    case PS_IG:
3621
        return env->igregs;
3622
    }
3623
}
3624

    
3625
static inline void change_pstate(uint32_t new_pstate)
3626
{
3627
    uint32_t pstate_regs, new_pstate_regs;
3628
    uint64_t *src, *dst;
3629

    
3630
    if (env->def->features & CPU_FEATURE_GL) {
3631
        // PS_AG is not implemented in this case
3632
        new_pstate &= ~PS_AG;
3633
    }
3634

    
3635
    pstate_regs = env->pstate & 0xc01;
3636
    new_pstate_regs = new_pstate & 0xc01;
3637

    
3638
    if (new_pstate_regs != pstate_regs) {
3639
        DPRINTF_PSTATE("change_pstate: switching regs old=%x new=%x\n",
3640
                       pstate_regs, new_pstate_regs);
3641
        // Switch global register bank
3642
        src = get_gregset(new_pstate_regs);
3643
        dst = get_gregset(pstate_regs);
3644
        memcpy32(dst, env->gregs);
3645
        memcpy32(env->gregs, src);
3646
    }
3647
    else {
3648
        DPRINTF_PSTATE("change_pstate: regs new=%x (unchanged)\n",
3649
                       new_pstate_regs);
3650
    }
3651
    env->pstate = new_pstate;
3652
}
3653

    
3654
void helper_wrpstate(target_ulong new_state)
3655
{
3656
    change_pstate(new_state & 0xf3f);
3657

    
3658
#if !defined(CONFIG_USER_ONLY)
3659
    if (cpu_interrupts_enabled(env)) {
3660
        cpu_check_irqs(env);
3661
    }
3662
#endif
3663
}
3664

    
3665
void helper_wrpil(target_ulong new_pil)
3666
{
3667
#if !defined(CONFIG_USER_ONLY)
3668
    DPRINTF_PSTATE("helper_wrpil old=%x new=%x\n",
3669
                   env->psrpil, (uint32_t)new_pil);
3670

    
3671
    env->psrpil = new_pil;
3672

    
3673
    if (cpu_interrupts_enabled(env)) {
3674
        cpu_check_irqs(env);
3675
    }
3676
#endif
3677
}
3678

    
3679
void helper_done(void)
3680
{
3681
    trap_state* tsptr = cpu_tsptr(env);
3682

    
3683
    env->pc = tsptr->tnpc;
3684
    env->npc = tsptr->tnpc + 4;
3685
    put_ccr(tsptr->tstate >> 32);
3686
    env->asi = (tsptr->tstate >> 24) & 0xff;
3687
    change_pstate((tsptr->tstate >> 8) & 0xf3f);
3688
    put_cwp64(tsptr->tstate & 0xff);
3689
    env->tl--;
3690

    
3691
    DPRINTF_PSTATE("... helper_done tl=%d\n", env->tl);
3692

    
3693
#if !defined(CONFIG_USER_ONLY)
3694
    if (cpu_interrupts_enabled(env)) {
3695
        cpu_check_irqs(env);
3696
    }
3697
#endif
3698
}
3699

    
3700
void helper_retry(void)
3701
{
3702
    trap_state* tsptr = cpu_tsptr(env);
3703

    
3704
    env->pc = tsptr->tpc;
3705
    env->npc = tsptr->tnpc;
3706
    put_ccr(tsptr->tstate >> 32);
3707
    env->asi = (tsptr->tstate >> 24) & 0xff;
3708
    change_pstate((tsptr->tstate >> 8) & 0xf3f);
3709
    put_cwp64(tsptr->tstate & 0xff);
3710
    env->tl--;
3711

    
3712
    DPRINTF_PSTATE("... helper_retry tl=%d\n", env->tl);
3713

    
3714
#if !defined(CONFIG_USER_ONLY)
3715
    if (cpu_interrupts_enabled(env)) {
3716
        cpu_check_irqs(env);
3717
    }
3718
#endif
3719
}
3720

    
3721
static void do_modify_softint(const char* operation, uint32_t value)
3722
{
3723
    if (env->softint != value) {
3724
        env->softint = value;
3725
        DPRINTF_PSTATE(": %s new %08x\n", operation, env->softint);
3726
#if !defined(CONFIG_USER_ONLY)
3727
        if (cpu_interrupts_enabled(env)) {
3728
            cpu_check_irqs(env);
3729
        }
3730
#endif
3731
    }
3732
}
3733

    
3734
void helper_set_softint(uint64_t value)
3735
{
3736
    do_modify_softint("helper_set_softint", env->softint | (uint32_t)value);
3737
}
3738

    
3739
void helper_clear_softint(uint64_t value)
3740
{
3741
    do_modify_softint("helper_clear_softint", env->softint & (uint32_t)~value);
3742
}
3743

    
3744
void helper_write_softint(uint64_t value)
3745
{
3746
    do_modify_softint("helper_write_softint", (uint32_t)value);
3747
}
3748
#endif
3749

    
3750
void helper_flush(target_ulong addr)
3751
{
3752
    addr &= ~7;
3753
    tb_invalidate_page_range(addr, addr + 8);
3754
}
3755

    
3756
#ifdef TARGET_SPARC64
3757
#ifdef DEBUG_PCALL
3758
static const char * const excp_names[0x80] = {
3759
    [TT_TFAULT] = "Instruction Access Fault",
3760
    [TT_TMISS] = "Instruction Access MMU Miss",
3761
    [TT_CODE_ACCESS] = "Instruction Access Error",
3762
    [TT_ILL_INSN] = "Illegal Instruction",
3763
    [TT_PRIV_INSN] = "Privileged Instruction",
3764
    [TT_NFPU_INSN] = "FPU Disabled",
3765
    [TT_FP_EXCP] = "FPU Exception",
3766
    [TT_TOVF] = "Tag Overflow",
3767
    [TT_CLRWIN] = "Clean Windows",
3768
    [TT_DIV_ZERO] = "Division By Zero",
3769
    [TT_DFAULT] = "Data Access Fault",
3770
    [TT_DMISS] = "Data Access MMU Miss",
3771
    [TT_DATA_ACCESS] = "Data Access Error",
3772
    [TT_DPROT] = "Data Protection Error",
3773
    [TT_UNALIGNED] = "Unaligned Memory Access",
3774
    [TT_PRIV_ACT] = "Privileged Action",
3775
    [TT_EXTINT | 0x1] = "External Interrupt 1",
3776
    [TT_EXTINT | 0x2] = "External Interrupt 2",
3777
    [TT_EXTINT | 0x3] = "External Interrupt 3",
3778
    [TT_EXTINT | 0x4] = "External Interrupt 4",
3779
    [TT_EXTINT | 0x5] = "External Interrupt 5",
3780
    [TT_EXTINT | 0x6] = "External Interrupt 6",
3781
    [TT_EXTINT | 0x7] = "External Interrupt 7",
3782
    [TT_EXTINT | 0x8] = "External Interrupt 8",
3783
    [TT_EXTINT | 0x9] = "External Interrupt 9",
3784
    [TT_EXTINT | 0xa] = "External Interrupt 10",
3785
    [TT_EXTINT | 0xb] = "External Interrupt 11",
3786
    [TT_EXTINT | 0xc] = "External Interrupt 12",
3787
    [TT_EXTINT | 0xd] = "External Interrupt 13",
3788
    [TT_EXTINT | 0xe] = "External Interrupt 14",
3789
    [TT_EXTINT | 0xf] = "External Interrupt 15",
3790
};
3791
#endif
3792

    
3793
trap_state* cpu_tsptr(CPUState* env)
3794
{
3795
    return &env->ts[env->tl & MAXTL_MASK];
3796
}
3797

    
3798
void do_interrupt(CPUState *env)
3799
{
3800
    int intno = env->exception_index;
3801
    trap_state* tsptr;
3802

    
3803
#ifdef DEBUG_PCALL
3804
    if (qemu_loglevel_mask(CPU_LOG_INT)) {
3805
        static int count;
3806
        const char *name;
3807

    
3808
        if (intno < 0 || intno >= 0x180)
3809
            name = "Unknown";
3810
        else if (intno >= 0x100)
3811
            name = "Trap Instruction";
3812
        else if (intno >= 0xc0)
3813
            name = "Window Fill";
3814
        else if (intno >= 0x80)
3815
            name = "Window Spill";
3816
        else {
3817
            name = excp_names[intno];
3818
            if (!name)
3819
                name = "Unknown";
3820
        }
3821

    
3822
        qemu_log("%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
3823
                " SP=%016" PRIx64 "\n",
3824
                count, name, intno,
3825
                env->pc,
3826
                env->npc, env->regwptr[6]);
3827
        log_cpu_state(env, 0);
3828
#if 0
3829
        {
3830
            int i;
3831
            uint8_t *ptr;
3832

3833
            qemu_log("       code=");
3834
            ptr = (uint8_t *)env->pc;
3835
            for(i = 0; i < 16; i++) {
3836
                qemu_log(" %02x", ldub(ptr + i));
3837
            }
3838
            qemu_log("\n");
3839
        }
3840
#endif
3841
        count++;
3842
    }
3843
#endif
3844
#if !defined(CONFIG_USER_ONLY)
3845
    if (env->tl >= env->maxtl) {
3846
        cpu_abort(env, "Trap 0x%04x while trap level (%d) >= MAXTL (%d),"
3847
                  " Error state", env->exception_index, env->tl, env->maxtl);
3848
        return;
3849
    }
3850
#endif
3851
    if (env->tl < env->maxtl - 1) {
3852
        env->tl++;
3853
    } else {
3854
        env->pstate |= PS_RED;
3855
        if (env->tl < env->maxtl)
3856
            env->tl++;
3857
    }
3858
    tsptr = cpu_tsptr(env);
3859

    
3860
    tsptr->tstate = (get_ccr() << 32) |
3861
        ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
3862
        get_cwp64();
3863
    tsptr->tpc = env->pc;
3864
    tsptr->tnpc = env->npc;
3865
    tsptr->tt = intno;
3866

    
3867
    switch (intno) {
3868
    case TT_IVEC:
3869
        change_pstate(PS_PEF | PS_PRIV | PS_IG);
3870
        break;
3871
    case TT_TFAULT:
3872
    case TT_DFAULT:
3873
    case TT_TMISS ... TT_TMISS + 3:
3874
    case TT_DMISS ... TT_DMISS + 3:
3875
    case TT_DPROT ... TT_DPROT + 3:
3876
        change_pstate(PS_PEF | PS_PRIV | PS_MG);
3877
        break;
3878
    default:
3879
        change_pstate(PS_PEF | PS_PRIV | PS_AG);
3880
        break;
3881
    }
3882

    
3883
    if (intno == TT_CLRWIN) {
3884
        set_cwp(cwp_dec(env->cwp - 1));
3885
    } else if ((intno & 0x1c0) == TT_SPILL) {
3886
        set_cwp(cwp_dec(env->cwp - env->cansave - 2));
3887
    } else if ((intno & 0x1c0) == TT_FILL) {
3888
        set_cwp(cwp_inc(env->cwp + 1));
3889
    }
3890
    env->tbr &= ~0x7fffULL;
3891
    env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
3892
    env->pc = env->tbr;
3893
    env->npc = env->pc + 4;
3894
    env->exception_index = -1;
3895
}
3896
#else
3897
#ifdef DEBUG_PCALL
3898
static const char * const excp_names[0x80] = {
3899
    [TT_TFAULT] = "Instruction Access Fault",
3900
    [TT_ILL_INSN] = "Illegal Instruction",
3901
    [TT_PRIV_INSN] = "Privileged Instruction",
3902
    [TT_NFPU_INSN] = "FPU Disabled",
3903
    [TT_WIN_OVF] = "Window Overflow",
3904
    [TT_WIN_UNF] = "Window Underflow",
3905
    [TT_UNALIGNED] = "Unaligned Memory Access",
3906
    [TT_FP_EXCP] = "FPU Exception",
3907
    [TT_DFAULT] = "Data Access Fault",
3908
    [TT_TOVF] = "Tag Overflow",
3909
    [TT_EXTINT | 0x1] = "External Interrupt 1",
3910
    [TT_EXTINT | 0x2] = "External Interrupt 2",
3911
    [TT_EXTINT | 0x3] = "External Interrupt 3",
3912
    [TT_EXTINT | 0x4] = "External Interrupt 4",
3913
    [TT_EXTINT | 0x5] = "External Interrupt 5",
3914
    [TT_EXTINT | 0x6] = "External Interrupt 6",
3915
    [TT_EXTINT | 0x7] = "External Interrupt 7",
3916
    [TT_EXTINT | 0x8] = "External Interrupt 8",
3917
    [TT_EXTINT | 0x9] = "External Interrupt 9",
3918
    [TT_EXTINT | 0xa] = "External Interrupt 10",
3919
    [TT_EXTINT | 0xb] = "External Interrupt 11",
3920
    [TT_EXTINT | 0xc] = "External Interrupt 12",
3921
    [TT_EXTINT | 0xd] = "External Interrupt 13",
3922
    [TT_EXTINT | 0xe] = "External Interrupt 14",
3923
    [TT_EXTINT | 0xf] = "External Interrupt 15",
3924
    [TT_TOVF] = "Tag Overflow",
3925
    [TT_CODE_ACCESS] = "Instruction Access Error",
3926
    [TT_DATA_ACCESS] = "Data Access Error",
3927
    [TT_DIV_ZERO] = "Division By Zero",
3928
    [TT_NCP_INSN] = "Coprocessor Disabled",
3929
};
3930
#endif
3931

    
3932
void do_interrupt(CPUState *env)
3933
{
3934
    int cwp, intno = env->exception_index;
3935

    
3936
#ifdef DEBUG_PCALL
3937
    if (qemu_loglevel_mask(CPU_LOG_INT)) {
3938
        static int count;
3939
        const char *name;
3940

    
3941
        if (intno < 0 || intno >= 0x100)
3942
            name = "Unknown";
3943
        else if (intno >= 0x80)
3944
            name = "Trap Instruction";
3945
        else {
3946
            name = excp_names[intno];
3947
            if (!name)
3948
                name = "Unknown";
3949
        }
3950

    
3951
        qemu_log("%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
3952
                count, name, intno,
3953
                env->pc,
3954
                env->npc, env->regwptr[6]);
3955
        log_cpu_state(env, 0);
3956
#if 0
3957
        {
3958
            int i;
3959
            uint8_t *ptr;
3960

3961
            qemu_log("       code=");
3962
            ptr = (uint8_t *)env->pc;
3963
            for(i = 0; i < 16; i++) {
3964
                qemu_log(" %02x", ldub(ptr + i));
3965
            }
3966
            qemu_log("\n");
3967
        }
3968
#endif
3969
        count++;
3970
    }
3971
#endif
3972
#if !defined(CONFIG_USER_ONLY)
3973
    if (env->psret == 0) {
3974
        cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
3975
                  env->exception_index);
3976
        return;
3977
    }
3978
#endif
3979
    env->psret = 0;
3980
    cwp = cwp_dec(env->cwp - 1);
3981
    set_cwp(cwp);
3982
    env->regwptr[9] = env->pc;
3983
    env->regwptr[10] = env->npc;
3984
    env->psrps = env->psrs;
3985
    env->psrs = 1;
3986
    env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
3987
    env->pc = env->tbr;
3988
    env->npc = env->pc + 4;
3989
    env->exception_index = -1;
3990
}
3991
#endif
3992

    
3993
#if !defined(CONFIG_USER_ONLY)
3994

    
3995
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
3996
                                void *retaddr);
3997

    
3998
#define MMUSUFFIX _mmu
3999
#define ALIGNED_ONLY
4000

    
4001
#define SHIFT 0
4002
#include "softmmu_template.h"
4003

    
4004
#define SHIFT 1
4005
#include "softmmu_template.h"
4006

    
4007
#define SHIFT 2
4008
#include "softmmu_template.h"
4009

    
4010
#define SHIFT 3
4011
#include "softmmu_template.h"
4012

    
4013
/* XXX: make it generic ? */
4014
static void cpu_restore_state2(void *retaddr)
4015
{
4016
    TranslationBlock *tb;
4017
    unsigned long pc;
4018

    
4019
    if (retaddr) {
4020
        /* now we have a real cpu fault */
4021
        pc = (unsigned long)retaddr;
4022
        tb = tb_find_pc(pc);
4023
        if (tb) {
4024
            /* the PC is inside the translated code. It means that we have
4025
               a virtual CPU fault */
4026
            cpu_restore_state(tb, env, pc, (void *)(long)env->cond);
4027
        }
4028
    }
4029
}
4030

    
4031
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
4032
                                void *retaddr)
4033
{
4034
#ifdef DEBUG_UNALIGNED
4035
    printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
4036
           "\n", addr, env->pc);
4037
#endif
4038
    cpu_restore_state2(retaddr);
4039
    raise_exception(TT_UNALIGNED);
4040
}
4041

    
4042
/* try to fill the TLB and return an exception if error. If retaddr is
4043
   NULL, it means that the function was called in C code (i.e. not
4044
   from generated code or from helper.c) */
4045
/* XXX: fix it to restore all registers */
4046
void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
4047
{
4048
    int ret;
4049
    CPUState *saved_env;
4050

    
4051
    /* XXX: hack to restore env in all cases, even if not called from
4052
       generated code */
4053
    saved_env = env;
4054
    env = cpu_single_env;
4055

    
4056
    ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
4057
    if (ret) {
4058
        cpu_restore_state2(retaddr);
4059
        cpu_loop_exit();
4060
    }
4061
    env = saved_env;
4062
}
4063

    
4064
#endif /* !CONFIG_USER_ONLY */
4065

    
4066
#ifndef TARGET_SPARC64
4067
#if !defined(CONFIG_USER_ONLY)
4068
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
4069
                          int is_asi, int size)
4070
{
4071
    CPUState *saved_env;
4072
    int fault_type;
4073

    
4074
    /* XXX: hack to restore env in all cases, even if not called from
4075
       generated code */
4076
    saved_env = env;
4077
    env = cpu_single_env;
4078
#ifdef DEBUG_UNASSIGNED
4079
    if (is_asi)
4080
        printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
4081
               " asi 0x%02x from " TARGET_FMT_lx "\n",
4082
               is_exec ? "exec" : is_write ? "write" : "read", size,
4083
               size == 1 ? "" : "s", addr, is_asi, env->pc);
4084
    else
4085
        printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
4086
               " from " TARGET_FMT_lx "\n",
4087
               is_exec ? "exec" : is_write ? "write" : "read", size,
4088
               size == 1 ? "" : "s", addr, env->pc);
4089
#endif
4090
    /* Don't overwrite translation and access faults */
4091
    fault_type = (env->mmuregs[3] & 0x1c) >> 2;
4092
    if ((fault_type > 4) || (fault_type == 0)) {
4093
        env->mmuregs[3] = 0; /* Fault status register */
4094
        if (is_asi)
4095
            env->mmuregs[3] |= 1 << 16;
4096
        if (env->psrs)
4097
            env->mmuregs[3] |= 1 << 5;
4098
        if (is_exec)
4099
            env->mmuregs[3] |= 1 << 6;
4100
        if (is_write)
4101
            env->mmuregs[3] |= 1 << 7;
4102
        env->mmuregs[3] |= (5 << 2) | 2;
4103
        /* SuperSPARC will never place instruction fault addresses in the FAR */
4104
        if (!is_exec) {
4105
            env->mmuregs[4] = addr; /* Fault address register */
4106
        }
4107
    }
4108
    /* overflow (same type fault was not read before another fault) */
4109
    if (fault_type == ((env->mmuregs[3] & 0x1c)) >> 2) {
4110
        env->mmuregs[3] |= 1;
4111
    }
4112

    
4113
    if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
4114
        if (is_exec)
4115
            raise_exception(TT_CODE_ACCESS);
4116
        else
4117
            raise_exception(TT_DATA_ACCESS);
4118
    }
4119

    
4120
    /* flush neverland mappings created during no-fault mode,
4121
       so the sequential MMU faults report proper fault types */
4122
    if (env->mmuregs[0] & MMU_NF) {
4123
        tlb_flush(env, 1);
4124
    }
4125

    
4126
    env = saved_env;
4127
}
4128
#endif
4129
#else
4130
#if defined(CONFIG_USER_ONLY)
4131
static void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
4132
                          int is_asi, int size)
4133
#else
4134
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
4135
                          int is_asi, int size)
4136
#endif
4137
{
4138
    CPUState *saved_env;
4139

    
4140
    /* XXX: hack to restore env in all cases, even if not called from
4141
       generated code */
4142
    saved_env = env;
4143
    env = cpu_single_env;
4144

    
4145
#ifdef DEBUG_UNASSIGNED
4146
    printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx
4147
           "\n", addr, env->pc);
4148
#endif
4149

    
4150
    if (is_exec)
4151
        raise_exception(TT_CODE_ACCESS);
4152
    else
4153
        raise_exception(TT_DATA_ACCESS);
4154

    
4155
    env = saved_env;
4156
}
4157
#endif
4158

    
4159

    
4160
#ifdef TARGET_SPARC64
4161
void helper_tick_set_count(void *opaque, uint64_t count)
4162
{
4163
#if !defined(CONFIG_USER_ONLY)
4164
    cpu_tick_set_count(opaque, count);
4165
#endif
4166
}
4167

    
4168
uint64_t helper_tick_get_count(void *opaque)
4169
{
4170
#if !defined(CONFIG_USER_ONLY)
4171
    return cpu_tick_get_count(opaque);
4172
#else
4173
    return 0;
4174
#endif
4175
}
4176

    
4177
void helper_tick_set_limit(void *opaque, uint64_t limit)
4178
{
4179
#if !defined(CONFIG_USER_ONLY)
4180
    cpu_tick_set_limit(opaque, limit);
4181
#endif
4182
}
4183
#endif