Statistics
| Branch: | Revision:

root / target-sparc / op_helper.c @ 6c78ea32

History | View | Annotate | Download (100.5 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
static uint32_t compute_all_flags(void)
750
{
751
    return env->psr & PSR_ICC;
752
}
753

    
754
static uint32_t compute_C_flags(void)
755
{
756
    return env->psr & PSR_CARRY;
757
}
758

    
759
static inline uint32_t get_NZ_icc(target_ulong dst)
760
{
761
    uint32_t ret = 0;
762

    
763
    if (!(dst & 0xffffffffULL))
764
        ret |= PSR_ZERO;
765
    if ((int32_t) (dst & 0xffffffffULL) < 0)
766
        ret |= PSR_NEG;
767
    return ret;
768
}
769

    
770
#ifdef TARGET_SPARC64
771
static uint32_t compute_all_flags_xcc(void)
772
{
773
    return env->xcc & PSR_ICC;
774
}
775

    
776
static uint32_t compute_C_flags_xcc(void)
777
{
778
    return env->xcc & PSR_CARRY;
779
}
780

    
781
static inline uint32_t get_NZ_xcc(target_ulong dst)
782
{
783
    uint32_t ret = 0;
784

    
785
    if (!dst)
786
        ret |= PSR_ZERO;
787
    if ((int64_t)dst < 0)
788
        ret |= PSR_NEG;
789
    return ret;
790
}
791
#endif
792

    
793
static inline uint32_t get_V_div_icc(target_ulong src2)
794
{
795
    uint32_t ret = 0;
796

    
797
    if (src2 != 0)
798
        ret |= PSR_OVF;
799
    return ret;
800
}
801

    
802
static uint32_t compute_all_div(void)
803
{
804
    uint32_t ret;
805

    
806
    ret = get_NZ_icc(CC_DST);
807
    ret |= get_V_div_icc(CC_SRC2);
808
    return ret;
809
}
810

    
811
static uint32_t compute_C_div(void)
812
{
813
    return 0;
814
}
815

    
816
static inline uint32_t get_C_add_icc(target_ulong dst, target_ulong src1)
817
{
818
    uint32_t ret = 0;
819

    
820
    if ((dst & 0xffffffffULL) < (src1 & 0xffffffffULL))
821
        ret |= PSR_CARRY;
822
    return ret;
823
}
824

    
825
static inline uint32_t get_V_add_icc(target_ulong dst, target_ulong src1,
826
                                         target_ulong src2)
827
{
828
    uint32_t ret = 0;
829

    
830
    if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1ULL << 31))
831
        ret |= PSR_OVF;
832
    return ret;
833
}
834

    
835
static uint32_t compute_all_add(void)
836
{
837
    uint32_t ret;
838

    
839
    ret = get_NZ_icc(CC_DST);
840
    ret |= get_C_add_icc(CC_DST, CC_SRC);
841
    ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
842
    return ret;
843
}
844

    
845
static uint32_t compute_C_add(void)
846
{
847
    return get_C_add_icc(CC_DST, CC_SRC);
848
}
849

    
850
#ifdef TARGET_SPARC64
851
static inline uint32_t get_C_add_xcc(target_ulong dst, target_ulong src1)
852
{
853
    uint32_t ret = 0;
854

    
855
    if (dst < src1)
856
        ret |= PSR_CARRY;
857
    return ret;
858
}
859

    
860
static inline uint32_t get_V_add_xcc(target_ulong dst, target_ulong src1,
861
                                         target_ulong src2)
862
{
863
    uint32_t ret = 0;
864

    
865
    if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1ULL << 63))
866
        ret |= PSR_OVF;
867
    return ret;
868
}
869

    
870
static uint32_t compute_all_add_xcc(void)
871
{
872
    uint32_t ret;
873

    
874
    ret = get_NZ_xcc(CC_DST);
875
    ret |= get_C_add_xcc(CC_DST, CC_SRC);
876
    ret |= get_V_add_xcc(CC_DST, CC_SRC, CC_SRC2);
877
    return ret;
878
}
879

    
880
static uint32_t compute_C_add_xcc(void)
881
{
882
    return get_C_add_xcc(CC_DST, CC_SRC);
883
}
884
#endif
885

    
886
static uint32_t compute_all_addx(void)
887
{
888
    uint32_t ret;
889

    
890
    ret = get_NZ_icc(CC_DST);
891
    ret |= get_C_add_icc(CC_DST - CC_SRC2, CC_SRC);
892
    ret |= get_C_add_icc(CC_DST, CC_SRC);
893
    ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
894
    return ret;
895
}
896

    
897
static uint32_t compute_C_addx(void)
898
{
899
    uint32_t ret;
900

    
901
    ret = get_C_add_icc(CC_DST - CC_SRC2, CC_SRC);
902
    ret |= get_C_add_icc(CC_DST, CC_SRC);
903
    return ret;
904
}
905

    
906
#ifdef TARGET_SPARC64
907
static uint32_t compute_all_addx_xcc(void)
908
{
909
    uint32_t ret;
910

    
911
    ret = get_NZ_xcc(CC_DST);
912
    ret |= get_C_add_xcc(CC_DST - CC_SRC2, CC_SRC);
913
    ret |= get_C_add_xcc(CC_DST, CC_SRC);
914
    ret |= get_V_add_xcc(CC_DST, CC_SRC, CC_SRC2);
915
    return ret;
916
}
917

    
918
static uint32_t compute_C_addx_xcc(void)
919
{
920
    uint32_t ret;
921

    
922
    ret = get_C_add_xcc(CC_DST - CC_SRC2, CC_SRC);
923
    ret |= get_C_add_xcc(CC_DST, CC_SRC);
924
    return ret;
925
}
926
#endif
927

    
928
static inline uint32_t get_V_tag_icc(target_ulong src1, target_ulong src2)
929
{
930
    uint32_t ret = 0;
931

    
932
    if ((src1 | src2) & 0x3)
933
        ret |= PSR_OVF;
934
    return ret;
935
}
936

    
937
static uint32_t compute_all_tadd(void)
938
{
939
    uint32_t ret;
940

    
941
    ret = get_NZ_icc(CC_DST);
942
    ret |= get_C_add_icc(CC_DST, CC_SRC);
943
    ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
944
    ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
945
    return ret;
946
}
947

    
948
static uint32_t compute_C_tadd(void)
949
{
950
    return get_C_add_icc(CC_DST, CC_SRC);
951
}
952

    
953
static uint32_t compute_all_taddtv(void)
954
{
955
    uint32_t ret;
956

    
957
    ret = get_NZ_icc(CC_DST);
958
    ret |= get_C_add_icc(CC_DST, CC_SRC);
959
    return ret;
960
}
961

    
962
static uint32_t compute_C_taddtv(void)
963
{
964
    return get_C_add_icc(CC_DST, CC_SRC);
965
}
966

    
967
static inline uint32_t get_C_sub_icc(target_ulong src1, target_ulong src2)
968
{
969
    uint32_t ret = 0;
970

    
971
    if ((src1 & 0xffffffffULL) < (src2 & 0xffffffffULL))
972
        ret |= PSR_CARRY;
973
    return ret;
974
}
975

    
976
static inline uint32_t get_V_sub_icc(target_ulong dst, target_ulong src1,
977
                                     target_ulong src2)
978
{
979
    uint32_t ret = 0;
980

    
981
    if (((src1 ^ src2) & (src1 ^ dst)) & (1ULL << 31))
982
        ret |= PSR_OVF;
983
    return ret;
984
}
985

    
986
static uint32_t compute_all_sub(void)
987
{
988
    uint32_t ret;
989

    
990
    ret = get_NZ_icc(CC_DST);
991
    ret |= get_C_sub_icc(CC_SRC, CC_SRC2);
992
    ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
993
    return ret;
994
}
995

    
996
static uint32_t compute_C_sub(void)
997
{
998
    return get_C_sub_icc(CC_SRC, CC_SRC2);
999
}
1000

    
1001
#ifdef TARGET_SPARC64
1002
static inline uint32_t get_C_sub_xcc(target_ulong src1, target_ulong src2)
1003
{
1004
    uint32_t ret = 0;
1005

    
1006
    if (src1 < src2)
1007
        ret |= PSR_CARRY;
1008
    return ret;
1009
}
1010

    
1011
static inline uint32_t get_V_sub_xcc(target_ulong dst, target_ulong src1,
1012
                                     target_ulong src2)
1013
{
1014
    uint32_t ret = 0;
1015

    
1016
    if (((src1 ^ src2) & (src1 ^ dst)) & (1ULL << 63))
1017
        ret |= PSR_OVF;
1018
    return ret;
1019
}
1020

    
1021
static uint32_t compute_all_sub_xcc(void)
1022
{
1023
    uint32_t ret;
1024

    
1025
    ret = get_NZ_xcc(CC_DST);
1026
    ret |= get_C_sub_xcc(CC_SRC, CC_SRC2);
1027
    ret |= get_V_sub_xcc(CC_DST, CC_SRC, CC_SRC2);
1028
    return ret;
1029
}
1030

    
1031
static uint32_t compute_C_sub_xcc(void)
1032
{
1033
    return get_C_sub_xcc(CC_SRC, CC_SRC2);
1034
}
1035
#endif
1036

    
1037
static uint32_t compute_all_subx(void)
1038
{
1039
    uint32_t ret;
1040

    
1041
    ret = get_NZ_icc(CC_DST);
1042
    ret |= get_C_sub_icc(CC_DST - CC_SRC2, CC_SRC);
1043
    ret |= get_C_sub_icc(CC_DST, CC_SRC2);
1044
    ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1045
    return ret;
1046
}
1047

    
1048
static uint32_t compute_C_subx(void)
1049
{
1050
    uint32_t ret;
1051

    
1052
    ret = get_C_sub_icc(CC_DST - CC_SRC2, CC_SRC);
1053
    ret |= get_C_sub_icc(CC_DST, CC_SRC2);
1054
    return ret;
1055
}
1056

    
1057
#ifdef TARGET_SPARC64
1058
static uint32_t compute_all_subx_xcc(void)
1059
{
1060
    uint32_t ret;
1061

    
1062
    ret = get_NZ_xcc(CC_DST);
1063
    ret |= get_C_sub_xcc(CC_DST - CC_SRC2, CC_SRC);
1064
    ret |= get_C_sub_xcc(CC_DST, CC_SRC2);
1065
    ret |= get_V_sub_xcc(CC_DST, CC_SRC, CC_SRC2);
1066
    return ret;
1067
}
1068

    
1069
static uint32_t compute_C_subx_xcc(void)
1070
{
1071
    uint32_t ret;
1072

    
1073
    ret = get_C_sub_xcc(CC_DST - CC_SRC2, CC_SRC);
1074
    ret |= get_C_sub_xcc(CC_DST, CC_SRC2);
1075
    return ret;
1076
}
1077
#endif
1078

    
1079
static uint32_t compute_all_tsub(void)
1080
{
1081
    uint32_t ret;
1082

    
1083
    ret = get_NZ_icc(CC_DST);
1084
    ret |= get_C_sub_icc(CC_DST, CC_SRC);
1085
    ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1086
    ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
1087
    return ret;
1088
}
1089

    
1090
static uint32_t compute_C_tsub(void)
1091
{
1092
    return get_C_sub_icc(CC_DST, CC_SRC);
1093
}
1094

    
1095
static uint32_t compute_all_tsubtv(void)
1096
{
1097
    uint32_t ret;
1098

    
1099
    ret = get_NZ_icc(CC_DST);
1100
    ret |= get_C_sub_icc(CC_DST, CC_SRC);
1101
    return ret;
1102
}
1103

    
1104
static uint32_t compute_C_tsubtv(void)
1105
{
1106
    return get_C_sub_icc(CC_DST, CC_SRC);
1107
}
1108

    
1109
static uint32_t compute_all_logic(void)
1110
{
1111
    return get_NZ_icc(CC_DST);
1112
}
1113

    
1114
static uint32_t compute_C_logic(void)
1115
{
1116
    return 0;
1117
}
1118

    
1119
#ifdef TARGET_SPARC64
1120
static uint32_t compute_all_logic_xcc(void)
1121
{
1122
    return get_NZ_xcc(CC_DST);
1123
}
1124
#endif
1125

    
1126
typedef struct CCTable {
1127
    uint32_t (*compute_all)(void); /* return all the flags */
1128
    uint32_t (*compute_c)(void);  /* return the C flag */
1129
} CCTable;
1130

    
1131
static const CCTable icc_table[CC_OP_NB] = {
1132
    /* CC_OP_DYNAMIC should never happen */
1133
    [CC_OP_FLAGS] = { compute_all_flags, compute_C_flags },
1134
    [CC_OP_DIV] = { compute_all_div, compute_C_div },
1135
    [CC_OP_ADD] = { compute_all_add, compute_C_add },
1136
    [CC_OP_ADDX] = { compute_all_addx, compute_C_addx },
1137
    [CC_OP_TADD] = { compute_all_tadd, compute_C_tadd },
1138
    [CC_OP_TADDTV] = { compute_all_taddtv, compute_C_taddtv },
1139
    [CC_OP_SUB] = { compute_all_sub, compute_C_sub },
1140
    [CC_OP_SUBX] = { compute_all_subx, compute_C_subx },
1141
    [CC_OP_TSUB] = { compute_all_tsub, compute_C_tsub },
1142
    [CC_OP_TSUBTV] = { compute_all_tsubtv, compute_C_tsubtv },
1143
    [CC_OP_LOGIC] = { compute_all_logic, compute_C_logic },
1144
};
1145

    
1146
#ifdef TARGET_SPARC64
1147
static const CCTable xcc_table[CC_OP_NB] = {
1148
    /* CC_OP_DYNAMIC should never happen */
1149
    [CC_OP_FLAGS] = { compute_all_flags_xcc, compute_C_flags_xcc },
1150
    [CC_OP_DIV] = { compute_all_logic_xcc, compute_C_logic },
1151
    [CC_OP_ADD] = { compute_all_add_xcc, compute_C_add_xcc },
1152
    [CC_OP_ADDX] = { compute_all_addx_xcc, compute_C_addx_xcc },
1153
    [CC_OP_TADD] = { compute_all_add_xcc, compute_C_add_xcc },
1154
    [CC_OP_TADDTV] = { compute_all_add_xcc, compute_C_add_xcc },
1155
    [CC_OP_SUB] = { compute_all_sub_xcc, compute_C_sub_xcc },
1156
    [CC_OP_SUBX] = { compute_all_subx_xcc, compute_C_subx_xcc },
1157
    [CC_OP_TSUB] = { compute_all_sub_xcc, compute_C_sub_xcc },
1158
    [CC_OP_TSUBTV] = { compute_all_sub_xcc, compute_C_sub_xcc },
1159
    [CC_OP_LOGIC] = { compute_all_logic_xcc, compute_C_logic },
1160
};
1161
#endif
1162

    
1163
void helper_compute_psr(void)
1164
{
1165
    uint32_t new_psr;
1166

    
1167
    new_psr = icc_table[CC_OP].compute_all();
1168
    env->psr = new_psr;
1169
#ifdef TARGET_SPARC64
1170
    new_psr = xcc_table[CC_OP].compute_all();
1171
    env->xcc = new_psr;
1172
#endif
1173
    CC_OP = CC_OP_FLAGS;
1174
}
1175

    
1176
uint32_t helper_compute_C_icc(void)
1177
{
1178
    uint32_t ret;
1179

    
1180
    ret = icc_table[CC_OP].compute_c() >> PSR_CARRY_SHIFT;
1181
    return ret;
1182
}
1183

    
1184
#ifdef TARGET_SPARC64
1185
GEN_FCMPS(fcmps_fcc1, float32, 22, 0);
1186
GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
1187
GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0);
1188

    
1189
GEN_FCMPS(fcmps_fcc2, float32, 24, 0);
1190
GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
1191
GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0);
1192

    
1193
GEN_FCMPS(fcmps_fcc3, float32, 26, 0);
1194
GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
1195
GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0);
1196

    
1197
GEN_FCMPS(fcmpes_fcc1, float32, 22, 1);
1198
GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
1199
GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1);
1200

    
1201
GEN_FCMPS(fcmpes_fcc2, float32, 24, 1);
1202
GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
1203
GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1);
1204

    
1205
GEN_FCMPS(fcmpes_fcc3, float32, 26, 1);
1206
GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
1207
GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
1208
#endif
1209
#undef GEN_FCMPS
1210

    
1211
#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) && \
1212
    defined(DEBUG_MXCC)
