Statistics
| Branch: | Revision:

root / target-sparc / op_helper.c @ 9c22a623

History | View | Annotate | Download (91.2 kB)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
90
#endif
91

    
92
static inline void address_mask(CPUState *env1, target_ulong *addr)
93
{
94
#ifdef TARGET_SPARC64
95
    if (AM_CHECK(env1))
96
        *addr &= 0xffffffffULL;
97
#endif
98
}
99

    
100
static void raise_exception(int tt)
101
{
102
    env->exception_index = tt;
103
    cpu_loop_exit();
104
}
105

    
106
void HELPER(raise_exception)(int tt)
107
{
108
    raise_exception(tt);
109
}
110

    
111
static inline void set_cwp(int new_cwp)
112
{
113
    cpu_set_cwp(env, new_cwp);
114
}
115

    
116
void helper_check_align(target_ulong addr, uint32_t align)
117
{
118
    if (addr & align) {
119
#ifdef DEBUG_UNALIGNED
120
    printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
121
           "\n", addr, env->pc);
122
#endif
123
        raise_exception(TT_UNALIGNED);
124
    }
125
}
126

    
127
#define F_HELPER(name, p) void helper_f##name##p(void)
128

    
129
#define F_BINOP(name)                                           \
130
    float32 helper_f ## name ## s (float32 src1, float32 src2)  \
131
    {                                                           \
132
        return float32_ ## name (src1, src2, &env->fp_status);  \
133
    }                                                           \
134
    F_HELPER(name, d)                                           \
135
    {                                                           \
136
        DT0 = float64_ ## name (DT0, DT1, &env->fp_status);     \
137
    }                                                           \
138
    F_HELPER(name, q)                                           \
139
    {                                                           \
140
        QT0 = float128_ ## name (QT0, QT1, &env->fp_status);    \
141
    }
142

    
143
F_BINOP(add);
144
F_BINOP(sub);
145
F_BINOP(mul);
146
F_BINOP(div);
147
#undef F_BINOP
148

    
149
void helper_fsmuld(float32 src1, float32 src2)
150
{
151
    DT0 = float64_mul(float32_to_float64(src1, &env->fp_status),
152
                      float32_to_float64(src2, &env->fp_status),
153
                      &env->fp_status);
154
}
155

    
156
void helper_fdmulq(void)
157
{
158
    QT0 = float128_mul(float64_to_float128(DT0, &env->fp_status),
159
                       float64_to_float128(DT1, &env->fp_status),
160
                       &env->fp_status);
161
}
162

    
163
float32 helper_fnegs(float32 src)
164
{
165
    return float32_chs(src);
166
}
167

    
168
#ifdef TARGET_SPARC64
169
F_HELPER(neg, d)
170
{
171
    DT0 = float64_chs(DT1);
172
}
173

    
174
F_HELPER(neg, q)
175
{
176
    QT0 = float128_chs(QT1);
177
}
178
#endif
179

    
180
/* Integer to float conversion.  */
181
float32 helper_fitos(int32_t src)
182
{
183
    return int32_to_float32(src, &env->fp_status);
184
}
185

    
186
void helper_fitod(int32_t src)
187
{
188
    DT0 = int32_to_float64(src, &env->fp_status);
189
}
190

    
191
void helper_fitoq(int32_t src)
192
{
193
    QT0 = int32_to_float128(src, &env->fp_status);
194
}
195

    
196
#ifdef TARGET_SPARC64
197
float32 helper_fxtos(void)
198
{
199
    return int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
200
}
201

    
202
F_HELPER(xto, d)
203
{
204
    DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
205
}
206

    
207
F_HELPER(xto, q)
208
{
209
    QT0 = int64_to_float128(*((int64_t *)&DT1), &env->fp_status);
210
}
211
#endif
212
#undef F_HELPER
213

    
214
/* floating point conversion */
215
float32 helper_fdtos(void)
216
{
217
    return float64_to_float32(DT1, &env->fp_status);
218
}
219

    
220
void helper_fstod(float32 src)
221
{
222
    DT0 = float32_to_float64(src, &env->fp_status);
223
}
224

    
225
float32 helper_fqtos(void)
226
{
227
    return float128_to_float32(QT1, &env->fp_status);
228
}
229

    
230
void helper_fstoq(float32 src)
231
{
232
    QT0 = float32_to_float128(src, &env->fp_status);
233
}
234

    
235
void helper_fqtod(void)
236
{
237
    DT0 = float128_to_float64(QT1, &env->fp_status);
238
}
239

    
240
void helper_fdtoq(void)
241
{
242
    QT0 = float64_to_float128(DT1, &env->fp_status);
243
}
244

    
245
/* Float to integer conversion.  */
246
int32_t helper_fstoi(float32 src)
247
{
248
    return float32_to_int32_round_to_zero(src, &env->fp_status);
249
}
250

    
251
int32_t helper_fdtoi(void)
252
{
253
    return float64_to_int32_round_to_zero(DT1, &env->fp_status);
254
}
255

    
256
int32_t helper_fqtoi(void)
257
{
258
    return float128_to_int32_round_to_zero(QT1, &env->fp_status);
259
}
260

    
261
#ifdef TARGET_SPARC64
262
void helper_fstox(float32 src)
263
{
264
    *((int64_t *)&DT0) = float32_to_int64_round_to_zero(src, &env->fp_status);
265
}
266

    
267
void helper_fdtox(void)
268
{
269
    *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status);
270
}
271

    
272
void helper_fqtox(void)
273
{
274
    *((int64_t *)&DT0) = float128_to_int64_round_to_zero(QT1, &env->fp_status);
275
}
276

    
277
void helper_faligndata(void)
278
{
279
    uint64_t tmp;
280

    
281
    tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8);
282
    /* on many architectures a shift of 64 does nothing */
283
    if ((env->gsr & 7) != 0) {
284
        tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8);
285
    }
286
    *((uint64_t *)&DT0) = tmp;
287
}
288

    
289
#ifdef WORDS_BIGENDIAN
290
#define VIS_B64(n) b[7 - (n)]
291
#define VIS_W64(n) w[3 - (n)]
292
#define VIS_SW64(n) sw[3 - (n)]
293
#define VIS_L64(n) l[1 - (n)]
294
#define VIS_B32(n) b[3 - (n)]
295
#define VIS_W32(n) w[1 - (n)]
296
#else
297
#define VIS_B64(n) b[n]
298
#define VIS_W64(n) w[n]
299
#define VIS_SW64(n) sw[n]
300
#define VIS_L64(n) l[n]
301
#define VIS_B32(n) b[n]
302
#define VIS_W32(n) w[n]
303
#endif
304

    
305
typedef union {
306
    uint8_t b[8];
307
    uint16_t w[4];
308
    int16_t sw[4];
309
    uint32_t l[2];
310
    float64 d;
311
} vis64;
312

    
313
typedef union {
314
    uint8_t b[4];
315
    uint16_t w[2];
316
    uint32_t l;
317
    float32 f;
318
} vis32;
319

    
320
void helper_fpmerge(void)
321
{
322
    vis64 s, d;
323

    
324
    s.d = DT0;
325
    d.d = DT1;
326

    
327
    // Reverse calculation order to handle overlap
328
    d.VIS_B64(7) = s.VIS_B64(3);
329
    d.VIS_B64(6) = d.VIS_B64(3);
330
    d.VIS_B64(5) = s.VIS_B64(2);
331
    d.VIS_B64(4) = d.VIS_B64(2);
332
    d.VIS_B64(3) = s.VIS_B64(1);
333
    d.VIS_B64(2) = d.VIS_B64(1);
334
    d.VIS_B64(1) = s.VIS_B64(0);
335
    //d.VIS_B64(0) = d.VIS_B64(0);
336

    
337
    DT0 = d.d;
338
}
339

    
340
void helper_fmul8x16(void)
341
{
342
    vis64 s, d;
343
    uint32_t tmp;
344

    
345
    s.d = DT0;
346
    d.d = DT1;
347

    
348
#define PMUL(r)                                                 \
349
    tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r);       \
350
    if ((tmp & 0xff) > 0x7f)                                    \
351
        tmp += 0x100;                                           \
352
    d.VIS_W64(r) = tmp >> 8;
353

    
354
    PMUL(0);
355
    PMUL(1);
356
    PMUL(2);
357
    PMUL(3);
358
#undef PMUL
359

    
360
    DT0 = d.d;
361
}
362

    
363
void helper_fmul8x16al(void)
364
{
365
    vis64 s, d;
366
    uint32_t tmp;
367

    
368
    s.d = DT0;
369
    d.d = DT1;
370

    
371
#define PMUL(r)                                                 \
372
    tmp = (int32_t)d.VIS_SW64(1) * (int32_t)s.VIS_B64(r);       \
373
    if ((tmp & 0xff) > 0x7f)                                    \
374
        tmp += 0x100;                                           \
375
    d.VIS_W64(r) = tmp >> 8;
376

    
377
    PMUL(0);
378
    PMUL(1);
379
    PMUL(2);
380
    PMUL(3);
381
#undef PMUL
382

    
383
    DT0 = d.d;
384
}
385

    
386
void helper_fmul8x16au(void)
387
{
388
    vis64 s, d;
389
    uint32_t tmp;
390

    
391
    s.d = DT0;
392
    d.d = DT1;
393

    
394
#define PMUL(r)                                                 \
395
    tmp = (int32_t)d.VIS_SW64(0) * (int32_t)s.VIS_B64(r);       \
396
    if ((tmp & 0xff) > 0x7f)                                    \
397
        tmp += 0x100;                                           \
398
    d.VIS_W64(r) = tmp >> 8;
399

    
400
    PMUL(0);
401
    PMUL(1);
402
    PMUL(2);
403
    PMUL(3);
404
#undef PMUL
405

    
406
    DT0 = d.d;
407
}
408

    
409
void helper_fmul8sux16(void)
410
{
411
    vis64 s, d;
412
    uint32_t tmp;
413

    
414
    s.d = DT0;
415
    d.d = DT1;
416

    
417
#define PMUL(r)                                                         \
418
    tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
419
    if ((tmp & 0xff) > 0x7f)                                            \
420
        tmp += 0x100;                                                   \
421
    d.VIS_W64(r) = tmp >> 8;
422

    
423
    PMUL(0);
424
    PMUL(1);
425
    PMUL(2);
426
    PMUL(3);
427
#undef PMUL
428

    
429
    DT0 = d.d;
430
}
431

    
432
void helper_fmul8ulx16(void)
433
{
434
    vis64 s, d;
435
    uint32_t tmp;
436

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

    
440
#define PMUL(r)                                                         \
441
    tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
442
    if ((tmp & 0xff) > 0x7f)                                            \
443
        tmp += 0x100;                                                   \
444
    d.VIS_W64(r) = tmp >> 8;
445

    
446
    PMUL(0);
447
    PMUL(1);
448
    PMUL(2);
449
    PMUL(3);
450
#undef PMUL
451

    
452
    DT0 = d.d;
453
}
454

    
455
void helper_fmuld8sux16(void)
456
{
457
    vis64 s, d;
458
    uint32_t tmp;
459

    
460
    s.d = DT0;
461
    d.d = DT1;
462

    
463
#define PMUL(r)                                                         \
464
    tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
465
    if ((tmp & 0xff) > 0x7f)                                            \
466
        tmp += 0x100;                                                   \
467
    d.VIS_L64(r) = tmp;
468

    
469
    // Reverse calculation order to handle overlap
470
    PMUL(1);
471
    PMUL(0);
472
#undef PMUL
473

    
474
    DT0 = d.d;
475
}
476

    
477
void helper_fmuld8ulx16(void)
478
{
479
    vis64 s, d;
480
    uint32_t tmp;
481

    
482
    s.d = DT0;
483
    d.d = DT1;
484

    
485
#define PMUL(r)                                                         \
486
    tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
487
    if ((tmp & 0xff) > 0x7f)                                            \
488
        tmp += 0x100;                                                   \
489
    d.VIS_L64(r) = tmp;
490

    
491
    // Reverse calculation order to handle overlap
492
    PMUL(1);
493
    PMUL(0);
494
#undef PMUL
495

    
496
    DT0 = d.d;
497
}
498

    
499
void helper_fexpand(void)
500
{
501
    vis32 s;
502
    vis64 d;
503

    
504
    s.l = (uint32_t)(*(uint64_t *)&DT0 & 0xffffffff);
505
    d.d = DT1;
506
    d.VIS_W64(0) = s.VIS_B32(0) << 4;
507
    d.VIS_W64(1) = s.VIS_B32(1) << 4;
508
    d.VIS_W64(2) = s.VIS_B32(2) << 4;
509
    d.VIS_W64(3) = s.VIS_B32(3) << 4;
510

    
511
    DT0 = d.d;
512
}
513

    
514
#define VIS_HELPER(name, F)                             \
515
    void name##16(void)                                 \
516
    {                                                   \
517
        vis64 s, d;                                     \
518
                                                        \
519
        s.d = DT0;                                      \
520
        d.d = DT1;                                      \
521
                                                        \
522
        d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0));   \
523
        d.VIS_W64(1) = F(d.VIS_W64(1), s.VIS_W64(1));   \
524
        d.VIS_W64(2) = F(d.VIS_W64(2), s.VIS_W64(2));   \
525
        d.VIS_W64(3) = F(d.VIS_W64(3), s.VIS_W64(3));   \
526
                                                        \
527
        DT0 = d.d;                                      \
528
    }                                                   \
529
                                                        \
530
    uint32_t name##16s(uint32_t src1, uint32_t src2)    \
