Statistics
| Branch: | Revision:

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

History | View | Annotate | Download (103.9 kB)

1
#include "exec.h"
2
#include "host-utils.h"
3
#include "helper.h"
4
#if !defined(CONFIG_USER_ONLY)
5
#include "softmmu_exec.h"
6
#endif /* !defined(CONFIG_USER_ONLY) */
7

    
8
//#define DEBUG_MMU
9
//#define DEBUG_MXCC
10
//#define DEBUG_UNALIGNED
11
//#define DEBUG_UNASSIGNED
12
//#define DEBUG_ASI
13
//#define DEBUG_PCALL
14
//#define DEBUG_PSTATE
15

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

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

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

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

    
42
#ifdef TARGET_SPARC64
43
#ifndef TARGET_ABI32
44
#define AM_CHECK(env1) ((env1)->pstate & PS_AM)
45
#else
46
#define AM_CHECK(env1) (1)
47
#endif
48
#endif
49

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

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

    
63
    // now reorder bits
64
    uint64_t tsb_base_mask = ~0x1fffULL;
65
    uint64_t va = tag_access_va;
66

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

    
74
    if (tsb_size) {
75
        tsb_base_mask <<= tsb_size;
76
    }
77

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

    
88
    return ((tsb_base & tsb_base_mask) | (va & ~tsb_base_mask)) & ~0xfULL;
89
}
90

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

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

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

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

    
111
        va = tlb->tag & mask;
112

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

    
118
    tlb->tag = tlb_tag;
119
    tlb->tte = tlb_tte;
120
}
121

    
122
static void demap_tlb(SparcTLBEntry *tlb, target_ulong demap_addr,
123
                      const char* strmmu, CPUState *env1)
124
{
125
    unsigned int i;
126
    target_ulong mask;
127

    
128
    for (i = 0; i < 64; i++) {
129
        if (TTE_IS_VALID(tlb[i].tte)) {
130

    
131
            mask = 0xffffffffffffe000ULL;
132
            mask <<= 3 * ((tlb[i].tte >> 61) & 3);
133

    
134
            if ((demap_addr & mask) == (tlb[i].tag & mask)) {
135
                replace_tlb_entry(&tlb[i], 0, 0, env1);
136
#ifdef DEBUG_MMU
137
                DPRINTF_MMU("%s demap invalidated entry [%02u]\n", strmmu, i);
138
                dump_mmu(env1);
139
#endif
140
            }
141
            //return;
142
        }
143
    }
144

    
145
}
146

    
147
static void replace_tlb_1bit_lru(SparcTLBEntry *tlb,
148
                                 uint64_t tlb_tag, uint64_t tlb_tte,
149
                                 const char* strmmu, CPUState *env1)
150
{
151
    unsigned int i, replace_used;
152

    
153
    // Try replacing invalid entry
154
    for (i = 0; i < 64; i++) {
155
        if (!TTE_IS_VALID(tlb[i].tte)) {
156
            replace_tlb_entry(&tlb[i], tlb_tag, tlb_tte, env1);
157
#ifdef DEBUG_MMU
158
            DPRINTF_MMU("%s lru replaced invalid entry [%i]\n", strmmu, i);
159
            dump_mmu(env1);
160
#endif
161
            return;
162
        }
163
    }
164

    
165
    // All entries are valid, try replacing unlocked entry
166

    
167
    for (replace_used = 0; replace_used < 2; ++replace_used) {
168

    
169
        // Used entries are not replaced on first pass
170

    
171
        for (i = 0; i < 64; i++) {
172
            if (!TTE_IS_LOCKED(tlb[i].tte) && !TTE_IS_USED(tlb[i].tte)) {
173

    
174
                replace_tlb_entry(&tlb[i], tlb_tag, tlb_tte, env1);
175
#ifdef DEBUG_MMU
176
                DPRINTF_MMU("%s lru replaced unlocked %s entry [%i]\n",
177
                            strmmu, (replace_used?"used":"unused"), i);
178
                dump_mmu(env1);
179
#endif
180
                return;
181
            }
182
        }
183

    
184
        // Now reset used bit and search for unused entries again
185

    
186
        for (i = 0; i < 64; i++) {
187
            TTE_SET_UNUSED(tlb[i].tte);
188
        }
189
    }
190

    
191
#ifdef DEBUG_MMU
192
    DPRINTF_MMU("%s lru replacement failed: no entries available\n", strmmu);
193
#endif
194
    // error state?
195
}
196

    
197
#endif
198

    
199
static inline void address_mask(CPUState *env1, target_ulong *addr)
200
{
201
#ifdef TARGET_SPARC64
202
    if (AM_CHECK(env1))
203
        *addr &= 0xffffffffULL;
204
#endif
205
}
206

    
207
static void raise_exception(int tt)
208
{
209
    env->exception_index = tt;
210
    cpu_loop_exit();
211
}
212

    
213
void HELPER(raise_exception)(int tt)
214
{
215
    raise_exception(tt);
216
}
217

    
218
static inline void set_cwp(int new_cwp)
219
{
220
    cpu_set_cwp(env, new_cwp);
221
}
222

    
223
void helper_check_align(target_ulong addr, uint32_t align)
224
{
225
    if (addr & align) {
226
#ifdef DEBUG_UNALIGNED
227
    printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
228
           "\n", addr, env->pc);
229
#endif
230
        raise_exception(TT_UNALIGNED);
231
    }
232
}
233

    
234
#define F_HELPER(name, p) void helper_f##name##p(void)
235

    
236
#define F_BINOP(name)                                           \
237
    float32 helper_f ## name ## s (float32 src1, float32 src2)  \
238
    {                                                           \
239
        return float32_ ## name (src1, src2, &env->fp_status);  \
240
    }                                                           \
241
    F_HELPER(name, d)                                           \
242
    {                                                           \
243
        DT0 = float64_ ## name (DT0, DT1, &env->fp_status);     \
244
    }                                                           \
245
    F_HELPER(name, q)                                           \
246
    {                                                           \
247
        QT0 = float128_ ## name (QT0, QT1, &env->fp_status);    \
248
    }
249

    
250
F_BINOP(add);
251
F_BINOP(sub);
252
F_BINOP(mul);
253
F_BINOP(div);
254
#undef F_BINOP
255

    
256
void helper_fsmuld(float32 src1, float32 src2)
257
{
258
    DT0 = float64_mul(float32_to_float64(src1, &env->fp_status),
259
                      float32_to_float64(src2, &env->fp_status),
260
                      &env->fp_status);
261
}
262

    
263
void helper_fdmulq(void)
264
{
265
    QT0 = float128_mul(float64_to_float128(DT0, &env->fp_status),
266
                       float64_to_float128(DT1, &env->fp_status),
267
                       &env->fp_status);
268
}
269

    
270
float32 helper_fnegs(float32 src)
271
{
272
    return float32_chs(src);
273
}
274

    
275
#ifdef TARGET_SPARC64
276
F_HELPER(neg, d)
277
{
278
    DT0 = float64_chs(DT1);
279
}
280

    
281
F_HELPER(neg, q)
282
{
283
    QT0 = float128_chs(QT1);
284
}
285
#endif
286

    
287
/* Integer to float conversion.  */
288
float32 helper_fitos(int32_t src)
289
{
290
    return int32_to_float32(src, &env->fp_status);
291
}
292

    
293
void helper_fitod(int32_t src)
294
{
295
    DT0 = int32_to_float64(src, &env->fp_status);
296
}
297

    
298
void helper_fitoq(int32_t src)
299
{
300
    QT0 = int32_to_float128(src, &env->fp_status);
301
}
302

    
303
#ifdef TARGET_SPARC64
304
float32 helper_fxtos(void)
305
{
306
    return int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
307
}
308

    
309
F_HELPER(xto, d)
310
{
311
    DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
312
}
313

    
314
F_HELPER(xto, q)
315
{
316
    QT0 = int64_to_float128(*((int64_t *)&DT1), &env->fp_status);
317
}
318
#endif
319
#undef F_HELPER
320

    
321
/* floating point conversion */
322
float32 helper_fdtos(void)
323
{
324
    return float64_to_float32(DT1, &env->fp_status);
325
}
326

    
327
void helper_fstod(float32 src)
328
{
329
    DT0 = float32_to_float64(src, &env->fp_status);
330
}
331

    
332
float32 helper_fqtos(void)
333
{
334
    return float128_to_float32(QT1, &env->fp_status);
335
}
336

    
337
void helper_fstoq(float32 src)
338
{
339
    QT0 = float32_to_float128(src, &env->fp_status);
340
}
341

    
342
void helper_fqtod(void)
343
{
344
    DT0 = float128_to_float64(QT1, &env->fp_status);
345
}
346

    
347
void helper_fdtoq(void)
348
{
349
    QT0 = float64_to_float128(DT1, &env->fp_status);
350
}
351

    
352
/* Float to integer conversion.  */
353
int32_t helper_fstoi(float32 src)
354
{
355
    return float32_to_int32_round_to_zero(src, &env->fp_status);
356
}
357

    
358
int32_t helper_fdtoi(void)
359
{
360
    return float64_to_int32_round_to_zero(DT1, &env->fp_status);
361
}
362

    
363
int32_t helper_fqtoi(void)
364
{
365
    return float128_to_int32_round_to_zero(QT1, &env->fp_status);
366
}
367

    
368
#ifdef TARGET_SPARC64
369
void helper_fstox(float32 src)
370
{
371
    *((int64_t *)&DT0) = float32_to_int64_round_to_zero(src, &env->fp_status);
372
}
373

    
374
void helper_fdtox(void)
375
{
376
    *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status);
377
}
378

    
379
void helper_fqtox(void)
380
{
381
    *((int64_t *)&DT0) = float128_to_int64_round_to_zero(QT1, &env->fp_status);
382
}
383

    
384
void helper_faligndata(void)
385
{
386
    uint64_t tmp;
387

    
388
    tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8);
389
    /* on many architectures a shift of 64 does nothing */
390
    if ((env->gsr & 7) != 0) {
391
        tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8);
392
    }
393
    *((uint64_t *)&DT0) = tmp;
394
}
395

    
396
#ifdef HOST_WORDS_BIGENDIAN
397
#define VIS_B64(n) b[7 - (n)]
398
#define VIS_W64(n) w[3 - (n)]
399
#define VIS_SW64(n) sw[3 - (n)]
400
#define VIS_L64(n) l[1 - (n)]
401
#define VIS_B32(n) b[3 - (n)]
402
#define VIS_W32(n) w[1 - (n)]
403
#else
404
#define VIS_B64(n) b[n]
405
#define VIS_W64(n) w[n]
406
#define VIS_SW64(n) sw[n]
407
#define VIS_L64(n) l[n]
408
#define VIS_B32(n) b[n]
409
#define VIS_W32(n) w[n]
410
#endif
411

    
412
typedef union {
413
    uint8_t b[8];
414
    uint16_t w[4];
415
    int16_t sw[4];
416
    uint32_t l[2];
417
    float64 d;
418
} vis64;
419

    
420
typedef union {
421
    uint8_t b[4];
422
    uint16_t w[2];
423
    uint32_t l;
424
    float32 f;
425
} vis32;
426

    
427
void helper_fpmerge(void)
428
{
429
    vis64 s, d;
430

    
431
    s.d = DT0;
432
    d.d = DT1;
433

    
434
    // Reverse calculation order to handle overlap
435
    d.VIS_B64(7) = s.VIS_B64(3);
436
    d.VIS_B64(6) = d.VIS_B64(3);
437
    d.VIS_B64(5) = s.VIS_B64(2);
438
    d.VIS_B64(4) = d.VIS_B64(2);
439
    d.VIS_B64(3) = s.VIS_B64(1);
440
    d.VIS_B64(2) = d.VIS_B64(1);
441
    d.VIS_B64(1) = s.VIS_B64(0);
442
    //d.VIS_B64(0) = d.VIS_B64(0);
443

    
444
    DT0 = d.d;
445
}
446

    
447
void helper_fmul8x16(void)
448
{
449
    vis64 s, d;
450
    uint32_t tmp;
451

    
452
    s.d = DT0;
453
    d.d = DT1;
454

    
455
#define PMUL(r)                                                 \
456
    tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r);       \
457
    if ((tmp & 0xff) > 0x7f)                                    \
458
        tmp += 0x100;                                           \
459
    d.VIS_W64(r) = tmp >> 8;
460

    
461
    PMUL(0);
462
    PMUL(1);
463
    PMUL(2);
464
    PMUL(3);
465
#undef PMUL
466

    
467
    DT0 = d.d;
468
}
469

    
470
void helper_fmul8x16al(void)
471
{
472
    vis64 s, d;
473
    uint32_t tmp;
474

    
475
    s.d = DT0;
476
    d.d = DT1;
477

    
478
#define PMUL(r)                                                 \
479
    tmp = (int32_t)d.VIS_SW64(1) * (int32_t)s.VIS_B64(r);       \
480
    if ((tmp & 0xff) > 0x7f)                                    \
481
        tmp += 0x100;                                           \
482
    d.VIS_W64(r) = tmp >> 8;
483

    
484
    PMUL(0);
485
    PMUL(1);
486
    PMUL(2);
487
    PMUL(3);
488
#undef PMUL
489

    
490
    DT0 = d.d;
491
}
492

    
493
void helper_fmul8x16au(void)
494
{
495
    vis64 s, d;
496
    uint32_t tmp;
497

    
498
    s.d = DT0;
499
    d.d = DT1;
500

    
501
#define PMUL(r)                                                 \
502
    tmp = (int32_t)d.VIS_SW64(0) * (int32_t)s.VIS_B64(r);       \
503
    if ((tmp & 0xff) > 0x7f)                                    \
504
        tmp += 0x100;                                           \
505
    d.VIS_W64(r) = tmp >> 8;
506

    
507
    PMUL(0);
508
    PMUL(1);
509
    PMUL(2);
510
    PMUL(3);
511
#undef PMUL
512

    
513
    DT0 = d.d;
514
}
515

    
516
void helper_fmul8sux16(void)
517
{
518
    vis64 s, d;
519
    uint32_t tmp;
520

    
521
    s.d = DT0;
522
    d.d = DT1;
523

    
524
#define PMUL(r)                                                         \
525
    tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
526
    if ((tmp & 0xff) > 0x7f)                                            \
527
        tmp += 0x100;                                                   \
528
    d.VIS_W64(r) = tmp >> 8;
529

    
530
    PMUL(0);
531
    PMUL(1);
532
    PMUL(2);
533
    PMUL(3);
534
#undef PMUL
535

    
536
    DT0 = d.d;
537
}
538

    
539
void helper_fmul8ulx16(void)
540
{
541
    vis64 s, d;
542
    uint32_t tmp;
543

    
544
    s.d = DT0;
545
    d.d = DT1;
546

    
547
#define PMUL(r)                                                         \
548
    tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
549
    if ((tmp & 0xff) > 0x7f)                                            \
550
        tmp += 0x100;                                                   \
551
    d.VIS_W64(r) = tmp >> 8;
552

    
553
    PMUL(0);
554
    PMUL(1);
555
    PMUL(2);
556
    PMUL(3);
557
#undef PMUL
558

    
559
    DT0 = d.d;
560
}
561

    
562
void helper_fmuld8sux16(void)
563
{
564
    vis64 s, d;
565
    uint32_t tmp;
566

    
567
    s.d = DT0;
568
    d.d = DT1;
569

    
570
#define PMUL(r)                                                         \
571
    tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
572
    if ((tmp & 0xff) > 0x7f)                                            \
573
        tmp += 0x100;                                                   \
574
    d.VIS_L64(r) = tmp;
575

    
576
    // Reverse calculation order to handle overlap
577
    PMUL(1);
578
    PMUL(0);
579
#undef PMUL
580

    
581
    DT0 = d.d;
582
}
583

    
584
void helper_fmuld8ulx16(void)
585
{
586
    vis64 s, d;
587
    uint32_t tmp;
588

    
589
    s.d = DT0;
590
    d.d = DT1;
591

    
592
#define PMUL(r)                                                         \
593
    tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
594
    if ((tmp & 0xff) > 0x7f)                                            \
595
        tmp += 0x100;                                                   \
596
    d.VIS_L64(r) = tmp;
597

    
598
    // Reverse calculation order to handle overlap
599
    PMUL(1);
600
    PMUL(0);
601
#undef PMUL
602

    
603
    DT0 = d.d;
604
}
605

    
606
void helper_fexpand(void)
607
{
608
    vis32 s;
609
    vis64 d;
610

    
611
    s.l = (uint32_t)(*(uint64_t *)&DT0 & 0xffffffff);
612
    d.d = DT1;
613
    d.VIS_W64(0) = s.VIS_B32(0) << 4;
614
    d.VIS_W64(1) = s.VIS_B32(1) << 4;
615
    d.VIS_W64(2) = s.VIS_B32(2) << 4;
616
    d.VIS_W64(3) = s.VIS_B32(3) << 4;
617

    
618
    DT0 = d.d;
619
}
620

    
621
#define VIS_HELPER(name, F)                             \
622
    void name##16(void)                                 \
