Statistics
| Branch: | Revision:

root / target-sparc / op_helper.c @ 3c7b48b7

History | View | Annotate | Download (104.9 kB)

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

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

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

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

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

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

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

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

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

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

    
68
    // now reorder bits
69
    uint64_t tsb_base_mask = ~0x1fffULL;
70
    uint64_t va = tag_access_va;
71

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

    
79
    if (tsb_size) {
80
        tsb_base_mask <<= tsb_size;
81
    }
82

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

    
93
    return ((tsb_base & tsb_base_mask) | (va & ~tsb_base_mask)) & ~0xfULL;
94
}
95

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

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

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

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

    
116
        va = tlb->tag & mask;
117

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

    
123
    tlb->tag = tlb_tag;
124
    tlb->tte = tlb_tte;
125
}
126

    
127
static void demap_tlb(SparcTLBEntry *tlb, target_ulong demap_addr,
128
                      const char* strmmu, CPUState *env1)
129
{
130
    unsigned int i;
131
    target_ulong mask;
132

    
133
    for (i = 0; i < 64; i++) {
134
        if (TTE_IS_VALID(tlb[i].tte)) {
135

    
136
            mask = 0xffffffffffffe000ULL;
137
            mask <<= 3 * ((tlb[i].tte >> 61) & 3);
138

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

    
150
}
151

    
152
static void replace_tlb_1bit_lru(SparcTLBEntry *tlb,
153
                                 uint64_t tlb_tag, uint64_t tlb_tte,
154
                                 const char* strmmu, CPUState *env1)
155
{
156
    unsigned int i, replace_used;
157

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

    
170
    // All entries are valid, try replacing unlocked entry
171

    
172
    for (replace_used = 0; replace_used < 2; ++replace_used) {
173

    
174
        // Used entries are not replaced on first pass
175

    
176
        for (i = 0; i < 64; i++) {
177
            if (!TTE_IS_LOCKED(tlb[i].tte) && !TTE_IS_USED(tlb[i].tte)) {
178

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

    
189
        // Now reset used bit and search for unused entries again
190

    
191
        for (i = 0; i < 64; i++) {
192
            TTE_SET_UNUSED(tlb[i].tte);
193
        }
194
    }
195

    
196
#ifdef DEBUG_MMU
197
    DPRINTF_MMU("%s lru replacement failed: no entries available\n", strmmu);
198
#endif
199
    // error state?
200
}
201

    
202
#endif
203

    
204
static inline void address_mask(CPUState *env1, target_ulong *addr)
205
{
206
#ifdef TARGET_SPARC64
207
    if (AM_CHECK(env1))
208
        *addr &= 0xffffffffULL;
209
#endif
210
}
211

    
212
static void raise_exception(int tt)
213
{
214
    env->exception_index = tt;
215
    cpu_loop_exit();
216
}
217

    
218
void HELPER(raise_exception)(int tt)
219
{
220
    raise_exception(tt);
221
}
222

    
223
static inline void set_cwp(int new_cwp)
224
{
225
    cpu_set_cwp(env, new_cwp);
226
}
227

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

    
239
#define F_HELPER(name, p) void helper_f##name##p(void)
240

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

    
255
F_BINOP(add);
256
F_BINOP(sub);
257
F_BINOP(mul);
258
F_BINOP(div);
259
#undef F_BINOP
260

    
261
void helper_fsmuld(float32 src1, float32 src2)
262
{
263
    DT0 = float64_mul(float32_to_float64(src1, &env->fp_status),
264
                      float32_to_float64(src2, &env->fp_status),
265
                      &env->fp_status);
266
}
267

    
268
void helper_fdmulq(void)
269
{
270
    QT0 = float128_mul(float64_to_float128(DT0, &env->fp_status),
271
                       float64_to_float128(DT1, &env->fp_status),
272
                       &env->fp_status);
273
}
274

    
275
float32 helper_fnegs(float32 src)
276
{
277
    return float32_chs(src);
278
}
279

    
280
#ifdef TARGET_SPARC64
281
F_HELPER(neg, d)
282
{
283
    DT0 = float64_chs(DT1);
284
}
285

    
286
F_HELPER(neg, q)
287
{
288
    QT0 = float128_chs(QT1);
289
}
290
#endif
291

    
292
/* Integer to float conversion.  */
293
float32 helper_fitos(int32_t src)
294
{
295
    return int32_to_float32(src, &env->fp_status);
296
}
297

    
298
void helper_fitod(int32_t src)
299
{
300
    DT0 = int32_to_float64(src, &env->fp_status);
301
}
302

    
303
void helper_fitoq(int32_t src)
304
{
305
    QT0 = int32_to_float128(src, &env->fp_status);
306
}
307

    
308
#ifdef TARGET_SPARC64
309
float32 helper_fxtos(void)
310
{
311
    return int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
312
}
313

    
314
F_HELPER(xto, d)
315
{
316
    DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
317
}
318

    
319
F_HELPER(xto, q)
320
{
321
    QT0 = int64_to_float128(*((int64_t *)&DT1), &env->fp_status);
322
}
323
#endif
324
#undef F_HELPER
325

    
326
/* floating point conversion */
327
float32 helper_fdtos(void)
328
{
329
    return float64_to_float32(DT1, &env->fp_status);
330
}
331

    
332
void helper_fstod(float32 src)
333
{
334
    DT0 = float32_to_float64(src, &env->fp_status);
335
}
336

    
337
float32 helper_fqtos(void)
338
{
339
    return float128_to_float32(QT1, &env->fp_status);
340
}
341

    
342
void helper_fstoq(float32 src)
343
{
344
    QT0 = float32_to_float128(src, &env->fp_status);
345
}
346

    
347
void helper_fqtod(void)
348
{
349
    DT0 = float128_to_float64(QT1, &env->fp_status);
350
}
351

    
352
void helper_fdtoq(void)
353
{
354
    QT0 = float64_to_float128(DT1, &env->fp_status);
355
}
356

    
357
/* Float to integer conversion.  */
358
int32_t helper_fstoi(float32 src)
359
{
360
    return float32_to_int32_round_to_zero(src, &env->fp_status);
361
}
362

    
363
int32_t helper_fdtoi(void)
364
{
365
    return float64_to_int32_round_to_zero(DT1, &env->fp_status);
366
}
367

    
368
int32_t helper_fqtoi(void)
369
{
370
    return float128_to_int32_round_to_zero(QT1, &env->fp_status);
371
}
372

    
373
#ifdef TARGET_SPARC64
374
void helper_fstox(float32 src)
375
{
376
    *((int64_t *)&DT0) = float32_to_int64_round_to_zero(src, &env->fp_status);
377
}
378

    
379
void helper_fdtox(void)
380
{
381
    *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status);
382
}
383

    
384
void helper_fqtox(void)
385
{
386
    *((int64_t *)&DT0) = float128_to_int64_round_to_zero(QT1, &env->fp_status);
387
}
388

    
389
void helper_faligndata(void)
390
{
391
    uint64_t tmp;
392

    
393
    tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8);
394
    /* on many architectures a shift of 64 does nothing */
395
    if ((env->gsr & 7) != 0) {
396
        tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8);
397
    }
398
    *((uint64_t *)&DT0) = tmp;
399
}
400

    
401
#ifdef HOST_WORDS_BIGENDIAN
402
#define VIS_B64(n) b[7 - (n)]
403
#define VIS_W64(n) w[3 - (n)]
404
#define VIS_SW64(n) sw[3 - (n)]
405
#define VIS_L64(n) l[1 - (n)]
406
#define VIS_B32(n) b[3 - (n)]
407
#define VIS_W32(n) w[1 - (n)]
408
#else
409
#define VIS_B64(n) b[n]
410
#define VIS_W64(n) w[n]
411
#define VIS_SW64(n) sw[n]
412
#define VIS_L64(n) l[n]
413
#define VIS_B32(n) b[n]
414
#define VIS_W32(n) w[n]
415
#endif
416

    
417
typedef union {
418
    uint8_t b[8];
419
    uint16_t w[4];
420
    int16_t sw[4];
421
    uint32_t l[2];
422
    float64 d;
423
} vis64;
424

    
425
typedef union {
426
    uint8_t b[4];
427
    uint16_t w[2];
428
    uint32_t l;
429
    float32 f;
430
} vis32;
431

    
432
void helper_fpmerge(void)
433
{
434
    vis64 s, d;
435

    
436
    s.d = DT0;
437
    d.d = DT1;
438

    
439
    // Reverse calculation order to handle overlap
440
    d.VIS_B64(7) = s.VIS_B64(3);
441
    d.VIS_B64(6) = d.VIS_B64(3);
442
    d.VIS_B64(5) = s.VIS_B64(2);
443
    d.VIS_B64(4) = d.VIS_B64(2);
444
    d.VIS_B64(3) = s.VIS_B64(1);
445
    d.VIS_B64(2) = d.VIS_B64(1);
446
    d.VIS_B64(1) = s.VIS_B64(0);
447
    //d.VIS_B64(0) = d.VIS_B64(0);
448

    
449
    DT0 = d.d;
450
}
451

    
452
void helper_fmul8x16(void)
453
{
454
    vis64 s, d;
455
    uint32_t tmp;
456

    
457
    s.d = DT0;
458
    d.d = DT1;
459

    
460
#define PMUL(r)                                                 \
461
    tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r);       \
462
    if ((tmp & 0xff) > 0x7f)                                    \
463
        tmp += 0x100;                                           \
464
    d.VIS_W64(r) = tmp >> 8;
465

    
466
    PMUL(0);
467
    PMUL(1);
468
    PMUL(2);
469
    PMUL(3);
470
#undef PMUL
471

    
472
    DT0 = d.d;
473
}
474

    
475
void helper_fmul8x16al(void)
476
{
477
    vis64 s, d;
478
    uint32_t tmp;
479

    
480
    s.d = DT0;
481
    d.d = DT1;
482

    
483
#define PMUL(r)                                                 \
484
    tmp = (int32_t)d.VIS_SW64(1) * (int32_t)s.VIS_B64(r);       \
485
    if ((tmp & 0xff) > 0x7f)                                    \
486
        tmp += 0x100;                                           \
487
    d.VIS_W64(r) = tmp >> 8;
488

    
489
    PMUL(0);
490
    PMUL(1);
491
    PMUL(2);
492
    PMUL(3);
493
#undef PMUL
494

    
495
    DT0 = d.d;
496
}
497

    
498
void helper_fmul8x16au(void)
499
{
500
    vis64 s, d;
501
    uint32_t tmp;
502

    
503
    s.d = DT0;
504
    d.d = DT1;
505

    
506
#define PMUL(r)                                                 \
507
    tmp = (int32_t)d.VIS_SW64(0) * (int32_t)s.VIS_B64(r);       \
508
    if ((tmp & 0xff) > 0x7f)                                    \
509
        tmp += 0x100;                                           \
510
    d.VIS_W64(r) = tmp >> 8;
511

    
512
    PMUL(0);
513
    PMUL(1);
514
    PMUL(2);
515
    PMUL(3);
516
#undef PMUL
517

    
518
    DT0 = d.d;
519
}
520

    
521
void helper_fmul8sux16(void)
522
{
523
    vis64 s, d;
524
    uint32_t tmp;
525

    
526
    s.d = DT0;
527
    d.d = DT1;
528

    
529
#define PMUL(r)                                                         \
530
    tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
531
    if ((tmp & 0xff) > 0x7f)                                            \
532
        tmp += 0x100;                                                   \
533
    d.VIS_W64(r) = tmp >> 8;
534

    
535
    PMUL(0);
536
    PMUL(1);
537
    PMUL(2);
538
    PMUL(3);
539
#undef PMUL
540

    
541
    DT0 = d.d;
542
}
543

    
544
void helper_fmul8ulx16(void)
545
{
546
    vis64 s, d;
547
    uint32_t tmp;
548

    
549
    s.d = DT0;
550
    d.d = DT1;
551

    
552
#define PMUL(r)                                                         \
553
    tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
554
    if ((tmp & 0xff) > 0x7f)                                            \
555
        tmp += 0x100;                                                   \
556
    d.VIS_W64(r) = tmp >> 8;
557

    
558
    PMUL(0);
559
    PMUL(1);
560
    PMUL(2);
561
    PMUL(3);
562
#undef PMUL
563

    
564
    DT0 = d.d;
565
}
566

    
567
void helper_fmuld8sux16(void)
568
{
569
    vis64 s, d;
570
    uint32_t tmp;
571

    
572
    s.d = DT0;
573
    d.d = DT1;
574

    
575
#define PMUL(r)                                                         \
576
    tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
577
    if ((tmp & 0xff) > 0x7f)                                            \
578
        tmp += 0x100;                                                   \
579
    d.VIS_L64(r) = tmp;
580

    
581
    // Reverse calculation order to handle overlap
582
    PMUL(1);
583
    PMUL(0);
584
#undef PMUL
585

    
586
    DT0 = d.d;
587
}
588

    
589
void helper_fmuld8ulx16(void)
590
{
591
    vis64 s, d;
592
    uint32_t tmp;
593

    
594
    s.d = DT0;
595
    d.d = DT1;
596

    
597
#define PMUL(r)                                                         \
598
    tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
599
    if ((tmp & 0xff) > 0x7f)                                            \
600
        tmp += 0x100;                                                   \
601
    d.VIS_L64(r) = tmp;
602

    
603
    // Reverse calculation order to handle overlap
604
    PMUL(1);
605
    PMUL(0);
606
#undef PMUL
607

    
608
    DT0 = d.d;
609
}
610

    
611
void helper_fexpand(void)
612
{
613
    vis32 s;
614
    vis64 d;
615

    
616
    s.l = (uint32_t)(*(uint64_t *)&DT0 & 0xffffffff);
617
    d.d = DT1;
618
    d.VIS_W64(0) = s.VIS_B32(0) << 4;
619
    d.VIS_W64(1) = s.VIS_B32(1) << 4;
620
    d.VIS_W64(2) = s.VIS_B32(2) << 4;
621
    d.VIS_W64(3) = s.VIS_B32(3) << 4;
622

    
623
    DT0 = d.d;
624
}
625

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

    
680
#define FADD(a, b) ((a) + (b))
681
#define FSUB(a, b) ((a) - (b))
682
VIS_HELPER(helper_fpadd, FADD)
683
VIS_HELPER(helper_fpsub, FSUB)
684

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

    
714
#define FCMPGT(a, b) ((a) > (b))
715
#define FCMPEQ(a, b) ((a) == (b))
716
#define FCMPLE(a, b) ((a) <= (b))
717
#define FCMPNE(a, b) ((a) != (b))
718

    
719
VIS_CMPHELPER(helper_fcmpgt, FCMPGT)
720
VIS_CMPHELPER(helper_fcmpeq, FCMPEQ)
721
VIS_CMPHELPER(helper_fcmple, FCMPLE)
722
VIS_CMPHELPER(helper_fcmpne, FCMPNE)
723
#endif
724

    
725
void helper_check_ieee_exceptions(void)
726
{
727
    target_ulong status;
728

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

    
743
        if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) {
744
            /* Unmasked exception, generate a trap */
745
            env->fsr |= FSR_FTT_IEEE_EXCP;
746
            raise_exception(TT_FP_EXCP);
747
        } else {
748
            /* Accumulate exceptions */
749
            env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
750
        }
