Statistics
| Branch: | Revision:

root / target-sparc / op_helper.c @ 4c1a0d82

History | View | Annotate | Download (113.3 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
#define DT0 (env->dt0)
48
#define DT1 (env->dt1)
49
#define QT0 (env->qt0)
50
#define QT1 (env->qt1)
51

    
52
#if defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64)
53
static void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
54
                          int is_asi, int size);
55
#endif
56

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

    
67
    // discard lower 13 bits which hold tag access context
68
    uint64_t tag_access_va = tag_access_register & ~0x1fffULL;
69

    
70
    // now reorder bits
71
    uint64_t tsb_base_mask = ~0x1fffULL;
72
    uint64_t va = tag_access_va;
73

    
74
    // move va bits to correct position
75
    if (page_size == 8*1024) {
76
        va >>= 9;
77
    } else if (page_size == 64*1024) {
78
        va >>= 12;
79
    }
80

    
81
    if (tsb_size) {
82
        tsb_base_mask <<= tsb_size;
83
    }
84

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

    
95
    return ((tsb_base & tsb_base_mask) | (va & ~tsb_base_mask)) & ~0xfULL;
96
}
97

    
98
// Calculates tag target register value by reordering bits
99
// in tag access register
100
static uint64_t ultrasparc_tag_target(uint64_t tag_access_register)
101
{
102
    return ((tag_access_register & 0x1fff) << 48) | (tag_access_register >> 22);
103
}
104

    
105
static void replace_tlb_entry(SparcTLBEntry *tlb,
106
                              uint64_t tlb_tag, uint64_t tlb_tte,
107
                              CPUState *env1)
108
{
109
    target_ulong mask, size, va, offset;
110

    
111
    // flush page range if translation is valid
112
    if (TTE_IS_VALID(tlb->tte)) {
113

    
114
        mask = 0xffffffffffffe000ULL;
115
        mask <<= 3 * ((tlb->tte >> 61) & 3);
116
        size = ~mask + 1;
117

    
118
        va = tlb->tag & mask;
119

    
120
        for (offset = 0; offset < size; offset += TARGET_PAGE_SIZE) {
121
            tlb_flush_page(env1, va + offset);
122
        }
123
    }
124

    
125
    tlb->tag = tlb_tag;
126
    tlb->tte = tlb_tte;
127
}
128

    
129
static void demap_tlb(SparcTLBEntry *tlb, target_ulong demap_addr,
130
                      const char* strmmu, CPUState *env1)
131
{
132
    unsigned int i;
133
    target_ulong mask;
134
    uint64_t context;
135

    
136
    int is_demap_context = (demap_addr >> 6) & 1;
137

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

    
154
    for (i = 0; i < 64; i++) {
155
        if (TTE_IS_VALID(tlb[i].tte)) {
156

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

    
169
                if (!compare_masked(demap_addr, tlb[i].tag, mask)) {
170
                    continue;
171
                }
172

    
173
                // entry should be global or matching context value
174
                if (!TTE_IS_GLOBAL(tlb[i].tte) &&
175
                    !tlb_compare_context(&tlb[i], context)) {
176
                    continue;
177
                }
178
            }
179

    
180
            replace_tlb_entry(&tlb[i], 0, 0, env1);
181
#ifdef DEBUG_MMU
182
            DPRINTF_MMU("%s demap invalidated entry [%02u]\n", strmmu, i);
183
            dump_mmu(env1);
184
#endif
185
        }
186
    }
187
}
188

    
189
static void replace_tlb_1bit_lru(SparcTLBEntry *tlb,
190
                                 uint64_t tlb_tag, uint64_t tlb_tte,
191
                                 const char* strmmu, CPUState *env1)
192
{
193
    unsigned int i, replace_used;
194

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

    
207
    // All entries are valid, try replacing unlocked entry
208

    
209
    for (replace_used = 0; replace_used < 2; ++replace_used) {
210

    
211
        // Used entries are not replaced on first pass
212

    
213
        for (i = 0; i < 64; i++) {
214
            if (!TTE_IS_LOCKED(tlb[i].tte) && !TTE_IS_USED(tlb[i].tte)) {
215

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

    
226
        // Now reset used bit and search for unused entries again
227

    
228
        for (i = 0; i < 64; i++) {
229
            TTE_SET_UNUSED(tlb[i].tte);
230
        }
231
    }
232

    
233
#ifdef DEBUG_MMU
234
    DPRINTF_MMU("%s lru replacement failed: no entries available\n", strmmu);
235
#endif
236
    // error state?
237
}
238

    
239
#endif
240

    
241
static inline target_ulong address_mask(CPUState *env1, target_ulong addr)
242
{
243
#ifdef TARGET_SPARC64
244
    if (AM_CHECK(env1))
245
        addr &= 0xffffffffULL;
246
#endif
247
    return addr;
248
}
249

    
250
static void raise_exception(int tt)
251
{
252
    env->exception_index = tt;
253
    cpu_loop_exit();
254
}
255

    
256
void HELPER(raise_exception)(int tt)
257
{
258
    raise_exception(tt);
259
}
260

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

    
272
#define F_HELPER(name, p) void helper_f##name##p(void)
273

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

    
288
F_BINOP(add);
289
F_BINOP(sub);
290
F_BINOP(mul);
291
F_BINOP(div);
292
#undef F_BINOP
293

    
294
void helper_fsmuld(float32 src1, float32 src2)
295
{
296
    DT0 = float64_mul(float32_to_float64(src1, &env->fp_status),
297
                      float32_to_float64(src2, &env->fp_status),
298
                      &env->fp_status);
299
}
300

    
301
void helper_fdmulq(void)
302
{
303
    QT0 = float128_mul(float64_to_float128(DT0, &env->fp_status),
304
                       float64_to_float128(DT1, &env->fp_status),
305
                       &env->fp_status);
306
}
307

    
308
float32 helper_fnegs(float32 src)
309
{
310
    return float32_chs(src);
311
}
312

    
313
#ifdef TARGET_SPARC64
314
F_HELPER(neg, d)
315
{
316
    DT0 = float64_chs(DT1);
317
}
318

    
319
F_HELPER(neg, q)
320
{
321
    QT0 = float128_chs(QT1);
322
}
323
#endif
324

    
325
/* Integer to float conversion.  */
326
float32 helper_fitos(int32_t src)
327
{
328
    return int32_to_float32(src, &env->fp_status);
329
}
330

    
331
void helper_fitod(int32_t src)
332
{
333
    DT0 = int32_to_float64(src, &env->fp_status);
334
}
335

    
336
void helper_fitoq(int32_t src)
337
{
338
    QT0 = int32_to_float128(src, &env->fp_status);
339
}
340

    
341
#ifdef TARGET_SPARC64
342
float32 helper_fxtos(void)
343
{
344
    return int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
345
}
346

    
347
F_HELPER(xto, d)
348
{
349
    DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
350
}
351

    
352
F_HELPER(xto, q)
353
{
354
    QT0 = int64_to_float128(*((int64_t *)&DT1), &env->fp_status);
355
}
356
#endif
357
#undef F_HELPER
358

    
359
/* floating point conversion */
360
float32 helper_fdtos(void)
361
{
362
    return float64_to_float32(DT1, &env->fp_status);
363
}
364

    
365
void helper_fstod(float32 src)
366
{
367
    DT0 = float32_to_float64(src, &env->fp_status);
368
}
369

    
370
float32 helper_fqtos(void)
371
{
372
    return float128_to_float32(QT1, &env->fp_status);
373
}
374

    
375
void helper_fstoq(float32 src)
376
{
377
    QT0 = float32_to_float128(src, &env->fp_status);
378
}
379

    
380
void helper_fqtod(void)
381
{
382
    DT0 = float128_to_float64(QT1, &env->fp_status);
383
}
384

    
385
void helper_fdtoq(void)
386
{
387
    QT0 = float64_to_float128(DT1, &env->fp_status);
388
}
389

    
390
/* Float to integer conversion.  */
391
int32_t helper_fstoi(float32 src)
392
{
393
    return float32_to_int32_round_to_zero(src, &env->fp_status);
394
}
395

    
396
int32_t helper_fdtoi(void)
397
{
398
    return float64_to_int32_round_to_zero(DT1, &env->fp_status);
399
}
400

    
401
int32_t helper_fqtoi(void)
402
{
403
    return float128_to_int32_round_to_zero(QT1, &env->fp_status);
404
}
405

    
406
#ifdef TARGET_SPARC64
407
void helper_fstox(float32 src)
408
{
409
    *((int64_t *)&DT0) = float32_to_int64_round_to_zero(src, &env->fp_status);
410
}
411

    
412
void helper_fdtox(void)
413
{
414
    *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status);
415
}
416

    
417
void helper_fqtox(void)
418
{
419
    *((int64_t *)&DT0) = float128_to_int64_round_to_zero(QT1, &env->fp_status);
420
}
421

    
422
void helper_faligndata(void)
423
{
424
    uint64_t tmp;
425

    
426
    tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8);
427
    /* on many architectures a shift of 64 does nothing */
428
    if ((env->gsr & 7) != 0) {
429
        tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8);
430
    }