531
    {                                                   \
532
        vis32 s, d;                                     \
533
                                                        \
534
        s.l = src1;                                     \
535
        d.l = src2;                                     \
536
                                                        \
537
        d.VIS_W32(0) = F(d.VIS_W32(0), s.VIS_W32(0));   \
538
        d.VIS_W32(1) = F(d.VIS_W32(1), s.VIS_W32(1));   \
539
                                                        \
540
        return d.l;                                     \
541
    }                                                   \
542
                                                        \
543
    void name##32(void)                                 \
544
    {                                                   \
545
        vis64 s, d;                                     \
546
                                                        \
547
        s.d = DT0;                                      \
548
        d.d = DT1;                                      \
549
                                                        \
550
        d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0));   \
551
        d.VIS_L64(1) = F(d.VIS_L64(1), s.VIS_L64(1));   \
552
                                                        \
553
        DT0 = d.d;                                      \
554
    }                                                   \
555
                                                        \
556
    uint32_t name##32s(uint32_t src1, uint32_t src2)    \
557
    {                                                   \
558
        vis32 s, d;                                     \
559
                                                        \
560
        s.l = src1;                                     \
561
        d.l = src2;                                     \
562
                                                        \
563
        d.l = F(d.l, s.l);                              \
564
                                                        \
565
        return d.l;                                     \
566
    }
567

    
568
#define FADD(a, b) ((a) + (b))
569
#define FSUB(a, b) ((a) - (b))
570
VIS_HELPER(helper_fpadd, FADD)
571
VIS_HELPER(helper_fpsub, FSUB)
572

    
573
#define VIS_CMPHELPER(name, F)                                        \
574
    void name##16(void)                                           \
575
    {                                                             \
576
        vis64 s, d;                                               \
577
                                                                  \
578
        s.d = DT0;                                                \
579
        d.d = DT1;                                                \
580
                                                                  \
581
        d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0))? 1: 0;       \
582
        d.VIS_W64(0) |= F(d.VIS_W64(1), s.VIS_W64(1))? 2: 0;      \
583
        d.VIS_W64(0) |= F(d.VIS_W64(2), s.VIS_W64(2))? 4: 0;      \
584
        d.VIS_W64(0) |= F(d.VIS_W64(3), s.VIS_W64(3))? 8: 0;      \
585
                                                                  \
586
        DT0 = d.d;                                                \
587
    }                                                             \
588
                                                                  \
589
    void name##32(void)                                           \
590
    {                                                             \
591
        vis64 s, d;                                               \
592
                                                                  \
593
        s.d = DT0;                                                \
594
        d.d = DT1;                                                \
595
                                                                  \
596
        d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0))? 1: 0;       \
597
        d.VIS_L64(0) |= F(d.VIS_L64(1), s.VIS_L64(1))? 2: 0;      \
598
                                                                  \
599
        DT0 = d.d;                                                \
600
    }
601

    
602
#define FCMPGT(a, b) ((a) > (b))
603
#define FCMPEQ(a, b) ((a) == (b))
604
#define FCMPLE(a, b) ((a) <= (b))
605
#define FCMPNE(a, b) ((a) != (b))
606

    
607
VIS_CMPHELPER(helper_fcmpgt, FCMPGT)
608
VIS_CMPHELPER(helper_fcmpeq, FCMPEQ)
609
VIS_CMPHELPER(helper_fcmple, FCMPLE)
610
VIS_CMPHELPER(helper_fcmpne, FCMPNE)
611
#endif
612

    
613
void helper_check_ieee_exceptions(void)
614
{
615
    target_ulong status;
616

    
617
    status = get_float_exception_flags(&env->fp_status);
618
    if (status) {
619
        /* Copy IEEE 754 flags into FSR */
620
        if (status & float_flag_invalid)
621
            env->fsr |= FSR_NVC;
622
        if (status & float_flag_overflow)
623
            env->fsr |= FSR_OFC;
624
        if (status & float_flag_underflow)
625
            env->fsr |= FSR_UFC;
626
        if (status & float_flag_divbyzero)
627
            env->fsr |= FSR_DZC;
628
        if (status & float_flag_inexact)
629
            env->fsr |= FSR_NXC;
630

    
631
        if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) {
632
            /* Unmasked exception, generate a trap */
633
            env->fsr |= FSR_FTT_IEEE_EXCP;
634
            raise_exception(TT_FP_EXCP);
635
        } else {
636
            /* Accumulate exceptions */
637
            env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
638
        }
639
    }
640
}
641

    
642
void helper_clear_float_exceptions(void)
643
{
644
    set_float_exception_flags(0, &env->fp_status);
645
}
646

    
647
float32 helper_fabss(float32 src)
648
{
649
    return float32_abs(src);
650
}
651

    
652
#ifdef TARGET_SPARC64
653
void helper_fabsd(void)
654
{
655
    DT0 = float64_abs(DT1);
656
}
657

    
658
void helper_fabsq(void)
659
{
660
    QT0 = float128_abs(QT1);
661
}
662
#endif
663

    
664
float32 helper_fsqrts(float32 src)
665
{
666
    return float32_sqrt(src, &env->fp_status);
667
}
668

    
669
void helper_fsqrtd(void)
670
{
671
    DT0 = float64_sqrt(DT1, &env->fp_status);
672
}
673

    
674
void helper_fsqrtq(void)
675
{
676
    QT0 = float128_sqrt(QT1, &env->fp_status);
677
}
678

    
679
#define GEN_FCMP(name, size, reg1, reg2, FS, TRAP)                      \
680
    void glue(helper_, name) (void)                                     \
681
    {                                                                   \
682
        target_ulong new_fsr;                                           \
683
                                                                        \
684
        env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                     \
685
        switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) {   \
686
        case float_relation_unordered:                                  \
687
            new_fsr = (FSR_FCC1 | FSR_FCC0) << FS;                      \
688
            if ((env->fsr & FSR_NVM) || TRAP) {                         \
689
                env->fsr |= new_fsr;                                    \
690
                env->fsr |= FSR_NVC;                                    \
691
                env->fsr |= FSR_FTT_IEEE_EXCP;                          \
692
                raise_exception(TT_FP_EXCP);                            \
693
            } else {                                                    \
694
                env->fsr |= FSR_NVA;                                    \
695
            }                                                           \
696
            break;                                                      \
697
        case float_relation_less:                                       \
698
            new_fsr = FSR_FCC0 << FS;                                   \
699
            break;                                                      \
700
        case float_relation_greater:                                    \
701
            new_fsr = FSR_FCC1 << FS;                                   \
702
            break;                                                      \
703
        default:                                                        \
704
            new_fsr = 0;                                                \
705
            break;                                                      \
706
        }                                                               \
707
        env->fsr |= new_fsr;                                            \
708
    }
709
#define GEN_FCMPS(name, size, FS, TRAP)                                 \
710
    void glue(helper_, name)(float32 src1, float32 src2)                \
711
    {                                                                   \
712
        target_ulong new_fsr;                                           \
713
                                                                        \
714
        env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                     \
715
        switch (glue(size, _compare) (src1, src2, &env->fp_status)) {   \
716
        case float_relation_unordered:                                  \
717
            new_fsr = (FSR_FCC1 | FSR_FCC0) << FS;                      \
718
            if ((env->fsr & FSR_NVM) || TRAP) {                         \
719
                env->fsr |= new_fsr;                                    \
720
                env->fsr |= FSR_NVC;                                    \
721
                env->fsr |= FSR_FTT_IEEE_EXCP;                          \
722
                raise_exception(TT_FP_EXCP);                            \
723
            } else {                                                    \
724
                env->fsr |= FSR_NVA;                                    \
725
            }                                                           \
726
            break;                                                      \
727
        case float_relation_less:                                       \
728
            new_fsr = FSR_FCC0 << FS;                                   \
729
            break;                                                      \
730
        case float_relation_greater:                                    \
731
            new_fsr = FSR_FCC1 << FS;                                   \
732
            break;                                                      \
733
        default:                                                        \
734
            new_fsr = 0;                                                \
735
            break;                                                      \
736
        }                                                               \
737
        env->fsr |= new_fsr;                                            \
738
    }
739

    
740
GEN_FCMPS(fcmps, float32, 0, 0);
741
GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
742

    
743
GEN_FCMPS(fcmpes, float32, 0, 1);
744
GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
745

    
746
GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0);
747
GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1);
748

    
749
#ifdef TARGET_SPARC64
750
GEN_FCMPS(fcmps_fcc1, float32, 22, 0);
751
GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
752
GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0);
753

    
754
GEN_FCMPS(fcmps_fcc2, float32, 24, 0);
755
GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
756
GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0);
757

    
758
GEN_FCMPS(fcmps_fcc3, float32, 26, 0);
759
GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
760
GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0);
761

    
762
GEN_FCMPS(fcmpes_fcc1, float32, 22, 1);
763
GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
764
GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1);
765

    
766
GEN_FCMPS(fcmpes_fcc2, float32, 24, 1);
767
GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
768
GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1);
769

    
770
GEN_FCMPS(fcmpes_fcc3, float32, 26, 1);
771
GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
772
GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
773
#endif
774
#undef GEN_FCMPS
775

    
776
#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) && \
777
    defined(DEBUG_MXCC)
778
static void dump_mxcc(CPUState *env)
779
{
780
    printf("mxccdata: %016llx %016llx %016llx %016llx\n",
781
           env->mxccdata[0], env->mxccdata[1],
782
           env->mxccdata[2], env->mxccdata[3]);
783
    printf("mxccregs: %016llx %016llx %016llx %016llx\n"
784
           "          %016llx %016llx %016llx %016llx\n",
785
           env->mxccregs[0], env->mxccregs[1],
786
           env->mxccregs[2], env->mxccregs[3],
787
           env->mxccregs[4], env->mxccregs[5],
788
           env->mxccregs[6], env->mxccregs[7]);
789
}
790
#endif
791

    
792
#if (defined(TARGET_SPARC64) || !defined(CONFIG_USER_ONLY)) \
793
    && defined(DEBUG_ASI)
794
static void dump_asi(const char *txt, target_ulong addr, int asi, int size,
795
                     uint64_t r1)
796
{
797
    switch (size)
798
    {
799
    case 1:
800
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %02" PRIx64 "\n", txt,
801
                    addr, asi, r1 & 0xff);
802
        break;
803
    case 2:
804
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %04" PRIx64 "\n", txt,
805
                    addr, asi, r1 & 0xffff);
806
        break;
807
    case 4:
808
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %08" PRIx64 "\n", txt,
809
                    addr, asi, r1 & 0xffffffff);
810
        break;
811
    case 8:
812
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %016" PRIx64 "\n", txt,
813
                    addr, asi, r1);
814
        break;
815
    }
816
}
817
#endif
818

    
819
#ifndef TARGET_SPARC64
820
#ifndef CONFIG_USER_ONLY
821
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
822
{
823
    uint64_t ret = 0;
824
#if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
825
    uint32_t last_addr = addr;
826
#endif
827

    
828
    helper_check_align(addr, size - 1);
829
    switch (asi) {
830
    case 2: /* SuperSparc MXCC registers */
831
        switch (addr) {
832
        case 0x01c00a00: /* MXCC control register */
833
            if (size == 8)
834
                ret = env->mxccregs[3];
835
            else
836
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
837
                             size);
838
            break;
839
        case 0x01c00a04: /* MXCC control register */
840
            if (size == 4)
841
                ret = env->mxccregs[3];
842
            else
843
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
844
                             size);
845
            break;
846
        case 0x01c00c00: /* Module reset register */
847
            if (size == 8) {
848
                ret = env->mxccregs[5];
849
                // should we do something here?
850
            } else
851
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
852
                             size);
853
            break;
854
        case 0x01c00f00: /* MBus port address register */
855
            if (size == 8)
856
                ret = env->mxccregs[7];
857
            else
858
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
859
                             size);
860
            break;
861
        default:
862
            DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr,
863
                         size);
864
            break;
865
        }
866
        DPRINTF_MXCC("asi = %d, size = %d, sign = %d, "
867
                     "addr = %08x -> ret = %" PRIx64 ","
868
                     "addr = %08x\n", asi, size, sign, last_addr, ret, addr);
869
#ifdef DEBUG_MXCC
870
        dump_mxcc(env);
871
#endif
872
        break;
873
    case 3: /* MMU probe */
874
        {
875
            int mmulev;
876

    
877
            mmulev = (addr >> 8) & 15;
878
            if (mmulev > 4)
879
                ret = 0;
880
            else
881
                ret = mmu_probe(env, addr, mmulev);
882
            DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08" PRIx64 "\n",
883
                        addr, mmulev, ret);
884
        }
885
        break;
886
    case 4: /* read MMU regs */
887
        {
888
            int reg = (addr >> 8) & 0x1f;
889

    
890
            ret = env->mmuregs[reg];
891
            if (reg == 3) /* Fault status cleared on read */
892
                env->mmuregs[3] = 0;
893
            else if (reg == 0x13) /* Fault status read */
894
                ret = env->mmuregs[3];
895
            else if (reg == 0x14) /* Fault address read */
896
                ret = env->mmuregs[4];
897
            DPRINTF_MMU("mmu_read: reg[%d] = 0x%08" PRIx64 "\n", reg, ret);
898
        }
899
        break;
900
    case 5: // Turbosparc ITLB Diagnostic
901
    case 6: // Turbosparc DTLB Diagnostic
902
    case 7: // Turbosparc IOTLB Diagnostic
903
        break;
904
    case 9: /* Supervisor code access */
