Statistics
| Branch: | Revision:

root / target-sparc / op_helper.c @ 38482a77

History | View | Annotate | Download (95.7 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_C_add_icc(target_ulong dst, target_ulong src1)
794
{
795
    uint32_t ret = 0;
796

    
797
    if ((dst & 0xffffffffULL) < (src1 & 0xffffffffULL))
798
        ret |= PSR_CARRY;
799
    return ret;
800
}
801

    
802
static inline uint32_t get_V_add_icc(target_ulong dst, target_ulong src1,
803
                                         target_ulong src2)
804
{
805
    uint32_t ret = 0;
806

    
807
    if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1ULL << 31))
808
        ret |= PSR_OVF;
809
    return ret;
810
}
811

    
812
static uint32_t compute_all_add(void)
813
{
814
    uint32_t ret;
815

    
816
    ret = get_NZ_icc(CC_DST);
817
    ret |= get_C_add_icc(CC_DST, CC_SRC);
818
    ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
819
    return ret;
820
}
821

    
822
static uint32_t compute_C_add(void)
823
{
824
    return get_C_add_icc(CC_DST, CC_SRC);
825
}
826

    
827
#ifdef TARGET_SPARC64
828
static inline uint32_t get_C_add_xcc(target_ulong dst, target_ulong src1)
829
{
830
    uint32_t ret = 0;
831

    
832
    if (dst < src1)
833
        ret |= PSR_CARRY;
834
    return ret;
835
}
836

    
837
static inline uint32_t get_V_add_xcc(target_ulong dst, target_ulong src1,
838
                                         target_ulong src2)
839
{
840
    uint32_t ret = 0;
841

    
842
    if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1ULL << 63))
843
        ret |= PSR_OVF;
844
    return ret;
845
}
846

    
847
static uint32_t compute_all_add_xcc(void)
848
{
849
    uint32_t ret;
850

    
851
    ret = get_NZ_xcc(CC_DST);
852
    ret |= get_C_add_xcc(CC_DST, CC_SRC);
853
    ret |= get_V_add_xcc(CC_DST, CC_SRC, CC_SRC2);
854
    return ret;
855
}
856

    
857
static uint32_t compute_C_add_xcc(void)
858
{
859
    return get_C_add_xcc(CC_DST, CC_SRC);
860
}
861
#endif
862

    
863
static uint32_t compute_all_addx(void)
864
{
865
    uint32_t ret;
866

    
867
    ret = get_NZ_icc(CC_DST);
868
    ret |= get_C_add_icc(CC_DST - CC_SRC2, CC_SRC);
869
    ret |= get_C_add_icc(CC_DST, CC_SRC);
870
    ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
871
    return ret;
872
}
873

    
874
static uint32_t compute_C_addx(void)
875
{
876
    uint32_t ret;
877

    
878
    ret = get_C_add_icc(CC_DST - CC_SRC2, CC_SRC);
879
    ret |= get_C_add_icc(CC_DST, CC_SRC);
880
    return ret;
881
}
882

    
883
#ifdef TARGET_SPARC64
884
static uint32_t compute_all_addx_xcc(void)
885
{
886
    uint32_t ret;
887

    
888
    ret = get_NZ_xcc(CC_DST);
889
    ret |= get_C_add_xcc(CC_DST - CC_SRC2, CC_SRC);
890
    ret |= get_C_add_xcc(CC_DST, CC_SRC);
891
    ret |= get_V_add_xcc(CC_DST, CC_SRC, CC_SRC2);
892
    return ret;
893
}
894

    
895
static uint32_t compute_C_addx_xcc(void)
896
{
897
    uint32_t ret;
898

    
899
    ret = get_C_add_xcc(CC_DST - CC_SRC2, CC_SRC);
900
    ret |= get_C_add_xcc(CC_DST, CC_SRC);
901
    return ret;
902
}
903
#endif
904

    
905
static uint32_t compute_all_logic(void)
906
{
907
    return get_NZ_icc(CC_DST);
908
}
909

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

    
915
#ifdef TARGET_SPARC64
916
static uint32_t compute_all_logic_xcc(void)
917
{
918
    return get_NZ_xcc(CC_DST);
919
}
920
#endif
921

    
922
typedef struct CCTable {
923
    uint32_t (*compute_all)(void); /* return all the flags */
924
    uint32_t (*compute_c)(void);  /* return the C flag */
925
} CCTable;
926

    
927
static const CCTable icc_table[CC_OP_NB] = {
928
    /* CC_OP_DYNAMIC should never happen */
929
    [CC_OP_FLAGS] = { compute_all_flags, compute_C_flags },
930
    [CC_OP_ADD] = { compute_all_add, compute_C_add },
931
    [CC_OP_ADDX] = { compute_all_addx, compute_C_addx },
932
    [CC_OP_LOGIC] = { compute_all_logic, compute_C_logic },
933
};
934

    
935
#ifdef TARGET_SPARC64
936
static const CCTable xcc_table[CC_OP_NB] = {
937
    /* CC_OP_DYNAMIC should never happen */
938
    [CC_OP_FLAGS] = { compute_all_flags_xcc, compute_C_flags_xcc },
939
    [CC_OP_ADD] = { compute_all_add_xcc, compute_C_add_xcc },
940
    [CC_OP_ADDX] = { compute_all_addx_xcc, compute_C_addx_xcc },
941
    [CC_OP_LOGIC] = { compute_all_logic_xcc, compute_C_logic },
942
};
943
#endif
944

    
945
void helper_compute_psr(void)
946
{
947
    uint32_t new_psr;
948

    
949
    new_psr = icc_table[CC_OP].compute_all();
950
    env->psr = new_psr;
951
#ifdef TARGET_SPARC64
952
    new_psr = xcc_table[CC_OP].compute_all();
953
    env->xcc = new_psr;
954
#endif
955
    CC_OP = CC_OP_FLAGS;
956
}
957

    
958
uint32_t helper_compute_C_icc(void)
959
{
960
    uint32_t ret;
961

    
962
    ret = icc_table[CC_OP].compute_c() >> PSR_CARRY_SHIFT;
963
    return ret;
964
}
965

    
966
#ifdef TARGET_SPARC64
967
GEN_FCMPS(fcmps_fcc1, float32, 22, 0);
968
GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
969
GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0);
970

    
971
GEN_FCMPS(fcmps_fcc2, float32, 24, 0);
972
GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
973
GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0);
974

    
975
GEN_FCMPS(fcmps_fcc3, float32, 26, 0);
976
GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
977
GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0);
978

    
979
GEN_FCMPS(fcmpes_fcc1, float32, 22, 1);
980
GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
981
GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1);
982

    
983
GEN_FCMPS(fcmpes_fcc2, float32, 24, 1);
984
GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
985
GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1);
986

    
987
GEN_FCMPS(fcmpes_fcc3, float32, 26, 1);
988
GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
989
GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
990
#endif
991
#undef GEN_FCMPS
992

    
993
#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) && \
994
    defined(DEBUG_MXCC)
995
static void dump_mxcc(CPUState *env)
996
{
997
    printf("mxccdata: %016llx %016llx %016llx %016llx\n",
998
           env->mxccdata[0], env->mxccdata[1],
999
           env->mxccdata[2], env->mxccdata[3]);
1000
    printf("mxccregs: %016llx %016llx %016llx %016llx\n"
1001
           "          %016llx %016llx %016llx %016llx\n",
1002
           env->mxccregs[0], env->mxccregs[1],
1003
           env->mxccregs[2], env->mxccregs[3],
1004
           env->mxccregs[4], env->mxccregs[5],
1005
           env->mxccregs[6], env->mxccregs[7]);
1006
}
1007
#endif
1008

    
1009
#if (defined(TARGET_SPARC64) || !defined(CONFIG_USER_ONLY)) \
1010
    && defined(DEBUG_ASI)
1011
static void dump_asi(const char *txt, target_ulong addr, int asi, int size,
1012
                     uint64_t r1)
1013
{
1014
    switch (size)
1015
    {
1016
    case 1:
1017
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %02" PRIx64 "\n", txt,
1018
                    addr, asi, r1 & 0xff);
1019
        break;
1020
    case 2:
1021
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %04" PRIx64 "\n", txt,
1022
                    addr, asi, r1 & 0xffff);
1023
        break;
1024
    case 4:
1025
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %08" PRIx64 "\n", txt,
1026
                    addr, asi, r1 & 0xffffffff);
1027
        break;
1028
    case 8:
1029
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %016" PRIx64 "\n", txt,
1030
                    addr, asi, r1);
1031
        break;
1032
    }
1033
}
1034
#endif
1035

    
1036
#ifndef TARGET_SPARC64
1037
#ifndef CONFIG_USER_ONLY
1038
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1039
{
1040
    uint64_t ret = 0;
1041
#if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
1042
    uint32_t last_addr = addr;
1043
#endif
1044

    
1045
    helper_check_align(addr, size - 1);
1046
    switch (asi) {
1047
    case 2: /* SuperSparc MXCC registers */
1048
        switch (addr) {
1049
        case 0x01c00a00: /* MXCC control register */
1050
            if (size == 8)
1051
                ret = env->mxccregs[3];
1052
            else
1053
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1054
                             size);
1055
            break;
1056
        case 0x01c00a04: /* MXCC control register */
1057
            if (size == 4)
1058
                ret = env->mxccregs[3];
1059
            else
1060
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1061
                             size);
1062
            break;
1063
        case 0x01c00c00: /* Module reset register */
1064
            if (size == 8) {
1065
                ret = env->mxccregs[5];
1066
                // should we do something here?
1067
            } else
1068
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1069
                             size);
1070
            break;
1071
        case 0x01c00f00: /* MBus port address register */
1072
            if (size == 8)
1073
                ret = env->mxccregs[7];
1074
            else
1075
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1076
                             size);
1077
            break;
1078
        default:
1079
            DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr,
1080
                         size);
1081
            break;
1082
        }
1083
        DPRINTF_MXCC("asi = %d, size = %d, sign = %d, "
1084
                     "addr = %08x -> ret = %" PRIx64 ","
1085
                     "addr = %08x\n", asi, size, sign, last_addr, ret, addr);
1086
#ifdef DEBUG_MXCC
1087
        dump_mxcc(env);
1088
#endif
1089
        break;
1090
    case 3: /* MMU probe */
1091
        {
1092
            int mmulev;
1093

    
1094
            mmulev = (addr >> 8) & 15;
1095
            if (mmulev > 4)
1096
                ret = 0;
1097
            else
1098
                ret = mmu_probe(env, addr, mmulev);
1099
            DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08" PRIx64 "\n",
1100
                        addr, mmulev, ret);
1101
        }
1102
        break;
1103
    case 4: /* read MMU regs */
1104
        {
1105
            int reg = (addr >> 8) & 0x1f;
1106

    
1107
            ret = env->mmuregs[reg];
1108
            if (reg == 3) /* Fault status cleared on read */
1109
                env->mmuregs[3] = 0;
1110
            else if (reg == 0x13) /* Fault status read */
1111
                ret = env->mmuregs[3];
1112
            else if (reg == 0x14) /* Fault address read */
1113
                ret = env->mmuregs[4];
1114
            DPRINTF_MMU("mmu_read: reg[%d] = 0x%08" PRIx64 "\n", reg, ret);
1115
        }
1116
        break;
1117
    case 5: // Turbosparc ITLB Diagnostic
1118
    case 6: // Turbosparc DTLB Diagnostic
1119
    case 7: // Turbosparc IOTLB Diagnostic
1120
        break;
1121
    case 9: /* Supervisor code access */
