Statistics
| Branch: | Revision:

root / target-sparc / op_helper.c @ e2542fe2

History | View | Annotate | Download (102.2 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

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

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

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

    
34
#ifdef TARGET_SPARC64
35
#ifndef TARGET_ABI32
36
#define AM_CHECK(env1) ((env1)->pstate & PS_AM)
37
#else
38
#define AM_CHECK(env1) (1)
39
#endif
40
#endif
41

    
42
#if defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
43
// Calculates TSB pointer value for fault page size 8k or 64k
44
static uint64_t ultrasparc_tsb_pointer(uint64_t tsb_register,
45
                                       uint64_t tag_access_register,
46
                                       int page_size)
47
{
48
    uint64_t tsb_base = tsb_register & ~0x1fffULL;
49
    int tsb_split = (tsb_register & 0x1000ULL) ? 1 : 0;
50
    int tsb_size  = tsb_register & 0xf;
51

    
52
    // discard lower 13 bits which hold tag access context
53
    uint64_t tag_access_va = tag_access_register & ~0x1fffULL;
54

    
55
    // now reorder bits
56
    uint64_t tsb_base_mask = ~0x1fffULL;
57
    uint64_t va = tag_access_va;
58

    
59
    // move va bits to correct position
60
    if (page_size == 8*1024) {
61
        va >>= 9;
62
    } else if (page_size == 64*1024) {
63
        va >>= 12;
64
    }
65

    
66
    if (tsb_size) {
67
        tsb_base_mask <<= tsb_size;
68
    }
69

    
70
    // calculate tsb_base mask and adjust va if split is in use
71
    if (tsb_split) {
72
        if (page_size == 8*1024) {
73
            va &= ~(1ULL << (13 + tsb_size));
74
        } else if (page_size == 64*1024) {
75
            va |= (1ULL << (13 + tsb_size));
76
        }
77
        tsb_base_mask <<= 1;
78
    }
79

    
80
    return ((tsb_base & tsb_base_mask) | (va & ~tsb_base_mask)) & ~0xfULL;
81
}
82

    
83
// Calculates tag target register value by reordering bits
84
// in tag access register
85
static uint64_t ultrasparc_tag_target(uint64_t tag_access_register)
86
{
87
    return ((tag_access_register & 0x1fff) << 48) | (tag_access_register >> 22);
88
}
89

    
90
static void replace_tlb_entry(SparcTLBEntry *tlb,
91
                              uint64_t tlb_tag, uint64_t tlb_tte,
92
                              CPUState *env1)
93
{
94
    target_ulong mask, size, va, offset;
95

    
96
    // flush page range if translation is valid
97
    if (TTE_IS_VALID(tlb->tte)) {
98

    
99
        mask = 0xffffffffffffe000ULL;
100
        mask <<= 3 * ((tlb->tte >> 61) & 3);
101
        size = ~mask + 1;
102

    
103
        va = tlb->tag & mask;
104

    
105
        for (offset = 0; offset < size; offset += TARGET_PAGE_SIZE) {
106
            tlb_flush_page(env1, va + offset);
107
        }
108
    }
109

    
110
    tlb->tag = tlb_tag;
111
    tlb->tte = tlb_tte;
112
}
113

    
114
static void demap_tlb(SparcTLBEntry *tlb, target_ulong demap_addr,
115
                      const char* strmmu, CPUState *env1)
116
{
117
    unsigned int i;
118
    target_ulong mask;
119

    
120
    for (i = 0; i < 64; i++) {
121
        if (TTE_IS_VALID(tlb[i].tte)) {
122

    
123
            mask = 0xffffffffffffe000ULL;
124
            mask <<= 3 * ((tlb[i].tte >> 61) & 3);
125

    
126
            if ((demap_addr & mask) == (tlb[i].tag & mask)) {
127
                replace_tlb_entry(&tlb[i], 0, 0, env1);
128
#ifdef DEBUG_MMU
129
                DPRINTF_MMU("%s demap invalidated entry [%02u]\n", strmmu, i);
130
                dump_mmu(env1);
131
#endif
132
            }
133
            //return;
134
        }
135
    }
136

    
137
}
138

    
139
static void replace_tlb_1bit_lru(SparcTLBEntry *tlb,
140
                                 uint64_t tlb_tag, uint64_t tlb_tte,
141
                                 const char* strmmu, CPUState *env1)
142
{
143
    unsigned int i, replace_used;
144

    
145
    // Try replacing invalid entry
146
    for (i = 0; i < 64; i++) {
147
        if (!TTE_IS_VALID(tlb[i].tte)) {
148
            replace_tlb_entry(&tlb[i], tlb_tag, tlb_tte, env1);
149
#ifdef DEBUG_MMU
150
            DPRINTF_MMU("%s lru replaced invalid entry [%i]\n", strmmu, i);
151
            dump_mmu(env1);
152
#endif
153
            return;
154
        }
155
    }
156

    
157
    // All entries are valid, try replacing unlocked entry
158

    
159
    for (replace_used = 0; replace_used < 2; ++replace_used) {
160

    
161
        // Used entries are not replaced on first pass
162

    
163
        for (i = 0; i < 64; i++) {
164
            if (!TTE_IS_LOCKED(tlb[i].tte) && !TTE_IS_USED(tlb[i].tte)) {
165

    
166
                replace_tlb_entry(&tlb[i], tlb_tag, tlb_tte, env1);
167
#ifdef DEBUG_MMU
168
                DPRINTF_MMU("%s lru replaced unlocked %s entry [%i]\n",
169
                            strmmu, (replace_used?"used":"unused"), i);
170
                dump_mmu(env1);
171
#endif
172
                return;
173
            }
174
        }
175

    
176
        // Now reset used bit and search for unused entries again
177

    
178
        for (i = 0; i < 64; i++) {
179
            TTE_SET_UNUSED(tlb[i].tte);
180
        }
181
    }
182

    
183
#ifdef DEBUG_MMU
184
    DPRINTF_MMU("%s lru replacement failed: no entries available\n", strmmu);
185
#endif
186
    // error state?
187
}
188

    
189
#endif
190

    
191
static inline void address_mask(CPUState *env1, target_ulong *addr)
192
{
193
#ifdef TARGET_SPARC64
194
    if (AM_CHECK(env1))
195
        *addr &= 0xffffffffULL;
196
#endif
197
}
198

    
199
static void raise_exception(int tt)
200
{
201
    env->exception_index = tt;
202
    cpu_loop_exit();
203
}
204

    
205
void HELPER(raise_exception)(int tt)
206
{
207
    raise_exception(tt);
208
}
209

    
210
static inline void set_cwp(int new_cwp)
211
{
212
    cpu_set_cwp(env, new_cwp);
213
}
214

    
215
void helper_check_align(target_ulong addr, uint32_t align)
216
{
217
    if (addr & align) {
218
#ifdef DEBUG_UNALIGNED
219
    printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
220
           "\n", addr, env->pc);
221
#endif
222
        raise_exception(TT_UNALIGNED);
223
    }
224
}
225

    
226
#define F_HELPER(name, p) void helper_f##name##p(void)
227

    
228
#define F_BINOP(name)                                           \
229
    float32 helper_f ## name ## s (float32 src1, float32 src2)  \
230
    {                                                           \
231
        return float32_ ## name (src1, src2, &env->fp_status);  \
232
    }                                                           \
233
    F_HELPER(name, d)                                           \
234
    {                                                           \
235
        DT0 = float64_ ## name (DT0, DT1, &env->fp_status);     \
236
    }                                                           \
237
    F_HELPER(name, q)                                           \
238
    {                                                           \
239
        QT0 = float128_ ## name (QT0, QT1, &env->fp_status);    \
240
    }
241

    
242
F_BINOP(add);
243
F_BINOP(sub);
244
F_BINOP(mul);
245
F_BINOP(div);
246
#undef F_BINOP
247

    
248
void helper_fsmuld(float32 src1, float32 src2)
249
{
250
    DT0 = float64_mul(float32_to_float64(src1, &env->fp_status),
251
                      float32_to_float64(src2, &env->fp_status),
252
                      &env->fp_status);
253
}
254

    
255
void helper_fdmulq(void)
256
{
257
    QT0 = float128_mul(float64_to_float128(DT0, &env->fp_status),
258
                       float64_to_float128(DT1, &env->fp_status),
259
                       &env->fp_status);
260
}
261

    
262
float32 helper_fnegs(float32 src)
263
{
264
    return float32_chs(src);
265
}
266

    
267
#ifdef TARGET_SPARC64
268
F_HELPER(neg, d)
269
{
270
    DT0 = float64_chs(DT1);
271
}
272

    
273
F_HELPER(neg, q)
274
{
275
    QT0 = float128_chs(QT1);
276
}
277
#endif
278

    
279
/* Integer to float conversion.  */
280
float32 helper_fitos(int32_t src)
281
{
282
    return int32_to_float32(src, &env->fp_status);
283
}
284

    
285
void helper_fitod(int32_t src)
286
{
287
    DT0 = int32_to_float64(src, &env->fp_status);
288
}
289

    
290
void helper_fitoq(int32_t src)
291
{
292
    QT0 = int32_to_float128(src, &env->fp_status);
293
}
294

    
295
#ifdef TARGET_SPARC64
296
float32 helper_fxtos(void)
297
{
298
    return int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
299
}
300

    
301
F_HELPER(xto, d)
302
{
303
    DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
304
}
305

    
306
F_HELPER(xto, q)
307
{
308
    QT0 = int64_to_float128(*((int64_t *)&DT1), &env->fp_status);
309
}
310
#endif
311
#undef F_HELPER
312

    
313
/* floating point conversion */
314
float32 helper_fdtos(void)
315
{
316
    return float64_to_float32(DT1, &env->fp_status);
317
}
318

    
319
void helper_fstod(float32 src)
320
{
321
    DT0 = float32_to_float64(src, &env->fp_status);
322
}
323

    
324
float32 helper_fqtos(void)
325
{
326
    return float128_to_float32(QT1, &env->fp_status);
327
}
328

    
329
void helper_fstoq(float32 src)
330
{
331
    QT0 = float32_to_float128(src, &env->fp_status);
332
}
333

    
334
void helper_fqtod(void)
335
{
336
    DT0 = float128_to_float64(QT1, &env->fp_status);
337
}
338

    
339
void helper_fdtoq(void)
340
{
341
    QT0 = float64_to_float128(DT1, &env->fp_status);
342
}
343

    
344
/* Float to integer conversion.  */
345
int32_t helper_fstoi(float32 src)
346
{
347
    return float32_to_int32_round_to_zero(src, &env->fp_status);
348
}
349

    
350
int32_t helper_fdtoi(void)
351
{
352
    return float64_to_int32_round_to_zero(DT1, &env->fp_status);
353
}
354

    
355
int32_t helper_fqtoi(void)
356
{
357
    return float128_to_int32_round_to_zero(QT1, &env->fp_status);
358
}
359

    
360
#ifdef TARGET_SPARC64
361
void helper_fstox(float32 src)
362
{
363
    *((int64_t *)&DT0) = float32_to_int64_round_to_zero(src, &env->fp_status);
364
}
365

    
366
void helper_fdtox(void)
367
{
368
    *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status);
369
}
370

    
371
void helper_fqtox(void)
372
{
373
    *((int64_t *)&DT0) = float128_to_int64_round_to_zero(QT1, &env->fp_status);
374
}
375

    
376
void helper_faligndata(void)
377
{
378
    uint64_t tmp;
379

    
380
    tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8);
381
    /* on many architectures a shift of 64 does nothing */
382
    if ((env->gsr & 7) != 0) {
383
        tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8);
384
    }
385
    *((uint64_t *)&DT0) = tmp;
386
}
387

    
388
#ifdef HOST_WORDS_BIGENDIAN
389
#define VIS_B64(n) b[7 - (n)]
390
#define VIS_W64(n) w[3 - (n)]
391
#define VIS_SW64(n) sw[3 - (n)]
392
#define VIS_L64(n) l[1 - (n)]
393
#define VIS_B32(n) b[3 - (n)]
394
#define VIS_W32(n) w[1 - (n)]
395
#else
396
#define VIS_B64(n) b[n]
397
#define VIS_W64(n) w[n]
398
#define VIS_SW64(n) sw[n]
399
#define VIS_L64(n) l[n]
400
#define VIS_B32(n) b[n]
401
#define VIS_W32(n) w[n]
402
#endif
403

    
404
typedef union {
405
    uint8_t b[8];
406
    uint16_t w[4];
407
    int16_t sw[4];
408
    uint32_t l[2];
409
    float64 d;
410
} vis64;
411

    
412
typedef union {
413
    uint8_t b[4];
414
    uint16_t w[2];
415
    uint32_t l;
416
    float32 f;
417
} vis32;
418

    
419
void helper_fpmerge(void)
420
{
421
    vis64 s, d;
422

    
423
    s.d = DT0;
424
    d.d = DT1;
425

    
426
    // Reverse calculation order to handle overlap
427
    d.VIS_B64(7) = s.VIS_B64(3);
428
    d.VIS_B64(6) = d.VIS_B64(3);
429
    d.VIS_B64(5) = s.VIS_B64(2);
430
    d.VIS_B64(4) = d.VIS_B64(2);
431
    d.VIS_B64(3) = s.VIS_B64(1);
432
    d.VIS_B64(2) = d.VIS_B64(1);
433
    d.VIS_B64(1) = s.VIS_B64(0);
434
    //d.VIS_B64(0) = d.VIS_B64(0);
435

    
436
    DT0 = d.d;
437
}
438

    
439
void helper_fmul8x16(void)
440
{
441
    vis64 s, d;
442
    uint32_t tmp;
443

    
444
    s.d = DT0;
445
    d.d = DT1;
446

    
447
#define PMUL(r)                                                 \
448
    tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r);       \