905
        switch(size) {
906
        case 1:
907
            ret = ldub_code(addr);
908
            break;
909
        case 2:
910
            ret = lduw_code(addr);
911
            break;
912
        default:
913
        case 4:
914
            ret = ldl_code(addr);
915
            break;
916
        case 8:
917
            ret = ldq_code(addr);
918
            break;
919
        }
920
        break;
921
    case 0xa: /* User data access */
922
        switch(size) {
923
        case 1:
924
            ret = ldub_user(addr);
925
            break;
926
        case 2:
927
            ret = lduw_user(addr);
928
            break;
929
        default:
930
        case 4:
931
            ret = ldl_user(addr);
932
            break;
933
        case 8:
934
            ret = ldq_user(addr);
935
            break;
936
        }
937
        break;
938
    case 0xb: /* Supervisor data access */
939
        switch(size) {
940
        case 1:
941
            ret = ldub_kernel(addr);
942
            break;
943
        case 2:
944
            ret = lduw_kernel(addr);
945
            break;
946
        default:
947
        case 4:
948
            ret = ldl_kernel(addr);
949
            break;
950
        case 8:
951
            ret = ldq_kernel(addr);
952
            break;
953
        }
954
        break;
955
    case 0xc: /* I-cache tag */
956
    case 0xd: /* I-cache data */
957
    case 0xe: /* D-cache tag */
958
    case 0xf: /* D-cache data */
959
        break;
960
    case 0x20: /* MMU passthrough */
961
        switch(size) {
962
        case 1:
963
            ret = ldub_phys(addr);
964
            break;
965
        case 2:
966
            ret = lduw_phys(addr);
967
            break;
968
        default:
969
        case 4:
970
            ret = ldl_phys(addr);
971
            break;
972
        case 8:
973
            ret = ldq_phys(addr);
974
            break;
975
        }
976
        break;
977
    case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
978
        switch(size) {
979
        case 1:
980
            ret = ldub_phys((target_phys_addr_t)addr
981
                            | ((target_phys_addr_t)(asi & 0xf) << 32));
982
            break;
983
        case 2:
984
            ret = lduw_phys((target_phys_addr_t)addr
985
                            | ((target_phys_addr_t)(asi & 0xf) << 32));
986
            break;
987
        default:
988
        case 4:
989
            ret = ldl_phys((target_phys_addr_t)addr
990
                           | ((target_phys_addr_t)(asi & 0xf) << 32));
991
            break;
992
        case 8:
993
            ret = ldq_phys((target_phys_addr_t)addr
994
                           | ((target_phys_addr_t)(asi & 0xf) << 32));
995
            break;
996
        }
997
        break;
998
    case 0x30: // Turbosparc secondary cache diagnostic
999
    case 0x31: // Turbosparc RAM snoop
1000
    case 0x32: // Turbosparc page table descriptor diagnostic
1001
    case 0x39: /* data cache diagnostic register */
1002
        ret = 0;
1003
        break;
1004
    case 0x38: /* SuperSPARC MMU Breakpoint Control Registers */
1005
        {
1006
            int reg = (addr >> 8) & 3;
1007

    
1008
            switch(reg) {
1009
            case 0: /* Breakpoint Value (Addr) */
1010
                ret = env->mmubpregs[reg];
1011
                break;
1012
            case 1: /* Breakpoint Mask */
1013
                ret = env->mmubpregs[reg];
1014
                break;
1015
            case 2: /* Breakpoint Control */
1016
                ret = env->mmubpregs[reg];
1017
                break;
1018
            case 3: /* Breakpoint Status */
1019
                ret = env->mmubpregs[reg];
1020
                env->mmubpregs[reg] = 0ULL;
1021
                break;
1022
            }
1023
            DPRINTF_MMU("read breakpoint reg[%d] 0x%016llx\n", reg, ret);
1024
        }
1025
        break;
1026
    case 8: /* User code access, XXX */
1027
    default:
1028
        do_unassigned_access(addr, 0, 0, asi, size);
1029
        ret = 0;
1030
        break;
1031
    }
1032
    if (sign) {
1033
        switch(size) {
1034
        case 1:
1035
            ret = (int8_t) ret;
1036
            break;
1037
        case 2:
1038
            ret = (int16_t) ret;
1039
            break;
1040
        case 4:
1041
            ret = (int32_t) ret;
1042
            break;
1043
        default:
1044
            break;
1045
        }
1046
    }
1047
#ifdef DEBUG_ASI
1048
    dump_asi("read ", last_addr, asi, size, ret);
1049
#endif
1050
    return ret;
1051
}
1052

    
1053
void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
1054
{
1055
    helper_check_align(addr, size - 1);
1056
    switch(asi) {
1057
    case 2: /* SuperSparc MXCC registers */
1058
        switch (addr) {
1059
        case 0x01c00000: /* MXCC stream data register 0 */
1060
            if (size == 8)
1061
                env->mxccdata[0] = val;
1062
            else
1063
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1064
                             size);
1065
            break;
1066
        case 0x01c00008: /* MXCC stream data register 1 */
1067
            if (size == 8)
1068
                env->mxccdata[1] = val;
1069
            else
1070
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1071
                             size);
1072
            break;
1073
        case 0x01c00010: /* MXCC stream data register 2 */
1074
            if (size == 8)
1075
                env->mxccdata[2] = val;
1076
            else
1077
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1078
                             size);
1079
            break;
1080
        case 0x01c00018: /* MXCC stream data register 3 */
1081
            if (size == 8)
1082
                env->mxccdata[3] = val;
1083
            else
1084
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1085
                             size);
1086
            break;
1087
        case 0x01c00100: /* MXCC stream source */
1088
            if (size == 8)
1089
                env->mxccregs[0] = val;
1090
            else
1091
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1092
                             size);
1093
            env->mxccdata[0] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1094
                                        0);
1095
            env->mxccdata[1] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1096
                                        8);
1097
            env->mxccdata[2] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1098
                                        16);
1099
            env->mxccdata[3] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1100
                                        24);
1101
            break;
1102
        case 0x01c00200: /* MXCC stream destination */
1103
            if (size == 8)
1104
                env->mxccregs[1] = val;
1105
            else
1106
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1107
                             size);
1108
            stq_phys((env->mxccregs[1] & 0xffffffffULL) +  0,
1109
                     env->mxccdata[0]);
1110
            stq_phys((env->mxccregs[1] & 0xffffffffULL) +  8,
1111
                     env->mxccdata[1]);
1112
            stq_phys((env->mxccregs[1] & 0xffffffffULL) + 16,
1113
                     env->mxccdata[2]);
1114
            stq_phys((env->mxccregs[1] & 0xffffffffULL) + 24,
1115
                     env->mxccdata[3]);
1116
            break;
1117
        case 0x01c00a00: /* MXCC control register */
1118
            if (size == 8)
1119
                env->mxccregs[3] = val;
1120
            else
1121
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1122
                             size);
1123
            break;
1124
        case 0x01c00a04: /* MXCC control register */
1125
            if (size == 4)
1126
                env->mxccregs[3] = (env->mxccregs[3] & 0xffffffff00000000ULL)
1127
                    | val;
1128
            else
1129
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1130
                             size);
1131
            break;
1132
        case 0x01c00e00: /* MXCC error register  */
1133
            // writing a 1 bit clears the error
1134
            if (size == 8)
1135
                env->mxccregs[6] &= ~val;
1136
            else
1137
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1138
                             size);
1139
            break;
1140
        case 0x01c00f00: /* MBus port address register */
1141
            if (size == 8)
1142
                env->mxccregs[7] = val;
1143
            else
1144
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1145
                             size);
1146
            break;
1147
        default:
1148
            DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr,
1149
                         size);
1150
            break;
1151
        }
1152
        DPRINTF_MXCC("asi = %d, size = %d, addr = %08x, val = %" PRIx64 "\n",
1153
                     asi, size, addr, val);
1154
#ifdef DEBUG_MXCC
1155
        dump_mxcc(env);
1156
#endif
1157
        break;
1158
    case 3: /* MMU flush */
1159
        {
1160
            int mmulev;
1161

    
1162
            mmulev = (addr >> 8) & 15;
1163
            DPRINTF_MMU("mmu flush level %d\n", mmulev);
1164
            switch (mmulev) {
1165
            case 0: // flush page
1166
                tlb_flush_page(env, addr & 0xfffff000);
1167
                break;
1168
            case 1: // flush segment (256k)
1169
            case 2: // flush region (16M)
1170
            case 3: // flush context (4G)
1171
            case 4: // flush entire
1172
                tlb_flush(env, 1);
1173
                break;
1174
            default:
1175
                break;
1176
            }
1177
#ifdef DEBUG_MMU
1178
            dump_mmu(env);
1179
#endif
1180
        }
1181
        break;
1182
    case 4: /* write MMU regs */
1183
        {
1184
            int reg = (addr >> 8) & 0x1f;
1185
            uint32_t oldreg;
1186

    
1187
            oldreg = env->mmuregs[reg];
1188
            switch(reg) {
1189
            case 0: // Control Register
1190
                env->mmuregs[reg] = (env->mmuregs[reg] & 0xff000000) |
1191
                                    (val & 0x00ffffff);
1192
                // Mappings generated during no-fault mode or MMU
1193
                // disabled mode are invalid in normal mode
1194
                if ((oldreg & (MMU_E | MMU_NF | env->def->mmu_bm)) !=
1195
                    (env->mmuregs[reg] & (MMU_E | MMU_NF | env->def->mmu_bm)))
1196
                    tlb_flush(env, 1);
1197
                break;
1198
            case 1: // Context Table Pointer Register
1199
                env->mmuregs[reg] = val & env->def->mmu_ctpr_mask;
1200
                break;
1201
            case 2: // Context Register
1202
                env->mmuregs[reg] = val & env->def->mmu_cxr_mask;
1203
                if (oldreg != env->mmuregs[reg]) {
1204
                    /* we flush when the MMU context changes because
1205
                       QEMU has no MMU context support */
1206
                    tlb_flush(env, 1);
1207
                }
1208
                break;
1209
            case 3: // Synchronous Fault Status Register with Clear
1210
            case 4: // Synchronous Fault Address Register
1211
                break;
1212
            case 0x10: // TLB Replacement Control Register
1213
                env->mmuregs[reg] = val & env->def->mmu_trcr_mask;
1214
                break;
1215
            case 0x13: // Synchronous Fault Status Register with Read and Clear
1216
                env->mmuregs[3] = val & env->def->mmu_sfsr_mask;
1217
                break;
1218
            case 0x14: // Synchronous Fault Address Register
1219
                env->mmuregs[4] = val;
1220
                break;
1221
            default:
1222
                env->mmuregs[reg] = val;
1223
                break;
1224
            }
1225
            if (oldreg != env->mmuregs[reg]) {
1226
                DPRINTF_MMU("mmu change reg[%d]: 0x%08x -> 0x%08x\n",
1227
                            reg, oldreg, env->mmuregs[reg]);
1228
            }
1229
#ifdef DEBUG_MMU
1230
            dump_mmu(env);
1231
#endif
1232
        }
1233
        break;
1234
    case 5: // Turbosparc ITLB Diagnostic
1235
    case 6: // Turbosparc DTLB Diagnostic
1236
    case 7: // Turbosparc IOTLB Diagnostic
1237
        break;
1238
    case 0xa: /* User data access */
1239
        switch(size) {
1240
        case 1:
1241
            stb_user(addr, val);
1242
            break;
1243
        case 2:
1244
            stw_user(addr, val);
1245
            break;
1246
        default:
1247
        case 4:
1248
            stl_user(addr, val);
1249
            break;
1250
        case 8:
1251
            stq_user(addr, val);
1252
            break;
1253
        }
1254
        break;
1255
    case 0xb: /* Supervisor data access */
1256
        switch(size) {
1257
        case 1:
1258
            stb_kernel(addr, val);
1259
            break;
1260
        case 2:
1261
            stw_kernel(addr, val);
1262
            break;
1263
        default:
1264
        case 4:
1265
            stl_kernel(addr, val);
1266
            break;
1267
        case 8:
1268
            stq_kernel(addr, val);
1269
            break;
1270
        }
1271
        break;
1272
    case 0xc: /* I-cache tag */
1273
    case 0xd: /* I-cache data */
1274
    case 0xe: /* D-cache tag */
1275
    case 0xf: /* D-cache data */
1276
    case 0x10: /* I/D-cache flush page */
1277
    case 0x11: /* I/D-cache flush segment */
1278
    case 0x12: /* I/D-cache flush region */
1279
    case 0x13: /* I/D-cache flush context */
1280
    case 0x14: /* I/D-cache flush user */
1281
        break;
1282
    case 0x17: /* Block copy, sta access */
1283
        {
1284
            // val = src
1285
            // addr = dst
1286
            // copy 32 bytes
1287
            unsigned int i;
1288
            uint32_t src = val & ~3, dst = addr & ~3, temp;
1289

    
1290
            for (i = 0; i < 32; i += 4, src += 4, dst += 4) {
1291
                temp = ldl_kernel(src);
1292
                stl_kernel(dst, temp);
1293
            }
1294
        }
1295
        break;
1296
    case 0x1f: /* Block fill, stda access */
1297
        {
1298
            // addr = dst
1299
            // fill 32 bytes with val
1300
            unsigned int i;
1301
            uint32_t dst = addr & 7;
1302

    
1303
            for (i = 0; i < 32; i += 8, dst += 8)
1304
                stq_kernel(dst, val);
1305
        }
1306
        break;
1307
    case 0x20: /* MMU passthrough */