431
    *((uint64_t *)&DT0) = tmp;
432
}
433

    
434
#ifdef HOST_WORDS_BIGENDIAN
435
#define VIS_B64(n) b[7 - (n)]
436
#define VIS_W64(n) w[3 - (n)]
437
#define VIS_SW64(n) sw[3 - (n)]
438
#define VIS_L64(n) l[1 - (n)]
439
#define VIS_B32(n) b[3 - (n)]
440
#define VIS_W32(n) w[1 - (n)]
441
#else
442
#define VIS_B64(n) b[n]
443
#define VIS_W64(n) w[n]
444
#define VIS_SW64(n) sw[n]
445
#define VIS_L64(n) l[n]
446
#define VIS_B32(n) b[n]
447
#define VIS_W32(n) w[n]
448
#endif
449

    
450
typedef union {
451
    uint8_t b[8];
452
    uint16_t w[4];
453
    int16_t sw[4];
454
    uint32_t l[2];
455
    float64 d;
456
} vis64;
457

    
458
typedef union {
459
    uint8_t b[4];
460
    uint16_t w[2];
461
    uint32_t l;
462
    float32 f;
463
} vis32;
464

    
465
void helper_fpmerge(void)
466
{
467
    vis64 s, d;
468

    
469
    s.d = DT0;
470
    d.d = DT1;
471

    
472
    // Reverse calculation order to handle overlap
473
    d.VIS_B64(7) = s.VIS_B64(3);
474
    d.VIS_B64(6) = d.VIS_B64(3);
475
    d.VIS_B64(5) = s.VIS_B64(2);
476
    d.VIS_B64(4) = d.VIS_B64(2);
477
    d.VIS_B64(3) = s.VIS_B64(1);
478
    d.VIS_B64(2) = d.VIS_B64(1);
479
    d.VIS_B64(1) = s.VIS_B64(0);
480
    //d.VIS_B64(0) = d.VIS_B64(0);
481

    
482
    DT0 = d.d;
483
}
484

    
485
void helper_fmul8x16(void)
486
{
487
    vis64 s, d;
488
    uint32_t tmp;
489

    
490
    s.d = DT0;
491
    d.d = DT1;
492

    
493
#define PMUL(r)                                                 \
494
    tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r);       \
495
    if ((tmp & 0xff) > 0x7f)                                    \
496
        tmp += 0x100;                                           \
497
    d.VIS_W64(r) = tmp >> 8;
498

    
499
    PMUL(0);
500
    PMUL(1);
501
    PMUL(2);
502
    PMUL(3);
503
#undef PMUL
504

    
505
    DT0 = d.d;
506
}
507

    
508
void helper_fmul8x16al(void)
509
{
510
    vis64 s, d;
511
    uint32_t tmp;
512

    
513
    s.d = DT0;
514
    d.d = DT1;
515

    
516
#define PMUL(r)                                                 \
517
    tmp = (int32_t)d.VIS_SW64(1) * (int32_t)s.VIS_B64(r);       \
518
    if ((tmp & 0xff) > 0x7f)                                    \
519
        tmp += 0x100;                                           \
520
    d.VIS_W64(r) = tmp >> 8;
521

    
522
    PMUL(0);
523
    PMUL(1);
524
    PMUL(2);
525
    PMUL(3);
526
#undef PMUL
527

    
528
    DT0 = d.d;
529
}
530

    
531
void helper_fmul8x16au(void)
532
{
533
    vis64 s, d;
534
    uint32_t tmp;
535

    
536
    s.d = DT0;
537
    d.d = DT1;
538

    
539
#define PMUL(r)                                                 \
540
    tmp = (int32_t)d.VIS_SW64(0) * (int32_t)s.VIS_B64(r);       \
541
    if ((tmp & 0xff) > 0x7f)                                    \
542
        tmp += 0x100;                                           \
543
    d.VIS_W64(r) = tmp >> 8;
544

    
545
    PMUL(0);
546
    PMUL(1);
547
    PMUL(2);
548
    PMUL(3);
549
#undef PMUL
550

    
551
    DT0 = d.d;
552
}
553

    
554
void helper_fmul8sux16(void)
555
{
556
    vis64 s, d;
557
    uint32_t tmp;
558

    
559
    s.d = DT0;
560
    d.d = DT1;
561

    
562
#define PMUL(r)                                                         \
563
    tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
564
    if ((tmp & 0xff) > 0x7f)                                            \
565
        tmp += 0x100;                                                   \
566
    d.VIS_W64(r) = tmp >> 8;
567

    
568
    PMUL(0);
569
    PMUL(1);
570
    PMUL(2);
571
    PMUL(3);
572
#undef PMUL
573

    
574
    DT0 = d.d;
575
}
576

    
577
void helper_fmul8ulx16(void)
578
{
579
    vis64 s, d;
580
    uint32_t tmp;
581

    
582
    s.d = DT0;
583
    d.d = DT1;
584

    
585
#define PMUL(r)                                                         \
586
    tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
587
    if ((tmp & 0xff) > 0x7f)                                            \
588
        tmp += 0x100;                                                   \
589
    d.VIS_W64(r) = tmp >> 8;
590

    
591
    PMUL(0);
592
    PMUL(1);
593
    PMUL(2);
594
    PMUL(3);
595
#undef PMUL
596

    
597
    DT0 = d.d;
598
}
599

    
600
void helper_fmuld8sux16(void)
601
{
602
    vis64 s, d;
603
    uint32_t tmp;
604

    
605
    s.d = DT0;
606
    d.d = DT1;
607

    
608
#define PMUL(r)                                                         \
609
    tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
610
    if ((tmp & 0xff) > 0x7f)                                            \
611
        tmp += 0x100;                                                   \
612
    d.VIS_L64(r) = tmp;
613

    
614
    // Reverse calculation order to handle overlap
615
    PMUL(1);
616
    PMUL(0);
617
#undef PMUL
618

    
619
    DT0 = d.d;
620
}
621

    
622
void helper_fmuld8ulx16(void)
623
{
624
    vis64 s, d;
625
    uint32_t tmp;
626

    
627
    s.d = DT0;
628
    d.d = DT1;
629

    
630
#define PMUL(r)                                                         \
631
    tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
632
    if ((tmp & 0xff) > 0x7f)                                            \
633
        tmp += 0x100;                                                   \
634
    d.VIS_L64(r) = tmp;
635

    
636
    // Reverse calculation order to handle overlap
637
    PMUL(1);
638
    PMUL(0);
639
#undef PMUL
640

    
641
    DT0 = d.d;
642
}
643

    
644
void helper_fexpand(void)
645
{
646
    vis32 s;
647
    vis64 d;
648

    
649
    s.l = (uint32_t)(*(uint64_t *)&DT0 & 0xffffffff);
650
    d.d = DT1;
651
    d.VIS_W64(0) = s.VIS_B32(0) << 4;
652
    d.VIS_W64(1) = s.VIS_B32(1) << 4;
653
    d.VIS_W64(2) = s.VIS_B32(2) << 4;
654
    d.VIS_W64(3) = s.VIS_B32(3) << 4;
655

    
656
    DT0 = d.d;
657
}
658

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

    
713
#define FADD(a, b) ((a) + (b))
714
#define FSUB(a, b) ((a) - (b))
715
VIS_HELPER(helper_fpadd, FADD)
716
VIS_HELPER(helper_fpsub, FSUB)
717

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

    
747
#define FCMPGT(a, b) ((a) > (b))
748
#define FCMPEQ(a, b) ((a) == (b))
749
#define FCMPLE(a, b) ((a) <= (b))
750
#define FCMPNE(a, b) ((a) != (b))
751

    
752
VIS_CMPHELPER(helper_fcmpgt, FCMPGT)
753
VIS_CMPHELPER(helper_fcmpeq, FCMPEQ)
754
VIS_CMPHELPER(helper_fcmple, FCMPLE)
755
VIS_CMPHELPER(helper_fcmpne, FCMPNE)
756
#endif
757

    
758
void helper_check_ieee_exceptions(void)
759
{
760
    target_ulong status;
761

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

    
776
        if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) {
777
            /* Unmasked exception, generate a trap */
778
            env->fsr |= FSR_FTT_IEEE_EXCP;
779
            raise_exception(TT_FP_EXCP);
780
        } else {
781
            /* Accumulate exceptions */
782
            env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
783
        }