751
    }
752
}
753

    
754
void helper_clear_float_exceptions(void)
755
{
756
    set_float_exception_flags(0, &env->fp_status);
757
}
758

    
759
float32 helper_fabss(float32 src)
760
{
761
    return float32_abs(src);
762
}
763

    
764
#ifdef TARGET_SPARC64
765
void helper_fabsd(void)
766
{
767
    DT0 = float64_abs(DT1);
768
}
769

    
770
void helper_fabsq(void)
771
{
772
    QT0 = float128_abs(QT1);
773
}
774
#endif
775

    
776
float32 helper_fsqrts(float32 src)
777
{
778
    return float32_sqrt(src, &env->fp_status);
779
}
780

    
781
void helper_fsqrtd(void)
782
{
783
    DT0 = float64_sqrt(DT1, &env->fp_status);
784
}
785

    
786
void helper_fsqrtq(void)
787
{
788
    QT0 = float128_sqrt(QT1, &env->fp_status);
789
}
790

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

    
852
GEN_FCMPS(fcmps, float32, 0, 0);
853
GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
854

    
855
GEN_FCMPS(fcmpes, float32, 0, 1);
856
GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
857

    
858
GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0);
859
GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1);
860

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

    
866
static uint32_t compute_C_flags(void)
867
{
868
    return env->psr & PSR_CARRY;
869
}
870

    
871
static inline uint32_t get_NZ_icc(target_ulong dst)
872
{
873
    uint32_t ret = 0;
874

    
875
    if (!(dst & 0xffffffffULL))
876
        ret |= PSR_ZERO;
877
    if ((int32_t) (dst & 0xffffffffULL) < 0)
878
        ret |= PSR_NEG;
879
    return ret;
880
}
881

    
882
#ifdef TARGET_SPARC64
883
static uint32_t compute_all_flags_xcc(void)
884
{
885
    return env->xcc & PSR_ICC;
886
}
887

    
888
static uint32_t compute_C_flags_xcc(void)
889
{
890
    return env->xcc & PSR_CARRY;
891
}
892

    
893
static inline uint32_t get_NZ_xcc(target_ulong dst)
894
{
895
    uint32_t ret = 0;
896

    
897
    if (!dst)
898
        ret |= PSR_ZERO;
899
    if ((int64_t)dst < 0)
900
        ret |= PSR_NEG;
901
    return ret;
902
}
903
#endif
904

    
905
static inline uint32_t get_V_div_icc(target_ulong src2)
906
{
907
    uint32_t ret = 0;
908

    
909
    if (src2 != 0)
910
        ret |= PSR_OVF;
911
    return ret;
912
}
913

    
914
static uint32_t compute_all_div(void)
915
{
916
    uint32_t ret;
917

    
918
    ret = get_NZ_icc(CC_DST);
919
    ret |= get_V_div_icc(CC_SRC2);
920
    return ret;
921
}
922

    
923
static uint32_t compute_C_div(void)
924
{
925
    return 0;
926
}
927

    
928
/* carry = (src1[31] & src2[31]) | ( ~dst[31] & (src1[31] | src2[31])) */
929
static inline uint32_t get_C_add_icc(target_ulong dst, target_ulong src1,
930
                                     target_ulong src2)