623
    {                                                   \
624
        vis64 s, d;                                     \
625
                                                        \
626
        s.d = DT0;                                      \
627
        d.d = DT1;                                      \
628
                                                        \
629
        d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0));   \
630
        d.VIS_W64(1) = F(d.VIS_W64(1), s.VIS_W64(1));   \
631
        d.VIS_W64(2) = F(d.VIS_W64(2), s.VIS_W64(2));   \
632
        d.VIS_W64(3) = F(d.VIS_W64(3), s.VIS_W64(3));   \
633
                                                        \
634
        DT0 = d.d;                                      \
635
    }                                                   \
636
                                                        \
637
    uint32_t name##16s(uint32_t src1, uint32_t src2)    \
638
    {                                                   \
639
        vis32 s, d;                                     \
640
                                                        \
641
        s.l = src1;                                     \
642
        d.l = src2;                                     \
643
                                                        \
644
        d.VIS_W32(0) = F(d.VIS_W32(0), s.VIS_W32(0));   \
645
        d.VIS_W32(1) = F(d.VIS_W32(1), s.VIS_W32(1));   \
646
                                                        \
647
        return d.l;                                     \
648
    }                                                   \
649
                                                        \
650
    void name##32(void)                                 \
651
    {                                                   \
652
        vis64 s, d;                                     \
653
                                                        \
654
        s.d = DT0;                                      \
655
        d.d = DT1;                                      \
656
                                                        \
657
        d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0));   \
658
        d.VIS_L64(1) = F(d.VIS_L64(1), s.VIS_L64(1));   \
659
                                                        \
660
        DT0 = d.d;                                      \
661
    }                                                   \
662
                                                        \
663
    uint32_t name##32s(uint32_t src1, uint32_t src2)    \
664
    {                                                   \
665
        vis32 s, d;                                     \
666
                                                        \
667
        s.l = src1;                                     \
668
        d.l = src2;                                     \
669
                                                        \
670
        d.l = F(d.l, s.l);                              \
671
                                                        \
672
        return d.l;                                     \
673
    }
674

    
675
#define FADD(a, b) ((a) + (b))
676
#define FSUB(a, b) ((a) - (b))
677
VIS_HELPER(helper_fpadd, FADD)
678
VIS_HELPER(helper_fpsub, FSUB)
679

    
680
#define VIS_CMPHELPER(name, F)                                        \
681
    void name##16(void)                                           \
682
    {                                                             \
683
        vis64 s, d;                                               \
684
                                                                  \
685
        s.d = DT0;                                                \
686
        d.d = DT1;                                                \
687
                                                                  \
688
        d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0))? 1: 0;       \
689
        d.VIS_W64(0) |= F(d.VIS_W64(1), s.VIS_W64(1))? 2: 0;      \
690
        d.VIS_W64(0) |= F(d.VIS_W64(2), s.VIS_W64(2))? 4: 0;      \
691
        d.VIS_W64(0) |= F(d.VIS_W64(3), s.VIS_W64(3))? 8: 0;      \
692
                                                                  \
693
        DT0 = d.d;                                                \
694
    }                                                             \
695
                                                                  \
696
    void name##32(void)                                           \
697
    {                                                             \
698
        vis64 s, d;                                               \
699
                                                                  \
700
        s.d = DT0;                                                \
701
        d.d = DT1;                                                \
702
                                                                  \
703
        d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0))? 1: 0;       \
704
        d.VIS_L64(0) |= F(d.VIS_L64(1), s.VIS_L64(1))? 2: 0;      \
705
                                                                  \
706
        DT0 = d.d;                                                \
707
    }
708

    
709
#define FCMPGT(a, b) ((a) > (b))
710
#define FCMPEQ(a, b) ((a) == (b))
711
#define FCMPLE(a, b) ((a) <= (b))
712
#define FCMPNE(a, b) ((a) != (b))
713

    
714
VIS_CMPHELPER(helper_fcmpgt, FCMPGT)
715
VIS_CMPHELPER(helper_fcmpeq, FCMPEQ)
716
VIS_CMPHELPER(helper_fcmple, FCMPLE)
717
VIS_CMPHELPER(helper_fcmpne, FCMPNE)
718
#endif
719

    
720
void helper_check_ieee_exceptions(void)
721
{
722
    target_ulong status;
723

    
724
    status = get_float_exception_flags(&env->fp_status);
725
    if (status) {
726
        /* Copy IEEE 754 flags into FSR */
727
        if (status & float_flag_invalid)
728
            env->fsr |= FSR_NVC;
729
        if (status & float_flag_overflow)
730
            env->fsr |= FSR_OFC;
731
        if (status & float_flag_underflow)
732
            env->fsr |= FSR_UFC;
733
        if (status & float_flag_divbyzero)
734
            env->fsr |= FSR_DZC;
735
        if (status & float_flag_inexact)
736
            env->fsr |= FSR_NXC;
737

    
738
        if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) {
739
            /* Unmasked exception, generate a trap */
740
            env->fsr |= FSR_FTT_IEEE_EXCP;
741
            raise_exception(TT_FP_EXCP);
742
        } else {
743
            /* Accumulate exceptions */
744
            env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
745
        }
746
    }
747
}
748

    
749
void helper_clear_float_exceptions(void)
750
{
751
    set_float_exception_flags(0, &env->fp_status);
752
}
753

    
754
float32 helper_fabss(float32 src)
755
{
756
    return float32_abs(src);
757
}
758

    
759
#ifdef TARGET_SPARC64
760
void helper_fabsd(void)
761
{
762
    DT0 = float64_abs(DT1);
763
}
764

    
765
void helper_fabsq(void)
766
{
767
    QT0 = float128_abs(QT1);
768
}
769
#endif
770

    
771
float32 helper_fsqrts(float32 src)
772
{
773
    return float32_sqrt(src, &env->fp_status);
774
}
775

    
776
void helper_fsqrtd(void)
777
{
778
    DT0 = float64_sqrt(DT1, &env->fp_status);
779
}
780

    
781
void helper_fsqrtq(void)
782
{
783
    QT0 = float128_sqrt(QT1, &env->fp_status);
784
}
785

    
786
#define GEN_FCMP(name, size, reg1, reg2, FS, TRAP)                      \
787
    void glue(helper_, name) (void)                                     \
788
    {                                                                   \
789
        target_ulong new_fsr;                                           \
790
                                                                        \
791
        env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                     \
792
        switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) {   \
793
        case float_relation_unordered:                                  \
794
            new_fsr = (FSR_FCC1 | FSR_FCC0) << FS;                      \
795
            if ((env->fsr & FSR_NVM) || TRAP) {                         \
796
                env->fsr |= new_fsr;                                    \
797
                env->fsr |= FSR_NVC;                                    \
798
                env->fsr |= FSR_FTT_IEEE_EXCP;                          \
799
                raise_exception(TT_FP_EXCP);                            \
800
            } else {                                                    \
801
                env->fsr |= FSR_NVA;                                    \
802
            }                                                           \
803
            break;                                                      \
804
        case float_relation_less:                                       \
805
            new_fsr = FSR_FCC0 << FS;                                   \
806
            break;                                                      \
807
        case float_relation_greater:                                    \
808
            new_fsr = FSR_FCC1 << FS;                                   \
809
            break;                                                      \
810
        default:                                                        \
811
            new_fsr = 0;                                                \
812
            break;                                                      \
813
        }                                                               \
814
        env->fsr |= new_fsr;                                            \
815
    }
816
#define GEN_FCMPS(name, size, FS, TRAP)                                 \
817
    void glue(helper_, name)(float32 src1, float32 src2)                \
818
    {                                                                   \
819
        target_ulong new_fsr;                                           \
820
                                                                        \
821
        env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                     \
822
        switch (glue(size, _compare) (src1, src2, &env->fp_status)) {   \
823
        case float_relation_unordered:                                  \
824
            new_fsr = (FSR_FCC1 | FSR_FCC0) << FS;                      \
825
            if ((env->fsr & FSR_NVM) || TRAP) {                         \
826
                env->fsr |= new_fsr;                                    \
827
                env->fsr |= FSR_NVC;                                    \
828
                env->fsr |= FSR_FTT_IEEE_EXCP;                          \
829
                raise_exception(TT_FP_EXCP);                            \
830
            } else {                                                    \
831
                env->fsr |= FSR_NVA;                                    \
832
            }                                                           \
833
            break;                                                      \
834
        case float_relation_less:                                       \
835
            new_fsr = FSR_FCC0 << FS;                                   \
836
            break;                                                      \
837
        case float_relation_greater:                                    \
838
            new_fsr = FSR_FCC1 << FS;                                   \
839
            break;                                                      \
840
        default:                                                        \
841
            new_fsr = 0;                                                \
842
            break;                                                      \
843
        }                                                               \
844
        env->fsr |= new_fsr;                                            \
845
    }
846

    
847
GEN_FCMPS(fcmps, float32, 0, 0);
848
GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
849

    
850
GEN_FCMPS(fcmpes, float32, 0, 1);
851
GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
852

    
853
GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0);
854
GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1);
855

    
856
static uint32_t compute_all_flags(void)
857
{
858
    return env->psr & PSR_ICC;
859
}
860

    
861
static uint32_t compute_C_flags(void)
862
{
863
    return env->psr & PSR_CARRY;
864
}
865

    
866
static inline uint32_t get_NZ_icc(target_ulong dst)
867
{
868
    uint32_t ret = 0;
869

    
870
    if (!(dst & 0xffffffffULL))
871
        ret |= PSR_ZERO;
872
    if ((int32_t) (dst & 0xffffffffULL) < 0)
873
        ret |= PSR_NEG;
874
    return ret;
875
}
876

    
877
#ifdef TARGET_SPARC64
878
static uint32_t compute_all_flags_xcc(void)
879
{
880
    return env->xcc & PSR_ICC;
881
}
882

    
883
static uint32_t compute_C_flags_xcc(void)
884
{
885
    return env->xcc & PSR_CARRY;
886
}
887

    
888
static inline uint32_t get_NZ_xcc(target_ulong dst)
889
{
890
    uint32_t ret = 0;
891

    
892
    if (!dst)
893
        ret |= PSR_ZERO;
894
    if ((int64_t)dst < 0)
895
        ret |= PSR_NEG;
896
    return ret;
897
}
898
#endif
899

    
900
static inline uint32_t get_V_div_icc(target_ulong src2)
901
{
902
    uint32_t ret = 0;
903

    
904
    if (src2 != 0)
905
        ret |= PSR_OVF;
906
    return ret;
907
}
908

    
909
static uint32_t compute_all_div(void)
910
{
911
    uint32_t ret;
912

    
913
    ret = get_NZ_icc(CC_DST);
914
    ret |= get_V_div_icc(CC_SRC2);
915
    return ret;
916
}
917

    
918
static uint32_t compute_C_div(void)
919
{
920
    return 0;
921
}
922

    
923
/* carry = (src1[31] & src2[31]) | ( ~dst[31] & (src1[31] | src2[31])) */
924
static inline uint32_t get_C_add_icc(target_ulong dst, target_ulong src1,
925
                                     target_ulong src2)
926
{
927
    uint32_t ret = 0;
928

    
929
    if (((src1 & (1ULL << 31)) & (src2 & (1ULL << 31)))
930
        | ((~(dst & (1ULL << 31)))
931
           & ((src1 & (1ULL << 31)) | (src2 & (1ULL << 31)))))
932
        ret |= PSR_CARRY;
933
    return ret;
934
}
935

    
936
static inline uint32_t get_V_add_icc(target_ulong dst, target_ulong src1,
937
                                         target_ulong src2)
938
{
939
    uint32_t ret = 0;
940

    
941
    if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1ULL << 31))
942
        ret |= PSR_OVF;
943
    return ret;
944
}
945

    
946
#ifdef TARGET_SPARC64
947
static inline uint32_t get_C_add_xcc(target_ulong dst, target_ulong src1)
948
{
949
    uint32_t ret = 0;
950

    
951
    if (dst < src1)
952
        ret |= PSR_CARRY;
953
    return ret;
954
}
955

    
956
static inline uint32_t get_V_add_xcc(target_ulong dst, target_ulong src1,
957
                                         target_ulong src2)
958
{
959
    uint32_t ret = 0;
960

    
961
    if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1ULL << 63))
962
        ret |= PSR_OVF;
963
    return ret;