1308
        {
1309
            switch(size) {
1310
            case 1:
1311
                stb_phys(addr, val);
1312
                break;
1313
            case 2:
1314
                stw_phys(addr, val);
1315
                break;
1316
            case 4:
1317
            default:
1318
                stl_phys(addr, val);
1319
                break;
1320
            case 8:
1321
                stq_phys(addr, val);
1322
                break;
1323
            }
1324
        }
1325
        break;
1326
    case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
1327
        {
1328
            switch(size) {
1329
            case 1:
1330
                stb_phys((target_phys_addr_t)addr
1331
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1332
                break;
1333
            case 2:
1334
                stw_phys((target_phys_addr_t)addr
1335
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1336
                break;
1337
            case 4:
1338
            default:
1339
                stl_phys((target_phys_addr_t)addr
1340
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1341
                break;
1342
            case 8:
1343
                stq_phys((target_phys_addr_t)addr
1344
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1345
                break;
1346
            }
1347
        }
1348
        break;
1349
    case 0x30: // store buffer tags or Turbosparc secondary cache diagnostic
1350
    case 0x31: // store buffer data, Ross RT620 I-cache flush or
1351
               // Turbosparc snoop RAM
1352
    case 0x32: // store buffer control or Turbosparc page table
1353
               // descriptor diagnostic
1354
    case 0x36: /* I-cache flash clear */
1355
    case 0x37: /* D-cache flash clear */
1356
    case 0x4c: /* breakpoint action */
1357
        break;
1358
    case 0x38: /* SuperSPARC MMU Breakpoint Control Registers*/
1359
        {
1360
            int reg = (addr >> 8) & 3;
1361

    
1362
            switch(reg) {
1363
            case 0: /* Breakpoint Value (Addr) */
1364
                env->mmubpregs[reg] = (val & 0xfffffffffULL);
1365
                break;
1366
            case 1: /* Breakpoint Mask */
1367
                env->mmubpregs[reg] = (val & 0xfffffffffULL);
1368
                break;
1369
            case 2: /* Breakpoint Control */
1370
                env->mmubpregs[reg] = (val & 0x7fULL);
1371
                break;
1372
            case 3: /* Breakpoint Status */
1373
                env->mmubpregs[reg] = (val & 0xfULL);
1374
                break;
1375
            }
1376
            DPRINTF_MMU("write breakpoint reg[%d] 0x%016llx\n", reg,
1377
                        env->mmuregs[reg]);
1378
        }
1379
        break;
1380
    case 8: /* User code access, XXX */
1381
    case 9: /* Supervisor code access, XXX */
1382
    default:
1383
        do_unassigned_access(addr, 1, 0, asi, size);
1384
        break;
1385
    }
1386
#ifdef DEBUG_ASI
1387
    dump_asi("write", addr, asi, size, val);
1388
#endif
1389
}
1390

    
1391
#endif /* CONFIG_USER_ONLY */
1392
#else /* TARGET_SPARC64 */
1393

    
1394
#ifdef CONFIG_USER_ONLY
1395
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1396
{
1397
    uint64_t ret = 0;
1398
#if defined(DEBUG_ASI)
1399
    target_ulong last_addr = addr;
1400
#endif
1401

    
1402
    if (asi < 0x80)
1403
        raise_exception(TT_PRIV_ACT);
1404

    
1405
    helper_check_align(addr, size - 1);
1406
    address_mask(env, &addr);
1407

    
1408
    switch (asi) {
1409
    case 0x82: // Primary no-fault
1410
    case 0x8a: // Primary no-fault LE
1411
        if (page_check_range(addr, size, PAGE_READ) == -1) {
1412
#ifdef DEBUG_ASI
1413
            dump_asi("read ", last_addr, asi, size, ret);
1414
#endif
1415
            return 0;
1416
        }
1417
        // Fall through
1418
    case 0x80: // Primary
1419
    case 0x88: // Primary LE
1420
        {
1421
            switch(size) {
1422
            case 1:
1423
                ret = ldub_raw(addr);
1424
                break;
1425
            case 2:
1426
                ret = lduw_raw(addr);
1427
                break;
1428
            case 4:
1429
                ret = ldl_raw(addr);
1430
                break;
1431
            default:
1432
            case 8:
1433
                ret = ldq_raw(addr);
1434
                break;
1435
            }
1436
        }
1437
        break;
1438
    case 0x83: // Secondary no-fault
1439
    case 0x8b: // Secondary no-fault LE
1440
        if (page_check_range(addr, size, PAGE_READ) == -1) {
1441
#ifdef DEBUG_ASI
1442
            dump_asi("read ", last_addr, asi, size, ret);
1443
#endif
1444
            return 0;
1445
        }
1446
        // Fall through
1447
    case 0x81: // Secondary
1448
    case 0x89: // Secondary LE
1449
        // XXX
1450
        break;
1451
    default:
1452
        break;
1453
    }
1454

    
1455
    /* Convert from little endian */
1456
    switch (asi) {
1457
    case 0x88: // Primary LE
1458
    case 0x89: // Secondary LE
1459
    case 0x8a: // Primary no-fault LE
1460
    case 0x8b: // Secondary no-fault LE
1461
        switch(size) {
1462
        case 2:
1463
            ret = bswap16(ret);
1464
            break;
1465
        case 4:
1466
            ret = bswap32(ret);
1467
            break;
1468
        case 8:
1469
            ret = bswap64(ret);
1470
            break;
1471
        default:
1472
            break;
1473
        }
1474
    default:
1475
        break;
1476
    }
1477

    
1478
    /* Convert to signed number */
1479
    if (sign) {
1480
        switch(size) {
1481
        case 1:
1482
            ret = (int8_t) ret;
1483
            break;
1484
        case 2:
1485
            ret = (int16_t) ret;
1486
            break;
1487
        case 4:
1488
            ret = (int32_t) ret;
1489
            break;
1490
        default:
1491
            break;
1492
        }
1493
    }
1494
#ifdef DEBUG_ASI
1495
    dump_asi("read ", last_addr, asi, size, ret);
1496
#endif
1497
    return ret;
1498
}
1499

    
1500
void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
1501
{
1502
#ifdef DEBUG_ASI
1503
    dump_asi("write", addr, asi, size, val);
1504
#endif
1505
    if (asi < 0x80)
1506
        raise_exception(TT_PRIV_ACT);
1507

    
1508
    helper_check_align(addr, size - 1);
1509
    address_mask(env, &addr);
1510

    
1511
    /* Convert to little endian */
1512
    switch (asi) {
1513
    case 0x88: // Primary LE
1514
    case 0x89: // Secondary LE
1515
        switch(size) {
1516
        case 2:
1517
            addr = bswap16(addr);
1518
            break;
1519
        case 4:
1520
            addr = bswap32(addr);
1521
            break;
1522
        case 8:
1523
            addr = bswap64(addr);
1524
            break;
1525
        default:
1526
            break;
1527
        }
1528
    default:
1529
        break;
1530
    }
1531

    
1532
    switch(asi) {
1533
    case 0x80: // Primary
1534
    case 0x88: // Primary LE
1535
        {
1536
            switch(size) {
1537
            case 1:
1538
                stb_raw(addr, val);
1539
                break;
1540
            case 2:
1541
                stw_raw(addr, val);
1542
                break;
1543
            case 4:
1544
                stl_raw(addr, val);
1545
                break;
1546
            case 8:
1547
            default:
1548
                stq_raw(addr, val);
1549
                break;
1550
            }
1551
        }
1552
        break;
1553
    case 0x81: // Secondary
1554
    case 0x89: // Secondary LE
1555
        // XXX
1556
        return;
1557

    
1558
    case 0x82: // Primary no-fault, RO
1559
    case 0x83: // Secondary no-fault, RO
1560
    case 0x8a: // Primary no-fault LE, RO
1561
    case 0x8b: // Secondary no-fault LE, RO
1562
    default:
1563
        do_unassigned_access(addr, 1, 0, 1, size);
1564
        return;
1565
    }
1566
}
1567

    
1568
#else /* CONFIG_USER_ONLY */
1569

    
1570
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1571
{
1572
    uint64_t ret = 0;
1573
#if defined(DEBUG_ASI)
1574
    target_ulong last_addr = addr;
1575
#endif
1576

    
1577
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
1578
        || ((env->def->features & CPU_FEATURE_HYPV)
1579
            && asi >= 0x30 && asi < 0x80
1580
            && !(env->hpstate & HS_PRIV)))
1581
        raise_exception(TT_PRIV_ACT);
1582

    
1583
    helper_check_align(addr, size - 1);
1584
    switch (asi) {
1585
    case 0x82: // Primary no-fault
1586
    case 0x8a: // Primary no-fault LE
1587
        if (cpu_get_phys_page_debug(env, addr) == -1ULL) {
1588
#ifdef DEBUG_ASI
1589
            dump_asi("read ", last_addr, asi, size, ret);
1590
#endif
1591
            return 0;
1592
        }
1593
        // Fall through
1594
    case 0x10: // As if user primary
1595
    case 0x18: // As if user primary LE
1596
    case 0x80: // Primary
1597
    case 0x88: // Primary LE
1598
    case 0xe2: // UA2007 Primary block init
1599
    case 0xe3: // UA2007 Secondary block init
1600
        if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
1601
            if ((env->def->features & CPU_FEATURE_HYPV)
1602
                && env->hpstate & HS_PRIV) {
1603
                switch(size) {
1604
                case 1:
1605
                    ret = ldub_hypv(addr);
1606
                    break;
1607
                case 2:
1608
                    ret = lduw_hypv(addr);
1609
                    break;
1610
                case 4:
1611
                    ret = ldl_hypv(addr);
1612
                    break;
1613
                default:
1614
                case 8:
1615
                    ret = ldq_hypv(addr);
1616
                    break;
1617
                }
1618
            } else {
1619
                switch(size) {
1620
                case 1:
1621
                    ret = ldub_kernel(addr);
1622
                    break;
1623
                case 2:
1624
                    ret = lduw_kernel(addr);
1625
                    break;
1626
                case 4:
1627
                    ret = ldl_kernel(addr);
1628
                    break;
1629
                default:
1630
                case 8:
1631
                    ret = ldq_kernel(addr);
1632
                    break;
1633
                }
1634
            }
1635
        } else {
1636
            switch(size) {
1637
            case 1:
1638
                ret = ldub_user(addr);
1639
                break;
1640
            case 2:
1641
                ret = lduw_user(addr);
1642
                break;
1643
            case 4:
1644
                ret = ldl_user(addr);
1645
                break;
1646
            default:
1647
            case 8:
1648
                ret = ldq_user(addr);
1649
                break;
1650
            }
1651
        }
1652
        break;
1653
    case 0x14: // Bypass
1654
    case 0x15: // Bypass, non-cacheable
1655
    case 0x1c: // Bypass LE
1656
    case 0x1d: // Bypass, non-cacheable LE
1657
        {
1658
            switch(size) {
1659
            case 1:
1660
                ret = ldub_phys(addr);
1661
                break;
1662
            case 2:
1663
                ret = lduw_phys(addr);
1664
                break;
1665
            case 4:
1666
                ret = ldl_phys(addr);
1667
                break;
1668
            default:
1669
            case 8:
1670
                ret = ldq_phys(addr);
1671
                break;
1672
            }
1673
            break;
1674
        }
1675
    case 0x24: // Nucleus quad LDD 128 bit atomic
1676
    case 0x2c: // Nucleus quad LDD 128 bit atomic LE
1677
        //  Only ldda allowed
1678
        raise_exception(TT_ILL_INSN);
1679
        return 0;
1680
    case 0x83: // Secondary no-fault
1681
    case 0x8b: // Secondary no-fault LE
1682
        if (cpu_get_phys_page_debug(env, addr) == -1ULL) {
1683
#ifdef DEBUG_ASI
1684
            dump_asi("read ", last_addr, asi, size, ret);
1685
#endif
1686
            return 0;
1687
        }
1688
        // Fall through
1689
    case 0x04: // Nucleus
1690
    case 0x0c: // Nucleus Little Endian (LE)
1691
    case 0x11: // As if user secondary
1692
    case 0x19: // As if user secondary LE
1693
    case 0x4a: // UPA config
1694
    case 0x81: // Secondary
1695
    case 0x89: // Secondary LE
1696
        // XXX
1697
        break;
1698
    case 0x45: // LSU
1699
        ret = env->lsu;
1700
        break;
1701
    case 0x50: // I-MMU regs
1702
        {
1703
            int reg = (addr >> 3) & 0xf;
1704

    
1705
            if (reg == 0) {
1706
                // I-TSB Tag Target register
1707
                ret = ultrasparc_tag_target(env->immuregs[6]);
1708
            } else {
1709
                ret = env->immuregs[reg];
1710
            }
1711

    
1712
            break;
1713
        }
1714
    case 0x51: // I-MMU 8k TSB pointer
1715
        {
1716
            // env->immuregs[5] holds I-MMU TSB register value
1717
            // env->immuregs[6] holds I-MMU Tag Access register value
1718
            ret = ultrasparc_tsb_pointer(env->immuregs[5], env->immuregs[6],
1719
                                         8*1024);
1720
            break;
1721
        }
1722
    case 0x52: // I-MMU 64k TSB pointer
1723
        {
1724
            // env->immuregs[5] holds I-MMU TSB register value
1725
            // env->immuregs[6] holds I-MMU Tag Access register value
1726
            ret = ultrasparc_tsb_pointer(env->immuregs[5], env->immuregs[6],
1727
                                         64*1024);
1728
            break;
1729
        }
1730
    case 0x55: // I-MMU data access
1731
        {
1732
            int reg = (addr >> 3) & 0x3f;
1733

    
1734
            ret = env->itlb_tte[reg];
1735
            break;
1736
        }
1737
    case 0x56: // I-MMU tag read
1738
        {
1739
            int reg = (addr >> 3) & 0x3f;
1740

    
1741
            ret = env->itlb_tag[reg];
1742
            break;
1743
        }
1744
    case 0x58: // D-MMU regs
1745
        {
1746
            int reg = (addr >> 3) & 0xf;
1747

    
1748
            if (reg == 0) {
1749
                // D-TSB Tag Target register
1750
                ret = ultrasparc_tag_target(env->dmmuregs[6]);
1751
            } else {
1752
                ret = env->dmmuregs[reg];
1753
            }
1754
            break;
1755
        }
1756
    case 0x59: // D-MMU 8k TSB pointer
1757
        {
1758
            // env->dmmuregs[5] holds D-MMU TSB register value
1759
            // env->dmmuregs[6] holds D-MMU Tag Access register value
1760
            ret = ultrasparc_tsb_pointer(env->dmmuregs[5], env->dmmuregs[6],
1761
                                         8*1024);
1762
            break;
1763
        }
1764
    case 0x5a: // D-MMU 64k TSB pointer
1765
        {
1766
            // env->dmmuregs[5] holds D-MMU TSB register value
1767
            // env->dmmuregs[6] holds D-MMU Tag Access register value
1768
            ret = ultrasparc_tsb_pointer(env->dmmuregs[5], env->dmmuregs[6],
1769
                                         64*1024);
1770
            break;
1771
        }
1772
    case 0x5d: // D-MMU data access
1773
        {
1774
            int reg = (addr >> 3) & 0x3f;
1775

    
1776
            ret = env->dtlb_tte[reg];
1777
            break;
1778
        }
1779
    case 0x5e: // D-MMU tag read
1780
        {
1781
            int reg = (addr >> 3) & 0x3f;
1782

    
1783
            ret = env->dtlb_tag[reg];
1784
            break;
1785
        }
1786
    case 0x46: // D-cache data
1787
    case 0x47: // D-cache tag access
1788
    case 0x4b: // E-cache error enable
1789
    case 0x4c: // E-cache asynchronous fault status
1790
    case 0x4d: // E-cache asynchronous fault address
1791
    case 0x4e: // E-cache tag data
1792
    case 0x66: // I-cache instruction access
1793
    case 0x67: // I-cache tag access
1794
    case 0x6e: // I-cache predecode
1795
    case 0x6f: // I-cache LRU etc.
1796
    case 0x76: // E-cache tag
1797
    case 0x7e: // E-cache tag
1798
        break;
1799
    case 0x5b: // D-MMU data pointer
1800
    case 0x48: // Interrupt dispatch, RO
1801
    case 0x49: // Interrupt data receive
1802
    case 0x7f: // Incoming interrupt vector, RO
1803
        // XXX
1804
        break;
1805
    case 0x54: // I-MMU data in, WO
1806
    case 0x57: // I-MMU demap, WO
1807
    case 0x5c: // D-MMU data in, WO
1808
    case 0x5f: // D-MMU demap, WO
1809
    case 0x77: // Interrupt vector, WO
1810
    default:
1811
        do_unassigned_access(addr, 0, 0, 1, size);
1812
        ret = 0;
1813
        break;
1814
    }
1815

    
1816
    /* Convert from little endian */
1817
    switch (asi) {
1818
    case 0x0c: // Nucleus Little Endian (LE)
1819
    case 0x18: // As if user primary LE
1820
    case 0x19: // As if user secondary LE
1821
    case 0x1c: // Bypass LE
1822
    case 0x1d: // Bypass, non-cacheable LE
1823
    case 0x88: // Primary LE
1824
    case 0x89: // Secondary LE
1825
    case 0x8a: // Primary no-fault LE
1826
    case 0x8b: // Secondary no-fault LE
1827
        switch(size) {
1828
        case 2:
1829
            ret = bswap16(ret);
1830
            break;
1831
        case 4:
1832
            ret = bswap32(ret);
1833
            break;
1834
        case 8:
1835
            ret = bswap64(ret);
1836
            break;
1837
        default:
1838
            break;
1839
        }
1840
    default:
1841
        break;
1842
    }
1843

    
1844
    /* Convert to signed number */
1845
    if (sign) {
1846
        switch(size) {
1847
        case 1:
1848
            ret = (int8_t) ret;
1849
            break;
1850
        case 2:
1851
            ret = (int16_t) ret;
1852
            break;
1853
        case 4:
1854
            ret = (int32_t) ret;
1855
            break;
1856
        default:
1857
            break;
1858
        }
1859
    }
1860
#ifdef DEBUG_ASI
1861
    dump_asi("read ", last_addr, asi, size, ret);
1862
#endif
1863
    return ret;
1864
}
1865

    
1866
void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
1867
{
1868
#ifdef DEBUG_ASI
1869
    dump_asi("write", addr, asi, size, val);
1870
#endif
1871
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
1872
        || ((env->def->features & CPU_FEATURE_HYPV)
1873
            && asi >= 0x30 && asi < 0x80
1874
            && !(env->hpstate & HS_PRIV)))