1122
        switch(size) {
1123
        case 1:
1124
            ret = ldub_code(addr);
1125
            break;
1126
        case 2:
1127
            ret = lduw_code(addr);
1128
            break;
1129
        default:
1130
        case 4:
1131
            ret = ldl_code(addr);
1132
            break;
1133
        case 8:
1134
            ret = ldq_code(addr);
1135
            break;
1136
        }
1137
        break;
1138
    case 0xa: /* User data access */
1139
        switch(size) {
1140
        case 1:
1141
            ret = ldub_user(addr);
1142
            break;
1143
        case 2:
1144
            ret = lduw_user(addr);
1145
            break;
1146
        default:
1147
        case 4:
1148
            ret = ldl_user(addr);
1149
            break;
1150
        case 8:
1151
            ret = ldq_user(addr);
1152
            break;
1153
        }
1154
        break;
1155
    case 0xb: /* Supervisor data access */
1156
        switch(size) {
1157
        case 1:
1158
            ret = ldub_kernel(addr);
1159
            break;
1160
        case 2:
1161
            ret = lduw_kernel(addr);
1162
            break;
1163
        default:
1164
        case 4:
1165
            ret = ldl_kernel(addr);
1166
            break;
1167
        case 8:
1168
            ret = ldq_kernel(addr);
1169
            break;
1170
        }
1171
        break;
1172
    case 0xc: /* I-cache tag */
1173
    case 0xd: /* I-cache data */
1174
    case 0xe: /* D-cache tag */
1175
    case 0xf: /* D-cache data */
1176
        break;
1177
    case 0x20: /* MMU passthrough */
1178
        switch(size) {
1179
        case 1:
1180
            ret = ldub_phys(addr);
1181
            break;
1182
        case 2:
1183
            ret = lduw_phys(addr);
1184
            break;
1185
        default:
1186
        case 4:
1187
            ret = ldl_phys(addr);
1188
            break;
1189
        case 8:
1190
            ret = ldq_phys(addr);
1191
            break;
1192
        }
1193
        break;
1194
    case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
1195
        switch(size) {
1196
        case 1:
1197
            ret = ldub_phys((target_phys_addr_t)addr
1198
                            | ((target_phys_addr_t)(asi & 0xf) << 32));
1199
            break;
1200
        case 2:
1201
            ret = lduw_phys((target_phys_addr_t)addr
1202
                            | ((target_phys_addr_t)(asi & 0xf) << 32));
1203
            break;
1204
        default:
1205
        case 4:
1206
            ret = ldl_phys((target_phys_addr_t)addr
1207
                           | ((target_phys_addr_t)(asi & 0xf) << 32));
1208
            break;
1209
        case 8:
1210
            ret = ldq_phys((target_phys_addr_t)addr
1211
                           | ((target_phys_addr_t)(asi & 0xf) << 32));
1212
            break;
1213
        }
1214
        break;
1215
    case 0x30: // Turbosparc secondary cache diagnostic
1216
    case 0x31: // Turbosparc RAM snoop
1217
    case 0x32: // Turbosparc page table descriptor diagnostic
1218
    case 0x39: /* data cache diagnostic register */
1219
        ret = 0;
1220
        break;
1221
    case 0x38: /* SuperSPARC MMU Breakpoint Control Registers */
1222
        {
1223
            int reg = (addr >> 8) & 3;
1224

    
1225
            switch(reg) {
1226
            case 0: /* Breakpoint Value (Addr) */
1227
                ret = env->mmubpregs[reg];
1228
                break;
1229
            case 1: /* Breakpoint Mask */
1230
                ret = env->mmubpregs[reg];
1231
                break;
1232
            case 2: /* Breakpoint Control */
1233
                ret = env->mmubpregs[reg];
1234
                break;
1235
            case 3: /* Breakpoint Status */
1236
                ret = env->mmubpregs[reg];
1237
                env->mmubpregs[reg] = 0ULL;
1238
                break;
1239
            }
1240
            DPRINTF_MMU("read breakpoint reg[%d] 0x%016llx\n", reg, ret);
1241
        }
1242
        break;
1243
    case 8: /* User code access, XXX */
1244
    default:
1245
        do_unassigned_access(addr, 0, 0, asi, size);
1246
        ret = 0;
1247
        break;
1248
    }
1249
    if (sign) {
1250
        switch(size) {
1251
        case 1:
1252
            ret = (int8_t) ret;
1253
            break;
1254
        case 2:
1255
            ret = (int16_t) ret;
1256
            break;
1257
        case 4:
1258
            ret = (int32_t) ret;
1259
            break;
1260
        default:
1261
            break;
1262
        }
1263
    }
1264
#ifdef DEBUG_ASI
1265
    dump_asi("read ", last_addr, asi, size, ret);
1266
#endif
1267
    return ret;
1268
}
1269

    
1270
void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
1271
{
1272
    helper_check_align(addr, size - 1);
1273
    switch(asi) {
1274
    case 2: /* SuperSparc MXCC registers */
1275
        switch (addr) {
1276
        case 0x01c00000: /* MXCC stream data register 0 */
1277
            if (size == 8)
1278
                env->mxccdata[0] = val;
1279
            else
1280
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1281
                             size);
1282
            break;
1283
        case 0x01c00008: /* MXCC stream data register 1 */
1284
            if (size == 8)
1285
                env->mxccdata[1] = val;
1286
            else
1287
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1288
                             size);
1289
            break;
1290
        case 0x01c00010: /* MXCC stream data register 2 */
1291
            if (size == 8)
1292
                env->mxccdata[2] = val;
1293
            else
1294
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1295
                             size);
1296
            break;
1297
        case 0x01c00018: /* MXCC stream data register 3 */
1298
            if (size == 8)
1299
                env->mxccdata[3] = val;
1300
            else
1301
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1302
                             size);
1303
            break;
1304
        case 0x01c00100: /* MXCC stream source */
1305
            if (size == 8)
1306
                env->mxccregs[0] = val;
1307
            else
1308
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1309
                             size);
1310
            env->mxccdata[0] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1311
                                        0);
1312
            env->mxccdata[1] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1313
                                        8);
1314
            env->mxccdata[2] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1315
                                        16);
1316
            env->mxccdata[3] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1317
                                        24);
1318
            break;
1319
        case 0x01c00200: /* MXCC stream destination */
1320
            if (size == 8)
1321
                env->mxccregs[1] = val;
1322
            else
1323
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1324
                             size);
1325
            stq_phys((env->mxccregs[1] & 0xffffffffULL) +  0,
1326
                     env->mxccdata[0]);
1327
            stq_phys((env->mxccregs[1] & 0xffffffffULL) +  8,
1328
                     env->mxccdata[1]);
1329
            stq_phys((env->mxccregs[1] & 0xffffffffULL) + 16,
1330
                     env->mxccdata[2]);
1331
            stq_phys((env->mxccregs[1] & 0xffffffffULL) + 24,
1332
                     env->mxccdata[3]);
1333
            break;
1334
        case 0x01c00a00: /* MXCC control register */
1335
            if (size == 8)
1336
                env->mxccregs[3] = val;
1337
            else
1338
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1339
                             size);
1340
            break;
1341
        case 0x01c00a04: /* MXCC control register */
1342
            if (size == 4)
1343
                env->mxccregs[3] = (env->mxccregs[3] & 0xffffffff00000000ULL)
1344
                    | val;
1345
            else
1346
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1347
                             size);
1348
            break;
1349
        case 0x01c00e00: /* MXCC error register  */
1350
            // writing a 1 bit clears the error
1351
            if (size == 8)
1352
                env->mxccregs[6] &= ~val;
1353
            else
1354
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1355
                             size);
1356
            break;
1357
        case 0x01c00f00: /* MBus port address register */
1358
            if (size == 8)
1359
                env->mxccregs[7] = val;
1360
            else
1361
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1362
                             size);
1363
            break;
1364
        default:
1365
            DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr,
1366
                         size);
1367
            break;
1368
        }
1369
        DPRINTF_MXCC("asi = %d, size = %d, addr = %08x, val = %" PRIx64 "\n",
1370
                     asi, size, addr, val);
1371
#ifdef DEBUG_MXCC
1372
        dump_mxcc(env);
1373
#endif
1374
        break;
1375
    case 3: /* MMU flush */
1376
        {
1377
            int mmulev;
1378

    
1379
            mmulev = (addr >> 8) & 15;
1380
            DPRINTF_MMU("mmu flush level %d\n", mmulev);
1381
            switch (mmulev) {
1382
            case 0: // flush page
1383
                tlb_flush_page(env, addr & 0xfffff000);
1384
                break;
1385
            case 1: // flush segment (256k)
1386
            case 2: // flush region (16M)
1387
            case 3: // flush context (4G)
1388
            case 4: // flush entire
1389
                tlb_flush(env, 1);
1390
                break;
1391
            default:
1392
                break;
1393
            }
1394
#ifdef DEBUG_MMU
1395
            dump_mmu(env);
1396
#endif
1397
        }
1398
        break;
1399
    case 4: /* write MMU regs */
1400
        {
1401
            int reg = (addr >> 8) & 0x1f;
1402
            uint32_t oldreg;
1403

    
1404
            oldreg = env->mmuregs[reg];
1405
            switch(reg) {
1406
            case 0: // Control Register
1407
                env->mmuregs[reg] = (env->mmuregs[reg] & 0xff000000) |
1408
                                    (val & 0x00ffffff);
1409
                // Mappings generated during no-fault mode or MMU
1410
                // disabled mode are invalid in normal mode
1411
                if ((oldreg & (MMU_E | MMU_NF | env->def->mmu_bm)) !=
1412
                    (env->mmuregs[reg] & (MMU_E | MMU_NF | env->def->mmu_bm)))
1413
                    tlb_flush(env, 1);
1414
                break;
1415
            case 1: // Context Table Pointer Register
1416
                env->mmuregs[reg] = val & env->def->mmu_ctpr_mask;
1417
                break;
1418
            case 2: // Context Register
1419
                env->mmuregs[reg] = val & env->def->mmu_cxr_mask;
1420
                if (oldreg != env->mmuregs[reg]) {
1421
                    /* we flush when the MMU context changes because
1422
                       QEMU has no MMU context support */
1423
                    tlb_flush(env, 1);
1424
                }
1425
                break;
1426
            case 3: // Synchronous Fault Status Register with Clear
1427
            case 4: // Synchronous Fault Address Register
1428
                break;
1429
            case 0x10: // TLB Replacement Control Register
1430
                env->mmuregs[reg] = val & env->def->mmu_trcr_mask;
1431
                break;
1432
            case 0x13: // Synchronous Fault Status Register with Read and Clear
1433
                env->mmuregs[3] = val & env->def->mmu_sfsr_mask;
1434
                break;
1435
            case 0x14: // Synchronous Fault Address Register
1436
                env->mmuregs[4] = val;
1437
                break;
1438
            default:
1439
                env->mmuregs[reg] = val;
1440
                break;
1441
            }
1442
            if (oldreg != env->mmuregs[reg]) {
1443
                DPRINTF_MMU("mmu change reg[%d]: 0x%08x -> 0x%08x\n",
1444
                            reg, oldreg, env->mmuregs[reg]);
1445
            }
1446
#ifdef DEBUG_MMU
1447
            dump_mmu(env);
1448
#endif
1449
        }
1450
        break;
1451
    case 5: // Turbosparc ITLB Diagnostic
1452
    case 6: // Turbosparc DTLB Diagnostic
1453
    case 7: // Turbosparc IOTLB Diagnostic
1454
        break;
1455
    case 0xa: /* User data access */
1456
        switch(size) {
1457
        case 1:
1458
            stb_user(addr, val);
1459
            break;
1460
        case 2:
1461
            stw_user(addr, val);
1462
            break;
1463
        default:
1464
        case 4:
1465
            stl_user(addr, val);
1466
            break;
1467
        case 8:
1468
            stq_user(addr, val);
1469
            break;
1470
        }