449
    if ((tmp & 0xff) > 0x7f)                                    \
450
        tmp += 0x100;                                           \
451
    d.VIS_W64(r) = tmp >> 8;
452

    
453
    PMUL(0);
454
    PMUL(1);
455
    PMUL(2);
456
    PMUL(3);
457
#undef PMUL
458

    
459
    DT0 = d.d;
460
}
461

    
462
void helper_fmul8x16al(void)
463
{
464
    vis64 s, d;
465
    uint32_t tmp;
466

    
467
    s.d = DT0;
468
    d.d = DT1;
469

    
470
#define PMUL(r)                                                 \
471
    tmp = (int32_t)d.VIS_SW64(1) * (int32_t)s.VIS_B64(r);       \
472
    if ((tmp & 0xff) > 0x7f)                                    \
473
        tmp += 0x100;                                           \
474
    d.VIS_W64(r) = tmp >> 8;
475

    
476
    PMUL(0);
477
    PMUL(1);
478
    PMUL(2);
479
    PMUL(3);
480
#undef PMUL
481

    
482
    DT0 = d.d;
483
}
484

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

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

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

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

    
505
    DT0 = d.d;
506
}
507

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

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

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

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

    
528
    DT0 = d.d;
529
}
530

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

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

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

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

    
551
    DT0 = d.d;
552
}
553

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

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

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

    
568
    // Reverse calculation order to handle overlap
569
    PMUL(1);
570
    PMUL(0);
571
#undef PMUL
572

    
573
    DT0 = d.d;
574
}
575

    
576
void helper_fmuld8ulx16(void)
577
{
578
    vis64 s, d;
579
    uint32_t tmp;
580

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

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

    
590
    // Reverse calculation order to handle overlap
591
    PMUL(1);
592
    PMUL(0);
593
#undef PMUL
594

    
595
    DT0 = d.d;
596
}
597

    
598
void helper_fexpand(void)
599
{
600
    vis32 s;
601
    vis64 d;
602

    
603
    s.l = (uint32_t)(*(uint64_t *)&DT0 & 0xffffffff);
604
    d.d = DT1;
605
    d.VIS_W64(0) = s.VIS_B32(0) << 4;
606
    d.VIS_W64(1) = s.VIS_B32(1) << 4;
607
    d.VIS_W64(2) = s.VIS_B32(2) << 4;
608
    d.VIS_W64(3) = s.VIS_B32(3) << 4;
609

    
610
    DT0 = d.d;
611
}
612

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

    
667
#define FADD(a, b) ((a) + (b))
668
#define FSUB(a, b) ((a) - (b))
669
VIS_HELPER(helper_fpadd, FADD)
670
VIS_HELPER(helper_fpsub, FSUB)
671

    
672
#define VIS_CMPHELPER(name, F)                                        \
673
    void name##16(void)                                           \
674
    {                                                             \
675
        vis64 s, d;                                               \
676
                                                                  \
677
        s.d = DT0;                                                \
678
        d.d = DT1;                                                \
679
                                                                  \
680
        d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0))? 1: 0;       \
681
        d.VIS_W64(0) |= F(d.VIS_W64(1), s.VIS_W64(1))? 2: 0;      \
682
        d.VIS_W64(0) |= F(d.VIS_W64(2), s.VIS_W64(2))? 4: 0;      \
683
        d.VIS_W64(0) |= F(d.VIS_W64(3), s.VIS_W64(3))? 8: 0;      \
684
                                                                  \
685
        DT0 = d.d;                                                \
686
    }                                                             \
687
                                                                  \
688
    void name##32(void)                                           \
689
    {                                                             \
690
        vis64 s, d;                                               \
691
                                                                  \
692
        s.d = DT0;                                                \
693
        d.d = DT1;                                                \
694
                                                                  \
695
        d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0))? 1: 0;       \
696
        d.VIS_L64(0) |= F(d.VIS_L64(1), s.VIS_L64(1))? 2: 0;      \
697
                                                                  \
698
        DT0 = d.d;                                                \
699
    }
700

    
701
#define FCMPGT(a, b) ((a) > (b))
702
#define FCMPEQ(a, b) ((a) == (b))
703
#define FCMPLE(a, b) ((a) <= (b))
704
#define FCMPNE(a, b) ((a) != (b))
705

    
706
VIS_CMPHELPER(helper_fcmpgt, FCMPGT)
707
VIS_CMPHELPER(helper_fcmpeq, FCMPEQ)
708
VIS_CMPHELPER(helper_fcmple, FCMPLE)
709
VIS_CMPHELPER(helper_fcmpne, FCMPNE)
710
#endif
711

    
712
void helper_check_ieee_exceptions(void)
713
{
714
    target_ulong status;
715

    
716
    status = get_float_exception_flags(&env->fp_status);
717
    if (status) {
718
        /* Copy IEEE 754 flags into FSR */
719
        if (status & float_flag_invalid)
720
            env->fsr |= FSR_NVC;
721
        if (status & float_flag_overflow)
722
            env->fsr |= FSR_OFC;
723
        if (status & float_flag_underflow)
724
            env->fsr |= FSR_UFC;
725
        if (status & float_flag_divbyzero)
726
            env->fsr |= FSR_DZC;
727
        if (status & float_flag_inexact)
728
            env->fsr |= FSR_NXC;
729

    
730
        if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) {
731
            /* Unmasked exception, generate a trap */
732
            env->fsr |= FSR_FTT_IEEE_EXCP;
733
            raise_exception(TT_FP_EXCP);
734
        } else {
735
            /* Accumulate exceptions */
736
            env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
737
        }
738
    }
739
}
740

    
741
void helper_clear_float_exceptions(void)
742
{
743
    set_float_exception_flags(0, &env->fp_status);
744
}
745

    
746
float32 helper_fabss(float32 src)
747
{
748
    return float32_abs(src);
749
}
750

    
751
#ifdef TARGET_SPARC64
752
void helper_fabsd(void)
753
{
754
    DT0 = float64_abs(DT1);
755
}
756

    
757
void helper_fabsq(void)
758
{
759
    QT0 = float128_abs(QT1);
760
}
761
#endif
762

    
763
float32 helper_fsqrts(float32 src)
764
{
765
    return float32_sqrt(src, &env->fp_status);
766
}
767

    
768
void helper_fsqrtd(void)
769
{
770
    DT0 = float64_sqrt(DT1, &env->fp_status);
771
}
772

    
773
void helper_fsqrtq(void)
774
{
775
    QT0 = float128_sqrt(QT1, &env->fp_status);
776
}
777

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

    
839
GEN_FCMPS(fcmps, float32, 0, 0);
840
GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
841

    
842
GEN_FCMPS(fcmpes, float32, 0, 1);
843
GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
844

    
845
GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0);
846
GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1);
847

    
848
static uint32_t compute_all_flags(void)
849
{
850
    return env->psr & PSR_ICC;
851
}
852

    
853
static uint32_t compute_C_flags(void)
854
{
855
    return env->psr & PSR_CARRY;
856
}
857

    
858
static inline uint32_t get_NZ_icc(target_ulong dst)
859
{
860
    uint32_t ret = 0;
861

    
862
    if (!(dst & 0xffffffffULL))
863
        ret |= PSR_ZERO;
864
    if ((int32_t) (dst & 0xffffffffULL) < 0)
865
        ret |= PSR_NEG;
866
    return ret;
867
}
868

    
869
#ifdef TARGET_SPARC64
870
static uint32_t compute_all_flags_xcc(void)
871
{
872
    return env->xcc & PSR_ICC;
873
}
874

    
875
static uint32_t compute_C_flags_xcc(void)
876
{
877
    return env->xcc & PSR_CARRY;
878
}
879

    
880
static inline uint32_t get_NZ_xcc(target_ulong dst)
881
{
882
    uint32_t ret = 0;
883

    
884
    if (!dst)
885
        ret |= PSR_ZERO;
886
    if ((int64_t)dst < 0)
887
        ret |= PSR_NEG;
888
    return ret;
889
}
890
#endif
891

    
892
static inline uint32_t get_V_div_icc(target_ulong src2)
893
{
894
    uint32_t ret = 0;
895

    
896
    if (src2 != 0)
897
        ret |= PSR_OVF;
898
    return ret;
899
}
900

    
901
static uint32_t compute_all_div(void)
902
{
903
    uint32_t ret;
904

    
905
    ret = get_NZ_icc(CC_DST);
906
    ret |= get_V_div_icc(CC_SRC2);
907
    return ret;
908
}
909

    
910
static uint32_t compute_C_div(void)
911
{
912
    return 0;
913
}
914

    
915
static inline uint32_t get_C_add_icc(target_ulong dst, target_ulong src1)
916
{
917
    uint32_t ret = 0;
918

    
919
    if ((dst & 0xffffffffULL) < (src1 & 0xffffffffULL))
920
        ret |= PSR_CARRY;
921
    return ret;
922
}
923

    
924
static inline uint32_t get_V_add_icc(target_ulong dst, target_ulong src1,
925
                                         target_ulong src2)
926
{
927
    uint32_t ret = 0;
928

    
929
    if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1ULL << 31))
930
        ret |= PSR_OVF;
931
    return ret;
932
}
933

    
934
static uint32_t compute_all_add(void)
935
{
936
    uint32_t ret;
937

    
938
    ret = get_NZ_icc(CC_DST);
939
    ret |= get_C_add_icc(CC_DST, CC_SRC);
940
    ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
941
    return ret;
942
}
943

    
944
static uint32_t compute_C_add(void)
945
{
946
    return get_C_add_icc(CC_DST, CC_SRC);
947
}
948

    
949
#ifdef TARGET_SPARC64
950
static inline uint32_t get_C_add_xcc(target_ulong dst, target_ulong src1)
951
{
952
    uint32_t ret = 0;
953

    
954
    if (dst < src1)
955
        ret |= PSR_CARRY;
956
    return ret;
957
}
958

    
959
static inline uint32_t get_V_add_xcc(target_ulong dst, target_ulong src1,
960
                                         target_ulong src2)
961
{
962
    uint32_t ret = 0;
963

    
964
    if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1ULL << 63))
965
        ret |= PSR_OVF;
966
    return ret;