784
    }
785
}
786

    
787
void helper_clear_float_exceptions(void)
788
{
789
    set_float_exception_flags(0, &env->fp_status);
790
}
791

    
792
float32 helper_fabss(float32 src)
793
{
794
    return float32_abs(src);
795
}
796

    
797
#ifdef TARGET_SPARC64
798
void helper_fabsd(void)
799
{
800
    DT0 = float64_abs(DT1);
801
}
802

    
803
void helper_fabsq(void)
804
{
805
    QT0 = float128_abs(QT1);
806
}
807
#endif
808

    
809
float32 helper_fsqrts(float32 src)
810
{
811
    return float32_sqrt(src, &env->fp_status);
812
}
813

    
814
void helper_fsqrtd(void)
815
{
816
    DT0 = float64_sqrt(DT1, &env->fp_status);
817
}
818

    
819
void helper_fsqrtq(void)
820
{
821
    QT0 = float128_sqrt(QT1, &env->fp_status);
822
}
823

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

    
885
GEN_FCMPS(fcmps, float32, 0, 0);
886
GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
887

    
888
GEN_FCMPS(fcmpes, float32, 0, 1);
889
GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
890

    
891
GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0);
892
GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1);
893

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

    
899
static uint32_t compute_C_flags(void)
900
{
901
    return env->psr & PSR_CARRY;
902
}
903

    
904
static inline uint32_t get_NZ_icc(target_ulong dst)
905
{
906
    uint32_t ret = 0;
907

    
908
    if (!(dst & 0xffffffffULL))
909
        ret |= PSR_ZERO;
910
    if ((int32_t) (dst & 0xffffffffULL) < 0)
911
        ret |= PSR_NEG;
912
    return ret;
913
}
914

    
915
#ifdef TARGET_SPARC64
916
static uint32_t compute_all_flags_xcc(void)
917
{
918
    return env->xcc & PSR_ICC;
919
}
920

    
921
static uint32_t compute_C_flags_xcc(void)
922
{
923
    return env->xcc & PSR_CARRY;
924
}
925

    
926
static inline uint32_t get_NZ_xcc(target_ulong dst)
927
{
928
    uint32_t ret = 0;
929

    
930
    if (!dst)
931
        ret |= PSR_ZERO;
932
    if ((int64_t)dst < 0)
933
        ret |= PSR_NEG;
934
    return ret;
935
}
936
#endif
937

    
938
static inline uint32_t get_V_div_icc(target_ulong src2)
939
{
940
    uint32_t ret = 0;
941

    
942
    if (src2 != 0)
943
        ret |= PSR_OVF;
944
    return ret;
945
}
946

    
947
static uint32_t compute_all_div(void)
948
{
949
    uint32_t ret;
950

    
951
    ret = get_NZ_icc(CC_DST);
952
    ret |= get_V_div_icc(CC_SRC2);
953
    return ret;
954
}
955

    
956
static uint32_t compute_C_div(void)
957
{
958
    return 0;
959
}
960

    
961
/* carry = (src1[31] & src2[31]) | ( ~dst[31] & (src1[31] | src2[31])) */
962
static inline uint32_t get_C_add_icc(target_ulong dst, target_ulong src1,
963
                                     target_ulong src2)
964
{
965
    uint32_t ret = 0;
966

    
967
    if (((src1 & (1ULL << 31)) & (src2 & (1ULL << 31)))
968
        | ((~(dst & (1ULL << 31)))
969
           & ((src1 & (1ULL << 31)) | (src2 & (1ULL << 31)))))
970
        ret |= PSR_CARRY;
971
    return ret;
972
}
973

    
974
static inline uint32_t get_V_add_icc(target_ulong dst, target_ulong src1,
975
                                         target_ulong src2)
976
{
977
    uint32_t ret = 0;
978

    
979
    if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1ULL << 31))
980
        ret |= PSR_OVF;
981
    return ret;
982
}
983

    
984
#ifdef TARGET_SPARC64
985
static inline uint32_t get_C_add_xcc(target_ulong dst, target_ulong src1)
986
{
987
    uint32_t ret = 0;
988

    
989
    if (dst < src1)
990
        ret |= PSR_CARRY;
991
    return ret;
992
}
993

    
994
static inline uint32_t get_V_add_xcc(target_ulong dst, target_ulong src1,
995
                                         target_ulong src2)
996
{
997
    uint32_t ret = 0;
998

    
999
    if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1ULL << 63))
1000
        ret |= PSR_OVF;
1001
    return ret;