1471
        break;
1472
    case 0xb: /* Supervisor data access */
1473
        switch(size) {
1474
        case 1:
1475
            stb_kernel(addr, val);
1476
            break;
1477
        case 2:
1478
            stw_kernel(addr, val);
1479
            break;
1480
        default:
1481
        case 4:
1482
            stl_kernel(addr, val);
1483
            break;
1484
        case 8:
1485
            stq_kernel(addr, val);
1486
            break;
1487
        }
1488
        break;
1489
    case 0xc: /* I-cache tag */
1490
    case 0xd: /* I-cache data */
1491
    case 0xe: /* D-cache tag */
1492
    case 0xf: /* D-cache data */
1493
    case 0x10: /* I/D-cache flush page */
1494
    case 0x11: /* I/D-cache flush segment */
1495
    case 0x12: /* I/D-cache flush region */
1496
    case 0x13: /* I/D-cache flush context */
1497
    case 0x14: /* I/D-cache flush user */
1498
        break;
1499
    case 0x17: /* Block copy, sta access */
1500
        {
1501
            // val = src
1502
            // addr = dst
1503
            // copy 32 bytes
1504
            unsigned int i;
1505
            uint32_t src = val & ~3, dst = addr & ~3, temp;
1506

    
1507
            for (i = 0; i < 32; i += 4, src += 4, dst += 4) {
1508
                temp = ldl_kernel(src);
1509
                stl_kernel(dst, temp);
1510
            }
1511
        }
1512
        break;
1513
    case 0x1f: /* Block fill, stda access */
1514
        {
1515
            // addr = dst
1516
            // fill 32 bytes with val
1517
            unsigned int i;
1518
            uint32_t dst = addr & 7;
1519

    
1520
            for (i = 0; i < 32; i += 8, dst += 8)
1521
                stq_kernel(dst, val);
1522
        }
1523
        break;
1524
    case 0x20: /* MMU passthrough */
1525
        {
1526
            switch(size) {
1527
            case 1:
1528
                stb_phys(addr, val);
1529
                break;
1530
            case 2:
1531
                stw_phys(addr, val);
1532
                break;
1533
            case 4:
1534
            default:
1535
                stl_phys(addr, val);
1536
                break;
1537
            case 8:
1538
                stq_phys(addr, val);
1539
                break;
1540
            }
1541
        }
1542
        break;
1543
    case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
1544
        {
1545
            switch(size) {
1546
            case 1:
1547
                stb_phys((target_phys_addr_t)addr
1548
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1549
                break;
1550
            case 2:
1551
                stw_phys((target_phys_addr_t)addr
1552
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1553
                break;
1554
            case 4:
1555
            default:
1556
                stl_phys((target_phys_addr_t)addr
1557
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1558
                break;
1559
            case 8:
1560
                stq_phys((target_phys_addr_t)addr
1561
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1562
                break;
1563
            }
1564
        }
1565
        break;
1566
    case 0x30: // store buffer tags or Turbosparc secondary cache diagnostic
1567
    case 0x31: // store buffer data, Ross RT620 I-cache flush or
1568
               // Turbosparc snoop RAM
1569
    case 0x32: // store buffer control or Turbosparc page table
1570
               // descriptor diagnostic
1571
    case 0x36: /* I-cache flash clear */
1572
    case 0x37: /* D-cache flash clear */
1573
    case 0x4c: /* breakpoint action */
1574
        break;
1575
    case 0x38: /* SuperSPARC MMU Breakpoint Control Registers*/
1576
        {
1577
            int reg = (addr >> 8) & 3;
1578

    
1579
            switch(reg) {
1580
            case 0: /* Breakpoint Value (Addr) */
1581
                env->mmubpregs[reg] = (val & 0xfffffffffULL);
1582
                break;
1583
            case 1: /* Breakpoint Mask */
1584
                env->mmubpregs[reg] = (val & 0xfffffffffULL);
1585
                break;
1586
            case 2: /* Breakpoint Control */
1587
                env->mmubpregs[reg] = (val & 0x7fULL);
1588
                break;
1589
            case 3: /* Breakpoint Status */
1590
                env->mmubpregs[reg] = (val & 0xfULL);
1591
                break;
1592
            }
1593
            DPRINTF_MMU("write breakpoint reg[%d] 0x%016llx\n", reg,
1594
                        env->mmuregs[reg]);
1595
        }
1596
        break;
1597
    case 8: /* User code access, XXX */
1598
    case 9: /* Supervisor code access, XXX */
1599
    default:
1600
        do_unassigned_access(addr, 1, 0, asi, size);
1601
        break;
1602
    }
1603
#ifdef DEBUG_ASI
1604
    dump_asi("write", addr, asi, size, val);
1605
#endif
1606
}
1607

    
1608
#endif /* CONFIG_USER_ONLY */
1609
#else /* TARGET_SPARC64 */
1610

    
1611
#ifdef CONFIG_USER_ONLY
1612
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1613
{
1614
    uint64_t ret = 0;
1615
#if defined(DEBUG_ASI)
1616
    target_ulong last_addr = addr;
1617
#endif
1618

    
1619
    if (asi < 0x80)
1620
        raise_exception(TT_PRIV_ACT);
1621

    
1622
    helper_check_align(addr, size - 1);
1623
    address_mask(env, &addr);
1624

    
1625
    switch (asi) {
1626
    case 0x82: // Primary no-fault
1627
    case 0x8a: // Primary no-fault LE
1628
        if (page_check_range(addr, size, PAGE_READ) == -1) {
1629
#ifdef DEBUG_ASI
1630
            dump_asi("read ", last_addr, asi, size, ret);
1631
#endif
1632
            return 0;
1633
        }
1634
        // Fall through
1635
    case 0x80: // Primary
1636
    case 0x88: // Primary LE
1637
        {
1638
            switch(size) {
1639
            case 1:
1640
                ret = ldub_raw(addr);
1641
                break;
1642
            case 2:
1643
                ret = lduw_raw(addr);
1644
                break;
1645
            case 4:
1646
                ret = ldl_raw(addr);
1647
                break;
1648
            default:
1649
            case 8:
1650
                ret = ldq_raw(addr);
1651
                break;
1652
            }
1653
        }
1654
        break;
1655
    case 0x83: // Secondary no-fault
1656
    case 0x8b: // Secondary no-fault LE
1657
        if (page_check_range(addr, size, PAGE_READ) == -1) {
1658
#ifdef DEBUG_ASI
1659
            dump_asi("read ", last_addr, asi, size, ret);
1660
#endif
1661
            return 0;
1662
        }
1663
        // Fall through
1664
    case 0x81: // Secondary
1665
    case 0x89: // Secondary LE
1666
        // XXX
1667
        break;
1668
    default:
1669
        break;
1670
    }
1671

    
1672
    /* Convert from little endian */
1673
    switch (asi) {
1674
    case 0x88: // Primary LE
1675
    case 0x89: // Secondary LE
1676
    case 0x8a: // Primary no-fault LE
1677
    case 0x8b: // Secondary no-fault LE
1678
        switch(size) {
1679
        case 2:
1680
            ret = bswap16(ret);
1681
            break;
1682
        case 4:
1683
            ret = bswap32(ret);
1684
            break;
1685
        case 8:
1686
            ret = bswap64(ret);
1687
            break;
1688
        default:
1689
            break;
1690
        }
1691
    default:
1692
        break;
1693
    }
1694

    
1695
    /* Convert to signed number */
1696
    if (sign) {
1697
        switch(size) {
1698
        case 1:
1699
            ret = (int8_t) ret;
1700
            break;
1701
        case 2:
1702
            ret = (int16_t) ret;
1703
            break;
1704
        case 4:
1705
            ret = (int32_t) ret;
1706
            break;
1707
        default:
1708
            break;
1709
        }
1710
    }
1711
#ifdef DEBUG_ASI
1712
    dump_asi("read ", last_addr, asi, size, ret);
1713
#endif
1714
    return ret;
1715
}
1716

    
1717
void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
1718
{
1719
#ifdef DEBUG_ASI
1720
    dump_asi("write", addr, asi, size, val);
1721
#endif
1722
    if (asi < 0x80)
1723
        raise_exception(TT_PRIV_ACT);
1724

    
1725
    helper_check_align(addr, size - 1);
1726
    address_mask(env, &addr);
1727

    
1728
    /* Convert to little endian */
1729
    switch (asi) {
1730
    case 0x88: // Primary LE
1731
    case 0x89: // Secondary LE
1732
        switch(size) {
1733
        case 2:
1734
            addr = bswap16(addr);
1735
            break;
1736
        case 4:
1737
            addr = bswap32(addr);
1738
            break;
1739
        case 8:
1740
            addr = bswap64(addr);
1741
            break;
1742
        default:
1743
            break;
1744
        }
1745
    default:
1746
        break;
1747
    }
1748

    
1749
    switch(asi) {
1750
    case 0x80: // Primary
1751
    case 0x88: // Primary LE
1752
        {
1753
            switch(size) {
1754
            case 1:
1755
                stb_raw(addr, val);
1756
                break;
1757
            case 2:
1758
                stw_raw(addr, val);
1759
                break;
1760
            case 4:
1761
                stl_raw(addr, val);
1762
                break;
1763
            case 8:
1764
            default:
1765
                stq_raw(addr, val);
1766
                break;
1767
            }
1768
        }
1769
        break;
1770
    case 0x81: // Secondary
1771
    case 0x89: // Secondary LE
1772
        // XXX
1773
        return;
1774

    
1775
    case 0x82: // Primary no-fault, RO
1776
    case 0x83: // Secondary no-fault, RO
1777
    case 0x8a: // Primary no-fault LE, RO
1778
    case 0x8b: // Secondary no-fault LE, RO
1779
    default:
1780
        do_unassigned_access(addr, 1, 0, 1, size);
1781
        return;
1782
    }
1783
}
1784

    
1785
#else /* CONFIG_USER_ONLY */
1786

    
1787
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1788
{
1789
    uint64_t ret = 0;
1790
#if defined(DEBUG_ASI)
1791
    target_ulong last_addr = addr;
1792
#endif
1793

    
1794
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
1795
        || ((env->def->features & CPU_FEATURE_HYPV)
1796
            && asi >= 0x30 && asi < 0x80
1797
            && !(env->hpstate & HS_PRIV)))
1798
        raise_exception(TT_PRIV_ACT);
1799

    
1800
    helper_check_align(addr, size - 1);
1801
    switch (asi) {
1802
    case 0x82: // Primary no-fault
1803
    case 0x8a: // Primary no-fault LE
1804
        if (cpu_get_phys_page_debug(env, addr) == -1ULL) {
1805
#ifdef DEBUG_ASI
1806
            dump_asi("read ", last_addr, asi, size, ret);
1807
#endif
1808
            return 0;
1809
        }
1810
        // Fall through
1811
    case 0x10: // As if user primary
1812
    case 0x18: // As if user primary LE
1813
    case 0x80: // Primary
1814
    case 0x88: // Primary LE
1815
    case 0xe2: // UA2007 Primary block init
1816
    case 0xe3: // UA2007 Secondary block init
1817
        if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
1818
            if ((env->def->features & CPU_FEATURE_HYPV)
1819
                && env->hpstate & HS_PRIV) {
1820
                switch(size) {
1821
                case 1:
1822
                    ret = ldub_hypv(addr);
1823
                    break;
1824
                case 2:
1825
                    ret = lduw_hypv(addr);
1826
                    break;
1827
                case 4:
1828
                    ret = ldl_hypv(addr);
1829
                    break;
1830
                default:
1831
                case 8:
1832
                    ret = ldq_hypv(addr);
1833
                    break;
1834
                }
1835
            } else {
1836
                switch(size) {
1837
                case 1:
1838
                    ret = ldub_kernel(addr);
1839
                    break;
1840
                case 2:
1841
                    ret = lduw_kernel(addr);
1842
                    break;
1843
                case 4:
1844
                    ret = ldl_kernel(addr);
1845
                    break;
1846
                default:
1847
                case 8:
1848
                    ret = ldq_kernel(addr);
1849
                    break;
1850
                }
1851
            }
1852
        } else {
1853
            switch(size) {
1854
            case 1:
1855
                ret = ldub_user(addr);
1856
                break;
1857
            case 2:
1858
                ret = lduw_user(addr);
1859
                break;
1860
            case 4:
1861
                ret = ldl_user(addr);
1862
                break;
1863
            default:
1864
            case 8:
1865
                ret = ldq_user(addr);
1866
                break;
1867
            }
1868
        }
1869
        break;
1870
    case 0x14: // Bypass
1871
    case 0x15: // Bypass, non-cacheable
1872
    case 0x1c: // Bypass LE
1873
    case 0x1d: // Bypass, non-cacheable LE
1874
        {
1875
            switch(size) {
1876
            case 1:
1877
                ret = ldub_phys(addr);
1878
                break;
1879
            case 2:
1880
                ret = lduw_phys(addr);
1881
                break;
1882
            case 4:
1883
                ret = ldl_phys(addr);
1884
                break;
1885
            default:
1886
            case 8:
1887
                ret = ldq_phys(addr);
1888
                break;
1889
            }
1890
            break;
1891
        }
1892
    case 0x24: // Nucleus quad LDD 128 bit atomic
1893
    case 0x2c: // Nucleus quad LDD 128 bit atomic LE
1894
        //  Only ldda allowed
1895
        raise_exception(TT_ILL_INSN);
1896
        return 0;
1897
    case 0x83: // Secondary no-fault
1898
    case 0x8b: // Secondary no-fault LE
1899
        if (cpu_get_phys_page_debug(env, addr) == -1ULL) {
1900
#ifdef DEBUG_ASI
1901
            dump_asi("read ", last_addr, asi, size, ret);
1902
#endif
1903
            return 0;
1904
        }
1905
        // Fall through
1906
    case 0x04: // Nucleus
1907
    case 0x0c: // Nucleus Little Endian (LE)
1908
    case 0x11: // As if user secondary
1909
    case 0x19: // As if user secondary LE
1910
    case 0x4a: // UPA config
1911
    case 0x81: // Secondary
1912
    case 0x89: // Secondary LE
1913
        // XXX
1914
        break;
1915
    case 0x45: // LSU
1916
        ret = env->lsu;
1917
        break;
1918
    case 0x50: // I-MMU regs
1919
        {
1920
            int reg = (addr >> 3) & 0xf;
1921

    
1922
            if (reg == 0) {
1923
                // I-TSB Tag Target register
1924
                ret = ultrasparc_tag_target(env->immuregs[6]);
1925
            } else {
1926
                ret = env->immuregs[reg];
1927
            }
1928

    
1929
            break;
1930
        }
1931
    case 0x51: // I-MMU 8k TSB pointer
1932
        {
1933
            // env->immuregs[5] holds I-MMU TSB register value
1934
            // env->immuregs[6] holds I-MMU Tag Access register value
1935
            ret = ultrasparc_tsb_pointer(env->immuregs[5], env->immuregs[6],
1936
                                         8*1024);
1937
            break;
1938
        }
1939
    case 0x52: // I-MMU 64k TSB pointer
1940
        {
1941
            // env->immuregs[5] holds I-MMU TSB register value
1942
            // env->immuregs[6] holds I-MMU Tag Access register value
1943
            ret = ultrasparc_tsb_pointer(env->immuregs[5], env->immuregs[6],
1944
                                         64*1024);
1945
            break;
1946
        }
1947
    case 0x55: // I-MMU data access
1948
        {
1949
            int reg = (addr >> 3) & 0x3f;
1950

    
1951
            ret = env->itlb_tte[reg];
1952
            break;
1953
        }
1954
    case 0x56: // I-MMU tag read
1955
        {
1956
            int reg = (addr >> 3) & 0x3f;
1957

    
1958
            ret = env->itlb_tag[reg];
1959
            break;
1960
        }
1961
    case 0x58: // D-MMU regs
1962
        {
1963
            int reg = (addr >> 3) & 0xf;
1964

    
1965
            if (reg == 0) {
1966
                // D-TSB Tag Target register
1967
                ret = ultrasparc_tag_target(env->dmmuregs[6]);
1968
            } else {
1969
                ret = env->dmmuregs[reg];
1970
            }
1971
            break;
1972
        }
1973
    case 0x59: // D-MMU 8k TSB pointer
1974
        {
1975
            // env->dmmuregs[5] holds D-MMU TSB register value
1976
            // env->dmmuregs[6] holds D-MMU Tag Access register value
1977
            ret = ultrasparc_tsb_pointer(env->dmmuregs[5], env->dmmuregs[6],
1978
                                         8*1024);
1979
            break;
1980
        }
1981
    case 0x5a: // D-MMU 64k TSB pointer
1982
        {
1983
            // env->dmmuregs[5] holds D-MMU TSB register value
1984
            // env->dmmuregs[6] holds D-MMU Tag Access register value
1985
            ret = ultrasparc_tsb_pointer(env->dmmuregs[5], env->dmmuregs[6],
1986
                                         64*1024);
1987
            break;
1988
        }
1989
    case 0x5d: // D-MMU data access
1990
        {
1991
            int reg = (addr >> 3) & 0x3f;
1992

    
1993
            ret = env->dtlb_tte[reg];
1994
            break;
1995
        }
1996
    case 0x5e: // D-MMU tag read
1997
        {
1998
            int reg = (addr >> 3) & 0x3f;
1999

    
2000
            ret = env->dtlb_tag[reg];
2001
            break;
2002
        }
2003
    case 0x46: // D-cache data
2004
    case 0x47: // D-cache tag access
2005
    case 0x4b: // E-cache error enable
2006
    case 0x4c: // E-cache asynchronous fault status
2007
    case 0x4d: // E-cache asynchronous fault address
2008
    case 0x4e: // E-cache tag data
2009
    case 0x66: // I-cache instruction access
2010
    case 0x67: // I-cache tag access
2011
    case 0x6e: // I-cache predecode
2012
    case 0x6f: // I-cache LRU etc.
2013
    case 0x76: // E-cache tag
2014
    case 0x7e: // E-cache tag
2015
        break;
2016
    case 0x5b: // D-MMU data pointer
2017
    case 0x48: // Interrupt dispatch, RO
2018
    case 0x49: // Interrupt data receive
2019
    case 0x7f: // Incoming interrupt vector, RO
2020
        // XXX
2021
        break;
2022
    case 0x54: // I-MMU data in, WO
2023
    case 0x57: // I-MMU demap, WO
2024
    case 0x5c: // D-MMU data in, WO
2025
    case 0x5f: // D-MMU demap, WO
2026
    case 0x77: // Interrupt vector, WO
2027
    default:
2028
        do_unassigned_access(addr, 0, 0, 1, size);
2029
        ret = 0;
2030
        break;
2031
    }
2032

    
2033
    /* Convert from little endian */
2034
    switch (asi) {
2035
    case 0x0c: // Nucleus Little Endian (LE)
2036
    case 0x18: // As if user primary LE
2037
    case 0x19: // As if user secondary LE
2038
    case 0x1c: // Bypass LE
2039
    case 0x1d: // Bypass, non-cacheable LE
2040
    case 0x88: // Primary LE
2041
    case 0x89: // Secondary LE
2042
    case 0x8a: // Primary no-fault LE
2043
    case 0x8b: // Secondary no-fault LE
2044
        switch(size) {
2045
        case 2:
2046
            ret = bswap16(ret);
2047
            break;
2048
        case 4:
2049
            ret = bswap32(ret);
2050
            break;
2051
        case 8:
2052
            ret = bswap64(ret);
2053
            break;
2054
        default:
2055
            break;
2056
        }
2057
    default:
2058
        break;
2059
    }
2060

    
2061
    /* Convert to signed number */
2062
    if (sign) {
2063
        switch(size) {
2064
        case 1:
2065
            ret = (int8_t) ret;
2066
            break;
2067
        case 2:
2068
            ret = (int16_t) ret;
2069
            break;
2070
        case 4:
2071
            ret = (int32_t) ret;
2072
            break;
2073
        default:
2074
            break;
2075
        }
2076
    }
2077
#ifdef DEBUG_ASI
2078
    dump_asi("read ", last_addr, asi, size, ret);
2079
#endif
2080
    return ret;
2081
}
2082

    
2083
void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
2084
{
2085
#ifdef DEBUG_ASI
2086
    dump_asi("write", addr, asi, size, val);
2087
#endif
2088
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
2089
        || ((env->def->features & CPU_FEATURE_HYPV)
2090
            && asi >= 0x30 && asi < 0x80
2091
            && !(env->hpstate & HS_PRIV)))