967
}
968

    
969
static uint32_t compute_all_add_xcc(void)
970
{
971
    uint32_t ret;
972

    
973
    ret = get_NZ_xcc(CC_DST);
974
    ret |= get_C_add_xcc(CC_DST, CC_SRC);
975
    ret |= get_V_add_xcc(CC_DST, CC_SRC, CC_SRC2);
976
    return ret;
977
}
978

    
979
static uint32_t compute_C_add_xcc(void)
980
{
981
    return get_C_add_xcc(CC_DST, CC_SRC);
982
}
983
#endif
984

    
985
static uint32_t compute_all_addx(void)
986
{
987
    uint32_t ret;
988

    
989
    ret = get_NZ_icc(CC_DST);
990
    ret |= get_C_add_icc(CC_DST - CC_SRC2, CC_SRC);
991
    ret |= get_C_add_icc(CC_DST, CC_SRC);
992
    ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
993
    return ret;
994
}
995

    
996
static uint32_t compute_C_addx(void)
997
{
998
    uint32_t ret;
999

    
1000
    ret = get_C_add_icc(CC_DST - CC_SRC2, CC_SRC);
1001
    ret |= get_C_add_icc(CC_DST, CC_SRC);
1002
    return ret;
1003
}
1004

    
1005
#ifdef TARGET_SPARC64
1006
static uint32_t compute_all_addx_xcc(void)
1007
{
1008
    uint32_t ret;
1009

    
1010
    ret = get_NZ_xcc(CC_DST);
1011
    ret |= get_C_add_xcc(CC_DST - CC_SRC2, CC_SRC);
1012
    ret |= get_C_add_xcc(CC_DST, CC_SRC);
1013
    ret |= get_V_add_xcc(CC_DST, CC_SRC, CC_SRC2);
1014
    return ret;
1015
}
1016

    
1017
static uint32_t compute_C_addx_xcc(void)
1018
{
1019
    uint32_t ret;
1020

    
1021
    ret = get_C_add_xcc(CC_DST - CC_SRC2, CC_SRC);
1022
    ret |= get_C_add_xcc(CC_DST, CC_SRC);
1023
    return ret;
1024
}
1025
#endif
1026

    
1027
static inline uint32_t get_V_tag_icc(target_ulong src1, target_ulong src2)
1028
{
1029
    uint32_t ret = 0;
1030

    
1031
    if ((src1 | src2) & 0x3)
1032
        ret |= PSR_OVF;
1033
    return ret;
1034
}
1035

    
1036
static uint32_t compute_all_tadd(void)
1037
{
1038
    uint32_t ret;
1039

    
1040
    ret = get_NZ_icc(CC_DST);
1041
    ret |= get_C_add_icc(CC_DST, CC_SRC);
1042
    ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
1043
    ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
1044
    return ret;
1045
}
1046

    
1047
static uint32_t compute_C_tadd(void)
1048
{
1049
    return get_C_add_icc(CC_DST, CC_SRC);
1050
}
1051

    
1052
static uint32_t compute_all_taddtv(void)
1053
{
1054
    uint32_t ret;
1055

    
1056
    ret = get_NZ_icc(CC_DST);
1057
    ret |= get_C_add_icc(CC_DST, CC_SRC);
1058
    return ret;
1059
}
1060

    
1061
static uint32_t compute_C_taddtv(void)
1062
{
1063
    return get_C_add_icc(CC_DST, CC_SRC);
1064
}
1065

    
1066
static inline uint32_t get_C_sub_icc(target_ulong src1, target_ulong src2)
1067
{
1068
    uint32_t ret = 0;
1069

    
1070
    if ((src1 & 0xffffffffULL) < (src2 & 0xffffffffULL))
1071
        ret |= PSR_CARRY;
1072
    return ret;
1073
}
1074

    
1075
static inline uint32_t get_V_sub_icc(target_ulong dst, target_ulong src1,
1076
                                     target_ulong src2)
1077
{
1078
    uint32_t ret = 0;
1079

    
1080
    if (((src1 ^ src2) & (src1 ^ dst)) & (1ULL << 31))
1081
        ret |= PSR_OVF;
1082
    return ret;
1083
}
1084

    
1085
static uint32_t compute_all_sub(void)
1086
{
1087
    uint32_t ret;
1088

    
1089
    ret = get_NZ_icc(CC_DST);
1090
    ret |= get_C_sub_icc(CC_SRC, CC_SRC2);
1091
    ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1092
    return ret;
1093
}
1094

    
1095
static uint32_t compute_C_sub(void)
1096
{
1097
    return get_C_sub_icc(CC_SRC, CC_SRC2);
1098
}
1099

    
1100
#ifdef TARGET_SPARC64
1101
static inline uint32_t get_C_sub_xcc(target_ulong src1, target_ulong src2)
1102
{
1103
    uint32_t ret = 0;
1104

    
1105
    if (src1 < src2)
1106
        ret |= PSR_CARRY;
1107
    return ret;
1108
}
1109

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

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

    
1120
static uint32_t compute_all_sub_xcc(void)
1121
{
1122
    uint32_t ret;
1123

    
1124
    ret = get_NZ_xcc(CC_DST);
1125
    ret |= get_C_sub_xcc(CC_SRC, CC_SRC2);
1126
    ret |= get_V_sub_xcc(CC_DST, CC_SRC, CC_SRC2);
1127
    return ret;
1128
}
1129

    
1130
static uint32_t compute_C_sub_xcc(void)
1131
{
1132
    return get_C_sub_xcc(CC_SRC, CC_SRC2);
1133
}
1134
#endif
1135

    
1136
static uint32_t compute_all_subx(void)
1137
{
1138
    uint32_t ret;
1139

    
1140
    ret = get_NZ_icc(CC_DST);
1141
    ret |= get_C_sub_icc(CC_DST - CC_SRC2, CC_SRC);
1142
    ret |= get_C_sub_icc(CC_DST, CC_SRC2);
1143
    ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1144
    return ret;
1145
}
1146

    
1147
static uint32_t compute_C_subx(void)
1148
{
1149
    uint32_t ret;
1150

    
1151
    ret = get_C_sub_icc(CC_DST - CC_SRC2, CC_SRC);
1152
    ret |= get_C_sub_icc(CC_DST, CC_SRC2);
1153
    return ret;
1154
}
1155

    
1156
#ifdef TARGET_SPARC64
1157
static uint32_t compute_all_subx_xcc(void)
1158
{
1159
    uint32_t ret;
1160

    
1161
    ret = get_NZ_xcc(CC_DST);
1162
    ret |= get_C_sub_xcc(CC_DST - CC_SRC2, CC_SRC);
1163
    ret |= get_C_sub_xcc(CC_DST, CC_SRC2);
1164
    ret |= get_V_sub_xcc(CC_DST, CC_SRC, CC_SRC2);
1165
    return ret;
1166
}
1167

    
1168
static uint32_t compute_C_subx_xcc(void)
1169
{
1170
    uint32_t ret;
1171

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

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

    
1182
    ret = get_NZ_icc(CC_DST);
1183
    ret |= get_C_sub_icc(CC_DST, CC_SRC);
1184
    ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1185
    ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
1186
    return ret;
1187
}
1188

    
1189
static uint32_t compute_C_tsub(void)
1190
{
1191
    return get_C_sub_icc(CC_DST, CC_SRC);
1192
}
1193

    
1194
static uint32_t compute_all_tsubtv(void)
1195
{
1196
    uint32_t ret;
1197

    
1198
    ret = get_NZ_icc(CC_DST);
1199
    ret |= get_C_sub_icc(CC_DST, CC_SRC);
1200
    return ret;
1201
}
1202

    
1203
static uint32_t compute_C_tsubtv(void)
1204
{
1205
    return get_C_sub_icc(CC_DST, CC_SRC);
1206
}
1207

    
1208
static uint32_t compute_all_logic(void)
1209
{
1210
    return get_NZ_icc(CC_DST);
1211
}
1212

    
1213
static uint32_t compute_C_logic(void)
1214
{
1215
    return 0;
1216
}
1217

    
1218
#ifdef TARGET_SPARC64
1219
static uint32_t compute_all_logic_xcc(void)
1220
{
1221
    return get_NZ_xcc(CC_DST);
1222
}
1223
#endif
1224

    
1225
typedef struct CCTable {
1226
    uint32_t (*compute_all)(void); /* return all the flags */
1227
    uint32_t (*compute_c)(void);  /* return the C flag */
1228
} CCTable;
1229

    
1230
static const CCTable icc_table[CC_OP_NB] = {
1231
    /* CC_OP_DYNAMIC should never happen */
1232
    [CC_OP_FLAGS] = { compute_all_flags, compute_C_flags },
1233
    [CC_OP_DIV] = { compute_all_div, compute_C_div },
1234
    [CC_OP_ADD] = { compute_all_add, compute_C_add },
1235
    [CC_OP_ADDX] = { compute_all_addx, compute_C_addx },
1236
    [CC_OP_TADD] = { compute_all_tadd, compute_C_tadd },
1237
    [CC_OP_TADDTV] = { compute_all_taddtv, compute_C_taddtv },
1238
    [CC_OP_SUB] = { compute_all_sub, compute_C_sub },
1239
    [CC_OP_SUBX] = { compute_all_subx, compute_C_subx },
1240
    [CC_OP_TSUB] = { compute_all_tsub, compute_C_tsub },
1241
    [CC_OP_TSUBTV] = { compute_all_tsubtv, compute_C_tsubtv },
1242
    [CC_OP_LOGIC] = { compute_all_logic, compute_C_logic },
1243
};
1244

    
1245
#ifdef TARGET_SPARC64
1246
static const CCTable xcc_table[CC_OP_NB] = {
1247
    /* CC_OP_DYNAMIC should never happen */
1248
    [CC_OP_FLAGS] = { compute_all_flags_xcc, compute_C_flags_xcc },
1249
    [CC_OP_DIV] = { compute_all_logic_xcc, compute_C_logic },
1250
    [CC_OP_ADD] = { compute_all_add_xcc, compute_C_add_xcc },
1251
    [CC_OP_ADDX] = { compute_all_addx_xcc, compute_C_addx_xcc },
1252
    [CC_OP_TADD] = { compute_all_add_xcc, compute_C_add_xcc },
1253
    [CC_OP_TADDTV] = { compute_all_add_xcc, compute_C_add_xcc },
1254
    [CC_OP_SUB] = { compute_all_sub_xcc, compute_C_sub_xcc },
1255
    [CC_OP_SUBX] = { compute_all_subx_xcc, compute_C_subx_xcc },
1256
    [CC_OP_TSUB] = { compute_all_sub_xcc, compute_C_sub_xcc },
1257
    [CC_OP_TSUBTV] = { compute_all_sub_xcc, compute_C_sub_xcc },
1258
    [CC_OP_LOGIC] = { compute_all_logic_xcc, compute_C_logic },
1259
};
1260
#endif
1261

    
1262
void helper_compute_psr(void)
1263
{
1264
    uint32_t new_psr;
1265

    
1266
    new_psr = icc_table[CC_OP].compute_all();
1267
    env->psr = new_psr;
1268
#ifdef TARGET_SPARC64
1269
    new_psr = xcc_table[CC_OP].compute_all();
1270
    env->xcc = new_psr;
1271
#endif
1272
    CC_OP = CC_OP_FLAGS;
1273
}
1274

    
1275
uint32_t helper_compute_C_icc(void)
1276
{
1277
    uint32_t ret;
1278

    
1279
    ret = icc_table[CC_OP].compute_c() >> PSR_CARRY_SHIFT;
1280
    return ret;
1281
}
1282

    
1283
#ifdef TARGET_SPARC64
1284
GEN_FCMPS(fcmps_fcc1, float32, 22, 0);
1285
GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
1286
GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0);
1287

    
1288
GEN_FCMPS(fcmps_fcc2, float32, 24, 0);
1289
GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
1290
GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0);
1291

    
1292
GEN_FCMPS(fcmps_fcc3, float32, 26, 0);
1293
GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
1294
GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0);
1295

    
1296
GEN_FCMPS(fcmpes_fcc1, float32, 22, 1);
1297
GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
1298
GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1);
1299

    
1300
GEN_FCMPS(fcmpes_fcc2, float32, 24, 1);
1301
GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
1302
GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1);
1303

    
1304
GEN_FCMPS(fcmpes_fcc3, float32, 26, 1);
1305
GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
1306
GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
1307
#endif
1308
#undef GEN_FCMPS
1309

    
1310
#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) && \
1311
    defined(DEBUG_MXCC)
1312
static void dump_mxcc(CPUState *env)
1313
{
1314
    printf("mxccdata: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64
1315
           "\n",
1316
           env->mxccdata[0], env->mxccdata[1],
1317
           env->mxccdata[2], env->mxccdata[3]);
1318
    printf("mxccregs: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64
1319
           "\n"
1320
           "          %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64
1321
           "\n",
1322
           env->mxccregs[0], env->mxccregs[1],
1323
           env->mxccregs[2], env->mxccregs[3],
1324
           env->mxccregs[4], env->mxccregs[5],
1325
           env->mxccregs[6], env->mxccregs[7]);
1326
}
1327
#endif
1328

    
1329
#if (defined(TARGET_SPARC64) || !defined(CONFIG_USER_ONLY)) \
1330
    && defined(DEBUG_ASI)
1331
static void dump_asi(const char *txt, target_ulong addr, int asi, int size,
1332
                     uint64_t r1)
1333
{
1334
    switch (size)
1335
    {
1336
    case 1:
1337
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %02" PRIx64 "\n", txt,
1338
                    addr, asi, r1 & 0xff);
1339
        break;
1340
    case 2:
1341
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %04" PRIx64 "\n", txt,
1342
                    addr, asi, r1 & 0xffff);
1343
        break;
1344
    case 4:
1345
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %08" PRIx64 "\n", txt,
1346
                    addr, asi, r1 & 0xffffffff);
1347
        break;
1348
    case 8:
1349
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %016" PRIx64 "\n", txt,
1350
                    addr, asi, r1);
1351
        break;
1352
    }
1353
}
1354
#endif
1355

    
1356
#ifndef TARGET_SPARC64
1357
#ifndef CONFIG_USER_ONLY
1358
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1359
{
1360
    uint64_t ret = 0;
1361
#if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
1362
    uint32_t last_addr = addr;
1363
#endif
1364

    
1365
    helper_check_align(addr, size - 1);
1366
    switch (asi) {
1367
    case 2: /* SuperSparc MXCC registers */
1368
        switch (addr) {
1369
        case 0x01c00a00: /* MXCC control register */
1370
            if (size == 8)
1371
                ret = env->mxccregs[3];
1372
            else
1373
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1374
                             size);
1375
            break;
1376
        case 0x01c00a04: /* MXCC control register */
1377
            if (size == 4)
1378
                ret = env->mxccregs[3];
1379
            else
1380
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1381
                             size);
1382
            break;
1383
        case 0x01c00c00: /* Module reset register */
1384
            if (size == 8) {
1385
                ret = env->mxccregs[5];
1386
                // should we do something here?
1387
            } else
1388
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1389
                             size);