1002
}
1003

    
1004
static uint32_t compute_all_add_xcc(void)
1005
{
1006
    uint32_t ret;
1007

    
1008
    ret = get_NZ_xcc(CC_DST);
1009
    ret |= get_C_add_xcc(CC_DST, CC_SRC);
1010
    ret |= get_V_add_xcc(CC_DST, CC_SRC, CC_SRC2);
1011
    return ret;
1012
}
1013

    
1014
static uint32_t compute_C_add_xcc(void)
1015
{
1016
    return get_C_add_xcc(CC_DST, CC_SRC);
1017
}
1018
#endif
1019

    
1020
static uint32_t compute_all_add(void)
1021
{
1022
    uint32_t ret;
1023

    
1024
    ret = get_NZ_icc(CC_DST);
1025
    ret |= get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
1026
    ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
1027
    return ret;
1028
}
1029

    
1030
static uint32_t compute_C_add(void)
1031
{
1032
    return get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
1033
}
1034

    
1035
#ifdef TARGET_SPARC64
1036
static uint32_t compute_all_addx_xcc(void)
1037
{
1038
    uint32_t ret;
1039

    
1040
    ret = get_NZ_xcc(CC_DST);
1041
    ret |= get_C_add_xcc(CC_DST - CC_SRC2, CC_SRC);
1042
    ret |= get_C_add_xcc(CC_DST, CC_SRC);
1043
    ret |= get_V_add_xcc(CC_DST, CC_SRC, CC_SRC2);
1044
    return ret;
1045
}
1046

    
1047
static uint32_t compute_C_addx_xcc(void)
1048
{
1049
    uint32_t ret;
1050

    
1051
    ret = get_C_add_xcc(CC_DST - CC_SRC2, CC_SRC);
1052
    ret |= get_C_add_xcc(CC_DST, CC_SRC);
1053
    return ret;
1054
}
1055
#endif
1056

    
1057
static inline uint32_t get_V_tag_icc(target_ulong src1, target_ulong src2)
1058
{
1059
    uint32_t ret = 0;
1060

    
1061
    if ((src1 | src2) & 0x3)
1062
        ret |= PSR_OVF;
1063
    return ret;
1064
}
1065

    
1066
static uint32_t compute_all_tadd(void)
1067
{
1068
    uint32_t ret;
1069

    
1070
    ret = get_NZ_icc(CC_DST);
1071
    ret |= get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
1072
    ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
1073
    ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
1074
    return ret;
1075
}
1076

    
1077
static uint32_t compute_C_tadd(void)
1078
{
1079
    return get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
1080
}
1081

    
1082
static uint32_t compute_all_taddtv(void)
1083
{
1084
    uint32_t ret;
1085

    
1086
    ret = get_NZ_icc(CC_DST);
1087
    ret |= get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
1088
    return ret;
1089
}
1090

    
1091
static uint32_t compute_C_taddtv(void)
1092
{
1093
    return get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
1094
}
1095

    
1096
/* carry = (~src1[31] & src2[31]) | ( dst[31]  & (~src1[31] | src2[31])) */
1097
static inline uint32_t get_C_sub_icc(target_ulong dst, target_ulong src1,
1098
                                     target_ulong src2)
1099
{
1100
    uint32_t ret = 0;
1101

    
1102
    if (((~(src1 & (1ULL << 31))) & (src2 & (1ULL << 31)))
1103
        | ((dst & (1ULL << 31)) & (( ~(src1 & (1ULL << 31)))
1104
                                   | (src2 & (1ULL << 31)))))
1105
        ret |= PSR_CARRY;
1106
    return ret;
1107
}
1108

    
1109
static inline uint32_t get_V_sub_icc(target_ulong dst, target_ulong src1,
1110
                                     target_ulong src2)
1111
{
1112
    uint32_t ret = 0;
1113

    
1114
    if (((src1 ^ src2) & (src1 ^ dst)) & (1ULL << 31))
1115
        ret |= PSR_OVF;
1116
    return ret;
1117
}
1118

    
1119

    
1120
#ifdef TARGET_SPARC64
1121
static inline uint32_t get_C_sub_xcc(target_ulong src1, target_ulong src2)
1122
{
1123
    uint32_t ret = 0;
1124

    
1125
    if (src1 < src2)
1126
        ret |= PSR_CARRY;
1127
    return ret;
1128
}
1129

    
1130
static inline uint32_t get_V_sub_xcc(target_ulong dst, target_ulong src1,
1131
                                     target_ulong src2)