2092
        raise_exception(TT_PRIV_ACT);
2093

    
2094
    helper_check_align(addr, size - 1);
2095
    /* Convert to little endian */
2096
    switch (asi) {
2097
    case 0x0c: // Nucleus Little Endian (LE)
2098
    case 0x18: // As if user primary LE
2099
    case 0x19: // As if user secondary LE
2100
    case 0x1c: // Bypass LE
2101
    case 0x1d: // Bypass, non-cacheable LE
2102
    case 0x88: // Primary LE
2103
    case 0x89: // Secondary LE
2104
        switch(size) {
2105
        case 2:
2106
            addr = bswap16(addr);
2107
            break;
2108
        case 4:
2109
            addr = bswap32(addr);
2110
            break;
2111
        case 8:
2112
            addr = bswap64(addr);
2113
            break;
2114
        default:
2115
            break;
2116
        }
2117
    default:
2118
        break;
2119
    }
2120

    
2121
    switch(asi) {
2122
    case 0x10: // As if user primary
2123
    case 0x18: // As if user primary LE
2124
    case 0x80: // Primary
2125
    case 0x88: // Primary LE
2126
    case 0xe2: // UA2007 Primary block init
2127
    case 0xe3: // UA2007 Secondary block init
2128
        if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
2129
            if ((env->def->features & CPU_FEATURE_HYPV)
2130
                && env->hpstate & HS_PRIV) {
2131
                switch(size) {
2132
                case 1:
2133
                    stb_hypv(addr, val);
2134
                    break;
2135
                case 2:
2136
                    stw_hypv(addr, val);
2137
                    break;
2138
                case 4:
2139
                    stl_hypv(addr, val);
2140
                    break;
2141
                case 8:
2142
                default:
2143
                    stq_hypv(addr, val);
2144
                    break;
2145
                }
2146
            } else {
2147
                switch(size) {
2148
                case 1:
2149
                    stb_kernel(addr, val);
2150
                    break;
2151
                case 2:
2152
                    stw_kernel(addr, val);
2153
                    break;
2154
                case 4:
2155
                    stl_kernel(addr, val);
2156
                    break;
2157
                case 8:
2158
                default:
2159
                    stq_kernel(addr, val);
2160
                    break;
2161
                }
2162
            }
2163
        } else {
2164
            switch(size) {
2165
            case 1:
2166
                stb_user(addr, val);
2167
                break;
2168
            case 2:
2169
                stw_user(addr, val);
2170
                break;
2171
            case 4:
2172
                stl_user(addr, val);
2173
                break;
2174
            case 8:
2175
            default:
2176
                stq_user(addr, val);
2177
                break;
2178
            }
2179
        }
2180
        break;