1213
static void dump_mxcc(CPUState *env)
1214
{
1215
    printf("mxccdata: %016llx %016llx %016llx %016llx\n",
1216
           env->mxccdata[0], env->mxccdata[1],
1217
           env->mxccdata[2], env->mxccdata[3]);
1218
    printf("mxccregs: %016llx %016llx %016llx %016llx\n"
1219
           "          %016llx %016llx %016llx %016llx\n",
1220
           env->mxccregs[0], env->mxccregs[1],
1221
           env->mxccregs[2], env->mxccregs[3],
1222
           env->mxccregs[4], env->mxccregs[5],
1223
           env->mxccregs[6], env->mxccregs[7]);
1224
}
1225
#endif
1226

    
1227
#if (defined(TARGET_SPARC64) || !defined(CONFIG_USER_ONLY)) \
1228
    && defined(DEBUG_ASI)
1229
static void dump_asi(const char *txt, target_ulong addr, int asi, int size,
1230
                     uint64_t r1)
1231
{
1232
    switch (size)
1233
    {
1234
    case 1:
1235
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %02" PRIx64 "\n", txt,
1236
                    addr, asi, r1 & 0xff);
1237
        break;
1238
    case 2:
1239
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %04" PRIx64 "\n", txt,
1240
                    addr, asi, r1 & 0xffff);
1241
        break;
1242
    case 4:
1243
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %08" PRIx64 "\n", txt,
1244
                    addr, asi, r1 & 0xffffffff);
1245
        break;
1246
    case 8:
1247
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %016" PRIx64 "\n", txt,
1248
                    addr, asi, r1);
1249
        break;
1250
    }
1251
}
1252
#endif
1253

    
1254
#ifndef TARGET_SPARC64
1255
#ifndef CONFIG_USER_ONLY
1256
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1257
{
1258
    uint64_t ret = 0;
1259
#if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
1260
    uint32_t last_addr = addr;
1261
#endif
1262

    
1263
    helper_check_align(addr, size - 1);
1264
    switch (asi) {
1265
    case 2: /* SuperSparc MXCC registers */
1266
        switch (addr) {
1267
        case 0x01c00a00: /* MXCC control register */
1268
            if (size == 8)
1269
                ret = env->mxccregs[3];
1270
            else
1271
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1272
                             size);
1273
            break;
1274
        case 0x01c00a04: /* MXCC control register */
1275
            if (size == 4)
1276
                ret = env->mxccregs[3];
1277
            else
1278
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1279
                             size);
1280
            break;
1281
        case 0x01c00c00: /* Module reset register */
1282
            if (size == 8) {
1283
                ret = env->mxccregs[5];
1284
                // should we do something here?
1285
            } else
1286
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1287
                             size);
1288
            break;
1289
        case 0x01c00f00: /* MBus port address register */
1290
            if (size == 8)
1291
                ret = env->mxccregs[7];
1292
            else
1293
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1294
                             size);
1295
            break;
1296
        default:
1297
            DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr,
1298
                         size);
1299
            break;
1300
        }
1301
        DPRINTF_MXCC("asi = %d, size = %d, sign = %d, "
1302
                     "addr = %08x -> ret = %" PRIx64 ","
1303
                     "addr = %08x\n", asi, size, sign, last_addr, ret, addr);
1304
#ifdef DEBUG_MXCC
1305
        dump_mxcc(env);
1306
#endif
1307
        break;
1308
    case 3: /* MMU probe */
1309
        {
1310
            int mmulev;
1311

    
1312
            mmulev = (addr >> 8) & 15;
1313
            if (mmulev > 4)
1314
                ret = 0;
1315
            else
1316
                ret = mmu_probe(env, addr, mmulev);
1317
            DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08" PRIx64 "\n",
1318
                        addr, mmulev, ret);
1319
        }
1320
        break;
1321
    case 4: /* read MMU regs */
1322
        {
1323
            int reg = (addr >> 8) & 0x1f;
1324

    
1325
            ret = env->mmuregs[reg];
1326
            if (reg == 3) /* Fault status cleared on read */
1327
                env->mmuregs[3] = 0;
1328
            else if (reg == 0x13) /* Fault status read */
1329
                ret = env->mmuregs[3];
1330
            else if (reg == 0x14) /* Fault address read */
1331
                ret = env->mmuregs[4];
1332
            DPRINTF_MMU("mmu_read: reg[%d] = 0x%08" PRIx64 "\n", reg, ret);
1333
        }
1334
        break;
1335
    case 5: // Turbosparc ITLB Diagnostic
1336
    case 6: // Turbosparc DTLB Diagnostic
1337
    case 7: // Turbosparc IOTLB Diagnostic
1338
        break;
1339
    case 9: /* Supervisor code access */
1340
        switch(size) {
1341
        case 1:
1342
            ret = ldub_code(addr);
1343
            break;
1344
        case 2:
1345
            ret = lduw_code(addr);
1346
            break;
1347
        default:
1348
        case 4:
1349
            ret = ldl_code(addr);
1350
            break;
1351
        case 8:
1352
            ret = ldq_code(addr);
1353
            break;
1354
        }
1355
        break;
1356
    case 0xa: /* User data access */
1357
        switch(size) {
1358
        case 1:
1359
            ret = ldub_user(addr);
1360
            break;
1361
        case 2:
1362
            ret = lduw_user(addr);
1363
            break;
1364
        default:
1365
        case 4:
1366
            ret = ldl_user(addr);
1367
            break;
1368
        case 8:
1369
            ret = ldq_user(addr);
1370
            break;
1371
        }
1372
        break;
1373
    case 0xb: /* Supervisor data access */
1374
        switch(size) {
1375
        case 1:
1376
            ret = ldub_kernel(addr);
1377
            break;
1378
        case 2:
1379
            ret = lduw_kernel(addr);
1380
            break;
1381
        default:
1382
        case 4:
1383
            ret = ldl_kernel(addr);
1384
            break;
1385
        case 8:
1386
            ret = ldq_kernel(addr);
1387
            break;
1388
        }
1389
        break;
1390
    case 0xc: /* I-cache tag */
1391
    case 0xd: /* I-cache data */
1392
    case 0xe: /* D-cache tag */
1393
    case 0xf: /* D-cache data */
1394
        break;
1395
    case 0x20: /* MMU passthrough */
1396
        switch(size) {
1397
        case 1:
1398
            ret = ldub_phys(addr);
1399
            break;
1400
        case 2:
1401
            ret = lduw_phys(addr);
1402
            break;
1403
        default:
1404
        case 4:
1405
            ret = ldl_phys(addr);
1406
            break;
1407
        case 8:
1408
            ret = ldq_phys(addr);
1409
            break;
1410
        }
1411
        break;
1412
    case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
1413
        switch(size) {
1414
        case 1:
1415
            ret = ldub_phys((target_phys_addr_t)addr
1416
                            | ((target_phys_addr_t)(asi & 0xf) << 32));
1417
            break;
1418
        case 2:
1419
            ret = lduw_phys((target_phys_addr_t)addr
1420
                            | ((target_phys_addr_t)(asi & 0xf) << 32));
1421
            break;
1422
        default:
1423
        case 4:
1424
            ret = ldl_phys((target_phys_addr_t)addr
1425
                           | ((target_phys_addr_t)(asi & 0xf) << 32));
1426
            break;
1427
        case 8:
1428
            ret = ldq_phys((target_phys_addr_t)addr
1429
                           | ((target_phys_addr_t)(asi & 0xf) << 32));
1430
            break;
1431
        }
1432
        break;
1433
    case 0x30: // Turbosparc secondary cache diagnostic
1434
    case 0x31: // Turbosparc RAM snoop
1435
    case 0x32: // Turbosparc page table descriptor diagnostic
1436
    case 0x39: /* data cache diagnostic register */
1437
        ret = 0;
1438
        break;
1439
    case 0x38: /* SuperSPARC MMU Breakpoint Control Registers */
1440
        {
1441
            int reg = (addr >> 8) & 3;
1442

    
1443
            switch(reg) {
1444
            case 0: /* Breakpoint Value (Addr) */
1445
                ret = env->mmubpregs[reg];
1446
                break;
1447
            case 1: /* Breakpoint Mask */
1448
                ret = env->mmubpregs[reg];
1449
                break;
1450
            case 2: /* Breakpoint Control */
1451
                ret = env->mmubpregs[reg];
1452
                break;
1453
            case 3: /* Breakpoint Status */
1454
                ret = env->mmubpregs[reg];
1455
                env->mmubpregs[reg] = 0ULL;
1456
                break;
1457
            }
1458
            DPRINTF_MMU("read breakpoint reg[%d] 0x%016llx\n", reg, ret);
1459
        }
1460
        break;
1461
    case 8: /* User code access, XXX */
1462
    default:
1463
        do_unassigned_access(addr, 0, 0, asi, size);
1464
        ret = 0;
1465
        break;
1466
    }
