Statistics
| Branch: | Revision:

root / target-sparc / op_helper.c @ 99a0949b

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((a_target_phys_addr)addr
1518
                            | ((a_target_phys_addr)(asi & 0xf) << 32));
1519
            break;
1520
        case 2:
1521
            ret = lduw_phys((a_target_phys_addr)addr
1522
                            | ((a_target_phys_addr)(asi & 0xf) << 32));
1523
            break;
1524
        default:
1525
        case 4:
1526
            ret = ldl_phys((a_target_phys_addr)addr
1527
                           | ((a_target_phys_addr)(asi & 0xf) << 32));
1528
            break;
1529
        case 8:
1530
            ret = ldq_phys((a_target_phys_addr)addr
1531
                           | ((a_target_phys_addr)(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((a_target_phys_addr)addr
1869
                         | ((a_target_phys_addr)(asi & 0xf) << 32), val);
1870
                break;
1871
            case 2:
1872
                stw_phys((a_target_phys_addr)addr
1873
                         | ((a_target_phys_addr)(asi & 0xf) << 32), val);
1874
                break;
1875
            case 4:
1876
            default:
1877
                stl_phys((a_target_phys_addr)addr
1878
                         | ((a_target_phys_addr)(asi & 0xf) << 32), val);
1879
                break;
1880
            case 8:
1881
                stq_phys((a_target_phys_addr)addr
1882
                         | ((a_target_phys_addr)(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
    asi &= 0xff;
2116

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

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

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

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

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

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

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

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

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

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

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

    
2406
void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
2407
{
2408
#ifdef DEBUG_ASI
2409
    dump_asi("write", addr, asi, size, val);
2410
#endif
2411

    
2412
    asi &= 0xff;
2413

    
2414
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
2415
        || ((env->def->features & CPU_FEATURE_HYPV)
2416
            && asi >= 0x30 && asi < 0x80
2417
            && !(env->hpstate & HS_PRIV)))
2418
        raise_exception(TT_PRIV_ACT);
2419

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

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

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

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

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

    
2611
            unsigned int i = (addr >> 3) & 0x3f;
2612

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

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

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

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

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

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

    
2725
void helper_ldda_asi(target_ulong addr, int asi, int rd)
2726
{
2727
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
2728
        || ((env->def->features & CPU_FEATURE_HYPV)
2729
            && asi >= 0x30 && asi < 0x80
2730
            && !(env->hpstate & HS_PRIV)))
2731
        raise_exception(TT_PRIV_ACT);
2732

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

    
2772
void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
2773
{
2774
    unsigned int i;
2775
    target_ulong val;
2776

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

    
2794
        return;
2795
    default:
2796
        break;
2797
    }
2798

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

    
2814
void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
2815
{
2816
    unsigned int i;
2817
    target_ulong val = 0;
2818

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

    
2838
        return;
2839
    default:
2840
        break;
2841
    }
2842

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

    
2858
target_ulong helper_cas_asi(target_ulong addr, target_ulong val1,
2859
                            target_ulong val2, uint32_t asi)
2860
{
2861
    target_ulong ret;
2862

    
2863
    val2 &= 0xffffffffUL;
2864
    ret = helper_ld_asi(addr, asi, 4, 0);
2865
    ret &= 0xffffffffUL;
2866
    if (val2 == ret)
2867
        helper_st_asi(addr, val1 & 0xffffffffUL, asi, 4);
2868
    return ret;
2869
}
2870

    
2871
target_ulong helper_casx_asi(target_ulong addr, target_ulong val1,
2872
                             target_ulong val2, uint32_t asi)
2873
{
2874
    target_ulong ret;
2875

    
2876
    ret = helper_ld_asi(addr, asi, 8, 0);
2877
    if (val2 == ret)
2878
        helper_st_asi(addr, val1, asi, 8);
2879
    return ret;
2880
}
2881
#endif /* TARGET_SPARC64 */
2882

    
2883
#ifndef TARGET_SPARC64
2884
void helper_rett(void)
2885
{
2886
    unsigned int cwp;
2887

    
2888
    if (env->psret == 1)
2889
        raise_exception(TT_ILL_INSN);
2890

    
2891
    env->psret = 1;
2892
    cwp = cpu_cwp_inc(env, env->cwp + 1) ;
2893
    if (env->wim & (1 << cwp)) {
2894
        raise_exception(TT_WIN_UNF);
2895
    }
2896
    set_cwp(cwp);
2897
    env->psrs = env->psrps;
2898
}
2899
#endif
2900

    
2901
target_ulong helper_udiv(target_ulong a, target_ulong b)
2902
{
2903
    uint64_t x0;
2904
    uint32_t x1;
2905

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

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

    
2913
    x0 = x0 / x1;
2914
    if (x0 > 0xffffffff) {
2915
        env->cc_src2 = 1;
2916
        return 0xffffffff;
2917
    } else {
2918
        env->cc_src2 = 0;
2919
        return x0;
2920
    }
2921
}
2922

    
2923
target_ulong helper_sdiv(target_ulong a, target_ulong b)
2924
{
2925
    int64_t x0;
2926
    int32_t x1;
2927

    
2928
    x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
2929
    x1 = b;
2930

    
2931
    if (x1 == 0) {
2932
        raise_exception(TT_DIV_ZERO);
2933
    }
2934

    
2935
    x0 = x0 / x1;
2936
    if ((int32_t) x0 != x0) {
2937
        env->cc_src2 = 1;
2938
        return x0 < 0? 0x80000000: 0x7fffffff;
2939
    } else {
2940
        env->cc_src2 = 0;
2941
        return x0;
2942
    }
2943
}
2944

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

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

    
2995
void helper_ldqf(target_ulong addr, int mem_idx)
2996
{
2997
    // XXX add 128 bit load
2998
    CPU_QuadU u;
2999

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

    
3031
void helper_stqf(target_ulong addr, int mem_idx)
3032
{
3033
    // XXX add 128 bit store
3034
    CPU_QuadU u;
3035

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

    
3067
static inline void set_fsr(void)
3068
{
3069
    int rnd_mode;
3070

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

    
3089
void helper_ldfsr(uint32_t new_fsr)
3090
{
3091
    env->fsr = (new_fsr & FSR_LDFSR_MASK) | (env->fsr & FSR_LDFSR_OLDMASK);
3092
    set_fsr();
3093
}
3094

    
3095
#ifdef TARGET_SPARC64
3096
void helper_ldxfsr(uint64_t new_fsr)
3097
{
3098
    env->fsr = (new_fsr & FSR_LDXFSR_MASK) | (env->fsr & FSR_LDXFSR_OLDMASK);
3099
    set_fsr();
3100
}
3101
#endif
3102

    
3103
void helper_debug(void)
3104
{
3105
    env->exception_index = EXCP_DEBUG;
3106
    cpu_loop_exit();
3107
}
3108

    
3109
#ifndef TARGET_SPARC64
3110
/* XXX: use another pointer for %iN registers to avoid slow wrapping
3111
   handling ? */
3112
void helper_save(void)
3113
{
3114
    uint32_t cwp;
3115

    
3116
    cwp = cpu_cwp_dec(env, env->cwp - 1);
3117
    if (env->wim & (1 << cwp)) {
3118
        raise_exception(TT_WIN_OVF);
3119
    }
3120
    set_cwp(cwp);
3121
}
3122

    
3123
void helper_restore(void)
3124
{
3125
    uint32_t cwp;
3126

    
3127
    cwp = cpu_cwp_inc(env, env->cwp + 1);
3128
    if (env->wim & (1 << cwp)) {
3129
        raise_exception(TT_WIN_UNF);
3130
    }
3131
    set_cwp(cwp);
3132
}
3133

    
3134
void helper_wrpsr(target_ulong new_psr)
3135
{
3136
    if ((new_psr & PSR_CWP) >= env->nwindows)
3137
        raise_exception(TT_ILL_INSN);
3138
    else
3139
        PUT_PSR(env, new_psr);
3140
}
3141

    
3142
target_ulong helper_rdpsr(void)
3143
{
3144
    return GET_PSR(env);
3145
}
3146

    
3147
#else
3148
/* XXX: use another pointer for %iN registers to avoid slow wrapping
3149
   handling ? */
3150
void helper_save(void)
3151
{
3152
    uint32_t cwp;
3153

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

    
3171
void helper_restore(void)
3172
{
3173
    uint32_t cwp;
3174

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

    
3187
void helper_flushw(void)
3188
{
3189
    if (env->cansave != env->nwindows - 2) {
3190
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
3191
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
3192
                                    ((env->wstate & 0x7) << 2)));
3193
    }
3194
}
3195

    
3196
void helper_saved(void)
3197
{
3198
    env->cansave++;
3199
    if (env->otherwin == 0)
3200
        env->canrestore--;
3201
    else
3202
        env->otherwin--;
3203
}
3204

    
3205
void helper_restored(void)
3206
{
3207
    env->canrestore++;
3208
    if (env->cleanwin < env->nwindows - 1)
3209
        env->cleanwin++;
3210
    if (env->otherwin == 0)
3211
        env->cansave--;
3212
    else
3213
        env->otherwin--;
3214
}
3215

    
3216
target_ulong helper_rdccr(void)
3217
{
3218
    return GET_CCR(env);
3219
}
3220

    
3221
void helper_wrccr(target_ulong new_ccr)
3222
{
3223
    PUT_CCR(env, new_ccr);
3224
}
3225

    
3226
// CWP handling is reversed in V9, but we still use the V8 register
3227
// order.
3228
target_ulong helper_rdcwp(void)
3229
{
3230
    return GET_CWP64(env);
3231
}
3232

    
3233
void helper_wrcwp(target_ulong new_cwp)
3234
{
3235
    PUT_CWP64(env, new_cwp);
3236
}
3237

    
3238
// This function uses non-native bit order
3239
#define GET_FIELD(X, FROM, TO)                                  \
3240
    ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
3241

    
3242
// This function uses the order in the manuals, i.e. bit 0 is 2^0
3243
#define GET_FIELD_SP(X, FROM, TO)               \
3244
    GET_FIELD(X, 63 - (TO), 63 - (FROM))
3245

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

    
3259
target_ulong helper_alignaddr(target_ulong addr, target_ulong offset)
3260
{
3261
    uint64_t tmp;
3262

    
3263
    tmp = addr + offset;
3264
    env->gsr &= ~7ULL;
3265
    env->gsr |= tmp & 7ULL;
3266
    return tmp & ~7ULL;
3267
}
3268

    
3269
target_ulong helper_popc(target_ulong val)
3270
{
3271
    return ctpop64(val);
3272
}
3273

    
3274
static inline uint64_t *get_gregset(uint64_t pstate)
3275
{
3276
    switch (pstate) {
3277
    default:
3278
    case 0:
3279
        return env->bgregs;
3280
    case PS_AG:
3281
        return env->agregs;
3282
    case PS_MG:
3283
        return env->mgregs;
3284
    case PS_IG:
3285
        return env->igregs;
3286
    }
3287
}
3288

    
3289
static inline void change_pstate(uint64_t new_pstate)
3290
{
3291
    uint64_t pstate_regs, new_pstate_regs;
3292
    uint64_t *src, *dst;
3293

    
3294
    if (env->def->features & CPU_FEATURE_GL) {
3295
        // PS_AG is not implemented in this case
3296
        new_pstate &= ~PS_AG;
3297
    }
3298

    
3299
    pstate_regs = env->pstate & 0xc01;
3300
    new_pstate_regs = new_pstate & 0xc01;
3301

    
3302
    if (new_pstate_regs != pstate_regs) {
3303
        // Switch global register bank
3304
        src = get_gregset(new_pstate_regs);
3305
        dst = get_gregset(pstate_regs);
3306
        memcpy32(dst, env->gregs);
3307
        memcpy32(env->gregs, src);
3308
    }
3309
    env->pstate = new_pstate;
3310
}
3311

    
3312
void helper_wrpstate(target_ulong new_state)
3313
{
3314
    change_pstate(new_state & 0xf3f);
3315
}
3316

    
3317
void helper_done(void)
3318
{
3319
    trap_state* tsptr = cpu_tsptr(env);
3320

    
3321
    env->pc = tsptr->tpc;
3322
    env->npc = tsptr->tnpc + 4;
3323
    PUT_CCR(env, tsptr->tstate >> 32);
3324
    env->asi = (tsptr->tstate >> 24) & 0xff;
3325
    change_pstate((tsptr->tstate >> 8) & 0xf3f);
3326
    PUT_CWP64(env, tsptr->tstate & 0xff);
3327
    env->tl--;
3328
}
3329

    
3330
void helper_retry(void)
3331
{
3332
    trap_state* tsptr = cpu_tsptr(env);
3333

    
3334
    env->pc = tsptr->tpc;
3335
    env->npc = tsptr->tnpc;
3336
    PUT_CCR(env, tsptr->tstate >> 32);
3337
    env->asi = (tsptr->tstate >> 24) & 0xff;
3338
    change_pstate((tsptr->tstate >> 8) & 0xf3f);
3339
    PUT_CWP64(env, tsptr->tstate & 0xff);
3340
    env->tl--;
3341
}
3342

    
3343
void helper_set_softint(uint64_t value)
3344
{
3345
    env->softint |= (uint32_t)value;
3346
}
3347

    
3348
void helper_clear_softint(uint64_t value)
3349
{
3350
    env->softint &= (uint32_t)~value;
3351
}
3352

    
3353
void helper_write_softint(uint64_t value)
3354
{
3355
    env->softint = (uint32_t)value;
3356
}
3357
#endif
3358

    
3359
void helper_flush(target_ulong addr)
3360
{
3361
    addr &= ~7;
3362
    tb_invalidate_page_range(addr, addr + 8);
3363
}
3364

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

    
3402
trap_state* cpu_tsptr(CPUState* env)
3403
{
3404
    return &env->ts[env->tl & MAXTL_MASK];
3405
}
3406

    
3407
void do_interrupt(CPUState *env)
3408
{
3409
    int intno = env->exception_index;
3410
    trap_state* tsptr;
3411

    
3412
#ifdef DEBUG_PCALL
3413
    if (qemu_loglevel_mask(CPU_LOG_INT)) {
3414
        static int count;
3415
        const char *name;
3416

    
3417
        if (intno < 0 || intno >= 0x180)
3418
            name = "Unknown";
3419
        else if (intno >= 0x100)
3420
            name = "Trap Instruction";
3421
        else if (intno >= 0xc0)
3422
            name = "Window Fill";
3423
        else if (intno >= 0x80)
3424
            name = "Window Spill";
3425
        else {
3426
            name = excp_names[intno];
3427
            if (!name)
3428
                name = "Unknown";
3429
        }
3430

    
3431
        qemu_log("%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
3432
                " SP=%016" PRIx64 "\n",
3433
                count, name, intno,
3434
                env->pc,
3435
                env->npc, env->regwptr[6]);
3436
        log_cpu_state(env, 0);
3437
#if 0
3438
        {
3439
            int i;
3440
            uint8_t *ptr;
3441

3442
            qemu_log("       code=");
3443
            ptr = (uint8_t *)env->pc;
3444
            for(i = 0; i < 16; i++) {
3445
                qemu_log(" %02x", ldub(ptr + i));
3446
            }
3447
            qemu_log("\n");
3448
        }
3449
#endif
3450
        count++;
3451
    }
3452
#endif
3453
#if !defined(CONFIG_USER_ONLY)
3454
    if (env->tl >= env->maxtl) {
3455
        cpu_abort(env, "Trap 0x%04x while trap level (%d) >= MAXTL (%d),"
3456
                  " Error state", env->exception_index, env->tl, env->maxtl);
3457
        return;
3458
    }
3459
#endif
3460
    if (env->tl < env->maxtl - 1) {
3461
        env->tl++;
3462
    } else {
3463
        env->pstate |= PS_RED;
3464
        if (env->tl < env->maxtl)
3465
            env->tl++;
3466
    }
3467
    tsptr = cpu_tsptr(env);
3468

    
3469
    tsptr->tstate = ((uint64_t)GET_CCR(env) << 32) |
3470
        ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
3471
        GET_CWP64(env);
3472
    tsptr->tpc = env->pc;
3473
    tsptr->tnpc = env->npc;
3474
    tsptr->tt = intno;
3475

    
3476
    switch (intno) {
3477
    case TT_IVEC:
3478
        change_pstate(PS_PEF | PS_PRIV | PS_IG);
3479
        break;
3480
    case TT_TFAULT:
3481
    case TT_TMISS:
3482
    case TT_DFAULT:
3483
    case TT_DMISS:
3484
    case TT_DPROT:
3485
        change_pstate(PS_PEF | PS_PRIV | PS_MG);
3486
        break;
3487
    default:
3488
        change_pstate(PS_PEF | PS_PRIV | PS_AG);
3489
        break;
3490
    }
3491

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

    
3540
void do_interrupt(CPUState *env)
3541
{
3542
    int cwp, intno = env->exception_index;
3543

    
3544
#ifdef DEBUG_PCALL
3545
    if (qemu_loglevel_mask(CPU_LOG_INT)) {
3546
        static int count;
3547
        const char *name;
3548

    
3549
        if (intno < 0 || intno >= 0x100)
3550
            name = "Unknown";
3551
        else if (intno >= 0x80)
3552
            name = "Trap Instruction";
3553
        else {
3554
            name = excp_names[intno];
3555
            if (!name)
3556
                name = "Unknown";
3557
        }
3558

    
3559
        qemu_log("%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
3560
                count, name, intno,
3561
                env->pc,
3562
                env->npc, env->regwptr[6]);
3563
        log_cpu_state(env, 0);
3564
#if 0
3565
        {
3566
            int i;
3567
            uint8_t *ptr;
3568

3569
            qemu_log("       code=");
3570
            ptr = (uint8_t *)env->pc;
3571
            for(i = 0; i < 16; i++) {
3572
                qemu_log(" %02x", ldub(ptr + i));
3573
            }
3574
            qemu_log("\n");
3575
        }
3576
#endif
3577
        count++;
3578
    }
3579
#endif
3580
#if !defined(CONFIG_USER_ONLY)
3581
    if (env->psret == 0) {
3582
        cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
3583
                  env->exception_index);
3584
        return;
3585
    }
3586
#endif
3587
    env->psret = 0;
3588
    cwp = cpu_cwp_dec(env, env->cwp - 1);
3589
    cpu_set_cwp(env, cwp);
3590
    env->regwptr[9] = env->pc;
3591
    env->regwptr[10] = env->npc;
3592
    env->psrps = env->psrs;
3593
    env->psrs = 1;
3594
    env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
3595
    env->pc = env->tbr;
3596
    env->npc = env->pc + 4;
3597
    env->exception_index = 0;
3598
}
3599
#endif
3600

    
3601
#if !defined(CONFIG_USER_ONLY)
3602

    
3603
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
3604
                                void *retaddr);
3605

    
3606
#define MMUSUFFIX _mmu
3607
#define ALIGNED_ONLY
3608

    
3609
#define SHIFT 0
3610
#include "softmmu_template.h"
3611

    
3612
#define SHIFT 1
3613
#include "softmmu_template.h"
3614

    
3615
#define SHIFT 2
3616
#include "softmmu_template.h"
3617

    
3618
#define SHIFT 3
3619
#include "softmmu_template.h"
3620

    
3621
/* XXX: make it generic ? */
3622
static void cpu_restore_state2(void *retaddr)
3623
{
3624
    TranslationBlock *tb;
3625
    unsigned long pc;
3626

    
3627
    if (retaddr) {
3628
        /* now we have a real cpu fault */
3629
        pc = (unsigned long)retaddr;
3630
        tb = tb_find_pc(pc);
3631
        if (tb) {
3632
            /* the PC is inside the translated code. It means that we have
3633
               a virtual CPU fault */
3634
            cpu_restore_state(tb, env, pc, (void *)(long)env->cond);
3635
        }
3636
    }
3637
}
3638

    
3639
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
3640
                                void *retaddr)
3641
{
3642
#ifdef DEBUG_UNALIGNED
3643
    printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
3644
           "\n", addr, env->pc);
3645
#endif
3646
    cpu_restore_state2(retaddr);
3647
    raise_exception(TT_UNALIGNED);
3648
}
3649

    
3650
/* try to fill the TLB and return an exception if error. If retaddr is
3651
   NULL, it means that the function was called in C code (i.e. not
3652
   from generated code or from helper.c) */
3653
/* XXX: fix it to restore all registers */
3654
void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
3655
{
3656
    int ret;
3657
    CPUState *saved_env;
3658

    
3659
    /* XXX: hack to restore env in all cases, even if not called from
3660
       generated code */
3661
    saved_env = env;
3662
    env = cpu_single_env;
3663

    
3664
    ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
3665
    if (ret) {
3666
        cpu_restore_state2(retaddr);
3667
        cpu_loop_exit();
3668
    }
3669
    env = saved_env;
3670
}
3671

    
3672
#endif
3673

    
3674
#ifndef TARGET_SPARC64
3675
void do_unassigned_access(a_target_phys_addr addr, int is_write, int is_exec,
3676
                          int is_asi, int size)
3677
{
3678
    CPUState *saved_env;
3679

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

    
3723
    /* XXX: hack to restore env in all cases, even if not called from
3724
       generated code */
3725
    saved_env = env;
3726
    env = cpu_single_env;
3727
    printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx
3728
           "\n", addr, env->pc);
3729
    env = saved_env;
3730
#endif
3731
    if (is_exec)
3732
        raise_exception(TT_CODE_ACCESS);
3733
    else
3734
        raise_exception(TT_DATA_ACCESS);
3735
}
3736
#endif
3737

    
3738
#ifdef TARGET_SPARC64
3739
void helper_tick_set_count(void *opaque, uint64_t count)
3740
{
3741
#if !defined(CONFIG_USER_ONLY)
3742
    cpu_tick_set_count(opaque, count);
3743
#endif
3744
}
3745

    
3746
uint64_t helper_tick_get_count(void *opaque)
3747
{
3748
#if !defined(CONFIG_USER_ONLY)
3749
    return cpu_tick_get_count(opaque);
3750
#else
3751
    return 0;
3752
#endif
3753
}
3754

    
3755
void helper_tick_set_limit(void *opaque, uint64_t limit)
3756
{
3757
#if !defined(CONFIG_USER_ONLY)
3758
    cpu_tick_set_limit(opaque, limit);
3759
#endif
3760
}
3761
#endif