1875
        raise_exception(TT_PRIV_ACT);
1876

    
1877
    helper_check_align(addr, size - 1);
1878
    /* Convert to little endian */
1879
    switch (asi) {
1880
    case 0x0c: // Nucleus Little Endian (LE)
1881
    case 0x18: // As if user primary LE
1882
    case 0x19: // As if user secondary LE
1883
    case 0x1c: // Bypass LE
1884
    case 0x1d: // Bypass, non-cacheable LE
1885
    case 0x88: // Primary LE
1886
    case 0x89: // Secondary LE
1887
        switch(size) {
1888
        case 2:
1889
            addr = bswap16(addr);
1890
            break;
1891
        case 4:
1892
            addr = bswap32(addr);
1893
            break;
1894
        case 8:
1895
            addr = bswap64(addr);
1896
            break;
1897
        default:
1898
            break;
1899
        }
1900
    default:
1901
        break;
1902
    }
1903

    
1904
    switch(asi) {
1905
    case 0x10: // As if user primary
1906
    case 0x18: // As if user primary LE
1907
    case 0x80: // Primary
1908
    case 0x88: // Primary LE
1909
    case 0xe2: // UA2007 Primary block init
1910
    case 0xe3: // UA2007 Secondary block init
1911
        if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
1912
            if ((env->def->features & CPU_FEATURE_HYPV)
1913
                && env->hpstate & HS_PRIV) {
1914
                switch(size) {
1915
                case 1:
1916
                    stb_hypv(addr, val);
1917
                    break;
1918
                case 2:
1919
                    stw_hypv(addr, val);
1920
                    break;
1921
                case 4:
1922
                    stl_hypv(addr, val);
1923
                    break;
1924
                case 8:
1925
                default:
1926
                    stq_hypv(addr, val);
1927
                    break;
1928
                }
1929
            } else {
1930
                switch(size) {
1931
                case 1:
1932
                    stb_kernel(addr, val);
1933
                    break;
1934
                case 2:
1935
                    stw_kernel(addr, val);
1936
                    break;
1937
                case 4:
1938
                    stl_kernel(addr, val);
1939
                    break;
1940
                case 8:
1941
                default:
1942
                    stq_kernel(addr, val);
1943
                    break;
1944
                }
1945
            }
1946
        } else {
1947
            switch(size) {
1948
            case 1:
1949
                stb_user(addr, val);
1950
                break;
1951
            case 2:
1952
                stw_user(addr, val);
1953
                break;
1954
            case 4:
1955
                stl_user(addr, val);
1956
                break;
1957
            case 8:
1958
            default:
1959
                stq_user(addr, val);
1960
                break;
1961
            }
1962
        }
1963
        break;
1964
    case 0x14: // Bypass
1965
    case 0x15: // Bypass, non-cacheable
1966
    case 0x1c: // Bypass LE
1967
    case 0x1d: // Bypass, non-cacheable LE
1968
        {
1969
            switch(size) {
1970
            case 1:
1971
                stb_phys(addr, val);
1972
                break;
1973
            case 2:
1974
                stw_phys(addr, val);
1975
                break;
1976
            case 4:
1977
                stl_phys(addr, val);
1978
                break;
1979
            case 8:
1980
            default:
1981
                stq_phys(addr, val);
1982
                break;
1983
            }
1984
        }
1985
        return;
1986
    case 0x24: // Nucleus quad LDD 128 bit atomic
1987
    case 0x2c: // Nucleus quad LDD 128 bit atomic LE
1988
        //  Only ldda allowed
1989
        raise_exception(TT_ILL_INSN);
1990
        return;
1991
    case 0x04: // Nucleus
1992
    case 0x0c: // Nucleus Little Endian (LE)
1993
    case 0x11: // As if user secondary
1994
    case 0x19: // As if user secondary LE
1995
    case 0x4a: // UPA config
1996
    case 0x81: // Secondary
1997
    case 0x89: // Secondary LE
1998
        // XXX
1999
        return;
2000
    case 0x45: // LSU
2001
        {
2002
            uint64_t oldreg;
2003

    
2004
            oldreg = env->lsu;
2005
            env->lsu = val & (DMMU_E | IMMU_E);
2006
            // Mappings generated during D/I MMU disabled mode are
2007
            // invalid in normal mode
2008
            if (oldreg != env->lsu) {
2009
                DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n",
2010
                            oldreg, env->lsu);
2011
#ifdef DEBUG_MMU
2012
                dump_mmu(env);
2013
#endif
2014
                tlb_flush(env, 1);
2015
            }
2016
            return;
2017
        }
2018
    case 0x50: // I-MMU regs
2019
        {
2020
            int reg = (addr >> 3) & 0xf;
2021
            uint64_t oldreg;
2022

    
2023
            oldreg = env->immuregs[reg];
2024
            switch(reg) {
2025
            case 0: // RO
2026
            case 4:
2027
                return;
2028
            case 1: // Not in I-MMU
2029
            case 2:
2030
            case 7:
2031
            case 8:
2032
                return;
2033
            case 3: // SFSR
2034
                if ((val & 1) == 0)
2035
                    val = 0; // Clear SFSR
2036
                break;
2037
            case 5: // TSB access
2038
            case 6: // Tag access
2039
            default:
2040
                break;
2041
            }
2042
            env->immuregs[reg] = val;
2043
            if (oldreg != env->immuregs[reg]) {
2044
                DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08"
2045
                            PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
2046
            }
2047
#ifdef DEBUG_MMU
2048
            dump_mmu(env);
2049
#endif
2050
            return;
2051
        }
2052
    case 0x54: // I-MMU data in
2053
        {
2054
            unsigned int i;
2055

    
2056
            // Try finding an invalid entry
2057
            for (i = 0; i < 64; i++) {
2058
                if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) {
2059
                    env->itlb_tag[i] = env->immuregs[6];
2060
                    env->itlb_tte[i] = val;
2061
                    return;
2062
                }
2063
            }
2064
            // Try finding an unlocked entry
2065
            for (i = 0; i < 64; i++) {
2066
                if ((env->itlb_tte[i] & 0x40) == 0) {
2067
                    env->itlb_tag[i] = env->immuregs[6];
2068
                    env->itlb_tte[i] = val;
2069
                    return;
2070
                }
2071
            }
2072
            // error state?
2073
            return;
2074
        }
2075
    case 0x55: // I-MMU data access
2076
        {
2077
            // TODO: auto demap
2078

    
2079
            unsigned int i = (addr >> 3) & 0x3f;
2080

    
2081
            env->itlb_tag[i] = env->immuregs[6];
2082
            env->itlb_tte[i] = val;
2083
            return;
2084
        }
2085
    case 0x57: // I-MMU demap
2086
        {
2087
            unsigned int i;
2088

    
2089
            for (i = 0; i < 64; i++) {
2090
                if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) {
2091
                    target_ulong mask = 0xffffffffffffe000ULL;
2092

    
2093
                    mask <<= 3 * ((env->itlb_tte[i] >> 61) & 3);
2094
                    if ((val & mask) == (env->itlb_tag[i] & mask)) {
2095
                        env->itlb_tag[i] = 0;
2096
                        env->itlb_tte[i] = 0;
2097
                    }
2098
                    return;
2099
                }
2100
            }
2101
        }
2102
        return;
2103
    case 0x58: // D-MMU regs
2104
        {
2105
            int reg = (addr >> 3) & 0xf;
2106
            uint64_t oldreg;
2107

    
2108
            oldreg = env->dmmuregs[reg];
2109
            switch(reg) {
2110
            case 0: // RO
2111
            case 4:
2112
                return;
2113
            case 3: // SFSR
2114
                if ((val & 1) == 0) {
2115
                    val = 0; // Clear SFSR, Fault address
2116
                    env->dmmuregs[4] = 0;
2117
                }
2118
                env->dmmuregs[reg] = val;
2119
                break;
2120
            case 1: // Primary context
2121
            case 2: // Secondary context
2122
            case 5: // TSB access
2123
            case 6: // Tag access
2124
            case 7: // Virtual Watchpoint
2125
            case 8: // Physical Watchpoint
2126
            default:
2127
                break;
2128
            }
2129
            env->dmmuregs[reg] = val;
2130
            if (oldreg != env->dmmuregs[reg]) {
2131
                DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08"
2132
                            PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
2133
            }
2134
#ifdef DEBUG_MMU
2135
            dump_mmu(env);
2136
#endif
2137
            return;
2138
        }
2139
    case 0x5c: // D-MMU data in