931
{
932
    uint32_t ret = 0;
933

    
934
    if (((src1 & (1ULL << 31)) & (src2 & (1ULL << 31)))
935
        | ((~(dst & (1ULL << 31)))
936
           & ((src1 & (1ULL << 31)) | (src2 & (1ULL << 31)))))
937
        ret |= PSR_CARRY;
938
    return ret;
939
}
940

    
941
static inline uint32_t get_V_add_icc(target_ulong dst, target_ulong src1,
942
                                         target_ulong src2)
943
{
944
    uint32_t ret = 0;
945

    
946
    if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1ULL << 31))
947
        ret |= PSR_OVF;
948
    return ret;
949
}
950

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

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

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

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

    
971
static uint32_t compute_all_add_xcc(void)
972
{
973
    uint32_t ret;
974

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

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

    
987
static uint32_t compute_all_add(void)
988
{
989
    uint32_t ret;
990

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

    
997
static uint32_t compute_C_add(void)
998
{
999
    return get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
1000
}
1001

    
1002
#ifdef TARGET_SPARC64
1003
static uint32_t compute_all_addx_xcc(void)
1004
{
1005
    uint32_t ret;
1006

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

    
1014
static uint32_t compute_C_addx_xcc(void)
1015
{
1016
    uint32_t ret;
1017

    
1018
    ret = get_C_add_xcc(CC_DST - CC_SRC2, CC_SRC);
1019
    ret |= get_C_add_xcc(CC_DST, CC_SRC);
1020
    return ret;
1021
}
1022
#endif
1023

    
1024
static inline uint32_t get_V_tag_icc(target_ulong src1, target_ulong src2)
1025
{
1026
    uint32_t ret = 0;
1027

    
1028
    if ((src1 | src2) & 0x3)
1029
        ret |= PSR_OVF;
1030
    return ret;
1031
}
1032

    
1033
static uint32_t compute_all_tadd(void)
1034
{
1035
    uint32_t ret;
1036

    
1037
    ret = get_NZ_icc(CC_DST);
1038
    ret |= get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
1039
    ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
1040
    ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
1041
    return ret;
1042
}
1043

    
1044
static uint32_t compute_C_tadd(void)
1045
{
1046
    return get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
1047
}
1048

    
1049
static uint32_t compute_all_taddtv(void)
1050
{
1051
    uint32_t ret;
1052

    
1053
    ret = get_NZ_icc(CC_DST);
1054
    ret |= get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
1055
    return ret;
1056
}
1057

    
1058
static uint32_t compute_C_taddtv(void)
1059
{
1060
    return get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
1061
}
1062

    
1063
/* carry = (~src1[31] & src2[31]) | ( dst[31]  & (~src1[31] | src2[31])) */
1064
static inline uint32_t get_C_sub_icc(target_ulong dst, target_ulong src1,
1065
                                     target_ulong src2)
1066
{
1067
    uint32_t ret = 0;
1068

    
1069
    if (((~(src1 & (1ULL << 31))) & (src2 & (1ULL << 31)))
1070
        | ((dst & (1ULL << 31)) & (( ~(src1 & (1ULL << 31)))
1071
                                   | (src2 & (1ULL << 31)))))
1072
        ret |= PSR_CARRY;
1073
    return ret;
1074
}
1075

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

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

    
1086

    
1087
#ifdef TARGET_SPARC64
1088
static inline uint32_t get_C_sub_xcc(target_ulong src1, target_ulong src2)
1089
{
1090
    uint32_t ret = 0;
1091

    
1092
    if (src1 < src2)
1093
        ret |= PSR_CARRY;
1094
    return ret;
1095
}
1096

    
1097
static inline uint32_t get_V_sub_xcc(target_ulong dst, target_ulong src1,
1098
                                     target_ulong src2)
1099
{
1100
    uint32_t ret = 0;
1101

    
1102
    if (((src1 ^ src2) & (src1 ^ dst)) & (1ULL << 63))
1103
        ret |= PSR_OVF;
1104
    return ret;
1105
}
1106

    
1107
static uint32_t compute_all_sub_xcc(void)
1108
{
1109
    uint32_t ret;
1110

    
1111
    ret = get_NZ_xcc(CC_DST);
1112
    ret |= get_C_sub_xcc(CC_SRC, CC_SRC2);
1113
    ret |= get_V_sub_xcc(CC_DST, CC_SRC, CC_SRC2);
1114
    return ret;
1115
}
1116

    
1117
static uint32_t compute_C_sub_xcc(void)
1118
{
1119
    return get_C_sub_xcc(CC_SRC, CC_SRC2);
1120
}
1121
#endif
1122

    
1123
static uint32_t compute_all_sub(void)
1124
{
1125
    uint32_t ret;
1126

    
1127
    ret = get_NZ_icc(CC_DST);
1128
    ret |= get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1129
    ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1130
    return ret;
1131
}
1132

    
1133
static uint32_t compute_C_sub(void)
1134
{
1135
    return get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1136
}
1137

    
1138
#ifdef TARGET_SPARC64
1139
static uint32_t compute_all_subx_xcc(void)
1140
{
1141
    uint32_t ret;
1142

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

    
1150
static uint32_t compute_C_subx_xcc(void)
1151
{
1152
    uint32_t ret;
1153

    
1154
    ret = get_C_sub_xcc(CC_DST - CC_SRC2, CC_SRC);
1155
    ret |= get_C_sub_xcc(CC_DST, CC_SRC2);
1156
    return ret;
1157
}
1158
#endif
1159

    
1160
static uint32_t compute_all_tsub(void)
1161
{
1162
    uint32_t ret;
1163

    
1164
    ret = get_NZ_icc(CC_DST);
1165
    ret |= get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1166
    ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1167
    ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
1168
    return ret;
1169
}
1170

    
1171
static uint32_t compute_C_tsub(void)
1172
{
1173
    return get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1174
}
1175

    
1176
static uint32_t compute_all_tsubtv(void)
1177
{
1178
    uint32_t ret;
1179

    
1180
    ret = get_NZ_icc(CC_DST);
1181
    ret |= get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1182
    return ret;
1183
}
1184

    
1185
static uint32_t compute_C_tsubtv(void)
1186
{
1187
    return get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1188
}
1189

    
1190
static uint32_t compute_all_logic(void)
1191
{
1192
    return get_NZ_icc(CC_DST);
1193
}
1194

    
1195
static uint32_t compute_C_logic(void)
1196
{
1197
    return 0;
1198
}
1199

    
1200
#ifdef TARGET_SPARC64
1201
static uint32_t compute_all_logic_xcc(void)
1202
{
1203
    return get_NZ_xcc(CC_DST);
1204
}
1205
#endif
1206

    
1207
typedef struct CCTable {
1208
    uint32_t (*compute_all)(void); /* return all the flags */
1209
    uint32_t (*compute_c)(void);  /* return the C flag */
1210
} CCTable;
1211

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

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

    
1244
void helper_compute_psr(void)
1245
{
1246
    uint32_t new_psr;
1247

    
1248
    new_psr = icc_table[CC_OP].compute_all();
1249
    env->psr = new_psr;
1250
#ifdef TARGET_SPARC64
1251
    new_psr = xcc_table[CC_OP].compute_all();
1252
    env->xcc = new_psr;
1253
#endif
1254
    CC_OP = CC_OP_FLAGS;
1255
}
1256

    
1257
uint32_t helper_compute_C_icc(void)
1258
{
1259
    uint32_t ret;
1260

    
1261
    ret = icc_table[CC_OP].compute_c() >> PSR_CARRY_SHIFT;
1262
    return ret;
1263
}
1264

    
1265
#ifdef TARGET_SPARC64
1266
GEN_FCMPS(fcmps_fcc1, float32, 22, 0);
1267
GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
1268
GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0);
1269

    
1270
GEN_FCMPS(fcmps_fcc2, float32, 24, 0);
1271
GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
1272
GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0);
1273

    
1274
GEN_FCMPS(fcmps_fcc3, float32, 26, 0);
1275
GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
1276
GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0);
1277

    
1278
GEN_FCMPS(fcmpes_fcc1, float32, 22, 1);
1279
GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
1280
GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1);
1281

    
1282
GEN_FCMPS(fcmpes_fcc2, float32, 24, 1);
1283
GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
1284
GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1);
1285

    
1286
GEN_FCMPS(fcmpes_fcc3, float32, 26, 1);
1287
GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
1288
GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
1289
#endif
1290
#undef GEN_FCMPS
1291

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

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

    
1338
#ifndef TARGET_SPARC64
1339
#ifndef CONFIG_USER_ONLY
1340
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1341
{
1342
    uint64_t ret = 0;
1343
#if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
1344
    uint32_t last_addr = addr;
1345
#endif
1346

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

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

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

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

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

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

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

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

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

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

    
1911
#endif /* CONFIG_USER_ONLY */
1912
#else /* TARGET_SPARC64 */
1913

    
1914
#ifdef CONFIG_USER_ONLY
1915
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1916
{
1917
    uint64_t ret = 0;
1918
#if defined(DEBUG_ASI)
1919
    target_ulong last_addr = addr;
1920
#endif
1921

    
1922
    if (asi < 0x80)
1923
        raise_exception(TT_PRIV_ACT);
1924

    
1925
    helper_check_align(addr, size - 1);
1926
    address_mask(env, &addr);
1927

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

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

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

    
2020
void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
2021
{
2022
#ifdef DEBUG_ASI
2023
    dump_asi("write", addr, asi, size, val);
2024
#endif
2025
    if (asi < 0x80)
2026
        raise_exception(TT_PRIV_ACT);
2027

    
2028
    helper_check_align(addr, size - 1);
2029
    address_mask(env, &addr);
2030

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

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

    
2078
    case 0x82: // Primary no-fault, RO
2079
    case 0x83: // Secondary no-fault, RO
2080
    case 0x8a: // Primary no-fault LE, RO
2081
    case 0x8b: // Secondary no-fault LE, RO
2082
    default:
2083
        do_unassigned_access(addr, 1, 0, 1, size);
2084
        return;
2085
    }
2086
}
2087

    
2088
#else /* CONFIG_USER_ONLY */
2089

    
2090
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
2091
{
2092
    uint64_t ret = 0;
2093
#if defined(DEBUG_ASI)
2094
    target_ulong last_addr = addr;
2095
#endif
2096

    
2097
    asi &= 0xff;
2098

    
2099
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
2100
        || ((env->def->features & CPU_FEATURE_HYPV)
2101
            && asi >= 0x30 && asi < 0x80
2102
            && !(env->hpstate & HS_PRIV)))
2103
        raise_exception(TT_PRIV_ACT);
2104

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

    
2227
            if (reg == 0) {
2228
                // I-TSB Tag Target register
2229
                ret = ultrasparc_tag_target(env->immu.tag_access);
2230
            } else {
2231
                ret = env->immuregs[reg];
2232
            }
2233

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

    
2256
            ret = env->itlb[reg].tte;
2257
            break;
2258
        }