1467
    if (sign) {
1468
        switch(size) {
1469
        case 1:
1470
            ret = (int8_t) ret;
1471
            break;
1472
        case 2:
1473
            ret = (int16_t) ret;
1474
            break;
1475
        case 4:
1476
            ret = (int32_t) ret;
1477
            break;
1478
        default:
1479
            break;
1480
        }
1481
    }
1482
#ifdef DEBUG_ASI
1483
    dump_asi("read ", last_addr, asi, size, ret);
1484
#endif
1485
    return ret;
1486
}
1487

    
1488
void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
1489
{
1490
    helper_check_align(addr, size - 1);
1491
    switch(asi) {
1492
    case 2: /* SuperSparc MXCC registers */
1493
        switch (addr) {
1494
        case 0x01c00000: /* MXCC stream data register 0 */
1495
            if (size == 8)
1496
                env->mxccdata[0] = val;
1497
            else
1498
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1499
                             size);
1500
            break;
1501
        case 0x01c00008: /* MXCC stream data register 1 */
1502
            if (size == 8)
1503
                env->mxccdata[1] = val;
1504
            else
1505
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1506
                             size);
1507
            break;
1508
        case 0x01c00010: /* MXCC stream data register 2 */
1509
            if (size == 8)
1510
                env->mxccdata[2] = val;
1511
            else
1512
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1513
                             size);
1514
            break;
1515
        case 0x01c00018: /* MXCC stream data register 3 */
1516
            if (size == 8)
1517
                env->mxccdata[3] = val;
1518
            else
1519
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1520
                             size);
1521
            break;
1522
        case 0x01c00100: /* MXCC stream source */
1523
            if (size == 8)
1524
                env->mxccregs[0] = val;
1525
            else
1526
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1527
                             size);
1528
            env->mxccdata[0] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1529
                                        0);
1530
            env->mxccdata[1] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1531
                                        8);
1532
            env->mxccdata[2] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1533
                                        16);
1534
            env->mxccdata[3] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1535
                                        24);
1536
            break;
1537
        case 0x01c00200: /* MXCC stream destination */
1538
            if (size == 8)
1539
                env->mxccregs[1] = val;
1540
            else
1541
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1542
                             size);
1543
            stq_phys((env->mxccregs[1] & 0xffffffffULL) +  0,
1544
                     env->mxccdata[0]);
1545
            stq_phys((env->mxccregs[1] & 0xffffffffULL) +  8,
1546
                     env->mxccdata[1]);
1547
            stq_phys((env->mxccregs[1] & 0xffffffffULL) + 16,
1548
                     env->mxccdata[2]);
1549
            stq_phys((env->mxccregs[1] & 0xffffffffULL) + 24,
1550
                     env->mxccdata[3]);
1551
            break;
1552
        case 0x01c00a00: /* MXCC control register */
1553
            if (size == 8)
1554
                env->mxccregs[3] = val;
1555
            else
1556
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1557
                             size);
1558
            break;
1559
        case 0x01c00a04: /* MXCC control register */
1560
            if (size == 4)
1561
                env->mxccregs[3] = (env->mxccregs[3] & 0xffffffff00000000ULL)
1562
                    | val;
1563
            else
1564
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1565
                             size);
1566
            break;
1567
        case 0x01c00e00: /* MXCC error register  */
1568
            // writing a 1 bit clears the error
1569
            if (size == 8)
1570
                env->mxccregs[6] &= ~val;
1571
            else
1572
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1573
                             size);
1574
            break;
1575
        case 0x01c00f00: /* MBus port address register */
1576
            if (size == 8)
1577
                env->mxccregs[7] = val;
1578
            else
1579
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1580
                             size);
1581
            break;
1582
        default:
1583
            DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr,
1584
                         size);
1585
            break;
1586
        }
1587
        DPRINTF_MXCC("asi = %d, size = %d, addr = %08x, val = %" PRIx64 "\n",
1588
                     asi, size, addr, val);
1589
#ifdef DEBUG_MXCC
1590
        dump_mxcc(env);
1591
#endif
1592
        break;
1593
    case 3: /* MMU flush */
1594
        {
1595
            int mmulev;
1596

    
1597
            mmulev = (addr >> 8) & 15;
1598
            DPRINTF_MMU("mmu flush level %d\n", mmulev);
1599
            switch (mmulev) {
1600
            case 0: // flush page
1601
                tlb_flush_page(env, addr & 0xfffff000);
1602
                break;
1603
            case 1: // flush segment (256k)
1604
            case 2: // flush region (16M)
1605
            case 3: // flush context (4G)
1606
            case 4: // flush entire
1607
                tlb_flush(env, 1);
1608
                break;
1609
            default:
1610
                break;
1611
            }
1612
#ifdef DEBUG_MMU
1613
            dump_mmu(env);
1614
#endif
1615
        }
1616
        break;
1617
    case 4: /* write MMU regs */
1618
        {
1619
            int reg = (addr >> 8) & 0x1f;
1620
            uint32_t oldreg;
1621

    
1622
            oldreg = env->mmuregs[reg];
1623
            switch(reg) {
1624
            case 0: // Control Register
1625
                env->mmuregs[reg] = (env->mmuregs[reg] & 0xff000000) |
1626
                                    (val & 0x00ffffff);
1627
                // Mappings generated during no-fault mode or MMU
1628
                // disabled mode are invalid in normal mode
1629
                if ((oldreg & (MMU_E | MMU_NF | env->def->mmu_bm)) !=
1630
                    (env->mmuregs[reg] & (MMU_E | MMU_NF | env->def->mmu_bm)))
1631
                    tlb_flush(env, 1);
1632
                break;
1633
            case 1: // Context Table Pointer Register
1634
                env->mmuregs[reg] = val & env->def->mmu_ctpr_mask;
1635
                break;
1636
            case 2: // Context Register
1637
                env->mmuregs[reg] = val & env->def->mmu_cxr_mask;
1638
                if (oldreg != env->mmuregs[reg]) {
1639
                    /* we flush when the MMU context changes because
1640
                       QEMU has no MMU context support */
1641
                    tlb_flush(env, 1);
1642
                }
1643
                break;
1644
            case 3: // Synchronous Fault Status Register with Clear
1645
            case 4: // Synchronous Fault Address Register
1646
                break;
1647
            case 0x10: // TLB Replacement Control Register
1648
                env->mmuregs[reg] = val & env->def->mmu_trcr_mask;
1649
                break;
1650
            case 0x13: // Synchronous Fault Status Register with Read and Clear
1651
                env->mmuregs[3] = val & env->def->mmu_sfsr_mask;
1652
                break;
1653
            case 0x14: // Synchronous Fault Address Register
1654
                env->mmuregs[4] = val;
1655
                break;
1656
            default:
1657
                env->mmuregs[reg] = val;
1658
                break;
1659
            }
1660
            if (oldreg != env->mmuregs[reg]) {
1661
                DPRINTF_MMU("mmu change reg[%d]: 0x%08x -> 0x%08x\n",
1662
                            reg, oldreg, env->mmuregs[reg]);
1663
            }
1664
#ifdef DEBUG_MMU
1665
            dump_mmu(env);
1666
#endif
1667
        }
1668
        break;
1669
    case 5: // Turbosparc ITLB Diagnostic
1670
    case 6: // Turbosparc DTLB Diagnostic
1671
    case 7: // Turbosparc IOTLB Diagnostic
1672
        break;
1673
    case 0xa: /* User data access */
1674
        switch(size) {
1675
        case 1:
1676
            stb_user(addr, val);
1677
            break;
1678
        case 2:
1679
            stw_user(addr, val);
1680
            break;
1681
        default:
1682
        case 4:
1683
            stl_user(addr, val);
1684
            break;
1685
        case 8:
1686
            stq_user(addr, val);
1687
            break;
1688
        }
1689
        break;
1690
    case 0xb: /* Supervisor data access */
1691
        switch(size) {
1692
        case 1:
1693
            stb_kernel(addr, val);
1694
            break;
1695
        case 2:
1696
            stw_kernel(addr, val);
1697
            break;
1698
        default:
1699
        case 4:
1700
            stl_kernel(addr, val);
1701
            break;
1702
        case 8:
1703
            stq_kernel(addr, val);
1704
            break;
1705
        }
1706
        break;
1707
    case 0xc: /* I-cache tag */
1708
    case 0xd: /* I-cache data */
1709
    case 0xe: /* D-cache tag */
1710
    case 0xf: /* D-cache data */
1711
    case 0x10: /* I/D-cache flush page */
1712
    case 0x11: /* I/D-cache flush segment */
1713
    case 0x12: /* I/D-cache flush region */
1714
    case 0x13: /* I/D-cache flush context */
1715
    case 0x14: /* I/D-cache flush user */
1716
        break;
1717
    case 0x17: /* Block copy, sta access */
1718
        {
1719
            // val = src
1720
            // addr = dst
1721
            // copy 32 bytes
1722
            unsigned int i;
1723
            uint32_t src = val & ~3, dst = addr & ~3, temp;
1724

    
1725
            for (i = 0; i < 32; i += 4, src += 4, dst += 4) {
1726
                temp = ldl_kernel(src);
1727
                stl_kernel(dst, temp);
1728
            }
1729
        }
1730
        break;
1731
    case 0x1f: /* Block fill, stda access */
1732
        {
1733
            // addr = dst
1734
            // fill 32 bytes with val
1735
            unsigned int i;
1736
            uint32_t dst = addr & 7;
1737

    
1738
            for (i = 0; i < 32; i += 8, dst += 8)
1739
                stq_kernel(dst, val);
1740
        }
1741
        break;
1742
    case 0x20: /* MMU passthrough */
1743
        {
1744
            switch(size) {
1745
            case 1:
1746
                stb_phys(addr, val);
1747
                break;
1748
            case 2:
1749
                stw_phys(addr, val);
1750
                break;
1751
            case 4:
1752
            default:
1753
                stl_phys(addr, val);
1754
                break;
1755
            case 8:
1756
                stq_phys(addr, val);
1757
                break;
1758
            }
1759
        }
1760
        break;
1761
    case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