964
}
965

    
966
static uint32_t compute_all_add_xcc(void)
967
{
968
    uint32_t ret;
969

    
970
    ret = get_NZ_xcc(CC_DST);
971
    ret |= get_C_add_xcc(CC_DST, CC_SRC);
972
    ret |= get_V_add_xcc(CC_DST, CC_SRC, CC_SRC2);
973
    return ret;
974
}
975

    
976
static uint32_t compute_C_add_xcc(void)
977
{
978
    return get_C_add_xcc(CC_DST, CC_SRC);
979
}
980
#endif
981

    
982
static uint32_t compute_all_add(void)
983
{
984
    uint32_t ret;
985

    
986
    ret = get_NZ_icc(CC_DST);
987
    ret |= get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
988
    ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
989
    return ret;
990
}
991

    
992
static uint32_t compute_C_add(void)
993
{
994
    return get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
995
}
996

    
997
#ifdef TARGET_SPARC64
998
static uint32_t compute_all_addx_xcc(void)
999
{
1000
    uint32_t ret;
1001

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

    
1009
static uint32_t compute_C_addx_xcc(void)
1010
{
1011
    uint32_t ret;
1012

    
1013
    ret = get_C_add_xcc(CC_DST - CC_SRC2, CC_SRC);
1014
    ret |= get_C_add_xcc(CC_DST, CC_SRC);
1015
    return ret;
1016
}
1017
#endif
1018

    
1019
static inline uint32_t get_V_tag_icc(target_ulong src1, target_ulong src2)
1020
{
1021
    uint32_t ret = 0;
1022

    
1023
    if ((src1 | src2) & 0x3)
1024
        ret |= PSR_OVF;
1025
    return ret;
1026
}
1027

    
1028
static uint32_t compute_all_tadd(void)
1029
{
1030
    uint32_t ret;
1031

    
1032
    ret = get_NZ_icc(CC_DST);
1033
    ret |= get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
1034
    ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
1035
    ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
1036
    return ret;
1037
}
1038

    
1039
static uint32_t compute_C_tadd(void)
1040
{
1041
    return get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
1042
}
1043

    
1044
static uint32_t compute_all_taddtv(void)
1045
{
1046
    uint32_t ret;
1047

    
1048
    ret = get_NZ_icc(CC_DST);
1049
    ret |= get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
1050
    return ret;
1051
}
1052

    
1053
static uint32_t compute_C_taddtv(void)
1054
{
1055
    return get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
1056
}
1057

    
1058
/* carry = (~src1[31] & src2[31]) | ( dst[31]  & (~src1[31] | src2[31])) */
1059
static inline uint32_t get_C_sub_icc(target_ulong dst, target_ulong src1,
1060
                                     target_ulong src2)
1061
{
1062
    uint32_t ret = 0;
1063

    
1064
    if (((~(src1 & (1ULL << 31))) & (src2 & (1ULL << 31)))
1065
        | ((dst & (1ULL << 31)) & (( ~(src1 & (1ULL << 31)))
1066
                                   | (src2 & (1ULL << 31)))))
1067
        ret |= PSR_CARRY;
1068
    return ret;
1069
}
1070

    
1071
static inline uint32_t get_V_sub_icc(target_ulong dst, target_ulong src1,
1072
                                     target_ulong src2)
1073
{
1074
    uint32_t ret = 0;
1075

    
1076
    if (((src1 ^ src2) & (src1 ^ dst)) & (1ULL << 31))
1077
        ret |= PSR_OVF;
1078
    return ret;
1079
}
1080

    
1081

    
1082
#ifdef TARGET_SPARC64
1083
static inline uint32_t get_C_sub_xcc(target_ulong src1, target_ulong src2)
1084
{
1085
    uint32_t ret = 0;
1086

    
1087
    if (src1 < src2)
1088
        ret |= PSR_CARRY;
1089
    return ret;
1090
}
1091

    
1092
static inline uint32_t get_V_sub_xcc(target_ulong dst, target_ulong src1,
1093
                                     target_ulong src2)
1094
{
1095
    uint32_t ret = 0;
1096

    
1097
    if (((src1 ^ src2) & (src1 ^ dst)) & (1ULL << 63))
1098
        ret |= PSR_OVF;
1099
    return ret;
1100
}
1101

    
1102
static uint32_t compute_all_sub_xcc(void)
1103
{
1104
    uint32_t ret;
1105

    
1106
    ret = get_NZ_xcc(CC_DST);
1107
    ret |= get_C_sub_xcc(CC_SRC, CC_SRC2);
1108
    ret |= get_V_sub_xcc(CC_DST, CC_SRC, CC_SRC2);
1109
    return ret;
1110
}
1111

    
1112
static uint32_t compute_C_sub_xcc(void)
1113
{
1114
    return get_C_sub_xcc(CC_SRC, CC_SRC2);
1115
}
1116
#endif
1117

    
1118
static uint32_t compute_all_sub(void)
1119
{
1120
    uint32_t ret;
1121

    
1122
    ret = get_NZ_icc(CC_DST);
1123
    ret |= get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1124
    ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1125
    return ret;
1126
}
1127

    
1128
static uint32_t compute_C_sub(void)
1129
{
1130
    return get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1131
}
1132

    
1133
#ifdef TARGET_SPARC64
1134
static uint32_t compute_all_subx_xcc(void)
1135
{
1136
    uint32_t ret;
1137

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

    
1145
static uint32_t compute_C_subx_xcc(void)
1146
{
1147
    uint32_t ret;
1148

    
1149
    ret = get_C_sub_xcc(CC_DST - CC_SRC2, CC_SRC);
1150
    ret |= get_C_sub_xcc(CC_DST, CC_SRC2);
1151
    return ret;
1152
}
1153
#endif
1154

    
1155
static uint32_t compute_all_tsub(void)
1156
{
1157
    uint32_t ret;
1158

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

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

    
1171
static uint32_t compute_all_tsubtv(void)
1172
{
1173
    uint32_t ret;
1174

    
1175
    ret = get_NZ_icc(CC_DST);
1176
    ret |= get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1177
    return ret;
1178
}
1179

    
1180
static uint32_t compute_C_tsubtv(void)
1181
{
1182
    return get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1183
}
1184

    
1185
static uint32_t compute_all_logic(void)
1186
{
1187
    return get_NZ_icc(CC_DST);
1188
}
1189

    
1190
static uint32_t compute_C_logic(void)
1191
{
1192
    return 0;
1193
}
1194

    
1195
#ifdef TARGET_SPARC64
1196
static uint32_t compute_all_logic_xcc(void)
1197
{
1198
    return get_NZ_xcc(CC_DST);
1199
}
1200
#endif
1201

    
1202
typedef struct CCTable {
1203
    uint32_t (*compute_all)(void); /* return all the flags */
1204
    uint32_t (*compute_c)(void);  /* return the C flag */
1205
} CCTable;
1206

    
1207
static const CCTable icc_table[CC_OP_NB] = {
1208
    /* CC_OP_DYNAMIC should never happen */
1209
    [CC_OP_FLAGS] = { compute_all_flags, compute_C_flags },
1210
    [CC_OP_DIV] = { compute_all_div, compute_C_div },
1211
    [CC_OP_ADD] = { compute_all_add, compute_C_add },
1212
    [CC_OP_ADDX] = { compute_all_add, compute_C_add },
1213
    [CC_OP_TADD] = { compute_all_tadd, compute_C_tadd },
1214
    [CC_OP_TADDTV] = { compute_all_taddtv, compute_C_taddtv },
1215
    [CC_OP_SUB] = { compute_all_sub, compute_C_sub },
1216
    [CC_OP_SUBX] = { compute_all_sub, compute_C_sub },
1217
    [CC_OP_TSUB] = { compute_all_tsub, compute_C_tsub },
1218
    [CC_OP_TSUBTV] = { compute_all_tsubtv, compute_C_tsubtv },
1219
    [CC_OP_LOGIC] = { compute_all_logic, compute_C_logic },
1220
};
1221

    
1222
#ifdef TARGET_SPARC64
1223
static const CCTable xcc_table[CC_OP_NB] = {
1224
    /* CC_OP_DYNAMIC should never happen */
1225
    [CC_OP_FLAGS] = { compute_all_flags_xcc, compute_C_flags_xcc },
1226
    [CC_OP_DIV] = { compute_all_logic_xcc, compute_C_logic },
1227
    [CC_OP_ADD] = { compute_all_add_xcc, compute_C_add_xcc },
1228
    [CC_OP_ADDX] = { compute_all_addx_xcc, compute_C_addx_xcc },
1229
    [CC_OP_TADD] = { compute_all_add_xcc, compute_C_add_xcc },
1230
    [CC_OP_TADDTV] = { compute_all_add_xcc, compute_C_add_xcc },
1231
    [CC_OP_SUB] = { compute_all_sub_xcc, compute_C_sub_xcc },
1232
    [CC_OP_SUBX] = { compute_all_subx_xcc, compute_C_subx_xcc },
1233
    [CC_OP_TSUB] = { compute_all_sub_xcc, compute_C_sub_xcc },
1234
    [CC_OP_TSUBTV] = { compute_all_sub_xcc, compute_C_sub_xcc },
1235
    [CC_OP_LOGIC] = { compute_all_logic_xcc, compute_C_logic },
1236
};
1237
#endif
1238

    
1239
void helper_compute_psr(void)
1240
{
1241
    uint32_t new_psr;
1242

    
1243
    new_psr = icc_table[CC_OP].compute_all();
1244
    env->psr = new_psr;
1245
#ifdef TARGET_SPARC64
1246
    new_psr = xcc_table[CC_OP].compute_all();
1247
    env->xcc = new_psr;
1248
#endif
1249
    CC_OP = CC_OP_FLAGS;
1250
}
1251

    
1252
uint32_t helper_compute_C_icc(void)
1253
{
1254
    uint32_t ret;
1255

    
1256
    ret = icc_table[CC_OP].compute_c() >> PSR_CARRY_SHIFT;
1257
    return ret;
1258
}
1259

    
1260
#ifdef TARGET_SPARC64
1261
GEN_FCMPS(fcmps_fcc1, float32, 22, 0);
1262
GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
1263
GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0);
1264

    
1265
GEN_FCMPS(fcmps_fcc2, float32, 24, 0);
1266
GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
1267
GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0);
1268

    
1269
GEN_FCMPS(fcmps_fcc3, float32, 26, 0);
1270
GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
1271
GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0);
1272

    
1273
GEN_FCMPS(fcmpes_fcc1, float32, 22, 1);
1274
GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
1275
GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1);
1276

    
1277
GEN_FCMPS(fcmpes_fcc2, float32, 24, 1);
1278
GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
1279
GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1);
1280

    
1281
GEN_FCMPS(fcmpes_fcc3, float32, 26, 1);
1282
GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
1283
GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
1284
#endif
1285
#undef GEN_FCMPS
1286

    
1287
#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) && \
1288
    defined(DEBUG_MXCC)
1289
static void dump_mxcc(CPUState *env)
1290
{
1291
    printf("mxccdata: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64
1292
           "\n",
1293
           env->mxccdata[0], env->mxccdata[1],
1294
           env->mxccdata[2], env->mxccdata[3]);
1295
    printf("mxccregs: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64
1296
           "\n"
1297
           "          %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64
1298
           "\n",
1299
           env->mxccregs[0], env->mxccregs[1],
1300
           env->mxccregs[2], env->mxccregs[3],
1301
           env->mxccregs[4], env->mxccregs[5],
1302
           env->mxccregs[6], env->mxccregs[7]);
1303
}
1304
#endif
1305

    
1306
#if (defined(TARGET_SPARC64) || !defined(CONFIG_USER_ONLY)) \
1307
    && defined(DEBUG_ASI)
1308
static void dump_asi(const char *txt, target_ulong addr, int asi, int size,
1309
                     uint64_t r1)
1310
{
1311
    switch (size)
1312
    {
1313
    case 1:
1314
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %02" PRIx64 "\n", txt,
1315
                    addr, asi, r1 & 0xff);
1316
        break;
1317
    case 2:
1318
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %04" PRIx64 "\n", txt,
1319
                    addr, asi, r1 & 0xffff);
1320
        break;
1321
    case 4:
1322
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %08" PRIx64 "\n", txt,
1323
                    addr, asi, r1 & 0xffffffff);
1324
        break;
1325
    case 8:
1326
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %016" PRIx64 "\n", txt,
1327
                    addr, asi, r1);
1328
        break;
1329
    }
1330
}
1331
#endif
1332

    
1333
#ifndef TARGET_SPARC64
1334
#ifndef CONFIG_USER_ONLY
1335
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1336
{
1337
    uint64_t ret = 0;
1338
#if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
1339
    uint32_t last_addr = addr;
1340
#endif
1341

    
1342
    helper_check_align(addr, size - 1);
1343
    switch (asi) {
1344
    case 2: /* SuperSparc MXCC registers */
1345
        switch (addr) {
1346
        case 0x01c00a00: /* MXCC control register */
1347
            if (size == 8)
1348
                ret = env->mxccregs[3];
1349
            else
1350
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1351
                             size);
1352
            break;
1353
        case 0x01c00a04: /* MXCC control register */
1354
            if (size == 4)
1355
                ret = env->mxccregs[3];
1356
            else
1357
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1358
                             size);
1359
            break;
1360
        case 0x01c00c00: /* Module reset register */
1361
            if (size == 8) {
1362
                ret = env->mxccregs[5];
1363
                // should we do something here?
1364
            } else
1365
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1366
                             size);
1367
            break;
1368
        case 0x01c00f00: /* MBus port address register */
1369
            if (size == 8)
1370
                ret = env->mxccregs[7];
1371
            else
1372
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1373
                             size);
1374
            break;
1375
        default:
1376
            DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr,
1377
                         size);
1378
            break;
1379
        }
1380
        DPRINTF_MXCC("asi = %d, size = %d, sign = %d, "
1381
                     "addr = %08x -> ret = %" PRIx64 ","
1382
                     "addr = %08x\n", asi, size, sign, last_addr, ret, addr);
1383
#ifdef DEBUG_MXCC
1384
        dump_mxcc(env);
1385
#endif
1386
        break;
1387
    case 3: /* MMU probe */
1388
        {
1389
            int mmulev;
1390

    
1391
            mmulev = (addr >> 8) & 15;
1392
            if (mmulev > 4)
1393
                ret = 0;
1394
            else
1395
                ret = mmu_probe(env, addr, mmulev);
1396
            DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08" PRIx64 "\n",
1397
                        addr, mmulev, ret);
1398
        }
1399
        break;
1400
    case 4: /* read MMU regs */
1401
        {
1402
            int reg = (addr >> 8) & 0x1f;
1403

    
1404
            ret = env->mmuregs[reg];
1405
            if (reg == 3) /* Fault status cleared on read */
1406
                env->mmuregs[3] = 0;
1407
            else if (reg == 0x13) /* Fault status read */
1408
                ret = env->mmuregs[3];
1409
            else if (reg == 0x14) /* Fault address read */
1410
                ret = env->mmuregs[4];
1411
            DPRINTF_MMU("mmu_read: reg[%d] = 0x%08" PRIx64 "\n", reg, ret);
1412
        }
1413
        break;
1414
    case 5: // Turbosparc ITLB Diagnostic
1415
    case 6: // Turbosparc DTLB Diagnostic
1416
    case 7: // Turbosparc IOTLB Diagnostic
1417
        break;
1418
    case 9: /* Supervisor code access */
1419
        switch(size) {
1420
        case 1:
1421
            ret = ldub_code(addr);
1422
            break;
1423
        case 2:
1424
            ret = lduw_code(addr);
1425
            break;
1426
        default:
1427
        case 4:
1428
            ret = ldl_code(addr);
1429
            break;
1430
        case 8:
1431
            ret = ldq_code(addr);
1432
            break;
1433
        }
1434
        break;
1435
    case 0xa: /* User data access */
1436
        switch(size) {
1437
        case 1:
1438
            ret = ldub_user(addr);
1439
            break;
1440
        case 2:
1441
            ret = lduw_user(addr);
1442
            break;
1443
        default:
1444
        case 4:
1445
            ret = ldl_user(addr);
1446
            break;
1447
        case 8:
1448
            ret = ldq_user(addr);
1449
            break;
1450
        }
1451
        break;
1452
    case 0xb: /* Supervisor data access */
1453
        switch(size) {
1454
        case 1:
1455
            ret = ldub_kernel(addr);
1456
            break;
1457
        case 2:
1458
            ret = lduw_kernel(addr);
1459
            break;
1460
        default:
1461
        case 4:
1462
            ret = ldl_kernel(addr);
1463
            break;
1464
        case 8:
1465
            ret = ldq_kernel(addr);
1466
            break;
1467
        }
1468
        break;
1469
    case 0xc: /* I-cache tag */
1470
    case 0xd: /* I-cache data */
1471
    case 0xe: /* D-cache tag */
1472
    case 0xf: /* D-cache data */
1473
        break;
1474
    case 0x20: /* MMU passthrough */
1475
        switch(size) {
1476
        case 1:
1477
            ret = ldub_phys(addr);
1478
            break;
1479
        case 2:
1480
            ret = lduw_phys(addr);
1481
            break;
1482
        default:
1483
        case 4:
1484
            ret = ldl_phys(addr);
1485
            break;
1486
        case 8:
1487
            ret = ldq_phys(addr);
1488
            break;
1489
        }
1490
        break;
1491
    case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
1492
        switch(size) {
1493
        case 1:
1494
            ret = ldub_phys((target_phys_addr_t)addr
1495
                            | ((target_phys_addr_t)(asi & 0xf) << 32));
1496
            break;
1497
        case 2:
1498
            ret = lduw_phys((target_phys_addr_t)addr
1499
                            | ((target_phys_addr_t)(asi & 0xf) << 32));
1500
            break;
1501
        default:
1502
        case 4:
1503
            ret = ldl_phys((target_phys_addr_t)addr
1504
                           | ((target_phys_addr_t)(asi & 0xf) << 32));
1505
            break;
1506
        case 8:
1507
            ret = ldq_phys((target_phys_addr_t)addr
1508
                           | ((target_phys_addr_t)(asi & 0xf) << 32));
1509
            break;
1510
        }
1511
        break;
1512
    case 0x30: // Turbosparc secondary cache diagnostic
1513
    case 0x31: // Turbosparc RAM snoop
1514
    case 0x32: // Turbosparc page table descriptor diagnostic
1515
    case 0x39: /* data cache diagnostic register */
1516
        ret = 0;
1517
        break;
1518
    case 0x38: /* SuperSPARC MMU Breakpoint Control Registers */