2140
        {
2141
            unsigned int i;
2142

    
2143
            // Try finding an invalid entry
2144
            for (i = 0; i < 64; i++) {
2145
                if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) {
2146
                    env->dtlb_tag[i] = env->dmmuregs[6];
2147
                    env->dtlb_tte[i] = val;
2148
                    return;
2149
                }
2150
            }
2151
            // Try finding an unlocked entry
2152
            for (i = 0; i < 64; i++) {
2153
                if ((env->dtlb_tte[i] & 0x40) == 0) {
2154
                    env->dtlb_tag[i] = env->dmmuregs[6];
2155
                    env->dtlb_tte[i] = val;
2156
                    return;
2157
                }
2158
            }
2159
            // error state?
2160
            return;
2161
        }
2162
    case 0x5d: // D-MMU data access
2163
        {
2164
            unsigned int i = (addr >> 3) & 0x3f;
2165

    
2166
            env->dtlb_tag[i] = env->dmmuregs[6];
2167
            env->dtlb_tte[i] = val;
2168
            return;
2169
        }
2170
    case 0x5f: // D-MMU demap
2171
        {
2172
            unsigned int i;
2173

    
2174
            for (i = 0; i < 64; i++) {
2175
                if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) {
2176
                    target_ulong mask = 0xffffffffffffe000ULL;
2177

    
2178
                    mask <<= 3 * ((env->dtlb_tte[i] >> 61) & 3);
2179
                    if ((val & mask) == (env->dtlb_tag[i] & mask)) {
2180
                        env->dtlb_tag[i] = 0;
2181
                        env->dtlb_tte[i] = 0;
2182
                    }
2183
                    return;
2184
                }
2185
            }
2186
        }
2187
        return;
2188
    case 0x49: // Interrupt data receive
2189
        // XXX
2190
        return;
2191
    case 0x46: // D-cache data
2192
    case 0x47: // D-cache tag access
2193
    case 0x4b: // E-cache error enable
2194
    case 0x4c: // E-cache asynchronous fault status
2195
    case 0x4d: // E-cache asynchronous fault address
2196
    case 0x4e: // E-cache tag data
2197
    case 0x66: // I-cache instruction access
2198
    case 0x67: // I-cache tag access
2199
    case 0x6e: // I-cache predecode
2200
    case 0x6f: // I-cache LRU etc.
2201
    case 0x76: // E-cache tag
2202
    case 0x7e: // E-cache tag
2203
        return;
2204
    case 0x51: // I-MMU 8k TSB pointer, RO
2205
    case 0x52: // I-MMU 64k TSB pointer, RO
2206
    case 0x56: // I-MMU tag read, RO
2207
    case 0x59: // D-MMU 8k TSB pointer, RO
2208
    case 0x5a: // D-MMU 64k TSB pointer, RO
2209
    case 0x5b: // D-MMU data pointer, RO
2210
    case 0x5e: // D-MMU tag read, RO
2211
    case 0x48: // Interrupt dispatch, RO
2212
    case 0x7f: // Incoming interrupt vector, RO
2213
    case 0x82: // Primary no-fault, RO
2214
    case 0x83: // Secondary no-fault, RO
2215
    case 0x8a: // Primary no-fault LE, RO
2216
    case 0x8b: // Secondary no-fault LE, RO
2217
    default:
2218
        do_unassigned_access(addr, 1, 0, 1, size);
2219
        return;
2220
    }
2221
}
2222
#endif /* CONFIG_USER_ONLY */
2223

    
2224
void helper_ldda_asi(target_ulong addr, int asi, int rd)
2225
{
2226
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
2227
        || ((env->def->features & CPU_FEATURE_HYPV)
2228
            && asi >= 0x30 && asi < 0x80
2229
            && !(env->hpstate & HS_PRIV)))
2230
        raise_exception(TT_PRIV_ACT);
2231

    
2232
    switch (asi) {
2233
    case 0x24: // Nucleus quad LDD 128 bit atomic
2234
    case 0x2c: // Nucleus quad LDD 128 bit atomic LE
2235
        helper_check_align(addr, 0xf);
2236
        if (rd == 0) {
2237
            env->gregs[1] = ldq_kernel(addr + 8);
2238
            if (asi == 0x2c)
2239
                bswap64s(&env->gregs[1]);
2240
        } else if (rd < 8) {
2241
            env->gregs[rd] = ldq_kernel(addr);
2242
            env->gregs[rd + 1] = ldq_kernel(addr + 8);
2243
            if (asi == 0x2c) {
2244
                bswap64s(&env->gregs[rd]);
2245
                bswap64s(&env->gregs[rd + 1]);
2246
            }
2247
        } else {
2248
            env->regwptr[rd] = ldq_kernel(addr);
2249
            env->regwptr[rd + 1] = ldq_kernel(addr + 8);
2250
            if (asi == 0x2c) {
2251
                bswap64s(&env->regwptr[rd]);
2252
                bswap64s(&env->regwptr[rd + 1]);
2253
            }
2254
        }
2255
        break;
2256
    default:
2257
        helper_check_align(addr, 0x3);
2258
        if (rd == 0)
2259
            env->gregs[1] = helper_ld_asi(addr + 4, asi, 4, 0);
2260
        else if (rd < 8) {
2261
            env->gregs[rd] = helper_ld_asi(addr, asi, 4, 0);
2262
            env->gregs[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
2263
        } else {
2264
            env->regwptr[rd] = helper_ld_asi(addr, asi, 4, 0);
2265
            env->regwptr[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
2266
        }
2267
        break;
2268
    }
2269
}
2270

    
2271
void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
2272
{
2273
    unsigned int i;
2274
    target_ulong val;
2275

    
2276
    helper_check_align(addr, 3);
2277
    switch (asi) {
2278
    case 0xf0: // Block load primary
2279
    case 0xf1: // Block load secondary
2280
    case 0xf8: // Block load primary LE
2281
    case 0xf9: // Block load secondary LE
2282
        if (rd & 7) {
2283
            raise_exception(TT_ILL_INSN);
2284
            return;
2285
        }
2286
        helper_check_align(addr, 0x3f);
2287
        for (i = 0; i < 16; i++) {
2288
            *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x8f, 4,
2289
                                                         0);
2290
            addr += 4;
2291
        }
2292

    
2293
        return;
2294
    default:
2295
        break;
2296
    }
2297

    
2298
    val = helper_ld_asi(addr, asi, size, 0);
2299
    switch(size) {
2300
    default:
2301
    case 4:
2302
        *((uint32_t *)&env->fpr[rd]) = val;
2303
        break;
2304
    case 8:
2305
        *((int64_t *)&DT0) = val;
2306
        break;
2307
    case 16:
2308
        // XXX
2309
        break;
2310
    }
2311
}
2312

    
2313
void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
2314
{
2315
    unsigned int i;
2316
    target_ulong val = 0;
2317

    
2318
    helper_check_align(addr, 3);
2319
    switch (asi) {
2320
    case 0xe0: // UA2007 Block commit store primary (cache flush)
2321
    case 0xe1: // UA2007 Block commit store secondary (cache flush)
2322
    case 0xf0: // Block store primary
2323
    case 0xf1: // Block store secondary
2324
    case 0xf8: // Block store primary LE
2325
    case 0xf9: // Block store secondary LE
2326
        if (rd & 7) {
2327
            raise_exception(TT_ILL_INSN);
2328
            return;
2329
        }
2330
        helper_check_align(addr, 0x3f);
2331
        for (i = 0; i < 16; i++) {
2332
            val = *(uint32_t *)&env->fpr[rd++];
2333
            helper_st_asi(addr, val, asi & 0x8f, 4);
2334
            addr += 4;
2335
        }
2336

    
2337
        return;
2338
    default:
2339
        break;
2340
    }
2341

    
2342
    switch(size) {
2343
    default:
2344
    case 4:
2345
        val = *((uint32_t *)&env->fpr[rd]);
2346
        break;
2347
    case 8:
2348
        val = *((int64_t *)&DT0);
2349
        break;
2350
    case 16:
2351
        // XXX
2352
        break;
2353
    }
2354
    helper_st_asi(addr, val, asi, size);
2355
}
2356

    
2357
target_ulong helper_cas_asi(target_ulong addr, target_ulong val1,
2358
                            target_ulong val2, uint32_t asi)
2359
{
2360
    target_ulong ret;
2361

    
2362
    val2 &= 0xffffffffUL;
2363
    ret = helper_ld_asi(addr, asi, 4, 0);
2364
    ret &= 0xffffffffUL;
2365
    if (val2 == ret)
2366
        helper_st_asi(addr, val1 & 0xffffffffUL, asi, 4);
2367
    return ret;
2368
}
2369

    
2370
target_ulong helper_casx_asi(target_ulong addr, target_ulong val1,
2371
                             target_ulong val2, uint32_t asi)
2372
{
2373
    target_ulong ret;
2374

    
2375
    ret = helper_ld_asi(addr, asi, 8, 0);
2376
    if (val2 == ret)
2377
        helper_st_asi(addr, val1, asi, 8);
2378
    return ret;
2379
}
2380
#endif /* TARGET_SPARC64 */
2381

    
2382
#ifndef TARGET_SPARC64
2383
void helper_rett(void)
2384
{
2385
    unsigned int cwp;
2386

    
2387
    if (env->psret == 1)
2388
        raise_exception(TT_ILL_INSN);
2389

    
2390
    env->psret = 1;
2391
    cwp = cpu_cwp_inc(env, env->cwp + 1) ;
2392
    if (env->wim & (1 << cwp)) {
2393
        raise_exception(TT_WIN_UNF);
2394
    }
2395
    set_cwp(cwp);
2396
    env->psrs = env->psrps;
2397
}
2398
#endif
2399

    
2400
target_ulong helper_udiv(target_ulong a, target_ulong b)
2401
{
2402
    uint64_t x0;
2403
    uint32_t x1;
2404

    
2405
    x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
2406
    x1 = b;
2407

    
2408
    if (x1 == 0) {
2409
        raise_exception(TT_DIV_ZERO);
2410
    }
2411

    
2412
    x0 = x0 / x1;
2413
    if (x0 > 0xffffffff) {
2414
        env->cc_src2 = 1;
2415
        return 0xffffffff;
2416
    } else {
2417
        env->cc_src2 = 0;
2418
        return x0;
2419
    }
2420
}
2421

    
2422
target_ulong helper_sdiv(target_ulong a, target_ulong b)
2423
{
2424
    int64_t x0;
2425
    int32_t x1;
2426

    
2427
    x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
2428
    x1 = b;
2429

    
2430
    if (x1 == 0) {
2431
        raise_exception(TT_DIV_ZERO);
2432
    }
2433

    
2434
    x0 = x0 / x1;
2435
    if ((int32_t) x0 != x0) {
2436
        env->cc_src2 = 1;
2437
        return x0 < 0? 0x80000000: 0x7fffffff;
2438
    } else {
2439
        env->cc_src2 = 0;
2440
        return x0;
2441
    }
2442
}
2443

    
2444
void helper_stdf(target_ulong addr, int mem_idx)
2445
{
2446
    helper_check_align(addr, 7);
2447
#if !defined(CONFIG_USER_ONLY)
2448
    switch (mem_idx) {
2449
    case 0:
2450
        stfq_user(addr, DT0);
2451
        break;
2452
    case 1:
2453
        stfq_kernel(addr, DT0);
2454
        break;
2455
#ifdef TARGET_SPARC64
2456
    case 2:
2457
        stfq_hypv(addr, DT0);
2458
        break;
2459
#endif
2460
    default:
2461
        break;
2462
    }
2463
#else
2464
    address_mask(env, &addr);
2465
    stfq_raw(addr, DT0);
2466
#endif
2467
}
2468

    
2469
void helper_lddf(target_ulong addr, int mem_idx)
2470
{
2471
    helper_check_align(addr, 7);
2472
#if !defined(CONFIG_USER_ONLY)
2473
    switch (mem_idx) {
2474
    case 0:
2475
        DT0 = ldfq_user(addr);
2476
        break;
2477
    case 1:
2478
        DT0 = ldfq_kernel(addr);
2479
        break;
2480
#ifdef TARGET_SPARC64
2481
    case 2:
2482
        DT0 = ldfq_hypv(addr);
2483
        break;
2484
#endif
2485
    default:
2486
        break;
2487
    }
2488
#else
2489
    address_mask(env, &addr);
2490
    DT0 = ldfq_raw(addr);
2491
#endif
2492
}
2493

    
2494
void helper_ldqf(target_ulong addr, int mem_idx)
2495
{
2496
    // XXX add 128 bit load
2497
    CPU_QuadU u;
2498

    
2499
    helper_check_align(addr, 7);
2500
#if !defined(CONFIG_USER_ONLY)
2501
    switch (mem_idx) {
2502
    case 0:
2503
        u.ll.upper = ldq_user(addr);
2504
        u.ll.lower = ldq_user(addr + 8);
2505
        QT0 = u.q;
2506
        break;
2507
    case 1:
2508
        u.ll.upper = ldq_kernel(addr);
2509
        u.ll.lower = ldq_kernel(addr + 8);
2510
        QT0 = u.q;
2511
        break;
2512
#ifdef TARGET_SPARC64
2513
    case 2:
2514
        u.ll.upper = ldq_hypv(addr);
2515
        u.ll.lower = ldq_hypv(addr + 8);
2516
        QT0 = u.q;
2517
        break;
2518
#endif
2519
    default:
2520
        break;
2521
    }
2522
#else
2523
    address_mask(env, &addr);
2524
    u.ll.upper = ldq_raw(addr);
2525
    u.ll.lower = ldq_raw((addr + 8) & 0xffffffffULL);
2526
    QT0 = u.q;
2527
#endif
2528
}
2529

    
2530
void helper_stqf(target_ulong addr, int mem_idx)
2531
{
2532
    // XXX add 128 bit store
2533
    CPU_QuadU u;
2534

    
2535
    helper_check_align(addr, 7);
2536
#if !defined(CONFIG_USER_ONLY)
2537
    switch (mem_idx) {
2538
    case 0:
2539
        u.q = QT0;
2540
        stq_user(addr, u.ll.upper);
2541
        stq_user(addr + 8, u.ll.lower);
2542
        break;
2543
    case 1:
2544
        u.q = QT0;
2545
        stq_kernel(addr, u.ll.upper);
2546
        stq_kernel(addr + 8, u.ll.lower);
2547
        break;
2548
#ifdef TARGET_SPARC64
2549
    case 2:
2550
        u.q = QT0;
2551
        stq_hypv(addr, u.ll.upper);
2552
        stq_hypv(addr + 8, u.ll.lower);
2553
        break;
2554
#endif
2555
    default:
2556
        break;
2557
    }
2558
#else
2559
    u.q = QT0;
2560
    address_mask(env, &addr);
2561
    stq_raw(addr, u.ll.upper);
2562
    stq_raw((addr + 8) & 0xffffffffULL, u.ll.lower);
2563
#endif
2564
}
2565

    
2566
static inline void set_fsr(void)
2567
{
2568
    int rnd_mode;
2569

    
2570
    switch (env->fsr & FSR_RD_MASK) {
2571
    case FSR_RD_NEAREST:
2572
        rnd_mode = float_round_nearest_even;
2573
        break;
2574
    default:
2575
    case FSR_RD_ZERO:
2576
        rnd_mode = float_round_to_zero;
2577
        break;
2578
    case FSR_RD_POS:
2579
        rnd_mode = float_round_up;
2580
        break;
2581
    case FSR_RD_NEG:
2582
        rnd_mode = float_round_down;
2583
        break;
2584
    }
2585
    set_float_rounding_mode(rnd_mode, &env->fp_status);
2586
}
2587

    
2588
void helper_ldfsr(uint32_t new_fsr)
2589
{
2590
    env->fsr = (new_fsr & FSR_LDFSR_MASK) | (env->fsr & FSR_LDFSR_OLDMASK);
2591
    set_fsr();
2592
}
2593

    
2594
#ifdef TARGET_SPARC64
2595
void helper_ldxfsr(uint64_t new_fsr)
2596
{
2597
    env->fsr = (new_fsr & FSR_LDXFSR_MASK) | (env->fsr & FSR_LDXFSR_OLDMASK);
2598
    set_fsr();
2599
}
2600
#endif
2601

    
2602
void helper_debug(void)
2603
{
2604
    env->exception_index = EXCP_DEBUG;
2605
    cpu_loop_exit();
2606
}
2607

    
2608
#ifndef TARGET_SPARC64
2609
/* XXX: use another pointer for %iN registers to avoid slow wrapping
2610
   handling ? */