2181
    case 0x14: // Bypass
2182
    case 0x15: // Bypass, non-cacheable
2183
    case 0x1c: // Bypass LE
2184
    case 0x1d: // Bypass, non-cacheable LE
2185
        {
2186
            switch(size) {
2187
            case 1:
2188
                stb_phys(addr, val);
2189
                break;
2190
            case 2:
2191
                stw_phys(addr, val);
2192
                break;
2193
            case 4:
2194
                stl_phys(addr, val);
2195
                break;
2196
            case 8:
2197
            default:
2198
                stq_phys(addr, val);
2199
                break;
2200
            }
2201
        }
2202
        return;
2203
    case 0x24: // Nucleus quad LDD 128 bit atomic
2204
    case 0x2c: // Nucleus quad LDD 128 bit atomic LE
2205
        //  Only ldda allowed
2206
        raise_exception(TT_ILL_INSN);
2207
        return;
2208
    case 0x04: // Nucleus
2209
    case 0x0c: // Nucleus Little Endian (LE)
2210
    case 0x11: // As if user secondary
2211
    case 0x19: // As if user secondary LE
2212
    case 0x4a: // UPA config
2213
    case 0x81: // Secondary
2214
    case 0x89: // Secondary LE
2215
        // XXX
2216
        return;
2217
    case 0x45: // LSU
2218
        {
2219
            uint64_t oldreg;
2220

    
2221
            oldreg = env->lsu;
2222
            env->lsu = val & (DMMU_E | IMMU_E);
2223
            // Mappings generated during D/I MMU disabled mode are
2224
            // invalid in normal mode
2225
            if (oldreg != env->lsu) {
2226
                DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n",
2227
                            oldreg, env->lsu);
2228
#ifdef DEBUG_MMU
2229
                dump_mmu(env);
2230
#endif
2231
                tlb_flush(env, 1);
2232
            }
2233
            return;
2234
        }
2235
    case 0x50: // I-MMU regs
2236
        {
2237
            int reg = (addr >> 3) & 0xf;
2238
            uint64_t oldreg;
2239

    
2240
            oldreg = env->immuregs[reg];
2241
            switch(reg) {
2242
            case 0: // RO
2243
            case 4:
2244
                return;
2245
            case 1: // Not in I-MMU
2246
            case 2:
2247
            case 7:
2248
            case 8:
2249
                return;
2250
            case 3: // SFSR
2251
                if ((val & 1) == 0)
2252
                    val = 0; // Clear SFSR
2253
                break;
2254
            case 5: // TSB access
2255
            case 6: // Tag access
2256
            default:
2257
                break;
2258
            }
2259
            env->immuregs[reg] = val;
2260
            if (oldreg != env->immuregs[reg]) {
2261
                DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08"
2262
                            PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
2263
            }
2264
#ifdef DEBUG_MMU
2265
            dump_mmu(env);
2266
#endif
2267
            return;
2268
        }
2269
    case 0x54: // I-MMU data in
2270
        {
2271
            unsigned int i;
2272

    
2273
            // Try finding an invalid entry
2274
            for (i = 0; i < 64; i++) {
2275
                if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) {
2276
                    env->itlb_tag[i] = env->immuregs[6];
2277
                    env->itlb_tte[i] = val;
2278
                    return;
2279
                }
2280
            }
2281
            // Try finding an unlocked entry
2282
            for (i = 0; i < 64; i++) {
2283
                if ((env->itlb_tte[i] & 0x40) == 0) {
2284
                    env->itlb_tag[i] = env->immuregs[6];
2285
                    env->itlb_tte[i] = val;
2286
                    return;
2287
                }
2288
            }
2289
            // error state?
2290
            return;
2291
        }
2292
    case 0x55: // I-MMU data access
2293
        {
2294
            // TODO: auto demap
2295

    
2296
            unsigned int i = (addr >> 3) & 0x3f;
2297

    
2298
            env->itlb_tag[i] = env->immuregs[6];
2299
            env->itlb_tte[i] = val;
2300
            return;
2301
        }
2302
    case 0x57: // I-MMU demap
2303
        {
2304
            unsigned int i;
2305

    
2306
            for (i = 0; i < 64; i++) {
2307
                if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) {
2308
                    target_ulong mask = 0xffffffffffffe000ULL;
2309

    
2310
                    mask <<= 3 * ((env->itlb_tte[i] >> 61) & 3);
2311
                    if ((val & mask) == (env->itlb_tag[i] & mask)) {
2312
                        env->itlb_tag[i] = 0;
2313
                        env->itlb_tte[i] = 0;
2314
                    }
2315
                    return;
2316
                }
2317
            }
2318
        }
2319
        return;
2320
    case 0x58: // D-MMU regs
2321
        {
2322
            int reg = (addr >> 3) & 0xf;
2323
            uint64_t oldreg;
2324

    
2325
            oldreg = env->dmmuregs[reg];
2326
            switch(reg) {
2327
            case 0: // RO
2328
            case 4:
2329
                return;
2330
            case 3: // SFSR
2331
                if ((val & 1) == 0) {
2332
                    val = 0; // Clear SFSR, Fault address
2333
                    env->dmmuregs[4] = 0;
2334
                }
2335
                env->dmmuregs[reg] = val;
2336
                break;
2337
            case 1: // Primary context
2338
            case 2: // Secondary context
2339
            case 5: // TSB access
2340
            case 6: // Tag access
2341
            case 7: // Virtual Watchpoint
2342
            case 8: // Physical Watchpoint
2343
            default:
2344
                break;
2345
            }
2346
            env->dmmuregs[reg] = val;
2347
            if (oldreg != env->dmmuregs[reg]) {
2348
                DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08"
2349
                            PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
2350
            }
2351
#ifdef DEBUG_MMU
2352
            dump_mmu(env);
2353
#endif
2354
            return;
2355
        }
2356
    case 0x5c: // D-MMU data in
2357
        {
2358
            unsigned int i;
2359

    
2360
            // Try finding an invalid entry
2361
            for (i = 0; i < 64; i++) {
2362
                if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) {
2363
                    env->dtlb_tag[i] = env->dmmuregs[6];
2364
                    env->dtlb_tte[i] = val;
2365
                    return;
2366
                }
2367
            }
2368
            // Try finding an unlocked entry
2369
            for (i = 0; i < 64; i++) {
2370
                if ((env->dtlb_tte[i] & 0x40) == 0) {
2371
                    env->dtlb_tag[i] = env->dmmuregs[6];
2372
                    env->dtlb_tte[i] = val;
2373
                    return;
2374
                }
2375
            }
2376
            // error state?
2377
            return;
2378
        }
2379
    case 0x5d: // D-MMU data access
2380
        {
2381
            unsigned int i = (addr >> 3) & 0x3f;
2382

    
2383
            env->dtlb_tag[i] = env->dmmuregs[6];
2384
            env->dtlb_tte[i] = val;
2385
            return;
2386
        }
2387
    case 0x5f: // D-MMU demap
2388
        {
2389
            unsigned int i;
2390

    
2391
            for (i = 0; i < 64; i++) {
2392
                if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) {
2393
                    target_ulong mask = 0xffffffffffffe000ULL;
2394

    
2395
                    mask <<= 3 * ((env->dtlb_tte[i] >> 61) & 3);
2396
                    if ((val & mask) == (env->dtlb_tag[i] & mask)) {
2397
                        env->dtlb_tag[i] = 0;
2398
                        env->dtlb_tte[i] = 0;
2399
                    }
2400
                    return;
2401
                }
2402
            }
2403
        }
2404
        return;
2405
    case 0x49: // Interrupt data receive
2406
        // XXX
2407
        return;
2408
    case 0x46: // D-cache data
2409
    case 0x47: // D-cache tag access
2410
    case 0x4b: // E-cache error enable
2411
    case 0x4c: // E-cache asynchronous fault status
2412
    case 0x4d: // E-cache asynchronous fault address
2413
    case 0x4e: // E-cache tag data
2414
    case 0x66: // I-cache instruction access
2415
    case 0x67: // I-cache tag access
2416
    case 0x6e: // I-cache predecode
2417
    case 0x6f: // I-cache LRU etc.
2418
    case 0x76: // E-cache tag
2419
    case 0x7e: // E-cache tag
2420
        return;
2421
    case 0x51: // I-MMU 8k TSB pointer, RO
2422
    case 0x52: // I-MMU 64k TSB pointer, RO
2423
    case 0x56: // I-MMU tag read, RO
2424
    case 0x59: // D-MMU 8k TSB pointer, RO
2425
    case 0x5a: // D-MMU 64k TSB pointer, RO
2426
    case 0x5b: // D-MMU data pointer, RO
2427
    case 0x5e: // D-MMU tag read, RO
2428
    case 0x48: // Interrupt dispatch, RO
2429
    case 0x7f: // Incoming interrupt vector, RO
2430
    case 0x82: // Primary no-fault, RO
2431
    case 0x83: // Secondary no-fault, RO
2432
    case 0x8a: // Primary no-fault LE, RO
2433
    case 0x8b: // Secondary no-fault LE, RO
2434
    default:
2435
        do_unassigned_access(addr, 1, 0, 1, size);
2436
        return;
2437
    }
2438
}
2439
#endif /* CONFIG_USER_ONLY */
2440

    
2441
void helper_ldda_asi(target_ulong addr, int asi, int rd)
2442
{
2443
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
2444
        || ((env->def->features & CPU_FEATURE_HYPV)
2445
            && asi >= 0x30 && asi < 0x80
2446
            && !(env->hpstate & HS_PRIV)))
2447
        raise_exception(TT_PRIV_ACT);