1519
        {
1520
            int reg = (addr >> 8) & 3;
1521

    
1522
            switch(reg) {
1523
            case 0: /* Breakpoint Value (Addr) */
1524
                ret = env->mmubpregs[reg];
1525
                break;
1526
            case 1: /* Breakpoint Mask */
1527
                ret = env->mmubpregs[reg];
1528
                break;
1529
            case 2: /* Breakpoint Control */
1530
                ret = env->mmubpregs[reg];
1531
                break;
1532
            case 3: /* Breakpoint Status */
1533
                ret = env->mmubpregs[reg];
1534
                env->mmubpregs[reg] = 0ULL;
1535
                break;
1536
            }
1537
            DPRINTF_MMU("read breakpoint reg[%d] 0x%016" PRIx64 "\n", reg,
1538
                        ret);
1539
        }
1540
        break;
1541
    case 8: /* User code access, XXX */
1542
    default:
1543
        do_unassigned_access(addr, 0, 0, asi, size);
1544
        ret = 0;
1545
        break;
1546
    }
1547
    if (sign) {
1548
        switch(size) {
1549
        case 1:
1550
            ret = (int8_t) ret;
1551
            break;
1552
        case 2:
1553
            ret = (int16_t) ret;
1554
            break;
1555
        case 4:
1556
            ret = (int32_t) ret;
1557
            break;
1558
        default:
1559
            break;
1560
        }
1561
    }
1562
#ifdef DEBUG_ASI
1563
    dump_asi("read ", last_addr, asi, size, ret);
1564
#endif
1565
    return ret;
1566
}
1567

    
1568
void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
1569
{
1570
    helper_check_align(addr, size - 1);
1571
    switch(asi) {
1572
    case 2: /* SuperSparc MXCC registers */
1573
        switch (addr) {
1574
        case 0x01c00000: /* MXCC stream data register 0 */
1575
            if (size == 8)
1576
                env->mxccdata[0] = val;
1577
            else
1578
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1579
                             size);
1580
            break;
1581
        case 0x01c00008: /* MXCC stream data register 1 */
1582
            if (size == 8)
1583
                env->mxccdata[1] = val;
1584
            else
1585
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1586
                             size);
1587
            break;
1588
        case 0x01c00010: /* MXCC stream data register 2 */
1589
            if (size == 8)
1590
                env->mxccdata[2] = val;
1591
            else
1592
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1593
                             size);
1594
            break;
1595
        case 0x01c00018: /* MXCC stream data register 3 */
1596
            if (size == 8)
1597
                env->mxccdata[3] = val;
1598
            else
1599
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1600
                             size);
1601
            break;
1602
        case 0x01c00100: /* MXCC stream source */
1603
            if (size == 8)
1604
                env->mxccregs[0] = val;
1605
            else
1606
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1607
                             size);
1608
            env->mxccdata[0] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1609
                                        0);
1610
            env->mxccdata[1] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1611
                                        8);
1612
            env->mxccdata[2] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1613
                                        16);
1614
            env->mxccdata[3] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1615
                                        24);
1616
            break;
1617
        case 0x01c00200: /* MXCC stream destination */
1618
            if (size == 8)
1619
                env->mxccregs[1] = val;
1620
            else
1621
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1622
                             size);
1623
            stq_phys((env->mxccregs[1] & 0xffffffffULL) +  0,
1624
                     env->mxccdata[0]);
1625
            stq_phys((env->mxccregs[1] & 0xffffffffULL) +  8,
1626
                     env->mxccdata[1]);
1627
            stq_phys((env->mxccregs[1] & 0xffffffffULL) + 16,
1628
                     env->mxccdata[2]);
1629
            stq_phys((env->mxccregs[1] & 0xffffffffULL) + 24,
1630
                     env->mxccdata[3]);
1631
            break;
1632
        case 0x01c00a00: /* MXCC control register */
1633
            if (size == 8)
1634
                env->mxccregs[3] = val;
1635
            else
1636
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1637
                             size);
1638
            break;
1639
        case 0x01c00a04: /* MXCC control register */
1640
            if (size == 4)
1641
                env->mxccregs[3] = (env->mxccregs[3] & 0xffffffff00000000ULL)
1642
                    | val;
1643
            else
1644
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1645
                             size);
1646
            break;
1647
        case 0x01c00e00: /* MXCC error register  */
1648
            // writing a 1 bit clears the error
1649
            if (size == 8)
1650
                env->mxccregs[6] &= ~val;
1651
            else
1652
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1653
                             size);
1654
            break;
1655
        case 0x01c00f00: /* MBus port address register */
1656
            if (size == 8)
1657
                env->mxccregs[7] = val;
1658
            else
1659
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1660
                             size);
1661
            break;
1662
        default:
1663
            DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr,
1664
                         size);
1665
            break;
1666
        }
1667
        DPRINTF_MXCC("asi = %d, size = %d, addr = %08x, val = %" PRIx64 "\n",
1668
                     asi, size, addr, val);
1669
#ifdef DEBUG_MXCC
1670
        dump_mxcc(env);
1671
#endif
1672
        break;
1673
    case 3: /* MMU flush */
1674
        {
1675
            int mmulev;
1676

    
1677
            mmulev = (addr >> 8) & 15;
1678
            DPRINTF_MMU("mmu flush level %d\n", mmulev);
1679
            switch (mmulev) {
1680
            case 0: // flush page
1681
                tlb_flush_page(env, addr & 0xfffff000);
1682
                break;
1683
            case 1: // flush segment (256k)
1684
            case 2: // flush region (16M)
1685
            case 3: // flush context (4G)
1686
            case 4: // flush entire
1687
                tlb_flush(env, 1);
1688
                break;
1689
            default:
1690
                break;
1691
            }
1692
#ifdef DEBUG_MMU
1693
            dump_mmu(env);
1694
#endif
1695
        }
1696
        break;
1697
    case 4: /* write MMU regs */
1698
        {
1699
            int reg = (addr >> 8) & 0x1f;
1700
            uint32_t oldreg;
1701

    
1702
            oldreg = env->mmuregs[reg];
1703
            switch(reg) {
1704
            case 0: // Control Register
1705
                env->mmuregs[reg] = (env->mmuregs[reg] & 0xff000000) |
1706
                                    (val & 0x00ffffff);
1707
                // Mappings generated during no-fault mode or MMU
1708
                // disabled mode are invalid in normal mode
1709
                if ((oldreg & (MMU_E | MMU_NF | env->def->mmu_bm)) !=
1710
                    (env->mmuregs[reg] & (MMU_E | MMU_NF | env->def->mmu_bm)))
1711
                    tlb_flush(env, 1);
1712
                break;
1713
            case 1: // Context Table Pointer Register
1714
                env->mmuregs[reg] = val & env->def->mmu_ctpr_mask;
1715
                break;
1716
            case 2: // Context Register
1717
                env->mmuregs[reg] = val & env->def->mmu_cxr_mask;
1718
                if (oldreg != env->mmuregs[reg]) {
1719
                    /* we flush when the MMU context changes because
1720
                       QEMU has no MMU context support */
1721
                    tlb_flush(env, 1);
1722
                }
1723
                break;
1724
            case 3: // Synchronous Fault Status Register with Clear
1725
            case 4: // Synchronous Fault Address Register
1726
                break;
1727
            case 0x10: // TLB Replacement Control Register
1728
                env->mmuregs[reg] = val & env->def->mmu_trcr_mask;
1729
                break;
1730
            case 0x13: // Synchronous Fault Status Register with Read and Clear
1731
                env->mmuregs[3] = val & env->def->mmu_sfsr_mask;
1732
                break;
1733
            case 0x14: // Synchronous Fault Address Register
1734
                env->mmuregs[4] = val;
1735
                break;
1736
            default:
1737
                env->mmuregs[reg] = val;
1738
                break;
1739
            }
1740
            if (oldreg != env->mmuregs[reg]) {
1741
                DPRINTF_MMU("mmu change reg[%d]: 0x%08x -> 0x%08x\n",
1742
                            reg, oldreg, env->mmuregs[reg]);
1743
            }
1744
#ifdef DEBUG_MMU
1745
            dump_mmu(env);
1746
#endif
1747
        }
1748
        break;
1749
    case 5: // Turbosparc ITLB Diagnostic
1750
    case 6: // Turbosparc DTLB Diagnostic
1751
    case 7: // Turbosparc IOTLB Diagnostic
1752
        break;
1753
    case 0xa: /* User data access */
1754
        switch(size) {
1755
        case 1:
1756
            stb_user(addr, val);
1757
            break;
1758
        case 2:
1759
            stw_user(addr, val);
1760
            break;
1761
        default:
1762
        case 4:
1763
            stl_user(addr, val);
1764
            break;
1765
        case 8:
1766
            stq_user(addr, val);
1767
            break;
1768
        }
1769
        break;
1770
    case 0xb: /* Supervisor data access */
1771
        switch(size) {
1772
        case 1:
1773
            stb_kernel(addr, val);
1774
            break;
1775
        case 2:
1776
            stw_kernel(addr, val);
1777
            break;
1778
        default:
1779
        case 4:
1780
            stl_kernel(addr, val);
1781
            break;
1782
        case 8:
1783
            stq_kernel(addr, val);
1784
            break;
1785
        }
1786
        break;
1787
    case 0xc: /* I-cache tag */
1788
    case 0xd: /* I-cache data */
1789
    case 0xe: /* D-cache tag */
1790
    case 0xf: /* D-cache data */
1791
    case 0x10: /* I/D-cache flush page */
1792
    case 0x11: /* I/D-cache flush segment */
1793
    case 0x12: /* I/D-cache flush region */
1794
    case 0x13: /* I/D-cache flush context */
1795
    case 0x14: /* I/D-cache flush user */
1796
        break;
1797
    case 0x17: /* Block copy, sta access */
1798
        {
1799
            // val = src
1800
            // addr = dst
1801
            // copy 32 bytes
1802
            unsigned int i;
1803
            uint32_t src = val & ~3, dst = addr & ~3, temp;
1804

    
1805
            for (i = 0; i < 32; i += 4, src += 4, dst += 4) {
1806
                temp = ldl_kernel(src);
1807
                stl_kernel(dst, temp);
1808
            }
1809
        }
1810
        break;
1811
    case 0x1f: /* Block fill, stda access */
1812
        {
1813
            // addr = dst
1814
            // fill 32 bytes with val
1815
            unsigned int i;
1816
            uint32_t dst = addr & 7;
1817

    
1818
            for (i = 0; i < 32; i += 8, dst += 8)
1819
                stq_kernel(dst, val);
1820
        }
1821
        break;
1822
    case 0x20: /* MMU passthrough */
1823
        {
1824
            switch(size) {
1825
            case 1:
1826
                stb_phys(addr, val);
1827
                break;
1828
            case 2:
1829
                stw_phys(addr, val);
1830
                break;
1831
            case 4:
1832
            default:
1833
                stl_phys(addr, val);
1834
                break;
1835
            case 8:
1836
                stq_phys(addr, val);
1837
                break;
1838
            }
1839
        }
1840
        break;
1841
    case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