1762
        {
1763
            switch(size) {
1764
            case 1:
1765
                stb_phys((target_phys_addr_t)addr
1766
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1767
                break;
1768
            case 2:
1769
                stw_phys((target_phys_addr_t)addr
1770
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1771
                break;
1772
            case 4:
1773
            default:
1774
                stl_phys((target_phys_addr_t)addr
1775
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1776
                break;
1777
            case 8:
1778
                stq_phys((target_phys_addr_t)addr
1779
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1780
                break;
1781
            }
1782
        }
1783
        break;
1784
    case 0x30: // store buffer tags or Turbosparc secondary cache diagnostic
1785
    case 0x31: // store buffer data, Ross RT620 I-cache flush or
1786
               // Turbosparc snoop RAM
1787
    case 0x32: // store buffer control or Turbosparc page table
1788
               // descriptor diagnostic
1789
    case 0x36: /* I-cache flash clear */
1790
    case 0x37: /* D-cache flash clear */
1791
    case 0x4c: /* breakpoint action */
1792
        break;
1793
    case 0x38: /* SuperSPARC MMU Breakpoint Control Registers*/
1794
        {
1795
            int reg = (addr >> 8) & 3;
1796

    
1797
            switch(reg) {
1798
            case 0: /* Breakpoint Value (Addr) */
1799
                env->mmubpregs[reg] = (val & 0xfffffffffULL);
1800
                break;
1801
            case 1: /* Breakpoint Mask */
1802
                env->mmubpregs[reg] = (val & 0xfffffffffULL);
1803
                break;
1804
            case 2: /* Breakpoint Control */
1805
                env->mmubpregs[reg] = (val & 0x7fULL);
1806
                break;
1807
            case 3: /* Breakpoint Status */
1808
                env->mmubpregs[reg] = (val & 0xfULL);
1809
                break;
1810
            }
1811
            DPRINTF_MMU("write breakpoint reg[%d] 0x%016llx\n", reg,
1812
                        env->mmuregs[reg]);
1813
        }
1814
        break;
1815
    case 8: /* User code access, XXX */
1816
    case 9: /* Supervisor code access, XXX */
1817
    default:
1818
        do_unassigned_access(addr, 1, 0, asi, size);
1819
        break;
1820
    }
1821
#ifdef DEBUG_ASI
1822
    dump_asi("write", addr, asi, size, val);
1823
#endif
1824
}
1825

    
1826
#endif /* CONFIG_USER_ONLY */
1827
#else /* TARGET_SPARC64 */
1828

    
1829
#ifdef CONFIG_USER_ONLY
1830
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1831
{
1832
    uint64_t ret = 0;
1833
#if defined(DEBUG_ASI)
1834
    target_ulong last_addr = addr;
1835
#endif
1836

    
1837
    if (asi < 0x80)
1838
        raise_exception(TT_PRIV_ACT);
1839

    
1840
    helper_check_align(addr, size - 1);
1841
    address_mask(env, &addr);
1842

    
1843
    switch (asi) {
1844
    case 0x82: // Primary no-fault
1845
    case 0x8a: // Primary no-fault LE
1846
        if (page_check_range(addr, size, PAGE_READ) == -1) {
1847
#ifdef DEBUG_ASI
1848
            dump_asi("read ", last_addr, asi, size, ret);
1849
#endif
1850
            return 0;
1851
        }
1852
        // Fall through
1853
    case 0x80: // Primary
1854
    case 0x88: // Primary LE
1855
        {
1856
            switch(size) {
1857
            case 1:
1858
                ret = ldub_raw(addr);
1859
                break;
1860
            case 2:
1861
                ret = lduw_raw(addr);
1862
                break;
1863
            case 4:
1864
                ret = ldl_raw(addr);
1865
                break;
1866
            default:
1867
            case 8:
1868
                ret = ldq_raw(addr);
1869
                break;
1870
            }
1871
        }
1872
        break;
1873
    case 0x83: // Secondary no-fault
1874
    case 0x8b: // Secondary no-fault LE
1875
        if (page_check_range(addr, size, PAGE_READ) == -1) {
1876
#ifdef DEBUG_ASI
1877
            dump_asi("read ", last_addr, asi, size, ret);
1878
#endif
1879
            return 0;
1880
        }
1881
        // Fall through
1882
    case 0x81: // Secondary
1883
    case 0x89: // Secondary LE
1884
        // XXX
1885
        break;
1886
    default:
1887
        break;
1888
    }
1889

    
1890
    /* Convert from little endian */
1891
    switch (asi) {
1892
    case 0x88: // Primary LE
1893
    case 0x89: // Secondary LE
1894
    case 0x8a: // Primary no-fault LE
1895
    case 0x8b: // Secondary no-fault LE
1896
        switch(size) {
1897
        case 2:
1898
            ret = bswap16(ret);
1899
            break;
1900
        case 4:
1901
            ret = bswap32(ret);
1902
            break;
1903
        case 8:
1904
            ret = bswap64(ret);
1905
            break;
1906
        default:
1907
            break;
1908
        }
1909
    default:
1910
        break;
1911
    }
1912

    
1913
    /* Convert to signed number */
1914
    if (sign) {
1915
        switch(size) {
1916
        case 1:
1917
            ret = (int8_t) ret;
1918
            break;
1919
        case 2:
1920
            ret = (int16_t) ret;
1921
            break;
1922
        case 4:
1923
            ret = (int32_t) ret;
1924
            break;
1925
        default:
1926
            break;
1927
        }
1928
    }
1929
#ifdef DEBUG_ASI
1930
    dump_asi("read ", last_addr, asi, size, ret);
1931
#endif
1932
    return ret;
1933
}
1934

    
1935
void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
1936
{
1937
#ifdef DEBUG_ASI
1938
    dump_asi("write", addr, asi, size, val);
1939
#endif
1940
    if (asi < 0x80)
1941
        raise_exception(TT_PRIV_ACT);
1942

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

    
1946
    /* Convert to little endian */
1947
    switch (asi) {
1948
    case 0x88: // Primary LE
1949
    case 0x89: // Secondary LE
1950
        switch(size) {
1951
        case 2:
1952
            addr = bswap16(addr);
1953
            break;
1954
        case 4:
1955
            addr = bswap32(addr);
1956
            break;
1957
        case 8:
1958
            addr = bswap64(addr);
1959
            break;
1960
        default:
1961
            break;
1962
        }
1963
    default:
1964
        break;
1965
    }
1966

    
1967
    switch(asi) {
1968
    case 0x80: // Primary
1969
    case 0x88: // Primary LE
1970
        {
1971
            switch(size) {
1972
            case 1:
1973
                stb_raw(addr, val);
1974
                break;
1975
            case 2:
1976
                stw_raw(addr, val);
1977
                break;
1978
            case 4:
1979
                stl_raw(addr, val);
1980
                break;
1981
            case 8:
1982
            default:
1983
                stq_raw(addr, val);
1984
                break;
1985
            }
1986
        }
1987
        break;
1988
    case 0x81: // Secondary
1989
    case 0x89: // Secondary LE
1990
        // XXX
1991
        return;
1992

    
1993
    case 0x82: // Primary no-fault, RO
1994
    case 0x83: // Secondary no-fault, RO
1995
    case 0x8a: // Primary no-fault LE, RO
1996
    case 0x8b: // Secondary no-fault LE, RO
1997
    default:
1998
        do_unassigned_access(addr, 1, 0, 1, size);
1999
        return;
2000
    }
2001
}
2002

    
2003
#else /* CONFIG_USER_ONLY */
2004

    
2005
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
2006
{
2007
    uint64_t ret = 0;
2008
#if defined(DEBUG_ASI)
2009
    target_ulong last_addr = addr;
2010
#endif
2011

    
2012
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
2013
        || ((env->def->features & CPU_FEATURE_HYPV)
2014
            && asi >= 0x30 && asi < 0x80
2015
            && !(env->hpstate & HS_PRIV)))
2016
        raise_exception(TT_PRIV_ACT);
2017

    
2018
    helper_check_align(addr, size - 1);
2019
    switch (asi) {
2020
    case 0x82: // Primary no-fault
2021
    case 0x8a: // Primary no-fault LE
2022
        if (cpu_get_phys_page_debug(env, addr) == -1ULL) {
2023
#ifdef DEBUG_ASI
2024
            dump_asi("read ", last_addr, asi, size, ret);
2025
#endif
2026
            return 0;
2027
        }
2028
        // Fall through
2029
    case 0x10: // As if user primary
2030
    case 0x18: // As if user primary LE
2031
    case 0x80: // Primary
2032
    case 0x88: // Primary LE
2033
    case 0xe2: // UA2007 Primary block init
2034
    case 0xe3: // UA2007 Secondary block init
2035
        if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
2036
            if ((env->def->features & CPU_FEATURE_HYPV)
2037
                && env->hpstate & HS_PRIV) {
2038
                switch(size) {
2039
                case 1:
2040
                    ret = ldub_hypv(addr);
2041
                    break;
2042
                case 2:
2043
                    ret = lduw_hypv(addr);
2044
                    break;
2045
                case 4:
2046
                    ret = ldl_hypv(addr);
2047
                    break;
2048
                default:
2049
                case 8:
2050
                    ret = ldq_hypv(addr);
2051
                    break;
2052
                }
2053
            } else {
2054
                switch(size) {
2055
                case 1:
2056
                    ret = ldub_kernel(addr);
2057
                    break;
2058
                case 2:
2059
                    ret = lduw_kernel(addr);
2060
                    break;
2061
                case 4:
2062
                    ret = ldl_kernel(addr);
2063
                    break;
2064
                default:
2065
                case 8:
2066
                    ret = ldq_kernel(addr);
2067
                    break;
2068
                }
2069
            }
2070
        } else {
2071
            switch(size) {
2072
            case 1:
2073
                ret = ldub_user(addr);
2074
                break;
2075
            case 2:
2076
                ret = lduw_user(addr);
2077
                break;
2078
            case 4:
2079
                ret = ldl_user(addr);
2080
                break;
2081
            default:
2082
            case 8:
2083
                ret = ldq_user(addr);
2084
                break;
2085
            }
2086
        }
2087
        break;
2088
    case 0x14: // Bypass
2089
    case 0x15: // Bypass, non-cacheable
2090
    case 0x1c: // Bypass LE
2091
    case 0x1d: // Bypass, non-cacheable LE
2092
        {
2093
            switch(size) {
2094
            case 1:
2095
                ret = ldub_phys(addr);
2096
                break;
2097
            case 2:
2098
                ret = lduw_phys(addr);
2099
                break;
2100
            case 4:
2101
                ret = ldl_phys(addr);
2102
                break;
2103
            default:
2104
            case 8:
2105
                ret = ldq_phys(addr);
2106
                break;
2107
            }
2108
            break;
2109
        }
2110
    case 0x24: // Nucleus quad LDD 128 bit atomic
2111
    case 0x2c: // Nucleus quad LDD 128 bit atomic LE
2112
        //  Only ldda allowed
2113
        raise_exception(TT_ILL_INSN);
2114
        return 0;
2115
    case 0x83: // Secondary no-fault
2116
    case 0x8b: // Secondary no-fault LE
2117
        if (cpu_get_phys_page_debug(env, addr) == -1ULL) {
2118
#ifdef DEBUG_ASI
2119
            dump_asi("read ", last_addr, asi, size, ret);
2120
#endif
2121
            return 0;
2122
        }
2123
        // Fall through
2124
    case 0x04: // Nucleus
2125
    case 0x0c: // Nucleus Little Endian (LE)
2126
    case 0x11: // As if user secondary
2127
    case 0x19: // As if user secondary LE
2128
    case 0x4a: // UPA config
2129
    case 0x81: // Secondary
2130
    case 0x89: // Secondary LE
2131
        // XXX
2132
        break;
2133
    case 0x45: // LSU
2134
        ret = env->lsu;
2135
        break;
2136
    case 0x50: // I-MMU regs
2137
        {
2138
            int reg = (addr >> 3) & 0xf;
2139

    
2140
            if (reg == 0) {
2141
                // I-TSB Tag Target register
2142
                ret = ultrasparc_tag_target(env->immuregs[6]);
2143
            } else {
2144
                ret = env->immuregs[reg];
2145
            }
2146

    
2147
            break;
2148
        }
2149
    case 0x51: // I-MMU 8k TSB pointer
2150
        {
2151
            // env->immuregs[5] holds I-MMU TSB register value
2152
            // env->immuregs[6] holds I-MMU Tag Access register value
2153
            ret = ultrasparc_tsb_pointer(env->immuregs[5], env->immuregs[6],
2154
                                         8*1024);
2155
            break;
2156
        }
2157
    case 0x52: // I-MMU 64k TSB pointer
2158
        {
2159
            // env->immuregs[5] holds I-MMU TSB register value
2160
            // env->immuregs[6] holds I-MMU Tag Access register value
2161
            ret = ultrasparc_tsb_pointer(env->immuregs[5], env->immuregs[6],
2162
                                         64*1024);
2163
            break;
2164
        }
2165
    case 0x55: // I-MMU data access
2166
        {
2167
            int reg = (addr >> 3) & 0x3f;
2168

    
2169
            ret = env->itlb_tte[reg];
2170
            break;
2171
        }
2172
    case 0x56: // I-MMU tag read
2173
        {
2174
            int reg = (addr >> 3) & 0x3f;
2175

    
2176
            ret = env->itlb_tag[reg];
2177
            break;
2178
        }
2179
    case 0x58: // D-MMU regs
2180
        {
2181
            int reg = (addr >> 3) & 0xf;
2182

    
2183
            if (reg == 0) {
2184
                // D-TSB Tag Target register
2185
                ret = ultrasparc_tag_target(env->dmmuregs[6]);
2186
            } else {
2187
                ret = env->dmmuregs[reg];
2188
            }
2189
            break;
2190
        }
2191
    case 0x59: // D-MMU 8k TSB pointer
2192
        {
2193
            // env->dmmuregs[5] holds D-MMU TSB register value
2194
            // env->dmmuregs[6] holds D-MMU Tag Access register value
2195
            ret = ultrasparc_tsb_pointer(env->dmmuregs[5], env->dmmuregs[6],
2196
                                         8*1024);
2197
            break;
2198
        }
2199
    case 0x5a: // D-MMU 64k TSB pointer
2200
        {
2201
            // env->dmmuregs[5] holds D-MMU TSB register value
2202
            // env->dmmuregs[6] holds D-MMU Tag Access register value
2203
            ret = ultrasparc_tsb_pointer(env->dmmuregs[5], env->dmmuregs[6],
2204
                                         64*1024);
2205
            break;
2206
        }
2207
    case 0x5d: // D-MMU data access
2208
        {
2209
            int reg = (addr >> 3) & 0x3f;
2210

    
2211
            ret = env->dtlb_tte[reg];
2212
            break;
2213
        }
2214
    case 0x5e: // D-MMU tag read
2215
        {
2216
            int reg = (addr >> 3) & 0x3f;
2217

    
2218
            ret = env->dtlb_tag[reg];
2219
            break;
2220
        }
2221
    case 0x46: // D-cache data
2222
    case 0x47: // D-cache tag access
2223
    case 0x4b: // E-cache error enable
2224
    case 0x4c: // E-cache asynchronous fault status
2225
    case 0x4d: // E-cache asynchronous fault address
2226
    case 0x4e: // E-cache tag data
2227
    case 0x66: // I-cache instruction access
2228
    case 0x67: // I-cache tag access
2229
    case 0x6e: // I-cache predecode
2230
    case 0x6f: // I-cache LRU etc.
2231
    case 0x76: // E-cache tag
2232
    case 0x7e: // E-cache tag
2233
        break;
2234
    case 0x5b: // D-MMU data pointer
2235
    case 0x48: // Interrupt dispatch, RO
2236
    case 0x49: // Interrupt data receive
2237
    case 0x7f: // Incoming interrupt vector, RO
2238
        // XXX
2239
        break;
2240
    case 0x54: // I-MMU data in, WO
2241
    case 0x57: // I-MMU demap, WO
2242
    case 0x5c: // D-MMU data in, WO
2243
    case 0x5f: // D-MMU demap, WO
2244
    case 0x77: // Interrupt vector, WO
2245
    default:
2246
        do_unassigned_access(addr, 0, 0, 1, size);
2247
        ret = 0;
2248
        break;
2249
    }
2250

    
2251
    /* Convert from little endian */
2252
    switch (asi) {
2253
    case 0x0c: // Nucleus Little Endian (LE)
2254
    case 0x18: // As if user primary LE
2255
    case 0x19: // As if user secondary LE
2256
    case 0x1c: // Bypass LE
2257
    case 0x1d: // Bypass, non-cacheable LE
2258
    case 0x88: // Primary LE
2259
    case 0x89: // Secondary LE
2260
    case 0x8a: // Primary no-fault LE
2261
    case 0x8b: // Secondary no-fault LE
2262
        switch(size) {
2263
        case 2:
2264
            ret = bswap16(ret);
2265
            break;
2266
        case 4:
2267
            ret = bswap32(ret);
2268
            break;
2269
        case 8:
2270
            ret = bswap64(ret);
2271
            break;
2272
        default:
2273
            break;
2274
        }
2275
    default:
2276
        break;
2277
    }
2278

    
2279
    /* Convert to signed number */
2280
    if (sign) {
2281
        switch(size) {
2282
        case 1:
2283
            ret = (int8_t) ret;
2284
            break;
2285
        case 2:
2286
            ret = (int16_t) ret;
2287
            break;
2288
        case 4:
2289
            ret = (int32_t) ret;
2290
            break;
2291
        default:
2292
            break;
2293
        }
2294
    }
2295
#ifdef DEBUG_ASI
2296
    dump_asi("read ", last_addr, asi, size, ret);
2297
#endif
2298
    return ret;
2299
}
2300

    
2301
void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
2302
{
2303
#ifdef DEBUG_ASI
2304
    dump_asi("write", addr, asi, size, val);
2305
#endif
2306
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
2307
        || ((env->def->features & CPU_FEATURE_HYPV)
2308
            && asi >= 0x30 && asi < 0x80
2309
            && !(env->hpstate & HS_PRIV)))