2259
    case 0x56: // I-MMU tag read
2260
        {
2261
            int reg = (addr >> 3) & 0x3f;
2262

    
2263
            ret = env->itlb[reg].tag;
2264
            break;
2265
        }
2266
    case 0x58: // D-MMU regs
2267
        {
2268
            int reg = (addr >> 3) & 0xf;
2269

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

    
2298
            ret = env->dtlb[reg].tte;
2299
            break;
2300
        }
2301
    case 0x5e: // D-MMU tag read
2302
        {
2303
            int reg = (addr >> 3) & 0x3f;
2304

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

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

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

    
2388
void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
2389
{
2390
#ifdef DEBUG_ASI
2391
    dump_asi("write", addr, asi, size, val);
2392
#endif
2393

    
2394
    asi &= 0xff;
2395

    
2396
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
2397
        || ((env->def->features & CPU_FEATURE_HYPV)
2398
            && asi >= 0x30 && asi < 0x80
2399
            && !(env->hpstate & HS_PRIV)))
2400
        raise_exception(TT_PRIV_ACT);
2401

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

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

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

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

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

    
2593
            unsigned int i = (addr >> 3) & 0x3f;
2594

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

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

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

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

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

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

    
2707
void helper_ldda_asi(target_ulong addr, int asi, int rd)
2708
{
2709
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
2710
        || ((env->def->features & CPU_FEATURE_HYPV)
2711
            && asi >= 0x30 && asi < 0x80
2712
            && !(env->hpstate & HS_PRIV)))
2713
        raise_exception(TT_PRIV_ACT);
2714

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

    
2754
void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
2755
{
2756
    unsigned int i;
2757
    target_ulong val;
2758

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

    
2776
        return;
2777
    default:
2778
        break;
2779
    }
2780

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

    
2796
void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
2797
{
2798
    unsigned int i;
2799
    target_ulong val = 0;
2800

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

    
2820
        return;
2821
    default:
2822
        break;
2823
    }
2824

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

    
2840
target_ulong helper_cas_asi(target_ulong addr, target_ulong val1,
2841
                            target_ulong val2, uint32_t asi)
2842
{
2843
    target_ulong ret;
2844

    
2845
    val2 &= 0xffffffffUL;
2846
    ret = helper_ld_asi(addr, asi, 4, 0);
2847
    ret &= 0xffffffffUL;
2848
    if (val2 == ret)
2849
        helper_st_asi(addr, val1 & 0xffffffffUL, asi, 4);
2850
    return ret;
2851
}
2852

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

    
2858
    ret = helper_ld_asi(addr, asi, 8, 0);
2859
    if (val2 == ret)
2860
        helper_st_asi(addr, val1, asi, 8);
2861
    return ret;
2862
}
2863
#endif /* TARGET_SPARC64 */
2864

    
2865
#ifndef TARGET_SPARC64
2866
void helper_rett(void)
2867
{
2868
    unsigned int cwp;
2869

    
2870
    if (env->psret == 1)
2871
        raise_exception(TT_ILL_INSN);
2872

    
2873
    env->psret = 1;
2874
    cwp = cpu_cwp_inc(env, env->cwp + 1) ;
2875
    if (env->wim & (1 << cwp)) {
2876
        raise_exception(TT_WIN_UNF);
2877
    }
2878
    set_cwp(cwp);
2879
    env->psrs = env->psrps;
2880
}
2881
#endif
2882

    
2883
target_ulong helper_udiv(target_ulong a, target_ulong b)
2884
{
2885
    uint64_t x0;
2886
    uint32_t x1;
2887

    
2888
    x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
2889
    x1 = b;
2890

    
2891
    if (x1 == 0) {
2892
        raise_exception(TT_DIV_ZERO);
2893
    }
2894

    
2895
    x0 = x0 / x1;
2896
    if (x0 > 0xffffffff) {
2897
        env->cc_src2 = 1;
2898
        return 0xffffffff;
2899
    } else {
2900
        env->cc_src2 = 0;
2901
        return x0;
2902
    }
2903
}
2904

    
2905
target_ulong helper_sdiv(target_ulong a, target_ulong b)
2906
{
2907
    int64_t x0;
2908
    int32_t x1;
2909

    
2910
    x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
2911
    x1 = b;
2912

    
2913
    if (x1 == 0) {
2914
        raise_exception(TT_DIV_ZERO);
2915
    }
2916

    
2917
    x0 = x0 / x1;
2918
    if ((int32_t) x0 != x0) {
2919
        env->cc_src2 = 1;
2920
        return x0 < 0? 0x80000000: 0x7fffffff;
2921
    } else {
2922
        env->cc_src2 = 0;
2923
        return x0;
2924
    }
2925
}
2926

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

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

    
2977
void helper_ldqf(target_ulong addr, int mem_idx)
2978
{
2979
    // XXX add 128 bit load
2980
    CPU_QuadU u;
2981

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

    
3013
void helper_stqf(target_ulong addr, int mem_idx)
3014
{
3015
    // XXX add 128 bit store
3016
    CPU_QuadU u;
3017

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

    
3049
static inline void set_fsr(void)
3050
{
3051
    int rnd_mode;
3052

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

    
3071
void helper_ldfsr(uint32_t new_fsr)
3072
{
3073
    env->fsr = (new_fsr & FSR_LDFSR_MASK) | (env->fsr & FSR_LDFSR_OLDMASK);
3074
    set_fsr();
3075
}
3076

    
3077
#ifdef TARGET_SPARC64
3078
void helper_ldxfsr(uint64_t new_fsr)
3079
{
3080
    env->fsr = (new_fsr & FSR_LDXFSR_MASK) | (env->fsr & FSR_LDXFSR_OLDMASK);
3081
    set_fsr();
3082
}
3083
#endif
3084

    
3085
void helper_debug(void)
3086
{
3087
    env->exception_index = EXCP_DEBUG;
3088
    cpu_loop_exit();
3089
}
3090

    
3091
#ifndef TARGET_SPARC64
3092
/* XXX: use another pointer for %iN registers to avoid slow wrapping
3093
   handling ? */
3094
void helper_save(void)
3095
{
3096
    uint32_t cwp;
3097

    
3098
    cwp = cpu_cwp_dec(env, env->cwp - 1);
3099
    if (env->wim & (1 << cwp)) {
3100
        raise_exception(TT_WIN_OVF);
3101
    }
3102
    set_cwp(cwp);
3103
}
3104

    
3105
void helper_restore(void)
3106
{
3107
    uint32_t cwp;
3108

    
3109
    cwp = cpu_cwp_inc(env, env->cwp + 1);
3110
    if (env->wim & (1 << cwp)) {
3111
        raise_exception(TT_WIN_UNF);
3112
    }
3113
    set_cwp(cwp);
3114
}
3115

    
3116
void helper_wrpsr(target_ulong new_psr)
3117
{
3118
    if ((new_psr & PSR_CWP) >= env->nwindows)
3119
        raise_exception(TT_ILL_INSN);
3120
    else
3121
        PUT_PSR(env, new_psr);
3122
}
3123

    
3124
target_ulong helper_rdpsr(void)
3125
{
3126
    return GET_PSR(env);
3127
}
3128

    
3129
#else
3130
/* XXX: use another pointer for %iN registers to avoid slow wrapping
3131
   handling ? */
3132
void helper_save(void)
3133
{
3134
    uint32_t cwp;
3135

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

    
3153
void helper_restore(void)
3154
{
3155
    uint32_t cwp;
3156

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

    
3169
void helper_flushw(void)
3170
{
3171
    if (env->cansave != env->nwindows - 2) {
3172
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
3173
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
3174
                                    ((env->wstate & 0x7) << 2)));
3175
    }
3176
}
3177

    
3178
void helper_saved(void)
3179
{
3180
    env->cansave++;
3181
    if (env->otherwin == 0)
3182
        env->canrestore--;
3183
    else
3184
        env->otherwin--;
3185
}
3186

    
3187
void helper_restored(void)
3188
{
3189
    env->canrestore++;
3190
    if (env->cleanwin < env->nwindows - 1)
3191
        env->cleanwin++;
3192
    if (env->otherwin == 0)
3193
        env->cansave--;
3194
    else
3195
        env->otherwin--;
3196
}
3197

    
3198
target_ulong helper_rdccr(void)
3199
{
3200
    return GET_CCR(env);
3201
}
3202

    
3203
void helper_wrccr(target_ulong new_ccr)
3204
{
3205
    PUT_CCR(env, new_ccr);
3206
}
3207

    
3208
// CWP handling is reversed in V9, but we still use the V8 register
3209
// order.
3210
target_ulong helper_rdcwp(void)
3211
{
3212
    return GET_CWP64(env);
3213
}
3214

    
3215
void helper_wrcwp(target_ulong new_cwp)
3216
{
3217
    PUT_CWP64(env, new_cwp);
3218
}
3219

    
3220
// This function uses non-native bit order
3221
#define GET_FIELD(X, FROM, TO)                                  \
3222
    ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
3223

    
3224
// This function uses the order in the manuals, i.e. bit 0 is 2^0
3225
#define GET_FIELD_SP(X, FROM, TO)               \
3226
    GET_FIELD(X, 63 - (TO), 63 - (FROM))
3227

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

    
3241
target_ulong helper_alignaddr(target_ulong addr, target_ulong offset)
3242
{
3243
    uint64_t tmp;
3244

    
3245
    tmp = addr + offset;
3246
    env->gsr &= ~7ULL;
3247
    env->gsr |= tmp & 7ULL;
3248
    return tmp & ~7ULL;
3249
}
3250

    
3251
target_ulong helper_popc(target_ulong val)
3252
{
3253
    return ctpop64(val);
3254
}
3255

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

    
3277
static inline void change_pstate(uint32_t new_pstate)
3278
{
3279
    uint32_t pstate_regs, new_pstate_regs;
3280
    uint64_t *src, *dst;
3281

    
3282
    if (env->def->features & CPU_FEATURE_GL) {
3283
        // PS_AG is not implemented in this case
3284
        new_pstate &= ~PS_AG;
3285
    }
3286

    
3287
    pstate_regs = env->pstate & 0xc01;
3288
    new_pstate_regs = new_pstate & 0xc01;
3289

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

    
3306
void helper_wrpstate(target_ulong new_state)
3307
{
3308
    change_pstate(new_state & 0xf3f);
3309

    
3310
#if !defined(CONFIG_USER_ONLY)
3311
    if (cpu_interrupts_enabled(env)) {
3312
        cpu_check_irqs(env);
3313
    }
3314
#endif
3315
}
3316

    
3317
void helper_wrpil(target_ulong new_pil)
3318
{
3319
#if !defined(CONFIG_USER_ONLY)
3320
    DPRINTF_PSTATE("helper_wrpil old=%x new=%x\n",
3321
                   env->psrpil, (uint32_t)new_pil);
3322

    
3323
    env->psrpil = new_pil;
3324

    
3325
    if (cpu_interrupts_enabled(env)) {
3326
        cpu_check_irqs(env);
3327
    }
3328
#endif
3329
}
3330

    
3331
void helper_done(void)
3332
{
3333
    trap_state* tsptr = cpu_tsptr(env);
3334

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

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

    
3345
#if !defined(CONFIG_USER_ONLY)
3346
    if (cpu_interrupts_enabled(env)) {
3347
        cpu_check_irqs(env);
3348
    }
3349
#endif
3350
}
3351

    
3352
void helper_retry(void)
3353
{
3354
    trap_state* tsptr = cpu_tsptr(env);
3355

    
3356
    env->pc = tsptr->tpc;
3357
    env->npc = tsptr->tnpc;
3358
    PUT_CCR(env, tsptr->tstate >> 32);
3359
    env->asi = (tsptr->tstate >> 24) & 0xff;
3360
    change_pstate((tsptr->tstate >> 8) & 0xf3f);
3361
    PUT_CWP64(env, tsptr->tstate & 0xff);
3362
    env->tl--;
3363

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

    
3366
#if !defined(CONFIG_USER_ONLY)
3367
    if (cpu_interrupts_enabled(env)) {
3368
        cpu_check_irqs(env);
3369
    }
3370
#endif
3371
}
3372

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

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

    
3391
void helper_clear_softint(uint64_t value)
3392
{
3393
    do_modify_softint("helper_clear_softint", env->softint & (uint32_t)~value);
3394
}
3395

    
3396
void helper_write_softint(uint64_t value)
3397
{
3398
    do_modify_softint("helper_write_softint", (uint32_t)value);
3399
}
3400
#endif
3401

    
3402
void helper_flush(target_ulong addr)
3403
{
3404
    addr &= ~7;
3405
    tb_invalidate_page_range(addr, addr + 8);
3406
}
3407

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

    
3445
trap_state* cpu_tsptr(CPUState* env)
3446
{
3447
    return &env->ts[env->tl & MAXTL_MASK];
3448
}
3449

    
3450
void do_interrupt(CPUState *env)
3451
{
3452
    int intno = env->exception_index;
3453
    trap_state* tsptr;
3454

    
3455
#ifdef DEBUG_PCALL
3456
    if (qemu_loglevel_mask(CPU_LOG_INT)) {
3457
        static int count;
3458
        const char *name;
3459

    
3460
        if (intno < 0 || intno >= 0x180)
3461
            name = "Unknown";
3462
        else if (intno >= 0x100)
3463
            name = "Trap Instruction";
3464
        else if (intno >= 0xc0)
3465
            name = "Window Fill";
3466
        else if (intno >= 0x80)
3467
            name = "Window Spill";
3468
        else {
3469
            name = excp_names[intno];
3470
            if (!name)
3471
                name = "Unknown";
3472
        }
3473

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

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

    
3512
    tsptr->tstate = ((uint64_t)GET_CCR(env) << 32) |
3513
        ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
3514
        GET_CWP64(env);
3515
    tsptr->tpc = env->pc;
3516
    tsptr->tnpc = env->npc;
3517
    tsptr->tt = intno;
3518

    
3519
    switch (intno) {
3520
    case TT_IVEC:
3521
        change_pstate(PS_PEF | PS_PRIV | PS_IG);
3522
        break;
3523
    case TT_TFAULT:
3524
    case TT_DFAULT:
3525
    case TT_TMISS ... TT_TMISS + 3:
3526
    case TT_DMISS ... TT_DMISS + 3:
3527
    case TT_DPROT ... TT_DPROT + 3:
3528
        change_pstate(PS_PEF | PS_PRIV | PS_MG);
3529
        break;
3530
    default:
3531
        change_pstate(PS_PEF | PS_PRIV | PS_AG);
3532
        break;
3533
    }
3534

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

    
3583
void do_interrupt(CPUState *env)
3584
{
3585
    int cwp, intno = env->exception_index;
3586

    
3587
#ifdef DEBUG_PCALL
3588
    if (qemu_loglevel_mask(CPU_LOG_INT)) {
3589
        static int count;
3590
        const char *name;
3591

    
3592
        if (intno < 0 || intno >= 0x100)
3593
            name = "Unknown";
3594
        else if (intno >= 0x80)
3595
            name = "Trap Instruction";
3596
        else {
3597
            name = excp_names[intno];
3598
            if (!name)
3599
                name = "Unknown";
3600
        }
3601

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

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

    
3644
#if !defined(CONFIG_USER_ONLY)
3645

    
3646
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
3647
                                void *retaddr);
3648

    
3649
#define MMUSUFFIX _mmu
3650
#define ALIGNED_ONLY
3651

    
3652
#define SHIFT 0
3653
#include "softmmu_template.h"
3654

    
3655
#define SHIFT 1
3656
#include "softmmu_template.h"
3657

    
3658
#define SHIFT 2
3659
#include "softmmu_template.h"
3660

    
3661
#define SHIFT 3
3662
#include "softmmu_template.h"
3663

    
3664
/* XXX: make it generic ? */
3665
static void cpu_restore_state2(void *retaddr)
3666
{
3667
    TranslationBlock *tb;
3668
    unsigned long pc;
3669

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

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

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

    
3702
    /* XXX: hack to restore env in all cases, even if not called from
3703
       generated code */
3704
    saved_env = env;
3705
    env = cpu_single_env;
3706

    
3707
    ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
3708
    if (ret) {
3709
        cpu_restore_state2(retaddr);
3710
        cpu_loop_exit();
3711
    }
3712
    env = saved_env;
3713
}
3714

    
3715
#endif /* !CONFIG_USER_ONLY */
3716

    
3717
#ifndef TARGET_SPARC64
3718
#if !defined(CONFIG_USER_ONLY)
3719
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
3720
                          int is_asi, int size)
3721
{
3722
    CPUState *saved_env;
3723
    int fault_type;
3724

    
3725
    /* XXX: hack to restore env in all cases, even if not called from
3726
       generated code */
3727
    saved_env = env;
3728
    env = cpu_single_env;
3729
#ifdef DEBUG_UNASSIGNED
3730
    if (is_asi)
3731
        printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
3732
               " asi 0x%02x from " TARGET_FMT_lx "\n",
3733
               is_exec ? "exec" : is_write ? "write" : "read", size,
3734
               size == 1 ? "" : "s", addr, is_asi, env->pc);
3735
    else
3736
        printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
3737
               " from " TARGET_FMT_lx "\n",
3738
               is_exec ? "exec" : is_write ? "write" : "read", size,
3739
               size == 1 ? "" : "s", addr, env->pc);
3740
#endif
3741
    /* Don't overwrite translation and access faults */
3742
    fault_type = (env->mmuregs[3] & 0x1c) >> 2;
3743
    if ((fault_type > 4) || (fault_type == 0)) {
3744
        env->mmuregs[3] = 0; /* Fault status register */
3745
        if (is_asi)
3746
            env->mmuregs[3] |= 1 << 16;
3747
        if (env->psrs)
3748
            env->mmuregs[3] |= 1 << 5;
3749
        if (is_exec)
3750
            env->mmuregs[3] |= 1 << 6;
3751
        if (is_write)
3752
            env->mmuregs[3] |= 1 << 7;
3753
        env->mmuregs[3] |= (5 << 2) | 2;
3754
        /* SuperSPARC will never place instruction fault addresses in the FAR */
3755
        if (!is_exec) {
3756
            env->mmuregs[4] = addr; /* Fault address register */
3757
        }
3758
    }
3759
    /* overflow (same type fault was not read before another fault) */
3760
    if (fault_type == ((env->mmuregs[3] & 0x1c)) >> 2) {
3761
        env->mmuregs[3] |= 1;
3762
    }
3763

    
3764
    if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
3765
        if (is_exec)
3766
            raise_exception(TT_CODE_ACCESS);
3767
        else
3768
            raise_exception(TT_DATA_ACCESS);
3769
    }
3770

    
3771
    /* flush neverland mappings created during no-fault mode,
3772
       so the sequential MMU faults report proper fault types */
3773
    if (env->mmuregs[0] & MMU_NF) {
3774
        tlb_flush(env, 1);
3775
    }
3776

    
3777
    env = saved_env;
3778
}
3779
#endif
3780
#else
3781
#if defined(CONFIG_USER_ONLY)
3782
static void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
3783
                          int is_asi, int size)
3784
#else
3785
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
3786
                          int is_asi, int size)
3787
#endif
3788
{
3789
    CPUState *saved_env;
3790

    
3791
    /* XXX: hack to restore env in all cases, even if not called from
3792
       generated code */
3793
    saved_env = env;
3794
    env = cpu_single_env;
3795

    
3796
#ifdef DEBUG_UNASSIGNED
3797
    printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx
3798
           "\n", addr, env->pc);
3799
#endif
3800

    
3801
    if (is_exec)
3802
        raise_exception(TT_CODE_ACCESS);
3803
    else
3804
        raise_exception(TT_DATA_ACCESS);
3805

    
3806
    env = saved_env;
3807
}
3808
#endif
3809

    
3810

    
3811
#ifdef TARGET_SPARC64
3812
void helper_tick_set_count(void *opaque, uint64_t count)
3813
{
3814
#if !defined(CONFIG_USER_ONLY)
3815
    cpu_tick_set_count(opaque, count);
3816
#endif
3817
}
3818

    
3819
uint64_t helper_tick_get_count(void *opaque)
3820
{
3821
#if !defined(CONFIG_USER_ONLY)
3822
    return cpu_tick_get_count(opaque);
3823
#else
3824
    return 0;
3825
#endif
3826
}
3827

    
3828
void helper_tick_set_limit(void *opaque, uint64_t limit)
3829
{
3830
#if !defined(CONFIG_USER_ONLY)
3831
    cpu_tick_set_limit(opaque, limit);
3832
#endif
3833
}
3834
#endif