2448

    
2449
    switch (asi) {
2450
    case 0x24: // Nucleus quad LDD 128 bit atomic
2451
    case 0x2c: // Nucleus quad LDD 128 bit atomic LE
2452
        helper_check_align(addr, 0xf);
2453
        if (rd == 0) {
2454
            env->gregs[1] = ldq_kernel(addr + 8);
2455
            if (asi == 0x2c)
2456
                bswap64s(&env->gregs[1]);
2457
        } else if (rd < 8) {
2458
            env->gregs[rd] = ldq_kernel(addr);
2459
            env->gregs[rd + 1] = ldq_kernel(addr + 8);
2460
            if (asi == 0x2c) {
2461
                bswap64s(&env->gregs[rd]);
2462
                bswap64s(&env->gregs[rd + 1]);
2463
            }
2464
        } else {
2465
            env->regwptr[rd] = ldq_kernel(addr);
2466
            env->regwptr[rd + 1] = ldq_kernel(addr + 8);
2467
            if (asi == 0x2c) {
2468
                bswap64s(&env->regwptr[rd]);
2469
                bswap64s(&env->regwptr[rd + 1]);
2470
            }
2471
        }
2472
        break;
2473
    default:
2474
        helper_check_align(addr, 0x3);
2475
        if (rd == 0)
2476
            env->gregs[1] = helper_ld_asi(addr + 4, asi, 4, 0);
2477
        else if (rd < 8) {
2478
            env->gregs[rd] = helper_ld_asi(addr, asi, 4, 0);
2479
            env->gregs[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
2480
        } else {
2481
            env->regwptr[rd] = helper_ld_asi(addr, asi, 4, 0);
2482
            env->regwptr[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
2483
        }
2484
        break;
2485
    }
2486
}
2487

    
2488
void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
2489
{
2490
    unsigned int i;
2491
    target_ulong val;
2492

    
2493
    helper_check_align(addr, 3);
2494
    switch (asi) {
2495
    case 0xf0: // Block load primary
2496
    case 0xf1: // Block load secondary
2497
    case 0xf8: // Block load primary LE
2498
    case 0xf9: // Block load secondary LE
2499
        if (rd & 7) {
2500
            raise_exception(TT_ILL_INSN);
2501
            return;
2502
        }
2503
        helper_check_align(addr, 0x3f);
2504
        for (i = 0; i < 16; i++) {
2505
            *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x8f, 4,
2506
                                                         0);
2507
            addr += 4;
2508
        }
2509

    
2510
        return;
2511
    default:
2512
        break;
2513
    }
2514

    
2515
    val = helper_ld_asi(addr, asi, size, 0);
2516
    switch(size) {
2517
    default:
2518
    case 4:
2519
        *((uint32_t *)&env->fpr[rd]) = val;
2520
        break;
2521
    case 8:
2522
        *((int64_t *)&DT0) = val;
2523
        break;
2524
    case 16:
2525
        // XXX
2526
        break;
2527
    }
2528
}
2529

    
2530
void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
2531
{
2532
    unsigned int i;
2533
    target_ulong val = 0;
2534

    
2535
    helper_check_align(addr, 3);
2536
    switch (asi) {
2537
    case 0xe0: // UA2007 Block commit store primary (cache flush)
2538
    case 0xe1: // UA2007 Block commit store secondary (cache flush)
2539
    case 0xf0: // Block store primary
2540
    case 0xf1: // Block store secondary
2541
    case 0xf8: // Block store primary LE
2542
    case 0xf9: // Block store secondary LE
2543
        if (rd & 7) {
2544
            raise_exception(TT_ILL_INSN);
2545
            return;
2546
        }
2547
        helper_check_align(addr, 0x3f);
2548
        for (i = 0; i < 16; i++) {
2549
            val = *(uint32_t *)&env->fpr[rd++];
2550
            helper_st_asi(addr, val, asi & 0x8f, 4);
2551
            addr += 4;
2552
        }
2553

    
2554
        return;
2555
    default:
2556
        break;
2557
    }
2558

    
2559
    switch(size) {
2560
    default:
2561
    case 4:
2562
        val = *((uint32_t *)&env->fpr[rd]);
2563
        break;
2564
    case 8:
2565
        val = *((int64_t *)&DT0);
2566
        break;
2567
    case 16:
2568
        // XXX
2569
        break;
2570
    }
2571
    helper_st_asi(addr, val, asi, size);
2572
}
2573

    
2574
target_ulong helper_cas_asi(target_ulong addr, target_ulong val1,
2575
                            target_ulong val2, uint32_t asi)
2576
{
2577
    target_ulong ret;
2578

    
2579
    val2 &= 0xffffffffUL;
2580
    ret = helper_ld_asi(addr, asi, 4, 0);
2581
    ret &= 0xffffffffUL;
2582
    if (val2 == ret)
2583
        helper_st_asi(addr, val1 & 0xffffffffUL, asi, 4);
2584
    return ret;
2585
}
2586

    
2587
target_ulong helper_casx_asi(target_ulong addr, target_ulong val1,
2588
                             target_ulong val2, uint32_t asi)
2589
{
2590
    target_ulong ret;
2591

    
2592
    ret = helper_ld_asi(addr, asi, 8, 0);
2593
    if (val2 == ret)
2594
        helper_st_asi(addr, val1, asi, 8);
2595
    return ret;
2596
}
2597
#endif /* TARGET_SPARC64 */
2598

    
2599
#ifndef TARGET_SPARC64
2600
void helper_rett(void)
2601
{
2602
    unsigned int cwp;
2603

    
2604
    if (env->psret == 1)
2605
        raise_exception(TT_ILL_INSN);
2606

    
2607
    env->psret = 1;
2608
    cwp = cpu_cwp_inc(env, env->cwp + 1) ;
2609
    if (env->wim & (1 << cwp)) {
2610
        raise_exception(TT_WIN_UNF);
2611
    }
2612
    set_cwp(cwp);
2613
    env->psrs = env->psrps;
2614
}
2615
#endif
2616

    
2617
target_ulong helper_udiv(target_ulong a, target_ulong b)
2618
{
2619
    uint64_t x0;
2620
    uint32_t x1;
2621

    
2622
    x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
2623
    x1 = b;
2624

    
2625
    if (x1 == 0) {
2626
        raise_exception(TT_DIV_ZERO);
2627
    }
2628

    
2629
    x0 = x0 / x1;
2630
    if (x0 > 0xffffffff) {
2631
        env->cc_src2 = 1;
2632
        return 0xffffffff;
2633
    } else {
2634
        env->cc_src2 = 0;
2635
        return x0;
2636
    }
2637
}
2638

    
2639
target_ulong helper_sdiv(target_ulong a, target_ulong b)
2640
{
2641
    int64_t x0;
2642
    int32_t x1;
2643

    
2644
    x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
2645
    x1 = b;
2646

    
2647
    if (x1 == 0) {
2648
        raise_exception(TT_DIV_ZERO);
2649
    }
2650

    
2651
    x0 = x0 / x1;
2652
    if ((int32_t) x0 != x0) {
2653
        env->cc_src2 = 1;
2654
        return x0 < 0? 0x80000000: 0x7fffffff;
2655
    } else {
2656
        env->cc_src2 = 0;
2657
        return x0;
2658
    }
2659
}
2660

    
2661
void helper_stdf(target_ulong addr, int mem_idx)
2662
{
2663
    helper_check_align(addr, 7);
2664
#if !defined(CONFIG_USER_ONLY)
2665
    switch (mem_idx) {
2666
    case 0:
2667
        stfq_user(addr, DT0);
2668
        break;
2669
    case 1:
2670
        stfq_kernel(addr, DT0);
2671
        break;
2672
#ifdef TARGET_SPARC64
2673
    case 2:
2674
        stfq_hypv(addr, DT0);
2675
        break;
2676
#endif
2677
    default:
2678
        break;
2679
    }
2680
#else
2681
    address_mask(env, &addr);
2682
    stfq_raw(addr, DT0);
2683
#endif
2684
}
2685

    
2686
void helper_lddf(target_ulong addr, int mem_idx)
2687
{
2688
    helper_check_align(addr, 7);
2689
#if !defined(CONFIG_USER_ONLY)
2690
    switch (mem_idx) {
2691
    case 0:
2692
        DT0 = ldfq_user(addr);
2693
        break;
2694
    case 1:
2695
        DT0 = ldfq_kernel(addr);
2696
        break;
2697
#ifdef TARGET_SPARC64
2698
    case 2:
2699
        DT0 = ldfq_hypv(addr);
2700
        break;
2701
#endif
2702
    default:
2703
        break;
2704
    }
2705
#else
2706
    address_mask(env, &addr);
2707
    DT0 = ldfq_raw(addr);
2708
#endif
2709
}
2710

    
2711
void helper_ldqf(target_ulong addr, int mem_idx)
2712
{
2713
    // XXX add 128 bit load
2714
    CPU_QuadU u;
2715

    
2716
    helper_check_align(addr, 7);
2717
#if !defined(CONFIG_USER_ONLY)
2718
    switch (mem_idx) {
2719
    case 0:
2720
        u.ll.upper = ldq_user(addr);
2721
        u.ll.lower = ldq_user(addr + 8);
2722
        QT0 = u.q;
2723
        break;
2724
    case 1:
2725
        u.ll.upper = ldq_kernel(addr);
2726
        u.ll.lower = ldq_kernel(addr + 8);
2727
        QT0 = u.q;
2728
        break;
2729
#ifdef TARGET_SPARC64
2730
    case 2:
2731
        u.ll.upper = ldq_hypv(addr);
2732
        u.ll.lower = ldq_hypv(addr + 8);
2733
        QT0 = u.q;
2734
        break;
2735
#endif
2736
    default:
2737
        break;
2738
    }
2739
#else
2740
    address_mask(env, &addr);
2741
    u.ll.upper = ldq_raw(addr);
2742
    u.ll.lower = ldq_raw((addr + 8) & 0xffffffffULL);
2743
    QT0 = u.q;
2744
#endif
2745
}
2746

    
2747
void helper_stqf(target_ulong addr, int mem_idx)
2748
{
2749
    // XXX add 128 bit store
2750
    CPU_QuadU u;
2751

    
2752
    helper_check_align(addr, 7);
2753
#if !defined(CONFIG_USER_ONLY)
2754
    switch (mem_idx) {
2755
    case 0:
2756
        u.q = QT0;
2757
        stq_user(addr, u.ll.upper);
2758
        stq_user(addr + 8, u.ll.lower);
2759
        break;
2760
    case 1:
2761
        u.q = QT0;
2762
        stq_kernel(addr, u.ll.upper);
2763
        stq_kernel(addr + 8, u.ll.lower);
2764
        break;
2765
#ifdef TARGET_SPARC64
2766
    case 2:
2767
        u.q = QT0;
2768
        stq_hypv(addr, u.ll.upper);
2769
        stq_hypv(addr + 8, u.ll.lower);
2770
        break;
2771
#endif
2772
    default:
2773
        break;
2774
    }
2775
#else
2776
    u.q = QT0;
2777
    address_mask(env, &addr);
2778
    stq_raw(addr, u.ll.upper);
2779
    stq_raw((addr + 8) & 0xffffffffULL, u.ll.lower);
2780
#endif
2781
}
2782

    
2783
static inline void set_fsr(void)
2784
{
2785
    int rnd_mode;
2786

    
2787
    switch (env->fsr & FSR_RD_MASK) {
2788
    case FSR_RD_NEAREST:
2789
        rnd_mode = float_round_nearest_even;
2790
        break;
2791
    default:
2792
    case FSR_RD_ZERO:
2793
        rnd_mode = float_round_to_zero;
2794
        break;
2795
    case FSR_RD_POS:
2796
        rnd_mode = float_round_up;
2797
        break;
2798
    case FSR_RD_NEG:
2799
        rnd_mode = float_round_down;
2800
        break;
2801
    }
2802
    set_float_rounding_mode(rnd_mode, &env->fp_status);
2803
}
2804

    
2805
void helper_ldfsr(uint32_t new_fsr)
2806
{
2807
    env->fsr = (new_fsr & FSR_LDFSR_MASK) | (env->fsr & FSR_LDFSR_OLDMASK);
2808
    set_fsr();
2809
}
2810

    
2811
#ifdef TARGET_SPARC64
2812
void helper_ldxfsr(uint64_t new_fsr)
2813
{
2814
    env->fsr = (new_fsr & FSR_LDXFSR_MASK) | (env->fsr & FSR_LDXFSR_OLDMASK);
2815
    set_fsr();
2816
}
2817
#endif
2818

    
2819
void helper_debug(void)
2820
{
2821
    env->exception_index = EXCP_DEBUG;
2822
    cpu_loop_exit();
2823
}
2824

    
2825
#ifndef TARGET_SPARC64
2826
/* XXX: use another pointer for %iN registers to avoid slow wrapping
2827
   handling ? */
2828
void helper_save(void)
2829
{
2830
    uint32_t cwp;
2831

    
2832
    cwp = cpu_cwp_dec(env, env->cwp - 1);
2833
    if (env->wim & (1 << cwp)) {
2834
        raise_exception(TT_WIN_OVF);
2835
    }
2836
    set_cwp(cwp);
2837
}
2838

    
2839
void helper_restore(void)
2840
{
2841
    uint32_t cwp;
2842

    
2843
    cwp = cpu_cwp_inc(env, env->cwp + 1);
2844
    if (env->wim & (1 << cwp)) {
2845
        raise_exception(TT_WIN_UNF);
2846
    }
2847
    set_cwp(cwp);
2848
}
2849

    
2850
void helper_wrpsr(target_ulong new_psr)
2851
{
2852
    if ((new_psr & PSR_CWP) >= env->nwindows)
2853
        raise_exception(TT_ILL_INSN);
2854
    else
2855
        PUT_PSR(env, new_psr);
2856
}
2857

    
2858
target_ulong helper_rdpsr(void)
2859
{
2860
    return GET_PSR(env);
2861
}
2862

    
2863
#else
2864
/* XXX: use another pointer for %iN registers to avoid slow wrapping
2865
   handling ? */