2310
        raise_exception(TT_PRIV_ACT);
2311

    
2312
    helper_check_align(addr, size - 1);
2313
    /* Convert to little endian */
2314
    switch (asi) {
2315
    case 0x0c: // Nucleus Little Endian (LE)
2316
    case 0x18: // As if user primary LE
2317
    case 0x19: // As if user secondary LE
2318
    case 0x1c: // Bypass LE
2319
    case 0x1d: // Bypass, non-cacheable LE
2320
    case 0x88: // Primary LE
2321
    case 0x89: // Secondary LE
2322
        switch(size) {
2323
        case 2:
2324
            addr = bswap16(addr);
2325
            break;
2326
        case 4:
2327
            addr = bswap32(addr);
2328
            break;
2329
        case 8:
2330
            addr = bswap64(addr);
2331
            break;
2332
        default:
2333
            break;
2334
        }
2335
    default:
2336
        break;
2337
    }
2338

    
2339
    switch(asi) {
2340
    case 0x10: // As if user primary
2341
    case 0x18: // As if user primary LE
2342
    case 0x80: // Primary
2343
    case 0x88: // Primary LE
2344
    case 0xe2: // UA2007 Primary block init
2345
    case 0xe3: // UA2007 Secondary block init
2346
        if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
2347
            if ((env->def->features & CPU_FEATURE_HYPV)
2348
                && env->hpstate & HS_PRIV) {
2349
                switch(size) {
2350
                case 1:
2351
                    stb_hypv(addr, val);
2352
                    break;
2353
                case 2:
2354
                    stw_hypv(addr, val);
2355
                    break;
2356
                case 4:
2357
                    stl_hypv(addr, val);
2358
                    break;
2359
                case 8:
2360
                default:
2361
                    stq_hypv(addr, val);
2362
                    break;
2363
                }
2364
            } else {
2365
                switch(size) {
2366
                case 1:
2367
                    stb_kernel(addr, val);
2368
                    break;
2369
                case 2:
2370
                    stw_kernel(addr, val);
2371
                    break;
2372
                case 4:
2373
                    stl_kernel(addr, val);
2374
                    break;
2375
                case 8:
2376
                default:
2377
                    stq_kernel(addr, val);
2378
                    break;
2379
                }
2380
            }
2381
        } else {
2382
            switch(size) {
2383
            case 1:
2384
                stb_user(addr, val);
2385
                break;
2386
            case 2:
2387
                stw_user(addr, val);
2388
                break;
2389
            case 4:
2390
                stl_user(addr, val);
2391
                break;
2392
            case 8:
2393
            default:
2394
                stq_user(addr, val);
2395
                break;
2396
            }
2397
        }
2398
        break;
2399
    case 0x14: // Bypass
2400
    case 0x15: // Bypass, non-cacheable
2401
    case 0x1c: // Bypass LE
2402
    case 0x1d: // Bypass, non-cacheable LE
2403
        {
2404
            switch(size) {
2405
            case 1:
2406
                stb_phys(addr, val);
2407
                break;
2408
            case 2:
2409
                stw_phys(addr, val);
2410
                break;
2411
            case 4:
2412
                stl_phys(addr, val);
2413
                break;
2414
            case 8:
2415
            default:
2416
                stq_phys(addr, val);
2417
                break;
2418
            }
2419
        }
2420
        return;
2421
    case 0x24: // Nucleus quad LDD 128 bit atomic
2422
    case 0x2c: // Nucleus quad LDD 128 bit atomic LE
2423
        //  Only ldda allowed
2424
        raise_exception(TT_ILL_INSN);
2425
        return;
2426
    case 0x04: // Nucleus
2427
    case 0x0c: // Nucleus Little Endian (LE)
2428
    case 0x11: // As if user secondary
2429
    case 0x19: // As if user secondary LE
2430
    case 0x4a: // UPA config
2431
    case 0x81: // Secondary
2432
    case 0x89: // Secondary LE
2433
        // XXX
2434
        return;
2435
    case 0x45: // LSU
2436
        {
2437
            uint64_t oldreg;
2438

    
2439
            oldreg = env->lsu;
2440
            env->lsu = val & (DMMU_E | IMMU_E);
2441
            // Mappings generated during D/I MMU disabled mode are
2442
            // invalid in normal mode
2443
            if (oldreg != env->lsu) {
2444
                DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n",
2445
                            oldreg, env->lsu);
2446
#ifdef DEBUG_MMU
2447
                dump_mmu(env);
2448
#endif
2449
                tlb_flush(env, 1);
2450
            }
2451
            return;
2452
        }
2453
    case 0x50: // I-MMU regs
2454
        {
2455
            int reg = (addr >> 3) & 0xf;
2456
            uint64_t oldreg;
2457

    
2458
            oldreg = env->immuregs[reg];
2459
            switch(reg) {
2460
            case 0: // RO
2461
            case 4:
2462
                return;
2463
            case 1: // Not in I-MMU
2464
            case 2:
2465
            case 7:
2466
            case 8:
2467
                return;
2468
            case 3: // SFSR
2469
                if ((val & 1) == 0)
2470
                    val = 0; // Clear SFSR
2471
                break;
2472
            case 5: // TSB access
2473
            case 6: // Tag access
2474
            default:
2475
                break;
2476
            }
2477
            env->immuregs[reg] = val;
2478
            if (oldreg != env->immuregs[reg]) {
2479
                DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08"
2480
                            PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
2481
            }
2482
#ifdef DEBUG_MMU
2483
            dump_mmu(env);
2484
#endif
2485
            return;
2486
        }
2487
    case 0x54: // I-MMU data in
2488
        {
2489
            unsigned int i;
2490

    
2491
            // Try finding an invalid entry
2492
            for (i = 0; i < 64; i++) {
2493
                if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) {
2494
                    env->itlb_tag[i] = env->immuregs[6];
2495
                    env->itlb_tte[i] = val;
2496
                    return;
2497
                }
2498
            }
2499
            // Try finding an unlocked entry
2500
            for (i = 0; i < 64; i++) {
2501
                if ((env->itlb_tte[i] & 0x40) == 0) {
2502
                    env->itlb_tag[i] = env->immuregs[6];
2503
                    env->itlb_tte[i] = val;
2504
                    return;
2505
                }
2506
            }
2507
            // error state?
2508
            return;
2509
        }
2510
    case 0x55: // I-MMU data access
2511
        {
2512
            // TODO: auto demap
2513

    
2514
            unsigned int i = (addr >> 3) & 0x3f;
2515

    
2516
            env->itlb_tag[i] = env->immuregs[6];
2517
            env->itlb_tte[i] = val;
2518
            return;
2519
        }
2520
    case 0x57: // I-MMU demap
2521
        {
2522
            unsigned int i;
2523

    
2524
            for (i = 0; i < 64; i++) {
2525
                if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) {
2526
                    target_ulong mask = 0xffffffffffffe000ULL;
2527

    
2528
                    mask <<= 3 * ((env->itlb_tte[i] >> 61) & 3);
2529
                    if ((val & mask) == (env->itlb_tag[i] & mask)) {
2530
                        env->itlb_tag[i] = 0;
2531
                        env->itlb_tte[i] = 0;
2532
                    }
2533
                    return;
2534
                }
2535
            }
2536
        }
2537
        return;
2538
    case 0x58: // D-MMU regs
2539
        {
2540
            int reg = (addr >> 3) & 0xf;
2541
            uint64_t oldreg;
2542

    
2543
            oldreg = env->dmmuregs[reg];
2544
            switch(reg) {
2545
            case 0: // RO
2546
            case 4:
2547
                return;
2548
            case 3: // SFSR
2549
                if ((val & 1) == 0) {
2550
                    val = 0; // Clear SFSR, Fault address
2551
                    env->dmmuregs[4] = 0;
2552
                }
2553
                env->dmmuregs[reg] = val;
2554
                break;
2555
            case 1: // Primary context
2556
            case 2: // Secondary context
2557
            case 5: // TSB access
2558
            case 6: // Tag access
2559
            case 7: // Virtual Watchpoint
2560
            case 8: // Physical Watchpoint
2561
            default:
2562
                break;
2563
            }
2564
            env->dmmuregs[reg] = val;
2565
            if (oldreg != env->dmmuregs[reg]) {
2566
                DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08"
2567
                            PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
2568
            }
2569
#ifdef DEBUG_MMU
2570
            dump_mmu(env);
2571
#endif
2572
            return;
2573
        }
2574
    case 0x5c: // D-MMU data in
2575
        {
2576
            unsigned int i;
2577

    
2578
            // Try finding an invalid entry
2579
            for (i = 0; i < 64; i++) {
2580
                if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) {
2581
                    env->dtlb_tag[i] = env->dmmuregs[6];
2582
                    env->dtlb_tte[i] = val;
2583
                    return;
2584
                }
2585
            }
2586
            // Try finding an unlocked entry
2587
            for (i = 0; i < 64; i++) {
2588
                if ((env->dtlb_tte[i] & 0x40) == 0) {
2589
                    env->dtlb_tag[i] = env->dmmuregs[6];
2590
                    env->dtlb_tte[i] = val;
2591
                    return;
2592
                }
2593
            }
2594
            // error state?
2595
            return;
2596
        }
2597
    case 0x5d: // D-MMU data access
2598
        {
2599
            unsigned int i = (addr >> 3) & 0x3f;
2600

    
2601
            env->dtlb_tag[i] = env->dmmuregs[6];
2602
            env->dtlb_tte[i] = val;
2603
            return;
2604
        }
2605
    case 0x5f: // D-MMU demap
2606
        {
2607
            unsigned int i;
2608

    
2609
            for (i = 0; i < 64; i++) {
2610
                if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) {
2611
                    target_ulong mask = 0xffffffffffffe000ULL;
2612

    
2613
                    mask <<= 3 * ((env->dtlb_tte[i] >> 61) & 3);
2614
                    if ((val & mask) == (env->dtlb_tag[i] & mask)) {
2615
                        env->dtlb_tag[i] = 0;
2616
                        env->dtlb_tte[i] = 0;
2617
                    }
2618
                    return;
2619
                }
2620
            }