1842
        {
1843
            switch(size) {
1844
            case 1:
1845
                stb_phys((target_phys_addr_t)addr
1846
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1847
                break;
1848
            case 2:
1849
                stw_phys((target_phys_addr_t)addr
1850
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1851
                break;
1852
            case 4:
1853
            default:
1854
                stl_phys((target_phys_addr_t)addr
1855
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1856
                break;
1857
            case 8:
1858
                stq_phys((target_phys_addr_t)addr
1859
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1860
                break;
1861
            }
1862
        }
1863
        break;
1864
    case 0x30: // store buffer tags or Turbosparc secondary cache diagnostic
1865
    case 0x31: // store buffer data, Ross RT620 I-cache flush or
1866
               // Turbosparc snoop RAM
1867
    case 0x32: // store buffer control or Turbosparc page table
1868
               // descriptor diagnostic
1869
    case 0x36: /* I-cache flash clear */
1870
    case 0x37: /* D-cache flash clear */
1871
    case 0x4c: /* breakpoint action */
1872
        break;
1873
    case 0x38: /* SuperSPARC MMU Breakpoint Control Registers*/
1874
        {
1875
            int reg = (addr >> 8) & 3;
1876

    
1877
            switch(reg) {
1878
            case 0: /* Breakpoint Value (Addr) */
1879
                env->mmubpregs[reg] = (val & 0xfffffffffULL);
1880
                break;
1881
            case 1: /* Breakpoint Mask */
1882
                env->mmubpregs[reg] = (val & 0xfffffffffULL);
1883
                break;
1884
            case 2: /* Breakpoint Control */
1885
                env->mmubpregs[reg] = (val & 0x7fULL);
1886
                break;
1887
            case 3: /* Breakpoint Status */
1888
                env->mmubpregs[reg] = (val & 0xfULL);
1889
                break;
1890
            }
1891
            DPRINTF_MMU("write breakpoint reg[%d] 0x%016x\n", reg,
1892
                        env->mmuregs[reg]);
1893
        }
1894
        break;
1895
    case 8: /* User code access, XXX */
1896
    case 9: /* Supervisor code access, XXX */
1897
    default:
1898
        do_unassigned_access(addr, 1, 0, asi, size);
1899
        break;
1900
    }
1901
#ifdef DEBUG_ASI
1902
    dump_asi("write", addr, asi, size, val);
1903
#endif
1904
}
1905

    
1906
#endif /* CONFIG_USER_ONLY */
1907
#else /* TARGET_SPARC64 */
1908

    
1909
#ifdef CONFIG_USER_ONLY
1910
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1911
{
1912
    uint64_t ret = 0;
1913
#if defined(DEBUG_ASI)
1914
    target_ulong last_addr = addr;
1915
#endif
1916

    
1917
    if (asi < 0x80)
1918
        raise_exception(TT_PRIV_ACT);
1919

    
1920
    helper_check_align(addr, size - 1);
1921
    address_mask(env, &addr);
1922

    
1923
    switch (asi) {
1924
    case 0x82: // Primary no-fault
1925
    case 0x8a: // Primary no-fault LE
1926
        if (page_check_range(addr, size, PAGE_READ) == -1) {
1927
#ifdef DEBUG_ASI
1928
            dump_asi("read ", last_addr, asi, size, ret);
1929
#endif
1930
            return 0;
1931
        }
1932
        // Fall through
1933
    case 0x80: // Primary
1934
    case 0x88: // Primary LE
1935
        {
1936
            switch(size) {
1937
            case 1:
1938
                ret = ldub_raw(addr);
1939
                break;
1940
            case 2:
1941
                ret = lduw_raw(addr);
1942
                break;
1943
            case 4:
1944
                ret = ldl_raw(addr);
1945
                break;
1946
            default:
1947
            case 8:
1948
                ret = ldq_raw(addr);
1949
                break;
1950
            }
1951
        }
1952
        break;
1953
    case 0x83: // Secondary no-fault
1954
    case 0x8b: // Secondary no-fault LE
1955
        if (page_check_range(addr, size, PAGE_READ) == -1) {
1956
#ifdef DEBUG_ASI
1957
            dump_asi("read ", last_addr, asi, size, ret);
1958
#endif
1959
            return 0;
1960
        }
1961
        // Fall through
1962
    case 0x81: // Secondary
1963
    case 0x89: // Secondary LE
1964
        // XXX
1965
        break;
1966
    default:
1967
        break;
1968
    }
1969

    
1970
    /* Convert from little endian */
1971
    switch (asi) {
1972
    case 0x88: // Primary LE
1973
    case 0x89: // Secondary LE
1974
    case 0x8a: // Primary no-fault LE
1975
    case 0x8b: // Secondary no-fault LE
1976
        switch(size) {
1977
        case 2:
1978
            ret = bswap16(ret);
1979
            break;
1980
        case 4:
1981
            ret = bswap32(ret);
1982
            break;
1983
        case 8:
1984
            ret = bswap64(ret);
1985
            break;
1986
        default:
1987
            break;
1988
        }
1989
    default:
1990
        break;
1991
    }
1992

    
1993
    /* Convert to signed number */
1994
    if (sign) {
1995
        switch(size) {
1996
        case 1:
1997
            ret = (int8_t) ret;
1998
            break;
1999
        case 2:
2000
            ret = (int16_t) ret;
2001
            break;
2002
        case 4:
2003
            ret = (int32_t) ret;
2004
            break;
2005
        default:
2006
            break;
2007
        }
2008
    }
2009
#ifdef DEBUG_ASI
2010
    dump_asi("read ", last_addr, asi, size, ret);
2011
#endif
2012
    return ret;
2013
}
2014

    
2015
void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
2016
{
2017
#ifdef DEBUG_ASI
2018
    dump_asi("write", addr, asi, size, val);
2019
#endif
2020
    if (asi < 0x80)
2021
        raise_exception(TT_PRIV_ACT);
2022

    
2023
    helper_check_align(addr, size - 1);
2024
    address_mask(env, &addr);
2025

    
2026
    /* Convert to little endian */
2027
    switch (asi) {
2028
    case 0x88: // Primary LE
2029
    case 0x89: // Secondary LE
2030
        switch(size) {
2031
        case 2:
2032
            val = bswap16(val);
2033
            break;
2034
        case 4:
2035
            val = bswap32(val);
2036
            break;
2037
        case 8:
2038
            val = bswap64(val);
2039
            break;
2040
        default:
2041
            break;
2042
        }
2043
    default:
2044
        break;
2045
    }
2046

    
2047
    switch(asi) {
2048
    case 0x80: // Primary
2049
    case 0x88: // Primary LE
2050
        {
2051
            switch(size) {
2052
            case 1:
2053
                stb_raw(addr, val);
2054
                break;
2055
            case 2:
2056
                stw_raw(addr, val);
2057
                break;
2058
            case 4:
2059
                stl_raw(addr, val);
2060
                break;
2061
            case 8:
2062
            default:
2063
                stq_raw(addr, val);
2064
                break;
2065
            }
2066
        }
2067
        break;
2068
    case 0x81: // Secondary
2069
    case 0x89: // Secondary LE
2070
        // XXX
2071
        return;
2072

    
2073
    case 0x82: // Primary no-fault, RO
2074
    case 0x83: // Secondary no-fault, RO
2075
    case 0x8a: // Primary no-fault LE, RO
2076
    case 0x8b: // Secondary no-fault LE, RO
2077
    default:
2078
        do_unassigned_access(addr, 1, 0, 1, size);
2079
        return;
2080
    }
2081
}
2082

    
2083
#else /* CONFIG_USER_ONLY */
2084

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

    
2092
    asi &= 0xff;
2093

    
2094
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
2095
        || ((env->def->features & CPU_FEATURE_HYPV)
2096
            && asi >= 0x30 && asi < 0x80
2097
            && !(env->hpstate & HS_PRIV)))
2098
        raise_exception(TT_PRIV_ACT);
2099

    
2100
    helper_check_align(addr, size - 1);
2101
    switch (asi) {
2102
    case 0x82: // Primary no-fault
2103
    case 0x8a: // Primary no-fault LE
2104
        if (cpu_get_phys_page_debug(env, addr) == -1ULL) {
2105
#ifdef DEBUG_ASI
2106
            dump_asi("read ", last_addr, asi, size, ret);
2107
#endif
2108
            return 0;
2109
        }
2110
        // Fall through
2111
    case 0x10: // As if user primary
2112
    case 0x18: // As if user primary LE
2113
    case 0x80: // Primary
2114
    case 0x88: // Primary LE
2115
    case 0xe2: // UA2007 Primary block init
2116
    case 0xe3: // UA2007 Secondary block init
2117
        if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
2118
            if ((env->def->features & CPU_FEATURE_HYPV)
2119
                && env->hpstate & HS_PRIV) {
2120
                switch(size) {
2121
                case 1:
2122
                    ret = ldub_hypv(addr);
2123
                    break;
2124
                case 2:
2125
                    ret = lduw_hypv(addr);
2126
                    break;
2127
                case 4:
2128
                    ret = ldl_hypv(addr);
2129
                    break;
2130
                default:
2131
                case 8:
2132
                    ret = ldq_hypv(addr);
2133
                    break;
2134
                }
2135
            } else {
2136
                switch(size) {
2137
                case 1:
2138
                    ret = ldub_kernel(addr);
2139
                    break;
2140
                case 2:
2141
                    ret = lduw_kernel(addr);
2142
                    break;
2143
                case 4:
2144
                    ret = ldl_kernel(addr);
2145
                    break;
2146
                default:
2147
                case 8:
2148
                    ret = ldq_kernel(addr);
2149
                    break;
2150
                }
2151
            }
2152
        } else {
2153
            switch(size) {
2154
            case 1:
2155
                ret = ldub_user(addr);
2156
                break;
2157
            case 2:
2158
                ret = lduw_user(addr);
2159
                break;
2160
            case 4:
2161
                ret = ldl_user(addr);
2162
                break;
2163
            default:
2164
            case 8:
2165
                ret = ldq_user(addr);
2166
                break;
2167
            }
2168
        }
2169
        break;
2170
    case 0x14: // Bypass
2171
    case 0x15: // Bypass, non-cacheable
2172
    case 0x1c: // Bypass LE
2173
    case 0x1d: // Bypass, non-cacheable LE
2174
        {
2175
            switch(size) {
2176
            case 1:
2177
                ret = ldub_phys(addr);
2178
                break;
2179
            case 2:
2180
                ret = lduw_phys(addr);
2181
                break;
2182
            case 4:
2183
                ret = ldl_phys(addr);
2184
                break;
2185
            default:
2186
            case 8:
2187
                ret = ldq_phys(addr);
2188
                break;
2189
            }
2190
            break;
2191
        }
2192
    case 0x24: // Nucleus quad LDD 128 bit atomic
2193
    case 0x2c: // Nucleus quad LDD 128 bit atomic LE
2194
        //  Only ldda allowed
2195
        raise_exception(TT_ILL_INSN);
2196
        return 0;
2197
    case 0x83: // Secondary no-fault
2198
    case 0x8b: // Secondary no-fault LE
2199
        if (cpu_get_phys_page_debug(env, addr) == -1ULL) {
2200
#ifdef DEBUG_ASI
2201
            dump_asi("read ", last_addr, asi, size, ret);
2202
#endif
2203
            return 0;
2204
        }
2205
        // Fall through
2206
    case 0x04: // Nucleus
2207
    case 0x0c: // Nucleus Little Endian (LE)
2208
    case 0x11: // As if user secondary
2209
    case 0x19: // As if user secondary LE
2210
    case 0x4a: // UPA config
2211
    case 0x81: // Secondary
2212
    case 0x89: // Secondary LE
2213
        // XXX
2214
        break;
2215
    case 0x45: // LSU
2216
        ret = env->lsu;
2217
        break;
2218
    case 0x50: // I-MMU regs
2219
        {
2220
            int reg = (addr >> 3) & 0xf;
2221

    
2222
            if (reg == 0) {
2223
                // I-TSB Tag Target register
2224
                ret = ultrasparc_tag_target(env->immu.tag_access);
2225
            } else {
2226
                ret = env->immuregs[reg];
2227
            }
2228

    
2229
            break;
2230
        }
2231
    case 0x51: // I-MMU 8k TSB pointer
2232
        {
2233
            // env->immuregs[5] holds I-MMU TSB register value
2234
            // env->immuregs[6] holds I-MMU Tag Access register value
2235
            ret = ultrasparc_tsb_pointer(env->immu.tsb, env->immu.tag_access,
2236
                                         8*1024);
2237
            break;
2238
        }
2239
    case 0x52: // I-MMU 64k TSB pointer
2240
        {
2241
            // env->immuregs[5] holds I-MMU TSB register value
2242
            // env->immuregs[6] holds I-MMU Tag Access register value
2243
            ret = ultrasparc_tsb_pointer(env->immu.tsb, env->immu.tag_access,
2244
                                         64*1024);
2245
            break;
2246
        }
2247
    case 0x55: // I-MMU data access
2248
        {
2249
            int reg = (addr >> 3) & 0x3f;
2250

    
2251
            ret = env->itlb[reg].tte;
2252
            break;
2253
        }
2254
    case 0x56: // I-MMU tag read
2255
        {
2256
            int reg = (addr >> 3) & 0x3f;
2257

    
2258
            ret = env->itlb[reg].tag;
2259
            break;
2260
        }
2261
    case 0x58: // D-MMU regs
2262
        {
2263
            int reg = (addr >> 3) & 0xf;
2264

    
2265
            if (reg == 0) {
2266
                // D-TSB Tag Target register
2267
                ret = ultrasparc_tag_target(env->dmmu.tag_access);
2268
            } else {
2269
                ret = env->dmmuregs[reg];
2270
            }
2271
            break;
2272
        }
2273
    case 0x59: // D-MMU 8k TSB pointer
2274
        {
2275
            // env->dmmuregs[5] holds D-MMU TSB register value
2276
            // env->dmmuregs[6] holds D-MMU Tag Access register value
2277
            ret = ultrasparc_tsb_pointer(env->dmmu.tsb, env->dmmu.tag_access,
2278
                                         8*1024);
2279
            break;
2280
        }
2281
    case 0x5a: // D-MMU 64k TSB pointer
2282
        {
2283
            // env->dmmuregs[5] holds D-MMU TSB register value
2284
            // env->dmmuregs[6] holds D-MMU Tag Access register value
2285
            ret = ultrasparc_tsb_pointer(env->dmmu.tsb, env->dmmu.tag_access,
2286
                                         64*1024);
2287
            break;
2288
        }
2289
    case 0x5d: // D-MMU data access
2290
        {
2291
            int reg = (addr >> 3) & 0x3f;
2292

    
2293
            ret = env->dtlb[reg].tte;
2294
            break;
2295
        }
2296
    case 0x5e: // D-MMU tag read
2297
        {
2298
            int reg = (addr >> 3) & 0x3f;
2299

    
2300
            ret = env->dtlb[reg].tag;
2301
            break;
2302
        }
2303
    case 0x46: // D-cache data
2304
    case 0x47: // D-cache tag access
2305
    case 0x4b: // E-cache error enable
2306
    case 0x4c: // E-cache asynchronous fault status
2307
    case 0x4d: // E-cache asynchronous fault address
2308
    case 0x4e: // E-cache tag data
2309
    case 0x66: // I-cache instruction access
2310
    case 0x67: // I-cache tag access
2311
    case 0x6e: // I-cache predecode
2312
    case 0x6f: // I-cache LRU etc.
2313
    case 0x76: // E-cache tag
2314
    case 0x7e: // E-cache tag
2315
        break;
2316
    case 0x5b: // D-MMU data pointer
2317
    case 0x48: // Interrupt dispatch, RO
2318
    case 0x49: // Interrupt data receive
2319
    case 0x7f: // Incoming interrupt vector, RO
2320
        // XXX
2321
        break;
2322
    case 0x54: // I-MMU data in, WO
2323
    case 0x57: // I-MMU demap, WO
2324
    case 0x5c: // D-MMU data in, WO
2325
    case 0x5f: // D-MMU demap, WO
2326
    case 0x77: // Interrupt vector, WO
2327
    default:
2328
        do_unassigned_access(addr, 0, 0, 1, size);
2329
        ret = 0;
2330
        break;
2331
    }
2332

    
2333
    /* Convert from little endian */
2334
    switch (asi) {
2335
    case 0x0c: // Nucleus Little Endian (LE)
2336
    case 0x18: // As if user primary LE
2337
    case 0x19: // As if user secondary LE
2338
    case 0x1c: // Bypass LE
2339
    case 0x1d: // Bypass, non-cacheable LE
2340
    case 0x88: // Primary LE
2341
    case 0x89: // Secondary LE
2342
    case 0x8a: // Primary no-fault LE
2343
    case 0x8b: // Secondary no-fault LE
2344
        switch(size) {
2345
        case 2:
2346
            ret = bswap16(ret);
2347
            break;
2348
        case 4:
2349
            ret = bswap32(ret);
2350
            break;
2351
        case 8:
2352
            ret = bswap64(ret);
2353
            break;
2354
        default:
2355
            break;
2356
        }
2357
    default:
2358
        break;
2359
    }
2360

    
2361
    /* Convert to signed number */
2362
    if (sign) {
2363
        switch(size) {
2364
        case 1:
2365
            ret = (int8_t) ret;
2366
            break;
2367
        case 2:
2368
            ret = (int16_t) ret;
2369
            break;
2370
        case 4:
2371
            ret = (int32_t) ret;
2372
            break;
2373
        default:
2374
            break;
2375
        }
2376
    }
2377
#ifdef DEBUG_ASI
2378
    dump_asi("read ", last_addr, asi, size, ret);
2379
#endif
2380
    return ret;
2381
}
2382

    
2383
void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
2384
{
2385
#ifdef DEBUG_ASI
2386
    dump_asi("write", addr, asi, size, val);
2387
#endif
2388

    
2389
    asi &= 0xff;
2390

    
2391
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
2392
        || ((env->def->features & CPU_FEATURE_HYPV)
2393
            && asi >= 0x30 && asi < 0x80
2394
            && !(env->hpstate & HS_PRIV)))
2395
        raise_exception(TT_PRIV_ACT);
2396

    
2397
    helper_check_align(addr, size - 1);
2398
    /* Convert to little endian */
2399
    switch (asi) {
2400
    case 0x0c: // Nucleus Little Endian (LE)
2401
    case 0x18: // As if user primary LE
2402
    case 0x19: // As if user secondary LE
2403
    case 0x1c: // Bypass LE
2404
    case 0x1d: // Bypass, non-cacheable LE
2405
    case 0x88: // Primary LE
2406
    case 0x89: // Secondary LE
2407
        switch(size) {
2408
        case 2:
2409
            val = bswap16(val);
2410
            break;
2411
        case 4:
2412
            val = bswap32(val);
2413
            break;
2414
        case 8:
2415
            val = bswap64(val);
2416
            break;
2417
        default:
2418
            break;
2419
        }
2420
    default:
2421
        break;
2422
    }
2423

    
2424
    switch(asi) {
2425
    case 0x10: // As if user primary
2426
    case 0x18: // As if user primary LE
2427
    case 0x80: // Primary
2428
    case 0x88: // Primary LE
2429
    case 0xe2: // UA2007 Primary block init
2430
    case 0xe3: // UA2007 Secondary block init
2431
        if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
2432
            if ((env->def->features & CPU_FEATURE_HYPV)
2433
                && env->hpstate & HS_PRIV) {
2434
                switch(size) {
2435
                case 1:
2436
                    stb_hypv(addr, val);
2437
                    break;
2438
                case 2:
2439
                    stw_hypv(addr, val);
2440
                    break;
2441
                case 4:
2442
                    stl_hypv(addr, val);
2443
                    break;
2444
                case 8:
2445
                default:
2446
                    stq_hypv(addr, val);
2447
                    break;
2448
                }
2449
            } else {
2450
                switch(size) {
2451
                case 1:
2452
                    stb_kernel(addr, val);
2453
                    break;
2454
                case 2:
2455
                    stw_kernel(addr, val);
2456
                    break;
2457
                case 4:
2458
                    stl_kernel(addr, val);
2459
                    break;
2460
                case 8:
2461
                default:
2462
                    stq_kernel(addr, val);
2463
                    break;
2464
                }
2465
            }
2466
        } else {
2467
            switch(size) {
2468
            case 1:
2469
                stb_user(addr, val);
2470
                break;
2471
            case 2:
2472
                stw_user(addr, val);
2473
                break;
2474
            case 4:
2475
                stl_user(addr, val);
2476
                break;
2477
            case 8:
2478
            default:
2479
                stq_user(addr, val);
2480
                break;
2481
            }
2482
        }
2483
        break;
2484
    case 0x14: // Bypass
2485
    case 0x15: // Bypass, non-cacheable
2486
    case 0x1c: // Bypass LE