2866
void helper_save(void)
2867
{
2868
    uint32_t cwp;
2869

    
2870
    cwp = cpu_cwp_dec(env, env->cwp - 1);
2871
    if (env->cansave == 0) {
2872
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
2873
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
2874
                                    ((env->wstate & 0x7) << 2)));
2875
    } else {
2876
        if (env->cleanwin - env->canrestore == 0) {
2877
            // XXX Clean windows without trap
2878
            raise_exception(TT_CLRWIN);
2879
        } else {
2880
            env->cansave--;
2881
            env->canrestore++;
2882
            set_cwp(cwp);
2883
        }
2884
    }
2885
}
2886

    
2887
void helper_restore(void)
2888
{
2889
    uint32_t cwp;
2890

    
2891
    cwp = cpu_cwp_inc(env, env->cwp + 1);
2892
    if (env->canrestore == 0) {
2893
        raise_exception(TT_FILL | (env->otherwin != 0 ?
2894
                                   (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
2895
                                   ((env->wstate & 0x7) << 2)));
2896
    } else {
2897
        env->cansave++;
2898
        env->canrestore--;
2899
        set_cwp(cwp);
2900
    }
2901
}
2902

    
2903
void helper_flushw(void)
2904
{
2905
    if (env->cansave != env->nwindows - 2) {
2906
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
2907
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
2908
                                    ((env->wstate & 0x7) << 2)));
2909
    }
2910
}
2911

    
2912
void helper_saved(void)
2913
{
2914
    env->cansave++;
2915
    if (env->otherwin == 0)
2916
        env->canrestore--;
2917
    else
2918
        env->otherwin--;
2919
}
2920

    
2921
void helper_restored(void)
2922
{
2923
    env->canrestore++;
2924
    if (env->cleanwin < env->nwindows - 1)
2925
        env->cleanwin++;
2926
    if (env->otherwin == 0)
2927
        env->cansave--;
2928
    else
2929
        env->otherwin--;
2930
}
2931

    
2932
target_ulong helper_rdccr(void)
2933
{
2934
    return GET_CCR(env);
2935
}
2936

    
2937
void helper_wrccr(target_ulong new_ccr)
2938
{
2939
    PUT_CCR(env, new_ccr);
2940
}
2941

    
2942
// CWP handling is reversed in V9, but we still use the V8 register
2943
// order.
2944
target_ulong helper_rdcwp(void)
2945
{
2946
    return GET_CWP64(env);
2947
}
2948

    
2949
void helper_wrcwp(target_ulong new_cwp)
2950
{
2951
    PUT_CWP64(env, new_cwp);
2952
}
2953

    
2954
// This function uses non-native bit order
2955
#define GET_FIELD(X, FROM, TO)                                  \
2956
    ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
2957

    
2958
// This function uses the order in the manuals, i.e. bit 0 is 2^0
2959
#define GET_FIELD_SP(X, FROM, TO)               \
2960
    GET_FIELD(X, 63 - (TO), 63 - (FROM))
2961

    
2962
target_ulong helper_array8(target_ulong pixel_addr, target_ulong cubesize)
2963
{
2964
    return (GET_FIELD_SP(pixel_addr, 60, 63) << (17 + 2 * cubesize)) |
2965
        (GET_FIELD_SP(pixel_addr, 39, 39 + cubesize - 1) << (17 + cubesize)) |
2966
        (GET_FIELD_SP(pixel_addr, 17 + cubesize - 1, 17) << 17) |
2967
        (GET_FIELD_SP(pixel_addr, 56, 59) << 13) |
2968
        (GET_FIELD_SP(pixel_addr, 35, 38) << 9) |
2969
        (GET_FIELD_SP(pixel_addr, 13, 16) << 5) |
2970
        (((pixel_addr >> 55) & 1) << 4) |
2971
        (GET_FIELD_SP(pixel_addr, 33, 34) << 2) |
2972
        GET_FIELD_SP(pixel_addr, 11, 12);
2973
}
2974

    
2975
target_ulong helper_alignaddr(target_ulong addr, target_ulong offset)
2976
{
2977
    uint64_t tmp;
2978

    
2979
    tmp = addr + offset;
2980
    env->gsr &= ~7ULL;
2981
    env->gsr |= tmp & 7ULL;
2982
    return tmp & ~7ULL;
2983
}
2984

    
2985
target_ulong helper_popc(target_ulong val)
2986
{
2987
    return ctpop64(val);
2988
}
2989

    
2990
static inline uint64_t *get_gregset(uint64_t pstate)
2991
{
2992
    switch (pstate) {
2993
    default:
2994
    case 0:
2995
        return env->bgregs;
2996
    case PS_AG:
2997
        return env->agregs;
2998
    case PS_MG:
2999
        return env->mgregs;
3000
    case PS_IG:
3001
        return env->igregs;
3002
    }
3003
}
3004

    
3005
static inline void change_pstate(uint64_t new_pstate)
3006
{
3007
    uint64_t pstate_regs, new_pstate_regs;
3008
    uint64_t *src, *dst;
3009

    
3010
    pstate_regs = env->pstate & 0xc01;
3011
    new_pstate_regs = new_pstate & 0xc01;
3012
    if (new_pstate_regs != pstate_regs) {
3013
        // Switch global register bank
3014
        src = get_gregset(new_pstate_regs);
3015
        dst = get_gregset(pstate_regs);
3016
        memcpy32(dst, env->gregs);
3017
        memcpy32(env->gregs, src);
3018
    }
3019
    env->pstate = new_pstate;
3020
}
3021

    
3022
void helper_wrpstate(target_ulong new_state)
3023
{
3024
    if (!(env->def->features & CPU_FEATURE_GL))
3025
        change_pstate(new_state & 0xf3f);
3026
}
3027

    
3028
void helper_done(void)
3029
{
3030
    env->pc = env->tsptr->tpc;
3031
    env->npc = env->tsptr->tnpc + 4;
3032
    PUT_CCR(env, env->tsptr->tstate >> 32);
3033
    env->asi = (env->tsptr->tstate >> 24) & 0xff;
3034
    change_pstate((env->tsptr->tstate >> 8) & 0xf3f);
3035
    PUT_CWP64(env, env->tsptr->tstate & 0xff);
3036
    env->tl--;
3037
    env->tsptr = &env->ts[env->tl & MAXTL_MASK];
3038
}
3039

    
3040
void helper_retry(void)
3041
{
3042
    env->pc = env->tsptr->tpc;
3043
    env->npc = env->tsptr->tnpc;
3044
    PUT_CCR(env, env->tsptr->tstate >> 32);
3045
    env->asi = (env->tsptr->tstate >> 24) & 0xff;
3046
    change_pstate((env->tsptr->tstate >> 8) & 0xf3f);
3047
    PUT_CWP64(env, env->tsptr->tstate & 0xff);
3048
    env->tl--;
3049
    env->tsptr = &env->ts[env->tl & MAXTL_MASK];
3050
}
3051

    
3052
void helper_set_softint(uint64_t value)
3053
{
3054
    env->softint |= (uint32_t)value;
3055
}
3056

    
3057
void helper_clear_softint(uint64_t value)
3058
{
3059
    env->softint &= (uint32_t)~value;
3060
}
3061

    
3062
void helper_write_softint(uint64_t value)
3063
{
3064
    env->softint = (uint32_t)value;
3065
}
3066
#endif
3067

    
3068
void helper_flush(target_ulong addr)
3069
{
3070
    addr &= ~7;
3071
    tb_invalidate_page_range(addr, addr + 8);
3072
}
3073

    
3074
#ifdef TARGET_SPARC64
3075
#ifdef DEBUG_PCALL
3076
static const char * const excp_names[0x80] = {
3077
    [TT_TFAULT] = "Instruction Access Fault",
3078
    [TT_TMISS] = "Instruction Access MMU Miss",
3079
    [TT_CODE_ACCESS] = "Instruction Access Error",
3080
    [TT_ILL_INSN] = "Illegal Instruction",
3081
    [TT_PRIV_INSN] = "Privileged Instruction",
3082
    [TT_NFPU_INSN] = "FPU Disabled",
3083
    [TT_FP_EXCP] = "FPU Exception",
3084
    [TT_TOVF] = "Tag Overflow",
3085
    [TT_CLRWIN] = "Clean Windows",
3086
    [TT_DIV_ZERO] = "Division By Zero",
3087
    [TT_DFAULT] = "Data Access Fault",
3088
    [TT_DMISS] = "Data Access MMU Miss",
3089
    [TT_DATA_ACCESS] = "Data Access Error",
3090
    [TT_DPROT] = "Data Protection Error",
3091
    [TT_UNALIGNED] = "Unaligned Memory Access",
3092
    [TT_PRIV_ACT] = "Privileged Action",
3093
    [TT_EXTINT | 0x1] = "External Interrupt 1",
3094
    [TT_EXTINT | 0x2] = "External Interrupt 2",
3095
    [TT_EXTINT | 0x3] = "External Interrupt 3",
3096
    [TT_EXTINT | 0x4] = "External Interrupt 4",
3097
    [TT_EXTINT | 0x5] = "External Interrupt 5",
3098
    [TT_EXTINT | 0x6] = "External Interrupt 6",
3099
    [TT_EXTINT | 0x7] = "External Interrupt 7",
3100
    [TT_EXTINT | 0x8] = "External Interrupt 8",
3101
    [TT_EXTINT | 0x9] = "External Interrupt 9",
3102
    [TT_EXTINT | 0xa] = "External Interrupt 10",
3103
    [TT_EXTINT | 0xb] = "External Interrupt 11",
3104
    [TT_EXTINT | 0xc] = "External Interrupt 12",
3105
    [TT_EXTINT | 0xd] = "External Interrupt 13",
3106
    [TT_EXTINT | 0xe] = "External Interrupt 14",
3107
    [TT_EXTINT | 0xf] = "External Interrupt 15",
3108
};
3109
#endif
3110

    
3111
void do_interrupt(CPUState *env)
3112
{
3113
    int intno = env->exception_index;
3114

    
3115
#ifdef DEBUG_PCALL
3116
    if (qemu_loglevel_mask(CPU_LOG_INT)) {
3117
        static int count;
3118
        const char *name;
3119

    
3120
        if (intno < 0 || intno >= 0x180)
3121
            name = "Unknown";
3122
        else if (intno >= 0x100)
3123
            name = "Trap Instruction";
3124
        else if (intno >= 0xc0)
3125
            name = "Window Fill";
3126
        else if (intno >= 0x80)
3127
            name = "Window Spill";
3128
        else {
3129
            name = excp_names[intno];
3130
            if (!name)
3131
                name = "Unknown";
3132
        }
3133

    
3134
        qemu_log("%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
3135
                " SP=%016" PRIx64 "\n",
3136
                count, name, intno,
3137
                env->pc,
3138
                env->npc, env->regwptr[6]);
3139
        log_cpu_state(env, 0);
3140
#if 0
3141
        {
3142
            int i;
3143
            uint8_t *ptr;
3144

3145
            qemu_log("       code=");
3146
            ptr = (uint8_t *)env->pc;
3147
            for(i = 0; i < 16; i++) {
3148
                qemu_log(" %02x", ldub(ptr + i));
3149
            }
3150
            qemu_log("\n");
3151
        }
3152
#endif
3153
        count++;
3154
    }
3155
#endif
3156
#if !defined(CONFIG_USER_ONLY)
3157
    if (env->tl >= env->maxtl) {
3158
        cpu_abort(env, "Trap 0x%04x while trap level (%d) >= MAXTL (%d),"
3159
                  " Error state", env->exception_index, env->tl, env->maxtl);
3160
        return;
3161
    }
3162
#endif
3163
    if (env->tl < env->maxtl - 1) {
3164
        env->tl++;
3165
    } else {
3166
        env->pstate |= PS_RED;
3167
        if (env->tl < env->maxtl)
3168
            env->tl++;
3169
    }
3170
    env->tsptr = &env->ts[env->tl & MAXTL_MASK];
3171
    env->tsptr->tstate = ((uint64_t)GET_CCR(env) << 32) |
3172
        ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
3173
        GET_CWP64(env);
3174
    env->tsptr->tpc = env->pc;
3175
    env->tsptr->tnpc = env->npc;
3176
    env->tsptr->tt = intno;
3177
    if (!(env->def->features & CPU_FEATURE_GL)) {
3178
        switch (intno) {
3179
        case TT_IVEC:
3180
            change_pstate(PS_PEF | PS_PRIV | PS_IG);
3181
            break;
3182
        case TT_TFAULT:
3183
        case TT_TMISS:
3184
        case TT_DFAULT:
3185
        case TT_DMISS:
3186
        case TT_DPROT:
3187
            change_pstate(PS_PEF | PS_PRIV | PS_MG);
3188
            break;
3189
        default:
3190
            change_pstate(PS_PEF | PS_PRIV | PS_AG);
3191
            break;
3192
        }
3193
    }
3194
    if (intno == TT_CLRWIN)
3195
        cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1));