1132
{
1133
    uint32_t ret = 0;
1134

    
1135
    if (((src1 ^ src2) & (src1 ^ dst)) & (1ULL << 63))
1136
        ret |= PSR_OVF;
1137
    return ret;
1138
}
1139

    
1140
static uint32_t compute_all_sub_xcc(void)
1141
{
1142
    uint32_t ret;
1143

    
1144
    ret = get_NZ_xcc(CC_DST);
1145
    ret |= get_C_sub_xcc(CC_SRC, CC_SRC2);
1146
    ret |= get_V_sub_xcc(CC_DST, CC_SRC, CC_SRC2);
1147
    return ret;
1148
}
1149

    
1150
static uint32_t compute_C_sub_xcc(void)
1151
{
1152
    return get_C_sub_xcc(CC_SRC, CC_SRC2);
1153
}
1154
#endif
1155

    
1156
static uint32_t compute_all_sub(void)
1157
{
1158
    uint32_t ret;
1159

    
1160
    ret = get_NZ_icc(CC_DST);
1161
    ret |= get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1162
    ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1163
    return ret;
1164
}
1165

    
1166
static uint32_t compute_C_sub(void)
1167
{
1168
    return get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1169
}
1170

    
1171
#ifdef TARGET_SPARC64
1172
static uint32_t compute_all_subx_xcc(void)
1173
{
1174
    uint32_t ret;
1175

    
1176
    ret = get_NZ_xcc(CC_DST);
1177
    ret |= get_C_sub_xcc(CC_DST - CC_SRC2, CC_SRC);
1178
    ret |= get_C_sub_xcc(CC_DST, CC_SRC2);
1179
    ret |= get_V_sub_xcc(CC_DST, CC_SRC, CC_SRC2);
1180
    return ret;
1181
}
1182

    
1183
static uint32_t compute_C_subx_xcc(void)
1184
{
1185
    uint32_t ret;
1186

    
1187
    ret = get_C_sub_xcc(CC_DST - CC_SRC2, CC_SRC);
1188
    ret |= get_C_sub_xcc(CC_DST, CC_SRC2);
1189
    return ret;
1190
}
1191
#endif
1192

    
1193
static uint32_t compute_all_tsub(void)
1194
{
1195
    uint32_t ret;
1196

    
1197
    ret = get_NZ_icc(CC_DST);
1198
    ret |= get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1199
    ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1200
    ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
1201
    return ret;
1202
}
1203

    
1204
static uint32_t compute_C_tsub(void)
1205
{
1206
    return get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1207
}
1208

    
1209
static uint32_t compute_all_tsubtv(void)
1210
{
1211
    uint32_t ret;
1212

    
1213
    ret = get_NZ_icc(CC_DST);
1214
    ret |= get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1215
    return ret;
1216
}
1217

    
1218
static uint32_t compute_C_tsubtv(void)
1219
{
1220
    return get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1221
}
1222

    
1223
static uint32_t compute_all_logic(void)
1224
{
1225
    return get_NZ_icc(CC_DST);
1226
}
1227

    
1228
static uint32_t compute_C_logic(void)
1229
{
1230
    return 0;
1231
}
1232

    
1233
#ifdef TARGET_SPARC64
1234
static uint32_t compute_all_logic_xcc(void)
1235
{
1236
    return get_NZ_xcc(CC_DST);
1237
}
1238
#endif
1239

    
1240
typedef struct CCTable {
1241
    uint32_t (*compute_all)(void); /* return all the flags */
1242
    uint32_t (*compute_c)(void);  /* return the C flag */
1243
} CCTable;
1244

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

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

    
1277
void helper_compute_psr(void)
1278
{
1279
    uint32_t new_psr;
1280

    
1281
    new_psr = icc_table[CC_OP].compute_all();
1282
    env->psr = new_psr;
1283
#ifdef TARGET_SPARC64
1284
    new_psr = xcc_table[CC_OP].compute_all();
1285
    env->xcc = new_psr;
1286
#endif
1287
    CC_OP = CC_OP_FLAGS;
1288
}
1289

    
1290
target_ulong helper_compute_C_icc(void)
1291
{
1292
    uint32_t ret;
1293

    
1294
    ret = icc_table[CC_OP].compute_c() >> PSR_CARRY_SHIFT;
1295
    return ret;
1296
}
1297

    
1298
static inline void memcpy32(target_ulong *dst, const target_ulong *src)
1299
{
1300
    dst[0] = src[0];
1301
    dst[1] = src[1];
1302
    dst[2] = src[2];
1303
    dst[3] = src[3];
1304
    dst[4] = src[4];
1305
    dst[5] = src[5];
1306
    dst[6] = src[6];
1307
    dst[7] = src[7];
1308
}
1309

    
1310
static void set_cwp(int new_cwp)
1311
{
1312
    /* put the modified wrap registers at their proper location */
1313
    if (env->cwp == env->nwindows - 1) {
1314
        memcpy32(env->regbase, env->regbase + env->nwindows * 16);
1315
    }
1316
    env->cwp = new_cwp;
1317

    
1318
    /* put the wrap registers at their temporary location */
1319
    if (new_cwp == env->nwindows - 1) {
1320
        memcpy32(env->regbase + env->nwindows * 16, env->regbase);
1321
    }
1322
    env->regwptr = env->regbase + (new_cwp * 16);
1323
}
1324

    
1325
void cpu_set_cwp(CPUState *env1, int new_cwp)
1326
{
1327
    CPUState *saved_env;
1328

    
1329
    saved_env = env;
1330
    env = env1;
1331
    set_cwp(new_cwp);
1332
    env = saved_env;
1333
}
1334

    
1335
static target_ulong get_psr(void)
1336
{
1337
    helper_compute_psr();
1338

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

    
1355
target_ulong cpu_get_psr(CPUState *env1)
1356
{
1357
    CPUState *saved_env;
1358
    target_ulong ret;
1359

    
1360
    saved_env = env;
1361
    env = env1;
1362
    ret = get_psr();
1363
    env = saved_env;
1364
    return ret;
1365
}
1366

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

    
1384
void cpu_put_psr(CPUState *env1, target_ulong val)
1385
{
1386
    CPUState *saved_env;
1387

    
1388
    saved_env = env;
1389
    env = env1;
1390
    put_psr(val);
1391
    env = saved_env;
1392
}
1393

    
1394
static int cwp_inc(int cwp)
1395
{
1396
    if (unlikely(cwp >= env->nwindows)) {
1397
        cwp -= env->nwindows;
1398
    }
1399
    return cwp;
1400
}
1401

    
1402
int cpu_cwp_inc(CPUState *env1, int cwp)
1403
{
1404
    CPUState *saved_env;
1405
    target_ulong ret;
1406

    
1407
    saved_env = env;
1408
    env = env1;
1409
    ret = cwp_inc(cwp);
1410
    env = saved_env;
1411
    return ret;
1412
}
1413

    
1414
static int cwp_dec(int cwp)
1415
{
1416
    if (unlikely(cwp < 0)) {
1417
        cwp += env->nwindows;
1418
    }
1419
    return cwp;
1420
}
1421

    
1422
int cpu_cwp_dec(CPUState *env1, int cwp)
1423
{
1424
    CPUState *saved_env;
1425
    target_ulong ret;
1426

    
1427
    saved_env = env;
1428
    env = env1;
1429
    ret = cwp_dec(cwp);
1430
    env = saved_env;
1431
    return ret;
1432
}
1433

    
1434
#ifdef TARGET_SPARC64
1435
GEN_FCMPS(fcmps_fcc1, float32, 22, 0);
1436
GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
1437
GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0);
1438

    
1439
GEN_FCMPS(fcmps_fcc2, float32, 24, 0);
1440
GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
1441
GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0);
1442

    
1443
GEN_FCMPS(fcmps_fcc3, float32, 26, 0);
1444
GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
1445
GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0);
1446

    
1447
GEN_FCMPS(fcmpes_fcc1, float32, 22, 1);
1448
GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
1449
GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1);
1450

    
1451
GEN_FCMPS(fcmpes_fcc2, float32, 24, 1);
1452
GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
1453
GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1);
1454

    
1455
GEN_FCMPS(fcmpes_fcc3, float32, 26, 1);
1456
GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
1457
GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
1458
#endif
1459
#undef GEN_FCMPS
1460

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

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

    
1507
#ifndef TARGET_SPARC64
1508
#ifndef CONFIG_USER_ONLY
1509
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1510
{
1511
    uint64_t ret = 0;
1512
#if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
1513
    uint32_t last_addr = addr;
1514
#endif
1515

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

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

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

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

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

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

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

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

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

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

    
2080
#endif /* CONFIG_USER_ONLY */
2081
#else /* TARGET_SPARC64 */
2082

    
2083
#ifdef CONFIG_USER_ONLY
2084
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
2085
{
2086
    uint64_t ret = 0;
2087
#if defined(DEBUG_ASI)
2088
    target_ulong last_addr = addr;
2089
#endif
2090

    
2091
    if (asi < 0x80)
2092
        raise_exception(TT_PRIV_ACT);
2093

    
2094
    helper_check_align(addr, size - 1);
2095
    addr = address_mask(env, addr);
2096

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

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

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

    
2189
void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
2190
{
2191
#ifdef DEBUG_ASI
2192
    dump_asi("write", addr, asi, size, val);
2193
#endif
2194
    if (asi < 0x80)
2195
        raise_exception(TT_PRIV_ACT);
2196

    
2197
    helper_check_align(addr, size - 1);
2198
    addr = address_mask(env, addr);
2199

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

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

    
2247
    case 0x82: // Primary no-fault, RO
2248
    case 0x83: // Secondary no-fault, RO
2249
    case 0x8a: // Primary no-fault LE, RO
2250
    case 0x8b: // Secondary no-fault LE, RO
2251
    default:
2252
        do_unassigned_access(addr, 1, 0, 1, size);
2253
        return;
2254
    }
2255
}
2256

    
2257
#else /* CONFIG_USER_ONLY */
2258

    
2259
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
2260
{
2261
    uint64_t ret = 0;
2262
#if defined(DEBUG_ASI)
2263
    target_ulong last_addr = addr;
2264
#endif
2265

    
2266
    asi &= 0xff;
2267

    
2268
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
2269
        || ((env->def->features & CPU_FEATURE_HYPV)
2270
            && asi >= 0x30 && asi < 0x80
2271
            && !(env->hpstate & HS_PRIV)))
2272
        raise_exception(TT_PRIV_ACT);
2273

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

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

    
2451
            if (reg == 0) {
2452
                // I-TSB Tag Target register
2453
                ret = ultrasparc_tag_target(env->immu.tag_access);
2454
            } else {
2455
                ret = env->immuregs[reg];
2456
            }
2457

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

    
2480
            ret = env->itlb[reg].tte;
2481
            break;
2482
        }