2487
    case 0x1d: // Bypass, non-cacheable LE
2488
        {
2489
            switch(size) {
2490
            case 1:
2491
                stb_phys(addr, val);
2492
                break;
2493
            case 2:
2494
                stw_phys(addr, val);
2495
                break;
2496
            case 4:
2497
                stl_phys(addr, val);
2498
                break;
2499
            case 8:
2500
            default:
2501
                stq_phys(addr, val);
2502
                break;
2503
            }
2504
        }
2505
        return;
2506
    case 0x24: // Nucleus quad LDD 128 bit atomic
2507
    case 0x2c: // Nucleus quad LDD 128 bit atomic LE
2508
        //  Only ldda allowed
2509
        raise_exception(TT_ILL_INSN);
2510
        return;
2511
    case 0x04: // Nucleus
2512
    case 0x0c: // Nucleus Little Endian (LE)
2513
    case 0x11: // As if user secondary
2514
    case 0x19: // As if user secondary LE
2515
    case 0x4a: // UPA config
2516
    case 0x81: // Secondary
2517
    case 0x89: // Secondary LE
2518
        // XXX
2519
        return;
2520
    case 0x45: // LSU
2521
        {
2522
            uint64_t oldreg;
2523

    
2524
            oldreg = env->lsu;
2525
            env->lsu = val & (DMMU_E | IMMU_E);
2526
            // Mappings generated during D/I MMU disabled mode are
2527
            // invalid in normal mode
2528
            if (oldreg != env->lsu) {
2529
                DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n",
2530
                            oldreg, env->lsu);
2531
#ifdef DEBUG_MMU
2532
                dump_mmu(env);
2533
#endif
2534
                tlb_flush(env, 1);
2535
            }
2536
            return;
2537
        }
2538
    case 0x50: // I-MMU regs
2539
        {
2540
            int reg = (addr >> 3) & 0xf;
2541
            uint64_t oldreg;
2542

    
2543
            oldreg = env->immuregs[reg];
2544
            switch(reg) {
2545
            case 0: // RO
2546
                return;
2547
            case 1: // Not in I-MMU
2548
            case 2:
2549
                return;
2550
            case 3: // SFSR
2551
                if ((val & 1) == 0)
2552
                    val = 0; // Clear SFSR
2553
                env->immu.sfsr = val;
2554
                break;
2555
            case 4: // RO
2556
                return;
2557
            case 5: // TSB access
2558
                DPRINTF_MMU("immu TSB write: 0x%016" PRIx64 " -> 0x%016"
2559
                            PRIx64 "\n", env->immu.tsb, val);
2560
                env->immu.tsb = val;
2561
                break;
2562
            case 6: // Tag access
2563
                env->immu.tag_access = val;
2564
                break;
2565
            case 7:
2566
            case 8:
2567
                return;
2568
            default:
2569
                break;
2570
            }
2571

    
2572
            if (oldreg != env->immuregs[reg]) {
2573
                DPRINTF_MMU("immu change reg[%d]: 0x%016" PRIx64 " -> 0x%016"
2574
                            PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
2575
            }
2576
#ifdef DEBUG_MMU
2577
            dump_mmu(env);
2578
#endif
2579
            return;
2580
        }
2581
    case 0x54: // I-MMU data in
2582
        replace_tlb_1bit_lru(env->itlb, env->immu.tag_access, val, "immu", env);
2583
        return;
2584
    case 0x55: // I-MMU data access
2585
        {
2586
            // TODO: auto demap
2587

    
2588
            unsigned int i = (addr >> 3) & 0x3f;
2589

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

    
2592
#ifdef DEBUG_MMU
2593
            DPRINTF_MMU("immu data access replaced entry [%i]\n", i);
2594
            dump_mmu(env);
2595
#endif
2596
            return;
2597
        }
2598
    case 0x57: // I-MMU demap
2599
        demap_tlb(env->itlb, val, "immu", env);
2600
        return;
2601
    case 0x58: // D-MMU regs
2602
        {
2603
            int reg = (addr >> 3) & 0xf;
2604
            uint64_t oldreg;
2605

    
2606
            oldreg = env->dmmuregs[reg];
2607
            switch(reg) {
2608
            case 0: // RO
2609
            case 4:
2610
                return;
2611
            case 3: // SFSR
2612
                if ((val & 1) == 0) {
2613
                    val = 0; // Clear SFSR, Fault address
2614
                    env->dmmu.sfar = 0;
2615
                }
2616
                env->dmmu.sfsr = val;
2617
                break;
2618
            case 1: // Primary context
2619
                env->dmmu.mmu_primary_context = val;
2620
                break;
2621
            case 2: // Secondary context
2622
                env->dmmu.mmu_secondary_context = val;
2623
                break;
2624
            case 5: // TSB access
2625
                DPRINTF_MMU("dmmu TSB write: 0x%016" PRIx64 " -> 0x%016"
2626
                            PRIx64 "\n", env->dmmu.tsb, val);
2627
                env->dmmu.tsb = val;
2628
                break;
2629
            case 6: // Tag access
2630
                env->dmmu.tag_access = val;
2631
                break;
2632
            case 7: // Virtual Watchpoint
2633
            case 8: // Physical Watchpoint
2634
            default:
2635
                env->dmmuregs[reg] = val;
2636
                break;
2637
            }
2638

    
2639
            if (oldreg != env->dmmuregs[reg]) {
2640
                DPRINTF_MMU("dmmu change reg[%d]: 0x%016" PRIx64 " -> 0x%016"
2641
                            PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
2642
            }
2643
#ifdef DEBUG_MMU
2644
            dump_mmu(env);
2645
#endif
2646
            return;
2647
        }
2648
    case 0x5c: // D-MMU data in
2649
        replace_tlb_1bit_lru(env->dtlb, env->dmmu.tag_access, val, "dmmu", env);
2650
        return;
2651
    case 0x5d: // D-MMU data access
2652
        {
2653
            unsigned int i = (addr >> 3) & 0x3f;
2654

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

    
2657
#ifdef DEBUG_MMU
2658
            DPRINTF_MMU("dmmu data access replaced entry [%i]\n", i);
2659
            dump_mmu(env);
2660
#endif
2661
            return;
2662
        }
2663
    case 0x5f: // D-MMU demap
2664
        demap_tlb(env->dtlb, val, "dmmu", env);
2665
        return;
2666
    case 0x49: // Interrupt data receive
2667
        // XXX
2668
        return;
2669
    case 0x46: // D-cache data
2670
    case 0x47: // D-cache tag access
2671
    case 0x4b: // E-cache error enable
2672
    case 0x4c: // E-cache asynchronous fault status
2673
    case 0x4d: // E-cache asynchronous fault address
2674
    case 0x4e: // E-cache tag data
2675
    case 0x66: // I-cache instruction access
2676
    case 0x67: // I-cache tag access
2677
    case 0x6e: // I-cache predecode
2678
    case 0x6f: // I-cache LRU etc.
2679
    case 0x76: // E-cache tag
2680
    case 0x7e: // E-cache tag
2681
        return;
2682
    case 0x51: // I-MMU 8k TSB pointer, RO
2683
    case 0x52: // I-MMU 64k TSB pointer, RO
2684
    case 0x56: // I-MMU tag read, RO
2685
    case 0x59: // D-MMU 8k TSB pointer, RO
2686
    case 0x5a: // D-MMU 64k TSB pointer, RO
2687
    case 0x5b: // D-MMU data pointer, RO
2688
    case 0x5e: // D-MMU tag read, RO
2689
    case 0x48: // Interrupt dispatch, RO
2690
    case 0x7f: // Incoming interrupt vector, RO
2691
    case 0x82: // Primary no-fault, RO
2692
    case 0x83: // Secondary no-fault, RO
2693
    case 0x8a: // Primary no-fault LE, RO
2694
    case 0x8b: // Secondary no-fault LE, RO
2695
    default:
2696
        do_unassigned_access(addr, 1, 0, 1, size);
2697
        return;
2698
    }
2699
}
2700
#endif /* CONFIG_USER_ONLY */
2701

    
2702
void helper_ldda_asi(target_ulong addr, int asi, int rd)
2703
{
2704
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
2705
        || ((env->def->features & CPU_FEATURE_HYPV)
2706
            && asi >= 0x30 && asi < 0x80
2707
            && !(env->hpstate & HS_PRIV)))
2708
        raise_exception(TT_PRIV_ACT);
2709

    
2710
    switch (asi) {
2711
    case 0x24: // Nucleus quad LDD 128 bit atomic
2712
    case 0x2c: // Nucleus quad LDD 128 bit atomic LE
2713
        helper_check_align(addr, 0xf);
2714
        if (rd == 0) {
2715
            env->gregs[1] = ldq_kernel(addr + 8);
2716
            if (asi == 0x2c)
2717
                bswap64s(&env->gregs[1]);
2718
        } else if (rd < 8) {
2719
            env->gregs[rd] = ldq_kernel(addr);
2720
            env->gregs[rd + 1] = ldq_kernel(addr + 8);
2721
            if (asi == 0x2c) {
2722
                bswap64s(&env->gregs[rd]);
2723
                bswap64s(&env->gregs[rd + 1]);
2724
            }
2725
        } else {
2726
            env->regwptr[rd] = ldq_kernel(addr);
2727
            env->regwptr[rd + 1] = ldq_kernel(addr + 8);
2728
            if (asi == 0x2c) {
2729
                bswap64s(&env->regwptr[rd]);
2730
                bswap64s(&env->regwptr[rd + 1]);
2731
            }
2732
        }
2733
        break;
2734
    default:
2735
        helper_check_align(addr, 0x3);
2736
        if (rd == 0)
2737
            env->gregs[1] = helper_ld_asi(addr + 4, asi, 4, 0);
2738
        else if (rd < 8) {
2739
            env->gregs[rd] = helper_ld_asi(addr, asi, 4, 0);
2740
            env->gregs[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
2741
        } else {
2742
            env->regwptr[rd] = helper_ld_asi(addr, asi, 4, 0);
2743
            env->regwptr[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
2744
        }
2745
        break;
2746
    }
2747
}
2748

    
2749
void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
2750
{
2751
    unsigned int i;
2752
    target_ulong val;
2753

    
2754
    helper_check_align(addr, 3);
2755
    switch (asi) {
2756
    case 0xf0: // Block load primary
2757
    case 0xf1: // Block load secondary
2758
    case 0xf8: // Block load primary LE
2759
    case 0xf9: // Block load secondary LE
2760
        if (rd & 7) {
2761
            raise_exception(TT_ILL_INSN);
2762
            return;
2763
        }
2764
        helper_check_align(addr, 0x3f);
2765
        for (i = 0; i < 16; i++) {
2766
            *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x8f, 4,
2767
                                                         0);
2768
            addr += 4;
2769
        }
2770

    
2771
        return;
2772
    default:
2773
        break;
2774
    }
2775

    
2776
    val = helper_ld_asi(addr, asi, size, 0);
2777
    switch(size) {
2778
    default:
2779
    case 4:
2780
        *((uint32_t *)&env->fpr[rd]) = val;
2781
        break;
2782
    case 8:
2783
        *((int64_t *)&DT0) = val;
2784
        break;
2785
    case 16:
2786
        // XXX
2787
        break;
2788
    }
2789
}
2790

    
2791
void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
2792
{
2793
    unsigned int i;
2794
    target_ulong val = 0;
2795

    
2796
    helper_check_align(addr, 3);
2797
    switch (asi) {
2798
    case 0xe0: // UA2007 Block commit store primary (cache flush)
2799
    case 0xe1: // UA2007 Block commit store secondary (cache flush)
2800
    case 0xf0: // Block store primary
2801
    case 0xf1: // Block store secondary
2802
    case 0xf8: // Block store primary LE
2803
    case 0xf9: // Block store secondary LE
2804
        if (rd & 7) {
2805
            raise_exception(TT_ILL_INSN);
2806
            return;
2807
        }
2808
        helper_check_align(addr, 0x3f);
2809
        for (i = 0; i < 16; i++) {
2810
            val = *(uint32_t *)&env->fpr[rd++];
2811
            helper_st_asi(addr, val, asi & 0x8f, 4);
2812
            addr += 4;
2813
        }
2814

    
2815
        return;
2816
    default:
2817
        break;
2818
    }
2819

    
2820
    switch(size) {
2821
    default:
2822
    case 4:
2823
        val = *((uint32_t *)&env->fpr[rd]);
2824
        break;
2825
    case 8:
2826
        val = *((int64_t *)&DT0);
2827
        break;
2828
    case 16:
2829
        // XXX
2830
        break;
2831
    }
2832
    helper_st_asi(addr, val, asi, size);
2833
}
2834

    
2835
target_ulong helper_cas_asi(target_ulong addr, target_ulong val1,
2836
                            target_ulong val2, uint32_t asi)
2837
{
2838
    target_ulong ret;
2839

    
2840
    val2 &= 0xffffffffUL;
2841
    ret = helper_ld_asi(addr, asi, 4, 0);
2842
    ret &= 0xffffffffUL;
2843
    if (val2 == ret)
2844
        helper_st_asi(addr, val1 & 0xffffffffUL, asi, 4);
2845
    return ret;
2846
}
2847

    
2848
target_ulong helper_casx_asi(target_ulong addr, target_ulong val1,
2849
                             target_ulong val2, uint32_t asi)