2611
void helper_save(void)
2612
{
2613
    uint32_t cwp;
2614

    
2615
    cwp = cpu_cwp_dec(env, env->cwp - 1);
2616
    if (env->wim & (1 << cwp)) {
2617
        raise_exception(TT_WIN_OVF);
2618
    }
2619
    set_cwp(cwp);
2620
}
2621

    
2622
void helper_restore(void)
2623
{
2624
    uint32_t cwp;
2625

    
2626
    cwp = cpu_cwp_inc(env, env->cwp + 1);
2627
    if (env->wim & (1 << cwp)) {
2628
        raise_exception(TT_WIN_UNF);
2629
    }
2630
    set_cwp(cwp);
2631
}
2632

    
2633
void helper_wrpsr(target_ulong new_psr)
2634
{
2635
    if ((new_psr & PSR_CWP) >= env->nwindows)
2636
        raise_exception(TT_ILL_INSN);
2637
    else
2638
        PUT_PSR(env, new_psr);
2639
}
2640

    
2641
target_ulong helper_rdpsr(void)
2642
{
2643
    return GET_PSR(env);
2644
}
2645

    
2646
#else
2647
/* XXX: use another pointer for %iN registers to avoid slow wrapping
2648
   handling ? */
2649
void helper_save(void)
2650
{
2651
    uint32_t cwp;
2652

    
2653
    cwp = cpu_cwp_dec(env, env->cwp - 1);
2654
    if (env->cansave == 0) {
2655
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
2656
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
2657
                                    ((env->wstate & 0x7) << 2)));
2658
    } else {
2659
        if (env->cleanwin - env->canrestore == 0) {
2660
            // XXX Clean windows without trap
2661
            raise_exception(TT_CLRWIN);
2662
        } else {
2663
            env->cansave--;
2664
            env->canrestore++;
2665
            set_cwp(cwp);
2666
        }
2667
    }
2668
}
2669

    
2670
void helper_restore(void)
2671
{
2672
    uint32_t cwp;
2673

    
2674
    cwp = cpu_cwp_inc(env, env->cwp + 1);
2675
    if (env->canrestore == 0) {
2676
        raise_exception(TT_FILL | (env->otherwin != 0 ?
2677
                                   (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
2678
                                   ((env->wstate & 0x7) << 2)));
2679
    } else {
2680
        env->cansave++;
2681
        env->canrestore--;
2682
        set_cwp(cwp);
2683
    }
2684
}
2685

    
2686
void helper_flushw(void)
2687
{
2688
    if (env->cansave != env->nwindows - 2) {
2689
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
2690
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
2691
                                    ((env->wstate & 0x7) << 2)));
2692
    }
2693
}
2694

    
2695
void helper_saved(void)
2696
{
2697
    env->cansave++;
2698
    if (env->otherwin == 0)
2699
        env->canrestore--;
2700
    else
2701
        env->otherwin--;
2702
}
2703

    
2704
void helper_restored(void)
2705
{
2706
    env->canrestore++;
2707
    if (env->cleanwin < env->nwindows - 1)
2708
        env->cleanwin++;
2709
    if (env->otherwin == 0)
2710
        env->cansave--;
2711
    else
2712
        env->otherwin--;
2713
}
2714

    
2715
target_ulong helper_rdccr(void)
2716
{
2717
    return GET_CCR(env);
2718
}
2719

    
2720
void helper_wrccr(target_ulong new_ccr)
2721
{
2722
    PUT_CCR(env, new_ccr);
2723
}
2724

    
2725
// CWP handling is reversed in V9, but we still use the V8 register
2726
// order.
2727
target_ulong helper_rdcwp(void)
2728
{
2729
    return GET_CWP64(env);
2730
}
2731

    
2732
void helper_wrcwp(target_ulong new_cwp)
2733
{
2734
    PUT_CWP64(env, new_cwp);
2735
}
2736

    
2737
// This function uses non-native bit order
2738
#define GET_FIELD(X, FROM, TO)                                  \
2739
    ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
2740

    
2741
// This function uses the order in the manuals, i.e. bit 0 is 2^0
2742
#define GET_FIELD_SP(X, FROM, TO)               \
2743
    GET_FIELD(X, 63 - (TO), 63 - (FROM))
2744

    
2745
target_ulong helper_array8(target_ulong pixel_addr, target_ulong cubesize)
2746
{
2747
    return (GET_FIELD_SP(pixel_addr, 60, 63) << (17 + 2 * cubesize)) |
2748
        (GET_FIELD_SP(pixel_addr, 39, 39 + cubesize - 1) << (17 + cubesize)) |
2749
        (GET_FIELD_SP(pixel_addr, 17 + cubesize - 1, 17) << 17) |
2750
        (GET_FIELD_SP(pixel_addr, 56, 59) << 13) |
2751
        (GET_FIELD_SP(pixel_addr, 35, 38) << 9) |
2752
        (GET_FIELD_SP(pixel_addr, 13, 16) << 5) |
2753
        (((pixel_addr >> 55) & 1) << 4) |
2754
        (GET_FIELD_SP(pixel_addr, 33, 34) << 2) |
2755
        GET_FIELD_SP(pixel_addr, 11, 12);
2756
}
2757

    
2758
target_ulong helper_alignaddr(target_ulong addr, target_ulong offset)
2759
{
2760
    uint64_t tmp;
2761

    
2762
    tmp = addr + offset;
2763
    env->gsr &= ~7ULL;
2764
    env->gsr |= tmp & 7ULL;
2765
    return tmp & ~7ULL;
2766
}
2767

    
2768
target_ulong helper_popc(target_ulong val)
2769
{
2770
    return ctpop64(val);
2771
}
2772

    
2773
static inline uint64_t *get_gregset(uint64_t pstate)
2774
{
2775
    switch (pstate) {
2776
    default:
2777
    case 0:
2778
        return env->bgregs;
2779
    case PS_AG:
2780
        return env->agregs;
2781
    case PS_MG:
2782
        return env->mgregs;
2783
    case PS_IG:
2784
        return env->igregs;
2785
    }
2786
}
2787

    
2788
static inline void change_pstate(uint64_t new_pstate)
2789
{
2790
    uint64_t pstate_regs, new_pstate_regs;
2791
    uint64_t *src, *dst;
2792

    
2793
    pstate_regs = env->pstate & 0xc01;
2794
    new_pstate_regs = new_pstate & 0xc01;
2795
    if (new_pstate_regs != pstate_regs) {
2796
        // Switch global register bank
2797
        src = get_gregset(new_pstate_regs);
2798
        dst = get_gregset(pstate_regs);
2799
        memcpy32(dst, env->gregs);
2800
        memcpy32(env->gregs, src);
2801
    }
2802
    env->pstate = new_pstate;
2803
}
2804

    
2805
void helper_wrpstate(target_ulong new_state)
2806
{
2807
    if (!(env->def->features & CPU_FEATURE_GL))
2808
        change_pstate(new_state & 0xf3f);
2809
}
2810

    
2811
void helper_done(void)
2812
{
2813
    env->pc = env->tsptr->tpc;
2814
    env->npc = env->tsptr->tnpc + 4;
2815
    PUT_CCR(env, env->tsptr->tstate >> 32);
2816
    env->asi = (env->tsptr->tstate >> 24) & 0xff;
2817
    change_pstate((env->tsptr->tstate >> 8) & 0xf3f);
2818
    PUT_CWP64(env, env->tsptr->tstate & 0xff);
2819
    env->tl--;
2820
    env->tsptr = &env->ts[env->tl & MAXTL_MASK];
2821
}
2822

    
2823
void helper_retry(void)
2824
{
2825
    env->pc = env->tsptr->tpc;
2826
    env->npc = env->tsptr->tnpc;
2827
    PUT_CCR(env, env->tsptr->tstate >> 32);
2828
    env->asi = (env->tsptr->tstate >> 24) & 0xff;
2829
    change_pstate((env->tsptr->tstate >> 8) & 0xf3f);
2830
    PUT_CWP64(env, env->tsptr->tstate & 0xff);
2831
    env->tl--;
2832
    env->tsptr = &env->ts[env->tl & MAXTL_MASK];
2833
}
2834

    
2835
void helper_set_softint(uint64_t value)
2836
{
2837
    env->softint |= (uint32_t)value;
2838
}
2839

    
2840
void helper_clear_softint(uint64_t value)
2841
{
2842
    env->softint &= (uint32_t)~value;
2843
}
2844

    
2845
void helper_write_softint(uint64_t value)
2846
{
2847
    env->softint = (uint32_t)value;
2848
}
2849
#endif
2850

    
2851
void helper_flush(target_ulong addr)
2852
{
2853
    addr &= ~7;
2854
    tb_invalidate_page_range(addr, addr + 8);
2855
}
2856

    
2857
#ifdef TARGET_SPARC64
2858
#ifdef DEBUG_PCALL
2859
static const char * const excp_names[0x80] = {
2860
    [TT_TFAULT] = "Instruction Access Fault",
2861
    [TT_TMISS] = "Instruction Access MMU Miss",
2862
    [TT_CODE_ACCESS] = "Instruction Access Error",
2863
    [TT_ILL_INSN] = "Illegal Instruction",
2864
    [TT_PRIV_INSN] = "Privileged Instruction",
2865
    [TT_NFPU_INSN] = "FPU Disabled",
2866
    [TT_FP_EXCP] = "FPU Exception",
2867
    [TT_TOVF] = "Tag Overflow",
2868
    [TT_CLRWIN] = "Clean Windows",
2869
    [TT_DIV_ZERO] = "Division By Zero",
2870
    [TT_DFAULT] = "Data Access Fault",
2871
    [TT_DMISS] = "Data Access MMU Miss",
2872
    [TT_DATA_ACCESS] = "Data Access Error",
2873
    [TT_DPROT] = "Data Protection Error",
2874
    [TT_UNALIGNED] = "Unaligned Memory Access",
2875
    [TT_PRIV_ACT] = "Privileged Action",
2876
    [TT_EXTINT | 0x1] = "External Interrupt 1",
2877
    [TT_EXTINT | 0x2] = "External Interrupt 2",
2878
    [TT_EXTINT | 0x3] = "External Interrupt 3",
2879
    [TT_EXTINT | 0x4] = "External Interrupt 4",
2880
    [TT_EXTINT | 0x5] = "External Interrupt 5",
2881
    [TT_EXTINT | 0x6] = "External Interrupt 6",
2882
    [TT_EXTINT | 0x7] = "External Interrupt 7",
2883
    [TT_EXTINT | 0x8] = "External Interrupt 8",
2884
    [TT_EXTINT | 0x9] = "External Interrupt 9",
2885
    [TT_EXTINT | 0xa] = "External Interrupt 10",
2886
    [TT_EXTINT | 0xb] = "External Interrupt 11",
2887
    [TT_EXTINT | 0xc] = "External Interrupt 12",
2888
    [TT_EXTINT | 0xd] = "External Interrupt 13",
2889
    [TT_EXTINT | 0xe] = "External Interrupt 14",
2890
    [TT_EXTINT | 0xf] = "External Interrupt 15",
2891
};
2892
#endif
2893

    
2894
void do_interrupt(CPUState *env)
2895
{
2896
    int intno = env->exception_index;
2897

    
2898
#ifdef DEBUG_PCALL
2899
    if (qemu_loglevel_mask(CPU_LOG_INT)) {
2900
        static int count;
2901
        const char *name;
2902

    
2903
        if (intno < 0 || intno >= 0x180)
2904
            name = "Unknown";
2905
        else if (intno >= 0x100)
2906
            name = "Trap Instruction";
2907
        else if (intno >= 0xc0)
2908
            name = "Window Fill";
2909
        else if (intno >= 0x80)
2910
            name = "Window Spill";
2911
        else {
2912
            name = excp_names[intno];
2913
            if (!name)
2914
                name = "Unknown";
2915
        }
2916

    
2917
        qemu_log("%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
2918
                " SP=%016" PRIx64 "\n",
2919
                count, name, intno,
2920
                env->pc,
2921
                env->npc, env->regwptr[6]);
2922
        log_cpu_state(env, 0);
2923
#if 0
2924
        {
2925
            int i;
2926
            uint8_t *ptr;
2927

2928
            qemu_log("       code=");
2929
            ptr = (uint8_t *)env->pc;
2930
            for(i = 0; i < 16; i++) {
2931
                qemu_log(" %02x", ldub(ptr + i));
2932
            }
2933
            qemu_log("\n");
2934
        }
2935
#endif
2936
        count++;
2937
    }
2938
#endif
2939
#if !defined(CONFIG_USER_ONLY)
2940
    if (env->tl >= env->maxtl) {
2941
        cpu_abort(env, "Trap 0x%04x while trap level (%d) >= MAXTL (%d),"
2942
                  " Error state", env->exception_index, env->tl, env->maxtl);
2943
        return;
2944
    }
2945
#endif
2946
    if (env->tl < env->maxtl - 1) {
2947
        env->tl++;
2948
    } else {
2949
        env->pstate |= PS_RED;
2950
        if (env->tl < env->maxtl)
2951
            env->tl++;
2952
    }
2953
    env->tsptr = &env->ts[env->tl & MAXTL_MASK];
2954
    env->tsptr->tstate = ((uint64_t)GET_CCR(env) << 32) |
2955
        ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
2956
        GET_CWP64(env);
2957
    env->tsptr->tpc = env->pc;
2958
    env->tsptr->tnpc = env->npc;
2959
    env->tsptr->tt = intno;
2960
    if (!(env->def->features & CPU_FEATURE_GL)) {
2961
        switch (intno) {
2962
        case TT_IVEC:
2963
            change_pstate(PS_PEF | PS_PRIV | PS_IG);
2964
            break;
2965
        case TT_TFAULT:
2966
        case TT_TMISS:
2967
        case TT_DFAULT:
2968
        case TT_DMISS:
2969
        case TT_DPROT:
2970
            change_pstate(PS_PEF | PS_PRIV | PS_MG);
2971
            break;
2972
        default:
2973
            change_pstate(PS_PEF | PS_PRIV | PS_AG);
2974
            break;
2975
        }
2976
    }
2977
    if (intno == TT_CLRWIN)
2978
        cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1));