2621
        }
2622
        return;
2623
    case 0x49: // Interrupt data receive
2624
        // XXX
2625
        return;
2626
    case 0x46: // D-cache data
2627
    case 0x47: // D-cache tag access
2628
    case 0x4b: // E-cache error enable
2629
    case 0x4c: // E-cache asynchronous fault status
2630
    case 0x4d: // E-cache asynchronous fault address
2631
    case 0x4e: // E-cache tag data
2632
    case 0x66: // I-cache instruction access
2633
    case 0x67: // I-cache tag access
2634
    case 0x6e: // I-cache predecode
2635
    case 0x6f: // I-cache LRU etc.
2636
    case 0x76: // E-cache tag
2637
    case 0x7e: // E-cache tag
2638
        return;
2639
    case 0x51: // I-MMU 8k TSB pointer, RO
2640
    case 0x52: // I-MMU 64k TSB pointer, RO
2641
    case 0x56: // I-MMU tag read, RO
2642
    case 0x59: // D-MMU 8k TSB pointer, RO
2643
    case 0x5a: // D-MMU 64k TSB pointer, RO
2644
    case 0x5b: // D-MMU data pointer, RO
2645
    case 0x5e: // D-MMU tag read, RO
2646
    case 0x48: // Interrupt dispatch, RO
2647
    case 0x7f: // Incoming interrupt vector, RO
2648
    case 0x82: // Primary no-fault, RO
2649
    case 0x83: // Secondary no-fault, RO
2650
    case 0x8a: // Primary no-fault LE, RO
2651
    case 0x8b: // Secondary no-fault LE, RO
2652
    default:
2653
        do_unassigned_access(addr, 1, 0, 1, size);
2654
        return;
2655
    }
2656
}
2657
#endif /* CONFIG_USER_ONLY */
2658

    
2659
void helper_ldda_asi(target_ulong addr, int asi, int rd)
2660
{
2661
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
2662
        || ((env->def->features & CPU_FEATURE_HYPV)
2663
            && asi >= 0x30 && asi < 0x80
2664
            && !(env->hpstate & HS_PRIV)))
2665
        raise_exception(TT_PRIV_ACT);
2666

    
2667
    switch (asi) {
2668
    case 0x24: // Nucleus quad LDD 128 bit atomic
2669
    case 0x2c: // Nucleus quad LDD 128 bit atomic LE
2670
        helper_check_align(addr, 0xf);
2671
        if (rd == 0) {
2672
            env->gregs[1] = ldq_kernel(addr + 8);
2673
            if (asi == 0x2c)
2674
                bswap64s(&env->gregs[1]);
2675
        } else if (rd < 8) {
2676
            env->gregs[rd] = ldq_kernel(addr);
2677
            env->gregs[rd + 1] = ldq_kernel(addr + 8);
2678
            if (asi == 0x2c) {
2679
                bswap64s(&env->gregs[rd]);
2680
                bswap64s(&env->gregs[rd + 1]);
2681
            }
2682
        } else {
2683
            env->regwptr[rd] = ldq_kernel(addr);
2684
            env->regwptr[rd + 1] = ldq_kernel(addr + 8);
2685
            if (asi == 0x2c) {
2686
                bswap64s(&env->regwptr[rd]);
2687
                bswap64s(&env->regwptr[rd + 1]);
2688
            }
2689
        }
2690
        break;
2691
    default:
2692
        helper_check_align(addr, 0x3);
2693
        if (rd == 0)
2694
            env->gregs[1] = helper_ld_asi(addr + 4, asi, 4, 0);
2695
        else if (rd < 8) {
2696
            env->gregs[rd] = helper_ld_asi(addr, asi, 4, 0);
2697
            env->gregs[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
2698
        } else {
2699
            env->regwptr[rd] = helper_ld_asi(addr, asi, 4, 0);
2700
            env->regwptr[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
2701
        }
2702
        break;
2703
    }
2704
}
2705

    
2706
void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
2707
{
2708
    unsigned int i;
2709
    target_ulong val;
2710

    
2711
    helper_check_align(addr, 3);
2712
    switch (asi) {
2713
    case 0xf0: // Block load primary
2714
    case 0xf1: // Block load secondary
2715
    case 0xf8: // Block load primary LE
2716
    case 0xf9: // Block load secondary LE
2717
        if (rd & 7) {
2718
            raise_exception(TT_ILL_INSN);
2719
            return;
2720
        }
2721
        helper_check_align(addr, 0x3f);
2722
        for (i = 0; i < 16; i++) {
2723
            *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x8f, 4,
2724
                                                         0);
2725
            addr += 4;
2726
        }
2727

    
2728
        return;
2729
    default:
2730
        break;
2731
    }
2732

    
2733
    val = helper_ld_asi(addr, asi, size, 0);
2734
    switch(size) {
2735
    default:
2736
    case 4:
2737
        *((uint32_t *)&env->fpr[rd]) = val;
2738
        break;
2739
    case 8:
2740
        *((int64_t *)&DT0) = val;
2741
        break;
2742
    case 16:
2743
        // XXX
2744
        break;
2745
    }
2746
}
2747

    
2748
void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
2749
{
2750
    unsigned int i;
2751
    target_ulong val = 0;
2752

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

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

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

    
2792
target_ulong helper_cas_asi(target_ulong addr, target_ulong val1,
2793
                            target_ulong val2, uint32_t asi)
2794
{
2795
    target_ulong ret;
2796

    
2797
    val2 &= 0xffffffffUL;
2798
    ret = helper_ld_asi(addr, asi, 4, 0);
2799
    ret &= 0xffffffffUL;
2800
    if (val2 == ret)
2801
        helper_st_asi(addr, val1 & 0xffffffffUL, asi, 4);
2802
    return ret;
2803
}
2804

    
2805
target_ulong helper_casx_asi(target_ulong addr, target_ulong val1,
2806
                             target_ulong val2, uint32_t asi)
2807
{
2808
    target_ulong ret;
2809

    
2810
    ret = helper_ld_asi(addr, asi, 8, 0);
2811
    if (val2 == ret)
2812
        helper_st_asi(addr, val1, asi, 8);
2813
    return ret;
2814
}
2815
#endif /* TARGET_SPARC64 */
2816

    
2817
#ifndef TARGET_SPARC64
2818
void helper_rett(void)
2819
{
2820
    unsigned int cwp;
2821

    
2822
    if (env->psret == 1)
2823
        raise_exception(TT_ILL_INSN);
2824

    
2825
    env->psret = 1;
2826
    cwp = cpu_cwp_inc(env, env->cwp + 1) ;
2827
    if (env->wim & (1 << cwp)) {
2828
        raise_exception(TT_WIN_UNF);
2829
    }
2830
    set_cwp(cwp);
2831
    env->psrs = env->psrps;
2832
}
2833
#endif
2834

    
2835
target_ulong helper_udiv(target_ulong a, target_ulong b)
2836
{
2837
    uint64_t x0;
2838
    uint32_t x1;
2839

    
2840
    x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
2841
    x1 = b;
2842

    
2843
    if (x1 == 0) {
2844
        raise_exception(TT_DIV_ZERO);
2845
    }
2846

    
2847
    x0 = x0 / x1;
2848
    if (x0 > 0xffffffff) {
2849
        env->cc_src2 = 1;
2850
        return 0xffffffff;
2851
    } else {
2852
        env->cc_src2 = 0;
2853
        return x0;
2854
    }
2855
}
2856

    
2857
target_ulong helper_sdiv(target_ulong a, target_ulong b)
2858
{
2859
    int64_t x0;
2860
    int32_t x1;
2861

    
2862
    x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
2863
    x1 = b;
2864

    
2865
    if (x1 == 0) {
2866
        raise_exception(TT_DIV_ZERO);
2867
    }
2868

    
2869
    x0 = x0 / x1;
2870
    if ((int32_t) x0 != x0) {
2871
        env->cc_src2 = 1;
2872
        return x0 < 0? 0x80000000: 0x7fffffff;
2873
    } else {
2874
        env->cc_src2 = 0;
2875
        return x0;
2876
    }
2877
}
2878

    
2879
void helper_stdf(target_ulong addr, int mem_idx)
2880
{
2881
    helper_check_align(addr, 7);
2882
#if !defined(CONFIG_USER_ONLY)
2883
    switch (mem_idx) {
2884
    case 0:
2885
        stfq_user(addr, DT0);
2886
        break;
2887
    case 1:
2888
        stfq_kernel(addr, DT0);
2889
        break;
2890
#ifdef TARGET_SPARC64
2891
    case 2:
2892
        stfq_hypv(addr, DT0);
2893
        break;
2894
#endif
2895
    default:
2896
        break;
2897
    }
2898
#else
2899
    address_mask(env, &addr);
2900
    stfq_raw(addr, DT0);
2901
#endif
2902
}
2903

    
2904
void helper_lddf(target_ulong addr, int mem_idx)
2905
{
2906
    helper_check_align(addr, 7);
2907
#if !defined(CONFIG_USER_ONLY)
2908
    switch (mem_idx) {
2909
    case 0:
2910
        DT0 = ldfq_user(addr);
2911
        break;
2912
    case 1:
2913
        DT0 = ldfq_kernel(addr);
2914
        break;
2915
#ifdef TARGET_SPARC64
2916
    case 2:
2917
        DT0 = ldfq_hypv(addr);
2918
        break;
2919
#endif
2920
    default:
2921
        break;
2922
    }
2923
#else
2924
    address_mask(env, &addr);
2925
    DT0 = ldfq_raw(addr);
2926
#endif
2927
}
2928

    
2929
void helper_ldqf(target_ulong addr, int mem_idx)
2930
{
2931
    // XXX add 128 bit load
2932
    CPU_QuadU u;
2933

    
2934
    helper_check_align(addr, 7);
2935
#if !defined(CONFIG_USER_ONLY)
2936
    switch (mem_idx) {
2937
    case 0:
2938
        u.ll.upper = ldq_user(addr);
2939
        u.ll.lower = ldq_user(addr + 8);
2940
        QT0 = u.q;
2941
        break;
2942
    case 1:
2943
        u.ll.upper = ldq_kernel(addr);
2944
        u.ll.lower = ldq_kernel(addr + 8);
2945
        QT0 = u.q;
2946
        break;
2947
#ifdef TARGET_SPARC64
2948
    case 2:
2949
        u.ll.upper = ldq_hypv(addr);
2950
        u.ll.lower = ldq_hypv(addr + 8);
2951
        QT0 = u.q;
2952
        break;
2953
#endif
2954
    default:
2955
        break;
2956
    }
2957
#else
2958
    address_mask(env, &addr);
2959
    u.ll.upper = ldq_raw(addr);
2960
    u.ll.lower = ldq_raw((addr + 8) & 0xffffffffULL);
2961
    QT0 = u.q;
2962
#endif
2963
}
2964

    
2965
void helper_stqf(target_ulong addr, int mem_idx)
2966
{
2967
    // XXX add 128 bit store
2968
    CPU_QuadU u;
2969

    
2970
    helper_check_align(addr, 7);
2971
#if !defined(CONFIG_USER_ONLY)
2972
    switch (mem_idx) {
2973
    case 0:
2974
        u.q = QT0;
2975
        stq_user(addr, u.ll.upper);
2976
        stq_user(addr + 8, u.ll.lower);
2977
        break;
2978
    case 1:
2979
        u.q = QT0;
2980
        stq_kernel(addr, u.ll.upper);
2981
        stq_kernel(addr + 8, u.ll.lower);
2982
        break;
2983
#ifdef TARGET_SPARC64
2984
    case 2:
2985
        u.q = QT0;
2986
        stq_hypv(addr, u.ll.upper);
2987
        stq_hypv(addr + 8, u.ll.lower);
2988
        break;
2989
#endif
2990
    default:
2991
        break;
2992
    }
2993
#else
2994
    u.q = QT0;
2995
    address_mask(env, &addr);
2996
    stq_raw(addr, u.ll.upper);
2997
    stq_raw((addr + 8) & 0xffffffffULL, u.ll.lower);
2998
#endif
2999
}
3000

    
3001
static inline void set_fsr(void)
3002
{
3003
    int rnd_mode;
3004

    
3005
    switch (env->fsr & FSR_RD_MASK) {
3006
    case FSR_RD_NEAREST:
3007
        rnd_mode = float_round_nearest_even;
3008
        break;
3009
    default:
3010
    case FSR_RD_ZERO:
3011
        rnd_mode = float_round_to_zero;
3012
        break;
3013
    case FSR_RD_POS:
3014
        rnd_mode = float_round_up;
3015
        break;
3016
    case FSR_RD_NEG:
3017
        rnd_mode = float_round_down;
3018
        break;
3019
    }
3020
    set_float_rounding_mode(rnd_mode, &env->fp_status);
3021
}
3022

    
3023
void helper_ldfsr(uint32_t new_fsr)
3024
{
3025
    env->fsr = (new_fsr & FSR_LDFSR_MASK) | (env->fsr & FSR_LDFSR_OLDMASK);
3026
    set_fsr();
3027
}
3028

    
3029
#ifdef TARGET_SPARC64
3030
void helper_ldxfsr(uint64_t new_fsr)
3031
{
3032
    env->fsr = (new_fsr & FSR_LDXFSR_MASK) | (env->fsr & FSR_LDXFSR_OLDMASK);
3033
    set_fsr();
3034
}
3035
#endif
3036

    
3037
void helper_debug(void)
3038
{
3039
    env->exception_index = EXCP_DEBUG;
3040
    cpu_loop_exit();
3041
}
3042

    
3043
#ifndef TARGET_SPARC64
3044
/* XXX: use another pointer for %iN registers to avoid slow wrapping
3045
   handling ? */
3046
void helper_save(void)
3047
{
3048
    uint32_t cwp;
3049

    
3050
    cwp = cpu_cwp_dec(env, env->cwp - 1);
3051
    if (env->wim & (1 << cwp)) {
3052
        raise_exception(TT_WIN_OVF);
3053
    }
3054
    set_cwp(cwp);
3055
}
3056

    
3057
void helper_restore(void)
3058
{
3059
    uint32_t cwp;
3060

    
3061
    cwp = cpu_cwp_inc(env, env->cwp + 1);
3062
    if (env->wim & (1 << cwp)) {
3063
        raise_exception(TT_WIN_UNF);
3064
    }
3065
    set_cwp(cwp);
3066
}
3067

    
3068
void helper_wrpsr(target_ulong new_psr)
3069
{
3070
    if ((new_psr & PSR_CWP) >= env->nwindows)
3071
        raise_exception(TT_ILL_INSN);
3072
    else
3073
        PUT_PSR(env, new_psr);
3074
}
3075

    
3076
target_ulong helper_rdpsr(void)
3077
{
3078
    return GET_PSR(env);
3079
}
3080

    
3081
#else
3082
/* XXX: use another pointer for %iN registers to avoid slow wrapping
3083
   handling ? */
3084
void helper_save(void)
3085
{
3086
    uint32_t cwp;
3087

    
3088
    cwp = cpu_cwp_dec(env, env->cwp - 1);
3089
    if (env->cansave == 0) {
3090
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
3091
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
3092
                                    ((env->wstate & 0x7) << 2)));
3093
    } else {
3094
        if (env->cleanwin - env->canrestore == 0) {
3095
            // XXX Clean windows without trap
3096
            raise_exception(TT_CLRWIN);
3097
        } else {
3098
            env->cansave--;
3099
            env->canrestore++;
3100
            set_cwp(cwp);
3101
        }
3102
    }