1390
            break;
1391
        case 0x01c00f00: /* MBus port address register */
1392
            if (size == 8)
1393
                ret = env->mxccregs[7];
1394
            else
1395
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1396
                             size);
1397
            break;
1398
        default:
1399
            DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr,
1400
                         size);
1401
            break;
1402
        }
1403
        DPRINTF_MXCC("asi = %d, size = %d, sign = %d, "
1404
                     "addr = %08x -> ret = %" PRIx64 ","
1405
                     "addr = %08x\n", asi, size, sign, last_addr, ret, addr);
1406
#ifdef DEBUG_MXCC
1407
        dump_mxcc(env);
1408
#endif
1409
        break;
1410
    case 3: /* MMU probe */
1411
        {
1412
            int mmulev;
1413

    
1414
            mmulev = (addr >> 8) & 15;
1415
            if (mmulev > 4)
1416
                ret = 0;
1417
            else
1418
                ret = mmu_probe(env, addr, mmulev);
1419
            DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08" PRIx64 "\n",
1420
                        addr, mmulev, ret);
1421
        }
1422
        break;
1423
    case 4: /* read MMU regs */
1424
        {
1425
            int reg = (addr >> 8) & 0x1f;
1426

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

    
1545
            switch(reg) {
1546
            case 0: /* Breakpoint Value (Addr) */
1547
                ret = env->mmubpregs[reg];
1548
                break;
1549
            case 1: /* Breakpoint Mask */
1550
                ret = env->mmubpregs[reg];
1551
                break;
1552
            case 2: /* Breakpoint Control */
1553
                ret = env->mmubpregs[reg];
1554
                break;
1555
            case 3: /* Breakpoint Status */
1556
                ret = env->mmubpregs[reg];
1557
                env->mmubpregs[reg] = 0ULL;
1558
                break;
1559
            }
1560
            DPRINTF_MMU("read breakpoint reg[%d] 0x%016" PRIx64 "\n", reg,
1561
                        ret);
1562
        }
1563
        break;
1564
    case 8: /* User code access, XXX */
1565
    default:
1566
        do_unassigned_access(addr, 0, 0, asi, size);
1567
        ret = 0;
1568
        break;
1569
    }
1570
    if (sign) {
1571
        switch(size) {
1572
        case 1:
1573
            ret = (int8_t) ret;
1574
            break;
1575
        case 2:
1576
            ret = (int16_t) ret;
1577
            break;
1578
        case 4:
1579
            ret = (int32_t) ret;
1580
            break;
1581
        default:
1582
            break;
1583
        }
1584
    }
1585
#ifdef DEBUG_ASI
1586
    dump_asi("read ", last_addr, asi, size, ret);
1587
#endif
1588
    return ret;
1589
}
1590

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

    
1700
            mmulev = (addr >> 8) & 15;
1701
            DPRINTF_MMU("mmu flush level %d\n", mmulev);
1702
            switch (mmulev) {
1703
            case 0: // flush page
1704
                tlb_flush_page(env, addr & 0xfffff000);
1705
                break;
1706
            case 1: // flush segment (256k)
1707
            case 2: // flush region (16M)
1708
            case 3: // flush context (4G)
1709
            case 4: // flush entire
1710
                tlb_flush(env, 1);
1711
                break;
1712
            default:
1713
                break;
1714
            }
1715
#ifdef DEBUG_MMU
1716
            dump_mmu(env);
1717
#endif
1718
        }
1719
        break;
1720
    case 4: /* write MMU regs */
1721
        {
1722
            int reg = (addr >> 8) & 0x1f;
1723
            uint32_t oldreg;
1724

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

    
1828
            for (i = 0; i < 32; i += 4, src += 4, dst += 4) {
1829
                temp = ldl_kernel(src);
1830
                stl_kernel(dst, temp);
1831
            }
1832
        }
1833
        break;
1834
    case 0x1f: /* Block fill, stda access */
1835
        {
1836
            // addr = dst
1837
            // fill 32 bytes with val
1838
            unsigned int i;
1839
            uint32_t dst = addr & 7;
1840

    
1841
            for (i = 0; i < 32; i += 8, dst += 8)
1842
                stq_kernel(dst, val);
1843
        }
1844
        break;
1845
    case 0x20: /* MMU passthrough */
1846
        {
1847
            switch(size) {
1848
            case 1:
1849
                stb_phys(addr, val);
1850
                break;
1851
            case 2:
1852
                stw_phys(addr, val);
1853
                break;
1854
            case 4:
1855
            default:
1856
                stl_phys(addr, val);
1857
                break;
1858
            case 8:
1859
                stq_phys(addr, val);
1860
                break;
1861
            }
1862
        }
1863
        break;
1864
    case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
1865
        {
1866
            switch(size) {
1867
            case 1:
1868
                stb_phys((target_phys_addr_t)addr
1869
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1870
                break;
1871
            case 2:
1872
                stw_phys((target_phys_addr_t)addr
1873
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1874
                break;
1875
            case 4:
1876
            default:
1877
                stl_phys((target_phys_addr_t)addr
1878
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1879
                break;
1880
            case 8:
1881
                stq_phys((target_phys_addr_t)addr
1882
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1883
                break;
1884
            }
1885
        }
1886
        break;
1887
    case 0x30: // store buffer tags or Turbosparc secondary cache diagnostic
1888
    case 0x31: // store buffer data, Ross RT620 I-cache flush or
1889
               // Turbosparc snoop RAM
1890
    case 0x32: // store buffer control or Turbosparc page table
1891
               // descriptor diagnostic
1892
    case 0x36: /* I-cache flash clear */
1893
    case 0x37: /* D-cache flash clear */
1894
    case 0x4c: /* breakpoint action */
1895
        break;
1896
    case 0x38: /* SuperSPARC MMU Breakpoint Control Registers*/
1897
        {
1898
            int reg = (addr >> 8) & 3;
1899

    
1900
            switch(reg) {
1901
            case 0: /* Breakpoint Value (Addr) */
1902
                env->mmubpregs[reg] = (val & 0xfffffffffULL);
1903
                break;
1904
            case 1: /* Breakpoint Mask */
1905
                env->mmubpregs[reg] = (val & 0xfffffffffULL);
1906
                break;
1907
            case 2: /* Breakpoint Control */
1908
                env->mmubpregs[reg] = (val & 0x7fULL);
1909
                break;
1910
            case 3: /* Breakpoint Status */
1911
                env->mmubpregs[reg] = (val & 0xfULL);
1912
                break;
1913
            }
1914
            DPRINTF_MMU("write breakpoint reg[%d] 0x%016x\n", reg,
1915
                        env->mmuregs[reg]);
1916
        }
1917
        break;
1918
    case 8: /* User code access, XXX */
1919
    case 9: /* Supervisor code access, XXX */
1920
    default:
1921
        do_unassigned_access(addr, 1, 0, asi, size);
1922
        break;
1923
    }
1924
#ifdef DEBUG_ASI
1925
    dump_asi("write", addr, asi, size, val);
1926
#endif
1927
}
1928

    
1929
#endif /* CONFIG_USER_ONLY */
1930
#else /* TARGET_SPARC64 */
1931

    
1932
#ifdef CONFIG_USER_ONLY
1933
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1934
{
1935
    uint64_t ret = 0;
1936
#if defined(DEBUG_ASI)
1937
    target_ulong last_addr = addr;
1938
#endif
1939

    
1940
    if (asi < 0x80)
1941
        raise_exception(TT_PRIV_ACT);
1942

    
1943
    helper_check_align(addr, size - 1);
1944
    address_mask(env, &addr);
1945

    
1946
    switch (asi) {
1947
    case 0x82: // Primary no-fault
1948
    case 0x8a: // Primary no-fault LE
1949
        if (page_check_range(addr, size, PAGE_READ) == -1) {
1950
#ifdef DEBUG_ASI
1951
            dump_asi("read ", last_addr, asi, size, ret);
1952
#endif
1953
            return 0;
1954
        }
1955
        // Fall through
1956
    case 0x80: // Primary
1957
    case 0x88: // Primary LE
1958
        {
1959
            switch(size) {
1960
            case 1:
1961
                ret = ldub_raw(addr);
1962
                break;
1963
            case 2:
1964
                ret = lduw_raw(addr);
1965
                break;
1966
            case 4:
1967
                ret = ldl_raw(addr);
1968
                break;
1969
            default:
1970
            case 8:
1971
                ret = ldq_raw(addr);
1972
                break;
1973
            }
1974
        }
1975
        break;
1976
    case 0x83: // Secondary no-fault
1977
    case 0x8b: // Secondary no-fault LE
1978
        if (page_check_range(addr, size, PAGE_READ) == -1) {
1979
#ifdef DEBUG_ASI
1980
            dump_asi("read ", last_addr, asi, size, ret);
1981
#endif
1982
            return 0;
1983
        }
1984
        // Fall through
1985
    case 0x81: // Secondary
1986
    case 0x89: // Secondary LE
1987
        // XXX
1988
        break;
1989
    default:
1990
        break;
1991
    }
1992

    
1993
    /* Convert from little endian */
1994
    switch (asi) {
1995
    case 0x88: // Primary LE
1996
    case 0x89: // Secondary LE
1997
    case 0x8a: // Primary no-fault LE
1998
    case 0x8b: // Secondary no-fault LE
1999
        switch(size) {
2000
        case 2:
2001
            ret = bswap16(ret);
2002
            break;
2003
        case 4:
2004
            ret = bswap32(ret);
2005
            break;
2006
        case 8:
2007
            ret = bswap64(ret);
2008
            break;
2009
        default:
2010
            break;
2011
        }
2012
    default:
2013
        break;
2014
    }
2015

    
2016
    /* Convert to signed number */
2017
    if (sign) {
2018
        switch(size) {
2019
        case 1:
2020
            ret = (int8_t) ret;
2021
            break;
2022
        case 2:
2023
            ret = (int16_t) ret;
2024
            break;
2025
        case 4:
2026
            ret = (int32_t) ret;
2027
            break;
2028
        default:
2029
            break;
2030
        }
2031
    }
2032
#ifdef DEBUG_ASI
2033
    dump_asi("read ", last_addr, asi, size, ret);
2034
#endif
2035
    return ret;
2036
}
2037

    
2038
void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
2039
{
2040
#ifdef DEBUG_ASI
2041
    dump_asi("write", addr, asi, size, val);
2042
#endif
2043
    if (asi < 0x80)
2044
        raise_exception(TT_PRIV_ACT);
2045

    
2046
    helper_check_align(addr, size - 1);
2047
    address_mask(env, &addr);
2048

    
2049
    /* Convert to little endian */
2050
    switch (asi) {
2051
    case 0x88: // Primary LE
2052
    case 0x89: // Secondary LE
2053
        switch(size) {
2054
        case 2:
2055
            val = bswap16(val);
2056
            break;
2057
        case 4:
2058
            val = bswap32(val);
2059
            break;
2060
        case 8:
2061
            val = bswap64(val);
2062
            break;
2063
        default:
2064
            break;
2065
        }
2066
    default:
2067
        break;
2068
    }
2069

    
2070
    switch(asi) {
2071
    case 0x80: // Primary
2072
    case 0x88: // Primary LE
2073
        {
2074
            switch(size) {
2075
            case 1:
2076
                stb_raw(addr, val);
2077
                break;
2078
            case 2:
2079
                stw_raw(addr, val);
2080
                break;
2081
            case 4:
2082
                stl_raw(addr, val);
2083
                break;
2084
            case 8:
2085
            default:
2086
                stq_raw(addr, val);
2087
                break;
2088
            }
2089
        }
2090
        break;
2091
    case 0x81: // Secondary
2092
    case 0x89: // Secondary LE
2093
        // XXX
2094
        return;
2095

    
2096
    case 0x82: // Primary no-fault, RO
2097
    case 0x83: // Secondary no-fault, RO
2098
    case 0x8a: // Primary no-fault LE, RO
2099
    case 0x8b: // Secondary no-fault LE, RO
2100
    default:
2101
        do_unassigned_access(addr, 1, 0, 1, size);
2102
        return;
2103
    }
2104
}
2105

    
2106
#else /* CONFIG_USER_ONLY */
2107

    
2108
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
2109
{
2110
    uint64_t ret = 0;
2111
#if defined(DEBUG_ASI)
2112
    target_ulong last_addr = addr;
2113
#endif
2114

    
2115
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
2116
        || ((env->def->features & CPU_FEATURE_HYPV)
2117
            && asi >= 0x30 && asi < 0x80
2118
            && !(env->hpstate & HS_PRIV)))
2119
        raise_exception(TT_PRIV_ACT);
2120

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

    
2243
            if (reg == 0) {
2244
                // I-TSB Tag Target register
2245
                ret = ultrasparc_tag_target(env->immu.tag_access);
2246
            } else {
2247
                ret = env->immuregs[reg];
2248
            }
2249

    
2250
            break;
2251
        }
2252
    case 0x51: // I-MMU 8k TSB pointer
2253
        {
2254
            // env->immuregs[5] holds I-MMU TSB register value
2255
            // env->immuregs[6] holds I-MMU Tag Access register value
2256
            ret = ultrasparc_tsb_pointer(env->immu.tsb, env->immu.tag_access,
2257
                                         8*1024);
2258
            break;
2259
        }
2260
    case 0x52: // I-MMU 64k TSB pointer
2261
        {
2262
            // env->immuregs[5] holds I-MMU TSB register value
2263
            // env->immuregs[6] holds I-MMU Tag Access register value
2264
            ret = ultrasparc_tsb_pointer(env->immu.tsb, env->immu.tag_access,
2265
                                         64*1024);
2266
            break;
2267
        }
2268
    case 0x55: // I-MMU data access
2269
        {
2270
            int reg = (addr >> 3) & 0x3f;
2271

    
2272
            ret = env->itlb[reg].tte;
2273
            break;
2274
        }
2275
    case 0x56: // I-MMU tag read
2276
        {
2277
            int reg = (addr >> 3) & 0x3f;
2278

    
2279
            ret = env->itlb[reg].tag;
2280
            break;
2281
        }
2282
    case 0x58: // D-MMU regs
2283
        {
2284
            int reg = (addr >> 3) & 0xf;
2285

    
2286
            if (reg == 0) {
2287
                // D-TSB Tag Target register
2288
                ret = ultrasparc_tag_target(env->dmmu.tag_access);
2289
            } else {
2290
                ret = env->dmmuregs[reg];
2291
            }
2292
            break;
2293
        }
2294
    case 0x59: // D-MMU 8k TSB pointer
2295
        {
2296
            // env->dmmuregs[5] holds D-MMU TSB register value
2297
            // env->dmmuregs[6] holds D-MMU Tag Access register value
2298
            ret = ultrasparc_tsb_pointer(env->dmmu.tsb, env->dmmu.tag_access,
2299
                                         8*1024);
2300
            break;
2301
        }
2302
    case 0x5a: // D-MMU 64k TSB pointer
2303
        {
2304
            // env->dmmuregs[5] holds D-MMU TSB register value
2305
            // env->dmmuregs[6] holds D-MMU Tag Access register value
2306
            ret = ultrasparc_tsb_pointer(env->dmmu.tsb, env->dmmu.tag_access,
2307
                                         64*1024);
2308
            break;
2309
        }
2310
    case 0x5d: // D-MMU data access
2311
        {
2312
            int reg = (addr >> 3) & 0x3f;
2313

    
2314
            ret = env->dtlb[reg].tte;
2315
            break;
2316
        }
2317
    case 0x5e: // D-MMU tag read
2318
        {
2319
            int reg = (addr >> 3) & 0x3f;
2320

    
2321
            ret = env->dtlb[reg].tag;
2322
            break;
2323
        }
2324
    case 0x46: // D-cache data
2325
    case 0x47: // D-cache tag access
2326
    case 0x4b: // E-cache error enable
2327
    case 0x4c: // E-cache asynchronous fault status
2328
    case 0x4d: // E-cache asynchronous fault address
2329
    case 0x4e: // E-cache tag data
2330
    case 0x66: // I-cache instruction access
2331
    case 0x67: // I-cache tag access
2332
    case 0x6e: // I-cache predecode
2333
    case 0x6f: // I-cache LRU etc.
2334
    case 0x76: // E-cache tag
2335
    case 0x7e: // E-cache tag
2336
        break;
2337
    case 0x5b: // D-MMU data pointer
2338
    case 0x48: // Interrupt dispatch, RO
2339
    case 0x49: // Interrupt data receive
2340
    case 0x7f: // Incoming interrupt vector, RO
2341
        // XXX
2342
        break;
2343
    case 0x54: // I-MMU data in, WO
2344
    case 0x57: // I-MMU demap, WO
2345
    case 0x5c: // D-MMU data in, WO
2346
    case 0x5f: // D-MMU demap, WO
2347
    case 0x77: // Interrupt vector, WO
2348
    default:
2349
        do_unassigned_access(addr, 0, 0, 1, size);
2350
        ret = 0;
2351
        break;
2352
    }