2979
    else if ((intno & 0x1c0) == TT_SPILL)
2980
        cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2));
2981
    else if ((intno & 0x1c0) == TT_FILL)
2982
        cpu_set_cwp(env, cpu_cwp_inc(env, env->cwp + 1));
2983
    env->tbr &= ~0x7fffULL;
2984
    env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
2985
    env->pc = env->tbr;
2986
    env->npc = env->pc + 4;
2987
    env->exception_index = 0;
2988
}
2989
#else
2990
#ifdef DEBUG_PCALL
2991
static const char * const excp_names[0x80] = {
2992
    [TT_TFAULT] = "Instruction Access Fault",
2993
    [TT_ILL_INSN] = "Illegal Instruction",
2994
    [TT_PRIV_INSN] = "Privileged Instruction",
2995
    [TT_NFPU_INSN] = "FPU Disabled",
2996
    [TT_WIN_OVF] = "Window Overflow",
2997
    [TT_WIN_UNF] = "Window Underflow",
2998
    [TT_UNALIGNED] = "Unaligned Memory Access",
2999
    [TT_FP_EXCP] = "FPU Exception",
3000
    [TT_DFAULT] = "Data Access Fault",
3001
    [TT_TOVF] = "Tag Overflow",
3002
    [TT_EXTINT | 0x1] = "External Interrupt 1",
3003
    [TT_EXTINT | 0x2] = "External Interrupt 2",
3004
    [TT_EXTINT | 0x3] = "External Interrupt 3",
3005
    [TT_EXTINT | 0x4] = "External Interrupt 4",
3006
    [TT_EXTINT | 0x5] = "External Interrupt 5",
3007
    [TT_EXTINT | 0x6] = "External Interrupt 6",
3008
    [TT_EXTINT | 0x7] = "External Interrupt 7",
3009
    [TT_EXTINT | 0x8] = "External Interrupt 8",
3010
    [TT_EXTINT | 0x9] = "External Interrupt 9",
3011
    [TT_EXTINT | 0xa] = "External Interrupt 10",
3012
    [TT_EXTINT | 0xb] = "External Interrupt 11",
3013
    [TT_EXTINT | 0xc] = "External Interrupt 12",
3014
    [TT_EXTINT | 0xd] = "External Interrupt 13",
3015
    [TT_EXTINT | 0xe] = "External Interrupt 14",
3016
    [TT_EXTINT | 0xf] = "External Interrupt 15",
3017
    [TT_TOVF] = "Tag Overflow",
3018
    [TT_CODE_ACCESS] = "Instruction Access Error",
3019
    [TT_DATA_ACCESS] = "Data Access Error",
3020
    [TT_DIV_ZERO] = "Division By Zero",
3021
    [TT_NCP_INSN] = "Coprocessor Disabled",
3022
};
3023
#endif
3024

    
3025
void do_interrupt(CPUState *env)
3026
{
3027
    int cwp, intno = env->exception_index;
3028

    
3029
#ifdef DEBUG_PCALL
3030
    if (qemu_loglevel_mask(CPU_LOG_INT)) {
3031
        static int count;
3032
        const char *name;
3033

    
3034
        if (intno < 0 || intno >= 0x100)
3035
            name = "Unknown";
3036
        else if (intno >= 0x80)
3037
            name = "Trap Instruction";
3038
        else {
3039
            name = excp_names[intno];
3040
            if (!name)
3041
                name = "Unknown";
3042
        }
3043

    
3044
        qemu_log("%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
3045
                count, name, intno,
3046
                env->pc,
3047
                env->npc, env->regwptr[6]);
3048
        log_cpu_state(env, 0);
3049
#if 0
3050
        {
3051
            int i;
3052
            uint8_t *ptr;
3053

3054
            qemu_log("       code=");
3055
            ptr = (uint8_t *)env->pc;
3056
            for(i = 0; i < 16; i++) {
3057
                qemu_log(" %02x", ldub(ptr + i));
3058
            }
3059
            qemu_log("\n");
3060
        }
3061
#endif
3062
        count++;
3063
    }
3064
#endif
3065
#if !defined(CONFIG_USER_ONLY)
3066
    if (env->psret == 0) {
3067
        cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
3068
                  env->exception_index);
3069
        return;
3070
    }
3071
#endif
3072
    env->psret = 0;
3073
    cwp = cpu_cwp_dec(env, env->cwp - 1);
3074
    cpu_set_cwp(env, cwp);
3075
    env->regwptr[9] = env->pc;
3076
    env->regwptr[10] = env->npc;
3077
    env->psrps = env->psrs;
3078
    env->psrs = 1;
3079
    env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
3080
    env->pc = env->tbr;
3081
    env->npc = env->pc + 4;
3082
    env->exception_index = 0;
3083
}
3084
#endif
3085

    
3086
#if !defined(CONFIG_USER_ONLY)
3087

    
3088
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
3089
                                void *retaddr);
3090

    
3091
#define MMUSUFFIX _mmu
3092
#define ALIGNED_ONLY
3093

    
3094
#define SHIFT 0
3095
#include "softmmu_template.h"
3096

    
3097
#define SHIFT 1
3098
#include "softmmu_template.h"
3099

    
3100
#define SHIFT 2
3101
#include "softmmu_template.h"
3102

    
3103
#define SHIFT 3
3104
#include "softmmu_template.h"
3105

    
3106
/* XXX: make it generic ? */
3107
static void cpu_restore_state2(void *retaddr)
3108
{
3109
    TranslationBlock *tb;
3110
    unsigned long pc;
3111

    
3112
    if (retaddr) {
3113
        /* now we have a real cpu fault */
3114
        pc = (unsigned long)retaddr;
3115
        tb = tb_find_pc(pc);
3116
        if (tb) {
3117
            /* the PC is inside the translated code. It means that we have
3118
               a virtual CPU fault */
3119
            cpu_restore_state(tb, env, pc, (void *)(long)env->cond);
3120
        }
3121
    }
3122
}
3123

    
3124
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
3125
                                void *retaddr)
3126
{
3127
#ifdef DEBUG_UNALIGNED
3128
    printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
3129
           "\n", addr, env->pc);
3130
#endif
3131
    cpu_restore_state2(retaddr);
3132
    raise_exception(TT_UNALIGNED);
3133
}
3134

    
3135
/* try to fill the TLB and return an exception if error. If retaddr is
3136
   NULL, it means that the function was called in C code (i.e. not
3137
   from generated code or from helper.c) */
3138
/* XXX: fix it to restore all registers */
3139
void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
3140
{
3141
    int ret;
3142
    CPUState *saved_env;
3143

    
3144
    /* XXX: hack to restore env in all cases, even if not called from
3145
       generated code */
3146
    saved_env = env;
3147
    env = cpu_single_env;
3148

    
3149
    ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
3150
    if (ret) {
3151
        cpu_restore_state2(retaddr);
3152
        cpu_loop_exit();
3153
    }
3154
    env = saved_env;
3155
}
3156

    
3157
#endif
3158

    
3159
#ifndef TARGET_SPARC64
3160
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
3161
                          int is_asi, int size)
3162
{
3163
    CPUState *saved_env;
3164

    
3165
    /* XXX: hack to restore env in all cases, even if not called from
3166
       generated code */
3167
    saved_env = env;
3168
    env = cpu_single_env;
3169
#ifdef DEBUG_UNASSIGNED
3170
    if (is_asi)
3171
        printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
3172
               " asi 0x%02x from " TARGET_FMT_lx "\n",
3173
               is_exec ? "exec" : is_write ? "write" : "read", size,
3174
               size == 1 ? "" : "s", addr, is_asi, env->pc);
3175
    else
3176
        printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
3177
               " from " TARGET_FMT_lx "\n",
3178
               is_exec ? "exec" : is_write ? "write" : "read", size,
3179
               size == 1 ? "" : "s", addr, env->pc);
3180
#endif
3181
    if (env->mmuregs[3]) /* Fault status register */
3182
        env->mmuregs[3] = 1; /* overflow (not read before another fault) */
3183
    if (is_asi)
3184
        env->mmuregs[3] |= 1 << 16;
3185
    if (env->psrs)
3186
        env->mmuregs[3] |= 1 << 5;
3187
    if (is_exec)
3188
        env->mmuregs[3] |= 1 << 6;
3189
    if (is_write)
3190
        env->mmuregs[3] |= 1 << 7;
3191
    env->mmuregs[3] |= (5 << 2) | 2;
3192
    env->mmuregs[4] = addr; /* Fault address register */
3193
    if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
3194
        if (is_exec)
3195
            raise_exception(TT_CODE_ACCESS);
3196
        else
3197
            raise_exception(TT_DATA_ACCESS);
3198
    }
3199
    env = saved_env;
3200
}
3201
#else
3202
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
3203
                          int is_asi, int size)
3204
{
3205
#ifdef DEBUG_UNASSIGNED
3206
    CPUState *saved_env;
3207

    
3208
    /* XXX: hack to restore env in all cases, even if not called from
3209
       generated code */
3210
    saved_env = env;
3211
    env = cpu_single_env;
3212
    printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx
3213
           "\n", addr, env->pc);
3214
    env = saved_env;
3215
#endif
3216
    if (is_exec)
3217
        raise_exception(TT_CODE_ACCESS);
3218
    else
3219
        raise_exception(TT_DATA_ACCESS);
3220
}
3221
#endif
3222

    
3223
#ifdef TARGET_SPARC64
3224
void helper_tick_set_count(void *opaque, uint64_t count)
3225
{
3226
#if !defined(CONFIG_USER_ONLY)
3227
    cpu_tick_set_count(opaque, count);
3228
#endif
3229
}
3230

    
3231
uint64_t helper_tick_get_count(void *opaque)
3232
{
3233
#if !defined(CONFIG_USER_ONLY)
3234
    return cpu_tick_get_count(opaque);
3235
#else
3236
    return 0;
3237
#endif
3238
}
3239

    
3240
void helper_tick_set_limit(void *opaque, uint64_t limit)
3241
{
3242
#if !defined(CONFIG_USER_ONLY)
3243
    cpu_tick_set_limit(opaque, limit);
3244
#endif
3245
}
3246
#endif