2850
{
2851
    target_ulong ret;
2852

    
2853
    ret = helper_ld_asi(addr, asi, 8, 0);
2854
    if (val2 == ret)
2855
        helper_st_asi(addr, val1, asi, 8);
2856
    return ret;
2857
}
2858
#endif /* TARGET_SPARC64 */
2859

    
2860
#ifndef TARGET_SPARC64
2861
void helper_rett(void)
2862
{
2863
    unsigned int cwp;
2864

    
2865
    if (env->psret == 1)
2866
        raise_exception(TT_ILL_INSN);
2867

    
2868
    env->psret = 1;
2869
    cwp = cpu_cwp_inc(env, env->cwp + 1) ;
2870
    if (env->wim & (1 << cwp)) {
2871
        raise_exception(TT_WIN_UNF);
2872
    }
2873
    set_cwp(cwp);
2874
    env->psrs = env->psrps;
2875
}
2876
#endif
2877

    
2878
target_ulong helper_udiv(target_ulong a, target_ulong b)
2879
{
2880
    uint64_t x0;
2881
    uint32_t x1;
2882

    
2883
    x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
2884
    x1 = b;
2885

    
2886
    if (x1 == 0) {
2887
        raise_exception(TT_DIV_ZERO);
2888
    }
2889

    
2890
    x0 = x0 / x1;
2891
    if (x0 > 0xffffffff) {
2892
        env->cc_src2 = 1;
2893
        return 0xffffffff;
2894
    } else {
2895
        env->cc_src2 = 0;
2896
        return x0;
2897
    }
2898
}
2899

    
2900
target_ulong helper_sdiv(target_ulong a, target_ulong b)
2901
{
2902
    int64_t x0;
2903
    int32_t x1;
2904

    
2905
    x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
2906
    x1 = b;
2907

    
2908
    if (x1 == 0) {
2909
        raise_exception(TT_DIV_ZERO);
2910
    }
2911

    
2912
    x0 = x0 / x1;
2913
    if ((int32_t) x0 != x0) {
2914
        env->cc_src2 = 1;
2915
        return x0 < 0? 0x80000000: 0x7fffffff;
2916
    } else {
2917
        env->cc_src2 = 0;
2918
        return x0;
2919
    }
2920
}
2921

    
2922
void helper_stdf(target_ulong addr, int mem_idx)
2923
{
2924
    helper_check_align(addr, 7);
2925
#if !defined(CONFIG_USER_ONLY)
2926
    switch (mem_idx) {
2927
    case 0:
2928
        stfq_user(addr, DT0);
2929
        break;
2930
    case 1:
2931
        stfq_kernel(addr, DT0);
2932
        break;
2933
#ifdef TARGET_SPARC64
2934
    case 2:
2935
        stfq_hypv(addr, DT0);
2936
        break;
2937
#endif
2938
    default:
2939
        break;
2940
    }
2941
#else
2942
    address_mask(env, &addr);
2943
    stfq_raw(addr, DT0);
2944
#endif
2945
}
2946

    
2947
void helper_lddf(target_ulong addr, int mem_idx)
2948
{
2949
    helper_check_align(addr, 7);
2950
#if !defined(CONFIG_USER_ONLY)
2951
    switch (mem_idx) {
2952
    case 0:
2953
        DT0 = ldfq_user(addr);
2954
        break;
2955
    case 1:
2956
        DT0 = ldfq_kernel(addr);
2957
        break;
2958
#ifdef TARGET_SPARC64
2959
    case 2:
2960
        DT0 = ldfq_hypv(addr);
2961
        break;
2962
#endif
2963
    default:
2964
        break;
2965
    }
2966
#else
2967
    address_mask(env, &addr);
2968
    DT0 = ldfq_raw(addr);
2969
#endif
2970
}
2971

    
2972
void helper_ldqf(target_ulong addr, int mem_idx)
2973
{
2974
    // XXX add 128 bit load
2975
    CPU_QuadU u;
2976

    
2977
    helper_check_align(addr, 7);
2978
#if !defined(CONFIG_USER_ONLY)
2979
    switch (mem_idx) {
2980
    case 0:
2981
        u.ll.upper = ldq_user(addr);
2982
        u.ll.lower = ldq_user(addr + 8);
2983
        QT0 = u.q;
2984
        break;
2985
    case 1:
2986
        u.ll.upper = ldq_kernel(addr);
2987
        u.ll.lower = ldq_kernel(addr + 8);
2988
        QT0 = u.q;
2989
        break;
2990
#ifdef TARGET_SPARC64
2991
    case 2:
2992
        u.ll.upper = ldq_hypv(addr);
2993
        u.ll.lower = ldq_hypv(addr + 8);
2994
        QT0 = u.q;
2995
        break;
2996
#endif
2997
    default:
2998
        break;
2999
    }
3000
#else
3001
    address_mask(env, &addr);
3002
    u.ll.upper = ldq_raw(addr);
3003
    u.ll.lower = ldq_raw((addr + 8) & 0xffffffffULL);
3004
    QT0 = u.q;
3005
#endif
3006
}
3007

    
3008
void helper_stqf(target_ulong addr, int mem_idx)
3009
{
3010
    // XXX add 128 bit store
3011
    CPU_QuadU u;
3012

    
3013
    helper_check_align(addr, 7);
3014
#if !defined(CONFIG_USER_ONLY)
3015
    switch (mem_idx) {
3016
    case 0:
3017
        u.q = QT0;
3018
        stq_user(addr, u.ll.upper);
3019
        stq_user(addr + 8, u.ll.lower);
3020
        break;
3021
    case 1:
3022
        u.q = QT0;
3023
        stq_kernel(addr, u.ll.upper);
3024
        stq_kernel(addr + 8, u.ll.lower);
3025
        break;
3026
#ifdef TARGET_SPARC64
3027
    case 2:
3028
        u.q = QT0;
3029
        stq_hypv(addr, u.ll.upper);
3030
        stq_hypv(addr + 8, u.ll.lower);
3031
        break;
3032
#endif
3033
    default:
3034
        break;
3035
    }
3036
#else
3037
    u.q = QT0;
3038
    address_mask(env, &addr);
3039
    stq_raw(addr, u.ll.upper);
3040
    stq_raw((addr + 8) & 0xffffffffULL, u.ll.lower);
3041
#endif
3042
}
3043

    
3044
static inline void set_fsr(void)
3045
{
3046
    int rnd_mode;
3047

    
3048
    switch (env->fsr & FSR_RD_MASK) {
3049
    case FSR_RD_NEAREST:
3050
        rnd_mode = float_round_nearest_even;
3051
        break;
3052
    default:
3053
    case FSR_RD_ZERO:
3054
        rnd_mode = float_round_to_zero;
3055
        break;
3056
    case FSR_RD_POS:
3057
        rnd_mode = float_round_up;
3058
        break;
3059
    case FSR_RD_NEG:
3060
        rnd_mode = float_round_down;
3061
        break;
3062
    }
3063
    set_float_rounding_mode(rnd_mode, &env->fp_status);
3064
}
3065

    
3066
void helper_ldfsr(uint32_t new_fsr)
3067
{
3068
    env->fsr = (new_fsr & FSR_LDFSR_MASK) | (env->fsr & FSR_LDFSR_OLDMASK);
3069
    set_fsr();
3070
}
3071

    
3072
#ifdef TARGET_SPARC64
3073
void helper_ldxfsr(uint64_t new_fsr)
3074
{
3075
    env->fsr = (new_fsr & FSR_LDXFSR_MASK) | (env->fsr & FSR_LDXFSR_OLDMASK);
3076
    set_fsr();
3077
}
3078
#endif
3079

    
3080
void helper_debug(void)
3081
{
3082
    env->exception_index = EXCP_DEBUG;
3083
    cpu_loop_exit();
3084
}
3085

    
3086
#ifndef TARGET_SPARC64
3087
/* XXX: use another pointer for %iN registers to avoid slow wrapping
3088
   handling ? */
3089
void helper_save(void)
3090
{
3091
    uint32_t cwp;
3092

    
3093
    cwp = cpu_cwp_dec(env, env->cwp - 1);
3094
    if (env->wim & (1 << cwp)) {
3095
        raise_exception(TT_WIN_OVF);
3096
    }
3097
    set_cwp(cwp);
3098
}
3099

    
3100
void helper_restore(void)
3101
{
3102
    uint32_t cwp;
3103

    
3104
    cwp = cpu_cwp_inc(env, env->cwp + 1);
3105
    if (env->wim & (1 << cwp)) {
3106
        raise_exception(TT_WIN_UNF);
3107
    }
3108
    set_cwp(cwp);
3109
}
3110

    
3111
void helper_wrpsr(target_ulong new_psr)
3112
{
3113
    if ((new_psr & PSR_CWP) >= env->nwindows)
3114
        raise_exception(TT_ILL_INSN);
3115
    else
3116
        PUT_PSR(env, new_psr);
3117
}
3118

    
3119
target_ulong helper_rdpsr(void)
3120
{
3121
    return GET_PSR(env);
3122
}
3123

    
3124
#else
3125
/* XXX: use another pointer for %iN registers to avoid slow wrapping
3126
   handling ? */
3127
void helper_save(void)
3128
{
3129
    uint32_t cwp;
3130

    
3131
    cwp = cpu_cwp_dec(env, env->cwp - 1);
3132
    if (env->cansave == 0) {
3133
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
3134
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
3135
                                    ((env->wstate & 0x7) << 2)));
3136
    } else {
3137
        if (env->cleanwin - env->canrestore == 0) {
3138
            // XXX Clean windows without trap
3139
            raise_exception(TT_CLRWIN);
3140
        } else {
3141
            env->cansave--;
3142
            env->canrestore++;
3143
            set_cwp(cwp);
3144
        }
3145
    }
3146
}
3147

    
3148
void helper_restore(void)
3149
{
3150
    uint32_t cwp;
3151

    
3152
    cwp = cpu_cwp_inc(env, env->cwp + 1);
3153
    if (env->canrestore == 0) {
3154
        raise_exception(TT_FILL | (env->otherwin != 0 ?
3155
                                   (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
3156
                                   ((env->wstate & 0x7) << 2)));
3157
    } else {
3158
        env->cansave++;
3159
        env->canrestore--;
3160
        set_cwp(cwp);
3161
    }
3162
}
3163

    
3164
void helper_flushw(void)
3165
{
3166
    if (env->cansave != env->nwindows - 2) {
3167
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
3168
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
3169
                                    ((env->wstate & 0x7) << 2)));
3170
    }
3171
}
3172

    
3173
void helper_saved(void)
3174
{
3175
    env->cansave++;
3176
    if (env->otherwin == 0)
3177
        env->canrestore--;
3178
    else
3179
        env->otherwin--;
3180
}
3181

    
3182
void helper_restored(void)
3183
{
3184
    env->canrestore++;
3185
    if (env->cleanwin < env->nwindows - 1)
3186
        env->cleanwin++;
3187
    if (env->otherwin == 0)
3188
        env->cansave--;
3189
    else
3190
        env->otherwin--;
3191
}
3192

    
3193
target_ulong helper_rdccr(void)
3194
{
3195
    return GET_CCR(env);
3196
}
3197

    
3198
void helper_wrccr(target_ulong new_ccr)
3199
{
3200
    PUT_CCR(env, new_ccr);
3201
}
3202

    
3203
// CWP handling is reversed in V9, but we still use the V8 register
3204
// order.
3205
target_ulong helper_rdcwp(void)
3206
{
3207
    return GET_CWP64(env);
3208
}
3209

    
3210
void helper_wrcwp(target_ulong new_cwp)
3211
{
3212
    PUT_CWP64(env, new_cwp);
3213
}
3214

    
3215
// This function uses non-native bit order
3216
#define GET_FIELD(X, FROM, TO)                                  \
3217
    ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
3218

    
3219
// This function uses the order in the manuals, i.e. bit 0 is 2^0
3220
#define GET_FIELD_SP(X, FROM, TO)               \
3221
    GET_FIELD(X, 63 - (TO), 63 - (FROM))
3222

    
3223
target_ulong helper_array8(target_ulong pixel_addr, target_ulong cubesize)
3224
{
3225
    return (GET_FIELD_SP(pixel_addr, 60, 63) << (17 + 2 * cubesize)) |
3226
        (GET_FIELD_SP(pixel_addr, 39, 39 + cubesize - 1) << (17 + cubesize)) |
3227
        (GET_FIELD_SP(pixel_addr, 17 + cubesize - 1, 17) << 17) |
3228
        (GET_FIELD_SP(pixel_addr, 56, 59) << 13) |
3229
        (GET_FIELD_SP(pixel_addr, 35, 38) << 9) |
3230
        (GET_FIELD_SP(pixel_addr, 13, 16) << 5) |
3231
        (((pixel_addr >> 55) & 1) << 4) |
3232
        (GET_FIELD_SP(pixel_addr, 33, 34) << 2) |
3233
        GET_FIELD_SP(pixel_addr, 11, 12);
3234
}
3235

    
3236
target_ulong helper_alignaddr(target_ulong addr, target_ulong offset)
3237
{
3238
    uint64_t tmp;
3239

    
3240
    tmp = addr + offset;
3241
    env->gsr &= ~7ULL;
3242
    env->gsr |= tmp & 7ULL;
3243
    return tmp & ~7ULL;
3244
}
3245

    
3246
target_ulong helper_popc(target_ulong val)
3247
{
3248
    return ctpop64(val);
3249
}
3250

    
3251
static inline uint64_t *get_gregset(uint32_t pstate)
3252
{
3253
    switch (pstate) {
3254
    default:
3255
        DPRINTF_PSTATE("ERROR in get_gregset: active pstate bits=%x%s%s%s\n",
3256
                pstate,
3257
                (pstate & PS_IG) ? " IG" : "",
3258
                (pstate & PS_MG) ? " MG" : "",
3259
                (pstate & PS_AG) ? " AG" : "");
3260
        /* pass through to normal set of global registers */
3261
    case 0:
3262
        return env->bgregs;
3263
    case PS_AG:
3264
        return env->agregs;
3265
    case PS_MG:
3266
        return env->mgregs;
3267
    case PS_IG:
3268
        return env->igregs;
3269
    }
3270
}
3271

    
3272
static inline void change_pstate(uint32_t new_pstate)
3273
{
3274
    uint32_t pstate_regs, new_pstate_regs;
3275
    uint64_t *src, *dst;
3276

    
3277
    if (env->def->features & CPU_FEATURE_GL) {
3278
        // PS_AG is not implemented in this case
3279
        new_pstate &= ~PS_AG;
3280
    }
3281

    
3282
    pstate_regs = env->pstate & 0xc01;
3283
    new_pstate_regs = new_pstate & 0xc01;
3284

    
3285
    if (new_pstate_regs != pstate_regs) {
3286
        DPRINTF_PSTATE("change_pstate: switching regs old=%x new=%x\n",
3287
                       pstate_regs, new_pstate_regs);
3288
        // Switch global register bank
3289
        src = get_gregset(new_pstate_regs);
3290
        dst = get_gregset(pstate_regs);
3291
        memcpy32(dst, env->gregs);
3292
        memcpy32(env->gregs, src);
3293
    }
3294
    else {
3295
        DPRINTF_PSTATE("change_pstate: regs new=%x (unchanged)\n",
3296
                       new_pstate_regs);
3297
    }
3298
    env->pstate = new_pstate;
3299
}
3300

    
3301
void helper_wrpstate(target_ulong new_state)
3302
{
3303
    change_pstate(new_state & 0xf3f);
3304

    
3305
#if !defined(CONFIG_USER_ONLY)
3306
    if (cpu_interrupts_enabled(env)) {
3307
        cpu_check_irqs(env);
3308
    }
3309
#endif
3310
}
3311

    
3312
void helper_wrpil(target_ulong new_pil)
3313
{
3314
#if !defined(CONFIG_USER_ONLY)
3315
    DPRINTF_PSTATE("helper_wrpil old=%x new=%x\n",
3316
                   env->psrpil, (uint32_t)new_pil);
3317

    
3318
    env->psrpil = new_pil;
3319

    
3320
    if (cpu_interrupts_enabled(env)) {
3321
        cpu_check_irqs(env);
3322
    }
3323
#endif
3324
}
3325

    
3326
void helper_done(void)
3327
{
3328
    trap_state* tsptr = cpu_tsptr(env);
3329

    
3330
    env->pc = tsptr->tnpc;
3331
    env->npc = tsptr->tnpc + 4;
3332
    PUT_CCR(env, tsptr->tstate >> 32);
3333
    env->asi = (tsptr->tstate >> 24) & 0xff;
3334
    change_pstate((tsptr->tstate >> 8) & 0xf3f);
3335
    PUT_CWP64(env, tsptr->tstate & 0xff);
3336
    env->tl--;
3337

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

    
3340
#if !defined(CONFIG_USER_ONLY)
3341
    if (cpu_interrupts_enabled(env)) {
3342
        cpu_check_irqs(env);
3343
    }
3344
#endif
3345
}
3346

    
3347
void helper_retry(void)
3348
{
3349
    trap_state* tsptr = cpu_tsptr(env);
3350

    
3351
    env->pc = tsptr->tpc;
3352
    env->npc = tsptr->tnpc;
3353
    PUT_CCR(env, tsptr->tstate >> 32);
3354
    env->asi = (tsptr->tstate >> 24) & 0xff;
3355
    change_pstate((tsptr->tstate >> 8) & 0xf3f);
3356
    PUT_CWP64(env, tsptr->tstate & 0xff);
3357
    env->tl--;
3358

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

    
3361
#if !defined(CONFIG_USER_ONLY)
3362
    if (cpu_interrupts_enabled(env)) {
3363
        cpu_check_irqs(env);
3364
    }
3365
#endif
3366
}
3367

    
3368
static void do_modify_softint(const char* operation, uint32_t value)
3369
{
3370
    if (env->softint != value) {
3371
        env->softint = value;
3372
        DPRINTF_PSTATE(": %s new %08x\n", operation, env->softint);
3373
#if !defined(CONFIG_USER_ONLY)
3374
        if (cpu_interrupts_enabled(env)) {
3375
            cpu_check_irqs(env);
3376
        }
3377
#endif
3378
    }
3379
}
3380

    
3381
void helper_set_softint(uint64_t value)
3382
{
3383
    do_modify_softint("helper_set_softint", env->softint | (uint32_t)value);
3384
}
3385

    
3386
void helper_clear_softint(uint64_t value)
3387
{
3388
    do_modify_softint("helper_clear_softint", env->softint & (uint32_t)~value);
3389
}
3390

    
3391
void helper_write_softint(uint64_t value)
3392
{
3393
    do_modify_softint("helper_write_softint", (uint32_t)value);
3394
}
3395
#endif
3396

    
3397
void helper_flush(target_ulong addr)
3398
{
3399
    addr &= ~7;
3400
    tb_invalidate_page_range(addr, addr + 8);
3401
}
3402

    
3403
#ifdef TARGET_SPARC64
3404
#ifdef DEBUG_PCALL
3405
static const char * const excp_names[0x80] = {
3406
    [TT_TFAULT] = "Instruction Access Fault",
3407
    [TT_TMISS] = "Instruction Access MMU Miss",
3408
    [TT_CODE_ACCESS] = "Instruction Access Error",
3409
    [TT_ILL_INSN] = "Illegal Instruction",
3410
    [TT_PRIV_INSN] = "Privileged Instruction",
3411
    [TT_NFPU_INSN] = "FPU Disabled",
3412
    [TT_FP_EXCP] = "FPU Exception",
3413
    [TT_TOVF] = "Tag Overflow",
3414
    [TT_CLRWIN] = "Clean Windows",
3415
    [TT_DIV_ZERO] = "Division By Zero",
3416
    [TT_DFAULT] = "Data Access Fault",
3417
    [TT_DMISS] = "Data Access MMU Miss",
3418
    [TT_DATA_ACCESS] = "Data Access Error",
3419
    [TT_DPROT] = "Data Protection Error",
3420
    [TT_UNALIGNED] = "Unaligned Memory Access",
3421
    [TT_PRIV_ACT] = "Privileged Action",
3422
    [TT_EXTINT | 0x1] = "External Interrupt 1",
3423
    [TT_EXTINT | 0x2] = "External Interrupt 2",
3424
    [TT_EXTINT | 0x3] = "External Interrupt 3",
3425
    [TT_EXTINT | 0x4] = "External Interrupt 4",
3426
    [TT_EXTINT | 0x5] = "External Interrupt 5",
3427
    [TT_EXTINT | 0x6] = "External Interrupt 6",
3428
    [TT_EXTINT | 0x7] = "External Interrupt 7",
3429
    [TT_EXTINT | 0x8] = "External Interrupt 8",
3430
    [TT_EXTINT | 0x9] = "External Interrupt 9",
3431
    [TT_EXTINT | 0xa] = "External Interrupt 10",
3432
    [TT_EXTINT | 0xb] = "External Interrupt 11",
3433
    [TT_EXTINT | 0xc] = "External Interrupt 12",
3434
    [TT_EXTINT | 0xd] = "External Interrupt 13",
3435
    [TT_EXTINT | 0xe] = "External Interrupt 14",
3436
    [TT_EXTINT | 0xf] = "External Interrupt 15",
3437
};
3438
#endif
3439

    
3440
trap_state* cpu_tsptr(CPUState* env)
3441
{
3442
    return &env->ts[env->tl & MAXTL_MASK];
3443
}
3444

    
3445
void do_interrupt(CPUState *env)
3446
{
3447
    int intno = env->exception_index;
3448
    trap_state* tsptr;
3449

    
3450
#ifdef DEBUG_PCALL
3451
    if (qemu_loglevel_mask(CPU_LOG_INT)) {
3452
        static int count;
3453
        const char *name;
3454

    
3455
        if (intno < 0 || intno >= 0x180)
3456
            name = "Unknown";
3457
        else if (intno >= 0x100)
3458
            name = "Trap Instruction";
3459
        else if (intno >= 0xc0)
3460
            name = "Window Fill";
3461
        else if (intno >= 0x80)
3462
            name = "Window Spill";
3463
        else {
3464
            name = excp_names[intno];
3465
            if (!name)
3466
                name = "Unknown";
3467
        }
3468

    
3469
        qemu_log("%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
3470
                " SP=%016" PRIx64 "\n",
3471
                count, name, intno,
3472
                env->pc,
3473
                env->npc, env->regwptr[6]);
3474
        log_cpu_state(env, 0);
3475
#if 0
3476
        {
3477
            int i;
3478
            uint8_t *ptr;
3479

3480
            qemu_log("       code=");
3481
            ptr = (uint8_t *)env->pc;
3482
            for(i = 0; i < 16; i++) {
3483
                qemu_log(" %02x", ldub(ptr + i));
3484
            }
3485
            qemu_log("\n");
3486
        }
3487
#endif
3488
        count++;
3489
    }
3490
#endif
3491
#if !defined(CONFIG_USER_ONLY)
3492
    if (env->tl >= env->maxtl) {
3493
        cpu_abort(env, "Trap 0x%04x while trap level (%d) >= MAXTL (%d),"
3494
                  " Error state", env->exception_index, env->tl, env->maxtl);
3495
        return;
3496
    }
3497
#endif
3498
    if (env->tl < env->maxtl - 1) {
3499
        env->tl++;
3500
    } else {
3501
        env->pstate |= PS_RED;
3502
        if (env->tl < env->maxtl)
3503
            env->tl++;
3504
    }
3505
    tsptr = cpu_tsptr(env);
3506

    
3507
    tsptr->tstate = ((uint64_t)GET_CCR(env) << 32) |
3508
        ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
3509
        GET_CWP64(env);
3510
    tsptr->tpc = env->pc;
3511
    tsptr->tnpc = env->npc;
3512
    tsptr->tt = intno;
3513

    
3514
    switch (intno) {
3515
    case TT_IVEC:
3516
        change_pstate(PS_PEF | PS_PRIV | PS_IG);
3517
        break;
3518
    case TT_TFAULT:
3519
    case TT_DFAULT:
3520
    case TT_TMISS ... TT_TMISS + 3:
3521
    case TT_DMISS ... TT_DMISS + 3:
3522
    case TT_DPROT ... TT_DPROT + 3:
3523
        change_pstate(PS_PEF | PS_PRIV | PS_MG);
3524
        break;
3525
    default:
3526
        change_pstate(PS_PEF | PS_PRIV | PS_AG);
3527
        break;
3528
    }
3529

    
3530
    if (intno == TT_CLRWIN)
3531
        cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1));