2483
    case 0x56: // I-MMU tag read
2484
        {
2485
            int reg = (addr >> 3) & 0x3f;
2486

    
2487
            ret = env->itlb[reg].tag;
2488
            break;
2489
        }
2490
    case 0x58: // D-MMU regs
2491
        {
2492
            int reg = (addr >> 3) & 0xf;
2493

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

    
2522
            ret = env->dtlb[reg].tte;
2523
            break;
2524
        }
2525
    case 0x5e: // D-MMU tag read
2526
        {
2527
            int reg = (addr >> 3) & 0x3f;
2528

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

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

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

    
2612
void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
2613
{
2614
#ifdef DEBUG_ASI
2615
    dump_asi("write", addr, asi, size, val);
2616
#endif
2617

    
2618
    asi &= 0xff;
2619

    
2620
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
2621
        || ((env->def->features & CPU_FEATURE_HYPV)
2622
            && asi >= 0x30 && asi < 0x80
2623
            && !(env->hpstate & HS_PRIV)))
2624
        raise_exception(TT_PRIV_ACT);
2625

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

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

    
2803
    case 0x4a: // UPA config
2804
        // XXX
2805
        return;
2806
    case 0x45: // LSU
2807
        {
2808
            uint64_t oldreg;
2809

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

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

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

    
2874
            unsigned int i = (addr >> 3) & 0x3f;
2875

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

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

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

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

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

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

    
2988
void helper_ldda_asi(target_ulong addr, int asi, int rd)
2989
{
2990
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
2991
        || ((env->def->features & CPU_FEATURE_HYPV)
2992
            && asi >= 0x30 && asi < 0x80
2993
            && !(env->hpstate & HS_PRIV)))
2994
        raise_exception(TT_PRIV_ACT);
2995

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

    
3035
void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
3036
{
3037
    unsigned int i;
3038
    target_ulong val;
3039

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

    
3057
        return;
3058
    default:
3059
        break;
3060
    }
3061

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

    
3077
void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
3078
{
3079
    unsigned int i;
3080
    target_ulong val = 0;
3081

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

    
3101
        return;
3102
    default:
3103
        break;
3104
    }
3105

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

    
3121
target_ulong helper_cas_asi(target_ulong addr, target_ulong val1,
3122
                            target_ulong val2, uint32_t asi)
3123
{
3124
    target_ulong ret;
3125

    
3126
    val2 &= 0xffffffffUL;
3127
    ret = helper_ld_asi(addr, asi, 4, 0);
3128
    ret &= 0xffffffffUL;
3129
    if (val2 == ret)
3130
        helper_st_asi(addr, val1 & 0xffffffffUL, asi, 4);
3131
    return ret;
3132
}
3133

    
3134
target_ulong helper_casx_asi(target_ulong addr, target_ulong val1,
3135
                             target_ulong val2, uint32_t asi)
3136
{
3137
    target_ulong ret;
3138

    
3139
    ret = helper_ld_asi(addr, asi, 8, 0);
3140
    if (val2 == ret)
3141
        helper_st_asi(addr, val1, asi, 8);
3142
    return ret;
3143
}
3144
#endif /* TARGET_SPARC64 */
3145

    
3146
#ifndef TARGET_SPARC64
3147
void helper_rett(void)
3148
{
3149
    unsigned int cwp;
3150

    
3151
    if (env->psret == 1)
3152
        raise_exception(TT_ILL_INSN);
3153

    
3154
    env->psret = 1;
3155
    cwp = cwp_inc(env->cwp + 1) ;
3156
    if (env->wim & (1 << cwp)) {
3157
        raise_exception(TT_WIN_UNF);
3158
    }
3159
    set_cwp(cwp);
3160
    env->psrs = env->psrps;
3161
}
3162
#endif
3163

    
3164
target_ulong helper_udiv(target_ulong a, target_ulong b)
3165
{
3166
    uint64_t x0;
3167
    uint32_t x1;
3168

    
3169
    x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
3170
    x1 = b;
3171

    
3172
    if (x1 == 0) {
3173
        raise_exception(TT_DIV_ZERO);
3174
    }
3175

    
3176
    x0 = x0 / x1;
3177
    if (x0 > 0xffffffff) {
3178
        env->cc_src2 = 1;
3179
        return 0xffffffff;
3180
    } else {
3181
        env->cc_src2 = 0;
3182
        return x0;
3183
    }
3184
}
3185

    
3186
target_ulong helper_sdiv(target_ulong a, target_ulong b)
3187
{
3188
    int64_t x0;
3189
    int32_t x1;
3190

    
3191
    x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
3192
    x1 = b;
3193

    
3194
    if (x1 == 0) {
3195
        raise_exception(TT_DIV_ZERO);
3196
    }
3197

    
3198
    x0 = x0 / x1;
3199
    if ((int32_t) x0 != x0) {
3200
        env->cc_src2 = 1;
3201
        return x0 < 0? 0x80000000: 0x7fffffff;
3202
    } else {
3203
        env->cc_src2 = 0;
3204
        return x0;
3205
    }
3206
}
3207

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

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

    
3256
void helper_ldqf(target_ulong addr, int mem_idx)
3257
{
3258
    // XXX add 128 bit load
3259
    CPU_QuadU u;
3260

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

    
3291
void helper_stqf(target_ulong addr, int mem_idx)
3292
{
3293
    // XXX add 128 bit store
3294
    CPU_QuadU u;
3295

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

    
3326
static inline void set_fsr(void)
3327
{
3328
    int rnd_mode;
3329

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

    
3348
void helper_ldfsr(uint32_t new_fsr)
3349
{
3350
    env->fsr = (new_fsr & FSR_LDFSR_MASK) | (env->fsr & FSR_LDFSR_OLDMASK);
3351
    set_fsr();
3352
}
3353

    
3354
#ifdef TARGET_SPARC64
3355
void helper_ldxfsr(uint64_t new_fsr)
3356
{
3357
    env->fsr = (new_fsr & FSR_LDXFSR_MASK) | (env->fsr & FSR_LDXFSR_OLDMASK);
3358
    set_fsr();
3359
}
3360
#endif
3361

    
3362
void helper_debug(void)
3363
{
3364
    env->exception_index = EXCP_DEBUG;
3365
    cpu_loop_exit();
3366
}
3367

    
3368
#ifndef TARGET_SPARC64
3369
/* XXX: use another pointer for %iN registers to avoid slow wrapping
3370
   handling ? */
3371
void helper_save(void)
3372
{
3373
    uint32_t cwp;
3374

    
3375
    cwp = cwp_dec(env->cwp - 1);
3376
    if (env->wim & (1 << cwp)) {
3377
        raise_exception(TT_WIN_OVF);
3378
    }
3379
    set_cwp(cwp);
3380
}
3381

    
3382
void helper_restore(void)
3383
{
3384
    uint32_t cwp;
3385

    
3386
    cwp = cwp_inc(env->cwp + 1);
3387
    if (env->wim & (1 << cwp)) {
3388
        raise_exception(TT_WIN_UNF);
3389
    }
3390
    set_cwp(cwp);
3391
}
3392

    
3393
void helper_wrpsr(target_ulong new_psr)
3394
{
3395
    if ((new_psr & PSR_CWP) >= env->nwindows) {
3396
        raise_exception(TT_ILL_INSN);
3397
    } else {
3398
        cpu_put_psr(env, new_psr);
3399
    }
3400
}
3401

    
3402
target_ulong helper_rdpsr(void)
3403
{
3404
    return get_psr();
3405
}
3406

    
3407
#else
3408
/* XXX: use another pointer for %iN registers to avoid slow wrapping
3409
   handling ? */
3410
void helper_save(void)
3411
{
3412
    uint32_t cwp;
3413

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

    
3431
void helper_restore(void)
3432
{
3433
    uint32_t cwp;
3434

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

    
3447
void helper_flushw(void)
3448
{
3449
    if (env->cansave != env->nwindows - 2) {
3450
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
3451
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
3452
                                    ((env->wstate & 0x7) << 2)));
3453
    }
3454
}
3455

    
3456
void helper_saved(void)
3457
{
3458
    env->cansave++;
3459
    if (env->otherwin == 0)
3460
        env->canrestore--;
3461
    else
3462
        env->otherwin--;
3463
}
3464

    
3465
void helper_restored(void)
3466
{
3467
    env->canrestore++;
3468
    if (env->cleanwin < env->nwindows - 1)
3469
        env->cleanwin++;
3470
    if (env->otherwin == 0)
3471
        env->cansave--;
3472
    else
3473
        env->otherwin--;
3474
}
3475

    
3476
static target_ulong get_ccr(void)
3477
{
3478
    target_ulong psr;
3479

    
3480
    psr = get_psr();
3481

    
3482
    return ((env->xcc >> 20) << 4) | ((psr & PSR_ICC) >> 20);
3483
}
3484

    
3485
target_ulong cpu_get_ccr(CPUState *env1)
3486
{
3487
    CPUState *saved_env;
3488
    target_ulong ret;
3489

    
3490
    saved_env = env;
3491
    env = env1;
3492
    ret = get_ccr();
3493
    env = saved_env;
3494
    return ret;
3495
}
3496

    
3497
static void put_ccr(target_ulong val)
3498
{
3499
    target_ulong tmp = val;
3500

    
3501
    env->xcc = (tmp >> 4) << 20;
3502
    env->psr = (tmp & 0xf) << 20;
3503
    CC_OP = CC_OP_FLAGS;
3504
}
3505

    
3506
void cpu_put_ccr(CPUState *env1, target_ulong val)
3507
{
3508
    CPUState *saved_env;
3509

    
3510
    saved_env = env;
3511
    env = env1;
3512
    put_ccr(val);
3513
    env = saved_env;
3514
}
3515

    
3516
static target_ulong get_cwp64(void)
3517
{
3518
    return env->nwindows - 1 - env->cwp;
3519
}
3520

    
3521
target_ulong cpu_get_cwp64(CPUState *env1)
3522
{
3523
    CPUState *saved_env;
3524
    target_ulong ret;
3525

    
3526
    saved_env = env;
3527
    env = env1;
3528
    ret = get_cwp64();
3529
    env = saved_env;
3530
    return ret;
3531
}
3532

    
3533
static void put_cwp64(int cwp)
3534
{
3535
    if (unlikely(cwp >= env->nwindows || cwp < 0)) {
3536
        cwp %= env->nwindows;
3537
    }
3538
    set_cwp(env->nwindows - 1 - cwp);
3539
}
3540

    
3541
void cpu_put_cwp64(CPUState *env1, int cwp)
3542
{
3543
    CPUState *saved_env;
3544

    
3545
    saved_env = env;
3546
    env = env1;
3547
    put_cwp64(cwp);
3548
    env = saved_env;
3549
}
3550

    
3551
target_ulong helper_rdccr(void)
3552
{
3553
    return get_ccr();
3554
}
3555

    
3556
void helper_wrccr(target_ulong new_ccr)
3557
{
3558
    put_ccr(new_ccr);
3559
}
3560

    
3561
// CWP handling is reversed in V9, but we still use the V8 register
3562
// order.
3563
target_ulong helper_rdcwp(void)
3564
{
3565
    return get_cwp64();
3566
}
3567

    
3568
void helper_wrcwp(target_ulong new_cwp)
3569
{
3570
    put_cwp64(new_cwp);
3571
}
3572

    
3573
// This function uses non-native bit order
3574
#define GET_FIELD(X, FROM, TO)                                  \
3575
    ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
3576

    
3577
// This function uses the order in the manuals, i.e. bit 0 is 2^0
3578
#define GET_FIELD_SP(X, FROM, TO)               \
3579
    GET_FIELD(X, 63 - (TO), 63 - (FROM))
3580

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

    
3594
target_ulong helper_alignaddr(target_ulong addr, target_ulong offset)
3595
{
3596
    uint64_t tmp;
3597

    
3598
    tmp = addr + offset;
3599
    env->gsr &= ~7ULL;
3600
    env->gsr |= tmp & 7ULL;
3601
    return tmp & ~7ULL;
3602
}
3603

    
3604
target_ulong helper_popc(target_ulong val)
3605
{
3606
    return ctpop64(val);
3607
}
3608

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

    
3630
static inline void change_pstate(uint32_t new_pstate)
3631
{
3632
    uint32_t pstate_regs, new_pstate_regs;
3633
    uint64_t *src, *dst;
3634

    
3635
    if (env->def->features & CPU_FEATURE_GL) {
3636
        // PS_AG is not implemented in this case
3637
        new_pstate &= ~PS_AG;
3638
    }
3639

    
3640
    pstate_regs = env->pstate & 0xc01;
3641
    new_pstate_regs = new_pstate & 0xc01;
3642

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

    
3659
void helper_wrpstate(target_ulong new_state)
3660
{
3661
    change_pstate(new_state & 0xf3f);
3662

    
3663
#if !defined(CONFIG_USER_ONLY)
3664
    if (cpu_interrupts_enabled(env)) {
3665
        cpu_check_irqs(env);
3666
    }
3667
#endif
3668
}
3669

    
3670
void helper_wrpil(target_ulong new_pil)
3671
{
3672
#if !defined(CONFIG_USER_ONLY)
3673
    DPRINTF_PSTATE("helper_wrpil old=%x new=%x\n",
3674
                   env->psrpil, (uint32_t)new_pil);
3675

    
3676
    env->psrpil = new_pil;
3677

    
3678
    if (cpu_interrupts_enabled(env)) {
3679
        cpu_check_irqs(env);
3680
    }
3681
#endif
3682
}
3683

    
3684
void helper_done(void)
3685
{
3686
    trap_state* tsptr = cpu_tsptr(env);
3687

    
3688
    env->pc = tsptr->tnpc;
3689
    env->npc = tsptr->tnpc + 4;
3690
    put_ccr(tsptr->tstate >> 32);
3691
    env->asi = (tsptr->tstate >> 24) & 0xff;
3692
    change_pstate((tsptr->tstate >> 8) & 0xf3f);
3693
    put_cwp64(tsptr->tstate & 0xff);
3694
    env->tl--;
3695

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

    
3698
#if !defined(CONFIG_USER_ONLY)
3699
    if (cpu_interrupts_enabled(env)) {
3700
        cpu_check_irqs(env);
3701
    }
3702
#endif
3703
}
3704

    
3705
void helper_retry(void)
3706
{
3707
    trap_state* tsptr = cpu_tsptr(env);
3708

    
3709
    env->pc = tsptr->tpc;
3710
    env->npc = tsptr->tnpc;
3711
    put_ccr(tsptr->tstate >> 32);
3712
    env->asi = (tsptr->tstate >> 24) & 0xff;
3713
    change_pstate((tsptr->tstate >> 8) & 0xf3f);
3714
    put_cwp64(tsptr->tstate & 0xff);
3715
    env->tl--;
3716

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

    
3719
#if !defined(CONFIG_USER_ONLY)
3720
    if (cpu_interrupts_enabled(env)) {
3721
        cpu_check_irqs(env);
3722
    }
3723
#endif
3724
}
3725

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

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

    
3744
void helper_clear_softint(uint64_t value)
3745
{
3746
    do_modify_softint("helper_clear_softint", env->softint & (uint32_t)~value);
3747
}
3748

    
3749
void helper_write_softint(uint64_t value)
3750
{
3751
    do_modify_softint("helper_write_softint", (uint32_t)value);
3752
}
3753
#endif
3754

    
3755
void helper_flush(target_ulong addr)
3756
{
3757
    addr &= ~7;
3758
    tb_invalidate_page_range(addr, addr + 8);
3759
}
3760

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

    
3798
trap_state* cpu_tsptr(CPUState* env)
3799
{
3800
    return &env->ts[env->tl & MAXTL_MASK];
3801
}
3802

    
3803
void do_interrupt(CPUState *env)
3804
{
3805
    int intno = env->exception_index;
3806
    trap_state* tsptr;
3807

    
3808
#ifdef DEBUG_PCALL
3809
    if (qemu_loglevel_mask(CPU_LOG_INT)) {
3810
        static int count;
3811
        const char *name;
3812

    
3813
        if (intno < 0 || intno >= 0x180)
3814
            name = "Unknown";
3815
        else if (intno >= 0x100)
3816
            name = "Trap Instruction";
3817
        else if (intno >= 0xc0)
3818
            name = "Window Fill";
3819
        else if (intno >= 0x80)
3820
            name = "Window Spill";
3821
        else {
3822
            name = excp_names[intno];
3823
            if (!name)
3824
                name = "Unknown";
3825
        }
3826

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

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

    
3865
    tsptr->tstate = (get_ccr() << 32) |
3866
        ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
3867
        get_cwp64();
3868
    tsptr->tpc = env->pc;
3869
    tsptr->tnpc = env->npc;
3870
    tsptr->tt = intno;
3871

    
3872
    switch (intno) {
3873
    case TT_IVEC:
3874
        change_pstate(PS_PEF | PS_PRIV | PS_IG);
3875
        break;
3876
    case TT_TFAULT:
3877
    case TT_DFAULT:
3878
    case TT_TMISS ... TT_TMISS + 3:
3879
    case TT_DMISS ... TT_DMISS + 3:
3880
    case TT_DPROT ... TT_DPROT + 3:
3881
        change_pstate(PS_PEF | PS_PRIV | PS_MG);
3882
        break;
3883
    default:
3884
        change_pstate(PS_PEF | PS_PRIV | PS_AG);
3885
        break;
3886
    }
3887

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

    
3937
void do_interrupt(CPUState *env)
3938
{
3939
    int cwp, intno = env->exception_index;
3940

    
3941
#ifdef DEBUG_PCALL
3942
    if (qemu_loglevel_mask(CPU_LOG_INT)) {
3943
        static int count;
3944
        const char *name;
3945

    
3946
        if (intno < 0 || intno >= 0x100)
3947
            name = "Unknown";
3948
        else if (intno >= 0x80)
3949
            name = "Trap Instruction";
3950
        else {
3951
            name = excp_names[intno];
3952
            if (!name)
3953
                name = "Unknown";
3954
        }
3955

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

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

    
3998
#if !defined(CONFIG_USER_ONLY)
3999

    
4000
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
4001
                                void *retaddr);
4002

    
4003
#define MMUSUFFIX _mmu
4004
#define ALIGNED_ONLY
4005

    
4006
#define SHIFT 0
4007
#include "softmmu_template.h"
4008

    
4009
#define SHIFT 1
4010
#include "softmmu_template.h"
4011

    
4012
#define SHIFT 2
4013
#include "softmmu_template.h"
4014

    
4015
#define SHIFT 3
4016
#include "softmmu_template.h"
4017

    
4018
/* XXX: make it generic ? */
4019
static void cpu_restore_state2(void *retaddr)
4020
{
4021
    TranslationBlock *tb;
4022
    unsigned long pc;
4023

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

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

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

    
4056
    /* XXX: hack to restore env in all cases, even if not called from
4057
       generated code */
4058
    saved_env = env;
4059
    env = cpu_single_env;
4060

    
4061
    ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
4062
    if (ret) {
4063
        cpu_restore_state2(retaddr);
4064
        cpu_loop_exit();
4065
    }
4066
    env = saved_env;
4067
}
4068

    
4069
#endif /* !CONFIG_USER_ONLY */
4070

    
4071
#ifndef TARGET_SPARC64
4072
#if !defined(CONFIG_USER_ONLY)
4073
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
4074
                          int is_asi, int size)
4075
{
4076
    CPUState *saved_env;
4077
    int fault_type;
4078

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

    
4118
    if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
4119
        if (is_exec)
4120
            raise_exception(TT_CODE_ACCESS);
4121
        else
4122
            raise_exception(TT_DATA_ACCESS);
4123
    }
4124

    
4125
    /* flush neverland mappings created during no-fault mode,
4126
       so the sequential MMU faults report proper fault types */
4127
    if (env->mmuregs[0] & MMU_NF) {
4128
        tlb_flush(env, 1);
4129
    }
4130

    
4131
    env = saved_env;
4132
}
4133
#endif
4134
#else
4135
#if defined(CONFIG_USER_ONLY)
4136
static void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
4137
                          int is_asi, int size)
4138
#else
4139
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
4140
                          int is_asi, int size)
4141
#endif
4142
{
4143
    CPUState *saved_env;
4144

    
4145
    /* XXX: hack to restore env in all cases, even if not called from
4146
       generated code */
4147
    saved_env = env;
4148
    env = cpu_single_env;
4149

    
4150
#ifdef DEBUG_UNASSIGNED
4151
    printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx
4152
           "\n", addr, env->pc);
4153
#endif
4154

    
4155
    if (is_exec)
4156
        raise_exception(TT_CODE_ACCESS);
4157
    else
4158
        raise_exception(TT_DATA_ACCESS);
4159

    
4160
    env = saved_env;
4161
}
4162
#endif
4163

    
4164

    
4165
#ifdef TARGET_SPARC64
4166
void helper_tick_set_count(void *opaque, uint64_t count)
4167
{
4168
#if !defined(CONFIG_USER_ONLY)
4169
    cpu_tick_set_count(opaque, count);
4170
#endif
4171
}
4172

    
4173
uint64_t helper_tick_get_count(void *opaque)
4174
{
4175
#if !defined(CONFIG_USER_ONLY)
4176
    return cpu_tick_get_count(opaque);
4177
#else
4178
    return 0;
4179
#endif
4180
}
4181

    
4182
void helper_tick_set_limit(void *opaque, uint64_t limit)
4183
{
4184
#if !defined(CONFIG_USER_ONLY)
4185
    cpu_tick_set_limit(opaque, limit);
4186
#endif
4187
}
4188
#endif