3103
}
3104

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

    
3109
    cwp = cpu_cwp_inc(env, env->cwp + 1);
3110
    if (env->canrestore == 0) {
3111
        raise_exception(TT_FILL | (env->otherwin != 0 ?
3112
                                   (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
3113
                                   ((env->wstate & 0x7) << 2)));
3114
    } else {
3115
        env->cansave++;
3116
        env->canrestore--;
3117
        set_cwp(cwp);
3118
    }
3119
}
3120

    
3121
void helper_flushw(void)
3122
{
3123
    if (env->cansave != env->nwindows - 2) {
3124
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
3125
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
3126
                                    ((env->wstate & 0x7) << 2)));
3127
    }
3128
}
3129

    
3130
void helper_saved(void)
3131
{
3132
    env->cansave++;
3133
    if (env->otherwin == 0)
3134
        env->canrestore--;
3135
    else
3136
        env->otherwin--;
3137
}
3138

    
3139
void helper_restored(void)
3140
{
3141
    env->canrestore++;
3142
    if (env->cleanwin < env->nwindows - 1)
3143
        env->cleanwin++;
3144
    if (env->otherwin == 0)
3145
        env->cansave--;
3146
    else
3147
        env->otherwin--;
3148
}
3149

    
3150
target_ulong helper_rdccr(void)
3151
{
3152
    return GET_CCR(env);
3153
}
3154

    
3155
void helper_wrccr(target_ulong new_ccr)
3156
{
3157
    PUT_CCR(env, new_ccr);
3158
}
3159

    
3160
// CWP handling is reversed in V9, but we still use the V8 register
3161
// order.
3162
target_ulong helper_rdcwp(void)
3163
{
3164
    return GET_CWP64(env);
3165
}
3166

    
3167
void helper_wrcwp(target_ulong new_cwp)
3168
{
3169
    PUT_CWP64(env, new_cwp);
3170
}
3171

    
3172
// This function uses non-native bit order
3173
#define GET_FIELD(X, FROM, TO)                                  \
3174
    ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
3175

    
3176
// This function uses the order in the manuals, i.e. bit 0 is 2^0
3177
#define GET_FIELD_SP(X, FROM, TO)               \
3178
    GET_FIELD(X, 63 - (TO), 63 - (FROM))
3179

    
3180
target_ulong helper_array8(target_ulong pixel_addr, target_ulong cubesize)
3181
{
3182
    return (GET_FIELD_SP(pixel_addr, 60, 63) << (17 + 2 * cubesize)) |
3183
        (GET_FIELD_SP(pixel_addr, 39, 39 + cubesize - 1) << (17 + cubesize)) |
3184
        (GET_FIELD_SP(pixel_addr, 17 + cubesize - 1, 17) << 17) |
3185
        (GET_FIELD_SP(pixel_addr, 56, 59) << 13) |
3186
        (GET_FIELD_SP(pixel_addr, 35, 38) << 9) |
3187
        (GET_FIELD_SP(pixel_addr, 13, 16) << 5) |
3188
        (((pixel_addr >> 55) & 1) << 4) |
3189
        (GET_FIELD_SP(pixel_addr, 33, 34) << 2) |
3190
        GET_FIELD_SP(pixel_addr, 11, 12);
3191
}
3192

    
3193
target_ulong helper_alignaddr(target_ulong addr, target_ulong offset)
3194
{
3195
    uint64_t tmp;
3196

    
3197
    tmp = addr + offset;
3198
    env->gsr &= ~7ULL;
3199
    env->gsr |= tmp & 7ULL;
3200
    return tmp & ~7ULL;
3201
}
3202

    
3203
target_ulong helper_popc(target_ulong val)
3204
{
3205
    return ctpop64(val);
3206
}
3207

    
3208
static inline uint64_t *get_gregset(uint64_t pstate)
3209
{
3210
    switch (pstate) {
3211
    default:
3212
    case 0:
3213
        return env->bgregs;
3214
    case PS_AG:
3215
        return env->agregs;
3216
    case PS_MG:
3217
        return env->mgregs;
3218
    case PS_IG:
3219
        return env->igregs;
3220
    }
3221
}
3222

    
3223
static inline void change_pstate(uint64_t new_pstate)
3224
{
3225
    uint64_t pstate_regs, new_pstate_regs;
3226
    uint64_t *src, *dst;
3227

    
3228
    pstate_regs = env->pstate & 0xc01;
3229
    new_pstate_regs = new_pstate & 0xc01;
3230
    if (new_pstate_regs != pstate_regs) {
3231
        // Switch global register bank
3232
        src = get_gregset(new_pstate_regs);
3233
        dst = get_gregset(pstate_regs);
3234
        memcpy32(dst, env->gregs);
3235
        memcpy32(env->gregs, src);
3236
    }
3237
    env->pstate = new_pstate;
3238
}
3239

    
3240
void helper_wrpstate(target_ulong new_state)
3241
{
3242
    if (!(env->def->features & CPU_FEATURE_GL))
3243
        change_pstate(new_state & 0xf3f);
3244
}
3245

    
3246
void helper_done(void)
3247
{
3248
    env->pc = env->tsptr->tpc;
3249
    env->npc = env->tsptr->tnpc + 4;
3250
    PUT_CCR(env, env->tsptr->tstate >> 32);
3251
    env->asi = (env->tsptr->tstate >> 24) & 0xff;
3252
    change_pstate((env->tsptr->tstate >> 8) & 0xf3f);
3253
    PUT_CWP64(env, env->tsptr->tstate & 0xff);
3254
    env->tl--;
3255
    env->tsptr = &env->ts[env->tl & MAXTL_MASK];
3256
}
3257

    
3258
void helper_retry(void)
3259
{
3260
    env->pc = env->tsptr->tpc;
3261
    env->npc = env->tsptr->tnpc;
3262
    PUT_CCR(env, env->tsptr->tstate >> 32);
3263
    env->asi = (env->tsptr->tstate >> 24) & 0xff;
3264
    change_pstate((env->tsptr->tstate >> 8) & 0xf3f);
3265
    PUT_CWP64(env, env->tsptr->tstate & 0xff);
3266
    env->tl--;
3267
    env->tsptr = &env->ts[env->tl & MAXTL_MASK];
3268
}
3269

    
3270
void helper_set_softint(uint64_t value)
3271
{
3272
    env->softint |= (uint32_t)value;
3273
}
3274

    
3275
void helper_clear_softint(uint64_t value)
3276
{
3277
    env->softint &= (uint32_t)~value;
3278
}
3279

    
3280
void helper_write_softint(uint64_t value)
3281
{
3282
    env->softint = (uint32_t)value;
3283
}
3284
#endif
3285

    
3286
void helper_flush(target_ulong addr)
3287
{
3288
    addr &= ~7;
3289
    tb_invalidate_page_range(addr, addr + 8);
3290
}
3291

    
3292
#ifdef TARGET_SPARC64
3293
#ifdef DEBUG_PCALL
3294
static const char * const excp_names[0x80] = {
3295
    [TT_TFAULT] = "Instruction Access Fault",
3296
    [TT_TMISS] = "Instruction Access MMU Miss",
3297
    [TT_CODE_ACCESS] = "Instruction Access Error",
3298
    [TT_ILL_INSN] = "Illegal Instruction",
3299
    [TT_PRIV_INSN] = "Privileged Instruction",
3300
    [TT_NFPU_INSN] = "FPU Disabled",
3301
    [TT_FP_EXCP] = "FPU Exception",
3302
    [TT_TOVF] = "Tag Overflow",
3303
    [TT_CLRWIN] = "Clean Windows",
3304
    [TT_DIV_ZERO] = "Division By Zero",
3305
    [TT_DFAULT] = "Data Access Fault",
3306
    [TT_DMISS] = "Data Access MMU Miss",
3307
    [TT_DATA_ACCESS] = "Data Access Error",
3308
    [TT_DPROT] = "Data Protection Error",
3309
    [TT_UNALIGNED] = "Unaligned Memory Access",
3310
    [TT_PRIV_ACT] = "Privileged Action",
3311
    [TT_EXTINT | 0x1] = "External Interrupt 1",
3312
    [TT_EXTINT | 0x2] = "External Interrupt 2",
3313
    [TT_EXTINT | 0x3] = "External Interrupt 3",
3314
    [TT_EXTINT | 0x4] = "External Interrupt 4",
3315
    [TT_EXTINT | 0x5] = "External Interrupt 5",
3316
    [TT_EXTINT | 0x6] = "External Interrupt 6",
3317
    [TT_EXTINT | 0x7] = "External Interrupt 7",
3318
    [TT_EXTINT | 0x8] = "External Interrupt 8",
3319
    [TT_EXTINT | 0x9] = "External Interrupt 9",
3320
    [TT_EXTINT | 0xa] = "External Interrupt 10",
3321
    [TT_EXTINT | 0xb] = "External Interrupt 11",
3322
    [TT_EXTINT | 0xc] = "External Interrupt 12",
3323
    [TT_EXTINT | 0xd] = "External Interrupt 13",
3324
    [TT_EXTINT | 0xe] = "External Interrupt 14",
3325
    [TT_EXTINT | 0xf] = "External Interrupt 15",
3326
};
3327
#endif
3328

    
3329
void do_interrupt(CPUState *env)
3330
{
3331
    int intno = env->exception_index;
3332

    
3333
#ifdef DEBUG_PCALL
3334
    if (qemu_loglevel_mask(CPU_LOG_INT)) {
3335
        static int count;
3336
        const char *name;
3337

    
3338
        if (intno < 0 || intno >= 0x180)
3339
            name = "Unknown";
3340
        else if (intno >= 0x100)
3341
            name = "Trap Instruction";
3342
        else if (intno >= 0xc0)
3343
            name = "Window Fill";
3344
        else if (intno >= 0x80)
3345
            name = "Window Spill";
3346
        else {
3347
            name = excp_names[intno];
3348
            if (!name)
3349
                name = "Unknown";
3350
        }
3351

    
3352
        qemu_log("%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
3353
                " SP=%016" PRIx64 "\n",
3354
                count, name, intno,
3355
                env->pc,
3356
                env->npc, env->regwptr[6]);
3357
        log_cpu_state(env, 0);
3358
#if 0
3359
        {
3360
            int i;
3361
            uint8_t *ptr;
3362

3363
            qemu_log("       code=");
3364
            ptr = (uint8_t *)env->pc;
3365
            for(i = 0; i < 16; i++) {
3366
                qemu_log(" %02x", ldub(ptr + i));
3367
            }
3368
            qemu_log("\n");
3369
        }
3370
#endif
3371
        count++;
3372
    }
3373
#endif
3374
#if !defined(CONFIG_USER_ONLY)
3375
    if (env->tl >= env->maxtl) {
3376
        cpu_abort(env, "Trap 0x%04x while trap level (%d) >= MAXTL (%d),"
3377
                  " Error state", env->exception_index, env->tl, env->maxtl);
3378
        return;
3379
    }
3380
#endif
3381
    if (env->tl < env->maxtl - 1) {
3382
        env->tl++;
3383
    } else {
3384
        env->pstate |= PS_RED;
3385
        if (env->tl < env->maxtl)
3386
            env->tl++;
3387
    }
3388
    env->tsptr = &env->ts[env->tl & MAXTL_MASK];
3389
    env->tsptr->tstate = ((uint64_t)GET_CCR(env) << 32) |
3390
        ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
3391
        GET_CWP64(env);
3392
    env->tsptr->tpc = env->pc;
3393
    env->tsptr->tnpc = env->npc;
3394
    env->tsptr->tt = intno;
3395
    if (!(env->def->features & CPU_FEATURE_GL)) {
3396
        switch (intno) {
3397
        case TT_IVEC:
3398
            change_pstate(PS_PEF | PS_PRIV | PS_IG);
3399
            break;
3400
        case TT_TFAULT:
3401
        case TT_TMISS:
3402
        case TT_DFAULT:
3403
        case TT_DMISS:
3404
        case TT_DPROT:
3405
            change_pstate(PS_PEF | PS_PRIV | PS_MG);
3406
            break;
3407
        default:
3408
            change_pstate(PS_PEF | PS_PRIV | PS_AG);
3409
            break;
3410
        }
3411
    }
3412
    if (intno == TT_CLRWIN)
3413
        cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1));