2353

    
2354
    /* Convert from little endian */
2355
    switch (asi) {
2356
    case 0x0c: // Nucleus Little Endian (LE)
2357
    case 0x18: // As if user primary LE
2358
    case 0x19: // As if user secondary LE
2359
    case 0x1c: // Bypass LE
2360
    case 0x1d: // Bypass, non-cacheable LE
2361
    case 0x88: // Primary LE
2362
    case 0x89: // Secondary LE
2363
    case 0x8a: // Primary no-fault LE
2364
    case 0x8b: // Secondary no-fault LE
2365
        switch(size) {
2366
        case 2:
2367
            ret = bswap16(ret);
2368
            break;
2369
        case 4:
2370
            ret = bswap32(ret);
2371
            break;
2372
        case 8:
2373
            ret = bswap64(ret);
2374
            break;
2375
        default:
2376
            break;
2377
        }
2378
    default:
2379
        break;
2380
    }
2381

    
2382
    /* Convert to signed number */
2383
    if (sign) {
2384
        switch(size) {
2385
        case 1:
2386
            ret = (int8_t) ret;
2387
            break;
2388
        case 2:
2389
            ret = (int16_t) ret;
2390
            break;
2391
        case 4:
2392
            ret = (int32_t) ret;
2393
            break;
2394
        default:
2395
            break;
2396
        }
2397
    }
2398
#ifdef DEBUG_ASI
2399
    dump_asi("read ", last_addr, asi, size, ret);
2400
#endif
2401
    return ret;
2402
}
2403

    
2404
void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
2405
{
2406
#ifdef DEBUG_ASI
2407
    dump_asi("write", addr, asi, size, val);
2408
#endif
2409
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
2410
        || ((env->def->features & CPU_FEATURE_HYPV)
2411
            && asi >= 0x30 && asi < 0x80
2412
            && !(env->hpstate & HS_PRIV)))
2413
        raise_exception(TT_PRIV_ACT);
2414

    
2415
    helper_check_align(addr, size - 1);
2416
    /* Convert to little endian */
2417
    switch (asi) {
2418
    case 0x0c: // Nucleus Little Endian (LE)
2419
    case 0x18: // As if user primary LE
2420
    case 0x19: // As if user secondary LE
2421
    case 0x1c: // Bypass LE
2422
    case 0x1d: // Bypass, non-cacheable LE
2423
    case 0x88: // Primary LE
2424
    case 0x89: // Secondary LE
2425
        switch(size) {
2426
        case 2:
2427
            val = bswap16(val);
2428
            break;
2429
        case 4:
2430
            val = bswap32(val);
2431
            break;
2432
        case 8:
2433
            val = bswap64(val);
2434
            break;
2435
        default:
2436
            break;
2437
        }
2438
    default:
2439
        break;
2440
    }
2441

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

    
2542
            oldreg = env->lsu;
2543
            env->lsu = val & (DMMU_E | IMMU_E);
2544
            // Mappings generated during D/I MMU disabled mode are
2545
            // invalid in normal mode
2546
            if (oldreg != env->lsu) {
2547
                DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n",
2548
                            oldreg, env->lsu);
2549
#ifdef DEBUG_MMU
2550
                dump_mmu(env);
2551
#endif
2552
                tlb_flush(env, 1);
2553
            }
2554
            return;
2555
        }
2556
    case 0x50: // I-MMU regs
2557
        {
2558
            int reg = (addr >> 3) & 0xf;
2559
            uint64_t oldreg;
2560

    
2561
            oldreg = env->immuregs[reg];
2562
            switch(reg) {
2563
            case 0: // RO
2564
                return;
2565
            case 1: // Not in I-MMU
2566
            case 2:
2567
                return;
2568
            case 3: // SFSR
2569
                if ((val & 1) == 0)
2570
                    val = 0; // Clear SFSR
2571
                env->immu.sfsr = val;
2572
                break;
2573
            case 4: // RO
2574
                return;
2575
            case 5: // TSB access
2576
                DPRINTF_MMU("immu TSB write: 0x%016" PRIx64 " -> 0x%016"
2577
                            PRIx64 "\n", env->immu.tsb, val);
2578
                env->immu.tsb = val;
2579
                break;
2580
            case 6: // Tag access
2581
                env->immu.tag_access = val;
2582
                break;
2583
            case 7:
2584
            case 8:
2585
                return;
2586
            default:
2587
                break;
2588
            }
2589

    
2590
            if (oldreg != env->immuregs[reg]) {
2591
                DPRINTF_MMU("immu change reg[%d]: 0x%016" PRIx64 " -> 0x%016"
2592
                            PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
2593
            }
2594
#ifdef DEBUG_MMU
2595
            dump_mmu(env);
2596
#endif
2597
            return;
2598
        }
2599
    case 0x54: // I-MMU data in
2600
        replace_tlb_1bit_lru(env->itlb, env->immu.tag_access, val, "immu", env);
2601
        return;
2602
    case 0x55: // I-MMU data access
2603
        {
2604
            // TODO: auto demap
2605

    
2606
            unsigned int i = (addr >> 3) & 0x3f;
2607

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

    
2610
#ifdef DEBUG_MMU
2611
            DPRINTF_MMU("immu data access replaced entry [%i]\n", i);
2612
            dump_mmu(env);
2613
#endif
2614
            return;
2615
        }
2616
    case 0x57: // I-MMU demap
2617
        demap_tlb(env->itlb, val, "immu", env);
2618
        return;
2619
    case 0x58: // D-MMU regs
2620
        {
2621
            int reg = (addr >> 3) & 0xf;
2622
            uint64_t oldreg;
2623

    
2624
            oldreg = env->dmmuregs[reg];
2625
            switch(reg) {
2626
            case 0: // RO
2627
            case 4:
2628
                return;
2629
            case 3: // SFSR
2630
                if ((val & 1) == 0) {
2631
                    val = 0; // Clear SFSR, Fault address
2632
                    env->dmmu.sfar = 0;
2633
                }
2634
                env->dmmu.sfsr = val;
2635
                break;
2636
            case 1: // Primary context
2637
                env->dmmu.mmu_primary_context = val;
2638
                break;
2639
            case 2: // Secondary context
2640
                env->dmmu.mmu_secondary_context = val;
2641
                break;
2642
            case 5: // TSB access
2643
                DPRINTF_MMU("dmmu TSB write: 0x%016" PRIx64 " -> 0x%016"
2644
                            PRIx64 "\n", env->dmmu.tsb, val);
2645
                env->dmmu.tsb = val;
2646
                break;
2647
            case 6: // Tag access
2648
                env->dmmu.tag_access = val;
2649
                break;
2650
            case 7: // Virtual Watchpoint
2651
            case 8: // Physical Watchpoint
2652
            default:
2653
                env->dmmuregs[reg] = val;
2654
                break;
2655
            }
2656

    
2657
            if (oldreg != env->dmmuregs[reg]) {
2658
                DPRINTF_MMU("dmmu change reg[%d]: 0x%016" PRIx64 " -> 0x%016"
2659
                            PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
2660
            }
2661
#ifdef DEBUG_MMU
2662
            dump_mmu(env);
2663
#endif
2664
            return;
2665
        }
2666
    case 0x5c: // D-MMU data in
2667
        replace_tlb_1bit_lru(env->dtlb, env->dmmu.tag_access, val, "dmmu", env);
2668
        return;
2669
    case 0x5d: // D-MMU data access
2670
        {
2671
            unsigned int i = (addr >> 3) & 0x3f;
2672

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

    
2675
#ifdef DEBUG_MMU
2676
            DPRINTF_MMU("dmmu data access replaced entry [%i]\n", i);
2677
            dump_mmu(env);
2678
#endif
2679
            return;
2680
        }
2681
    case 0x5f: // D-MMU demap
2682
        demap_tlb(env->dtlb, val, "dmmu", env);
2683
        return;
2684
    case 0x49: // Interrupt data receive
2685
        // XXX
2686
        return;
2687
    case 0x46: // D-cache data
2688
    case 0x47: // D-cache tag access
2689
    case 0x4b: // E-cache error enable
2690
    case 0x4c: // E-cache asynchronous fault status
2691
    case 0x4d: // E-cache asynchronous fault address
2692
    case 0x4e: // E-cache tag data
2693
    case 0x66: // I-cache instruction access
2694
    case 0x67: // I-cache tag access
2695
    case 0x6e: // I-cache predecode
2696
    case 0x6f: // I-cache LRU etc.
2697
    case 0x76: // E-cache tag
2698
    case 0x7e: // E-cache tag
2699
        return;
2700
    case 0x51: // I-MMU 8k TSB pointer, RO
2701
    case 0x52: // I-MMU 64k TSB pointer, RO
2702
    case 0x56: // I-MMU tag read, RO
2703
    case 0x59: // D-MMU 8k TSB pointer, RO
2704
    case 0x5a: // D-MMU 64k TSB pointer, RO
2705
    case 0x5b: // D-MMU data pointer, RO
2706
    case 0x5e: // D-MMU tag read, RO
2707
    case 0x48: // Interrupt dispatch, RO
2708
    case 0x7f: // Incoming interrupt vector, RO
2709
    case 0x82: // Primary no-fault, RO
2710
    case 0x83: // Secondary no-fault, RO
2711
    case 0x8a: // Primary no-fault LE, RO
2712
    case 0x8b: // Secondary no-fault LE, RO
2713
    default:
2714
        do_unassigned_access(addr, 1, 0, 1, size);
2715
        return;
2716
    }
2717
}
2718
#endif /* CONFIG_USER_ONLY */
2719

    
2720
void helper_ldda_asi(target_ulong addr, int asi, int rd)
2721
{
2722
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
2723
        || ((env->def->features & CPU_FEATURE_HYPV)
2724
            && asi >= 0x30 && asi < 0x80
2725
            && !(env->hpstate & HS_PRIV)))