3196
    else if ((intno & 0x1c0) == TT_SPILL)
3197
        cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2));
3198
    else if ((intno & 0x1c0) == TT_FILL)
3199
        cpu_set_cwp(env, cpu_cwp_inc(env, env->cwp + 1));
3200
    env->tbr &= ~0x7fffULL;
3201
    env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
3202
    env->pc = env->tbr;
3203
    env->npc = env->pc + 4;
3204
    env->exception_index = 0;
3205
}
3206
#else
3207
#ifdef DEBUG_PCALL
3208
static const char * const excp_names[0x80] = {
3209
    [TT_TFAULT] = "Instruction Access Fault",
3210
    [TT_ILL_INSN] = "Illegal Instruction",
3211
    [TT_PRIV_INSN] = "Privileged Instruction",
3212
    [TT_NFPU_INSN] = "FPU Disabled",
3213
    [TT_WIN_OVF] = "Window Overflow",
3214
    [TT_WIN_UNF] = "Window Underflow",
3215
    [TT_UNALIGNED] = "Unaligned Memory Access",
3216
    [TT_FP_EXCP] = "FPU Exception",
3217
    [TT_DFAULT] = "Data Access Fault",
3218
    [TT_TOVF] = "Tag Overflow",
3219
    [TT_EXTINT | 0x1] = "External Interrupt 1",
3220
    [TT_EXTINT | 0x2] = "External Interrupt 2",
3221
    [TT_EXTINT | 0x3] = "External Interrupt 3",
3222
    [TT_EXTINT | 0x4] = "External Interrupt 4",
3223
    [TT_EXTINT | 0x5] = "External Interrupt 5",
3224
    [TT_EXTINT | 0x6] = "External Interrupt 6",
3225
    [TT_EXTINT | 0x7] = "External Interrupt 7",
3226
    [TT_EXTINT | 0x8] = "External Interrupt 8",
3227
    [TT_EXTINT | 0x9] = "External Interrupt 9",
3228
    [TT_EXTINT | 0xa] = "External Interrupt 10",
3229
    [TT_EXTINT | 0xb] = "External Interrupt 11",
3230
    [TT_EXTINT | 0xc] = "External Interrupt 12",
3231
    [TT_EXTINT | 0xd] = "External Interrupt 13",
3232
    [TT_EXTINT | 0xe] = "External Interrupt 14",
3233
    [TT_EXTINT | 0xf] = "External Interrupt 15",
3234
    [TT_TOVF] = "Tag Overflow",
3235
    [TT_CODE_ACCESS] = "Instruction Access Error",
3236
    [TT_DATA_ACCESS] = "Data Access Error",
3237
    [TT_DIV_ZERO] = "Division By Zero",
3238
    [TT_NCP_INSN] = "Coprocessor Disabled",
3239
};
3240
#endif
3241

    
3242
void do_interrupt(CPUState *env)
3243
{
3244
    int cwp, intno = env->exception_index;
3245

    
3246
#ifdef DEBUG_PCALL
3247
    if (qemu_loglevel_mask(CPU_LOG_INT)) {
3248
        static int count;
3249
        const char *name;
3250

    
3251
        if (intno < 0 || intno >= 0x100)
3252
            name = "Unknown";
3253
        else if (intno >= 0x80)
3254
            name = "Trap Instruction";
3255
        else {
3256
            name = excp_names[intno];
3257
            if (!name)
3258
                name = "Unknown";
3259
        }
3260

    
3261
        qemu_log("%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
3262
                count, name, intno,
3263
                env->pc,
3264
                env->npc, env->regwptr[6]);
3265
        log_cpu_state(env, 0);
3266
#if 0
3267
        {
3268
            int i;
3269
            uint8_t *ptr;
3270

3271
            qemu_log("       code=");
3272
            ptr = (uint8_t *)env->pc;
3273
            for(i = 0; i < 16; i++) {
3274
                qemu_log(" %02x", ldub(ptr + i));
3275
            }
3276
            qemu_log("\n");
3277
        }
3278
#endif
3279
        count++;
3280
    }
3281
#endif
3282
#if !defined(CONFIG_USER_ONLY)
3283
    if (env->psret == 0) {
3284
        cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
3285
                  env->exception_index);
3286
        return;
3287
    }
3288
#endif
3289
    env->psret = 0;
3290
    cwp = cpu_cwp_dec(env, env->cwp - 1);
3291
    cpu_set_cwp(env, cwp);
3292
    env->regwptr[9] = env->pc;
3293
    env->regwptr[10] = env->npc;
3294
    env->psrps = env->psrs;
3295
    env->psrs = 1;
3296
    env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
3297
    env->pc = env->tbr;
3298
    env->npc = env->pc + 4;
3299
    env->exception_index = 0;
3300
}
3301
#endif
3302

    
3303
#if !defined(CONFIG_USER_ONLY)
3304

    
3305
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
3306
                                void *retaddr);
3307

    
3308
#define MMUSUFFIX _mmu
3309
#define ALIGNED_ONLY
3310

    
3311
#define SHIFT 0
3312
#include "softmmu_template.h"
3313

    
3314
#define SHIFT 1
3315
#include "softmmu_template.h"
3316

    
3317
#define SHIFT 2
3318
#include "softmmu_template.h"
3319

    
3320
#define SHIFT 3
3321
#include "softmmu_template.h"
3322

    
3323
/* XXX: make it generic ? */
3324
static void cpu_restore_state2(void *retaddr)
3325
{
3326
    TranslationBlock *tb;
3327
    unsigned long pc;
3328

    
3329
    if (retaddr) {
3330
        /* now we have a real cpu fault */
3331
        pc = (unsigned long)retaddr;
3332
        tb = tb_find_pc(pc);
3333
        if (tb) {
3334
            /* the PC is inside the translated code. It means that we have
3335
               a virtual CPU fault */
3336
            cpu_restore_state(tb, env, pc, (void *)(long)env->cond);
3337
        }
3338
    }
3339
}
3340

    
3341
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
3342
                                void *retaddr)
3343
{
3344
#ifdef DEBUG_UNALIGNED
3345
    printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
3346
           "\n", addr, env->pc);
3347
#endif
3348
    cpu_restore_state2(retaddr);
3349
    raise_exception(TT_UNALIGNED);
3350
}
3351

    
3352
/* try to fill the TLB and return an exception if error. If retaddr is
3353
   NULL, it means that the function was called in C code (i.e. not
3354
   from generated code or from helper.c) */
3355
/* XXX: fix it to restore all registers */
3356
void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
3357
{
3358
    int ret;
3359
    CPUState *saved_env;
3360

    
3361
    /* XXX: hack to restore env in all cases, even if not called from
3362
       generated code */
3363
    saved_env = env;
3364
    env = cpu_single_env;
3365

    
3366
    ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
3367
    if (ret) {
3368
        cpu_restore_state2(retaddr);
3369
        cpu_loop_exit();
3370
    }
3371
    env = saved_env;
3372
}
3373

    
3374
#endif
3375

    
3376
#ifndef TARGET_SPARC64
3377
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
3378
                          int is_asi, int size)
3379
{
3380
    CPUState *saved_env;
3381

    
3382
    /* XXX: hack to restore env in all cases, even if not called from
3383
       generated code */
3384
    saved_env = env;
3385
    env = cpu_single_env;
3386
#ifdef DEBUG_UNASSIGNED
3387
    if (is_asi)
3388
        printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
3389
               " asi 0x%02x from " TARGET_FMT_lx "\n",
3390
               is_exec ? "exec" : is_write ? "write" : "read", size,
3391
               size == 1 ? "" : "s", addr, is_asi, env->pc);
3392
    else
3393
        printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
3394
               " from " TARGET_FMT_lx "\n",
3395
               is_exec ? "exec" : is_write ? "write" : "read", size,
3396
               size == 1 ? "" : "s", addr, env->pc);
3397
#endif
3398
    if (env->mmuregs[3]) /* Fault status register */
3399
        env->mmuregs[3] = 1; /* overflow (not read before another fault) */
3400
    if (is_asi)
3401
        env->mmuregs[3] |= 1 << 16;
3402
    if (env->psrs)
3403
        env->mmuregs[3] |= 1 << 5;
3404
    if (is_exec)
3405
        env->mmuregs[3] |= 1 << 6;
3406
    if (is_write)
3407
        env->mmuregs[3] |= 1 << 7;
3408
    env->mmuregs[3] |= (5 << 2) | 2;
3409
    env->mmuregs[4] = addr; /* Fault address register */
3410
    if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
3411
        if (is_exec)
3412
            raise_exception(TT_CODE_ACCESS);
3413
        else
3414
            raise_exception(TT_DATA_ACCESS);
3415
    }
3416
    env = saved_env;
3417
}
3418
#else
3419
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
3420
                          int is_asi, int size)
3421
{
3422
#ifdef DEBUG_UNASSIGNED
3423
    CPUState *saved_env;
3424

    
3425
    /* XXX: hack to restore env in all cases, even if not called from
3426
       generated code */
3427
    saved_env = env;
3428
    env = cpu_single_env;
3429
    printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx
3430
           "\n", addr, env->pc);
3431
    env = saved_env;
3432
#endif
3433
    if (is_exec)
3434
        raise_exception(TT_CODE_ACCESS);
3435
    else
3436
        raise_exception(TT_DATA_ACCESS);
3437
}
3438
#endif
3439

    
3440
#ifdef TARGET_SPARC64
3441
void helper_tick_set_count(void *opaque, uint64_t count)
3442
{
3443
#if !defined(CONFIG_USER_ONLY)
3444
    cpu_tick_set_count(opaque, count);
3445
#endif
3446
}
3447

    
3448
uint64_t helper_tick_get_count(void *opaque)
3449
{
3450
#if !defined(CONFIG_USER_ONLY)
3451
    return cpu_tick_get_count(opaque);
3452
#else
3453
    return 0;
3454
#endif
3455
}
3456

    
3457
void helper_tick_set_limit(void *opaque, uint64_t limit)
3458
{
3459
#if !defined(CONFIG_USER_ONLY)
3460
    cpu_tick_set_limit(opaque, limit);
3461
#endif
3462
}
3463
#endif