3414
    else if ((intno & 0x1c0) == TT_SPILL)
3415
        cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2));
3416
    else if ((intno & 0x1c0) == TT_FILL)
3417
        cpu_set_cwp(env, cpu_cwp_inc(env, env->cwp + 1));
3418
    env->tbr &= ~0x7fffULL;
3419
    env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
3420
    env->pc = env->tbr;
3421
    env->npc = env->pc + 4;
3422
    env->exception_index = 0;
3423
}
3424
#else
3425
#ifdef DEBUG_PCALL
3426
static const char * const excp_names[0x80] = {
3427
    [TT_TFAULT] = "Instruction Access Fault",
3428
    [TT_ILL_INSN] = "Illegal Instruction",
3429
    [TT_PRIV_INSN] = "Privileged Instruction",
3430
    [TT_NFPU_INSN] = "FPU Disabled",
3431
    [TT_WIN_OVF] = "Window Overflow",
3432
    [TT_WIN_UNF] = "Window Underflow",
3433
    [TT_UNALIGNED] = "Unaligned Memory Access",
3434
    [TT_FP_EXCP] = "FPU Exception",
3435
    [TT_DFAULT] = "Data Access Fault",
3436
    [TT_TOVF] = "Tag Overflow",
3437
    [TT_EXTINT | 0x1] = "External Interrupt 1",
3438
    [TT_EXTINT | 0x2] = "External Interrupt 2",
3439
    [TT_EXTINT | 0x3] = "External Interrupt 3",
3440
    [TT_EXTINT | 0x4] = "External Interrupt 4",
3441
    [TT_EXTINT | 0x5] = "External Interrupt 5",
3442
    [TT_EXTINT | 0x6] = "External Interrupt 6",
3443
    [TT_EXTINT | 0x7] = "External Interrupt 7",
3444
    [TT_EXTINT | 0x8] = "External Interrupt 8",
3445
    [TT_EXTINT | 0x9] = "External Interrupt 9",
3446
    [TT_EXTINT | 0xa] = "External Interrupt 10",
3447
    [TT_EXTINT | 0xb] = "External Interrupt 11",
3448
    [TT_EXTINT | 0xc] = "External Interrupt 12",
3449
    [TT_EXTINT | 0xd] = "External Interrupt 13",
3450
    [TT_EXTINT | 0xe] = "External Interrupt 14",
3451
    [TT_EXTINT | 0xf] = "External Interrupt 15",
3452
    [TT_TOVF] = "Tag Overflow",
3453
    [TT_CODE_ACCESS] = "Instruction Access Error",
3454
    [TT_DATA_ACCESS] = "Data Access Error",
3455
    [TT_DIV_ZERO] = "Division By Zero",
3456
    [TT_NCP_INSN] = "Coprocessor Disabled",
3457
};
3458
#endif
3459

    
3460
void do_interrupt(CPUState *env)
3461
{
3462
    int cwp, intno = env->exception_index;
3463

    
3464
#ifdef DEBUG_PCALL
3465
    if (qemu_loglevel_mask(CPU_LOG_INT)) {
3466
        static int count;
3467
        const char *name;
3468

    
3469
        if (intno < 0 || intno >= 0x100)
3470
            name = "Unknown";
3471
        else if (intno >= 0x80)
3472
            name = "Trap Instruction";
3473
        else {
3474
            name = excp_names[intno];
3475
            if (!name)
3476
                name = "Unknown";
3477
        }
3478

    
3479
        qemu_log("%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
3480
                count, name, intno,
3481
                env->pc,
3482
                env->npc, env->regwptr[6]);
3483
        log_cpu_state(env, 0);
3484
#if 0
3485
        {
3486
            int i;
3487
            uint8_t *ptr;
3488

3489
            qemu_log("       code=");
3490
            ptr = (uint8_t *)env->pc;
3491
            for(i = 0; i < 16; i++) {
3492
                qemu_log(" %02x", ldub(ptr + i));
3493
            }
3494
            qemu_log("\n");
3495
        }
3496
#endif
3497
        count++;
3498
    }
3499
#endif
3500
#if !defined(CONFIG_USER_ONLY)
3501
    if (env->psret == 0) {
3502
        cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
3503
                  env->exception_index);
3504
        return;
3505
    }
3506
#endif
3507
    env->psret = 0;
3508
    cwp = cpu_cwp_dec(env, env->cwp - 1);
3509
    cpu_set_cwp(env, cwp);
3510
    env->regwptr[9] = env->pc;
3511
    env->regwptr[10] = env->npc;
3512
    env->psrps = env->psrs;
3513
    env->psrs = 1;
3514
    env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
3515
    env->pc = env->tbr;
3516
    env->npc = env->pc + 4;
3517
    env->exception_index = 0;
3518
}
3519
#endif
3520

    
3521
#if !defined(CONFIG_USER_ONLY)
3522

    
3523
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
3524
                                void *retaddr);
3525

    
3526
#define MMUSUFFIX _mmu
3527
#define ALIGNED_ONLY
3528

    
3529
#define SHIFT 0
3530
#include "softmmu_template.h"
3531

    
3532
#define SHIFT 1
3533
#include "softmmu_template.h"
3534

    
3535
#define SHIFT 2
3536
#include "softmmu_template.h"
3537

    
3538
#define SHIFT 3
3539
#include "softmmu_template.h"
3540

    
3541
/* XXX: make it generic ? */
3542
static void cpu_restore_state2(void *retaddr)
3543
{
3544
    TranslationBlock *tb;
3545
    unsigned long pc;
3546

    
3547
    if (retaddr) {
3548
        /* now we have a real cpu fault */
3549
        pc = (unsigned long)retaddr;
3550
        tb = tb_find_pc(pc);
3551
        if (tb) {
3552
            /* the PC is inside the translated code. It means that we have
3553
               a virtual CPU fault */
3554
            cpu_restore_state(tb, env, pc, (void *)(long)env->cond);
3555
        }
3556
    }
3557
}
3558

    
3559
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
3560
                                void *retaddr)
3561
{
3562
#ifdef DEBUG_UNALIGNED
3563
    printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
3564
           "\n", addr, env->pc);
3565
#endif
3566
    cpu_restore_state2(retaddr);
3567
    raise_exception(TT_UNALIGNED);
3568
}
3569

    
3570
/* try to fill the TLB and return an exception if error. If retaddr is
3571
   NULL, it means that the function was called in C code (i.e. not
3572
   from generated code or from helper.c) */
3573
/* XXX: fix it to restore all registers */
3574
void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
3575
{
3576
    int ret;
3577
    CPUState *saved_env;
3578

    
3579
    /* XXX: hack to restore env in all cases, even if not called from
3580
       generated code */
3581
    saved_env = env;
3582
    env = cpu_single_env;
3583

    
3584
    ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
3585
    if (ret) {
3586
        cpu_restore_state2(retaddr);
3587
        cpu_loop_exit();
3588
    }
3589
    env = saved_env;
3590
}
3591

    
3592
#endif
3593

    
3594
#ifndef TARGET_SPARC64
3595
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
3596
                          int is_asi, int size)
3597
{
3598
    CPUState *saved_env;
3599

    
3600
    /* XXX: hack to restore env in all cases, even if not called from
3601
       generated code */
3602
    saved_env = env;
3603
    env = cpu_single_env;
3604
#ifdef DEBUG_UNASSIGNED
3605
    if (is_asi)
3606
        printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
3607
               " asi 0x%02x from " TARGET_FMT_lx "\n",
3608
               is_exec ? "exec" : is_write ? "write" : "read", size,
3609
               size == 1 ? "" : "s", addr, is_asi, env->pc);
3610
    else
3611
        printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
3612
               " from " TARGET_FMT_lx "\n",
3613
               is_exec ? "exec" : is_write ? "write" : "read", size,
3614
               size == 1 ? "" : "s", addr, env->pc);
3615
#endif
3616
    if (env->mmuregs[3]) /* Fault status register */
3617
        env->mmuregs[3] = 1; /* overflow (not read before another fault) */
3618
    if (is_asi)
3619
        env->mmuregs[3] |= 1 << 16;
3620
    if (env->psrs)
3621
        env->mmuregs[3] |= 1 << 5;
3622
    if (is_exec)
3623
        env->mmuregs[3] |= 1 << 6;
3624
    if (is_write)
3625
        env->mmuregs[3] |= 1 << 7;
3626
    env->mmuregs[3] |= (5 << 2) | 2;
3627
    env->mmuregs[4] = addr; /* Fault address register */
3628
    if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
3629
        if (is_exec)
3630
            raise_exception(TT_CODE_ACCESS);
3631
        else
3632
            raise_exception(TT_DATA_ACCESS);
3633
    }
3634
    env = saved_env;
3635
}
3636
#else
3637
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
3638
                          int is_asi, int size)
3639
{
3640
#ifdef DEBUG_UNASSIGNED
3641
    CPUState *saved_env;
3642

    
3643
    /* XXX: hack to restore env in all cases, even if not called from
3644
       generated code */
3645
    saved_env = env;
3646
    env = cpu_single_env;
3647
    printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx
3648
           "\n", addr, env->pc);
3649
    env = saved_env;
3650
#endif
3651
    if (is_exec)
3652
        raise_exception(TT_CODE_ACCESS);
3653
    else
3654
        raise_exception(TT_DATA_ACCESS);
3655
}
3656
#endif
3657

    
3658
#ifdef TARGET_SPARC64
3659
void helper_tick_set_count(void *opaque, uint64_t count)
3660
{
3661
#if !defined(CONFIG_USER_ONLY)
3662
    cpu_tick_set_count(opaque, count);
3663
#endif
3664
}
3665

    
3666
uint64_t helper_tick_get_count(void *opaque)
3667
{
3668
#if !defined(CONFIG_USER_ONLY)
3669
    return cpu_tick_get_count(opaque);
3670
#else
3671
    return 0;
3672
#endif
3673
}
3674

    
3675
void helper_tick_set_limit(void *opaque, uint64_t limit)
3676
{
3677
#if !defined(CONFIG_USER_ONLY)
3678
    cpu_tick_set_limit(opaque, limit);
3679
#endif
3680
}
3681
#endif