2726
        raise_exception(TT_PRIV_ACT);
2727

    
2728
    switch (asi) {
2729
    case 0x24: // Nucleus quad LDD 128 bit atomic
2730
    case 0x2c: // Nucleus quad LDD 128 bit atomic LE
2731
        helper_check_align(addr, 0xf);
2732
        if (rd == 0) {
2733
            env->gregs[1] = ldq_kernel(addr + 8);
2734
            if (asi == 0x2c)
2735
                bswap64s(&env->gregs[1]);
2736
        } else if (rd < 8) {
2737
            env->gregs[rd] = ldq_kernel(addr);
2738
            env->gregs[rd + 1] = ldq_kernel(addr + 8);
2739
            if (asi == 0x2c) {
2740
                bswap64s(&env->gregs[rd]);
2741
                bswap64s(&env->gregs[rd + 1]);
2742
            }
2743
        } else {
2744
            env->regwptr[rd] = ldq_kernel(addr);
2745
            env->regwptr[rd + 1] = ldq_kernel(addr + 8);
2746
            if (asi == 0x2c) {
2747
                bswap64s(&env->regwptr[rd]);
2748
                bswap64s(&env->regwptr[rd + 1]);
2749
            }
2750
        }
2751
        break;
2752
    default:
2753
        helper_check_align(addr, 0x3);
2754
        if (rd == 0)
2755
            env->gregs[1] = helper_ld_asi(addr + 4, asi, 4, 0);
2756
        else if (rd < 8) {
2757
            env->gregs[rd] = helper_ld_asi(addr, asi, 4, 0);
2758
            env->gregs[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
2759
        } else {
2760
            env->regwptr[rd] = helper_ld_asi(addr, asi, 4, 0);
2761
            env->regwptr[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
2762
        }
2763
        break;
2764
    }
2765
}
2766

    
2767
void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
2768
{
2769
    unsigned int i;
2770
    target_ulong val;
2771

    
2772
    helper_check_align(addr, 3);
2773
    switch (asi) {
2774
    case 0xf0: // Block load primary
2775
    case 0xf1: // Block load secondary
2776
    case 0xf8: // Block load primary LE
2777
    case 0xf9: // Block load secondary LE
2778
        if (rd & 7) {
2779
            raise_exception(TT_ILL_INSN);
2780
            return;
2781
        }
2782
        helper_check_align(addr, 0x3f);
2783
        for (i = 0; i < 16; i++) {
2784
            *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x8f, 4,
2785
                                                         0);
2786
            addr += 4;
2787
        }
2788

    
2789
        return;
2790
    default:
2791
        break;
2792
    }
2793

    
2794
    val = helper_ld_asi(addr, asi, size, 0);
2795
    switch(size) {
2796
    default:
2797
    case 4:
2798
        *((uint32_t *)&env->fpr[rd]) = val;
2799
        break;
2800
    case 8:
2801
        *((int64_t *)&DT0) = val;
2802
        break;
2803
    case 16:
2804
        // XXX
2805
        break;
2806
    }
2807
}
2808

    
2809
void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
2810
{
2811
    unsigned int i;
2812
    target_ulong val = 0;
2813

    
2814
    helper_check_align(addr, 3);
2815
    switch (asi) {
2816
    case 0xe0: // UA2007 Block commit store primary (cache flush)
2817
    case 0xe1: // UA2007 Block commit store secondary (cache flush)
2818
    case 0xf0: // Block store primary
2819
    case 0xf1: // Block store secondary
2820
    case 0xf8: // Block store primary LE
2821
    case 0xf9: // Block store secondary LE
2822
        if (rd & 7) {
2823
            raise_exception(TT_ILL_INSN);
2824
            return;
2825
        }
2826
        helper_check_align(addr, 0x3f);
2827
        for (i = 0; i < 16; i++) {
2828
            val = *(uint32_t *)&env->fpr[rd++];
2829
            helper_st_asi(addr, val, asi & 0x8f, 4);
2830
            addr += 4;
2831
        }
2832

    
2833
        return;
2834
    default:
2835
        break;
2836
    }
2837

    
2838
    switch(size) {
2839
    default:
2840
    case 4:
2841
        val = *((uint32_t *)&env->fpr[rd]);
2842
        break;
2843
    case 8:
2844
        val = *((int64_t *)&DT0);
2845
        break;
2846
    case 16:
2847
        // XXX
2848
        break;
2849
    }
2850
    helper_st_asi(addr, val, asi, size);
2851
}
2852

    
2853
target_ulong helper_cas_asi(target_ulong addr, target_ulong val1,
2854
                            target_ulong val2, uint32_t asi)
2855
{
2856
    target_ulong ret;
2857

    
2858
    val2 &= 0xffffffffUL;
2859
    ret = helper_ld_asi(addr, asi, 4, 0);
2860
    ret &= 0xffffffffUL;
2861
    if (val2 == ret)
2862
        helper_st_asi(addr, val1 & 0xffffffffUL, asi, 4);
2863
    return ret;
2864
}
2865

    
2866
target_ulong helper_casx_asi(target_ulong addr, target_ulong val1,
2867
                             target_ulong val2, uint32_t asi)
2868
{
2869
    target_ulong ret;
2870

    
2871
    ret = helper_ld_asi(addr, asi, 8, 0);
2872
    if (val2 == ret)
2873
        helper_st_asi(addr, val1, asi, 8);
2874
    return ret;
2875
}
2876
#endif /* TARGET_SPARC64 */
2877

    
2878
#ifndef TARGET_SPARC64
2879
void helper_rett(void)
2880
{
2881
    unsigned int cwp;
2882

    
2883
    if (env->psret == 1)
2884
        raise_exception(TT_ILL_INSN);
2885

    
2886
    env->psret = 1;
2887
    cwp = cpu_cwp_inc(env, env->cwp + 1) ;
2888
    if (env->wim & (1 << cwp)) {
2889
        raise_exception(TT_WIN_UNF);
2890
    }
2891
    set_cwp(cwp);
2892
    env->psrs = env->psrps;
2893
}
2894
#endif
2895

    
2896
target_ulong helper_udiv(target_ulong a, target_ulong b)
2897
{
2898
    uint64_t x0;
2899
    uint32_t x1;
2900

    
2901
    x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
2902
    x1 = b;
2903

    
2904
    if (x1 == 0) {
2905
        raise_exception(TT_DIV_ZERO);
2906
    }
2907

    
2908
    x0 = x0 / x1;
2909
    if (x0 > 0xffffffff) {
2910
        env->cc_src2 = 1;
2911
        return 0xffffffff;
2912
    } else {
2913
        env->cc_src2 = 0;
2914
        return x0;
2915
    }
2916
}
2917

    
2918
target_ulong helper_sdiv(target_ulong a, target_ulong b)
2919
{
2920
    int64_t x0;
2921
    int32_t x1;
2922

    
2923
    x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
2924
    x1 = b;
2925

    
2926
    if (x1 == 0) {
2927
        raise_exception(TT_DIV_ZERO);
2928
    }
2929

    
2930
    x0 = x0 / x1;
2931
    if ((int32_t) x0 != x0) {
2932
        env->cc_src2 = 1;
2933
        return x0 < 0? 0x80000000: 0x7fffffff;
2934
    } else {
2935
        env->cc_src2 = 0;
2936
        return x0;
2937
    }
2938
}
2939

    
2940
void helper_stdf(target_ulong addr, int mem_idx)
2941
{
2942
    helper_check_align(addr, 7);
2943
#if !defined(CONFIG_USER_ONLY)
2944
    switch (mem_idx) {
2945
    case 0:
2946
        stfq_user(addr, DT0);
2947
        break;
2948
    case 1:
2949
        stfq_kernel(addr, DT0);
2950
        break;
2951
#ifdef TARGET_SPARC64
2952
    case 2:
2953
        stfq_hypv(addr, DT0);
2954
        break;
2955
#endif
2956
    default:
2957
        break;
2958
    }
2959
#else
2960
    address_mask(env, &addr);
2961
    stfq_raw(addr, DT0);
2962
#endif
2963
}
2964

    
2965
void helper_lddf(target_ulong addr, int mem_idx)
2966
{
2967
    helper_check_align(addr, 7);
2968
#if !defined(CONFIG_USER_ONLY)
2969
    switch (mem_idx) {
2970
    case 0:
2971
        DT0 = ldfq_user(addr);
2972
        break;
2973
    case 1:
2974
        DT0 = ldfq_kernel(addr);
2975
        break;
2976
#ifdef TARGET_SPARC64
2977
    case 2:
2978
        DT0 = ldfq_hypv(addr);
2979
        break;
2980
#endif
2981
    default:
2982
        break;
2983
    }
2984
#else
2985
    address_mask(env, &addr);
2986
    DT0 = ldfq_raw(addr);
2987
#endif
2988
}
2989

    
2990
void helper_ldqf(target_ulong addr, int mem_idx)
2991
{
2992
    // XXX add 128 bit load
2993
    CPU_QuadU u;
2994

    
2995
    helper_check_align(addr, 7);
2996
#if !defined(CONFIG_USER_ONLY)
2997
    switch (mem_idx) {
2998
    case 0:
2999
        u.ll.upper = ldq_user(addr);
3000
        u.ll.lower = ldq_user(addr + 8);
3001
        QT0 = u.q;
3002
        break;
3003
    case 1:
3004
        u.ll.upper = ldq_kernel(addr);
3005
        u.ll.lower = ldq_kernel(addr + 8);
3006
        QT0 = u.q;
3007
        break;
3008
#ifdef TARGET_SPARC64
3009
    case 2:
3010
        u.ll.upper = ldq_hypv(addr);
3011
        u.ll.lower = ldq_hypv(addr + 8);
3012
        QT0 = u.q;
3013
        break;
3014
#endif
3015
    default:
3016
        break;
3017
    }
3018
#else
3019
    address_mask(env, &addr);
3020
    u.ll.upper = ldq_raw(addr);
3021
    u.ll.lower = ldq_raw((addr + 8) & 0xffffffffULL);
3022
    QT0 = u.q;
3023
#endif
3024
}
3025

    
3026
void helper_stqf(target_ulong addr, int mem_idx)
3027
{
3028
    // XXX add 128 bit store
3029
    CPU_QuadU u;
3030

    
3031
    helper_check_align(addr, 7);
3032
#if !defined(CONFIG_USER_ONLY)
3033
    switch (mem_idx) {
3034
    case 0:
3035
        u.q = QT0;
3036
        stq_user(addr, u.ll.upper);
3037
        stq_user(addr + 8, u.ll.lower);
3038
        break;
3039
    case 1:
3040
        u.q = QT0;
3041
        stq_kernel(addr, u.ll.upper);
3042
        stq_kernel(addr + 8, u.ll.lower);
3043
        break;
3044
#ifdef TARGET_SPARC64
3045
    case 2:
3046
        u.q = QT0;
3047
        stq_hypv(addr, u.ll.upper);
3048
        stq_hypv(addr + 8, u.ll.lower);
3049
        break;
3050
#endif
3051
    default:
3052
        break;
3053
    }
3054
#else
3055
    u.q = QT0;
3056
    address_mask(env, &addr);
3057
    stq_raw(addr, u.ll.upper);
3058
    stq_raw((addr + 8) & 0xffffffffULL, u.ll.lower);
3059
#endif
3060
}
3061

    
3062
static inline void set_fsr(void)
3063
{
3064
    int rnd_mode;
3065

    
3066
    switch (env->fsr & FSR_RD_MASK) {
3067
    case FSR_RD_NEAREST:
3068
        rnd_mode = float_round_nearest_even;
3069
        break;
3070
    default:
3071
    case FSR_RD_ZERO:
3072
        rnd_mode = float_round_to_zero;
3073
        break;
3074
    case FSR_RD_POS:
3075
        rnd_mode = float_round_up;
3076
        break;
3077
    case FSR_RD_NEG:
3078
        rnd_mode = float_round_down;
3079
        break;
3080
    }
3081
    set_float_rounding_mode(rnd_mode, &env->fp_status);
3082
}
3083

    
3084
void helper_ldfsr(uint32_t new_fsr)
3085
{
3086
    env->fsr = (new_fsr & FSR_LDFSR_MASK) | (env->fsr & FSR_LDFSR_OLDMASK);
3087
    set_fsr();
3088
}
3089

    
3090
#ifdef TARGET_SPARC64
3091
void helper_ldxfsr(uint64_t new_fsr)
3092
{
3093
    env->fsr = (new_fsr & FSR_LDXFSR_MASK) | (env->fsr & FSR_LDXFSR_OLDMASK);
3094
    set_fsr();
3095
}
3096
#endif
3097

    
3098
void helper_debug(void)
3099
{
3100
    env->exception_index = EXCP_DEBUG;
3101
    cpu_loop_exit();
3102
}
3103

    
3104
#ifndef TARGET_SPARC64
3105
/* XXX: use another pointer for %iN registers to avoid slow wrapping
3106
   handling ? */