3532
    else if ((intno & 0x1c0) == TT_SPILL)
3533
        cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2));
3534
    else if ((intno & 0x1c0) == TT_FILL)
3535
        cpu_set_cwp(env, cpu_cwp_inc(env, env->cwp + 1));
3536
    env->tbr &= ~0x7fffULL;
3537
    env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
3538
    env->pc = env->tbr;
3539
    env->npc = env->pc + 4;
3540
    env->exception_index = -1;
3541
}
3542
#else
3543
#ifdef DEBUG_PCALL
3544
static const char * const excp_names[0x80] = {
3545
    [TT_TFAULT] = "Instruction Access Fault",
3546
    [TT_ILL_INSN] = "Illegal Instruction",
3547
    [TT_PRIV_INSN] = "Privileged Instruction",
3548
    [TT_NFPU_INSN] = "FPU Disabled",
3549
    [TT_WIN_OVF] = "Window Overflow",
3550
    [TT_WIN_UNF] = "Window Underflow",
3551
    [TT_UNALIGNED] = "Unaligned Memory Access",
3552
    [TT_FP_EXCP] = "FPU Exception",
3553
    [TT_DFAULT] = "Data Access Fault",
3554
    [TT_TOVF] = "Tag Overflow",
3555
    [TT_EXTINT | 0x1] = "External Interrupt 1",
3556
    [TT_EXTINT | 0x2] = "External Interrupt 2",
3557
    [TT_EXTINT | 0x3] = "External Interrupt 3",
3558
    [TT_EXTINT | 0x4] = "External Interrupt 4",
3559
    [TT_EXTINT | 0x5] = "External Interrupt 5",
3560
    [TT_EXTINT | 0x6] = "External Interrupt 6",
3561
    [TT_EXTINT | 0x7] = "External Interrupt 7",
3562
    [TT_EXTINT | 0x8] = "External Interrupt 8",
3563
    [TT_EXTINT | 0x9] = "External Interrupt 9",
3564
    [TT_EXTINT | 0xa] = "External Interrupt 10",
3565
    [TT_EXTINT | 0xb] = "External Interrupt 11",
3566
    [TT_EXTINT | 0xc] = "External Interrupt 12",
3567
    [TT_EXTINT | 0xd] = "External Interrupt 13",
3568
    [TT_EXTINT | 0xe] = "External Interrupt 14",
3569
    [TT_EXTINT | 0xf] = "External Interrupt 15",
3570
    [TT_TOVF] = "Tag Overflow",
3571
    [TT_CODE_ACCESS] = "Instruction Access Error",
3572
    [TT_DATA_ACCESS] = "Data Access Error",
3573
    [TT_DIV_ZERO] = "Division By Zero",
3574
    [TT_NCP_INSN] = "Coprocessor Disabled",
3575
};
3576
#endif
3577

    
3578
void do_interrupt(CPUState *env)
3579
{
3580
    int cwp, intno = env->exception_index;
3581

    
3582
#ifdef DEBUG_PCALL
3583
    if (qemu_loglevel_mask(CPU_LOG_INT)) {
3584
        static int count;
3585
        const char *name;
3586

    
3587
        if (intno < 0 || intno >= 0x100)
3588
            name = "Unknown";
3589
        else if (intno >= 0x80)
3590
            name = "Trap Instruction";
3591
        else {
3592
            name = excp_names[intno];
3593
            if (!name)
3594
                name = "Unknown";
3595
        }
3596

    
3597
        qemu_log("%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
3598
                count, name, intno,
3599
                env->pc,
3600
                env->npc, env->regwptr[6]);
3601
        log_cpu_state(env, 0);
3602
#if 0
3603
        {
3604
            int i;
3605
            uint8_t *ptr;
3606

3607
            qemu_log("       code=");
3608
            ptr = (uint8_t *)env->pc;
3609
            for(i = 0; i < 16; i++) {
3610
                qemu_log(" %02x", ldub(ptr + i));
3611
            }
3612
            qemu_log("\n");
3613
        }
3614
#endif
3615
        count++;
3616
    }
3617
#endif
3618
#if !defined(CONFIG_USER_ONLY)
3619
    if (env->psret == 0) {
3620
        cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
3621
                  env->exception_index);
3622
        return;
3623
    }
3624
#endif
3625
    env->psret = 0;
3626
    cwp = cpu_cwp_dec(env, env->cwp - 1);
3627
    cpu_set_cwp(env, cwp);
3628
    env->regwptr[9] = env->pc;
3629
    env->regwptr[10] = env->npc;
3630
    env->psrps = env->psrs;
3631
    env->psrs = 1;
3632
    env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
3633
    env->pc = env->tbr;
3634
    env->npc = env->pc + 4;
3635
    env->exception_index = -1;
3636
}
3637
#endif
3638

    
3639
#if !defined(CONFIG_USER_ONLY)
3640

    
3641
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
3642
                                void *retaddr);
3643

    
3644
#define MMUSUFFIX _mmu
3645
#define ALIGNED_ONLY
3646

    
3647
#define SHIFT 0
3648
#include "softmmu_template.h"
3649

    
3650
#define SHIFT 1
3651
#include "softmmu_template.h"
3652

    
3653
#define SHIFT 2
3654
#include "softmmu_template.h"
3655

    
3656
#define SHIFT 3
3657
#include "softmmu_template.h"
3658

    
3659
/* XXX: make it generic ? */
3660
static void cpu_restore_state2(void *retaddr)
3661
{
3662
    TranslationBlock *tb;
3663
    unsigned long pc;
3664

    
3665
    if (retaddr) {
3666
        /* now we have a real cpu fault */
3667
        pc = (unsigned long)retaddr;
3668
        tb = tb_find_pc(pc);
3669
        if (tb) {
3670
            /* the PC is inside the translated code. It means that we have
3671
               a virtual CPU fault */
3672
            cpu_restore_state(tb, env, pc, (void *)(long)env->cond);
3673
        }
3674
    }
3675
}
3676

    
3677
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
3678
                                void *retaddr)
3679
{
3680
#ifdef DEBUG_UNALIGNED
3681
    printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
3682
           "\n", addr, env->pc);
3683
#endif
3684
    cpu_restore_state2(retaddr);
3685
    raise_exception(TT_UNALIGNED);
3686
}
3687

    
3688
/* try to fill the TLB and return an exception if error. If retaddr is
3689
   NULL, it means that the function was called in C code (i.e. not
3690
   from generated code or from helper.c) */
3691
/* XXX: fix it to restore all registers */
3692
void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
3693
{
3694
    int ret;
3695
    CPUState *saved_env;
3696

    
3697
    /* XXX: hack to restore env in all cases, even if not called from
3698
       generated code */
3699
    saved_env = env;
3700
    env = cpu_single_env;
3701

    
3702
    ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
3703
    if (ret) {
3704
        cpu_restore_state2(retaddr);
3705
        cpu_loop_exit();
3706
    }
3707
    env = saved_env;
3708
}
3709

    
3710
#endif
3711

    
3712
#ifndef TARGET_SPARC64
3713
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
3714
                          int is_asi, int size)
3715
{
3716
    CPUState *saved_env;
3717

    
3718
    /* XXX: hack to restore env in all cases, even if not called from
3719
       generated code */
3720
    saved_env = env;
3721
    env = cpu_single_env;
3722
#ifdef DEBUG_UNASSIGNED
3723
    if (is_asi)
3724
        printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
3725
               " asi 0x%02x from " TARGET_FMT_lx "\n",
3726
               is_exec ? "exec" : is_write ? "write" : "read", size,
3727
               size == 1 ? "" : "s", addr, is_asi, env->pc);
3728
    else
3729
        printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
3730
               " from " TARGET_FMT_lx "\n",
3731
               is_exec ? "exec" : is_write ? "write" : "read", size,
3732
               size == 1 ? "" : "s", addr, env->pc);
3733
#endif
3734
    if (env->mmuregs[3]) /* Fault status register */
3735
        env->mmuregs[3] = 1; /* overflow (not read before another fault) */
3736
    if (is_asi)
3737
        env->mmuregs[3] |= 1 << 16;
3738
    if (env->psrs)
3739
        env->mmuregs[3] |= 1 << 5;
3740
    if (is_exec)
3741
        env->mmuregs[3] |= 1 << 6;
3742
    if (is_write)
3743
        env->mmuregs[3] |= 1 << 7;
3744
    env->mmuregs[3] |= (5 << 2) | 2;
3745
    env->mmuregs[4] = addr; /* Fault address register */
3746
    if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
3747
        if (is_exec)
3748
            raise_exception(TT_CODE_ACCESS);
3749
        else
3750
            raise_exception(TT_DATA_ACCESS);
3751
    }
3752
    env = saved_env;
3753
}
3754
#else
3755
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
3756
                          int is_asi, int size)
3757
{
3758
    CPUState *saved_env;
3759

    
3760
    /* XXX: hack to restore env in all cases, even if not called from
3761
       generated code */
3762
    saved_env = env;
3763
    env = cpu_single_env;
3764

    
3765
#ifdef DEBUG_UNASSIGNED
3766
    printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx
3767
           "\n", addr, env->pc);
3768
#endif
3769

    
3770
    if (is_exec)
3771
        raise_exception(TT_CODE_ACCESS);
3772
    else
3773
        raise_exception(TT_DATA_ACCESS);
3774

    
3775
    env = saved_env;
3776
}
3777
#endif
3778

    
3779
#ifdef TARGET_SPARC64
3780
void helper_tick_set_count(void *opaque, uint64_t count)
3781
{
3782
#if !defined(CONFIG_USER_ONLY)
3783
    cpu_tick_set_count(opaque, count);
3784
#endif
3785
}
3786

    
3787
uint64_t helper_tick_get_count(void *opaque)
3788
{
3789
#if !defined(CONFIG_USER_ONLY)
3790
    return cpu_tick_get_count(opaque);
3791
#else
3792
    return 0;
3793
#endif
3794
}
3795

    
3796
void helper_tick_set_limit(void *opaque, uint64_t limit)
3797
{
3798
#if !defined(CONFIG_USER_ONLY)
3799
    cpu_tick_set_limit(opaque, limit);
3800
#endif
3801
}
3802
#endif