3107
void helper_save(void)
3108
{
3109
    uint32_t cwp;
3110

    
3111
    cwp = cpu_cwp_dec(env, env->cwp - 1);
3112
    if (env->wim & (1 << cwp)) {
3113
        raise_exception(TT_WIN_OVF);
3114
    }
3115
    set_cwp(cwp);
3116
}
3117

    
3118
void helper_restore(void)
3119
{
3120
    uint32_t cwp;
3121

    
3122
    cwp = cpu_cwp_inc(env, env->cwp + 1);
3123
    if (env->wim & (1 << cwp)) {
3124
        raise_exception(TT_WIN_UNF);
3125
    }
3126
    set_cwp(cwp);
3127
}
3128

    
3129
void helper_wrpsr(target_ulong new_psr)
3130
{
3131
    if ((new_psr & PSR_CWP) >= env->nwindows)
3132
        raise_exception(TT_ILL_INSN);
3133
    else
3134
        PUT_PSR(env, new_psr);
3135
}
3136

    
3137
target_ulong helper_rdpsr(void)
3138
{
3139
    return GET_PSR(env);
3140
}
3141

    
3142
#else
3143
/* XXX: use another pointer for %iN registers to avoid slow wrapping
3144
   handling ? */
3145
void helper_save(void)
3146
{
3147
    uint32_t cwp;
3148

    
3149
    cwp = cpu_cwp_dec(env, env->cwp - 1);
3150
    if (env->cansave == 0) {
3151
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
3152
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
3153
                                    ((env->wstate & 0x7) << 2)));
3154
    } else {
3155
        if (env->cleanwin - env->canrestore == 0) {
3156
            // XXX Clean windows without trap
3157
            raise_exception(TT_CLRWIN);
3158
        } else {
3159
            env->cansave--;
3160
            env->canrestore++;
3161
            set_cwp(cwp);
3162
        }
3163
    }
3164
}
3165

    
3166
void helper_restore(void)
3167
{
3168
    uint32_t cwp;
3169

    
3170
    cwp = cpu_cwp_inc(env, env->cwp + 1);
3171
    if (env->canrestore == 0) {
3172
        raise_exception(TT_FILL | (env->otherwin != 0 ?
3173
                                   (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
3174
                                   ((env->wstate & 0x7) << 2)));
3175
    } else {
3176
        env->cansave++;
3177
        env->canrestore--;
3178
        set_cwp(cwp);
3179
    }
3180
}
3181

    
3182
void helper_flushw(void)
3183
{
3184
    if (env->cansave != env->nwindows - 2) {
3185
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
3186
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
3187
                                    ((env->wstate & 0x7) << 2)));
3188
    }
3189
}
3190

    
3191
void helper_saved(void)
3192
{
3193
    env->cansave++;
3194
    if (env->otherwin == 0)
3195
        env->canrestore--;
3196
    else
3197
        env->otherwin--;
3198
}
3199

    
3200
void helper_restored(void)
3201
{
3202
    env->canrestore++;
3203
    if (env->cleanwin < env->nwindows - 1)
3204
        env->cleanwin++;
3205
    if (env->otherwin == 0)
3206
        env->cansave--;
3207
    else
3208
        env->otherwin--;
3209
}
3210

    
3211
target_ulong helper_rdccr(void)
3212
{
3213
    return GET_CCR(env);
3214
}
3215

    
3216
void helper_wrccr(target_ulong new_ccr)
3217
{
3218
    PUT_CCR(env, new_ccr);
3219
}
3220

    
3221
// CWP handling is reversed in V9, but we still use the V8 register
3222
// order.
3223
target_ulong helper_rdcwp(void)
3224
{
3225
    return GET_CWP64(env);
3226
}
3227

    
3228
void helper_wrcwp(target_ulong new_cwp)
3229
{
3230
    PUT_CWP64(env, new_cwp);
3231
}
3232

    
3233
// This function uses non-native bit order
3234
#define GET_FIELD(X, FROM, TO)                                  \
3235
    ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
3236

    
3237
// This function uses the order in the manuals, i.e. bit 0 is 2^0
3238
#define GET_FIELD_SP(X, FROM, TO)               \
3239
    GET_FIELD(X, 63 - (TO), 63 - (FROM))
3240

    
3241
target_ulong helper_array8(target_ulong pixel_addr, target_ulong cubesize)
3242
{
3243
    return (GET_FIELD_SP(pixel_addr, 60, 63) << (17 + 2 * cubesize)) |
3244
        (GET_FIELD_SP(pixel_addr, 39, 39 + cubesize - 1) << (17 + cubesize)) |
3245
        (GET_FIELD_SP(pixel_addr, 17 + cubesize - 1, 17) << 17) |
3246
        (GET_FIELD_SP(pixel_addr, 56, 59) << 13) |
3247
        (GET_FIELD_SP(pixel_addr, 35, 38) << 9) |
3248
        (GET_FIELD_SP(pixel_addr, 13, 16) << 5) |
3249
        (((pixel_addr >> 55) & 1) << 4) |
3250
        (GET_FIELD_SP(pixel_addr, 33, 34) << 2) |
3251
        GET_FIELD_SP(pixel_addr, 11, 12);
3252
}
3253

    
3254
target_ulong helper_alignaddr(target_ulong addr, target_ulong offset)
3255
{
3256
    uint64_t tmp;
3257

    
3258
    tmp = addr + offset;
3259
    env->gsr &= ~7ULL;
3260
    env->gsr |= tmp & 7ULL;
3261
    return tmp & ~7ULL;
3262
}
3263

    
3264
target_ulong helper_popc(target_ulong val)
3265
{
3266
    return ctpop64(val);
3267
}
3268

    
3269
static inline uint64_t *get_gregset(uint64_t pstate)
3270
{
3271
    switch (pstate) {
3272
    default:
3273
    case 0:
3274
        return env->bgregs;
3275
    case PS_AG:
3276
        return env->agregs;
3277
    case PS_MG:
3278
        return env->mgregs;
3279
    case PS_IG:
3280
        return env->igregs;
3281
    }
3282
}
3283

    
3284
static inline void change_pstate(uint64_t new_pstate)
3285
{
3286
    uint64_t pstate_regs, new_pstate_regs;
3287
    uint64_t *src, *dst;
3288

    
3289
    if (env->def->features & CPU_FEATURE_GL) {
3290
        // PS_AG is not implemented in this case
3291
        new_pstate &= ~PS_AG;
3292
    }
3293

    
3294
    pstate_regs = env->pstate & 0xc01;
3295
    new_pstate_regs = new_pstate & 0xc01;
3296

    
3297
    if (new_pstate_regs != pstate_regs) {
3298
        // Switch global register bank
3299
        src = get_gregset(new_pstate_regs);
3300
        dst = get_gregset(pstate_regs);
3301
        memcpy32(dst, env->gregs);
3302
        memcpy32(env->gregs, src);
3303
    }
3304
    env->pstate = new_pstate;
3305
}
3306

    
3307
void helper_wrpstate(target_ulong new_state)
3308
{
3309
    change_pstate(new_state & 0xf3f);
3310
}
3311

    
3312
void helper_done(void)
3313
{
3314
    env->pc = env->tsptr->tpc;
3315
    env->npc = env->tsptr->tnpc + 4;
3316
    PUT_CCR(env, env->tsptr->tstate >> 32);
3317
    env->asi = (env->tsptr->tstate >> 24) & 0xff;
3318
    change_pstate((env->tsptr->tstate >> 8) & 0xf3f);
3319
    PUT_CWP64(env, env->tsptr->tstate & 0xff);
3320
    env->tl--;
3321
    env->tsptr = &env->ts[env->tl & MAXTL_MASK];
3322
}
3323

    
3324
void helper_retry(void)
3325
{
3326
    env->pc = env->tsptr->tpc;
3327
    env->npc = env->tsptr->tnpc;
3328
    PUT_CCR(env, env->tsptr->tstate >> 32);
3329
    env->asi = (env->tsptr->tstate >> 24) & 0xff;
3330
    change_pstate((env->tsptr->tstate >> 8) & 0xf3f);
3331
    PUT_CWP64(env, env->tsptr->tstate & 0xff);
3332
    env->tl--;
3333
    env->tsptr = &env->ts[env->tl & MAXTL_MASK];
3334
}
3335

    
3336
void helper_set_softint(uint64_t value)
3337
{
3338
    env->softint |= (uint32_t)value;
3339
}
3340

    
3341
void helper_clear_softint(uint64_t value)
3342
{
3343
    env->softint &= (uint32_t)~value;
3344
}
3345

    
3346
void helper_write_softint(uint64_t value)
3347
{
3348
    env->softint = (uint32_t)value;
3349
}
3350
#endif
3351

    
3352
void helper_flush(target_ulong addr)
3353
{
3354
    addr &= ~7;
3355
    tb_invalidate_page_range(addr, addr + 8);
3356
}
3357

    
3358
#ifdef TARGET_SPARC64
3359
#ifdef DEBUG_PCALL
3360
static const char * const excp_names[0x80] = {
3361
    [TT_TFAULT] = "Instruction Access Fault",
3362
    [TT_TMISS] = "Instruction Access MMU Miss",
3363
    [TT_CODE_ACCESS] = "Instruction Access Error",
3364
    [TT_ILL_INSN] = "Illegal Instruction",
3365
    [TT_PRIV_INSN] = "Privileged Instruction",
3366
    [TT_NFPU_INSN] = "FPU Disabled",
3367
    [TT_FP_EXCP] = "FPU Exception",
3368
    [TT_TOVF] = "Tag Overflow",
3369
    [TT_CLRWIN] = "Clean Windows",
3370
    [TT_DIV_ZERO] = "Division By Zero",
3371
    [TT_DFAULT] = "Data Access Fault",
3372
    [TT_DMISS] = "Data Access MMU Miss",
3373
    [TT_DATA_ACCESS] = "Data Access Error",
3374
    [TT_DPROT] = "Data Protection Error",
3375
    [TT_UNALIGNED] = "Unaligned Memory Access",
3376
    [TT_PRIV_ACT] = "Privileged Action",
3377
    [TT_EXTINT | 0x1] = "External Interrupt 1",
3378
    [TT_EXTINT | 0x2] = "External Interrupt 2",
3379
    [TT_EXTINT | 0x3] = "External Interrupt 3",
3380
    [TT_EXTINT | 0x4] = "External Interrupt 4",
3381
    [TT_EXTINT | 0x5] = "External Interrupt 5",
3382
    [TT_EXTINT | 0x6] = "External Interrupt 6",
3383
    [TT_EXTINT | 0x7] = "External Interrupt 7",
3384
    [TT_EXTINT | 0x8] = "External Interrupt 8",
3385
    [TT_EXTINT | 0x9] = "External Interrupt 9",
3386
    [TT_EXTINT | 0xa] = "External Interrupt 10",
3387
    [TT_EXTINT | 0xb] = "External Interrupt 11",
3388
    [TT_EXTINT | 0xc] = "External Interrupt 12",
3389
    [TT_EXTINT | 0xd] = "External Interrupt 13",
3390
    [TT_EXTINT | 0xe] = "External Interrupt 14",
3391
    [TT_EXTINT | 0xf] = "External Interrupt 15",
3392
};
3393
#endif
3394

    
3395
void do_interrupt(CPUState *env)
3396
{
3397
    int intno = env->exception_index;
3398

    
3399
#ifdef DEBUG_PCALL
3400
    if (qemu_loglevel_mask(CPU_LOG_INT)) {
3401
        static int count;
3402
        const char *name;
3403

    
3404
        if (intno < 0 || intno >= 0x180)
3405
            name = "Unknown";
3406
        else if (intno >= 0x100)
3407
            name = "Trap Instruction";
3408
        else if (intno >= 0xc0)
3409
            name = "Window Fill";
3410
        else if (intno >= 0x80)
3411
            name = "Window Spill";
3412
        else {
3413
            name = excp_names[intno];
3414
            if (!name)
3415
                name = "Unknown";
3416
        }
3417

    
3418
        qemu_log("%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
3419
                " SP=%016" PRIx64 "\n",
3420
                count, name, intno,
3421
                env->pc,
3422
                env->npc, env->regwptr[6]);
3423
        log_cpu_state(env, 0);
3424
#if 0
3425
        {
3426
            int i;
3427
            uint8_t *ptr;
3428

3429
            qemu_log("       code=");
3430
            ptr = (uint8_t *)env->pc;
3431
            for(i = 0; i < 16; i++) {
3432
                qemu_log(" %02x", ldub(ptr + i));
3433
            }
3434
            qemu_log("\n");
3435
        }
3436
#endif
3437
        count++;
3438
    }
3439
#endif
3440
#if !defined(CONFIG_USER_ONLY)
3441
    if (env->tl >= env->maxtl) {
3442
        cpu_abort(env, "Trap 0x%04x while trap level (%d) >= MAXTL (%d),"
3443
                  " Error state", env->exception_index, env->tl, env->maxtl);
3444
        return;
3445
    }
3446
#endif
3447
    if (env->tl < env->maxtl - 1) {
3448
        env->tl++;
3449
    } else {
3450
        env->pstate |= PS_RED;
3451
        if (env->tl < env->maxtl)
3452
            env->tl++;
3453
    }
3454
    env->tsptr = &env->ts[env->tl & MAXTL_MASK];
3455
    env->tsptr->tstate = ((uint64_t)GET_CCR(env) << 32) |
3456
        ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
3457
        GET_CWP64(env);
3458
    env->tsptr->tpc = env->pc;
3459
    env->tsptr->tnpc = env->npc;
3460
    env->tsptr->tt = intno;
3461

    
3462
    switch (intno) {
3463
    case TT_IVEC:
3464
        change_pstate(PS_PEF | PS_PRIV | PS_IG);
3465
        break;
3466
    case TT_TFAULT:
3467
    case TT_TMISS:
3468
    case TT_DFAULT:
3469
    case TT_DMISS:
3470
    case TT_DPROT:
3471
        change_pstate(PS_PEF | PS_PRIV | PS_MG);
3472
        break;
3473
    default:
3474
        change_pstate(PS_PEF | PS_PRIV | PS_AG);
3475
        break;
3476
    }
3477

    
3478
    if (intno == TT_CLRWIN)
3479
        cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1));
3480
    else if ((intno & 0x1c0) == TT_SPILL)
3481
        cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2));
3482
    else if ((intno & 0x1c0) == TT_FILL)
3483
        cpu_set_cwp(env, cpu_cwp_inc(env, env->cwp + 1));
3484
    env->tbr &= ~0x7fffULL;
3485
    env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
3486
    env->pc = env->tbr;
3487
    env->npc = env->pc + 4;
3488
    env->exception_index = 0;
3489
}
3490
#else
3491
#ifdef DEBUG_PCALL
3492
static const char * const excp_names[0x80] = {
3493
    [TT_TFAULT] = "Instruction Access Fault",
3494
    [TT_ILL_INSN] = "Illegal Instruction",
3495
    [TT_PRIV_INSN] = "Privileged Instruction",
3496
    [TT_NFPU_INSN] = "FPU Disabled",
3497
    [TT_WIN_OVF] = "Window Overflow",
3498
    [TT_WIN_UNF] = "Window Underflow",
3499
    [TT_UNALIGNED] = "Unaligned Memory Access",
3500
    [TT_FP_EXCP] = "FPU Exception",
3501
    [TT_DFAULT] = "Data Access Fault",
3502
    [TT_TOVF] = "Tag Overflow",
3503
    [TT_EXTINT | 0x1] = "External Interrupt 1",
3504
    [TT_EXTINT | 0x2] = "External Interrupt 2",
3505
    [TT_EXTINT | 0x3] = "External Interrupt 3",
3506
    [TT_EXTINT | 0x4] = "External Interrupt 4",
3507
    [TT_EXTINT | 0x5] = "External Interrupt 5",
3508
    [TT_EXTINT | 0x6] = "External Interrupt 6",
3509
    [TT_EXTINT | 0x7] = "External Interrupt 7",
3510
    [TT_EXTINT | 0x8] = "External Interrupt 8",
3511
    [TT_EXTINT | 0x9] = "External Interrupt 9",
3512
    [TT_EXTINT | 0xa] = "External Interrupt 10",
3513
    [TT_EXTINT | 0xb] = "External Interrupt 11",
3514
    [TT_EXTINT | 0xc] = "External Interrupt 12",
3515
    [TT_EXTINT | 0xd] = "External Interrupt 13",
3516
    [TT_EXTINT | 0xe] = "External Interrupt 14",
3517
    [TT_EXTINT | 0xf] = "External Interrupt 15",
3518
    [TT_TOVF] = "Tag Overflow",
3519
    [TT_CODE_ACCESS] = "Instruction Access Error",
3520
    [TT_DATA_ACCESS] = "Data Access Error",
3521
    [TT_DIV_ZERO] = "Division By Zero",
3522
    [TT_NCP_INSN] = "Coprocessor Disabled",
3523
};
3524
#endif
3525

    
3526
void do_interrupt(CPUState *env)
3527
{
3528
    int cwp, intno = env->exception_index;
3529

    
3530
#ifdef DEBUG_PCALL
3531
    if (qemu_loglevel_mask(CPU_LOG_INT)) {
3532
        static int count;
3533
        const char *name;
3534

    
3535
        if (intno < 0 || intno >= 0x100)
3536
            name = "Unknown";
3537
        else if (intno >= 0x80)
3538
            name = "Trap Instruction";
3539
        else {
3540
            name = excp_names[intno];
3541
            if (!name)
3542
                name = "Unknown";
3543
        }
3544

    
3545
        qemu_log("%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
3546
                count, name, intno,
3547
                env->pc,
3548
                env->npc, env->regwptr[6]);
3549
        log_cpu_state(env, 0);
3550
#if 0
3551
        {
3552
            int i;
3553
            uint8_t *ptr;
3554

3555
            qemu_log("       code=");
3556
            ptr = (uint8_t *)env->pc;
3557
            for(i = 0; i < 16; i++) {
3558
                qemu_log(" %02x", ldub(ptr + i));
3559
            }
3560
            qemu_log("\n");
3561
        }
3562
#endif
3563
        count++;
3564
    }
3565
#endif
3566
#if !defined(CONFIG_USER_ONLY)
3567
    if (env->psret == 0) {
3568
        cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
3569
                  env->exception_index);
3570
        return;
3571
    }
3572
#endif
3573
    env->psret = 0;
3574
    cwp = cpu_cwp_dec(env, env->cwp - 1);
3575
    cpu_set_cwp(env, cwp);
3576
    env->regwptr[9] = env->pc;
3577
    env->regwptr[10] = env->npc;
3578
    env->psrps = env->psrs;
3579
    env->psrs = 1;
3580
    env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
3581
    env->pc = env->tbr;
3582
    env->npc = env->pc + 4;
3583
    env->exception_index = 0;
3584
}
3585
#endif
3586

    
3587
#if !defined(CONFIG_USER_ONLY)
3588

    
3589
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
3590
                                void *retaddr);
3591

    
3592
#define MMUSUFFIX _mmu
3593
#define ALIGNED_ONLY
3594

    
3595
#define SHIFT 0
3596
#include "softmmu_template.h"
3597

    
3598
#define SHIFT 1
3599
#include "softmmu_template.h"
3600

    
3601
#define SHIFT 2
3602
#include "softmmu_template.h"
3603

    
3604
#define SHIFT 3
3605
#include "softmmu_template.h"
3606

    
3607
/* XXX: make it generic ? */
3608
static void cpu_restore_state2(void *retaddr)
3609
{
3610
    TranslationBlock *tb;
3611
    unsigned long pc;
3612

    
3613
    if (retaddr) {
3614
        /* now we have a real cpu fault */
3615
        pc = (unsigned long)retaddr;
3616
        tb = tb_find_pc(pc);
3617
        if (tb) {
3618
            /* the PC is inside the translated code. It means that we have
3619
               a virtual CPU fault */
3620
            cpu_restore_state(tb, env, pc, (void *)(long)env->cond);
3621
        }
3622
    }
3623
}
3624

    
3625
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
3626
                                void *retaddr)
3627
{
3628
#ifdef DEBUG_UNALIGNED
3629
    printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
3630
           "\n", addr, env->pc);
3631
#endif
3632
    cpu_restore_state2(retaddr);
3633
    raise_exception(TT_UNALIGNED);
3634
}
3635

    
3636
/* try to fill the TLB and return an exception if error. If retaddr is
3637
   NULL, it means that the function was called in C code (i.e. not
3638
   from generated code or from helper.c) */
3639
/* XXX: fix it to restore all registers */
3640
void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
3641
{
3642
    int ret;
3643
    CPUState *saved_env;
3644

    
3645
    /* XXX: hack to restore env in all cases, even if not called from
3646
       generated code */
3647
    saved_env = env;
3648
    env = cpu_single_env;
3649

    
3650
    ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
3651
    if (ret) {
3652
        cpu_restore_state2(retaddr);
3653
        cpu_loop_exit();
3654
    }
3655
    env = saved_env;
3656
}
3657

    
3658
#endif
3659

    
3660
#ifndef TARGET_SPARC64
3661
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
3662
                          int is_asi, int size)
3663
{
3664
    CPUState *saved_env;
3665

    
3666
    /* XXX: hack to restore env in all cases, even if not called from
3667
       generated code */
3668
    saved_env = env;
3669
    env = cpu_single_env;
3670
#ifdef DEBUG_UNASSIGNED
3671
    if (is_asi)
3672
        printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
3673
               " asi 0x%02x from " TARGET_FMT_lx "\n",
3674
               is_exec ? "exec" : is_write ? "write" : "read", size,
3675
               size == 1 ? "" : "s", addr, is_asi, env->pc);
3676
    else
3677
        printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
3678
               " from " TARGET_FMT_lx "\n",
3679
               is_exec ? "exec" : is_write ? "write" : "read", size,
3680
               size == 1 ? "" : "s", addr, env->pc);
3681
#endif
3682
    if (env->mmuregs[3]) /* Fault status register */
3683
        env->mmuregs[3] = 1; /* overflow (not read before another fault) */
3684
    if (is_asi)
3685
        env->mmuregs[3] |= 1 << 16;
3686
    if (env->psrs)
3687
        env->mmuregs[3] |= 1 << 5;
3688
    if (is_exec)
3689
        env->mmuregs[3] |= 1 << 6;
3690
    if (is_write)
3691
        env->mmuregs[3] |= 1 << 7;
3692
    env->mmuregs[3] |= (5 << 2) | 2;
3693
    env->mmuregs[4] = addr; /* Fault address register */
3694
    if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
3695
        if (is_exec)
3696
            raise_exception(TT_CODE_ACCESS);
3697
        else
3698
            raise_exception(TT_DATA_ACCESS);
3699
    }
3700
    env = saved_env;
3701
}
3702
#else
3703
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
3704
                          int is_asi, int size)
3705
{
3706
#ifdef DEBUG_UNASSIGNED
3707
    CPUState *saved_env;
3708

    
3709
    /* XXX: hack to restore env in all cases, even if not called from
3710
       generated code */
3711
    saved_env = env;
3712
    env = cpu_single_env;
3713
    printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx
3714
           "\n", addr, env->pc);
3715
    env = saved_env;
3716
#endif
3717
    if (is_exec)
3718
        raise_exception(TT_CODE_ACCESS);
3719
    else
3720
        raise_exception(TT_DATA_ACCESS);
3721
}
3722
#endif
3723

    
3724
#ifdef TARGET_SPARC64
3725
void helper_tick_set_count(void *opaque, uint64_t count)
3726
{
3727
#if !defined(CONFIG_USER_ONLY)
3728
    cpu_tick_set_count(opaque, count);
3729
#endif
3730
}
3731

    
3732
uint64_t helper_tick_get_count(void *opaque)
3733
{
3734
#if !defined(CONFIG_USER_ONLY)
3735
    return cpu_tick_get_count(opaque);
3736
#else
3737
    return 0;
3738
#endif
3739
}
3740

    
3741
void helper_tick_set_limit(void *opaque, uint64_t limit)
3742
{
3743
#if !defined(CONFIG_USER_ONLY)
3744
    cpu_tick_set_limit(opaque, limit);
3745
#endif
3746
}
3747
#endif